多媒体框架
支持的芯片:[RTL8735C]
概述
SDK 提供轻量化的 多媒体框架 (MMF),用于让音频与视频 pipeline 的开发更模块化、更直观。每个功能组件,包括 video capture、audio capture、H.264/HEVC encoding、AAC encoding/decoding、RTSP streaming、USB UVC output、MP4 recording 以及 neural network inference,都会以独立 module 的形式实现。开发者可通过打开所需 module、配置参数,并使用 linker 将 module 连接起来,建立完整 pipeline。
这种模块化设计具备以下优点:
每个 module 都可以独立开发、测试与替换。
不同复杂度的 pipeline 都使用相同的 API pattern 建立。
若要替换输出目标(例如从 RTSP 改为 UVC,或从 RTSP 改为 MP4),通常只需要改变 module 之间的连接方式。
若要将 NN inference 加入既有 pipeline,只需打开 VIPNN module,并将其插入数据路径。
MMF 运行在 FreeRTOS 上,并采用 producer-consumer model:module 会将处理后的 frame 放入 output queue,linker task 再从 queue 中取出 frame,并推送到下一个 module 的 input。因此,module 之间的数据传递是异步且 thread-safe 的。
视频管线架构
在 video 应用中,平台内部会使用两个 core。AP core (CA32) 运行用户侧 media application,例如 RTSP、UVC、MP4 recording 或 NN 示例。VP core (KM4) 运行 Realtek 提供的 video firmware,负责 camera、ISP、encoder 与 video frame export path。
从应用开发者的角度来看,AP 侧的 video_module 是主要接口。开发者在 AP 侧配置 stream 参数、打开 MMF module,并使用 linker 将 module 连接起来。底层 ISP 与 encoder driver 流程则由 VP firmware 处理。
AP 内部会将 video control command 发送到 VP,VP 再将产生的 frame 推回 AP 侧 MMF pipeline。多数应用不需要直接调用 IPC API。
备注
应用开发者只需要专注于 AP 侧应用开发。IPC 机制与 VP 侧 firmware 由 Realtek 提供。本图仅用于帮助用户理解整体 video 架构。
框架架构
下图说明典型 pipeline 中的数据流向:
┌─────────────┐ mm_queue_item_t ┌──────────────┐ mm_queue_item_t ┌──────────────┐
│ Module A │ ──────────────────> │ Linker │ ──────────────────> │ Module B │
│ (Producer) │ │ (SISO/MIMO) │ │ (Consumer) │
└─────────────┘ └──────────────┘ └──────────────┘
每个 module 都维护自己的 internal output queue。当 module 完成一帧数据处理后,会将对应的 mm_queue_item_t 放入 output queue。linker task 会持续从 queue 中取出 item,并转发到 pipeline 中的下一个 module。Frame buffer 会由 framework 内部回收,因此应用程序不需要自行管理 buffer lifetime。
关键概念
模块 (``mm_module_t``)
模块由 mm_module_t 结构定义,是独立的处理单元。它提供标准接口:create、destroy、control 与 handle。可用模块 章节列出所有 module 及其用途。
模块上下文 (``mm_context_t``)
调用 mm_module_open() 会分配并返回 mm_context_t handle。该 opaque handle 会保存 module 的内部状态、queue pair,以及指向 private instance data 的指针。后续所有配置与连接操作都会使用这个 handle。
mm_context_t *ctx = mm_module_open(&video_module);
队列项 (``mm_queue_item_t``)
模块之间会以 mm_queue_item_t item 的形式传递数据。对应用开发者最重要的字段如下:
字段 |
说明 |
|---|---|
|
指向 frame payload 的指针(encoded bitstream、 raw PCM 等) |
|
Payload size,单位为 byte |
|
Codec 或数据类型( |
|
Frame timestamp,单位为 ms |
|
Allocation mode: |
STATIC 与 DYNAMIC 分配模式
初始化 module queue(MM_CMD_INIT_QUEUE_ITEMS)时,需要在两种 allocation mode 中选择一种:
MMQI_FLAG_STATIC:所有 queue item buffer 会在启动时一次性预分配。Buffer size 固定。适合 audio(frame size 固定,latency 可预测)。MMQI_FLAG_DYNAMIC:buffer 会依照需求从 heap 动态分配。适合 frame size 会逐帧变化的 video stream(例如压缩后的 H.264)。弹性较高,但会使用 heap memory。
一般建议:audio module 使用 MMQI_FLAG_STATIC,video module 使用 MMQI_FLAG_DYNAMIC。
链接器 (Linker)
Linker 是一个 FreeRTOS task,会持续从一个 module 的 output queue 读取 item,并推送到下一个 module 的 input。可用的 linker topology 有四种:
类型 |
Topology |
典型用途 |
|---|---|---|
SISO |
1 input -> 1 output |
单一 stream 片段 |
MIMO |
最多 4 inputs -> 最多 4 outputs (可为每个 output 指定 dependency mask) |
从共用 source 同时进行 A/V recording 与 streaming |
MISO |
Multiple inputs -> 1 output |
Audio mixing |
SIMO |
1 input -> multiple outputs |
将一个 stream 复制给多个 consumer |
模块生命周期
所有 module 都遵循相同的初始化顺序:
// 1. Open the module — returns a context handle
mm_context_t *ctx = mm_module_open(&xxx_module);
if (!ctx) goto error;
// 2. Configure parameters
mm_module_ctrl(ctx, CMD_XXX_GET_PARAMS, (int)¶ms); // read defaults (optional)
params.field = value;
mm_module_ctrl(ctx, CMD_XXX_SET_PARAMS, (int)¶ms);
// 3. Set queue depth and allocate queue items
mm_module_ctrl(ctx, MM_CMD_SET_QUEUE_LEN, 6);
mm_module_ctrl(ctx, MM_CMD_INIT_QUEUE_ITEMS, MMQI_FLAG_STATIC); // or MMQI_FLAG_DYNAMIC
// 4. Apply (start the module)
mm_module_ctrl(ctx, CMD_XXX_APPLY, 0);
标准 control command (所有 module 都可接受):
Command |
说明 |
|---|---|
|
设置 queue depth(item 数量) |
|
分配 queue item(arg: |
|
清除 queued item |
Queue depth 建议:
Video module(encoded output):
60个 item,搭配MMQI_FLAG_DYNAMICAudio module:
6个 item,搭配MMQI_FLAG_STATICNN / post-processing:
6个 item,搭配MMQI_FLAG_DYNAMIC
较深的 video queue 可吸收 encoder 的 burst output,并在 downstream module 短时间忙碌时避免 frame drop。
Teardown 顺序
请务必先拆除 linker,再关闭 module:
// 1. Stop and delete linkers first
siso_stop(siso);
siso_delete(siso);
// 2. Then close modules
mm_module_close(ctx);
如果 module 已关闭但 linker 仍在运行,linker task 会访问已释放的 memory。
Linker API
SISO
SISO 用于连接一个 module output 到一个 module input。每个 SISO instance 会建立一个 FreeRTOS task。
mm_siso_t *siso = siso_create();
siso_ctrl(siso, MMIC_CMD_ADD_INPUT, (uint32_t)src_ctx, 0);
siso_ctrl(siso, MMIC_CMD_ADD_OUTPUT, (uint32_t)dst_ctx, 0);
// Optional tuning
siso_ctrl(siso, MMIC_CMD_SET_STACKSIZE, 32 * 1024, 0); // stack size in bytes
siso_ctrl(siso, MMIC_CMD_SET_TASKPRIORITY, 3, 0); // FreeRTOS priority
siso_start(siso);
其他 SISO 操作:
siso_pause(siso); // temporarily halt data flow
siso_resume(siso); // resume
siso_stop(siso); // stop the task
siso_delete(siso); // free all resources
MIMO
MIMO 用于连接多个 input 到多个 output。每个 output 会建立自己的 FreeRTOS task,output_dep bitmask 用于控制某个 output task 在转发数据前,需要等待哪些 input 已就绪。单一 MIMO instance 因此可同时处理来自三个共用 input source 的 MP4 recording(V1 + audio)与 RTSP streaming(V2 + audio)。
mm_mimo_t *mimo = mimo_create();
mimo_ctrl(mimo, MMIC_CMD_ADD_INPUT0, (uint32_t)video_v1_ctx, 0); // input 0: V1 stream
mimo_ctrl(mimo, MMIC_CMD_ADD_INPUT1, (uint32_t)video_v2_ctx, 0); // input 1: V2 stream
mimo_ctrl(mimo, MMIC_CMD_ADD_INPUT2, (uint32_t)aac_ctx, 0); // input 2: audio
// Output 0 (MP4): waits for V1 and audio to both be ready
mimo_ctrl(mimo, MMIC_CMD_ADD_OUTPUT0, (uint32_t)mp4_ctx,
MMIC_DEP_INPUT0 | MMIC_DEP_INPUT2);
// Output 1 (RTSP): waits for V2 and audio to both be ready
mimo_ctrl(mimo, MMIC_CMD_ADD_OUTPUT1, (uint32_t)rtsp_ctx,
MMIC_DEP_INPUT1 | MMIC_DEP_INPUT2);
mimo_start(mimo);
Dependency bitmask 常量:
常量 |
Bit |
|---|---|
|
0x01 |
|
0x02 |
|
0x04 |
|
0x08 |
MIMO 支持选择性 pause 与 resume:
mimo_pause(mimo, pause_mask); // pause specific inputs or outputs
mimo_resume(mimo); // resume all outputs
MISO
MISO (Multiple Input, Single Output) 会从多个 source 收集 frame,并送入一个 downstream module。典型用途是 audio mixing,也就是在编码前混合多个 PCM source。
mm_miso_t *miso = miso_create();
miso_ctrl(miso, MMIC_CMD_ADD_INPUT0, (uint32_t)audio_ctx_a, 0);
miso_ctrl(miso, MMIC_CMD_ADD_INPUT1, (uint32_t)audio_ctx_b, 0);
miso_ctrl(miso, MMIC_CMD_ADD_OUTPUT, (uint32_t)aac_ctx, 0);
miso_start(miso);
SIMO
SIMO (Single Input, Multiple Output) 会将一个 module 的输出送给多个 downstream consumer。Framework 会自动处理 buffer sharing 与 recycling;应用程序只需要照常连接 module 并启动 linker。
mm_simo_t *simo = simo_create();
simo_ctrl(simo, MMIC_CMD_ADD_INPUT, (uint32_t)video_v1_ctx, 0);
simo_ctrl(simo, MMIC_CMD_ADD_OUTPUT0, (uint32_t)rtsp_ctx, 0);
simo_ctrl(simo, MMIC_CMD_ADD_OUTPUT1, (uint32_t)uvcd_ctx, 0);
simo_start(simo);
常用 linker control command
Command |
说明 |
|---|---|
|
连接 port N 上的 input module |
|
连接 port N 上的 output module |
|
FreeRTOS task stack size(byte) |
|
FreeRTOS task priority |
|
Control command timeout(ms) |
Stack size 参考值
Linker task 的 stack 必须足以容纳 downstream module 的 handler。如果 stack 太小,FreeRTOS 会发生 stack-overflow 并复位系统。
场景 |
建议大小 |
|---|---|
Simple pass-through(mux/demux) |
8 - 16 KB |
Video encoding(H.264 / HEVC) |
32 KB |
Audio encoding(AAC) |
44 KB |
NN inference(VIPNN) |
32 - 64 KB |
任务优先级建议
Linker task 的默认 priority 为 1``(``tskIDLE_PRIORITY + 1)。可依照系统调度需求调整 priority。请勿将 linker task priority 提高到 5 以上,因为过高的 priority 可能会阻塞 ISP 与 encoder driver task,造成 frame drop。
可用模块
AP 侧 multimedia framework 提供以下 module:
模块 |
头文件 |
说明 |
|---|---|---|
|
|
Video capture 与 encoding(H.264 / HEVC / JPEG / RGB) |
|
|
通过 AMIC / DMIC / DAC 进行 audio capture 与 playback |
|
|
AAC audio encoder |
|
|
AAC audio decoder(用于 playback) |
|
|
RTP audio receiver(用于 two-way audio) |
|
|
通过网络进行 live audio/video streaming 的 RTSP server |
|
|
USB UVC device,将 video stream 输出到 USB host |
|
|
用于 SD card recording 的 MP4 file muxer |
|
|
VIP neural network inference(object / face detection) |
|
|
Face recognition:比较 MobileFaceNet embedding 与已保存的 identity database |
|
|
用于 offline testing 的 synthetic data source(不需要 ISP) |
|
|
通用 file saver |
关键 module 参数会在各自的使用指南中说明。以下章节概述最重要的配置点。
video_module
video_module 封装 ISP 与 hardware encoder。依照 format 字段设置,它可输出 raw(RGB / NV12)或 compressed(H.264 / HEVC / JPEG)数据。
ISP 最多支持 5 个同时输出的 channel。每个 video_module instance 会占用一个 channel,并由 stream_id 参数选择:
Channel |
典型格式 |
典型用途 |
|---|---|---|
V1 |
H.264 或 HEVC,高分辨率 |
Recording (MP4) 或主要 RTSP stream |
V2 |
H.264,中分辨率 |
第二路 RTSP stream 或 UVC |
V3 |
H.264 或 JPEG,低分辨率 |
Thumbnail、snapshot |
V4 |
JPEG |
Still capture |
V5 |
RGB888 或 NV12 |
Neural network inference input |
V5 较特殊:hardware encoder 会被 bypass,raw RGB 或 NV12 frame 会直接传给 downstream module,通常是 vipnn_module。
video_params_t video_params = {
.stream_id = V1_STREAM_ID, // 0–4, selects the ISP output channel
.format = VIDEO_H264, // VIDEO_HEVC, VIDEO_JPEG, VIDEO_RGB, VIDEO_NV12
.width = 1920,
.height = 1080,
.fps = 30,
.gop = 30, // keyframe interval (frames)
.bps = 2000000, // target bitrate in bps
.rc_mode = ENC_VBR, // ENC_VBR, ENC_CBR, ENC_ABR
};
mm_module_ctrl(video_ctx, CMD_VIDEO_SET_PARAMS, (int)&video_params);
mm_module_ctrl(video_ctx, MM_CMD_SET_QUEUE_LEN, 60);
mm_module_ctrl(video_ctx, MM_CMD_INIT_QUEUE_ITEMS, MMQI_FLAG_DYNAMIC);
mm_module_ctrl(video_ctx, CMD_VIDEO_APPLY, 0);
Runtime 调整:module 运行后,可在不重启 pipeline 的情况下动态修改 bitrate 与 frame rate:
mm_module_ctrl(video_ctx, CMD_VIDEO_BITRATE, 1500000); // change target bitrate (bps)
mm_module_ctrl(video_ctx, CMD_VIDEO_FPS, 20); // change frame rate
强制 keyframe:当新的 RTSP client 连接时,可调用此 command,让 client 不必等待下一次自然产生的 keyframe 即可开始解码:
mm_module_ctrl(video_ctx, CMD_VIDEO_FORCE_IFRAME, 0);
audio_module
audio_module 在同一个 module instance 中同时处理 capture(microphone)与 playback(DAC)路径。
audio_params_t audio_params;
mm_module_ctrl(audio_ctx, CMD_AUDIO_GET_PARAMS, (int)&audio_params); // read defaults
audio_params.sample_rate = ASR_16KHZ; // ASR_8KHZ, ASR_16KHZ, ASR_48KHZ
audio_params.channel = 1;
audio_params.use_mic_type = USE_AUDIO_AMIC; // or DMIC_LEFT, DMIC_RIGHT
audio_params.mic_gain = MIC_20DB;
audio_params.enable_record = 1;
audio_params.avsync_en = 1; // enable A/V sync timestamps (required for MP4)
mm_module_ctrl(audio_ctx, CMD_AUDIO_SET_PARAMS, (int)&audio_params);
mm_module_ctrl(audio_ctx, MM_CMD_SET_QUEUE_LEN, 6);
mm_module_ctrl(audio_ctx, MM_CMD_INIT_QUEUE_ITEMS, MMQI_FLAG_STATIC);
mm_module_ctrl(audio_ctx, CMD_AUDIO_APPLY, 0);
备注
当 audio 会与 video 在 MIMO pipeline 中组合时(MP4 recording、A/V RTSP),请设置 avsync_en = 1。此设置会为每个 audio frame 启用硬件对齐的 timestamp,使 muxer 能正确同步 audio 与 video。若未启用,MP4 文件可能出现 audio/video drift。
aac_module
aac_module 会将 PCM audio 编码为 AAC。设置参数后必须显式初始化 memory pool。
aac_params_t aac_params = {
.trans_type = AAC_TYPE_ADTS, // AAC_TYPE_RAW or AAC_TYPE_ADTS
.object_type = AAC_AOT_LC,
.sample_rate = 16000,
.channel = 1,
.bitrate = 32000,
};
mm_module_ctrl(aac_ctx, CMD_AAC_SET_PARAMS, (int)&aac_params);
mm_module_ctrl(aac_ctx, CMD_AAC_INIT_MEM_POOL, 0); // must call after SET_PARAMS
mm_module_ctrl(aac_ctx, MM_CMD_SET_QUEUE_LEN, 6);
mm_module_ctrl(aac_ctx, MM_CMD_INIT_QUEUE_ITEMS, MMQI_FLAG_DYNAMIC);
mm_module_ctrl(aac_ctx, CMD_AAC_APPLY, 0);
备注
连接 audio_module -> aac_module 的 SISO linker 必须设置较大的 stack size(44 KB),因为 AAC encoder 会在 linker task context 中运行。
siso_ctrl(siso_audio_aac, MMIC_CMD_SET_STACKSIZE, 44 * 1024, 0);
rtsp2_module
rtsp2_module 通过 RTSP 输出 video 与 audio。Video stream 与 audio stream 会使用 CMD_RTSP2_SELECT_STREAM 分别配置。
// Configure video stream (stream 0)
rtsp2_params_t rtsp2_v = {
.type = AVMEDIA_TYPE_VIDEO,
.u.v = { .codec_id = AV_CODEC_ID_H264, .fps = 30 },
};
mm_module_ctrl(rtsp_ctx, CMD_RTSP2_SELECT_STREAM, 0);
mm_module_ctrl(rtsp_ctx, CMD_RTSP2_SET_PARAMS, (int)&rtsp2_v);
mm_module_ctrl(rtsp_ctx, CMD_RTSP2_SET_APPLY, 0);
// Configure audio stream (stream 1)
rtsp2_params_t rtsp2_a = {
.type = AVMEDIA_TYPE_AUDIO,
.u.a = { .codec_id = AV_CODEC_ID_MP4A_LATM, .channel = 1, .samplerate = 16000 },
};
mm_module_ctrl(rtsp_ctx, CMD_RTSP2_SELECT_STREAM, 1);
mm_module_ctrl(rtsp_ctx, CMD_RTSP2_SET_PARAMS, (int)&rtsp2_a);
mm_module_ctrl(rtsp_ctx, CMD_RTSP2_SET_APPLY, 0);
mm_module_ctrl(rtsp_ctx, CMD_RTSP2_SET_STREAMMING, ON);
mp4_module
mp4_module 会将 video 与 audio mux 成 MP4 文件并写入 SD card。发出 CMD_MP4_START 后开始 recording。
mp4_params_t mp4_params = {
.fps = 30,
.gop = 30,
.width = 1920,
.height = 1080,
.sample_rate = 16000,
.channel = 1,
.record_length = 60, // seconds per file
.record_file_num = 5,
.record_type = STORAGE_ALL, // video + audio
.record_file_name = "mmc:/test",
.fatfs_buf_size = 32 * 1024,
};
mm_module_ctrl(mp4_ctx, CMD_MP4_SET_PARAMS, (int)&mp4_params);
mm_module_ctrl(mp4_ctx, CMD_MP4_LOOP_MODE, 0);
mm_module_ctrl(mp4_ctx, CMD_MP4_START, mp4_params.record_file_num);
vipnn_module
vipnn_module 会在 NPU 上执行 neural network inference。完整说明请参考 NN 使用指南。与 multimedia pipeline 整合时,关键是通过 CMD_VIPNN_SET_DISPPOST 注册 result callback:
static nn_data_param_t nn_input_params = {
.img = {
.width = NN_WIDTH, // incoming RGB/NV12 frame width
.height = NN_HEIGHT, // incoming RGB/NV12 frame height
},
.codec_type = AV_CODEC_ID_RGB888,
};
mm_module_ctrl(vipnn_ctx, CMD_VIPNN_SET_MODEL, (int)&NN_MODEL_OBJ);
mm_module_ctrl(vipnn_ctx, CMD_VIPNN_SET_MODEL_FILE_NAME, (int)"vfs:/model.nb");
mm_module_ctrl(vipnn_ctx, CMD_VIPNN_SET_IN_PARAMS, (int)&nn_input_params);
mm_module_ctrl(vipnn_ctx, CMD_VIPNN_SET_DISPPOST, (int)nn_display_cb);
mm_module_ctrl(vipnn_ctx, CMD_VIPNN_SET_RES_SIZE, sizeof(objdetect_res_t));
mm_module_ctrl(vipnn_ctx, CMD_VIPNN_SET_RES_MAX_zhT, 32);
mm_module_ctrl(vipnn_ctx, CMD_VIPNN_APPLY, 0);
nn_data_param_t.img.width 与 height 描述 VIPNN 实际收到的 frame。近期 SDK 示例使用完整 frame 作为 NN input;此结构中不再配置 per-frame ROI。
array_module
array_module 会将预先加载的 binary buffer 当作 video 或 audio source 重放。此 module 适合在没有 camera 或 microphone 的情况下做 offline testing。Buffer 是编译时加载到 memory 中的 raw encoded stream(例如 H.264 或 RGB frame)。
array_params_t array_params = {
.type = AVMEDIA_TYPE_VIDEO,
.codec_id = AV_CODEC_ID_RGB888,
.fps = 15,
.loop_en = 1,
.u = { .v = { .width = 416, .height = 416 } },
};
mm_module_ctrl(array_ctx, CMD_ARRAY_SET_PARAMS, (int)&array_params);
mm_module_ctrl(array_ctx, MM_CMD_SET_QUEUE_LEN, 6);
mm_module_ctrl(array_ctx, MM_CMD_INIT_QUEUE_ITEMS, MMQI_FLAG_DYNAMIC);
mm_module_ctrl(array_ctx, CMD_ARRAY_APPLY, 0);
mm_module_ctrl(array_ctx, CMD_ARRAY_STREAMING, 1); // start playback
Pipeline 示例
以下图示说明常见的 pipeline topology。各示例的完整 source code、build 说明与 compile-time option,请参考 视频使用指南 。
示例 1:单一 stream — V1 -> RTSP
这是最小且实用的 pipeline:单一路 H.264 channel 通过 RTSP live streaming 输出。若刚开始使用 MMF,建议从此示例开始。
[video_module V1: H.264 1920×1080 @ 30fps] ──SISO──> [rtsp2_module]
示例 2:NN inference — array -> VIPNN
不使用 camera 的 offline model verification。Synthetic image buffer 会通过 SISO linker 将 test frame 送入 NPU。此方式适合在连接 live ISP channel 前验证 model integration。
[array_module (RGB test image)] ──SISO──> [vipnn_module]
|
nn_display_cb()
示例 3:双 stream — V1 RTSP + V5 face detection
两个独立的 SISO pipeline 同时共享 ISP。V1 编码 H.264 并用于 RTSP streaming;V5 输出 raw RGB frame 到 face detection model。两个 pipeline 可使用不同 frame rate,且彼此不会互相干扰。
[video_module V1: H.264 1920×1080 @ 30fps] ──SISO──> [rtsp2_module]
[video_module V5: RGB 576×320 @ 15fps ] ──SISO──> [vipnn_module]
|
nn_display_cb()
示例 4:完整 A/V — MP4 recording + RTSP + NN
三个 video channel、AAC-encoded audio、MP4 file recording、RTSP live streaming 与 YOLO object detection 可通过 MIMO linker 同时运行。
┌──MIMO──> [mp4_module] (V1 + AAC)
[video_module V1: HEVC 1920×1080] ──┐ │
[video_module V2: H264 1280×720] ──┼──┤
[audio_module] ─SISO─> [aac_module]─┘ └──MIMO──> [rtsp2_module] (V2 + AAC)
[video_module V5: RGB 416×416] ──SISO──> [vipnn_module]
|
nn_display_cb()
MIMO linker 有 3 个 input 与 2 个 output。每个 output 都会通过 bitmask 指定其依赖的 input(请参考 Linker API -> MIMO):
Output 0 (MP4):
MMIC_DEP_INPUT0 | MMIC_DEP_INPUT2— V1 + AACOutput 1 (RTSP):
MMIC_DEP_INPUT1 | MMIC_DEP_INPUT2— V2 + AAC
V5 NN chain 完全独立运行,不会影响 recording 或 streaming 的 throughput。
错误处理模式
所有 module open 与 linker create 操作都可能失败。各示例中使用的标准写法会检查 return value,并在失败时跳转到 cleanup label:
mm_context_t *video_ctx = mm_module_open(&video_module);
if (!video_ctx) {
RTK_LOGE(TAG, "video open fail\n\r");
goto error;
}
mm_module_ctrl(video_ctx, CMD_VIDEO_SET_PARAMS, (int)&video_params);
mm_module_ctrl(video_ctx, MM_CMD_SET_QUEUE_LEN, 60);
mm_module_ctrl(video_ctx, MM_CMD_INIT_QUEUE_ITEMS, MMQI_FLAG_DYNAMIC);
mm_module_ctrl(video_ctx, CMD_VIDEO_APPLY, 0);
mm_siso_t *siso = siso_create();
if (!siso) {
RTK_LOGE(TAG, "siso create fail\n\r");
goto error;
}
siso_ctrl(siso, MMIC_CMD_ADD_INPUT, (uint32_t)video_ctx, 0);
siso_ctrl(siso, MMIC_CMD_ADD_OUTPUT, (uint32_t)rtsp_ctx, 0);
siso_start(siso);
return;
error:
if (siso) { siso_stop(siso); siso_delete(siso); }
if (video_ctx) { mm_module_close(video_ctx); }
return;
Debug 输出
MMF 提供可在 runtime 控制的 per-subsystem debug logging。可使用 mmf2_dbg.h 中的 macro 启用或关闭特定类别:
DBG_MMF_DEBUG_MSG_ON(_MMF_DBG_NN_); // enable NN module debug
DBG_MMF_DEBUG_MSG_ON(_MMF_DBG_LINKER_); // enable linker debug
DBG_MMF_INFO_MSG_OFF(0xFFFFFFFF); // suppress all INFO messages
常用 flag:
Flag |
Module |
|---|---|
|
video_module |
|
audio_module |
|
rtsp2_module |
|
vipnn_module |
|
Core module framework |
|
所有 linker type(SISO、MIMO 等) |
|
ISP driver |
|
Hardware encoder |