pub use ffcine_assembly as assembly;
pub use ffcine_audio as audio;
pub use ffcine_core::{ColorSpace, Error, Lut, LutType, MediaInfo, Rational, Result};
pub use ffcine_core::{camera, color, geom, lut, probe};
pub use ffcine_delivery as delivery;
pub use ffcine_filters as filters;
pub use ffcine_filters::{Denoise, Grain, Spatial, Temporal};
pub use ffcine_hooks as hooks;
pub use ffcine_import as import;
pub use ffcine_ingest as ingest;
pub use ffcine_reframe as reframe;
pub use ffcine_render::{
Backend, Codec, ColorMapTuning, ColorOverride, Crop, Deband, Decode, DeliveryProfile, Device,
Dither, DitherMethod, EncoderSettings, GamutMapping, Grade, Hook, Image, Layer, LayerSource,
LutStage, Mask, Overlay, OverlayPart, ParamTrack, Pipeline, PixelFormat, RateControl, RunStats,
Scaler, Scaling, Size, Stage, ToneMapping, Warp,
};
pub use ffcine_render::{backend, encode, grade, layer, overlay, pipeline, profile, shaders};
pub use ffcine_stabilize as stabilize;
pub use ffcine_text as text;
pub use ffcine_timeline as timeline;
pub use ffcine_triage as triage;
#[cfg(feature = "nvof")]
pub fn stabilize_pipeline(
backend: &dyn Backend,
pipeline: &mut Pipeline,
params: &stabilize::StabilizeParams,
cache: bool,
) -> Result<(stabilize::Stabilization, bool)> {
let start = pipeline.start.as_secs_f64();
let (rate, frames) = match (pipeline.frame_rate, pipeline.frames) {
(Some(r), Some(n)) => (r, n),
(r, n) => {
let info = backend.probe(&pipeline.input)?;
let rate = r
.or_else(|| info.video().and_then(|(_, v)| v.frame_rate))
.ok_or_else(|| Error::Pipeline("stabilize: source has no frame rate".into()))?;
let n = n.unwrap_or_else(|| {
let left = info.duration.map_or(0.0, |d| d.as_secs_f64()) - start;
#[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
let n = (left.max(0.0) * rate.as_f64()).round() as u64;
n
});
(rate, n)
}
};
let range = stabilize::SourceRange {
start,
frames: usize::try_from(frames).unwrap_or(usize::MAX),
rate,
};
let detect = stabilize::DetectParams::default();
let (det, cached) = if cache {
stabilize::detect_cached(&pipeline.input, &range, &detect)?
} else {
(stabilize::detect(&pipeline.input, &range, &detect)?, false)
};
let st = stabilize::stabilize(&det, params);
let warp = Some(Warp {
transforms: st.transforms.clone(),
});
if let Some(Stage::Grade(g)) = pipeline.stages.first_mut() {
g.warp = warp;
} else {
pipeline.stages.insert(
0,
Stage::Grade(Grade {
warp,
..Grade::default()
}),
);
}
Ok((st, cached))
}