diff options
Diffstat (limited to 'media')
49 files changed, 444 insertions, 187 deletions
diff --git a/media/libstagefright/frameworks/av/media/libstagefright/SampleIterator.cpp b/media/libstagefright/frameworks/av/media/libstagefright/SampleIterator.cpp index 37bb2b7a5..f1c797c9a 100644 --- a/media/libstagefright/frameworks/av/media/libstagefright/SampleIterator.cpp +++ b/media/libstagefright/frameworks/av/media/libstagefright/SampleIterator.cpp @@ -321,7 +321,18 @@ status_t SampleIterator::findSampleTime( *time = mTTSSampleTime + mTTSDuration * (sampleIndex - mTTSSampleIndex); - *time += mTable->getCompositionTimeOffset(sampleIndex); + int32_t offset = mTable->getCompositionTimeOffset(sampleIndex); + if ((offset < 0 && *time < (offset == INT32_MIN ? + INT32_MAX : uint32_t(-offset))) || + (offset > 0 && *time > UINT32_MAX - offset)) { + ALOGE("%u + %d would overflow", *time, offset); + return ERROR_OUT_OF_RANGE; + } + if (offset > 0) { + *time += offset; + } else { + *time -= (offset == INT32_MIN ? INT32_MAX : (-offset)); + } return OK; } diff --git a/media/libstagefright/frameworks/av/media/libstagefright/SampleTable.cpp b/media/libstagefright/frameworks/av/media/libstagefright/SampleTable.cpp index bbb2227e7..bc991e8e1 100644 --- a/media/libstagefright/frameworks/av/media/libstagefright/SampleTable.cpp +++ b/media/libstagefright/frameworks/av/media/libstagefright/SampleTable.cpp @@ -52,14 +52,14 @@ struct SampleTable::CompositionDeltaLookup { CompositionDeltaLookup(); void setEntries( - const uint32_t *deltaEntries, size_t numDeltaEntries); + const int32_t *deltaEntries, size_t numDeltaEntries); - uint32_t getCompositionTimeOffset(uint32_t sampleIndex); + int32_t getCompositionTimeOffset(uint32_t sampleIndex); private: Mutex mLock; - const uint32_t *mDeltaEntries; + const int32_t *mDeltaEntries; size_t mNumDeltaEntries; size_t mCurrentDeltaEntry; @@ -76,7 +76,7 @@ SampleTable::CompositionDeltaLookup::CompositionDeltaLookup() } void SampleTable::CompositionDeltaLookup::setEntries( - const uint32_t *deltaEntries, size_t numDeltaEntries) { + const int32_t *deltaEntries, size_t numDeltaEntries) { Mutex::Autolock autolock(mLock); mDeltaEntries = deltaEntries; @@ -85,7 +85,7 @@ void SampleTable::CompositionDeltaLookup::setEntries( mCurrentEntrySampleIndex = 0; } -uint32_t SampleTable::CompositionDeltaLookup::getCompositionTimeOffset( +int32_t SampleTable::CompositionDeltaLookup::getCompositionTimeOffset( uint32_t sampleIndex) { Mutex::Autolock autolock(mLock); @@ -381,6 +381,10 @@ status_t SampleTable::setTimeToSampleParams( return OK; } +// NOTE: per 14996-12, version 0 ctts contains unsigned values, while version 1 +// contains signed values, however some software creates version 0 files that +// contain signed values, so we're always treating the values as signed, +// regardless of version. status_t SampleTable::setCompositionTimeToSampleParams( off64_t data_offset, size_t data_size) { ALOGV("There are reordered frames present."); @@ -398,8 +402,12 @@ status_t SampleTable::setCompositionTimeToSampleParams( uint32_t numEntries = U32_AT(&header[4]); - if (U32_AT(header) != 0 && numEntries) { - // Expected version = 0, flags = 0. + uint32_t flags = U32_AT(header); + uint32_t version = flags >> 24; + flags &= 0xffffff; + + if ((version != 0 && version != 1) || flags != 0) { + // Expected version = 0 or 1, flags = 0. return ERROR_MALFORMED; } @@ -408,7 +416,7 @@ status_t SampleTable::setCompositionTimeToSampleParams( } mNumCompositionTimeDeltaEntries = numEntries; - mCompositionTimeDeltaEntries = new (mozilla::fallible) uint32_t[2 * numEntries]; + mCompositionTimeDeltaEntries = new (mozilla::fallible) int32_t[2 * numEntries]; if (!mCompositionTimeDeltaEntries) { return ERROR_BUFFER_TOO_SMALL; } @@ -801,12 +809,28 @@ status_t SampleTable::buildSampleEntriesTable() { mSampleTimeEntries[sampleIndex].mSampleIndex = sampleIndex; - uint32_t compTimeDelta = + int32_t compTimeDelta = mCompositionDeltaLookup->getCompositionTimeOffset( sampleIndex); + if ((compTimeDelta < 0 && sampleTime < + (compTimeDelta == INT32_MIN ? + INT32_MAX : uint32_t(-compTimeDelta))) + || (compTimeDelta > 0 && + sampleTime > UINT32_MAX - compTimeDelta)) { + ALOGE("%u + %d would overflow, clamping", + sampleTime, compTimeDelta); + if (compTimeDelta < 0) { + sampleTime = 0; + } else { + sampleTime = UINT32_MAX; + } + compTimeDelta = 0; + } + mSampleTimeEntries[sampleIndex].mCompositionTime = - sampleTime + compTimeDelta; + compTimeDelta > 0 ? sampleTime + compTimeDelta: + sampleTime - (-compTimeDelta); } ++sampleIndex; @@ -1136,7 +1160,7 @@ status_t SampleTable::getMetaDataForSample( return OK; } -uint32_t SampleTable::getCompositionTimeOffset(uint32_t sampleIndex) { +int32_t SampleTable::getCompositionTimeOffset(uint32_t sampleIndex) { return mCompositionDeltaLookup->getCompositionTimeOffset(sampleIndex); } diff --git a/media/libstagefright/frameworks/av/media/libstagefright/include/SampleTable.h b/media/libstagefright/frameworks/av/media/libstagefright/include/SampleTable.h index e115c92bb..c235f281e 100644 --- a/media/libstagefright/frameworks/av/media/libstagefright/include/SampleTable.h +++ b/media/libstagefright/frameworks/av/media/libstagefright/include/SampleTable.h @@ -134,7 +134,7 @@ private: }; SampleTimeEntry *mSampleTimeEntries; - uint32_t *mCompositionTimeDeltaEntries; + int32_t *mCompositionTimeDeltaEntries; size_t mNumCompositionTimeDeltaEntries; CompositionDeltaLookup *mCompositionDeltaLookup; @@ -171,7 +171,7 @@ private: friend struct SampleIterator; status_t getSampleSize_l(uint32_t sample_index, size_t *sample_size); - uint32_t getCompositionTimeOffset(uint32_t sampleIndex); + int32_t getCompositionTimeOffset(uint32_t sampleIndex); static int CompareIncreasingTime(const void *, const void *); diff --git a/media/libwebp/AUTHORS b/media/libwebp/AUTHORS index 83c7b9c5e..0d70b7fb2 100644 --- a/media/libwebp/AUTHORS +++ b/media/libwebp/AUTHORS @@ -1,4 +1,5 @@ Contributors: +- Alan Browning (browning at google dot com) - Charles Munger (clm at google dot com) - Christian Duvivier (cduvivier at google dot com) - Djordje Pesut (djordje dot pesut at imgtec dot com) @@ -6,9 +7,10 @@ Contributors: - James Zern (jzern at google dot com) - Jan Engelhardt (jengelh at medozas dot de) - Jehan (jehan at girinstud dot io) -- Johann (johann dot koenig at duck dot com) +- Johann Koenig (johann dot koenig at duck dot com) - Jovan Zelincevic (jovan dot zelincevic at imgtec dot com) - Jyrki Alakuijala (jyrki at google dot com) +- Konstantin Ivlev (tomskside at gmail dot com) - Lode Vandevenne (lode at google dot com) - Lou Quillio (louquillio at google dot com) - Mans Rullgard (mans at mansr dot com) @@ -37,3 +39,4 @@ Contributors: - Vincent Rabaud (vrabaud at google dot com) - Vlad Tsyrklevich (vtsyrklevich at chromium dot org) - Yang Zhang (yang dot zhang at arm dot com) +- Yannis Guyon (yguyon at google dot com) diff --git a/media/libwebp/NEWS b/media/libwebp/NEWS index 480cb7d34..aa393c819 100644 --- a/media/libwebp/NEWS +++ b/media/libwebp/NEWS @@ -1,3 +1,23 @@ +- 1/14/2019: version 1.0.2 + This is a binary compatible release. + * (Windows) unicode file support in the tools (linux and mac already had + support, issue #398) + * lossless encoder speedups + * lossy encoder speedup on ARM + * lossless multi-threaded security fix (chromium:917029) + +- 11/2/2018: version 1.0.1 + This is a binary compatible release. + * lossless encoder speedups + * big-endian fix for alpha decoding (issue #393) + * gif2webp fix for loop count=65535 transcode (issue #382) + * further security related hardening in libwebp & libwebpmux + (issues #383, #385, #386, #387, #388, #391) + (oss-fuzz #9099, #9100, #9105, #9106, #9111, #9112, #9119, #9123, #9170, + #9178, #9179, #9183, #9186, #9191, #9364, #9417, #9496, #10349, + #10423, #10634, #10700, #10838, #10922, #11021, #11088, #11152) + * miscellaneous bug & build fixes (issues #381, #394, #396, #397, #400) + - 4/2/2018: version 1.0.0 This is a binary compatible release. * lossy encoder improvements to avoid chroma shifts in various circumstances diff --git a/media/libwebp/README b/media/libwebp/README index a76b3787f..502a4c1c2 100644 --- a/media/libwebp/README +++ b/media/libwebp/README @@ -4,7 +4,7 @@ \__\__/\____/\_____/__/ ____ ___ / _/ / \ \ / _ \/ _/ / \_/ / / \ \ __/ \__ - \____/____/\_____/_____/____/v1.0.0 + \____/____/\_____/_____/____/v1.0.2 Description: ============ @@ -136,6 +136,8 @@ cmake -DWEBP_BUILD_CWEBP=ON -DWEBP_BUILD_DWEBP=ON ../ or through your favorite interface (like ccmake or cmake-qt-gui). +Use option -DWEBP_UNICODE=ON for Unicode support on Windows (with chcp 65001). + Finally, once installed, you can also use WebP in your CMake project by doing: find_package(WebP) @@ -402,12 +404,14 @@ Options are: -nofilter .... disable in-loop filtering -dither <int> dithering strength (0..100), default=50 -noalphadither disable alpha plane dithering + -usebgcolor .. display background color -mt .......... use multi-threading -info ........ print info -h ........... this help message Keyboard shortcuts: 'c' ................ toggle use of color profile + 'b' ................ toggle background color display 'i' ................ overlay file information 'd' ................ disable blending & disposal (debug) 'q' / 'Q' / ESC .... quit @@ -470,6 +474,9 @@ Per-frame options (only used for subsequent images input): example: img2webp -loop 2 in0.png -lossy in1.jpg -d 80 in2.tiff -o out.webp +Note: if a single file name is passed as the argument, the arguments will be +tokenized from this file. The file name must not start with the character '-'. + Animated GIF conversion: ======================== Animated GIF files can be converted to WebP files with animation using the diff --git a/media/libwebp/README.mux b/media/libwebp/README.mux index bd4f92fa3..7e9c3c903 100644 --- a/media/libwebp/README.mux +++ b/media/libwebp/README.mux @@ -1,7 +1,7 @@ __ __ ____ ____ ____ __ __ _ __ __ / \\/ \/ _ \/ _ \/ _ \/ \ \/ \___/_ / _\ \ / __/ _ \ __/ / / (_/ /__ - \__\__/\_____/_____/__/ \__//_/\_____/__/___/v1.0.0 + \__\__/\_____/_____/__/ \__//_/\_____/__/___/v1.0.2 Description: @@ -211,6 +211,35 @@ Code example: For a detailed AnimEncoder API reference, please refer to the header file (src/webp/mux.h). +AnimDecoder API: +================ +This AnimDecoder API allows decoding (possibly) animated WebP images. + +Code Example: + + WebPAnimDecoderOptions dec_options; + WebPAnimDecoderOptionsInit(&dec_options); + // Tune 'dec_options' as needed. + WebPAnimDecoder* dec = WebPAnimDecoderNew(webp_data, &dec_options); + WebPAnimInfo anim_info; + WebPAnimDecoderGetInfo(dec, &anim_info); + for (uint32_t i = 0; i < anim_info.loop_count; ++i) { + while (WebPAnimDecoderHasMoreFrames(dec)) { + uint8_t* buf; + int timestamp; + WebPAnimDecoderGetNext(dec, &buf, ×tamp); + // ... (Render 'buf' based on 'timestamp'). + // ... (Do NOT free 'buf', as it is owned by 'dec'). + } + WebPAnimDecoderReset(dec); + } + const WebPDemuxer* demuxer = WebPAnimDecoderGetDemuxer(dec); + // ... (Do something using 'demuxer'; e.g. get EXIF/XMP/ICC data). + WebPAnimDecoderDelete(dec); + +For a detailed AnimDecoder API reference, please refer to the header file +(src/webp/demux.h). + Bugs: ===== diff --git a/media/libwebp/UXPCHANGES b/media/libwebp/UXPCHANGES index 8c3eb5ad2..78b7823c8 100644 --- a/media/libwebp/UXPCHANGES +++ b/media/libwebp/UXPCHANGES @@ -2,3 +2,4 @@ Changes made to pristine libwebp source by Moonchild Productions and mozilla.org 2017/01/27 -- Synced with libwebp-0.6.0 (BZ #1294490). 2018/06/29 -- Synced with libwebp-1.0.0 + BUG=webp:381,383,384. +2019/01/21 -- Synced with libwebp-1.0.2 diff --git a/media/libwebp/dec/alphai_dec.h b/media/libwebp/dec/alphai_dec.h index 3b40691b5..d2a404dc5 100644 --- a/media/libwebp/dec/alphai_dec.h +++ b/media/libwebp/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/media/libwebp/dec/common_dec.h b/media/libwebp/dec/common_dec.h index 9995f1a51..b158550a8 100644 --- a/media/libwebp/dec/common_dec.h +++ b/media/libwebp/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/media/libwebp/dec/frame_dec.c b/media/libwebp/dec/frame_dec.c index 57e4d9669..3d1d66274 100644 --- a/media/libwebp/dec/frame_dec.c +++ b/media/libwebp/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/media/libwebp/dec/idec_dec.c b/media/libwebp/dec/idec_dec.c index c9506bc83..ee0d33eac 100644 --- a/media/libwebp/dec/idec_dec.c +++ b/media/libwebp/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, @@ -449,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)) { @@ -471,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; } @@ -489,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; @@ -569,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/media/libwebp/dec/vp8_dec.h b/media/libwebp/dec/vp8_dec.h index 7b4941d65..03f4415fb 100644 --- a/media/libwebp/dec/vp8_dec.h +++ b/media/libwebp/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/media/libwebp/dec/vp8i_dec.h b/media/libwebp/dec/vp8i_dec.h index d0ef67b91..fabee44a0 100644 --- a/media/libwebp/dec/vp8i_dec.h +++ b/media/libwebp/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 2 // 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/media/libwebp/dec/vp8l_dec.c b/media/libwebp/dec/vp8l_dec.c index 3d303fb22..0502cb9a5 100644 --- a/media/libwebp/dec/vp8l_dec.c +++ b/media/libwebp/dec/vp8l_dec.c @@ -359,17 +359,22 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize, int color_cache_bits, int allow_recursion) { int i, j; VP8LBitReader* const br = &dec->br_; - VP8LBitReader br_tmp; 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_limit = 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. @@ -386,21 +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. If it seems too big, use a + // 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 + // 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 > 1000 || num_htree_groups > xsize * ysize) { - num_htree_groups_limit = (xsize * ysize > 1000) ? 1000 : xsize * ysize; - br_tmp = dec->br_; + 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_limit = num_htree_groups; + num_htree_groups = num_htree_groups_max; } } @@ -419,99 +444,91 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize, code_lengths = (int*)WebPSafeCalloc((uint64_t)max_alphabet_size, sizeof(*code_lengths)); - // If num_htree_groups_tmp == num_htree_groups, the following loop is executed - // once. - // If num_htree_groups_tmp != num_htree_groups, we execute the loop the first - // time with little memory allocation in the hope that there is a bitstream - // error. If after num_htree_groups_tmp iterations, no error appears, - // num_htree_groups is probably the right value so try it out. - do { - huffman_tables = (HuffmanCode*)WebPSafeMalloc( - num_htree_groups_limit * table_size, sizeof(*huffman_tables)); - htree_groups = VP8LHtreeGroupsNew(num_htree_groups_limit); - - if (htree_groups == NULL || code_lengths == NULL || - huffman_tables == NULL) { - dec->status_ = VP8_STATUS_OUT_OF_MEMORY; - goto Error; - } + huffman_tables = (HuffmanCode*)WebPSafeMalloc(num_htree_groups * table_size, + sizeof(*huffman_tables)); + htree_groups = VP8LHtreeGroupsNew(num_htree_groups); - next = huffman_tables; - for (i = 0; i < num_htree_groups_limit; ++i) { - HTreeGroup* const htree_group = &htree_groups[i]; - HuffmanCode** const htrees = htree_group->htrees; - 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; - if (j == 0 && color_cache_bits > 0) { - alphabet_size += 1 << color_cache_bits; - } - size = ReadHuffmanCode(alphabet_size, dec, code_lengths, next); - if (size == 0) { - goto Error; - } - if (is_trivial_literal && kLiteralMap[j] == 1) { - is_trivial_literal = (next->bits == 0); - } - total_size += next->bits; - next += size; - if (j <= ALPHA) { - int local_max_bits = code_lengths[0]; - int k; - for (k = 1; k < alphabet_size; ++k) { - if (code_lengths[k] > local_max_bits) { - local_max_bits = code_lengths[k]; - } - } - max_bits += local_max_bits; - } + if (htree_groups == NULL || code_lengths == NULL || huffman_tables == NULL) { + dec->status_ = VP8_STATUS_OUT_OF_MEMORY; + goto Error; + } + + next = huffman_tables; + 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] = huffman_tables_i; + if (j == 0 && color_cache_bits > 0) { + alphabet_size += 1 << color_cache_bits; } - 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; - 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; + 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 = (huffman_tables_i->bits == 0); + } + total_size += huffman_tables_i->bits; + huffman_tables_i += size; + if (j <= ALPHA) { + int local_max_bits = code_lengths[0]; + int k; + for (k = 1; k < alphabet_size; ++k) { + if (code_lengths[k] > local_max_bits) { + local_max_bits = code_lengths[k]; + } } + max_bits += local_max_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); } - // If we have survived up to here, num_htree_groups might actually be - // that big so restart with a proper allocation. - if (num_htree_groups != num_htree_groups_limit) { - num_htree_groups_limit = num_htree_groups; - WebPSafeFree(huffman_tables); - VP8LHtreeGroupsFree(htree_groups); - huffman_tables = NULL; - htree_groups = NULL; - dec->br_ = br_tmp; + 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; + 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; + } } - } while (i != num_htree_groups); - WebPSafeFree(code_lengths); + htree_group->use_packed_table = + !htree_group->is_trivial_code && (max_bits < HUFFMAN_PACKED_BITS); + if (htree_group->use_packed_table) BuildPackedTable(htree_group); + } + 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; } //------------------------------------------------------------------------------ @@ -916,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) @@ -1555,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_; @@ -1587,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/media/libwebp/dec/vp8li_dec.h b/media/libwebp/dec/vp8li_dec.h index ed89a02a9..2b9c95a44 100644 --- a/media/libwebp/dec/vp8li_dec.h +++ b/media/libwebp/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/media/libwebp/dec/webpi_dec.h b/media/libwebp/dec/webpi_dec.h index d0a045e70..83d7444e5 100644 --- a/media/libwebp/dec/webpi_dec.h +++ b/media/libwebp/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_ diff --git a/media/libwebp/demux/demux.c b/media/libwebp/demux/demux.c index aec2a0a2d..2034024d0 100644 --- a/media/libwebp/demux/demux.c +++ b/media/libwebp/demux/demux.c @@ -25,7 +25,7 @@ #define DMUX_MAJ_VERSION 1 #define DMUX_MIN_VERSION 0 -#define DMUX_REV_VERSION 0 +#define DMUX_REV_VERSION 2 typedef struct { size_t start_; // start location of the data diff --git a/media/libwebp/dsp/dsp.h b/media/libwebp/dsp/dsp.h index 537ea2044..4e509bd2c 100644 --- a/media/libwebp/dsp/dsp.h +++ b/media/libwebp/dsp/dsp.h @@ -76,10 +76,6 @@ extern "C" { #define WEBP_USE_SSE41 #endif -#if defined(__AVX2__) || defined(WEBP_HAVE_AVX2) -#define WEBP_USE_AVX2 -#endif - // The intrinsics currently cause compiler errors with arm-nacl-gcc and the // inline assembly would need to be modified for use with Native Client. #if (defined(__ARM_NEON__) || \ @@ -679,4 +675,4 @@ void VP8FiltersInit(void); } // extern "C" #endif -#endif /* WEBP_DSP_DSP_H_ */ +#endif // WEBP_DSP_DSP_H_ diff --git a/media/libwebp/dsp/lossless.c b/media/libwebp/dsp/lossless.c index 93ccecdfd..1a1523d22 100644 --- a/media/libwebp/dsp/lossless.c +++ b/media/libwebp/dsp/lossless.c @@ -23,8 +23,6 @@ #include "../dsp/lossless.h" #include "../dsp/lossless_common.h" -#define MAX_DIFF_COST (1e30f) - //------------------------------------------------------------------------------ // Image transforms. diff --git a/media/libwebp/dsp/lossless.h b/media/libwebp/dsp/lossless.h index 4a1d1e0dd..6db5fafc1 100644 --- a/media/libwebp/dsp/lossless.h +++ b/media/libwebp/dsp/lossless.h @@ -163,7 +163,7 @@ extern VP8LCostCombinedFunc VP8LExtraCostCombined; extern VP8LCombinedShannonEntropyFunc VP8LCombinedShannonEntropy; typedef struct { // small struct to hold counters - int counts[2]; // index: 0=zero steak, 1=non-zero streak + int counts[2]; // index: 0=zero streak, 1=non-zero streak int streaks[2][2]; // [zero/non-zero][streak<3 / streak>=3] } VP8LStreaks; @@ -194,10 +194,14 @@ extern VP8LGetEntropyUnrefinedFunc VP8LGetEntropyUnrefined; void VP8LBitsEntropyUnrefined(const uint32_t* const array, int n, VP8LBitEntropy* const entropy); -typedef void (*VP8LHistogramAddFunc)(const VP8LHistogram* const a, - const VP8LHistogram* const b, - VP8LHistogram* const out); -extern VP8LHistogramAddFunc VP8LHistogramAdd; +typedef void (*VP8LAddVectorFunc)(const uint32_t* a, const uint32_t* b, + uint32_t* out, int size); +extern VP8LAddVectorFunc VP8LAddVector; +typedef void (*VP8LAddVectorEqFunc)(const uint32_t* a, uint32_t* out, int size); +extern VP8LAddVectorEqFunc VP8LAddVectorEq; +void VP8LHistogramAdd(const VP8LHistogram* const a, + const VP8LHistogram* const b, + VP8LHistogram* const out); // ----------------------------------------------------------------------------- // PrefixEncode() diff --git a/media/libwebp/dsp/msa_macro.h b/media/libwebp/dsp/msa_macro.h index dfacda6cc..de026a1d9 100644 --- a/media/libwebp/dsp/msa_macro.h +++ b/media/libwebp/dsp/msa_macro.h @@ -1389,4 +1389,4 @@ static WEBP_INLINE uint32_t func_hadd_uh_u32(v8u16 in) { } while (0) #define AVER_UB2_UB(...) AVER_UB2(v16u8, __VA_ARGS__) -#endif /* WEBP_DSP_MSA_MACRO_H_ */ +#endif // WEBP_DSP_MSA_MACRO_H_ diff --git a/media/libwebp/dsp/quant.h b/media/libwebp/dsp/quant.h new file mode 100644 index 000000000..b82e728a5 --- /dev/null +++ b/media/libwebp/dsp/quant.h @@ -0,0 +1,70 @@ +// Copyright 2018 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- + +#ifndef WEBP_DSP_QUANT_H_ +#define WEBP_DSP_QUANT_H_ + +#include "../dsp/dsp.h" +#include "../webp/types.h" + +#if defined(WEBP_USE_NEON) && !defined(WEBP_ANDROID_NEON) && \ + !defined(WEBP_HAVE_NEON_RTCD) +#include <arm_neon.h> + +#define IsFlat IsFlat_NEON + +static uint32x2_t horizontal_add_uint32x4(const uint32x4_t a) { + const uint64x2_t b = vpaddlq_u32(a); + return vadd_u32(vreinterpret_u32_u64(vget_low_u64(b)), + vreinterpret_u32_u64(vget_high_u64(b))); +} + +static WEBP_INLINE int IsFlat(const int16_t* levels, int num_blocks, + int thresh) { + const int16x8_t tst_ones = vdupq_n_s16(-1); + uint32x4_t sum = vdupq_n_u32(0); + + for (int i = 0; i < num_blocks; ++i) { + // Set DC to zero. + const int16x8_t a_0 = vsetq_lane_s16(0, vld1q_s16(levels), 0); + const int16x8_t a_1 = vld1q_s16(levels + 8); + + const uint16x8_t b_0 = vshrq_n_u16(vtstq_s16(a_0, tst_ones), 15); + const uint16x8_t b_1 = vshrq_n_u16(vtstq_s16(a_1, tst_ones), 15); + + sum = vpadalq_u16(sum, b_0); + sum = vpadalq_u16(sum, b_1); + + levels += 16; + } + return thresh >= (int32_t)vget_lane_u32(horizontal_add_uint32x4(sum), 0); +} + +#else + +#define IsFlat IsFlat_C + +static WEBP_INLINE int IsFlat(const int16_t* levels, int num_blocks, + int thresh) { + int score = 0; + while (num_blocks-- > 0) { // TODO(skal): refine positional scoring? + int i; + for (i = 1; i < 16; ++i) { // omit DC, we're only interested in AC + score += (levels[i] != 0); + if (score > thresh) return 0; + } + levels += 16; + } + return 1; +} + +#endif // defined(WEBP_USE_NEON) && !defined(WEBP_ANDROID_NEON) && + // !defined(WEBP_HAVE_NEON_RTCD) + +#endif // WEBP_DSP_QUANT_H_ diff --git a/media/libwebp/dsp/rescaler.c b/media/libwebp/dsp/rescaler.c index f70e6beef..6bf387f8e 100644 --- a/media/libwebp/dsp/rescaler.c +++ b/media/libwebp/dsp/rescaler.c @@ -21,6 +21,7 @@ #define ROUNDER (WEBP_RESCALER_ONE >> 1) #define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX) +#define MULT_FIX_FLOOR(x, y) (((uint64_t)(x) * (y)) >> WEBP_RESCALER_RFIX) //------------------------------------------------------------------------------ // Row import @@ -138,7 +139,7 @@ void WebPRescalerExportRowShrink_C(WebPRescaler* const wrk) { if (yscale) { for (x_out = 0; x_out < x_out_max; ++x_out) { const uint32_t frac = (uint32_t)MULT_FIX(frow[x_out], yscale); - const int v = (int)MULT_FIX(irow[x_out] - frac, wrk->fxy_scale); + const int v = (int)MULT_FIX_FLOOR(irow[x_out] - frac, wrk->fxy_scale); assert(v >= 0 && v <= 255); dst[x_out] = v; irow[x_out] = frac; // new fractional start @@ -153,6 +154,7 @@ void WebPRescalerExportRowShrink_C(WebPRescaler* const wrk) { } } +#undef MULT_FIX_FLOOR #undef MULT_FIX #undef ROUNDER diff --git a/media/libwebp/dsp/rescaler_neon.c b/media/libwebp/dsp/rescaler_neon.c index 835e646c1..b560d0cdc 100644 --- a/media/libwebp/dsp/rescaler_neon.c +++ b/media/libwebp/dsp/rescaler_neon.c @@ -22,6 +22,7 @@ #define ROUNDER (WEBP_RESCALER_ONE >> 1) #define MULT_FIX_C(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX) +#define MULT_FIX_FLOOR_C(x, y) (((uint64_t)(x) * (y)) >> WEBP_RESCALER_RFIX) #define LOAD_32x4(SRC, DST) const uint32x4_t DST = vld1q_u32((SRC)) #define LOAD_32x8(SRC, DST0, DST1) \ @@ -35,8 +36,11 @@ #if (WEBP_RESCALER_RFIX == 32) #define MAKE_HALF_CST(C) vdupq_n_s32((int32_t)((C) >> 1)) -#define MULT_FIX(A, B) /* note: B is actualy scale>>1. See MAKE_HALF_CST */ \ +// note: B is actualy scale>>1. See MAKE_HALF_CST +#define MULT_FIX(A, B) \ vreinterpretq_u32_s32(vqrdmulhq_s32(vreinterpretq_s32_u32((A)), (B))) +#define MULT_FIX_FLOOR(A, B) \ + vreinterpretq_u32_s32(vqdmulhq_s32(vreinterpretq_s32_u32((A)), (B))) #else #error "MULT_FIX/WEBP_RESCALER_RFIX need some more work" #endif @@ -135,8 +139,8 @@ static void RescalerExportRowShrink_NEON(WebPRescaler* const wrk) { const uint32x4_t A1 = MULT_FIX(in1, yscale_half); const uint32x4_t B0 = vqsubq_u32(in2, A0); const uint32x4_t B1 = vqsubq_u32(in3, A1); - const uint32x4_t C0 = MULT_FIX(B0, fxy_scale_half); - const uint32x4_t C1 = MULT_FIX(B1, fxy_scale_half); + const uint32x4_t C0 = MULT_FIX_FLOOR(B0, fxy_scale_half); + const uint32x4_t C1 = MULT_FIX_FLOOR(B1, fxy_scale_half); const uint16x4_t D0 = vmovn_u32(C0); const uint16x4_t D1 = vmovn_u32(C1); const uint8x8_t E = vmovn_u16(vcombine_u16(D0, D1)); @@ -145,7 +149,7 @@ static void RescalerExportRowShrink_NEON(WebPRescaler* const wrk) { } for (; x_out < x_out_max; ++x_out) { const uint32_t frac = (uint32_t)MULT_FIX_C(frow[x_out], yscale); - const int v = (int)MULT_FIX_C(irow[x_out] - frac, wrk->fxy_scale); + const int v = (int)MULT_FIX_FLOOR_C(irow[x_out] - frac, fxy_scale); assert(v >= 0 && v <= 255); dst[x_out] = v; irow[x_out] = frac; // new fractional start @@ -170,6 +174,12 @@ static void RescalerExportRowShrink_NEON(WebPRescaler* const wrk) { } } +#undef MULT_FIX_FLOOR_C +#undef MULT_FIX_C +#undef MULT_FIX_FLOOR +#undef MULT_FIX +#undef ROUNDER + //------------------------------------------------------------------------------ extern void WebPRescalerDspInitNEON(void); diff --git a/media/libwebp/dsp/rescaler_sse2.c b/media/libwebp/dsp/rescaler_sse2.c index 1306f8457..2d35f76ab 100644 --- a/media/libwebp/dsp/rescaler_sse2.c +++ b/media/libwebp/dsp/rescaler_sse2.c @@ -25,6 +25,7 @@ #define ROUNDER (WEBP_RESCALER_ONE >> 1) #define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX) +#define MULT_FIX_FLOOR(x, y) (((uint64_t)(x) * (y)) >> WEBP_RESCALER_RFIX) // input: 8 bytes ABCDEFGH -> output: A0E0B0F0C0G0D0H0 static void LoadTwoPixels_SSE2(const uint8_t* const src, __m128i* out) { @@ -224,6 +225,35 @@ static WEBP_INLINE void ProcessRow_SSE2(const __m128i* const A0, _mm_storel_epi64((__m128i*)dst, G); } +static WEBP_INLINE void ProcessRow_Floor_SSE2(const __m128i* const A0, + const __m128i* const A1, + const __m128i* const A2, + const __m128i* const A3, + const __m128i* const mult, + uint8_t* const dst) { + const __m128i mask = _mm_set_epi32(0xffffffffu, 0, 0xffffffffu, 0); + const __m128i B0 = _mm_mul_epu32(*A0, *mult); + const __m128i B1 = _mm_mul_epu32(*A1, *mult); + const __m128i B2 = _mm_mul_epu32(*A2, *mult); + const __m128i B3 = _mm_mul_epu32(*A3, *mult); + const __m128i D0 = _mm_srli_epi64(B0, WEBP_RESCALER_RFIX); + const __m128i D1 = _mm_srli_epi64(B1, WEBP_RESCALER_RFIX); +#if (WEBP_RESCALER_RFIX < 32) + const __m128i D2 = + _mm_and_si128(_mm_slli_epi64(B2, 32 - WEBP_RESCALER_RFIX), mask); + const __m128i D3 = + _mm_and_si128(_mm_slli_epi64(B3, 32 - WEBP_RESCALER_RFIX), mask); +#else + const __m128i D2 = _mm_and_si128(B2, mask); + const __m128i D3 = _mm_and_si128(B3, mask); +#endif + const __m128i E0 = _mm_or_si128(D0, D2); + const __m128i E1 = _mm_or_si128(D1, D3); + const __m128i F = _mm_packs_epi32(E0, E1); + const __m128i G = _mm_packus_epi16(F, F); + _mm_storel_epi64((__m128i*)dst, G); +} + static void RescalerExportRowExpand_SSE2(WebPRescaler* const wrk) { int x_out; uint8_t* const dst = wrk->dst; @@ -322,12 +352,12 @@ static void RescalerExportRowShrink_SSE2(WebPRescaler* const wrk) { const __m128i G1 = _mm_or_si128(D1, F3); _mm_storeu_si128((__m128i*)(irow + x_out + 0), G0); _mm_storeu_si128((__m128i*)(irow + x_out + 4), G1); - ProcessRow_SSE2(&E0, &E1, &E2, &E3, &mult_xy, dst + x_out); + ProcessRow_Floor_SSE2(&E0, &E1, &E2, &E3, &mult_xy, dst + x_out); } } for (; x_out < x_out_max; ++x_out) { const uint32_t frac = (int)MULT_FIX(frow[x_out], yscale); - const int v = (int)MULT_FIX(irow[x_out] - frac, wrk->fxy_scale); + const int v = (int)MULT_FIX_FLOOR(irow[x_out] - frac, wrk->fxy_scale); assert(v >= 0 && v <= 255); dst[x_out] = v; irow[x_out] = frac; // new fractional start @@ -352,6 +382,7 @@ static void RescalerExportRowShrink_SSE2(WebPRescaler* const wrk) { } } +#undef MULT_FIX_FLOOR #undef MULT_FIX #undef ROUNDER diff --git a/media/libwebp/dsp/yuv.h b/media/libwebp/dsp/yuv.h index b4c5d0b6c..947b89e13 100644 --- a/media/libwebp/dsp/yuv.h +++ b/media/libwebp/dsp/yuv.h @@ -207,4 +207,4 @@ static WEBP_INLINE int VP8RGBToV(int r, int g, int b, int rounding) { } // extern "C" #endif -#endif /* WEBP_DSP_YUV_H_ */ +#endif // WEBP_DSP_YUV_H_ diff --git a/media/libwebp/enc/cost_enc.h b/media/libwebp/enc/cost_enc.h index d731ee2fa..114823234 100644 --- a/media/libwebp/enc/cost_enc.h +++ b/media/libwebp/enc/cost_enc.h @@ -79,4 +79,4 @@ extern const uint16_t VP8FixedCostsI4[NUM_BMODES][NUM_BMODES][NUM_BMODES]; } // extern "C" #endif -#endif /* WEBP_ENC_COST_ENC_H_ */ +#endif // WEBP_ENC_COST_ENC_H_ diff --git a/media/libwebp/enc/histogram_enc.h b/media/libwebp/enc/histogram_enc.h index 4fbb73702..ef39b7c6d 100644 --- a/media/libwebp/enc/histogram_enc.h +++ b/media/libwebp/enc/histogram_enc.h @@ -44,6 +44,7 @@ typedef struct { double literal_cost_; // Cached values of dominant entropy costs: double red_cost_; // literal, red & blue. double blue_cost_; + uint8_t is_used_[5]; // 5 for literal, red, blue, alpha, distance } VP8LHistogram; // Collection of histograms with fixed capacity, allocated as one @@ -67,7 +68,9 @@ void VP8LHistogramCreate(VP8LHistogram* const p, int VP8LGetHistogramSize(int palette_code_bits); // Set the palette_code_bits and reset the stats. -void VP8LHistogramInit(VP8LHistogram* const p, int palette_code_bits); +// If init_arrays is true, the arrays are also filled with 0's. +void VP8LHistogramInit(VP8LHistogram* const p, int palette_code_bits, + int init_arrays); // Collect all the references into a histogram (without reset) void VP8LHistogramStoreRefs(const VP8LBackwardRefs* const refs, @@ -83,6 +86,9 @@ void VP8LFreeHistogramSet(VP8LHistogramSet* const histo); // using 'cache_bits'. Return NULL in case of memory error. VP8LHistogramSet* VP8LAllocateHistogramSet(int size, int cache_bits); +// Set the histograms in set to 0. +void VP8LHistogramSetClear(VP8LHistogramSet* const set); + // Allocate and initialize histogram object with specified 'cache_bits'. // Returns NULL in case of memory error. // Special case of VP8LAllocateHistogramSet, with size equals 1. @@ -113,7 +119,7 @@ double VP8LBitsEntropy(const uint32_t* const array, int n); // Estimate how many bits the combined entropy of literals and distance // approximately maps to. -double VP8LHistogramEstimateBits(const VP8LHistogram* const p); +double VP8LHistogramEstimateBits(VP8LHistogram* const p); #ifdef __cplusplus } diff --git a/media/libwebp/enc/vp8i_enc.h b/media/libwebp/enc/vp8i_enc.h index 8972d9f10..009ccf223 100644 --- a/media/libwebp/enc/vp8i_enc.h +++ b/media/libwebp/enc/vp8i_enc.h @@ -32,7 +32,7 @@ extern "C" { // version numbers #define ENC_MAJ_VERSION 1 #define ENC_MIN_VERSION 0 -#define ENC_REV_VERSION 0 +#define ENC_REV_VERSION 2 enum { MAX_LF_LEVELS = 64, // Maximum loop filter level MAX_VARIABLE_LEVEL = 67, // last (inclusive) level with variable cost @@ -278,7 +278,7 @@ int VP8IteratorIsDone(const VP8EncIterator* const it); // Import uncompressed samples from source. // If tmp_32 is not NULL, import boundary samples too. // tmp_32 is a 32-bytes scratch buffer that must be aligned in memory. -void VP8IteratorImport(VP8EncIterator* const it, uint8_t* tmp_32); +void VP8IteratorImport(VP8EncIterator* const it, uint8_t* const tmp_32); // export decimated samples void VP8IteratorExport(const VP8EncIterator* const it); // go to next macroblock. Returns false if not finished. @@ -515,4 +515,4 @@ void WebPCleanupTransparentAreaLossless(WebPPicture* const pic); } // extern "C" #endif -#endif /* WEBP_ENC_VP8I_ENC_H_ */ +#endif // WEBP_ENC_VP8I_ENC_H_ diff --git a/media/libwebp/enc/vp8li_enc.h b/media/libwebp/enc/vp8li_enc.h index 5dcba9ef0..1e259eda7 100644 --- a/media/libwebp/enc/vp8li_enc.h +++ b/media/libwebp/enc/vp8li_enc.h @@ -115,4 +115,4 @@ void VP8LColorSpaceTransform(int width, int height, int bits, int quality, } // extern "C" #endif -#endif /* WEBP_ENC_VP8LI_ENC_H_ */ +#endif // WEBP_ENC_VP8LI_ENC_H_ diff --git a/media/libwebp/utils/bit_reader_inl_utils.h b/media/libwebp/utils/bit_reader_inl_utils.h index 2bb9a1918..8d1249ef9 100644 --- a/media/libwebp/utils/bit_reader_inl_utils.h +++ b/media/libwebp/utils/bit_reader_inl_utils.h @@ -187,4 +187,4 @@ static WEBP_INLINE int VP8GetBitAlt(VP8BitReader* const br, int prob) { } // extern "C" #endif -#endif // WEBP_UTILS_BIT_READER_INL_UTILS_H_ +#endif // WEBP_UTILS_BIT_READER_INL_UTILS_H_ diff --git a/media/libwebp/utils/bit_reader_utils.h b/media/libwebp/utils/bit_reader_utils.h index 53e9db6ad..377a7821a 100644 --- a/media/libwebp/utils/bit_reader_utils.h +++ b/media/libwebp/utils/bit_reader_utils.h @@ -172,4 +172,4 @@ static WEBP_INLINE void VP8LFillBitWindow(VP8LBitReader* const br) { } // extern "C" #endif -#endif /* WEBP_UTILS_BIT_READER_UTILS_H_ */ +#endif // WEBP_UTILS_BIT_READER_UTILS_H_ diff --git a/media/libwebp/utils/bit_writer_utils.h b/media/libwebp/utils/bit_writer_utils.h index 9e9c2b729..b854fae73 100644 --- a/media/libwebp/utils/bit_writer_utils.h +++ b/media/libwebp/utils/bit_writer_utils.h @@ -151,4 +151,4 @@ static WEBP_INLINE void VP8LPutBits(VP8LBitWriter* const bw, } // extern "C" #endif -#endif /* WEBP_UTILS_BIT_WRITER_UTILS_H_ */ +#endif // WEBP_UTILS_BIT_WRITER_UTILS_H_ diff --git a/media/libwebp/utils/filters_utils.h b/media/libwebp/utils/filters_utils.h index 9466030e5..891771ddc 100644 --- a/media/libwebp/utils/filters_utils.h +++ b/media/libwebp/utils/filters_utils.h @@ -29,4 +29,4 @@ WEBP_FILTER_TYPE WebPEstimateBestFilter(const uint8_t* data, } // extern "C" #endif -#endif /* WEBP_UTILS_FILTERS_UTILS_H_ */ +#endif // WEBP_UTILS_FILTERS_UTILS_H_ diff --git a/media/libwebp/utils/quant_levels_dec_utils.c b/media/libwebp/utils/quant_levels_dec_utils.c index 5c498382d..a60de3444 100644 --- a/media/libwebp/utils/quant_levels_dec_utils.c +++ b/media/libwebp/utils/quant_levels_dec_utils.c @@ -261,9 +261,15 @@ static void CleanupParams(SmoothParams* const p) { int WebPDequantizeLevels(uint8_t* const data, int width, int height, int stride, int strength) { - const int radius = 4 * strength / 100; + int radius = 4 * strength / 100; + if (strength < 0 || strength > 100) return 0; if (data == NULL || width <= 0 || height <= 0) return 0; // bad params + + // limit the filter size to not exceed the image dimensions + if (2 * radius + 1 > width) radius = (width - 1) >> 1; + if (2 * radius + 1 > height) radius = (height - 1) >> 1; + if (radius > 0) { SmoothParams p; memset(&p, 0, sizeof(p)); diff --git a/media/libwebp/utils/quant_levels_dec_utils.h b/media/libwebp/utils/quant_levels_dec_utils.h index 4a59e06fe..c05376c67 100644 --- a/media/libwebp/utils/quant_levels_dec_utils.h +++ b/media/libwebp/utils/quant_levels_dec_utils.h @@ -32,4 +32,4 @@ int WebPDequantizeLevels(uint8_t* const data, int width, int height, int stride, } // extern "C" #endif -#endif /* WEBP_UTILS_QUANT_LEVELS_DEC_UTILS_H_ */ +#endif // WEBP_UTILS_QUANT_LEVELS_DEC_UTILS_H_ diff --git a/media/libwebp/utils/quant_levels_utils.h b/media/libwebp/utils/quant_levels_utils.h index 837bd2730..52a25a5f9 100644 --- a/media/libwebp/utils/quant_levels_utils.h +++ b/media/libwebp/utils/quant_levels_utils.h @@ -33,4 +33,4 @@ int QuantizeLevels(uint8_t* const data, int width, int height, int num_levels, } // extern "C" #endif -#endif /* WEBP_UTILS_QUANT_LEVELS_UTILS_H_ */ +#endif // WEBP_UTILS_QUANT_LEVELS_UTILS_H_ diff --git a/media/libwebp/utils/random_utils.h b/media/libwebp/utils/random_utils.h index 7b58de8c9..6688d2801 100644 --- a/media/libwebp/utils/random_utils.h +++ b/media/libwebp/utils/random_utils.h @@ -60,4 +60,4 @@ static WEBP_INLINE int VP8RandomBits(VP8Random* const rg, int num_bits) { } // extern "C" #endif -#endif /* WEBP_UTILS_RANDOM_UTILS_H_ */ +#endif // WEBP_UTILS_RANDOM_UTILS_H_ diff --git a/media/libwebp/utils/rescaler_utils.h b/media/libwebp/utils/rescaler_utils.h index 1c7b31d7f..b5d176ecf 100644 --- a/media/libwebp/utils/rescaler_utils.h +++ b/media/libwebp/utils/rescaler_utils.h @@ -98,4 +98,4 @@ int WebPRescalerHasPendingOutput(const WebPRescaler* const rescaler) { } // extern "C" #endif -#endif /* WEBP_UTILS_RESCALER_UTILS_H_ */ +#endif // WEBP_UTILS_RESCALER_UTILS_H_ diff --git a/media/libwebp/utils/thread_utils.h b/media/libwebp/utils/thread_utils.h index 0e88c2470..eb788f6e0 100644 --- a/media/libwebp/utils/thread_utils.h +++ b/media/libwebp/utils/thread_utils.h @@ -87,4 +87,4 @@ WEBP_EXTERN const WebPWorkerInterface* WebPGetWorkerInterface(void); } // extern "C" #endif -#endif /* WEBP_UTILS_THREAD_UTILS_H_ */ +#endif // WEBP_UTILS_THREAD_UTILS_H_ diff --git a/media/libwebp/utils/utils.h b/media/libwebp/utils/utils.h index 27dc7e090..d22151b0f 100644 --- a/media/libwebp/utils/utils.h +++ b/media/libwebp/utils/utils.h @@ -107,19 +107,6 @@ static WEBP_INLINE void PutLE32(uint8_t* const data, uint32_t val) { PutLE16(data + 2, (int)(val >> 16)); } -// Returns 31 ^ clz(n) = log2(n). This is the default C-implementation, either -// based on table or not. Can be used as fallback if clz() is not available. -#define WEBP_NEED_LOG_TABLE_8BIT -extern const uint8_t WebPLogTable8bit[256]; -static WEBP_INLINE int WebPLog2FloorC(uint32_t n) { - int log_value = 0; - while (n >= 256) { - log_value += 8; - n >>= 8; - } - return log_value + WebPLogTable8bit[n]; -} - // Returns (int)floor(log2(n)). n must be > 0. // use GNU builtins where available. #if defined(__GNUC__) && \ @@ -138,6 +125,19 @@ static WEBP_INLINE int BitsLog2Floor(uint32_t n) { return first_set_bit; } #else // default: use the C-version. +// Returns 31 ^ clz(n) = log2(n). This is the default C-implementation, either +// based on table or not. Can be used as fallback if clz() is not available. +#define WEBP_NEED_LOG_TABLE_8BIT +extern const uint8_t WebPLogTable8bit[256]; +static WEBP_INLINE int WebPLog2FloorC(uint32_t n) { + int log_value = 0; + while (n >= 256) { + log_value += 8; + n >>= 8; + } + return log_value + WebPLogTable8bit[n]; +} + static WEBP_INLINE int BitsLog2Floor(uint32_t n) { return WebPLog2FloorC(n); } #endif @@ -175,4 +175,4 @@ WEBP_EXTERN int WebPGetColorPalette(const struct WebPPicture* const pic, } // extern "C" #endif -#endif /* WEBP_UTILS_UTILS_H_ */ +#endif // WEBP_UTILS_UTILS_H_ diff --git a/media/libwebp/webp/decode.h b/media/libwebp/webp/decode.h index 2165e96c9..ae8bfe840 100644 --- a/media/libwebp/webp/decode.h +++ b/media/libwebp/webp/decode.h @@ -42,6 +42,12 @@ WEBP_EXTERN int WebPGetDecoderVersion(void); // This function will also validate the header, returning true on success, // false otherwise. '*width' and '*height' are only valid on successful return. // Pointers 'width' and 'height' can be passed NULL if deemed irrelevant. +// Note: The following chunk sequences (before the raw VP8/VP8L data) are +// considered valid by this function: +// RIFF + VP8(L) +// RIFF + VP8X + (optional chunks) + VP8(L) +// ALPH + VP8 <-- Not a valid WebP format: only allowed for internal purpose. +// VP8(L) <-- Not a valid WebP format: only allowed for internal purpose. WEBP_EXTERN int WebPGetInfo(const uint8_t* data, size_t data_size, int* width, int* height); @@ -425,6 +431,12 @@ WEBP_EXTERN VP8StatusCode WebPGetFeaturesInternal( // Returns VP8_STATUS_OK when the features are successfully retrieved. Returns // VP8_STATUS_NOT_ENOUGH_DATA when more data is needed to retrieve the // features from headers. Returns error in other cases. +// Note: The following chunk sequences (before the raw VP8/VP8L data) are +// considered valid by this function: +// RIFF + VP8(L) +// RIFF + VP8X + (optional chunks) + VP8(L) +// ALPH + VP8 <-- Not a valid WebP format: only allowed for internal purpose. +// VP8(L) <-- Not a valid WebP format: only allowed for internal purpose. static WEBP_INLINE VP8StatusCode WebPGetFeatures( const uint8_t* data, size_t data_size, WebPBitstreamFeatures* features) { @@ -491,4 +503,4 @@ WEBP_EXTERN VP8StatusCode WebPDecode(const uint8_t* data, size_t data_size, } // extern "C" #endif -#endif /* WEBP_WEBP_DECODE_H_ */ +#endif // WEBP_WEBP_DECODE_H_ diff --git a/media/libwebp/webp/demux.h b/media/libwebp/webp/demux.h index 555d64133..846eeb15a 100644 --- a/media/libwebp/webp/demux.h +++ b/media/libwebp/webp/demux.h @@ -360,4 +360,4 @@ WEBP_EXTERN void WebPAnimDecoderDelete(WebPAnimDecoder* dec); } // extern "C" #endif -#endif /* WEBP_WEBP_DEMUX_H_ */ +#endif // WEBP_WEBP_DEMUX_H_ diff --git a/media/libwebp/webp/encode.h b/media/libwebp/webp/encode.h index 7ec3543dc..549cf0773 100644 --- a/media/libwebp/webp/encode.h +++ b/media/libwebp/webp/encode.h @@ -542,4 +542,4 @@ WEBP_EXTERN int WebPEncode(const WebPConfig* config, WebPPicture* picture); } // extern "C" #endif -#endif /* WEBP_WEBP_ENCODE_H_ */ +#endif // WEBP_WEBP_ENCODE_H_ diff --git a/media/libwebp/webp/format_constants.h b/media/libwebp/webp/format_constants.h index 329fc8a3b..eca6981a4 100644 --- a/media/libwebp/webp/format_constants.h +++ b/media/libwebp/webp/format_constants.h @@ -84,4 +84,4 @@ typedef enum { // overflow a uint32_t. #define MAX_CHUNK_PAYLOAD (~0U - CHUNK_HEADER_SIZE - 1) -#endif /* WEBP_WEBP_FORMAT_CONSTANTS_H_ */ +#endif // WEBP_WEBP_FORMAT_CONSTANTS_H_ diff --git a/media/libwebp/webp/mux.h b/media/libwebp/webp/mux.h index 28bb4a41c..66096a92e 100644 --- a/media/libwebp/webp/mux.h +++ b/media/libwebp/webp/mux.h @@ -527,4 +527,4 @@ WEBP_EXTERN void WebPAnimEncoderDelete(WebPAnimEncoder* enc); } // extern "C" #endif -#endif /* WEBP_WEBP_MUX_H_ */ +#endif // WEBP_WEBP_MUX_H_ diff --git a/media/libwebp/webp/mux_types.h b/media/libwebp/webp/mux_types.h index b37e2c67a..ceea77dfc 100644 --- a/media/libwebp/webp/mux_types.h +++ b/media/libwebp/webp/mux_types.h @@ -95,4 +95,4 @@ static WEBP_INLINE int WebPDataCopy(const WebPData* src, WebPData* dst) { } // extern "C" #endif -#endif /* WEBP_WEBP_MUX_TYPES_H_ */ +#endif // WEBP_WEBP_MUX_TYPES_H_ diff --git a/media/libwebp/webp/types.h b/media/libwebp/webp/types.h index 989a763f0..0ce2622e4 100644 --- a/media/libwebp/webp/types.h +++ b/media/libwebp/webp/types.h @@ -49,4 +49,4 @@ typedef long long int int64_t; // Macro to check ABI compatibility (same major revision number) #define WEBP_ABI_IS_INCOMPATIBLE(a, b) (((a) >> 8) != ((b) >> 8)) -#endif /* WEBP_WEBP_TYPES_H_ */ +#endif // WEBP_WEBP_TYPES_H_ |