diff --git a/src/utils/bit_writer_utils.c b/src/utils/bit_writer_utils.c index e9c0e3e5..64f1ff55 100644 --- a/src/utils/bit_writer_utils.c +++ b/src/utils/bit_writer_utils.c @@ -275,7 +275,8 @@ void VP8LBitWriterSwap(VP8LBitWriter* const src, VP8LBitWriter* const dst) { *dst = tmp; } -void VP8LPutBitsFlushBits(VP8LBitWriter* const bw) { +void VP8LPutBitsFlushBits(VP8LBitWriter* const bw, int* used, + vp8l_atype_t* bits) { // 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; @@ -286,51 +287,42 @@ void VP8LPutBitsFlushBits(VP8LBitWriter* const bw) { return; } } - *(vp8l_wtype_t*)bw->cur = (vp8l_wtype_t)WSWAP((vp8l_wtype_t)bw->bits); + *(vp8l_wtype_t*)bw->cur = (vp8l_wtype_t)WSWAP((vp8l_wtype_t)*bits); bw->cur += VP8L_WRITER_BYTES; - bw->bits >>= VP8L_WRITER_BITS; - bw->used -= VP8L_WRITER_BITS; + *bits >>= VP8L_WRITER_BITS; + *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(sizeof(vp8l_wtype_t) == 2); - if (n_bits > 0) { - vp8l_atype_t lbits = bw->bits; - int used = bw->used; - // Special case of overflow handling for 32bit accumulator (2-steps flush). #if VP8L_WRITER_BITS == 16 - if (used + n_bits >= VP8L_WRITER_MAX_BITS) { - // Fill up all the VP8L_WRITER_MAX_BITS so it can be flushed out below. - const int shift = VP8L_WRITER_MAX_BITS - used; - lbits |= (vp8l_atype_t)bits << used; - used = VP8L_WRITER_MAX_BITS; - n_bits -= shift; +void VP8LPutBitsInternal(VP8LBitWriter* const bw, uint32_t bits, int n_bits) { + vp8l_atype_t lbits = bw->bits; + int used = bw->used; + assert(n_bits <= VP8L_WRITER_MAX_BITS); + if (n_bits == 0) return; + // Special case of overflow handling for 32bit accumulator (2-steps flush). + if (used + n_bits >= VP8L_WRITER_MAX_BITS) { + // Fill up all the VP8L_WRITER_MAX_BITS so it can be flushed out below. + const int shift = VP8L_WRITER_MAX_BITS - used; + lbits |= (vp8l_atype_t)bits << used; + used = VP8L_WRITER_MAX_BITS; + n_bits -= shift; + if (shift >= (int)sizeof(bits) * 8) { + // Undefined behavior. + assert(shift == (int)sizeof(bits) * 8); + bits = 0; + } else { bits >>= shift; - assert(n_bits <= VP8L_WRITER_MAX_BITS); } -#endif - // If needed, make some room by flushing some bits out. - while (used >= VP8L_WRITER_BITS) { - if (bw->cur + VP8L_WRITER_BYTES > bw->end) { - const uint64_t extra_size = (bw->end - bw->buf) + MIN_EXTRA_SIZE; - if (!CheckSizeOverflow(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)lbits); - bw->cur += VP8L_WRITER_BYTES; - lbits >>= VP8L_WRITER_BITS; - used -= VP8L_WRITER_BITS; - } - bw->bits = lbits | ((vp8l_atype_t)bits << used); - bw->used = used + n_bits; + assert(n_bits <= VP8L_WRITER_MAX_BITS); } + // If needed, make some room by flushing some bits out. + while (used >= VP8L_WRITER_BITS) { + VP8LPutBitsFlushBits(bw, &used, &lbits); + } + bw->bits = lbits | ((vp8l_atype_t)bits << used); + bw->used = used + n_bits; } +#endif // VP8L_WRITER_BITS == 16 uint8_t* VP8LBitWriterFinish(VP8LBitWriter* const bw) { // flush leftover bits diff --git a/src/utils/bit_writer_utils.h b/src/utils/bit_writer_utils.h index 79924176..50b9f6a8 100644 --- a/src/utils/bit_writer_utils.h +++ b/src/utils/bit_writer_utils.h @@ -125,30 +125,33 @@ void VP8LBitWriterReset(const VP8LBitWriter* const bw_init, // Swaps the memory held by two BitWriters. void VP8LBitWriterSwap(VP8LBitWriter* const src, VP8LBitWriter* const dst); -// Internal function for VP8LPutBits flushing 32 bits from the written state. -void VP8LPutBitsFlushBits(VP8LBitWriter* const bw); +// Internal function for VP8LPutBits flushing VP8L_WRITER_BITS bits from the +// written state. +void VP8LPutBitsFlushBits(VP8LBitWriter* const bw, int* used, + vp8l_atype_t* bits); +#if VP8L_WRITER_BITS == 16 // PutBits internal function used in the 16 bit vp8l_wtype_t case. void VP8LPutBitsInternal(VP8LBitWriter* const bw, uint32_t bits, int n_bits); +#endif // 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). +// This function can write up to VP8L_WRITER_MAX_BITS 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. 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); +#if VP8L_WRITER_BYTES == 4 + if (n_bits == 0) return; + if (bw->used >= VP8L_WRITER_BITS) { + VP8LPutBitsFlushBits(bw, &bw->used, &bw->bits); } + bw->bits |= (vp8l_atype_t)bits << bw->used; + bw->used += n_bits; +#else + VP8LPutBitsInternal(bw, bits, n_bits); +#endif } //------------------------------------------------------------------------------