From 6a747e2e290101d7aafc24b9c8d3b8ba44eddbae Mon Sep 17 00:00:00 2001 From: Philippe Normand Date: Fri, 2 Oct 2009 11:09:12 +0200 Subject: [PATCH] sink: replace the idle with a timeout --- .../platform/graphics/gtk/VideoSinkGStreamer.cpp | 74 ++++++++++++++------ 1 files changed, 51 insertions(+), 23 deletions(-) diff --git a/WebCore/platform/graphics/gtk/VideoSinkGStreamer.cpp b/WebCore/platform/graphics/gtk/VideoSinkGStreamer.cpp index bb269cd..4cfd4d2 100644 --- a/WebCore/platform/graphics/gtk/VideoSinkGStreamer.cpp +++ b/WebCore/platform/graphics/gtk/VideoSinkGStreamer.cpp @@ -65,7 +65,6 @@ static guint webkit_video_sink_signals[LAST_SIGNAL] = { 0, }; struct _WebKitVideoSinkPrivate { cairo_surface_t* surface; - GAsyncQueue* async_queue; gboolean rgb_ordering; int width; int height; @@ -73,6 +72,14 @@ struct _WebKitVideoSinkPrivate { int fps_d; int par_n; int par_d; + GAsyncQueue* timeout_ids_async_queue; +}; + +typedef struct _TimeoutData TimeoutData; + +struct _TimeoutData { + WebKitVideoSink* sink; + GstBuffer* buffer; }; #define _do_init(bla) \ @@ -102,25 +109,26 @@ webkit_video_sink_init(WebKitVideoSink* sink, WebKitVideoSinkClass* klass) WebKitVideoSinkPrivate* priv; sink->priv = priv = G_TYPE_INSTANCE_GET_PRIVATE(sink, WEBKIT_TYPE_VIDEO_SINK, WebKitVideoSinkPrivate); - priv->async_queue = g_async_queue_new(); + priv->timeout_ids_async_queue = g_async_queue_new(); + g_object_set(sink, "render-delay", 100 * GST_MSECOND, NULL); } static gboolean -webkit_video_sink_idle_func(gpointer data) +webkit_video_sink_timeout_func(gpointer data) { - WebKitVideoSink* sink = reinterpret_cast(data); + TimeoutData* timeout_data = reinterpret_cast(data); + WebKitVideoSink* sink = timeout_data->sink; WebKitVideoSinkPrivate* priv = sink->priv; - GstBuffer* buffer; + GstBuffer* buffer = timeout_data->buffer; + guint timeout_id; GstCaps* caps; GstVideoFormat* format; gint par_n, par_d; gfloat par; gint bwidth, bheight; - if (!priv->async_queue) - return FALSE; + g_return_val_if_fail(priv->timeout_ids_async_queue, FALSE); - buffer = (GstBuffer*)g_async_queue_try_pop(priv->async_queue); if (!buffer || G_UNLIKELY(!GST_IS_BUFFER(buffer))) return FALSE; @@ -136,7 +144,6 @@ webkit_video_sink_idle_func(gpointer data) par = (gfloat) par_n / (gfloat) par_d; - // TODO: consider priv->rgb_ordering? cairo_surface_t* src = cairo_image_surface_create_for_data(GST_BUFFER_DATA(buffer), CAIRO_FORMAT_RGB24, bwidth, bheight, @@ -151,23 +158,45 @@ webkit_video_sink_idle_func(gpointer data) cairo_rectangle(cr, 0, 0, priv->width, priv->height); cairo_fill(cr); cairo_destroy(cr); - gst_buffer_unref(buffer); - g_async_queue_unref(priv->async_queue); + + timeout_id = GPOINTER_TO_UINT(g_async_queue_try_pop(priv->timeout_ids_async_queue)); + g_return_val_if_fail(timeout_id != 0, FALSE); + g_source_remove(timeout_id); g_signal_emit(sink, webkit_video_sink_signals[REPAINT_REQUESTED], 0); return FALSE; } +static void +destroy_timeout_data(gpointer data) +{ + TimeoutData* timeout_data = reinterpret_cast(data); + WebKitVideoSink* sink = timeout_data->sink; + WebKitVideoSinkPrivate* priv = sink->priv; + + gst_buffer_unref(timeout_data->buffer); + g_slice_free(TimeoutData, timeout_data); + g_async_queue_unref(priv->timeout_ids_async_queue); +} + static GstFlowReturn webkit_video_sink_render(GstBaseSink* bsink, GstBuffer* buffer) { WebKitVideoSink* sink = WEBKIT_VIDEO_SINK(bsink); WebKitVideoSinkPrivate* priv = sink->priv; + TimeoutData* data = g_slice_new(TimeoutData); + + data->sink = sink; + data->buffer = gst_buffer_ref(buffer); + + // use HIGH_IDLE+20 priority, like Gtk+ for redrawing operations + guint timeout_id = g_timeout_add_full(G_PRIORITY_HIGH_IDLE + 20, 100, + webkit_video_sink_timeout_func, + data, destroy_timeout_data); + g_async_queue_ref(priv->timeout_ids_async_queue); + g_async_queue_push(priv->timeout_ids_async_queue, GUINT_TO_POINTER(timeout_id)); - g_async_queue_ref(priv->async_queue); - g_async_queue_push(priv->async_queue, gst_buffer_ref(buffer)); - g_idle_add_full(G_PRIORITY_HIGH_IDLE, webkit_video_sink_idle_func, sink, 0); return GST_FLOW_OK; } @@ -225,9 +254,9 @@ webkit_video_sink_dispose(GObject* object) priv->surface = 0; } - if (priv->async_queue) { - g_async_queue_unref(priv->async_queue); - priv->async_queue = 0; + if (priv->timeout_ids_async_queue) { + g_async_queue_unref(priv->timeout_ids_async_queue); + priv->timeout_ids_async_queue = 0; } G_OBJECT_CLASS(parent_class)->dispose(object); @@ -277,15 +306,14 @@ webkit_video_sink_stop(GstBaseSink* base_sink) { WebKitVideoSinkPrivate* priv = WEBKIT_VIDEO_SINK(base_sink)->priv; - g_async_queue_lock(priv->async_queue); + g_async_queue_lock(priv->timeout_ids_async_queue); /* Remove all remaining objects from the queue */ - while (GstBuffer* buffer = (GstBuffer*)g_async_queue_try_pop_unlocked(priv->async_queue)) - gst_buffer_unref(buffer); - - g_async_queue_unlock(priv->async_queue); + while (guint timeout_id = GPOINTER_TO_UINT(\ + g_async_queue_try_pop_unlocked(priv->timeout_ids_async_queue))) + g_source_remove(timeout_id); - g_idle_remove_by_data(base_sink); + g_async_queue_unlock(priv->timeout_ids_async_queue); return TRUE; } -- 1.6.0.4