You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-07 12:30:27 +00:00
Update libwebp to 1.0.3
This commit is contained in:
@@ -104,7 +104,8 @@ void VP8LoadNewBytes(VP8BitReader* const br) {
|
||||
}
|
||||
|
||||
// Read a bit with proba 'prob'. Speed-critical function!
|
||||
static WEBP_INLINE int VP8GetBit(VP8BitReader* const br, int prob) {
|
||||
static WEBP_INLINE int VP8GetBit(VP8BitReader* const br,
|
||||
int prob, const char label[]) {
|
||||
// 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.
|
||||
@@ -129,13 +130,14 @@ static WEBP_INLINE int VP8GetBit(VP8BitReader* const br, int prob) {
|
||||
br->bits_ -= shift;
|
||||
}
|
||||
br->range_ = range - 1;
|
||||
BT_TRACK(br);
|
||||
return bit;
|
||||
}
|
||||
}
|
||||
|
||||
// simplified version of VP8GetBit() for prob=0x80 (note shift is always 1 here)
|
||||
static WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW WEBP_INLINE
|
||||
int VP8GetSigned(VP8BitReader* const br, int v) {
|
||||
int VP8GetSigned(VP8BitReader* const br, int v, const char label[]) {
|
||||
if (br->bits_ < 0) {
|
||||
VP8LoadNewBytes(br);
|
||||
}
|
||||
@@ -148,11 +150,13 @@ int VP8GetSigned(VP8BitReader* const br, int v) {
|
||||
br->range_ += mask;
|
||||
br->range_ |= 1;
|
||||
br->value_ -= (bit_t)((split + 1) & mask) << pos;
|
||||
BT_TRACK(br);
|
||||
return (v ^ mask) - mask;
|
||||
}
|
||||
}
|
||||
|
||||
static WEBP_INLINE int VP8GetBitAlt(VP8BitReader* const br, int prob) {
|
||||
static WEBP_INLINE int VP8GetBitAlt(VP8BitReader* const br,
|
||||
int prob, const char label[]) {
|
||||
// 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.
|
||||
@@ -179,6 +183,7 @@ static WEBP_INLINE int VP8GetBitAlt(VP8BitReader* const br, int prob) {
|
||||
br->bits_ -= shift;
|
||||
}
|
||||
br->range_ = range;
|
||||
BT_TRACK(br);
|
||||
return bit;
|
||||
}
|
||||
}
|
||||
|
||||
86
thirdparty/libwebp/src/utils/bit_reader_utils.c
vendored
86
thirdparty/libwebp/src/utils/bit_reader_utils.c
vendored
@@ -109,17 +109,18 @@ void VP8LoadFinalBytes(VP8BitReader* const br) {
|
||||
//------------------------------------------------------------------------------
|
||||
// Higher-level calls
|
||||
|
||||
uint32_t VP8GetValue(VP8BitReader* const br, int bits) {
|
||||
uint32_t VP8GetValue(VP8BitReader* const br, int bits, const char label[]) {
|
||||
uint32_t v = 0;
|
||||
while (bits-- > 0) {
|
||||
v |= VP8GetBit(br, 0x80) << bits;
|
||||
v |= VP8GetBit(br, 0x80, label) << bits;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
int32_t VP8GetSignedValue(VP8BitReader* const br, int bits) {
|
||||
const int value = VP8GetValue(br, bits);
|
||||
return VP8Get(br) ? -value : value;
|
||||
int32_t VP8GetSignedValue(VP8BitReader* const br, int bits,
|
||||
const char label[]) {
|
||||
const int value = VP8GetValue(br, bits, label);
|
||||
return VP8Get(br, label) ? -value : value;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -227,3 +228,78 @@ uint32_t VP8LReadBits(VP8LBitReader* const br, int n_bits) {
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Bit-tracing tool
|
||||
|
||||
#if (BITTRACE > 0)
|
||||
|
||||
#include <stdlib.h> // for atexit()
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define MAX_NUM_LABELS 32
|
||||
static struct {
|
||||
const char* label;
|
||||
int size;
|
||||
int count;
|
||||
} kLabels[MAX_NUM_LABELS];
|
||||
|
||||
static int last_label = 0;
|
||||
static int last_pos = 0;
|
||||
static const uint8_t* buf_start = NULL;
|
||||
static int init_done = 0;
|
||||
|
||||
static void PrintBitTraces(void) {
|
||||
int i;
|
||||
int scale = 1;
|
||||
int total = 0;
|
||||
const char* units = "bits";
|
||||
#if (BITTRACE == 2)
|
||||
scale = 8;
|
||||
units = "bytes";
|
||||
#endif
|
||||
for (i = 0; i < last_label; ++i) total += kLabels[i].size;
|
||||
if (total < 1) total = 1; // avoid rounding errors
|
||||
printf("=== Bit traces ===\n");
|
||||
for (i = 0; i < last_label; ++i) {
|
||||
const int skip = 16 - (int)strlen(kLabels[i].label);
|
||||
const int value = (kLabels[i].size + scale - 1) / scale;
|
||||
assert(skip > 0);
|
||||
printf("%s \%*s: %6d %s \t[%5.2f%%] [count: %7d]\n",
|
||||
kLabels[i].label, skip, "", value, units,
|
||||
100.f * kLabels[i].size / total,
|
||||
kLabels[i].count);
|
||||
}
|
||||
total = (total + scale - 1) / scale;
|
||||
printf("Total: %d %s\n", total, units);
|
||||
}
|
||||
|
||||
void BitTrace(const struct VP8BitReader* const br, const char label[]) {
|
||||
int i, pos;
|
||||
if (!init_done) {
|
||||
memset(kLabels, 0, sizeof(kLabels));
|
||||
atexit(PrintBitTraces);
|
||||
buf_start = br->buf_;
|
||||
init_done = 1;
|
||||
}
|
||||
pos = (int)(br->buf_ - buf_start) * 8 - br->bits_;
|
||||
// if there's a too large jump, we've changed partition -> reset counter
|
||||
if (abs(pos - last_pos) > 32) {
|
||||
buf_start = br->buf_;
|
||||
pos = 0;
|
||||
last_pos = 0;
|
||||
}
|
||||
if (br->range_ >= 0x7f) pos += kVP8Log2Range[br->range_ - 0x7f];
|
||||
for (i = 0; i < last_label; ++i) {
|
||||
if (!strcmp(label, kLabels[i].label)) break;
|
||||
}
|
||||
if (i == MAX_NUM_LABELS) abort(); // overflow!
|
||||
kLabels[i].label = label;
|
||||
kLabels[i].size += pos - last_pos;
|
||||
kLabels[i].count += 1;
|
||||
if (i == last_label) ++last_label;
|
||||
last_pos = pos;
|
||||
}
|
||||
|
||||
#endif // BITTRACE > 0
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
33
thirdparty/libwebp/src/utils/bit_reader_utils.h
vendored
33
thirdparty/libwebp/src/utils/bit_reader_utils.h
vendored
@@ -21,6 +21,27 @@
|
||||
#endif
|
||||
#include "src/webp/types.h"
|
||||
|
||||
// Warning! This macro triggers quite some MACRO wizardry around func signature!
|
||||
#if !defined(BITTRACE)
|
||||
#define BITTRACE 0 // 0 = off, 1 = print bits, 2 = print bytes
|
||||
#endif
|
||||
|
||||
#if (BITTRACE > 0)
|
||||
struct VP8BitReader;
|
||||
extern void BitTrace(const struct VP8BitReader* const br, const char label[]);
|
||||
#define BT_TRACK(br) BitTrace(br, label)
|
||||
#define VP8Get(BR, L) VP8GetValue(BR, 1, L)
|
||||
#else
|
||||
#define BT_TRACK(br)
|
||||
// We'll REMOVE the 'const char label[]' from all signatures and calls (!!):
|
||||
#define VP8GetValue(BR, N, L) VP8GetValue(BR, N)
|
||||
#define VP8Get(BR, L) VP8GetValue(BR, 1, L)
|
||||
#define VP8GetSignedValue(BR, N, L) VP8GetSignedValue(BR, N)
|
||||
#define VP8GetBit(BR, P, L) VP8GetBit(BR, P)
|
||||
#define VP8GetBitAlt(BR, P, L) VP8GetBitAlt(BR, P)
|
||||
#define VP8GetSigned(BR, V, L) VP8GetSigned(BR, V)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -102,17 +123,15 @@ void VP8BitReaderSetBuffer(VP8BitReader* const br,
|
||||
void VP8RemapBitReader(VP8BitReader* const br, ptrdiff_t offset);
|
||||
|
||||
// return the next value made of 'num_bits' bits
|
||||
uint32_t VP8GetValue(VP8BitReader* const br, int num_bits);
|
||||
static WEBP_INLINE uint32_t VP8Get(VP8BitReader* const br) {
|
||||
return VP8GetValue(br, 1);
|
||||
}
|
||||
uint32_t VP8GetValue(VP8BitReader* const br, int num_bits, const char label[]);
|
||||
|
||||
// return the next value with sign-extension.
|
||||
int32_t VP8GetSignedValue(VP8BitReader* const br, int num_bits);
|
||||
int32_t VP8GetSignedValue(VP8BitReader* const br, int num_bits,
|
||||
const char label[]);
|
||||
|
||||
// bit_reader_inl.h will implement the following methods:
|
||||
// static WEBP_INLINE int VP8GetBit(VP8BitReader* const br, int prob)
|
||||
// static WEBP_INLINE int VP8GetSigned(VP8BitReader* const br, int v)
|
||||
// static WEBP_INLINE int VP8GetBit(VP8BitReader* const br, int prob, ...)
|
||||
// static WEBP_INLINE int VP8GetSigned(VP8BitReader* const br, int v, ...)
|
||||
// and should be included by the .c files that actually need them.
|
||||
// This is to avoid recompiling the whole library whenever this file is touched,
|
||||
// and also allowing platform-specific ad-hoc hacks.
|
||||
|
||||
@@ -70,7 +70,7 @@ static void Flush(VP8BitWriter* const bw) {
|
||||
const int value = (bits & 0x100) ? 0x00 : 0xff;
|
||||
for (; bw->run_ > 0; --bw->run_) bw->buf_[pos++] = value;
|
||||
}
|
||||
bw->buf_[pos++] = bits;
|
||||
bw->buf_[pos++] = bits & 0xff;
|
||||
bw->pos_ = pos;
|
||||
} else {
|
||||
bw->run_++; // delay writing of bytes 0xff, pending eventual carry.
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "src/dsp/dsp.h"
|
||||
#include "src/webp/types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -30,10 +31,11 @@ typedef struct {
|
||||
int hash_bits_;
|
||||
} VP8LColorCache;
|
||||
|
||||
static const uint64_t kHashMul = 0x1e35a7bdull;
|
||||
static const uint32_t kHashMul = 0x1e35a7bdu;
|
||||
|
||||
static WEBP_INLINE int VP8LHashPix(uint32_t argb, int shift) {
|
||||
return (int)(((argb * kHashMul) & 0xffffffffu) >> shift);
|
||||
static WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW WEBP_INLINE
|
||||
int VP8LHashPix(uint32_t argb, int shift) {
|
||||
return (int)((argb * kHashMul) >> shift);
|
||||
}
|
||||
|
||||
static WEBP_INLINE uint32_t VP8LColorCacheLookup(
|
||||
|
||||
26
thirdparty/libwebp/src/utils/huffman_utils.c
vendored
26
thirdparty/libwebp/src/utils/huffman_utils.c
vendored
@@ -91,7 +91,8 @@ static int BuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
|
||||
|
||||
assert(code_lengths_size != 0);
|
||||
assert(code_lengths != NULL);
|
||||
assert(root_table != NULL);
|
||||
assert((root_table != NULL && sorted != NULL) ||
|
||||
(root_table == NULL && sorted == NULL));
|
||||
assert(root_bits > 0);
|
||||
|
||||
// Build histogram of code lengths.
|
||||
@@ -120,16 +121,22 @@ static int BuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
|
||||
for (symbol = 0; symbol < code_lengths_size; ++symbol) {
|
||||
const int symbol_code_length = code_lengths[symbol];
|
||||
if (code_lengths[symbol] > 0) {
|
||||
sorted[offset[symbol_code_length]++] = symbol;
|
||||
if (sorted != NULL) {
|
||||
sorted[offset[symbol_code_length]++] = symbol;
|
||||
} else {
|
||||
offset[symbol_code_length]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Special case code with only one value.
|
||||
if (offset[MAX_ALLOWED_CODE_LENGTH] == 1) {
|
||||
HuffmanCode code;
|
||||
code.bits = 0;
|
||||
code.value = (uint16_t)sorted[0];
|
||||
ReplicateValue(table, 1, total_size, code);
|
||||
if (sorted != NULL) {
|
||||
HuffmanCode code;
|
||||
code.bits = 0;
|
||||
code.value = (uint16_t)sorted[0];
|
||||
ReplicateValue(table, 1, total_size, code);
|
||||
}
|
||||
return total_size;
|
||||
}
|
||||
|
||||
@@ -151,6 +158,7 @@ static int BuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
|
||||
if (num_open < 0) {
|
||||
return 0;
|
||||
}
|
||||
if (root_table == NULL) continue;
|
||||
for (; count[len] > 0; --count[len]) {
|
||||
HuffmanCode code;
|
||||
code.bits = (uint8_t)len;
|
||||
@@ -169,6 +177,7 @@ static int BuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
|
||||
if (num_open < 0) {
|
||||
return 0;
|
||||
}
|
||||
if (root_table == NULL) continue;
|
||||
for (; count[len] > 0; --count[len]) {
|
||||
HuffmanCode code;
|
||||
if ((key & mask) != low) {
|
||||
@@ -206,7 +215,10 @@ 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) {
|
||||
if (root_table == NULL) {
|
||||
total_size = BuildHuffmanTable(NULL, root_bits,
|
||||
code_lengths, code_lengths_size, NULL);
|
||||
} else 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,
|
||||
|
||||
2
thirdparty/libwebp/src/utils/huffman_utils.h
vendored
2
thirdparty/libwebp/src/utils/huffman_utils.h
vendored
@@ -78,6 +78,8 @@ void VP8LHtreeGroupsFree(HTreeGroup* const htree_groups);
|
||||
// the huffman table.
|
||||
// Returns built table size or 0 in case of error (invalid tree or
|
||||
// memory error).
|
||||
// If root_table is NULL, it returns 0 if a lookup cannot be built, something
|
||||
// > 0 otherwise (but not the table size).
|
||||
int VP8LBuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
|
||||
const int code_lengths[], int code_lengths_size);
|
||||
|
||||
|
||||
@@ -84,14 +84,14 @@ int WebPRescalerGetScaledDimensions(int src_width, int src_height,
|
||||
int height = *scaled_height;
|
||||
|
||||
// if width is unspecified, scale original proportionally to height ratio.
|
||||
if (width == 0) {
|
||||
if (width == 0 && src_height > 0) {
|
||||
width =
|
||||
(int)(((uint64_t)src_width * height + src_height / 2) / src_height);
|
||||
(int)(((uint64_t)src_width * height + src_height - 1) / src_height);
|
||||
}
|
||||
// if height is unspecified, scale original proportionally to width ratio.
|
||||
if (height == 0) {
|
||||
if (height == 0 && src_width > 0) {
|
||||
height =
|
||||
(int)(((uint64_t)src_height * width + src_width / 2) / src_width);
|
||||
(int)(((uint64_t)src_height * width + src_width - 1) / src_width);
|
||||
}
|
||||
// Check if the overall dimensions still make sense.
|
||||
if (width <= 0 || height <= 0) {
|
||||
|
||||
12
thirdparty/libwebp/src/utils/thread_utils.c
vendored
12
thirdparty/libwebp/src/utils/thread_utils.c
vendored
@@ -217,8 +217,12 @@ static THREADFN ThreadLoop(void* ptr) {
|
||||
done = 1;
|
||||
}
|
||||
// signal to the main thread that we're done (for Sync())
|
||||
pthread_cond_signal(&impl->condition_);
|
||||
// Note the associated mutex does not need to be held when signaling the
|
||||
// condition. Unlocking the mutex first may improve performance in some
|
||||
// implementations, avoiding the case where the waiting thread can't
|
||||
// reacquire the mutex when woken.
|
||||
pthread_mutex_unlock(&impl->mutex_);
|
||||
pthread_cond_signal(&impl->condition_);
|
||||
}
|
||||
return THREAD_RETURN(NULL); // Thread is finished
|
||||
}
|
||||
@@ -240,7 +244,13 @@ static void ChangeState(WebPWorker* const worker, WebPWorkerStatus new_status) {
|
||||
// assign new status and release the working thread if needed
|
||||
if (new_status != OK) {
|
||||
worker->status_ = new_status;
|
||||
// Note the associated mutex does not need to be held when signaling the
|
||||
// condition. Unlocking the mutex first may improve performance in some
|
||||
// implementations, avoiding the case where the waiting thread can't
|
||||
// reacquire the mutex when woken.
|
||||
pthread_mutex_unlock(&impl->mutex_);
|
||||
pthread_cond_signal(&impl->condition_);
|
||||
return;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&impl->mutex_);
|
||||
|
||||
6
thirdparty/libwebp/src/utils/utils.h
vendored
6
thirdparty/libwebp/src/utils/utils.h
vendored
@@ -92,14 +92,14 @@ static WEBP_INLINE uint32_t GetLE32(const uint8_t* const data) {
|
||||
// Store 16, 24 or 32 bits in little-endian order.
|
||||
static WEBP_INLINE void PutLE16(uint8_t* const data, int val) {
|
||||
assert(val < (1 << 16));
|
||||
data[0] = (val >> 0);
|
||||
data[1] = (val >> 8);
|
||||
data[0] = (val >> 0) & 0xff;
|
||||
data[1] = (val >> 8) & 0xff;
|
||||
}
|
||||
|
||||
static WEBP_INLINE void PutLE24(uint8_t* const data, int val) {
|
||||
assert(val < (1 << 24));
|
||||
PutLE16(data, val & 0xffff);
|
||||
data[2] = (val >> 16);
|
||||
data[2] = (val >> 16) & 0xff;
|
||||
}
|
||||
|
||||
static WEBP_INLINE void PutLE32(uint8_t* const data, uint32_t val) {
|
||||
|
||||
Reference in New Issue
Block a user