1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-16 14:00:40 +00:00

Update libwebp to 0.6.0

This commit is contained in:
volzhs
2017-02-17 23:49:40 +09:00
parent d5c2a6b76b
commit f7ef78c998
139 changed files with 10209 additions and 3709 deletions

View File

@@ -20,13 +20,12 @@
#include "../webp/config.h"
#endif
#ifdef WEBP_FORCE_ALIGNED
#include <string.h> // memcpy
#endif
#include <string.h> // for memcpy
#include "../dsp/dsp.h"
#include "./bit_reader.h"
#include "./endian_inl.h"
#include "./bit_reader_utils.h"
#include "./endian_inl_utils.h"
#include "./utils.h"
#ifdef __cplusplus
extern "C" {
@@ -62,10 +61,7 @@ void VP8LoadNewBytes(VP8BitReader* const br) {
if (br->buf_ < br->buf_max_) {
// convert memory type to register type (with some zero'ing!)
bit_t bits;
#if defined(WEBP_FORCE_ALIGNED)
lbit_t in_bits;
memcpy(&in_bits, br->buf_, sizeof(in_bits));
#elif defined(WEBP_USE_MIPS32)
#if defined(WEBP_USE_MIPS32)
// This is needed because of un-aligned read.
lbit_t in_bits;
lbit_t* p_buf_ = (lbit_t*)br->buf_;
@@ -80,7 +76,8 @@ void VP8LoadNewBytes(VP8BitReader* const br) {
: "memory", "at"
);
#else
const lbit_t in_bits = *(const lbit_t*)br->buf_;
lbit_t in_bits;
memcpy(&in_bits, br->buf_, sizeof(in_bits));
#endif
br->buf_ += BITS >> 3;
#if !defined(WORDS_BIGENDIAN)
@@ -119,37 +116,26 @@ static WEBP_INLINE int VP8GetBit(VP8BitReader* const br, int prob) {
const int pos = br->bits_;
const range_t split = (range * prob) >> 8;
const range_t value = (range_t)(br->value_ >> pos);
#if defined(__arm__) || defined(_M_ARM) // ARM-specific
const int bit = ((int)(split - value) >> 31) & 1;
if (value > split) {
range -= split + 1;
const int bit = (value > split);
if (bit) {
range -= split;
br->value_ -= (bit_t)(split + 1) << pos;
} else {
range = split;
range = split + 1;
}
#else // faster version on x86
int bit; // Don't use 'const int bit = (value > split);", it's slower.
if (value > split) {
range -= split + 1;
br->value_ -= (bit_t)(split + 1) << pos;
bit = 1;
} else {
range = split;
bit = 0;
}
#endif
if (range <= (range_t)0x7e) {
const int shift = kVP8Log2Range[range];
range = kVP8NewRange[range];
{
const int shift = 7 ^ BitsLog2Floor(range);
range <<= shift;
br->bits_ -= shift;
}
br->range_ = range;
br->range_ = range - 1;
return bit;
}
}
// simplified version of VP8GetBit() for prob=0x80 (note shift is always 1 here)
static WEBP_INLINE int VP8GetSigned(VP8BitReader* const br, int v) {
static WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW WEBP_INLINE
int VP8GetSigned(VP8BitReader* const br, int v) {
if (br->bits_ < 0) {
VP8LoadNewBytes(br);
}
@@ -166,6 +152,37 @@ static WEBP_INLINE int VP8GetSigned(VP8BitReader* const br, int v) {
}
}
static WEBP_INLINE int VP8GetBitAlt(VP8BitReader* const br, int prob) {
// Don't move this declaration! It makes a big speed difference to store
// 'range' *before* calling VP8LoadNewBytes(), even if this function doesn't
// alter br->range_ value.
range_t range = br->range_;
if (br->bits_ < 0) {
VP8LoadNewBytes(br);
}
{
const int pos = br->bits_;
const range_t split = (range * prob) >> 8;
const range_t value = (range_t)(br->value_ >> pos);
int bit; // Don't use 'const int bit = (value > split);", it's slower.
if (value > split) {
range -= split + 1;
br->value_ -= (bit_t)(split + 1) << pos;
bit = 1;
} else {
range = split;
bit = 0;
}
if (range <= (range_t)0x7e) {
const int shift = kVP8Log2Range[range];
range = kVP8NewRange[range];
br->bits_ -= shift;
}
br->range_ = range;
return bit;
}
}
#ifdef __cplusplus
} // extern "C"
#endif

View File

@@ -15,7 +15,7 @@
#include "../webp/config.h"
#endif
#include "./bit_reader_inl.h"
#include "./bit_reader_inl_utils.h"
#include "../utils/utils.h"
//------------------------------------------------------------------------------

View File

@@ -16,8 +16,8 @@
#include <string.h> // for memcpy()
#include <stdlib.h>
#include "./bit_writer.h"
#include "./endian_inl.h"
#include "./bit_writer_utils.h"
#include "./endian_inl_utils.h"
#include "./utils.h"
//------------------------------------------------------------------------------
@@ -143,13 +143,13 @@ int VP8PutBitUniform(VP8BitWriter* const bw, int bit) {
void VP8PutBits(VP8BitWriter* const bw, uint32_t value, int nb_bits) {
uint32_t mask;
assert(nb_bits > 0 && nb_bits < 32);
for (mask = 1u << (nb_bits - 1); mask; mask >>= 1)
for (mask = 1u << (nb_bits - 1); mask; mask >>= 1) {
VP8PutBitUniform(bw, value & mask);
}
}
void VP8PutSignedBits(VP8BitWriter* const bw, int value, int nb_bits) {
if (!VP8PutBitUniform(bw, value != 0))
return;
if (!VP8PutBitUniform(bw, value != 0)) return;
if (value < 0) {
VP8PutBits(bw, ((-value) << 1) | 1, nb_bits + 1);
} else {

View File

@@ -54,7 +54,8 @@ int VP8BitWriterAppend(VP8BitWriter* const bw,
// return approximate write position (in bits)
static WEBP_INLINE uint64_t VP8BitWriterPos(const VP8BitWriter* const bw) {
return (uint64_t)(bw->pos_ + bw->run_) * 8 + 8 + bw->nb_bits_;
const uint64_t nb_bits = 8 + bw->nb_bits_; // bw->nb_bits_ is <= 0, note
return (bw->pos_ + bw->run_) * 8 + nb_bits;
}
// Returns a pointer to the internal buffer.

View File

@@ -14,7 +14,7 @@
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "./color_cache.h"
#include "./color_cache_utils.h"
#include "./utils.h"
//------------------------------------------------------------------------------

View File

@@ -28,7 +28,11 @@ typedef struct {
int hash_bits_;
} VP8LColorCache;
static const uint32_t kHashMul = 0x1e35a7bd;
static const uint64_t kHashMul = 0x1e35a7bdull;
static WEBP_INLINE int HashPix(uint32_t argb, int shift) {
return (int)(((argb * kHashMul) & 0xffffffffu) >> shift);
}
static WEBP_INLINE uint32_t VP8LColorCacheLookup(
const VP8LColorCache* const cc, uint32_t key) {
@@ -44,19 +48,20 @@ static WEBP_INLINE void VP8LColorCacheSet(const VP8LColorCache* const cc,
static WEBP_INLINE void VP8LColorCacheInsert(const VP8LColorCache* const cc,
uint32_t argb) {
const uint32_t key = (kHashMul * argb) >> cc->hash_shift_;
const int key = HashPix(argb, cc->hash_shift_);
cc->colors_[key] = argb;
}
static WEBP_INLINE int VP8LColorCacheGetIndex(const VP8LColorCache* const cc,
uint32_t argb) {
return (kHashMul * argb) >> cc->hash_shift_;
return HashPix(argb, cc->hash_shift_);
}
// Return the key if cc contains argb, and -1 otherwise.
static WEBP_INLINE int VP8LColorCacheContains(const VP8LColorCache* const cc,
uint32_t argb) {
const uint32_t key = (kHashMul * argb) >> cc->hash_shift_;
return (cc->colors_[key] == argb);
const int key = HashPix(argb, cc->hash_shift_);
return (cc->colors_[key] == argb) ? key : -1;
}
//------------------------------------------------------------------------------

View File

@@ -11,7 +11,7 @@
//
// Author: Urvang (urvang@google.com)
#include "./filters.h"
#include "./filters_utils.h"
#include <stdlib.h>
#include <string.h>

View File

@@ -14,7 +14,7 @@
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "./huffman_encode.h"
#include "./huffman_encode_utils.h"
#include "./utils.h"
#include "../webp/format_constants.h"

View File

@@ -14,7 +14,7 @@
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "./huffman.h"
#include "./huffman_utils.h"
#include "./utils.h"
#include "../webp/format_constants.h"
@@ -45,7 +45,7 @@ static WEBP_INLINE uint32_t GetNextKey(uint32_t key, int len) {
while (key & step) {
step >>= 1;
}
return (key & (step - 1)) + step;
return step ? (key & (step - 1)) + step : key;
}
// Stores code in table[0], table[step], table[2*step], ..., table[end].
@@ -75,11 +75,13 @@ static WEBP_INLINE int NextTableBitSize(const int* const count,
return len - root_bits;
}
int VP8LBuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
const int code_lengths[], int code_lengths_size) {
// sorted[code_lengths_size] is a pre-allocated array for sorting symbols
// by code length.
static int BuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
const int code_lengths[], int code_lengths_size,
uint16_t sorted[]) {
HuffmanCode* table = root_table; // next available space in table
int total_size = 1 << root_bits; // total size root table + 2nd level table
int* sorted = NULL; // symbols sorted by code length
int len; // current code length
int symbol; // symbol index in original or sorted table
// number of codes of each length:
@@ -114,11 +116,6 @@ int VP8LBuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
offset[len + 1] = offset[len] + count[len];
}
sorted = (int*)WebPSafeMalloc(code_lengths_size, sizeof(*sorted));
if (sorted == NULL) {
return 0;
}
// Sort symbols by length, by symbol order within each length.
for (symbol = 0; symbol < code_lengths_size; ++symbol) {
const int symbol_code_length = code_lengths[symbol];
@@ -133,7 +130,6 @@ int VP8LBuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
code.bits = 0;
code.value = (uint16_t)sorted[0];
ReplicateValue(table, 1, total_size, code);
WebPSafeFree(sorted);
return total_size;
}
@@ -153,7 +149,6 @@ int VP8LBuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
num_nodes += num_open;
num_open -= count[len];
if (num_open < 0) {
WebPSafeFree(sorted);
return 0;
}
for (; count[len] > 0; --count[len]) {
@@ -172,7 +167,6 @@ int VP8LBuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
num_nodes += num_open;
num_open -= count[len];
if (num_open < 0) {
WebPSafeFree(sorted);
return 0;
}
for (; count[len] > 0; --count[len]) {
@@ -195,11 +189,35 @@ int VP8LBuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
// Check if tree is full.
if (num_nodes != 2 * offset[MAX_ALLOWED_CODE_LENGTH] - 1) {
WebPSafeFree(sorted);
return 0;
}
}
WebPSafeFree(sorted);
return total_size;
}
// Maximum code_lengths_size is 2328 (reached for 11-bit color_cache_bits).
// More commonly, the value is around ~280.
#define MAX_CODE_LENGTHS_SIZE \
((1 << MAX_CACHE_BITS) + NUM_LITERAL_CODES + NUM_LENGTH_CODES)
// Cut-off value for switching between heap and stack allocation.
#define SORTED_SIZE_CUTOFF 512
int VP8LBuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
const int code_lengths[], int code_lengths_size) {
int total_size;
assert(code_lengths_size <= MAX_CODE_LENGTHS_SIZE);
if (code_lengths_size <= SORTED_SIZE_CUTOFF) {
// use local stack-allocated array.
uint16_t sorted[SORTED_SIZE_CUTOFF];
total_size = BuildHuffmanTable(root_table, root_bits,
code_lengths, code_lengths_size, sorted);
} else { // rare case. Use heap allocation.
uint16_t* const sorted =
(uint16_t*)WebPSafeMalloc(code_lengths_size, sizeof(*sorted));
if (sorted == NULL) return 0;
total_size = BuildHuffmanTable(root_table, root_bits,
code_lengths, code_lengths_size, sorted);
WebPSafeFree(sorted);
}
return total_size;
}

View File

@@ -14,7 +14,7 @@
//
// Author: Skal (pascal.massimino@gmail.com)
#include "./quant_levels_dec.h"
#include "./quant_levels_dec_utils.h"
#include <string.h> // for memset

View File

@@ -14,7 +14,7 @@
#include <assert.h>
#include "./quant_levels.h"
#include "./quant_levels_utils.h"
#define NUM_SYMBOLS 256

View File

@@ -12,7 +12,7 @@
// Author: Skal (pascal.massimino@gmail.com)
#include <string.h>
#include "./random.h"
#include "./random_utils.h"
//------------------------------------------------------------------------------

View File

@@ -15,7 +15,7 @@
#include <stdlib.h>
#include <string.h>
#include "../dsp/dsp.h"
#include "./rescaler.h"
#include "./rescaler_utils.h"
//------------------------------------------------------------------------------

View File

@@ -13,7 +13,7 @@
#include <assert.h>
#include <string.h> // for memset()
#include "./thread.h"
#include "./thread_utils.h"
#include "./utils.h"
#ifdef WEBP_USE_THREAD
@@ -183,8 +183,7 @@ static int pthread_cond_wait(pthread_cond_t* const condition,
#else
// note that there is a consumer available so the signal isn't dropped in
// pthread_cond_signal
if (!ReleaseSemaphore(condition->waiting_sem_, 1, NULL))
return 1;
if (!ReleaseSemaphore(condition->waiting_sem_, 1, NULL)) return 1;
// now unlock the mutex so pthread_cond_signal may be issued
pthread_mutex_unlock(mutex);
ok = (WaitForSingleObject(condition->signal_event_, INFINITE) ==
@@ -226,8 +225,7 @@ static THREADFN ThreadLoop(void* ptr) {
}
// main thread state control
static void ChangeState(WebPWorker* const worker,
WebPWorkerStatus new_status) {
static void ChangeState(WebPWorker* const worker, WebPWorkerStatus new_status) {
// No-op when attempting to change state on a thread that didn't come up.
// Checking status_ without acquiring the lock first would result in a data
// race.

View File

@@ -25,7 +25,7 @@
// http://valgrind.org/docs/manual/ms-manual.html
// Here is an example command line:
/* valgrind --tool=massif --massif-out-file=massif.out \
--stacks=yes --alloc-fn=WebPSafeAlloc --alloc-fn=WebPSafeCalloc
--stacks=yes --alloc-fn=WebPSafeMalloc --alloc-fn=WebPSafeCalloc
ms_print massif.out
*/
// In addition:
@@ -243,8 +243,7 @@ void WebPCopyPixels(const WebPPicture* const src, WebPPicture* const dst) {
//------------------------------------------------------------------------------
#define MAX_COLOR_COUNT MAX_PALETTE_SIZE
#define COLOR_HASH_SIZE (MAX_COLOR_COUNT * 4)
#define COLOR_HASH_SIZE (MAX_PALETTE_SIZE * 4)
#define COLOR_HASH_RIGHT_SHIFT 22 // 32 - log2(COLOR_HASH_SIZE).
int WebPGetColorPalette(const WebPPicture* const pic, uint32_t* const palette) {
@@ -253,7 +252,7 @@ int WebPGetColorPalette(const WebPPicture* const pic, uint32_t* const palette) {
int num_colors = 0;
uint8_t in_use[COLOR_HASH_SIZE] = { 0 };
uint32_t colors[COLOR_HASH_SIZE];
static const uint32_t kHashMul = 0x1e35a7bdU;
static const uint64_t kHashMul = 0x1e35a7bdull;
const uint32_t* argb = pic->argb;
const int width = pic->width;
const int height = pic->height;
@@ -268,14 +267,14 @@ int WebPGetColorPalette(const WebPPicture* const pic, uint32_t* const palette) {
continue;
}
last_pix = argb[x];
key = (kHashMul * last_pix) >> COLOR_HASH_RIGHT_SHIFT;
key = ((last_pix * kHashMul) & 0xffffffffu) >> COLOR_HASH_RIGHT_SHIFT;
while (1) {
if (!in_use[key]) {
colors[key] = last_pix;
in_use[key] = 1;
++num_colors;
if (num_colors > MAX_COLOR_COUNT) {
return MAX_COLOR_COUNT + 1; // Exact count not needed.
if (num_colors > MAX_PALETTE_SIZE) {
return MAX_PALETTE_SIZE + 1; // Exact count not needed.
}
break;
} else if (colors[key] == last_pix) {
@@ -302,8 +301,30 @@ int WebPGetColorPalette(const WebPPicture* const pic, uint32_t* const palette) {
return num_colors;
}
#undef MAX_COLOR_COUNT
#undef COLOR_HASH_SIZE
#undef COLOR_HASH_RIGHT_SHIFT
//------------------------------------------------------------------------------
#if defined(WEBP_NEED_LOG_TABLE_8BIT)
const uint8_t WebPLogTable8bit[256] = { // 31 ^ clz(i)
0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
};
#endif
//------------------------------------------------------------------------------

View File

@@ -62,7 +62,6 @@ WEBP_EXTERN(void) WebPSafeFree(void* const ptr);
#define WEBP_ALIGN_CST 31
#define WEBP_ALIGN(PTR) (((uintptr_t)(PTR) + WEBP_ALIGN_CST) & ~WEBP_ALIGN_CST)
#if defined(WEBP_FORCE_ALIGNED)
#include <string.h>
// memcpy() is the safe way of moving potentially unaligned 32b memory.
static WEBP_INLINE uint32_t WebPMemToUint32(const uint8_t* const ptr) {
@@ -73,16 +72,6 @@ static WEBP_INLINE uint32_t WebPMemToUint32(const uint8_t* const ptr) {
static WEBP_INLINE void WebPUint32ToMem(uint8_t* const ptr, uint32_t val) {
memcpy(ptr, &val, sizeof(val));
}
#else
static WEBP_UBSAN_IGNORE_UNDEF WEBP_INLINE
uint32_t WebPMemToUint32(const uint8_t* const ptr) {
return *(const uint32_t*)ptr;
}
static WEBP_UBSAN_IGNORE_UNDEF WEBP_INLINE
void WebPUint32ToMem(uint8_t* const ptr, uint32_t val) {
*(uint32_t*)ptr = val;
}
#endif
//------------------------------------------------------------------------------
// Reading/writing data.
@@ -118,6 +107,19 @@ 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 = 0;
while (n >= 256) {
log += 8;
n >>= 8;
}
return log + WebPLogTable8bit[n];
}
// Returns (int)floor(log2(n)). n must be > 0.
// use GNU builtins where available.
#if defined(__GNUC__) && \
@@ -135,22 +137,8 @@ static WEBP_INLINE int BitsLog2Floor(uint32_t n) {
_BitScanReverse(&first_set_bit, n);
return first_set_bit;
}
#else
static WEBP_INLINE int BitsLog2Floor(uint32_t n) {
int log = 0;
uint32_t value = n;
int i;
for (i = 4; i >= 0; --i) {
const int shift = (1 << i);
const uint32_t x = value >> shift;
if (x != 0) {
value = x;
log += shift;
}
}
return log;
}
#else // default: use the C-version.
static WEBP_INLINE int BitsLog2Floor(uint32_t n) { return WebPLog2FloorC(n); }
#endif
//------------------------------------------------------------------------------
@@ -172,12 +160,12 @@ WEBP_EXTERN(void) WebPCopyPixels(const struct WebPPicture* const src,
// Unique colors.
// Returns count of unique colors in 'pic', assuming pic->use_argb is true.
// If the unique color count is more than MAX_COLOR_COUNT, returns
// MAX_COLOR_COUNT+1.
// If the unique color count is more than MAX_PALETTE_SIZE, returns
// MAX_PALETTE_SIZE+1.
// If 'palette' is not NULL and number of unique colors is less than or equal to
// MAX_COLOR_COUNT, also outputs the actual unique colors into 'palette'.
// MAX_PALETTE_SIZE, also outputs the actual unique colors into 'palette'.
// Note: 'palette' is assumed to be an array already allocated with at least
// MAX_COLOR_COUNT elements.
// MAX_PALETTE_SIZE elements.
WEBP_EXTERN(int) WebPGetColorPalette(const struct WebPPicture* const pic,
uint32_t* const palette);