[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