|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
Streaming PNG scanline decoder for the transcode producer (#231). More...
#include <stddef.h>#include <stdint.h>#include <string.h>#include "jof_internal.h"#include "jof_png_internal.h"#include "miniz.h"#include "ra8_attributes.h"#include "ra8_check.h"#include "ra8_err.h"#include "ra8_log.h"Go to the source code of this file.
Data Structures | |
| struct | ra8_png_iter_t |
| Inflate-loop cursor: compressed-input window + progress guard. More... | |
Functions | |
| static uint8_t | internal_png_paeth (uint8_t a, uint8_t b, uint8_t c) |
| Paeth predictor (PNG sec 9.4 "Filter type 4: Paeth"). | |
| static ra8_err_t | internal_png_unfilter (uint8_t filter, uint8_t *row, const uint8_t *prev, uint32_t nbytes, uint8_t bpp) |
| Reconstruct one filtered scanline in place (PNG sec 9 filters). | |
| static ra8_err_t | internal_png_translate (ra8_png_state_t *st, const uint8_t *row) |
| Translate one reconstructed source row into the output layout. | |
| static ra8_err_t | internal_png_consume_rows (ra8_png_state_t *st, const uint8_t *src, uint32_t avail) |
| Assemble, reconstruct and emit rows from freshly inflated bytes. | |
| static ra8_err_t | internal_png_bind_geometry (ra8_png_state_t *st, jof_bump_t *bump) |
| Fire the geometry hook and carve the pixel-path buffers. | |
| static ra8_err_t | internal_png_refill_input (ra8_png_state_t *st, uint32_t *out_avail) |
| Refill the compressed-input buffer from the IDAT chunk stream. | |
| static ra8_err_t | internal_png_inflate_step (ra8_png_state_t *st, ra8_png_iter_t *it) |
| One inflate iteration: refill, tinfl, progress guard, drain rows. | |
| static ra8_err_t | internal_png_inflate_idat (ra8_png_state_t *st, uint32_t first_len) |
| Inflate the whole IDAT stream, emitting every scanline. | |
| static ra8_err_t | internal_png_run_idat (ra8_png_state_t *st, jof_bump_t *bump, uint32_t len) |
| The IDAT arm: bind geometry, inflate the stream, finish the walk. | |
| static ra8_err_t | internal_png_walk_chunks (ra8_png_state_t *st, jof_bump_t *bump, uint16_t max_w, uint16_t max_h) |
| Walk the chunk stream: pre-IDAT chunks, then the IDAT arm. | |
| ra8_err_t | priv_jof_png_rows (jof_pull_fn pull, void *pull_ctx, jof_bump_t *bump, uint16_t max_w, uint16_t max_h, jof_geom_fn on_geom, jof_rows_fn on_rows, void *cb_ctx) |
| Streaming PNG scanline decode: pull bytes in, emit rows in order. | |
Streaming PNG scanline decoder for the transcode producer (#231).
Implements priv_jof_png_rows(): a bounded-RAM, pull-based PNG decoder that never holds the whole image. IDAT deflate data inflates through miniz tinfl into a 64 KiB power-of-two ring (the LZ dictionary), bytes drain into a single scanline assembly buffer, each completed scanline is unfiltered against one previous row (PNG spec sec 9 "Filtering"), then translated to the producer's output layout and emitted – resident cost is the ring plus three rows, independent of the image height.
Supported: 8-bit depth, colour types 0 (gray), 2 (RGB), 3 (palette, with/without tRNS), 4 (gray+alpha), 6 (RGBA), non-interlaced. Everything else is rejected fail-closed – this decoder feeds on untrusted EPUB content. Spec citations reference the W3C PNG specification (second edition), abbreviated PNG sec N.
[Ring 4 / Domain] {World: NS}
Definition in file jof_png.c.
|
static |
Fire the geometry hook and carve the pixel-path buffers.
Runs once, at the first IDAT: decides the output channel count (palette + tRNS promotes to RGBA), requires PLTE for palette images, and carves the inflate + row buffers from the arena.
| [in,out] | st | Decoder state. |
| [in,out] | bump | Work-arena allocator. |
| k_ra8_ok | Buffers carved; hook accepted. |
| k_ra8_err_validation_failed | Palette image with no PLTE. |
| k_ra8_err_invalid_size | Arena exhausted (budget fail-closed). |
| other | The geometry hook aborted the decode. |
bump has the PNG carve set available. Definition at line 279 of file jof_png.c.
References ra8_png_state_t::cb_ctx, ra8_png_state_t::color_type, ra8_png_state_t::dst_ch, ra8_png_state_t::h, ra8_png_state_t::has_plte, ra8_png_state_t::has_trns, ra8_png_state_t::inbuf, ra8_png_state_t::inflator, k_ra8_err_invalid_size, k_ra8_err_validation_failed, k_ra8_ok, k_ra8_png_ch_1, k_ra8_png_ch_3, k_ra8_png_ch_4, k_ra8_png_color_ga, k_ra8_png_color_gray, k_ra8_png_color_pal, k_ra8_png_inbuf_bytes, k_ra8_png_ring_bytes, memset(), ra8_png_state_t::on_geom, ra8_png_state_t::prevrow, priv_jof_bump_take(), RA8_INTERNAL, ra8_png_state_t::ring, ra8_png_state_t::rowbuf, ra8_png_state_t::rowlen, ra8_png_state_t::src_ch, ra8_png_state_t::w, and ra8_png_state_t::xlat.
Referenced by internal_png_run_idat().
|
static |
Assemble, reconstruct and emit rows from freshly inflated bytes.
Drains avail produced bytes into the scanline buffer; each completed scanline is unfiltered, saved as the new previous row, translated and emitted. Producing more scanlines than IHDR declared is a hostile-stream error.
| [in,out] | st | Decoder state. |
| [in] | src | Freshly produced ring bytes (contiguous). |
| [in] | avail | Byte count at src. |
| k_ra8_ok | Bytes consumed (rows possibly emitted). |
| k_ra8_err_validation_failed | Extra rows / bad filter / bad index. |
| other | Propagated from the row sink. |
src covers avail bytes. Definition at line 217 of file jof_png.c.
References ra8_png_state_t::cb_ctx, ra8_png_state_t::dst_ch, ra8_png_state_t::h, internal_png_translate(), internal_png_unfilter(), k_ra8_err_validation_failed, k_ra8_ok, memcpy(), ra8_png_state_t::on_rows, ra8_png_state_t::prevrow, ra8_png_state_t::rowbuf, ra8_png_state_t::rowfill, ra8_png_state_t::rowlen, ra8_png_state_t::rows_done, ra8_png_state_t::src_ch, ra8_png_state_t::w, and ra8_png_state_t::xlat.
Referenced by internal_png_inflate_step().
|
static |
Inflate the whole IDAT stream, emitting every scanline.
Drives internal_png_inflate_step until the zlib stream terminates, then applies the strict termination checks: every declared row arrived, no partial scanline remains, and no compressed bytes trail the stream inside the IDAT chunks.
| [in,out] | st | Decoder state. |
| [in] | first_len | Payload length of the first IDAT chunk. |
| k_ra8_ok | All rows emitted; stream ended clean. |
| k_ra8_err_protocol_error | Corrupt / truncated deflate stream. |
| k_ra8_err_validation_failed | Row-count / trailing-byte mismatch. |
| other | Propagated from pull / the hooks. |
Definition at line 477 of file jof_png.c.
References ra8_png_iter_t::done, ra8_png_state_t::h, ra8_png_state_t::idat_rem, ra8_png_iter_t::in_avail, ra8_png_iter_t::in_pos, internal_png_inflate_step(), k_ra8_err_validation_failed, k_ra8_ok, RA8_INTERNAL, ra8_png_state_t::rowfill, and ra8_png_state_t::rows_done.
Referenced by internal_png_run_idat().
|
static |
One inflate iteration: refill, tinfl, progress guard, drain rows.
The ring is tinfl's LZ dictionary; each call produces into the contiguous run [ring_wr, ring_end) which drains into the scanline assembler before the write offset wraps. Two consecutive zero-progress iterations (or any stall after the source ended) abort as a truncated/hostile stream.
| [in,out] | st | Decoder state. |
| [in,out] | it | Loop cursor (input window + guards). |
| k_ra8_ok | Progress made (or clean stream end). |
| k_ra8_err_protocol_error | Corrupt deflate / no progress. |
| k_ra8_err_validation_failed | Row-stream inconsistency. |
| other | Propagated from pull / the hooks. |
it was zero-initialised before the first call. Definition at line 410 of file jof_png.c.
References ra8_png_iter_t::done, ra8_png_iter_t::in_avail, ra8_png_iter_t::in_pos, ra8_png_state_t::inbuf, ra8_png_state_t::inflator, internal_png_consume_rows(), internal_png_refill_input(), k_ra8_err_protocol_error, k_ra8_ok, k_ra8_png_ring_bytes, RA8_INTERNAL, ra8_png_state_t::ring, ra8_png_state_t::ring_wr, ra8_png_state_t::source_done, and ra8_png_iter_t::stalls.
Referenced by internal_png_inflate_idat().
|
static |
Paeth predictor (PNG sec 9.4 "Filter type 4: Paeth").
Selects whichever neighbour is closest to the linear predictor a + b - c.
| [in] | a | Left reconstructed byte. |
| [in] | b | Above reconstructed byte. |
| [in] | c | Above-left reconstructed byte. |
| a-c | Whichever neighbour is closest to a + b - c. |
Definition at line 65 of file jof_png.c.
References RA8_INTERNAL.
Referenced by internal_png_unfilter().
|
static |
Refill the compressed-input buffer from the IDAT chunk stream.
Crosses consecutive IDAT chunks transparently (skipping each CRC); a non-IDAT chunk ends the compressed stream and is parked as the pending chunk for the outer walk. Bounded by the chunk budget shared with the outer walk.
| [in,out] | st | Decoder state. |
| [out] | out_avail | Receives the refilled byte count (0 = stream end). |
| k_ra8_ok | Buffer refilled (or clean stream end). |
| k_ra8_err_protocol_error | Truncated chunk structure. |
| other | Propagated from the pull callback. |
out_avail is writable. Definition at line 335 of file jof_png.c.
References ra8_png_state_t::idat_rem, ra8_png_state_t::inbuf, k_ra8_err_protocol_error, k_ra8_ok, k_ra8_png_crc_bytes, k_ra8_png_inbuf_bytes, k_ra8_png_max_chunks, k_ra8_png_type_idat, ra8_png_state_t::pending_len, ra8_png_state_t::pending_type, ra8_png_state_t::pending_valid, priv_jof_png_chunk_hdr(), priv_jof_png_pull_exact(), priv_jof_png_skip(), RA8_INTERNAL, and ra8_png_state_t::source_done.
Referenced by internal_png_inflate_step().
|
static |
The IDAT arm: bind geometry, inflate the stream, finish the walk.
Runs once, at the first IDAT chunk; every subsequent IDAT is consumed inside the inflate phase.
| [in,out] | st | Decoder state. |
| [in,out] | bump | Work-arena allocator for the pixel-path carves. |
| [in] | len | Payload length of the first IDAT chunk. |
| k_ra8_ok | Every row emitted and the datastream consumed to IEND. |
| other | Propagated from geometry / inflate / the chunk walk. |
bump has the PNG carve set available. Definition at line 521 of file jof_png.c.
References internal_png_bind_geometry(), internal_png_inflate_idat(), k_ra8_ok, and priv_jof_png_finish().
Referenced by internal_png_walk_chunks().
|
static |
Translate one reconstructed source row into the output layout.
gray -> gray8; RGB/RGBA -> copied; gray+alpha -> RGBA (the gray value replicated); palette -> RGB or RGBA via PLTE (+ tRNS), with every index bounds-checked against the palette (hostile streams may index past a short PLTE).
| [in,out] | st | Decoder state (xlat written). |
| [in] | row | Reconstructed source row (w * src_ch bytes). |
| k_ra8_ok | Row translated into st->xlat. |
| k_ra8_err_validation_failed | A palette index is out of range. |
Definition at line 157 of file jof_png.c.
References ra8_png_state_t::color_type, ra8_png_state_t::dst_ch, k_ra8_err_validation_failed, k_ra8_ok, k_ra8_png_ch_2, k_ra8_png_ch_3, k_ra8_png_ch_4, k_ra8_png_color_ga, k_ra8_png_color_pal, k_ra8_png_opaque, memcpy(), ra8_png_state_t::palette, ra8_png_state_t::plte_count, RA8_INTERNAL, ra8_png_state_t::trns, ra8_png_state_t::trns_count, ra8_png_state_t::w, and ra8_png_state_t::xlat.
Referenced by internal_png_consume_rows().
|
static |
Reconstruct one filtered scanline in place (PNG sec 9 filters).
row is the raw scanline (post filter-byte); prev is the previous reconstructed row (all zeroes for the first row, per spec). The filter arithmetic is modulo-256 by construction.
| [in] | filter | Filter-type byte (0..4; caller-validated range in). |
| [in,out] | row | Scanline bytes, reconstructed in place. |
| [in] | prev | Previous reconstructed row. |
| [in] | nbytes | Scanline byte count (w * src_ch). |
| [in] | bpp | Filter delta distance (source bytes per pixel). |
| k_ra8_ok | Row reconstructed. |
| k_ra8_err_validation_failed | Unknown filter type (hostile stream). |
row and prev each cover nbytes bytes. bpp is in 1..4. row holds reconstructed bytes. Definition at line 101 of file jof_png.c.
References internal_png_paeth(), k_ra8_err_validation_failed, k_ra8_ok, k_ra8_png_filter_avg, k_ra8_png_filter_none, k_ra8_png_filter_paeth, k_ra8_png_filter_sub, k_ra8_png_filter_up, and RA8_INTERNAL.
Referenced by internal_png_consume_rows().
|
static |
Walk the chunk stream: pre-IDAT chunks, then the IDAT arm.
Bounded by the shared chunk budget (NASA Rule 2); a stream that never reaches an IDAT within it is rejected as hostile.
| [in,out] | st | Decoder state (prologue already parsed). |
| [in,out] | bump | Work-arena allocator for the pixel-path carves. |
| [in] | max_w | Fail-closed width cap (for the prologue). |
| [in] | max_h | Fail-closed height cap (for the prologue). |
| k_ra8_ok | Every row emitted; stream consumed. |
| k_ra8_err_protocol_error | Structure error / chunk budget spent. |
| other | Propagated from the chunk / IDAT arms. |
st. Definition at line 555 of file jof_png.c.
References internal_png_run_idat(), k_ra8_err_protocol_error, k_ra8_ok, k_ra8_png_max_chunks, k_ra8_png_type_idat, priv_jof_png_chunk_hdr(), priv_jof_png_pre_idat(), and priv_jof_png_prologue().
Referenced by priv_jof_png_rows().
| ra8_err_t priv_jof_png_rows | ( | jof_pull_fn | pull, |
| void * | pull_ctx, | ||
| jof_bump_t * | bump, | ||
| uint16_t | max_w, | ||
| uint16_t | max_h, | ||
| jof_geom_fn | on_geom, | ||
| jof_rows_fn | on_rows, | ||
| void * | cb_ctx ) |
Streaming PNG scanline decode: pull bytes in, emit rows in order.
Bounded-RAM PNG decoder for the transcode producer: 8-bit depth, colour types 0/2/3/4/6, non-interlaced. IDAT inflates through miniz tinfl into a 64 KiB ring, scanlines are unfiltered against one previous row and translated to the output layout (gray -> 1, RGB / opaque palette -> 3, gray+alpha / RGBA / palette+tRNS -> 4), then handed to on_rows one row at a time. All working buffers are carved from bump. Interlaced, 16-bit, and out-of-spec structures are rejected fail-closed. Chunk CRCs are not verified (the ZIP layer above already integrity-checks the entry; the zlib Adler32 inside IDAT is verified).
| [in] | pull | Sequential byte source positioned at byte 0 of the PNG stream (the producer replays sniffed bytes). |
| [in] | pull_ctx | Context for pull. |
| [in,out] | bump | Work-arena allocator for the decoder's buffers. |
| [in] | max_w | Fail-closed width cap, pixels. |
| [in] | max_h | Fail-closed height cap, pixels. |
| [in] | on_geom | Geometry hook (fires once, before rows). |
| [in] | on_rows | Row sink (fires height times, in order). |
| [in] | cb_ctx | Context for both hooks. |
| k_ra8_ok | Every row emitted. |
| k_ra8_err_invalid_size | Dimensions exceed the caps or the arena is exhausted. |
| k_ra8_err_not_supported | Interlaced / 16-bit / unknown colour type / non-zero compression or filter method. |
| k_ra8_err_protocol_error | Malformed chunk structure or a corrupt / truncated deflate stream. |
| k_ra8_err_validation_failed | Pixel-stream inconsistency (filter byte, palette index, row count). |
| other | Propagated from pull / the hooks. |
pull delivers the PNG from its first signature byte. bump has capacity per jof_work_bytes(). Definition at line 579 of file jof_png.c.
References ra8_png_state_t::cb_ctx, internal_png_walk_chunks(), memset(), ra8_png_state_t::on_geom, ra8_png_state_t::on_rows, ra8_png_state_t::pull, ra8_png_state_t::pull_ctx, RA8_CHECK_NULL_PTR, RA8_PRIV, and s_tag.
Referenced by internal_dispatch().