From 066023c47de5a60bfde7b4bd0ddeaa31fa4e465e Mon Sep 17 00:00:00 2001 From: Romane Lafon Date: Thu, 10 Aug 2023 15:29:00 +0200 Subject: [PATCH 1/5] fix last frame detected for audio or video --- src/probe/black_detect.rs | 9 +++++---- src/probe/dualmono_detect.rs | 8 ++++---- src/probe/ocr_detect.rs | 10 +++++----- src/probe/silence_detect.rs | 10 +++++----- src/probe/sine_detect.rs | 26 ++++++++++++-------------- 5 files changed, 31 insertions(+), 32 deletions(-) diff --git a/src/probe/black_detect.rs b/src/probe/black_detect.rs index 7102bdb..e6f95a4 100644 --- a/src/probe/black_detect.rs +++ b/src/probe/black_detect.rs @@ -96,7 +96,7 @@ pub fn detect_black_frames( Ok(results) => { info!("END OF PROCESS"); info!("-> {:?} frames processed", results.len()); - let mut duration = 0; + let mut end_from_duration = 0; let mut max_duration = None; let mut min_duration = None; if let Some(duration) = params.get("duration") { @@ -113,10 +113,11 @@ pub fn detect_black_frames( if let Ok(stream) = ContextStream::new(context.get_stream(index as isize)) { if let AVMediaType::AVMEDIA_TYPE_VIDEO = context.get_stream_type(index as isize) { let frame_rate = stream.get_frame_rate().to_float(); + let frame_duration = stream.get_frame_rate().invert().to_float(); if let Some(stream_duration) = stream.get_duration() { - duration = (stream_duration * 1000.0) as i64; + end_from_duration = ((stream_duration - frame_duration) * 1000.0).round() as i64; } else { - duration = (results.len() as f32 / frame_rate * 1000.0) as i64; + end_from_duration = ((results.len() as f32 - 1.0) / frame_rate * 1000.0).round() as i64; } } } @@ -132,7 +133,7 @@ pub fn detect_black_frames( let detected_black = streams[(index) as usize].detected_black.as_mut().unwrap(); let mut black = BlackResult { start: 0, - end: duration, + end: end_from_duration, }; if let Some(value) = entry_map.get("lavfi.black_start") { diff --git a/src/probe/dualmono_detect.rs b/src/probe/dualmono_detect.rs index 32e52da..8effa34 100644 --- a/src/probe/dualmono_detect.rs +++ b/src/probe/dualmono_detect.rs @@ -137,7 +137,7 @@ pub fn detect_dualmono( Ok(results) => { info!("END OF PROCESS"); info!("-> {:?} frames processed", results.len()); - let mut duration = 0; + let mut end_from_duration = 0; let mut audio_stream_qualif_number = 0; match params.get("pairing_list") { @@ -166,8 +166,8 @@ pub fn detect_dualmono( if let Ok(stream) = ContextStream::new(context.get_stream(index as isize)) { if let AVMediaType::AVMEDIA_TYPE_VIDEO = context.get_stream_type(index as isize) { let frame_rate = stream.get_frame_rate().to_float() as f64; - duration = (results.len() as f64 / audio_stream_qualif_number as f64 / frame_rate - * 1000.0) as i64; + end_from_duration = (((results.len() as f64 / audio_stream_qualif_number as f64) - 1.0) / frame_rate + * 1000.0).round() as i64; } } } @@ -185,7 +185,7 @@ pub fn detect_dualmono( .unwrap(); let mut dualmono = DualMonoResult { start: 0, - end: duration, + end: end_from_duration, }; if let Some(value) = entry_map.get("lavfi.aphasemeter.mono_start") { dualmono.start = (value.parse::().unwrap() * 1000.0).round() as i64; diff --git a/src/probe/ocr_detect.rs b/src/probe/ocr_detect.rs index 98c7f37..4f19f2b 100644 --- a/src/probe/ocr_detect.rs +++ b/src/probe/ocr_detect.rs @@ -96,7 +96,7 @@ pub fn detect_ocr( info!("-> {:?} frames processed", results.len()); let mut frame_rate = 1.0; let mut media_offline_detected = false; - let mut nb_frames = 0; + let mut last_frame = 0; let mut context = FormatContext::new(filename).unwrap(); if let Err(msg) = context.open_input() { context.close_input(); @@ -107,10 +107,10 @@ pub fn detect_ocr( if let Ok(stream) = ContextStream::new(context.get_stream(index as isize)) { if let AVMediaType::AVMEDIA_TYPE_VIDEO = context.get_stream_type(index as isize) { frame_rate = stream.get_frame_rate().to_float(); - if let Some(frames_number) = stream.get_nb_frames() { - nb_frames = frames_number; + if let Some(nb_frames) = stream.get_nb_frames() { + last_frame = nb_frames - 1; } else { - nb_frames = results.len() as i64; + last_frame = results.len() as i64 - 1; } } } @@ -126,7 +126,7 @@ pub fn detect_ocr( let detected_ocr = streams[(index) as usize].detected_ocr.as_mut().unwrap(); let mut ocr = OcrResult { frame_start: 0, - frame_end: nb_frames as u64, + frame_end: last_frame as u64, text: "".to_string(), word_confidence: "".to_string(), }; diff --git a/src/probe/silence_detect.rs b/src/probe/silence_detect.rs index b9afa72..a1a029c 100644 --- a/src/probe/silence_detect.rs +++ b/src/probe/silence_detect.rs @@ -100,7 +100,7 @@ pub fn detect_silence( Ok(results) => { info!("END OF PROCESS"); info!("-> {:?} frames processed", results.len()); - let mut duration = 0; + let mut end_from_duration = 0; let mut context = FormatContext::new(filename).unwrap(); if let Err(msg) = context.open_input() { context.close_input(); @@ -111,8 +111,8 @@ pub fn detect_silence( if let Ok(stream) = ContextStream::new(context.get_stream(index as isize)) { if let AVMediaType::AVMEDIA_TYPE_VIDEO = context.get_stream_type(index as isize) { let frame_rate = stream.get_frame_rate().to_float() as f64; - duration = (results.len() as f64 / audio_indexes.clone().len() as f64 / frame_rate - * 1000.0) as i64; + end_from_duration = (((results.len() as f64 / audio_indexes.clone().len() as f64) - 1.0) / frame_rate + * 1000.0).round() as i64; } } } @@ -131,7 +131,7 @@ pub fn detect_silence( let detected_silence = streams[(index) as usize].detected_silence.as_mut().unwrap(); let mut silence = SilenceResult { start: 0, - end: duration, + end: end_from_duration, }; if let Some(value) = entry_map.get("lavfi.silence_start") { @@ -157,7 +157,7 @@ pub fn detect_silence( let detected_silence = streams[(index) as usize].detected_silence.as_mut().unwrap(); if detected_silence.len() == 1 && detected_silence[0].start == 0 - && detected_silence[0].end == duration + && detected_silence[0].end == end_from_duration { streams[(index) as usize].silent_stream = Some(true); } diff --git a/src/probe/sine_detect.rs b/src/probe/sine_detect.rs index 1fb543b..b8d9021 100644 --- a/src/probe/sine_detect.rs +++ b/src/probe/sine_detect.rs @@ -109,14 +109,14 @@ pub fn detect_sine( Ok(results) => { info!("END OF PROCESS"); info!("-> {:?} frames processed", results.len()); - let mut duration = 0; - let mut time_base = 1.0; + let mut end_from_duration = 0; + let mut frame_rate = 1.0; let mut tracks: Vec> = Vec::new(); let mut sine: SineResult = Default::default(); let mut range_value: f64 = 1.0; //contains the range values to code a sample let mut last_starts: HashMap> = HashMap::new(); //contains the previous declared start let mut last_crests: HashMap = HashMap::new(); //contains the crest factor from the previous frame - let mut frames: HashMap = HashMap::new(); //contains the current frame number + let mut frames: HashMap = HashMap::new(); //contains the current frame number let mut zero_cross: HashMap = HashMap::new(); //contains the number of zero crossings let mut max_duration = None; let mut min_duration = None; @@ -142,10 +142,9 @@ pub fn detect_sine( for index in 0..context.get_nb_streams() { if let Ok(stream) = ContextStream::new(context.get_stream(index as isize)) { if let AVMediaType::AVMEDIA_TYPE_VIDEO = context.get_stream_type(index as isize) { - let frame_rate = stream.get_frame_rate().to_float() as f64; - duration = - (results.len() as f64 / audio_indexes.len() as f64 / frame_rate * 1000.0) as i64; - time_base = stream.get_time_base().to_float(); + frame_rate = stream.get_frame_rate().to_float() as f64; + end_from_duration = + (((results.len() as f64 / audio_indexes.len() as f64) - 1.0) / frame_rate * 1000.0).round() as i64; } } } @@ -193,9 +192,8 @@ pub fn detect_sine( let audio_stream_key = Track::new(index, channel); //update frame count - let prev_frame = frames.get(&audio_stream_key).unwrap_or(&0.0); - frames.insert(audio_stream_key.clone(), prev_frame + 1.0); - let frame = frames.get(&audio_stream_key).unwrap(); + let frame = *frames.get(&audio_stream_key).unwrap_or(&0.0); + frames.insert(audio_stream_key.clone(), frame + 1.0); let last_start_opt = last_starts.get(&audio_stream_key).unwrap_or(&None); //update signal zero crossing count @@ -213,10 +211,10 @@ pub fn detect_sine( if last_start_opt.is_some() { if let Some(last_start) = last_start_opt { //check if audio ends => 1000Hz until the end - if (frame * (time_base * 1000.0)) as i64 == duration { + if (frame / frame_rate * 1000.0).round() as i64 == end_from_duration { sine.channel = channel; sine.start = *last_start; - sine.end = duration; + sine.end = end_from_duration; //check if sine is a 1000Hz => push and reset if let Some(zero_crossing) = zero_cross.get(&audio_stream_key.clone()) { if ((zero_crossing) / (sine.end - sine.start) as f64) == 2.0 { @@ -238,7 +236,7 @@ pub fn detect_sine( } } } else { - sine.start = ((frame - 1.0) * (time_base * 1000.0)).round() as i64; + sine.start = (frame / frame_rate * 1000.0).round() as i64; last_starts.insert(audio_stream_key.clone(), Some(sine.start)); } } else if (2_f64.sqrt() - 1e-3_f64..2_f64.sqrt() + 1e-3_f64) @@ -248,7 +246,7 @@ pub fn detect_sine( if let Some(last_start) = last_start_opt { sine.channel = channel; sine.start = *last_start; - sine.end = ((frame - 1.0) * (time_base * 1000.0)).round() as i64; + sine.end = ((frame - 1.0) / frame_rate * 1000.0).round() as i64; //check if sine is a 1000Hz => push and reset if let Some(zero_crossing) = zero_cross.get(&audio_stream_key) { if (zero_crossing / (sine.end - sine.start) as f64) == 2.0 { From 9ed9d7a82cfcd0bd624ce351972ec78544f8910a Mon Sep 17 00:00:00 2001 From: Romane Lafon Date: Fri, 11 Aug 2023 12:19:34 +0200 Subject: [PATCH 2/5] fix detected durations --- src/probe/black_and_silence.rs | 3 ++- src/probe/black_detect.rs | 7 ++++--- src/probe/deep.rs | 3 +++ src/probe/dualmono_detect.rs | 6 ++++-- src/probe/silence_detect.rs | 9 ++++++--- src/probe/sine_detect.rs | 14 ++++++++------ 6 files changed, 27 insertions(+), 15 deletions(-) diff --git a/src/probe/black_and_silence.rs b/src/probe/black_and_silence.rs index d19c56e..47720b2 100644 --- a/src/probe/black_and_silence.rs +++ b/src/probe/black_and_silence.rs @@ -6,6 +6,7 @@ pub fn detect_black_and_silence( video_indexes: Vec, audio_indexes: Vec, params: HashMap, + frame_duration: f32, ) { let mut bas = BlackAndSilenceResult { start: 0, end: 0 }; let mut duration_min = None; @@ -33,7 +34,7 @@ pub fn detect_black_and_silence( bas.start = bl_detect.start; } if bas.start < bas.end { - let bas_duration: i64 = bas.end - bas.start; + let bas_duration: i64 = bas.end - bas.start + (frame_duration * 1000.0).round() as i64; let detected_black_and_silence = streams[si_index as usize] .detected_black_and_silence .as_mut() diff --git a/src/probe/black_detect.rs b/src/probe/black_detect.rs index e6f95a4..66a81a7 100644 --- a/src/probe/black_detect.rs +++ b/src/probe/black_detect.rs @@ -99,6 +99,7 @@ pub fn detect_black_frames( let mut end_from_duration = 0; let mut max_duration = None; let mut min_duration = None; + let mut frame_duration = 0.0; if let Some(duration) = params.get("duration") { max_duration = duration.max; min_duration = duration.min; @@ -113,7 +114,7 @@ pub fn detect_black_frames( if let Ok(stream) = ContextStream::new(context.get_stream(index as isize)) { if let AVMediaType::AVMEDIA_TYPE_VIDEO = context.get_stream_type(index as isize) { let frame_rate = stream.get_frame_rate().to_float(); - let frame_duration = stream.get_frame_rate().invert().to_float(); + frame_duration = stream.get_frame_rate().invert().to_float(); if let Some(stream_duration) = stream.get_duration() { end_from_duration = ((stream_duration - frame_duration) * 1000.0).round() as i64; } else { @@ -142,8 +143,8 @@ pub fn detect_black_frames( } if let Some(value) = entry_map.get("lavfi.black_end") { if let Some(last_detect) = detected_black.last_mut() { - last_detect.end = (value.parse::().unwrap() * 1000.0).round() as i64; - let black_duration = last_detect.end - last_detect.start; + last_detect.end = ((value.parse::().unwrap() - frame_duration) * 1000.0).round() as i64; + let black_duration = last_detect.end - last_detect.start + (frame_duration * 1000.0).round() as i64; if let Some(max) = max_duration { if black_duration > max as i64 { detected_black.pop(); diff --git a/src/probe/deep.rs b/src/probe/deep.rs index 0bd7fa7..6a53dbd 100644 --- a/src/probe/deep.rs +++ b/src/probe/deep.rs @@ -330,6 +330,7 @@ impl DeepProbe { return Ok(()); } + let mut frame_duration = 0.0; let mut streams = vec![]; streams.resize(context.get_nb_streams() as usize, StreamProbeResult::new()); while let Ok(packet) = context.next_packet() { @@ -351,6 +352,7 @@ impl DeepProbe { streams[stream_index].color_primaries = stream.get_color_primaries(); streams[stream_index].color_trc = stream.get_color_trc(); streams[stream_index].color_matrix = stream.get_color_matrix(); + frame_duration = stream.get_frame_rate().invert().to_float(); } } } @@ -392,6 +394,7 @@ impl DeepProbe { video_indexes.clone(), audio_indexes.clone(), black_and_silence_parameters, + frame_duration ); } } diff --git a/src/probe/dualmono_detect.rs b/src/probe/dualmono_detect.rs index 8effa34..adfc303 100644 --- a/src/probe/dualmono_detect.rs +++ b/src/probe/dualmono_detect.rs @@ -122,6 +122,7 @@ pub fn detect_dualmono( ) { let mut order = create_graph(filename, ¶ms).unwrap(); let mut max_duration = None; + let mut frame_duration = 0.0; if let Some(duration) = params.get("duration") { max_duration = duration.max; } @@ -166,6 +167,7 @@ pub fn detect_dualmono( if let Ok(stream) = ContextStream::new(context.get_stream(index as isize)) { if let AVMediaType::AVMEDIA_TYPE_VIDEO = context.get_stream_type(index as isize) { let frame_rate = stream.get_frame_rate().to_float() as f64; + frame_duration = stream.get_frame_rate().invert().to_float() as f64; end_from_duration = (((results.len() as f64 / audio_stream_qualif_number as f64) - 1.0) / frame_rate * 1000.0).round() as i64; } @@ -193,7 +195,7 @@ pub fn detect_dualmono( } if let Some(value) = entry_map.get("lavfi.aphasemeter.mono_end") { if let Some(last_detect) = detected_dualmono.last_mut() { - last_detect.end = (value.parse::().unwrap() * 1000.0).round() as i64; + last_detect.end = ((value.parse::().unwrap() - frame_duration) * 1000.0).round() as i64; } } if let Some(value) = entry_map.get("lavfi.aphasemeter.mono_duration") { @@ -213,7 +215,7 @@ pub fn detect_dualmono( .as_mut() .unwrap(); if let Some(last_detect) = detected_dualmono.last() { - let duration = last_detect.end - last_detect.start; + let duration = last_detect.end - last_detect.start + (frame_duration * 1000.0).round() as i64; if let Some(max) = max_duration { if duration > max as i64 { detected_dualmono.pop(); diff --git a/src/probe/silence_detect.rs b/src/probe/silence_detect.rs index a1a029c..5c6900b 100644 --- a/src/probe/silence_detect.rs +++ b/src/probe/silence_detect.rs @@ -101,6 +101,7 @@ pub fn detect_silence( info!("END OF PROCESS"); info!("-> {:?} frames processed", results.len()); let mut end_from_duration = 0; + let mut frame_duration = 0.0; let mut context = FormatContext::new(filename).unwrap(); if let Err(msg) = context.open_input() { context.close_input(); @@ -111,6 +112,7 @@ pub fn detect_silence( if let Ok(stream) = ContextStream::new(context.get_stream(index as isize)) { if let AVMediaType::AVMEDIA_TYPE_VIDEO = context.get_stream_type(index as isize) { let frame_rate = stream.get_frame_rate().to_float() as f64; + frame_duration = stream.get_frame_rate().invert().to_float() as f64; end_from_duration = (((results.len() as f64 / audio_indexes.clone().len() as f64) - 1.0) / frame_rate * 1000.0).round() as i64; } @@ -140,12 +142,12 @@ pub fn detect_silence( } if let Some(value) = entry_map.get("lavfi.silence_end") { if let Some(last_detect) = detected_silence.last_mut() { - last_detect.end = (value.parse::().unwrap() * 1000.0).round() as i64; + last_detect.end = ((value.parse::().unwrap() - frame_duration) * 1000.0).round() as i64; } } if let Some(value) = entry_map.get("lavfi.silence_duration") { if let Some(max) = max_duration { - if (value.parse::().unwrap() * 1000.0) as u64 > max { + if (value.parse::().unwrap() * 1000.0).round() as u64 > max { detected_silence.pop(); } } @@ -163,7 +165,8 @@ pub fn detect_silence( } if let Some(max) = max_duration { if let Some(last_detect) = detected_silence.last() { - if (last_detect.end - last_detect.start) > max as i64 { + let silence_duration = last_detect.end - last_detect.start + (frame_duration * 1000.0).round() as i64; + if silence_duration > max as i64 { detected_silence.pop(); } } diff --git a/src/probe/sine_detect.rs b/src/probe/sine_detect.rs index b8d9021..b56a05e 100644 --- a/src/probe/sine_detect.rs +++ b/src/probe/sine_detect.rs @@ -217,17 +217,18 @@ pub fn detect_sine( sine.end = end_from_duration; //check if sine is a 1000Hz => push and reset if let Some(zero_crossing) = zero_cross.get(&audio_stream_key.clone()) { - if ((zero_crossing) / (sine.end - sine.start) as f64) == 2.0 { + let sine_duration = ((frame + 1.0) / frame_rate * 1000.0).round() as i64 - sine.start; + if (zero_crossing / sine_duration as f64) == 2.0 { detected_sine.push(sine); last_starts.insert(audio_stream_key.clone(), None); zero_cross.insert(audio_stream_key.clone(), 0.0); if let Some(max) = max_duration { - if (sine.end - sine.start) > max as i64 { + if sine_duration > max as i64 { detected_sine.pop(); } } if let Some(min) = min_duration { - if (sine.end - sine.start) < min as i64 { + if sine_duration < min as i64 { detected_sine.pop(); } } @@ -248,18 +249,19 @@ pub fn detect_sine( sine.start = *last_start; sine.end = ((frame - 1.0) / frame_rate * 1000.0).round() as i64; //check if sine is a 1000Hz => push and reset + let sine_duration = (frame / frame_rate * 1000.0).round() as i64 - sine.start; if let Some(zero_crossing) = zero_cross.get(&audio_stream_key) { - if (zero_crossing / (sine.end - sine.start) as f64) == 2.0 { + if (zero_crossing / sine_duration as f64) == 2.0 { detected_sine.push(sine); last_starts.insert(audio_stream_key.clone(), None); zero_cross.insert(audio_stream_key.clone(), 0.0); if let Some(max) = max_duration { - if (sine.end - sine.start) > max as i64 { + if sine_duration > max as i64 { detected_sine.pop(); } } if let Some(min) = min_duration { - if (sine.end - sine.start) < min as i64 { + if sine_duration < min as i64 { detected_sine.pop(); } } From 5e23b8cbc42f5c718a0cbfea1585019859cb192c Mon Sep 17 00:00:00 2001 From: Romane Lafon Date: Fri, 11 Aug 2023 12:42:14 +0200 Subject: [PATCH 3/5] format and test --- src/probe/black_detect.rs | 9 ++++--- src/probe/deep.rs | 2 +- src/probe/dualmono_detect.rs | 12 ++++++---- src/probe/silence_detect.rs | 12 ++++++---- src/probe/sine_detect.rs | 6 +++-- tests/deep_probe.json | 46 ++++++++++++++++++------------------ 6 files changed, 50 insertions(+), 37 deletions(-) diff --git a/src/probe/black_detect.rs b/src/probe/black_detect.rs index 66a81a7..3982068 100644 --- a/src/probe/black_detect.rs +++ b/src/probe/black_detect.rs @@ -118,7 +118,8 @@ pub fn detect_black_frames( if let Some(stream_duration) = stream.get_duration() { end_from_duration = ((stream_duration - frame_duration) * 1000.0).round() as i64; } else { - end_from_duration = ((results.len() as f32 - 1.0) / frame_rate * 1000.0).round() as i64; + end_from_duration = + ((results.len() as f32 - 1.0) / frame_rate * 1000.0).round() as i64; } } } @@ -143,8 +144,10 @@ pub fn detect_black_frames( } if let Some(value) = entry_map.get("lavfi.black_end") { if let Some(last_detect) = detected_black.last_mut() { - last_detect.end = ((value.parse::().unwrap() - frame_duration) * 1000.0).round() as i64; - let black_duration = last_detect.end - last_detect.start + (frame_duration * 1000.0).round() as i64; + last_detect.end = + ((value.parse::().unwrap() - frame_duration) * 1000.0).round() as i64; + let black_duration = + last_detect.end - last_detect.start + (frame_duration * 1000.0).round() as i64; if let Some(max) = max_duration { if black_duration > max as i64 { detected_black.pop(); diff --git a/src/probe/deep.rs b/src/probe/deep.rs index 6a53dbd..266dda1 100644 --- a/src/probe/deep.rs +++ b/src/probe/deep.rs @@ -394,7 +394,7 @@ impl DeepProbe { video_indexes.clone(), audio_indexes.clone(), black_and_silence_parameters, - frame_duration + frame_duration, ); } } diff --git a/src/probe/dualmono_detect.rs b/src/probe/dualmono_detect.rs index adfc303..dac89b7 100644 --- a/src/probe/dualmono_detect.rs +++ b/src/probe/dualmono_detect.rs @@ -168,8 +168,10 @@ pub fn detect_dualmono( if let AVMediaType::AVMEDIA_TYPE_VIDEO = context.get_stream_type(index as isize) { let frame_rate = stream.get_frame_rate().to_float() as f64; frame_duration = stream.get_frame_rate().invert().to_float() as f64; - end_from_duration = (((results.len() as f64 / audio_stream_qualif_number as f64) - 1.0) / frame_rate - * 1000.0).round() as i64; + end_from_duration = (((results.len() as f64 / audio_stream_qualif_number as f64) - 1.0) + / frame_rate + * 1000.0) + .round() as i64; } } } @@ -195,7 +197,8 @@ pub fn detect_dualmono( } if let Some(value) = entry_map.get("lavfi.aphasemeter.mono_end") { if let Some(last_detect) = detected_dualmono.last_mut() { - last_detect.end = ((value.parse::().unwrap() - frame_duration) * 1000.0).round() as i64; + last_detect.end = + ((value.parse::().unwrap() - frame_duration) * 1000.0).round() as i64; } } if let Some(value) = entry_map.get("lavfi.aphasemeter.mono_duration") { @@ -215,7 +218,8 @@ pub fn detect_dualmono( .as_mut() .unwrap(); if let Some(last_detect) = detected_dualmono.last() { - let duration = last_detect.end - last_detect.start + (frame_duration * 1000.0).round() as i64; + let duration = + last_detect.end - last_detect.start + (frame_duration * 1000.0).round() as i64; if let Some(max) = max_duration { if duration > max as i64 { detected_dualmono.pop(); diff --git a/src/probe/silence_detect.rs b/src/probe/silence_detect.rs index 5c6900b..e76484e 100644 --- a/src/probe/silence_detect.rs +++ b/src/probe/silence_detect.rs @@ -113,8 +113,10 @@ pub fn detect_silence( if let AVMediaType::AVMEDIA_TYPE_VIDEO = context.get_stream_type(index as isize) { let frame_rate = stream.get_frame_rate().to_float() as f64; frame_duration = stream.get_frame_rate().invert().to_float() as f64; - end_from_duration = (((results.len() as f64 / audio_indexes.clone().len() as f64) - 1.0) / frame_rate - * 1000.0).round() as i64; + end_from_duration = + (((results.len() as f64 / audio_indexes.clone().len() as f64) - 1.0) / frame_rate + * 1000.0) + .round() as i64; } } } @@ -142,7 +144,8 @@ pub fn detect_silence( } if let Some(value) = entry_map.get("lavfi.silence_end") { if let Some(last_detect) = detected_silence.last_mut() { - last_detect.end = ((value.parse::().unwrap() - frame_duration) * 1000.0).round() as i64; + last_detect.end = + ((value.parse::().unwrap() - frame_duration) * 1000.0).round() as i64; } } if let Some(value) = entry_map.get("lavfi.silence_duration") { @@ -165,7 +168,8 @@ pub fn detect_silence( } if let Some(max) = max_duration { if let Some(last_detect) = detected_silence.last() { - let silence_duration = last_detect.end - last_detect.start + (frame_duration * 1000.0).round() as i64; + let silence_duration = + last_detect.end - last_detect.start + (frame_duration * 1000.0).round() as i64; if silence_duration > max as i64 { detected_silence.pop(); } diff --git a/src/probe/sine_detect.rs b/src/probe/sine_detect.rs index b56a05e..8f50f84 100644 --- a/src/probe/sine_detect.rs +++ b/src/probe/sine_detect.rs @@ -144,7 +144,8 @@ pub fn detect_sine( if let AVMediaType::AVMEDIA_TYPE_VIDEO = context.get_stream_type(index as isize) { frame_rate = stream.get_frame_rate().to_float() as f64; end_from_duration = - (((results.len() as f64 / audio_indexes.len() as f64) - 1.0) / frame_rate * 1000.0).round() as i64; + (((results.len() as f64 / audio_indexes.len() as f64) - 1.0) / frame_rate * 1000.0) + .round() as i64; } } } @@ -217,7 +218,8 @@ pub fn detect_sine( sine.end = end_from_duration; //check if sine is a 1000Hz => push and reset if let Some(zero_crossing) = zero_cross.get(&audio_stream_key.clone()) { - let sine_duration = ((frame + 1.0) / frame_rate * 1000.0).round() as i64 - sine.start; + let sine_duration = + ((frame + 1.0) / frame_rate * 1000.0).round() as i64 - sine.start; if (zero_crossing / sine_duration as f64) == 2.0 { detected_sine.push(sine); last_starts.insert(audio_stream_key.clone(), None); diff --git a/tests/deep_probe.json b/tests/deep_probe.json index 3bda56b..2c74898 100644 --- a/tests/deep_probe.json +++ b/tests/deep_probe.json @@ -16,11 +16,11 @@ "detected_black": [ { "start": 0, - "end": 4960 + "end": 4920 }, { "start": 9960, - "end": 14960 + "end": 14920 } ], "detected_scene": [ @@ -63,15 +63,15 @@ "detected_silence": [ { "start": 3000, - "end": 6000 + "end": 5960 }, { "start": 9000, - "end": 12000 + "end": 11960 }, { "start": 15000, - "end": 18000 + "end": 17960 } ], "detected_loudness": [ @@ -88,32 +88,32 @@ "detected_black_and_silence": [ { "start": 3000, - "end": 4960 + "end": 4920 }, { "start": 9960, - "end": 12000 + "end": 11960 } ], "detected_sine": [ { "channel": 1, - "end": 3000, + "end": 2960, "start": 0 }, { "channel": 1, - "end": 9000, + "end": 8960, "start": 6000 }, { "channel": 1, - "end": 15000, + "end": 14960, "start": 12000 }, { "channel": 1, - "end": 20000, + "end": 19960, "start": 18000 } ] @@ -131,7 +131,7 @@ "detected_silence": [ { "start": 9000, - "end": 18000 + "end": 17960 } ], "detected_loudness": [ @@ -148,18 +148,18 @@ "detected_black_and_silence": [ { "start": 9960, - "end": 14960 + "end": 14920 } ], "detected_sine": [ { "channel": 1, - "end": 9000, + "end": 8960, "start": 0 }, { "channel": 1, - "end": 20000, + "end": 19960, "start": 18000 } ] @@ -219,19 +219,19 @@ "detected_dualmono": [ { "start": 0, - "end": 20000 + "end": 19960 } ], "detected_silence": [], "detected_sine": [ { "channel": 1, - "end": 20000, + "end": 19960, "start": 0 }, { "channel": 2, - "end": 20000, + "end": 19960, "start": 0 } ], @@ -263,7 +263,7 @@ "detected_sine": [ { "channel": 1, - "end": 20000, + "end": 19960, "start": 0 } ], @@ -292,14 +292,14 @@ "detected_dualmono": [ { "start": 0, - "end": 20000 + "end": 19960 } ], "detected_silence": [], "detected_sine": [ { "channel": 1, - "end": 20000, + "end": 19960, "start": 0 } ], @@ -328,14 +328,14 @@ "detected_dualmono": [ { "start": 0, - "end": 20000 + "end": 19960 } ], "detected_silence": [], "detected_sine": [ { "channel": 1, - "end": 20000, + "end": 19960, "start": 0 } ], From 058a60fd87adf18339ab6bb8edcb232ae058a576 Mon Sep 17 00:00:00 2001 From: Romane Lafon Date: Mon, 20 Nov 2023 18:38:26 +0100 Subject: [PATCH 4/5] remove getting stream data from detect functions --- src/probe/black_detect.rs | 33 +++++-------------- src/probe/crop_detect.rs | 62 ++++++++++-------------------------- src/probe/deep.rs | 41 +++++++++++++++++++++++- src/probe/dualmono_detect.rs | 31 ++++-------------- src/probe/loudness_detect.rs | 7 ---- src/probe/ocr_detect.rs | 27 +++------------- src/probe/scene_detect.rs | 19 ++--------- src/probe/silence_detect.rs | 32 +++++-------------- src/probe/sine_detect.rs | 30 +++++++---------- 9 files changed, 97 insertions(+), 185 deletions(-) diff --git a/src/probe/black_detect.rs b/src/probe/black_detect.rs index 3982068..afd1a12 100644 --- a/src/probe/black_detect.rs +++ b/src/probe/black_detect.rs @@ -1,14 +1,11 @@ use crate::{ - format_context::FormatContext, order::{ filter_input::FilterInput, filter_output::FilterOutput, input::Input, input_kind::InputKind, output::Output, output_kind::OutputKind, stream::Stream, Filter, Order, OutputResult::Entry, ParameterValue, }, probe::deep::{BlackResult, CheckParameterValue, StreamProbeResult}, - stream::Stream as ContextStream, }; -use ffmpeg_sys_next::AVMediaType; use std::collections::HashMap; pub fn create_graph( @@ -82,6 +79,9 @@ pub fn detect_black_frames( streams: &mut [StreamProbeResult], video_indexes: Vec, params: HashMap, + frame_rate: f32, + frame_duration: f32, + stream_duration: Option, ) { let mut order = create_graph(filename, video_indexes.clone(), params.clone()).unwrap(); if let Err(msg) = order.setup() { @@ -96,34 +96,17 @@ pub fn detect_black_frames( Ok(results) => { info!("END OF PROCESS"); info!("-> {:?} frames processed", results.len()); - let mut end_from_duration = 0; + let end_from_duration = match stream_duration { + Some(duration) => ((duration - frame_duration) * 1000.0).round() as i64, + None => ((results.len() as f32 - 1.0) / frame_rate * 1000.0).round() as i64, + }; let mut max_duration = None; let mut min_duration = None; - let mut frame_duration = 0.0; if let Some(duration) = params.get("duration") { max_duration = duration.max; min_duration = duration.min; } - let mut context = FormatContext::new(filename).unwrap(); - if let Err(msg) = context.open_input() { - context.close_input(); - error!("{:?}", msg); - return; - } - for index in 0..context.get_nb_streams() { - if let Ok(stream) = ContextStream::new(context.get_stream(index as isize)) { - if let AVMediaType::AVMEDIA_TYPE_VIDEO = context.get_stream_type(index as isize) { - let frame_rate = stream.get_frame_rate().to_float(); - frame_duration = stream.get_frame_rate().invert().to_float(); - if let Some(stream_duration) = stream.get_duration() { - end_from_duration = ((stream_duration - frame_duration) * 1000.0).round() as i64; - } else { - end_from_duration = - ((results.len() as f32 - 1.0) / frame_rate * 1000.0).round() as i64; - } - } - } - } + for result in results { if let Entry(entry_map) = result { if let Some(stream_id) = entry_map.get("stream_id") { diff --git a/src/probe/crop_detect.rs b/src/probe/crop_detect.rs index c997d79..dfb2625 100644 --- a/src/probe/crop_detect.rs +++ b/src/probe/crop_detect.rs @@ -1,13 +1,10 @@ -use crate::format_context::FormatContext; use crate::order::{ filter_input::FilterInput, filter_output::FilterOutput, input::Input, input_kind::InputKind, output::Output, output_kind::OutputKind, stream::Stream, }; use crate::order::{Filter, Order, OutputResult::Entry, ParameterValue}; use crate::probe::deep::{CheckParameterValue, CropResult, StreamProbeResult}; -use crate::stream::Stream as ContextStream; use crate::tools::rational::Rational; -use ffmpeg_sys_next::AVMediaType; use std::collections::HashMap; pub fn create_graph( @@ -91,31 +88,20 @@ pub fn detect_black_borders( streams: &mut [StreamProbeResult], video_indexes: Vec, params: HashMap, + stream_frames: Option, + bits_raw_sample: Option, + time_base: f32, + metadata_width: i32, + metadata_height: i32, + aspect_ratio: Rational, ) { - let mut context = FormatContext::new(filename).unwrap(); - if let Err(msg) = context.open_input() { - context.close_input(); - error!("{:?}", msg); - return; - } - - let mut nb_frames = 0; - let mut limit = 0; - for index in 0..context.get_nb_streams() { - if let Ok(stream) = ContextStream::new(context.get_stream(index as isize)) { - if let AVMediaType::AVMEDIA_TYPE_VIDEO = context.get_stream_type(index as isize) { - if let Some(frames) = stream.get_nb_frames() { - nb_frames = frames; - } - // black threshold : 16 pour 8bits / 64 pour 10bits / 256 pour 12bits - limit = match stream.get_bits_per_raw_sample() { - Some(10) => 64, - Some(12) => 256, - _ => 16, - } - } - } - } + let nb_frames = stream_frames.unwrap_or(0); + // black threshold : 16 pour 8bits / 64 pour 10bits / 256 pour 12bits + let limit = match bits_raw_sample { + Some(10) => 64, + Some(12) => 256, + _ => 16, + }; let mut order = create_graph(filename, video_indexes.clone(), params, nb_frames, limit).unwrap(); if let Err(msg) = order.setup() { error!("{:?}", msg); @@ -129,27 +115,11 @@ pub fn detect_black_borders( Ok(results) => { info!("END OF PROCESS"); info!("-> {:?} frames processed", results.len()); - let mut time_base = 1.0; - let mut metadata_width = 0; - let mut metadata_height = 0; - let mut real_width = 0; - let mut real_height = 0; let mut w_changed = false; let mut h_changed = false; - let mut pict_size = Rational::new(1, 1); + let mut real_width = metadata_width; + let mut real_height = metadata_height; - for index in 0..context.get_nb_streams() { - if let Ok(stream) = ContextStream::new(context.get_stream(index as isize)) { - if let AVMediaType::AVMEDIA_TYPE_VIDEO = context.get_stream_type(index as isize) { - time_base = stream.get_time_base().to_float(); - metadata_width = stream.get_width(); - metadata_height = stream.get_height(); - pict_size = stream.get_picture_aspect_ratio(); - real_width = metadata_width; - real_height = metadata_height; - } - } - } for result in results { if let Entry(entry_map) = result { if let Some(stream_id) = entry_map.get("stream_id") { @@ -190,7 +160,7 @@ pub fn detect_black_borders( crop.height = real_height; crop.pts = (pts.parse::().unwrap() * time_base * 1000.0).round() as i64; let real_aspect = - (real_width * pict_size.num) as f32 / (real_height * pict_size.den) as f32; + (real_width * aspect_ratio.num) as f32 / (real_height * aspect_ratio.den) as f32; crop.aspect_ratio = real_aspect; detected_crop.push(crop); w_changed = false; diff --git a/src/probe/deep.rs b/src/probe/deep.rs index 266dda1..e26b693 100644 --- a/src/probe/deep.rs +++ b/src/probe/deep.rs @@ -9,6 +9,7 @@ use crate::probe::scene_detect::detect_scene; use crate::probe::silence_detect::detect_silence; use crate::probe::sine_detect::detect_sine; use crate::stream::Stream; +use crate::tools::rational::Rational; use ffmpeg_sys_next::*; use log::LevelFilter; use std::{cmp, collections::HashMap, fmt}; @@ -331,6 +332,14 @@ impl DeepProbe { } let mut frame_duration = 0.0; + let mut frame_rate = 1.0; + let mut time_base = 1.0; + let mut metadata_width = 0; + let mut metadata_height = 0; + let mut stream_duration = None; + let mut stream_frames = None; + let mut bits_raw_sample = None; + let mut aspect_ratio = Rational::new(1, 1); let mut streams = vec![]; streams.resize(context.get_nb_streams() as usize, StreamProbeResult::new()); while let Ok(packet) = context.next_packet() { @@ -353,6 +362,14 @@ impl DeepProbe { streams[stream_index].color_trc = stream.get_color_trc(); streams[stream_index].color_matrix = stream.get_color_matrix(); frame_duration = stream.get_frame_rate().invert().to_float(); + frame_rate = stream.get_frame_rate().to_float(); + time_base = stream.get_time_base().to_float(); + stream_duration = stream.get_duration(); + stream_frames = stream.get_nb_frames(); + bits_raw_sample = stream.get_bits_per_raw_sample(); + metadata_width = stream.get_width(); + metadata_height = stream.get_height(); + aspect_ratio = stream.get_picture_aspect_ratio(); } } } @@ -375,6 +392,8 @@ impl DeepProbe { &mut streams, audio_indexes.clone(), silence_parameters, + frame_rate, + frame_duration, ); } @@ -384,6 +403,9 @@ impl DeepProbe { &mut streams, video_indexes.clone(), black_parameters, + frame_rate, + frame_duration, + stream_duration, ); } @@ -405,6 +427,12 @@ impl DeepProbe { &mut streams, video_indexes.clone(), crop_parameters, + stream_frames, + bits_raw_sample, + time_base, + metadata_width, + metadata_height, + aspect_ratio, ); } @@ -414,6 +442,7 @@ impl DeepProbe { &mut streams, video_indexes.clone(), scene_parameters, + frame_rate, ); } @@ -423,6 +452,8 @@ impl DeepProbe { &mut streams, video_indexes.clone(), ocr_parameters, + frame_rate, + stream_frames, ); } @@ -447,11 +478,19 @@ impl DeepProbe { &mut streams, audio_indexes.clone(), dualmono_parameters, + frame_rate, + frame_duration, ); } if let Some(sine_parameters) = check.sine_detect { - detect_sine(&self.filename, &mut streams, audio_indexes, sine_parameters); + detect_sine( + &self.filename, + &mut streams, + audio_indexes, + sine_parameters, + frame_rate, + ); } let mut format = FormatProbeResult::new(); diff --git a/src/probe/dualmono_detect.rs b/src/probe/dualmono_detect.rs index dac89b7..7fabaf8 100644 --- a/src/probe/dualmono_detect.rs +++ b/src/probe/dualmono_detect.rs @@ -1,4 +1,3 @@ -use crate::format_context::FormatContext; use crate::{ order::{ filter_input::FilterInput, filter_output::FilterOutput, input::Input, input_kind::InputKind, @@ -6,9 +5,7 @@ use crate::{ ParameterValue, }, probe::deep::{CheckParameterValue, DualMonoResult, StreamProbeResult}, - stream::Stream as ContextStream, }; -use ffmpeg_sys_next::AVMediaType; use std::collections::HashMap; pub fn create_graph( @@ -119,10 +116,11 @@ pub fn detect_dualmono( streams: &mut [StreamProbeResult], audio_indexes: Vec, params: HashMap, + frame_rate: f32, + frame_duration: f32, ) { let mut order = create_graph(filename, ¶ms).unwrap(); let mut max_duration = None; - let mut frame_duration = 0.0; if let Some(duration) = params.get("duration") { max_duration = duration.max; } @@ -138,7 +136,6 @@ pub fn detect_dualmono( Ok(results) => { info!("END OF PROCESS"); info!("-> {:?} frames processed", results.len()); - let mut end_from_duration = 0; let mut audio_stream_qualif_number = 0; match params.get("pairing_list") { @@ -157,24 +154,10 @@ pub fn detect_dualmono( None => warn!("No input message for the dualmono analysis (list of indexes to merge)"), } - let mut context = FormatContext::new(filename).unwrap(); - if let Err(msg) = context.open_input() { - context.close_input(); - error!("{:?}", msg); - return; - } - for index in 0..context.get_nb_streams() { - if let Ok(stream) = ContextStream::new(context.get_stream(index as isize)) { - if let AVMediaType::AVMEDIA_TYPE_VIDEO = context.get_stream_type(index as isize) { - let frame_rate = stream.get_frame_rate().to_float() as f64; - frame_duration = stream.get_frame_rate().invert().to_float() as f64; - end_from_duration = (((results.len() as f64 / audio_stream_qualif_number as f64) - 1.0) - / frame_rate - * 1000.0) - .round() as i64; - } - } - } + let end_from_duration = (((results.len() as f64 / audio_stream_qualif_number as f64) - 1.0) + / frame_rate as f64 + * 1000.0) + .round() as i64; for result in results { if let Entry(entry_map) = result { if let Some(stream_id) = entry_map.get("stream_id") { @@ -198,7 +181,7 @@ pub fn detect_dualmono( if let Some(value) = entry_map.get("lavfi.aphasemeter.mono_end") { if let Some(last_detect) = detected_dualmono.last_mut() { last_detect.end = - ((value.parse::().unwrap() - frame_duration) * 1000.0).round() as i64; + ((value.parse::().unwrap() - frame_duration as f64) * 1000.0).round() as i64; } } if let Some(value) = entry_map.get("lavfi.aphasemeter.mono_duration") { diff --git a/src/probe/loudness_detect.rs b/src/probe/loudness_detect.rs index 9f4e0db..460607e 100644 --- a/src/probe/loudness_detect.rs +++ b/src/probe/loudness_detect.rs @@ -1,4 +1,3 @@ -use crate::format_context::FormatContext; use crate::order::{ filter_input::FilterInput, filter_output::FilterOutput, input::Input, input_kind::InputKind, output::Output, output_kind::OutputKind, stream::Stream, Filter, Order, OutputResult::Entry, @@ -126,12 +125,6 @@ pub fn detect_loudness( Ok(results) => { info!("END OF PROCESS"); info!("-> {:?} frames processed", results.len()); - let mut context = FormatContext::new(filename).unwrap(); - if let Err(msg) = context.open_input() { - context.close_input(); - error!("{:?}", msg); - return; - } for result in results { if let Entry(entry_map) = result { if let Some(stream_id) = entry_map.get("stream_id") { diff --git a/src/probe/ocr_detect.rs b/src/probe/ocr_detect.rs index 4f19f2b..8672f1d 100644 --- a/src/probe/ocr_detect.rs +++ b/src/probe/ocr_detect.rs @@ -1,12 +1,9 @@ -use crate::format_context::FormatContext; use crate::order::{ filter_input::FilterInput, filter_output::FilterOutput, input::Input, input_kind::InputKind, output::Output, output_kind::OutputKind, stream::Stream, Filter, Order, OutputResult::Entry, ParameterValue, }; use crate::probe::deep::{CheckParameterValue, OcrResult, StreamProbeResult}; -use crate::stream::Stream as ContextStream; -use ffmpeg_sys_next::AVMediaType; use std::collections::HashMap; pub fn create_graph( @@ -80,6 +77,8 @@ pub fn detect_ocr( streams: &mut [StreamProbeResult], video_indexes: Vec, params: HashMap, + frame_rate: f32, + stream_frames: Option, ) { let mut order = create_graph(filename, video_indexes.clone(), ¶ms).unwrap(); if let Err(msg) = order.setup() { @@ -94,27 +93,9 @@ pub fn detect_ocr( Ok(results) => { info!("END OF PROCESS"); info!("-> {:?} frames processed", results.len()); - let mut frame_rate = 1.0; let mut media_offline_detected = false; - let mut last_frame = 0; - let mut context = FormatContext::new(filename).unwrap(); - if let Err(msg) = context.open_input() { - context.close_input(); - error!("{:?}", msg); - return; - } - for index in 0..context.get_nb_streams() { - if let Ok(stream) = ContextStream::new(context.get_stream(index as isize)) { - if let AVMediaType::AVMEDIA_TYPE_VIDEO = context.get_stream_type(index as isize) { - frame_rate = stream.get_frame_rate().to_float(); - if let Some(nb_frames) = stream.get_nb_frames() { - last_frame = nb_frames - 1; - } else { - last_frame = results.len() as i64 - 1; - } - } - } - } + let last_frame = stream_frames.unwrap_or(results.len() as i64) - 1; + for result in results { if let Entry(entry_map) = result { if let Some(stream_id) = entry_map.get("stream_id") { diff --git a/src/probe/scene_detect.rs b/src/probe/scene_detect.rs index 10ad29f..f5701cd 100644 --- a/src/probe/scene_detect.rs +++ b/src/probe/scene_detect.rs @@ -1,12 +1,9 @@ -use crate::format_context::FormatContext; use crate::order::{ filter_input::FilterInput, filter_output::FilterOutput, input::Input, input_kind::InputKind, output::Output, output_kind::OutputKind, stream::Stream, Filter, Order, OutputResult::Entry, ParameterValue, }; use crate::probe::deep::{CheckParameterValue, FalseSceneResult, SceneResult, StreamProbeResult}; -use crate::stream::Stream as ContextStream; -use ffmpeg_sys_next::AVMediaType; use std::collections::HashMap; pub fn create_graph( @@ -67,6 +64,7 @@ pub fn detect_scene( streams: &mut [StreamProbeResult], video_indexes: Vec, params: HashMap, + frame_rate: f32, ) { let mut order = create_graph(filename, video_indexes.clone(), ¶ms).unwrap(); if let Err(msg) = order.setup() { @@ -82,21 +80,8 @@ pub fn detect_scene( Ok(results) => { info!("END OF PROCESS"); info!("-> {:?} frames processed", results.len()); - let mut frame_rate = 1.0; let mut scene_count = 0; - let mut context = FormatContext::new(filename).unwrap(); - if let Err(msg) = context.open_input() { - context.close_input(); - error!("{:?}", msg); - return; - } - for index in 0..context.get_nb_streams() { - if let Ok(stream) = ContextStream::new(context.get_stream(index as isize)) { - if let AVMediaType::AVMEDIA_TYPE_VIDEO = context.get_stream_type(index as isize) { - frame_rate = stream.get_frame_rate().to_float(); - } - } - } + for result in results { if let Entry(entry_map) = result { if let Some(stream_id) = entry_map.get("stream_id") { diff --git a/src/probe/silence_detect.rs b/src/probe/silence_detect.rs index e76484e..eb6ef9e 100644 --- a/src/probe/silence_detect.rs +++ b/src/probe/silence_detect.rs @@ -1,12 +1,9 @@ -use crate::format_context::FormatContext; use crate::order::{ filter_input::FilterInput, filter_output::FilterOutput, input::Input, input_kind::InputKind, output::Output, output_kind::OutputKind, stream::Stream, Filter, Order, OutputResult::Entry, ParameterValue, }; use crate::probe::deep::{CheckParameterValue, SilenceResult, StreamProbeResult}; -use crate::stream::Stream as ContextStream; -use ffmpeg_sys_next::AVMediaType; use std::collections::HashMap; pub fn create_graph( @@ -86,6 +83,8 @@ pub fn detect_silence( streams: &mut [StreamProbeResult], audio_indexes: Vec, params: HashMap, + frame_rate: f32, + frame_duration: f32, ) { let mut order = create_graph(filename, audio_indexes.clone(), ¶ms).unwrap(); if let Err(msg) = order.setup() { @@ -100,26 +99,11 @@ pub fn detect_silence( Ok(results) => { info!("END OF PROCESS"); info!("-> {:?} frames processed", results.len()); - let mut end_from_duration = 0; - let mut frame_duration = 0.0; - let mut context = FormatContext::new(filename).unwrap(); - if let Err(msg) = context.open_input() { - context.close_input(); - error!("{:?}", msg); - return; - } - for index in 0..context.get_nb_streams() { - if let Ok(stream) = ContextStream::new(context.get_stream(index as isize)) { - if let AVMediaType::AVMEDIA_TYPE_VIDEO = context.get_stream_type(index as isize) { - let frame_rate = stream.get_frame_rate().to_float() as f64; - frame_duration = stream.get_frame_rate().invert().to_float() as f64; - end_from_duration = - (((results.len() as f64 / audio_indexes.clone().len() as f64) - 1.0) / frame_rate - * 1000.0) - .round() as i64; - } - } - } + let end_from_duration = (((results.len() as f64 / audio_indexes.clone().len() as f64) - 1.0) + / frame_rate as f64 + * 1000.0) + .round() as i64; + let mut max_duration = None; if let Some(duration) = params.get("duration") { max_duration = duration.max; @@ -145,7 +129,7 @@ pub fn detect_silence( if let Some(value) = entry_map.get("lavfi.silence_end") { if let Some(last_detect) = detected_silence.last_mut() { last_detect.end = - ((value.parse::().unwrap() - frame_duration) * 1000.0).round() as i64; + ((value.parse::().unwrap() - frame_duration as f64) * 1000.0).round() as i64; } } if let Some(value) = entry_map.get("lavfi.silence_duration") { diff --git a/src/probe/sine_detect.rs b/src/probe/sine_detect.rs index 8f50f84..09d4355 100644 --- a/src/probe/sine_detect.rs +++ b/src/probe/sine_detect.rs @@ -95,6 +95,7 @@ pub fn detect_sine( streams: &mut [StreamProbeResult], audio_indexes: Vec, params: HashMap, + frame_rate: f32, ) { let mut order = create_graph(filename, audio_indexes.clone(), ¶ms).unwrap(); if let Err(msg) = order.setup() { @@ -109,8 +110,9 @@ pub fn detect_sine( Ok(results) => { info!("END OF PROCESS"); info!("-> {:?} frames processed", results.len()); - let mut end_from_duration = 0; - let mut frame_rate = 1.0; + let end_from_duration = + (((results.len() as f64 / audio_indexes.len() as f64) - 1.0) / frame_rate as f64 * 1000.0) + .round() as i64; let mut tracks: Vec> = Vec::new(); let mut sine: SineResult = Default::default(); let mut range_value: f64 = 1.0; //contains the range values to code a sample @@ -139,16 +141,6 @@ pub fn detect_sine( error!("{:?}", msg); return; } - for index in 0..context.get_nb_streams() { - if let Ok(stream) = ContextStream::new(context.get_stream(index as isize)) { - if let AVMediaType::AVMEDIA_TYPE_VIDEO = context.get_stream_type(index as isize) { - frame_rate = stream.get_frame_rate().to_float() as f64; - end_from_duration = - (((results.len() as f64 / audio_indexes.len() as f64) - 1.0) / frame_rate * 1000.0) - .round() as i64; - } - } - } for result in results { if let Entry(entry_map) = result { if let Some(stream_id) = entry_map.get("stream_id") { @@ -212,14 +204,15 @@ pub fn detect_sine( if last_start_opt.is_some() { if let Some(last_start) = last_start_opt { //check if audio ends => 1000Hz until the end - if (frame / frame_rate * 1000.0).round() as i64 == end_from_duration { + if (frame / frame_rate as f64 * 1000.0).round() as i64 == end_from_duration { sine.channel = channel; sine.start = *last_start; sine.end = end_from_duration; //check if sine is a 1000Hz => push and reset if let Some(zero_crossing) = zero_cross.get(&audio_stream_key.clone()) { - let sine_duration = - ((frame + 1.0) / frame_rate * 1000.0).round() as i64 - sine.start; + let sine_duration = ((frame + 1.0) / frame_rate as f64 * 1000.0).round() + as i64 + - sine.start; if (zero_crossing / sine_duration as f64) == 2.0 { detected_sine.push(sine); last_starts.insert(audio_stream_key.clone(), None); @@ -239,7 +232,7 @@ pub fn detect_sine( } } } else { - sine.start = (frame / frame_rate * 1000.0).round() as i64; + sine.start = (frame / frame_rate as f64 * 1000.0).round() as i64; last_starts.insert(audio_stream_key.clone(), Some(sine.start)); } } else if (2_f64.sqrt() - 1e-3_f64..2_f64.sqrt() + 1e-3_f64) @@ -249,9 +242,10 @@ pub fn detect_sine( if let Some(last_start) = last_start_opt { sine.channel = channel; sine.start = *last_start; - sine.end = ((frame - 1.0) / frame_rate * 1000.0).round() as i64; + sine.end = ((frame - 1.0) / frame_rate as f64 * 1000.0).round() as i64; //check if sine is a 1000Hz => push and reset - let sine_duration = (frame / frame_rate * 1000.0).round() as i64 - sine.start; + let sine_duration = + (frame / frame_rate as f64 * 1000.0).round() as i64 - sine.start; if let Some(zero_crossing) = zero_cross.get(&audio_stream_key) { if (zero_crossing / sine_duration as f64) == 2.0 { detected_sine.push(sine); From e63412cdfa59b6bd026c03a335b88e4a9e55cb6d Mon Sep 17 00:00:00 2001 From: Romane Lafon Date: Tue, 21 Nov 2023 12:02:39 +0100 Subject: [PATCH 5/5] use struct to pass video paramaters to detection --- src/probe/black_detect.rs | 21 +++++---- src/probe/crop_detect.rs | 33 ++++++-------- src/probe/deep.rs | 83 ++++++++++++++++++++---------------- src/probe/dualmono_detect.rs | 14 +++--- src/probe/ocr_detect.rs | 13 +++--- src/probe/silence_detect.rs | 14 +++--- src/tools/rational.rs | 2 +- 7 files changed, 93 insertions(+), 87 deletions(-) diff --git a/src/probe/black_detect.rs b/src/probe/black_detect.rs index afd1a12..e3c1056 100644 --- a/src/probe/black_detect.rs +++ b/src/probe/black_detect.rs @@ -4,7 +4,7 @@ use crate::{ output::Output, output_kind::OutputKind, stream::Stream, Filter, Order, OutputResult::Entry, ParameterValue, }, - probe::deep::{BlackResult, CheckParameterValue, StreamProbeResult}, + probe::deep::{BlackResult, CheckParameterValue, StreamProbeResult, VideoDetails}, }; use std::collections::HashMap; @@ -79,9 +79,7 @@ pub fn detect_black_frames( streams: &mut [StreamProbeResult], video_indexes: Vec, params: HashMap, - frame_rate: f32, - frame_duration: f32, - stream_duration: Option, + video_details: VideoDetails, ) { let mut order = create_graph(filename, video_indexes.clone(), params.clone()).unwrap(); if let Err(msg) = order.setup() { @@ -96,9 +94,9 @@ pub fn detect_black_frames( Ok(results) => { info!("END OF PROCESS"); info!("-> {:?} frames processed", results.len()); - let end_from_duration = match stream_duration { - Some(duration) => ((duration - frame_duration) * 1000.0).round() as i64, - None => ((results.len() as f32 - 1.0) / frame_rate * 1000.0).round() as i64, + let end_from_duration = match video_details.stream_duration { + Some(duration) => ((duration - video_details.frame_duration) * 1000.0).round() as i64, + None => ((results.len() as f32 - 1.0) / video_details.frame_rate * 1000.0).round() as i64, }; let mut max_duration = None; let mut min_duration = None; @@ -127,10 +125,11 @@ pub fn detect_black_frames( } if let Some(value) = entry_map.get("lavfi.black_end") { if let Some(last_detect) = detected_black.last_mut() { - last_detect.end = - ((value.parse::().unwrap() - frame_duration) * 1000.0).round() as i64; - let black_duration = - last_detect.end - last_detect.start + (frame_duration * 1000.0).round() as i64; + last_detect.end = ((value.parse::().unwrap() - video_details.frame_duration) + * 1000.0) + .round() as i64; + let black_duration = last_detect.end - last_detect.start + + (video_details.frame_duration * 1000.0).round() as i64; if let Some(max) = max_duration { if black_duration > max as i64 { detected_black.pop(); diff --git a/src/probe/crop_detect.rs b/src/probe/crop_detect.rs index dfb2625..aa54570 100644 --- a/src/probe/crop_detect.rs +++ b/src/probe/crop_detect.rs @@ -3,8 +3,7 @@ use crate::order::{ output::Output, output_kind::OutputKind, stream::Stream, }; use crate::order::{Filter, Order, OutputResult::Entry, ParameterValue}; -use crate::probe::deep::{CheckParameterValue, CropResult, StreamProbeResult}; -use crate::tools::rational::Rational; +use crate::probe::deep::{CheckParameterValue, CropResult, StreamProbeResult, VideoDetails}; use std::collections::HashMap; pub fn create_graph( @@ -88,16 +87,11 @@ pub fn detect_black_borders( streams: &mut [StreamProbeResult], video_indexes: Vec, params: HashMap, - stream_frames: Option, - bits_raw_sample: Option, - time_base: f32, - metadata_width: i32, - metadata_height: i32, - aspect_ratio: Rational, + video_details: VideoDetails, ) { - let nb_frames = stream_frames.unwrap_or(0); + let nb_frames = video_details.stream_frames.unwrap_or(0); // black threshold : 16 pour 8bits / 64 pour 10bits / 256 pour 12bits - let limit = match bits_raw_sample { + let limit = match video_details.bits_raw_sample { Some(10) => 64, Some(12) => 256, _ => 16, @@ -117,8 +111,8 @@ pub fn detect_black_borders( info!("-> {:?} frames processed", results.len()); let mut w_changed = false; let mut h_changed = false; - let mut real_width = metadata_width; - let mut real_height = metadata_height; + let mut real_width = video_details.metadata_width; + let mut real_height = video_details.metadata_height; for result in results { if let Entry(entry_map) = result { @@ -130,8 +124,8 @@ pub fn detect_black_borders( } let detected_crop = streams[(index) as usize].detected_crop.as_mut().unwrap(); let mut crop = CropResult { - width: metadata_width, - height: metadata_height, + width: video_details.metadata_width, + height: video_details.metadata_height, ..Default::default() }; if let (Some(x1), Some(x2)) = ( @@ -139,7 +133,7 @@ pub fn detect_black_borders( entry_map.get("lavfi.cropdetect.x2"), ) { let width = x2.parse::().unwrap() - x1.parse::().unwrap() + 1; - if width != metadata_width { + if width != video_details.metadata_width { w_changed = true; } real_width = width; @@ -149,7 +143,7 @@ pub fn detect_black_borders( entry_map.get("lavfi.cropdetect.y2"), ) { let height = y2.parse::().unwrap() - y1.parse::().unwrap() + 1; - if height != metadata_height { + if height != video_details.metadata_height { h_changed = true; } real_height = height; @@ -158,9 +152,10 @@ pub fn detect_black_borders( if w_changed || h_changed { crop.width = real_width; crop.height = real_height; - crop.pts = (pts.parse::().unwrap() * time_base * 1000.0).round() as i64; - let real_aspect = - (real_width * aspect_ratio.num) as f32 / (real_height * aspect_ratio.den) as f32; + crop.pts = + (pts.parse::().unwrap() * video_details.time_base * 1000.0).round() as i64; + let real_aspect = (real_width * video_details.aspect_ratio.num) as f32 + / (real_height * video_details.aspect_ratio.den) as f32; crop.aspect_ratio = real_aspect; detected_crop.push(crop); w_changed = false; diff --git a/src/probe/deep.rs b/src/probe/deep.rs index e26b693..e0e4ab4 100644 --- a/src/probe/deep.rs +++ b/src/probe/deep.rs @@ -174,6 +174,19 @@ pub struct DeepProbeCheck { pub sine_detect: Option>, } +#[derive(Clone, Debug, Default)] +pub struct VideoDetails { + pub frame_rate: f32, + pub time_base: f32, + pub frame_duration: f32, + pub stream_duration: Option, + pub stream_frames: Option, + pub bits_raw_sample: Option, + pub metadata_width: i32, + pub metadata_height: i32, + pub aspect_ratio: Rational, +} + impl fmt::Display for DeepProbeResult { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { for (index, stream) in self.streams.iter().enumerate() { @@ -301,6 +314,22 @@ impl Track { } } +impl VideoDetails { + pub fn new() -> Self { + VideoDetails { + frame_rate: 1.0, + time_base: 1.0, + frame_duration: 0.0, + stream_duration: None, + stream_frames: None, + bits_raw_sample: None, + metadata_width: 0, + metadata_height: 0, + aspect_ratio: Rational::new(1, 1), + } + } +} + impl DeepProbe { pub fn new(filename: &str, id: Uuid) -> Self { DeepProbe { @@ -331,15 +360,7 @@ impl DeepProbe { return Ok(()); } - let mut frame_duration = 0.0; - let mut frame_rate = 1.0; - let mut time_base = 1.0; - let mut metadata_width = 0; - let mut metadata_height = 0; - let mut stream_duration = None; - let mut stream_frames = None; - let mut bits_raw_sample = None; - let mut aspect_ratio = Rational::new(1, 1); + let mut video_details = VideoDetails::new(); let mut streams = vec![]; streams.resize(context.get_nb_streams() as usize, StreamProbeResult::new()); while let Ok(packet) = context.next_packet() { @@ -361,15 +382,15 @@ impl DeepProbe { streams[stream_index].color_primaries = stream.get_color_primaries(); streams[stream_index].color_trc = stream.get_color_trc(); streams[stream_index].color_matrix = stream.get_color_matrix(); - frame_duration = stream.get_frame_rate().invert().to_float(); - frame_rate = stream.get_frame_rate().to_float(); - time_base = stream.get_time_base().to_float(); - stream_duration = stream.get_duration(); - stream_frames = stream.get_nb_frames(); - bits_raw_sample = stream.get_bits_per_raw_sample(); - metadata_width = stream.get_width(); - metadata_height = stream.get_height(); - aspect_ratio = stream.get_picture_aspect_ratio(); + video_details.frame_duration = stream.get_frame_rate().invert().to_float(); + video_details.frame_rate = stream.get_frame_rate().to_float(); + video_details.time_base = stream.get_time_base().to_float(); + video_details.stream_duration = stream.get_duration(); + video_details.stream_frames = stream.get_nb_frames(); + video_details.bits_raw_sample = stream.get_bits_per_raw_sample(); + video_details.metadata_width = stream.get_width(); + video_details.metadata_height = stream.get_height(); + video_details.aspect_ratio = stream.get_picture_aspect_ratio(); } } } @@ -392,8 +413,7 @@ impl DeepProbe { &mut streams, audio_indexes.clone(), silence_parameters, - frame_rate, - frame_duration, + video_details.clone(), ); } @@ -403,9 +423,7 @@ impl DeepProbe { &mut streams, video_indexes.clone(), black_parameters, - frame_rate, - frame_duration, - stream_duration, + video_details.clone(), ); } @@ -416,7 +434,7 @@ impl DeepProbe { video_indexes.clone(), audio_indexes.clone(), black_and_silence_parameters, - frame_duration, + video_details.frame_duration, ); } } @@ -427,12 +445,7 @@ impl DeepProbe { &mut streams, video_indexes.clone(), crop_parameters, - stream_frames, - bits_raw_sample, - time_base, - metadata_width, - metadata_height, - aspect_ratio, + video_details.clone(), ); } @@ -442,7 +455,7 @@ impl DeepProbe { &mut streams, video_indexes.clone(), scene_parameters, - frame_rate, + video_details.frame_rate, ); } @@ -452,8 +465,7 @@ impl DeepProbe { &mut streams, video_indexes.clone(), ocr_parameters, - frame_rate, - stream_frames, + video_details.clone(), ); } @@ -478,8 +490,7 @@ impl DeepProbe { &mut streams, audio_indexes.clone(), dualmono_parameters, - frame_rate, - frame_duration, + video_details.clone(), ); } @@ -489,7 +500,7 @@ impl DeepProbe { &mut streams, audio_indexes, sine_parameters, - frame_rate, + video_details.frame_rate, ); } diff --git a/src/probe/dualmono_detect.rs b/src/probe/dualmono_detect.rs index 7fabaf8..2c2faf4 100644 --- a/src/probe/dualmono_detect.rs +++ b/src/probe/dualmono_detect.rs @@ -4,7 +4,7 @@ use crate::{ output::Output, output_kind::OutputKind, stream::Stream, Filter, Order, OutputResult::Entry, ParameterValue, }, - probe::deep::{CheckParameterValue, DualMonoResult, StreamProbeResult}, + probe::deep::{CheckParameterValue, DualMonoResult, StreamProbeResult, VideoDetails}, }; use std::collections::HashMap; @@ -116,8 +116,7 @@ pub fn detect_dualmono( streams: &mut [StreamProbeResult], audio_indexes: Vec, params: HashMap, - frame_rate: f32, - frame_duration: f32, + video_details: VideoDetails, ) { let mut order = create_graph(filename, ¶ms).unwrap(); let mut max_duration = None; @@ -155,7 +154,7 @@ pub fn detect_dualmono( } let end_from_duration = (((results.len() as f64 / audio_stream_qualif_number as f64) - 1.0) - / frame_rate as f64 + / video_details.frame_rate as f64 * 1000.0) .round() as i64; for result in results { @@ -181,7 +180,8 @@ pub fn detect_dualmono( if let Some(value) = entry_map.get("lavfi.aphasemeter.mono_end") { if let Some(last_detect) = detected_dualmono.last_mut() { last_detect.end = - ((value.parse::().unwrap() - frame_duration as f64) * 1000.0).round() as i64; + ((value.parse::().unwrap() - video_details.frame_duration as f64) * 1000.0) + .round() as i64; } } if let Some(value) = entry_map.get("lavfi.aphasemeter.mono_duration") { @@ -201,8 +201,8 @@ pub fn detect_dualmono( .as_mut() .unwrap(); if let Some(last_detect) = detected_dualmono.last() { - let duration = - last_detect.end - last_detect.start + (frame_duration * 1000.0).round() as i64; + let duration = last_detect.end - last_detect.start + + (video_details.frame_duration * 1000.0).round() as i64; if let Some(max) = max_duration { if duration > max as i64 { detected_dualmono.pop(); diff --git a/src/probe/ocr_detect.rs b/src/probe/ocr_detect.rs index 8672f1d..1bfe23b 100644 --- a/src/probe/ocr_detect.rs +++ b/src/probe/ocr_detect.rs @@ -3,7 +3,7 @@ use crate::order::{ output::Output, output_kind::OutputKind, stream::Stream, Filter, Order, OutputResult::Entry, ParameterValue, }; -use crate::probe::deep::{CheckParameterValue, OcrResult, StreamProbeResult}; +use crate::probe::deep::{CheckParameterValue, OcrResult, StreamProbeResult, VideoDetails}; use std::collections::HashMap; pub fn create_graph( @@ -77,8 +77,7 @@ pub fn detect_ocr( streams: &mut [StreamProbeResult], video_indexes: Vec, params: HashMap, - frame_rate: f32, - stream_frames: Option, + video_details: VideoDetails, ) { let mut order = create_graph(filename, video_indexes.clone(), ¶ms).unwrap(); if let Err(msg) = order.setup() { @@ -94,7 +93,7 @@ pub fn detect_ocr( info!("END OF PROCESS"); info!("-> {:?} frames processed", results.len()); let mut media_offline_detected = false; - let last_frame = stream_frames.unwrap_or(results.len() as i64) - 1; + let last_frame = video_details.stream_frames.unwrap_or(results.len() as i64) - 1; for result in results { if let Entry(entry_map) = result { @@ -115,7 +114,8 @@ pub fn detect_ocr( if media_offline_detected { if let Some(last_detect) = detected_ocr.last_mut() { if let Some(value) = entry_map.get("lavfi.scd.time") { - last_detect.frame_end = (value.parse::().unwrap() * frame_rate - 1.0) as u64; + last_detect.frame_end = + (value.parse::().unwrap() * video_details.frame_rate - 1.0) as u64; media_offline_detected = false; } } @@ -125,7 +125,8 @@ pub fn detect_ocr( media_offline_detected = true; ocr.text = value.to_string(); if let Some(value) = entry_map.get("lavfi.scd.time") { - ocr.frame_start = (value.parse::().unwrap() * frame_rate) as u64; + ocr.frame_start = + (value.parse::().unwrap() * video_details.frame_rate) as u64; } if let Some(value) = entry_map.get("lavfi.ocr.confidence") { let mut word_conf = value.to_string().replace(char::is_whitespace, "%,"); diff --git a/src/probe/silence_detect.rs b/src/probe/silence_detect.rs index eb6ef9e..6b4652d 100644 --- a/src/probe/silence_detect.rs +++ b/src/probe/silence_detect.rs @@ -3,7 +3,7 @@ use crate::order::{ output::Output, output_kind::OutputKind, stream::Stream, Filter, Order, OutputResult::Entry, ParameterValue, }; -use crate::probe::deep::{CheckParameterValue, SilenceResult, StreamProbeResult}; +use crate::probe::deep::{CheckParameterValue, SilenceResult, StreamProbeResult, VideoDetails}; use std::collections::HashMap; pub fn create_graph( @@ -83,8 +83,7 @@ pub fn detect_silence( streams: &mut [StreamProbeResult], audio_indexes: Vec, params: HashMap, - frame_rate: f32, - frame_duration: f32, + video_details: VideoDetails, ) { let mut order = create_graph(filename, audio_indexes.clone(), ¶ms).unwrap(); if let Err(msg) = order.setup() { @@ -100,7 +99,7 @@ pub fn detect_silence( info!("END OF PROCESS"); info!("-> {:?} frames processed", results.len()); let end_from_duration = (((results.len() as f64 / audio_indexes.clone().len() as f64) - 1.0) - / frame_rate as f64 + / video_details.frame_rate as f64 * 1000.0) .round() as i64; @@ -129,7 +128,8 @@ pub fn detect_silence( if let Some(value) = entry_map.get("lavfi.silence_end") { if let Some(last_detect) = detected_silence.last_mut() { last_detect.end = - ((value.parse::().unwrap() - frame_duration as f64) * 1000.0).round() as i64; + ((value.parse::().unwrap() - video_details.frame_duration as f64) * 1000.0) + .round() as i64; } } if let Some(value) = entry_map.get("lavfi.silence_duration") { @@ -152,8 +152,8 @@ pub fn detect_silence( } if let Some(max) = max_duration { if let Some(last_detect) = detected_silence.last() { - let silence_duration = - last_detect.end - last_detect.start + (frame_duration * 1000.0).round() as i64; + let silence_duration = last_detect.end - last_detect.start + + (video_details.frame_duration * 1000.0).round() as i64; if silence_duration > max as i64 { detected_silence.pop(); } diff --git a/src/tools/rational.rs b/src/tools/rational.rs index c5e5e33..a5aef24 100644 --- a/src/tools/rational.rs +++ b/src/tools/rational.rs @@ -1,7 +1,7 @@ use ffmpeg_sys_next::*; use std::mem::swap; -#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)] +#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] pub struct Rational { pub num: i32, pub den: i32,