diff options
author | volzhs <volzhs@gmail.com> | 2018-12-10 22:33:51 +0900 |
---|---|---|
committer | volzhs <volzhs@gmail.com> | 2018-12-10 22:34:39 +0900 |
commit | d4133ac8440321f2ae2e26fb317871bd847b35eb (patch) | |
tree | ce05e8c433f4987765633f6170c253c0e56820b1 /thirdparty/libwebp/src/dec | |
parent | bf59b73250b0d8e0edf191104246da50bdf16541 (diff) |
Update libwebp to 1.0.1
Diffstat (limited to 'thirdparty/libwebp/src/dec')
-rw-r--r-- | thirdparty/libwebp/src/dec/alphai_dec.h | 2 | ||||
-rw-r--r-- | thirdparty/libwebp/src/dec/buffer_dec.c | 3 | ||||
-rw-r--r-- | thirdparty/libwebp/src/dec/common_dec.h | 2 | ||||
-rw-r--r-- | thirdparty/libwebp/src/dec/frame_dec.c | 9 | ||||
-rw-r--r-- | thirdparty/libwebp/src/dec/idec_dec.c | 25 | ||||
-rw-r--r-- | thirdparty/libwebp/src/dec/vp8_dec.h | 2 | ||||
-rw-r--r-- | thirdparty/libwebp/src/dec/vp8i_dec.h | 4 | ||||
-rw-r--r-- | thirdparty/libwebp/src/dec/vp8l_dec.c | 103 | ||||
-rw-r--r-- | thirdparty/libwebp/src/dec/vp8li_dec.h | 2 | ||||
-rw-r--r-- | thirdparty/libwebp/src/dec/webpi_dec.h | 2 |
10 files changed, 106 insertions, 48 deletions
diff --git a/thirdparty/libwebp/src/dec/alphai_dec.h b/thirdparty/libwebp/src/dec/alphai_dec.h index e0fa281a55..a64104abeb 100644 --- a/thirdparty/libwebp/src/dec/alphai_dec.h +++ b/thirdparty/libwebp/src/dec/alphai_dec.h @@ -51,4 +51,4 @@ void WebPDeallocateAlphaMemory(VP8Decoder* const dec); } // extern "C" #endif -#endif /* WEBP_DEC_ALPHAI_DEC_H_ */ +#endif // WEBP_DEC_ALPHAI_DEC_H_ diff --git a/thirdparty/libwebp/src/dec/buffer_dec.c b/thirdparty/libwebp/src/dec/buffer_dec.c index 75eb3c40b4..3cd94eb4d9 100644 --- a/thirdparty/libwebp/src/dec/buffer_dec.c +++ b/thirdparty/libwebp/src/dec/buffer_dec.c @@ -74,7 +74,8 @@ static VP8StatusCode CheckDecBuffer(const WebPDecBuffer* const buffer) { } else { // RGB checks const WebPRGBABuffer* const buf = &buffer->u.RGBA; const int stride = abs(buf->stride); - const uint64_t size = MIN_BUFFER_SIZE(width, height, stride); + const uint64_t size = + MIN_BUFFER_SIZE(width * kModeBpp[mode], height, stride); ok &= (size <= buf->size); ok &= (stride >= width * kModeBpp[mode]); ok &= (buf->rgba != NULL); diff --git a/thirdparty/libwebp/src/dec/common_dec.h b/thirdparty/libwebp/src/dec/common_dec.h index 9995f1a51a..b158550a80 100644 --- a/thirdparty/libwebp/src/dec/common_dec.h +++ b/thirdparty/libwebp/src/dec/common_dec.h @@ -51,4 +51,4 @@ enum { MB_FEATURE_TREE_PROBS = 3, NUM_PROBAS = 11 }; -#endif // WEBP_DEC_COMMON_DEC_H_ +#endif // WEBP_DEC_COMMON_DEC_H_ diff --git a/thirdparty/libwebp/src/dec/frame_dec.c b/thirdparty/libwebp/src/dec/frame_dec.c index a9d5430d00..bda9e1a6f6 100644 --- a/thirdparty/libwebp/src/dec/frame_dec.c +++ b/thirdparty/libwebp/src/dec/frame_dec.c @@ -338,7 +338,6 @@ void VP8InitDithering(const WebPDecoderOptions* const options, for (s = 0; s < NUM_MB_SEGMENTS; ++s) { VP8QuantMatrix* const dqm = &dec->dqm_[s]; if (dqm->uv_quant_ < DITHER_AMP_TAB_SIZE) { - // TODO(skal): should we specially dither more for uv_quant_ < 0? const int idx = (dqm->uv_quant_ < 0) ? 0 : dqm->uv_quant_; dqm->dither_ = (f * kQuantToDitherAmp[idx]) >> 3; } @@ -669,15 +668,9 @@ int VP8GetThreadMethod(const WebPDecoderOptions* const options, (void)height; assert(headers == NULL || !headers->is_lossless); #if defined(WEBP_USE_THREAD) - if (width < MIN_WIDTH_FOR_THREADS) return 0; - // TODO(skal): tune the heuristic further -#if 0 - if (height < 2 * width) return 2; + if (width >= MIN_WIDTH_FOR_THREADS) return 2; #endif - return 2; -#else // !WEBP_USE_THREAD return 0; -#endif } #undef MT_CACHE_LINES diff --git a/thirdparty/libwebp/src/dec/idec_dec.c b/thirdparty/libwebp/src/dec/idec_dec.c index a371ed7500..9bc9166808 100644 --- a/thirdparty/libwebp/src/dec/idec_dec.c +++ b/thirdparty/libwebp/src/dec/idec_dec.c @@ -140,10 +140,9 @@ static void DoRemap(WebPIDecoder* const idec, ptrdiff_t offset) { if (NeedCompressedAlpha(idec)) { ALPHDecoder* const alph_dec = dec->alph_dec_; dec->alpha_data_ += offset; - if (alph_dec != NULL) { + if (alph_dec != NULL && alph_dec->vp8l_dec_ != NULL) { if (alph_dec->method_ == ALPHA_LOSSLESS_COMPRESSION) { VP8LDecoder* const alph_vp8l_dec = alph_dec->vp8l_dec_; - assert(alph_vp8l_dec != NULL); assert(dec->alpha_data_size_ >= ALPHA_HEADER_LEN); VP8LBitReaderSetBuffer(&alph_vp8l_dec->br_, dec->alpha_data_ + ALPHA_HEADER_LEN, @@ -283,10 +282,8 @@ static void RestoreContext(const MBContext* context, VP8Decoder* const dec, static VP8StatusCode IDecError(WebPIDecoder* const idec, VP8StatusCode error) { if (idec->state_ == STATE_VP8_DATA) { - VP8Io* const io = &idec->io_; - if (io->teardown != NULL) { - io->teardown(io); - } + // Synchronize the thread, clean-up and check for errors. + VP8ExitCritical((VP8Decoder*)idec->dec_, &idec->io_); } idec->state_ = STATE_ERROR; return error; @@ -451,7 +448,10 @@ static VP8StatusCode DecodeRemaining(WebPIDecoder* const idec) { VP8Decoder* const dec = (VP8Decoder*)idec->dec_; VP8Io* const io = &idec->io_; - assert(dec->ready_); + // Make sure partition #0 has been read before, to set dec to ready_. + if (!dec->ready_) { + return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR); + } for (; dec->mb_y_ < dec->mb_h_; ++dec->mb_y_) { if (idec->last_mb_y_ != dec->mb_y_) { if (!VP8ParseIntraModeRow(&dec->br_, dec)) { @@ -473,6 +473,12 @@ static VP8StatusCode DecodeRemaining(WebPIDecoder* const idec) { MemDataSize(&idec->mem_) > MAX_MB_SIZE) { return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR); } + // Synchronize the threads. + if (dec->mt_method_ > 0) { + if (!WebPGetWorkerInterface()->Sync(&dec->worker_)) { + return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR); + } + } RestoreContext(&context, dec, token_br); return VP8_STATUS_SUSPENDED; } @@ -491,6 +497,7 @@ static VP8StatusCode DecodeRemaining(WebPIDecoder* const idec) { } // Synchronize the thread and check for errors. if (!VP8ExitCritical(dec, io)) { + idec->state_ = STATE_ERROR; // prevent re-entry in IDecError return IDecError(idec, VP8_STATUS_USER_ABORT); } dec->ready_ = 0; @@ -571,6 +578,10 @@ static VP8StatusCode IDecode(WebPIDecoder* idec) { status = DecodePartition0(idec); } if (idec->state_ == STATE_VP8_DATA) { + const VP8Decoder* const dec = (VP8Decoder*)idec->dec_; + if (dec == NULL) { + return VP8_STATUS_SUSPENDED; // can't continue if we have no decoder. + } status = DecodeRemaining(idec); } if (idec->state_ == STATE_VP8L_HEADER) { diff --git a/thirdparty/libwebp/src/dec/vp8_dec.h b/thirdparty/libwebp/src/dec/vp8_dec.h index ca85b340cf..a05405df72 100644 --- a/thirdparty/libwebp/src/dec/vp8_dec.h +++ b/thirdparty/libwebp/src/dec/vp8_dec.h @@ -182,4 +182,4 @@ WEBP_EXTERN int VP8LGetInfo( } // extern "C" #endif -#endif /* WEBP_DEC_VP8_DEC_H_ */ +#endif // WEBP_DEC_VP8_DEC_H_ diff --git a/thirdparty/libwebp/src/dec/vp8i_dec.h b/thirdparty/libwebp/src/dec/vp8i_dec.h index c929933e1c..e5e89df57d 100644 --- a/thirdparty/libwebp/src/dec/vp8i_dec.h +++ b/thirdparty/libwebp/src/dec/vp8i_dec.h @@ -32,7 +32,7 @@ extern "C" { // version numbers #define DEC_MAJ_VERSION 1 #define DEC_MIN_VERSION 0 -#define DEC_REV_VERSION 0 +#define DEC_REV_VERSION 1 // YUV-cache parameters. Cache is 32-bytes wide (= one cacheline). // Constraints are: We need to store one 16x16 block of luma samples (y), @@ -316,4 +316,4 @@ const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec, } // extern "C" #endif -#endif /* WEBP_DEC_VP8I_DEC_H_ */ +#endif // WEBP_DEC_VP8I_DEC_H_ diff --git a/thirdparty/libwebp/src/dec/vp8l_dec.c b/thirdparty/libwebp/src/dec/vp8l_dec.c index 0570f53a77..333bb3e80d 100644 --- a/thirdparty/libwebp/src/dec/vp8l_dec.c +++ b/thirdparty/libwebp/src/dec/vp8l_dec.c @@ -362,12 +362,19 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize, VP8LMetadata* const hdr = &dec->hdr_; uint32_t* huffman_image = NULL; HTreeGroup* htree_groups = NULL; + // When reading htrees, some might be unused, as the format allows it. + // We will still read them but put them in this htree_group_bogus. + HTreeGroup htree_group_bogus; HuffmanCode* huffman_tables = NULL; + HuffmanCode* huffman_tables_bogus = NULL; HuffmanCode* next = NULL; int num_htree_groups = 1; + int num_htree_groups_max = 1; int max_alphabet_size = 0; int* code_lengths = NULL; const int table_size = kTableSize[color_cache_bits]; + int* mapping = NULL; + int ok = 0; if (allow_recursion && VP8LReadBits(br, 1)) { // use meta Huffman codes. @@ -384,9 +391,41 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize, // The huffman data is stored in red and green bytes. const int group = (huffman_image[i] >> 8) & 0xffff; huffman_image[i] = group; - if (group >= num_htree_groups) { - num_htree_groups = group + 1; + if (group >= num_htree_groups_max) { + num_htree_groups_max = group + 1; + } + } + // Check the validity of num_htree_groups_max. If it seems too big, use a + // smaller value for later. This will prevent big memory allocations to end + // up with a bad bitstream anyway. + // The value of 1000 is totally arbitrary. We know that num_htree_groups_max + // is smaller than (1 << 16) and should be smaller than the number of pixels + // (though the format allows it to be bigger). + if (num_htree_groups_max > 1000 || num_htree_groups_max > xsize * ysize) { + // Create a mapping from the used indices to the minimal set of used + // values [0, num_htree_groups) + mapping = (int*)WebPSafeMalloc(num_htree_groups_max, sizeof(*mapping)); + if (mapping == NULL) { + dec->status_ = VP8_STATUS_OUT_OF_MEMORY; + goto Error; + } + // -1 means a value is unmapped, and therefore unused in the Huffman + // image. + memset(mapping, 0xff, num_htree_groups_max * sizeof(*mapping)); + for (num_htree_groups = 0, i = 0; i < huffman_pixs; ++i) { + // Get the current mapping for the group and remap the Huffman image. + int* const mapped_group = &mapping[huffman_image[i]]; + if (*mapped_group == -1) *mapped_group = num_htree_groups++; + huffman_image[i] = *mapped_group; + } + huffman_tables_bogus = (HuffmanCode*)WebPSafeMalloc( + table_size, sizeof(*huffman_tables_bogus)); + if (huffman_tables_bogus == NULL) { + dec->status_ = VP8_STATUS_OUT_OF_MEMORY; + goto Error; } + } else { + num_htree_groups = num_htree_groups_max; } } @@ -403,11 +442,11 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize, } } + code_lengths = (int*)WebPSafeCalloc((uint64_t)max_alphabet_size, + sizeof(*code_lengths)); huffman_tables = (HuffmanCode*)WebPSafeMalloc(num_htree_groups * table_size, sizeof(*huffman_tables)); htree_groups = VP8LHtreeGroupsNew(num_htree_groups); - code_lengths = (int*)WebPSafeCalloc((uint64_t)max_alphabet_size, - sizeof(*code_lengths)); if (htree_groups == NULL || code_lengths == NULL || huffman_tables == NULL) { dec->status_ = VP8_STATUS_OUT_OF_MEMORY; @@ -415,28 +454,35 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize, } next = huffman_tables; - for (i = 0; i < num_htree_groups; ++i) { - HTreeGroup* const htree_group = &htree_groups[i]; + for (i = 0; i < num_htree_groups_max; ++i) { + // If the index "i" is unused in the Huffman image, read the coefficients + // but store them to a bogus htree_group. + const int is_bogus = (mapping != NULL && mapping[i] == -1); + HTreeGroup* const htree_group = + is_bogus ? &htree_group_bogus : + &htree_groups[(mapping == NULL) ? i : mapping[i]]; HuffmanCode** const htrees = htree_group->htrees; + HuffmanCode* huffman_tables_i = is_bogus ? huffman_tables_bogus : next; int size; int total_size = 0; int is_trivial_literal = 1; int max_bits = 0; for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) { int alphabet_size = kAlphabetSize[j]; - htrees[j] = next; + htrees[j] = huffman_tables_i; if (j == 0 && color_cache_bits > 0) { alphabet_size += 1 << color_cache_bits; } - size = ReadHuffmanCode(alphabet_size, dec, code_lengths, next); + size = + ReadHuffmanCode(alphabet_size, dec, code_lengths, huffman_tables_i); if (size == 0) { goto Error; } if (is_trivial_literal && kLiteralMap[j] == 1) { - is_trivial_literal = (next->bits == 0); + is_trivial_literal = (huffman_tables_i->bits == 0); } - total_size += next->bits; - next += size; + total_size += huffman_tables_i->bits; + huffman_tables_i += size; if (j <= ALPHA) { int local_max_bits = code_lengths[0]; int k; @@ -448,38 +494,41 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize, max_bits += local_max_bits; } } + if (!is_bogus) next = huffman_tables_i; htree_group->is_trivial_literal = is_trivial_literal; htree_group->is_trivial_code = 0; if (is_trivial_literal) { const int red = htrees[RED][0].value; const int blue = htrees[BLUE][0].value; const int alpha = htrees[ALPHA][0].value; - htree_group->literal_arb = - ((uint32_t)alpha << 24) | (red << 16) | blue; + htree_group->literal_arb = ((uint32_t)alpha << 24) | (red << 16) | blue; if (total_size == 0 && htrees[GREEN][0].value < NUM_LITERAL_CODES) { htree_group->is_trivial_code = 1; htree_group->literal_arb |= htrees[GREEN][0].value << 8; } } - htree_group->use_packed_table = !htree_group->is_trivial_code && - (max_bits < HUFFMAN_PACKED_BITS); + htree_group->use_packed_table = + !htree_group->is_trivial_code && (max_bits < HUFFMAN_PACKED_BITS); if (htree_group->use_packed_table) BuildPackedTable(htree_group); } - WebPSafeFree(code_lengths); + ok = 1; - // All OK. Finalize pointers and return. + // All OK. Finalize pointers. hdr->huffman_image_ = huffman_image; hdr->num_htree_groups_ = num_htree_groups; hdr->htree_groups_ = htree_groups; hdr->huffman_tables_ = huffman_tables; - return 1; Error: WebPSafeFree(code_lengths); - WebPSafeFree(huffman_image); - WebPSafeFree(huffman_tables); - VP8LHtreeGroupsFree(htree_groups); - return 0; + WebPSafeFree(huffman_tables_bogus); + WebPSafeFree(mapping); + if (!ok) { + WebPSafeFree(huffman_image); + WebPSafeFree(huffman_tables); + VP8LHtreeGroupsFree(htree_groups); + } + return ok; } //------------------------------------------------------------------------------ @@ -884,7 +933,11 @@ static WEBP_INLINE void CopyBlock8b(uint8_t* const dst, int dist, int length) { #endif break; case 2: +#if !defined(WORDS_BIGENDIAN) memcpy(&pattern, src, sizeof(uint16_t)); +#else + pattern = ((uint32_t)src[0] << 8) | src[1]; +#endif #if defined(__arm__) || defined(_M_ARM) pattern |= pattern << 16; #elif defined(WEBP_USE_MIPS_DSP_R2) @@ -1523,7 +1576,6 @@ int VP8LDecodeAlphaHeader(ALPHDecoder* const alph_dec, if (dec == NULL) return 0; assert(alph_dec != NULL); - alph_dec->vp8l_dec_ = dec; dec->width_ = alph_dec->width_; dec->height_ = alph_dec->height_; @@ -1555,11 +1607,12 @@ int VP8LDecodeAlphaHeader(ALPHDecoder* const alph_dec, if (!ok) goto Err; + // Only set here, once we are sure it is valid (to avoid thread races). + alph_dec->vp8l_dec_ = dec; return 1; Err: - VP8LDelete(alph_dec->vp8l_dec_); - alph_dec->vp8l_dec_ = NULL; + VP8LDelete(dec); return 0; } diff --git a/thirdparty/libwebp/src/dec/vp8li_dec.h b/thirdparty/libwebp/src/dec/vp8li_dec.h index 8e500cf9ff..0a4d613f99 100644 --- a/thirdparty/libwebp/src/dec/vp8li_dec.h +++ b/thirdparty/libwebp/src/dec/vp8li_dec.h @@ -132,4 +132,4 @@ void VP8LDelete(VP8LDecoder* const dec); } // extern "C" #endif -#endif /* WEBP_DEC_VP8LI_DEC_H_ */ +#endif // WEBP_DEC_VP8LI_DEC_H_ diff --git a/thirdparty/libwebp/src/dec/webpi_dec.h b/thirdparty/libwebp/src/dec/webpi_dec.h index c378ba6fc3..24baff5d27 100644 --- a/thirdparty/libwebp/src/dec/webpi_dec.h +++ b/thirdparty/libwebp/src/dec/webpi_dec.h @@ -130,4 +130,4 @@ int WebPAvoidSlowMemory(const WebPDecBuffer* const output, } // extern "C" #endif -#endif /* WEBP_DEC_WEBPI_DEC_H_ */ +#endif // WEBP_DEC_WEBPI_DEC_H_ |