Files
oak-editor/docs/zh/modularization-plan/README.md
T

115 lines
9.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Olive/Oak 模块化与多进程渲染:显式加载 + 纯 C 接口方案
> **状态**:详细实施计划
> **范围**:仅制定方案,不涉及代码变更。
> **核心目标**
> 1. 所有业务模块编译为动态库,主进程**显式加载**`dlopen`/`LoadLibrary`),通过**纯 C 接口**交互。
> 2. 渲染引擎拆分为独立可执行文件 `olive-renderer`,采用**"用完即弃"**的进程模型:每帧(或每几帧)启动一个新进程,渲染完成后立即退出,最大限度避免锁和状态同步问题。
---
## 目录索引
| 文件 | 内容 |
|---|---|
| `README.md` | 本文档:总体架构、设计哲学、目录索引 |
| `09-c-api-design.md` | **先读此文件**:C API 设计规范、显式加载器、内存管理、错误处理、类型映射总纲。所有其他库的 C API 都遵循此规范。 |
| `01-olivecore.md` | `libolivecore.so`:基础数据类型库(Rational, Color, TimeRange, PixelFormat, SampleBuffer 等) |
| `02-olivecodec.md` | `libolivecodec.so`:编解码库(Decoder, Encoder, Frame, Stream |
| `03-oliveplugin.md` | `liboliveplugin.so`OFX 插件宿主支持 |
| `04-oliveaudio.md` | `liboliveaudio.so`:音频播放与处理 |
| `05-olivenode.md` | `libolivenode.so`:节点图系统(Node, NodeGraph, Project, Param, Keyframe, Timeline, Undo |
| `06-oliverender.md` | `liboliverender.so`:渲染引擎抽象(RenderContext, RenderJob, RenderResult |
| `07-oliveui.md` | `liboliveui.so`UI 层(Widget, Panel, Window, Dialog |
| `08-olive-renderer.md` | `olive-renderer` 可执行文件:多进程渲染的"用完即弃"模型详细设计 |
| `10-implementation-roadmap.md` | 10 周小步快跑实施路线图,含每周任务、验收标准、回退策略 |
| `11-ipc-protocol.md` | 渲染子进程的 IPC 协议(命令行参数、stdin JSON、stdout NDJSON、共享内存) |
---
## 总体架构图
```
┌─────────────────────────────────────────────────────────────────────────────┐
│ olive-editor(主进程,GUI
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ ModuleLoader(显式加载管理器) │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
│ │ │dlopen │ │dlopen │ │dlopen │ │dlopen │ │dlopen │ │ │
│ │ │olivecore │ │olivecodec│ │olivenode │ │oliverender││oliveui │ │ │
│ │ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ │ │
│ │ │ │ │ │ │ │ │
│ │ └────────────┴────────────┴────────────┘ │ │ │
│ │ 纯 C 接口交互 │ │ │
│ │ ▼ │ │
│ │ ┌──────────────┐ │ │
│ │ │ QProcess │ │ │
│ │ │ 启动/等待/回收 │ │ │
│ │ └──────┬───────┘ │ │
│ └───────────────────────────────────────────────────────────┼───────────┘ │
│ │ │
├──────────────────────────────────────────────────────────────┼───────────────┤
│ │ │
│ ┌───────────────────────────────────────────────────────────┘ │
│ │ olive-renderer(子进程,无 GUI"用完即弃"
│ │ │
│ │ 启动参数:--node-graph=/tmp/g.xml --time=1001/30000 --output-shm=/o_123 │
│ │ │
│ │ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ │ 1. 初始化 Qt Core │ │
│ │ │ 2. 初始化 OpenGL 离屏上下文 │ │
│ │ │ 3. 加载节点图 XML │ │
│ │ │ 4. 执行渲染(RenderProcessor + OpenGLRenderer │ │
│ │ │ 5. 将帧数据写入共享内存 │ │
│ │ │ 6. 输出 JSON 结果到 stdout │ │
│ │ │ 7. 清理并退出(return 0 │ │
│ │ └─────────────────────────────────────────────────────────────────────┘ │
│ └────────────────────────────────────────────────────────────────────────────┘
│ 所有动态库共享的基础依赖:QtCore, FFmpeg, OpenColorIO 等(由操作系统加载器解析)
└─────────────────────────────────────────────────────────────────────────────┘
```
---
## 核心设计哲学
### 1. 显式加载 + 纯 C 接口
- **主进程不链接任何业务动态库**。`olive-editor``main.cpp``core.cpp` 中没有任何对业务模块的 `#include`(除 C API 头文件外)。
- 所有跨模块边界的交互通过**纯 C 函数**完成,使用**不透明指针(Opaque Pointer**封装 C++ 对象。
- 动态库内部可以继续使用 C++、Qt、STL、虚函数、模板等任意特性,但对外仅暴露 C 接口。
**为什么用 C 接口而非 C++ 类?**
- C++ 的 ABI(虚表布局、name mangling、异常传播)在不同编译器/版本间不兼容。
- C 接口的符号名干净(无 mangling),`dlsym` 可直接查找。
- 未来如果需要,C 接口可被 Python、Rust、C# 等语言直接绑定。
### 2. "用完即弃"的渲染进程
- **每一帧(或每 N 帧)渲染任务 = 一个独立的操作系统进程**。
- 进程启动时接收完整的渲染参数和节点图,渲染完成后立即 `exit(0)`
- **不存在常驻渲染进程**,因此不需要:心跳检测、崩溃恢复、状态同步、读写锁、graph_ref 缓存、复杂的取消机制。
- 主进程如果需要取消渲染,直接 `QProcess::kill()` 即可。
**可能的问题与回退**
- 若进程启动开销(`QProcess::start()` + OpenGL 上下文初始化)导致实时预览帧率不足,可回退为**"批处理模式"**:每 3–5 帧共享一个进程,或预先启动一个进程池(但进程池内的进程仍不共享状态,每个进程只处理一个批次后自杀)。详见 `08-olive-renderer.md`
### 3. 小步快跑
- 每个模块的改造都是**独立、可回退、可并行**的。
- 不改现有 C++ 类定义,只在其上层**新增 C 封装层**(`api/<module>_api.cpp`)。
- 保留原有 OBJECT 库编译方式,通过 CMake 选项 `-DOLIVE_DYNAMIC_MODULES=ON` 切换。
- 每完成一个模块,就通过该模块的单元测试验证,再进入下一个模块。
---
## 快速开始(阅读顺序)
1. **先读 `09-c-api-design.md`**:理解 C API 的约定、显式加载器、内存管理规则。
2. **再读 `08-olive-renderer.md`**:理解最核心的架构变革——多进程渲染。
3. **然后按任意顺序阅读 `01-` 到 `07-`**:各业务模块的具体 C API 设计和实施步骤。
4. **最后读 `10-implementation-roadmap.md`**:10 周实施计划,了解如何排期和验收。
5. **参考 `11-ipc-protocol.md`**:渲染子进程的通信协议细节。