How to correctly handle interrupts with multiple queues (using appsink) ?

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

How to correctly handle interrupts with multiple queues (using appsink) ?

simo-zz
Hello,

I am developing a C program which uses the following pipeline

v4l2src device=/dev/webcam ! videoconvert ! video/x-raw,width=544,height=288 ! tee name=t ! queue ! v4l2h264enc ! h264parse ! mp4mux ! filesink location=/path/to/video.mp4 t. ! queue ! appsink

and I need to restart the pipeline every N seconds, which involves sending an EOS to the pipeline so the video can be closed (otherwise I will not be able to play with a media player).
I decided to handle the restart from the appsink callback function, since I can control the timeout each time I receive a "new-sample" to appsink.

The problem I am stuck on is that the interrupt is catched, but the program hangs, the EOS message in never received and nothing happens. The program remain locked showing the string "Interrupt: Stopping pipeline ..." (code below) and nothing more.
The code involved in the restart handling is the following:

// global variables
// use sigUsr1Watch for interrupt
guint sigUsr1Watch;
// timeval is set when main starts,
// then sum it a value in seconds
time_t timeval;
// gstreamer loop
GMainLoop *loop;
// restart control variable
gboolean restart;

// GstData is the struct containing the pipeline elements
gboolean irqUsr1Handler(GstData *user_data)
{
    GstElement *pipeline = (GstElement *) user_data->pipeline;
    GstElement *appsink = (GstElement *) user_data->appsink;

    g_print("Interrupt: Stopping pipeline ...\n");
    // stop emitting signals from appsink
    gst_app_sink_set_emit_signals(GST_APP_SINK(appsink), false);
    // send EOS to the pipeline
    gst_element_send_event(pipeline, gst_event_new_eos());

    restart = true;
    sigUsr1Watch = 0;
    return ELR_INTERRUPT;
}

// dataProbe is the appsink callback function,
// executed when "new-sample" signal is catched
GstFlowReturn dataProbe(GstElement *source)
{  
    g_print("data probe\n");
    GstMapInfo map;
    GstSample *sample = gst_app_sink_pull_sample(GST_APP_SINK(source));
    GstBuffer *buffer = gst_sample_get_buffer(sample);
    gst_buffer_ref(buffer);
    gst_buffer_map (buffer, &map, GST_MAP_READ);
   
    // do something with map.data here ...

    gst_buffer_unmap(buffer, &map);
    gst_buffer_unref(buffer);
    gst_sample_unref(sample);
   
    // check if time is elapsed
    if(time(NULL) > timeval)
        raise(SIGUSR1);

    return GST_FLOW_OK;
}

// Gst Bus message handler function
// here I catch the GST_MESSAGE_EOS
gboolean gstMsgHandler(GstBus *bus, GstMessage *message, gpointer user_data)
{
    GstElement *pipeline = (GstElement *) user_data;

    switch (GST_MESSAGE_TYPE (message))
    {
        case GST_MESSAGE_EOS:
        {
            // we have received the EOS.
            // we can stop the loop, close the pipeline and restart everything.        
            g_print("Got EOS from element \"%s\".\n", GST_MESSAGE_SRC_NAME (message));
            if (restart && g_main_loop_is_running(loop))
            {
                g_main_loop_quit(loop);
                g_main_loop_unref(loop);
            }
            break;
        }
        default:
            break;
    }

    return true;
}

The problem is of course due to a bad interrupt handling in presence of the tee and queues, because with the following pipeline using filesink only for video recording:

v4l2src device=/dev/webcam ! videoconvert ! video/x-raw,width=544,height=288 ! v4l2h264enc ! h264parse ! mp4mux ! filesink location=/path/to/video.mp4

everything works fine and I am able to restart the pipeline correctly.
Is the appsink causing these problems ?

What is the correct way to handle interrupt and signals in presence of multiple queues like my situation ?
Thank you in advance.
Regards,
Simon

_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
Reply | Threaded
Open this post in threaded view
|

Re: How to correctly handle interrupts with multiple queues (using appsink) ?

simo-zz
Hello.
Solved.

Setting the option "flush-on-eos" for each queue and configuring the pipeline with:

gst_app_sink_set_drop(GST_APP_SINK(gstData->appsink), true);
gst_app_sink_set_max_buffers(GST_APP_SINK(gstData->appsink), 1);

do the trick.
Regards,
Simon


El Martes 12 de septiembre de 2017 17:31, simo zz <[hidden email]> escribió:


Hello,

I am developing a C program which uses the following pipeline

v4l2src device=/dev/webcam ! videoconvert ! video/x-raw,width=544,height=288 ! tee name=t ! queue ! v4l2h264enc ! h264parse ! mp4mux ! filesink location=/path/to/video.mp4 t. ! queue ! appsink

and I need to restart the pipeline every N seconds, which involves sending an EOS to the pipeline so the video can be closed (otherwise I will not be able to play with a media player).
I decided to handle the restart from the appsink callback function, since I can control the timeout each time I receive a "new-sample" to appsink.

The problem I am stuck on is that the interrupt is catched, but the program hangs, the EOS message in never received and nothing happens. The program remain locked showing the string "Interrupt: Stopping pipeline ..." (code below) and nothing more.
The code involved in the restart handling is the following:

// global variables
// use sigUsr1Watch for interrupt
guint sigUsr1Watch;
// timeval is set when main starts,
// then sum it a value in seconds
time_t timeval;
// gstreamer loop
GMainLoop *loop;
// restart control variable
gboolean restart;

// GstData is the struct containing the pipeline elements
gboolean irqUsr1Handler(GstData *user_data)
{
    GstElement *pipeline = (GstElement *) user_data->pipeline;
    GstElement *appsink = (GstElement *) user_data->appsink;

    g_print("Interrupt: Stopping pipeline ...\n");
    // stop emitting signals from appsink
    gst_app_sink_set_emit_signals(GST_APP_SINK(appsink), false);
    // send EOS to the pipeline
    gst_element_send_event(pipeline, gst_event_new_eos());

    restart = true;
    sigUsr1Watch = 0;
    return ELR_INTERRUPT;
}

// dataProbe is the appsink callback function,
// executed when "new-sample" signal is catched
GstFlowReturn dataProbe(GstElement *source)
{  
    g_print("data probe\n");
    GstMapInfo map;
    GstSample *sample = gst_app_sink_pull_sample(GST_APP_SINK(source));
    GstBuffer *buffer = gst_sample_get_buffer(sample);
    gst_buffer_ref(buffer);
    gst_buffer_map (buffer, &map, GST_MAP_READ);
   
    // do something with map.data here ...

    gst_buffer_unmap(buffer, &map);
    gst_buffer_unref(buffer);
    gst_sample_unref(sample);
   
    // check if time is elapsed
    if(time(NULL) > timeval)
        raise(SIGUSR1);

    return GST_FLOW_OK;
}

// Gst Bus message handler function
// here I catch the GST_MESSAGE_EOS
gboolean gstMsgHandler(GstBus *bus, GstMessage *message, gpointer user_data)
{
    GstElement *pipeline = (GstElement *) user_data;

    switch (GST_MESSAGE_TYPE (message))
    {
        case GST_MESSAGE_EOS:
        {
            // we have received the EOS.
            // we can stop the loop, close the pipeline and restart everything.        
            g_print("Got EOS from element \"%s\".\n", GST_MESSAGE_SRC_NAME (message));
            if (restart && g_main_loop_is_running(loop))
            {
                g_main_loop_quit(loop);
                g_main_loop_unref(loop);
            }
            break;
        }
        default:
            break;
    }

    return true;
}

The problem is of course due to a bad interrupt handling in presence of the tee and queues, because with the following pipeline using filesink only for video recording:

v4l2src device=/dev/webcam ! videoconvert ! video/x-raw,width=544,height=288 ! v4l2h264enc ! h264parse ! mp4mux ! filesink location=/path/to/video.mp4

everything works fine and I am able to restart the pipeline correctly.
Is the appsink causing these problems ?

What is the correct way to handle interrupt and signals in presence of multiple queues like my situation ?
Thank you in advance.
Regards,
Simon



_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
Reply | Threaded
Open this post in threaded view
|

Re: How to correctly handle interrupts with multiple queues (using appsink) ?

simo-zz
In reply to this post by simo-zz
Hello,
Sorry for cross-posting, I wrote too much earlier...

In fact it worked one time, and no more.
So this is not a solution.

Regards,
Simon

El Martes 12 de septiembre de 2017 17:49, simo zz <[hidden email]> escribió:


Hello.
Solved.

Setting the option "flush-on-eos" for each queue and configuring the pipeline with:

gst_app_sink_set_drop(GST_APP_SINK(gstData->appsink), true);
gst_app_sink_set_max_buffers(GST_APP_SINK(gstData->appsink), 1);

do the trick.
Regards,
Simon


El Martes 12 de septiembre de 2017 17:31, simo zz <[hidden email]> escribió:


Hello,

I am developing a C program which uses the following pipeline

v4l2src device=/dev/webcam ! videoconvert ! video/x-raw,width=544,height=288 ! tee name=t ! queue ! v4l2h264enc ! h264parse ! mp4mux ! filesink location=/path/to/video.mp4 t. ! queue ! appsink

and I need to restart the pipeline every N seconds, which involves sending an EOS to the pipeline so the video can be closed (otherwise I will not be able to play with a media player).
I decided to handle the restart from the appsink callback function, since I can control the timeout each time I receive a "new-sample" to appsink.

The problem I am stuck on is that the interrupt is catched, but the program hangs, the EOS message in never received and nothing happens. The program remain locked showing the string "Interrupt: Stopping pipeline ..." (code below) and nothing more.
The code involved in the restart handling is the following:

// global variables
// use sigUsr1Watch for interrupt
guint sigUsr1Watch;
// timeval is set when main starts,
// then sum it a value in seconds
time_t timeval;
// gstreamer loop
GMainLoop *loop;
// restart control variable
gboolean restart;

// GstData is the struct containing the pipeline elements
gboolean irqUsr1Handler(GstData *user_data)
{
    GstElement *pipeline = (GstElement *) user_data->pipeline;
    GstElement *appsink = (GstElement *) user_data->appsink;

    g_print("Interrupt: Stopping pipeline ...\n");
    // stop emitting signals from appsink
    gst_app_sink_set_emit_signals(GST_APP_SINK(appsink), false);
    // send EOS to the pipeline
    gst_element_send_event(pipeline, gst_event_new_eos());

    restart = true;
    sigUsr1Watch = 0;
    return ELR_INTERRUPT;
}

// dataProbe is the appsink callback function,
// executed when "new-sample" signal is catched
GstFlowReturn dataProbe(GstElement *source)
{  
    g_print("data probe\n");
    GstMapInfo map;
    GstSample *sample = gst_app_sink_pull_sample(GST_APP_SINK(source));
    GstBuffer *buffer = gst_sample_get_buffer(sample);
    gst_buffer_ref(buffer);
    gst_buffer_map (buffer, &map, GST_MAP_READ);
   
    // do something with map.data here ...

    gst_buffer_unmap(buffer, &map);
    gst_buffer_unref(buffer);
    gst_sample_unref(sample);
   
    // check if time is elapsed
    if(time(NULL) > timeval)
        raise(SIGUSR1);

    return GST_FLOW_OK;
}

// Gst Bus message handler function
// here I catch the GST_MESSAGE_EOS
gboolean gstMsgHandler(GstBus *bus, GstMessage *message, gpointer user_data)
{
    GstElement *pipeline = (GstElement *) user_data;

    switch (GST_MESSAGE_TYPE (message))
    {
        case GST_MESSAGE_EOS:
        {
            // we have received the EOS.
            // we can stop the loop, close the pipeline and restart everything.        
            g_print("Got EOS from element \"%s\".\n", GST_MESSAGE_SRC_NAME (message));
            if (restart && g_main_loop_is_running(loop))
            {
                g_main_loop_quit(loop);
                g_main_loop_unref(loop);
            }
            break;
        }
        default:
            break;
    }

    return true;
}

The problem is of course due to a bad interrupt handling in presence of the tee and queues, because with the following pipeline using filesink only for video recording:

v4l2src device=/dev/webcam ! videoconvert ! video/x-raw,width=544,height=288 ! v4l2h264enc ! h264parse ! mp4mux ! filesink location=/path/to/video.mp4

everything works fine and I am able to restart the pipeline correctly.
Is the appsink causing these problems ?

What is the correct way to handle interrupt and signals in presence of multiple queues like my situation ?
Thank you in advance.
Regards,
Simon





_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
Reply | Threaded
Open this post in threaded view
|

RE: How to correctly handle interrupts with multiple queues (using appsink) ?

simo-zz


I finally solved using the g_timeout_add function.
It helps me to do exactly what I need and it works like a sharm..

Here a link to an example:

Regards,
Simon

_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
Reply | Threaded
Open this post in threaded view
|

Re: How to correctly handle interrupts with multiple queues (using appsink) ?

Michael MacIntosh

Hey, one thing that might help (I don't know what you are trying to accomplish), but if you just need to rotate to a new file after a certain period of time / file size, there is an element splitmuxsink

https://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-good/html/gst-plugins-good-plugins-splitmuxsink.html

That might be what you are looking for!



On 9/12/2017 11:18 AM, simo zz wrote:


I finally solved using the g_timeout_add function.
It helps me to do exactly what I need and it works like a sharm..

Here a link to an example:

Regards,
Simon


_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel


_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
Reply | Threaded
Open this post in threaded view
|

Re: How to correctly handle interrupts with multiple queues (using appsink) ?

simo-zz
Hi, this is fantastic, that's what I need. I will test it as soon as possible !
Thank you Michael.
Regards,
Simon


El Martes 12 de septiembre de 2017 22:01, Michael MacIntosh <[hidden email]> escribió:


Hey, one thing that might help (I don't know what you are trying to accomplish), but if you just need to rotate to a new file after a certain period of time / file size, there is an element splitmuxsink
That might be what you are looking for!


On 9/12/2017 11:18 AM, simo zz wrote:


I finally solved using the g_timeout_add function.
It helps me to do exactly what I need and it works like a sharm..

Here a link to an example:

Regards,
Simon


_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel

_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel



_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel