Kinesis Video Streams C++ プロデューサーライブラリの使い方を探る

先日、

[コンビニで買った育てるサラダをrasPiで撮ってKinesisに流してゴニョゴニョする ](https://qiita.com/ikegam1/items/e420f48e73d05f2d1993)

ってのでKinesis video stream のプロデューサーライブラリっていうのを使いましたが、ただビルドしてsample_appを動かしただけ。
ちょっと自分のコードにしたいなー、と思ったので見てみることにしました。

DLして設定する手順はこちら
https://docs.aws.amazon.com/ja_jp/kinesisvideostreams/latest/dg/producersdk-cpp-download.html

落としたソースの```kinesis-video-gst-demo/kinesis_video_gstreamer_sample_app.cpp``` の中身をみてみる。
トータル649行、そんなに大きいものではない。

## 0~50
0～50行目あたりはincludeやらDEFINEやら。
例えばGstreamerのパラメーターとか定義されてる。
https://docs.aws.amazon.com/ja_jp/kinesisvideostreams/latest/dg/examples-gstreamer-plugin-parameters.html

## gstreamer_init
main関数で呼ばれてるのはこれ。
最初は[gstreamer](https://docs.aws.amazon.com/ja_jp/kinesisvideostreams/latest/dg/examples-gstreamer-plugin.html)に渡すオプションの設定とかっぽいですね。
例えばargumentsから```int width = 0, height = 0, framerate = 25, bitrateInKBPS = 512;```のあたりを拾う。-wとか-hとか-fとか-bとか。
ちなみにgst_initはgst/gst.cに書かれてた。gstに渡すオプションとか書いたけどgstにはそのまま渡してる。kvsにも同じのを渡すために読み取ってる感じすね。
で、446行目でkinesis_video_init(&data, stream_name);を呼びます。
一旦、ここの処理見よう。

## kinesis_video_init
```void kinesis_video_init(CustomData *data, char *stream_name) {```
とあります。
SampleDeviceInfoProvider内でstorageSizeを決めてる。
デフォは512Mだけどラズパイは256以下にするのがよさそう。
ちなみにDefaultDeviceInfoProviderのあたりとかはここに書かれてる。
https://docs.aws.amazon.com/ja_jp/kinesisvideostreams/latest/dg/producer-reference-structures-producer.html#producer-reference-structures-producer-deviceinfo

で、awsのcredential作るとこのあとで```KinesisVideoProducer::createSync```があってKinesisVideoProducerのインスタンスが作られる。
その次にStreamDefinition～createStreamSyncでkinesis video streamのインスタンスを作る。基本、これらを操作していく感じでしょうか。
そしてこのへんは [ここ](https://docs.aws.amazon.com/ja_jp/kinesisvideostreams/latest/dg/producersdk-cpp-write.html) に書いてある。
kinesis_video_initはここまで。

## gstreamer_init再び
kvsを初期化して、いよいよストリームを流していく部分。
途中、こんなコメントがあります。

```
    /* create the elemnents */
    /*
       gst-launch-1.0 v4l2src device=/dev/video0 ! video/x-raw,format=I420,width=1280,height=720,framerate=15/1 ! x264enc pass=quant bframes=0 ! video/x-h264,profile=baseline,format=I420,width=1280,height=720,framerate=15/1 ! matroskamux ! filesink location=test.mkv
     */
```

要は、この長ったらしいコマンドを作り上げていく感じじゃないかな。

[GStreamer アプリケーション開発マニュアル 日本語訳 (0.10.25.1)](http://oss.infoscience.co.jp/gstreamer/section-elements-create.html)
これによるとgst_element_factory_makeはGstElementっていうのを作成しているっぽい。なんかargumentの一個一個の要素を作ってる感じに見える。
例えばencorderの設定のとこで、

```
data.encoder = gst_element_factory_make("omxh264enc", "encoder");
```

ってやって正の値が返ってきたらomxh264encに対応しているからお前はRaspiだ、みたいな事をやってる。逆に対応してなかったら違うからx264encにしますよ、みたいな。

でこの後・・
やべえ。padとかcapsとかよくわかんない言葉出てくる。マニュアルに逃げよう。

[パッド](http://oss.infoscience.co.jp/gstreamer/section-intro-basics-pads.html)
>パッドは、エレメント上にあって、ほかのエレメントとの間でリンクを作成するために使用できる"プラグ"や"ポート"のようなものと考えることができます。
>ケイパビリティネゴシエーション (caps negotiation) と呼ばれるプロセスを使って、パッド間でネゴシエーションされます。データの種類は、GstCaps として記述されます。

なんとなくわかったようなわかんないような。
パッドとcapsでエレメントをつなげるのか。
capsは```gst_caps_new_simple```で作るんだけど、widthやheightやvideoformatが必要な感じっぽい。

516行目あたりからは解像度とかフレームレート決めてるみたいだけど、
```
        vector<int> res_width = {640, 1280, 1920};
        vector<int> res_height = {480, 720, 1080};
        vector<int> fps = {30, 25, 20};
```
この組み合わせなのか。```resolution_supported```ってのでサポートされてるかをチェックしてるみたい。解像度を見てからそれに対してのフレームレートのチェック。もっと小さいサイズにしたらアカンのやろうか。やってみよう。
あと ```    if (width != 0 && height != 0) { ```の部分があんまりよくわかってない。これだと手動で設定できないことにならんのやろうか。
そしてcapsだとかpadはこのチェックのために使ってるだけなのか。

で、gst_bin_add_manyで実際のコマンドを作ってるっぽい。これで一連の処理がつながって、最後のappsinkってとこでkvsにリンクするんじゃなかろうか。
```gst_element_set_state```って関数で再生されるみたい。


細かいとこや推測で済ましたとこもあるけど、いじりたいところはだいたいわかった。

## そしてとりあえず、
ファイルを複製しつつ、解像度とフレームレートのところだけ調整してみました。
結果、こんな感じ。

```cpp:raspi_stream_app.cpp
        vector<int> res_width = {320, 352, 640};
        vector<int> res_height = {240, 288, 480};
        vector<int> fps = {5, 10, 15};
```

にして、

```
[DEBUG][2018-11-24 06:09:51] resolution supported width:320
[DEBUG][2018-11-24 06:09:51] resolution supported height:240
[DEBUG][2018-11-24 06:09:51] resolution supported fp:15
```

自分のコードってほどではないけど、とりあえずいじれるようになったしいいかな。
しかし、フレームレートは15未満は無理なんかなぁ。
ほんとは画像をパシャパシャしてタイムラプス動画にする程度でもいいレベルではある。（しかしkinesis video stream使いたかったし。。)