diff --git a/src/lib/bitstream.c b/src/lib/bitstream.c index c49c4ff..5bd235e 100644 --- a/src/lib/bitstream.c +++ b/src/lib/bitstream.c @@ -73,6 +73,33 @@ void shine_putbits(bitstream_t *bs, unsigned int val, unsigned int N) } } +/* + * shine_flush_end_of_frame: + * ------------------------- + * Flush remaining bits of the frame to the bitstream. Must be called only at end of + * frame, because only then is the cache guaranteed to be filled to a byte boundary. + */ +void shine_flush_end_of_frame(bitstream_t *bs) +{ + int bits_to_flush; + int cache_bytes; + + if (bs->cache_bits < 32) { + bits_to_flush = 32 - bs->cache_bits; + + /* fill the remaining cache bits with zeros (they will be ignored). */ + shine_putbits(bs, 0, bs->cache_bits); + + /* correct output position because a full 4 bytes may not have been written */ + cache_bytes = bits_to_flush / 8; + bs->data_position += cache_bytes - 4; + + /* clear the cache for the next frame */ + bs->cache_bits = 32; + bs->cache = 0; + } +} + int shine_get_bits_count(bitstream_t *bs) { return bs->data_position * 8 + 32 - bs->cache_bits; diff --git a/src/lib/bitstream.h b/src/lib/bitstream.h index d910ef9..6b6645a 100644 --- a/src/lib/bitstream.h +++ b/src/lib/bitstream.h @@ -23,6 +23,7 @@ typedef struct bit_stream_struc { void shine_open_bit_stream(bitstream_t *bs,const int size); void shine_close_bit_stream(bitstream_t *bs); void shine_putbits(bitstream_t *bs,unsigned int val, unsigned int N); +void shine_flush_end_of_frame(bitstream_t *bs); int shine_get_bits_count(bitstream_t *bs); #endif diff --git a/src/lib/layer3.c b/src/lib/layer3.c index 0b574ad..de586a6 100644 --- a/src/lib/layer3.c +++ b/src/lib/layer3.c @@ -165,6 +165,9 @@ static unsigned char *shine_encode_buffer_internal(shine_global_config *config, /* write the frame to the bitstream */ shine_format_bitstream(config); + /* flush the cache bits to write a full frame */ + shine_flush_end_of_frame(&config->bs); + /* Return data. */ *written = config->bs.data_position; config->bs.data_position = 0; @@ -191,6 +194,8 @@ unsigned char *shine_encode_buffer_interleaved(shine_global_config *config, int1 } unsigned char *shine_flush(shine_global_config *config, int *written) { + shine_flush_end_of_frame(&config->bs); + *written = config->bs.data_position; config->bs.data_position = 0;