Skip to content

Commit

Permalink
Merge pull request #47 from nomalab/add_fade_to_black_detection
Browse files Browse the repository at this point in the history
Add fade to black detection
  • Loading branch information
Bramart authored Nov 22, 2023
2 parents 05d4df9 + bc56057 commit 386c912
Show file tree
Hide file tree
Showing 6 changed files with 200 additions and 12 deletions.
33 changes: 31 additions & 2 deletions examples/deep_probe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,39 @@ fn main() {
max: None,
num: None,
den: None,
th: Some(0.1),
th: Some(0.0),
pairs: None,
};
let black_picture_params = CheckParameterValue {
min: None,
max: None,
num: None,
den: None,
th: Some(0.98),
th: Some(1.0),
pairs: None,
};
let blackfade_duration_params = CheckParameterValue {
min: Some(40),
max: None,
num: None,
den: None,
th: None,
pairs: None,
};
let blackfade_pixel_params = CheckParameterValue {
min: None,
max: None,
num: None,
den: None,
th: Some(0.5),
pairs: None,
};
let blackfade_picture_params = CheckParameterValue {
min: None,
max: None,
num: None,
den: None,
th: Some(1.0),
pairs: None,
};
let spot_check = CheckParameterValue {
Expand Down Expand Up @@ -127,6 +151,7 @@ fn main() {

let mut silence_params = HashMap::new();
let mut black_params = HashMap::new();
let mut blackfade_params = HashMap::new();
let mut select_params = HashMap::new();
let mut black_and_silence_params = HashMap::new();
let mut scene_params = HashMap::new();
Expand All @@ -138,6 +163,9 @@ fn main() {
black_params.insert("duration".to_string(), black_duration_params);
black_params.insert("picture".to_string(), black_picture_params);
black_params.insert("pixel".to_string(), black_pixel_params);
blackfade_params.insert("duration".to_string(), blackfade_duration_params);
blackfade_params.insert("picture".to_string(), blackfade_picture_params);
blackfade_params.insert("pixel".to_string(), blackfade_pixel_params);
select_params.insert("spot_check".to_string(), spot_check);
loudness_params.insert("pairing_list".to_string(), loudness_check);
dualmono_params.insert("duration".to_string(), dualmono_duration_check.clone());
Expand All @@ -150,6 +178,7 @@ fn main() {
let check = DeepProbeCheck {
silence_detect: Some(silence_params),
black_detect: Some(black_params),
blackfade_detect: Some(blackfade_params),
crop_detect: Some(select_params),
black_and_silence_detect: Some(black_and_silence_params),
scene_detect: Some(scene_params),
Expand Down
102 changes: 102 additions & 0 deletions src/probe/blackfade_detect.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
use super::black_detect::create_graph;
use crate::{
order::OutputResult::Entry,
probe::deep::{BlackFadeResult, CheckParameterValue, StreamProbeResult, VideoDetails},
};
use std::collections::HashMap;

pub fn detect_blackfade(
filename: &str,
streams: &mut [StreamProbeResult],
video_indexes: Vec<u32>,
params: HashMap<String, CheckParameterValue>,
video_details: VideoDetails,
) {
let mut order = create_graph(filename, video_indexes.clone(), params.clone()).unwrap();
if let Err(msg) = order.setup() {
error!("{:?}", msg);
return;
}
for index in video_indexes.clone() {
streams[index as usize].detected_blackfade = Some(vec![]);
}

match order.process() {
Ok(results) => {
info!("END OF PROCESS");
info!("-> {:?} frames processed", results.len());
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;
if let Some(duration) = params.get("duration") {
max_duration = duration.max;
min_duration = duration.min;
}

for result in results {
if let Entry(entry_map) = result {
if let Some(stream_id) = entry_map.get("stream_id") {
let index: i32 = stream_id.parse().unwrap();
if streams[(index) as usize].detected_blackfade.is_none() {
error!("Error : unexpected detection on stream ${index}");
break;
}
let detected_blackfade = streams[(index) as usize]
.detected_blackfade
.as_mut()
.unwrap();
let mut blackfade = BlackFadeResult {
start: 0,
end: end_from_duration,
};

if let Some(value) = entry_map.get("lavfi.black_start") {
blackfade.start = (value.parse::<f32>().unwrap() * 1000.0).round() as i64;
detected_blackfade.push(blackfade.clone());
}
if let Some(value) = entry_map.get("lavfi.black_end") {
if let Some(last_detect) = detected_blackfade.last_mut() {
last_detect.end = ((value.parse::<f32>().unwrap() - video_details.frame_duration)
* 1000.0)
.round() as i64;
let blackfade_duration = last_detect.end - last_detect.start
+ (video_details.frame_duration * 1000.0).round() as i64;
let detected_black = streams[index as usize].detected_black.clone();
let mut fade = false;
if let Some(blackframes) = detected_black {
for blackframe in blackframes {
if (last_detect.start < blackframe.start && blackframe.start <= last_detect.end)
|| (last_detect.start <= blackframe.end && blackframe.end < last_detect.end)
{
fade = true;
}
}
}
if !fade {
detected_blackfade.pop();
} else {
if let Some(max) = max_duration {
if blackfade_duration > max as i64 {
detected_blackfade.pop();
}
}
if let Some(min) = min_duration {
if blackfade_duration < min as i64 {
detected_blackfade.pop();
}
}
}
}
}
}
}
}
}
Err(msg) => {
error!("ERROR: {}", msg);
}
}
}
59 changes: 57 additions & 2 deletions src/probe/deep.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::format_context::FormatContext;
use crate::probe::black_and_silence::detect_black_and_silence;
use crate::probe::black_detect::detect_black_frames;
use crate::probe::blackfade_detect::detect_blackfade;
use crate::probe::crop_detect::detect_black_borders;
use crate::probe::dualmono_detect::detect_dualmono;
use crate::probe::loudness_detect::detect_loudness;
Expand Down Expand Up @@ -42,6 +43,12 @@ pub struct BlackResult {
pub end: i64,
}

#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
pub struct BlackFadeResult {
pub start: i64,
pub end: i64,
}

#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
pub struct BlackAndSilenceResult {
pub start: i64,
Expand Down Expand Up @@ -114,6 +121,8 @@ pub struct StreamProbeResult {
#[serde(skip_serializing_if = "Option::is_none")]
pub detected_black: Option<Vec<BlackResult>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub detected_blackfade: Option<Vec<BlackFadeResult>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub detected_crop: Option<Vec<CropResult>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub detected_scene: Option<Vec<SceneResult>>,
Expand Down Expand Up @@ -165,6 +174,7 @@ pub struct CheckParameterValue {
pub struct DeepProbeCheck {
pub silence_detect: Option<HashMap<String, CheckParameterValue>>,
pub black_detect: Option<HashMap<String, CheckParameterValue>>,
pub blackfade_detect: Option<HashMap<String, CheckParameterValue>>,
pub black_and_silence_detect: Option<HashMap<String, CheckParameterValue>>,
pub crop_detect: Option<HashMap<String, CheckParameterValue>>,
pub scene_detect: Option<HashMap<String, CheckParameterValue>>,
Expand Down Expand Up @@ -221,6 +231,11 @@ impl fmt::Display for DeepProbeResult {
"Silence detection", stream.detected_silence
)?;
writeln!(f, "{:30} : {:?}", "Black detection", stream.detected_black)?;
writeln!(
f,
"{:30} : {:?}",
"Blackfade detection", stream.detected_blackfade
)?;
writeln!(
f,
"{:30} : {:?}",
Expand Down Expand Up @@ -274,6 +289,7 @@ impl StreamProbeResult {
detected_silence: None,
silent_stream: None,
detected_black: None,
detected_blackfade: None,
detected_black_and_silence: None,
detected_crop: None,
detected_scene: None,
Expand Down Expand Up @@ -427,6 +443,16 @@ impl DeepProbe {
);
}

if let Some(blackfade_parameters) = check.blackfade_detect {
detect_blackfade(
&self.filename,
&mut streams,
video_indexes.clone(),
blackfade_parameters,
video_details.clone(),
);
}

if let Some(black_and_silence_parameters) = check.black_and_silence_detect {
if check.black_detect.is_some() && check.silence_detect.is_some() {
detect_black_and_silence(
Expand Down Expand Up @@ -541,15 +567,39 @@ fn deep_probe() {
max: None,
num: None,
den: None,
th: Some(0.1),
th: Some(0.0),
pairs: None,
};
let black_picture_params = CheckParameterValue {
min: None,
max: None,
num: None,
den: None,
th: Some(0.98),
th: Some(1.0),
pairs: None,
};
let blackfade_duration_params = CheckParameterValue {
min: Some(40),
max: None,
num: None,
den: None,
th: None,
pairs: None,
};
let blackfade_pixel_params = CheckParameterValue {
min: None,
max: None,
num: None,
den: None,
th: Some(0.5),
pairs: None,
};
let blackfade_picture_params = CheckParameterValue {
min: None,
max: None,
num: None,
den: None,
th: Some(1.0),
pairs: None,
};
let spot_check = CheckParameterValue {
Expand Down Expand Up @@ -635,6 +685,7 @@ fn deep_probe() {

let mut silence_params = HashMap::new();
let mut black_params = HashMap::new();
let mut blackfade_params = HashMap::new();
let mut select_params = HashMap::new();
let mut black_and_silence_params = HashMap::new();
let mut scene_params = HashMap::new();
Expand All @@ -646,6 +697,9 @@ fn deep_probe() {
black_params.insert("duration".to_string(), black_duration_params);
black_params.insert("picture".to_string(), black_picture_params);
black_params.insert("pixel".to_string(), black_pixel_params);
blackfade_params.insert("duration".to_string(), blackfade_duration_params);
blackfade_params.insert("picture".to_string(), blackfade_picture_params);
blackfade_params.insert("pixel".to_string(), blackfade_pixel_params);
select_params.insert("spot_check".to_string(), spot_check);
loudness_params.insert("pairing_list".to_string(), loudness_check);
dualmono_params.insert("duration".to_string(), dualmono_duration_check.clone());
Expand All @@ -658,6 +712,7 @@ fn deep_probe() {
let check = DeepProbeCheck {
silence_detect: Some(silence_params),
black_detect: Some(black_params),
blackfade_detect: Some(blackfade_params),
crop_detect: Some(select_params),
black_and_silence_detect: Some(black_and_silence_params),
scene_detect: Some(scene_params),
Expand Down
1 change: 1 addition & 0 deletions src/probe/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
mod black_and_silence;
mod black_detect;
mod blackfade_detect;
mod crop_detect;
pub mod deep;
mod dualmono_detect;
Expand Down
17 changes: 9 additions & 8 deletions tests/deep_probe.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,22 @@
"end": 14920
}
],
"detected_scene": [
"detected_blackfade": [
{
"frame_index": 124,
"score": 33,
"scene_number": 1
},
"start": 0,
"end": 5560
}
],
"detected_scene": [
{
"frame_index": 249,
"score": 31,
"scene_number": 2
"scene_number": 1
},
{
"frame_index": 374,
"score": 33,
"scene_number": 3
"scene_number": 2
}
],
"detected_false_scene": [],
Expand Down Expand Up @@ -344,7 +345,7 @@
}
],
"format": {
"detected_bitrate_format": 13973326
"detected_bitrate_format": 14329064
}
}
}
Binary file modified tests/test_file.mxf
Binary file not shown.

0 comments on commit 386c912

Please sign in to comment.