视频编码与图像处理
本文档介绍 AC792N SDK 中视频编码与图像处理子系统的整体架构与实现,涵盖 YUV 数据获取、JPEG 硬件编解码(encoder_one_jpeg / decoder_one_jpeg)、JPG 转 AVI、Logo 叠加、运动检测、视频录制/显示、网络 AVI 播放以及 LVGL 视频转图片等能力的源码级说明。
Purpose and Scope
本页面覆盖 sdk/apps/common/video/ 目录及 sdk/apps/wifi_bbm/stream/ 中与视频编解码、图像处理直接相关的实现:
- JPEG 硬件编码:
encoder_one_jpeg.c中的yuv_enc_jpeg()应用层 API - JPEG 解码:
decoder_one_jpeg.c中的decoder_one_jpeg()示例流程 - 配套的图像处理模块:
get_yuv_data、jpg2avi、logo_show、motion_detect - 上层应用入口:
user_video_disp/user_video_rec、video_dec_demo/video_rec_demo - 网络 AVI 播放器:
net_avi_player/ - LVGL 视频转图片工具:
lvgl_v8/src/extra/jl_extra/libs/video_to_images/ - 视频通话/流媒体管线:
sdk/apps/wifi_bbm/stream/video_pipeline*、video_stream_*、video_call
以下主题属于其他页面,不在本文展开:USB 摄像头 Host 驱动(usb_video.c)、LVGL UI 画面本身、Wi-Fi 通信协议栈细节。有关系统启动流程请参见系统启动相关页面。
Overview
在 AC792N 这类带硬件 JPEG 编解码器的 SoC 上,视频/图像处理链路通常是:
- 从摄像头(或文件、网络)取得原始 YUV 数据;
- 使用硬件 JPEG 编码器把 YUV 压缩为 JPG 图片(
asm/jpeg_codec.h提供的jpeg_encode_one_image); - 反过来,把 JPG 解码为 YUV(
jpeg_decode_image_info+jpeg_decode_one_image),再经yuv_to_rgb.h/yuv_soft_scalling.h转成 RGB 或缩放后送显示; - 在录制场景中,多帧 JPG 由
jpg2avi封装为 AVI 文件;播放场景则使用net_avi_player从本地/网络流解析 AVI 并逐帧解码。
该子系统的设计意图非常明确:把重计算(JPEG 编解码)交给硬件,应用层只负责缓冲管理、文件 I/O 与格式封装。因此应用层 API(如 yuv_enc_jpeg)的入参设计围绕"内存缓冲 + 分辨率 + 质量"展开,返回值为实际编码字节数,方便调用方直接落盘。
Architecture
flowchart TD
subgraph sg_Source["数据源层"]
Cam["摄像头/YUV 文件"]
SD["SD 卡 JPG/AVI"]
Net["网络流 (curl)"]
end
subgraph sg_Codec["编解码核心 (asm/jpeg_codec.h 硬件加速)"]
Enc["jpeg_encode_one_image"]
Dec["jpeg_decode_image_info / jpeg_decode_one_image"]
end
subgraph sg_App["应用层封装 (sdk/apps/common/video)"]
EncDemo["encoder_one_jpeg.c / yuv_enc_jpeg"]
DecDemo["decoder_one_jpeg.c / decoder_one_jpeg"]
GetYuv["get_yuv_data.c"]
Jpg2Avi["jpg2avi.c"]
Logo["logo_show.c"]
Motion["motion_detect.h"]
Rec["user_video_rec / video_rec_demo"]
Disp["user_video_disp / video_dec_demo"]
AviPlayer["net_avi_player (avi_parse/avi_player)"]
end
subgraph sg_Ext["扩展集成"]
LvglImg["lv_video_to_images (LVGL)"]
WifiStream["video_pipeline / video_stream_* (wifi_bbm)"]
end
Cam --> GetYuv
GetYuv --> EncDemo
EncDemo --> Enc
SD --> DecDemo
DecDemo --> Dec
Dec -->|"YUV/RGB565 输出"| Disp
EncDemo -->|"JPG 字节"| Jpg2Avi
Jpg2Avi --> SD
Net --> AviPlayer
AviPlayer --> Dec
Logo --> Disp
Motion --> Rec
Rec --> EncDemo
DecDemo --> LvglImg
EncDemo --> WifiStream
各组件职责:
asm/jpeg_codec.h(位于 SDK 芯片库,未在本仓库应用层):硬件 JPEG 编解码的统一接口,提供jpeg_encode_one_image、jpeg_decode_image_info、jpeg_decode_one_image、jpeg_codec_init等函数。应用层所有编解码最终都落到这里。encoder_one_jpeg.c:把 YUV 数据编码为 JPG 的应用层示例,核心 API 为yuv_enc_jpeg(),自动根据数据长度推断 YUV444/422/420 采样格式,并支持"仅 Y 数据"模式(JPEG_ENC_ONLY_Y)。decoder_one_jpeg.c:把 JPG 文件解码为 YUV(或 RGB565)的应用层示例,先解析图像信息(宽/高/采样格式),再按格式申请 YUV 缓冲。get_yuv_data.c:负责从视频设备获取 YUV 数据(配合video_ioctl.h/video.h)。jpg2avi.c:把连续 JPG 帧封装为 AVI 容器,用于录像文件生成。logo_show.c:把 Logo 图像叠加到视频画面,属于图像后处理。motion_detect.h:运动检测接口,用于录像触发等场景。net_avi_player/:本地/网络 AVI 播放器,包含avi_parse(AVI 容器解析)、avi_player(播放控制)、curl_get_data(网络取流)、pipeline_jpeg_dec(JPEG 解码流水线)与play_demo(示例入口)。video_pipeline.c/video_stream_*(wifi_bbm 工程):视频通话与流媒体录制/接收/请求的管线实现,把上述编解码能力接入 Wi-Fi 应用。
注:除
encoder_one_jpeg.c、decoder_one_jpeg.c外,上表多数模块的角色依据目录结构与头文件名归纳;其内部详细 API 请直接阅读对应源文件。
核心实现:JPEG 编码
yuv_enc_jpeg() — YUV 转 JPG 应用层 API
encoder_one_jpeg.c 第 32-90 行实现了最核心的编码入口。其设计要点在于根据 yuvdata_size 与 width*height 的关系自动判定采样格式:
- 数据长度 =
width * height * 3→JPG_SAMP_FMT_YUV444 - 数据长度 =
width * height * 2→JPG_SAMP_FMT_YUV422 - 其他(默认)→
JPG_SAMP_FMT_YUV420;若长度恰好等于width * height(只有 Y 平面),则内部申请width*height + width*height/4的缓冲,并把 U/V 平面填充为 0x80(中性色),从而用同一套接口兼容灰度源数据。
//应用层使用YUV编码JPG API
//yuvdata:YUV或Y数据地址,yuvdata_size:数据长度
//jpg_buf:JPG图片编码预先存放数据缓存区,jpg_buf_size:JPG数据缓存区长度(30K-100K:<=320*240->30K,480*320->40K,640*480->50K,1280*720*90K)
//width/height:YUV/Y数据源的分辨率宽高, q_val:图片编码质量:0-13
//返回值:0失败,非0:JPG实际编码的图片数据长度(用户调用该函数后保存JPG数据为jpg_buf,长度为返回值)
int yuv_enc_jpeg(char *yuvdata, int yuvdata_size, char *jpg_buf, int jpg_buf_size, int width, int height, int q_val)
{
struct jpeg_encode_req req = {0};
int err = 0;
char only_y = 0;
char yuv_alloc = 0;
char *yuv = yuvdata;
if (yuvdata_size == width * height * 3) {
req.format = JPG_SAMP_FMT_YUV444;
} else if (yuvdata_size == width * height * 2) {
req.format = JPG_SAMP_FMT_YUV422;
} else {
req.format = JPG_SAMP_FMT_YUV420;
only_y = (yuvdata_size == width * height) ? 1 : 0;
if (only_y) {
yuv = malloc(width * height + width * height / 4);
yuv_alloc = 1;
}
}
if (!yuv) {
printf("err yuv buf not enough\n");
return 0;
}
req.q = q_val;
req.data.buf = (u8 *)jpg_buf;
req.data.len = jpg_buf_size;
req.width = width;
req.height = height;
req.y = (u8 *)yuv;
req.u = req.y + req.width * req.height;
req.v = req.u + req.width * req.height / 4;
#if JPEG_ENC_ONLY_Y
only_y = 1;
#endif
if (only_y) {
if (yuv != yuvdata) {
memcpy(yuv, yuvdata, width * height);
}
memset(yuv + width * height, 0x80, width * height / 4);
req.v = req.u;
}
if (jpeg_encode_one_image(&req) == 0) {
printf("jpeg_encode_one_image ok\n");
err = req.data.len;
} else {
printf("jpeg_encode_one_image err\n");
}
if (yuv_alloc) {
free(yuv);
}
return err;
}
Source: encoder_one_jpeg.c
实现要点:
- 硬件请求结构体
struct jpeg_encode_req:q(质量 0-13)、data.buf/len(输出 JPG 缓冲)、width/height、y/u/v三个平面指针、format采样格式。U 平面紧跟 Y 之后(偏移width*height),V 平面在 U 之后偏移width*height/4,这是 YUV420 的典型内存布局。 JPEG_ENC_ONLY_Y编译宏:SDK 允许只编码 Y 平面以节省带宽/内存;开启后强制走 only_y 路径,V 平面指针直接指向 U(req.v = req.u),UV 数据为 0x80 中性色。- 返回值语义:
jpeg_encode_one_image成功返回 0 时,req.data.len被硬件/驱动回写为实际编码字节数,因此函数返回该值;失败返回 0。调用方只需把jpg_buf前返回值字节写盘即可。 - 内存纪律:
only_y路径内部malloc的临时 YUV 缓冲在退出前必须free,避免在长时间录像循环中泄漏内存。
encoder_one_jpeg() — 文件级编码示例
encoder_one_jpeg(const char *path, int width, int height) 演示了从 SD 卡读取 YUV 文件、申请输出缓冲(100KB,见第 99 行注释"一般 50K-100K,不够再加大")、调用 yuv_enc_jpeg、再把 JPG 写回磁盘的完整流程。文件头部的 path_change_suf_name() 工具函数负责把源文件后缀替换为目标后缀(如 .yuv → .jpg),该函数在编码与解码示例中都被复用。
void encoder_one_jpeg(const char *path, int width, int height)
{
int err = 0;
FILE *fd = NULL;
int yuv_size;
char name[64];
int pix = width * height;
int jpg_size = 100 * 1024;//指定分辨率编码的数据长度缓冲区(一般50K-100K,不够再加大)
char *jpg_img = NULL;
char *yuvbuf = NULL;
fd = fopen(path, "rb");
if (fd == NULL) {
printf("no file name :%s \n", path);
goto exit;
}
yuv_size = flen(fd);//读取jYUV数据长度
yuvbuf = malloc(yuv_size);//申请YUV内存块
if (!yuvbuf) {
printf("yuvbuf malloc err ...\n");
goto exit;
}
if (fread(yuvbuf, yuv_size, 1, fd) != yuv_size) {//读取YUV数据
printf("read file yuv_size err ...\n");
goto exit;
}
fclose(fd);
fd = NULL;
//4.申请编码的JPEG的内存缓冲区,一般50K-100K即可
/* VGA图片大小说明:低等质量(小于20K),中等质量(20K-40K),高质量(大于40K,极限70K)
Source: encoder_one_jpeg.c
该示例使用 goto exit 统一做错误清理(关闭文件、释放缓冲),这是嵌入式 C 代码中常见的"单出口"错误处理模式,保证任何失败路径都不会泄漏资源。
核心实现:JPEG 解码
decoder_one_jpeg() — 文件级解码示例
decoder_one_jpeg(const char *path) 演示解码流程,顺序为:打开文件 → 读取 JPG 数据 → jpeg_codec_init() 初始化硬件 → jpeg_decode_image_info() 解析图像信息 → 按采样格式计算 YUV 缓冲大小 → 申请缓冲 → 解码 → 按 JPEG_SAVE_FILE_YUV 选择保存 YUV 或 RGB565。
jpeg_codec_init();
//2.解析jpeg信息获取源JPEG YUV数据类型和分辨率
struct jpeg_image_info info = {0};
info.input.data.buf = buf;
info.input.data.len = lenth;
if (jpeg_decode_image_info(&info)) {
printf("jpeg_decode_image_info err %s\n", path);
goto exit;
}
width = info.width;
height = info.height;
pix = width * height;
switch (info.sample_fmt) {
case JPG_SAMP_FMT_YUV444:
ytype = 1;
printf("jpeg yuv444, pix : %dx%d \n", width, height);
break;//444
case JPG_SAMP_FMT_YUV420:
ytype = 4;
printf("jpeg yuv420, pix : %dx%d \n", width, height);
break;//420
default:
ytype = 2;
printf("jpeg yuv422, pix : %dx%d \n", width, height);
break;//422
}
//3.申请YUV内存缓存
len = pix + pix / ytype * 2;
if (!yuv) {
yuv = malloc(len);
if (!yuv) {
printf("yuv malloc err len : %d , width : %d , height : %d \n", width, height, len);
goto exit;
}
Source: decoder_one_jpeg.c
实现要点:
- 两阶段解码:先用
jpeg_decode_image_info拿到struct jpeg_image_info(含width、height、sample_fmt),再据此精确计算 YUV 缓冲长度pix + pix/ytype*2(YUV444 为 3 倍像素、YUV422 为 2 倍、YUV420 为 1.5 倍)。这种设计避免了盲目按最大尺寸申请内存,对 SRAM 有限的 MCU 至关重要。 - 采样格式映射:
ytype取值 1/2/4 分别对应 444/422/420,直接参与缓冲大小计算,默认分支把未知格式按 422 处理,保证解码不因未知格式而崩溃。 - 输出格式可配:文件头
#define JPEG_SAVE_FILE_YUV 1决定保存为 YUV(1)还是 RGB565(0),配合yuv_to_rgb.h完成色彩空间转换。
Core Flow
编码流程
sequenceDiagram
participant App as 应用调用方
participant YuvEnc as yuv_enc_jpeg()
participant Codec as jpeg_codec 硬件驱动
participant Mem as 内存缓冲
App->>YuvEnc: 传入 yuvdata/yuvdata_size/width/height/q_val
YuvEnc->>YuvEnc: 按 yuvdata_size 判定采样格式 (444/422/420)
alt 只有 Y 数据 (only_y)
YuvEnc->>Mem: malloc(w*h + w*h/4)
YuvEnc->>Mem: 复制 Y 平面, UV 填充 0x80
end
YuvEnc->>Codec: 填充 jpeg_encode_req (y/u/v/q/format)
Codec->>Codec: 硬件压缩 YUV → JPG
Codec-->>YuvEnc: 成功返回 0, req.data.len 回写实际长度
YuvEnc-->>App: 返回 JPG 字节数 (失败返回 0)
App->>App: 将 jpg_buf[0..len] 写盘/发送
解码流程
sequenceDiagram
participant App as 应用调用方
participant Dec as decoder_one_jpeg()
participant Info as jpeg_decode_image_info
participant Hw as jpeg_decode_one_image
participant File as SD 卡
App->>File: fopen(path) / flen / fread 读取 JPG
Dec->>Info: 解析 width/height/sample_fmt
Info-->>Dec: 图像信息
Dec->>Dec: 计算 len = pix + pix/ytype*2 并 malloc
Dec->>Hw: 解码 YUV 数据
Hw-->>Dec: YUV 缓冲填充完成
Dec->>Dec: 按 JPEG_SAVE_FILE_YUV 保存 YUV 或转 RGB565
Dec-->>App: 输出文件/返回结果
相关图像处理模块
除编解码核心外,sdk/apps/common/video/ 目录还提供一系列配套能力(角色依据文件命名与目录结构归纳):
YUV 数据获取 — get_yuv_data.c/h
负责从视频设备(摄像头)取回 YUV 帧,供编码/显示链路使用。它与 video_ioctl.h、video.h 协同,是 yuv_enc_jpeg 的典型上游数据来源。录像类应用(user_video_rec、video_rec_demo)通常按"取帧 → 编码 → 落盘"的节奏循环。
JPG 转 AVI — jpg2avi.c/h
把连续编码得到的 JPG 帧按 AVI 容器格式封装成录像文件。设计动机是:JPEG 硬件编码速度快、单帧独立可解码,但裸 JPG 序列不便播放;AVI 容器提供索引与帧边界信息,使 PC 播放器可直接顺序播放。user_video_rec 录像流程即为"逐帧 yuv_enc_jpeg → jpg2avi 写帧"。
Logo 叠加 — logo_show.c/h
把 Logo 位图叠加到待显示/待编码的画面中,属于图像后处理(composition)。通常在解码/缩放之后、送显示之前调用,用于产品品牌标识。
运动检测 — motion_detect.h
提供运动检测接口,用于事件触发型录像(检测到运动才编码落盘),可显著降低存储与功耗开销。
视频录制/显示上层入口
user_video_rec.c、video_rec_demo.c:录像应用,展示"取 YUV → 编码 JPG → AVI 封装"的完整链路。user_video_disp.c、video_dec_demo.c:显示应用,展示"解码 JPG → YUV → RGB565 → 显示"的完整链路,并演示yuv_soft_scalling缩放与yuv_to_rgb转换的用法。
网络 AVI 播放器 — net_avi_player/
avi_parse.c/h:解析 AVI 容器(RIFF 块、帧索引),不依赖文件系统类型。curl_get_data.c/h:基于 curl 的网络取流,支持边下边播。avi_player.c/h+pipeline_jpeg_dec.c/h:播放控制与 JPEG 解码流水线,play_demo.c为示例入口。该子目录把"网络传输 → 容器解析 → 硬件解码 → 显示"串成一条完整管线,是视频通话/监控类功能的基础。
LVGL 视频转图片 — lv_video_to_images.h / diff_image_to_video_types.h
位于 lvgl_v8/src/extra/jl_extra/libs/video_to_images/,把视频帧转换为 LVGL 可用的图片资源(配合差分图类型定义),用于 UI 侧的动画/预览展示。
Wi-Fi 视频流管线 — video_pipeline.c/h、video_stream_*(wifi_bbm 工程)
video_pipeline 把采集、编码、发送、接收、解码、显示组装为可配置管线;video_stream_recorder、video_stream_recv、video_stream_request 分别对应录像、接收、请求三类流行为;video_call.c 提供视频通话模式入口。它们与 usb_video.c(USB 摄像头 Host)共同支撑实时音视频类应用。
配置选项
| 选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
JPEG_ENC_ONLY_Y | 宏(encoder_one_jpeg.c) | 未定义 | 定义后强制只编码 Y 平面,UV 填充 0x80,节省编码带宽 |
JPEG_SAVE_FILE_YUV | 宏(decoder_one_jpeg.c) | 1 | 解码输出保存格式:1 保存 YUV,0 保存 RGB565 |
q_val | yuv_enc_jpeg 参数 | 调用方指定 | 编码质量 0-13,值越大质量越高、体积越大 |
jpg_buf_size | yuv_enc_jpeg 参数 | 调用方指定 | JPG 输出缓冲长度,建议:≤320×240→30K、480×320→40K、640×480→50K、1280×720→90K |
yuvdata_size | yuv_enc_jpeg 参数 | 调用方指定 | 决定采样格式:w*h*3→YUV444、w*h*2→YUV422、w*h→仅 Y(YUV420) |
API Reference
int yuv_enc_jpeg(char *yuvdata, int yuvdata_size, char *jpg_buf, int jpg_buf_size, int width, int height, int q_val)
把 YUV(或仅 Y)数据编码为 JPG。位于 encoder_one_jpeg.c。
参数:
yuvdata(char*):YUV 或 Y 数据源地址yuvdata_size(int):源数据长度,用于推断采样格式jpg_buf(char*):JPG 输出缓冲jpg_buf_size(int):输出缓冲长度(见上表建议值)width/height(int):图像分辨率q_val(int):编码质量 0-13
返回: 实际编码的 JPG 字节数(非 0);失败返回 0。
说明: 内部调用 jpeg_encode_one_image(asm/jpeg_codec.h)。only_y 模式会临时 malloc YUV420 缓冲并在返回前释放。
void encoder_one_jpeg(const char *path, int width, int height)
文件级编码示例:读取 YUV 文件 → 编码 → 写 JPG 文件。位于 encoder_one_jpeg.c。
参数:
path(const char*):源 YUV 文件路径width/height(int):YUV 分辨率
返回: 无(结果打印到日志)。
int decoder_one_jpeg(const char *path)
文件级解码示例:读取 JPG 文件 → 解析信息 → 解码 → 保存 YUV/RGB565。位于 decoder_one_jpeg.c。
参数:
path(const char*):JPG 文件路径
返回: 0 成功;非 0 失败(文件不存在、缓冲申请失败、解析失败等,均打印错误日志)。
硬件接口(asm/jpeg_codec.h,芯片库提供)
| 函数 | 作用 |
|---|---|
jpeg_codec_init() | 初始化 JPEG 编解码硬件 |
jpeg_encode_one_image(struct jpeg_encode_req *req) | 单帧 YUV → JPG 编码,成功返回 0,req.data.len 回写实际长度 |
jpeg_decode_image_info(struct jpeg_image_info *info) | 解析 JPG 头信息(宽/高/采样格式),成功返回 0 |
jpeg_decode_one_image(...) | 单帧 JPG → YUV 解码 |
上述硬件接口的具体签名以 SDK 芯片库头文件为准,本仓库应用层仅通过
#include "asm/jpeg_codec.h"使用。
失败模式与边界情况
源码中体现的失败处理模式如下:
| 场景 | 处理方式 | 来源 |
|---|---|---|
| 文件不存在 | 打印 no file name 并 goto exit 返回 0 | encoder_one_jpeg.c |
| 内存申请失败 | 打印 xxx malloc err,goto exit 统一清理 | decoder_one_jpeg.c |
| 文件读取长度不匹配 | fread 返回值校验,失败即退出 | encoder_one_jpeg.c |
| JPG 信息解析失败 | jpeg_decode_image_info 非 0 → 打印并退出 | decoder_one_jpeg.c |
| 硬件编码失败 | jpeg_encode_one_image 非 0 → 返回 0 表示失败 | encoder_one_jpeg.c |
| 未知采样格式 | 解码默认按 YUV422(ytype=2)处理,避免崩溃 | decoder_one_jpeg.c |
边界情况:
- YUV420 缓冲布局:
yuv_enc_jpeg假设 U 平面紧邻 Y(偏移w*h)、V 平面偏移w*h + w*h/4。调用方传入非连续三平面数据时需自行拷贝为连续布局。 - 输出缓冲不足:JPG 编码质量高、画面复杂时可能超出
jpg_buf_size,jpeg_encode_one_image将失败。示例注释给出的 30K-100K 建议值正是为了规避该问题;更高分辨率(如 720P)需按 90K 以上配置。 - 仅 Y 输入的色度填充:
only_y路径把 UV 填 0x80(128,即中性灰),编码结果可正常解码显示,但画面为灰度效果——这是设计上"省内存换灰度"的取舍。
并发与资源竞争:
- 示例代码为单线程串行流程,
jpeg_codec_init()与编解码调用之间没有加锁;若多任务同时调用编解码(例如录像与预览并发),需要在应用层互斥,避免硬件编解码器被抢占。 - 所有临时缓冲(YUV、JPG、AVI 封装)均来自
malloc,在内存紧张的 MCU 上需评估峰值占用:录像链路典型同时存在"YUV 帧缓冲 + JPG 输出缓冲 + AVI 写缓冲"三份内存。
性能与运维注意事项
- 硬件加速是性能基石:编解码由硬件完成(
asm/jpeg_codec.h),应用层瓶颈在内存拷贝(memcpy/memset)与文件 I/O,而非 CPU 计算。only_y模式通过减少色度数据处理量进一步提升帧率。 - 缓冲大小即帧率上限:JPG 输出缓冲越大,单帧可容纳的细节越多;但过大的
malloc会抬高内存峰值。建议按目标分辨率上限配置(见配置表),并在初始化时一次性分配、循环复用。 - 文件 I/O 建议:录像/播放场景使用
flen/fread/fwrite流式读写;网络播放(net_avi_player)则依赖curl_get_data的分块拉取,避免整文件缓存。 - 日志输出成本:示例在编码/解码关键点大量使用
printf,量产代码建议按日志级别裁剪,避免在高帧率循环中拖慢吞吐。
扩展点
- 新图像格式支持:
decoder_one_jpeg的switch (info.sample_fmt)分支是扩展点——在JPG_SAMP_FMT_YUV444/420之外增加新格式时,只需补充ytype映射与缓冲计算。 - 输出格式切换:
JPEG_SAVE_FILE_YUV宏与yuv_to_rgb.h提供 YUV/RGB565 双输出,可进一步扩展为 RGB888 等。 - 流水线组装:
video_pipeline.c(wifi_bbm)把采集/编码/传输/解码/显示抽象为可配置管线,新增"录制到云端"等能力时可在该层插入新节点,复用yuv_enc_jpeg与net_avi_player的组件。 - UI 侧集成:
lv_video_to_images允许把视频帧转为 LVGL 图片资源,是 UI 预览类功能的扩展入口。
测试情况
本仓库 sdk/apps/common/video/ 下的 encoder_one_jpeg.c、decoder_one_jpeg.c、video_rec_demo.c、video_dec_demo.c、net_avi_player/play_demo.c 本身就是可独立运行的演示程序(demo),承担了"功能验证"角色:它们演示了 API 的正确调用顺序(初始化 → 编解码 → 落盘/显示)与预期的日志输出(jpeg_encode_one_image ok、jpeg yuv444, pix : WxH 等),可作为回归验证的基线。未发现独立的自动化单元测试文件。
Related Links
- encoder_one_jpeg.c — YUV 编码 JPG 应用层实现
- decoder_one_jpeg.c — JPG 解码 YUV 应用层实现
- get_yuv_data.c — YUV 数据获取
- jpg2avi.c — JPG 帧封装 AVI 容器
- logo_show.c — Logo 叠加
- user_video_rec.c / user_video_disp.c — 录像与显示上层应用
- net_avi_player/ — 网络 AVI 播放器
- lv_video_to_images.h — LVGL 视频转图片
- video_pipeline.c — wifi_bbm 视频流管线
- usb_video.c — USB 摄像头 Host(兄弟页面主题)