Error writing Mat frames to gstreamer pipeline

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

Error writing Mat frames to gstreamer pipeline

gayathri1818
I am trying to stream Mat data to output video using gstreamer buffer, but
facing issues while doing so.
-----
tatic GMainLoop *loop;
int count = 0;
VideoCapture input_video;
Mat  frame;
GstElement *pipeline, *conv;
GstElement *src, *decoder, *sink , *encoder , *qtmux , *filter;
int sourceid = 0 , num_samples = 0;

static void cb_newpad (GstElement *decodebin,
       GstPad     *pad,
       gpointer    data)
{
    g_print ("In callback function");
  GstCaps *caps;
  GstStructure *str;
  GstPad *convpad;

  /* only link once */
  convpad = gst_element_get_static_pad (conv, "sink");
  if (GST_PAD_IS_LINKED (convpad)) {
    g_object_unref (convpad);
    return;
  }

  /* link*/
  gst_pad_link (pad, convpad);

  g_object_unref (convpad);
}

static void
cb_need_data (GstElement *appsrc,
        guint       unused_size,
        gpointer    user_data)
{
    input_video >> frame;
    if(frame.empty()){
        /* something wrong, stop pushing */
        g_main_loop_quit (loop);
    }
    cv::Mat* img = new cv::Mat(frame);
    gsize sizeInBytes = img->total()*img->elemSize();
    GstBuffer *buffer = gst_buffer_new_wrapped_full((GstMemoryFlags)0,
(gpointer)(img->data), sizeInBytes, 0, sizeInBytes, NULL , NULL);
    static GstClockTime timestamp = 0;
    GstFlowReturn ret;

    GST_BUFFER_PTS      (buffer) = timestamp;
    GST_BUFFER_DTS      (buffer) = timestamp;
    GST_BUFFER_DURATION (buffer) = gst_util_uint64_scale_int (1, GST_SECOND,
1);

    timestamp += GST_BUFFER_DURATION (buffer);

    g_signal_emit_by_name (src, "push-buffer", buffer, &ret);
    gst_buffer_unref (buffer);
    if (ret != GST_FLOW_OK) {
        /* something wrong, stop pushing */
        g_main_loop_quit (loop);
    }
}


int main (int   argc, char *argv[])
{
    input_video = VideoCapture(argv[1]);

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

    /* setup pipeline */
    pipeline = gst_pipeline_new ("pipeline");
    src = gst_element_factory_make ("appsrc", "source");
    decoder = gst_element_factory_make("decodebin", "decoder");
    g_signal_connect (decoder, "pad-added", G_CALLBACK (cb_newpad), NULL);
    conv = gst_element_factory_make ("videoconvert", "conv");
    encoder = gst_element_factory_make("omxh264enc", "encoder");
    qtmux = gst_element_factory_make("qtmux", "qtmux");
    sink = gst_element_factory_make ("filesink", "videosink");
    g_object_set (G_OBJECT (sink), "location", "final_ouput.mp4", NULL);

    /* setup */
    g_object_set (G_OBJECT (src), "caps",
               gst_caps_new_simple ("video/x-raw",
                "format", G_TYPE_STRING, "BGR",
                "width", G_TYPE_INT, 1024,
                "height", G_TYPE_INT, 600,
                NULL), NULL);
    gst_bin_add_many (GST_BIN (pipeline), src, decoder , conv, encoder ,
qtmux , sink, NULL);
    gst_element_link (src, decoder );
    gst_element_link(conv, encoder);
    GstPad *qtmux_sink_pad = gst_element_get_request_pad(qtmux ,
"video_%u");
    GstPad *encoder_pad = gst_element_get_static_pad(encoder , "src");

    if(gst_pad_link(encoder_pad , qtmux_sink_pad) != GST_PAD_LINK_OK){
        printf("couldnt link encoder and qtmux\n");
    }
    gst_element_link(qtmux , sink);

    /* setup appsrc */
    g_object_set (G_OBJECT (src),
            "stream-type", 0,
            "format", GST_FORMAT_TIME, NULL);
    g_signal_connect (src, "need-data", G_CALLBACK (cb_need_data), NULL);

    /* play */
    gst_element_set_state (pipeline, GST_STATE_PLAYING);
    g_main_loop_run (loop);

    /* clean up */
    gst_element_set_state (pipeline, GST_STATE_NULL);
    gst_object_unref (GST_OBJECT (pipeline));
    g_main_loop_unref (loop);

    return 0;
}
The above code works fine when the sink is xvimagesink, the video renders
properly onto the xwindow, but with sink as filesink there is an issue
creating the output file.
running this commmand on the output video gives below info:
gst-discoverer-1.0 final_output.mp4.
Analyzing file:/final_output.mp4
Done discovering file:final_output.mp4
An error was encountered while discovering the file
 This file contains no playable streams.

I could only suspect the problem with encoding , could anyone correct me if
I am doing anything wrong while encoding the video stream to write onto the
file.




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

Re: Error writing Mat frames to gstreamer pipeline

Michael Gruner
Hi Gayathri

An MP4 dile needs an EOS pushed to the pipeline before closing, otherwise the file won’t be playable. You may:

1. Process normally as you are
2. Send an EOS to the pipeline
3. Wait for the EOS to be posted on the bus (meaning that all the elements received the EOS)
4. Tear down the pipe

Michael
www.ridgerun.com

> On Aug 12, 2019, at 11:34 PM, gayathri1818 <[hidden email]> wrote:
>
> I am trying to stream Mat data to output video using gstreamer buffer, but
> facing issues while doing so.
> -----
> tatic GMainLoop *loop;
> int count = 0;
> VideoCapture input_video;
> Mat  frame;
> GstElement *pipeline, *conv;
> GstElement *src, *decoder, *sink , *encoder , *qtmux , *filter;
> int sourceid = 0 , num_samples = 0;
>
> static void cb_newpad (GstElement *decodebin,
>       GstPad     *pad,
>       gpointer    data)
> {
>    g_print ("In callback function");
>  GstCaps *caps;
>  GstStructure *str;
>  GstPad *convpad;
>
>  /* only link once */
>  convpad = gst_element_get_static_pad (conv, "sink");
>  if (GST_PAD_IS_LINKED (convpad)) {
>    g_object_unref (convpad);
>    return;
>  }
>
>  /* link*/
>  gst_pad_link (pad, convpad);
>
>  g_object_unref (convpad);
> }
>
> static void
> cb_need_data (GstElement *appsrc,
>        guint       unused_size,
>        gpointer    user_data)
> {
>    input_video >> frame;
>    if(frame.empty()){
>        /* something wrong, stop pushing */
>        g_main_loop_quit (loop);
>    }
>    cv::Mat* img = new cv::Mat(frame);
>    gsize sizeInBytes = img->total()*img->elemSize();
>    GstBuffer *buffer = gst_buffer_new_wrapped_full((GstMemoryFlags)0,
> (gpointer)(img->data), sizeInBytes, 0, sizeInBytes, NULL , NULL);
>    static GstClockTime timestamp = 0;
>    GstFlowReturn ret;
>
>    GST_BUFFER_PTS      (buffer) = timestamp;
>    GST_BUFFER_DTS      (buffer) = timestamp;
>    GST_BUFFER_DURATION (buffer) = gst_util_uint64_scale_int (1, GST_SECOND,
> 1);
>
>    timestamp += GST_BUFFER_DURATION (buffer);
>
>    g_signal_emit_by_name (src, "push-buffer", buffer, &ret);
>    gst_buffer_unref (buffer);
>    if (ret != GST_FLOW_OK) {
>        /* something wrong, stop pushing */
>        g_main_loop_quit (loop);
>    }
> }
>
>
> int main (int   argc, char *argv[])
> {
>    input_video = VideoCapture(argv[1]);
>
>    /* init GStreamer */
>    gst_init (&argc, &argv);
>    loop = g_main_loop_new (NULL, FALSE);
>
>    /* setup pipeline */
>    pipeline = gst_pipeline_new ("pipeline");
>    src = gst_element_factory_make ("appsrc", "source");
>    decoder = gst_element_factory_make("decodebin", "decoder");
>    g_signal_connect (decoder, "pad-added", G_CALLBACK (cb_newpad), NULL);
>    conv = gst_element_factory_make ("videoconvert", "conv");
>    encoder = gst_element_factory_make("omxh264enc", "encoder");
>    qtmux = gst_element_factory_make("qtmux", "qtmux");
>    sink = gst_element_factory_make ("filesink", "videosink");
>    g_object_set (G_OBJECT (sink), "location", "final_ouput.mp4", NULL);
>
>    /* setup */
>    g_object_set (G_OBJECT (src), "caps",
>               gst_caps_new_simple ("video/x-raw",
>                "format", G_TYPE_STRING, "BGR",
>                "width", G_TYPE_INT, 1024,
>                "height", G_TYPE_INT, 600,
>                NULL), NULL);
>    gst_bin_add_many (GST_BIN (pipeline), src, decoder , conv, encoder ,
> qtmux , sink, NULL);
>    gst_element_link (src, decoder );
>    gst_element_link(conv, encoder);
>    GstPad *qtmux_sink_pad = gst_element_get_request_pad(qtmux ,
> "video_%u");
>    GstPad *encoder_pad = gst_element_get_static_pad(encoder , "src");
>
>    if(gst_pad_link(encoder_pad , qtmux_sink_pad) != GST_PAD_LINK_OK){
>        printf("couldnt link encoder and qtmux\n");
>    }
>    gst_element_link(qtmux , sink);
>
>    /* setup appsrc */
>    g_object_set (G_OBJECT (src),
>            "stream-type", 0,
>            "format", GST_FORMAT_TIME, NULL);
>    g_signal_connect (src, "need-data", G_CALLBACK (cb_need_data), NULL);
>
>    /* play */
>    gst_element_set_state (pipeline, GST_STATE_PLAYING);
>    g_main_loop_run (loop);
>
>    /* clean up */
>    gst_element_set_state (pipeline, GST_STATE_NULL);
>    gst_object_unref (GST_OBJECT (pipeline));
>    g_main_loop_unref (loop);
>
>    return 0;
> }
> The above code works fine when the sink is xvimagesink, the video renders
> properly onto the xwindow, but with sink as filesink there is an issue
> creating the output file.
> running this commmand on the output video gives below info:
> gst-discoverer-1.0 final_output.mp4.
> Analyzing file:/final_output.mp4
> Done discovering file:final_output.mp4
> An error was encountered while discovering the file
> This file contains no playable streams.
>
> I could only suspect the problem with encoding , could anyone correct me if
> I am doing anything wrong while encoding the video stream to write onto the
> file.
>
>
>
>
> --
> Sent from: http://gstreamer-devel.966125.n4.nabble.com/
> _______________________________________________
> 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