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. Originally committed as revision 16708 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
@@ -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,
|
|||||||
}
|
}
|
||||||
|
|
||||||
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,
|
|||||||
|
|
||||||
/* 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,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
|||||||
|
|
||||||
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,
|
|||||||
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,
|
|||||||
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;
|
||||||
|
Reference in New Issue
Block a user