- riir.md: split project file read/write into standalone oakstorage module (pluggable backend, DB-replaceable); add Mermaid data flow diagram of all modules; adjust batch table and milestones - riir/04-interfaces.md: new provides/consumes contract matrix for all modules - riir/M10-oakstorage.md: new manual with frozen C API (typed opaque handles, manual vtable for storage backends, URI addressing) - riir/01: codify pure-C OO interface rules (typed handles instead of void*, init/free pairs, manual vtables, no C++ objects or member calls across shared library boundaries); upper layers issue commands only, no module-to-module event subscriptions (async task callbacks excepted) - sync 00/02/03 and M2-M9 manuals: remove subscribe APIs, replace void* with typed handles, update tests accordingly
6.3 KiB
02 · 模块清单、依赖矩阵与拆分顺序
本文基于 2026-07-26 对 engine/ 全量 490 个源文件的 include 扫描 (方法:按 include 目标首段归类计数)。每个模块手册(M1-M9)里的 切割点清单都出自这张表。
1. 依赖矩阵(include 次数,空格=0)
| from\to | audio | codec | common | config | node | plugin | render | task | timeline | undo | core |
|---|---|---|---|---|---|---|---|---|---|---|---|
| audio | 1 | 5 | 2 | 2 | 5 | ||||||
| codec | 12 | 1 | 3 | 11 | 5 | 4 | |||||
| common | 1 | 1 | 3 | 1 | 7 | 1 | 2 | ||||
| config | 1 | 4 | 1 | 1 | |||||||
| node | 4 | 8 | 31 | 10 | 3 | 47 | 5 | 4 | 4 | ||
| pluginSupport | 6 | 6 | 6 | 2 | 2 | ||||||
| render | 3 | 9 | 24 | 6 | 38 | 5 | 2 | 1 | 8 | ||
| task | 4 | 4 | 2 | 38 | 4 | 1 | |||||
| timeline | 4 | 2 | 32 | 1 | 3 | ||||||
| undo | 2 | 1 | |||||||||
| src(capi) | 9 | 13 | 1 | 3 | 110 | 3 | 48 | 12 | 16 | 14 | 3 |
已知分层违规 1 处:render/ 引用了 src/capi/displayinternal.h
(R7-A 重做 display.h 时一并消除)。
2026-08 增补(oakstorage 拆出):矩阵扫描早于 oakstorage 单列。 其依赖关系为:oakstorage → node(serializer 落盘路径,含版本化 serializerXXXXXX 族)+ common;oaktask → oakstorage(load/save/otio 委托);facade → oakstorage。详细契约见 04 §2.10 与 M10。
2. 模块定义与拆分顺序
顺序原则:叶子先、根后;每步只引入"已拆模块的 C ABI",不引入 "未拆模块的 C++ 头"。
| 序 | 模块 | 内容(engine/ 下目录) | 主要切割点 |
|---|---|---|---|
| M0 | oakcore | core/(已完成,不动) |
— |
| M1 | oakcommon | common/(41 文件工具集)+ config/ |
common→render/node/undo/codec/plugin 的 12 次反向 include(清单见 M1 §3) |
| M2 | oakundo | undo/(undocommand/undostack) |
undo→node/project.h 1 处(M2 §3) |
| M3 | oaknode | node/(图、工厂、keyframe、nodeundo、traverser) |
node→render 47、node→codec 8、node→timeline 5、node→audio 4、node→undo 4(M3 §3,最大的活) |
| M3a | oakstorage | node/project/serializer 落盘路径 + task/project/{load,save,loadotio,saveotio} 文件 IO(工程持久化单列,后端可插拔:当前 XML 文件,未来数据库) |
storage→node(序列化建图取图,经 oaknode C ABI);手册 M10 |
| M4 | oaktimeline | timeline/(marker/workarea/timeline undo 命令族/timelinecommon) |
timeline→node 32(经 oaknode C ABI + 适配类) |
| M5 | oakcodec | codec/(decoder/encoder/frame/proxy/conform) |
codec→render 11(videoparams 等随 M3.5 下沉)、codec→task 5、codec→node 3 |
| M6 | oakaudio | audio/(AudioManager/AudioProcessor/输出) |
audio→render 2、audio→codec 1 |
| M7 | oakrender | render/(Renderer/PlaybackCache/ColorManager/帧缓存/job) |
render→node 38、render→codec 9、render→task 2、render→undo 1、render→src 1(违规) |
| M8 | oaktask | task/(Task/TaskManager/项目任务编排/cache 任务;工程文件 IO 已划给 oakstorage,M3a) |
task→node 38、task→codec 4、task→render 4、task→storage(load/save 委托) |
| M9 | oakplugin | pluginSupport/(OpenFX host) |
plugin→node 6、plugin→render 6、plugin→undo 2、plugin→coreengine 2 |
| — | liboakengine | src/capi + coreengine + tool/ + ui/ 残余 |
纯装配层:facade 内部调用改经各模块 C ABI(或保持现状直接链,见 M9 §4 裁决) |
M3.5(伴随 M3 的类型下沉):render/videoparams.h、
render/subtitleparams.h、render/colortransform.h 是纯数据类型,
codec/node 都重度引用——下沉到 oakcommon(或独立 oakmedia 目录,
执行时二选一,默认并 oakcommon),切断 codec→render 的大头。
3. 依赖环处理总表
| 环 | 数据 | 处理 |
|---|---|---|
| node ↔ render | 47/38 | M3 时 node 侧 47 次引用经 oakrender 尚未存在——因此 M3 拆分时 node→render 的引用先经"前向 C ABI"处理:把 node 用到的 render 类(ColorProcessor/RenderManager/footagejob/pluginjob/videoparams)的 C API 定义在 oaknode 手册里但由 M7 实现?否——正确顺序见 §4 说明 |
| node ↔ timeline | 5/32 | node→timeline 5 次(timelinecommon×2、marker/workarea/timelineundogeneral 各1):枚举/常量头下沉 oakcommon,其余经 M4 反向 C ABI |
| node ↔ codec | 8/3 | node→codec 8(decoder/frame/encoder/proxymanager):M5 反向 C ABI |
| node ↔ audio | 4/4 | M6 反向 C ABI |
| render ↔ codec | 9/11 | M3.5 类型下沉后剩 ~3(renderer.h/framemanager.h),M5 时处理 |
| codec ↔ task | 5/4 | codec→task 5(taskmanager/conform/proxy 的编排引用):重排归属(proxy/conform 的 task 依赖上移 oaktask),M5/M8 处理 |
| common ↔ 各 | 12 | M1 §3 逐条 |
4. 关键顺序裁决:node ↔ render 怎么破
node→render 的 47 次引用(ColorProcessor 8、videoparams 5、 footagejob 4、rendermanager 3、pluginjob 3 等)在 M3 时 oakrender 还不存在。两条路:
- A(选定):M3 阶段不追求 oaknode 立即独立链接,先把 oaknode 的公共 C ABI 头(node/project/viewer/track/block/footage 等 跨界类的 init/free/func)定义并实现出来;node→render 的引用在 M7(oakrender 拆分)时统一改成经 oakrender C ABI。 即:M3 只要求"oaknode 有自己的 include/ + C API + 测试",链接 验证推迟到 M7 闭环。
- B(否决):先把 render 里被 node 引用的类全搬到下层——伤筋动骨, 违反"只拆不写"。
M3 的完成判据因此放宽为:oaknode C API 实现 + 测试绿 + oaknode 内 不再新增对 render 的引用;链接级独立在 M7 复核。
5. 每模块通用落地步骤(M 手册都按此节奏)
- 建目录:
oak<mod>/include/oak<mod>/、oak<mod>/src/(先软链接/ 移动源文件,CMake 独立目标)。 - 按手册 C API 表写
include/oak<mod>/*.h+src/capi_*.cpp实现 (01 §1)。 - 消费侧逐个换:include 换适配头(01 §2),反向切割点逐条处理。
- 按 03 写测试(该模块每个 C API 至少 1 个 TEST)。
- 全量构建 + 全量 ctest + nm 审计(00 §判据 2)+ 提交。