summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKostya Shishkov <kostya.shishkov@gmail.com>2009-01-21 13:24:35 +0000
committerKostya Shishkov <kostya.shishkov@gmail.com>2009-01-21 13:24:35 +0000
commit716ba2d01c6818eb402484cdf0403515b9e49ba8 (patch)
tree22896d19c573a974a16e41182c837d76ae5025f0
parent33054e35e30ab69b600964b5f2ceefd7e4624033 (diff)
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
-rw-r--r--libavcodec/vmdav.c45
-rw-r--r--libavformat/sierravmd.c29
2 files changed, 28 insertions, 46 deletions
diff --git a/libavcodec/vmdav.c b/libavcodec/vmdav.c
index 48f76bfaf3..ed9ba28dac 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 83262f8f1a..82a7fea16a 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;