Issue #2073 - m-c 523950: Discard decoded frames of very large GIF animations (squashed)

Controlled by image.animated.decode-on-demand.threshold-kb, default 256MB

Includes squashed bugfixes/regressions:
 - m-c 1444537: Shutting down the decode pool should make animated decoders bail early
 - m-c 1628606: Make sure to mark the surface cache entry available before sending the frame complete notification
 - m-c 1502275: Skip recreating the decoder after redecode errors if an animated image is reset
 - m-c 1443232: Don't insert frames into our AnimationFrameBuffer that we consider in error and unusable
This commit is contained in:
Martok 2022-12-31 22:55:46 +01:00 committed by roytam1
commit e96122ede2
25 changed files with 925 additions and 63 deletions

View file

@ -64,12 +64,7 @@ AnimationState::UpdateStateInternal(LookupResult& aResult,
if (mHasBeenDecoded) {
Maybe<uint32_t> frameCount = FrameCount();
MOZ_ASSERT(frameCount.isSome());
aResult.Surface().Seek(*frameCount - 1);
if (aResult.Surface() && aResult.Surface()->IsFinished()) {
mIsCurrentlyDecoded = true;
} else {
mIsCurrentlyDecoded = false;
}
mIsCurrentlyDecoded = aResult.Surface().IsFullyDecoded();
}
}
@ -286,8 +281,12 @@ FrameAnimator::AdvanceFrame(AnimationState& aState,
// failure) we would have discarded all the old frames and may not yet have
// the new ones.
if (!nextFrame || !nextFrame->IsFinished()) {
// Uh oh, the frame we want to show is currently being decoded (partial)
// Wait until the next refresh driver tick and try again
// Uh oh, the frame we want to show is currently being decoded (partial).
// Similar to the above case, we could be blocked by network or decoding,
// and so we should advance our current time rather than risk jumping
// through the animation. We will wait until the next refresh driver tick
// and try again.
aState.mCurrentAnimationFrameTime = aTime;
return ret;
}
@ -313,6 +312,7 @@ FrameAnimator::AdvanceFrame(AnimationState& aState,
MOZ_ASSERT(currentFrameEndTime.isSome());
aState.mCurrentAnimationFrameTime = *currentFrameEndTime;
aState.mCurrentAnimationFrameIndex = nextFrameIndex;
aFrames.Advance(nextFrameIndex);
return ret;
}
@ -343,6 +343,7 @@ FrameAnimator::AdvanceFrame(AnimationState& aState,
// Set currentAnimationFrameIndex at the last possible moment
aState.mCurrentAnimationFrameIndex = nextFrameIndex;
aFrames.Advance(nextFrameIndex);
// If we're here, we successfully advanced the frame.
ret.mFrameAdvanced = true;
@ -350,6 +351,25 @@ FrameAnimator::AdvanceFrame(AnimationState& aState,
return ret;
}
void
FrameAnimator::ResetAnimation(AnimationState& aState)
{
aState.ResetAnimation();
// Our surface provider is synchronized to our state, so we need to reset its
// state as well, if we still have one.
LookupResult result =
SurfaceCache::Lookup(ImageKey(mImage),
RasterSurfaceKey(mSize,
DefaultSurfaceFlags(),
PlaybackType::eAnimated));
if (!result) {
return;
}
result.Surface().Reset();
}
RefreshResult
FrameAnimator::RequestRefresh(AnimationState& aState,
const TimeStamp& aTime,