ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
jof_produce.c File Reference

Transcode producer: sniff, decode, tile, encode, emit (#231, #290). More...

#include "jof_produce.h"
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include "jof.h"
#include "jof_internal.h"
#include "ra8_attributes.h"
#include "ra8_check.h"
#include "ra8_compress.h"
#include "ra8_err.h"
#include "ra8_jpeg_sw.h"
#include "ra8_log.h"
#include "ra8_webp.h"
Include dependency graph for jof_produce.c:

Go to the source code of this file.

Enumerations

enum  jof_prod_const_t : uint32_t {
  k_jof_sniff_bytes = 12U ,
  k_jof_png_sig_len = 8U ,
  k_jof_jpeg_soi_first = 0xFFU ,
  k_jof_jpeg_soi_second = 0xD8U ,
  k_jof_webp_fourcc_ofs = 8U ,
  k_jof_png_ring = 65536U ,
  k_jof_png_inbuf = 4096U ,
  k_jof_byte_mask = 0xFFU ,
  k_jof_le_sh8 = 8U ,
  k_jof_le_sh16 = 16U ,
  k_jof_le_sh24 = 24U ,
  k_jof_png_ihdr_w = 16U ,
  k_jof_png_ihdr_h = 20U ,
  k_jof_png_ihdr_end = 24U
}
 Producer sizing and sniffing constants. More...
enum  jof_png_signature_t : uint8_t {
  k_jof_png_sig_high = 0x89U ,
  k_jof_png_sig_cr = 0x0DU ,
  k_jof_png_sig_lf = 0x0AU ,
  k_jof_png_sig_sub = 0x1AU
}
 Fixed non-ASCII bytes in the PNG signature. More...

Functions

void * priv_jof_bump_take (jof_bump_t *bump, size_t len)
 Implementation of priv_jof_bump_take() – aligned linear carve.
static void internal_wr_u16 (uint8_t *buf, uint16_t v)
 Store a uint16 little-endian at buf.
static void internal_wr_u32 (uint8_t *buf, uint32_t v)
 Store a uint32 little-endian at buf.
static ra8_err_t internal_sink (jof_prod_state_t *st, const uint8_t *buf, size_t len)
 Append bytes to the caller sink, tracking the atlas offset.
ra8_err_t priv_jof_prefix_pull (void *ctx, uint8_t *buf, size_t cap, size_t *got)
 Pull adapter: replay the sniffed head, then delegate to the source.
static ra8_err_t internal_emit_header (jof_prod_state_t *st)
 Serialize + sink the 32-byte JOF header from the bound geometry.
static ra8_err_t internal_carve_pixel_path (jof_prod_state_t *st)
 Carve the band, stage, index and compressed-tile buffers.
ra8_err_t priv_jof_on_geom (void *ctx, uint16_t width, uint16_t height, uint8_t channels)
 Bind the source geometry: validate caps, carve buffers, emit header.
static ra8_err_t internal_encode_tile (jof_prod_state_t *st, uint32_t payload)
 Encode one packed tile payload and append it to the atlas.
static ra8_err_t internal_flush_band (jof_prod_state_t *st, uint32_t th)
 Cut the accumulated band into tiles and append each to the atlas.
ra8_err_t priv_jof_on_rows (void *ctx, const uint8_t *px, uint16_t width, uint16_t y0, uint16_t nrows, uint8_t channels)
 Row sink shared by every decoder arm: accumulate, flush full bands.
static ra8_err_t internal_jpeg_geom (void *ctx, uint16_t width, uint16_t height, uint8_t channels, uint16_t stripe_rows, uint8_t **out_stripe, uint32_t *out_stripe_cap)
 JPEG geometry adapter: bind geometry, then carve the MCU stripe.
static ra8_err_t internal_finish (jof_prod_state_t *st, jof_info_t *out_info)
 Emit the tile index and footer, then fill the caller's info.
static ra8_err_t internal_check_cfg (const jof_produce_cfg_t *cfg)
 Validate the caller configuration's non-pointer invariants.
uint32_t jof_work_bytes (uint16_t max_width, uint16_t max_height, uint16_t tile_w, uint16_t tile_h)
 Compute the work-arena size the producer needs for given caps.
static ra8_err_t internal_init_state (jof_prod_state_t *st, const jof_produce_cfg_t *cfg)
 Reset the transcode state and carve the deflate scratch.
static ra8_err_t internal_sniff_head (const jof_produce_cfg_t *cfg, uint8_t *head)
 Pull the sniff head (both formats need at least these bytes).
static ra8_err_t internal_dispatch (jof_prod_state_t *st, const uint8_t *head, jof_prefix_pull_t *pfx)
 Dispatch the sniffed source to the matching decoder.
static uint32_t internal_rd_be32 (const uint8_t *buf)
 Read a big-endian uint32 (PNG stores its IHDR fields big-endian).
static bool internal_is_webp (const uint8_t *data)
 True if the sniff window carries the WebP RIFF container magic.
static ra8_err_t internal_png_dims (const uint8_t *data, size_t len, uint32_t *out_w, uint32_t *out_h)
 Read the pixel geometry out of a PNG IHDR chunk.
static ra8_err_t internal_probe_sniff (const uint8_t *data, size_t len, uint16_t *out_w, uint16_t *out_h)
 Sniff the container, read its declared geometry and range-check it.
ra8_err_t jof_probe_dims (const uint8_t *data, size_t len, uint16_t *out_w, uint16_t *out_h)
 Read a source image's pixel dimensions without decoding its body.
static ra8_err_t internal_epilogue (jof_prod_state_t *st, jof_info_t *out_info)
 Post-decode checks, final band flush and trailer emission.
static ra8_err_t internal_produce_args_ok (const jof_produce_cfg_t *cfg, const jof_info_t *out_info)
 Reject any NULL jof_produce argument or seam.
ra8_err_t jof_produce (const jof_produce_cfg_t *cfg, jof_info_t *out_info)
 Transcode one encoded JPEG/PNG/WebP source into a JOF atlas (#231, #290).

Variables

static const char *const s_tag = "jof_prod"
 Module log tag.
static const uint8_t s_prod_png_sig [k_jof_png_sig_len]
 PNG signature for source sniffing (mirrors the PNG decoder unit).
static const uint8_t s_prod_webp_riff [k_jof_magic_len] = {'R', 'I', 'F', 'F'}
 WebP RIFF container tag (source head bytes 0..3).
static const uint8_t s_prod_webp_webp [k_jof_magic_len] = {'W', 'E', 'B', 'P'}
 WebP form-type fourCC (source head bytes 8..11).

Detailed Description

Transcode producer: sniff, decode, tile, encode, emit (#231, #290).

Implements jof_produce() and jof_work_bytes(). The producer owns the band accumulator (one tile row of decoded pixels), the tile cut + intra-encode + sink stage, and the trailing index/footer emission; the pixel rows arrive from ra8_jpeg_sw_decode_stripes() (JPEG) or priv_jof_png_rows() (PNG), both bounded-RAM by construction. Every streaming buffer is carved from the caller's work arena through the bump allocator – the producer allocates nothing on the heap. The whole-frame WebP arm (#290) is dispatched here but lives in the sibling jof_produce_webp.c, sharing the producer state and the geometry / rows / prefix-pull seams through jof_internal.h.

[Ring 4 / Domain] {World: NS}

Definition in file jof_produce.c.

Enumeration Type Documentation

◆ jof_png_signature_t

enum jof_png_signature_t : uint8_t

Fixed non-ASCII bytes in the PNG signature.

Enumerator
k_jof_png_sig_high 

High-bit signature byte.

k_jof_png_sig_cr 

Carriage return byte.

k_jof_png_sig_lf 

Line feed byte.

k_jof_png_sig_sub 

DOS EOF byte.

Definition at line 65 of file jof_produce.c.

◆ jof_prod_const_t

enum jof_prod_const_t : uint32_t

Producer sizing and sniffing constants.

Enumerator
k_jof_sniff_bytes 

Magic bytes pulled up front (WebP needs 12).

k_jof_png_sig_len 

PNG signature length.

k_jof_jpeg_soi_first 

JPEG SOI first byte.

k_jof_jpeg_soi_second 

JPEG SOI second byte.

k_jof_webp_fourcc_ofs 

Offset of the "WEBP" fourCC.

k_jof_png_ring 

PNG inflate ring carve (bytes).

k_jof_png_inbuf 

PNG input-buffer carve (bytes).

k_jof_byte_mask 

Low-byte mask.

k_jof_le_sh8 

Little-endian shift.

k_jof_le_sh16 

Little-endian shift.

k_jof_le_sh24 

Little-endian shift.

k_jof_png_ihdr_w 

PNG IHDR width field offset (big-endian).

k_jof_png_ihdr_h 

PNG IHDR height field offset (big-endian).

k_jof_png_ihdr_end 

Bytes needed to read both IHDR fields.

Definition at line 47 of file jof_produce.c.

Function Documentation

◆ internal_carve_pixel_path()

ra8_err_t internal_carve_pixel_path ( jof_prod_state_t * st)
static

Carve the band, stage, index and compressed-tile buffers.

Sizes are computed in 64-bit and checked against the u32 format cap before any carve; arena exhaustion fails closed.

Parameters
[in,out]stProducer state (geometry fields already bound).
Returns
Result code.
Return values
k_ra8_okEvery pixel-path buffer is carved.
k_ra8_err_invalid_sizeOverflow or arena exhaustion.
Precondition
st->w/st->h/st->bpp and the grid fields are bound.
st->bump has the geometry carve set available.
Postcondition
On success band/stage/idx (and cmp for deflate) are bound.
On error the transcode aborts.
Note
Not thread-safe.
Since
0.1.0

Definition at line 251 of file jof_produce.c.

References jof_prod_state_t::band, jof_prod_state_t::bpp, jof_prod_state_t::bump, jof_prod_state_t::cfg, jof_prod_state_t::cmp, jof_prod_state_t::cmp_cap, jof_produce_cfg_t::codec, jof_prod_state_t::h, jof_prod_state_t::idx, jof_stored_bound(), k_jof_codec_deflate, k_jof_index_entry, k_ra8_err_invalid_size, k_ra8_ok, priv_jof_bump_take(), RA8_INTERNAL, jof_prod_state_t::stage, jof_prod_state_t::tile_count, jof_produce_cfg_t::tile_h, jof_produce_cfg_t::tile_w, and jof_prod_state_t::w.

Referenced by priv_jof_on_geom().

◆ internal_check_cfg()

ra8_err_t internal_check_cfg ( const jof_produce_cfg_t * cfg)
static

Validate the caller configuration's non-pointer invariants.

Single-condition guards over the tile geometry and codec selector.

Parameters
[in]cfgProducer configuration.
Returns
Result code.
Return values
k_ra8_okGeometry and codec are usable.
k_ra8_err_invalid_argZero tile geometry or unknown codec.
Precondition
cfg is non-NULL (caller-validated).
Pointer members were validated by the caller.
Postcondition
No state mutated.
Return depends solely on cfg.
Note
Thread-safe (pure).
Since
0.1.0

Definition at line 579 of file jof_produce.c.

References jof_produce_cfg_t::codec, k_jof_codec_deflate, k_ra8_err_invalid_arg, k_ra8_ok, RA8_INTERNAL, jof_produce_cfg_t::tile_h, and jof_produce_cfg_t::tile_w.

Referenced by jof_produce().

◆ internal_dispatch()

ra8_err_t internal_dispatch ( jof_prod_state_t * st,
const uint8_t * head,
jof_prefix_pull_t * pfx )
static

Dispatch the sniffed source to the matching decoder.

The compound sniff decision carries MC/DC vectors in test_jof_produce.c (JPEG head), the PNG head vector, and test_jof_produce_webp.c (WebP RIFF+WEBP head, plus the RIFF-without-WEBP fail-closed vector).

Parameters
[in,out]stProducer state.
[in]headThe sniffed source head.
[in,out]pfxPrefix-replay pull adapter over the source.
Returns
Result code.
Return values
k_ra8_okWhole source decoded and accumulated.
k_ra8_err_not_supportedThe head is not JPEG/PNG/WebP.
k_ra8_err_invalid_sizeThe arena cannot fit the decoder set.
otherPropagated from the decoders.
Precondition
internal_init_state() succeeded.
pfx replays head before the live source.
Postcondition
On success every source row reached the band accumulator.
On error the transcode aborts.
Note
Not thread-safe.
Since
0.1.0

Definition at line 727 of file jof_produce.c.

References jof_prod_state_t::bump, jof_prod_state_t::cap_h, jof_prod_state_t::cap_w, internal_jpeg_geom(), k_jof_jpeg_soi_first, k_jof_jpeg_soi_second, k_jof_webp_fourcc_ofs, k_ra8_err_invalid_size, k_ra8_err_not_supported, k_ra8_jpeg_sw_stream_min_window, memcmp(), priv_jof_bump_take(), priv_jof_on_geom(), priv_jof_on_rows(), priv_jof_png_rows(), priv_jof_prefix_pull(), priv_jof_webp_transcode(), ra8_jpeg_sw_decode_stripes(), s_prod_png_sig, s_prod_webp_riff, and s_prod_webp_webp.

Referenced by jof_produce().

◆ internal_emit_header()

ra8_err_t internal_emit_header ( jof_prod_state_t * st)
static

Serialize + sink the 32-byte JOF header from the bound geometry.

Serializes every geometry field per the JOF layout table in jof.h.

Parameters
[in,out]stProducer state (written advances via the sink).
Returns
Result code.
Return values
k_ra8_okThe header is the first 32 atlas bytes.
otherPropagated from the sink.
Precondition
The geometry fields of st are bound and validated.
No atlas byte has been sunk yet (written == 0).
Postcondition
On success the sink holds exactly the header.
On error the transcode aborts.
Note
Not thread-safe.
Since
0.1.0

Definition at line 218 of file jof_produce.c.

References jof_prod_state_t::bpp, jof_prod_state_t::cfg, jof_produce_cfg_t::codec, jof_prod_state_t::h, internal_sink(), internal_wr_u16(), internal_wr_u32(), k_jof_hdr_bytes, k_jof_ofs_bpp, k_jof_ofs_codec, k_jof_ofs_height, k_jof_ofs_tile_count, k_jof_ofs_tile_h, k_jof_ofs_tile_w, k_jof_ofs_width, RA8_INTERNAL, jof_prod_state_t::tile_count, jof_produce_cfg_t::tile_h, jof_produce_cfg_t::tile_w, and jof_prod_state_t::w.

Referenced by priv_jof_on_geom().

◆ internal_encode_tile()

ra8_err_t internal_encode_tile ( jof_prod_state_t * st,
uint32_t payload )
static

Encode one packed tile payload and append it to the atlas.

Raw codec sinks the payload verbatim; the deflate codec runs it through the zero-heap ra8_compress() into the bounded compressed-tile buffer. The tile's index entry (absolute offset plus stored length) is recorded before the bytes are sunk.

Parameters
[in,out]stProducer state.
[in]payloadPacked tile byte count (tw * th * bpp).
Returns
Result code.
Return values
k_ra8_okTile encoded, recorded and sunk.
k_ra8_err_validation_failedThe compressor overran its bound (cannot happen for real inputs).
otherPropagated from the sink.
Precondition
st->stage holds payload packed bytes.
st->tiles_done < st->tile_count.
Postcondition
On success tiles_done advanced and the index entry is recorded.
On error the transcode aborts.
Note
Not thread-safe.
Since
0.1.0

Definition at line 354 of file jof_produce.c.

References jof_prod_state_t::cfg, jof_prod_state_t::cmp, jof_prod_state_t::cmp_cap, jof_produce_cfg_t::codec, jof_prod_state_t::dfl, jof_prod_state_t::dfl_len, jof_prod_state_t::idx, internal_sink(), internal_wr_u32(), k_jof_codec_deflate, k_jof_idx_ofs_length, k_jof_idx_ofs_offset, k_jof_index_entry, k_ra8_err_validation_failed, k_ra8_ok, ra8_compress(), RA8_INTERNAL, jof_prod_state_t::stage, jof_prod_state_t::tiles_done, and jof_prod_state_t::written.

Referenced by internal_flush_band().

◆ internal_epilogue()

ra8_err_t internal_epilogue ( jof_prod_state_t * st,
jof_info_t * out_info )
static

Post-decode checks, final band flush and trailer emission.

The decoder must have bound the geometry and delivered every row; a short delivery is a hostile-source abort.

Parameters
[in,out]stProducer state.
[out]out_infoReceives the finished atlas geometry.
Returns
Result code.
Return values
k_ra8_okAtlas fully written to the sink.
k_ra8_err_validation_failedThe decoder under-delivered.
otherPropagated from the flush / trailer.
Precondition
internal_dispatch() returned success.
out_info is writable.
Postcondition
On success the sink holds one complete, parseable atlas.
On error the partial atlas must be discarded.
Note
Not thread-safe.
Since
0.1.0

Definition at line 921 of file jof_produce.c.

References jof_prod_state_t::band_fill, jof_prod_state_t::geom_done, jof_prod_state_t::h, internal_finish(), internal_flush_band(), k_ra8_err_validation_failed, k_ra8_ok, RA8_INTERNAL, and jof_prod_state_t::rows_seen.

Referenced by jof_produce().

◆ internal_finish()

ra8_err_t internal_finish ( jof_prod_state_t * st,
jof_info_t * out_info )
static

Emit the tile index and footer, then fill the caller's info.

Emits the trailing tile index and 16-byte footer, then mirrors the parsed-info fields.

Parameters
[in,out]stProducer state.
[out]out_infoReceives the finished atlas geometry.
Returns
Result code.
Return values
k_ra8_okAtlas complete and accounted.
k_ra8_err_validation_failedNot every tile was flushed.
otherPropagated from the sink.
Precondition
All rows arrived and the last band was flushed.
st->idx holds tile_count serialized entries.
Postcondition
On success the sink holds a complete JOF atlas.
On error the partial atlas must be discarded.
Note
Not thread-safe.
Since
0.1.0

Definition at line 528 of file jof_produce.c.

References jof_info_t::bpp, jof_prod_state_t::bpp, jof_prod_state_t::cfg, jof_info_t::codec, jof_produce_cfg_t::codec, jof_prod_state_t::h, jof_info_t::height, jof_prod_state_t::idx, jof_info_t::index_off, internal_sink(), internal_wr_u32(), k_jof_footer_bytes, k_jof_ftr_index_off, k_jof_ftr_magic, k_jof_ftr_tile_count, k_jof_ftr_total_size, k_jof_index_entry, k_ra8_err_validation_failed, k_ra8_ok, RA8_INTERNAL, jof_info_t::tile_cols, jof_prod_state_t::tile_cols, jof_info_t::tile_count, jof_prod_state_t::tile_count, jof_info_t::tile_h, jof_produce_cfg_t::tile_h, jof_info_t::tile_rows, jof_prod_state_t::tile_rows, jof_info_t::tile_w, jof_produce_cfg_t::tile_w, jof_prod_state_t::tiles_done, jof_info_t::total_size, jof_prod_state_t::w, jof_info_t::width, and jof_prod_state_t::written.

Referenced by internal_epilogue().

◆ internal_flush_band()

ra8_err_t internal_flush_band ( jof_prod_state_t * st,
uint32_t th )
static

Cut the accumulated band into tiles and append each to the atlas.

Iterates the tile columns left to right (row-major tile order), packing each tile's rows tightly into the stage buffer before encoding. Edge columns carry their clamped width.

Parameters
[in,out]stProducer state (band consumed; tiles emitted).
[in]thRows in this band (tile_h, or less for the last band).
Returns
Result code.
Return values
k_ra8_okEvery tile of the band was encoded and sunk.
otherPropagated from the encode/sink stage.
Precondition
st->band holds th complete rows.
th >= 1.
Postcondition
On success tiles_done advanced by tile_cols.
On error the transcode aborts.
Note
Not thread-safe.
Since
0.1.0

Definition at line 396 of file jof_produce.c.

References jof_prod_state_t::band, jof_prod_state_t::bpp, jof_prod_state_t::cfg, internal_encode_tile(), k_ra8_ok, memcpy(), RA8_INTERNAL, jof_prod_state_t::stage, jof_prod_state_t::tile_cols, jof_produce_cfg_t::tile_w, and jof_prod_state_t::w.

Referenced by internal_epilogue(), and priv_jof_on_rows().

◆ internal_init_state()

ra8_err_t internal_init_state ( jof_prod_state_t * st,
const jof_produce_cfg_t * cfg )
static

Reset the transcode state and carve the deflate scratch.

Clamps the caller caps to the format maximum, binds the owned bump allocator over the caller's work arena, and carves the codec scratch.

Parameters
[out]stProducer state to (re)initialise.
[in]cfgCaller configuration (validated).
Returns
Result code.
Return values
k_ra8_okState bound; scratch carved when needed.
k_ra8_err_invalid_sizeThe arena cannot fit the deflate scratch.
Precondition
cfg passed the pointer + geometry guards.
cfg->work covers work_cap bytes.
Postcondition
On success the effective caps and codec scratch are bound.
On error the transcode aborts before any sink write.
Note
Not thread-safe.
Since
0.1.0

Definition at line 646 of file jof_produce.c.

References jof_prod_state_t::bump, jof_prod_state_t::bump_store, jof_prod_state_t::cap_h, jof_prod_state_t::cap_w, jof_prod_state_t::cfg, jof_produce_cfg_t::codec, jof_prod_state_t::dfl, jof_prod_state_t::dfl_len, k_jof_codec_deflate, k_jof_max_dim, k_ra8_compress_scratch_bytes, k_ra8_err_invalid_size, k_ra8_ok, jof_produce_cfg_t::max_height, jof_produce_cfg_t::max_width, memset(), priv_jof_bump_take(), RA8_INTERNAL, and jof_produce_cfg_t::work_cap.

Referenced by jof_produce().

◆ internal_is_webp()

bool internal_is_webp ( const uint8_t * data)
static

True if the sniff window carries the WebP RIFF container magic.

A WebP file is a RIFF container whose form type is "WEBP", so both fourCCs must match – a bare "RIFF" is some other RIFF payload.

Parameters
[in]dataSource bytes (at least k_jof_sniff_bytes readable).
Returns
Whether both fourCCs matched.
Return values
trueThe source is a WebP RIFF container.
falseEither fourCC differs.
Precondition
data holds k_jof_sniff_bytes readable bytes.
The caller has already excluded the JPEG and PNG signatures.
Postcondition
No state is mutated.
The result depends only on the first twelve source bytes.
Note
Pure; thread-safe.
Since
0.1.0

Definition at line 796 of file jof_produce.c.

References k_jof_webp_fourcc_ofs, memcmp(), RA8_INTERNAL, s_prod_webp_riff, and s_prod_webp_webp.

Referenced by internal_probe_sniff().

◆ internal_jpeg_geom()

ra8_err_t internal_jpeg_geom ( void * ctx,
uint16_t width,
uint16_t height,
uint8_t channels,
uint16_t stripe_rows,
uint8_t ** out_stripe,
uint32_t * out_stripe_cap )
static

JPEG geometry adapter: bind geometry, then carve the MCU stripe.

Wraps priv_jof_on_geom for ra8_jpeg_sw_decode_stripes(), which additionally needs a caller-owned stripe buffer sized width * stripe_rows * channels.

Parameters
[in]ctxThe producer state.
[in]widthSource width, pixels.
[in]heightSource height, pixels.
[in]channelsOutput channels (1 or 3).
[in]stripe_rowsRows per stripe (8 or 16).
[out]out_stripeReceives the carved stripe buffer.
[out]out_stripe_capReceives its capacity.
Returns
Result code.
Return values
k_ra8_okGeometry bound; stripe carved.
k_ra8_err_invalid_sizeCaps exceeded or arena exhausted.
otherPropagated from priv_jof_on_geom.
Precondition
out_stripe / out_stripe_cap are writable.
st->bump has the JPEG carve set available.
Postcondition
On success the stripe buffer is bound for the scan.
On error the transcode aborts.
Note
Not thread-safe.
Since
0.1.0

Definition at line 483 of file jof_produce.c.

References jof_prod_state_t::bump, k_ra8_err_invalid_size, k_ra8_ok, priv_jof_bump_take(), priv_jof_on_geom(), and RA8_INTERNAL.

Referenced by internal_dispatch().

◆ internal_png_dims()

ra8_err_t internal_png_dims ( const uint8_t * data,
size_t len,
uint32_t * out_w,
uint32_t * out_h )
static

Read the pixel geometry out of a PNG IHDR chunk.

IHDR is fixed at the head of every PNG, so the width and height sit at constant offsets; both are big-endian per the specification.

Parameters
[in]dataSource bytes beginning with the PNG signature.
[in]lenReadable length of data in bytes.
[out]out_wReceives the declared width in pixels.
[out]out_hReceives the declared height in pixels.
Returns
Result code.
Return values
k_ra8_okGeometry read.
k_ra8_err_not_supportedThe source is too short to hold a full IHDR.
Precondition
data starts with the eight-byte PNG signature.
out_w and out_h are writable.
Postcondition
On success both outputs hold the IHDR fields verbatim, unvalidated.
On failure neither output is written.
Note
Pure apart from the outputs; thread-safe.
See also
internal_rd_be32()
Since
0.1.0

Definition at line 823 of file jof_produce.c.

References internal_rd_be32(), k_jof_png_ihdr_end, k_jof_png_ihdr_h, k_jof_png_ihdr_w, k_ra8_err_not_supported, and k_ra8_ok.

Referenced by internal_probe_sniff().

◆ internal_probe_sniff()

ra8_err_t internal_probe_sniff ( const uint8_t * data,
size_t len,
uint16_t * out_w,
uint16_t * out_h )
static

Sniff the container, read its declared geometry and range-check it.

The probing algorithm behind jof_probe_dims, split from it so the public entry carries only the null-pointer contract. The dispatch order mirrors internal_dispatch, which is what keeps "the caller can size it" and "the producer will decode it" in step.

JPEG is answered by ra8_jpeg_sw_get_dimensions directly: that reader already range-checks against its own frame limits and writes the 16-bit outputs itself, so it returns without a second check. PNG and WebP yield 32-bit values that still have to be proved non-zero and within k_jof_max_dim before narrowing.

Parameters
[in]dataEncoded source bytes.
[in]lenReadable length of data in bytes.
[out]out_wReceives the source width in pixels.
[out]out_hReceives the source height in pixels.
Returns
Result code.
Return values
k_ra8_okGeometry probed and within range.
k_ra8_err_not_supportedToo short to sniff, or not JPEG/PNG/WebP.
k_ra8_err_invalid_sizeA dimension is zero or over the atlas cap.
otherPropagated from the per-format reader.
Precondition
data holds len readable bytes.
out_w and out_h are non-null and writable.
Postcondition
On success both outputs hold a non-zero, in-range dimension.
On any error neither output is written.
Note
Not thread-safe beyond its arguments.
See also
internal_png_dims(), internal_is_webp(), ra8_webp_get_info()
Since
0.1.0

Definition at line 864 of file jof_produce.c.

References internal_is_webp(), internal_png_dims(), k_jof_jpeg_soi_first, k_jof_jpeg_soi_second, k_jof_max_dim, k_jof_sniff_bytes, k_ra8_err_invalid_size, k_ra8_err_not_supported, k_ra8_ok, memcmp(), ra8_jpeg_sw_get_dimensions(), ra8_webp_get_info(), and s_prod_png_sig.

Referenced by jof_probe_dims().

◆ internal_produce_args_ok()

ra8_err_t internal_produce_args_ok ( const jof_produce_cfg_t * cfg,
const jof_info_t * out_info )
static

Reject any NULL jof_produce argument or seam.

Split out so the public entry stays under the statement budget.

Parameters
[in]cfgProducer configuration to validate.
[in]out_infoOutput pointer to validate.
Returns
Result code.
Return values
k_ra8_okEvery required pointer is non-NULL.
k_ra8_err_null_ptrSome pointer is NULL.
Precondition
Only cfg is dereferenced (after its own check).
The caller forwards its own arguments.
Postcondition
No state mutated.
Return depends solely on the inputs.
Note
Thread-safe (pure).
Since
0.1.0

Definition at line 953 of file jof_produce.c.

References k_ra8_ok, jof_produce_cfg_t::pull, RA8_CHECK_NULL_PTR, RA8_INTERNAL, s_tag, and jof_produce_cfg_t::sink.

Referenced by jof_produce().

◆ internal_rd_be32()

uint32_t internal_rd_be32 ( const uint8_t * buf)
static

Read a big-endian uint32 (PNG stores its IHDR fields big-endian).

The JOF container is little-endian throughout, so the little-endian helpers above do not serve the PNG IHDR probe.

Parameters
[in]bufSource bytes (at least 4 readable).
Returns
The decoded value.
Return values
0All four source bytes were zero.
Precondition
buf holds 4 readable bytes.
The field is big-endian per the PNG specification.
Postcondition
No state is mutated.
The result equals the four bytes assembled big-endian.
Note
Pure; thread-safe.
Since
0.1.0

Definition at line 774 of file jof_produce.c.

References k_jof_le_sh16, k_jof_le_sh24, k_jof_le_sh8, and RA8_INTERNAL.

Referenced by internal_png_dims().

◆ internal_sink()

ra8_err_t internal_sink ( jof_prod_state_t * st,
const uint8_t * buf,
size_t len )
static

Append bytes to the caller sink, tracking the atlas offset.

Guards the u32 atlas size cap before delegating to the caller sink.

Parameters
[in,out]stProducer state (written advances).
[in]bufBytes to append.
[in]lenByte count.
Returns
Result code.
Return values
k_ra8_okBytes sunk and accounted.
k_ra8_err_invalid_sizeThe atlas would exceed the u32 format cap.
otherPropagated from the caller sink.
Precondition
buf holds len readable bytes.
st->cfg->sink is bound.
Postcondition
On success st->written grew by len.
On error the transcode aborts (partial atlas discarded).
Note
Not thread-safe.
Since
0.1.0

Definition at line 166 of file jof_produce.c.

References jof_prod_state_t::cfg, k_ra8_err_invalid_size, k_ra8_ok, RA8_INTERNAL, jof_produce_cfg_t::sink, jof_produce_cfg_t::sink_ctx, and jof_prod_state_t::written.

Referenced by internal_emit_header(), internal_encode_tile(), and internal_finish().

◆ internal_sniff_head()

ra8_err_t internal_sniff_head ( const jof_produce_cfg_t * cfg,
uint8_t * head )
static

Pull the sniff head (both formats need at least these bytes).

Loops the pull seam until the fixed sniff length arrives (bounded by that length).

Parameters
[in]cfgCaller configuration.
[out]headReceives k_jof_sniff_bytes source bytes.
Returns
Result code.
Return values
k_ra8_okHead filled.
k_ra8_err_protocol_errorThe source is too short to be an image.
otherPropagated from the pull callback.
Precondition
head holds k_jof_sniff_bytes writable bytes.
The source is positioned at byte 0.
Postcondition
On success the head bytes are consumed from the source.
On error the transcode aborts.
Note
Not thread-safe.
Since
0.1.0

Definition at line 686 of file jof_produce.c.

References k_jof_sniff_bytes, k_ra8_err_protocol_error, k_ra8_ok, jof_produce_cfg_t::pull, jof_produce_cfg_t::pull_ctx, and RA8_INTERNAL.

Referenced by jof_produce().

◆ internal_wr_u16()

void internal_wr_u16 ( uint8_t * buf,
uint16_t v )
static

Store a uint16 little-endian at buf.

Serializes v as two little-endian bytes.

Parameters
[out]bufDestination (2 writable bytes).
[in]vValue to store.
Precondition
buf holds 2 writable bytes.
None (total over uint16_t).
Postcondition
buf[0..1] holds v little-endian.
No other state mutated.
Note
Pure over its output; thread-safe.
Since
0.1.0

Definition at line 121 of file jof_produce.c.

References k_jof_byte_mask, k_jof_le_sh8, and RA8_INTERNAL.

Referenced by internal_emit_header().

◆ internal_wr_u32()

void internal_wr_u32 ( uint8_t * buf,
uint32_t v )
static

Store a uint32 little-endian at buf.

Serializes v as four little-endian bytes.

Parameters
[out]bufDestination (4 writable bytes).
[in]vValue to store.
Precondition
buf holds 4 writable bytes.
None (total over uint32_t).
Postcondition
buf[0..3] holds v little-endian.
No other state mutated.
Note
Pure over its output; thread-safe.
Since
0.1.0

Definition at line 140 of file jof_produce.c.

References k_jof_byte_mask, k_jof_le_sh16, k_jof_le_sh24, k_jof_le_sh8, and RA8_INTERNAL.

Referenced by internal_emit_header(), internal_encode_tile(), and internal_finish().

◆ jof_probe_dims()

ra8_err_t jof_probe_dims ( const uint8_t * data,
size_t len,
uint16_t * out_w,
uint16_t * out_h )
nodiscard

Read a source image's pixel dimensions without decoding its body.

Sniffs the same three magics jof_produce() dispatches on (JPEG SOI, PNG signature, WebP RIFF+WEBP) and returns the declared geometry from the matching header: the JPEG SOF, the PNG IHDR, or the WebP VP8/VP8L header via ra8_webp_get_info. Callers need this before producing, because the work-arena sizes and the tile width are all functions of the geometry – jof_work_bytes and jof_webp_work_bytes both take it as input.

The probe shares the producer's magic constants and accepts exactly the set the producer accepts, so "probe succeeded" and "produce will dispatch" cannot drift apart. A non-WebP RIFF (WAVE, AVI) is rejected rather than handed to the WebP reader.

Parameters
[in]dataEncoded source bytes (non-NULL).
[in]lenReadable byte count at data.
[out]out_wReceives the source width in pixels.
[out]out_hReceives the source height in pixels.
Returns
Result code.
Return values
k_ra8_okDimensions read; both outputs written.
k_ra8_err_null_ptrdata, out_w or out_h is NULL.
k_ra8_err_not_supportedToo short to sniff, header truncated, or the magic is not JPEG / PNG / WebP.
k_ra8_err_invalid_sizeA dimension is zero or exceeds k_jof_max_dim.
otherPropagated from the per-format reader.
Precondition
data holds len readable bytes.
out_w and out_h point at writable storage.
Postcondition
On k_ra8_ok both *out_w and *out_h are in [1, k_jof_max_dim].
On any error neither output is relied upon and no state is mutated.
Note
Thread-safe (pure; reads only the caller's buffer).
Example:
uint16_t w = 0U, h = 0U;
if (jof_probe_dims(src, src_len, &w, &h) == k_ra8_ok) {
const uint32_t work = jof_work_bytes(w, h, w, tile_h);
}
ra8_err_t jof_probe_dims(const uint8_t *data, size_t len, uint16_t *out_w, uint16_t *out_h)
Read a source image's pixel dimensions without decoding its body.
uint32_t jof_work_bytes(uint16_t max_width, uint16_t max_height, uint16_t tile_w, uint16_t tile_h)
Compute the work-arena size the producer needs for given caps.
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
See also
jof_produce()
jof_work_bytes()
jof_webp_work_bytes()
Since
0.1.0

Definition at line 895 of file jof_produce.c.

References internal_probe_sniff(), RA8_CHECK_NULL_PTR, and s_tag.

Referenced by internal_jof_one(), and jof_worker_convert().

◆ jof_produce()

ra8_err_t jof_produce ( const jof_produce_cfg_t * cfg,
jof_info_t * out_info )
nodiscard

Transcode one encoded JPEG/PNG/WebP source into a JOF atlas (#231, #290).

Sniffs the source magic (JPEG SOI, PNG signature, or WebP RIFF/WEBP), then:

  • JPEG/PNG stream through the matching bounded stripe decoder, so the whole decoded image is never resident – every internal buffer (decoder window/stripe set, band, tile stage, compressor state, index) is carved from work, and the RAM high-water is exactly work_cap bytes, independent of the image.
  • WebP decodes whole-frame through the ra8_webp facade into the caller's webp_work arena (source + RGBA frame + libwebp scratch), then bands that frame through the identical tile path. webp_work == NULL rejects WebP with k_ra8_err_not_supported.

Either way the rows are accumulated into one band, each tile is cut + encoded through the configured (lossless) codec, and header / tiles / index / footer are appended to the sink in one forward pass. On success out_info describes the finished atlas exactly as jof_parse() would report it, and the atlas is byte-identical across source codecs that decode to the same pixels.

Parameters
[in]cfgProducer configuration (see the struct contract).
[out]out_infoReceives the finished atlas geometry.
Returns
ra8_err_t
Return values
k_ra8_okAtlas fully written to the sink.
k_ra8_err_null_ptrA required pointer in cfg is NULL.
k_ra8_err_invalid_argZero tile geometry or unknown codec.
k_ra8_err_invalid_sizeSource exceeds the budget caps, the grid exceeds the tile cap, or work / webp_work is too small (fail-closed).
k_ra8_err_not_supportedSource format not JPEG/PNG/WebP, a WebP source with no webp_work arena, a WebP axis over the 8192 cap, or an unsupported variant (progressive, interlaced, 16-bit, ...).
k_ra8_err_protocol_errorMalformed / truncated / hostile source structure.
k_ra8_err_validation_failedPixel-stream inconsistency (row count, inflate size, palette index).
otherPropagated from pull / sink.
Precondition
cfg->work covers work_cap bytes sized per jof_work_bytes().
cfg->pull delivers the encoded source strictly in order, once.
Postcondition
On success the sink holds one complete, parseable JOF atlas.
On any error the sink holds a partial atlas that must be discarded (it will fail jof_parse() – no torn atlas is readable).
Note
Not thread-safe (module-static decoder contexts).
Example:
jof_memstore_t store = { .buf = sdram_buf, .cap = sizeof sdram_buf };
.pull = epub_entry_pull, .pull_ctx = &cursor,
.sink = jof_memstore_sink, .sink_ctx = &store,
.tile_w = 256, .tile_h = 256,
.max_width = 8192, .max_height = 16384,
.work = arena, .work_cap = sizeof arena,
};
ra8_err_t err = jof_produce(&cfg, &info);
@ k_jof_codec_deflate
Tile stream is one raw-DEFLATE run.
Definition jof.h:192
ra8_err_t jof_memstore_sink(void *ctx, const uint8_t *buf, size_t len)
Append len bytes to a jof_memstore_t (producer sink).
Definition jof.c:163
ra8_err_t jof_produce(const jof_produce_cfg_t *cfg, jof_info_t *out_info)
Transcode one encoded JPEG/PNG/WebP source into a JOF atlas (#231, #290).
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
Parsed + validated geometry of one JOF atlas.
Definition jof.h:208
Append-only memory store: the simplest atlas backing (RAM/SDRAM).
Definition jof.h:256
Producer configuration: source, sink, tile geometry and work arena.
See also
jof_parse() Validate / reopen the produced atlas.
jof_read_tile() Page tiles back in bounded RAM.
Since
0.1.0

Definition at line 964 of file jof_produce.c.

References internal_check_cfg(), internal_dispatch(), internal_epilogue(), internal_init_state(), internal_produce_args_ok(), internal_sniff_head(), k_jof_sniff_bytes, k_ra8_ok, jof_produce_cfg_t::pull, and jof_produce_cfg_t::pull_ctx.

Referenced by internal_jof_produce_page(), internal_produce(), mg_build_atlas(), ra8_fmt_jof_convert_stream(), and worker_produce_to_file().

◆ jof_work_bytes()

uint32_t jof_work_bytes ( uint16_t max_width,
uint16_t max_height,
uint16_t tile_w,
uint16_t tile_h )
nodiscard

Compute the work-arena size the producer needs for given caps.

Sums the worst of the two decoder carve sets (JPEG window + stripe vs PNG inflate state + ring + rows) with the band, tile stage, compressed-tile bound, deflate scratch and tile index for the given budget caps, plus per-carve alignment slack. Passing the same caps here and in the config guarantees jof_produce() never fails on arena exhaustion for an in-budget source.

Parameters
[in]max_widthLargest source width to support (>= 1, <= cap).
[in]max_heightLargest source height to support (>= 1, <= cap).
[in]tile_wTile width the producer will use (>= 1).
[in]tile_hTile height the producer will use (>= 1).
Returns
Required arena size in bytes, or 0 on nonsense inputs.
Return values
0An argument was zero or exceeded k_jof_max_dim, or the tile grid would exceed k_jof_max_tiles.
>0Byte size to allocate for work.
Precondition
Arguments describe the caller's real budget caps.
The same tile_w/tile_h will be used in the produce config.
Postcondition
No state mutated.
A work_cap of the returned size never exhausts mid-transcode.
Note
Thread-safe (pure).
See also
jof_produce()
Since
0.1.0

Definition at line 590 of file jof_produce.c.

References jof_stored_bound(), k_jof_bpp_max, k_jof_carve_slack, k_jof_index_entry, k_jof_max_dim, k_jof_max_tiles, k_jof_png_inbuf, k_jof_png_ring, k_ra8_compress_scratch_bytes, k_ra8_jpeg_sw_stream_mcu_rows_max, and k_ra8_jpeg_sw_stream_min_window.

Referenced by internal_jof_one(), jof_worker_convert(), mg_build_atlas(), ra8_fmt_jof_convert_requirements(), and ra8_fmt_jof_verify_requirements().

◆ priv_jof_bump_take()

void * priv_jof_bump_take ( jof_bump_t * bump,
size_t len )

Implementation of priv_jof_bump_take() – aligned linear carve.

Carve len 8-byte-aligned bytes from the bump arena.

Definition at line 89 of file jof_produce.c.

References jof_bump_t::base, jof_bump_t::cap, k_jof_bump_align, jof_bump_t::off, and RA8_PRIV.

Referenced by internal_carve_pixel_path(), internal_dispatch(), internal_init_state(), internal_jpeg_geom(), and internal_png_bind_geometry().

◆ priv_jof_on_geom()

ra8_err_t priv_jof_on_geom ( void * ctx,
uint16_t width,
uint16_t height,
uint8_t channels )

Bind the source geometry: validate caps, carve buffers, emit header.

Fires once per transcode (from either decoder). Rejects, fail closed: dimensions above the caps, a tile grid above the format cap, and any carve the arena cannot fit. On success the 32-byte JOF header has been sunk.

Parameters
[in]ctxThe producer state.
[in]widthSource width, pixels.
[in]heightSource height, pixels.
[in]channelsOutput bytes per pixel (1, 3 or 4).
Returns
Result code.
Return values
k_ra8_okGeometry bound; header written.
k_ra8_err_invalid_sizeOver the caps / grid cap / arena exhausted.
k_ra8_err_invalid_stateThe geometry hook fired twice.
otherPropagated from the sink.
Precondition
The decoder validated width/height non-zero.
st->cfg and st->bump are bound.
Postcondition
On success band/stage/cmp/idx are carved and header sunk.
On error the transcode aborts.
Note
Not thread-safe.
Since
0.1.0

Definition at line 301 of file jof_produce.c.

References jof_prod_state_t::bpp, jof_prod_state_t::cap_h, jof_prod_state_t::cap_w, jof_prod_state_t::cfg, jof_prod_state_t::geom_done, jof_prod_state_t::h, internal_carve_pixel_path(), internal_emit_header(), k_jof_max_tiles, k_ra8_err_invalid_size, k_ra8_err_invalid_state, k_ra8_ok, RA8_PRIV, jof_prod_state_t::tile_cols, jof_prod_state_t::tile_count, jof_produce_cfg_t::tile_h, jof_prod_state_t::tile_rows, jof_produce_cfg_t::tile_w, and jof_prod_state_t::w.

Referenced by internal_dispatch(), internal_jpeg_geom(), and priv_jof_webp_transcode().

◆ priv_jof_on_rows()

ra8_err_t priv_jof_on_rows ( void * ctx,
const uint8_t * px,
uint16_t width,
uint16_t y0,
uint16_t nrows,
uint8_t channels )

Row sink shared by every decoder arm: accumulate, flush full bands.

Enforces the strict in-order row contract (y0 == rows_seen), then copies the delivered rows into the band, flushing a tile row every time the band fills. A row group may span a band boundary; the copy loop splits it. Matches jof_rows_fn.

Parameters
[in]ctxThe producer state (jof_prod_state_t).
[in]pxDecoded row pixels.
[in]widthRow width, pixels.
[in]y0Image row of the first delivered row.
[in]nrowsRows delivered.
[in]channelsBytes per pixel.
Returns
Result code.
Return values
k_ra8_okRows accumulated (bands maybe flushed).
k_ra8_err_validation_failedContract violation (order, geometry).
otherPropagated from the flush stage.
Precondition
The geometry hook has fired (geom_done == 1).
px holds nrows * width * channels bytes.
Postcondition
rows_seen advanced by nrows on success.
On error the transcode aborts.
Note
Not thread-safe.
Since
0.1.0

Definition at line 418 of file jof_produce.c.

References jof_prod_state_t::band, jof_prod_state_t::band_fill, jof_prod_state_t::bpp, jof_prod_state_t::cfg, jof_prod_state_t::geom_done, jof_prod_state_t::h, internal_flush_band(), k_ra8_err_validation_failed, k_ra8_ok, memcpy(), RA8_CHECK_NULL_PTR, RA8_PRIV, jof_prod_state_t::rows_seen, s_tag, jof_produce_cfg_t::tile_h, and jof_prod_state_t::w.

Referenced by internal_dispatch(), and internal_webp_feed().

◆ priv_jof_prefix_pull()

ra8_err_t priv_jof_prefix_pull ( void * ctx,
uint8_t * buf,
size_t cap,
size_t * got )

Pull adapter: replay the sniffed head, then delegate to the source.

Serves the replay bytes first, then transparently delegates to the inner source. Matches jof_pull_fn so it can be passed as the pull seam to any decoder.

Parameters
[in]ctxA jof_prefix_pull_t.
[out]bufDestination buffer.
[in]capCapacity of buf.
[out]gotBytes delivered.
Returns
Result code.
Return values
k_ra8_okDelivered replay or source bytes.
otherPropagated from the inner source.
Precondition
ctx points at an initialised adapter.
buf holds cap writable bytes.
Postcondition
*got <= cap bytes were written to buf.
The replay cursor never exceeds the head length.
Note
Not thread-safe.
Since
0.1.0

Definition at line 184 of file jof_produce.c.

References jof_prefix_pull_t::head, jof_prefix_pull_t::head_len, jof_prefix_pull_t::inner, jof_prefix_pull_t::inner_ctx, k_ra8_ok, memcpy(), jof_prefix_pull_t::pos, and RA8_PRIV.

Referenced by internal_dispatch(), and internal_webp_pull_all().

Variable Documentation

◆ s_prod_png_sig

const uint8_t s_prod_png_sig[k_jof_png_sig_len]
static
Initial value:
'P',
'N',
'G',
@ k_jof_png_sig_cr
Carriage return byte.
Definition jof_produce.c:67
@ k_jof_png_sig_sub
DOS EOF byte.
Definition jof_produce.c:69
@ k_jof_png_sig_lf
Line feed byte.
Definition jof_produce.c:68
@ k_jof_png_sig_high
High-bit signature byte.
Definition jof_produce.c:66

PNG signature for source sniffing (mirrors the PNG decoder unit).

Definition at line 73 of file jof_produce.c.

Referenced by internal_dispatch(), and internal_probe_sniff().

◆ s_prod_webp_riff

const uint8_t s_prod_webp_riff[k_jof_magic_len] = {'R', 'I', 'F', 'F'}
static

WebP RIFF container tag (source head bytes 0..3).

Definition at line 83 of file jof_produce.c.

Referenced by internal_dispatch(), and internal_is_webp().

◆ s_prod_webp_webp

const uint8_t s_prod_webp_webp[k_jof_magic_len] = {'W', 'E', 'B', 'P'}
static

WebP form-type fourCC (source head bytes 8..11).

Definition at line 86 of file jof_produce.c.

Referenced by internal_dispatch(), and internal_is_webp().

◆ s_tag

const char* const s_tag = "jof_prod"
static

Module log tag.

Definition at line 41 of file jof_produce.c.