Bug 1595603 - part2 : delay seeking task when media is inactive r=bryce

When media element is inactive, asking MDSM to seek is actually useless, because all the data we decode won't be showed to user. In addition, we have to store extra pending events for `seeking` and `seeked`, which might result in memory overflow if the inactive page is calling `seek()` all the time.

Therfore, we should delay all seeking tasks while media is inactive, and perform the latest seeking task when media becomes active.

Differential Revision: https://phabricator.services.mozilla.com/D58918
This commit is contained in:
alwu
2020-01-09 17:10:08 +00:00
parent 0e0b0572c4
commit d3d8a3d56e
4 changed files with 36 additions and 2 deletions

View File

@@ -6526,6 +6526,7 @@ void HTMLMediaElement::SuspendOrResumeElement(bool aSuspendElement) {
if (mDecoder) {
mDecoder->Pause();
mDecoder->Suspend();
mDecoder->SetDelaySeekMode(true);
}
mEventDeliveryPaused = true;
// We won't want to resume media element from the bfcache.
@@ -6540,6 +6541,7 @@ void HTMLMediaElement::SuspendOrResumeElement(bool aSuspendElement) {
if (!mPaused && !mDecoder->IsEnded()) {
mDecoder->Play();
}
mDecoder->SetDelaySeekMode(false);
}
if (mEventDeliveryPaused) {
mEventDeliveryPaused = false;

View File

@@ -630,7 +630,6 @@ void MediaDecoder::Seek(double aTime, SeekTarget::Type aSeekType) {
auto time = TimeUnit::FromSeconds(aTime);
mLogicalPosition = aTime;
mLogicallySeeking = true;
SeekTarget target = SeekTarget(time, aSeekType);
CallSeek(target);
@@ -641,6 +640,20 @@ void MediaDecoder::Seek(double aTime, SeekTarget::Type aSeekType) {
}
}
void MediaDecoder::SetDelaySeekMode(bool aShouldDelaySeek) {
MOZ_ASSERT(NS_IsMainThread());
LOG("SetDelaySeekMode, shouldDelaySeek=%d", aShouldDelaySeek);
if (mShouldDelaySeek == aShouldDelaySeek) {
return;
}
mShouldDelaySeek = aShouldDelaySeek;
if (!mShouldDelaySeek && mDelayedSeekTarget) {
Seek(mDelayedSeekTarget->GetTime().ToSeconds(),
mDelayedSeekTarget->GetType());
mDelayedSeekTarget.reset();
}
}
void MediaDecoder::DiscardOngoingSeekIfExists() {
MOZ_ASSERT(NS_IsMainThread());
AbstractThread::AutoEnter context(AbstractMainThread());
@@ -650,8 +663,13 @@ void MediaDecoder::DiscardOngoingSeekIfExists() {
void MediaDecoder::CallSeek(const SeekTarget& aTarget) {
MOZ_ASSERT(NS_IsMainThread());
AbstractThread::AutoEnter context(AbstractMainThread());
if (mShouldDelaySeek) {
LOG("Delay seek to %f and store it to delayed seek target",
mDelayedSeekTarget->GetTime().ToSeconds());
mDelayedSeekTarget = Some(aTarget);
return;
}
DiscardOngoingSeekIfExists();
mDecoderStateMachine->InvokeSeek(aTarget)
->Then(mAbstractMainThread, __func__, this, &MediaDecoder::OnSeekResolved,
&MediaDecoder::OnSeekRejected)

View File

@@ -159,6 +159,14 @@ class MediaDecoder : public DecoderDoctorLifeLogger<MediaDecoder> {
bool GetMinimizePreroll() const { return mMinimizePreroll; }
// When we enable delay seek mode, media decoder won't actually ask MDSM to do
// seeking. During this period, we would store the latest seeking target and
// perform the seek to that target when we leave the mode. If we have any
// delayed seeks stored `IsSeeking()` will return true. E.g. During delay
// seeking mode, if we get seek target to 5s, 10s, 7s. When we stop delaying
// seeking, we would only seek to 7s.
void SetDelaySeekMode(bool aShouldDelaySeek);
// All MediaStream-related data is protected by mReentrantMonitor.
// We have at most one DecodedStreamData per MediaDecoder. Its stream
// is used as the input for each ProcessedMediaTrack created by calls to
@@ -664,6 +672,11 @@ class MediaDecoder : public DecoderDoctorLifeLogger<MediaDecoder> {
// background.
bool mIsBackgroundVideoDecodingAllowed;
// True if we want to delay seeking, and and save the latest seeking target to
// resume to when we stop delaying seeking.
bool mShouldDelaySeek = false;
Maybe<SeekTarget> mDelayedSeekTarget;
public:
AbstractCanonical<double>* CanonicalVolume() { return &mVolume; }
AbstractCanonical<bool>* CanonicalPreservesPitch() {

View File

@@ -57,6 +57,7 @@ struct SeekTarget {
bool IsAccurate() const { return mType == SeekTarget::Type::Accurate; }
bool IsNextFrame() const { return mType == SeekTarget::Type::NextFrame; }
bool IsVideoOnly() const { return mVideoOnly; }
Type GetType() const { return mType; }
private:
// Seek target time.