From 4cd6b885ffe017cd4ea1b6a7c547d98fe2c6d119 Mon Sep 17 00:00:00 2001 From: jb-alvarado Date: Mon, 9 May 2022 15:16:40 +0200 Subject: [PATCH] remove str/string conversions in vectors, log ingest url with match --- src/input/ingest.rs | 19 ++++++++----------- src/input/playlist.rs | 2 +- src/output/desktop.rs | 5 +++-- src/output/hls.rs | 31 ++++++++++++++---------------- src/output/mod.rs | 14 +++++++------- src/output/stream.rs | 25 ++++++++++++------------ src/utils/config.rs | 44 ++++++++++++++++++++++--------------------- src/utils/logging.rs | 6 +++--- src/utils/mod.rs | 7 +++++++ 9 files changed, 79 insertions(+), 74 deletions(-) diff --git a/src/input/ingest.rs b/src/input/ingest.rs index 05961723..225b5a35 100644 --- a/src/input/ingest.rs +++ b/src/input/ingest.rs @@ -10,6 +10,7 @@ use simplelog::*; use crate::filter::ingest_filter::filter_cmd; use crate::utils::{stderr_reader, GlobalConfig, Ingest, ProcessControl}; +use crate::vec_strings; /// ffmpeg Ingest Server /// @@ -21,22 +22,18 @@ pub fn ingest_server( ) -> Result<(), Error> { let config = GlobalConfig::global(); let mut buffer: [u8; 65088] = [0; 65088]; - let filter_list = filter_cmd(); - - let mut server_cmd = vec!["-hide_banner", "-nostats", "-v", log_format.as_str()]; + let mut server_cmd = vec_strings!["-hide_banner", "-nostats", "-v", log_format]; let stream_input = config.ingest.input_cmd.clone().unwrap(); - let stream_settings = config.processing.settings.clone().unwrap(); - server_cmd.append(&mut stream_input.iter().map(String::as_str).collect()); - server_cmd.append(&mut filter_list.iter().map(String::as_str).collect()); - server_cmd.append(&mut stream_settings.iter().map(String::as_str).collect()); + server_cmd.append(&mut stream_input.clone()); + server_cmd.append(&mut filter_cmd()); + server_cmd.append(&mut config.processing.settings.clone().unwrap()); let mut is_running; - info!( - "Start ingest server, listening on: {}", - stream_input.last().unwrap() - ); + if let Some(url) = stream_input.iter().find(|s| s.contains("://")) { + info!("Start ingest server, listening on: {url}",); + }; debug!( "Server CMD: \"ffmpeg {}\"", diff --git a/src/input/playlist.rs b/src/input/playlist.rs index 36a2dd61..3b1d1f4c 100644 --- a/src/input/playlist.rs +++ b/src/input/playlist.rs @@ -243,7 +243,6 @@ impl Iterator for CurrentProgram { fn next(&mut self) -> Option { if self.playout_stat.list_init.load(Ordering::SeqCst) { - debug!("Playlist init"); self.check_update(true); if self.json_path.is_some() { @@ -451,6 +450,7 @@ fn gen_source(mut node: Media) -> Media { /// Handle init clip, but this clip can be the last one in playlist, /// this we have to figure out and calculate the right length. fn handle_list_init(mut node: Media) -> Media { + debug!("Playlist init"); let (_, total_delta) = get_delta(&node.begin.unwrap()); let mut out = node.out; diff --git a/src/output/desktop.rs b/src/output/desktop.rs index a94fa2f5..51dbbf56 100644 --- a/src/output/desktop.rs +++ b/src/output/desktop.rs @@ -4,6 +4,7 @@ use simplelog::*; use crate::filter::v_drawtext; use crate::utils::{GlobalConfig, Media}; +use crate::vec_strings; /// Desktop Output /// @@ -13,7 +14,7 @@ pub fn output(log_format: &str) -> process::Child { let mut enc_filter: Vec = vec![]; - let mut enc_cmd = vec!["-hide_banner", "-nostats", "-v", log_format, "-i", "pipe:0"]; + let mut enc_cmd = vec_strings!["-hide_banner", "-nostats", "-v", log_format, "-i", "pipe:0"]; if config.text.add_text && !config.text.over_pre { info!( @@ -26,7 +27,7 @@ pub fn output(log_format: &str) -> process::Child { enc_filter = vec!["-vf".to_string(), filter]; } - enc_cmd.append(&mut enc_filter.iter().map(String::as_str).collect()); + enc_cmd.append(&mut enc_filter); debug!( "Encoder CMD: \"ffplay {}\"", diff --git a/src/output/hls.rs b/src/output/hls.rs index deabfbf2..166fa407 100644 --- a/src/output/hls.rs +++ b/src/output/hls.rs @@ -33,6 +33,7 @@ use crate::utils::{ sec_to_time, stderr_reader, Decoder, GlobalConfig, Ingest, PlayerControl, PlayoutStatus, ProcessControl, }; +use crate::vec_strings; fn format_line(line: String, level: &str) -> String { line.replace(&format!("[{level: >5}] "), "") @@ -44,23 +45,20 @@ fn ingest_to_hls_server( mut proc_control: ProcessControl, ) -> Result<(), Error> { let config = GlobalConfig::global(); - let dec_settings = config.out.clone().output_cmd.unwrap(); let playlist_init = playout_stat.list_init; - let filter_list = filter_cmd(); - let mut server_cmd = vec!["-hide_banner", "-nostats", "-v", "level+info"]; + let mut server_cmd = vec_strings!["-hide_banner", "-nostats", "-v", "level+info"]; let stream_input = config.ingest.input_cmd.clone().unwrap(); - server_cmd.append(&mut stream_input.iter().map(String::as_str).collect()); - server_cmd.append(&mut filter_list.iter().map(String::as_str).collect()); - server_cmd.append(&mut dec_settings.iter().map(String::as_str).collect()); + server_cmd.append(&mut stream_input.clone()); + server_cmd.append(&mut filter_cmd()); + server_cmd.append(&mut config.out.clone().output_cmd.unwrap()); let mut is_running; - info!( - "Start ingest server, listening on: {}", - stream_input.last().unwrap() - ); + if let Some(url) = stream_input.iter().find(|s| s.contains("://")) { + info!("Start ingest server, listening on: {url}",); + }; debug!( "Server CMD: \"ffmpeg {}\"", @@ -137,7 +135,6 @@ pub fn write_hls( mut proc_control: ProcessControl, ) { let config = GlobalConfig::global(); - let dec_settings = config.out.clone().output_cmd.unwrap(); let ff_log_format = format!("level+{}", config.logging.ffmpeg_level.to_lowercase()); let play_stat = playout_stat.clone(); let proc_control_c = proc_control.clone(); @@ -158,7 +155,7 @@ pub fn write_hls( for node in get_source { *play_control.current_media.lock().unwrap() = Some(node.clone()); - let cmd = match node.cmd { + let mut cmd = match node.cmd { Some(cmd) => cmd, None => break, }; @@ -173,15 +170,15 @@ pub fn write_hls( node.source ); - let filter = node.filter.unwrap(); - let mut dec_cmd = vec!["-hide_banner", "-nostats", "-v", ff_log_format.as_str()]; - dec_cmd.append(&mut cmd.iter().map(String::as_str).collect()); + let mut filter = node.filter.unwrap(); + let mut dec_cmd = vec_strings!["-hide_banner", "-nostats", "-v", &ff_log_format]; + dec_cmd.append(&mut cmd); if filter.len() > 1 { - dec_cmd.append(&mut filter.iter().map(String::as_str).collect()); + dec_cmd.append(&mut filter); } - dec_cmd.append(&mut dec_settings.iter().map(String::as_str).collect()); + dec_cmd.append(&mut config.out.clone().output_cmd.unwrap()); debug!( "HLS writer CMD: \"ffmpeg {}\"", diff --git a/src/output/mod.rs b/src/output/mod.rs index fd2ece80..c93d4446 100644 --- a/src/output/mod.rs +++ b/src/output/mod.rs @@ -20,6 +20,7 @@ use crate::utils::{ sec_to_time, stderr_reader, Decoder, Encoder, GlobalConfig, PlayerControl, PlayoutStatus, ProcessControl, }; +use crate::vec_strings; /// Player /// @@ -36,7 +37,6 @@ pub fn player( mut proc_control: ProcessControl, ) { let config = GlobalConfig::global(); - let dec_settings = config.processing.clone().settings.unwrap(); let ff_log_format = format!("level+{}", config.logging.ffmpeg_level.to_lowercase()); let mut buffer = [0; 65088]; let mut live_on = false; @@ -80,7 +80,7 @@ pub fn player( 'source_iter: for node in get_source { *play_control.current_media.lock().unwrap() = Some(node.clone()); - let cmd = match node.cmd { + let mut cmd = match node.cmd { Some(cmd) => cmd, None => break, }; @@ -95,15 +95,15 @@ pub fn player( node.source ); - let filter = node.filter.unwrap(); - let mut dec_cmd = vec!["-hide_banner", "-nostats", "-v", ff_log_format.as_str()]; - dec_cmd.append(&mut cmd.iter().map(String::as_str).collect()); + let mut filter = node.filter.unwrap(); + let mut dec_cmd = vec_strings!["-hide_banner", "-nostats", "-v", &ff_log_format]; + dec_cmd.append(&mut cmd); if filter.len() > 1 { - dec_cmd.append(&mut filter.iter().map(String::as_str).collect()); + dec_cmd.append(&mut filter); } - dec_cmd.append(&mut dec_settings.iter().map(String::as_str).collect()); + dec_cmd.append(&mut config.processing.clone().settings.unwrap()); debug!( "Decoder CMD: \"ffmpeg {}\"", diff --git a/src/output/stream.rs b/src/output/stream.rs index 9c203a09..32f86c81 100644 --- a/src/output/stream.rs +++ b/src/output/stream.rs @@ -7,6 +7,7 @@ use simplelog::*; use crate::filter::v_drawtext; use crate::utils::{GlobalConfig, Media}; +use crate::vec_strings; /// Streaming Output /// @@ -14,18 +15,18 @@ use crate::utils::{GlobalConfig, Media}; pub fn output(log_format: &str) -> process::Child { let config = GlobalConfig::global(); let mut enc_filter: Vec = vec![]; - let mut preview: Vec<&str> = vec![]; - let preview_cmd = config.out.preview_cmd.as_ref().unwrap().clone(); - let output_cmd = config.out.output_cmd.as_ref().unwrap().clone(); + let mut preview: Vec = vec_strings![]; + let mut preview_cmd = config.out.preview_cmd.as_ref().unwrap().clone(); + let mut output_cmd = config.out.output_cmd.as_ref().unwrap().clone(); - let mut enc_cmd = vec![ + let mut enc_cmd = vec_strings![ "-hide_banner", "-nostats", "-v", log_format, "-re", "-i", - "pipe:0", + "pipe:0" ]; if config.text.add_text && !config.text.over_pre { @@ -34,25 +35,25 @@ pub fn output(log_format: &str) -> process::Child { config.text.bind_address ); - let mut filter: String = "[0:v]null,".to_string(); + let mut filter = "[0:v]null,".to_string(); filter.push_str(v_drawtext::filter_node(&mut Media::new(0, String::new(), false)).as_str()); if config.out.preview { filter.push_str(",split=2[v_out1][v_out2]"); - preview = vec!["-map", "[v_out1]", "-map", "0:a"]; - preview.append(&mut preview_cmd.iter().map(String::as_str).collect()); - preview.append(&mut vec!["-map", "[v_out2]", "-map", "0:a"]); + preview = vec_strings!["-map", "[v_out1]", "-map", "0:a"]; + preview.append(&mut preview_cmd); + preview.append(&mut vec_strings!["-map", "[v_out2]", "-map", "0:a"]); } enc_filter = vec!["-filter_complex".to_string(), filter]; } else if config.out.preview { - preview = preview_cmd.iter().map(String::as_str).collect() + preview = preview_cmd } - enc_cmd.append(&mut enc_filter.iter().map(String::as_str).collect()); + enc_cmd.append(&mut enc_filter); enc_cmd.append(&mut preview); - enc_cmd.append(&mut output_cmd.iter().map(String::as_str).collect()); + enc_cmd.append(&mut output_cmd); debug!( "Encoder CMD: \"ffmpeg {}\"", diff --git a/src/utils/config.rs b/src/utils/config.rs index 0c753f44..ceac3a07 100644 --- a/src/utils/config.rs +++ b/src/utils/config.rs @@ -11,6 +11,7 @@ use serde_yaml::{self}; use shlex::split; use crate::utils::{get_args, time_to_sec}; +use crate::vec_strings; /// Global Config /// @@ -167,8 +168,15 @@ impl GlobalConfig { .join("ffplayout_status.json") .display() .to_string(); - let fps = config.processing.fps.to_string(); - let bitrate = config.processing.width * config.processing.height / 10; + let bitrate = format!( + "{}k", + config.processing.width * config.processing.height / 10 + ); + let buf_size = format!( + "{}k", + (config.processing.width * config.processing.height / 10) / 2 + ); + config.playlist.start_sec = Some(time_to_sec(&config.playlist.day_start)); if config.playlist.length.contains(':') { @@ -178,35 +186,29 @@ impl GlobalConfig { } // We set the decoder settings here, so we only define them ones. - let mut settings: Vec = vec![ + let mut settings = vec_strings![ "-pix_fmt", "yuv420p", "-r", - &fps, + &config.processing.fps.to_string(), "-c:v", "mpeg2video", "-g", "1", "-b:v", - format!("{bitrate}k").as_str(), + &bitrate, "-minrate", - format!("{bitrate}k").as_str(), + &bitrate, "-maxrate", - format!("{bitrate}k").as_str(), + &bitrate, "-bufsize", - format!("{}k", bitrate / 2).as_str(), - ] - .iter() - .map(|&s| s.into()) - .collect(); + &buf_size + ]; settings.append(&mut pre_audio_codec(config.processing.add_loudnorm)); - settings.append( - &mut vec!["-ar", "48000", "-ac", "2", "-f", "mpegts", "-"] - .iter() - .map(|&s| s.into()) - .collect(), - ); + settings.append(&mut vec_strings![ + "-ar", "48000", "-ac", "2", "-f", "mpegts", "-" + ]); config.processing.settings = Some(settings); @@ -277,13 +279,13 @@ static INSTANCE: OnceCell = OnceCell::new(); /// s302m has higher quality, but is experimental /// and works not well together with the loudnorm filter. fn pre_audio_codec(add_loudnorm: bool) -> Vec { - let mut codec = vec!["-c:a", "s302m", "-strict", "-2"]; + let mut codec = vec_strings!["-c:a", "s302m", "-strict", "-2"]; if add_loudnorm { - codec = vec!["-c:a", "mp2", "-b:a", "384k"]; + codec = vec_strings!["-c:a", "mp2", "-b:a", "384k"]; } - codec.iter().map(|&s| s.into()).collect() + codec } pub fn init_config() { diff --git a/src/utils/logging.rs b/src/utils/logging.rs index e60e1005..102d6d45 100644 --- a/src/utils/logging.rs +++ b/src/utils/logging.rs @@ -131,7 +131,7 @@ impl SharedLogger for LogMailer { /// /// ToDo: maybe in next version from simplelog this is not necessary anymore. fn clean_string(text: &str) -> String { - let regex: Regex = Regex::new(r"\x1b\[[0-9;]*[mGKF]").unwrap(); + let regex = Regex::new(r"\x1b\[[0-9;]*[mGKF]").unwrap(); regex.replace_all(text, "").to_string() } @@ -169,7 +169,7 @@ pub fn init_logging() -> Vec> { let file_config = log_config .clone() .set_time_format_custom(format_description!( - "[[year]-[month]-[day] [hour]:[minute]:[second].[subsecond]]" + "[[year]-[month]-[day] [hour]:[minute]:[second].[subsecond digits:5]]" )) .build(); let mut log_path = "logs/ffplayout.log".to_string(); @@ -207,7 +207,7 @@ pub fn init_logging() -> Vec> { .set_level_color(Level::Warn, Some(Color::Ansi256(208))) .set_level_color(Level::Error, Some(Color::Ansi256(9))) .set_time_format_custom(format_description!( - "\x1b[[30;1m[[[year]-[month]-[day] [hour]:[minute]:[second].[subsecond digits:4]]\x1b[[0m" + "\x1b[[30;1m[[[year]-[month]-[day] [hour]:[minute]:[second].[subsecond digits:5]]\x1b[[0m" )) .build(); diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 23e6941d..a4022286 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -35,6 +35,13 @@ pub use logging::init_logging; use crate::filter::filter_chains; +#[macro_export] +macro_rules! vec_strings { + ($($str:expr),*) => ({ + vec![$(String::from($str),)*] as Vec + }); +} + /// Video clip struct to hold some important states and comments for current media. #[derive(Debug, Serialize, Deserialize, Clone)] pub struct Media {