summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKostya Shishkov <kostya.shishkov@gmail.com>2006-11-19 05:30:43 +0000
committerKostya Shishkov <kostya.shishkov@gmail.com>2006-11-19 05:30:43 +0000
commitc8f9f9b91a3d3254e62f4fbcd6065a504164b06b (patch)
tree5ad5eb7117e47080e3f328e2750f2f3c300bc441
parent5836d158b61241a556c8db53314182e4d78a5a32 (diff)
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
-rw-r--r--libavcodec/vmdav.c22
-rw-r--r--libavformat/sierravmd.c37
2 files changed, 37 insertions, 22 deletions
diff --git a/libavcodec/vmdav.c b/libavcodec/vmdav.c
index 394d6d50d8..a9937144e4 100644
--- a/libavcodec/vmdav.c
+++ b/libavcodec/vmdav.c
@@ -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);
diff --git a/libavformat/sierravmd.c b/libavformat/sierravmd.c
index bdb18072f7..a056d9fbf3 100644
--- a/libavformat/sierravmd.c
+++ b/libavformat/sierravmd.c
@@ -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;