Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Complete loudness results #59

Merged
merged 4 commits into from
Jun 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions .github/workflows/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
FROM ubuntu:22.04

RUN apt-get update

RUN apt-get install -y autoconf \
automake \
build-essential \
clang \
cmake \
git-core \
libfreetype6-dev \
libgnutls28-dev \
libsdl2-dev \
libssl-dev \
libtool \
libva-dev \
libvdpau-dev \
libunistring-dev \
libxcb1-dev \
libxcb-shm0-dev \
libxcb-xfixes0-dev \
meson \
ninja-build \
pkg-config \
texinfo \
wget \
yasm \
zlib1g-dev

# ffmpeg 5.0.1 libav => codec59.18.100 device59.4.100 filter8.24.100 format59.16.100 util57.17.100
RUN wget -q http://ffmpeg.org/releases/ffmpeg-5.0.1.tar.gz && \
tar xf ffmpeg-5.0.1.tar.gz && \
cd ffmpeg-5.0.1 && \
PATH="/bin:$PATH" PKG_CONFIG_PATH="/usr/lib/pkgconfig" \
./configure --pkg-config-flags="--static" --extra-cflags="-I/usr/include" --extra-ldflags="-L/usr/lib" --extra-libs="-lpthread -lm" --ld="g++" --bindir="/bin" \
--enable-gpl --enable-gnutls --enable-libfreetype --enable-nonfree && \
PATH="/bin:$PATH" make -j32 && \
make install
43 changes: 10 additions & 33 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,22 @@ jobs:
build_and_test:
# The type of runner that the job will run on
runs-on: ubuntu-22.04
container: nomalab/ffmpeg:5.0.1 # image made from Dockerfile in directory

continue-on-error: ${{ (matrix.rust == 'beta') || (matrix.rust == 'nightly') }}

strategy:
fail-fast: false
matrix:
rust: [
1.69.0,
1.70.0,
1.71.0,
1.72.0,
1.73.0,
1.74.0,
1.75.0,
1.76.0,
1.77.0,
1.78.0,
stable,
beta,
nightly
Expand All @@ -37,18 +41,6 @@ jobs:
steps:
- uses: actions/checkout@v3

- name: Install libs
run: >-
sudo apt-get update &&
sudo apt-get install libasound2-dev libavcodec-dev
libavformat-dev libavutil-dev libavdevice-dev libavfilter-dev
libpostproc-dev libswscale-dev -y

- name: Setup FFmpeg
uses: Iamshankhadeep/[email protected]
with:
version: "5.0"

- name: Install Rust
uses: actions-rs/toolchain@v1
with:
Expand Down Expand Up @@ -81,17 +73,11 @@ jobs:

clippy:
runs-on: ubuntu-22.04
container: nomalab/ffmpeg:5.0.1

steps:
- uses: actions/checkout@v3

- name: Install libs
run: >-
sudo apt-get update &&
sudo apt-get install libasound2-dev libavcodec-dev
libavformat-dev libavutil-dev libavdevice-dev libavfilter-dev
libpostproc-dev libswscale-dev -y

- name: Install Rust with clippy
uses: actions-rs/toolchain@v1
with:
Expand All @@ -105,22 +91,13 @@ jobs:

tarpaulin:
runs-on: ubuntu-22.04
container:
image: nomalab/ffmpeg:5.0.1
options: --security-opt seccomp=unconfined

steps:
- uses: actions/checkout@v3

- name: Install libs
run: >-
sudo apt-get update &&
sudo apt-get install libasound2-dev libavcodec-dev
libavformat-dev libavutil-dev libavdevice-dev libavfilter-dev
libpostproc-dev libswscale-dev -y

- name: Setup FFmpeg
uses: Iamshankhadeep/[email protected]
with:
version: "5.0"

- name: Install Rust
uses: actions-rs/toolchain@v1
with:
Expand Down
2 changes: 1 addition & 1 deletion examples/deep_probe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ fn main() {
};
let spot_check = CheckParameterValue {
min: None,
max: Some(3),
max: Some(5),
num: None,
den: None,
th: None,
Expand Down
22 changes: 19 additions & 3 deletions src/probe/deep.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,18 @@ pub struct OcrResult {
pub word_confidence: String,
}

#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)]
pub struct MinMax {
pub min: f64,
pub max: f64,
}

#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)]
pub struct LoudnessResult {
pub integrated: f64,
pub range: f64,
pub momentary: MinMax,
pub short_term: MinMax,
pub true_peaks: Vec<f64>,
}

Expand Down Expand Up @@ -130,7 +138,7 @@ pub struct StreamProbeResult {
#[serde(skip_serializing_if = "Option::is_none")]
pub detected_ocr: Option<Vec<OcrResult>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub detected_loudness: Option<Vec<LoudnessResult>>,
pub detected_loudness: Option<LoudnessResult>,
#[serde(skip_serializing_if = "Option::is_none")]
pub detected_dualmono: Option<Vec<DualMonoResult>>,
#[serde(skip_serializing_if = "Option::is_none")]
Expand Down Expand Up @@ -194,6 +202,7 @@ pub struct VideoDetails {
pub metadata_width: i32,
pub metadata_height: i32,
pub aspect_ratio: Rational,
pub sample_rate: i32,
}

#[derive(Default)]
Expand Down Expand Up @@ -303,8 +312,8 @@ impl StreamProbeResult {
color_primaries: None,
color_trc: None,
color_matrix: None,
min_packet_size: std::i32::MAX,
max_packet_size: std::i32::MIN,
min_packet_size: i32::MAX,
max_packet_size: i32::MIN,
detected_silence: None,
silent_stream: None,
detected_black: None,
Expand Down Expand Up @@ -360,6 +369,7 @@ impl VideoDetails {
metadata_width: 0,
metadata_height: 0,
aspect_ratio: Rational::new(1, 1),
sample_rate: 0,
}
}
}
Expand Down Expand Up @@ -430,6 +440,11 @@ impl DeepProbe {
deep_orders.video_details.aspect_ratio = stream.get_picture_aspect_ratio();
}
}
if context.get_stream_type(stream_index as isize) == AVMediaType::AVMEDIA_TYPE_AUDIO {
if let Ok(stream) = Stream::new(context.get_stream(stream_index as isize)) {
deep_orders.video_details.sample_rate = stream.get_sample_rate();
}
}
}
}

Expand Down Expand Up @@ -624,6 +639,7 @@ impl DeepProbe {
&mut deep_orders.streams,
deep_orders.audio_indexes.clone(),
params,
deep_orders.video_details.clone(),
)
}
}
Expand Down
77 changes: 56 additions & 21 deletions src/probe/loudness_detect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ use crate::order::{
output::Output, output_kind::OutputKind, stream::Stream, Filter, Order, OutputResult::Entry,
ParameterValue,
};
use crate::probe::deep::{CheckName, CheckParameterValue, LoudnessResult, StreamProbeResult};
use crate::probe::deep::{
CheckName, CheckParameterValue, LoudnessResult, MinMax, StreamProbeResult, VideoDetails,
};
use ffmpeg_sys_next::log10;
use std::collections::{BTreeMap, HashMap};

Expand All @@ -27,11 +29,12 @@ pub fn create_graph<S: ::std::hash::BuildHasher>(
let mut outputs = vec![];
let mut filters = vec![];

let metadata_param = ParameterValue::Bool(true);
let true_param = ParameterValue::Bool(true);
let peak_param = ParameterValue::String("true".to_string());
let mut loudnessdetect_params: HashMap<String, ParameterValue> = HashMap::new();
loudnessdetect_params.insert("metadata".to_string(), metadata_param);
loudnessdetect_params.insert("metadata".to_string(), true_param.clone());
loudnessdetect_params.insert("peak".to_string(), peak_param);
loudnessdetect_params.insert("dualmono".to_string(), true_param);

match params.get("pairing_list") {
Some(pairing_list) => {
Expand All @@ -40,7 +43,12 @@ pub fn create_graph<S: ::std::hash::BuildHasher>(
let mut amerge_params: HashMap<String, ParameterValue> = HashMap::new();
let mut amerge_input = vec![];
let mut input_streams_vec = vec![];
let mut lavfi_keys = vec!["lavfi.r128.I".to_string(), "lavfi.r128.LRA".to_string()];
let mut lavfi_keys = vec![
"lavfi.r128.I".to_string(),
"lavfi.r128.LRA".to_string(),
"lavfi.r128.S".to_string(),
"lavfi.r128.M".to_string(),
];
let output_label = format!("output_label_{iter:?}");

for track in pair {
Expand Down Expand Up @@ -124,9 +132,22 @@ pub fn detect_loudness<S: ::std::hash::BuildHasher>(
streams: &mut [StreamProbeResult],
audio_indexes: Vec<u32>,
params: HashMap<String, CheckParameterValue, S>,
video_details: VideoDetails,
) {
for index in audio_indexes {
streams[index as usize].detected_loudness = Some(vec![]);
for index in audio_indexes.clone() {
streams[index as usize].detected_loudness = Some(LoudnessResult {
range: -99.9,
integrated: -99.9,
true_peaks: vec![],
momentary: MinMax {
min: 99.9,
max: -99.9,
},
short_term: MinMax {
min: 99.9,
max: -99.9,
},
});
}
let results = output_results.get(&CheckName::Loudness).unwrap();
info!("END OF LOUDNESS PROCESS");
Expand All @@ -144,24 +165,37 @@ pub fn detect_loudness<S: ::std::hash::BuildHasher>(
.detected_loudness
.as_mut()
.unwrap();
let mut loudness = LoudnessResult {
range: -99.9,
integrated: -99.9,
true_peaks: vec![],
};
let mut channel_start = 0;
let mut channel_end = 0;
let mut pts_time: f32 = 0.0;
if let Some(pts) = entry_map.get("pts") {
pts_time = pts.parse::<f32>().unwrap() / video_details.sample_rate as f32;
}

if let Some(value) = entry_map.get("lavfi.r128.I") {
let x = value.parse::<f64>().unwrap();
loudness.integrated = (x * 100.0).round() / 100.0;
if loudness.integrated == -70.0 {
loudness.integrated = -99.0;
let i = value.parse::<f64>().unwrap();
detected_loudness.integrated = (i * 100.0).round() / 100.0;
if detected_loudness.integrated == -70.0 {
detected_loudness.integrated = -99.0;
}
}
if let Some(value) = entry_map.get("lavfi.r128.LRA") {
let y = value.parse::<f64>().unwrap();
loudness.range = (y * 100.0).round() / 100.0;
let lra = value.parse::<f64>().unwrap();
detected_loudness.range = (lra * 100.0).round() / 100.0;
}
if let Some(value) = entry_map.get("lavfi.r128.S") {
if pts_time >= 2.9 {
let s = (value.parse::<f64>().unwrap() * 100.0).round() / 100.0;
detected_loudness.short_term.min = f64::min(detected_loudness.short_term.min, s);
detected_loudness.short_term.max = f64::max(detected_loudness.short_term.max, s);
}
}
if let Some(value) = entry_map.get("lavfi.r128.M") {
if pts_time >= 0.3 {
let m = (value.parse::<f64>().unwrap() * 100.0).round() / 100.0;
detected_loudness.momentary.min = f64::min(detected_loudness.momentary.min, m);
detected_loudness.momentary.max = f64::max(detected_loudness.momentary.max, m);
}
}

match params.get("pairing_list") {
Expand All @@ -184,22 +218,23 @@ pub fn detect_loudness<S: ::std::hash::BuildHasher>(
}
None => warn!("No input message for the loudness analysis (audio qualification)"),
}
let mut tpks = vec![];
for i in channel_start..channel_end {
let str_tpk_key = format!("lavfi.r128.true_peaks_ch{i}");
if let Some(value) = entry_map.get(&str_tpk_key) {
let energy = value.parse::<f64>().unwrap();
unsafe {
let mut tpk = 20.0 * log10(energy);
tpk = (tpk * 100.0).round() / 100.0;
if tpk == std::f64::NEG_INFINITY {
if tpk == f64::NEG_INFINITY {
tpk = -99.00;
}
loudness.true_peaks.push(tpk);
tpks.push(tpk)
}
}
}
detected_loudness.drain(..);
detected_loudness.push(loudness);
detected_loudness.true_peaks.drain(..);
detected_loudness.true_peaks = tpks;
}
}
}
Expand Down
Loading
Loading