$NetBSD: patch-mozilla_content_media_gstreamer_GStreamerReader.cpp,v 1.1 2014/03/30 04:13:17 ryoon Exp $ --- mozilla/content/media/gstreamer/GStreamerReader.cpp.orig 2014-03-19 01:41:47.000000000 +0000 +++ mozilla/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,7 +340,7 @@ 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); @@ -358,6 +367,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 +381,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 +391,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 +422,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 +440,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 +483,11 @@ nsresult GStreamerReader::CheckSupported } } +#if GST_VERSION_MAJOR >= 1 + g_value_unset (&value); +#else gst_object_unref(element); +#endif done = unsupported; break; } @@ -484,6 +511,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 +523,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 +551,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 +567,43 @@ 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,73 +677,55 @@ 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)); + " threshold %" GST_TIME_FORMAT, + GST_TIME_ARGS(timestamp * 1000), + GST_TIME_ARGS(aTimeThreshold * 1000)); gst_buffer_unref(buffer); return true; } - if (!buffer) /* 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 +748,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 +763,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 +787,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 +822,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 +842,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 +880,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,108 +965,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