diff --git a/cmake/OpenCVFindLibsVideo.cmake b/cmake/OpenCVFindLibsVideo.cmake index 1654df73ca..514aa5cd3d 100644 --- a/cmake/OpenCVFindLibsVideo.cmake +++ b/cmake/OpenCVFindLibsVideo.cmake @@ -12,8 +12,8 @@ endif(WITH_VFW) # --- GStreamer --- ocv_clear_vars(HAVE_GSTREAMER) -# try to find gstreamer 1.x first -if(WITH_GSTREAMER) +# try to find gstreamer 1.x first if 0.10 was not requested +if(WITH_GSTREAMER AND NOT WITH_GSTREAMER_0_10) CHECK_MODULE(gstreamer-base-1.0 HAVE_GSTREAMER_BASE) CHECK_MODULE(gstreamer-video-1.0 HAVE_GSTREAMER_VIDEO) CHECK_MODULE(gstreamer-app-1.0 HAVE_GSTREAMER_APP) @@ -29,7 +29,7 @@ if(WITH_GSTREAMER) set(GSTREAMER_PBUTILS_VERSION ${ALIASOF_gstreamer-pbutils-1.0_VERSION}) endif() -endif(WITH_GSTREAMER) +endif() # gstreamer support was requested but could not find gstreamer 1.x, # so fallback/try to find gstreamer 0.10 diff --git a/modules/highgui/src/cap.cpp b/modules/highgui/src/cap.cpp index 491e388559..5c17848e8d 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 cae719996e..cab652dfd2 100644 --- a/modules/highgui/src/cap_gstreamer.cpp +++ b/modules/highgui/src/cap_gstreamer.cpp @@ -75,10 +75,13 @@ #if GST_VERSION_MAJOR == 0 #define COLOR_ELEM "ffmpegcolorspace" +#define COLOR_ELEM_NAME "ffmpegcsp" #elif FULL_GST_VERSION < VERSION_NUM(1,5,0) #define COLOR_ELEM "videoconvert" +#define COLOR_ELEM_NAME COLOR_ELEM #else #define COLOR_ELEM "autovideoconvert" +#define COLOR_ELEM_NAME COLOR_ELEM #endif void toFraction(double decimal, double &numerator, double &denominator); @@ -142,6 +145,7 @@ protected: gpointer data); GstElement* pipeline; GstElement* uridecodebin; + GstElement* v4l2src; GstElement* color; GstElement* sink; #if GST_VERSION_MAJOR > 0 @@ -165,6 +169,7 @@ void CvCapture_GStreamer::init() { pipeline = NULL; uridecodebin = NULL; + v4l2src = NULL; color = NULL; sink = NULL; #if GST_VERSION_MAJOR > 0 @@ -371,9 +376,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 +571,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 +641,9 @@ bool CvCapture_GStreamer::open( int type, const char* filename ) stream = true; manualpipeline = true; } - } else { + } + else + { stream = true; uri = g_strdup(filename); } @@ -641,68 +664,86 @@ 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) { - CV_ERROR(CV_StsError, "GStreamer: cannot find appsink in manual pipeline\n"); - return false; - } -#else - it = gst_bin_iterate_sinks (GST_BIN(uridecodebin)); + GstIterator *it = gst_bin_iterate_elements(GST_BIN(uridecodebin)); - gboolean done = FALSE; GstElement *element = NULL; + gboolean done = false; gchar* name = NULL; +#if GST_VERSION_MAJOR > 0 GValue value = G_VALUE_INIT; +#endif - while (!done) { - switch (gst_iterator_next (it, &value)) { + while (!done) + { +#if GST_VERSION_MAJOR > 0 + 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; - } - g_free(name); - } - g_value_unset (&value); + element = GST_ELEMENT (g_value_get_object (&value)); +#else + switch (gst_iterator_next (it, (gpointer *)&element)) + { + case GST_ITERATOR_OK: +#endif + name = gst_element_get_name(element); + if (name) + { + if (strstr(name, "opencvsink") != NULL || strstr(name, "appsink") != NULL) + { + sink = GST_ELEMENT ( gst_object_ref (element) ); + } + else if (strstr(name, COLOR_ELEM_NAME) != NULL) + { + color = GST_ELEMENT ( gst_object_ref (element) ); + } + else if (strstr(name, "v4l") != NULL) + { + v4l2src = GST_ELEMENT ( gst_object_ref (element) ); + } + g_free(name); - break; + done = sink && color && v4l2src; + } +#if GST_VERSION_MAJOR > 0 + g_value_unset (&value); +#endif + + 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; } -#endif + pipeline = uridecodebin; } else @@ -715,18 +756,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 +800,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 +857,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__; @@ -852,7 +890,7 @@ double CvCapture_GStreamer::getProperty( int propId ) if(!pipeline) { CV_WARN("GStreamer: no pipeline"); - return false; + return 0; } switch(propId) { @@ -861,7 +899,7 @@ double CvCapture_GStreamer::getProperty( int propId ) status = gst_element_query_position(sink, FORMAT, &value); if(!status) { CV_WARN("GStreamer: unable to query position of stream"); - return false; + return 0; } return value * 1e-6; // nano seconds to milli seconds case CV_CAP_PROP_POS_FRAMES: @@ -869,7 +907,7 @@ double CvCapture_GStreamer::getProperty( int propId ) status = gst_element_query_position(sink, FORMAT, &value); if(!status) { CV_WARN("GStreamer: unable to query position of stream"); - return false; + return 0; } return value; case CV_CAP_PROP_POS_AVI_RATIO: @@ -877,7 +915,7 @@ double CvCapture_GStreamer::getProperty( int propId ) status = gst_element_query_position(sink, FORMAT, &value); if(!status) { CV_WARN("GStreamer: unable to query position of stream"); - return false; + return 0; } return ((double) value) / GST_FORMAT_PERCENT_MAX; case CV_CAP_PROP_FRAME_WIDTH: @@ -896,6 +934,21 @@ double CvCapture_GStreamer::getProperty( int propId ) case CV_CAP_PROP_CONTRAST: case CV_CAP_PROP_SATURATION: case CV_CAP_PROP_HUE: + if (v4l2src) + { + const gchar * propName = + propId == CV_CAP_PROP_BRIGHTNESS ? "brightness" : + propId == CV_CAP_PROP_CONTRAST ? "contrast" : + propId == CV_CAP_PROP_SATURATION ? "saturation" : + propId == CV_CAP_PROP_HUE ? "hue" : NULL; + + if (propName) + { + gint32 value32 = 0; + g_object_get(G_OBJECT(v4l2src), propName, &value32, NULL); + return value32; + } + } case CV_CAP_PROP_GAIN: case CV_CAP_PROP_CONVERT_RGB: break; @@ -912,7 +965,7 @@ double CvCapture_GStreamer::getProperty( int propId ) #undef FORMAT - return false; + return 0; } /*! @@ -991,6 +1044,21 @@ bool CvCapture_GStreamer::setProperty( int propId, double value ) case CV_CAP_PROP_CONTRAST: case CV_CAP_PROP_SATURATION: case CV_CAP_PROP_HUE: + if (v4l2src) + { + const gchar * propName = + propId == CV_CAP_PROP_BRIGHTNESS ? "brightness" : + propId == CV_CAP_PROP_CONTRAST ? "contrast" : + propId == CV_CAP_PROP_SATURATION ? "saturation" : + propId == CV_CAP_PROP_HUE ? "hue" : NULL; + + if (propName) + { + gint32 value32 = cv::saturate_cast(value); + g_object_set(G_OBJECT(v4l2src), propName, &value32, NULL); + return true; + } + } case CV_CAP_PROP_GAIN: case CV_CAP_PROP_CONVERT_RGB: break;