render: apply clip effect stacks in the montage path
Adding an effect to a clip did nothing: the sequence render is flattened into a montage (decode + composite), and MontageClip carried no effect data at all. - MontageClip gains an ordered effect stack (type id / enabled / effect input / parameter values); protocol v2 carries it as an additive wire field (older peers default to an empty stack). - renderops::video_montage fills the stack from the effect chain (the footage source node — the chain end without an effect input — is dropped; the montage decodes the footage itself). Export (oak-task) and the multicam single-track montage fill it too. - The worker applies the stack between decode and composite: built-in Opacity gets a CPU evaluator (C++ opacity.frag parity — whole vec4, alpha included, unity pass-through); everything else dispatches as an OFX plugin job through a new instance-factory slot (oak-plugin lazily creates + caches one instance per identifier per render process) with the montage's parameters injected. Disabled effects bypass (the C++ traverser pushes the effect input through). Unknown types warn once per type id and pass through — no silent no-ops. Not covered (explicitly): Transform/Crop and the other ~30 built-in effects have no CPU evaluator in oak-render (they pass through with a warning), keyframed parameter animation, audio effect chains, and the CLI's simplified montage. Acceptance: a real 50% Opacity on real media quarters the rendered pixels both in-process (renderops test) and through a real worker process over IPC + shared memory (procpool_integration test); disabling restores the plain render byte-for-byte.
This commit is contained in:
@@ -975,6 +975,7 @@ impl WorkerSession {
|
||||
out_time: Rational::new(c.out_num, c.out_den),
|
||||
media_in: Rational::new(c.media_in_num, c.media_in_den),
|
||||
gain: c.gain,
|
||||
effects: c.effects.iter().map(crate::ipc::montage_effect_from).collect(),
|
||||
})
|
||||
.collect();
|
||||
Ok(AudioTicketParams {
|
||||
@@ -1069,6 +1070,7 @@ impl WorkerSession {
|
||||
out_time: Rational::new(c.out_num, c.out_den),
|
||||
media_in: Rational::new(c.media_in_num, c.media_in_den),
|
||||
gain: c.gain,
|
||||
effects: c.effects.iter().map(crate::ipc::montage_effect_from).collect(),
|
||||
})
|
||||
.collect();
|
||||
VideoTicketParams {
|
||||
|
||||
Reference in New Issue
Block a user