move function prepare_output_cmd, add test video_audio_output

This commit is contained in:
jb-alvarado 2022-10-12 17:57:34 +02:00
parent 87c508be54
commit b7a3e356d1
6 changed files with 215 additions and 145 deletions

View File

@ -28,10 +28,11 @@ use std::{
use simplelog::*; use simplelog::*;
use crate::input::{ingest::log_line, source_generator}; use crate::input::{ingest::log_line, source_generator};
use crate::utils::prepare_output_cmd;
use ffplayout_lib::filter::filter_chains; use ffplayout_lib::filter::filter_chains;
use ffplayout_lib::utils::{ use ffplayout_lib::utils::{
prepare_output_cmd, sec_to_time, stderr_reader, test_tcp_port, Encoder, Ingest, Media, sec_to_time, stderr_reader, test_tcp_port, Encoder, Ingest, Media, PlayerControl,
PlayerControl, PlayoutConfig, PlayoutStatus, ProcessControl, PlayoutConfig, PlayoutStatus, ProcessControl,
}; };
use ffplayout_lib::vec_strings; use ffplayout_lib::vec_strings;

View File

@ -5,8 +5,9 @@ use std::{
use simplelog::*; use simplelog::*;
use crate::utils::prepare_output_cmd;
use ffplayout_lib::filter::v_drawtext; use ffplayout_lib::filter::v_drawtext;
use ffplayout_lib::utils::{prepare_output_cmd, PlayoutConfig}; use ffplayout_lib::utils::PlayoutConfig;
use ffplayout_lib::vec_strings; use ffplayout_lib::vec_strings;
/// Streaming Output /// Streaming Output

View File

@ -6,8 +6,12 @@ use std::{
pub mod arg_parse; pub mod arg_parse;
pub use arg_parse::Args; pub use arg_parse::Args;
use ffplayout_lib::utils::{time_to_sec, PlayoutConfig}; use ffplayout_lib::{
utils::{time_to_sec, PlayoutConfig},
vec_strings,
};
/// Read command line arguments, and override the config with them.
pub fn get_config(args: Args) -> PlayoutConfig { pub fn get_config(args: Args) -> PlayoutConfig {
let cfg_path = match args.channel { let cfg_path = match args.channel {
Some(c) => { Some(c) => {
@ -80,4 +84,79 @@ pub fn get_config(args: Args) -> PlayoutConfig {
config config
} }
// Read command line arguments, and override the config with them.
/// Prepare output parameters
///
/// seek for multiple outputs and add mapping for it
pub fn prepare_output_cmd(
prefix: Vec<String>,
mut filter: Vec<String>,
params: Vec<String>,
mode: &str,
) -> Vec<String> {
let params_len = params.len();
let mut output_params = params.clone();
let mut output_a_map = "[a_out1]".to_string();
let mut output_v_map = "[v_out1]".to_string();
let mut output_count = 1;
let mut cmd = prefix;
if !filter.is_empty() {
output_params.clear();
for (i, p) in params.iter().enumerate() {
let mut param = p.clone();
param = param.replace("[0:v]", "[vout0]");
param = param.replace("[0:a]", "[aout0]");
if param != "-filter_complex" {
output_params.push(param.clone());
}
if i > 0
&& !param.starts_with('-')
&& !params[i - 1].starts_with('-')
&& i < params_len - 1
{
output_count += 1;
let mut a_map = "0:a".to_string();
let v_map = format!("[v_out{output_count}]");
output_v_map.push_str(&v_map);
if mode == "hls" {
a_map = format!("[a_out{output_count}]");
}
output_a_map.push_str(&a_map);
let mut map = vec_strings!["-map", v_map, "-map", a_map];
output_params.append(&mut map);
}
}
if output_count > 1 && mode == "hls" {
filter[1].push_str(&format!(";[vout0]split={output_count}{output_v_map}"));
filter[1].push_str(&format!(";[aout0]asplit={output_count}{output_a_map}"));
filter.drain(2..);
cmd.append(&mut filter);
cmd.append(&mut vec_strings!["-map", "[v_out1]", "-map", "[a_out1]"]);
} else if output_count == 1 && mode == "hls" && output_params[0].contains("split") {
let out_filter = output_params.remove(0);
filter[1].push_str(&format!(";{out_filter}"));
filter.drain(2..);
cmd.append(&mut filter);
} else if output_count > 1 && mode == "stream" {
filter[1].push_str(&format!(",split={output_count}{output_v_map}"));
cmd.append(&mut filter);
cmd.append(&mut vec_strings!["-map", "[v_out1]", "-map", "0:a"]);
} else {
cmd.append(&mut filter);
}
}
cmd.append(&mut output_params);
cmd
}

View File

@ -570,82 +570,6 @@ pub fn gen_dummy(config: &PlayoutConfig, duration: f64) -> (String, Vec<String>)
// count // count
// } // }
/// Prepare output parameters
///
/// seek for multiple outputs and add mapping for it
pub fn prepare_output_cmd(
prefix: Vec<String>,
mut filter: Vec<String>,
params: Vec<String>,
mode: &str,
) -> Vec<String> {
let params_len = params.len();
let mut output_params = params.clone();
let mut output_a_map = "[a_out1]".to_string();
let mut output_v_map = "[v_out1]".to_string();
let mut output_count = 1;
let mut cmd = prefix;
if !filter.is_empty() {
output_params.clear();
for (i, p) in params.iter().enumerate() {
let mut param = p.clone();
param = param.replace("[0:v]", "[vout0]");
param = param.replace("[0:a]", "[aout0]");
if param != "-filter_complex" {
output_params.push(param.clone());
}
if i > 0
&& !param.starts_with('-')
&& !params[i - 1].starts_with('-')
&& i < params_len - 1
{
output_count += 1;
let mut a_map = "0:a".to_string();
let v_map = format!("[v_out{output_count}]");
output_v_map.push_str(&v_map);
if mode == "hls" {
a_map = format!("[a_out{output_count}]");
}
output_a_map.push_str(&a_map);
let mut map = vec_strings!["-map", v_map, "-map", a_map];
output_params.append(&mut map);
}
}
if output_count > 1 && mode == "hls" {
filter[1].push_str(&format!(";[vout0]split={output_count}{output_v_map}"));
filter[1].push_str(&format!(";[aout0]asplit={output_count}{output_a_map}"));
filter.drain(2..);
cmd.append(&mut filter);
cmd.append(&mut vec_strings!["-map", "[v_out1]", "-map", "[a_out1]"]);
} else if output_count == 1 && mode == "hls" && output_params[0].contains("split") {
let out_filter = output_params.remove(0);
filter[1].push_str(&format!(";{out_filter}"));
filter.drain(2..);
cmd.append(&mut filter);
} else if output_count > 1 && mode == "stream" {
filter[1].push_str(&format!(",split={output_count}{output_v_map}"));
cmd.append(&mut filter);
cmd.append(&mut vec_strings!["-map", "[v_out1]", "-map", "0:a"]);
} else {
cmd.append(&mut filter);
}
}
cmd.append(&mut output_params);
cmd
}
pub fn is_remote(path: &str) -> bool { pub fn is_remote(path: &str) -> bool {
Regex::new(r"^https?://.*").unwrap().is_match(path) Regex::new(r"^https?://.*").unwrap().is_match(path)
} }

View File

@ -1,4 +1,4 @@
use ffplayout::input::playlist::gen_source; use ffplayout::{input::playlist::gen_source, utils::prepare_output_cmd};
use ffplayout_lib::{ use ffplayout_lib::{
utils::{Media, PlayoutConfig}, utils::{Media, PlayoutConfig},
vec_strings, vec_strings,
@ -80,3 +80,131 @@ fn dual_audio_input() {
assert_eq!(media.cmd, Some(vec_strings!["-i", "assets/dual_audio.mp4"])); assert_eq!(media.cmd, Some(vec_strings!["-i", "assets/dual_audio.mp4"]));
assert_eq!(media.filter, test_filter_cmd); assert_eq!(media.filter, test_filter_cmd);
} }
#[test]
fn test_prepare_output_cmd() {
let enc_prefix = vec_strings![
"-hide_banner",
"-nostats",
"-v",
"level+error",
"-re",
"-i",
"pipe:0"
];
let filter = vec_strings![
"-filter_complex",
"[0:v]null,zmq=b=tcp\\\\://'127.0.0.1\\:5555',drawtext=text=''"
];
let params = vec_strings![
"-c:v",
"libx264",
"-flags",
"+global_header",
"-f",
"flv",
"rtmp://localhost/live/stream",
"-s",
"512x288",
"-c:v",
"libx264",
"-flags",
"+global_header",
"-f",
"flv",
"rtmp://localhost:1937/live/stream"
];
let mut t1_params = enc_prefix.clone();
t1_params.append(&mut params.clone());
let cmd_two_outs =
prepare_output_cmd(enc_prefix.clone(), vec_strings![], params.clone(), "stream");
assert_eq!(cmd_two_outs, t1_params);
let mut test_cmd = enc_prefix.clone();
let mut test_params = params.clone();
let mut t2_filter = filter.clone();
t2_filter[1].push_str(",split=2[v_out1][v_out2]");
test_cmd.append(&mut t2_filter);
test_params.insert(0, "-map".to_string());
test_params.insert(1, "[v_out1]".to_string());
test_params.insert(2, "-map".to_string());
test_params.insert(3, "0:a".to_string());
test_params.insert(11, "-map".to_string());
test_params.insert(12, "[v_out2]".to_string());
test_params.insert(13, "-map".to_string());
test_params.insert(14, "0:a".to_string());
test_cmd.append(&mut test_params);
let cmd_two_outs_with_filter = prepare_output_cmd(enc_prefix, filter, params, "stream");
assert_eq!(cmd_two_outs_with_filter, test_cmd);
}
#[test]
fn video_audio_output() {
let mut config = PlayoutConfig::new(Some("../assets/ffplayout.yml".to_string()));
config.out.mode = "stream".to_string();
config.processing.add_logo = false;
config.out.output_cmd = Some(vec_strings![
"-c:v",
"libx264",
"-c:a",
"aac",
"-ar",
"44100",
"-b:a",
"128k",
"-flags",
"+global_header",
"-f",
"flv",
"rtmp://localhost/live/stream"
]);
let mut enc_cmd = vec![];
let enc_filter = vec![];
let mut output_cmd = config.out.output_cmd.as_ref().unwrap().clone();
let enc_prefix = vec_strings![
"-hide_banner",
"-nostats",
"-v",
"level+error",
"-re",
"-i",
"pipe:0"
];
enc_cmd.append(&mut output_cmd);
let enc_cmd = prepare_output_cmd(enc_prefix, enc_filter, enc_cmd, &config.out.mode);
let test_cmd = vec_strings![
"-hide_banner",
"-nostats",
"-v",
"level+error",
"-re",
"-i",
"pipe:0",
"-c:v",
"libx264",
"-c:a",
"aac",
"-ar",
"44100",
"-b:a",
"128k",
"-flags",
"+global_header",
"-f",
"flv",
"rtmp://localhost/live/stream"
];
assert_eq!(enc_cmd, test_cmd);
}

View File

@ -50,66 +50,3 @@ fn test_delta() {
assert!(delta < 2.0); assert!(delta < 2.0);
} }
#[test]
fn test_prepare_output_cmd() {
let enc_prefix = vec_strings![
"-hide_banner",
"-nostats",
"-v",
"level+error",
"-re",
"-i",
"pipe:0"
];
let filter = vec_strings![
"-filter_complex",
"[0:v]null,zmq=b=tcp\\\\://'127.0.0.1\\:5555',drawtext=text=''"
];
let params = vec_strings![
"-c:v",
"libx264",
"-flags",
"+global_header",
"-f",
"flv",
"rtmp://localhost/live/stream",
"-s",
"512x288",
"-c:v",
"libx264",
"-flags",
"+global_header",
"-f",
"flv",
"rtmp://localhost:1937/live/stream"
];
let mut t1_params = enc_prefix.clone();
t1_params.append(&mut params.clone());
let cmd_two_outs =
prepare_output_cmd(enc_prefix.clone(), vec_strings![], params.clone(), "stream");
assert_eq!(cmd_two_outs, t1_params);
let mut test_cmd = enc_prefix.clone();
let mut test_params = params.clone();
let mut t2_filter = filter.clone();
t2_filter[1].push_str(",split=2[v_out1][v_out2]");
test_cmd.append(&mut t2_filter);
test_params.insert(0, "-map".to_string());
test_params.insert(1, "[v_out1]".to_string());
test_params.insert(2, "-map".to_string());
test_params.insert(3, "0:a".to_string());
test_params.insert(11, "-map".to_string());
test_params.insert(12, "[v_out2]".to_string());
test_params.insert(13, "-map".to_string());
test_params.insert(14, "0:a".to_string());
test_cmd.append(&mut test_params);
let cmd_two_outs_with_filter = prepare_output_cmd(enc_prefix, filter, params, "stream");
assert_eq!(cmd_two_outs_with_filter, test_cmd);
}