| OLD | NEW |
| 1 // Copyright 2012 Google Inc. All Rights Reserved. | 1 // Copyright 2012 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 // Authors: Vikas Arora (vikaas.arora@gmail.com) | 12 // Authors: Vikas Arora (vikaas.arora@gmail.com) |
| 13 // Jyrki Alakuijala (jyrki@google.com) | 13 // Jyrki Alakuijala (jyrki@google.com) |
| 14 | 14 |
| 15 #include <stdlib.h> | 15 #include <stdlib.h> |
| 16 | 16 |
| 17 #include "./alphai.h" | 17 #include "./alphai_dec.h" |
| 18 #include "./vp8li.h" | 18 #include "./vp8li_dec.h" |
| 19 #include "../dsp/dsp.h" | 19 #include "../dsp/dsp.h" |
| 20 #include "../dsp/lossless.h" | 20 #include "../dsp/lossless.h" |
| 21 #include "../dsp/lossless_common.h" |
| 21 #include "../dsp/yuv.h" | 22 #include "../dsp/yuv.h" |
| 22 #include "../utils/endian_inl.h" | 23 #include "../utils/endian_inl_utils.h" |
| 23 #include "../utils/huffman.h" | 24 #include "../utils/huffman_utils.h" |
| 24 #include "../utils/utils.h" | 25 #include "../utils/utils.h" |
| 25 | 26 |
| 26 #define NUM_ARGB_CACHE_ROWS 16 | 27 #define NUM_ARGB_CACHE_ROWS 16 |
| 27 | 28 |
| 28 static const int kCodeLengthLiterals = 16; | 29 static const int kCodeLengthLiterals = 16; |
| 29 static const int kCodeLengthRepeatCode = 16; | 30 static const int kCodeLengthRepeatCode = 16; |
| 30 static const int kCodeLengthExtraBits[3] = { 2, 3, 7 }; | 31 static const int kCodeLengthExtraBits[3] = { 2, 3, 7 }; |
| 31 static const int kCodeLengthRepeatOffsets[3] = { 3, 3, 11 }; | 32 static const int kCodeLengthRepeatOffsets[3] = { 3, 3, 11 }; |
| 32 | 33 |
| 33 // ----------------------------------------------------------------------------- | 34 // ----------------------------------------------------------------------------- |
| (...skipping 506 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 540 uint8_t* in, int in_stride, int mb_h, | 541 uint8_t* in, int in_stride, int mb_h, |
| 541 uint8_t* const out, int out_stride) { | 542 uint8_t* const out, int out_stride) { |
| 542 const WEBP_CSP_MODE colorspace = dec->output_->colorspace; | 543 const WEBP_CSP_MODE colorspace = dec->output_->colorspace; |
| 543 int num_lines_in = 0; | 544 int num_lines_in = 0; |
| 544 int num_lines_out = 0; | 545 int num_lines_out = 0; |
| 545 while (num_lines_in < mb_h) { | 546 while (num_lines_in < mb_h) { |
| 546 uint8_t* const row_in = in + num_lines_in * in_stride; | 547 uint8_t* const row_in = in + num_lines_in * in_stride; |
| 547 uint8_t* const row_out = out + num_lines_out * out_stride; | 548 uint8_t* const row_out = out + num_lines_out * out_stride; |
| 548 const int lines_left = mb_h - num_lines_in; | 549 const int lines_left = mb_h - num_lines_in; |
| 549 const int needed_lines = WebPRescaleNeededLines(dec->rescaler, lines_left); | 550 const int needed_lines = WebPRescaleNeededLines(dec->rescaler, lines_left); |
| 551 int lines_imported; |
| 550 assert(needed_lines > 0 && needed_lines <= lines_left); | 552 assert(needed_lines > 0 && needed_lines <= lines_left); |
| 551 WebPMultARGBRows(row_in, in_stride, | 553 WebPMultARGBRows(row_in, in_stride, |
| 552 dec->rescaler->src_width, needed_lines, 0); | 554 dec->rescaler->src_width, needed_lines, 0); |
| 553 WebPRescalerImport(dec->rescaler, lines_left, row_in, in_stride); | 555 lines_imported = |
| 554 num_lines_in += needed_lines; | 556 WebPRescalerImport(dec->rescaler, lines_left, row_in, in_stride); |
| 557 assert(lines_imported == needed_lines); |
| 558 num_lines_in += lines_imported; |
| 555 num_lines_out += Export(dec->rescaler, colorspace, out_stride, row_out); | 559 num_lines_out += Export(dec->rescaler, colorspace, out_stride, row_out); |
| 556 } | 560 } |
| 557 return num_lines_out; | 561 return num_lines_out; |
| 558 } | 562 } |
| 559 | 563 |
| 560 // Emit rows without any scaling. | 564 // Emit rows without any scaling. |
| 561 static int EmitRows(WEBP_CSP_MODE colorspace, | 565 static int EmitRows(WEBP_CSP_MODE colorspace, |
| 562 const uint8_t* row_in, int in_stride, | 566 const uint8_t* row_in, int in_stride, |
| 563 int mb_w, int mb_h, | 567 int mb_w, int mb_h, |
| 564 uint8_t* const out, int out_stride) { | 568 uint8_t* const out, int out_stride) { |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 616 return num_lines_out; | 620 return num_lines_out; |
| 617 } | 621 } |
| 618 | 622 |
| 619 static int EmitRescaledRowsYUVA(const VP8LDecoder* const dec, | 623 static int EmitRescaledRowsYUVA(const VP8LDecoder* const dec, |
| 620 uint8_t* in, int in_stride, int mb_h) { | 624 uint8_t* in, int in_stride, int mb_h) { |
| 621 int num_lines_in = 0; | 625 int num_lines_in = 0; |
| 622 int y_pos = dec->last_out_row_; | 626 int y_pos = dec->last_out_row_; |
| 623 while (num_lines_in < mb_h) { | 627 while (num_lines_in < mb_h) { |
| 624 const int lines_left = mb_h - num_lines_in; | 628 const int lines_left = mb_h - num_lines_in; |
| 625 const int needed_lines = WebPRescaleNeededLines(dec->rescaler, lines_left); | 629 const int needed_lines = WebPRescaleNeededLines(dec->rescaler, lines_left); |
| 630 int lines_imported; |
| 626 WebPMultARGBRows(in, in_stride, dec->rescaler->src_width, needed_lines, 0); | 631 WebPMultARGBRows(in, in_stride, dec->rescaler->src_width, needed_lines, 0); |
| 627 WebPRescalerImport(dec->rescaler, lines_left, in, in_stride); | 632 lines_imported = |
| 628 num_lines_in += needed_lines; | 633 WebPRescalerImport(dec->rescaler, lines_left, in, in_stride); |
| 634 assert(lines_imported == needed_lines); |
| 635 num_lines_in += lines_imported; |
| 629 in += needed_lines * in_stride; | 636 in += needed_lines * in_stride; |
| 630 y_pos += ExportYUVA(dec, y_pos); | 637 y_pos += ExportYUVA(dec, y_pos); |
| 631 } | 638 } |
| 632 return y_pos; | 639 return y_pos; |
| 633 } | 640 } |
| 634 | 641 |
| 635 static int EmitRowsYUVA(const VP8LDecoder* const dec, | 642 static int EmitRowsYUVA(const VP8LDecoder* const dec, |
| 636 const uint8_t* in, int in_stride, | 643 const uint8_t* in, int in_stride, |
| 637 int mb_w, int num_rows) { | 644 int mb_w, int num_rows) { |
| 638 int y_pos = dec->last_out_row_; | 645 int y_pos = dec->last_out_row_; |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 698 static void ApplyInverseTransforms(VP8LDecoder* const dec, int num_rows, | 705 static void ApplyInverseTransforms(VP8LDecoder* const dec, int num_rows, |
| 699 const uint32_t* const rows) { | 706 const uint32_t* const rows) { |
| 700 int n = dec->next_transform_; | 707 int n = dec->next_transform_; |
| 701 const int cache_pixs = dec->width_ * num_rows; | 708 const int cache_pixs = dec->width_ * num_rows; |
| 702 const int start_row = dec->last_row_; | 709 const int start_row = dec->last_row_; |
| 703 const int end_row = start_row + num_rows; | 710 const int end_row = start_row + num_rows; |
| 704 const uint32_t* rows_in = rows; | 711 const uint32_t* rows_in = rows; |
| 705 uint32_t* const rows_out = dec->argb_cache_; | 712 uint32_t* const rows_out = dec->argb_cache_; |
| 706 | 713 |
| 707 // Inverse transforms. | 714 // Inverse transforms. |
| 708 // TODO: most transforms only need to operate on the cropped region only. | |
| 709 memcpy(rows_out, rows_in, cache_pixs * sizeof(*rows_out)); | |
| 710 while (n-- > 0) { | 715 while (n-- > 0) { |
| 711 VP8LTransform* const transform = &dec->transforms_[n]; | 716 VP8LTransform* const transform = &dec->transforms_[n]; |
| 712 VP8LInverseTransform(transform, start_row, end_row, rows_in, rows_out); | 717 VP8LInverseTransform(transform, start_row, end_row, rows_in, rows_out); |
| 713 rows_in = rows_out; | 718 rows_in = rows_out; |
| 714 } | 719 } |
| 720 if (rows_in != rows_out) { |
| 721 // No transform called, hence just copy. |
| 722 memcpy(rows_out, rows_in, cache_pixs * sizeof(*rows_out)); |
| 723 } |
| 715 } | 724 } |
| 716 | 725 |
| 717 // Processes (transforms, scales & color-converts) the rows decoded after the | 726 // Processes (transforms, scales & color-converts) the rows decoded after the |
| 718 // last call. | 727 // last call. |
| 719 static void ProcessRows(VP8LDecoder* const dec, int row) { | 728 static void ProcessRows(VP8LDecoder* const dec, int row) { |
| 720 const uint32_t* const rows = dec->pixels_ + dec->width_ * dec->last_row_; | 729 const uint32_t* const rows = dec->pixels_ + dec->width_ * dec->last_row_; |
| 721 const int num_rows = row - dec->last_row_; | 730 const int num_rows = row - dec->last_row_; |
| 722 | 731 |
| 723 assert(row <= dec->io_->crop_bottom); | 732 assert(row <= dec->io_->crop_bottom); |
| 724 // We can't process more than NUM_ARGB_CACHE_ROWS at a time (that's the size | 733 // We can't process more than NUM_ARGB_CACHE_ROWS at a time (that's the size |
| (...skipping 478 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1203 if (new_color_map == NULL) { | 1212 if (new_color_map == NULL) { |
| 1204 return 0; | 1213 return 0; |
| 1205 } else { | 1214 } else { |
| 1206 uint8_t* const data = (uint8_t*)transform->data_; | 1215 uint8_t* const data = (uint8_t*)transform->data_; |
| 1207 uint8_t* const new_data = (uint8_t*)new_color_map; | 1216 uint8_t* const new_data = (uint8_t*)new_color_map; |
| 1208 new_color_map[0] = transform->data_[0]; | 1217 new_color_map[0] = transform->data_[0]; |
| 1209 for (i = 4; i < 4 * num_colors; ++i) { | 1218 for (i = 4; i < 4 * num_colors; ++i) { |
| 1210 // Equivalent to AddPixelEq(), on a byte-basis. | 1219 // Equivalent to AddPixelEq(), on a byte-basis. |
| 1211 new_data[i] = (data[i] + new_data[i - 4]) & 0xff; | 1220 new_data[i] = (data[i] + new_data[i - 4]) & 0xff; |
| 1212 } | 1221 } |
| 1213 for (; i < 4 * final_num_colors; ++i) | 1222 for (; i < 4 * final_num_colors; ++i) { |
| 1214 new_data[i] = 0; // black tail. | 1223 new_data[i] = 0; // black tail. |
| 1224 } |
| 1215 WebPSafeFree(transform->data_); | 1225 WebPSafeFree(transform->data_); |
| 1216 transform->data_ = new_color_map; | 1226 transform->data_ = new_color_map; |
| 1217 } | 1227 } |
| 1218 return 1; | 1228 return 1; |
| 1219 } | 1229 } |
| 1220 | 1230 |
| 1221 static int ReadTransform(int* const xsize, int const* ysize, | 1231 static int ReadTransform(int* const xsize, int const* ysize, |
| 1222 VP8LDecoder* const dec) { | 1232 VP8LDecoder* const dec) { |
| 1223 int ok = 1; | 1233 int ok = 1; |
| 1224 VP8LBitReader* const br = &dec->br_; | 1234 VP8LBitReader* const br = &dec->br_; |
| (...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1475 while (num_rows > 0) { | 1485 while (num_rows > 0) { |
| 1476 const int num_rows_to_process = | 1486 const int num_rows_to_process = |
| 1477 (num_rows > NUM_ARGB_CACHE_ROWS) ? NUM_ARGB_CACHE_ROWS : num_rows; | 1487 (num_rows > NUM_ARGB_CACHE_ROWS) ? NUM_ARGB_CACHE_ROWS : num_rows; |
| 1478 // Extract alpha (which is stored in the green plane). | 1488 // Extract alpha (which is stored in the green plane). |
| 1479 ALPHDecoder* const alph_dec = (ALPHDecoder*)dec->io_->opaque; | 1489 ALPHDecoder* const alph_dec = (ALPHDecoder*)dec->io_->opaque; |
| 1480 uint8_t* const output = alph_dec->output_; | 1490 uint8_t* const output = alph_dec->output_; |
| 1481 const int width = dec->io_->width; // the final width (!= dec->width_) | 1491 const int width = dec->io_->width; // the final width (!= dec->width_) |
| 1482 const int cache_pixs = width * num_rows_to_process; | 1492 const int cache_pixs = width * num_rows_to_process; |
| 1483 uint8_t* const dst = output + width * cur_row; | 1493 uint8_t* const dst = output + width * cur_row; |
| 1484 const uint32_t* const src = dec->argb_cache_; | 1494 const uint32_t* const src = dec->argb_cache_; |
| 1485 int i; | |
| 1486 ApplyInverseTransforms(dec, num_rows_to_process, in); | 1495 ApplyInverseTransforms(dec, num_rows_to_process, in); |
| 1487 for (i = 0; i < cache_pixs; ++i) dst[i] = (src[i] >> 8) & 0xff; | 1496 WebPExtractGreen(src, dst, cache_pixs); |
| 1488 AlphaApplyFilter(alph_dec, | 1497 AlphaApplyFilter(alph_dec, |
| 1489 cur_row, cur_row + num_rows_to_process, dst, width); | 1498 cur_row, cur_row + num_rows_to_process, dst, width); |
| 1490 num_rows -= num_rows_to_process; | 1499 num_rows -= num_rows_to_process; |
| 1491 in += num_rows_to_process * dec->width_; | 1500 in += num_rows_to_process * dec->width_; |
| 1492 cur_row += num_rows_to_process; | 1501 cur_row += num_rows_to_process; |
| 1493 } | 1502 } |
| 1494 assert(cur_row == last_row); | 1503 assert(cur_row == last_row); |
| 1495 dec->last_row_ = dec->last_out_row_ = last_row; | 1504 dec->last_row_ = dec->last_out_row_ = last_row; |
| 1496 } | 1505 } |
| 1497 | 1506 |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1545 | 1554 |
| 1546 int VP8LDecodeAlphaImageStream(ALPHDecoder* const alph_dec, int last_row) { | 1555 int VP8LDecodeAlphaImageStream(ALPHDecoder* const alph_dec, int last_row) { |
| 1547 VP8LDecoder* const dec = alph_dec->vp8l_dec_; | 1556 VP8LDecoder* const dec = alph_dec->vp8l_dec_; |
| 1548 assert(dec != NULL); | 1557 assert(dec != NULL); |
| 1549 assert(last_row <= dec->height_); | 1558 assert(last_row <= dec->height_); |
| 1550 | 1559 |
| 1551 if (dec->last_row_ >= last_row) { | 1560 if (dec->last_row_ >= last_row) { |
| 1552 return 1; // done | 1561 return 1; // done |
| 1553 } | 1562 } |
| 1554 | 1563 |
| 1564 if (!alph_dec->use_8b_decode_) WebPInitAlphaProcessing(); |
| 1565 |
| 1555 // Decode (with special row processing). | 1566 // Decode (with special row processing). |
| 1556 return alph_dec->use_8b_decode_ ? | 1567 return alph_dec->use_8b_decode_ ? |
| 1557 DecodeAlphaData(dec, (uint8_t*)dec->pixels_, dec->width_, dec->height_, | 1568 DecodeAlphaData(dec, (uint8_t*)dec->pixels_, dec->width_, dec->height_, |
| 1558 last_row) : | 1569 last_row) : |
| 1559 DecodeImageData(dec, dec->pixels_, dec->width_, dec->height_, | 1570 DecodeImageData(dec, dec->pixels_, dec->width_, dec->height_, |
| 1560 last_row, ExtractAlphaRows); | 1571 last_row, ExtractAlphaRows); |
| 1561 } | 1572 } |
| 1562 | 1573 |
| 1563 //------------------------------------------------------------------------------ | 1574 //------------------------------------------------------------------------------ |
| 1564 | 1575 |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1651 params->last_y = dec->last_out_row_; | 1662 params->last_y = dec->last_out_row_; |
| 1652 return 1; | 1663 return 1; |
| 1653 | 1664 |
| 1654 Err: | 1665 Err: |
| 1655 VP8LClear(dec); | 1666 VP8LClear(dec); |
| 1656 assert(dec->status_ != VP8_STATUS_OK); | 1667 assert(dec->status_ != VP8_STATUS_OK); |
| 1657 return 0; | 1668 return 0; |
| 1658 } | 1669 } |
| 1659 | 1670 |
| 1660 //------------------------------------------------------------------------------ | 1671 //------------------------------------------------------------------------------ |
| OLD | NEW |