--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -1219,16 +1219,17 @@ DecodeMetadataState::OnMetadataRead(Meta
{
mMetadataRequest.Complete();
// Set mode to PLAYBACK after reading metadata.
Resource()->SetReadMode(MediaCacheStream::MODE_PLAYBACK);
mMaster->mInfo = Some(aMetadata->mInfo);
mMaster->mMetadataTags = aMetadata->mTags.forget();
+ mMaster->mMediaSeekable = Info().mMediaSeekable;
if (Info().mMetadataDuration.isSome()) {
mMaster->RecomputeDuration();
} else if (Info().mUnadjustedMetadataEndTime.isSome()) {
RefPtr<Master> master = mMaster;
Reader()->AwaitStartTime()->Then(OwnerThread(), __func__,
[master] () {
NS_ENSURE_TRUE_VOID(!master->IsShutdown());
@@ -1656,31 +1657,31 @@ ShutdownState::Enter()
master->Reset();
master->mMediaSink->Shutdown();
// Prevent dangling pointers by disconnecting the listeners.
master->mAudioQueueListener.Disconnect();
master->mVideoQueueListener.Disconnect();
master->mMetadataManager.Disconnect();
+ master->mOnMediaNotSeekable.Disconnect();
// Disconnect canonicals and mirrors before shutting down our task queue.
master->mBuffered.DisconnectIfConnected();
master->mEstimatedDuration.DisconnectIfConnected();
master->mExplicitDuration.DisconnectIfConnected();
master->mPlayState.DisconnectIfConnected();
master->mNextPlayState.DisconnectIfConnected();
master->mVolume.DisconnectIfConnected();
master->mPreservesPitch.DisconnectIfConnected();
master->mSameOriginMedia.DisconnectIfConnected();
master->mMediaPrincipalHandle.DisconnectIfConnected();
master->mPlaybackBytesPerSecond.DisconnectIfConnected();
master->mPlaybackRateReliable.DisconnectIfConnected();
master->mDecoderPosition.DisconnectIfConnected();
- master->mMediaSeekable.DisconnectIfConnected();
master->mMediaSeekableOnlyInBufferedRanges.DisconnectIfConnected();
master->mIsVisible.DisconnectIfConnected();
master->mDuration.DisconnectAll();
master->mIsShutdown.DisconnectAll();
master->mNextFrameStatus.DisconnectAll();
master->mCurrentPosition.DisconnectAll();
master->mPlaybackOffset.DisconnectAll();
@@ -1743,17 +1744,16 @@ MediaDecoderStateMachine::MediaDecoderSt
INIT_MIRROR(mNextPlayState, MediaDecoder::PLAY_STATE_PAUSED),
INIT_MIRROR(mVolume, 1.0),
INIT_MIRROR(mPreservesPitch, true),
INIT_MIRROR(mSameOriginMedia, false),
INIT_MIRROR(mMediaPrincipalHandle, PRINCIPAL_HANDLE_NONE),
INIT_MIRROR(mPlaybackBytesPerSecond, 0.0),
INIT_MIRROR(mPlaybackRateReliable, true),
INIT_MIRROR(mDecoderPosition, 0),
- INIT_MIRROR(mMediaSeekable, true),
INIT_MIRROR(mMediaSeekableOnlyInBufferedRanges, false),
INIT_MIRROR(mIsVisible, true),
INIT_CANONICAL(mDuration, NullableTimeUnit()),
INIT_CANONICAL(mIsShutdown, false),
INIT_CANONICAL(mNextFrameStatus, MediaDecoderOwner::NEXT_FRAME_UNINITIALIZED),
INIT_CANONICAL(mCurrentPosition, 0),
INIT_CANONICAL(mPlaybackOffset, 0),
INIT_CANONICAL(mIsAudioDataAudible, false)
@@ -1800,17 +1800,16 @@ MediaDecoderStateMachine::Initialization
mNextPlayState.Connect(aDecoder->CanonicalNextPlayState());
mVolume.Connect(aDecoder->CanonicalVolume());
mPreservesPitch.Connect(aDecoder->CanonicalPreservesPitch());
mSameOriginMedia.Connect(aDecoder->CanonicalSameOriginMedia());
mMediaPrincipalHandle.Connect(aDecoder->CanonicalMediaPrincipalHandle());
mPlaybackBytesPerSecond.Connect(aDecoder->CanonicalPlaybackBytesPerSecond());
mPlaybackRateReliable.Connect(aDecoder->CanonicalPlaybackRateReliable());
mDecoderPosition.Connect(aDecoder->CanonicalDecoderPosition());
- mMediaSeekable.Connect(aDecoder->CanonicalMediaSeekable());
mMediaSeekableOnlyInBufferedRanges.Connect(aDecoder->CanonicalMediaSeekableOnlyInBufferedRanges());
// Initialize watchers.
mWatchManager.Watch(mBuffered, &MediaDecoderStateMachine::BufferedRangeUpdated);
mWatchManager.Watch(mState, &MediaDecoderStateMachine::UpdateNextFrameStatus);
mWatchManager.Watch(mAudioCompleted, &MediaDecoderStateMachine::UpdateNextFrameStatus);
mWatchManager.Watch(mVideoCompleted, &MediaDecoderStateMachine::UpdateNextFrameStatus);
mWatchManager.Watch(mVolume, &MediaDecoderStateMachine::VolumeChanged);
@@ -2181,16 +2180,21 @@ nsresult MediaDecoderStateMachine::Init(
mAudioQueueListener = AudioQueue().PopEvent().Connect(
mTaskQueue, this, &MediaDecoderStateMachine::OnAudioPopped);
mVideoQueueListener = VideoQueue().PopEvent().Connect(
mTaskQueue, this, &MediaDecoderStateMachine::OnVideoPopped);
mMetadataManager.Connect(mReader->TimedMetadataEvent(), OwnerThread());
+ mOnMediaNotSeekable = mReader->OnMediaNotSeekable().Connect(
+ OwnerThread(), [this] () {
+ mMediaSeekable = false;
+ });
+
mMediaSink = CreateMediaSink(mAudioCaptured);
mCDMProxyPromise.Begin(aDecoder->RequestCDMProxy()->Then(
OwnerThread(), __func__, this,
&MediaDecoderStateMachine::OnCDMProxyReady,
&MediaDecoderStateMachine::OnCDMProxyNotReady));
nsresult rv = mReader->Init();
@@ -2841,17 +2845,17 @@ MediaDecoderStateMachine::FinishDecodeFi
// 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());
+ Duration().ToMicroseconds(), mResource->IsTransportSeekable(), mMediaSeekable);
// Get potentially updated metadata
mReader->ReadUpdatedMetadata(mInfo.ptr());
if (!mNotifyMetadataBeforeFirstFrame) {
// If we didn't have duration and/or start time before, we should now.
EnqueueLoadedMetadataEvent();
}
--- a/dom/media/MediaDecoderStateMachine.h
+++ b/dom/media/MediaDecoderStateMachine.h
@@ -729,32 +729,36 @@ private:
// notified the FirstFrameLoaded event. Note we can't initiate seek until the
// start time is known which happens when the first frames are decoded or we
// are playing an MSE stream (the start time is always assumed 0).
bool mSentFirstFrameLoadedEvent;
// True if video decoding is suspended.
bool mVideoDecodeSuspended;
+ // True if the media is seekable (i.e. supports random access).
+ bool mMediaSeekable = true;
+
// Track enabling video decode suspension via timer
DelayedScheduler mVideoDecodeSuspendTimer;
// Data about MediaStreams that are being fed by the decoder.
const RefPtr<OutputStreamManager> mOutputStreamManager;
// Media data resource from the decoder.
RefPtr<MediaResource> mResource;
// Track the complete & error for audio/video separately
MozPromiseRequestHolder<GenericPromise> mMediaSinkAudioPromise;
MozPromiseRequestHolder<GenericPromise> mMediaSinkVideoPromise;
MediaEventListener mAudioQueueListener;
MediaEventListener mVideoQueueListener;
MediaEventListener mAudibleListener;
+ MediaEventListener mOnMediaNotSeekable;
MediaEventProducerExc<nsAutoPtr<MediaInfo>,
nsAutoPtr<MetadataTags>,
MediaDecoderEventVisibility> mMetadataLoadedEvent;
MediaEventProducerExc<nsAutoPtr<MediaInfo>,
MediaDecoderEventVisibility> mFirstFrameLoadedEvent;
MediaEventProducer<MediaEventType> mOnPlaybackEvent;
@@ -803,19 +807,16 @@ private:
Mirror<double> mPlaybackBytesPerSecond;
// True if mPlaybackBytesPerSecond is a reliable estimate.
Mirror<bool> mPlaybackRateReliable;
// Current decoding position in the stream.
Mirror<int64_t> mDecoderPosition;
- // True if the media is seekable (i.e. supports random access).
- Mirror<bool> mMediaSeekable;
-
// True if the media is seekable only in buffered ranges.
Mirror<bool> mMediaSeekableOnlyInBufferedRanges;
// IsVisible, mirrored from the media decoder.
Mirror<bool> mIsVisible;
// Duration of the media. This is guaranteed to be non-null after we finish
// decoding the first frame.