Gstreamer appsrc:需要数据回调的奇怪行为

时间:2014-11-19 15:07:36

标签: c++ c audio callback gstreamer

我正在使用appsrc使用我自己的数据源实现gstreamer媒体播放器。一切都很好,除了一件事:
当流到达它结束时,回调会发出"end-of-stream"信号。发送信息的信号
g_signal_emit_by_name(appsrc, "end-of-stream", &ret)
返回GstFlowReturnGST_FLOW_OK。但是它再次调用need-data我的回调,因此它再次返回"end-of-stream"信号。此时GstFlowReturn值为(-3),即GST_FLOW UNEXPECTED。我假设它已经收到一个信号时不会发出"end-of-stream"信号,但为什么它要求的数据多于?也许是因为我没有为蒸汽设定size值?

Gstreamer版本是0.10 回调函数代码(appsrc类型可以搜索btw):

static void cb_need_data (GstElement *appsrc, guint size, gpointer user_data)
{
    GstBuffer *buffer;
    GstFlowReturn ret;
    AppsrcData* data = static_cast<AppsrcData*>(user_data);
    buffer = gst_buffer_new_and_alloc(size);

    int read = fread(GST_BUFFER_DATA(buffer), 1, size, data->file);
    GST_BUFFER_SIZE(buffer) = read;

    g_signal_emit_by_name (appsrc, "push-buffer", buffer, &ret);

    if (ret != GST_FLOW_OK) {
        /* something wrong, stop pushing */
       g_printerr("GST_FLOW != OK, return value is %d\n", ret);
       g_main_loop_quit (data->loop);
    }

    if(feof(data->file) || read == 0)
    {
        g_signal_emit_by_name(appsrc, "end-of-stream", &ret);
        if (ret != GST_FLOW_OK) {
           g_printerr("EOF reached, GST_FLOW != OK, return value is %d\nAborting...", ret);
           g_main_loop_quit (data->loop);
        }
    }
}

2 个答案:

答案 0 :(得分:1)

您应该对代码进行一些更正(如果它们不存在),这些更正应该可以缓解您的问题并帮助整个应用程序:

  1. 在没有先检查它是否确实有数据的情况下,不要尝试发送缓冲区。因此,只需检查缓冲区数据和长度,以确保数据不是NULL并且长度> 0
  2. 您可以在user_data中标记流已结束。当您发送EOS时,在userdata中设置一个项目以表明它已被发送,如果appsrc请求更多数据,只需检查它是否已被发送,然后不再向缓冲区发送任何其他内容。
  3. 在管道总线上监听EOS,以便在处理EOS消息时可以销毁流并关闭循环,这样您就可以确保您的mediasink已经收到EOS并且您可以安全地处理管道和循环而不丢失任何数据。

答案 1 :(得分:0)

您是否尝试过方法gst_app_src_end_of_stream()?我不确定在调用它之后应该使用什么返回代码,但它应该是GST_FLOW_OK或GST_FLOW_UNEXPECTED。

在GStreamer 1.x中,您返回GST_FLOW_EOS。