Skip to main content

<alp/jpeg.h> — JPEG Encoder

Portable JPEG encoding of planar YUV frames, hardware-accelerated where the silicon has an encoder and software everywhere else. New in v0.14.0.

:::note Encoder only There is no decode path in this header. <alp/jpeg.h> encodes; it does not decode. If you need to decode, that is outside this surface today. :::

#include <alp/jpeg.h>

Quick example

alp_jpeg_t *enc = alp_jpeg_open(&(alp_jpeg_config_t){
.engine_id = 0u,
.max_width = 640u,
.max_height = 480u,
});
if (enc == NULL) {
printk("jpeg open failed: %d\n", alp_last_error());
return;
}

const alp_jpeg_encode_req_t req = {
.width = 64u,
.height = 64u,
.format = ALP_PIXFMT_NV12,
.subsample = ALP_JPEG_SUBSAMPLE_420,
.quality = 80u,
.y_plane = y_buf, /* NOT in TCM — see below */
.y_stride = 64u,
.u_plane = uv_buf,
.u_stride = 64u,
.v_plane = NULL,
.v_stride = 0u,
};

size_t out_len = 0u;
alp_status_t rc = alp_jpeg_encode(enc, &req, out_buf, sizeof(out_buf), &out_len);

alp_jpeg_close(enc);

:::warning The hardware backend DMAs from your planes — keep them out of TCM The hardware-accelerated backend reads the caller's planes by DMA directly, so those buffers must live in globally-addressable RAM. A TCM buffer is not DMA-reachable and yields ALP_ERR_NOSUPPORT — the encode never starts. This is the single most likely first-run failure on E8. :::

Types

alp_jpeg_subsample_t

ValueNumeric
ALP_JPEG_SUBSAMPLE_4000
ALP_JPEG_SUBSAMPLE_4201
ALP_JPEG_SUBSAMPLE_4222

alp_jpeg_config_t

FieldTypeNotes
engine_iduint32_tWhich encoder engine to open.
max_widthuint16_tLargest frame width this handle will be asked to encode.
max_heightuint16_tLargest frame height this handle will be asked to encode.

alp_jpeg_encode_req_t

Fields in header order:

FieldNotes
width / heightFrame geometry for this encode.
formatalp_pixfmt_t — the input pixel format.
subsampleChroma subsampling for the output JPEG.
qualityEncoder quality setting.
y_plane / y_strideLuma plane and its row stride.
u_plane / u_strideU (or interleaved UV, for NV12) plane and its row stride.
v_plane / v_strideV plane and its row stride.

alp_jpeg_caps_t

FieldTypeNotes
hw_acceleratedbooltrue when a hardware encoder is behind the handle.
mjpeg_supportedbool
max_width / max_heightLargest geometry the backend will encode.
subsample_maskBitmask of the supported alp_jpeg_subsample_t values.
pixfmt_maskBitmask of the supported alp_pixfmt_t inputs.

Query it with alp_jpeg_capabilities(handle, &caps) — note this class returns an alp_status_t and fills a caller-provided struct, rather than returning a const alp_capabilities_t * like the bus classes do.

New pixel formats

Two values were appended to alp_pixfmt_t in <alp/peripheral.h> for this class:

ValueNumeric
ALP_PIXFMT_YUV420_PLANAR4
ALP_PIXFMT_NV125

Existing values are unchanged — this is an ABI-safe append, and ALP_PIXFMT_ARGB8888 remains 3.

Functions

CallReturns
alp_jpeg_open(const alp_jpeg_config_t *cfg)alp_jpeg_t *, or NULL — read alp_last_error().
alp_jpeg_encode(h, const alp_jpeg_encode_req_t *req, void *out_buf, size_t out_cap, size_t *out_len)alp_status_t; on ALP_OK, *out_len is the encoded byte count written into out_buf.
alp_jpeg_capabilities(const alp_jpeg_t *h, alp_jpeg_caps_t *out)alp_status_t; fills *out.
alp_jpeg_close(h)void.

Errors

alp_jpeg_open() returns NULL and sets alp_last_error() to one of:

CodeMeaning
ALP_ERR_INVALBad config.
ALP_ERR_NOMEMAllocation failed.
ALP_ERR_NOT_PRESENT_ON_THIS_SOCNo encoder engine on this silicon.
ALP_ERR_NOT_IMPLEMENTEDThe selected backend is the stub.

alp_jpeg_encode() returns:

CodeMeaning
ALP_ERR_INVALBad argument.
ALP_ERR_NOSUPPORTUnsupported pixel format or subsampling — or a buffer that is not DMA-reachable on the hardware backend (the TCM case above).
ALP_ERR_NOMEMout_cap too small for the encoded frame.
ALP_ERR_IOHardware fault.
ALP_ERR_NOT_IMPLEMENTEDNo encode path in the selected backend.
ALP_ERR_NOT_READYHandle or engine not ready.

Backends

BackendApplies toStatus
alif_hantro (priority 100, silicon_ref="alif:ensemble:e8")Alif Ensemble E8 Hantro VC9000E hardware encoder, driven through the Zephyr video driver class; NV12 input only; gated on CONFIG_ALP_SDK_JPEG_ALIF_HANTROBench-verified on real E1M-AEN801 (Ensemble E8) silicon: JPEG_SWREG0 reads back JPEG_HW_ID 0x90001000, hardware version 0x00c0c200; alp_jpeg_encode() returned rc=0 out_len=935 for a 64×64 NV12 frame, round-tripped through libjpeg to a correct image.
sw_baseline (priority 50, silicon_ref="*")Portable TooJpeg baseline encoder, 4:2:0 and 4:0:0 onlySoftware fallback; wins on every non-E8 SoM.
zephyr_stub (priority 0)Safety netReturns ALP_ERR_NOT_IMPLEMENTED.

See the selection rules for how priority and silicon_ref pick a row.

Practical consequence: on E8 with the Hantro row compiled in you get hardware encoding of NV12; anywhere else — and on E8 without CONFIG_ALP_SDK_JPEG_ALIF_HANTRO — the TooJpeg baseline encoder runs, and ALP_JPEG_SUBSAMPLE_422 is not available there.

ABI status

[ABI-EXPERIMENTAL] — new in v0.14.0. Encoder-only, one hardware backend, and a surface that may still move. Pin your SDK to a specific commit if you depend on it.

See also

Questions about this page? Discuss in Community Forum