Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Conversation

@mklim
Copy link
Contributor

@mklim mklim commented Dec 1, 2018

Previously codec.cc needed all required frames to already be decoded
before it could decode any of their dependent frames. To accomplish this
it would always cache required frames, regardless of cache limit.

However both GIF and WEBP (the only currently supported animated image
formats) only allow the image to depend on one decoded frame at a time.
This means that there's no reason to cache all the required frames since
it's only valid for the image formats to require one previously decoded
frame at a time. (For example, frame 10 and frame 11 in a hypothetical
animated image could all depend on frame 9. But no subsequent frame
after frame 9 could depend on frames 0-8.)

Warning: this logic will break if we decide to support more animated
formats in the future.

Fixes flutter/flutter#24835.

@mklim
Copy link
Contributor Author

mklim commented Dec 1, 2018

⚠️ This is ready for review but shouldn't be merged yet. ⚠️

@mklim mklim changed the title Cache required frames until they're used Only overflow the cache for one required frame Dec 20, 2018
@mklim
Copy link
Contributor Author

mklim commented Dec 20, 2018

Turns out the required frame dependencies are much more limited than what I originally thought and this PR can be hugely simplified, thanks @amirh. 🎉 Updated with a new patch to only cache one required frame over the limit at a time.

This is also now ready to merge whenever it gets LGTM.

@amirh
Copy link
Contributor

amirh commented Dec 20, 2018

Thanks Michael! great to see this simplified!

What do you think about further simplifying by removing our initialization step of marking required frames?
I believe we can instead just keep 2 members (one for the previous required frame and one for the previous frame) which should be enough to make sure we always have the required frame in memory.
We should then be able to treat all other frames with equal caching priority.

@mklim
Copy link
Contributor Author

mklim commented Dec 20, 2018

I believe we can instead just keep 2 members (one for the previous required frame and one for the previous frame) which should be enough to make sure we always have the required frame in memory.

Just to make sure @amirh: you mean these two members in addition to the regular map of cached bitmaps within our decoded limit, right? Since we'd still want the frame-indexed cache for non-required frames after looping.

If I'm understanding your suggestion right, I think this would work but it would end up taking more memory at runtime. I think we'd need to cache 2 frames over the limit instead of just 1 in cases where we were using required frames at all, and in cases where we weren't we'd always cache 1 frame over the limit instead of 0. We'd want to always cache the N-1 frame in case it ends up being required, even in GIFs that don't have any required frames at all or only one required frame. Since we'd no longer be saving this info about the frames at initialization, we'd need to assume the worst. In cases of overflow always caching N-1 would also mean inserting and deleting from the cache every frame, too. And then on top of that we'd always want to cache the actual last required frame (if it exists) in case a previously required frame is used again instead of the N-1 frame. I don't think it would be preferable to the initialization step since it would end up using more memory, and I don't think the initialization step is really costing us much. What do you think?

@mklim
Copy link
Contributor Author

mklim commented Dec 22, 2018

We talked about this offline. So far the frameBitmaps_ cache has been mixing concerns about caching extraneous frames under the limit and caching required frames in general, which makes the caching logic hard to follow because it's special casing the required frames. I didn't remove the initialization step entirely, but I did update the patch so that it always keeps the last required frame completely separate from the frameBitmaps_ collection of generic decoded frames. I think the logic is more straightforward now.

Copy link
Contributor

@amirh amirh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Michael Klimushyn added 3 commits December 21, 2018 16:32
Previously codec.cc needed all required frames to already be decoded
before it could decode any of their dependent frames. To accomplish this
it would always cache required frames, regardless of cache limit.

However both GIF and WEBP (the only currently supported animated image
formats) only allow the image to depend on one decoded frame at a time.
This means that there's no reason to cache all the required frames since
it's only valid for the image formats to require one previously decoded
frame at a time. (For example, frame 10 and frame 11 in a hypothetical
animated image could all depend on frame 9. But no subsequent frame
after frame 9 could depend on frames 0-8.)

Warning: this logic will break if we decide to support more animated
formats in the future.
This allows us to clean up some of the caching logic so that it's always
consistent and straightforward, instead of it diverging to handle
required frames. `DecodedFrame` struct has been removed and required
frames are now just tracked in their own map.

Frames are always added to the cache as long as they're under the limit,
and never removed. Required frames are always stored as a seperate
member on `MultiFrameCodec`.
@mklim mklim merged commit 770536a into flutter:master Dec 22, 2018
@mklim mklim deleted the gif_decoding branch December 22, 2018 00:55
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Dec 22, 2018
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Dec 23, 2018
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Dec 23, 2018
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Dec 23, 2018
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Dec 24, 2018
engine-flutter-autoroll added a commit to flutter/flutter that referenced this pull request Dec 24, 2018
flutter/engine@215ca15...d8c5ec0

git log 215ca15..d8c5ec0 --no-merges --oneline
d8c5ec0 Roll src/third_party/skia f16825ed3c71..dc5863c4d665 (1 commits) (flutter/engine#7297)
efb8a3f Roll src/third_party/skia 945a56644728..f16825ed3c71 (1 commits) (flutter/engine#7296)
67150a5 Roll src/third_party/skia 28bd882a1e40..945a56644728 (2 commits) (flutter/engine#7295)
3705a1e Roll src/third_party/skia ea8900e74ea7..28bd882a1e40 (1 commits) (flutter/engine#7294)
943ecfc Roll src/third_party/skia 13654b20ce5b..ea8900e74ea7 (1 commits) (flutter/engine#7293)
7b12ae2 Roll src/third_party/skia 12a6d452b126..13654b20ce5b (1 commits) (flutter/engine#7292)
1fe7e1f Roll src/third_party/skia c983480b117f..12a6d452b126 (1 commits) (flutter/engine#7291)
a8b0d26 Roll src/third_party/skia 2e40d9886402..c983480b117f (1 commits) (flutter/engine#7290)
c64f971 Roll src/third_party/skia 98a4e4a4135b..2e40d9886402 (1 commits) (flutter/engine#7289)
65420c2 Roll src/third_party/skia 2a0967383087..98a4e4a4135b (1 commits) (flutter/engine#7288)
770536a Only overflow the cache for one required frame (flutter/engine#7048)
b6880bb Roll src/third_party/skia 9803b8f1d197..2a0967383087 (16 commits) (flutter/engine#7285)

The AutoRoll server is located here: https://autoroll.skia.org/r/flutter-engine-flutter-autoroll

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+/master/autoroll/README.md

If the roll is causing failures, please contact the current sheriff ([email protected]), and stop
the roller if necessary.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants