第 8章パッドとケイパビリティ

すでに「エレメント」の章でみたように、パッドはエレメントが持つ外の世界に対するインタフェースです。データは、あるエレメントのソースパッドから別のエレメントのシンクパッドへと流れます。エレメントが処理することができる特定のメディアの種類は、パッドのケイパビリティによって公開されます。ケイパビリティについては、この章のあとの方で詳しく取り上げます (項8.2 を参照)。

8.1. パッド

パッドの種類は、方向 (direction) と利用可能性 (availability) の 2 つのプロパティによって定義されます。すでにみたように、GStreamer では、ソースパッドとシンクパッドの 2 つの方向が定義されています。この用語は、エレメント内部からみたときの呼び名です。すなわち、エレメントはシンクパッドでデータを受け取り、ソースパッドでデータを生成します。このマニュアルで図示する場合には、シンクパッドはエレメントの左に、ソースパッドはエレメントの右側に表示します。この場合、データは左から右へと流れます。 [1]

パッドの方向は非常にシンプルですが、パッドの利用可能性については事情が異なります。パッドは 3 つの利用可能性のいずれかを持つことができます。3 つの利用可能性とはすなわち、常時 (always)、一時的 (sometimes)、およびオンリクエスト (on request) です。これら 3 つの種類の意味は、名前が示すとおりです。常時 (always) パッドは常に存在し、一時的 (sometimes) パッドは状況に応じてのみ存在し (かつランダムに消失することが可能で)、オンリクエスト (on request) パッドはアプリケーションから明示的に要求された場合にのみ出現します。

8.1.1. 動的 (または一時的) パッド

エレメントによっては、エレメントが作成されたときに、そのエレメントが持つことのできるすべてのパッドを必ずしも持っていないことがあります。たとえば、Ogg デマルチプレクサエレメントではこのようなことが起こります。Ogg デマルチプレクサエレメントは、Ogg ストリームを読み取り、Ogg ストリーム内でエレメンタリストリーム (vorbis、theora) を認識すると、それぞれのエレメンタリストリームについて動的パッドを作成します。そして作成時と同様に、ストリームが終了するとパッドを削除します。このような処理方法は、たとえばデマルチプレクサエレメントでは非常に有益です。

gst-inspect oggdemux を実行すると、エレメントには 1 つしかパッドがないことがわかります。具体的には、'sink' と呼ばれるシンクパッドがそれです。その他のパッドは "休止状態" (dormant) です。これはパッドテンプレートを見るとわかります。"Exists: Sometimes" プロパティが存在しているからです[訳注:正しくは「"Availability: Sometimes" プロパティ」と思われます]。パッドは、再生する Ogg ファイルの種類に応じて作成されます。あとで示しますが、これは動的パイプラインを作成するときに非常に重要です。エレメントが"一時的"パッドテンプレートのいずれかから新しいパッドを作成したときに通知を受け取れるよう、エレメントにシグナルハンドラをアタッチすることができます。次に示すコードは、これを実際に実現する例です。


#include <gst/gst.h>

static void
cb_new_pad (GstElement *element,
	    GstPad     *pad,
	    gpointer    data)
{
  gchar *name;

  name = gst_pad_get_name (pad);
  g_print ("A new pad %s was created\n", name);
  g_free (name);

  /* here, you would setup a new pad link for the newly created pad */
[..]

}

int 
main (int   argc,
      char *argv[]) 
{
  GstElement *pipeline, *source, *demux;
  GMainLoop *loop;

  /* init */
  gst_init (&argc, &argv);

  /* create elements */
  pipeline = gst_pipeline_new ("my_pipeline");
  source = gst_element_factory_make ("filesrc", "source");
  g_object_set (source, "location", argv[1], NULL);
  demux = gst_element_factory_make ("oggdemux", "demuxer");

  /* you would normally check that the elements were created properly */

  /* put together a pipeline */
  gst_bin_add_many (GST_BIN (pipeline), source, demux, NULL);
  gst_element_link_pads (source, "src", demux, "sink");

  /* listen for newly created pads */
  g_signal_connect (demux, "pad-added", G_CALLBACK (cb_new_pad), NULL);

  /* start the pipeline */
  gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
  loop = g_main_loop_new (NULL, FALSE);
  g_main_loop_run (loop);

[..]

}
      

8.1.2. リクエストパッド

エレメントはリクエスト (request) パッドを持つこともできます。リクエストパッドは自動的には作成されず、オンデマンドでのみ作成されます。これは、マルチプレクサ、アグリゲータ、およびティー (tee) エレメントでは非常に便利です。アグリゲータとは、複数の入力ストリームの内容を 1 つの出力ストリームにまとめるエレメントのことです。ティーエレメントはその逆で、1 つの入力ストリームを複数の出力パッドのそれぞれにコピーするエレメントのことで、これらの出力パッドは要求に応じて (on request) 作成されます。この場合、アプリケーションでは、ストリームのコピーがもう 1 つ必要になったときに、ティーエレメントから新しい出力パッドを要求するだけで済みます。

次のコードは、"ティー" (tee) エレメントから新しい出力パッドを要求する方法を示しています。


static void
some_function (GstElement *tee)
{
  GstPad * pad;
  gchar *name;

  pad = gst_element_get_request_pad (tee, "src%d");
  name = gst_pad_get_name (pad);
  g_print ("A new pad %s was created\n", name);
  g_free (name);

  /* here, you would link the pad */
[..]

  /* and, after doing that, free our reference */
  gst_object_unref (GST_OBJECT (pad));
}
      

gst_element_get_request_pad () メソッドは、パッドテンプレートの名前をベースにエレメントからパッドを取得するときに使用します。ほかのパッドテンプレートと互換性のあるパッドを要求することもできます。これは、あるエレメントをマルチプレクサエレメントにリンクして、互換性のあるパッドを要求する必要がある場合に非常に便利です。互換性のあるパッドを要求するには、次の例に示すように、gst_element_get_compatible_pad () メソッドを使用します。この例では、任意の入力を受け取る Ogg マルチプレクサから、互換性のあるパッドを要求します。


static void
link_to_multiplexer (GstPad     *tolink_pad,
		     GstElement *mux)
{
  GstPad *pad;
  gchar *srcname, *sinkname;

  srcname = gst_pad_get_name (tolink_pad);
  pad = gst_element_get_compatible_pad (mux, tolink_pad);
  gst_pad_link (tolinkpad, pad);
  sinkname = gst_pad_get_name (pad);
  gst_object_unref (GST_OBJECT (pad));

  g_print ("A new pad %s was created and linked to %s\n", srcname, sinkname);
  g_free (sinkname);
  g_free (srcname);
}
      

注意

[1]

実際には、ソースパッドから左のエレメントのシンクパッドへと (図の左へ向かって) データが流れるという形で図を表現することも可能です。ただし、その場合もデータはあるエレメントのソースパッドから、別のエレメントのシンクパッドへと流れることに変わりはありません。