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

Pure-software baseline JPEG decoder: marker parser and scan. More...

#include <stdint.h>
#include <string.h>
#include "ra8_attributes.h"
#include "ra8_check.h"
#include "ra8_err.h"
#include "ra8_jpeg_sw.h"
#include "ra8_jpeg_sw_internal.h"
Include dependency graph for ra8_jpeg_sw_decode.c:

Go to the source code of this file.

Functions

ra8_err_t priv_jpeg_sw_skip_segment (ra8_jpeg_dec_ctx_t *d)
 Implementation of priv_jpeg_sw_skip_segment() – bounds-checked cursor hop.
ra8_err_t priv_jpeg_sw_parse_dqt (ra8_jpeg_dec_ctx_t *d)
 Implementation of priv_jpeg_sw_parse_dqt() – T.81 B.2.4.1 de-zigzag parse.
static ra8_err_t internal_dec_parse_dht_one (ra8_jpeg_dec_ctx_t *d, uint32_t end)
 Parse one (TcTh, BITS, HUFFVAL) table out of a DHT segment.
ra8_err_t priv_jpeg_sw_parse_dht (ra8_jpeg_dec_ctx_t *d)
 Implementation of priv_jpeg_sw_parse_dht() – T.81 B.2.4.2 record loop.
static void internal_dec_parse_sof0_components (ra8_jpeg_dec_ctx_t *d, uint32_t *s)
 Read the per-component id/sampling/quant fields of an SOF0.
static ra8_err_t internal_dec_check_chroma_layout (const ra8_jpeg_dec_ctx_t *d)
 Accept only the 4:4:4 and 4:2:0 3-component chroma layouts.
ra8_err_t priv_jpeg_sw_parse_sof0 (ra8_jpeg_dec_ctx_t *d)
 Implementation of priv_jpeg_sw_parse_sof0() – T.81 B.2.2 frame header.
ra8_err_t priv_jpeg_sw_parse_sos (ra8_jpeg_dec_ctx_t *d)
 Implementation of priv_jpeg_sw_parse_sos() – T.81 B.2.3 selector binding.
static ra8_err_t internal_dec_block_ac (ra8_jpeg_dec_ctx_t *d, ra8_jpeg_bitreader_t *br, uint8_t ci, int32_t *outblk)
 Run-length decode the 63 AC coefficients of one block.
ra8_err_t priv_jpeg_sw_block (ra8_jpeg_dec_ctx_t *d, ra8_jpeg_bitreader_t *br, uint8_t ci, int32_t *outblk)
 Implementation of priv_jpeg_sw_block() – T.81 F.2.2 DC diff + AC run-length.
void priv_jpeg_sw_idct_into (int32_t *coeffs, uint8_t *tile)
 Implementation of priv_jpeg_sw_idct_into() – IDCT + level shift + clamp.
static void internal_dec_copy_block_to_tile (const uint8_t *blk, uint8_t *y_tile, uint8_t bx, uint8_t by, uint16_t mcu_w_px)
 Copy one reconstructed 8x8 luma block into its Y-tile slot.
ra8_err_t priv_jpeg_sw_mcu_y (ra8_jpeg_dec_ctx_t *d, ra8_jpeg_bitreader_t *br, uint8_t *y_tile, uint16_t mcu_w_px)
 Implementation of priv_jpeg_sw_mcu_y() – hmax*vmax luma block loop.
ra8_err_t priv_jpeg_sw_mcu_chroma (ra8_jpeg_dec_ctx_t *d, ra8_jpeg_bitreader_t *br, uint8_t *cb_tile, uint8_t *cr_tile)
 Implementation of priv_jpeg_sw_mcu_chroma() – one Cb then one Cr block.
static void internal_dec_emit_mcu_rgb (const ra8_jpeg_dec_ctx_t *d, const uint8_t *y_tile, const uint8_t *cb_tile, const uint8_t *cr_tile, uint16_t mx, uint16_t my, uint16_t mcu_w_px, uint16_t mcu_h_px, uint8_t *out_buf)
 Convert one MCU's reconstructed YCbCr tiles into output RGB pixels.
static ra8_err_t internal_dec_decode_mcu (ra8_jpeg_dec_ctx_t *d, ra8_jpeg_bitreader_t *br, uint8_t *y_tile, uint8_t *cb_tile, uint8_t *cr_tile, uint16_t mx, uint16_t my, uint16_t mcu_w_px, uint16_t mcu_h_px, uint8_t *out_buf)
 Decode one MCU (luma + optional chroma) and emit its RGB pixels.
static void internal_dec_scan_begin (ra8_jpeg_dec_ctx_t *d, ra8_jpeg_bitreader_t *br)
 Prime the bit reader and reset the DC predictors for a scan.
static ra8_err_t internal_dec_decode_scan (ra8_jpeg_dec_ctx_t *d, uint8_t *out_buf, uint32_t out_buf_len)
 Decode the whole entropy-coded segment, MCU by MCU.
static ra8_err_t internal_dec_dispatch_tail (ra8_jpeg_dec_ctx_t *d, uint16_t mk, bool got_sof, ra8_jpeg_dec_marker_action_t *action)
 Handle a non-SOF marker in the decode dispatch chain.
ra8_err_t priv_jpeg_sw_dispatch (ra8_jpeg_dec_ctx_t *d, bool *got_sof, ra8_jpeg_dec_marker_action_t *action)
 Implementation of priv_jpeg_sw_dispatch() – marker extraction + routing.
static ra8_err_t internal_dec_run (ra8_jpeg_dec_ctx_t *d, uint8_t *out_buf, uint32_t out_buf_len, uint16_t *out_w, uint16_t *out_h)
 Marker-walk driver for the whole-buffer decode.
ra8_err_t ra8_jpeg_sw_decode (const uint8_t *jpeg_buf, uint32_t jpeg_len, uint8_t *out_buf, uint32_t out_buf_len, uint16_t *out_w, uint16_t *out_h)
 Decode a baseline JPEG stream into packed RGB888.

Variables

static const char * s_tag = "JPEG_SW"
 Component log tag.

Detailed Description

Pure-software baseline JPEG decoder: marker parser and scan.

Tag
[Ring 4 / Domain] {World: NS}

Implements the marker-segment parser (DQT / DHT / SOF0 / SOS), the per-MCU entropy-decode + IDCT + colour-conversion scan loop, and the ra8_jpeg_sw_decode() public API for baseline (8-bit, sequential, Huffman) JPEG streams in the YCbCr 4:2:0, YCbCr 4:4:4 and grayscale layouts. The reference codec is the C99 reformulation of "TJpgDec" by ChaN, re-implemented from scratch in this project's style; no third-party code is copied.

This is the decoder-driver half of the software JPEG codec; the shared entropy/DSP primitives (bit reader, Huffman tables, inverse DCT, colour conversion) and the ra8_jpeg_sw_get_dimensions() public API live in ra8_jpeg_sw.c, and every cross-unit symbol lives in ra8_jpeg_sw_internal.h.

Spec citations are tagged T.81 sec X.Y "..." and refer to ITU-T Recommendation T.81 (1992) | ISO/IEC 10918-1.

Since
0.1.0

Definition in file ra8_jpeg_sw_decode.c.

Function Documentation

◆ internal_dec_block_ac()

ra8_err_t internal_dec_block_ac ( ra8_jpeg_dec_ctx_t * d,
ra8_jpeg_bitreader_t * br,
uint8_t ci,
int32_t * outblk )
static

Run-length decode the 63 AC coefficients of one block.

Implements the T.81 sec F.2.2.2 AC decode loop: each Huffman symbol packs a zero-run nibble (RRRR) and a magnitude-bit count (SSSS); ZRL (0xF0) skips 16 zeros, SSSS == 0 with RRRR == 0 is EOB. Each non-zero coefficient is sign-extended, dequantized through the component's quant table and de-zigzagged into outblk.

Parameters
[in,out]dDecoder context (read-only tables used).
[in,out]brBit reader over the entropy-coded segment.
[in]ciComponent index (0 = luma).
[out]outblk64-entry coefficient block (AC slots written).
Returns
ra8_err_t Error code.
Return values
k_ra8_okAC coefficients decoded (or EOB hit).
k_ra8_err_protocol_errorStream underflow, illegal symbol, or zig-zag index overflow.
Precondition
outblk was zero-filled and DC-populated by the caller.
d's AC Huffman/quant tables for ci were parsed.
Postcondition
On success every non-zero AC coefficient is dequantized in place.
On error the scan aborts.
Note
Internal helper; not thread-safe.
Since
0.1.0

Definition at line 359 of file ra8_jpeg_sw_decode.c.

References ra8_jpeg_dec_ctx_t::comp_ac_id, ra8_jpeg_dec_ctx_t::comp_qid, ra8_jpeg_dec_ctx_t::hac, k_jpeg_nibble_mask, k_ra8_err_protocol_error, k_ra8_jpeg_block_size, k_ra8_jpeg_nibble_mask, k_ra8_jpeg_nibble_shift, k_ra8_ok, priv_jpeg_sw_br_get_bits(), priv_jpeg_sw_htab_decode(), priv_jpeg_sw_huff_extend(), ra8_jpeg_dec_ctx_t::qtab, and s_zigzag.

Referenced by priv_jpeg_sw_block().

◆ internal_dec_check_chroma_layout()

ra8_err_t internal_dec_check_chroma_layout ( const ra8_jpeg_dec_ctx_t * d)
static

Accept only the 4:4:4 and 4:2:0 3-component chroma layouts.

Applies the codec's format envelope to the sampling factors parsed from SOF0: for 3-component streams only 4:4:4 (all 1x1) and 4:2:0 (luma 2x2, both chromas 1x1) are decodable; grayscale streams pass unconditionally.

Parameters
[in]dDecoder context with ncomp/hmax/vmax/comp_* set.
Returns
ra8_err_t Error code.
Return values
k_ra8_okLayout is 4:4:4, 4:2:0 or grayscale.
k_ra8_err_not_supportedAny other chroma layout.
Precondition
d is non-NULL (module-internal call chain).
internal_dec_parse_sof0_components() ran for this frame.
Postcondition
No decoder state is mutated.
Return value fully determines whether the scan may proceed.
Note
Internal helper; not thread-safe.
Since
0.1.0

Definition at line 243 of file ra8_jpeg_sw_decode.c.

References ra8_jpeg_dec_ctx_t::comp_h, ra8_jpeg_dec_ctx_t::comp_v, ra8_jpeg_dec_ctx_t::hmax, k_ra8_err_not_supported, k_ra8_ok, ra8_jpeg_dec_ctx_t::ncomp, RA8_INTERNAL, and ra8_jpeg_dec_ctx_t::vmax.

Referenced by priv_jpeg_sw_parse_sof0().

◆ internal_dec_copy_block_to_tile()

void internal_dec_copy_block_to_tile ( const uint8_t * blk,
uint8_t * y_tile,
uint8_t bx,
uint8_t by,
uint16_t mcu_w_px )
static

Copy one reconstructed 8x8 luma block into its Y-tile slot.

Writes the 64 samples of blk into the (bx, by) sub-rectangle of the MCU's luma tile, whose rows are mcu_w_px samples wide, so the MCU pixel-emit loop can address the tile linearly.

Parameters
[in]blk64-byte reconstructed luma block (row-major).
[out]y_tileDestination MCU luma tile.
[in]bxBlock column inside the MCU (0..hmax-1).
[in]byBlock row inside the MCU (0..vmax-1).
[in]mcu_w_pxMCU width in pixels (tile row stride).
Precondition
blk holds 64 valid samples.
y_tile covers mcu_w_px * 8 * (by + 1) bytes.
Postcondition
The (bx, by) sub-rectangle of y_tile is populated.
No other tile bytes are touched.
Note
Internal helper; not thread-safe.
Since
0.1.0

Definition at line 456 of file ra8_jpeg_sw_decode.c.

References k_ra8_jpeg_block_dim, and RA8_INTERNAL.

Referenced by priv_jpeg_sw_mcu_y().

◆ internal_dec_decode_mcu()

ra8_err_t internal_dec_decode_mcu ( ra8_jpeg_dec_ctx_t * d,
ra8_jpeg_bitreader_t * br,
uint8_t * y_tile,
uint8_t * cb_tile,
uint8_t * cr_tile,
uint16_t mx,
uint16_t my,
uint16_t mcu_w_px,
uint16_t mcu_h_px,
uint8_t * out_buf )
static

Decode one MCU (luma + optional chroma) and emit its RGB pixels.

Loop body of internal_dec_decode_scan(): entropy-decodes the MCU's hmax*vmax luma blocks into y_tile, the Cb/Cr pair for 3-component streams, and converts the reconstructed tiles into output RGB at MCU position (mx, my).

Parameters
[in,out]dDecoder context (DC predictors mutate).
[in,out]brBit reader over the entropy-coded segment.
[out]y_tileScratch luma tile (mcu_w_px * mcu_h_px bytes).
[out]cb_tileScratch 64-byte Cb tile.
[out]cr_tileScratch 64-byte Cr tile.
[in]mxMCU column index in the output image.
[in]myMCU row index in the output image.
[in]mcu_w_pxMCU width in pixels.
[in]mcu_h_pxMCU height in pixels.
[out]out_bufDestination RGB888 image buffer.
Returns
ra8_err_t Error code.
Return values
k_ra8_okMCU decoded and emitted.
k_ra8_err_protocol_errorEntropy-stream error in any block.
Precondition
All tile buffers are sized for the stream's sampling layout.
out_buf covers the full decoded image (caller-checked).
Postcondition
On success the MCU's visible pixels are written to out_buf.
On error the scan aborts; already-emitted pixels stay valid.
Note
Internal helper; not thread-safe.
Since
0.1.0

Definition at line 613 of file ra8_jpeg_sw_decode.c.

References internal_dec_emit_mcu_rgb(), k_ra8_ok, ra8_jpeg_dec_ctx_t::ncomp, priv_jpeg_sw_mcu_chroma(), priv_jpeg_sw_mcu_y(), and RA8_INTERNAL.

Referenced by internal_dec_decode_scan().

◆ internal_dec_decode_scan()

ra8_err_t internal_dec_decode_scan ( ra8_jpeg_dec_ctx_t * d,
uint8_t * out_buf,
uint32_t out_buf_len )
static

Decode the whole entropy-coded segment, MCU by MCU.

T.81 sec F.2.2 scan decode: sizes the MCU grid from the SOF0 sampling factors, primes the bit reader and DC predictors via internal_dec_scan_begin(), then walks every MCU through internal_dec_decode_mcu(), which reconstructs and emits its RGB pixels.

Parameters
[in,out]dDecoder context (cursor lands after the scan).
[out]out_bufDestination RGB888 image buffer.
[in]out_buf_lenCapacity of out_buf in bytes.
Returns
ra8_err_t Error code.
Return values
k_ra8_okWhole image decoded.
k_ra8_err_invalid_sizeout_buf smaller than w*h*3 bytes.
k_ra8_err_protocol_errorEntropy-stream error in any MCU.
Precondition
A successful SOF0 + SOS parse preceded this call.
d->cursor sits at the first entropy-coded byte.
Postcondition
On success d->cursor advanced past the scan data.
On error already-emitted pixels remain valid in out_buf.
Note
Internal helper; not thread-safe.
Since
0.1.0

Definition at line 697 of file ra8_jpeg_sw_decode.c.

References ra8_jpeg_dec_ctx_t::cursor, ra8_jpeg_dec_ctx_t::height, ra8_jpeg_dec_ctx_t::hmax, internal_dec_decode_mcu(), internal_dec_scan_begin(), k_ra8_err_invalid_size, k_ra8_jpeg_block_dim, k_ra8_jpeg_block_size, k_ra8_jpeg_mcu_max_dim, k_ra8_jpeg_rgb_components, k_ra8_ok, ra8_jpeg_bitreader_t::pos, RA8_ASSERT, ra8_jpeg_dec_ctx_t::vmax, and ra8_jpeg_dec_ctx_t::width.

Referenced by internal_dec_run().

◆ internal_dec_dispatch_tail()

ra8_err_t internal_dec_dispatch_tail ( ra8_jpeg_dec_ctx_t * d,
uint16_t mk,
bool got_sof,
ra8_jpeg_dec_marker_action_t * action )
static

Handle a non-SOF marker in the decode dispatch chain.

Tail of priv_jpeg_sw_dispatch(): routes the already-extracted marker code to the DQT/DHT/SOS parsers, flags EOI, consumes RST markers as standalone bytes, and skips unrecognized APPn/COM segments via priv_jpeg_sw_skip_segment().

Parameters
[in,out]dDecoder context (cursor advances).
[in]mkMarker code (0xFFxx) to route.
[in]got_sofWhether SOF0 has been parsed yet.
[out]actionWhat the driver should do next.
Returns
ra8_err_t Error code.
Return values
k_ra8_okMarker handled (see *action).
k_ra8_err_protocol_errorMalformed payload or SOS before SOF.
k_ra8_err_not_supportedPropagated from the segment parsers.
Precondition
mk is not SOF0 and not an unsupported SOFn (caller-routed).
*action was preset to k_ra8_jpeg_dec_continue.
Postcondition
d->cursor advanced past any sized payload.
*action is a ra8_jpeg_dec_marker_action_t value.
Note
Internal helper; not thread-safe.
Since
0.1.0

Definition at line 776 of file ra8_jpeg_sw_decode.c.

References k_ra8_err_protocol_error, k_ra8_jpeg_dec_eoi, k_ra8_jpeg_dec_scan, k_ra8_jpeg_marker_dht, k_ra8_jpeg_marker_dqt, k_ra8_jpeg_marker_eoi, k_ra8_jpeg_marker_rst0, k_ra8_jpeg_marker_rst7, k_ra8_jpeg_marker_sos, k_ra8_ok, priv_jpeg_sw_parse_dht(), priv_jpeg_sw_parse_dqt(), priv_jpeg_sw_parse_sos(), priv_jpeg_sw_skip_segment(), and RA8_INTERNAL.

Referenced by priv_jpeg_sw_dispatch().

◆ internal_dec_emit_mcu_rgb()

void internal_dec_emit_mcu_rgb ( const ra8_jpeg_dec_ctx_t * d,
const uint8_t * y_tile,
const uint8_t * cb_tile,
const uint8_t * cr_tile,
uint16_t mx,
uint16_t my,
uint16_t mcu_w_px,
uint16_t mcu_h_px,
uint8_t * out_buf )
static

Convert one MCU's reconstructed YCbCr tiles into output RGB pixels.

Walks every pixel of the MCU at output position (mx,my), pulling the matching Y sample from y_tile and the (sub-sampled) Cb/Cr samples from cb_tile/cr_tile according to the stream's hmax/vmax. For grayscale streams (ncomp == 1) the chroma samples default to the level-offset (128) so the BT.601 transform produces R==G==B==Y.

Parameters
[in]dDecoder context (provides hmax, vmax, width/height).
[in]y_tilemcu_w_px-stride buffer of Y samples for this MCU.
[in]cb_tile64-byte Cb tile (ignored when d->ncomp != 3).
[in]cr_tile64-byte Cr tile (ignored when d->ncomp != 3).
[in]mxMCU column index in the output image.
[in]myMCU row index in the output image.
[in]mcu_w_pxMCU width in pixels.
[in]mcu_h_pxMCU height in pixels.
[out]out_bufDestination RGB888 image buffer.
Returns
None.
Precondition
out_buf has space for d->width * d->height * 3 bytes.
mcu_w_px > 0 and mcu_h_px > 0.
Postcondition
out_buf updated only inside the visible region of this MCU.
No JPEG-stream state is modified.
Note
Not thread-safe; caller serializes via decoder context.
Since
0.1.0

Definition at line 542 of file ra8_jpeg_sw_decode.c.

References ra8_jpeg_dec_ctx_t::height, ra8_jpeg_dec_ctx_t::hmax, k_ra8_jpeg_block_dim, k_ra8_jpeg_level_offset, k_ra8_jpeg_rgb_components, ra8_jpeg_dec_ctx_t::ncomp, priv_jpeg_sw_ycc_to_rgb(), RA8_INTERNAL, ra8_jpeg_dec_ctx_t::vmax, and ra8_jpeg_dec_ctx_t::width.

Referenced by internal_dec_decode_mcu().

◆ internal_dec_parse_dht_one()

ra8_err_t internal_dec_parse_dht_one ( ra8_jpeg_dec_ctx_t * d,
uint32_t end )
static

Parse one (TcTh, BITS, HUFFVAL) table out of a DHT segment.

Consumes exactly one Huffman-table record starting at d->cursor (T.81 sec B.2.4.2): the TcTh selector byte, the 16-entry BITS list and the HUFFVAL symbol list, then canonical-builds the table via priv_jpeg_sw_htab_build(). Called in a loop by priv_jpeg_sw_parse_dht() until the segment is exhausted.

Parameters
[in,out]dDecoder context (cursor advances; table written).
[in]endOne-past-the-end offset of the DHT segment.
Returns
ra8_err_t Error code.
Return values
k_ra8_okOne table parsed and built.
k_ra8_err_protocol_errorTruncated record or symbol overflow.
k_ra8_err_not_supportedTable class / id out of range.
Precondition
d->cursor < end (caller's loop condition).
end <= d->src_len (validated by the caller).
Postcondition
On success d->cursor sits at the next record (or end).
On error the decode aborts; table state is partial.
Note
Internal helper; not thread-safe.
Since
0.1.0

Definition at line 124 of file ra8_jpeg_sw_decode.c.

References ra8_jpeg_htab_t::bits, ra8_jpeg_dec_ctx_t::cursor, ra8_jpeg_dec_ctx_t::hac, ra8_jpeg_dec_ctx_t::hdc, k_ra8_err_not_supported, k_ra8_err_protocol_error, k_ra8_jpeg_huff_classes, k_ra8_jpeg_huff_ids, k_ra8_jpeg_huff_lengths, k_ra8_jpeg_huff_max, k_ra8_jpeg_nibble_mask, k_ra8_jpeg_nibble_shift, k_ra8_ok, priv_jpeg_sw_htab_build(), RA8_INTERNAL, ra8_jpeg_dec_ctx_t::src, and ra8_jpeg_htab_t::vals.

Referenced by priv_jpeg_sw_parse_dht().

◆ internal_dec_parse_sof0_components()

void internal_dec_parse_sof0_components ( ra8_jpeg_dec_ctx_t * d,
uint32_t * s )
static

Read the per-component id/sampling/quant fields of an SOF0.

Consumes d->ncomp three-byte component records (T.81 sec B.2.2: Ci, HiVi, Tqi) starting at *s, filling the per-component arrays and folding the running hmax/vmax maxima exactly as the previous monolithic priv_jpeg_sw_parse_sof0() body did.

Parameters
[in,out]dDecoder context (component tables + hmax/vmax written).
[in,out]sByte cursor into the SOF0 payload (advances 3/comp).
Precondition
d->ncomp is 1 or 3 (validated by the caller).
The 3 * ncomp record bytes are inside the segment (caller-checked).
Postcondition
d->comp_*[0..ncomp-1] and d->hmax/d->vmax are populated.
*s advanced past the last component record.
Note
Internal helper; not thread-safe.
Since
0.1.0

Definition at line 198 of file ra8_jpeg_sw_decode.c.

References ra8_jpeg_dec_ctx_t::comp_h, ra8_jpeg_dec_ctx_t::comp_id, ra8_jpeg_dec_ctx_t::comp_qid, ra8_jpeg_dec_ctx_t::comp_v, ra8_jpeg_dec_ctx_t::hmax, k_ra8_jpeg_nibble_mask, k_ra8_jpeg_nibble_shift, ra8_jpeg_dec_ctx_t::ncomp, RA8_INTERNAL, ra8_jpeg_dec_ctx_t::src, and ra8_jpeg_dec_ctx_t::vmax.

Referenced by priv_jpeg_sw_parse_sof0().

◆ internal_dec_run()

ra8_err_t internal_dec_run ( ra8_jpeg_dec_ctx_t * d,
uint8_t * out_buf,
uint32_t out_buf_len,
uint16_t * out_w,
uint16_t * out_h )
static

Marker-walk driver for the whole-buffer decode.

Loops priv_jpeg_sw_dispatch() over the stream until an SOS hands off to internal_dec_decode_scan(), an EOI ends the walk without a scan (protocol error), or the stream is exhausted.

Parameters
[in,out]dInitialised decoder context (cursor at 2).
[out]out_bufDestination RGB888 buffer.
[in]out_buf_lenCapacity of out_buf in bytes.
[out]out_wReceives the image width on scan start.
[out]out_hReceives the image height on scan start.
Returns
ra8_err_t Error code.
Return values
k_ra8_okImage decoded into out_buf.
k_ra8_err_invalid_sizeout_buf too small for the frame.
k_ra8_err_protocol_errorMalformed stream or no scan found.
k_ra8_err_not_supportedNon-baseline stream feature.
Precondition
d->src/d->src_len describe an SOI-verified stream.
All output pointers are non-NULL (public API validated them).
Postcondition
On success *out_w/*out_h hold the SOF0 dimensions.
On error the output buffer contents are unspecified.
Note
Internal helper; not thread-safe.
Since
0.1.0

Definition at line 871 of file ra8_jpeg_sw_decode.c.

References ra8_jpeg_dec_ctx_t::cursor, ra8_jpeg_dec_ctx_t::height, internal_dec_decode_scan(), k_ra8_err_protocol_error, k_ra8_jpeg_dec_continue, k_ra8_jpeg_dec_eoi, k_ra8_jpeg_dec_scan, k_ra8_ok, priv_jpeg_sw_dispatch(), RA8_INTERNAL, ra8_jpeg_dec_ctx_t::src_len, and ra8_jpeg_dec_ctx_t::width.

Referenced by ra8_jpeg_sw_decode().

◆ internal_dec_scan_begin()

void internal_dec_scan_begin ( ra8_jpeg_dec_ctx_t * d,
ra8_jpeg_bitreader_t * br )
static

Prime the bit reader and reset the DC predictors for a scan.

Positions the entropy bit reader at the decoder cursor and zeroes every component's DC predictor, exactly as T.81 sec F.2.1.3.1 requires at the start of a scan.

Parameters
[in,out]dDecoder context (DC predictors reset).
[out]brBit reader to initialise over the scan data.
Precondition
d->cursor sits at the first entropy-coded byte (post-SOS).
br is non-NULL (module-internal call chain).
Postcondition
br reads from d->src starting at d->cursor.
All d->comp_dc_pred[] entries are zero.
Note
Internal helper; not thread-safe.
Since
0.1.0

Definition at line 657 of file ra8_jpeg_sw_decode.c.

References ra8_jpeg_bitreader_t::acc, ra8_jpeg_bitreader_t::buf, ra8_jpeg_dec_ctx_t::comp_dc_pred, ra8_jpeg_dec_ctx_t::cursor, ra8_jpeg_bitreader_t::had_eoi, k_ra8_jpeg_max_comps, ra8_jpeg_bitreader_t::len, ra8_jpeg_bitreader_t::nbits, ra8_jpeg_bitreader_t::pos, RA8_INTERNAL, ra8_jpeg_dec_ctx_t::src, and ra8_jpeg_dec_ctx_t::src_len.

Referenced by internal_dec_decode_scan().

◆ priv_jpeg_sw_block()

◆ priv_jpeg_sw_dispatch()

◆ priv_jpeg_sw_idct_into()

void priv_jpeg_sw_idct_into ( int32_t * coeffs,
uint8_t * tile )

Implementation of priv_jpeg_sw_idct_into() – IDCT + level shift + clamp.

IDCT a coefficient block and emit level-shifted 8-bit samples.

Definition at line 425 of file ra8_jpeg_sw_decode.c.

References internal_clamp_u8(), k_ra8_jpeg_block_size, k_ra8_jpeg_level_offset, priv_jpeg_sw_idct8x8(), and RA8_PRIV.

Referenced by priv_jpeg_sw_mcu_chroma(), and priv_jpeg_sw_mcu_y().

◆ priv_jpeg_sw_mcu_chroma()

ra8_err_t priv_jpeg_sw_mcu_chroma ( ra8_jpeg_dec_ctx_t * d,
ra8_jpeg_bitreader_t * br,
uint8_t * cb_tile,
uint8_t * cr_tile )

Implementation of priv_jpeg_sw_mcu_chroma() – one Cb then one Cr block.

Decode the Cb and Cr 8x8 blocks of one MCU.

Definition at line 493 of file ra8_jpeg_sw_decode.c.

References k_ra8_jpeg_block_size, k_ra8_ok, priv_jpeg_sw_block(), priv_jpeg_sw_idct_into(), and RA8_PRIV.

Referenced by internal_dec_decode_mcu(), and internal_js_decode_mcu().

◆ priv_jpeg_sw_mcu_y()

ra8_err_t priv_jpeg_sw_mcu_y ( ra8_jpeg_dec_ctx_t * d,
ra8_jpeg_bitreader_t * br,
uint8_t * y_tile,
uint16_t mcu_w_px )

Implementation of priv_jpeg_sw_mcu_y() – hmax*vmax luma block loop.

Decode the hmax*vmax luma blocks of one MCU into the Y tile.

Definition at line 472 of file ra8_jpeg_sw_decode.c.

References ra8_jpeg_dec_ctx_t::hmax, internal_dec_copy_block_to_tile(), k_ra8_jpeg_block_size, k_ra8_ok, priv_jpeg_sw_block(), priv_jpeg_sw_idct_into(), RA8_PRIV, and ra8_jpeg_dec_ctx_t::vmax.

Referenced by internal_dec_decode_mcu(), and internal_js_decode_mcu().

◆ priv_jpeg_sw_parse_dht()

ra8_err_t priv_jpeg_sw_parse_dht ( ra8_jpeg_dec_ctx_t * d)

Implementation of priv_jpeg_sw_parse_dht() – T.81 B.2.4.2 record loop.

Parse a DHT segment (T.81 sec B.2.4.2) and build its tables.

Definition at line 158 of file ra8_jpeg_sw_decode.c.

References ra8_jpeg_dec_ctx_t::cursor, internal_dec_parse_dht_one(), internal_read_be16(), k_ra8_err_protocol_error, k_ra8_ok, RA8_PRIV, ra8_jpeg_dec_ctx_t::src, and ra8_jpeg_dec_ctx_t::src_len.

Referenced by internal_dec_dispatch_tail().

◆ priv_jpeg_sw_parse_dqt()

◆ priv_jpeg_sw_parse_sof0()

◆ priv_jpeg_sw_parse_sos()

◆ priv_jpeg_sw_skip_segment()

ra8_err_t priv_jpeg_sw_skip_segment ( ra8_jpeg_dec_ctx_t * d)

Implementation of priv_jpeg_sw_skip_segment() – bounds-checked cursor hop.

Skip an unrecognized variable-length segment.

Definition at line 54 of file ra8_jpeg_sw_decode.c.

References ra8_jpeg_dec_ctx_t::cursor, internal_read_be16(), k_ra8_err_protocol_error, k_ra8_ok, RA8_PRIV, ra8_jpeg_dec_ctx_t::src, and ra8_jpeg_dec_ctx_t::src_len.

Referenced by internal_dec_dispatch_tail().

◆ ra8_jpeg_sw_decode()

ra8_err_t ra8_jpeg_sw_decode ( const uint8_t * jpeg_buf,
uint32_t jpeg_len,
uint8_t * out_buf,
uint32_t out_buf_len,
uint16_t * out_w,
uint16_t * out_h )
nodiscard

Decode a baseline JPEG stream into packed RGB888.

Performs full entropy decoding, dequantization, inverse DCT and YCbCr-to-RGB colour conversion (ITU-T T.871 JFIF colour conversion). The output buffer must be at least width * height * 3 bytes; the actual size is reported via *out_w and *out_h.

Supported source formats:

  • Grayscale: 1 component, no subsampling.
  • YCbCr: 3 components, 4:4:4 (H1V1,H1V1,H1V1), 4:2:0 (H2V2,H1V1,H1V1).

Algorithm (per MCU):

  1. Decode Huffman-coded DC/AC coefficients per block.
  2. Dequantize against the per-component quantization table.
  3. Apply the IDCT (T.81 Annex A.3.3 8x8 inverse DCT).
  4. Upsample chroma to luma resolution where required.
  5. YCbCr -> RGB and store row-major into out_buf.
Parameters
[in]jpeg_bufPointer to the JPEG byte stream.
[in]jpeg_lenLength of jpeg_buf in bytes.
[out]out_bufDestination buffer for RGB888 pixels.
[in]out_buf_lenCapacity of out_buf in bytes.
[out]out_wReceives image width in pixels.
[out]out_hReceives image height in pixels.
Returns
ra8_err_t error code.
Return values
k_ra8_okDecoded successfully.
k_ra8_err_null_ptrAny pointer argument was NULL.
k_ra8_err_protocol_errorMalformed JPEG stream.
k_ra8_err_not_supportedProgressive / arithmetic / 12-bit / unsupported chroma layout.
k_ra8_err_invalid_sizeout_buf_len < width*height*3.
Precondition
jpeg_buf and out_buf reference disjoint memory.
Image dimensions in the SOF0 marker are non-zero.
Postcondition
On success *out_w * *out_h * 3 <= out_buf_len.
On any error out_buf contents are unspecified but the caller's stack is unaffected.
Note
Thread-safe (re-entrant): all state lives on the caller's stack.
Warning
The decoder does not stream – the entire JPEG must be buffered in memory before the call. For typical RA8D2 camera frames (<= 256 KiB) this is fine.
See also
ra8_jpeg_sw_get_dimensions Lightweight dimension probe.
ra8_jpeg_sw_encode Inverse operation.
Since
0.1.0

Definition at line 896 of file ra8_jpeg_sw_decode.c.

References ra8_jpeg_dec_ctx_t::cursor, internal_dec_run(), internal_read_be16(), k_ra8_err_invalid_size, k_ra8_err_protocol_error, k_ra8_jpeg_marker_soi, memset(), RA8_CHECK_NULL_PTR, s_tag, ra8_jpeg_dec_ctx_t::src, and ra8_jpeg_dec_ctx_t::src_len.

Variable Documentation

◆ s_tag

const char* s_tag = "JPEG_SW"
static

Component log tag.

Definition at line 41 of file ra8_jpeg_sw_decode.c.