

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

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

在本節`KvsVideoOnlyStreamingSample.c`中，您會在 GitHub 上 [https://github.com/awslabs/amazon-kinesis-video-streams-producer-c](https://github.com/awslabs/amazon-kinesis-video-streams-producer-c) 儲存庫的 `samples`資料夾中檢查範例應用程式的程式碼。您在上一個步驟中下載了此程式碼。此範例示範如何使用 C 生產者程式庫，將資料夾內的 H.264 編碼影片影格`samples/h264SampleFrames`傳送至 Kinesis 影片串流。

此範例應用程式有三個部分：
+ 初始化及設定：
  + 初始化及設定平台特定的媒體管道。
  + 初始化及設定管道的 KinesisVideoClient 和 KinesisVideoStream、設定回呼、整合案例特定驗證、擷取和提交轉碼器私有資料，以及讓串流成為「就緒」狀態。
+ 主要迴圈：
  + 從包含時間戳記及旗標的媒體管道取得影格。
  + 提交影格至 KinesisVideoStream。
+ 分解：
  + 停止 (同步) KinesisVideoStream、釋放 KinesisVideoStream、釋放 KinesisVideoClient。

此範例應用程式完成下列任務：
+ 呼叫 `createDefaultDeviceInfo` API 以建立 `deviceInfo` 物件，其中包含裝置或儲存組態的相關資訊。

  ```
  // default storage size is 128MB. Use setDeviceInfoStorageSize after create to change storage size.
  CHK_STATUS(createDefaultDeviceInfo(&pDeviceInfo));
  // adjust members of pDeviceInfo here if needed
      pDeviceInfo->clientInfo.loggerLogLevel = LOG_LEVEL_DEBUG;
  ```
+ 呼叫 `createRealtimeVideoStreamInfoProvider` API 以建立 `StreamInfo` 物件。

  ```
  CHK_STATUS(createRealtimeVideoStreamInfoProvider(streamName, DEFAULT_RETENTION_PERIOD, DEFAULT_BUFFER_DURATION, &pStreamInfo));
  // adjust members of pStreamInfo here if needed
  ```
+ 呼叫 `createDefaultCallbacksProviderWithAwsCredentials` API，根據靜態 AWS 登入資料建立預設回呼提供者。

  ```
  CHK_STATUS(createDefaultCallbacksProviderWithAwsCredentials(accessKey,
                                                                  secretKey,
                                                                  sessionToken,
                                                                  MAX_UINT64,
                                                                  region,
                                                                  cacertPath,
                                                                  NULL,
                                                                  NULL,
                                                                  FALSE,
                                                                  &pClientCallbacks));
  ```
+ 呼叫 `createKinesisVideoClient` API 以建立包含裝置儲存相關資訊的`KinesisVideoClient`物件，並維護回呼以報告 Kinesis Video Streams 事件。

  ```
  CHK_STATUS(createKinesisVideoClient(pDeviceInfo, pClientCallbacks, &clientHandle));                
  ```
+ 呼叫 `createKinesisVideoStreamSync` API 以建立 `KinesisVideoStream` 物件。

  ```
  CHK_STATUS(createKinesisVideoStreamSync(clientHandle, pStreamInfo, &streamHandle));                
  ```
+ 設定範例影格並呼叫 `PutKinesisVideoFrame` API，將該影格傳送至 `KinesisVideoStream` 物件。

  ```
   // setup sample frame
      MEMSET(frameBuffer, 0x00, frameSize);
      frame.frameData = frameBuffer;
      frame.version = FRAME_CURRENT_VERSION;
      frame.trackId = DEFAULT_VIDEO_TRACK_ID;
      frame.duration = HUNDREDS_OF_NANOS_IN_A_SECOND / DEFAULT_FPS_VALUE;
      frame.decodingTs = defaultGetTime(); // current time
      frame.presentationTs = frame.decodingTs;
  
      while(defaultGetTime() > streamStopTime) {
          frame.index = frameIndex;
          frame.flags = fileIndex % DEFAULT_KEY_FRAME_INTERVAL == 0 ? FRAME_FLAG_KEY_FRAME : FRAME_FLAG_NONE;
          frame.size = SIZEOF(frameBuffer);
  
          CHK_STATUS(readFrameData(&frame, frameFilePath));
  
          CHK_STATUS(putKinesisVideoFrame(streamHandle, &frame));
          defaultThreadSleep(frame.duration);
  
          frame.decodingTs += frame.duration;
          frame.presentationTs = frame.decodingTs;
          frameIndex++;
          fileIndex++;
          fileIndex = fileIndex % NUMBER_OF_FRAME_FILES;
      }
  ```
+ 分解：

  ```
  CHK_STATUS(stopKinesisVideoStreamSync(streamHandle));
  CHK_STATUS(freeKinesisVideoStream(&streamHandle));
  CHK_STATUS(freeKinesisVideoClient(&clientHandle));
  ```