[Ffmpeg-devel] [PATCH] Fix bug in ac3 decoding from MPEG2 stream
Geoffrey Hausheer
b3zknt8xu02
Sun Nov 6 02:34:30 CET 2005
There is a bug in libavcodec when processing AC3 audio from MPEG2 streams.
The problem is that the very last audio frame does not get returned
via av_read_frame.
This happens because of the following code in ac3_parse (in parser.c):
while (buf_size > 0) {
len = s->inbuf_ptr - s->inbuf;
if (s->frame_size == 0) {
...
} else if (len < s->frame_size) {
len = s->frame_size - len;
if (len > buf_size)
len = buf_size;
memcpy(s->inbuf_ptr, buf_ptr, len);
buf_ptr += len;
s->inbuf_ptr += len;
buf_size -= len;
} else {
*poutbuf = s->inbuf;
*poutbuf_size = s->frame_size;
s->inbuf_ptr = s->inbuf;
s->frame_size = 0;
break;
}
}
what happens is that a full block comes in (1536 bytes), and since
this is the last frame, buf_size==1536. The first time through,
s_frame_size==0, so we read in the header (7 bytes). The next time
through len < s_frame_size (len==7), so we copy the remaining bytes
(1529 of them) into s->inbuf_ptr, making (s->inbuf_ptr -
s->inbuf)==s->frame_size. however, the loop never runs a third time,
because buf_size==0, resulting in poutbuf never getting filled. Since
this is the last audio frame, next time av_parser_parse is called,
buf_size will be 0, so we won't ever process this frame.
The following fixes the problem, by allowing one more time through the
loop in this case:
--- parser.old.c 2005-11-05 17:30:44.000000000 -0800
+++ parser.c 2005-11-05 16:47:15.000000000 -0800
@@ -790,7 +790,8 @@
*poutbuf_size = 0;
buf_ptr = buf;
- while (buf_size > 0) {
+ while (buf_size > 0 ||
+ (s->frame_size != 0 && (s->inbuf_ptr - s->inbuf) ==
s->frame_size)) {
len = s->inbuf_ptr - s->inbuf;
if (s->frame_size == 0) {
/* no header seen : find one. We need at least 7 bytes to
parse it */
There may be a better solution, but the above has been verified to
work correctly.
Thanks,
.Geoff
More information about the ffmpeg-devel
mailing list