Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(128)

Side by Side Diff: third_party/libwebp/enc/quant.c

Issue 12942006: libwebp: update snapshot to v0.3.0-rc6 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « third_party/libwebp/enc/picture.c ('k') | third_party/libwebp/enc/syntax.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « third_party/libwebp/enc/picture.c ('k') | third_party/libwebp/enc/syntax.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698