From ee0c16e43ef693264833cd2558a1258e86535638 Mon Sep 17 00:00:00 2001 From: Nils Hasler Date: Sat, 23 Apr 2011 07:27:04 +0000 Subject: [PATCH] * added property CV_CAP_GSTREAMER_QUEUE_LENGTH * removed unnecessary memcpy * fixed minor memory leak --- .../include/opencv2/highgui/highgui_c.h | 7 ++- modules/highgui/src/cap_gstreamer.cpp | 55 +++++++++++++++---- 2 files changed, 48 insertions(+), 14 deletions(-) diff --git a/modules/highgui/include/opencv2/highgui/highgui_c.h b/modules/highgui/include/opencv2/highgui/highgui_c.h index cee386b899..efd28b8c3a 100644 --- a/modules/highgui/include/opencv2/highgui/highgui_c.h +++ b/modules/highgui/include/opencv2/highgui/highgui_c.h @@ -358,14 +358,17 @@ enum CV_CAP_OPENNI_IMAGE_GENERATOR = 1 << 31, CV_CAP_OPENNI_GENERATORS_MASK = 1 << 31, - // Properties of cameras avalible through OpenNI interfaces + // Properties of cameras available through OpenNI interfaces CV_CAP_PROP_OPENNI_OUTPUT_MODE = 100, CV_CAP_PROP_OPENNI_FRAME_MAX_DEPTH = 101, // in mm CV_CAP_PROP_OPENNI_BASELINE = 102, // in mm CV_CAP_PROP_OPENNI_FOCAL_LENGTH = 103, // in pixels CV_CAP_OPENNI_IMAGE_GENERATOR_OUTPUT_MODE = CV_CAP_OPENNI_IMAGE_GENERATOR + CV_CAP_PROP_OPENNI_OUTPUT_MODE, CV_CAP_OPENNI_DEPTH_GENERATOR_BASELINE = CV_CAP_OPENNI_DEPTH_GENERATOR + CV_CAP_PROP_OPENNI_BASELINE, - CV_CAP_OPENNI_DEPTH_GENERATOR_FOCAL_LENGTH = CV_CAP_OPENNI_DEPTH_GENERATOR + CV_CAP_PROP_OPENNI_FOCAL_LENGTH + CV_CAP_OPENNI_DEPTH_GENERATOR_FOCAL_LENGTH = CV_CAP_OPENNI_DEPTH_GENERATOR + CV_CAP_PROP_OPENNI_FOCAL_LENGTH, + + // Properties of cameras available through GStreamer interface + CV_CAP_GSTREAMER_QUEUE_LENGTH = 200 // default is 1 }; enum diff --git a/modules/highgui/src/cap_gstreamer.cpp b/modules/highgui/src/cap_gstreamer.cpp index 5414d34d15..d931405685 100644 --- a/modules/highgui/src/cap_gstreamer.cpp +++ b/modules/highgui/src/cap_gstreamer.cpp @@ -104,6 +104,7 @@ protected: GstCaps *caps; IplImage *frame; }; + void CvCapture_GStreamer::init() { pipeline=0; @@ -185,7 +186,9 @@ bool CvCapture_GStreamer::grabFrame() else #endif { +// printf("pulling buffer\n"); buffer = gst_app_sink_pull_buffer(GST_APP_SINK(sink)); +// printf("pulled buffer %p\n", GST_BUFFER_DATA(buffer)); } if(!buffer) return false; @@ -201,6 +204,8 @@ IplImage * CvCapture_GStreamer::retrieveFrame(int) if(!buffer) return false; +// printf("retrieving buffer %p\n", GST_BUFFER_DATA(buffer)); + if(!frame) { gint height, width; GstCaps *buff_caps = gst_buffer_get_caps(buffer); @@ -208,17 +213,18 @@ IplImage * CvCapture_GStreamer::retrieveFrame(int) GstStructure* structure = gst_caps_get_structure(buff_caps, 0); if(!gst_structure_get_int(structure, "width", &width) || - !gst_structure_get_int(structure, "height", &height)) + !gst_structure_get_int(structure, "height", &height)) return false; - frame = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 3); + frame = cvCreateImageHeader(cvSize(width, height), IPL_DEPTH_8U, 3); gst_caps_unref(buff_caps); } - memcpy (frame->imageData, GST_BUFFER_DATA(buffer), GST_BUFFER_SIZE (buffer)); + frame->imageData = (char *)GST_BUFFER_DATA(buffer); + //memcpy (frame->imageData, GST_BUFFER_DATA(buffer), GST_BUFFER_SIZE (buffer)); //gst_data_copy_into (frame->imageData,GST_BUFFER_DATA(buffer)); - gst_buffer_unref(buffer); - buffer = 0; + //gst_buffer_unref(buffer); + //buffer = 0; return frame; } @@ -306,6 +312,14 @@ void CvCapture_GStreamer::newPad(GstElement *uridecodebin, gst_object_unref (sinkpad); } +// static int buffernum = 0; +// static GstFlowReturn newbuffer(GstAppSink *sink, gpointer data) +// { + // printf("new buffer %d\n", buffernum); + // buffernum++; + // return GST_FLOW_OK; +// } + bool CvCapture_GStreamer::open( int type, const char* filename ) { close(); @@ -384,6 +398,8 @@ bool CvCapture_GStreamer::open( int type, const char* filename ) if (stream) { gst_app_sink_set_drop (GST_APP_SINK(sink),true); } +// GstAppSinkCallbacks cb = {0, 0, newbuffer, 0}; +// gst_app_sink_set_callbacks(GST_APP_SINK(sink), &cb, 0, 0); #else sink = gst_element_factory_make("opencv-appsink", NULL); #endif @@ -501,11 +517,11 @@ void CvVideoWriter_GStreamer::init() } void CvVideoWriter_GStreamer::close() { - if (pipeline) { - gst_app_src_end_of_stream(GST_APP_SRC(source)); - gst_element_set_state (pipeline, GST_STATE_NULL); - gst_object_unref (GST_OBJECT (pipeline)); - } + if (pipeline) { + gst_app_src_end_of_stream(GST_APP_SRC(source)); + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (GST_OBJECT (pipeline)); + } } bool CvVideoWriter_GStreamer::open( const char * filename, int fourcc, double fps, CvSize frameSize, bool is_color ) @@ -637,6 +653,10 @@ void CvCapture_GStreamer::close() } if(buffer) gst_buffer_unref(buffer); + if(frame) { + frame->imageData = 0; + cvReleaseImage(&frame); + } } double CvCapture_GStreamer::getProperty( int propId ) @@ -653,14 +673,14 @@ double CvCapture_GStreamer::getProperty( int propId ) switch(propId) { case CV_CAP_PROP_POS_MSEC: format = GST_FORMAT_TIME; - if(!gst_element_query_position(pipeline, &format, &value)) { + if(!gst_element_query_position(sink, &format, &value)) { CV_WARN("GStreamer: unable to query position of stream"); return false; } return value * 1e-6; // nano seconds to milli seconds case CV_CAP_PROP_POS_FRAMES: format = GST_FORMAT_DEFAULT; - if(!gst_element_query_position(pipeline, &format, &value)) { + if(!gst_element_query_position(sink, &format, &value)) { CV_WARN("GStreamer: unable to query position of stream"); return false; } @@ -693,6 +713,12 @@ double CvCapture_GStreamer::getProperty( int propId ) case CV_CAP_PROP_GAIN: case CV_CAP_PROP_CONVERT_RGB: break; + case CV_CAP_GSTREAMER_QUEUE_LENGTH: + if(!sink) { + CV_WARN("GStreamer: there is no sink yet"); + return false; + } + return gst_app_sink_get_max_buffers(GST_APP_SINK(sink)); default: CV_WARN("GStreamer: unhandled property"); break; @@ -772,6 +798,11 @@ bool CvCapture_GStreamer::setProperty( int propId, double value ) case CV_CAP_PROP_GAIN: case CV_CAP_PROP_CONVERT_RGB: break; + case CV_CAP_GSTREAMER_QUEUE_LENGTH: + if(!sink) + break; + gst_app_sink_set_max_buffers(GST_APP_SINK(sink), (guint) value); + break; default: CV_WARN("GStreamer: unhandled property"); }