8.3. ケイパビリティの用途

ケイパビリティ (短く caps と書かれることもあります) は、2 つのパッドの間を流れるデータの種類、または 1 つのパッド (テンプレート) がサポートするデータの種類を表します。このことを利用すれば、いろいろな目的でケイパビリティを便利に使用できます。

8.3.1. メタデータでのケイパビリティの使用

パッドは、ケイパビリティのセット (すなわち 1 つ以上のケイパビリティ) を自身にアタッチすることができます。ケイパビリティ (GstCaps) は、1 つ以上の GstStructure の配列として表現され、各 GstStructure は、フィールド名文字列 ("width" など) と型を持つ値 (G_TYPE_INTGST_TYPE_INT_RANGE など) とからなるフィールドの配列です。

ここで、パッドが持ち得る (possible) ケイパビリティ (すなわち、一般に gst-inspect を実行したときに表示されるパッドテンプレートのケイパビリティとして見えるもの) と、パッドで許可された (allowed) ケイパビリティ (これは、ピアパッドが持ち得るケイパビリティに応じて、パッドテンプレートのケイパビリティと同じである場合もあれば、そのサブセットである場合もあります)、さらに、ネゴシエーションの済んだ (negotiated) ケイパビリティ (ストリームまたはバッファの正確な形式を記述するケイパビリティで、構造体を 1 つだけ含み、範囲やリストのような可変ビットを持たないケイパビリティ、すなわち固定ケイパビリティ) の 3 つのケイパビリティの間には、はっきりとした区別があることに注意してください。

ケイパビリティのセットに含まれるプロパティの値を取得するには、1 つの構造体の個々のプロパティに対して問い合わせを実行します。ケイパビリティの構造体を 1 つ取得するには gst_caps_get_structure () を使用し、GstCaps に含まれる構造体の数を取得するには gst_caps_get_size () を使用します。

ケイパビリティに含まれている構造体が 1 つしかない場合、そのケイパビリティはシンプル (simple) ケイパビリティと呼ばれます。また、ケイパビリティに含まれている構造体が 1 つしかなく、(取り得る値の範囲やリストなどの) 可変フィールド型を持たない場合、そのケイパビリティは固定 (fixed) ケイパビリティと呼ばれます。これら以外に、ANY ケイパビリティ空の (empty) ケイパビリティという 2 つの特別な種類のケイパビリティがあります。

次に示すのは、固定サイズ動画のケイパビリティのセットから幅と高さを取り出す例です。


static void
read_video_props (GstCaps *caps)
{
  gint width, height;
  const GstStructure *str;

  g_return_if_fail (gst_caps_is_fixed (caps));

  str = gst_caps_get_structure (caps, 0);
  if (!gst_structure_get_int (str, "width", &width) ||
      !gst_structure_get_int (str, "height", &height)) {
    g_print ("No width/height available\n");
    return;
  }

  g_print ("The video size of this set of capabilities is %dx%d\n",
	   width, height);
}
      

8.3.2. フィルタリング用のケイパビリティの作成

ケイパビリティは、パッドのメディアの種類を記述する目的で主にプラグインの中で使われますが、アプリケーションプログラマも、プラグインを操作する場合、特にフィルタリングされたケイパビリティを使ってプラグインを操作する場合に、ケイパビリティについての基本的な理解が必要になります。フィルタリングされたケイパビリティ、すなわち固定化 (fixation) を使用すると、2 つのパッド間を流れることができるメディアの種類を、これらのパッドによってサポートされているメディアの種類のサブセットに限定することになります。実際にこれを実現するには、パイプラインで capsfilter エレメントを使います。また、そのために独自の GstCaps を作成する必要もあります。こうした操作を行うための最も簡単な方法は、次に示すように簡易関数 gst_caps_new_simple () を使うことです。


static gboolean
link_elements_with_filter (GstElement *element1, GstElement *element2)
{
  gboolean link_ok;
  GstCaps *caps;

  caps = gst_caps_new_simple ("video/x-raw-yuv",
  	      "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I', '4', '2', '0'),
	      "width", G_TYPE_INT, 384,
	      "height", G_TYPE_INT, 288,
	      "framerate", GST_TYPE_FRACTION, 25, 1,
	      NULL);

  link_ok = gst_element_link_filtered (element1, element2, caps);
  gst_caps_unref (caps);

  if (!link_ok) {
    g_warning ("Failed to link element1 and element2!");
  }

  return link_ok;
}
      
これで、2 つのエレメント間のデータフローは強制的に一定の動画形式、幅、高さ、およびフレームレートになります (関係するエレメント間でこのようなことが不可能な場合には、リンクが失敗します)。なお、 gst_element_link_filtered () を使うと、この関数によって自動的に capsfilter エレメントが作成され、ビンまたはパイプラインの中の互いに接続しようとしている 2 つのエレメントの間にこのエレメントが挿入されることに注意してください (この点は、これら 2 つのエレメントを切断しようとする場合に重要な意味を持ちます。なぜならこの場合、どちらのエレメントも capsfilter から切断する必要があるからです)。

場合によっては、もっと細かな指定をしたケイパビリティのセットを作成して、2 つのパッド間のリンクをフィルタリングしたいことがあります。そのような場合、gst_caps_new_simple ()では機能が不十分なので、次に示すようにメソッド gst_caps_new_full () を使います。


static gboolean
link_elements_with_filter (GstElement *element1, GstElement *element2)
{
  gboolean link_ok;
  GstCaps *caps;
                                                                                
  caps = gst_caps_new_full (
      gst_structure_new ("video/x-raw-yuv",
			 "width", G_TYPE_INT, 384,
			 "height", G_TYPE_INT, 288,
			 "framerate", GST_TYPE_FRACTION, 25, 1,
			 NULL),
      gst_structure_new ("video/x-raw-rgb",
			 "width", G_TYPE_INT, 384,
			 "height", G_TYPE_INT, 288,
			 "framerate", GST_TYPE_FRACTION, 25, 1,
			 NULL),
      NULL);

  link_ok = gst_element_link_filtered (element1, element2, caps);
  gst_caps_unref (caps);

  if (!link_ok) {
    g_warning ("Failed to link element1 and element2!");
  }

  return link_ok;
}
      

GstStructureGstCaps の完全な API については、API リファレンスを参照してください。