

# Use the C producer library
<a name="producer-sdk-c-api"></a>

You can use the Amazon Kinesis Video Streams provided C producer library to write application code to send media data from a device to a Kinesis video stream. 

## Object model
<a name="producer-sdk-c-objectmodel"></a>

The Kinesis Video Streams C producer library is based on a common component called Platform Independent Codebase (PIC), which is available on GitHub at [https://github.com/awslabs/amazon-kinesis-video-streams-pic/](https://github.com/awslabs/amazon-kinesis-video-streams-pic/). The PIC contains platform-independent business logic for the foundational components. The Kinesis Video Streams C producer library wraps PIC with additional layer of API that allows scenario-and platform-specific callbacks and events. The Kinesis Video Streams C producer library has the following components built on top of PIC:
+ **Device info providers** – Exposes the `DeviceInfo` structure that can be directly supplied to the PIC API. You can configure a set of providers, including application scenario-optimized provider that can optimize the content store based on the number and types of streams that your application handles and the amount of required buffering configured based on the amount of available RAM.
+ **Stream info provider** – Exposes the `StreamInfo` structure that can be directly supplied to the PIC API. There's a set of providers that are specific to the application types and the common types of streaming scenarios. These include providers such as video, audio, and audio and video multitrack. Each of these scenarios have defaults that you can customize according to your application's requirements. 
+ **Callback provider** – Exposes the `ClientCallbacks` structure that can be directly supplied to the PIC API. This includes a set of callback providers for networking (CURL-based API callbacks), authorization (AWS credentials API), and retry streaming on errors callbacks. The Callback Provider API takes a number of arguments to configure, such as the AWS Region and authorization information. This is done by using IoT certificates or by using AWS AccessKeyId, SecretKey, or SessionToken. You can enhance Callback Provider with custom callbacks if your application needs further processing of a particular callback to achieve some application-specific logic.
+ **FrameOrderCoordinator** – Helps handle audio and video synchronization for multi-track scenarios. It has default behavior, which you can customize to handle your application's specific logic. It also streamlines the frame metadata packaging in PIC Frame structure before submitting it to the lower-layer PIC API. For non-multitrack scenarios, this component is a pass-through to PIC putFrame API.

The C library provides the following objects to manage sending data to a Kinesis video stream:
+ **KinesisVideoClient** – Contains information about your device and maintains callbacks to report on Kinesis Video Streams events.
+ **KinesisVideoStream** – Represents information about the video stream's parameters, such as name, data retention period, and media content type.

## Put media into the stream
<a name="producer-sdk-c-putframe"></a>

You can use the C library provided methods (for example, `PutKinesisVideoFrame`) to put data into the `KinesisVideoStream` object. The library then manages the internal state of the data, which can include the following tasks: 
+ Performing authentication.
+ Watching for network latency. If the latency is too high, the library might choose to drop frames.
+ Tracking status of streaming in progress.

## Procedure: Use the C producer SDK
<a name="producer-sdk-c-using"></a>

This procedure demonstrates how to use the Kinesis Video Streams client and media sources in a C application to send H.264-encoded video frames to your Kinesis video stream.

The procedure includes the following steps:
+ [Download the C producer library code](producersdk-c-download.md)
+ [Write and examine the code](producersdk-c-write.md)
+ [Run and verify the code](producersdk-c-test.md)

# Prerequisites
<a name="producer-sdk-c-prerequisites"></a>

Before you set up the C producer SDK, ensure that you have the following prerequisites: 
+ **Credentials** – In the sample code, you provide credentials by specifying a profile that you set up in your AWS credentials profile file. If you haven't already done so, first set up your credentials profile. 

  For more information, see [Set up AWS Credentials and Region for Development](http://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/setup-credentials.html).
+ **Certificate store integration** – The Kinesis Video Streams producer library must establish trust with the service it calls. This is done through validating the certificate authorities (CAs) in the public certificate store. On Linux-based models, this store is located in the `/etc/ssl`/ directory. 

  Download the certificate from the following location to your certificate store:

  [https://www.amazontrust.com/repository/SFSRootCAG2.pem](https://www.amazontrust.com/repository/SFSRootCAG2.pem)
+ Install the following build dependencies for macOS:
  + [Autoconf 2.69](http://www.gnu.org/software/autoconf/autoconf.html) (License GPLv3\$1/Autoconf: GNU GPL version 3 or later) 
  + [CMake 3.7 or 3.8](https://cmake.org/)
  + [Pkg-Config](https://www.freedesktop.org/wiki/Software/pkg-config/)
  + xCode (macOS) / clang / gcc (xcode-select version 2347)
  + Java Development Kit (JDK) (for Java JNI compilation)
  + [Lib-Pkg](https://github.com/freebsd/pkg/tree/master/libpkg)
+ Install the following build dependencies for Ubuntu:
  + Git: `sudo apt install git`
  + [CMake](http://kitware.com/cmake): `sudo apt install cmake`
  + G\$1\$1: `sudo apt install g++`
  + pkg-config: `sudo apt install pkg-config`
  + OpenJDK: `sudo apt install openjdk-8-jdk`
  + Set the `JAVA_HOME` environment variable: `export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64/`

# Download the C producer library code
<a name="producersdk-c-download"></a>

In this section, you download the low-level libraries. For prerequisites and other details about this example, see [Use the C\$1\$1 producer library](producer-sdk-cpp.md).





1. Create a directory, and then clone the example source code from the GitHub repository. 

   ```
   git clone --recursive https://github.com/awslabs/amazon-kinesis-video-streams-producer-c.git
   ```
**Note**  
If you miss running git clone with `--recursive`, run `git submodule update --init` in the `amazon-kinesis-video-streams-producer-c/open-source` directory. You must also install pkg-config, CMake, and a build environment.  
For more information, see the `README.md` in [https://github.com/awslabs/amazon-kinesis-video-streams-producer-c.git](https://github.com/awslabs/amazon-kinesis-video-streams-producer-c.git).

1. Open the code in the integrated development environment (IDE) of your choice (for example, [Eclipse](https://www.eclipse.org/)).

# Write and examine the code
<a name="producersdk-c-write"></a>

In this section, you examine the code of the sample application `KvsVideoOnlyStreamingSample.c` in the `samples` folder of the [https://github.com/awslabs/amazon-kinesis-video-streams-producer-c](https://github.com/awslabs/amazon-kinesis-video-streams-producer-c) repo on GitHub. You downloaded this code in the previous step. This sample demonstrates how to use the C producer library to send H.264-encoded video frames inside the folder `samples/h264SampleFrames` to your Kinesis video stream.

This sample application has three sections:
+ Initialization and configuration:
  + Initializing and configuring the platform-specific media pipeline.
  + Initializing and configuring KinesisVideoClient and KinesisVideoStream for the pipeline, setting the callbacks, integrating scenario-specific authentication, extracting and submitting codec private data, and getting the stream to READY state.
+ Main loop:
  + Getting the frame from the media pipeline with the timestamps and flags.
  + Submitting the frame to the KinesisVideoStream.
+ Teardown:
  + Stopping (sync) KinesisVideoStream, freeing KinesisVideoStream, freeing KinesisVideoClient.

This sample application completes the following tasks:
+ Call the `createDefaultDeviceInfo` API to create the `deviceInfo` object that contains information about the device or storage configuration.

  ```
  // 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;
  ```
+ Call the `createRealtimeVideoStreamInfoProvider` API to create the `StreamInfo` object.

  ```
  CHK_STATUS(createRealtimeVideoStreamInfoProvider(streamName, DEFAULT_RETENTION_PERIOD, DEFAULT_BUFFER_DURATION, &pStreamInfo));
  // adjust members of pStreamInfo here if needed
  ```
+ Call the `createDefaultCallbacksProviderWithAwsCredentials` API to create the default callbacks provider based on static AWS credentials.

  ```
  CHK_STATUS(createDefaultCallbacksProviderWithAwsCredentials(accessKey,
                                                                  secretKey,
                                                                  sessionToken,
                                                                  MAX_UINT64,
                                                                  region,
                                                                  cacertPath,
                                                                  NULL,
                                                                  NULL,
                                                                  FALSE,
                                                                  &pClientCallbacks));
  ```
+ Call the `createKinesisVideoClient` API to create the `KinesisVideoClient` object that contains information about your device storage and maintains callbacks to report on Kinesis Video Streams events.

  ```
  CHK_STATUS(createKinesisVideoClient(pDeviceInfo, pClientCallbacks, &clientHandle));                
  ```
+ Call the `createKinesisVideoStreamSync` API to create the `KinesisVideoStream` object.

  ```
  CHK_STATUS(createKinesisVideoStreamSync(clientHandle, pStreamInfo, &streamHandle));                
  ```
+ Set up a sample frame and call `PutKinesisVideoFrame` API to send that frame to the `KinesisVideoStream` object.

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

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

# Run and verify the code
<a name="producersdk-c-test"></a>



To run and verify the code for the [Use the C\$1\$1 producer library](producer-sdk-cpp.md), do the following:

1. Run the following commands to create a `build` directory in your [downloaded C SDK](https://github.com/awslabs/amazon-kinesis-video-streams-producer-c.git), and launch `cmake` from it:

   ```
   mkdir -p amazon-kinesis-video-streams-producer-c/build; 
   cd amazon-kinesis-video-streams-producer-c/build; 
   cmake ..
   ```

   You can pass the following options to `cmake ..`
   + `-DBUILD_DEPENDENCIES` - whether to build depending libraries from source.
   + `-DBUILD_TEST=TRUE` - build unit and integration tests. Might be useful to confirm support for your device. 

     `./tst/webrtc_client_test`
   + `-DCODE_COVERAGE` - enable coverage reporting.
   + `-DCOMPILER_WARNINGS` - enable all compiler warnings.
   + `-DADDRESS_SANITIZER` - build with AddressSanitizer.
   + `-DMEMORY_SANITIZER` - build with MemorySanitizer.
   + `-DTHREAD_SANITIZER` - build with ThreadSanitizer.
   + `-DUNDEFINED_BEHAVIOR_SANITIZER` - build with UndefinedBehaviorSanitizer.
   + `-DALIGNED_MEMORY_MODEL` - build for aligned memory model only devices. Default is `OFF`.

1. Navigate to the `build` directory that you just created with the previous step, and run `make` to build the WebRTC C SDK and its provided samples. 

   ```
   make                
   ```

1. The sample application `kinesis_video_cproducer_video_only_sample` sends h.264-encoded video frames inside the folder `samples/h264SampleFrames` to Kinesis Video Streams. The following command sends the video frames in a loop for ten seconds to Kinesis Video Streams:

   ```
   ./kinesis_video_cproducer_video_only_sample YourStreamName 10
   ```

   If you want to send H.264-encoded frames from another folder (for example, `MyH264FramesFolder`), run the sample with the following arguments:

   ```
   ./kinesis_video_cproducer_video_only_sample YourStreamName 10 MyH264FramesFolder
   ```

1. To enable verbose logs, define the `HEAP_DEBUG` and `LOG_STREAMING` C-defines by uncommenting the appropriate lines in `CMakeList.txt`.

You can monitor the progress of the test suite in the debug output in your IDE. You can also monitor the traffic on your stream by watching the metrics that are associated with your stream in the Amazon CloudWatch console, such as `PutMedia.IncomingBytes`.

**Note**  
The console doesn't display the data as a video stream because the test harness only sends frames of empty bytes.