Bug 1272267 - adjust the seek target in the MediaFormatReader; r=jya
MozReview-Commit-ID: H297znLMtOC
--- a/dom/media/MediaFormatReader.cpp
+++ b/dom/media/MediaFormatReader.cpp
@@ -924,16 +924,21 @@ MediaFormatReader::HandleDemuxedSamples(
NotifyError(aTrack);
return;
}
if (!EnsureDecoderInitialized(aTrack)) {
return;
}
+ if (!ForceZeroStartTime() && decoder.mFirstDemuxedSampleTime.isNothing()) {
+ decoder.mFirstDemuxedSampleTime.emplace(
+ media::TimeUnit::FromMicroseconds(decoder.mQueuedSamples[0]->mTime));
+ }
+
LOGV("Giving %s input to decoder", TrackTypeToStr(aTrack));
// Decode all our demuxed frames.
bool samplesPending = false;
while (decoder.mQueuedSamples.Length()) {
RefPtr<MediaRawData> sample = decoder.mQueuedSamples[0];
RefPtr<SharedTrackInfo> info = sample->mTrackInfo;
@@ -1506,27 +1511,59 @@ MediaFormatReader::Seek(SeekTarget aTarg
LOG("Seek() END (Unseekable)");
return SeekPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
}
if (mShutdown) {
return SeekPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
}
- mOriginalSeekTarget = aTarget;
- mFallbackSeekTime = mPendingSeekTime = Some(aTarget.GetTime());
+ SetSeekTarget(Move(aTarget));
RefPtr<SeekPromise> p = mSeekPromise.Ensure(__func__);
ScheduleSeek();
return p;
}
void
+MediaFormatReader::SetSeekTarget(const SeekTarget& aTarget)
+{
+ MOZ_ASSERT(OnTaskQueue());
+
+ SeekTarget target = aTarget;
+
+ // Transform the seek target time to the demuxer timeline.
+ if (!ForceZeroStartTime()) {
+ target.SetTime(aTarget.GetTime() - TimeUnit::FromMicroseconds(StartTime())
+ + DemuxStartTime());
+ }
+
+ mOriginalSeekTarget = target;
+ mFallbackSeekTime = mPendingSeekTime = Some(target.GetTime());
+}
+
+TimeUnit
+MediaFormatReader::DemuxStartTime()
+{
+ MOZ_ASSERT(OnTaskQueue());
+ MOZ_ASSERT(!ForceZeroStartTime());
+ MOZ_ASSERT((!HasAudio() || mAudio.mFirstDemuxedSampleTime.isSome()) &&
+ (!HasVideo() || mVideo.mFirstDemuxedSampleTime.isSome()));
+
+ return std::min(HasAudio()
+ ? mAudio.mFirstDemuxedSampleTime.ref()
+ : TimeUnit::FromInfinity(),
+ HasVideo()
+ ? mVideo.mFirstDemuxedSampleTime.ref()
+ : TimeUnit::FromInfinity());
+}
+
+void
MediaFormatReader::ScheduleSeek()
{
if (mSeekScheduled) {
return;
}
mSeekScheduled = true;
OwnerThread()->Dispatch(NewRunnableMethod(this, &MediaFormatReader::AttemptSeek));
}
--- a/dom/media/MediaFormatReader.h
+++ b/dom/media/MediaFormatReader.h
@@ -396,16 +396,17 @@ private:
// This value is updated after a frame is successfully decoded.
Atomic<bool> mIsHardwareAccelerated;
// Sample format monitoring.
uint32_t mLastStreamSourceID;
Maybe<uint32_t> mNextStreamSourceID;
media::TimeIntervals mTimeRanges;
Maybe<media::TimeUnit> mLastTimeRangesEnd;
RefPtr<SharedTrackInfo> mInfo;
+ Maybe<media::TimeUnit> mFirstDemuxedSampleTime;
};
class DecoderDataWithPromise : public DecoderData {
public:
DecoderDataWithPromise(MediaFormatReader* aOwner,
MediaData::Type aType,
uint32_t aDecodeAhead)
: DecoderData(aOwner, aType, aDecodeAhead)
@@ -501,16 +502,18 @@ private:
// Set to true if any of our track buffers may be blocking.
bool mTrackDemuxersMayBlock;
// Set the demuxed-only flag.
Atomic<bool> mDemuxOnly;
// Seeking objects.
+ void SetSeekTarget(const SeekTarget& aTarget);
+ media::TimeUnit DemuxStartTime();
bool IsSeeking() const { return mPendingSeekTime.isSome(); }
bool IsVideoSeeking() const
{
return IsSeeking() && mOriginalSeekTarget.IsVideoOnly();
}
void ScheduleSeek();
void AttemptSeek();
void OnSeekFailed(TrackType aTrack, DemuxerFailureReason aFailure);