Index: bitstream.h =================================================================== --- bitstream.h (revision 0) +++ bitstream.h (revision 0) @@ -0,0 +1,1001 @@ +/* + * copyright (c) 2004 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file bitstream.h + * bitstream api header. + */ + +#ifndef BITSTREAM_H +#define BITSTREAM_H + +#ifndef av_always_inline +#define av_always_inline inline +#endif +#ifndef attribute_deprecated +#define attribute_deprecated +#endif + +#ifdef CPU_ARM +#define CONFIG_ALIGN 1 +#endif + +#ifdef ROCKBOX_BIG_ENDIAN +#define WORDS_BIGENDIAN +#endif + +#include +#include +#include "bswap.h" + + + +extern const uint8_t ff_log2_tab[256]; + + +/*misc utility functions added to make it compile */ +/*static inline int av_log2(unsigned int v) +{ + int n; + + n = 0; + if (v & 0xffff0000) { + v >>= 16; + n += 16; + } + if (v & 0xff00) { + v >>= 8; + n += 8; + } + n += ff_log2_tab[v]; + + return n; +}*/ + + +//#include "log.h" + +#if defined(ALT_BITSTREAM_READER_LE) && !defined(ALT_BITSTREAM_READER) +#define ALT_BITSTREAM_READER +#endif + +//#define ALT_BITSTREAM_WRITER +//#define ALIGNED_BITSTREAM_WRITER +#if !defined(LIBMPEG2_BITSTREAM_READER) && !defined(A32_BITSTREAM_READER) && !defined(ALT_BITSTREAM_READER) +# ifdef ARCH_ARMV4L +# define A32_BITSTREAM_READER +# else +#define ALT_BITSTREAM_READER +//#define LIBMPEG2_BITSTREAM_READER +//#define A32_BITSTREAM_READER +# endif +#endif +#define LIBMPEG2_BITSTREAM_READER_HACK //add BERO + +extern const uint8_t ff_reverse[256]; + +#if defined(ARCH_X86) +// avoid +32 for shift optimization (gcc should do that ...) +static inline int32_t NEG_SSR32( int32_t a, int8_t s){ + asm ("sarl %1, %0\n\t" + : "+r" (a) + : "ic" ((uint8_t)(-s)) + ); + return a; +} +static inline uint32_t NEG_USR32(uint32_t a, int8_t s){ + asm ("shrl %1, %0\n\t" + : "+r" (a) + : "ic" ((uint8_t)(-s)) + ); + return a; +} +#else +# define NEG_SSR32(a,s) ((( int32_t)(a))>>(32-(s))) +# define NEG_USR32(a,s) (((uint32_t)(a))>>(32-(s))) +#endif + +/* bit output */ + +/* buf and buf_end must be present and used by every alternative writer. */ +typedef struct PutBitContext { +#ifdef ALT_BITSTREAM_WRITER + uint8_t *buf, *buf_end; + int index; +#else + uint32_t bit_buf; + int bit_left; + uint8_t *buf, *buf_ptr, *buf_end; +#endif +} PutBitContext; + +static inline void init_put_bits(PutBitContext *s, uint8_t *buffer, int buffer_size) +{ + if(buffer_size < 0) { + buffer_size = 0; + buffer = NULL; + } + + s->buf = buffer; + s->buf_end = s->buf + buffer_size; +#ifdef ALT_BITSTREAM_WRITER + s->index=0; + ((uint32_t*)(s->buf))[0]=0; +// memset(buffer, 0, buffer_size); +#else + s->buf_ptr = s->buf; + s->bit_left=32; + s->bit_buf=0; +#endif +} + +/* return the number of bits output */ +static inline int put_bits_count(PutBitContext *s) +{ +#ifdef ALT_BITSTREAM_WRITER + return s->index; +#else + return (s->buf_ptr - s->buf) * 8 + 32 - s->bit_left; +#endif +} + +/* pad the end of the output stream with zeros */ +static inline void flush_put_bits(PutBitContext *s) +{ +#ifdef ALT_BITSTREAM_WRITER + align_put_bits(s); +#else + s->bit_buf<<= s->bit_left; + while (s->bit_left < 32) { + /* XXX: should test end of buffer */ + *s->buf_ptr++=s->bit_buf >> 24; + s->bit_buf<<=8; + s->bit_left+=8; + } + s->bit_left=32; + s->bit_buf=0; +#endif +} + +void align_put_bits(PutBitContext *s); +void ff_put_string(PutBitContext * pbc, char *s, int put_zero); + +/* bit input */ +/* buffer, buffer_end and size_in_bits must be present and used by every reader */ +typedef struct GetBitContext { + const uint8_t *buffer, *buffer_end; +#ifdef ALT_BITSTREAM_READER + int index; +#elif defined LIBMPEG2_BITSTREAM_READER + uint8_t *buffer_ptr; + uint32_t cache; + int bit_count; +#elif defined A32_BITSTREAM_READER + uint32_t *buffer_ptr; + uint32_t cache0; + uint32_t cache1; + int bit_count; +#endif + int size_in_bits; +} GetBitContext; + +#define VLC_TYPE int16_t + +typedef struct VLC { + int bits; + VLC_TYPE (*table)[2]; ///< code, bits + int table_size, table_allocated; +} VLC; + +typedef struct RL_VLC_ELEM { + int16_t level; + int8_t len; + uint8_t run; +} RL_VLC_ELEM; + +#if defined(ARCH_SPARC) || defined(ARCH_ARMV4L) || defined(ARCH_MIPS) || defined(ARCH_BFIN) +#define UNALIGNED_STORES_ARE_BAD +#endif + +/* used to avoid missaligned exceptions on some archs (alpha, ...) */ +#if defined(ARCH_X86) || defined(CPU_COLDFIRE) +# define unaligned16(a) (*(const uint16_t*)(a)) +# define unaligned32(a) (*(const uint32_t*)(a)) +# define unaligned64(a) (*(const uint64_t*)(a)) +#else +# ifdef __GNUC__ +# define unaligned(x) \ +static inline uint##x##_t unaligned##x(const void *v) { \ + struct Unaligned { \ + uint##x##_t i; \ + } __attribute__((packed)); \ + \ + return ((const struct Unaligned *) v)->i; \ +} +# elif defined(__DECC) +# define unaligned(x) \ +static inline uint##x##_t unaligned##x(const void *v) { \ + return *(const __unaligned uint##x##_t *) v; \ +} +# else +# define unaligned(x) \ +static inline uint##x##_t unaligned##x(const void *v) { \ + return *(const uint##x##_t *) v; \ +} +# endif +unaligned(16) +unaligned(32) +unaligned(64) +#undef unaligned +#endif /* defined(ARCH_X86) */ + +#ifndef ALT_BITSTREAM_WRITER +static inline void put_bits(PutBitContext *s, int n, unsigned int value) +{ + unsigned int bit_buf; + int bit_left; + + // printf("put_bits=%d %x\n", n, value); + // assert(n == 32 || value < (1U << n)); + + bit_buf = s->bit_buf; + bit_left = s->bit_left; + + // printf("n=%d value=%x cnt=%d buf=%x\n", n, value, bit_cnt, bit_buf); + /* XXX: optimize */ + if (n < bit_left) { + bit_buf = (bit_buf<> (n - bit_left); +#ifdef UNALIGNED_STORES_ARE_BAD + if (3 & (intptr_t) s->buf_ptr) { + s->buf_ptr[0] = bit_buf >> 24; + s->buf_ptr[1] = bit_buf >> 16; + s->buf_ptr[2] = bit_buf >> 8; + s->buf_ptr[3] = bit_buf ; + } else +#endif + *(uint32_t *)s->buf_ptr = be2me_32(bit_buf); + //printf("bitbuf = %08x\n", bit_buf); + s->buf_ptr+=4; + bit_left+=32 - n; + bit_buf = value; + } + + s->bit_buf = bit_buf; + s->bit_left = bit_left; +} +#endif + + +#ifdef ALT_BITSTREAM_WRITER +static inline void put_bits(PutBitContext *s, int n, unsigned int value) +{ +# ifdef ALIGNED_BITSTREAM_WRITER +# if defined(ARCH_X86) + asm volatile( + "movl %0, %%ecx \n\t" + "xorl %%eax, %%eax \n\t" + "shrdl %%cl, %1, %%eax \n\t" + "shrl %%cl, %1 \n\t" + "movl %0, %%ecx \n\t" + "shrl $3, %%ecx \n\t" + "andl $0xFFFFFFFC, %%ecx \n\t" + "bswapl %1 \n\t" + "orl %1, (%2, %%ecx) \n\t" + "bswapl %%eax \n\t" + "addl %3, %0 \n\t" + "movl %%eax, 4(%2, %%ecx) \n\t" + : "=&r" (s->index), "=&r" (value) + : "r" (s->buf), "r" (n), "0" (s->index), "1" (value<<(-n)) + : "%eax", "%ecx" + ); +# else + int index= s->index; + uint32_t *ptr= ((uint32_t *)s->buf)+(index>>5); + + value<<= 32-n; + + ptr[0] |= be2me_32(value>>(index&31)); + ptr[1] = be2me_32(value<<(32-(index&31))); +//if(n>24) printf("%d %d\n", n, value); + index+= n; + s->index= index; +# endif +# else //ALIGNED_BITSTREAM_WRITER +# if defined(ARCH_X86) + asm volatile( + "movl $7, %%ecx \n\t" + "andl %0, %%ecx \n\t" + "addl %3, %%ecx \n\t" + "negl %%ecx \n\t" + "shll %%cl, %1 \n\t" + "bswapl %1 \n\t" + "movl %0, %%ecx \n\t" + "shrl $3, %%ecx \n\t" + "orl %1, (%%ecx, %2) \n\t" + "addl %3, %0 \n\t" + "movl $0, 4(%%ecx, %2) \n\t" + : "=&r" (s->index), "=&r" (value) + : "r" (s->buf), "r" (n), "0" (s->index), "1" (value) + : "%ecx" + ); +# else + int index= s->index; + uint32_t *ptr= (uint32_t*)(((uint8_t *)s->buf)+(index>>3)); + + ptr[0] |= be2me_32(value<<(32-n-(index&7) )); + ptr[1] = 0; +//if(n>24) printf("%d %d\n", n, value); + index+= n; + s->index= index; +# endif +# endif //!ALIGNED_BITSTREAM_WRITER +} +#endif + + +static inline uint8_t* pbBufPtr(PutBitContext *s) +{ +#ifdef ALT_BITSTREAM_WRITER + return s->buf + (s->index>>3); +#else + return s->buf_ptr; +#endif +} + +/** + * + * PutBitContext must be flushed & aligned to a byte boundary before calling this. + */ +static inline void skip_put_bytes(PutBitContext *s, int n){ + // assert((put_bits_count(s)&7)==0); +#ifdef ALT_BITSTREAM_WRITER + FIXME may need some cleaning of the buffer + s->index += n<<3; +#else + // assert(s->bit_left==32); + s->buf_ptr += n; +#endif +} + +/** + * skips the given number of bits. + * must only be used if the actual values in the bitstream dont matter + */ +static inline void skip_put_bits(PutBitContext *s, int n){ +#ifdef ALT_BITSTREAM_WRITER + s->index += n; +#else + s->bit_left -= n; + s->buf_ptr-= s->bit_left>>5; + s->bit_left &= 31; +#endif +} + +/** + * Changes the end of the buffer. + */ +static inline void set_put_bits_buffer_size(PutBitContext *s, int size){ + s->buf_end= s->buf + size; +} + +/* Bitstream reader API docs: +name + abritary name which is used as prefix for the internal variables + +gb + getbitcontext + +OPEN_READER(name, gb) + loads gb into local variables + +CLOSE_READER(name, gb) + stores local vars in gb + +UPDATE_CACHE(name, gb) + refills the internal cache from the bitstream + after this call at least MIN_CACHE_BITS will be available, + +GET_CACHE(name, gb) + will output the contents of the internal cache, next bit is MSB of 32 or 64 bit (FIXME 64bit) + +SHOW_UBITS(name, gb, num) + will return the next num bits + +SHOW_SBITS(name, gb, num) + will return the next num bits and do sign extension + +SKIP_BITS(name, gb, num) + will skip over the next num bits + note, this is equivalent to SKIP_CACHE; SKIP_COUNTER + +SKIP_CACHE(name, gb, num) + will remove the next num bits from the cache (note SKIP_COUNTER MUST be called before UPDATE_CACHE / CLOSE_READER) + +SKIP_COUNTER(name, gb, num) + will increment the internal bit counter (see SKIP_CACHE & SKIP_BITS) + +LAST_SKIP_CACHE(name, gb, num) + will remove the next num bits from the cache if it is needed for UPDATE_CACHE otherwise it will do nothing + +LAST_SKIP_BITS(name, gb, num) + is equivalent to SKIP_LAST_CACHE; SKIP_COUNTER + +for examples see get_bits, show_bits, skip_bits, get_vlc +*/ + +static inline int unaligned32_be(const void *v) +{ +#ifdef CONFIG_ALIGN + const uint8_t *p=v; + return (((p[0]<<8) | p[1])<<16) | (p[2]<<8) | (p[3]); +#else + return be2me_32( unaligned32(v)); //original +#endif +} + +static inline int unaligned32_le(const void *v) +{ +#ifdef CONFIG_ALIGN + const uint8_t *p=v; + return (((p[3]<<8) | p[2])<<16) | (p[1]<<8) | (p[0]); +#else + return le2me_32( unaligned32(v)); //original +#endif +} + +#ifdef ALT_BITSTREAM_READER +# define MIN_CACHE_BITS 25 + +# define OPEN_READER(name, gb)\ + int name##_index= (gb)->index;\ + int name##_cache= 0;\ + +# define CLOSE_READER(name, gb)\ + (gb)->index= name##_index;\ + +# ifdef ALT_BITSTREAM_READER_LE +# define UPDATE_CACHE(name, gb)\ + name##_cache= unaligned32_le( ((const uint8_t *)(gb)->buffer)+(name##_index>>3) ) >> (name##_index&0x07);\ + +# define SKIP_CACHE(name, gb, num)\ + name##_cache >>= (num); +# else +# define UPDATE_CACHE(name, gb)\ + name##_cache= unaligned32_be( ((const uint8_t *)(gb)->buffer)+(name##_index>>3) ) << (name##_index&0x07);\ + +# define SKIP_CACHE(name, gb, num)\ + name##_cache <<= (num); +# endif + +// FIXME name? +# define SKIP_COUNTER(name, gb, num)\ + name##_index += (num);\ + +# define SKIP_BITS(name, gb, num)\ + {\ + SKIP_CACHE(name, gb, num)\ + SKIP_COUNTER(name, gb, num)\ + }\ + +# define LAST_SKIP_BITS(name, gb, num) SKIP_COUNTER(name, gb, num) +# define LAST_SKIP_CACHE(name, gb, num) ; + +# ifdef ALT_BITSTREAM_READER_LE +# define SHOW_UBITS(name, gb, num)\ + ((name##_cache) & (NEG_USR32(0xffffffff,num))) + +# define SHOW_SBITS(name, gb, num)\ + NEG_SSR32((name##_cache)<<(32-(num)), num) +# else +# define SHOW_UBITS(name, gb, num)\ + NEG_USR32(name##_cache, num) + +# define SHOW_SBITS(name, gb, num)\ + NEG_SSR32(name##_cache, num) +# endif + +# define GET_CACHE(name, gb)\ + ((uint32_t)name##_cache) + +static inline int get_bits_count(GetBitContext *s){ + return s->index; +} + +static inline void skip_bits_long(GetBitContext *s, int n){ + s->index += n; +} + +#elif defined LIBMPEG2_BITSTREAM_READER +//libmpeg2 like reader + +# define MIN_CACHE_BITS 17 + +# define OPEN_READER(name, gb)\ + int name##_bit_count=(gb)->bit_count;\ + int name##_cache= (gb)->cache;\ + uint8_t * name##_buffer_ptr=(gb)->buffer_ptr;\ + +# define CLOSE_READER(name, gb)\ + (gb)->bit_count= name##_bit_count;\ + (gb)->cache= name##_cache;\ + (gb)->buffer_ptr= name##_buffer_ptr;\ + +#ifdef LIBMPEG2_BITSTREAM_READER_HACK + +# define UPDATE_CACHE(name, gb)\ + if(name##_bit_count >= 0){\ + name##_cache+= (int)be2me_16(*(uint16_t*)name##_buffer_ptr) << name##_bit_count;\ + name##_buffer_ptr += 2;\ + name##_bit_count-= 16;\ + }\ + +#else + +# define UPDATE_CACHE(name, gb)\ + if(name##_bit_count >= 0){\ + name##_cache+= ((name##_buffer_ptr[0]<<8) + name##_buffer_ptr[1]) << name##_bit_count;\ + name##_buffer_ptr+=2;\ + name##_bit_count-= 16;\ + }\ + +#endif + +# define SKIP_CACHE(name, gb, num)\ + name##_cache <<= (num);\ + +# define SKIP_COUNTER(name, gb, num)\ + name##_bit_count += (num);\ + +# define SKIP_BITS(name, gb, num)\ + {\ + SKIP_CACHE(name, gb, num)\ + SKIP_COUNTER(name, gb, num)\ + }\ + +# define LAST_SKIP_BITS(name, gb, num) SKIP_BITS(name, gb, num) +# define LAST_SKIP_CACHE(name, gb, num) SKIP_CACHE(name, gb, num) + +# define SHOW_UBITS(name, gb, num)\ + NEG_USR32(name##_cache, num) + +# define SHOW_SBITS(name, gb, num)\ + NEG_SSR32(name##_cache, num) + +# define GET_CACHE(name, gb)\ + ((uint32_t)name##_cache) + +static inline int get_bits_count(GetBitContext *s){ + return (s->buffer_ptr - s->buffer)*8 - 16 + s->bit_count; +} + +static inline void skip_bits_long(GetBitContext *s, int n){ + OPEN_READER(re, s) + re_bit_count += n; + re_buffer_ptr += 2*(re_bit_count>>4); + re_bit_count &= 15; + re_cache = ((re_buffer_ptr[-2]<<8) + re_buffer_ptr[-1]) << (16+re_bit_count); + UPDATE_CACHE(re, s) + CLOSE_READER(re, s) +} + +#elif defined A32_BITSTREAM_READER + +# define MIN_CACHE_BITS 32 + +# define OPEN_READER(name, gb)\ + int name##_bit_count=(gb)->bit_count;\ + uint32_t name##_cache0= (gb)->cache0;\ + uint32_t name##_cache1= (gb)->cache1;\ + uint32_t * name##_buffer_ptr=(gb)->buffer_ptr;\ + +# define CLOSE_READER(name, gb)\ + (gb)->bit_count= name##_bit_count;\ + (gb)->cache0= name##_cache0;\ + (gb)->cache1= name##_cache1;\ + (gb)->buffer_ptr= name##_buffer_ptr;\ + +# define UPDATE_CACHE(name, gb)\ + if(name##_bit_count > 0){\ + const uint32_t next= be2me_32( *name##_buffer_ptr );\ + name##_cache0 |= NEG_USR32(next,name##_bit_count);\ + name##_cache1 |= next<buffer_ptr - s->buffer)*8 - 32 + s->bit_count; +} + +static inline void skip_bits_long(GetBitContext *s, int n){ + OPEN_READER(re, s) + re_bit_count += n; + re_buffer_ptr += re_bit_count>>5; + re_bit_count &= 31; + re_cache0 = be2me_32( re_buffer_ptr[-1] ) << re_bit_count; + re_cache1 = 0; + UPDATE_CACHE(re, s) + CLOSE_READER(re, s) +} + +#endif + +/** + * read mpeg1 dc style vlc (sign bit + mantisse with no MSB). + * if MSB not set it is negative + * @param n length in bits + * @author BERO + */ +static inline int get_xbits(GetBitContext *s, int n){ + register int sign; + register int32_t cache; + OPEN_READER(re, s) + UPDATE_CACHE(re, s) + cache = GET_CACHE(re,s); + sign=(~cache)>>31; + LAST_SKIP_BITS(re, s, n) + CLOSE_READER(re, s) + return (NEG_USR32(sign ^ cache, n) ^ sign) - sign; +} + +static inline int get_sbits(GetBitContext *s, int n){ + register int tmp; + OPEN_READER(re, s) + UPDATE_CACHE(re, s) + tmp= SHOW_SBITS(re, s, n); + LAST_SKIP_BITS(re, s, n) + CLOSE_READER(re, s) + return tmp; +} + +/** + * reads 1-17 bits. + * Note, the alt bitstream reader can read up to 25 bits, but the libmpeg2 reader can't + */ +static inline unsigned int get_bits(GetBitContext *s, int n){ + register int tmp; + OPEN_READER(re, s) + UPDATE_CACHE(re, s) + tmp= SHOW_UBITS(re, s, n); + LAST_SKIP_BITS(re, s, n) + CLOSE_READER(re, s) + return tmp; +} + +/** + * shows 1-17 bits. + * Note, the alt bitstream reader can read up to 25 bits, but the libmpeg2 reader can't + */ +static inline unsigned int show_bits(GetBitContext *s, int n){ + register int tmp; + OPEN_READER(re, s) + UPDATE_CACHE(re, s) + tmp= SHOW_UBITS(re, s, n); +// CLOSE_READER(re, s) + return tmp; +} + +static inline void skip_bits(GetBitContext *s, int n){ + //Note gcc seems to optimize this to s->index+=n for the ALT_READER :)) + OPEN_READER(re, s) + UPDATE_CACHE(re, s) + LAST_SKIP_BITS(re, s, n) + CLOSE_READER(re, s) +} + +static inline unsigned int get_bits1(GetBitContext *s){ +#ifdef ALT_BITSTREAM_READER + int index= s->index; + uint8_t result= s->buffer[ index>>3 ]; +#ifdef ALT_BITSTREAM_READER_LE + result>>= (index&0x07); + result&= 1; +#else + result<<= (index&0x07); + result>>= 8 - 1; +#endif + index++; + s->index= index; + + return result; +#else + return get_bits(s, 1); +#endif +} + +static inline unsigned int show_bits1(GetBitContext *s){ + return show_bits(s, 1); +} + +static inline void skip_bits1(GetBitContext *s){ + skip_bits(s, 1); +} + +/** + * reads 0-32 bits. + */ +static inline unsigned int get_bits_long(GetBitContext *s, int n){ + if(n<=17) return get_bits(s, n); + else{ +#ifdef ALT_BITSTREAM_READER_LE + int ret= get_bits(s, 16); + return ret | (get_bits(s, n-16) << 16); +#else + int ret= get_bits(s, 16) << (n-16); + return ret | get_bits(s, n-16); +#endif + } +} + +/** + * shows 0-32 bits. + */ +static inline unsigned int show_bits_long(GetBitContext *s, int n){ + if(n<=17) return show_bits(s, n); + else{ + GetBitContext gb= *s; + int ret= get_bits_long(s, n); + *s= gb; + return ret; + } +} + +/* +static inline int check_marker(GetBitContext *s, const char *msg) +{ + int bit= get_bits1(s); + if(!bit) + av_log(NULL, AV_LOG_INFO, "Marker bit missing %s\n", msg); + + return bit; +} +*/ +/** + * init GetBitContext. + * @param buffer bitstream buffer, must be FF_INPUT_BUFFER_PADDING_SIZE bytes larger then the actual read bits + * because some optimized bitstream readers read 32 or 64 bit at once and could read over the end + * @param bit_size the size of the buffer in bits + */ +static inline void init_get_bits(GetBitContext *s, + const uint8_t *buffer, int bit_size) +{ + int buffer_size= (bit_size+7)>>3; + if(buffer_size < 0 || bit_size < 0) { + buffer_size = bit_size = 0; + buffer = NULL; + } + + s->buffer= buffer; + s->size_in_bits= bit_size; + s->buffer_end= buffer + buffer_size; +#ifdef ALT_BITSTREAM_READER + s->index=0; +#elif defined LIBMPEG2_BITSTREAM_READER + s->buffer_ptr = (uint8_t*)((intptr_t)buffer&(~1)); + s->bit_count = 16 + 8*((intptr_t)buffer&1); + skip_bits_long(s, 0); +#elif defined A32_BITSTREAM_READER + s->buffer_ptr = (uint32_t*)((intptr_t)buffer&(~3)); + s->bit_count = 32 + 8*((intptr_t)buffer&3); + skip_bits_long(s, 0); +#endif +} + +static inline void align_get_bits(GetBitContext *s) +{ + int n= (-get_bits_count(s)) & 7; + if(n) skip_bits(s, n); +} + +int init_vlc(VLC *vlc, int nb_bits, int nb_codes, + const void *bits, int bits_wrap, int bits_size, + const void *codes, int codes_wrap, int codes_size, + int flags); +#define INIT_VLC_USE_STATIC 1 +#define INIT_VLC_LE 2 +void free_vlc(VLC *vlc); + +/** + * + * if the vlc code is invalid and max_depth=1 than no bits will be removed + * if the vlc code is invalid and max_depth>1 than the number of bits removed + * is undefined + */ +#define GET_VLC(code, name, gb, table, bits, max_depth)\ +{\ + int n, index, nb_bits;\ +\ + index= SHOW_UBITS(name, gb, bits);\ + code = table[index][0];\ + n = table[index][1];\ +\ + if(max_depth > 1 && n < 0){\ + LAST_SKIP_BITS(name, gb, bits)\ + UPDATE_CACHE(name, gb)\ +\ + nb_bits = -n;\ +\ + index= SHOW_UBITS(name, gb, nb_bits) + code;\ + code = table[index][0];\ + n = table[index][1];\ + if(max_depth > 2 && n < 0){\ + LAST_SKIP_BITS(name, gb, nb_bits)\ + UPDATE_CACHE(name, gb)\ +\ + nb_bits = -n;\ +\ + index= SHOW_UBITS(name, gb, nb_bits) + code;\ + code = table[index][0];\ + n = table[index][1];\ + }\ + }\ + SKIP_BITS(name, gb, n)\ +} + +#define GET_RL_VLC(level, run, name, gb, table, bits, max_depth, need_update)\ +{\ + int n, index, nb_bits;\ +\ + index= SHOW_UBITS(name, gb, bits);\ + level = table[index].level;\ + n = table[index].len;\ +\ + if(max_depth > 1 && n < 0){\ + SKIP_BITS(name, gb, bits)\ + if(need_update){\ + UPDATE_CACHE(name, gb)\ + }\ +\ + nb_bits = -n;\ +\ + index= SHOW_UBITS(name, gb, nb_bits) + level;\ + level = table[index].level;\ + n = table[index].len;\ + }\ + run= table[index].run;\ + SKIP_BITS(name, gb, n)\ +} + + +/** + * parses a vlc code, faster then get_vlc() + * @param bits is the number of bits which will be read at once, must be + * identical to nb_bits in init_vlc() + * @param max_depth is the number of times bits bits must be read to completely + * read the longest vlc code + * = (max_vlc_length + bits - 1) / bits + */ +static av_always_inline int get_vlc2(GetBitContext *s, VLC_TYPE (*table)[2], + int bits, int max_depth) +{ + int code; + + OPEN_READER(re, s) + UPDATE_CACHE(re, s) + + GET_VLC(code, re, s, table, bits, max_depth) + + CLOSE_READER(re, s) + return code; +} + +//#define TRACE + +#ifdef TRACE +static inline void print_bin(int bits, int n){ + int i; + + for(i=n-1; i>=0; i--){ + av_log(NULL, AV_LOG_DEBUG, "%d", (bits>>i)&1); + } + for(i=n; i<24; i++) + av_log(NULL, AV_LOG_DEBUG, " "); +} + +static inline int get_bits_trace(GetBitContext *s, int n, char *file, const char *func, int line){ + int r= get_bits(s, n); + + print_bin(r, n); + av_log(NULL, AV_LOG_DEBUG, "%5d %2d %3d bit @%5d in %s %s:%d\n", r, n, r, get_bits_count(s)-n, file, func, line); + return r; +} +static inline int get_vlc_trace(GetBitContext *s, VLC_TYPE (*table)[2], int bits, int max_depth, char *file, const char *func, int line){ + int show= show_bits(s, 24); + int pos= get_bits_count(s); + int r= get_vlc2(s, table, bits, max_depth); + int len= get_bits_count(s) - pos; + int bits2= show>>(24-len); + + print_bin(bits2, len); + + av_log(NULL, AV_LOG_DEBUG, "%5d %2d %3d vlc @%5d in %s %s:%d\n", bits2, len, r, pos, file, func, line); + return r; +} +static inline int get_xbits_trace(GetBitContext *s, int n, char *file, const char *func, int line){ + int show= show_bits(s, n); + int r= get_xbits(s, n); + + print_bin(show, n); + av_log(NULL, AV_LOG_DEBUG, "%5d %2d %3d xbt @%5d in %s %s:%d\n", show, n, r, get_bits_count(s)-n, file, func, line); + return r; +} + +#define get_bits(s, n) get_bits_trace(s, n, __FILE__, __PRETTY_FUNCTION__, __LINE__) +#define get_bits1(s) get_bits_trace(s, 1, __FILE__, __PRETTY_FUNCTION__, __LINE__) +#define get_xbits(s, n) get_xbits_trace(s, n, __FILE__, __PRETTY_FUNCTION__, __LINE__) +#define get_vlc(s, vlc) get_vlc_trace(s, (vlc)->table, (vlc)->bits, 3, __FILE__, __PRETTY_FUNCTION__, __LINE__) +#define get_vlc2(s, tab, bits, max) get_vlc_trace(s, tab, bits, max, __FILE__, __PRETTY_FUNCTION__, __LINE__) + +#define tprintf(p, ...) av_log(p, AV_LOG_DEBUG, __VA_ARGS__) + +#else //TRACE +#define tprintf(p, ...) {} +#endif + +static inline int decode012(GetBitContext *gb){ + int n; + n = get_bits1(gb); + if (n == 0) + return 0; + else + return get_bits1(gb) + 1; +} + +#endif /* BITSTREAM_H */ Index: cook.h =================================================================== --- cook.h (revision 0) +++ cook.h (revision 0) @@ -0,0 +1,65 @@ +#include "bitstream.h" +//#include "dsputil.h" + +#include "cookdata.h" +#include "cookdata_fixpoint.h" + +typedef struct { + int *now; + int *previous; +} cook_gains; + +typedef struct { + GetBitContext gb; + /* stream data */ + int nb_channels; + int joint_stereo; + int bit_rate; + int sample_rate; + int extradata_size; + int samples_per_channel; + int samples_per_frame; + int subbands; + int log2_numvector_size; + int numvector_size; //1 << log2_numvector_size; + int js_subband_start; + int total_subbands; + int num_vectors; + int bits_per_subpacket; + int cookversion; + /* states */ + int random_state; + + /* gain buffers */ + cook_gains gains1; + cook_gains gains2; + int gain_1[9]; + int gain_2[9]; + int gain_3[9]; + int gain_4[9]; + + /* VLC data */ + int js_vlc_bits; + VLC envelope_quant_index[13]; + VLC sqvh[7]; //scalar quantization + VLC ccpl; //channel coupling + + /* Variables for fixed/float arithmetic routines */ + realvars_t math; + + /* data buffers */ + //uint8_t* decoded_bytes_buffer; + uint8_t decoded_bytes_buffer[1024]; + REAL_T mono_mdct_output[2048] __attribute__ ((aligned(16))); + REAL_T mono_previous_buffer1[1024]; + REAL_T mono_previous_buffer2[1024]; + REAL_T decode_buffer_1[1024]; + REAL_T decode_buffer_2[1024]; +} COOKContext; + +int cook_decode_init(RMContext *rmctx, COOKContext *q); +int cook_decode_close(COOKContext *q); +int cook_decode_frame(RMContext *rmctx,COOKContext *q, + int16_t *outbuffer, int *data_size, + const uint8_t *inbuffer, int buf_size); + Index: cookdata_fixpoint.h =================================================================== --- cookdata_fixpoint.h (revision 0) +++ cookdata_fixpoint.h (revision 0) @@ -0,0 +1,433 @@ +/* + * COOK compatible decoder fixed point data types and constants + * Copyright (c) 2007 Ian Braithwaite + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +/** + * @file cookdata_fixpoint.h + * Cook AKA RealAudio G2 compatible decoder + * fixed point data types and constants + */ + +#include +typedef int32_t FIXP; /* Fixed point variable type */ +typedef uint16_t FIXPU; /* Fixed point fraction 0<=x<1 */ + +typedef FIXP REAL_T; + + +/* No additional variables in COOKContext + * for fixed point routines + */ +typedef struct { +} realvars_t; + + +#define cPI1_8 0xec83 /* 1pi/8 2^16 */ +#define cPI2_8 0xb505 /* 2pi/8 2^16 */ +#define cPI3_8 0x61f8 /* 3pi/8 2^16 */ + +static const FIXPU sincos_lookup[2050] = { + /* x_i = 2^16 sin(i 2pi/8192), 2^16 cos(i 2pi/8192); i=0..1024 */ + 0x0000, 0xffff, 0x0032, 0xffff, 0x0065, 0xffff, 0x0097, 0xffff, + 0x00c9, 0xffff, 0x00fb, 0xffff, 0x012e, 0xffff, 0x0160, 0xffff, + 0x0192, 0xffff, 0x01c4, 0xfffe, 0x01f7, 0xfffe, 0x0229, 0xfffe, + 0x025b, 0xfffd, 0x028d, 0xfffd, 0x02c0, 0xfffc, 0x02f2, 0xfffc, + 0x0324, 0xfffb, 0x0356, 0xfffa, 0x0389, 0xfffa, 0x03bb, 0xfff9, + 0x03ed, 0xfff8, 0x0420, 0xfff7, 0x0452, 0xfff7, 0x0484, 0xfff6, + 0x04b6, 0xfff5, 0x04e9, 0xfff4, 0x051b, 0xfff3, 0x054d, 0xfff2, + 0x057f, 0xfff1, 0x05b2, 0xfff0, 0x05e4, 0xffef, 0x0616, 0xffed, + 0x0648, 0xffec, 0x067b, 0xffeb, 0x06ad, 0xffea, 0x06df, 0xffe8, + 0x0711, 0xffe7, 0x0744, 0xffe6, 0x0776, 0xffe4, 0x07a8, 0xffe3, + 0x07da, 0xffe1, 0x080d, 0xffe0, 0x083f, 0xffde, 0x0871, 0xffdc, + 0x08a3, 0xffdb, 0x08d5, 0xffd9, 0x0908, 0xffd7, 0x093a, 0xffd5, + 0x096c, 0xffd4, 0x099e, 0xffd2, 0x09d1, 0xffd0, 0x0a03, 0xffce, + 0x0a35, 0xffcc, 0x0a67, 0xffca, 0x0a9a, 0xffc8, 0x0acc, 0xffc6, + 0x0afe, 0xffc4, 0x0b30, 0xffc1, 0x0b62, 0xffbf, 0x0b95, 0xffbd, + 0x0bc7, 0xffbb, 0x0bf9, 0xffb8, 0x0c2b, 0xffb6, 0x0c5d, 0xffb4, + 0x0c90, 0xffb1, 0x0cc2, 0xffaf, 0x0cf4, 0xffac, 0x0d26, 0xffa9, + 0x0d59, 0xffa7, 0x0d8b, 0xffa4, 0x0dbd, 0xffa2, 0x0def, 0xff9f, + 0x0e21, 0xff9c, 0x0e53, 0xff99, 0x0e86, 0xff96, 0x0eb8, 0xff94, + 0x0eea, 0xff91, 0x0f1c, 0xff8e, 0x0f4e, 0xff8b, 0x0f81, 0xff88, + 0x0fb3, 0xff85, 0x0fe5, 0xff82, 0x1017, 0xff7e, 0x1049, 0xff7b, + 0x107b, 0xff78, 0x10ae, 0xff75, 0x10e0, 0xff71, 0x1112, 0xff6e, + 0x1144, 0xff6b, 0x1176, 0xff67, 0x11a8, 0xff64, 0x11da, 0xff60, + 0x120d, 0xff5d, 0x123f, 0xff59, 0x1271, 0xff56, 0x12a3, 0xff52, + 0x12d5, 0xff4e, 0x1307, 0xff4b, 0x1339, 0xff47, 0x136c, 0xff43, + 0x139e, 0xff3f, 0x13d0, 0xff3b, 0x1402, 0xff38, 0x1434, 0xff34, + 0x1466, 0xff30, 0x1498, 0xff2c, 0x14ca, 0xff28, 0x14fc, 0xff23, + 0x152e, 0xff1f, 0x1561, 0xff1b, 0x1593, 0xff17, 0x15c5, 0xff13, + 0x15f7, 0xff0e, 0x1629, 0xff0a, 0x165b, 0xff06, 0x168d, 0xff01, + 0x16bf, 0xfefd, 0x16f1, 0xfef8, 0x1723, 0xfef4, 0x1755, 0xfeef, + 0x1787, 0xfeeb, 0x17b9, 0xfee6, 0x17eb, 0xfee1, 0x181d, 0xfedd, + 0x1850, 0xfed8, 0x1882, 0xfed3, 0x18b4, 0xfece, 0x18e6, 0xfec9, + 0x1918, 0xfec4, 0x194a, 0xfebf, 0x197c, 0xfeba, 0x19ae, 0xfeb5, + 0x19e0, 0xfeb0, 0x1a12, 0xfeab, 0x1a44, 0xfea6, 0x1a76, 0xfea1, + 0x1aa8, 0xfe9c, 0x1ada, 0xfe97, 0x1b0c, 0xfe91, 0x1b3e, 0xfe8c, + 0x1b70, 0xfe87, 0x1ba2, 0xfe81, 0x1bd4, 0xfe7c, 0x1c06, 0xfe76, + 0x1c38, 0xfe71, 0x1c69, 0xfe6b, 0x1c9b, 0xfe66, 0x1ccd, 0xfe60, + 0x1cff, 0xfe5a, 0x1d31, 0xfe55, 0x1d63, 0xfe4f, 0x1d95, 0xfe49, + 0x1dc7, 0xfe43, 0x1df9, 0xfe3d, 0x1e2b, 0xfe37, 0x1e5d, 0xfe31, + 0x1e8f, 0xfe2b, 0x1ec1, 0xfe25, 0x1ef3, 0xfe1f, 0x1f24, 0xfe19, + 0x1f56, 0xfe13, 0x1f88, 0xfe0d, 0x1fba, 0xfe07, 0x1fec, 0xfe01, + 0x201e, 0xfdfa, 0x2050, 0xfdf4, 0x2082, 0xfdee, 0x20b3, 0xfde7, + 0x20e5, 0xfde1, 0x2117, 0xfdda, 0x2149, 0xfdd4, 0x217b, 0xfdcd, + 0x21ad, 0xfdc7, 0x21de, 0xfdc0, 0x2210, 0xfdb9, 0x2242, 0xfdb3, + 0x2274, 0xfdac, 0x22a6, 0xfda5, 0x22d7, 0xfd9e, 0x2309, 0xfd97, + 0x233b, 0xfd90, 0x236d, 0xfd89, 0x239f, 0xfd83, 0x23d0, 0xfd7c, + 0x2402, 0xfd74, 0x2434, 0xfd6d, 0x2466, 0xfd66, 0x2497, 0xfd5f, + 0x24c9, 0xfd58, 0x24fb, 0xfd51, 0x252d, 0xfd49, 0x255e, 0xfd42, + 0x2590, 0xfd3b, 0x25c2, 0xfd33, 0x25f4, 0xfd2c, 0x2625, 0xfd24, + 0x2657, 0xfd1d, 0x2689, 0xfd15, 0x26ba, 0xfd0e, 0x26ec, 0xfd06, + 0x271e, 0xfcfe, 0x274f, 0xfcf7, 0x2781, 0xfcef, 0x27b3, 0xfce7, + 0x27e4, 0xfcdf, 0x2816, 0xfcd8, 0x2848, 0xfcd0, 0x2879, 0xfcc8, + 0x28ab, 0xfcc0, 0x28dd, 0xfcb8, 0x290e, 0xfcb0, 0x2940, 0xfca8, + 0x2971, 0xfca0, 0x29a3, 0xfc97, 0x29d5, 0xfc8f, 0x2a06, 0xfc87, + 0x2a38, 0xfc7f, 0x2a69, 0xfc76, 0x2a9b, 0xfc6e, 0x2acc, 0xfc66, + 0x2afe, 0xfc5d, 0x2b30, 0xfc55, 0x2b61, 0xfc4c, 0x2b93, 0xfc44, + 0x2bc4, 0xfc3b, 0x2bf6, 0xfc33, 0x2c27, 0xfc2a, 0x2c59, 0xfc21, + 0x2c8a, 0xfc18, 0x2cbc, 0xfc10, 0x2ced, 0xfc07, 0x2d1f, 0xfbfe, + 0x2d50, 0xfbf5, 0x2d82, 0xfbec, 0x2db3, 0xfbe3, 0x2de5, 0xfbda, + 0x2e16, 0xfbd1, 0x2e47, 0xfbc8, 0x2e79, 0xfbbf, 0x2eaa, 0xfbb6, + 0x2edc, 0xfbad, 0x2f0d, 0xfba4, 0x2f3f, 0xfb9a, 0x2f70, 0xfb91, + 0x2fa1, 0xfb88, 0x2fd3, 0xfb7e, 0x3004, 0xfb75, 0x3035, 0xfb6b, + 0x3067, 0xfb62, 0x3098, 0xfb58, 0x30ca, 0xfb4f, 0x30fb, 0xfb45, + 0x312c, 0xfb3c, 0x315e, 0xfb32, 0x318f, 0xfb28, 0x31c0, 0xfb1f, + 0x31f1, 0xfb15, 0x3223, 0xfb0b, 0x3254, 0xfb01, 0x3285, 0xfaf7, + 0x32b7, 0xfaed, 0x32e8, 0xfae3, 0x3319, 0xfad9, 0x334a, 0xfacf, + 0x337c, 0xfac5, 0x33ad, 0xfabb, 0x33de, 0xfab1, 0x340f, 0xfaa7, + 0x3440, 0xfa9c, 0x3472, 0xfa92, 0x34a3, 0xfa88, 0x34d4, 0xfa7d, + 0x3505, 0xfa73, 0x3536, 0xfa69, 0x3568, 0xfa5e, 0x3599, 0xfa54, + 0x35ca, 0xfa49, 0x35fb, 0xfa3e, 0x362c, 0xfa34, 0x365d, 0xfa29, + 0x368e, 0xfa1f, 0x36c0, 0xfa14, 0x36f1, 0xfa09, 0x3722, 0xf9fe, + 0x3753, 0xf9f3, 0x3784, 0xf9e8, 0x37b5, 0xf9de, 0x37e6, 0xf9d3, + 0x3817, 0xf9c8, 0x3848, 0xf9bd, 0x3879, 0xf9b2, 0x38aa, 0xf9a6, + 0x38db, 0xf99b, 0x390c, 0xf990, 0x393d, 0xf985, 0x396e, 0xf97a, + 0x399f, 0xf96e, 0x39d0, 0xf963, 0x3a01, 0xf958, 0x3a32, 0xf94c, + 0x3a63, 0xf941, 0x3a94, 0xf935, 0x3ac5, 0xf92a, 0x3af6, 0xf91e, + 0x3b27, 0xf913, 0x3b58, 0xf907, 0x3b88, 0xf8fb, 0x3bb9, 0xf8f0, + 0x3bea, 0xf8e4, 0x3c1b, 0xf8d8, 0x3c4c, 0xf8cc, 0x3c7d, 0xf8c0, + 0x3cae, 0xf8b4, 0x3cde, 0xf8a9, 0x3d0f, 0xf89d, 0x3d40, 0xf891, + 0x3d71, 0xf885, 0x3da2, 0xf878, 0x3dd2, 0xf86c, 0x3e03, 0xf860, + 0x3e34, 0xf854, 0x3e65, 0xf848, 0x3e95, 0xf83b, 0x3ec6, 0xf82f, + 0x3ef7, 0xf823, 0x3f28, 0xf816, 0x3f58, 0xf80a, 0x3f89, 0xf7fe, + 0x3fba, 0xf7f1, 0x3fea, 0xf7e5, 0x401b, 0xf7d8, 0x404c, 0xf7cb, + 0x407c, 0xf7bf, 0x40ad, 0xf7b2, 0x40de, 0xf7a5, 0x410e, 0xf799, + 0x413f, 0xf78c, 0x416f, 0xf77f, 0x41a0, 0xf772, 0x41d1, 0xf765, + 0x4201, 0xf758, 0x4232, 0xf74b, 0x4262, 0xf73e, 0x4293, 0xf731, + 0x42c3, 0xf724, 0x42f4, 0xf717, 0x4324, 0xf70a, 0x4355, 0xf6fd, + 0x4385, 0xf6ef, 0x43b6, 0xf6e2, 0x43e6, 0xf6d5, 0x4417, 0xf6c7, + 0x4447, 0xf6ba, 0x4478, 0xf6ad, 0x44a8, 0xf69f, 0x44d9, 0xf692, + 0x4509, 0xf684, 0x4539, 0xf677, 0x456a, 0xf669, 0x459a, 0xf65b, + 0x45cb, 0xf64e, 0x45fb, 0xf640, 0x462b, 0xf632, 0x465c, 0xf624, + 0x468c, 0xf616, 0x46bc, 0xf609, 0x46ec, 0xf5fb, 0x471d, 0xf5ed, + 0x474d, 0xf5df, 0x477d, 0xf5d1, 0x47ae, 0xf5c3, 0x47de, 0xf5b5, + 0x480e, 0xf5a6, 0x483e, 0xf598, 0x486f, 0xf58a, 0x489f, 0xf57c, + 0x48cf, 0xf56e, 0x48ff, 0xf55f, 0x492f, 0xf551, 0x495f, 0xf543, + 0x4990, 0xf534, 0x49c0, 0xf526, 0x49f0, 0xf517, 0x4a20, 0xf509, + 0x4a50, 0xf4fa, 0x4a80, 0xf4eb, 0x4ab0, 0xf4dd, 0x4ae0, 0xf4ce, + 0x4b10, 0xf4bf, 0x4b40, 0xf4b1, 0x4b71, 0xf4a2, 0x4ba1, 0xf493, + 0x4bd1, 0xf484, 0x4c01, 0xf475, 0x4c31, 0xf466, 0x4c61, 0xf457, + 0x4c90, 0xf448, 0x4cc0, 0xf439, 0x4cf0, 0xf42a, 0x4d20, 0xf41b, + 0x4d50, 0xf40c, 0x4d80, 0xf3fd, 0x4db0, 0xf3ed, 0x4de0, 0xf3de, + 0x4e10, 0xf3cf, 0x4e40, 0xf3c0, 0x4e70, 0xf3b0, 0x4e9f, 0xf3a1, + 0x4ecf, 0xf391, 0x4eff, 0xf382, 0x4f2f, 0xf372, 0x4f5f, 0xf363, + 0x4f8e, 0xf353, 0x4fbe, 0xf343, 0x4fee, 0xf334, 0x501e, 0xf324, + 0x504d, 0xf314, 0x507d, 0xf304, 0x50ad, 0xf2f5, 0x50dd, 0xf2e5, + 0x510c, 0xf2d5, 0x513c, 0xf2c5, 0x516c, 0xf2b5, 0x519b, 0xf2a5, + 0x51cb, 0xf295, 0x51fb, 0xf285, 0x522a, 0xf275, 0x525a, 0xf265, + 0x5289, 0xf254, 0x52b9, 0xf244, 0x52e8, 0xf234, 0x5318, 0xf224, + 0x5348, 0xf213, 0x5377, 0xf203, 0x53a7, 0xf1f3, 0x53d6, 0xf1e2, + 0x5406, 0xf1d2, 0x5435, 0xf1c1, 0x5464, 0xf1b1, 0x5494, 0xf1a0, + 0x54c3, 0xf18f, 0x54f3, 0xf17f, 0x5522, 0xf16e, 0x5552, 0xf15d, + 0x5581, 0xf14c, 0x55b0, 0xf13c, 0x55e0, 0xf12b, 0x560f, 0xf11a, + 0x563e, 0xf109, 0x566e, 0xf0f8, 0x569d, 0xf0e7, 0x56cc, 0xf0d6, + 0x56fc, 0xf0c5, 0x572b, 0xf0b4, 0x575a, 0xf0a3, 0x5789, 0xf092, + 0x57b9, 0xf080, 0x57e8, 0xf06f, 0x5817, 0xf05e, 0x5846, 0xf04d, + 0x5875, 0xf03b, 0x58a5, 0xf02a, 0x58d4, 0xf018, 0x5903, 0xf007, + 0x5932, 0xeff5, 0x5961, 0xefe4, 0x5990, 0xefd2, 0x59bf, 0xefc1, + 0x59ee, 0xefaf, 0x5a1d, 0xef9d, 0x5a4c, 0xef8c, 0x5a7b, 0xef7a, + 0x5aaa, 0xef68, 0x5ad9, 0xef56, 0x5b08, 0xef45, 0x5b37, 0xef33, + 0x5b66, 0xef21, 0x5b95, 0xef0f, 0x5bc4, 0xeefd, 0x5bf3, 0xeeeb, + 0x5c22, 0xeed9, 0x5c51, 0xeec7, 0x5c80, 0xeeb4, 0x5caf, 0xeea2, + 0x5cde, 0xee90, 0x5d0c, 0xee7e, 0x5d3b, 0xee6b, 0x5d6a, 0xee59, + 0x5d99, 0xee47, 0x5dc8, 0xee34, 0x5df6, 0xee22, 0x5e25, 0xee0f, + 0x5e54, 0xedfd, 0x5e83, 0xedea, 0x5eb1, 0xedd8, 0x5ee0, 0xedc5, + 0x5f0f, 0xedb3, 0x5f3d, 0xeda0, 0x5f6c, 0xed8d, 0x5f9b, 0xed7a, + 0x5fc9, 0xed68, 0x5ff8, 0xed55, 0x6026, 0xed42, 0x6055, 0xed2f, + 0x6084, 0xed1c, 0x60b2, 0xed09, 0x60e1, 0xecf6, 0x610f, 0xece3, + 0x613e, 0xecd0, 0x616c, 0xecbd, 0x619b, 0xecaa, 0x61c9, 0xec97, + 0x61f8, 0xec83, 0x6226, 0xec70, 0x6254, 0xec5d, 0x6283, 0xec4a, + 0x62b1, 0xec36, 0x62e0, 0xec23, 0x630e, 0xec0f, 0x633c, 0xebfc, + 0x636b, 0xebe8, 0x6399, 0xebd5, 0x63c7, 0xebc1, 0x63f5, 0xebae, + 0x6424, 0xeb9a, 0x6452, 0xeb86, 0x6480, 0xeb73, 0x64ae, 0xeb5f, + 0x64dd, 0xeb4b, 0x650b, 0xeb37, 0x6539, 0xeb23, 0x6567, 0xeb0f, + 0x6595, 0xeafc, 0x65c3, 0xeae8, 0x65f2, 0xead4, 0x6620, 0xeac0, + 0x664e, 0xeaab, 0x667c, 0xea97, 0x66aa, 0xea83, 0x66d8, 0xea6f, + 0x6706, 0xea5b, 0x6734, 0xea47, 0x6762, 0xea32, 0x6790, 0xea1e, + 0x67be, 0xea0a, 0x67ec, 0xe9f5, 0x681a, 0xe9e1, 0x6848, 0xe9cc, + 0x6876, 0xe9b8, 0x68a3, 0xe9a3, 0x68d1, 0xe98f, 0x68ff, 0xe97a, + 0x692d, 0xe966, 0x695b, 0xe951, 0x6989, 0xe93c, 0x69b6, 0xe927, + 0x69e4, 0xe913, 0x6a12, 0xe8fe, 0x6a40, 0xe8e9, 0x6a6d, 0xe8d4, + 0x6a9b, 0xe8bf, 0x6ac9, 0xe8aa, 0x6af6, 0xe895, 0x6b24, 0xe880, + 0x6b52, 0xe86b, 0x6b7f, 0xe856, 0x6bad, 0xe841, 0x6bdb, 0xe82c, + 0x6c08, 0xe817, 0x6c36, 0xe801, 0x6c63, 0xe7ec, 0x6c91, 0xe7d7, + 0x6cbe, 0xe7c2, 0x6cec, 0xe7ac, 0x6d19, 0xe797, 0x6d47, 0xe781, + 0x6d74, 0xe76c, 0x6da2, 0xe756, 0x6dcf, 0xe741, 0x6dfc, 0xe72b, + 0x6e2a, 0xe716, 0x6e57, 0xe700, 0x6e85, 0xe6ea, 0x6eb2, 0xe6d5, + 0x6edf, 0xe6bf, 0x6f0d, 0xe6a9, 0x6f3a, 0xe693, 0x6f67, 0xe67d, + 0x6f94, 0xe667, 0x6fc2, 0xe652, 0x6fef, 0xe63c, 0x701c, 0xe626, + 0x7049, 0xe610, 0x7076, 0xe5f9, 0x70a3, 0xe5e3, 0x70d1, 0xe5cd, + 0x70fe, 0xe5b7, 0x712b, 0xe5a1, 0x7158, 0xe58b, 0x7185, 0xe574, + 0x71b2, 0xe55e, 0x71df, 0xe548, 0x720c, 0xe531, 0x7239, 0xe51b, + 0x7266, 0xe504, 0x7293, 0xe4ee, 0x72c0, 0xe4d7, 0x72ed, 0xe4c1, + 0x731a, 0xe4aa, 0x7347, 0xe494, 0x7373, 0xe47d, 0x73a0, 0xe466, + 0x73cd, 0xe450, 0x73fa, 0xe439, 0x7427, 0xe422, 0x7454, 0xe40b, + 0x7480, 0xe3f4, 0x74ad, 0xe3de, 0x74da, 0xe3c7, 0x7507, 0xe3b0, + 0x7533, 0xe399, 0x7560, 0xe382, 0x758d, 0xe36b, 0x75b9, 0xe353, + 0x75e6, 0xe33c, 0x7612, 0xe325, 0x763f, 0xe30e, 0x766c, 0xe2f7, + 0x7698, 0xe2df, 0x76c5, 0xe2c8, 0x76f1, 0xe2b1, 0x771e, 0xe299, + 0x774a, 0xe282, 0x7777, 0xe26b, 0x77a3, 0xe253, 0x77d0, 0xe23c, + 0x77fc, 0xe224, 0x7828, 0xe20d, 0x7855, 0xe1f5, 0x7881, 0xe1dd, + 0x78ad, 0xe1c6, 0x78da, 0xe1ae, 0x7906, 0xe196, 0x7932, 0xe17e, + 0x795f, 0xe167, 0x798b, 0xe14f, 0x79b7, 0xe137, 0x79e3, 0xe11f, + 0x7a10, 0xe107, 0x7a3c, 0xe0ef, 0x7a68, 0xe0d7, 0x7a94, 0xe0bf, + 0x7ac0, 0xe0a7, 0x7aec, 0xe08f, 0x7b18, 0xe077, 0x7b44, 0xe05e, + 0x7b70, 0xe046, 0x7b9c, 0xe02e, 0x7bc8, 0xe016, 0x7bf4, 0xdffd, + 0x7c20, 0xdfe5, 0x7c4c, 0xdfcd, 0x7c78, 0xdfb4, 0x7ca4, 0xdf9c, + 0x7cd0, 0xdf83, 0x7cfc, 0xdf6b, 0x7d28, 0xdf52, 0x7d54, 0xdf39, + 0x7d7f, 0xdf21, 0x7dab, 0xdf08, 0x7dd7, 0xdef0, 0x7e03, 0xded7, + 0x7e2f, 0xdebe, 0x7e5a, 0xdea5, 0x7e86, 0xde8c, 0x7eb2, 0xde74, + 0x7edd, 0xde5b, 0x7f09, 0xde42, 0x7f35, 0xde29, 0x7f60, 0xde10, + 0x7f8c, 0xddf7, 0x7fb7, 0xddde, 0x7fe3, 0xddc5, 0x800f, 0xddab, + 0x803a, 0xdd92, 0x8066, 0xdd79, 0x8091, 0xdd60, 0x80bc, 0xdd47, + 0x80e8, 0xdd2d, 0x8113, 0xdd14, 0x813f, 0xdcfb, 0x816a, 0xdce1, + 0x8195, 0xdcc8, 0x81c1, 0xdcae, 0x81ec, 0xdc95, 0x8217, 0xdc7b, + 0x8243, 0xdc62, 0x826e, 0xdc48, 0x8299, 0xdc2f, 0x82c4, 0xdc15, + 0x82f0, 0xdbfb, 0x831b, 0xdbe1, 0x8346, 0xdbc8, 0x8371, 0xdbae, + 0x839c, 0xdb94, 0x83c7, 0xdb7a, 0x83f2, 0xdb60, 0x841d, 0xdb46, + 0x8449, 0xdb2c, 0x8474, 0xdb12, 0x849f, 0xdaf8, 0x84ca, 0xdade, + 0x84f5, 0xdac4, 0x851f, 0xdaaa, 0x854a, 0xda90, 0x8575, 0xda76, + 0x85a0, 0xda5c, 0x85cb, 0xda41, 0x85f6, 0xda27, 0x8621, 0xda0d, + 0x864c, 0xd9f2, 0x8676, 0xd9d8, 0x86a1, 0xd9be, 0x86cc, 0xd9a3, + 0x86f7, 0xd989, 0x8721, 0xd96e, 0x874c, 0xd954, 0x8777, 0xd939, + 0x87a1, 0xd91e, 0x87cc, 0xd904, 0x87f6, 0xd8e9, 0x8821, 0xd8ce, + 0x884c, 0xd8b4, 0x8876, 0xd899, 0x88a1, 0xd87e, 0x88cb, 0xd863, + 0x88f6, 0xd848, 0x8920, 0xd82d, 0x894a, 0xd812, 0x8975, 0xd7f8, + 0x899f, 0xd7dc, 0x89ca, 0xd7c1, 0x89f4, 0xd7a6, 0x8a1e, 0xd78b, + 0x8a49, 0xd770, 0x8a73, 0xd755, 0x8a9d, 0xd73a, 0x8ac7, 0xd71f, + 0x8af2, 0xd703, 0x8b1c, 0xd6e8, 0x8b46, 0xd6cd, 0x8b70, 0xd6b1, + 0x8b9a, 0xd696, 0x8bc5, 0xd67a, 0x8bef, 0xd65f, 0x8c19, 0xd644, + 0x8c43, 0xd628, 0x8c6d, 0xd60c, 0x8c97, 0xd5f1, 0x8cc1, 0xd5d5, + 0x8ceb, 0xd5ba, 0x8d15, 0xd59e, 0x8d3f, 0xd582, 0x8d69, 0xd566, + 0x8d93, 0xd54b, 0x8dbc, 0xd52f, 0x8de6, 0xd513, 0x8e10, 0xd4f7, + 0x8e3a, 0xd4db, 0x8e64, 0xd4bf, 0x8e8d, 0xd4a3, 0x8eb7, 0xd487, + 0x8ee1, 0xd46b, 0x8f0b, 0xd44f, 0x8f34, 0xd433, 0x8f5e, 0xd417, + 0x8f88, 0xd3fb, 0x8fb1, 0xd3df, 0x8fdb, 0xd3c2, 0x9004, 0xd3a6, + 0x902e, 0xd38a, 0x9057, 0xd36d, 0x9081, 0xd351, 0x90aa, 0xd335, + 0x90d4, 0xd318, 0x90fd, 0xd2fc, 0x9127, 0xd2df, 0x9150, 0xd2c3, + 0x9179, 0xd2a6, 0x91a3, 0xd28a, 0x91cc, 0xd26d, 0x91f5, 0xd250, + 0x921f, 0xd234, 0x9248, 0xd217, 0x9271, 0xd1fa, 0x929a, 0xd1de, + 0x92c4, 0xd1c1, 0x92ed, 0xd1a4, 0x9316, 0xd187, 0x933f, 0xd16a, + 0x9368, 0xd14d, 0x9391, 0xd130, 0x93ba, 0xd113, 0x93e3, 0xd0f6, + 0x940c, 0xd0d9, 0x9435, 0xd0bc, 0x945e, 0xd09f, 0x9487, 0xd082, + 0x94b0, 0xd065, 0x94d9, 0xd047, 0x9502, 0xd02a, 0x952b, 0xd00d, + 0x9554, 0xcff0, 0x957d, 0xcfd2, 0x95a5, 0xcfb5, 0x95ce, 0xcf98, + 0x95f7, 0xcf7a, 0x9620, 0xcf5d, 0x9648, 0xcf3f, 0x9671, 0xcf22, + 0x969a, 0xcf04, 0x96c2, 0xcee7, 0x96eb, 0xcec9, 0x9713, 0xceab, + 0x973c, 0xce8e, 0x9765, 0xce70, 0x978d, 0xce52, 0x97b6, 0xce34, + 0x97de, 0xce17, 0x9807, 0xcdf9, 0x982f, 0xcddb, 0x9857, 0xcdbd, + 0x9880, 0xcd9f, 0x98a8, 0xcd81, 0x98d0, 0xcd63, 0x98f9, 0xcd45, + 0x9921, 0xcd27, 0x9949, 0xcd09, 0x9972, 0xcceb, 0x999a, 0xcccd, + 0x99c2, 0xccae, 0x99ea, 0xcc90, 0x9a12, 0xcc72, 0x9a3a, 0xcc54, + 0x9a63, 0xcc35, 0x9a8b, 0xcc17, 0x9ab3, 0xcbf9, 0x9adb, 0xcbda, + 0x9b03, 0xcbbc, 0x9b2b, 0xcb9e, 0x9b53, 0xcb7f, 0x9b7b, 0xcb61, + 0x9ba3, 0xcb42, 0x9bca, 0xcb23, 0x9bf2, 0xcb05, 0x9c1a, 0xcae6, + 0x9c42, 0xcac7, 0x9c6a, 0xcaa9, 0x9c92, 0xca8a, 0x9cb9, 0xca6b, + 0x9ce1, 0xca4d, 0x9d09, 0xca2e, 0x9d31, 0xca0f, 0x9d58, 0xc9f0, + 0x9d80, 0xc9d1, 0x9da7, 0xc9b2, 0x9dcf, 0xc993, 0x9df7, 0xc974, + 0x9e1e, 0xc955, 0x9e46, 0xc936, 0x9e6d, 0xc917, 0x9e95, 0xc8f8, + 0x9ebc, 0xc8d9, 0x9ee3, 0xc8ba, 0x9f0b, 0xc89a, 0x9f32, 0xc87b, + 0x9f5a, 0xc85c, 0x9f81, 0xc83c, 0x9fa8, 0xc81d, 0x9fd0, 0xc7fe, + 0x9ff7, 0xc7de, 0xa01e, 0xc7bf, 0xa045, 0xc7a0, 0xa06c, 0xc780, + 0xa094, 0xc761, 0xa0bb, 0xc741, 0xa0e2, 0xc721, 0xa109, 0xc702, + 0xa130, 0xc6e2, 0xa157, 0xc6c2, 0xa17e, 0xc6a3, 0xa1a5, 0xc683, + 0xa1cc, 0xc663, 0xa1f3, 0xc644, 0xa21a, 0xc624, 0xa241, 0xc604, + 0xa268, 0xc5e4, 0xa28e, 0xc5c4, 0xa2b5, 0xc5a4, 0xa2dc, 0xc584, + 0xa303, 0xc564, 0xa32a, 0xc544, 0xa350, 0xc524, 0xa377, 0xc504, + 0xa39e, 0xc4e4, 0xa3c4, 0xc4c4, 0xa3eb, 0xc4a4, 0xa412, 0xc483, + 0xa438, 0xc463, 0xa45f, 0xc443, 0xa485, 0xc423, 0xa4ac, 0xc402, + 0xa4d2, 0xc3e2, 0xa4f9, 0xc3c2, 0xa51f, 0xc3a1, 0xa545, 0xc381, + 0xa56c, 0xc360, 0xa592, 0xc340, 0xa5b8, 0xc31f, 0xa5df, 0xc2ff, + 0xa605, 0xc2de, 0xa62b, 0xc2be, 0xa652, 0xc29d, 0xa678, 0xc27c, + 0xa69e, 0xc25c, 0xa6c4, 0xc23b, 0xa6ea, 0xc21a, 0xa710, 0xc1f9, + 0xa736, 0xc1d8, 0xa75c, 0xc1b8, 0xa782, 0xc197, 0xa7a8, 0xc176, + 0xa7ce, 0xc155, 0xa7f4, 0xc134, 0xa81a, 0xc113, 0xa840, 0xc0f2, + 0xa866, 0xc0d1, 0xa88c, 0xc0b0, 0xa8b2, 0xc08f, 0xa8d7, 0xc06e, + 0xa8fd, 0xc04c, 0xa923, 0xc02b, 0xa949, 0xc00a, 0xa96e, 0xbfe9, + 0xa994, 0xbfc7, 0xa9ba, 0xbfa6, 0xa9df, 0xbf85, 0xaa05, 0xbf63, + 0xaa2a, 0xbf42, 0xaa50, 0xbf21, 0xaa76, 0xbeff, 0xaa9b, 0xbede, + 0xaac1, 0xbebc, 0xaae6, 0xbe9b, 0xab0b, 0xbe79, 0xab31, 0xbe57, + 0xab56, 0xbe36, 0xab7b, 0xbe14, 0xaba1, 0xbdf2, 0xabc6, 0xbdd1, + 0xabeb, 0xbdaf, 0xac11, 0xbd8d, 0xac36, 0xbd6b, 0xac5b, 0xbd4a, + 0xac80, 0xbd28, 0xaca5, 0xbd06, 0xacca, 0xbce4, 0xacef, 0xbcc2, + 0xad14, 0xbca0, 0xad39, 0xbc7e, 0xad5e, 0xbc5c, 0xad83, 0xbc3a, + 0xada8, 0xbc18, 0xadcd, 0xbbf6, 0xadf2, 0xbbd4, 0xae17, 0xbbb1, + 0xae3c, 0xbb8f, 0xae61, 0xbb6d, 0xae85, 0xbb4b, 0xaeaa, 0xbb28, + 0xaecf, 0xbb06, 0xaef4, 0xbae4, 0xaf18, 0xbac1, 0xaf3d, 0xba9f, + 0xaf62, 0xba7d, 0xaf86, 0xba5a, 0xafab, 0xba38, 0xafcf, 0xba15, + 0xaff4, 0xb9f3, 0xb018, 0xb9d0, 0xb03d, 0xb9ae, 0xb061, 0xb98b, + 0xb086, 0xb968, 0xb0aa, 0xb946, 0xb0ce, 0xb923, 0xb0f3, 0xb900, + 0xb117, 0xb8dd, 0xb13b, 0xb8bb, 0xb160, 0xb898, 0xb184, 0xb875, + 0xb1a8, 0xb852, 0xb1cc, 0xb82f, 0xb1f0, 0xb80c, 0xb215, 0xb7e9, + 0xb239, 0xb7c6, 0xb25d, 0xb7a3, 0xb281, 0xb780, 0xb2a5, 0xb75d, + 0xb2c9, 0xb73a, 0xb2ed, 0xb717, 0xb311, 0xb6f4, 0xb335, 0xb6d1, + 0xb358, 0xb6ad, 0xb37c, 0xb68a, 0xb3a0, 0xb667, 0xb3c4, 0xb644, + 0xb3e8, 0xb620, 0xb40b, 0xb5fd, 0xb42f, 0xb5da, 0xb453, 0xb5b6, + 0xb477, 0xb593, 0xb49a, 0xb56f, 0xb4be, 0xb54c, 0xb4e1, 0xb528, + 0xb505, 0xb505 +}; + +static const FIXPU pow128_tab[128] = { + /* x_i = 2^(15+i/128) */ + 0x8000, 0x80b2, 0x8165, 0x8219, 0x82ce, 0x8383, 0x843a, 0x84f2, 0x85ab, + 0x8665, 0x871f, 0x87db, 0x8898, 0x8956, 0x8a15, 0x8ad5, 0x8b96, 0x8c58, + 0x8d1b, 0x8ddf, 0x8ea4, 0x8f6b, 0x9032, 0x90fa, 0x91c4, 0x928e, 0x935a, + 0x9427, 0x94f5, 0x95c4, 0x9694, 0x9765, 0x9838, 0x990c, 0x99e0, 0x9ab6, + 0x9b8d, 0x9c65, 0x9d3f, 0x9e19, 0x9ef5, 0x9fd2, 0xa0b0, 0xa190, 0xa270, + 0xa352, 0xa435, 0xa519, 0xa5ff, 0xa6e6, 0xa7ce, 0xa8b7, 0xa9a1, 0xaa8d, + 0xab7a, 0xac69, 0xad58, 0xae49, 0xaf3b, 0xb02f, 0xb124, 0xb21a, 0xb312, + 0xb40b, 0xb505, 0xb601, 0xb6fe, 0xb7fc, 0xb8fc, 0xb9fd, 0xbaff, 0xbc03, + 0xbd09, 0xbe0f, 0xbf18, 0xc021, 0xc12c, 0xc239, 0xc347, 0xc456, 0xc567, + 0xc67a, 0xc78d, 0xc8a3, 0xc9ba, 0xcad2, 0xcbec, 0xcd08, 0xce25, 0xcf43, + 0xd063, 0xd185, 0xd2a8, 0xd3cd, 0xd4f3, 0xd61b, 0xd745, 0xd870, 0xd99d, + 0xdacc, 0xdbfc, 0xdd2e, 0xde61, 0xdf96, 0xe0cd, 0xe205, 0xe340, 0xe47b, + 0xe5b9, 0xe6f8, 0xe839, 0xe97c, 0xeac1, 0xec07, 0xed4f, 0xee99, 0xefe5, + 0xf132, 0xf281, 0xf3d3, 0xf525, 0xf67a, 0xf7d1, 0xf929, 0xfa84, 0xfbe0, + 0xfd3e, 0xfe9e +}; + + +/* dither_table and quant_centroid_table. + * Index 1: [0] - scaled by 2^13, [1] - scaled by 2^13 / sqrt(2) + * Index 2: [0..7] - category + * Index 3: [0] - dither_table, [1..13] - quant_centroid_table + */ +static const FIXP quant_tables[2][8][14] = {{{ + 0x00000000, 0x0645a1cb, 0x0c2d0e56, 0x11eb851f, 0x17a1cac1, 0x1d4fdf3b, + 0x22ed9168, 0x28a7ef9e, 0x2e49ba5e, 0x33eb851f, 0x39916873, 0x3f126e98, + 0x449ba5e3, 0x4b958106 +},{ + 0x00000000, 0x08b43958, 0x10f5c28f, 0x19020c4a, 0x2116872b, 0x2922d0e5, + 0x3126e979, 0x38fdf3b6, 0x411eb852, 0x49eb851f, 0x00000000, 0x00000000, + 0x00000000, 0x00000000 +},{ + 0x00000000, 0x0bef9db2, 0x176c8b44, 0x22e147ae, 0x2e1cac08, 0x39581062, + 0x450e5604, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000 +},{ + 0x00000000, 0x10189375, 0x20000000, 0x2fe353f8, 0x3fc28f5c, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000 +},{ + 0x00000000, 0x1522d0e5, 0x2b3f7cee, 0x3fba5e35, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000 +},{ + 0x02d413cd, 0x1a83126f, 0x37db22d1, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000 +},{ + 0x04000000, 0x1f6c8b44, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000 +},{ + 0x0b504f33, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000 +}},{{ + 0x00000000, 0x046f5a70, 0x089c1768, 0x0cabddd3, 0x10b5d955, 0x14ba09ed, + 0x18b2a4b4, 0x1cbf85aa, 0x20bb05e5, 0x24b68620, 0x28b4ebcf, 0x2c994066, + 0x30835fe6, 0x35722a5e +},{ + 0x00000000, 0x062797a1, 0x0bfe1683, 0x11aeee7a, 0x1765915b, 0x1d166952, + 0x22c17660, 0x284ca76c, 0x2e0bfaaa, 0x3444f306, 0x00000000, 0x00000000, + 0x00000000, 0x00000000 +},{ + 0x00000000, 0x0870a594, 0x1090326a, 0x18a9f456, 0x209b29e3, 0x288c5f70, + 0x30d478a5, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000 +},{ + 0x00000000, 0x0b61afee, 0x16a09e66, 0x21dca76a, 0x2d15caf9, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000 +},{ + 0x00000000, 0x0ef20652, 0x1e94b968, 0x2d100010, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000 +},{ + 0x02000000, 0x12bf2f44, 0x277f041b, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000 +},{ + 0x02d413cd, 0x16385a03, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000 +},{ + 0x08000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000 +}}}; + +static const FIXPU cplscale2[3] = { + /* 2^16 C_ij */ + 0xf3f9, 0xb505, 0x4d8b +}; +static const FIXPU cplscale3[7] = { + /* 2^16 C_ij */ + 0xfb35, 0xefdf, 0xe03d, 0xb505, 0x7b81, 0x596e, 0x314d +}; +static const FIXPU cplscale4[15] = { + /* 2^16 C_ij */ + 0xfdd2, 0xf927, 0xf3f9, 0xee1d, 0xe749, 0xdee9, 0xd381, 0xb505, 0x903b, + 0x7de2, 0x6dbe, 0x5e02, 0x4d8b, 0x3ad1, 0x2155 +}; +static const FIXPU cplscale5[31] = { + /* 2^16 C_ij */ + 0xfef5, 0xfcce, 0xfa8e, 0xf832, 0xf5b5, 0xf314, 0xf049, 0xed4c, 0xea12, + 0xe68e, 0xe2ab, 0xde4b, 0xd938, 0xd30b, 0xcab6, 0xb505, 0x9c59, 0x90e8, + 0x8778, 0x7ef9, 0x76fc, 0x6f45, 0x67ab, 0x600e, 0x5850, 0x504d, 0x47db, + 0x3ebd, 0x3486, 0x2853, 0x1715 +}; +static const FIXPU cplscale6[63] = { + /* 2^16 C_ij */ + 0xff7d, 0xfe74, 0xfd65, 0xfc50, 0xfb35, 0xfa14, 0xf8eb, 0xf7bb, 0xf683, + 0xf543, 0xf3f9, 0xf2a6, 0xf148, 0xefdf, 0xee6a, 0xece6, 0xeb54, 0xe9b2, + 0xe7fd, 0xe634, 0xe453, 0xe258, 0xe03d, 0xddff, 0xdb94, 0xd8f4, 0xd610, + 0xd2d2, 0xcf13, 0xca8c, 0xc47c, 0xb505, 0xa41a, 0x9c90, 0x9685, 0x913a, + 0x8c67, 0x87e5, 0x839c, 0x7f7e, 0x7b81, 0x779b, 0x73c7, 0x6fff, 0x6c3f, + 0x6883, 0x64c7, 0x6107, 0x5d40, 0x596e, 0x558d, 0x5198, 0x4d8b, 0x495f, + 0x450d, 0x408b, 0x3bcd, 0x36c1, 0x314d, 0x2b4a, 0x246e, 0x1c1a, 0x1029 +}; + +static const FIXPU* cplscales[5] = { + cplscale2, cplscale3, cplscale4, cplscale5, cplscale6 +}; + Index: patch =================================================================== --- patch (revision 0) +++ patch (revision 0) @@ -0,0 +1,1514 @@ +Index: bitstream.h +=================================================================== +--- bitstream.h (revision 0) ++++ bitstream.h (revision 0) +@@ -0,0 +1,1001 @@ ++/* ++ * copyright (c) 2004 Michael Niedermayer ++ * ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++/** ++ * @file bitstream.h ++ * bitstream api header. ++ */ ++ ++#ifndef BITSTREAM_H ++#define BITSTREAM_H ++ ++#ifndef av_always_inline ++#define av_always_inline inline ++#endif ++#ifndef attribute_deprecated ++#define attribute_deprecated ++#endif ++ ++#ifdef CPU_ARM ++#define CONFIG_ALIGN 1 ++#endif ++ ++#ifdef ROCKBOX_BIG_ENDIAN ++#define WORDS_BIGENDIAN ++#endif ++ ++#include ++#include ++#include "bswap.h" ++ ++ ++ ++extern const uint8_t ff_log2_tab[256]; ++ ++ ++/*misc utility functions added to make it compile */ ++/*static inline int av_log2(unsigned int v) ++{ ++ int n; ++ ++ n = 0; ++ if (v & 0xffff0000) { ++ v >>= 16; ++ n += 16; ++ } ++ if (v & 0xff00) { ++ v >>= 8; ++ n += 8; ++ } ++ n += ff_log2_tab[v]; ++ ++ return n; ++}*/ ++ ++ ++//#include "log.h" ++ ++#if defined(ALT_BITSTREAM_READER_LE) && !defined(ALT_BITSTREAM_READER) ++#define ALT_BITSTREAM_READER ++#endif ++ ++//#define ALT_BITSTREAM_WRITER ++//#define ALIGNED_BITSTREAM_WRITER ++#if !defined(LIBMPEG2_BITSTREAM_READER) && !defined(A32_BITSTREAM_READER) && !defined(ALT_BITSTREAM_READER) ++# ifdef ARCH_ARMV4L ++# define A32_BITSTREAM_READER ++# else ++#define ALT_BITSTREAM_READER ++//#define LIBMPEG2_BITSTREAM_READER ++//#define A32_BITSTREAM_READER ++# endif ++#endif ++#define LIBMPEG2_BITSTREAM_READER_HACK //add BERO ++ ++extern const uint8_t ff_reverse[256]; ++ ++#if defined(ARCH_X86) ++// avoid +32 for shift optimization (gcc should do that ...) ++static inline int32_t NEG_SSR32( int32_t a, int8_t s){ ++ asm ("sarl %1, %0\n\t" ++ : "+r" (a) ++ : "ic" ((uint8_t)(-s)) ++ ); ++ return a; ++} ++static inline uint32_t NEG_USR32(uint32_t a, int8_t s){ ++ asm ("shrl %1, %0\n\t" ++ : "+r" (a) ++ : "ic" ((uint8_t)(-s)) ++ ); ++ return a; ++} ++#else ++# define NEG_SSR32(a,s) ((( int32_t)(a))>>(32-(s))) ++# define NEG_USR32(a,s) (((uint32_t)(a))>>(32-(s))) ++#endif ++ ++/* bit output */ ++ ++/* buf and buf_end must be present and used by every alternative writer. */ ++typedef struct PutBitContext { ++#ifdef ALT_BITSTREAM_WRITER ++ uint8_t *buf, *buf_end; ++ int index; ++#else ++ uint32_t bit_buf; ++ int bit_left; ++ uint8_t *buf, *buf_ptr, *buf_end; ++#endif ++} PutBitContext; ++ ++static inline void init_put_bits(PutBitContext *s, uint8_t *buffer, int buffer_size) ++{ ++ if(buffer_size < 0) { ++ buffer_size = 0; ++ buffer = NULL; ++ } ++ ++ s->buf = buffer; ++ s->buf_end = s->buf + buffer_size; ++#ifdef ALT_BITSTREAM_WRITER ++ s->index=0; ++ ((uint32_t*)(s->buf))[0]=0; ++// memset(buffer, 0, buffer_size); ++#else ++ s->buf_ptr = s->buf; ++ s->bit_left=32; ++ s->bit_buf=0; ++#endif ++} ++ ++/* return the number of bits output */ ++static inline int put_bits_count(PutBitContext *s) ++{ ++#ifdef ALT_BITSTREAM_WRITER ++ return s->index; ++#else ++ return (s->buf_ptr - s->buf) * 8 + 32 - s->bit_left; ++#endif ++} ++ ++/* pad the end of the output stream with zeros */ ++static inline void flush_put_bits(PutBitContext *s) ++{ ++#ifdef ALT_BITSTREAM_WRITER ++ align_put_bits(s); ++#else ++ s->bit_buf<<= s->bit_left; ++ while (s->bit_left < 32) { ++ /* XXX: should test end of buffer */ ++ *s->buf_ptr++=s->bit_buf >> 24; ++ s->bit_buf<<=8; ++ s->bit_left+=8; ++ } ++ s->bit_left=32; ++ s->bit_buf=0; ++#endif ++} ++ ++void align_put_bits(PutBitContext *s); ++void ff_put_string(PutBitContext * pbc, char *s, int put_zero); ++ ++/* bit input */ ++/* buffer, buffer_end and size_in_bits must be present and used by every reader */ ++typedef struct GetBitContext { ++ const uint8_t *buffer, *buffer_end; ++#ifdef ALT_BITSTREAM_READER ++ int index; ++#elif defined LIBMPEG2_BITSTREAM_READER ++ uint8_t *buffer_ptr; ++ uint32_t cache; ++ int bit_count; ++#elif defined A32_BITSTREAM_READER ++ uint32_t *buffer_ptr; ++ uint32_t cache0; ++ uint32_t cache1; ++ int bit_count; ++#endif ++ int size_in_bits; ++} GetBitContext; ++ ++#define VLC_TYPE int16_t ++ ++typedef struct VLC { ++ int bits; ++ VLC_TYPE (*table)[2]; ///< code, bits ++ int table_size, table_allocated; ++} VLC; ++ ++typedef struct RL_VLC_ELEM { ++ int16_t level; ++ int8_t len; ++ uint8_t run; ++} RL_VLC_ELEM; ++ ++#if defined(ARCH_SPARC) || defined(ARCH_ARMV4L) || defined(ARCH_MIPS) || defined(ARCH_BFIN) ++#define UNALIGNED_STORES_ARE_BAD ++#endif ++ ++/* used to avoid missaligned exceptions on some archs (alpha, ...) */ ++#if defined(ARCH_X86) || defined(CPU_COLDFIRE) ++# define unaligned16(a) (*(const uint16_t*)(a)) ++# define unaligned32(a) (*(const uint32_t*)(a)) ++# define unaligned64(a) (*(const uint64_t*)(a)) ++#else ++# ifdef __GNUC__ ++# define unaligned(x) \ ++static inline uint##x##_t unaligned##x(const void *v) { \ ++ struct Unaligned { \ ++ uint##x##_t i; \ ++ } __attribute__((packed)); \ ++ \ ++ return ((const struct Unaligned *) v)->i; \ ++} ++# elif defined(__DECC) ++# define unaligned(x) \ ++static inline uint##x##_t unaligned##x(const void *v) { \ ++ return *(const __unaligned uint##x##_t *) v; \ ++} ++# else ++# define unaligned(x) \ ++static inline uint##x##_t unaligned##x(const void *v) { \ ++ return *(const uint##x##_t *) v; \ ++} ++# endif ++unaligned(16) ++unaligned(32) ++unaligned(64) ++#undef unaligned ++#endif /* defined(ARCH_X86) */ ++ ++#ifndef ALT_BITSTREAM_WRITER ++static inline void put_bits(PutBitContext *s, int n, unsigned int value) ++{ ++ unsigned int bit_buf; ++ int bit_left; ++ ++ // printf("put_bits=%d %x\n", n, value); ++ // assert(n == 32 || value < (1U << n)); ++ ++ bit_buf = s->bit_buf; ++ bit_left = s->bit_left; ++ ++ // printf("n=%d value=%x cnt=%d buf=%x\n", n, value, bit_cnt, bit_buf); ++ /* XXX: optimize */ ++ if (n < bit_left) { ++ bit_buf = (bit_buf<> (n - bit_left); ++#ifdef UNALIGNED_STORES_ARE_BAD ++ if (3 & (intptr_t) s->buf_ptr) { ++ s->buf_ptr[0] = bit_buf >> 24; ++ s->buf_ptr[1] = bit_buf >> 16; ++ s->buf_ptr[2] = bit_buf >> 8; ++ s->buf_ptr[3] = bit_buf ; ++ } else ++#endif ++ *(uint32_t *)s->buf_ptr = be2me_32(bit_buf); ++ //printf("bitbuf = %08x\n", bit_buf); ++ s->buf_ptr+=4; ++ bit_left+=32 - n; ++ bit_buf = value; ++ } ++ ++ s->bit_buf = bit_buf; ++ s->bit_left = bit_left; ++} ++#endif ++ ++ ++#ifdef ALT_BITSTREAM_WRITER ++static inline void put_bits(PutBitContext *s, int n, unsigned int value) ++{ ++# ifdef ALIGNED_BITSTREAM_WRITER ++# if defined(ARCH_X86) ++ asm volatile( ++ "movl %0, %%ecx \n\t" ++ "xorl %%eax, %%eax \n\t" ++ "shrdl %%cl, %1, %%eax \n\t" ++ "shrl %%cl, %1 \n\t" ++ "movl %0, %%ecx \n\t" ++ "shrl $3, %%ecx \n\t" ++ "andl $0xFFFFFFFC, %%ecx \n\t" ++ "bswapl %1 \n\t" ++ "orl %1, (%2, %%ecx) \n\t" ++ "bswapl %%eax \n\t" ++ "addl %3, %0 \n\t" ++ "movl %%eax, 4(%2, %%ecx) \n\t" ++ : "=&r" (s->index), "=&r" (value) ++ : "r" (s->buf), "r" (n), "0" (s->index), "1" (value<<(-n)) ++ : "%eax", "%ecx" ++ ); ++# else ++ int index= s->index; ++ uint32_t *ptr= ((uint32_t *)s->buf)+(index>>5); ++ ++ value<<= 32-n; ++ ++ ptr[0] |= be2me_32(value>>(index&31)); ++ ptr[1] = be2me_32(value<<(32-(index&31))); ++//if(n>24) printf("%d %d\n", n, value); ++ index+= n; ++ s->index= index; ++# endif ++# else //ALIGNED_BITSTREAM_WRITER ++# if defined(ARCH_X86) ++ asm volatile( ++ "movl $7, %%ecx \n\t" ++ "andl %0, %%ecx \n\t" ++ "addl %3, %%ecx \n\t" ++ "negl %%ecx \n\t" ++ "shll %%cl, %1 \n\t" ++ "bswapl %1 \n\t" ++ "movl %0, %%ecx \n\t" ++ "shrl $3, %%ecx \n\t" ++ "orl %1, (%%ecx, %2) \n\t" ++ "addl %3, %0 \n\t" ++ "movl $0, 4(%%ecx, %2) \n\t" ++ : "=&r" (s->index), "=&r" (value) ++ : "r" (s->buf), "r" (n), "0" (s->index), "1" (value) ++ : "%ecx" ++ ); ++# else ++ int index= s->index; ++ uint32_t *ptr= (uint32_t*)(((uint8_t *)s->buf)+(index>>3)); ++ ++ ptr[0] |= be2me_32(value<<(32-n-(index&7) )); ++ ptr[1] = 0; ++//if(n>24) printf("%d %d\n", n, value); ++ index+= n; ++ s->index= index; ++# endif ++# endif //!ALIGNED_BITSTREAM_WRITER ++} ++#endif ++ ++ ++static inline uint8_t* pbBufPtr(PutBitContext *s) ++{ ++#ifdef ALT_BITSTREAM_WRITER ++ return s->buf + (s->index>>3); ++#else ++ return s->buf_ptr; ++#endif ++} ++ ++/** ++ * ++ * PutBitContext must be flushed & aligned to a byte boundary before calling this. ++ */ ++static inline void skip_put_bytes(PutBitContext *s, int n){ ++ // assert((put_bits_count(s)&7)==0); ++#ifdef ALT_BITSTREAM_WRITER ++ FIXME may need some cleaning of the buffer ++ s->index += n<<3; ++#else ++ // assert(s->bit_left==32); ++ s->buf_ptr += n; ++#endif ++} ++ ++/** ++ * skips the given number of bits. ++ * must only be used if the actual values in the bitstream dont matter ++ */ ++static inline void skip_put_bits(PutBitContext *s, int n){ ++#ifdef ALT_BITSTREAM_WRITER ++ s->index += n; ++#else ++ s->bit_left -= n; ++ s->buf_ptr-= s->bit_left>>5; ++ s->bit_left &= 31; ++#endif ++} ++ ++/** ++ * Changes the end of the buffer. ++ */ ++static inline void set_put_bits_buffer_size(PutBitContext *s, int size){ ++ s->buf_end= s->buf + size; ++} ++ ++/* Bitstream reader API docs: ++name ++ abritary name which is used as prefix for the internal variables ++ ++gb ++ getbitcontext ++ ++OPEN_READER(name, gb) ++ loads gb into local variables ++ ++CLOSE_READER(name, gb) ++ stores local vars in gb ++ ++UPDATE_CACHE(name, gb) ++ refills the internal cache from the bitstream ++ after this call at least MIN_CACHE_BITS will be available, ++ ++GET_CACHE(name, gb) ++ will output the contents of the internal cache, next bit is MSB of 32 or 64 bit (FIXME 64bit) ++ ++SHOW_UBITS(name, gb, num) ++ will return the next num bits ++ ++SHOW_SBITS(name, gb, num) ++ will return the next num bits and do sign extension ++ ++SKIP_BITS(name, gb, num) ++ will skip over the next num bits ++ note, this is equivalent to SKIP_CACHE; SKIP_COUNTER ++ ++SKIP_CACHE(name, gb, num) ++ will remove the next num bits from the cache (note SKIP_COUNTER MUST be called before UPDATE_CACHE / CLOSE_READER) ++ ++SKIP_COUNTER(name, gb, num) ++ will increment the internal bit counter (see SKIP_CACHE & SKIP_BITS) ++ ++LAST_SKIP_CACHE(name, gb, num) ++ will remove the next num bits from the cache if it is needed for UPDATE_CACHE otherwise it will do nothing ++ ++LAST_SKIP_BITS(name, gb, num) ++ is equivalent to SKIP_LAST_CACHE; SKIP_COUNTER ++ ++for examples see get_bits, show_bits, skip_bits, get_vlc ++*/ ++ ++static inline int unaligned32_be(const void *v) ++{ ++#ifdef CONFIG_ALIGN ++ const uint8_t *p=v; ++ return (((p[0]<<8) | p[1])<<16) | (p[2]<<8) | (p[3]); ++#else ++ return be2me_32( unaligned32(v)); //original ++#endif ++} ++ ++static inline int unaligned32_le(const void *v) ++{ ++#ifdef CONFIG_ALIGN ++ const uint8_t *p=v; ++ return (((p[3]<<8) | p[2])<<16) | (p[1]<<8) | (p[0]); ++#else ++ return le2me_32( unaligned32(v)); //original ++#endif ++} ++ ++#ifdef ALT_BITSTREAM_READER ++# define MIN_CACHE_BITS 25 ++ ++# define OPEN_READER(name, gb)\ ++ int name##_index= (gb)->index;\ ++ int name##_cache= 0;\ ++ ++# define CLOSE_READER(name, gb)\ ++ (gb)->index= name##_index;\ ++ ++# ifdef ALT_BITSTREAM_READER_LE ++# define UPDATE_CACHE(name, gb)\ ++ name##_cache= unaligned32_le( ((const uint8_t *)(gb)->buffer)+(name##_index>>3) ) >> (name##_index&0x07);\ ++ ++# define SKIP_CACHE(name, gb, num)\ ++ name##_cache >>= (num); ++# else ++# define UPDATE_CACHE(name, gb)\ ++ name##_cache= unaligned32_be( ((const uint8_t *)(gb)->buffer)+(name##_index>>3) ) << (name##_index&0x07);\ ++ ++# define SKIP_CACHE(name, gb, num)\ ++ name##_cache <<= (num); ++# endif ++ ++// FIXME name? ++# define SKIP_COUNTER(name, gb, num)\ ++ name##_index += (num);\ ++ ++# define SKIP_BITS(name, gb, num)\ ++ {\ ++ SKIP_CACHE(name, gb, num)\ ++ SKIP_COUNTER(name, gb, num)\ ++ }\ ++ ++# define LAST_SKIP_BITS(name, gb, num) SKIP_COUNTER(name, gb, num) ++# define LAST_SKIP_CACHE(name, gb, num) ; ++ ++# ifdef ALT_BITSTREAM_READER_LE ++# define SHOW_UBITS(name, gb, num)\ ++ ((name##_cache) & (NEG_USR32(0xffffffff,num))) ++ ++# define SHOW_SBITS(name, gb, num)\ ++ NEG_SSR32((name##_cache)<<(32-(num)), num) ++# else ++# define SHOW_UBITS(name, gb, num)\ ++ NEG_USR32(name##_cache, num) ++ ++# define SHOW_SBITS(name, gb, num)\ ++ NEG_SSR32(name##_cache, num) ++# endif ++ ++# define GET_CACHE(name, gb)\ ++ ((uint32_t)name##_cache) ++ ++static inline int get_bits_count(GetBitContext *s){ ++ return s->index; ++} ++ ++static inline void skip_bits_long(GetBitContext *s, int n){ ++ s->index += n; ++} ++ ++#elif defined LIBMPEG2_BITSTREAM_READER ++//libmpeg2 like reader ++ ++# define MIN_CACHE_BITS 17 ++ ++# define OPEN_READER(name, gb)\ ++ int name##_bit_count=(gb)->bit_count;\ ++ int name##_cache= (gb)->cache;\ ++ uint8_t * name##_buffer_ptr=(gb)->buffer_ptr;\ ++ ++# define CLOSE_READER(name, gb)\ ++ (gb)->bit_count= name##_bit_count;\ ++ (gb)->cache= name##_cache;\ ++ (gb)->buffer_ptr= name##_buffer_ptr;\ ++ ++#ifdef LIBMPEG2_BITSTREAM_READER_HACK ++ ++# define UPDATE_CACHE(name, gb)\ ++ if(name##_bit_count >= 0){\ ++ name##_cache+= (int)be2me_16(*(uint16_t*)name##_buffer_ptr) << name##_bit_count;\ ++ name##_buffer_ptr += 2;\ ++ name##_bit_count-= 16;\ ++ }\ ++ ++#else ++ ++# define UPDATE_CACHE(name, gb)\ ++ if(name##_bit_count >= 0){\ ++ name##_cache+= ((name##_buffer_ptr[0]<<8) + name##_buffer_ptr[1]) << name##_bit_count;\ ++ name##_buffer_ptr+=2;\ ++ name##_bit_count-= 16;\ ++ }\ ++ ++#endif ++ ++# define SKIP_CACHE(name, gb, num)\ ++ name##_cache <<= (num);\ ++ ++# define SKIP_COUNTER(name, gb, num)\ ++ name##_bit_count += (num);\ ++ ++# define SKIP_BITS(name, gb, num)\ ++ {\ ++ SKIP_CACHE(name, gb, num)\ ++ SKIP_COUNTER(name, gb, num)\ ++ }\ ++ ++# define LAST_SKIP_BITS(name, gb, num) SKIP_BITS(name, gb, num) ++# define LAST_SKIP_CACHE(name, gb, num) SKIP_CACHE(name, gb, num) ++ ++# define SHOW_UBITS(name, gb, num)\ ++ NEG_USR32(name##_cache, num) ++ ++# define SHOW_SBITS(name, gb, num)\ ++ NEG_SSR32(name##_cache, num) ++ ++# define GET_CACHE(name, gb)\ ++ ((uint32_t)name##_cache) ++ ++static inline int get_bits_count(GetBitContext *s){ ++ return (s->buffer_ptr - s->buffer)*8 - 16 + s->bit_count; ++} ++ ++static inline void skip_bits_long(GetBitContext *s, int n){ ++ OPEN_READER(re, s) ++ re_bit_count += n; ++ re_buffer_ptr += 2*(re_bit_count>>4); ++ re_bit_count &= 15; ++ re_cache = ((re_buffer_ptr[-2]<<8) + re_buffer_ptr[-1]) << (16+re_bit_count); ++ UPDATE_CACHE(re, s) ++ CLOSE_READER(re, s) ++} ++ ++#elif defined A32_BITSTREAM_READER ++ ++# define MIN_CACHE_BITS 32 ++ ++# define OPEN_READER(name, gb)\ ++ int name##_bit_count=(gb)->bit_count;\ ++ uint32_t name##_cache0= (gb)->cache0;\ ++ uint32_t name##_cache1= (gb)->cache1;\ ++ uint32_t * name##_buffer_ptr=(gb)->buffer_ptr;\ ++ ++# define CLOSE_READER(name, gb)\ ++ (gb)->bit_count= name##_bit_count;\ ++ (gb)->cache0= name##_cache0;\ ++ (gb)->cache1= name##_cache1;\ ++ (gb)->buffer_ptr= name##_buffer_ptr;\ ++ ++# define UPDATE_CACHE(name, gb)\ ++ if(name##_bit_count > 0){\ ++ const uint32_t next= be2me_32( *name##_buffer_ptr );\ ++ name##_cache0 |= NEG_USR32(next,name##_bit_count);\ ++ name##_cache1 |= next<buffer_ptr - s->buffer)*8 - 32 + s->bit_count; ++} ++ ++static inline void skip_bits_long(GetBitContext *s, int n){ ++ OPEN_READER(re, s) ++ re_bit_count += n; ++ re_buffer_ptr += re_bit_count>>5; ++ re_bit_count &= 31; ++ re_cache0 = be2me_32( re_buffer_ptr[-1] ) << re_bit_count; ++ re_cache1 = 0; ++ UPDATE_CACHE(re, s) ++ CLOSE_READER(re, s) ++} ++ ++#endif ++ ++/** ++ * read mpeg1 dc style vlc (sign bit + mantisse with no MSB). ++ * if MSB not set it is negative ++ * @param n length in bits ++ * @author BERO ++ */ ++static inline int get_xbits(GetBitContext *s, int n){ ++ register int sign; ++ register int32_t cache; ++ OPEN_READER(re, s) ++ UPDATE_CACHE(re, s) ++ cache = GET_CACHE(re,s); ++ sign=(~cache)>>31; ++ LAST_SKIP_BITS(re, s, n) ++ CLOSE_READER(re, s) ++ return (NEG_USR32(sign ^ cache, n) ^ sign) - sign; ++} ++ ++static inline int get_sbits(GetBitContext *s, int n){ ++ register int tmp; ++ OPEN_READER(re, s) ++ UPDATE_CACHE(re, s) ++ tmp= SHOW_SBITS(re, s, n); ++ LAST_SKIP_BITS(re, s, n) ++ CLOSE_READER(re, s) ++ return tmp; ++} ++ ++/** ++ * reads 1-17 bits. ++ * Note, the alt bitstream reader can read up to 25 bits, but the libmpeg2 reader can't ++ */ ++static inline unsigned int get_bits(GetBitContext *s, int n){ ++ register int tmp; ++ OPEN_READER(re, s) ++ UPDATE_CACHE(re, s) ++ tmp= SHOW_UBITS(re, s, n); ++ LAST_SKIP_BITS(re, s, n) ++ CLOSE_READER(re, s) ++ return tmp; ++} ++ ++/** ++ * shows 1-17 bits. ++ * Note, the alt bitstream reader can read up to 25 bits, but the libmpeg2 reader can't ++ */ ++static inline unsigned int show_bits(GetBitContext *s, int n){ ++ register int tmp; ++ OPEN_READER(re, s) ++ UPDATE_CACHE(re, s) ++ tmp= SHOW_UBITS(re, s, n); ++// CLOSE_READER(re, s) ++ return tmp; ++} ++ ++static inline void skip_bits(GetBitContext *s, int n){ ++ //Note gcc seems to optimize this to s->index+=n for the ALT_READER :)) ++ OPEN_READER(re, s) ++ UPDATE_CACHE(re, s) ++ LAST_SKIP_BITS(re, s, n) ++ CLOSE_READER(re, s) ++} ++ ++static inline unsigned int get_bits1(GetBitContext *s){ ++#ifdef ALT_BITSTREAM_READER ++ int index= s->index; ++ uint8_t result= s->buffer[ index>>3 ]; ++#ifdef ALT_BITSTREAM_READER_LE ++ result>>= (index&0x07); ++ result&= 1; ++#else ++ result<<= (index&0x07); ++ result>>= 8 - 1; ++#endif ++ index++; ++ s->index= index; ++ ++ return result; ++#else ++ return get_bits(s, 1); ++#endif ++} ++ ++static inline unsigned int show_bits1(GetBitContext *s){ ++ return show_bits(s, 1); ++} ++ ++static inline void skip_bits1(GetBitContext *s){ ++ skip_bits(s, 1); ++} ++ ++/** ++ * reads 0-32 bits. ++ */ ++static inline unsigned int get_bits_long(GetBitContext *s, int n){ ++ if(n<=17) return get_bits(s, n); ++ else{ ++#ifdef ALT_BITSTREAM_READER_LE ++ int ret= get_bits(s, 16); ++ return ret | (get_bits(s, n-16) << 16); ++#else ++ int ret= get_bits(s, 16) << (n-16); ++ return ret | get_bits(s, n-16); ++#endif ++ } ++} ++ ++/** ++ * shows 0-32 bits. ++ */ ++static inline unsigned int show_bits_long(GetBitContext *s, int n){ ++ if(n<=17) return show_bits(s, n); ++ else{ ++ GetBitContext gb= *s; ++ int ret= get_bits_long(s, n); ++ *s= gb; ++ return ret; ++ } ++} ++ ++/* ++static inline int check_marker(GetBitContext *s, const char *msg) ++{ ++ int bit= get_bits1(s); ++ if(!bit) ++ av_log(NULL, AV_LOG_INFO, "Marker bit missing %s\n", msg); ++ ++ return bit; ++} ++*/ ++/** ++ * init GetBitContext. ++ * @param buffer bitstream buffer, must be FF_INPUT_BUFFER_PADDING_SIZE bytes larger then the actual read bits ++ * because some optimized bitstream readers read 32 or 64 bit at once and could read over the end ++ * @param bit_size the size of the buffer in bits ++ */ ++static inline void init_get_bits(GetBitContext *s, ++ const uint8_t *buffer, int bit_size) ++{ ++ int buffer_size= (bit_size+7)>>3; ++ if(buffer_size < 0 || bit_size < 0) { ++ buffer_size = bit_size = 0; ++ buffer = NULL; ++ } ++ ++ s->buffer= buffer; ++ s->size_in_bits= bit_size; ++ s->buffer_end= buffer + buffer_size; ++#ifdef ALT_BITSTREAM_READER ++ s->index=0; ++#elif defined LIBMPEG2_BITSTREAM_READER ++ s->buffer_ptr = (uint8_t*)((intptr_t)buffer&(~1)); ++ s->bit_count = 16 + 8*((intptr_t)buffer&1); ++ skip_bits_long(s, 0); ++#elif defined A32_BITSTREAM_READER ++ s->buffer_ptr = (uint32_t*)((intptr_t)buffer&(~3)); ++ s->bit_count = 32 + 8*((intptr_t)buffer&3); ++ skip_bits_long(s, 0); ++#endif ++} ++ ++static inline void align_get_bits(GetBitContext *s) ++{ ++ int n= (-get_bits_count(s)) & 7; ++ if(n) skip_bits(s, n); ++} ++ ++int init_vlc(VLC *vlc, int nb_bits, int nb_codes, ++ const void *bits, int bits_wrap, int bits_size, ++ const void *codes, int codes_wrap, int codes_size, ++ int flags); ++#define INIT_VLC_USE_STATIC 1 ++#define INIT_VLC_LE 2 ++void free_vlc(VLC *vlc); ++ ++/** ++ * ++ * if the vlc code is invalid and max_depth=1 than no bits will be removed ++ * if the vlc code is invalid and max_depth>1 than the number of bits removed ++ * is undefined ++ */ ++#define GET_VLC(code, name, gb, table, bits, max_depth)\ ++{\ ++ int n, index, nb_bits;\ ++\ ++ index= SHOW_UBITS(name, gb, bits);\ ++ code = table[index][0];\ ++ n = table[index][1];\ ++\ ++ if(max_depth > 1 && n < 0){\ ++ LAST_SKIP_BITS(name, gb, bits)\ ++ UPDATE_CACHE(name, gb)\ ++\ ++ nb_bits = -n;\ ++\ ++ index= SHOW_UBITS(name, gb, nb_bits) + code;\ ++ code = table[index][0];\ ++ n = table[index][1];\ ++ if(max_depth > 2 && n < 0){\ ++ LAST_SKIP_BITS(name, gb, nb_bits)\ ++ UPDATE_CACHE(name, gb)\ ++\ ++ nb_bits = -n;\ ++\ ++ index= SHOW_UBITS(name, gb, nb_bits) + code;\ ++ code = table[index][0];\ ++ n = table[index][1];\ ++ }\ ++ }\ ++ SKIP_BITS(name, gb, n)\ ++} ++ ++#define GET_RL_VLC(level, run, name, gb, table, bits, max_depth, need_update)\ ++{\ ++ int n, index, nb_bits;\ ++\ ++ index= SHOW_UBITS(name, gb, bits);\ ++ level = table[index].level;\ ++ n = table[index].len;\ ++\ ++ if(max_depth > 1 && n < 0){\ ++ SKIP_BITS(name, gb, bits)\ ++ if(need_update){\ ++ UPDATE_CACHE(name, gb)\ ++ }\ ++\ ++ nb_bits = -n;\ ++\ ++ index= SHOW_UBITS(name, gb, nb_bits) + level;\ ++ level = table[index].level;\ ++ n = table[index].len;\ ++ }\ ++ run= table[index].run;\ ++ SKIP_BITS(name, gb, n)\ ++} ++ ++ ++/** ++ * parses a vlc code, faster then get_vlc() ++ * @param bits is the number of bits which will be read at once, must be ++ * identical to nb_bits in init_vlc() ++ * @param max_depth is the number of times bits bits must be read to completely ++ * read the longest vlc code ++ * = (max_vlc_length + bits - 1) / bits ++ */ ++static av_always_inline int get_vlc2(GetBitContext *s, VLC_TYPE (*table)[2], ++ int bits, int max_depth) ++{ ++ int code; ++ ++ OPEN_READER(re, s) ++ UPDATE_CACHE(re, s) ++ ++ GET_VLC(code, re, s, table, bits, max_depth) ++ ++ CLOSE_READER(re, s) ++ return code; ++} ++ ++//#define TRACE ++ ++#ifdef TRACE ++static inline void print_bin(int bits, int n){ ++ int i; ++ ++ for(i=n-1; i>=0; i--){ ++ av_log(NULL, AV_LOG_DEBUG, "%d", (bits>>i)&1); ++ } ++ for(i=n; i<24; i++) ++ av_log(NULL, AV_LOG_DEBUG, " "); ++} ++ ++static inline int get_bits_trace(GetBitContext *s, int n, char *file, const char *func, int line){ ++ int r= get_bits(s, n); ++ ++ print_bin(r, n); ++ av_log(NULL, AV_LOG_DEBUG, "%5d %2d %3d bit @%5d in %s %s:%d\n", r, n, r, get_bits_count(s)-n, file, func, line); ++ return r; ++} ++static inline int get_vlc_trace(GetBitContext *s, VLC_TYPE (*table)[2], int bits, int max_depth, char *file, const char *func, int line){ ++ int show= show_bits(s, 24); ++ int pos= get_bits_count(s); ++ int r= get_vlc2(s, table, bits, max_depth); ++ int len= get_bits_count(s) - pos; ++ int bits2= show>>(24-len); ++ ++ print_bin(bits2, len); ++ ++ av_log(NULL, AV_LOG_DEBUG, "%5d %2d %3d vlc @%5d in %s %s:%d\n", bits2, len, r, pos, file, func, line); ++ return r; ++} ++static inline int get_xbits_trace(GetBitContext *s, int n, char *file, const char *func, int line){ ++ int show= show_bits(s, n); ++ int r= get_xbits(s, n); ++ ++ print_bin(show, n); ++ av_log(NULL, AV_LOG_DEBUG, "%5d %2d %3d xbt @%5d in %s %s:%d\n", show, n, r, get_bits_count(s)-n, file, func, line); ++ return r; ++} ++ ++#define get_bits(s, n) get_bits_trace(s, n, __FILE__, __PRETTY_FUNCTION__, __LINE__) ++#define get_bits1(s) get_bits_trace(s, 1, __FILE__, __PRETTY_FUNCTION__, __LINE__) ++#define get_xbits(s, n) get_xbits_trace(s, n, __FILE__, __PRETTY_FUNCTION__, __LINE__) ++#define get_vlc(s, vlc) get_vlc_trace(s, (vlc)->table, (vlc)->bits, 3, __FILE__, __PRETTY_FUNCTION__, __LINE__) ++#define get_vlc2(s, tab, bits, max) get_vlc_trace(s, tab, bits, max, __FILE__, __PRETTY_FUNCTION__, __LINE__) ++ ++#define tprintf(p, ...) av_log(p, AV_LOG_DEBUG, __VA_ARGS__) ++ ++#else //TRACE ++#define tprintf(p, ...) {} ++#endif ++ ++static inline int decode012(GetBitContext *gb){ ++ int n; ++ n = get_bits1(gb); ++ if (n == 0) ++ return 0; ++ else ++ return get_bits1(gb) + 1; ++} ++ ++#endif /* BITSTREAM_H */ +Index: cook.h +=================================================================== +--- cook.h (revision 0) ++++ cook.h (revision 0) +@@ -0,0 +1,65 @@ ++#include "bitstream.h" ++//#include "dsputil.h" ++ ++#include "cookdata.h" ++#include "cookdata_fixpoint.h" ++ ++typedef struct { ++ int *now; ++ int *previous; ++} cook_gains; ++ ++typedef struct { ++ GetBitContext gb; ++ /* stream data */ ++ int nb_channels; ++ int joint_stereo; ++ int bit_rate; ++ int sample_rate; ++ int extradata_size; ++ int samples_per_channel; ++ int samples_per_frame; ++ int subbands; ++ int log2_numvector_size; ++ int numvector_size; //1 << log2_numvector_size; ++ int js_subband_start; ++ int total_subbands; ++ int num_vectors; ++ int bits_per_subpacket; ++ int cookversion; ++ /* states */ ++ int random_state; ++ ++ /* gain buffers */ ++ cook_gains gains1; ++ cook_gains gains2; ++ int gain_1[9]; ++ int gain_2[9]; ++ int gain_3[9]; ++ int gain_4[9]; ++ ++ /* VLC data */ ++ int js_vlc_bits; ++ VLC envelope_quant_index[13]; ++ VLC sqvh[7]; //scalar quantization ++ VLC ccpl; //channel coupling ++ ++ /* Variables for fixed/float arithmetic routines */ ++ realvars_t math; ++ ++ /* data buffers */ ++ //uint8_t* decoded_bytes_buffer; ++ uint8_t decoded_bytes_buffer[1024]; ++ REAL_T mono_mdct_output[2048] __attribute__ ((aligned(16))); ++ REAL_T mono_previous_buffer1[1024]; ++ REAL_T mono_previous_buffer2[1024]; ++ REAL_T decode_buffer_1[1024]; ++ REAL_T decode_buffer_2[1024]; ++} COOKContext; ++ ++int cook_decode_init(RMContext *rmctx, COOKContext *q); ++int cook_decode_close(COOKContext *q); ++int cook_decode_frame(RMContext *rmctx,COOKContext *q, ++ int16_t *outbuffer, int *data_size, ++ const uint8_t *inbuffer, int buf_size); ++ +Index: cookdata_fixpoint.h +=================================================================== +--- cookdata_fixpoint.h (revision 0) ++++ cookdata_fixpoint.h (revision 0) +@@ -0,0 +1,433 @@ ++/* ++ * COOK compatible decoder fixed point data types and constants ++ * Copyright (c) 2007 Ian Braithwaite ++ * ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ * ++ */ ++ ++/** ++ * @file cookdata_fixpoint.h ++ * Cook AKA RealAudio G2 compatible decoder ++ * fixed point data types and constants ++ */ ++ ++#include ++typedef int32_t FIXP; /* Fixed point variable type */ ++typedef uint16_t FIXPU; /* Fixed point fraction 0<=x<1 */ ++ ++typedef FIXP REAL_T; ++ ++ ++/* No additional variables in COOKContext ++ * for fixed point routines ++ */ ++typedef struct { ++} realvars_t; ++ ++ ++#define cPI1_8 0xec83 /* 1pi/8 2^16 */ ++#define cPI2_8 0xb505 /* 2pi/8 2^16 */ ++#define cPI3_8 0x61f8 /* 3pi/8 2^16 */ ++ ++static const FIXPU sincos_lookup[2050] = { ++ /* x_i = 2^16 sin(i 2pi/8192), 2^16 cos(i 2pi/8192); i=0..1024 */ ++ 0x0000, 0xffff, 0x0032, 0xffff, 0x0065, 0xffff, 0x0097, 0xffff, ++ 0x00c9, 0xffff, 0x00fb, 0xffff, 0x012e, 0xffff, 0x0160, 0xffff, ++ 0x0192, 0xffff, 0x01c4, 0xfffe, 0x01f7, 0xfffe, 0x0229, 0xfffe, ++ 0x025b, 0xfffd, 0x028d, 0xfffd, 0x02c0, 0xfffc, 0x02f2, 0xfffc, ++ 0x0324, 0xfffb, 0x0356, 0xfffa, 0x0389, 0xfffa, 0x03bb, 0xfff9, ++ 0x03ed, 0xfff8, 0x0420, 0xfff7, 0x0452, 0xfff7, 0x0484, 0xfff6, ++ 0x04b6, 0xfff5, 0x04e9, 0xfff4, 0x051b, 0xfff3, 0x054d, 0xfff2, ++ 0x057f, 0xfff1, 0x05b2, 0xfff0, 0x05e4, 0xffef, 0x0616, 0xffed, ++ 0x0648, 0xffec, 0x067b, 0xffeb, 0x06ad, 0xffea, 0x06df, 0xffe8, ++ 0x0711, 0xffe7, 0x0744, 0xffe6, 0x0776, 0xffe4, 0x07a8, 0xffe3, ++ 0x07da, 0xffe1, 0x080d, 0xffe0, 0x083f, 0xffde, 0x0871, 0xffdc, ++ 0x08a3, 0xffdb, 0x08d5, 0xffd9, 0x0908, 0xffd7, 0x093a, 0xffd5, ++ 0x096c, 0xffd4, 0x099e, 0xffd2, 0x09d1, 0xffd0, 0x0a03, 0xffce, ++ 0x0a35, 0xffcc, 0x0a67, 0xffca, 0x0a9a, 0xffc8, 0x0acc, 0xffc6, ++ 0x0afe, 0xffc4, 0x0b30, 0xffc1, 0x0b62, 0xffbf, 0x0b95, 0xffbd, ++ 0x0bc7, 0xffbb, 0x0bf9, 0xffb8, 0x0c2b, 0xffb6, 0x0c5d, 0xffb4, ++ 0x0c90, 0xffb1, 0x0cc2, 0xffaf, 0x0cf4, 0xffac, 0x0d26, 0xffa9, ++ 0x0d59, 0xffa7, 0x0d8b, 0xffa4, 0x0dbd, 0xffa2, 0x0def, 0xff9f, ++ 0x0e21, 0xff9c, 0x0e53, 0xff99, 0x0e86, 0xff96, 0x0eb8, 0xff94, ++ 0x0eea, 0xff91, 0x0f1c, 0xff8e, 0x0f4e, 0xff8b, 0x0f81, 0xff88, ++ 0x0fb3, 0xff85, 0x0fe5, 0xff82, 0x1017, 0xff7e, 0x1049, 0xff7b, ++ 0x107b, 0xff78, 0x10ae, 0xff75, 0x10e0, 0xff71, 0x1112, 0xff6e, ++ 0x1144, 0xff6b, 0x1176, 0xff67, 0x11a8, 0xff64, 0x11da, 0xff60, ++ 0x120d, 0xff5d, 0x123f, 0xff59, 0x1271, 0xff56, 0x12a3, 0xff52, ++ 0x12d5, 0xff4e, 0x1307, 0xff4b, 0x1339, 0xff47, 0x136c, 0xff43, ++ 0x139e, 0xff3f, 0x13d0, 0xff3b, 0x1402, 0xff38, 0x1434, 0xff34, ++ 0x1466, 0xff30, 0x1498, 0xff2c, 0x14ca, 0xff28, 0x14fc, 0xff23, ++ 0x152e, 0xff1f, 0x1561, 0xff1b, 0x1593, 0xff17, 0x15c5, 0xff13, ++ 0x15f7, 0xff0e, 0x1629, 0xff0a, 0x165b, 0xff06, 0x168d, 0xff01, ++ 0x16bf, 0xfefd, 0x16f1, 0xfef8, 0x1723, 0xfef4, 0x1755, 0xfeef, ++ 0x1787, 0xfeeb, 0x17b9, 0xfee6, 0x17eb, 0xfee1, 0x181d, 0xfedd, ++ 0x1850, 0xfed8, 0x1882, 0xfed3, 0x18b4, 0xfece, 0x18e6, 0xfec9, ++ 0x1918, 0xfec4, 0x194a, 0xfebf, 0x197c, 0xfeba, 0x19ae, 0xfeb5, ++ 0x19e0, 0xfeb0, 0x1a12, 0xfeab, 0x1a44, 0xfea6, 0x1a76, 0xfea1, ++ 0x1aa8, 0xfe9c, 0x1ada, 0xfe97, 0x1b0c, 0xfe91, 0x1b3e, 0xfe8c, ++ 0x1b70, 0xfe87, 0x1ba2, 0xfe81, 0x1bd4, 0xfe7c, 0x1c06, 0xfe76, ++ 0x1c38, 0xfe71, 0x1c69, 0xfe6b, 0x1c9b, 0xfe66, 0x1ccd, 0xfe60, ++ 0x1cff, 0xfe5a, 0x1d31, 0xfe55, 0x1d63, 0xfe4f, 0x1d95, 0xfe49, ++ 0x1dc7, 0xfe43, 0x1df9, 0xfe3d, 0x1e2b, 0xfe37, 0x1e5d, 0xfe31, ++ 0x1e8f, 0xfe2b, 0x1ec1, 0xfe25, 0x1ef3, 0xfe1f, 0x1f24, 0xfe19, ++ 0x1f56, 0xfe13, 0x1f88, 0xfe0d, 0x1fba, 0xfe07, 0x1fec, 0xfe01, ++ 0x201e, 0xfdfa, 0x2050, 0xfdf4, 0x2082, 0xfdee, 0x20b3, 0xfde7, ++ 0x20e5, 0xfde1, 0x2117, 0xfdda, 0x2149, 0xfdd4, 0x217b, 0xfdcd, ++ 0x21ad, 0xfdc7, 0x21de, 0xfdc0, 0x2210, 0xfdb9, 0x2242, 0xfdb3, ++ 0x2274, 0xfdac, 0x22a6, 0xfda5, 0x22d7, 0xfd9e, 0x2309, 0xfd97, ++ 0x233b, 0xfd90, 0x236d, 0xfd89, 0x239f, 0xfd83, 0x23d0, 0xfd7c, ++ 0x2402, 0xfd74, 0x2434, 0xfd6d, 0x2466, 0xfd66, 0x2497, 0xfd5f, ++ 0x24c9, 0xfd58, 0x24fb, 0xfd51, 0x252d, 0xfd49, 0x255e, 0xfd42, ++ 0x2590, 0xfd3b, 0x25c2, 0xfd33, 0x25f4, 0xfd2c, 0x2625, 0xfd24, ++ 0x2657, 0xfd1d, 0x2689, 0xfd15, 0x26ba, 0xfd0e, 0x26ec, 0xfd06, ++ 0x271e, 0xfcfe, 0x274f, 0xfcf7, 0x2781, 0xfcef, 0x27b3, 0xfce7, ++ 0x27e4, 0xfcdf, 0x2816, 0xfcd8, 0x2848, 0xfcd0, 0x2879, 0xfcc8, ++ 0x28ab, 0xfcc0, 0x28dd, 0xfcb8, 0x290e, 0xfcb0, 0x2940, 0xfca8, ++ 0x2971, 0xfca0, 0x29a3, 0xfc97, 0x29d5, 0xfc8f, 0x2a06, 0xfc87, ++ 0x2a38, 0xfc7f, 0x2a69, 0xfc76, 0x2a9b, 0xfc6e, 0x2acc, 0xfc66, ++ 0x2afe, 0xfc5d, 0x2b30, 0xfc55, 0x2b61, 0xfc4c, 0x2b93, 0xfc44, ++ 0x2bc4, 0xfc3b, 0x2bf6, 0xfc33, 0x2c27, 0xfc2a, 0x2c59, 0xfc21, ++ 0x2c8a, 0xfc18, 0x2cbc, 0xfc10, 0x2ced, 0xfc07, 0x2d1f, 0xfbfe, ++ 0x2d50, 0xfbf5, 0x2d82, 0xfbec, 0x2db3, 0xfbe3, 0x2de5, 0xfbda, ++ 0x2e16, 0xfbd1, 0x2e47, 0xfbc8, 0x2e79, 0xfbbf, 0x2eaa, 0xfbb6, ++ 0x2edc, 0xfbad, 0x2f0d, 0xfba4, 0x2f3f, 0xfb9a, 0x2f70, 0xfb91, ++ 0x2fa1, 0xfb88, 0x2fd3, 0xfb7e, 0x3004, 0xfb75, 0x3035, 0xfb6b, ++ 0x3067, 0xfb62, 0x3098, 0xfb58, 0x30ca, 0xfb4f, 0x30fb, 0xfb45, ++ 0x312c, 0xfb3c, 0x315e, 0xfb32, 0x318f, 0xfb28, 0x31c0, 0xfb1f, ++ 0x31f1, 0xfb15, 0x3223, 0xfb0b, 0x3254, 0xfb01, 0x3285, 0xfaf7, ++ 0x32b7, 0xfaed, 0x32e8, 0xfae3, 0x3319, 0xfad9, 0x334a, 0xfacf, ++ 0x337c, 0xfac5, 0x33ad, 0xfabb, 0x33de, 0xfab1, 0x340f, 0xfaa7, ++ 0x3440, 0xfa9c, 0x3472, 0xfa92, 0x34a3, 0xfa88, 0x34d4, 0xfa7d, ++ 0x3505, 0xfa73, 0x3536, 0xfa69, 0x3568, 0xfa5e, 0x3599, 0xfa54, ++ 0x35ca, 0xfa49, 0x35fb, 0xfa3e, 0x362c, 0xfa34, 0x365d, 0xfa29, ++ 0x368e, 0xfa1f, 0x36c0, 0xfa14, 0x36f1, 0xfa09, 0x3722, 0xf9fe, ++ 0x3753, 0xf9f3, 0x3784, 0xf9e8, 0x37b5, 0xf9de, 0x37e6, 0xf9d3, ++ 0x3817, 0xf9c8, 0x3848, 0xf9bd, 0x3879, 0xf9b2, 0x38aa, 0xf9a6, ++ 0x38db, 0xf99b, 0x390c, 0xf990, 0x393d, 0xf985, 0x396e, 0xf97a, ++ 0x399f, 0xf96e, 0x39d0, 0xf963, 0x3a01, 0xf958, 0x3a32, 0xf94c, ++ 0x3a63, 0xf941, 0x3a94, 0xf935, 0x3ac5, 0xf92a, 0x3af6, 0xf91e, ++ 0x3b27, 0xf913, 0x3b58, 0xf907, 0x3b88, 0xf8fb, 0x3bb9, 0xf8f0, ++ 0x3bea, 0xf8e4, 0x3c1b, 0xf8d8, 0x3c4c, 0xf8cc, 0x3c7d, 0xf8c0, ++ 0x3cae, 0xf8b4, 0x3cde, 0xf8a9, 0x3d0f, 0xf89d, 0x3d40, 0xf891, ++ 0x3d71, 0xf885, 0x3da2, 0xf878, 0x3dd2, 0xf86c, 0x3e03, 0xf860, ++ 0x3e34, 0xf854, 0x3e65, 0xf848, 0x3e95, 0xf83b, 0x3ec6, 0xf82f, ++ 0x3ef7, 0xf823, 0x3f28, 0xf816, 0x3f58, 0xf80a, 0x3f89, 0xf7fe, ++ 0x3fba, 0xf7f1, 0x3fea, 0xf7e5, 0x401b, 0xf7d8, 0x404c, 0xf7cb, ++ 0x407c, 0xf7bf, 0x40ad, 0xf7b2, 0x40de, 0xf7a5, 0x410e, 0xf799, ++ 0x413f, 0xf78c, 0x416f, 0xf77f, 0x41a0, 0xf772, 0x41d1, 0xf765, ++ 0x4201, 0xf758, 0x4232, 0xf74b, 0x4262, 0xf73e, 0x4293, 0xf731, ++ 0x42c3, 0xf724, 0x42f4, 0xf717, 0x4324, 0xf70a, 0x4355, 0xf6fd, ++ 0x4385, 0xf6ef, 0x43b6, 0xf6e2, 0x43e6, 0xf6d5, 0x4417, 0xf6c7, ++ 0x4447, 0xf6ba, 0x4478, 0xf6ad, 0x44a8, 0xf69f, 0x44d9, 0xf692, ++ 0x4509, 0xf684, 0x4539, 0xf677, 0x456a, 0xf669, 0x459a, 0xf65b, ++ 0x45cb, 0xf64e, 0x45fb, 0xf640, 0x462b, 0xf632, 0x465c, 0xf624, ++ 0x468c, 0xf616, 0x46bc, 0xf609, 0x46ec, 0xf5fb, 0x471d, 0xf5ed, ++ 0x474d, 0xf5df, 0x477d, 0xf5d1, 0x47ae, 0xf5c3, 0x47de, 0xf5b5, ++ 0x480e, 0xf5a6, 0x483e, 0xf598, 0x486f, 0xf58a, 0x489f, 0xf57c, ++ 0x48cf, 0xf56e, 0x48ff, 0xf55f, 0x492f, 0xf551, 0x495f, 0xf543, ++ 0x4990, 0xf534, 0x49c0, 0xf526, 0x49f0, 0xf517, 0x4a20, 0xf509, ++ 0x4a50, 0xf4fa, 0x4a80, 0xf4eb, 0x4ab0, 0xf4dd, 0x4ae0, 0xf4ce, ++ 0x4b10, 0xf4bf, 0x4b40, 0xf4b1, 0x4b71, 0xf4a2, 0x4ba1, 0xf493, ++ 0x4bd1, 0xf484, 0x4c01, 0xf475, 0x4c31, 0xf466, 0x4c61, 0xf457, ++ 0x4c90, 0xf448, 0x4cc0, 0xf439, 0x4cf0, 0xf42a, 0x4d20, 0xf41b, ++ 0x4d50, 0xf40c, 0x4d80, 0xf3fd, 0x4db0, 0xf3ed, 0x4de0, 0xf3de, ++ 0x4e10, 0xf3cf, 0x4e40, 0xf3c0, 0x4e70, 0xf3b0, 0x4e9f, 0xf3a1, ++ 0x4ecf, 0xf391, 0x4eff, 0xf382, 0x4f2f, 0xf372, 0x4f5f, 0xf363, ++ 0x4f8e, 0xf353, 0x4fbe, 0xf343, 0x4fee, 0xf334, 0x501e, 0xf324, ++ 0x504d, 0xf314, 0x507d, 0xf304, 0x50ad, 0xf2f5, 0x50dd, 0xf2e5, ++ 0x510c, 0xf2d5, 0x513c, 0xf2c5, 0x516c, 0xf2b5, 0x519b, 0xf2a5, ++ 0x51cb, 0xf295, 0x51fb, 0xf285, 0x522a, 0xf275, 0x525a, 0xf265, ++ 0x5289, 0xf254, 0x52b9, 0xf244, 0x52e8, 0xf234, 0x5318, 0xf224, ++ 0x5348, 0xf213, 0x5377, 0xf203, 0x53a7, 0xf1f3, 0x53d6, 0xf1e2, ++ 0x5406, 0xf1d2, 0x5435, 0xf1c1, 0x5464, 0xf1b1, 0x5494, 0xf1a0, ++ 0x54c3, 0xf18f, 0x54f3, 0xf17f, 0x5522, 0xf16e, 0x5552, 0xf15d, ++ 0x5581, 0xf14c, 0x55b0, 0xf13c, 0x55e0, 0xf12b, 0x560f, 0xf11a, ++ 0x563e, 0xf109, 0x566e, 0xf0f8, 0x569d, 0xf0e7, 0x56cc, 0xf0d6, ++ 0x56fc, 0xf0c5, 0x572b, 0xf0b4, 0x575a, 0xf0a3, 0x5789, 0xf092, ++ 0x57b9, 0xf080, 0x57e8, 0xf06f, 0x5817, 0xf05e, 0x5846, 0xf04d, ++ 0x5875, 0xf03b, 0x58a5, 0xf02a, 0x58d4, 0xf018, 0x5903, 0xf007, ++ 0x5932, 0xeff5, 0x5961, 0xefe4, 0x5990, 0xefd2, 0x59bf, 0xefc1, ++ 0x59ee, 0xefaf, 0x5a1d, 0xef9d, 0x5a4c, 0xef8c, 0x5a7b, 0xef7a, ++ 0x5aaa, 0xef68, 0x5ad9, 0xef56, 0x5b08, 0xef45, 0x5b37, 0xef33, ++ 0x5b66, 0xef21, 0x5b95, 0xef0f, 0x5bc4, 0xeefd, 0x5bf3, 0xeeeb, ++ 0x5c22, 0xeed9, 0x5c51, 0xeec7, 0x5c80, 0xeeb4, 0x5caf, 0xeea2, ++ 0x5cde, 0xee90, 0x5d0c, 0xee7e, 0x5d3b, 0xee6b, 0x5d6a, 0xee59, ++ 0x5d99, 0xee47, 0x5dc8, 0xee34, 0x5df6, 0xee22, 0x5e25, 0xee0f, ++ 0x5e54, 0xedfd, 0x5e83, 0xedea, 0x5eb1, 0xedd8, 0x5ee0, 0xedc5, ++ 0x5f0f, 0xedb3, 0x5f3d, 0xeda0, 0x5f6c, 0xed8d, 0x5f9b, 0xed7a, ++ 0x5fc9, 0xed68, 0x5ff8, 0xed55, 0x6026, 0xed42, 0x6055, 0xed2f, ++ 0x6084, 0xed1c, 0x60b2, 0xed09, 0x60e1, 0xecf6, 0x610f, 0xece3, ++ 0x613e, 0xecd0, 0x616c, 0xecbd, 0x619b, 0xecaa, 0x61c9, 0xec97, ++ 0x61f8, 0xec83, 0x6226, 0xec70, 0x6254, 0xec5d, 0x6283, 0xec4a, ++ 0x62b1, 0xec36, 0x62e0, 0xec23, 0x630e, 0xec0f, 0x633c, 0xebfc, ++ 0x636b, 0xebe8, 0x6399, 0xebd5, 0x63c7, 0xebc1, 0x63f5, 0xebae, ++ 0x6424, 0xeb9a, 0x6452, 0xeb86, 0x6480, 0xeb73, 0x64ae, 0xeb5f, ++ 0x64dd, 0xeb4b, 0x650b, 0xeb37, 0x6539, 0xeb23, 0x6567, 0xeb0f, ++ 0x6595, 0xeafc, 0x65c3, 0xeae8, 0x65f2, 0xead4, 0x6620, 0xeac0, ++ 0x664e, 0xeaab, 0x667c, 0xea97, 0x66aa, 0xea83, 0x66d8, 0xea6f, ++ 0x6706, 0xea5b, 0x6734, 0xea47, 0x6762, 0xea32, 0x6790, 0xea1e, ++ 0x67be, 0xea0a, 0x67ec, 0xe9f5, 0x681a, 0xe9e1, 0x6848, 0xe9cc, ++ 0x6876, 0xe9b8, 0x68a3, 0xe9a3, 0x68d1, 0xe98f, 0x68ff, 0xe97a, ++ 0x692d, 0xe966, 0x695b, 0xe951, 0x6989, 0xe93c, 0x69b6, 0xe927, ++ 0x69e4, 0xe913, 0x6a12, 0xe8fe, 0x6a40, 0xe8e9, 0x6a6d, 0xe8d4, ++ 0x6a9b, 0xe8bf, 0x6ac9, 0xe8aa, 0x6af6, 0xe895, 0x6b24, 0xe880, ++ 0x6b52, 0xe86b, 0x6b7f, 0xe856, 0x6bad, 0xe841, 0x6bdb, 0xe82c, ++ 0x6c08, 0xe817, 0x6c36, 0xe801, 0x6c63, 0xe7ec, 0x6c91, 0xe7d7, ++ 0x6cbe, 0xe7c2, 0x6cec, 0xe7ac, 0x6d19, 0xe797, 0x6d47, 0xe781, ++ 0x6d74, 0xe76c, 0x6da2, 0xe756, 0x6dcf, 0xe741, 0x6dfc, 0xe72b, ++ 0x6e2a, 0xe716, 0x6e57, 0xe700, 0x6e85, 0xe6ea, 0x6eb2, 0xe6d5, ++ 0x6edf, 0xe6bf, 0x6f0d, 0xe6a9, 0x6f3a, 0xe693, 0x6f67, 0xe67d, ++ 0x6f94, 0xe667, 0x6fc2, 0xe652, 0x6fef, 0xe63c, 0x701c, 0xe626, ++ 0x7049, 0xe610, 0x7076, 0xe5f9, 0x70a3, 0xe5e3, 0x70d1, 0xe5cd, ++ 0x70fe, 0xe5b7, 0x712b, 0xe5a1, 0x7158, 0xe58b, 0x7185, 0xe574, ++ 0x71b2, 0xe55e, 0x71df, 0xe548, 0x720c, 0xe531, 0x7239, 0xe51b, ++ 0x7266, 0xe504, 0x7293, 0xe4ee, 0x72c0, 0xe4d7, 0x72ed, 0xe4c1, ++ 0x731a, 0xe4aa, 0x7347, 0xe494, 0x7373, 0xe47d, 0x73a0, 0xe466, ++ 0x73cd, 0xe450, 0x73fa, 0xe439, 0x7427, 0xe422, 0x7454, 0xe40b, ++ 0x7480, 0xe3f4, 0x74ad, 0xe3de, 0x74da, 0xe3c7, 0x7507, 0xe3b0, ++ 0x7533, 0xe399, 0x7560, 0xe382, 0x758d, 0xe36b, 0x75b9, 0xe353, ++ 0x75e6, 0xe33c, 0x7612, 0xe325, 0x763f, 0xe30e, 0x766c, 0xe2f7, ++ 0x7698, 0xe2df, 0x76c5, 0xe2c8, 0x76f1, 0xe2b1, 0x771e, 0xe299, ++ 0x774a, 0xe282, 0x7777, 0xe26b, 0x77a3, 0xe253, 0x77d0, 0xe23c, ++ 0x77fc, 0xe224, 0x7828, 0xe20d, 0x7855, 0xe1f5, 0x7881, 0xe1dd, ++ 0x78ad, 0xe1c6, 0x78da, 0xe1ae, 0x7906, 0xe196, 0x7932, 0xe17e, ++ 0x795f, 0xe167, 0x798b, 0xe14f, 0x79b7, 0xe137, 0x79e3, 0xe11f, ++ 0x7a10, 0xe107, 0x7a3c, 0xe0ef, 0x7a68, 0xe0d7, 0x7a94, 0xe0bf, ++ 0x7ac0, 0xe0a7, 0x7aec, 0xe08f, 0x7b18, 0xe077, 0x7b44, 0xe05e, ++ 0x7b70, 0xe046, 0x7b9c, 0xe02e, 0x7bc8, 0xe016, 0x7bf4, 0xdffd, ++ 0x7c20, 0xdfe5, 0x7c4c, 0xdfcd, 0x7c78, 0xdfb4, 0x7ca4, 0xdf9c, ++ 0x7cd0, 0xdf83, 0x7cfc, 0xdf6b, 0x7d28, 0xdf52, 0x7d54, 0xdf39, ++ 0x7d7f, 0xdf21, 0x7dab, 0xdf08, 0x7dd7, 0xdef0, 0x7e03, 0xded7, ++ 0x7e2f, 0xdebe, 0x7e5a, 0xdea5, 0x7e86, 0xde8c, 0x7eb2, 0xde74, ++ 0x7edd, 0xde5b, 0x7f09, 0xde42, 0x7f35, 0xde29, 0x7f60, 0xde10, ++ 0x7f8c, 0xddf7, 0x7fb7, 0xddde, 0x7fe3, 0xddc5, 0x800f, 0xddab, ++ 0x803a, 0xdd92, 0x8066, 0xdd79, 0x8091, 0xdd60, 0x80bc, 0xdd47, ++ 0x80e8, 0xdd2d, 0x8113, 0xdd14, 0x813f, 0xdcfb, 0x816a, 0xdce1, ++ 0x8195, 0xdcc8, 0x81c1, 0xdcae, 0x81ec, 0xdc95, 0x8217, 0xdc7b, ++ 0x8243, 0xdc62, 0x826e, 0xdc48, 0x8299, 0xdc2f, 0x82c4, 0xdc15, ++ 0x82f0, 0xdbfb, 0x831b, 0xdbe1, 0x8346, 0xdbc8, 0x8371, 0xdbae, ++ 0x839c, 0xdb94, 0x83c7, 0xdb7a, 0x83f2, 0xdb60, 0x841d, 0xdb46, ++ 0x8449, 0xdb2c, 0x8474, 0xdb12, 0x849f, 0xdaf8, 0x84ca, 0xdade, ++ 0x84f5, 0xdac4, 0x851f, 0xdaaa, 0x854a, 0xda90, 0x8575, 0xda76, ++ 0x85a0, 0xda5c, 0x85cb, 0xda41, 0x85f6, 0xda27, 0x8621, 0xda0d, ++ 0x864c, 0xd9f2, 0x8676, 0xd9d8, 0x86a1, 0xd9be, 0x86cc, 0xd9a3, ++ 0x86f7, 0xd989, 0x8721, 0xd96e, 0x874c, 0xd954, 0x8777, 0xd939, ++ 0x87a1, 0xd91e, 0x87cc, 0xd904, 0x87f6, 0xd8e9, 0x8821, 0xd8ce, ++ 0x884c, 0xd8b4, 0x8876, 0xd899, 0x88a1, 0xd87e, 0x88cb, 0xd863, ++ 0x88f6, 0xd848, 0x8920, 0xd82d, 0x894a, 0xd812, 0x8975, 0xd7f8, ++ 0x899f, 0xd7dc, 0x89ca, 0xd7c1, 0x89f4, 0xd7a6, 0x8a1e, 0xd78b, ++ 0x8a49, 0xd770, 0x8a73, 0xd755, 0x8a9d, 0xd73a, 0x8ac7, 0xd71f, ++ 0x8af2, 0xd703, 0x8b1c, 0xd6e8, 0x8b46, 0xd6cd, 0x8b70, 0xd6b1, ++ 0x8b9a, 0xd696, 0x8bc5, 0xd67a, 0x8bef, 0xd65f, 0x8c19, 0xd644, ++ 0x8c43, 0xd628, 0x8c6d, 0xd60c, 0x8c97, 0xd5f1, 0x8cc1, 0xd5d5, ++ 0x8ceb, 0xd5ba, 0x8d15, 0xd59e, 0x8d3f, 0xd582, 0x8d69, 0xd566, ++ 0x8d93, 0xd54b, 0x8dbc, 0xd52f, 0x8de6, 0xd513, 0x8e10, 0xd4f7, ++ 0x8e3a, 0xd4db, 0x8e64, 0xd4bf, 0x8e8d, 0xd4a3, 0x8eb7, 0xd487, ++ 0x8ee1, 0xd46b, 0x8f0b, 0xd44f, 0x8f34, 0xd433, 0x8f5e, 0xd417, ++ 0x8f88, 0xd3fb, 0x8fb1, 0xd3df, 0x8fdb, 0xd3c2, 0x9004, 0xd3a6, ++ 0x902e, 0xd38a, 0x9057, 0xd36d, 0x9081, 0xd351, 0x90aa, 0xd335, ++ 0x90d4, 0xd318, 0x90fd, 0xd2fc, 0x9127, 0xd2df, 0x9150, 0xd2c3, ++ 0x9179, 0xd2a6, 0x91a3, 0xd28a, 0x91cc, 0xd26d, 0x91f5, 0xd250, ++ 0x921f, 0xd234, 0x9248, 0xd217, 0x9271, 0xd1fa, 0x929a, 0xd1de, ++ 0x92c4, 0xd1c1, 0x92ed, 0xd1a4, 0x9316, 0xd187, 0x933f, 0xd16a, ++ 0x9368, 0xd14d, 0x9391, 0xd130, 0x93ba, 0xd113, 0x93e3, 0xd0f6, ++ 0x940c, 0xd0d9, 0x9435, 0xd0bc, 0x945e, 0xd09f, 0x9487, 0xd082, ++ 0x94b0, 0xd065, 0x94d9, 0xd047, 0x9502, 0xd02a, 0x952b, 0xd00d, ++ 0x9554, 0xcff0, 0x957d, 0xcfd2, 0x95a5, 0xcfb5, 0x95ce, 0xcf98, ++ 0x95f7, 0xcf7a, 0x9620, 0xcf5d, 0x9648, 0xcf3f, 0x9671, 0xcf22, ++ 0x969a, 0xcf04, 0x96c2, 0xcee7, 0x96eb, 0xcec9, 0x9713, 0xceab, ++ 0x973c, 0xce8e, 0x9765, 0xce70, 0x978d, 0xce52, 0x97b6, 0xce34, ++ 0x97de, 0xce17, 0x9807, 0xcdf9, 0x982f, 0xcddb, 0x9857, 0xcdbd, ++ 0x9880, 0xcd9f, 0x98a8, 0xcd81, 0x98d0, 0xcd63, 0x98f9, 0xcd45, ++ 0x9921, 0xcd27, 0x9949, 0xcd09, 0x9972, 0xcceb, 0x999a, 0xcccd, ++ 0x99c2, 0xccae, 0x99ea, 0xcc90, 0x9a12, 0xcc72, 0x9a3a, 0xcc54, ++ 0x9a63, 0xcc35, 0x9a8b, 0xcc17, 0x9ab3, 0xcbf9, 0x9adb, 0xcbda, ++ 0x9b03, 0xcbbc, 0x9b2b, 0xcb9e, 0x9b53, 0xcb7f, 0x9b7b, 0xcb61, ++ 0x9ba3, 0xcb42, 0x9bca, 0xcb23, 0x9bf2, 0xcb05, 0x9c1a, 0xcae6, ++ 0x9c42, 0xcac7, 0x9c6a, 0xcaa9, 0x9c92, 0xca8a, 0x9cb9, 0xca6b, ++ 0x9ce1, 0xca4d, 0x9d09, 0xca2e, 0x9d31, 0xca0f, 0x9d58, 0xc9f0, ++ 0x9d80, 0xc9d1, 0x9da7, 0xc9b2, 0x9dcf, 0xc993, 0x9df7, 0xc974, ++ 0x9e1e, 0xc955, 0x9e46, 0xc936, 0x9e6d, 0xc917, 0x9e95, 0xc8f8, ++ 0x9ebc, 0xc8d9, 0x9ee3, 0xc8ba, 0x9f0b, 0xc89a, 0x9f32, 0xc87b, ++ 0x9f5a, 0xc85c, 0x9f81, 0xc83c, 0x9fa8, 0xc81d, 0x9fd0, 0xc7fe, ++ 0x9ff7, 0xc7de, 0xa01e, 0xc7bf, 0xa045, 0xc7a0, 0xa06c, 0xc780, ++ 0xa094, 0xc761, 0xa0bb, 0xc741, 0xa0e2, 0xc721, 0xa109, 0xc702, ++ 0xa130, 0xc6e2, 0xa157, 0xc6c2, 0xa17e, 0xc6a3, 0xa1a5, 0xc683, ++ 0xa1cc, 0xc663, 0xa1f3, 0xc644, 0xa21a, 0xc624, 0xa241, 0xc604, ++ 0xa268, 0xc5e4, 0xa28e, 0xc5c4, 0xa2b5, 0xc5a4, 0xa2dc, 0xc584, ++ 0xa303, 0xc564, 0xa32a, 0xc544, 0xa350, 0xc524, 0xa377, 0xc504, ++ 0xa39e, 0xc4e4, 0xa3c4, 0xc4c4, 0xa3eb, 0xc4a4, 0xa412, 0xc483, ++ 0xa438, 0xc463, 0xa45f, 0xc443, 0xa485, 0xc423, 0xa4ac, 0xc402, ++ 0xa4d2, 0xc3e2, 0xa4f9, 0xc3c2, 0xa51f, 0xc3a1, 0xa545, 0xc381, ++ 0xa56c, 0xc360, 0xa592, 0xc340, 0xa5b8, 0xc31f, 0xa5df, 0xc2ff, ++ 0xa605, 0xc2de, 0xa62b, 0xc2be, 0xa652, 0xc29d, 0xa678, 0xc27c, ++ 0xa69e, 0xc25c, 0xa6c4, 0xc23b, 0xa6ea, 0xc21a, 0xa710, 0xc1f9, ++ 0xa736, 0xc1d8, 0xa75c, 0xc1b8, 0xa782, 0xc197, 0xa7a8, 0xc176, ++ 0xa7ce, 0xc155, 0xa7f4, 0xc134, 0xa81a, 0xc113, 0xa840, 0xc0f2, ++ 0xa866, 0xc0d1, 0xa88c, 0xc0b0, 0xa8b2, 0xc08f, 0xa8d7, 0xc06e, ++ 0xa8fd, 0xc04c, 0xa923, 0xc02b, 0xa949, 0xc00a, 0xa96e, 0xbfe9, ++ 0xa994, 0xbfc7, 0xa9ba, 0xbfa6, 0xa9df, 0xbf85, 0xaa05, 0xbf63, ++ 0xaa2a, 0xbf42, 0xaa50, 0xbf21, 0xaa76, 0xbeff, 0xaa9b, 0xbede, ++ 0xaac1, 0xbebc, 0xaae6, 0xbe9b, 0xab0b, 0xbe79, 0xab31, 0xbe57, ++ 0xab56, 0xbe36, 0xab7b, 0xbe14, 0xaba1, 0xbdf2, 0xabc6, 0xbdd1, ++ 0xabeb, 0xbdaf, 0xac11, 0xbd8d, 0xac36, 0xbd6b, 0xac5b, 0xbd4a, ++ 0xac80, 0xbd28, 0xaca5, 0xbd06, 0xacca, 0xbce4, 0xacef, 0xbcc2, ++ 0xad14, 0xbca0, 0xad39, 0xbc7e, 0xad5e, 0xbc5c, 0xad83, 0xbc3a, ++ 0xada8, 0xbc18, 0xadcd, 0xbbf6, 0xadf2, 0xbbd4, 0xae17, 0xbbb1, ++ 0xae3c, 0xbb8f, 0xae61, 0xbb6d, 0xae85, 0xbb4b, 0xaeaa, 0xbb28, ++ 0xaecf, 0xbb06, 0xaef4, 0xbae4, 0xaf18, 0xbac1, 0xaf3d, 0xba9f, ++ 0xaf62, 0xba7d, 0xaf86, 0xba5a, 0xafab, 0xba38, 0xafcf, 0xba15, ++ 0xaff4, 0xb9f3, 0xb018, 0xb9d0, 0xb03d, 0xb9ae, 0xb061, 0xb98b, ++ 0xb086, 0xb968, 0xb0aa, 0xb946, 0xb0ce, 0xb923, 0xb0f3, 0xb900, ++ 0xb117, 0xb8dd, 0xb13b, 0xb8bb, 0xb160, 0xb898, 0xb184, 0xb875, ++ 0xb1a8, 0xb852, 0xb1cc, 0xb82f, 0xb1f0, 0xb80c, 0xb215, 0xb7e9, ++ 0xb239, 0xb7c6, 0xb25d, 0xb7a3, 0xb281, 0xb780, 0xb2a5, 0xb75d, ++ 0xb2c9, 0xb73a, 0xb2ed, 0xb717, 0xb311, 0xb6f4, 0xb335, 0xb6d1, ++ 0xb358, 0xb6ad, 0xb37c, 0xb68a, 0xb3a0, 0xb667, 0xb3c4, 0xb644, ++ 0xb3e8, 0xb620, 0xb40b, 0xb5fd, 0xb42f, 0xb5da, 0xb453, 0xb5b6, ++ 0xb477, 0xb593, 0xb49a, 0xb56f, 0xb4be, 0xb54c, 0xb4e1, 0xb528, ++ 0xb505, 0xb505 ++}; ++ ++static const FIXPU pow128_tab[128] = { ++ /* x_i = 2^(15+i/128) */ ++ 0x8000, 0x80b2, 0x8165, 0x8219, 0x82ce, 0x8383, 0x843a, 0x84f2, 0x85ab, ++ 0x8665, 0x871f, 0x87db, 0x8898, 0x8956, 0x8a15, 0x8ad5, 0x8b96, 0x8c58, ++ 0x8d1b, 0x8ddf, 0x8ea4, 0x8f6b, 0x9032, 0x90fa, 0x91c4, 0x928e, 0x935a, ++ 0x9427, 0x94f5, 0x95c4, 0x9694, 0x9765, 0x9838, 0x990c, 0x99e0, 0x9ab6, ++ 0x9b8d, 0x9c65, 0x9d3f, 0x9e19, 0x9ef5, 0x9fd2, 0xa0b0, 0xa190, 0xa270, ++ 0xa352, 0xa435, 0xa519, 0xa5ff, 0xa6e6, 0xa7ce, 0xa8b7, 0xa9a1, 0xaa8d, ++ 0xab7a, 0xac69, 0xad58, 0xae49, 0xaf3b, 0xb02f, 0xb124, 0xb21a, 0xb312, ++ 0xb40b, 0xb505, 0xb601, 0xb6fe, 0xb7fc, 0xb8fc, 0xb9fd, 0xbaff, 0xbc03, ++ 0xbd09, 0xbe0f, 0xbf18, 0xc021, 0xc12c, 0xc239, 0xc347, 0xc456, 0xc567, ++ 0xc67a, 0xc78d, 0xc8a3, 0xc9ba, 0xcad2, 0xcbec, 0xcd08, 0xce25, 0xcf43, ++ 0xd063, 0xd185, 0xd2a8, 0xd3cd, 0xd4f3, 0xd61b, 0xd745, 0xd870, 0xd99d, ++ 0xdacc, 0xdbfc, 0xdd2e, 0xde61, 0xdf96, 0xe0cd, 0xe205, 0xe340, 0xe47b, ++ 0xe5b9, 0xe6f8, 0xe839, 0xe97c, 0xeac1, 0xec07, 0xed4f, 0xee99, 0xefe5, ++ 0xf132, 0xf281, 0xf3d3, 0xf525, 0xf67a, 0xf7d1, 0xf929, 0xfa84, 0xfbe0, ++ 0xfd3e, 0xfe9e ++}; ++ ++ ++/* dither_table and quant_centroid_table. ++ * Index 1: [0] - scaled by 2^13, [1] - scaled by 2^13 / sqrt(2) ++ * Index 2: [0..7] - category ++ * Index 3: [0] - dither_table, [1..13] - quant_centroid_table ++ */ ++static const FIXP quant_tables[2][8][14] = {{{ ++ 0x00000000, 0x0645a1cb, 0x0c2d0e56, 0x11eb851f, 0x17a1cac1, 0x1d4fdf3b, ++ 0x22ed9168, 0x28a7ef9e, 0x2e49ba5e, 0x33eb851f, 0x39916873, 0x3f126e98, ++ 0x449ba5e3, 0x4b958106 ++},{ ++ 0x00000000, 0x08b43958, 0x10f5c28f, 0x19020c4a, 0x2116872b, 0x2922d0e5, ++ 0x3126e979, 0x38fdf3b6, 0x411eb852, 0x49eb851f, 0x00000000, 0x00000000, ++ 0x00000000, 0x00000000 ++},{ ++ 0x00000000, 0x0bef9db2, 0x176c8b44, 0x22e147ae, 0x2e1cac08, 0x39581062, ++ 0x450e5604, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, ++ 0x00000000, 0x00000000 ++},{ ++ 0x00000000, 0x10189375, 0x20000000, 0x2fe353f8, 0x3fc28f5c, 0x00000000, ++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, ++ 0x00000000, 0x00000000 ++},{ ++ 0x00000000, 0x1522d0e5, 0x2b3f7cee, 0x3fba5e35, 0x00000000, 0x00000000, ++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, ++ 0x00000000, 0x00000000 ++},{ ++ 0x02d413cd, 0x1a83126f, 0x37db22d1, 0x00000000, 0x00000000, 0x00000000, ++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, ++ 0x00000000, 0x00000000 ++},{ ++ 0x04000000, 0x1f6c8b44, 0x00000000, 0x00000000, 0x00000000, 0x00000000, ++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, ++ 0x00000000, 0x00000000 ++},{ ++ 0x0b504f33, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, ++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, ++ 0x00000000, 0x00000000 ++}},{{ ++ 0x00000000, 0x046f5a70, 0x089c1768, 0x0cabddd3, 0x10b5d955, 0x14ba09ed, ++ 0x18b2a4b4, 0x1cbf85aa, 0x20bb05e5, 0x24b68620, 0x28b4ebcf, 0x2c994066, ++ 0x30835fe6, 0x35722a5e ++},{ ++ 0x00000000, 0x062797a1, 0x0bfe1683, 0x11aeee7a, 0x1765915b, 0x1d166952, ++ 0x22c17660, 0x284ca76c, 0x2e0bfaaa, 0x3444f306, 0x00000000, 0x00000000, ++ 0x00000000, 0x00000000 ++},{ ++ 0x00000000, 0x0870a594, 0x1090326a, 0x18a9f456, 0x209b29e3, 0x288c5f70, ++ 0x30d478a5, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, ++ 0x00000000, 0x00000000 ++},{ ++ 0x00000000, 0x0b61afee, 0x16a09e66, 0x21dca76a, 0x2d15caf9, 0x00000000, ++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, ++ 0x00000000, 0x00000000 ++},{ ++ 0x00000000, 0x0ef20652, 0x1e94b968, 0x2d100010, 0x00000000, 0x00000000, ++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, ++ 0x00000000, 0x00000000 ++},{ ++ 0x02000000, 0x12bf2f44, 0x277f041b, 0x00000000, 0x00000000, 0x00000000, ++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, ++ 0x00000000, 0x00000000 ++},{ ++ 0x02d413cd, 0x16385a03, 0x00000000, 0x00000000, 0x00000000, 0x00000000, ++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, ++ 0x00000000, 0x00000000 ++},{ ++ 0x08000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, ++ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, ++ 0x00000000, 0x00000000 ++}}}; ++ ++static const FIXPU cplscale2[3] = { ++ /* 2^16 C_ij */ ++ 0xf3f9, 0xb505, 0x4d8b ++}; ++static const FIXPU cplscale3[7] = { ++ /* 2^16 C_ij */ ++ 0xfb35, 0xefdf, 0xe03d, 0xb505, 0x7b81, 0x596e, 0x314d ++}; ++static const FIXPU cplscale4[15] = { ++ /* 2^16 C_ij */ ++ 0xfdd2, 0xf927, 0xf3f9, 0xee1d, 0xe749, 0xdee9, 0xd381, 0xb505, 0x903b, ++ 0x7de2, 0x6dbe, 0x5e02, 0x4d8b, 0x3ad1, 0x2155 ++}; ++static const FIXPU cplscale5[31] = { ++ /* 2^16 C_ij */ ++ 0xfef5, 0xfcce, 0xfa8e, 0xf832, 0xf5b5, 0xf314, 0xf049, 0xed4c, 0xea12, ++ 0xe68e, 0xe2ab, 0xde4b, 0xd938, 0xd30b, 0xcab6, 0xb505, 0x9c59, 0x90e8, ++ 0x8778, 0x7ef9, 0x76fc, 0x6f45, 0x67ab, 0x600e, 0x5850, 0x504d, 0x47db, ++ 0x3ebd, 0x3486, 0x2853, 0x1715 ++}; ++static const FIXPU cplscale6[63] = { ++ /* 2^16 C_ij */ ++ 0xff7d, 0xfe74, 0xfd65, 0xfc50, 0xfb35, 0xfa14, 0xf8eb, 0xf7bb, 0xf683, ++ 0xf543, 0xf3f9, 0xf2a6, 0xf148, 0xefdf, 0xee6a, 0xece6, 0xeb54, 0xe9b2, ++ 0xe7fd, 0xe634, 0xe453, 0xe258, 0xe03d, 0xddff, 0xdb94, 0xd8f4, 0xd610, ++ 0xd2d2, 0xcf13, 0xca8c, 0xc47c, 0xb505, 0xa41a, 0x9c90, 0x9685, 0x913a, ++ 0x8c67, 0x87e5, 0x839c, 0x7f7e, 0x7b81, 0x779b, 0x73c7, 0x6fff, 0x6c3f, ++ 0x6883, 0x64c7, 0x6107, 0x5d40, 0x596e, 0x558d, 0x5198, 0x4d8b, 0x495f, ++ 0x450d, 0x408b, 0x3bcd, 0x36c1, 0x314d, 0x2b4a, 0x246e, 0x1c1a, 0x1029 ++}; ++ ++static const FIXPU* cplscales[5] = { ++ cplscale2, cplscale3, cplscale4, cplscale5, cplscale6 ++}; ++ Index: rm2wav.c =================================================================== --- rm2wav.c (revision 0) +++ rm2wav.c (revision 0) @@ -0,0 +1,566 @@ + +#include +#include +#include +#include +#include +#include +#include + +#include "id3.h" +#include "rm.h" + +#define MAX_PATH 260 +#define PKT_HEADER_SIZE 12 +#define RAW_AUDIO_DATA packet_length-PKT_HEADER_SIZE + + +#if 0 +#define DEBUG +#define DEBUGF printf +#else +#define DEBUGF(...) +#endif + +/* ASF codec IDs */ +#define CODEC_ID_WMAV1 0x160 +#define CODEC_ID_WMAV2 0x161 + +struct waveformatex_t { + uint16_t codec_id; + uint16_t channels; + uint32_t rate; + uint32_t bitrate; + uint16_t blockalign; + uint16_t bitspersample; + uint16_t datalen; + uint8_t data[6]; +}; + +int open_wav(char* filename) { + int fd; + + fd=open(filename,O_CREAT|O_WRONLY|O_TRUNC,S_IRUSR,S_IWUSR); + if (fd >= 0) { + write(fd,wav_header,sizeof(wav_header)); + } + + return(fd); +} + +void close_wav(int fd, RMContext *rmctx) { + int x; + int filesize; + int bytes_per_sample = 2; + int samples_per_frame = rmctx->samples_pf_pc; + int nb_channels = rmctx->nb_channels; + int frame_size = rmctx->block_align; + int sample_rate = rmctx->sample_rate; + int nb_frames = rmctx->audio_framesize/rmctx->block_align * rmctx->nb_packets - 2; // first 2 frames have no valid audio; skipped in output + + filesize= samples_per_frame*bytes_per_sample*nb_frames +44; + printf("Filesize = %d\n",filesize); + + // ChunkSize + x=filesize-8; + wav_header[4]=(x&0xff); + wav_header[5]=(x&0xff00)>>8; + wav_header[6]=(x&0xff0000)>>16; + wav_header[7]=(x&0xff000000)>>24; + + // Number of channels + wav_header[22]=nb_channels; + + // Samplerate + wav_header[24]=sample_rate&0xff; + wav_header[25]=(sample_rate&0xff00)>>8; + wav_header[26]=(sample_rate&0xff0000)>>16; + wav_header[27]=(sample_rate&0xff000000)>>24; + + // ByteRate + x=sample_rate*bytes_per_sample*nb_channels; + wav_header[28]=(x&0xff); + wav_header[29]=(x&0xff00)>>8; + wav_header[30]=(x&0xff0000)>>16; + wav_header[31]=(x&0xff000000)>>24; + + // BlockAlign + wav_header[32]=rmctx->block_align;//2*rmctx->nb_channels; + + // Bits per sample + wav_header[34]=16; + + // Subchunk2Size + x=filesize-44; + wav_header[40]=(x&0xff); + wav_header[41]=(x&0xff00)>>8; + wav_header[42]=(x&0xff0000)>>16; + wav_header[43]=(x&0xff000000)>>24; + + lseek(fd,0,SEEK_SET); + write(fd,wav_header,sizeof(wav_header)); + close(fd); +} + +/* Some Rockbox-like functions (these should be implemented in metadata_common.[ch] */ +struct cook_extradata { + uint32_t cook_version; + uint16_t samples_pf_pc; /* samples per frame per channel */ + uint16_t nb_subbands; /* number of subbands in the frequency domain */ + + /* extra 8 bytes for stereo data */ + uint32_t unused; + uint16_t js_subband_start; /* joint stereo subband start */ + uint16_t js_vlc_bits; +}; + +static int read_uint8(int fd, uint8_t* buf) +{ + unsigned char tmp[1]; + int res; + + res=read(fd, tmp, 1); + *buf = tmp[0]; + return res; +} + +static int read_uint16be(int fd, uint16_t* buf) +{ + unsigned char tmp[2]; + int res; + + res=read(fd, tmp, 2); + *buf = (tmp[0] << 8) | tmp[1]; + return res; +} + +static int read_uint32be(int fd, uint32_t* buf) +{ + unsigned char tmp[4]; + int res; + + res=read(fd, tmp, 4); + *buf = (tmp[0] << 24) | (tmp[1] << 16) | (tmp[2] << 8) | tmp[3]; + return res; +} + +off_t filesize(int fd) +{ + struct stat buf; + + if (fstat(fd,&buf) == -1) { + return -1; + } else { + return buf.st_size; + } +} + +int read_cook_extradata(int fd, RMContext *rmctx) { + read_uint32be(fd, &rmctx->cook_version); + read_uint16be(fd, &rmctx->samples_pf_pc); + read_uint16be(fd, &rmctx->nb_subbands); + if(rmctx->extradata_size == 16) { + read_uint32be(fd, &rmctx->unused); + read_uint16be(fd, &rmctx->js_subband_start); + read_uint16be(fd, &rmctx->js_vlc_bits); + } + return rmctx->extradata_size; /* for 'skipped' */ +} + +void print_cook_extradata(RMContext *rmctx) { + + printf(" cook_version = 0x%08x\n", rmctx->cook_version); + printf(" samples_per_frame_per_channel = %d\n", rmctx->samples_pf_pc); + printf(" number_of_subbands_in_freq_domain = %d\n", rmctx->nb_subbands); + if(rmctx->extradata_size == 16) { + printf(" joint_stereo_subband_start = %d\n",rmctx->js_subband_start); + printf(" joint_stereo_vlc_bits = %d\n", rmctx->js_vlc_bits); + } +} + + +struct real_object_t +{ + uint32_t fourcc; + uint32_t size; + uint16_t version; +}; + +#define FOURCC(a,b,c,d) (((a)<<24) | ((b) << 16) | ((c) << 8) | (d)) + +static int real_read_object_header(int fd, struct real_object_t* obj) +{ + int n; + + if ((n = read_uint32be(fd, &obj->fourcc)) <= 0) return n; + if ((n = read_uint32be(fd, &obj->size)) <= 0) return n; + if ((n = read_uint16be(fd, &obj->version)) <= 0) return n; + + return 1; +} + +static char* fourcc2str(uint32_t f) +{ + static char res[5]; + + res[0] = (f & 0xff000000) >> 24; + res[1] = (f & 0xff0000) >> 16; + res[2] = (f & 0xff00) >> 8; + res[3] = (f & 0xff); + res[4] = 0; + + return res; +} + +static int read_str(int fd, char* buf) +{ + uint8_t len; + + read(fd, &len, 1); + read(fd, buf, len); + buf[len]=0; + + return len+1; +} + +static int real_read_audio_stream_info(int fd, RMContext *rmctx) +{ + int skipped = 0; + uint32_t version; + struct real_object_t obj; + uint32_t header_size; + uint16_t flavor; + uint32_t coded_framesize; + uint32_t unknown1; + uint32_t unknown2; + uint32_t unknown3; + uint16_t sub_packet_h; + uint16_t frame_size; /* block_align in ffmpeg */ + uint16_t sub_packet_size; + uint16_t unknown4; + uint16_t unknown5; + uint16_t unknown6; + uint16_t unknown7; + uint16_t sample_rate; + uint32_t unknown8; + uint16_t channels; + uint8_t interleaver_id_length; + uint32_t interleaver_id; + uint8_t fourcc_length; + uint32_t fourcc; + uint8_t unknown9; + uint16_t unknown10; + uint8_t unknown11; + uint32_t codec_extradata_length; + struct cook_extradata *ced; + + read_uint32be(fd, &version); + skipped += 4; + + printf(" version=0x%04x\n",((version >> 16) & 0xff)); + if (((version >> 16) & 0xff) == 3) { + /* Very old version */ + } else { + real_read_object_header(fd, &obj); + skipped += 10; + read_uint32be(fd, &header_size); + skipped += 4; + /* obj.size will be filled with an unknown value, replaced with header_size */ + printf(" Object: %s, size: %d bytes, version: 0x%04x\n",fourcc2str(obj.fourcc),header_size,obj.version); + + read_uint16be(fd, &flavor); + read_uint32be(fd, &coded_framesize); + read_uint32be(fd, &unknown1); + read_uint32be(fd, &unknown2); + read_uint32be(fd, &unknown3); + read_uint16be(fd, &rmctx->sub_packet_h); + read_uint16be(fd, &rmctx->block_align); + read_uint16be(fd, &rmctx->sub_packet_size); + read_uint16be(fd, &unknown4); + skipped += 26; + if (((version >> 16) & 0xff) == 5) + { + read_uint16be(fd, &unknown5); + read_uint16be(fd, &unknown6); + read_uint16be(fd, &unknown7); + skipped += 6; + } + read_uint16be(fd, &rmctx->sample_rate); + read_uint32be(fd, &unknown8); + read_uint16be(fd, &rmctx->nb_channels); + skipped += 8; + if (((version >> 16) & 0xff) == 4) + { + read_uint8(fd, &interleaver_id_length); + read_uint32be(fd, &interleaver_id); + read_uint8(fd, &fourcc_length); + read_uint32be(fd, &fourcc); + skipped += 10; + } + if (((version >> 16) & 0xff) == 5) + { + read_uint32be(fd, &interleaver_id); + read_uint32be(fd, &fourcc); + skipped += 8; + } + read_uint8(fd,&unknown9); + read_uint16be(fd,&unknown10); + skipped += 3; + if (((version >> 16) & 0xff) == 5) + { + read_uint8(fd, &unknown11); + skipped += 1; + } + + read_uint32be(fd, &rmctx->extradata_size); + skipped += 4; + if(!strncmp(fourcc2str(fourcc),"cook",4)) + skipped += read_cook_extradata(fd, rmctx); + + + printf(" flavor = %d\n",flavor); + printf(" coded_frame_size = %d\n",coded_framesize); + printf(" sub_packet_h = %d\n",rmctx->sub_packet_h); + printf(" frame_size = %d\n",rmctx->block_align); + printf(" sub_packet_size = %d\n",rmctx->sub_packet_size); + printf(" sample_rate= %d\n",rmctx->sample_rate); + printf(" channels= %d\n",rmctx->nb_channels); + printf(" fourcc = %s\n",fourcc2str(fourcc)); + printf(" codec_extra_data_length = %d\n",rmctx->extradata_size); + printf(" codec_extradata :\n"); + print_cook_extradata(rmctx); + + } + + return skipped; +} + +int real_parse_header(int fd, RMContext *rmctx) +{ + struct real_object_t obj; + int res; + int skipped; + off_t curpos; + + uint32_t unknown1; + uint32_t unknown2; + + uint32_t max_bitrate; + uint32_t avg_bitrate; + uint32_t max_packet_size; + uint32_t avg_packet_size; + uint32_t packet_count; + uint32_t duration; + uint32_t preroll; + uint32_t index_offset; + uint32_t data_offset; + uint16_t num_streams; + uint16_t flags; + + uint16_t stream_id; + uint32_t start_time; + char desc[256]; + char mimetype[256]; + uint32_t codec_data_size; + uint32_t v; + + char title[256]; + char author[256]; + char copyright[256]; + char comment[256]; + + uint32_t data_nb_packets; + uint32_t next_data_off; + uint8_t header_end; + + curpos = lseek(fd, 0, SEEK_SET); + res = real_read_object_header(fd, &obj); + + if (obj.fourcc == FOURCC('.','r','a',0xfd)) + { + /* Very old .ra format - not yet supported */ + return -1; + } + else if (obj.fourcc != FOURCC('.','R','M','F')) + { + return -1; + } + + read_uint32be(fd, &unknown1); + read_uint32be(fd, &unknown2); + + printf("Object: %s, size: %d bytes, version: 0x%04x, pos: %d\n",fourcc2str(obj.fourcc),(int)obj.size,obj.version,(int)curpos); + printf(" unknown1=%d (0x%08x)\n",unknown1,unknown1); + printf(" unknown2=%d (0x%08x)\n",unknown2,unknown2); + + res = real_read_object_header(fd, &obj); + header_end = 0; + while(res) + { + printf("Object: %s, size: %d bytes, version: 0x%04x, pos: %d\n",fourcc2str(obj.fourcc),(int)obj.size,obj.version,(int)curpos); + skipped = 10; + if(obj.fourcc == FOURCC('I','N','D','X')) + break; + switch (obj.fourcc) + { + case FOURCC('P','R','O','P'): /* File properties */ + read_uint32be(fd, &max_bitrate); + read_uint32be(fd, &rmctx->bit_rate); /*avg bitrate*/ + read_uint32be(fd, &max_packet_size); + read_uint32be(fd, &avg_packet_size); + read_uint32be(fd, &packet_count); + read_uint32be(fd, &duration); + read_uint32be(fd, &preroll); + read_uint32be(fd, &index_offset); + read_uint32be(fd, &data_offset); + read_uint16be(fd, &num_streams); + read_uint16be(fd, &rmctx->flags); + skipped += 40; + + printf(" max_bitrate = %d\n",max_bitrate); + printf(" avg_bitrate = %d\n",avg_bitrate); + printf(" max_packet_size = %d\n",max_packet_size); + printf(" avg_packet_size = %d\n",avg_packet_size); + printf(" packet_count = %d\n",packet_count); + printf(" duration = %d\n",duration); + printf(" preroll = %d\n",preroll); + printf(" index_offset = %d\n",index_offset); + printf(" data_offset = %d\n",data_offset); + printf(" num_streams = %d\n",num_streams); + printf(" flags=0x%04x\n",flags); + break; + + case FOURCC('C','O','N','T'): + /* Four strings - Title, Author, Copyright, Comment */ + skipped += read_str(fd,rmctx->title); + skipped += read_str(fd,rmctx->artist); + skipped += read_str(fd,copyright); + skipped += read_str(fd,comment); + + printf(" title=\"%s\"\n",title); + printf(" author=\"%s\"\n",author); + printf(" copyright=\"%s\"\n",copyright); + printf(" comment=\"%s\"\n",comment); + break; + + case FOURCC('M','D','P','R'): /* Media properties */ + read_uint16be(fd,&stream_id); + skipped += 2; + read_uint32be(fd,&max_bitrate); + skipped += 4; + read_uint32be(fd,&avg_bitrate); + skipped += 4; + read_uint32be(fd,&max_packet_size); + skipped += 4; + read_uint32be(fd,&avg_packet_size); + skipped += 4; + read_uint32be(fd,&start_time); + skipped += 4; + read_uint32be(fd,&preroll); + skipped += 4; + read_uint32be(fd,&rmctx->duration); + skipped += 4; + skipped += read_str(fd,desc); + skipped += read_str(fd,mimetype); + read_uint32be(fd,&codec_data_size); + skipped += 4; + //From ffmpeg: codec_pos = url_ftell(pb); + read_uint32be(fd,&v); + skipped += 4; + + printf(" stream_id = 0x%04x\n",stream_id); + printf(" max_bitrate = %d\n",max_bitrate); + printf(" avg_bitrate = %d\n",avg_bitrate); + printf(" max_packet_size = %d\n",max_packet_size); + printf(" avg_packet_size = %d\n",avg_packet_size); + printf(" start_time = %d\n",start_time); + printf(" preroll = %d\n",preroll); + printf(" duration = %d\n",rmctx->duration); + printf(" desc=\"%s\"\n",desc); + printf(" mimetype=\"%s\"\n",mimetype); + printf(" codec_data_size = %d\n",codec_data_size); + printf(" v=\"%s\"\n", fourcc2str(v)); + + if (v == FOURCC('.','r','a',0xfd)) + { + skipped += real_read_audio_stream_info(fd, rmctx); + } + + break; + + case FOURCC('D','A','T','A'): + + read_uint32be(fd,&rmctx->nb_packets); + skipped += 4; + read_uint32be(fd,&next_data_off); + skipped += 4; + if (!rmctx->nb_packets && (rmctx->flags & 4)) + rmctx->nb_packets = 3600 * 25; + printf(" data_nb_packets = %d\n",rmctx->nb_packets); + printf(" next DATA offset = %d\n",next_data_off); + header_end = 1; + break; + } + if(header_end) break; + curpos = lseek(fd, obj.size - skipped, SEEK_CUR); + res = real_read_object_header(fd, &obj); + } + + + return 0; +} + +void rm_get_packet(int fd,RMContext *rmctx, RMPacket *pkt) +{ + uint8_t unknown,packet_group; + uint16_t x, place; + uint16_t sps = rmctx->sub_packet_size; + uint16_t cfs = rmctx->coded_framesize; + uint16_t h = rmctx->sub_packet_h; + uint16_t y = rmctx->sub_packet_cnt; + uint16_t w = rmctx->audio_framesize; + do + { + y = rmctx->sub_packet_cnt; + read_uint16be(fd,&pkt->version); + read_uint16be(fd,&pkt->length); + read_uint16be(fd,&pkt->stream_number); + read_uint32be(fd,&pkt->timestamp); + DEBUGF(" version = %d\n" + " length = %d\n" + " stream = %d\n" + " timestmp= %d\n",pkt->version,pkt->length,pkt->stream_number,pkt->timestamp); + + //getchar(); + if(pkt->version == 0) + { + read_uint8(fd,&packet_group); + read_uint8(fd,&pkt->flags); + } + if(pkt->version == 1) + read_uint8(fd,&unknown); + + if (pkt->flags & 2) /* keyframe */ + y = rmctx->sub_packet_cnt = 0; + if (!y) /* if keyframe update playback elapsed time */ + rmctx->audiotimestamp = pkt->timestamp; + + for(x = 0 ; x < w/sps; x++) + { + place = sps*(h*x+((h+1)/2)*(y&1)+(y>>1)); + read(fd,pkt->data+place, sps); + //DEBUGF("place = %d data[place] = %d\n",place,pkt->data[place]); + } + rmctx->audio_pkt_cnt++; + }while(++(rmctx->sub_packet_cnt) < h); + +} +#ifdef DEBUG +void dump_rm_context(RMContext *rmctx) +{ + DEBUGF("block_align = %d\n", rmctx->block_align); + DEBUGF("nb_channels = %d\n", rmctx->nb_channels); + DEBUGF("sample_rate = %d\n", rmctx->sample_rate); + DEBUGF("bit_rate = %d\n", rmctx->bit_rate ); +} +#endif Index: cook_fixpoint.h =================================================================== --- cook_fixpoint.h (revision 0) +++ cook_fixpoint.h (revision 0) @@ -0,0 +1,287 @@ +/* + * COOK compatible decoder, fixed point implementation. + * Copyright (c) 2007 Ian Braithwaite + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +/** + * @file cook_float.h + * + * Cook AKA RealAudio G2 fixed point functions. + * + * Fixed point values are represented as 32 bit signed integers, + * which can be added and subtracted directly in C (without checks for + * overflow/saturation. + * Two multiplication routines are provided: + * 1) Multiplication by powers of two (2^-31 .. 2^31), implemented + * with C's bit shift operations. + * 2) Multiplication by 16 bit fractions (0 <= x < 1), implemented + * in C using two 32 bit integer multiplications. + */ + +/* misc math functions */ +extern const uint8_t ff_log2_tab[256]; + +static inline int av_log2(unsigned int v) +{ + int n = 0; + if (v & 0xffff0000) { + v >>= 16; + n += 16; + } + if (v & 0xff00) { + v >>= 8; + n += 8; + } + n += ff_log2_tab[v]; + + return n; +} + +static inline int av_log2_16bit(unsigned int v) +{ + int n = 0; + if (v & 0xff00) { + v >>= 8; + n += 8; + } + n += ff_log2_tab[v]; + + return n; +} + +/** + * Clips a signed integer value into the amin-amax range. + * @param a value to clip + * @param amin minimum value of the clip range + * @param amax maximum value of the clip range + * @return clipped value + */ +static inline int av_clip(int a, int amin, int amax) +{ + if (a < amin) return amin; + else if (a > amax) return amax; + else return a; +} + +/** + * Initialise fixed point implementation. + * Nothing to do for fixed point. + * + * @param q pointer to the COOKContext + */ +static inline int init_cook_math(COOKContext *q) +{ + return 0; +} + +/** + * Free resources used by floating point implementation. + * Nothing to do for fixed point. + * + * @param q pointer to the COOKContext + */ +static inline void free_cook_math(COOKContext *q) +{ + return; +} + + +/** + * Fixed point multiply by power of two. + * + * @param x fix point value + * @param i integer power-of-two, -31..+31 + */ +static inline FIXP fixp_pow2(FIXP x, int i) +{ + if (i < 0) + return (x >> -i) + ((x >> (-i-1)) & 1); + else + return x << i; /* no check for overflow */ +} + +/** + * Fixed point multiply by fraction. + * + * @param a fix point value + * @param b fix point fraction, 0 <= b < 1 + */ +static inline FIXP fixp_mult_su(FIXP a, FIXPU b) +{ + int32_t hb = (a >> 16) * b; + uint32_t lb = (a & 0xffff) * b; + + return hb + (lb >> 16) + ((lb & 0x8000) >> 15); +} + + +/** + * The real requantization of the mltcoefs + * + * @param q pointer to the COOKContext + * @param index index + * @param quant_index quantisation index for this band + * @param subband_coef_index array of indexes to quant_centroid_tab + * @param subband_coef_sign use random noise instead of predetermined value + * @param mlt_ptr pointer to the mlt coefficients + */ +static void scalar_dequant_math(COOKContext *q, int index, + int quant_index, int* subband_coef_index, + int* subband_coef_sign, REAL_T *mlt_p) +{ + /* Num. half bits to right shift */ + const int s = 33 - quant_index + av_log2(q->samples_per_channel); + const FIXP *table = quant_tables[s & 1][index]; + FIXP f; + int i; + + for(i=0 ; i= 64) ? 0 : fixp_pow2(f, -(s/2)); + } +} + + +/** + * The modulated lapped transform, this takes transform coefficients + * and transforms them into timedomain samples. + * A window step is also included. + * + * @param q pointer to the COOKContext + * @param inbuffer pointer to the mltcoefficients + * @param outbuffer pointer to the timedomain buffer + * @param mlt_tmp pointer to temporary storage space + */ +#include "cook_fixp_mdct.h" + +static inline void imlt_math(COOKContext *q, FIXP *in) +{ + const int n = q->samples_per_channel; + const int step = 4 << (10 - av_log2(n)); + int i = 0, j = step>>1; + + cook_mdct_backward(2 * n, in, q->mono_mdct_output); + + do { + FIXP tmp = q->mono_mdct_output[i]; + + q->mono_mdct_output[i] = + fixp_mult_su(-q->mono_mdct_output[n + i], sincos_lookup[j]); + q->mono_mdct_output[n + i] = fixp_mult_su(tmp, sincos_lookup[j+1]); + j += step; + } while (++i < n/2); + do { + FIXP tmp = q->mono_mdct_output[i]; + + j -= step; + q->mono_mdct_output[i] = + fixp_mult_su(-q->mono_mdct_output[n + i], sincos_lookup[j+1]); + q->mono_mdct_output[n + i] = fixp_mult_su(tmp, sincos_lookup[j]); + } while (++i < n); +} + + +/** + * Perform buffer overlapping. + * + * @param q pointer to the COOKContext + * @param gain gain correction to apply first to output buffer + * @param buffer data to overlap + */ +static inline void overlap_math(COOKContext *q, int gain, FIXP buffer[]) +{ + int i; + for(i=0 ; isamples_per_channel ; i++) { + q->mono_mdct_output[i] = + fixp_pow2(q->mono_mdct_output[i], gain) + buffer[i]; + } +} + + +/** + * the actual requantization of the timedomain samples + * + * @param q pointer to the COOKContext + * @param buffer pointer to the timedomain buffer + * @param gain_index index for the block multiplier + * @param gain_index_next index for the next block multiplier + */ +static inline void +interpolate_math(COOKContext *q, FIXP* buffer, + int gain_index, int gain_index_next) +{ + int i; + int gain_size_factor = q->samples_per_channel / 8; + + if(gain_index == gain_index_next){ //static gain + for(i = 0; i < gain_size_factor; i++) { + buffer[i] = fixp_pow2(buffer[i], gain_index); + } + } else { //smooth gain + int step = (gain_index_next - gain_index) + << (7 - av_log2(gain_size_factor)); + int x = 0; + + for(i = 0; i < gain_size_factor; i++) { + buffer[i] = fixp_mult_su(buffer[i], pow128_tab[x]); + buffer[i] = fixp_pow2(buffer[i], gain_index+1); + + x += step; + gain_index += (x + 128) / 128 - 1; + x = (x + 128) % 128; + } + } +} + + +/** + * Decoupling calculation for joint stereo coefficients. + * + * @param x mono coefficient + * @param table number of decoupling table + * @param i table index + */ +static inline FIXP cplscale_math(FIXP x, int table, int i) +{ + return fixp_mult_su(x, cplscales[table-2][i]); +} + + +/** + * Final converion from floating point values to + * signed, 16 bit sound samples. Round and clip. + * + * @param q pointer to the COOKContext + * @param out pointer to the output buffer + * @param chan 0: left or single channel, 1: right channel + */ +static inline void output_math(COOKContext *q, int16_t *out, int chan) +{ + int j; + + for (j = 0; j < q->samples_per_channel; j++) { + out[chan + q->nb_channels * j] = + av_clip(fixp_pow2(q->mono_mdct_output[j], -11), -32768, 32767); + } +} Index: bswap.h =================================================================== --- bswap.h (revision 0) +++ bswap.h (revision 0) @@ -0,0 +1,150 @@ +/** + * @file bswap.h + * byte swap. + */ + +#ifndef __BSWAP_H__ +#define __BSWAP_H__ + +#ifdef HAVE_BYTESWAP_H +#include +#else + +#ifdef ROCKBOX +#include "codecs.h" + +/* rockbox' optimised inline functions */ +#define bswap_16(x) swap16(x) +#define bswap_32(x) swap32(x) + +static inline uint64_t ByteSwap64(uint64_t x) +{ + union { + uint64_t ll; + struct { + uint32_t l,h; + } l; + } r; + r.l.l = bswap_32 (x); + r.l.h = bswap_32 (x>>32); + return r.ll; +} +#define bswap_64(x) ByteSwap64(x) + +#elif defined(ARCH_X86) +static inline unsigned short ByteSwap16(unsigned short x) +{ + __asm("xchgb %b0,%h0" : + "=q" (x) : + "0" (x)); + return x; +} +#define bswap_16(x) ByteSwap16(x) + +static inline unsigned int ByteSwap32(unsigned int x) +{ +#if __CPU__ > 386 + __asm("bswap %0": + "=r" (x) : +#else + __asm("xchgb %b0,%h0\n" + " rorl $16,%0\n" + " xchgb %b0,%h0": + "=q" (x) : +#endif + "0" (x)); + return x; +} +#define bswap_32(x) ByteSwap32(x) + +static inline unsigned long long int ByteSwap64(unsigned long long int x) +{ + register union { __extension__ uint64_t __ll; + uint32_t __l[2]; } __x; + asm("xchgl %0,%1": + "=r"(__x.__l[0]),"=r"(__x.__l[1]): + "0"(bswap_32((unsigned long)x)),"1"(bswap_32((unsigned long)(x>>32)))); + return __x.__ll; +} +#define bswap_64(x) ByteSwap64(x) + +#elif defined(ARCH_SH4) + +static inline uint16_t ByteSwap16(uint16_t x) { + __asm__("swap.b %0,%0":"=r"(x):"0"(x)); + return x; +} + +static inline uint32_t ByteSwap32(uint32_t x) { + __asm__( + "swap.b %0,%0\n" + "swap.w %0,%0\n" + "swap.b %0,%0\n" + :"=r"(x):"0"(x)); + return x; +} + +#define bswap_16(x) ByteSwap16(x) +#define bswap_32(x) ByteSwap32(x) + +static inline uint64_t ByteSwap64(uint64_t x) +{ + union { + uint64_t ll; + struct { + uint32_t l,h; + } l; + } r; + r.l.l = bswap_32 (x); + r.l.h = bswap_32 (x>>32); + return r.ll; +} +#define bswap_64(x) ByteSwap64(x) + +#else + +#define bswap_16(x) (((x) & 0x00ff) << 8 | ((x) & 0xff00) >> 8) + + +// code from bits/byteswap.h (C) 1997, 1998 Free Software Foundation, Inc. +#define bswap_32(x) \ + ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \ + (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) + +/*static inline uint64_t ByteSwap64(uint64_t x) +{ + union { + uint64_t ll; + uint32_t l[2]; + } w, r; + w.ll = x; + r.l[0] = bswap_32 (w.l[1]); + r.l[1] = bswap_32 (w.l[0]); + return r.ll; +}*/ +#define bswap_64(x) ByteSwap64(x) + +#endif /* !ARCH_X86 */ + +#endif /* !HAVE_BYTESWAP_H */ + +// be2me ... BigEndian to MachineEndian +// le2me ... LittleEndian to MachineEndian + +#ifdef WORDS_BIGENDIAN +#define be2me_16(x) (x) +#define be2me_32(x) (x) +#define be2me_64(x) (x) +#define le2me_16(x) bswap_16(x) +#define le2me_32(x) bswap_32(x) +#define le2me_64(x) bswap_64(x) +#else +#define be2me_16(x) bswap_16(x) +#define be2me_32(x) bswap_32(x) +#define be2me_64(x) bswap_64(x) +#define le2me_16(x) (x) +#define le2me_32(x) (x) +#define le2me_64(x) (x) +#endif + +#endif /* __BSWAP_H__ */ Index: rm.h =================================================================== --- rm.h (revision 0) +++ rm.h (revision 0) @@ -0,0 +1,74 @@ +#include +#include + +typedef struct rm_packet +{ + uint8_t data[30000]; /* Reordered data. No malloc, hence the size */ + uint16_t version; + uint16_t length; + uint32_t timestamp; + uint16_t stream_number; + uint8_t flags; +}RMPacket; + +typedef struct rm_context +{ + /* Demux Context */ + int old_format; + int current_stream; + int remaining_len; + int audio_stream_num; /*< Stream number for audio packets*/ + int audio_pkt_cnt; /* Output packet counter*/ + + /* Stream Variables */ + uint32_t audiotimestamp; /* Audio packet timestamp*/ + uint16_t sub_packet_cnt; /* Subpacket counter, used while reading */ + uint16_t sub_packet_size, sub_packet_h, coded_framesize; /* Descrambling parameters from container */ + uint16_t audio_framesize; /* Audio frame size from container */ + uint16_t sub_packet_lengths[16]; /* Length of each subpacket */ + + /* Metadata */ + char title[50]; + char artist[50]; + + /* Codec Context */ + uint16_t block_align; + uint32_t duration; + uint32_t nb_packets; + int frame_number; + uint32_t extradata_size; + uint16_t sample_rate; + uint16_t nb_channels; + uint32_t bit_rate; + uint16_t flags; + + /*cook extradata*/ + uint32_t cook_version; + uint16_t samples_pf_pc; /* samples per frame per channel */ + uint16_t nb_subbands; /* number of subbands in the frequency domain */ + /* extra 8 bytes for stereo data */ + uint32_t unused; + uint16_t js_subband_start; /* joint stereo subband start */ + uint16_t js_vlc_bits; + +} RMContext; + +static unsigned char wav_header[44]={ + 'R','I','F','F',// 0 - ChunkID + 0,0,0,0, // 4 - ChunkSize (filesize-8) + 'W','A','V','E',// 8 - Format + 'f','m','t',' ',// 12 - SubChunkID + 16,0,0,0, // 16 - SubChunk1ID // 16 for PCM + 1,0, // 20 - AudioFormat (1=Uncompressed) + 2,0, // 22 - NumChannels + 0,0,0,0, // 24 - SampleRate in Hz + 0,0,0,0, // 28 - Byte Rate (SampleRate*NumChannels*(BitsPerSample/8) + 4,0, // 32 - BlockAlign (== NumChannels * BitsPerSample/8) + 16,0, // 34 - BitsPerSample + 'd','a','t','a',// 36 - Subchunk2ID + 0,0,0,0 // 40 - Subchunk2Size +}; +int open_wav(char* filename); +void close_wav(int fd, RMContext *rmctx); +int real_parse_header(int fd, RMContext *rmctx); +void rm_get_packet(int fd,RMContext *rmctx, RMPacket *pkt); Index: id3.h =================================================================== --- id3.h (revision 0) +++ id3.h (revision 0) @@ -0,0 +1,153 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: id3.h 13730 2007-06-28 20:28:43Z nicolasp $ + * + * Copyright (C) 2002 by Daniel Stenberg + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#ifndef ID3_H +#define ID3_H + +#include + +#define ID3V2_BUF_SIZE 300 +#define MAX_PATH 260 +/* Audio file types. */ +/* NOTE: The values of the AFMT_* items are used for the %fc tag in the WPS + - so new entries MUST be added to the end to maintain compatibility. + */ +enum +{ + AFMT_UNKNOWN = 0, /* Unknown file format */ + + /* start formats */ + + AFMT_MPA_L1, /* MPEG Audio layer 1 */ + AFMT_MPA_L2, /* MPEG Audio layer 2 */ + AFMT_MPA_L3, /* MPEG Audio layer 3 */ + + AFMT_AIFF, /* Audio Interchange File Format */ + AFMT_PCM_WAV, /* Uncompressed PCM in a WAV file */ + AFMT_OGG_VORBIS, /* Ogg Vorbis */ + AFMT_FLAC, /* FLAC */ + AFMT_MPC, /* Musepack */ + AFMT_A52, /* A/52 (aka AC3) audio */ + AFMT_WAVPACK, /* WavPack */ + AFMT_ALAC, /* Apple Lossless Audio Codec */ + AFMT_AAC, /* Advanced Audio Coding (AAC) in M4A container */ + AFMT_SHN, /* Shorten */ + AFMT_SID, /* SID File Format */ + AFMT_ADX, /* ADX File Format */ + AFMT_NSF, /* NESM (NES Sound Format) */ + AFMT_SPEEX, /* Ogg Speex speech */ + AFMT_SPC, /* SPC700 save state */ + AFMT_APE, /* Monkey's Audio (APE) */ + + /* add new formats at any index above this line to have a sensible order - + specified array index inits are used */ + /* format arrays defined in id3.c */ + + AFMT_NUM_CODECS +}; + +struct mp3entry { + char path[MAX_PATH]; + char* title; + char* artist; + char* album; + char* genre_string; + char* track_string; + char* year_string; + char* composer; + char* comment; + char* albumartist; + int tracknum; + int version; + int layer; + int year; + unsigned char id3version; + unsigned int codectype; + unsigned int bitrate; + unsigned long frequency; + unsigned long id3v2len; + unsigned long id3v1len; + unsigned long first_frame_offset; /* Byte offset to first real MP3 frame. + Used for skipping leading garbage to + avoid gaps between tracks. */ + unsigned long vbr_header_pos; + unsigned long filesize; /* without headers; in bytes */ + unsigned long length; /* song length in ms */ + unsigned long elapsed; /* ms played */ + + int lead_trim; /* Number of samples to skip at the beginning */ + int tail_trim; /* Number of samples to remove from the end */ + + /* Added for Vorbis */ + unsigned long samples; /* number of samples in track */ + + /* MP3 stream specific info */ + unsigned long frame_count; /* number of frames in the file (if VBR) */ + + /* Used for A52/AC3 */ + unsigned long bytesperframe; /* number of bytes per frame (if CBR) */ + + /* Xing VBR fields */ + bool vbr; + bool has_toc; /* True if there is a VBR header in the file */ + unsigned char toc[100]; /* table of contents */ + + /* these following two fields are used for local buffering */ + char id3v2buf[ID3V2_BUF_SIZE]; + char id3v1buf[4][92]; + + /* resume related */ + unsigned long offset; /* bytes played */ + int index; /* playlist index */ + + /* FileEntry fields */ + long fileentryoffset; + long filehash; + long songentryoffset; + long rundbentryoffset; + + /* runtime database fields */ + short rating; + short score; + long playcount; + long lastplayed; + + /* replaygain support */ + +#if CONFIG_CODEC == SWCODEC + char* track_gain_string; + char* album_gain_string; + long track_gain; /* 7.24 signed fixed point. 0 for no gain. */ + long album_gain; + long track_peak; /* 7.24 signed fixed point. 0 for no peak. */ + long album_peak; +#endif + + /* Cuesheet support */ + int cuesheet_type; /* 0: none, 1: external, 2: embedded */ +}; + +enum { + ID3_VER_1_0 = 1, + ID3_VER_1_1, + ID3_VER_2_2, + ID3_VER_2_3, + ID3_VER_2_4 +}; + +#endif Index: main.c =================================================================== --- main.c (revision 0) +++ main.c (revision 0) @@ -0,0 +1,92 @@ +#include +#include +#include +#include + +#include +#include "rm.h" +#include "cook.h" + +#if 1 +//# define DEBUGF(message,args ...) av_log(NULL,AV_LOG_ERROR,message,## args) +#define DEBUGF printf +#else +# define DEBUGF(...) +#endif + +int main(int argc, char *argv[]) { + int fd, fd_out, fd_dec; + int res, h,datasize, nb_frames,packet_count,x,y,i,fs,sps; + char filename[15]; + int8_t outbuf[4096]; + uint8_t inbuf[1024]; + COOKContext q; + RMContext rmctx; + RMPacket pkt; + memset(&q,0,sizeof(COOKContext)); + memset(&rmctx,0,sizeof(RMContext)); + memset(&pkt,0,sizeof(RMPacket)); + if (argc != 2) { + DEBUGF("Incorrect number of arguments\n"); + return -1; + } + + fd = open(argv[1],O_RDONLY); + if (fd < 0) { + DEBUGF("Error opening file %s\n", argv[1]); + return -1; + } + + fd_dec = open_wav("output.wav"); + if (fd_dec < 0) { + DEBUGF("Error creating output file\n"); + return -1; + } + res = real_parse_header(fd, &rmctx); + packet_count = (int) rmctx.nb_packets; + rmctx.audio_framesize = rmctx.block_align; + rmctx.block_align = rmctx.sub_packet_size; + fs = (int) rmctx.audio_framesize; + sps= (int) rmctx.block_align; + h = (int) rmctx.sub_packet_h; + cook_decode_init(&rmctx,&q); + DEBUGF("nb_frames = %d\n",nb_frames); + x = 0; y = 0; + if(packet_count % h) + { + packet_count += h - (packet_count % h); + rmctx.nb_packets = packet_count; + } + while(packet_count )//>= h || packet_count >= -1*h ) + { + + memset(pkt.data,0,sizeof(pkt.data)); + rm_get_packet(fd, &rmctx, &pkt); + DEBUGF("total frames = %d packet count = %d output counter = %d \n",rmctx.audio_pkt_cnt*(fs/sps), packet_count,rmctx.audio_pkt_cnt); + //getchar(); + for(i = 0; i < rmctx.audio_pkt_cnt*(fs/sps) ; i++) + { + //snprintf(filename,sizeof(filename),"dump%d.raw",++x); + //fd_out = open(filename,O_WRONLY|O_CREAT|O_APPEND); + //write(fd_out,pkt.data+i*sps,sps); + //memcpy(inbuf,pkt.data+i*sps,sps); + nb_frames = cook_decode_frame(&rmctx,&q, outbuf, &datasize, pkt.data+i*sps , rmctx.block_align); + //DEBUGF("nb_frames = %d frame number = %d datasize = %d\n",nb_frames,rmctx.frame_number,datasize); + rmctx.frame_number++; + //write(fd_out,outbuf,datasize); + write(fd_dec,outbuf,datasize); + //getchar(); + //DEBUGF("Wrote frame %d nb_frames = %d datasize = %d\n",++x,nb_frames,datasize); + //close(fd_out); + } + packet_count -= rmctx.audio_pkt_cnt; + rmctx.audio_pkt_cnt = 0; + } + //if(packet_count < h) rmctx.nb_packets += (h % (packet_count > 0 ? packet_count: h+packet_count)) - packet_count; + cook_decode_close(&q); + close_wav(fd_dec,&rmctx); + close(fd); + + + return 0; +} Index: cookdata.h =================================================================== --- cookdata.h (revision 0) +++ cookdata.h (revision 0) @@ -0,0 +1,493 @@ +/* + * COOK compatible decoder data + * Copyright (c) 2003 Sascha Sommer + * Copyright (c) 2005 Benjamin Larsson + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +/** + * @file cookdata.h + * Cook AKA RealAudio G2 compatible decoderdata + */ + +/* various data tables */ + +static const int expbits_tab[8] = { + 52,47,43,37,29,22,16,0, +}; + +static const int invradix_tab[7] = { + 74899, 104858, 149797, 209716, 262144, 349526, 524288, +}; + +static const int kmax_tab[7] = { + 13, 9, 6, 4, 3, 2, 1, +}; + +static const int vd_tab[7] = { + 2, 2, 2, 4, 4, 5, 5, +}; + +static const int vpr_tab[7] = { + 10, 10, 10, 5, 5, 4, 4, +}; + + + +/* VLC data */ + +static const int vhsize_tab[7] = { + 191, 97, 48, 607, 246, 230, 32, +}; + +static const int vhvlcsize_tab[7] = { + 8, 7, 7, 10, 9, 9, 6, +}; + +static const uint8_t envelope_quant_index_huffbits[13][24] = { + { 4, 6, 5, 5, 4, 4, 4, 4, 4, 4, 3, 3, 3, 4, 5, 7, 8, 9, 11, 11, 12, 12, 12, 12 }, + { 10, 8, 6, 5, 5, 4, 3, 3, 3, 3, 3, 3, 4, 5, 7, 9, 11, 12, 13, 15, 15, 15, 16, 16 }, + { 12, 10, 8, 6, 5, 4, 4, 4, 4, 4, 4, 3, 3, 3, 4, 4, 5, 5, 7, 9, 11, 13, 14, 14 }, + { 13, 10, 9, 9, 7, 7, 5, 5, 4, 3, 3, 3, 3, 3, 4, 4, 4, 5, 7, 9, 11, 13, 13, 13 }, + { 12, 13, 10, 8, 6, 6, 5, 5, 4, 4, 3, 3, 3, 3, 3, 4, 5, 5, 6, 7, 9, 11, 14, 14 }, + { 12, 11, 9, 8, 8, 7, 5, 4, 4, 3, 3, 3, 3, 3, 4, 4, 5, 5, 7, 8, 10, 13, 14, 14 }, + { 15, 16, 15, 12, 10, 8, 6, 5, 4, 3, 3, 3, 2, 3, 4, 5, 5, 7, 9, 11, 13, 16, 16, 16 }, + { 14, 14, 11, 10, 9, 7, 7, 5, 5, 4, 3, 3, 2, 3, 3, 4, 5, 7, 9, 9, 12, 14, 15, 15 }, + { 9, 9, 9, 8, 7, 6, 5, 4, 3, 3, 3, 3, 3, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 13 }, + { 14, 12, 10, 8, 6, 6, 5, 4, 3, 3, 3, 3, 3, 3, 4, 5, 6, 8, 8, 9, 11, 14, 14, 14 }, + { 13, 10, 9, 8, 6, 6, 5, 4, 4, 4, 3, 3, 2, 3, 4, 5, 6, 8, 9, 9, 11, 12, 14, 14 }, + { 16, 13, 12, 11, 9, 6, 5, 5, 4, 4, 4, 3, 2, 3, 3, 4, 5, 7, 8, 10, 14, 16, 16, 16 }, + { 13, 14, 14, 14, 10, 8, 7, 7, 5, 4, 3, 3, 2, 3, 3, 4, 5, 5, 7, 9, 11, 14, 14, 14 }, +}; + +static const uint16_t envelope_quant_index_huffcodes[13][24] = { + {0x0006, 0x003e, 0x001c, 0x001d, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x0000, 0x0001, + 0x0002, 0x000d, 0x001e, 0x007e, 0x00fe, 0x01fe, 0x07fc, 0x07fd, 0x0ffc, 0x0ffd, 0x0ffe, 0x0fff}, + {0x03fe, 0x00fe, 0x003e, 0x001c, 0x001d, 0x000c, 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, + 0x000d, 0x001e, 0x007e, 0x01fe, 0x07fe, 0x0ffe, 0x1ffe, 0x7ffc, 0x7ffd, 0x7ffe, 0xfffe, 0xffff}, + {0x0ffe, 0x03fe, 0x00fe, 0x003e, 0x001c, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x0000, + 0x0001, 0x0002, 0x000c, 0x000d, 0x001d, 0x001e, 0x007e, 0x01fe, 0x07fe, 0x1ffe, 0x3ffe, 0x3fff}, + {0x1ffc, 0x03fe, 0x01fc, 0x01fd, 0x007c, 0x007d, 0x001c, 0x001d, 0x000a, 0x0000, 0x0001, 0x0002, + 0x0003, 0x0004, 0x000b, 0x000c, 0x000d, 0x001e, 0x007e, 0x01fe, 0x07fe, 0x1ffd, 0x1ffe, 0x1fff}, + {0x0ffe, 0x1ffe, 0x03fe, 0x00fe, 0x003c, 0x003d, 0x001a, 0x001b, 0x000a, 0x000b, 0x0000, 0x0001, + 0x0002, 0x0003, 0x0004, 0x000c, 0x001c, 0x001d, 0x003e, 0x007e, 0x01fe, 0x07fe, 0x3ffe, 0x3fff}, + {0x0ffe, 0x07fe, 0x01fe, 0x00fc, 0x00fd, 0x007c, 0x001c, 0x000a, 0x000b, 0x0000, 0x0001, 0x0002, + 0x0003, 0x0004, 0x000c, 0x000d, 0x001d, 0x001e, 0x007d, 0x00fe, 0x03fe, 0x1ffe, 0x3ffe, 0x3fff}, + {0x7ffc, 0xfffc, 0x7ffd, 0x0ffe, 0x03fe, 0x00fe, 0x003e, 0x001c, 0x000c, 0x0002, 0x0003, 0x0004, + 0x0000, 0x0005, 0x000d, 0x001d, 0x001e, 0x007e, 0x01fe, 0x07fe, 0x1ffe, 0xfffd, 0xfffe, 0xffff}, + {0x3ffc, 0x3ffd, 0x07fe, 0x03fe, 0x01fc, 0x007c, 0x007d, 0x001c, 0x001d, 0x000c, 0x0002, 0x0003, + 0x0000, 0x0004, 0x0005, 0x000d, 0x001e, 0x007e, 0x01fd, 0x01fe, 0x0ffe, 0x3ffe, 0x7ffe, 0x7fff}, + {0x01fc, 0x01fd, 0x01fe, 0x00fc, 0x007c, 0x003c, 0x001c, 0x000c, 0x0000, 0x0001, 0x0002, 0x0003, + 0x0004, 0x0005, 0x000d, 0x001d, 0x003d, 0x007d, 0x00fd, 0x03fe, 0x07fe, 0x0ffe, 0x1ffe, 0x1fff}, + {0x3ffc, 0x0ffe, 0x03fe, 0x00fc, 0x003c, 0x003d, 0x001c, 0x000c, 0x0000, 0x0001, 0x0002, 0x0003, + 0x0004, 0x0005, 0x000d, 0x001d, 0x003e, 0x00fd, 0x00fe, 0x01fe, 0x07fe, 0x3ffd, 0x3ffe, 0x3fff}, + {0x1ffe, 0x03fe, 0x01fc, 0x00fc, 0x003c, 0x003d, 0x001c, 0x000a, 0x000b, 0x000c, 0x0002, 0x0003, + 0x0000, 0x0004, 0x000d, 0x001d, 0x003e, 0x00fd, 0x01fd, 0x01fe, 0x07fe, 0x0ffe, 0x3ffe, 0x3fff}, + {0xfffc, 0x1ffe, 0x0ffe, 0x07fe, 0x01fe, 0x003e, 0x001c, 0x001d, 0x000a, 0x000b, 0x000c, 0x0002, + 0x0000, 0x0003, 0x0004, 0x000d, 0x001e, 0x007e, 0x00fe, 0x03fe, 0x3ffe, 0xfffd, 0xfffe, 0xffff}, + {0x1ffc, 0x3ffa, 0x3ffb, 0x3ffc, 0x03fe, 0x00fe, 0x007c, 0x007d, 0x001c, 0x000c, 0x0002, 0x0003, + 0x0000, 0x0004, 0x0005, 0x000d, 0x001d, 0x001e, 0x007e, 0x01fe, 0x07fe, 0x3ffd, 0x3ffe, 0x3fff}, +}; + + +static const uint8_t cvh_huffbits0[191] = { + 1, 4, 6, 6, 7, 7, 8, 8, 8, 9, 9, 10, + 11, 11, 4, 5, 6, 7, 7, 8, 8, 9, 9, 9, + 9, 10, 11, 11, 5, 6, 7, 8, 8, 9, 9, 9, + 9, 10, 10, 10, 11, 12, 6, 7, 8, 9, 9, 9, + 9, 10, 10, 10, 10, 11, 12, 13, 7, 7, 8, 9, + 9, 9, 10, 10, 10, 10, 11, 11, 12, 13, 8, 8, + 9, 9, 9, 10, 10, 10, 10, 11, 11, 12, 13, 14, + 8, 8, 9, 9, 10, 10, 11, 11, 11, 12, 12, 13, + 13, 15, 8, 8, 9, 9, 10, 10, 11, 11, 11, 12, + 12, 13, 14, 15, 9, 9, 9, 10, 10, 10, 11, 11, + 12, 13, 12, 14, 15, 16, 9, 9, 10, 10, 10, 10, + 11, 12, 12, 14, 14, 16, 16, 0, 9, 9, 10, 10, + 11, 11, 12, 13, 13, 14, 14, 15, 0, 0, 10, 10, + 10, 11, 11, 12, 12, 13, 15, 15, 16, 0, 0, 0, + 11, 11, 11, 12, 13, 13, 13, 15, 16, 16, 0, 0, + 0, 0, 11, 11, 12, 13, 13, 14, 15, 16, 16, +}; + +static const uint16_t cvh_huffcodes0[191] = { + 0x0000,0x0008,0x002c,0x002d,0x0062,0x0063,0x00d4,0x00d5,0x00d6,0x01c6,0x01c7,0x03ca, + 0x07d6,0x07d7,0x0009,0x0014,0x002e,0x0064,0x0065,0x00d7,0x00d8,0x01c8,0x01c9,0x01ca, + 0x01cb,0x03cb,0x07d8,0x07d9,0x0015,0x002f,0x0066,0x00d9,0x00da,0x01cc,0x01cd,0x01ce, + 0x01cf,0x03cc,0x03cd,0x03ce,0x07da,0x0fe4,0x0030,0x0067,0x00db,0x01d0,0x01d1,0x01d2, + 0x01d3,0x03cf,0x03d0,0x03d1,0x03d2,0x07db,0x0fe5,0x1fea,0x0068,0x0069,0x00dc,0x01d4, + 0x01d5,0x01d6,0x03d3,0x03d4,0x03d5,0x03d6,0x07dc,0x07dd,0x0fe6,0x1feb,0x00dd,0x00de, + 0x01d7,0x01d8,0x01d9,0x03d7,0x03d8,0x03d9,0x03da,0x07de,0x07df,0x0fe7,0x1fec,0x3ff2, + 0x00df,0x00e0,0x01da,0x01db,0x03db,0x03dc,0x07e0,0x07e1,0x07e2,0x0fe8,0x0fe9,0x1fed, + 0x1fee,0x7ff4,0x00e1,0x00e2,0x01dc,0x01dd,0x03dd,0x03de,0x07e3,0x07e4,0x07e5,0x0fea, + 0x0feb,0x1fef,0x3ff3,0x7ff5,0x01de,0x01df,0x01e0,0x03df,0x03e0,0x03e1,0x07e6,0x07e7, + 0x0fec,0x1ff0,0x0fed,0x3ff4,0x7ff6,0xfff8,0x01e1,0x01e2,0x03e2,0x03e3,0x03e4,0x03e5, + 0x07e8,0x0fee,0x0fef,0x3ff5,0x3ff6,0xfff9,0xfffa,0xfffa,0x01e3,0x01e4,0x03e6,0x03e7, + 0x07e9,0x07ea,0x0ff0,0x1ff1,0x1ff2,0x3ff7,0x3ff8,0x7ff7,0x7ff7,0xfffa,0x03e8,0x03e9, + 0x03ea,0x07eb,0x07ec,0x0ff1,0x0ff2,0x1ff3,0x7ff8,0x7ff9,0xfffb,0x3ff8,0x7ff7,0x7ff7, + 0x07ed,0x07ee,0x07ef,0x0ff3,0x1ff4,0x1ff5,0x1ff6,0x7ffa,0xfffc,0xfffd,0xfffb,0xfffb, + 0x3ff8,0x7ff7,0x07f0,0x07f1,0x0ff4,0x1ff7,0x1ff8,0x3ff9,0x7ffb,0xfffe,0xffff, +}; + + +static const uint8_t cvh_huffbits1[97] = { + 1, 4, 5, 6, 7, 8, 8, 9, 10, 10, 4, 5, + 6, 7, 7, 8, 8, 9, 9, 11, 5, 5, 6, 7, + 8, 8, 9, 9, 10, 11, 6, 6, 7, 8, 8, 9, + 9, 10, 11, 12, 7, 7, 8, 8, 9, 9, 10, 11, + 11, 13, 8, 8, 8, 9, 9, 10, 10, 11, 12, 14, + 8, 8, 8, 9, 10, 11, 11, 12, 13, 15, 9, 9, + 9, 10, 11, 12, 12, 14, 14, 0, 9, 9, 9, 10, + 11, 12, 14, 16, 0, 0, 10, 10, 11, 12, 13, 14, + 16, +}; + + +static const uint16_t cvh_huffcodes1[97] = { + 0x0000,0x0008,0x0014,0x0030,0x006a,0x00e2,0x00e3,0x01e4,0x03ec,0x03ed,0x0009,0x0015, + 0x0031,0x006b,0x006c,0x00e4,0x00e5,0x01e5,0x01e6,0x07f0,0x0016,0x0017,0x0032,0x006d, + 0x00e6,0x00e7,0x01e7,0x01e8,0x03ee,0x07f1,0x0033,0x0034,0x006e,0x00e8,0x00e9,0x01e9, + 0x01ea,0x03ef,0x07f2,0x0ff6,0x006f,0x0070,0x00ea,0x00eb,0x01eb,0x01ec,0x03f0,0x07f3, + 0x07f4,0x1ffa,0x00ec,0x00ed,0x00ee,0x01ed,0x01ee,0x03f1,0x03f2,0x07f5,0x0ff7,0x3ffa, + 0x00ef,0x00f0,0x00f1,0x01ef,0x03f3,0x07f6,0x07f7,0x0ff8,0x1ffb,0x7ffe,0x01f0,0x01f1, + 0x01f2,0x03f4,0x07f8,0x0ff9,0x0ffa,0x3ffb,0x3ffc,0x0000,0x01f3,0x01f4,0x01f5,0x03f5, + 0x07f9,0x0ffb,0x3ffd,0xfffe,0x0000,0x0000,0x03f6,0x03f7,0x07fa,0x0ffc,0x1ffc,0x3ffe, + 0xffff, +}; + +static const uint8_t cvh_huffbits2[48] = { + 1, 4, 5, 7, 8, 9, 10, 3, 4, 5, 7, 8, + 9, 10, 5, 5, 6, 7, 8, 10, 10, 7, 6, 7, + 8, 9, 10, 12, 8, 8, 8, 9, 10, 12, 14, 8, + 9, 9, 10, 11, 15, 16, 9, 10, 11, 12, 13, 16, +}; + +static const uint16_t cvh_huffcodes2[48] = { + 0x0000,0x000a,0x0018,0x0074,0x00f2,0x01f4,0x03f6,0x0004,0x000b,0x0019,0x0075,0x00f3, + 0x01f5,0x03f7,0x001a,0x001b,0x0038,0x0076,0x00f4,0x03f8,0x03f9,0x0077,0x0039,0x0078, + 0x00f5,0x01f6,0x03fa,0x0ffc,0x00f6,0x00f7,0x00f8,0x01f7,0x03fb,0x0ffd,0x3ffe,0x00f9, + 0x01f8,0x01f9,0x03fc,0x07fc,0x7ffe,0xfffe,0x01fa,0x03fd,0x07fd,0x0ffe,0x1ffe,0xffff, +}; + +static const uint8_t cvh_huffbits3[607] = { + 2, 4, 6, 8, 10, 5, 5, 6, 8, 10, 7, 8, + 8, 10, 12, 9, 9, 10, 12, 15, 10, 11, 13, 16, + 16, 5, 6, 8, 10, 11, 5, 6, 8, 10, 12, 7, + 7, 8, 10, 13, 9, 9, 10, 12, 15, 12, 11, 13, + 16, 16, 7, 9, 10, 12, 15, 7, 8, 10, 12, 13, + 9, 9, 11, 13, 16, 11, 11, 12, 14, 16, 12, 12, + 14, 16, 0, 9, 11, 12, 16, 16, 9, 10, 13, 15, + 16, 10, 11, 12, 16, 16, 13, 13, 16, 16, 16, 16, + 16, 15, 16, 0, 11, 13, 16, 16, 15, 11, 13, 15, + 16, 16, 13, 13, 16, 16, 0, 14, 16, 16, 16, 0, + 16, 16, 0, 0, 0, 4, 6, 8, 10, 13, 6, 6, + 8, 10, 13, 9, 8, 10, 12, 16, 10, 10, 11, 15, + 16, 13, 12, 14, 16, 16, 5, 6, 8, 11, 13, 6, + 6, 8, 10, 13, 8, 8, 9, 11, 14, 10, 10, 12, + 12, 16, 13, 12, 13, 15, 16, 7, 8, 9, 12, 16, + 7, 8, 10, 12, 14, 9, 9, 10, 13, 16, 11, 10, + 12, 15, 16, 13, 13, 16, 16, 0, 9, 11, 13, 16, + 16, 9, 10, 12, 15, 16, 10, 11, 13, 16, 16, 13, + 12, 16, 16, 16, 16, 16, 16, 16, 0, 11, 13, 16, + 16, 16, 11, 13, 16, 16, 16, 12, 13, 15, 16, 0, + 16, 16, 16, 16, 0, 16, 16, 0, 0, 0, 6, 8, + 11, 13, 16, 8, 8, 10, 12, 16, 11, 10, 11, 13, + 16, 12, 13, 13, 15, 16, 16, 16, 14, 16, 0, 6, + 8, 10, 13, 16, 8, 8, 10, 12, 16, 10, 10, 11, + 13, 16, 13, 12, 13, 16, 16, 14, 14, 14, 16, 0, + 8, 9, 11, 13, 16, 8, 9, 11, 16, 14, 10, 10, + 12, 15, 16, 12, 12, 13, 16, 16, 15, 16, 16, 16, + 0, 10, 12, 15, 16, 16, 10, 12, 12, 14, 16, 12, + 12, 13, 16, 16, 14, 15, 16, 16, 0, 16, 16, 16, + 0, 0, 12, 15, 15, 16, 0, 13, 13, 16, 16, 0, + 14, 16, 16, 16, 0, 16, 16, 16, 0, 0, 0, 0, + 0, 0, 0, 8, 10, 13, 15, 16, 10, 11, 13, 16, + 16, 13, 13, 14, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 0, 8, 10, 11, 15, 16, 9, 10, 12, + 16, 16, 12, 12, 15, 16, 16, 16, 14, 16, 16, 16, + 16, 16, 16, 16, 0, 9, 11, 14, 16, 16, 10, 11, + 13, 16, 16, 14, 13, 14, 16, 16, 16, 15, 15, 16, + 0, 16, 16, 16, 0, 0, 11, 13, 16, 16, 16, 11, + 13, 15, 16, 16, 13, 16, 16, 16, 0, 16, 16, 16, + 16, 0, 16, 16, 0, 0, 0, 15, 16, 16, 16, 0, + 14, 16, 16, 16, 0, 16, 16, 16, 0, 0, 16, 16, + 0, 0, 0, 0, 0, 0, 0, 0, 9, 13, 16, 16, + 16, 11, 13, 16, 16, 16, 14, 15, 16, 16, 0, 15, + 16, 16, 16, 0, 16, 16, 0, 0, 0, 9, 13, 15, + 15, 16, 12, 13, 14, 16, 16, 16, 15, 16, 16, 0, + 16, 16, 16, 16, 0, 16, 16, 0, 0, 0, 11, 13, + 15, 16, 0, 12, 14, 16, 16, 0, 16, 16, 16, 16, + 0, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 16, + 16, 16, 16, 0, 16, 16, 16, 16, 0, 16, 16, 16, + 0, 0, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, + 16, 16, 0, 0, 0, 16, 16, +}; + + +static const uint16_t cvh_huffcodes3[607] = { + 0x0000,0x0004,0x0022,0x00c6,0x03b0,0x000c,0x000d,0x0023,0x00c7,0x03b1,0x005c,0x00c8, + 0x00c9,0x03b2,0x0fa4,0x01c2,0x01c3,0x03b3,0x0fa5,0x7f72,0x03b4,0x07b2,0x1f9a,0xff24, + 0xff25,0x000e,0x0024,0x00ca,0x03b5,0x07b3,0x000f,0x0025,0x00cb,0x03b6,0x0fa6,0x005d, + 0x005e,0x00cc,0x03b7,0x1f9b,0x01c4,0x01c5,0x03b8,0x0fa7,0x7f73,0x0fa8,0x07b4,0x1f9c, + 0xff26,0xff27,0x005f,0x01c6,0x03b9,0x0fa9,0x7f74,0x0060,0x00cd,0x03ba,0x0faa,0x1f9d, + 0x01c7,0x01c8,0x07b5,0x1f9e,0xff28,0x07b6,0x07b7,0x0fab,0x3fa2,0xff29,0x0fac,0x0fad, + 0x3fa3,0xff2a,0x3fa2,0x01c9,0x07b8,0x0fae,0xff2b,0xff2c,0x01ca,0x03bb,0x1f9f,0x7f75, + 0xff2d,0x03bc,0x07b9,0x0faf,0xff2e,0xff2f,0x1fa0,0x1fa1,0xff30,0xff31,0xff32,0xff33, + 0xff34,0x7f76,0xff35,0xff31,0x07ba,0x1fa2,0xff36,0xff37,0x7f77,0x07bb,0x1fa3,0x7f78, + 0xff38,0xff39,0x1fa4,0x1fa5,0xff3a,0xff3b,0xff2e,0x3fa4,0xff3c,0xff3d,0xff3e,0xff31, + 0xff3f,0xff40,0xff30,0xff31,0xff31,0x0005,0x0026,0x00ce,0x03bd,0x1fa6,0x0027,0x0028, + 0x00cf,0x03be,0x1fa7,0x01cb,0x00d0,0x03bf,0x0fb0,0xff41,0x03c0,0x03c1,0x07bc,0x7f79, + 0xff42,0x1fa8,0x0fb1,0x3fa5,0xff43,0xff44,0x0010,0x0029,0x00d1,0x07bd,0x1fa9,0x002a, + 0x002b,0x00d2,0x03c2,0x1faa,0x00d3,0x00d4,0x01cc,0x07be,0x3fa6,0x03c3,0x03c4,0x0fb2, + 0x0fb3,0xff45,0x1fab,0x0fb4,0x1fac,0x7f7a,0xff46,0x0061,0x00d5,0x01cd,0x0fb5,0xff47, + 0x0062,0x00d6,0x03c5,0x0fb6,0x3fa7,0x01ce,0x01cf,0x03c6,0x1fad,0xff48,0x07bf,0x03c7, + 0x0fb7,0x7f7b,0xff49,0x1fae,0x1faf,0xff4a,0xff4b,0x7f7b,0x01d0,0x07c0,0x1fb0,0xff4c, + 0xff4d,0x01d1,0x03c8,0x0fb8,0x7f7c,0xff4e,0x03c9,0x07c1,0x1fb1,0xff4f,0xff50,0x1fb2, + 0x0fb9,0xff51,0xff52,0xff53,0xff54,0xff55,0xff56,0xff57,0xff52,0x07c2,0x1fb3,0xff58, + 0xff59,0xff5a,0x07c3,0x1fb4,0xff5b,0xff5c,0xff5d,0x0fba,0x1fb5,0x7f7d,0xff5e,0xff4f, + 0xff5f,0xff60,0xff61,0xff62,0xff52,0xff63,0xff64,0xff51,0xff52,0xff52,0x002c,0x00d7, + 0x07c4,0x1fb6,0xff65,0x00d8,0x00d9,0x03ca,0x0fbb,0xff66,0x07c5,0x03cb,0x07c6,0x1fb7, + 0xff67,0x0fbc,0x1fb8,0x1fb9,0x7f7e,0xff68,0xff69,0xff6a,0x3fa8,0xff6b,0x7f7e,0x002d, + 0x00da,0x03cc,0x1fba,0xff6c,0x00db,0x00dc,0x03cd,0x0fbd,0xff6d,0x03ce,0x03cf,0x07c7, + 0x1fbb,0xff6e,0x1fbc,0x0fbe,0x1fbd,0xff6f,0xff70,0x3fa9,0x3faa,0x3fab,0xff71,0xff6f, + 0x00dd,0x01d2,0x07c8,0x1fbe,0xff72,0x00de,0x01d3,0x07c9,0xff73,0x3fac,0x03d0,0x03d1, + 0x0fbf,0x7f7f,0xff74,0x0fc0,0x0fc1,0x1fbf,0xff75,0xff76,0x7f80,0xff77,0xff78,0xff79, + 0xff75,0x03d2,0x0fc2,0x7f81,0xff7a,0xff7b,0x03d3,0x0fc3,0x0fc4,0x3fad,0xff7c,0x0fc5, + 0x0fc6,0x1fc0,0xff7d,0xff7e,0x3fae,0x7f82,0xff7f,0xff80,0xff80,0xff81,0xff82,0xff83, + 0xff80,0xff80,0x0fc7,0x7f83,0x7f84,0xff84,0xff7a,0x1fc1,0x1fc2,0xff85,0xff86,0x3fad, + 0x3faf,0xff87,0xff88,0xff89,0xff7d,0xff8a,0xff8b,0xff8c,0xff80,0xff80,0x3fae,0x7f82, + 0xff7f,0xff80,0xff80,0x00df,0x03d4,0x1fc3,0x7f85,0xff8d,0x03d5,0x07ca,0x1fc4,0xff8e, + 0xff8f,0x1fc5,0x1fc6,0x3fb0,0xff90,0xff91,0xff92,0xff93,0xff94,0xff95,0xff96,0xff97, + 0xff98,0xff99,0xff9a,0xff95,0x00e0,0x03d6,0x07cb,0x7f86,0xff9b,0x01d4,0x03d7,0x0fc8, + 0xff9c,0xff9d,0x0fc9,0x0fca,0x7f87,0xff9e,0xff9f,0xffa0,0x3fb1,0xffa1,0xffa2,0xffa3, + 0xffa4,0xffa5,0xffa6,0xffa7,0xffa2,0x01d5,0x07cc,0x3fb2,0xffa8,0xffa9,0x03d8,0x07cd, + 0x1fc7,0xffaa,0xffab,0x3fb3,0x1fc8,0x3fb4,0xffac,0xffad,0xffae,0x7f88,0x7f89,0xffaf, + 0xffaf,0xffb0,0xffb1,0xffb2,0xffaf,0xffaf,0x07ce,0x1fc9,0xffb3,0xffb4,0xffb5,0x07cf, + 0x1fca,0x7f8a,0xffb6,0xffb7,0x1fcb,0xffb8,0xffb9,0xffba,0xffba,0xffbb,0xffbc,0xffbd, + 0xffbe,0xffbe,0xffbf,0xffc0,0xffbd,0xffbe,0xffbe,0x7f8b,0xffc1,0xffc2,0xffc3,0xffb4, + 0x3fb5,0xffc4,0xffc5,0xffc6,0xffb6,0xffc7,0xffc8,0xffc9,0xffba,0xffba,0xffca,0xffcb, + 0xffbd,0xffbe,0xffbe,0xffbb,0xffbc,0xffbd,0xffbe,0xffbe,0x01d6,0x1fcc,0xffcc,0xffcd, + 0xffce,0x07d0,0x1fcd,0xffcf,0xffd0,0xffd1,0x3fb6,0x7f8c,0xffd2,0xffd3,0xff90,0x7f8d, + 0xffd4,0xffd5,0xffd6,0xff95,0xffd7,0xffd8,0xff94,0xff95,0xff95,0x01d7,0x1fce,0x7f8e, + 0x7f8f,0xffd9,0x0fcb,0x1fcf,0x3fb7,0xffda,0xffdb,0xffdc,0x7f90,0xffdd,0xffde,0xff9e, + 0xffdf,0xffe0,0xffe1,0xffe2,0xffa2,0xffe3,0xffe4,0xffa1,0xffa2,0xffa2,0x07d1,0x1fd0, + 0x7f91,0xffe5,0xffa8,0x0fcc,0x3fb8,0xffe6,0xffe7,0xffaa,0xffe8,0xffe9,0xffea,0xffeb, + 0xffac,0xffec,0xffed,0xffee,0xffaf,0xffaf,0xffae,0x7f88,0x7f89,0xffaf,0xffaf,0xffef, + 0xfff0,0xfff1,0xfff2,0xffb4,0xfff3,0xfff4,0xfff5,0xfff6,0xffb6,0xfff7,0xfff8,0xfff9, + 0xffba,0xffba,0xfffa,0xfffb,0xffbd,0xffbe,0xffbe,0xffbb,0xffbc,0xffbd,0xffbe,0xffbe, + 0xfffc,0xfffd,0xffb3,0xffb4,0xffb4,0xfffe,0xffff, +}; + +static const uint8_t cvh_huffbits4[246] = { + 2, 4, 7, 10, 4, 5, 7, 10, 7, 8, 10, 14, + 11, 11, 15, 15, 4, 5, 9, 12, 5, 5, 8, 12, + 8, 7, 10, 15, 11, 11, 15, 15, 7, 9, 12, 15, + 8, 8, 12, 15, 10, 10, 13, 15, 14, 14, 15, 0, + 11, 13, 15, 15, 11, 13, 15, 15, 14, 15, 15, 0, + 15, 15, 0, 0, 4, 5, 9, 13, 5, 6, 9, 13, + 9, 9, 11, 15, 14, 13, 15, 15, 4, 6, 9, 12, + 5, 6, 9, 13, 9, 8, 11, 15, 13, 12, 15, 15, + 7, 9, 12, 15, 7, 8, 11, 15, 10, 10, 14, 15, + 14, 15, 15, 0, 10, 12, 15, 15, 11, 13, 15, 15, + 15, 15, 15, 0, 15, 15, 0, 0, 6, 9, 13, 14, + 8, 9, 12, 15, 12, 12, 15, 15, 15, 15, 15, 0, + 7, 9, 13, 15, 8, 9, 12, 15, 11, 12, 15, 15, + 15, 15, 15, 0, 9, 11, 15, 15, 9, 11, 15, 15, + 14, 14, 15, 0, 15, 15, 0, 0, 14, 15, 15, 0, + 14, 15, 15, 0, 15, 15, 0, 0, 0, 0, 0, 0, + 9, 12, 15, 15, 12, 13, 15, 15, 15, 15, 15, 0, + 15, 15, 0, 0, 10, 12, 15, 15, 12, 14, 15, 15, + 15, 15, 15, 0, 15, 15, 0, 0, 14, 15, 15, 0, + 15, 15, 15, 0, 15, 15, 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 15, 15, +}; + + +static const uint16_t cvh_huffcodes4[246] = { + 0x0000,0x0004,0x006c,0x03e6,0x0005,0x0012,0x006d,0x03e7,0x006e,0x00e8,0x03e8,0x3fc4, + 0x07e0,0x07e1,0x7fa4,0x7fa5,0x0006,0x0013,0x01e2,0x0fda,0x0014,0x0015,0x00e9,0x0fdb, + 0x00ea,0x006f,0x03e9,0x7fa6,0x07e2,0x07e3,0x7fa7,0x7fa8,0x0070,0x01e3,0x0fdc,0x7fa9, + 0x00eb,0x00ec,0x0fdd,0x7faa,0x03ea,0x03eb,0x1fd6,0x7fab,0x3fc5,0x3fc6,0x7fac,0x1fd6, + 0x07e4,0x1fd7,0x7fad,0x7fae,0x07e5,0x1fd8,0x7faf,0x7fb0,0x3fc7,0x7fb1,0x7fb2,0x1fd6, + 0x7fb3,0x7fb4,0x1fd6,0x1fd6,0x0007,0x0016,0x01e4,0x1fd9,0x0017,0x0032,0x01e5,0x1fda, + 0x01e6,0x01e7,0x07e6,0x7fb5,0x3fc8,0x1fdb,0x7fb6,0x7fb7,0x0008,0x0033,0x01e8,0x0fde, + 0x0018,0x0034,0x01e9,0x1fdc,0x01ea,0x00ed,0x07e7,0x7fb8,0x1fdd,0x0fdf,0x7fb9,0x7fba, + 0x0071,0x01eb,0x0fe0,0x7fbb,0x0072,0x00ee,0x07e8,0x7fbc,0x03ec,0x03ed,0x3fc9,0x7fbd, + 0x3fca,0x7fbe,0x7fbf,0x3fc9,0x03ee,0x0fe1,0x7fc0,0x7fc1,0x07e9,0x1fde,0x7fc2,0x7fc3, + 0x7fc4,0x7fc5,0x7fc6,0x3fc9,0x7fc7,0x7fc8,0x3fc9,0x3fc9,0x0035,0x01ec,0x1fdf,0x3fcb, + 0x00ef,0x01ed,0x0fe2,0x7fc9,0x0fe3,0x0fe4,0x7fca,0x7fcb,0x7fcc,0x7fcd,0x7fce,0x7fca, + 0x0073,0x01ee,0x1fe0,0x7fcf,0x00f0,0x01ef,0x0fe5,0x7fd0,0x07ea,0x0fe6,0x7fd1,0x7fd2, + 0x7fd3,0x7fd4,0x7fd5,0x7fd1,0x01f0,0x07eb,0x7fd6,0x7fd7,0x01f1,0x07ec,0x7fd8,0x7fd9, + 0x3fcc,0x3fcd,0x7fda,0x7fda,0x7fdb,0x7fdc,0x7fda,0x7fda,0x3fce,0x7fdd,0x7fde,0x7fd6, + 0x3fcf,0x7fdf,0x7fe0,0x7fd8,0x7fe1,0x7fe2,0x7fda,0x7fda,0x3fcc,0x3fcd,0x7fda,0x7fda, + 0x01f2,0x0fe7,0x7fe3,0x7fe4,0x0fe8,0x1fe1,0x7fe5,0x7fe6,0x7fe7,0x7fe8,0x7fe9,0x7fca, + 0x7fea,0x7feb,0x7fca,0x7fca,0x03ef,0x0fe9,0x7fec,0x7fed,0x0fea,0x3fd0,0x7fee,0x7fef, + 0x7ff0,0x7ff1,0x7ff2,0x7fd1,0x7ff3,0x7ff4,0x7fd1,0x7fd1,0x3fd1,0x7ff5,0x7ff6,0x7fd6, + 0x7ff7,0x7ff8,0x7ff9,0x7fd8,0x7ffa,0x7ffb,0x7fda,0x7fda,0x3fcc,0x3fcd,0x7fda,0x7fda, + 0x7ffc,0x7ffd,0x7fd6,0x7fd6,0x7ffe,0x7fff, +}; + + +static const uint8_t cvh_huffbits5[230] = { + 2, 4, 8, 4, 5, 9, 9, 10, 14, 4, 6, 11, + 5, 6, 12, 10, 11, 15, 9, 11, 15, 10, 13, 15, + 14, 15, 0, 4, 6, 12, 6, 7, 12, 12, 12, 15, + 5, 7, 13, 6, 7, 13, 12, 13, 15, 10, 12, 15, + 11, 13, 15, 15, 15, 0, 8, 13, 15, 11, 12, 15, + 15, 15, 0, 10, 13, 15, 12, 15, 15, 15, 15, 0, + 15, 15, 0, 15, 15, 0, 0, 0, 0, 4, 5, 11, + 5, 7, 12, 11, 12, 15, 6, 7, 13, 7, 8, 14, + 12, 14, 15, 11, 13, 15, 12, 13, 15, 15, 15, 0, + 5, 6, 13, 7, 8, 15, 12, 14, 15, 6, 8, 14, + 7, 8, 15, 14, 15, 15, 12, 12, 15, 12, 13, 15, + 15, 15, 0, 9, 13, 15, 12, 13, 15, 15, 15, 0, + 11, 13, 15, 13, 13, 15, 15, 15, 0, 14, 15, 0, + 15, 15, 0, 0, 0, 0, 8, 10, 15, 11, 12, 15, + 15, 15, 0, 10, 12, 15, 12, 13, 15, 15, 15, 0, + 14, 15, 0, 15, 15, 0, 0, 0, 0, 8, 12, 15, + 12, 13, 15, 15, 15, 0, 11, 13, 15, 13, 15, 15, + 15, 15, 0, 15, 15, 0, 15, 15, 0, 0, 0, 0, + 14, 15, 0, 15, 15, 0, 0, 0, 0, 15, 15, 0, + 15, 15, +}; + + + +static const uint16_t cvh_huffcodes5[230] = { + 0x0000,0x0004,0x00f0,0x0005,0x0012,0x01f0,0x01f1,0x03e8,0x3fce,0x0006,0x0030,0x07de, + 0x0013,0x0031,0x0fd2,0x03e9,0x07df,0x7fb0,0x01f2,0x07e0,0x7fb1,0x03ea,0x1fd2,0x7fb2, + 0x3fcf,0x7fb3,0x0031,0x0007,0x0032,0x0fd3,0x0033,0x0070,0x0fd4,0x0fd5,0x0fd6,0x7fb4, + 0x0014,0x0071,0x1fd3,0x0034,0x0072,0x1fd4,0x0fd7,0x1fd5,0x7fb5,0x03eb,0x0fd8,0x7fb6, + 0x07e1,0x1fd6,0x7fb7,0x7fb8,0x7fb9,0x0072,0x00f1,0x1fd7,0x7fba,0x07e2,0x0fd9,0x7fbb, + 0x7fbc,0x7fbd,0x0070,0x03ec,0x1fd8,0x7fbe,0x0fda,0x7fbf,0x7fc0,0x7fc1,0x7fc2,0x0072, + 0x7fc3,0x7fc4,0x0071,0x7fc5,0x7fc6,0x0072,0x0034,0x0072,0x0072,0x0008,0x0015,0x07e3, + 0x0016,0x0073,0x0fdb,0x07e4,0x0fdc,0x7fc7,0x0035,0x0074,0x1fd9,0x0075,0x00f2,0x3fd0, + 0x0fdd,0x3fd1,0x7fc8,0x07e5,0x1fda,0x7fc9,0x0fde,0x1fdb,0x7fca,0x7fcb,0x7fcc,0x00f2, + 0x0017,0x0036,0x1fdc,0x0076,0x00f3,0x7fcd,0x0fdf,0x3fd2,0x7fce,0x0037,0x00f4,0x3fd3, + 0x0077,0x00f5,0x7fcf,0x3fd4,0x7fd0,0x7fd1,0x0fe0,0x0fe1,0x7fd2,0x0fe2,0x1fdd,0x7fd3, + 0x7fd4,0x7fd5,0x00f5,0x01f3,0x1fde,0x7fd6,0x0fe3,0x1fdf,0x7fd7,0x7fd8,0x7fd9,0x00f3, + 0x07e6,0x1fe0,0x7fda,0x1fe1,0x1fe2,0x7fdb,0x7fdc,0x7fdd,0x00f5,0x3fd5,0x7fde,0x00f4, + 0x7fdf,0x7fe0,0x00f5,0x0077,0x00f5,0x00f5,0x00f6,0x03ed,0x7fe1,0x07e7,0x0fe4,0x7fe2, + 0x7fe3,0x7fe4,0x0073,0x03ee,0x0fe5,0x7fe5,0x0fe6,0x1fe3,0x7fe6,0x7fe7,0x7fe8,0x00f2, + 0x3fd6,0x7fe9,0x0074,0x7fea,0x7feb,0x00f2,0x0075,0x00f2,0x00f2,0x00f7,0x0fe7,0x7fec, + 0x0fe8,0x1fe4,0x7fed,0x7fee,0x7fef,0x00f3,0x07e8,0x1fe5,0x7ff0,0x1fe6,0x7ff1,0x7ff2, + 0x7ff3,0x7ff4,0x00f5,0x7ff5,0x7ff6,0x00f4,0x7ff7,0x7ff8,0x00f5,0x0077,0x00f5,0x00f5, + 0x3fd7,0x7ff9,0x0036,0x7ffa,0x7ffb,0x00f3,0x0076,0x00f3,0x00f3,0x7ffc,0x7ffd,0x0000, + 0x7ffe,0x7fff, +}; + + +static const uint8_t cvh_huffbits6[32] = { + 1, 4, 4, 6, 4, 6, 6, 8, 4, 6, 6, 8, + 6, 9, 8, 10, 4, 6, 7, 8, 6, 9, 8, 11, + 6, 9, 8, 10, 8, 10, 9, 11, +}; + +static const uint16_t cvh_huffcodes6[32] = { + 0x0000,0x0008,0x0009,0x0034,0x000a,0x0035,0x0036,0x00f6,0x000b,0x0037,0x0038,0x00f7, + 0x0039,0x01fa,0x00f8,0x03fc,0x000c,0x003a,0x007a,0x00f9,0x003b,0x01fb,0x00fa,0x07fe, + 0x003c,0x01fc,0x00fb,0x03fd,0x00fc,0x03fe,0x01fd,0x07ff, +}; + +static const uint16_t* cvh_huffcodes[7] = { + cvh_huffcodes0, cvh_huffcodes1, cvh_huffcodes2, cvh_huffcodes3, + cvh_huffcodes4, cvh_huffcodes5, cvh_huffcodes6, +}; + +static const uint8_t* cvh_huffbits[7] = { + cvh_huffbits0, cvh_huffbits1, cvh_huffbits2, cvh_huffbits3, + cvh_huffbits4, cvh_huffbits5, cvh_huffbits6, +}; + + +static const uint16_t ccpl_huffcodes2[3] = { + 0x02,0x00,0x03, +}; + +static const uint16_t ccpl_huffcodes3[7] = { + 0x3e,0x1e,0x02,0x00,0x06,0x0e,0x3f, +}; + +static const uint16_t ccpl_huffcodes4[15] = { + 0xfc,0xfd,0x7c,0x3c,0x1c,0x0c,0x04,0x00,0x05,0x0d,0x1d,0x3d, + 0x7d,0xfe,0xff, +}; + +static const uint16_t ccpl_huffcodes5[31] = { + 0x03f8,0x03f9,0x03fa,0x03fb,0x01f8,0x01f9,0x00f8,0x00f9,0x0078,0x0079,0x0038,0x0039, + 0x0018,0x0019,0x0004,0x0000,0x0005,0x001a,0x001b,0x003a,0x003b,0x007a,0x007b,0x00fa, + 0x00fb,0x01fa,0x01fb,0x03fc,0x03fd,0x03fe,0x03ff, +}; + +static const uint16_t ccpl_huffcodes6[63] = { + 0x0004,0x0005,0x0005,0x0006,0x0006,0x0007,0x0007,0x0007,0x0007,0x0008,0x0008,0x0008, + 0x0008,0x0009,0x0009,0x0009,0x0009,0x000a,0x000a,0x000a,0x000a,0x000a,0x000b,0x000b, + 0x000b,0x000b,0x000c,0x000d,0x000e,0x000e,0x0010,0x0000,0x000a,0x0018,0x0019,0x0036, + 0x0037,0x0074,0x0075,0x0076,0x0077,0x00f4,0x00f5,0x00f6,0x00f7,0x01f5,0x01f6,0x01f7, + 0x01f8,0x03f6,0x03f7,0x03f8,0x03f9,0x03fa,0x07fa,0x07fb,0x07fc,0x07fd,0x0ffd,0x1ffd, + 0x3ffd,0x3ffe,0xffff, +}; + +static const uint8_t ccpl_huffbits2[3] = { + 2,1,2, +}; + +static const uint8_t ccpl_huffbits3[7] = { + 6,5,2,1,3,4,6, +}; + +static const uint8_t ccpl_huffbits4[15] = { + 8,8,7,6,5,4,3,1,3,4,5,6,7,8,8, +}; + +static const uint8_t ccpl_huffbits5[31] = { + 10,10,10,10,9,9,8,8,7,7,6,6, + 5,5,3,1,3,5,5,6,6,7,7,8, + 8,9,9,10,10,10,10, +}; + +static const uint8_t ccpl_huffbits6[63] = { + 16,15,14,13,12,11,11,11,11,10,10,10, + 10,9,9,9,9,9,8,8,8,8,7,7, + 7,7,6,6,5,5,3,1,4,5,5,6, + 6,7,7,7,7,8,8,8,8,9,9,9, + 9,10,10,10,10,10,11,11,11,11,12,13, + 14,14,16, +}; + +static const uint16_t* ccpl_huffcodes[5] = { + ccpl_huffcodes2,ccpl_huffcodes3, + ccpl_huffcodes4,ccpl_huffcodes5,ccpl_huffcodes6 +}; + +static const uint8_t* ccpl_huffbits[5] = { + ccpl_huffbits2,ccpl_huffbits3, + ccpl_huffbits4,ccpl_huffbits5,ccpl_huffbits6 +}; + + +//Coupling tables + +static const int cplband[51] = { + 0,1,2,3,4,5,6,7,8,9, + 10,11,11,12,12,13,13,14,14,14, + 15,15,15,15,16,16,16,16,16,17, + 17,17,17,17,17,18,18,18,18,18, + 18,18,19,19,19,19,19,19,19,19, + 19, +}; Index: bitstream.c =================================================================== --- bitstream.c (revision 0) +++ bitstream.c (revision 0) @@ -0,0 +1,313 @@ +/* + * Common bit i/o utils + * Copyright (c) 2000, 2001 Fabrice Bellard. + * Copyright (c) 2002-2004 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * alternative bitstream reader & writer by Michael Niedermayer + */ + +/** + * @file bitstream.c + * bitstream api. + */ + +#include "bitstream.h" +#define DEBUGF printf +#define INIT_VLC_LE 2 +/** + * Same as av_mallocz_static(), but does a realloc. + * + * @param[in] ptr The block of memory to reallocate. + * @param[in] size The requested size. + * @return Block of memory of requested size. + * @deprecated. Code which uses ff_realloc_static is broken/missdesigned + * and should correctly use static arrays + */ +attribute_deprecated void *ff_realloc_static(void *ptr, unsigned int size); + + +const uint8_t ff_sqrt_tab[128]={ + 0, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11 +}; + +const uint8_t ff_log2_tab[256]={ + 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 +}; + +#if 0 +void align_put_bits(PutBitContext *s) +{ +#ifdef ALT_BITSTREAM_WRITER + put_bits(s,( - s->index) & 7,0); +#else + put_bits(s,s->bit_left & 7,0); +#endif +} + +void ff_put_string(PutBitContext * pbc, char *s, int put_zero) +{ + while(*s){ + put_bits(pbc, 8, *s); + s++; + } + if(put_zero) + put_bits(pbc, 8, 0); +} +#endif +/* VLC decoding */ + +//#define DEBUG_VLC + +#define GET_DATA(v, table, i, wrap, size) \ +{\ + const uint8_t *ptr = (const uint8_t *)table + i * wrap;\ + switch(size) {\ + case 1:\ + v = *(const uint8_t *)ptr;\ + break;\ + case 2:\ + v = *(const uint16_t *)ptr;\ + break;\ + default:\ + v = *(const uint32_t *)ptr;\ + break;\ + }\ +} + + +/*static int alloc_table(VLC *vlc, int size) +{ + int index; + index = vlc->table_size; + vlc->table_size += size; + if (vlc->table_size > vlc->table_allocated) { + DEBUGF("Tried to allocate past the end of a Huffman table: %d/%d\n", + vlc->table_allocated, vlc->table_allocated+(1 << vlc->bits)); + vlc->table_allocated += (1 << vlc->bits); + if (!vlc->table) + return -1; + } +DEBUGF("index = %d\n",index); + return index; +}*/ +#if 0 +static int alloc_table(VLC *vlc, int size) +{ + int index; + index = vlc->table_size; + vlc->table_size += size; + if (vlc->table_size > vlc->table_allocated) { + + vlc->table_allocated += (1 << vlc->bits); + /*if(use_static) + vlc->table = ff_realloc_static(vlc->table, + sizeof(VLC_TYPE) * 2 * vlc->table_allocated); + else*/ + vlc->table = av_realloc(vlc->table, + sizeof(VLC_TYPE) * 2 * vlc->table_allocated); +printf("realloc size = %d\n",sizeof(VLC_TYPE) * 2 * vlc->table_allocated); + if (!vlc->table) + return -1; + } + return index; +} +#endif +#if 1 +static int alloc_table(VLC *vlc, int size) +{ + int index; + index = vlc->table_size; + vlc->table_size += size; + if (vlc->table_size > vlc->table_allocated) { + DEBUGF("Tried to allocate past the end of a Huffman table: %d/%d\n", + vlc->table_allocated, vlc->table_allocated+(1 << vlc->bits)); + vlc->table_allocated += (1 << vlc->bits); + if (!vlc->table) + return -1; + } + return index; +} +#endif +static int build_table(VLC *vlc, int table_nb_bits, + int nb_codes, + const void *bits, int bits_wrap, int bits_size, + const void *codes, int codes_wrap, int codes_size, + uint32_t code_prefix, int n_prefix) +{ + int i, j, k, n, table_size, table_index, nb, n1, index, code_prefix2; + uint32_t code; + int flags = 0; + VLC_TYPE (*table)[2]; + + table_size = 1 << table_nb_bits; + table_index = alloc_table(vlc, table_size); +#ifdef DEBUG_VLC + printf("new table index=%d size=%d code_prefix=%x n=%d\n", + table_index, table_size, code_prefix, n_prefix); +#endif + if (table_index < 0) + return -1; + table = &vlc->table[table_index]; + + for(i=0;i=32 ? 0xffffffff : (uint32_t)(1 << n_prefix)-1); + else + code_prefix2= code >> n; + if (n > 0 && (int)code_prefix2 == (int)code_prefix) { + if (n <= table_nb_bits) { + /* no need to add another table */ + j = (code << (table_nb_bits - n)) & (table_size - 1); + nb = 1 << (table_nb_bits - n); + for(k=0;k> n_prefix) + (k<> ((flags & INIT_VLC_LE) ? n_prefix : n)) & ((1 << table_nb_bits) - 1); +#ifdef DEBUG_VLC + printf("%4x: n=%d (subtable)\n", + j, n); +#endif + /* compute table size */ + n1 = -table[j][1]; //bits + if (n > n1) + n1 = n; + table[j][1] = -n1; //bits + } + } + } + + /* second pass : fill auxillary tables recursively */ + for(i=0;i table_nb_bits) { + n = table_nb_bits; + table[i][1] = -n; //bits + } + index = build_table(vlc, n, nb_codes, + bits, bits_wrap, bits_size, + codes, codes_wrap, codes_size, + (flags & INIT_VLC_LE) ? (code_prefix | (i << n_prefix)) : ((code_prefix << table_nb_bits) | i), + n_prefix + table_nb_bits); + if (index < 0) + return -1; + /* note: realloc has been done, so reload tables */ + table = &vlc->table[table_index]; + table[i][0] = index; //code + } + } + return table_index; +} + + +/* Build VLC decoding tables suitable for use with get_vlc(). + + 'nb_bits' set thee decoding table size (2^nb_bits) entries. The + bigger it is, the faster is the decoding. But it should not be too + big to save memory and L1 cache. '9' is a good compromise. + + 'nb_codes' : number of vlcs codes + + 'bits' : table which gives the size (in bits) of each vlc code. + + 'codes' : table which gives the bit pattern of of each vlc code. + + 'xxx_wrap' : give the number of bytes between each entry of the + 'bits' or 'codes' tables. + + 'xxx_size' : gives the number of bytes of each entry of the 'bits' + or 'codes' tables. + + 'wrap' and 'size' allows to use any memory configuration and types + (byte/word/long) to store the 'bits' and 'codes' tables. + + 'use_static' should be set to 1 for tables, which should be freed + with av_free_static(), 0 if free_vlc() will be used. +*/ +int init_vlc(VLC *vlc, int nb_bits, int nb_codes, + const void *bits, int bits_wrap, int bits_size, + const void *codes, int codes_wrap, int codes_size, + int flags) +{ + + vlc->bits = nb_bits; + vlc->table_size = 0; + +#ifdef DEBUG_VLC + printf("build table nb_codes=%d\n", nb_codes); +#endif + + if (build_table(vlc, nb_bits, nb_codes, + bits, bits_wrap, bits_size, + codes, codes_wrap, codes_size, + 0, 0) < 0) { + //av_free(vlc->table); + return -1; + } + /* return flags to block gcc warning while allowing us to keep + * consistent with ffmpeg's function parameters + */ + return flags; +} +#if 0 +void free_vlc(VLC *vlc) +{ + av_freep(&vlc->table); +} +#endif Index: cook.c =================================================================== --- cook.c (revision 0) +++ cook.c (revision 0) @@ -0,0 +1,923 @@ +/* + * COOK compatible decoder + * Copyright (c) 2003 Sascha Sommer + * Copyright (c) 2005 Benjamin Larsson + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +/** + * @file cook.c + * Cook compatible decoder. + * This decoder handles RealNetworks, RealAudio G2 data. + * Cook is identified by the codec name cook in RM files. + * + * To use this decoder, a calling application must supply the extradata + * bytes provided from the RM container; 8+ bytes for mono streams and + * 16+ for stereo streams (maybe more). + * + * Codec technicalities (all this assume a buffer length of 1024): + * Cook works with several different techniques to achieve its compression. + * In the timedomain the buffer is divided into 8 pieces and quantized. If + * two neighboring pieces have different quantization index a smooth + * quantization curve is used to get a smooth overlap between the different + * pieces. + * To get to the transformdomain Cook uses a modulated lapped transform. + * The transform domain has 50 subbands with 20 elements each. This + * means only a maximum of 50*20=1000 coefficients are used out of the 1024 + * available. + */ + +/* Enable the following define for a fixed point implementation */ +#define COOK_FIXPOINT + +#include +#include +#include +#include +#include +#include +#include +#include +#include "rm.h" +#include "cook.h" + +/* the different Cook versions */ +#define MONO 0x1000001 +#define STEREO 0x1000002 +#define JOINT_STEREO 0x1000003 +#define MC_COOK 0x2000000 //multichannel Cook, not supported + +#define SUBBAND_SIZE 20 +#define COOKDEBUG +#define DEBUGF printf + +/** + * Random bit stream generator. + */ +static int inline cook_random(COOKContext *q) +{ + q->random_state = + q->random_state * 214013 + 2531011; /* typical RNG numbers */ + + return (q->random_state/0x1000000)&1; /*>>31*/ +} +#include "cook_fixpoint.h" + + +/* debug functions */ + +#ifdef COOKDEBUG +static void dump_int_table(int* table, int size, int delimiter) { + int i=0; + DEBUGF("\n[%d]: ",i); + for (i=0 ; ienvelope_quant_index[i].table = vlcbuf[i]; + q->envelope_quant_index[i].table_allocated = VLCBUF1SIZE; + result &= init_vlc (&q->envelope_quant_index[i], 9, 24, + envelope_quant_index_huffbits[i], 1, 1, + envelope_quant_index_huffcodes[i], 2, 2, 0); + } + DEBUGF("sqvh VLC init\n"); + for (i=0 ; i<7 ; i++) { + q->sqvh[i].table = vlcbuf[i+13]; + q->sqvh[i].table_allocated = VLCBUF1SIZE; + result &= init_vlc (&q->sqvh[i], vhvlcsize_tab[i], vhsize_tab[i], + cvh_huffbits[i], 1, 1, + cvh_huffcodes[i], 2, 2, 0); + } + + if (q->nb_channels==2 && q->joint_stereo==1){ + q->ccpl.table = vlcbuf[20]; + q->ccpl.table_allocated = VLCBUF1SIZE; + result &= init_vlc (&q->ccpl, 6, (1<js_vlc_bits)-1, + ccpl_huffbits[q->js_vlc_bits-2], 1, 1, + ccpl_huffcodes[q->js_vlc_bits-2], 2, 2, 0); + DEBUGF("Joint-stereo VLC used.\n"); + } + + DEBUGF("VLC tables initialized.\n"); + return result; +} + +/*************** init functions end ***********/ + +/** + * Cook indata decoding, every 32 bits are XORed with 0x37c511f2. + * 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. + * + * @param inbuffer pointer to byte array of indata + * @param out pointer to byte 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 int decode_bytes(uint8_t* inbuffer, uint8_t* out, int bytes){ + int i, off; + uint32_t c; + uint32_t* buf; + uint32_t* obuf = (uint32_t*) out; + /* FIXME: 64 bit platforms would be able to do 64 bits at a time. + * I'm too lazy though, should be something like + * for(i=0 ; i> (off*8)) | (0x37c511f2 << (32-(off*8)))); + bytes += 3 + off; + for (i = 0; i < bytes/4; i++) + obuf[i] = c ^ buf[i]; + + return off; +} + +/** + * Cook uninit + */ + +int cook_decode_close(COOKContext *q) +{ + int i; + //COOKContext *q = avctx->priv_data; + DEBUGF( "Deallocating memory.\n"); + + /* Free fixed/floating point resources. */ + free_cook_math(q); + + /* Free the VLC tables. */ + //for (i=0 ; i<13 ; i++) { + // free_vlc(&q->envelope_quant_index[i]); + //} + //for (i=0 ; i<7 ; i++) { + // free_vlc(&q->sqvh[i]); + //} + //if(q->nb_channels==2 && q->joint_stereo==1 ){ + // free_vlc(&q->ccpl); + //} + + DEBUGF("Memory deallocated.\n"); + + return 0; +} + +/** + * Fill the gain array for the timedomain quantization. + * + * @param q pointer to the COOKContext + * @param gaininfo[9] array of gain indices + */ + +static void decode_gain_info(GetBitContext *gb, int *gaininfo) +{ + int i, n; + + while (get_bits1(gb)) {} + n = get_bits_count(gb) - 1; //amount of elements*2 to update + + i = 0; + while (n--) { + int index = get_bits(gb, 3); + int gain = get_bits1(gb) ? get_bits(gb, 4) - 7 : -1; + + while (i <= index) gaininfo[i++] = gain; + } + while (i <= 8) gaininfo[i++] = 0; +} + +/** + * Create the quant index table needed for the envelope. + * + * @param q pointer to the COOKContext + * @param quant_index_table pointer to the array + */ + +static void decode_envelope(COOKContext *q, int* quant_index_table) { + int i,j, vlc_index; + int bitbias; + + bitbias = get_bits_count(&q->gb); + quant_index_table[0]= get_bits(&q->gb,6) - 6; //This is used later in categorize + + for (i=1 ; i < q->total_subbands ; i++){ + vlc_index=i; + if (i >= q->js_subband_start * 2) { + vlc_index-=q->js_subband_start; + } else { + vlc_index/=2; + if(vlc_index < 1) vlc_index = 1; + } + if (vlc_index>13) vlc_index = 13; //the VLC tables >13 are identical to No. 13 + + j = get_vlc2(&q->gb, q->envelope_quant_index[vlc_index-1].table, + q->envelope_quant_index[vlc_index-1].bits,2); + quant_index_table[i] = quant_index_table[i-1] + j - 12; //differential encoding + } +} + +/** + * Calculate the category and category_index vector. + * + * @param q pointer to the COOKContext + * @param quant_index_table pointer to the array + * @param category pointer to the category array + * @param category_index pointer to the category_index array + */ + +static void categorize(COOKContext *q, int* quant_index_table, + int* category, int* category_index){ + int exp_idx, bias, tmpbias, bits_left, num_bits, index, v, i, j; + int exp_index2[102]; + int exp_index1[102]; + + int tmp_categorize_array1[128]; + int tmp_categorize_array1_idx=0; + int tmp_categorize_array2[128]; + int tmp_categorize_array2_idx=0; + int category_index_size=0; + + bits_left = q->bits_per_subpacket - get_bits_count(&q->gb); + + if(bits_left > q->samples_per_channel) { + bits_left = q->samples_per_channel + + ((bits_left - q->samples_per_channel)*5)/8; + //DEBUGF("bits_left = %d\n",bits_left); + } + + memset(&exp_index1,0,102*sizeof(int)); + memset(&exp_index2,0,102*sizeof(int)); + memset(&tmp_categorize_array1,0,128*sizeof(int)); + memset(&tmp_categorize_array2,0,128*sizeof(int)); + + bias=-32; + + /* Estimate bias. */ + for (i=32 ; i>0 ; i=i/2){ + num_bits = 0; + index = 0; + for (j=q->total_subbands ; j>0 ; j--){ + exp_idx = (i - quant_index_table[index] + bias) / 2; + if (exp_idx<0){ + exp_idx=0; + } else if(exp_idx >7) { + exp_idx=7; + } + index++; + num_bits+=expbits_tab[exp_idx]; + } + if(num_bits >= bits_left - 32){ + bias+=i; + } + } + + /* Calculate total number of bits. */ + num_bits=0; + for (i=0 ; itotal_subbands ; i++) { + exp_idx = (bias - quant_index_table[i]) / 2; + if (exp_idx<0) { + exp_idx=0; + } else if(exp_idx >7) { + exp_idx=7; + } + num_bits += expbits_tab[exp_idx]; + exp_index1[i] = exp_idx; + exp_index2[i] = exp_idx; + } + tmpbias = bias = num_bits; + + for (j = 1 ; j < q->numvector_size ; j++) { + if (tmpbias + bias > 2*bits_left) { /* ---> */ + int max = -999999; + index=-1; + for (i=0 ; itotal_subbands ; i++){ + if (exp_index1[i] < 7) { + v = (-2*exp_index1[i]) - quant_index_table[i] - 32; + if ( v >= max) { + max = v; + index = i; + } + } + } + if(index==-1)break; + tmp_categorize_array1[tmp_categorize_array1_idx++] = index; + tmpbias -= expbits_tab[exp_index1[index]] - + expbits_tab[exp_index1[index]+1]; + ++exp_index1[index]; + } else { /* <--- */ + int min = 999999; + index=-1; + for (i=0 ; itotal_subbands ; i++){ + if(exp_index2[i] > 0){ + v = (-2*exp_index2[i])-quant_index_table[i]; + if ( v < min) { + min = v; + index = i; + } + } + } + if(index == -1)break; + tmp_categorize_array2[tmp_categorize_array2_idx++] = index; + tmpbias -= expbits_tab[exp_index2[index]] - + expbits_tab[exp_index2[index]-1]; + --exp_index2[index]; + } + } + + for(i=0 ; itotal_subbands ; i++) + category[i] = exp_index2[i]; + + /* Concatenate the two arrays. */ + for(i=tmp_categorize_array2_idx-1 ; i >= 0; i--) + category_index[category_index_size++] = tmp_categorize_array2[i]; + + for(i=0;inumvector_size;i++) + category_index[i]=0; + +} + + +/** + * Expand the category vector. + * + * @param q pointer to the COOKContext + * @param category pointer to the category array + * @param category_index pointer to the category_index array + */ + +static void inline expand_category(COOKContext *q, int* category, + int* category_index){ + int i; + for(i=0 ; inum_vectors ; i++){ + ++category[category_index[i]]; + } +} + +/** + * Unpack the subband_coef_index and subband_coef_sign vectors. + * + * @param q pointer to the COOKContext + * @param category pointer to the category array + * @param subband_coef_index array of indexes to quant_centroid_tab + * @param subband_coef_sign signs of coefficients + */ + +static int unpack_SQVH(COOKContext *q, int category, int* subband_coef_index, + int* subband_coef_sign) { + int i,j; + int vlc, vd ,tmp, result; + int ub; + int cb; + + vd = vd_tab[category]; + result = 0; + for(i=0 ; igb); + vlc = get_vlc2(&q->gb, q->sqvh[category].table, q->sqvh[category].bits, 3); + cb = get_bits_count(&q->gb); + if (q->bits_per_subpacket < get_bits_count(&q->gb)){ + vlc = 0; + result = 1; + } + for(j=vd-1 ; j>=0 ; j--){ + tmp = (vlc * invradix_tab[category])/0x100000; + subband_coef_index[vd*i+j] = vlc - tmp * (kmax_tab[category]+1); + vlc = tmp; + } + for(j=0 ; jgb) < q->bits_per_subpacket){ + subband_coef_sign[i*vd+j] = get_bits1(&q->gb); + } else { + result=1; + subband_coef_sign[i*vd+j]=0; + } + } else { + subband_coef_sign[i*vd+j]=0; + } + } + } + return result; +} + + +/** + * Fill the mlt_buffer with mlt coefficients. + * + * @param q pointer to the COOKContext + * @param category pointer to the category array + * @param quant_index_table pointer to the array + * @param mlt_buffer pointer to mlt coefficients + */ + + +static void decode_vectors(COOKContext* q, int* category, + int *quant_index_table, REAL_T *mlt_buffer){ + /* A zero in this table means that the subband coefficient is + random noise coded. */ + int subband_coef_index[SUBBAND_SIZE]; + /* A zero in this table means that the subband coefficient is a + positive multiplicator. */ + int subband_coef_sign[SUBBAND_SIZE]; + int band, j; + int index=0; + + for(band=0 ; bandtotal_subbands ; band++){ + index = category[band]; + if(category[band] < 7){ + if(unpack_SQVH(q, category[band], subband_coef_index, subband_coef_sign)){ + index=7; + for(j=0 ; jtotal_subbands ; j++) category[band+j]=7; + } + } + if(index==7) { + memset(subband_coef_index, 0, sizeof(subband_coef_index)); + memset(subband_coef_sign, 0, sizeof(subband_coef_sign)); + } + scalar_dequant_math(q, index, quant_index_table[band], + subband_coef_index, subband_coef_sign, + &mlt_buffer[band * 20]); + } + + if(q->total_subbands*SUBBAND_SIZE >= q->samples_per_channel){ + return; + } /* FIXME: should this be removed, or moved into loop above? */ +} + + +/** + * function for decoding mono data + * + * @param q pointer to the COOKContext + * @param mlt_buffer1 pointer to left channel mlt coefficients + * @param mlt_buffer2 pointer to right channel mlt coefficients + */ + +static void mono_decode(COOKContext *q, REAL_T *mlt_buffer) { + + int category_index[128]; + int quant_index_table[102]; + int category[128]; + + memset(&category, 0, 128*sizeof(int)); + memset(&category_index, 0, 128*sizeof(int)); + + decode_envelope(q, quant_index_table); + q->num_vectors = get_bits(&q->gb,q->log2_numvector_size); + categorize(q, quant_index_table, category, category_index); + expand_category(q, category, category_index); + decode_vectors(q, category, quant_index_table, mlt_buffer); +} + + +/** + * mlt overlapping and buffer management + * + * @param q pointer to the COOKContext + * @param gains_ptr current and previous gains + * @param previous_buffer pointer to the previous buffer to be used for overlapping + */ + +static void gain_compensate(COOKContext *q, cook_gains *gains_ptr, + REAL_T* previous_buffer) +{ + REAL_T *buffer = q->mono_mdct_output; + int i; + + /* Overlap with the previous block. */ + overlap_math(q, gains_ptr->previous[0], previous_buffer); + + /* Apply gain profile */ + for (i = 0; i < 8; i++) { + if (gains_ptr->now[i] || gains_ptr->now[i + 1]) + interpolate_math(q, &buffer[q->samples_per_channel/8 * i], + gains_ptr->now[i], gains_ptr->now[i + 1]); + } + + /* Save away the current to be previous block. */ + memcpy(previous_buffer, buffer+q->samples_per_channel, + sizeof(REAL_T)*q->samples_per_channel); +} + + +/** + * function for getting the jointstereo coupling information + * + * @param q pointer to the COOKContext + * @param decouple_tab decoupling array + * + */ + +static void decouple_info(COOKContext *q, int* decouple_tab){ + int length, i; + + if(get_bits1(&q->gb)) { + if(cplband[q->js_subband_start] > cplband[q->subbands-1]) return; + + length = cplband[q->subbands-1] - cplband[q->js_subband_start] + 1; + for (i=0 ; ijs_subband_start] + i] = get_vlc2(&q->gb, q->ccpl.table, q->ccpl.bits, 2); + } + return; + } + + if(cplband[q->js_subband_start] > cplband[q->subbands-1]) return; + + length = cplband[q->subbands-1] - cplband[q->js_subband_start] + 1; + for (i=0 ; ijs_subband_start] + i] = get_bits(&q->gb, q->js_vlc_bits); + } + return; +} + + +/** + * function for decoding joint stereo data + * + * @param q pointer to the COOKContext + * @param mlt_buffer1 pointer to left channel mlt coefficients + * @param mlt_buffer2 pointer to right channel mlt coefficients + */ + +static void joint_decode(COOKContext *q, REAL_T *mlt_buffer1, + REAL_T *mlt_buffer2) { + int i,j; + int decouple_tab[SUBBAND_SIZE]; + REAL_T decode_buffer[1060]; + int idx; + + memset(decouple_tab, 0, sizeof(decouple_tab)); + memset(decode_buffer, 0, sizeof(decode_buffer)); + + /* Make sure the buffers are zeroed out. */ + memset(mlt_buffer1,0, 1024*sizeof(REAL_T)); + memset(mlt_buffer2,0, 1024*sizeof(REAL_T)); + decouple_info(q, decouple_tab); + mono_decode(q, decode_buffer); + + /* The two channels are stored interleaved in decode_buffer. */ + for (i=0 ; ijs_subband_start ; i++) { + for (j=0 ; jjs_vlc_bits) - 1; + for (i=q->js_subband_start ; isubbands ; i++) { + int i1 = decouple_tab[cplband[i]]; + int i2 = idx - i1 - 1; + for (j=0 ; jjs_subband_start + i)*20)+j]; + mlt_buffer1[20*i+j] = cplscale_math(x, q->js_vlc_bits, i1); + mlt_buffer2[20*i+j] = cplscale_math(x, q->js_vlc_bits, i2); + } + } +} + +/** + * 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 + */ +#define FFSWAP(type,a,b) do{type SWAP_tmp= b; b= a; a= SWAP_tmp;}while(0) +static inline void +decode_bytes_and_gain(COOKContext *q, uint8_t *inbuffer, + cook_gains *gains_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, gains_ptr->now); + + /* Swap current and previous gains */ + FFSWAP(int *, gains_ptr->now, gains_ptr->previous); +} + +/** + * Final part of subpacket decoding: + * Apply modulated lapped transform, gain compensation, + * clip and convert to integer. + * + * @param q pointer to the COOKContext + * @param decode_buffer pointer to the mlt coefficients + * @param gain_ptr array of current/prev gain pointers + * @param previous_buffer pointer to the previous buffer to be used for overlapping + * @param out pointer to the output buffer + * @param chan 0: left or single channel, 1: right channel + */ + +static inline void + mlt_compensate_output(COOKContext *q, REAL_T *decode_buffer, + cook_gains *gains, REAL_T *previous_buffer, + int16_t *out, int chan) +{ + imlt_math(q, decode_buffer); + gain_compensate(q, gains, previous_buffer); + + output_math(q, out, chan); +} + + +/** + * Cook subpacket decoding. This function returns one decoded subpacket, + * usually 1024 samples per channel. + * + * @param q pointer to the COOKContext + * @param inbuffer pointer to the inbuffer + * @param sub_packet_size subpacket size + * @param outbuffer pointer to the outbuffer + */ + + +static int decode_subpacket(COOKContext *q, uint8_t *inbuffer, + int sub_packet_size, int16_t *outbuffer) { + /* packet dump */ +// for (i=0 ; igains1); + + if (q->joint_stereo) { + joint_decode(q, q->decode_buffer_1, q->decode_buffer_2); + } else { + mono_decode(q, q->decode_buffer_1); + + if (q->nb_channels == 2) { + decode_bytes_and_gain(q, inbuffer + sub_packet_size/2, &q->gains2); + mono_decode(q, q->decode_buffer_2); + } + } + + mlt_compensate_output(q, q->decode_buffer_1, &q->gains1, + q->mono_previous_buffer1, outbuffer, 0); + + if (q->nb_channels == 2) { + if (q->joint_stereo) { + mlt_compensate_output(q, q->decode_buffer_2, &q->gains1, + q->mono_previous_buffer2, outbuffer, 1); + } else { + mlt_compensate_output(q, q->decode_buffer_2, &q->gains2, + q->mono_previous_buffer2, outbuffer, 1); + } + } + return q->samples_per_frame * sizeof(int16_t); +} + + +/** + * Cook frame decoding + * + * @param avctx pointer to the AVCodecContext + */ +int cook_decode_frame(RMContext *rmctx,COOKContext *q, + int16_t *outbuffer, int *data_size, + const uint8_t *inbuffer, int buf_size) { + //COOKContext *q = avctx->priv_data; + //COOKContext *q; + + if (buf_size < rmctx->block_align) + return buf_size; + + *data_size = decode_subpacket(q, inbuffer, rmctx->block_align, outbuffer); + + /* Discard the first two frames: no valid audio. */ + if (rmctx->frame_number < 2) *data_size = 0; + + return rmctx->block_align; +} +/* +static int cook_decode_frame(AVCodecContext *avctx, + void *data, int *data_size, + uint8_t *buf, int buf_size) { + COOKContext *q = avctx->priv_data; + + if (buf_size < avctx->block_align) + return buf_size; + + *data_size = decode_subpacket(q, buf, avctx->block_align, data); + + /* Discard the first two frames: no valid audio. + if (avctx->frame_number < 2) *data_size = 0; + + return avctx->block_align; +}*/ + +#ifdef COOKDEBUG +static void dump_cook_context(COOKContext *q) +{ + //int i=0; +#define PRINT(a,b) DEBUGF(" %s = %d\n", a, b); + DEBUGF("COOKextradata\n"); + DEBUGF("cookversion=%x\n",q->cookversion); + if (q->cookversion > STEREO) { + PRINT("js_subband_start",q->js_subband_start); + PRINT("js_vlc_bits",q->js_vlc_bits); + } + DEBUGF("COOKContext\n"); + PRINT("nb_channels",q->nb_channels); + PRINT("bit_rate",q->bit_rate); + PRINT("sample_rate",q->sample_rate); + PRINT("samples_per_channel",q->samples_per_channel); + PRINT("samples_per_frame",q->samples_per_frame); + PRINT("subbands",q->subbands); + PRINT("random_state",q->random_state); + PRINT("js_subband_start",q->js_subband_start); + PRINT("log2_numvector_size",q->log2_numvector_size); + PRINT("numvector_size",q->numvector_size); + PRINT("total_subbands",q->total_subbands); +} +#endif + +/** + * Cook initialization + * + * @param avctx pointer to the AVCodecContext + */ + +int cook_decode_init(RMContext *rmctx, COOKContext *q) +{ + /* cook extradata */ + q->cookversion = rmctx->cook_version; + q->samples_per_frame = rmctx->samples_pf_pc; + q->subbands = rmctx->nb_subbands; + q->extradata_size = rmctx->extradata_size; + if (q->extradata_size >= 16){ + q->js_subband_start = rmctx->js_subband_start; + q->js_vlc_bits = rmctx->js_vlc_bits; + } + + /* Take data from the RMContext (RM container). */ + q->sample_rate = rmctx->sample_rate; + q->nb_channels = rmctx->nb_channels; + q->bit_rate = rmctx->bit_rate; + + /* Initialize state. */ + q->random_state = 1; + + /* Initialize extradata related variables. */ + q->samples_per_channel = q->samples_per_frame / q->nb_channels; + q->bits_per_subpacket = rmctx->block_align * 8; + + /* Initialize default data states. */ + q->log2_numvector_size = 5; + q->total_subbands = q->subbands; + + /* Initialize version-dependent variables */ + DEBUGF("q->cookversion=%x\n",q->cookversion); + q->joint_stereo = 0; + switch (q->cookversion) { + case MONO: + if (q->nb_channels != 1) { + DEBUGF("Container channels != 1, report sample!\n"); + return -1; + } + DEBUGF("MONO\n"); + break; + case STEREO: + if (q->nb_channels != 1) { + q->bits_per_subpacket = q->bits_per_subpacket/2; + } + DEBUGF("STEREO\n"); + break; + case JOINT_STEREO: + if (q->nb_channels != 2) { + DEBUGF("Container channels != 2, report sample!\n"); + return -1; + } + DEBUGF("JOINT_STEREO\n"); + if (q->extradata_size >= 16){ + q->total_subbands = q->subbands + q->js_subband_start; + q->joint_stereo = 1; + } + if (q->samples_per_channel > 256) { + q->log2_numvector_size = 6; + } + if (q->samples_per_channel > 512) { + q->log2_numvector_size = 7; + } + break; + case MC_COOK: + DEBUGF("MC_COOK not supported!\n"); + return -1; + break; + default: + DEBUGF("Unknown Cook version, report sample!\n"); + return -1; + break; + } + + /* Initialize variable relations */ + q->numvector_size = (1 << q->log2_numvector_size); + + /* Generate tables */ + if (init_cook_vlc_tables(q) != 0) + return -1; + + + if(rmctx->block_align >= UINT_MAX/2) + return -1; + + q->gains1.now = q->gain_1; + q->gains1.previous = q->gain_2; + q->gains2.now = q->gain_3; + q->gains2.previous = q->gain_4; + + /* Initialize fixed/floating point routines. */ + if (init_cook_math(q) != 0) + return -1; + + /* Try to catch some obviously faulty streams, othervise it might be exploitable */ + if (q->total_subbands > 53) { + DEBUGF("total_subbands > 53, report sample!\n"); + return -1; + } + if (q->subbands > 50) { + DEBUGF("subbands > 50, report sample!\n"); + return -1; + } + if ((q->samples_per_channel == 256) || (q->samples_per_channel == 512) || (q->samples_per_channel == 1024)) { + } else { + DEBUGF("unknown amount of samples_per_channel = %d, report sample!\n",q->samples_per_channel); + return -1; + } + if ((q->js_vlc_bits > 6) || (q->js_vlc_bits < 0)) { + DEBUGF("q->js_vlc_bits = %d, only >= 0 and <= 6 allowed!\n",q->js_vlc_bits); + return -1; + } + +#ifdef COOKDEBUG + dump_cook_context(q); +#endif + return 0; +} + + Index: Makefile =================================================================== --- Makefile (revision 0) +++ Makefile (revision 0) @@ -0,0 +1,9 @@ +CFLAGS = -Wall -O3 -c +OBJS = main.o bitstream.o cook.o rm2wav.o +CC = gcc +cookfixtest.o: $(OBJS) + gcc -c main.c bitstream.c cook.c rm2wav.c + gcc -o cookfixtest.o $(OBJS) -lm + +clean: + rm -f cookfixtest.o $(OBJS) *~ Index: cook_fixp_mdct.h =================================================================== --- cook_fixp_mdct.h (revision 0) +++ cook_fixp_mdct.h (revision 0) @@ -0,0 +1,545 @@ +/* + * The following (normalized modified discrete cosine transform) + * is taken from the OggVorbis 'TREMOR' source code. + * + * It has been modified for the ffmpeg cook fixed point decoder. + */ + +/******************************************************************** + * * + * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * + * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * + * * + ******************************************************************** + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + - Neither the name of the Xiph.org Foundation nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + ********************************************************************* + + function: normalized modified discrete cosine transform + power of two length transform only [64 <= n ] + last mod: $Id: mdct.c 14281 2004-12-30 12:11:32Z henry $ + + Original algorithm adapted long ago from _The use of multirate filter + banks for coding of high quality digital audio_, by T. Sporer, + K. Brandenburg and B. Edler, collection of the European Signal + Processing Conference (EUSIPCO), Amsterdam, June 1992, Vol.1, pp + 211-214 + + The below code implements an algorithm that no longer looks much like + that presented in the paper, but the basic structure remains if you + dig deep enough to see it. + + This module DOES NOT INCLUDE code to generate/apply the window + function. Everybody has their own weird favorite including me... I + happen to like the properties of y=sin(.5PI*sin^2(x)), but others may + vehemently disagree. + + ********************************************************************/ + +#define STIN static inline + +typedef int32_t ogg_int32_t; + +#define DATA_TYPE ogg_int32_t +#define REG_TYPE register ogg_int32_t +#define LOOKUP_T const uint16_t + +static inline ogg_int32_t MULT32(ogg_int32_t x, ogg_int32_t y) { + return fixp_mult_su(x, y) >> 1; +} + +static inline ogg_int32_t MULT31(ogg_int32_t x, ogg_int32_t y) { + return fixp_mult_su(x, y); +} + +/* + * This should be used as a memory barrier, forcing all cached values in + * registers to wr writen back to memory. Might or might not be beneficial + * depending on the architecture and compiler. + */ +#define MB() + +/* + * The XPROD functions are meant to optimize the cross products found all + * over the place in mdct.c by forcing memory operation ordering to avoid + * unnecessary register reloads as soon as memory is being written to. + * However this is only beneficial on CPUs with a sane number of general + * purpose registers which exclude the Intel x86. On Intel, better let the + * compiler actually reload registers directly from original memory by using + * macros. + */ + +#ifdef __i386__ + +#define XPROD32(_a, _b, _t, _v, _x, _y) \ + { *(_x)=MULT32(_a,_t)+MULT32(_b,_v); \ + *(_y)=MULT32(_b,_t)-MULT32(_a,_v); } +#define XPROD31(_a, _b, _t, _v, _x, _y) \ + { *(_x)=MULT31(_a,_t)+MULT31(_b,_v); \ + *(_y)=MULT31(_b,_t)-MULT31(_a,_v); } +#define XNPROD31(_a, _b, _t, _v, _x, _y) \ + { *(_x)=MULT31(_a,_t)-MULT31(_b,_v); \ + *(_y)=MULT31(_b,_t)+MULT31(_a,_v); } + +#else + +static inline void XPROD32(ogg_int32_t a, ogg_int32_t b, + ogg_int32_t t, ogg_int32_t v, + ogg_int32_t *x, ogg_int32_t *y) +{ + *x = MULT32(a, t) + MULT32(b, v); + *y = MULT32(b, t) - MULT32(a, v); +} + +static inline void XPROD31(ogg_int32_t a, ogg_int32_t b, + ogg_int32_t t, ogg_int32_t v, + ogg_int32_t *x, ogg_int32_t *y) +{ + *x = MULT31(a, t) + MULT31(b, v); + *y = MULT31(b, t) - MULT31(a, v); +} + +static inline void XNPROD31(ogg_int32_t a, ogg_int32_t b, + ogg_int32_t t, ogg_int32_t v, + ogg_int32_t *x, ogg_int32_t *y) +{ + *x = MULT31(a, t) - MULT31(b, v); + *y = MULT31(b, t) + MULT31(a, v); +} + +#endif + + +/* 8 point butterfly (in place) */ +STIN void mdct_butterfly_8(DATA_TYPE *x){ + + REG_TYPE r0 = x[4] + x[0]; + REG_TYPE r1 = x[4] - x[0]; + REG_TYPE r2 = x[5] + x[1]; + REG_TYPE r3 = x[5] - x[1]; + REG_TYPE r4 = x[6] + x[2]; + REG_TYPE r5 = x[6] - x[2]; + REG_TYPE r6 = x[7] + x[3]; + REG_TYPE r7 = x[7] - x[3]; + + x[0] = r5 + r3; + x[1] = r7 - r1; + x[2] = r5 - r3; + x[3] = r7 + r1; + x[4] = r4 - r0; + x[5] = r6 - r2; + x[6] = r4 + r0; + x[7] = r6 + r2; + MB(); +} + +/* 16 point butterfly (in place, 4 register) */ +STIN void mdct_butterfly_16(DATA_TYPE *x){ + + REG_TYPE r0, r1; + + r0 = x[ 0] - x[ 8]; x[ 8] += x[ 0]; + r1 = x[ 1] - x[ 9]; x[ 9] += x[ 1]; + x[ 0] = MULT31((r0 + r1) , cPI2_8); + x[ 1] = MULT31((r1 - r0) , cPI2_8); + MB(); + + r0 = x[10] - x[ 2]; x[10] += x[ 2]; + r1 = x[ 3] - x[11]; x[11] += x[ 3]; + x[ 2] = r1; x[ 3] = r0; + MB(); + + r0 = x[12] - x[ 4]; x[12] += x[ 4]; + r1 = x[13] - x[ 5]; x[13] += x[ 5]; + x[ 4] = MULT31((r0 - r1) , cPI2_8); + x[ 5] = MULT31((r0 + r1) , cPI2_8); + MB(); + + r0 = x[14] - x[ 6]; x[14] += x[ 6]; + r1 = x[15] - x[ 7]; x[15] += x[ 7]; + x[ 6] = r0; x[ 7] = r1; + MB(); + + mdct_butterfly_8(x); + mdct_butterfly_8(x+8); +} + +/* 32 point butterfly (in place, 4 register) */ +STIN void mdct_butterfly_32(DATA_TYPE *x){ + + REG_TYPE r0, r1; + + r0 = x[30] - x[14]; x[30] += x[14]; + r1 = x[31] - x[15]; x[31] += x[15]; + x[14] = r0; x[15] = r1; + MB(); + + r0 = x[28] - x[12]; x[28] += x[12]; + r1 = x[29] - x[13]; x[29] += x[13]; + XNPROD31( r0, r1, cPI1_8, cPI3_8, &x[12], &x[13] ); + MB(); + + r0 = x[26] - x[10]; x[26] += x[10]; + r1 = x[27] - x[11]; x[27] += x[11]; + x[10] = MULT31((r0 - r1) , cPI2_8); + x[11] = MULT31((r0 + r1) , cPI2_8); + MB(); + + r0 = x[24] - x[ 8]; x[24] += x[ 8]; + r1 = x[25] - x[ 9]; x[25] += x[ 9]; + XNPROD31( r0, r1, cPI3_8, cPI1_8, &x[ 8], &x[ 9] ); + MB(); + + r0 = x[22] - x[ 6]; x[22] += x[ 6]; + r1 = x[ 7] - x[23]; x[23] += x[ 7]; + x[ 6] = r1; x[ 7] = r0; + MB(); + + r0 = x[ 4] - x[20]; x[20] += x[ 4]; + r1 = x[ 5] - x[21]; x[21] += x[ 5]; + XPROD31 ( r0, r1, cPI3_8, cPI1_8, &x[ 4], &x[ 5] ); + MB(); + + r0 = x[ 2] - x[18]; x[18] += x[ 2]; + r1 = x[ 3] - x[19]; x[19] += x[ 3]; + x[ 2] = MULT31((r1 + r0) , cPI2_8); + x[ 3] = MULT31((r1 - r0) , cPI2_8); + MB(); + + r0 = x[ 0] - x[16]; x[16] += x[ 0]; + r1 = x[ 1] - x[17]; x[17] += x[ 1]; + XPROD31 ( r0, r1, cPI1_8, cPI3_8, &x[ 0], &x[ 1] ); + MB(); + + mdct_butterfly_16(x); + mdct_butterfly_16(x+16); +} + +/* N/stage point generic N stage butterfly (in place, 2 register) */ +STIN void mdct_butterfly_generic(DATA_TYPE *x,int points,int step){ + + LOOKUP_T *T = sincos_lookup; + DATA_TYPE *x1 = x + points - 8; + DATA_TYPE *x2 = x + (points>>1) - 8; + REG_TYPE r0; + REG_TYPE r1; + + //av_log(0, 0, "bfly: points=%d, step=%d\n", points, step); + + do{ + r0 = x1[6] - x2[6]; x1[6] += x2[6]; + r1 = x2[7] - x1[7]; x1[7] += x2[7]; + XPROD31( r1, r0, T[0], T[1], &x2[6], &x2[7] ); T+=step; + + r0 = x1[4] - x2[4]; x1[4] += x2[4]; + r1 = x2[5] - x1[5]; x1[5] += x2[5]; + XPROD31( r1, r0, T[0], T[1], &x2[4], &x2[5] ); T+=step; + + r0 = x1[2] - x2[2]; x1[2] += x2[2]; + r1 = x2[3] - x1[3]; x1[3] += x2[3]; + XPROD31( r1, r0, T[0], T[1], &x2[2], &x2[3] ); T+=step; + + r0 = x1[0] - x2[0]; x1[0] += x2[0]; + r1 = x2[1] - x1[1]; x1[1] += x2[1]; + XPROD31( r1, r0, T[0], T[1], &x2[0], &x2[1] ); T+=step; + + x1-=8; x2-=8; + }while(Tsincos_lookup); + do{ + r0 = x2[6] - x1[6]; x1[6] += x2[6]; + r1 = x2[7] - x1[7]; x1[7] += x2[7]; + XPROD31( r0, r1, T[0], T[1], &x2[6], &x2[7] ); T+=step; + + r0 = x2[4] - x1[4]; x1[4] += x2[4]; + r1 = x2[5] - x1[5]; x1[5] += x2[5]; + XPROD31( r0, r1, T[0], T[1], &x2[4], &x2[5] ); T+=step; + + r0 = x2[2] - x1[2]; x1[2] += x2[2]; + r1 = x2[3] - x1[3]; x1[3] += x2[3]; + XPROD31( r0, r1, T[0], T[1], &x2[2], &x2[3] ); T+=step; + + r0 = x2[0] - x1[0]; x1[0] += x2[0]; + r1 = x2[1] - x1[1]; x1[1] += x2[1]; + XPROD31( r0, r1, T[0], T[1], &x2[0], &x2[1] ); T+=step; + + x1-=8; x2-=8; + }while(Tsincos_lookup); +} + +STIN void mdct_butterflies(DATA_TYPE *x,int points,int shift){ + + int stages=8-shift; + int i,j; + + for(i=0;--stages>0;i++){ + for(j=0;j<(1<>i)*j,points>>i,8<<(i+shift)); + } + + for(j=0;j>8]|(bitrev[(x&0x0f0)>>4]<<4)|(((int)bitrev[x&0x00f])<<8); +} + +STIN void mdct_bitreverse(DATA_TYPE *x,int n,int step,int shift){ + + int bit = 0; + DATA_TYPE *w0 = x; + DATA_TYPE *w1 = x = w0+(n>>1); + LOOKUP_T *T = sincos_lookup+(step>>1); + LOOKUP_T *Ttop = T+2048; + DATA_TYPE r2; + + //av_log(0, 0, "brev: shift=%d, step=%d\n", shift, step); + + do{ + DATA_TYPE r3 = bitrev12(bit++); + DATA_TYPE *x0 = x + ((r3 ^ 0xfff)>>shift) -1; + DATA_TYPE *x1 = x + (r3>>shift); + + REG_TYPE r0 = x0[0] + x1[0]; + REG_TYPE r1 = x1[1] - x0[1]; + + XPROD32( r0, r1, T[1], T[0], &r2, &r3 ); T+=step; + + w1 -= 4; + + r0 = (x0[1] + x1[1])>>1; + r1 = (x0[0] - x1[0])>>1; + w0[0] = r0 + r2; + w0[1] = r1 + r3; + w1[2] = r0 - r2; + w1[3] = r3 - r1; + + r3 = bitrev12(bit++); + x0 = x + ((r3 ^ 0xfff)>>shift) -1; + x1 = x + (r3>>shift); + + r0 = x0[0] + x1[0]; + r1 = x1[1] - x0[1]; + + XPROD32( r0, r1, T[1], T[0], &r2, &r3 ); T+=step; + + r0 = (x0[1] + x1[1])>>1; + r1 = (x0[0] - x1[0])>>1; + w0[2] = r0 + r2; + w0[3] = r1 + r3; + w1[0] = r0 - r2; + w1[1] = r3 - r1; + + w0 += 4; + }while(T>shift) -1; + DATA_TYPE *x1 = x + (r3>>shift); + + REG_TYPE r0 = x0[0] + x1[0]; + REG_TYPE r1 = x1[1] - x0[1]; + + T-=step; XPROD32( r0, r1, T[0], T[1], &r2, &r3 ); + + w1 -= 4; + + r0 = (x0[1] + x1[1])>>1; + r1 = (x0[0] - x1[0])>>1; + w0[0] = r0 + r2; + w0[1] = r1 + r3; + w1[2] = r0 - r2; + w1[3] = r3 - r1; + + r3 = bitrev12(bit++); + x0 = x + ((r3 ^ 0xfff)>>shift) -1; + x1 = x + (r3>>shift); + + r0 = x0[0] + x1[0]; + r1 = x1[1] - x0[1]; + + T-=step; XPROD32( r0, r1, T[0], T[1], &r2, &r3 ); + + r0 = (x0[1] + x1[1])>>1; + r1 = (x0[0] - x1[0])>>1; + w0[2] = r0 + r2; + w0[3] = r1 + r3; + w1[0] = r0 - r2; + w1[1] = r3 - r1; + + w0 += 4; + }while(w0>1; + int n4=n>>2; + DATA_TYPE *iX; + DATA_TYPE *oX; + LOOKUP_T *T; + int shift; + int step; + + for (shift=6;!(n&(1<=in+n4); + do{ + oX-=4; + XPROD31( iX[4], iX[6], T[1], T[0], &oX[2], &oX[3] ); T-=step; + XPROD31( iX[0], iX[2], T[1], T[0], &oX[0], &oX[1] ); T-=step; + iX-=8; + }while(iX>=in); + + iX = in+n2-8; + oX = out+n2+n4; + T = sincos_lookup; + + do{ + T+=step; XNPROD31( iX[6], iX[4], T[0], T[1], &oX[0], &oX[1] ); + T+=step; XNPROD31( iX[2], iX[0], T[0], T[1], &oX[2], &oX[3] ); + iX-=8; + oX+=4; + }while(iX>=in+n4); + do{ + T-=step; XNPROD31( iX[6], iX[4], T[1], T[0], &oX[0], &oX[1] ); + T-=step; XNPROD31( iX[2], iX[0], T[1], T[0], &oX[2], &oX[3] ); + iX-=8; + oX+=4; + }while(iX>=in); + + mdct_butterflies(out+n2,n2,shift); + mdct_bitreverse(out,n,step,shift); + + /* rotate */ + + step>>=2; + //step=4; + { + DATA_TYPE *oX1=out+n2+n4; + DATA_TYPE *oX2=out+n2+n4; + DATA_TYPE *iX =out; + + T=sincos_lookup+(step>>1); + do{ + oX1-=4; + XPROD31( iX[0], -iX[1], T[0], T[1], &oX1[3], &oX2[0] ); T+=step; + XPROD31( iX[2], -iX[3], T[0], T[1], &oX1[2], &oX2[1] ); T+=step; + XPROD31( iX[4], -iX[5], T[0], T[1], &oX1[1], &oX2[2] ); T+=step; + XPROD31( iX[6], -iX[7], T[0], T[1], &oX1[0], &oX2[3] ); T+=step; + oX2+=4; + iX+=8; + }while(iXoX2); + } +}