05 视频编码应用
本章节介绍 GK7206 的视频编码应用示例 —— sample_venc。该应用演示了完整的视频编码功能,包括 H.265/H.264/MJPEG 编码、RTSP 推流、多种码率控制模式、QP Map、ROI 以及 JPEG 快照等高级功能。
应用源码位于 SDK 目录 sample/venc/,是开发视频编码、推流相关应用的参考模板。
重要提示(2026-07-24 更新)
sample_venc 源码已修改,所有保存路径从 "." 改为 "/sd_card"(共 8 处)。现在从任意目录运行都直接写 /sd_card,无需 cd /sd_card。前提是 SD 卡已挂载到 /sd_card。
1 应用概述
1.1 功能特性
- 多编码格式支持:H.265、H.264、MJPEG、JPEG
- 多码流模式:主码流 + 子码流、MJPEG 流 + JPEG 快照
- 多种码率控制:CBR、VBR、AVBR、FixQP
- RTSP 推流:内置 RTSP 服务器,支持实时流推送
- 高级编码功能:
- QP Map(量化参数映射)
- ROI(感兴趣区域编码)
- 环形缓冲低延迟编码
- JPEG 快照分割放大编码
- 文件编码:支持从 YUV 文件编码为码流文件
- 自动保存路径:所有输出文件自动保存到
/sd_card
1.2 技术参数
| 参数 | 值 |
|---|---|
编码格式 | H.265、H.264、MJPEG、JPEG |
分辨率 | 根据 Sensor 配置(如 2560×1440) |
帧率 | 由 Sensor 决定(通常 30 FPS) |
码率控制模式 | CBR、VBR、AVBR、FixQP |
GOP 模式 | NORMALP、SMARTP |
RTSP 端口 | 554 |
输出路径 | /sd_card(已写死在源码中) |
内存占用 | 较高(需 sensor) |
1.3 测试用例列表
| index | 名称 | 测试指令 | 预期现象(成功) | 失败可能原因 |
|---|---|---|---|---|
| 0 | 低延迟环形缓冲 | ./sample_venc 0 | 打印 rtsp://<ip>:554/livestream/0、.../1,按非 q 键抓图 | 输出写 /tmp → Killed(OOM) |
| 1 | 主+子码流 | ./sample_venc 1 | 同上 RTSP 双流 | 同上 |
| 2 | qpmap | ./sample_venc 2 | qpmap 编码 RTSP | sensor/VB 失败 |
| 3 | roi | ./sample_venc 3 | roi 编码 RTSP | 同上 |
| 4 | mjpeg+snap | ./sample_venc 4 | mjpeg 流 + 按键抓 JPEG | 同上 |
| 5 | snap 放大 | ./sample_venc 5 | snap 分割放大编码 | 同上 |
| 文件 | YUV→码流 | ./sample_venc /sd_card/in.yuv 1920 1080 h264 | 生成编码码流文件 | yuv 文件/格式错 |
1.4 目录结构
sample/venc/
├── Makefile # 构建脚本
└── sample_venc.c # 主程序2 编译与部署
2.1 前置条件
在编译本应用之前,请确保已完成以下准备工作:
- SDK 环境已搭建:参照 SDK 编译 完成交叉编译工具链和 SDK 配置
- Sensor 已连接:需连接 SC465SL 或兼容的图像传感器
2.2 编译应用
# 进入 sample 目录
cd <SDK_PATH>/sample
# 编译 venc 示例
make -C venc clean && make -C venc或者从顶层编译:
make -C sample all2.3 部署到板端
# 挂载 SD 卡
mkdir -p /sd_card
mount -t vfat /dev/mmcblk1p1 /sd_card
# 使用 SCP 传输到开发板
scp sample/venc/sample_venc root@<板端IP>:/sd_card/
# 或通过 TFTP 下载
tftp -g -r sample_venc <板端IP>注意
SD 卡必须挂载到 /sd_card,否则程序无法保存抓图文件。
2.4 运行应用
# 添加执行权限
chmod +x /sd_card/sample_venc
# 运行(index 0:低延迟环形缓冲)
./sample_venc 0
# 交互选择码率控制模式
c # 选择 CBR
# 交互选择 GOP 模式
0 # 选择 NORMALP2.5 预期输出
Index 0: 低延迟环形缓冲
启动流程:
please input choose rc mode!
c) cbr.
v) vbr.
a) avbr.
f) fixQp
c
please input choose gop mode!
0) NORMALP.
1) SMARTP.
0
[SENSOR][Func]:sc465sl_set_slave_addr [Line]:1637 [Info]:Sensor dev [0] set slave addr 0x60 success.
[SENSOR][Func]:sc465sl_i2c_init [Line]:1664 [Info]:====== i2c[1] init success!=======
[SENSOR][Func]:sc465sl_set_wdr_mode [Line]:487 [Info]:linear mode
[sample_comm_isp_sensor_init]-368: sensor i2c_id = 1, clk_id = 1
[SENSOR][Func]:sc465sl_get_ae_common_default [Line]:858 [Info]:man_ratio_enable: 0
[SENSOR][Func]:sc465sl_calc_fps [Line]:1358 [Info]:sc465sl set fps = 30.000000
[ISP]isp_init[1113]: isp[0] init success
[ISP]isp_run[771]: isp run.
[sample_comm_vi_start_dev]-1066: mipi_rate: 864.
[ISP]isp_start[503]: isp0 start.
[SENSOR][Func]:sc465sl_4lane_linear_2560x1440_init [Line]:952 [Info]:============================================================================
[SENSOR][Func]:sc465sl_4lane_linear_2560x1440_init [Line]:953 [Info]:=== SC465SL_27MInput_MIPI_4lane_12bit_30fps_2560x1440_linear init success! =
[SENSOR][Func]:sc465sl_4lane_linear_2560x1440_init [Line]:954 [Info]:============================================================================
rtsp://192.168.49.17:554/livestream/0
rtsp://192.168.49.17:554/livestream/1
[venc] save path = /sd_card (orig '.', readonly rootfs)
---press 'q' to exit or any other key to capture pic---
[SENSOR][Func]:sc465sl_calc_fps [Line]:1358 [Info]:sc465sl set fps = 25.000000
^C[ISP]isp_stop[522]: isp0 stop.
[ISP]isp_exit[1183]: isp0 start exit
[ISP]isp_exit[1218]: isp0 exit success
[main]-1772: program exit normally!交互选择码率控制模式:
please input choose rc mode!
c) cbr.
v) vbr.
a) avbr.
f) fixQp
c交互选择 GOP 模式:
please input choose gop mode!
0) NORMALP
1) SMARTP
0成功标志:
- 显示 RTSP 地址:
rtsp://<ip>:554/livestream/0和livestream/1 - 显示
[venc] save path = /sd_card表示保存路径正确 - Sensor 初始化成功:
SC465SL_27MInput_MIPI_4lane_12bit_30fps_2560x1440_linear init success! - 显示
---press 'q' to exit or any other key to capture pic---交互提示
固定与可变部分说明
- 固定部分:Sensor 型号(SC465SL)、分辨率(2560x1440)、帧率(25/30 fps)、MIPI 速率(864)、保存路径提示
- 可变部分:RTSP URL 中的 IP 地址(根据板子网络配置变化)
Index 1: 主+子码流
预期输出:
please input choose rc mode!
c) cbr.
v) vbr.
a) avbr.
f) fixQp
c
please input choose gop mode!
0) NORMALP.
1) SMARTP.
0
[SENSOR][Func]:sc465sl_set_slave_addr [Line]:1637 [Info]:Sensor dev [0] set slave addr 0x60 success.
[SENSOR][Func]:sc465sl_i2c_init [Line]:1664 [Info]:====== i2c[1] init success!=======
[SENSOR][Func]:sc465sl_set_wdr_mode [Line]:487 [Info]:linear mode
[sample_comm_isp_sensor_init]-368: sensor i2c_id = 1, clk_id = 1
[SENSOR][Func]:sc465sl_get_ae_common_default [Line]:858 [Info]:man_ratio_enable: 0
[SENSOR][Func]:sc465sl_calc_fps [Line]:1358 [Info]:sc465sl set fps = 30.000000
[ISP]isp_init[1113]: isp[0] init success
[ISP]isp_run[771]: isp run.
[sample_comm_vi_start_dev]-1066: mipi_rate: 864.
[ISP]isp_start[503]: isp0 start.
[SENSOR][Func]:sc465sl_4lane_linear_2560x1440_init [Line]:952 [Info]:============================================================================
[SENSOR][Func]:sc465sl_4lane_linear_2560x1440_init [Line]:953 [Info]:=== SC465SL_27MInput_MIPI_4lane_12bit_30fps_2560x1440_linear init success! =
[SENSOR][Func]:sc465sl_4lane_linear_2560x1440_init [Line]:954 [Info]:============================================================================
rtsp://192.168.49.17:554/livestream/0
rtsp://192.168.49.17:554/livestream/1
[venc] save path = /sd_card (orig '.', readonly rootfs)
---------------press any key to exit!---------------
[SENSOR][Func]:sc465sl_calc_fps [Line]:1358 [Info]:sc465sl set fps = 25.000000
^C[ISP]isp_stop[522]: isp0 stop.
[ISP]isp_exit[1183]: isp0 start exit
[ISP]isp_exit[1218]: isp0 exit success
[main]-1772: program exit normally!成功标志:显示两个 RTSP 流地址,主码流(0)和子码流(1)。
固定与可变部分说明
- 固定部分:Sensor 型号、分辨率、帧率、MIPI 速率、保存路径提示
- 可变部分:RTSP URL 中的 IP 地址、交互提示(
---press 'q' to exitvs---------------press any key to exit!---------------)
Index 2: qpmap
预期输出:
please input choose gop mode!
0) NORMALP.
1) SMARTP.
0
[SENSOR][Func]:sc465sl_set_slave_addr [Line]:1637 [Info]:Sensor dev [0] set slave addr 0x60 success.
[SENSOR][Func]:sc465sl_i2c_init [Line]:1664 [Info]:====== i2c[1] init success!=======
[SENSOR][Func]:sc465sl_set_wdr_mode [Line]:487 [Info]:linear mode
[sample_comm_isp_sensor_init]-368: sensor i2c_id = 1, clk_id = 1
[SENSOR][Func]:sc465sl_get_ae_common_default [Line]:858 [Info]:man_ratio_enable: 0
[SENSOR][Func]:sc465sl_calc_fps [Line]:1358 [Info]:sc465sl set fps = 30.000000
[ISP]isp_init[1113]: isp[0] init success
[ISP]isp_run[771]: isp run.
[sample_comm_vi_start_dev]-1066: mipi_rate: 864.
[ISP]isp_start[503]: isp0 start.
[SENSOR][Func]:sc465sl_4lane_linear_2560x1440_init [Line]:952 [Info]:============================================================================
[SENSOR][Func]:sc465sl_4lane_linear_2560x1440_init [Line]:953 [Info]:=== SC465SL_27MInput_MIPI_4lane_12bit_30fps_2560x1440_linear init success! =
[SENSOR][Func]:sc465sl_4lane_linear_2560x1440_init [Line]:954 [Info]:============================================================================
rtsp://192.168.49.17:554/livestream/0
rtsp://192.168.49.17:554/livestream/1
[venc] save path = /sd_card (orig '.', readonly rootfs)
---------------press any key to exit!---------------
[SENSOR][Func]:sc465sl_calc_fps [Line]:1358 [Info]:sc465sl set fps = 25.000000
^C[ISP]isp_stop[522]: isp0 stop.
[ISP]isp_exit[1183]: isp0 start exit
[ISP]isp_exit[1218]: isp0 exit success
[main]-1772: program exit normally!成功标志:显示 qpmap 初始化成功和 RTSP 地址。
固定与可变部分说明
- 固定部分:Sensor 型号、分辨率、帧率、MIPI 速率、保存路径提示
- 可变部分:RTSP URL 中的 IP 地址
Index 3: roi
预期输出:
please input choose rc mode!
c) cbr.
v) vbr.
a) avbr.
f) fixQp
c
please input choose gop mode!
0) NORMALP.
1) SMARTP.
0
[SENSOR][Func]:sc465sl_set_slave_addr [Line]:1637 [Info]:Sensor dev [0] set slave addr 0x60 success.
[SENSOR][Func]:sc465sl_i2c_init [Line]:1664 [Info]:====== i2c[1] init success!=======
[SENSOR][Func]:sc465sl_set_wdr_mode [Line]:487 [Info]:linear mode
[sample_comm_isp_sensor_init]-368: sensor i2c_id = 1, clk_id = 1
[SENSOR][Func]:sc465sl_get_ae_common_default [Line]:858 [Info]:man_ratio_enable: 0
[SENSOR][Func]:sc465sl_calc_fps [Line]:1358 [Info]:sc465sl set fps = 30.000000
[ISP]isp_init[1113]: isp[0] init success
[ISP]isp_run[771]: isp run.
[sample_comm_vi_start_dev]-1066: mipi_rate: 864.
[ISP]isp_start[503]: isp0 start.
[SENSOR][Func]:sc465sl_4lane_linear_2560x1440_init [Line]:952 [Info]:============================================================================
[SENSOR][Func]:sc465sl_4lane_linear_2560x1440_init [Line]:953 [Info]:=== SC465SL_27MInput_MIPI_4lane_12bit_30fps_2560x1440_linear init success! =
[SENSOR][Func]:sc465sl_4lane_linear_2560x1440_init [Line]:954 [Info]:============================================================================
rtsp://192.168.49.17:554/livestream/0
rtsp://192.168.49.17:554/livestream/1
[venc] save path = /sd_card (orig '.', readonly rootfs)
---------------press any key to exit!---------------
[SENSOR][Func]:sc465sl_calc_fps [Line]:1358 [Info]:sc465sl set fps = 25.000000
^C[ISP]isp_stop[522]: isp0 stop.
[ISP]isp_exit[1183]: isp0 start exit
[ISP]isp_exit[1218]: isp0 exit success
[main]-1772: program exit normally!成功标志:显示 roi 初始化成功和 RTSP 地址。
固定与可变部分说明
- 固定部分:Sensor 型号、分辨率、帧率、MIPI 速率、保存路径提示
- 可变部分:RTSP URL 中的 IP 地址
Index 4: mjpeg+snap
预期输出:
please input choose rc mode!
c) cbr.
v) vbr.
a) avbr.
f) fixQp
c
[SENSOR][Func]:sc465sl_set_slave_addr [Line]:1637 [Info]:Sensor dev [0] set slave addr 0x60 success.
[SENSOR][Func]:sc465sl_i2c_init [Line]:1664 [Info]:====== i2c[1] init success!=======
[SENSOR][Func]:sc465sl_set_wdr_mode [Line]:487 [Info]:linear mode
[sample_comm_isp_sensor_init]-368: sensor i2c_id = 1, clk_id = 1
[SENSOR][Func]:sc465sl_get_ae_common_default [Line]:858 [Info]:man_ratio_enable: 0
[SENSOR][Func]:sc465sl_calc_fps [Line]:1358 [Info]:sc465sl set fps = 30.000000
[ISP]isp_init[1113]: isp[0] init success
[ISP]isp_run[771]: isp run.
[sample_comm_vi_start_dev]-1066: mipi_rate: 864.
[ISP]isp_start[503]: isp0 start.
[SENSOR][Func]:sc465sl_4lane_linear_2560x1440_init [Line]:952 [Info]:============================================================================
[SENSOR][Func]:sc465sl_4lane_linear_2560x1440_init [Line]:953 [Info]:=== SC465SL_27MInput_MIPI_4lane_12bit_30fps_2560x1440_linear init success! =
[SENSOR][Func]:sc465sl_4lane_linear_2560x1440_init [Line]:954 [Info]:============================================================================
[venc] save path = /sd_card (orig '.', readonly rootfs)
---press 'q' to exit or any other key to capture pic---
[SENSOR][Func]:sc465sl_calc_fps [Line]:1358 [Info]:sc465sl set fps = 25.000000
^C[ISP]isp_stop[522]: isp0 stop.
[ISP]isp_exit[1183]: isp0 start exit
[ISP]isp_exit[1218]: isp0 exit success
[main]-1772: program exit normally!成功标志:显示 MJPEG 流地址,可按按键抓 JPEG 图片。
固定与可变部分说明
- 固定部分:Sensor 型号、分辨率、帧率、MIPI 速率、保存路径提示
- 可变部分:无 RTSP URL(此模式不输出 RTSP 流)
Index 5: snap 放大
预期输出:
[SENSOR][Func]:sc465sl_set_slave_addr [Line]:1637 [Info]:Sensor dev [0] set slave addr 0x60 success.
[SENSOR][Func]:sc465sl_i2c_init [Line]:1664 [Info]:====== i2c[1] init success!=======
[SENSOR][Func]:sc465sl_set_wdr_mode [Line]:487 [Info]:linear mode
[sample_comm_isp_sensor_init]-368: sensor i2c_id = 1, clk_id = 1
[SENSOR][Func]:sc465sl_get_ae_common_default [Line]:858 [Info]:man_ratio_enable: 0
[SENSOR][Func]:sc465sl_calc_fps [Line]:1358 [Info]:sc465sl set fps = 30.000000
[ISP]isp_init[1113]: isp[0] init success
[ISP]isp_run[771]: isp run.
[sample_comm_vi_start_dev]-1066: mipi_rate: 864.
[ISP]isp_start[503]: isp0 start.
[SENSOR][Func]:sc465sl_4lane_linear_2560x1440_init [Line]:952 [Info]:============================================================================
[SENSOR][Func]:sc465sl_4lane_linear_2560x1440_init [Line]:953 [Info]:=== SC465SL_27MInput_MIPI_4lane_12bit_30fps_2560x1440_linear init success! =
[SENSOR][Func]:sc465sl_4lane_linear_2560x1440_init [Line]:954 [Info]:============================================================================
---press 'q' to exit or any other key to capture pic---
[SENSOR][Func]:sc465sl_calc_fps [Line]:1358 [Info]:sc465sl set fps = 25.000000
^C[ISP]isp_stop[522]: isp0 stop.
[ISP]isp_exit[1183]: isp0 start exit
[ISP]isp_exit[1218]: isp0 exit success
[main]-1772: program exit normally!成功标志:显示 snap 分割放大编码信息和 RTSP 地址。
固定与可变部分说明
- 固定部分:Sensor 型号、分辨率、帧率、MIPI 速率、交互提示
- 可变部分:无 RTSP URL(此模式不输出 RTSP 流)
文件编码模式
命令:./sample_venc /sd_card/in.yuv 1920 1080 h264
预期输出:
sample_venc file encode running
input file: /sd_card/in.yuv
width: 1920
height: 1080
codec: h264
...
encode completed, output: /sd_card/in.264成功标志:生成编码码流文件,如 in.264、in.265 或 in.mjpg。
错误情况
open file[./chn2_snap_0.jpg] err!原因:SD 卡未挂载或路径错误 解决:确认 SD 卡已挂载到 /sd_card
Killed原因:内存不足(OOM),输出写到了 /tmp 内存盘 解决:确认 SD 卡已挂载,检查 /sd_card 可写性
2.6 浏览器/播放器访问
使用 VLC 或 ffplay 拉流:
# 拉主码流
ffplay rtsp://<板子IP>:554/livestream/0
# 拉子码流
ffplay rtsp://<板子IP>:554/livestream/13 内部执行逻辑详解
3.1 应用架构
本应用采用以下架构:
Sensor → VI → VPSS → VENC → RTSP 推流
↓
MJPEG 流
↓
JPEG 快照3.2 视频管线初始化流程
// 步骤 1:系统初始化(配置 VB 内存池)
sample_comm_sys_init(&sys_config);
// 步骤 2:ISP 初始化
sample_comm_isp_init();
// 步骤 3:VI 启动
sample_comm_vi_start(...);
// 步骤 4:VPSS 启动
sample_comm_vpss_start(...);
// 步骤 5:VENC 启动
sample_comm_venc_start(...);
// 步骤 6:绑定模块
xmedia_bind_vi_to_vpss(...);
xmedia_bind_vpss_to_venc(...);
// 步骤 7:RTSP 推流
sample_comm_livestream_create(...);3.3 RTSP 推流实现
RTSP 推流使用内置的 live_rtsp_server 库:
// 创建 RTSP 会话
sample_comm_livestream_create(venc_chn, livestream_type);
// 启动 RTSP 服务
sample_comm_livestream_start();3.4 抓图功能
抓图功能通过按键触发:
// 等待用户输入
c = getchar();
if (c != 'q') {
// 生成 JPEG 快照
sample_venc_snap_process(venc_chn, snap_cnt);
// 打印保存路径
printf("[venc] save path = /sd_card/chn2_snap_%d.jpg\n", snap_cnt);
}3.5 源码改动(2026-07-24)
源码中 8 处保存路径从 "." 改为 "/sd_card":
// 原代码(行注释保留)
// snprintf(snap_path, sizeof(snap_path), "./chn%d_snap_%d.jpg", chn, cnt);
// 新代码
snprintf(snap_path, sizeof(snap_path), "/sd_card/chn%d_snap_%d.jpg", chn, cnt);
printf("[venc] save path = %s\n", snap_path);改动位置:
start_get_stream()函数:5 处capture_jpeg()函数:2 处splicing函数:1 处
4 关键编程要点
4.1 码率控制模式选择
应用提供交互式选择码率控制模式:
sample_rc sample_venc_get_rc_mode(void)
{
char c;
printf("please input choose rc mode!\n");
printf("\t c) cbr.\n");
printf("\t v) vbr.\n");
printf("\t a) avbr.\n");
printf("\t f) fixQp\n");
c = getchar();
switch(c) {
case 'c': return SAMPLE_RC_CBR;
case 'v': return SAMPLE_RC_VBR;
case 'a': return SAMPLE_RC_AVBR;
case 'f': return SAMPLE_RC_FIXQP;
default: goto begin_get;
}
}4.2 编码通道配置
// H.265 主码流
venc_chn_attr[0].type = XMEDIA_PT_H265;
venc_chn_attr[0].max_width = 2560;
venc_chn_attr[0].max_height = 1440;
venc_chn_attr[0].rc_mode = VENC_RC_MODE_H265CBR;
// H.264 子码流
venc_chn_attr[1].type = XMEDIA_PT_H264;
venc_chn_attr[1].max_width = 640;
venc_chn_attr[1].max_height = 480;
venc_chn_attr[1].rc_mode = VENC_RC_MODE_H264CBR;
// JPEG 快照
venc_chn_attr[2].type = XMEDIA_PT_JPEG;
venc_chn_attr[2].max_width = 2560;
venc_chn_attr[2].max_height = 1440;4.3 错误处理
每个 API 调用都应检查返回值:
ret = sample_comm_sys_init(&sys_config);
if (ret != XMEDIA_SUCCESS) {
printf("sys init failed!\n");
goto exit0;
}
ret = sample_comm_isp_init();
if (ret != XMEDIA_SUCCESS) {
printf("isp init failed!\n");
goto exit1;
}5 常见问题排查
| 问题 | 可能原因 | 解决方案 |
|---|---|---|
Killed(OOM) | 输出写 /tmp 内存盘 | 确认 SD 卡已挂载到 /sd_card |
open file[./chn2_snap_0.jpg] err! | 旧版本源码 "." 路径在只读 rootfs | 更新到新版本源码,重新编译 |
| RTSP 无法拉流 | sensor 初始化失败 | 检查 sensor 连接和配置 |
| 编码失败 | VB 内存不足 | 调整 VB Pool 配置 |
| 抓图失败 | JPEG 通道未配置 | 检查 VENC 通道配置 |
6 内存与路径管理
6.1 内存限制
本板 DDR 总量 128 MB,Linux 可用约 26 MB。视频编码占用内存较大,建议:
- 挂载 SD 卡到
/sd_card - 所有输出文件写 SD 卡
- 测前释放内存:
sync; echo 3 > /proc/sys/vm/drop_caches
6.2 路径管理
提示
源码已写死保存路径为 /sd_card,无需 cd /sd_card。但 SD 卡必须先挂载。
