Skip to content

Commit

Permalink
vmaf: Don't force input frame rate. (#215)
Browse files Browse the repository at this point in the history
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.

---------

Co-authored-by: Alex Butler <alexheretic@gmail.com>
  • Loading branch information
WhitePeter and alexheretic authored Jul 27, 2024
1 parent 49a6415 commit a7b1f03
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 37 deletions.
70 changes: 35 additions & 35 deletions src/command/args/vmaf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,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) {
Expand All @@ -99,13 +99,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]"
)
};

Expand Down Expand Up @@ -213,9 +213,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"
);
}

Expand All @@ -232,9 +232,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"
);
}

Expand All @@ -246,9 +246,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!(
Expand All @@ -265,9 +265,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!(
Expand All @@ -286,9 +286,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"
);
}

Expand All @@ -302,9 +302,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"
);
}

Expand All @@ -318,9 +318,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"
);
}

Expand All @@ -338,9 +338,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"
);
}

Expand All @@ -361,9 +361,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"
);
}

Expand All @@ -376,8 +376,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"
);
}
2 changes: 0 additions & 2 deletions src/vmaf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down

0 comments on commit a7b1f03

Please sign in to comment.