Skip to content

Commit

Permalink
Merge pull request #45 from nomalab/fix_deep_probe_last_frame
Browse files Browse the repository at this point in the history
Fix deep probe last frame
  • Loading branch information
Romanelaf authored Nov 21, 2023
2 parents bc2b3bf + e63412c commit 04dcb94
Show file tree
Hide file tree
Showing 12 changed files with 173 additions and 231 deletions.
3 changes: 2 additions & 1 deletion src/probe/black_and_silence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pub fn detect_black_and_silence(
video_indexes: Vec<u32>,
audio_indexes: Vec<u32>,
params: HashMap<String, CheckParameterValue>,
frame_duration: f32,
) {
let mut bas = BlackAndSilenceResult { start: 0, end: 0 };
let mut duration_min = None;
Expand Down Expand Up @@ -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()
Expand Down
39 changes: 13 additions & 26 deletions src/probe/black_detect.rs
Original file line number Diff line number Diff line change
@@ -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,
probe::deep::{BlackResult, CheckParameterValue, StreamProbeResult, VideoDetails},
};
use ffmpeg_sys_next::AVMediaType;
use std::collections::HashMap;

pub fn create_graph(
Expand Down Expand Up @@ -82,6 +79,7 @@ pub fn detect_black_frames(
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() {
Expand All @@ -96,31 +94,17 @@ pub fn detect_black_frames(
Ok(results) => {
info!("END OF PROCESS");
info!("-> {:?} frames processed", results.len());
let mut duration = 0;
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;
}
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();
if let Some(stream_duration) = stream.get_duration() {
duration = (stream_duration * 1000.0) as i64;
} else {
duration = (results.len() as f32 / frame_rate * 1000.0) as i64;
}
}
}
}

for result in results {
if let Entry(entry_map) = result {
if let Some(stream_id) = entry_map.get("stream_id") {
Expand All @@ -132,7 +116,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") {
Expand All @@ -141,8 +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::<f32>().unwrap() * 1000.0).round() as i64;
let black_duration = last_detect.end - last_detect.start;
last_detect.end = ((value.parse::<f32>().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();
Expand Down
73 changes: 19 additions & 54 deletions src/probe/crop_detect.rs
Original file line number Diff line number Diff line change
@@ -1,13 +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,
};
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 crate::probe::deep::{CheckParameterValue, CropResult, StreamProbeResult, VideoDetails};
use std::collections::HashMap;

pub fn create_graph(
Expand Down Expand Up @@ -91,31 +87,15 @@ pub fn detect_black_borders(
streams: &mut [StreamProbeResult],
video_indexes: Vec<u32>,
params: HashMap<String, CheckParameterValue>,
video_details: VideoDetails,
) {
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 = video_details.stream_frames.unwrap_or(0);
// black threshold : 16 pour 8bits / 64 pour 10bits / 256 pour 12bits
let limit = match video_details.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);
Expand All @@ -129,27 +109,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 = video_details.metadata_width;
let mut real_height = video_details.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") {
Expand All @@ -160,16 +124,16 @@ 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)) = (
entry_map.get("lavfi.cropdetect.x1"),
entry_map.get("lavfi.cropdetect.x2"),
) {
let width = x2.parse::<i32>().unwrap() - x1.parse::<i32>().unwrap() + 1;
if width != metadata_width {
if width != video_details.metadata_width {
w_changed = true;
}
real_width = width;
Expand All @@ -179,7 +143,7 @@ pub fn detect_black_borders(
entry_map.get("lavfi.cropdetect.y2"),
) {
let height = y2.parse::<i32>().unwrap() - y1.parse::<i32>().unwrap() + 1;
if height != metadata_height {
if height != video_details.metadata_height {
h_changed = true;
}
real_height = height;
Expand All @@ -188,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::<f32>().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;
crop.pts =
(pts.parse::<f32>().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;
Expand Down
55 changes: 54 additions & 1 deletion src/probe/deep.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -173,6 +174,19 @@ pub struct DeepProbeCheck {
pub sine_detect: Option<HashMap<String, CheckParameterValue>>,
}

#[derive(Clone, Debug, Default)]
pub struct VideoDetails {
pub frame_rate: f32,
pub time_base: f32,
pub frame_duration: f32,
pub stream_duration: Option<f32>,
pub stream_frames: Option<i64>,
pub bits_raw_sample: Option<i32>,
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() {
Expand Down Expand Up @@ -300,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 {
Expand Down Expand Up @@ -330,6 +360,7 @@ impl DeepProbe {
return Ok(());
}

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() {
Expand All @@ -351,6 +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();
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();
}
}
}
Expand All @@ -373,6 +413,7 @@ impl DeepProbe {
&mut streams,
audio_indexes.clone(),
silence_parameters,
video_details.clone(),
);
}

Expand All @@ -382,6 +423,7 @@ impl DeepProbe {
&mut streams,
video_indexes.clone(),
black_parameters,
video_details.clone(),
);
}

Expand All @@ -392,6 +434,7 @@ impl DeepProbe {
video_indexes.clone(),
audio_indexes.clone(),
black_and_silence_parameters,
video_details.frame_duration,
);
}
}
Expand All @@ -402,6 +445,7 @@ impl DeepProbe {
&mut streams,
video_indexes.clone(),
crop_parameters,
video_details.clone(),
);
}

Expand All @@ -411,6 +455,7 @@ impl DeepProbe {
&mut streams,
video_indexes.clone(),
scene_parameters,
video_details.frame_rate,
);
}

Expand All @@ -420,6 +465,7 @@ impl DeepProbe {
&mut streams,
video_indexes.clone(),
ocr_parameters,
video_details.clone(),
);
}

Expand All @@ -444,11 +490,18 @@ impl DeepProbe {
&mut streams,
audio_indexes.clone(),
dualmono_parameters,
video_details.clone(),
);
}

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,
video_details.frame_rate,
);
}

let mut format = FormatProbeResult::new();
Expand Down
Loading

0 comments on commit 04dcb94

Please sign in to comment.