c - 将 Gstrplaybin 链接到自定义视频接收器 videoconvert 和接收器不链接 gstreamer

标签 c gstreamer rtsp gstreamer-1.0 playbin2

尝试从管道制作 gstreamer 应用程序:gst-launch-1.0 playbin uri=rtsp://video-sink="videoconvert !video/x-raw,width=720, height=480 !ximagesink"

链接元素时出错。发布我的代码:

#include <gst/gst.h>

int main(int argc, char *argv[]) {
    GstElement *source, *videosink, *pipeline, *videoconvert;
    GstCaps *capsFilter;
    GstBus *bus;
    GstMessage *msg;
    GstPad *pad;
    gboolean link_ok;

    /* Initialize GStreamer */
    gst_init (&argc, &argv);


    /* Create Elements */
    pipeline = gst_pipeline_new("my-pipeline");
    source = gst_element_factory_make ("playbin", "source");
    videoconvert = gst_element_factory_make("videoconvert", "convert");
    videosink = gst_element_factory_make("ximagesink", "autovideosink");

    /* set property value */
    g_object_set (source, "uri", "rtsp:<file location>", NULL);

    if (!pipeline || !source || !videoconvert || !videosink)
    {   
            g_printerr ("Not all elements could be created.\n");
            return;
    }   


    gst_bin_add_many (GST_BIN(pipeline), videoconvert, videosink, NULL);
    capsFilter = gst_caps_new_simple("video/x-raw",
                    "width", G_TYPE_INT, 176,
                    "height", G_TYPE_INT, 144, 
                    NULL);
    link_ok = gst_element_link_filtered(videoconvert,videosink, capsFilter);
    gst_caps_unref (capsFilter);

    if (!link_ok) {
            g_warning ("Failed to link element1 and element2!");
    }   
    if (gst_element_link_many( videoconvert, videosink, NULL) != TRUE) {
            g_print ("Failed to link some elements .....1 !\n");
            gst_object_unref (pipeline);
            return -1; 
    }   


      /* Start playing */
    gst_element_set_state (source, GST_STATE_PLAYING);

    /* Wait until error or EOS */
    bus = gst_element_get_bus (source);
    msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE,
GST_MESSAGE_ERROR | GST_MESSAGE_EOS);

最佳答案

应该注意的是,playbin 元素提供了从 src 到 sink 的完整管道,因此没有 sink 东西的管道可以完美播放:

gst-launch-1.0 playbin uri=rtsp://127.0.0.1:8551/test

接下来是您要创建的正确管道:

gst-launch-1.0 playbin uri=rtsp://127.0.0.1:8551/test video-sink="videoconvert ! video/x-raw,width=320,height=240 ! ximagesink"

为了将其嵌入到 GStreamer 应用程序中,没有必要链接所有元素。取而代之的是,需要执行的必要步骤是构建自定义视频输出容器并将其设置为播放容器的 video-sink 属性。换句话说,要走的路是创建一个 bin 并链接必要的元素,然后告诉 playbin 通过它的 video-sink 属性使用它。还需要为 bin 创建一个 GhostPad,并将其指向 bin 内第一个元素的 sink pad。

这是结果:

#include <gst/gst.h>

int main(int argc, char *argv[]) {
    GstElement *source, *videosink, *pipeline, *videoconvert, *customoutput;
    GstCaps *capsFilter;
    GstBus *bus;
    GstMessage *msg;
    GstPad *pad;
    gboolean add_ok;
    gboolean link_ok;
    GstStateChangeReturn ret;
    GMainLoop *loop;

    /* Initialize GStreamer */
    gst_init (&argc, &argv);
    loop = g_main_loop_new (NULL, FALSE);


    /* Create Elements */
    pipeline = gst_pipeline_new("my-pipeline");
    source = gst_element_factory_make ("playbin", "source");
    videoconvert = gst_element_factory_make("videoconvert", "videoconvert");
    capsFilter = gst_caps_new_simple("video/x-raw",
                    "width", G_TYPE_INT, 320,
                    "height", G_TYPE_INT, 240, 
                    NULL);
    videosink = gst_element_factory_make("ximagesink", "videosink");
    customoutput = gst_bin_new("customoutput");

    // It is possible to create the bin like this 
    // Ghost pads on the bin for unlinked source or sink pads within the bin can automatically be created
    // customoutput =  gst_parse_bin_from_description ("videoconvert ! video/x-raw,width=320 ! ximagesink", TRUE, NULL);
    gst_bin_add_many (GST_BIN (customoutput), videoconvert, videosink, NULL);

    link_ok = gst_element_link_filtered(videoconvert,videosink, capsFilter);
    gst_caps_unref (capsFilter);
    if (!link_ok) {
            g_warning ("Failed to link element1 and element2!");
    }

    GstPad *sinkpad,*ghost_sinkpad;
    sinkpad = gst_element_get_static_pad (videoconvert, "sink"); 
    ghost_sinkpad = gst_ghost_pad_new ("sink", sinkpad); 
    gst_pad_set_active (ghost_sinkpad, TRUE); 
    gst_element_add_pad (customoutput, ghost_sinkpad); 

    /* set property value */
    g_object_set (source, "video-sink", customoutput, NULL);
    g_object_set (source, "uri", "rtsp://127.0.0.1:8551/test", NULL);

    if (!pipeline || !source || !videoconvert || !capsFilter || !videosink || !customoutput)
    {   
            g_printerr ("Not all elements could be created.\n");
            return -1;
    }

    gst_bin_add_many (GST_BIN(pipeline), source,NULL);

    // Start playing */
    ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
    g_print ("Running...\n");
    g_main_loop_run (loop);
    if (ret == GST_STATE_CHANGE_FAILURE) {
        g_printerr ("Unable to set the pipeline to the playing state.\n");
        gst_object_unref (pipeline);
        return -1;
    }
    /* Wait until error or EOS */
    //bus = gst_element_get_bus (pipeline);
    //msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE,GST_MESSAGE_ERROR | GST_MESSAGE_EOS);

      /* Free resources */
    gst_object_unref (bus);
    gst_element_set_state (pipeline, GST_STATE_NULL);
    gst_object_unref (pipeline);
    g_main_loop_unref (loop);

    return 0;
}

关于c - 将 Gstrplaybin 链接到自定义视频接收器 videoconvert 和接收器不链接 gstreamer,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41585909/

相关文章:

c - 在同一语句中向左和向右按位移位

c - 在 UDP 套接字上监听,同时还使用 C 从标准输入接收输入

java - Gstreamer Tee/队列多流水线

curl - libcurl 仅在使用摘要身份验证时不支持协议(protocol)

android - 如何使用 url 在我的 android 应用程序上进行 RTSP 流式传输?

c - 我是否需要在编译时添加一个 _REENTRANT 宏以使我的 errno 线程安全?

c++ - 将结构数组传递给 OpenGL

javascript - 在具有良好浏览器兼容性的网页上播放 Rtsp 流的最有效插件

jpeg - 困难的 gstreamer 管道 - 使用 DirectShow 在 Windows 上将 h264 文件解码/解复用为 jpeg

android - MediaCodec 和摄像头 : colorspaces don't match