

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 撰寫並檢查程式碼
<a name="producersdk-cpp-write"></a>

在 的本節中[使用 C\+\+ 生產者程式庫](producer-sdk-cpp.md)，您會檢查 C\+\+ 測試工具組中的程式碼 (`tst/ProducerTestFixture.h` 和其他 檔案）。您在上一節中下載了此程式碼。

**平台獨立** C\+\+ 範例顯示下列編碼模式：
+ 建立 執行個體`KinesisVideoProducer`以存取 Kinesis Video Streams。
+ 建立 `KinesisVideoStream` 的執行個體。 AWS 帳戶 如果相同名稱的串流尚未存在，這會在 中建立 Kinesis 影片串流。
+ 當可用時，在 `KinesisVideoStream` 上呼叫每個資料畫面的 `putFrame`，將其傳送到串流。

下列各節提供有關此編碼模式的詳細資訊。



## 建立 KinesisVideoProducer 的執行個體
<a name="producersdk-cpp-write-create-producer"></a>

您呼叫 `KinesisVideoProducer` 方法建立 `KinesisVideoProducer::createSync` 物件。下列範例在 `KinesisVideoProducer` 檔案中建立 `ProducerTestFixture.h`：

```
kinesis_video_producer_ = KinesisVideoProducer::createSync(move(device_provider_),
    move(client_callback_provider_),
    move(stream_callback_provider_),
    move(credential_provider_),
    defaultRegion_);
```

`createSync` 方法會使用下列三個參數：
+ `DeviceInfoProvider` 物件，其會傳回包含裝置或存放區組態相關資訊的 `DeviceInfo` 物件。
**注意**  
您使用 `deviceInfo.storageInfo.storageSize` 參數設定內容存放區大小。您的內容串流會共用內容存放區。若要判斷您的儲存大小需求，請將平均畫面大小乘以為所有串流最大持續時間存放的畫面數量，再乘以 1.2 以計算磁碟重組。例如，假設您的應用程式具有以下組態：  
三個串流
最大持續時間 3 分鐘
每個串流為每秒 30 個影格 (FPS)
每個畫面大小為 10,000 KB
此應用程式的內容存放區需求為 **3 （串流） \* 3 （分鐘） \* 60 （分鐘內秒） \* 10000 (kb) \* 1.2 （重組額度） = 194.4 Mb \~ 200 Mb。**
+ `ClientCallbackProvider` 物件，其會傳回報告用戶端特定事件的函數指標。
+ `StreamCallbackProvider` 物件，其會傳回串流特定事件發生後收回的函數指標。
+ `CredentialProvider` 物件，可讓您存取 AWS 登入資料環境變數。
+ The AWS 區域 ("us-west-2")。服務端點取決於區域。

## 建立 KinesisVideoStream 的執行個體
<a name="producersdk-cpp-write-create-stream"></a>

您呼叫使用 `StreamDefinition` 參數的 `KinesisVideoProducer::CreateStream` 方法建立 `KinesisVideoStream` 物件。該範例會在 `ProducerTestFixture.h` 檔案中建立 `KinesisVideoStream`，並將軌道類型設為視訊，軌道 ID 設為 1：

```
auto stream_definition = make_unique<StreamDefinition>(stream_name,
                                               hours(2),
                                               tags,
                                               "",
                                               STREAMING_TYPE_REALTIME,
                                               "video/h264",
                                               milliseconds::zero(),
                                               seconds(2),
                                               milliseconds(1),
                                               true,
                                               true,
                                               true);
return kinesis_video_producer_->createStream(move(stream_definition));
```

`StreamDefinition` 物件包含以下欄位：
+ 串流名稱。
+ 資料保留期間。
+ 標籤的串流。這些標籤可供消費者應用程式用於尋找正確的串流，或是取得更多關於串流的資訊。​也可以在 AWS 管理主控台​ 查看這些標籤。
+ AWS KMS 串流的加密金鑰。如需詳細資訊，請參閱[Kinesis Video Streams 中的資料保護](how-kms.md)。
+ 串流類型。目前唯一有效的值為：`STREAMING_TYPE_REALTIME`。
+ 媒體內容類型。
+ 媒體延遲。此值目前未使用，且應設為 0。
+ 每個片段的播放持續時間。
+ 媒體時間碼擴展。
+ 媒體是否使用關鍵影格片段。
+ 媒體是否使用時間碼。
+ 媒體是否使用絕對片段時間。

## 將音軌新增至 Kinesis 影片串流
<a name="producersdk-cpp-write-add-audiotrack-to-stream"></a>

您可以使用 的 `addTrack`方法，將音訊軌詳細資訊新增至視訊軌串流定義`StreamDefinition`：

```
stream_definition->addTrack(DEFAULT_AUDIO_TRACKID, DEFAULT_AUDIO_TRACK_NAME, DEFAULT_AUDIO_CODEC_ID, MKV_TRACK_INFO_TYPE_AUDIO);
```

`addTrack` 方法需要下列參數：
+ 音軌 ID （做為音訊的 ID)。這應該是唯一且非零的數值。
+ 使用者定義的音軌名稱 （例如，音訊音軌的「音訊」)。
+ 此音軌的轉碼器 ID （例如，音訊音軌 "A\_AAC")。
+ 音軌類型 （例如，將 MKV\_TRACK\_INFO\_TYPE\_AUDIO 的列舉值用於音訊）。

如果您有音軌的轉碼器私有資料，則可以在呼叫 addTrack 函數時傳遞。您也可以在建立 KinesisVideoStream 物件之後傳送轉碼器建立私有資料，同時在 KinesisVideoStream 中呼叫開始方法。

## 將影格放入 Kinesis 影片串流
<a name="producersdk-cpp-write-putframe"></a>

您可以使用 將媒體放入 Kinesis 影片串流`KinesisVideoStream::putFrame`，並傳入包含 標頭和媒體資料的`Frame`物件。此範例呼叫 `ProducerApiTest.cpp` 檔案中的 `putFrame`：

```
frame.duration = FRAME_DURATION_IN_MICROS * HUNDREDS_OF_NANOS_IN_A_MICROSECOND;
    frame.size = SIZEOF(frameBuffer_);
    frame.frameData = frameBuffer_;
    MEMSET(frame.frameData, 0x55, frame.size);

    while (!stop_producer_) {
        // Produce frames
        timestamp = std::chrono::duration_cast<std::chrono::nanoseconds>(
                std::chrono::system_clock::now().time_since_epoch()).count() / DEFAULT_TIME_UNIT_IN_NANOS;
        frame.index = index++;
        frame.decodingTs = timestamp;
        frame.presentationTs = timestamp;

        // Key frame every 50th
        frame.flags = (frame.index % 50 == 0) ? FRAME_FLAG_KEY_FRAME : FRAME_FLAG_NONE;
    ...

    EXPECT_TRUE(kinesis_video_stream->putFrame(frame));
```

**注意**  
上述 C\+\+ 生產者範例會傳送測試資料的緩衝區。在實際的應用程式中，您應該從媒體資源 (例如攝影機) 獲得畫面資料的畫面緩衝和大小。

`Frame` 物件包含以下欄位：
+ 畫面索引。此應為單一遞增的值。
+ 與畫面關聯的旗標。例如，如果設定編碼器產生關鍵影格，將會指定 `FRAME_FLAG_KEY_FRAME` 旗標給此畫面。
+ 解碼時間戳記。
+ 簡報時間戳記。
+ 畫面的持續時間 (到 100 ns 單位)。
+ 畫面的大小 (位元組)。
+ 畫面資料。

如需影格格式的詳細資訊，請參閱 [Kinesis Video Streams 資料模型](how-data.md)。

## 將 KinesisVideoFrame 放入 KinesisVideoStream 的特定軌道
<a name="producersdk-cpp-write-putframeintospecifictrack"></a>

您可以使用 `PutFrameHelper`類別將影格資料放入特定軌道。首先，呼叫 `getFrameDataBuffer`以取得其中一個預先配置緩衝區的指標，以填入`KinesisVideoFrame`資料。然後，您可以呼叫 `putFrameMultiTrack`來傳送 `KinesisVideoFrame`以及布林值，以指出影格資料類型。如果是視訊資料，使用 true，或者，如果影格包含音訊資料，則使用 false。此`putFrameMultiTrack`方法使用佇列機制，以確保 MKV 片段維持單調增加的影格時間戳記，且任兩個片段都不會重疊。例如，片段第一個影格的 MKV 時間戳記應一律大於先前片段最後一個影格的 MKV 時間戳記。

`PutFrameHelper` 具有下列欄位：
+ 佇列中的音訊影格數目上限。
+ 佇列中的影片影格數目上限。
+ 為單一音訊影格配置的大小。
+ 要為單一影片影格配置的大小。

## 存取指標和指標記錄
<a name="producersdk-cpp-write-metrics"></a>

C\+\+ 生產者 SDK 包含指標和指標記錄的功能。

您可以使用 `getKinesisVideoMetrics`和 `getKinesisVideoStreamMetrics` API 操作來擷取 Kinesis Video Streams 和作用中串流的相關資訊。

以下是來自 `kinesis-video-pic/src/client/include/com/amazonaws/kinesis/video/client/Include.h` 檔案的程式碼。

```
/**
* Gets information about the storage availability.
*
* @param 1 CLIENT_HANDLE - the client object handle.
* @param 2 PKinesisVideoMetrics - OUT - Kinesis Video metrics to be filled.
*
* @return Status of the function call.
*/
PUBLIC_API STATUS getKinesisVideoMetrics(CLIENT_HANDLE, PKinesisVideoMetrics);

/**
* Gets information about the stream content view.
*
* @param 1 STREAM_HANDLE - the stream object handle.
* @param 2 PStreamMetrics - Stream metrics to fill.
*
* @return Status of the function call.
*/
PUBLIC_API STATUS getKinesisVideoStreamMetrics(STREAM_HANDLE, PStreamMetrics);
```

由 `getKinesisVideoMetrics` 填滿的 `PClientMetrics` 物件包含下列資訊：
+ **contentStoreSize：**內容存放區 (用於存放串流資料的記憶體) 的總大小 (位元組)。
+ **contentStoreAvailableSize：**內容存放區中可用的記憶體，以位元組為單位。
+ **contentStoreAllocatedSize：**內容存放區的配置記憶體。
+ **totalContentViewsSize：**用於內容檢視的總記憶體。內容檢視是內容存放區中一系列的資訊索引。
+ **totalFrameRate：**所有作用中串流的每秒畫面彙總數量。
+ **totalTransferRate：**所有串流中每秒傳送的總位元數 (bps)。

由 `getKinesisVideoStreamMetrics` 填滿的 `PStreamMetrics` 物件包含下列資訊：
+ **currentViewDuration：**內容檢視前端 （編碼影格時） 與目前位置 （將影格資料傳送至 Kinesis Video Streams 時） 之間 100 ns 單位的差異。
+ **overallViewDuration：**內容檢視前端 （編碼影格時） 與尾端 （從記憶體排清影格時，因為超過內容檢視的總配置空間，或因為從 Kinesis Video Streams 接收`PersistedAck`訊息，而已知會保留的影格） 之間的 100 ns 單位差異。
+ **currentViewSize：**內容檢視的大小，從前端 （編碼影格時） 到目前位置 （將影格傳送至 Kinesis Video Streams 時）。
+ **overallViewSize：**內容檢視的總大小 (位元組)。
+ **currentFrameRate：**串流的最新測量速率 (每秒畫面數)。
+ **currentTransferRate：**串流的最新測量速率 (每秒位元組)。

## 分解
<a name="producersdk-cpp-write-teardown"></a>

如果您想要傳送緩衝區中剩餘的位元組，並等待 `ACK`，則可以使用 `stopSync`：

```
kinesis_video_stream->stopSync();            
```

或者，您可以呼叫 `stop` 來結束串流：

```
kinesis_video_stream->stop();            
```

停止串流後，您可以透過叫用下列 API 來釋出串流：

```
kinesis_video_producer_->freeStream(kinesis_video_stream);            
```