Changeset 50284 in webkit


Ignore:
Timestamp:
Oct 29, 2009 10:50:49 AM (15 years ago)
Author:
eric@webkit.org
Message:

2009-10-29 Sebastian Dröge <sebastian.droege@collabora.co.uk>

Reviewed by Gustavo Noronha.

https://bugs.webkit.org/show_bug.cgi?id=30308

Add support for ARGB videos.

  • platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp: (WebCore::MediaPlayerPrivate::paint): Create the Cairo image surface for ARGB32 or RGB24 depending on the buffer's caps.
  • platform/graphics/gtk/VideoSinkGStreamer.cpp: (webkit_video_sink_timeout_func): (webkit_video_sink_render): Handle ARGB video and convert GStreamer's ARGB to Cairo's for displaying.
Location:
trunk/WebCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r50283 r50284  
     12009-10-29  Sebastian Dröge  <sebastian.droege@collabora.co.uk>
     2
     3        Reviewed by Gustavo Noronha.
     4
     5        https://bugs.webkit.org/show_bug.cgi?id=30308
     6       
     7        Add support for ARGB videos.
     8
     9        * platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp:
     10        (WebCore::MediaPlayerPrivate::paint):
     11        Create the Cairo image surface for ARGB32 or RGB24
     12        depending on the buffer's caps.
     13       
     14        * platform/graphics/gtk/VideoSinkGStreamer.cpp:
     15        (webkit_video_sink_timeout_func):
     16        (webkit_video_sink_render):
     17        Handle ARGB video and convert GStreamer's ARGB to
     18        Cairo's for displaying.
     19
    1202009-10-29  Anton Muhin  <antonm@chromium.org>
    221
  • trunk/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp

    r50122 r50284  
    632632    double displayHeight;
    633633    double scale, gapHeight, gapWidth;
     634    GstVideoFormat format;
    634635
    635636    GstCaps *caps = gst_buffer_get_caps(m_buffer);
    636637
    637     if (!gst_video_format_parse_caps(caps, NULL, &width, &height) ||
    638         !gst_video_parse_caps_pixel_aspect_ratio(caps, &pixelAspectRatioNumerator, &pixelAspectRatioDenominator)) {
     638    if (G_UNLIKELY(!gst_video_format_parse_caps(caps, &format, &width, &height) ||
     639        !gst_video_parse_caps_pixel_aspect_ratio(caps, &pixelAspectRatioNumerator, &pixelAspectRatioDenominator))) {
    639640      gst_caps_unref(caps);
    640641      return;
     
    646647    doublePixelAspectRatioDenominator = pixelAspectRatioDenominator;
    647648
     649    cairo_format_t cairoFormat;
     650    if (format == GST_VIDEO_FORMAT_ARGB || format == GST_VIDEO_FORMAT_BGRA)
     651        cairoFormat = CAIRO_FORMAT_ARGB32;
     652    else
     653        cairoFormat = CAIRO_FORMAT_RGB24;
     654
    648655    cairo_t* cr = context->platformContext();
    649656    cairo_surface_t* src = cairo_image_surface_create_for_data(GST_BUFFER_DATA(m_buffer),
    650                                                                CAIRO_FORMAT_RGB24,
     657                                                               cairoFormat,
    651658                                                               width, height,
    652659                                                               4 * width);
  • trunk/WebCore/platform/graphics/gtk/VideoSinkGStreamer.cpp

    r49623 r50284  
    3838// CAIRO_FORMAT_RGB24 used to render the video buffers is little/big endian dependant.
    3939#if G_BYTE_ORDER == G_LITTLE_ENDIAN
    40                                                                    GST_STATIC_CAPS(GST_VIDEO_CAPS_BGRx)
     40                                                                   GST_STATIC_CAPS(GST_VIDEO_CAPS_BGRx ";" GST_VIDEO_CAPS_BGRA)
    4141#else
    42                                                                    GST_STATIC_CAPS(GST_VIDEO_CAPS_xRGB)
     42                                                                   GST_STATIC_CAPS(GST_VIDEO_CAPS_xRGB ";" GST_VIDEO_CAPS_ARGB)
    4343#endif
    4444);
     
    130130    }
    131131
    132     if (G_UNLIKELY(!GST_BUFFER_CAPS(buffer))) {
    133         buffer = gst_buffer_make_metadata_writable(buffer);
    134         gst_buffer_set_caps(buffer, GST_PAD_CAPS(GST_BASE_SINK_PAD(sink)));
    135     }
    136 
    137132    g_signal_emit(sink, webkit_video_sink_signals[REPAINT_REQUESTED], 0, buffer);
    138133    gst_buffer_unref(buffer);
     
    157152
    158153    priv->buffer = gst_buffer_ref(buffer);
     154
     155    // For the unlikely case where the buffer has no caps, the caps
     156    // are implicitely the caps of the pad. This shouldn't happen.
     157    if (G_UNLIKELY(!GST_BUFFER_CAPS(buffer))) {
     158        buffer = priv->buffer = gst_buffer_make_metadata_writable(priv->buffer);
     159        gst_buffer_set_caps(priv->buffer, GST_PAD_CAPS(GST_BASE_SINK_PAD(bsink)));
     160    }
     161
     162    GstCaps *caps = GST_BUFFER_CAPS(buffer);
     163    GstVideoFormat format;
     164    int width, height;
     165    if (G_UNLIKELY(!gst_video_format_parse_caps(caps, &format, &width, &height))) {
     166        gst_buffer_unref(buffer);
     167        g_mutex_unlock(priv->buffer_mutex);
     168        return GST_FLOW_ERROR;
     169    }
     170
     171    // Cairo's ARGB has pre-multiplied alpha while GStreamer's doesn't.
     172    // Here we convert to Cairo's ARGB.
     173    if (format == GST_VIDEO_FORMAT_ARGB || format == GST_VIDEO_FORMAT_BGRA) {
     174        // Because GstBaseSink::render() only owns the buffer reference in the
     175        // method scope we can't use gst_buffer_make_writable() here. Also
     176        // The buffer content should not be changed here because the same buffer
     177        // could be passed multiple times to this method (in theory)
     178        GstBuffer *newBuffer = gst_buffer_try_new_and_alloc(GST_BUFFER_SIZE(buffer));
     179
     180        // Check if allocation failed
     181        if (G_UNLIKELY(!newBuffer)) {
     182            gst_buffer_unref(buffer);
     183            g_mutex_unlock(priv->buffer_mutex);
     184            return GST_FLOW_ERROR;
     185        }
     186
     187        gst_buffer_copy_metadata(newBuffer, buffer, (GstBufferCopyFlags) GST_BUFFER_COPY_ALL);
     188
     189        // We don't use Color::premultipliedARGBFromColor() here because
     190        // one function call per video pixel is just too expensive:
     191        // For 720p/PAL for example this means 1280*720*25=23040000
     192        // function calls per second!
     193        unsigned short alpha;
     194        const guint8 *source = GST_BUFFER_DATA(buffer);
     195        guint8 *destination = GST_BUFFER_DATA(newBuffer);
     196
     197        for (int x = 0; x < height; x++) {
     198            for (int y = 0; y < width; y++) {
     199#if G_BYTE_ORDER == G_LITTLE_ENDIAN
     200                alpha = source[3];
     201                destination[0] = (source[0] * alpha + 128) / 255;
     202                destination[1] = (source[1] * alpha + 128) / 255;
     203                destination[2] = (source[2] * alpha + 128) / 255;
     204                destination[3] = alpha;
     205#else
     206                alpha = source[0];
     207                destination[0] = alpha;
     208                destination[1] = (source[1] * alpha + 128) / 255;
     209                destination[2] = (source[2] * alpha + 128) / 255;
     210                destination[3] = (source[3] * alpha + 128) / 255;
     211#endif
     212                source += 4;
     213                destination += 4;
     214            }
     215        }
     216        gst_buffer_unref(buffer);
     217        buffer = priv->buffer = newBuffer;
     218    }
    159219
    160220    // Use HIGH_IDLE+20 priority, like Gtk+ for redrawing operations.
Note: See TracChangeset for help on using the changeset viewer.