Backed out changeset 66f39ef1bdce (bug 1309516)
authorSebastian Hengst <archaeopteryx@coole-files.de>
Sat, 05 Nov 2016 11:00:12 +0100
changeset 321125 7244d8f6c4f30d02b5d16c8e73513a457081a228
parent 321124 420731164890399f40d6e657533708ca46b5a657
child 321126 1e1e71cf9feac94a4626178313022af9a128537f
push id30919
push userphilringnalda@gmail.com
push dateSat, 05 Nov 2016 20:28:20 +0000
treeherdermozilla-central@572249b2ffb6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1309516
milestone52.0a1
backs out66f39ef1bdcec3d3cdeedc91eb469d3a60301ac0
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out changeset 66f39ef1bdce (bug 1309516)
dom/media/MediaDecoderReaderWrapper.cpp
dom/media/MediaDecoderReaderWrapper.h
--- a/dom/media/MediaDecoderReaderWrapper.cpp
+++ b/dom/media/MediaDecoderReaderWrapper.cpp
@@ -4,16 +4,145 @@
  * 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 {
+  typedef MediaDecoderReader::MediaDataPromise MediaDataPromise;
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(StartTimeRendezvous);
+
+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<MediaData::Type SampleType>
+  RefPtr<MediaDataPromise>
+  ProcessFirstSample(MediaData* aData)
+  {
+    typedef typename MediaDataPromise::Private PromisePrivate;
+    MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
+
+    MaybeSetChannelStartTime<SampleType>(aData->mTime);
+
+    RefPtr<PromisePrivate> p = new PromisePrivate(__func__);
+    RefPtr<MediaData> 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(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
+      });
+
+    return p.forget();
+  }
+
+  template<MediaData::Type SampleType>
+  void FirstSampleRejected(const MediaResult& aError)
+  {
+    MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
+    if (aError == NS_ERROR_DOM_MEDIA_END_OF_STREAM) {
+      LOG("StartTimeRendezvous=%p SampleType(%d) Has no samples.",
+           this, SampleType);
+      MaybeSetChannelStartTime<SampleType>(INT64_MAX);
+    } else if (aError != NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA) {
+      mHaveStartTimePromise.RejectIfExists(false, __func__);
+    }
+  }
+
+  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;
+};
+
 MediaDecoderReaderWrapper::MediaDecoderReaderWrapper(AbstractThread* aOwnerThread,
                                                      MediaDecoderReader* aReader)
   : mForceZeroStartTime(aReader->ForceZeroStartTime())
   , mOwnerThread(aOwnerThread)
   , mReader(aReader)
 {}
 
 MediaDecoderReaderWrapper::~MediaDecoderReaderWrapper()
@@ -217,16 +346,20 @@ MediaDecoderReaderWrapper::ResetDecode(T
 RefPtr<ShutdownPromise>
 MediaDecoderReaderWrapper::Shutdown()
 {
   MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
   MOZ_ASSERT(!mAudioDataRequest.Exists());
   MOZ_ASSERT(!mVideoDataRequest.Exists());
 
   mShutdown = true;
+  if (mStartTimeRendezvous) {
+    mStartTimeRendezvous->Destroy();
+    mStartTimeRendezvous = nullptr;
+  }
   return InvokeAsync(mReader->OwnerThread(), mReader.get(), __func__,
                      &MediaDecoderReader::Shutdown);
 }
 
 void
 MediaDecoderReaderWrapper::OnMetadataRead(MetadataHolder* aMetadata)
 {
   MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
--- a/dom/media/MediaDecoderReaderWrapper.h
+++ b/dom/media/MediaDecoderReaderWrapper.h
@@ -12,16 +12,18 @@
 #include "mozilla/Variant.h"
 #include "nsISupportsImpl.h"
 
 #include "MediaDecoderReader.h"
 #include "MediaEventSource.h"
 
 namespace mozilla {
 
+class StartTimeRendezvous;
+
 typedef MozPromise<bool, bool, /* isExclusive = */ false> HaveStartTimePromise;
 
 typedef Variant<MediaData*, MediaResult> AudioCallbackData;
 typedef Variant<Tuple<MediaData*, TimeStamp>, MediaResult> VideoCallbackData;
 typedef Variant<MediaData::Type, WaitForDataRejectValue> WaitCallbackData;
 
 /**
  * A wrapper around MediaDecoderReader to offset the timestamps of Audio/Video
@@ -122,16 +124,17 @@ private:
   MediaCallbackExc<WaitCallbackData>& WaitCallbackRef(MediaData::Type aType);
   MozPromiseRequestHolder<WaitForDataPromise>& WaitRequestRef(MediaData::Type aType);
 
   const bool mForceZeroStartTime;
   const RefPtr<AbstractThread> mOwnerThread;
   const RefPtr<MediaDecoderReader> mReader;
 
   bool mShutdown = false;
+  RefPtr<StartTimeRendezvous> mStartTimeRendezvous;
   Maybe<media::TimeUnit> mStartTime;
 
   MozPromiseRequestHolder<MediaDataPromise> mAudioDataRequest;
   MozPromiseRequestHolder<MediaDataPromise> mVideoDataRequest;
   MozPromiseRequestHolder<WaitForDataPromise> mAudioWaitRequest;
   MozPromiseRequestHolder<WaitForDataPromise> mVideoWaitRequest;
 };