Backed out changeset 1f5a169f0476 (bug 1139206) due to it causing bug 1150716

This commit is contained in:
Naoki Hirata 2015-04-02 18:17:36 -07:00
parent 861aa7e2cc
commit aed24c1ceb
6 changed files with 131 additions and 121 deletions

View File

@ -1215,10 +1215,9 @@ void MediaDecoder::UpdateReadyStateForData()
mOwner->UpdateReadyStateForData(frameStatus);
}
void MediaDecoder::OnSeekResolved(SeekResolveValue aVal)
void MediaDecoder::OnSeekResolvedInternal(bool aAtEnd, MediaDecoderEventVisibility aEventVisibility)
{
MOZ_ASSERT(NS_IsMainThread());
mSeekRequest.Complete();
if (mShuttingDown)
return;
@ -1235,20 +1234,20 @@ void MediaDecoder::OnSeekResolved(SeekResolveValue aVal)
seekWasAborted = true;
} else {
UnpinForSeek();
fireEnded = aVal.mAtEnd;
if (aVal.mAtEnd) {
fireEnded = aAtEnd;
if (aAtEnd) {
ChangeState(PLAY_STATE_ENDED);
} else if (aVal.mEventVisibility != MediaDecoderEventVisibility::Suppressed) {
ChangeState(aVal.mAtEnd ? PLAY_STATE_ENDED : mNextState);
} else if (aEventVisibility != MediaDecoderEventVisibility::Suppressed) {
ChangeState(aAtEnd ? PLAY_STATE_ENDED : mNextState);
}
}
}
PlaybackPositionChanged(aVal.mEventVisibility);
PlaybackPositionChanged(aEventVisibility);
if (mOwner) {
UpdateReadyStateForData();
if (!seekWasAborted && (aVal.mEventVisibility != MediaDecoderEventVisibility::Suppressed)) {
if (!seekWasAborted && (aEventVisibility != MediaDecoderEventVisibility::Suppressed)) {
mOwner->SeekCompleted();
if (fireEnded) {
mOwner->PlaybackEnded();

View File

@ -806,7 +806,21 @@ public:
void PlaybackEnded();
void OnSeekRejected() { mSeekRequest.Complete(); }
void OnSeekResolved(SeekResolveValue aVal);
void OnSeekResolvedInternal(bool aAtEnd, MediaDecoderEventVisibility aEventVisibility);
void OnSeekResolved(SeekResolveValue aVal)
{
mSeekRequest.Complete();
OnSeekResolvedInternal(aVal.mAtEnd, aVal.mEventVisibility);
}
#ifdef MOZ_AUDIO_OFFLOAD
// Temporary hack - see bug 1139206.
void SimulateSeekResolvedForAudioOffload(MediaDecoderEventVisibility aEventVisibility)
{
OnSeekResolvedInternal(false, aEventVisibility);
}
#endif
// Seeking has started. Inform the element on the main
// thread.

View File

@ -57,10 +57,13 @@ static const uint64_t OFFLOAD_PAUSE_MAX_MSECS = 60000ll;
AudioOffloadPlayer::AudioOffloadPlayer(MediaOmxCommonDecoder* aObserver) :
mStarted(false),
mPlaying(false),
mSeeking(false),
mReachedEOS(false),
mSeekDuringPause(false),
mIsElementVisible(true),
mSampleRate(0),
mStartPosUs(0),
mSeekTimeUs(0),
mPositionTimeMediaUs(-1),
mInputBuffer(nullptr),
mObserver(aObserver)
@ -196,6 +199,13 @@ status_t AudioOffloadPlayer::ChangeState(MediaDecoder::PlayState aState)
StartTimeUpdate();
} break;
case MediaDecoder::PLAY_STATE_SEEKING: {
int64_t seekTimeUs
= mObserver->GetSeekTime();
SeekTo(seekTimeUs, true);
mObserver->ResetSeekTime();
} break;
case MediaDecoder::PLAY_STATE_PAUSED:
case MediaDecoder::PLAY_STATE_SHUTDOWN:
// Just pause here during play state shutdown as well to stop playing
@ -268,12 +278,8 @@ status_t AudioOffloadPlayer::Play()
return err;
}
// Seek to last play position only when there was no seek during last pause
android::Mutex::Autolock autoLock(mLock);
if (!mSeekTarget.IsValid()) {
mSeekTarget = SeekTarget(mPositionTimeMediaUs,
SeekTarget::Accurate,
MediaDecoderEventVisibility::Suppressed);
DoSeek();
if (!mSeeking) {
SeekTo(mPositionTimeMediaUs);
}
}
@ -337,36 +343,28 @@ void AudioOffloadPlayer::Reset()
WakeLockRelease();
}
nsRefPtr<MediaDecoder::SeekPromise> AudioOffloadPlayer::Seek(SeekTarget aTarget)
status_t AudioOffloadPlayer::SeekTo(int64_t aTimeUs, bool aDispatchSeekEvents)
{
MOZ_ASSERT(NS_IsMainThread());
android::Mutex::Autolock autoLock(mLock);
mSeekPromise.RejectIfExists(true, __func__);
mSeekTarget = aTarget;
nsRefPtr<MediaDecoder::SeekPromise> p = mSeekPromise.Ensure(__func__);
DoSeek();
return p;
}
status_t AudioOffloadPlayer::DoSeek()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mSeekTarget.IsValid());
CHECK(mAudioSink.get());
AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("DoSeek ( %lld )", mSeekTarget.mTime));
android::Mutex::Autolock autoLock(mLock);
AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("SeekTo ( %lld )", aTimeUs));
mSeeking = true;
mReachedEOS = false;
mPositionTimeMediaUs = -1;
mStartPosUs = mSeekTarget.mTime;
mSeekTimeUs = aTimeUs;
mStartPosUs = aTimeUs;
mDispatchSeekEvents = aDispatchSeekEvents;
if (!mSeekPromise.IsEmpty()) {
if (mDispatchSeekEvents) {
nsCOMPtr<nsIRunnable> nsEvent =
NS_NewRunnableMethodWithArg<MediaDecoderEventVisibility>(
mObserver,
&MediaDecoder::SeekingStarted,
mSeekTarget.mEventVisibility);
MediaDecoderEventVisibility::Observable);
NS_DispatchToCurrentThread(nsEvent);
}
@ -376,15 +374,21 @@ status_t AudioOffloadPlayer::DoSeek()
mAudioSink->Start();
} else {
mSeekDuringPause = true;
if (mStarted) {
mAudioSink->Flush();
}
if (!mSeekPromise.IsEmpty()) {
if (mDispatchSeekEvents) {
mDispatchSeekEvents = false;
AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("Fake seek complete during pause"));
// We do not reset mSeekTarget here.
MediaDecoder::SeekResolveValue val(mReachedEOS, mSeekTarget.mEventVisibility);
mSeekPromise.Resolve(val, __func__);
nsCOMPtr<nsIRunnable> nsEvent =
NS_NewRunnableMethodWithArg<MediaDecoderEventVisibility>(
mObserver,
&MediaDecoder::SimulateSeekResolvedForAudioOffload,
MediaDecoderEventVisibility::Observable);
NS_DispatchToCurrentThread(nsEvent);
}
}
@ -403,8 +407,8 @@ int64_t AudioOffloadPlayer::GetMediaTimeUs()
android::Mutex::Autolock autoLock(mLock);
int64_t playPosition = 0;
if (mSeekTarget.IsValid()) {
return mSeekTarget.mTime;
if (mSeeking) {
return mSeekTimeUs;
}
if (!mStarted) {
return mPositionTimeMediaUs;
@ -435,12 +439,6 @@ int64_t AudioOffloadPlayer::GetOutputPlayPositionUs_l() const
void AudioOffloadPlayer::NotifyAudioEOS()
{
android::Mutex::Autolock autoLock(mLock);
// We do not reset mSeekTarget here.
if (!mSeekPromise.IsEmpty()) {
MediaDecoder::SeekResolveValue val(mReachedEOS, mSeekTarget.mEventVisibility);
mSeekPromise.Resolve(val, __func__);
}
nsCOMPtr<nsIRunnable> nsEvent = NS_NewRunnableMethod(mObserver,
&MediaDecoder::PlaybackEnded);
NS_DispatchToMainThread(nsEvent);
@ -458,15 +456,6 @@ void AudioOffloadPlayer::NotifyPositionChanged()
void AudioOffloadPlayer::NotifyAudioTearDown()
{
// Fallback to state machine.
// state machine's seeks will be done with
// MediaDecoderEventVisibility::Suppressed.
android::Mutex::Autolock autoLock(mLock);
// We do not reset mSeekTarget here.
if (!mSeekPromise.IsEmpty()) {
MediaDecoder::SeekResolveValue val(mReachedEOS, mSeekTarget.mEventVisibility);
mSeekPromise.Resolve(val, __func__);
}
nsCOMPtr<nsIRunnable> nsEvent = NS_NewRunnableMethod(mObserver,
&MediaOmxCommonDecoder::AudioOffloadTearDown);
NS_DispatchToMainThread(nsEvent);
@ -517,24 +506,27 @@ size_t AudioOffloadPlayer::FillBuffer(void* aData, size_t aSize)
size_t sizeDone = 0;
size_t sizeRemaining = aSize;
int64_t seekTimeUs = -1;
while (sizeRemaining > 0) {
MediaSource::ReadOptions options;
bool refreshSeekTime = false;
{
android::Mutex::Autolock autoLock(mLock);
if (mSeekTarget.IsValid()) {
seekTimeUs = mSeekTarget.mTime;
options.setSeekTo(seekTimeUs);
if (mSeeking) {
options.setSeekTo(mSeekTimeUs);
refreshSeekTime = true;
if (mInputBuffer) {
mInputBuffer->release();
mInputBuffer = nullptr;
}
mSeeking = false;
}
}
if (!mInputBuffer) {
status_t err;
err = mSource->read(&mInputBuffer, &options);
@ -543,9 +535,6 @@ size_t AudioOffloadPlayer::FillBuffer(void* aData, size_t aSize)
android::Mutex::Autolock autoLock(mLock);
if (err != OK) {
if (mSeekTarget.IsValid()) {
mSeekTarget.Reset();
}
AUDIO_OFFLOAD_LOG(PR_LOG_ERROR, ("Error while reading media source %d "
"Ok to receive EOS error at end", err));
if (!mReachedEOS) {
@ -575,24 +564,41 @@ size_t AudioOffloadPlayer::FillBuffer(void* aData, size_t aSize)
kKeyTime, &mPositionTimeMediaUs));
}
if (mSeekTarget.IsValid() && seekTimeUs == mSeekTarget.mTime) {
mSeekTarget.Reset();
if (!mSeekPromise.IsEmpty()) {
if (refreshSeekTime) {
if (mDispatchSeekEvents && !mSeekDuringPause) {
mDispatchSeekEvents = false;
AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("FillBuffer posting SEEK_COMPLETE"));
MediaDecoder::SeekResolveValue val(mReachedEOS, mSeekTarget.mEventVisibility);
mSeekPromise.Resolve(val, __func__);
nsCOMPtr<nsIRunnable> nsEvent =
NS_NewRunnableMethodWithArg<MediaDecoderEventVisibility>(
mObserver,
&MediaDecoder::SimulateSeekResolvedForAudioOffload,
MediaDecoderEventVisibility::Observable);
NS_DispatchToMainThread(nsEvent, NS_DISPATCH_NORMAL);
} else if (mSeekDuringPause) {
// Callback is already called for seek during pause. Just reset the
// flag
AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("Not posting seek complete as its"
" already faked"));
mSeekDuringPause = false;
}
NotifyPositionChanged();
// need to adjust the mStartPosUs for offload decoding since parser
// might not be able to get the exact seek time requested.
mStartPosUs = mPositionTimeMediaUs;
AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("Adjust seek time to: %.2f",
mStartPosUs / 1E6));
// clear seek time with mLock locked and once we have valid
// mPositionTimeMediaUs
// before clearing mSeekTimeUs check if a new seek request has been
// received while we were reading from the source with mLock released.
if (!mSeeking) {
mSeekTimeUs = 0;
}
} else if (mSeekTarget.IsValid()) {
AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("seek is updated during unlocking mLock"));
}
NotifyPositionChanged();
// need to adjust the mStartPosUs for offload decoding since parser
// might not be able to get the exact seek time requested.
mStartPosUs = mPositionTimeMediaUs;
AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("Adjust seek time to: %.2f",
mStartPosUs / 1E6));
}
if (mInputBuffer->range_length() == 0) {

View File

@ -78,27 +78,25 @@ public:
~AudioOffloadPlayer();
// Caller retains ownership of "aSource".
virtual void SetSource(const android::sp<MediaSource> &aSource) override;
void SetSource(const android::sp<MediaSource> &aSource);
// Start the source if it's not already started and open the AudioSink to
// create an offloaded audio track
virtual status_t Start(bool aSourceAlreadyStarted = false) override;
status_t Start(bool aSourceAlreadyStarted = false);
virtual status_t ChangeState(MediaDecoder::PlayState aState) override;
virtual void SetVolume(double aVolume) override;
virtual double GetMediaTimeSecs() override;
double GetMediaTimeSecs();
// To update progress bar when the element is visible
virtual void SetElementVisibility(bool aIsVisible) override;;
void SetElementVisibility(bool aIsVisible);
status_t ChangeState(MediaDecoder::PlayState aState);
void SetVolume(double aVolume);
// Update ready state based on current play state. Not checking data
// availability since offloading is currently done only when whole compressed
// data is available
virtual MediaDecoderOwner::NextFrameStatus GetNextFrameStatus() override;
virtual nsRefPtr<MediaDecoder::SeekPromise> Seek(SeekTarget aTarget) override;
MediaDecoderOwner::NextFrameStatus GetNextFrameStatus();
void TimeUpdate();
@ -114,12 +112,28 @@ private:
// Used only in main thread
bool mPlaying;
// Set when playstate is seeking and reset when FillBUffer() acknowledged
// seeking by seeking audio source. Used in main thread and offload
// callback thread, protected by Mutex mLock
bool mSeeking;
// Once playback reached end of stream (last ~100ms), position provided by DSP
// may be reset/corrupted. This bool is used to avoid that.
// Used in main thread and offload callback thread, protected by Mutex
// mLock
bool mReachedEOS;
// Set when there is a seek request during pause.
// Used in main thread and offload callback thread, protected by Mutex
// mLock
bool mSeekDuringPause;
// Seek can be triggered internally or by MediaDecoder. This bool is to
// to track seek triggered by MediaDecoder so that we can send back
// SeekingStarted and SeekingStopped events.
// Used in main thread and offload callback thread, protected by Mutex mLock
bool mDispatchSeekEvents;
// Set when the HTML Audio Element is visible to the user.
// Used only in main thread
bool mIsElementVisible;
@ -141,15 +155,10 @@ private:
// mLock
int64_t mStartPosUs;
// The target of current seek when there is a request to seek
// Given seek time when there is a request to seek
// Used in main thread and offload callback thread, protected by Mutex
// mLock
SeekTarget mSeekTarget;
// MediaPromise of current seek.
// Used in main thread and offload callback thread, protected by Mutex
// mLock
MediaPromiseHolder<MediaDecoder::SeekPromise> mSeekPromise;
int64_t mSeekTimeUs;
// Positions obtained from offlaoded tracks (DSP)
// Used in main thread and offload callback thread, protected by Mutex
@ -212,15 +221,15 @@ private:
bool IsSeeking();
// Set mSeekTarget to the given position and restart the sink. Actual seek
// happens in FillBuffer(). If mSeekPromise is not empty, send
// Set mSeekTime to the given position and restart the sink. Actual seek
// happens in FillBuffer(). If aDispatchSeekEvents is true, send
// SeekingStarted event always and SeekingStopped event when the play state is
// paused to MediaDecoder.
// When decoding and playing happens separately, if there is a seek during
// pause, we can decode and keep data ready.
// In case of offload player, no way to seek during pause. So just fake that
// seek is done.
status_t DoSeek();
status_t SeekTo(int64_t aTimeUs, bool aDispatchSeekEvents = false);
// Start/Resume the audio sink so that callback will start being called to get
// compressed data

View File

@ -66,8 +66,6 @@ public:
{
return MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE;
}
virtual nsRefPtr<MediaDecoder::SeekPromise> Seek(SeekTarget aTarget) = 0;
};
} // namespace mozilla

View File

@ -126,9 +126,8 @@ MediaOmxCommonDecoder::ResumeStateMachine()
mAudioOffloadPlayer = nullptr;
int64_t timeUsecs = 0;
SecondsToUsecs(mCurrentTime, timeUsecs);
mRequestedSeekTarget = SeekTarget(timeUsecs,
SeekTarget::Accurate,
MediaDecoderEventVisibility::Suppressed);
mRequestedSeekTarget = SeekTarget(timeUsecs, SeekTarget::Accurate);
mNextState = mPlayState;
ChangeState(PLAY_STATE_LOADING);
// exit dormant state
@ -194,25 +193,10 @@ MediaOmxCommonDecoder::ChangeState(PlayState aState)
// in between
MediaDecoder::ChangeState(aState);
if (!mAudioOffloadPlayer) {
return;
}
status_t err = mAudioOffloadPlayer->ChangeState(aState);
if (err != OK) {
ResumeStateMachine();
return;
}
switch (mPlayState) {
case PLAY_STATE_SEEKING:
mSeekRequest.Begin(mAudioOffloadPlayer->Seek(mRequestedSeekTarget)
->RefableThen(NS_GetCurrentThread(), __func__, static_cast<MediaDecoder*>(this),
&MediaDecoder::OnSeekResolved, &MediaDecoder::OnSeekRejected));
mRequestedSeekTarget.Reset();
break;
default: {
break;
if (mAudioOffloadPlayer) {
status_t err = mAudioOffloadPlayer->ChangeState(aState);
if (err != OK) {
ResumeStateMachine();
}
}
}