From 53e5f028ec832ce34b44e283c4cffe5bdabb5308 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole=20Andr=C3=A9=20Vadla=20Ravn=C3=A5s?= Date: Fri, 11 Apr 2008 19:33:53 +0000 Subject: [PATCH] sys/dshowsrcwrapper/gstdshowvideosrc.*: Don't increase latency by queuing buffers in an async queue when the streamin... MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Original commit message from CVS: Patch by: Ole André Vadla Ravnås * sys/dshowsrcwrapper/gstdshowvideosrc.c: (PROP_DEVICE_NAME), (gst_dshowvideosrc_class_init), (gst_dshowvideosrc_init), (gst_dshowvideosrc_dispose), (gst_dshowvideosrc_stop), (gst_dshowvideosrc_unlock), (gst_dshowvideosrc_unlock_stop), (gst_dshowvideosrc_create), (gst_dshowvideosrc_push_buffer): * sys/dshowsrcwrapper/gstdshowvideosrc.h: Don't increase latency by queuing buffers in an async queue when the streaming thread can't keep up or isn't scheduled often enough for some other reason, but just drop the previous buffer in that case. Also implement GstBaseSrc::unlock for faster unlocking when shutting down. (#520892). --- ChangeLog | 16 ++++++ sys/dshowsrcwrapper/gstdshowvideosrc.c | 72 +++++++++++++++++++++++--- sys/dshowsrcwrapper/gstdshowvideosrc.h | 7 ++- 3 files changed, 87 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index b28ffdd0a6..a7b1a31e00 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2008-04-11 Tim-Philipp Müller + + Patch by: Ole André Vadla Ravnås + + * sys/dshowsrcwrapper/gstdshowvideosrc.c: (PROP_DEVICE_NAME), + (gst_dshowvideosrc_class_init), (gst_dshowvideosrc_init), + (gst_dshowvideosrc_dispose), (gst_dshowvideosrc_stop), + (gst_dshowvideosrc_unlock), (gst_dshowvideosrc_unlock_stop), + (gst_dshowvideosrc_create), (gst_dshowvideosrc_push_buffer): + * sys/dshowsrcwrapper/gstdshowvideosrc.h: + Don't increase latency by queuing buffers in an async queue when + the streaming thread can't keep up or isn't scheduled often + enough for some other reason, but just drop the previous buffer + in that case. Also implement GstBaseSrc::unlock for faster + unlocking when shutting down. (#520892). + 2008-04-11 Tim-Philipp Müller * tests/icles/metadata_editor.c: (ENC_UNKNOWN), (last_pixbuf), diff --git a/sys/dshowsrcwrapper/gstdshowvideosrc.c b/sys/dshowsrcwrapper/gstdshowvideosrc.c index 79ed596342..a7692ad584 100644 --- a/sys/dshowsrcwrapper/gstdshowvideosrc.c +++ b/sys/dshowsrcwrapper/gstdshowvideosrc.c @@ -100,6 +100,8 @@ static GstStateChangeReturn gst_dshowvideosrc_change_state (GstElement * static gboolean gst_dshowvideosrc_start (GstBaseSrc * bsrc); static gboolean gst_dshowvideosrc_stop (GstBaseSrc * bsrc); +static gboolean gst_dshowvideosrc_unlock (GstBaseSrc * bsrc); +static gboolean gst_dshowvideosrc_unlock_stop (GstBaseSrc * bsrc); static gboolean gst_dshowvideosrc_set_caps (GstBaseSrc * bsrc, GstCaps * caps); static GstCaps *gst_dshowvideosrc_get_caps (GstBaseSrc * bsrc); static GstFlowReturn gst_dshowvideosrc_create (GstPushSrc * psrc, @@ -170,6 +172,9 @@ gst_dshowvideosrc_class_init (GstDshowVideoSrcClass * klass) gstbasesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_dshowvideosrc_set_caps); gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_dshowvideosrc_start); gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_dshowvideosrc_stop); + gstbasesrc_class->unlock = GST_DEBUG_FUNCPTR (gst_dshowvideosrc_unlock); + gstbasesrc_class->unlock_stop = + GST_DEBUG_FUNCPTR (gst_dshowvideosrc_unlock_stop); gstpushsrc_class->create = GST_DEBUG_FUNCPTR (gst_dshowvideosrc_create); @@ -201,7 +206,10 @@ gst_dshowvideosrc_init (GstDshowVideoSrc * src, GstDshowVideoSrcClass * klass) src->pins_mediatypes = NULL; src->is_rgb = FALSE; - src->async_queue = g_async_queue_new (); + src->buffer_cond = g_cond_new (); + src->buffer_mutex = g_mutex_new (); + src->buffer = NULL; + src->stop_requested = FALSE; CoInitializeEx (NULL, COINIT_MULTITHREADED); @@ -239,9 +247,19 @@ gst_dshowvideosrc_dispose (GObject * gobject) src->video_cap_filter = NULL; } - if (src->async_queue) { - g_async_queue_unref (src->async_queue); - src->async_queue = NULL; + if (src->buffer_mutex) { + g_mutex_free (src->buffer_mutex); + src->buffer_mutex = NULL; + } + + if (src->buffer_cond) { + g_cond_free (src->buffer_cond); + src->buffer_cond = NULL; + } + + if (src->buffer) { + gst_buffer_unref (src->buffer); + src->buffer = NULL; } CoUninitialize (); @@ -511,6 +529,7 @@ gst_dshowvideosrc_get_caps (GstBaseSrc * basesrc) GstCaps *caps = gst_dshowvideosrc_getcaps_from_streamcaps (src, capture_pin, streamcaps); + if (caps) { gst_caps_append (src->caps, caps); } @@ -791,12 +810,48 @@ gst_dshowvideosrc_stop (GstBaseSrc * bsrc) return TRUE; } +static gboolean +gst_dshowvideosrc_unlock (GstBaseSrc * bsrc) +{ + GstDshowVideoSrc *src = GST_DSHOWVIDEOSRC (bsrc); + + g_mutex_lock (src->buffer_mutex); + src->stop_requested = TRUE; + g_cond_signal (src->buffer_cond); + g_mutex_unlock (src->buffer_mutex); + + return TRUE; +} + +static gboolean +gst_dshowvideosrc_unlock_stop (GstBaseSrc * bsrc) +{ + GstDshowVideoSrc *src = GST_DSHOWVIDEOSRC (bsrc); + + src->stop_requested = FALSE; + + return TRUE; +} + static GstFlowReturn gst_dshowvideosrc_create (GstPushSrc * psrc, GstBuffer ** buf) { GstDshowVideoSrc *src = GST_DSHOWVIDEOSRC (psrc); - *buf = g_async_queue_pop (src->async_queue); + g_mutex_lock (src->buffer_mutex); + while (src->buffer == NULL && !src->stop_requested) + g_cond_wait (src->buffer_cond, src->buffer_mutex); + *buf = src->buffer; + src->buffer = NULL; + g_mutex_unlock (src->buffer_mutex); + + if (src->stop_requested) { + if (*buf != NULL) { + gst_buffer_unref (*buf); + *buf = NULL; + } + return GST_FLOW_WRONG_STATE; + } GST_CAT_DEBUG (dshowvideosrc_debug, "dshowvideosrc_create => pts %" GST_TIME_FORMAT " duration %" @@ -998,7 +1053,12 @@ gst_dshowvideosrc_push_buffer (byte * buffer, long size, byte * src_object, /* the negotiate() method already set caps on the source pad */ gst_buffer_set_caps (buf, GST_PAD_CAPS (GST_BASE_SRC_PAD (src))); - g_async_queue_push (src->async_queue, buf); + g_mutex_lock (src->buffer_mutex); + if (src->buffer != NULL) + gst_buffer_unref (src->buffer); + src->buffer = buf; + g_cond_signal (src->buffer_cond); + g_mutex_unlock (src->buffer_mutex); return TRUE; } diff --git a/sys/dshowsrcwrapper/gstdshowvideosrc.h b/sys/dshowsrcwrapper/gstdshowvideosrc.h index 994326fdcc..8bc52fa903 100644 --- a/sys/dshowsrcwrapper/gstdshowvideosrc.h +++ b/sys/dshowsrcwrapper/gstdshowvideosrc.h @@ -66,8 +66,11 @@ struct _GstDshowVideoSrc IMediaFilter *media_filter; IFilterGraph *filter_graph; - /* async queue which will contain incoming buffers from directshow */ - GAsyncQueue *async_queue; + /* the last buffer from DirectShow */ + GCond * buffer_cond; + GMutex * buffer_mutex; + GstBuffer * buffer; + gboolean stop_requested; gboolean is_rgb; gint width;