媒体示例

支持的芯片:[RTL8735C]

概述

类别

示例

入口 / 源文件

说明

视频示例

mmf2_video_example_v1_rtsp_init

mmf2_video_example_v1_rtsp_init.c

V1 H.264 视频通过 RTSP 进行实时串流。

视频示例

mmf2_video_example_v1v2_mp4_rtsp_init

mmf2_video_example_v1v2_mp4_rtsp_init.c

双视频通道,同时进行 MP4 录制与 RTSP 串流。

音频示例

mmf2_example_audioloop_init

mmf2_example_audioloop_init.c

麦克风采集后直接回放到扬声器。

音频示例

mmf2_example_aacloop_init

mmf2_example_aacloop_init.c

AAC 编码 / 解码音频回环。

音频示例

mmf2_example_2way_audio_init

mmf2_example_2way_audio_init.c

通过 RTSP/RTP 实现全双工双向音频。

音频示例

audio_vqe_test

audio_vqe_test.c

使用 AEC、AGC 与噪声抑制的音频 VQE 测试。

AI 示例

人脸检测示例

mmf2_video_example_nn_face_detection_init.c

SCRFD 人脸检测,支持 UVC 或 RTSP 输出与 OSD overlay。

AI 示例

目标检测示例

mmf2_video_example_nn_object_detection_init.c

在 V5 RGB 输入上运行 YOLO/NanoDet 目标检测。

AI 示例

人脸识别示例

mmf2_video_example_nn_face_recognition_init.c

级联人脸检测、embedding、识别与 OSD overlay。

整合示例

mmf2_video_example_av_rtsp_mp4_nn_init

mmf2_video_example_av_rtsp_mp4_nn_init.c

同时运行音频、视频录制、RTSP 串流与 NN 检测。

整合示例

mmf2_video_example_joint_test_uvc_init / rtsp_init

mmf2_video_example_joint_test_init.c

AP 侧完整多媒体联合测试,包含录制、串流、NN、OSD 与文件保存。

视频示例

以下示例说明如何使用多媒体框架 (MMF) 建立视频 pipeline。

编译视频示例

编译视频示例前,必须先在 menuconfig 中启用必要选项:

./ameba.py menuconfig

进入以下路径:

(Top) > CONFIG VIDEO SOFTWARE > BUILD AP MEDIA EXAMPLE

启用该选项后,系统会自动打开视频示例所需的 module。

接着在 SDK 根目录执行以下命令,编译视频 AP 示例:

./ameba.py build --app video_ap

编译成功后,将 image 烧录到开发板,并打开串口控制台执行示例。

示例源文件

源文件位于:

component/soc/<soc>/sw/media_example/ap_media_example/video_example_src/

每个示例都会通过 VIDEO_APP_TABLE_SECTION 注册到应用表,并可通过串口控制台调用:

VIDEO list         # 列出所有已注册的视频示例
VIDEO run [n]      # 执行索引为 n 的示例(默认值为 0)

部分示例会导出多个应用表 entry。例如联合测试示例会提供独立的 UVC 与 RTSP entry,因此可直接从 VIDEO list 选择所需的输出路径,再执行对应索引。

备注

同一时间只能执行一个示例。切换到其他示例前,请先复位开发板。

备注

使用网络功能的示例(例如 RTSP 串流)需要先建立 Wi-Fi 连接。请先使用以下 AT 命令连接路由器:

AT+WLCONN=ssid,<your_ssid>,pw,<your_password>

等待出现 [$]wifi got ip 信息,确认 IP address 已分配后,再执行 video 示例。完整 Wi-Fi command 说明请参考 Wi-Fi AT Commands

mmf2_video_example_v1_rtsp_init

源文件: ap_media_example/video_example_src/mmf2_video_example_v1_rtsp_init.c

这是最简单的实时串流示例。V1 采集 H.264 视频并通过 RTSP 输出。对于刚开始使用 MMF 的开发者,建议从此示例开始;它只使用一个 video_module、一个 rtsp2_module 与一个 SISO linker。

数据流:

[Video V1: H.264 1920x1080 @ 30fps] --> SISO --> [RTSP server]

开发板运行后,可使用 VLC 或其他支持 RTSP 的播放器连接 rtsp://<device-ip>/stream

编译时选项:

#define AINR_ENA    0   /* AI noise reduction on V1; set 1 to enable */

关键说明:

  • 需要 CONFIG_LWIP_LAYER=1 (否则会出现 compile-time error)。

  • video module queue 必须使用 MMQI_FLAG_DYNAMIC,因为 H.264 frame size 会随每一帧变化。

  • Queue depth 60 可吸收 encoder burst output,并避免 frame drop。

  • 当新的 client 连接时,可在 RTSP connected callback 中调用 mm_module_ctrl(video_v1_ctx, CMD_VIDEO_FORCE_IFRAME, 0) 强制产生 keyframe。

mmf2_video_example_v1v2_mp4_rtsp_init

源文件: ap_media_example/video_example_src/mmf2_video_example_v1v2_mp4_rtsp_init.c

这是一个双通道的视频示例。V1 以全分辨率采集 HEVC,用于 SD 卡上的 MP4 录制;V2 以较低分辨率采集 H.264,用于同时进行 RTSP 实时串流。两个通道共享同一个 MIMO linker,不包含音频。

数据流:

[Video V1: HEVC 2688x1520 @ 15fps] --+
                                      +--> MIMO --> [mp4_module]   (V1 -> SD card)
[Video V2: H.264 1280x720  @ 30fps] --+
                                      +--> MIMO --> [rtsp2_module] (V2 -> RTSP)

编译时选项:

#define AINR_ENA    0   /* AI noise reduction; set 1 to enable */

关键说明:

  • 需要 CONFIG_LWIP_LAYER=1

  • V1 与 V2 可使用各自独立的 frame rate 与 bitrate;V1 用于高画质保存,V2 则针对串流带宽优化。

  • mp4_params.record_type 中设置为 STORAGE_VIDEO``(仅 video)。若需要录制 audio,可改为 ``STORAGE_ALL 并增加 audio chain。

  • MIMO dependency mask 使两个输出彼此独立:MP4 使用 MMIC_DEP_INPUT0,RTSP 使用 MMIC_DEP_INPUT1

音频示例

以下示例说明如何使用多媒体框架 (MMF) 建立音频 pipeline。示例源文件位于:

component/soc/<soc>/sw/media_example/ap_media_example/audio_example_src/

每个示例都会通过 AUDIO_APP_TABLE_SECTION 注册到应用表,并可在串口控制台中执行:

AUDIO list         # 列出所有已注册的音频示例
AUDIO run [n]      # 执行索引为 n 的示例(默认值为 0)

备注

同一时间只能执行一个示例。切换到其他示例前,请先复位开发板。

mmf2_example_audioloop_init

源文件: ap_media_example/audio_example_src/mmf2_example_audioloop_init.c

这是一个简单的音频回环示例。音频从内建麦克风 (AMIC) 采集后,会通过 audio module 立即从扬声器播放。

数据流:

[Audio Module] --> SISO --> [Audio Module]
  (capture)                   (playback)

关键参数:

audio_params.sample_rate = ASR_48KHZ;

mmf2_example_aacloop_init

源文件: ap_media_example/audio_example_src/mmf2_example_aacloop_init.c

这是一个音频编码/解码回环示例。从麦克风采集的音频会先编码为 AAC,再立即解码并播放。该示例用于说明 AAC encoder (module_aac) 与 AAC decoder (module_aad) 的 pipeline。

数据流:

[Audio] --> SISO --> [AAC Encoder] --> SISO --> [AAC Decoder] --> SISO --> [Audio]
 (capture)                                                                 (playback)

关键参数:

aac_params.sample_rate  = 16000;
aac_params.channel      = 1;         // mono
aac_params.trans_type   = AAC_TYPE_RAW;
aac_params.object_type  = AAC_AOT_LC;
aac_params.bitrate      = 32000;     // 32 kbps

aad_params.sample_rate  = 16000;
aad_params.channel      = 1;
aad_params.trans_type   = AAD_TYPE_RAW;
aad_params.object_type  = AAD_AOT_LC;

mmf2_example_2way_audio_init

源文件: ap_media_example/audio_example_src/mmf2_example_2way_audio_init.c

这是一个使用 RTSP server 与 RTP client 的双向音频串流示例。麦克风采集的音频会编码为 AAC 并通过 RTSP 输出,同时设备也会接收 RTP 音频流、进行解码,并通过扬声器播放。该示例展示完整的全双工音频通信流程。

数据流:

[Audio] --> SISO --> [aac_module] --> SISO --> [rtsp2_module] -----> (Network)
(capture)              (encode)                   (server)            (stream)

[Audio] <-- SISO <-- [aad_module] <-- SISO <-- [rtp_module] <---- (Network)
(playback)             (decode)                 (receive)            (send)

关键参数:

// Audio capture/playback
audio_params.sample_rate = ASR_16KHZ;

// AAC Encoder
aac_params.sample_rate  = 16000;
aac_params.channel      = 1;         // mono
aac_params.trans_type   = AAC_TYPE_ADTS;
aac_params.object_type  = AAC_AOT_LC;
aac_params.bitrate      = 32000;     // 32 kbps

// RTSP Server
rtsp2_params.codec_id   = AV_CODEC_ID_MP4A_LATM;
rtsp2_params.channel    = 1;
rtsp2_params.samplerate = 16000;

// RTP Receiver
rtp_params.port         = 16384;

// AAC Decoder
aad_params.sample_rate  = 16000;
aad_params.channel      = 1;
aad_params.trans_type   = AAD_TYPE_RTP_RAW;
aad_params.object_type  = AAD_AOT_LC;

使用方式:

  • 使用 VLC 或其他 RTSP client 连接 RTSP stream:rtsp://<device_ip>:554/

  • 设备默认以 16 kHz mono AAC 格式输出音频

  • 设备会同时在 port 16384 接收 RTP 音频并播放

从设备串流音频到 VLC Player

  1. 点击 Media -> Open Network Stream

  2. 输入 rtsp://<device_ip>:554/,其中 <device_ip> 为 Ameba 的 IP 地址,RTSP server 默认 port 为 554。

  3. 点击 Play

从 VLC Player 串流音频到设备

  1. 点击 Media -> Stream

  2. 选择 File,点击 Add,选择音频文件后点击 Stream

    备注

    请选择与 decoder 设置一致的音频文件格式(mono,16 kHz sampling rate)。

  3. 确认选中的文件后,点击 Next

  4. 选择 RTP Audio/Video Profile,点击 Add

  5. Address 字段输入设备 IP 地址,将 Base port 设为 16384,然后点击 Next

  6. 确认 Activate Transcoding 未勾选,点击 Next -> Stream

  7. 此时可从板子的 3.5 mm audio jack 听到声音。

audio_vqe_test

源文件: ap_media_example/audio_example_src/audio_vqe_test.c

这是一个使用 ASP (Audio Signal Processing) library 的音频 Voice Quality Enhancement (VQE) 测试示例。该示例展示包含 Acoustic Echo Cancellation (AEC)、Automatic Gain Control (AGC) 与 Noise Suppression (NS) 的音频处理 pipeline,并同时覆盖发送端(speaker)与接收端(microphone)路径。

数据流:

[Speaker] --> [VQE SND: AEC + AGC + NS] --> [Output]
                  ^
                  | (farend reference)
[Microphone] -----+

[Input] --> [VQE RCV: NS + AGC] --> [Microphone TX]

关键组件:

  • VQE_SND(发送路径): 对麦克风输入进行 AEC、AGC 与 NS 处理,以消除回声并降低噪声。

  • VQE_RCV(接收路径): 对输出数据进行 NS 与 AGC 处理,用于传输路径。

关键参数:

// Frame configuration
#define AUDIO_DMA_PAGE_SIZE 640
#define FRAME_SIZE (AUDIO_DMA_PAGE_SIZE / 2)  // 320 samples
Sample rate: 16000 Hz

// RX Path - Noise Suppression
RX_NS.NS_EN = 1;
RX_NS.NSLevel = 10;           // Suppression level when no speech
RX_NS.HPFEnable = 0;          // High-pass filter disabled

// RX Path - Automatic Level Control (ALC)
RX_AGC.AGC_EN = 1;
RX_AGC.AGCMode = CT_ALC;      // ALC mode (vs. CT_LIMITER)
RX_AGC.ReferenceLvl = 0;      // Target level 0 dBFS
RX_AGC.RatioFormat = 1;       // 8.8 fix point ratio format
RX_AGC.AttackTime = 10;       // 10 ms
RX_AGC.ReleaseTime = 50;      // 50 ms
RX_AGC.Ratio[0..2] = 50 * 256; // Compression ratio
RX_AGC.Threshold[0] = 39;     // Threshold1 in dB
RX_AGC.Threshold[1] = 70;     // Threshold2 in dB
RX_AGC.Threshold[2] = 80;     // Noise gate level in dB
RX_AGC.NoiseFloorAdaptEnable = 1;
RX_AGC.RMSDetectorEnable = 1;
RX_AGC.MaxGainLimit = 30;     // 30 dB max gain

// RX Path - Acoustic Echo Cancellation
RX_AEC.AEC_EN = 1;
RX_AEC.EchoTailLen = 60;      // Echo tail length in ms
RX_AEC.CNGEnable = 1;         // Comfort noise generation enabled
RX_AEC.PPLevel = 4;           // Post-processing level (1-18)
RX_AEC.DTControl = 1;         // Double-talk control type

// TX Path - Noise Suppression
TX_NS.NS_EN = 1;
TX_NS.NSLevel = 10;

// TX Path - Automatic Level Control
TX_AGC.AGC_EN = 1;
TX_AGC.AGCMode = CT_ALC;
TX_AGC.ReferenceLvl = 0;
TX_AGC.RatioFormat = 1;
TX_AGC.AttackTime = 10;
TX_AGC.ReleaseTime = 50;
TX_AGC.Ratio[0..2] = 50 * 256;
TX_AGC.Threshold[0] = 39;
TX_AGC.Threshold[1] = 70;
TX_AGC.Threshold[2] = 80;
TX_AGC.NoiseFloorAdaptEnable = 1;
TX_AGC.RMSDetectorEnable = 1;
TX_AGC.MaxGainLimit = 30;

ASP API 函数:

函数

说明

VQE_SND_init()

初始化发送路径 VQE(AEC + AGC + NS)

VQE_SND_process()

通过发送路径处理一帧数据

VQE_SND_destroy()

销毁发送路径 VQE context

VQE_RCV_NS_init()

初始化接收路径 noise suppression

VQE_RCV_NS_process()

通过接收路径 NS 处理一帧数据

VQE_RCV_NS_destroy()

销毁接收路径 NS context

VQE_RCV_AGC_init()

初始化接收路径 AGC

VQE_RCV_AGC_process()

通过接收路径 AGC 处理一帧数据

VQE_RCV_AGC_destroy()

销毁接收路径 AGC context

ASP 配置结构:

typedef struct CTNS_cfg_s {
    int16_t NS_EN;                    // Enable noise suppression
    int16_t NSLevel;                  // Suppression level (0-10)
    int16_t HPFEnable;                // High-pass filter enable
    int16_t NSSlowConvergence;        // Slow convergence time (ms)
    int16_t QuickConvergenceEnable;   // Quick convergence enable
} CTNS_cfg_t;

typedef struct CTAGC_cfg_s {
    int16_t AGC_EN;                   // Enable AGC
    CT_AGC_MODE AGCMode;              // CT_ALC or CT_LIMITER
    int16_t ReferenceLvl;             // Reference level in dB
    int16_t RatioFormat;              // Ratio format (0: integer, 1: 8.8 fix point)
    int16_t AttackTime;               // Attack time in ms
    int16_t ReleaseTime;              // Release time in ms
    int16_t Ratio[3];                 // Compression ratios
    int16_t Threshold[3];             // Thresholds (Threshold1, Threshold2, NoiseGateLvl)
    int16_t KneeWidth;                // Knee width
    int16_t NoiseFloorAdaptEnable;    // Noise floor adaptation enable
    int16_t RMSDetectorEnable;        // RMS detector enable
    int16_t MaxGainLimit;             // Maximum gain limit in dB
} CTAGC_cfg_t;

typedef struct CTAEC_cfg_s {
    int16_t AEC_EN;                   // Enable AEC
    int16_t EchoTailLen;              // Echo tail length in ms
    int16_t CNGEnable;                // Comfort noise generation enable
    int16_t PPLevel;                  // Post-processing level (1-18)
    int16_t DTControl;                // Double-talk control type
    int16_t ConvergenceTime;          // Convergence time
} CTAEC_cfg_t;

使用方式:

  1. 通过串口控制台执行:audio run <index>``(可使用 ``audio list 查看 index)。

  2. 示例会从 SD card 读取 pink_noise.bin 作为 farend input。

  3. 处理后的输出会保存为 asp_rx.bin

  4. 测试时长为 30 秒(可通过 AUDIO_TEST_DURATION 调整)。

注意事项:

  • 需要在 SD card 中放置 pink_noise.bin 测试文件作为 farend input。

  • 使用 16 kHz sample rate 与 320-sample frame(20 ms)。

  • 麦克风输入会经过 AEC、AGC 与 NS pipeline 处理。

AI 示例

编译 NN 视频示例

NN 视频示例作为 AP 媒体示例应用的一部分进行编译。编译前,请在 menuconfig 中打开对应选项:

CONFIG MEDIA FRAMEWORK
  -> CONFIG APPLICATION EXAMPLE
    -> CONFIG EXAMPLE MEDIA FRAMEWORK
      -> CONFIG MEDIA VIDEO APP
        -> CONFIG ENABLE NN EXAMPLE

然后在 SDK 根目录下编译 video AP application:

python3 ameba.py build --app video_ap

编译成功后,将固件映像与 LittleFS 模型映像烧录到开发板,并打开串口终端。示例会注册到 video application table,可通过命令列出并运行:

help
mmf2_video_example_v1_init

RTSP 示例运行前需要先连接路由器:

AT+WLCONN=ssid,<your_ssid>,pw,<your_password>

等待 [$]wifi got ip 表示已获取 IP 地址后,再运行 RTSP 示例。UVC 示例需要使能 CONFIG_USBD_UVC=1

人脸检测示例

源码: ap_media_example/video_example_src/mmf2_video_example_nn_face_detection_init.c

该示例将 V1 H.264 视频输出到 UVC 或 RTSP,同时在 V5 RGB stream 上运行 SCRFD 人脸检测。V1 是显示与 OSD 坐标空间,V5 是 NN 输入 stream。

数据流:

[Video V1: H.264 1920x1080@30fps] --> SISO --> [UVC / RTSP]
                                               |
                                          (OSD overlay)

[Video V5: RGB  576x320@10fps   ] --> SISO --> [VIPNN: SCRFD face detection]
                                                    |
                                               nn_display_cb()
                                               (draws boxes & landmarks)

主要编译期选项:

#define FACEDET_STREAM_WIDTH       1920
#define FACEDET_STREAM_HEIGHT      1080
#define FACEDET_STREAM_FPS         30
#define FACEDET_NN_WIDTH           576
#define FACEDET_NN_HEIGHT          320
#define FACEDET_NN_FPS             10

该示例导出两个入口:mmf2_video_example_nn_face_detection_uvc_initmmf2_video_example_nn_face_detection_rtsp_init。UVC 需要 CONFIG_USBD_UVC=1;RTSP 需要 CONFIG_LWIP_LAYER=1

目标检测示例

源码: ap_media_example/video_example_src/mmf2_video_example_nn_object_detection_init.c

该示例在 V5 RGB stream 上运行 YOLO/NanoDet 目标检测,同时将 V1 H.264 输出到 UVC 或 RTSP 并叠加 OSD。NN 输入可选择 V5 RGB(OBJDET_USE_ARRAY_INPUT=0)或 synthetic array_module buffer(OBJDET_USE_ARRAY_INPUT=1)。

模型选择:

#include "model_yolo.h"
#include "model_yolov9.h"
#define OBJDET_MODEL_OBJ    yolov4_tiny
#define OBJDET_MODEL_NAME   "vfs:/yolov4_tiny_asymu8.nb"
#define OBJDET_NN_WIDTH     416
#define OBJDET_NN_HEIGHT    416
  • Model object:可从 yolov4_tinyyolov7_tinynanodet_plus_myolov9_tiny 等模型类型中选择。

  • Model file path:支持 LittleFS(vfs:/)和 SD card(sd:)两种存储路径。

  • ResolutionOBJDET_NN_WIDTHOBJDET_NN_HEIGHT 表示输入 RGB 帧尺寸。如果该尺寸与模型 tensor 尺寸不同,模型预处理代码会在推理前对完整帧进行 resize。

  • Output sink:导出 mmf2_video_example_nn_object_detection_uvc_initmmf2_video_example_nn_object_detection_rtsp_init 两个入口。

人脸识别示例

源码: ap_media_example/video_example_src/mmf2_video_example_nn_face_recognition_init.c

该示例使用两阶段级联 NN pipeline 实现人脸检测与识别,并叠加 OSD。SCRFD 在 V5 RGB 帧中检测人脸,MobileFaceNet 提取 128 维 embedding,facerecog_module 将 embedding 与已保存数据库进行比对。已知人脸以绿色显示,未知人脸以红色显示。

数据流:

[Video V1: H.264 1920x1080 @ 30fps] --> SISO --> [UVC / RTSP]
                                                       |
                                                  (OSD overlay)

[Video V5: RGB 576x320 @ 10fps] --> SISO --> [VIPNN: SCRFD face detection]
                                                    |
                                             (cascaded output)
                                                    |
                                             [VIPNN: MobileFaceNet embedding]
                                                    |
                                             [facerecog_module: identity match]
                                                    |
                                          face_recognition_draw_object()

运行时 shell 命令:

命令

说明

FREG <name>

进入注册模式。下一张检测到的人脸会以给定名称保存。

FRRM

返回识别模式。

FRFL

vfs:/face_feature.bin 加载已注册人脸特征。

FRFS

将已注册人脸特征保存到 vfs:/face_feature.bin

FRFR

清除 RAM 中的注册特征,不影响文件。

FRLS

列出 RAM 中所有已注册人脸名称。

FRSC <score>

设置识别相似度阈值,整数除以 100。例如 FRSC 90 表示阈值为 0.90。

备注

SCRFD 阶段必须使能模块输出(CMD_VIPNN_SET_OUTPUT),并配置为 data group 起点(MM_CMD_SET_DATAGROUP, MM_GROUP_START)。MobileFaceNet 配置为 group 终点(MM_GROUP_END),并使用 VIPNN_CMODE_ALL_ROI,使其针对每个检测到的人脸执行一次。

整合示例

mmf2_video_example_av_rtsp_mp4_nn_init

源文件: ap_media_example/video_example_src/mmf2_video_example_av_rtsp_mp4_nn_init.c

这是一个完整的音视频示例,可同时进行 RTSP 实时串流、MP4 SD 卡录制与 NN 物体检测。

数据流:

[Audio (16kHz AMIC)] --> SISO --> [AAC Encoder] ---+
                                                    |
[Video V1: HEVC 2688x1520@15fps] ---+              +--> MIMO --> [MP4 Recording]
[Video V2: H.264 1280x720@30fps ] --+              |
                                    +-- MIMO ------+--> [RTSP Streaming (V2 + Audio)]

[Video V5: RGB 416x416@10fps    ] --> SISO --> [VIPNN: YOLO object detection]
                                                    |
                                               nn_display_cb()

编译时选项:

#define AINR_ENA   1  /* AI noise reduction on video channels */
#define AUDIO_ENA  1  /* enable audio for both RTSP and MP4 */
#define NN_ENA     1  /* enable NN object detection on V5 */

视频参数(V1 用于 MP4 录制):

video_v1_params.format  = VIDEO_HEVC;
video_v1_params.width   = 2688;
video_v1_params.height  = 1520;
video_v1_params.fps     = 15;
video_v1_params.bps     = 2000000;
video_v1_params.rc_mode = ENC_VBR;

视频参数(V2 用于 RTSP 串流):

video_v2_params.format  = VIDEO_H264;
video_v2_params.width   = 1280;
video_v2_params.height  = 720;
video_v2_params.fps     = 30;
video_v2_params.bps     = 500000;

MP4 录制参数:

mp4_params.record_length    = 10;                  // seconds per file
mp4_params.record_file_num  = 3;                   // rolling 3 files
mp4_params.record_file_name = "AmebaPro_recording";
mp4_params.mp4_audio_format = AUDIO_AAC;

NN model:

#define NN_MODEL_OBJ    yolov4_tiny
#define NN_MODEL_NAME   "vfs:/yolov4_tiny_asymu8.nb"
#define NN_WIDTH        416
#define NN_HEIGHT       416

mmf2_video_example_joint_test_uvc_init / rtsp_init

源文件: ap_media_example/video_example_src/mmf2_video_example_joint_test_init.c

这是完整的联合测试示例,最多可启用 5 个同时运行的视频通道,并可选择启用 AI 噪声抑制、实时串流(UVC 或 RTSP)、MP4 录制、带 OSD overlay 的 NN 检测,以及文件保存。该示例用于验证 AP 侧多媒体管线的完整功能。

SDK 现在会为该源文件注册两个 runtime entry:

mmf2_video_example_joint_test_uvc_init
mmf2_video_example_joint_test_rtsp_init

两个 entry 共用相同的内部初始化流程。所选的 VIDEO list entry 会在 module 打开前设置 V2 live-stream sink:UVC entry 将 V2 路由到 uvcd_module;RTSP entry 将 V2 路由到 rtsp2_module

通道配置:

Ch

ID

默认分辨率 / 格式

用途

V1

0

HEVC 2688x1520 @ 15fps

视频录制 (MP4)

V2

1

H.264 1280x720 @ 30fps

实时串流 (UVC / RTSP)

V3

2

JPEG 1920x1080 @ 1fps

JPEG 抓图

V4

3

NV12 640x480 @ 10fps

运动检测

V5

4

RGB 416x416 @ 10fps

NN AI 检测

编译时选项:

#define V1_ENA     1  /* enable V1 channel */
#define V2_ENA     1  /* enable V2 channel */
#define V3_ENA     1  /* enable V3 channel */
#define V4_ENA     1  /* enable V4 channel */
#define V5_ENA     1  /* enable V5 channel */

#define AINR_ENA   1  /* AI noise reduction */
#define MP4_ENA    1  /* MP4 SD card recording on V1 */
#define NN_ENA     0  /* NN object detection on V5 */
#define NN_OSD_ENA 1  /* draw NN detection result on V2 stream */

#define V5_RGB_WIDTH  416
#define V5_RGB_HEIGHT 416

V2 输出目标不再由 VAPP 命令选择。请先通过 VIDEO list 选择 UVC entry 或 RTSP entry,再执行该示例。UVC entry 需要 CONFIG_USBD_UVC=1。RTSP entry 需要 CONFIG_LWIP_LAYER=1,并会等待 Wi-Fi 连接完成后再打开 rtsp2_module

NN 模型选择:

/* Supported models: yolov4_tiny, yolov7_tiny, nanodet_plus_m */
#define NN_MODEL_OBJ    yolov4_tiny
#define NN_MODEL_NAME   "vfs:/yolov4_tiny_asymu8.nb"  /* or "sd:yolov4_tiny_asymu8.nb" */
#define NN_WIDTH        416
#define NN_HEIGHT       416

如果所选 .nb 包含预处理或缩放 layer,请将 V5_RGB_WIDTH / V5_RGB_HEIGHT 设为实际 V5 RGB 输出尺寸,并维持 NN_WIDTH / NN_HEIGHT 为 detector 的逻辑输入尺寸。示例会将两组数值都传给 VIPNN:

static nn_data_param_t nn_input_params = {
    .img = {
        .width = V5_RGB_WIDTH,
        .height = V5_RGB_HEIGHT,
        .model_width = NN_WIDTH,
        .model_height = NN_HEIGHT,
    },
    .codec_type = AV_CODEC_ID_RGB888
};

NN 物体类别过滤:

该示例支持依照 class ID 过滤检测到的物体:

static int desired_class_list[] = {0};  /* 0: person (COCO dataset) */

只有符合 desired_class_list[] 中 class ID 的物体才会显示。可参考 COCO dataset class labels 获取可用的 class ID。

NN OSD overlay 功能:

启用 NN_OSD_ENA 后,该示例会使用 nn_osd_group API 将检测到的物体 bounding box 绘制到 V2 串流通道。该 group 会为每个 color layer 管理一个 1bpp bitmap canvas,自动分配 hardware OSD index,并可在 NN callback 停止时通过 watchdog 清除过期 overlay。

OSD group 会初始化一次(lazy initialization,可每帧安全调用),并在每次 callback 中更新:

static nn_osd_group_t osd_group;
static const nn_osd_layer_config_t osd_layer[] = {
    {
        .stream_id = V2_STREAM_ID,
        .alpha = 128,  /* OSD alpha */
        .y = 0,        /* green Y */
        .u = 0,        /* green U */
        .v = 0,        /* green V */
    },
};

/* In the NN display callback: */
nn_osd_group_init(&osd_group, im_w, im_h, osd_layer, 1, 0 /* no watchdog */);
nn_osd_group_lock(&osd_group);
nn_osd_group_clear(&osd_group);

nn_osd_coord_map_t map;
nn_osd_coord_map_init(&map, im_w, im_h, im, NN_OSD_SCALE_STRETCH);
/* for each detection: */
nn_osd_canvas_t *canvas = nn_osd_group_canvas(&osd_group, NN_OSD_LAYER);
nn_osd_coord_map_bbox(&map, rx0, ry0, rx1, ry1, &xmin, &ymin, &xmax, &ymax);
nn_osd_draw_rect(canvas, xmin, ymin, xmax, ymax, 10);
nn_osd_draw_stringf(canvas, xmin, ymin - 24, 3, "%s %d", label, score);

nn_osd_group_flush(&osd_group);
nn_osd_group_unlock(&osd_group);

运行时测试命令:

联合测试示例也会注册 CmdApVideoAppTest(),并通过 VAPP console command 暴露。以下命令用于在不重新编译 firmware 的情况下进行动态验证:

与 encoder 相关的运行时命令只覆盖 bitrate/QP、GOP 与 force-I-frame,不会修改只适合初始化阶段设置的 encoder header、VUI、HRD 或 profile-level 配置。其他 VAPP command,例如 OSD、AINR 与 NN 控制,是示例层级的运行时控制,不会修改 encoder init-only 设置。

命令

说明

VAPP bps <ch> <bps>

在 runtime 修改 channel ch 的 encoder bitrate。例如:VAPP bps 1 4000000VAPP bps 1 256000

VAPP qp <ch> <min_qp> <max_qp>

修改 channel ch 的 encoder QP range。例如:VAPP qp 1 26 28VAPP qp 1 45 48

VAPP gop <ch> <gop>

修改 channel ch 的 encoder GOP length。

VAPP i <ch>

强制通道 ch 输出 I-frame。此命令适用于修改 bitrate/QP 后,或串流客户端重新连接时。

VAPP osd <ch> <idx> <fmt> <x> <y> <w> <h> <alpha> <Y> <U> <V> <bitmap_addr>

手动更新 hardware OSD bitmap 参数。例如:VAPP osd 1 0 0 100 100 320 320 128 200 200 200 0x80000000

VAPP ainr <0|1>

全局关闭或启用 AI noise reduction。例如:VAPP ainr 1

VAPP nn <0|1>

暂停或恢复 VIPNN inference。当 NN_OSD_ENA=1 且 inference 暂停时,示例会清除 V2 OSD canvas。

VAPP stop

停止 joint test 示例,并以反向顺序 de-initialize linker/module。

备注

VAPP command 不再用于切换 V2 sink。如需切换,请先使用 VAPP stop 停止当前示例,再通过 VIDEO listVIDEO run [n] 启动 UVC 或 RTSP joint-test entry。

FileSaver module:

当某个 channel 的主要输出通过编译时 flag 关闭时,该 channel 可能会 fallback 到 filesaver_module consumer。MP4_ENA=0 时,V1 会使用 FileSaver;V3(JPEG snapshot)与 V4(NV12 motion detection)始终路由到 FileSaver;NN_ENA=0 时,V5 会路由到 FileSaver。V2 在此示例中不再具有 none / FileSaver sink:所选 entry 会将 V2 路由到 UVC 或 RTSP。