Fase 2: Scrittura e analisi del codice - Amazon Kinesis Video Streams

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à.

Fase 2: Scrittura e analisi del codice

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

La libreria parser del flusso video Kinesis contiene i seguenti strumenti:

StreamingMkvreader

Questa classe legge gli elementi MKV specificati da un flusso in modalità senza blocchi.

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); ... } } }

FragmentMetadataVisitatore

Questa classe recupera i metadati relativi ai frammenti (elementi multimediali) e alle tracce (singoli flussi di dati che contengono informazioni multimediali, ad esempio dati privati del codec, larghezza 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. Ovvero, verificare che il numero di traccia del fotogramma precedente, se presente, sia inferiore a quello del fotogramma corrente.

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

mkvElement.get().accept(fragmentVisitor);

OutputSegmentFusione

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 FragmentMetadataVisitatoreper 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.

KinesisVideoEsempio

Questa è un'applicazione di esempio che illustra come utilizzare la libreria parser del flusso 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.

  • Calls (Chiamate)PutMediaper effettuare lo streaming dei frammenti video sul flusso video Kinesis.

  • Calls (Chiamate)GetMediaper effettuare lo streaming dei frammenti video al di fuori del flusso video Kinesis.

  • Utilizza un StreamingMkvreader per analizzare i frammenti restituiti sul flusso e un FragmentMetadataVisitatore per registrare i frammenti.

Eliminazione e nuova creazione del flusso

L'esempio di codice seguente (dalStreamOps.javafile) elimina un dato flusso video Kinesis:

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

L'esempio di codice seguente (dalStreamOps.javafile) crea un flusso video Kinesis con il nome specificato:

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

Esegui una chiamata aPutMedia

L'esempio di codice seguente (dalPutMediaWorker.javafile) chiamatePutMediasul flusso:

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

Esegui una chiamata aGetMedia

L'esempio di codice seguente (dalGetMediaWorker.javafile) chiamateGetMediasul flusso:

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

Analizza ilGetMediarisultato

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

Lettura dell'output diGetMediaconStreamingMkvreader

L'esempio di codice seguente (dalGetMediaWorker.javafile) crea unStreamingMkvreadere lo usa per analizzare il risultato dalGetMediaoperazione:

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 FragmentMetadataVisitatore.

Recupero dei frammenti conFragmentMetadataVisitatore

Gli esempi di codice seguenti (dai file KinesisVideoExample.java e StreamingMkvReader.java) creano un FragmentMetadataVisitatore. 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.

  • Un OutputStream che scrive i dati in entrata su un file MKV.

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

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

  • Un CompositeMkvElementVisitor che compone il FragmentMetadataVisitatore, l'OutputSegmentFusionee il LogVisitor in un singolo visitatore di 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 degli elementi multimediali vengono quindi inviati al GetMediaWorker, che viene a sua volta inviato all'ExecutorService che esegue il lavoratore su un thread separato:

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

Fase successiva

Fase 3: Esecuzione e verifica del codice