Changeset 49401 in webkit


Ignore:
Timestamp:
Oct 9, 2009 12:37:40 PM (15 years ago)
Author:
eric@webkit.org
Message:

2009-10-09 Philippe Normand <pnormand@igalia.com>

Reviewed by Gustavo Noronha.

[GTK] QoS support in the video sink
https://bugs.webkit.org/show_bug.cgi?id=29959

Removed the async buffer queue from the sink. Synchronize the
render method of the sink using a g_timeout_add() combined with a
gcond triggered when the buffer has been rendered.
Also fixed the video sink reference handling in the player, now
that the idle is not there anymore to mess up things.

  • platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp: (WebCore::MediaPlayerPrivate::~MediaPlayerPrivate): (WebCore::MediaPlayerPrivate::createGSTPlayBin):
  • platform/graphics/gtk/VideoSinkGStreamer.cpp: (webkit_video_sink_init): (webkit_video_sink_timeout_func): (webkit_video_sink_render): (webkit_video_sink_dispose): (unlock_buffer_mutex): (webkit_video_sink_unlock): (webkit_video_sink_stop): (webkit_video_sink_class_init):
Location:
trunk/WebCore
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r49400 r49401  
     12009-10-09  Philippe Normand  <pnormand@igalia.com>
     2
     3        Reviewed by Gustavo Noronha.
     4
     5        [GTK] QoS support in the video sink
     6        https://bugs.webkit.org/show_bug.cgi?id=29959
     7
     8        Removed the async buffer queue from the sink. Synchronize the
     9        render method of the sink using a g_timeout_add() combined with a
     10        gcond triggered when the buffer has been rendered.
     11        Also fixed the video sink reference handling in the player, now
     12        that the idle is not there anymore to mess up things.
     13
     14        * platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp:
     15        (WebCore::MediaPlayerPrivate::~MediaPlayerPrivate):
     16        (WebCore::MediaPlayerPrivate::createGSTPlayBin):
     17        * platform/graphics/gtk/VideoSinkGStreamer.cpp:
     18        (webkit_video_sink_init):
     19        (webkit_video_sink_timeout_func):
     20        (webkit_video_sink_render):
     21        (webkit_video_sink_dispose):
     22        (unlock_buffer_mutex):
     23        (webkit_video_sink_unlock):
     24        (webkit_video_sink_stop):
     25        (webkit_video_sink_class_init):
     26
    1272009-10-09  Dirk Schulze  <krit@webkit.org>
    228
  • trunk/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp

    r49019 r49401  
    159159}
    160160
    161 static gboolean idleUnref(gpointer data)
    162 {
    163     g_object_unref(reinterpret_cast<GObject*>(data));
    164     return FALSE;
    165 }
    166 
    167161MediaPlayerPrivate::~MediaPlayerPrivate()
    168162{
     
    175169    }
    176170
    177     // FIXME: We should find a better way to handle the lifetime of this object; this is
    178     // needed because the object is sometimes being destroyed inbetween a call to
    179     // webkit_video_sink_render, and the idle it schedules. Adding a ref in
    180     // webkit_video_sink_render that would be balanced by the idle is not an option,
    181     // because in some cases the destruction of the sink may happen in time for the idle
    182     // to be removed from the queue, so it may not run. It would also cause lots of ref
    183     // counting churn (render/idle are called many times). This is an ugly race.
    184171    if (m_videoSink) {
    185         g_idle_add(idleUnref, m_videoSink);
     172        g_object_unref(m_videoSink);
    186173        m_videoSink = 0;
    187174    }
     
    816803    m_videoSink = webkit_video_sink_new(m_surface);
    817804
    818     // This ref is to protect the sink from being destroyed before we stop the idle it
    819     // creates internally. See the comment in ~MediaPlayerPrivate.
    820     g_object_ref(m_videoSink);
    821 
     805    g_object_ref_sink(m_videoSink);
    822806    g_object_set(m_playBin, "video-sink", m_videoSink, NULL);
    823807
  • trunk/WebCore/platform/graphics/gtk/VideoSinkGStreamer.cpp

    r49176 r49401  
    6666struct _WebKitVideoSinkPrivate {
    6767    cairo_surface_t* surface;
    68     GAsyncQueue* async_queue;
    6968    gboolean rgb_ordering;
    7069    int width;
     
    7473    int par_n;
    7574    int par_d;
     75    GstBuffer* buffer;
     76    guint timeout_id;
     77    GMutex* buffer_mutex;
     78    GCond* data_cond;
    7679};
    7780
     
    8487GST_BOILERPLATE_FULL(WebKitVideoSink,
    8588                     webkit_video_sink,
    86                      GstBaseSink,
    87                      GST_TYPE_BASE_SINK,
     89                     GstVideoSink,
     90                     GST_TYPE_VIDEO_SINK,
    8891                     _do_init);
    8992
     
    103106
    104107    sink->priv = priv = G_TYPE_INSTANCE_GET_PRIVATE(sink, WEBKIT_TYPE_VIDEO_SINK, WebKitVideoSinkPrivate);
    105     priv->async_queue = g_async_queue_new();
     108    priv->data_cond = g_cond_new();
     109    priv->buffer_mutex = g_mutex_new();
    106110}
    107111
    108112static gboolean
    109 webkit_video_sink_idle_func(gpointer data)
     113webkit_video_sink_timeout_func(gpointer data)
    110114{
    111115    WebKitVideoSink* sink = reinterpret_cast<WebKitVideoSink*>(data);
     
    118122    gint bwidth, bheight;
    119123
    120     if (!priv->async_queue)
     124    g_mutex_lock(priv->buffer_mutex);
     125    buffer = priv->buffer;
     126    priv->timeout_id = 0;
     127
     128    if (!buffer || G_UNLIKELY(!GST_IS_BUFFER(buffer))) {
     129        g_cond_signal(priv->data_cond);
     130        g_mutex_unlock(priv->buffer_mutex);
    121131        return FALSE;
    122 
    123     buffer = (GstBuffer*)g_async_queue_try_pop(priv->async_queue);
    124     if (!buffer || G_UNLIKELY(!GST_IS_BUFFER(buffer)))
    125         return FALSE;
     132    }
    126133
    127134    caps = GST_BUFFER_CAPS(buffer);
     
    129136        GST_ERROR_OBJECT(sink, "Unknown video format in buffer caps '%s'",
    130137                         gst_caps_to_string(caps));
     138        g_cond_signal(priv->data_cond);
     139        g_mutex_unlock(priv->buffer_mutex);
    131140        return FALSE;
    132141    }
     
    137146    par = (gfloat) par_n / (gfloat) par_d;
    138147
    139     // TODO: consider priv->rgb_ordering?
    140148    cairo_surface_t* src = cairo_image_surface_create_for_data(GST_BUFFER_DATA(buffer),
    141149                                                               CAIRO_FORMAT_RGB24,
     
    152160    cairo_fill(cr);
    153161    cairo_destroy(cr);
     162
    154163    gst_buffer_unref(buffer);
    155     g_async_queue_unref(priv->async_queue);
     164    priv->buffer = 0;
    156165
    157166    g_signal_emit(sink, webkit_video_sink_signals[REPAINT_REQUESTED], 0);
     167    g_cond_signal(priv->data_cond);
     168    g_mutex_unlock(priv->buffer_mutex);
    158169
    159170    return FALSE;
     
    166177    WebKitVideoSinkPrivate* priv = sink->priv;
    167178
    168     g_async_queue_ref(priv->async_queue);
    169     g_async_queue_push(priv->async_queue, gst_buffer_ref(buffer));
    170     g_idle_add_full(G_PRIORITY_HIGH_IDLE, webkit_video_sink_idle_func, sink, 0);
    171 
     179    g_mutex_lock(priv->buffer_mutex);
     180    priv->buffer = gst_buffer_ref(buffer);
     181
     182    // Use HIGH_IDLE+20 priority, like Gtk+ for redrawing operations.
     183    priv->timeout_id = g_timeout_add_full(G_PRIORITY_HIGH_IDLE + 20, 0,
     184                                          webkit_video_sink_timeout_func,
     185                                          gst_object_ref(sink),
     186                                          (GDestroyNotify)gst_object_unref);
     187
     188    g_cond_wait(priv->data_cond, priv->buffer_mutex);
     189    g_mutex_unlock(priv->buffer_mutex);
    172190    return GST_FLOW_OK;
    173191}
     
    226244    }
    227245
    228     if (priv->async_queue) {
    229         g_async_queue_unref(priv->async_queue);
    230         priv->async_queue = 0;
     246    if (priv->data_cond) {
     247        g_cond_free(priv->data_cond);
     248        priv->data_cond = 0;
     249    }
     250
     251    if (priv->buffer_mutex) {
     252        g_mutex_free(priv->buffer_mutex);
     253        priv->buffer_mutex = 0;
    231254    }
    232255
     
    235258
    236259static void
    237 webkit_video_sink_finalize(GObject* object)
    238 {
    239     G_OBJECT_CLASS(parent_class)->finalize(object);
     260unlock_buffer_mutex(WebKitVideoSinkPrivate* priv)
     261{
     262    g_mutex_lock(priv->buffer_mutex);
     263
     264    if (priv->buffer) {
     265        gst_buffer_unref(priv->buffer);
     266        priv->buffer = 0;
     267    }
     268
     269    g_cond_signal(priv->data_cond);
     270    g_mutex_unlock(priv->buffer_mutex);
     271
     272}
     273
     274static gboolean
     275webkit_video_sink_unlock(GstBaseSink* object)
     276{
     277    WebKitVideoSink* sink = WEBKIT_VIDEO_SINK(object);
     278    unlock_buffer_mutex(sink->priv);
     279    GST_CALL_PARENT_WITH_DEFAULT(GST_BASE_SINK_CLASS, unlock,
     280                                 (object), TRUE);
    240281}
    241282
     
    277318{
    278319    WebKitVideoSinkPrivate* priv = WEBKIT_VIDEO_SINK(base_sink)->priv;
    279 
    280     g_async_queue_lock(priv->async_queue);
    281 
    282     /* Remove all remaining objects from the queue */
    283     while (GstBuffer* buffer = (GstBuffer*)g_async_queue_try_pop_unlocked(priv->async_queue))
    284         gst_buffer_unref(buffer);
    285 
    286     g_async_queue_unlock(priv->async_queue);
    287 
    288     g_idle_remove_by_data(base_sink);
    289 
     320    unlock_buffer_mutex(priv);
    290321    return TRUE;
    291322}
     
    303334
    304335    gobject_class->dispose = webkit_video_sink_dispose;
    305     gobject_class->finalize = webkit_video_sink_finalize;
    306 
     336
     337    gstbase_sink_class->unlock = webkit_video_sink_unlock;
    307338    gstbase_sink_class->render = webkit_video_sink_render;
    308339    gstbase_sink_class->preroll = webkit_video_sink_render;
  • trunk/WebCore/platform/graphics/gtk/VideoSinkGStreamer.h

    r46587 r49401  
    2323#include <cairo.h>
    2424#include <glib-object.h>
    25 #include <gst/base/gstbasesink.h>
     25#include <gst/video/gstvideosink.h>
    2626
    2727G_BEGIN_DECLS
     
    5555struct _WebKitVideoSink {
    5656    /*< private >*/
    57     GstBaseSink parent;
     57    GstVideoSink parent;
    5858    WebKitVideoSinkPrivate *priv;
    5959};
     
    6161struct _WebKitVideoSinkClass {
    6262    /*< private >*/
    63     GstBaseSinkClass parent_class;
     63    GstVideoSinkClass parent_class;
    6464
    6565    /* Future padding */
Note: See TracChangeset for help on using the changeset viewer.