

Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.

# Untersuchen Sie den Code
<a name="parser-library-write"></a>

In diesem Abschnitt prüfen Sie die Java-Bibliothek sowie den Testcode und lernen, wie Sie die Klassen der Bibliothek in eigenem Code verwenden können.

Die Kinesis-Videostream-Parser-Bibliothek enthält die folgenden Tools:
+ [StreamingMkvReader](#parser-library-write-SMSR)
+ [FragmentMetadataVisitor](#parser-library-write-FMV)
+ [OutputSegmentMerger](#parser-library-write-OSM)
+ [KinesisVideoExample](#parser-library-write-example)

## StreamingMkvReader
<a name="parser-library-write-SMSR"></a>

Diese Klasse liest bestimmte MKV-Elemente aus einem Stream blockierungsfrei.

Das folgende Beispiel (aus der Datei `FragmentMetadataVisitorTest`) zeigt, wie Sie ein `Streaming MkvReader`-Objekt erstellen und verwenden können, um `MkvElement`-Objekte aus dem Eingabe-Stream `inputStream` zu extrahieren:

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

## FragmentMetadataVisitor
<a name="parser-library-write-FMV"></a>

Diese Klasse ruft Metadaten für Fragmente (Medienelemente) ab und verfolgt einzelne Datenströme, die Medieninformationen wie private Codec-Daten, Pixelbreite oder Pixelhöhe enthalten. 

Das folgende Codebeispiel (aus der Datei `FragmentMetadataVisitorTest`) zeigt, wie Sie mit `FragmentMetadataVisitor` Daten aus einem `MkvElement`-Objekt auslesen können:

```
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++;
                    }
                }
            }

        }
```

Das vorhergehende Beispiel weist folgendes Codierungsmuster auf:
+ Ein `FragmentMetadataVisitor`-Objekt wird zum Analysieren der Daten und ein [StreamingMkvReader](#parser-library-write-SMSR)-Objekt zum Bereitstellen der Daten erstellt.
+ Bei jedem `MkvElement` im Stream wird geprüft, ob dessen Metadaten den Typ `SIMPLEBLOCK` haben.
+ Ist dies der Fall, wird das `MkvDataElement` aus dem `MkvElement` abgerufen.
+ Das `Frame`-Objekt (Mediendaten) wird aus `MkvDataElement` abgerufen.
+ Das `MkvTrackMetadata`-Element des `Frame`-Objekts wird aus dem `FragmentMetadataVisitor`-Objekt abgerufen.
+ Die folgenden Daten werden aus den `Frame`- und `MkvTrackMetadata`-Objekten abgerufen und geprüft:
  + Track-Nummer
  + Framehöhe in Pixeln
  + Framebreite in Pixeln
  + ID des zur Codierung des Frames verwendeten Codecs
  + Richtige Position des Frames im Stream. Stellen Sie sicher, dass die Titelnummer des vorherigen Frames, falls vorhanden, kleiner ist als die des aktuellen Frames.

Um `FragmentMetadataVisitor` im Projekt zu verwenden, übergeben Sie `MkvElement`-Objekte mit deren `accept`-Methode an das Visitor-Objekt:

```
mkvElement.get().accept(fragmentVisitor);
```

## OutputSegmentMerger
<a name="parser-library-write-OSM"></a>

Diese Klasse führt die Metadaten verschiedener Tracks im Stream zu einem Stream mit einem einzigen Segment zusammen.

Das folgende Codebeispiel (aus der Datei `FragmentMetadataVisitorTest`) zeigt, wie Sie mit einem `OutputSegmentMerger`-Objekt die Track-Metadaten im Byte-Array `inputBytes` zusammenführen:

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

Das vorhergehende Beispiel weist folgendes Codierungsmuster auf:
+ Erstellen Sie [FragmentMetadataVisitor](#parser-library-write-FMV), um die Metadaten aus dem Stream abzurufen.
+ Ein Ausgabe-Stream für die zusammengeführten Metadaten wird erstellt.
+ Erstellen Sie `OutputSegmentMerger`, übergeben Sie dabei `ByteArrayOutputStream`.
+ Erstellen Sie das `CompositeMkvElementVisitor`-Objekt, das die beiden Besucher enthält. 
+ Erstellen Sie einen `InputStream`, der auf die angegebene Datei zeigt.
+ Die einzelnen Elemente in den Eingabedaten werden im Ausgabe-Stream zusammengeführt.

## KinesisVideoExample
<a name="parser-library-write-example"></a>

Dies ist eine Beispielanwendung, die zeigt, wie die Kinesis-Videostream-Parser-Bibliothek verwendet wird.

Diese Klasse führt die folgenden Operationen aus:
+ Erzeugt einen Kinesis-Videostream. Wenn ein Stream mit dem angegebenen Namen bereits vorhanden ist, wird der Stream gelöscht und neu erstellt.
+ Aufrufe [PutMedia](https://docs.aws.amazon.com/kinesisvideostreams/latest/dg/API_dataplane_PutMedia.html)zum Streamen von Videofragmenten in den Kinesis-Videostream.
+ Aufrufe [GetMedia](https://docs.aws.amazon.com/kinesisvideostreams/latest/dg/API_dataplane_GetMedia.html)zum Streamen von Videofragmenten aus dem Kinesis-Videostream.
+ Verwendet einen [StreamingMkvReader](#parser-library-write-SMSR) zum Analysieren der zurückgegebenen Fragmente auf dem Stream und verwendet [FragmentMetadataVisitor](#parser-library-write-FMV) für die Protokollierung der Fragmente.

### Löschen und Neuerstellen des Streams
<a name="parser-library-write-example-create"></a>

Das folgende Codebeispiel (aus der `StreamOps.java` Datei) löscht einen bestimmten Kinesis-Videostream:

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

Das folgende Codebeispiel (aus der `StreamOps.java` Datei) erstellt einen Kinesis-Videostream mit dem angegebenen Namen:

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

### Rufen Sie an PutMedia
<a name="parser-library-write-example-putmedia"></a>

Das folgende Codebeispiel (aus der `PutMediaWorker.java` Datei) ruft den Stream [PutMedia](https://docs.aws.amazon.com/kinesisvideostreams/latest/dg/API_dataplane_PutMedia.html)auf:

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

### Rufen Sie GetMedia
<a name="parser-library-write-example-getmedia"></a>

Das folgende Codebeispiel (aus der `GetMediaWorker.java` Datei) ruft den Stream [GetMedia](https://docs.aws.amazon.com/kinesisvideostreams/latest/dg/API_dataplane_GetMedia.html)auf:

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

### Analysieren Sie das Ergebnis GetMedia
<a name="parser-library-write-example-parse"></a>

Dieser Abschnitt beschreibt, wie [StreamingMkvReader](#parser-library-write-SMSR), [FragmentMetadataVisitor](#parser-library-write-FMV) und `CompositeMkvElementVisitor` zur Analyse, zum Speichern in die Datei und zur Protokollierung der von `GetMedia` zurückgegebenen Daten verwendet wird.

#### Lesen Sie die Ausgabe von mit GetMedia StreamingMkvReader
<a name="parser-library-write-example-parse-smr"></a>

Das folgende Codebeispiel (aus der `GetMediaWorker.java` Datei) erstellt eine [StreamingMkvReader](#parser-library-write-SMSR) und verwendet sie, um das Ergebnis der [GetMedia](https://docs.aws.amazon.com/kinesisvideostreams/latest/dg/API_dataplane_GetMedia.html)Operation zu analysieren:

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

Im vorigen Codebeispiel ruft der [StreamingMkvReader](#parser-library-write-SMSR) `MKVElement`-Objekte aus der Nutzlast des Ergebnisses von `GetMedia` ab. Im nächsten Abschnitt werden die Elemente einem [FragmentMetadataVisitor](#parser-library-write-FMV) übergeben.

#### Fragmente abrufen mit FragmentMetadataVisitor
<a name="parser-library-write-example-parse-fmv"></a>

Die folgenden Codebeispiele (aus den Dateien `KinesisVideoExample.java` und `StreamingMkvReader.java`) erstellen einen [FragmentMetadataVisitor](#parser-library-write-FMV). Die `MkvElement`-Objekte, die von dem [StreamingMkvReader](#parser-library-write-SMSR) durchlaufen werden, werden dann über die Methode `accept` dem Besucher übergeben. 

*von `KinesisVideoExample.java`:*

```
FragmentMetadataVisitor fragmentMetadataVisitor = FragmentMetadataVisitor.create();
```

*von `StreamingMkvReader.java`:*

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

#### Die Elemente schreiben und in eine Datei schreiben
<a name="parser-library-write-example-parse-cmev"></a>

Das folgende Code-Beispiel (aus der `KinesisVideoExample.java`-Datei) erstellt die folgenden Objekte und gibt sie als Teil des Rückgabewerts der `GetMediaProcessingArguments`-Funktion zurück:
+ Einen `LogVisitor` (eine Erweiterung von `MkvElementVisitor`), die in das Systemprotokoll schreibt.
+ Einen `OutputStream` , der die eingehenden Daten in eine MKV-Datei schreibt.
+ Einen `BufferedOutputStream` , der die für `OutputStream` gebundenen Daten puffert.
+ Einen [OutputSegmentMerger](#parser-library-write-OSM), der aufeinanderfolgende Elemente in das `GetMedia`-Ergebnis einfügt, mit denselben Track- und EBML-Daten.
+ A`CompositeMkvElementVisitor`, das das [FragmentMetadataVisitor](#parser-library-write-FMV)[OutputSegmentMerger](#parser-library-write-OSM), und zu einem einzigen Element zusammensetzt, `LogVisitor` den Besucher.

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

Die Argumente für die Medienverarbeitung werden dann an den übergeben`GetMediaWorker`, der wiederum an den übergeben wird`ExecutorService`, der den Worker in einem separaten Thread ausführt:

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