From: Daniel S. <daniel@InstantHarmony.com> - 2009-04-29 23:24:23
|
I recently upgraded from an older version of Lame to v3.98.2, and i discovered that lame_encode_flush() is now behaving differently, and returning too much data. After encoding a stream of samples, i'm calling lame_encode_flush() repeatedly until it returns 0, indicating that it has finished flushing its internal buffers. However, where it used to successfully flush its input in the first call and return zero subsequently, now it takes several calls before zero is returned, and around 6 spurious packets are emitted. The resulting stream decodes to a significantly longer duration. I tracked it down to the re-factoring of lame_encode_flush in libmp3lame/lame.c. I believe there are two problems in v3_98_2: 1) lame.c:: lame_encode_flush() lines 1932-1945: int samples_to_encode = gfc->mf_samples_to_encode; . . . pad_out_samples = gfp->framesize - (samples_to_encode % gfp->framesize); end_padding += pad_out_samples; frames_left = (samples_to_encode + pad_out_samples) / gfp->framesize; I think the intention here is to pad a non-zero number of remaining samples up to a framesize boundary. However, this statement rounds 0 up to framesize, and adds framesize to sample counts that are already an exact multiple of framesize. The correct code should be: pad_out_samples = gfp->framesize - (samples_to_encode % gfp->framesize); if (pad_out_samples == gfp->framesize) { pad_out_samples = 0; } end_padding += pad_out_samples; frames_left = (samples_to_encode + pad_out_samples) / gfp->framesize; 2) lame.c:: lame_encode_flush() lines 1959-1965: In a previous version, gfc->mf_samples_to_encode was reduced by framesize every time lame_encode_buffer() was called ... this was used to determine the loop end condition. In the current version, the loop count is calculated from mf_samples_to_encode up front, but mf_samples_to_encode is never reduced to account for the data consumed by the loop. One obvious solution is to add: gfc->mf_samples_to_encode = 0; right after the loop finishes, eg, just before flush_bitstream() is called. With both of the above changes, the behavior of lame_encode_flush() matches its previous behavior, and there is only minimal expansion of the stream duration. -daniel |