<div>I have encountered a confusing problem on my jetson-TX1(gstreamer1.8,qt5.5,opencv3.2 which has been configured with gstreamer).<br>First,I tested "gst-launch-1.0 rtspsrc location=rtsp://admin:admin12345@192.168.1.64:554/h264/ch33/main/av_stream latency=0 ! decodebin ! videoconvert ! xvimagesink sync=false" in command window and I got real-time video of my IP camera.<br>However,when I want to use gstreamer in qt project to do opencv displaying.I tested the follow code which used appsink callback and the result is that video is not real-time and the delaying is accumulating over time.The result is unacceptable in my real-time project.Could someone help me?Best wishes to you all!<br><br>#include <gst/gst.h><br>#include <gst/app/gstappsink.h><br>#include <stdlib.h><br>#include<QTime><br>#include<QDebug><br><br>#include "opencv2/opencv.hpp"<br><br>using namespace cv;<br><br>#define CAPS "video/x-raw,format=BGR,fFrameRate=25/1,width=1280,height=720"<br><br>// TODO: use synchronized deque<br>GMainLoop *loop;<br>std::deque<Mat> frameQueue;<br>int live_flag = 0;<br>int quit_flag = 0;<br>int sum_time=0;<br><br>GstFlowReturn new_preroll(GstAppSink *appsink, gpointer data)<br>{<br>    g_print ("Got preroll!\n");<br>    return GST_FLOW_OK;<br>}<br><br>GstFlowReturn new_sample(GstAppSink *appsink, gpointer data)<br>{<br>    QTime time;<br>    time.start();<br>    static int framecount = 0;<br>    framecount++;<br><br>    static int width=0, height=0 ;<br><br>    GstSample *sample = gst_app_sink_pull_sample(appsink);<br>    GstCaps *caps = gst_sample_get_caps(sample);<br>    GstBuffer *buffer = gst_sample_get_buffer(sample);<br>    static GstStructure *s;<br>    const GstStructure *info = gst_sample_get_info(sample);<br>    // ---- get width and height<br>    if(framecount==1)<br>    {<br>        if(!caps)<br>        {<br>            g_print("Could not get image info from filter caps");<br>            exit(-11);<br>        }<br><br>        s = gst_caps_get_structure(caps,0);<br>        gboolean res = gst_structure_get_int(s, "width", &width);<br>        res |= gst_structure_get_int(s, "height", &height);<br>        if(!res)<br>        {<br>            g_print("Could not get image width and height from filter caps");<br>            exit(-12);<br>        }<br>        g_print("Image size: %d\t%d\n",width,height);<br>    }<br><br><br>    // ---- Read frame and convert to opencv format ---------------<br>    GstMapInfo map;<br>    gst_buffer_map (buffer, &map, GST_MAP_READ);<br><br>    // convert gstreamer data to OpenCV Mat, you could actually<br>    // resolve height / width from caps...<br><br>    Mat frame(Size(width, height), CV_8UC3, (char*)map.data, Mat::AUTO_STEP);<br><br>        // this lags pretty badly even when grabbing frames from webcam<br>        //Mat edges;<br>        //cvtColor(frame, edges, CV_RGB2GRAY);<br>        //GaussianBlur(edges, edges, Size(7,7), 1.5, 1.5);<br>        //Canny(edges, edges, 0, 30, 3);<br>        imshow("stream", frame);<br><br>        //char key = cv::waitKey(10);<br>        //if(key!=-1) quit_flag = 1;<br><br><br>    gst_buffer_unmap(buffer, &map);<br><br>    // ------------------------------------------------------------<br><br>    // print dot every 30 frames<br>    if (framecount%30 == 0) {<br>    g_print (".");<br>    }<br><br>    // show caps on first frame<br>    if (framecount == 1) {<br>    g_print ("%s\n", gst_caps_to_string(caps));<br>    }<br><br>    gst_sample_unref (sample);<br>    sum_time =time.elapsed();<br>    qDebug()<<"time:"<<sum_time<<"\n";<br>    return GST_FLOW_OK;<br>}<br><br>static gboolean my_bus_callback (GstBus *bus, GstMessage *message, gpointer data)<br>{<br>    g_print ("Got %s message from %s\n", GST_MESSAGE_TYPE_NAME (message), GST_OBJECT_NAME (message->src));<br>    switch (GST_MESSAGE_TYPE (message))<br>    {<br>            case GST_MESSAGE_ERROR:<br>            {<br>                    GError *err;<br>                    gchar *debug;<br><br>                    gst_message_parse_error (message, &err, &debug);<br>                    g_print ("Error from %s: %s\n", GST_OBJECT_NAME (message->src), err->message);<br>                    g_error_free (err);<br>                    g_free (debug);<br>                    break;<br>            }<br>            case GST_MESSAGE_EOS:<br>                    /* end-of-stream */<br>                    quit_flag = 1;<br>                    break;<br>            case GST_MESSAGE_STATE_CHANGED:<br>                    GstState oldstate, newstate;<br>                    gst_message_parse_state_changed(message, &oldstate, &newstate, NULL);<br>                    g_print ("Element %s changed state from %s to %s.\n",<br>                    GST_OBJECT_NAME (message->src),<br>                            gst_element_state_get_name (oldstate),<br>                            gst_element_state_get_name (newstate));<br>                    break;<br>            default:<br>                    /* unhandled message */<br>                    break;<br>    }<br>    /* we want to be notified again the next time there is a message<br>    * on the bus, so returning TRUE (FALSE means we want to stop watching<br>    * for messages on the bus and our callback should not be called again)<br>    */<br>    return TRUE;<br>}<br><br>int main (int argc, char *argv[])<br>{<br>    GError *error = NULL;<br><br>    GstElement *pipeline, *sink;<br>    GstStateChangeReturn state_ret;<br><br>    GstSample *sample;<br><br>    gst_init (&argc, &argv);<br><br>        gchar *descr = g_strdup(<br>        "rtspsrc location=rtsp://admin:admin12345@192.168.1.64:554/h264/ch33/main/av_stream latency=0 ! "<br>        "decodebin ! "<br>        "videoconvert ! "<br>        "appsink name=sink sync=false"<br>    );<br><br>//    gchar *descr = g_strdup(<br>//              "rtspsrc location=\"rtsp://admin:admin12345@192.168.1.64:554/h264/ch33/main/av_stream\" latency=0 ! "<br>//                    "decodebin ! "<br>//                    "videoconvert ! "<br>//                    "xvimagesink name=sink sync=true"<br>//                );<br><br>    pipeline = gst_parse_launch (descr, &error);<br><br>    if (error != NULL)<br>    {<br>        g_print ("could not construct pipeline: %s\n", error->message);<br>        g_error_free (error);<br>        exit (-1);<br>    }<br><br>    /* get sink */<br>    sink = gst_bin_get_by_name (GST_BIN (pipeline), "sink");<br><br>    /*set to pause*/<br>    state_ret = gst_element_set_state(pipeline, GST_STATE_PAUSED);<br><br>    switch(state_ret)<br>    {<br>        case GST_STATE_CHANGE_FAILURE:<br>            g_print ("failed to play the file\n");<br>            exit (-2);<br>        case GST_STATE_CHANGE_NO_PREROLL:<br>            /* for live sources, we need to set the pipeline to PLAYING before we can<br>            * receive a buffer. */<br>            g_print ("live source detected\n");<br>            live_flag = 1;<br>            break;<br>        default:<br>            break;<br>    }<br><br>    gst_app_sink_set_emit_signals((GstAppSink*)sink, true);<br>    gst_app_sink_set_drop((GstAppSink*)sink, true);<br>    gst_app_sink_set_max_buffers((GstAppSink*)sink, 1);<br>    GstAppSinkCallbacks callbacks = { NULL, new_preroll, new_sample };<br>    gst_app_sink_set_callbacks (GST_APP_SINK(sink), &callbacks, NULL, NULL);<br><br>    GstBus *bus;<br>    guint bus_watch_id;<br>    bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));<br>    bus_watch_id = gst_bus_add_watch (bus, my_bus_callback, NULL);<br>    gst_object_unref (bus);<br><br>        gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);<br><br>    namedWindow("stream",1);<br><br>    loop = g_main_loop_new(NULL,false);<br>        g_main_loop_run(loop);<br><br>    cv::destroyWindow("stream");<br>    g_print ("Going to end of main!\n");<br>    gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);<br>    gst_object_unref (GST_OBJECT (pipeline));<br><br>    return 0;<br>}<br><br></div>