Commit 888c9675 authored by kostya's avatar kostya

VMD first chunk of audio is not coded as many separate chunks of block_align

size. Thus, make demuxer and decoder handle it as a whole.



git-svn-id: file:///var/local/repositories/ffmpeg/trunk@16708 9553f0bf-9b14-0410-a0b8-cfaf0461ba5b
parent 220e38f3
...@@ -456,13 +456,13 @@ static av_cold int vmdaudio_decode_init(AVCodecContext *avctx) ...@@ -456,13 +456,13 @@ static av_cold int vmdaudio_decode_init(AVCodecContext *avctx)
} }
static void vmdaudio_decode_audio(VmdAudioContext *s, unsigned char *data, static void vmdaudio_decode_audio(VmdAudioContext *s, unsigned char *data,
const uint8_t *buf, int stereo) const uint8_t *buf, int buf_size, int stereo)
{ {
int i; int i;
int chan = 0; int chan = 0;
int16_t *out = (int16_t*)data; int16_t *out = (int16_t*)data;
for(i = 0; i < s->block_align; i++) { for(i = 0; i < buf_size; i++) {
if(buf[i] & 0x80) if(buf[i] & 0x80)
s->predictors[chan] -= vmdaudio_table[buf[i] & 0x7F]; s->predictors[chan] -= vmdaudio_table[buf[i] & 0x7F];
else else
...@@ -474,7 +474,7 @@ static void vmdaudio_decode_audio(VmdAudioContext *s, unsigned char *data, ...@@ -474,7 +474,7 @@ static void vmdaudio_decode_audio(VmdAudioContext *s, unsigned char *data,
} }
static int vmdaudio_loadsound(VmdAudioContext *s, unsigned char *data, static int vmdaudio_loadsound(VmdAudioContext *s, unsigned char *data,
const uint8_t *buf, int silence) const uint8_t *buf, int silence, int data_size)
{ {
int bytes_decoded = 0; int bytes_decoded = 0;
int i; int i;
...@@ -485,30 +485,30 @@ static int vmdaudio_loadsound(VmdAudioContext *s, unsigned char *data, ...@@ -485,30 +485,30 @@ static int vmdaudio_loadsound(VmdAudioContext *s, unsigned char *data,
/* stereo handling */ /* stereo handling */
if (silence) { if (silence) {
memset(data, 0, s->block_align * 2); memset(data, 0, data_size * 2);
} else { } else {
if (s->bits == 16) if (s->bits == 16)
vmdaudio_decode_audio(s, data, buf, 1); vmdaudio_decode_audio(s, data, buf, data_size, 1);
else { else {
/* copy the data but convert it to signed */ /* copy the data but convert it to signed */
for (i = 0; i < s->block_align; i++){ for (i = 0; i < data_size; i++){
*data++ = buf[i] + 0x80; *data++ = buf[i] + 0x80;
*data++ = buf[i] + 0x80; *data++ = buf[i] + 0x80;
} }
} }
} }
} else { } else {
bytes_decoded = s->block_align * 2; bytes_decoded = data_size * 2;
/* mono handling */ /* mono handling */
if (silence) { if (silence) {
memset(data, 0, s->block_align * 2); memset(data, 0, data_size * 2);
} else { } else {
if (s->bits == 16) { if (s->bits == 16) {
vmdaudio_decode_audio(s, data, buf, 0); vmdaudio_decode_audio(s, data, buf, data_size, 0);
} else { } else {
/* copy the data but convert it to signed */ /* copy the data but convert it to signed */
for (i = 0; i < s->block_align; i++){ for (i = 0; i < data_size; i++){
*data++ = buf[i] + 0x80; *data++ = buf[i] + 0x80;
*data++ = buf[i] + 0x80; *data++ = buf[i] + 0x80;
} }
...@@ -516,7 +516,7 @@ static int vmdaudio_loadsound(VmdAudioContext *s, unsigned char *data, ...@@ -516,7 +516,7 @@ static int vmdaudio_loadsound(VmdAudioContext *s, unsigned char *data,
} }
} }
return s->block_align * 2; return data_size * 2;
} }
static int vmdaudio_decode_frame(AVCodecContext *avctx, static int vmdaudio_decode_frame(AVCodecContext *avctx,
...@@ -534,15 +534,26 @@ static int vmdaudio_decode_frame(AVCodecContext *avctx, ...@@ -534,15 +534,26 @@ static int vmdaudio_decode_frame(AVCodecContext *avctx,
if (buf[6] == 1) { if (buf[6] == 1) {
/* 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, buf_size - 16);
} else if (buf[6] == 2) { } else if (buf[6] == 2) {
/* the chunk may contain audio */ /* initial chunk, may contain audio and silence */
p += 4; uint32_t flags = AV_RB32(p);
*data_size = vmdaudio_loadsound(s, output_samples, p, (buf_size == 16)); int raw_block_size = s->block_align * s->bits / 8;
output_samples += (s->block_align * s->bits / 8); int silent_chunks;
if(flags == 0xFFFFFFFF)
silent_chunks = 32;
else
silent_chunks = av_log2(flags + 1);
if(*data_size < (s->block_align*silent_chunks + buf_size - 20) * 2)
return -1;
*data_size = 0;
memset(output_samples, 0, raw_block_size * silent_chunks);
output_samples += raw_block_size * silent_chunks;
*data_size = raw_block_size * silent_chunks;
*data_size += vmdaudio_loadsound(s, output_samples, p + 4, 0, buf_size - 20);
} 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, 0);
} }
return buf_size; return buf_size;
......
...@@ -193,7 +193,6 @@ static int vmd_read_header(AVFormatContext *s, ...@@ -193,7 +193,6 @@ static int vmd_read_header(AVFormatContext *s,
case 1: /* Audio Chunk */ case 1: /* Audio Chunk */
if (!st) break; if (!st) break;
/* first audio chunk contains several audio buffers */ /* 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;
...@@ -201,34 +200,6 @@ static int vmd_read_header(AVFormatContext *s, ...@@ -201,34 +200,6 @@ static int vmd_read_header(AVFormatContext *s,
vmd->frame_table[total_frames].pts = current_audio_pts; vmd->frame_table[total_frames].pts = current_audio_pts;
total_frames++; total_frames++;
current_audio_pts += 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; 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