From 4d72ec2a4da4427ef632fd04387df3626163903e Mon Sep 17 00:00:00 2001
From: Benjamin Otte <otte@gnome.org>
Date: Wed, 14 Oct 2009 17:38:36 +0200
Subject: [PATCH 11/12] Port video to use gstreamer-cairo

---
 .../graphics/gtk/MediaPlayerPrivateGStreamer.cpp   |   64 +++++++------------
 .../platform/graphics/gtk/VideoSinkGStreamer.cpp   |   35 +++++++----
 configure.ac                                       |    2 +-
 3 files changed, 48 insertions(+), 53 deletions(-)

diff --git a/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp b/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp
index 61a88ee..9dc402a 100644
--- a/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp
+++ b/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp
@@ -39,10 +39,10 @@
 #include "Widget.h"
 #include "TimeRanges.h"
 
+#include <gst/cairo/gstcairo.h>
 #include <gst/gst.h>
 #include <gst/interfaces/mixer.h>
 #include <gst/interfaces/xoverlay.h>
-#include <gst/video/video.h>
 #include <limits>
 #include <math.h>
 #include <wtf/GOwnPtr.h>
@@ -215,7 +215,7 @@ float MediaPlayerPrivate::duration() const
 
     if (!gst_element_query_duration(m_playBin, &timeFormat, &timeLength) ||
         timeFormat != GST_FORMAT_TIME ||
-        timeLength == GST_CLOCK_TIME_NONE) {
+        timeLength == (gint64) GST_CLOCK_TIME_NONE) {
         LOG_VERBOSE(Media, "Time duration query failed.");
         return numeric_limits<float>::infinity();
     }
@@ -319,20 +319,20 @@ IntSize MediaPlayerPrivate::naturalSize() const
     // https://bugzilla.gnome.org/show_bug.cgi?id=596326
     int width = 0, height = 0;
     if (GstPad* pad = gst_element_get_static_pad(m_videoSink, "sink")) {
-        GstCaps* caps = GST_PAD_CAPS(pad);
-        gfloat pixelAspectRatio;
-        gint pixelAspectRatioNumerator, pixelAspectRatioDenominator;
-
-        if (!gst_video_format_parse_caps(caps, NULL, &width, &height) ||
-            !gst_video_parse_caps_pixel_aspect_ratio(caps, &pixelAspectRatioNumerator,
-                                                           &pixelAspectRatioDenominator)) {
+        GstCaps *caps = GST_PAD_CAPS (pad);
+        if (caps == NULL || !gst_caps_is_fixed(caps)) {
             gst_object_unref(GST_OBJECT(pad));
             return IntSize();
         }
+        gfloat pixelAspectRatio;
+        gint pixelAspectRatioNumerator, pixelAspectRatioDenominator;
+        
+        GstCairoFormat *format = gst_cairo_format_new(caps);
+        gst_cairo_format_get_pixel_aspect_ratio (format, &pixelAspectRatioNumerator, &pixelAspectRatioDenominator);
 
         pixelAspectRatio = (gfloat) pixelAspectRatioNumerator / (gfloat) pixelAspectRatioDenominator;
-        width *= pixelAspectRatio;
-        height /= pixelAspectRatio;
+        width = gst_cairo_format_get_width(format) * pixelAspectRatio;
+        height = gst_cairo_format_get_height(format) / pixelAspectRatio;
         gst_object_unref(GST_OBJECT(pad));
     }
 
@@ -643,33 +643,17 @@ void MediaPlayerPrivate::paint(GraphicsContext* context, const IntRect& rect)
     if (!m_buffer)
         return;
 
-    int width = 0, height = 0;
-    int pixelAspectRatioNumerator = 0;
-    int pixelAspectRatioDenominator = 0;
-    double doublePixelAspectRatioNumerator = 0;
-    double doublePixelAspectRatioDenominator = 0;
-    double displayWidth;
-    double displayHeight;
-    double scale, gapHeight, gapWidth;
-
-    GstCaps *caps = gst_buffer_get_caps(m_buffer);
-
-    if (!gst_video_format_parse_caps(caps, NULL, &width, &height) ||
-        !gst_video_parse_caps_pixel_aspect_ratio(caps, &pixelAspectRatioNumerator, &pixelAspectRatioDenominator)) {
-      gst_caps_unref(caps);
-      return;
-    }
+    GstCairoFormat *format = gst_cairo_format_new (GST_BUFFER_CAPS (m_buffer));
 
-    displayWidth = width;
-    displayHeight = height;
-    doublePixelAspectRatioNumerator = pixelAspectRatioNumerator;
-    doublePixelAspectRatioDenominator = pixelAspectRatioDenominator;
+    double displayWidth = gst_cairo_format_get_width (format);
+    double displayHeight = gst_cairo_format_get_height (format);
+    int pixelAspectRatioNumerator, pixelAspectRatioDenominator;
+    gst_cairo_format_get_pixel_aspect_ratio (format, &pixelAspectRatioNumerator, &pixelAspectRatioDenominator);
+    double doublePixelAspectRatioNumerator = pixelAspectRatioNumerator;
+    double doublePixelAspectRatioDenominator = pixelAspectRatioDenominator;
 
     cairo_t* cr = context->platformContext();
-    cairo_surface_t* src = cairo_image_surface_create_for_data(GST_BUFFER_DATA(m_buffer),
-                                                               CAIRO_FORMAT_RGB24,
-                                                               width, height,
-                                                               4 * width);
+    cairo_surface_t* src = gst_cairo_create_similar_surface (m_buffer, cairo_get_target (cr), format);
 
     cairo_save(cr);
     cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
@@ -677,13 +661,13 @@ void MediaPlayerPrivate::paint(GraphicsContext* context, const IntRect& rect)
     displayWidth *= doublePixelAspectRatioNumerator / doublePixelAspectRatioDenominator;
     displayHeight *= doublePixelAspectRatioDenominator / doublePixelAspectRatioNumerator;
 
-    scale = MIN (rect.width () / displayWidth, rect.height () / displayHeight);
+    double scale = MIN (rect.width () / displayWidth, rect.height () / displayHeight);
     displayWidth *= scale;
     displayHeight *= scale;
 
-    // Calculate gap between border an picture
-    gapWidth = (rect.width() - displayWidth) / 2.0;
-    gapHeight = (rect.height() - displayHeight) / 2.0;
+    // Calculate gap between border and picture
+    double gapWidth = (rect.width() - displayWidth) / 2.0;
+    double gapHeight = (rect.height() - displayHeight) / 2.0;
 
     // paint the rectangle on the context and draw the surface inside.
     cairo_translate(cr, rect.x() + gapWidth, rect.y() + gapHeight);
@@ -696,7 +680,7 @@ void MediaPlayerPrivate::paint(GraphicsContext* context, const IntRect& rect)
     cairo_restore(cr);
 
     cairo_surface_destroy(src);
-    gst_caps_unref(caps);
+    gst_cairo_format_free(format);
 }
 
 static HashSet<String> mimeTypeCache()
diff --git a/WebCore/platform/graphics/gtk/VideoSinkGStreamer.cpp b/WebCore/platform/graphics/gtk/VideoSinkGStreamer.cpp
index 614431f..a7ec748 100644
--- a/WebCore/platform/graphics/gtk/VideoSinkGStreamer.cpp
+++ b/WebCore/platform/graphics/gtk/VideoSinkGStreamer.cpp
@@ -30,18 +30,9 @@
 #include "VideoSinkGStreamer.h"
 
 #include <glib.h>
+#include <gdk/gdk.h>
 #include <gst/gst.h>
-#include <gst/video/video.h>
-
-static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE("sink",
-                                                                   GST_PAD_SINK, GST_PAD_ALWAYS,
-// CAIRO_FORMAT_RGB24 used to render the video buffers is little/big endian dependant.
-#if G_BYTE_ORDER == G_LITTLE_ENDIAN
-                                                                   GST_STATIC_CAPS(GST_VIDEO_CAPS_BGRx)
-#else
-                                                                   GST_STATIC_CAPS(GST_VIDEO_CAPS_xRGB)
-#endif
-);
+#include <gst/cairo/gstcairo.h>
 
 GST_DEBUG_CATEGORY_STATIC(webkit_video_sink_debug);
 #define GST_CAT_DEFAULT webkit_video_sink_debug
@@ -81,7 +72,8 @@ webkit_video_sink_base_init(gpointer g_class)
 {
     GstElementClass* element_class = GST_ELEMENT_CLASS(g_class);
 
-    gst_element_class_add_pad_template(element_class, gst_static_pad_template_get(&sinktemplate));
+    gst_element_class_add_pad_template(element_class, 
+        gst_cairo_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS));
     gst_element_class_set_details_simple(element_class, "WebKit video sink",
         "Sink/Video", "Sends video data from a GStreamer pipeline to a Cairo surface",
         "Alp Toker <alp@atoker.com>, Benjamin Otte <ote@gnome.org>");
@@ -198,6 +190,24 @@ webkit_video_sink_stop(GstBaseSink* base_sink)
     return TRUE;
 }
 
+static GstFlowReturn
+webkit_video_sink_buffer_alloc (GstBaseSink * bsink, guint64 offset,
+    guint size, GstCaps * caps, GstBuffer ** buf)
+{
+  GstCairoFormat *format;
+
+  format = gst_cairo_format_new (caps);
+  if (gst_cairo_format_is_native (format)) {
+    //These functions should be threadsafe - if not, use gdk_threads_enter/leave()
+    cairo_t *cr = gdk_cairo_create (gdk_get_default_root_window ());
+    *buf = gst_cairo_buffer_new_similar (cairo_get_target (cr), format);
+    cairo_destroy (cr);
+  }
+  gst_cairo_format_free (format);
+
+  return GST_FLOW_OK;
+}
+
 static void
 marshal_VOID__MINIOBJECT(GClosure * closure, GValue * return_value,
                          guint n_param_values, const GValue * param_values,
@@ -236,6 +246,7 @@ webkit_video_sink_class_init(WebKitVideoSinkClass* klass)
     gstbase_sink_class->render = webkit_video_sink_render;
     gstbase_sink_class->preroll = webkit_video_sink_render;
     gstbase_sink_class->stop = webkit_video_sink_stop;
+    gstbase_sink_class->buffer_alloc = webkit_video_sink_buffer_alloc;
 
     webkit_video_sink_signals[REPAINT_REQUESTED] = g_signal_new("repaint-requested",
             G_TYPE_FROM_CLASS(klass),
diff --git a/configure.ac b/configure.ac
index 7638a34..0c553de 100644
--- a/configure.ac
+++ b/configure.ac
@@ -690,7 +690,7 @@ if test "$enable_video" = "yes"; then
                      gstreamer-base-0.10
                      gstreamer-pbutils-0.10
                      gstreamer-plugins-base-0.10
-                     gstreamer-video-0.10])
+                     gstreamer-cairo-0.10])
    AC_SUBST([GSTREAMER_CFLAGS])
    AC_SUBST([GSTREAMER_LIBS])
 fi
-- 
1.6.3.3

