All pastes #1586137 Raw Edit

Miscellany

public diff v1 · immutable
#1586137 ·published 2009-09-30 15:13 UTC
rendered paste body
From 120c49401838ccf14eb39fbb36e238a0c6965c9b Mon Sep 17 00:00:00 2001From: Philippe Normand <pnormand@igalia.com>Date: Wed, 30 Sep 2009 10:51:08 +0200Subject: [PATCH] GTK: data: uris support in media player--- ChangeLog                                          |   11 + LayoutTests/ChangeLog                              |   11 + LayoutTests/platform/gtk/Skipped                   |    1 - WebCore/ChangeLog                                  |   30 +++ WebCore/GNUmakefile.am                             |    7 +- .../platform/graphics/gtk/DataSourceGStreamer.cpp  |  267 ++++++++++++++++++++ .../platform/graphics/gtk/DataSourceGStreamer.h    |   54 ++++ .../graphics/gtk/MediaPlayerPrivateGStreamer.cpp   |   24 ++- configure.ac                                       |    1 + 9 files changed, 394 insertions(+), 12 deletions(-) create mode 100644 WebCore/platform/graphics/gtk/DataSourceGStreamer.cpp create mode 100644 WebCore/platform/graphics/gtk/DataSourceGStreamer.hdiff --git a/ChangeLog b/ChangeLogindex e2c1ef5..94cf2e3 100644--- a/ChangeLog+++ b/ChangeLog@@ -1,3 +1,14 @@+2009-09-30  Philippe Normand  <pnormand@igalia.com>++        Reviewed by NOBODY (OOPS!).++        [GTK] data: uri support in media player+        https://bugs.webkit.org/show_bug.cgi?id=29842++        Check presence of gstreamer-pbutils-0.10.++        * configure.ac:+ 2009-09-26  David Kilzer  <ddkilzer@apple.com>          GTK BUILD FIX: add ENABLE_ORIENTATION_EVENTS support to configure.acdiff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLogindex a5aa373..6cde74b 100644--- a/LayoutTests/ChangeLog+++ b/LayoutTests/ChangeLog@@ -1,3 +1,14 @@+2009-09-30  Philippe Normand  <pnormand@igalia.com>++        Reviewed by NOBODY (OOPS!).++        [GTK] data: uri support in media player+        https://bugs.webkit.org/show_bug.cgi?id=29842++        Re-enable media/audio-data-url.html.++        * platform/gtk/Skipped:+ 2009-09-29  Shinichiro Hamaji  <hamaji@chromium.org>          Reviewed by Eric Seidel.diff --git a/LayoutTests/platform/gtk/Skipped b/LayoutTests/platform/gtk/Skippedindex 36620ff..ef65b41 100644--- a/LayoutTests/platform/gtk/Skipped+++ b/LayoutTests/platform/gtk/Skipped@@ -3804,7 +3804,6 @@ media/video-controls-transformed.html media/video-controls-zoomed.html media/video-size-intrinsic-scale.html #   Tests timing out-media/audio-data-url.html media/controls-drag-timebar.html media/event-attributes.html media/unsupported-rtsp.htmldiff --git a/WebCore/ChangeLog b/WebCore/ChangeLogindex aacc3dc..3d4411d 100644--- a/WebCore/ChangeLog+++ b/WebCore/ChangeLog@@ -1,3 +1,33 @@+2009-09-30  Philippe Normand  <pnormand@igalia.com>++        Reviewed by NOBODY (OOPS!).++        [GTK] data: uri support in media player+        https://bugs.webkit.org/show_bug.cgi?id=29842++        New GStreamer element to handle data: uris. For now only base64+        encoded data is supported. Decoded data is handed over to+        giostreamsrc.++        * GNUmakefile.am:+        * platform/graphics/gtk/DataSourceGStreamer.cpp: Added.+        (_do_init):+        (webkit_data_src_base_init):+        (webkit_data_src_class_init):+        (webkit_data_src_reset):+        (webkit_data_src_init):+        (webkit_data_src_finalize):+        (webkit_data_src_uri_get_type):+        (webkit_data_src_uri_get_protocols):+        (webkit_data_src_uri_get_uri):+        (webkit_data_src_uri_set_uri):+        (webkit_data_src_uri_handler_init):+        * platform/graphics/gtk/DataSourceGStreamer.h: Added.+        * platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp:+        (WebCore::do_gst_init):+        (WebCore::MediaPlayerPrivate::MediaPlayerPrivate):+        (WebCore::MediaPlayerPrivate::mimeTypeCache):+ 2009-09-29  Dave Hyatt  <hyatt@apple.com>          Reviewed by Jon Honeycutt.diff --git a/WebCore/GNUmakefile.am b/WebCore/GNUmakefile.amindex 6060851..5169e5f 100644--- a/WebCore/GNUmakefile.am+++ b/WebCore/GNUmakefile.am@@ -2315,11 +2315,14 @@ webcoregtk_sources += \ 	WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp \ 	WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.h \ 	WebCore/platform/graphics/gtk/VideoSinkGStreamer.cpp \-	WebCore/platform/graphics/gtk/VideoSinkGStreamer.h+	WebCore/platform/graphics/gtk/VideoSinkGStreamer.h \+	WebCore/platform/graphics/gtk/DataSourceGStreamer.cpp \+	WebCore/platform/graphics/gtk/DataSourceGstreamer.h  webcore_libadd += \ 	-lgstinterfaces-0.10 \-	-lgstvideo-0.10+	-lgstvideo-0.10 \+	-lgstpbutils-0.10  endif # END ENABLE_VIDEO diff --git a/WebCore/platform/graphics/gtk/DataSourceGStreamer.cpp b/WebCore/platform/graphics/gtk/DataSourceGStreamer.cppnew file mode 100644index 0000000..7fe8cd6--- /dev/null+++ b/WebCore/platform/graphics/gtk/DataSourceGStreamer.cpp@@ -0,0 +1,267 @@+/*+ *  Copyright (C) 2009  Igalia S.L+ *+ *  This library is free software; you can redistribute it and/or+ *  modify it under the terms of the GNU Lesser General Public+ *  License as published by the Free Software Foundation; either+ *  version 2 of the License, or (at your option) any later version.+ *+ *  This library is distributed in the hope that it will be useful,+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU+ *  Lesser General Public License for more details.+ *+ *  You should have received a copy of the GNU Lesser General Public+ *  License along with this library; if not, write to the Free Software+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA+ */++#include "config.h"+#include "DataSourceGStreamer.h"++#include <gio/gio.h>+#include <glib.h>+#include <gst/gst.h>+#include <gst/pbutils/missing-plugins.h>++static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE("src",+                                                                   GST_PAD_SRC,+                                                                   GST_PAD_ALWAYS,+                                                                   GST_STATIC_CAPS_ANY);++GST_DEBUG_CATEGORY_STATIC(webkit_data_src_debug);+#define GST_CAT_DEFAULT webkit_data_src_debug++static void webkit_data_src_uri_handler_init(gpointer g_iface,+                                             gpointer iface_data);++static void webkit_data_src_dispose(GObject* object);+static void webkit_data_src_finalize(WebkitDataSrc* src);+static GstStateChangeReturn webkit_data_src_change_state(GstElement* element,+                                                         GstStateChange transition);++static const GInterfaceInfo urihandler_info = {+    webkit_data_src_uri_handler_init,+    0, 0+};+++static void+_do_init(GType datasrc_type)+{+    GST_DEBUG_CATEGORY_INIT(webkit_data_src_debug, "webkit_data_src", 0, "datasrc element");+    g_type_add_interface_static(datasrc_type, GST_TYPE_URI_HANDLER,+                                &urihandler_info);+}++GST_BOILERPLATE_FULL(WebkitDataSrc, webkit_data_src, GstBin, GST_TYPE_BIN, _do_init);++static void+webkit_data_src_base_init(gpointer klass)+{+    GstElementClass* element_class = GST_ELEMENT_CLASS(klass);++    gst_element_class_add_pad_template(element_class,+                                       gst_static_pad_template_get(&src_template));+    gst_element_class_set_details_simple(element_class, (gchar*) "WebKit data source element",+                                         (gchar*) "Source",+                                         (gchar*) "Handles data: uris",+                                         (gchar*) "Philippe Normand <pnormand@igalia.com>");++}++static void+webkit_data_src_class_init(WebkitDataSrcClass* klass)+{+    GObjectClass* oklass = G_OBJECT_CLASS(klass);+    GstElementClass* eklass = GST_ELEMENT_CLASS(klass);++    oklass->finalize = (GObjectFinalizeFunc) webkit_data_src_finalize;+    eklass->change_state = webkit_data_src_change_state;+}+++static gboolean+webkit_data_src_reset(WebkitDataSrc* src)+{+    GstPad* targetpad;++    if (src->kid) {+        gst_element_set_state(src->kid, GST_STATE_NULL);+        gst_bin_remove(GST_BIN(src), src->kid);+    }++    src->kid = gst_element_factory_make("giostreamsrc", "streamsrc");+    if (!src->kid) {+        GST_ERROR_OBJECT(src, "Failed to create giostreamsrc");+        return FALSE;+    }++    gst_bin_add(GST_BIN(src), src->kid);++    targetpad = gst_element_get_static_pad(src->kid, "src");+    gst_ghost_pad_set_target(GST_GHOST_PAD(src->pad), targetpad);+    gst_object_unref(targetpad);++    return TRUE;+}++static void+webkit_data_src_init(WebkitDataSrc* src,+    WebkitDataSrcClass* g_class)+{+    GstPadTemplate* pad_template = gst_static_pad_template_get(&src_template);+    src->pad = gst_ghost_pad_new_no_target_from_template("src",+                                                         pad_template);++    gst_element_add_pad(GST_ELEMENT(src), src->pad);++    webkit_data_src_reset(src);+}++static void+webkit_data_src_finalize(WebkitDataSrc* src)+{+    g_free(src->uri);++    if (src->kid) {+        GST_DEBUG_OBJECT(src, "Removing giostreamsrc element");+        gst_element_set_state(src->kid, GST_STATE_NULL);+        gst_bin_remove(GST_BIN(src), src->kid);+        src->kid = 0;+    }++    GST_CALL_PARENT(G_OBJECT_CLASS, finalize, ((GObject *)(src)));+}++static GstStateChangeReturn+webkit_data_src_change_state(GstElement* element, GstStateChange transition)+{+    GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;+    WebkitDataSrc* src = WEBKIT_DATA_SRC(element);++    switch (transition) {+    case GST_STATE_CHANGE_NULL_TO_READY:+        if (!src->kid) {+            gst_element_post_message(element,+                                     gst_missing_element_message_new(element, "giostreamsrc"));+            GST_ELEMENT_ERROR(src, CORE, MISSING_PLUGIN, (0), ("no giostreamsrc!"));+            return GST_STATE_CHANGE_FAILURE;+        }+        break;+    case GST_STATE_CHANGE_READY_TO_PAUSED:+    case GST_STATE_CHANGE_PAUSED_TO_READY:+        break;+    default:+        break;+    }++    {+        ret = GST_ELEMENT_CLASS(parent_class)->change_state(element, transition);+        if (G_UNLIKELY(ret == GST_STATE_CHANGE_FAILURE))+            return ret;+    }++    switch (transition) {+    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:+    case GST_STATE_CHANGE_PAUSED_TO_READY:+    case GST_STATE_CHANGE_READY_TO_NULL:+        break;+    default:+        break;+    }++    return ret;+}++/*** GSTURIHANDLER INTERFACE *************************************************/++static GstURIType+webkit_data_src_uri_get_type(void)+{+    return GST_URI_SRC;+}++static gchar **+webkit_data_src_uri_get_protocols(void)+{+    static gchar* protocols[] = {(gchar*) "data", 0 };++    return protocols;+}++static const gchar *+webkit_data_src_uri_get_uri(GstURIHandler* handler)+{+    WebkitDataSrc* src = WEBKIT_DATA_SRC(handler);++    return src->uri;+}++static gboolean+webkit_data_src_uri_set_uri(GstURIHandler* handler, const gchar* uri)+{+    WebkitDataSrc* src = WEBKIT_DATA_SRC(handler);++    // URI as defined in RFC2397:+    // "data:" [ mediatype ] [ ";base64" ] "," data+    // we parse URIs like this one:+    // data:audio/3gpp;base64,AA...++    gchar** scheme_and_remains = g_strsplit(uri, ":", 2);+    gchar** mime_type_and_options = g_strsplit(scheme_and_remains[1], ";", 0);+    gint options_size = g_strv_length(mime_type_and_options);+    gchar* data = 0;+    gchar* mime_type = 0;+    gint ret = FALSE;++    // we require uris with a specified mime-type and base64-encoded+    // data. It doesn't make much sense anyway to play plain/text data+    // with very few allowed characters (as per the RFC).++    if (GST_STATE(src) >= GST_STATE_PAUSED) {+        GST_ERROR_OBJECT(src, "Element already configured. Reset it and retry");+    } else if (!options_size)+        GST_ERROR_OBJECT(src, "A mime-type is needed in %s", uri);+    else {+        mime_type = mime_type_and_options[0];+        data = mime_type_and_options[options_size-1];++        guchar* decoded_data = 0;+        gsize decoded_size;++        if (!g_str_has_prefix(data, "base64"))+            GST_ERROR_OBJECT(src, "Data has to be base64-encoded in %s", uri);+        else {+            decoded_data = g_base64_decode(data+7, &decoded_size);+            GInputStream* stream = g_memory_input_stream_new_from_data(decoded_data,+                                                                       decoded_size,+                                                                       g_free);+            g_object_set(src->kid, "stream", stream, 0);+            g_object_unref(stream);++            if (src->uri) {+                g_free(src->uri);+                src->uri = 0;+            }++            src->uri = g_strdup(uri);+            ret = TRUE;+        }+    }++    g_strfreev(scheme_and_remains);+    g_strfreev(mime_type_and_options);+    return ret;+}++static void+webkit_data_src_uri_handler_init(gpointer g_iface, gpointer iface_data)+{+    GstURIHandlerInterface* iface = (GstURIHandlerInterface *) g_iface;++    iface->get_type = webkit_data_src_uri_get_type;+    iface->get_protocols = webkit_data_src_uri_get_protocols;+    iface->get_uri = webkit_data_src_uri_get_uri;+    iface->set_uri = webkit_data_src_uri_set_uri;+}diff --git a/WebCore/platform/graphics/gtk/DataSourceGStreamer.h b/WebCore/platform/graphics/gtk/DataSourceGStreamer.hnew file mode 100644index 0000000..a9532fe--- /dev/null+++ b/WebCore/platform/graphics/gtk/DataSourceGStreamer.h@@ -0,0 +1,54 @@+/*+ *  Copyright (C) 2009  Igalia S.L+ *+ *  This library is free software; you can redistribute it and/or+ *  modify it under the terms of the GNU Lesser General Public+ *  License as published by the Free Software Foundation; either+ *  version 2 of the License, or (at your option) any later version.+ *+ *  This library is distributed in the hope that it will be useful,+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU+ *  Lesser General Public License for more details.+ *+ *  You should have received a copy of the GNU Lesser General Public+ *  License along with this library; if not, write to the Free Software+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA+ */++#ifndef DATA_SOURCE_GSTREAMER_H+#define DATA_SOURCE_GSTREAMER_H++#include <glib-object.h>+#include <gst/base/gstbasesrc.h>++G_BEGIN_DECLS++#define WEBKIT_TYPE_DATA_SRC            (webkit_data_src_get_type ())+#define WEBKIT_DATA_SRC(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), WEBKIT_TYPE_DATA_SRC, WebkitDataSrc))+#define WEBKIT_DATA_SRC_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), WEBKIT_TYPE_DATA_SRC, WebkitDataSrcClass))+#define WEBKIT_IS_DATA_SRC(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), WEBKIT_TYPE_DATA_SRC))+#define WEBKIT_IS_DATA_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), WEBKIT_TYPE_DATA_SRC))++typedef struct _WebkitDataSrc        WebkitDataSrc;+typedef struct _WebkitDataSrcClass   WebkitDataSrcClass;+++struct _WebkitDataSrc {+    GstBin parent;++    /* explicit pointers to stuff used */+    GstElement* kid;+    GstPad* pad;+    gchar* uri;+};++struct _WebkitDataSrcClass {+    GstBinClass parent_class;+};++GType webkit_data_src_get_type(void);++G_END_DECLS++#endifdiff --git a/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp b/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.cppindex 00d8242..64c41d1 100644--- a/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp+++ b/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp@@ -25,6 +25,7 @@ #if ENABLE(VIDEO)  #include "MediaPlayerPrivateGStreamer.h"+#include "DataSourceGStreamer.h"  #include "CString.h" #include "GraphicsContext.h"@@ -122,6 +123,17 @@ void MediaPlayerPrivate::registerMediaEngine(MediaEngineRegistrar registrar)  static bool gstInitialized = false; +static void do_gst_init() {+    // FIXME: We should pass the arguments from the command line+    if (!gstInitialized) {+        gst_init(0, 0);+        gstInitialized = true;+        gst_element_register(0, "webkitmediasrc", GST_RANK_PRIMARY,+                             WEBKIT_TYPE_DATA_SRC);++    }+}+ MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player)     : m_player(player)     , m_playBin(0)@@ -140,11 +152,7 @@ MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player)     , m_seeking(false)     , m_errorOccured(false) {-    // FIXME: We should pass the arguments from the command line-    if (!gstInitialized) {-        gst_init(0, 0);-        gstInitialized = true;-    }+    do_gst_init();      // FIXME: The size shouldn't be fixed here, this is just a quick hack.     m_surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 640, 480);@@ -652,10 +660,8 @@ void MediaPlayerPrivate::paint(GraphicsContext* context, const IntRect& rect)  static HashSet<String> mimeTypeCache() {-    if (!gstInitialized) {-        gst_init(0, NULL);-        gstInitialized = true;-    }++    do_gst_init();      static HashSet<String> cache;     static bool typeListInitialized = false;diff --git a/configure.ac b/configure.acindex a65c65d..1096dc4 100644--- a/configure.ac+++ b/configure.ac@@ -680,6 +680,7 @@ if test "$enable_video" = "yes"; then    PKG_CHECK_MODULES([GSTREAMER],                      [gstreamer-0.10 >= $GSTREAMER_REQUIRED_VERSION                      gstreamer-base-0.10+                     gstreamer-pbutils-0.10                      gstreamer-plugins-base-0.10                      gstreamer-video-0.10])    AC_SUBST([GSTREAMER_CFLAGS])-- 1.6.0.4