感谢你们发布 FFMedia v2.6.2。我们查看了新版本的公开接口、文档和示例,新增的编码控制、SEI、ROI、分片输出和运行指标已经覆盖了我们之前提出的很多需求。
为了推进集成,我们整理了剩余需要补齐或确认的内容,重点是:
- 逐帧准确关联:将 SEI、ROI、IDR 请求与具体输入帧绑定,在排队、并行处理和丢帧情况下仍能正确对应。
- 真正的低延迟分片输出:分片就绪后立即交付,并提供帧标识、分片序号、结束标记和明确的 buffer 生命周期。
- 可靠的运行时控制:统一参数单位,明确修改是否成功,以及从哪一帧开始生效。
- 时间戳和分数帧率:保留输入时间信息,正确支持 59.94、29.97 等帧率,并验证长期音视频同步。
- 稳定性与正式交付:完善队列限制、慢消费者及录像故障处理,提供可复现的测试结果和正式 SDK 包。
下面的计划包含建议接口、实施步骤、兼容性要求和验收标准,可以直接交给开发工程师或 AI 编码助手参考。接口名称和实现方式可以根据你们现有架构调整;已经具备的能力,补充公开接口、文档和验证结果即可。
请先帮我们确认各项的当前支持情况、需要扩展的部分、硬件限制,以及预计实现时间。也欢迎提出更适合 FFMedia 架构的方案。
详细实施计划如下:
FFMedia v2.6.2 补全实施计划、接口建议及验收规范
用途:交给 Firefly 开发工程师或其 AI 编码助手(如 Codex)拆分任务、实现和验收。本文仅涉及 FFMedia 的媒体接口、编码能力、时间戳、缓冲管理、录像和 SDK 发布。
基线:2026-09-25 检查的 v2.6.2,发布仓库提交 84993c8e367da4f3ba3ec2ca53e5e559314de5ee。以下新增接口名称、文件名、测试数量和验收门槛均为实施建议,不是当前 SDK 已存在的能力或已测结果。若内部已有等价实现,应优先公开接口、补充契约和测试,不必重写。
核心目标:在保持可维护性和兼容性的前提下,实现逐帧确定的编码控制与元数据、可验证的早期分片输出,以及可重复的性能和稳定性验收。开始编码前请完成第 6 节的基线核对,再按第 7—16 节推进。
我们已检查 v2.6.2(发布仓库提交 84993c8e367da4f3ba3ec2ca53e5e559314de5ee)的公开头文件、文档和测试示例。新增的编码控制、SEI、ROI、split、录像及运行统计接口非常有帮助。为完成 RK3588 上的集成和验收,希望确认以下事项。
1. 逐帧 SEI 与 ROI 的准确绑定
当前 setSeiUserData() 的文档说明是替换“后续帧配置”。希望提供将 SEI、UUID、ROI 与特定输入帧绑定的不可变配置接口,并在输出返回同一 frame ID。请明确多帧排队、并行编码、丢帧和重启时的关联及生命周期规则;仅在提交输入前调用全局 setter 是否有明确保证?
建议增加自动测试:每帧使用不同 frame ID 和 SEI,交替修改 ROI;独立解析输出并检查所有帧的对应关系。参数设置成功与实际应用到某帧应能区分。
2. 分片完成即输出的契约
setSplit() 已公开。请提供 H.264/H.265 在 RK3588 上启用 lowdelay/segment 后的示例,明确每个回调包含完整帧还是单个分片,以及 frame ID、PTS/DTS、分片序号、最后分片标记、关键帧信息和 buffer 持有规则。
希望提供同一帧首片/末片回调的单调时钟日志,证明首片可以在整帧编码完成前交付。当前编码测试按输出 buffer 计数并与输入帧数比较;如果一帧对应多个输出 buffer,需要分别统计帧数和分片数。
3. 运行时控制、单位及时间戳
- 头文件允许运行时
changeEncodeParameter(),但 API 文档仍写停止后调用并重新初始化,请统一说明。
- 参数文档写
encode/bitrate 的 backend 会乘以 1024,而 schema 标为 bps,请统一单位或提供明确兼容接口。
- 文档写
duration-usec 默认 0,头文件仍写默认按 FPS 计算,请统一并添加输入 PTS 保留测试。
- 请说明 60000/1001、30000/1001 等分数帧率如何配置,是否同时正确设置码控、VUI 和输出时间戳;仅保留输入 PTS 与编码器采用分数帧率是不同问题。
- 如已支持,请公开全局 QP 上下限、码率上下限、VBV/CPB、无 B 帧/重排序设置及生效帧查询;如受芯片或模式限制,请返回明确的不支持错误。
- 帧内刷新 count 的单位在不同说明中不一致,请明确 H.264/H.265 各模式的单位和实际限制。
4. 正式包与验收环境
SDK_MANIFEST.txt 当前标注 dirty、development、Publishable final release: no。请提供干净源码构建的正式包、校验值、ABI 验证结果,以及验证使用的板卡、BSP/kernel、MPP、RGA 和 HDMI 驱动版本。
请补充 1080p60/59.94、4K 目标模式、编码动态调参、分片与 SEI/ROI 同时使用、音视频同步、输入断开重连及长时间运行的测试结果。
录像恢复接口是否仅恢复索引?请说明异常掉电时当前 MP4/MKV/TS 分片的可恢复范围。还希望验证录像磁盘变慢/写满时其他媒体分支的行为。
5. 源码及使用授权
目前发布仓库可见头文件、例程和预编译库,但未见核心编码模块实现。请确认是否可提供核心源码、定制扩展支持,以及商业设备中库和示例代码的使用、修改、再分发条款。
6. 工作拆分与执行顺序
公开头文件存在,不等于完整行为契约和硬件验收已经完成。请将每项需求标记为以下状态之一:已有并已验证、已有但需公开、需扩展、后端不支持。后端不支持时应提供能力查询和明确错误,不能以静默忽略或假成功代替。
| 编号 |
优先级 |
工作包 |
主要交付物 |
前置依赖 |
| T0 |
P0 |
固定环境、核对内部实现和 ABI |
能力矩阵、构建清单、契约草案 |
无 |
| T1 |
P0 |
输入帧身份及不可变元数据 |
随帧传播的元数据接口和所有权测试 |
T0 |
| T2 |
P0 |
逐帧 SEI、ROI、IDR 与结果关联 |
编码输入选项、输出关联、失败/丢帧结果 |
T1 |
| T3 |
P0 |
运行时参数事务及生效结果 |
正确单位、原子更新、应用状态 |
T0;精确帧关联依赖 T1 |
| T4 |
P0 |
早期分片输出和安全持有 |
独立 chunk 接口、完整帧兼容路径、时序证据 |
T1、T2 |
| T5 |
P0 |
时间戳保真及分数帧率 |
有理数帧率、时钟语义、长时间测试 |
T1、T3 |
| T6 |
P1 |
有界队列、分支隔离及指标 |
明确的溢出策略、队列年龄、故障测试 |
T1、T4 |
| T7 |
P1 |
录像及 A/V 稳定性 |
容器恢复说明、磁盘故障隔离、A/V 测试 |
T5、T6 |
| T8 |
P0 |
外部模块扩展和完整例程 |
仅使用安装 SDK 的可构建项目 |
T1—T5 |
| T9 |
发布门槛 |
自动测试、硬件报告和正式包 |
干净构建、校验、兼容性报告、授权说明 |
所有承诺支持的能力 |
建议按 T0 → T1 → T2/T3 → T4/T5 → T6/T7/T8 → T9 提交小范围变更,每次提交附对应测试。不要只修改发布仓库的头文件而没有匹配的库实现。
6.1 T0:先核对真实源码和硬件能力
- 定位内部编码、元数据、队列和输出发布实现。公开仓库中的例程构建工程不能替代核心源码;若编码助手只有发布仓库访问权限,先记录需要维护者在内部工程完成的任务。
- 固定板卡型号、SoC、BSP/kernel、HDMI/V4L2 驱动、MPP/RGA 版本、编译器和 FFMedia 源码提交。
- 查询当前 MPP 在每种 codec、分辨率、帧率、输入格式下实际支持的 SEI、ROI、分片、刷新和码控能力。不得猜测私有 MPP key、结构体或 flag。
- 逐项对齐头文件、参数 schema、文档、Python/CLI 和运行行为。保留冲突清单直到测试关闭。
- 为每项能力明确支持条件、限制和失败方式。能力查询至少区分“编译进 SDK”“当前设备支持”“当前配置支持”;可采用初始化后查询有效能力的方式。
6.2 ABI 约束
优先增加独立类型、非虚接口或扩展私有实现,避免改变已发布类的布局、虚函数表和旧结构体尺寸。新增元数据类型可采用 opaque/PImpl;跨版本快照采用明确的 size/version 协商,并验证旧调用者不会越界。
仅在新结构体首部增加 size/version 并不能自动解决 C++/STL ABI 问题,工具链和所有权约定仍需保持一致。如果无法兼容,必须按 ABI_POLICY.md 提升 Module ABI/SONAME 并给迁移说明,不得沿用旧 ABI 号掩盖布局变化。
6.3 修改位置与回归范围
下列头文件位置来自公开包;核心实现需在内部源码工程定位,不假设它们已在发布仓库开放。新文件/测试名称仅为建议。
| 工作包 |
公开接口/文档 |
需定位的内部实现 |
建议测试 |
| T1 |
base/media_buffer.hpp、module/module_app.hpp;可新增独立 metadata 头文件 |
buffer 发布/回收、队列项、AppSource、RGA 元数据传播 |
test_frame_metadata、test_metadata_lifetime |
| T2/T3 |
module/vp/module_mppenc.hpp、docs/ffmedia_parameters.md |
编码提交、MPP frame/task 映射、默认配置快照、参数应用 |
test_encoder_frame_options、test_encoder_update |
| T4 |
编码器输出扩展、通道描述、buffer 所有权文档 |
MPP packet 取出、分片发布、完整帧 assembler |
test_encoder_chunks、test_chunk_assembler |
| T5 |
时间信息/有理数速率接口、docs/ffmedia_api.md |
时间戳换算、MPP 帧率配置、VUI/封装参数 |
test_fractional_timing、硬件码流解析测试 |
| T6 |
base/media_metrics.hpp、module/module_media.hpp |
队列、池等待、分支发布、统计快照 |
test_queue_limits、test_slow_consumer |
| T7 |
module/vo/module_recorder.hpp、module/vo/module_ffmpegMux.hpp |
录像 worker、索引持久化、mux 和 A/V 处理 |
test_recorder_faults、test_av_timing |
| T8/T9 |
examples/、测试 CMake、安装导出、ABI 与 manifest |
语言绑定、打包和最终包检查 |
安装后外部工程、旧二进制兼容测试 |
按以下顺序提交,便于审查:先声明和失败语义及 CPU 测试,再接后端实现及硬件测试,最后同步例程和正式文档。新增声明与实现应作为同一可构建变更交付,不能发布仅有声明的中间包。
7. T1:输入帧身份与不可变元数据
7.1 建议的数据契约
下面是字段语义,不要求采用这些具体名称。
| 对象 |
建议字段 |
规则 |
FrameIdentity |
source/channel 标识、generation、64 位 frame_id |
frame_id 在同一代内唯一;输入源重新开始或不连续时更新 generation。不能用池索引、指针或 PTS 代替。 |
FrameTimingInfo |
原始 PTS/DTS、各自有效标志、time_base 分子/分母 |
PTS=0 或负数可以是合法值;无效值必须显式表示。 |
CaptureTimeInfo |
可选采集时间、单位、clock_domain、timestamp_semantic、有效性 |
时间戳的含义需区分驱动采集时刻、buffer 完成时刻、应用提交时刻;未知时明确标注。 |
FrameOptions |
可选逐帧 SEI 列表、完整 ROI 列表、force-IDR 请求 |
在提交成功时形成不可变快照,不能引用调用者之后可修改的内存。 |
FrameResult |
identity、完成/丢弃/取消/失败状态、原因、有效配置编号 |
每个已接受的编码输入恰有一个最终结果;分片回调与最终结果分开计数。 |
7.2 实施步骤
- 为应用输入增加带元数据的提交入口,或提供等价的正式扩展接口。原有提交接口继续可用,可由 SDK 为无显式 ID 的输入分配身份。
- 在内部队列中将 payload 的持有者、身份、时间信息和选项作为同一次提交的整体处理。图连接输入和应用主动提交必须走相同语义,避免某条路径丢失元数据。
- 原始图像经过一对一 RGA 处理时保留身份。ROI 坐标定义为编码器输入图像的可见像素坐标;若 ROI 在变换前产生,需显式变换或在 RGA 后赋值,不能悄悄沿用旧坐标。
- 对 drop、复制、替换和重采样等操作定义传播规则。多输入合成或改变帧数量时创建新的输出身份并说明来源,不能把其中一个输入身份误当作一对一映射。
- 实现 clone/copyMetadata、buffer 归还、stop、flush 和重启时的元数据清理。sidecar 必须跟随一次发布/持有生命周期,不可只用可复用裸指针做全局查表。
- 不占用应用既有
private_data,也不把每帧 SEI 塞入用于 codec extradata 的字段。
7.3 所有权及并发规则
- 元数据和选项在提交后不可变;深拷贝或转移所有权均可,但必须公开说明。
- payload 可继续使用 DMA-BUF/共享 buffer;“元数据不可变”不要求复制大幅原始图像。
- 提交失败时调用者仍拥有原资源,SDK 不产生一个虚假的已接受 ticket。
- 接受后再丢弃或取消,必须有可观测结果;重启不能把上一代结果挂到新帧上。
- 对队列内修改、重复 identity、超限 payload、失效 ROI、迟到控制返回可区分的错误。
- 完成事件可采用有界事件队列或回调,但不能静默遗失已接受输入的最终结果;停止时需有明确的结算/查询机制。
8. T2:精确逐帧 SEI、ROI 与 IDR
8.1 选项继承和替换
请使用三态而非含糊的空数组:未指定=继承本次提交时的默认值;指定空列表=该帧清除;指定非空列表=该帧替换。SEI、ROI、IDR 各自独立。输入被接受时固定有效选项,后续全局 setter 不得修改已经入队帧的逐帧快照。
兼容原有 setSeiUserData() 的默认配置用途;在文档中明确默认配置的快照边界。逐帧接口优先于默认配置,不允许出现两个线程争抢“下一帧”的隐式状态。
8.2 SEI 实现
- 在编码工作线程将该帧身份与所用 MPP frame/task 关联;使用已验证的后端逐帧元数据能力。
- 每条 SEI 接收 16 字节 UUID 和原始 payload,编码器负责 NAL/RBSP 封装与防竞争字节处理;公开最大条数和最大字节数。
- 定义 H.264/H.265 的插入位置及顺序。用于该图像的前置元数据应在该 access unit 首个 VCL 数据前可获得,且不应按 slice 重复插入,除非显式请求。
- 静态 SEI 与逐帧 SEI 使用同一校验/封装实现,避免行为分叉。
- 若后端无法可靠按帧关联,不允许用无确认的全局 setter 模拟。可提供“完整帧输出后插入”的明确替代模式,但不能把它宣称为编码期间的早期分片模式。
SEI payload 应作为应用自定义字节处理,FFMedia 不需要理解其中业务内容。测试只需使用公开测试 UUID、计数器和校验数据。
8.3 ROI 与 IDR 实现
每帧一次性提交完整 ROI 集合,避免循环修改全局 index 时只应用一部分区域。说明区域数、坐标对齐、越界、重叠优先级、绝对/相对 QP 范围及不同 codec 的限制。需要裁剪或对齐时返回实际应用结果,或明确拒绝,不可静默改变。
force-IDR 绑定具体输入身份;若输入在编码前被丢弃,报告未执行,不能无说明地把请求转移给下一帧。旧 setIdrFrame() 可继续表达“编码器下一次可接受的编码帧”,但要写清楚与精确逐帧接口的区别。
8.4 验收
使用至少 1,000 帧的合成视频,逐帧不同 SEI/ROI,穿插默认继承、清除、队列积压和输入丢弃。独立解析 SEI,对比输入 identity 和编码输出;检查序列、长度、UUID、包含 00 00 01 等字节的 payload,以及空/超限输入。
使用后端可用的 QP/区域证据或独立分析验证 ROI 生效,不能仅凭 setter 返回 0。验证目标帧为 IDR;若实际受硬件限制,应显示 unsupported 并从支持矩阵排除。
9. T3:运行时参数事务、单位和应用确认
9.1 建议新增或等价接口
queryEncoderCapabilities(current_input, codec) -> capabilities
requestEncoderUpdate(config_patch, apply_policy) -> request_id 或明确错误
queryEncoderUpdate(request_id) -> 状态、错误、实际配置、首个生效 FrameIdentity
上面是接口设计示意,不是当前 SDK 函数。apply_policy 至少支持“下一个尚未提交到硬件的帧”;若支持指定 FrameIdentity,需拒绝已经提交或已丢弃的目标。
9.2 实施步骤
- 区分请求编号和成功应用的配置编号。建议状态为 pending / applied / rejected / cancelled;仅“请求已保存”不能标为 applied。
- 对整组更新进行类型、范围、硬件能力和生命周期验证,再由工作线程在帧边界应用。
- 公开是否支持原子应用。若底层多步配置不能原子提交,应实现经过验证的回滚/重建,或拒绝原子请求;不能部分成功后仍报告整组成功。
- 实际开始使用新配置的输出带有效配置编号。被后续请求覆盖或 stop 取消的请求也要有最终状态。
- codec、分辨率等需要重建的变更明确返回状态限制,并要求受控停止/重新初始化。不要隐藏重启或继承旧 extradata。
- 控制线程不得持有可能等待输出、回调或消费者的长锁。回调内禁止的重入操作需显式拒绝;stop/drain 有超时和取消规则。
9.3 单位与完整控制面
新接口统一使用 bit/s。建议保留旧 encode/bitrate 的历史单位并清楚标为兼容接口,增加名称明确的新字段;不要原地改变单位导致旧应用相差 1,024 倍。新旧字段同时写入且互相矛盾时应拒绝。转换使用足够宽的整数并校验溢出,公开量化后的实际值。
按后端真实能力提供目标/最小/最大码率、QP 范围、GOP、RC mode、帧内刷新、B 帧/重排序及 VBV/CPB。每项标出单位、适用 codec、运行时可写性和限制;硬件不支持的项明确返回错误。不可把“码率上限配置”描述为所有时间窗口都绝不超限的硬保证。
9.4 验收
在相同视频输入下执行 12→6→3→8 Mbit/s 更新,包含合法/非法混合参数、并发请求、停止时取消和后端失败注入。核对返回状态、首个生效帧、实际输出码率和解码连续性。测量 100 ms/1 s 窗口峰值、收敛时间、P95/P99 编码时延,不以静态画面上的平均码率代替完整验证。
10. T4:早期分片输出
10.1 明确两种输出契约
默认保留完整 access unit 输出,保护已有消费者。新增显式的 chunk 模式,且消费者必须声明可处理 chunk。对只接受完整帧的组件,应拒绝不兼容连接或显式接入 assembler;不能把半帧当作完整 MediaBuffer 无提示送入现有模块。
| chunk 字段 |
要求 |
| identity |
与输入完全对应,包含 generation |
| PTS/DTS 及有效性 |
同一图像保持一致;未知 DTS 不伪造 |
| chunk_index |
从 0 递增;即使不同图像交错也可独立重组 |
| first/last 标记 |
正常完成仅一个 last;单 chunk 同时为 first 和 last |
| codec/config 编号 |
明确解码配置代次及实际编码配置 |
| 图像类型信息 |
可区分 IDR、其他随机访问图像、普通图像;未知时有有效标志 |
| 边界描述 |
明确完整 NAL、完整 slice 或任意字节片段;声明 Annex-B/长度前缀格式 |
| payload owner |
持有期内内容不可被回收覆盖;原始裸指针不能独立延长寿命 |
chunk 数量在编码早期通常未知,不应要求提前填最终总数。EOS 与 last-chunk 分开表示。已经输出一部分后发生故障时发出 frame-aborted 结果,不能将残缺图像标记为正常完成。
10.2 实施步骤
- 检查所固定 MPP 版本真实的 partition/segment 输出机制和完成标志,确认 RK3588 对两种 codec 的限制。
- 后端首段可读时立即发布;禁止先拼完整帧再拆分制造“早期回调”。同帧输出顺序明确,不得丢失 codec header 或前置 SEI。
- 为每段保留有效 owner;如果硬件复用同一 packet 存储且无法安全持有,可做有界段复制。不要为了宣传零拷贝牺牲数据有效性。
- 提供 assembler 作为完整帧兼容支路,限制每帧字节数、未完成帧数和等待时间;超限/缺段作为错误处理。
- 原始低延迟回调路径不得等待 assembler、录像或慢消费者。用第 12 节的预算和过载规则保持内存有界。
- 修正测试计数:input_frames、completed_frames、aborted_frames、output_chunks、output_bytes 独立统计。
10.3 时序证明
每帧记录:提交、后端接受、首段可用、首回调、末段可用、末回调、完成结果的单调时钟时间;后端无法提供的时间点标为 unavailable。
首回调早于末回调本身不足以证明硬件重叠,因为完整帧后拆分也会出现这种顺序。需要结合后端获取路径/事件证明首回调没有等待整帧完成,并核对代码没有完整帧缓存。若只能测到软件输出跨度,应据实标注,不能宣称已证明硬件逐片早出。
两种 codec 分别测试关闭分片、按字节、按 CTU、lowdelay、segment 及组合模式;同时加入 SEI/ROI/动态调参。检查重组码流可独立解码、标记完整且没有丢帧或重复结束事件。报告相对于完整帧模式的首输出收益、CPU/内存及相同画质/码率条件下的变化。
11. T5:时间戳与分数帧率
11.1 时间戳契约
默认保留输入 PTS;同步修正文档、头文件、schema 和构造函数行为。任何主动生成、变换、复制或丢弃时间戳的模式必须显式选择。
记录原始时钟域和时间戳语义,保留未舍入值(若输入提供);SDK 只使用微秒时需公开转换精度,不能虚构更高精度。不要按时间数值大小猜测 UTC/monotonic,也不要把用户态取到 buffer 的时间标为曝光开始时间。
保留原始捕获时间和媒体 PTS 的不同职责。A/V 时钟转换、设备丢失和时钟跳变必须可观测;没有可靠采集时钟的输入应报告未知。此项只要求 SDK 准确携带时间信息,不要求 SDK 解释自定义 SEI 内容。
11.2 有理数帧率
- 增加分子/分母接口,验证分母非零、范围和约分;保留整数接口兼容行为。
- 分清输入速率、编码速率、是否丢帧/重复帧以及码流时序;仅修改 RC fps 不应隐式改变实际输出帧数。
- 真实支持时将有理数速率正确传入后端,并检查 H.264/H.265 VUI 和容器时基。后端受限时公开有效值,不能默默把 59.94 当成 60。
- 需要生成 PTS 时采用整数余数累计或
floor(n × 1000000 × den / num) 的安全计算,避免反复加截断后的固定帧间隔。使用足够宽的中间类型并测试溢出。
11.3 验收
CPU 仿真至少 1,000,000 帧,包含 24000/1001、30000/1001、60000/1001;对于上述微秒生成策略,每个 PTS 与理想值的差小于 1 微秒且无累积漂移。该门槛只针对数值生成器,不代表实际采集或显示精度。
硬件测试包含有效零/负 PTS、重复 PTS、跳变、丢帧、stop/start 和格式变化。identity 在 PTS 重复时仍须正确。时钟不连续应有明确事件及代次策略。实测 59.94/60 的帧数、时长、码流声明及 A/V 偏差,区分输入抖动与 SDK 增加的误差。
12. T6:有界队列、分支隔离与观测
12.1 缓冲策略
各队列公开容量及适用单位,区分原始帧、编码帧、chunk、字节和时间。显式设置低延迟配置;不要把大容量默认为必须填满,也不要把池深度视为固定时延。
原始帧队列可支持拒绝最新、丢弃最旧或有超时阻塞;已接受后被丢弃必须给出身份及原因。编码输出不可任意丢弃某一段后仍声明图像完整;需要中止该帧/支路并报告不连续或恢复要求。
为慢消费者设置持有预算、队列年龄和可取消的停机路径。单纯缩小队列不能解决消费者长期持有共享 buffer:可用有界复制隔离非实时支路,或在超限时断开/报错。说明由谁持有最终引用及何时归还设备 buffer。
12.2 指标
在现有统计上补充或明确以下定义:已接受输入数、完整输出帧数、chunk 数、排队时间、最老队列项年龄、buffer 池等待、首输出/最终输出时间、各阶段丢弃/错误、待应用参数及生效帧。
不要把 chunk 计数写作 FPS。指标开关、reset、快照并发及直方图采样开销应有契约。默认统计存储有界,不保存无限增长的逐帧历史;详细追踪作为可选实验模式。
12.3 验收
注入慢回调、消费者持续持有 buffer、输入过载和停止中的消费者。要求在指定时间内返回或取消,内存不持续增长,输出身份不被复用覆盖,错误可观测。选取至少两种池深度和队列深度,证明参数改变有效,且默认演示不会掩盖阻塞。
13. T7:录像、封装和 A/V 行为
对 ModuleRecorder 分别说明索引恢复、已关闭分片恢复、当前未关闭分片可读性三件事;恢复索引不能等同于修复媒体数据。
实施建议:
- 为完整帧输入、codec extradata、关键帧分段和参数变更定义清楚的入口契约。若启用 chunk 输出,显式通过已验证的 assembler 进入只接受完整帧的录像组件。
- 分别验证普通 MP4、配置正确的 fragmented MP4、MKV、TS 实际支持情况;不承诺所有格式异常终止后行为相同。
- 异常终止后标注残缺分片,不得因文件存在就标为 complete;处理文件与索引持久化顺序、磁盘已满和写失败。
- 验证时间/大小分段可能等待关键帧的边界;大小阈值不是绝对磁盘占用上限,应说明头部及当前分片余量。
- 说明 mux
flush() 的交错队列和缓存语义、可调用状态及并发限制;不能因主动 flush 破坏 A/V DTS 顺序。
- 测试 HDMI/ALSA 和 USB 音频的时间基、初始偏差及长期漂移;音频设备拔插或格式变更要有明确恢复路径。
验收包括磁盘变慢、ENOSPC、只读目录、进程被终止和重启恢复。真实掉电测试仅在专用测试环境安排,并与进程终止测试分开报告。录像失败不得导致不相关实时媒体分支永久阻塞。
14. T8:外部模块、例程和语言绑定
至少交付以下独立、有限时长的可运行例程,文件名可调整:
| 建议例程 |
覆盖内容 |
encoder_frame_options |
应用输入 → 可选 RGA → 编码;每帧不同 SEI/ROI、IDR、身份验证 |
encoder_live_controls |
运行时参数请求、拒绝、取消及生效帧回读 |
encoder_chunk_output |
首段输出、持有/释放、frame-aborted、完整帧重组对照 |
encoder_fractional_timing |
分数帧率、输入 PTS 保留及码流时序核对 |
capture_preview_record |
实际采集、音频、预览、编码和独立录像分支 |
external_encoder_module |
外部派生模块使用公开 SDK 注入完整帧/chunk 和元数据 |
外部模块例程只包含安装公开头文件,链接导出的 CMake target,不依赖 FFMedia 私有 include 路径或碰巧导出的内部符号。用于证明用户可以替换编码模块,同时遵守通道、所有权和生命周期规则。
C++ 提供完整能力;CLI/Python 的支持范围明确列出。Python 回调必须说明 GIL 和对象所有权,不能因回调返回就释放仍被用户持有的输出。未实现的语言绑定明确标注,不做同名空实现。
例程提供构建命令、输入格式、参数单位、预期输出和资源需求;默认输出至用户指定目录,有限帧数运行,不自动删除用户已有录像。开启输出路径覆盖时应有明确选项。
15. 自动验收矩阵与提交证据
以下门槛为建议。性能目标若受平台限制,可协商调整,但功能正确性不得用平均性能代替。
| 测试组 |
方法 |
完成标准 |
| CPU/接口 |
单位转换、非法参数、事务、身份传播、合成后端 |
自动断言;覆盖错误/取消;不要求 MPP 设备 |
| 所有权 |
复用池、延迟释放、克隆、stop/flush;适用时使用 sanitizer |
无越界、悬空引用、数据被提前覆盖或无界增长 |
| 逐帧控制 |
独立 SEI 解析、ROI 证据、目标 IDR |
所有成功帧准确对应,其他输入均有失败/丢弃结果 |
| 分片 |
软件/后端时序、边界、重组及独立解码 |
能区分已证实早出、完整帧后拆分及不支持情况 |
| 码控 |
码率阶跃、场景切换、非法更新 |
可追踪实际应用帧,无静默局部成功 |
| 时基 |
长序列有理数仿真、硬件 PTS/VUI |
数值无累积漂移,实际时序和能力声明一致 |
| 真实输入 |
1080p60/59.94、4K 目标模式、格式切换和断开恢复 |
每种实际支持模式单独列结果;不把未测写作通过 |
| 稳定性 |
含音频/预览/录像的至少 8 小时专用测试 |
无死锁、持续资源泄漏或未解释的身份/时间戳错误 |
| 发布兼容 |
旧例程/外部派生类、安装 SDK 再构建 |
ABI 策略符合,文档与实物包一致 |
4K30/60、HDR、10-bit 等模式仅在硬件及当前实现支持时列为能力,不因 SoC 名称或“8K”产品标题推断。记录像素格式、色深、色域/范围、帧率和 codec;不在这次补全中暗示新增硬件采集能力。
每组提供命令、退出码、日志、输入模式、环境清单和机器可读结果。建议 CSV 至少包含 identity、有效 PTS/DTS、时间基、请求/有效配置编号、chunk 序号、阶段时间点、字节数及错误原因;不适用字段为空并标明原因。
无丢弃/失败场景要求已接受数与完整完成数一致;有丢弃/取消/中止场景要求每个已接受身份被恰好一个最终结果结算。报告中区分 PASS、FAIL、SKIP/UNSUPPORTED;无设备不能作为硬件测试通过。
统计必须注明接受点:AppSource 接受、编码器接受和最终输出是不同阶段,不能相加后与编码完成数比较。编码前丢弃、编码中中止和正常完成分开结算,并保留同一身份以便追踪。
16. T9:交付、发布与完成定义
每个工作包提交:实现变更、公共声明、对应测试、例程、限制说明和迁移说明。若需求已在内部实现,只需补公开面与证据,但仍需完成相同验收。
正式交付检查:
- 基线及支持矩阵齐全,具体 MPP/RGA/BSP 版本可复现。
- 逐帧选项、身份和元数据生命周期公开且验证。
- 早期输出支持情况有后端证据,chunk 和完整帧路径明确区分。
- 运行时控制的单位、事务结果和生效帧可查询。
- 时间戳保真和分数帧率在声明支持模式下通过测试。
- 队列、异步持有和分支故障均有资源上限和恢复规则。
- 录像恢复边界和语言绑定能力明确。
- 安装后可构建外部模块;不依赖私有实现符号。
- dirty/development 包替换为按正式流程生成的干净、已标记可发布包。
- 公共头文件、动态库、Python wheel、CLI、文档和版本/ABI 信息相互匹配。
- 提供实际发布文件的校验值、源码版本、测试报告及变更说明。
- 明确核心源码可用性、定制支持和商业设备的使用/修改/再分发条款。
不能完成的需求请返回:具体限制、影响的模式、当前替代方式、能力查询/错误码,以及是否计划后续支持。不要把未支持项目隐藏在“全部已完成”中。
17. 可直接交给编码助手的任务说明
请基于上述固定版本先核对真实核心源码和硬件后端。严格区分已有能力、缺失契约和新功能。按 T0—T9 逐项实现并提交证据,优先保证逐帧身份/不可变选项、运行时参数应用确认、早期分片输出和时间戳正确性。本文中的 API 名称是建议,可以用保持相同语义的设计替代。不要编造 MPP 接口;不要仅新增声明而没有实现;不要静默改变旧码率单位或破坏 ABI;没有 RK3588 环境时只报告已完成的 CPU/构建检查,列出待运行的硬件步骤。每次完成一个工作包,更新能力矩阵、例程、测试和剩余限制。
18. 审查依据
以下固定版本链接用于定位当前公开契约;上述设计和门槛是建议的新增工作,不是这些文件已经承诺的行为。