菜单

STTFFmpeg使用手册

下载

STTFFmpeg.h 使用手册

STTFFmpeg 封装本地媒体、摄像头、HTTP/RTSP 流的播放。ARM 真机的视频路径通常走硬件播放器,音频及模拟器走 LVGL FFmpeg;STTFFmpegSoft 强制使用软件路径。两套后端行为并不完全一致。

1. 初始化和通道规划

cpp 复制代码
// 必须在创建第一个视频控件之前调用
STTFFmpeg::setVideoChannels(2);
STTFFmpeg::setLiveAlignInterval(60);
STTFFmpeg::rtsp_transport = "tcp";

STTFFmpeg* cam1 = new STTFFmpeg(getRuntime(), this, "cam1");
cam1->channel = 0;
STTFFmpeg* cam2 = new STTFFmpeg(getRuntime(), this, "cam2");
cam2->channel = 1;

构造函数会自动调用一次 init();也可由应用显式调用。IsInited 表示底层初始化是否成功。setVideoChannels(n) 只支持 1..4,并在 ARM 上按路数调整队列内存,必须在首次 init/构造之前调用才生效。

当前构造函数把每个实例的公开字段 channel 初始设为 0。多路播放时必须为实例分配唯一的 0..3 通道,否则它们会共享播放状态、列表和底层播放器,产生互相停止或覆盖。

setLiveAlignInterval(seconds) 设置 RTSP 定期清缓冲间隔;负数禁用。清缓冲可降低累计延迟,但可能短暂跳帧、爆音或等待下一个关键帧。

2. 最常用的创建方式

本地文件:

cpp 复制代码
video = new STTFFmpeg(getRuntime(), this, "video");
video->channel = 0;
video->setMainArg(20, 20, 440, 248, "/customer/usr/demo.mp4");
video->setVolume(60)->setAutoRestart(false)->play();

RTSP 页面无阻塞初始化:

cpp 复制代码
video->setMainArgAsync(20, 20, 440, 248,
                       "rtsp://user:pass@192.168.1.10/live", 300);

setMainArg(x,y,w,h,src) 自动识别源并设置播放列表。ARM 视频窗口的宽高会向下取 8 的倍数,例如 445 变为 440。setMainArg(src) 使用之前保存的位置和尺寸。

setMainArgAsync 先固定等待约 200 ms,再在完成回调中配置;delayms=0 立即播放,>0 再延时播放,<0 只配置不播放。对象被销毁后会通过内部映射跳过回调,但仍应在页面关闭前主动停止。

带分辨率、帧率和 const char* 的 setMainArg 以及 setVideoProp 是兼容旧代码/摄像头的接口,新文件播放优先使用 string 重载。

3. 播放控制

cpp 复制代码
video->play();
video->pause();
video->resume();
video->gotoSec(30);
video->stop(200); // 先暂停,200 ms 后停止

int command = video->getCmd();
double total = video->getDuration();
double current = video->getPlayedSecond();
int frames = video->getFrameNum();
  • setCmd(0/1/2/3):播放、停止、暂停、继续;继续后内部命令状态记为 0。
  • play(ms):ms<=0 直接播放,正数异步延时。
  • stop(ms):0 直接停止;正数先暂停,再异步停止。
  • gotoSec(sec):负数改为 0;直播流通常不支持任意 seek。
  • getCmd() 是最近命令,不等价于底层真实网络/解码状态。
  • getDuration() / getPlayedSecond() 失败返回 0,直播时 duration 可能未知。

静态帧信息:

cpp 复制代码
int w = 0, h = 0, fps = 0;
int count = STTFFmpeg::getFrameNum("/customer/usr/demo.mp4", w, h, fps);

解析文件可能耗时,RTSP 不应依赖完整帧数。返回 0 既可能表示失败,也可能表示未知,需结合源类型判断。

4. 位置、尺寸、缩放和旋转

cpp 复制代码
video->setPos(20, 20)
     ->setSize(440, 248)
     ->setImgSize(1280, 720)
     ->setImgZoom(1.0f);

video->stop();
video->setRotate(90);
video->setRotateContent(90);
video->play();
  • setPos/setSize 设置显示窗口并保存参数。
  • setImgSize 设置内部图像区域。
  • setImgZoom(z) 使用 z*256;z<=0 会退回 1 倍,当前实现没有限制超大值。
  • setRotate 用于跟随屏幕方向,接受 0..3 或 0/90/180/270;ARM 会交换 90/270 的内部方向。
  • setRotateContent 仅旋转内容,当前只在 ARM 生效。
  • setHidden(bool) 同时隐藏/显示内部 image 和容器,并在 ARM 调整 framebuffer 透明色。

旋转说明虽写“调用 play 生效”,当前 ARM 视频还会尝试立即更新窗口;为保持各平台一致,仍建议 stop、设置、play。

5. 音量与音频

cpp 复制代码
video->setVolume(70);
video->ignoreAudio(false);

STTFFmpeg::ignoreAudioHard(true, 0);
STTFFmpeg::intercutWav("/customer/usr/alarm.wav", 0);

setVolume(value) 设计范围为 0..100,但当前实现本身没有统一钳制;调用者必须限制范围。音量保存在全局值中,新播放会再次应用,因此多个实例可能互相影响。

ignoreAudio 是实例通道静音/停止送硬件;ignoreAudioHard 和 intercutWav 是指定通道的静态操作。模拟器行为不同:忽略音频通过清空回调实现,插播走 WavePlayer。

自定义音频设备回调:

cpp 复制代码
video->setAudioInitCb(myAudioInit)
     ->setAudioPlayCb(myAudioPlay)
     ->setAudioVolumeCb(myAudioVolume)
     ->setAudioDeInitCb(myAudioDeInit);

这些是全局底层回调,不是实例私有配置。函数和其依赖资源必须在整个播放期有效;多控件不要分别设置互相冲突的回调。

6. 播放列表

cpp 复制代码
vector<string> files = {
    "/customer/usr/a.mp4",
    "/customer/usr/b.mp4"
};
video->stop();
video->setPlayList(files, true)
     ->setAutoRestart(true)
     ->play();

video->addPlayList("/customer/usr/c.mp4", false);
video->playNext();
video->playPrev();
video->removePlayList("/customer/usr/b.mp4", true);
  • setPlayList(vector,resetSrc) 替换列表,非空时当前索引设为 0;resetSrc=true 同时设置第一项为当前源。
  • setPlayList(path) 建立单项列表。
  • addPlayList(...,allowSame) 默认去重。
  • removePlayList(path,once) 不删除正在播放项;空 path 表示清除非播放项或在停止时全清。
  • playNext/playPrev 循环到首尾。
  • setRandPlay/isRandPlay 控制随机下一项。
  • setAutoRestart 是业务推荐的自动续播开关;enLoop/isLoop 是底层循环标志。

getPlayList() 返回内部 vector 指针,不要 delete,也不要长期缓存。播放线程可能访问列表,修改列表前先 stop();头文件也明确要求替换列表时关闭视频。

只有一个条目时开启随机播放会进入“排除当前索引”的随机循环风险,不要对单项列表启用随机。

7. RTSP

cpp 复制代码
STTFFmpeg::rtsp_transport = "tcp"; // 也可 "udp"

bool online = STTFFmpeg::checkRtspSource(
    "rtsp://user:pass@192.168.1.10:554/live");
if (online) video->setMainArgAsync(20, 20, 440, 248, url, 0);

checkRtspSource 是同步探测。ARM 当前通过 TCP 连接并发送 DESCRIBE,连接和接收各约 1 秒超时,只把 RTSP 200 视为成功;认证支持取决于服务器响应。不要在 UI 高频定时器直接调用,应放到工作线程。

getRtspStatus() 返回位掩码,而不是单一枚举:

位 含义
0x0001/0x0002 音频/视频完成
0x0004 暂停
0x0008/0x0010 音频/视频解码错误
0x0020 不同步
0x0040/0x0080 读取超时/网络中断
0x0100 无效源
0x0200/0x0400 静音/音频暂停
0x0800/0x1000 循环/切换文件
0x2000/0x4000 加载中/源连接中断

返回 <0 表示播放器未打开,0 表示没有置位状态或正常播放。必须用按位与判断,例如 (status & 0x0040) != 0。

statusLabel 是 RTSP 状态标签,可改样式或隐藏,但由视频控件按需创建和管理,不要 delete。

flushBuffer() 在 ARM 清 packet、帧队列和解码器以降低直播延迟;会造成画面短暂中断,模拟器为空操作。

8. 截图和静态图

cpp 复制代码
bool saved = video->saveJpg("/customer/usr/capture.jpg");
video->setImage("/customer/usr/poster.png");
bool av = video->isAv();

saveJpg 只在已经打开且正在产生画面时可靠;路径后缀可用 PNG/JPG。ARM 调硬件播放器保存,模拟器走控件截图,结果和颜色通道可能有差异。不要在同一路视频上高频并发截图。

isAv() 根据文件/协议/摄像头路径重新判断并写入公开字段 isAV。setImage 直接给内部 LVGL image 设置源,路径资源必须有效。

9. 命令变量

cpp 复制代码
video->setVarOfCmd("Video.Command");
Ivariable commandVar = video->getVarOfCmd();

循环播放流程中,播放完成可把变量设为 1,下一项开始时设为 0。setVarOfCmd 未检查变量是否存在,使用前先通过变量管理器验证名称。

onDataChanged 在当前实现中为空;仅调用继承的 bindData 不会自动把变量值解释成播放命令,需使用命令变量/变量消息或业务回调。

10. 多路延时加载

cpp 复制代码
STTFFmpeg::delayLoadRtsp(
    {cam1, cam2},
    {0, 500},
    {url1, url2});

三个 vector 按最短长度配对,空指针及非法通道被跳过。内部先延时约 200 ms,再依次配置;ms=0 立即播放、正数延时、负数不播放。调用前先设置每个控件的位置、尺寸和唯一通道。

11. 页面关闭

cpp 复制代码
void Frm01::beforeClose() {
    video->stop();
    STTFFmpeg::prepareCloseAll(50);
    // 随后再销毁页面/视频对象
}

prepareCloseAll 用于避免多个 ARM 硬件通道在析构时逐个长时间等待。注意当前实现与头文件“异步预关闭”说明不一致:它先等待约 200 ms,然后并行启动 close,但会 join 等到所有 close 完成;参数 closeWaitMs 当前未使用。因此该调用本身仍可能阻塞,只是多路关闭并行化。模拟器为空操作。

析构时若已预关闭,会 detach 播放线程而不 join。页面切换前应确保业务不再访问对象,也不要立即复用仍在退出的外部资源。

12. STTFFmpegSoft

cpp 复制代码
STTFFmpegSoft* soft = new STTFFmpegSoft(getRuntime(), this, "soft");
soft->setMainArg(20, 20, 440, 248, "/customer/usr/demo.mp4");
soft->setVolume(60)->setAutoRestart(true)->play();

它重载 getFrameNum、setSrc、setCmd、play、stop、pause、resume、gotoSec、getDuration、getPlayedSecond、setAutoRestart、setVolume、setRotate 和两种 setMainArg。

实际差异:

  • 始终走 lv_ffmpeg_player_* 软件路径。
  • setVolume(value) 传给底层的是 value-60,与主类 ARM 语义不同。
  • setRotate 当前直接返回,不做任何旋转。
  • stop() 是无参数重载。
  • 旧式 setMainArg 同样把宽高向下取 8 的倍数。

软解码占用 CPU 和内存更高,适合硬解码不支持的格式或调试,不适合未经压测的多路高清播放。

13. 注意事项

  1. 最多规划 4 路,每个实例使用唯一 channel;所有通道索引必须在 0..3。
  2. filePath、iPlaying、resX/resY、isAV 等公开字段主要供框架使用,业务优先调用方法。
  3. enHardDecode 注释已说明过期;H.264/H.265 由底层自动决定。enFlipHor 需在停止后设置,再播放生效。
  4. RTSP 探测、源解析、关闭和截图都可能阻塞,不应放在短周期 UI 回调。
  5. 异步 play/stop/load 完成前不要复用或销毁其父页面;虽然实现会检查映射,外部回调和资源仍需自行管理。
  6. STT_USE_FFMPEG 在头文件定义为 0 是编译期标志,不代表构造一定成功;运行时还必须检查平台库、编解码器和 IsInited。
最近修改: 2026-10-21Powered by