1*b2055c35SXin Li // Copyright 2011 Google Inc. All Rights Reserved.
2*b2055c35SXin Li //
3*b2055c35SXin Li // Use of this source code is governed by a BSD-style license
4*b2055c35SXin Li // that can be found in the COPYING file in the root of the source
5*b2055c35SXin Li // tree. An additional intellectual property rights grant can be found
6*b2055c35SXin Li // in the file PATENTS. All contributing project authors may
7*b2055c35SXin Li // be found in the AUTHORS file in the root of the source tree.
8*b2055c35SXin Li // -----------------------------------------------------------------------------
9*b2055c35SXin Li //
10*b2055c35SXin Li // Bit writing and boolean coder
11*b2055c35SXin Li //
12*b2055c35SXin Li // Author: Skal ([email protected])
13*b2055c35SXin Li
14*b2055c35SXin Li #ifndef WEBP_UTILS_BIT_WRITER_UTILS_H_
15*b2055c35SXin Li #define WEBP_UTILS_BIT_WRITER_UTILS_H_
16*b2055c35SXin Li
17*b2055c35SXin Li #include "src/webp/types.h"
18*b2055c35SXin Li
19*b2055c35SXin Li #ifdef __cplusplus
20*b2055c35SXin Li extern "C" {
21*b2055c35SXin Li #endif
22*b2055c35SXin Li
23*b2055c35SXin Li //------------------------------------------------------------------------------
24*b2055c35SXin Li // Bit-writing
25*b2055c35SXin Li
26*b2055c35SXin Li typedef struct VP8BitWriter VP8BitWriter;
27*b2055c35SXin Li struct VP8BitWriter {
28*b2055c35SXin Li int32_t range_; // range-1
29*b2055c35SXin Li int32_t value_;
30*b2055c35SXin Li int run_; // number of outstanding bits
31*b2055c35SXin Li int nb_bits_; // number of pending bits
32*b2055c35SXin Li uint8_t* buf_; // internal buffer. Re-allocated regularly. Not owned.
33*b2055c35SXin Li size_t pos_;
34*b2055c35SXin Li size_t max_pos_;
35*b2055c35SXin Li int error_; // true in case of error
36*b2055c35SXin Li };
37*b2055c35SXin Li
38*b2055c35SXin Li // Initialize the object. Allocates some initial memory based on expected_size.
39*b2055c35SXin Li int VP8BitWriterInit(VP8BitWriter* const bw, size_t expected_size);
40*b2055c35SXin Li // Finalize the bitstream coding. Returns a pointer to the internal buffer.
41*b2055c35SXin Li uint8_t* VP8BitWriterFinish(VP8BitWriter* const bw);
42*b2055c35SXin Li // Release any pending memory and zeroes the object. Not a mandatory call.
43*b2055c35SXin Li // Only useful in case of error, when the internal buffer hasn't been grabbed!
44*b2055c35SXin Li void VP8BitWriterWipeOut(VP8BitWriter* const bw);
45*b2055c35SXin Li
46*b2055c35SXin Li int VP8PutBit(VP8BitWriter* const bw, int bit, int prob);
47*b2055c35SXin Li int VP8PutBitUniform(VP8BitWriter* const bw, int bit);
48*b2055c35SXin Li void VP8PutBits(VP8BitWriter* const bw, uint32_t value, int nb_bits);
49*b2055c35SXin Li void VP8PutSignedBits(VP8BitWriter* const bw, int value, int nb_bits);
50*b2055c35SXin Li
51*b2055c35SXin Li // Appends some bytes to the internal buffer. Data is copied.
52*b2055c35SXin Li int VP8BitWriterAppend(VP8BitWriter* const bw,
53*b2055c35SXin Li const uint8_t* data, size_t size);
54*b2055c35SXin Li
55*b2055c35SXin Li // return approximate write position (in bits)
VP8BitWriterPos(const VP8BitWriter * const bw)56*b2055c35SXin Li static WEBP_INLINE uint64_t VP8BitWriterPos(const VP8BitWriter* const bw) {
57*b2055c35SXin Li const uint64_t nb_bits = 8 + bw->nb_bits_; // bw->nb_bits_ is <= 0, note
58*b2055c35SXin Li return (bw->pos_ + bw->run_) * 8 + nb_bits;
59*b2055c35SXin Li }
60*b2055c35SXin Li
61*b2055c35SXin Li // Returns a pointer to the internal buffer.
VP8BitWriterBuf(const VP8BitWriter * const bw)62*b2055c35SXin Li static WEBP_INLINE uint8_t* VP8BitWriterBuf(const VP8BitWriter* const bw) {
63*b2055c35SXin Li return bw->buf_;
64*b2055c35SXin Li }
65*b2055c35SXin Li // Returns the size of the internal buffer.
VP8BitWriterSize(const VP8BitWriter * const bw)66*b2055c35SXin Li static WEBP_INLINE size_t VP8BitWriterSize(const VP8BitWriter* const bw) {
67*b2055c35SXin Li return bw->pos_;
68*b2055c35SXin Li }
69*b2055c35SXin Li
70*b2055c35SXin Li //------------------------------------------------------------------------------
71*b2055c35SXin Li // VP8LBitWriter
72*b2055c35SXin Li
73*b2055c35SXin Li #if defined(__x86_64__) || defined(_M_X64) // 64bit
74*b2055c35SXin Li typedef uint64_t vp8l_atype_t; // accumulator type
75*b2055c35SXin Li typedef uint32_t vp8l_wtype_t; // writing type
76*b2055c35SXin Li #define WSWAP HToLE32
77*b2055c35SXin Li #define VP8L_WRITER_BYTES 4 // sizeof(vp8l_wtype_t)
78*b2055c35SXin Li #define VP8L_WRITER_BITS 32 // 8 * sizeof(vp8l_wtype_t)
79*b2055c35SXin Li #define VP8L_WRITER_MAX_BITS 64 // 8 * sizeof(vp8l_atype_t)
80*b2055c35SXin Li #else
81*b2055c35SXin Li typedef uint32_t vp8l_atype_t;
82*b2055c35SXin Li typedef uint16_t vp8l_wtype_t;
83*b2055c35SXin Li #define WSWAP HToLE16
84*b2055c35SXin Li #define VP8L_WRITER_BYTES 2
85*b2055c35SXin Li #define VP8L_WRITER_BITS 16
86*b2055c35SXin Li #define VP8L_WRITER_MAX_BITS 32
87*b2055c35SXin Li #endif
88*b2055c35SXin Li
89*b2055c35SXin Li typedef struct {
90*b2055c35SXin Li vp8l_atype_t bits_; // bit accumulator
91*b2055c35SXin Li int used_; // number of bits used in accumulator
92*b2055c35SXin Li uint8_t* buf_; // start of buffer
93*b2055c35SXin Li uint8_t* cur_; // current write position
94*b2055c35SXin Li uint8_t* end_; // end of buffer
95*b2055c35SXin Li
96*b2055c35SXin Li // After all bits are written (VP8LBitWriterFinish()), the caller must observe
97*b2055c35SXin Li // the state of error_. A value of 1 indicates that a memory allocation
98*b2055c35SXin Li // failure has happened during bit writing. A value of 0 indicates successful
99*b2055c35SXin Li // writing of bits.
100*b2055c35SXin Li int error_;
101*b2055c35SXin Li } VP8LBitWriter;
102*b2055c35SXin Li
VP8LBitWriterNumBytes(const VP8LBitWriter * const bw)103*b2055c35SXin Li static WEBP_INLINE size_t VP8LBitWriterNumBytes(const VP8LBitWriter* const bw) {
104*b2055c35SXin Li return (bw->cur_ - bw->buf_) + ((bw->used_ + 7) >> 3);
105*b2055c35SXin Li }
106*b2055c35SXin Li
107*b2055c35SXin Li // Returns false in case of memory allocation error.
108*b2055c35SXin Li int VP8LBitWriterInit(VP8LBitWriter* const bw, size_t expected_size);
109*b2055c35SXin Li // Returns false in case of memory allocation error.
110*b2055c35SXin Li int VP8LBitWriterClone(const VP8LBitWriter* const src,
111*b2055c35SXin Li VP8LBitWriter* const dst);
112*b2055c35SXin Li // Finalize the bitstream coding. Returns a pointer to the internal buffer.
113*b2055c35SXin Li uint8_t* VP8LBitWriterFinish(VP8LBitWriter* const bw);
114*b2055c35SXin Li // Release any pending memory and zeroes the object.
115*b2055c35SXin Li void VP8LBitWriterWipeOut(VP8LBitWriter* const bw);
116*b2055c35SXin Li // Resets the cursor of the BitWriter bw to when it was like in bw_init.
117*b2055c35SXin Li void VP8LBitWriterReset(const VP8LBitWriter* const bw_init,
118*b2055c35SXin Li VP8LBitWriter* const bw);
119*b2055c35SXin Li // Swaps the memory held by two BitWriters.
120*b2055c35SXin Li void VP8LBitWriterSwap(VP8LBitWriter* const src, VP8LBitWriter* const dst);
121*b2055c35SXin Li
122*b2055c35SXin Li // Internal function for VP8LPutBits flushing 32 bits from the written state.
123*b2055c35SXin Li void VP8LPutBitsFlushBits(VP8LBitWriter* const bw);
124*b2055c35SXin Li
125*b2055c35SXin Li // PutBits internal function used in the 16 bit vp8l_wtype_t case.
126*b2055c35SXin Li void VP8LPutBitsInternal(VP8LBitWriter* const bw, uint32_t bits, int n_bits);
127*b2055c35SXin Li
128*b2055c35SXin Li // This function writes bits into bytes in increasing addresses (little endian),
129*b2055c35SXin Li // and within a byte least-significant-bit first.
130*b2055c35SXin Li // This function can write up to 32 bits in one go, but VP8LBitReader can only
131*b2055c35SXin Li // read 24 bits max (VP8L_MAX_NUM_BIT_READ).
132*b2055c35SXin Li // VP8LBitWriter's error_ flag is set in case of memory allocation error.
VP8LPutBits(VP8LBitWriter * const bw,uint32_t bits,int n_bits)133*b2055c35SXin Li static WEBP_INLINE void VP8LPutBits(VP8LBitWriter* const bw,
134*b2055c35SXin Li uint32_t bits, int n_bits) {
135*b2055c35SXin Li if (sizeof(vp8l_wtype_t) == 4) {
136*b2055c35SXin Li if (n_bits > 0) {
137*b2055c35SXin Li if (bw->used_ >= 32) {
138*b2055c35SXin Li VP8LPutBitsFlushBits(bw);
139*b2055c35SXin Li }
140*b2055c35SXin Li bw->bits_ |= (vp8l_atype_t)bits << bw->used_;
141*b2055c35SXin Li bw->used_ += n_bits;
142*b2055c35SXin Li }
143*b2055c35SXin Li } else {
144*b2055c35SXin Li VP8LPutBitsInternal(bw, bits, n_bits);
145*b2055c35SXin Li }
146*b2055c35SXin Li }
147*b2055c35SXin Li
148*b2055c35SXin Li //------------------------------------------------------------------------------
149*b2055c35SXin Li
150*b2055c35SXin Li #ifdef __cplusplus
151*b2055c35SXin Li } // extern "C"
152*b2055c35SXin Li #endif
153*b2055c35SXin Li
154*b2055c35SXin Li #endif // WEBP_UTILS_BIT_WRITER_UTILS_H_
155