1From 3ef723bdb6f816e0d467aa6cf7739d525857f669 Mon Sep 17 00:00:00 2001 2From: Lukasz Anforowicz <[email protected]> 3Date: Thu, 3 Oct 2024 19:38:26 +0000 4Subject: [PATCH 103/113] Call `finish_decoding` after last `next_row`. 5 6Before this commit, `next_frame` would take care to read till the end of 7an `IDAT`/`fdAT` chunks sequence, by calling 8`self.decoder.finish_decoding` when 9`!self.subframe.consumed_and_flushed`. `next_row` wouldn't do this and 10therefore the next call to `next_frame` would be temporarily stuck on 11the previous frame (i.e. finishing decoding after the previous frame 12rather than advancing to the next frame). 13 14After this commit, the `finish_decoding` code is extracted to a separate 15helper function that is called by *both* `next_frame` and 16`next_interlaced_row` (once they detect that all rows of a frame have 17been already decoded). 18 19This commit fixes the `test_row_by_row_then_next_frame` unit test. 20--- 21 src/decoder/mod.rs | 25 ++++++++++++++++++++----- 22 src/decoder/stream.rs | 14 +++++++++++--- 23 2 files changed, 31 insertions(+), 8 deletions(-) 24 25diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/mod.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/mod.rs 26index 8a76200..56570b3 100644 27--- a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/mod.rs 28+++ b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/mod.rs 29@@ -532,10 +532,7 @@ impl<R: Read> Reader<R> { 30 } 31 32 // Advance over the rest of data for this (sub-)frame. 33- if !self.subframe.consumed_and_flushed { 34- self.decoder.finish_decoding()?; 35- self.subframe.consumed_and_flushed = true; 36- } 37+ self.finish_decoding()?; 38 39 // Advance our state to expect the next frame. 40 let past_end_subframe = self 41@@ -558,6 +555,21 @@ impl<R: Read> Reader<R> { 42 Ok(output_info) 43 } 44 45+ /// Advance over the rest of data for this (sub-)frame. 46+ /// Called after decoding the last row of a frame. 47+ fn finish_decoding(&mut self) -> Result<(), DecodingError> { 48+ // Double-check that all rows of this frame have been decoded. 49+ assert!(self.subframe.current_interlace_info.is_none()); 50+ 51+ // Discard the remaining data in the current sequence of `IDAT` or `fdAT` chunks. 52+ if !self.subframe.consumed_and_flushed { 53+ self.decoder.finish_decoding()?; 54+ self.subframe.consumed_and_flushed = true; 55+ } 56+ 57+ Ok(()) 58+ } 59+ 60 /// Returns the next processed row of the image 61 pub fn next_row(&mut self) -> Result<Option<Row>, DecodingError> { 62 self.next_interlaced_row() 63@@ -567,7 +579,10 @@ impl<R: Read> Reader<R> { 64 /// Returns the next processed row of the image 65 pub fn next_interlaced_row(&mut self) -> Result<Option<InterlacedRow>, DecodingError> { 66 let interlace = match self.subframe.current_interlace_info.as_ref() { 67- None => return Ok(None), 68+ None => { 69+ self.finish_decoding()?; 70+ return Ok(None); 71+ } 72 Some(interlace) => *interlace, 73 }; 74 if interlace.line_number() == 0 { 75diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs 76index 9c7e1b6..2607078 100644 77--- a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs 78+++ b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs 79@@ -2431,8 +2431,16 @@ mod tests { 80 .next_frame(&mut buf) 81 .expect("Expecting no error from next_frame call"); 82 83- // TODO: Verify if we have read the next `fcTL` chunk + repopulated `buf`: 84- //assert_eq!(reader.info().frame_control.as_ref().unwrap().sequence_number, 1); 85- //assert!(buf.iter().any(|byte| *byte != 0x0f)); 86+ // Verify if we have read the next `fcTL` chunk + repopulated `buf`: 87+ assert_eq!( 88+ reader 89+ .info() 90+ .frame_control 91+ .as_ref() 92+ .unwrap() 93+ .sequence_number, 94+ 1 95+ ); 96+ assert!(buf.iter().any(|byte| *byte != 0x0f)); 97 } 98 } 99-- 1002.47.0.rc0.187.ge670bccf7e-goog 101 102