Update avcodec to 20080825

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27562 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
David McPaul
2008-09-15 14:12:05 +00:00
parent c17be5fb78
commit 46077e4bb0
12 changed files with 3347 additions and 3718 deletions
@@ -1,513 +1,356 @@
/* /*
* Real Audio 1.0 (14.4K) * Real Audio 1.0 (14.4K)
* Copyright (c) 2003 the ffmpeg project
* *
* This library is free software; you can redistribute it and/or * Copyright (c) 2008 Vitor Sessak
* Copyright (c) 2003 Nick Kurshev
* Based on public domain decoder at http://www.honeypot.net/audio
*
* 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 * modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either * License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version. * version 2.1 of the License, or (at your option) any later version.
* *
* This library is distributed in the hope that it will be useful, * FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details. * Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software * License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#include "avcodec.h" #include "avcodec.h"
#include "bitstream.h"
#include "ra144.h" #include "ra144.h"
#include "acelp_filters.h"
#define DATABLOCK1 20 /* size of 14.4 input block in bytes */ #define NBLOCKS 4 ///< number of subblocks within a block
#define DATACHUNK1 1440 /* size of 14.4 input chunk in bytes */ #define BLOCKSIZE 40 ///< subblock size in 16-bit words
#define AUDIOBLOCK 160 /* size of output block in 16-bit words (320 bytes) */ #define BUFFERSIZE 146 ///< the size of the adaptive codebook
#define AUDIOBUFFER 12288 /* size of output buffer in 16-bit words (24576 bytes) */
/* consts */
#define NBLOCKS 4 /* number of segments within a block */
#define BLOCKSIZE 40 /* (quarter) block size in 16-bit words (80 bytes) */
#define HALFBLOCK 20 /* BLOCKSIZE/2 */
#define BUFFERSIZE 146 /* for do_output */
/* internal globals */
typedef struct { typedef struct {
unsigned int resetflag, val, oldval; unsigned int old_energy; ///< previous frame energy
unsigned int unpacked[28]; /* buffer for unpacked input */
unsigned int *iptr; /* pointer to current input (from unpacked) */
unsigned int gval;
unsigned short *gsp;
unsigned int gbuf1[8];
unsigned short gbuf2[120];
signed short output_buffer[40];
unsigned int *decptr; /* decoder ptr */
signed short *decsp;
/* the swapped buffers */ unsigned int lpc_tables[2][10];
unsigned int swapb1a[10];
unsigned int swapb2a[10];
unsigned int swapb1b[10];
unsigned int swapb2b[10];
unsigned int *swapbuf1;
unsigned int *swapbuf2;
unsigned int *swapbuf1alt;
unsigned int *swapbuf2alt;
unsigned int buffer[5]; /** LPC coefficients: lpc_coef[0] is the coefficients of the current frame
unsigned short int buffer_2[148]; * and lpc_coef[1] of the previous one */
unsigned short int buffer_a[40]; unsigned int *lpc_coef[2];
unsigned short int buffer_b[40];
unsigned short int buffer_c[40];
unsigned short int buffer_d[40];
unsigned short int work[50]; unsigned int lpc_refl_rms[2];
unsigned short *sptr;
int buffer1[10]; /** the current subblock padded by the last 10 values of the previous one*/
int buffer2[10]; int16_t curr_sblock[50];
signed short wavtable1[2304]; /** adaptive codebook. Its size is two units bigger to avoid a
unsigned short wavtable2[2304]; * buffer overflow */
} Real144_internal; uint16_t adapt_cb[148];
} RA144Context;
static int ra144_decode_init(AVCodecContext * avctx) static int ra144_decode_init(AVCodecContext * avctx)
{ {
Real144_internal *glob=avctx->priv_data; RA144Context *ractx = avctx->priv_data;
memset(glob,0,sizeof(Real144_internal)); ractx->lpc_coef[0] = ractx->lpc_tables[0];
glob->resetflag=1; ractx->lpc_coef[1] = ractx->lpc_tables[1];
glob->swapbuf1=glob->swapb1a;
glob->swapbuf2=glob->swapb2a;
glob->swapbuf1alt=glob->swapb1b;
glob->swapbuf2alt=glob->swapb2b;
memcpy(glob->wavtable1,wavtable1,sizeof(wavtable1)); avctx->sample_fmt = SAMPLE_FMT_S16;
memcpy(glob->wavtable2,wavtable2,sizeof(wavtable2)); return 0;
return 0;
} }
static void final(Real144_internal *glob, short *i1, short *i2, void *out, int *statbuf, int len); /**
static void add_wav(Real144_internal *glob, int n, int f, int m1, int m2, int m3, short *s1, short *s2, short *s3, short *dest); * Evaluate sqrt(x << 24). x must fit in 20 bits. This value is evaluated in an
static int irms(short *data, int factor); * odd way to make the output identical to the binary decoder.
static void rotate_block(short *source, short *target, int offset); */
/* lookup square roots in table */
static int t_sqrt(unsigned int x) static int t_sqrt(unsigned int x)
{ {
int s=0; int s = 2;
while (x>0xfff) { s++; x=x>>2; } while (x > 0xfff) {
return (sqrt_table[x]<<s)<<2; s++;
} x >>= 2;
/* do 'voice' */
static void do_voice(int *a1, int *a2)
{
int buffer[10];
int *b1,*b2;
int x,y;
int *ptr,*tmp;
b1=buffer;
b2=a2;
for (x=0;x<10;x++) {
b1[x]=(*a1)<<4;
if(x>0) {
ptr=b2+x;
for (y=0;y<=x-1;y++)
b1[y]=(((*a1)*(*(--ptr)))>>12)+b2[y];
} }
tmp=b1;
b1=b2; return ff_sqrt(x << 20) << s;
b2=tmp;
a1++;
}
ptr=a2+10;
while (ptr>a2) (*a2++)>>=4;
} }
/**
/* do quarter-block output */ * Evaluate the LPC filter coefficients from the reflection coefficients.
static void do_output_subblock(Real144_internal *glob, int x) * Does the inverse of the eval_refl() function.
*/
static void eval_coefs(int *coefs, const int *refl)
{ {
int a,b,c,d,e,f,g; int buffer[10];
int *b1 = buffer;
int *b2 = coefs;
int i, j;
if (x==1) memset(glob->buffer,0,20); for (i=0; i < 10; i++) {
if ((*glob->iptr)==0) a=0; b1[i] = refl[i] << 4;
else a=(*glob->iptr)+HALFBLOCK-1;
glob->iptr++;
b=*(glob->iptr++);
c=*(glob->iptr++);
d=*(glob->iptr++);
if (a) rotate_block(glob->buffer_2,glob->buffer_a,a);
memcpy(glob->buffer_b,etable1+b*BLOCKSIZE,BLOCKSIZE*2);
e=((ftable1[b]>>4)*glob->gval)>>8;
memcpy(glob->buffer_c,etable2+c*BLOCKSIZE,BLOCKSIZE*2);
f=((ftable2[c]>>4)*glob->gval)>>8;
if (a) g=irms(glob->buffer_a,glob->gval)>>12;
else g=0;
add_wav(glob,d,a,g,e,f,glob->buffer_a,glob->buffer_b,glob->buffer_c,glob->buffer_d);
memmove(glob->buffer_2,glob->buffer_2+BLOCKSIZE,(BUFFERSIZE-BLOCKSIZE)*2);
memcpy(glob->buffer_2+BUFFERSIZE-BLOCKSIZE,glob->buffer_d,BLOCKSIZE*2);
final(glob,glob->gsp,glob->buffer_d,glob->output_buffer,glob->buffer,BLOCKSIZE);
}
/* rotate block */ for (j=0; j < i; j++)
static void rotate_block(short *source, short *target, int offset) b1[j] = ((refl[i] * b2[i-j-1]) >> 12) + b2[j];
{
short *end;
short *ptr1;
short *ptr2;
short *ptr3;
ptr2=source+BUFFERSIZE;
ptr3=ptr1=ptr2-offset;
end=target+BLOCKSIZE;
while (target<end) {
*(target++)=*(ptr3++);
if (ptr3==ptr2) ptr3=ptr1;
}
}
/* inverse root mean square */ FFSWAP(int *, b1, b2);
static int irms(short *data, int factor)
{
short *p1,*p2;
unsigned int sum;
p2=(p1=data)+BLOCKSIZE;
for (sum=0;p2>p1;p1++) sum+=(*p1)*(*p1);
if (sum==0) return 0; /* OOPS - division by zero */
return (0x20000000/(t_sqrt(sum)>>8))*factor;
}
/* multiply/add wavetable */
static void add_wav(Real144_internal *glob, int n, int f, int m1, int m2, int m3, short *s1, short *s2, short *s3, short *dest)
{
int a,b,c;
short *ptr,*ptr2;
ptr=glob->wavtable1+n*9;
ptr2=glob->wavtable2+n*9;
if (f!=0) {
a=((*ptr)*m1)>>((*ptr2)+1);
} else {
a=0;
}
ptr++;ptr2++;
b=((*ptr)*m2)>>((*ptr2)+1);
ptr++;ptr2++;
c=((*ptr)*m3)>>((*ptr2)+1);
ptr2=(ptr=dest)+BLOCKSIZE;
if (f!=0)
while (ptr<ptr2)
*(ptr++)=((*(s1++))*a+(*(s2++))*b+(*(s3++))*c)>>12;
else
while (ptr<ptr2)
*(ptr++)=((*(s2++))*b+(*(s3++))*c)>>12;
}
static void final(Real144_internal *glob, short *i1, short *i2, void *out, int *statbuf, int len)
{
int x,sum;
int buffer[10];
short *ptr;
short *ptr2;
memcpy(glob->work,statbuf,20);
memcpy(glob->work+10,i2,len*2);
buffer[9]=i1[0];
buffer[8]=i1[1];
buffer[7]=i1[2];
buffer[6]=i1[3];
buffer[5]=i1[4];
buffer[4]=i1[5];
buffer[3]=i1[6];
buffer[2]=i1[7];
buffer[1]=i1[8];
buffer[0]=i1[9];
ptr2=(ptr=glob->work)+len;
while (ptr<ptr2) {
for(sum=0,x=0;x<=9;x++)
sum+=buffer[x]*(ptr[x]);
sum=sum>>12;
x=ptr[10]-sum;
if (x<-32768 || x>32767)
{
memset(out,0,len*2);
memset(statbuf,0,20);
return;
} }
ptr[10]=x;
ptr++; for (i=0; i < 10; i++)
} coefs[i] >>= 4;
memcpy(out,ptr+10-len,len*2);
memcpy(statbuf,ptr,20);
} }
/* Decode 20-byte input */ /**
static void unpack_input(unsigned char *input, unsigned int *output) * Copy the last offset values of *source to *target. If those values are not
* enough to fill the target buffer, fill it with another copy of those values.
*/
static void copy_and_dup(int16_t *target, const int16_t *source, int offset)
{ {
unsigned int outbuffer[28]; source += BUFFERSIZE - offset;
unsigned short inbuffer[10];
unsigned int x;
unsigned int *ptr;
/* fix endianness */ if (offset > BLOCKSIZE) {
for (x=0;x<20;x+=2) memcpy(target, source, BLOCKSIZE*sizeof(*target));
inbuffer[x/2]=(input[x]<<8)+input[x+1];
/* unpack */
ptr=outbuffer;
*(ptr++)=27;
*(ptr++)=(inbuffer[0]>>10)&0x3f;
*(ptr++)=(inbuffer[0]>>5)&0x1f;
*(ptr++)=inbuffer[0]&0x1f;
*(ptr++)=(inbuffer[1]>>12)&0xf;
*(ptr++)=(inbuffer[1]>>8)&0xf;
*(ptr++)=(inbuffer[1]>>5)&7;
*(ptr++)=(inbuffer[1]>>2)&7;
*(ptr++)=((inbuffer[1]<<1)&6)|((inbuffer[2]>>15)&1);
*(ptr++)=(inbuffer[2]>>12)&7;
*(ptr++)=(inbuffer[2]>>10)&3;
*(ptr++)=(inbuffer[2]>>5)&0x1f;
*(ptr++)=((inbuffer[2]<<2)&0x7c)|((inbuffer[3]>>14)&3);
*(ptr++)=(inbuffer[3]>>6)&0xff;
*(ptr++)=((inbuffer[3]<<1)&0x7e)|((inbuffer[4]>>15)&1);
*(ptr++)=(inbuffer[4]>>8)&0x7f;
*(ptr++)=(inbuffer[4]>>1)&0x7f;
*(ptr++)=((inbuffer[4]<<7)&0x80)|((inbuffer[5]>>9)&0x7f);
*(ptr++)=(inbuffer[5]>>2)&0x7f;
*(ptr++)=((inbuffer[5]<<5)&0x60)|((inbuffer[6]>>11)&0x1f);
*(ptr++)=(inbuffer[6]>>4)&0x7f;
*(ptr++)=((inbuffer[6]<<4)&0xf0)|((inbuffer[7]>>12)&0xf);
*(ptr++)=(inbuffer[7]>>5)&0x7f;
*(ptr++)=((inbuffer[7]<<2)&0x7c)|((inbuffer[8]>>14)&3);
*(ptr++)=(inbuffer[8]>>7)&0x7f;
*(ptr++)=((inbuffer[8]<<1)&0xfe)|((inbuffer[9]>>15)&1);
*(ptr++)=(inbuffer[9]>>8)&0x7f;
*(ptr++)=(inbuffer[9]>>1)&0x7f;
*(output++)=outbuffer[11];
for (x=1;x<11;*(output++)=outbuffer[x++]);
ptr=outbuffer+12;
for (x=0;x<16;x+=4)
{
*(output++)=ptr[x];
*(output++)=ptr[x+2];
*(output++)=ptr[x+3];
*(output++)=ptr[x+1];
}
}
static unsigned int rms(int *data, int f)
{
int *c;
int x;
unsigned int res;
int b;
c=data;
b=0;
res=0x10000;
for (x=0;x<10;x++)
{
res=(((0x1000000-(*c)*(*c))>>12)*res)>>12;
if (res==0) return 0;
if (res<=0x3fff)
{
while (res<=0x3fff)
{
b++;
res<<=2;
}
} else { } else {
if (res>0x10000) memcpy(target, source, offset*sizeof(*target));
return 0; /* We're screwed, might as well go out with a bang. :P */ memcpy(target + offset, source, (BLOCKSIZE - offset)*sizeof(*target));
} }
c++;
}
if (res>0) res=t_sqrt(res);
res>>=(b+10);
res=(res*f)>>10;
return res;
} }
static void dec1(Real144_internal *glob, int *data, int *inp, int n, int f) /** inverse root mean square */
static int irms(const int16_t *data)
{ {
short *ptr,*end; unsigned int i, sum = 0;
*(glob->decptr++)=rms(data,f); for (i=0; i < BLOCKSIZE; i++)
glob->decptr++; sum += data[i] * data[i];
end=(ptr=glob->decsp)+(n*10);
while (ptr<end) *(ptr++)=*(inp++); if (sum == 0)
return 0; /* OOPS - division by zero */
return 0x20000000 / (t_sqrt(sum) >> 8);
} }
static int eq(Real144_internal *glob, short *in, int *target) static void add_wav(int16_t *dest, int n, int skip_first, int *m,
const int16_t *s1, const int8_t *s2, const int8_t *s3)
{ {
int retval; int i;
int a; int v[3];
int b;
int c;
unsigned int u;
short *sptr;
int *ptr1,*ptr2,*ptr3;
int *bp1,*bp2,*temp;
retval=0; v[0] = 0;
bp1=glob->buffer1; for (i=!skip_first; i<3; i++)
bp2=glob->buffer2; v[i] = (gain_val_tab[n][i] * m[i]) >> (gain_exp_tab[n][i] + 1);
ptr2=(ptr3=glob->buffer2)+9;
sptr=in;
while (ptr2>=ptr3)
*(ptr3++)=*(sptr++);
target+=9; for (i=0; i < BLOCKSIZE; i++)
a=bp2[9]; dest[i] = (s1[i]*v[0] + s2[i]*v[1] + s3[i]*v[2]) >> 12;
*target=a;
if (a+0x1000>0x1fff)
return 0; /* We're screwed, might as well go out with a bang. :P */
c=8;u=a;
while (c>=0)
{
if (u==0x1000) u++;
if (u==0xfffff000) u--;
b=0x1000-((u*u)>>12);
if (b==0) b++;
ptr2=bp1;
ptr1=(ptr3=bp2)+c;
for (u=0;u<=c;u++)
*(ptr2++)=((*(ptr3++)-(((*target)*(*(ptr1--)))>>12))*(0x1000000/b))>>12;
*(--target)=u=bp1[(c--)];
if ((u+0x1000)>0x1fff) retval=1;
temp=bp2;
bp2=bp1;
bp1=temp;
}
return retval;
} }
static void dec2(Real144_internal *glob, int *data, int *inp, int n, int f, int *inp2, int l) static unsigned int rescale_rms(unsigned int rms, unsigned int energy)
{ {
unsigned int *ptr1,*ptr2; return (rms * energy) >> 10;
int work[10];
int a,b;
int x;
int result;
if(l+1<NBLOCKS/2) a=NBLOCKS-(l+1);
else a=l+1;
b=NBLOCKS-a;
if (l==0)
{
glob->decsp=glob->sptr=glob->gbuf2;
glob->decptr=glob->gbuf1;
}
ptr1=inp;
ptr2=inp2;
for (x=0;x<10*n;x++)
*(glob->sptr++)=(a*(*ptr1++)+b*(*ptr2++))>>2;
result=eq(glob,glob->decsp,work);
if (result==1)
{
dec1(glob,data,inp,n,f);
} else {
*(glob->decptr++)=rms(work,f);
glob->decptr++;
}
glob->decsp+=n*10;
} }
/* Uncompress one block (20 bytes -> 160*2 bytes) */ static unsigned int rms(const int *data)
static int ra144_decode_frame(AVCodecContext * avctx,
void *data, int *data_size,
uint8_t * buf, int buf_size)
{ {
unsigned int a,b,c; int i;
long s; unsigned int res = 0x10000;
signed short *shptr; int b = 10;
unsigned int *lptr,*temp;
const short **dptr;
void *datao;
Real144_internal *glob=avctx->priv_data;
datao = data; for (i=0; i < 10; i++) {
unpack_input(buf,glob->unpacked); res = (((0x1000000 - data[i]*data[i]) >> 12) * res) >> 12;
glob->iptr=glob->unpacked; if (res == 0)
glob->val=decodetable[0][(*(glob->iptr++))<<1]; return 0;
dptr=decodetable+1; while (res <= 0x3fff) {
lptr=glob->swapbuf1; b++;
while (lptr<glob->swapbuf1+10) res <<= 2;
*(lptr++)=(*(dptr++))[(*(glob->iptr++))<<1]; }
}
do_voice(glob->swapbuf1,glob->swapbuf2); return t_sqrt(res) >> b;
}
a=t_sqrt(glob->val*glob->oldval)>>12; static void do_output_subblock(RA144Context *ractx, const uint16_t *lpc_coefs,
int gval, GetBitContext *gb)
{
uint16_t buffer_a[40];
uint16_t *block;
int cba_idx = get_bits(gb, 7); // index of the adaptive CB, 0 if none
int gain = get_bits(gb, 8);
int cb1_idx = get_bits(gb, 7);
int cb2_idx = get_bits(gb, 7);
int m[3];
for (c=0;c<NBLOCKS;c++) { if (cba_idx) {
if (c==(NBLOCKS-1)) { cba_idx += BLOCKSIZE/2 - 1;
dec1(glob,glob->swapbuf1,glob->swapbuf2,3,glob->val); copy_and_dup(buffer_a, ractx->adapt_cb, cba_idx);
m[0] = (irms(buffer_a) * gval) >> 12;
} else { } else {
if (c*2==(NBLOCKS-2)) { m[0] = 0;
if (glob->oldval<glob->val) {
dec2(glob,glob->swapbuf1,glob->swapbuf2,3,a,glob->swapbuf2alt,c);
} else {
dec2(glob,glob->swapbuf1alt,glob->swapbuf2alt,3,a,glob->swapbuf2,c);
}
} else {
if (c*2<(NBLOCKS-2)) {
dec2(glob,glob->swapbuf1alt,glob->swapbuf2alt,3,glob->oldval,glob->swapbuf2,c);
} else {
dec2(glob,glob->swapbuf1,glob->swapbuf2,3,glob->val,glob->swapbuf2alt,c);
}
}
} }
}
/* do output */ m[1] = (cb1_base[cb1_idx] * gval) >> 8;
for (b=0,c=0;c<4;c++) { m[2] = (cb2_base[cb2_idx] * gval) >> 8;
glob->gval=glob->gbuf1[c*2];
glob->gsp=glob->gbuf2+b;
do_output_subblock(glob,glob->resetflag);
glob->resetflag=0;
shptr=glob->output_buffer; memmove(ractx->adapt_cb, ractx->adapt_cb + BLOCKSIZE,
while (shptr<glob->output_buffer+BLOCKSIZE) { (BUFFERSIZE - BLOCKSIZE) * sizeof(*ractx->adapt_cb));
s=*(shptr++)<<2;
*((int16_t *)data)=s;
if (s>32767) *((int16_t *)data)=32767;
if (s<-32767) *((int16_t *)data)=-32768;
data = (int16_t *)data + 1;
}
b+=30;
}
glob->oldval=glob->val; block = ractx->adapt_cb + BUFFERSIZE - BLOCKSIZE;
temp=glob->swapbuf1alt;
glob->swapbuf1alt=glob->swapbuf1; add_wav(block, gain, cba_idx, m, buffer_a,
glob->swapbuf1=temp; cb1_vects[cb1_idx], cb2_vects[cb2_idx]);
temp=glob->swapbuf2alt;
glob->swapbuf2alt=glob->swapbuf2; memcpy(ractx->curr_sblock, ractx->curr_sblock + 40,
glob->swapbuf2=temp; 10*sizeof(*ractx->curr_sblock));
*data_size=data-datao;
return 20; if (ff_acelp_lp_synthesis_filter(ractx->curr_sblock + 10, lpc_coefs,
block, BLOCKSIZE, 10, 1, 0xfff))
memset(ractx->curr_sblock, 0, 50*sizeof(*ractx->curr_sblock));
} }
static void int_to_int16(int16_t *out, const int *inp)
{
int i;
for (i=0; i < 30; i++)
*(out++) = *(inp++);
}
/**
* Evaluate the reflection coefficients from the filter coefficients.
* Does the inverse of the eval_coefs() function.
*
* @return 1 if one of the reflection coefficients is of magnitude greater than
* 4095, 0 if not.
*/
static int eval_refl(int *refl, const int16_t *coefs, RA144Context *ractx)
{
int b, i, j;
int buffer1[10];
int buffer2[10];
int *bp1 = buffer1;
int *bp2 = buffer2;
for (i=0; i < 10; i++)
buffer2[i] = coefs[i];
refl[9] = bp2[9];
if ((unsigned) bp2[9] + 0x1000 > 0x1fff) {
av_log(ractx, AV_LOG_ERROR, "Overflow. Broken sample?\n");
return 1;
}
for (i=8; i >= 0; i--) {
b = 0x1000-((bp2[i+1] * bp2[i+1]) >> 12);
if (!b)
b = -2;
for (j=0; j <= i; j++)
bp1[j] = ((bp2[j] - ((refl[i+1] * bp2[i-j]) >> 12)) * (0x1000000 / b)) >> 12;
refl[i] = bp1[i];
if ((unsigned) bp1[i] + 0x1000 > 0x1fff)
return 1;
FFSWAP(int *, bp1, bp2);
}
return 0;
}
static int interp(RA144Context *ractx, int16_t *out, int block_num,
int copyold, int energy)
{
int work[10];
int a = block_num + 1;
int b = NBLOCKS - a;
int i;
// Interpolate block coefficients from the this frame forth block and
// last frame forth block
for (i=0; i<30; i++)
out[i] = (a * ractx->lpc_coef[0][i] + b * ractx->lpc_coef[1][i])>> 2;
if (eval_refl(work, out, ractx)) {
// The interpolated coefficients are unstable, copy either new or old
// coefficients
int_to_int16(out, ractx->lpc_coef[copyold]);
return rescale_rms(ractx->lpc_refl_rms[copyold], energy);
} else {
return rescale_rms(rms(work), energy);
}
}
/** Uncompress one block (20 bytes -> 160*2 bytes) */
static int ra144_decode_frame(AVCodecContext * avctx, void *vdata,
int *data_size, const uint8_t *buf, int buf_size)
{
static const uint8_t sizes[10] = {6, 5, 5, 4, 4, 3, 3, 3, 3, 2};
unsigned int refl_rms[4]; // RMS of the reflection coefficients
uint16_t block_coefs[4][30]; // LPC coefficients of each sub-block
unsigned int lpc_refl[10]; // LPC reflection coefficients of the frame
int i, j;
int16_t *data = vdata;
unsigned int energy;
RA144Context *ractx = avctx->priv_data;
GetBitContext gb;
if (*data_size < 2*160)
return -1;
if(buf_size < 20) {
av_log(avctx, AV_LOG_ERROR,
"Frame too small (%d bytes). Truncated file?\n", buf_size);
*data_size = 0;
return buf_size;
}
init_get_bits(&gb, buf, 20 * 8);
for (i=0; i<10; i++)
lpc_refl[i] = lpc_refl_cb[i][get_bits(&gb, sizes[i])];
eval_coefs(ractx->lpc_coef[0], lpc_refl);
ractx->lpc_refl_rms[0] = rms(lpc_refl);
energy = energy_tab[get_bits(&gb, 5)];
refl_rms[0] = interp(ractx, block_coefs[0], 0, 1, ractx->old_energy);
refl_rms[1] = interp(ractx, block_coefs[1], 1, energy <= ractx->old_energy,
t_sqrt(energy*ractx->old_energy) >> 12);
refl_rms[2] = interp(ractx, block_coefs[2], 2, 0, energy);
refl_rms[3] = rescale_rms(ractx->lpc_refl_rms[0], energy);
int_to_int16(block_coefs[3], ractx->lpc_coef[0]);
for (i=0; i < 4; i++) {
do_output_subblock(ractx, block_coefs[i], refl_rms[i], &gb);
for (j=0; j < BLOCKSIZE; j++)
*data++ = av_clip_int16(ractx->curr_sblock[j + 10] << 2);
}
ractx->old_energy = energy;
ractx->lpc_refl_rms[1] = ractx->lpc_refl_rms[0];
FFSWAP(unsigned int *, ractx->lpc_coef[0], ractx->lpc_coef[1]);
*data_size = 2*160;
return 20;
}
AVCodec ra_144_decoder = AVCodec ra_144_decoder =
{ {
"real_144", "real_144",
CODEC_TYPE_AUDIO, CODEC_TYPE_AUDIO,
CODEC_ID_RA_144, CODEC_ID_RA_144,
sizeof(Real144_internal), sizeof(RA144Context),
ra144_decode_init, ra144_decode_init,
NULL, NULL,
NULL, NULL,
ra144_decode_frame, ra144_decode_frame,
.long_name = NULL_IF_CONFIG_SMALL("RealAudio 1.0 (14.4K)"),
}; };
File diff suppressed because it is too large Load Diff
@@ -2,267 +2,260 @@
* RealAudio 2.0 (28.8K) * RealAudio 2.0 (28.8K)
* Copyright (c) 2003 the ffmpeg project * Copyright (c) 2003 the ffmpeg project
* *
* This library is free software; you can redistribute it and/or * 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 * modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either * License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version. * version 2.1 of the License, or (at your option) any later version.
* *
* This library is distributed in the hope that it will be useful, * FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details. * Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software * License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#include "avcodec.h" #include "avcodec.h"
#define ALT_BITSTREAM_READER_LE
#include "bitstream.h"
#include "ra288.h" #include "ra288.h"
typedef struct { typedef struct {
float history[8]; float sp_lpc[36]; ///< LPC coefficients for speech data (spec: A)
float output[40]; float gain_lpc[10]; ///< LPC coefficients for gain (spec: GB)
float pr1[36];
float pr2[10];
int phase, phasep;
float st1a[111],st1b[37],st1[37]; float sp_hist[111]; ///< Speech data history (spec: SB)
float st2a[38],st2b[11],st2[11];
float sb[41];
float lhist[10];
} Real288_internal;
static int ra288_decode_init(AVCodecContext * avctx) /** Speech part of the gain autocorrelation (spec: REXP) */
float sp_rec[37];
float gain_hist[38]; ///< Log-gain history (spec: SBLG)
/** Recursive part of the gain autocorrelation (spec: REXPLG) */
float gain_rec[11];
float sp_block[41]; ///< Speech data of four blocks (spec: STTMP)
float gain_block[10]; ///< Gain data of four blocks (spec: GSTATE)
} RA288Context;
static av_cold int ra288_decode_init(AVCodecContext *avctx)
{ {
Real288_internal *glob=avctx->priv_data; avctx->sample_fmt = SAMPLE_FMT_S16;
memset(glob,0,sizeof(Real288_internal));
return 0;
}
static void prodsum(float *tgt, float *src, int len, int n);
static void co(int n, int i, int j, float *in, float *out, float *st1, float *st2, const float *table);
static int pred(float *in, float *tgt, int n);
static void colmult(float *tgt, float *m1, const float *m2, int n);
/* initial decode */
static void unpack(unsigned short *tgt, unsigned char *src, int len)
{
int x,y,z;
int n,temp;
int buffer[len];
for (x=0;x<len;tgt[x++]=0)
buffer[x]=9+(x&1);
for (x=y=z=0;x<len/*was 38*/;x++) {
n=buffer[y]-z;
temp=src[x];
if (n<8) temp&=255>>(8-n);
tgt[y]+=temp<<z;
if (n<=8) {
tgt[++y]+=src[x]>>n;
z=8-n;
} else z+=8;
}
}
static void update(Real288_internal *glob)
{
int x,y;
float buffer1[40],temp1[37];
float buffer2[8],temp2[11];
for (x=0,y=glob->phasep+5;x<40;buffer1[x++]=glob->output[(y++)%40]);
co(36,40,35,buffer1,temp1,glob->st1a,glob->st1b,table1);
if (pred(temp1,glob->st1,36))
colmult(glob->pr1,glob->st1,table1a,36);
for (x=0,y=glob->phase+1;x<8;buffer2[x++]=glob->history[(y++)%8]);
co(10,8,20,buffer2,temp2,glob->st2a,glob->st2b,table2);
if (pred(temp2,glob->st2,10))
colmult(glob->pr2,glob->st2,table2a,10);
}
/* Decode and produce output */
static void decode(Real288_internal *glob, unsigned int input)
{
unsigned int x,y;
float f;
double sum,sumsum;
float *p1,*p2;
float buffer[5];
const float *table;
for (x=36;x--;glob->sb[x+5]=glob->sb[x]);
for (x=5;x--;) {
p1=glob->sb+x;p2=glob->pr1;
for (sum=0,y=36;y--;sum-=(*(++p1))*(*(p2++)));
glob->sb[x]=sum;
}
f=amptable[input&7];
table=codetable+(input>>3)*5;
/* convert log and do rms */
for (sum=32,x=10;x--;sum-=glob->pr2[x]*glob->lhist[x]);
if (sum<0) sum=0; else if (sum>60) sum=60;
sumsum=exp(sum*0.1151292546497)*f; /* pow(10.0,sum/20)*f */
for (sum=0,x=5;x--;) { buffer[x]=table[x]*sumsum; sum+=buffer[x]*buffer[x]; }
if ((sum/=5)<1) sum=1;
/* shift and store */
for (x=10;--x;glob->lhist[x]=glob->lhist[x-1]);
*glob->lhist=glob->history[glob->phase]=10*log10(sum)-32;
for (x=1;x<5;x++) for (y=x;y--;buffer[x]-=glob->pr1[x-y-1]*buffer[y]);
/* output */
for (x=0;x<5;x++) {
f=glob->sb[4-x]+buffer[x];
if (f>4095) f=4095; else if (f<-4095) f=-4095;
glob->output[glob->phasep+x]=glob->sb[4-x]=f;
}
}
/* column multiply */
static void colmult(float *tgt, float *m1, const float *m2, int n)
{
while (n--)
*(tgt++)=(*(m1++))*(*(m2++));
}
static int pred(float *in, float *tgt, int n)
{
int x,y;
float *p1,*p2;
double f0,f1,f2;
float temp;
if (in[n]==0) return 0;
if ((f0=*in)<=0) return 0;
for (x=1;;x++) {
if (n<x) return 1;
p1=in+x;
p2=tgt;
f1=*(p1--);
for (y=x;--y;f1+=(*(p1--))*(*(p2++)));
p1=tgt+x-1;
p2=tgt;
*(p1--)=f2=-f1/f0;
for (y=x>>1;y--;) {
temp=*p2+*p1*f2;
*(p1--)+=*p2*f2;
*(p2++)=temp;
}
if ((f0+=f1*f2)<0) return 0;
}
}
static void co(int n, int i, int j, float *in, float *out, float *st1, float *st2, const float *table)
{
int a,b,c;
unsigned int x;
float *fp;
float buffer1[37];
float buffer2[37];
float work[111];
/* rotate and multiply */
c=(b=(a=n+i)+j)-i;
fp=st1+i;
for (x=0;x<b;x++) {
if (x==c) fp=in;
work[x]=*(table++)*(*(st1++)=*(fp++));
}
prodsum(buffer1,work+n,i,n);
prodsum(buffer2,work+a,j,n);
for (x=0;x<=n;x++) {
*st2=*st2*(0.5625)+buffer1[x];
out[x]=*(st2++)+buffer2[x];
}
*out*=1.00390625; /* to prevent clipping */
}
/* product sum (lsf) */
static void prodsum(float *tgt, float *src, int len, int n)
{
unsigned int x;
float *p1,*p2;
double sum;
while (n>=0)
{
p1=(p2=src)-n;
for (sum=0,x=len;x--;sum+=(*p1++)*(*p2++));
tgt[n--]=sum;
}
}
void * decode_block(AVCodecContext * avctx, unsigned char *in, signed short int *out,unsigned len)
{
int x,y;
Real288_internal *glob=avctx->priv_data;
unsigned short int buffer[len];
unpack(buffer,in,len);
for (x=0;x<32;x++)
{
glob->phasep=(glob->phase=x&7)*5;
decode(glob,buffer[x]);
for (y=0;y<5;*(out++)=8*glob->output[glob->phasep+(y++)]);
if (glob->phase==3) update(glob);
}
return out;
}
/* Decode a block (celp) */
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_size<w*h)
{
av_log(avctx, AV_LOG_ERROR, "ffra288: Error! Input buffer is too small [%d<%d]\n",buf_size,w*h);
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_size = data - datao;
return bret;
}
else
{
av_log(avctx, AV_LOG_ERROR, "ffra288: Error: need extra data!!!\n");
return 0; return 0;
} }
static inline float scalar_product_float(const float * v1, const float * v2,
int size)
{
float res = 0.;
while (size--)
res += *v1++ * *v2++;
return res;
}
static void colmult(float *tgt, const float *m1, const float *m2, int n)
{
while (n--)
*tgt++ = *m1++ * *m2++;
}
static void decode(RA288Context *ractx, float gain, int cb_coef)
{
int i, j;
double sumsum;
float sum, buffer[5];
float *block = ractx->sp_block + 36; // Current block
memmove(ractx->sp_block, ractx->sp_block + 5, 36*sizeof(*ractx->sp_block));
for (i=0; i < 5; i++) {
block[i] = 0.;
for (j=0; j < 36; j++)
block[i] -= block[i-1-j]*ractx->sp_lpc[j];
}
/* block 46 of G.728 spec */
sum = 32.;
for (i=0; i < 10; i++)
sum -= ractx->gain_block[9-i] * ractx->gain_lpc[i];
/* block 47 of G.728 spec */
sum = av_clipf(sum, 0, 60);
/* block 48 of G.728 spec */
sumsum = exp(sum * 0.1151292546497) * gain; /* pow(10.0,sum/20)*gain */
for (i=0; i < 5; i++)
buffer[i] = codetable[cb_coef][i] * sumsum;
sum = scalar_product_float(buffer, buffer, 5) / 5;
sum = FFMAX(sum, 1);
/* shift and store */
memmove(ractx->gain_block, ractx->gain_block + 1,
9 * sizeof(*ractx->gain_block));
ractx->gain_block[9] = 10 * log10(sum) - 32;
for (i=1; i < 5; i++)
for (j=i-1; j >= 0; j--)
buffer[i] -= ractx->sp_lpc[i-j-1] * buffer[j];
/* output */
for (i=0; i < 5; i++)
block[i] = av_clipf(block[i] + buffer[i], -4095, 4095);
}
/**
* Converts autocorrelation coefficients to LPC coefficients using the
* Levinson-Durbin algorithm. See blocks 37 and 50 of the G.728 specification.
*
* @return 0 if success, -1 if fail
*/
static int eval_lpc_coeffs(const float *in, float *tgt, int n)
{
int i, j;
double f0, f1, f2;
if (in[n] == 0)
return -1;
if ((f0 = *in) <= 0)
return -1;
in--; // To avoid a -1 subtraction in the inner loop
for (i=1; i <= n; i++) {
f1 = in[i+1];
for (j=0; j < i - 1; j++)
f1 += in[i-j]*tgt[j];
tgt[i-1] = f2 = -f1/f0;
for (j=0; j < i >> 1; j++) {
float temp = tgt[j] + tgt[i-j-2]*f2;
tgt[i-j-2] += tgt[j]*f2;
tgt[j] = temp;
}
if ((f0 += f1*f2) < 0)
return -1;
}
return 0;
}
static void convolve(float *tgt, const float *src, int len, int n)
{
for (; n >= 0; n--)
tgt[n] = scalar_product_float(src, src - n, len);
}
/**
* Hybrid window filtering. See blocks 36 and 49 of the G.728 specification.
*
* @param order the order of the filter
* @param n the length of the input
* @param non_rec the number of non-recursive samples
* @param out the filter output
* @param in pointer to the input of the filter
* @param hist pointer to the input history of the filter. It is updated by
* this function.
* @param out pointer to the non-recursive part of the output
* @param out2 pointer to the recursive part of the output
* @param window pointer to the windowing function table
*/
static void do_hybrid_window(int order, int n, int non_rec, const float *in,
float *out, float *hist, float *out2,
const float *window)
{
int i;
float buffer1[order + 1];
float buffer2[order + 1];
float work[order + n + non_rec];
/* update history */
memmove(hist , hist + n, (order + non_rec)*sizeof(*hist));
memcpy (hist + order + non_rec, in , n *sizeof(*hist));
colmult(work, window, hist, order + n + non_rec);
convolve(buffer1, work + order , n , order);
convolve(buffer2, work + order + n, non_rec, order);
for (i=0; i <= order; i++) {
out2[i] = out2[i] * 0.5625 + buffer1[i];
out [i] = out2[i] + buffer2[i];
}
/* Multiply by the white noise correcting factor (WNCF) */
*out *= 257./256.;
}
/**
* Backward synthesis filter. Find the LPC coefficients from past speech data.
*/
static void backward_filter(RA288Context *ractx)
{
float temp1[37]; // RTMP in the spec
float temp2[11]; // GPTPMP in the spec
do_hybrid_window(36, 40, 35, ractx->sp_block+1, temp1, ractx->sp_hist,
ractx->sp_rec, syn_window);
if (!eval_lpc_coeffs(temp1, ractx->sp_lpc, 36))
colmult(ractx->sp_lpc, ractx->sp_lpc, syn_bw_tab, 36);
do_hybrid_window(10, 8, 20, ractx->gain_block+2, temp2, ractx->gain_hist,
ractx->gain_rec, gain_window);
if (!eval_lpc_coeffs(temp2, ractx->gain_lpc, 10))
colmult(ractx->gain_lpc, ractx->gain_lpc, gain_bw_tab, 10);
}
static int ra288_decode_frame(AVCodecContext * avctx, void *data,
int *data_size, const uint8_t * buf,
int buf_size)
{
int16_t *out = data;
int i, j;
RA288Context *ractx = avctx->priv_data;
GetBitContext gb;
if (buf_size < avctx->block_align) {
av_log(avctx, AV_LOG_ERROR,
"Error! Input buffer is too small [%d<%d]\n",
buf_size, avctx->block_align);
return 0;
}
if (*data_size < 32*5*2)
return -1;
init_get_bits(&gb, buf, avctx->block_align * 8);
for (i=0; i < 32; i++) {
float gain = amptable[get_bits(&gb, 3)];
int cb_coef = get_bits(&gb, 6 + (i&1));
decode(ractx, gain, cb_coef);
for (j=0; j < 5; j++)
*(out++) = 8 * ractx->sp_block[36 + j];
if ((i & 7) == 3)
backward_filter(ractx);
}
*data_size = (char *)out - (char *)data;
return avctx->block_align;
} }
AVCodec ra_288_decoder = AVCodec ra_288_decoder =
@@ -270,9 +263,10 @@ AVCodec ra_288_decoder =
"real_288", "real_288",
CODEC_TYPE_AUDIO, CODEC_TYPE_AUDIO,
CODEC_ID_RA_288, CODEC_ID_RA_288,
sizeof(Real288_internal), sizeof(RA288Context),
ra288_decode_init, ra288_decode_init,
NULL, NULL,
NULL, NULL,
ra288_decode_frame, ra288_decode_frame,
.long_name = NULL_IF_CONFIG_SMALL("RealAudio 2.0 (28.8K)"),
}; };
@@ -2,202 +2,208 @@
* RealAudio 2.0 (28.8K) * RealAudio 2.0 (28.8K)
* Copyright (c) 2003 the ffmpeg project * Copyright (c) 2003 the ffmpeg project
* *
* This library is free software; you can redistribute it and/or * 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 * modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either * License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version. * version 2.1 of the License, or (at your option) any later version.
* *
* This library is distributed in the hope that it will be useful, * FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details. * Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software * License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#ifndef RA288TABLES_H #ifndef FFMPEG_RA288_H
#define RA288TABLES_H #define FFMPEG_RA288_H
static const float amptable[8]={ 0.515625, 0.90234375, 1.57910156, 2.76342773, static const float amptable[8]={
-0.515625,-0.90234375,-1.57910156,-2.76342773 }; 0.515625, 0.90234375, 1.57910156, 2.76342773,
-0.515625, -0.90234375, -1.57910156, -2.76342773
static const float codetable[640]={
0.326171875, -1.4404296875, -0.6123046875, -0.8740234375, -1.24658203125,
-2.45703125, -2.23486328125, -0.51025390625, 1.419921875, 1.6201171875,
-1.37646484375, -1.30712890625, -0.462890625, -1.37939453125, -2.1728515625,
-3.26123046875, -0.166015625, 0.7236328125, -0.623046875, 0.6162109375,
-0.2744140625, -3.29931640625, 0.62548828125, 0.08740234375, -0.6220703125,
-1.2265625, -3.4814453125, -2.40478515625, 3.37548828125, 1.17724609375,
-1.2099609375, -0.076171875, 2.28662109375, -1.89111328125, 0,
-4.0078125, 1.044921875, -0.2333984375, -1.35986328125, 0.26025390625,
0.92236328125, 1.34716796875, 0.67431640625, -3.39599609375, -2.88720703125,
2.4814453125, -1.201171875, -2.8212890625, 0.87744140625, 0.27734375,
-1.078125, -1.61572265625, -2.20849609375, -3.044921875, -3.66455078125,
-1.32763671875, 2.1279296875, -1.458984375, -0.56103515625, 1.30078125,
0.61474609375, 0.48583984375, 1.32373046875, -1.203125, -5.0732421875,
0.8408203125, -3.69580078125, -1.3388671875, 1.06005859375, -1.13720703125,
0.50390625, 0.36474609375, -0.4189453125, -3.8798828125, -6.27099609375,
1.5166015625, 2.37109375, -2.04736328125, -1.24072265625, 0.50537109375,
0.9091796875, -0.46875, -3.236328125, 0.2001953125, 2.8720703125,
-1.21728515625, -1.283203125, -1.953125, -0.029296875, 3.5166015625,
-1.3046875, 0.7060546875, 0.75, -1.87060546875, 0.60205078125,
-2.5888671875, 3.375, 0.77587890625, -2.04443359375, 1.78955078125,
-1.6875, -3.9892578125, -3.76416015625, 0.67578125, 2.2939453125,
-2.29443359375, -3.03173828125, -5.45703125, 3.95703125, 8.2177734375,
0.4541015625, 3.419921875, 0.61962890625, -4.38330078125, 1.25341796875,
2.27001953125, 5.763671875, 1.68017578125, -2.76220703125, 0.58544921875,
1.2412109375, -0.08935546875, -4.32568359375, -3.89453125, 1.5771484375,
-1.40234375, -0.98193359375, -4.74267578125, -4.09423828125, 6.33935546875,
1.5068359375, 1.044921875, -1.796875, -4.70849609375, -1.4140625,
-3.71533203125, 3.18115234375, -1.11474609375, -1.2314453125, 3.091796875,
-1.62744140625, -2.744140625, -4.4580078125, -5.43505859375, 2.70654296875,
-0.19873046875, -3.28173828125, -8.5283203125, -1.41064453125, 5.6484375,
1.802734375, 3.318359375, -0.1279296875, -5.2958984375, -0.90625,
3.55224609375, 6.544921875, -1.45947265625, -5.17333984375, 2.41015625,
0.119140625, -1.08349609375, 1.296875, 1.84375, -2.642578125,
-1.97412109375, -2.8974609375, 1.04052734375, 0.42138671875, -1.3994140625,
-1.6123046875, 0.85107421875, -0.9794921875, -0.0625, -1.001953125,
-3.10595703125, 1.6318359375, -0.77294921875, -0.01025390625, 0.5576171875,
-1.87353515625, -0.89404296875, 3.12353515625, 1.24267578125, -1.390625,
-4.556640625, -3.1875, 2.59228515625, 0.9697265625, -1.09619140625,
-2.1923828125, 0.365234375, 0.94482421875, -1.47802734375, -0.24072265625,
-4.51904296875, 2.6201171875, 1.55908203125, -2.19384765625, 0.87109375,
2.3359375, -0.1806640625, 0.9111328125, 0.51611328125, -0.92236328125,
3.5849609375, -1.3134765625, -1.25830078125, 0.330078125, -0.29833984375,
-0.2451171875, 1.09130859375, -0.9033203125, -0.86767578125, -1.00048828125,
0.49365234375, 1.89453125, -1.20361328125, 1.07861328125, -0.07421875,
1.265625, 1.38134765625, 2.728515625, 1.38623046875, -3.5673828125,
-1.48876953125, -2.4013671875, 2.90771484375, 4.49267578125, -2.17138671875,
0.34033203125, 1.908203125, 2.8310546875, -2.17333984375, -2.267578125,
-1.03564453125, 2.658203125, -1.2548828125, 0.15673828125, -0.5869140625,
1.3896484375, -1.0185546875, 1.724609375, 0.2763671875, -0.345703125,
-2.08935546875, 0.4638671875, 2.431640625, 1.83056640625, 0.220703125,
-1.212890625, 1.7099609375, 0.83935546875, -0.0830078125, 0.1162109375,
-1.67724609375, 0.12841796875, 1.0322265625, -0.97900390625, 1.15283203125,
-3.5830078125, -0.58984375, 4.56396484375, -0.59375, -1.95947265625,
-6.5908203125, -0.21435546875, 3.919921875, -2.06640625, 0.17626953125,
-1.82080078125, 2.65283203125, 0.978515625, -2.30810546875, -0.61474609375,
-1.9462890625, 3.78076171875, 4.11572265625, -1.80224609375, -0.48193359375,
2.5380859375, -0.20654296875, 0.5615234375, -0.62548828125, 0.3984375,
3.61767578125, 2.00634765625, -1.92822265625, 1.3134765625, 0.0146484384313,
0.6083984375, 1.49169921875, -0.01708984375, -0.6689453125, -0.1201171875,
-0.72705078125, 2.75146484375, -0.3310546875, -1.28271484375, 1.5478515625,
2.3583984375, -2.23876953125, 0.98046875, -0.5185546875, 0.39013671875,
-0.06298828125, 0.35009765625, 2.2431640625, 7.29345703125, 5.2275390625,
0.20361328125, 1.34716796875, 0.9033203125, -2.46923828125, -0.56298828125,
-1.89794921875, 3.59423828125, -2.81640625, 2.09228515625, 0.3251953125,
0.70458984375, -0.4580078125, 0.009765625, -1.03466796875, -0.82861328125,
-1.8125, -1.6611328125, -1.080078125, 0.0537109375, 1.04296875,
-1.44140625, 0.005859375, -0.765625, -1.708984375, -0.90576171875,
-0.64208984375, -0.84521484375, 0.56640625, -0.2724609375, 0.83447265625,
0.04296875, -2.23095703125, 0.0947265625, -0.2216796875, -1.44384765625,
-1.38623046875, -0.8134765625, -0.13330078125, 1.017578125, -0.07568359375,
-0.09228515625, -1.16015625, 0.81201171875, -0.5078125, -1.19580078125,
-1.3876953125, -0.66845703125, 0.310546875, -0.12109375, -1.30712890625,
0.74072265625, 0.03857421875, -1.47119140625, -1.79150390625, -0.47509765625,
0.93408203125, -1.21728515625, -2.59375, -0.36572265625, 0.62060546875,
-1.41748046875, -1.623046875, -1.833984375, -1.8017578125, -0.89306640625,
-1.42236328125, -0.75537109375, -1.34765625, -0.6865234375, 0.548828125,
0.900390625, -0.8955078125, 0.22265625, 0.3447265625, -2.0859375,
0.22802734375, -2.078125, -0.93212890625, 0.74267578125, 0.5537109375,
-0.06201171875, -0.4853515625, -0.31103515625, -0.72802734375, -3.1708984375,
0.42626953125, -0.99853515625, -1.869140625, -1.36328125, -0.2822265625,
1.12841796875, -0.88720703125, 1.28515625, -1.490234375, 0.9609375,
0.31298828125, 0.5830078125, 0.92431640625, 2.00537109375, 3.0966796875,
-0.02197265625, 0.5849609375, 1.0546875, -0.70751953125, 1.07568359375,
-0.978515625, 0.83642578125, 1.7177734375, 1.294921875, 2.07568359375,
1.43359375, -1.9375, 0.625, 0.06396484375, -0.720703125,
1.38037109375, 0.00390625, -0.94140625, 1.2978515625, 1.71533203125,
1.56201171875, -0.3984375, 1.31201171875, -0.85009765625, -0.68701171875,
1.439453125, 1.96728515625, 0.1923828125, -0.12353515625, 0.6337890625,
2.0927734375, 0.02490234375, -2.20068359375, -0.015625, -0.32177734375,
1.90576171875, 2.7568359375, -2.728515625, -1.265625, 2.78662109375,
-0.2958984375, 0.6025390625, -0.78466796875, -2.53271484375, 0.32421875,
-0.25634765625, 1.767578125, -1.0703125, -1.23388671875, 0.83349609375,
2.09814453125, -1.58740234375, -1.11474609375, 0.396484375, -1.10546875,
2.81494140625, 0.2578125, -1.60498046875, 0.66015625, 0.81640625,
1.33544921875, 0.60595703125, -0.53857421875, -1.59814453125, -1.66357421875,
1.96923828125, 0.8046875, -1.44775390625, -0.5732421875, 0.705078125,
0.0361328125, 0.4482421875, 0.97607421875, 0.44677734375, -0.5009765625,
-1.21875, -0.78369140625, 0.9931640625, 1.4404296875, 0.11181640625,
-1.05859375, 0.99462890625, 0.00732421921566,-0.6171875, -0.1015625,
-1.734375, 0.7470703125, 0.28369140625, 0.72802734375, 0.4697265625,
-1.27587890625, -1.1416015625, 1.76806640625, -0.7265625, -1.06689453125,
-0.85302734375, 0.03955078125, 2.7041015625, 0.69921875, -1.10205078125,
-0.49755859375, 0.42333984375, 0.1044921875, -1.115234375, -0.7373046875,
-0.822265625, 1.375, -0.11181640625, 1.24560546875, -0.67822265625,
1.32177734375, 0.24609375, 0.23388671875, 1.35888671875, -0.49267578125,
1.22900390625, -0.72607421875, -0.779296875, 0.30322265625, 0.94189453125,
-0.072265625, 1.0771484375, -2.09375, 0.630859375, -0.68408203125,
-0.25732421875, 0.60693359375, -1.33349609375, 0.93212890625, 0.625,
1.04931640625, -0.73291015625, 1.80078125, 0.2978515625, -2.24169921875,
1.6142578125, -1.64501953125, 0.91552734375, 1.775390625, -0.59423828125,
1.2568359375, 1.22705078125, 0.70751953125, -1.5009765625, -2.43115234375,
0.3974609375, 0.8916015625, -1.21923828125, 2.0673828125, -1.99072265625,
0.8125, -0.107421875, 1.6689453125, 0.4892578125, 0.54443359375,
0.38134765625, 0.8095703125, 1.91357421875, 2.9931640625, 1.533203125,
0.560546875, 1.98486328125, 0.740234375, 0.39794921875, 0.09716796875,
0.58154296875, 1.21533203125, 1.25048828125, 1.18212890625, 1.19287109375,
0.3759765625, -2.88818359375, 2.69287109375, -0.1796875, -1.56201171875,
0.5810546875, 0.51123046875, 1.8271484375, 3.38232421875, -1.02001953125,
0.142578125, 1.51318359375, 2.103515625, -0.3701171875, -1.19873046875,
0.25537109375, 1.91455078125, 1.974609375, 0.6767578125, 0.04150390625,
2.13232421875, 0.4912109375, -0.611328125, -0.7158203125, -0.67529296875,
1.880859375, 0.77099609375, -0.03759765625, 1.0078125, 0.423828125,
2.49462890625, 1.42529296875, -0.0986328125, 0.17529296875, -0.24853515625,
1.7822265625, 1.5654296875, 1.12451171875, 0.82666015625, 0.6328125,
1.41845703125, -1.90771484375, 0.11181640625, -0.583984375, -1.138671875,
2.91845703125, -1.75048828125, 0.39306640625, 1.86767578125, -1.5322265625,
1.8291015625, -0.2958984375, 0.02587890625, -0.13134765625, -1.61181640625,
0.2958984375, 0.9853515625, -0.642578125, 1.984375, 0.1943359375
}; };
static const float table1[111]={ static const float codetable[128][5]={
0.576690972, 0.580838025, 0.585013986, 0.589219987, 0.59345597, 0.597723007, { 0.326171875, -1.4404296875, -0.6123046875, -0.8740234375, -1.24658203125},
0.602020264, 0.606384277, 0.610748291, 0.615142822, 0.619598389, 0.624084473, {-2.45703125, -2.23486328125, -0.51025390625, 1.419921875, 1.6201171875 },
0.628570557, 0.633117676, 0.637695313, 0.642272949, 0.646911621, 0.651580811, {-1.37646484375, -1.30712890625, -0.462890625, -1.37939453125, -2.1728515625 },
0.656280518, 0.66104126, 0.665802002, 0.670593262, 0.675445557, 0.680328369, {-3.26123046875, -0.166015625, 0.7236328125, -0.623046875, 0.6162109375 },
0.685241699, 0.690185547, 0.695159912, 0.700164795, 0.705230713, 0.710327148, {-0.2744140625, -3.29931640625, 0.62548828125, 0.08740234375, -0.6220703125 },
0.715454102, 0.720611572, 0.725830078, 0.731048584, 0.736328125, 0.741638184, {-1.2265625, -3.4814453125, -2.40478515625, 3.37548828125, 1.17724609375},
0.747009277, 0.752380371, 0.7578125, 0.763305664, 0.768798828, 0.774353027, {-1.2099609375, -0.076171875, 2.28662109375, -1.89111328125, 0 },
0.779937744, 0.785583496, 0.791229248, 0.796936035, 0.802703857, 0.808502197, {-4.0078125, 1.044921875, -0.2333984375, -1.35986328125, 0.26025390625},
0.814331055, 0.820220947, 0.826141357, 0.832092285, 0.838104248, 0.844146729, { 0.92236328125, 1.34716796875, 0.67431640625, -3.39599609375, -2.88720703125},
0.850250244, 0.856384277, 0.862548828, 0.868774414, 0.875061035, 0.881378174, { 2.4814453125, -1.201171875, -2.8212890625, 0.87744140625, 0.27734375 },
0.88772583, 0.894134521, 0.900604248, 0.907104492, 0.913635254, 0.920227051, {-1.078125, -1.61572265625, -2.20849609375, -3.044921875, -3.66455078125},
0.926879883, 0.933563232, 0.940307617, 0.94708252, 0.953918457, 0.96081543, {-1.32763671875, 2.1279296875, -1.458984375, -0.56103515625, 1.30078125 },
0.96774292, 0.974731445, 0.981781006, 0.988861084, 0.994842529, 0.998565674, { 0.61474609375, 0.48583984375, 1.32373046875, -1.203125, -5.0732421875 },
0.999969482, 0.99911499, 0.996002197, 0.990600586, 0.982910156, 0.973022461, { 0.8408203125, -3.69580078125, -1.3388671875, 1.06005859375, -1.13720703125},
0.960876465, 0.946533203, 0.930053711, 0.911437988, 0.89074707, 0.868041992, { 0.50390625, 0.36474609375, -0.4189453125, -3.8798828125, -6.27099609375},
0.843322754, 0.816680908, 0.788208008, 0.757904053, 0.725891113, 0.692199707, { 1.5166015625, 2.37109375, -2.04736328125, -1.24072265625, 0.50537109375},
0.656921387, 0.620178223, 0.582000732, 0.542480469, 0.501739502, 0.459838867, { 0.9091796875, -0.46875, -3.236328125, 0.2001953125, 2.8720703125 },
0.416900635, 0.373016357, 0.328277588, 0.282775879, 0.236663818, 0.189971924, {-1.21728515625, -1.283203125, -1.953125, -0.029296875, 3.5166015625 },
0.142852783, 0.0954284668, 0.0477600098 {-1.3046875, 0.7060546875, 0.75, -1.87060546875, 0.60205078125},
{-2.5888671875, 3.375, 0.77587890625, -2.04443359375, 1.78955078125},
{-1.6875, -3.9892578125, -3.76416015625, 0.67578125, 2.2939453125 },
{-2.29443359375, -3.03173828125, -5.45703125, 3.95703125, 8.2177734375 },
{ 0.4541015625, 3.419921875, 0.61962890625, -4.38330078125, 1.25341796875},
{ 2.27001953125, 5.763671875, 1.68017578125, -2.76220703125, 0.58544921875},
{ 1.2412109375, -0.08935546875, -4.32568359375, -3.89453125, 1.5771484375 },
{-1.40234375, -0.98193359375, -4.74267578125, -4.09423828125, 6.33935546875},
{ 1.5068359375, 1.044921875, -1.796875, -4.70849609375, -1.4140625 },
{-3.71533203125, 3.18115234375, -1.11474609375, -1.2314453125, 3.091796875 },
{-1.62744140625, -2.744140625, -4.4580078125, -5.43505859375, 2.70654296875},
{-0.19873046875, -3.28173828125, -8.5283203125, -1.41064453125, 5.6484375 },
{ 1.802734375, 3.318359375, -0.1279296875, -5.2958984375, -0.90625 },
{ 3.55224609375, 6.544921875, -1.45947265625, -5.17333984375, 2.41015625 },
{ 0.119140625, -1.08349609375, 1.296875, 1.84375, -2.642578125 },
{-1.97412109375, -2.8974609375, 1.04052734375, 0.42138671875, -1.3994140625 },
{-1.6123046875, 0.85107421875, -0.9794921875, -0.0625, -1.001953125 },
{-3.10595703125, 1.6318359375, -0.77294921875, -0.01025390625, 0.5576171875 },
{-1.87353515625, -0.89404296875, 3.12353515625, 1.24267578125, -1.390625 },
{-4.556640625, -3.1875, 2.59228515625, 0.9697265625, -1.09619140625},
{-2.1923828125, 0.365234375, 0.94482421875, -1.47802734375, -0.24072265625},
{-4.51904296875, 2.6201171875, 1.55908203125, -2.19384765625, 0.87109375 },
{ 2.3359375, -0.1806640625, 0.9111328125, 0.51611328125, -0.92236328125},
{ 3.5849609375, -1.3134765625, -1.25830078125, 0.330078125, -0.29833984375},
{-0.2451171875, 1.09130859375, -0.9033203125, -0.86767578125, -1.00048828125},
{ 0.49365234375, 1.89453125, -1.20361328125, 1.07861328125, -0.07421875 },
{ 1.265625, 1.38134765625, 2.728515625, 1.38623046875, -3.5673828125 },
{-1.48876953125, -2.4013671875, 2.90771484375, 4.49267578125, -2.17138671875},
{ 0.34033203125, 1.908203125, 2.8310546875, -2.17333984375, -2.267578125 },
{-1.03564453125, 2.658203125, -1.2548828125, 0.15673828125, -0.5869140625 },
{ 1.3896484375, -1.0185546875, 1.724609375, 0.2763671875, -0.345703125 },
{-2.08935546875, 0.4638671875, 2.431640625, 1.83056640625, 0.220703125 },
{-1.212890625, 1.7099609375, 0.83935546875, -0.0830078125, 0.1162109375 },
{-1.67724609375, 0.12841796875, 1.0322265625, -0.97900390625, 1.15283203125},
{-3.5830078125, -0.58984375, 4.56396484375, -0.59375, -1.95947265625},
{-6.5908203125, -0.21435546875, 3.919921875, -2.06640625, 0.17626953125},
{-1.82080078125, 2.65283203125, 0.978515625, -2.30810546875, -0.61474609375},
{-1.9462890625, 3.78076171875, 4.11572265625, -1.80224609375, -0.48193359375},
{ 2.5380859375, -0.20654296875, 0.5615234375, -0.62548828125, 0.3984375 },
{ 3.61767578125, 2.00634765625, -1.92822265625, 1.3134765625, 0.0146484384313},
{ 0.6083984375, 1.49169921875, -0.01708984375, -0.6689453125, -0.1201171875 },
{-0.72705078125, 2.75146484375, -0.3310546875, -1.28271484375, 1.5478515625 },
{ 2.3583984375, -2.23876953125, 0.98046875, -0.5185546875, 0.39013671875},
{-0.06298828125, 0.35009765625, 2.2431640625, 7.29345703125, 5.2275390625 },
{ 0.20361328125, 1.34716796875, 0.9033203125, -2.46923828125, -0.56298828125},
{-1.89794921875, 3.59423828125, -2.81640625, 2.09228515625, 0.3251953125 },
{ 0.70458984375, -0.4580078125, 0.009765625, -1.03466796875, -0.82861328125},
{-1.8125, -1.6611328125, -1.080078125, 0.0537109375, 1.04296875 },
{-1.44140625, 0.005859375, -0.765625, -1.708984375, -0.90576171875},
{-0.64208984375, -0.84521484375, 0.56640625, -0.2724609375, 0.83447265625},
{ 0.04296875, -2.23095703125, 0.0947265625, -0.2216796875, -1.44384765625},
{-1.38623046875, -0.8134765625, -0.13330078125, 1.017578125, -0.07568359375},
{-0.09228515625, -1.16015625, 0.81201171875, -0.5078125, -1.19580078125},
{-1.3876953125, -0.66845703125, 0.310546875, -0.12109375, -1.30712890625},
{ 0.74072265625, 0.03857421875, -1.47119140625, -1.79150390625, -0.47509765625},
{ 0.93408203125, -1.21728515625, -2.59375, -0.36572265625, 0.62060546875},
{-1.41748046875, -1.623046875, -1.833984375, -1.8017578125, -0.89306640625},
{-1.42236328125, -0.75537109375, -1.34765625, -0.6865234375, 0.548828125 },
{ 0.900390625, -0.8955078125, 0.22265625, 0.3447265625, -2.0859375 },
{ 0.22802734375, -2.078125, -0.93212890625, 0.74267578125, 0.5537109375 },
{-0.06201171875, -0.4853515625, -0.31103515625, -0.72802734375, -3.1708984375 },
{ 0.42626953125, -0.99853515625, -1.869140625, -1.36328125, -0.2822265625 },
{ 1.12841796875, -0.88720703125, 1.28515625, -1.490234375, 0.9609375 },
{ 0.31298828125, 0.5830078125, 0.92431640625, 2.00537109375, 3.0966796875 },
{-0.02197265625, 0.5849609375, 1.0546875, -0.70751953125, 1.07568359375},
{-0.978515625, 0.83642578125, 1.7177734375, 1.294921875, 2.07568359375},
{ 1.43359375, -1.9375, 0.625, 0.06396484375, -0.720703125 },
{ 1.38037109375, 0.00390625, -0.94140625, 1.2978515625, 1.71533203125},
{ 1.56201171875, -0.3984375, 1.31201171875, -0.85009765625, -0.68701171875},
{ 1.439453125, 1.96728515625, 0.1923828125, -0.12353515625, 0.6337890625 },
{ 2.0927734375, 0.02490234375, -2.20068359375, -0.015625, -0.32177734375},
{ 1.90576171875, 2.7568359375, -2.728515625, -1.265625, 2.78662109375},
{-0.2958984375, 0.6025390625, -0.78466796875, -2.53271484375, 0.32421875 },
{-0.25634765625, 1.767578125, -1.0703125, -1.23388671875, 0.83349609375},
{ 2.09814453125, -1.58740234375, -1.11474609375, 0.396484375, -1.10546875 },
{ 2.81494140625, 0.2578125, -1.60498046875, 0.66015625, 0.81640625 },
{ 1.33544921875, 0.60595703125, -0.53857421875, -1.59814453125, -1.66357421875},
{ 1.96923828125, 0.8046875, -1.44775390625, -0.5732421875, 0.705078125 },
{ 0.0361328125, 0.4482421875, 0.97607421875, 0.44677734375, -0.5009765625 },
{-1.21875, -0.78369140625, 0.9931640625, 1.4404296875, 0.11181640625},
{-1.05859375, 0.99462890625,0.00732421921566,-0.6171875, -0.1015625 },
{-1.734375, 0.7470703125, 0.28369140625, 0.72802734375, 0.4697265625 },
{-1.27587890625, -1.1416015625, 1.76806640625, -0.7265625, -1.06689453125},
{-0.85302734375, 0.03955078125, 2.7041015625, 0.69921875, -1.10205078125},
{-0.49755859375, 0.42333984375, 0.1044921875, -1.115234375, -0.7373046875 },
{-0.822265625, 1.375, -0.11181640625, 1.24560546875, -0.67822265625},
{ 1.32177734375, 0.24609375, 0.23388671875, 1.35888671875, -0.49267578125},
{ 1.22900390625, -0.72607421875, -0.779296875, 0.30322265625, 0.94189453125},
{-0.072265625, 1.0771484375, -2.09375, 0.630859375, -0.68408203125},
{-0.25732421875, 0.60693359375, -1.33349609375, 0.93212890625, 0.625 },
{ 1.04931640625, -0.73291015625, 1.80078125, 0.2978515625, -2.24169921875},
{ 1.6142578125, -1.64501953125, 0.91552734375, 1.775390625, -0.59423828125},
{ 1.2568359375, 1.22705078125, 0.70751953125, -1.5009765625, -2.43115234375},
{ 0.3974609375, 0.8916015625, -1.21923828125, 2.0673828125, -1.99072265625},
{ 0.8125, -0.107421875, 1.6689453125, 0.4892578125, 0.54443359375},
{ 0.38134765625, 0.8095703125, 1.91357421875, 2.9931640625, 1.533203125 },
{ 0.560546875, 1.98486328125, 0.740234375, 0.39794921875, 0.09716796875},
{ 0.58154296875, 1.21533203125, 1.25048828125, 1.18212890625, 1.19287109375},
{ 0.3759765625, -2.88818359375, 2.69287109375, -0.1796875, -1.56201171875},
{ 0.5810546875, 0.51123046875, 1.8271484375, 3.38232421875, -1.02001953125},
{ 0.142578125, 1.51318359375, 2.103515625, -0.3701171875, -1.19873046875},
{ 0.25537109375, 1.91455078125, 1.974609375, 0.6767578125, 0.04150390625},
{ 2.13232421875, 0.4912109375, -0.611328125, -0.7158203125, -0.67529296875},
{ 1.880859375, 0.77099609375, -0.03759765625, 1.0078125, 0.423828125 },
{ 2.49462890625, 1.42529296875, -0.0986328125, 0.17529296875, -0.24853515625},
{ 1.7822265625, 1.5654296875, 1.12451171875, 0.82666015625, 0.6328125 },
{ 1.41845703125, -1.90771484375, 0.11181640625, -0.583984375, -1.138671875 },
{ 2.91845703125, -1.75048828125, 0.39306640625, 1.86767578125, -1.5322265625 },
{ 1.8291015625, -0.2958984375, 0.02587890625, -0.13134765625, -1.61181640625},
{ 0.2958984375, 0.9853515625, -0.642578125, 1.984375, 0.1943359375 }
}; };
static const float table2[38]={ static const float syn_window[111]={
0.505699992, 0.524200022, 0.54339999, 0.563300014, 0.583953857, 0.60534668, 0.576690972, 0.580838025, 0.585013986, 0.589219987, 0.59345597, 0.597723007,
0.627502441, 0.650482178, 0.674316406, 0.699005127, 0.724578857, 0.75112915, 0.602020264, 0.606384277, 0.610748291, 0.615142822, 0.619598389, 0.624084473,
0.778625488, 0.807128906, 0.836669922, 0.86730957, 0.899078369, 0.932006836, 0.628570557, 0.633117676, 0.637695313, 0.642272949, 0.646911621, 0.651580811,
0.961486816, 0.982757568, 0.995635986, 1, 0.995819092, 0.983154297, 0.656280518, 0.66104126, 0.665802002, 0.670593262, 0.675445557, 0.680328369,
0.96206665, 0.932769775, 0.895507813, 0.850585938, 0.798400879, 0.739379883, 0.685241699, 0.690185547, 0.695159912, 0.700164795, 0.705230713, 0.710327148,
0.674072266, 0.602996826, 0.526763916, 0.446014404, 0.361480713, 0.273834229, 0.715454102, 0.720611572, 0.725830078, 0.731048584, 0.736328125, 0.741638184,
0.183868408, 0.0923461914 0.747009277, 0.752380371, 0.7578125, 0.763305664, 0.768798828, 0.774353027,
0.779937744, 0.785583496, 0.791229248, 0.796936035, 0.802703857, 0.808502197,
0.814331055, 0.820220947, 0.826141357, 0.832092285, 0.838104248, 0.844146729,
0.850250244, 0.856384277, 0.862548828, 0.868774414, 0.875061035, 0.881378174,
0.88772583, 0.894134521, 0.900604248, 0.907104492, 0.913635254, 0.920227051,
0.926879883, 0.933563232, 0.940307617, 0.94708252, 0.953918457, 0.96081543,
0.96774292, 0.974731445, 0.981781006, 0.988861084, 0.994842529, 0.998565674,
0.999969482, 0.99911499, 0.996002197, 0.990600586, 0.982910156, 0.973022461,
0.960876465, 0.946533203, 0.930053711, 0.911437988, 0.89074707, 0.868041992,
0.843322754, 0.816680908, 0.788208008, 0.757904053, 0.725891113, 0.692199707,
0.656921387, 0.620178223, 0.582000732, 0.542480469, 0.501739502, 0.459838867,
0.416900635, 0.373016357, 0.328277588, 0.282775879, 0.236663818, 0.189971924,
0.142852783, 0.0954284668,0.0477600098
}; };
static const float table1a[36]={ static const float gain_window[38]={
0.98828125, 0.976699829, 0.965254128, 0.953942537, 0.942763507, 0.931715488, 0.505699992, 0.524200022, 0.54339999, 0.563300014, 0.583953857, 0.60534668,
0.920796931, 0.910006344, 0.899342179, 0.888803005, 0.878387332, 0.868093729, 0.627502441, 0.650482178, 0.674316406, 0.699005127, 0.724578857, 0.75112915,
0.857920766, 0.847867012, 0.837931097, 0.828111589, 0.818407178, 0.808816493, 0.778625488, 0.807128906, 0.836669922, 0.86730957, 0.899078369, 0.932006836,
0.799338162, 0.789970934, 0.780713439, 0.771564424, 0.762522638, 0.753586829, 0.961486816, 0.982757568, 0.995635986, 1, 0.995819092, 0.983154297,
0.744755745, 0.736028135, 0.727402806, 0.718878567, 0.710454226, 0.702128589, 0.96206665, 0.932769775, 0.895507813, 0.850585938, 0.798400879, 0.739379883,
0.693900526, 0.685768902, 0.677732527, 0.669790328, 0.66194123, 0.654184103 0.674072266, 0.602996826, 0.526763916, 0.446014404, 0.361480713, 0.273834229,
0.183868408, 0.0923461914
}; };
static const float table2a[10]={ /** Synthesis bandwidth broadening table */
0.90625, 0.821289063, 0.74432373, 0.674499512, 0.61126709, static const float syn_bw_tab[36]={
0.553955078, 0.50201416, 0.454956055, 0.41229248, 0.373657227 0.98828125, 0.976699829, 0.965254128, 0.953942537, 0.942763507, 0.931715488,
0.920796931, 0.910006344, 0.899342179, 0.888803005, 0.878387332, 0.868093729,
0.857920766, 0.847867012, 0.837931097, 0.828111589, 0.818407178, 0.808816493,
0.799338162, 0.789970934, 0.780713439, 0.771564424, 0.762522638, 0.753586829,
0.744755745, 0.736028135, 0.727402806, 0.718878567, 0.710454226, 0.702128589,
0.693900526, 0.685768902, 0.677732527, 0.669790328, 0.66194123, 0.654184103
}; };
#endif /* RA288TABLES_H */ /** Gain bandwidth broadening table */
static const float gain_bw_tab[10]={
0.90625, 0.821289063, 0.74432373, 0.674499512, 0.61126709,
0.553955078, 0.50201416, 0.454956055, 0.41229248, 0.373657227
};
#endif /* FFMPEG_RA288_H */
@@ -0,0 +1,152 @@
/*
* Range coder
* Copyright (c) 2004 Michael Niedermayer <[email protected]>
*
* 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 rangecoder.c
* Range coder.
* based upon
* "Range encoding: an algorithm for removing redundancy from a digitised
* message.
* G. N. N. Martin Presented in March 1979 to the Video &
* Data Recording Conference,
* IBM UK Scientific Center held in Southampton July 24-27 1979."
*
*/
#include <string.h>
#include "avcodec.h"
#include "rangecoder.h"
#include "bytestream.h"
void ff_init_range_encoder(RangeCoder *c, uint8_t *buf, int buf_size){
c->bytestream_start=
c->bytestream= buf;
c->bytestream_end= buf + buf_size;
c->low= 0;
c->range= 0xFF00;
c->outstanding_count= 0;
c->outstanding_byte= -1;
}
void ff_init_range_decoder(RangeCoder *c, const uint8_t *buf, int buf_size){
/* cast to avoid compiler warning */
ff_init_range_encoder(c, (uint8_t *) buf, buf_size);
c->low = bytestream_get_be16(&c->bytestream);
}
void ff_build_rac_states(RangeCoder *c, int factor, int max_p){
const int64_t one= 1LL<<32;
int64_t p;
int last_p8, p8, i;
memset(c->zero_state, 0, sizeof(c->zero_state));
memset(c-> one_state, 0, sizeof(c-> one_state));
last_p8= 0;
p= one/2;
for(i=0; i<128; i++){
p8= (256*p + one/2) >> 32; //FIXME try without the one
if(p8 <= last_p8) p8= last_p8+1;
if(last_p8 && last_p8<256 && p8<=max_p)
c->one_state[last_p8]= p8;
p+= ((one-p)*factor + one/2) >> 32;
last_p8= p8;
}
for(i=256-max_p; i<=max_p; i++){
if(c->one_state[i])
continue;
p= (i*one + 128) >> 8;
p+= ((one-p)*factor + one/2) >> 32;
p8= (256*p + one/2) >> 32; //FIXME try without the one
if(p8 <= i) p8= i+1;
if(p8 > max_p) p8= max_p;
c->one_state[ i]= p8;
}
for(i=1; i<255; i++)
c->zero_state[i]= 256-c->one_state[256-i];
}
/**
*
* @return the number of bytes written
*/
int ff_rac_terminate(RangeCoder *c){
c->range=0xFF;
c->low +=0xFF;
renorm_encoder(c);
c->range=0xFF;
renorm_encoder(c);
assert(c->low == 0);
assert(c->range >= 0x100);
return c->bytestream - c->bytestream_start;
}
#ifdef TEST
#define SIZE 10240
#undef random
int main(void){
RangeCoder c;
uint8_t b[9*SIZE];
uint8_t r[9*SIZE];
int i;
uint8_t state[10]= {0};
ff_init_range_encoder(&c, b, SIZE);
ff_build_rac_states(&c, 0.05*(1LL<<32), 128+64+32+16);
memset(state, 128, sizeof(state));
for(i=0; i<SIZE; i++){
r[i]= random()%7;
}
for(i=0; i<SIZE; i++){
START_TIMER
put_rac(&c, state, r[i]&1);
STOP_TIMER("put_rac")
}
ff_rac_terminate(&c);
ff_init_range_decoder(&c, b, SIZE);
memset(state, 128, sizeof(state));
for(i=0; i<SIZE; i++){
START_TIMER
if( (r[i]&1) != get_rac(&c, state) )
av_log(NULL, AV_LOG_DEBUG, "rac failure at %d\n", i);
STOP_TIMER("get_rac")
}
return 0;
}
#endif /* TEST */
@@ -0,0 +1,141 @@
/*
* Range coder
* Copyright (c) 2004 Michael Niedermayer <[email protected]>
*
* 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 rangecoder.h
* Range coder.
*/
#ifndef FFMPEG_RANGECODER_H
#define FFMPEG_RANGECODER_H
#include <stdint.h>
#include <assert.h>
#include "common.h"
typedef struct RangeCoder{
int low;
int range;
int outstanding_count;
int outstanding_byte;
uint8_t zero_state[256];
uint8_t one_state[256];
uint8_t *bytestream_start;
uint8_t *bytestream;
uint8_t *bytestream_end;
}RangeCoder;
void ff_init_range_encoder(RangeCoder *c, uint8_t *buf, int buf_size);
void ff_init_range_decoder(RangeCoder *c, const uint8_t *buf, int buf_size);
int ff_rac_terminate(RangeCoder *c);
void ff_build_rac_states(RangeCoder *c, int factor, int max_p);
static inline void renorm_encoder(RangeCoder *c){
//FIXME optimize
while(c->range < 0x100){
if(c->outstanding_byte < 0){
c->outstanding_byte= c->low>>8;
}else if(c->low <= 0xFF00){
*c->bytestream++ = c->outstanding_byte;
for(;c->outstanding_count; c->outstanding_count--)
*c->bytestream++ = 0xFF;
c->outstanding_byte= c->low>>8;
}else if(c->low >= 0x10000){
*c->bytestream++ = c->outstanding_byte + 1;
for(;c->outstanding_count; c->outstanding_count--)
*c->bytestream++ = 0x00;
c->outstanding_byte= (c->low>>8) & 0xFF;
}else{
c->outstanding_count++;
}
c->low = (c->low & 0xFF)<<8;
c->range <<= 8;
}
}
static inline int get_rac_count(RangeCoder *c){
int x= c->bytestream - c->bytestream_start + c->outstanding_count;
if(c->outstanding_byte >= 0)
x++;
return 8*x - av_log2(c->range);
}
static inline void put_rac(RangeCoder *c, uint8_t * const state, int bit){
int range1= (c->range * (*state)) >> 8;
assert(*state);
assert(range1 < c->range);
assert(range1 > 0);
if(!bit){
c->range -= range1;
*state= c->zero_state[*state];
}else{
c->low += c->range - range1;
c->range = range1;
*state= c->one_state[*state];
}
renorm_encoder(c);
}
static inline void refill(RangeCoder *c){
if(c->range < 0x100){
c->range <<= 8;
c->low <<= 8;
if(c->bytestream < c->bytestream_end)
c->low+= c->bytestream[0];
c->bytestream++;
}
}
static inline int get_rac(RangeCoder *c, uint8_t * const state){
int range1= (c->range * (*state)) >> 8;
int av_unused one_mask;
c->range -= range1;
#if 1
if(c->low < c->range){
*state= c->zero_state[*state];
refill(c);
return 0;
}else{
c->low -= c->range;
*state= c->one_state[*state];
c->range = range1;
refill(c);
return 1;
}
#else
one_mask= (c->range - c->low-1)>>31;
c->low -= c->range & one_mask;
c->range += (range1 - c->range) & one_mask;
*state= c->zero_state[(*state) + (256&one_mask)];
refill(c);
return one_mask&1;
#endif
}
#endif /* FFMPEG_RANGECODER_H */
@@ -3,19 +3,21 @@
* *
* Copyright (c) 2002-2004 Michael Niedermayer <[email protected]> * Copyright (c) 2002-2004 Michael Niedermayer <[email protected]>
* *
* This library is free software; you can redistribute it and/or * 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 * modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either * License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version. * version 2.1 of the License, or (at your option) any later version.
* *
* This library is distributed in the hope that it will be useful, * FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details. * Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software * License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
/** /**
@@ -25,9 +27,11 @@
#include "avcodec.h" #include "avcodec.h"
#include "dsputil.h" #include "dsputil.h"
#include "ratecontrol.h"
#include "mpegvideo.h" #include "mpegvideo.h"
#include "eval.h"
#undef NDEBUG // allways check asserts, the speed effect is far too small to disable them #undef NDEBUG // Always check asserts, the speed effect is far too small to disable them.
#include <assert.h> #include <assert.h>
#ifndef M_E #ifndef M_E
@@ -38,18 +42,76 @@ static int init_pass2(MpegEncContext *s);
static double get_qscale(MpegEncContext *s, RateControlEntry *rce, double rate_factor, int frame_num); static double get_qscale(MpegEncContext *s, RateControlEntry *rce, double rate_factor, int frame_num);
void ff_write_pass1_stats(MpegEncContext *s){ void ff_write_pass1_stats(MpegEncContext *s){
sprintf(s->avctx->stats_out, "in:%d out:%d type:%d q:%d itex:%d ptex:%d mv:%d misc:%d fcode:%d bcode:%d mc-var:%d var:%d icount:%d;\n", snprintf(s->avctx->stats_out, 256, "in:%d out:%d type:%d q:%d itex:%d ptex:%d mv:%d misc:%d fcode:%d bcode:%d mc-var:%d var:%d icount:%d skipcount:%d hbits:%d;\n",
s->current_picture_ptr->display_picture_number, s->current_picture_ptr->coded_picture_number, s->pict_type, s->current_picture_ptr->display_picture_number, s->current_picture_ptr->coded_picture_number, s->pict_type,
s->current_picture.quality, s->i_tex_bits, s->p_tex_bits, s->mv_bits, s->misc_bits, s->current_picture.quality, s->i_tex_bits, s->p_tex_bits, s->mv_bits, s->misc_bits,
s->f_code, s->b_code, s->current_picture.mc_mb_var_sum, s->current_picture.mb_var_sum, s->i_count); s->f_code, s->b_code, s->current_picture.mc_mb_var_sum, s->current_picture.mb_var_sum, s->i_count, s->skip_count, s->header_bits);
}
static inline double qp2bits(RateControlEntry *rce, double qp){
if(qp<=0.0){
av_log(NULL, AV_LOG_ERROR, "qp<=0.0\n");
}
return rce->qscale * (double)(rce->i_tex_bits + rce->p_tex_bits+1)/ qp;
}
static inline double bits2qp(RateControlEntry *rce, double bits){
if(bits<0.9){
av_log(NULL, AV_LOG_ERROR, "bits<0.9\n");
}
return rce->qscale * (double)(rce->i_tex_bits + rce->p_tex_bits+1)/ bits;
} }
int ff_rate_control_init(MpegEncContext *s) int ff_rate_control_init(MpegEncContext *s)
{ {
RateControlContext *rcc= &s->rc_context; RateControlContext *rcc= &s->rc_context;
int i; int i;
const char *error = NULL;
static const char * const const_names[]={
"PI",
"E",
"iTex",
"pTex",
"tex",
"mv",
"fCode",
"iCount",
"mcVar",
"var",
"isI",
"isP",
"isB",
"avgQP",
"qComp",
/* "lastIQP",
"lastPQP",
"lastBQP",
"nextNonBQP",*/
"avgIITex",
"avgPITex",
"avgPPTex",
"avgBPTex",
"avgTex",
NULL
};
static double (*func1[])(void *, double)={
(void *)bits2qp,
(void *)qp2bits,
NULL
};
static const char * const func1_names[]={
"bits2qp",
"qp2bits",
NULL
};
emms_c(); emms_c();
rcc->rc_eq_eval = ff_parse(s->avctx->rc_eq ? s->avctx->rc_eq : "tex^qComp", const_names, func1, func1_names, NULL, NULL, &error);
if (!rcc->rc_eq_eval) {
av_log(s->avctx, AV_LOG_ERROR, "Error parsing rc_eq \"%s\": %s\n", s->avctx->rc_eq, error? error : "");
return -1;
}
for(i=0; i<5; i++){ for(i=0; i<5; i++){
rcc->pred[i].coeff= FF_QP2LAMBDA * 7.0; rcc->pred[i].coeff= FF_QP2LAMBDA * 7.0;
rcc->pred[i].count= 1.0; rcc->pred[i].count= 1.0;
@@ -59,7 +121,7 @@ int ff_rate_control_init(MpegEncContext *s)
rcc->p_cplx_sum [i]= rcc->p_cplx_sum [i]=
rcc->mv_bits_sum[i]= rcc->mv_bits_sum[i]=
rcc->qscale_sum [i]= rcc->qscale_sum [i]=
rcc->frame_count[i]= 1; // 1 is better cuz of 1/0 and such rcc->frame_count[i]= 1; // 1 is better because of 1/0 and such
rcc->last_qscale_for[i]=FF_QP2LAMBDA * 5; rcc->last_qscale_for[i]=FF_QP2LAMBDA * 5;
} }
rcc->buffer_index= s->avctx->rc_initial_buffer_occupancy; rcc->buffer_index= s->avctx->rc_initial_buffer_occupancy;
@@ -74,13 +136,15 @@ int ff_rate_control_init(MpegEncContext *s)
p= strchr(p+1, ';'); p= strchr(p+1, ';');
} }
i+= s->max_b_frames; i+= s->max_b_frames;
rcc->entry = (RateControlEntry*)av_mallocz(i*sizeof(RateControlEntry)); if(i<=0 || i>=INT_MAX / sizeof(RateControlEntry))
return -1;
rcc->entry = av_mallocz(i*sizeof(RateControlEntry));
rcc->num_entries= i; rcc->num_entries= i;
/* init all to skiped p frames (with b frames we might have a not encoded frame at the end FIXME) */ /* init all to skipped p frames (with b frames we might have a not encoded frame at the end FIXME) */
for(i=0; i<rcc->num_entries; i++){ for(i=0; i<rcc->num_entries; i++){
RateControlEntry *rce= &rcc->entry[i]; RateControlEntry *rce= &rcc->entry[i];
rce->pict_type= rce->new_pict_type=P_TYPE; rce->pict_type= rce->new_pict_type=FF_P_TYPE;
rce->qscale= rce->new_qscale=FF_QP2LAMBDA * 2; rce->qscale= rce->new_qscale=FF_QP2LAMBDA * 2;
rce->misc_bits= s->mb_num + 10; rce->misc_bits= s->mb_num + 10;
rce->mb_var_sum= s->mb_num*100; rce->mb_var_sum= s->mb_num*100;
@@ -96,7 +160,7 @@ int ff_rate_control_init(MpegEncContext *s)
next= strchr(p, ';'); next= strchr(p, ';');
if(next){ if(next){
(*next)=0; //sscanf in unbelieavle slow on looong strings //FIXME copy / dont write (*next)=0; //sscanf in unbelievably slow on looong strings //FIXME copy / do not write
next++; next++;
} }
e= sscanf(p, " in:%d ", &picture_number); e= sscanf(p, " in:%d ", &picture_number);
@@ -105,17 +169,28 @@ int ff_rate_control_init(MpegEncContext *s)
assert(picture_number < rcc->num_entries); assert(picture_number < rcc->num_entries);
rce= &rcc->entry[picture_number]; rce= &rcc->entry[picture_number];
e+=sscanf(p, " in:%*d out:%*d type:%d q:%f itex:%d ptex:%d mv:%d misc:%d fcode:%d bcode:%d mc-var:%d var:%d icount:%d", e+=sscanf(p, " in:%*d out:%*d type:%d q:%f itex:%d ptex:%d mv:%d misc:%d fcode:%d bcode:%d mc-var:%d var:%d icount:%d skipcount:%d hbits:%d",
&rce->pict_type, &rce->qscale, &rce->i_tex_bits, &rce->p_tex_bits, &rce->mv_bits, &rce->misc_bits, &rce->pict_type, &rce->qscale, &rce->i_tex_bits, &rce->p_tex_bits, &rce->mv_bits, &rce->misc_bits,
&rce->f_code, &rce->b_code, &rce->mc_mb_var_sum, &rce->mb_var_sum, &rce->i_count); &rce->f_code, &rce->b_code, &rce->mc_mb_var_sum, &rce->mb_var_sum, &rce->i_count, &rce->skip_count, &rce->header_bits);
if(e!=12){ if(e!=14){
av_log(s->avctx, AV_LOG_ERROR, "statistics are damaged at line %d, parser out=%d\n", i, e); av_log(s->avctx, AV_LOG_ERROR, "statistics are damaged at line %d, parser out=%d\n", i, e);
return -1; return -1;
} }
p= next; p= next;
} }
if(init_pass2(s) < 0) return -1; if(init_pass2(s) < 0) return -1;
//FIXME maybe move to end
if((s->flags&CODEC_FLAG_PASS2) && s->avctx->rc_strategy == FF_RC_STRATEGY_XVID) {
#ifdef CONFIG_LIBXVID
return ff_xvid_rate_control_init(s);
#else
av_log(s->avctx, AV_LOG_ERROR, "Xvid ratecontrol requires libavcodec compiled with Xvid support.\n");
return -1;
#endif
}
} }
if(!(s->flags&CODEC_FLAG_PASS2)){ if(!(s->flags&CODEC_FLAG_PASS2)){
@@ -126,6 +201,10 @@ int ff_rate_control_init(MpegEncContext *s)
rcc->pass1_rc_eq_output_sum= 0.001; rcc->pass1_rc_eq_output_sum= 0.001;
rcc->pass1_wanted_bits=0.001; rcc->pass1_wanted_bits=0.001;
if(s->avctx->qblur > 1.0){
av_log(s->avctx, AV_LOG_ERROR, "qblur too large\n");
return -1;
}
/* init stuff with the user specified complexity */ /* init stuff with the user specified complexity */
if(s->avctx->rc_initial_cplx){ if(s->avctx->rc_initial_cplx){
for(i=0; i<60*30; i++){ for(i=0; i<60*30; i++){
@@ -133,9 +212,9 @@ int ff_rate_control_init(MpegEncContext *s)
RateControlEntry rce; RateControlEntry rce;
double q; double q;
if (i%((s->gop_size+3)/4)==0) rce.pict_type= I_TYPE; if (i%((s->gop_size+3)/4)==0) rce.pict_type= FF_I_TYPE;
else if(i%(s->max_b_frames+1)) rce.pict_type= B_TYPE; else if(i%(s->max_b_frames+1)) rce.pict_type= FF_B_TYPE;
else rce.pict_type= P_TYPE; else rce.pict_type= FF_P_TYPE;
rce.new_pict_type= rce.pict_type; rce.new_pict_type= rce.pict_type;
rce.mc_mb_var_sum= bits*s->mb_num/100000; rce.mc_mb_var_sum= bits*s->mb_num/100000;
@@ -145,7 +224,7 @@ int ff_rate_control_init(MpegEncContext *s)
rce.b_code = 1; rce.b_code = 1;
rce.misc_bits= 1; rce.misc_bits= 1;
if(s->pict_type== I_TYPE){ if(s->pict_type== FF_I_TYPE){
rce.i_count = s->mb_num; rce.i_count = s->mb_num;
rce.i_tex_bits= bits; rce.i_tex_bits= bits;
rce.p_tex_bits= 0; rce.p_tex_bits= 0;
@@ -164,7 +243,7 @@ int ff_rate_control_init(MpegEncContext *s)
bits= rce.i_tex_bits + rce.p_tex_bits; bits= rce.i_tex_bits + rce.p_tex_bits;
q= get_qscale(s, &rce, rcc->pass1_wanted_bits/rcc->pass1_rc_eq_output_sum, i); q= get_qscale(s, &rce, rcc->pass1_wanted_bits/rcc->pass1_rc_eq_output_sum, i);
rcc->pass1_wanted_bits+= s->bit_rate/(s->avctx->frame_rate / (double)s->avctx->frame_rate_base); rcc->pass1_wanted_bits+= s->bit_rate/(1/av_q2d(s->avctx->time_base)); //FIXME misbehaves a little for variable fps
} }
} }
@@ -178,26 +257,18 @@ void ff_rate_control_uninit(MpegEncContext *s)
RateControlContext *rcc= &s->rc_context; RateControlContext *rcc= &s->rc_context;
emms_c(); emms_c();
ff_eval_free(rcc->rc_eq_eval);
av_freep(&rcc->entry); av_freep(&rcc->entry);
}
static inline double qp2bits(RateControlEntry *rce, double qp){ #ifdef CONFIG_LIBXVID
if(qp<=0.0){ if((s->flags&CODEC_FLAG_PASS2) && s->avctx->rc_strategy == FF_RC_STRATEGY_XVID)
av_log(NULL, AV_LOG_ERROR, "qp<=0.0\n"); ff_xvid_rate_control_uninit(s);
} #endif
return rce->qscale * (double)(rce->i_tex_bits + rce->p_tex_bits+1)/ qp;
}
static inline double bits2qp(RateControlEntry *rce, double bits){
if(bits<0.9){
av_log(NULL, AV_LOG_ERROR, "bits<0.9\n");
}
return rce->qscale * (double)(rce->i_tex_bits + rce->p_tex_bits+1)/ bits;
} }
int ff_vbv_update(MpegEncContext *s, int frame_size){ int ff_vbv_update(MpegEncContext *s, int frame_size){
RateControlContext *rcc= &s->rc_context; RateControlContext *rcc= &s->rc_context;
const double fps= (double)s->avctx->frame_rate / (double)s->avctx->frame_rate_base; const double fps= 1/av_q2d(s->avctx->time_base);
const int buffer_size= s->avctx->rc_buffer_size; const int buffer_size= s->avctx->rc_buffer_size;
const double min_rate= s->avctx->rc_min_rate/fps; const double min_rate= s->avctx->rc_min_rate/fps;
const double max_rate= s->avctx->rc_max_rate/fps; const double max_rate= s->avctx->rc_max_rate/fps;
@@ -213,7 +284,7 @@ int ff_vbv_update(MpegEncContext *s, int frame_size){
} }
left= buffer_size - rcc->buffer_index - 1; left= buffer_size - rcc->buffer_index - 1;
rcc->buffer_index += clip(left, min_rate, max_rate); rcc->buffer_index += av_clip(left, min_rate, max_rate);
if(rcc->buffer_index > buffer_size){ if(rcc->buffer_index > buffer_size){
int stuffing= ceil((rcc->buffer_index - buffer_size)/8); int stuffing= ceil((rcc->buffer_index - buffer_size)/8);
@@ -249,65 +320,32 @@ static double get_qscale(MpegEncContext *s, RateControlEntry *rce, double rate_f
rce->p_tex_bits*rce->qscale, rce->p_tex_bits*rce->qscale,
(rce->i_tex_bits + rce->p_tex_bits)*(double)rce->qscale, (rce->i_tex_bits + rce->p_tex_bits)*(double)rce->qscale,
rce->mv_bits/mb_num, rce->mv_bits/mb_num,
rce->pict_type == B_TYPE ? (rce->f_code + rce->b_code)*0.5 : rce->f_code, rce->pict_type == FF_B_TYPE ? (rce->f_code + rce->b_code)*0.5 : rce->f_code,
rce->i_count/mb_num, rce->i_count/mb_num,
rce->mc_mb_var_sum/mb_num, rce->mc_mb_var_sum/mb_num,
rce->mb_var_sum/mb_num, rce->mb_var_sum/mb_num,
rce->pict_type == I_TYPE, rce->pict_type == FF_I_TYPE,
rce->pict_type == P_TYPE, rce->pict_type == FF_P_TYPE,
rce->pict_type == B_TYPE, rce->pict_type == FF_B_TYPE,
rcc->qscale_sum[pict_type] / (double)rcc->frame_count[pict_type], rcc->qscale_sum[pict_type] / (double)rcc->frame_count[pict_type],
a->qcompress, a->qcompress,
/* rcc->last_qscale_for[I_TYPE], /* rcc->last_qscale_for[FF_I_TYPE],
rcc->last_qscale_for[P_TYPE], rcc->last_qscale_for[FF_P_TYPE],
rcc->last_qscale_for[B_TYPE], rcc->last_qscale_for[FF_B_TYPE],
rcc->next_non_b_qscale,*/ rcc->next_non_b_qscale,*/
rcc->i_cplx_sum[I_TYPE] / (double)rcc->frame_count[I_TYPE], rcc->i_cplx_sum[FF_I_TYPE] / (double)rcc->frame_count[FF_I_TYPE],
rcc->i_cplx_sum[P_TYPE] / (double)rcc->frame_count[P_TYPE], rcc->i_cplx_sum[FF_P_TYPE] / (double)rcc->frame_count[FF_P_TYPE],
rcc->p_cplx_sum[P_TYPE] / (double)rcc->frame_count[P_TYPE], rcc->p_cplx_sum[FF_P_TYPE] / (double)rcc->frame_count[FF_P_TYPE],
rcc->p_cplx_sum[B_TYPE] / (double)rcc->frame_count[B_TYPE], rcc->p_cplx_sum[FF_B_TYPE] / (double)rcc->frame_count[FF_B_TYPE],
(rcc->i_cplx_sum[pict_type] + rcc->p_cplx_sum[pict_type]) / (double)rcc->frame_count[pict_type], (rcc->i_cplx_sum[pict_type] + rcc->p_cplx_sum[pict_type]) / (double)rcc->frame_count[pict_type],
0 0
}; };
static const char *const_names[]={
"PI",
"E",
"iTex",
"pTex",
"tex",
"mv",
"fCode",
"iCount",
"mcVar",
"var",
"isI",
"isP",
"isB",
"avgQP",
"qComp",
/* "lastIQP",
"lastPQP",
"lastBQP",
"nextNonBQP",*/
"avgIITex",
"avgPITex",
"avgPPTex",
"avgBPTex",
"avgTex",
NULL
};
static double (*func1[])(void *, double)={
(void *)bits2qp,
(void *)qp2bits,
NULL
};
static const char *func1_names[]={
"bits2qp",
"qp2bits",
NULL
};
bits= ff_eval(s->avctx->rc_eq, const_values, const_names, func1, func1_names, NULL, NULL, rce); bits= ff_parse_eval(rcc->rc_eq_eval, const_values, rce);
if (isnan(bits)) {
av_log(s->avctx, AV_LOG_ERROR, "Error evaluating rc_eq \"%s\"\n", s->avctx->rc_eq);
return -1;
}
rcc->pass1_rc_eq_output_sum+= bits; rcc->pass1_rc_eq_output_sum+= bits;
bits*=rate_factor; bits*=rate_factor;
@@ -329,10 +367,11 @@ static double get_qscale(MpegEncContext *s, RateControlEntry *rce, double rate_f
q= bits2qp(rce, bits); q= bits2qp(rce, bits);
/* I/B difference */ /* I/B difference */
if (pict_type==I_TYPE && s->avctx->i_quant_factor<0.0) if (pict_type==FF_I_TYPE && s->avctx->i_quant_factor<0.0)
q= -q*s->avctx->i_quant_factor + s->avctx->i_quant_offset; q= -q*s->avctx->i_quant_factor + s->avctx->i_quant_offset;
else if(pict_type==B_TYPE && s->avctx->b_quant_factor<0.0) else if(pict_type==FF_B_TYPE && s->avctx->b_quant_factor<0.0)
q= -q*s->avctx->b_quant_factor + s->avctx->b_quant_offset; q= -q*s->avctx->b_quant_factor + s->avctx->b_quant_offset;
if(q<1) q=1;
return q; return q;
} }
@@ -341,16 +380,17 @@ static double get_diff_limited_q(MpegEncContext *s, RateControlEntry *rce, doubl
RateControlContext *rcc= &s->rc_context; RateControlContext *rcc= &s->rc_context;
AVCodecContext *a= s->avctx; AVCodecContext *a= s->avctx;
const int pict_type= rce->new_pict_type; const int pict_type= rce->new_pict_type;
const double last_p_q = rcc->last_qscale_for[P_TYPE]; const double last_p_q = rcc->last_qscale_for[FF_P_TYPE];
const double last_non_b_q= rcc->last_qscale_for[rcc->last_non_b_pict_type]; const double last_non_b_q= rcc->last_qscale_for[rcc->last_non_b_pict_type];
if (pict_type==I_TYPE && (a->i_quant_factor>0.0 || rcc->last_non_b_pict_type==P_TYPE)) if (pict_type==FF_I_TYPE && (a->i_quant_factor>0.0 || rcc->last_non_b_pict_type==FF_P_TYPE))
q= last_p_q *ABS(a->i_quant_factor) + a->i_quant_offset; q= last_p_q *FFABS(a->i_quant_factor) + a->i_quant_offset;
else if(pict_type==B_TYPE && a->b_quant_factor>0.0) else if(pict_type==FF_B_TYPE && a->b_quant_factor>0.0)
q= last_non_b_q* a->b_quant_factor + a->b_quant_offset; q= last_non_b_q* a->b_quant_factor + a->b_quant_offset;
if(q<1) q=1;
/* last qscale / qdiff stuff */ /* last qscale / qdiff stuff */
if(rcc->last_non_b_pict_type==pict_type || pict_type!=I_TYPE){ if(rcc->last_non_b_pict_type==pict_type || pict_type!=FF_I_TYPE){
double last_q= rcc->last_qscale_for[pict_type]; double last_q= rcc->last_qscale_for[pict_type];
const int maxdiff= FF_QP2LAMBDA * a->max_qdiff; const int maxdiff= FF_QP2LAMBDA * a->max_qdiff;
@@ -358,9 +398,9 @@ static double get_diff_limited_q(MpegEncContext *s, RateControlEntry *rce, doubl
else if(q < last_q - maxdiff) q= last_q - maxdiff; else if(q < last_q - maxdiff) q= last_q - maxdiff;
} }
rcc->last_qscale_for[pict_type]= q; //Note we cant do that after blurring rcc->last_qscale_for[pict_type]= q; //Note we cannot do that after blurring
if(pict_type!=B_TYPE) if(pict_type!=FF_B_TYPE)
rcc->last_non_b_pict_type= pict_type; rcc->last_non_b_pict_type= pict_type;
return q; return q;
@@ -375,16 +415,16 @@ static void get_qminmax(int *qmin_ret, int *qmax_ret, MpegEncContext *s, int pic
assert(qmin <= qmax); assert(qmin <= qmax);
if(pict_type==B_TYPE){ if(pict_type==FF_B_TYPE){
qmin= (int)(qmin*ABS(s->avctx->b_quant_factor)+s->avctx->b_quant_offset + 0.5); qmin= (int)(qmin*FFABS(s->avctx->b_quant_factor)+s->avctx->b_quant_offset + 0.5);
qmax= (int)(qmax*ABS(s->avctx->b_quant_factor)+s->avctx->b_quant_offset + 0.5); qmax= (int)(qmax*FFABS(s->avctx->b_quant_factor)+s->avctx->b_quant_offset + 0.5);
}else if(pict_type==I_TYPE){ }else if(pict_type==FF_I_TYPE){
qmin= (int)(qmin*ABS(s->avctx->i_quant_factor)+s->avctx->i_quant_offset + 0.5); qmin= (int)(qmin*FFABS(s->avctx->i_quant_factor)+s->avctx->i_quant_offset + 0.5);
qmax= (int)(qmax*ABS(s->avctx->i_quant_factor)+s->avctx->i_quant_offset + 0.5); qmax= (int)(qmax*FFABS(s->avctx->i_quant_factor)+s->avctx->i_quant_offset + 0.5);
} }
qmin= clip(qmin, 1, FF_LAMBDA_MAX); qmin= av_clip(qmin, 1, FF_LAMBDA_MAX);
qmax= clip(qmax, 1, FF_LAMBDA_MAX); qmax= av_clip(qmax, 1, FF_LAMBDA_MAX);
if(qmax<qmin) qmax= qmin; if(qmax<qmin) qmax= qmin;
@@ -398,14 +438,14 @@ static double modify_qscale(MpegEncContext *s, RateControlEntry *rce, double q,
double bits; double bits;
const int pict_type= rce->new_pict_type; const int pict_type= rce->new_pict_type;
const double buffer_size= s->avctx->rc_buffer_size; const double buffer_size= s->avctx->rc_buffer_size;
const double fps= (double)s->avctx->frame_rate / (double)s->avctx->frame_rate_base; const double fps= 1/av_q2d(s->avctx->time_base);
const double min_rate= s->avctx->rc_min_rate / fps; const double min_rate= s->avctx->rc_min_rate / fps;
const double max_rate= s->avctx->rc_max_rate / fps; const double max_rate= s->avctx->rc_max_rate / fps;
get_qminmax(&qmin, &qmax, s, pict_type); get_qminmax(&qmin, &qmax, s, pict_type);
/* modulation */ /* modulation */
if(s->avctx->rc_qmod_freq && frame_num%s->avctx->rc_qmod_freq==0 && pict_type==P_TYPE) if(s->avctx->rc_qmod_freq && frame_num%s->avctx->rc_qmod_freq==0 && pict_type==FF_P_TYPE)
q*= s->avctx->rc_qmod_amp; q*= s->avctx->rc_qmod_amp;
bits= qp2bits(rce, q); bits= qp2bits(rce, q);
@@ -499,13 +539,16 @@ static void adaptive_quantization(MpegEncContext *s, double q){
const float temp_cplx_masking= s->avctx->temporal_cplx_masking; const float temp_cplx_masking= s->avctx->temporal_cplx_masking;
const float spatial_cplx_masking = s->avctx->spatial_cplx_masking; const float spatial_cplx_masking = s->avctx->spatial_cplx_masking;
const float p_masking = s->avctx->p_masking; const float p_masking = s->avctx->p_masking;
const float border_masking = s->avctx->border_masking;
float bits_sum= 0.0; float bits_sum= 0.0;
float cplx_sum= 0.0; float cplx_sum= 0.0;
float cplx_tab[s->mb_num]; float cplx_tab[s->mb_num];
float bits_tab[s->mb_num]; float bits_tab[s->mb_num];
const int qmin= s->avctx->lmin; const int qmin= s->avctx->mb_lmin;
const int qmax= s->avctx->lmax; const int qmax= s->avctx->mb_lmax;
Picture * const pic= &s->current_picture; Picture * const pic= &s->current_picture;
const int mb_width = s->mb_width;
const int mb_height = s->mb_height;
for(i=0; i<s->mb_num; i++){ for(i=0; i<s->mb_num; i++){
const int mb_xy= s->mb_index2xy[i]; const int mb_xy= s->mb_index2xy[i];
@@ -513,6 +556,10 @@ static void adaptive_quantization(MpegEncContext *s, double q){
float spat_cplx= sqrt(pic->mb_var[mb_xy]); float spat_cplx= sqrt(pic->mb_var[mb_xy]);
const int lumi= pic->mb_mean[mb_xy]; const int lumi= pic->mb_mean[mb_xy];
float bits, cplx, factor; float bits, cplx, factor;
int mb_x = mb_xy % s->mb_stride;
int mb_y = mb_xy / s->mb_stride;
int mb_distance;
float mb_factor = 0.0;
#if 0 #if 0
if(spat_cplx < q/3) spat_cplx= q/3; //FIXME finetune if(spat_cplx < q/3) spat_cplx= q/3; //FIXME finetune
if(temp_cplx < q/3) temp_cplx= q/3; //FIXME finetune if(temp_cplx < q/3) temp_cplx= q/3; //FIXME finetune
@@ -534,6 +581,23 @@ static void adaptive_quantization(MpegEncContext *s, double q){
else else
factor*= (1.0 - (lumi-128)*(lumi-128)*dark_masking); factor*= (1.0 - (lumi-128)*(lumi-128)*dark_masking);
if(mb_x < mb_width/5){
mb_distance = mb_width/5 - mb_x;
mb_factor = (float)mb_distance / (float)(mb_width/5);
}else if(mb_x > 4*mb_width/5){
mb_distance = mb_x - 4*mb_width/5;
mb_factor = (float)mb_distance / (float)(mb_width/5);
}
if(mb_y < mb_height/5){
mb_distance = mb_height/5 - mb_y;
mb_factor = FFMAX(mb_factor, (float)mb_distance / (float)(mb_height/5));
}else if(mb_y > 4*mb_height/5){
mb_distance = mb_y - 4*mb_height/5;
mb_factor = FFMAX(mb_factor, (float)mb_distance / (float)(mb_height/5));
}
factor*= 1.0 - border_masking*mb_factor;
if(factor<0.00001) factor= 0.00001; if(factor<0.00001) factor= 0.00001;
bits= cplx*factor; bits= cplx*factor;
@@ -543,11 +607,12 @@ static void adaptive_quantization(MpegEncContext *s, double q){
bits_tab[i]= bits; bits_tab[i]= bits;
} }
/* handle qmin/qmax cliping */ /* handle qmin/qmax clipping */
if(s->flags&CODEC_FLAG_NORMALIZE_AQP){ if(s->flags&CODEC_FLAG_NORMALIZE_AQP){
float factor= bits_sum/cplx_sum;
for(i=0; i<s->mb_num; i++){ for(i=0; i<s->mb_num; i++){
float newq= q*cplx_tab[i]/bits_tab[i]; float newq= q*cplx_tab[i]/bits_tab[i];
newq*= bits_sum/cplx_sum; newq*= factor;
if (newq > qmax){ if (newq > qmax){
bits_sum -= bits_tab[i]; bits_sum -= bits_tab[i];
@@ -558,6 +623,8 @@ static void adaptive_quantization(MpegEncContext *s, double q){
cplx_sum -= cplx_tab[i]*q/qmin; cplx_sum -= cplx_tab[i]*q/qmin;
} }
} }
if(bits_sum < 0.001) bits_sum= 0.001;
if(cplx_sum < 0.001) cplx_sum= 0.001;
} }
for(i=0; i<s->mb_num; i++){ for(i=0; i<s->mb_num; i++){
@@ -578,9 +645,20 @@ static void adaptive_quantization(MpegEncContext *s, double q){
s->lambda_table[mb_xy]= intq; s->lambda_table[mb_xy]= intq;
} }
} }
void ff_get_2pass_fcode(MpegEncContext *s){
RateControlContext *rcc= &s->rc_context;
int picture_number= s->picture_number;
RateControlEntry *rce;
rce= &rcc->entry[picture_number];
s->f_code= rce->f_code;
s->b_code= rce->b_code;
}
//FIXME rd or at least approx for dquant //FIXME rd or at least approx for dquant
float ff_rate_estimate_qscale(MpegEncContext *s) float ff_rate_estimate_qscale(MpegEncContext *s, int dry_run)
{ {
float q; float q;
int qmin, qmax; int qmin, qmax;
@@ -600,13 +678,18 @@ float ff_rate_estimate_qscale(MpegEncContext *s)
Picture * const pic= &s->current_picture; Picture * const pic= &s->current_picture;
emms_c(); emms_c();
#ifdef CONFIG_LIBXVID
if((s->flags&CODEC_FLAG_PASS2) && s->avctx->rc_strategy == FF_RC_STRATEGY_XVID)
return ff_xvid_rate_estimate_qscale(s, dry_run);
#endif
get_qminmax(&qmin, &qmax, s, pict_type); get_qminmax(&qmin, &qmax, s, pict_type);
fps= (double)s->avctx->frame_rate / (double)s->avctx->frame_rate_base; fps= 1/av_q2d(s->avctx->time_base);
//printf("input_pic_num:%d pic_num:%d frame_rate:%d\n", s->input_picture_number, s->picture_number, s->frame_rate); //printf("input_pic_num:%d pic_num:%d frame_rate:%d\n", s->input_picture_number, s->picture_number, s->frame_rate);
/* update predictors */ /* update predictors */
if(picture_number>2){ if(picture_number>2 && !dry_run){
const int last_var= s->last_pict_type == I_TYPE ? rcc->last_mb_var_sum : rcc->last_mc_mb_var_sum; const int last_var= s->last_pict_type == FF_I_TYPE ? rcc->last_mb_var_sum : rcc->last_mc_mb_var_sum;
update_predictor(&rcc->pred[s->last_pict_type], rcc->last_qscale, sqrt(last_var), s->frame_bits); update_predictor(&rcc->pred[s->last_pict_type], rcc->last_qscale, sqrt(last_var), s->frame_bits);
} }
@@ -616,19 +699,34 @@ float ff_rate_estimate_qscale(MpegEncContext *s)
rce= &rcc->entry[picture_number]; rce= &rcc->entry[picture_number];
wanted_bits= rce->expected_bits; wanted_bits= rce->expected_bits;
}else{ }else{
Picture *dts_pic;
rce= &local_rce; rce= &local_rce;
wanted_bits= (uint64_t)(s->bit_rate*(double)picture_number/fps);
//FIXME add a dts field to AVFrame and ensure its set and use it here instead of reordering
//but the reordering is simpler for now until h.264 b pyramid must be handeld
if(s->pict_type == FF_B_TYPE || s->low_delay)
dts_pic= s->current_picture_ptr;
else
dts_pic= s->last_picture_ptr;
//if(dts_pic)
// av_log(NULL, AV_LOG_ERROR, "%Ld %Ld %Ld %d\n", s->current_picture_ptr->pts, s->user_specified_pts, dts_pic->pts, picture_number);
if(!dts_pic || dts_pic->pts == AV_NOPTS_VALUE)
wanted_bits= (uint64_t)(s->bit_rate*(double)picture_number/fps);
else
wanted_bits= (uint64_t)(s->bit_rate*(double)dts_pic->pts/fps);
} }
diff= s->total_bits - wanted_bits; diff= s->total_bits - wanted_bits;
br_compensation= (a->bit_rate_tolerance - diff)/a->bit_rate_tolerance; br_compensation= (a->bit_rate_tolerance - diff)/a->bit_rate_tolerance;
if(br_compensation<=0.0) br_compensation=0.001; if(br_compensation<=0.0) br_compensation=0.001;
var= pict_type == I_TYPE ? pic->mb_var_sum : pic->mc_mb_var_sum; var= pict_type == FF_I_TYPE ? pic->mb_var_sum : pic->mc_mb_var_sum;
short_term_q = 0; /* avoid warning */ short_term_q = 0; /* avoid warning */
if(s->flags&CODEC_FLAG_PASS2){ if(s->flags&CODEC_FLAG_PASS2){
if(pict_type!=I_TYPE) if(pict_type!=FF_I_TYPE)
assert(pict_type == rce->new_pict_type); assert(pict_type == rce->new_pict_type);
q= rce->new_qscale / br_compensation; q= rce->new_qscale / br_compensation;
@@ -644,7 +742,7 @@ float ff_rate_estimate_qscale(MpegEncContext *s)
rce->misc_bits= 1; rce->misc_bits= 1;
bits= predict_size(&rcc->pred[pict_type], rce->qscale, sqrt(var)); bits= predict_size(&rcc->pred[pict_type], rce->qscale, sqrt(var));
if(pict_type== I_TYPE){ if(pict_type== FF_I_TYPE){
rce->i_count = s->mb_num; rce->i_count = s->mb_num;
rce->i_tex_bits= bits; rce->i_tex_bits= bits;
rce->p_tex_bits= 0; rce->p_tex_bits= 0;
@@ -665,6 +763,8 @@ float ff_rate_estimate_qscale(MpegEncContext *s)
rate_factor= rcc->pass1_wanted_bits/rcc->pass1_rc_eq_output_sum * br_compensation; rate_factor= rcc->pass1_wanted_bits/rcc->pass1_rc_eq_output_sum * br_compensation;
q= get_qscale(s, rce, rate_factor, picture_number); q= get_qscale(s, rce, rate_factor, picture_number);
if (q < 0)
return -1;
assert(q>0.0); assert(q>0.0);
//printf("%f ", q); //printf("%f ", q);
@@ -672,7 +772,7 @@ float ff_rate_estimate_qscale(MpegEncContext *s)
//printf("%f ", q); //printf("%f ", q);
assert(q>0.0); assert(q>0.0);
if(pict_type==P_TYPE || s->intra_only){ //FIXME type dependant blur like in 2-pass if(pict_type==FF_P_TYPE || s->intra_only){ //FIXME type dependent blur like in 2-pass
rcc->short_term_qsum*=a->qblur; rcc->short_term_qsum*=a->qblur;
rcc->short_term_qcount*=a->qblur; rcc->short_term_qcount*=a->qblur;
@@ -706,9 +806,11 @@ float ff_rate_estimate_qscale(MpegEncContext *s)
else else
q= (int)(q + 0.5); q= (int)(q + 0.5);
rcc->last_qscale= q; if(!dry_run){
rcc->last_mc_mb_var_sum= pic->mc_mb_var_sum; rcc->last_qscale= q;
rcc->last_mb_var_sum= pic->mb_var_sum; rcc->last_mc_mb_var_sum= pic->mc_mb_var_sum;
rcc->last_mb_var_sum= pic->mb_var_sum;
}
#if 0 #if 0
{ {
static int mvsum=0, texsum=0; static int mvsum=0, texsum=0;
@@ -727,12 +829,10 @@ static int init_pass2(MpegEncContext *s)
{ {
RateControlContext *rcc= &s->rc_context; RateControlContext *rcc= &s->rc_context;
AVCodecContext *a= s->avctx; AVCodecContext *a= s->avctx;
int i; int i, toobig;
double fps= (double)s->avctx->frame_rate / (double)s->avctx->frame_rate_base; double fps= 1/av_q2d(s->avctx->time_base);
double complexity[5]={0,0,0,0,0}; // aproximate bits at quant=1 double complexity[5]={0,0,0,0,0}; // aproximate bits at quant=1
double avg_quantizer[5]; uint64_t const_bits[5]={0,0,0,0,0}; // quantizer independent bits
uint64_t const_bits[5]={0,0,0,0,0}; // quantizer idependant bits
uint64_t available_bits[5];
uint64_t all_const_bits; uint64_t all_const_bits;
uint64_t all_available_bits= (uint64_t)(s->bit_rate*(double)rcc->num_entries/fps); uint64_t all_available_bits= (uint64_t)(s->bit_rate*(double)rcc->num_entries/fps);
double rate_factor=0; double rate_factor=0;
@@ -740,7 +840,7 @@ static int init_pass2(MpegEncContext *s)
//int last_i_frame=-10000000; //int last_i_frame=-10000000;
const int filter_size= (int)(a->qblur*4) | 1; const int filter_size= (int)(a->qblur*4) | 1;
double expected_bits; double expected_bits;
double *qscale, *blured_qscale; double *qscale, *blurred_qscale, qscale_sum;
/* find complexity & const_bits & decide the pict_types */ /* find complexity & const_bits & decide the pict_types */
for(i=0; i<rcc->num_entries; i++){ for(i=0; i<rcc->num_entries; i++){
@@ -755,40 +855,16 @@ static int init_pass2(MpegEncContext *s)
complexity[rce->new_pict_type]+= (rce->i_tex_bits+ rce->p_tex_bits)*(double)rce->qscale; complexity[rce->new_pict_type]+= (rce->i_tex_bits+ rce->p_tex_bits)*(double)rce->qscale;
const_bits[rce->new_pict_type]+= rce->mv_bits + rce->misc_bits; const_bits[rce->new_pict_type]+= rce->mv_bits + rce->misc_bits;
} }
all_const_bits= const_bits[I_TYPE] + const_bits[P_TYPE] + const_bits[B_TYPE]; all_const_bits= const_bits[FF_I_TYPE] + const_bits[FF_P_TYPE] + const_bits[FF_B_TYPE];
if(all_available_bits < all_const_bits){ if(all_available_bits < all_const_bits){
av_log(s->avctx, AV_LOG_ERROR, "requested bitrate is to low\n"); av_log(s->avctx, AV_LOG_ERROR, "requested bitrate is too low\n");
return -1; return -1;
} }
/* find average quantizers */
avg_quantizer[P_TYPE]=0;
for(step=256*256; step>0.0000001; step*=0.5){
double expected_bits=0;
avg_quantizer[P_TYPE]+= step;
avg_quantizer[I_TYPE]= avg_quantizer[P_TYPE]*ABS(s->avctx->i_quant_factor) + s->avctx->i_quant_offset;
avg_quantizer[B_TYPE]= avg_quantizer[P_TYPE]*ABS(s->avctx->b_quant_factor) + s->avctx->b_quant_offset;
expected_bits=
+ all_const_bits
+ complexity[I_TYPE]/avg_quantizer[I_TYPE]
+ complexity[P_TYPE]/avg_quantizer[P_TYPE]
+ complexity[B_TYPE]/avg_quantizer[B_TYPE];
if(expected_bits < all_available_bits) avg_quantizer[P_TYPE]-= step;
//printf("%f %lld %f\n", expected_bits, all_available_bits, avg_quantizer[P_TYPE]);
}
//printf("qp_i:%f, qp_p:%f, qp_b:%f\n", avg_quantizer[I_TYPE],avg_quantizer[P_TYPE],avg_quantizer[B_TYPE]);
for(i=0; i<5; i++){
available_bits[i]= const_bits[i] + complexity[i]/avg_quantizer[i];
}
//printf("%lld %lld %lld %lld\n", available_bits[I_TYPE], available_bits[P_TYPE], available_bits[B_TYPE], all_available_bits);
qscale= av_malloc(sizeof(double)*rcc->num_entries); qscale= av_malloc(sizeof(double)*rcc->num_entries);
blured_qscale= av_malloc(sizeof(double)*rcc->num_entries); blurred_qscale= av_malloc(sizeof(double)*rcc->num_entries);
toobig = 0;
for(step=256*256; step>0.0000001; step*=0.5){ for(step=256*256; step>0.0000001; step*=0.5){
expected_bits=0; expected_bits=0;
@@ -826,30 +902,62 @@ static int init_pass2(MpegEncContext *s)
q+= qscale[index] * coeff; q+= qscale[index] * coeff;
sum+= coeff; sum+= coeff;
} }
blured_qscale[i]= q/sum; blurred_qscale[i]= q/sum;
} }
/* find expected bits */ /* find expected bits */
for(i=0; i<rcc->num_entries; i++){ for(i=0; i<rcc->num_entries; i++){
RateControlEntry *rce= &rcc->entry[i]; RateControlEntry *rce= &rcc->entry[i];
double bits; double bits;
rce->new_qscale= modify_qscale(s, rce, blured_qscale[i], i); rce->new_qscale= modify_qscale(s, rce, blurred_qscale[i], i);
bits= qp2bits(rce, rce->new_qscale) + rce->mv_bits + rce->misc_bits; bits= qp2bits(rce, rce->new_qscale) + rce->mv_bits + rce->misc_bits;
//printf("%d %f\n", rce->new_bits, blured_qscale[i]); //printf("%d %f\n", rce->new_bits, blurred_qscale[i]);
bits += 8*ff_vbv_update(s, bits); bits += 8*ff_vbv_update(s, bits);
rce->expected_bits= expected_bits; rce->expected_bits= expected_bits;
expected_bits += bits; expected_bits += bits;
} }
// printf("%f %d %f\n", expected_bits, (int)all_available_bits, rate_factor); /*
if(expected_bits > all_available_bits) rate_factor-= step; av_log(s->avctx, AV_LOG_INFO,
"expected_bits: %f all_available_bits: %d rate_factor: %f\n",
expected_bits, (int)all_available_bits, rate_factor);
*/
if(expected_bits > all_available_bits) {
rate_factor-= step;
++toobig;
}
} }
av_free(qscale); av_free(qscale);
av_free(blured_qscale); av_free(blurred_qscale);
if(abs(expected_bits/all_available_bits - 1.0) > 0.01 ){ /* check bitrate calculations and print info */
av_log(s->avctx, AV_LOG_ERROR, "Error: 2pass curve failed to converge\n"); qscale_sum = 0.0;
for(i=0; i<rcc->num_entries; i++){
/* av_log(s->avctx, AV_LOG_DEBUG, "[lavc rc] entry[%d].new_qscale = %.3f qp = %.3f\n",
i, rcc->entry[i].new_qscale, rcc->entry[i].new_qscale / FF_QP2LAMBDA); */
qscale_sum += av_clip(rcc->entry[i].new_qscale / FF_QP2LAMBDA, s->avctx->qmin, s->avctx->qmax);
}
assert(toobig <= 40);
av_log(s->avctx, AV_LOG_DEBUG,
"[lavc rc] requested bitrate: %d bps expected bitrate: %d bps\n",
s->bit_rate,
(int)(expected_bits / ((double)all_available_bits/s->bit_rate)));
av_log(s->avctx, AV_LOG_DEBUG,
"[lavc rc] estimated target average qp: %.3f\n",
(float)qscale_sum / rcc->num_entries);
if (toobig == 0) {
av_log(s->avctx, AV_LOG_INFO,
"[lavc rc] Using all of requested bitrate is not "
"necessary for this video with these parameters.\n");
} else if (toobig == 40) {
av_log(s->avctx, AV_LOG_ERROR,
"[lavc rc] Error: bitrate too low for this video "
"with these parameters.\n");
return -1;
} else if (fabs(expected_bits/all_available_bits - 1.0) > 0.01) {
av_log(s->avctx, AV_LOG_ERROR,
"[lavc rc] Error: 2pass curve failed to converge\n");
return -1; return -1;
} }
@@ -0,0 +1,105 @@
/*
* Ratecontrol
* Copyright (c) 2000, 2001, 2002 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
*/
#ifndef FFMPEG_RATECONTROL_H
#define FFMPEG_RATECONTROL_H
/**
* @file ratecontrol.h
* ratecontrol header.
*/
#include <stdio.h>
#include <stdint.h>
#include "eval.h"
typedef struct Predictor{
double coeff;
double count;
double decay;
} Predictor;
typedef struct RateControlEntry{
int pict_type;
float qscale;
int mv_bits;
int i_tex_bits;
int p_tex_bits;
int misc_bits;
int header_bits;
uint64_t expected_bits;
int new_pict_type;
float new_qscale;
int mc_mb_var_sum;
int mb_var_sum;
int i_count;
int skip_count;
int f_code;
int b_code;
}RateControlEntry;
/**
* rate control context.
*/
typedef struct RateControlContext{
FILE *stats_file;
int num_entries; ///< number of RateControlEntries
RateControlEntry *entry;
double buffer_index; ///< amount of bits in the video/audio buffer
Predictor pred[5];
double short_term_qsum; ///< sum of recent qscales
double short_term_qcount; ///< count of recent qscales
double pass1_rc_eq_output_sum;///< sum of the output of the rc equation, this is used for normalization
double pass1_wanted_bits; ///< bits which should have been outputed by the pass1 code (including complexity init)
double last_qscale;
double last_qscale_for[5]; ///< last qscale for a specific pict type, used for max_diff & ipb factor stuff
int last_mc_mb_var_sum;
int last_mb_var_sum;
uint64_t i_cplx_sum[5];
uint64_t p_cplx_sum[5];
uint64_t mv_bits_sum[5];
uint64_t qscale_sum[5];
int frame_count[5];
int last_non_b_pict_type;
void *non_lavc_opaque; ///< context for non lavc rc code (for example xvid)
float dry_run_qscale; ///< for xvid rc
int last_picture_number; ///< for xvid rc
AVEvalExpr * rc_eq_eval;
}RateControlContext;
struct MpegEncContext;
/* rate control */
int ff_rate_control_init(struct MpegEncContext *s);
float ff_rate_estimate_qscale(struct MpegEncContext *s, int dry_run);
void ff_write_pass1_stats(struct MpegEncContext *s);
void ff_rate_control_uninit(struct MpegEncContext *s);
int ff_vbv_update(struct MpegEncContext *s, int frame_size);
void ff_get_2pass_fcode(struct MpegEncContext *s);
int ff_xvid_rate_control_init(struct MpegEncContext *s);
void ff_xvid_rate_control_uninit(struct MpegEncContext *s);
float ff_xvid_rate_estimate_qscale(struct MpegEncContext *s, int dry_run);
#endif /* FFMPEG_RATECONTROL_H */
@@ -2,19 +2,21 @@
* Raw Video Codec * Raw Video Codec
* Copyright (c) 2001 Fabrice Bellard. * Copyright (c) 2001 Fabrice Bellard.
* *
* This library is free software; you can redistribute it and/or * 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 * modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either * License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version. * version 2.1 of the License, or (at your option) any later version.
* *
* This library is distributed in the hope that it will be useful, * FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details. * Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software * License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
/** /**
@@ -23,22 +25,12 @@
*/ */
#include "avcodec.h" #include "avcodec.h"
#include "raw.h"
typedef struct RawVideoContext { const PixelFormatTag ff_raw_pixelFormatTags[] = {
unsigned char * buffer; /* block of memory for holding one frame */
unsigned char * p; /* current position in buffer */
int length; /* number of bytes in buffer */
AVFrame pic; ///< AVCodecContext.coded_frame
} RawVideoContext;
typedef struct PixleFormatTag {
int pix_fmt;
unsigned int fourcc;
} PixelFormatTag;
const PixelFormatTag pixelFormatTags[] = {
{ PIX_FMT_YUV420P, MKTAG('I', '4', '2', '0') }, /* Planar formats */ { PIX_FMT_YUV420P, MKTAG('I', '4', '2', '0') }, /* Planar formats */
{ PIX_FMT_YUV420P, MKTAG('I', 'Y', 'U', 'V') }, { PIX_FMT_YUV420P, MKTAG('I', 'Y', 'U', 'V') },
{ PIX_FMT_YUV420P, MKTAG('Y', 'V', '1', '2') },
{ PIX_FMT_YUV410P, MKTAG('Y', 'U', 'V', '9') }, { PIX_FMT_YUV410P, MKTAG('Y', 'U', 'V', '9') },
{ PIX_FMT_YUV411P, MKTAG('Y', '4', '1', 'B') }, { PIX_FMT_YUV411P, MKTAG('Y', '4', '1', 'B') },
{ PIX_FMT_YUV422P, MKTAG('Y', '4', '2', 'B') }, { PIX_FMT_YUV422P, MKTAG('Y', '4', '2', 'B') },
@@ -46,131 +38,30 @@ const PixelFormatTag pixelFormatTags[] = {
{ PIX_FMT_GRAY8, MKTAG(' ', ' ', 'Y', '8') }, { PIX_FMT_GRAY8, MKTAG(' ', ' ', 'Y', '8') },
{ PIX_FMT_YUV422, MKTAG('Y', '4', '2', '2') }, /* Packed formats */ { PIX_FMT_YUYV422, MKTAG('Y', 'U', 'Y', '2') }, /* Packed formats */
{ PIX_FMT_YUV422, MKTAG('U', 'Y', 'V', 'Y') }, { PIX_FMT_YUYV422, MKTAG('Y', '4', '2', '2') },
{ PIX_FMT_UYVY422, MKTAG('U', 'Y', 'V', 'Y') },
{ PIX_FMT_UYVY422, MKTAG('H', 'D', 'Y', 'C') },
{ PIX_FMT_GRAY8, MKTAG('G', 'R', 'E', 'Y') }, { PIX_FMT_GRAY8, MKTAG('G', 'R', 'E', 'Y') },
{ PIX_FMT_RGB555, MKTAG('R', 'G', 'B', 15) },
{ PIX_FMT_BGR555, MKTAG('B', 'G', 'R', 15) },
{ PIX_FMT_RGB565, MKTAG('R', 'G', 'B', 16) },
{ PIX_FMT_BGR565, MKTAG('B', 'G', 'R', 16) },
/* quicktime */
{ PIX_FMT_UYVY422, MKTAG('2', 'v', 'u', 'y') },
{ PIX_FMT_UYVY422, MKTAG('A', 'V', 'U', 'I') }, /* FIXME merge both fields */
{ -1, 0 }, { -1, 0 },
}; };
static int findPixelFormat(unsigned int fourcc) unsigned int avcodec_pix_fmt_to_codec_tag(enum PixelFormat fmt)
{ {
const PixelFormatTag * tags = pixelFormatTags; const PixelFormatTag * tags = ff_raw_pixelFormatTags;
while (tags->pix_fmt >= 0) {
if (tags->fourcc == fourcc)
return tags->pix_fmt;
tags++;
}
return PIX_FMT_YUV420P;
}
static unsigned int findFourCC(int fmt)
{
const PixelFormatTag * tags = pixelFormatTags;
while (tags->pix_fmt >= 0) { while (tags->pix_fmt >= 0) {
if (tags->pix_fmt == fmt) if (tags->pix_fmt == fmt)
return tags->fourcc; return tags->fourcc;
tags++; tags++;
} }
return 0; return 0;
} }
/* RAW Decoder Implementation */
static int raw_init_decoder(AVCodecContext *avctx)
{
RawVideoContext *context = avctx->priv_data;
if (avctx->codec_tag)
avctx->pix_fmt = findPixelFormat(avctx->codec_tag);
context->length = avpicture_get_size(avctx->pix_fmt, avctx->width, avctx->height);
context->buffer = av_malloc(context->length);
context->p = context->buffer;
context->pic.pict_type = FF_I_TYPE;
context->pic.key_frame = 1;
avctx->coded_frame= &context->pic;
if (!context->buffer)
return -1;
return 0;
}
static int raw_decode(AVCodecContext *avctx,
void *data, int *data_size,
uint8_t *buf, int buf_size)
{
RawVideoContext *context = avctx->priv_data;
int bytesNeeded;
AVPicture * picture = (AVPicture *) data;
/* Early out without copy if packet size == frame size */
if (buf_size == context->length && context->p == context->buffer) {
avpicture_fill(picture, buf, avctx->pix_fmt, avctx->width, avctx->height);
*data_size = sizeof(AVPicture);
return buf_size;
}
bytesNeeded = context->length - (context->p - context->buffer);
if (buf_size < bytesNeeded) {
memcpy(context->p, buf, buf_size);
context->p += buf_size;
*data_size = 0;
return buf_size;
}
memcpy(context->p, buf, bytesNeeded);
context->p = context->buffer;
avpicture_fill(picture, context->buffer, avctx->pix_fmt, avctx->width, avctx->height);
*data_size = sizeof(AVPicture);
return bytesNeeded;
}
static int raw_close_decoder(AVCodecContext *avctx)
{
RawVideoContext *context = avctx->priv_data;
av_freep(&context->buffer);
return 0;
}
/* RAW Encoder Implementation */
static int raw_init_encoder(AVCodecContext *avctx)
{
avctx->coded_frame = (AVFrame *)avctx->priv_data;
avctx->coded_frame->pict_type = FF_I_TYPE;
avctx->coded_frame->key_frame = 1;
avctx->codec_tag = findFourCC(avctx->pix_fmt);
return 0;
}
static int raw_encode(AVCodecContext *avctx,
unsigned char *frame, int buf_size, void *data)
{
return avpicture_layout((AVPicture *)data, avctx->pix_fmt, avctx->width,
avctx->height, frame, buf_size);
}
AVCodec rawvideo_encoder = {
"rawvideo",
CODEC_TYPE_VIDEO,
CODEC_ID_RAWVIDEO,
sizeof(AVFrame),
raw_init_encoder,
raw_encode,
};
AVCodec rawvideo_decoder = {
"rawvideo",
CODEC_TYPE_VIDEO,
CODEC_ID_RAWVIDEO,
sizeof(RawVideoContext),
raw_init_decoder,
NULL,
raw_close_decoder,
raw_decode,
};
@@ -0,0 +1,39 @@
/*
* Raw Video Codec
* Copyright (c) 2001 Fabrice Bellard.
*
* 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 raw.h
* Raw Video Codec
*/
#ifndef FFMPEG_RAW_H
#define FFMPEG_RAW_H
#include "avcodec.h"
typedef struct PixelFormatTag {
int pix_fmt;
unsigned int fourcc;
} PixelFormatTag;
extern const PixelFormatTag ff_raw_pixelFormatTags[];
#endif /* FFMPEG_RAW_H */
@@ -0,0 +1,166 @@
/*
* Raw Video Decoder
* Copyright (c) 2001 Fabrice Bellard.
*
* 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 rawdec.c
* Raw Video Decoder
*/
#include "avcodec.h"
#include "raw.h"
typedef struct RawVideoContext {
unsigned char * buffer; /* block of memory for holding one frame */
int length; /* number of bytes in buffer */
AVFrame pic; ///< AVCodecContext.coded_frame
} RawVideoContext;
static const PixelFormatTag pixelFormatBpsAVI[] = {
{ PIX_FMT_PAL8, 4 },
{ PIX_FMT_PAL8, 8 },
{ PIX_FMT_RGB555, 15 },
{ PIX_FMT_RGB555, 16 },
{ PIX_FMT_BGR24, 24 },
{ PIX_FMT_RGB32, 32 },
{ -1, 0 },
};
static const PixelFormatTag pixelFormatBpsMOV[] = {
/* FIXME fix swscaler to support those */
/* http://developer.apple.com/documentation/QuickTime/QTFF/QTFFChap3/chapter_4_section_2.html */
{ PIX_FMT_PAL8, 4 },
{ PIX_FMT_PAL8, 8 },
{ PIX_FMT_BGR555, 16 },
{ PIX_FMT_RGB24, 24 },
{ PIX_FMT_BGR32_1, 32 },
{ -1, 0 },
};
static int findPixelFormat(const PixelFormatTag *tags, unsigned int fourcc)
{
while (tags->pix_fmt >= 0) {
if (tags->fourcc == fourcc)
return tags->pix_fmt;
tags++;
}
return PIX_FMT_YUV420P;
}
static av_cold int raw_init_decoder(AVCodecContext *avctx)
{
RawVideoContext *context = avctx->priv_data;
if (avctx->codec_tag == MKTAG('r','a','w',' '))
avctx->pix_fmt = findPixelFormat(pixelFormatBpsMOV, avctx->bits_per_sample);
else if (avctx->codec_tag)
avctx->pix_fmt = findPixelFormat(ff_raw_pixelFormatTags, avctx->codec_tag);
else if (avctx->bits_per_sample)
avctx->pix_fmt = findPixelFormat(pixelFormatBpsAVI, avctx->bits_per_sample);
context->length = avpicture_get_size(avctx->pix_fmt, avctx->width, avctx->height);
context->buffer = av_malloc(context->length);
context->pic.pict_type = FF_I_TYPE;
context->pic.key_frame = 1;
avctx->coded_frame= &context->pic;
if (!context->buffer)
return -1;
return 0;
}
static void flip(AVCodecContext *avctx, AVPicture * picture){
if(!avctx->codec_tag && avctx->bits_per_sample && picture->linesize[2]==0){
picture->data[0] += picture->linesize[0] * (avctx->height-1);
picture->linesize[0] *= -1;
}
}
static int raw_decode(AVCodecContext *avctx,
void *data, int *data_size,
const uint8_t *buf, int buf_size)
{
RawVideoContext *context = avctx->priv_data;
AVFrame * frame = (AVFrame *) data;
AVPicture * picture = (AVPicture *) data;
frame->interlaced_frame = avctx->coded_frame->interlaced_frame;
frame->top_field_first = avctx->coded_frame->top_field_first;
//4bpp raw in avi and mov (yes this is ugly ...)
if(avctx->bits_per_sample == 4 && avctx->pix_fmt==PIX_FMT_PAL8 &&
(!avctx->codec_tag || avctx->codec_tag == MKTAG('r','a','w',' '))){
int i;
for(i=256*2; i+1 < context->length>>1; i++){
context->buffer[2*i+0]= buf[i-256*2]>>4;
context->buffer[2*i+1]= buf[i-256*2]&15;
}
buf= context->buffer + 256*4;
buf_size= context->length - 256*4;
}
if(buf_size < context->length - (avctx->pix_fmt==PIX_FMT_PAL8 ? 256*4 : 0))
return -1;
avpicture_fill(picture, buf, avctx->pix_fmt, avctx->width, avctx->height);
if(avctx->pix_fmt==PIX_FMT_PAL8 && buf_size < context->length){
frame->data[1]= context->buffer;
}
if (avctx->palctrl && avctx->palctrl->palette_changed) {
memcpy(frame->data[1], avctx->palctrl->palette, AVPALETTE_SIZE);
avctx->palctrl->palette_changed = 0;
}
flip(avctx, picture);
if (avctx->codec_tag == MKTAG('Y', 'V', '1', '2'))
{
// swap fields
unsigned char *tmp = picture->data[1];
picture->data[1] = picture->data[2];
picture->data[2] = tmp;
}
*data_size = sizeof(AVPicture);
return buf_size;
}
static av_cold int raw_close_decoder(AVCodecContext *avctx)
{
RawVideoContext *context = avctx->priv_data;
av_freep(&context->buffer);
return 0;
}
AVCodec rawvideo_decoder = {
"rawvideo",
CODEC_TYPE_VIDEO,
CODEC_ID_RAWVIDEO,
sizeof(RawVideoContext),
raw_init_decoder,
NULL,
raw_close_decoder,
raw_decode,
.long_name = NULL_IF_CONFIG_SMALL("raw video"),
};
@@ -0,0 +1,55 @@
/*
* Raw Video Encoder
* Copyright (c) 2001 Fabrice Bellard.
*
* 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 rawenc.c
* Raw Video Encoder
*/
#include "avcodec.h"
#include "raw.h"
static av_cold int raw_init_encoder(AVCodecContext *avctx)
{
avctx->coded_frame = (AVFrame *)avctx->priv_data;
avctx->coded_frame->pict_type = FF_I_TYPE;
avctx->coded_frame->key_frame = 1;
if(!avctx->codec_tag)
avctx->codec_tag = avcodec_pix_fmt_to_codec_tag(avctx->pix_fmt);
return 0;
}
static int raw_encode(AVCodecContext *avctx,
unsigned char *frame, int buf_size, void *data)
{
return avpicture_layout((AVPicture *)data, avctx->pix_fmt, avctx->width,
avctx->height, frame, buf_size);
}
AVCodec rawvideo_encoder = {
"rawvideo",
CODEC_TYPE_VIDEO,
CODEC_ID_RAWVIDEO,
sizeof(AVFrame),
raw_init_encoder,
raw_encode,
.long_name = NULL_IF_CONFIG_SMALL("raw video"),
};