diff --git a/src/utils/bit_writer.c b/src/utils/bit_writer.c index 97925bc6..a95245bb 100644 --- a/src/utils/bit_writer.c +++ b/src/utils/bit_writer.c @@ -250,12 +250,28 @@ void VP8LBitWriterWipeOut(VP8LBitWriter* const bw) { } } -void VP8LPutBits(VP8LBitWriter* const bw, uint32_t bits, int n_bits) { +void VP8LPutBitsFlushBits(VP8LBitWriter* const bw) { + // If needed, make some room by flushing some bits out. + if (bw->cur_ + VP8L_WRITER_BYTES > bw->end_) { + const uint64_t extra_size = (bw->end_ - bw->buf_) + MIN_EXTRA_SIZE; + if (extra_size != (size_t)extra_size || + !VP8LBitWriterResize(bw, (size_t)extra_size)) { + bw->cur_ = bw->buf_; + bw->error_ = 1; + return; + } + } + *(vp8l_wtype_t*)bw->cur_ = (vp8l_wtype_t)WSWAP((vp8l_wtype_t)bw->bits_); + bw->cur_ += VP8L_WRITER_BYTES; + bw->bits_ >>= VP8L_WRITER_BITS; + bw->used_ -= VP8L_WRITER_BITS; +} + +void VP8LPutBitsInternal(VP8LBitWriter* const bw, uint32_t bits, int n_bits) { assert(n_bits <= 32); // That's the max we can handle: - assert(bw->used_ + n_bits <= 2 * VP8L_WRITER_MAX_BITS); + assert(sizeof(vp8l_wtype_t) == 2); if (n_bits > 0) { - // Local field copy. vp8l_atype_t lbits = bw->bits_; int used = bw->used_; // Special case of overflow handling for 32bit accumulator (2-steps flush). @@ -286,7 +302,6 @@ void VP8LPutBits(VP8LBitWriter* const bw, uint32_t bits, int n_bits) { lbits >>= VP8L_WRITER_BITS; used -= VP8L_WRITER_BITS; } - // Eventually, insert new bits. bw->bits_ = lbits | ((vp8l_atype_t)bits << used); bw->used_ = used + n_bits; } diff --git a/src/utils/bit_writer.h b/src/utils/bit_writer.h index 6765e554..78b41af4 100644 --- a/src/utils/bit_writer.h +++ b/src/utils/bit_writer.h @@ -104,12 +104,31 @@ uint8_t* VP8LBitWriterFinish(VP8LBitWriter* const bw); // Release any pending memory and zeroes the object. void VP8LBitWriterWipeOut(VP8LBitWriter* const bw); +// Internal function for VP8LPutBits flushing 32 bits from the written state. +void VP8LPutBitsFlushBits(VP8LBitWriter* const bw); + +// PutBits internal function used in the 16 bit vp8l_wtype_t case. +void VP8LPutBitsInternal(VP8LBitWriter* const bw, uint32_t bits, int n_bits); + // This function writes bits into bytes in increasing addresses (little endian), // and within a byte least-significant-bit first. // This function can write up to 32 bits in one go, but VP8LBitReader can only // read 24 bits max (VP8L_MAX_NUM_BIT_READ). // VP8LBitWriter's error_ flag is set in case of memory allocation error. -void VP8LPutBits(VP8LBitWriter* const bw, uint32_t bits, int n_bits); +static WEBP_INLINE void VP8LPutBits(VP8LBitWriter* const bw, + uint32_t bits, int n_bits) { + if (sizeof(vp8l_wtype_t) == 4) { + if (n_bits > 0) { + if (bw->used_ >= 32) { + VP8LPutBitsFlushBits(bw); + } + bw->bits_ |= (vp8l_atype_t)bits << bw->used_; + bw->used_ += n_bits; + } + } else { + VP8LPutBitsInternal(bw, bits, n_bits); + } +} //------------------------------------------------------------------------------