tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

MediaDecoderStateMachineBase.cpp (7775B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 #include "MediaDecoderStateMachineBase.h"
      6 
      7 #include "MediaDecoder.h"
      8 #include "mozilla/ProfilerMarkers.h"
      9 #include "mozilla/TaskQueue.h"
     10 #include "nsThreadUtils.h"
     11 
     12 namespace mozilla {
     13 
     14 #define INIT_MIRROR(name, val) \
     15  name(mTaskQueue, val, "MediaDecoderStateMachineBase::" #name " (Mirror)")
     16 #define INIT_CANONICAL(name, val) \
     17  name(mTaskQueue, val, "MediaDecoderStateMachineBase::" #name " (Canonical)")
     18 #define FMT(x, ...) "Decoder=%p " x, mDecoderID, ##__VA_ARGS__
     19 #define LOG(x, ...)                                                         \
     20  DDMOZ_LOG(gMediaDecoderLog, LogLevel::Debug, "Decoder=%p " x, mDecoderID, \
     21            ##__VA_ARGS__)
     22 #define LOGV(x, ...)                                                          \
     23  DDMOZ_LOG(gMediaDecoderLog, LogLevel::Verbose, "Decoder=%p " x, mDecoderID, \
     24            ##__VA_ARGS__)
     25 #define LOGW(x, ...) NS_WARNING(nsPrintfCString(FMT(x, ##__VA_ARGS__)).get())
     26 #define LOGE(x, ...)                                                   \
     27  NS_DebugBreak(NS_DEBUG_WARNING,                                      \
     28                nsPrintfCString(FMT(x, ##__VA_ARGS__)).get(), nullptr, \
     29                __FILE__, __LINE__)
     30 
     31 MediaDecoderStateMachineBase::MediaDecoderStateMachineBase(
     32    MediaDecoder* aDecoder, MediaFormatReader* aReader)
     33    : mDecoderID(aDecoder),
     34      mAbstractMainThread(aDecoder->AbstractMainThread()),
     35      mFrameStats(&aDecoder->GetFrameStatistics()),
     36      mVideoFrameContainer(aDecoder->GetVideoFrameContainer()),
     37      mTaskQueue(TaskQueue::Create(GetMediaThreadPool(MediaThreadType::MDSM),
     38                                   "MDSM::mTaskQueue",
     39                                   /* aSupportsTailDispatch = */ true)),
     40      mReader(new ReaderProxy(mTaskQueue, aReader)),
     41      mPlaybackRate(1.0),
     42      INIT_MIRROR(mBuffered, media::TimeIntervals()),
     43      INIT_MIRROR(mPlayState, MediaDecoder::PLAY_STATE_LOADING),
     44      INIT_MIRROR(mVolume, 1.0),
     45      INIT_MIRROR(mPreservesPitch, true),
     46      INIT_MIRROR(mLooping, false),
     47      INIT_MIRROR(mSecondaryVideoContainer, nullptr),
     48      INIT_CANONICAL(mDuration, media::NullableTimeUnit()),
     49      INIT_CANONICAL(mCurrentPosition, media::TimeUnit::Zero()),
     50      INIT_CANONICAL(mIsAudioDataAudible, false),
     51      mMinimizePreroll(aDecoder->GetMinimizePreroll()),
     52      mIsLiveStream(false),
     53      mWatchManager(this, mTaskQueue) {}
     54 
     55 MediaEventSource<void>& MediaDecoderStateMachineBase::OnMediaNotSeekable()
     56    const {
     57  return mReader->OnMediaNotSeekable();
     58 }
     59 
     60 AbstractCanonical<media::TimeIntervals>*
     61 MediaDecoderStateMachineBase::CanonicalBuffered() const {
     62  return mReader->CanonicalBuffered();
     63 }
     64 
     65 void MediaDecoderStateMachineBase::DispatchSetFragmentEndTime(
     66    const media::TimeUnit& aEndTime) {
     67  OwnerThread()->DispatchStateChange(NewRunnableMethod<media::TimeUnit>(
     68      "MediaDecoderStateMachineBase::SetFragmentEndTime", this,
     69      &MediaDecoderStateMachineBase::SetFragmentEndTime, aEndTime));
     70 }
     71 
     72 void MediaDecoderStateMachineBase::DispatchCanPlayThrough(
     73    bool aCanPlayThrough) {
     74  OwnerThread()->DispatchStateChange(NewRunnableMethod<bool>(
     75      "MediaDecoderStateMachineBase::SetCanPlayThrough", this,
     76      &MediaDecoderStateMachineBase::SetCanPlayThrough, aCanPlayThrough));
     77 }
     78 
     79 void MediaDecoderStateMachineBase::DispatchIsLiveStream(bool aIsLiveStream) {
     80  OwnerThread()->DispatchStateChange(NewRunnableMethod<bool>(
     81      "MediaDecoderStateMachineBase::SetIsLiveStream", this,
     82      &MediaDecoderStateMachineBase::SetIsLiveStream, aIsLiveStream));
     83 }
     84 
     85 void MediaDecoderStateMachineBase::DispatchSetPlaybackRate(
     86    double aPlaybackRate) {
     87  OwnerThread()->DispatchStateChange(NewRunnableMethod<double>(
     88      "MediaDecoderStateMachineBase::SetPlaybackRate", this,
     89      &MediaDecoderStateMachineBase::SetPlaybackRate, aPlaybackRate));
     90 }
     91 
     92 nsresult MediaDecoderStateMachineBase::Init(MediaDecoder* aDecoder) {
     93  MOZ_ASSERT(NS_IsMainThread());
     94 
     95  // Dispatch initialization that needs to happen on that task queue.
     96  nsCOMPtr<nsIRunnable> r = NewRunnableMethod<RefPtr<MediaDecoder>>(
     97      "MediaDecoderStateMachineBase::InitializationTask", this,
     98      &MediaDecoderStateMachineBase::InitializationTask, aDecoder);
     99  mTaskQueue->DispatchStateChange(r.forget());
    100 
    101  // Connect mirrors.
    102  aDecoder->CanonicalPlayState().ConnectMirror(&mPlayState);
    103  aDecoder->CanonicalVolume().ConnectMirror(&mVolume);
    104  aDecoder->CanonicalPreservesPitch().ConnectMirror(&mPreservesPitch);
    105  aDecoder->CanonicalLooping().ConnectMirror(&mLooping);
    106  aDecoder->CanonicalSecondaryVideoContainer().ConnectMirror(
    107      &mSecondaryVideoContainer);
    108 
    109  nsresult rv = mReader->Init();
    110  NS_ENSURE_SUCCESS(rv, rv);
    111 
    112  mMetadataManager.Connect(mReader->TimedMetadataEvent(), OwnerThread());
    113 
    114  return NS_OK;
    115 }
    116 
    117 void MediaDecoderStateMachineBase::InitializationTask(MediaDecoder* aDecoder) {
    118  MOZ_ASSERT(OnTaskQueue());
    119 
    120  // Connect mirrors.
    121  mBuffered.Connect(mReader->CanonicalBuffered());
    122  mReader->SetCanonicalDuration(mDuration);
    123 
    124  // Initialize watchers.
    125  mWatchManager.Watch(mBuffered,
    126                      &MediaDecoderStateMachineBase::BufferedRangeUpdated);
    127  mWatchManager.Watch(mVolume, &MediaDecoderStateMachineBase::VolumeChanged);
    128  mWatchManager.Watch(mPreservesPitch,
    129                      &MediaDecoderStateMachineBase::PreservesPitchChanged);
    130  mWatchManager.Watch(mPlayState,
    131                      &MediaDecoderStateMachineBase::PlayStateChanged);
    132  mWatchManager.Watch(mLooping, &MediaDecoderStateMachineBase::LoopingChanged);
    133  mWatchManager.Watch(
    134      mSecondaryVideoContainer,
    135      &MediaDecoderStateMachineBase::UpdateSecondaryVideoContainer);
    136 }
    137 
    138 RefPtr<ShutdownPromise> MediaDecoderStateMachineBase::BeginShutdown() {
    139  MOZ_ASSERT(NS_IsMainThread());
    140  return InvokeAsync(
    141      OwnerThread(), __func__,
    142      [self = RefPtr<MediaDecoderStateMachineBase>(this), this]() {
    143        mWatchManager.Shutdown();
    144        mBuffered.DisconnectIfConnected();
    145        mPlayState.DisconnectIfConnected();
    146        mVolume.DisconnectIfConnected();
    147        mPreservesPitch.DisconnectIfConnected();
    148        mLooping.DisconnectIfConnected();
    149        mSecondaryVideoContainer.DisconnectIfConnected();
    150        return Shutdown();
    151      });
    152 }
    153 
    154 RefPtr<MediaDecoder::SeekPromise> MediaDecoderStateMachineBase::InvokeSeek(
    155    const SeekTarget& aTarget) {
    156  return InvokeAsync(OwnerThread(), __func__,
    157                     [self = RefPtr<MediaDecoderStateMachineBase>(this),
    158                      target = aTarget]() { return self->Seek(target); });
    159 }
    160 
    161 bool MediaDecoderStateMachineBase::OnTaskQueue() const {
    162  return OwnerThread()->IsCurrentThreadIn();
    163 }
    164 
    165 void MediaDecoderStateMachineBase::DecodeError(const MediaResult& aError) {
    166  MOZ_ASSERT(OnTaskQueue());
    167  if (aError != NS_ERROR_DOM_MEDIA_EXTERNAL_ENGINE_NOT_SUPPORTED_ERR) {
    168    LOGE("Decode error: %s", aError.Description().get());
    169  }
    170  PROFILER_MARKER_TEXT("MDSMBase::DecodeError", MEDIA_PLAYBACK, {},
    171                       aError.Description());
    172  // Notify the decode error and MediaDecoder will shut down MDSM.
    173  mOnPlaybackErrorEvent.Notify(aError);
    174 #ifdef DEBUG
    175  mHasNotifiedPlaybackError = true;
    176 #endif
    177 }
    178 
    179 RefPtr<SetCDMPromise> MediaDecoderStateMachineBase::SetCDMProxy(
    180    CDMProxy* aProxy) {
    181  return mReader->SetCDMProxy(aProxy);
    182 }
    183 
    184 void MediaDecoderStateMachineBase::SetIsLiveStream(bool aIsLiveStream) {
    185  mIsLiveStream = aIsLiveStream;
    186 }
    187 
    188 bool MediaDecoderStateMachineBase::IsLiveStream() const {
    189  return mIsLiveStream;
    190 }
    191 
    192 #undef INIT_MIRROR
    193 #undef INIT_CANONICAL
    194 #undef FMT
    195 #undef LOG
    196 #undef LOGV
    197 #undef LOGW
    198 #undef LOGE
    199 
    200 }  // namespace mozilla