Commit c8f9f9b9 authored by Kostya Shishkov's avatar Kostya Shishkov

Divide first audio buffer chunk into atomary bufffers.

This slightly simplifies decoder and removes potential
audio buffer overrun.

Originally committed as revision 7121 to svn://svn.ffmpeg.org/ffmpeg/trunk
parent 5836d158
......@@ -519,12 +519,10 @@ static int vmdaudio_decode_frame(AVCodecContext *avctx,
uint8_t *buf, int buf_size)
{
VmdAudioContext *s = (VmdAudioContext *)avctx->priv_data;
unsigned int sound_flags;
unsigned char *output_samples = (unsigned char *)data;
/* point to the start of the encoded data */
unsigned char *p = buf + 16;
unsigned char *p_end = buf + buf_size;
if (buf_size < 16)
return buf_size;
......@@ -533,24 +531,10 @@ static int vmdaudio_decode_frame(AVCodecContext *avctx,
/* the chunk contains audio */
*data_size = vmdaudio_loadsound(s, output_samples, p, 0);
} else if (buf[6] == 2) {
/* the chunk contains audio and silence mixed together */
sound_flags = LE_32(p);
/* the chunk may contain audio */
p += 4;
/* do something with extrabufs here? */
while (p < p_end) {
if (sound_flags & 0x01)
/* silence */
*data_size += vmdaudio_loadsound(s, output_samples, p, 1);
else {
/* audio */
*data_size += vmdaudio_loadsound(s, output_samples, p, 0);
p += s->block_align;
}
output_samples += (s->block_align * s->bits / 8);
sound_flags >>= 1;
}
*data_size = vmdaudio_loadsound(s, output_samples, p, (buf_size == 16));
output_samples += (s->block_align * s->bits / 8);
} else if (buf[6] == 3) {
/* silent chunk */
*data_size = vmdaudio_loadsound(s, output_samples, p, 1);
......
......@@ -87,6 +87,7 @@ static int vmd_read_header(AVFormatContext *s,
int64_t current_video_pts = 0, current_audio_pts = 0;
unsigned char chunk[BYTES_PER_FRAME_RECORD];
int num, den;
int sound_buffers;
/* fetch the main header, including the 2 header length bytes */
url_fseek(pb, 0, SEEK_SET);
......@@ -146,13 +147,14 @@ static int vmd_read_header(AVFormatContext *s,
raw_frame_table = NULL;
vmd->frame_table = NULL;
sound_buffers = LE_16(&vmd->vmd_header[808]);
raw_frame_table_size = vmd->frame_count * 6;
raw_frame_table = av_malloc(raw_frame_table_size);
if(vmd->frame_count * vmd->frames_per_block >= UINT_MAX / sizeof(vmd_frame_t)){
av_log(s, AV_LOG_ERROR, "vmd->frame_count * vmd->frames_per_block too large\n");
return -1;
}
vmd->frame_table = av_malloc(vmd->frame_count * vmd->frames_per_block * sizeof(vmd_frame_t));
vmd->frame_table = av_malloc((vmd->frame_count * vmd->frames_per_block + sound_buffers) * sizeof(vmd_frame_t));
if (!raw_frame_table || !vmd->frame_table) {
av_free(raw_frame_table);
av_free(vmd->frame_table);
......@@ -182,14 +184,43 @@ static int vmd_read_header(AVFormatContext *s,
continue;
switch(type) {
case 1: /* Audio Chunk */
/* 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;
memcpy(vmd->frame_table[total_frames].frame_record, chunk, BYTES_PER_FRAME_RECORD);
vmd->frame_table[total_frames].pts = current_audio_pts;
total_frames++;
/* first audio chunk contains several audio buffers */
current_audio_pts += (current_audio_pts == 0) ? LE_16(&vmd->vmd_header[808]) * pts_inc : pts_inc;
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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment