X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fvmdav.c;h=710c2028cf15cf665706e842033b244aca86f90c;hb=767848d7619ce43e00d1a13607a5cf2aa61d2d6e;hp=48739a726b1038dd65b84f237e0aab05e284fdb6;hpb=8e9027d266ef39ab9f88b4bbad5cf9e425d0696c;p=ffmpeg diff --git a/libavcodec/vmdav.c b/libavcodec/vmdav.c index 48739a726b1..710c2028cf1 100644 --- a/libavcodec/vmdav.c +++ b/libavcodec/vmdav.c @@ -2,20 +2,20 @@ * Sierra VMD Audio & Video Decoders * Copyright (C) 2004 the ffmpeg project * - * This file is part of FFmpeg. + * This file is part of Libav. * - * FFmpeg is free software; you can redistribute it and/or + * Libav is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * - * FFmpeg is distributed in the hope that it will be useful, + * Libav is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software + * License along with Libav; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -420,9 +420,7 @@ static av_cold int vmdvideo_decode_end(AVCodecContext *avctx) typedef struct VmdAudioContext { AVCodecContext *avctx; - int channels; - int bits; - int block_align; + int out_bps; int predictors[2]; } VmdAudioContext; @@ -447,13 +445,16 @@ static av_cold int vmdaudio_decode_init(AVCodecContext *avctx) VmdAudioContext *s = avctx->priv_data; s->avctx = avctx; - s->channels = avctx->channels; - s->bits = avctx->bits_per_coded_sample; - s->block_align = avctx->block_align; - avctx->sample_fmt = AV_SAMPLE_FMT_S16; + if (avctx->bits_per_coded_sample == 16) + avctx->sample_fmt = AV_SAMPLE_FMT_S16; + else + avctx->sample_fmt = AV_SAMPLE_FMT_U8; + s->out_bps = av_get_bits_per_sample_fmt(avctx->sample_fmt) >> 3; - av_log(s->avctx, AV_LOG_DEBUG, "%d channels, %d bits/sample, block align = %d, sample rate = %d\n", - s->channels, s->bits, s->block_align, avctx->sample_rate); + av_log(avctx, AV_LOG_DEBUG, "%d channels, %d bits/sample, " + "block align = %d, sample rate = %d\n", + avctx->channels, avctx->bits_per_coded_sample, avctx->block_align, + avctx->sample_rate); return 0; } @@ -477,25 +478,22 @@ static void vmdaudio_decode_audio(VmdAudioContext *s, unsigned char *data, } static int vmdaudio_loadsound(VmdAudioContext *s, unsigned char *data, - const uint8_t *buf, int silence, int data_size) + const uint8_t *buf, int silent_chunks, int data_size) { - int i; + int silent_size = s->avctx->block_align * silent_chunks * s->out_bps; - if (silence) { - memset(data, 0, data_size * 2); - } else { - if (s->bits == 16) - vmdaudio_decode_audio(s, data, buf, data_size, s->channels == 2); - else { - /* copy the data but convert it to signed */ - for (i = 0; i < data_size; i++){ - *data++ = buf[i] + 0x80; - *data++ = buf[i] + 0x80; - } - } + if (silent_chunks) { + memset(data, s->out_bps == 2 ? 0x00 : 0x80, silent_size); + data += silent_size; + } + if (s->avctx->bits_per_coded_sample == 16) + vmdaudio_decode_audio(s, data, buf, data_size, s->avctx->channels == 2); + else { + /* just copy the data */ + memcpy(data, buf, data_size); } - return data_size * 2; + return silent_size + data_size * s->out_bps; } static int vmdaudio_decode_frame(AVCodecContext *avctx, @@ -505,7 +503,7 @@ static int vmdaudio_decode_frame(AVCodecContext *avctx, const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; VmdAudioContext *s = avctx->priv_data; - int block_type; + int block_type, silent_chunks; unsigned char *output_samples = (unsigned char *)data; if (buf_size < 16) { @@ -522,29 +520,23 @@ static int vmdaudio_decode_frame(AVCodecContext *avctx, buf += 16; buf_size -= 16; - if (block_type == BLOCK_TYPE_AUDIO) { - /* the chunk contains audio */ - *data_size = vmdaudio_loadsound(s, output_samples, buf, 0, buf_size); - } else if (block_type == BLOCK_TYPE_INITIAL) { - /* initial chunk, may contain audio and silence */ + silent_chunks = 0; + if (block_type == BLOCK_TYPE_INITIAL) { uint32_t flags = AV_RB32(buf); - int raw_block_size = s->block_align * - (av_get_bits_per_sample_fmt(avctx->sample_fmt) / 8); - int silent_chunks = av_popcount(flags); + silent_chunks = av_popcount(flags); buf += 4; buf_size -= 4; - if(*data_size < (s->block_align*silent_chunks + buf_size) * 2) - return -1; - *data_size = 0; - memset(output_samples, 0, raw_block_size * silent_chunks); - output_samples += raw_block_size * silent_chunks; - *data_size = raw_block_size * silent_chunks; - *data_size += vmdaudio_loadsound(s, output_samples, buf, 0, buf_size); } else if (block_type == BLOCK_TYPE_SILENCE) { - /* silent chunk */ - *data_size = vmdaudio_loadsound(s, output_samples, buf, 1, s->block_align); + silent_chunks = 1; + buf_size = 0; // should already be zero but set it just to be sure } + /* ensure output buffer is large enough */ + if (*data_size < (avctx->block_align*silent_chunks + buf_size) * s->out_bps) + return -1; + + *data_size = vmdaudio_loadsound(s, output_samples, buf, silent_chunks, buf_size); + return avpkt->size; }