<div dir="auto"><div><br><br><div class="gmail_quote"><div dir="ltr">Le sam. 21 avr. 2018 12:12, Erickson.LU <<a href="mailto:ericksonlushan@gmail.com">ericksonlushan@gmail.com</a>> a écrit :<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">I tried to use appsink get frame and convert it cv::mat and use imshow show<br>
the mat on screen.<br>
The program some part is from opensource code.<br>
I have 2 question :<br>
(1)I think gst_buffer_ref(buffer);  used for releasing the Buffer. But why i<br>
can't use gst_buffer_unref(buffer); ???<br>
<br>
(2) The program use appsink pull frame Buffer from v4l2src and convert it to<br>
cv::mat, at last use imshow show the mat.<br>
But when i comment out  *g_main_loop_thread_ = boost::thread(RunMainLoop); *<br>
Everything is ok . The mat will continuously show the mat, and the log<br>
"frame count = ..."  will scroll .<br>
<br>
<br>
The log is :<br>
*main thread lwpid = 20051<br>
main thread tid = 1807194688<br>
Process_frame thread lwpid = 20055<br>
Process_frame thread tid = 1377380096<br>
frame count = 1<br>
Element APP_SINK0 changed state from NULL to READY.<br>
Element capsfilter1 changed state from NULL to READY.<br>
Element videoconvert0 changed state from NULL to READY.<br>
Element capsfilter0 changed state from NULL to READY.<br>
Element v4l2src0 changed state from NULL to READY.<br>
Element pipeline0 changed state from NULL to READY.<br>
Element capsfilter1 changed state from READY to PAUSED.<br>
Element videoconvert0 changed state from READY to PAUSED.<br>
Element capsfilter0 changed state from READY to PAUSED.<br>
STREAM STATUS received from element v4l2src0: CREATE<br>
Element v4l2src0 changed state from READY to PAUSED.<br>
Element pipeline0 changed state from READY to PAUSED.<br>
Unparsed message received of type: new-clock<br>
Element capsfilter1 changed state from PAUSED to PLAYING.<br>
Element videoconvert0 changed state from PAUSED to PLAYING.<br>
Element capsfilter0 changed state from PAUSED to PLAYING.<br>
Element v4l2src0 changed state from PAUSED to PLAYING.<br>
STREAM STATUS received from element v4l2src0: ENTER<br>
Unparsed message received of type: stream-start<br>
Element APP_SINK0 changed state from READY to PAUSED.<br>
Unparsed message received of type: async-done<br>
Element APP_SINK0 changed state from PAUSED to PLAYING.<br>
Element pipeline0 changed state from PAUSED to PLAYING.<br>
frame count = 2<br>
frame count = 3<br>
frame count = 4<br>
frame count = 5<br>
frame count = 6<br>
frame count = 7<br>
frame count = 8<br>
frame count = 9<br>
frame count = 10<br>
...*<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
But when I don't comment out  *g_main_loop_thread_ =<br>
boost::thread(RunMainLoop); * <br>
The mat just show only one frame on my screen and pause at there. And the<br>
log is:<br>
<br>
<br>
*main thread lwpid = 18025<br>
main thread tid = 4097198656<br>
RunningMainLoop thread lwpid = 18027<br>
RunningMainLoop thread tid = 3675776768<br>
Element APP_SINK0 changed state from NULL to READY.<br>
Element capsfilter1 changed state from NULL to READY.<br>
Element videoconvert0 changed state from NULL to READY.<br>
Element capsfilter0 changed state from NULL to READY.<br>
Element v4l2src0 changed state from NULL to READY.<br>
Element pipeline0 changed state from NULL to READY.<br>
Element capsfilter1 changed state from READY to PAUSED.<br>
Element videoconvert0 changed state from READY to PAUSED.<br>
Element capsfilter0 changed state from READY to PAUSED.<br>
STREAM STATUS received from element v4l2src0: CREATE<br>
Element v4l2src0 changed state from READY to PAUSED.<br>
Element pipeline0 changed state from READY to PAUSED.<br>
STREAM STATUS received from element v4l2src0: ENTER<br>
Unparsed message received of type: new-clock<br>
Process_frame thread lwpid = 18029<br>
Element capsfilter1 changed state from PAUSED to PLAYING.<br>
Process_frame thread tid = 3658991360<br>
Unparsed message received of type: stream-start<br>
Element videoconvert0 changed state from PAUSED to PLAYING.<br>
Element capsfilter0 changed state from PAUSED to PLAYING.<br>
Element v4l2src0 changed state from PAUSED to PLAYING.<br>
Element APP_SINK0 changed state from READY to PAUSED.Unparsed message<br>
received of type: async-done<br>
<br>
Element APP_SINK0 changed state from PAUSED to PLAYING.<br>
frame count = 1<br>
Element pipeline0 changed state from PAUSED to PLAYING.<br>
test_now: Fatal IO error 11 (Resource temporarily unavailable) on X server<br>
:0.*<br>
<br>
<br>
<br>
If i use *RunMainLoop(); instead of g_main_loop_thread_ =<br>
boost::thread(RunMainLoop);* on the main thread .<br>
It will block at *g_main_loop_run(loop);*. I can understand at blocking at<br>
there. But why i run it at a new thread it will block the Process_frame<br>
method at cv::waitKey(30); ? Does it the function  *g_main_loop_run* will<br>
occupy the X Windows server or something, make opencv can't use that ?<br>
<br>
<br>
<br>
<br>
<br>
<br>
The whole program is bleow:<br>
<br>
GstElement* pipeline;<br>
GstBus* bus;<br>
boost::thread g_main_loop_thread_;<br>
GstElement* appsink;<br>
boost::mutex mutex;<br>
GstSample* retrievedBuffer;<br>
GstSample* currentBuffer;<br>
<br>
#define SINK0 "v4l2src device=/dev/video0 ! video/x-raw,format=(string)I420,<br>
width=(int)640, height=(int)480, pixel-aspect-ratio=(fraction)1/1 !<br>
videoconvert ! video/x-raw,format=(string)BGR, width=(int)640,<br>
height=(int)480, pixel-aspect-ratio=(fraction)1/1 ! appsink name=APP_SINK0<br>
caps=video/x-raw,format=BGR,width=640,height=480,pixel-aspect-ratio=1/1"<br>
const cv::Scalar RED(0,0,255), GREEN(0,255,0);<br>
void DoNewSample()<br>
{<br>
    GstSample* sample = gst_app_sink_pull_sample(GST_APP_SINK(appsink));<br>
<br>
    if (sample) {<br>
        boost::lock_guard<boost::mutex> guard(mutex);<br>
        if (currentBuffer != 0)<br>
        {<br>
            gst_sample_unref(currentBuffer);<br>
        }<br>
        currentBuffer = sample;<br>
    }<br>
}<br>
bool IsNewFrameAvailable()<br>
{<br>
    boost::lock_guard<boost::mutex> guard(mutex);<br>
    return ((retrievedBuffer == 0) && (currentBuffer != 0));<br>
}<br>
bool GetSample(GstSample** sample)<br>
{<br>
    boost::lock_guard<boost::mutex> guard(mutex);<br>
    if (retrievedBuffer == 0) {<br>
        if (currentBuffer != 0) {<br>
            retrievedBuffer = currentBuffer;<br>
            currentBuffer = 0;<br>
            (*sample) = retrievedBuffer;<br>
            retrievedBuffer=0;<br>
        }<br>
    } else {<br>
        (*sample) = NULL;<br>
        return false;<br>
    }<br>
<br>
    return true;<br>
}<br>
<br>
void ReleaseSample()<br>
{<br>
    boost::lock_guard<boost::mutex> guard(mutex);<br>
<br>
    if (retrievedBuffer)<br>
        gst_sample_unref(retrievedBuffer);<br>
    retrievedBuffer = 0;<br>
<br>
}<br>
<br>
void Process_frame(){<br>
    GstSample* sample;<br>
    GstMapInfo map;<br>
    GstStructure* s;<br>
    GstBuffer* buffer;<br>
    GstCaps* caps;<br>
    GstMemory* mem;<br>
    int height, width, size;<br>
    int count=0;<br>
    void* map_data;<br>
    g_print("Process_frame thread lwpid = %u\n", syscall(SYS_gettid));<br>
    g_print("Process_frame thread tid = %u\n", pthread_self());<br>
    while(true){<br>
        if(IsNewFrameAvailable()){<br>
            GetSample(&sample);<br>
            caps = gst_sample_get_caps(sample);<br>
            buffer = gst_sample_get_buffer(sample);<br>
            s = gst_caps_get_structure(caps, 0);<br>
            gst_structure_get_int(s, "height", &height);<br>
            gst_structure_get_int(s, "width", &width);<br>
            size = gst_buffer_get_size(buffer);<br>
            if (gst_buffer_map (buffer, &map, GST_MAP_READ)) {<br>
                cv::Mat frame(height, width, CV_8UC3,map.data,<br>
cv::Mat::AUTO_STEP);<br>
                std::string msg ="Copy Right";<br>
                cv::Point origin(0,0+13);<br>
                cv::putText( frame, msg, origin, 1, 1, RED);<br>
                count++;<br>
                g_print("frame count = %d\n",count);<br>
                cv::imshow("View_CV",frame);<br>
                cv::waitKey(30);<br>
<br>
                gst_buffer_unmap (buffer, &map);<br>
                gst_buffer_ref(buffer);<br>
            }<br>
            gst_sample_unref (sample);<br>
            ReleaseSample();<br>
        } else {<br>
        }<br>
    }<br>
}<br>
<br>
<br>
void EndOfStreamCallback(GstAppSink* appsink, gpointer user_data)<br>
{<br>
<br>
}<br>
<br>
GstFlowReturn PrerollCallback(GstAppSink* appsink, gpointer user_data)<br>
{<br>
    GstSample* sample = gst_app_sink_pull_preroll(appsink);<br>
    gst_sample_unref(sample);<br>
    return GST_FLOW_OK;<br>
}<br>
GstFlowReturn SampleCallback(GstAppSink* appsink, gpointer user_data)<br>
{<br>
    DoNewSample();<br>
    return GST_FLOW_OK;<br>
}<br>
<br>
bool GstMessageParser(GstBus* bus, GstMessage* msg, pipelinewrapper*<br>
pipeline)<br>
{<br>
<br>
<br>
    if (msg != NULL) {<br>
        GError* err = 0;<br>
        gchar* debug_info = 0;<br>
<br>
        switch (GST_MESSAGE_TYPE(msg)) {<br>
            case GST_MESSAGE_ERROR:<br>
                gst_message_parse_error(msg, &err, &debug_info);<br>
                g_printerr("Error received from element %s: %s\n",<br>
GST_OBJECT_NAME(msg->src), err->message);<br>
                g_printerr("Debugging information: %s\n", debug_info ?<br>
debug_info : "none");<br>
                g_clear_error(&err);<br>
                g_free(debug_info);<br>
                break;<br>
<br>
            case GST_MESSAGE_WARNING:<br>
                gst_message_parse_warning(msg, &err, &debug_info);<br>
                g_printerr("Warning received from element %s: %s\n",<br>
GST_OBJECT_NAME(msg->src), err->message);<br>
                g_printerr("Debugging information: %s\n", debug_info ?<br>
debug_info : "none");<br>
                g_clear_error(&err);<br>
                g_free(debug_info);<br>
                break;<br>
<br>
            case GST_MESSAGE_INFO:<br>
                gst_message_parse_info(msg, &err, &debug_info);<br>
                g_printerr("Info received from element %s: %s\n",<br>
GST_OBJECT_NAME(msg->src), err->message);<br>
                g_printerr("Debugging information: %s\n", debug_info ?<br>
debug_info : "none");<br>
                g_clear_error(&err);<br>
                g_free(debug_info);<br>
                break;<br>
<br>
            case GST_MESSAGE_EOS:<br>
                g_print("End-Of-Stream reached.\n");<br>
                break;<br>
<br>
            case GST_MESSAGE_STATE_CHANGED:<br>
                GstState old_state, new_state;<br>
                gst_message_parse_state_changed(msg, &old_state, &new_state,<br>
0);<br>
                g_print("Element %s changed state from %s to %s.\n",<br>
GST_OBJECT_NAME(msg->src), gst_element_state_get_name(old_state),<br>
gst_element_state_get_name(new_state));<br>
                break;<br>
<br>
            case GST_MESSAGE_QOS:<br>
                break;<br>
<br>
            case GST_MESSAGE_STREAM_STATUS:<br>
<br>
                GstStreamStatusType stream_status_type;<br>
                GstElement* owner;<br>
                const gchar* stream_status_type_string;<br>
                gst_message_parse_stream_status(msg, &stream_status_type,<br>
&owner);<br>
<br>
                switch (stream_status_type) {<br>
                    case GST_STREAM_STATUS_TYPE_CREATE:<br>
                        stream_status_type_string = "CREATE";<br>
                        break;<br>
                    case GST_STREAM_STATUS_TYPE_ENTER:<br>
                        stream_status_type_string = "ENTER";<br>
                        break;<br>
                    case GST_STREAM_STATUS_TYPE_LEAVE:<br>
                        stream_status_type_string = "LEAVE";<br>
                        break;<br>
                    case GST_STREAM_STATUS_TYPE_DESTROY:<br>
                        stream_status_type_string = "DESTROY";<br>
                        break;<br>
<br>
                    case GST_STREAM_STATUS_TYPE_START:<br>
                        stream_status_type_string = "START";<br>
                        break;<br>
                    case GST_STREAM_STATUS_TYPE_PAUSE:<br>
                        stream_status_type_string = "PAUSE";<br>
                        break;<br>
                    case GST_STREAM_STATUS_TYPE_STOP:<br>
                        stream_status_type_string = "STOP";<br>
                        break;<br>
                }<br>
<br>
                g_printerr("STREAM STATUS received from element %s: %s\n",<br>
GST_OBJECT_NAME(owner), stream_status_type_string);<br>
                //g_free (stream_status_type_string);<br>
                break;<br>
<br>
            default:<br>
                g_printerr("Unparsed message received of type: %s\n",<br>
gst_message_type_get_name(GST_MESSAGE_TYPE(msg)));<br>
                break;<br>
        }<br>
    }<br>
    return true;<br>
}<br>
<br>
void RunMainLoop()<br>
{<br>
    GMainLoop* loop = g_main_loop_new(NULL, FALSE);<br></blockquote></div></div><div dir="auto"><br></div><div dir="auto">This is wrong, Null mean default main context, which must be created on the same thread. It's really hard to control in which thread the one will be created. In your case, it probably get created in your main function, when you do gst_bus_add_watch(). You could try to create it here, but in general, it's more robust to create a new one. Nd then make everything explicit. Using push_thread_default, and also gst_bus_create_watch and g_source_attach</div><div dir="auto"><br></div><div dir="auto"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
    g_print("RunningMainLoop thread lwpid = %u\n", syscall(SYS_gettid));<br>
    g_print("RunningMainLoop thread tid = %u\n", pthread_self());<br>
    g_main_loop_run(loop);<br>
}<br>
<br>
int<br>
main (int argc, char *argv[])<br>
{<br>
<br>
    gst_init(&argc, &argv);<br>
//    XInitThreads();<br>
    boost::thread g_main_loop_thread0;<br>
<br>
    GstAppSinkCallbacks appsinkCallbacks;<br>
    std::string pipelineString = SINK0;<br>
    std::string appsink_name="APP_SINK0";<br>
    GError* err = 0;<br>
    pipeline = gst_parse_launch(pipelineString.c_str(), &err);<br>
<br>
    bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline));<br>
    gst_bus_add_watch(bus, (GstBusFunc)GstMessageParser, NULL);<br>
<br>
    g_main_loop_thread_ = boost::thread(RunMainLoop);<br>
//    RunMainLoop();<br>
    appsink = gst_bin_get_by_name(GST_BIN(pipeline), appsink_name.c_str());<br>
<br>
    g_print("main thread lwpid = %u\n", syscall(SYS_gettid));<br>
    g_print("main thread tid = %u\n", pthread_self());<br>
<br>
<br>
    appsinkCallbacks.new_preroll = &PrerollCallback;<br>
    appsinkCallbacks.new_sample = &SampleCallback;<br>
//    appsinkCallbacks.eos = &EndOfStreamCallback;<br>
    gst_app_sink_set_drop(GST_APP_SINK(appsink), true);<br>
    gst_app_sink_set_max_buffers(GST_APP_SINK(appsink), 1);<br>
    gst_app_sink_set_callbacks(GST_APP_SINK(appsink), &appsinkCallbacks,<br>
NULL, NULL);<br>
<br>
<br>
    GstStateChangeReturn ret = gst_element_set_state(pipeline,<br>
GST_STATE_PLAYING);<br>
<br>
    if (ret == GST_STATE_CHANGE_FAILURE) {<br>
        g_printerr("Unable to set the pipeline to the playing state");<br>
        gst_object_unref(pipeline);<br>
        return false;<br>
    }<br>
<br>
<br>
//    Process_frame();<br>
    g_main_loop_thread0 = boost::thread(&Process_frame);<br>
    g_main_loop_thread0.join();<br>
<br>
    /* cleanup and exit */<br>
<br>
    gst_element_set_state(pipeline,GST_STATE_NULL);<br>
    gst_object_unref (pipeline);<br>
<br>
    exit (0);<br>
}<br>
<br>
<br>
<br>
<br>
--<br>
Sent from: <a href="http://gstreamer-devel.966125.n4.nabble.com/" rel="noreferrer noreferrer" target="_blank">http://gstreamer-devel.966125.n4.nabble.com/</a><br>
_______________________________________________<br>
gstreamer-devel mailing list<br>
<a href="mailto:gstreamer-devel@lists.freedesktop.org" target="_blank" rel="noreferrer">gstreamer-devel@lists.freedesktop.org</a><br>
<a href="https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel" rel="noreferrer noreferrer" target="_blank">https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel</a><br>
</blockquote></div></div></div>