ククログ

株式会社クリアコード > ククログ > GStreamer 0.10からGStreamer 1.0へ移行するには

GStreamer 0.10からGStreamer 1.0へ移行するには

はじめに

C/C++に対応しているテスティングフレームワークの一つにCutterがあります。

以前、CutterのGStreamerサポートについて というCutterのテストをGStreamerの仕組みと組み合わせて実行する方法についての記事を書きました。

今回は、Cutterで当初サポートしていた GStreamer 0.10系に代わり、GStreamer 1.0への移行をどのように行ったかについて紹介します。Cutterの特徴について知りたい方はCutterの機能を参照してください。 Cutterそのものについては過去に何度かククログでもとりあげていますので、そちらも併せて参照するとよいでしょう。

GStreamer 0.10時代の終わり

CutterにGStreamerのサポートがはいったのは、2008年のことでした。まだ、GStreamerのバージョンが 0.10.20ぐらいのときのことです。 その後、GStreamerやGLibのバージョンアップにともない動作しなくなったことから、Cutter 1.2.3ではGStreamer 0.10向けのサポートを打ち切りました。

そしてGStreamer 1.0へ

Cutter 1.2.3のリリース以降、GStreamer 0.10からGStreamer 1.0へのAPIの変更に追従できないまま 1 になっていましたが、最近になってようやくその対応が入りました。

Cutterが提供しているエレメントは、あくまでテストをGStreamerの枠組みで行うためのもので、映像や音声を扱う一般的なエレメントとは異なります。 そのため、API等の変更の影響はそれほどありませんでした。とはいえ細かな修正をいくつか実施する必要がありました。

例えば、以下のような変更が必要でした。

  • 廃止された定数の修正

  • 廃止されたエレメントの修正

  • 廃止されたマクロの修正

  • 廃止されたvirtual methodの修正

  • マクロ定義の変更への追従

それぞれ、どんな変更をしたのかを説明します。

なお、移行にあたっては、GStreamer 0.10 to 1.0 porting guideをまず最初に参照しました。

廃止された定数の修正

Cutterでは、廃止された GST_FLOW_UNEXPECTED を 使っていたため、同等の GST_FLOW_EOS へと置き換えました。

diff --git a/gst-plugins/gst-cutter-test-runner.c b/gst-plugins/gst-cutter-test-runner.c
index 8b1ccbc..bd38dcd 100644
--- a/gst-plugins/gst-cutter-test-runner.c
+++ b/gst-plugins/gst-cutter-test-runner.c
@@ -284,7 +284,7 @@ create (GstBaseSrc *base_src, guint64 offset,
     GST_BUFFER_OFFSET_END(buf) = offset + send_size;
     *buffer = buf;
 
-    return !is_end_of_buffer ? GST_FLOW_OK : GST_FLOW_UNEXPECTED;
+    return !is_end_of_buffer ? GST_FLOW_OK : GST_FLOW_EOS;
 }
 
 static GstStateChangeReturn

廃止されたエレメントの修正

Cutterでは、廃止された GstElementDetails を使っていました。 そのため、メタデータを設定するためのAPIである、 gst_element_class_set_metadata に置き換える必要がありました。

diff --git a/gst-plugins/gst-cutter-server.c b/gst-plugins/gst-cutter-server.c
index 40f4e8d..1723d22 100644
--- a/gst-plugins/gst-cutter-server.c
+++ b/gst-plugins/gst-cutter-server.c
@@ -30,11 +30,6 @@
 GST_DEBUG_CATEGORY_STATIC(cutter_server_debug);
 #define GST_CAT_DEFAULT cutter_server_debug
 
-static const GstElementDetails cutter_server_details =
-    GST_ELEMENT_DETAILS("Cutter test server",
-                        "Cutter test server",
-                        "Cutter test server",
-                        "g新部 Hiroyuki Ikezoe  <poincare@ikezoe.net>");
 static GstStaticPadTemplate cutter_server_src_template_factory =
     GST_STATIC_PAD_TEMPLATE("src",
                             GST_PAD_SRC,
@@ -97,7 +92,11 @@ gst_cutter_server_base_init (gpointer klass)
     gst_element_class_add_pad_template(element_class,
         gst_static_pad_template_get(&cutter_server_sink_template_factory));
 
-    gst_element_class_set_details(element_class, &cutter_server_details);
+    gst_element_class_set_metadata(element_class,
+                                   "Cutter test server",
+                                   "Cutter test server",
+                                   "Cutter test server",
+                                   "g新部 Hiroyuki Ikezoe  <poincare@ikezoe.net>");
 }

廃止されたマクロの修正

Cutterでは、廃止された GST_BUFFER_XXX 系のマクロを使っていました。そのため、その部分について修正する必要がありました。

例えば、プログラムの文脈に応じて GstBuffer を扱う上でより適切と思われるAPIである gst_buffer_map を使う、gst_buffer_fill に置き換える、などです。

また、GST_BOILERPLATE が廃止されたため、G_DEFINE_TYPE に置き換える必要がありました。 gst_cutter_test_runner_init はその影響を受け、引数の定義を変更する必要がありました。

diff --git a/gst-plugins/gst-cutter-test-runner.c b/gst-plugins/gst-cutter-test-runner.c
index f00b0b6..edcc55a 100644
--- a/gst-plugins/gst-cutter-test-runner.c
+++ b/gst-plugins/gst-cutter-test-runner.c
@@ -49,7 +49,7 @@ struct _GstCutterTestRunnerPrivate
     GString *xml_string;
 };
 
-GST_BOILERPLATE(GstCutterTestRunner, gst_cutter_test_runner, GstBaseSrc, GST_TYPE_BASE_SRC);
+G_DEFINE_TYPE(GstCutterTestRunner, gst_cutter_test_runner, GST_TYPE_BASE_SRC);
 
 enum
 {
@@ -129,7 +129,7 @@ gst_cutter_test_runner_class_init (GstCutterTestRunnerClass * klass)
 }
 
 static void
-gst_cutter_test_runner_init (GstCutterTestRunner *cutter_test_runner, GstCutterTestRunnerClass * klass)
+gst_cutter_test_runner_init (GstCutterTestRunner *cutter_test_runner)
 {
     GstCutterTestRunnerPrivate *priv = GST_CUTTER_TEST_RUNNER_GET_PRIVATE(cutter_test_runner);
 

それだけでなく、 _base_init が呼ばれなくなるため、_class_init 内で同等の処理を行う必要がありました。

diff --git a/gst-plugins/gst-cutter-test-runner.c b/gst-plugins/gst-cutter-test-runner.c
index edcc55a..b3f4c99 100644
--- a/gst-plugins/gst-cutter-test-runner.c
+++ b/gst-plugins/gst-cutter-test-runner.c
@@ -80,21 +80,6 @@ static GstStateChangeReturn change_state (GstElement *element,
                                           GstStateChange transition);
 
 static void
-gst_cutter_test_runner_base_init (gpointer klass)
-{
-    GstElementClass *element_class = GST_ELEMENT_CLASS(klass);
-
-    gst_element_class_add_pad_template(element_class,
-        gst_static_pad_template_get(&cutter_test_runner_src_template_factory));
-
-    gst_element_class_set_metadata(element_class,
-                                   "Cutter test runner",
-                                   "Cutter test runner",
-                                   "Cutter test runner",
-                                   "g新部 Hiroyuki Ikezoe  <poincare@ikezoe.net>");
-}
-
-static void
 gst_cutter_test_runner_class_init (GstCutterTestRunnerClass * klass)
 {
     GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
@@ -126,6 +111,15 @@ gst_cutter_test_runner_class_init (GstCutterTestRunnerClass * klass)
     g_type_class_add_private(gobject_class, sizeof(GstCutterTestRunnerPrivate));
 
     GST_DEBUG_CATEGORY_INIT(cutter_test_runner_debug, "cutter-test", 0, "Cutter test elements");
+
+    gst_element_class_add_pad_template(element_class,
+        gst_static_pad_template_get(&cutter_test_runner_src_template_factory));
+
+    gst_element_class_set_metadata(element_class,
+                                   "Cutter test runner",
+                                   "Cutter test runner",
+                                   "Cutter test runner",
+                                   "g新部 Hiroyuki Ikezoe  <poincare@ikezoe.net>");
 }

廃止されたvirtual methodの修正

Cutterでは GstBaseSrc を使っていたことから、check_get_range の廃止に対応する必要がありました。

そのため、元々どういう挙動が期待されていたのかを確認したうえで、同等の振舞いとなるように修正する必要がありました。

元々の振舞いについては、過去のドキュメントを参照しました。

  /* check whether the source would support pull-based operation if
   * it were to be opened now. This vfunc is optional, but should be
   * implemented if possible to avoid unnecessary start/stop cycles.
   * The default implementation will open and close the resource to
   * find out whether get_range is supported and that is usually
   * undesirable. */

元のコードでは、 check_get_range で明示的に FALSE を返しており、上記の説明にあるpullモードはサポートしていません。 GstBaseSrcリファレンスマニュアルを参照すると、pullモードがサポートされる条件が明記されており、is_seekableFALSE を返せばpull モードをサポートしない(従来と挙動が同じになる)ことがわかりました。 たまたま、元のコードでも is_seekableFALSE を返すようになっていたので、最終的には、check_get_rangeがらみのコードを削除するだけでよいことになりました。

diff --git a/gst-plugins/gst-cutter-test-runner.c b/gst-plugins/gst-cutter-test-runner.c
index 9b05c5b..0cedf9d 100644
--- a/gst-plugins/gst-cutter-test-runner.c
+++ b/gst-plugins/gst-cutter-test-runner.c
@@ -75,7 +75,6 @@ static GstFlowReturn create          (GstBaseSrc *basr_src,
                                       guint64     offset,
                                       guint       length,
                                       GstBuffer **buffer);
-static gboolean      check_get_range (GstBaseSrc *base_src);
 
 static GstStateChangeReturn change_state (GstElement *element,
                                           GstStateChange transition);
@@ -100,7 +99,6 @@ gst_cutter_test_runner_class_init (GstCutterTestRunnerClass * klass)
     base_src_class->stop            = stop;
     base_src_class->is_seekable     = is_seekable;
     base_src_class->create          = create;
-    base_src_class->check_get_range = check_get_range;
 
     spec = g_param_spec_string("test-directory",
                                "Test directory",
@@ -248,12 +246,6 @@ is_seekable (GstBaseSrc *base_src)
     return FALSE;
 }
 
-static gboolean
-check_get_range (GstBaseSrc *base_src)
-{
-    return FALSE;
-}
-
 static GstFlowReturn

マクロ定義の変更への追従

従来問題なかったものの、マクロ定義の変更に伴い警告がでるようになってしまった箇所への対応も行いました。 具体的には、プラグインを定義する GST_PLUGIN_DEFINE の引数の変更です。

これまでは、第三引数は文字列を渡すのが正しいやりかたでした。 しかし、文字列化もマクロ展開時に行われるようになったので、それに合わせるようにしました。

diff --git a/gst-plugins/gst-cutter-test.c b/gst-plugins/gst-cutter-test.c
index b373b76..c44ef66 100644
--- a/gst-plugins/gst-cutter-test.c
+++ b/gst-plugins/gst-cutter-test.c
@@ -42,7 +42,7 @@ plugin_init (GstPlugin * plugin)
 }
 
 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR, 
-                   "cutter-test", "Cutter element",
+                   cutter-test, "Cutter element",
                    plugin_init, VERSION, "LGPL",
                    "GstCutterTest", "http://cutter.sf.net");

このようにして、CutterはGstreamer 0.10からGStreamer 1.0系への対応を行いました。

まとめ

今回はCutterというテスティングフレームワークのGStreamer 1.0対応について紹介しました。GStreamer 1.0対応が入ったバージョンをCutter 1.2.5として今月リリースする予定です。

  1. GStreamer 1.0対応は優先度が低かった。