Bug 1508434 - p1: Support explicitly resetting seek threshold. r=jya

Usually the threshold is reset internally in MediaDataDecoder subclasses
that support the hint in their Flush() implementations so the value
will start fresh after seeking completed. But sometimes when there are
consecutive seek requests, MediaFormatReader::DecoderData::Flush() could
return early because DecoderData::mFlushed stays true when there is no
sample demuxed yet, and the threshold will not be cleared. Also, in
MediaFormatReader::SetVideoDecodeThreshold() we decide not to set the
hint when the seek target is close to EOS by checking the existence of
the next keyframe, and that could fail when there are gaps between MSE
buffered ranges. To make sure the hint is never out of date, we should
clear it rather than leaving it untouched.

Differential Revision: https://phabricator.services.mozilla.com/D15227

--HG--
extra : moz-landing-system : lando
This commit is contained in:
John Lin 2019-01-11 17:07:49 +00:00
Родитель 6b77f9e5ee
Коммит 2a6faa6bf8
11 изменённых файлов: 32 добавлений и 15 удалений

Просмотреть файл

@ -2890,10 +2890,9 @@ void MediaFormatReader::SetVideoDecodeThreshold() {
// If the key frame is invalid/infinite, it means the target position is
// closing to end of stream. We don't want to skip any frame at this point.
if (!keyframe.IsValid() || keyframe.IsInfinite()) {
return;
}
threshold = mOriginalSeekTarget.GetTime();
threshold = keyframe.IsValid() && !keyframe.IsInfinite()
? mOriginalSeekTarget.GetTime()
: TimeUnit::Invalid();
} else {
return;
}

Просмотреть файл

@ -37,7 +37,7 @@ parent:
async Flush();
async Drain();
async Shutdown();
// To clear the threshold, call with INT64_MIN.
async SetSeekThreshold(int64_t time);
async __delete__();

Просмотреть файл

@ -37,7 +37,7 @@ parent:
async Flush();
async Drain();
async Shutdown();
// To clear the threshold, call with INT64_MIN.
async SetSeekThreshold(int64_t time);
async __delete__();

Просмотреть файл

@ -289,7 +289,7 @@ nsCString RemoteVideoDecoderChild::GetDescriptionName() const {
void RemoteVideoDecoderChild::SetSeekThreshold(const media::TimeUnit& aTime) {
AssertOnManagerThread();
if (mCanSend) {
SendSetSeekThreshold(aTime.ToMicroseconds());
SendSetSeekThreshold(aTime.IsValid() ? aTime.ToMicroseconds() : INT64_MIN);
}
}

Просмотреть файл

@ -204,7 +204,9 @@ mozilla::ipc::IPCResult RemoteVideoDecoderParent::RecvSetSeekThreshold(
const int64_t& aTime) {
MOZ_ASSERT(!mDestroyed);
MOZ_ASSERT(OnManagerThread());
mDecoder->SetSeekThreshold(TimeUnit::FromMicroseconds(aTime));
mDecoder->SetSeekThreshold(aTime == INT64_MIN
? TimeUnit::Invalid()
: TimeUnit::FromMicroseconds(aTime));
return IPC_OK();
}

Просмотреть файл

@ -304,7 +304,7 @@ nsCString VideoDecoderChild::GetDescriptionName() const {
void VideoDecoderChild::SetSeekThreshold(const media::TimeUnit& aTime) {
AssertOnManagerThread();
if (mCanSend) {
SendSetSeekThreshold(aTime.ToMicroseconds());
SendSetSeekThreshold(aTime.IsValid() ? aTime.ToMicroseconds() : INT64_MIN);
}
}

Просмотреть файл

@ -252,7 +252,9 @@ mozilla::ipc::IPCResult VideoDecoderParent::RecvSetSeekThreshold(
const int64_t& aTime) {
MOZ_ASSERT(!mDestroyed);
MOZ_ASSERT(OnManagerThread());
mDecoder->SetSeekThreshold(TimeUnit::FromMicroseconds(aTime));
mDecoder->SetSeekThreshold(aTime == INT64_MIN
? TimeUnit::Invalid()
: TimeUnit::FromMicroseconds(aTime));
return IPC_OK();
}

Просмотреть файл

@ -319,7 +319,8 @@ class MediaDataDecoder : public DecoderDoctorLifeLogger<MediaDataDecoder> {
// Set a hint of seek target time to decoder. Decoder will drop any decoded
// data which pts is smaller than this value. This threshold needs to be clear
// after reset decoder.
// after reset decoder. To clear it explicitly, call this method with
// TimeUnit::Invalid().
// Decoder may not honor this value. However, it'd be better that
// video decoder implements this API to improve seek performance.
// Note: it should be called before Input() or after Flush().

Просмотреть файл

@ -221,8 +221,13 @@ class RemoteVideoDecoder : public RemoteDataDecoder {
void SetSeekThreshold(const TimeUnit& aTime) override {
RefPtr<RemoteVideoDecoder> self = this;
nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableFunction(
"RemoteVideoDecoder::SetSeekThreshold",
[self, aTime]() { self->mSeekTarget = Some(aTime); });
"RemoteVideoDecoder::SetSeekThreshold", [self, aTime]() {
if (aTime.IsValid()) {
self->mSeekTarget = Some(aTime);
} else {
self->mSeekTarget.reset();
}
});
nsresult rv = mTaskQueue->Dispatch(runnable.forget());
MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
Unused << rv;

Просмотреть файл

@ -246,7 +246,11 @@ AppleVTDecoder::AppleFrameRef* AppleVTDecoder::CreateAppleFrameRef(
void AppleVTDecoder::SetSeekThreshold(const media::TimeUnit& aTime) {
LOG("SetSeekThreshold %lld", aTime.ToMicroseconds());
mSeekTargetThreshold = Some(aTime);
if (aTime.IsValid()) {
mSeekTargetThreshold = Some(aTime);
} else {
mSeekTargetThreshold.reset();
}
}
//

Просмотреть файл

@ -58,7 +58,11 @@ class MFTManager {
virtual nsCString GetDescriptionName() const = 0;
virtual void SetSeekThreshold(const media::TimeUnit& aTime) {
mSeekTargetThreshold = Some(aTime);
if (aTime.IsValid()) {
mSeekTargetThreshold = Some(aTime);
} else {
mSeekTargetThreshold.reset();
}
}
virtual MediaDataDecoder::ConversionRequired NeedsConversion() const {