-
Notifications
You must be signed in to change notification settings - Fork 176
Fix FFmpeg VMAF fails to validate even when Target Quality is not used #1103
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
Conversation
Add Zones validation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #1103 +/- ##
==========================================
- Coverage 62.31% 61.98% -0.34%
==========================================
Files 23 23
Lines 6303 6410 +107
==========================================
+ Hits 3928 3973 +45
- Misses 2375 2437 +62 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
fix confirmed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR fixes an issue where FFmpeg VMAF validation was being performed even when Target Quality was not used. The changes ensure that Target Metric validation only occurs when --target-quality
is supplied or when at least one Zone has Target Quality enabled.
- Extracted metric validation logic into reusable methods in
EncodeArgs
- Added a new
validate_zones
function to validate Target Metrics used in zones - Moved zone validation to occur after parsing all zones
Reviewed Changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.
File | Description |
---|---|
av1an-core/src/zones.rs | Adds new validate_zones function that conditionally validates Target Metrics based on zone configurations |
av1an-core/src/settings.rs | Refactors metric validation logic into separate methods and adds conditional validation for global target quality |
av1an-core/src/context.rs | Integrates zone validation after zone parsing |
av1an-core/src/zones.rs
Outdated
.and_then(|tq| tq.target.as_ref().filter(|_| tq.metric == TargetMetric::SSIMULACRA2)) | ||
.is_some() | ||
}) { | ||
args.validate_ssimululacra2()?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Method name 'validate_ssimululacra2' contains a typo - should be 'validate_ssimulacra2' (missing 'u' in 'ssimulacra')
args.validate_ssimululacra2()?; | |
args.validate_ssimulacra2()?; |
Copilot uses AI. Check for mistakes.
av1an-core/src/settings.rs
Outdated
} | ||
|
||
#[inline] | ||
pub fn validate_ssimululacra2(&self) -> anyhow::Result<()> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Function name 'validate_ssimululacra2' contains a typo - should be 'validate_ssimulacra2' (missing 'u' in 'ssimulacra')
pub fn validate_ssimululacra2(&self) -> anyhow::Result<()> { | |
pub fn validate_ssimulacra2(&self) -> anyhow::Result<()> { |
Copilot uses AI. Check for mistakes.
av1an-core/src/settings.rs
Outdated
if self.target_quality.target.is_some() { | ||
match self.target_quality.metric { | ||
TargetMetric::VMAF => validate_libvmaf()?, | ||
TargetMetric::SSIMULACRA2 => self.validate_ssimululacra2()?, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Method call 'validate_ssimululacra2' contains a typo - should be 'validate_ssimulacra2' (missing 'u' in 'ssimulacra')
TargetMetric::SSIMULACRA2 => self.validate_ssimululacra2()?, | |
TargetMetric::SSIMULACRA2 => self.validate_ssimulacra2()?, |
Copilot uses AI. Check for mistakes.
pub(crate) fn validate_zones(args: &EncodeArgs, zones: &[Scene]) -> anyhow::Result<()> { | ||
if zones.is_empty() { | ||
// No zones to validate | ||
return Ok(()); | ||
} | ||
|
||
// Using VMAF, validate libvmaf | ||
if zones.iter().any(|zone| { | ||
zone.zone_overrides | ||
.as_ref() | ||
.and_then(|ovr| ovr.target_quality.as_ref()) | ||
.and_then(|tq| tq.target.as_ref().filter(|_| tq.metric == TargetMetric::VMAF)) | ||
.is_some() | ||
}) { | ||
validate_libvmaf()?; | ||
} | ||
|
||
// Using SSIMULACRA2, validate SSIMULACRA2 | ||
if zones.iter().any(|zone| { | ||
zone.zone_overrides | ||
.as_ref() | ||
.and_then(|ovr| ovr.target_quality.as_ref()) | ||
.and_then(|tq| tq.target.as_ref().filter(|_| tq.metric == TargetMetric::SSIMULACRA2)) | ||
.is_some() | ||
}) { | ||
args.validate_ssimululacra2()?; | ||
} | ||
|
||
// Using butteraugli-Inf, validate butteraugli-Inf | ||
if zones.iter().any(|zone| { | ||
zone.zone_overrides | ||
.as_ref() | ||
.and_then(|ovr| ovr.target_quality.as_ref()) | ||
.and_then(|tq| tq.target.as_ref().filter(|_| tq.metric == TargetMetric::ButteraugliINF)) | ||
.is_some() | ||
}) { | ||
args.validate_butteraugli_inf()?; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The validation logic has significant code duplication across all metric checks. Consider extracting a helper function that takes a predicate to reduce repetition and improve maintainability.
pub(crate) fn validate_zones(args: &EncodeArgs, zones: &[Scene]) -> anyhow::Result<()> { | |
if zones.is_empty() { | |
// No zones to validate | |
return Ok(()); | |
} | |
// Using VMAF, validate libvmaf | |
if zones.iter().any(|zone| { | |
zone.zone_overrides | |
.as_ref() | |
.and_then(|ovr| ovr.target_quality.as_ref()) | |
.and_then(|tq| tq.target.as_ref().filter(|_| tq.metric == TargetMetric::VMAF)) | |
.is_some() | |
}) { | |
validate_libvmaf()?; | |
} | |
// Using SSIMULACRA2, validate SSIMULACRA2 | |
if zones.iter().any(|zone| { | |
zone.zone_overrides | |
.as_ref() | |
.and_then(|ovr| ovr.target_quality.as_ref()) | |
.and_then(|tq| tq.target.as_ref().filter(|_| tq.metric == TargetMetric::SSIMULACRA2)) | |
.is_some() | |
}) { | |
args.validate_ssimululacra2()?; | |
} | |
// Using butteraugli-Inf, validate butteraugli-Inf | |
if zones.iter().any(|zone| { | |
zone.zone_overrides | |
.as_ref() | |
.and_then(|ovr| ovr.target_quality.as_ref()) | |
.and_then(|tq| tq.target.as_ref().filter(|_| tq.metric == TargetMetric::ButteraugliINF)) | |
.is_some() | |
}) { | |
args.validate_butteraugli_inf()?; | |
} | |
fn validate_metric_in_zones<F>( | |
zones: &[Scene], | |
metric: TargetMetric, | |
validate_fn: F, | |
) -> anyhow::Result<()> | |
where | |
F: Fn() -> anyhow::Result<()>, | |
{ | |
if zones.iter().any(|zone| { | |
zone.zone_overrides | |
.as_ref() | |
.and_then(|ovr| ovr.target_quality.as_ref()) | |
.and_then(|tq| tq.target.as_ref().filter(|_| tq.metric == metric)) | |
.is_some() | |
}) { | |
validate_fn()?; | |
} | |
Ok(()) | |
} | |
pub(crate) fn validate_zones(args: &EncodeArgs, zones: &[Scene]) -> anyhow::Result<()> { | |
if zones.is_empty() { | |
// No zones to validate | |
return Ok(()); | |
} | |
// Using VMAF, validate libvmaf | |
validate_metric_in_zones(zones, TargetMetric::VMAF, || validate_libvmaf())?; | |
// Using SSIMULACRA2, validate SSIMULACRA2 | |
validate_metric_in_zones(zones, TargetMetric::SSIMULACRA2, || args.validate_ssimululacra2())?; | |
// Using butteraugli-Inf, validate butteraugli-Inf | |
validate_metric_in_zones(zones, TargetMetric::ButteraugliINF, || args.validate_butteraugli_inf())?; |
Copilot uses AI. Check for mistakes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should have done this the Rust Idiomatic way in the first place.
The comments from copilot seem valid, if you wouldn't mind fixing those, then we can merge. |
Add ensure_chunk_method to consolidate ChunkMethod checks Add generic tq_used_and functions to consolidate condition checks for Zones Target Quality validation
Resolves #1102
Target Metric VMAF is now only validated if the user supplies
--target-quality
or specifies at least 1 Zone where Target Quality is enabled. Zones are now validated after parsing so any issues with a specified Target Metric can be addressed in the new function.I initially wanted to cache the validation as I planned to validate each Zone as it's parsed but instead went with parsing all Zones, then doing a filter check for the exact condition(s) that require validation. At worst, XPSNR could be validated up to 3 times, 2 for everything else. With the function only executing up to a maximum of 3 times, I decided to forgo complicating things with lazy loading and caching.
Thanks,
- Boats M.