OLD | NEW |
1 // Copyright 2011 Google Inc. | 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 MULT_8B(a, b) (((a) * (b) + 128) >> 8) | 30 #define MULT_8B(a, b) (((a) * (b) + 128) >> 8) |
31 | 31 |
32 #if defined(__cplusplus) || defined(c_plusplus) | 32 #if defined(__cplusplus) || defined(c_plusplus) |
33 extern "C" { | 33 extern "C" { |
34 #endif | 34 #endif |
35 | 35 |
36 //------------------------------------------------------------------------------ | 36 //------------------------------------------------------------------------------ |
37 | 37 |
38 static inline int clip(int v, int m, int M) { | 38 static WEBP_INLINE int clip(int v, int m, int M) { |
39 return v < m ? m : v > M ? M : v; | 39 return v < m ? m : v > M ? M : v; |
40 } | 40 } |
41 | 41 |
42 static const uint8_t kZigzag[16] = { | 42 static const uint8_t kZigzag[16] = { |
43 0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15 | 43 0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15 |
44 }; | 44 }; |
45 | 45 |
46 static const uint8_t kDcTable[128] = { | 46 static const uint8_t kDcTable[128] = { |
47 4, 5, 6, 7, 8, 9, 10, 10, | 47 4, 5, 6, 7, 8, 9, 10, 10, |
48 11, 12, 13, 14, 15, 16, 17, 17, | 48 11, 12, 13, 14, 15, 16, 17, 17, |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
292 // Must be ordered using {DC_PRED, TM_PRED, V_PRED, H_PRED} as index | 292 // Must be ordered using {DC_PRED, TM_PRED, V_PRED, H_PRED} as index |
293 const int VP8I16ModeOffsets[4] = { I16DC16, I16TM16, I16VE16, I16HE16 }; | 293 const int VP8I16ModeOffsets[4] = { I16DC16, I16TM16, I16VE16, I16HE16 }; |
294 const int VP8UVModeOffsets[4] = { C8DC8, C8TM8, C8VE8, C8HE8 }; | 294 const int VP8UVModeOffsets[4] = { C8DC8, C8TM8, C8VE8, C8HE8 }; |
295 | 295 |
296 // Must be indexed using {B_DC_PRED -> B_HU_PRED} as index | 296 // Must be indexed using {B_DC_PRED -> B_HU_PRED} as index |
297 const int VP8I4ModeOffsets[NUM_BMODES] = { | 297 const int VP8I4ModeOffsets[NUM_BMODES] = { |
298 I4DC4, I4TM4, I4VE4, I4HE4, I4RD4, I4VR4, I4LD4, I4VL4, I4HD4, I4HU4 | 298 I4DC4, I4TM4, I4VE4, I4HE4, I4RD4, I4VR4, I4LD4, I4VL4, I4HD4, I4HU4 |
299 }; | 299 }; |
300 | 300 |
301 void VP8MakeLuma16Preds(const VP8EncIterator* const it) { | 301 void VP8MakeLuma16Preds(const VP8EncIterator* const it) { |
302 VP8Encoder* const enc = it->enc_; | 302 const VP8Encoder* const enc = it->enc_; |
303 const uint8_t* left = it->x_ ? enc->y_left_ : NULL; | 303 const uint8_t* const left = it->x_ ? enc->y_left_ : NULL; |
304 const uint8_t* top = it->y_ ? enc->y_top_ + it->x_ * 16 : NULL; | 304 const uint8_t* const top = it->y_ ? enc->y_top_ + it->x_ * 16 : NULL; |
305 VP8EncPredLuma16(it->yuv_p_, left, top); | 305 VP8EncPredLuma16(it->yuv_p_, left, top); |
306 } | 306 } |
307 | 307 |
308 void VP8MakeChroma8Preds(const VP8EncIterator* const it) { | 308 void VP8MakeChroma8Preds(const VP8EncIterator* const it) { |
309 VP8Encoder* const enc = it->enc_; | 309 const VP8Encoder* const enc = it->enc_; |
310 const uint8_t* left = it->x_ ? enc->u_left_ : NULL; | 310 const uint8_t* const left = it->x_ ? enc->u_left_ : NULL; |
311 const uint8_t* top = it->y_ ? enc->uv_top_ + it->x_ * 16 : NULL; | 311 const uint8_t* const top = it->y_ ? enc->uv_top_ + it->x_ * 16 : NULL; |
312 VP8EncPredChroma8(it->yuv_p_, left, top); | 312 VP8EncPredChroma8(it->yuv_p_, left, top); |
313 } | 313 } |
314 | 314 |
315 void VP8MakeIntra4Preds(const VP8EncIterator* const it) { | 315 void VP8MakeIntra4Preds(const VP8EncIterator* const it) { |
316 VP8EncPredLuma4(it->yuv_p_, it->i4_top_); | 316 VP8EncPredLuma4(it->yuv_p_, it->i4_top_); |
317 } | 317 } |
318 | 318 |
319 //------------------------------------------------------------------------------ | 319 //------------------------------------------------------------------------------ |
320 // Quantize | 320 // Quantize |
321 | 321 |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
399 } Node; | 399 } Node; |
400 | 400 |
401 // If a coefficient was quantized to a value Q (using a neutral bias), | 401 // If a coefficient was quantized to a value Q (using a neutral bias), |
402 // we test all alternate possibilities between [Q-MIN_DELTA, Q+MAX_DELTA] | 402 // we test all alternate possibilities between [Q-MIN_DELTA, Q+MAX_DELTA] |
403 // We don't test negative values though. | 403 // We don't test negative values though. |
404 #define MIN_DELTA 0 // how much lower level to try | 404 #define MIN_DELTA 0 // how much lower level to try |
405 #define MAX_DELTA 1 // how much higher | 405 #define MAX_DELTA 1 // how much higher |
406 #define NUM_NODES (MIN_DELTA + 1 + MAX_DELTA) | 406 #define NUM_NODES (MIN_DELTA + 1 + MAX_DELTA) |
407 #define NODE(n, l) (nodes[(n) + 1][(l) + MIN_DELTA]) | 407 #define NODE(n, l) (nodes[(n) + 1][(l) + MIN_DELTA]) |
408 | 408 |
409 static inline void SetRDScore(int lambda, VP8ModeScore* const rd) { | 409 static WEBP_INLINE void SetRDScore(int lambda, VP8ModeScore* const rd) { |
410 // TODO: incorporate the "* 256" in the tables? | 410 // TODO: incorporate the "* 256" in the tables? |
411 rd->score = rd->R * lambda + 256 * (rd->D + rd->SD); | 411 rd->score = rd->R * lambda + 256 * (rd->D + rd->SD); |
412 } | 412 } |
413 | 413 |
414 static inline score_t RDScoreTrellis(int lambda, score_t rate, | 414 static WEBP_INLINE score_t RDScoreTrellis(int lambda, score_t rate, |
415 score_t distortion) { | 415 score_t distortion) { |
416 return rate * lambda + 256 * distortion; | 416 return rate * lambda + 256 * distortion; |
417 } | 417 } |
418 | 418 |
419 static int TrellisQuantizeBlock(const VP8EncIterator* const it, | 419 static int TrellisQuantizeBlock(const VP8EncIterator* const it, |
420 int16_t in[16], int16_t out[16], | 420 int16_t in[16], int16_t out[16], |
421 int ctx0, int coeff_type, | 421 int ctx0, int coeff_type, |
422 const VP8Matrix* const mtx, | 422 const VP8Matrix* const mtx, |
423 int lambda) { | 423 int lambda) { |
424 ProbaArray* const last_costs = it->enc_->proba_.coeffs_[coeff_type]; | 424 ProbaArray* const last_costs = it->enc_->proba_.coeffs_[coeff_type]; |
425 CostArray* const costs = it->enc_->proba_.level_cost_[coeff_type]; | 425 CostArray* const costs = it->enc_->proba_.level_cost_[coeff_type]; |
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
693 uint8_t* const tmp = *a; | 693 uint8_t* const tmp = *a; |
694 *a = *b; | 694 *a = *b; |
695 *b = tmp; | 695 *b = tmp; |
696 } | 696 } |
697 | 697 |
698 static void SwapOut(VP8EncIterator* const it) { | 698 static void SwapOut(VP8EncIterator* const it) { |
699 SwapPtr(&it->yuv_out_, &it->yuv_out2_); | 699 SwapPtr(&it->yuv_out_, &it->yuv_out2_); |
700 } | 700 } |
701 | 701 |
702 static void PickBestIntra16(VP8EncIterator* const it, VP8ModeScore* const rd) { | 702 static void PickBestIntra16(VP8EncIterator* const it, VP8ModeScore* const rd) { |
703 VP8Encoder* const enc = it->enc_; | 703 const VP8Encoder* const enc = it->enc_; |
704 const VP8SegmentInfo* const dqm = &enc->dqm_[it->mb_->segment_]; | 704 const VP8SegmentInfo* const dqm = &enc->dqm_[it->mb_->segment_]; |
705 const int lambda = dqm->lambda_i16_; | 705 const int lambda = dqm->lambda_i16_; |
706 const int tlambda = dqm->tlambda_; | 706 const int tlambda = dqm->tlambda_; |
707 const uint8_t* const src = it->yuv_in_ + Y_OFF; | 707 const uint8_t* const src = it->yuv_in_ + Y_OFF; |
708 VP8ModeScore rd16; | 708 VP8ModeScore rd16; |
709 int mode; | 709 int mode; |
710 | 710 |
711 rd->mode_i16 = -1; | 711 rd->mode_i16 = -1; |
712 for (mode = 0; mode < 4; ++mode) { | 712 for (mode = 0; mode < 4; ++mode) { |
713 uint8_t* const tmp_dst = it->yuv_out2_ + Y_OFF; // scratch buffer | 713 uint8_t* const tmp_dst = it->yuv_out2_ + Y_OFF; // scratch buffer |
(...skipping 21 matching lines...) Expand all Loading... |
735 } | 735 } |
736 } | 736 } |
737 SetRDScore(dqm->lambda_mode_, rd); // finalize score for mode decision. | 737 SetRDScore(dqm->lambda_mode_, rd); // finalize score for mode decision. |
738 VP8SetIntra16Mode(it, rd->mode_i16); | 738 VP8SetIntra16Mode(it, rd->mode_i16); |
739 } | 739 } |
740 | 740 |
741 //------------------------------------------------------------------------------ | 741 //------------------------------------------------------------------------------ |
742 | 742 |
743 // return the cost array corresponding to the surrounding prediction modes. | 743 // return the cost array corresponding to the surrounding prediction modes. |
744 static const uint16_t* GetCostModeI4(VP8EncIterator* const it, | 744 static const uint16_t* GetCostModeI4(VP8EncIterator* const it, |
745 const int modes[16]) { | 745 const uint8_t modes[16]) { |
746 const int preds_w = it->enc_->preds_w_; | 746 const int preds_w = it->enc_->preds_w_; |
747 const int x = (it->i4_ & 3), y = it->i4_ >> 2; | 747 const int x = (it->i4_ & 3), y = it->i4_ >> 2; |
748 const int left = (x == 0) ? it->preds_[y * preds_w - 1] : modes[it->i4_ - 1]; | 748 const int left = (x == 0) ? it->preds_[y * preds_w - 1] : modes[it->i4_ - 1]; |
749 const int top = (y == 0) ? it->preds_[-preds_w + x] : modes[it->i4_ - 4]; | 749 const int top = (y == 0) ? it->preds_[-preds_w + x] : modes[it->i4_ - 4]; |
750 return VP8FixedCostsI4[top][left]; | 750 return VP8FixedCostsI4[top][left]; |
751 } | 751 } |
752 | 752 |
753 static int PickBestIntra4(VP8EncIterator* const it, VP8ModeScore* const rd) { | 753 static int PickBestIntra4(VP8EncIterator* const it, VP8ModeScore* const rd) { |
754 VP8Encoder* const enc = it->enc_; | 754 const VP8Encoder* const enc = it->enc_; |
755 const VP8SegmentInfo* const dqm = &enc->dqm_[it->mb_->segment_]; | 755 const VP8SegmentInfo* const dqm = &enc->dqm_[it->mb_->segment_]; |
756 const int lambda = dqm->lambda_i4_; | 756 const int lambda = dqm->lambda_i4_; |
757 const int tlambda = dqm->tlambda_; | 757 const int tlambda = dqm->tlambda_; |
758 const uint8_t* const src0 = it->yuv_in_ + Y_OFF; | 758 const uint8_t* const src0 = it->yuv_in_ + Y_OFF; |
759 uint8_t* const best_blocks = it->yuv_out2_ + Y_OFF; | 759 uint8_t* const best_blocks = it->yuv_out2_ + Y_OFF; |
760 int total_header_bits = 0; | 760 int total_header_bits = 0; |
761 VP8ModeScore rd_best; | 761 VP8ModeScore rd_best; |
762 | 762 |
763 if (enc->max_i4_header_bits_ == 0) { | 763 if (enc->max_i4_header_bits_ == 0) { |
764 return 0; | 764 return 0; |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
820 CopyScore(rd, &rd_best); | 820 CopyScore(rd, &rd_best); |
821 VP8SetIntra4Mode(it, rd->modes_i4); | 821 VP8SetIntra4Mode(it, rd->modes_i4); |
822 SwapOut(it); | 822 SwapOut(it); |
823 memcpy(rd->y_ac_levels, rd_best.y_ac_levels, sizeof(rd->y_ac_levels)); | 823 memcpy(rd->y_ac_levels, rd_best.y_ac_levels, sizeof(rd->y_ac_levels)); |
824 return 1; // select intra4x4 over intra16x16 | 824 return 1; // select intra4x4 over intra16x16 |
825 } | 825 } |
826 | 826 |
827 //------------------------------------------------------------------------------ | 827 //------------------------------------------------------------------------------ |
828 | 828 |
829 static void PickBestUV(VP8EncIterator* const it, VP8ModeScore* const rd) { | 829 static void PickBestUV(VP8EncIterator* const it, VP8ModeScore* const rd) { |
830 VP8Encoder* const enc = it->enc_; | 830 const VP8Encoder* const enc = it->enc_; |
831 const VP8SegmentInfo* const dqm = &enc->dqm_[it->mb_->segment_]; | 831 const VP8SegmentInfo* const dqm = &enc->dqm_[it->mb_->segment_]; |
832 const int lambda = dqm->lambda_uv_; | 832 const int lambda = dqm->lambda_uv_; |
833 const uint8_t* const src = it->yuv_in_ + U_OFF; | 833 const uint8_t* const src = it->yuv_in_ + U_OFF; |
834 uint8_t* const tmp_dst = it->yuv_out2_ + U_OFF; // scratch buffer | 834 uint8_t* const tmp_dst = it->yuv_out2_ + U_OFF; // scratch buffer |
835 uint8_t* const dst0 = it->yuv_out_ + U_OFF; | 835 uint8_t* const dst0 = it->yuv_out_ + U_OFF; |
836 VP8ModeScore rd_best; | 836 VP8ModeScore rd_best; |
837 int mode; | 837 int mode; |
838 | 838 |
839 rd->mode_uv = -1; | 839 rd->mode_uv = -1; |
840 InitScore(&rd_best); | 840 InitScore(&rd_best); |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
921 SimpleQuantize(it, rd); | 921 SimpleQuantize(it, rd); |
922 } | 922 } |
923 is_skipped = (rd->nz == 0); | 923 is_skipped = (rd->nz == 0); |
924 VP8SetSkip(it, is_skipped); | 924 VP8SetSkip(it, is_skipped); |
925 return is_skipped; | 925 return is_skipped; |
926 } | 926 } |
927 | 927 |
928 #if defined(__cplusplus) || defined(c_plusplus) | 928 #if defined(__cplusplus) || defined(c_plusplus) |
929 } // extern "C" | 929 } // extern "C" |
930 #endif | 930 #endif |
OLD | NEW |