Bug 856308 - Enable GStreamer video buffer handling optimization for gstreamer versions older than 0.10.36. DONTBUILD because NPOTB r=alessandro.d,padenot
authorIvaylo Dimitrov <freemangordon@abv.bg>
Fri, 03 May 2013 16:44:54 +0200
changeset 141684 02fb8ac3f108be3bcc48a3783ccaa0a43cf79de2
parent 141683 3b2020da6f66a78fc17fc56fcf8539b96039a3cc
child 141685 6e0956c0dfe4c72ee7bad903cb3652d34605bc10
push id2579
push userakeybl@mozilla.com
push dateMon, 24 Jun 2013 18:52:47 +0000
treeherdermozilla-beta@b69b7de8a05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersalessandro
bugs856308
milestone23.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 856308 - Enable GStreamer video buffer handling optimization for gstreamer versions older than 0.10.36. DONTBUILD because NPOTB r=alessandro.d,padenot
content/media/gstreamer/GStreamerMozVideoBuffer.cpp
content/media/gstreamer/GStreamerMozVideoBuffer.h
content/media/gstreamer/GStreamerReader.cpp
content/media/gstreamer/GStreamerReader.h
content/media/gstreamer/Makefile.in
new file mode 100644
--- /dev/null
+++ b/content/media/gstreamer/GStreamerMozVideoBuffer.cpp
@@ -0,0 +1,118 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include <string.h>
+#include "GStreamerReader.h"
+#include "GStreamerMozVideoBuffer.h"
+
+namespace mozilla {
+
+static GstMozVideoBuffer *gst_moz_video_buffer_copy(GstMozVideoBuffer* self);
+static void gst_moz_video_buffer_finalize(GstMozVideoBuffer* self);
+
+G_DEFINE_TYPE(GstMozVideoBuffer, gst_moz_video_buffer, GST_TYPE_BUFFER);
+
+static void
+gst_moz_video_buffer_class_init(GstMozVideoBufferClass* klass)
+{
+  g_return_if_fail(GST_IS_MOZ_VIDEO_BUFFER_CLASS(klass));
+
+  GstMiniObjectClass *mo_class = GST_MINI_OBJECT_CLASS(klass);
+
+  mo_class->copy =(GstMiniObjectCopyFunction)gst_moz_video_buffer_copy;
+  mo_class->finalize =(GstMiniObjectFinalizeFunction)gst_moz_video_buffer_finalize;
+}
+
+static void
+gst_moz_video_buffer_init(GstMozVideoBuffer* self)
+{
+  g_return_if_fail(GST_IS_MOZ_VIDEO_BUFFER(self));
+}
+
+static void
+gst_moz_video_buffer_finalize(GstMozVideoBuffer* self)
+{
+  g_return_if_fail(GST_IS_MOZ_VIDEO_BUFFER(self));
+
+  if(self->data)
+    g_boxed_free(GST_TYPE_MOZ_VIDEO_BUFFER_DATA, self->data);
+
+  GST_MINI_OBJECT_CLASS(gst_moz_video_buffer_parent_class)->finalize(GST_MINI_OBJECT(self));
+}
+
+static GstMozVideoBuffer*
+gst_moz_video_buffer_copy(GstMozVideoBuffer* self)
+{
+  GstMozVideoBuffer* copy;
+
+  g_return_val_if_fail(GST_IS_MOZ_VIDEO_BUFFER(self), NULL);
+
+  copy = gst_moz_video_buffer_new();
+
+  /* we simply copy everything from our parent */
+  GST_BUFFER_DATA(GST_BUFFER_CAST(copy)) =
+      (guint8*)g_memdup(GST_BUFFER_DATA(GST_BUFFER_CAST(self)), GST_BUFFER_SIZE(GST_BUFFER_CAST(self)));
+
+  /* make sure it gets freed(even if the parent is subclassed, we return a
+     normal buffer) */
+  GST_BUFFER_MALLOCDATA(GST_BUFFER_CAST(copy)) = GST_BUFFER_DATA(GST_BUFFER_CAST(copy));
+  GST_BUFFER_SIZE(GST_BUFFER_CAST(copy)) = GST_BUFFER_SIZE(GST_BUFFER_CAST(self));
+
+  /* copy metadata */
+  gst_buffer_copy_metadata(GST_BUFFER_CAST(copy),
+                           GST_BUFFER_CAST(self),
+                           (GstBufferCopyFlags)GST_BUFFER_COPY_ALL);
+  /* copy videobuffer */
+  if(self->data)
+    copy->data = (GstMozVideoBufferData*)g_boxed_copy(GST_TYPE_MOZ_VIDEO_BUFFER_DATA, self->data);
+
+  return copy;
+}
+
+GstMozVideoBuffer*
+gst_moz_video_buffer_new(void)
+{
+  GstMozVideoBuffer *self;
+
+  self =(GstMozVideoBuffer*)gst_mini_object_new(GST_TYPE_MOZ_VIDEO_BUFFER);
+  self->data = nullptr;
+
+  return self;
+}
+
+void
+gst_moz_video_buffer_set_data(GstMozVideoBuffer* self, GstMozVideoBufferData* data)
+{
+  g_return_if_fail(GST_IS_MOZ_VIDEO_BUFFER(self));
+
+  self->data = data;
+}
+
+GstMozVideoBufferData*
+gst_moz_video_buffer_get_data(const GstMozVideoBuffer* self)
+{
+  g_return_val_if_fail(GST_IS_MOZ_VIDEO_BUFFER(self), NULL);
+
+  return self->data;
+}
+
+GType
+gst_moz_video_buffer_data_get_type(void)
+{
+  static volatile gsize g_define_type_id__volatile = 0;
+
+  if(g_once_init_enter(&g_define_type_id__volatile)) {
+    GType g_define_type_id =
+        g_boxed_type_register_static(g_intern_static_string("GstMozVideoBufferData"),
+                                     (GBoxedCopyFunc)GstMozVideoBufferData::Copy,
+                                     (GBoxedFreeFunc)GstMozVideoBufferData::Free);
+    g_once_init_leave(&g_define_type_id__volatile, g_define_type_id);
+  }
+
+  return g_define_type_id__volatile;
+}
+
+}
new file mode 100644
--- /dev/null
+++ b/content/media/gstreamer/GStreamerMozVideoBuffer.h
@@ -0,0 +1,60 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef __GST_MOZ_VIDEO_BUFFER_H__
+#define __GST_MOZ_VIDEO_BUFFER_H__
+
+#include <gst/gst.h>
+#include "MediaDecoderReader.h"
+
+namespace mozilla {
+
+#define GST_TYPE_MOZ_VIDEO_BUFFER_DATA            (gst_moz_video_buffer_data_get_type())
+#define GST_IS_MOZ_VIDEO_BUFFER_DATA(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_MOZ_VIDEO_BUFFER_DATA))
+
+#define GST_TYPE_MOZ_VIDEO_BUFFER            (gst_moz_video_buffer_get_type())
+#define GST_IS_MOZ_VIDEO_BUFFER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_MOZ_VIDEO_BUFFER))
+#define GST_IS_MOZ_VIDEO_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_MOZ_VIDEO_BUFFER))
+#define GST_MOZ_VIDEO_BUFFER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_MOZ_VIDEO_BUFFER, GstMozVideoBuffer))
+
+typedef struct _GstMozVideoBuffer GstMozVideoBuffer;
+typedef struct _GstMozVideoBufferClass GstMozVideoBufferClass;
+
+class GstMozVideoBufferData;
+
+struct _GstMozVideoBuffer {
+  GstBuffer buffer;
+  GstMozVideoBufferData* data;
+};
+
+struct _GstMozVideoBufferClass {
+  GstBufferClass  buffer_class;
+};
+
+GType gst_moz_video_buffer_get_type(void);
+GstMozVideoBuffer* gst_moz_video_buffer_new(void);
+void gst_moz_video_buffer_set_data(GstMozVideoBuffer* buf, GstMozVideoBufferData* data);
+GstMozVideoBufferData* gst_moz_video_buffer_get_data(const GstMozVideoBuffer* buf);
+
+class GstMozVideoBufferData {
+  public:
+    GstMozVideoBufferData(layers::PlanarYCbCrImage* aImage) : mImage(aImage) {}
+
+    static void* Copy(void* aData) {
+      return new GstMozVideoBufferData(reinterpret_cast<GstMozVideoBufferData*>(aData)->mImage);
+    }
+
+    static void Free(void* aData) {
+      delete reinterpret_cast<GstMozVideoBufferData*>(aData);
+    }
+
+    nsRefPtr<layers::PlanarYCbCrImage> mImage;
+};
+
+GType gst_moz_video_buffer_data_get_type (void);
+
+} // namespace mozilla
+
+#endif /* __GST_MOZ_VIDEO_BUFFER_H__ */
+
--- a/content/media/gstreamer/GStreamerReader.cpp
+++ b/content/media/gstreamer/GStreamerReader.cpp
@@ -5,16 +5,17 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsError.h"
 #include "MediaDecoderStateMachine.h"
 #include "AbstractMediaDecoder.h"
 #include "MediaResource.h"
 #include "GStreamerReader.h"
 #include "GStreamerFormatHelper.h"
+#include "GStreamerMozVideoBuffer.h"
 #include "VideoUtils.h"
 #include "mozilla/dom/TimeRanges.h"
 #include "mozilla/Preferences.h"
 
 namespace mozilla {
 
 using namespace layers;
 
@@ -34,18 +35,16 @@ IsYV12Format(const VideoData::YCbCrBuffe
              const VideoData::YCbCrBuffer::Plane& aCrPlane);
 
 static const int MAX_CHANNELS = 4;
 // Let the demuxer work in pull mode for short files
 static const int SHORT_FILE_SIZE = 1024 * 1024;
 // The default resource->Read() size when working in push mode
 static const int DEFAULT_SOURCE_READ_SIZE = 50 * 1024;
 
-G_DEFINE_BOXED_TYPE(BufferData, buffer_data, BufferData::Copy, BufferData::Free);
-
 typedef enum {
   GST_PLAY_FLAG_VIDEO         = (1 << 0),
   GST_PLAY_FLAG_AUDIO         = (1 << 1),
   GST_PLAY_FLAG_TEXT          = (1 << 2),
   GST_PLAY_FLAG_VIS           = (1 << 3),
   GST_PLAY_FLAG_SOFT_VOLUME   = (1 << 4),
   GST_PLAY_FLAG_NATIVE_AUDIO  = (1 << 5),
   GST_PLAY_FLAG_NATIVE_VIDEO  = (1 << 6),
@@ -134,19 +133,17 @@ nsresult GStreamerReader::Init(MediaDeco
   mVideoAppSink = GST_APP_SINK(gst_bin_get_by_name(GST_BIN(mVideoSink),
         "videosink"));
   gst_app_sink_set_callbacks(mVideoAppSink, &mSinkCallbacks,
       (gpointer) this, nullptr);
   GstPad* sinkpad = gst_element_get_pad(GST_ELEMENT(mVideoAppSink), "sink");
   gst_pad_add_event_probe(sinkpad,
       G_CALLBACK(&GStreamerReader::EventProbeCb), this);
   gst_object_unref(sinkpad);
-#if GST_VERSION_MICRO >= 36
   gst_pad_set_bufferalloc_function(sinkpad, GStreamerReader::AllocateVideoBufferCb);
-#endif
   gst_pad_set_element_private(sinkpad, this);
 
   mAudioSink = gst_parse_bin_from_description("capsfilter name=filter ! "
 #ifdef MOZ_SAMPLE_TYPE_FLOAT32
         "appsink name=audiosink sync=true caps=audio/x-raw-float,"
 #ifdef IS_LITTLE_ENDIAN
         "channels={1,2},width=32,endianness=1234", TRUE, nullptr);
 #else
@@ -527,25 +524,21 @@ bool GStreamerReader::DecodeVideoFrame(b
     break;
   }
 
   if (!buffer)
     /* no more frames */
     return false;
 
   nsRefPtr<PlanarYCbCrImage> image;
-#if GST_VERSION_MICRO >= 36
-  const GstStructure* structure = gst_buffer_get_qdata(buffer,
-      g_quark_from_string("moz-reader-data"));
-  const GValue* value = gst_structure_get_value(structure, "image");
-  if (value) {
-    BufferData* data = reinterpret_cast<BufferData*>(g_value_get_boxed(value));
-    image = data->mImage;
-  }
-#endif
+  GstMozVideoBufferData* bufferdata = reinterpret_cast<GstMozVideoBufferData*>
+      GST_IS_MOZ_VIDEO_BUFFER(buffer)?gst_moz_video_buffer_get_data(GST_MOZ_VIDEO_BUFFER(buffer)):nullptr;
+
+  if(bufferdata)
+    image = bufferdata->mImage;
 
   if (!image) {
     /* Ugh, upstream is not calling gst_pad_alloc_buffer(). Fallback to
      * allocating a PlanarYCbCrImage backed GstBuffer here and memcpy.
      */
     GstBuffer* tmp = nullptr;
     AllocateVideoBufferFull(nullptr, GST_BUFFER_OFFSET(buffer),
         GST_BUFFER_SIZE(buffer), nullptr, &tmp, image);
@@ -839,39 +832,28 @@ GstFlowReturn GStreamerReader::AllocateV
 {
   /* allocate an image using the container */
   ImageContainer* container = mDecoder->GetImageContainer();
   ImageFormat format = PLANAR_YCBCR;
   PlanarYCbCrImage* img = reinterpret_cast<PlanarYCbCrImage*>(container->CreateImage(&format, 1).get());
   nsRefPtr<PlanarYCbCrImage> image = dont_AddRef(img);
 
   /* prepare a GstBuffer pointing to the underlying PlanarYCbCrImage buffer */
-  GstBuffer* buf = gst_buffer_new();
+  GstBuffer* buf = GST_BUFFER(gst_moz_video_buffer_new());
   GST_BUFFER_SIZE(buf) = aSize;
   /* allocate the actual YUV buffer */
   GST_BUFFER_DATA(buf) = image->AllocateAndGetNewBuffer(aSize);
 
   aImage = image;
 
-#if GST_VERSION_MICRO >= 36
-  /* create a GBoxed handle to hold the image */
-  BufferData* data = new BufferData(image);
+  /* create a GstMozVideoBufferData to hold the image */
+  GstMozVideoBufferData* bufferdata = new GstMozVideoBufferData(image);
 
-  /* store it in a GValue so we can put it in a GstStructure */
-  GValue value = {0,};
-  g_value_init(&value, buffer_data_get_type());
-  g_value_take_boxed(&value, data);
-
-  /* store the value in the structure */
-  GstStructure* structure = gst_structure_new("moz-reader-data", nullptr);
-  gst_structure_take_value(structure, "image", &value);
-
-  /* and attach the structure to the buffer */
-  gst_buffer_set_qdata(buf, g_quark_from_string("moz-reader-data"), structure);
-#endif
+  /* Attach bufferdata to our GstMozVideoBuffer, it will take care to free it */
+  gst_moz_video_buffer_set_data(GST_MOZ_VIDEO_BUFFER(buf), bufferdata);
 
   *aBuf = buf;
   return GST_FLOW_OK;
 }
 
 GstFlowReturn GStreamerReader::AllocateVideoBufferCb(GstPad* aPad,
                                                      guint64 aOffset,
                                                      guint aSize,
--- a/content/media/gstreamer/GStreamerReader.h
+++ b/content/media/gstreamer/GStreamerReader.h
@@ -148,26 +148,11 @@ private:
   /* offset we've reached reading from the source */
   gint64 mByteOffset;
   /* the last offset we reported with NotifyBytesConsumed */
   gint64 mLastReportedByteOffset;
   int fpsNum;
   int fpsDen;
 };
 
-class BufferData {
-  public:
-    BufferData(layers::PlanarYCbCrImage* aImage) : mImage(aImage) {}
-
-    static void* Copy(void* aData) {
-      return new BufferData(reinterpret_cast<BufferData*>(aData)->mImage);
-    }
-
-    static void Free(void* aData) {
-      delete reinterpret_cast<BufferData*>(aData);
-    }
-
-    nsRefPtr<layers::PlanarYCbCrImage> mImage;
-};
-
 } // namespace mozilla
 
 #endif
--- a/content/media/gstreamer/Makefile.in
+++ b/content/media/gstreamer/Makefile.in
@@ -13,16 +13,17 @@ include $(DEPTH)/config/autoconf.mk
 LIBRARY_NAME	= gkcongstreamer_s
 LIBXUL_LIBRARY 	= 1
 
 
 CPPSRCS		= \
 		GStreamerReader.cpp \
 		GStreamerDecoder.cpp \
 		GStreamerFormatHelper.cpp \
+		GStreamerMozVideoBuffer.cpp \
 		$(NULL)
 
 FORCE_STATIC_LIB = 1
 
 include $(topsrcdir)/config/rules.mk
 
 CFLAGS		+= $(GSTREAMER_CFLAGS)
 CXXFLAGS	+= $(GSTREAMER_CFLAGS)