rivet/encoder_worker/mod.rs
1//! Per-segment encoder worker: pop a chunk → encode K frames →
2//! emit one CMAF segment file → repeat.
3//!
4//! v2 multi-GPU model (2026-05-11): each worker owns one GPU lease
5//! and one encoder for its lifetime, but builds a fresh
6//! `CmafVideoMuxer` per claimed segment. The muxer is configured
7//! with the segment's index + base decode time so the on-disk
8//! filename + tfdt match what a single-encoder pipeline would
9//! produce. Helpers attaching mid-flight just start popping from
10//! the queue's current head; no decode-and-discard.
11//!
12//! Workers exit when `queue.pop()` returns `None` (pump closed +
13//! queue drained). The returned `WorkerOutput` lists every segment
14//! the worker wrote so the orchestrator can merge contributions
15//! into the per-rung manifest.
16
17mod invariant;
18mod config;
19mod cmaf_worker;
20mod chunk_worker;
21#[cfg(test)]
22mod tests;
23
24pub use invariant::{
25 Av1Invariant, H26xInvariant, InvariantCheck, RungCodecInvariant,
26 validate_or_set_rung_invariant,
27};
28pub use config::{EncoderWorkerConfig, WorkerOutput};
29pub use cmaf_worker::run_encoder_worker_blocking;
30pub use chunk_worker::{ChunkPackets, run_chunk_encoder_worker_blocking};
31
32use codec::encode::EncoderConfig;
33
34/// Build the per-rung `EncoderConfig` from the resolved output format + quality
35/// knobs. Shared by the CMAF and packet workers.
36fn build_enc_config(cfg: &EncoderWorkerConfig) -> EncoderConfig {
37 EncoderConfig {
38 codec: cfg.codec,
39 width: cfg.width,
40 height: cfg.height,
41 frame_rate: cfg.frame_rate,
42 quality: cfg.quality,
43 speed_preset: cfg.speed_preset,
44 keyframe_interval: cfg.keyframe_interval,
45 threads: cfg.threads,
46 pixel_format: cfg.output_pixel_format,
47 color_metadata: cfg.output_color_metadata,
48 gpu_index: cfg.gpu_index,
49 gpu_vendor: cfg.gpu_vendor,
50 target: cfg.target,
51 tier: cfg.tier,
52 constant_qp: cfg.constant_qp,
53 ..EncoderConfig::default()
54 }
55}