Commit 6deb979d authored by banan's avatar banan

Cook stereo (MONO_COOK2) bugfix, by Ian Braithwaite.

ian at braithwaite dot dk.


git-svn-id: file:///var/local/repositories/ffmpeg/trunk@7738 9553f0bf-9b14-0410-a0b8-cfaf0461ba5b
parent 216088ab
...@@ -277,16 +277,30 @@ static int init_cook_mlt(COOKContext *q) { ...@@ -277,16 +277,30 @@ static int init_cook_mlt(COOKContext *q) {
/** /**
* Cook indata decoding, every 32 bits are XORed with 0x37c511f2. * Cook indata decoding, every 32 bits are XORed with 0x37c511f2.
* Why? No idea, some checksum/error detection method maybe. * Why? No idea, some checksum/error detection method maybe.
*
* Out buffer size: extra bytes are needed to cope with
* padding/missalignment.
* Subpackets passed to the decoder can contain two, consecutive
* half-subpackets, of identical but arbitrary size.
* 1234 1234 1234 1234 extraA extraB
* Case 1: AAAA BBBB 0 0
* Case 2: AAAA ABBB BB-- 3 3
* Case 3: AAAA AABB BBBB 2 2
* Case 4: AAAA AAAB BBBB BB-- 1 5
*
* Nice way to waste CPU cycles. * Nice way to waste CPU cycles.
* *
* @param in pointer to 32bit array of indata * @param inbuffer pointer to byte array of indata
* @param bits amount of bits * @param out pointer to byte array of outdata
* @param out pointer to 32bit array of outdata * @param bytes number of bytes
*/ */
#define DECODE_BYTES_PAD1(bytes) (3 - ((bytes)+3) % 4)
#define DECODE_BYTES_PAD2(bytes) ((bytes) % 4 + DECODE_BYTES_PAD1(2 * (bytes)))
static inline void decode_bytes(uint8_t* inbuffer, uint8_t* out, int bytes){ static inline int decode_bytes(uint8_t* inbuffer, uint8_t* out, int bytes){
int i; int i, off;
uint32_t* buf = (uint32_t*) inbuffer; uint32_t c;
uint32_t* buf;
uint32_t* obuf = (uint32_t*) out; uint32_t* obuf = (uint32_t*) out;
/* FIXME: 64 bit platforms would be able to do 64 bits at a time. /* FIXME: 64 bit platforms would be able to do 64 bits at a time.
* I'm too lazy though, should be something like * I'm too lazy though, should be something like
...@@ -294,14 +308,14 @@ static inline void decode_bytes(uint8_t* inbuffer, uint8_t* out, int bytes){ ...@@ -294,14 +308,14 @@ static inline void decode_bytes(uint8_t* inbuffer, uint8_t* out, int bytes){
* (int64_t)out[i] = 0x37c511f237c511f2^be2me_64(int64_t)in[i]); * (int64_t)out[i] = 0x37c511f237c511f2^be2me_64(int64_t)in[i]);
* Buffer alignment needs to be checked. */ * Buffer alignment needs to be checked. */
off = (uint32_t)inbuffer % 4;
buf = (uint32_t*) (inbuffer - off);
c = be2me_32((0x37c511f2 >> (off*8)) | (0x37c511f2 << (32-(off*8))));
bytes += 3 + off;
for (i = 0; i < bytes/4; i++)
obuf[i] = c ^ buf[i];
for(i=0 ; i<bytes/4 ; i++){ return off;
#ifdef WORDS_BIGENDIAN
obuf[i] = 0x37c511f2^buf[i];
#else
obuf[i] = 0xf211c537^buf[i];
#endif
}
} }
/** /**
...@@ -947,6 +961,28 @@ static void joint_decode(COOKContext *q, float* mlt_buffer1, ...@@ -947,6 +961,28 @@ static void joint_decode(COOKContext *q, float* mlt_buffer1,
} }
} }
/**
* First part of subpacket decoding:
* decode raw stream bytes and read gain info.
*
* @param q pointer to the COOKContext
* @param inbuffer pointer to raw stream data
* @param gain_ptr array of current/prev gain pointers
*/
static inline void
decode_bytes_and_gain(COOKContext *q, uint8_t *inbuffer, COOKgain *gain_ptr)
{
int offset;
offset = decode_bytes(inbuffer, q->decoded_bytes_buffer,
q->bits_per_subpacket/8);
init_get_bits(&q->gb, q->decoded_bytes_buffer + offset,
q->bits_per_subpacket);
decode_gain_info(&q->gb, gain_ptr);
}
/** /**
* Cook subpacket decoding. This function returns one decoded subpacket, * Cook subpacket decoding. This function returns one decoded subpacket,
* usually 1024 samples per channel. * usually 1024 samples per channel.
...@@ -970,11 +1006,9 @@ static int decode_subpacket(COOKContext *q, uint8_t *inbuffer, ...@@ -970,11 +1006,9 @@ static int decode_subpacket(COOKContext *q, uint8_t *inbuffer,
// } // }
// av_log(NULL, AV_LOG_ERROR, "\n"); // av_log(NULL, AV_LOG_ERROR, "\n");
decode_bytes(inbuffer, q->decoded_bytes_buffer, sub_packet_size);
init_get_bits(&q->gb, q->decoded_bytes_buffer, sub_packet_size*8);
decode_gain_info(&q->gb, &q->gain_current);
if(q->nb_channels==2 && q->joint_stereo==1){ if(q->nb_channels==2 && q->joint_stereo==1){
decode_bytes_and_gain(q, inbuffer, &q->gain_current);
joint_decode(q, q->decode_buf_ptr[0], q->decode_buf_ptr[2]); joint_decode(q, q->decode_buf_ptr[0], q->decode_buf_ptr[2]);
/* Swap buffer pointers. */ /* Swap buffer pointers. */
...@@ -1014,6 +1048,8 @@ static int decode_subpacket(COOKContext *q, uint8_t *inbuffer, ...@@ -1014,6 +1048,8 @@ static int decode_subpacket(COOKContext *q, uint8_t *inbuffer,
} else if (q->nb_channels==2 && q->joint_stereo==0) { } else if (q->nb_channels==2 && q->joint_stereo==0) {
/* channel 0 */ /* channel 0 */
decode_bytes_and_gain(q, inbuffer, &q->gain_current);
mono_decode(q, q->decode_buf_ptr2[0]); mono_decode(q, q->decode_buf_ptr2[0]);
tmp_ptr = q->decode_buf_ptr2[0]; tmp_ptr = q->decode_buf_ptr2[0];
...@@ -1035,17 +1071,17 @@ static int decode_subpacket(COOKContext *q, uint8_t *inbuffer, ...@@ -1035,17 +1071,17 @@ static int decode_subpacket(COOKContext *q, uint8_t *inbuffer,
value = lrintf(q->mono_mdct_output[j]); value = lrintf(q->mono_mdct_output[j]);
if(value < -32768) value = -32768; if(value < -32768) value = -32768;
else if(value > 32767) value = 32767; else if(value > 32767) value = 32767;
outbuffer[2*j+1] = value; outbuffer[2*j] = value;
} }
/* channel 1 */ /* channel 1 */
//av_log(NULL,AV_LOG_ERROR,"bits = %d\n",get_bits_count(&q->gb)); //av_log(NULL,AV_LOG_ERROR,"bits = %d\n",get_bits_count(&q->gb));
init_get_bits(&q->gb, q->decoded_bytes_buffer, sub_packet_size*8+q->bits_per_subpacket); decode_bytes_and_gain(q, inbuffer + sub_packet_size/2,
&q->gain_channel2[0]);
q->gain_now_ptr = &q->gain_channel2[0]; q->gain_now_ptr = &q->gain_channel2[0];
q->gain_previous_ptr = &q->gain_channel2[1]; q->gain_previous_ptr = &q->gain_channel2[1];
decode_gain_info(&q->gb, &q->gain_channel2[0]);
mono_decode(q, q->decode_buf_ptr[0]); mono_decode(q, q->decode_buf_ptr[0]);
tmp_ptr = q->decode_buf_ptr[0]; tmp_ptr = q->decode_buf_ptr[0];
...@@ -1067,10 +1103,12 @@ static int decode_subpacket(COOKContext *q, uint8_t *inbuffer, ...@@ -1067,10 +1103,12 @@ static int decode_subpacket(COOKContext *q, uint8_t *inbuffer,
value = lrintf(q->mono_mdct_output[j]); value = lrintf(q->mono_mdct_output[j]);
if(value < -32768) value = -32768; if(value < -32768) value = -32768;
else if(value > 32767) value = 32767; else if(value > 32767) value = 32767;
outbuffer[2*j] = value; outbuffer[2*j+1] = value;
} }
} else { } else {
decode_bytes_and_gain(q, inbuffer, &q->gain_current);
mono_decode(q, q->decode_buf_ptr[0]); mono_decode(q, q->decode_buf_ptr[0]);
/* Swap buffer pointers. */ /* Swap buffer pointers. */
...@@ -1258,9 +1296,21 @@ static int cook_decode_init(AVCodecContext *avctx) ...@@ -1258,9 +1296,21 @@ static int cook_decode_init(AVCodecContext *avctx)
if(avctx->block_align >= UINT_MAX/2) if(avctx->block_align >= UINT_MAX/2)
return -1; return -1;
/* Pad the databuffer with FF_INPUT_BUFFER_PADDING_SIZE, /* Pad the databuffer with:
this is for the bitstreamreader. */ DECODE_BYTES_PAD1 or DECODE_BYTES_PAD2 for decode_bytes(),
if ((q->decoded_bytes_buffer = av_mallocz((avctx->block_align+(4-avctx->block_align%4) + FF_INPUT_BUFFER_PADDING_SIZE)*sizeof(uint8_t))) == NULL) FF_INPUT_BUFFER_PADDING_SIZE, for the bitstreamreader. */
if (q->nb_channels==2 && q->joint_stereo==0) {
q->decoded_bytes_buffer =
av_mallocz(avctx->block_align/2
+ DECODE_BYTES_PAD2(avctx->block_align/2)
+ FF_INPUT_BUFFER_PADDING_SIZE);
} else {
q->decoded_bytes_buffer =
av_mallocz(avctx->block_align
+ DECODE_BYTES_PAD1(avctx->block_align)
+ FF_INPUT_BUFFER_PADDING_SIZE);
}
if (q->decoded_bytes_buffer == NULL)
return -1; return -1;
q->decode_buf_ptr[0] = q->decode_buffer_1; q->decode_buf_ptr[0] = q->decode_buffer_1;
......
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