第 11章位置のトラッキングとシーク

これまでにパイプラインの作成方法とパイプラインの実行方法については説明しました。これらの方法に加えて、メディアの進捗状況をユーザーにフィードバックする方法は、ほとんどのアプリケーション開発者が興味を持つテーマでしょう。たとえば、メディアプレーヤーでは曲の進捗状況を示すスライダを表示したり、ストリームの長さを示すラベルを表示したりできると便利です。変換を行うアプリケーションでは、作業が何 % まで完了したかをプログレスバーで表示できると使い勝手もよくなります。GStreamer は、問い合わせ (querying) と呼ばれるコンセプトを使って、これらのことをサポートする仕組みをはじめから備えています。シークはこれに非常に近い処理なので、ここではシークについても取り上げます。シークは、イベントというコンセプトを使って実現されています。

11.1. 問い合わせ: ストリームの位置または長さの取得

問い合わせは、進捗状況のトラッキングに関連した特定のストリームプロパティの要求として定義されています。これには、ストリームの長さの取得 (長さがわかる場合)や、現在位置の取得が含まれます。こうしたストリームプロパティは、時間、音声サンプル、動画フレーム、またはバイトといった、さまざまな形式で取得することができます。そのためによく使われる関数が gst_element_query () です。なお、いくつか簡易ラッパー (gst_element_query_position () および gst_element_query_duration () など) も用意されています。通常、プログラマは直接パイプラインに対して問い合わせを行うことができ、問い合わせの具体的な対象となるエレメントなど、内部の詳細については、パイプラインがプログラマに代わって処理を行います。

内部的には、問い合わせはシンクに送られ、問い合わせを処理できるエレメントに行きあたるまで、逆方向に "ディスパッチ" されます。処理結果は、関数の呼び出し元に返されます。通常、これに該当するエレメントはデマルチプレクサですが、(ウェブカムからの) ライブソースの場合は、ソース自身になります。


#include <gst/gst.h>




static gboolean
cb_print_position (GstElement *pipeline)
{
  GstFormat fmt = GST_FORMAT_TIME;
  gint64 pos, len;

  if (gst_element_query_position (pipeline, &fmt, &pos)
    && gst_element_query_duration (pipeline, &fmt, &len)) {
    g_print ("Time: %" GST_TIME_FORMAT " / %" GST_TIME_FORMAT "\r",
	     GST_TIME_ARGS (pos), GST_TIME_ARGS (len));
  }

  /* call me again */
  return TRUE;
}

gint
main (gint   argc,
      gchar *argv[])
{
  GstElement *pipeline;

[..]

  /* run pipeline */
  g_timeout_add (200, (GSourceFunc) cb_print_position, pipeline);
  g_main_loop_run (loop);

[..]

}