OLD | NEW |
1 // Copyright 2011 Google Inc. All Rights Reserved. | 1 // Copyright 2011 Google Inc. All Rights Reserved. |
2 // | 2 // |
3 // Use of this source code is governed by a BSD-style license | 3 // Use of this source code is governed by a BSD-style license |
4 // that can be found in the COPYING file in the root of the source | 4 // that can be found in the COPYING file in the root of the source |
5 // tree. An additional intellectual property rights grant can be found | 5 // tree. An additional intellectual property rights grant can be found |
6 // in the file PATENTS. All contributing project authors may | 6 // in the file PATENTS. All contributing project authors may |
7 // be found in the AUTHORS file in the root of the source tree. | 7 // be found in the AUTHORS file in the root of the source tree. |
8 // ----------------------------------------------------------------------------- | 8 // ----------------------------------------------------------------------------- |
9 // | 9 // |
10 // frame coding and analysis | 10 // frame coding and analysis |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
178 | 178 |
179 //------------------------------------------------------------------------------ | 179 //------------------------------------------------------------------------------ |
180 // Finalize Segment probability based on the coding tree | 180 // Finalize Segment probability based on the coding tree |
181 | 181 |
182 static int GetProba(int a, int b) { | 182 static int GetProba(int a, int b) { |
183 const int total = a + b; | 183 const int total = a + b; |
184 return (total == 0) ? 255 // that's the default probability. | 184 return (total == 0) ? 255 // that's the default probability. |
185 : (255 * a + total / 2) / total; // rounded proba | 185 : (255 * a + total / 2) / total; // rounded proba |
186 } | 186 } |
187 | 187 |
| 188 static void ResetSegments(VP8Encoder* const enc) { |
| 189 int n; |
| 190 for (n = 0; n < enc->mb_w_ * enc->mb_h_; ++n) { |
| 191 enc->mb_info_[n].segment_ = 0; |
| 192 } |
| 193 } |
| 194 |
188 static void SetSegmentProbas(VP8Encoder* const enc) { | 195 static void SetSegmentProbas(VP8Encoder* const enc) { |
189 int p[NUM_MB_SEGMENTS] = { 0 }; | 196 int p[NUM_MB_SEGMENTS] = { 0 }; |
190 int n; | 197 int n; |
191 | 198 |
192 for (n = 0; n < enc->mb_w_ * enc->mb_h_; ++n) { | 199 for (n = 0; n < enc->mb_w_ * enc->mb_h_; ++n) { |
193 const VP8MBInfo* const mb = &enc->mb_info_[n]; | 200 const VP8MBInfo* const mb = &enc->mb_info_[n]; |
194 p[mb->segment_]++; | 201 p[mb->segment_]++; |
195 } | 202 } |
196 if (enc->pic_->stats != NULL) { | 203 if (enc->pic_->stats != NULL) { |
197 for (n = 0; n < NUM_MB_SEGMENTS; ++n) { | 204 for (n = 0; n < NUM_MB_SEGMENTS; ++n) { |
198 enc->pic_->stats->segment_size[n] = p[n]; | 205 enc->pic_->stats->segment_size[n] = p[n]; |
199 } | 206 } |
200 } | 207 } |
201 if (enc->segment_hdr_.num_segments_ > 1) { | 208 if (enc->segment_hdr_.num_segments_ > 1) { |
202 uint8_t* const probas = enc->proba_.segments_; | 209 uint8_t* const probas = enc->proba_.segments_; |
203 probas[0] = GetProba(p[0] + p[1], p[2] + p[3]); | 210 probas[0] = GetProba(p[0] + p[1], p[2] + p[3]); |
204 probas[1] = GetProba(p[0], p[1]); | 211 probas[1] = GetProba(p[0], p[1]); |
205 probas[2] = GetProba(p[2], p[3]); | 212 probas[2] = GetProba(p[2], p[3]); |
206 | 213 |
207 enc->segment_hdr_.update_map_ = | 214 enc->segment_hdr_.update_map_ = |
208 (probas[0] != 255) || (probas[1] != 255) || (probas[2] != 255); | 215 (probas[0] != 255) || (probas[1] != 255) || (probas[2] != 255); |
| 216 if (!enc->segment_hdr_.update_map_) ResetSegments(enc); |
209 enc->segment_hdr_.size_ = | 217 enc->segment_hdr_.size_ = |
210 p[0] * (VP8BitCost(0, probas[0]) + VP8BitCost(0, probas[1])) + | 218 p[0] * (VP8BitCost(0, probas[0]) + VP8BitCost(0, probas[1])) + |
211 p[1] * (VP8BitCost(0, probas[0]) + VP8BitCost(1, probas[1])) + | 219 p[1] * (VP8BitCost(0, probas[0]) + VP8BitCost(1, probas[1])) + |
212 p[2] * (VP8BitCost(1, probas[0]) + VP8BitCost(0, probas[2])) + | 220 p[2] * (VP8BitCost(1, probas[0]) + VP8BitCost(0, probas[2])) + |
213 p[3] * (VP8BitCost(1, probas[0]) + VP8BitCost(1, probas[2])); | 221 p[3] * (VP8BitCost(1, probas[0]) + VP8BitCost(1, probas[2])); |
214 } else { | 222 } else { |
215 enc->segment_hdr_.update_map_ = 0; | 223 enc->segment_hdr_.update_map_ = 0; |
216 enc->segment_hdr_.size_ = 0; | 224 enc->segment_hdr_.size_ = 0; |
217 } | 225 } |
218 } | 226 } |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
399 int x, y, ch; | 407 int x, y, ch; |
400 VP8Residual res; | 408 VP8Residual res; |
401 VP8Encoder* const enc = it->enc_; | 409 VP8Encoder* const enc = it->enc_; |
402 | 410 |
403 VP8IteratorNzToBytes(it); | 411 VP8IteratorNzToBytes(it); |
404 if (it->mb_->type_ == 1) { // i16x16 | 412 if (it->mb_->type_ == 1) { // i16x16 |
405 const int ctx = it->top_nz_[8] + it->left_nz_[8]; | 413 const int ctx = it->top_nz_[8] + it->left_nz_[8]; |
406 VP8InitResidual(0, 1, enc, &res); | 414 VP8InitResidual(0, 1, enc, &res); |
407 VP8SetResidualCoeffs(rd->y_dc_levels, &res); | 415 VP8SetResidualCoeffs(rd->y_dc_levels, &res); |
408 it->top_nz_[8] = it->left_nz_[8] = | 416 it->top_nz_[8] = it->left_nz_[8] = |
409 VP8RecordCoeffTokens(ctx, 1, | 417 VP8RecordCoeffTokens(ctx, &res, tokens); |
410 res.first, res.last, res.coeffs, tokens); | |
411 VP8RecordCoeffs(ctx, &res); | |
412 VP8InitResidual(1, 0, enc, &res); | 418 VP8InitResidual(1, 0, enc, &res); |
413 } else { | 419 } else { |
414 VP8InitResidual(0, 3, enc, &res); | 420 VP8InitResidual(0, 3, enc, &res); |
415 } | 421 } |
416 | 422 |
417 // luma-AC | 423 // luma-AC |
418 for (y = 0; y < 4; ++y) { | 424 for (y = 0; y < 4; ++y) { |
419 for (x = 0; x < 4; ++x) { | 425 for (x = 0; x < 4; ++x) { |
420 const int ctx = it->top_nz_[x] + it->left_nz_[y]; | 426 const int ctx = it->top_nz_[x] + it->left_nz_[y]; |
421 VP8SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res); | 427 VP8SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res); |
422 it->top_nz_[x] = it->left_nz_[y] = | 428 it->top_nz_[x] = it->left_nz_[y] = |
423 VP8RecordCoeffTokens(ctx, res.coeff_type, | 429 VP8RecordCoeffTokens(ctx, &res, tokens); |
424 res.first, res.last, res.coeffs, tokens); | |
425 VP8RecordCoeffs(ctx, &res); | |
426 } | 430 } |
427 } | 431 } |
428 | 432 |
429 // U/V | 433 // U/V |
430 VP8InitResidual(0, 2, enc, &res); | 434 VP8InitResidual(0, 2, enc, &res); |
431 for (ch = 0; ch <= 2; ch += 2) { | 435 for (ch = 0; ch <= 2; ch += 2) { |
432 for (y = 0; y < 2; ++y) { | 436 for (y = 0; y < 2; ++y) { |
433 for (x = 0; x < 2; ++x) { | 437 for (x = 0; x < 2; ++x) { |
434 const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y]; | 438 const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y]; |
435 VP8SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res); | 439 VP8SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res); |
436 it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = | 440 it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = |
437 VP8RecordCoeffTokens(ctx, 2, | 441 VP8RecordCoeffTokens(ctx, &res, tokens); |
438 res.first, res.last, res.coeffs, tokens); | |
439 VP8RecordCoeffs(ctx, &res); | |
440 } | 442 } |
441 } | 443 } |
442 } | 444 } |
443 VP8IteratorBytesToNz(it); | 445 VP8IteratorBytesToNz(it); |
444 return !tokens->error_; | 446 return !tokens->error_; |
445 } | 447 } |
446 | 448 |
447 #endif // !DISABLE_TOKEN_BUFFER | 449 #endif // !DISABLE_TOKEN_BUFFER |
448 | 450 |
449 //------------------------------------------------------------------------------ | 451 //------------------------------------------------------------------------------ |
(...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
807 stats.value = (double)size; | 809 stats.value = (double)size; |
808 } else { // compute and store PSNR | 810 } else { // compute and store PSNR |
809 stats.value = GetPSNR(distortion, pixel_count); | 811 stats.value = GetPSNR(distortion, pixel_count); |
810 } | 812 } |
811 | 813 |
812 #if (DEBUG_SEARCH > 0) | 814 #if (DEBUG_SEARCH > 0) |
813 printf("#%2d metric:%.1lf -> %.1lf last_q=%.2lf q=%.2lf dq=%.2lf\n", | 815 printf("#%2d metric:%.1lf -> %.1lf last_q=%.2lf q=%.2lf dq=%.2lf\n", |
814 num_pass_left, stats.last_value, stats.value, | 816 num_pass_left, stats.last_value, stats.value, |
815 stats.last_q, stats.q, stats.dq); | 817 stats.last_q, stats.q, stats.dq); |
816 #endif | 818 #endif |
817 if (size_p0 > PARTITION0_SIZE_LIMIT) { | 819 if (enc->max_i4_header_bits_ > 0 && size_p0 > PARTITION0_SIZE_LIMIT) { |
818 ++num_pass_left; | 820 ++num_pass_left; |
819 enc->max_i4_header_bits_ >>= 1; // strengthen header bit limitation... | 821 enc->max_i4_header_bits_ >>= 1; // strengthen header bit limitation... |
820 continue; // ...and start over | 822 continue; // ...and start over |
821 } | 823 } |
822 if (is_last_pass) { | 824 if (is_last_pass) { |
823 break; // done | 825 break; // done |
824 } | 826 } |
825 if (do_search) { | 827 if (do_search) { |
826 ComputeNextQ(&stats); // Adjust q | 828 ComputeNextQ(&stats); // Adjust q |
827 } | 829 } |
(...skipping 13 matching lines...) Expand all Loading... |
841 | 843 |
842 int VP8EncTokenLoop(VP8Encoder* const enc) { | 844 int VP8EncTokenLoop(VP8Encoder* const enc) { |
843 (void)enc; | 845 (void)enc; |
844 return 0; // we shouldn't be here. | 846 return 0; // we shouldn't be here. |
845 } | 847 } |
846 | 848 |
847 #endif // DISABLE_TOKEN_BUFFER | 849 #endif // DISABLE_TOKEN_BUFFER |
848 | 850 |
849 //------------------------------------------------------------------------------ | 851 //------------------------------------------------------------------------------ |
850 | 852 |
OLD | NEW |