Bug 806917 - support GStreamer 1.0 firefox20
authorWolfgang Rosenauer <wr@rosenauer.org>
Thu, 28 Feb 2013 23:25:28 +0100
branchfirefox20
changeset 6259f6e14430916
parent 624 ea8e1b6429f5
child 626 e3b03c331906
Bug 806917 - support GStreamer 1.0
MozillaFirefox/MozillaFirefox.changes
MozillaFirefox/MozillaFirefox.spec
MozillaFirefox/mozilla-gstreamer-1.patch
mozilla-gstreamer-1.patch
series
     1.1 --- a/MozillaFirefox/MozillaFirefox.changes	Thu Feb 28 23:13:27 2013 +0100
     1.2 +++ b/MozillaFirefox/MozillaFirefox.changes	Thu Feb 28 23:25:28 2013 +0100
     1.3 @@ -2,6 +2,7 @@
     1.4  Thu Feb 28 22:12:37 UTC 2013 - wr@rosenauer.org
     1.5  
     1.6  - update to Firefox 20.0b2
     1.7 +- use GStreamer 1.0 starting with 12.3 (mozilla-gstreamer-1.patch)
     1.8  
     1.9  -------------------------------------------------------------------
    1.10  Thu Feb 28 22:06:36 UTC 2013 - wr@rosenauer.org
     2.1 --- a/MozillaFirefox/MozillaFirefox.spec	Thu Feb 28 23:13:27 2013 +0100
     2.2 +++ b/MozillaFirefox/MozillaFirefox.spec	Thu Feb 28 23:25:28 2013 +0100
     2.3 @@ -98,6 +98,7 @@
     2.4  Patch13:        mozilla-ppc.patch
     2.5  Patch14:        mozilla-gstreamer-760140.patch
     2.6  Patch15:        mozilla-libproxy-compat.patch
     2.7 +Patch16:        mozilla-gstreamer-1.patch
     2.8  # Firefox/browser
     2.9  Patch30:        firefox-browser-css.patch
    2.10  Patch31:        firefox-kde.patch
    2.11 @@ -232,6 +233,7 @@
    2.12  %patch13 -p1
    2.13  %patch14 -p1
    2.14  %patch15 -p1
    2.15 +%patch16 -p1
    2.16  #
    2.17  %patch30 -p1
    2.18  %if %suse_version >= 1110
    2.19 @@ -302,11 +304,17 @@
    2.20  ac_add_options --enable-gio
    2.21  EOF
    2.22  %endif
    2.23 +%if %suse_version > 1220
    2.24 +cat << EOF >> $MOZCONFIG
    2.25 +ac_add_options --enable-gstreamer=1.0
    2.26 +EOF
    2.27 +%else
    2.28  %if %suse_version > 1140
    2.29  cat << EOF >> $MOZCONFIG
    2.30  ac_add_options --enable-gstreamer
    2.31  EOF
    2.32  %endif
    2.33 +%endif
    2.34  %if %branding
    2.35  cat << EOF >> $MOZCONFIG
    2.36  ac_add_options --enable-official-branding
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/MozillaFirefox/mozilla-gstreamer-1.patch	Thu Feb 28 23:25:28 2013 +0100
     3.3 @@ -0,0 +1,1 @@
     3.4 +../mozilla-gstreamer-1.patch
     3.5 \ No newline at end of file
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/mozilla-gstreamer-1.patch	Thu Feb 28 23:25:28 2013 +0100
     4.3 @@ -0,0 +1,667 @@
     4.4 +# HG changeset patch
     4.5 +# Parent fb80f99ca86bacbcddaf203f7183e0456f194811
     4.6 +# User Mike Gorse <mgorse@suse.com>
     4.7 +
     4.8 +Bug 806917 - support GStreamer 1.0
     4.9 +
    4.10 +diff --git a/configure.in b/configure.in
    4.11 +--- a/configure.in
    4.12 ++++ b/configure.in
    4.13 +@@ -5758,28 +5758,36 @@ fi
    4.14 + 
    4.15 + AC_SUBST(MOZ_PULSEAUDIO)
    4.16 + AC_SUBST(MOZ_PULSEAUDIO_CFLAGS)
    4.17 + AC_SUBST(MOZ_PULSEAUDIO_LIBS)
    4.18 + 
    4.19 + dnl ========================================================
    4.20 + dnl = Enable GStreamer
    4.21 + dnl ========================================================
    4.22 +-MOZ_ARG_ENABLE_BOOL(gstreamer,
    4.23 +-[  --enable-gstreamer           Enable GStreamer support],
    4.24 +-MOZ_GSTREAMER=1,
    4.25 +-MOZ_GSTREAMER=)
    4.26 ++MOZ_ARG_ENABLE_STRING(gstreamer,
    4.27 ++[  --enable-gstreamer[=1.0]           Enable GStreamer support],
    4.28 ++[ MOZ_GSTREAMER=1
    4.29 ++  # API version, eg 0.10, 1.0 etc
    4.30 ++  if test -n "$enableval" ]; then
    4.31 ++    GST_API_VERSION=$enableval
    4.32 ++  else
    4.33 ++    GST_API_VERSION=0.10
    4.34 ++  fi]
    4.35 ++[ MOZ_GSTREAMER=])
    4.36 + 
    4.37 + if test "$MOZ_GSTREAMER"; then
    4.38 +-    # API version, eg 0.10, 1.0 etc
    4.39 +-    GST_API_VERSION=0.10
    4.40 +     # core/base release number
    4.41 +     # depend on >= 0.10.33 as that's when the playbin2 source-setup signal was
    4.42 +     # introduced
    4.43 +-    GST_VERSION=0.10.33
    4.44 ++    if test "$GST_API_VERSION" = "1.0"; then
    4.45 ++      GST_VERSION=1.0
    4.46 ++    else
    4.47 ++      GST_VERSION=0.10.33
    4.48 ++    fi
    4.49 +     PKG_CHECK_MODULES(GSTREAMER,
    4.50 +                       gstreamer-$GST_API_VERSION >= $GST_VERSION
    4.51 +                       gstreamer-app-$GST_API_VERSION
    4.52 +                       gstreamer-plugins-base-$GST_API_VERSION)
    4.53 +     if test -n "$GSTREAMER_LIBS"; then
    4.54 +        _SAVE_LDFLAGS=$LDFLAGS
    4.55 +        LDFLAGS="$LDFLAGS $GSTREAMER_LIBS -lgstvideo-$GST_API_VERSION"
    4.56 +        AC_TRY_LINK(,[return 0;],_HAVE_LIBGSTVIDEO=1,_HAVE_LIBGSTVIDEO=)
    4.57 +diff --git a/content/media/gstreamer/GStreamerReader.cpp b/content/media/gstreamer/GStreamerReader.cpp
    4.58 +--- a/content/media/gstreamer/GStreamerReader.cpp
    4.59 ++++ b/content/media/gstreamer/GStreamerReader.cpp
    4.60 +@@ -69,18 +69,22 @@ GStreamerReader::GStreamerReader(Abstrac
    4.61 +   MOZ_COUNT_CTOR(GStreamerReader);
    4.62 + 
    4.63 +   mSrcCallbacks.need_data = GStreamerReader::NeedDataCb;
    4.64 +   mSrcCallbacks.enough_data = GStreamerReader::EnoughDataCb;
    4.65 +   mSrcCallbacks.seek_data = GStreamerReader::SeekDataCb;
    4.66 + 
    4.67 +   mSinkCallbacks.eos = GStreamerReader::EosCb;
    4.68 +   mSinkCallbacks.new_preroll = GStreamerReader::NewPrerollCb;
    4.69 ++#if GST_VERSION_MAJOR == 1
    4.70 ++  mSinkCallbacks.new_sample = GStreamerReader::NewBufferCb;
    4.71 ++#else
    4.72 +   mSinkCallbacks.new_buffer = GStreamerReader::NewBufferCb;
    4.73 +   mSinkCallbacks.new_buffer_list = NULL;
    4.74 ++#endif
    4.75 + 
    4.76 +   gst_segment_init(&mVideoSegment, GST_FORMAT_UNDEFINED);
    4.77 +   gst_segment_init(&mAudioSegment, GST_FORMAT_UNDEFINED);
    4.78 + }
    4.79 + 
    4.80 + GStreamerReader::~GStreamerReader()
    4.81 + {
    4.82 +   MOZ_COUNT_DTOR(GStreamerReader);
    4.83 +@@ -120,19 +124,26 @@ nsresult GStreamerReader::Init(MediaDeco
    4.84 +   mVideoSink = gst_parse_bin_from_description("capsfilter name=filter ! "
    4.85 +       "appsink name=videosink sync=true max-buffers=1 "
    4.86 +       "caps=video/x-raw-yuv,format=(fourcc)I420"
    4.87 +       , TRUE, NULL);
    4.88 +   mVideoAppSink = GST_APP_SINK(gst_bin_get_by_name(GST_BIN(mVideoSink),
    4.89 +         "videosink"));
    4.90 +   gst_app_sink_set_callbacks(mVideoAppSink, &mSinkCallbacks,
    4.91 +       (gpointer) this, NULL);
    4.92 +-  GstPad *sinkpad = gst_element_get_pad(GST_ELEMENT(mVideoAppSink), "sink");
    4.93 ++  GstPad *sinkpad = gst_element_get_static_pad(GST_ELEMENT(mVideoAppSink), "sink");
    4.94 ++#if GST_VERSION_MAJOR == 1
    4.95 ++  // TODO: Figure out whether we need UPSTREAM or DOWNSTREAM, or both
    4.96 ++  gst_pad_add_probe(sinkpad,
    4.97 ++      (GstPadProbeType) (GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM | GST_PAD_PROBE_TYPE_EVENT_UPSTREAM),
    4.98 ++      &GStreamerReader::EventProbeCb, this, NULL);
    4.99 ++#else
   4.100 +   gst_pad_add_event_probe(sinkpad,
   4.101 +       G_CALLBACK(&GStreamerReader::EventProbeCb), this);
   4.102 ++#endif
   4.103 +   gst_object_unref(sinkpad);
   4.104 + 
   4.105 +   mAudioSink = gst_parse_bin_from_description("capsfilter name=filter ! "
   4.106 + #ifdef MOZ_SAMPLE_TYPE_FLOAT32
   4.107 +         "appsink name=audiosink sync=true caps=audio/x-raw-float,"
   4.108 + #ifdef IS_LITTLE_ENDIAN
   4.109 +         "channels={1,2},rate=44100,width=32,endianness=1234", TRUE, NULL);
   4.110 + #else
   4.111 +@@ -145,19 +156,25 @@ nsresult GStreamerReader::Init(MediaDeco
   4.112 + #else
   4.113 +         "channels={1,2},rate=48000,width=16,endianness=4321", TRUE, NULL);
   4.114 + #endif
   4.115 + #endif
   4.116 +   mAudioAppSink = GST_APP_SINK(gst_bin_get_by_name(GST_BIN(mAudioSink),
   4.117 +         "audiosink"));
   4.118 +   gst_app_sink_set_callbacks(mAudioAppSink, &mSinkCallbacks,
   4.119 +       (gpointer) this, NULL);
   4.120 +-  sinkpad = gst_element_get_pad(GST_ELEMENT(mAudioAppSink), "sink");
   4.121 ++  sinkpad = gst_element_get_static_pad(GST_ELEMENT(mAudioAppSink), "sink");
   4.122 ++#if GST_VERSION_MAJOR == 1
   4.123 ++  gst_pad_add_probe(sinkpad,
   4.124 ++      (GstPadProbeType) (GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM | GST_PAD_PROBE_TYPE_EVENT_UPSTREAM),
   4.125 ++      &GStreamerReader::EventProbeCb, this, NULL);
   4.126 ++#else
   4.127 +   gst_pad_add_event_probe(sinkpad,
   4.128 +       G_CALLBACK(&GStreamerReader::EventProbeCb), this);
   4.129 ++#endif
   4.130 +   gst_object_unref(sinkpad);
   4.131 + 
   4.132 +   g_object_set(mPlayBin, "uri", "appsrc://",
   4.133 +       "video-sink", mVideoSink,
   4.134 +       "audio-sink", mAudioSink,
   4.135 +       NULL);
   4.136 + 
   4.137 +   g_object_connect(mPlayBin, "signal::source-setup",
   4.138 +@@ -231,17 +248,17 @@ nsresult GStreamerReader::ReadMetadata(V
   4.139 +       filter = gst_bin_get_by_name(GST_BIN(mAudioSink), "filter");
   4.140 +     else if (!(current_flags & GST_PLAY_FLAG_VIDEO))
   4.141 +       filter = gst_bin_get_by_name(GST_BIN(mVideoSink), "filter");
   4.142 + 
   4.143 +     if (filter) {
   4.144 +       /* Little trick: set the target caps to "skip" so that playbin2 fails to
   4.145 +        * find a decoder for the stream we want to skip.
   4.146 +        */
   4.147 +-      GstCaps *filterCaps = gst_caps_new_simple ("skip", NULL);
   4.148 ++      GstCaps *filterCaps = gst_caps_new_simple ("skip", NULL, NULL);
   4.149 +       g_object_set(filter, "caps", filterCaps, NULL);
   4.150 +       gst_caps_unref(filterCaps);
   4.151 +       gst_object_unref(filter);
   4.152 +     }
   4.153 + 
   4.154 +     /* start the pipeline */
   4.155 +     gst_element_set_state(mPlayBin, GST_STATE_PAUSED);
   4.156 + 
   4.157 +@@ -284,19 +301,24 @@ nsresult GStreamerReader::ReadMetadata(V
   4.158 +       gst_element_set_state(mPlayBin, GST_STATE_NULL);
   4.159 +       gst_message_unref(message);
   4.160 +       return NS_ERROR_FAILURE;
   4.161 +     }
   4.162 +   }
   4.163 + 
   4.164 +   /* report the duration */
   4.165 +   gint64 duration;
   4.166 ++#if GST_VERSION_MAJOR == 1
   4.167 ++  if (gst_element_query_duration(GST_ELEMENT(mPlayBin),
   4.168 ++      GST_FORMAT_TIME, &duration)) {
   4.169 ++#else
   4.170 +   GstFormat format = GST_FORMAT_TIME;
   4.171 +   if (gst_element_query_duration(GST_ELEMENT(mPlayBin),
   4.172 +       &format, &duration) && format == GST_FORMAT_TIME) {
   4.173 ++#endif
   4.174 +     ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
   4.175 +     LOG(PR_LOG_DEBUG, ("returning duration %" GST_TIME_FORMAT,
   4.176 +           GST_TIME_ARGS (duration)));
   4.177 +     duration = GST_TIME_AS_USECONDS (duration);
   4.178 +     mDecoder->SetMediaDuration(duration);
   4.179 +   }
   4.180 + 
   4.181 +   int n_video = 0, n_audio = 0;
   4.182 +@@ -365,59 +387,87 @@ bool GStreamerReader::DecodeAudioData()
   4.183 + {
   4.184 +   NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
   4.185 + 
   4.186 +   if (!WaitForDecodedData(&mAudioSinkBufferCount)) {
   4.187 +     mAudioQueue.Finish();
   4.188 +     return false;
   4.189 +   }
   4.190 + 
   4.191 ++#if GST_VERSION_MAJOR == 1
   4.192 ++    GstSample *sample = gst_app_sink_pull_sample(mAudioAppSink);
   4.193 ++    GstBuffer *buffer = gst_sample_get_buffer(sample);
   4.194 ++#else
   4.195 +   GstBuffer *buffer = gst_app_sink_pull_buffer(mAudioAppSink);
   4.196 ++#endif
   4.197 +   int64_t timestamp = GST_BUFFER_TIMESTAMP(buffer);
   4.198 +   timestamp = gst_segment_to_stream_time(&mAudioSegment,
   4.199 +       GST_FORMAT_TIME, timestamp);
   4.200 +   timestamp = GST_TIME_AS_USECONDS(timestamp);
   4.201 +   int64_t duration = 0;
   4.202 +   if (GST_CLOCK_TIME_IS_VALID(GST_BUFFER_DURATION(buffer)))
   4.203 +     duration = GST_TIME_AS_USECONDS(GST_BUFFER_DURATION(buffer));
   4.204 + 
   4.205 +   int64_t offset = GST_BUFFER_OFFSET(buffer);
   4.206 ++#if GST_VERSION_MAJOR == 1
   4.207 ++  GstMapInfo info;
   4.208 ++  gst_buffer_map(buffer, &info, GST_MAP_READ);
   4.209 ++  unsigned int size = info.size;
   4.210 ++#else
   4.211 +   unsigned int size = GST_BUFFER_SIZE(buffer);
   4.212 ++#endif
   4.213 +   int32_t frames = (size / sizeof(AudioDataValue)) / mInfo.mAudioChannels;
   4.214 +   ssize_t outSize = static_cast<size_t>(size / sizeof(AudioDataValue));
   4.215 +   nsAutoArrayPtr<AudioDataValue> data(new AudioDataValue[outSize]);
   4.216 ++#if GST_VERSION_MAJOR == 1
   4.217 ++  memcpy(data, info.data, info.size);
   4.218 ++  gst_buffer_unmap(buffer, &info);
   4.219 ++#else
   4.220 +   memcpy(data, GST_BUFFER_DATA(buffer), GST_BUFFER_SIZE(buffer));
   4.221 ++#endif
   4.222 +   AudioData *audio = new AudioData(offset, timestamp, duration,
   4.223 +       frames, data.forget(), mInfo.mAudioChannels);
   4.224 + 
   4.225 +   mAudioQueue.Push(audio);
   4.226 +   gst_buffer_unref(buffer);
   4.227 + 
   4.228 +   return true;
   4.229 + }
   4.230 + 
   4.231 + bool GStreamerReader::DecodeVideoFrame(bool &aKeyFrameSkip,
   4.232 +                                          int64_t aTimeThreshold)
   4.233 + {
   4.234 +   NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
   4.235 + 
   4.236 ++#if GST_VERSION_MAJOR == 1
   4.237 ++    GstSample *sample = NULL;
   4.238 ++#endif
   4.239 +   GstBuffer *buffer = NULL;
   4.240 +   int64_t timestamp, nextTimestamp;
   4.241 +   while (true)
   4.242 +   {
   4.243 +     if (!WaitForDecodedData(&mVideoSinkBufferCount)) {
   4.244 +       mVideoQueue.Finish();
   4.245 +       break;
   4.246 +     }
   4.247 +     mDecoder->NotifyDecodedFrames(0, 1);
   4.248 + 
   4.249 ++#if GST_VERSION_MAJOR == 1
   4.250 ++    sample = gst_app_sink_pull_sample(mVideoAppSink);
   4.251 ++    buffer = gst_sample_get_buffer(sample);
   4.252 ++#else
   4.253 +     buffer = gst_app_sink_pull_buffer(mVideoAppSink);
   4.254 ++#endif
   4.255 +     bool isKeyframe = !GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DISCONT);
   4.256 +     if ((aKeyFrameSkip && !isKeyframe)) {
   4.257 ++#if GST_VERSION_MAJOR == 1
   4.258 ++      gst_sample_unref(sample);
   4.259 ++#else
   4.260 +       gst_buffer_unref(buffer);
   4.261 ++#endif
   4.262 +       buffer = NULL;
   4.263 +       continue;
   4.264 +     }
   4.265 + 
   4.266 +     timestamp = GST_BUFFER_TIMESTAMP(buffer);
   4.267 +     {
   4.268 +       ReentrantMonitorAutoEnter mon(mGstThreadsMonitor);
   4.269 +       timestamp = gst_segment_to_stream_time(&mVideoSegment,
   4.270 +@@ -431,62 +481,90 @@ bool GStreamerReader::DecodeVideoFrame(b
   4.271 +     else if (fpsNum && fpsDen)
   4.272 +       /* add 1-frame duration */
   4.273 +       nextTimestamp += gst_util_uint64_scale(GST_USECOND, fpsNum, fpsDen);
   4.274 + 
   4.275 +     if (timestamp < aTimeThreshold) {
   4.276 +       LOG(PR_LOG_DEBUG, ("skipping frame %" GST_TIME_FORMAT
   4.277 +             " threshold %" GST_TIME_FORMAT,
   4.278 +             GST_TIME_ARGS(timestamp), GST_TIME_ARGS(aTimeThreshold)));
   4.279 ++#if GST_VERSION_MAJOR == 1
   4.280 ++      gst_sample_unref(sample);
   4.281 ++#else
   4.282 +       gst_buffer_unref(buffer);
   4.283 ++#endif
   4.284 +       buffer = NULL;
   4.285 +       continue;
   4.286 +     }
   4.287 + 
   4.288 +     break;
   4.289 +   }
   4.290 + 
   4.291 +   if (buffer == NULL)
   4.292 +     /* no more frames */
   4.293 +     return false;
   4.294 + 
   4.295 ++#if GST_VERSION_MAJOR == 1
   4.296 ++  GstMapInfo info;
   4.297 ++  gst_buffer_map(buffer, &info, GST_MAP_READ);
   4.298 ++  guint8 *data = info.data;
   4.299 ++#else
   4.300 +   guint8 *data = GST_BUFFER_DATA(buffer);
   4.301 ++#endif
   4.302 + 
   4.303 +   int width = mPicture.width;
   4.304 +   int height = mPicture.height;
   4.305 +   GstVideoFormat format = mFormat;
   4.306 + 
   4.307 +   VideoData::YCbCrBuffer b;
   4.308 ++#if GST_VERSION_MAJOR == 1
   4.309 ++  GstVideoInfo *video_info;
   4.310 ++  gst_video_info_set_format(video_info, format, width, height);
   4.311 ++  for(int i = 0; i < 3; i++) {
   4.312 ++    b.mPlanes[i].mData = data + GST_VIDEO_INFO_COMP_OFFSET(video_info, i);
   4.313 ++    b.mPlanes[i].mStride = GST_VIDEO_INFO_COMP_STRIDE(video_info, i);
   4.314 ++    b.mPlanes[i].mHeight = GST_VIDEO_INFO_COMP_HEIGHT(video_info, i);
   4.315 ++    b.mPlanes[i].mWidth = GST_VIDEO_INFO_COMP_WIDTH(video_info, i);
   4.316 ++    b.mPlanes[i].mOffset = 0;
   4.317 ++    b.mPlanes[i].mSkip = 0;
   4.318 ++  }
   4.319 ++#else
   4.320 +   for(int i = 0; i < 3; i++) {
   4.321 +     b.mPlanes[i].mData = data + gst_video_format_get_component_offset(format, i,
   4.322 +         width, height);
   4.323 +     b.mPlanes[i].mStride = gst_video_format_get_row_stride(format, i, width);
   4.324 +     b.mPlanes[i].mHeight = gst_video_format_get_component_height(format,
   4.325 +         i, height);
   4.326 +     b.mPlanes[i].mWidth = gst_video_format_get_component_width(format,
   4.327 +         i, width);
   4.328 +     b.mPlanes[i].mOffset = 0;
   4.329 +     b.mPlanes[i].mSkip = 0;
   4.330 +   }
   4.331 ++#endif
   4.332 + 
   4.333 +   bool isKeyframe = !GST_BUFFER_FLAG_IS_SET(buffer,
   4.334 +       GST_BUFFER_FLAG_DELTA_UNIT);
   4.335 +   /* XXX ? */
   4.336 +   int64_t offset = 0;
   4.337 +   VideoData *video = VideoData::Create(mInfo,
   4.338 +                                        mDecoder->GetImageContainer(),
   4.339 +                                        offset,
   4.340 +                                        timestamp,
   4.341 +                                        nextTimestamp,
   4.342 +                                        b,
   4.343 +                                        isKeyframe,
   4.344 +                                        -1,
   4.345 +                                        mPicture);
   4.346 +   mVideoQueue.Push(video);
   4.347 ++#if GST_VERSION_MAJOR == 1
   4.348 ++  gst_buffer_unmap(buffer, &info);
   4.349 ++  gst_sample_unref(sample);
   4.350 ++#else
   4.351 +   gst_buffer_unref(buffer);
   4.352 ++#endif
   4.353 + 
   4.354 +   return true;
   4.355 + }
   4.356 + 
   4.357 + nsresult GStreamerReader::Seek(int64_t aTarget,
   4.358 +                                  int64_t aStartTime,
   4.359 +                                  int64_t aEndTime,
   4.360 +                                  int64_t aCurrentTime)
   4.361 +@@ -509,52 +587,62 @@ nsresult GStreamerReader::Seek(int64_t a
   4.362 + 
   4.363 + nsresult GStreamerReader::GetBuffered(nsTimeRanges* aBuffered,
   4.364 +                                         int64_t aStartTime)
   4.365 + {
   4.366 +   if (!mInfo.mHasVideo && !mInfo.mHasAudio) {
   4.367 +     return NS_OK;
   4.368 +   }
   4.369 + 
   4.370 +-  GstFormat format = GST_FORMAT_TIME;
   4.371 ++#if GST_VERSION_MAJOR == 0
   4.372 ++    GstFormat format = GST_FORMAT_TIME;
   4.373 ++#endif
   4.374 ++
   4.375 +   MediaResource* resource = mDecoder->GetResource();
   4.376 +   gint64 resourceLength = resource->GetLength();
   4.377 +   nsTArray<MediaByteRange> ranges;
   4.378 +   resource->GetCachedRanges(ranges);
   4.379 + 
   4.380 +   if (mDecoder->OnStateMachineThread())
   4.381 +     /* Report the position from here while buffering as we can't report it from
   4.382 +      * the gstreamer threads that are actually reading from the resource
   4.383 +      */
   4.384 +     NotifyBytesConsumed();
   4.385 + 
   4.386 +   if (resource->IsDataCachedToEndOfResource(0)) {
   4.387 +     /* fast path for local or completely cached files */
   4.388 +     gint64 duration = 0;
   4.389 +-    GstFormat format = GST_FORMAT_TIME;
   4.390 +-
   4.391 +     duration = QueryDuration();
   4.392 +     double end = (double) duration / GST_MSECOND;
   4.393 +     LOG(PR_LOG_DEBUG, ("complete range [0, %f] for [0, %li]",
   4.394 +           end, resourceLength));
   4.395 +     aBuffered->Add(0, end);
   4.396 +     return NS_OK;
   4.397 +   }
   4.398 + 
   4.399 +   for(uint32_t index = 0; index < ranges.Length(); index++) {
   4.400 +     int64_t startOffset = ranges[index].mStart;
   4.401 +     int64_t endOffset = ranges[index].mEnd;
   4.402 +     gint64 startTime, endTime;
   4.403 + 
   4.404 ++#if GST_VERSION_MAJOR == 1
   4.405 ++    if (!gst_element_query_convert(GST_ELEMENT(mPlayBin), GST_FORMAT_BYTES,
   4.406 ++      startOffset, GST_FORMAT_TIME, &startTime))
   4.407 ++      continue;
   4.408 ++    if (!gst_element_query_convert(GST_ELEMENT(mPlayBin), GST_FORMAT_BYTES,
   4.409 ++      endOffset, GST_FORMAT_TIME, &endTime))
   4.410 ++      continue;
   4.411 ++#else
   4.412 +     if (!gst_element_query_convert(GST_ELEMENT(mPlayBin), GST_FORMAT_BYTES,
   4.413 +       startOffset, &format, &startTime) || format != GST_FORMAT_TIME)
   4.414 +       continue;
   4.415 +     if (!gst_element_query_convert(GST_ELEMENT(mPlayBin), GST_FORMAT_BYTES,
   4.416 +       endOffset, &format, &endTime) || format != GST_FORMAT_TIME)
   4.417 +       continue;
   4.418 ++#endif
   4.419 + 
   4.420 +     double start = start = (double) GST_TIME_AS_USECONDS (startTime) / GST_MSECOND;
   4.421 +     double end = (double) GST_TIME_AS_USECONDS (endTime) / GST_MSECOND;
   4.422 +     LOG(PR_LOG_DEBUG, ("adding range [%f, %f] for [%li %li] size %li",
   4.423 +           start, end, startOffset, endOffset, resourceLength));
   4.424 +     aBuffered->Add(start, end);
   4.425 +   }
   4.426 + 
   4.427 +@@ -563,48 +651,64 @@ nsresult GStreamerReader::GetBuffered(ns
   4.428 + 
   4.429 + void GStreamerReader::ReadAndPushData(guint aLength)
   4.430 + {
   4.431 +   MediaResource* resource = mDecoder->GetResource();
   4.432 +   NS_ASSERTION(resource, "Decoder has no media resource");
   4.433 +   nsresult rv = NS_OK;
   4.434 + 
   4.435 +   GstBuffer *buffer = gst_buffer_new_and_alloc(aLength);
   4.436 ++#if GST_VERSION_MAJOR == 1
   4.437 ++  GstMapInfo info;
   4.438 ++  gst_buffer_map(buffer, &info, GST_MAP_WRITE);
   4.439 ++  guint8 *data = info.data;
   4.440 ++#else
   4.441 +   guint8 *data = GST_BUFFER_DATA(buffer);
   4.442 ++#endif
   4.443 +   uint32_t size = 0, bytesRead = 0;
   4.444 +   while(bytesRead < aLength) {
   4.445 +     rv = resource->Read(reinterpret_cast<char*>(data + bytesRead),
   4.446 +         aLength - bytesRead, &size);
   4.447 +     if (NS_FAILED(rv) || size == 0)
   4.448 +       break;
   4.449 + 
   4.450 +     bytesRead += size;
   4.451 +   }
   4.452 + 
   4.453 ++#if GST_VERSION_MAJOR == 1
   4.454 ++  info.size = bytesRead;
   4.455 ++  gst_buffer_unmap(buffer, &info);
   4.456 ++#else
   4.457 +   GST_BUFFER_SIZE(buffer) = bytesRead;
   4.458 ++#endif
   4.459 +   mByteOffset += bytesRead;
   4.460 + 
   4.461 +   GstFlowReturn ret = gst_app_src_push_buffer(mSource, gst_buffer_ref(buffer));
   4.462 +   if (ret != GST_FLOW_OK)
   4.463 +     LOG(PR_LOG_ERROR, ("ReadAndPushData push ret %s", gst_flow_get_name(ret)));
   4.464 + 
   4.465 +-  if (GST_BUFFER_SIZE (buffer) < aLength)
   4.466 ++  if (bytesRead < aLength)
   4.467 +     /* If we read less than what we wanted, we reached the end */
   4.468 +     gst_app_src_end_of_stream(mSource);
   4.469 + 
   4.470 +   gst_buffer_unref(buffer);
   4.471 + }
   4.472 + 
   4.473 + int64_t GStreamerReader::QueryDuration()
   4.474 + {
   4.475 +   gint64 duration = 0;
   4.476 +   GstFormat format = GST_FORMAT_TIME;
   4.477 + 
   4.478 ++#if GST_VERSION_MAJOR == 1
   4.479 ++  if (gst_element_query_duration(GST_ELEMENT(mPlayBin),
   4.480 ++      format, &duration)) {
   4.481 ++#else
   4.482 +   if (gst_element_query_duration(GST_ELEMENT(mPlayBin),
   4.483 +       &format, &duration)) {
   4.484 ++#endif
   4.485 +     if (format == GST_FORMAT_TIME) {
   4.486 +       LOG(PR_LOG_DEBUG, ("pipeline duration %" GST_TIME_FORMAT,
   4.487 +             GST_TIME_ARGS (duration)));
   4.488 +       duration = GST_TIME_AS_USECONDS (duration);
   4.489 +     }
   4.490 +   }
   4.491 + 
   4.492 +   /*if (mDecoder->mDuration != -1 &&
   4.493 +@@ -668,60 +772,95 @@ gboolean GStreamerReader::SeekData(GstAp
   4.494 +   if (NS_SUCCEEDED(rv))
   4.495 +     mByteOffset = mLastReportedByteOffset = aOffset;
   4.496 +   else
   4.497 +     LOG(PR_LOG_ERROR, ("seek at %lu failed", aOffset));
   4.498 + 
   4.499 +   return NS_SUCCEEDED(rv);
   4.500 + }
   4.501 + 
   4.502 ++#if GST_VERSION_MAJOR == 1
   4.503 ++GstPadProbeReturn GStreamerReader::EventProbeCb(GstPad *aPad,
   4.504 ++                                                GstPadProbeInfo *aInfo,
   4.505 ++                                                gpointer aUserData)
   4.506 ++{
   4.507 ++  GStreamerReader *reader = (GStreamerReader *) aUserData;
   4.508 ++  GstEvent *aEvent = (GstEvent *)aInfo->data;
   4.509 ++  return reader->EventProbe(aPad, aEvent);
   4.510 ++}
   4.511 ++#else
   4.512 + gboolean GStreamerReader::EventProbeCb(GstPad *aPad,
   4.513 +                                          GstEvent *aEvent,
   4.514 +                                          gpointer aUserData)
   4.515 + {
   4.516 +   GStreamerReader *reader = (GStreamerReader *) aUserData;
   4.517 +   return reader->EventProbe(aPad, aEvent);
   4.518 + }
   4.519 ++#endif
   4.520 + 
   4.521 ++#if GST_VERSION_MAJOR == 1
   4.522 ++GstPadProbeReturn GStreamerReader::EventProbe(GstPad *aPad, GstEvent *aEvent)
   4.523 ++#else
   4.524 + gboolean GStreamerReader::EventProbe(GstPad *aPad, GstEvent *aEvent)
   4.525 ++#endif
   4.526 + {
   4.527 +   GstElement *parent = GST_ELEMENT(gst_pad_get_parent(aPad));
   4.528 +   switch(GST_EVENT_TYPE(aEvent)) {
   4.529 ++#if GST_VERSION_MAJOR == 1
   4.530 ++    case GST_EVENT_SEGMENT:
   4.531 ++#else
   4.532 +     case GST_EVENT_NEWSEGMENT:
   4.533 ++#endif
   4.534 +     {
   4.535 ++#if GST_VERSION_MAJOR == 1
   4.536 ++      const GstSegment *newSegment;
   4.537 ++#else
   4.538 +       gboolean update;
   4.539 +       gdouble rate;
   4.540 +       GstFormat format;
   4.541 +       gint64 start, stop, position;
   4.542 ++#endif
   4.543 +       GstSegment *segment;
   4.544 + 
   4.545 +       /* Store the segments so we can convert timestamps to stream time, which
   4.546 +        * is what the upper layers sync on.
   4.547 +        */
   4.548 +       ReentrantMonitorAutoEnter mon(mGstThreadsMonitor);
   4.549 ++#if GST_VERSION_MAJOR == 1
   4.550 ++      gst_event_parse_segment(aEvent, &newSegment);
   4.551 ++#else
   4.552 +       gst_event_parse_new_segment(aEvent, &update, &rate, &format,
   4.553 +           &start, &stop, &position);
   4.554 ++#endif
   4.555 +       if (parent == GST_ELEMENT(mVideoAppSink))
   4.556 +         segment = &mVideoSegment;
   4.557 +       else
   4.558 +         segment = &mAudioSegment;
   4.559 ++#if GST_VERSION_MAJOR == 1
   4.560 ++      gst_segment_copy_into (newSegment, segment);
   4.561 ++#else
   4.562 +       gst_segment_set_newsegment(segment, update, rate, format,
   4.563 +           start, stop, position);
   4.564 ++#endif
   4.565 +       break;
   4.566 +     }
   4.567 +     case GST_EVENT_FLUSH_STOP:
   4.568 +       /* Reset on seeks */
   4.569 +       ResetDecode();
   4.570 +       break;
   4.571 +     default:
   4.572 +       break;
   4.573 +   }
   4.574 +   gst_object_unref(parent);
   4.575 + 
   4.576 ++#if GST_VERSION_MAJOR == 1
   4.577 ++  return GST_PAD_PROBE_OK;
   4.578 ++#else
   4.579 +   return TRUE;
   4.580 ++#endif
   4.581 + }
   4.582 + 
   4.583 + GstFlowReturn GStreamerReader::NewPrerollCb(GstAppSink *aSink,
   4.584 +                                               gpointer aUserData)
   4.585 + {
   4.586 +   GStreamerReader *reader = (GStreamerReader *) aUserData;
   4.587 + 
   4.588 +   if (aSink == reader->mVideoAppSink)
   4.589 +@@ -730,18 +869,22 @@ GstFlowReturn GStreamerReader::NewPrerol
   4.590 +     reader->AudioPreroll();
   4.591 +   return GST_FLOW_OK;
   4.592 + }
   4.593 + 
   4.594 + void GStreamerReader::AudioPreroll()
   4.595 + {
   4.596 +   /* The first audio buffer has reached the audio sink. Get rate and channels */
   4.597 +   LOG(PR_LOG_DEBUG, ("Audio preroll"));
   4.598 +-  GstPad *sinkpad = gst_element_get_pad(GST_ELEMENT(mAudioAppSink), "sink");
   4.599 ++  GstPad *sinkpad = gst_element_get_static_pad(GST_ELEMENT(mAudioAppSink), "sink");
   4.600 ++#if GST_VERSION_MAJOR == 1
   4.601 ++  GstCaps *caps = gst_pad_get_current_caps(sinkpad);
   4.602 ++#else
   4.603 +   GstCaps *caps = gst_pad_get_negotiated_caps(sinkpad);
   4.604 ++#endif
   4.605 +   GstStructure *s = gst_caps_get_structure(caps, 0);
   4.606 +   mInfo.mAudioRate = mInfo.mAudioChannels = 0;
   4.607 +   gst_structure_get_int(s, "rate", (gint *) &mInfo.mAudioRate);
   4.608 +   gst_structure_get_int(s, "channels", (gint *) &mInfo.mAudioChannels);
   4.609 +   NS_ASSERTION(mInfo.mAudioRate != 0, ("audio rate is zero"));
   4.610 +   NS_ASSERTION(mInfo.mAudioChannels != 0, ("audio channels is zero"));
   4.611 +   NS_ASSERTION(mInfo.mAudioChannels > 0 && mInfo.mAudioChannels <= MAX_CHANNELS,
   4.612 +       "invalid audio channels number");
   4.613 +@@ -749,19 +892,29 @@ void GStreamerReader::AudioPreroll()
   4.614 +   gst_caps_unref(caps);
   4.615 +   gst_object_unref(sinkpad);
   4.616 + }
   4.617 + 
   4.618 + void GStreamerReader::VideoPreroll()
   4.619 + {
   4.620 +   /* The first video buffer has reached the video sink. Get width and height */
   4.621 +   LOG(PR_LOG_DEBUG, ("Video preroll"));
   4.622 +-  GstPad *sinkpad = gst_element_get_pad(GST_ELEMENT(mVideoAppSink), "sink");
   4.623 ++  GstPad *sinkpad = gst_element_get_static_pad(GST_ELEMENT(mVideoAppSink), "sink");
   4.624 ++#if GST_VERSION_MAJOR == 1
   4.625 ++  GstCaps *caps = gst_pad_get_current_caps(sinkpad);
   4.626 ++  GstVideoInfo info;
   4.627 ++  memset (&info, 0, sizeof (info));
   4.628 ++  gst_video_info_from_caps(&info, caps);
   4.629 ++  mFormat = info.finfo->format;
   4.630 ++  mPicture.width = info.width;
   4.631 ++  mPicture.height = info.height;
   4.632 ++#else
   4.633 +   GstCaps *caps = gst_pad_get_negotiated_caps(sinkpad);
   4.634 +   gst_video_format_parse_caps(caps, &mFormat, &mPicture.width, &mPicture.height);
   4.635 ++#endif
   4.636 +   GstStructure *structure = gst_caps_get_structure(caps, 0);
   4.637 +   gst_structure_get_fraction(structure, "framerate", &fpsNum, &fpsDen);
   4.638 +   NS_ASSERTION(mPicture.width && mPicture.height, "invalid video resolution");
   4.639 +   mInfo.mDisplay = nsIntSize(mPicture.width, mPicture.height);
   4.640 +   mInfo.mHasVideo = true;
   4.641 +   gst_caps_unref(caps);
   4.642 +   gst_object_unref(sinkpad);
   4.643 + }
   4.644 +diff --git a/content/media/gstreamer/GStreamerReader.h b/content/media/gstreamer/GStreamerReader.h
   4.645 +--- a/content/media/gstreamer/GStreamerReader.h
   4.646 ++++ b/content/media/gstreamer/GStreamerReader.h
   4.647 +@@ -71,18 +71,23 @@ private:
   4.648 + 
   4.649 +   /* Called when a seek is issued on the pipeline */
   4.650 +   static gboolean SeekDataCb(GstAppSrc *aSrc,
   4.651 +                              guint64 aOffset,
   4.652 +                              gpointer aUserData);
   4.653 +   gboolean SeekData(GstAppSrc *aSrc, guint64 aOffset);
   4.654 + 
   4.655 +   /* Called when events reach the sinks. See inline comments */
   4.656 ++#if GST_VERSION_MAJOR == 1
   4.657 ++  static GstPadProbeReturn EventProbeCb(GstPad *aPad, GstPadProbeInfo *aInfo, gpointer aUserData);
   4.658 ++  GstPadProbeReturn EventProbe(GstPad *aPad, GstEvent *aEvent);
   4.659 ++#else
   4.660 +   static gboolean EventProbeCb(GstPad *aPad, GstEvent *aEvent, gpointer aUserData);
   4.661 +   gboolean EventProbe(GstPad *aPad, GstEvent *aEvent);
   4.662 ++#endif
   4.663 + 
   4.664 +   /* Called when the pipeline is prerolled, that is when at start or after a
   4.665 +    * seek, the first audio and video buffers are queued in the sinks.
   4.666 +    */
   4.667 +   static GstFlowReturn NewPrerollCb(GstAppSink *aSink, gpointer aUserData);
   4.668 +   void VideoPreroll();
   4.669 +   void AudioPreroll();
   4.670 + 
     5.1 --- a/series	Thu Feb 28 23:13:27 2013 +0100
     5.2 +++ b/series	Thu Feb 28 23:25:28 2013 +0100
     5.3 @@ -18,6 +18,7 @@
     5.4  mozilla-ppc.patch
     5.5  mozilla-idldir.patch
     5.6  mozilla-libproxy-compat.patch
     5.7 +mozilla-gstreamer-1.patch
     5.8  #mozilla-disable-neon-option.patch
     5.9  
    5.10  # Firefox patches