Error writing Mat frames to gstreamer pipeline

Michael Gruner michael.gruner at ridgerun.com
Tue Aug 13 14:09:51 UTC 2019


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 <gayathri.devi at linoy.in> 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
> gstreamer-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel


More information about the gstreamer-devel mailing list