diff --git a/src/enc/frame.c b/src/enc/frame.c index dd345ed0..3566d81c 100644 --- a/src/enc/frame.c +++ b/src/enc/frame.c @@ -695,7 +695,7 @@ int VP8EncLoop(VP8Encoder* const enc) { VP8EncIterator it; VP8ModeScore info; const int dont_use_skip = !enc->proba_.use_skip_proba_; - const int rd_opt = enc->rd_opt_level_; + const VP8RDLevel rd_opt = enc->rd_opt_level_; const int kAverageBytesPerMB = 5; // TODO: have a kTable[quality/10] const int bytes_per_parts = enc->mb_w_ * enc->mb_h_ * kAverageBytesPerMB / enc->num_parts_; @@ -762,8 +762,8 @@ int VP8EncLoop(VP8Encoder* const enc) { #define kHeaderSizeEstimate (15 + 20 + 10) // TODO: fix better -static int OneStatPass(VP8Encoder* const enc, float q, int rd_opt, int nb_mbs, - float* const PSNR, int percent_delta) { +static int OneStatPass(VP8Encoder* const enc, float q, VP8RDLevel rd_opt, + int nb_mbs, float* const PSNR, int percent_delta) { VP8EncIterator it; uint64_t size = 0; uint64_t distortion = 0; @@ -829,7 +829,7 @@ int VP8StatLoop(VP8Encoder* const enc) { // No target size: just do several pass without changing 'q' if (!do_search) { for (pass = 0; pass < max_passes; ++pass) { - const int rd_opt = (enc->method_ > 2); + const VP8RDLevel rd_opt = (enc->method_ > 2) ? RD_OPT_BASIC : RD_OPT_NONE; if (!OneStatPass(enc, q, rd_opt, nb_mbs, NULL, percent_per_pass)) { return 0; } @@ -837,10 +837,9 @@ int VP8StatLoop(VP8Encoder* const enc) { } else { // binary search for a size close to target for (pass = 0; pass < max_passes && (dqs[pass] > 0); ++pass) { - const int rd_opt = 1; float PSNR; int criterion; - const int size = OneStatPass(enc, q, rd_opt, nb_mbs, &PSNR, + const int size = OneStatPass(enc, q, RD_OPT_BASIC, nb_mbs, &PSNR, percent_per_pass); #if DEBUG_SEARCH printf("#%d size=%d PSNR=%.2f q=%.2f\n", pass, size, PSNR, q); diff --git a/src/enc/quant.c b/src/enc/quant.c index 4fbfef47..d74fa373 100644 --- a/src/enc/quant.c +++ b/src/enc/quant.c @@ -956,7 +956,8 @@ static void SimpleQuantize(VP8EncIterator* const it, VP8ModeScore* const rd) { //------------------------------------------------------------------------------ // Entry point -int VP8Decimate(VP8EncIterator* const it, VP8ModeScore* const rd, int rd_opt) { +int VP8Decimate(VP8EncIterator* const it, VP8ModeScore* const rd, + VP8RDLevel rd_opt) { int is_skipped; InitScore(rd); @@ -966,16 +967,14 @@ int VP8Decimate(VP8EncIterator* const it, VP8ModeScore* const rd, int rd_opt) { VP8MakeLuma16Preds(it); VP8MakeChroma8Preds(it); - // for rd_opt = 2, we perform trellis-quant on the final decision only. - // for rd_opt > 2, we use it for every scoring (=much slower). - if (rd_opt > 0) { - it->do_trellis_ = (rd_opt > 2); + if (rd_opt > RD_OPT_NONE) { + it->do_trellis_ = (rd_opt >= RD_OPT_TRELLIS_ALL); PickBestIntra16(it, rd); if (it->enc_->method_ >= 2) { PickBestIntra4(it, rd); } PickBestUV(it, rd); - if (rd_opt == 2) { + if (rd_opt == RD_OPT_TRELLIS) { // finish off with trellis-optim now it->do_trellis_ = 1; SimpleQuantize(it, rd); } diff --git a/src/enc/vp8enci.h b/src/enc/vp8enci.h index abd1957a..153f9e51 100644 --- a/src/enc/vp8enci.h +++ b/src/enc/vp8enci.h @@ -57,6 +57,13 @@ enum { NUM_MB_SEGMENTS = 4, MAX_VARIABLE_LEVEL = 67 // last (inclusive) level with variable cost }; +typedef enum { // Rate-distortion optimization levels + RD_OPT_NONE = 0, // no rd-opt + RD_OPT_BASIC = 1, // basic scoring (no trellis) + RD_OPT_TRELLIS = 2, // perform trellis-quant on the final decision only + RD_OPT_TRELLIS_ALL = 3 // trellis-quant for every scoring (much slower) +} VP8RDLevel; + // YUV-cache parameters. Cache is 16-pixels wide. // The original or reconstructed samples can be accessed using VP8Scan[] // The predicted blocks can be accessed using offsets to yuv_p_ and @@ -405,9 +412,9 @@ struct VP8Encoder { int block_count_[3]; // quality/speed settings - int method_; // 0=fastest, 6=best/slowest. - int rd_opt_level_; // Deduced from method_. - int max_i4_header_bits_; // partition #0 safeness factor + int method_; // 0=fastest, 6=best/slowest. + VP8RDLevel rd_opt_level_; // Deduced from method_. + int max_i4_header_bits_; // partition #0 safeness factor // Memory VP8MBInfo* mb_info_; // contextual macroblock infos (mb_w_ + 1) @@ -486,7 +493,8 @@ int VP8EncAnalyze(VP8Encoder* const enc); // Sets up segment's quantization values, base_quant_ and filter strengths. void VP8SetSegmentParams(VP8Encoder* const enc, float quality); // Pick best modes and fills the levels. Returns true if skipped. -int VP8Decimate(VP8EncIterator* const it, VP8ModeScore* const rd, int rd_opt); +int VP8Decimate(VP8EncIterator* const it, VP8ModeScore* const rd, + VP8RDLevel rd_opt); // in alpha.c void VP8EncInitAlpha(VP8Encoder* const enc); // initialize alpha compression diff --git a/src/enc/webpenc.c b/src/enc/webpenc.c index 3c275589..48ab4b39 100644 --- a/src/enc/webpenc.c +++ b/src/enc/webpenc.c @@ -114,10 +114,10 @@ static void MapConfigToTools(VP8Encoder* const enc) { const int method = enc->config_->method; const int limit = 100 - enc->config_->partition_limit; enc->method_ = method; - enc->rd_opt_level_ = (method >= 6) ? 3 - : (method >= 5) ? 2 - : (method >= 3) ? 1 - : 0; + enc->rd_opt_level_ = (method >= 6) ? RD_OPT_TRELLIS_ALL + : (method >= 5) ? RD_OPT_TRELLIS + : (method >= 3) ? RD_OPT_BASIC + : RD_OPT_NONE; enc->max_i4_header_bits_ = 256 * 16 * 16 * // upper bound: up to 16bit per 4x4 block (limit * limit) / (100 * 100); // ... modulated with a quadratic curve.