mozilla-gstreamer-1.patch
changeset 630 72f6f8dbdb4f
parent 627 cc7671532e60
child 637 73640b76d6c3
equal deleted inserted replaced
618:49dc6da2c835 630:72f6f8dbdb4f
       
     1 # HG changeset patch
       
     2 # Parent 0559be6b60075e1a708ca90e874f922ff200c462
       
     3 # User Mike Gorse <mgorse@suse.com>
       
     4 
       
     5 Bug 806917 - support GStreamer 1.0
       
     6 
       
     7 diff --git a/configure.in b/configure.in
       
     8 --- a/configure.in
       
     9 +++ b/configure.in
       
    10 @@ -5758,28 +5758,36 @@ fi
       
    11  
       
    12  AC_SUBST(MOZ_PULSEAUDIO)
       
    13  AC_SUBST(MOZ_PULSEAUDIO_CFLAGS)
       
    14  AC_SUBST(MOZ_PULSEAUDIO_LIBS)
       
    15  
       
    16  dnl ========================================================
       
    17  dnl = Enable GStreamer
       
    18  dnl ========================================================
       
    19 -MOZ_ARG_ENABLE_BOOL(gstreamer,
       
    20 -[  --enable-gstreamer           Enable GStreamer support],
       
    21 -MOZ_GSTREAMER=1,
       
    22 -MOZ_GSTREAMER=)
       
    23 +MOZ_ARG_ENABLE_STRING(gstreamer,
       
    24 +[  --enable-gstreamer[=1.0]           Enable GStreamer support],
       
    25 +[ MOZ_GSTREAMER=1
       
    26 +  # API version, eg 0.10, 1.0 etc
       
    27 +  if test -n "$enableval" ]; then
       
    28 +    GST_API_VERSION=$enableval
       
    29 +  else
       
    30 +    GST_API_VERSION=0.10
       
    31 +  fi]
       
    32 +[ MOZ_GSTREAMER=])
       
    33  
       
    34  if test "$MOZ_GSTREAMER"; then
       
    35 -    # API version, eg 0.10, 1.0 etc
       
    36 -    GST_API_VERSION=0.10
       
    37      # core/base release number
       
    38      # depend on >= 0.10.33 as that's when the playbin2 source-setup signal was
       
    39      # introduced
       
    40 -    GST_VERSION=0.10.33
       
    41 +    if test "$GST_API_VERSION" = "1.0"; then
       
    42 +      GST_VERSION=1.0
       
    43 +    else
       
    44 +      GST_VERSION=0.10.33
       
    45 +    fi
       
    46      PKG_CHECK_MODULES(GSTREAMER,
       
    47                        gstreamer-$GST_API_VERSION >= $GST_VERSION
       
    48                        gstreamer-app-$GST_API_VERSION
       
    49                        gstreamer-plugins-base-$GST_API_VERSION)
       
    50      if test -n "$GSTREAMER_LIBS"; then
       
    51         _SAVE_LDFLAGS=$LDFLAGS
       
    52         LDFLAGS="$LDFLAGS $GSTREAMER_LIBS -lgstvideo-$GST_API_VERSION"
       
    53         AC_TRY_LINK(,[return 0;],_HAVE_LIBGSTVIDEO=1,_HAVE_LIBGSTVIDEO=)
       
    54 diff --git a/content/media/gstreamer/GStreamerFormatHelper.cpp b/content/media/gstreamer/GStreamerFormatHelper.cpp
       
    55 --- a/content/media/gstreamer/GStreamerFormatHelper.cpp
       
    56 +++ b/content/media/gstreamer/GStreamerFormatHelper.cpp
       
    57 @@ -141,17 +141,21 @@ bool GStreamerFormatHelper::HaveElements
       
    58      }
       
    59      g_list_free(list);
       
    60    }
       
    61  
       
    62    return true;
       
    63  }
       
    64  
       
    65  GList* GStreamerFormatHelper::GetFactories() {
       
    66 +#if GST_VERSION_MAJOR == 1
       
    67 +  uint32_t cookie = gst_registry_get_feature_list_cookie(gst_registry_get());
       
    68 +#else
       
    69    uint32_t cookie = gst_default_registry_get_feature_list_cookie ();
       
    70 +#endif
       
    71    if (cookie != mCookie) {
       
    72      g_list_free(mFactories);
       
    73      mFactories = gst_element_factory_list_get_elements
       
    74          (GST_ELEMENT_FACTORY_TYPE_DEMUXER | GST_ELEMENT_FACTORY_TYPE_DECODER,
       
    75           GST_RANK_MARGINAL);
       
    76      mCookie = cookie;
       
    77    }
       
    78  
       
    79 diff --git a/content/media/gstreamer/GStreamerReader.cpp b/content/media/gstreamer/GStreamerReader.cpp
       
    80 --- a/content/media/gstreamer/GStreamerReader.cpp
       
    81 +++ b/content/media/gstreamer/GStreamerReader.cpp
       
    82 @@ -69,18 +69,22 @@ GStreamerReader::GStreamerReader(Abstrac
       
    83    MOZ_COUNT_CTOR(GStreamerReader);
       
    84  
       
    85    mSrcCallbacks.need_data = GStreamerReader::NeedDataCb;
       
    86    mSrcCallbacks.enough_data = GStreamerReader::EnoughDataCb;
       
    87    mSrcCallbacks.seek_data = GStreamerReader::SeekDataCb;
       
    88  
       
    89    mSinkCallbacks.eos = GStreamerReader::EosCb;
       
    90    mSinkCallbacks.new_preroll = GStreamerReader::NewPrerollCb;
       
    91 +#if GST_VERSION_MAJOR == 1
       
    92 +  mSinkCallbacks.new_sample = GStreamerReader::NewBufferCb;
       
    93 +#else
       
    94    mSinkCallbacks.new_buffer = GStreamerReader::NewBufferCb;
       
    95    mSinkCallbacks.new_buffer_list = NULL;
       
    96 +#endif
       
    97  
       
    98    gst_segment_init(&mVideoSegment, GST_FORMAT_UNDEFINED);
       
    99    gst_segment_init(&mAudioSegment, GST_FORMAT_UNDEFINED);
       
   100  }
       
   101  
       
   102  GStreamerReader::~GStreamerReader()
       
   103  {
       
   104    MOZ_COUNT_DTOR(GStreamerReader);
       
   105 @@ -120,19 +124,26 @@ nsresult GStreamerReader::Init(MediaDeco
       
   106    mVideoSink = gst_parse_bin_from_description("capsfilter name=filter ! "
       
   107        "appsink name=videosink sync=true max-buffers=1 "
       
   108        "caps=video/x-raw-yuv,format=(fourcc)I420"
       
   109        , TRUE, NULL);
       
   110    mVideoAppSink = GST_APP_SINK(gst_bin_get_by_name(GST_BIN(mVideoSink),
       
   111          "videosink"));
       
   112    gst_app_sink_set_callbacks(mVideoAppSink, &mSinkCallbacks,
       
   113        (gpointer) this, NULL);
       
   114 -  GstPad *sinkpad = gst_element_get_pad(GST_ELEMENT(mVideoAppSink), "sink");
       
   115 +  GstPad *sinkpad = gst_element_get_static_pad(GST_ELEMENT(mVideoAppSink), "sink");
       
   116 +#if GST_VERSION_MAJOR == 1
       
   117 +  // TODO: Figure out whether we need UPSTREAM or DOWNSTREAM, or both
       
   118 +  gst_pad_add_probe(sinkpad,
       
   119 +      (GstPadProbeType) (GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM | GST_PAD_PROBE_TYPE_EVENT_UPSTREAM),
       
   120 +      &GStreamerReader::EventProbeCb, this, NULL);
       
   121 +#else
       
   122    gst_pad_add_event_probe(sinkpad,
       
   123        G_CALLBACK(&GStreamerReader::EventProbeCb), this);
       
   124 +#endif
       
   125    gst_object_unref(sinkpad);
       
   126  
       
   127    mAudioSink = gst_parse_bin_from_description("capsfilter name=filter ! "
       
   128  #ifdef MOZ_SAMPLE_TYPE_FLOAT32
       
   129          "appsink name=audiosink sync=true caps=audio/x-raw-float,"
       
   130  #ifdef IS_LITTLE_ENDIAN
       
   131          "channels={1,2},rate=44100,width=32,endianness=1234", TRUE, NULL);
       
   132  #else
       
   133 @@ -145,19 +156,25 @@ nsresult GStreamerReader::Init(MediaDeco
       
   134  #else
       
   135          "channels={1,2},rate=48000,width=16,endianness=4321", TRUE, NULL);
       
   136  #endif
       
   137  #endif
       
   138    mAudioAppSink = GST_APP_SINK(gst_bin_get_by_name(GST_BIN(mAudioSink),
       
   139          "audiosink"));
       
   140    gst_app_sink_set_callbacks(mAudioAppSink, &mSinkCallbacks,
       
   141        (gpointer) this, NULL);
       
   142 -  sinkpad = gst_element_get_pad(GST_ELEMENT(mAudioAppSink), "sink");
       
   143 +  sinkpad = gst_element_get_static_pad(GST_ELEMENT(mAudioAppSink), "sink");
       
   144 +#if GST_VERSION_MAJOR == 1
       
   145 +  gst_pad_add_probe(sinkpad,
       
   146 +      (GstPadProbeType) (GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM | GST_PAD_PROBE_TYPE_EVENT_UPSTREAM),
       
   147 +      &GStreamerReader::EventProbeCb, this, NULL);
       
   148 +#else
       
   149    gst_pad_add_event_probe(sinkpad,
       
   150        G_CALLBACK(&GStreamerReader::EventProbeCb), this);
       
   151 +#endif
       
   152    gst_object_unref(sinkpad);
       
   153  
       
   154    g_object_set(mPlayBin, "uri", "appsrc://",
       
   155        "video-sink", mVideoSink,
       
   156        "audio-sink", mAudioSink,
       
   157        NULL);
       
   158  
       
   159    g_object_connect(mPlayBin, "signal::source-setup",
       
   160 @@ -231,17 +248,17 @@ nsresult GStreamerReader::ReadMetadata(V
       
   161        filter = gst_bin_get_by_name(GST_BIN(mAudioSink), "filter");
       
   162      else if (!(current_flags & GST_PLAY_FLAG_VIDEO))
       
   163        filter = gst_bin_get_by_name(GST_BIN(mVideoSink), "filter");
       
   164  
       
   165      if (filter) {
       
   166        /* Little trick: set the target caps to "skip" so that playbin2 fails to
       
   167         * find a decoder for the stream we want to skip.
       
   168         */
       
   169 -      GstCaps *filterCaps = gst_caps_new_simple ("skip", NULL);
       
   170 +      GstCaps *filterCaps = gst_caps_new_simple ("skip", NULL, NULL);
       
   171        g_object_set(filter, "caps", filterCaps, NULL);
       
   172        gst_caps_unref(filterCaps);
       
   173        gst_object_unref(filter);
       
   174      }
       
   175  
       
   176      /* start the pipeline */
       
   177      gst_element_set_state(mPlayBin, GST_STATE_PAUSED);
       
   178  
       
   179 @@ -284,19 +301,24 @@ nsresult GStreamerReader::ReadMetadata(V
       
   180        gst_element_set_state(mPlayBin, GST_STATE_NULL);
       
   181        gst_message_unref(message);
       
   182        return NS_ERROR_FAILURE;
       
   183      }
       
   184    }
       
   185  
       
   186    /* report the duration */
       
   187    gint64 duration;
       
   188 +#if GST_VERSION_MAJOR == 1
       
   189 +  if (gst_element_query_duration(GST_ELEMENT(mPlayBin),
       
   190 +      GST_FORMAT_TIME, &duration)) {
       
   191 +#else
       
   192    GstFormat format = GST_FORMAT_TIME;
       
   193    if (gst_element_query_duration(GST_ELEMENT(mPlayBin),
       
   194        &format, &duration) && format == GST_FORMAT_TIME) {
       
   195 +#endif
       
   196      ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
       
   197      LOG(PR_LOG_DEBUG, ("returning duration %" GST_TIME_FORMAT,
       
   198            GST_TIME_ARGS (duration)));
       
   199      duration = GST_TIME_AS_USECONDS (duration);
       
   200      mDecoder->SetMediaDuration(duration);
       
   201    }
       
   202  
       
   203    int n_video = 0, n_audio = 0;
       
   204 @@ -365,59 +387,87 @@ bool GStreamerReader::DecodeAudioData()
       
   205  {
       
   206    NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
       
   207  
       
   208    if (!WaitForDecodedData(&mAudioSinkBufferCount)) {
       
   209      mAudioQueue.Finish();
       
   210      return false;
       
   211    }
       
   212  
       
   213 +#if GST_VERSION_MAJOR == 1
       
   214 +    GstSample *sample = gst_app_sink_pull_sample(mAudioAppSink);
       
   215 +    GstBuffer *buffer = gst_sample_get_buffer(sample);
       
   216 +#else
       
   217    GstBuffer *buffer = gst_app_sink_pull_buffer(mAudioAppSink);
       
   218 +#endif
       
   219    int64_t timestamp = GST_BUFFER_TIMESTAMP(buffer);
       
   220    timestamp = gst_segment_to_stream_time(&mAudioSegment,
       
   221        GST_FORMAT_TIME, timestamp);
       
   222    timestamp = GST_TIME_AS_USECONDS(timestamp);
       
   223    int64_t duration = 0;
       
   224    if (GST_CLOCK_TIME_IS_VALID(GST_BUFFER_DURATION(buffer)))
       
   225      duration = GST_TIME_AS_USECONDS(GST_BUFFER_DURATION(buffer));
       
   226  
       
   227    int64_t offset = GST_BUFFER_OFFSET(buffer);
       
   228 +#if GST_VERSION_MAJOR == 1
       
   229 +  GstMapInfo info;
       
   230 +  gst_buffer_map(buffer, &info, GST_MAP_READ);
       
   231 +  unsigned int size = info.size;
       
   232 +#else
       
   233    unsigned int size = GST_BUFFER_SIZE(buffer);
       
   234 +#endif
       
   235    int32_t frames = (size / sizeof(AudioDataValue)) / mInfo.mAudioChannels;
       
   236    ssize_t outSize = static_cast<size_t>(size / sizeof(AudioDataValue));
       
   237    nsAutoArrayPtr<AudioDataValue> data(new AudioDataValue[outSize]);
       
   238 +#if GST_VERSION_MAJOR == 1
       
   239 +  memcpy(data, info.data, info.size);
       
   240 +  gst_buffer_unmap(buffer, &info);
       
   241 +#else
       
   242    memcpy(data, GST_BUFFER_DATA(buffer), GST_BUFFER_SIZE(buffer));
       
   243 +#endif
       
   244    AudioData *audio = new AudioData(offset, timestamp, duration,
       
   245        frames, data.forget(), mInfo.mAudioChannels);
       
   246  
       
   247    mAudioQueue.Push(audio);
       
   248    gst_buffer_unref(buffer);
       
   249  
       
   250    return true;
       
   251  }
       
   252  
       
   253  bool GStreamerReader::DecodeVideoFrame(bool &aKeyFrameSkip,
       
   254                                           int64_t aTimeThreshold)
       
   255  {
       
   256    NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
       
   257  
       
   258 +#if GST_VERSION_MAJOR == 1
       
   259 +    GstSample *sample = NULL;
       
   260 +#endif
       
   261    GstBuffer *buffer = NULL;
       
   262    int64_t timestamp, nextTimestamp;
       
   263    while (true)
       
   264    {
       
   265      if (!WaitForDecodedData(&mVideoSinkBufferCount)) {
       
   266        mVideoQueue.Finish();
       
   267        break;
       
   268      }
       
   269      mDecoder->NotifyDecodedFrames(0, 1);
       
   270  
       
   271 +#if GST_VERSION_MAJOR == 1
       
   272 +    sample = gst_app_sink_pull_sample(mVideoAppSink);
       
   273 +    buffer = gst_sample_get_buffer(sample);
       
   274 +#else
       
   275      buffer = gst_app_sink_pull_buffer(mVideoAppSink);
       
   276 +#endif
       
   277      bool isKeyframe = !GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DISCONT);
       
   278      if ((aKeyFrameSkip && !isKeyframe)) {
       
   279 +#if GST_VERSION_MAJOR == 1
       
   280 +      gst_sample_unref(sample);
       
   281 +#else
       
   282        gst_buffer_unref(buffer);
       
   283 +#endif
       
   284        buffer = NULL;
       
   285        continue;
       
   286      }
       
   287  
       
   288      timestamp = GST_BUFFER_TIMESTAMP(buffer);
       
   289      {
       
   290        ReentrantMonitorAutoEnter mon(mGstThreadsMonitor);
       
   291        timestamp = gst_segment_to_stream_time(&mVideoSegment,
       
   292 @@ -431,62 +481,90 @@ bool GStreamerReader::DecodeVideoFrame(b
       
   293      else if (fpsNum && fpsDen)
       
   294        /* add 1-frame duration */
       
   295        nextTimestamp += gst_util_uint64_scale(GST_USECOND, fpsNum, fpsDen);
       
   296  
       
   297      if (timestamp < aTimeThreshold) {
       
   298        LOG(PR_LOG_DEBUG, ("skipping frame %" GST_TIME_FORMAT
       
   299              " threshold %" GST_TIME_FORMAT,
       
   300              GST_TIME_ARGS(timestamp), GST_TIME_ARGS(aTimeThreshold)));
       
   301 +#if GST_VERSION_MAJOR == 1
       
   302 +      gst_sample_unref(sample);
       
   303 +#else
       
   304        gst_buffer_unref(buffer);
       
   305 +#endif
       
   306        buffer = NULL;
       
   307        continue;
       
   308      }
       
   309  
       
   310      break;
       
   311    }
       
   312  
       
   313    if (buffer == NULL)
       
   314      /* no more frames */
       
   315      return false;
       
   316  
       
   317 +#if GST_VERSION_MAJOR == 1
       
   318 +  GstMapInfo info;
       
   319 +  gst_buffer_map(buffer, &info, GST_MAP_READ);
       
   320 +  guint8 *data = info.data;
       
   321 +#else
       
   322    guint8 *data = GST_BUFFER_DATA(buffer);
       
   323 +#endif
       
   324  
       
   325    int width = mPicture.width;
       
   326    int height = mPicture.height;
       
   327    GstVideoFormat format = mFormat;
       
   328  
       
   329    VideoData::YCbCrBuffer b;
       
   330 +#if GST_VERSION_MAJOR == 1
       
   331 +  GstVideoInfo *video_info;
       
   332 +  gst_video_info_set_format(video_info, format, width, height);
       
   333 +  for(int i = 0; i < 3; i++) {
       
   334 +    b.mPlanes[i].mData = data + GST_VIDEO_INFO_COMP_OFFSET(video_info, i);
       
   335 +    b.mPlanes[i].mStride = GST_VIDEO_INFO_COMP_STRIDE(video_info, i);
       
   336 +    b.mPlanes[i].mHeight = GST_VIDEO_INFO_COMP_HEIGHT(video_info, i);
       
   337 +    b.mPlanes[i].mWidth = GST_VIDEO_INFO_COMP_WIDTH(video_info, i);
       
   338 +    b.mPlanes[i].mOffset = 0;
       
   339 +    b.mPlanes[i].mSkip = 0;
       
   340 +  }
       
   341 +#else
       
   342    for(int i = 0; i < 3; i++) {
       
   343      b.mPlanes[i].mData = data + gst_video_format_get_component_offset(format, i,
       
   344          width, height);
       
   345      b.mPlanes[i].mStride = gst_video_format_get_row_stride(format, i, width);
       
   346      b.mPlanes[i].mHeight = gst_video_format_get_component_height(format,
       
   347          i, height);
       
   348      b.mPlanes[i].mWidth = gst_video_format_get_component_width(format,
       
   349          i, width);
       
   350      b.mPlanes[i].mOffset = 0;
       
   351      b.mPlanes[i].mSkip = 0;
       
   352    }
       
   353 +#endif
       
   354  
       
   355    bool isKeyframe = !GST_BUFFER_FLAG_IS_SET(buffer,
       
   356        GST_BUFFER_FLAG_DELTA_UNIT);
       
   357    /* XXX ? */
       
   358    int64_t offset = 0;
       
   359    VideoData *video = VideoData::Create(mInfo,
       
   360                                         mDecoder->GetImageContainer(),
       
   361                                         offset,
       
   362                                         timestamp,
       
   363                                         nextTimestamp,
       
   364                                         b,
       
   365                                         isKeyframe,
       
   366                                         -1,
       
   367                                         mPicture);
       
   368    mVideoQueue.Push(video);
       
   369 +#if GST_VERSION_MAJOR == 1
       
   370 +  gst_buffer_unmap(buffer, &info);
       
   371 +  gst_sample_unref(sample);
       
   372 +#else
       
   373    gst_buffer_unref(buffer);
       
   374 +#endif
       
   375  
       
   376    return true;
       
   377  }
       
   378  
       
   379  nsresult GStreamerReader::Seek(int64_t aTarget,
       
   380                                   int64_t aStartTime,
       
   381                                   int64_t aEndTime,
       
   382                                   int64_t aCurrentTime)
       
   383 @@ -509,52 +587,62 @@ nsresult GStreamerReader::Seek(int64_t a
       
   384  
       
   385  nsresult GStreamerReader::GetBuffered(nsTimeRanges* aBuffered,
       
   386                                          int64_t aStartTime)
       
   387  {
       
   388    if (!mInfo.mHasVideo && !mInfo.mHasAudio) {
       
   389      return NS_OK;
       
   390    }
       
   391  
       
   392 -  GstFormat format = GST_FORMAT_TIME;
       
   393 +#if GST_VERSION_MAJOR == 0
       
   394 +    GstFormat format = GST_FORMAT_TIME;
       
   395 +#endif
       
   396 +
       
   397    MediaResource* resource = mDecoder->GetResource();
       
   398    gint64 resourceLength = resource->GetLength();
       
   399    nsTArray<MediaByteRange> ranges;
       
   400    resource->GetCachedRanges(ranges);
       
   401  
       
   402    if (mDecoder->OnStateMachineThread())
       
   403      /* Report the position from here while buffering as we can't report it from
       
   404       * the gstreamer threads that are actually reading from the resource
       
   405       */
       
   406      NotifyBytesConsumed();
       
   407  
       
   408    if (resource->IsDataCachedToEndOfResource(0)) {
       
   409      /* fast path for local or completely cached files */
       
   410      gint64 duration = 0;
       
   411 -    GstFormat format = GST_FORMAT_TIME;
       
   412 -
       
   413      duration = QueryDuration();
       
   414      double end = (double) duration / GST_MSECOND;
       
   415      LOG(PR_LOG_DEBUG, ("complete range [0, %f] for [0, %li]",
       
   416            end, resourceLength));
       
   417      aBuffered->Add(0, end);
       
   418      return NS_OK;
       
   419    }
       
   420  
       
   421    for(uint32_t index = 0; index < ranges.Length(); index++) {
       
   422      int64_t startOffset = ranges[index].mStart;
       
   423      int64_t endOffset = ranges[index].mEnd;
       
   424      gint64 startTime, endTime;
       
   425  
       
   426 +#if GST_VERSION_MAJOR == 1
       
   427 +    if (!gst_element_query_convert(GST_ELEMENT(mPlayBin), GST_FORMAT_BYTES,
       
   428 +      startOffset, GST_FORMAT_TIME, &startTime))
       
   429 +      continue;
       
   430 +    if (!gst_element_query_convert(GST_ELEMENT(mPlayBin), GST_FORMAT_BYTES,
       
   431 +      endOffset, GST_FORMAT_TIME, &endTime))
       
   432 +      continue;
       
   433 +#else
       
   434      if (!gst_element_query_convert(GST_ELEMENT(mPlayBin), GST_FORMAT_BYTES,
       
   435        startOffset, &format, &startTime) || format != GST_FORMAT_TIME)
       
   436        continue;
       
   437      if (!gst_element_query_convert(GST_ELEMENT(mPlayBin), GST_FORMAT_BYTES,
       
   438        endOffset, &format, &endTime) || format != GST_FORMAT_TIME)
       
   439        continue;
       
   440 +#endif
       
   441  
       
   442      double start = start = (double) GST_TIME_AS_USECONDS (startTime) / GST_MSECOND;
       
   443      double end = (double) GST_TIME_AS_USECONDS (endTime) / GST_MSECOND;
       
   444      LOG(PR_LOG_DEBUG, ("adding range [%f, %f] for [%li %li] size %li",
       
   445            start, end, startOffset, endOffset, resourceLength));
       
   446      aBuffered->Add(start, end);
       
   447    }
       
   448  
       
   449 @@ -563,48 +651,64 @@ nsresult GStreamerReader::GetBuffered(ns
       
   450  
       
   451  void GStreamerReader::ReadAndPushData(guint aLength)
       
   452  {
       
   453    MediaResource* resource = mDecoder->GetResource();
       
   454    NS_ASSERTION(resource, "Decoder has no media resource");
       
   455    nsresult rv = NS_OK;
       
   456  
       
   457    GstBuffer *buffer = gst_buffer_new_and_alloc(aLength);
       
   458 +#if GST_VERSION_MAJOR == 1
       
   459 +  GstMapInfo info;
       
   460 +  gst_buffer_map(buffer, &info, GST_MAP_WRITE);
       
   461 +  guint8 *data = info.data;
       
   462 +#else
       
   463    guint8 *data = GST_BUFFER_DATA(buffer);
       
   464 +#endif
       
   465    uint32_t size = 0, bytesRead = 0;
       
   466    while(bytesRead < aLength) {
       
   467      rv = resource->Read(reinterpret_cast<char*>(data + bytesRead),
       
   468          aLength - bytesRead, &size);
       
   469      if (NS_FAILED(rv) || size == 0)
       
   470        break;
       
   471  
       
   472      bytesRead += size;
       
   473    }
       
   474  
       
   475 +#if GST_VERSION_MAJOR == 1
       
   476 +  info.size = bytesRead;
       
   477 +  gst_buffer_unmap(buffer, &info);
       
   478 +#else
       
   479    GST_BUFFER_SIZE(buffer) = bytesRead;
       
   480 +#endif
       
   481    mByteOffset += bytesRead;
       
   482  
       
   483    GstFlowReturn ret = gst_app_src_push_buffer(mSource, gst_buffer_ref(buffer));
       
   484    if (ret != GST_FLOW_OK)
       
   485      LOG(PR_LOG_ERROR, ("ReadAndPushData push ret %s", gst_flow_get_name(ret)));
       
   486  
       
   487 -  if (GST_BUFFER_SIZE (buffer) < aLength)
       
   488 +  if (bytesRead < aLength)
       
   489      /* If we read less than what we wanted, we reached the end */
       
   490      gst_app_src_end_of_stream(mSource);
       
   491  
       
   492    gst_buffer_unref(buffer);
       
   493  }
       
   494  
       
   495  int64_t GStreamerReader::QueryDuration()
       
   496  {
       
   497    gint64 duration = 0;
       
   498    GstFormat format = GST_FORMAT_TIME;
       
   499  
       
   500 +#if GST_VERSION_MAJOR == 1
       
   501 +  if (gst_element_query_duration(GST_ELEMENT(mPlayBin),
       
   502 +      format, &duration)) {
       
   503 +#else
       
   504    if (gst_element_query_duration(GST_ELEMENT(mPlayBin),
       
   505        &format, &duration)) {
       
   506 +#endif
       
   507      if (format == GST_FORMAT_TIME) {
       
   508        LOG(PR_LOG_DEBUG, ("pipeline duration %" GST_TIME_FORMAT,
       
   509              GST_TIME_ARGS (duration)));
       
   510        duration = GST_TIME_AS_USECONDS (duration);
       
   511      }
       
   512    }
       
   513  
       
   514    /*if (mDecoder->mDuration != -1 &&
       
   515 @@ -668,60 +772,95 @@ gboolean GStreamerReader::SeekData(GstAp
       
   516    if (NS_SUCCEEDED(rv))
       
   517      mByteOffset = mLastReportedByteOffset = aOffset;
       
   518    else
       
   519      LOG(PR_LOG_ERROR, ("seek at %lu failed", aOffset));
       
   520  
       
   521    return NS_SUCCEEDED(rv);
       
   522  }
       
   523  
       
   524 +#if GST_VERSION_MAJOR == 1
       
   525 +GstPadProbeReturn GStreamerReader::EventProbeCb(GstPad *aPad,
       
   526 +                                                GstPadProbeInfo *aInfo,
       
   527 +                                                gpointer aUserData)
       
   528 +{
       
   529 +  GStreamerReader *reader = (GStreamerReader *) aUserData;
       
   530 +  GstEvent *aEvent = (GstEvent *)aInfo->data;
       
   531 +  return reader->EventProbe(aPad, aEvent);
       
   532 +}
       
   533 +#else
       
   534  gboolean GStreamerReader::EventProbeCb(GstPad *aPad,
       
   535                                           GstEvent *aEvent,
       
   536                                           gpointer aUserData)
       
   537  {
       
   538    GStreamerReader *reader = (GStreamerReader *) aUserData;
       
   539    return reader->EventProbe(aPad, aEvent);
       
   540  }
       
   541 +#endif
       
   542  
       
   543 +#if GST_VERSION_MAJOR == 1
       
   544 +GstPadProbeReturn GStreamerReader::EventProbe(GstPad *aPad, GstEvent *aEvent)
       
   545 +#else
       
   546  gboolean GStreamerReader::EventProbe(GstPad *aPad, GstEvent *aEvent)
       
   547 +#endif
       
   548  {
       
   549    GstElement *parent = GST_ELEMENT(gst_pad_get_parent(aPad));
       
   550    switch(GST_EVENT_TYPE(aEvent)) {
       
   551 +#if GST_VERSION_MAJOR == 1
       
   552 +    case GST_EVENT_SEGMENT:
       
   553 +#else
       
   554      case GST_EVENT_NEWSEGMENT:
       
   555 +#endif
       
   556      {
       
   557 +#if GST_VERSION_MAJOR == 1
       
   558 +      const GstSegment *newSegment;
       
   559 +#else
       
   560        gboolean update;
       
   561        gdouble rate;
       
   562        GstFormat format;
       
   563        gint64 start, stop, position;
       
   564 +#endif
       
   565        GstSegment *segment;
       
   566  
       
   567        /* Store the segments so we can convert timestamps to stream time, which
       
   568         * is what the upper layers sync on.
       
   569         */
       
   570        ReentrantMonitorAutoEnter mon(mGstThreadsMonitor);
       
   571 +#if GST_VERSION_MAJOR == 1
       
   572 +      gst_event_parse_segment(aEvent, &newSegment);
       
   573 +#else
       
   574        gst_event_parse_new_segment(aEvent, &update, &rate, &format,
       
   575            &start, &stop, &position);
       
   576 +#endif
       
   577        if (parent == GST_ELEMENT(mVideoAppSink))
       
   578          segment = &mVideoSegment;
       
   579        else
       
   580          segment = &mAudioSegment;
       
   581 +#if GST_VERSION_MAJOR == 1
       
   582 +      gst_segment_copy_into (newSegment, segment);
       
   583 +#else
       
   584        gst_segment_set_newsegment(segment, update, rate, format,
       
   585            start, stop, position);
       
   586 +#endif
       
   587        break;
       
   588      }
       
   589      case GST_EVENT_FLUSH_STOP:
       
   590        /* Reset on seeks */
       
   591        ResetDecode();
       
   592        break;
       
   593      default:
       
   594        break;
       
   595    }
       
   596    gst_object_unref(parent);
       
   597  
       
   598 +#if GST_VERSION_MAJOR == 1
       
   599 +  return GST_PAD_PROBE_OK;
       
   600 +#else
       
   601    return TRUE;
       
   602 +#endif
       
   603  }
       
   604  
       
   605  GstFlowReturn GStreamerReader::NewPrerollCb(GstAppSink *aSink,
       
   606                                                gpointer aUserData)
       
   607  {
       
   608    GStreamerReader *reader = (GStreamerReader *) aUserData;
       
   609  
       
   610    if (aSink == reader->mVideoAppSink)
       
   611 @@ -730,18 +869,22 @@ GstFlowReturn GStreamerReader::NewPrerol
       
   612      reader->AudioPreroll();
       
   613    return GST_FLOW_OK;
       
   614  }
       
   615  
       
   616  void GStreamerReader::AudioPreroll()
       
   617  {
       
   618    /* The first audio buffer has reached the audio sink. Get rate and channels */
       
   619    LOG(PR_LOG_DEBUG, ("Audio preroll"));
       
   620 -  GstPad *sinkpad = gst_element_get_pad(GST_ELEMENT(mAudioAppSink), "sink");
       
   621 +  GstPad *sinkpad = gst_element_get_static_pad(GST_ELEMENT(mAudioAppSink), "sink");
       
   622 +#if GST_VERSION_MAJOR == 1
       
   623 +  GstCaps *caps = gst_pad_get_current_caps(sinkpad);
       
   624 +#else
       
   625    GstCaps *caps = gst_pad_get_negotiated_caps(sinkpad);
       
   626 +#endif
       
   627    GstStructure *s = gst_caps_get_structure(caps, 0);
       
   628    mInfo.mAudioRate = mInfo.mAudioChannels = 0;
       
   629    gst_structure_get_int(s, "rate", (gint *) &mInfo.mAudioRate);
       
   630    gst_structure_get_int(s, "channels", (gint *) &mInfo.mAudioChannels);
       
   631    NS_ASSERTION(mInfo.mAudioRate != 0, ("audio rate is zero"));
       
   632    NS_ASSERTION(mInfo.mAudioChannels != 0, ("audio channels is zero"));
       
   633    NS_ASSERTION(mInfo.mAudioChannels > 0 && mInfo.mAudioChannels <= MAX_CHANNELS,
       
   634        "invalid audio channels number");
       
   635 @@ -749,19 +892,29 @@ void GStreamerReader::AudioPreroll()
       
   636    gst_caps_unref(caps);
       
   637    gst_object_unref(sinkpad);
       
   638  }
       
   639  
       
   640  void GStreamerReader::VideoPreroll()
       
   641  {
       
   642    /* The first video buffer has reached the video sink. Get width and height */
       
   643    LOG(PR_LOG_DEBUG, ("Video preroll"));
       
   644 -  GstPad *sinkpad = gst_element_get_pad(GST_ELEMENT(mVideoAppSink), "sink");
       
   645 +  GstPad *sinkpad = gst_element_get_static_pad(GST_ELEMENT(mVideoAppSink), "sink");
       
   646 +#if GST_VERSION_MAJOR == 1
       
   647 +  GstCaps *caps = gst_pad_get_current_caps(sinkpad);
       
   648 +  GstVideoInfo info;
       
   649 +  memset (&info, 0, sizeof (info));
       
   650 +  gst_video_info_from_caps(&info, caps);
       
   651 +  mFormat = info.finfo->format;
       
   652 +  mPicture.width = info.width;
       
   653 +  mPicture.height = info.height;
       
   654 +#else
       
   655    GstCaps *caps = gst_pad_get_negotiated_caps(sinkpad);
       
   656    gst_video_format_parse_caps(caps, &mFormat, &mPicture.width, &mPicture.height);
       
   657 +#endif
       
   658    GstStructure *structure = gst_caps_get_structure(caps, 0);
       
   659    gst_structure_get_fraction(structure, "framerate", &fpsNum, &fpsDen);
       
   660    NS_ASSERTION(mPicture.width && mPicture.height, "invalid video resolution");
       
   661    mInfo.mDisplay = nsIntSize(mPicture.width, mPicture.height);
       
   662    mInfo.mHasVideo = true;
       
   663    gst_caps_unref(caps);
       
   664    gst_object_unref(sinkpad);
       
   665  }
       
   666 diff --git a/content/media/gstreamer/GStreamerReader.h b/content/media/gstreamer/GStreamerReader.h
       
   667 --- a/content/media/gstreamer/GStreamerReader.h
       
   668 +++ b/content/media/gstreamer/GStreamerReader.h
       
   669 @@ -71,18 +71,23 @@ private:
       
   670  
       
   671    /* Called when a seek is issued on the pipeline */
       
   672    static gboolean SeekDataCb(GstAppSrc *aSrc,
       
   673                               guint64 aOffset,
       
   674                               gpointer aUserData);
       
   675    gboolean SeekData(GstAppSrc *aSrc, guint64 aOffset);
       
   676  
       
   677    /* Called when events reach the sinks. See inline comments */
       
   678 +#if GST_VERSION_MAJOR == 1
       
   679 +  static GstPadProbeReturn EventProbeCb(GstPad *aPad, GstPadProbeInfo *aInfo, gpointer aUserData);
       
   680 +  GstPadProbeReturn EventProbe(GstPad *aPad, GstEvent *aEvent);
       
   681 +#else
       
   682    static gboolean EventProbeCb(GstPad *aPad, GstEvent *aEvent, gpointer aUserData);
       
   683    gboolean EventProbe(GstPad *aPad, GstEvent *aEvent);
       
   684 +#endif
       
   685  
       
   686    /* Called when the pipeline is prerolled, that is when at start or after a
       
   687     * seek, the first audio and video buffers are queued in the sinks.
       
   688     */
       
   689    static GstFlowReturn NewPrerollCb(GstAppSink *aSink, gpointer aUserData);
       
   690    void VideoPreroll();
       
   691    void AudioPreroll();
       
   692