Paso 2: escribir y examinar el código - Amazon Kinesis Video Streams

Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.

Paso 2: escribir y examinar el código

En esta sección, puede examinar la biblioteca de Java y el código de prueba y aprender a utilizar las herramientas de la biblioteca en su propio código.

La biblioteca de analizadores de transmisión de vídeo de Kinesis contiene las siguientes herramientas:

StreamingMkvReader

Esta clase lee elementos MKV especificados de una transmisión sin generar ningún bloqueo.

El siguiente ejemplo de código (de FragmentMetadataVisitorTest) muestra cómo crear y utilizar un Streaming MkvReader para recuperar objetos MkvElement de una transmisión de entrada llamada inputStream:

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

FragmentMetadataVisitor

Esta clase recupera los metadatos de los fragmentos (elementos multimedia) y rastrea los flujos de datos individuales que contienen información multimedia, como los datos privados del códec, el ancho o la altura de los píxeles.

El siguiente ejemplo de código (del archivo FragmentMetadataVisitorTest) muestra cómo utilizar FragmentMetadataVisitor para recuperar datos de un objeto 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++; } } } }

El ejemplo anterior muestra el siguiente patrón de codificación:

  • Cree una clase FragmentMetadataVisitor para analizar los datos y una clase StreamingMkvReader para proporcionar los datos.

  • Para cada MkvElement de la transmisión, pruebe si sus metadatos son del tipo SIMPLEBLOCK.

  • En caso afirmativo, recupere el MkvDataElement del MkvElement.

  • Recupere el Frame (datos multimedia) del MkvDataElement.

  • Recupere los MkvTrackMetadata para el Frame del FragmentMetadataVisitor.

  • Recupere y compruebe los siguientes datos de los objetos Frame y MkvTrackMetadata:

    • El número de pista.

    • La altura en píxeles del fotograma.

    • La anchura en píxeles del fotograma.

    • El ID del códec para el códec que utilice para codificar el fotograma.

    • Que el fotograma haya llegado en orden. Compruebe que el número de pista del fotograma anterior, si está presente, sea inferior al del fotograma actual.

Para utilizar FragmentMetadataVisitor en su proyecto, transfiera los objetos MkvElement al visitante con su método accept:

mkvElement.get().accept(fragmentVisitor);

OutputSegmentMerger

Esta clase reúne los metadatos de diferentes pistas en la transmisión en una transmisión con un único segmento.

El siguiente ejemplo de código (del archivo FragmentMetadataVisitorTest) muestra cómo utilizar OutputSegmentMerger para combinar metadatos de pistas a partir de una matriz de bytes denominada 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); } }

El ejemplo anterior muestra el siguiente patrón de codificación:

  • Cree una FragmentMetadataVisitorpara recuperar los metadatos de la secuencia.

  • Cree una transmisión de salida para recibir los metadatos combinados.

  • Cree un OutputSegmentMerger, transfiriendo el ByteArrayOutputStream.

  • Cree un CompositeMkvElementVisitor que contenga los dos visitantes.

  • Cree un InputStream que apunte al archivo especificado.

  • Combine cada elemento de los datos de entrada en la transmisión de salida.

KinesisVideoExample

Este es un ejemplo de aplicación que muestra cómo utilizar la biblioteca de analizadores de transmisión de vídeo de Kinesis.

Esta clase realiza las operaciones siguientes:

  • Crea una transmisión de video de Kinesis. Si ya existe una transmisión con ese nombre, se elimina y se vuelve a crear.

  • Llamadas PutMediapara transmitir fragmentos de vídeo a la transmisión de vídeo de Kinesis.

  • Llamadas GetMediapara transmitir fragmentos de video desde la transmisión de video de Kinesis.

  • Utiliza StreamingMkvReader para analizar los fragmentos devueltos de la transmisión y utiliza FragmentMetadataVisitor para registrar los fragmentos.

Eliminación y nueva creación de la transmisión

El siguiente ejemplo de código (del StreamOps.java archivo) elimina una transmisión de vídeo de Kinesis determinada:

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

El siguiente ejemplo de código (del StreamOps.java archivo) crea una transmisión de vídeo de Kinesis con el nombre especificado:

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

Llamar PutMedia

El siguiente ejemplo de código (del PutMediaWorker.java archivo) llama PutMediaa la transmisión:

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

Llamar GetMedia

El siguiente ejemplo de código (del GetMediaWorker.java archivo) llama GetMediaa la transmisión:

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

Analiza el GetMedia resultado

En esta sección se describe cómo utilizar StreamingMkvReader, FragmentMetadataVisitor y CompositeMkvElementVisitor para analizar, guardar en archivo y registrar los datos devueltos de GetMedia.

Lea el resultado de GetMedia with StreamingMkvReader

El siguiente ejemplo de código (del GetMediaWorker.java archivo) crea un StreamingMkvReader y lo usa para analizar el resultado de la GetMediaoperación:

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

En el ejemplo de código anterior, StreamingMkvReader recupera objetos MKVElement de la carga del resultado de GetMedia. En la siguiente sección, los elementos se pasan a un FragmentMetadataVisitor.

Recupera fragmentos con FragmentMetadataVisitor

Los siguientes ejemplos de código (de los archivos KinesisVideoExample.java y StreamingMkvReader.java) crean un FragmentMetadataVisitor. A continuación, los objetos MkvElement por los que ha iterado StreamingMkvReader se pasan al visitante con el método accept.

de KinesisVideoExample.java:

FragmentMetadataVisitor fragmentMetadataVisitor = FragmentMetadataVisitor.create();

de StreamingMkvReader.java:

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

Registro de los elementos y escritura en un archivo

El siguiente ejemplo de código (del archivo KinesisVideoExample.java) crea los siguientes objetos y los devuelve como parte del valor de retorno de la función GetMediaProcessingArguments:

  • Un LogVisitor (una extensión de MkvElementVisitor) que escribe en el log del sistema.

  • Un OutputStream que escribe los datos entrantes en un archivo MKV.

  • Un BufferedOutputStream que almacena en búfer los datos vinculados para OutputStream.

  • Un OutputSegmentMerger que fusiona los elementos consecutivos en el resultado de GetMedia con los mismos datos de pista y EBML.

  • A CompositeMkvElementVisitor que compone elFragmentMetadataVisitor,OutputSegmentMerger, y LogVisitor en un solo elemento visitante.

//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);

Los argumentos del procesamiento multimedia se pasan luego a laGetMediaWorker, que a su vez pasa a laExecutorService, que lleva a cabo el trabajo en un hilo separado:

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

Paso siguiente

Paso 3: Ejecutar y verificar el código