Bug 856308 - Enable GStreamer video buffer handling optimization for gstreamer versions older than 0.10.36. DONTBUILD because NPOTB r=alessandro.d,padenot

This commit is contained in:
Ivaylo Dimitrov 2013-05-03 16:44:54 +02:00
parent 2b6efddc0c
commit 231cb29945
5 changed files with 190 additions and 44 deletions

View File

@ -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;
}
}

View File

@ -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__ */

View File

@ -10,6 +10,7 @@
#include "MediaResource.h"
#include "GStreamerReader.h"
#include "GStreamerFormatHelper.h"
#include "GStreamerMozVideoBuffer.h"
#include "VideoUtils.h"
#include "mozilla/dom/TimeRanges.h"
#include "mozilla/Preferences.h"
@ -39,8 +40,6 @@ 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),
@ -139,9 +138,7 @@ nsresult GStreamerReader::Init(MediaDecoderReader* aCloneDonor)
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 ! "
@ -532,15 +529,11 @@ bool GStreamerReader::DecodeVideoFrame(bool &aKeyFrameSkip,
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
@ -844,29 +837,18 @@ GstFlowReturn GStreamerReader::AllocateVideoBufferFull(GstPad* aPad,
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;

View File

@ -153,21 +153,6 @@ private:
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

View File

@ -18,6 +18,7 @@ CPPSRCS = \
GStreamerReader.cpp \
GStreamerDecoder.cpp \
GStreamerFormatHelper.cpp \
GStreamerMozVideoBuffer.cpp \
$(NULL)
FORCE_STATIC_LIB = 1