Scrivi ed esamina il codice - Flusso di video Amazon Kinesis

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

Scrivi ed esamina il codice

In questa sezione, puoi esaminare la libreria Java, testare il codice e scoprire come utilizzare gli strumenti della libreria nel codice.

La libreria di analisi dei flussi video Kinesis contiene i seguenti strumenti:

StreamingMkvReader

Questa classe legge MKV gli elementi specificati da un flusso in modo non bloccante.

L'esempio di codice seguente (da FragmentMetadataVisitorTest) mostra come creare e utilizzare un Streaming MkvReader per recuperare gli oggetti MkvElement da un flusso di input chiamato inputStream:

StreamingMkvReader mkvStreamReader = StreamingMkvReader.createDefault(new InputStreamParserByteSource(inputStream)); while (mkvStreamReader.mightHaveNext()) { Optional<MkvElement> mkvElement = mkvStreamReader.nextIfAvailable(); if (mkvElement.isPresent()) { mkvElement.get().accept(fragmentVisitor); ... } } }

FragmentMetadataVisitor

Questa classe recupera i metadati per i frammenti (elementi multimediali) e tiene traccia dei singoli flussi di dati contenenti informazioni multimediali, come dati privati del codec, larghezza dei pixel o altezza dei pixel.

L'esempio di codice seguente (dal file FragmentMetadataVisitorTest) illustra come utilizzare FragmentMetadataVisitor per recuperare i dati da un oggetto MkvElement:

FragmentMetadataVisitor fragmentVisitor = FragmentMetadataVisitor.create(); StreamingMkvReader mkvStreamReader = StreamingMkvReader.createDefault(new InputStreamParserByteSource(in)); int segmentCount = 0; while(mkvStreamReader.mightHaveNext()) { Optional<MkvElement> mkvElement = mkvStreamReader.nextIfAvailable(); if (mkvElement.isPresent()) { mkvElement.get().accept(fragmentVisitor); if (MkvTypeInfos.SIMPLEBLOCK.equals(mkvElement.get().getElementMetaData().getTypeInfo())) { MkvDataElement dataElement = (MkvDataElement) mkvElement.get(); Frame frame = ((MkvValue<Frame>)dataElement.getValueCopy()).getVal(); MkvTrackMetadata trackMetadata = fragmentVisitor.getMkvTrackMetadata(frame.getTrackNumber()); assertTrackAndFragmentInfo(fragmentVisitor, frame, trackMetadata); } if (MkvTypeInfos.SEGMENT.equals(mkvElement.get().getElementMetaData().getTypeInfo())) { if (mkvElement.get() instanceof MkvEndMasterElement) { if (segmentCount < continuationTokens.size()) { Optional<String> continuationToken = fragmentVisitor.getContinuationToken(); Assert.assertTrue(continuationToken.isPresent()); Assert.assertEquals(continuationTokens.get(segmentCount), continuationToken.get()); } segmentCount++; } } } }

L'esempio precedente mostra i seguenti modelli di codifica:

  • Creare un FragmentMetadataVisitor per analizzare i dati e un StreamingMkvReader per inserire i dati.

  • Per ogni MkvElement nel flusso, verificare se i relativi metadati sono di tipo SIMPLEBLOCK.

  • Se sì, recuperare il MkvDataElement dal MkvElement.

  • Recuperate il Frame (dati multimediali) dal MkvDataElement.

  • Recuperare il MkvTrackMetadata relativo al Frame dal FragmentMetadataVisitor.

  • Recuperare e verificare i dati seguenti dagli oggetti Frame e MkvTrackMetadata:

    • Il numero di traccia.

    • L'altezza dei pixel del fotogramma.

    • La larghezza dei pixel del fotogramma.

    • L'ID codec relativo al codec utilizzato per la codifica del fotogramma.

    • L'arrivo del fotogramma nell'ordine corretto. Verificate che il numero di traccia del frame precedente, se presente, sia inferiore a quello del frame corrente.

Per utilizzare FragmentMetadataVisitor nel progetto, inviare gli oggetti MkvElement al visitatore tramite il relativo metodo accept:

mkvElement.get().accept(fragmentVisitor);

OutputSegmentMerger

Questa classe unisce i metadati di diverse tracce del flusso in un flusso con un singolo segmento.

L'esempio di codice seguente (dal file FragmentMetadataVisitorTest) illustra come utilizzare OutputSegmentMerger per unire i metadati della traccia da un array di byte chiamato inputBytes:

FragmentMetadataVisitor fragmentVisitor = FragmentMetadataVisitor.create(); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); OutputSegmentMerger outputSegmentMerger = OutputSegmentMerger.createDefault(outputStream); CompositeMkvElementVisitor compositeVisitor = new TestCompositeVisitor(fragmentVisitor, outputSegmentMerger); final InputStream in = TestResourceUtil.getTestInputStream("output_get_media.mkv"); StreamingMkvReader mkvStreamReader = StreamingMkvReader.createDefault(new InputStreamParserByteSource(in)); while (mkvStreamReader.mightHaveNext()) { Optional<MkvElement> mkvElement = mkvStreamReader.nextIfAvailable(); if (mkvElement.isPresent()) { mkvElement.get().accept(compositeVisitor); if (MkvTypeInfos.SIMPLEBLOCK.equals(mkvElement.get().getElementMetaData().getTypeInfo())) { MkvDataElement dataElement = (MkvDataElement) mkvElement.get(); Frame frame = ((MkvValue<Frame>) dataElement.getValueCopy()).getVal(); Assert.assertTrue(frame.getFrameData().limit() > 0); MkvTrackMetadata trackMetadata = fragmentVisitor.getMkvTrackMetadata(frame.getTrackNumber()); assertTrackAndFragmentInfo(fragmentVisitor, frame, trackMetadata); } }

L'esempio precedente mostra i seguenti modelli di codifica:

  • Creare un FragmentMetadataVisitorper recuperare i metadati dal flusso.

  • Creare un flusso di output per ricevere i metadati uniti.

  • Creare un OutputSegmentMerger, tramite l'invio del ByteArrayOutputStream.

  • Creare un CompositeMkvElementVisitor contenente i due visitatori.

  • Creare un InputStream che punti al file specificato.

  • Unire ciascun elemento nei dati di input nel flusso di output.

KinesisVideoExample

Questa è un'applicazione di esempio che mostra come utilizzare la libreria di parser di flussi video Kinesis.

Questa classe effettua le seguenti operazioni:

  • Crea un flusso video Kinesis. Se un flusso con il nome specificato è già esistente, tale flusso verrà eliminato e ricreato.

  • Chiamate PutMediaper trasmettere frammenti video allo stream video Kinesis.

  • Chiamate GetMediaper lo streaming di frammenti video dal flusso video di Kinesis.

  • Utilizza un StreamingMkvReader per analizzare i frammenti restituiti sul flusso e un FragmentMetadataVisitor per registrare i frammenti.

Eliminazione e nuova creazione del flusso

Il seguente esempio di codice (dal StreamOps.java file) elimina un determinato flusso video Kinesis:

//Delete the stream amazonKinesisVideo.deleteStream(new DeleteStreamRequest().withStreamARN(streamInfo.get().getStreamARN()));

Il seguente esempio di codice (dal StreamOps.java file) crea un flusso video Kinesis con il nome specificato:

amazonKinesisVideo.createStream(new CreateStreamRequest().withStreamName(streamName) .withDataRetentionInHours(DATA_RETENTION_IN_HOURS) .withMediaType("video/h264"));

Chiama PutMedia

Il seguente esempio di codice (dal PutMediaWorker.java file) chiama PutMedialo stream:

putMedia.putMedia(new PutMediaRequest().withStreamName(streamName) .withFragmentTimecodeType(FragmentTimecodeType.RELATIVE) .withProducerStartTimestamp(new Date()) .withPayload(inputStream), new PutMediaAckResponseHandler() { ... });

Chiama GetMedia

Il seguente esempio di codice (dal GetMediaWorker.java file) chiama GetMedialo stream:

GetMediaResult result = videoMedia.getMedia(new GetMediaRequest().withStreamName(streamName).withStartSelector(startSelector));

Analizza il risultato GetMedia

In questa sezione viene descritto come utilizzare StreamingMkvReader, FragmentMetadataVisitor e CompositeMkvElementVisitor per analizzare, salvare sul file e registrare i dati restituiti da GetMedia.

Leggi l'output di with GetMedia StreamingMkvReader

Il seguente esempio di codice (dal GetMediaWorker.java file) crea un file StreamingMkvReader e lo utilizza per analizzare il risultato dell'GetMediaoperazione:

StreamingMkvReader mkvStreamReader = StreamingMkvReader.createDefault(new InputStreamParserByteSource(result.getPayload())); log.info("StreamingMkvReader created for stream {} ", streamName); try { mkvStreamReader.apply(this.elementVisitor); } catch (MkvElementVisitException e) { log.error("Exception while accepting visitor {}", e); }

Nell'esempio di codice precedente, il StreamingMkvReader recupera gli oggetti MKVElement dal payload dei risultati GetMedia. Nella sezione successiva, gli elementi vengono inviati a un FragmentMetadataVisitor.

Recupera i frammenti con FragmentMetadataVisitor

Gli esempi di codice seguenti (dai file KinesisVideoExample.java e StreamingMkvReader.java) creano un FragmentMetadataVisitor. Gli oggetti MkvElement iterati dal StreamingMkvReader vengono quindi inviati al visitatore tramite il metodo accept.

da KinesisVideoExample.java:

FragmentMetadataVisitor fragmentMetadataVisitor = FragmentMetadataVisitor.create();

da StreamingMkvReader.java:

if (mkvElementOptional.isPresent()) { //Apply the MkvElement to the visitor mkvElementOptional.get().accept(elementVisitor); }

Registrazione degli elementi e scrittura in un file

L'esempio di codice seguente (dal file KinesisVideoExample.java) crea gli oggetti seguenti e li restituisce come parte del valore restituito della funzione GetMediaProcessingArguments:

  • Un LogVisitor (un'estensione di MkvElementVisitor) che effettua la scrittura nel log di sistema.

  • E OutputStream questo scrive i dati in entrata in un file. MKV

  • Un BufferedOutputStream che effettua il buffer dei dati associati all'OutputStream.

  • E OutputSegmentMerger che unisce elementi consecutivi nel GetMedia risultato con la stessa traccia e EBML gli stessi dati.

  • A CompositeMkvElementVisitor che compone il FragmentMetadataVisitor visitatoreOutputSegmentMerger, e LogVisitor in un singolo elemento.

//A visitor used to log as the GetMedia stream is processed. LogVisitor logVisitor = new LogVisitor(fragmentMetadataVisitor); //An OutputSegmentMerger to combine multiple segments that share track and ebml metadata into one //mkv segment. OutputStream fileOutputStream = Files.newOutputStream(Paths.get("kinesis_video_example_merged_output2.mkv"), StandardOpenOption.WRITE, StandardOpenOption.CREATE); BufferedOutputStream outputStream = new BufferedOutputStream(fileOutputStream); OutputSegmentMerger outputSegmentMerger = OutputSegmentMerger.createDefault(outputStream); //A composite visitor to encapsulate the three visitors. CompositeMkvElementVisitor mkvElementVisitor = new CompositeMkvElementVisitor(fragmentMetadataVisitor, outputSegmentMerger, logVisitor); return new GetMediaProcessingArguments(outputStream, logVisitor, mkvElementVisitor);

Gli argomenti di elaborazione multimediale vengono quindi passati aGetMediaWorker, che a sua volta viene passato aExecutorService, che esegue il worker su un thread separato:

GetMediaWorker getMediaWorker = GetMediaWorker.create(getRegion(), getCredentialsProvider(), getStreamName(), new StartSelector().withStartSelectorType(StartSelectorType.EARLIEST), amazonKinesisVideo, getMediaProcessingArgumentsLocal.getMkvElementVisitor()); executorService.submit(getMediaWorker);