user2487382
user2487382

Reputation:

Gstreamer appsrc: odd behaviour of need-data callback

I'm implementing gstreamer media player with my own source of data using appsrc. Everything works fine except one thing:
When stream reaches it's end, callback emits "end-of-stream" signal. Signals sending fucntion
g_signal_emit_by_name(appsrc, "end-of-stream", &ret)
returns GstFlowReturn value GST_FLOW_OK. But then it calls need-data my callback again, so it returns "end-of-stream" signal again. And this time GstFlowReturn value is (-3) which is GST_FLOW UNEXPECTED. I assume that it does not expect "end-of-stream" signal when it already recieved one, but why it requests more data than? Maybe it is because I didn't set size value iof the steam?

Gstreamer version is 0.10.
Callback function code (appsrc type is seekable 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);
        }
    }
}

Upvotes: 2

Views: 3113

Answers (2)

mpr
mpr

Reputation: 3378

Have you tried the method gst_app_src_end_of_stream()? I'm not sure what return code you should use after invoking it, but it should be either GST_FLOW_OK or GST_FLOW_UNEXPECTED.

In GStreamer 1.x you return GST_FLOW_EOS.

Upvotes: 0

Benjamin Trent
Benjamin Trent

Reputation: 7566

You should provide some corrections to your code(if they are not there already) that should alleviate your issue and help the overall application:

  1. Never try and send a buffer without first checking if it actually has data. So, simply check the buffer data and length to make sure that the data is not NULL and that the length is >0
  2. You can flag that a stream is ended in your user_data. When you send your EOS, set an item in your userdata to indicate that it has been sent and if the appsrc requests more data, simply check if it has been sent and then do not send anything else to the buffer.
  3. Listen for the EOS on your pipeline bus so that it can destroy the stream and close the loop when the EOS message is handled so that you can be sure that your mediasink has received the EOS and you can safely dispose of the pipeline and loop without losing any data.

Upvotes: 1

Related Questions