{"id":931,"date":"2023-02-15T09:08:29","date_gmt":"2023-02-15T01:08:29","guid":{"rendered":"https:\/\/swordofmorning.com\/?p=931"},"modified":"2025-10-09T13:55:19","modified_gmt":"2025-10-09T05:55:19","slug":"gstreamer-02","status":"publish","type":"post","link":"https:\/\/swordofmorning.com\/index.php\/2023\/02\/15\/gstreamer-02\/","title":{"rendered":"GStreamer 02 Manual Hello World"},"content":{"rendered":"<p><div class=\"has-toc have-toc\"><\/div><\/p>\n<h2>\u4e00\u3001\u76ee\u6807<\/h2>\n<p>&emsp;&emsp;\u5728\u4e0a\u4e00\u7bc7\u6587\u7ae0\u4e2d\uff0c\u6211\u4eec\u4ecb\u7ecd\u4e86\u5982\u4f55\u4f7f\u7528<code>gst_parse_launch<\/code>\u5feb\u901f\u521b\u5efa\u4e00\u4e2apipeline\u3002\u672c\u7ae0\u4e2d\u6211\u4eec\u5c06\u5b66\u4e60\u64ad\u653e\u4e00\u4e2atest video\u7684\u6d41\u7a0b\uff1a<\/p>\n<ol>\n<li>\u4ec0\u4e48\u662fGStreamer Element\uff0c\u4ee5\u53ca\u5982\u4f55\u521b\u5efa\u3002<\/li>\n<li>\u5982\u4f55\u8fde\u63a5\u8fd9\u4e9b\u5143\u7d20\u3002<\/li>\n<li>\u5982\u4f55\u81ea\u5b9a\u4e49\u5143\u7d20\u7684\u5c5e\u6027\u3002<\/li>\n<li>\u5982\u4f55\u76d1\u89c6\u603b\u7ebf\u7684\u9519\u8bef\u60c5\u51b5\uff0c\u4ee5\u53ca\u5982\u4f55\u4eceGStreamer message\u4e2d\u63d0\u53d6\u51fa\u5176\u4fe1\u606f\u3002<\/li>\n<\/ol>\n<h2>\u4e8c\u3001\u4ee3\u7801<\/h2>\n<pre><code class=\"language-c\">int BT02_ManualHelloWorld(int argc, char** argv)\n{\n    GstElement *pipeline, *source, *sink;\n    GstBus *bus;\n    GstMessage *msg;\n    GstStateChangeReturn ret;\n    int retval = 0;\n\n    \/* Initialize GStreamer *\/\n    gst_init (&amp;argc, &amp;argv);\n\n    \/* Create the elements *\/\n    source = gst_element_factory_make(&quot;videotestsrc&quot;, &quot;source&quot;);\n    sink = gst_element_factory_make(&quot;autovideosink&quot;, &quot;sink&quot;);\n\n    \/* Create the empty pipeline *\/\n    pipeline = gst_pipeline_new(&quot;test-pipeline&quot;);\n\n    if (!pipeline || !source || !sink)\n    {\n        g_printerr(&quot;No Element Created.\\n&quot;);\n        retval = -1;\n        goto out_return;\n    }\n\n    \/* Build the pipeline *\/\n    gst_bin_add_many(GST_BIN(pipeline), source, sink, NULL);\n    if (gst_element_link(source, sink) != TRUE)\n    {\n        g_printerr(&quot;No Element Link.\\n&quot;);\n        retval = -2;\n        goto out_unref;\n    }\n\n    \/* Modify the source&#039;s properties *\/\n    g_object_set(source, &quot;pattern&quot;, 0 , NULL);\n\n    \/* Start playing *\/\n    ret = gst_element_set_state(pipeline, GST_STATE_PLAYING);\n    if (ret == GST_STATE_CHANGE_FAILURE) \n    {\n        g_printerr(&quot;Unable to set the pipeline to the playing state.\\n&quot;);\n        retval = -3;\n        goto out_unref;\n    }\n\n    \/* Wait until error or EOS *\/\n    bus = gst_element_get_bus(pipeline);\n    msg = gst_bus_timed_pop_filtered(\n        bus, GST_CLOCK_TIME_NONE,\n        GST_MESSAGE_ERROR | GST_MESSAGE_EOS\n    );\n\n    \/* Parse message *\/\n    if (msg != NULL)\n    {\n        GError *err;\n        gchar *debug_info;\n\n        switch (GST_MESSAGE_TYPE(msg))\n        {\n            case GST_MESSAGE_ERROR:\n                gst_message_parse_error(msg, &amp;err, &amp;debug_info);\n\n                g_printerr(&quot;Error received from element %s: %s\\n&quot;,\n                    GST_OBJECT_NAME (msg-&gt;src), err-&gt;message\n                );\n                g_printerr(&quot;Debugging information: %s\\n&quot;,\n                    debug_info ? debug_info : &quot;none&quot;\n                );\n\n                g_clear_error(&amp;err);\n                g_free(debug_info);\n                break;\n            case GST_MESSAGE_EOS:\n                g_print(&quot;End-Of-Stream reached.\\n&quot;);\n                break;\n            default:\n                g_printerr(&quot;Unexpected message received.\\n&quot;);\n                break;\n        }\n\n        gst_object_unref(msg);\n    }\n\n    gst_object_unref(bus);\n    gst_element_set_state(pipeline, GST_STATE_NULL);\nout_unref:\n    gst_object_unref(pipeline);\nout_return:\n    return retval;\n}<\/code><\/pre>\n<h2>\u4e09\u3001\u89e3\u91ca<\/h2>\n<blockquote>\n<p>source -&gt; filter -&gt; sink<\/p>\n<\/blockquote>\n<p>&emsp;&emsp;Elements\u662fGStreamer\u6700\u57fa\u672c\u7684\u6784\u9020\u5757\u3002\u5b83\u4eec\u5904\u7406\u4ecesource\uff08data producers\uff09\u85c9\u7531filter\u5230sink\uff08data consumers\uff09\u7684\u6570\u636e\u6d41\u3002<\/p>\n<h3>3.1 \u521b\u5efa\u5143\u7d20<\/h3>\n<pre><code class=\"language-c\">source = gst_element_factory_make(&quot;videotestsrc&quot;, &quot;source&quot;);\nsink = gst_element_factory_make(&quot;autovideosink&quot;, &quot;sink&quot;);<\/code><\/pre>\n<p>&emsp;&emsp;\u901a\u8fc7\u4e0a\u8ff0\u4ee3\u7801\u6211\u4eec\u5df2\u77e5\uff0c\u5143\u7d20\u53ef\u88ab<code>gst_element_factory_make()<\/code>\u521b\u5efa\u3002\u5176\u7b2c\u4e00\u4e2a\u53c2\u6570\uff0c\u6307\u521b\u5efa\u7684\u5143\u7d20\u7684\u7c7b\u578b\uff08\u53c2\u8003<a href = \"https:\/\/gstreamer.freedesktop.org\/documentation\/tutorials\/basic\/handy-elements.html?gi-language=c\">BT14<\/a>\uff0c\u548c<a href = \"https:\/\/gstreamer.freedesktop.org\/documentation\/tutorials\/basic\/gstreamer-tools.html?gi-language=c\">BT10<\/a>\uff09\u3002\u7b2c\u4e8c\u4e2a\u53c2\u6570\u662f\u8be5Element\u5b9e\u4f8b\u5316\u7684\u540d\u5b57\u3002\u5982\u679c\u6ca1\u6709\u4fdd\u7559\u5bf9\u5e94\u5143\u7d20\u7684\u6307\u9488\uff0c\u90a3\u4e48\u4f7f\u7528\u547d\u540d\u5c06\u6709\u52a9\u4e8edebug\u4e00\u7c7b\u7684\u7ba1\u7406\u3002\u5982\u679c\u4f20\u9012NULL\u4f5c\u4e3a\u53c2\u6570\uff0c\u5219GStreamer\u5c06\u81ea\u52a8\u4e3a\u5176\u547d\u540d\u3002<\/p>\n<p>&emsp;&emsp;\u5728\u672c\u4f8b\u4e2d\uff0c\u6211\u4eec\u521b\u5efa\u4e86\u4e24\u4e2a\u5143\u7d20\uff0c<code>videotestsrc<\/code>\u548c<code>autovideosink<\/code>\u3002\u8fd9\u91cc\u6ca1\u6709filter\u5143\u7d20\uff0c\u56e0\u6b64\u6574\u4e2a\u7ba1\u7ebf\u770b\u8d77\u6765\u662f\u8fd9\u6837\u7684\uff1a<\/p>\n<blockquote>\n<p>source(videotestsrc) -&gt; sink(autovideosink)<\/p>\n<\/blockquote>\n<ul>\n<li>videotestsrc\u521b\u5efa\u4e00\u4e2a\u6d4b\u8bd5\u89c6\u9891\u3002\u8be5\u89c6\u9891\u53ea\u5728\u6d4b\u8bd5\u4e2d\u4f7f\u7528\uff0c\u5b9e\u9645\u9879\u76ee\u4e2d\u5e76\u4e0d\u4f1a\u7528\u5230\u3002<\/li>\n<li>autovideosink\u5728\u7a97\u53e3\u4e0a\u663e\u793a\u5b83\u6240\u63a5\u6536\u5230\u7684\u56fe\u50cf\u3002\u8be5\u547d\u4ee4\u81ea\u52a8\u9009\u62e9\u9002\u5408\u7684sink\u5b9e\u4f8b\u3002<\/li>\n<\/ul>\n<h3>3.2 \u521b\u5efa\u7ba1\u7ebf<\/h3>\n<p>&emsp;&emsp;\u6240\u6709\u7684\u5143\u7d20\u9700\u8981\u5728\u7ba1\u7ebf\u4e2d\u624d\u80fd\u88ab\u4f7f\u7528\uff0c\u7ba1\u7ebf\u8d1f\u8d23\u4f20\u9012\u5143\u7d20\u76f4\u63a5\u7684\u4fe1\u606f\u548c\u65f6\u949f\u3002\u6211\u4eec\u4f7f\u7528<code>pipeline = gst_pipeline_new()<\/code>\u6765\u521b\u5efa\u7ba1\u7ebf\u3002<\/p>\n<p>&emsp;&emsp;\u7ba1\u7ebf\u662f\u4e00\u79cd\u7279\u6b8a\u7c7b\u578b\u7684\u5143\u7d20\uff0c\u5b83\u662f\u4e00\u4e2a\u5b58\u653e\u5176\u4ed6\u5143\u7d20\u7684\u5bb9\u5668\u3002\u5728\u6211\u4eec\u521b\u5efa\u4e00\u6761\u5b8c\u6574\u7684\u7ba1\u7ebf\u65f6\uff0c\u6211\u4eec\u9700\u8981\u5148\u5411\u5176\u4e2d\u6dfb\u52a0\u5143\u7d20\uff08gst_bin_add\uff09\uff0c\u7136\u540e\u518d\u8fde\u63a5\u5b83\u4eec\uff08gst_element_link\uff09\uff0c<em>\u4f46\u662f\u9700\u8981\u6ce8\u610f\uff0c\u5728\u8fde\u63a5\u65f6\u6709\u4e9b\u5143\u7d20\u7684pad\u5e76\u4e0d\u4f1a\u81ea\u52a8\u5b9e\u73b0<\/em>\u3002\u5728\u4e0a\u9762\u7684\u4f8b\u5b50\u4e2d\uff1a<\/p>\n<pre><code class=\"language-c\">gst_bin_add_many(GST_BIN(pipeline), source, sink, NULL);\n\ngst_element_link(source, sink) != TRUE<\/code><\/pre>\n<p>\u540c\u65f6\uff0c\u8fde\u63a5\u9700\u8981\u6ce8\u610f\u5176\u987a\u5e8f\u3002<\/p>\n<h3>3.3 \u7279\u6027<\/h3>\n<p>&emsp;&emsp;GStreamer\u5143\u7d20\u90fd\u662f\u7279\u6b8a\u7684GObject\uff0c\u5b83\u662f\u63d0\u4f9bproperty facilities\u7684\u5b9e\u4f53\u3002\u5927\u591a\u6570\u7684\u5143\u7d20\u90fd\u6709\u53ef\u81ea\u5b9a\u4e49\u7684\u5c5e\u6027\uff1a\u53ef\u4ee5\u4fee\u6539\u4ee5\u66f4\u6539\u5143\u7d20\u7684\u884c\u4e3a\uff08\u53ef\u5199\u5c5e\u6027\uff09\u6216\u67e5\u8be2\u4ee5\u4e86\u89e3\u5143\u7d20\u7684\u5185\u90e8\u72b6\u6001\uff08\u53ef\u8bfb\u5c5e\u6027\uff09\u7684\u547d\u540d\u5c5e\u6027\u3002<\/p>\n<p>&emsp;&emsp;\u5c5e\u6027\u53ef\u4ee5\u901a\u8fc7<code>g_object_get()<\/code>\u83b7\u53d6\uff1b\u901a\u8fc7<code>g_object_set()<\/code>\u8bbe\u7f6e\u3002<code>g_object_set()<\/code>\u63a5\u53d7\u4ee5NULL\u7ed3\u5c3e\u7684\u5c5e\u6027\u540d\u3001\u5c5e\u6027\u503c\u5bf9\u5217\u8868\uff0c\u56e0\u6b64\u53ef\u4ee5\u4e00\u6b21\u66f4\u6539\u591a\u4e2a\u5c5e\u6027\u3002<\/p>\n<pre><code class=\"language-c\">g_object_set(source, &quot;pattern&quot;, 0 , NULL);<\/code><\/pre>\n<p>\u8fd9\u91cc\u901a\u8fc7\u8bbe\u7f6e<code>videotestsrc<\/code>\u7684<code>pattern<\/code>\u5c5e\u6027\uff0c\u6765\u6539\u53d8\u6d4b\u8bd5\u89c6\u9891\u7684\u8f93\u51fa\u3002<\/p>\n<h3>3.4 \u9519\u8bef\u68c0\u67e5<\/h3>\n<p>&emsp;&emsp;\u6b64\u65f6\u6211\u4eec\u5df2\u7ecf\u5b8c\u6210\u4e86\u6574\u4e2a\u7ba1\u7ebf\u7684\u5efa\u6784\uff0c\u4e0b\u9762\u662f\u4e00\u4e9b\u9519\u8bef\u68c0\u67e5\u3002<\/p>\n<pre><code class=\"language-c\">ret = gst_element_set_state(pipeline, GST_STATE_PLAYING);\nif (ret == GST_STATE_CHANGE_FAILURE) \n{\n    g_printerr(&quot;Unable to set the pipeline to the playing state.\\n&quot;);\n    retval = -3;\n    goto out_unref;\n}<\/code><\/pre>\n<p>&emsp;&emsp;\u5728\u4e0a\u4e00\u8282\u6559\u7a0b\u4e2d\uff0c\u6211\u4eec\u540c\u6837\u8bd5\u4e86\u4e86<code>gst_element_set_state<\/code>\u3002\u4f46\u662f\u8fd9\u6b21\u6211\u4eec\u9700\u8981\u68c0\u67e5\u5176\u8fd4\u56de\u503c\uff0c\u4ee5\u786e\u5b9a\u8bed\u53e5\u662f\u5426\u6b63\u5e38\u8fd0\u884c\u3002\u5173\u4e8e\u201c\u66f4\u6539\u72b6\u6001\u201d\u7684\u66f4\u591a\u5185\u5bb9\u5c06\u5728\u4e0b\u4e00\u7bc7\u6587\u7ae0\u4e2d\u8ba8\u8bba\u3002<\/p>\n<pre><code class=\"language-c\">\/* Wait until error or EOS *\/\nbus = gst_element_get_bus(pipeline);\nmsg = gst_bus_timed_pop_filtered(\n    bus, GST_CLOCK_TIME_NONE,\n    GST_MESSAGE_ERROR | GST_MESSAGE_EOS\n);\n\n\/* Parse message *\/\nif (msg != NULL)\n{\n    GError *err;\n    gchar *debug_info;\n\n    switch (GST_MESSAGE_TYPE(msg))\n    {\n        case GST_MESSAGE_ERROR:\n            gst_message_parse_error(msg, &amp;err, &amp;debug_info);\n\n            g_printerr(&quot;Error received from element %s: %s\\n&quot;,\n                GST_OBJECT_NAME (msg-&gt;src), err-&gt;message\n            );\n            g_printerr(&quot;Debugging information: %s\\n&quot;,\n                debug_info ? debug_info : &quot;none&quot;\n            );\n\n            g_clear_error(&amp;err);\n            g_free(debug_info);\n            break;\n        case GST_MESSAGE_EOS:\n            g_print(&quot;End-Of-Stream reached.\\n&quot;);\n            break;\n        default:\n            g_printerr(&quot;Unexpected message received.\\n&quot;);\n            break;\n    }\n\n    gst_object_unref(msg);\n}<\/code><\/pre>\n<p>&emsp;&emsp;<code>gst_bus_timed_pop_filtered<\/code>\u7b49\u5f85\u6267\u884c\u7ed3\u675f\u5e76\u8fd4\u56de\u6211\u4eec\u4e4b\u524d\u5ffd\u7565\u7684GstMessage\u3002\u6211\u4eec\u8981\u6c42<code>gst_bus_timed_pop_filtered<\/code>\u5728\u9047\u5230\u9519\u8bef\u6216\u8005\u5230\u8fbeEOS\uff08End of Stream\uff09\u65f6\u8fd4\u56de\u4e00\u6761GstMessage\uff0c\u56e0\u6b64\u6211\u4eec\u68c0\u67e5\u8fd9\u4e2a\u8fd4\u56de\u503c\u662f<strong>\u9519\u8bef<\/strong>\u8fd8\u662f<strong>EOS<\/strong>\u3002<\/p>\n<p>&emsp;&emsp;GstMessage\u662f\u4e00\u79cd\u975e\u5e38\u901a\u7528\u7684\u7ed3\u6784\uff0c\u5b83\u51e0\u4e4e\u53ef\u4ee5\u4f20\u9012\u6240\u6709\u7c7b\u578b\u7684\u6d88\u606f\u3002\u5e76\u4e14GStreamer\u4e3a\u5176\u63d0\u4f9b\u4e86\u4e00\u7cfb\u5217\u89e3\u6790\u51fd\u6570\u3002<\/p>\n<ol>\n<li>\u6211\u4eec\u9996\u5148\u53ef\u4ee5\u901a\u8fc7<code>GST_MESSAGE_TYPE()<\/code>\u6765\u89e3\u6790\u6d88\u606f\u7684\u7c7b\u578b\u3002<\/li>\n<li>\u5982\u679c\u9047\u5230\u9519\u8bef\uff0c\u5219\u53ef\u4ee5\u4f7f\u7528<code>gst_message_parse_error<\/code>\u63d0\u53d6\u6d88\u606f\u5230<code>GError<\/code>\u4e2d\u3002<\/li>\n<\/ol>\n<h3>3.5 Gst\u603b\u7ebf<\/h3>\n<p>&emsp;&emsp;\u5728\u8fd9\u4e00\u70b9\u4e0a\uff0c\u503c\u5f97\u66f4\u6b63\u5f0f\u5730\u4ecb\u7ecd\u4e00\u4e0bGStreamer\u603b\u7ebf\u3002\u5b83\u662f\u8d1f\u8d23\u5c06\u5143\u7d20\u751f\u6210\u7684GstMessages\u6309\u987a\u5e8f\u4ea4\u4ed8\u7ed9\u5e94\u7528\u7a0b\u5e8f\u5e76\u4ea4\u4ed8\u7ed9\u5e94\u7528\u7a0b\u5e8f\u7ebf\u7a0b\u7684\u5bf9\u8c61\u3002\u6700\u540e\u4e00\u70b9\u5f88\u91cd\u8981\uff0c\u56e0\u4e3a\u5b9e\u9645\u7684\u5a92\u4f53\u6d41\u662f\u5728\u5e94\u7528\u7a0b\u5e8f\u4e4b\u5916\u7684\u53e6\u4e00\u4e2a\u7ebf\u7a0b\u4e2d\u5b8c\u6210\u7684\u3002<\/p>\n<p>&emsp;&emsp;\u53ef\u4ee5\u4f7f\u7528gst_bus_timed_pop_filtered()\u53ca\u5176\u540c\u7ea7\u4ece\u603b\u7ebf\u540c\u6b65\u63d0\u53d6\u6d88\u606f\uff0c\u6216\u8005\u4f7f\u7528\u4fe1\u53f7\u5f02\u6b65\u63d0\u53d6\u6d88\u606f\uff08\u5728\u4e0b\u4e00\u6559\u7a0b\u4e2d\u663e\u793a\uff09\u3002 \u60a8\u7684\u5e94\u7528\u7a0b\u5e8f\u5e94\u59cb\u7ec8\u5173\u6ce8\u603b\u7ebf\uff0c\u4ee5\u4fbf\u6536\u5230\u6709\u5173\u9519\u8bef\u548c\u5176\u4ed6\u64ad\u653e\u76f8\u5173\u95ee\u9898\u7684\u901a\u77e5\u3002<\/p>\n<pre><code class=\"language-c\">    gst_object_unref(bus);\n    gst_element_set_state(pipeline, GST_STATE_NULL);\nout_unref:\n    gst_object_unref(pipeline);\nout_return:\n    return retval;<\/code><\/pre>\n<p>\u4f59\u4e0b\u7684\u8fd9\u90e8\u5206\u4ee3\u7801\u5219\u662f\u6e05\u7406\u3002<\/p>\n<h2>\u56db\u3001\u603b\u7ed3<\/h2>\n<p>&emsp;&emsp;\u672c\u7bc7\u6587\u7ae0\u63cf\u8ff0\u4e86\uff1a<\/p>\n<ol>\n<li>\u5982\u4f55\u4f7f\u7528<code>gst_element_factory_make<\/code>\u6765\u521b\u5efa\u5143\u7d20\u3002<\/li>\n<li>\u5982\u4f55\u4f7f\u7528<code>gst_pipeline_new<\/code>\u6765\u521b\u5efa\u7ba1\u7ebf\u3002<\/li>\n<li>\u5982\u4f55\u4f7f\u7528<code>gst_bin_add_many<\/code>\u6765\u4e3a\u7ba1\u7ebf\u6dfb\u52a0\u5143\u7d20\u3002<\/li>\n<li>\u5982\u4f55\u4f7f\u7528<code>gst_element_link<\/code>\u6765\u8fde\u63a5\u7ba1\u7ebf\u4e2d\u5143\u7d20\u3002<\/li>\n<\/ol>\n","protected":false},"excerpt":{"rendered":"<p>\u4e00\u3001\u76ee\u6807 &emsp;&emsp;\u5728\u4e0a\u4e00\u7bc7\u6587\u7ae0\u4e2d\uff0c\u6211\u4eec\u4ecb\u7ecd\u4e86\u5982\u4f55\u4f7f\u7528gst_parse_launch\u5feb\u901f\u521b\u5efa\u4e00\u4e2apipeline\u3002 &#8230;<\/p>","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[54],"tags":[239],"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/swordofmorning.com\/index.php\/wp-json\/wp\/v2\/posts\/931"}],"collection":[{"href":"https:\/\/swordofmorning.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/swordofmorning.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/swordofmorning.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/swordofmorning.com\/index.php\/wp-json\/wp\/v2\/comments?post=931"}],"version-history":[{"count":1,"href":"https:\/\/swordofmorning.com\/index.php\/wp-json\/wp\/v2\/posts\/931\/revisions"}],"predecessor-version":[{"id":932,"href":"https:\/\/swordofmorning.com\/index.php\/wp-json\/wp\/v2\/posts\/931\/revisions\/932"}],"wp:attachment":[{"href":"https:\/\/swordofmorning.com\/index.php\/wp-json\/wp\/v2\/media?parent=931"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/swordofmorning.com\/index.php\/wp-json\/wp\/v2\/categories?post=931"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/swordofmorning.com\/index.php\/wp-json\/wp\/v2\/tags?post=931"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}