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