Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(358)

Unified Diff: third_party/libwebp/utils/bit_reader.h

Issue 10832153: libwebp: update snapshot to v0.2.0-rc1 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/libwebp/utils/bit_reader.h
diff --git a/third_party/libwebp/utils/bit_reader.h b/third_party/libwebp/utils/bit_reader.h
index d65a74e4acf51c7f1e5fb55a8b260523d2325053..36fc13e2da286cea63f931b6ede1d73b79595fc0 100644
--- a/third_party/libwebp/utils/bit_reader.h
+++ b/third_party/libwebp/utils/bit_reader.h
@@ -1,4 +1,4 @@
-// Copyright 2010 Google Inc.
+// Copyright 2010 Google Inc. All Rights Reserved.
//
// This code is licensed under the same terms as WebM:
// Software License Agreement: http://www.webmproject.org/license/software/
@@ -8,17 +8,35 @@
// Boolean decoder
//
// Author: Skal (pascal.massimino@gmail.com)
+// Vikas Arora (vikaas.arora@gmail.com)
#ifndef WEBP_UTILS_BIT_READER_H_
#define WEBP_UTILS_BIT_READER_H_
#include <assert.h>
-#include "../webp/decode_vp8.h"
+#ifdef _MSC_VER
+#include <stdlib.h> // _byteswap_ulong
+#endif
+#include <string.h> // For memcpy
+#include "../webp/types.h"
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
+#define BITS 32 // can be 32, 16 or 8
+#define MASK ((((bit_t)1) << (BITS)) - 1)
+#if (BITS == 32)
+typedef uint64_t bit_t; // natural register type
+typedef uint32_t lbit_t; // natural type for memory I/O
+#elif (BITS == 16)
+typedef uint32_t bit_t;
+typedef uint16_t lbit_t;
+#else
+typedef uint32_t bit_t;
+typedef uint8_t lbit_t;
+#endif
+
//------------------------------------------------------------------------------
// Bitreader and code-tree reader
@@ -29,9 +47,9 @@ struct VP8BitReader {
int eof_; // true if input is exhausted
// boolean decoder
- uint32_t range_; // current range minus 1. In [127, 254] interval.
- uint32_t value_; // current value
- int missing_; // number of missing bits in value_ (8bit)
+ bit_t range_; // current range minus 1. In [127, 254] interval.
+ bit_t value_; // current value
+ int missing_; // number of missing bits in value_ (8bit)
};
// Initialize the bit reader and the boolean decoder.
@@ -40,7 +58,7 @@ void VP8InitBitReader(VP8BitReader* const br,
// return the next value made of 'num_bits' bits
uint32_t VP8GetValue(VP8BitReader* const br, int num_bits);
-static inline uint32_t VP8Get(VP8BitReader* const br) {
+static WEBP_INLINE uint32_t VP8Get(VP8BitReader* const br) {
return VP8GetValue(br, 1);
}
@@ -49,59 +67,129 @@ int32_t VP8GetSignedValue(VP8BitReader* const br, int num_bits);
// Read a bit with proba 'prob'. Speed-critical function!
extern const uint8_t kVP8Log2Range[128];
-extern const uint8_t kVP8NewRange[128];
-static inline uint32_t VP8GetByte(VP8BitReader* const br) {
- assert(br);
- if (br->buf_ < br->buf_end_) {
- assert(br->buf_);
- return *br->buf_++;
+extern const bit_t kVP8NewRange[128];
+
+void VP8LoadFinalBytes(VP8BitReader* const br); // special case for the tail
+
+static WEBP_INLINE void VP8LoadNewBytes(VP8BitReader* const br) {
+ assert(br && br->buf_);
+ // Read 'BITS' bits at a time if possible.
+ if (br->buf_ + sizeof(lbit_t) <= br->buf_end_) {
+ // convert memory type to register type (with some zero'ing!)
+ bit_t bits;
+ lbit_t in_bits = *(lbit_t*)br->buf_;
+ br->buf_ += (BITS) >> 3;
+#if !defined(__BIG_ENDIAN__)
+#if (BITS == 32)
+#if defined(__i386__) || defined(__x86_64__)
+ __asm__ volatile("bswap %k0" : "=r"(in_bits) : "0"(in_bits));
+ bits = (bit_t)in_bits; // 32b -> 64b zero-extension
+#elif defined(_MSC_VER)
+ bits = _byteswap_ulong(in_bits);
+#else
+ bits = (bit_t)(in_bits >> 24) | ((in_bits >> 8) & 0xff00)
+ | ((in_bits << 8) & 0xff0000) | (in_bits << 24);
+#endif // x86
+#elif (BITS == 16)
+ // gcc will recognize a 'rorw $8, ...' here:
+ bits = (bit_t)(in_bits >> 8) | ((in_bits & 0xff) << 8);
+#endif
+#else // LITTLE_ENDIAN
+ bits = (bit_t)in_bits;
+#endif
+ br->value_ |= bits << br->missing_;
+ br->missing_ -= (BITS);
+ } else {
+ VP8LoadFinalBytes(br); // no need to be inlined
}
- br->eof_ = 1;
- return 0xff;
}
-static inline uint32_t VP8BitUpdate(VP8BitReader* const br, uint32_t split) {
- uint32_t bit;
- const uint32_t value_split = (split + 1) << 8;
- // Make sure we have a least 8 bits in 'value_'
- if (br->missing_ > 0) {
- br->value_ |= VP8GetByte(br) << br->missing_;
- br->missing_ -= 8;
+static WEBP_INLINE int VP8BitUpdate(VP8BitReader* const br, bit_t split) {
+ const bit_t value_split = split | (MASK);
+ if (br->missing_ > 0) { // Make sure we have a least BITS bits in 'value_'
+ VP8LoadNewBytes(br);
}
- bit = (br->value_ >= value_split);
- if (bit) {
- br->range_ -= split + 1;
- br->value_ -= value_split;
+ if (br->value_ > value_split) {
+ br->range_ -= value_split + 1;
+ br->value_ -= value_split + 1;
+ return 1;
} else {
- br->range_ = split;
+ br->range_ = value_split;
+ return 0;
}
- return bit;
}
-static inline void VP8Shift(VP8BitReader* const br) {
+static WEBP_INLINE void VP8Shift(VP8BitReader* const br) {
// range_ is in [0..127] interval here.
- const int shift = kVP8Log2Range[br->range_];
- br->range_ = kVP8NewRange[br->range_];
+ const int idx = br->range_ >> (BITS);
+ const int shift = kVP8Log2Range[idx];
+ br->range_ = kVP8NewRange[idx];
br->value_ <<= shift;
br->missing_ += shift;
}
-static inline uint32_t VP8GetBit(VP8BitReader* const br, int prob) {
- const uint32_t split = (br->range_ * prob) >> 8;
- const uint32_t bit = VP8BitUpdate(br, split);
- if (br->range_ < 0x7f) {
+static WEBP_INLINE int VP8GetBit(VP8BitReader* const br, int prob) {
+ // It's important to avoid generating a 64bit x 64bit multiply here.
+ // We just need an 8b x 8b after all.
+ const bit_t split =
+ (bit_t)((uint32_t)(br->range_ >> (BITS)) * prob) << ((BITS) - 8);
+ const int bit = VP8BitUpdate(br, split);
+ if (br->range_ <= (((bit_t)0x7e << (BITS)) | (MASK))) {
VP8Shift(br);
}
return bit;
}
-static inline int VP8GetSigned(VP8BitReader* const br, int v) {
- const uint32_t split = br->range_ >> 1;
- const uint32_t bit = VP8BitUpdate(br, split);
+static WEBP_INLINE int VP8GetSigned(VP8BitReader* const br, int v) {
+ const bit_t split = (br->range_ >> 1);
+ const int bit = VP8BitUpdate(br, split);
VP8Shift(br);
return bit ? -v : v;
}
+
+// -----------------------------------------------------------------------------
+// Bitreader
+
+typedef struct {
+ uint64_t val_;
+ const uint8_t* buf_;
+ size_t len_;
+ size_t pos_;
+ int bit_pos_;
+ int eos_;
+ int error_;
+} VP8LBitReader;
+
+void VP8LInitBitReader(VP8LBitReader* const br,
+ const uint8_t* const start,
+ size_t length);
+
+// Sets a new data buffer.
+void VP8LBitReaderSetBuffer(VP8LBitReader* const br,
+ const uint8_t* const buffer, size_t length);
+
+// Reads the specified number of bits from Read Buffer.
+// Flags an error in case end_of_stream or n_bits is more than allowed limit.
+// Flags eos if this read attempt is going to cross the read buffer.
+uint32_t VP8LReadBits(VP8LBitReader* const br, int n_bits);
+
+// Reads one bit from Read Buffer. Flags an error in case end_of_stream.
+// Flags eos after reading last bit from the buffer.
+uint32_t VP8LReadOneBit(VP8LBitReader* const br);
+
+// VP8LReadOneBitUnsafe is faster than VP8LReadOneBit, but it can be called only
+// 32 times after the last VP8LFillBitWindow. Any subsequent calls
+// (without VP8LFillBitWindow) will return invalid data.
+static WEBP_INLINE uint32_t VP8LReadOneBitUnsafe(VP8LBitReader* const br) {
+ const uint32_t val = (br->val_ >> br->bit_pos_) & 1;
+ ++br->bit_pos_;
+ return val;
+}
+
+// Advances the Read buffer by 4 bytes to make room for reading next 32 bits.
+void VP8LFillBitWindow(VP8LBitReader* const br);
+
#if defined(__cplusplus) || defined(c_plusplus)
} // extern "C"
#endif

Powered by Google App Engine
This is Rietveld 408576698