diff --git a/CHANGELOG.md b/CHANGELOG.md index 026409a..8683b96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +# Unreleased +* crf-search: Tweak 2nd iteration logic that slices the crf range at the 25% or 75% crf point. + - Widen to 20%/80% to account for searches of the "middle" two subranges being more optimal. + - Disable when using custom min/max crf ranges under half the default. + # v0.7.19 * Fix stdin handling sometimes breaking bash shells. diff --git a/Cargo.lock b/Cargo.lock index 1b975ba..d6797ec 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -48,9 +48,9 @@ checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "anstream" -version = "0.6.17" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23a1e53f0f5d86382dafe1cf314783b2044280f406e7e1506368220ad11b1338" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" dependencies = [ "anstyle", "anstyle-parse", @@ -63,9 +63,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8365de52b16c035ff4fcafe0092ba9390540e3e352870ac09933bebcaa2c8c56" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "anstyle-parse" @@ -97,9 +97,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.92" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74f37166d7d48a0284b99dd824694c26119c700b53bf0d1540cdb147dbdaaf13" +checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" [[package]] name = "arrayref" @@ -195,9 +195,9 @@ checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" [[package]] name = "cc" -version = "1.1.31" +version = "1.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f" +checksum = "baee610e9452a8f6f0a1b6194ec09ff9e2d85dea54432acdae41aa0761c95d70" dependencies = [ "shlex", ] @@ -233,9 +233,9 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.5.36" +version = "4.5.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86bc73de94bc81e52f3bebec71bc4463e9748f7a59166663e32044669577b0e2" +checksum = "11611dca53440593f38e6b25ec629de50b14cdfa63adc0fb856115a2c6d97595" dependencies = [ "clap", ] @@ -377,9 +377,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" +checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" [[package]] name = "ffprobe" @@ -582,9 +582,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.161" +version = "0.2.162" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" +checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398" [[package]] name = "libredox" @@ -767,9 +767,9 @@ checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustix" -version = "0.38.38" +version = "0.38.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa260229e6538e52293eeb577aabd09945a09d6d9cc0fc550ed7529056c2e32a" +checksum = "375116bee2be9ed569afe2154ea6a99dfdffd257f533f187498c2a8f5feaf4ee" dependencies = [ "bitflags 2.6.0", "errno", @@ -882,9 +882,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" -version = "2.0.86" +version = "2.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89275301d38033efb81a6e60e3497e734dfcc62571f2854bf4b16690398824c" +checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" dependencies = [ "proc-macro2", "quote", @@ -903,18 +903,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.66" +version = "1.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d171f59dbaa811dbbb1aee1e73db92ec2b122911a48e1390dfe327a821ddede" +checksum = "02dd99dc800bbb97186339685293e1cc5d9df1f8fae2d0aecd9ff1c77efea892" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.66" +version = "1.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b08be0f17bd307950653ce45db00cd31200d82b624b36e181337d9c7d92765b5" +checksum = "a7c61ec9a6f64d2793d8a45faba21efbe3ced62a886d44c36a009b2b519b4c7e" dependencies = [ "proc-macro2", "quote", @@ -953,9 +953,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.41.0" +version = "1.41.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "145f3413504347a2be84393cc8a7d2fb4d863b375909ea59f2158261aa258bbb" +checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" dependencies = [ "backtrace", "bytes", diff --git a/src/command/crf_search.rs b/src/command/crf_search.rs index d84b4c5..3028a5b 100644 --- a/src/command/crf_search.rs +++ b/src/command/crf_search.rs @@ -21,6 +21,7 @@ use std::{ }; const BAR_LEN: u64 = 1_000_000_000; +const DEFAULT_MIN_CRF: f32 = 10.0; /// Interpolated binary search using sample-encode to find the best crf /// value delivering min-vmaf & max-encoded-percent. @@ -46,12 +47,12 @@ pub struct Args { pub max_encoded_percent: f32, /// Minimum (highest quality) crf value to try. - #[arg(long, default_value_t = 10.0)] + #[arg(long, default_value_t = DEFAULT_MIN_CRF)] pub min_crf: f32, /// Maximum (lowest quality) crf value to try. /// - /// [default: 55, 46 for x264,x265, 255 for rav1e] + /// [default: 55, 46 for x264,x265, 255 for rav1e,av1_vaapi] #[arg(long)] pub max_crf: Option, @@ -144,9 +145,20 @@ async fn _run( input_probe: Arc, bar: ProgressBar, ) -> Result { - let max_crf = max_crf.unwrap_or_else(|| args.encoder.default_max_crf()); + let default_max_crf = args.encoder.default_max_crf(); + let max_crf = max_crf.unwrap_or(default_max_crf); ensure_other!(*min_crf < max_crf, "Invalid --min-crf & --max-crf"); + // Whether to make the 2nd iteration on the ~20%/~80% crf point instead of the min/max to + // improve interpolation by narrowing the crf range a 20% (or 30%) subrange. + // + // 20/80% is preferred to 25/75% to account for searches in the "middle" benefitting from + // having both bounds computed after the 2nd iteration, whereas the two edges must compute + // the min/max crf on the 3rd iter. + // + // If a custom crf range is being used under half the default, this 2nd cut is not needed. + let cut_on_iter2 = (max_crf - *min_crf) > (default_max_crf - DEFAULT_MIN_CRF) * 0.5; + let crf_increment = crf_increment .unwrap_or_else(|| args.encoder.default_crf_increment()) .max(0.001); @@ -230,8 +242,8 @@ async fn _run( ensure_or_no_good_crf!(sample_small_enough, sample); return Ok(sample); } - None if run == 1 && sample.q + 1 < max_q => { - q = (sample.q + max_q) / 2; + None if cut_on_iter2 && run == 1 && sample.q + 1 < max_q => { + q = (sample.q as f32 * 0.4 + max_q as f32 * 0.6).round() as _; } None => q = max_q, }; @@ -257,8 +269,8 @@ async fn _run( Some(lower) => { q = vmaf_lerp_q(*min_vmaf, &sample, lower); } - None if run == 1 && sample.q > min_q + 1 => { - q = (min_q + sample.q) / 2; + None if cut_on_iter2 && run == 1 && sample.q > min_q + 1 => { + q = (sample.q as f32 * 0.4 + min_q as f32 * 0.6).round() as _; } None => q = min_q, };