core: merge oak-common into oak-core
oak-common is gone; its modules (configstore, xmlutils, ocioutils,
oiioutils, colormath, colortransform, videoparams, ffmpegutils, ...)
now live in oak-core alongside the value types. The render value/GPU
types moved too: backend (wgpu context + DisplayRenderer), color
(ColorProcessor over ocio-rs), texture, frame, and the commonutil
config helpers.
Fix-ups to make the merged tree build and pass tests:
- oak-core Cargo.toml: wgpu back to 25 (the moved backend code is
written against that API generation); add the toml/quick-xml/image
deps oak-common carried.
- lib.rs: drop the duplicate 'pub mod error;'.
- error.rs: unified OAKCORE_* codes; restore Error::new() and
From<OcioError> from oak-common's error type.
- backend.rs/color.rs: oak_core::/oak_render:: self-references
rewritten to crate::; the shaderfx-dependent GPU effect test moved
to oak-render's shaderfx tests (shaderfx depends on oak-node and
cannot live in oak-core).
- oak-render's error module re-exports oak_core::error::{Error,
Result}; the OAKRENDER_* codes stay as the public-code contract.
- oak-node jobs.rs: ColorProcessor imported from oak_core::color.
- Integration tests repointed at oak_core::{texture, frame, backend,
color, colormath}.
- the display-ICC regression test treats an empty OAK_DISPLAY_ICC as
unset, matching displayicc::env_override_icc.
This commit is contained in:
@@ -18,7 +18,7 @@
|
||||
|
||||
```
|
||||
oakcore(已有,不动)
|
||||
oakcommon ─ oakundo ─ oaknode ─ oaktimeline ─ oakcodec ─ oakrender ─ oaktask ─ oakplugin
|
||||
oak_core ─ oakundo ─ oaknode ─ oaktimeline ─ oakcodec ─ oakrender ─ oaktask ─ oakplugin
|
||||
│ │
|
||||
└────────────── oakstorage(工程持久化, ┘
|
||||
后端可插拔:文件→数据库)
|
||||
|
||||
@@ -58,7 +58,7 @@ OAKMOD_API <ret> oakmod_clazz_<func>_s(/* 参数 */);
|
||||
3. 多个构造重载用后缀区分:`oakmod_clazz_init`(默认)、
|
||||
`oakmod_clazz_init_from_file`、`oakmod_clazz_init_copy` 等。
|
||||
4. 命名全小写,模块前缀 `oak<mod>_`(oakundo/oaknode/oaktimeline/
|
||||
oakcodec/oakrender/oaktask/oakaudio/oakplugin/oakcommon/oakstorage)。
|
||||
oakcodec/oakrender/oaktask/oakaudio/oakplugin/oak_core/oakstorage)。
|
||||
5. 导出宏 `OAKMOD_API` 照 `oakengine/export.h` 样式
|
||||
(`__attribute__((visibility("default")))`),模块编译加
|
||||
`-fvisibility=hidden`——每个模块**出生即 visibility 干净**,
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
| 序 | 模块 | 内容(engine/ 下目录) | 主要切割点 |
|
||||
|---|---|---|---|
|
||||
| M0 | oakcore | `core/`(已完成,不动) | — |
|
||||
| M1 | oakcommon | `common/`(41 文件工具集)+ `config/` | common→render/node/undo/codec/plugin 的 12 次反向 include(清单见 M1 §3) |
|
||||
| M1 | oak_core | `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 |
|
||||
@@ -52,15 +52,15 @@
|
||||
|
||||
**M3.5(伴随 M3 的类型下沉)**:`render/videoparams.h`、
|
||||
`render/subtitleparams.h`、`render/colortransform.h` 是纯数据类型,
|
||||
codec/node 都重度引用——下沉到 **oakcommon**(或独立 oakmedia 目录,
|
||||
执行时二选一,默认并 oakcommon),切断 codec→render 的大头。
|
||||
codec/node 都重度引用——下沉到 **oak_core**(或独立 oakmedia 目录,
|
||||
执行时二选一,默认并 oak_core),切断 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 ↔ timeline | 5/32 | node→timeline 5 次(timelinecommon×2、marker/workarea/timelineundogeneral 各1):枚举/常量头下沉 oak_core,其余经 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 时处理 |
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
行 = 消费方,列 = 提供方;单元格 = 消费的接口族(详见各提供方手册)。
|
||||
|
||||
| 消费 ↓ \ 提供 → | oakcommon | oakundo | oaknode | oaktimeline | oakcodec | oakaudio | oakrender | oakstorage | oaktask | oakplugin | oakcore |
|
||||
| 消费 ↓ \ 提供 → | oak_core | oakundo | oaknode | oaktimeline | oakcodec | oakaudio | oakrender | oakstorage | oaktask | oakplugin | oakcore |
|
||||
|---|---|---|---|---|---|---|---|---|---|---|---|
|
||||
| **facade**(src/capi) | 工具/类型 | undo 全族 | node/project/footage/serializer(clipboard) 族 | timeline 全族 | decoder/frame/proxy 族 | audio 全族 | renderer/playback/preview 族 | open/save/probe 族 | task/manager 全族 | plugin 全族 | rational/timecode |
|
||||
| **oaktask** | 工具 | command 句柄 | footage/project/sequence/folder 族 | — | conform/proxy 族 | — | 导出用 render 族 | **load/save/otio 委托** | — | — | — |
|
||||
@@ -26,16 +26,16 @@
|
||||
| **oaknode** | 枚举/常量/工具 | undocommand.h(4 处) | — | marker/workarea(2 处,M4 反向) | decoder/frame/proxy(8 处,M5 反向) | audio 参数(4 处,M6 反向) | colorprocessor/rendermanager/job(M7 反向,02 §4 裁决 A) | — | — | — | rational/bezier |
|
||||
| **oakundo** | 工具 | — | — | — | — | — | — | — | — | — | — |
|
||||
| **oakstorage** | 工具 | — | **project/root/序列化建图取图** | — | — | — | — | — | — | — | — |
|
||||
| **oakcommon** | — | — | — | — | — | — | — | — | — | — | — |
|
||||
| **oak_core** | — | — | — | — | — | — | — | — | — | — | — |
|
||||
|
||||
(空格 = 无依赖。"N 处"数据来自 02 的 include 扫描。oakcore 与
|
||||
ffmpeg_bridge 为现成独立库,不参与拆分顺序。)
|
||||
|
||||
## 2. 逐模块接口契约
|
||||
|
||||
### 2.1 oakcommon(M1)— 纯下沉,无业务对象
|
||||
### 2.1 oak_core(M1)— 纯下沉,无业务对象
|
||||
|
||||
- **提供**:`include/oakcommon/types.h` 的全模块共用 POD(时间戳/区间/
|
||||
- **提供**:`include/oak_core/types.h` 的全模块共用 POD(时间戳/区间/
|
||||
枚举常量,含 M3.5 下沉的 `OakVideoParams`/`OakSubtitleParams`/
|
||||
`OakColorTransform`);工具函数(全 `_s` 静态式,无句柄)。
|
||||
- **消费**:无(叶子)。
|
||||
@@ -47,7 +47,7 @@ ffmpeg_bridge 为现成独立库,不参与拆分顺序。)
|
||||
(redo/undo 行为)经 **回调函数指针** 实现
|
||||
(`oakundo_command_create(name, redo, undo, free_fn, userdata)`),
|
||||
即铁律 §0.4 的手工虚表;消费侧**不构造 C++ 子类**。
|
||||
- **消费**:oakcommon。
|
||||
- **消费**:oak_core。
|
||||
- **边界数据**:命令句柄(owned)。无事件——push/undo/redo 的调用方
|
||||
知道栈索引变化,通知由调用方(facade 适配层)发出(见 §3)。
|
||||
|
||||
@@ -57,7 +57,7 @@ ffmpeg_bridge 为现成独立库,不参与拆分顺序。)
|
||||
Project/Folder/Sequence/Track/TrackList/Block/Footage/ColorManager`
|
||||
句柄族。逐族清单见 M3 §2。无订阅接口——所有修改经命令函数完成,
|
||||
调用方知道影响(§3)。
|
||||
- **消费**:oakcommon、oakundo;对 render/codec/audio/timeline 的引用按
|
||||
- **消费**:oak_core、oakundo;对 render/codec/audio/timeline 的引用按
|
||||
02 §3/§4 的反向切割表在各模块就位后改经其 C ABI。
|
||||
- **边界数据**:节点句柄(borrowed 为主,工程拥有节点)、
|
||||
`oak_node_value` POD、id 字符串(buf/size)。
|
||||
@@ -67,7 +67,7 @@ ffmpeg_bridge 为现成独立库,不参与拆分顺序。)
|
||||
- **提供**:marker/workarea/timeline 编辑原语句柄族(`OakTimelineMarker`
|
||||
等),timeline 专用 undo 命令**经 oakundo 的回调式命令**注册,不自带
|
||||
命令子类。
|
||||
- **消费**:oaknode(32 处,全部经句柄族)、oakundo、oakcommon。
|
||||
- **消费**:oaknode(32 处,全部经句柄族)、oakundo、oak_core。
|
||||
|
||||
### 2.5 oakcodec(M5)
|
||||
|
||||
@@ -75,7 +75,7 @@ ffmpeg_bridge 为现成独立库,不参与拆分顺序。)
|
||||
帧以 `OakCodecFrame *` 不透明句柄跨边界(owned,配对 free),
|
||||
像素数据经 `oakcodec_frame_data(frame, plane, &linesize)` 取出指针
|
||||
(borrowed,生命周期随 frame)。
|
||||
- **消费**:oakcommon、oaknode(footage 流信息)、oakcore、ffmpeg_bridge。
|
||||
- **消费**:oak_core、oaknode(footage 流信息)、oakcore、ffmpeg_bridge。
|
||||
|
||||
### 2.6 oakaudio(M6)
|
||||
|
||||
@@ -89,7 +89,7 @@ ffmpeg_bridge 为现成独立库,不参与拆分顺序。)
|
||||
渲染结果帧为 owned 句柄;渲染 ticket 是**异步命令**(后台线程),
|
||||
进度/完成回调是它的返回通道——这是 §3 允许回调的唯一情形
|
||||
(线程语义按 riir.md §6.2 钉死)。
|
||||
- **消费**:oaknode、oakcodec、oakcommon、oakundo(1 处)、oakbackend
|
||||
- **消费**:oaknode、oakcodec、oak_core、oakundo(1 处)、oakbackend
|
||||
(GPU 插件,经 `renderbackend_c.h` 手工虚表——现有先例)。
|
||||
|
||||
### 2.8 oaktask(M8)— 编排者
|
||||
@@ -114,7 +114,7 @@ ffmpeg_bridge 为现成独立库,不参与拆分顺序。)
|
||||
静态函数。**URI 寻址**:`file://…/*.ove` 走内建 ove-xml 后端;未来
|
||||
`oakdb://` 走数据库后端——替换数据库 = 新增一个后端实现并注册,
|
||||
消费侧零改动。
|
||||
- **消费**:oaknode(反序列化建图 / 序列化取图)、oakcommon。
|
||||
- **消费**:oaknode(反序列化建图 / 序列化取图)、oak_core。
|
||||
- **边界数据**:工程句柄(owned)、XML 字节流(buf/size)、后端表。
|
||||
无事件——open/save 是同步命令,成败与结果全在返回值里,调用方
|
||||
(oaktask/facade)知道影响,由它发通知(§3)。
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# M1 · oakcommon 拆分手册
|
||||
# M1 · oak_core 拆分手册
|
||||
|
||||
> 内容:`engine/common/`(41 文件通用工具集)+ `engine/config/`。
|
||||
> 依赖:oakcore(2)。被依赖:几乎全员(node 31、render 24、
|
||||
@@ -8,99 +8,99 @@
|
||||
## 1. 目标形态
|
||||
|
||||
```
|
||||
oakcommon/
|
||||
include/oakcommon/ # 公共头(C ABI + 允许直引的纯头工具)
|
||||
oak_core/
|
||||
include/oak_core/ # 公共头(C ABI + 允许直引的纯头工具)
|
||||
src/ # 现有 .cpp 原样迁入
|
||||
tests/ # oakcommon_gtest
|
||||
tests/ # oak_core_gtest
|
||||
```
|
||||
|
||||
- **纯头工具**(lerp.h、define.h、decibel.h、tohex.h、digit.h、
|
||||
memorypool.h、threadsafemap.h、range.h 等无 .cpp 的):作为
|
||||
oakcommon 公共头直接提供给其他模块 include——拆分阶段允许
|
||||
oak_core 公共头直接提供给其他模块 include——拆分阶段允许
|
||||
(不产生链接依赖)。RIIR 阶段这些会改写成各语言自有实现。
|
||||
- **config/config.h**:单头配置存取,被全模块引用(10+)。
|
||||
它是 Qt 依赖(QSettings 包装),按 §2 冻结 C ABI。
|
||||
|
||||
## 2. 冻结 C API(有 .cpp 实现的函数族)
|
||||
|
||||
命名前缀 `oakcommon_`。以下按头分组(签名机械规则见 01 §3,
|
||||
命名前缀 `oak_core_`。以下按头分组(签名机械规则见 01 §3,
|
||||
此处冻结函数清单与特殊约定):
|
||||
|
||||
### 2.1 `oakcommon/config.h`(对应 config/config.h)
|
||||
### 2.1 `oak_core/config.h`(对应 config/config.h)
|
||||
|
||||
```c
|
||||
void oakcommon_config_set(const char *group, const char *key,
|
||||
void oak_core_config_set(const char *group, const char *key,
|
||||
const char *value_utf8);
|
||||
int oakcommon_config_get(const char *group, const char *key,
|
||||
int oak_core_config_get(const char *group, const char *key,
|
||||
char *buf, int buf_size); /* 两段式 */
|
||||
int oakcommon_config_get_int(const char *group, const char *key,
|
||||
int oak_core_config_get_int(const char *group, const char *key,
|
||||
int fallback);
|
||||
double oakcommon_config_get_double(const char *group, const char *key,
|
||||
double oak_core_config_get_double(const char *group, const char *key,
|
||||
double fallback);
|
||||
void oakcommon_config_set_int(const char *group, const char *key, int v);
|
||||
void oak_core_config_set_int(const char *group, const char *key, int v);
|
||||
```
|
||||
|
||||
### 2.2 `oakcommon/xml.h`(对应 common/xmlutils.h,8 次被引)
|
||||
### 2.2 `oak_core/xml.h`(对应 common/xmlutils.h,8 次被引)
|
||||
|
||||
```c
|
||||
/* XMLAttributeLoop/xml_read_next_start_element 的 C 化:
|
||||
* 以迭代器句柄包装 QXmlStreamReader */
|
||||
typedef struct OakCommonXmlReader OakCommonXmlReader;
|
||||
OakCommonXmlReader *oakcommon_xml_reader_init(const char *utf8, int len);
|
||||
void oakcommon_xml_reader_free(OakCommonXmlReader *r);
|
||||
int oakcommon_xml_read_next_start_element(OakCommonXmlReader *r);
|
||||
int oakcommon_xml_reader_name(OakCommonXmlReader *r, char *buf, int n);
|
||||
int oakcommon_xml_reader_attr(OakCommonXmlReader *r, const char *attr,
|
||||
typedef struct oak_coreXmlReader oak_coreXmlReader;
|
||||
oak_coreXmlReader *oak_core_xml_reader_init(const char *utf8, int len);
|
||||
void oak_core_xml_reader_free(oak_coreXmlReader *r);
|
||||
int oak_core_xml_read_next_start_element(oak_coreXmlReader *r);
|
||||
int oak_core_xml_reader_name(oak_coreXmlReader *r, char *buf, int n);
|
||||
int oak_core_xml_reader_attr(oak_coreXmlReader *r, const char *attr,
|
||||
char *buf, int n);
|
||||
int oakcommon_xml_reader_read_element_text(OakCommonXmlReader *r,
|
||||
int oak_core_xml_reader_read_element_text(oak_coreXmlReader *r,
|
||||
char *buf, int n);
|
||||
void oakcommon_xml_reader_skip_current(OakCommonXmlReader *r);
|
||||
void oak_core_xml_reader_skip_current(oak_coreXmlReader *r);
|
||||
```
|
||||
|
||||
写出侧 `oakcommon_xml_writer_*`(init_to_string/write_attribute/
|
||||
写出侧 `oak_core_xml_writer_*`(init_to_string/write_attribute/
|
||||
write_text_element/free 得字符串,两段式)。
|
||||
|
||||
### 2.3 `oakcommon/files.h`(common/filefunctions.h,render 7 次)
|
||||
### 2.3 `oak_core/files.h`(common/filefunctions.h,render 7 次)
|
||||
|
||||
```c
|
||||
int oakcommon_file_exists(const char *path); /* 1/0 */
|
||||
int oakcommon_file_size(const char *path); /* -1 失败 */
|
||||
int oakcommon_file_read_all(const char *path, char *buf, int n); /* 两段式 */
|
||||
int oakcommon_file_write_all(const char *path, const char *data, int n);
|
||||
int oakcommon_dir_mkpath(const char *path);
|
||||
int oakcommon_get_config_path(char *buf, int n);
|
||||
int oakcommon_get_temp_path(char *buf, int n);
|
||||
int oak_core_file_exists(const char *path); /* 1/0 */
|
||||
int oak_core_file_size(const char *path); /* -1 失败 */
|
||||
int oak_core_file_read_all(const char *path, char *buf, int n); /* 两段式 */
|
||||
int oak_core_file_write_all(const char *path, const char *data, int n);
|
||||
int oak_core_dir_mkpath(const char *path);
|
||||
int oak_core_get_config_path(char *buf, int n);
|
||||
int oak_core_get_temp_path(char *buf, int n);
|
||||
```
|
||||
|
||||
### 2.4 `oakcommon/ocio.h`、`oakcommon/oii.h`、`oakcommon/ffmpeg.h`
|
||||
### 2.4 `oak_core/ocio.h`、`oak_core/oii.h`、`oak_core/ffmpeg.h`
|
||||
|
||||
(ocioutils/oiioutils/ffmpegutils,按 01 §3 机械 POD 化;
|
||||
OAK/OIIO/FFmpeg 类型全部句柄化或拍平字段。)
|
||||
|
||||
### 2.5 `oakcommon/misc.h`
|
||||
### 2.5 `oak_core/misc.h`
|
||||
|
||||
`jobtime`(`double oakcommon_jobtime_now(void)`)、`current`
|
||||
(`oakcommon_current_get/set` 线程局部当前对象句柄)。
|
||||
`jobtime`(`double oak_core_jobtime_now(void)`)、`current`
|
||||
(`oak_core_current_get/set` 线程局部当前对象句柄)。
|
||||
|
||||
## 3. 切割点(common 的 12 次反向 include,逐条)
|
||||
|
||||
| 现状 | 处理 |
|
||||
|---|---|
|
||||
| common → render/ 7 次(播放钟/自动滚动等引 render 类型) | 涉及文件(playbackaudioclock/autoscroll 等)**上移出 oakcommon**:它们不是底层工具,归 oakrender(M7) |
|
||||
| common → render/ 7 次(播放钟/自动滚动等引 render 类型) | 涉及文件(playbackaudioclock/autoscroll 等)**上移出 oak_core**:它们不是底层工具,归 oakrender(M7) |
|
||||
| common → node/ 3 次 | 同上,归 oaknode(M3) |
|
||||
| common → undo/ 1 次 | 同上,归 oakundo(M2) |
|
||||
| common → codec/ 1 次 | 同上,归 oakcodec(M5) |
|
||||
| common → pluginSupport/ 1 次 | 同上,归 oakplugin(M9) |
|
||||
|
||||
判据:切完后 `grep -rn '#include "' oakcommon/src | grep -vE
|
||||
'"(oakcommon|olive/core)'` 为空(只剩 oakcore 与 Qt/系统头)。
|
||||
判据:切完后 `grep -rn '#include "' oak_core/src | grep -vE
|
||||
'"(oak_core|olive/core)'` 为空(只剩 oakcore 与 Qt/系统头)。
|
||||
|
||||
## 4. 测试(映射 03 §2)
|
||||
|
||||
- config:set/get 往返、int/double fallback、两段式 buf。
|
||||
- xml:reader 解析样例串、attr/text 读取、skip、writer 产出解析回读。
|
||||
- files:临时目录建/写/读/尺寸/删除。
|
||||
- 每函数 1 正常 + 1 错误路径;`oakcommon_debug_alive_count()` 泄漏断言。
|
||||
- 每函数 1 正常 + 1 错误路径;`oak_core_debug_alive_count()` 泄漏断言。
|
||||
|
||||
## 实施现状(2026-08-05)
|
||||
|
||||
@@ -110,10 +110,10 @@ M1 已落地并可独立构建、测试全绿(127 个用例:126 通过,1
|
||||
### 最终目录结构
|
||||
|
||||
- `src/common/src/` — 去 Qt 化 C++ 实现(`olive::` 命名空间),target
|
||||
`oakcommon`(SHARED)。
|
||||
`oak_core`(SHARED)。
|
||||
- `src/common/c_api/` — 纯 C ABI 包装,通过 `target_sources` 合并进
|
||||
`oakcommon`,不单独成库。
|
||||
- `src/common/tests/` — gtest,target `oakcommon-gtest`,
|
||||
`oak_core`,不单独成库。
|
||||
- `src/common/tests/` — gtest,target `oak_core-gtest`,
|
||||
`gtest_discover_tests`。
|
||||
- `include/common/`(仓库根)— 公共 C 头:`commandlineparser.h`、
|
||||
`current.h`、`debug.h`、`dropworkflowbehavior.h`、`error.h`、
|
||||
@@ -124,18 +124,18 @@ M1 已落地并可独立构建、测试全绿(127 个用例:126 通过,1
|
||||
### 独立构建与测试
|
||||
|
||||
```sh
|
||||
cmake -S src/common/standalone -B build-oakcommon
|
||||
cmake --build build-oakcommon -j
|
||||
ctest --test-dir build-oakcommon --output-on-failure
|
||||
cmake -S src/common/standalone -B build-oak_core
|
||||
cmake --build build-oak_core -j
|
||||
ctest --test-dir build-oak_core --output-on-failure
|
||||
```
|
||||
|
||||
driver 通过 `find_package(... CONFIG)` 使用 Homebrew 的 OCIO/OIIO/GTest
|
||||
(顶层 `cmake/FindOpenColorIO.cmake`/`FindOpenImageIO.cmake` 面向
|
||||
`.so`,macOS 下不适用),并把 config target 映射到 oakcommon
|
||||
`.so`,macOS 下不适用),并把 config target 映射到 oak_core
|
||||
CMakeLists 消费的 `${OCIO_LIBRARIES}` 等变量。driver 中额外处理了两点:
|
||||
给 `olivecore` 补 `third_party/openfx/include` 头路径(顶层靠全局
|
||||
include);禁用 OpenTimelineIO(`/opt/otio` 的 dylib 用 `@loader_path`
|
||||
安装名,构建树内无法加载,且 oakcommon 不需要 OTIO)。
|
||||
安装名,构建树内无法加载,且 oak_core 不需要 OTIO)。
|
||||
|
||||
### 实际依赖
|
||||
|
||||
@@ -150,16 +150,16 @@ include);禁用 OpenTimelineIO(`/opt/otio` 的 dylib 用 `@loader_path`
|
||||
`fb_find_best_pix_fmt_of_list`(ffmpeg_bridge 导出符号)。
|
||||
- `pixelformat.h`/`sampleformat.h` 本身是 header-only,只需头路径
|
||||
(`core/include`、`ffmpeg_bridge/include`,因这两个 target 的
|
||||
include 目录是 PRIVATE,在 oakcommon 里显式补为 PUBLIC)。
|
||||
include 目录是 PRIVATE,在 oak_core 里显式补为 PUBLIC)。
|
||||
- 未按计划只链 oakcore 头;OLIVECORE_BUILD_TESTS 在独立构建中关闭。
|
||||
|
||||
### 与计划的主要差异
|
||||
|
||||
- 接口未按 §2 冻结清单逐条实现,而是按实际使用面包装:C ABI 头放在
|
||||
仓库根 `include/common/`,命名 `oakcommon_<模块>_<动词>`,两段式
|
||||
仓库根 `include/common/`,命名 `oak_core_<模块>_<动词>`,两段式
|
||||
buffer(先查询尺寸再拷入)约定统一。
|
||||
- `xmlutils` 用 expat 实现(事件预先解析成队列);C API 的
|
||||
`oakcommon_xml_reader_read_element_text` 因底层是消费型读取,在
|
||||
`oak_core_xml_reader_read_element_text` 因底层是消费型读取,在
|
||||
handle 内缓存最近一次文本以兼容两段式调用。
|
||||
- 被移除/上移的类(播放钟、autoscroll 等反向 include 涉及项)见
|
||||
`notes.md`。
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
> 与 `engine/task/project/{load,save,loadotio,saveotio}` 的**文件 IO 部分**。
|
||||
> **不含**剪贴板序列化(copy/paste 的节点图 XML 留在 oaknode 的
|
||||
> serializer 族,见 M3)。
|
||||
> 依赖:oaknode(project/root/序列化建图取图)、oakcommon。
|
||||
> 依赖:oaknode(project/root/序列化建图取图)、oak_core。
|
||||
> 被依赖:oaktask(load/save 任务委托)、facade。
|
||||
> 拆分顺序:M3a(oaknode 之后、oakserialize 同批)。
|
||||
>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
## 0. 形态决策(2026-08,已定)
|
||||
|
||||
- **A 方案(用户拍板)**:app / oak-cli / oak-worker 只依赖
|
||||
oakcommon / oakundo / oaknode / oaktimeline / oakcodec / oakaudio /
|
||||
oak_core / oakundo / oaknode / oaktimeline / oakcodec / oakaudio /
|
||||
oakrender / oaktask / oakplugin / oakstorage 的 rlib;不链接
|
||||
liboakengine(连 rlib 形态都不用)。
|
||||
- **oakengine 保留为纯 cdylib**:只给 OFX 插件和未来的外部消费者
|
||||
|
||||
@@ -132,21 +132,21 @@ ctest --test-dir build-oakundo --output-on-failure
|
||||
|
||||
### 实际依赖
|
||||
|
||||
- Oak 内部:仅 oakcommon 的头文件宏(`define.h` 的
|
||||
- Oak 内部:仅 oak_core 的头文件宏(`define.h` 的
|
||||
`DISABLE_COPY_MOVE`),纯头文件,按 include 路径引用
|
||||
(`${OAK_REPO_ROOT}/src/common/src`),**不链接** oakcommon;
|
||||
(`${OAK_REPO_ROOT}/src/common/src`),**不链接** oak_core;
|
||||
不依赖 olivecore/ffmpeg_bridge。
|
||||
- 第三方:GTest(仅测试)。无 Qt。
|
||||
|
||||
### 与计划的主要差异
|
||||
|
||||
- 接口未按 §2 冻结清单逐条实现,而是对齐 oakcommon 的既有契约:
|
||||
- 接口未按 §2 冻结清单逐条实现,而是对齐 oak_core 的既有契约:
|
||||
C ABI 头放在仓库根 `include/undo/`,命名 `oakundo_<族>_<动词>`;
|
||||
查询类函数返回 int 错误码 + out 参数(计划中的
|
||||
`int64_t oakundo_undostack_count(...)` 直接返回值形式改为
|
||||
`int ...(OakUndoStack *, int64_t *out)`);字符串两段式 buffer 约定。
|
||||
- 句柄族名:`OakUndoCommand`/`OakUndoStack`;init/free 语义与
|
||||
oakcommon 一致(init 失败返回 NULL 且内部 try/catch 兜底,
|
||||
oak_core 一致(init 失败返回 NULL 且内部 try/catch 兜底,
|
||||
free(NULL) 为 no-op)。
|
||||
- §2.2 的 `OakUndoObjectParent`(QObject 挂载点)、
|
||||
`oakundo_undostack_update_actions`、`oakundo_undostack_undo_action/
|
||||
|
||||
@@ -61,9 +61,9 @@ project.h、timeline.h 的对应函数就是模板,参数命名前缀换
|
||||
|
||||
| 现状(次数) | 处理 |
|
||||
|---|---|
|
||||
| node → render/ 47(colorprocessor 8、videoparams 5、footagejob 4、rendermanager 3、pluginjob 3 等) | videoparams/colortransform 随 M3.5 下沉 oakcommon;其余 **M7 时**改经 oakrender C ABI(02 §4 裁决 A:M3 暂不断链,禁止新增) |
|
||||
| node → render/ 47(colorprocessor 8、videoparams 5、footagejob 4、rendermanager 3、pluginjob 3 等) | videoparams/colortransform 随 M3.5 下沉 oak_core;其余 **M7 时**改经 oakrender C ABI(02 §4 裁决 A:M3 暂不断链,禁止新增) |
|
||||
| node → codec/ 8(decoder 4、frame 2、encoder 1、proxymanager 1) | M5 时改经 oakcodec C ABI(M5 手册已含 frame/decoder 家族) |
|
||||
| node → timeline/ 5(timelinecommon 2、marker 1、workarea 1、timelineundogeneral 1) | timelinecommon 的枚举/常量下沉 oakcommon/types.h;marker/workarea 引用(均在 node/project/ 序列化路径)M4 时改经 oaktimeline C ABI |
|
||||
| node → timeline/ 5(timelinecommon 2、marker 1、workarea 1、timelineundogeneral 1) | timelinecommon 的枚举/常量下沉 oak_core/types.h;marker/workarea 引用(均在 node/project/ 序列化路径)M4 时改经 oaktimeline C ABI |
|
||||
| node → audio/ 4 | M6 时改经 oakaudio C ABI |
|
||||
| node → undo/ 4(undocommand.h) | M2 后改 include oakundo 公共头 + 适配类 |
|
||||
|
||||
@@ -117,15 +117,15 @@ driver 照 src/common/standalone 模式:EXPAT/OpenColorIO/OpenImageIO
|
||||
用 Homebrew 的 config 包(`find_package(... CONFIG)`)并映射到
|
||||
`${OCIO_LIBRARIES}` 等变量;`add_subdirectory` 引入真实 in-repo
|
||||
target(core→olivecore、ffmpeg_bridge、src/undo→oakundo、
|
||||
src/common→oakcommon,各自 BUILD_TESTS 关闭),不再链接预构建
|
||||
src/common→oak_core,各自 BUILD_TESTS 关闭),不再链接预构建
|
||||
dylib;禁用 OpenTimelineIO(`/opt/otio` 的 `@loader_path` 问题,
|
||||
oaknode 不需要)。
|
||||
|
||||
### 实际依赖
|
||||
|
||||
- Oak 内部:oakcommon(XML/Current/工具)、oakundo(UndoCommand/
|
||||
- Oak 内部:oak_core(XML/Current/工具)、oakundo(UndoCommand/
|
||||
UndoStack)、olivecore(`olive::core::Rational/Color/Bezier` 等
|
||||
C ABI 包装,真实符号)、ffmpeg_bridge(经 oakcommon 间接)。
|
||||
C ABI 包装,真实符号)、ffmpeg_bridge(经 oak_core 间接)。
|
||||
- 第三方:EXPAT、OpenColorIO、OpenImageIO、Imath(头)、FFmpeg
|
||||
(经 ffmpeg_bridge 间接)、GTest(仅测试)。
|
||||
- **transition stub 机制**(裁决 A):对尚未拆分的
|
||||
@@ -133,7 +133,7 @@ oaknode 不需要)。
|
||||
头文件由 `src/node/transition/` 的过渡 stub/转发头提供(engine 头
|
||||
仍是 Qt 版),符号经 `-undefined dynamic_lookup`(macOS)留到
|
||||
运行时解析。测试进程启动时必须能解析这些符号:oaknode-gtest
|
||||
链接真实 target(olivecore/oakcommon/oakundo + OCIO/OIIO/Imath
|
||||
链接真实 target(olivecore/oak_core/oakundo + OCIO/OIIO/Imath
|
||||
dylib)并 `-Wl,-force_load` 预构建的
|
||||
`build/third_party/openfx/HostSupport/libOfxHost.a`(OFX 符号与
|
||||
typeinfo,否则二进制启动即崩,PRE_TEST 发现模式也会挂;路径用
|
||||
@@ -145,7 +145,7 @@ oaknode 不需要)。
|
||||
|
||||
### 与冻结 C API 的主要差异
|
||||
|
||||
- 函数族命名与约定照 oakcommon/oakundo 既有契约:`oaknode_<族>_<动词>`,
|
||||
- 函数族命名与约定照 oak_core/oakundo 既有契约:`oaknode_<族>_<动词>`,
|
||||
int 错误码 + out 参数,字符串两段式 buffer;undoable 变体成对
|
||||
(`_undoable` 后缀,部分经 `OakUndoCommand *` 尾参)。
|
||||
- §2 冻结表中**跳过/未实现**的函数族:
|
||||
|
||||
@@ -61,11 +61,11 @@ OAKTL_API int oaktimeline_workarea_set_range_undoable(
|
||||
OAKTL_API int oaktimeline_workarea_set_enabled_undoable(
|
||||
OakTimelineWorkarea *w, int enabled, OakUndoCommand *command);
|
||||
OAKTL_API void oaktimeline_workarea_reset(int64_t *in_ts, int64_t *out_ts);
|
||||
/* load/save 经 oakcommon_xml 句柄在 oaknode 序列化路径调用 */
|
||||
/* load/save 经 oak_core_xml 句柄在 oaknode 序列化路径调用 */
|
||||
OAKTL_API int oaktimeline_workarea_load(OakTimelineWorkarea *w,
|
||||
OakCommonXmlReader *r);
|
||||
oak_coreXmlReader *r);
|
||||
OAKTL_API int oaktimeline_workarea_save(const OakTimelineWorkarea *w,
|
||||
OakCommonXmlWriter *x);
|
||||
oak_coreXmlWriter *x);
|
||||
```
|
||||
|
||||
### 2.3 `oaktimeline/edit.h`(timeline undo 命令族的语义入口)
|
||||
@@ -120,7 +120,7 @@ OAKTL_API int64_t oaktimeline_nearest_block_ts(OakNodeTrack *track,
|
||||
- 构建测试:`cmake -S src/timeline/standalone -B build-oaktimeline &&
|
||||
cmake --build build-oaktimeline -j && ctest --test-dir
|
||||
build-oaktimeline`——117/117(本模块 21 用例 + oaknode 回归 96)。
|
||||
全量回归:oakcommon 193、oaknode 96、oakrender 42、oakcodec 18、
|
||||
全量回归:oak_core 193、oaknode 96、oakrender 42、oakcodec 18、
|
||||
oakaudio 36 全绿。
|
||||
- C API 与 §2 冻结表的差异:marker/workarea 的增删改统一为
|
||||
`_command` 工厂形态(返回 OakUndoCommand,调用方 redo/push),
|
||||
|
||||
@@ -83,7 +83,7 @@ proxy:照 `oakengine/proxy.h` 模板(get_or_start/state/cancel)。
|
||||
|
||||
| 现状 | 处理 |
|
||||
|---|---|
|
||||
| codec → render/ 11 | videoparams/subtitleparams/colortransform 已随 M3.5 下沉 oakcommon;剩 renderer.h(2)、framemanager.h(1) → framemanager 是 codec 内部缓存编排,**随 codec 一起走**(从 render/ 移入 oakcodec/src,纯文件移动,它本来就主要服务 codec) |
|
||||
| codec → render/ 11 | videoparams/subtitleparams/colortransform 已随 M3.5 下沉 oak_core;剩 renderer.h(2)、framemanager.h(1) → framemanager 是 codec 内部缓存编排,**随 codec 一起走**(从 render/ 移入 oakcodec/src,纯文件移动,它本来就主要服务 codec) |
|
||||
| codec → task/ 5(taskmanager/conform/proxy 编排) | proxy/conform 对 TaskManager 的引用改为 01 §4 回调注册(`oakcodec_set_task_submit_cb`),Task 对象创建上移 oaktask(M8),oakcodec 只调回调 |
|
||||
| codec → node/ 3 | 经 oaknode C ABI(M3 已就位) |
|
||||
|
||||
|
||||
@@ -179,7 +179,7 @@ oakengine_ipc_* 悬置符号。
|
||||
|
||||
### 实际依赖与链接形态
|
||||
|
||||
- Oak 内部:oaknode、oakcommon、oakundo、olivecore、ffmpeg_bridge
|
||||
- Oak 内部:oaknode、oak_core、oakundo、olivecore、ffmpeg_bridge
|
||||
(真实 target,`add_subdirectory` 引入)。
|
||||
- 第三方:OpenColorIO、OpenImageIO、Imath/OpenEXR(头)、OpenGL/
|
||||
CoreVideo/Metal/QuartzCore framework、GTest(仅测试)。
|
||||
@@ -209,10 +209,10 @@ oakengine_ipc_* 悬置符号。
|
||||
共 **56** 个,**0 个悬置**」:25 个由 liboakrender 解析
|
||||
(PlaybackCache/FrameHashCache/DiskManager/RenderManager/
|
||||
ColorProcessor/PreviewAutoCacher/LUTLibrary 等),其余 31 个由
|
||||
oakcommon(VideoParams/XmlStream*/SubtitleParams/QtUtils)、
|
||||
oak_core(VideoParams/XmlStream*/SubtitleParams/QtUtils)、
|
||||
oakundo(UndoCommand/UndoStack/MultiUndoCommand vtable)解析。
|
||||
- 公共头位于 `include/render/`(非 §1 的 `include/oakrender/`),
|
||||
函数前缀 `oakrender_`,与 oaknode/oakcommon 的既有契约一致
|
||||
函数前缀 `oakrender_`,与 oaknode/oak_core 的既有契约一致
|
||||
(§1 目标形态中的 `oakrender/include/oakrender/` 未采用)。
|
||||
- C API 命名照 R7-A §A.2 的 display.h 重写版改前缀
|
||||
`oakrender_display_*`/`oakrender_codec_frame_*`;`OakCodecFrame`
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
CancelableObject只在render和task处有🚰,移入对应模块。
|
||||
|
||||
## 从 oakcommon(src/common)移除的类(2026-08-05)
|
||||
## 从 oak_core(src/common)移除的类(2026-08-05)
|
||||
|
||||
判据:不严重依赖 common 其他类,且只有一个非 common 模块使用它
|
||||
(tests/gtest 不计入使用方)。以下类已从 `src/common/` 移除,
|
||||
@@ -12,7 +12,7 @@ CancelableObject只在render和task处有🚰,移入对应模块。
|
||||
|
||||
| 类 | 唯一使用方 | 应放到 |
|
||||
|---|---|---|
|
||||
| `Html`(html.h/.cpp) | engine/node | oaknode(M3)。注意它依赖 common 的 xmlutils,迁移时需连同 XML 辅助或改为调用 oakcommon C API |
|
||||
| `Html`(html.h/.cpp) | engine/node | oaknode(M3)。注意它依赖 common 的 xmlutils,迁移时需连同 XML 辅助或改为调用 oak_core C API |
|
||||
| `JobTime`(jobtime.h/.cpp) | engine/render | oakrender(M7) |
|
||||
| `OTIOUtils`(otioutils.h) | engine/task | oaktask(M8) |
|
||||
| `PlaybackAudioClock`(playbackaudioclock.h) | engine/audio | oakaudio(M6) |
|
||||
@@ -27,15 +27,15 @@ CancelableObject只在render和task处有🚰,移入对应模块。
|
||||
|
||||
另:`power.h`、`memorypool.h`、`threadsafemap.h` 当前没有任何
|
||||
common 模块外的使用方(零用户),不满足移除判据,暂保留在
|
||||
oakcommon;后续若确认无用途可直接删除。
|
||||
oak_core;后续若确认无用途可直接删除。
|
||||
|
||||
## oakcommon 去Qt化的删除与语义变更(2026-08-05)
|
||||
## oak_core 去Qt化的删除与语义变更(2026-08-05)
|
||||
|
||||
去Qt化过程中以下函数被删除或语义变化,迁移调用方时需注意:
|
||||
|
||||
- `CommandLineParser::print_help()`:不再自动读取
|
||||
`QCoreApplication::applicationName()/applicationVersion()`,需先调
|
||||
`set_app_info()`(C API:`oakcommon_commandlineparser_set_app_info`),
|
||||
`set_app_info()`(C API:`oak_core_commandlineparser_set_app_info`),
|
||||
否则打印默认 `"oak"` + 空版本。
|
||||
- `FileFunctions::get_unique_file_identifier`:哈希由 SHA-1 改为
|
||||
FNV-1a 64-bit,旧缓存 key 全部失效(需一次重建)。
|
||||
@@ -51,7 +51,7 @@ oakcommon;后续若确认无用途可直接删除。
|
||||
`olive::XmlStreamReader/Writer` 替代(不支持 XML 命名空间)。
|
||||
- `OIIOUtils::frame_to_buffer/buffer_to_frame`:未进 C API,C++ 侧签名
|
||||
拍平为 `(const void *data, int64_t linesize_bytes, OIIO::ImageBuf *)`,
|
||||
engine/codec/frame.cpp 迁移时传成员即可。`OakCommonPixelFormat` 枚举
|
||||
engine/codec/frame.cpp 迁移时传成员即可。`oak_corePixelFormat` 枚举
|
||||
目前定义在 include/common/ocioutils.h,oiioutils 复用,后续可抽成
|
||||
独立的 include/common/pixelformat.h。
|
||||
- `MemoryPool`:删除 QTimer 每 5 秒自动回收空 arena,改为公有
|
||||
@@ -67,7 +67,7 @@ oakcommon;后续若确认无用途可直接删除。
|
||||
`create_horizontal/vertical_line`、`set_combo_box_data`、
|
||||
`word_wrap_string`、`flip_control_and_shift_modifiers`、
|
||||
`get_formatted_date_time`、`to_q_color`、`core::qHash`、
|
||||
`Q_DECLARE_METATYPE` 宏组)未迁入 oakcommon,app 层继续用 Qt 版。
|
||||
`Q_DECLARE_METATYPE` 宏组)未迁入 oak_core,app 层继续用 Qt 版。
|
||||
`ptr_to_value/value_to_ptr` 载体由 QVariant 改为 `uintptr_t`,
|
||||
迁移时调用点需同步改(renderprocessor.cpp、rendermanager.cpp、
|
||||
previewautocacher.cpp、src/capi/worker.cpp)。`get_parent_of_type`
|
||||
@@ -283,7 +283,7 @@ ColorManager)去Qt化过程中的删除与语义变化,迁移调用方时需
|
||||
- oaknode↔oaktimeline 运行期互相解析(add_default_nodes →
|
||||
TimelineAddTrackCommand),双方 dylib dynamic_lookup,测试二进制
|
||||
必须同时链两个库(各 standalone 驱动已接线)。
|
||||
- oakcommon xml C API 新增 get_native 借用访问器(C++ only),
|
||||
- oak_core xml C API 新增 get_native 借用访问器(C++ only),
|
||||
oaktimeline 的 load/save 经它取回 XmlStreamReader/Writer。
|
||||
|
||||
## oakplugin 去Qt化的删除与语义变更(2026-08-05)
|
||||
@@ -348,8 +348,8 @@ ColorManager)去Qt化过程中的删除与语义变化,迁移调用方时需
|
||||
OAK_TIMELINE_WAVEFORMS_*,值与 olive::Timeline 枚举保持兼容)。
|
||||
- tracklist.h/block.h 里 timelinecommon.h 的死引用删除;
|
||||
src/node/transition/timeline/ 四个 stub 头删除。
|
||||
- oakcommon xml C API 新增 oakcommon_xml_reader_wrap_native/
|
||||
oakcommon_xml_writer_wrap_native(C++ only 借用包装),
|
||||
- oak_core xml C API 新增 oak_core_xml_reader_wrap_native/
|
||||
oak_core_xml_writer_wrap_native(C++ only 借用包装),
|
||||
XmlReaderState/XmlWriterState 支持 owning/borrowed 双模式。
|
||||
- liboaknode 对 liboaktimeline 的 C++ 符号引用降为 0(nm 验证)。
|
||||
|
||||
@@ -404,7 +404,7 @@ Rust 重写驱动(RIIR 后调用方只能走 C ABI,接线自动发生且被
|
||||
|
||||
- 已切:oaknode→oaktimeline(81431d180)、oaknode→oakrender
|
||||
(5a564f30c,缓存体系/色彩/单例全部 C ABI 化)。
|
||||
- olive::Variant 从 oaknode 下沉到 oakcommon(src/common/src/
|
||||
- olive::Variant 从 oaknode 下沉到 oak_core(src/common/src/
|
||||
variant.{h,cpp})——它本是跨模块值类型。
|
||||
- 冻结时点的残留(nm 可查):
|
||||
- render→node 41 个 C++ 符号:ProjectCopier 深拷贝族、
|
||||
@@ -415,15 +415,15 @@ Rust 重写驱动(RIIR 后调用方只能走 C ABI,接线自动发生且被
|
||||
oaknode_project_deep_copy/sync_copy,traverser 改 hook 制)。
|
||||
- node/render→plugin 的 OFX C++ 符号:随 M11(DeepSeek 实现中)
|
||||
落地消解。
|
||||
- 各模块→oakcommon 的 XmlStreamReader/FileFunctions/VideoParams
|
||||
C++ 调用:随 oakcommon Rust 化消解。
|
||||
- 各模块→oak_core 的 XmlStreamReader/FileFunctions/VideoParams
|
||||
C++ 调用:随 oak_core Rust 化消解。
|
||||
- 文档化例外:Texture 的 Variant 载荷(Rust 侧不存在此问题)、
|
||||
UndoCommand 跨模块继承、oakgl2/oakvulkan 后端插件接口。
|
||||
- ④(隐藏 C++ API)同步搁置:模块 Rust 化后 C++ 符号自然消失。
|
||||
|
||||
## oakcommon Rust 测试:ffmpeg_bridge 符号依赖(2026-08-08)
|
||||
## oak_core Rust 测试:ffmpeg_bridge 符号依赖(2026-08-08)
|
||||
|
||||
`oakcommon_ffmpegutils_get_compatible_bridge_pixel_format` 在非测试构建
|
||||
`oak_core_ffmpegutils_get_compatible_bridge_pixel_format` 在非测试构建
|
||||
中会经 `find_best_pix_fmt_of_list` 引用 ffmpeg_bridge 的
|
||||
`fb_find_best_pix_fmt_of_list` 符号。集成测试二进制不链接 libffmpeg_bridge,
|
||||
实验证实直接调用该 FFI 导出会在链接期报 `_fb_find_best_pix_fmt_of_list`
|
||||
@@ -441,7 +441,7 @@ test-stubs 约定一致):
|
||||
(成功路径 + null out-param 的 E_INVALID 路径),需带
|
||||
`--features test-stubs` 运行;不带 flag 时该文件整体为空(cfg 门控)。
|
||||
|
||||
## oakcommon Rust:ocioutils/oiioutils 吸收 oakoci(2026-08-08 接手笔记)
|
||||
## oak_core Rust:ocioutils/oiioutils 吸收 oakoci(2026-08-08 接手笔记)
|
||||
|
||||
### 基线
|
||||
|
||||
|
||||
@@ -22,15 +22,15 @@
|
||||
```
|
||||
liboakengine(一个 dylib,crate 图是 DAG)
|
||||
├── oakcore-rs ← 共享 ABI 类型(CHandle + POD),无依赖的叶子
|
||||
├── oakcommon → oakcore-rs
|
||||
├── oak_core → oakcore-rs
|
||||
├── oakundo → oakcore-rs
|
||||
├── oaknode → oakcore-rs, oakcommon, oakundo, oakcodec
|
||||
├── oaknode → oakcore-rs, oak_core, oakundo, oakcodec
|
||||
├── oaktimeline → oakcore-rs, oakundo, oaknode
|
||||
├── oakcodec → oakcore-rs, oakrender (codec→render 直接调)
|
||||
├── oakaudio → oakcore-rs, oakcommon, oakcodec
|
||||
├── oakrender → oakcore-rs, oakcommon, oaknode (render→node 直接调)
|
||||
├── oaktask → oakcore-rs, oakcommon, oakundo, oakcodec, oaknode, oakrender
|
||||
├── oakplugin → oakcore-rs, oakcommon, oakundo, oaknode, oakrender(suites 仍 C)
|
||||
├── oakaudio → oakcore-rs, oak_core, oakcodec
|
||||
├── oakrender → oakcore-rs, oak_core, oaknode (render→node 直接调)
|
||||
├── oaktask → oakcore-rs, oak_core, oakundo, oakcodec, oaknode, oakrender
|
||||
├── oakplugin → oakcore-rs, oak_core, oakundo, oaknode, oakrender(suites 仍 C)
|
||||
└── oakengine → 全部(facade)
|
||||
```
|
||||
|
||||
@@ -64,7 +64,7 @@ liboakengine(一个 dylib,crate 图是 DAG)
|
||||
| oakcodec | extern "C" | common 15657 / render 7262(+test_stubs 27176) | 0 |
|
||||
| oakaudio | extern "C" | codec 6683 / common 1665 / ffmpeg 7812 | 0 |
|
||||
| oaktimeline | extern "C" | common / node 11742 / undo 2780(+teststubs 52921) | 0 |
|
||||
| oakundo / oakcommon | — | 无 bridge | — |
|
||||
| oakundo / oak_core | — | 无 bridge | — |
|
||||
|
||||
facade `src/engine/rust/src/bridge/`:9 个文件 2466 行、**624 个
|
||||
`extern "C"` 导入**(node 348 / common 91 / render 36 / timeline 34 /
|
||||
@@ -97,8 +97,8 @@ task 33 / audio 31 / codec 24 / undo 22 / plugin 5),由
|
||||
|
||||
| 环 | 边 | 处理 |
|
||||
|---|---|---|
|
||||
| **node ↔ render** | node→render 3 fn + render→node copier | §4.1:render→node 保留直接依赖;node→render 的 3 个函数下沉 oakcommon(实现本就在 oakcommon 侧:`default_disk_cache_path` 已是 render/bridge/common.rs 内的纯 Rust 实现;OCIO config 由 oakcommon `ocioutils::OcioConfig` 提供) |
|
||||
| **codec ↔ render** | codec→render cancelatom + render→codec stub | §4.2:cancelatom 下沉 oakcommon(原子取消旗标,纯 Rust);render→codec 的 stub 检查直接删除(路径必然 Err) |
|
||||
| **node ↔ render** | node→render 3 fn + render→node copier | §4.1:render→node 保留直接依赖;node→render 的 3 个函数下沉 oak_core(实现本就在 oak_core 侧:`default_disk_cache_path` 已是 render/bridge/common.rs 内的纯 Rust 实现;OCIO config 由 oak_core `ocioutils::OcioConfig` 提供) |
|
||||
| **codec ↔ render** | codec→render cancelatom + render→codec stub | §4.2:cancelatom 下沉 oak_core(原子取消旗标,纯 Rust);render→codec 的 stub 检查直接删除(路径必然 Err) |
|
||||
|
||||
其余方向均无环:node→timeline 0 调用、task→* 单向、plugin→* 单向、
|
||||
audio→* 单向、timeline→node/undo 单向。
|
||||
@@ -155,13 +155,13 @@ layout 相同但 Rust 类型不同的 `CHandle`、POD(`OakVideoParams`、
|
||||
| crate | 处理 |
|
||||
|---|---|
|
||||
| facade `engine/rust/src/bridge/` | §5:`extern "C"` 块 → 直接调用模块 crate `ffi` 的安全包装(同名同签名) |
|
||||
| oaknode `bridge/{undo,common,codec}` | 直接调用 oakundo/oakcommon/oakcodec 的 ffi;`bridge/` 删除 |
|
||||
| oaknode `bridge/{undo,common,codec}` | 直接调用 oakundo/oak_core/oakcodec 的 ffi;`bridge/` 删除 |
|
||||
| oaknode `bridge/{render,timeline,core}` | render/timeline 见 §4(环/死代码);core → oakcore-rs / 宿主 liboakcore(保持 link-time extern,见 §4.3) |
|
||||
| oaktask `bridge/*` | 直接调用各目标 crate ffi;`bridge/` 删除 |
|
||||
| oakrender `bridge/node` | 直接调用 oaknode ffi(§4.1) |
|
||||
| oakrender `bridge/{codec,common}` | codec → §4.2(stub 删除);common → 直接调用 oakcommon |
|
||||
| oakrender `bridge/{codec,common}` | codec → §4.2(stub 删除);common → 直接调用 oak_core |
|
||||
| oakplugin `bridge/{node,render,undo}` | 直接调用各目标 crate ffi;suites 保持 C |
|
||||
| oakcodec `bridge/{common,render}` | common → oakcommon;render → oakrender(cancelatom 移 oakcommon 后改调 oakcommon,见 §4.2) |
|
||||
| oakcodec `bridge/{common,render}` | common → oak_core;render → oakrender(cancelatom 移 oak_core 后改调 oak_core,见 §4.2) |
|
||||
| oakaudio `bridge/{codec,common,ffmpeg}` | codec/common → 直接调用;ffmpeg → ffmpeg_bridge(C++,保持 extern "C") |
|
||||
| oaktimeline `bridge/{node,undo,common}` | node/undo → 直接调用;common 0 调用 → 删除;`teststubs.rs` 见 §7 |
|
||||
|
||||
@@ -182,10 +182,10 @@ layout 相同但 Rust 类型不同的 `CHandle`、POD(`OakVideoParams`、
|
||||
实现**(2026-08-10 全量 grep 确认),所以运行时必然 dlsym 失败,走
|
||||
"缺失"分支。破环 = 删除死调用:
|
||||
|
||||
1. `disk_cache_path()`:实现**下沉 oakcommon**(新增
|
||||
1. `disk_cache_path()`:实现**下沉 oak_core**(新增
|
||||
`filefunctions::default_disk_cache_path()`,基于既有的
|
||||
`FileFunctions::get_configuration_location()`)。oaknode
|
||||
`project.rs` 与 oakrender `manager.rs` 都直接调 oakcommon。
|
||||
`project.rs` 与 oakrender `manager.rs` 都直接调 oak_core。
|
||||
2. `color_config_create_default()`/`color_config_load()`:oakrender 从未
|
||||
实现这两个符号 → node `colormanager.rs` 的调用恒为 `None`(走
|
||||
"标记已加载/保持原状" 分支)。删除调用、保留确定性等价逻辑(行为不变)。
|
||||
@@ -205,12 +205,12 @@ layout 相同但 Rust 类型不同的 `CHandle`、POD(`OakVideoParams`、
|
||||
render→codec = 0。
|
||||
- **codec → render**:只有 cancelatom。实施时发现 codec 收到的 atom 句柄
|
||||
是 oakrender `make_owned` 按 **oakrender 的 `RefBox` 布局**装箱的,
|
||||
codec 直接解引用会在不同 crate 的 `RefBox` 布局间读内存(oakcommon
|
||||
codec 直接解引用会在不同 crate 的 `RefBox` 布局间读内存(oak_core
|
||||
value-first、其余 refs-first),**不安全**。因此 cancelatom 的读取保持
|
||||
经 oakrender 的 C 导出(codec `bridge::render` 的 link-time extern,
|
||||
与 `oakcore_*`/`fb_*` 同类,属"不可避免的 C 边界");实现体下沉
|
||||
oakcommon(`cancelatom::CancelAtom`,oakrender 的
|
||||
`oakrender_cancelatom_*` 导出改包 oakcommon,`render/cancelatom.rs`
|
||||
oak_core(`cancelatom::CancelAtom`,oakrender 的
|
||||
`oakrender_cancelatom_*` 导出改包 oak_core,`render/cancelatom.rs`
|
||||
变为 re-export)。
|
||||
|
||||
结果:codec 与 render 之间无 crate 依赖;codec→render 仅剩 cancelatom
|
||||
@@ -239,7 +239,7 @@ pub fn oaknode_project_init() -> CHandle {
|
||||
```
|
||||
|
||||
- 每个 ffi fn 的路径:`oak<mod>::ffi::<子模块>::<fn>`(如
|
||||
`oaknode::ffi::project`、`oaknode::ffi::folder`、`oakcommon::ffi::config`…);
|
||||
`oaknode::ffi::project`、`oaknode::ffi::folder`、`oak_core::ffi::config`…);
|
||||
实现时以模块 crate 实际 `pub mod` 布局为准(已核对:oaknode ffi 有
|
||||
`project/node/keyframe/…` 子模块)。
|
||||
- **facade 业务代码(node.rs/timeline.rs/… 共 393 处调用)零改动**:
|
||||
@@ -257,24 +257,24 @@ pub fn oaknode_project_init() -> CHandle {
|
||||
逐方向(每步一个 crate 一个方向,`cargo build`+`cargo test` 闭环):
|
||||
|
||||
1. oaknode:`bridge/undo.rs`、`bridge/common.rs`、`bridge/codec.rs`
|
||||
(→ oakundo/oakcommon/oakcodec 直接调,同 §5 的包装写法);
|
||||
(→ oakundo/oak_core/oakcodec 直接调,同 §5 的包装写法);
|
||||
2. oaktimeline:`bridge/node.rs`、`bridge/undo.rs`(→ oaknode/oakundo);
|
||||
3. oakrender:`bridge/node.rs`(→ oaknode,§4.1)、`bridge/common.rs`
|
||||
(→ oakcommon);
|
||||
(→ oak_core);
|
||||
4. oaktask:`bridge/{node,render,codec,undo,common}.rs`;
|
||||
5. oakplugin:`bridge/{node,render,undo}.rs`(suites 不动);
|
||||
6. oakcodec:`bridge/common.rs`(→ oakcommon)、`bridge/render.rs`
|
||||
(→ oakcommon cancelatom,§4.2);
|
||||
6. oakcodec:`bridge/common.rs`(→ oak_core)、`bridge/render.rs`
|
||||
(→ oak_core cancelatom,§4.2);
|
||||
7. oakaudio:`bridge/{codec,common}.rs`;
|
||||
8. oaknode:`bridge/render.rs`(→ oakcommon,§4.1)、`bridge/timeline.rs`
|
||||
8. oaknode:`bridge/render.rs`(→ oak_core,§4.1)、`bridge/timeline.rs`
|
||||
(死代码删除,测试迁移见 §7)、`bridge/core.rs`(§4.3 保留 extern)。
|
||||
|
||||
被调方需要被加为 path 依赖的 crate:oaknode 加 `oakundo`/`oakcommon`/
|
||||
被调方需要被加为 path 依赖的 crate:oaknode 加 `oakundo`/`oak_core`/
|
||||
`oakcodec`;oaktimeline 加 `oakundo`/`oaknode`;oakrender 加
|
||||
`oakcommon`/`oaknode`;oaktask 加 `oakundo`/`oakcommon`/`oakcodec`/
|
||||
`oaknode`/`oakrender`;oakplugin 加 `oakcore-rs`/`oakcommon`/`oakundo`/
|
||||
`oaknode`/`oakrender`;oakcodec 加 `oakcommon`;oakaudio 加
|
||||
`oakcommon`/`oakcodec`。**不产生任何环**(§1.3 已消除)。
|
||||
`oak_core`/`oaknode`;oaktask 加 `oakundo`/`oak_core`/`oakcodec`/
|
||||
`oaknode`/`oakrender`;oakplugin 加 `oakcore-rs`/`oak_core`/`oakundo`/
|
||||
`oaknode`/`oakrender`;oakcodec 加 `oak_core`;oakaudio 加
|
||||
`oak_core`/`oakcodec`。**不产生任何环**(§1.3 已消除)。
|
||||
|
||||
## 7. 测试策略(每 crate 测试保持绿)
|
||||
|
||||
@@ -283,14 +283,14 @@ pub fn oaknode_project_init() -> CHandle {
|
||||
- **用 `bridge/` 的测试必须迁移**(桥层从生产路径删除后不能留在测试里):
|
||||
- 目标 crate 已 path 依赖的:`oaknode::bridge::undo::…` →
|
||||
`oakundo::ffi::…`(或 oakundo 类型层)直接调;`bridge::common::videoparams_*`
|
||||
→ `oakcommon::…`;`bridge::core::audioparams_*` → `oakcore_rs::…`
|
||||
→ `oak_core::…`;`bridge::core::audioparams_*` → `oakcore_rs::…`
|
||||
/ 宿主 liboakcore extern;
|
||||
- 依赖不存在(环/死代码)的:`node::bridge::timeline` 的测试用
|
||||
oaktimeline 自身导出或改写;`node::bridge::render` 的测试改调
|
||||
oakcommon 下沉后的函数;
|
||||
oak_core 下沉后的函数;
|
||||
- 专门测 dlsym 机制的测试(如 `node/rust/tests/dbg2_test.rs` 的
|
||||
`bridge::dlsym::resolve`)随机制删除而删除。
|
||||
- **`test-stubs` feature(oakplugin/oakcommon/oaktimeline/oaknode)**:
|
||||
- **`test-stubs` feature(oakplugin/oak_core/oaktimeline/oaknode)**:
|
||||
语义变为"编译测试桩 C ABI(替代尚未存在的宿主/兄弟模块实现)"。
|
||||
直接调用落地后,同一二进制内不再同时出现"真实现 + 桩"冲突:
|
||||
facade `cargo test` 的 dev-dependency feature union 按新依赖图调整
|
||||
@@ -319,7 +319,7 @@ pub fn oaknode_project_init() -> CHandle {
|
||||
`cargo build` + `cargo test`(这一步后直接调用才类型同一)。
|
||||
2. **facade bridge → 直接调用**(§5,步骤 a)。
|
||||
3. **环处理**(§4):删除死调用;disk_cache_path/cancelatom 下沉
|
||||
oakcommon;render 的 `codec_abi_available()` stub 检查删除。
|
||||
oak_core;render 的 `codec_abi_available()` stub 检查删除。
|
||||
4. **模块 bridge 逐方向 → 直接调用**(§6,步骤 b)。
|
||||
5. **dlsym 删除**(步骤 c):node/render/plugin 的 `bridge/mod.rs::dlsym`
|
||||
与残留调用清除;`linkage.rs` 注释更新。
|
||||
@@ -354,7 +354,7 @@ pub fn oaknode_project_init() -> CHandle {
|
||||
`OakUndoCommandVtable`/`OakVideoTicketParams`/`OakRenderVideoParams`/
|
||||
`OffsetResult`/`StretchOffsetResult`/`SourceClip` → 各模块 crate 类型。
|
||||
- **环处理**(§4 实施结论):node↔render 死调用删除;render→codec stub
|
||||
删除;`oakcommon::{filefunctions::default_disk_cache_path, cancelatom}`;
|
||||
删除;`oak_core::{filefunctions::default_disk_cache_path, cancelatom}`;
|
||||
render 的 `cancelatom.rs` 改为 re-export。
|
||||
- **模块 bridge**(步骤 b,模式已证明):oaknode `bridge/undo.rs`
|
||||
→ oakundo 直接调用(oakundo 加入 node 依赖;bridge 函数名/签名不变,
|
||||
@@ -372,18 +372,18 @@ encoding-params POD(`oakcodec_encoding_params` 等)在 4 个 crate 各有
|
||||
本轮完成的方向(每步 `cargo build` + 该 crate `cargo test` 绿):
|
||||
|
||||
- **oaknode `bridge/{undo,common,codec}` → 直接调用**(上轮已做 undo,
|
||||
本轮完成 common + codec):oakcommon/oakcodec 加入 node 依赖;common
|
||||
桥 31 个 dlsym 包装改为 `oakcommon::ffi::*` 直接调用,`test-stubs`
|
||||
本轮完成 common + codec):oak_core/oakcodec 加入 node 依赖;common
|
||||
桥 31 个 dlsym 包装改为 `oak_core::ffi::*` 直接调用,`test-stubs`
|
||||
特性与库内 XML 桩删除;codec 桥的 `decoder_probe` 改为直接调用
|
||||
`oakcodec::ffi::decoder::oakcodec_decoder_probe`(签名修正为真实
|
||||
单参返回 CHandle,footage.rs 调用点同步)。node dlsym 52→20。
|
||||
- **oakrender `bridge/common` → 直接调用**:config/configuration_location/
|
||||
disk_cache_path 改调 `oakcommon::ffi` 与 `oakcommon::filefunctions`;
|
||||
disk_cache_path 改调 `oak_core::ffi` 与 `oak_core::filefunctions`;
|
||||
`bridge/codec.rs` 全死代码(0 生产调用、0 测试引用)**删除**;
|
||||
`bridge/node.rs`(copier 深拷贝)是死方向(oaknode 未实现该 C ABI,
|
||||
且 `oakrender_project_copier_*` 是冻结导出)——保留 dlsym 并记录。
|
||||
render dlsym 22→4。
|
||||
- **oakaudio `bridge/{codec,common}` → 直接调用**:oakcodec/oakcommon
|
||||
- **oakaudio `bridge/{codec,common}` → 直接调用**:oakcodec/oak_core
|
||||
加入 audio 依赖;codec 桥的 `*mut c_void` 句柄约定与真实
|
||||
`CHandle`/`OakCodecAudioStreamInfo`/`oakcodec_encoding_params` 对齐
|
||||
(类型别名统一),调用点(waveform/manager)同步;common 桥改直接
|
||||
@@ -394,7 +394,7 @@ encoding-params POD(`oakcodec_encoding_params` 等)在 4 个 crate 各有
|
||||
断言改为探针错误路径(完整解码依赖宿主 ffmpeg_bridge,Rust 测试
|
||||
二进制不链接)。
|
||||
- **oakcodec `test-stubs` 特性拆分**(为 node 测试二进制提供宿主符号):
|
||||
`src/bridge/test_stubs.rs` 的 oakcommon_* 桩保持 `#[cfg(test)]`
|
||||
`src/bridge/test_stubs.rs` 的 oak_core_* 桩保持 `#[cfg(test)]`
|
||||
(codec 自身测试用),oakcore_*/oakrender_* 桩改为
|
||||
`#[cfg(any(test, feature="test-stubs"))]`;node 的 dev-dependencies
|
||||
以 `features=["test-stubs"]` 依赖 oakcodec,解决 node 测试链接
|
||||
@@ -429,16 +429,16 @@ encoding-params POD(`oakcodec_encoding_params` 等)在 4 个 crate 各有
|
||||
容错路径(`texture_is_dummy` 空句柄 0、`instance_render` 空 dst 被
|
||||
插件层 E_INVALID 拒绝、`render_job` 同);OFX suites 层未触碰。
|
||||
- **oaktimeline `bridge/{node,undo,common}` → 直接调用**:oaknode/
|
||||
oakundo/oakcommon 加入依赖;81 个桥函数直接调用。`teststubs.rs`
|
||||
oakundo/oak_core 加入依赖;81 个桥函数直接调用。`teststubs.rs`
|
||||
(1658 行)改为纯 Rust mock(去 `#[no_mangle]`),桥函数加
|
||||
`#[cfg(any(test, feature="test-stubs"))]` mock 变体 / 真实变体,
|
||||
测试二进制(cfg(test) 对依赖关)经 `--features test-stubs` 解析
|
||||
`bridge::teststubs`——与真实 crate 导出共存无冲突。修复桥签名漂移:
|
||||
`oakcommon_xml_reader_read_next_start_element` 2 参(found 标志,
|
||||
`oak_core_xml_reader_read_next_start_element` 2 参(found 标志,
|
||||
调用点 ffi.rs/tests 同步);`oakundo_stack_push`→真实
|
||||
`oakundo_undostack_push`。260 测试绿。
|
||||
- **oaktask `bridge/*` → 直接调用**(240 个桥函数):oaknode/oakundo/
|
||||
oakcommon/oakcodec/oakrender/oaktimeline 加入依赖(oakrender 由可选
|
||||
oak_core/oakcodec/oakrender/oaktimeline 加入依赖(oakrender 由可选
|
||||
转必选,`real-oakrender` 特性改为标记)。镜像类型对齐真实 crate:
|
||||
`OakCancelAtom`/`OakRenderTicket`/`OakRenderCache`/`OakColorProcessor`
|
||||
等 → CHandle 别名,`OakCodecEncodingParams`/`OakCodecProxyParams`/
|
||||
|
||||
Reference in New Issue
Block a user