ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_jpeg_sw_encode.c
Go to the documentation of this file.
1
34
35#include <stdint.h>
36#include <string.h>
37
38#include "ra8_attributes.h"
39#include "ra8_check.h"
40#include "ra8_err.h"
41#include "ra8_jpeg_sw.h"
44#include "ra8_log.h"
45
47static const char* s_tag = "JPEG_SW";
48
49/* ------------------------------------------------------------------ */
50/* Encoder quantization reference tables (T.81 Annex K.1) */
51/* ------------------------------------------------------------------ */
52
54static const uint8_t s_quant_luma[64] = {
55 16, 11, 10, 16, 24, 40, 51, 61, 12, 12, 14, 19, 26, 58, 60, 55, 14, 13, 16, 24, 40, 57,
56 69, 56, 14, 17, 22, 29, 51, 87, 80, 62, 18, 22, 37, 56, 68, 109, 103, 77, 24, 35, 55, 64,
57 81, 104, 113, 92, 49, 64, 78, 87, 103, 121, 120, 101, 72, 92, 95, 98, 112, 100, 103, 99,
58};
59
61static const uint8_t s_quant_chroma[64] = {
62 17, 18, 24, 47, 99, 99, 99, 99, 18, 21, 26, 66, 99, 99, 99, 99, 24, 26, 56, 99, 99, 99,
63 99, 99, 47, 66, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
64 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
65};
66
67/* ------------------------------------------------------------------ */
68/* Forward DCT (encoder) */
69/* ------------------------------------------------------------------ */
70
90RA8_INTERNAL static void internal_fwd_dct_1d_norm(const int32_t* in, int32_t* out)
91{
92 for (uint8_t k = 0U; k < (uint8_t)k_ra8_jpeg_block_dim; k++) {
93 int64_t s = 0;
94 for (uint8_t n = 0U; n < (uint8_t)k_ra8_jpeg_block_dim; n++) {
95 s += (int64_t)in[n] * (int64_t)s_dct_cos_q14[k][n];
96 }
97 /* s is Q14*Q0 = Q14; multiply by Q14 weight -> Q28; round to Q0. */
98 int64_t r =
99 ((s * (int64_t)s_dct_w_q14[k]) + (1LL << k_jpeg_idct_p1_bias_sh)) >> k_jpeg_idct_p1_sh;
100 out[k] = (int32_t)r;
101 }
102}
103
120RA8_INTERNAL static void internal_fdct8x8(int32_t* block)
121{
122 int32_t tmp[(uint32_t)k_ra8_jpeg_block_size];
123 int32_t row[(uint32_t)k_ra8_jpeg_block_dim];
124 int32_t col[(uint32_t)k_ra8_jpeg_block_dim];
125 int32_t out[(uint32_t)k_ra8_jpeg_block_dim];
126 for (uint8_t r = 0U; r < (uint8_t)k_ra8_jpeg_block_dim; r++) {
127 for (uint8_t c = 0U; c < (uint8_t)k_ra8_jpeg_block_dim; c++) {
128 row[c] = block[(r * (uint8_t)k_ra8_jpeg_block_dim) + c];
129 }
130 internal_fwd_dct_1d_norm(row, out);
131 for (uint8_t c = 0U; c < (uint8_t)k_ra8_jpeg_block_dim; c++) {
132 tmp[(r * (uint8_t)k_ra8_jpeg_block_dim) + c] = out[c];
133 }
134 }
135 for (uint8_t c = 0U; c < (uint8_t)k_ra8_jpeg_block_dim; c++) {
136 for (uint8_t r = 0U; r < (uint8_t)k_ra8_jpeg_block_dim; r++) {
137 col[r] = tmp[(r * (uint8_t)k_ra8_jpeg_block_dim) + c];
138 }
139 internal_fwd_dct_1d_norm(col, out);
140 for (uint8_t r = 0U; r < (uint8_t)k_ra8_jpeg_block_dim; r++) {
141 block[(r * (uint8_t)k_ra8_jpeg_block_dim) + c] = out[r];
142 }
143 }
144}
145
146/* ------------------------------------------------------------------ */
147/* Quantization */
148/* ------------------------------------------------------------------ */
149
170RA8_INTERNAL static uint16_t internal_enc_quality_scale(uint8_t q)
171{
172 if (q < (uint8_t)k_ra8_jpeg_quality_pivot) {
173 return (uint16_t)(k_jpeg_q_scale_low / q);
174 }
175 return (uint16_t)(k_jpeg_q_scale_high - (2U * (uint16_t)q));
176}
177
196RA8_INTERNAL static void internal_enc_scale_qtab(const uint8_t* base, uint8_t* dst, uint16_t scale)
197{
198 for (uint8_t i = 0U; i < (uint8_t)k_ra8_jpeg_block_size; i++) {
199 uint32_t t = (((uint32_t)base[i] * (uint32_t)scale) + k_jpeg_q_round_bias) / k_jpeg_q_percent;
200 if (t < 1U) {
201 t = 1U;
202 } else if (t > (uint32_t)k_ra8_jpeg_pixel_max) {
203 t = (uint32_t)k_ra8_jpeg_pixel_max;
204 }
205 dst[i] = (uint8_t)t;
206 }
207}
208
229RA8_INTERNAL static uint8_t internal_enc_bits_needed(int32_t v)
230{
231 uint32_t a = (v < 0) ? (uint32_t)(-v) : (uint32_t)v;
232 uint8_t n = 0U;
233 while (a != 0U) {
234 a >>= 1U;
235 n++;
236 }
237 return n;
238}
239
262RA8_INTERNAL static int32_t internal_enc_quantize(int32_t v, uint8_t qv)
263{
264 int32_t q = (int32_t)qv;
265 if (q == 0) {
266 q = 1;
267 }
268 if (v < 0) {
269 int32_t a = -v + (q >> 1);
270 return -(a / q);
271 }
272 return (v + (q >> 1)) / q;
273}
274
275/* ------------------------------------------------------------------ */
276/* Per-block Huffman emission */
277/* ------------------------------------------------------------------ */
278
301 const int32_t* z,
302 const uint16_t* ac_codes,
303 const uint8_t* ac_sizes)
304{
305 uint8_t run = 0U;
306 for (uint8_t k = 1U; k < (uint8_t)k_ra8_jpeg_block_size; k++) {
307 if (z[k] == 0) {
308 run++;
309 continue;
310 }
311 while (run >= 16U) {
312 /* ZRL = 0xF0. */
314 (uint32_t)ac_codes[k_jpeg_zrl_symbol],
315 ac_sizes[k_jpeg_zrl_symbol]);
316 run = (uint8_t)(run - 16U);
317 }
318 uint8_t mb = internal_enc_bits_needed(z[k]);
319 uint8_t sym = (uint8_t)((run << k_ra8_jpeg_nibble_shift) | mb);
320 priv_jpeg_sw_enc_put_bits(e, (uint32_t)ac_codes[sym], ac_sizes[sym]);
321 int32_t v = (z[k] < 0) ? (z[k] - 1) : z[k];
322 priv_jpeg_sw_enc_put_bits(e, (uint32_t)v & ((1U << mb) - 1U), mb);
323 run = 0U;
324 }
325 if (run > 0U) {
326 /* EOB = 0x00. */
327 priv_jpeg_sw_enc_put_bits(e, (uint32_t)ac_codes[0U], ac_sizes[0U]);
328 }
329}
330
356 const int32_t* spatial,
357 const uint8_t* qtab,
358 uint8_t comp_idx,
359 const uint16_t* dc_codes,
360 const uint8_t* dc_sizes,
361 const uint16_t* ac_codes,
362 const uint8_t* ac_sizes)
363{
364 int32_t blk[(uint32_t)k_ra8_jpeg_block_size];
365 for (uint8_t i = 0U; i < (uint8_t)k_ra8_jpeg_block_size; i++) {
366 blk[i] = spatial[i];
367 }
368 internal_fdct8x8(blk);
369
370 /* Quantize in zig-zag order. */
371 int32_t z[(uint32_t)k_ra8_jpeg_block_size];
372 for (uint8_t i = 0U; i < (uint8_t)k_ra8_jpeg_block_size; i++) {
373 z[i] = internal_enc_quantize(blk[s_zigzag[i]], qtab[s_zigzag[i]]);
374 }
375
376 /* DC differential. */
377 int32_t diff = z[0] - e->dc_pred[comp_idx];
378 e->dc_pred[comp_idx] = z[0];
379 uint8_t nb = internal_enc_bits_needed(diff);
380 priv_jpeg_sw_enc_put_bits(e, (uint32_t)dc_codes[nb], dc_sizes[nb]);
381 if (nb != 0U) {
382 int32_t v = (diff < 0) ? (diff - 1) : diff;
383 priv_jpeg_sw_enc_put_bits(e, (uint32_t)v & ((1U << nb) - 1U), nb);
384 }
385
386 /* AC. */
387 internal_enc_block_ac(e, z, ac_codes, ac_sizes);
388}
389
390/* ------------------------------------------------------------------ */
391/* RGB -> YCbCr conversion and block sampling */
392/* ------------------------------------------------------------------ */
393
415RA8_INTERNAL static void
416internal_enc_rgb_to_ycc_row(const uint8_t* rgb, uint16_t n, int32_t* y, int32_t* cb, int32_t* cr)
417{
418 for (uint16_t i = 0U; i < n; i++) {
419 uint32_t px = (uint32_t)i * (uint32_t)k_ra8_jpeg_rgb_components;
420 int32_t r = (int32_t)rgb[px];
421 int32_t g = (int32_t)rgb[px + 1U];
422 int32_t b = (int32_t)rgb[px + 2U];
423 y[i] = (((int32_t)k_ra8_jpeg_yr * r) + ((int32_t)k_ra8_jpeg_yg * g) +
424 ((int32_t)k_ra8_jpeg_yb * b)) >>
426 cb[i] = ((((int32_t)k_ra8_jpeg_cbr * r) + ((int32_t)k_ra8_jpeg_cbg * g) +
427 ((int32_t)k_ra8_jpeg_cbb * b)) >>
430 cr[i] = ((((int32_t)k_ra8_jpeg_crr * r) + ((int32_t)k_ra8_jpeg_crg * g) +
431 ((int32_t)k_ra8_jpeg_crb * b)) >>
434 }
435}
436
459RA8_INTERNAL static void internal_enc_sample_y_block(const int32_t* yplane,
460 uint16_t plane_w,
461 uint16_t plane_h,
462 uint16_t x0,
463 uint16_t y0,
464 int32_t* out)
465{
466 for (uint8_t r = 0U; r < (uint8_t)k_ra8_jpeg_block_dim; r++) {
467 uint16_t sy = (uint16_t)(y0 + r);
468 if (sy >= plane_h) {
469 sy = (uint16_t)(plane_h - 1U);
470 }
471 for (uint8_t c = 0U; c < (uint8_t)k_ra8_jpeg_block_dim; c++) {
472 uint16_t sx = (uint16_t)(x0 + c);
473 if (sx >= plane_w) {
474 sx = (uint16_t)(plane_w - 1U);
475 }
476 out[(r * (uint8_t)k_ra8_jpeg_block_dim) + c] =
477 yplane[((uint32_t)sy * plane_w) + sx] - (int32_t)k_ra8_jpeg_level_offset;
478 }
479 }
480}
481
508RA8_INTERNAL static int32_t internal_enc_avg_2x2(const int32_t* cplane,
509 uint16_t plane_w,
510 uint16_t plane_h,
511 uint16_t sx,
512 uint16_t sy)
513{
514 int32_t s = 0;
515 uint8_t n = 0U;
516 for (uint8_t dy = 0U; dy < 2U; dy++) {
517 for (uint8_t dx = 0U; dx < 2U; dx++) {
518 uint16_t yy = (uint16_t)(sy + dy);
519 uint16_t xx = (uint16_t)(sx + dx);
520 if (yy >= plane_h) {
521 yy = (uint16_t)(plane_h - 1U);
522 }
523 if (xx >= plane_w) {
524 xx = (uint16_t)(plane_w - 1U);
525 }
526 s += cplane[((uint32_t)yy * plane_w) + xx];
527 n++;
528 }
529 }
530 return s / (int32_t)n;
531}
532
555RA8_INTERNAL static void internal_enc_sample_c_block_420(const int32_t* cplane,
556 uint16_t plane_w,
557 uint16_t plane_h,
558 uint16_t x0,
559 uint16_t y0,
560 int32_t* out)
561{
562 for (uint8_t r = 0U; r < (uint8_t)k_ra8_jpeg_block_dim; r++) {
563 for (uint8_t c = 0U; c < (uint8_t)k_ra8_jpeg_block_dim; c++) {
564 uint16_t sy = (uint16_t)(y0 + (r * 2U));
565 uint16_t sx = (uint16_t)(x0 + (c * 2U));
566 out[(r * (uint8_t)k_ra8_jpeg_block_dim) + c] =
567 internal_enc_avg_2x2(cplane, plane_w, plane_h, sx, sy) - (int32_t)k_ra8_jpeg_level_offset;
568 }
569 }
570}
571
601RA8_INTERNAL static void internal_enc_convert_strip_to_ycc(const uint8_t* rgb,
602 uint16_t w,
603 uint16_t h,
604 uint16_t pad_w,
605 uint16_t mby,
606 int32_t* y_strip,
607 int32_t* cb_strip,
608 int32_t* cr_strip,
609 uint8_t* tmp_rgb)
610{
611 for (uint8_t r = 0U; r < 16U; r++) {
612 uint16_t src_y = mby + r;
613 if (src_y >= h) {
614 src_y = (uint16_t)(h - 1U);
615 }
616 for (uint16_t c = 0U; c < pad_w; c++) {
617 uint16_t src_x = c;
618 if (src_x >= w) {
619 src_x = (uint16_t)(w - 1U);
620 }
621 uint32_t sidx =
622 (((uint32_t)src_y * (uint32_t)w) + (uint32_t)src_x) * (uint32_t)k_ra8_jpeg_rgb_components;
623 uint32_t didx = (uint32_t)c * (uint32_t)k_ra8_jpeg_rgb_components;
624 tmp_rgb[didx] = rgb[sidx + 0U];
625 tmp_rgb[didx + 1U] = rgb[sidx + 1U];
626 tmp_rgb[didx + 2U] = rgb[sidx + 2U];
627 }
629 pad_w,
630 &y_strip[(size_t)r * pad_w],
631 &cb_strip[(size_t)r * pad_w],
632 &cr_strip[(size_t)r * pad_w]);
633 }
634}
635
661 uint16_t pad_w,
662 const int32_t* y_strip,
663 const int32_t* cb_strip,
664 const int32_t* cr_strip)
665{
666 for (uint16_t mbx = 0U; mbx < pad_w; mbx = (uint16_t)(mbx + 16U)) {
667 int32_t blk[(uint32_t)k_ra8_jpeg_block_size];
668 /* 4 luma blocks: (0,0) (0,8) (8,0) (8,8). */
669 for (uint8_t by = 0U; by < 2U; by++) {
670 for (uint8_t bx = 0U; bx < 2U; bx++) {
672 pad_w,
673 16U,
674 (uint16_t)(mbx + (bx * 8U)),
675 (uint16_t)(by * 8U),
676 blk);
678 blk,
679 e->qy,
680 0U,
681 e->code_dc_l,
682 e->size_dc_l,
683 e->code_ac_l,
684 e->size_ac_l);
685 }
686 }
687 internal_enc_sample_c_block_420(cb_strip, pad_w, 16U, mbx, 0U, blk);
688 internal_enc_block(e, blk, e->qc, 1U, e->code_dc_c, e->size_dc_c, e->code_ac_c, e->size_ac_c);
689 internal_enc_sample_c_block_420(cr_strip, pad_w, 16U, mbx, 0U, blk);
690 internal_enc_block(e, blk, e->qc, 2U, e->code_dc_c, e->size_dc_c, e->code_ac_c, e->size_ac_c);
691 }
692}
693
694/* ------------------------------------------------------------------ */
695/* Top-level driver and public API */
696/* ------------------------------------------------------------------ */
697
726internal_enc_run(ra8_jpeg_enc_ctx_t* e, const uint8_t* rgb, uint16_t w, uint16_t h, uint8_t quality)
727{
728 /* Build quantization tables. */
729 uint16_t qs = internal_enc_quality_scale(quality);
732
733 /* Build Huffman code tables from K.3.3 BITS/VALUES. */
734 uint16_t total_dc_l;
735 uint16_t total_ac_l;
736 uint16_t total_dc_c;
737 uint16_t total_ac_c;
738 priv_jpeg_sw_enc_build_huff(e, &total_dc_l, &total_ac_l, &total_dc_c, &total_ac_c);
739
740 priv_jpeg_sw_enc_headers(e, w, h, total_dc_l, total_ac_l, total_dc_c, total_ac_c);
741
742 /* Convert source rows to YCbCr 16-row strips. Static buffers
743 * keep the host stack small while still respecting NASA Rule 3
744 * (no heap). The encoder is single-threaded, so file-scope
745 * sharing is safe. */
746 uint16_t pad_w = (uint16_t)((w + k_jpeg_mcu_align) & ~k_jpeg_mcu_align);
747 uint16_t pad_h = (uint16_t)((h + k_jpeg_mcu_align) & ~k_jpeg_mcu_align);
748 if ((uint32_t)pad_w > (uint32_t)k_ra8_jpeg_enc_max_w) {
750 }
751 static int32_t s_y_strip[16U * (uint32_t)k_ra8_jpeg_enc_max_w];
752 static int32_t s_cb_strip[16U * (uint32_t)k_ra8_jpeg_enc_max_w];
753 static int32_t s_cr_strip[16U * (uint32_t)k_ra8_jpeg_enc_max_w];
754 static uint8_t s_tmp_rgb[3U * (uint32_t)k_ra8_jpeg_enc_max_w];
755
756 for (uint16_t mby = 0U; mby < pad_h; mby = (uint16_t)(mby + 16U)) {
758 w,
759 h,
760 pad_w,
761 mby,
762 s_y_strip,
763 s_cb_strip,
764 s_cr_strip,
765 s_tmp_rgb);
766 internal_enc_encode_mcu_row(e, pad_w, s_y_strip, s_cb_strip, s_cr_strip);
767 }
768
771
772 if (e->overflow) {
774 }
775 return k_ra8_ok;
776}
777
778ra8_err_t ra8_jpeg_sw_encode(const uint8_t* rgb_buf,
779 uint16_t width,
780 uint16_t height,
781 uint8_t quality,
782 uint8_t* out_buf,
783 uint32_t out_buf_len,
784 uint32_t* out_len)
785{
786 RA8_CHECK_NULL_PTR(rgb_buf, s_tag, "rgb_buf is NULL");
787 RA8_CHECK_NULL_PTR(out_buf, s_tag, "out_buf is NULL");
788 RA8_CHECK_NULL_PTR(out_len, s_tag, "out_len is NULL");
789 *out_len = 0U;
790 if (width == 0U || height == 0U) {
792 }
793 if (quality < (uint8_t)k_ra8_jpeg_sw_quality_min ||
794 quality > (uint8_t)k_ra8_jpeg_sw_quality_max) {
796 }
797
798 /* Encoder context contains 2KiB of Huffman code/size LUTs; allocate
799 * static to avoid the project's stack-usage budget firing. */
800 static ra8_jpeg_enc_ctx_t s_e;
801 ra8_jpeg_enc_ctx_t* e = &s_e;
802 memset(e, 0, sizeof(*e));
803 e->dst = out_buf;
804 e->cap = out_buf_len;
805
806 ra8_err_t err = internal_enc_run(e, rgb_buf, width, height, quality);
807 if (err != k_ra8_ok) {
808 return err;
809 }
810 *out_len = e->pos;
811 return k_ra8_ok;
812}
static const char * s_tag
Logging / check tag.
Definition ra8_app.c:17
Annotation-attribute framework macros for ra8-firmware.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
Validation and Error-Checking Macros for ra8-firmware.
#define RA8_CHECK_NULL_PTR(ptr, tag, message)
Reject nullptr pointer, returning k_ra8_err_null_ptr.
Definition ra8_check.h:243
Error Code Definitions for ra8-firmware.
@ k_ra8_err_invalid_arg
Invalid function argument.
Definition ra8_err.h:152
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
@ k_ra8_err_invalid_size
Invalid size parameter (too large, too small, or misaligned).
Definition ra8_err.h:167
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
void * memset(void *dst, int value, size_t n)
Fill memory with a constant byte value.
Pure-software baseline JPEG (ISO/IEC 10918-1 / ITU-T T.81) codec.
@ k_ra8_jpeg_sw_quality_min
Lowest legal quality.
Definition ra8_jpeg_sw.h:74
@ k_ra8_jpeg_sw_quality_max
Largest legal quality.
Definition ra8_jpeg_sw.h:78
static int32_t internal_enc_avg_2x2(const int32_t *cplane, uint16_t plane_w, uint16_t plane_h, uint16_t sx, uint16_t sy)
Average the 2x2 chroma neighbourhood at (sx, sy), clamped.
static void internal_enc_sample_y_block(const int32_t *yplane, uint16_t plane_w, uint16_t plane_h, uint16_t x0, uint16_t y0, int32_t *out)
Sample one 8x8 luma block from the Y plane (clamp-to-edge).
static int32_t internal_enc_quantize(int32_t v, uint8_t qv)
Quantize one DCT coefficient with symmetric rounding.
static void internal_enc_scale_qtab(const uint8_t *base, uint8_t *dst, uint16_t scale)
Scale a base quantization table by scale/100, clamped to 1..255.
static void internal_enc_rgb_to_ycc_row(const uint8_t *rgb, uint16_t n, int32_t *y, int32_t *cb, int32_t *cr)
Convert one row of RGB into Y, Cb, Cr samples (BT.601 Q16).
static void internal_enc_block_ac(ra8_jpeg_enc_ctx_t *e, const int32_t *z, const uint16_t *ac_codes, const uint8_t *ac_sizes)
Emit the 63 AC coefficients of one quantized block.
static uint16_t internal_enc_quality_scale(uint8_t q)
Compute the IJG quality-scale factor.
static void internal_enc_convert_strip_to_ycc(const uint8_t *rgb, uint16_t w, uint16_t h, uint16_t pad_w, uint16_t mby, int32_t *y_strip, int32_t *cb_strip, int32_t *cr_strip, uint8_t *tmp_rgb)
Convert 16 source RGB rows into Y / Cb / Cr 16-row strips.
static const uint8_t s_quant_chroma[64]
T.81 Annex K.1 chroma quantization table.
static void internal_fdct8x8(int32_t *block)
2-D forward DCT of one 8x8 block, in place.
static void internal_fwd_dct_1d_norm(const int32_t *in, int32_t *out)
1-D forward DCT pass with JPEG normalization folded in.
static uint8_t internal_enc_bits_needed(int32_t v)
Compute the number of significant-magnitude bits of v.
static void internal_enc_sample_c_block_420(const int32_t *cplane, uint16_t plane_w, uint16_t plane_h, uint16_t x0, uint16_t y0, int32_t *out)
Build one 8x8 chroma block by 2x2 averaging from a 16x16 region.
static void internal_enc_block(ra8_jpeg_enc_ctx_t *e, const int32_t *spatial, const uint8_t *qtab, uint8_t comp_idx, const uint16_t *dc_codes, const uint8_t *dc_sizes, const uint16_t *ac_codes, const uint8_t *ac_sizes)
Encode one 8x8 block of source samples.
static const uint8_t s_quant_luma[64]
T.81 Annex K.1 luma quantization table.
static void internal_enc_encode_mcu_row(ra8_jpeg_enc_ctx_t *e, uint16_t pad_w, const int32_t *y_strip, const int32_t *cb_strip, const int32_t *cr_strip)
Encode every 16x16 MCU in a 16-row YCbCr strip.
static ra8_err_t internal_enc_run(ra8_jpeg_enc_ctx_t *e, const uint8_t *rgb, uint16_t w, uint16_t h, uint8_t quality)
Top-level encode driver – emits the full JFIF byte stream.
ra8_err_t ra8_jpeg_sw_encode(const uint8_t *rgb_buf, uint16_t width, uint16_t height, uint8_t quality, uint8_t *out_buf, uint32_t out_buf_len, uint32_t *out_len)
Encode a packed RGB888 frame as a baseline JPEG.
void priv_jpeg_sw_enc_put_bits(ra8_jpeg_enc_ctx_t *e, uint32_t code, uint8_t n)
Implementation of priv_jpeg_sw_enc_put_bits() – T.81 F.1.2.3 stuffing.
void priv_jpeg_sw_enc_headers(ra8_jpeg_enc_ctx_t *e, uint16_t w, uint16_t h, uint16_t total_dc_l, uint16_t total_ac_l, uint16_t total_dc_c, uint16_t total_ac_c)
Implementation of priv_jpeg_sw_enc_headers() – JFIF 1.1 segment order.
void priv_jpeg_sw_enc_flush_bits(ra8_jpeg_enc_ctx_t *e)
Implementation of priv_jpeg_sw_enc_flush_bits() – 1-fill pad.
void priv_jpeg_sw_enc_build_huff(ra8_jpeg_enc_ctx_t *e, uint16_t *total_dc_l, uint16_t *total_ac_l, uint16_t *total_dc_c, uint16_t *total_ac_c)
Implementation of priv_jpeg_sw_enc_build_huff() – four K.3.3 LUT builds.
void priv_jpeg_sw_enc_emit_u16(ra8_jpeg_enc_ctx_t *e, uint16_t v)
Implementation of priv_jpeg_sw_enc_emit_u16() – big-endian byte pair.
Module-private declarations shared by the two encoder translation units of the software JPEG codec.
Module-private declarations shared across the software JPEGcodec translation units.
@ k_ra8_jpeg_marker_eoi
End of image.
@ k_ra8_jpeg_level_offset
RA8 JPEG level offset.
@ k_ra8_jpeg_nibble_shift
RA8 JPEG nibble shift.
@ k_ra8_jpeg_quality_pivot
RA8 JPEG quality pivot.
@ k_ra8_jpeg_rgb_components
RA8 JPEG RGB components.
@ k_ra8_jpeg_pixel_max
RA8 JPEG pixel maximum.
@ k_ra8_jpeg_yuv_shift
BT.601 fixed-point shift.
@ k_jpeg_idct_p1_bias_sh
JPEG idct p1 bias sh.
@ k_jpeg_idct_p1_sh
JPEG idct p1 sh.
@ k_jpeg_q_round_bias
JPEG q round bias.
@ k_jpeg_q_scale_high
JPEG q scale high.
@ k_jpeg_q_percent
JPEG q percent.
@ k_jpeg_q_scale_low
JPEG q scale low.
@ k_jpeg_zrl_symbol
JPEG zrl symbol.
@ k_jpeg_mcu_align
JPEG mcu align.
@ k_ra8_jpeg_enc_max_w
Encoder max image width (px).
@ k_ra8_jpeg_block_size
Coefficients per block.
@ k_ra8_jpeg_block_dim
8x8 DCT block edge.
static const int32_t s_dct_cos_q14[8][8]
Cosine table cos((2n+1)*k*pi/16) * 2^14, k = row, n = col.
static const uint8_t s_zigzag[64]
Zig-zag de-interleave order (T.81 Figure 5).
@ k_ra8_jpeg_cbr
RA8 JPEG CBR.
@ k_ra8_jpeg_crb
RA8 JPEG crb.
@ k_ra8_jpeg_crr
RA8 JPEG crr.
@ k_ra8_jpeg_yg
0.58700 * 65536.
@ k_ra8_jpeg_cbg
RA8 JPEG cbg.
@ k_ra8_jpeg_yr
0.29900 * 65536.
@ k_ra8_jpeg_yb
0.11400 * 65536.
@ k_ra8_jpeg_cbb
RA8 JPEG cbb.
@ k_ra8_jpeg_crg
RA8 JPEG crg.
static const int32_t s_dct_w_q14[8]
sqrt(2/N)*C(k) DCT normalization weights, Q14.
Lightweight Logging Interface for ra8-firmware.
Encoder state – buffer cursor, bit accumulator, scaled quant tables, Huffman LUTs and DC predictors.
int32_t dc_pred[k_ra8_jpeg_max_comps]
Per-component DC predictors.
bool overflow
Set on capacity exhaustion.
uint8_t size_ac_l[k_ra8_jpeg_huff_max]
Luma AC code lengths.
uint16_t code_dc_c[k_ra8_jpeg_huff_max]
Chroma DC Huffman codes.
uint8_t size_dc_l[k_ra8_jpeg_huff_max]
Luma DC code lengths.
uint8_t size_ac_c[k_ra8_jpeg_huff_max]
Chroma AC code lengths.
uint8_t * dst
Destination JPEG byte buffer.
uint32_t pos
Write cursor into dst.
uint16_t code_ac_c[k_ra8_jpeg_huff_max]
Chroma AC Huffman codes.
uint16_t code_dc_l[k_ra8_jpeg_huff_max]
Luma DC Huffman codes.
uint8_t qy[k_ra8_jpeg_block_size]
Scaled luma quant table.
uint16_t code_ac_l[k_ra8_jpeg_huff_max]
Luma AC Huffman codes.
uint8_t size_dc_c[k_ra8_jpeg_huff_max]
Chroma DC code lengths.
uint8_t qc[k_ra8_jpeg_block_size]
Scaled chroma quant table.
uint32_t cap
Capacity of dst in bytes.