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;