--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -232,16 +232,17 @@ public:
virtual void DumpDebugInfo() {}
protected:
using Master = MediaDecoderStateMachine;
explicit StateObject(Master* aPtr) : mMaster(aPtr) {}
TaskQueue* OwnerThread() const { return mMaster->mTaskQueue; }
MediaResource* Resource() const { return mMaster->mResource; }
MediaDecoderReaderWrapper* Reader() const { return mMaster->mReader; }
+ const MediaInfo& Info() const { return mMaster->Info(); }
// Note this function will delete the current state object.
// Don't access members to avoid UAF after this call.
void SetState(State aState) { mMaster->SetState(aState); }
// Take a raw pointer in order not to change the life cycle of MDSM.
// It is guaranteed to be valid by MDSM.
Master* mMaster;
@@ -304,29 +305,30 @@ private:
// No need to store mQueuedSeek because we are at position 0.
SetState(DECODER_STATE_DORMANT);
return;
}
// Set mode to PLAYBACK after reading metadata.
Resource()->SetReadMode(MediaCacheStream::MODE_PLAYBACK);
- mMaster->mInfo = aMetadata->mInfo;
+ mMaster->mInfo = Some(aMetadata->mInfo);
mMaster->mMetadataTags = aMetadata->mTags.forget();
- if (mMaster->mInfo.mMetadataDuration.isSome()) {
+ if (Info().mMetadataDuration.isSome()) {
mMaster->RecomputeDuration();
- } else if (mMaster->mInfo.mUnadjustedMetadataEndTime.isSome()) {
+ } else if (Info().mUnadjustedMetadataEndTime.isSome()) {
RefPtr<Master> master = mMaster;
Reader()->AwaitStartTime()->Then(OwnerThread(), __func__,
[master] () {
NS_ENSURE_TRUE_VOID(!master->IsShutdown());
- TimeUnit unadjusted = master->mInfo.mUnadjustedMetadataEndTime.ref();
+ auto& info = master->mInfo.ref();
+ TimeUnit unadjusted = info.mUnadjustedMetadataEndTime.ref();
TimeUnit adjustment = master->mReader->StartTime();
- master->mInfo.mMetadataDuration.emplace(unadjusted - adjustment);
+ info.mMetadataDuration.emplace(unadjusted - adjustment);
master->RecomputeDuration();
}, [master, this] () {
SWARN("Adjusting metadata end time failed");
}
);
}
if (mMaster->HasVideo()) {
@@ -337,17 +339,17 @@ private:
}
// In general, we wait until we know the duration before notifying the decoder.
// However, we notify unconditionally in this case without waiting for the start
// time, since the caller might be waiting on metadataloaded to be fired before
// feeding in the CDM, which we need to decode the first frame (and
// thus get the metadata). We could fix this if we could compute the start
// time by demuxing without necessaring decoding.
- bool waitingForCDM = mMaster->mInfo.IsEncrypted() && !mMaster->mCDMProxy;
+ bool waitingForCDM = Info().IsEncrypted() && !mMaster->mCDMProxy;
mMaster->mNotifyMetadataBeforeFirstFrame =
mMaster->mDuration.Ref().isSome() || waitingForCDM;
if (mMaster->mNotifyMetadataBeforeFirstFrame) {
mMaster->EnqueueLoadedMetadataEvent();
}
@@ -739,21 +741,21 @@ public:
// SeekTask will register its callbacks to MediaDecoderReaderWrapper.
mMaster->CancelMediaDecoderReaderWrapperCallback();
// Create a new SeekTask instance for the incoming seek task.
if (mSeekJob.mTarget.IsAccurate() ||
mSeekJob.mTarget.IsFast()) {
mSeekTask = new AccurateSeekTask(
mMaster->mDecoderID, OwnerThread(), Reader(), mSeekJob.mTarget,
- mMaster->mInfo, mMaster->Duration(), mMaster->GetMediaTime());
+ Info(), mMaster->Duration(), mMaster->GetMediaTime());
} else if (mSeekJob.mTarget.IsNextFrame()) {
mSeekTask = new NextFrameSeekTask(
mMaster->mDecoderID, OwnerThread(), Reader(), mSeekJob.mTarget,
- mMaster->mInfo, mMaster->Duration(),mMaster->GetMediaTime(),
+ Info(), mMaster->Duration(),mMaster->GetMediaTime(),
mMaster->AudioQueue(), mMaster->VideoQueue());
} else {
MOZ_DIAGNOSTIC_ASSERT(false, "Cannot handle this seek task.");
}
// Don't stop playback for a video-only seek since audio is playing.
if (!mSeekJob.mTarget.IsVideoOnly()) {
mMaster->StopPlayback();
@@ -951,17 +953,17 @@ private:
// Ensure timestamps are up to date.
mMaster->UpdatePlaybackPositionInternal(newCurrentTime);
// Try to decode another frame to detect if we're at the end...
SLOG("Seek completed, mCurrentPosition=%lld", mMaster->mCurrentPosition.Ref());
if (video) {
- mMaster->mMediaSink->Redraw(mMaster->mInfo.mVideo);
+ mMaster->mMediaSink->Redraw(Info().mVideo);
mMaster->mOnPlaybackEvent.Notify(MediaEventType::Invalidate);
}
SetState(nextState);
}
SeekJob mSeekJob;
MozPromiseRequestHolder<SeekTask::SeekTaskPromise> mSeekTaskRequest;
@@ -1352,17 +1354,17 @@ MediaDecoderStateMachine::AudioAudibleCh
media::MediaSink*
MediaDecoderStateMachine::CreateAudioSink()
{
RefPtr<MediaDecoderStateMachine> self = this;
auto audioSinkCreator = [self] () {
MOZ_ASSERT(self->OnTaskQueue());
DecodedAudioDataSink* audioSink = new DecodedAudioDataSink(
self->mTaskQueue, self->mAudioQueue, self->GetMediaTime(),
- self->mInfo.mAudio, self->mAudioChannel);
+ self->Info().mAudio, self->mAudioChannel);
self->mAudibleListener = audioSink->AudibleEvent().Connect(
self->mTaskQueue, self.get(), &MediaDecoderStateMachine::AudioAudibleChanged);
return audioSink;
};
return new AudioSinkWrapper(mTaskQueue, audioSinkCreator);
}
@@ -1968,18 +1970,18 @@ void MediaDecoderStateMachine::Recompute
// any other duration sources), but the duration isn't ready yet.
return;
}
// We don't fire duration changed for this case because it should have
// already been fired on the main thread when the explicit duration was set.
duration = TimeUnit::FromSeconds(d);
} else if (mEstimatedDuration.Ref().isSome()) {
duration = mEstimatedDuration.Ref().ref();
- } else if (mInfo.mMetadataDuration.isSome()) {
- duration = mInfo.mMetadataDuration.ref();
+ } else if (Info().mMetadataDuration.isSome()) {
+ duration = Info().mMetadataDuration.ref();
} else {
return;
}
// Only adjust the duration when an explicit duration isn't set (MSE).
// The duration is always exactly known with MSE and there's no need to adjust
// it based on what may have been seen in the past; in particular as this data
// may no longer exist such as when the mediasource duration was reduced.
@@ -2198,17 +2200,17 @@ void MediaDecoderStateMachine::Visibilit
// one to catch up.
if (mState == DECODER_STATE_SEEKING || mQueuedSeek.Exists()) {
return;
}
// Start counting recovery time from right now.
TimeStamp start = TimeStamp::Now();
// Local reference to mInfo, so that it will be copied in the lambda below.
- MediaInfo& info = mInfo;
+ auto& info = Info();
bool hw = mReader->VideoIsHardwareAccelerated();
// Start video-only seek to the current time.
SeekJob seekJob;
const SeekTarget::Type type = HasAudio()
? SeekTarget::Type::Accurate
: SeekTarget::Type::PrevSyncPoint;
@@ -2467,17 +2469,17 @@ MediaDecoderStateMachine::RequestVideoDa
}
void
MediaDecoderStateMachine::StartMediaSink()
{
MOZ_ASSERT(OnTaskQueue());
if (!mMediaSink->IsStarted()) {
mAudioCompleted = false;
- mMediaSink->Start(GetMediaTime(), mInfo);
+ mMediaSink->Start(GetMediaTime(), Info());
auto videoPromise = mMediaSink->OnEnded(TrackInfo::kVideoTrack);
auto audioPromise = mMediaSink->OnEnded(TrackInfo::kAudioTrack);
if (audioPromise) {
mMediaSinkAudioPromise.Begin(audioPromise->Then(
OwnerThread(), __func__, this,
&MediaDecoderStateMachine::OnMediaSinkAudioComplete,
@@ -2592,17 +2594,17 @@ MediaDecoderStateMachine::DecodeError(co
void
MediaDecoderStateMachine::EnqueueLoadedMetadataEvent()
{
MOZ_ASSERT(OnTaskQueue());
MediaDecoderEventVisibility visibility =
mSentLoadedMetadataEvent ? MediaDecoderEventVisibility::Suppressed
: MediaDecoderEventVisibility::Observable;
- mMetadataLoadedEvent.Notify(nsAutoPtr<MediaInfo>(new MediaInfo(mInfo)),
+ mMetadataLoadedEvent.Notify(nsAutoPtr<MediaInfo>(new MediaInfo(Info())),
Move(mMetadataTags),
visibility);
mSentLoadedMetadataEvent = true;
}
void
MediaDecoderStateMachine::EnqueueFirstFrameLoadedEvent()
{
@@ -2617,42 +2619,42 @@ MediaDecoderStateMachine::EnqueueFirstFr
__func__,
// Resolve
[self, firstFrameBeenLoaded]() {
self->mBufferedUpdateRequest.Complete();
MediaDecoderEventVisibility visibility =
firstFrameBeenLoaded ? MediaDecoderEventVisibility::Suppressed
: MediaDecoderEventVisibility::Observable;
self->mFirstFrameLoadedEvent.Notify(
- nsAutoPtr<MediaInfo>(new MediaInfo(self->mInfo)), visibility);
+ nsAutoPtr<MediaInfo>(new MediaInfo(self->Info())), visibility);
},
// Reject
[]() { MOZ_CRASH("Should not reach"); }));
}
void
MediaDecoderStateMachine::FinishDecodeFirstFrame()
{
MOZ_ASSERT(OnTaskQueue());
MOZ_ASSERT(!mSentFirstFrameLoadedEvent);
DECODER_LOG("FinishDecodeFirstFrame");
- mMediaSink->Redraw(mInfo.mVideo);
+ mMediaSink->Redraw(Info().mVideo);
// If we don't know the duration by this point, we assume infinity, per spec.
if (mDuration.Ref().isNothing()) {
mDuration = Some(TimeUnit::FromInfinity());
}
DECODER_LOG("Media duration %lld, "
"transportSeekable=%d, mediaSeekable=%d",
Duration().ToMicroseconds(), mResource->IsTransportSeekable(), mMediaSeekable.Ref());
// Get potentially updated metadata
- mReader->ReadUpdatedMetadata(&mInfo);
+ mReader->ReadUpdatedMetadata(mInfo.ptr());
if (!mNotifyMetadataBeforeFirstFrame) {
// If we didn't have duration and/or start time before, we should now.
EnqueueLoadedMetadataEvent();
}
EnqueueFirstFrameLoadedEvent();
}
@@ -2925,59 +2927,59 @@ MediaDecoderStateMachine::VideoEndTime()
}
return -1;
}
void
MediaDecoderStateMachine::OnMediaSinkVideoComplete()
{
MOZ_ASSERT(OnTaskQueue());
- MOZ_ASSERT(mInfo.HasVideo());
+ MOZ_ASSERT(HasVideo());
VERBOSE_LOG("[%s]", __func__);
mMediaSinkVideoPromise.Complete();
mVideoCompleted = true;
ScheduleStateMachine();
}
void
MediaDecoderStateMachine::OnMediaSinkVideoError()
{
MOZ_ASSERT(OnTaskQueue());
- MOZ_ASSERT(mInfo.HasVideo());
+ MOZ_ASSERT(HasVideo());
VERBOSE_LOG("[%s]", __func__);
mMediaSinkVideoPromise.Complete();
mVideoCompleted = true;
if (HasAudio()) {
return;
}
DecodeError(MediaResult(NS_ERROR_DOM_MEDIA_MEDIASINK_ERR, __func__));
}
void MediaDecoderStateMachine::OnMediaSinkAudioComplete()
{
MOZ_ASSERT(OnTaskQueue());
- MOZ_ASSERT(mInfo.HasAudio());
+ MOZ_ASSERT(HasAudio());
VERBOSE_LOG("[%s]", __func__);
mMediaSinkAudioPromise.Complete();
mAudioCompleted = true;
// To notify PlaybackEnded as soon as possible.
ScheduleStateMachine();
// Report OK to Decoder Doctor (to know if issue may have been resolved).
mOnDecoderDoctorEvent.Notify(
DecoderDoctorEvent{DecoderDoctorEvent::eAudioSinkStartup, NS_OK});
}
void MediaDecoderStateMachine::OnMediaSinkAudioError(nsresult aResult)
{
MOZ_ASSERT(OnTaskQueue());
- MOZ_ASSERT(mInfo.HasAudio());
+ MOZ_ASSERT(HasAudio());
VERBOSE_LOG("[%s]", __func__);
mMediaSinkAudioPromise.Complete();
mAudioCompleted = true;
// Result should never be NS_OK in this *error* handler. Report to Dec-Doc.
MOZ_ASSERT(NS_FAILED(aResult));
mOnDecoderDoctorEvent.Notify(