Étape 2 : Écrire et examiner le code - Amazon Kinesis Video Streams

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

Étape 2 : Écrire et examiner le code

Dans cette section, vous examinez la bibliothèque Java et le code test et apprenez à utiliser les outils de la bibliothèque dans votre propre code.

La bibliothèque d'analyseurs de flux vidéo Kinesis contient les outils suivants :

StreamingMkvReader

Cette classe lit les éléments spécifiés MKV à partir d'un flux sans blocage.

L'exemple de code suivant (à partir de FragmentMetadataVisitorTest) illustre comment créer et utiliser un Streaming MkvReader pour récupérer des objets MkvElement à partir d'un flux d'entrée appelé inputStream :

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

FragmentMetadataVisitor

Cette classe récupère les métadonnées des fragments (éléments multimédias) et suit les flux de données individuels contenant des informations multimédia, telles que les données privées du codec, la largeur des pixels ou la hauteur des pixels.

L'exemple de code suivant (à partir du fichier FragmentMetadataVisitorTest) illustre comment utiliser FragmentMetadataVisitor pour récupérer des données à partir d'un objet 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'exemple précédent présente le modèle de codage suivant :

  • Créez un FragmentMetadataVisitor pour analyser les données et un StreamingMkvReader pour fournir les données.

  • Pour chaque MkvElement dans le flux, testez si ses métadonnées sont de type SIMPLEBLOCK.

  • Si c'est le cas, récupérez le MkvDataElement à partir de MkvElement.

  • Récupérez le Frame (données média) à partir de MkvDataElement.

  • Récupérez les MkvTrackMetadata pour le Frame à partir de FragmentMetadataVisitor.

  • Récupérez et vérifiez les données suivantes à partir du Frame et des objets MkvTrackMetadata :

    • Le numéro de suivi.

    • La hauteur de l'image en pixels.

    • La largeur de l'image en pixels.

    • L'ID du codec utilisé pour coder l'image.

    • Cette structure est arrivée en ordre. Vérifiez que le numéro de piste de l'image précédente, s'il est présent, est inférieur à celui de l'image actuelle.

Pour utiliser FragmentMetadataVisitor dans votre projet, transmettez les objets MkvElement au visiteur à l'aide de leur méthode accept :

mkvElement.get().accept(fragmentVisitor);

OutputSegmentMerger

Cette classe fusionne des métadonnées à partir de différentes pistes du flux dans un flux avec un seul segment.

L'exemple de code suivant (à partir du fichier FragmentMetadataVisitorTest) illustre comment utiliser OutputSegmentMerger pour fusionner les métadonnées de suivi à partir d'une matrice à octets appelée 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'exemple précédent présente le modèle de codage suivant :

  • Créez un FragmentMetadataVisitorpour extraire les métadonnées du flux.

  • Créer un flux de sortie pour recevoir les métadonnées fusionnées.

  • Créez un OutputSegmentMergeren passant dans le ByteArrayOutputStream.

  • Créez un CompositeMkvElementVisitor qui contient les deux visiteurs.

  • Créez un InputStream qui pointe vers le fichier spécifié.

  • Fusionnez chaque élément des données d'entrée dans le flux de sortie.

KinesisVideoExample

Il s'agit d'un exemple d'application qui montre comment utiliser la bibliothèque d'analyseurs de flux vidéo Kinesis.

Cette classe effectue les opérations suivantes :

  • Crée un flux vidéo Kinesis. S'il existe déjà un flux portant ce nom, le flux est supprimé et recréé.

  • Appels PutMediapour diffuser des fragments vidéo dans le flux vidéo Kinesis.

  • Appels GetMediapour diffuser des fragments vidéo à partir du flux vidéo Kinesis.

  • Elle utilise un StreamingMkvReader pour analyser les fragments renvoyés sur le flux et utilise une FragmentMetadataVisitor pour consigner les fragments.

Supprimer et recréer le flux

L'exemple de code suivant (extrait du StreamOps.java fichier) supprime un flux vidéo Kinesis donné :

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

L'exemple de code suivant (extrait du StreamOps.java fichier) crée un flux vidéo Kinesis portant le nom spécifié :

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

Appel PutMedia

L'exemple de code suivant (extrait du PutMediaWorker.java fichier) appelle PutMediale flux :

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

Appel GetMedia

L'exemple de code suivant (extrait du GetMediaWorker.java fichier) appelle GetMediale flux :

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

Analyser le résultat GetMedia

Cette section décrit comment utiliser StreamingMkvReader, FragmentMetadataVisitor et CompositeMkvElementVisitor pour analyser, enregistrer dans un fichier et consigner les données renvoyées par GetMedia.

Lisez le résultat de GetMedia with StreamingMkvReader

L'exemple de code suivant (extrait du GetMediaWorker.java fichier) crée un StreamingMkvReader et l'utilise pour analyser le résultat de l'GetMediaopération :

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

Dans l'exemple de code précédent, l'élément StreamingMkvReader extrait des objets MKVElement à partir de la charge utile du résultat de GetMedia. Dans la section suivante, les éléments sont transmis à un élément FragmentMetadataVisitor.

Récupérez des fragments avec FragmentMetadataVisitor

Les exemples de code suivants (en provenance des fichiers KinesisVideoExample.java et StreamingMkvReader.java files) créent un élément FragmentMetadataVisitor. Les objets MkvElement itérés par l'élément StreamingMkvReader sont ensuite transmis au visiteur à l'aide de la méthode accept.

À partir de KinesisVideoExample.java :

FragmentMetadataVisitor fragmentMetadataVisitor = FragmentMetadataVisitor.create();

À partir de StreamingMkvReader.java :

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

Consigner les éléments et les écrire dans un fichier

L'exemple de code suivant (en provenance du fichier KinesisVideoExample.java) crée les objets suivants et les renvoie dans le cadre de la valeur renvoyée par la fonction GetMediaProcessingArguments :

  • Un élément LogVisitor (une extension de MkvElementVisitor) qui écrit des données dans le journal système.

  • Un élément OutputStream qui copie les données entrantes dans un fichier MKV.

  • Un élément BufferedOutputStream qui met en mémoire tampon les données de OutputStream.

  • Un élément OutputSegmentMerger qui fusionne les éléments consécutifs dans le résultat de GetMedia avec les mêmes données de suivi et EBML.

  • Un CompositeMkvElementVisitor qui compose le FragmentMetadataVisitorOutputSegmentMerger, et LogVisitor en un seul élément visiteur.

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

Les arguments du traitement multimédia sont ensuite transmis auGetMediaWorker, qui est à son tour transmis auExecutorService, qui exécute le travailleur sur un thread distinct :

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

Étape suivante

Étape 3 : Exécuter et vérifier le code