You've already forked FFmpeg
mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-08-15 14:13:16 +02:00
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
This commit is contained in:
@@ -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,
|
|||||||
/* 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,
|
|||||||
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,
|
|||||||
|
|
||||||
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,
|
|||||||
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;
|
||||||
|
Reference in New Issue
Block a user