

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# コードを調べる
<a name="parser-library-write"></a>

このセクションでは、Java ライブラリとテストコードを検証し、ライブラリに含まれるツールを独自のコードで使用する方法について学習します。

Kinesis ビデオストリームパーサーライブラリには、次のツールが含まれています。
+ [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>

このクラスは指定された MKV 要素をストリームからブロックしない方法で読み取ります。

次のコード例 (`FragmentMetadataVisitorTest` から) は、`Streaming MkvReader` を作成、使用して `inputStream` と呼ばれる入力ストリームから `MkvElement` オブジェクトを取得する方法を示しています。

```
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>

このクラスはフラグメント (メディア要素) のメタデータを取得し、コーデックのプライベートデータ、ピクセル幅、ピクセルの高さなどのメディア情報を含む個々のデータストリームを追跡します。

次のコード例 (`FragmentMetadataVisitorTest` ファイルから) は `FragmentMetadataVisitor` を使って `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++;
                    }
                }
            }

        }
```

前述の例は、次のコーディングパターンを示しています。
+ データ解析のための `FragmentMetadataVisitor` およびデータ提供のための [StreamingMkvReader](#parser-library-write-SMSR) を作成します。
+ ストリーム内の各 `MkvElement` について、そのメタデータが `SIMPLEBLOCK` タイプかどうかを検証します。
+ 該当する場合は `MkvElement` から `MkvDataElement` を取得します。
+ `MkvDataElement` から `Frame` (メディアデータ) を取得します。
+ `FragmentMetadataVisitor` から `Frame` 用の `MkvTrackMetadata` を取得します。
+ `Frame` および `MkvTrackMetadata` オブジェクトから次のデータを取得して検証します。
  + 追跡番号。
  + フレームのピクセルの高さ。
  + フレームのピクセルの幅。
  + フレームのエンコードに使用するコーデックのコーデック ID。
  + このフレームが順番に到着したこと。前のフレームのトラック番号が存在する場合、現在のフレームのトラック番号より小さいことを確認します。

プロジェクトで `FragmentMetadataVisitor` を使用するには、ビジターの `accept` 方法を使って `MkvElement` オブジェクトをビジターにパスします。

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

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

このクラスは、ストリーム内の異なるトラックのメタデータを単一のセグメントを持つストリームにマージします。

次のコード例 (`FragmentMetadataVisitorTest` ファイルから) は、`OutputSegmentMerger` を使って `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);
    }
}
```

前述の例は、次のコーディングパターンを示しています。
+ [FragmentMetadataVisitor](#parser-library-write-FMV) を作成してストリームからメタデータを取得する。
+ 出力ストリームを作成してマージされたメタデータを取得する。
+ `OutputSegmentMerger` を作成し、`ByteArrayOutputStream` に渡す。
+ 2 つのビジターを含む `CompositeMkvElementVisitor` を作成する。
+ 指定されたファイルを指す `InputStream` を作成する。
+ 入力データ内の各要素を出力ストリームにマージします。

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

これは、Kinesis ビデオストリームパーサーライブラリの使用方法を示すサンプルアプリケーションです。

このクラスは次の操作を実行します。
+ Kinesis のビデオストリームを作成します。指定した名前がすでに存在する場合は、ストリームが削除され、再作成されます。
+ Kinesis のビデオストリームに、動画フラグメントをストリーミングするために、[PutMedia](https://docs.aws.amazon.com/kinesisvideostreams/latest/dg/API_dataplane_PutMedia.html) を呼び出します。
+ Kinesis のビデオストリームから動画フラグメントをストリーミングするために、[GetMedia](https://docs.aws.amazon.com/kinesisvideostreams/latest/dg/API_dataplane_GetMedia.html) を呼び出します。
+ [StreamingMkvReader](#parser-library-write-SMSR) を使用してストリームで返されたフラグメントを解析し、[FragmentMetadataVisitor](#parser-library-write-FMV) を使用してフラグメントを記録します。

### ストリームを削除して再作成
<a name="parser-library-write-example-create"></a>

次のコード例 (`StreamOps.java` ファイルから) は、特定の Kinesis のビデオストリーム を削除します。

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

次のコード例 (`StreamOps.java` ファイルから) は、指定された名前の Kinesis のビデオストリームを作成します。

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

### PutMedia 呼び出し
<a name="parser-library-write-example-putmedia"></a>

次のコード例 (`PutMediaWorker.java` ファイルから) は、ストリームの [PutMedia](https://docs.aws.amazon.com/kinesisvideostreams/latest/dg/API_dataplane_PutMedia.html) を呼び出します。

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

### GetMedia 呼び出し
<a name="parser-library-write-example-getmedia"></a>

次のコード例 (`GetMediaWorker.java` ファイルから) は、ストリームの [GetMedia](https://docs.aws.amazon.com/kinesisvideostreams/latest/dg/API_dataplane_GetMedia.html) を呼び出します。

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

### GetMedia の結果を解析
<a name="parser-library-write-example-parse"></a>

このセクションでは、[StreamingMkvReader](#parser-library-write-SMSR)、[FragmentMetadataVisitor](#parser-library-write-FMV)、`CompositeMkvElementVisitor` を使用して、`GetMedia` から返されたデータを解析し、ファイルに保存して、ログに記録する方法について説明します。

#### StreamingMkvReader で GetMedia の出力を読み込む
<a name="parser-library-write-example-parse-smr"></a>

次のコード例 (`GetMediaWorker.java` ファイルから) は、[StreamingMkvReader](#parser-library-write-SMSR) を作成し、それを使用して [GetMedia](https://docs.aws.amazon.com/kinesisvideostreams/latest/dg/API_dataplane_GetMedia.html) オペレーションの結果を解析します。

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

上記のコード例では、[StreamingMkvReader](#parser-library-write-SMSR) は `GetMedia` 結果のペイロードから `MKVElement` オブジェクトを取得します。次のセクションでは、要素は [FragmentMetadataVisitor](#parser-library-write-FMV) に渡されます。

#### FragmentMetadataVisitor を使用してフラグメントを取得する
<a name="parser-library-write-example-parse-fmv"></a>

次のコード例 (`KinesisVideoExample.java` および `StreamingMkvReader.java` ファイルから) は、[FragmentMetadataVisitor](#parser-library-write-FMV) を作成します。[StreamingMkvReader](#parser-library-write-SMSR) で反復された `MkvElement` オブジェクトは、`accept` メソッドを使用して訪問者に渡されます。

*`KinesisVideoExample.java`: から*

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

*`StreamingMkvReader.java`: から*

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

#### 要素を記録し、ファイルに書き込む
<a name="parser-library-write-example-parse-cmev"></a>

次のコード例 (`KinesisVideoExample.java`ファイルから) は、以下のオブジェクトを作成し、それらを `GetMediaProcessingArguments` 関数の戻り値の一部として返します。
+ システムログに書き込む `LogVisitor` (`MkvElementVisitor` の拡張)。
+ 受信データを MKV ファイルに書き込む `OutputStream`。
+ `OutputStream` にバインドされたデータをバッファする `BufferedOutputStream`。
+ 同じトラックと EBML データで `GetMedia` 結果の連続した要素をマージする [OutputSegmentMerger](#parser-library-write-OSM)
+ [FragmentMetadataVisitor](#parser-library-write-FMV)、[OutputSegmentMerger](#parser-library-write-OSM)、 を 1 つの要素の訪問者`LogVisitor`に構成`CompositeMkvElementVisitor`する 。

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

その後、メディア処理引数は に渡され`GetMediaWorker`、次に に渡され`ExecutorService`、 は別のスレッドでワーカーを実行します。

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