mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1128357 Patch 2: Don't dispatch seeking/seeked events when coming out of dormant mode r=cpearce
This commit is contained in:
parent
18128e50cf
commit
603447a194
@ -573,7 +573,7 @@ HTMLMediaElement::Ended()
|
||||
}
|
||||
|
||||
if (mDecoder) {
|
||||
return mDecoder->IsEnded();
|
||||
return mDecoder->IsEndedOrShutdown();
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -2199,7 +2199,7 @@ HTMLMediaElement::Play(ErrorResult& aRv)
|
||||
// Even if we just did Load() or ResumeLoad(), we could already have a decoder
|
||||
// here if we managed to clone an existing decoder.
|
||||
if (mDecoder) {
|
||||
if (mDecoder->IsEnded()) {
|
||||
if (mDecoder->IsEndedOrShutdown()) {
|
||||
SetCurrentTime(0);
|
||||
}
|
||||
if (!mPausedForInactiveDocumentOrChannel) {
|
||||
@ -3177,7 +3177,7 @@ void HTMLMediaElement::PlaybackEnded()
|
||||
// We changed state which can affect AddRemoveSelfReference
|
||||
AddRemoveSelfReference();
|
||||
|
||||
NS_ASSERTION(!mDecoder || mDecoder->IsEnded(),
|
||||
NS_ASSERTION(!mDecoder || mDecoder->IsEndedOrShutdown(),
|
||||
"Decoder fired ended, but not in ended state");
|
||||
|
||||
// Discard all output streams that have finished now.
|
||||
@ -3414,7 +3414,7 @@ void HTMLMediaElement::UpdateReadyStateForData(MediaDecoderOwner::NextFrameStatu
|
||||
return;
|
||||
}
|
||||
|
||||
if (mDownloadSuspendedByCache && mDecoder && !mDecoder->IsEnded()) {
|
||||
if (mDownloadSuspendedByCache && mDecoder && !mDecoder->IsEndedOrShutdown()) {
|
||||
// The decoder has signaled that the download has been suspended by the
|
||||
// media cache. So move readyState into HAVE_ENOUGH_DATA, in case there's
|
||||
// script waiting for a "canplaythrough" event; without this forced
|
||||
@ -3697,7 +3697,7 @@ bool HTMLMediaElement::IsPlaybackEnded() const
|
||||
// the current playback position is equal to the effective end of the media resource.
|
||||
// See bug 449157.
|
||||
return mReadyState >= nsIDOMHTMLMediaElement::HAVE_METADATA &&
|
||||
mDecoder ? mDecoder->IsEnded() : false;
|
||||
mDecoder ? mDecoder->IsEndedOrShutdown() : false;
|
||||
}
|
||||
|
||||
already_AddRefed<nsIPrincipal> HTMLMediaElement::GetCurrentPrincipal()
|
||||
@ -3771,7 +3771,7 @@ void HTMLMediaElement::SuspendOrResumeElement(bool aPauseElement, bool aSuspendE
|
||||
#endif
|
||||
if (mDecoder) {
|
||||
mDecoder->Resume(false);
|
||||
if (!mPaused && !mDecoder->IsEnded()) {
|
||||
if (!mPaused && !mDecoder->IsEndedOrShutdown()) {
|
||||
mDecoder->Play();
|
||||
}
|
||||
} else if (mSrcStream) {
|
||||
@ -3832,7 +3832,7 @@ void HTMLMediaElement::AddRemoveSelfReference()
|
||||
bool needSelfReference = !mShuttingDown &&
|
||||
ownerDoc->IsActive() &&
|
||||
(mDelayingLoadEvent ||
|
||||
(!mPaused && mDecoder && !mDecoder->IsEnded()) ||
|
||||
(!mPaused && mDecoder && !mDecoder->IsEndedOrShutdown()) ||
|
||||
(!mPaused && mSrcStream && !mSrcStream->IsFinished()) ||
|
||||
(mDecoder && mDecoder->IsSeeking()) ||
|
||||
CanActivateAutoplay() ||
|
||||
|
@ -35,6 +35,11 @@ static inline bool IsCurrentThread(nsIThread* aThread) {
|
||||
return NS_GetCurrentThread() == aThread;
|
||||
}
|
||||
|
||||
enum class MediaDecoderEventVisibility : int8_t {
|
||||
Observable,
|
||||
Suppressed
|
||||
};
|
||||
|
||||
/**
|
||||
* The AbstractMediaDecoder class describes the public interface for a media decoder
|
||||
* and is used by the MediaReader classes.
|
||||
@ -90,9 +95,9 @@ public:
|
||||
// Return true if the transport layer supports seeking.
|
||||
virtual bool IsMediaSeekable() = 0;
|
||||
|
||||
virtual void MetadataLoaded(nsAutoPtr<MediaInfo> aInfo, nsAutoPtr<MetadataTags> aTags, bool aRestoredFromDormant) = 0;
|
||||
virtual void MetadataLoaded(nsAutoPtr<MediaInfo> aInfo, nsAutoPtr<MetadataTags> aTags, MediaDecoderEventVisibility aEventVisibility) = 0;
|
||||
virtual void QueueMetadata(int64_t aTime, nsAutoPtr<MediaInfo> aInfo, nsAutoPtr<MetadataTags> aTags) = 0;
|
||||
virtual void FirstFrameLoaded(nsAutoPtr<MediaInfo> aInfo, bool aRestoredFromDormant) = 0;
|
||||
virtual void FirstFrameLoaded(nsAutoPtr<MediaInfo> aInfo, MediaDecoderEventVisibility aEventVisibility) = 0;
|
||||
|
||||
virtual void RemoveMediaTracks() = 0;
|
||||
|
||||
@ -166,17 +171,17 @@ protected:
|
||||
MetadataContainer(AbstractMediaDecoder* aDecoder,
|
||||
nsAutoPtr<MediaInfo> aInfo,
|
||||
nsAutoPtr<MetadataTags> aTags,
|
||||
bool aRestoredFromDormant)
|
||||
MediaDecoderEventVisibility aEventVisibility)
|
||||
: mDecoder(aDecoder),
|
||||
mInfo(aInfo),
|
||||
mTags(aTags),
|
||||
mRestoredFromDormant(aRestoredFromDormant)
|
||||
mEventVisibility(aEventVisibility)
|
||||
{}
|
||||
|
||||
nsRefPtr<AbstractMediaDecoder> mDecoder;
|
||||
nsAutoPtr<MediaInfo> mInfo;
|
||||
nsAutoPtr<MetadataTags> mTags;
|
||||
bool mRestoredFromDormant;
|
||||
MediaDecoderEventVisibility mEventVisibility;
|
||||
};
|
||||
|
||||
class MetadataEventRunner : public nsRunnable, private MetadataContainer
|
||||
@ -185,13 +190,13 @@ public:
|
||||
MetadataEventRunner(AbstractMediaDecoder* aDecoder,
|
||||
nsAutoPtr<MediaInfo> aInfo,
|
||||
nsAutoPtr<MetadataTags> aTags,
|
||||
bool aRestoredFromDormant = false)
|
||||
: MetadataContainer(aDecoder, aInfo, aTags, aRestoredFromDormant)
|
||||
MediaDecoderEventVisibility aEventVisibility = MediaDecoderEventVisibility::Observable)
|
||||
: MetadataContainer(aDecoder, aInfo, aTags, aEventVisibility)
|
||||
{}
|
||||
|
||||
NS_IMETHOD Run() MOZ_OVERRIDE
|
||||
{
|
||||
mDecoder->MetadataLoaded(mInfo, mTags, mRestoredFromDormant);
|
||||
mDecoder->MetadataLoaded(mInfo, mTags, mEventVisibility);
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
@ -201,13 +206,13 @@ class FirstFrameLoadedEventRunner : public nsRunnable, private MetadataContainer
|
||||
public:
|
||||
FirstFrameLoadedEventRunner(AbstractMediaDecoder* aDecoder,
|
||||
nsAutoPtr<MediaInfo> aInfo,
|
||||
bool aRestoredFromDormant = false)
|
||||
: MetadataContainer(aDecoder, aInfo, nsAutoPtr<MetadataTags>(nullptr), aRestoredFromDormant)
|
||||
MediaDecoderEventVisibility aEventVisibility = MediaDecoderEventVisibility::Observable)
|
||||
: MetadataContainer(aDecoder, aInfo, nsAutoPtr<MetadataTags>(nullptr), aEventVisibility)
|
||||
{}
|
||||
|
||||
NS_IMETHOD Run() MOZ_OVERRIDE
|
||||
{
|
||||
mDecoder->FirstFrameLoaded(mInfo, mRestoredFromDormant);
|
||||
mDecoder->FirstFrameLoaded(mInfo, mEventVisibility);
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
@ -218,16 +223,16 @@ public:
|
||||
MetadataUpdatedEventRunner(AbstractMediaDecoder* aDecoder,
|
||||
nsAutoPtr<MediaInfo> aInfo,
|
||||
nsAutoPtr<MetadataTags> aTags,
|
||||
bool aRestoredFromDormant = false)
|
||||
: MetadataContainer(aDecoder, aInfo, aTags, aRestoredFromDormant)
|
||||
MediaDecoderEventVisibility aEventVisibility = MediaDecoderEventVisibility::Observable)
|
||||
: MetadataContainer(aDecoder, aInfo, aTags, aEventVisibility)
|
||||
{}
|
||||
|
||||
NS_IMETHOD Run() MOZ_OVERRIDE
|
||||
{
|
||||
nsAutoPtr<MediaInfo> info(new MediaInfo());
|
||||
*info = *mInfo;
|
||||
mDecoder->MetadataLoaded(info, mTags, mRestoredFromDormant);
|
||||
mDecoder->FirstFrameLoaded(mInfo, mRestoredFromDormant);
|
||||
mDecoder->MetadataLoaded(info, mTags, mEventVisibility);
|
||||
mDecoder->FirstFrameLoaded(mInfo, mEventVisibility);
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
@ -170,7 +170,7 @@ void MediaDecoder::UpdateDormantState(bool aDormantTimeout, bool aActivity)
|
||||
mIsHeuristicDormant = false;
|
||||
if (mIsHeuristicDormantSupported && mOwner->IsHidden()) {
|
||||
if (aDormantTimeout && !aActivity &&
|
||||
(mPlayState == PLAY_STATE_PAUSED || mPlayState == PLAY_STATE_ENDED)) {
|
||||
(mPlayState == PLAY_STATE_PAUSED || IsEnded())) {
|
||||
// Enable heuristic dormant
|
||||
mIsHeuristicDormant = true;
|
||||
} else if(prevHeuristicDormant && !aActivity) {
|
||||
@ -191,11 +191,9 @@ void MediaDecoder::UpdateDormantState(bool aDormantTimeout, bool aActivity)
|
||||
if (mIsDormant) {
|
||||
DECODER_LOG("UpdateDormantState() entering DORMANT state");
|
||||
mDecoderStateMachine->SetDormant(true);
|
||||
|
||||
int64_t timeUsecs = 0;
|
||||
SecondsToUsecs(mCurrentTime, timeUsecs);
|
||||
mRequestedSeekTarget = SeekTarget(timeUsecs, SeekTarget::Accurate);
|
||||
|
||||
if (IsEnded()) {
|
||||
mWasEndedWhenEnteredDormant = true;
|
||||
}
|
||||
mNextState = mPlayState;
|
||||
ChangeState(PLAY_STATE_LOADING);
|
||||
} else {
|
||||
@ -224,7 +222,7 @@ void MediaDecoder::StartDormantTimer()
|
||||
!mOwner ||
|
||||
!mOwner->IsHidden() ||
|
||||
(mPlayState != PLAY_STATE_PAUSED &&
|
||||
mPlayState != PLAY_STATE_ENDED))
|
||||
!IsEnded()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -251,7 +249,7 @@ void MediaDecoder::Pause()
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
if (mPlayState == PLAY_STATE_LOADING ||
|
||||
mPlayState == PLAY_STATE_SEEKING ||
|
||||
mPlayState == PLAY_STATE_ENDED) {
|
||||
IsEnded()) {
|
||||
mNextState = PLAY_STATE_PAUSED;
|
||||
return;
|
||||
}
|
||||
@ -584,6 +582,7 @@ MediaDecoder::MediaDecoder() :
|
||||
mMinimizePreroll(false),
|
||||
mMediaTracksConstructed(false),
|
||||
mIsDormant(false),
|
||||
mWasEndedWhenEnteredDormant(false),
|
||||
mIsHeuristicDormantSupported(
|
||||
Preferences::GetBool("media.decoder.heuristic.dormant.enabled", false)),
|
||||
mHeuristicDormantTimeout(
|
||||
@ -752,13 +751,12 @@ nsresult MediaDecoder::Play()
|
||||
}
|
||||
nsresult res = ScheduleStateMachineThread();
|
||||
NS_ENSURE_SUCCESS(res,res);
|
||||
if (mPlayState == PLAY_STATE_LOADING || mPlayState == PLAY_STATE_SEEKING) {
|
||||
if (IsEnded()) {
|
||||
return Seek(0, SeekTarget::PrevSyncPoint);
|
||||
} else if (mPlayState == PLAY_STATE_LOADING || mPlayState == PLAY_STATE_SEEKING) {
|
||||
mNextState = PLAY_STATE_PLAYING;
|
||||
return NS_OK;
|
||||
}
|
||||
if (mPlayState == PLAY_STATE_ENDED) {
|
||||
return Seek(0, SeekTarget::PrevSyncPoint);
|
||||
}
|
||||
|
||||
ChangeState(PLAY_STATE_PLAYING);
|
||||
return NS_OK;
|
||||
@ -778,6 +776,7 @@ nsresult MediaDecoder::Seek(double aTime, SeekTarget::Type aSeekType)
|
||||
|
||||
mRequestedSeekTarget = SeekTarget(timeUsecs, aSeekType);
|
||||
mCurrentTime = aTime;
|
||||
mWasEndedWhenEnteredDormant = false;
|
||||
|
||||
// If we are already in the seeking state, the new seek overrides the old one.
|
||||
if (mPlayState != PLAY_STATE_LOADING) {
|
||||
@ -842,7 +841,7 @@ MediaDecoder::IsExpectingMoreData()
|
||||
|
||||
void MediaDecoder::MetadataLoaded(nsAutoPtr<MediaInfo> aInfo,
|
||||
nsAutoPtr<MetadataTags> aTags,
|
||||
bool aRestoredFromDormant)
|
||||
MediaDecoderEventVisibility aEventVisibility)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
@ -872,7 +871,7 @@ void MediaDecoder::MetadataLoaded(nsAutoPtr<MediaInfo> aInfo,
|
||||
// Make sure the element and the frame (if any) are told about
|
||||
// our new size.
|
||||
Invalidate();
|
||||
if (!aRestoredFromDormant) {
|
||||
if (aEventVisibility != MediaDecoderEventVisibility::Suppressed) {
|
||||
mOwner->MetadataLoaded(mInfo, nsAutoPtr<const MetadataTags>(aTags.forget()));
|
||||
}
|
||||
}
|
||||
@ -894,7 +893,7 @@ MediaDecoder::PlayStateStr()
|
||||
}
|
||||
|
||||
void MediaDecoder::FirstFrameLoaded(nsAutoPtr<MediaInfo> aInfo,
|
||||
bool aRestoredFromDormant)
|
||||
MediaDecoderEventVisibility aEventVisibility)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
@ -912,7 +911,7 @@ void MediaDecoder::FirstFrameLoaded(nsAutoPtr<MediaInfo> aInfo,
|
||||
|
||||
if (mOwner) {
|
||||
Invalidate();
|
||||
if (!aRestoredFromDormant) {
|
||||
if (aEventVisibility != MediaDecoderEventVisibility::Suppressed) {
|
||||
mOwner->FirstFrameLoaded();
|
||||
}
|
||||
}
|
||||
@ -998,10 +997,16 @@ bool MediaDecoder::IsSeeking() const
|
||||
(mPlayState == PLAY_STATE_LOADING && mRequestedSeekTarget.IsValid()));
|
||||
}
|
||||
|
||||
bool MediaDecoder::IsEnded() const
|
||||
bool MediaDecoder::IsEndedOrShutdown() const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
return mPlayState == PLAY_STATE_ENDED || mPlayState == PLAY_STATE_SHUTDOWN;
|
||||
return IsEnded() || mPlayState == PLAY_STATE_SHUTDOWN;
|
||||
}
|
||||
|
||||
bool MediaDecoder::IsEnded() const
|
||||
{
|
||||
return mPlayState == PLAY_STATE_ENDED ||
|
||||
(mWasEndedWhenEnteredDormant && (mPlayState != PLAY_STATE_SHUTDOWN));
|
||||
}
|
||||
|
||||
void MediaDecoder::PlaybackEnded()
|
||||
@ -1184,14 +1189,15 @@ void MediaDecoder::NotifyBytesConsumed(int64_t aBytes, int64_t aOffset)
|
||||
void MediaDecoder::UpdateReadyStateForData()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (!mOwner || mShuttingDown || !mDecoderStateMachine)
|
||||
if (!mOwner || mShuttingDown || !mDecoderStateMachine) {
|
||||
return;
|
||||
}
|
||||
MediaDecoderOwner::NextFrameStatus frameStatus =
|
||||
mDecoderStateMachine->GetNextFrameStatus();
|
||||
mOwner->UpdateReadyStateForData(frameStatus);
|
||||
}
|
||||
|
||||
void MediaDecoder::SeekingStopped()
|
||||
void MediaDecoder::SeekingStopped(MediaDecoderEventVisibility aEventVisibility)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
@ -1209,15 +1215,17 @@ void MediaDecoder::SeekingStopped()
|
||||
seekWasAborted = true;
|
||||
} else {
|
||||
UnpinForSeek();
|
||||
ChangeState(mNextState);
|
||||
if (aEventVisibility != MediaDecoderEventVisibility::Suppressed) {
|
||||
ChangeState(mNextState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PlaybackPositionChanged();
|
||||
PlaybackPositionChanged(aEventVisibility);
|
||||
|
||||
if (mOwner) {
|
||||
UpdateReadyStateForData();
|
||||
if (!seekWasAborted) {
|
||||
if (!seekWasAborted && (aEventVisibility != MediaDecoderEventVisibility::Suppressed)) {
|
||||
mOwner->SeekCompleted();
|
||||
}
|
||||
}
|
||||
@ -1225,7 +1233,7 @@ void MediaDecoder::SeekingStopped()
|
||||
|
||||
// This is called when seeking stopped *and* we're at the end of the
|
||||
// media.
|
||||
void MediaDecoder::SeekingStoppedAtEnd()
|
||||
void MediaDecoder::SeekingStoppedAtEnd(MediaDecoderEventVisibility aEventVisibility)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
@ -1249,11 +1257,11 @@ void MediaDecoder::SeekingStoppedAtEnd()
|
||||
}
|
||||
}
|
||||
|
||||
PlaybackPositionChanged();
|
||||
PlaybackPositionChanged(aEventVisibility);
|
||||
|
||||
if (mOwner) {
|
||||
UpdateReadyStateForData();
|
||||
if (!seekWasAborted) {
|
||||
if (!seekWasAborted && (aEventVisibility != MediaDecoderEventVisibility::Suppressed)) {
|
||||
mOwner->SeekCompleted();
|
||||
if (fireEnded) {
|
||||
mOwner->PlaybackEnded();
|
||||
@ -1262,7 +1270,7 @@ void MediaDecoder::SeekingStoppedAtEnd()
|
||||
}
|
||||
}
|
||||
|
||||
void MediaDecoder::SeekingStarted()
|
||||
void MediaDecoder::SeekingStarted(MediaDecoderEventVisibility aEventVisibility)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (mShuttingDown)
|
||||
@ -1270,7 +1278,9 @@ void MediaDecoder::SeekingStarted()
|
||||
|
||||
if (mOwner) {
|
||||
UpdateReadyStateForData();
|
||||
mOwner->SeekStarted();
|
||||
if (aEventVisibility != MediaDecoderEventVisibility::Suppressed) {
|
||||
mOwner->SeekStarted();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1302,7 +1312,7 @@ void MediaDecoder::ChangeState(PlayState aState)
|
||||
|
||||
if (mPlayState == PLAY_STATE_PLAYING) {
|
||||
ConstructMediaTracks();
|
||||
} else if (mPlayState == PLAY_STATE_ENDED) {
|
||||
} else if (IsEnded()) {
|
||||
RemoveMediaTracks();
|
||||
}
|
||||
|
||||
@ -1338,7 +1348,7 @@ void MediaDecoder::ApplyStateToStateMachine(PlayState aState)
|
||||
}
|
||||
}
|
||||
|
||||
void MediaDecoder::PlaybackPositionChanged()
|
||||
void MediaDecoder::PlaybackPositionChanged(MediaDecoderEventVisibility aEventVisibility)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (mShuttingDown)
|
||||
@ -1374,7 +1384,9 @@ void MediaDecoder::PlaybackPositionChanged()
|
||||
// frame has reflowed and the size updated beforehand.
|
||||
Invalidate();
|
||||
|
||||
if (mOwner && lastTime != mCurrentTime) {
|
||||
if (mOwner &&
|
||||
(aEventVisibility != MediaDecoderEventVisibility::Suppressed) &&
|
||||
lastTime != mCurrentTime) {
|
||||
FireTimeUpdate();
|
||||
}
|
||||
}
|
||||
|
@ -235,16 +235,22 @@ struct SeekTarget {
|
||||
SeekTarget()
|
||||
: mTime(-1.0)
|
||||
, mType(SeekTarget::Invalid)
|
||||
, mEventVisibility(MediaDecoderEventVisibility::Observable)
|
||||
{
|
||||
}
|
||||
SeekTarget(int64_t aTimeUsecs, Type aType)
|
||||
SeekTarget(int64_t aTimeUsecs,
|
||||
Type aType,
|
||||
MediaDecoderEventVisibility aEventVisibility =
|
||||
MediaDecoderEventVisibility::Observable)
|
||||
: mTime(aTimeUsecs)
|
||||
, mType(aType)
|
||||
, mEventVisibility(aEventVisibility)
|
||||
{
|
||||
}
|
||||
SeekTarget(const SeekTarget& aOther)
|
||||
: mTime(aOther.mTime)
|
||||
, mType(aOther.mType)
|
||||
, mEventVisibility(aOther.mEventVisibility)
|
||||
{
|
||||
}
|
||||
bool IsValid() const {
|
||||
@ -260,6 +266,7 @@ struct SeekTarget {
|
||||
// "Fast" seeks to the seek point preceeding mTime, whereas
|
||||
// "Accurate" seeks as close as possible to mTime.
|
||||
Type mType;
|
||||
MediaDecoderEventVisibility mEventVisibility;
|
||||
};
|
||||
|
||||
class MediaDecoder : public nsIObserver,
|
||||
@ -576,9 +583,10 @@ public:
|
||||
// Call on the main thread only.
|
||||
virtual bool IsSeeking() const;
|
||||
|
||||
// Return true if the decoder has reached the end of playback.
|
||||
// Return true if the decoder has reached the end of playback or the decoder
|
||||
// has shutdown.
|
||||
// Call on the main thread only.
|
||||
virtual bool IsEnded() const;
|
||||
virtual bool IsEndedOrShutdown() const;
|
||||
|
||||
// Set the duration of the media resource in units of seconds.
|
||||
// This is called via a channel listener if it can pick up the duration
|
||||
@ -766,12 +774,12 @@ public:
|
||||
// state machine. Call on the main thread only.
|
||||
virtual void MetadataLoaded(nsAutoPtr<MediaInfo> aInfo,
|
||||
nsAutoPtr<MetadataTags> aTags,
|
||||
bool aRestoredFromDormant) MOZ_OVERRIDE;
|
||||
MediaDecoderEventVisibility aEventVisibility) MOZ_OVERRIDE;
|
||||
|
||||
// Called when the first audio and/or video from the media file has been loaded
|
||||
// by the state machine. Call on the main thread only.
|
||||
virtual void FirstFrameLoaded(nsAutoPtr<MediaInfo> aInfo,
|
||||
bool aRestoredFromDormant) MOZ_OVERRIDE;
|
||||
MediaDecoderEventVisibility aEventVisibility) MOZ_OVERRIDE;
|
||||
|
||||
// Called from MetadataLoaded(). Creates audio tracks and adds them to its
|
||||
// owner's audio track list, and implies to video tracks respectively.
|
||||
@ -795,20 +803,20 @@ public:
|
||||
|
||||
// Seeking has stopped. Inform the element on the main
|
||||
// thread.
|
||||
void SeekingStopped();
|
||||
void SeekingStopped(MediaDecoderEventVisibility aEventVisibility = MediaDecoderEventVisibility::Observable);
|
||||
|
||||
// Seeking has stopped at the end of the resource. Inform the element on the main
|
||||
// thread.
|
||||
void SeekingStoppedAtEnd();
|
||||
void SeekingStoppedAtEnd(MediaDecoderEventVisibility aEventVisibility = MediaDecoderEventVisibility::Observable);
|
||||
|
||||
// Seeking has started. Inform the element on the main
|
||||
// thread.
|
||||
void SeekingStarted();
|
||||
void SeekingStarted(MediaDecoderEventVisibility aEventVisibility = MediaDecoderEventVisibility::Observable);
|
||||
|
||||
// Called when the backend has changed the current playback
|
||||
// position. It dispatches a timeupdate event and invalidates the frame.
|
||||
// This must be called on the main thread only.
|
||||
virtual void PlaybackPositionChanged();
|
||||
virtual void PlaybackPositionChanged(MediaDecoderEventVisibility aEventVisibility = MediaDecoderEventVisibility::Observable);
|
||||
|
||||
// Calls mElement->UpdateReadyStateForData, telling it whether we have
|
||||
// data for the next frame and if we're buffering. Main thread only.
|
||||
@ -1028,6 +1036,9 @@ protected:
|
||||
// Cancel a timer for heuristic dormant.
|
||||
void CancelDormantTimer();
|
||||
|
||||
// Return true if the decoder has reached the end of playback
|
||||
bool IsEnded() const;
|
||||
|
||||
/******
|
||||
* The following members should be accessed with the decoder lock held.
|
||||
******/
|
||||
@ -1196,6 +1207,12 @@ protected:
|
||||
// True if MediaDecoder is in dormant state.
|
||||
bool mIsDormant;
|
||||
|
||||
// True if MediaDecoder was PLAY_STATE_ENDED state, when entering to dormant.
|
||||
// When MediaCodec is in dormant during PLAY_STATE_ENDED state, PlayState
|
||||
// becomes different from PLAY_STATE_ENDED. But the MediaDecoder need to act
|
||||
// as in PLAY_STATE_ENDED state to MediaDecoderOwner.
|
||||
bool mWasEndedWhenEnteredDormant;
|
||||
|
||||
// True if heuristic dormant is supported.
|
||||
const bool mIsHeuristicDormantSupported;
|
||||
|
||||
|
@ -1245,7 +1245,10 @@ void MediaDecoderStateMachine::UpdatePlaybackPosition(int64_t aTime)
|
||||
if (!mPositionChangeQueued || fragmentEnded) {
|
||||
mPositionChangeQueued = true;
|
||||
nsCOMPtr<nsIRunnable> event =
|
||||
NS_NewRunnableMethod(mDecoder, &MediaDecoder::PlaybackPositionChanged);
|
||||
NS_NewRunnableMethodWithArg<MediaDecoderEventVisibility>(
|
||||
mDecoder,
|
||||
&MediaDecoder::PlaybackPositionChanged,
|
||||
MediaDecoderEventVisibility::Observable);
|
||||
NS_DispatchToMainThread(event);
|
||||
}
|
||||
|
||||
@ -1457,6 +1460,10 @@ void MediaDecoderStateMachine::SetDormant(bool aDormant)
|
||||
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
|
||||
AssertCurrentThreadInMonitor();
|
||||
|
||||
if (mState == DECODER_STATE_SHUTDOWN) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mReader) {
|
||||
return;
|
||||
}
|
||||
@ -1464,12 +1471,22 @@ void MediaDecoderStateMachine::SetDormant(bool aDormant)
|
||||
DECODER_LOG("SetDormant=%d", aDormant);
|
||||
|
||||
if (aDormant) {
|
||||
if (mState == DECODER_STATE_SEEKING && !mQueuedSeekTarget.IsValid()) {
|
||||
if (mSeekTarget.IsValid()) {
|
||||
if (mState == DECODER_STATE_SEEKING) {
|
||||
if (mQueuedSeekTarget.IsValid()) {
|
||||
// Keep latest seek target
|
||||
} else if (mSeekTarget.IsValid()) {
|
||||
mQueuedSeekTarget = mSeekTarget;
|
||||
} else if (mCurrentSeekTarget.IsValid()) {
|
||||
mQueuedSeekTarget = mCurrentSeekTarget;
|
||||
} else {
|
||||
mQueuedSeekTarget = SeekTarget(mCurrentFrameTime,
|
||||
SeekTarget::Accurate,
|
||||
MediaDecoderEventVisibility::Suppressed);
|
||||
}
|
||||
} else {
|
||||
mQueuedSeekTarget = SeekTarget(mCurrentFrameTime,
|
||||
SeekTarget::Accurate,
|
||||
MediaDecoderEventVisibility::Suppressed);
|
||||
}
|
||||
mSeekTarget.Reset();
|
||||
mCurrentSeekTarget.Reset();
|
||||
@ -1740,7 +1757,7 @@ MediaDecoderStateMachine::StartSeek(const SeekTarget& aTarget)
|
||||
seekTime = std::max(mStartTime, seekTime);
|
||||
NS_ASSERTION(seekTime >= mStartTime && seekTime <= end,
|
||||
"Can only seek in range [0,duration]");
|
||||
mSeekTarget = SeekTarget(seekTime, aTarget.mType);
|
||||
mSeekTarget = SeekTarget(seekTime, aTarget.mType, aTarget.mEventVisibility);
|
||||
|
||||
DECODER_LOG("Changed state to SEEKING (to %lld)", mSeekTarget.mTime);
|
||||
SetState(DECODER_STATE_SEEKING);
|
||||
@ -2257,8 +2274,11 @@ MediaDecoderStateMachine::EnqueueLoadedMetadataEvent()
|
||||
{
|
||||
nsAutoPtr<MediaInfo> info(new MediaInfo());
|
||||
*info = mInfo;
|
||||
MediaDecoderEventVisibility visibility = mSentLoadedMetadataEvent?
|
||||
MediaDecoderEventVisibility::Suppressed :
|
||||
MediaDecoderEventVisibility::Observable;
|
||||
nsCOMPtr<nsIRunnable> metadataLoadedEvent =
|
||||
new MetadataEventRunner(mDecoder, info, mMetadataTags, mSentLoadedMetadataEvent);
|
||||
new MetadataEventRunner(mDecoder, info, mMetadataTags, visibility);
|
||||
NS_DispatchToMainThread(metadataLoadedEvent, NS_DISPATCH_NORMAL);
|
||||
mSentLoadedMetadataEvent = true;
|
||||
}
|
||||
@ -2268,8 +2288,11 @@ MediaDecoderStateMachine::EnqueueFirstFrameLoadedEvent()
|
||||
{
|
||||
nsAutoPtr<MediaInfo> info(new MediaInfo());
|
||||
*info = mInfo;
|
||||
MediaDecoderEventVisibility visibility = mSentFirstFrameLoadedEvent?
|
||||
MediaDecoderEventVisibility::Suppressed :
|
||||
MediaDecoderEventVisibility::Observable;
|
||||
nsCOMPtr<nsIRunnable> event =
|
||||
new FirstFrameLoadedEventRunner(mDecoder, info, mSentFirstFrameLoadedEvent);
|
||||
new FirstFrameLoadedEventRunner(mDecoder, info, visibility);
|
||||
NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
|
||||
mSentFirstFrameLoadedEvent = true;
|
||||
}
|
||||
@ -2474,7 +2497,10 @@ void MediaDecoderStateMachine::DecodeSeek()
|
||||
{
|
||||
ReentrantMonitorAutoExit exitMon(mDecoder->GetReentrantMonitor());
|
||||
nsCOMPtr<nsIRunnable> startEvent =
|
||||
NS_NewRunnableMethod(mDecoder, &MediaDecoder::SeekingStarted);
|
||||
NS_NewRunnableMethodWithArg<MediaDecoderEventVisibility>(
|
||||
mDecoder,
|
||||
&MediaDecoder::SeekingStarted,
|
||||
mCurrentSeekTarget.mEventVisibility);
|
||||
NS_DispatchToMainThread(startEvent, NS_DISPATCH_SYNC);
|
||||
}
|
||||
if (mState != DECODER_STATE_SEEKING) {
|
||||
@ -2552,6 +2578,15 @@ MediaDecoderStateMachine::OnSeekFailed(nsresult aResult)
|
||||
// Try again.
|
||||
mCurrentSeekTarget = mSeekTarget;
|
||||
mSeekTarget.Reset();
|
||||
{
|
||||
ReentrantMonitorAutoExit exitMon(mDecoder->GetReentrantMonitor());
|
||||
nsCOMPtr<nsIRunnable> startEvent =
|
||||
NS_NewRunnableMethodWithArg<MediaDecoderEventVisibility>(
|
||||
mDecoder,
|
||||
&MediaDecoder::SeekingStarted,
|
||||
mCurrentSeekTarget.mEventVisibility);
|
||||
NS_DispatchToMainThread(startEvent, NS_DISPATCH_SYNC);
|
||||
}
|
||||
mReader->Seek(mCurrentSeekTarget.mTime, mEndTime)
|
||||
->Then(DecodeTaskQueue(), __func__, this,
|
||||
&MediaDecoderStateMachine::OnSeekCompleted,
|
||||
@ -2638,14 +2673,20 @@ MediaDecoderStateMachine::SeekCompleted()
|
||||
// this if we're playing a live stream, since the end of media will advance
|
||||
// once we download more data!
|
||||
DECODER_LOG("Changed state from SEEKING (to %lld) to COMPLETED", seekTime);
|
||||
stopEvent = NS_NewRunnableMethod(mDecoder, &MediaDecoder::SeekingStoppedAtEnd);
|
||||
stopEvent = NS_NewRunnableMethodWithArg<MediaDecoderEventVisibility>(
|
||||
mDecoder,
|
||||
&MediaDecoder::SeekingStoppedAtEnd,
|
||||
mCurrentSeekTarget.mEventVisibility);
|
||||
// Explicitly set our state so we don't decode further, and so
|
||||
// we report playback ended to the media element.
|
||||
SetState(DECODER_STATE_COMPLETED);
|
||||
DispatchDecodeTasksIfNeeded();
|
||||
} else {
|
||||
DECODER_LOG("Changed state from SEEKING (to %lld) to DECODING", seekTime);
|
||||
stopEvent = NS_NewRunnableMethod(mDecoder, &MediaDecoder::SeekingStopped);
|
||||
stopEvent = NS_NewRunnableMethodWithArg<MediaDecoderEventVisibility>(
|
||||
mDecoder,
|
||||
&MediaDecoder::SeekingStopped,
|
||||
mCurrentSeekTarget.mEventVisibility);
|
||||
StartDecoding();
|
||||
}
|
||||
|
||||
|
@ -99,14 +99,14 @@ SourceBufferDecoder::IsMediaSeekable()
|
||||
void
|
||||
SourceBufferDecoder::MetadataLoaded(nsAutoPtr<MediaInfo> aInfo,
|
||||
nsAutoPtr<MetadataTags> aTags,
|
||||
bool aRestoredFromDormant)
|
||||
MediaDecoderEventVisibility aEventVisibility)
|
||||
{
|
||||
MSE_DEBUG("UNIMPLEMENTED");
|
||||
}
|
||||
|
||||
void
|
||||
SourceBufferDecoder::FirstFrameLoaded(nsAutoPtr<MediaInfo> aInfo,
|
||||
bool aRestoredFromDormant)
|
||||
MediaDecoderEventVisibility aEventVisibility)
|
||||
{
|
||||
MSE_DEBUG("UNIMPLEMENTED");
|
||||
}
|
||||
|
@ -48,8 +48,11 @@ public:
|
||||
virtual SourceBufferResource* GetResource() const MOZ_FINAL MOZ_OVERRIDE;
|
||||
virtual ReentrantMonitor& GetReentrantMonitor() MOZ_FINAL MOZ_OVERRIDE;
|
||||
virtual VideoFrameContainer* GetVideoFrameContainer() MOZ_FINAL MOZ_OVERRIDE;
|
||||
virtual void MetadataLoaded(nsAutoPtr<MediaInfo> aInfo, nsAutoPtr<MetadataTags> aTags, bool aRestoredFromDormant) MOZ_FINAL MOZ_OVERRIDE;
|
||||
virtual void FirstFrameLoaded(nsAutoPtr<MediaInfo> aInfo, bool aRestoredFromDormant) MOZ_FINAL MOZ_OVERRIDE;
|
||||
virtual void MetadataLoaded(nsAutoPtr<MediaInfo> aInfo,
|
||||
nsAutoPtr<MetadataTags> aTags,
|
||||
MediaDecoderEventVisibility aEventVisibility) MOZ_FINAL MOZ_OVERRIDE;
|
||||
virtual void FirstFrameLoaded(nsAutoPtr<MediaInfo> aInfo,
|
||||
MediaDecoderEventVisibility aEventVisibility) MOZ_FINAL MOZ_OVERRIDE;
|
||||
virtual void NotifyBytesConsumed(int64_t aBytes, int64_t aOffset) MOZ_FINAL MOZ_OVERRIDE;
|
||||
virtual void NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_t aOffset) MOZ_FINAL MOZ_OVERRIDE;
|
||||
virtual void NotifyDecodedFrames(uint32_t aParsed, uint32_t aDecoded, uint32_t aDropped) MOZ_FINAL MOZ_OVERRIDE;
|
||||
|
@ -360,8 +360,11 @@ status_t AudioOffloadPlayer::SeekTo(int64_t aTimeUs, bool aDispatchSeekEvents)
|
||||
mDispatchSeekEvents = aDispatchSeekEvents;
|
||||
|
||||
if (mDispatchSeekEvents) {
|
||||
nsCOMPtr<nsIRunnable> nsEvent = NS_NewRunnableMethod(mObserver,
|
||||
&MediaDecoder::SeekingStarted);
|
||||
nsCOMPtr<nsIRunnable> nsEvent =
|
||||
NS_NewRunnableMethodWithArg<MediaDecoderEventVisibility>(
|
||||
mObserver,
|
||||
&MediaDecoder::SeekingStarted,
|
||||
MediaDecoderEventVisibility::Observable);
|
||||
NS_DispatchToCurrentThread(nsEvent);
|
||||
}
|
||||
|
||||
@ -380,8 +383,11 @@ status_t AudioOffloadPlayer::SeekTo(int64_t aTimeUs, bool aDispatchSeekEvents)
|
||||
if (mDispatchSeekEvents) {
|
||||
mDispatchSeekEvents = false;
|
||||
AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("Fake seek complete during pause"));
|
||||
nsCOMPtr<nsIRunnable> nsEvent = NS_NewRunnableMethod(mObserver,
|
||||
&MediaDecoder::SeekingStopped);
|
||||
nsCOMPtr<nsIRunnable> nsEvent =
|
||||
NS_NewRunnableMethodWithArg<MediaDecoderEventVisibility>(
|
||||
mObserver,
|
||||
&MediaDecoder::SeekingStopped,
|
||||
MediaDecoderEventVisibility::Observable);
|
||||
NS_DispatchToCurrentThread(nsEvent);
|
||||
}
|
||||
}
|
||||
@ -440,8 +446,11 @@ void AudioOffloadPlayer::NotifyAudioEOS()
|
||||
|
||||
void AudioOffloadPlayer::NotifyPositionChanged()
|
||||
{
|
||||
nsCOMPtr<nsIRunnable> nsEvent = NS_NewRunnableMethod(mObserver,
|
||||
&MediaOmxCommonDecoder::PlaybackPositionChanged);
|
||||
nsCOMPtr<nsIRunnable> nsEvent =
|
||||
NS_NewRunnableMethodWithArg<MediaDecoderEventVisibility>(
|
||||
mObserver,
|
||||
&MediaOmxCommonDecoder::PlaybackPositionChanged,
|
||||
MediaDecoderEventVisibility::Observable);
|
||||
NS_DispatchToMainThread(nsEvent);
|
||||
}
|
||||
|
||||
@ -559,8 +568,11 @@ size_t AudioOffloadPlayer::FillBuffer(void* aData, size_t aSize)
|
||||
if (mDispatchSeekEvents && !mSeekDuringPause) {
|
||||
mDispatchSeekEvents = false;
|
||||
AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("FillBuffer posting SEEK_COMPLETE"));
|
||||
nsCOMPtr<nsIRunnable> nsEvent = NS_NewRunnableMethod(mObserver,
|
||||
&MediaDecoder::SeekingStopped);
|
||||
nsCOMPtr<nsIRunnable> nsEvent =
|
||||
NS_NewRunnableMethodWithArg<MediaDecoderEventVisibility>(
|
||||
mObserver,
|
||||
&MediaDecoder::SeekingStopped,
|
||||
MediaDecoderEventVisibility::Observable);
|
||||
NS_DispatchToMainThread(nsEvent, NS_DISPATCH_NORMAL);
|
||||
|
||||
} else if (mSeekDuringPause) {
|
||||
|
@ -58,10 +58,10 @@ MediaOmxCommonDecoder::CheckDecoderCanOffloadAudio()
|
||||
|
||||
void
|
||||
MediaOmxCommonDecoder::FirstFrameLoaded(nsAutoPtr<MediaInfo> aInfo,
|
||||
bool aRestoredFromDormant)
|
||||
MediaDecoderEventVisibility aEventVisibility)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MediaDecoder::FirstFrameLoaded(aInfo, aRestoredFromDormant);
|
||||
MediaDecoder::FirstFrameLoaded(aInfo, aEventVisibility);
|
||||
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
if (!CheckDecoderCanOffloadAudio()) {
|
||||
@ -203,7 +203,7 @@ MediaOmxCommonDecoder::ApplyStateToStateMachine(PlayState aState)
|
||||
}
|
||||
|
||||
void
|
||||
MediaOmxCommonDecoder::PlaybackPositionChanged()
|
||||
MediaOmxCommonDecoder::PlaybackPositionChanged(MediaDecoderEventVisibility aEventVisibility)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (!mAudioOffloadPlayer) {
|
||||
@ -220,7 +220,9 @@ MediaOmxCommonDecoder::PlaybackPositionChanged()
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
mCurrentTime = mAudioOffloadPlayer->GetMediaTimeSecs();
|
||||
}
|
||||
if (mOwner && lastTime != mCurrentTime) {
|
||||
if (mOwner &&
|
||||
(aEventVisibility != MediaDecoderEventVisibility::Suppressed) &&
|
||||
lastTime != mCurrentTime) {
|
||||
FireTimeUpdate();
|
||||
}
|
||||
}
|
||||
|
@ -24,11 +24,12 @@ public:
|
||||
MediaOmxCommonDecoder();
|
||||
|
||||
virtual void FirstFrameLoaded(nsAutoPtr<MediaInfo> aInfo,
|
||||
bool aRestoredFromDormant);
|
||||
MediaDecoderEventVisibility aEventVisibility);
|
||||
virtual void ChangeState(PlayState aState);
|
||||
virtual void ApplyStateToStateMachine(PlayState aState);
|
||||
virtual void SetVolume(double aVolume);
|
||||
virtual void PlaybackPositionChanged();
|
||||
virtual void PlaybackPositionChanged(MediaDecoderEventVisibility aEventVisibility =
|
||||
MediaDecoderEventVisibility::Observable);
|
||||
virtual void UpdateReadyStateForData();
|
||||
virtual void SetElementVisibility(bool aIsVisible);
|
||||
virtual void SetPlatformCanOffloadAudio(bool aCanOffloadAudio);
|
||||
|
@ -141,13 +141,13 @@ BufferDecoder::IsMediaSeekable()
|
||||
}
|
||||
|
||||
void
|
||||
BufferDecoder::MetadataLoaded(nsAutoPtr<MediaInfo> aInfo, nsAutoPtr<MetadataTags> aTags, bool aRestoredFromDormant)
|
||||
BufferDecoder::MetadataLoaded(nsAutoPtr<MediaInfo> aInfo, nsAutoPtr<MetadataTags> aTags, MediaDecoderEventVisibility aEventVisibility)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
|
||||
void
|
||||
BufferDecoder::FirstFrameLoaded(nsAutoPtr<MediaInfo> aInfo, bool aRestoredFromDormant)
|
||||
BufferDecoder::FirstFrameLoaded(nsAutoPtr<MediaInfo> aInfo, MediaDecoderEventVisibility aEventVisibility)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
|
@ -60,9 +60,12 @@ public:
|
||||
|
||||
virtual bool IsMediaSeekable() MOZ_FINAL MOZ_OVERRIDE;
|
||||
|
||||
virtual void MetadataLoaded(nsAutoPtr<MediaInfo> aInfo, nsAutoPtr<MetadataTags> aTags, bool aRestoredFromDormant) MOZ_FINAL MOZ_OVERRIDE;
|
||||
virtual void MetadataLoaded(nsAutoPtr<MediaInfo> aInfo,
|
||||
nsAutoPtr<MetadataTags> aTags,
|
||||
MediaDecoderEventVisibility aEventVisibility) MOZ_FINAL MOZ_OVERRIDE;
|
||||
virtual void QueueMetadata(int64_t aTime, nsAutoPtr<MediaInfo> aInfo, nsAutoPtr<MetadataTags> aTags) MOZ_FINAL MOZ_OVERRIDE;
|
||||
virtual void FirstFrameLoaded(nsAutoPtr<MediaInfo> aInfo, bool aRestoredFromDormant) MOZ_FINAL MOZ_OVERRIDE;
|
||||
virtual void FirstFrameLoaded(nsAutoPtr<MediaInfo> aInfo,
|
||||
MediaDecoderEventVisibility aEventVisibility) MOZ_FINAL MOZ_OVERRIDE;
|
||||
|
||||
virtual void RemoveMediaTracks() MOZ_FINAL MOZ_OVERRIDE;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user