Merge pull request #520 from jb-alvarado/master

support looping clips, fix #507
This commit is contained in:
jb-alvarado 2024-02-06 11:24:32 +01:00 committed by GitHub
commit 577b5fc045
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 68 additions and 23 deletions

8
Cargo.lock generated
View File

@ -1210,7 +1210,7 @@ checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
[[package]]
name = "ffplayout"
version = "0.20.4-beta1"
version = "0.20.4-beta2"
dependencies = [
"chrono",
"clap",
@ -1232,7 +1232,7 @@ dependencies = [
[[package]]
name = "ffplayout-api"
version = "0.20.4-beta1"
version = "0.20.4-beta2"
dependencies = [
"actix-files",
"actix-multipart",
@ -1271,7 +1271,7 @@ dependencies = [
[[package]]
name = "ffplayout-lib"
version = "0.20.4-beta1"
version = "0.20.4-beta2"
dependencies = [
"chrono",
"crossbeam-channel",
@ -3436,7 +3436,7 @@ dependencies = [
[[package]]
name = "tests"
version = "0.20.4-beta1"
version = "0.20.4-beta2"
dependencies = [
"chrono",
"crossbeam-channel",

View File

@ -4,7 +4,7 @@ default-members = ["ffplayout-api", "ffplayout-engine", "tests"]
resolver = "2"
[workspace.package]
version = "0.20.4-beta1"
version = "0.20.4-beta2"
license = "GPL-3.0"
repository = "https://github.com/ffplayout/ffplayout"
authors = ["Jonathan Baecker <jonbae77@gmail.com>"]

View File

@ -59,7 +59,8 @@ impl CurrentProgram {
}
}
// Check if playlist file got updated, and when yes we reload it and setup everything in place.
// Check if there is no current playlist or file got updated,
// and when is so load/reload it.
fn load_or_update_playlist(&mut self, seek: bool) {
let mut get_current = false;
let mut reload = false;
@ -235,7 +236,7 @@ impl CurrentProgram {
.current_list
.lock()
.unwrap()
.iter_mut()
.iter()
.enumerate()
{
if item.begin.unwrap() + item.out - item.seek > time_sec {
@ -267,12 +268,12 @@ impl CurrentProgram {
trace!("Clip from init: {}", node_clone.source);
// Important! When no manual drop is happen here, lock is still active in handle_list_init
drop(nodes);
node_clone.seek += time_sec
- (node_clone.begin.unwrap() - *self.playout_stat.time_shift.lock().unwrap());
// Important! When no manual drop is happen here, lock is still active in handle_list_init
drop(nodes);
self.current_node = handle_list_init(
&self.config,
node_clone,
@ -285,6 +286,7 @@ impl CurrentProgram {
.current_node
.source
.contains(&self.config.storage.path.to_string_lossy().to_string())
|| self.current_node.source.contains("color=c=#121212")
{
is_filler = true;
}
@ -392,6 +394,7 @@ impl Iterator for CurrentProgram {
let node_list = self.player_control.current_list.lock().unwrap();
let node = node_list[index].clone();
let last_index = node_list.len() - 1;
drop(node_list);
if index == last_index {
@ -519,6 +522,39 @@ fn timed_source(
new_node
}
fn duplicate_for_seek_and_loop(node: &mut Media, player_control: &PlayerControl) {
warn!("Clip loops and has seek value: duplicate clip to separate loop and seek.");
let mut nodes = player_control.current_list.lock().unwrap();
let index = node.index.unwrap_or_default();
let mut node_duplicate = node.clone();
node_duplicate.seek = 0.0;
let orig_seek = node.seek;
node.out = node.duration;
if node.seek > node.duration {
node.seek %= node.duration;
node_duplicate.out = node_duplicate.out - orig_seek - (node.out - node.seek);
} else {
node_duplicate.out -= node_duplicate.duration;
}
if node.seek == node.out {
node.seek = node_duplicate.seek;
node.out = node_duplicate.out;
} else if node_duplicate.out - node_duplicate.seek > 1.2 {
node_duplicate.begin =
Some(node_duplicate.begin.unwrap_or_default() + (node.out - node.seek));
nodes.insert(index + 1, node_duplicate);
for (i, item) in nodes.iter_mut().enumerate() {
item.index = Some(i);
}
}
}
/// Generate the source CMD, or when clip not exist, get a dummy.
pub fn gen_source(
config: &PlayoutConfig,
@ -536,9 +572,9 @@ pub fn gen_source(
duration = 1.2;
if node.seek > 1.0 {
node.seek -= 1.0;
node.seek -= 1.2;
} else {
node.out += 1.0;
node.out = 1.2;
}
}
@ -563,6 +599,10 @@ pub fn gen_source(
{
node.cmd = Some(loop_image(&node));
} else {
if node.seek > 0.0 && node.out > node.duration {
duplicate_for_seek_and_loop(&mut node, player_control);
}
node.cmd = Some(seek_and_length(&mut node));
}
} else {
@ -580,16 +620,17 @@ pub fn gen_source(
Err(e) => error!("Lock filler list error: {e}"),
}
// Set list_init to true, to stay in sync.
playout_stat.list_init.store(true, Ordering::SeqCst);
if config.storage.filler.is_dir() && !filler_list.is_empty() {
let filler_index = player_control.filler_index.fetch_add(1, Ordering::SeqCst);
let mut filler_media = filler_list[filler_index].clone();
trace!("take filler: {}", filler_media.source);
// Set list_init to true, to stay in sync.
playout_stat.list_init.store(true, Ordering::SeqCst);
if filler_index == filler_list.len() - 1 {
// reset index for next round
player_control.filler_index.store(0, Ordering::SeqCst)
}
@ -700,14 +741,11 @@ fn handle_list_init(
) -> Media {
debug!("Playlist init");
let (_, total_delta) = get_delta(config, &node.begin.unwrap());
let mut out = node.out;
if node.out - node.seek > total_delta {
out = total_delta + node.seek;
node.out = total_delta + node.seek;
}
node.out = out;
gen_source(config, node, playout_stat, player_control, last_index)
}

View File

@ -40,7 +40,7 @@ pub fn output(config: &PlayoutConfig, log_format: &str) -> process::Child {
}) {
enc_cmd.append(&mut cmd);
} else {
warn!("ffplay does not support given output parameters, they are skipped!");
warn!("ffplay doesn't support given output parameters, they will be skipped!");
}
}

View File

@ -529,6 +529,7 @@ pub fn loop_filler(node: &Media) -> Vec<String> {
/// Set clip seek in and length value.
pub fn seek_and_length(node: &mut Media) -> Vec<String> {
let loop_count = (node.out / node.duration).ceil() as i32;
let mut source_cmd = vec![];
let mut cut_audio = false;
let mut loop_audio = false;
@ -541,9 +542,15 @@ pub fn seek_and_length(node: &mut Media) -> Vec<String> {
source_cmd.append(&mut vec_strings!["-ss", node.seek])
}
if loop_count > 1 {
info!("Loop <b><magenta>{}</></b> <yellow>{loop_count}</> times, total duration: <yellow>{:.2}</>", node.source, node.out);
source_cmd.append(&mut vec_strings!["-stream_loop", loop_count]);
}
source_cmd.append(&mut vec_strings!["-i", node.source.clone()]);
if node.duration > node.out || remote_source {
if node.duration > node.out || remote_source || loop_count > 1 {
source_cmd.append(&mut vec_strings!["-t", node.out - node.seek]);
}
@ -552,9 +559,9 @@ pub fn seek_and_length(node: &mut Media) -> Vec<String> {
source_cmd.append(&mut vec_strings!["-ss", node.seek]);
}
if node.duration_audio > node.duration {
if node.duration_audio > node.out {
cut_audio = true;
} else if node.duration_audio < node.duration {
} else if node.duration_audio < node.out {
source_cmd.append(&mut vec_strings!["-stream_loop", -1]);
loop_audio = true;
}