frame_enc.c (29398B)
1 // Copyright 2011 Google Inc. All Rights Reserved. 2 // 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 5 // tree. An additional intellectual property rights grant can be found 6 // in the file PATENTS. All contributing project authors may 7 // be found in the AUTHORS file in the root of the source tree. 8 // ----------------------------------------------------------------------------- 9 // 10 // frame coding and analysis 11 // 12 // Author: Skal (pascal.massimino@gmail.com) 13 14 #include <assert.h> 15 #include <math.h> 16 #include <string.h> 17 18 #include "src/dec/common_dec.h" 19 #include "src/webp/types.h" 20 #include "src/dsp/dsp.h" 21 #include "src/enc/cost_enc.h" 22 #include "src/enc/vp8i_enc.h" 23 #include "src/utils/bit_writer_utils.h" 24 #include "src/webp/encode.h" 25 #include "src/webp/format_constants.h" // RIFF constants 26 27 #define SEGMENT_VISU 0 28 #define DEBUG_SEARCH 0 // useful to track search convergence 29 30 //------------------------------------------------------------------------------ 31 // multi-pass convergence 32 33 #define HEADER_SIZE_ESTIMATE (RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE + \ 34 VP8_FRAME_HEADER_SIZE) 35 #define DQ_LIMIT 0.4 // convergence is considered reached if dq < DQ_LIMIT 36 // we allow 2k of extra head-room in PARTITION0 limit. 37 #define PARTITION0_SIZE_LIMIT ((VP8_MAX_PARTITION0_SIZE - 2048ULL) << 11) 38 39 static float Clamp(float v, float min, float max) { 40 return (v < min) ? min : (v > max) ? max : v; 41 } 42 43 typedef struct { // struct for organizing convergence in either size or PSNR 44 int is_first; 45 float dq; 46 float q, last_q; 47 float qmin, qmax; 48 double value, last_value; // PSNR or size 49 double target; 50 int do_size_search; 51 } PassStats; 52 53 static int InitPassStats(const VP8Encoder* const enc, PassStats* const s) { 54 const uint64_t target_size = (uint64_t)enc->config->target_size; 55 const int do_size_search = (target_size != 0); 56 const float target_PSNR = enc->config->target_PSNR; 57 58 s->is_first = 1; 59 s->dq = 10.f; 60 s->qmin = 1.f * enc->config->qmin; 61 s->qmax = 1.f * enc->config->qmax; 62 s->q = s->last_q = Clamp(enc->config->quality, s->qmin, s->qmax); 63 s->target = do_size_search ? (double)target_size 64 : (target_PSNR > 0.) ? target_PSNR 65 : 40.; // default, just in case 66 s->value = s->last_value = 0.; 67 s->do_size_search = do_size_search; 68 return do_size_search; 69 } 70 71 static float ComputeNextQ(PassStats* const s) { 72 float dq; 73 if (s->is_first) { 74 dq = (s->value > s->target) ? -s->dq : s->dq; 75 s->is_first = 0; 76 } else if (s->value != s->last_value) { 77 const double slope = (s->target - s->value) / (s->last_value - s->value); 78 dq = (float)(slope * (s->last_q - s->q)); 79 } else { 80 dq = 0.; // we're done?! 81 } 82 // Limit variable to avoid large swings. 83 s->dq = Clamp(dq, -30.f, 30.f); 84 s->last_q = s->q; 85 s->last_value = s->value; 86 s->q = Clamp(s->q + s->dq, s->qmin, s->qmax); 87 return s->q; 88 } 89 90 //------------------------------------------------------------------------------ 91 // Tables for level coding 92 93 const uint8_t VP8Cat3[] = { 173, 148, 140 }; 94 const uint8_t VP8Cat4[] = { 176, 155, 140, 135 }; 95 const uint8_t VP8Cat5[] = { 180, 157, 141, 134, 130 }; 96 const uint8_t VP8Cat6[] = 97 { 254, 254, 243, 230, 196, 177, 153, 140, 133, 130, 129 }; 98 99 //------------------------------------------------------------------------------ 100 // Reset the statistics about: number of skips, token proba, level cost,... 101 102 static void ResetStats(VP8Encoder* const enc) { 103 VP8EncProba* const proba = &enc->proba; 104 VP8CalculateLevelCosts(proba); 105 proba->nb_skip = 0; 106 } 107 108 //------------------------------------------------------------------------------ 109 // Skip decision probability 110 111 #define SKIP_PROBA_THRESHOLD 250 // value below which using skip_proba is OK. 112 113 static int CalcSkipProba(uint64_t nb, uint64_t total) { 114 return (int)(total ? (total - nb) * 255 / total : 255); 115 } 116 117 // Returns the bit-cost for coding the skip probability. 118 static int FinalizeSkipProba(VP8Encoder* const enc) { 119 VP8EncProba* const proba = &enc->proba; 120 const int nb_mbs = enc->mb_w * enc->mb_h; 121 const int nb_events = proba->nb_skip; 122 int size; 123 proba->skip_proba = CalcSkipProba(nb_events, nb_mbs); 124 proba->use_skip_proba = (proba->skip_proba < SKIP_PROBA_THRESHOLD); 125 size = 256; // 'use_skip_proba' bit 126 if (proba->use_skip_proba) { 127 size += nb_events * VP8BitCost(1, proba->skip_proba) 128 + (nb_mbs - nb_events) * VP8BitCost(0, proba->skip_proba); 129 size += 8 * 256; // cost of signaling the 'skip_proba' itself. 130 } 131 return size; 132 } 133 134 // Collect statistics and deduce probabilities for next coding pass. 135 // Return the total bit-cost for coding the probability updates. 136 static int CalcTokenProba(int nb, int total) { 137 assert(nb <= total); 138 return nb ? (255 - nb * 255 / total) : 255; 139 } 140 141 // Cost of coding 'nb' 1's and 'total-nb' 0's using 'proba' probability. 142 static int BranchCost(int nb, int total, int proba) { 143 return nb * VP8BitCost(1, proba) + (total - nb) * VP8BitCost(0, proba); 144 } 145 146 static void ResetTokenStats(VP8Encoder* const enc) { 147 VP8EncProba* const proba = &enc->proba; 148 memset(proba->stats, 0, sizeof(proba->stats)); 149 } 150 151 static int FinalizeTokenProbas(VP8EncProba* const proba) { 152 int has_changed = 0; 153 int size = 0; 154 int t, b, c, p; 155 for (t = 0; t < NUM_TYPES; ++t) { 156 for (b = 0; b < NUM_BANDS; ++b) { 157 for (c = 0; c < NUM_CTX; ++c) { 158 for (p = 0; p < NUM_PROBAS; ++p) { 159 const proba_t stats = proba->stats[t][b][c][p]; 160 const int nb = (stats >> 0) & 0xffff; 161 const int total = (stats >> 16) & 0xffff; 162 const int update_proba = VP8CoeffsUpdateProba[t][b][c][p]; 163 const int old_p = VP8CoeffsProba0[t][b][c][p]; 164 const int new_p = CalcTokenProba(nb, total); 165 const int old_cost = BranchCost(nb, total, old_p) 166 + VP8BitCost(0, update_proba); 167 const int new_cost = BranchCost(nb, total, new_p) 168 + VP8BitCost(1, update_proba) 169 + 8 * 256; 170 const int use_new_p = (old_cost > new_cost); 171 size += VP8BitCost(use_new_p, update_proba); 172 if (use_new_p) { // only use proba that seem meaningful enough. 173 proba->coeffs[t][b][c][p] = new_p; 174 has_changed |= (new_p != old_p); 175 size += 8 * 256; 176 } else { 177 proba->coeffs[t][b][c][p] = old_p; 178 } 179 } 180 } 181 } 182 } 183 proba->dirty = has_changed; 184 return size; 185 } 186 187 //------------------------------------------------------------------------------ 188 // Finalize Segment probability based on the coding tree 189 190 static int GetProba(int a, int b) { 191 const int total = a + b; 192 return (total == 0) ? 255 // that's the default probability. 193 : (255 * a + total / 2) / total; // rounded proba 194 } 195 196 static void ResetSegments(VP8Encoder* const enc) { 197 int n; 198 for (n = 0; n < enc->mb_w * enc->mb_h; ++n) { 199 enc->mb_info[n].segment = 0; 200 } 201 } 202 203 static void SetSegmentProbas(VP8Encoder* const enc) { 204 int p[NUM_MB_SEGMENTS] = { 0 }; 205 int n; 206 207 for (n = 0; n < enc->mb_w * enc->mb_h; ++n) { 208 const VP8MBInfo* const mb = &enc->mb_info[n]; 209 ++p[mb->segment]; 210 } 211 #if !defined(WEBP_DISABLE_STATS) 212 if (enc->pic->stats != NULL) { 213 for (n = 0; n < NUM_MB_SEGMENTS; ++n) { 214 enc->pic->stats->segment_size[n] = p[n]; 215 } 216 } 217 #endif 218 if (enc->segment_hdr.num_segments > 1) { 219 uint8_t* const probas = enc->proba.segments; 220 probas[0] = GetProba(p[0] + p[1], p[2] + p[3]); 221 probas[1] = GetProba(p[0], p[1]); 222 probas[2] = GetProba(p[2], p[3]); 223 224 enc->segment_hdr.update_map = 225 (probas[0] != 255) || (probas[1] != 255) || (probas[2] != 255); 226 if (!enc->segment_hdr.update_map) ResetSegments(enc); 227 enc->segment_hdr.size = 228 p[0] * (VP8BitCost(0, probas[0]) + VP8BitCost(0, probas[1])) + 229 p[1] * (VP8BitCost(0, probas[0]) + VP8BitCost(1, probas[1])) + 230 p[2] * (VP8BitCost(1, probas[0]) + VP8BitCost(0, probas[2])) + 231 p[3] * (VP8BitCost(1, probas[0]) + VP8BitCost(1, probas[2])); 232 } else { 233 enc->segment_hdr.update_map = 0; 234 enc->segment_hdr.size = 0; 235 } 236 } 237 238 //------------------------------------------------------------------------------ 239 // Coefficient coding 240 241 static int PutCoeffs(VP8BitWriter* const bw, int ctx, const VP8Residual* res) { 242 int n = res->first; 243 // should be prob[VP8EncBands[n]], but it's equivalent for n=0 or 1 244 const uint8_t* p = res->prob[n][ctx]; 245 if (!VP8PutBit(bw, res->last >= 0, p[0])) { 246 return 0; 247 } 248 249 while (n < 16) { 250 const int c = res->coeffs[n++]; 251 const int sign = c < 0; 252 int v = sign ? -c : c; 253 if (!VP8PutBit(bw, v != 0, p[1])) { 254 p = res->prob[VP8EncBands[n]][0]; 255 continue; 256 } 257 if (!VP8PutBit(bw, v > 1, p[2])) { 258 p = res->prob[VP8EncBands[n]][1]; 259 } else { 260 if (!VP8PutBit(bw, v > 4, p[3])) { 261 if (VP8PutBit(bw, v != 2, p[4])) { 262 VP8PutBit(bw, v == 4, p[5]); 263 } 264 } else if (!VP8PutBit(bw, v > 10, p[6])) { 265 if (!VP8PutBit(bw, v > 6, p[7])) { 266 VP8PutBit(bw, v == 6, 159); 267 } else { 268 VP8PutBit(bw, v >= 9, 165); 269 VP8PutBit(bw, !(v & 1), 145); 270 } 271 } else { 272 int mask; 273 const uint8_t* tab; 274 if (v < 3 + (8 << 1)) { // VP8Cat3 (3b) 275 VP8PutBit(bw, 0, p[8]); 276 VP8PutBit(bw, 0, p[9]); 277 v -= 3 + (8 << 0); 278 mask = 1 << 2; 279 tab = VP8Cat3; 280 } else if (v < 3 + (8 << 2)) { // VP8Cat4 (4b) 281 VP8PutBit(bw, 0, p[8]); 282 VP8PutBit(bw, 1, p[9]); 283 v -= 3 + (8 << 1); 284 mask = 1 << 3; 285 tab = VP8Cat4; 286 } else if (v < 3 + (8 << 3)) { // VP8Cat5 (5b) 287 VP8PutBit(bw, 1, p[8]); 288 VP8PutBit(bw, 0, p[10]); 289 v -= 3 + (8 << 2); 290 mask = 1 << 4; 291 tab = VP8Cat5; 292 } else { // VP8Cat6 (11b) 293 VP8PutBit(bw, 1, p[8]); 294 VP8PutBit(bw, 1, p[10]); 295 v -= 3 + (8 << 3); 296 mask = 1 << 10; 297 tab = VP8Cat6; 298 } 299 while (mask) { 300 VP8PutBit(bw, !!(v & mask), *tab++); 301 mask >>= 1; 302 } 303 } 304 p = res->prob[VP8EncBands[n]][2]; 305 } 306 VP8PutBitUniform(bw, sign); 307 if (n == 16 || !VP8PutBit(bw, n <= res->last, p[0])) { 308 return 1; // EOB 309 } 310 } 311 return 1; 312 } 313 314 static void CodeResiduals(VP8BitWriter* const bw, VP8EncIterator* const it, 315 const VP8ModeScore* const rd) { 316 int x, y, ch; 317 VP8Residual res; 318 uint64_t pos1, pos2, pos3; 319 const int i16 = (it->mb->type == 1); 320 const int segment = it->mb->segment; 321 VP8Encoder* const enc = it->enc; 322 323 VP8IteratorNzToBytes(it); 324 325 pos1 = VP8BitWriterPos(bw); 326 if (i16) { 327 VP8InitResidual(0, 1, enc, &res); 328 VP8SetResidualCoeffs(rd->y_dc_levels, &res); 329 it->top_nz[8] = it->left_nz[8] = 330 PutCoeffs(bw, it->top_nz[8] + it->left_nz[8], &res); 331 VP8InitResidual(1, 0, enc, &res); 332 } else { 333 VP8InitResidual(0, 3, enc, &res); 334 } 335 336 // luma-AC 337 for (y = 0; y < 4; ++y) { 338 for (x = 0; x < 4; ++x) { 339 const int ctx = it->top_nz[x] + it->left_nz[y]; 340 VP8SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res); 341 it->top_nz[x] = it->left_nz[y] = PutCoeffs(bw, ctx, &res); 342 } 343 } 344 pos2 = VP8BitWriterPos(bw); 345 346 // U/V 347 VP8InitResidual(0, 2, enc, &res); 348 for (ch = 0; ch <= 2; ch += 2) { 349 for (y = 0; y < 2; ++y) { 350 for (x = 0; x < 2; ++x) { 351 const int ctx = it->top_nz[4 + ch + x] + it->left_nz[4 + ch + y]; 352 VP8SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res); 353 it->top_nz[4 + ch + x] = it->left_nz[4 + ch + y] = 354 PutCoeffs(bw, ctx, &res); 355 } 356 } 357 } 358 pos3 = VP8BitWriterPos(bw); 359 it->luma_bits = pos2 - pos1; 360 it->uv_bits = pos3 - pos2; 361 it->bit_count[segment][i16] += it->luma_bits; 362 it->bit_count[segment][2] += it->uv_bits; 363 VP8IteratorBytesToNz(it); 364 } 365 366 // Same as CodeResiduals, but doesn't actually write anything. 367 // Instead, it just records the event distribution. 368 static void RecordResiduals(VP8EncIterator* const it, 369 const VP8ModeScore* const rd) { 370 int x, y, ch; 371 VP8Residual res; 372 VP8Encoder* const enc = it->enc; 373 374 VP8IteratorNzToBytes(it); 375 376 if (it->mb->type == 1) { // i16x16 377 VP8InitResidual(0, 1, enc, &res); 378 VP8SetResidualCoeffs(rd->y_dc_levels, &res); 379 it->top_nz[8] = it->left_nz[8] = 380 VP8RecordCoeffs(it->top_nz[8] + it->left_nz[8], &res); 381 VP8InitResidual(1, 0, enc, &res); 382 } else { 383 VP8InitResidual(0, 3, enc, &res); 384 } 385 386 // luma-AC 387 for (y = 0; y < 4; ++y) { 388 for (x = 0; x < 4; ++x) { 389 const int ctx = it->top_nz[x] + it->left_nz[y]; 390 VP8SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res); 391 it->top_nz[x] = it->left_nz[y] = VP8RecordCoeffs(ctx, &res); 392 } 393 } 394 395 // U/V 396 VP8InitResidual(0, 2, enc, &res); 397 for (ch = 0; ch <= 2; ch += 2) { 398 for (y = 0; y < 2; ++y) { 399 for (x = 0; x < 2; ++x) { 400 const int ctx = it->top_nz[4 + ch + x] + it->left_nz[4 + ch + y]; 401 VP8SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res); 402 it->top_nz[4 + ch + x] = it->left_nz[4 + ch + y] = 403 VP8RecordCoeffs(ctx, &res); 404 } 405 } 406 } 407 408 VP8IteratorBytesToNz(it); 409 } 410 411 //------------------------------------------------------------------------------ 412 // Token buffer 413 414 #if !defined(DISABLE_TOKEN_BUFFER) 415 416 static int RecordTokens(VP8EncIterator* const it, const VP8ModeScore* const rd, 417 VP8TBuffer* const tokens) { 418 int x, y, ch; 419 VP8Residual res; 420 VP8Encoder* const enc = it->enc; 421 422 VP8IteratorNzToBytes(it); 423 if (it->mb->type == 1) { // i16x16 424 const int ctx = it->top_nz[8] + it->left_nz[8]; 425 VP8InitResidual(0, 1, enc, &res); 426 VP8SetResidualCoeffs(rd->y_dc_levels, &res); 427 it->top_nz[8] = it->left_nz[8] = 428 VP8RecordCoeffTokens(ctx, &res, tokens); 429 VP8InitResidual(1, 0, enc, &res); 430 } else { 431 VP8InitResidual(0, 3, enc, &res); 432 } 433 434 // luma-AC 435 for (y = 0; y < 4; ++y) { 436 for (x = 0; x < 4; ++x) { 437 const int ctx = it->top_nz[x] + it->left_nz[y]; 438 VP8SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res); 439 it->top_nz[x] = it->left_nz[y] = 440 VP8RecordCoeffTokens(ctx, &res, tokens); 441 } 442 } 443 444 // U/V 445 VP8InitResidual(0, 2, enc, &res); 446 for (ch = 0; ch <= 2; ch += 2) { 447 for (y = 0; y < 2; ++y) { 448 for (x = 0; x < 2; ++x) { 449 const int ctx = it->top_nz[4 + ch + x] + it->left_nz[4 + ch + y]; 450 VP8SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res); 451 it->top_nz[4 + ch + x] = it->left_nz[4 + ch + y] = 452 VP8RecordCoeffTokens(ctx, &res, tokens); 453 } 454 } 455 } 456 VP8IteratorBytesToNz(it); 457 return !tokens->error; 458 } 459 460 #endif // !DISABLE_TOKEN_BUFFER 461 462 //------------------------------------------------------------------------------ 463 // ExtraInfo map / Debug function 464 465 #if !defined(WEBP_DISABLE_STATS) 466 467 #if SEGMENT_VISU 468 static void SetBlock(uint8_t* p, int value, int size) { 469 int y; 470 for (y = 0; y < size; ++y) { 471 memset(p, value, size); 472 p += BPS; 473 } 474 } 475 #endif 476 477 static void ResetSSE(VP8Encoder* const enc) { 478 enc->sse[0] = 0; 479 enc->sse[1] = 0; 480 enc->sse[2] = 0; 481 // Note: enc->sse[3] is managed by alpha.c 482 enc->sse_count = 0; 483 } 484 485 static void StoreSSE(const VP8EncIterator* const it) { 486 VP8Encoder* const enc = it->enc; 487 const uint8_t* const in = it->yuv_in; 488 const uint8_t* const out = it->yuv_out; 489 // Note: not totally accurate at boundary. And doesn't include in-loop filter. 490 enc->sse[0] += VP8SSE16x16(in + Y_OFF_ENC, out + Y_OFF_ENC); 491 enc->sse[1] += VP8SSE8x8(in + U_OFF_ENC, out + U_OFF_ENC); 492 enc->sse[2] += VP8SSE8x8(in + V_OFF_ENC, out + V_OFF_ENC); 493 enc->sse_count += 16 * 16; 494 } 495 496 static void StoreSideInfo(const VP8EncIterator* const it) { 497 VP8Encoder* const enc = it->enc; 498 const VP8MBInfo* const mb = it->mb; 499 WebPPicture* const pic = enc->pic; 500 501 if (pic->stats != NULL) { 502 StoreSSE(it); 503 enc->block_count[0] += (mb->type == 0); 504 enc->block_count[1] += (mb->type == 1); 505 enc->block_count[2] += (mb->skip != 0); 506 } 507 508 if (pic->extra_info != NULL) { 509 uint8_t* const info = &pic->extra_info[it->x + it->y * enc->mb_w]; 510 switch (pic->extra_info_type) { 511 case 1: *info = mb->type; break; 512 case 2: *info = mb->segment; break; 513 case 3: *info = enc->dqm[mb->segment].quant; break; 514 case 4: *info = (mb->type == 1) ? it->preds[0] : 0xff; break; 515 case 5: *info = mb->uv_mode; break; 516 case 6: { 517 const int b = (int)((it->luma_bits + it->uv_bits + 7) >> 3); 518 *info = (b > 255) ? 255 : b; break; 519 } 520 case 7: *info = mb->alpha; break; 521 default: *info = 0; break; 522 } 523 } 524 #if SEGMENT_VISU // visualize segments and prediction modes 525 SetBlock(it->yuv_out + Y_OFF_ENC, mb->segment * 64, 16); 526 SetBlock(it->yuv_out + U_OFF_ENC, it->preds[0] * 64, 8); 527 SetBlock(it->yuv_out + V_OFF_ENC, mb->uv_mode * 64, 8); 528 #endif 529 } 530 531 static void ResetSideInfo(const VP8EncIterator* const it) { 532 VP8Encoder* const enc = it->enc; 533 WebPPicture* const pic = enc->pic; 534 if (pic->stats != NULL) { 535 memset(enc->block_count, 0, sizeof(enc->block_count)); 536 } 537 ResetSSE(enc); 538 } 539 #else // defined(WEBP_DISABLE_STATS) 540 static void ResetSSE(VP8Encoder* const enc) { 541 (void)enc; 542 } 543 static void StoreSideInfo(const VP8EncIterator* const it) { 544 VP8Encoder* const enc = it->enc; 545 WebPPicture* const pic = enc->pic; 546 if (pic->extra_info != NULL) { 547 if (it->x == 0 && it->y == 0) { // only do it once, at start 548 memset(pic->extra_info, 0, 549 enc->mb_w * enc->mb_h * sizeof(*pic->extra_info)); 550 } 551 } 552 } 553 554 static void ResetSideInfo(const VP8EncIterator* const it) { 555 (void)it; 556 } 557 #endif // !defined(WEBP_DISABLE_STATS) 558 559 static double GetPSNR(uint64_t mse, uint64_t size) { 560 return (mse > 0 && size > 0) ? 10. * log10(255. * 255. * size / mse) : 99; 561 } 562 563 //------------------------------------------------------------------------------ 564 // StatLoop(): only collect statistics (number of skips, token usage, ...). 565 // This is used for deciding optimal probabilities. It also modifies the 566 // quantizer value if some target (size, PSNR) was specified. 567 568 static void SetLoopParams(VP8Encoder* const enc, float q) { 569 // Make sure the quality parameter is inside valid bounds 570 q = Clamp(q, 0.f, 100.f); 571 572 VP8SetSegmentParams(enc, q); // setup segment quantizations and filters 573 SetSegmentProbas(enc); // compute segment probabilities 574 575 ResetStats(enc); 576 ResetSSE(enc); 577 } 578 579 static uint64_t OneStatPass(VP8Encoder* const enc, VP8RDLevel rd_opt, 580 int nb_mbs, int percent_delta, 581 PassStats* const s) { 582 VP8EncIterator it; 583 uint64_t size = 0; 584 uint64_t size_p0 = 0; 585 uint64_t distortion = 0; 586 const uint64_t pixel_count = (uint64_t)nb_mbs * 384; 587 588 VP8IteratorInit(enc, &it); 589 SetLoopParams(enc, s->q); 590 do { 591 VP8ModeScore info; 592 VP8IteratorImport(&it, NULL); 593 if (VP8Decimate(&it, &info, rd_opt)) { 594 // Just record the number of skips and act like skip_proba is not used. 595 ++enc->proba.nb_skip; 596 } 597 RecordResiduals(&it, &info); 598 size += info.R + info.H; 599 size_p0 += info.H; 600 distortion += info.D; 601 if (percent_delta && !VP8IteratorProgress(&it, percent_delta)) { 602 return 0; 603 } 604 VP8IteratorSaveBoundary(&it); 605 } while (VP8IteratorNext(&it) && --nb_mbs > 0); 606 607 size_p0 += enc->segment_hdr.size; 608 if (s->do_size_search) { 609 size += FinalizeSkipProba(enc); 610 size += FinalizeTokenProbas(&enc->proba); 611 size = ((size + size_p0 + 1024) >> 11) + HEADER_SIZE_ESTIMATE; 612 s->value = (double)size; 613 } else { 614 s->value = GetPSNR(distortion, pixel_count); 615 } 616 return size_p0; 617 } 618 619 static int StatLoop(VP8Encoder* const enc) { 620 const int method = enc->method; 621 const int do_search = enc->do_search; 622 const int fast_probe = ((method == 0 || method == 3) && !do_search); 623 int num_pass_left = enc->config->pass; 624 const int task_percent = 20; 625 const int percent_per_pass = 626 (task_percent + num_pass_left / 2) / num_pass_left; 627 const int final_percent = enc->percent + task_percent; 628 const VP8RDLevel rd_opt = 629 (method >= 3 || do_search) ? RD_OPT_BASIC : RD_OPT_NONE; 630 int nb_mbs = enc->mb_w * enc->mb_h; 631 PassStats stats; 632 633 InitPassStats(enc, &stats); 634 ResetTokenStats(enc); 635 636 // Fast mode: quick analysis pass over few mbs. Better than nothing. 637 if (fast_probe) { 638 if (method == 3) { // we need more stats for method 3 to be reliable. 639 nb_mbs = (nb_mbs > 200) ? nb_mbs >> 1 : 100; 640 } else { 641 nb_mbs = (nb_mbs > 200) ? nb_mbs >> 2 : 50; 642 } 643 } 644 645 while (num_pass_left-- > 0) { 646 const int is_last_pass = (fabs(stats.dq) <= DQ_LIMIT) || 647 (num_pass_left == 0) || 648 (enc->max_i4_header_bits == 0); 649 const uint64_t size_p0 = 650 OneStatPass(enc, rd_opt, nb_mbs, percent_per_pass, &stats); 651 if (size_p0 == 0) return 0; 652 #if (DEBUG_SEARCH > 0) 653 printf("#%d value:%.1lf -> %.1lf q:%.2f -> %.2f\n", 654 num_pass_left, stats.last_value, stats.value, stats.last_q, stats.q); 655 #endif 656 if (enc->max_i4_header_bits > 0 && size_p0 > PARTITION0_SIZE_LIMIT) { 657 ++num_pass_left; 658 enc->max_i4_header_bits >>= 1; // strengthen header bit limitation... 659 continue; // ...and start over 660 } 661 if (is_last_pass) { 662 break; 663 } 664 // If no target size: just do several pass without changing 'q' 665 if (do_search) { 666 ComputeNextQ(&stats); 667 if (fabs(stats.dq) <= DQ_LIMIT) break; 668 } 669 } 670 if (!do_search || !stats.do_size_search) { 671 // Need to finalize probas now, since it wasn't done during the search. 672 FinalizeSkipProba(enc); 673 FinalizeTokenProbas(&enc->proba); 674 } 675 VP8CalculateLevelCosts(&enc->proba); // finalize costs 676 return WebPReportProgress(enc->pic, final_percent, &enc->percent); 677 } 678 679 //------------------------------------------------------------------------------ 680 // Main loops 681 // 682 683 static const uint8_t kAverageBytesPerMB[8] = { 50, 24, 16, 9, 7, 5, 3, 2 }; 684 685 static int PreLoopInitialize(VP8Encoder* const enc) { 686 int p; 687 int ok = 1; 688 const int average_bytes_per_MB = kAverageBytesPerMB[enc->base_quant >> 4]; 689 const int bytes_per_parts = 690 enc->mb_w * enc->mb_h * average_bytes_per_MB / enc->num_parts; 691 // Initialize the bit-writers 692 for (p = 0; ok && p < enc->num_parts; ++p) { 693 ok = VP8BitWriterInit(enc->parts + p, bytes_per_parts); 694 } 695 if (!ok) { 696 VP8EncFreeBitWriters(enc); // malloc error occurred 697 return WebPEncodingSetError(enc->pic, VP8_ENC_ERROR_OUT_OF_MEMORY); 698 } 699 return ok; 700 } 701 702 static int PostLoopFinalize(VP8EncIterator* const it, int ok) { 703 VP8Encoder* const enc = it->enc; 704 if (ok) { // Finalize the partitions, check for extra errors. 705 int p; 706 for (p = 0; p < enc->num_parts; ++p) { 707 VP8BitWriterFinish(enc->parts + p); 708 ok &= !enc->parts[p].error; 709 } 710 } 711 712 if (ok) { // All good. Finish up. 713 #if !defined(WEBP_DISABLE_STATS) 714 if (enc->pic->stats != NULL) { // finalize byte counters... 715 int i, s; 716 for (i = 0; i <= 2; ++i) { 717 for (s = 0; s < NUM_MB_SEGMENTS; ++s) { 718 enc->residual_bytes[i][s] = (int)((it->bit_count[s][i] + 7) >> 3); 719 } 720 } 721 } 722 #endif 723 VP8AdjustFilterStrength(it); // ...and store filter stats. 724 } else { 725 // Something bad happened -> need to do some memory cleanup. 726 VP8EncFreeBitWriters(enc); 727 return WebPEncodingSetError(enc->pic, VP8_ENC_ERROR_OUT_OF_MEMORY); 728 } 729 return ok; 730 } 731 732 //------------------------------------------------------------------------------ 733 // VP8EncLoop(): does the final bitstream coding. 734 735 static void ResetAfterSkip(VP8EncIterator* const it) { 736 if (it->mb->type == 1) { 737 *it->nz = 0; // reset all predictors 738 it->left_nz[8] = 0; 739 } else { 740 *it->nz &= (1 << 24); // preserve the dc_nz bit 741 } 742 } 743 744 int VP8EncLoop(VP8Encoder* const enc) { 745 VP8EncIterator it; 746 int ok = PreLoopInitialize(enc); 747 if (!ok) return 0; 748 749 StatLoop(enc); // stats-collection loop 750 751 VP8IteratorInit(enc, &it); 752 VP8InitFilter(&it); 753 do { 754 VP8ModeScore info; 755 const int dont_use_skip = !enc->proba.use_skip_proba; 756 const VP8RDLevel rd_opt = enc->rd_opt_level; 757 758 VP8IteratorImport(&it, NULL); 759 // Warning! order is important: first call VP8Decimate() and 760 // *then* decide how to code the skip decision if there's one. 761 if (!VP8Decimate(&it, &info, rd_opt) || dont_use_skip) { 762 CodeResiduals(it.bw, &it, &info); 763 if (it.bw->error) { 764 // enc->pic->error_code is set in PostLoopFinalize(). 765 ok = 0; 766 break; 767 } 768 } else { // reset predictors after a skip 769 ResetAfterSkip(&it); 770 } 771 StoreSideInfo(&it); 772 VP8StoreFilterStats(&it); 773 VP8IteratorExport(&it); 774 ok = VP8IteratorProgress(&it, 20); 775 VP8IteratorSaveBoundary(&it); 776 } while (ok && VP8IteratorNext(&it)); 777 778 return PostLoopFinalize(&it, ok); 779 } 780 781 //------------------------------------------------------------------------------ 782 // Single pass using Token Buffer. 783 784 #if !defined(DISABLE_TOKEN_BUFFER) 785 786 #define MIN_COUNT 96 // minimum number of macroblocks before updating stats 787 788 int VP8EncTokenLoop(VP8Encoder* const enc) { 789 // Roughly refresh the proba eight times per pass 790 int max_count = (enc->mb_w * enc->mb_h) >> 3; 791 int num_pass_left = enc->config->pass; 792 int remaining_progress = 40; // percents 793 const int do_search = enc->do_search; 794 VP8EncIterator it; 795 VP8EncProba* const proba = &enc->proba; 796 const VP8RDLevel rd_opt = enc->rd_opt_level; 797 const uint64_t pixel_count = (uint64_t)enc->mb_w * enc->mb_h * 384; 798 PassStats stats; 799 int ok; 800 801 InitPassStats(enc, &stats); 802 ok = PreLoopInitialize(enc); 803 if (!ok) return 0; 804 805 if (max_count < MIN_COUNT) max_count = MIN_COUNT; 806 807 assert(enc->num_parts == 1); 808 assert(enc->use_tokens); 809 assert(proba->use_skip_proba == 0); 810 assert(rd_opt >= RD_OPT_BASIC); // otherwise, token-buffer won't be useful 811 assert(num_pass_left > 0); 812 813 while (ok && num_pass_left-- > 0) { 814 const int is_last_pass = (fabs(stats.dq) <= DQ_LIMIT) || 815 (num_pass_left == 0) || 816 (enc->max_i4_header_bits == 0); 817 uint64_t size_p0 = 0; 818 uint64_t distortion = 0; 819 int cnt = max_count; 820 // The final number of passes is not trivial to know in advance. 821 const int pass_progress = remaining_progress / (2 + num_pass_left); 822 remaining_progress -= pass_progress; 823 VP8IteratorInit(enc, &it); 824 SetLoopParams(enc, stats.q); 825 if (is_last_pass) { 826 ResetTokenStats(enc); 827 VP8InitFilter(&it); // don't collect stats until last pass (too costly) 828 } 829 VP8TBufferClear(&enc->tokens); 830 do { 831 VP8ModeScore info; 832 VP8IteratorImport(&it, NULL); 833 if (--cnt < 0) { 834 FinalizeTokenProbas(proba); 835 VP8CalculateLevelCosts(proba); // refresh cost tables for rd-opt 836 cnt = max_count; 837 } 838 VP8Decimate(&it, &info, rd_opt); 839 ok = RecordTokens(&it, &info, &enc->tokens); 840 if (!ok) { 841 WebPEncodingSetError(enc->pic, VP8_ENC_ERROR_OUT_OF_MEMORY); 842 break; 843 } 844 size_p0 += info.H; 845 distortion += info.D; 846 if (is_last_pass) { 847 StoreSideInfo(&it); 848 VP8StoreFilterStats(&it); 849 VP8IteratorExport(&it); 850 ok = VP8IteratorProgress(&it, pass_progress); 851 } 852 VP8IteratorSaveBoundary(&it); 853 } while (ok && VP8IteratorNext(&it)); 854 if (!ok) break; 855 856 size_p0 += enc->segment_hdr.size; 857 if (stats.do_size_search) { 858 uint64_t size = FinalizeTokenProbas(&enc->proba); 859 size += VP8EstimateTokenSize(&enc->tokens, 860 (const uint8_t*)proba->coeffs); 861 size = (size + size_p0 + 1024) >> 11; // -> size in bytes 862 size += HEADER_SIZE_ESTIMATE; 863 stats.value = (double)size; 864 } else { // compute and store PSNR 865 stats.value = GetPSNR(distortion, pixel_count); 866 } 867 868 #if (DEBUG_SEARCH > 0) 869 printf("#%2d metric:%.1lf -> %.1lf last_q=%.2lf q=%.2lf dq=%.2lf " 870 " range:[%.1f, %.1f]\n", 871 num_pass_left, stats.last_value, stats.value, 872 stats.last_q, stats.q, stats.dq, stats.qmin, stats.qmax); 873 #endif 874 if (enc->max_i4_header_bits > 0 && size_p0 > PARTITION0_SIZE_LIMIT) { 875 ++num_pass_left; 876 enc->max_i4_header_bits >>= 1; // strengthen header bit limitation... 877 if (is_last_pass) { 878 ResetSideInfo(&it); 879 } 880 continue; // ...and start over 881 } 882 if (is_last_pass) { 883 break; // done 884 } 885 if (do_search) { 886 ComputeNextQ(&stats); // Adjust q 887 } 888 } 889 if (ok) { 890 if (!stats.do_size_search) { 891 FinalizeTokenProbas(&enc->proba); 892 } 893 ok = VP8EmitTokens(&enc->tokens, enc->parts + 0, 894 (const uint8_t*)proba->coeffs, 1); 895 } 896 ok = ok && WebPReportProgress(enc->pic, enc->percent + remaining_progress, 897 &enc->percent); 898 return PostLoopFinalize(&it, ok); 899 } 900 901 #else 902 903 int VP8EncTokenLoop(VP8Encoder* const enc) { 904 (void)enc; 905 return 0; // we shouldn't be here. 906 } 907 908 #endif // DISABLE_TOKEN_BUFFER 909 910 //------------------------------------------------------------------------------