Bug 1264171 - seperate the fast seek's logic out from accurate seek's logic; r?jwwang
MozReview-Commit-ID: DgM0CuCX58s
new file mode 100644
--- /dev/null
+++ b/dom/media/FastSeekTask.cpp
@@ -0,0 +1,151 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "FastSeekTask.h"
+
+namespace mozilla {
+
+extern LazyLogModule gMediaSampleLog;
+
+// avoid redefined macro in unified build
+#undef LOG
+
+#define LOG(m, l, x, ...) \
+ MOZ_LOG(m, l, ("[SeekTask] Decoder=%p " x, mDecoderID, ##__VA_ARGS__))
+#define SAMPLE_LOG(x, ...) \
+ LOG(gMediaSampleLog, LogLevel::Debug, x, ##__VA_ARGS__)
+
+namespace media {
+
+FastSeekTask::FastSeekTask(const void* aDecoderID,
+ AbstractThread* aThread,
+ MediaDecoderReader* aReader,
+ MediaDecoderReaderWrapper* aReaderWrapper,
+ SeekJob&& aSeekJob,
+ const MediaInfo& aInfo,
+ const media::TimeUnit& aDuration,
+ int64_t aCurrentMediaTime)
+ : SeekTask(aDecoderID, aThread, aReader, aReaderWrapper, Move(aSeekJob),
+ aInfo, aDuration, aCurrentMediaTime)
+{
+}
+
+FastSeekTask::~FastSeekTask()
+{
+}
+
+void
+FastSeekTask::OnAudioDecoded(MediaData* aAudioSample)
+{
+ AssertOwnerThread();
+ RefPtr<MediaData> audio(aAudioSample);
+ MOZ_ASSERT(audio);
+ mAudioDataRequest.Complete();
+
+ // The MDSM::mDecodedAudioEndTime will be updated once the whole SeekTask is
+ // resolved.
+
+ SAMPLE_LOG("OnAudioDecoded [%lld,%lld] disc=%d",
+ (audio ? audio->mTime : -1),
+ (audio ? audio->GetEndTime() : -1),
+ (audio ? audio->mDiscontinuity : 0));
+
+ if (!Exists()) {
+ // We've received a sample from a previous decode. Discard it.
+ return;
+ }
+
+ if (audio->mDiscontinuity) {
+ mDropAudioUntilNextDiscontinuity = false;
+ }
+
+ if (!mDropAudioUntilNextDiscontinuity) {
+ // We must be after the discontinuity; we're receiving samples
+ // at or after the seek target.
+ if (mSeekJob.mTarget.IsFast() &&
+ mSeekJob.mTarget.GetTime().ToMicroseconds() > mCurrentTimeBeforeSeek &&
+ audio->mTime < mCurrentTimeBeforeSeek) {
+ // We are doing a fastSeek, but we ended up *before* the previous
+ // playback position. This is surprising UX, so switch to an accurate
+ // seek and decode to the seek target. This is not conformant to the
+ // spec, fastSeek should always be fast, but until we get the time to
+ // change all Readers to seek to the keyframe after the currentTime
+ // in this case, we'll just decode forward. Bug 1026330.
+ mSeekJob.mTarget.SetType(SeekTarget::Accurate);
+ }
+ if (mSeekJob.mTarget.IsFast()) {
+ // Non-precise seek; we can stop the seek at the first sample.
+ mSeekedAudioData = audio;
+ } else {
+ // We're doing an accurate seek. We must discard
+ // MediaData up to the one containing exact seek target.
+ if (NS_FAILED(DropAudioUpToSeekTarget(audio.get()))) {
+ RejectIfExist(__func__);
+ return;
+ }
+ }
+ }
+ CheckIfSeekComplete();
+}
+
+void
+FastSeekTask::OnVideoDecoded(MediaData* aVideoSample)
+{
+ AssertOwnerThread();
+ RefPtr<MediaData> video(aVideoSample);
+ MOZ_ASSERT(video);
+ mVideoDataRequest.Complete();
+
+ // The MDSM::mDecodedVideoEndTime will be updated once the whole SeekTask is
+ // resolved.
+
+ SAMPLE_LOG("OnVideoDecoded [%lld,%lld] disc=%d",
+ (video ? video->mTime : -1),
+ (video ? video->GetEndTime() : -1),
+ (video ? video->mDiscontinuity : 0));
+
+ if (!Exists()) {
+ // We've received a sample from a previous decode. Discard it.
+ return;
+ }
+
+ if (mDropVideoUntilNextDiscontinuity) {
+ if (video->mDiscontinuity) {
+ mDropVideoUntilNextDiscontinuity = false;
+ }
+ }
+
+ if (!mDropVideoUntilNextDiscontinuity) {
+ // We must be after the discontinuity; we're receiving samples
+ // at or after the seek target.
+ if (mSeekJob.mTarget.IsFast() &&
+ mSeekJob.mTarget.GetTime().ToMicroseconds() > mCurrentTimeBeforeSeek &&
+ video->mTime < mCurrentTimeBeforeSeek) {
+ // We are doing a fastSeek, but we ended up *before* the previous
+ // playback position. This is surprising UX, so switch to an accurate
+ // seek and decode to the seek target. This is not conformant to the
+ // spec, fastSeek should always be fast, but until we get the time to
+ // change all Readers to seek to the keyframe after the currentTime
+ // in this case, we'll just decode forward. Bug 1026330.
+ mSeekJob.mTarget.SetType(SeekTarget::Accurate);
+ }
+ if (mSeekJob.mTarget.IsFast()) {
+ // Non-precise seek. We can stop the seek at the first sample.
+ mSeekedVideoData = video;
+ } else {
+ // We're doing an accurate seek. We still need to discard
+ // MediaData up to the one containing exact seek target.
+ if (NS_FAILED(DropVideoUpToSeekTarget(video.get()))) {
+ RejectIfExist(__func__);
+ return;
+ }
+ }
+ }
+ CheckIfSeekComplete();
+}
+
+} // namespace media
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/media/FastSeekTask.h
@@ -0,0 +1,38 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef FAST_SEEK_TASK_H
+#define FAST_SEEK_TASK_H
+
+#include "SeekTask.h"
+
+namespace mozilla {
+namespace media {
+
+class FastSeekTask : SeekTask{
+ friend class SeekTask;
+
+protected:
+ FastSeekTask(const void* aDecoderID,
+ AbstractThread* aThread,
+ MediaDecoderReader* aReader,
+ MediaDecoderReaderWrapper* aReaderWrapper,
+ SeekJob&& aSeekJob,
+ const MediaInfo& aInfo,
+ const media::TimeUnit& aDuration,
+ int64_t aCurrentMediaTime);
+
+ virtual ~FastSeekTask();
+
+ virtual void OnAudioDecoded(MediaData* aAudioSample) override;
+
+ virtual void OnVideoDecoded(MediaData* aVideoSample) override;
+};
+
+} // namespace media
+} // namespace mozilla
+
+#endif /* FAST_SEEK_TASK_H */
--- a/dom/media/SeekTask.cpp
+++ b/dom/media/SeekTask.cpp
@@ -1,15 +1,16 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "SeekTask.h"
+#include "FastSeekTask.h"
#include "MediaDecoderReaderWrapper.h"
#include "mozilla/AbstractThread.h"
#include "mozilla/Assertions.h"
#include "nsPrintfCString.h"
namespace mozilla {
extern LazyLogModule gMediaDecoderLog;
@@ -42,19 +43,24 @@ SeekTask::CreateSeekTask(const void* aDe
AbstractThread* aThread,
MediaDecoderReader* aReader,
MediaDecoderReaderWrapper* aReaderWrapper,
SeekJob&& aSeekJob,
const MediaInfo& aInfo,
const media::TimeUnit& aDuration,
int64_t aCurrentMediaTime)
{
- RefPtr<SeekTask> task(new SeekTask(aDecoderID, aThread, aReader,
- aReaderWrapper, Move(aSeekJob), aInfo,
- aDuration, aCurrentMediaTime));
+ RefPtr<SeekTask> task;
+ if (aSeekJob.mTarget.IsAccurate()) {
+ task = new SeekTask(aDecoderID, aThread, aReader, aReaderWrapper,
+ Move(aSeekJob), aInfo, aDuration, aCurrentMediaTime);
+ } else if (aSeekJob.mTarget.IsFast()) {
+ task = new FastSeekTask(aDecoderID, aThread, aReader, aReaderWrapper,
+ Move(aSeekJob), aInfo, aDuration, aCurrentMediaTime);
+ }
return task.forget();
}
SeekTask::SeekTask(const void* aDecoderID,
AbstractThread* aThread,
MediaDecoderReader* aReader,
MediaDecoderReaderWrapper* aReaderWrapper,
@@ -526,39 +532,21 @@ SeekTask::OnAudioDecoded(MediaData* aAud
return;
}
if (audio->mDiscontinuity) {
mDropAudioUntilNextDiscontinuity = false;
}
if (!mDropAudioUntilNextDiscontinuity) {
- // We must be after the discontinuity; we're receiving samples
- // at or after the seek target.
- if (mSeekJob.mTarget.IsFast() &&
- mSeekJob.mTarget.GetTime().ToMicroseconds() > mCurrentTimeBeforeSeek &&
- audio->mTime < mCurrentTimeBeforeSeek) {
- // We are doing a fastSeek, but we ended up *before* the previous
- // playback position. This is surprising UX, so switch to an accurate
- // seek and decode to the seek target. This is not conformant to the
- // spec, fastSeek should always be fast, but until we get the time to
- // change all Readers to seek to the keyframe after the currentTime
- // in this case, we'll just decode forward. Bug 1026330.
- mSeekJob.mTarget.SetType(SeekTarget::Accurate);
- }
- if (mSeekJob.mTarget.IsFast()) {
- // Non-precise seek; we can stop the seek at the first sample.
- mSeekedAudioData = audio;
- } else {
- // We're doing an accurate seek. We must discard
- // MediaData up to the one containing exact seek target.
- if (NS_FAILED(DropAudioUpToSeekTarget(audio.get()))) {
- RejectIfExist(__func__);
- return;
- }
+ // We're doing an accurate seek. We must discard
+ // MediaData up to the one containing exact seek target.
+ if (NS_FAILED(DropAudioUpToSeekTarget(audio.get()))) {
+ RejectIfExist(__func__);
+ return;
}
}
CheckIfSeekComplete();
}
void
SeekTask::OnAudioNotDecoded(MediaDecoderReader::NotDecodedReason aReason)
{
@@ -632,39 +620,21 @@ SeekTask::OnVideoDecoded(MediaData* aVid
if (mDropVideoUntilNextDiscontinuity) {
if (video->mDiscontinuity) {
mDropVideoUntilNextDiscontinuity = false;
}
}
if (!mDropVideoUntilNextDiscontinuity) {
- // We must be after the discontinuity; we're receiving samples
- // at or after the seek target.
- if (mSeekJob.mTarget.IsFast() &&
- mSeekJob.mTarget.GetTime().ToMicroseconds() > mCurrentTimeBeforeSeek &&
- video->mTime < mCurrentTimeBeforeSeek) {
- // We are doing a fastSeek, but we ended up *before* the previous
- // playback position. This is surprising UX, so switch to an accurate
- // seek and decode to the seek target. This is not conformant to the
- // spec, fastSeek should always be fast, but until we get the time to
- // change all Readers to seek to the keyframe after the currentTime
- // in this case, we'll just decode forward. Bug 1026330.
- mSeekJob.mTarget.SetType(SeekTarget::Accurate);
- }
- if (mSeekJob.mTarget.IsFast()) {
- // Non-precise seek. We can stop the seek at the first sample.
- mSeekedVideoData = video;
- } else {
- // We're doing an accurate seek. We still need to discard
- // MediaData up to the one containing exact seek target.
- if (NS_FAILED(DropVideoUpToSeekTarget(video.get()))) {
- RejectIfExist(__func__);
- return;
- }
+ // We're doing an accurate seek. We still need to discard
+ // MediaData up to the one containing exact seek target.
+ if (NS_FAILED(DropVideoUpToSeekTarget(video.get()))) {
+ RejectIfExist(__func__);
+ return;
}
}
CheckIfSeekComplete();
}
void
SeekTask::OnVideoNotDecoded(MediaDecoderReader::NotDecodedReason aReason)
{
--- a/dom/media/moz.build
+++ b/dom/media/moz.build
@@ -96,16 +96,17 @@ EXPORTS += [
'AudioSegment.h',
'AudioStream.h',
'Benchmark.h',
'BufferMediaResource.h',
'CubebUtils.h',
'DecoderTraits.h',
'DOMMediaStream.h',
'EncodedBufferCache.h',
+ 'FastSeekTask.h',
'FileBlockCache.h',
'FlushableTaskQueue.h',
'FrameStatistics.h',
'Intervals.h',
'Latency.h',
'MediaCache.h',
'MediaData.h',
'MediaDataDemuxer.h',
@@ -205,16 +206,17 @@ UNIFIED_SOURCES += [
'AudioStreamTrack.cpp',
'AudioTrack.cpp',
'AudioTrackList.cpp',
'Benchmark.cpp',
'CanvasCaptureMediaStream.cpp',
'CubebUtils.cpp',
'DOMMediaStream.cpp',
'EncodedBufferCache.cpp',
+ 'FastSeekTask.cpp',
'FileBlockCache.cpp',
'FlushableTaskQueue.cpp',
'GetUserMediaRequest.cpp',
'GraphDriver.cpp',
'Latency.cpp',
'MediaCache.cpp',
'MediaData.cpp',
'MediaDecoder.cpp',