Bug 1128357 Patch 2: Don't dispatch seeking/seeked events when coming out of dormant mode r=cpearce

This commit is contained in:
Sotaro Ikeda 2015-03-04 17:33:40 -08:00
parent dad8dee2fb
commit 796ca98bba
12 changed files with 189 additions and 93 deletions

View File

@ -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() ||

View File

@ -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;
}
};

View File

@ -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());
@ -910,7 +909,7 @@ void MediaDecoder::FirstFrameLoaded(nsAutoPtr<MediaInfo> aInfo,
if (mOwner) {
Invalidate();
if (!aRestoredFromDormant) {
if (aEventVisibility != MediaDecoderEventVisibility::Suppressed) {
mOwner->FirstFrameLoaded();
}
}
@ -996,10 +995,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()
@ -1182,14 +1187,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());
@ -1207,15 +1213,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();
}
}
@ -1223,7 +1231,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());
@ -1247,11 +1255,11 @@ void MediaDecoder::SeekingStoppedAtEnd()
}
}
PlaybackPositionChanged();
PlaybackPositionChanged(aEventVisibility);
if (mOwner) {
UpdateReadyStateForData();
if (!seekWasAborted) {
if (!seekWasAborted && (aEventVisibility != MediaDecoderEventVisibility::Suppressed)) {
mOwner->SeekCompleted();
if (fireEnded) {
mOwner->PlaybackEnded();
@ -1260,7 +1268,7 @@ void MediaDecoder::SeekingStoppedAtEnd()
}
}
void MediaDecoder::SeekingStarted()
void MediaDecoder::SeekingStarted(MediaDecoderEventVisibility aEventVisibility)
{
MOZ_ASSERT(NS_IsMainThread());
if (mShuttingDown)
@ -1268,7 +1276,9 @@ void MediaDecoder::SeekingStarted()
if (mOwner) {
UpdateReadyStateForData();
mOwner->SeekStarted();
if (aEventVisibility != MediaDecoderEventVisibility::Suppressed) {
mOwner->SeekStarted();
}
}
}
@ -1300,7 +1310,7 @@ void MediaDecoder::ChangeState(PlayState aState)
if (mPlayState == PLAY_STATE_PLAYING) {
ConstructMediaTracks();
} else if (mPlayState == PLAY_STATE_ENDED) {
} else if (IsEnded()) {
RemoveMediaTracks();
}
@ -1336,7 +1346,7 @@ void MediaDecoder::ApplyStateToStateMachine(PlayState aState)
}
}
void MediaDecoder::PlaybackPositionChanged()
void MediaDecoder::PlaybackPositionChanged(MediaDecoderEventVisibility aEventVisibility)
{
MOZ_ASSERT(NS_IsMainThread());
if (mShuttingDown)
@ -1372,7 +1382,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();
}
}

View File

@ -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;

View File

@ -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();
}

View File

@ -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");
}

View File

@ -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;

View File

@ -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) {

View File

@ -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();
}
}

View File

@ -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);

View File

@ -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
}

View File

@ -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;