Skip to content

Commit 4362442

Browse files
telecosetemesi254
authored andcommitted
Clarify baseline scan checkpoint semantics
1 parent ea004be commit 4362442

4 files changed

Lines changed: 26 additions & 12 deletions

File tree

crates/zune-jpeg/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,13 @@ bodies, including baseline multi-SOS / non-interleaved images. Those images may
5252
still report no stable output rows until the later component scans have been
5353
decoded and final assembly has run.
5454

55+
Scan checkpoints store only scalar resume state: stream position, next MCU
56+
row/column, restart countdown, SOS parameters, DC predictors, and bitstream
57+
state. Coefficients for already-decoded component scans stay on the decoder
58+
across retries. For multi-SOS images this means a retry can continue inside the
59+
current component scan, then decode later component scans, but output rows are
60+
not considered stable until final assembly has all component data.
61+
5562
```Rust
5663
use zune_core::bytestream::ZCursor;
5764
use zune_jpeg::JpegDecoder;

crates/zune-jpeg/src/decoder.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -79,15 +79,15 @@ pub type IDCTPtr = fn(&mut [i32; 64], &mut [i16], usize);
7979

8080
/// Scan-phase state kept so `decode_into` can retry or replay after SOS.
8181
///
82-
/// Full replay starts at the first SOS; `rst_checkpoint` can resume from a
82+
/// Full replay starts at the first SOS; `scan_checkpoint` can resume from a
8383
/// later restart or row boundary when one is still valid.
8484
#[derive(Clone)]
8585
pub(crate) struct ScanDecodeState {
8686
pub(crate) scan_start_position: usize,
8787
pub(crate) append_snapshot: HeaderAppendStateSnapshot,
8888
pub(crate) sos_snapshot: SosParamsSnapshot,
8989
pub(crate) header_snapshot: ScanHeaderStateSnapshot,
90-
pub(crate) rst_checkpoint: Option<Box<ScanCheckpoint>>
90+
pub(crate) scan_checkpoint: Option<Box<ScanCheckpoint>>
9191
}
9292

9393
/// SOS fields restored before replaying scan data.
@@ -402,15 +402,15 @@ where
402402
append_snapshot,
403403
sos_snapshot,
404404
header_snapshot,
405-
rst_checkpoint: None
405+
scan_checkpoint: None
406406
}));
407407
Ok(())
408408
}
409409

410410
pub(crate) fn scan_checkpoint(&self) -> Option<&ScanCheckpoint> {
411411
self.scan_state
412412
.as_deref()
413-
.and_then(|state| state.rst_checkpoint.as_deref())
413+
.and_then(|state| state.scan_checkpoint.as_deref())
414414
}
415415

416416
// Save a scan checkpoint at the current restart or MCU-row boundary.
@@ -456,9 +456,9 @@ where
456456
dc_predictions,
457457
bitstream_state
458458
};
459-
match &mut state.rst_checkpoint {
459+
match &mut state.scan_checkpoint {
460460
Some(existing) => **existing = snapshot,
461-
None => state.rst_checkpoint = Some(Box::new(snapshot))
461+
None => state.scan_checkpoint = Some(Box::new(snapshot))
462462
}
463463
}
464464
Ok(())
@@ -476,7 +476,7 @@ where
476476
/// replaying from scan start.
477477
pub(crate) fn invalidate_scan_checkpoint(&mut self) {
478478
if let Some(state) = self.scan_state.as_mut() {
479-
state.rst_checkpoint = None;
479+
state.scan_checkpoint = None;
480480
}
481481
}
482482

@@ -1339,7 +1339,7 @@ where
13391339
outer_append_snapshot: state.append_snapshot,
13401340
outer_sos_snapshot: state.sos_snapshot,
13411341
outer_header_snapshot: state.header_snapshot.clone(),
1342-
checkpoint_view: state.rst_checkpoint.as_deref().map(|checkpoint| {
1342+
checkpoint_view: state.scan_checkpoint.as_deref().map(|checkpoint| {
13431343
CheckpointView {
13441344
append_snapshot: checkpoint.append_snapshot,
13451345
sos_snapshot: checkpoint.sos_snapshot,
@@ -1461,15 +1461,15 @@ where
14611461

14621462
match result {
14631463
Ok(()) => {
1464-
// Drop the RST checkpoint so a post-success replay starts
1464+
// Drop the scan checkpoint so a post-success replay starts
14651465
// from scan-start with zeroed DC predictors instead of
14661466
// pointing at stale entropy data.
14671467
debug_assert!(
14681468
self.scan_state.is_some(),
14691469
"scan_state should be Some after a successful scan decode"
14701470
);
14711471
if let Some(state) = self.scan_state.as_deref_mut() {
1472-
state.rst_checkpoint = None;
1472+
state.scan_checkpoint = None;
14731473
}
14741474
self.pixels_decoded = expected_size;
14751475
Ok(())

crates/zune-jpeg/src/lib.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,13 @@
6262
//! still report no stable output rows until the later component scans have been
6363
//! decoded and final assembly has run.
6464
//!
65+
//! Scan checkpoints store only scalar resume state: stream position, next MCU
66+
//! row/column, restart countdown, SOS parameters, DC predictors, and bitstream
67+
//! state. Coefficients for already-decoded component scans stay on the decoder
68+
//! across retries. For multi-SOS images this means a retry can continue inside the
69+
//! current component scan, then decode later component scans, but output rows are
70+
//! not considered stable until final assembly has all component data.
71+
//!
6572
//! ```no_run
6673
//! use zune_core::bytestream::ZCursor;
6774
//! use zune_jpeg::errors::DecodeErrors;

crates/zune-jpeg/src/mcu.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ impl<T: ZByteReaderTrait> JpegDecoder<T> {
6767
// Move the persistent multi-SOS coefficient buffer out of `self` so
6868
// the inner decoder can borrow it mutably while still calling methods
6969
// on `self`. The buffer is put back on return and survives across
70-
// `decode_into` retries, which is what lets per-RST checkpoints stay
70+
// `decode_into` retries, which is what lets scan checkpoints stay
7171
// allocation-free.
7272
let mut progressive_mcus = core::mem::take(&mut self.progressive_mcus_buffer);
7373
let result = self.decode_mcu_ycbcr_baseline_inner::<B>(pixels, &mut progressive_mcus);
@@ -147,7 +147,7 @@ impl<T: ZByteReaderTrait> JpegDecoder<T> {
147147
let mut tmp = [0_i32; DCT_BLOCK];
148148

149149
let comp_len = self.components.len();
150-
// True when we are resuming from a previously-saved RST checkpoint;
150+
// True when we are resuming from a previously-saved scan checkpoint;
151151
// in that case the per-component `raw_coeff` and `progressive_mcus`
152152
// buffers still hold the data from the prior `decode_into` call and
153153
// must not be re-zeroed. On a fresh decode they are (re-)allocated.

0 commit comments

Comments
 (0)