[Ffmpeg-devel] wma v2 decoding - attempt at fixing
Reimar Döffinger
Reimar.Doeffinger
Sun Dec 25 19:54:08 CET 2005
Hi,
the attached patch is what my test resulted in so far.
The sample I looked at was:
With this patch, about 10% instead of 0% of it decode correctly.
The patch is crappy, ugly and sure opens a few security holes, but since
I won't work on it for the next few weeks (on holiday without PC :-) ),
I thought posting it won't hurt. Hopefully someone can find the real
fix ;-)...
Greetings,
Reimar D?ffinger
-------------- next part --------------
Index: libavcodec/wmadec.c
===================================================================
RCS file: /cvsroot/ffmpeg/ffmpeg/libavcodec/wmadec.c,v
retrieving revision 1.26
diff -u -r1.26 wmadec.c
--- libavcodec/wmadec.c 17 Dec 2005 18:14:31 -0000 1.26
+++ libavcodec/wmadec.c 25 Dec 2005 18:53:18 -0000
@@ -34,6 +34,7 @@
#include "avcodec.h"
#include "bitstream.h"
#include "dsputil.h"
+#undef printf
/* size of blocks */
#define BLOCK_MIN_BITS 7
@@ -98,6 +99,7 @@
int block_len; /* block length in samples */
int block_num; /* block number in current frame */
int block_pos; /* current position in frame */
+ int block_noncoded;
uint8_t ms_stereo; /* true if mid/side stereo mode */
uint8_t channel_coded[MAX_CHANNELS]; /* true if channel is coded */
float exponents[MAX_CHANNELS][BLOCK_MAX_SIZE] __attribute__((aligned(16)));
@@ -108,7 +110,7 @@
float *windows[BLOCK_NB_SIZES];
FFTSample mdct_tmp[BLOCK_MAX_SIZE] __attribute__((aligned(16))); /* temporary storage for imdct */
/* output buffer for one frame and the last for IMDCT windowing */
- float frame_out[MAX_CHANNELS][BLOCK_MAX_SIZE * 2] __attribute__((aligned(16)));
+ float frame_out[MAX_CHANNELS][BLOCK_MAX_SIZE * 32] __attribute__((aligned(16)));
/* last frame info */
uint8_t last_superframe[MAX_CODED_SUPERFRAME_SIZE + 4]; /* padding added */
int last_bitoffset;
@@ -241,6 +243,7 @@
s->use_bit_reservoir = flags2 & 0x0002;
s->use_variable_block_len = flags2 & 0x0004;
+ s->sample_rate *= 2;
/* compute MDCT block size */
if (s->sample_rate <= 16000) {
s->frame_len_bits = 9;
@@ -250,12 +253,15 @@
} else {
s->frame_len_bits = 11;
}
+printf("info: %i %i %i %i\n", s->sample_rate, s->version, s->bit_rate, s->nb_channels);
+ s->sample_rate /= 2;
s->frame_len = 1 << s->frame_len_bits;
if (s->use_variable_block_len) {
int nb_max, nb;
nb = ((flags2 >> 3) & 3) + 1;
if ((s->bit_rate / s->nb_channels) >= 32000)
nb += 2;
+ nb++;
nb_max = s->frame_len_bits - BLOCK_MIN_BITS;
if (nb > nb_max)
nb = nb_max;
@@ -518,6 +524,8 @@
&coef_vlcs[coef_vlc_table * 2]);
init_coef_vlc(&s->coef_vlc[1], &s->run_table[1], &s->level_table[1],
&coef_vlcs[coef_vlc_table * 2 + 1]);
+ s->sample_rate *= 2;
+ avctx->sample_rate = s->sample_rate;
return 0;
}
@@ -716,6 +724,7 @@
tprintf("***decode_block: %d:%d\n", s->frame_count - 1, s->block_num);
#endif
+printf("1\n");
/* compute current block length */
if (s->use_variable_block_len) {
n = av_log2(s->nb_block_sizes - 1) + 1;
@@ -723,10 +732,12 @@
if (s->reset_block_lengths) {
s->reset_block_lengths = 0;
v = get_bits(&s->gb, n);
+printf("1b: %i, %i\n", v, s->nb_block_sizes);
if (v >= s->nb_block_sizes)
return -1;
s->prev_block_len_bits = s->frame_len_bits - v;
v = get_bits(&s->gb, n);
+printf("1c: %i, %i\n", v, s->nb_block_sizes);
if (v >= s->nb_block_sizes)
return -1;
s->block_len_bits = s->frame_len_bits - v;
@@ -736,6 +747,7 @@
s->block_len_bits = s->next_block_len_bits;
}
v = get_bits(&s->gb, n);
+printf("1d: %i, %i\n", v, s->nb_block_sizes);
if (v >= s->nb_block_sizes)
return -1;
s->next_block_len_bits = s->frame_len_bits - v;
@@ -745,11 +757,7 @@
s->prev_block_len_bits = s->frame_len_bits;
s->block_len_bits = s->frame_len_bits;
}
-
- /* now check if the block length is coherent with the frame length */
s->block_len = 1 << s->block_len_bits;
- if ((s->block_pos + s->block_len) > s->frame_len)
- return -1;
if (s->nb_channels == 2) {
s->ms_stereo = get_bits(&s->gb, 1);
@@ -762,8 +770,17 @@
}
/* if no channel coded, no need to go further */
/* XXX: fix potential framing problems */
- if (!v)
- goto next;
+ if (!v) {
+printf("non coded: %i %i\n", s->block_len, s->ms_stereo);
+ s->block_noncoded += s->block_len;
+ return 1;
+// goto next;
+ }
+
+ /* now check if the block length is coherent with the frame length */
+printf("2: %i %i %i %i\n", s->block_pos, s->block_len, s->block_pos - s->block_noncoded + s->block_len, s->frame_len);
+// if ((s->block_pos - s->block_noncoded + s->block_len) > s->frame_len)
+// return -1;
bsize = s->frame_len_bits - s->block_len_bits;
@@ -793,6 +810,7 @@
for(ch = 0; ch < s->nb_channels; ch++)
nb_coefs[ch] = n;
+printf("2b\n");
/* complex coding */
if (s->use_noise_coding) {
@@ -838,6 +856,7 @@
parse_exponents = get_bits(&s->gb, 1);
}
+printf("3\n");
if (parse_exponents) {
for(ch = 0; ch < s->nb_channels; ch++) {
if (s->channel_coded[ch]) {
@@ -858,6 +877,7 @@
}
}
+printf("4\n");
/* parse spectral coefficients : just RLE encoding */
for(ch = 0; ch < s->nb_channels; ch++) {
if (s->channel_coded[ch]) {
@@ -899,7 +919,7 @@
level = -level;
ptr += run;
if (ptr >= eptr)
- return -1;
+ break;
*ptr++ = level;
/* NOTE: EOB can be omitted */
if (ptr >= eptr)
@@ -1018,6 +1038,7 @@
}
}
+printf("5\n");
#ifdef TRACE
for(ch = 0; ch < s->nb_channels; ch++) {
if (s->channel_coded[ch]) {
@@ -1093,6 +1114,7 @@
}
+printf("6\n");
for(ch = 0; ch < s->nb_channels; ch++) {
if (s->channel_coded[ch]) {
FFTSample output[BLOCK_MAX_SIZE * 2] __attribute__((aligned(16)));
@@ -1134,7 +1156,7 @@
/* update block number */
s->block_num++;
s->block_pos += s->block_len;
- if (s->block_pos >= s->frame_len)
+ if (s->block_pos - s->block_noncoded >= s->frame_len)
return 1;
else
return 0;
@@ -1154,16 +1176,18 @@
/* read each block */
s->block_num = 0;
s->block_pos = 0;
+ s->block_noncoded = 0;
for(;;) {
ret = wma_decode_block(s);
if (ret < 0)
- return -1;
- if (ret)
+printf("fail!\n");
+// return -1;
+ if (ret > 0)
break;
}
/* convert frame to integer */
- n = s->frame_len;
+ n = s->block_pos;//s->frame_len;
incr = s->nb_channels;
for(ch = 0; ch < s->nb_channels; ch++) {
ptr = samples + ch;
@@ -1244,7 +1268,7 @@
current one */
if (wma_decode_frame(s, samples) < 0)
goto fail;
- samples += s->nb_channels * s->frame_len;
+ samples += s->nb_channels * s->block_pos;//s->frame_len;
}
/* read each frame starting from bit_offset */
@@ -1258,7 +1282,7 @@
for(i=0;i<nb_frames;i++) {
if (wma_decode_frame(s, samples) < 0)
goto fail;
- samples += s->nb_channels * s->frame_len;
+ samples += s->nb_channels * s->block_pos;//s->frame_len;
}
/* we copy the end of the frame in the last frame buffer */
@@ -1275,7 +1299,7 @@
/* single frame decode */
if (wma_decode_frame(s, samples) < 0)
goto fail;
- samples += s->nb_channels * s->frame_len;
+ samples += s->nb_channels * s->block_pos;//s->frame_len;
}
*data_size = (int8_t *)samples - (int8_t *)data;
return s->block_align;
More information about the ffmpeg-devel
mailing list