From 716ba2d01c6818eb402484cdf0403515b9e49ba8 Mon Sep 17 00:00:00 2001 From: Kostya Shishkov Date: Wed, 21 Jan 2009 13:24:35 +0000 Subject: [PATCH] VMD first chunk of audio is not coded as many separate chunks of block_align size. Thus, make demuxer and decoder handle it as a whole. Originally committed as revision 16708 to svn://svn.ffmpeg.org/ffmpeg/trunk --- libavcodec/vmdav.c | 45 ++++++++++++++++++++++++++++----------------- libavformat/sierravmd.c | 29 ----------------------------- 2 files changed, 28 insertions(+), 46 deletions(-) diff --git a/libavcodec/vmdav.c b/libavcodec/vmdav.c index 48f76bf..ed9ba28 100644 --- a/libavcodec/vmdav.c +++ b/libavcodec/vmdav.c @@ -456,13 +456,13 @@ static av_cold int vmdaudio_decode_init(AVCodecContext *avctx) } static void vmdaudio_decode_audio(VmdAudioContext *s, unsigned char *data, - const uint8_t *buf, int stereo) + const uint8_t *buf, int buf_size, int stereo) { int i; int chan = 0; int16_t *out = (int16_t*)data; - for(i = 0; i < s->block_align; i++) { + for(i = 0; i < buf_size; i++) { if(buf[i] & 0x80) s->predictors[chan] -= vmdaudio_table[buf[i] & 0x7F]; else @@ -474,7 +474,7 @@ 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) + const uint8_t *buf, int silence, int data_size) { int bytes_decoded = 0; int i; @@ -485,30 +485,30 @@ static int vmdaudio_loadsound(VmdAudioContext *s, unsigned char *data, /* stereo handling */ if (silence) { - memset(data, 0, s->block_align * 2); + memset(data, 0, data_size * 2); } else { if (s->bits == 16) - vmdaudio_decode_audio(s, data, buf, 1); + vmdaudio_decode_audio(s, data, buf, data_size, 1); else { /* copy the data but convert it to signed */ - for (i = 0; i < s->block_align; i++){ + for (i = 0; i < data_size; i++){ *data++ = buf[i] + 0x80; *data++ = buf[i] + 0x80; } } } } else { - bytes_decoded = s->block_align * 2; + bytes_decoded = data_size * 2; /* mono handling */ if (silence) { - memset(data, 0, s->block_align * 2); + memset(data, 0, data_size * 2); } else { if (s->bits == 16) { - vmdaudio_decode_audio(s, data, buf, 0); + vmdaudio_decode_audio(s, data, buf, data_size, 0); } else { /* copy the data but convert it to signed */ - for (i = 0; i < s->block_align; i++){ + for (i = 0; i < data_size; i++){ *data++ = buf[i] + 0x80; *data++ = buf[i] + 0x80; } @@ -516,7 +516,7 @@ static int vmdaudio_loadsound(VmdAudioContext *s, unsigned char *data, } } - return s->block_align * 2; + return data_size * 2; } static int vmdaudio_decode_frame(AVCodecContext *avctx, @@ -534,15 +534,26 @@ static int vmdaudio_decode_frame(AVCodecContext *avctx, if (buf[6] == 1) { /* the chunk contains audio */ - *data_size = vmdaudio_loadsound(s, output_samples, p, 0); + *data_size = vmdaudio_loadsound(s, output_samples, p, 0, buf_size - 16); } else if (buf[6] == 2) { - /* the chunk may contain audio */ - p += 4; - *data_size = vmdaudio_loadsound(s, output_samples, p, (buf_size == 16)); - output_samples += (s->block_align * s->bits / 8); + /* initial chunk, may contain audio and silence */ + uint32_t flags = AV_RB32(p); + int raw_block_size = s->block_align * s->bits / 8; + int silent_chunks; + if(flags == 0xFFFFFFFF) + silent_chunks = 32; + else + silent_chunks = av_log2(flags + 1); + if(*data_size < (s->block_align*silent_chunks + buf_size - 20) * 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, p + 4, 0, buf_size - 20); } else if (buf[6] == 3) { /* silent chunk */ - *data_size = vmdaudio_loadsound(s, output_samples, p, 1); + *data_size = vmdaudio_loadsound(s, output_samples, p, 1, 0); } return buf_size; diff --git a/libavformat/sierravmd.c b/libavformat/sierravmd.c index 83262f8..82a7fea 100644 --- a/libavformat/sierravmd.c +++ b/libavformat/sierravmd.c @@ -193,7 +193,6 @@ static int vmd_read_header(AVFormatContext *s, case 1: /* Audio Chunk */ if (!st) break; /* first audio chunk contains several audio buffers */ - if(current_audio_pts){ vmd->frame_table[total_frames].frame_offset = current_offset; vmd->frame_table[total_frames].stream_index = vmd->audio_stream_index; vmd->frame_table[total_frames].frame_size = size; @@ -201,34 +200,6 @@ static int vmd_read_header(AVFormatContext *s, vmd->frame_table[total_frames].pts = current_audio_pts; total_frames++; current_audio_pts += pts_inc; - }else{ - uint32_t flags; - int k; - int noff; - int64_t pos; - - pos = url_ftell(pb); - url_fseek(pb, current_offset, SEEK_SET); - flags = get_le32(pb); - noff = 4; - url_fseek(pb, pos, SEEK_SET); - av_log(s, AV_LOG_DEBUG, "Sound mapping = %08X (%i bufs)\n", flags, sound_buffers); - for(k = 0; k < sound_buffers - 1; k++){ - if(flags & 1) { /* silent block */ - vmd->frame_table[total_frames].frame_size = 0; - }else{ - vmd->frame_table[total_frames].frame_size = st->codec->block_align + (st->codec->block_align & 1); - } - noff += vmd->frame_table[total_frames].frame_size; - vmd->frame_table[total_frames].frame_offset = current_offset + noff; - vmd->frame_table[total_frames].stream_index = vmd->audio_stream_index; - memcpy(vmd->frame_table[total_frames].frame_record, chunk, BYTES_PER_FRAME_RECORD); - vmd->frame_table[total_frames].pts = current_audio_pts; - total_frames++; - current_audio_pts += pts_inc; - flags >>= 1; - } - } break; case 2: /* Video Chunk */ vmd->frame_table[total_frames].frame_offset = current_offset; -- 2.7.4