From e0f7e3297073e341b43522d67ad717a3d568cd3c Mon Sep 17 00:00:00 2001 From: Benjamin Larsson Date: Fri, 9 Dec 2005 16:08:18 +0000 Subject: [PATCH] Cook compatibe decoder, patch by Benjamin Larsson Add cook demucing, change rm demuxer so that it reorders audio packets before sending them to the decoder, and send minimum decodeable sized packets; pass only real codec extradata fo the decoder Fix 28_8 decoder for the new demuxer strategy Originally committed as revision 4726 to svn://svn.ffmpeg.org/ffmpeg/trunk --- libavcodec/Makefile | 3 + libavcodec/allcodecs.c | 3 + libavcodec/avcodec.h | 6 +- libavcodec/cook.c | 1286 ++++++++++++++++++++++++++++++++++++++++ libavcodec/cookdata.h | 557 +++++++++++++++++ libavcodec/ra288.c | 36 +- libavformat/avformat.h | 4 +- libavformat/rm.c | 111 +++- 8 files changed, 1960 insertions(+), 46 deletions(-) create mode 100644 libavcodec/cook.c create mode 100644 libavcodec/cookdata.h diff --git a/libavcodec/Makefile b/libavcodec/Makefile index cacf074389..ecbca83884 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -32,6 +32,9 @@ endif ifeq ($(CONFIG_CINEPAK_DECODER),yes) OBJS+= cinepak.o endif +ifeq ($(CONFIG_COOK_DECODER),yes) + OBJS+= cook.o +endif ifneq ($(CONFIG_CLJR_DECODER)$(CONFIG_CLJR_ENCODER),) OBJS+= cljr.o endif diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index d7aa1e0a29..c8c37ea5af 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -491,6 +491,9 @@ void avcodec_register_all(void) #ifdef CONFIG_QDM2_DECODER register_avcodec(&qdm2_decoder); #endif //CONFIG_QDM2_DECODER +#ifdef CONFIG_COOK_DECODER + register_avcodec(&cook_decoder); +#endif //CONFIG_COOK_DECODER #ifdef CONFIG_RAWVIDEO_DECODER register_avcodec(&rawvideo_decoder); #endif //CONFIG_RAWVIDEO_DECODER diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index ede77ead48..7cf7f979fb 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -21,8 +21,8 @@ extern "C" { #define AV_STRINGIFY(s) AV_TOSTRING(s) #define AV_TOSTRING(s) #s -#define LIBAVCODEC_VERSION_INT ((50<<16)+(1<<8)+0) -#define LIBAVCODEC_VERSION 50.1.0 +#define LIBAVCODEC_VERSION_INT ((51<<16)+(0<<8)+0) +#define LIBAVCODEC_VERSION 51.0.0 #define LIBAVCODEC_BUILD LIBAVCODEC_VERSION_INT #define LIBAVCODEC_IDENT "Lavc" AV_STRINGIFY(LIBAVCODEC_VERSION) @@ -187,6 +187,7 @@ enum CodecID { CODEC_ID_WESTWOOD_SND1, CODEC_ID_GSM, CODEC_ID_QDM2, + CODEC_ID_COOK, CODEC_ID_OGGTHEORA= 0x16000, @@ -2004,6 +2005,7 @@ extern AVCodec mp3_decoder; extern AVCodec mp3adu_decoder; extern AVCodec mp3on4_decoder; extern AVCodec qdm2_decoder; +extern AVCodec cook_decoder; extern AVCodec mace3_decoder; extern AVCodec mace6_decoder; extern AVCodec huffyuv_decoder; diff --git a/libavcodec/cook.c b/libavcodec/cook.c new file mode 100644 index 0000000000..d479660efb --- /dev/null +++ b/libavcodec/cook.c @@ -0,0 +1,1286 @@ +/* + * COOK compatible decoder + * Copyright (c) 2003 Sascha Sommer + * Copyright (c) 2005 Benjamin Larsson + * + * This library 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 of the License, or (at your option) any later version. + * + * This library 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 this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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. + */ + +#include +#include +#include + +#define ALT_BITSTREAM_READER +#include "avcodec.h" +#include "bitstream.h" +#include "dsputil.h" + +#include "cookdata.h" + +/* the different Cook versions */ +#define MONO_COOK1 0x1000001 +#define MONO_COOK2 0x1000002 +#define JOINT_STEREO 0x1000003 +#define MC_COOK 0x2000000 //multichannel Cook, not supported + +#define SUBBAND_SIZE 20 +//#define COOKDEBUG + +typedef struct { + int size; + int qidx_table1[8]; + int qidx_table2[8]; +} COOKgain; + +typedef struct __attribute__((__packed__)){ + /* codec data start */ + uint32_t cookversion; //in network order, bigendian + uint16_t samples_per_frame; //amount of samples per frame per channel, bigendian + uint16_t subbands; //amount of bands used in the frequency domain, bigendian + /* Mono extradata ends here. */ + uint32_t unused; + uint16_t js_subband_start; //bigendian + uint16_t js_vlc_bits; //bigendian + /* Stereo extradata ends here. */ +} COOKextradata; + + +typedef struct { + GetBitContext gb; + /* stream data */ + int nb_channels; + int joint_stereo; + int bit_rate; + int sample_rate; + int samples_per_channel; + int samples_per_frame; + int subbands; + int numvector_bits; + int numvector_size; //1 << numvector_bits; + int js_subband_start; + int total_subbands; + int num_vectors; + int bits_per_subpacket; + /* states */ + int random_state; + + /* transform data */ + FFTContext fft_ctx; + FFTSample mlt_tmp[1024] __attribute__((aligned(16))); /* temporary storage for imlt */ + float* mlt_window; + float* mlt_precos; + float* mlt_presin; + float* mlt_postcos; + int fft_size; + int fft_order; + int mlt_size; //modulated lapped transform size + + /* gain buffers */ + COOKgain* gain_now_ptr; + COOKgain* gain_previous_ptr; + COOKgain gain_copy; + COOKgain gain_current; + COOKgain gain_now; + COOKgain gain_previous; + + /* VLC data */ + int js_vlc_bits; + VLC envelope_quant_index[13]; + VLC sqvh[7]; //scalar quantization + VLC ccpl; //channel coupling + + /* generatable tables and related variables */ + int gain_size_factor; + float gain_table[23]; + float pow2tab[127]; + float rootpow2tab[127]; + + /* data buffers */ + uint8_t* frame_reorder_buffer; + int* frame_reorder_index; + int frame_reorder_counter; + int frame_reorder_complete; + int frame_reorder_index_size; + + uint8_t* decoded_bytes_buffer; + float mono_mdct_output[2048] __attribute__((aligned(16))); + float* previous_buffer_ptr[2]; + float mono_previous_buffer1[1024]; + float mono_previous_buffer2[1024]; + float* decode_buf_ptr[4]; + float decode_buffer_1[1024]; + float decode_buffer_2[1024]; + float decode_buffer_3[1024]; + float decode_buffer_4[1024]; +} COOKContext; + +/* debug functions */ + +#ifdef COOKDEBUG +static void dump_float_table(float* table, int size, int delimiter) { + int i=0; + av_log(NULL,AV_LOG_ERROR,"\n[%d]: ",i); + for (i=0 ; ipow2tab[63] = 1.0; + for (i=1 ; i<64 ; i++){ + q->pow2tab[63+i]=(float)pow(2.0,(double)i); + q->pow2tab[63-i]=1.0/(float)pow(2.0,(double)i); + } +} + +/* table generator */ +static void init_rootpow2table(COOKContext *q){ + int i; + q->rootpow2tab[63] = 1.0; + for (i=1 ; i<64 ; i++){ + q->rootpow2tab[63+i]=sqrt((float)powf(2.0,(float)i)); + q->rootpow2tab[63-i]=sqrt(1.0/(float)powf(2.0,(float)i)); + } +} + +/* table generator */ +static void init_gain_table(COOKContext *q) { + int i; + q->gain_size_factor = q->samples_per_channel/8; + for (i=0 ; i<23 ; i++) { + q->gain_table[i] = pow((double)q->pow2tab[i+52] , + (1.0/(double)q->gain_size_factor)); + } + memset(&q->gain_copy, 0, sizeof(COOKgain)); + memset(&q->gain_current, 0, sizeof(COOKgain)); + memset(&q->gain_now, 0, sizeof(COOKgain)); + memset(&q->gain_previous, 0, sizeof(COOKgain)); +} + + +static int init_cook_vlc_tables(COOKContext *q) { + int i, result; + + result = 0; + for (i=0 ; i<13 ; i++) { + 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); + } + av_log(NULL,AV_LOG_DEBUG,"sqvh VLC init\n"); + for (i=0 ; i<7 ; i++) { + 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){ + 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); + av_log(NULL,AV_LOG_DEBUG,"Joint-stereo VLC used.\n"); + } + + av_log(NULL,AV_LOG_DEBUG,"VLC tables initialized.\n"); + return result; +} + +static int init_cook_mlt(COOKContext *q) { + int j; + float alpha; + + /* Allocate the buffers, could be replaced with a static [512] + array if needed. */ + q->mlt_size = q->samples_per_channel; + q->mlt_window = av_malloc(sizeof(float)*q->mlt_size); + q->mlt_precos = av_malloc(sizeof(float)*q->mlt_size/2); + q->mlt_presin = av_malloc(sizeof(float)*q->mlt_size/2); + q->mlt_postcos = av_malloc(sizeof(float)*q->mlt_size/2); + + /* Initialize the MLT window: simple sine window. */ + alpha = M_PI / (2.0 * (float)q->mlt_size); + for(j=0 ; jmlt_size ; j++) { + q->mlt_window[j] = sin((j + 512.0/(float)q->mlt_size) * alpha); + } + + /* pre/post twiddle factors */ + for (j=0 ; jmlt_size/2 ; j++){ + q->mlt_precos[j] = cos( ((j+0.25)*M_PI)/q->mlt_size); + q->mlt_presin[j] = sin( ((j+0.25)*M_PI)/q->mlt_size); + q->mlt_postcos[j] = (float)sqrt(2.0/(float)q->mlt_size)*cos( ((float)j*M_PI) /q->mlt_size); //sqrt(2/MLT_size) = scalefactor + } + + /* Initialize the FFT. */ + ff_fft_init(&q->fft_ctx, av_log2(q->mlt_size)-1, 0); + av_log(NULL,AV_LOG_DEBUG,"FFT initialized, order = %d.\n", + av_log2(q->samples_per_channel)-1); + + return (int)(q->mlt_window && q->mlt_precos && q->mlt_presin && q->mlt_postcos); +} + +/*************** init functions end ***********/ + +/** + * Cook indata decoding, every 32 bits are XORed with 0x37c511f2. + * Why? No idea, some checksum/error detection method maybe. + * Nice way to waste CPU cycles. + * + * @param in pointer to 32bit array of indata + * @param bits amount of bits + * @param out pointer to 32bit array of outdata + */ + +static inline void decode_bytes(uint8_t* inbuffer, uint8_t* out, int bytes){ + int i; + uint32_t* buf = (uint32_t*) inbuffer; + 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 ; ipriv_data; + av_log(NULL,AV_LOG_DEBUG, "Deallocating memory.\n"); + + /* Free allocated memory buffers. */ + av_free(q->mlt_window); + av_free(q->mlt_precos); + av_free(q->mlt_presin); + av_free(q->mlt_postcos); + av_free(q->frame_reorder_index); + av_free(q->frame_reorder_buffer); + av_free(q->decoded_bytes_buffer); + + /* Free the transform. */ + ff_fft_end(&q->fft_ctx); + + /* 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); + } + + av_log(NULL,AV_LOG_DEBUG,"Memory deallocated.\n"); + + return 0; +} + +/** + * Fill the COOKgain structure for the timedomain quantization. + * + * @param q pointer to the COOKContext + * @param gaininfo pointer to the COOKgain + */ + +static void decode_gain_info(GetBitContext *gb, COOKgain* gaininfo) { + int i; + + while (get_bits1(gb)) {} + + gaininfo->size = get_bits_count(gb) - 1; //amount of elements*2 to update + + if (get_bits_count(gb) - 1 <= 0) return; + + for (i=0 ; isize ; i++){ + gaininfo->qidx_table1[i] = get_bits(gb,3); + if (get_bits1(gb)) { + gaininfo->qidx_table2[i] = get_bits(gb,4) - 7; //convert to signed + } else { + gaininfo->qidx_table2[i] = -1; + } + } +} + +/** + * 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 + } +} + +/** + * Create the quant value table. + * + * @param q pointer to the COOKContext + * @param quant_value_table pointer to the array + */ + +static void inline dequant_envelope(COOKContext *q, int* quant_index_table, + float* quant_value_table){ + + int i; + for(i=0 ; i < q->total_subbands ; i++){ + quant_value_table[i] = q->rootpow2tab[quant_index_table[i]+63]; + } +} + +/** + * 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; + //av_log(NULL, AV_LOG_ERROR, "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]]; + } +} + +/** + * The real requantization of the mltcoefs + * + * @param q pointer to the COOKContext + * @param index index + * @param band current subband + * @param quant_value_table pointer to the array + * @param subband_coef_index array of indexes to quant_centroid_tab + * @param subband_coef_noise use random noise instead of predetermined value + * @param mlt_buffer pointer to the mlt buffer + */ + + +static void scalar_dequant(COOKContext *q, int index, int band, + float* quant_value_table, int* subband_coef_index, + int* subband_coef_noise, float* mlt_buffer){ + int i; + float f1; + + for(i=0 ; irandom_state = q->random_state * 214013 + 2531011; //typical RNG numbers + f1 = randsign[(q->random_state/0x1000000)&1] * dither_tab[index]; //>>31 + } + mlt_buffer[band*20+ i] = f1 * quant_value_table[band]; + } +} +/** + * Unpack the subband_coef_index and subband_coef_noise 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_noise use random noise instead of predetermined value + */ + +static int unpack_SQVH(COOKContext *q, int category, int* subband_coef_index, + int* subband_coef_noise) { + 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_noise[i*vd+j] = get_bits1(&q->gb); + } else { + result=1; + subband_coef_noise[i*vd+j]=0; + } + } else { + subband_coef_noise[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_value_table pointer to the array + * @param mlt_buffer pointer to mlt coefficients + */ + + +static void decode_vectors(COOKContext* q, int* category, + float* quant_value_table, float* mlt_buffer){ + /* A zero in this table means that the subband coefficient is + random noise coded. */ + int subband_coef_noise[SUBBAND_SIZE]; + /* A zero in this table means that the subband coefficient is a + positive multiplicator. */ + int subband_coef_index[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_noise)){ + 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_noise, 0, sizeof(subband_coef_noise)); + } + scalar_dequant(q, index, band, quant_value_table, subband_coef_index, + subband_coef_noise, mlt_buffer); + } + + if(q->total_subbands*SUBBAND_SIZE >= q->samples_per_channel){ + return; + } +} + + +/** + * 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, float* mlt_buffer) { + + int category_index[128]; + float quant_value_table[102]; + int quant_index_table[102]; + int category[128]; + + memset(&category, 0, 128*sizeof(int)); + memset(&quant_value_table, 0, 102*sizeof(int)); + memset(&category_index, 0, 128*sizeof(int)); + + decode_envelope(q, quant_index_table); + q->num_vectors = get_bits(&q->gb,q->numvector_bits); + dequant_envelope(q, quant_index_table, quant_value_table); + categorize(q, quant_index_table, category, category_index); + expand_category(q, category, category_index); + decode_vectors(q, category, quant_value_table, mlt_buffer); +} + + +/** + * The modulated lapped transform, this takes transform coefficients + * and transforms them into timedomain samples. This is done through + * an FFT-based algorithm with pre- and postrotation steps. + * A window and reorder 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 + */ + +static void cook_imlt(COOKContext *q, float* inbuffer, float* outbuffer, + float* mlt_tmp){ + int i; + + /* prerotation */ + for(i=0 ; imlt_size ; i+=2){ + outbuffer[i] = (q->mlt_presin[i/2] * inbuffer[q->mlt_size-1-i]) + + (q->mlt_precos[i/2] * inbuffer[i]); + outbuffer[i+1] = (q->mlt_precos[i/2] * inbuffer[q->mlt_size-1-i]) - + (q->mlt_presin[i/2] * inbuffer[i]); + } + + /* FFT */ + ff_fft_permute(&q->fft_ctx, (FFTComplex *) outbuffer); + ff_fft_calc (&q->fft_ctx, (FFTComplex *) outbuffer); + + /* postrotation */ + for(i=0 ; imlt_size ; i+=2){ + mlt_tmp[i] = (q->mlt_postcos[(q->mlt_size-1-i)/2] * outbuffer[i+1]) + + (q->mlt_postcos[i/2] * outbuffer[i]); + mlt_tmp[q->mlt_size-1-i] = (q->mlt_postcos[(q->mlt_size-1-i)/2] * outbuffer[i]) - + (q->mlt_postcos[i/2] * outbuffer[i+1]); + } + + /* window and reorder */ + for(i=0 ; imlt_size/2 ; i++){ + outbuffer[i] = mlt_tmp[q->mlt_size/2-1-i] * q->mlt_window[i]; + outbuffer[q->mlt_size-1-i]= mlt_tmp[q->mlt_size/2-1-i] * + q->mlt_window[q->mlt_size-1-i]; + outbuffer[q->mlt_size+i]= mlt_tmp[q->mlt_size/2+i] * + q->mlt_window[q->mlt_size-1-i]; + outbuffer[2*q->mlt_size-1-i]= -(mlt_tmp[q->mlt_size/2+i] * + q->mlt_window[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 void interpolate(COOKContext *q, float* buffer, + int gain_index, int gain_index_next){ + int i; + float fc1, fc2; + fc1 = q->pow2tab[gain_index+63]; + + if(gain_index == gain_index_next){ //static gain + for(i=0 ; igain_size_factor ; i++){ + buffer[i]*=fc1; + } + return; + } else { //smooth gain + fc2 = q->gain_table[11 + (gain_index_next-gain_index)]; + for(i=0 ; igain_size_factor ; i++){ + buffer[i]*=fc1; + fc1*=fc2; + } + return; + } +} + +/** + * timedomain requantization of the timedomain samples + * + * @param q pointer to the COOKContext + * @param buffer pointer to the timedomain buffer + * @param gain_now current gain structure + * @param gain_previous previous gain structure + */ + +static void gain_window(COOKContext *q, float* buffer, COOKgain* gain_now, + COOKgain* gain_previous){ + int i, index; + int gain_index[9]; + int tmp_gain_index; + + gain_index[8]=0; + index = gain_previous->size; + for (i=7 ; i>=0 ; i--) { + if(index && gain_previous->qidx_table1[index-1]==i) { + gain_index[i] = gain_previous->qidx_table2[index-1]; + index--; + } else { + gain_index[i]=gain_index[i+1]; + } + } + /* This is applied to the to be previous data buffer. */ + for(i=0;i<8;i++){ + interpolate(q, &buffer[q->samples_per_channel+q->gain_size_factor*i], + gain_index[i], gain_index[i+1]); + } + + tmp_gain_index = gain_index[0]; + index = gain_now->size; + for (i=7 ; i>=0 ; i--) { + if(index && gain_now->qidx_table1[index-1]==i) { + gain_index[i]= gain_now->qidx_table2[index-1]; + index--; + } else { + gain_index[i]=gain_index[i+1]; + } + } + + /* This is applied to the to be current block. */ + for(i=0;i<8;i++){ + interpolate(q, &buffer[i*q->gain_size_factor], + tmp_gain_index+gain_index[i], + tmp_gain_index+gain_index[i+1]); + } +} + + +/** + * mlt overlapping and buffer management + * + * @param q pointer to the COOKContext + * @param buffer pointer to the timedomain buffer + * @param gain_now current gain structure + * @param gain_previous previous gain structure + * @param previous_buffer pointer to the previous buffer to be used for overlapping + * + */ + +static void gain_compensate(COOKContext *q, float* buffer, COOKgain* gain_now, + COOKgain* gain_previous, float* previous_buffer) { + int i; + if((gain_now->size || gain_previous->size)) { + gain_window(q, buffer, gain_now, gain_previous); + } + + /* Overlap with the previous block. */ + for(i=0 ; isamples_per_channel ; i++) buffer[i]+=previous_buffer[i]; + + /* Save away the current to be previous block. */ + memcpy(previous_buffer, buffer+q->samples_per_channel, + sizeof(float)*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, float* mlt_buffer1, + float* mlt_buffer2) { + int i,j; + int decouple_tab[SUBBAND_SIZE]; + float decode_buffer[2048]; //Only 1060 might be needed. + int idx, cpl_tmp,tmp_idx; + float f1,f2; + float* cplscale; + + 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(float)); + memset(mlt_buffer2,0, 1024*sizeof(float)); + 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; + if (q->js_subband_start < q->subbands) { + for (i=0 ; isubbands ; i++) { + cpl_tmp = cplband[i + q->js_subband_start]; + idx -=decouple_tab[cpl_tmp]; + cplscale = (float*)cplscales[q->js_vlc_bits-2]; //choose decoupler table + f1 = cplscale[decouple_tab[cpl_tmp]]; + f2 = cplscale[idx-1]; + for (j=0 ; jjs_subband_start + i)*20)+j; + mlt_buffer1[20*(i+q->js_subband_start) + j] = f1 * decode_buffer[tmp_idx]; + mlt_buffer2[20*(i+q->js_subband_start) + j] = f2 * decode_buffer[tmp_idx]; + } + idx = (1 << q->js_vlc_bits) - 1; + } + } +} + +/** + * 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 + * @param pos the subpacket number in the frame + */ + + +static int decode_subpacket(COOKContext *q, uint8_t *inbuffer, + int sub_packet_size, int16_t *outbuffer) { + int i,j; + int value; + float* tmp_ptr; + + /* packet dump */ +// for (i=0 ; idecoded_bytes_buffer, sub_packet_size); + init_get_bits(&q->gb, q->decoded_bytes_buffer, sub_packet_size*8); + decode_gain_info(&q->gb, &q->gain_current); + memcpy(&q->gain_copy, &q->gain_current ,sizeof(COOKgain)); //This copy does not seem to be used. FIXME + //fprintf(stdout,"cu bits ds = %d\n",get_bits_count(&q->gb)); + if(q->nb_channels==2 && q->joint_stereo==1){ + joint_decode(q, q->decode_buf_ptr[0], q->decode_buf_ptr[2]); + + /* Swap buffer pointers. */ + tmp_ptr = q->decode_buf_ptr[1]; + q->decode_buf_ptr[1] = q->decode_buf_ptr[0]; + q->decode_buf_ptr[0] = tmp_ptr; + tmp_ptr = q->decode_buf_ptr[3]; + q->decode_buf_ptr[3] = q->decode_buf_ptr[2]; + q->decode_buf_ptr[2] = tmp_ptr; + + /* FIXME: Rethink the gainbuffer handling, maybe a rename? + now/previous swap */ + q->gain_now_ptr = &q->gain_now; + q->gain_previous_ptr = &q->gain_previous; + for (i=0 ; inb_channels ; i++){ + + cook_imlt(q, q->decode_buf_ptr[i*2], q->mono_mdct_output, q->mlt_tmp); + gain_compensate(q, q->mono_mdct_output, q->gain_now_ptr, + q->gain_previous_ptr, q->previous_buffer_ptr[0]); + + /* Swap out the previous buffer. */ + tmp_ptr = q->previous_buffer_ptr[0]; + q->previous_buffer_ptr[0] = q->previous_buffer_ptr[1]; + q->previous_buffer_ptr[1] = tmp_ptr; + + /* Clip and convert the floats to 16 bits. */ + for (j=0 ; jsamples_per_frame ; j++){ + value = lrintf(q->mono_mdct_output[j]); + if(value < -32768) value = -32768; + else if(value > 32767) value = 32767; + outbuffer[2*j+i] = value; + } + } + + memcpy(&q->gain_now, &q->gain_previous, sizeof(COOKgain)); + memcpy(&q->gain_previous, &q->gain_current, sizeof(COOKgain)); + + } else if (q->nb_channels==2 && q->joint_stereo==0) { + for (i=0 ; inb_channels ; i++){ + mono_decode(q, q->decode_buf_ptr[0]); + + av_log(NULL,AV_LOG_ERROR,"Non-joint-stereo files are not supported at the moment, do not report as a bug!\n"); + tmp_ptr = q->decode_buf_ptr[0]; + q->decode_buf_ptr[0] = q->decode_buf_ptr[1]; + q->decode_buf_ptr[1] = q->decode_buf_ptr[2]; + q->decode_buf_ptr[2] = q->decode_buf_ptr[3]; + q->decode_buf_ptr[3] = tmp_ptr; + + q->gain_now_ptr = &q->gain_now; + q->gain_previous_ptr = &q->gain_previous; + + cook_imlt(q, q->decode_buf_ptr[0], q->mono_mdct_output,q->mlt_tmp); + gain_compensate(q, q->mono_mdct_output, q->gain_now_ptr, + q->gain_previous_ptr, q->previous_buffer_ptr[0]); + /* Swap out the previous buffer. */ + tmp_ptr = q->previous_buffer_ptr[0]; + q->previous_buffer_ptr[0] = q->previous_buffer_ptr[1]; + q->previous_buffer_ptr[1] = tmp_ptr; + + for (j=0 ; jsamples_per_frame ; j++){ + value = lrintf(q->mono_mdct_output[j]); + if(value < -32768) value = -32768; + else if(value > 32767) value = 32767; + outbuffer[2*j+i] = value; + } + memcpy(&q->gain_now, &q->gain_previous, sizeof(COOKgain)); + memcpy(&q->gain_previous, &q->gain_current, sizeof(COOKgain)); + } + } else { + mono_decode(q, q->decode_buf_ptr[0]); + + /* Swap buffer pointers. */ + tmp_ptr = q->decode_buf_ptr[1]; + q->decode_buf_ptr[1] = q->decode_buf_ptr[0]; + q->decode_buf_ptr[0] = tmp_ptr; + + /* FIXME: Rethink the gainbuffer handling, maybe a rename? + now/previous swap */ + q->gain_now_ptr = &q->gain_now; + q->gain_previous_ptr = &q->gain_previous; + + cook_imlt(q, q->decode_buf_ptr[0], q->mono_mdct_output,q->mlt_tmp); + gain_compensate(q, q->mono_mdct_output, q->gain_now_ptr, + q->gain_previous_ptr, q->mono_previous_buffer1); + + /* Clip and convert the floats to 16 bits */ + for (j=0 ; jsamples_per_frame ; j++){ + value = lrintf(q->mono_mdct_output[j]); + if(value < -32768) value = -32768; + else if(value > 32767) value = 32767; + outbuffer[j] = value; + } + memcpy(&q->gain_now, &q->gain_previous, sizeof(COOKgain)); + memcpy(&q->gain_previous, &q->gain_current, sizeof(COOKgain)); + } + /* FIXME: Shouldn't the total number of bytes be returned? */ + return /*q->nb_channels*/ q->samples_per_frame * sizeof(int16_t); +} + + +/** + * Cook frame decoding + * + * @param avctx pointer to the AVCodecContext + */ + +static int cook_decode_frame(AVCodecContext *avctx, + void *data, int *data_size, + uint8_t *buf, int buf_size) { + /* This stuff is quite messy, the Cook packets are sent unordered + * and need to be ordered before they are sent to the rest of the + * decoder. The order can be found in the q->frame_reorder_index. + * Currently decoding of the last packets is not handled at + * all. FIXME */ + + COOKContext *q = avctx->priv_data; + + if (buf_size < avctx->block_align) + return buf_size; + + *data_size = decode_subpacket(q, buf, avctx->block_align, data); + + return avctx->block_align; +} +#ifdef COOKDEBUG +static void dump_cook_context(COOKContext *q, COOKextradata *e) +{ + //int i=0; +#define PRINT(a,b) av_log(NULL,AV_LOG_ERROR," %s = %d\n", a, b); + av_log(NULL,AV_LOG_ERROR,"COOKextradata\n"); + av_log(NULL,AV_LOG_ERROR,"cookversion=%x\n",e->cookversion); + if (e->cookversion > MONO_COOK2) { + PRINT("js_subband_start",e->js_subband_start); + PRINT("js_vlc_bits",e->js_vlc_bits); + } + av_log(NULL,AV_LOG_ERROR,"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("mlt_size",q->mlt_size); + PRINT("js_subband_start",q->js_subband_start); + PRINT("numvector_bits",q->numvector_bits); + PRINT("numvector_size",q->numvector_size); + PRINT("total_subbands",q->total_subbands); + PRINT("frame_reorder_counter",q->frame_reorder_counter); + PRINT("frame_reorder_index_size",q->frame_reorder_index_size); +} +#endif +/** + * Cook initialization + * + * @param avctx pointer to the AVCodecContext + */ + +static int cook_decode_init(AVCodecContext *avctx) +{ + COOKextradata *e = avctx->extradata; + COOKContext *q = avctx->priv_data; + + /* Take care of the codec specific extradata. */ + if (avctx->extradata_size <= 0) { + av_log(NULL,AV_LOG_ERROR,"Necessary extradata missing!\n"); + return -1; + } else { + /* 8 for mono, 16 for stereo, ? for multichannel + Swap to right endianness so we don't need to care later on. */ + av_log(NULL,AV_LOG_DEBUG,"codecdata_length=%d\n",avctx->extradata_size); + if (avctx->extradata_size >= 8){ + e->cookversion = be2me_32(e->cookversion); + e->samples_per_frame = be2me_16(e->samples_per_frame); + e->subbands = be2me_16(e->subbands); + } + if (avctx->extradata_size >= 16){ + e->js_subband_start = be2me_16(e->js_subband_start); + e->js_vlc_bits = be2me_16(e->js_vlc_bits); + } + } + + /* Take data from the AVCodecContext (RM container). */ + q->sample_rate = avctx->sample_rate; + q->nb_channels = avctx->channels; + q->bit_rate = avctx->bit_rate; + + /* Initialize state. */ + q->random_state = 1; + + /* Initialize extradata related variables. */ + q->samples_per_channel = e->samples_per_frame / q->nb_channels; + q->samples_per_frame = e->samples_per_frame; + q->subbands = e->subbands; + q->bits_per_subpacket = avctx->block_align * 8; + + /* Initialize default data states. */ + q->js_subband_start = 0; + q->numvector_bits = 5; + q->total_subbands = q->subbands; + + /* Initialize version-dependent variables */ + av_log(NULL,AV_LOG_DEBUG,"e->cookversion=%x\n",e->cookversion); + switch (e->cookversion) { + case MONO_COOK1: + if (q->nb_channels != 1) { + av_log(NULL,AV_LOG_ERROR,"Container channels != 1, report sample!\n"); + return -1; + } + av_log(NULL,AV_LOG_DEBUG,"MONO_COOK1\n"); + break; + case MONO_COOK2: + if (q->nb_channels != 1) { + q->joint_stereo = 0; + av_log(NULL,AV_LOG_ERROR,"Non-joint-stereo files are not supported at the moment!\n"); + return -1; + } + av_log(NULL,AV_LOG_DEBUG,"MONO_COOK2\n"); + break; + case JOINT_STEREO: + if (q->nb_channels != 2) { + av_log(NULL,AV_LOG_ERROR,"Container channels != 2, report sample!\n"); + return -1; + } + av_log(NULL,AV_LOG_DEBUG,"JOINT_STEREO\n"); + if (avctx->extradata_size >= 16){ + q->total_subbands = q->subbands + e->js_subband_start; + q->js_subband_start = e->js_subband_start; + q->joint_stereo = 1; + q->js_vlc_bits = e->js_vlc_bits; + } + if (q->samples_per_channel > 256) { + q->numvector_bits++; // q->numvector_bits = 6 + } + if (q->samples_per_channel > 512) { + q->numvector_bits++; // q->numvector_bits = 7 + } + break; + case MC_COOK: + av_log(NULL,AV_LOG_ERROR,"MC_COOK not supported!\n"); + return -1; + break; + default: + av_log(NULL,AV_LOG_ERROR,"Unknown Cook version, report sample!\n"); + return -1; + break; + } + + /* Initialize variable relations */ + q->mlt_size = q->samples_per_channel; + q->numvector_size = (1 << q->numvector_bits); + + /* Generate tables */ + init_rootpow2table(q); + init_pow2table(q); + init_gain_table(q); + + if (init_cook_vlc_tables(q) != 0) + return -1; + + /* Pad the databuffer with FF_INPUT_BUFFER_PADDING_SIZE, + this is for the bitstreamreader. */ + if ((q->decoded_bytes_buffer = av_mallocz((avctx->block_align+(4-avctx->block_align%4) + FF_INPUT_BUFFER_PADDING_SIZE)*sizeof(uint8_t))) == NULL) + return -1; + + q->decode_buf_ptr[0] = q->decode_buffer_1; + q->decode_buf_ptr[1] = q->decode_buffer_2; + q->decode_buf_ptr[2] = q->decode_buffer_3; + q->decode_buf_ptr[3] = q->decode_buffer_4; + + q->previous_buffer_ptr[0] = q->mono_previous_buffer1; + q->previous_buffer_ptr[1] = q->mono_previous_buffer2; + + memset(q->decode_buffer_1,0,1024*sizeof(float)); + memset(q->decode_buffer_2,0,1024*sizeof(float)); + memset(q->decode_buffer_3,0,1024*sizeof(float)); + memset(q->decode_buffer_4,0,1024*sizeof(float)); + + /* Initialize transform. */ + if ( init_cook_mlt(q) == 0 ) + return -1; + + //dump_cook_context(q,e); + return 0; +} + + +AVCodec cook_decoder = +{ + .name = "cook", + .type = CODEC_TYPE_AUDIO, + .id = CODEC_ID_COOK, + .priv_data_size = sizeof(COOKContext), + .init = cook_decode_init, + .close = cook_decode_close, + .decode = cook_decode_frame, +}; diff --git a/libavcodec/cookdata.h b/libavcodec/cookdata.h new file mode 100644 index 0000000000..04b8000446 --- /dev/null +++ b/libavcodec/cookdata.h @@ -0,0 +1,557 @@ +/* + * COOK compatible decoder data + * Copyright (c) 2003 Sascha Sommer + * Copyright (c) 2005 Benjamin Larsson + * + * This library 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 of the License, or (at your option) any later version. + * + * This library 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 this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 float dither_tab[8] = { + 0.0, 0.0, 0.0, 0.0, 0.0, 0.176777, 0.25, 0.707107, +}; + +static const float randsign[2] = {1.0, -1.0}; + +static const float quant_centroid_tab[7][14] = { + { 0.000, 0.392, 0.761, 1.120, 1.477, 1.832, 2.183, 2.541, 2.893, 3.245, 3.598, 3.942, 4.288, 4.724 }, + { 0.000, 0.544, 1.060, 1.563, 2.068, 2.571, 3.072, 3.562, 4.070, 4.620, 0.000, 0.000, 0.000, 0.000 }, + { 0.000, 0.746, 1.464, 2.180, 2.882, 3.584, 4.316, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000 }, + { 0.000, 1.006, 2.000, 2.993, 3.985, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000 }, + { 0.000, 1.321, 2.703, 3.983, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000 }, + { 0.000, 1.657, 3.491, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000 }, + { 0.000, 1.964, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000 } +}; + +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, +}; + +static const float cplscale2[3] = { +0.953020632266998,0.70710676908493,0.302905440330505, +}; + +static const float cplscale3[7] = { +0.981279790401459,0.936997592449188,0.875934481620789,0.70710676908493, +0.482430040836334,0.349335819482803,0.192587479948997, +}; + +static const float cplscale4[15] = { +0.991486728191376,0.973249018192291,0.953020632266998,0.930133521556854, +0.903453230857849,0.870746195316315,0.826180458068848,0.70710676908493, +0.563405573368073,0.491732746362686,0.428686618804932,0.367221474647522, +0.302905440330505,0.229752898216248,0.130207896232605, +}; + +static const float cplscale5[31] = { +0.995926380157471,0.987517595291138,0.978726446628571,0.969505727291107, +0.95979779958725,0.949531257152557,0.938616216182709,0.926936149597168, +0.914336204528809,0.900602877140045,0.885426938533783,0.868331849575043, +0.84851086139679,0.824381768703461,0.791833400726318,0.70710676908493, +0.610737144947052,0.566034197807312,0.529177963733673,0.495983630418777, +0.464778542518616,0.434642940759659,0.404955863952637,0.375219136476517, +0.344963222742081,0.313672333955765,0.280692428350449,0.245068684220314, +0.205169528722763,0.157508864998817,0.0901700109243393, +}; + +static const float cplscale6[63] = { +0.998005926609039,0.993956744670868,0.989822506904602,0.985598564147949, +0.981279790401459,0.976860702037811,0.972335040569305,0.967696130275726, +0.962936460971832,0.958047747612000,0.953020632266998,0.947844684123993, +0.942508161067963,0.936997592449188,0.931297719478607,0.925390899181366, +0.919256627559662,0.912870943546295,0.906205296516418,0.899225592613220, +0.891890347003937,0.884148240089417,0.875934481620789,0.867165684700012, +0.857730865478516,0.847477376461029,0.836184680461884,0.823513329029083, +0.808890223503113,0.791194140911102,0.767520070075989,0.707106769084930, +0.641024887561798,0.611565053462982,0.587959706783295,0.567296981811523, +0.548448026180267,0.530831515789032,0.514098942279816,0.498019754886627, +0.482430040836334,0.467206478118896,0.452251672744751,0.437485188245773, +0.422837972640991,0.408248275518417,0.393658757209778,0.379014074802399, +0.364258885383606,0.349335819482803,0.334183186292648,0.318732559680939, +0.302905440330505,0.286608695983887,0.269728302955627,0.252119421958923, +0.233590632677078,0.213876649737358,0.192587479948997,0.169101938605309, +0.142307326197624,0.109772264957428,0.0631198287010193, +}; + +static const float* cplscales[5] = { + cplscale2, cplscale3, cplscale4, cplscale5, cplscale6, +}; diff --git a/libavcodec/ra288.c b/libavcodec/ra288.c index 4cff3106e5..9082920346 100644 --- a/libavcodec/ra288.c +++ b/libavcodec/ra288.c @@ -228,41 +228,19 @@ static int ra288_decode_frame(AVCodecContext * avctx, void *data, int *data_size, uint8_t * buf, int buf_size) { - if(avctx->extradata_size>=6) - { -//((short*)(avctx->extradata))[0]; /* subpacket size */ -//((short*)(avctx->extradata))[1]; /* subpacket height */ -//((short*)(avctx->extradata))[2]; /* subpacket flavour */ -//((short*)(avctx->extradata))[3]; /* coded frame size */ -//((short*)(avctx->extradata))[4]; /* codec's data length */ -//((short*)(avctx->extradata))[5...] /* codec's data */ - int bret; void *datao; - int w=avctx->block_align; /* 228 */ - int h=((short*)(avctx->extradata))[1]; /* 12 */ - int cfs=((short*)(avctx->extradata))[3]; /* coded frame size 38 */ - int i,j; - if(buf_sizeblock_align) { - av_log(avctx, AV_LOG_ERROR, "ffra288: Error! Input buffer is too small [%d<%d]\n",buf_size,w*h); + av_log(avctx, AV_LOG_ERROR, "ffra288: Error! Input buffer is too small [%d<%d]\n",buf_size,avctx->block_align); return 0; } + datao = data; - bret = 0; - for (j = 0; j < h/2; j++) - for (i = 0; i < h; i++) - { - data=decode_block(avctx,&buf[j*cfs+cfs*i*h/2],(signed short *)data,cfs); - bret += cfs; - } + data = decode_block(avctx, buf, (signed short *)data, avctx->block_align); + *data_size = (char *)data - (char *)datao; - return bret; - } - else - { - av_log(avctx, AV_LOG_ERROR, "ffra288: Error: need extra data!!!\n"); - return 0; - } + return avctx->block_align; } AVCodec ra_288_decoder = diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 8767e0b1fb..b3c055694e 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -5,8 +5,8 @@ extern "C" { #endif -#define LIBAVFORMAT_VERSION_INT ((49<<16)+(2<<8)+0) -#define LIBAVFORMAT_VERSION 49.2.0 +#define LIBAVFORMAT_VERSION_INT ((50<<16)+(0<<8)+0) +#define LIBAVFORMAT_VERSION 50.0.0 #define LIBAVFORMAT_BUILD LIBAVFORMAT_VERSION_INT #define LIBAVFORMAT_IDENT "Lavf" AV_STRINGIFY(LIBAVFORMAT_VERSION) diff --git a/libavformat/rm.c b/libavformat/rm.c index 683fcc9580..b8ef354353 100644 --- a/libavformat/rm.c +++ b/libavformat/rm.c @@ -42,6 +42,14 @@ typedef struct { int old_format; int current_stream; int remaining_len; + /// Audio descrambling matrix parameters + uint8_t *audiobuf; ///< place to store reordered audio data + int64_t audiotimestamp; ///< Audio packet timestamp + int sub_packet_cnt; // Subpacket counter, used while reading + int sub_packet_size, sub_packet_h, coded_framesize; ///< Descrambling parameters from container + int audio_stream_num; ///< Stream number for audio packets + int audio_pkt_cnt; ///< Output packet counter + int audio_framesize; /// Audio frame size from container } RMContext; #ifdef CONFIG_MUXERS @@ -478,6 +486,7 @@ static void get_str8(ByteIOContext *pb, char *buf, int buf_size) static void rm_read_audio_stream_info(AVFormatContext *s, AVStream *st, int read_all) { + RMContext *rm = s->priv_data; ByteIOContext *pb = &s->pb; char buf[128]; uint32_t version; @@ -500,39 +509,60 @@ static void rm_read_audio_stream_info(AVFormatContext *s, AVStream *st, st->codec->codec_type = CODEC_TYPE_AUDIO; st->codec->codec_id = CODEC_ID_RA_144; } else { - int flavor, sub_packet_h, coded_framesize; + int flavor, sub_packet_h, coded_framesize, sub_packet_size; /* old version (4) */ get_be32(pb); /* .ra4 */ get_be32(pb); /* data size */ get_be16(pb); /* version2 */ get_be32(pb); /* header size */ flavor= get_be16(pb); /* add codec info / flavor */ - coded_framesize= get_be32(pb); /* coded frame size */ + rm->coded_framesize = coded_framesize = get_be32(pb); /* coded frame size */ get_be32(pb); /* ??? */ get_be32(pb); /* ??? */ get_be32(pb); /* ??? */ - sub_packet_h= get_be16(pb); /* 1 */ + rm->sub_packet_h = sub_packet_h = get_be16(pb); /* 1 */ st->codec->block_align= get_be16(pb); /* frame size */ - get_be16(pb); /* sub packet size */ + rm->sub_packet_size = sub_packet_size = get_be16(pb); /* sub packet size */ get_be16(pb); /* ??? */ + if (((version >> 16) & 0xff) == 5) { + get_be16(pb); get_be16(pb); get_be16(pb); } st->codec->sample_rate = get_be16(pb); get_be32(pb); st->codec->channels = get_be16(pb); + if (((version >> 16) & 0xff) == 5) { + get_be32(pb); + buf[0] = get_byte(pb); + buf[1] = get_byte(pb); + buf[2] = get_byte(pb); + buf[3] = get_byte(pb); + buf[4] = 0; + } else { get_str8(pb, buf, sizeof(buf)); /* desc */ get_str8(pb, buf, sizeof(buf)); /* desc */ + } st->codec->codec_type = CODEC_TYPE_AUDIO; if (!strcmp(buf, "dnet")) { st->codec->codec_id = CODEC_ID_AC3; } else if (!strcmp(buf, "28_8")) { st->codec->codec_id = CODEC_ID_RA_288; - st->codec->extradata_size= 10; + st->codec->extradata_size= 0; + rm->audio_framesize = st->codec->block_align; + st->codec->block_align = coded_framesize; + rm->audiobuf = av_malloc(rm->audio_framesize * sub_packet_h); + } else if (!strcmp(buf, "cook")) { + int codecdata_length, i; + get_be16(pb); get_byte(pb); + if (((version >> 16) & 0xff) == 5) + get_byte(pb); + codecdata_length = get_be32(pb); + st->codec->codec_id = CODEC_ID_COOK; + st->codec->extradata_size= codecdata_length; st->codec->extradata= av_mallocz(st->codec->extradata_size); - /* this is completly braindead and broken, the idiot who added this codec and endianness - specific reordering to mplayer and libavcodec/ra288.c should be drowned in a see of cola */ - //FIXME pass the unpermutated extradata - ((uint16_t*)st->codec->extradata)[1]= sub_packet_h; - ((uint16_t*)st->codec->extradata)[2]= flavor; - ((uint16_t*)st->codec->extradata)[3]= coded_framesize; + for(i = 0; i < codecdata_length; i++) + ((uint8_t*)st->codec->extradata)[i] = get_byte(pb); + rm->audio_framesize = st->codec->block_align; + st->codec->block_align = rm->sub_packet_size; + rm->audiobuf = av_malloc(rm->audio_framesize * sub_packet_h); } else { st->codec->codec_id = CODEC_ID_NONE; pstrcpy(st->codec->codec_name, sizeof(st->codec->codec_name), @@ -819,6 +849,16 @@ static int rm_read_packet(AVFormatContext *s, AVPacket *pkt) } pkt->size = len; st = s->streams[0]; + } else if (rm->audio_pkt_cnt) { + // If there are queued audio packet return them first + st = s->streams[rm->audio_stream_num]; + av_new_packet(pkt, st->codec->block_align); + memcpy(pkt->data, rm->audiobuf + st->codec->block_align * + (rm->sub_packet_h * rm->audio_framesize / st->codec->block_align - rm->audio_pkt_cnt), + st->codec->block_align); + rm->audio_pkt_cnt--; + pkt->flags = 0; + pkt->stream_index = rm->audio_stream_num; } else { int seq=1; resync: @@ -850,15 +890,57 @@ resync: if(len2 && len2remaining_len-= len; + av_get_packet(pb, pkt, len); + } + + if (st->codec->codec_type == CODEC_TYPE_AUDIO) { + if ((st->codec->codec_id == CODEC_ID_RA_288) || + (st->codec->codec_id == CODEC_ID_COOK)) { + int x; + int sps = rm->sub_packet_size; + int cfs = rm->coded_framesize; + int h = rm->sub_packet_h; + int y = rm->sub_packet_cnt; + int w = rm->audio_framesize; + + if (flags & 2) + y = rm->sub_packet_cnt = 0; + if (!y) + rm->audiotimestamp = timestamp; + + switch(st->codec->codec_id) { + case CODEC_ID_RA_288: + for (x = 0; x < h/2; x++) + get_buffer(pb, rm->audiobuf+x*2*w+y*cfs, cfs); + break; + case CODEC_ID_COOK: + for (x = 0; x < w/sps; x++) + get_buffer(pb, rm->audiobuf+sps*(h*x+((h+1)/2)*(y&1)+(y>>1)), sps); + break; + } + + if (++(rm->sub_packet_cnt) < h) + goto resync; + else { + rm->sub_packet_cnt = 0; + rm->audio_stream_num = i; + rm->audio_pkt_cnt = h * w / st->codec->block_align - 1; + // Release first audio packet + av_new_packet(pkt, st->codec->block_align); + memcpy(pkt->data, rm->audiobuf, st->codec->block_align); + timestamp = rm->audiotimestamp; + flags = 2; // Mark first packet as keyframe + } + } else + av_get_packet(pb, pkt, len); } if( (st->discard >= AVDISCARD_NONKEY && !(flags&2)) || st->discard >= AVDISCARD_ALL){ - url_fskip(pb, len); + av_free_packet(pkt); goto resync; } - av_get_packet(pb, pkt, len); pkt->stream_index = i; #if 0 @@ -896,6 +978,9 @@ resync: static int rm_read_close(AVFormatContext *s) { + RMContext *rm = s->priv_data; + + av_free(rm->audiobuf); return 0; }