OLD | NEW |
1 // Copyright 2011 Google Inc. All Rights Reserved. | 1 // Copyright 2011 Google Inc. All Rights Reserved. |
2 // | 2 // |
3 // This code is licensed under the same terms as WebM: | 3 // This code is licensed under the same terms as WebM: |
4 // Software License Agreement: http://www.webmproject.org/license/software/ | 4 // Software License Agreement: http://www.webmproject.org/license/software/ |
5 // Additional IP Rights Grant: http://www.webmproject.org/license/additional/ | 5 // Additional IP Rights Grant: http://www.webmproject.org/license/additional/ |
6 // ----------------------------------------------------------------------------- | 6 // ----------------------------------------------------------------------------- |
7 // | 7 // |
8 // Quantization | 8 // Quantization |
9 // | 9 // |
10 // Author: Skal (pascal.massimino@gmail.com) | 10 // Author: Skal (pascal.massimino@gmail.com) |
11 | 11 |
12 #include <assert.h> | 12 #include <assert.h> |
13 #include <math.h> | 13 #include <math.h> |
14 | 14 |
15 #include "./vp8enci.h" | 15 #include "./vp8enci.h" |
16 #include "./cost.h" | 16 #include "./cost.h" |
17 | 17 |
18 #define DO_TRELLIS_I4 1 | 18 #define DO_TRELLIS_I4 1 |
19 #define DO_TRELLIS_I16 1 // not a huge gain, but ok at low bitrate. | 19 #define DO_TRELLIS_I16 1 // not a huge gain, but ok at low bitrate. |
20 #define DO_TRELLIS_UV 0 // disable trellis for UV. Risky. Not worth. | 20 #define DO_TRELLIS_UV 0 // disable trellis for UV. Risky. Not worth. |
21 #define USE_TDISTO 1 | 21 #define USE_TDISTO 1 |
22 | 22 |
23 #define MID_ALPHA 64 // neutral value for susceptibility | 23 #define MID_ALPHA 64 // neutral value for susceptibility |
24 #define MIN_ALPHA 30 // lowest usable value for susceptibility | 24 #define MIN_ALPHA 30 // lowest usable value for susceptibility |
25 #define MAX_ALPHA 100 // higher meaninful value for susceptibility | 25 #define MAX_ALPHA 100 // higher meaninful value for susceptibility |
26 | 26 |
27 #define SNS_TO_DQ 0.9 // Scaling constant between the sns value and the QP | 27 #define SNS_TO_DQ 0.9 // Scaling constant between the sns value and the QP |
28 // power-law modulation. Must be strictly less than 1. | 28 // power-law modulation. Must be strictly less than 1. |
29 | 29 |
| 30 #define I4_PENALTY 4000 // Rate-penalty for quick i4/i16 decision |
| 31 |
30 #define MULT_8B(a, b) (((a) * (b) + 128) >> 8) | 32 #define MULT_8B(a, b) (((a) * (b) + 128) >> 8) |
31 | 33 |
32 #if defined(__cplusplus) || defined(c_plusplus) | 34 #if defined(__cplusplus) || defined(c_plusplus) |
33 extern "C" { | 35 extern "C" { |
34 #endif | 36 #endif |
35 | 37 |
36 //------------------------------------------------------------------------------ | 38 //------------------------------------------------------------------------------ |
37 | 39 |
38 static WEBP_INLINE int clip(int v, int m, int M) { | 40 static WEBP_INLINE int clip(int v, int m, int M) { |
39 return v < m ? m : v > M ? M : v; | 41 return v < m ? m : v > M ? M : v; |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
217 //------------------------------------------------------------------------------ | 219 //------------------------------------------------------------------------------ |
218 | 220 |
219 // Note: if you change the values below, remember that the max range | 221 // Note: if you change the values below, remember that the max range |
220 // allowed by the syntax for DQ_UV is [-16,16]. | 222 // allowed by the syntax for DQ_UV is [-16,16]. |
221 #define MAX_DQ_UV (6) | 223 #define MAX_DQ_UV (6) |
222 #define MIN_DQ_UV (-4) | 224 #define MIN_DQ_UV (-4) |
223 | 225 |
224 // We want to emulate jpeg-like behaviour where the expected "good" quality | 226 // We want to emulate jpeg-like behaviour where the expected "good" quality |
225 // is around q=75. Internally, our "good" middle is around c=50. So we | 227 // is around q=75. Internally, our "good" middle is around c=50. So we |
226 // map accordingly using linear piece-wise function | 228 // map accordingly using linear piece-wise function |
227 static double QualityToCompression(double q) { | 229 static double QualityToCompression(double c) { |
228 const double c = q / 100.; | 230 const double linear_c = (c < 0.75) ? c * (2. / 3.) : 2. * c - 1.; |
229 return (c < 0.75) ? c * (2. / 3.) : 2. * c - 1.; | 231 // The file size roughly scales as pow(quantizer, 3.). Actually, the |
| 232 // exponent is somewhere between 2.8 and 3.2, but we're mostly interested |
| 233 // in the mid-quant range. So we scale the compressibility inversely to |
| 234 // this power-law: quant ~= compression ^ 1/3. This law holds well for |
| 235 // low quant. Finer modelling for high-quant would make use of kAcTable[] |
| 236 // more explicitly. |
| 237 const double v = pow(linear_c, 1 / 3.); |
| 238 return v; |
| 239 } |
| 240 |
| 241 static double QualityToJPEGCompression(double c, double alpha) { |
| 242 // We map the complexity 'alpha' and quality setting 'c' to a compression |
| 243 // exponent empirically matched to the compression curve of libjpeg6b. |
| 244 // On average, the WebP output size will be roughly similar to that of a |
| 245 // JPEG file compressed with same quality factor. |
| 246 const double amin = 0.30; |
| 247 const double amax = 0.85; |
| 248 const double exp_min = 0.4; |
| 249 const double exp_max = 0.9; |
| 250 const double slope = (exp_min - exp_max) / (amax - amin); |
| 251 // Linearly interpolate 'expn' from exp_min to exp_max |
| 252 // in the [amin, amax] range. |
| 253 const double expn = (alpha > amax) ? exp_min |
| 254 : (alpha < amin) ? exp_max |
| 255 : exp_max + slope * (alpha - amin); |
| 256 const double v = pow(c, expn); |
| 257 return v; |
| 258 } |
| 259 |
| 260 static int SegmentsAreEquivalent(const VP8SegmentInfo* const S1, |
| 261 const VP8SegmentInfo* const S2) { |
| 262 return (S1->quant_ == S2->quant_) && (S1->fstrength_ == S2->fstrength_); |
| 263 } |
| 264 |
| 265 static void SimplifySegments(VP8Encoder* const enc) { |
| 266 int map[NUM_MB_SEGMENTS] = { 0, 1, 2, 3 }; |
| 267 const int num_segments = enc->segment_hdr_.num_segments_; |
| 268 int num_final_segments = 1; |
| 269 int s1, s2; |
| 270 for (s1 = 1; s1 < num_segments; ++s1) { // find similar segments |
| 271 const VP8SegmentInfo* const S1 = &enc->dqm_[s1]; |
| 272 int found = 0; |
| 273 // check if we already have similar segment |
| 274 for (s2 = 0; s2 < num_final_segments; ++s2) { |
| 275 const VP8SegmentInfo* const S2 = &enc->dqm_[s2]; |
| 276 if (SegmentsAreEquivalent(S1, S2)) { |
| 277 found = 1; |
| 278 break; |
| 279 } |
| 280 } |
| 281 map[s1] = s2; |
| 282 if (!found) { |
| 283 if (num_final_segments != s1) { |
| 284 enc->dqm_[num_final_segments] = enc->dqm_[s1]; |
| 285 } |
| 286 ++num_final_segments; |
| 287 } |
| 288 } |
| 289 if (num_final_segments < num_segments) { // Remap |
| 290 int i = enc->mb_w_ * enc->mb_h_; |
| 291 while (i-- > 0) enc->mb_info_[i].segment_ = map[enc->mb_info_[i].segment_]; |
| 292 enc->segment_hdr_.num_segments_ = num_final_segments; |
| 293 // Replicate the trailing segment infos (it's mostly cosmetics) |
| 294 for (i = num_final_segments; i < num_segments; ++i) { |
| 295 enc->dqm_[i] = enc->dqm_[num_final_segments - 1]; |
| 296 } |
| 297 } |
230 } | 298 } |
231 | 299 |
232 void VP8SetSegmentParams(VP8Encoder* const enc, float quality) { | 300 void VP8SetSegmentParams(VP8Encoder* const enc, float quality) { |
233 int i; | 301 int i; |
234 int dq_uv_ac, dq_uv_dc; | 302 int dq_uv_ac, dq_uv_dc; |
235 const int num_segments = enc->config_->segments; | 303 const int num_segments = enc->segment_hdr_.num_segments_; |
236 const double amp = SNS_TO_DQ * enc->config_->sns_strength / 100. / 128.; | 304 const double amp = SNS_TO_DQ * enc->config_->sns_strength / 100. / 128.; |
237 const double c_base = QualityToCompression(quality); | 305 const double Q = quality / 100.; |
| 306 const double c_base = enc->config_->emulate_jpeg_size ? |
| 307 QualityToJPEGCompression(Q, enc->alpha_ / 255.) : |
| 308 QualityToCompression(Q); |
238 for (i = 0; i < num_segments; ++i) { | 309 for (i = 0; i < num_segments; ++i) { |
239 // The file size roughly scales as pow(quantizer, 3.). Actually, the | 310 // We modulate the base coefficient to accommodate for the quantization |
240 // exponent is somewhere between 2.8 and 3.2, but we're mostly interested | 311 // susceptibility and allow denser segments to be quantized more. |
241 // in the mid-quant range. So we scale the compressibility inversely to | 312 const double expn = 1. - amp * enc->dqm_[i].alpha_; |
242 // this power-law: quant ~= compression ^ 1/3. This law holds well for | |
243 // low quant. Finer modelling for high-quant would make use of kAcTable[] | |
244 // more explicitely. | |
245 // Additionally, we modulate the base exponent 1/3 to accommodate for the | |
246 // quantization susceptibility and allow denser segments to be quantized | |
247 // more. | |
248 const double expn = (1. - amp * enc->dqm_[i].alpha_) / 3.; | |
249 const double c = pow(c_base, expn); | 313 const double c = pow(c_base, expn); |
250 const int q = (int)(127. * (1. - c)); | 314 const int q = (int)(127. * (1. - c)); |
251 assert(expn > 0.); | 315 assert(expn > 0.); |
252 enc->dqm_[i].quant_ = clip(q, 0, 127); | 316 enc->dqm_[i].quant_ = clip(q, 0, 127); |
253 } | 317 } |
254 | 318 |
255 // purely indicative in the bitstream (except for the 1-segment case) | 319 // purely indicative in the bitstream (except for the 1-segment case) |
256 enc->base_quant_ = enc->dqm_[0].quant_; | 320 enc->base_quant_ = enc->dqm_[0].quant_; |
257 | 321 |
258 // fill-in values for the unused segments (required by the syntax) | 322 // fill-in values for the unused segments (required by the syntax) |
(...skipping 15 matching lines...) Expand all Loading... |
274 // tend to appear, and are displeasant). | 338 // tend to appear, and are displeasant). |
275 dq_uv_dc = -4 * enc->config_->sns_strength / 100; | 339 dq_uv_dc = -4 * enc->config_->sns_strength / 100; |
276 dq_uv_dc = clip(dq_uv_dc, -15, 15); // 4bit-signed max allowed | 340 dq_uv_dc = clip(dq_uv_dc, -15, 15); // 4bit-signed max allowed |
277 | 341 |
278 enc->dq_y1_dc_ = 0; // TODO(skal): dq-lum | 342 enc->dq_y1_dc_ = 0; // TODO(skal): dq-lum |
279 enc->dq_y2_dc_ = 0; | 343 enc->dq_y2_dc_ = 0; |
280 enc->dq_y2_ac_ = 0; | 344 enc->dq_y2_ac_ = 0; |
281 enc->dq_uv_dc_ = dq_uv_dc; | 345 enc->dq_uv_dc_ = dq_uv_dc; |
282 enc->dq_uv_ac_ = dq_uv_ac; | 346 enc->dq_uv_ac_ = dq_uv_ac; |
283 | 347 |
284 SetupMatrices(enc); | 348 SetupFilterStrength(enc); // initialize segments' filtering, eventually |
285 | 349 |
286 SetupFilterStrength(enc); // initialize segments' filtering, eventually | 350 if (num_segments > 1) SimplifySegments(enc); |
| 351 |
| 352 SetupMatrices(enc); // finalize quantization matrices |
287 } | 353 } |
288 | 354 |
289 //------------------------------------------------------------------------------ | 355 //------------------------------------------------------------------------------ |
290 // Form the predictions in cache | 356 // Form the predictions in cache |
291 | 357 |
292 // Must be ordered using {DC_PRED, TM_PRED, V_PRED, H_PRED} as index | 358 // Must be ordered using {DC_PRED, TM_PRED, V_PRED, H_PRED} as index |
293 const int VP8I16ModeOffsets[4] = { I16DC16, I16TM16, I16VE16, I16HE16 }; | 359 const int VP8I16ModeOffsets[4] = { I16DC16, I16TM16, I16VE16, I16HE16 }; |
294 const int VP8UVModeOffsets[4] = { C8DC8, C8TM8, C8VE8, C8HE8 }; | 360 const int VP8UVModeOffsets[4] = { C8DC8, C8TM8, C8VE8, C8HE8 }; |
295 | 361 |
296 // Must be indexed using {B_DC_PRED -> B_HU_PRED} as index | 362 // Must be indexed using {B_DC_PRED -> B_HU_PRED} as index |
(...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
702 static void PickBestIntra16(VP8EncIterator* const it, VP8ModeScore* const rd) { | 768 static void PickBestIntra16(VP8EncIterator* const it, VP8ModeScore* const rd) { |
703 const VP8Encoder* const enc = it->enc_; | 769 const VP8Encoder* const enc = it->enc_; |
704 const VP8SegmentInfo* const dqm = &enc->dqm_[it->mb_->segment_]; | 770 const VP8SegmentInfo* const dqm = &enc->dqm_[it->mb_->segment_]; |
705 const int lambda = dqm->lambda_i16_; | 771 const int lambda = dqm->lambda_i16_; |
706 const int tlambda = dqm->tlambda_; | 772 const int tlambda = dqm->tlambda_; |
707 const uint8_t* const src = it->yuv_in_ + Y_OFF; | 773 const uint8_t* const src = it->yuv_in_ + Y_OFF; |
708 VP8ModeScore rd16; | 774 VP8ModeScore rd16; |
709 int mode; | 775 int mode; |
710 | 776 |
711 rd->mode_i16 = -1; | 777 rd->mode_i16 = -1; |
712 for (mode = 0; mode < 4; ++mode) { | 778 for (mode = 0; mode < NUM_PRED_MODES; ++mode) { |
713 uint8_t* const tmp_dst = it->yuv_out2_ + Y_OFF; // scratch buffer | 779 uint8_t* const tmp_dst = it->yuv_out2_ + Y_OFF; // scratch buffer |
714 int nz; | 780 int nz; |
715 | 781 |
716 // Reconstruct | 782 // Reconstruct |
717 nz = ReconstructIntra16(it, &rd16, tmp_dst, mode); | 783 nz = ReconstructIntra16(it, &rd16, tmp_dst, mode); |
718 | 784 |
719 // Measure RD-score | 785 // Measure RD-score |
720 rd16.D = VP8SSE16x16(src, tmp_dst); | 786 rd16.D = VP8SSE16x16(src, tmp_dst); |
721 rd16.SD = tlambda ? MULT_8B(tlambda, VP8TDisto16x16(src, tmp_dst, kWeightY)) | 787 rd16.SD = tlambda ? MULT_8B(tlambda, VP8TDisto16x16(src, tmp_dst, kWeightY)) |
722 : 0; | 788 : 0; |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
831 const VP8SegmentInfo* const dqm = &enc->dqm_[it->mb_->segment_]; | 897 const VP8SegmentInfo* const dqm = &enc->dqm_[it->mb_->segment_]; |
832 const int lambda = dqm->lambda_uv_; | 898 const int lambda = dqm->lambda_uv_; |
833 const uint8_t* const src = it->yuv_in_ + U_OFF; | 899 const uint8_t* const src = it->yuv_in_ + U_OFF; |
834 uint8_t* const tmp_dst = it->yuv_out2_ + U_OFF; // scratch buffer | 900 uint8_t* const tmp_dst = it->yuv_out2_ + U_OFF; // scratch buffer |
835 uint8_t* const dst0 = it->yuv_out_ + U_OFF; | 901 uint8_t* const dst0 = it->yuv_out_ + U_OFF; |
836 VP8ModeScore rd_best; | 902 VP8ModeScore rd_best; |
837 int mode; | 903 int mode; |
838 | 904 |
839 rd->mode_uv = -1; | 905 rd->mode_uv = -1; |
840 InitScore(&rd_best); | 906 InitScore(&rd_best); |
841 for (mode = 0; mode < 4; ++mode) { | 907 for (mode = 0; mode < NUM_PRED_MODES; ++mode) { |
842 VP8ModeScore rd_uv; | 908 VP8ModeScore rd_uv; |
843 | 909 |
844 // Reconstruct | 910 // Reconstruct |
845 rd_uv.nz = ReconstructUV(it, &rd_uv, tmp_dst, mode); | 911 rd_uv.nz = ReconstructUV(it, &rd_uv, tmp_dst, mode); |
846 | 912 |
847 // Compute RD-score | 913 // Compute RD-score |
848 rd_uv.D = VP8SSE16x8(src, tmp_dst); | 914 rd_uv.D = VP8SSE16x8(src, tmp_dst); |
849 rd_uv.SD = 0; // TODO: should we call TDisto? it tends to flatten areas. | 915 rd_uv.SD = 0; // TODO: should we call TDisto? it tends to flatten areas. |
850 rd_uv.R = VP8GetCostUV(it, &rd_uv); | 916 rd_uv.R = VP8GetCostUV(it, &rd_uv); |
851 rd_uv.R += VP8FixedCostsUV[mode]; | 917 rd_uv.R += VP8FixedCostsUV[mode]; |
852 | 918 |
853 SetRDScore(lambda, &rd_uv); | 919 SetRDScore(lambda, &rd_uv); |
854 if (mode == 0 || rd_uv.score < rd_best.score) { | 920 if (mode == 0 || rd_uv.score < rd_best.score) { |
855 CopyScore(&rd_best, &rd_uv); | 921 CopyScore(&rd_best, &rd_uv); |
856 rd->mode_uv = mode; | 922 rd->mode_uv = mode; |
857 memcpy(rd->uv_levels, rd_uv.uv_levels, sizeof(rd->uv_levels)); | 923 memcpy(rd->uv_levels, rd_uv.uv_levels, sizeof(rd->uv_levels)); |
858 memcpy(dst0, tmp_dst, UV_SIZE); // TODO: SwapUVOut() ? | 924 memcpy(dst0, tmp_dst, UV_SIZE); // TODO: SwapUVOut() ? |
859 } | 925 } |
860 } | 926 } |
861 VP8SetIntraUVMode(it, rd->mode_uv); | 927 VP8SetIntraUVMode(it, rd->mode_uv); |
862 AddScore(rd, &rd_best); | 928 AddScore(rd, &rd_best); |
863 } | 929 } |
864 | 930 |
865 //------------------------------------------------------------------------------ | 931 //------------------------------------------------------------------------------ |
866 // Final reconstruction and quantization. | 932 // Final reconstruction and quantization. |
867 | 933 |
868 static void SimpleQuantize(VP8EncIterator* const it, VP8ModeScore* const rd) { | 934 static void SimpleQuantize(VP8EncIterator* const it, VP8ModeScore* const rd) { |
869 const VP8Encoder* const enc = it->enc_; | 935 const VP8Encoder* const enc = it->enc_; |
870 const int i16 = (it->mb_->type_ == 1); | 936 const int is_i16 = (it->mb_->type_ == 1); |
871 int nz = 0; | 937 int nz = 0; |
872 | 938 |
873 if (i16) { | 939 if (is_i16) { |
874 nz = ReconstructIntra16(it, rd, it->yuv_out_ + Y_OFF, it->preds_[0]); | 940 nz = ReconstructIntra16(it, rd, it->yuv_out_ + Y_OFF, it->preds_[0]); |
875 } else { | 941 } else { |
876 VP8IteratorStartI4(it); | 942 VP8IteratorStartI4(it); |
877 do { | 943 do { |
878 const int mode = | 944 const int mode = |
879 it->preds_[(it->i4_ & 3) + (it->i4_ >> 2) * enc->preds_w_]; | 945 it->preds_[(it->i4_ & 3) + (it->i4_ >> 2) * enc->preds_w_]; |
880 const uint8_t* const src = it->yuv_in_ + Y_OFF + VP8Scan[it->i4_]; | 946 const uint8_t* const src = it->yuv_in_ + Y_OFF + VP8Scan[it->i4_]; |
881 uint8_t* const dst = it->yuv_out_ + Y_OFF + VP8Scan[it->i4_]; | 947 uint8_t* const dst = it->yuv_out_ + Y_OFF + VP8Scan[it->i4_]; |
882 VP8MakeIntra4Preds(it); | 948 VP8MakeIntra4Preds(it); |
883 nz |= ReconstructIntra4(it, rd->y_ac_levels[it->i4_], | 949 nz |= ReconstructIntra4(it, rd->y_ac_levels[it->i4_], |
884 src, dst, mode) << it->i4_; | 950 src, dst, mode) << it->i4_; |
885 } while (VP8IteratorRotateI4(it, it->yuv_out_ + Y_OFF)); | 951 } while (VP8IteratorRotateI4(it, it->yuv_out_ + Y_OFF)); |
886 } | 952 } |
887 | 953 |
888 nz |= ReconstructUV(it, rd, it->yuv_out_ + U_OFF, it->mb_->uv_mode_); | 954 nz |= ReconstructUV(it, rd, it->yuv_out_ + U_OFF, it->mb_->uv_mode_); |
889 rd->nz = nz; | 955 rd->nz = nz; |
890 } | 956 } |
891 | 957 |
| 958 // Refine intra16/intra4 sub-modes based on distortion only (not rate). |
| 959 static void DistoRefine(VP8EncIterator* const it, int try_both_i4_i16) { |
| 960 const int is_i16 = (it->mb_->type_ == 1); |
| 961 score_t best_score = MAX_COST; |
| 962 |
| 963 if (try_both_i4_i16 || is_i16) { |
| 964 int mode; |
| 965 int best_mode = -1; |
| 966 for (mode = 0; mode < NUM_PRED_MODES; ++mode) { |
| 967 const uint8_t* const ref = it->yuv_p_ + VP8I16ModeOffsets[mode]; |
| 968 const uint8_t* const src = it->yuv_in_ + Y_OFF; |
| 969 const score_t score = VP8SSE16x16(src, ref); |
| 970 if (score < best_score) { |
| 971 best_mode = mode; |
| 972 best_score = score; |
| 973 } |
| 974 } |
| 975 VP8SetIntra16Mode(it, best_mode); |
| 976 } |
| 977 if (try_both_i4_i16 || !is_i16) { |
| 978 uint8_t modes_i4[16]; |
| 979 // We don't evaluate the rate here, but just account for it through a |
| 980 // constant penalty (i4 mode usually needs more bits compared to i16). |
| 981 score_t score_i4 = (score_t)I4_PENALTY; |
| 982 |
| 983 VP8IteratorStartI4(it); |
| 984 do { |
| 985 int mode; |
| 986 int best_sub_mode = -1; |
| 987 score_t best_sub_score = MAX_COST; |
| 988 const uint8_t* const src = it->yuv_in_ + Y_OFF + VP8Scan[it->i4_]; |
| 989 |
| 990 // TODO(skal): we don't really need the prediction pixels here, |
| 991 // but just the distortion against 'src'. |
| 992 VP8MakeIntra4Preds(it); |
| 993 for (mode = 0; mode < NUM_BMODES; ++mode) { |
| 994 const uint8_t* const ref = it->yuv_p_ + VP8I4ModeOffsets[mode]; |
| 995 const score_t score = VP8SSE4x4(src, ref); |
| 996 if (score < best_sub_score) { |
| 997 best_sub_mode = mode; |
| 998 best_sub_score = score; |
| 999 } |
| 1000 } |
| 1001 modes_i4[it->i4_] = best_sub_mode; |
| 1002 score_i4 += best_sub_score; |
| 1003 if (score_i4 >= best_score) break; |
| 1004 } while (VP8IteratorRotateI4(it, it->yuv_in_ + Y_OFF)); |
| 1005 if (score_i4 < best_score) { |
| 1006 VP8SetIntra4Mode(it, modes_i4); |
| 1007 } |
| 1008 } |
| 1009 } |
| 1010 |
892 //------------------------------------------------------------------------------ | 1011 //------------------------------------------------------------------------------ |
893 // Entry point | 1012 // Entry point |
894 | 1013 |
895 int VP8Decimate(VP8EncIterator* const it, VP8ModeScore* const rd, int rd_opt) { | 1014 int VP8Decimate(VP8EncIterator* const it, VP8ModeScore* const rd, |
| 1015 VP8RDLevel rd_opt) { |
896 int is_skipped; | 1016 int is_skipped; |
| 1017 const int method = it->enc_->method_; |
897 | 1018 |
898 InitScore(rd); | 1019 InitScore(rd); |
899 | 1020 |
900 // We can perform predictions for Luma16x16 and Chroma8x8 already. | 1021 // We can perform predictions for Luma16x16 and Chroma8x8 already. |
901 // Luma4x4 predictions needs to be done as-we-go. | 1022 // Luma4x4 predictions needs to be done as-we-go. |
902 VP8MakeLuma16Preds(it); | 1023 VP8MakeLuma16Preds(it); |
903 VP8MakeChroma8Preds(it); | 1024 VP8MakeChroma8Preds(it); |
904 | 1025 |
905 // for rd_opt = 2, we perform trellis-quant on the final decision only. | 1026 if (rd_opt > RD_OPT_NONE) { |
906 // for rd_opt > 2, we use it for every scoring (=much slower). | 1027 it->do_trellis_ = (rd_opt >= RD_OPT_TRELLIS_ALL); |
907 if (rd_opt > 0) { | |
908 it->do_trellis_ = (rd_opt > 2); | |
909 PickBestIntra16(it, rd); | 1028 PickBestIntra16(it, rd); |
910 if (it->enc_->method_ >= 2) { | 1029 if (method >= 2) { |
911 PickBestIntra4(it, rd); | 1030 PickBestIntra4(it, rd); |
912 } | 1031 } |
913 PickBestUV(it, rd); | 1032 PickBestUV(it, rd); |
914 if (rd_opt == 2) { | 1033 if (rd_opt == RD_OPT_TRELLIS) { // finish off with trellis-optim now |
915 it->do_trellis_ = 1; | 1034 it->do_trellis_ = 1; |
916 SimpleQuantize(it, rd); | 1035 SimpleQuantize(it, rd); |
917 } | 1036 } |
918 } else { | 1037 } else { |
919 // TODO: for method_ == 2, pick the best intra4/intra16 based on SSE | 1038 // For method == 2, pick the best intra4/intra16 based on SSE (~tad slower). |
920 it->do_trellis_ = (it->enc_->method_ == 2); | 1039 // For method <= 1, we refine intra4 or intra16 (but don't re-examine mode). |
| 1040 DistoRefine(it, (method >= 2)); |
921 SimpleQuantize(it, rd); | 1041 SimpleQuantize(it, rd); |
922 } | 1042 } |
923 is_skipped = (rd->nz == 0); | 1043 is_skipped = (rd->nz == 0); |
924 VP8SetSkip(it, is_skipped); | 1044 VP8SetSkip(it, is_skipped); |
925 return is_skipped; | 1045 return is_skipped; |
926 } | 1046 } |
927 | 1047 |
928 #if defined(__cplusplus) || defined(c_plusplus) | 1048 #if defined(__cplusplus) || defined(c_plusplus) |
929 } // extern "C" | 1049 } // extern "C" |
930 #endif | 1050 #endif |
OLD | NEW |