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;