refactor(task,render): RenderTask family over a new oakrender ticket C ABI

- oakrender: new ticket family (render_frame/render_audio with finished
  callback, result frame/samples access, cancel/wait), project copier
  C API, cache get_invalidated_ranges, manager set_aggressive_gc
- oaknode: node_copy_inputs, set_value_hint_track, viewer params
  setters, video frame cache borrowed outlet, project copy_settings
- oakcodec: encoder desired pixel format, export format extension,
  encoding generate_matrix, custom range in encoding params POD
- oaktask: RenderTask orchestrates oakrender tickets (no Qt threads/
  watchers), PreCacheTask and ExportTask rewritten over the oaknode/
  oakrender/oakcodec C ABIs; frames cross from oakrender to oakcodec
  handles by pixel copy (different control blocks)
- the two-step texture/download render path collapses into single-step
  (tickets always yield frames); subtitle sidecar kept
- tests: 105 in build-oaktask (export/precache factory paths,
  construction, conform end-to-end); regressions all green
This commit is contained in:
2026-08-07 14:40:12 +08:00
parent 6ded1d2d63
commit 40a336276f
29 changed files with 2548 additions and 726 deletions
+48
View File
@@ -314,3 +314,51 @@ TEST(OakTaskConform, SubmittedConformProducesPcm)
}
} // namespace
// ---- render family factories ----------------------------------------------
TEST(OakTaskRenderFamily, FactoryErrorPaths)
{
EXPECT_EQ(oaktask_create_precache(nullptr, 0, nullptr), nullptr);
oakcodec_encoding_params params = {};
EXPECT_EQ(oaktask_create_export(nullptr, nullptr, &params), nullptr);
EXPECT_EQ(oaktask_create_export(nullptr, nullptr, nullptr), nullptr);
}
TEST(OakTaskRenderFamily, ExportTaskConstruction)
{
OakNodeProject *project = oaknode_project_init();
ASSERT_NE(project, nullptr);
ASSERT_EQ(oaknode_project_initialize(project), OAKNODE_OK);
// A sequence gives us a viewer with tracks; the factory should wrap
// the task successfully (no render manager needed for construction)
OakNodeSequence *sequence = oaknode_sequence_create();
ASSERT_NE(sequence, nullptr);
ASSERT_EQ(oaknode_project_add_node(project,
oaknode_sequence_as_node(sequence)),
OAKNODE_OK);
OakNodeColorManager *cm = oaknode_colormanager_init(project);
ASSERT_NE(cm, nullptr);
oakcodec_encoding_params params = {};
strncpy(params.filename, "/tmp/oaktask_export_test.mp4",
sizeof(params.filename) - 1);
params.video_enabled = 1;
OakTaskTask *t = oaktask_create_export(
oaknode_sequence_as_node(sequence), cm, &params);
ASSERT_NE(t, nullptr);
char title[128];
EXPECT_GT(oaktask_task_title(t, title, sizeof(title)), 0);
// Running needs a render manager; not available in this binary
oaktask_task_free(t);
oaknode_colormanager_free(cm);
oaknode_project_free(project);
EXPECT_EQ(oaktask_debug_alive_count(), 0);
}