【问题标题】:Pushing images into a gstreamer pipeline将图像推送到 gstreamer 管道中
【发布时间】:2011-07-15 22:24:34
【问题描述】:

在玩了一些玩具应用程序之后,探索 文档和谷歌搜索(包括邮件列表 档案)我仍然对我认为相当普遍的事情感到困惑 用例。

我有一个生成图像(在内存中)的现有代码,我会 喜欢将这些图像推送到 gstreamer 管道中(创建一个 flv 视频在最后)。

我找不到“明显的方法”。我最好的猜测是 挖掘 GstMultiFileSrc 及其父 GstPushSrc 的源代码, 想办法解决。

你们中的任何人都可以指出我这样做的“明显方式”吗? 是否有任何相关的文档/教程/示例?

一旦我输入正确,剩下的就是小菜一碟,感谢 Gstreamer 真棒! (类似于“我的魔法输入 -> ffmpegcolorspace ! ffenc_flv ! !文件接收器位置=desktop.flv")

感谢您的回答。

【问题讨论】:

    标签: c++ image video gstreamer


    【解决方案1】:

    我找到了一个解决方案(也许)(我使用 OpenCV 获取图像)......但我的管道出现错误:来自元素 mysource 的错误:错误 en el flujo de datos interno。 调试信息: gstbasesrc.c(2574): gst_base_src_loop (): /GstPipeline:pipeline0/GstAppSrc:mysource: 流式传输任务暂停,原因未协商 (-4)

    这是代码:

    typedef struct _App App;
    struct _App{
        GstElement *pipeline;
        GstElement *appsrc;
    
        GMainLoop *loop;
        guint sourceid;
        GTimer *timer;
    };
    
    App s_app;
    CvCapture *capture;
    static gboolean read_data(App *app){
        GstFlowReturn ret;
        GstBuffer *buffer = gst_buffer_new();
        IplImage* frame = cvQueryFrame(capture);
        GST_BUFFER_DATA(buffer) = (uchar*)frame->imageData;
        GST_BUFFER_SIZE(buffer) = frame->width*frame->height*sizeof(uchar*);
        g_signal_emit_by_name(app->appsrc,"push-buffer",buffer,&ret);
        gst_buffer_unref(buffer);
        if(ret != GST_FLOW_OK){
            GST_DEBUG("Error al alimentar buffer");
            return FALSE;
        }
        return TRUE;
     }
    
    static void start_feed(GstElement* pipeline,guint size, App* app){
        if(app->sourceid == 0){
            GST_DEBUG("Alimentando");
            app->sourceid = g_idle_add((GSourceFunc) read_data, app);
        }
     }
    
    static void stop_feed(GstElement* pipeline, App* app){
        if(app->sourceid !=0 ){
            GST_DEBUG("Stop feeding");
            g_source_remove(app->sourceid);
            app->sourceid = 0;
        }
    }
    
    static gboolean
    bus_message (GstBus * bus, GstMessage * message, App * app)
    {
       GST_DEBUG ("got message %s",
       gst_message_type_get_name (GST_MESSAGE_TYPE (message)));
    
      switch (GST_MESSAGE_TYPE (message)) {
        case GST_MESSAGE_ERROR: {
            GError *err = NULL;
            gchar *dbg_info = NULL;
            gst_message_parse_error (message, &err, &dbg_info);
            g_printerr ("ERROR from element %s: %s\n",
                GST_OBJECT_NAME (message->src), err->message);
            g_printerr ("Debugging info: %s\n", (dbg_info) ? dbg_info : "none");
            g_error_free (err);
            g_free (dbg_info);
            g_main_loop_quit (app->loop);
            break;
        }
        case GST_MESSAGE_EOS:
          g_main_loop_quit (app->loop);
          break;
       default:
          break;
      }
      return TRUE;
    }
    
    int main(int argc, char* argv[]){
        App *app = &s_app;
        GError *error = NULL;
        GstBus *bus;
        GstCaps *caps;
        capture = cvCaptureFromCAM(0);
        gst_init(&argc,&argv);
        /* create a mainloop to get messages and to handle the idle handler that will
         * feed data to appsrc. */
        app->loop = g_main_loop_new (NULL, TRUE);
        app->timer = g_timer_new();
    
        app->pipeline = gst_parse_launch("appsrc name=mysource ! video/x-raw-rgb,width=640,height=480,bpp=24,depth=24 ! ffmpegcolorspace ! videoscale method=1 ! theoraenc bitrate=150 ! tcpserversink host=127.0.0.1 port=5000", NULL);
        g_assert (app->pipeline);
        bus = gst_pipeline_get_bus (GST_PIPELINE (app->pipeline));
        g_assert(bus);
        /* add watch for messages */
        gst_bus_add_watch (bus, (GstBusFunc) bus_message, app);
       /* get the appsrc */
        app->appsrc = gst_bin_get_by_name (GST_BIN(app->pipeline), "mysource");
        g_assert(app->appsrc);
        g_assert(GST_IS_APP_SRC(app->appsrc));
        g_signal_connect (app->appsrc, "need-data", G_CALLBACK (start_feed), app);
        g_signal_connect (app->appsrc, "enough-data", G_CALLBACK (stop_feed), app);
    
        /* set the caps on the source */
       caps = gst_caps_new_simple ("video/x-raw-rgb",
         "bpp",G_TYPE_INT,24,
         "depth",G_TYPE_INT,24,
         "width", G_TYPE_INT, 640,
         "height", G_TYPE_INT, 480,
         NULL);
       gst_app_src_set_caps(GST_APP_SRC(app->appsrc), caps);
      /* go to playing and wait in a mainloop. */
      gst_element_set_state (app->pipeline, GST_STATE_PLAYING);
    
       /* this mainloop is stopped when we receive an error or EOS */
       g_main_loop_run (app->loop);
       GST_DEBUG ("stopping");
      gst_element_set_state (app->pipeline, GST_STATE_NULL);
       gst_object_unref (bus);
       g_main_loop_unref (app->loop);
       cvReleaseCapture(&capture);
     return 0;
     }
    

    有什么想法???

    【讨论】:

    • 尝试将此作为单独的问题发布,而不是作为答案发布
    【解决方案2】:

    GStreamer 使用插件来完成所有工作。创建数据或从外部源获取数据的插件称为“src”插件。

    用于将应用程序生成的数据注入管道的通用 src 插件称为appsrc。 appsrc 提供的 API 记录为 App Library 的一部分。

    下面是一个示例,它演示了如何使用生成的图像向 apprc 提供数据:gdk-gstappsrc-stream.c。似乎来源于GStreamer源码树中的一些测试代码:here

    另一种方法是创建自己的 src 插件。查看goom 音乐可视化插件的示例,它的工作方式似乎与您指定的类似。

    【讨论】:

      【解决方案3】:

      您可以尝试破解imagefreeze 来做您想做的事。 appsrc 也可以这样做。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-03-23
        • 1970-01-01
        • 2016-09-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多