head 1.3;
access;
symbols
pkgsrc-2014Q1:1.1.0.2
pkgsrc-2014Q1-base:1.1;
locks; strict;
comment @// @;
1.3
date 2014.06.11.00.40.59; author ryoon; state dead;
branches;
next 1.2;
commitid QTw894DEf2Let2Ex;
1.2
date 2014.04.30.15.07.18; author ryoon; state Exp;
branches;
next 1.1;
commitid BxErbE5mH8g3CIyx;
1.1
date 2014.03.20.21.02.00; author ryoon; state Exp;
branches;
next ;
commitid 7yTA4yPlY6RyTttx;
desc
@@
1.3
log
@Update to 30.0
* debug build is broken
Changelog:
New
Sidebars button in browser chrome enables faster access to social, bookmark, & history sidebars
New
Mac OS X command-E sets find term to selected text
New
Support for GStreamer 1.0
Changed
Disallow calling WebIDL constructors as functions on the web
Developer
With the exception of those bundled inside an extension or ones that are whitelisted, plugins will no longer be activated by default (see blog post)
Developer
Fixes to box-shadow and other visual overflow (see bug 480888)
Developer
Mute and volume available per window when using WebAudio
Developer
background-blend-mode enabled by default
Developer
Use of line-height allowed for
Developer
ES6 array and generator comprehensions implemented (read docs for more details)
Developer
Error stack now contains column number
Developer
Support for alpha option in canvas context options (feature description)
Fixed
Ignore autocomplete="off" when offering to save passwords via the password manager (see 956906)
Fixed
TypedArrays don't support new named properties (see 695438)
Fixed
Various security fixes
Fixed in Firefox 30
MFSA 2014-54 Buffer overflow in Gamepad API
MFSA 2014-53 Buffer overflow in Web Audio Speex resampler
MFSA 2014-52 Use-after-free with SMIL Animation Controller
MFSA 2014-51 Use-after-free in Event Listener Manager
MFSA 2014-50 Clickjacking through cursor invisability after Flash interaction
MFSA 2014-49 Use-after-free and out of bounds issues found using Address Sanitizer
MFSA 2014-48 Miscellaneous memory safety hazards (rv:30.0 / rv:24.6)
@
text
@$NetBSD: patch-content_media_gstreamer_GStreamerReader.cpp,v 1.2 2014/04/30 15:07:18 ryoon Exp $
--- content/media/gstreamer/GStreamerReader.cpp.orig 2014-04-18 02:02:42.000000000 +0000
+++ content/media/gstreamer/GStreamerReader.cpp
@@@@ -10,8 +10,10 @@@@
#include "AbstractMediaDecoder.h"
#include "MediaResource.h"
#include "GStreamerReader.h"
+#if GST_VERSION_MAJOR >= 1
+#include "GStreamerAllocator.h"
+#endif
#include "GStreamerFormatHelper.h"
-#include "GStreamerMozVideoBuffer.h"
#include "VideoUtils.h"
#include "mozilla/dom/TimeRanges.h"
#include "mozilla/Preferences.h"
@@@@ -33,14 +35,16 @@@@ extern PRLogModuleInfo* gMediaDecoderLog
#define LOG(type, msg, ...)
#endif
-extern bool
-IsYV12Format(const VideoData::YCbCrBuffer::Plane& aYPlane,
- const VideoData::YCbCrBuffer::Plane& aCbPlane,
- const VideoData::YCbCrBuffer::Plane& aCrPlane);
-
+#if DEBUG
static const unsigned int MAX_CHANNELS = 4;
-// Let the demuxer work in pull mode for short files
-static const int SHORT_FILE_SIZE = 1024 * 1024;
+#endif
+// Let the demuxer work in pull mode for short files. This used to be a micro
+// optimization to have more accurate durations for ogg files in mochitests.
+// Since as of today we aren't using gstreamer to demux ogg, and having demuxers
+// work in pull mode over http makes them slower (since they really assume
+// near-zero latency in pull mode) set the constant to 0 for now, which
+// effectively disables it.
+static const int SHORT_FILE_SIZE = 0;
// The default resource->Read() size when working in push mode
static const int DEFAULT_SOURCE_READ_SIZE = 50 * 1024;
@@@@ -62,6 +66,10 @@@@ GStreamerReader::GStreamerReader(Abstrac
: MediaDecoderReader(aDecoder),
mMP3FrameParser(aDecoder->GetResource()->GetLength()),
mUseParserDuration(false),
+#if GST_VERSION_MAJOR >= 1
+ mAllocator(nullptr),
+ mBufferPool(nullptr),
+#endif
mPlayBin(nullptr),
mBus(nullptr),
mSource(nullptr),
@@@@ -74,6 +82,9 @@@@ GStreamerReader::GStreamerReader(Abstrac
mAudioSinkBufferCount(0),
mGstThreadsMonitor("media.gst.threads"),
mReachedEos(false),
+#if GST_VERSION_MAJOR >= 1
+ mConfigureAlignment(true),
+#endif
fpsNum(0),
fpsDen(0)
{
@@@@ -85,8 +96,12 @@@@ GStreamerReader::GStreamerReader(Abstrac
mSinkCallbacks.eos = GStreamerReader::EosCb;
mSinkCallbacks.new_preroll = GStreamerReader::NewPrerollCb;
+#if GST_VERSION_MAJOR >= 1
+ mSinkCallbacks.new_sample = GStreamerReader::NewBufferCb;
+#else
mSinkCallbacks.new_buffer = GStreamerReader::NewBufferCb;
mSinkCallbacks.new_buffer_list = nullptr;
+#endif
gst_segment_init(&mVideoSegment, GST_FORMAT_UNDEFINED);
gst_segment_init(&mAudioSegment, GST_FORMAT_UNDEFINED);
@@@@ -110,65 +125,59 @@@@ GStreamerReader::~GStreamerReader()
mAudioAppSink = nullptr;
gst_object_unref(mBus);
mBus = nullptr;
+#if GST_VERSION_MAJOR >= 1
+ g_object_unref(mAllocator);
+ g_object_unref(mBufferPool);
+#endif
}
}
nsresult GStreamerReader::Init(MediaDecoderReader* aCloneDonor)
{
- GError* error = nullptr;
- if (!gst_init_check(0, 0, &error)) {
- LOG(PR_LOG_ERROR, "gst initialization failed: %s", error->message);
- g_error_free(error);
- return NS_ERROR_FAILURE;
- }
+ GStreamerFormatHelper::Instance();
+
+#if GST_VERSION_MAJOR >= 1
+ mAllocator = static_cast(g_object_new(GST_TYPE_MOZ_GFX_MEMORY_ALLOCATOR, nullptr));
+ moz_gfx_memory_allocator_set_reader(mAllocator, this);
+
+ mBufferPool = static_cast(g_object_new(GST_TYPE_MOZ_GFX_BUFFER_POOL, nullptr));
+#endif
+#if GST_VERSION_MAJOR >= 1
+ mPlayBin = gst_element_factory_make("playbin", nullptr);
+#else
mPlayBin = gst_element_factory_make("playbin2", nullptr);
+#endif
if (!mPlayBin) {
- LOG(PR_LOG_ERROR, "couldn't create playbin2");
+ LOG(PR_LOG_ERROR, "couldn't create playbin");
return NS_ERROR_FAILURE;
}
g_object_set(mPlayBin, "buffer-size", 0, nullptr);
mBus = gst_pipeline_get_bus(GST_PIPELINE(mPlayBin));
mVideoSink = gst_parse_bin_from_description("capsfilter name=filter ! "
- "appsink name=videosink sync=true max-buffers=1 "
+ "appsink name=videosink sync=false max-buffers=1 "
+#if GST_VERSION_MAJOR >= 1
+ "caps=video/x-raw,format=I420"
+#else
"caps=video/x-raw-yuv,format=(fourcc)I420"
+#endif
, TRUE, nullptr);
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);
- gst_pad_set_bufferalloc_function(sinkpad, GStreamerReader::AllocateVideoBufferCb);
- gst_pad_set_element_private(sinkpad, this);
-
mAudioSink = gst_parse_bin_from_description("capsfilter name=filter ! "
-#ifdef MOZ_SAMPLE_TYPE_FLOAT32
- "appsink name=audiosink max-buffers=2 sync=false caps=audio/x-raw-float,"
-#ifdef IS_LITTLE_ENDIAN
- "channels={1,2},width=32,endianness=1234", TRUE, nullptr);
-#else
- "channels={1,2},width=32,endianness=4321", TRUE, nullptr);
-#endif
-#else
- "appsink name=audiosink max-buffers=2 sync=false caps=audio/x-raw-int,"
-#ifdef IS_LITTLE_ENDIAN
- "channels={1,2},width=16,endianness=1234", TRUE, nullptr);
-#else
- "channels={1,2},width=16,endianness=4321", TRUE, nullptr);
-#endif
-#endif
+ "appsink name=audiosink sync=false max-buffers=1", TRUE, nullptr);
mAudioAppSink = GST_APP_SINK(gst_bin_get_by_name(GST_BIN(mAudioSink),
"audiosink"));
+ GstCaps* caps = BuildAudioSinkCaps();
+ g_object_set(mAudioAppSink, "caps", caps, nullptr);
+ gst_caps_unref(caps);
+
+ gst_app_sink_set_callbacks(mVideoAppSink, &mSinkCallbacks,
+ (gpointer) this, nullptr);
gst_app_sink_set_callbacks(mAudioAppSink, &mSinkCallbacks,
(gpointer) this, nullptr);
- sinkpad = gst_element_get_pad(GST_ELEMENT(mAudioAppSink), "sink");
- gst_pad_add_event_probe(sinkpad,
- G_CALLBACK(&GStreamerReader::EventProbeCb), this);
- gst_object_unref(sinkpad);
+ InstallPadCallbacks();
g_object_set(mPlayBin, "uri", "appsrc://",
"video-sink", mVideoSink,
@@@@ -331,13 +340,12 @@@@ nsresult GStreamerReader::ReadMetadata(M
/* Little trick: set the target caps to "skip" so that playbin2 fails to
* find a decoder for the stream we want to skip.
*/
- GstCaps* filterCaps = gst_caps_new_simple ("skip", nullptr);
+ GstCaps* filterCaps = gst_caps_new_simple ("skip", nullptr, nullptr);
g_object_set(filter, "caps", filterCaps, nullptr);
gst_caps_unref(filterCaps);
gst_object_unref(filter);
}
- /* start the pipeline */
LOG(PR_LOG_DEBUG, "starting metadata pipeline");
gst_element_set_state(mPlayBin, GST_STATE_PAUSED);
@@@@ -358,6 +366,7 @@@@ nsresult GStreamerReader::ReadMetadata(M
gst_message_unref(message);
ret = NS_ERROR_FAILURE;
} else {
+ LOG(PR_LOG_DEBUG, "read metadata pipeline prerolled");
gst_message_unref(message);
ret = NS_OK;
break;
@@@@ -371,23 +380,8 @@@@ nsresult GStreamerReader::ReadMetadata(M
/* we couldn't get this to play */
return ret;
- /* FIXME: workaround for a bug in matroskademux. This seek makes matroskademux
- * parse the index */
- if (gst_element_seek_simple(mPlayBin, GST_FORMAT_TIME,
- GST_SEEK_FLAG_FLUSH, 0)) {
- /* after a seek we need to wait again for ASYNC_DONE */
- message = gst_bus_timed_pop_filtered(mBus, GST_CLOCK_TIME_NONE,
- (GstMessageType)(GST_MESSAGE_ASYNC_DONE | GST_MESSAGE_ERROR));
- if (GST_MESSAGE_TYPE(message) == GST_MESSAGE_ERROR) {
- gst_element_set_state(mPlayBin, GST_STATE_NULL);
- gst_message_unref(message);
- return NS_ERROR_FAILURE;
- }
- }
-
/* report the duration */
gint64 duration;
- GstFormat format = GST_FORMAT_TIME;
if (isMP3 && mMP3FrameParser.IsMP3()) {
// The MP3FrameParser has reported a duration; use that over the gstreamer
@@@@ -396,17 +390,25 @@@@ nsresult GStreamerReader::ReadMetadata(M
mUseParserDuration = true;
mLastParserDuration = mMP3FrameParser.GetDuration();
mDecoder->SetMediaDuration(mLastParserDuration);
-
- } else if (gst_element_query_duration(GST_ELEMENT(mPlayBin),
- &format, &duration) && format == GST_FORMAT_TIME) {
- // Otherwise use the gstreamer duration.
- ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
- LOG(PR_LOG_DEBUG, "returning duration %" GST_TIME_FORMAT, GST_TIME_ARGS(duration));
- duration = GST_TIME_AS_USECONDS (duration);
- mDecoder->SetMediaDuration(duration);
-
} else {
- mDecoder->SetMediaSeekable(false);
+ LOG(PR_LOG_DEBUG, "querying duration");
+ // Otherwise use the gstreamer duration.
+#if GST_VERSION_MAJOR >= 1
+ if (gst_element_query_duration(GST_ELEMENT(mPlayBin),
+ GST_FORMAT_TIME, &duration)) {
+#else
+ GstFormat format = GST_FORMAT_TIME;
+ if (gst_element_query_duration(GST_ELEMENT(mPlayBin),
+ &format, &duration) && format == GST_FORMAT_TIME) {
+#endif
+ ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
+ LOG(PR_LOG_DEBUG, "have duration %" GST_TIME_FORMAT,
+ GST_TIME_ARGS (duration));
+ duration = GST_TIME_AS_USECONDS (duration);
+ mDecoder->SetMediaDuration(duration);
+ } else {
+ mDecoder->SetMediaSeekable(false);
+ }
}
int n_video = 0, n_audio = 0;
@@@@ -419,7 +421,11 @@@@ nsresult GStreamerReader::ReadMetadata(M
*aTags = nullptr;
// Watch the pipeline for fatal errors
+#if GST_VERSION_MAJOR >= 1
+ gst_bus_set_sync_handler(mBus, GStreamerReader::ErrorCb, this, nullptr);
+#else
gst_bus_set_sync_handler(mBus, GStreamerReader::ErrorCb, this);
+#endif
/* set the pipeline to PLAYING so that it starts decoding and queueing data in
* the appsinks */
@@@@ -433,19 +439,35 @@@@ nsresult GStreamerReader::CheckSupported
bool done = false;
bool unsupported = false;
- GstIterator *it = gst_bin_iterate_recurse(GST_BIN(mPlayBin));
+ GstIterator* it = gst_bin_iterate_recurse(GST_BIN(mPlayBin));
while (!done) {
+ GstIteratorResult res;
GstElement* element;
- GstIteratorResult res = gst_iterator_next(it, (void **)&element);
+
+#if GST_VERSION_MAJOR >= 1
+ GValue value = {0,};
+ res = gst_iterator_next(it, &value);
+#else
+ res = gst_iterator_next(it, (void **) &element);
+#endif
switch(res) {
case GST_ITERATOR_OK:
{
+#if GST_VERSION_MAJOR >= 1
+ element = GST_ELEMENT (g_value_get_object (&value));
+#endif
GstElementFactory* factory = gst_element_get_factory(element);
if (factory) {
const char* klass = gst_element_factory_get_klass(factory);
- GstPad* pad = gst_element_get_pad(element, "sink");
+ GstPad* pad = gst_element_get_static_pad(element, "sink");
if (pad) {
- GstCaps* caps = gst_pad_get_negotiated_caps(pad);
+ GstCaps* caps;
+
+#if GST_VERSION_MAJOR >= 1
+ caps = gst_pad_get_current_caps(pad);
+#else
+ caps = gst_pad_get_negotiated_caps(pad);
+#endif
if (caps) {
/* check for demuxers but ignore elements like id3demux */
@@@@ -460,7 +482,11 @@@@ nsresult GStreamerReader::CheckSupported
}
}
+#if GST_VERSION_MAJOR >= 1
+ g_value_unset (&value);
+#else
gst_object_unref(element);
+#endif
done = unsupported;
break;
}
@@@@ -484,6 +510,8 @@@@ nsresult GStreamerReader::ResetDecode()
{
nsresult res = NS_OK;
+ LOG(PR_LOG_DEBUG, "reset decode");
+
if (NS_FAILED(MediaDecoderReader::ResetDecode())) {
res = NS_ERROR_FAILURE;
}
@@@@ -494,6 +522,11 @@@@ nsresult GStreamerReader::ResetDecode()
mVideoSinkBufferCount = 0;
mAudioSinkBufferCount = 0;
mReachedEos = false;
+#if GST_VERSION_MAJOR >= 1
+ mConfigureAlignment = true;
+#endif
+
+ LOG(PR_LOG_DEBUG, "reset decode done");
return res;
}
@@@@ -517,11 +550,11 @@@@ bool GStreamerReader::DecodeAudioData()
/* We have nothing decoded so it makes no sense to return to the state machine
* as it will call us back immediately, we'll return again and so on, wasting
* CPU cycles for no job done. So, block here until there is either video or
- * audio data available
+ * audio data available
*/
mon.Wait();
if (!mAudioSinkBufferCount) {
- /* There is still no audio data available, so either there is video data or
+ /* There is still no audio data available, so either there is video data or
* something else has happened (Eos, etc...). Return to the state machine
* to process it.
*/
@@@@ -533,24 +566,44 @@@@ bool GStreamerReader::DecodeAudioData()
}
}
+#if GST_VERSION_MAJOR >= 1
+ GstSample *sample = gst_app_sink_pull_sample(mAudioAppSink);
+ buffer = gst_buffer_ref(gst_sample_get_buffer(sample));
+ gst_sample_unref(sample);
+#else
buffer = gst_app_sink_pull_buffer(mAudioAppSink);
+#endif
+
mAudioSinkBufferCount--;
}
int64_t timestamp = GST_BUFFER_TIMESTAMP(buffer);
timestamp = gst_segment_to_stream_time(&mAudioSegment,
GST_FORMAT_TIME, timestamp);
+
timestamp = GST_TIME_AS_USECONDS(timestamp);
+
int64_t duration = 0;
if (GST_CLOCK_TIME_IS_VALID(GST_BUFFER_DURATION(buffer)))
duration = GST_TIME_AS_USECONDS(GST_BUFFER_DURATION(buffer));
int64_t offset = GST_BUFFER_OFFSET(buffer);
+#if GST_VERSION_MAJOR >= 1
+ GstMapInfo info;
+ gst_buffer_map(buffer, &info, GST_MAP_READ);
+ unsigned int size = info.size;
+#else
unsigned int size = GST_BUFFER_SIZE(buffer);
+#endif
int32_t frames = (size / sizeof(AudioDataValue)) / mInfo.mAudio.mChannels;
ssize_t outSize = static_cast(size / sizeof(AudioDataValue));
nsAutoArrayPtr data(new AudioDataValue[outSize]);
+#if GST_VERSION_MAJOR >= 1
+ memcpy(data, info.data, info.size);
+ gst_buffer_unmap(buffer, &info);
+#else
memcpy(data, GST_BUFFER_DATA(buffer), GST_BUFFER_SIZE(buffer));
+#endif
AudioData* audio = new AudioData(offset, timestamp, duration,
frames, data.forget(), mInfo.mAudio.mChannels);
@@@@ -561,7 +614,7 @@@@ bool GStreamerReader::DecodeAudioData()
}
bool GStreamerReader::DecodeVideoFrame(bool &aKeyFrameSkip,
- int64_t aTimeThreshold)
+ int64_t aTimeThreshold)
{
NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
@@@@ -580,11 +633,11 @@@@ bool GStreamerReader::DecodeVideoFrame(b
/* We have nothing decoded so it makes no sense to return to the state machine
* as it will call us back immediately, we'll return again and so on, wasting
* CPU cycles for no job done. So, block here until there is either video or
- * audio data available
+ * audio data available
*/
mon.Wait();
if (!mVideoSinkBufferCount) {
- /* There is still no video data available, so either there is audio data or
+ /* There is still no video data available, so either there is audio data or
* something else has happened (Eos, etc...). Return to the state machine
* to process it
*/
@@@@ -598,11 +651,17 @@@@ bool GStreamerReader::DecodeVideoFrame(b
mDecoder->NotifyDecodedFrames(0, 1);
+#if GST_VERSION_MAJOR >= 1
+ GstSample *sample = gst_app_sink_pull_sample(mVideoAppSink);
+ buffer = gst_buffer_ref(gst_sample_get_buffer(sample));
+ gst_sample_unref(sample);
+#else
buffer = gst_app_sink_pull_buffer(mVideoAppSink);
+#endif
mVideoSinkBufferCount--;
}
- bool isKeyframe = !GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DISCONT);
+ bool isKeyframe = !GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DELTA_UNIT);
if ((aKeyFrameSkip && !isKeyframe)) {
gst_buffer_unref(buffer);
return true;
@@@@ -618,10 +677,18 @@@@ bool GStreamerReader::DecodeVideoFrame(b
"frame has invalid timestamp");
timestamp = GST_TIME_AS_USECONDS(timestamp);
+ int64_t duration;
+ if (GST_CLOCK_TIME_IS_VALID(GST_BUFFER_DURATION(buffer)))
+ duration = GST_TIME_AS_USECONDS(GST_BUFFER_DURATION(buffer));
+ else if (fpsNum && fpsDen)
+ /* add 1-frame duration */
+ duration = gst_util_uint64_scale(GST_USECOND, fpsDen, fpsNum);
+
if (timestamp < aTimeThreshold) {
LOG(PR_LOG_DEBUG, "skipping frame %" GST_TIME_FORMAT
" threshold %" GST_TIME_FORMAT,
- GST_TIME_ARGS(timestamp), GST_TIME_ARGS(aTimeThreshold));
+ GST_TIME_ARGS(timestamp * 1000),
+ GST_TIME_ARGS(aTimeThreshold * 1000));
gst_buffer_unref(buffer);
return true;
}
@@@@ -630,61 +697,36 @@@@ bool GStreamerReader::DecodeVideoFrame(b
/* no more frames */
return false;
- int64_t duration = 0;
- if (GST_CLOCK_TIME_IS_VALID(GST_BUFFER_DURATION(buffer)))
- duration = GST_TIME_AS_USECONDS(GST_BUFFER_DURATION(buffer));
- else if (fpsNum && fpsDen)
- /* 1-frame duration */
- duration = gst_util_uint64_scale(GST_USECOND, fpsNum, fpsDen);
-
- nsRefPtr image;
- GstMozVideoBufferData* bufferdata = reinterpret_cast
- GST_IS_MOZ_VIDEO_BUFFER(buffer)?gst_moz_video_buffer_get_data(GST_MOZ_VIDEO_BUFFER(buffer)):nullptr;
-
- if(bufferdata)
- image = bufferdata->mImage;
+#if GST_VERSION_MAJOR >= 1
+ if (mConfigureAlignment && buffer->pool) {
+ GstStructure *config = gst_buffer_pool_get_config(buffer->pool);
+ GstVideoAlignment align;
+ if (gst_buffer_pool_config_get_video_alignment(config, &align))
+ gst_video_info_align(&mVideoInfo, &align);
+ gst_structure_free(config);
+ mConfigureAlignment = false;
+ }
+#endif
+ nsRefPtr image = GetImageFromBuffer(buffer);
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);
-
- /* copy */
- gst_buffer_copy_metadata(tmp, buffer, (GstBufferCopyFlags)GST_BUFFER_COPY_ALL);
- memcpy(GST_BUFFER_DATA(tmp), GST_BUFFER_DATA(buffer),
- GST_BUFFER_SIZE(tmp));
+ CopyIntoImageBuffer(buffer, &tmp, image);
gst_buffer_unref(buffer);
buffer = tmp;
}
- guint8* data = GST_BUFFER_DATA(buffer);
-
- int width = mPicture.width;
- int height = mPicture.height;
- GstVideoFormat format = mFormat;
-
- VideoData::YCbCrBuffer b;
- for(int i = 0; i < 3; i++) {
- b.mPlanes[i].mData = data + gst_video_format_get_component_offset(format, i,
- width, height);
- b.mPlanes[i].mStride = gst_video_format_get_row_stride(format, i, width);
- b.mPlanes[i].mHeight = gst_video_format_get_component_height(format,
- i, height);
- b.mPlanes[i].mWidth = gst_video_format_get_component_width(format,
- i, width);
- b.mPlanes[i].mOffset = 0;
- b.mPlanes[i].mSkip = 0;
- }
-
- isKeyframe = !GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DELTA_UNIT);
int64_t offset = mDecoder->GetResource()->Tell(); // Estimate location in media.
- VideoData* video = VideoData::Create(mInfo.mVideo, image, offset,
- timestamp, duration, b,
- isKeyframe, -1, mPicture);
+ VideoData* video = VideoData::CreateFromImage(mInfo.mVideo,
+ mDecoder->GetImageContainer(),
+ offset, timestamp, duration,
+ static_cast(image.get()),
+ isKeyframe, -1, mPicture);
mVideoQueue.Push(video);
+
gst_buffer_unref(buffer);
return true;
@@@@ -707,6 +749,10 @@@@ nsresult GStreamerReader::Seek(int64_t a
return NS_ERROR_FAILURE;
}
LOG(PR_LOG_DEBUG, "seek succeeded");
+ GstMessage* message = gst_bus_timed_pop_filtered(mBus, GST_CLOCK_TIME_NONE,
+ (GstMessageType)(GST_MESSAGE_ASYNC_DONE | GST_MESSAGE_ERROR));
+ gst_message_unref(message);
+ LOG(PR_LOG_DEBUG, "seek completed");
return DecodeToTarget(aTarget);
}
@@@@ -718,7 +764,9 @@@@ nsresult GStreamerReader::GetBuffered(do
return NS_OK;
}
+#if GST_VERSION_MAJOR == 0
GstFormat format = GST_FORMAT_TIME;
+#endif
MediaResource* resource = mDecoder->GetResource();
nsTArray ranges;
resource->GetCachedRanges(ranges);
@@@@ -740,12 +788,21 @@@@ nsresult GStreamerReader::GetBuffered(do
int64_t endOffset = ranges[index].mEnd;
gint64 startTime, endTime;
+#if GST_VERSION_MAJOR >= 1
+ if (!gst_element_query_convert(GST_ELEMENT(mPlayBin), GST_FORMAT_BYTES,
+ startOffset, GST_FORMAT_TIME, &startTime))
+ continue;
+ if (!gst_element_query_convert(GST_ELEMENT(mPlayBin), GST_FORMAT_BYTES,
+ endOffset, GST_FORMAT_TIME, &endTime))
+ continue;
+#else
if (!gst_element_query_convert(GST_ELEMENT(mPlayBin), GST_FORMAT_BYTES,
startOffset, &format, &startTime) || format != GST_FORMAT_TIME)
continue;
if (!gst_element_query_convert(GST_ELEMENT(mPlayBin), GST_FORMAT_BYTES,
endOffset, &format, &endTime) || format != GST_FORMAT_TIME)
continue;
+#endif
double start = (double) GST_TIME_AS_USECONDS (startTime) / GST_MSECOND;
double end = (double) GST_TIME_AS_USECONDS (endTime) / GST_MSECOND;
@@@@ -766,7 +823,13 @@@@ void GStreamerReader::ReadAndPushData(gu
nsresult rv = NS_OK;
GstBuffer* buffer = gst_buffer_new_and_alloc(aLength);
+#if GST_VERSION_MAJOR >= 1
+ GstMapInfo info;
+ gst_buffer_map(buffer, &info, GST_MAP_WRITE);
+ guint8 *data = info.data;
+#else
guint8* data = GST_BUFFER_DATA(buffer);
+#endif
uint32_t size = 0, bytesRead = 0;
while(bytesRead < aLength) {
rv = resource->Read(reinterpret_cast(data + bytesRead),
@@@@ -780,7 +843,12 @@@@ void GStreamerReader::ReadAndPushData(gu
int64_t offset2 = resource->Tell();
unused << offset2;
+#if GST_VERSION_MAJOR >= 1
+ gst_buffer_unmap(buffer, &info);
+ gst_buffer_set_size(buffer, bytesRead);
+#else
GST_BUFFER_SIZE(buffer) = bytesRead;
+#endif
GstFlowReturn ret = gst_app_src_push_buffer(mSource, gst_buffer_ref(buffer));
if (ret != GST_FLOW_OK) {
@@@@ -813,8 +881,13 @@@@ int64_t GStreamerReader::QueryDuration()
gint64 duration = 0;
GstFormat format = GST_FORMAT_TIME;
+#if GST_VERSION_MAJOR >= 1
+ if (gst_element_query_duration(GST_ELEMENT(mPlayBin),
+ format, &duration)) {
+#else
if (gst_element_query_duration(GST_ELEMENT(mPlayBin),
&format, &duration)) {
+#endif
if (format == GST_FORMAT_TIME) {
LOG(PR_LOG_DEBUG, "pipeline duration %" GST_TIME_FORMAT,
GST_TIME_ARGS (duration));
@@@@ -893,109 +966,6 @@@@ gboolean GStreamerReader::SeekData(GstAp
return NS_SUCCEEDED(rv);
}
-gboolean GStreamerReader::EventProbeCb(GstPad* aPad,
- GstEvent* aEvent,
- gpointer aUserData)
-{
- GStreamerReader* reader = reinterpret_cast(aUserData);
- return reader->EventProbe(aPad, aEvent);
-}
-
-gboolean GStreamerReader::EventProbe(GstPad* aPad, GstEvent* aEvent)
-{
- GstElement* parent = GST_ELEMENT(gst_pad_get_parent(aPad));
- switch(GST_EVENT_TYPE(aEvent)) {
- case GST_EVENT_NEWSEGMENT:
- {
- gboolean update;
- gdouble rate;
- GstFormat format;
- gint64 start, stop, position;
- GstSegment* segment;
-
- /* Store the segments so we can convert timestamps to stream time, which
- * is what the upper layers sync on.
- */
- ReentrantMonitorAutoEnter mon(mGstThreadsMonitor);
- gst_event_parse_new_segment(aEvent, &update, &rate, &format,
- &start, &stop, &position);
- if (parent == GST_ELEMENT(mVideoAppSink))
- segment = &mVideoSegment;
- else
- segment = &mAudioSegment;
- gst_segment_set_newsegment(segment, update, rate, format,
- start, stop, position);
- break;
- }
- case GST_EVENT_FLUSH_STOP:
- /* Reset on seeks */
- ResetDecode();
- break;
- default:
- break;
- }
- gst_object_unref(parent);
-
- return TRUE;
-}
-
-GstFlowReturn GStreamerReader::AllocateVideoBufferFull(GstPad* aPad,
- guint64 aOffset,
- guint aSize,
- GstCaps* aCaps,
- GstBuffer** aBuf,
- nsRefPtr& aImage)
-{
- /* allocate an image using the container */
- ImageContainer* container = mDecoder->GetImageContainer();
- if (!container) {
- // We don't have an ImageContainer. We probably belong to an