[FFmpeg-devel] [PATCH] Detect byte-swapped AC-3 (aka DNET) and support decoding it directly.

Justin Ruggles justin.ruggles
Sun Mar 6 17:44:49 CET 2011


On 03/05/2011 11:22 AM, Reimar D?ffinger wrote:

> 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 |   29 +++++++++++++++++++----------
>  1 files changed, 19 insertions(+), 10 deletions(-)
> 
> diff --git a/libavcodec/ac3dec.c b/libavcodec/ac3dec.c
> index 5ebee19..ddbc9b3 100644
> --- a/libavcodec/ac3dec.c
> +++ b/libavcodec/ac3dec.c
> @@ -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,32 @@ 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;
> +
> +    /* allocate context input buffer */
> +    if (!s->input_buffer &&
> +        (is_swapped || 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);
> +    }
>  
>      /* initialize the GetBitContext with the start of valid AC-3 Frame */
>      if (s->input_buffer) {
>          /* copy input buffer to decoder context to avoid reading past the end
>             of the buffer, which can be caused by a damaged input stream. */


Michael makes a good point about using the proper conditions to do the
copy or copy/swap rather than just to allocate the buffer.

So something like:
if (is_swapped || avctx->error_recognition >= FF_ER_CAREFUL) {
    if (!s->input_buffer)
        allocate buffer
    if (is_swapped)
        copy/swap
    else
        memcpy
}

> +        if (is_swapped) {
> +            int i;
> +            for (i = 0; i < FFMIN(buf_size, AC3_FRAME_BUFFER_SIZE) - 1; i += 2) {
> +                s->input_buffer[i]     = buf[i + 1];
> +                s->input_buffer[i + 1] = buf[i];
> +            }
> +        } 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;





More information about the ffmpeg-devel mailing list