LoginSignup
20
18

More than 5 years have passed since last update.

作って学ぶGStreamerエレメント

Last updated at Posted at 2017-10-06

Debian GNU/Linux (amd64, stretch)にて確認。

この文書では、以下のGStreamerエレメントを作る

  • guint32をインクリメントして出力し続けるnumbersrc
  • numbersrcを受けて数字を2倍して出力するtwicefilter
  • 結果を出力するnumbersink

チュートリアル等を参照しながら手探りで実行した結果なので間違いあるかも。

前準備

パッケージインストール

$ sudo apt install build-essential libgstreamer1.0-dev indent

エレメント雛形作成スクリプト(gst-element-maker)がGNUindentを使用するため一緒にインストールしている。

ツールのコピー

Debianだと残念ながらgst-plugins-badに入っているはずのgst-element-makerが無いため、リポジトリからコピーする。

$ git clone https://anongit.freedesktop.org/git/gstreamer/gst-plugins-bad.git
$ cd gst-plugsins-bad/tools
$ cp -r gst-element-maker element-templates <パスが通ったディレクトリ>

あとgst-element-makerから呼ばれるgst-indentもコピーする。

$ git clone https://anongit.freedesktop.org/git/gstreamer/gstreamer.git
$ cd gstreamer/tools
$ cp gst-indent <パスが通ったディレクトリ>

エレメント作成

ソースとシンクを作る

basesrcを継承してnumbersrc, basesinkを継承してnumbersinkを作成する。

$ gst-element-maker numbersrc basesrc
$ gst-element-maker numbersink basesink

gstnumbersrc.c, gstnumbersrc.h, gstnumbersink.c, gstnumbersink.hの4ファイルが作成され、ビルドまでしてgstnumbersrc.so, gstnumbersink.soが作成される。

Makefileを追加しビルド出来るようにしたものが以下
https://github.com/maueki/learning-gstreamer/tree/tag_add_makefile

だが実行してみるとエラーがでてしまう。

$ GST_PLUGIN_PATH=. gst-launch-1.0 numbersrc ! numbersink

(gst-launch-1.0:36307): GStreamer-CRITICAL **: gst_mini_object_ref: assertion 'mini_object != NULL' failed
(以下エラーいろいろ)
WARNING: erroneous pipeline: numbersrc0 を numbersink0 へリンクできません

原因はgst-element-makerで作成されたファイルではGstBaseSrcやGstBaseSinkのvmethodをオーバーライドしているが、NULLを返してしまったりとあまりよろしくない実装をしてしまっているためである。

ソース側はfill()、シンク側はrender()がオーバーライドされていれば最低限動作するため、それ以外のオーバーロードを無効にしたものが以下
https://github.com/maueki/learning-gstreamer/tree/tag_1st_run

ビルドして実行してみると

$ GST_PLUGIN_PATH=. gst-launch-1.0 numbersrc ! numbersink                             
パイプラインを一時停止 (PAUSED) にしています...     
Pipeline is PREROLLING ...                          
Pipeline is PREROLLED ...                           
パイプラインを再生中 (PLAYING) にしています...      
New clock: GstSystemClock  

無事動作した。

ソースからシンクへデータを受け渡す

ソースのgst_numbersrc_fill()を修正しデータを送ってみる

gstnumbersrc.c
static GstFlowReturn
gst_numbersrc_fill (GstBaseSrc * src, guint64 offset, guint size,
    GstBuffer * buf)
{
  static guint32 i = 0;
  GstNumbersrc *numbersrc = GST_NUMBERSRC (src);
  GstMapInfo info;

  GST_DEBUG_OBJECT (numbersrc, "fill");

  if (size < sizeof(i)) {
      GST_ERROR_OBJECT(numbersrc, "gst_numbersrc_fill: size too short");
      return GST_FLOW_ERROR;
  }

  if (!gst_buffer_map (buf, &info, GST_MAP_WRITE))
    return GST_FLOW_ERROR;

  guint8 *data = info.data;
  memcpy(data, &i, sizeof(i));
  i++;

  gst_buffer_unmap (buf, &info);
  gst_buffer_resize(buf, 0, sizeof(i));

  return GST_FLOW_OK;
}

gst_numbersrc_fill()が呼び出されるたびにインクリメントされる変数のメモリ内容を送るだけのものだ。

シンク側は送られてきたバッファをgst_util_dump_mem()でダンプする。

gstnumbersink.c
static GstFlowReturn
gst_numbersink_render (GstBaseSink * sink, GstBuffer * buffer)
{
  GstNumbersink *numbersink = GST_NUMBERSINK (sink);

  GST_DEBUG_OBJECT (numbersink, "render");

  GstMapInfo info;

  if (gst_buffer_map (buffer, &info, GST_MAP_READ)) {
      gst_util_dump_mem (info.data, info.size);
      gst_buffer_unmap (buffer, &info);
  }

  return GST_FLOW_OK;
}

実行してみる

$ GST_PLUGIN_PATH=. gst-launch-1.0 numbersrc ! numbersink
(snip)
00000000 (0x7ff294004490): 14 35 05 00                                      .5..                                                                                                                                   
00000000 (0x7ff294007090): 15 35 05 00                                      .5..                                                                                                                                   
00000000 (0x7ff294004490): 16 35 05 00                                      .5..                                                                                                                                   
00000000 (0x7ff294007090): 17 35 05 00                                      .5..                                                                                                                                   
00000000 (0x7ff294004490): 18 35 05 00                                      .5..                                                                                                                                   
00000000 (0x7ff294007090): 19 35 05 00                                      .5.. 

インクリメントされたメモリ内容がダンプされているのが見て取れる。

トランスフォームエレメントの作成

numbersrcを受けて2倍にして出力するtwicefilterを作ってみる

$ gst-element-maker twicefilter basetransform

ここではベースクラスとしてソース、シンクが1対1で対応するbasetransformを使用した。
例によって自動生成された実装はあまりよろしくないため、base_transform_class.transformへの登録以外はコメントアウトし、gst_twicefilter_transform()を以下のように実装した

gsttwicefilter.c
/* transform */
static GstFlowReturn
gst_twicefilter_transform (GstBaseTransform * trans, GstBuffer * inbuf,
    GstBuffer * outbuf)
{
  GstTwicefilter *twicefilter = GST_TWICEFILTER (trans);

  GST_DEBUG_OBJECT (twicefilter, "transform");

  GstMapInfo iinfo;
  if (!gst_buffer_map (inbuf, &iinfo ,GST_MAP_READ))
      return GST_FLOW_ERROR;

  guint32 i=0;
  memcpy(&i, iinfo.data, sizeof(i));
  gst_buffer_unmap(inbuf, &iinfo);

  i*=2;

  GstMapInfo oinfo;
  if (!gst_buffer_map(outbuf, &oinfo, GST_MAP_WRITE))
      return GST_FLOW_ERROR;

  memcpy(oinfo.data, &i, sizeof(i));

  gst_buffer_unmap(outbuf, &oinfo);
  gst_buffer_resize(outbuf, 0, sizeof(i));

  return GST_FLOW_OK;
}

かなりテキトウな実装だけどご勘弁。inbufから数字を取り出し2倍してoutbufへ格納しているだけ。

ビルドしたらgst-launch-1.0で動作を確認してみる

$ GST_PLUGIN_PATH=. gst-launch-1.0 numbersrc ! twicefilter ! numbersink
(snip)
00000000 (0x55870716e6f0): 90 a7 01 00                                      ....                         
00000000 (0x55870716e790): 92 a7 01 00                                      ....                         
00000000 (0x7fd3140060a0): 94 a7 01 00                                      ....                         
00000000 (0x7fd314006140): 96 a7 01 00                                      ....                         
00000000 (0x7fd3140061e0): 98 a7 01 00                                      ....                         
00000000 (0x7fd314006280): 9a a7 01 00                                      .... 

数字が2つ飛びになっており、たしかに2倍されていることがわかる。

20
18
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
18