From 2243bfa181dec54bf6cecca4f99a94296f807127 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Sat, 15 Aug 2015 18:30:08 +0300 Subject: [PATCH] repaired gstreamer camera capture: 1. Enabled property retrieval: height, width, FPS 2. Fixed issue when isOpened returns always true even for non-existing devices 3. Ability to work with non-0 device. Camera capture index is taken into account (cherry picked from commit dbd7912b88e36a045d1086d54f77467de5ab006f) --- modules/highgui/src/cap.cpp | 6 +- modules/highgui/src/cap_gstreamer.cpp | 130 +++++++++++++++++++++------------- 2 files changed, 83 insertions(+), 53 deletions(-) diff --git a/modules/highgui/src/cap.cpp b/modules/highgui/src/cap.cpp index 491e388..5c17848 100644 --- a/modules/highgui/src/cap.cpp +++ b/modules/highgui/src/cap.cpp @@ -238,10 +238,12 @@ CV_IMPL CvCapture * cvCreateCameraCapture (int index) #endif #ifdef HAVE_GSTREAMER - capture = cvCreateCapture_GStreamer(CV_CAP_GSTREAMER_V4L2, 0); + capture = cvCreateCapture_GStreamer(CV_CAP_GSTREAMER_V4L2, + reinterpret_cast(index)); if (capture) return capture; - capture = cvCreateCapture_GStreamer(CV_CAP_GSTREAMER_V4L, 0); + capture = cvCreateCapture_GStreamer(CV_CAP_GSTREAMER_V4L, + reinterpret_cast(index)); if (capture) return capture; #endif diff --git a/modules/highgui/src/cap_gstreamer.cpp b/modules/highgui/src/cap_gstreamer.cpp index cae7199..fe4eaf2 100644 --- a/modules/highgui/src/cap_gstreamer.cpp +++ b/modules/highgui/src/cap_gstreamer.cpp @@ -371,9 +371,7 @@ void CvCapture_GStreamer::startPipeline() if (status == GST_STATE_CHANGE_ASYNC) { // wait for status update - GstState st1; - GstState st2; - status = gst_element_get_state(pipeline, &st1, &st2, GST_CLOCK_TIME_NONE); + status = gst_element_get_state(pipeline, NULL, NULL, GST_CLOCK_TIME_NONE); } if (status == GST_STATE_CHANGE_FAILURE) { @@ -568,21 +566,39 @@ bool CvCapture_GStreamer::open( int type, const char* filename ) GstElementFactory * testfac; GstStateChangeReturn status; - if (type == CV_CAP_GSTREAMER_V4L){ + int cameraID = -1; + if (type == CV_CAP_GSTREAMER_V4L || + type == CV_CAP_GSTREAMER_V4L2) + { + cameraID = static_cast(reinterpret_cast(filename)); + } + + std::stringstream stdstream; + std::string stdfilename; + + if (type == CV_CAP_GSTREAMER_V4L) + { testfac = gst_element_factory_find("v4lsrc"); if (!testfac){ return false; } g_object_unref(G_OBJECT(testfac)); - filename = "v4lsrc ! "COLOR_ELEM" ! appsink"; + + stdstream << "v4lsrc device=/dev/video" << cameraID << " ! " << COLOR_ELEM << " ! appsink"; + stdfilename = stdstream.str(); + filename = stdfilename.c_str(); } - if (type == CV_CAP_GSTREAMER_V4L2){ + else if (type == CV_CAP_GSTREAMER_V4L2) + { testfac = gst_element_factory_find("v4l2src"); if (!testfac){ return false; } g_object_unref(G_OBJECT(testfac)); - filename = "v4l2src ! "COLOR_ELEM" ! appsink"; + + stdstream << "v4l2src device=/dev/video" << cameraID << " ! " << COLOR_ELEM << " ! appsink"; + stdfilename = stdstream.str(); + filename = stdfilename.c_str(); } @@ -620,7 +636,9 @@ bool CvCapture_GStreamer::open( int type, const char* filename ) stream = true; manualpipeline = true; } - } else { + } + else + { stream = true; uri = g_strdup(filename); } @@ -641,64 +659,77 @@ bool CvCapture_GStreamer::open( int type, const char* filename ) uridecodebin = gst_element_make_from_uri(GST_URI_SRC, uri, "src", NULL); #endif element_from_uri = true; - }else{ + } + else + { uridecodebin = gst_element_factory_make("uridecodebin", NULL); g_object_set(G_OBJECT(uridecodebin), "uri", uri, NULL); } g_free(protocol); - if(!uridecodebin) { + if(!uridecodebin) + { //fprintf(stderr, "GStreamer: Error opening bin: %s\n", err->message); close(); return false; } } - if(manualpipeline) + if (manualpipeline) { GstIterator *it = NULL; #if GST_VERSION_MAJOR == 0 it = gst_bin_iterate_sinks(GST_BIN(uridecodebin)); - if(gst_iterator_next(it, (gpointer *)&sink) != GST_ITERATOR_OK) { + if (gst_iterator_next(it, (gpointer *)&sink) != GST_ITERATOR_OK) + { CV_ERROR(CV_StsError, "GStreamer: cannot find appsink in manual pipeline\n"); return false; } #else - it = gst_bin_iterate_sinks (GST_BIN(uridecodebin)); + it = gst_bin_iterate_elements(GST_BIN(uridecodebin)); - gboolean done = FALSE; + gboolean done = false; GstElement *element = NULL; gchar* name = NULL; GValue value = G_VALUE_INIT; - while (!done) { - switch (gst_iterator_next (it, &value)) { + while (!done) + { + switch (gst_iterator_next (it, &value)) + { case GST_ITERATOR_OK: - element = GST_ELEMENT (g_value_get_object (&value)); - name = gst_element_get_name(element); - if (name){ - if(strstr(name, "opencvsink") != NULL || strstr(name, "appsink") != NULL) { - sink = GST_ELEMENT ( gst_object_ref (element) ); - done = TRUE; + element = GST_ELEMENT (g_value_get_object (&value)); + name = gst_element_get_name(element); + if (name) + { + if (strstr(name, "opencvsink") != NULL || strstr(name, "appsink") != NULL) + { + sink = GST_ELEMENT ( gst_object_ref (element) ); + done = sink && color; + } + else if (strstr(name, COLOR_ELEM) != NULL) + { + color = GST_ELEMENT ( gst_object_ref (element) ); + done = sink && color; + } + g_free(name); } - g_free(name); - } - g_value_unset (&value); + g_value_unset (&value); - break; + break; case GST_ITERATOR_RESYNC: - gst_iterator_resync (it); - break; + gst_iterator_resync (it); + break; case GST_ITERATOR_ERROR: case GST_ITERATOR_DONE: - done = TRUE; - break; - } + done = TRUE; + break; + } } gst_iterator_free (it); - - if (!sink){ + if (!sink) + { CV_ERROR(CV_StsError, "GStreamer: cannot find appsink in manual pipeline\n"); return false; } @@ -715,18 +746,23 @@ bool CvCapture_GStreamer::open( int type, const char* filename ) gst_bin_add_many(GST_BIN(pipeline), uridecodebin, color, sink, NULL); - if(element_from_uri) { - if(!gst_element_link(uridecodebin, color)) { + if(element_from_uri) + { + if(!gst_element_link(uridecodebin, color)) + { CV_ERROR(CV_StsError, "GStreamer: cannot link color -> sink\n"); gst_object_unref(pipeline); pipeline = NULL; return false; } - }else{ + } + else + { g_signal_connect(uridecodebin, "pad-added", G_CALLBACK(newPad), color); } - if(!gst_element_link(color, sink)) { + if(!gst_element_link(color, sink)) + { CV_ERROR(CV_StsError, "GStreamer: cannot link color -> sink\n"); gst_object_unref(pipeline); pipeline = NULL; @@ -754,16 +790,13 @@ bool CvCapture_GStreamer::open( int type, const char* filename ) gst_app_sink_set_caps(GST_APP_SINK(sink), caps); gst_caps_unref(caps); - // For video files only: set pipeline to PAUSED state to get its duration - if (file) { - status = gst_element_set_state(GST_ELEMENT(pipeline), GST_STATE_PAUSED); + status = gst_element_set_state(GST_ELEMENT(pipeline), + file ? GST_STATE_PAUSED : GST_STATE_PLAYING); if (status == GST_STATE_CHANGE_ASYNC) { // wait for status update - GstState st1; - GstState st2; - status = gst_element_get_state(pipeline, &st1, &st2, GST_CLOCK_TIME_NONE); + status = gst_element_get_state(pipeline, NULL, NULL, GST_CLOCK_TIME_NONE); } if (status == GST_STATE_CHANGE_FAILURE) { @@ -814,14 +847,9 @@ bool CvCapture_GStreamer::open( int type, const char* filename ) fps = (double)num/(double)denom; - // GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(pipeline), GST_DEBUG_GRAPH_SHOW_ALL, "pipeline"); - } - else - { - duration = -1; - width = -1; - height = -1; - fps = -1; + // GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(pipeline), GST_DEBUG_GRAPH_SHOW_ALL, "pipeline") + + stopPipeline(); } __END__; -- 2.7.4