Commit 7800d98a authored by Andreas Pehrson's avatar Andreas Pehrson
Browse files

Bug 1172394 - Refactor how DecodedStream is set up. r=padenot

This patch removes the responsibility of js-facing MediaStreamTracks from the
MediaDecoder stack, and moves the machinery for setting up DecodedStream to
higher order functions like state mirroring and watchables.

OutputStreamManager is completely gone, since it was designed to manage
MediaStreamTracks across multiple output streams for a single decoder,
on main thread. HTMLMediaElement took over its task in the previous patch.

The MediaDecoderStateMachine now has three control points for capturing:
- mOutputCaptured, which, if true, will capture all decoded data into
  mOutputTracks. If this is set, but mOutputTracks is empty, we are still
  waiting for tracks, and DecodedStream will not play any data. When tracks are
  set, a new DecodedStream is created that will play data through
  SourceMediaTracks piped into mOutputTracks.
- mOutputTracks, which is the set of tracks data is captured into, for
  forwarding to all the output tracks the media element is managing. This set of
  tracks is managed by the MediaDecoder owner, and must contain one audio track
  if the decoder is decoding audio, and one video track if the decoder is
  decoding video. It may be empty since output can be captured before metadata
  is loaded, or playback has ended.
- mOutputPrincipal, which is the principal of the decoded data. All data sent
  into SourceMediaTracks is tagged with this principal.

Differential Revision: https://phabricator.services.mozilla.com/D52042

--HG--
extra : moz-landing-system : lando
parent 7fac8df5
Loading
Loading
Loading
Loading
+12 −5
Original line number Diff line number Diff line
@@ -235,14 +235,16 @@ void MediaDecoder::SetOutputCaptured(bool aCaptured) {
  MOZ_ASSERT(NS_IsMainThread());
  MOZ_ASSERT(mDecoderStateMachine, "Must be called after Load().");
  AbstractThread::AutoEnter context(AbstractMainThread());
  MOZ_CRASH("Not implemented");
  mOutputCaptured = aCaptured;
}

void MediaDecoder::AddOutputTrack(RefPtr<ProcessedMediaTrack> aTrack) {
  MOZ_ASSERT(NS_IsMainThread());
  MOZ_ASSERT(mDecoderStateMachine, "Must be called after Load().");
  AbstractThread::AutoEnter context(AbstractMainThread());
  MOZ_CRASH("Not implemented");
  nsTArray<RefPtr<ProcessedMediaTrack>> tracks = mOutputTracks;
  tracks.AppendElement(std::move(aTrack));
  mOutputTracks = tracks;
}

void MediaDecoder::RemoveOutputTrack(
@@ -250,7 +252,10 @@ void MediaDecoder::RemoveOutputTrack(
  MOZ_ASSERT(NS_IsMainThread());
  MOZ_ASSERT(mDecoderStateMachine, "Must be called after Load().");
  AbstractThread::AutoEnter context(AbstractMainThread());
  MOZ_CRASH("Not implemented");
  nsTArray<RefPtr<ProcessedMediaTrack>> tracks = mOutputTracks;
  if (tracks.RemoveElement(aTrack)) {
    mOutputTracks = tracks;
  }
}

void MediaDecoder::SetOutputTracksPrincipal(
@@ -258,7 +263,7 @@ void MediaDecoder::SetOutputTracksPrincipal(
  MOZ_ASSERT(NS_IsMainThread());
  MOZ_ASSERT(mDecoderStateMachine, "Must be called after Load().");
  AbstractThread::AutoEnter context(AbstractMainThread());
  MOZ_CRASH("Not implemented");
  mOutputPrincipal = MakePrincipalHandle(aPrincipal);
}

double MediaDecoder::GetDuration() {
@@ -304,6 +309,9 @@ MediaDecoder::MediaDecoder(MediaDecoderInit& aInit)
      INIT_CANONICAL(mVolume, aInit.mVolume),
      INIT_CANONICAL(mPreservesPitch, aInit.mPreservesPitch),
      INIT_CANONICAL(mLooping, aInit.mLooping),
      INIT_CANONICAL(mOutputCaptured, false),
      INIT_CANONICAL(mOutputTracks, nsTArray<RefPtr<ProcessedMediaTrack>>()),
      INIT_CANONICAL(mOutputPrincipal, PRINCIPAL_HANDLE_NONE),
      INIT_CANONICAL(mPlayState, PLAY_STATE_LOADING),
      mSameOriginMedia(false),
      mVideoDecodingOberver(
@@ -665,7 +673,6 @@ void MediaDecoder::MetadataLoaded(
  mMediaSeekableOnlyInBufferedRanges =
      aInfo->mMediaSeekableOnlyInBufferedRanges;
  mInfo = aInfo.release();
  mDecoderStateMachine->EnsureOutputStreamManagerHasTracks(*mInfo);

  // Make sure the element and the frame (if any) are told about
  // our new size.
+23 −4
Original line number Diff line number Diff line
@@ -49,7 +49,6 @@ class VideoFrameContainer;
class MediaFormatReader;
class MediaDecoderStateMachine;
struct MediaPlaybackEvent;
struct SharedDummyTrack;

enum class Visibility : uint8_t;

@@ -168,11 +167,11 @@ class MediaDecoder : public DecoderDoctorLifeLogger<MediaDecoder> {
  // not connected to streams created by captureStreamUntilEnded.

  // Turn output capturing of this decoder on or off. If it is on, the
  // MediaDecoderStateMachine will only create a MediaSink after output tracks
  // have been set. This is to ensure that it doesn't create a regular MediaSink
  // MediaDecoderStateMachine's media sink will only play after output tracks
  // have been set. This is to ensure that it doesn't skip over any data
  // while the owner has intended to capture the full output, thus missing to
  // capture some of it. The owner of the MediaDecoder is responsible for adding
  // output tracks while the output is captured.
  // output tracks in a timely fashion while the output is captured.
  void SetOutputCaptured(bool aCaptured);
  // Add an output track. All decoder output for the track's media type will be
  // sent to the track.
@@ -615,6 +614,16 @@ class MediaDecoder : public DecoderDoctorLifeLogger<MediaDecoder> {

  Canonical<bool> mLooping;

  // Whether this MediaDecoder's output is captured. When captured, all decoded
  // data must be played out through mOutputTracks.
  Canonical<bool> mOutputCaptured;

  // Tracks that, if set, will get data routed through them.
  Canonical<nsTArray<RefPtr<ProcessedMediaTrack>>> mOutputTracks;

  // PrincipalHandle to be used when feeding data into mOutputTracks.
  Canonical<PrincipalHandle> mOutputPrincipal;

  // Media duration set explicitly by JS. At present, this is only ever present
  // for MSE.
  Maybe<double> mExplicitDuration;
@@ -647,6 +656,16 @@ class MediaDecoder : public DecoderDoctorLifeLogger<MediaDecoder> {
    return &mPreservesPitch;
  }
  AbstractCanonical<bool>* CanonicalLooping() { return &mLooping; }
  AbstractCanonical<bool>* CanonicalOutputCaptured() {
    return &mOutputCaptured;
  }
  AbstractCanonical<nsTArray<RefPtr<ProcessedMediaTrack>>>*
  CanonicalOutputTracks() {
    return &mOutputTracks;
  }
  AbstractCanonical<PrincipalHandle>* CanonicalOutputPrincipal() {
    return &mOutputPrincipal;
  }
  AbstractCanonical<PlayState>* CanonicalPlayState() { return &mPlayState; }

 private:
+62 −131
Original line number Diff line number Diff line
@@ -11,7 +11,6 @@
#include "mediasink/AudioSink.h"
#include "mediasink/AudioSinkWrapper.h"
#include "mediasink/DecodedStream.h"
#include "mediasink/OutputStreamManager.h"
#include "mediasink/VideoSink.h"
#include "mozilla/Logging.h"
#include "mozilla/MathAlgorithms.h"
@@ -2592,6 +2591,9 @@ RefPtr<ShutdownPromise> MediaDecoderStateMachine::ShutdownState::Enter() {
  master->mVolume.DisconnectIfConnected();
  master->mPreservesPitch.DisconnectIfConnected();
  master->mLooping.DisconnectIfConnected();
  master->mOutputCaptured.DisconnectIfConnected();
  master->mOutputTracks.DisconnectIfConnected();
  master->mOutputPrincipal.DisconnectIfConnected();

  master->mDuration.DisconnectAll();
  master->mCurrentPosition.DisconnectAll();
@@ -2627,12 +2629,10 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
      mReader(new ReaderProxy(mTaskQueue, aReader)),
      mPlaybackRate(1.0),
      mAmpleAudioThreshold(detail::AMPLE_AUDIO_THRESHOLD),
      mAudioCaptured(false),
      mMinimizePreroll(aDecoder->GetMinimizePreroll()),
      mSentFirstFrameLoadedEvent(false),
      mVideoDecodeSuspended(false),
      mVideoDecodeSuspendTimer(mTaskQueue),
      mOutputStreamManager(nullptr),
      mVideoDecodeMode(VideoDecodeMode::Normal),
      mIsMSE(aDecoder->IsMSE()),
      mSeamlessLoopingAllowed(false),
@@ -2641,6 +2641,12 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
      INIT_MIRROR(mVolume, 1.0),
      INIT_MIRROR(mPreservesPitch, true),
      INIT_MIRROR(mLooping, false),
      INIT_MIRROR(mOutputCaptured, false),
      INIT_MIRROR(mOutputTracks, nsTArray<RefPtr<ProcessedMediaTrack>>()),
      INIT_MIRROR(mOutputPrincipal, PRINCIPAL_HANDLE_NONE),
      INIT_CANONICAL(mCanonicalOutputTracks,
                     nsTArray<RefPtr<ProcessedMediaTrack>>()),
      INIT_CANONICAL(mCanonicalOutputPrincipal, PRINCIPAL_HANDLE_NONE),
      INIT_CANONICAL(mDuration, NullableTimeUnit()),
      INIT_CANONICAL(mCurrentPosition, TimeUnit::Zero()),
      INIT_CANONICAL(mIsAudioDataAudible, false),
@@ -2671,6 +2677,9 @@ void MediaDecoderStateMachine::InitializationTask(MediaDecoder* aDecoder) {
  mVolume.Connect(aDecoder->CanonicalVolume());
  mPreservesPitch.Connect(aDecoder->CanonicalPreservesPitch());
  mLooping.Connect(aDecoder->CanonicalLooping());
  mOutputCaptured.Connect(aDecoder->CanonicalOutputCaptured());
  mOutputTracks.Connect(aDecoder->CanonicalOutputTracks());
  mOutputPrincipal.Connect(aDecoder->CanonicalOutputPrincipal());

  // Initialize watchers.
  mWatchManager.Watch(mBuffered,
@@ -2680,6 +2689,14 @@ void MediaDecoderStateMachine::InitializationTask(MediaDecoder* aDecoder) {
                      &MediaDecoderStateMachine::PreservesPitchChanged);
  mWatchManager.Watch(mPlayState, &MediaDecoderStateMachine::PlayStateChanged);
  mWatchManager.Watch(mLooping, &MediaDecoderStateMachine::LoopingChanged);
  mWatchManager.Watch(mOutputCaptured,
                      &MediaDecoderStateMachine::UpdateOutputCaptured);
  mWatchManager.Watch(mOutputTracks,
                      &MediaDecoderStateMachine::UpdateOutputCaptured);
  mWatchManager.Watch(mOutputTracks,
                      &MediaDecoderStateMachine::OutputTracksChanged);
  mWatchManager.Watch(mOutputPrincipal,
                      &MediaDecoderStateMachine::OutputPrincipalChanged);

  MOZ_ASSERT(!mStateObj);
  auto* s = new DecodeMetadataState(this);
@@ -2708,11 +2725,10 @@ MediaSink* MediaDecoderStateMachine::CreateAudioSink() {
}

already_AddRefed<MediaSink> MediaDecoderStateMachine::CreateMediaSink(
    bool aAudioCaptured, OutputStreamManager* aManager) {
  MOZ_ASSERT_IF(aAudioCaptured, aManager);
    bool aOutputCaptured) {
  RefPtr<MediaSink> audioSink =
      aAudioCaptured ? new DecodedStream(mTaskQueue, mAbstractMainThread,
                                         mAudioQueue, mVideoQueue, aManager)
      aOutputCaptured
          ? new DecodedStream(this, mOutputTracks, mAudioQueue, mVideoQueue)
          : CreateAudioSink();

  RefPtr<MediaSink> mediaSink =
@@ -2803,7 +2819,7 @@ nsresult MediaDecoderStateMachine::Init(MediaDecoder* aDecoder) {
  mOnMediaNotSeekable = mReader->OnMediaNotSeekable().Connect(
      OwnerThread(), this, &MediaDecoderStateMachine::SetMediaNotSeekable);

  mMediaSink = CreateMediaSink(mAudioCaptured, mOutputStreamManager);
  mMediaSink = CreateMediaSink(mOutputCaptured);

  nsresult rv = mReader->Init();
  NS_ENSURE_SUCCESS(rv, rv);
@@ -3340,9 +3356,6 @@ void MediaDecoderStateMachine::FinishDecodeFirstFrame() {

RefPtr<ShutdownPromise> MediaDecoderStateMachine::BeginShutdown() {
  MOZ_ASSERT(NS_IsMainThread());
  if (mOutputStreamManager) {
    mOutputStreamManager->Disconnect();
  }
  return InvokeAsync(OwnerThread(), this, __func__,
                     &MediaDecoderStateMachine::Shutdown);
}
@@ -3431,7 +3444,7 @@ void MediaDecoderStateMachine::UpdatePlaybackPositionPeriodically() {
    }
  }
  // Note we have to update playback position before releasing the monitor.
  // Otherwise, MediaDecoder::AddOutputStream could kick in when we are outside
  // Otherwise, MediaDecoder::AddOutputTrack could kick in when we are outside
  // the monitor and get a staled value from GetCurrentTimeUs() which hits the
  // assertion in GetClock().

@@ -3517,6 +3530,41 @@ void MediaDecoderStateMachine::LoopingChanged() {
  }
}

void MediaDecoderStateMachine::UpdateOutputCaptured() {
  MOZ_ASSERT(OnTaskQueue());

  // Reset these flags so they are consistent with the status of the sink.
  // TODO: Move these flags into MediaSink to improve cohesion so we don't need
  // to reset these flags when switching MediaSinks.
  mAudioCompleted = false;
  mVideoCompleted = false;

  // Stop and shut down the existing sink.
  StopMediaSink();
  mMediaSink->Shutdown();

  // Create a new sink according to whether output is captured.
  mMediaSink = CreateMediaSink(mOutputCaptured);

  // Don't buffer as much when audio is captured because we don't need to worry
  // about high latency audio devices.
  mAmpleAudioThreshold = mOutputCaptured ? detail::AMPLE_AUDIO_THRESHOLD / 2
                                         : detail::AMPLE_AUDIO_THRESHOLD;

  mStateObj->HandleAudioCaptured();
}

void MediaDecoderStateMachine::OutputTracksChanged() {
  MOZ_ASSERT(OnTaskQueue());
  LOG("OutputTracksChanged, tracks=%zu", mOutputTracks.Ref().Length());
  mCanonicalOutputTracks = mOutputTracks;
}

void MediaDecoderStateMachine::OutputPrincipalChanged() {
  MOZ_ASSERT(OnTaskQueue());
  mCanonicalOutputPrincipal = mOutputPrincipal;
}

RefPtr<GenericPromise> MediaDecoderStateMachine::InvokeSetSink(
    RefPtr<AudioDeviceInfo> aSink) {
  MOZ_ASSERT(NS_IsMainThread());
@@ -3530,7 +3578,7 @@ RefPtr<GenericPromise> MediaDecoderStateMachine::InvokeSetSink(
RefPtr<GenericPromise> MediaDecoderStateMachine::SetSink(
    RefPtr<AudioDeviceInfo> aSink) {
  MOZ_ASSERT(OnTaskQueue());
  if (mAudioCaptured) {
  if (mOutputCaptured) {
    // Not supported yet.
    return GenericPromise::CreateAndReject(NS_ERROR_ABORT, __func__);
  }
@@ -3656,43 +3704,6 @@ void MediaDecoderStateMachine::OnMediaSinkAudioError(nsresult aResult) {
  DecodeError(MediaResult(NS_ERROR_DOM_MEDIA_MEDIASINK_ERR, __func__));
}

void MediaDecoderStateMachine::SetAudioCaptured(bool aCaptured,
                                                OutputStreamManager* aManager) {
  MOZ_ASSERT(OnTaskQueue());

  if (aCaptured == mAudioCaptured) {
    return;
  }

  // Rest these flags so they are consistent with the status of the sink.
  // TODO: Move these flags into MediaSink to improve cohesion so we don't need
  // to reset these flags when switching MediaSinks.
  mAudioCompleted = false;
  mVideoCompleted = false;

  // Backup current playback parameters.
  MediaSink::PlaybackParams params = mMediaSink->GetPlaybackParams();

  // Stop and shut down the existing sink.
  StopMediaSink();
  mMediaSink->Shutdown();

  // Create a new sink according to whether audio is captured.
  mMediaSink = CreateMediaSink(aCaptured, aManager);

  // Restore playback parameters.
  mMediaSink->SetPlaybackParams(params);

  mAudioCaptured = aCaptured;

  // Don't buffer as much when audio is captured because we don't need to worry
  // about high latency audio devices.
  mAmpleAudioThreshold = mAudioCaptured ? detail::AMPLE_AUDIO_THRESHOLD / 2
                                        : detail::AMPLE_AUDIO_THRESHOLD;

  mStateObj->HandleAudioCaptured();
}

uint32_t MediaDecoderStateMachine::GetAmpleVideoFrames() const {
  MOZ_ASSERT(OnTaskQueue());
  return mReader->VideoIsHardwareAccelerated()
@@ -3736,86 +3747,6 @@ RefPtr<GenericPromise> MediaDecoderStateMachine::RequestDebugInfo(
  return p.forget();
}

void MediaDecoderStateMachine::SetOutputStreamPrincipal(
    nsIPrincipal* aPrincipal) {
  MOZ_ASSERT(NS_IsMainThread());
  mOutputStreamPrincipal = aPrincipal;
  if (mOutputStreamManager) {
    mOutputStreamManager->SetPrincipal(mOutputStreamPrincipal);
  }
}

void MediaDecoderStateMachine::AddOutputStream(DOMMediaStream* aStream) {
  MOZ_ASSERT(NS_IsMainThread());
  LOG("AddOutputStream aStream=%p!", aStream);
  mOutputStreamManager->Add(aStream);
  nsCOMPtr<nsIRunnable> r =
      NS_NewRunnableFunction("MediaDecoderStateMachine::SetAudioCaptured",
                             [self = RefPtr<MediaDecoderStateMachine>(this),
                              manager = mOutputStreamManager]() {
                               self->SetAudioCaptured(true, manager);
                             });
  nsresult rv = OwnerThread()->Dispatch(r.forget());
  MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
  Unused << rv;
}

void MediaDecoderStateMachine::RemoveOutputStream(DOMMediaStream* aStream) {
  MOZ_ASSERT(NS_IsMainThread());
  LOG("RemoveOutputStream=%p!", aStream);
  mOutputStreamManager->Remove(aStream);
  if (mOutputStreamManager->IsEmpty()) {
    mOutputStreamManager->Disconnect();
    mOutputStreamManager = nullptr;
    nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(
        "MediaDecoderStateMachine::SetAudioCaptured",
        [self = RefPtr<MediaDecoderStateMachine>(this)]() {
          self->SetAudioCaptured(false);
        });
    nsresult rv = OwnerThread()->Dispatch(r.forget());
    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
    Unused << rv;
  }
}

void MediaDecoderStateMachine::EnsureOutputStreamManager(
    SharedDummyTrack* aDummyStream) {
  MOZ_ASSERT(NS_IsMainThread());
  if (mOutputStreamManager) {
    return;
  }
  mOutputStreamManager = new OutputStreamManager(
      aDummyStream, mOutputStreamPrincipal, mAbstractMainThread);
}

void MediaDecoderStateMachine::EnsureOutputStreamManagerHasTracks(
    const MediaInfo& aLoadedInfo) {
  MOZ_ASSERT(NS_IsMainThread());
  if (!mOutputStreamManager) {
    return;
  }
  if ((!aLoadedInfo.HasAudio() ||
       mOutputStreamManager->HasTrackType(MediaSegment::AUDIO)) &&
      (!aLoadedInfo.HasVideo() ||
       mOutputStreamManager->HasTrackType(MediaSegment::VIDEO))) {
    return;
  }
  if (aLoadedInfo.HasAudio()) {
    MOZ_ASSERT(!mOutputStreamManager->HasTrackType(MediaSegment::AUDIO));
    RefPtr<SourceMediaTrack> dummy =
        mOutputStreamManager->AddTrack(MediaSegment::AUDIO);
    LOG("Pre-created audio track with underlying track %p", dummy.get());
    Unused << dummy;
  }
  if (aLoadedInfo.HasVideo()) {
    MOZ_ASSERT(!mOutputStreamManager->HasTrackType(MediaSegment::VIDEO));
    RefPtr<SourceMediaTrack> dummy =
        mOutputStreamManager->AddTrack(MediaSegment::VIDEO);
    LOG("Pre-created video track with underlying track %p", dummy.get());
    Unused << dummy;
  }
}

class VideoQueueMemoryFunctor : public nsDequeFunctor {
 public:
  VideoQueueMemoryFunctor() : mSize(0) {}
+26 −35
Original line number Diff line number Diff line
@@ -106,7 +106,6 @@ class AbstractThread;
class AudioSegment;
class DecodedStream;
class DOMMediaStream;
class OutputStreamManager;
class ReaderProxy;
class TaskQueue;

@@ -186,19 +185,6 @@ class MediaDecoderStateMachine
  RefPtr<GenericPromise> RequestDebugInfo(
      dom::MediaDecoderStateMachineDebugInfo& aInfo);

  void SetOutputStreamPrincipal(nsIPrincipal* aPrincipal);
  // If an OutputStreamManager does not exist, one will be created.
  void EnsureOutputStreamManager(SharedDummyTrack* aDummyStream);
  // If an OutputStreamManager exists, tracks matching aLoadedInfo will be
  // created unless they already exist in the manager.
  void EnsureOutputStreamManagerHasTracks(const MediaInfo& aLoadedInfo);
  // Add an output stream to the output stream manager. The manager must have
  // been created through EnsureOutputStreamManager() before this.
  void AddOutputStream(DOMMediaStream* aStream);
  // Remove an output stream added with AddOutputStream. If the last output
  // stream was removed, we will also tear down the OutputStreamManager.
  void RemoveOutputStream(DOMMediaStream* aStream);

  // Seeks to the decoder to aTarget asynchronously.
  RefPtr<MediaDecoder::SeekPromise> InvokeSeek(const SeekTarget& aTarget);

@@ -316,11 +302,6 @@ class MediaDecoderStateMachine
  // constructor immediately after the task queue is created.
  void InitializationTask(MediaDecoder* aDecoder);

  // Sets the audio-captured state and recreates the media sink if needed.
  // A manager must be passed in if setting the audio-captured state to true.
  void SetAudioCaptured(bool aCaptured,
                        OutputStreamManager* aManager = nullptr);

  RefPtr<MediaDecoder::SeekPromise> Seek(const SeekTarget& aTarget);

  RefPtr<ShutdownPromise> Shutdown();
@@ -394,6 +375,9 @@ class MediaDecoderStateMachine
  void SetPlaybackRate(double aPlaybackRate);
  void PreservesPitchChanged();
  void LoopingChanged();
  void UpdateOutputCaptured();
  void OutputTracksChanged();
  void OutputPrincipalChanged();

  MediaQueue<AudioData>& AudioQueue() { return mAudioQueue; }
  MediaQueue<VideoData>& VideoQueue() { return mVideoQueue; }
@@ -438,10 +422,9 @@ class MediaDecoderStateMachine

  MediaSink* CreateAudioSink();

  // Always create mediasink which contains an AudioSink or StreamSink inside.
  // A manager must be passed in if aAudioCaptured is true.
  already_AddRefed<MediaSink> CreateMediaSink(
      bool aAudioCaptured, OutputStreamManager* aManager = nullptr);
  // Always create mediasink which contains an AudioSink or DecodedStream
  // inside.
  already_AddRefed<MediaSink> CreateMediaSink(bool aOutputCaptured);

  // Stops the media sink and shut it down.
  // The decoder monitor must be held with exactly one lock count.
@@ -626,11 +609,6 @@ class MediaDecoderStateMachine

  bool mIsLiveStream = false;

  // True if we shouldn't play our audio (but still write it to any capturing
  // streams). When this is true, the audio thread will never start again after
  // it has stopped.
  bool mAudioCaptured;

  // True if all audio frames are already rendered.
  bool mAudioCompleted = false;

@@ -672,13 +650,6 @@ class MediaDecoderStateMachine
  // Track enabling video decode suspension via timer
  DelayedScheduler mVideoDecodeSuspendTimer;

  // Data about MediaStreams that are being fed by the decoder.
  // Main thread only.
  RefPtr<OutputStreamManager> mOutputStreamManager;

  // Principal used by output streams. Main thread only.
  nsCOMPtr<nsIPrincipal> mOutputStreamPrincipal;

  // Track the current video decode mode.
  VideoDecodeMode mVideoDecodeMode;

@@ -733,6 +704,19 @@ class MediaDecoderStateMachine
  // upon reaching the end.
  Mirror<bool> mLooping;

  // Whether all output should be captured into mOutputTracks. While true, the
  // media sink will only play if there are output tracks.
  Mirror<bool> mOutputCaptured;

  // Tracks to capture data into.
  Mirror<nsTArray<RefPtr<ProcessedMediaTrack>>> mOutputTracks;

  // PrincipalHandle to feed with data captured into mOutputTracks.
  Mirror<PrincipalHandle> mOutputPrincipal;

  Canonical<nsTArray<RefPtr<ProcessedMediaTrack>>> mCanonicalOutputTracks;
  Canonical<PrincipalHandle> mCanonicalOutputPrincipal;

  // Duration of the media. This is guaranteed to be non-null after we finish
  // decoding the first frame.
  Canonical<media::NullableTimeUnit> mDuration;
@@ -751,6 +735,13 @@ class MediaDecoderStateMachine
 public:
  AbstractCanonical<media::TimeIntervals>* CanonicalBuffered() const;

  AbstractCanonical<nsTArray<RefPtr<ProcessedMediaTrack>>>*
  CanonicalOutputTracks() {
    return &mCanonicalOutputTracks;
  }
  AbstractCanonical<PrincipalHandle>* CanonicalOutputPrincipal() {
    return &mCanonicalOutputPrincipal;
  }
  AbstractCanonical<media::NullableTimeUnit>* CanonicalDuration() {
    return &mDuration;
  }
+96 −89

File changed.

Preview size limit exceeded, changes collapsed.

Loading