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

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

Issue 10832153: libwebp: update snapshot to v0.2.0-rc1 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 4 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
OLDNEW
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 // frame coding and analysis 8 // frame coding and analysis
9 // 9 //
10 // Author: Skal (pascal.massimino@gmail.com) 10 // Author: Skal (pascal.massimino@gmail.com)
11 11
12 #include <stdlib.h> 12 #include <stdlib.h>
13 #include <string.h> 13 #include <string.h>
14 #include <assert.h>
15 #include <math.h> 14 #include <math.h>
16 15
17 #include "vp8enci.h" 16 #include "./vp8enci.h"
18 #include "cost.h" 17 #include "./cost.h"
19 18
20 #if defined(__cplusplus) || defined(c_plusplus) 19 #if defined(__cplusplus) || defined(c_plusplus)
21 extern "C" { 20 extern "C" {
22 #endif 21 #endif
23 22
24 #define SEGMENT_VISU 0 23 #define SEGMENT_VISU 0
25 #define DEBUG_SEARCH 0 // useful to track search convergence 24 #define DEBUG_SEARCH 0 // useful to track search convergence
26 25
27 // On-the-fly info about the current set of residuals. Handy to avoid 26 // On-the-fly info about the current set of residuals. Handy to avoid
28 // passing zillions of params. 27 // passing zillions of params.
(...skipping 27 matching lines...) Expand all
56 55
57 static void ResetStats(VP8Encoder* const enc, int precalc_cost) { 56 static void ResetStats(VP8Encoder* const enc, int precalc_cost) {
58 VP8Proba* const proba = &enc->proba_; 57 VP8Proba* const proba = &enc->proba_;
59 if (precalc_cost) VP8CalculateLevelCosts(proba); 58 if (precalc_cost) VP8CalculateLevelCosts(proba);
60 proba->nb_skip_ = 0; 59 proba->nb_skip_ = 0;
61 } 60 }
62 61
63 //------------------------------------------------------------------------------ 62 //------------------------------------------------------------------------------
64 // Skip decision probability 63 // Skip decision probability
65 64
65 #define SKIP_PROBA_THRESHOLD 250 // value below which using skip_proba is OK.
66
66 static int CalcSkipProba(uint64_t nb, uint64_t total) { 67 static int CalcSkipProba(uint64_t nb, uint64_t total) {
67 return (int)(total ? (total - nb) * 255 / total : 255); 68 return (int)(total ? (total - nb) * 255 / total : 255);
68 } 69 }
69 70
70 // Returns the bit-cost for coding the skip probability. 71 // Returns the bit-cost for coding the skip probability.
71 static int FinalizeSkipProba(VP8Encoder* const enc) { 72 static int FinalizeSkipProba(VP8Encoder* const enc) {
72 VP8Proba* const proba = &enc->proba_; 73 VP8Proba* const proba = &enc->proba_;
73 const int nb_mbs = enc->mb_w_ * enc->mb_h_; 74 const int nb_mbs = enc->mb_w_ * enc->mb_h_;
74 const int nb_events = proba->nb_skip_; 75 const int nb_events = proba->nb_skip_;
75 int size; 76 int size;
76 proba->skip_proba_ = CalcSkipProba(nb_events, nb_mbs); 77 proba->skip_proba_ = CalcSkipProba(nb_events, nb_mbs);
77 proba->use_skip_proba_ = (proba->skip_proba_ < 250); 78 proba->use_skip_proba_ = (proba->skip_proba_ < SKIP_PROBA_THRESHOLD);
78 size = 256; // 'use_skip_proba' bit 79 size = 256; // 'use_skip_proba' bit
79 if (proba->use_skip_proba_) { 80 if (proba->use_skip_proba_) {
80 size += nb_events * VP8BitCost(1, proba->skip_proba_) 81 size += nb_events * VP8BitCost(1, proba->skip_proba_)
81 + (nb_mbs - nb_events) * VP8BitCost(0, proba->skip_proba_); 82 + (nb_mbs - nb_events) * VP8BitCost(0, proba->skip_proba_);
82 size += 8 * 256; // cost of signaling the skip_proba_ itself. 83 size += 8 * 256; // cost of signaling the skip_proba_ itself.
83 } 84 }
84 return size; 85 return size;
85 } 86 }
86 87
87 //------------------------------------------------------------------------------ 88 //------------------------------------------------------------------------------
88 // Recording of token probabilities. 89 // Recording of token probabilities.
89 90
90 static void ResetTokenStats(VP8Encoder* const enc) { 91 static void ResetTokenStats(VP8Encoder* const enc) {
91 VP8Proba* const proba = &enc->proba_; 92 VP8Proba* const proba = &enc->proba_;
92 memset(proba->stats_, 0, sizeof(proba->stats_)); 93 memset(proba->stats_, 0, sizeof(proba->stats_));
93 } 94 }
94 95
95 // Record proba context used 96 // Record proba context used
96 static int Record(int bit, uint64_t* const stats) { 97 static int Record(int bit, uint64_t* const stats) {
97 stats[0] += bit; 98 stats[0] += bit;
98 stats[1] += 1; 99 stats[1] += 1;
99 return bit; 100 return bit;
100 } 101 }
101 102
102 // We keep the table free variant around for reference, in case. 103 // We keep the table free variant around for reference, in case.
103 #define USE_LEVEL_CODE_TABLE 104 #define USE_LEVEL_CODE_TABLE
104 105
105 // Simulate block coding, but only record statistics. 106 // Simulate block coding, but only record statistics.
106 // Note: no need to record the fixed probas. 107 // Note: no need to record the fixed probas.
107 static int RecordCoeffs(int ctx, VP8Residual* res) { 108 static int RecordCoeffs(int ctx, const VP8Residual* const res) {
108 int n = res->first; 109 int n = res->first;
109 uint64_t (*s)[2] = res->stats[VP8EncBands[n]][ctx]; 110 uint64_t (*s)[2] = res->stats[VP8EncBands[n]][ctx];
110 if (!Record(res->last >= 0, s[0])) { 111 if (!Record(res->last >= 0, s[0])) {
111 return 0; 112 return 0;
112 } 113 }
113 114
114 while (1) { 115 while (1) {
115 int v = res->coeffs[n++]; 116 int v = res->coeffs[n++];
116 if (!Record(v != 0, s[1])) { 117 if (!Record(v != 0, s[1])) {
117 s = res->stats[VP8EncBands[n]][0]; 118 s = res->stats[VP8EncBands[n]][0];
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
216 res->coeffs = coeffs; 217 res->coeffs = coeffs;
217 } 218 }
218 219
219 //------------------------------------------------------------------------------ 220 //------------------------------------------------------------------------------
220 // Mode costs 221 // Mode costs
221 222
222 static int GetResidualCost(int ctx, const VP8Residual* const res) { 223 static int GetResidualCost(int ctx, const VP8Residual* const res) {
223 int n = res->first; 224 int n = res->first;
224 const uint8_t* p = res->prob[VP8EncBands[n]][ctx]; 225 const uint8_t* p = res->prob[VP8EncBands[n]][ctx];
225 const uint16_t *t = res->cost[VP8EncBands[n]][ctx]; 226 const uint16_t *t = res->cost[VP8EncBands[n]][ctx];
227 int last_p0 = p[0];
226 int cost; 228 int cost;
227 229
228 cost = VP8BitCost(res->last >= 0, p[0]);
229 if (res->last < 0) { 230 if (res->last < 0) {
230 return cost; 231 return VP8BitCost(0, last_p0);
231 } 232 }
233 cost = 0;
232 while (n <= res->last) { 234 while (n <= res->last) {
233 const int v = res->coeffs[n++]; 235 const int v = res->coeffs[n];
236 const int b = VP8EncBands[n + 1];
237 ++n;
234 if (v == 0) { 238 if (v == 0) {
235 cost += VP8LevelCost(t, 0); 239 cost += VP8LevelCost(t, 0);
236 p = res->prob[VP8EncBands[n]][0]; 240 p = res->prob[b][0];
237 t = res->cost[VP8EncBands[n]][0]; 241 t = res->cost[b][0];
238 continue; 242 continue;
239 } else if (2u >= (unsigned int)(v + 1)) { // v = -1 or 1 243 }
244 cost += VP8BitCost(1, last_p0);
245 if (2u >= (unsigned int)(v + 1)) { // v = -1 or 1
240 cost += VP8LevelCost(t, 1); 246 cost += VP8LevelCost(t, 1);
241 p = res->prob[VP8EncBands[n]][1]; 247 p = res->prob[b][1];
242 t = res->cost[VP8EncBands[n]][1]; 248 t = res->cost[b][1];
243 } else { 249 } else {
244 cost += VP8LevelCost(t, abs(v)); 250 cost += VP8LevelCost(t, abs(v));
245 p = res->prob[VP8EncBands[n]][2]; 251 p = res->prob[b][2];
246 t = res->cost[VP8EncBands[n]][2]; 252 t = res->cost[b][2];
247 } 253 }
248 if (n < 16) { 254 last_p0 = p[0];
249 cost += VP8BitCost(n <= res->last, p[0]);
250 }
251 } 255 }
256 if (n < 16) cost += VP8BitCost(0, last_p0);
252 return cost; 257 return cost;
253 } 258 }
254 259
255 int VP8GetCostLuma4(VP8EncIterator* const it, const int16_t levels[16]) { 260 int VP8GetCostLuma4(VP8EncIterator* const it, const int16_t levels[16]) {
256 const int x = (it->i4_ & 3), y = (it->i4_ >> 2); 261 const int x = (it->i4_ & 3), y = (it->i4_ >> 2);
257 VP8Residual res; 262 VP8Residual res;
263 VP8Encoder* const enc = it->enc_;
258 int R = 0; 264 int R = 0;
259 int ctx; 265 int ctx;
260 266
261 InitResidual(0, 3, it->enc_, &res); 267 InitResidual(0, 3, enc, &res);
262 ctx = it->top_nz_[x] + it->left_nz_[y]; 268 ctx = it->top_nz_[x] + it->left_nz_[y];
263 SetResidualCoeffs(levels, &res); 269 SetResidualCoeffs(levels, &res);
264 R += GetResidualCost(ctx, &res); 270 R += GetResidualCost(ctx, &res);
265 return R; 271 return R;
266 } 272 }
267 273
268 int VP8GetCostLuma16(VP8EncIterator* const it, const VP8ModeScore* const rd) { 274 int VP8GetCostLuma16(VP8EncIterator* const it, const VP8ModeScore* const rd) {
269 VP8Residual res; 275 VP8Residual res;
276 VP8Encoder* const enc = it->enc_;
270 int x, y; 277 int x, y;
271 int R = 0; 278 int R = 0;
272 279
273 VP8IteratorNzToBytes(it); // re-import the non-zero context 280 VP8IteratorNzToBytes(it); // re-import the non-zero context
274 281
275 // DC 282 // DC
276 InitResidual(0, 1, it->enc_, &res); 283 InitResidual(0, 1, enc, &res);
277 SetResidualCoeffs(rd->y_dc_levels, &res); 284 SetResidualCoeffs(rd->y_dc_levels, &res);
278 R += GetResidualCost(it->top_nz_[8] + it->left_nz_[8], &res); 285 R += GetResidualCost(it->top_nz_[8] + it->left_nz_[8], &res);
279 286
280 // AC 287 // AC
281 InitResidual(1, 0, it->enc_, &res); 288 InitResidual(1, 0, enc, &res);
282 for (y = 0; y < 4; ++y) { 289 for (y = 0; y < 4; ++y) {
283 for (x = 0; x < 4; ++x) { 290 for (x = 0; x < 4; ++x) {
284 const int ctx = it->top_nz_[x] + it->left_nz_[y]; 291 const int ctx = it->top_nz_[x] + it->left_nz_[y];
285 SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res); 292 SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res);
286 R += GetResidualCost(ctx, &res); 293 R += GetResidualCost(ctx, &res);
287 it->top_nz_[x] = it->left_nz_[y] = (res.last >= 0); 294 it->top_nz_[x] = it->left_nz_[y] = (res.last >= 0);
288 } 295 }
289 } 296 }
290 return R; 297 return R;
291 } 298 }
292 299
293 int VP8GetCostUV(VP8EncIterator* const it, const VP8ModeScore* const rd) { 300 int VP8GetCostUV(VP8EncIterator* const it, const VP8ModeScore* const rd) {
294 VP8Residual res; 301 VP8Residual res;
302 VP8Encoder* const enc = it->enc_;
295 int ch, x, y; 303 int ch, x, y;
296 int R = 0; 304 int R = 0;
297 305
298 VP8IteratorNzToBytes(it); // re-import the non-zero context 306 VP8IteratorNzToBytes(it); // re-import the non-zero context
299 307
300 InitResidual(0, 2, it->enc_, &res); 308 InitResidual(0, 2, enc, &res);
301 for (ch = 0; ch <= 2; ch += 2) { 309 for (ch = 0; ch <= 2; ch += 2) {
302 for (y = 0; y < 2; ++y) { 310 for (y = 0; y < 2; ++y) {
303 for (x = 0; x < 2; ++x) { 311 for (x = 0; x < 2; ++x) {
304 const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y]; 312 const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y];
305 SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res); 313 SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res);
306 R += GetResidualCost(ctx, &res); 314 R += GetResidualCost(ctx, &res);
307 it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = (res.last >= 0); 315 it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = (res.last >= 0);
308 } 316 }
309 } 317 }
310 } 318 }
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
386 } 394 }
387 395
388 static void CodeResiduals(VP8BitWriter* const bw, 396 static void CodeResiduals(VP8BitWriter* const bw,
389 VP8EncIterator* const it, 397 VP8EncIterator* const it,
390 const VP8ModeScore* const rd) { 398 const VP8ModeScore* const rd) {
391 int x, y, ch; 399 int x, y, ch;
392 VP8Residual res; 400 VP8Residual res;
393 uint64_t pos1, pos2, pos3; 401 uint64_t pos1, pos2, pos3;
394 const int i16 = (it->mb_->type_ == 1); 402 const int i16 = (it->mb_->type_ == 1);
395 const int segment = it->mb_->segment_; 403 const int segment = it->mb_->segment_;
404 VP8Encoder* const enc = it->enc_;
396 405
397 VP8IteratorNzToBytes(it); 406 VP8IteratorNzToBytes(it);
398 407
399 pos1 = VP8BitWriterPos(bw); 408 pos1 = VP8BitWriterPos(bw);
400 if (i16) { 409 if (i16) {
401 InitResidual(0, 1, it->enc_, &res); 410 InitResidual(0, 1, enc, &res);
402 SetResidualCoeffs(rd->y_dc_levels, &res); 411 SetResidualCoeffs(rd->y_dc_levels, &res);
403 it->top_nz_[8] = it->left_nz_[8] = 412 it->top_nz_[8] = it->left_nz_[8] =
404 PutCoeffs(bw, it->top_nz_[8] + it->left_nz_[8], &res); 413 PutCoeffs(bw, it->top_nz_[8] + it->left_nz_[8], &res);
405 InitResidual(1, 0, it->enc_, &res); 414 InitResidual(1, 0, enc, &res);
406 } else { 415 } else {
407 InitResidual(0, 3, it->enc_, &res); 416 InitResidual(0, 3, enc, &res);
408 } 417 }
409 418
410 // luma-AC 419 // luma-AC
411 for (y = 0; y < 4; ++y) { 420 for (y = 0; y < 4; ++y) {
412 for (x = 0; x < 4; ++x) { 421 for (x = 0; x < 4; ++x) {
413 const int ctx = it->top_nz_[x] + it->left_nz_[y]; 422 const int ctx = it->top_nz_[x] + it->left_nz_[y];
414 SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res); 423 SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res);
415 it->top_nz_[x] = it->left_nz_[y] = PutCoeffs(bw, ctx, &res); 424 it->top_nz_[x] = it->left_nz_[y] = PutCoeffs(bw, ctx, &res);
416 } 425 }
417 } 426 }
418 pos2 = VP8BitWriterPos(bw); 427 pos2 = VP8BitWriterPos(bw);
419 428
420 // U/V 429 // U/V
421 InitResidual(0, 2, it->enc_, &res); 430 InitResidual(0, 2, enc, &res);
422 for (ch = 0; ch <= 2; ch += 2) { 431 for (ch = 0; ch <= 2; ch += 2) {
423 for (y = 0; y < 2; ++y) { 432 for (y = 0; y < 2; ++y) {
424 for (x = 0; x < 2; ++x) { 433 for (x = 0; x < 2; ++x) {
425 const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y]; 434 const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y];
426 SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res); 435 SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res);
427 it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = 436 it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] =
428 PutCoeffs(bw, ctx, &res); 437 PutCoeffs(bw, ctx, &res);
429 } 438 }
430 } 439 }
431 } 440 }
432 pos3 = VP8BitWriterPos(bw); 441 pos3 = VP8BitWriterPos(bw);
433 it->luma_bits_ = pos2 - pos1; 442 it->luma_bits_ = pos2 - pos1;
434 it->uv_bits_ = pos3 - pos2; 443 it->uv_bits_ = pos3 - pos2;
435 it->bit_count_[segment][i16] += it->luma_bits_; 444 it->bit_count_[segment][i16] += it->luma_bits_;
436 it->bit_count_[segment][2] += it->uv_bits_; 445 it->bit_count_[segment][2] += it->uv_bits_;
437 VP8IteratorBytesToNz(it); 446 VP8IteratorBytesToNz(it);
438 } 447 }
439 448
440 // Same as CodeResiduals, but doesn't actually write anything. 449 // Same as CodeResiduals, but doesn't actually write anything.
441 // Instead, it just records the event distribution. 450 // Instead, it just records the event distribution.
442 static void RecordResiduals(VP8EncIterator* const it, 451 static void RecordResiduals(VP8EncIterator* const it,
443 const VP8ModeScore* const rd) { 452 const VP8ModeScore* const rd) {
444 int x, y, ch; 453 int x, y, ch;
445 VP8Residual res; 454 VP8Residual res;
455 VP8Encoder* const enc = it->enc_;
446 456
447 VP8IteratorNzToBytes(it); 457 VP8IteratorNzToBytes(it);
448 458
449 if (it->mb_->type_ == 1) { // i16x16 459 if (it->mb_->type_ == 1) { // i16x16
450 InitResidual(0, 1, it->enc_, &res); 460 InitResidual(0, 1, enc, &res);
451 SetResidualCoeffs(rd->y_dc_levels, &res); 461 SetResidualCoeffs(rd->y_dc_levels, &res);
452 it->top_nz_[8] = it->left_nz_[8] = 462 it->top_nz_[8] = it->left_nz_[8] =
453 RecordCoeffs(it->top_nz_[8] + it->left_nz_[8], &res); 463 RecordCoeffs(it->top_nz_[8] + it->left_nz_[8], &res);
454 InitResidual(1, 0, it->enc_, &res); 464 InitResidual(1, 0, enc, &res);
455 } else { 465 } else {
456 InitResidual(0, 3, it->enc_, &res); 466 InitResidual(0, 3, enc, &res);
457 } 467 }
458 468
459 // luma-AC 469 // luma-AC
460 for (y = 0; y < 4; ++y) { 470 for (y = 0; y < 4; ++y) {
461 for (x = 0; x < 4; ++x) { 471 for (x = 0; x < 4; ++x) {
462 const int ctx = it->top_nz_[x] + it->left_nz_[y]; 472 const int ctx = it->top_nz_[x] + it->left_nz_[y];
463 SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res); 473 SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res);
464 it->top_nz_[x] = it->left_nz_[y] = RecordCoeffs(ctx, &res); 474 it->top_nz_[x] = it->left_nz_[y] = RecordCoeffs(ctx, &res);
465 } 475 }
466 } 476 }
467 477
468 // U/V 478 // U/V
469 InitResidual(0, 2, it->enc_, &res); 479 InitResidual(0, 2, enc, &res);
470 for (ch = 0; ch <= 2; ch += 2) { 480 for (ch = 0; ch <= 2; ch += 2) {
471 for (y = 0; y < 2; ++y) { 481 for (y = 0; y < 2; ++y) {
472 for (x = 0; x < 2; ++x) { 482 for (x = 0; x < 2; ++x) {
473 const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y]; 483 const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y];
474 SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res); 484 SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res);
475 it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = 485 it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] =
476 RecordCoeffs(ctx, &res); 486 RecordCoeffs(ctx, &res);
477 } 487 }
478 } 488 }
479 } 489 }
480 490
481 VP8IteratorBytesToNz(it); 491 VP8IteratorBytesToNz(it);
482 } 492 }
483 493
484 //------------------------------------------------------------------------------ 494 //------------------------------------------------------------------------------
495 // Token buffer
496
497 #ifdef USE_TOKEN_BUFFER
498
499 void VP8TBufferInit(VP8TBuffer* const b) {
500 b->rows_ = NULL;
501 b->tokens_ = NULL;
502 b->last_ = &b->rows_;
503 b->left_ = 0;
504 b->error_ = 0;
505 }
506
507 int VP8TBufferNewPage(VP8TBuffer* const b) {
508 VP8Tokens* const page = b->error_ ? NULL : (VP8Tokens*)malloc(sizeof(*page));
509 if (page == NULL) {
510 b->error_ = 1;
511 return 0;
512 }
513 *b->last_ = page;
514 b->last_ = &page->next_;
515 b->left_ = MAX_NUM_TOKEN;
516 b->tokens_ = page->tokens_;
517 return 1;
518 }
519
520 void VP8TBufferClear(VP8TBuffer* const b) {
521 if (b != NULL) {
522 const VP8Tokens* p = b->rows_;
523 while (p != NULL) {
524 const VP8Tokens* const next = p->next_;
525 free((void*)p);
526 p = next;
527 }
528 VP8TBufferInit(b);
529 }
530 }
531
532 int VP8EmitTokens(const VP8TBuffer* const b, VP8BitWriter* const bw,
533 const uint8_t* const probas) {
534 VP8Tokens* p = b->rows_;
535 if (b->error_) return 0;
536 while (p != NULL) {
537 const int N = (p->next_ == NULL) ? b->left_ : 0;
538 int n = MAX_NUM_TOKEN;
539 while (n-- > N) {
540 VP8PutBit(bw, (p->tokens_[n] >> 15) & 1, probas[p->tokens_[n] & 0x7fff]);
541 }
542 p = p->next_;
543 }
544 return 1;
545 }
546
547 #define TOKEN_ID(b, ctx, p) ((p) + NUM_PROBAS * ((ctx) + (b) * NUM_CTX))
548
549 static int RecordCoeffTokens(int ctx, const VP8Residual* const res,
550 VP8TBuffer* tokens) {
551 int n = res->first;
552 int b = VP8EncBands[n];
553 if (!VP8AddToken(tokens, res->last >= 0, TOKEN_ID(b, ctx, 0))) {
554 return 0;
555 }
556
557 while (n < 16) {
558 const int c = res->coeffs[n++];
559 const int sign = c < 0;
560 int v = sign ? -c : c;
561 const int base_id = TOKEN_ID(b, ctx, 0);
562 if (!VP8AddToken(tokens, v != 0, base_id + 1)) {
563 b = VP8EncBands[n];
564 ctx = 0;
565 continue;
566 }
567 if (!VP8AddToken(tokens, v > 1, base_id + 2)) {
568 b = VP8EncBands[n];
569 ctx = 1;
570 } else {
571 if (!VP8AddToken(tokens, v > 4, base_id + 3)) {
572 if (VP8AddToken(tokens, v != 2, base_id + 4))
573 VP8AddToken(tokens, v == 4, base_id + 5);
574 } else if (!VP8AddToken(tokens, v > 10, base_id + 6)) {
575 if (!VP8AddToken(tokens, v > 6, base_id + 7)) {
576 // VP8AddToken(tokens, v == 6, 159);
577 } else {
578 // VP8AddToken(tokens, v >= 9, 165);
579 // VP8AddToken(tokens, !(v & 1), 145);
580 }
581 } else {
582 int mask;
583 const uint8_t* tab;
584 if (v < 3 + (8 << 1)) { // kCat3 (3b)
585 VP8AddToken(tokens, 0, base_id + 8);
586 VP8AddToken(tokens, 0, base_id + 9);
587 v -= 3 + (8 << 0);
588 mask = 1 << 2;
589 tab = kCat3;
590 } else if (v < 3 + (8 << 2)) { // kCat4 (4b)
591 VP8AddToken(tokens, 0, base_id + 8);
592 VP8AddToken(tokens, 1, base_id + 9);
593 v -= 3 + (8 << 1);
594 mask = 1 << 3;
595 tab = kCat4;
596 } else if (v < 3 + (8 << 3)) { // kCat5 (5b)
597 VP8AddToken(tokens, 1, base_id + 8);
598 VP8AddToken(tokens, 0, base_id + 10);
599 v -= 3 + (8 << 2);
600 mask = 1 << 4;
601 tab = kCat5;
602 } else { // kCat6 (11b)
603 VP8AddToken(tokens, 1, base_id + 8);
604 VP8AddToken(tokens, 1, base_id + 10);
605 v -= 3 + (8 << 3);
606 mask = 1 << 10;
607 tab = kCat6;
608 }
609 while (mask) {
610 // VP8AddToken(tokens, !!(v & mask), *tab++);
611 mask >>= 1;
612 }
613 }
614 ctx = 2;
615 }
616 b = VP8EncBands[n];
617 // VP8PutBitUniform(bw, sign);
618 if (n == 16 || !VP8AddToken(tokens, n <= res->last, TOKEN_ID(b, ctx, 0))) {
619 return 1; // EOB
620 }
621 }
622 return 1;
623 }
624
625 static void RecordTokens(VP8EncIterator* const it,
626 const VP8ModeScore* const rd, VP8TBuffer tokens[2]) {
627 int x, y, ch;
628 VP8Residual res;
629 VP8Encoder* const enc = it->enc_;
630
631 VP8IteratorNzToBytes(it);
632 if (it->mb_->type_ == 1) { // i16x16
633 InitResidual(0, 1, enc, &res);
634 SetResidualCoeffs(rd->y_dc_levels, &res);
635 // TODO(skal): FIX -> it->top_nz_[8] = it->left_nz_[8] =
636 RecordCoeffTokens(it->top_nz_[8] + it->left_nz_[8], &res, &tokens[0]);
637 InitResidual(1, 0, enc, &res);
638 } else {
639 InitResidual(0, 3, enc, &res);
640 }
641
642 // luma-AC
643 for (y = 0; y < 4; ++y) {
644 for (x = 0; x < 4; ++x) {
645 const int ctx = it->top_nz_[x] + it->left_nz_[y];
646 SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res);
647 it->top_nz_[x] = it->left_nz_[y] =
648 RecordCoeffTokens(ctx, &res, &tokens[0]);
649 }
650 }
651
652 // U/V
653 InitResidual(0, 2, enc, &res);
654 for (ch = 0; ch <= 2; ch += 2) {
655 for (y = 0; y < 2; ++y) {
656 for (x = 0; x < 2; ++x) {
657 const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y];
658 SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res);
659 it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] =
660 RecordCoeffTokens(ctx, &res, &tokens[1]);
661 }
662 }
663 }
664 }
665
666 #endif // USE_TOKEN_BUFFER
667
668 //------------------------------------------------------------------------------
485 // ExtraInfo map / Debug function 669 // ExtraInfo map / Debug function
486 670
487 #if SEGMENT_VISU 671 #if SEGMENT_VISU
488 static void SetBlock(uint8_t* p, int value, int size) { 672 static void SetBlock(uint8_t* p, int value, int size) {
489 int y; 673 int y;
490 for (y = 0; y < size; ++y) { 674 for (y = 0; y < size; ++y) {
491 memset(p, value, size); 675 memset(p, value, size);
492 p += BPS; 676 p += BPS;
493 } 677 }
494 } 678 }
(...skipping 13 matching lines...) Expand all
508 enc->sse_[1] += VP8SSE8x8(in + U_OFF, out + U_OFF); 692 enc->sse_[1] += VP8SSE8x8(in + U_OFF, out + U_OFF);
509 enc->sse_[2] += VP8SSE8x8(in + V_OFF, out + V_OFF); 693 enc->sse_[2] += VP8SSE8x8(in + V_OFF, out + V_OFF);
510 enc->sse_count_ += 16 * 16; 694 enc->sse_count_ += 16 * 16;
511 } 695 }
512 696
513 static void StoreSideInfo(const VP8EncIterator* const it) { 697 static void StoreSideInfo(const VP8EncIterator* const it) {
514 VP8Encoder* const enc = it->enc_; 698 VP8Encoder* const enc = it->enc_;
515 const VP8MBInfo* const mb = it->mb_; 699 const VP8MBInfo* const mb = it->mb_;
516 WebPPicture* const pic = enc->pic_; 700 WebPPicture* const pic = enc->pic_;
517 701
518 if (pic->stats) { 702 if (pic->stats != NULL) {
519 StoreSSE(it); 703 StoreSSE(it);
520 enc->block_count_[0] += (mb->type_ == 0); 704 enc->block_count_[0] += (mb->type_ == 0);
521 enc->block_count_[1] += (mb->type_ == 1); 705 enc->block_count_[1] += (mb->type_ == 1);
522 enc->block_count_[2] += (mb->skip_ != 0); 706 enc->block_count_[2] += (mb->skip_ != 0);
523 } 707 }
524 708
525 if (pic->extra_info) { 709 if (pic->extra_info != NULL) {
526 uint8_t* const info = &pic->extra_info[it->x_ + it->y_ * enc->mb_w_]; 710 uint8_t* const info = &pic->extra_info[it->x_ + it->y_ * enc->mb_w_];
527 switch(pic->extra_info_type) { 711 switch (pic->extra_info_type) {
528 case 1: *info = mb->type_; break; 712 case 1: *info = mb->type_; break;
529 case 2: *info = mb->segment_; break; 713 case 2: *info = mb->segment_; break;
530 case 3: *info = enc->dqm_[mb->segment_].quant_; break; 714 case 3: *info = enc->dqm_[mb->segment_].quant_; break;
531 case 4: *info = (mb->type_ == 1) ? it->preds_[0] : 0xff; break; 715 case 4: *info = (mb->type_ == 1) ? it->preds_[0] : 0xff; break;
532 case 5: *info = mb->uv_mode_; break; 716 case 5: *info = mb->uv_mode_; break;
533 case 6: { 717 case 6: {
534 const int b = (int)((it->luma_bits_ + it->uv_bits_ + 7) >> 3); 718 const int b = (int)((it->luma_bits_ + it->uv_bits_ + 7) >> 3);
535 *info = (b > 255) ? 255 : b; break; 719 *info = (b > 255) ? 255 : b; break;
536 } 720 }
537 default: *info = 0; break; 721 default: *info = 0; break;
(...skipping 15 matching lines...) Expand all
553 if (it->mb_->type_ == 1) { 737 if (it->mb_->type_ == 1) {
554 *it->nz_ = 0; // reset all predictors 738 *it->nz_ = 0; // reset all predictors
555 it->left_nz_[8] = 0; 739 it->left_nz_[8] = 0;
556 } else { 740 } else {
557 *it->nz_ &= (1 << 24); // preserve the dc_nz bit 741 *it->nz_ &= (1 << 24); // preserve the dc_nz bit
558 } 742 }
559 } 743 }
560 744
561 int VP8EncLoop(VP8Encoder* const enc) { 745 int VP8EncLoop(VP8Encoder* const enc) {
562 int i, s, p; 746 int i, s, p;
747 int ok = 1;
563 VP8EncIterator it; 748 VP8EncIterator it;
564 VP8ModeScore info; 749 VP8ModeScore info;
565 const int dont_use_skip = !enc->proba_.use_skip_proba_; 750 const int dont_use_skip = !enc->proba_.use_skip_proba_;
566 const int rd_opt = enc->rd_opt_level_; 751 const int rd_opt = enc->rd_opt_level_;
567 const int kAverageBytesPerMB = 5; // TODO: have a kTable[quality/10] 752 const int kAverageBytesPerMB = 5; // TODO: have a kTable[quality/10]
568 const int bytes_per_parts = 753 const int bytes_per_parts =
569 enc->mb_w_ * enc->mb_h_ * kAverageBytesPerMB / enc->num_parts_; 754 enc->mb_w_ * enc->mb_h_ * kAverageBytesPerMB / enc->num_parts_;
570 755
571 // Initialize the bit-writers 756 // Initialize the bit-writers
572 for (p = 0; p < enc->num_parts_; ++p) { 757 for (p = 0; p < enc->num_parts_; ++p) {
573 VP8BitWriterInit(enc->parts_ + p, bytes_per_parts); 758 VP8BitWriterInit(enc->parts_ + p, bytes_per_parts);
574 } 759 }
575 760
576 ResetStats(enc, rd_opt != 0); 761 ResetStats(enc, rd_opt != 0);
577 ResetSSE(enc); 762 ResetSSE(enc);
578 763
579 VP8IteratorInit(enc, &it); 764 VP8IteratorInit(enc, &it);
580 VP8InitFilter(&it); 765 VP8InitFilter(&it);
581 do { 766 do {
582 VP8IteratorImport(&it); 767 VP8IteratorImport(&it);
583 // Warning! order is important: first call VP8Decimate() and 768 // Warning! order is important: first call VP8Decimate() and
584 // *then* decide how to code the skip decision if there's one. 769 // *then* decide how to code the skip decision if there's one.
585 if (!VP8Decimate(&it, &info, rd_opt) || dont_use_skip) { 770 if (!VP8Decimate(&it, &info, rd_opt) || dont_use_skip) {
586 CodeResiduals(it.bw_, &it, &info); 771 CodeResiduals(it.bw_, &it, &info);
587 } else { // reset predictors after a skip 772 } else { // reset predictors after a skip
588 ResetAfterSkip(&it); 773 ResetAfterSkip(&it);
589 } 774 }
590 #ifdef WEBP_EXPERIMENTAL_FEATURES 775 #ifdef WEBP_EXPERIMENTAL_FEATURES
591 if (enc->has_alpha_) {
592 VP8EncCodeAlphaBlock(&it);
593 }
594 if (enc->use_layer_) { 776 if (enc->use_layer_) {
595 VP8EncCodeLayerBlock(&it); 777 VP8EncCodeLayerBlock(&it);
596 } 778 }
597 #endif 779 #endif
598 StoreSideInfo(&it); 780 StoreSideInfo(&it);
599 VP8StoreFilterStats(&it); 781 VP8StoreFilterStats(&it);
600 VP8IteratorExport(&it); 782 VP8IteratorExport(&it);
601 } while (VP8IteratorNext(&it, it.yuv_out_)); 783 ok = VP8IteratorProgress(&it, 20);
602 VP8AdjustFilterStrength(&it); 784 } while (ok && VP8IteratorNext(&it, it.yuv_out_));
603 785
604 // Finalize the partitions 786 if (ok) { // Finalize the partitions, check for extra errors.
605 for (p = 0; p < enc->num_parts_; ++p) { 787 for (p = 0; p < enc->num_parts_; ++p) {
606 VP8BitWriterFinish(enc->parts_ + p); 788 VP8BitWriterFinish(enc->parts_ + p);
789 ok &= !enc->parts_[p].error_;
790 }
607 } 791 }
608 // and byte counters 792
609 if (enc->pic_->stats) { 793 if (ok) { // All good. Finish up.
610 for (i = 0; i <= 2; ++i) { 794 if (enc->pic_->stats) { // finalize byte counters...
611 for (s = 0; s < NUM_MB_SEGMENTS; ++s) { 795 for (i = 0; i <= 2; ++i) {
612 enc->residual_bytes_[i][s] = (int)((it.bit_count_[s][i] + 7) >> 3); 796 for (s = 0; s < NUM_MB_SEGMENTS; ++s) {
797 enc->residual_bytes_[i][s] = (int)((it.bit_count_[s][i] + 7) >> 3);
798 }
613 } 799 }
614 } 800 }
801 VP8AdjustFilterStrength(&it); // ...and store filter stats.
802 } else {
803 // Something bad happened -> need to do some memory cleanup.
804 VP8EncFreeBitWriters(enc);
615 } 805 }
616 return 1; 806
807 return ok;
617 } 808 }
618 809
619 //------------------------------------------------------------------------------ 810 //------------------------------------------------------------------------------
620 // VP8StatLoop(): only collect statistics (number of skips, token usage, ...) 811 // VP8StatLoop(): only collect statistics (number of skips, token usage, ...)
621 // This is used for deciding optimal probabilities. It also 812 // This is used for deciding optimal probabilities. It also
622 // modifies the quantizer value if some target (size, PNSR) 813 // modifies the quantizer value if some target (size, PNSR)
623 // was specified. 814 // was specified.
624 815
625 #define kHeaderSizeEstimate (15 + 20 + 10) // TODO: fix better 816 #define kHeaderSizeEstimate (15 + 20 + 10) // TODO: fix better
626 817
627 static int OneStatPass(VP8Encoder* const enc, float q, int rd_opt, int nb_mbs, 818 static int OneStatPass(VP8Encoder* const enc, float q, int rd_opt, int nb_mbs,
628 float* const PSNR) { 819 float* const PSNR, int percent_delta) {
629 VP8EncIterator it; 820 VP8EncIterator it;
630 uint64_t size = 0; 821 uint64_t size = 0;
631 uint64_t distortion = 0; 822 uint64_t distortion = 0;
632 const uint64_t pixel_count = nb_mbs * 384; 823 const uint64_t pixel_count = nb_mbs * 384;
633 824
634 // Make sure the quality parameter is inside valid bounds 825 // Make sure the quality parameter is inside valid bounds
635 if (q < 0.) { 826 if (q < 0.) {
636 q = 0; 827 q = 0;
637 } else if (q > 100.) { 828 } else if (q > 100.) {
638 q = 100; 829 q = 100;
639 } 830 }
640 831
641 VP8SetSegmentParams(enc, q); // setup segment quantizations and filters 832 VP8SetSegmentParams(enc, q); // setup segment quantizations and filters
642 833
643 ResetStats(enc, rd_opt != 0); 834 ResetStats(enc, rd_opt != 0);
644 ResetTokenStats(enc); 835 ResetTokenStats(enc);
645 836
646 VP8IteratorInit(enc, &it); 837 VP8IteratorInit(enc, &it);
647 do { 838 do {
648 VP8ModeScore info; 839 VP8ModeScore info;
649 VP8IteratorImport(&it); 840 VP8IteratorImport(&it);
650 if (VP8Decimate(&it, &info, rd_opt)) { 841 if (VP8Decimate(&it, &info, rd_opt)) {
651 // Just record the number of skips and act like skip_proba is not used. 842 // Just record the number of skips and act like skip_proba is not used.
652 enc->proba_.nb_skip_++; 843 enc->proba_.nb_skip_++;
653 } 844 }
654 RecordResiduals(&it, &info); 845 RecordResiduals(&it, &info);
655 size += info.R; 846 size += info.R;
656 distortion += info.D; 847 distortion += info.D;
848 if (percent_delta && !VP8IteratorProgress(&it, percent_delta))
849 return 0;
657 } while (VP8IteratorNext(&it, it.yuv_out_) && --nb_mbs > 0); 850 } while (VP8IteratorNext(&it, it.yuv_out_) && --nb_mbs > 0);
658 size += FinalizeSkipProba(enc); 851 size += FinalizeSkipProba(enc);
659 size += FinalizeTokenProbas(enc); 852 size += FinalizeTokenProbas(enc);
660 size += enc->segment_hdr_.size_; 853 size += enc->segment_hdr_.size_;
661 size = ((size + 1024) >> 11) + kHeaderSizeEstimate; 854 size = ((size + 1024) >> 11) + kHeaderSizeEstimate;
662 855
663 if (PSNR) { 856 if (PSNR) {
664 *PSNR = (float)(10.* log10(255. * 255. * pixel_count / distortion)); 857 *PSNR = (float)(10.* log10(255. * 255. * pixel_count / distortion));
665 } 858 }
666 return (int)size; 859 return (int)size;
667 } 860 }
668 861
669 // successive refinement increments. 862 // successive refinement increments.
670 static const int dqs[] = { 20, 15, 10, 8, 6, 4, 2, 1, 0 }; 863 static const int dqs[] = { 20, 15, 10, 8, 6, 4, 2, 1, 0 };
671 864
672 int VP8StatLoop(VP8Encoder* const enc) { 865 int VP8StatLoop(VP8Encoder* const enc) {
673 const int do_search = 866 const int do_search =
674 (enc->config_->target_size > 0 || enc->config_->target_PSNR > 0); 867 (enc->config_->target_size > 0 || enc->config_->target_PSNR > 0);
675 const int fast_probe = (enc->method_ < 2 && !do_search); 868 const int fast_probe = (enc->method_ < 2 && !do_search);
676 float q = enc->config_->quality; 869 float q = enc->config_->quality;
870 const int max_passes = enc->config_->pass;
871 const int task_percent = 20;
872 const int percent_per_pass = (task_percent + max_passes / 2) / max_passes;
873 const int final_percent = enc->percent_ + task_percent;
677 int pass; 874 int pass;
678 int nb_mbs; 875 int nb_mbs;
679 876
680 // Fast mode: quick analysis pass over few mbs. Better than nothing. 877 // Fast mode: quick analysis pass over few mbs. Better than nothing.
681 nb_mbs = enc->mb_w_ * enc->mb_h_; 878 nb_mbs = enc->mb_w_ * enc->mb_h_;
682 if (fast_probe && nb_mbs > 100) nb_mbs = 100; 879 if (fast_probe && nb_mbs > 100) nb_mbs = 100;
683 880
684 // No target size: just do several pass without changing 'q' 881 // No target size: just do several pass without changing 'q'
685 if (!do_search) { 882 if (!do_search) {
686 for (pass = 0; pass < enc->config_->pass; ++pass) { 883 for (pass = 0; pass < max_passes; ++pass) {
687 const int rd_opt = (enc->method_ > 2); 884 const int rd_opt = (enc->method_ > 2);
688 OneStatPass(enc, q, rd_opt, nb_mbs, NULL); 885 if (!OneStatPass(enc, q, rd_opt, nb_mbs, NULL, percent_per_pass)) {
886 return 0;
887 }
689 } 888 }
690 return 1; 889 } else {
691 } 890 // binary search for a size close to target
692 891 for (pass = 0; pass < max_passes && (dqs[pass] > 0); ++pass) {
693 // binary search for a size close to target 892 const int rd_opt = 1;
694 for (pass = 0; pass < enc->config_->pass && (dqs[pass] > 0); ++pass) { 893 float PSNR;
695 const int rd_opt = 1; 894 int criterion;
696 float PSNR; 895 const int size = OneStatPass(enc, q, rd_opt, nb_mbs, &PSNR,
697 int criterion; 896 percent_per_pass);
698 const int size = OneStatPass(enc, q, rd_opt, nb_mbs, &PSNR);
699 #if DEBUG_SEARCH 897 #if DEBUG_SEARCH
700 printf("#%d size=%d PSNR=%.2f q=%.2f\n", pass, size, PSNR, q); 898 printf("#%d size=%d PSNR=%.2f q=%.2f\n", pass, size, PSNR, q);
701 #endif 899 #endif
702 900 if (!size) return 0;
703 if (enc->config_->target_PSNR > 0) { 901 if (enc->config_->target_PSNR > 0) {
704 criterion = (PSNR < enc->config_->target_PSNR); 902 criterion = (PSNR < enc->config_->target_PSNR);
705 } else { 903 } else {
706 criterion = (size < enc->config_->target_size); 904 criterion = (size < enc->config_->target_size);
707 } 905 }
708 // dichotomize 906 // dichotomize
709 if (criterion) { 907 if (criterion) {
710 q += dqs[pass]; 908 q += dqs[pass];
711 } else { 909 } else {
712 q -= dqs[pass]; 910 q -= dqs[pass];
911 }
713 } 912 }
714 } 913 }
715 return 1; 914 return WebPReportProgress(enc->pic_, final_percent, &enc->percent_);
716 } 915 }
717 916
718 //------------------------------------------------------------------------------ 917 //------------------------------------------------------------------------------
719 918
720 #if defined(__cplusplus) || defined(c_plusplus) 919 #if defined(__cplusplus) || defined(c_plusplus)
721 } // extern "C" 920 } // extern "C"
722 #endif 921 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698