Bug 1250054. Part 1 - add new files and move StartTimeRendezvous from MediaDecoderStateMachine.h to MediaDecoderReaderWrapper.cpp. r=jya.
☠☠ backed out by 97001a5fbcb5 ☠ ☠
authorJW Wang <jwwang@mozilla.com>
Tue, 29 Mar 2016 14:48:11 +0800
changeset 290912 15058cd337313e26ee0cc699826dcbe7f448c977
parent 290911 ab6ca47677a8219cb08014f02fd41bc7dd83b9a4
child 290913 fe425b8cb8cbe0260d3ce1ff1746831f3b65ad02
push id19656
push usergwagner@mozilla.com
push dateMon, 04 Apr 2016 13:43:23 +0000
treeherderb2g-inbound@e99061fde28a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjya
bugs1250054
milestone48.0a1
Bug 1250054. Part 1 - add new files and move StartTimeRendezvous from MediaDecoderStateMachine.h to MediaDecoderReaderWrapper.cpp. r=jya.
dom/media/MediaDecoderReaderWrapper.cpp
dom/media/MediaDecoderReaderWrapper.h
dom/media/MediaDecoderStateMachine.h
dom/media/moz.build
new file mode 100644
--- /dev/null
+++ b/dom/media/MediaDecoderReaderWrapper.cpp
@@ -0,0 +1,148 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/MozPromise.h"
+#include "MediaDecoderReaderWrapper.h"
+
+namespace mozilla {
+
+extern LazyLogModule gMediaDecoderLog;
+
+#undef LOG
+#define LOG(...) \
+  MOZ_LOG(gMediaDecoderLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
+
+// StartTimeRendezvous is a helper class that quarantines the first sample
+// until it gets a sample from both channels, such that we can be guaranteed
+// to know the start time by the time On{Audio,Video}Decoded is called on MDSM.
+class StartTimeRendezvous {
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(StartTimeRendezvous);
+  typedef MediaDecoderReader::AudioDataPromise AudioDataPromise;
+  typedef MediaDecoderReader::VideoDataPromise VideoDataPromise;
+
+public:
+  StartTimeRendezvous(AbstractThread* aOwnerThread,
+                      bool aHasAudio,
+                      bool aHasVideo,
+                      bool aForceZeroStartTime)
+    : mOwnerThread(aOwnerThread)
+  {
+    if (aForceZeroStartTime) {
+      mAudioStartTime.emplace(0);
+      mVideoStartTime.emplace(0);
+      return;
+    }
+    if (!aHasAudio) {
+      mAudioStartTime.emplace(INT64_MAX);
+    }
+    if (!aHasVideo) {
+      mVideoStartTime.emplace(INT64_MAX);
+    }
+  }
+
+  void Destroy()
+  {
+    mAudioStartTime = Some(mAudioStartTime.refOr(INT64_MAX));
+    mVideoStartTime = Some(mVideoStartTime.refOr(INT64_MAX));
+    mHaveStartTimePromise.RejectIfExists(false, __func__);
+  }
+
+  RefPtr<HaveStartTimePromise> AwaitStartTime()
+  {
+    if (HaveStartTime()) {
+      return HaveStartTimePromise::CreateAndResolve(true, __func__);
+    }
+    return mHaveStartTimePromise.Ensure(__func__);
+  }
+
+  template<typename PromiseType>
+  struct PromiseSampleType {
+    typedef typename PromiseType::ResolveValueType::element_type Type;
+  };
+
+  template<typename PromiseType, MediaData::Type SampleType>
+  RefPtr<PromiseType>
+  ProcessFirstSample(typename PromiseSampleType<PromiseType>::Type* aData)
+  {
+    typedef typename PromiseSampleType<PromiseType>::Type DataType;
+    typedef typename PromiseType::Private PromisePrivate;
+    MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
+
+    MaybeSetChannelStartTime<SampleType>(aData->mTime);
+
+    RefPtr<PromisePrivate> p = new PromisePrivate(__func__);
+    RefPtr<DataType> data = aData;
+    RefPtr<StartTimeRendezvous> self = this;
+    AwaitStartTime()->Then(
+      mOwnerThread, __func__,
+      [p, data, self] () {
+        MOZ_ASSERT(self->mOwnerThread->IsCurrentThreadIn());
+        p->Resolve(data, __func__);
+      },
+      [p] () {
+        p->Reject(MediaDecoderReader::CANCELED, __func__);
+      });
+
+    return p.forget();
+  }
+
+  template<MediaData::Type SampleType>
+  void FirstSampleRejected(MediaDecoderReader::NotDecodedReason aReason)
+  {
+    MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
+    if (aReason == MediaDecoderReader::DECODE_ERROR) {
+      mHaveStartTimePromise.RejectIfExists(false, __func__);
+    } else if (aReason == MediaDecoderReader::END_OF_STREAM) {
+      LOG("StartTimeRendezvous=%p SampleType(%d) Has no samples.",
+           this, SampleType);
+      MaybeSetChannelStartTime<SampleType>(INT64_MAX);
+    }
+  }
+
+  bool HaveStartTime() const
+  {
+    return mAudioStartTime.isSome() && mVideoStartTime.isSome();
+  }
+
+  int64_t StartTime() const
+  {
+    int64_t time = std::min(mAudioStartTime.ref(), mVideoStartTime.ref());
+    return time == INT64_MAX ? 0 : time;
+  }
+
+private:
+  ~StartTimeRendezvous() {}
+
+  template<MediaData::Type SampleType>
+  void MaybeSetChannelStartTime(int64_t aStartTime)
+  {
+    if (ChannelStartTime(SampleType).isSome()) {
+      // If we're initialized with aForceZeroStartTime=true, the channel start
+      // times are already set.
+      return;
+    }
+
+    LOG("StartTimeRendezvous=%p Setting SampleType(%d) start time to %lld",
+        this, SampleType, aStartTime);
+
+    ChannelStartTime(SampleType).emplace(aStartTime);
+    if (HaveStartTime()) {
+      mHaveStartTimePromise.ResolveIfExists(true, __func__);
+    }
+  }
+
+  Maybe<int64_t>& ChannelStartTime(MediaData::Type aType)
+  {
+    return aType == MediaData::AUDIO_DATA ? mAudioStartTime : mVideoStartTime;
+  }
+
+  MozPromiseHolder<HaveStartTimePromise> mHaveStartTimePromise;
+  RefPtr<AbstractThread> mOwnerThread;
+  Maybe<int64_t> mAudioStartTime;
+  Maybe<int64_t> mVideoStartTime;
+};
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/media/MediaDecoderReaderWrapper.h
@@ -0,0 +1,24 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef MediaDecoderReaderWrapper_h_
+#define MediaDecoderReaderWrapper_h_
+
+#include "mozilla/AbstractThread.h"
+#include "mozilla/RefPtr.h"
+#include "nsISupportsImpl.h"
+
+#include "MediaDecoderReader.h"
+
+namespace mozilla {
+
+class StartTimeRendezvous;
+
+typedef MozPromise<bool, bool, /* isExclusive = */ false> HaveStartTimePromise;
+
+} // namespace mozilla
+
+#endif // MediaDecoderReaderWrapper_h_
--- a/dom/media/MediaDecoderStateMachine.h
+++ b/dom/media/MediaDecoderStateMachine.h
@@ -689,143 +689,16 @@ private:
 
   // True if we've dispatched a task to run the state machine but the task has
   // yet to run.
   bool mDispatchedStateMachine;
 
   // Used to dispatch another round schedule with specific target time.
   DelayedScheduler mDelayedScheduler;
 
-  // StartTimeRendezvous is a helper class that quarantines the first sample
-  // until it gets a sample from both channels, such that we can be guaranteed
-  // to know the start time by the time On{Audio,Video}Decoded is called.
-  class StartTimeRendezvous {
-  public:
-    typedef MediaDecoderReader::AudioDataPromise AudioDataPromise;
-    typedef MediaDecoderReader::VideoDataPromise VideoDataPromise;
-    typedef MozPromise<bool, bool, /* isExclusive = */ false> HaveStartTimePromise;
-
-    NS_INLINE_DECL_THREADSAFE_REFCOUNTING(StartTimeRendezvous);
-    StartTimeRendezvous(AbstractThread* aOwnerThread, bool aHasAudio, bool aHasVideo,
-                        bool aForceZeroStartTime)
-      : mOwnerThread(aOwnerThread)
-    {
-      if (aForceZeroStartTime) {
-        mAudioStartTime.emplace(0);
-        mVideoStartTime.emplace(0);
-        return;
-      }
-
-      if (!aHasAudio) {
-        mAudioStartTime.emplace(INT64_MAX);
-      }
-
-      if (!aHasVideo) {
-        mVideoStartTime.emplace(INT64_MAX);
-      }
-    }
-
-    void Destroy()
-    {
-      mAudioStartTime = Some(mAudioStartTime.refOr(INT64_MAX));
-      mVideoStartTime = Some(mVideoStartTime.refOr(INT64_MAX));
-      mHaveStartTimePromise.RejectIfExists(false, __func__);
-    }
-
-    RefPtr<HaveStartTimePromise> AwaitStartTime()
-    {
-      if (HaveStartTime()) {
-        return HaveStartTimePromise::CreateAndResolve(true, __func__);
-      }
-      return mHaveStartTimePromise.Ensure(__func__);
-    }
-
-    template<typename PromiseType>
-    struct PromiseSampleType {
-      typedef typename PromiseType::ResolveValueType::element_type Type;
-    };
-
-    template<typename PromiseType, MediaData::Type SampleType>
-    RefPtr<PromiseType> ProcessFirstSample(typename PromiseSampleType<PromiseType>::Type* aData)
-    {
-      typedef typename PromiseSampleType<PromiseType>::Type DataType;
-      typedef typename PromiseType::Private PromisePrivate;
-      MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
-
-      MaybeSetChannelStartTime<SampleType>(aData->mTime);
-
-      RefPtr<PromisePrivate> p = new PromisePrivate(__func__);
-      RefPtr<DataType> data = aData;
-      RefPtr<StartTimeRendezvous> self = this;
-      AwaitStartTime()->Then(mOwnerThread, __func__,
-                             [p, data, self] () -> void {
-                               MOZ_ASSERT(self->mOwnerThread->IsCurrentThreadIn());
-                               p->Resolve(data, __func__);
-                             },
-                             [p] () -> void { p->Reject(MediaDecoderReader::CANCELED, __func__); });
-
-      return p.forget();
-    }
-
-    template<MediaData::Type SampleType>
-    void FirstSampleRejected(MediaDecoderReader::NotDecodedReason aReason)
-    {
-      MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
-      if (aReason == MediaDecoderReader::DECODE_ERROR) {
-        mHaveStartTimePromise.RejectIfExists(false, __func__);
-      } else if (aReason == MediaDecoderReader::END_OF_STREAM) {
-        MOZ_LOG(gMediaDecoderLog, LogLevel::Debug,
-                ("StartTimeRendezvous=%p SampleType(%d) Has no samples.", this, SampleType));
-        MaybeSetChannelStartTime<SampleType>(INT64_MAX);
-      }
-    }
-
-    bool HaveStartTime() { return mAudioStartTime.isSome() && mVideoStartTime.isSome(); }
-    int64_t StartTime()
-    {
-      int64_t time = std::min(mAudioStartTime.ref(), mVideoStartTime.ref());
-      return time == INT64_MAX ? 0 : time;
-    }
-  private:
-    virtual ~StartTimeRendezvous() {}
-
-    template<MediaData::Type SampleType>
-    void MaybeSetChannelStartTime(int64_t aStartTime)
-    {
-      if (ChannelStartTime(SampleType).isSome()) {
-        // If we're initialized with aForceZeroStartTime=true, the channel start
-        // times are already set.
-        return;
-      }
-
-      MOZ_LOG(gMediaDecoderLog, LogLevel::Debug,
-              ("StartTimeRendezvous=%p Setting SampleType(%d) start time to %lld",
-               this, SampleType, aStartTime));
-
-      ChannelStartTime(SampleType).emplace(aStartTime);
-      if (HaveStartTime()) {
-        mHaveStartTimePromise.ResolveIfExists(true, __func__);
-      }
-    }
-
-    Maybe<int64_t>& ChannelStartTime(MediaData::Type aType)
-    {
-      return aType == MediaData::AUDIO_DATA ? mAudioStartTime : mVideoStartTime;
-    }
-
-    MozPromiseHolder<HaveStartTimePromise> mHaveStartTimePromise;
-    RefPtr<AbstractThread> mOwnerThread;
-    Maybe<int64_t> mAudioStartTime;
-    Maybe<int64_t> mVideoStartTime;
-  };
-  RefPtr<StartTimeRendezvous> mStartTimeRendezvous;
-
-  bool HaveStartTime() { return mStartTimeRendezvous && mStartTimeRendezvous->HaveStartTime(); }
-  int64_t StartTime() { return mStartTimeRendezvous->StartTime(); }
-
   // Queue of audio frames. This queue is threadsafe, and is accessed from
   // the audio, decoder, state machine, and main threads.
   MediaQueue<MediaData> mAudioQueue;
   // Queue of video frames. This queue is threadsafe, and is accessed from
   // the decoder, state machine, and main threads.
   MediaQueue<MediaData> mVideoQueue;
 
   // The decoder monitor must be obtained before modifying this state.
--- a/dom/media/moz.build
+++ b/dom/media/moz.build
@@ -209,16 +209,17 @@ UNIFIED_SOURCES += [
     'FlushableTaskQueue.cpp',
     'GetUserMediaRequest.cpp',
     'GraphDriver.cpp',
     'Latency.cpp',
     'MediaCache.cpp',
     'MediaData.cpp',
     'MediaDecoder.cpp',
     'MediaDecoderReader.cpp',
+    'MediaDecoderReaderWrapper.cpp',
     'MediaDecoderStateMachine.cpp',
     'MediaDeviceInfo.cpp',
     'MediaDevices.cpp',
     'MediaFormatReader.cpp',
     'MediaManager.cpp',
     'MediaRecorder.cpp',
     'MediaResource.cpp',
     'MediaShutdownManager.cpp',