diff --git a/src/render/ffmpeg.rs b/src/render/ffmpeg.rs index 614ad19..8cc8a09 100644 --- a/src/render/ffmpeg.rs +++ b/src/render/ffmpeg.rs @@ -1,6 +1,6 @@ use super::{cmd, filter::Filter}; use crate::{ - render::filter::channel, + render::filter::{channel, next_tmp}, time::{format_time, Time}, Resolution }; @@ -107,9 +107,17 @@ enum FfmpegFilter { Rescale(Resolution) } +pub(crate) struct FfmpegOverlay { + pub(crate) overlay_input: Cow<'static, str>, + pub(crate) x: Cow<'static, str>, + pub(crate) y: Cow<'static, str>, + pub(crate) alpha: Rational +} + pub(crate) struct Ffmpeg { inputs: Vec, filter: FfmpegFilter, + overlay: Option, video_bitrate: Option<&'static str>, output: FfmpegOutput, @@ -121,6 +129,7 @@ impl Ffmpeg { Self { inputs: Vec::new(), filter: FfmpegFilter::None, + overlay: None, video_bitrate: None, output, @@ -182,6 +191,11 @@ impl Ffmpeg { self } + pub fn enable_overlay(&mut self, overlay: FfmpegOverlay) -> &mut Self { + self.overlay = Some(overlay); + self + } + pub fn set_video_bitrate(&mut self, bitrate: &'static str) -> &mut Self { self.video_bitrate = Some(bitrate); self @@ -229,10 +243,52 @@ impl Ffmpeg { for filter in filters { filter.append_to_complex_filter(&mut complex, &mut self.filter_idx); } - if vaapi { - write!(complex, "{}format=nv12,hwupload[v]", channel('v', &output)); + if let Some(FfmpegOverlay { + overlay_input, + x, + y, + alpha + }) = self.overlay + { + let tmp = next_tmp(&mut self.filter_idx); + if vaapi { + writeln!( + complex, + "{}format=nv12,hwupload{tmp};", + channel('v', &output) + ); + let tmp2 = next_tmp(&mut self.filter_idx); + writeln!( + complex, + "{}format=nv12,hwupload{tmp2};", + channel('v', &overlay_input) + ); + writeln!( + complex, + "{tmp}{tmp2}overlay_vaapi=x={x}:y={y}:alpha={alpha}[v]" + ); + } else { + writeln!( + complex, + "{}format=yuva444p,colorchannelmixer=aa={alpha}{tmp};", + channel('v', &output) + ); + writeln!( + complex, + "{tmp}{}overlay=x={x}:y={y}[v]", + channel('v', &overlay_input) + ); + } } else { - write!(complex, "{}null[v]", channel('v', &output)); + if vaapi { + writeln!( + complex, + "{}format=nv12,hwupload[v]", + channel('v', &output) + ); + } else { + writeln!(complex, "{}null[v]", channel('v', &output)); + } } cmd.arg("-filter_complex").arg(complex); cmd.arg("-map").arg("[v]"); diff --git a/src/render/filter.rs b/src/render/filter.rs index 6a76ccc..fc0c720 100644 --- a/src/render/filter.rs +++ b/src/render/filter.rs @@ -234,7 +234,7 @@ pub(super) fn channel(channel: char, id: &str) -> String { } } -fn next_tmp(filter_idx: &mut usize) -> String { +pub(super) fn next_tmp(filter_idx: &mut usize) -> String { *filter_idx += 1; format!("[tmp{filter_idx}]") } diff --git a/src/render/mod.rs b/src/render/mod.rs index 3b9257c..75d440c 100644 --- a/src/render/mod.rs +++ b/src/render/mod.rs @@ -3,7 +3,10 @@ pub mod ffmpeg; mod filter; -use self::{ffmpeg::FfmpegOutput, filter::Filter}; +use self::{ + ffmpeg::{FfmpegOutput, FfmpegOverlay}, + filter::Filter +}; use crate::{ iotro::{intro, outro}, render::ffmpeg::{Ffmpeg, FfmpegInput}, @@ -426,23 +429,15 @@ impl<'a> Renderer<'a> { }); // overlay the logo - let logoalpha = "logoalpha"; - ffmpeg.add_filter(Filter::Alpha { - input: logo.into(), - alpha: 0.5, - output: logoalpha.into() - }); - let overlay = "overlay"; - ffmpeg.add_filter(Filter::Overlay { - video_input: concat.into(), - overlay_input: logoalpha.into(), + ffmpeg.enable_overlay(FfmpegOverlay { + overlay_input: logo.into(), x: "main_w-overlay_w-130".into(), y: "main_h-overlay_h-65".into(), - output: overlay.into() + alpha: Rational::new(1, 2) }); // we're done :) - ffmpeg.set_filter_output(overlay); + ffmpeg.set_filter_output(concat); ffmpeg.run()?; Ok(output)