Bug 654787 - part5: Add the looping-offset time to audio data; r=jwwang
MozReview-Commit-ID: LUNF9x6foEA
--- a/dom/media/ReaderProxy.cpp
+++ b/dom/media/ReaderProxy.cpp
@@ -53,39 +53,47 @@ ReaderProxy::ReadMetadata()
&ReaderProxy::OnMetadataNotRead);
}
RefPtr<ReaderProxy::AudioDataPromise>
ReaderProxy::OnAudioDataRequestCompleted(RefPtr<AudioData> aAudio)
{
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
- int64_t startTime = StartTime().ToMicroseconds();
- aAudio->AdjustForStartTime(startTime);
+ // Subtract the start time and add the looping-offset time.
+ int64_t offset =
+ StartTime().ToMicroseconds() - mLoopingOffset.ToMicroseconds();
+ aAudio->AdjustForStartTime(offset);
+ mLastAudioEndTime = aAudio->mTime;
return AudioDataPromise::CreateAndResolve(aAudio.forget(), __func__);
}
RefPtr<ReaderProxy::AudioDataPromise>
ReaderProxy::OnAudioDataRequestFailed(const MediaResult& aError)
{
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
if (mSeamlessLoopingBlocked || !mSeamlessLoopingEnabled ||
aError.Code() != NS_ERROR_DOM_MEDIA_END_OF_STREAM) {
return AudioDataPromise::CreateAndReject(aError, __func__);
}
+ // The data time in the audio queue is assumed to be increased linearly,
+ // so we need to add the last ending time as the offset to correct the
+ // audio data time in the next round when seamless looping is enabled.
+ mLoopingOffset = mLastAudioEndTime;
+
// For seamless looping, the demuxer is sought to the beginning and then
// keep requesting decoded data in advance, upon receiving EOS.
// The MDSM will not be aware of the EOS and keep receiving decoded data
// as usual while looping is on.
RefPtr<ReaderProxy> self = this;
RefPtr<MediaFormatReader> reader = mReader;
ResetDecode(TrackInfo::kAudioTrack);
- return Seek(SeekTarget(media::TimeUnit::Zero(), SeekTarget::Accurate))
+ return SeekInternal(SeekTarget(media::TimeUnit::Zero(), SeekTarget::Accurate))
->Then(mReader->OwnerThread(),
__func__,
[reader]() { return reader->RequestAudioData(); },
[](const SeekRejectValue& aReject) {
return AudioDataPromise::CreateAndReject(aReject.mError, __func__);
})
->Then(mOwnerThread,
__func__,
@@ -144,16 +152,26 @@ ReaderProxy::RequestVideoData(const medi
});
}
RefPtr<ReaderProxy::SeekPromise>
ReaderProxy::Seek(const SeekTarget& aTarget)
{
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
mSeamlessLoopingBlocked = true;
+ // Reset the members for seamless looping if the seek is triggered outside.
+ mLoopingOffset = media::TimeUnit::Zero();
+ mLastAudioEndTime = media::TimeUnit::Zero();
+ return SeekInternal(aTarget);
+}
+
+RefPtr<ReaderProxy::SeekPromise>
+ReaderProxy::SeekInternal(const SeekTarget& aTarget)
+{
+ MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
SeekTarget adjustedTarget = aTarget;
adjustedTarget.SetTime(adjustedTarget.GetTime() + StartTime());
return InvokeAsync(mReader->OwnerThread(),
mReader.get(),
__func__,
&MediaFormatReader::Seek,
Move(adjustedTarget));
}
--- a/dom/media/ReaderProxy.h
+++ b/dom/media/ReaderProxy.h
@@ -86,16 +86,17 @@ public:
void SetSeamlessLoopingEnabled(bool aEnabled);
private:
~ReaderProxy();
RefPtr<MetadataPromise> OnMetadataRead(MetadataHolder&& aMetadata);
RefPtr<MetadataPromise> OnMetadataNotRead(const MediaResult& aError);
void UpdateDuration();
+ RefPtr<SeekPromise> SeekInternal(const SeekTarget& aTarget);
RefPtr<ReaderProxy::AudioDataPromise> OnAudioDataRequestCompleted(
RefPtr<AudioData> aAudio);
RefPtr<ReaderProxy::AudioDataPromise> OnAudioDataRequestFailed(
const MediaResult& aError);
const RefPtr<AbstractThread> mOwnerThread;
const RefPtr<MediaFormatReader> mReader;
@@ -104,16 +105,21 @@ private:
Maybe<media::TimeUnit> mStartTime;
// State-watching manager.
WatchManager<ReaderProxy> mWatchManager;
// Duration, mirrored from the state machine task queue.
Mirror<media::NullableTimeUnit> mDuration;
+ // The total duration of audio looping in previous rounds.
+ media::TimeUnit mLoopingOffset = media::TimeUnit::Zero();
+ // To keep tracking the latest time of decoded audio data.
+ media::TimeUnit mLastAudioEndTime = media::TimeUnit::Zero();
+
// To prevent seamless looping while seeking.
bool mSeamlessLoopingBlocked;
// Indicates whether we should loop the media.
bool mSeamlessLoopingEnabled;
};
} // namespace mozilla