[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