]> git.sesse.net Git - ffmpeg/commitdiff
Detect byte-swapped AC-3 (aka DNET) and support decoding it directly.
authorReimar Döffinger <Reimar.Doeffinger@gmx.de>
Sat, 5 Mar 2011 12:49:13 +0000 (13:49 +0100)
committerReimar Döffinger <Reimar.Doeffinger@gmx.de>
Sat, 19 Mar 2011 11:07:14 +0000 (12:07 +0100)
This allows the AC-3 decoder to be used directly with RealMedia
decoders that unlike the libavformat one do not byte-swap automatically.
Since the new code is only used in case we would fail directly otherwise
there should be no risk for regressions.
The "buf" pointer needs to be overwritten since otherwise the CRC check fails.

libavcodec/ac3dec.c

index 5ebee1908db5b0e3020f2e95ee9003b9e8b4b64d..fbcfdb0ce960775e1ea9bf8e5c7433623ee96479 100644 (file)
@@ -207,13 +207,6 @@ static av_cold int ac3_decode_init(AVCodecContext *avctx)
     }
     s->downmixed = 1;
 
-    /* allocate context input buffer */
-    if (avctx->error_recognition >= FF_ER_CAREFUL) {
-        s->input_buffer = av_mallocz(AC3_FRAME_BUFFER_SIZE + FF_INPUT_BUFFER_PADDING_SIZE);
-        if (!s->input_buffer)
-            return AVERROR(ENOMEM);
-    }
-
     avctx->sample_fmt = AV_SAMPLE_FMT_S16;
     return 0;
 }
@@ -1312,16 +1305,27 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data, int *data_size,
     int blk, ch, err;
     const uint8_t *channel_map;
     const float *output[AC3_MAX_CHANNELS];
+    // if it seems to be byte-swapped AC-3 (aka DNET)
+    int is_swapped = buf_size >= 2 && AV_RB16(buf) == 0x770B;
 
     /* initialize the GetBitContext with the start of valid AC-3 Frame */
-    if (s->input_buffer) {
+    if (is_swapped || avctx->error_recognition >= FF_ER_CAREFUL) {
+        /* allocate context input buffer */
+        if (!s->input_buffer)
+            s->input_buffer = av_mallocz(AC3_FRAME_BUFFER_SIZE + FF_INPUT_BUFFER_PADDING_SIZE);
+        if (!s->input_buffer)
+            return AVERROR(ENOMEM);
+
         /* copy input buffer to decoder context to avoid reading past the end
            of the buffer, which can be caused by a damaged input stream. */
+        if (is_swapped) {
+            int cnt = FFMIN(buf_size, AC3_FRAME_BUFFER_SIZE) >> 1;
+            s->dsp.bswap16_buf(s->input_buffer, buf, cnt);
+        } else
         memcpy(s->input_buffer, buf, FFMIN(buf_size, AC3_FRAME_BUFFER_SIZE));
-        init_get_bits(&s->gbc, s->input_buffer, buf_size * 8);
-    } else {
-        init_get_bits(&s->gbc, buf, buf_size * 8);
+        buf = s->input_buffer;
     }
+    init_get_bits(&s->gbc, buf, buf_size * 8);
 
     /* parse the syncinfo */
     *data_size = 0;