Escreva e examine o código - Amazon Kinesis Video Streams

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

Escreva e examine o código

Nesta seção, você examinará a biblioteca Java e o código de teste e aprenderá a usar as ferramentas da biblioteca no seu próprio código.

A biblioteca de analisadores de stream de vídeo do Kinesis contém as seguintes ferramentas:

StreamingMkvReader

Essa classe lê MKV elementos especificados de um fluxo de forma sem bloqueio.

O exemplo de código a seguir (de FragmentMetadataVisitorTest) mostra como criar e usar Streaming MkvReader para recuperar MkvElement objetos de um streaming de entrada chamado inputStream:

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

FragmentMetadataVisitor

Essa classe recupera metadados para fragmentos (elementos de mídia) e rastreia fluxos de dados individuais contendo informações de mídia, como dados privados do codec, largura ou altura de pixels.

O código de exemplo a seguir (do arquivo FragmentMetadataVisitorTest) mostra como usar FragmentMetadataVisitor para recuperar dados de um 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++; } } } }

O exemplo anterior mostra o padrão de codificação a seguir:

  • Crie uma classe FragmentMetadataVisitor para analisar os dados e uma StreamingMkvReader para fornecer os dados.

  • Em cada MkvElement no streaming, teste se os metadados são do tipo SIMPLEBLOCK.

  • Se forem, recupere o MkvDataElement do MkvElement.

  • Recupere o Frame (dados de mídia) do MkvDataElement.

  • Recupere os MkvTrackMetadata do Frame do FragmentMetadataVisitor.

  • Recupere e verifique os seguintes dados dos objetos Frame e MkvTrackMetadata:

    • O número de controle.

    • A altura do pixel de quadros.

    • A profundidade do pixel de quadros.

    • O ID do codec usado para codificar o quadro.

    • Que este quadro foi recebido em ordem. Verifique se o número da faixa do quadro anterior, se presente, é menor que o do quadro atual.

Para usar FragmentMetadataVisitor no seu projeto, passe os objetos MkvElement para o visitante usando o método accept:

mkvElement.get().accept(fragmentVisitor);

OutputSegmentMerger

Esta classe combina metadados de diferentes trilhas no streaming em um streaming com um segmento único.

O exemplo de código a seguir (do arquivo FragmentMetadataVisitorTest) mostra como usar OutputSegmentMerger para mesclar metadados de uma matriz de byte chamada 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); } }

O exemplo anterior mostra o padrão de codificação a seguir:

  • Crie um FragmentMetadataVisitorpara recuperar os metadados do stream.

  • Criar um streaming de saída para receber os metadados mesclados.

  • Crie um OutputSegmentMerger, passando o ByteArrayOutputStream.

  • Crie um CompositeMkvElementVisitor que contenha os dois visitantes.

  • Crie um InputStream que aponte para o arquivo especificado.

  • Mescle cada elemento nos dados de entrada no streaming de saída.

KinesisVideoExample

Este é um aplicativo de exemplo que mostra como usar a biblioteca de analisadores de stream de vídeo Kinesis.

Essa classe executa as seguintes operações:

  • Cria um stream de vídeo do Kinesis. Se um stream com o nome fornecido já existe, o stream é excluído e recriado.

  • Chamadas PutMediapara transmitir fragmentos de vídeo para o stream de vídeo do Kinesis.

  • Chamadas GetMediapara transmitir fragmentos de vídeo do stream de vídeo do Kinesis.

  • Usa uma StreamingMkvReader para analisar os fragmentos retornados no stream, e usa um FragmentMetadataVisitor para registrar os fragmentos.

Excluir e recriar o stream

O exemplo de código a seguir (do StreamOps.java arquivo) exclui um determinado stream de vídeo do Kinesis:

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

O exemplo de código a seguir (do StreamOps.java arquivo) cria um stream de vídeo do Kinesis com o nome especificado:

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

Ligue PutMedia

O exemplo de código a seguir (do PutMediaWorker.java arquivo) faz chamadas PutMediano stream:

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

Ligue GetMedia

O exemplo de código a seguir (do GetMediaWorker.java arquivo) faz chamadas GetMediano stream:

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

Analise o resultado GetMedia

Esta seção descreve como usar StreamingMkvReader, FragmentMetadataVisitor e CompositeMkvElementVisitor para analisar, salvar no arquivo e registrar os dados retornados de GetMedia.

Leia a saída de GetMedia com StreamingMkvReader

O exemplo de código a seguir (do GetMediaWorker.java arquivo) cria um StreamingMkvReader e o usa para analisar o resultado da GetMediaoperação:

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

No exemplo de código anterior, o StreamingMkvReader recupera objetos MKVElement da carga do resultado GetMedia. Na próxima seção, os elementos são passados para um FragmentMetadataVisitor.

Recupere fragmentos com FragmentMetadataVisitor

Os exemplos de código a seguir (dos arquivos KinesisVideoExample.java e StreamingMkvReader.java) criam um FragmentMetadataVisitor. Os objetos MkvElement iteradas pelo StreamingMkvReader são passados para o visitante usando o 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 elementos e gravação em um arquivo

O exemplo de código a seguir (do arquivo KinesisVideoExample.java) cria os seguintes objetos e os retorna como parte do valor de retorno da função GetMediaProcessingArguments:

  • Um LogVisitor (uma extensão de MkvElementVisitor) que grava no log do sistema.

  • E OutputStream que grava os dados recebidos em um MKV arquivo.

  • Um BufferedOutputStream que acumula dados delimitados para o OutputStream.

  • E OutputSegmentMerger que mescla elementos consecutivos no GetMedia resultado com a mesma faixa e EBML dados.

  • Um CompositeMkvElementVisitor que compõe oFragmentMetadataVisitor,OutputSegmentMerger, e LogVisitor em um único 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);

Os argumentos de processamento de mídia são então passados para oGetMediaWorker, que por sua vez é passado para oExecutorService, que executa o trabalhador em um encadeamento separado:

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