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, ...@@ -519,12 +519,10 @@ static int vmdaudio_decode_frame(AVCodecContext *avctx,
uint8_t *buf, int buf_size) uint8_t *buf, int buf_size)
{ {
VmdAudioContext *s = (VmdAudioContext *)avctx->priv_data; VmdAudioContext *s = (VmdAudioContext *)avctx->priv_data;
unsigned int sound_flags;
unsigned char *output_samples = (unsigned char *)data; unsigned char *output_samples = (unsigned char *)data;
/* point to the start of the encoded data */ /* point to the start of the encoded data */
unsigned char *p = buf + 16; unsigned char *p = buf + 16;
unsigned char *p_end = buf + buf_size;
if (buf_size < 16) if (buf_size < 16)
return buf_size; return buf_size;
...@@ -533,24 +531,10 @@ static int vmdaudio_decode_frame(AVCodecContext *avctx, ...@@ -533,24 +531,10 @@ static int vmdaudio_decode_frame(AVCodecContext *avctx,
/* the chunk contains audio */ /* the chunk contains audio */
*data_size = vmdaudio_loadsound(s, output_samples, p, 0); *data_size = vmdaudio_loadsound(s, output_samples, p, 0);
} else if (buf[6] == 2) { } else if (buf[6] == 2) {
/* the chunk contains audio and silence mixed together */ /* the chunk may contain audio */
sound_flags = LE_32(p);
p += 4; p += 4;
*data_size = vmdaudio_loadsound(s, output_samples, p, (buf_size == 16));
/* do something with extrabufs here? */ output_samples += (s->block_align * s->bits / 8);
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;
}
} else if (buf[6] == 3) { } else if (buf[6] == 3) {
/* silent chunk */ /* silent chunk */
*data_size = vmdaudio_loadsound(s, output_samples, p, 1); *data_size = vmdaudio_loadsound(s, output_samples, p, 1);
......
...@@ -87,6 +87,7 @@ static int vmd_read_header(AVFormatContext *s, ...@@ -87,6 +87,7 @@ static int vmd_read_header(AVFormatContext *s,
int64_t current_video_pts = 0, current_audio_pts = 0; int64_t current_video_pts = 0, current_audio_pts = 0;
unsigned char chunk[BYTES_PER_FRAME_RECORD]; unsigned char chunk[BYTES_PER_FRAME_RECORD];
int num, den; int num, den;
int sound_buffers;
/* fetch the main header, including the 2 header length bytes */ /* fetch the main header, including the 2 header length bytes */
url_fseek(pb, 0, SEEK_SET); url_fseek(pb, 0, SEEK_SET);
...@@ -146,13 +147,14 @@ static int vmd_read_header(AVFormatContext *s, ...@@ -146,13 +147,14 @@ static int vmd_read_header(AVFormatContext *s,
raw_frame_table = NULL; raw_frame_table = NULL;
vmd->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_size = vmd->frame_count * 6;
raw_frame_table = av_malloc(raw_frame_table_size); raw_frame_table = av_malloc(raw_frame_table_size);
if(vmd->frame_count * vmd->frames_per_block >= UINT_MAX / sizeof(vmd_frame_t)){ 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"); av_log(s, AV_LOG_ERROR, "vmd->frame_count * vmd->frames_per_block too large\n");
return -1; 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) { if (!raw_frame_table || !vmd->frame_table) {
av_free(raw_frame_table); av_free(raw_frame_table);
av_free(vmd->frame_table); av_free(vmd->frame_table);
...@@ -182,14 +184,43 @@ static int vmd_read_header(AVFormatContext *s, ...@@ -182,14 +184,43 @@ static int vmd_read_header(AVFormatContext *s,
continue; continue;
switch(type) { switch(type) {
case 1: /* Audio Chunk */ 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].frame_offset = current_offset;
vmd->frame_table[total_frames].stream_index = vmd->audio_stream_index; vmd->frame_table[total_frames].stream_index = vmd->audio_stream_index;
vmd->frame_table[total_frames].frame_size = size; vmd->frame_table[total_frames].frame_size = size;
memcpy(vmd->frame_table[total_frames].frame_record, chunk, BYTES_PER_FRAME_RECORD); memcpy(vmd->frame_table[total_frames].frame_record, chunk, BYTES_PER_FRAME_RECORD);
vmd->frame_table[total_frames].pts = current_audio_pts; vmd->frame_table[total_frames].pts = current_audio_pts;
total_frames++; total_frames++;
/* first audio chunk contains several audio buffers */ current_audio_pts += pts_inc;
current_audio_pts += (current_audio_pts == 0) ? LE_16(&vmd->vmd_header[808]) * pts_inc : 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; break;
case 2: /* Video Chunk */ case 2: /* Video Chunk */
vmd->frame_table[total_frames].frame_offset = current_offset; 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