From f5ddee1d44adca0f7e05392974e85b2a71ad6719 Mon Sep 17 00:00:00 2001 From: WhitePeter Date: Fri, 26 Jul 2024 01:07:51 +0200 Subject: [PATCH 1/2] vmaf: Don't force input frame rate. Remove the input option `-r` from ffmpeg command and rely on PTS of the respective containers. Add `settb` filter to establish common timebase for different containers. Different timestamp syncing: Use the absolute nearest timestamp for frame selection in libvmaf. Also stop at the end of the shortest stream, which sometimes helps with n_subsample>1 when, for some reason, ffmpeg fails with no score to parse. Both options can be overridden by `--vmaf`. In case the VMAF score obtained using this new approach are lower than expected, adding `--vmaf ts_sync_mode=default` should be tried. --- src/command/args/vmaf.rs | 70 ++++++++++++++++++++-------------------- src/vmaf.rs | 4 +-- 2 files changed, 37 insertions(+), 37 deletions(-) diff --git a/src/command/args/vmaf.rs b/src/command/args/vmaf.rs index 929a6b2..3f1817f 100644 --- a/src/command/args/vmaf.rs +++ b/src/command/args/vmaf.rs @@ -65,7 +65,7 @@ impl Vmaf { ); } let mut lavfi = args.join(":"); - lavfi.insert_str(0, "libvmaf="); + lavfi.insert_str(0, "libvmaf=shortest=true:ts_sync_mode=nearest:"); let mut model = VmafModel::from_args(&args); if let (None, Some((w, h))) = (model, distorted_res) { @@ -89,13 +89,13 @@ impl Vmaf { // * sync presentation timestamp let prefix = if let Some((w, h)) = self.vf_scale(model.unwrap_or_default(), distorted_res) { format!( - "[0:v]format={pix_fmt},scale={w}:{h}:flags=bicubic,setpts=PTS-STARTPTS[dis];\ - [1:v]format={pix_fmt},{ref_vf}scale={w}:{h}:flags=bicubic,setpts=PTS-STARTPTS[ref];[dis][ref]" + "[0:v]format={pix_fmt},scale={w}:{h}:flags=bicubic,setpts=PTS-STARTPTS,settb=AVTB[dis];\ + [1:v]format={pix_fmt},{ref_vf}scale={w}:{h}:flags=bicubic,setpts=PTS-STARTPTS,settb=AVTB[ref];[dis][ref]" ) } else { format!( - "[0:v]format={pix_fmt},setpts=PTS-STARTPTS[dis];\ - [1:v]format={pix_fmt},{ref_vf}setpts=PTS-STARTPTS[ref];[dis][ref]" + "[0:v]format={pix_fmt},setpts=PTS-STARTPTS,settb=AVTB[dis];\ + [1:v]format={pix_fmt},{ref_vf}setpts=PTS-STARTPTS,settb=AVTB[ref];[dis][ref]" ) }; @@ -208,9 +208,9 @@ fn vmaf_lavfi() { }; assert_eq!( vmaf.ffmpeg_lavfi(None, PixelFormat::Yuv420p, Some("scale=1280:-1,fps=24")), - "[0:v]format=yuv420p,setpts=PTS-STARTPTS[dis];\ - [1:v]format=yuv420p,scale=1280:-1,fps=24,setpts=PTS-STARTPTS[ref];\ - [dis][ref]libvmaf=n_threads=5:n_subsample=4" + "[0:v]format=yuv420p,setpts=PTS-STARTPTS,settb=AVTB[dis];\ + [1:v]format=yuv420p,scale=1280:-1,fps=24,setpts=PTS-STARTPTS,settb=AVTB[ref];\ + [dis][ref]libvmaf=shortest=true:ts_sync_mode=nearest:n_threads=5:n_subsample=4" ); } @@ -227,9 +227,9 @@ fn vmaf_lavfi_override_reference_vfilter() { PixelFormat::Yuv420p, Some("scale_vaapi=w=2560:h=1280") ), - "[0:v]format=yuv420p,setpts=PTS-STARTPTS[dis];\ - [1:v]format=yuv420p,scale=2560:-1,setpts=PTS-STARTPTS[ref];\ - [dis][ref]libvmaf=n_threads=5:n_subsample=4" + "[0:v]format=yuv420p,setpts=PTS-STARTPTS,settb=AVTB[dis];\ + [1:v]format=yuv420p,scale=2560:-1,setpts=PTS-STARTPTS,settb=AVTB[ref];\ + [dis][ref]libvmaf=shortest=true:ts_sync_mode=nearest:n_threads=5:n_subsample=4" ); } @@ -241,9 +241,9 @@ fn vmaf_lavfi_default() { reference_vfilter: None, }; let expected = format!( - "[0:v]format=yuv420p10le,setpts=PTS-STARTPTS[dis];\ - [1:v]format=yuv420p10le,setpts=PTS-STARTPTS[ref];\ - [dis][ref]libvmaf=n_threads={}", + "[0:v]format=yuv420p10le,setpts=PTS-STARTPTS,settb=AVTB[dis];\ + [1:v]format=yuv420p10le,setpts=PTS-STARTPTS,settb=AVTB[ref];\ + [dis][ref]libvmaf=shortest=true:ts_sync_mode=nearest:n_threads={}", thread::available_parallelism().map_or(1, |p| p.get()) ); assert_eq!( @@ -260,9 +260,9 @@ fn vmaf_lavfi_include_n_threads() { reference_vfilter: None, }; let expected = format!( - "[0:v]format=yuv420p,setpts=PTS-STARTPTS[dis];\ - [1:v]format=yuv420p,setpts=PTS-STARTPTS[ref];\ - [dis][ref]libvmaf=log_path=output.xml:n_threads={}", + "[0:v]format=yuv420p,setpts=PTS-STARTPTS,settb=AVTB[dis];\ + [1:v]format=yuv420p,setpts=PTS-STARTPTS,settb=AVTB[ref];\ + [dis][ref]libvmaf=shortest=true:ts_sync_mode=nearest:log_path=output.xml:n_threads={}", thread::available_parallelism().map_or(1, |p| p.get()) ); assert_eq!( @@ -281,9 +281,9 @@ fn vmaf_lavfi_small_width() { }; assert_eq!( vmaf.ffmpeg_lavfi(Some((1280, 720)), PixelFormat::Yuv420p, None), - "[0:v]format=yuv420p,scale=1920:-1:flags=bicubic,setpts=PTS-STARTPTS[dis];\ - [1:v]format=yuv420p,scale=1920:-1:flags=bicubic,setpts=PTS-STARTPTS[ref];\ - [dis][ref]libvmaf=n_threads=5:n_subsample=4" + "[0:v]format=yuv420p,scale=1920:-1:flags=bicubic,setpts=PTS-STARTPTS,settb=AVTB[dis];\ + [1:v]format=yuv420p,scale=1920:-1:flags=bicubic,setpts=PTS-STARTPTS,settb=AVTB[ref];\ + [dis][ref]libvmaf=shortest=true:ts_sync_mode=nearest:n_threads=5:n_subsample=4" ); } @@ -297,9 +297,9 @@ fn vmaf_lavfi_4k() { }; assert_eq!( vmaf.ffmpeg_lavfi(Some((3840, 2160)), PixelFormat::Yuv420p, None), - "[0:v]format=yuv420p,setpts=PTS-STARTPTS[dis];\ - [1:v]format=yuv420p,setpts=PTS-STARTPTS[ref];\ - [dis][ref]libvmaf=n_threads=5:n_subsample=4:model=version=vmaf_4k_v0.6.1" + "[0:v]format=yuv420p,setpts=PTS-STARTPTS,settb=AVTB[dis];\ + [1:v]format=yuv420p,setpts=PTS-STARTPTS,settb=AVTB[ref];\ + [dis][ref]libvmaf=shortest=true:ts_sync_mode=nearest:n_threads=5:n_subsample=4:model=version=vmaf_4k_v0.6.1" ); } @@ -313,9 +313,9 @@ fn vmaf_lavfi_3k_upscale_to_4k() { }; assert_eq!( vmaf.ffmpeg_lavfi(Some((3008, 1692)), PixelFormat::Yuv420p, None), - "[0:v]format=yuv420p,scale=3840:-1:flags=bicubic,setpts=PTS-STARTPTS[dis];\ - [1:v]format=yuv420p,scale=3840:-1:flags=bicubic,setpts=PTS-STARTPTS[ref];\ - [dis][ref]libvmaf=n_threads=5:model=version=vmaf_4k_v0.6.1" + "[0:v]format=yuv420p,scale=3840:-1:flags=bicubic,setpts=PTS-STARTPTS,settb=AVTB[dis];\ + [1:v]format=yuv420p,scale=3840:-1:flags=bicubic,setpts=PTS-STARTPTS,settb=AVTB[ref];\ + [dis][ref]libvmaf=shortest=true:ts_sync_mode=nearest:n_threads=5:model=version=vmaf_4k_v0.6.1" ); } @@ -333,9 +333,9 @@ fn vmaf_lavfi_small_width_custom_model() { }; assert_eq!( vmaf.ffmpeg_lavfi(Some((1280, 720)), PixelFormat::Yuv420p, None), - "[0:v]format=yuv420p,setpts=PTS-STARTPTS[dis];\ - [1:v]format=yuv420p,setpts=PTS-STARTPTS[ref];\ - [dis][ref]libvmaf=model=version=foo:n_threads=5:n_subsample=4" + "[0:v]format=yuv420p,setpts=PTS-STARTPTS,settb=AVTB[dis];\ + [1:v]format=yuv420p,setpts=PTS-STARTPTS,settb=AVTB[ref];\ + [dis][ref]libvmaf=shortest=true:ts_sync_mode=nearest:model=version=foo:n_threads=5:n_subsample=4" ); } @@ -356,9 +356,9 @@ fn vmaf_lavfi_custom_model_and_width() { }; assert_eq!( vmaf.ffmpeg_lavfi(Some((1280, 720)), PixelFormat::Yuv420p, None), - "[0:v]format=yuv420p,scale=123:-1:flags=bicubic,setpts=PTS-STARTPTS[dis];\ - [1:v]format=yuv420p,scale=123:-1:flags=bicubic,setpts=PTS-STARTPTS[ref];\ - [dis][ref]libvmaf=model=version=foo:n_threads=5:n_subsample=4" + "[0:v]format=yuv420p,scale=123:-1:flags=bicubic,setpts=PTS-STARTPTS,settb=AVTB[dis];\ + [1:v]format=yuv420p,scale=123:-1:flags=bicubic,setpts=PTS-STARTPTS,settb=AVTB[ref];\ + [dis][ref]libvmaf=shortest=true:ts_sync_mode=nearest:model=version=foo:n_threads=5:n_subsample=4" ); } @@ -371,8 +371,8 @@ fn vmaf_lavfi_1080p() { }; assert_eq!( vmaf.ffmpeg_lavfi(Some((1920, 1080)), PixelFormat::Yuv420p, None), - "[0:v]format=yuv420p,setpts=PTS-STARTPTS[dis];\ - [1:v]format=yuv420p,setpts=PTS-STARTPTS[ref];\ - [dis][ref]libvmaf=n_threads=5:n_subsample=4" + "[0:v]format=yuv420p,setpts=PTS-STARTPTS,settb=AVTB[dis];\ + [1:v]format=yuv420p,setpts=PTS-STARTPTS,settb=AVTB[ref];\ + [dis][ref]libvmaf=shortest=true:ts_sync_mode=nearest:n_threads=5:n_subsample=4" ); } diff --git a/src/vmaf.rs b/src/vmaf.rs index 0f39e02..69704d3 100644 --- a/src/vmaf.rs +++ b/src/vmaf.rs @@ -22,9 +22,9 @@ pub fn run( let mut cmd = Command::new("ffmpeg"); cmd.kill_on_drop(true) - .arg2("-r", "24") + // .arg2("-r", "24") .arg2("-i", distorted) - .arg2("-r", "24") + // .arg2("-r", "24") .arg2("-i", reference) .arg2("-filter_complex", filter_complex) .arg2("-f", "null") From c8195966c99e558f30b461bf00d42c41d0a793f4 Mon Sep 17 00:00:00 2001 From: Alex Butler Date: Sat, 27 Jul 2024 10:08:13 +0100 Subject: [PATCH 2/2] Apply suggestions from code review remove commented out lines --- src/vmaf.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/vmaf.rs b/src/vmaf.rs index 69704d3..f32468b 100644 --- a/src/vmaf.rs +++ b/src/vmaf.rs @@ -22,9 +22,7 @@ pub fn run( let mut cmd = Command::new("ffmpeg"); cmd.kill_on_drop(true) - // .arg2("-r", "24") .arg2("-i", distorted) - // .arg2("-r", "24") .arg2("-i", reference) .arg2("-filter_complex", filter_complex) .arg2("-f", "null")