Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New public api to advance to the next frame #518

Conversation

anforowicz
Copy link
Contributor

PTAL?

Note that this PR is a continuation of (i.e. is based on) #517. This means that you should only look at the last commit really. And this is why I am only submitting this PR as a draft for now. I am splitting things into 2 PRs, because I think the other PR is relatively non-controversial, but we may want to give ourselves a little bit of time to review this PR.

This PR partially address the issues raised in #510

This PR introduces a new public API that can be used to 1) read an fcTL chunk before starting to decode a frame via next_frame and 2) go to the next frame after finishing all rows via next_row / next_interlaced_row. I see the following potential open questions:

  • Return type:
    • I currently propose to return Result<&FrameControl, …>. I think that this helps to reinforce that the API moves to the next FrameControl / fcTL chunk.
    • But in theory the new API could just return Result<(), DecodingError>
  • Naming:
    • next_frame_info as currently proposed?
    • Maybe next_frame_control (since the struct is called FrameControl rather than FrameInfo)?
    • Alternatives that reflect that the private API wrapped here is called read_until_image_data: read_until_next_image_data? read_until_next_frame_data?
  • Behavior
    • The internal read_until_image_data panics if called when the previous image data hasn’t been fully processed (i.e. when subframe.consumed_and_flushed is still false). The panic comes from assert!(buf.is_empty()) in fn read_until_image_data.
    • I propose that the public API checks subframe.consumed_and_flushed and avoids the panic by discarding the previous image data if necessary (by calling finish_decoding).
    • Alternatively we could forbid calling the new public API when subframe.consumed_and_flushed is false (either panicking, or returning a DecodingError::Parameter).
      • One undesirable result of this alternative affects a scenario where the client wants to skip the IDAT frame (e.g. because it doesn’t have an fcTL chunk and is not part of the animation). To handle this scenario the client would have to remember a piece of state that says what to do when recovering from UnexpectedEof: whether to 1) continue discarding the image data vs 2) advance to the new image data by calling the new next_frame_info API
  • Docs
    • Anything else to mention (or change) in the docs?
    • I wondered whether an example in the doc comment would be useful, but I couldn’t come up with something illustrative, self-contained, and succinct.

WDYT?

.unwrap()
.sequence_number
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The new helper function helps to make the tests more compact...

matches!(&err, DecodingError::Parameter(_)),
"Unexpected kind of error: {:?}",
&err,
);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This test would fail (returning FormatError / MissingImageData error instead) without taking into account the "One remaining frame will be consumed by the finish_decoding call below" piece at the top of the new API.

@anforowicz
Copy link
Contributor Author

Oh, I forgot to mention that I've prototyped using this API in WIP http://review.skia.org/c/skia/+/902941 and WIP https://crrev.com/c/5786777 where the new API helps to pass additional tests (AnimatedPNGTests.ParseAndDecodeByteByByte in Chromium's blink_platform_unittests). So, I think I can say that I've validated that the new API is useful and helpful in at least some contexts :-). FWIW I note that the prototype ignores/discards the return/ok value from the new API.

@anforowicz anforowicz force-pushed the new-public-api-to-advance-to-next-frame branch from c04af60 to e52e569 Compare October 6, 2024 16:29
@anforowicz anforowicz marked this pull request as ready for review October 8, 2024 13:48
@kornelski kornelski merged commit ffed4de into image-rs:master Oct 9, 2024
19 checks passed
@anforowicz anforowicz deleted the new-public-api-to-advance-to-next-frame branch October 9, 2024 16:57
hubot pushed a commit to google/skia that referenced this pull request Oct 14, 2024
Before this CL, `SkPngRustCodec` would always report only a single
frame.  This CL refactors `SkPngRustCodec::onGetFrameCount` so that
(when not in the middle of decoding frame data) it will progress in the
input stream to reach additional frames and populate their frame info
based on `fcTL` chunks.  (This means that `onGetFrameCount` will return
progressively increasing values as it traverses the input.  This
behavior mimics `SkWuffsCodec` and `blink::GIFImageDecoder`.  This
behavior differs from `blink::PNGImageDecoder` which always/immediately
returns the final total number of frames.  `SkPngCodec` doesn't support
animated / multi-frame PNGs.)

Note that this CL depends on new public APIs in the `png` crate (ones
that are not yet present in `png-0.17.14`).  Therefore this CL depends
on having a post-0.17.14 crate version when building `FFI.rs`:

* In the short-term this dependency is fulfilled by patching the crate
  in https://crrev.com/c/5922033
* In the long-term this dependency will be met by a new release of the
  `png` crate (the PR at image-rs/image-png#518
  hasn't been released yet).

After this CL (and after patching in the WIP CL at
https://crrev.com/c/5786777) the
`RustEnabled/AnimatedPNGTests.ParseAndDecodeByteByByte/0` test starts to
pass in `blink_platform_unittests`.  (Note that the test only verifies
the number of frames and that byte-by-byte decoding produces the same
results.  The test doesn't expect specific frame contents and there are
some known minor differences like the one tracked in
https://crbug.com/370063145.  Also note that APNG support is still
incomplete at this point - one known issue is no handling of blend ops.)

Bug: chromium:356922876
Change-Id: Ice669f6c8a27529494412d0a7a0206c79da8e394
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/902941
Reviewed-by: Florin Malita <fmalita@google.com>
Reviewed-by: Daniel Dilan <danieldilan@google.com>
Commit-Queue: Florin Malita <fmalita@google.com>
Auto-Submit: Łukasz Anforowicz <lukasza@google.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants