| OLD | NEW |
| 1 // Copyright 2010 Google Inc. All Rights Reserved. | 1 // Copyright 2010 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 // main entry for the decoder | 10 // main entry for the decoder |
| 11 // | 11 // |
| 12 // Author: Skal (pascal.massimino@gmail.com) | 12 // Author: Skal (pascal.massimino@gmail.com) |
| 13 | 13 |
| 14 #include <stdlib.h> | 14 #include <stdlib.h> |
| 15 | 15 |
| 16 #include "./alphai.h" |
| 16 #include "./vp8i.h" | 17 #include "./vp8i.h" |
| 17 #include "./vp8li.h" | 18 #include "./vp8li.h" |
| 18 #include "./webpi.h" | 19 #include "./webpi.h" |
| 19 #include "../utils/bit_reader.h" | 20 #include "../utils/bit_reader.h" |
| 20 | 21 |
| 21 #if defined(__cplusplus) || defined(c_plusplus) | |
| 22 extern "C" { | |
| 23 #endif | |
| 24 | |
| 25 //------------------------------------------------------------------------------ | 22 //------------------------------------------------------------------------------ |
| 26 | 23 |
| 27 int WebPGetDecoderVersion(void) { | 24 int WebPGetDecoderVersion(void) { |
| 28 return (DEC_MAJ_VERSION << 16) | (DEC_MIN_VERSION << 8) | DEC_REV_VERSION; | 25 return (DEC_MAJ_VERSION << 16) | (DEC_MIN_VERSION << 8) | DEC_REV_VERSION; |
| 29 } | 26 } |
| 30 | 27 |
| 31 //------------------------------------------------------------------------------ | 28 //------------------------------------------------------------------------------ |
| 32 // VP8Decoder | 29 // VP8Decoder |
| 33 | 30 |
| 34 static void SetOk(VP8Decoder* const dec) { | 31 static void SetOk(VP8Decoder* const dec) { |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 116 | 113 |
| 117 if (((bits >> 1) & 7) > 3) { | 114 if (((bits >> 1) & 7) > 3) { |
| 118 return 0; // unknown profile | 115 return 0; // unknown profile |
| 119 } | 116 } |
| 120 if (!((bits >> 4) & 1)) { | 117 if (!((bits >> 4) & 1)) { |
| 121 return 0; // first frame is invisible! | 118 return 0; // first frame is invisible! |
| 122 } | 119 } |
| 123 if (((bits >> 5)) >= chunk_size) { // partition_length | 120 if (((bits >> 5)) >= chunk_size) { // partition_length |
| 124 return 0; // inconsistent size information. | 121 return 0; // inconsistent size information. |
| 125 } | 122 } |
| 123 if (w == 0 || h == 0) { |
| 124 return 0; // We don't support both width and height to be zero. |
| 125 } |
| 126 | 126 |
| 127 if (width) { | 127 if (width) { |
| 128 *width = w; | 128 *width = w; |
| 129 } | 129 } |
| 130 if (height) { | 130 if (height) { |
| 131 *height = h; | 131 *height = h; |
| 132 } | 132 } |
| 133 | 133 |
| 134 return 1; | 134 return 1; |
| 135 } | 135 } |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 242 } | 242 } |
| 243 | 243 |
| 244 // Topmost call | 244 // Topmost call |
| 245 int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io) { | 245 int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io) { |
| 246 const uint8_t* buf; | 246 const uint8_t* buf; |
| 247 size_t buf_size; | 247 size_t buf_size; |
| 248 VP8FrameHeader* frm_hdr; | 248 VP8FrameHeader* frm_hdr; |
| 249 VP8PictureHeader* pic_hdr; | 249 VP8PictureHeader* pic_hdr; |
| 250 VP8BitReader* br; | 250 VP8BitReader* br; |
| 251 VP8StatusCode status; | 251 VP8StatusCode status; |
| 252 WebPHeaderStructure headers; | |
| 253 | 252 |
| 254 if (dec == NULL) { | 253 if (dec == NULL) { |
| 255 return 0; | 254 return 0; |
| 256 } | 255 } |
| 257 SetOk(dec); | 256 SetOk(dec); |
| 258 if (io == NULL) { | 257 if (io == NULL) { |
| 259 return VP8SetError(dec, VP8_STATUS_INVALID_PARAM, | 258 return VP8SetError(dec, VP8_STATUS_INVALID_PARAM, |
| 260 "null VP8Io passed to VP8GetHeaders()"); | 259 "null VP8Io passed to VP8GetHeaders()"); |
| 261 } | 260 } |
| 262 | 261 buf = io->data; |
| 263 // Process Pre-VP8 chunks. | 262 buf_size = io->data_size; |
| 264 headers.data = io->data; | |
| 265 headers.data_size = io->data_size; | |
| 266 status = WebPParseHeaders(&headers); | |
| 267 if (status != VP8_STATUS_OK) { | |
| 268 return VP8SetError(dec, status, "Incorrect/incomplete header."); | |
| 269 } | |
| 270 if (headers.is_lossless) { | |
| 271 return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR, | |
| 272 "Unexpected lossless format encountered."); | |
| 273 } | |
| 274 | |
| 275 if (dec->alpha_data_ == NULL) { | |
| 276 assert(dec->alpha_data_size_ == 0); | |
| 277 // We have NOT set alpha data yet. Set it now. | |
| 278 // (This is to ensure that dec->alpha_data_ is NOT reset to NULL if | |
| 279 // WebPParseHeaders() is called more than once, as in incremental decoding | |
| 280 // case.) | |
| 281 dec->alpha_data_ = headers.alpha_data; | |
| 282 dec->alpha_data_size_ = headers.alpha_data_size; | |
| 283 } | |
| 284 | |
| 285 // Process the VP8 frame header. | |
| 286 buf = headers.data + headers.offset; | |
| 287 buf_size = headers.data_size - headers.offset; | |
| 288 assert(headers.data_size >= headers.offset); // WebPParseHeaders' guarantee | |
| 289 if (buf_size < 4) { | 263 if (buf_size < 4) { |
| 290 return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA, | 264 return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA, |
| 291 "Truncated header."); | 265 "Truncated header."); |
| 292 } | 266 } |
| 293 | 267 |
| 294 // Paragraph 9.1 | 268 // Paragraph 9.1 |
| 295 { | 269 { |
| 296 const uint32_t bits = buf[0] | (buf[1] << 8) | (buf[2] << 16); | 270 const uint32_t bits = buf[0] | (buf[1] << 8) | (buf[2] << 16); |
| 297 frm_hdr = &dec->frm_hdr_; | 271 frm_hdr = &dec->frm_hdr_; |
| 298 frm_hdr->key_frame_ = !(bits & 1); | 272 frm_hdr->key_frame_ = !(bits & 1); |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 374 status = ParsePartitions(dec, buf, buf_size); | 348 status = ParsePartitions(dec, buf, buf_size); |
| 375 if (status != VP8_STATUS_OK) { | 349 if (status != VP8_STATUS_OK) { |
| 376 return VP8SetError(dec, status, "cannot parse partitions"); | 350 return VP8SetError(dec, status, "cannot parse partitions"); |
| 377 } | 351 } |
| 378 | 352 |
| 379 // quantizer change | 353 // quantizer change |
| 380 VP8ParseQuant(dec); | 354 VP8ParseQuant(dec); |
| 381 | 355 |
| 382 // Frame buffer marking | 356 // Frame buffer marking |
| 383 if (!frm_hdr->key_frame_) { | 357 if (!frm_hdr->key_frame_) { |
| 384 // Paragraph 9.7 | |
| 385 #ifndef ONLY_KEYFRAME_CODE | |
| 386 dec->buffer_flags_ = VP8Get(br) << 0; // update golden | |
| 387 dec->buffer_flags_ |= VP8Get(br) << 1; // update alt ref | |
| 388 if (!(dec->buffer_flags_ & 1)) { | |
| 389 dec->buffer_flags_ |= VP8GetValue(br, 2) << 2; | |
| 390 } | |
| 391 if (!(dec->buffer_flags_ & 2)) { | |
| 392 dec->buffer_flags_ |= VP8GetValue(br, 2) << 4; | |
| 393 } | |
| 394 dec->buffer_flags_ |= VP8Get(br) << 6; // sign bias golden | |
| 395 dec->buffer_flags_ |= VP8Get(br) << 7; // sign bias alt ref | |
| 396 #else | |
| 397 return VP8SetError(dec, VP8_STATUS_UNSUPPORTED_FEATURE, | 358 return VP8SetError(dec, VP8_STATUS_UNSUPPORTED_FEATURE, |
| 398 "Not a key frame."); | 359 "Not a key frame."); |
| 399 #endif | |
| 400 } else { | |
| 401 dec->buffer_flags_ = 0x003 | 0x100; | |
| 402 } | 360 } |
| 403 | 361 |
| 404 // Paragraph 9.8 | 362 VP8Get(br); // ignore the value of update_proba_ |
| 405 #ifndef ONLY_KEYFRAME_CODE | |
| 406 dec->update_proba_ = VP8Get(br); | |
| 407 if (!dec->update_proba_) { // save for later restore | |
| 408 dec->proba_saved_ = dec->proba_; | |
| 409 } | |
| 410 dec->buffer_flags_ &= 1 << 8; | |
| 411 dec->buffer_flags_ |= | |
| 412 (frm_hdr->key_frame_ || VP8Get(br)) << 8; // refresh last frame | |
| 413 #else | |
| 414 VP8Get(br); // just ignore the value of update_proba_ | |
| 415 #endif | |
| 416 | 363 |
| 417 VP8ParseProba(br, dec); | 364 VP8ParseProba(br, dec); |
| 418 | 365 |
| 419 #ifdef WEBP_EXPERIMENTAL_FEATURES | 366 #ifdef WEBP_EXPERIMENTAL_FEATURES |
| 420 // Extensions | 367 // Extensions |
| 421 if (dec->pic_hdr_.colorspace_) { | 368 if (dec->pic_hdr_.colorspace_) { |
| 422 const size_t kTrailerSize = 8; | 369 const size_t kTrailerSize = 8; |
| 423 const uint8_t kTrailerMarker = 0x01; | 370 const uint8_t kTrailerMarker = 0x01; |
| 424 const uint8_t* ext_buf = buf - kTrailerSize; | 371 const uint8_t* ext_buf = buf - kTrailerSize; |
| 425 size_t size; | 372 size_t size; |
| (...skipping 28 matching lines...) Expand all Loading... |
| 454 static const uint8_t kCat3[] = { 173, 148, 140, 0 }; | 401 static const uint8_t kCat3[] = { 173, 148, 140, 0 }; |
| 455 static const uint8_t kCat4[] = { 176, 155, 140, 135, 0 }; | 402 static const uint8_t kCat4[] = { 176, 155, 140, 135, 0 }; |
| 456 static const uint8_t kCat5[] = { 180, 157, 141, 134, 130, 0 }; | 403 static const uint8_t kCat5[] = { 180, 157, 141, 134, 130, 0 }; |
| 457 static const uint8_t kCat6[] = | 404 static const uint8_t kCat6[] = |
| 458 { 254, 254, 243, 230, 196, 177, 153, 140, 133, 130, 129, 0 }; | 405 { 254, 254, 243, 230, 196, 177, 153, 140, 133, 130, 129, 0 }; |
| 459 static const uint8_t* const kCat3456[] = { kCat3, kCat4, kCat5, kCat6 }; | 406 static const uint8_t* const kCat3456[] = { kCat3, kCat4, kCat5, kCat6 }; |
| 460 static const uint8_t kZigzag[16] = { | 407 static const uint8_t kZigzag[16] = { |
| 461 0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15 | 408 0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15 |
| 462 }; | 409 }; |
| 463 | 410 |
| 464 typedef const uint8_t (*ProbaArray)[NUM_CTX][NUM_PROBAS]; // for const-casting | |
| 465 typedef const uint8_t (*ProbaCtxArray)[NUM_PROBAS]; | |
| 466 | |
| 467 // See section 13-2: http://tools.ietf.org/html/rfc6386#section-13.2 | 411 // See section 13-2: http://tools.ietf.org/html/rfc6386#section-13.2 |
| 468 static int GetLargeValue(VP8BitReader* const br, const uint8_t* const p) { | 412 static int GetLargeValue(VP8BitReader* const br, const uint8_t* const p) { |
| 469 int v; | 413 int v; |
| 470 if (!VP8GetBit(br, p[3])) { | 414 if (!VP8GetBit(br, p[3])) { |
| 471 if (!VP8GetBit(br, p[4])) { | 415 if (!VP8GetBit(br, p[4])) { |
| 472 v = 2; | 416 v = 2; |
| 473 } else { | 417 } else { |
| 474 v = 3 + VP8GetBit(br, p[5]); | 418 v = 3 + VP8GetBit(br, p[5]); |
| 475 } | 419 } |
| 476 } else { | 420 } else { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 490 for (tab = kCat3456[cat]; *tab; ++tab) { | 434 for (tab = kCat3456[cat]; *tab; ++tab) { |
| 491 v += v + VP8GetBit(br, *tab); | 435 v += v + VP8GetBit(br, *tab); |
| 492 } | 436 } |
| 493 v += 3 + (8 << cat); | 437 v += 3 + (8 << cat); |
| 494 } | 438 } |
| 495 } | 439 } |
| 496 return v; | 440 return v; |
| 497 } | 441 } |
| 498 | 442 |
| 499 // Returns the position of the last non-zero coeff plus one | 443 // Returns the position of the last non-zero coeff plus one |
| 500 // (and 0 if there's no coeff at all) | 444 static int GetCoeffs(VP8BitReader* const br, const VP8BandProbas* const prob, |
| 501 static int GetCoeffs(VP8BitReader* const br, ProbaArray prob, | |
| 502 int ctx, const quant_t dq, int n, int16_t* out) { | 445 int ctx, const quant_t dq, int n, int16_t* out) { |
| 503 // n is either 0 or 1 here. kBands[n] is not necessary for extracting '*p'. | 446 // n is either 0 or 1 here. kBands[n] is not necessary for extracting '*p'. |
| 504 const uint8_t* p = prob[n][ctx]; | 447 const uint8_t* p = prob[n].probas_[ctx]; |
| 505 if (!VP8GetBit(br, p[0])) { // first EOB is more a 'CBP' bit. | |
| 506 return 0; | |
| 507 } | |
| 508 for (; n < 16; ++n) { | 448 for (; n < 16; ++n) { |
| 509 const ProbaCtxArray p_ctx = prob[kBands[n + 1]]; | 449 if (!VP8GetBit(br, p[0])) { |
| 510 if (!VP8GetBit(br, p[1])) { | 450 return n; // previous coeff was last non-zero coeff |
| 511 p = p_ctx[0]; | 451 } |
| 512 } else { // non zero coeff | 452 while (!VP8GetBit(br, p[1])) { // sequence of zero coeffs |
| 453 p = prob[kBands[++n]].probas_[0]; |
| 454 if (n == 16) return 16; |
| 455 } |
| 456 { // non zero coeff |
| 457 const VP8ProbaArray* const p_ctx = &prob[kBands[n + 1]].probas_[0]; |
| 513 int v; | 458 int v; |
| 514 if (!VP8GetBit(br, p[2])) { | 459 if (!VP8GetBit(br, p[2])) { |
| 515 v = 1; | 460 v = 1; |
| 516 p = p_ctx[1]; | 461 p = p_ctx[1]; |
| 517 } else { | 462 } else { |
| 518 v = GetLargeValue(br, p); | 463 v = GetLargeValue(br, p); |
| 519 p = p_ctx[2]; | 464 p = p_ctx[2]; |
| 520 } | 465 } |
| 521 out[kZigzag[n]] = VP8GetSigned(br, v) * dq[n > 0]; | 466 out[kZigzag[n]] = VP8GetSigned(br, v) * dq[n > 0]; |
| 522 if (n < 15 && !VP8GetBit(br, p[0])) { // EOB | |
| 523 return n + 1; | |
| 524 } | |
| 525 } | 467 } |
| 526 } | 468 } |
| 527 return 16; | 469 return 16; |
| 528 } | 470 } |
| 529 | 471 |
| 530 // Alias-safe way of converting 4bytes to 32bits. | 472 static WEBP_INLINE uint32_t NzCodeBits(uint32_t nz_coeffs, int nz, int dc_nz) { |
| 531 typedef union { | 473 nz_coeffs <<= 2; |
| 532 uint8_t i8[4]; | 474 nz_coeffs |= (nz > 3) ? 3 : (nz > 1) ? 2 : dc_nz; |
| 533 uint32_t i32; | 475 return nz_coeffs; |
| 534 } PackedNz; | 476 } |
| 535 | 477 |
| 536 // Table to unpack four bits into four bytes | 478 static int ParseResiduals(VP8Decoder* const dec, |
| 537 static const PackedNz kUnpackTab[16] = { | 479 VP8MB* const mb, VP8BitReader* const token_br) { |
| 538 {{0, 0, 0, 0}}, {{1, 0, 0, 0}}, {{0, 1, 0, 0}}, {{1, 1, 0, 0}}, | 480 VP8BandProbas (* const bands)[NUM_BANDS] = dec->proba_.bands_; |
| 539 {{0, 0, 1, 0}}, {{1, 0, 1, 0}}, {{0, 1, 1, 0}}, {{1, 1, 1, 0}}, | 481 const VP8BandProbas* ac_proba; |
| 540 {{0, 0, 0, 1}}, {{1, 0, 0, 1}}, {{0, 1, 0, 1}}, {{1, 1, 0, 1}}, | 482 const VP8QuantMatrix* const q = &dec->dqm_[dec->segment_]; |
| 541 {{0, 0, 1, 1}}, {{1, 0, 1, 1}}, {{0, 1, 1, 1}}, {{1, 1, 1, 1}} }; | 483 VP8MBData* const block = dec->mb_data_ + dec->mb_x_; |
| 484 int16_t* dst = block->coeffs_; |
| 485 VP8MB* const left_mb = dec->mb_info_ - 1; |
| 486 uint8_t tnz, lnz; |
| 487 uint32_t non_zero_y = 0; |
| 488 uint32_t non_zero_uv = 0; |
| 489 int x, y, ch; |
| 490 uint32_t out_t_nz, out_l_nz; |
| 491 int first; |
| 542 | 492 |
| 543 // Macro to pack four LSB of four bytes into four bits. | |
| 544 #if defined(__PPC__) || defined(_M_PPC) || defined(_ARCH_PPC) || \ | |
| 545 defined(__BIG_ENDIAN__) | |
| 546 #define PACK_CST 0x08040201U | |
| 547 #else | |
| 548 #define PACK_CST 0x01020408U | |
| 549 #endif | |
| 550 #define PACK(X, S) ((((X).i32 * PACK_CST) & 0xff000000) >> (S)) | |
| 551 | |
| 552 static void ParseResiduals(VP8Decoder* const dec, | |
| 553 VP8MB* const mb, VP8BitReader* const token_br) { | |
| 554 int out_t_nz, out_l_nz, first; | |
| 555 ProbaArray ac_prob; | |
| 556 const VP8QuantMatrix* q = &dec->dqm_[dec->segment_]; | |
| 557 int16_t* dst = dec->coeffs_; | |
| 558 VP8MB* const left_mb = dec->mb_info_ - 1; | |
| 559 PackedNz nz_ac, nz_dc; | |
| 560 PackedNz tnz, lnz; | |
| 561 uint32_t non_zero_ac = 0; | |
| 562 uint32_t non_zero_dc = 0; | |
| 563 int x, y, ch; | |
| 564 | |
| 565 nz_dc.i32 = nz_ac.i32 = 0; | |
| 566 memset(dst, 0, 384 * sizeof(*dst)); | 493 memset(dst, 0, 384 * sizeof(*dst)); |
| 567 if (!dec->is_i4x4_) { // parse DC | 494 if (!block->is_i4x4_) { // parse DC |
| 568 int16_t dc[16] = { 0 }; | 495 int16_t dc[16] = { 0 }; |
| 569 const int ctx = mb->dc_nz_ + left_mb->dc_nz_; | 496 const int ctx = mb->nz_dc_ + left_mb->nz_dc_; |
| 570 mb->dc_nz_ = left_mb->dc_nz_ = | 497 const int nz = GetCoeffs(token_br, bands[1], ctx, q->y2_mat_, 0, dc); |
| 571 (GetCoeffs(token_br, (ProbaArray)dec->proba_.coeffs_[1], | 498 mb->nz_dc_ = left_mb->nz_dc_ = (nz > 0); |
| 572 ctx, q->y2_mat_, 0, dc) > 0); | 499 if (nz > 1) { // more than just the DC -> perform the full transform |
| 500 VP8TransformWHT(dc, dst); |
| 501 } else { // only DC is non-zero -> inlined simplified transform |
| 502 int i; |
| 503 const int dc0 = (dc[0] + 3) >> 3; |
| 504 for (i = 0; i < 16 * 16; i += 16) dst[i] = dc0; |
| 505 } |
| 573 first = 1; | 506 first = 1; |
| 574 ac_prob = (ProbaArray)dec->proba_.coeffs_[0]; | 507 ac_proba = bands[0]; |
| 575 VP8TransformWHT(dc, dst); | |
| 576 } else { | 508 } else { |
| 577 first = 0; | 509 first = 0; |
| 578 ac_prob = (ProbaArray)dec->proba_.coeffs_[3]; | 510 ac_proba = bands[3]; |
| 579 } | 511 } |
| 580 | 512 |
| 581 tnz = kUnpackTab[mb->nz_ & 0xf]; | 513 tnz = mb->nz_ & 0x0f; |
| 582 lnz = kUnpackTab[left_mb->nz_ & 0xf]; | 514 lnz = left_mb->nz_ & 0x0f; |
| 583 for (y = 0; y < 4; ++y) { | 515 for (y = 0; y < 4; ++y) { |
| 584 int l = lnz.i8[y]; | 516 int l = lnz & 1; |
| 517 uint32_t nz_coeffs = 0; |
| 585 for (x = 0; x < 4; ++x) { | 518 for (x = 0; x < 4; ++x) { |
| 586 const int ctx = l + tnz.i8[x]; | 519 const int ctx = l + (tnz & 1); |
| 587 const int nz = GetCoeffs(token_br, ac_prob, ctx, | 520 const int nz = GetCoeffs(token_br, ac_proba, ctx, q->y1_mat_, first, dst); |
| 588 q->y1_mat_, first, dst); | 521 l = (nz > first); |
| 589 tnz.i8[x] = l = (nz > 0); | 522 tnz = (tnz >> 1) | (l << 7); |
| 590 nz_dc.i8[x] = (dst[0] != 0); | 523 nz_coeffs = NzCodeBits(nz_coeffs, nz, dst[0] != 0); |
| 591 nz_ac.i8[x] = (nz > 1); | |
| 592 dst += 16; | 524 dst += 16; |
| 593 } | 525 } |
| 594 lnz.i8[y] = l; | 526 tnz >>= 4; |
| 595 non_zero_dc |= PACK(nz_dc, 24 - y * 4); | 527 lnz = (lnz >> 1) | (l << 7); |
| 596 non_zero_ac |= PACK(nz_ac, 24 - y * 4); | 528 non_zero_y = (non_zero_y << 8) | nz_coeffs; |
| 597 } | 529 } |
| 598 out_t_nz = PACK(tnz, 24); | 530 out_t_nz = tnz; |
| 599 out_l_nz = PACK(lnz, 24); | 531 out_l_nz = lnz >> 4; |
| 600 | 532 |
| 601 tnz = kUnpackTab[mb->nz_ >> 4]; | |
| 602 lnz = kUnpackTab[left_mb->nz_ >> 4]; | |
| 603 for (ch = 0; ch < 4; ch += 2) { | 533 for (ch = 0; ch < 4; ch += 2) { |
| 534 uint32_t nz_coeffs = 0; |
| 535 tnz = mb->nz_ >> (4 + ch); |
| 536 lnz = left_mb->nz_ >> (4 + ch); |
| 604 for (y = 0; y < 2; ++y) { | 537 for (y = 0; y < 2; ++y) { |
| 605 int l = lnz.i8[ch + y]; | 538 int l = lnz & 1; |
| 606 for (x = 0; x < 2; ++x) { | 539 for (x = 0; x < 2; ++x) { |
| 607 const int ctx = l + tnz.i8[ch + x]; | 540 const int ctx = l + (tnz & 1); |
| 608 const int nz = | 541 const int nz = GetCoeffs(token_br, bands[2], ctx, q->uv_mat_, 0, dst); |
| 609 GetCoeffs(token_br, (ProbaArray)dec->proba_.coeffs_[2], | 542 l = (nz > 0); |
| 610 ctx, q->uv_mat_, 0, dst); | 543 tnz = (tnz >> 1) | (l << 3); |
| 611 tnz.i8[ch + x] = l = (nz > 0); | 544 nz_coeffs = NzCodeBits(nz_coeffs, nz, dst[0] != 0); |
| 612 nz_dc.i8[y * 2 + x] = (dst[0] != 0); | |
| 613 nz_ac.i8[y * 2 + x] = (nz > 1); | |
| 614 dst += 16; | 545 dst += 16; |
| 615 } | 546 } |
| 616 lnz.i8[ch + y] = l; | 547 tnz >>= 2; |
| 548 lnz = (lnz >> 1) | (l << 5); |
| 617 } | 549 } |
| 618 non_zero_dc |= PACK(nz_dc, 8 - ch * 2); | 550 // Note: we don't really need the per-4x4 details for U/V blocks. |
| 619 non_zero_ac |= PACK(nz_ac, 8 - ch * 2); | 551 non_zero_uv |= nz_coeffs << (4 * ch); |
| 552 out_t_nz |= (tnz << 4) << ch; |
| 553 out_l_nz |= (lnz & 0xf0) << ch; |
| 620 } | 554 } |
| 621 out_t_nz |= PACK(tnz, 20); | |
| 622 out_l_nz |= PACK(lnz, 20); | |
| 623 mb->nz_ = out_t_nz; | 555 mb->nz_ = out_t_nz; |
| 624 left_mb->nz_ = out_l_nz; | 556 left_mb->nz_ = out_l_nz; |
| 625 | 557 |
| 626 dec->non_zero_ac_ = non_zero_ac; | 558 block->non_zero_y_ = non_zero_y; |
| 627 dec->non_zero_ = non_zero_ac | non_zero_dc; | 559 block->non_zero_uv_ = non_zero_uv; |
| 628 mb->skip_ = !dec->non_zero_; | 560 |
| 561 // We look at the mode-code of each block and check if some blocks have less |
| 562 // than three non-zero coeffs (code < 2). This is to avoid dithering flat and |
| 563 // empty blocks. |
| 564 block->dither_ = (non_zero_uv & 0xaaaa) ? 0 : q->dither_; |
| 565 |
| 566 return !(non_zero_y | non_zero_uv); // will be used for further optimization |
| 629 } | 567 } |
| 630 #undef PACK | |
| 631 | 568 |
| 632 //------------------------------------------------------------------------------ | 569 //------------------------------------------------------------------------------ |
| 633 // Main loop | 570 // Main loop |
| 634 | 571 |
| 635 int VP8DecodeMB(VP8Decoder* const dec, VP8BitReader* const token_br) { | 572 int VP8DecodeMB(VP8Decoder* const dec, VP8BitReader* const token_br) { |
| 636 VP8BitReader* const br = &dec->br_; | 573 VP8BitReader* const br = &dec->br_; |
| 637 VP8MB* const left = dec->mb_info_ - 1; | 574 VP8MB* const left = dec->mb_info_ - 1; |
| 638 VP8MB* const info = dec->mb_info_ + dec->mb_x_; | 575 VP8MB* const mb = dec->mb_info_ + dec->mb_x_; |
| 576 VP8MBData* const block = dec->mb_data_ + dec->mb_x_; |
| 577 int skip; |
| 639 | 578 |
| 640 // Note: we don't save segment map (yet), as we don't expect | 579 // Note: we don't save segment map (yet), as we don't expect |
| 641 // to decode more than 1 keyframe. | 580 // to decode more than 1 keyframe. |
| 642 if (dec->segment_hdr_.update_map_) { | 581 if (dec->segment_hdr_.update_map_) { |
| 643 // Hardcoded tree parsing | 582 // Hardcoded tree parsing |
| 644 dec->segment_ = !VP8GetBit(br, dec->proba_.segments_[0]) ? | 583 dec->segment_ = !VP8GetBit(br, dec->proba_.segments_[0]) ? |
| 645 VP8GetBit(br, dec->proba_.segments_[1]) : | 584 VP8GetBit(br, dec->proba_.segments_[1]) : |
| 646 2 + VP8GetBit(br, dec->proba_.segments_[2]); | 585 2 + VP8GetBit(br, dec->proba_.segments_[2]); |
| 647 } | 586 } |
| 648 info->skip_ = dec->use_skip_proba_ ? VP8GetBit(br, dec->skip_p_) : 0; | 587 skip = dec->use_skip_proba_ ? VP8GetBit(br, dec->skip_p_) : 0; |
| 649 | 588 |
| 650 VP8ParseIntraMode(br, dec); | 589 VP8ParseIntraMode(br, dec); |
| 651 if (br->eof_) { | 590 if (br->eof_) { |
| 652 return 0; | 591 return 0; |
| 653 } | 592 } |
| 654 | 593 |
| 655 if (!info->skip_) { | 594 if (!skip) { |
| 656 ParseResiduals(dec, info, token_br); | 595 skip = ParseResiduals(dec, mb, token_br); |
| 657 } else { | 596 } else { |
| 658 left->nz_ = info->nz_ = 0; | 597 left->nz_ = mb->nz_ = 0; |
| 659 if (!dec->is_i4x4_) { | 598 if (!block->is_i4x4_) { |
| 660 left->dc_nz_ = info->dc_nz_ = 0; | 599 left->nz_dc_ = mb->nz_dc_ = 0; |
| 661 } | 600 } |
| 662 dec->non_zero_ = 0; | 601 block->non_zero_y_ = 0; |
| 663 dec->non_zero_ac_ = 0; | 602 block->non_zero_uv_ = 0; |
| 664 } | 603 } |
| 665 | 604 |
| 666 if (dec->filter_type_ > 0) { // store filter info | 605 if (dec->filter_type_ > 0) { // store filter info |
| 667 VP8FInfo* const finfo = dec->f_info_ + dec->mb_x_; | 606 VP8FInfo* const finfo = dec->f_info_ + dec->mb_x_; |
| 668 *finfo = dec->fstrengths_[dec->segment_][dec->is_i4x4_]; | 607 *finfo = dec->fstrengths_[dec->segment_][block->is_i4x4_]; |
| 669 finfo->f_inner_ = (!info->skip_ || dec->is_i4x4_); | 608 finfo->f_inner_ |= !skip; |
| 670 } | 609 } |
| 671 | 610 |
| 672 return (!token_br->eof_); | 611 return !token_br->eof_; |
| 673 } | 612 } |
| 674 | 613 |
| 675 void VP8InitScanline(VP8Decoder* const dec) { | 614 void VP8InitScanline(VP8Decoder* const dec) { |
| 676 VP8MB* const left = dec->mb_info_ - 1; | 615 VP8MB* const left = dec->mb_info_ - 1; |
| 677 left->nz_ = 0; | 616 left->nz_ = 0; |
| 678 left->dc_nz_ = 0; | 617 left->nz_dc_ = 0; |
| 679 memset(dec->intra_l_, B_DC_PRED, sizeof(dec->intra_l_)); | 618 memset(dec->intra_l_, B_DC_PRED, sizeof(dec->intra_l_)); |
| 680 dec->filter_row_ = | 619 dec->mb_x_ = 0; |
| 681 (dec->filter_type_ > 0) && | |
| 682 (dec->mb_y_ >= dec->tl_mb_y_) && (dec->mb_y_ <= dec->br_mb_y_); | |
| 683 } | 620 } |
| 684 | 621 |
| 685 static int ParseFrame(VP8Decoder* const dec, VP8Io* io) { | 622 static int ParseFrame(VP8Decoder* const dec, VP8Io* io) { |
| 686 for (dec->mb_y_ = 0; dec->mb_y_ < dec->br_mb_y_; ++dec->mb_y_) { | 623 for (dec->mb_y_ = 0; dec->mb_y_ < dec->br_mb_y_; ++dec->mb_y_) { |
| 624 // Parse bitstream for this row. |
| 687 VP8BitReader* const token_br = | 625 VP8BitReader* const token_br = |
| 688 &dec->parts_[dec->mb_y_ & (dec->num_parts_ - 1)]; | 626 &dec->parts_[dec->mb_y_ & (dec->num_parts_ - 1)]; |
| 689 VP8InitScanline(dec); | 627 for (; dec->mb_x_ < dec->mb_w_; ++dec->mb_x_) { |
| 690 for (dec->mb_x_ = 0; dec->mb_x_ < dec->mb_w_; dec->mb_x_++) { | |
| 691 if (!VP8DecodeMB(dec, token_br)) { | 628 if (!VP8DecodeMB(dec, token_br)) { |
| 692 return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA, | 629 return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA, |
| 693 "Premature end-of-file encountered."); | 630 "Premature end-of-file encountered."); |
| 694 } | 631 } |
| 695 // Reconstruct and emit samples. | |
| 696 VP8ReconstructBlock(dec); | |
| 697 } | 632 } |
| 633 VP8InitScanline(dec); // Prepare for next scanline |
| 634 |
| 635 // Reconstruct, filter and emit the row. |
| 698 if (!VP8ProcessRow(dec, io)) { | 636 if (!VP8ProcessRow(dec, io)) { |
| 699 return VP8SetError(dec, VP8_STATUS_USER_ABORT, "Output aborted."); | 637 return VP8SetError(dec, VP8_STATUS_USER_ABORT, "Output aborted."); |
| 700 } | 638 } |
| 701 } | 639 } |
| 702 if (dec->use_threads_ && !WebPWorkerSync(&dec->worker_)) { | 640 if (dec->mt_method_ > 0) { |
| 703 return 0; | 641 if (!WebPWorkerSync(&dec->worker_)) return 0; |
| 704 } | 642 } |
| 705 | 643 |
| 706 // Finish | 644 // Finish |
| 707 #ifndef ONLY_KEYFRAME_CODE | |
| 708 if (!dec->update_proba_) { | |
| 709 dec->proba_ = dec->proba_saved_; | |
| 710 } | |
| 711 #endif | |
| 712 | |
| 713 #ifdef WEBP_EXPERIMENTAL_FEATURES | 645 #ifdef WEBP_EXPERIMENTAL_FEATURES |
| 714 if (dec->layer_data_size_ > 0) { | 646 if (dec->layer_data_size_ > 0) { |
| 715 if (!VP8DecodeLayer(dec)) { | 647 if (!VP8DecodeLayer(dec)) { |
| 716 return 0; | 648 return 0; |
| 717 } | 649 } |
| 718 } | 650 } |
| 719 #endif | 651 #endif |
| 720 | 652 |
| 721 return 1; | 653 return 1; |
| 722 } | 654 } |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 758 } | 690 } |
| 759 | 691 |
| 760 dec->ready_ = 0; | 692 dec->ready_ = 0; |
| 761 return ok; | 693 return ok; |
| 762 } | 694 } |
| 763 | 695 |
| 764 void VP8Clear(VP8Decoder* const dec) { | 696 void VP8Clear(VP8Decoder* const dec) { |
| 765 if (dec == NULL) { | 697 if (dec == NULL) { |
| 766 return; | 698 return; |
| 767 } | 699 } |
| 768 if (dec->use_threads_) { | 700 if (dec->mt_method_ > 0) { |
| 769 WebPWorkerEnd(&dec->worker_); | 701 WebPWorkerEnd(&dec->worker_); |
| 770 } | 702 } |
| 771 if (dec->mem_) { | 703 ALPHDelete(dec->alph_dec_); |
| 772 free(dec->mem_); | 704 dec->alph_dec_ = NULL; |
| 773 } | 705 free(dec->mem_); |
| 774 dec->mem_ = NULL; | 706 dec->mem_ = NULL; |
| 775 dec->mem_size_ = 0; | 707 dec->mem_size_ = 0; |
| 776 memset(&dec->br_, 0, sizeof(dec->br_)); | 708 memset(&dec->br_, 0, sizeof(dec->br_)); |
| 777 dec->ready_ = 0; | 709 dec->ready_ = 0; |
| 778 } | 710 } |
| 779 | 711 |
| 780 //------------------------------------------------------------------------------ | 712 //------------------------------------------------------------------------------ |
| 781 | 713 |
| 782 #if defined(__cplusplus) || defined(c_plusplus) | |
| 783 } // extern "C" | |
| 784 #endif | |
| OLD | NEW |