Update avcodec to 20080825
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27547 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
31ccd4b91b
commit
66ba2a5263
@ -2,32 +2,35 @@
|
||||
* Floating point AAN DCT
|
||||
* Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* this implementation is based upon the IJG integer AAN DCT (see jfdctfst.c)
|
||||
*
|
||||
* 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 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
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* this implementation is based upon the IJG integer AAN DCT (see jfdctfst.c)
|
||||
* The AAN DCT in this file except ff_faandct248() can also be used under the
|
||||
* new (3 clause) BSD license.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file faandct.c
|
||||
* @brief
|
||||
* @brief
|
||||
* Floating point AAN DCT
|
||||
* @author Michael Niedermayer <michaelni@gmx.at>
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "dsputil.h"
|
||||
#include "faandct.h"
|
||||
|
||||
@ -59,7 +62,7 @@ for(i=0; i<8; i++){
|
||||
#define A5 0.38268343236508977170 // cos(pi*6/16)
|
||||
#define A4 1.30656296487637652774 // cos(pi*2/16)sqrt(2)
|
||||
|
||||
static FLOAT postscale[64]={
|
||||
static const FLOAT postscale[64]={
|
||||
B0*B0, B0*B1, B0*B2, B0*B3, B0*B4, B0*B5, B0*B6, B0*B7,
|
||||
B1*B0, B1*B1, B1*B2, B1*B3, B1*B4, B1*B5, B1*B6, B1*B7,
|
||||
B2*B0, B2*B1, B2*B2, B2*B3, B2*B4, B2*B5, B2*B6, B2*B7,
|
||||
@ -70,11 +73,12 @@ B6*B0, B6*B1, B6*B2, B6*B3, B6*B4, B6*B5, B6*B6, B6*B7,
|
||||
B7*B0, B7*B1, B7*B2, B7*B3, B7*B4, B7*B5, B7*B6, B7*B7,
|
||||
};
|
||||
|
||||
static always_inline void row_fdct(FLOAT temp[64], DCTELEM * data)
|
||||
static av_always_inline void row_fdct(FLOAT temp[64], DCTELEM * data)
|
||||
{
|
||||
FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
|
||||
FLOAT tmp10, tmp11, tmp12, tmp13;
|
||||
FLOAT z1, z2, z3, z4, z5, z11, z13;
|
||||
FLOAT z2, z4, z11, z13;
|
||||
FLOAT av_unused z5;
|
||||
int i;
|
||||
|
||||
for (i=0; i<8*8; i+=8) {
|
||||
@ -86,43 +90,50 @@ static always_inline void row_fdct(FLOAT temp[64], DCTELEM * data)
|
||||
tmp5= data[2 + i] - data[5 + i];
|
||||
tmp3= data[3 + i] + data[4 + i];
|
||||
tmp4= data[3 + i] - data[4 + i];
|
||||
|
||||
|
||||
tmp10= tmp0 + tmp3;
|
||||
tmp13= tmp0 - tmp3;
|
||||
tmp11= tmp1 + tmp2;
|
||||
tmp12= tmp1 - tmp2;
|
||||
|
||||
|
||||
temp[0 + i]= tmp10 + tmp11;
|
||||
temp[4 + i]= tmp10 - tmp11;
|
||||
|
||||
z1= (tmp12 + tmp13)*A1;
|
||||
temp[2 + i]= tmp13 + z1;
|
||||
temp[6 + i]= tmp13 - z1;
|
||||
|
||||
tmp10= tmp4 + tmp5;
|
||||
tmp11= tmp5 + tmp6;
|
||||
tmp12= tmp6 + tmp7;
|
||||
|
||||
z5= (tmp10 - tmp12) * A5;
|
||||
z2= tmp10*A2 + z5;
|
||||
z4= tmp12*A4 + z5;
|
||||
z3= tmp11*A1;
|
||||
tmp12 += tmp13;
|
||||
tmp12 *= A1;
|
||||
temp[2 + i]= tmp13 + tmp12;
|
||||
temp[6 + i]= tmp13 - tmp12;
|
||||
|
||||
z11= tmp7 + z3;
|
||||
z13= tmp7 - z3;
|
||||
tmp4 += tmp5;
|
||||
tmp5 += tmp6;
|
||||
tmp6 += tmp7;
|
||||
|
||||
#if 0
|
||||
z5= (tmp4 - tmp6) * A5;
|
||||
z2= tmp4*A2 + z5;
|
||||
z4= tmp6*A4 + z5;
|
||||
#else
|
||||
z2= tmp4*(A2+A5) - tmp6*A5;
|
||||
z4= tmp6*(A4-A5) + tmp4*A5;
|
||||
#endif
|
||||
tmp5*=A1;
|
||||
|
||||
z11= tmp7 + tmp5;
|
||||
z13= tmp7 - tmp5;
|
||||
|
||||
temp[5 + i]= z13 + z2;
|
||||
temp[3 + i]= z13 - z2;
|
||||
temp[1 + i]= z11 + z4;
|
||||
temp[7 + i]= z11 - z4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ff_faandct(DCTELEM * data)
|
||||
{
|
||||
FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
|
||||
FLOAT tmp10, tmp11, tmp12, tmp13;
|
||||
FLOAT z1, z2, z3, z4, z5, z11, z13;
|
||||
FLOAT z2, z4, z11, z13;
|
||||
FLOAT av_unused z5;
|
||||
FLOAT temp[64];
|
||||
int i;
|
||||
|
||||
@ -139,30 +150,36 @@ void ff_faandct(DCTELEM * data)
|
||||
tmp5= temp[8*2 + i] - temp[8*5 + i];
|
||||
tmp3= temp[8*3 + i] + temp[8*4 + i];
|
||||
tmp4= temp[8*3 + i] - temp[8*4 + i];
|
||||
|
||||
|
||||
tmp10= tmp0 + tmp3;
|
||||
tmp13= tmp0 - tmp3;
|
||||
tmp11= tmp1 + tmp2;
|
||||
tmp12= tmp1 - tmp2;
|
||||
|
||||
|
||||
data[8*0 + i]= lrintf(SCALE(8*0 + i) * (tmp10 + tmp11));
|
||||
data[8*4 + i]= lrintf(SCALE(8*4 + i) * (tmp10 - tmp11));
|
||||
|
||||
z1= (tmp12 + tmp13)* A1;
|
||||
data[8*2 + i]= lrintf(SCALE(8*2 + i) * (tmp13 + z1));
|
||||
data[8*6 + i]= lrintf(SCALE(8*6 + i) * (tmp13 - z1));
|
||||
|
||||
tmp10= tmp4 + tmp5;
|
||||
tmp11= tmp5 + tmp6;
|
||||
tmp12= tmp6 + tmp7;
|
||||
|
||||
z5= (tmp10 - tmp12) * A5;
|
||||
z2= tmp10*A2 + z5;
|
||||
z4= tmp12*A4 + z5;
|
||||
z3= tmp11*A1;
|
||||
tmp12 += tmp13;
|
||||
tmp12 *= A1;
|
||||
data[8*2 + i]= lrintf(SCALE(8*2 + i) * (tmp13 + tmp12));
|
||||
data[8*6 + i]= lrintf(SCALE(8*6 + i) * (tmp13 - tmp12));
|
||||
|
||||
z11= tmp7 + z3;
|
||||
z13= tmp7 - z3;
|
||||
tmp4 += tmp5;
|
||||
tmp5 += tmp6;
|
||||
tmp6 += tmp7;
|
||||
|
||||
#if 0
|
||||
z5= (tmp4 - tmp6) * A5;
|
||||
z2= tmp4*A2 + z5;
|
||||
z4= tmp6*A4 + z5;
|
||||
#else
|
||||
z2= tmp4*(A2+A5) - tmp6*A5;
|
||||
z4= tmp6*(A4-A5) + tmp4*A5;
|
||||
#endif
|
||||
tmp5*=A1;
|
||||
|
||||
z11= tmp7 + tmp5;
|
||||
z13= tmp7 - tmp5;
|
||||
|
||||
data[8*5 + i]= lrintf(SCALE(8*5 + i) * (z13 + z2));
|
||||
data[8*3 + i]= lrintf(SCALE(8*3 + i) * (z13 - z2));
|
||||
@ -175,7 +192,6 @@ void ff_faandct248(DCTELEM * data)
|
||||
{
|
||||
FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
|
||||
FLOAT tmp10, tmp11, tmp12, tmp13;
|
||||
FLOAT z1;
|
||||
FLOAT temp[64];
|
||||
int i;
|
||||
|
||||
@ -192,29 +208,31 @@ void ff_faandct248(DCTELEM * data)
|
||||
tmp5 = temp[8*2 + i] - temp[8*3 + i];
|
||||
tmp6 = temp[8*4 + i] - temp[8*5 + i];
|
||||
tmp7 = temp[8*6 + i] - temp[8*7 + i];
|
||||
|
||||
|
||||
tmp10 = tmp0 + tmp3;
|
||||
tmp11 = tmp1 + tmp2;
|
||||
tmp12 = tmp1 - tmp2;
|
||||
tmp13 = tmp0 - tmp3;
|
||||
|
||||
|
||||
data[8*0 + i] = lrintf(SCALE(8*0 + i) * (tmp10 + tmp11));
|
||||
data[8*4 + i] = lrintf(SCALE(8*4 + i) * (tmp10 - tmp11));
|
||||
|
||||
z1 = (tmp12 + tmp13)* A1;
|
||||
data[8*2 + i] = lrintf(SCALE(8*2 + i) * (tmp13 + z1));
|
||||
data[8*6 + i] = lrintf(SCALE(8*6 + i) * (tmp13 - z1));
|
||||
|
||||
|
||||
tmp12 += tmp13;
|
||||
tmp12 *= A1;
|
||||
data[8*2 + i] = lrintf(SCALE(8*2 + i) * (tmp13 + tmp12));
|
||||
data[8*6 + i] = lrintf(SCALE(8*6 + i) * (tmp13 - tmp12));
|
||||
|
||||
tmp10 = tmp4 + tmp7;
|
||||
tmp11 = tmp5 + tmp6;
|
||||
tmp12 = tmp5 - tmp6;
|
||||
tmp13 = tmp4 - tmp7;
|
||||
tmp11 = tmp5 + tmp6;
|
||||
tmp12 = tmp5 - tmp6;
|
||||
tmp13 = tmp4 - tmp7;
|
||||
|
||||
data[8*1 + i] = lrintf(SCALE(8*0 + i) * (tmp10 + tmp11));
|
||||
data[8*5 + i] = lrintf(SCALE(8*4 + i) * (tmp10 - tmp11));
|
||||
data[8*1 + i] = lrintf(SCALE(8*0 + i) * (tmp10 + tmp11));
|
||||
data[8*5 + i] = lrintf(SCALE(8*4 + i) * (tmp10 - tmp11));
|
||||
|
||||
z1 = (tmp12 + tmp13)* A1;
|
||||
data[8*3 + i] = lrintf(SCALE(8*2 + i) * (tmp13 + z1));
|
||||
data[8*7 + i] = lrintf(SCALE(8*6 + i) * (tmp13 - z1));
|
||||
tmp12 += tmp13;
|
||||
tmp12 *= A1;
|
||||
data[8*3 + i] = lrintf(SCALE(8*2 + i) * (tmp13 + tmp12));
|
||||
data[8*7 + i] = lrintf(SCALE(8*6 + i) * (tmp13 - tmp12));
|
||||
}
|
||||
}
|
||||
|
@ -2,30 +2,38 @@
|
||||
* Floating point AAN DCT
|
||||
* Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at>
|
||||
*
|
||||
* 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
|
||||
* 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
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file faandct.h
|
||||
* @brief
|
||||
* @brief
|
||||
* Floating point AAN DCT
|
||||
* @author Michael Niedermayer <michaelni@gmx.at>
|
||||
*/
|
||||
|
||||
|
||||
#ifndef FFMPEG_FAANDCT_H
|
||||
#define FFMPEG_FAANDCT_H
|
||||
|
||||
#include "dsputil.h"
|
||||
|
||||
#define FAAN_POSTSCALE
|
||||
|
||||
|
||||
void ff_faandct(DCTELEM * data);
|
||||
void ff_faandct248(DCTELEM * data);
|
||||
|
||||
#endif /* FFMPEG_FAANDCT_H */
|
||||
|
168
src/add-ons/media/plugins/avcodec/libavcodec/faanidct.c
Normal file
168
src/add-ons/media/plugins/avcodec/libavcodec/faanidct.c
Normal file
@ -0,0 +1,168 @@
|
||||
/*
|
||||
* Floating point AAN IDCT
|
||||
* Copyright (c) 2008 Michael Niedermayer <michaelni@gmx.at>
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
#include "faanidct.h"
|
||||
|
||||
/* To allow switching to double. */
|
||||
#define FLOAT float
|
||||
|
||||
#define B0 1.0000000000000000000000
|
||||
#define B1 1.3870398453221474618216 // cos(pi*1/16)sqrt(2)
|
||||
#define B2 1.3065629648763765278566 // cos(pi*2/16)sqrt(2)
|
||||
#define B3 1.1758756024193587169745 // cos(pi*3/16)sqrt(2)
|
||||
#define B4 1.0000000000000000000000 // cos(pi*4/16)sqrt(2)
|
||||
#define B5 0.7856949583871021812779 // cos(pi*5/16)sqrt(2)
|
||||
#define B6 0.5411961001461969843997 // cos(pi*6/16)sqrt(2)
|
||||
#define B7 0.2758993792829430123360 // cos(pi*7/16)sqrt(2)
|
||||
|
||||
#define A4 0.70710678118654752438 // cos(pi*4/16)
|
||||
#define A2 0.92387953251128675613 // cos(pi*2/16)
|
||||
|
||||
static const FLOAT prescale[64]={
|
||||
B0*B0/8, B0*B1/8, B0*B2/8, B0*B3/8, B0*B4/8, B0*B5/8, B0*B6/8, B0*B7/8,
|
||||
B1*B0/8, B1*B1/8, B1*B2/8, B1*B3/8, B1*B4/8, B1*B5/8, B1*B6/8, B1*B7/8,
|
||||
B2*B0/8, B2*B1/8, B2*B2/8, B2*B3/8, B2*B4/8, B2*B5/8, B2*B6/8, B2*B7/8,
|
||||
B3*B0/8, B3*B1/8, B3*B2/8, B3*B3/8, B3*B4/8, B3*B5/8, B3*B6/8, B3*B7/8,
|
||||
B4*B0/8, B4*B1/8, B4*B2/8, B4*B3/8, B4*B4/8, B4*B5/8, B4*B6/8, B4*B7/8,
|
||||
B5*B0/8, B5*B1/8, B5*B2/8, B5*B3/8, B5*B4/8, B5*B5/8, B5*B6/8, B5*B7/8,
|
||||
B6*B0/8, B6*B1/8, B6*B2/8, B6*B3/8, B6*B4/8, B6*B5/8, B6*B6/8, B6*B7/8,
|
||||
B7*B0/8, B7*B1/8, B7*B2/8, B7*B3/8, B7*B4/8, B7*B5/8, B7*B6/8, B7*B7/8,
|
||||
};
|
||||
|
||||
static inline void p8idct(DCTELEM data[64], FLOAT temp[64], uint8_t *dest, int stride, int x, int y, int type){
|
||||
int i;
|
||||
FLOAT av_unused tmp0;
|
||||
FLOAT s04, d04, s17, d17, s26, d26, s53, d53;
|
||||
FLOAT os07, os16, os25, os34;
|
||||
FLOAT od07, od16, od25, od34;
|
||||
|
||||
for(i=0; i<y*8; i+=y){
|
||||
s17= temp[1*x + i] + temp[7*x + i];
|
||||
d17= temp[1*x + i] - temp[7*x + i];
|
||||
s53= temp[5*x + i] + temp[3*x + i];
|
||||
d53= temp[5*x + i] - temp[3*x + i];
|
||||
|
||||
od07= s17 + s53;
|
||||
od25= (s17 - s53)*(2*A4);
|
||||
|
||||
#if 0 //these 2 are equivalent
|
||||
tmp0= (d17 + d53)*(2*A2);
|
||||
od34= d17*( 2*B6) - tmp0;
|
||||
od16= d53*(-2*B2) + tmp0;
|
||||
#else
|
||||
od34= d17*(2*(B6-A2)) - d53*(2*A2);
|
||||
od16= d53*(2*(A2-B2)) + d17*(2*A2);
|
||||
#endif
|
||||
|
||||
od16 -= od07;
|
||||
od25 -= od16;
|
||||
od34 += od25;
|
||||
|
||||
s26 = temp[2*x + i] + temp[6*x + i];
|
||||
d26 = temp[2*x + i] - temp[6*x + i];
|
||||
d26*= 2*A4;
|
||||
d26-= s26;
|
||||
|
||||
s04= temp[0*x + i] + temp[4*x + i];
|
||||
d04= temp[0*x + i] - temp[4*x + i];
|
||||
|
||||
os07= s04 + s26;
|
||||
os34= s04 - s26;
|
||||
os16= d04 + d26;
|
||||
os25= d04 - d26;
|
||||
|
||||
if(type==0){
|
||||
temp[0*x + i]= os07 + od07;
|
||||
temp[7*x + i]= os07 - od07;
|
||||
temp[1*x + i]= os16 + od16;
|
||||
temp[6*x + i]= os16 - od16;
|
||||
temp[2*x + i]= os25 + od25;
|
||||
temp[5*x + i]= os25 - od25;
|
||||
temp[3*x + i]= os34 - od34;
|
||||
temp[4*x + i]= os34 + od34;
|
||||
}else if(type==1){
|
||||
data[0*x + i]= lrintf(os07 + od07);
|
||||
data[7*x + i]= lrintf(os07 - od07);
|
||||
data[1*x + i]= lrintf(os16 + od16);
|
||||
data[6*x + i]= lrintf(os16 - od16);
|
||||
data[2*x + i]= lrintf(os25 + od25);
|
||||
data[5*x + i]= lrintf(os25 - od25);
|
||||
data[3*x + i]= lrintf(os34 - od34);
|
||||
data[4*x + i]= lrintf(os34 + od34);
|
||||
}else if(type==2){
|
||||
dest[0*stride + i]= av_clip_uint8(((int)dest[0*stride + i]) + lrintf(os07 + od07));
|
||||
dest[7*stride + i]= av_clip_uint8(((int)dest[7*stride + i]) + lrintf(os07 - od07));
|
||||
dest[1*stride + i]= av_clip_uint8(((int)dest[1*stride + i]) + lrintf(os16 + od16));
|
||||
dest[6*stride + i]= av_clip_uint8(((int)dest[6*stride + i]) + lrintf(os16 - od16));
|
||||
dest[2*stride + i]= av_clip_uint8(((int)dest[2*stride + i]) + lrintf(os25 + od25));
|
||||
dest[5*stride + i]= av_clip_uint8(((int)dest[5*stride + i]) + lrintf(os25 - od25));
|
||||
dest[3*stride + i]= av_clip_uint8(((int)dest[3*stride + i]) + lrintf(os34 - od34));
|
||||
dest[4*stride + i]= av_clip_uint8(((int)dest[4*stride + i]) + lrintf(os34 + od34));
|
||||
}else{
|
||||
dest[0*stride + i]= av_clip_uint8(lrintf(os07 + od07));
|
||||
dest[7*stride + i]= av_clip_uint8(lrintf(os07 - od07));
|
||||
dest[1*stride + i]= av_clip_uint8(lrintf(os16 + od16));
|
||||
dest[6*stride + i]= av_clip_uint8(lrintf(os16 - od16));
|
||||
dest[2*stride + i]= av_clip_uint8(lrintf(os25 + od25));
|
||||
dest[5*stride + i]= av_clip_uint8(lrintf(os25 - od25));
|
||||
dest[3*stride + i]= av_clip_uint8(lrintf(os34 - od34));
|
||||
dest[4*stride + i]= av_clip_uint8(lrintf(os34 + od34));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ff_faanidct(DCTELEM block[64]){
|
||||
FLOAT temp[64];
|
||||
int i;
|
||||
|
||||
emms_c();
|
||||
|
||||
for(i=0; i<64; i++)
|
||||
temp[i] = block[i] * prescale[i];
|
||||
|
||||
p8idct(block, temp, NULL, 0, 1, 8, 0);
|
||||
p8idct(block, temp, NULL, 0, 8, 1, 1);
|
||||
}
|
||||
|
||||
void ff_faanidct_add(uint8_t *dest, int line_size, DCTELEM block[64]){
|
||||
FLOAT temp[64];
|
||||
int i;
|
||||
|
||||
emms_c();
|
||||
|
||||
for(i=0; i<64; i++)
|
||||
temp[i] = block[i] * prescale[i];
|
||||
|
||||
p8idct(block, temp, NULL, 0, 1, 8, 0);
|
||||
p8idct(NULL , temp, dest, line_size, 8, 1, 2);
|
||||
}
|
||||
|
||||
void ff_faanidct_put(uint8_t *dest, int line_size, DCTELEM block[64]){
|
||||
FLOAT temp[64];
|
||||
int i;
|
||||
|
||||
emms_c();
|
||||
|
||||
for(i=0; i<64; i++)
|
||||
temp[i] = block[i] * prescale[i];
|
||||
|
||||
p8idct(block, temp, NULL, 0, 1, 8, 0);
|
||||
p8idct(NULL , temp, dest, line_size, 8, 1, 3);
|
||||
}
|
32
src/add-ons/media/plugins/avcodec/libavcodec/faanidct.h
Normal file
32
src/add-ons/media/plugins/avcodec/libavcodec/faanidct.h
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Floating point AAN IDCT
|
||||
* Copyright (c) 2008 Michael Niedermayer <michaelni@gmx.at>
|
||||
*
|
||||
* 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_FAANIDCT_H
|
||||
#define FFMPEG_FAANIDCT_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "dsputil.h"
|
||||
|
||||
void ff_faanidct(DCTELEM block[64]);
|
||||
void ff_faanidct_add(uint8_t *dest, int line_size, DCTELEM block[64]);
|
||||
void ff_faanidct_put(uint8_t *dest, int line_size, DCTELEM block[64]);
|
||||
|
||||
#endif /* FFMPEG_FAANIDCT_H */
|
@ -27,7 +27,6 @@
|
||||
* are subject to royalty fees to patent holders. Many of these patents are
|
||||
* general enough such that they are unavoidable regardless of implementation
|
||||
* design.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
@ -64,51 +63,51 @@ void init_fdct()
|
||||
void fdct(block)
|
||||
short *block;
|
||||
{
|
||||
register int i, j;
|
||||
double s;
|
||||
double tmp[64];
|
||||
register int i, j;
|
||||
double s;
|
||||
double tmp[64];
|
||||
|
||||
for(i = 0; i < 8; i++)
|
||||
for(j = 0; j < 8; j++)
|
||||
{
|
||||
s = 0.0;
|
||||
for(i = 0; i < 8; i++)
|
||||
for(j = 0; j < 8; j++)
|
||||
{
|
||||
s = 0.0;
|
||||
|
||||
/*
|
||||
* for(k = 0; k < 8; k++)
|
||||
* s += c[j][k] * block[8 * i + k];
|
||||
* for(k = 0; k < 8; k++)
|
||||
* s += c[j][k] * block[8 * i + k];
|
||||
*/
|
||||
s += c[j][0] * block[8 * i + 0];
|
||||
s += c[j][1] * block[8 * i + 1];
|
||||
s += c[j][2] * block[8 * i + 2];
|
||||
s += c[j][3] * block[8 * i + 3];
|
||||
s += c[j][4] * block[8 * i + 4];
|
||||
s += c[j][5] * block[8 * i + 5];
|
||||
s += c[j][6] * block[8 * i + 6];
|
||||
s += c[j][7] * block[8 * i + 7];
|
||||
s += c[j][0] * block[8 * i + 0];
|
||||
s += c[j][1] * block[8 * i + 1];
|
||||
s += c[j][2] * block[8 * i + 2];
|
||||
s += c[j][3] * block[8 * i + 3];
|
||||
s += c[j][4] * block[8 * i + 4];
|
||||
s += c[j][5] * block[8 * i + 5];
|
||||
s += c[j][6] * block[8 * i + 6];
|
||||
s += c[j][7] * block[8 * i + 7];
|
||||
|
||||
tmp[8 * i + j] = s;
|
||||
}
|
||||
tmp[8 * i + j] = s;
|
||||
}
|
||||
|
||||
for(j = 0; j < 8; j++)
|
||||
for(i = 0; i < 8; i++)
|
||||
{
|
||||
s = 0.0;
|
||||
for(j = 0; j < 8; j++)
|
||||
for(i = 0; i < 8; i++)
|
||||
{
|
||||
s = 0.0;
|
||||
|
||||
/*
|
||||
* for(k = 0; k < 8; k++)
|
||||
* s += c[i][k] * tmp[8 * k + j];
|
||||
* for(k = 0; k < 8; k++)
|
||||
* s += c[i][k] * tmp[8 * k + j];
|
||||
*/
|
||||
s += c[i][0] * tmp[8 * 0 + j];
|
||||
s += c[i][1] * tmp[8 * 1 + j];
|
||||
s += c[i][2] * tmp[8 * 2 + j];
|
||||
s += c[i][3] * tmp[8 * 3 + j];
|
||||
s += c[i][4] * tmp[8 * 4 + j];
|
||||
s += c[i][5] * tmp[8 * 5 + j];
|
||||
s += c[i][6] * tmp[8 * 6 + j];
|
||||
s += c[i][7] * tmp[8 * 7 + j];
|
||||
s*=8.0;
|
||||
s += c[i][0] * tmp[8 * 0 + j];
|
||||
s += c[i][1] * tmp[8 * 1 + j];
|
||||
s += c[i][2] * tmp[8 * 2 + j];
|
||||
s += c[i][3] * tmp[8 * 3 + j];
|
||||
s += c[i][4] * tmp[8 * 4 + j];
|
||||
s += c[i][5] * tmp[8 * 5 + j];
|
||||
s += c[i][6] * tmp[8 * 6 + j];
|
||||
s += c[i][7] * tmp[8 * 7 + j];
|
||||
s*=8.0;
|
||||
|
||||
block[8 * i + j] = (short)floor(s + 0.499999);
|
||||
block[8 * i + j] = (short)floor(s + 0.499999);
|
||||
/*
|
||||
* reason for adding 0.499999 instead of 0.5:
|
||||
* s is quite often x.5 (at least for i and/or j = 0 or 4)
|
||||
@ -141,7 +140,7 @@ short *block;
|
||||
tmp[8*i+j] = partial_product;
|
||||
}
|
||||
|
||||
/* Transpose operation is integrated into address mapping by switching
|
||||
/* Transpose operation is integrated into address mapping by switching
|
||||
loop order of i and j */
|
||||
|
||||
for (j=0; j<8; j++)
|
||||
|
306
src/add-ons/media/plugins/avcodec/libavcodec/fft-test.c
Normal file
306
src/add-ons/media/plugins/avcodec/libavcodec/fft-test.c
Normal file
@ -0,0 +1,306 @@
|
||||
/*
|
||||
* (c) 2002 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 fft-test.c
|
||||
* FFT and MDCT tests.
|
||||
*/
|
||||
|
||||
#include "dsputil.h"
|
||||
#include <math.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#undef exit
|
||||
#undef random
|
||||
|
||||
/* reference fft */
|
||||
|
||||
#define MUL16(a,b) ((a) * (b))
|
||||
|
||||
#define CMAC(pre, pim, are, aim, bre, bim) \
|
||||
{\
|
||||
pre += (MUL16(are, bre) - MUL16(aim, bim));\
|
||||
pim += (MUL16(are, bim) + MUL16(bre, aim));\
|
||||
}
|
||||
|
||||
FFTComplex *exptab;
|
||||
|
||||
void fft_ref_init(int nbits, int inverse)
|
||||
{
|
||||
int n, i;
|
||||
double c1, s1, alpha;
|
||||
|
||||
n = 1 << nbits;
|
||||
exptab = av_malloc((n / 2) * sizeof(FFTComplex));
|
||||
|
||||
for(i=0;i<(n/2);i++) {
|
||||
alpha = 2 * M_PI * (float)i / (float)n;
|
||||
c1 = cos(alpha);
|
||||
s1 = sin(alpha);
|
||||
if (!inverse)
|
||||
s1 = -s1;
|
||||
exptab[i].re = c1;
|
||||
exptab[i].im = s1;
|
||||
}
|
||||
}
|
||||
|
||||
void fft_ref(FFTComplex *tabr, FFTComplex *tab, int nbits)
|
||||
{
|
||||
int n, i, j, k, n2;
|
||||
double tmp_re, tmp_im, s, c;
|
||||
FFTComplex *q;
|
||||
|
||||
n = 1 << nbits;
|
||||
n2 = n >> 1;
|
||||
for(i=0;i<n;i++) {
|
||||
tmp_re = 0;
|
||||
tmp_im = 0;
|
||||
q = tab;
|
||||
for(j=0;j<n;j++) {
|
||||
k = (i * j) & (n - 1);
|
||||
if (k >= n2) {
|
||||
c = -exptab[k - n2].re;
|
||||
s = -exptab[k - n2].im;
|
||||
} else {
|
||||
c = exptab[k].re;
|
||||
s = exptab[k].im;
|
||||
}
|
||||
CMAC(tmp_re, tmp_im, c, s, q->re, q->im);
|
||||
q++;
|
||||
}
|
||||
tabr[i].re = tmp_re;
|
||||
tabr[i].im = tmp_im;
|
||||
}
|
||||
}
|
||||
|
||||
void imdct_ref(float *out, float *in, int nbits)
|
||||
{
|
||||
int n = 1<<nbits;
|
||||
int k, i, a;
|
||||
double sum, f;
|
||||
|
||||
for(i=0;i<n;i++) {
|
||||
sum = 0;
|
||||
for(k=0;k<n/2;k++) {
|
||||
a = (2 * i + 1 + (n / 2)) * (2 * k + 1);
|
||||
f = cos(M_PI * a / (double)(2 * n));
|
||||
sum += f * in[k];
|
||||
}
|
||||
out[i] = -sum;
|
||||
}
|
||||
}
|
||||
|
||||
/* NOTE: no normalisation by 1 / N is done */
|
||||
void mdct_ref(float *output, float *input, int nbits)
|
||||
{
|
||||
int n = 1<<nbits;
|
||||
int k, i;
|
||||
double a, s;
|
||||
|
||||
/* do it by hand */
|
||||
for(k=0;k<n/2;k++) {
|
||||
s = 0;
|
||||
for(i=0;i<n;i++) {
|
||||
a = (2*M_PI*(2*i+1+n/2)*(2*k+1) / (4 * n));
|
||||
s += input[i] * cos(a);
|
||||
}
|
||||
output[k] = s;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float frandom(void)
|
||||
{
|
||||
return (float)((random() & 0xffff) - 32768) / 32768.0;
|
||||
}
|
||||
|
||||
int64_t gettime(void)
|
||||
{
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv,NULL);
|
||||
return (int64_t)tv.tv_sec * 1000000 + tv.tv_usec;
|
||||
}
|
||||
|
||||
void check_diff(float *tab1, float *tab2, int n)
|
||||
{
|
||||
int i;
|
||||
double max= 0;
|
||||
double error= 0;
|
||||
|
||||
for(i=0;i<n;i++) {
|
||||
double e= fabsf(tab1[i] - tab2[i]);
|
||||
if (e >= 1e-3) {
|
||||
av_log(NULL, AV_LOG_ERROR, "ERROR %d: %f %f\n",
|
||||
i, tab1[i], tab2[i]);
|
||||
}
|
||||
error+= e*e;
|
||||
if(e>max) max= e;
|
||||
}
|
||||
av_log(NULL, AV_LOG_INFO, "max:%f e:%g\n", max, sqrt(error)/n);
|
||||
}
|
||||
|
||||
|
||||
void help(void)
|
||||
{
|
||||
av_log(NULL, AV_LOG_INFO,"usage: fft-test [-h] [-s] [-i] [-n b]\n"
|
||||
"-h print this help\n"
|
||||
"-s speed test\n"
|
||||
"-m (I)MDCT test\n"
|
||||
"-i inverse transform test\n"
|
||||
"-n b set the transform size to 2^b\n"
|
||||
);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
FFTComplex *tab, *tab1, *tab_ref;
|
||||
FFTSample *tab2;
|
||||
int it, i, c;
|
||||
int do_speed = 0;
|
||||
int do_mdct = 0;
|
||||
int do_inverse = 0;
|
||||
FFTContext s1, *s = &s1;
|
||||
MDCTContext m1, *m = &m1;
|
||||
int fft_nbits, fft_size;
|
||||
|
||||
fft_nbits = 9;
|
||||
for(;;) {
|
||||
c = getopt(argc, argv, "hsimn:");
|
||||
if (c == -1)
|
||||
break;
|
||||
switch(c) {
|
||||
case 'h':
|
||||
help();
|
||||
break;
|
||||
case 's':
|
||||
do_speed = 1;
|
||||
break;
|
||||
case 'i':
|
||||
do_inverse = 1;
|
||||
break;
|
||||
case 'm':
|
||||
do_mdct = 1;
|
||||
break;
|
||||
case 'n':
|
||||
fft_nbits = atoi(optarg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fft_size = 1 << fft_nbits;
|
||||
tab = av_malloc(fft_size * sizeof(FFTComplex));
|
||||
tab1 = av_malloc(fft_size * sizeof(FFTComplex));
|
||||
tab_ref = av_malloc(fft_size * sizeof(FFTComplex));
|
||||
tab2 = av_malloc(fft_size * sizeof(FFTSample));
|
||||
|
||||
if (do_mdct) {
|
||||
if (do_inverse)
|
||||
av_log(NULL, AV_LOG_INFO,"IMDCT");
|
||||
else
|
||||
av_log(NULL, AV_LOG_INFO,"MDCT");
|
||||
ff_mdct_init(m, fft_nbits, do_inverse);
|
||||
} else {
|
||||
if (do_inverse)
|
||||
av_log(NULL, AV_LOG_INFO,"IFFT");
|
||||
else
|
||||
av_log(NULL, AV_LOG_INFO,"FFT");
|
||||
ff_fft_init(s, fft_nbits, do_inverse);
|
||||
fft_ref_init(fft_nbits, do_inverse);
|
||||
}
|
||||
av_log(NULL, AV_LOG_INFO," %d test\n", fft_size);
|
||||
|
||||
/* generate random data */
|
||||
|
||||
for(i=0;i<fft_size;i++) {
|
||||
tab1[i].re = frandom();
|
||||
tab1[i].im = frandom();
|
||||
}
|
||||
|
||||
/* checking result */
|
||||
av_log(NULL, AV_LOG_INFO,"Checking...\n");
|
||||
|
||||
if (do_mdct) {
|
||||
if (do_inverse) {
|
||||
imdct_ref((float *)tab_ref, (float *)tab1, fft_nbits);
|
||||
ff_imdct_calc(m, tab2, (float *)tab1);
|
||||
check_diff((float *)tab_ref, tab2, fft_size);
|
||||
} else {
|
||||
mdct_ref((float *)tab_ref, (float *)tab1, fft_nbits);
|
||||
|
||||
ff_mdct_calc(m, tab2, (float *)tab1);
|
||||
|
||||
check_diff((float *)tab_ref, tab2, fft_size / 2);
|
||||
}
|
||||
} else {
|
||||
memcpy(tab, tab1, fft_size * sizeof(FFTComplex));
|
||||
ff_fft_permute(s, tab);
|
||||
ff_fft_calc(s, tab);
|
||||
|
||||
fft_ref(tab_ref, tab1, fft_nbits);
|
||||
check_diff((float *)tab_ref, (float *)tab, fft_size * 2);
|
||||
}
|
||||
|
||||
/* do a speed test */
|
||||
|
||||
if (do_speed) {
|
||||
int64_t time_start, duration;
|
||||
int nb_its;
|
||||
|
||||
av_log(NULL, AV_LOG_INFO,"Speed test...\n");
|
||||
/* we measure during about 1 seconds */
|
||||
nb_its = 1;
|
||||
for(;;) {
|
||||
time_start = gettime();
|
||||
for(it=0;it<nb_its;it++) {
|
||||
if (do_mdct) {
|
||||
if (do_inverse) {
|
||||
ff_imdct_calc(m, (float *)tab, (float *)tab1);
|
||||
} else {
|
||||
ff_mdct_calc(m, (float *)tab, (float *)tab1);
|
||||
}
|
||||
} else {
|
||||
memcpy(tab, tab1, fft_size * sizeof(FFTComplex));
|
||||
ff_fft_calc(s, tab);
|
||||
}
|
||||
}
|
||||
duration = gettime() - time_start;
|
||||
if (duration >= 1000000)
|
||||
break;
|
||||
nb_its *= 2;
|
||||
}
|
||||
av_log(NULL, AV_LOG_INFO,"time: %0.1f us/transform [total time=%0.2f s its=%d]\n",
|
||||
(double)duration / nb_its,
|
||||
(double)duration / 1000000.0,
|
||||
nb_its);
|
||||
}
|
||||
|
||||
if (do_mdct) {
|
||||
ff_mdct_end(m);
|
||||
} else {
|
||||
ff_fft_end(s);
|
||||
}
|
||||
return 0;
|
||||
}
|
@ -1,20 +1,24 @@
|
||||
/*
|
||||
* FFT/IFFT transforms
|
||||
* Copyright (c) 2008 Loren Merritt
|
||||
* Copyright (c) 2002 Fabrice Bellard.
|
||||
* Partly based on libdjbfft by D. J. Bernstein
|
||||
*
|
||||
* 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
|
||||
* 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
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
@ -24,18 +28,53 @@
|
||||
|
||||
#include "dsputil.h"
|
||||
|
||||
/* cos(2*pi*x/n) for 0<=x<=n/4, followed by its reverse */
|
||||
DECLARE_ALIGNED_16(FFTSample, ff_cos_16[8]);
|
||||
DECLARE_ALIGNED_16(FFTSample, ff_cos_32[16]);
|
||||
DECLARE_ALIGNED_16(FFTSample, ff_cos_64[32]);
|
||||
DECLARE_ALIGNED_16(FFTSample, ff_cos_128[64]);
|
||||
DECLARE_ALIGNED_16(FFTSample, ff_cos_256[128]);
|
||||
DECLARE_ALIGNED_16(FFTSample, ff_cos_512[256]);
|
||||
DECLARE_ALIGNED_16(FFTSample, ff_cos_1024[512]);
|
||||
DECLARE_ALIGNED_16(FFTSample, ff_cos_2048[1024]);
|
||||
DECLARE_ALIGNED_16(FFTSample, ff_cos_4096[2048]);
|
||||
DECLARE_ALIGNED_16(FFTSample, ff_cos_8192[4096]);
|
||||
DECLARE_ALIGNED_16(FFTSample, ff_cos_16384[8192]);
|
||||
DECLARE_ALIGNED_16(FFTSample, ff_cos_32768[16384]);
|
||||
DECLARE_ALIGNED_16(FFTSample, ff_cos_65536[32768]);
|
||||
static FFTSample *ff_cos_tabs[] = {
|
||||
ff_cos_16, ff_cos_32, ff_cos_64, ff_cos_128, ff_cos_256, ff_cos_512, ff_cos_1024,
|
||||
ff_cos_2048, ff_cos_4096, ff_cos_8192, ff_cos_16384, ff_cos_32768, ff_cos_65536,
|
||||
};
|
||||
|
||||
static int split_radix_permutation(int i, int n, int inverse)
|
||||
{
|
||||
int m;
|
||||
if(n <= 2) return i&1;
|
||||
m = n >> 1;
|
||||
if(!(i&m)) return split_radix_permutation(i, m, inverse)*2;
|
||||
m >>= 1;
|
||||
if(inverse == !(i&m)) return split_radix_permutation(i, m, inverse)*4 + 1;
|
||||
else return split_radix_permutation(i, m, inverse)*4 - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* The size of the FFT is 2^nbits. If inverse is TRUE, inverse FFT is
|
||||
* done
|
||||
* done
|
||||
*/
|
||||
int fft_init(FFTContext *s, int nbits, int inverse)
|
||||
int ff_fft_init(FFTContext *s, int nbits, int inverse)
|
||||
{
|
||||
int i, j, m, n;
|
||||
float alpha, c1, s1, s2;
|
||||
|
||||
int split_radix = 1;
|
||||
int av_unused has_vectors;
|
||||
|
||||
if (nbits < 2 || nbits > 16)
|
||||
goto fail;
|
||||
s->nbits = nbits;
|
||||
n = 1 << nbits;
|
||||
|
||||
s->tmp_buf = NULL;
|
||||
s->exptab = av_malloc((n / 2) * sizeof(FFTComplex));
|
||||
if (!s->exptab)
|
||||
goto fail;
|
||||
@ -45,192 +84,125 @@ int fft_init(FFTContext *s, int nbits, int inverse)
|
||||
s->inverse = inverse;
|
||||
|
||||
s2 = inverse ? 1.0 : -1.0;
|
||||
|
||||
for(i=0;i<(n/2);i++) {
|
||||
alpha = 2 * M_PI * (float)i / (float)n;
|
||||
c1 = cos(alpha);
|
||||
s1 = sin(alpha) * s2;
|
||||
s->exptab[i].re = c1;
|
||||
s->exptab[i].im = s1;
|
||||
}
|
||||
s->fft_calc = fft_calc_c;
|
||||
|
||||
s->fft_permute = ff_fft_permute_c;
|
||||
s->fft_calc = ff_fft_calc_c;
|
||||
s->imdct_calc = ff_imdct_calc_c;
|
||||
s->imdct_half = ff_imdct_half_c;
|
||||
s->exptab1 = NULL;
|
||||
|
||||
/* compute constant table for HAVE_SSE version */
|
||||
#if (defined(HAVE_MMX) && defined(HAVE_BUILTIN_VECTOR)) || defined(HAVE_ALTIVEC)
|
||||
{
|
||||
int has_vectors = 0;
|
||||
|
||||
#if defined(HAVE_MMX)
|
||||
has_vectors = mm_support() & MM_SSE;
|
||||
#endif
|
||||
#if defined(HAVE_ALTIVEC) && !defined(ALTIVEC_USE_REFERENCE_C_CODE)
|
||||
has_vectors = mm_support() & MM_ALTIVEC;
|
||||
#endif
|
||||
if (has_vectors) {
|
||||
int np, nblocks, np2, l;
|
||||
FFTComplex *q;
|
||||
|
||||
np = 1 << nbits;
|
||||
nblocks = np >> 3;
|
||||
np2 = np >> 1;
|
||||
s->exptab1 = av_malloc(np * 2 * sizeof(FFTComplex));
|
||||
if (!s->exptab1)
|
||||
goto fail;
|
||||
q = s->exptab1;
|
||||
do {
|
||||
for(l = 0; l < np2; l += 2 * nblocks) {
|
||||
*q++ = s->exptab[l];
|
||||
*q++ = s->exptab[l + nblocks];
|
||||
|
||||
q->re = -s->exptab[l].im;
|
||||
q->im = s->exptab[l].re;
|
||||
q++;
|
||||
q->re = -s->exptab[l + nblocks].im;
|
||||
q->im = s->exptab[l + nblocks].re;
|
||||
q++;
|
||||
}
|
||||
nblocks = nblocks >> 1;
|
||||
} while (nblocks != 0);
|
||||
av_freep(&s->exptab);
|
||||
#if defined(HAVE_MMX)
|
||||
s->fft_calc = fft_calc_sse;
|
||||
#else
|
||||
s->fft_calc = fft_calc_altivec;
|
||||
#endif
|
||||
}
|
||||
#if defined HAVE_MMX && defined HAVE_YASM
|
||||
has_vectors = mm_support();
|
||||
if (has_vectors & MM_SSE) {
|
||||
/* SSE for P3/P4/K8 */
|
||||
s->imdct_calc = ff_imdct_calc_sse;
|
||||
s->imdct_half = ff_imdct_half_sse;
|
||||
s->fft_permute = ff_fft_permute_sse;
|
||||
s->fft_calc = ff_fft_calc_sse;
|
||||
} else if (has_vectors & MM_3DNOWEXT) {
|
||||
/* 3DNowEx for K7 */
|
||||
s->imdct_calc = ff_imdct_calc_3dn2;
|
||||
s->imdct_half = ff_imdct_half_3dn2;
|
||||
s->fft_calc = ff_fft_calc_3dn2;
|
||||
} else if (has_vectors & MM_3DNOW) {
|
||||
/* 3DNow! for K6-2/3 */
|
||||
s->imdct_calc = ff_imdct_calc_3dn;
|
||||
s->imdct_half = ff_imdct_half_3dn;
|
||||
s->fft_calc = ff_fft_calc_3dn;
|
||||
}
|
||||
#elif defined HAVE_ALTIVEC && !defined ALTIVEC_USE_REFERENCE_C_CODE
|
||||
has_vectors = mm_support();
|
||||
if (has_vectors & MM_ALTIVEC) {
|
||||
s->fft_calc = ff_fft_calc_altivec;
|
||||
split_radix = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* compute bit reverse table */
|
||||
|
||||
for(i=0;i<n;i++) {
|
||||
m=0;
|
||||
for(j=0;j<nbits;j++) {
|
||||
m |= ((i >> j) & 1) << (nbits-j-1);
|
||||
if (split_radix) {
|
||||
for(j=4; j<=nbits; j++) {
|
||||
int m = 1<<j;
|
||||
double freq = 2*M_PI/m;
|
||||
FFTSample *tab = ff_cos_tabs[j-4];
|
||||
for(i=0; i<=m/4; i++)
|
||||
tab[i] = cos(i*freq);
|
||||
for(i=1; i<m/4; i++)
|
||||
tab[m/2-i] = tab[i];
|
||||
}
|
||||
for(i=0; i<n; i++)
|
||||
s->revtab[-split_radix_permutation(i, n, s->inverse) & (n-1)] = i;
|
||||
s->tmp_buf = av_malloc(n * sizeof(FFTComplex));
|
||||
} else {
|
||||
int np, nblocks, np2, l;
|
||||
FFTComplex *q;
|
||||
|
||||
for(i=0; i<(n/2); i++) {
|
||||
alpha = 2 * M_PI * (float)i / (float)n;
|
||||
c1 = cos(alpha);
|
||||
s1 = sin(alpha) * s2;
|
||||
s->exptab[i].re = c1;
|
||||
s->exptab[i].im = s1;
|
||||
}
|
||||
|
||||
np = 1 << nbits;
|
||||
nblocks = np >> 3;
|
||||
np2 = np >> 1;
|
||||
s->exptab1 = av_malloc(np * 2 * sizeof(FFTComplex));
|
||||
if (!s->exptab1)
|
||||
goto fail;
|
||||
q = s->exptab1;
|
||||
do {
|
||||
for(l = 0; l < np2; l += 2 * nblocks) {
|
||||
*q++ = s->exptab[l];
|
||||
*q++ = s->exptab[l + nblocks];
|
||||
|
||||
q->re = -s->exptab[l].im;
|
||||
q->im = s->exptab[l].re;
|
||||
q++;
|
||||
q->re = -s->exptab[l + nblocks].im;
|
||||
q->im = s->exptab[l + nblocks].re;
|
||||
q++;
|
||||
}
|
||||
nblocks = nblocks >> 1;
|
||||
} while (nblocks != 0);
|
||||
av_freep(&s->exptab);
|
||||
|
||||
/* compute bit reverse table */
|
||||
for(i=0;i<n;i++) {
|
||||
m=0;
|
||||
for(j=0;j<nbits;j++) {
|
||||
m |= ((i >> j) & 1) << (nbits-j-1);
|
||||
}
|
||||
s->revtab[i]=m;
|
||||
}
|
||||
s->revtab[i]=m;
|
||||
}
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
av_freep(&s->revtab);
|
||||
av_freep(&s->exptab);
|
||||
av_freep(&s->exptab1);
|
||||
av_freep(&s->tmp_buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* butter fly op */
|
||||
#define BF(pre, pim, qre, qim, pre1, pim1, qre1, qim1) \
|
||||
{\
|
||||
FFTSample ax, ay, bx, by;\
|
||||
bx=pre1;\
|
||||
by=pim1;\
|
||||
ax=qre1;\
|
||||
ay=qim1;\
|
||||
pre = (bx + ax);\
|
||||
pim = (by + ay);\
|
||||
qre = (bx - ax);\
|
||||
qim = (by - ay);\
|
||||
}
|
||||
|
||||
#define MUL16(a,b) ((a) * (b))
|
||||
|
||||
#define CMUL(pre, pim, are, aim, bre, bim) \
|
||||
{\
|
||||
pre = (MUL16(are, bre) - MUL16(aim, bim));\
|
||||
pim = (MUL16(are, bim) + MUL16(bre, aim));\
|
||||
}
|
||||
|
||||
/**
|
||||
* Do a complex FFT with the parameters defined in fft_init(). The
|
||||
* input data must be permuted before with s->revtab table. No
|
||||
* 1.0/sqrt(n) normalization is done.
|
||||
* Do the permutation needed BEFORE calling ff_fft_calc()
|
||||
*/
|
||||
void fft_calc_c(FFTContext *s, FFTComplex *z)
|
||||
{
|
||||
int ln = s->nbits;
|
||||
int j, np, np2;
|
||||
int nblocks, nloops;
|
||||
register FFTComplex *p, *q;
|
||||
FFTComplex *exptab = s->exptab;
|
||||
int l;
|
||||
FFTSample tmp_re, tmp_im;
|
||||
|
||||
np = 1 << ln;
|
||||
|
||||
/* pass 0 */
|
||||
|
||||
p=&z[0];
|
||||
j=(np >> 1);
|
||||
do {
|
||||
BF(p[0].re, p[0].im, p[1].re, p[1].im,
|
||||
p[0].re, p[0].im, p[1].re, p[1].im);
|
||||
p+=2;
|
||||
} while (--j != 0);
|
||||
|
||||
/* pass 1 */
|
||||
|
||||
|
||||
p=&z[0];
|
||||
j=np >> 2;
|
||||
if (s->inverse) {
|
||||
do {
|
||||
BF(p[0].re, p[0].im, p[2].re, p[2].im,
|
||||
p[0].re, p[0].im, p[2].re, p[2].im);
|
||||
BF(p[1].re, p[1].im, p[3].re, p[3].im,
|
||||
p[1].re, p[1].im, -p[3].im, p[3].re);
|
||||
p+=4;
|
||||
} while (--j != 0);
|
||||
} else {
|
||||
do {
|
||||
BF(p[0].re, p[0].im, p[2].re, p[2].im,
|
||||
p[0].re, p[0].im, p[2].re, p[2].im);
|
||||
BF(p[1].re, p[1].im, p[3].re, p[3].im,
|
||||
p[1].re, p[1].im, p[3].im, -p[3].re);
|
||||
p+=4;
|
||||
} while (--j != 0);
|
||||
}
|
||||
/* pass 2 .. ln-1 */
|
||||
|
||||
nblocks = np >> 3;
|
||||
nloops = 1 << 2;
|
||||
np2 = np >> 1;
|
||||
do {
|
||||
p = z;
|
||||
q = z + nloops;
|
||||
for (j = 0; j < nblocks; ++j) {
|
||||
BF(p->re, p->im, q->re, q->im,
|
||||
p->re, p->im, q->re, q->im);
|
||||
|
||||
p++;
|
||||
q++;
|
||||
for(l = nblocks; l < np2; l += nblocks) {
|
||||
CMUL(tmp_re, tmp_im, exptab[l].re, exptab[l].im, q->re, q->im);
|
||||
BF(p->re, p->im, q->re, q->im,
|
||||
p->re, p->im, tmp_re, tmp_im);
|
||||
p++;
|
||||
q++;
|
||||
}
|
||||
|
||||
p += nloops;
|
||||
q += nloops;
|
||||
}
|
||||
nblocks = nblocks >> 1;
|
||||
nloops = nloops << 1;
|
||||
} while (nblocks != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Do the permutation needed BEFORE calling fft_calc()
|
||||
*/
|
||||
void fft_permute(FFTContext *s, FFTComplex *z)
|
||||
void ff_fft_permute_c(FFTContext *s, FFTComplex *z)
|
||||
{
|
||||
int j, k, np;
|
||||
FFTComplex tmp;
|
||||
const uint16_t *revtab = s->revtab;
|
||||
|
||||
/* reverse */
|
||||
np = 1 << s->nbits;
|
||||
|
||||
if (s->tmp_buf) {
|
||||
/* TODO: handle split-radix permute in a more optimal way, probably in-place */
|
||||
for(j=0;j<np;j++) s->tmp_buf[revtab[j]] = z[j];
|
||||
memcpy(z, s->tmp_buf, np * sizeof(FFTComplex));
|
||||
return;
|
||||
}
|
||||
|
||||
/* reverse */
|
||||
for(j=0;j<np;j++) {
|
||||
k = revtab[j];
|
||||
if (k < j) {
|
||||
@ -241,10 +213,174 @@ void fft_permute(FFTContext *s, FFTComplex *z)
|
||||
}
|
||||
}
|
||||
|
||||
void fft_end(FFTContext *s)
|
||||
void ff_fft_end(FFTContext *s)
|
||||
{
|
||||
av_freep(&s->revtab);
|
||||
av_freep(&s->exptab);
|
||||
av_freep(&s->exptab1);
|
||||
av_freep(&s->tmp_buf);
|
||||
}
|
||||
|
||||
#define sqrthalf (float)M_SQRT1_2
|
||||
|
||||
#define BF(x,y,a,b) {\
|
||||
x = a - b;\
|
||||
y = a + b;\
|
||||
}
|
||||
|
||||
#define BUTTERFLIES(a0,a1,a2,a3) {\
|
||||
BF(t3, t5, t5, t1);\
|
||||
BF(a2.re, a0.re, a0.re, t5);\
|
||||
BF(a3.im, a1.im, a1.im, t3);\
|
||||
BF(t4, t6, t2, t6);\
|
||||
BF(a3.re, a1.re, a1.re, t4);\
|
||||
BF(a2.im, a0.im, a0.im, t6);\
|
||||
}
|
||||
|
||||
// force loading all the inputs before storing any.
|
||||
// this is slightly slower for small data, but avoids store->load aliasing
|
||||
// for addresses separated by large powers of 2.
|
||||
#define BUTTERFLIES_BIG(a0,a1,a2,a3) {\
|
||||
FFTSample r0=a0.re, i0=a0.im, r1=a1.re, i1=a1.im;\
|
||||
BF(t3, t5, t5, t1);\
|
||||
BF(a2.re, a0.re, r0, t5);\
|
||||
BF(a3.im, a1.im, i1, t3);\
|
||||
BF(t4, t6, t2, t6);\
|
||||
BF(a3.re, a1.re, r1, t4);\
|
||||
BF(a2.im, a0.im, i0, t6);\
|
||||
}
|
||||
|
||||
#define TRANSFORM(a0,a1,a2,a3,wre,wim) {\
|
||||
t1 = a2.re * wre + a2.im * wim;\
|
||||
t2 = a2.im * wre - a2.re * wim;\
|
||||
t5 = a3.re * wre - a3.im * wim;\
|
||||
t6 = a3.im * wre + a3.re * wim;\
|
||||
BUTTERFLIES(a0,a1,a2,a3)\
|
||||
}
|
||||
|
||||
#define TRANSFORM_ZERO(a0,a1,a2,a3) {\
|
||||
t1 = a2.re;\
|
||||
t2 = a2.im;\
|
||||
t5 = a3.re;\
|
||||
t6 = a3.im;\
|
||||
BUTTERFLIES(a0,a1,a2,a3)\
|
||||
}
|
||||
|
||||
/* z[0...8n-1], w[1...2n-1] */
|
||||
#define PASS(name)\
|
||||
static void name(FFTComplex *z, const FFTSample *wre, unsigned int n)\
|
||||
{\
|
||||
FFTSample t1, t2, t3, t4, t5, t6;\
|
||||
int o1 = 2*n;\
|
||||
int o2 = 4*n;\
|
||||
int o3 = 6*n;\
|
||||
const FFTSample *wim = wre+o1;\
|
||||
n--;\
|
||||
\
|
||||
TRANSFORM_ZERO(z[0],z[o1],z[o2],z[o3]);\
|
||||
TRANSFORM(z[1],z[o1+1],z[o2+1],z[o3+1],wre[1],wim[-1]);\
|
||||
do {\
|
||||
z += 2;\
|
||||
wre += 2;\
|
||||
wim -= 2;\
|
||||
TRANSFORM(z[0],z[o1],z[o2],z[o3],wre[0],wim[0]);\
|
||||
TRANSFORM(z[1],z[o1+1],z[o2+1],z[o3+1],wre[1],wim[-1]);\
|
||||
} while(--n);\
|
||||
}
|
||||
|
||||
PASS(pass)
|
||||
#undef BUTTERFLIES
|
||||
#define BUTTERFLIES BUTTERFLIES_BIG
|
||||
PASS(pass_big)
|
||||
|
||||
#define DECL_FFT(n,n2,n4)\
|
||||
static void fft##n(FFTComplex *z)\
|
||||
{\
|
||||
fft##n2(z);\
|
||||
fft##n4(z+n4*2);\
|
||||
fft##n4(z+n4*3);\
|
||||
pass(z,ff_cos_##n,n4/2);\
|
||||
}
|
||||
|
||||
static void fft4(FFTComplex *z)
|
||||
{
|
||||
FFTSample t1, t2, t3, t4, t5, t6, t7, t8;
|
||||
|
||||
BF(t3, t1, z[0].re, z[1].re);
|
||||
BF(t8, t6, z[3].re, z[2].re);
|
||||
BF(z[2].re, z[0].re, t1, t6);
|
||||
BF(t4, t2, z[0].im, z[1].im);
|
||||
BF(t7, t5, z[2].im, z[3].im);
|
||||
BF(z[3].im, z[1].im, t4, t8);
|
||||
BF(z[3].re, z[1].re, t3, t7);
|
||||
BF(z[2].im, z[0].im, t2, t5);
|
||||
}
|
||||
|
||||
static void fft8(FFTComplex *z)
|
||||
{
|
||||
FFTSample t1, t2, t3, t4, t5, t6, t7, t8;
|
||||
|
||||
fft4(z);
|
||||
|
||||
BF(t1, z[5].re, z[4].re, -z[5].re);
|
||||
BF(t2, z[5].im, z[4].im, -z[5].im);
|
||||
BF(t3, z[7].re, z[6].re, -z[7].re);
|
||||
BF(t4, z[7].im, z[6].im, -z[7].im);
|
||||
BF(t8, t1, t3, t1);
|
||||
BF(t7, t2, t2, t4);
|
||||
BF(z[4].re, z[0].re, z[0].re, t1);
|
||||
BF(z[4].im, z[0].im, z[0].im, t2);
|
||||
BF(z[6].re, z[2].re, z[2].re, t7);
|
||||
BF(z[6].im, z[2].im, z[2].im, t8);
|
||||
|
||||
TRANSFORM(z[1],z[3],z[5],z[7],sqrthalf,sqrthalf);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_SMALL
|
||||
static void fft16(FFTComplex *z)
|
||||
{
|
||||
FFTSample t1, t2, t3, t4, t5, t6;
|
||||
|
||||
fft8(z);
|
||||
fft4(z+8);
|
||||
fft4(z+12);
|
||||
|
||||
TRANSFORM_ZERO(z[0],z[4],z[8],z[12]);
|
||||
TRANSFORM(z[2],z[6],z[10],z[14],sqrthalf,sqrthalf);
|
||||
TRANSFORM(z[1],z[5],z[9],z[13],ff_cos_16[1],ff_cos_16[3]);
|
||||
TRANSFORM(z[3],z[7],z[11],z[15],ff_cos_16[3],ff_cos_16[1]);
|
||||
}
|
||||
#else
|
||||
DECL_FFT(16,8,4)
|
||||
#endif
|
||||
DECL_FFT(32,16,8)
|
||||
DECL_FFT(64,32,16)
|
||||
DECL_FFT(128,64,32)
|
||||
DECL_FFT(256,128,64)
|
||||
DECL_FFT(512,256,128)
|
||||
#ifndef CONFIG_SMALL
|
||||
#define pass pass_big
|
||||
#endif
|
||||
DECL_FFT(1024,512,256)
|
||||
DECL_FFT(2048,1024,512)
|
||||
DECL_FFT(4096,2048,1024)
|
||||
DECL_FFT(8192,4096,2048)
|
||||
DECL_FFT(16384,8192,4096)
|
||||
DECL_FFT(32768,16384,8192)
|
||||
DECL_FFT(65536,32768,16384)
|
||||
|
||||
static void (*fft_dispatch[])(FFTComplex*) = {
|
||||
fft4, fft8, fft16, fft32, fft64, fft128, fft256, fft512, fft1024,
|
||||
fft2048, fft4096, fft8192, fft16384, fft32768, fft65536,
|
||||
};
|
||||
|
||||
/**
|
||||
* Do a complex FFT with the parameters defined in ff_fft_init(). The
|
||||
* input data must be permuted before with s->revtab table. No
|
||||
* 1.0/sqrt(n) normalization is done.
|
||||
*/
|
||||
void ff_fft_calc_c(FFTContext *s, FFTComplex *z)
|
||||
{
|
||||
fft_dispatch[s->nbits-2](z);
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
794
src/add-ons/media/plugins/avcodec/libavcodec/flac.c
Normal file
794
src/add-ons/media/plugins/avcodec/libavcodec/flac.c
Normal file
@ -0,0 +1,794 @@
|
||||
/*
|
||||
* FLAC (Free Lossless Audio Codec) decoder
|
||||
* Copyright (c) 2003 Alex Beregszaszi
|
||||
*
|
||||
* 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 flac.c
|
||||
* FLAC (Free Lossless Audio Codec) decoder
|
||||
* @author Alex Beregszaszi
|
||||
*
|
||||
* For more information on the FLAC format, visit:
|
||||
* http://flac.sourceforge.net/
|
||||
*
|
||||
* This decoder can be used in 1 of 2 ways: Either raw FLAC data can be fed
|
||||
* through, starting from the initial 'fLaC' signature; or by passing the
|
||||
* 34-byte streaminfo structure through avctx->extradata[_size] followed
|
||||
* by data starting with the 0xFFF8 marker.
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#define ALT_BITSTREAM_READER
|
||||
#include "crc.h"
|
||||
#include "avcodec.h"
|
||||
#include "bitstream.h"
|
||||
#include "golomb.h"
|
||||
#include "flac.h"
|
||||
|
||||
#undef NDEBUG
|
||||
#include <assert.h>
|
||||
|
||||
#define MAX_CHANNELS 8
|
||||
#define MAX_BLOCKSIZE 65535
|
||||
#define FLAC_STREAMINFO_SIZE 34
|
||||
|
||||
enum decorrelation_type {
|
||||
INDEPENDENT,
|
||||
LEFT_SIDE,
|
||||
RIGHT_SIDE,
|
||||
MID_SIDE,
|
||||
};
|
||||
|
||||
typedef struct FLACContext {
|
||||
FLACSTREAMINFO
|
||||
|
||||
AVCodecContext *avctx;
|
||||
GetBitContext gb;
|
||||
|
||||
int blocksize/*, last_blocksize*/;
|
||||
int curr_bps;
|
||||
enum decorrelation_type decorrelation;
|
||||
|
||||
int32_t *decoded[MAX_CHANNELS];
|
||||
uint8_t *bitstream;
|
||||
unsigned int bitstream_size;
|
||||
unsigned int bitstream_index;
|
||||
unsigned int allocated_bitstream_size;
|
||||
} FLACContext;
|
||||
|
||||
#define METADATA_TYPE_STREAMINFO 0
|
||||
|
||||
static const int sample_rate_table[] =
|
||||
{ 0, 0, 0, 0,
|
||||
8000, 16000, 22050, 24000, 32000, 44100, 48000, 96000,
|
||||
0, 0, 0, 0 };
|
||||
|
||||
static const int sample_size_table[] =
|
||||
{ 0, 8, 12, 0, 16, 20, 24, 0 };
|
||||
|
||||
static const int blocksize_table[] = {
|
||||
0, 192, 576<<0, 576<<1, 576<<2, 576<<3, 0, 0,
|
||||
256<<0, 256<<1, 256<<2, 256<<3, 256<<4, 256<<5, 256<<6, 256<<7
|
||||
};
|
||||
|
||||
static int64_t get_utf8(GetBitContext *gb){
|
||||
int64_t val;
|
||||
GET_UTF8(val, get_bits(gb, 8), return -1;)
|
||||
return val;
|
||||
}
|
||||
|
||||
static void allocate_buffers(FLACContext *s);
|
||||
static int metadata_parse(FLACContext *s);
|
||||
|
||||
static av_cold int flac_decode_init(AVCodecContext * avctx)
|
||||
{
|
||||
FLACContext *s = avctx->priv_data;
|
||||
s->avctx = avctx;
|
||||
|
||||
if (avctx->extradata_size > 4) {
|
||||
/* initialize based on the demuxer-supplied streamdata header */
|
||||
if (avctx->extradata_size == FLAC_STREAMINFO_SIZE) {
|
||||
ff_flac_parse_streaminfo(avctx, (FLACStreaminfo *)s, avctx->extradata);
|
||||
allocate_buffers(s);
|
||||
} else {
|
||||
init_get_bits(&s->gb, avctx->extradata, avctx->extradata_size*8);
|
||||
metadata_parse(s);
|
||||
}
|
||||
}
|
||||
|
||||
avctx->sample_fmt = SAMPLE_FMT_S16;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dump_headers(AVCodecContext *avctx, FLACStreaminfo *s)
|
||||
{
|
||||
av_log(avctx, AV_LOG_DEBUG, " Blocksize: %d .. %d\n", s->min_blocksize, s->max_blocksize);
|
||||
av_log(avctx, AV_LOG_DEBUG, " Max Framesize: %d\n", s->max_framesize);
|
||||
av_log(avctx, AV_LOG_DEBUG, " Samplerate: %d\n", s->samplerate);
|
||||
av_log(avctx, AV_LOG_DEBUG, " Channels: %d\n", s->channels);
|
||||
av_log(avctx, AV_LOG_DEBUG, " Bits: %d\n", s->bps);
|
||||
}
|
||||
|
||||
static void allocate_buffers(FLACContext *s){
|
||||
int i;
|
||||
|
||||
assert(s->max_blocksize);
|
||||
|
||||
if(s->max_framesize == 0 && s->max_blocksize){
|
||||
s->max_framesize= (s->channels * s->bps * s->max_blocksize + 7)/ 8; //FIXME header overhead
|
||||
}
|
||||
|
||||
for (i = 0; i < s->channels; i++)
|
||||
{
|
||||
s->decoded[i] = av_realloc(s->decoded[i], sizeof(int32_t)*s->max_blocksize);
|
||||
}
|
||||
|
||||
if(s->allocated_bitstream_size < s->max_framesize)
|
||||
s->bitstream= av_fast_realloc(s->bitstream, &s->allocated_bitstream_size, s->max_framesize);
|
||||
}
|
||||
|
||||
void ff_flac_parse_streaminfo(AVCodecContext *avctx, struct FLACStreaminfo *s,
|
||||
const uint8_t *buffer)
|
||||
{
|
||||
GetBitContext gb;
|
||||
init_get_bits(&gb, buffer, FLAC_STREAMINFO_SIZE*8);
|
||||
|
||||
/* mandatory streaminfo */
|
||||
s->min_blocksize = get_bits(&gb, 16);
|
||||
s->max_blocksize = get_bits(&gb, 16);
|
||||
|
||||
skip_bits(&gb, 24); /* skip min frame size */
|
||||
s->max_framesize = get_bits_long(&gb, 24);
|
||||
|
||||
s->samplerate = get_bits_long(&gb, 20);
|
||||
s->channels = get_bits(&gb, 3) + 1;
|
||||
s->bps = get_bits(&gb, 5) + 1;
|
||||
|
||||
avctx->channels = s->channels;
|
||||
avctx->sample_rate = s->samplerate;
|
||||
|
||||
skip_bits(&gb, 36); /* total num of samples */
|
||||
|
||||
skip_bits(&gb, 64); /* md5 sum */
|
||||
skip_bits(&gb, 64); /* md5 sum */
|
||||
|
||||
dump_headers(avctx, s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a list of metadata blocks. This list of blocks must begin with
|
||||
* the fLaC marker.
|
||||
* @param s the flac decoding context containing the gb bit reader used to
|
||||
* parse metadata
|
||||
* @return 1 if some metadata was read, 0 if no fLaC marker was found
|
||||
*/
|
||||
static int metadata_parse(FLACContext *s)
|
||||
{
|
||||
int i, metadata_last, metadata_type, metadata_size, streaminfo_updated=0;
|
||||
int initial_pos= get_bits_count(&s->gb);
|
||||
|
||||
if (show_bits_long(&s->gb, 32) == MKBETAG('f','L','a','C')) {
|
||||
skip_bits(&s->gb, 32);
|
||||
|
||||
av_log(s->avctx, AV_LOG_DEBUG, "STREAM HEADER\n");
|
||||
do {
|
||||
metadata_last = get_bits1(&s->gb);
|
||||
metadata_type = get_bits(&s->gb, 7);
|
||||
metadata_size = get_bits_long(&s->gb, 24);
|
||||
|
||||
if(get_bits_count(&s->gb) + 8*metadata_size > s->gb.size_in_bits){
|
||||
skip_bits_long(&s->gb, initial_pos - get_bits_count(&s->gb));
|
||||
break;
|
||||
}
|
||||
|
||||
av_log(s->avctx, AV_LOG_DEBUG,
|
||||
" metadata block: flag = %d, type = %d, size = %d\n",
|
||||
metadata_last, metadata_type, metadata_size);
|
||||
if (metadata_size) {
|
||||
switch (metadata_type) {
|
||||
case METADATA_TYPE_STREAMINFO:
|
||||
ff_flac_parse_streaminfo(s->avctx, (FLACStreaminfo *)s, s->gb.buffer+get_bits_count(&s->gb)/8);
|
||||
streaminfo_updated = 1;
|
||||
|
||||
default:
|
||||
for (i=0; i<metadata_size; i++)
|
||||
skip_bits(&s->gb, 8);
|
||||
}
|
||||
}
|
||||
} while (!metadata_last);
|
||||
|
||||
if (streaminfo_updated)
|
||||
allocate_buffers(s);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int decode_residuals(FLACContext *s, int channel, int pred_order)
|
||||
{
|
||||
int i, tmp, partition, method_type, rice_order;
|
||||
int sample = 0, samples;
|
||||
|
||||
method_type = get_bits(&s->gb, 2);
|
||||
if (method_type > 1){
|
||||
av_log(s->avctx, AV_LOG_DEBUG, "illegal residual coding method %d\n", method_type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
rice_order = get_bits(&s->gb, 4);
|
||||
|
||||
samples= s->blocksize >> rice_order;
|
||||
if (pred_order > samples) {
|
||||
av_log(s->avctx, AV_LOG_ERROR, "invalid predictor order: %i > %i\n", pred_order, samples);
|
||||
return -1;
|
||||
}
|
||||
|
||||
sample=
|
||||
i= pred_order;
|
||||
for (partition = 0; partition < (1 << rice_order); partition++)
|
||||
{
|
||||
tmp = get_bits(&s->gb, method_type == 0 ? 4 : 5);
|
||||
if (tmp == (method_type == 0 ? 15 : 31))
|
||||
{
|
||||
av_log(s->avctx, AV_LOG_DEBUG, "fixed len partition\n");
|
||||
tmp = get_bits(&s->gb, 5);
|
||||
for (; i < samples; i++, sample++)
|
||||
s->decoded[channel][sample] = get_sbits(&s->gb, tmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
// av_log(s->avctx, AV_LOG_DEBUG, "rice coded partition k=%d\n", tmp);
|
||||
for (; i < samples; i++, sample++){
|
||||
s->decoded[channel][sample] = get_sr_golomb_flac(&s->gb, tmp, INT_MAX, 0);
|
||||
}
|
||||
}
|
||||
i= 0;
|
||||
}
|
||||
|
||||
// av_log(s->avctx, AV_LOG_DEBUG, "partitions: %d, samples: %d\n", 1 << rice_order, sample);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int decode_subframe_fixed(FLACContext *s, int channel, int pred_order)
|
||||
{
|
||||
const int blocksize = s->blocksize;
|
||||
int32_t *decoded = s->decoded[channel];
|
||||
int a, b, c, d, i;
|
||||
|
||||
// av_log(s->avctx, AV_LOG_DEBUG, " SUBFRAME FIXED\n");
|
||||
|
||||
/* warm up samples */
|
||||
// av_log(s->avctx, AV_LOG_DEBUG, " warm up samples: %d\n", pred_order);
|
||||
|
||||
for (i = 0; i < pred_order; i++)
|
||||
{
|
||||
decoded[i] = get_sbits(&s->gb, s->curr_bps);
|
||||
// av_log(s->avctx, AV_LOG_DEBUG, " %d: %d\n", i, s->decoded[channel][i]);
|
||||
}
|
||||
|
||||
if (decode_residuals(s, channel, pred_order) < 0)
|
||||
return -1;
|
||||
|
||||
if(pred_order > 0)
|
||||
a = decoded[pred_order-1];
|
||||
if(pred_order > 1)
|
||||
b = a - decoded[pred_order-2];
|
||||
if(pred_order > 2)
|
||||
c = b - decoded[pred_order-2] + decoded[pred_order-3];
|
||||
if(pred_order > 3)
|
||||
d = c - decoded[pred_order-2] + 2*decoded[pred_order-3] - decoded[pred_order-4];
|
||||
|
||||
switch(pred_order)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
for (i = pred_order; i < blocksize; i++)
|
||||
decoded[i] = a += decoded[i];
|
||||
break;
|
||||
case 2:
|
||||
for (i = pred_order; i < blocksize; i++)
|
||||
decoded[i] = a += b += decoded[i];
|
||||
break;
|
||||
case 3:
|
||||
for (i = pred_order; i < blocksize; i++)
|
||||
decoded[i] = a += b += c += decoded[i];
|
||||
break;
|
||||
case 4:
|
||||
for (i = pred_order; i < blocksize; i++)
|
||||
decoded[i] = a += b += c += d += decoded[i];
|
||||
break;
|
||||
default:
|
||||
av_log(s->avctx, AV_LOG_ERROR, "illegal pred order %d\n", pred_order);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int decode_subframe_lpc(FLACContext *s, int channel, int pred_order)
|
||||
{
|
||||
int i, j;
|
||||
int coeff_prec, qlevel;
|
||||
int coeffs[pred_order];
|
||||
int32_t *decoded = s->decoded[channel];
|
||||
|
||||
// av_log(s->avctx, AV_LOG_DEBUG, " SUBFRAME LPC\n");
|
||||
|
||||
/* warm up samples */
|
||||
// av_log(s->avctx, AV_LOG_DEBUG, " warm up samples: %d\n", pred_order);
|
||||
|
||||
for (i = 0; i < pred_order; i++)
|
||||
{
|
||||
decoded[i] = get_sbits(&s->gb, s->curr_bps);
|
||||
// av_log(s->avctx, AV_LOG_DEBUG, " %d: %d\n", i, decoded[i]);
|
||||
}
|
||||
|
||||
coeff_prec = get_bits(&s->gb, 4) + 1;
|
||||
if (coeff_prec == 16)
|
||||
{
|
||||
av_log(s->avctx, AV_LOG_DEBUG, "invalid coeff precision\n");
|
||||
return -1;
|
||||
}
|
||||
// av_log(s->avctx, AV_LOG_DEBUG, " qlp coeff prec: %d\n", coeff_prec);
|
||||
qlevel = get_sbits(&s->gb, 5);
|
||||
// av_log(s->avctx, AV_LOG_DEBUG, " quant level: %d\n", qlevel);
|
||||
if(qlevel < 0){
|
||||
av_log(s->avctx, AV_LOG_DEBUG, "qlevel %d not supported, maybe buggy stream\n", qlevel);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < pred_order; i++)
|
||||
{
|
||||
coeffs[i] = get_sbits(&s->gb, coeff_prec);
|
||||
// av_log(s->avctx, AV_LOG_DEBUG, " %d: %d\n", i, coeffs[i]);
|
||||
}
|
||||
|
||||
if (decode_residuals(s, channel, pred_order) < 0)
|
||||
return -1;
|
||||
|
||||
if (s->bps > 16) {
|
||||
int64_t sum;
|
||||
for (i = pred_order; i < s->blocksize; i++)
|
||||
{
|
||||
sum = 0;
|
||||
for (j = 0; j < pred_order; j++)
|
||||
sum += (int64_t)coeffs[j] * decoded[i-j-1];
|
||||
decoded[i] += sum >> qlevel;
|
||||
}
|
||||
} else {
|
||||
for (i = pred_order; i < s->blocksize-1; i += 2)
|
||||
{
|
||||
int c;
|
||||
int d = decoded[i-pred_order];
|
||||
int s0 = 0, s1 = 0;
|
||||
for (j = pred_order-1; j > 0; j--)
|
||||
{
|
||||
c = coeffs[j];
|
||||
s0 += c*d;
|
||||
d = decoded[i-j];
|
||||
s1 += c*d;
|
||||
}
|
||||
c = coeffs[0];
|
||||
s0 += c*d;
|
||||
d = decoded[i] += s0 >> qlevel;
|
||||
s1 += c*d;
|
||||
decoded[i+1] += s1 >> qlevel;
|
||||
}
|
||||
if (i < s->blocksize)
|
||||
{
|
||||
int sum = 0;
|
||||
for (j = 0; j < pred_order; j++)
|
||||
sum += coeffs[j] * decoded[i-j-1];
|
||||
decoded[i] += sum >> qlevel;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int decode_subframe(FLACContext *s, int channel)
|
||||
{
|
||||
int type, wasted = 0;
|
||||
int i, tmp;
|
||||
|
||||
s->curr_bps = s->bps;
|
||||
if(channel == 0){
|
||||
if(s->decorrelation == RIGHT_SIDE)
|
||||
s->curr_bps++;
|
||||
}else{
|
||||
if(s->decorrelation == LEFT_SIDE || s->decorrelation == MID_SIDE)
|
||||
s->curr_bps++;
|
||||
}
|
||||
|
||||
if (get_bits1(&s->gb))
|
||||
{
|
||||
av_log(s->avctx, AV_LOG_ERROR, "invalid subframe padding\n");
|
||||
return -1;
|
||||
}
|
||||
type = get_bits(&s->gb, 6);
|
||||
// wasted = get_bits1(&s->gb);
|
||||
|
||||
// if (wasted)
|
||||
// {
|
||||
// while (!get_bits1(&s->gb))
|
||||
// wasted++;
|
||||
// if (wasted)
|
||||
// wasted++;
|
||||
// s->curr_bps -= wasted;
|
||||
// }
|
||||
#if 0
|
||||
wasted= 16 - av_log2(show_bits(&s->gb, 17));
|
||||
skip_bits(&s->gb, wasted+1);
|
||||
s->curr_bps -= wasted;
|
||||
#else
|
||||
if (get_bits1(&s->gb))
|
||||
{
|
||||
wasted = 1;
|
||||
while (!get_bits1(&s->gb))
|
||||
wasted++;
|
||||
s->curr_bps -= wasted;
|
||||
av_log(s->avctx, AV_LOG_DEBUG, "%d wasted bits\n", wasted);
|
||||
}
|
||||
#endif
|
||||
//FIXME use av_log2 for types
|
||||
if (type == 0)
|
||||
{
|
||||
av_log(s->avctx, AV_LOG_DEBUG, "coding type: constant\n");
|
||||
tmp = get_sbits(&s->gb, s->curr_bps);
|
||||
for (i = 0; i < s->blocksize; i++)
|
||||
s->decoded[channel][i] = tmp;
|
||||
}
|
||||
else if (type == 1)
|
||||
{
|
||||
av_log(s->avctx, AV_LOG_DEBUG, "coding type: verbatim\n");
|
||||
for (i = 0; i < s->blocksize; i++)
|
||||
s->decoded[channel][i] = get_sbits(&s->gb, s->curr_bps);
|
||||
}
|
||||
else if ((type >= 8) && (type <= 12))
|
||||
{
|
||||
// av_log(s->avctx, AV_LOG_DEBUG, "coding type: fixed\n");
|
||||
if (decode_subframe_fixed(s, channel, type & ~0x8) < 0)
|
||||
return -1;
|
||||
}
|
||||
else if (type >= 32)
|
||||
{
|
||||
// av_log(s->avctx, AV_LOG_DEBUG, "coding type: lpc\n");
|
||||
if (decode_subframe_lpc(s, channel, (type & ~0x20)+1) < 0)
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
av_log(s->avctx, AV_LOG_ERROR, "invalid coding type\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (wasted)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < s->blocksize; i++)
|
||||
s->decoded[channel][i] <<= wasted;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int decode_frame(FLACContext *s, int alloc_data_size)
|
||||
{
|
||||
int blocksize_code, sample_rate_code, sample_size_code, assignment, i, crc8;
|
||||
int decorrelation, bps, blocksize, samplerate;
|
||||
|
||||
blocksize_code = get_bits(&s->gb, 4);
|
||||
|
||||
sample_rate_code = get_bits(&s->gb, 4);
|
||||
|
||||
assignment = get_bits(&s->gb, 4); /* channel assignment */
|
||||
if (assignment < 8 && s->channels == assignment+1)
|
||||
decorrelation = INDEPENDENT;
|
||||
else if (assignment >=8 && assignment < 11 && s->channels == 2)
|
||||
decorrelation = LEFT_SIDE + assignment - 8;
|
||||
else
|
||||
{
|
||||
av_log(s->avctx, AV_LOG_ERROR, "unsupported channel assignment %d (channels=%d)\n", assignment, s->channels);
|
||||
return -1;
|
||||
}
|
||||
|
||||
sample_size_code = get_bits(&s->gb, 3);
|
||||
if(sample_size_code == 0)
|
||||
bps= s->bps;
|
||||
else if((sample_size_code != 3) && (sample_size_code != 7))
|
||||
bps = sample_size_table[sample_size_code];
|
||||
else
|
||||
{
|
||||
av_log(s->avctx, AV_LOG_ERROR, "invalid sample size code (%d)\n", sample_size_code);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (get_bits1(&s->gb))
|
||||
{
|
||||
av_log(s->avctx, AV_LOG_ERROR, "broken stream, invalid padding\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(get_utf8(&s->gb) < 0){
|
||||
av_log(s->avctx, AV_LOG_ERROR, "utf8 fscked\n");
|
||||
return -1;
|
||||
}
|
||||
#if 0
|
||||
if (/*((blocksize_code == 6) || (blocksize_code == 7)) &&*/
|
||||
(s->min_blocksize != s->max_blocksize)){
|
||||
}else{
|
||||
}
|
||||
#endif
|
||||
|
||||
if (blocksize_code == 0)
|
||||
blocksize = s->min_blocksize;
|
||||
else if (blocksize_code == 6)
|
||||
blocksize = get_bits(&s->gb, 8)+1;
|
||||
else if (blocksize_code == 7)
|
||||
blocksize = get_bits(&s->gb, 16)+1;
|
||||
else
|
||||
blocksize = blocksize_table[blocksize_code];
|
||||
|
||||
if(blocksize > s->max_blocksize){
|
||||
av_log(s->avctx, AV_LOG_ERROR, "blocksize %d > %d\n", blocksize, s->max_blocksize);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(blocksize * s->channels * sizeof(int16_t) > alloc_data_size)
|
||||
return -1;
|
||||
|
||||
if (sample_rate_code == 0){
|
||||
samplerate= s->samplerate;
|
||||
}else if ((sample_rate_code > 3) && (sample_rate_code < 12))
|
||||
samplerate = sample_rate_table[sample_rate_code];
|
||||
else if (sample_rate_code == 12)
|
||||
samplerate = get_bits(&s->gb, 8) * 1000;
|
||||
else if (sample_rate_code == 13)
|
||||
samplerate = get_bits(&s->gb, 16);
|
||||
else if (sample_rate_code == 14)
|
||||
samplerate = get_bits(&s->gb, 16) * 10;
|
||||
else{
|
||||
av_log(s->avctx, AV_LOG_ERROR, "illegal sample rate code %d\n", sample_rate_code);
|
||||
return -1;
|
||||
}
|
||||
|
||||
skip_bits(&s->gb, 8);
|
||||
crc8 = av_crc(av_crc_get_table(AV_CRC_8_ATM), 0,
|
||||
s->gb.buffer, get_bits_count(&s->gb)/8);
|
||||
if(crc8){
|
||||
av_log(s->avctx, AV_LOG_ERROR, "header crc mismatch crc=%2X\n", crc8);
|
||||
return -1;
|
||||
}
|
||||
|
||||
s->blocksize = blocksize;
|
||||
s->samplerate = samplerate;
|
||||
s->bps = bps;
|
||||
s->decorrelation= decorrelation;
|
||||
|
||||
// dump_headers(s->avctx, (FLACStreaminfo *)s);
|
||||
|
||||
/* subframes */
|
||||
for (i = 0; i < s->channels; i++)
|
||||
{
|
||||
// av_log(s->avctx, AV_LOG_DEBUG, "decoded: %x residual: %x\n", s->decoded[i], s->residual[i]);
|
||||
if (decode_subframe(s, i) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
align_get_bits(&s->gb);
|
||||
|
||||
/* frame footer */
|
||||
skip_bits(&s->gb, 16); /* data crc */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int flac_decode_frame(AVCodecContext *avctx,
|
||||
void *data, int *data_size,
|
||||
const uint8_t *buf, int buf_size)
|
||||
{
|
||||
FLACContext *s = avctx->priv_data;
|
||||
int tmp = 0, i, j = 0, input_buf_size = 0;
|
||||
int16_t *samples = data;
|
||||
int alloc_data_size= *data_size;
|
||||
|
||||
*data_size=0;
|
||||
|
||||
if(s->max_framesize == 0){
|
||||
s->max_framesize= 65536; // should hopefully be enough for the first header
|
||||
s->bitstream= av_fast_realloc(s->bitstream, &s->allocated_bitstream_size, s->max_framesize);
|
||||
}
|
||||
|
||||
if(1 && s->max_framesize){//FIXME truncated
|
||||
if(s->bitstream_size < 4 || AV_RL32(s->bitstream) != MKTAG('f','L','a','C'))
|
||||
buf_size= FFMIN(buf_size, s->max_framesize - FFMIN(s->bitstream_size, s->max_framesize));
|
||||
input_buf_size= buf_size;
|
||||
|
||||
if(s->bitstream_size + buf_size < buf_size || s->bitstream_index + s->bitstream_size + buf_size < s->bitstream_index)
|
||||
return -1;
|
||||
|
||||
if(s->allocated_bitstream_size < s->bitstream_size + buf_size)
|
||||
s->bitstream= av_fast_realloc(s->bitstream, &s->allocated_bitstream_size, s->bitstream_size + buf_size);
|
||||
|
||||
if(s->bitstream_index + s->bitstream_size + buf_size > s->allocated_bitstream_size){
|
||||
// printf("memmove\n");
|
||||
memmove(s->bitstream, &s->bitstream[s->bitstream_index], s->bitstream_size);
|
||||
s->bitstream_index=0;
|
||||
}
|
||||
memcpy(&s->bitstream[s->bitstream_index + s->bitstream_size], buf, buf_size);
|
||||
buf= &s->bitstream[s->bitstream_index];
|
||||
buf_size += s->bitstream_size;
|
||||
s->bitstream_size= buf_size;
|
||||
|
||||
if(buf_size < s->max_framesize && input_buf_size){
|
||||
// printf("wanna more data ...\n");
|
||||
return input_buf_size;
|
||||
}
|
||||
}
|
||||
|
||||
init_get_bits(&s->gb, buf, buf_size*8);
|
||||
|
||||
if(metadata_parse(s))
|
||||
goto end;
|
||||
|
||||
tmp = show_bits(&s->gb, 16);
|
||||
if((tmp & 0xFFFE) != 0xFFF8){
|
||||
av_log(s->avctx, AV_LOG_ERROR, "FRAME HEADER not here\n");
|
||||
while(get_bits_count(&s->gb)/8+2 < buf_size && (show_bits(&s->gb, 16) & 0xFFFE) != 0xFFF8)
|
||||
skip_bits(&s->gb, 8);
|
||||
goto end; // we may not have enough bits left to decode a frame, so try next time
|
||||
}
|
||||
skip_bits(&s->gb, 16);
|
||||
if (decode_frame(s, alloc_data_size) < 0){
|
||||
av_log(s->avctx, AV_LOG_ERROR, "decode_frame() failed\n");
|
||||
s->bitstream_size=0;
|
||||
s->bitstream_index=0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
/* fix the channel order here */
|
||||
if (s->order == MID_SIDE)
|
||||
{
|
||||
short *left = samples;
|
||||
short *right = samples + s->blocksize;
|
||||
for (i = 0; i < s->blocksize; i += 2)
|
||||
{
|
||||
uint32_t x = s->decoded[0][i];
|
||||
uint32_t y = s->decoded[0][i+1];
|
||||
|
||||
right[i] = x - (y / 2);
|
||||
left[i] = right[i] + y;
|
||||
}
|
||||
*data_size = 2 * s->blocksize;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < s->channels; i++)
|
||||
{
|
||||
switch(s->order)
|
||||
{
|
||||
case INDEPENDENT:
|
||||
for (j = 0; j < s->blocksize; j++)
|
||||
samples[(s->blocksize*i)+j] = s->decoded[i][j];
|
||||
break;
|
||||
case LEFT_SIDE:
|
||||
case RIGHT_SIDE:
|
||||
if (i == 0)
|
||||
for (j = 0; j < s->blocksize; j++)
|
||||
samples[(s->blocksize*i)+j] = s->decoded[0][j];
|
||||
else
|
||||
for (j = 0; j < s->blocksize; j++)
|
||||
samples[(s->blocksize*i)+j] = s->decoded[0][j] - s->decoded[i][j];
|
||||
break;
|
||||
// case MID_SIDE:
|
||||
// av_log(s->avctx, AV_LOG_DEBUG, "mid-side unsupported\n");
|
||||
}
|
||||
*data_size += s->blocksize;
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define DECORRELATE(left, right)\
|
||||
assert(s->channels == 2);\
|
||||
for (i = 0; i < s->blocksize; i++)\
|
||||
{\
|
||||
int a= s->decoded[0][i];\
|
||||
int b= s->decoded[1][i];\
|
||||
*samples++ = ((left) << (24 - s->bps)) >> 8;\
|
||||
*samples++ = ((right) << (24 - s->bps)) >> 8;\
|
||||
}\
|
||||
break;
|
||||
|
||||
switch(s->decorrelation)
|
||||
{
|
||||
case INDEPENDENT:
|
||||
for (j = 0; j < s->blocksize; j++)
|
||||
{
|
||||
for (i = 0; i < s->channels; i++)
|
||||
*samples++ = (s->decoded[i][j] << (24 - s->bps)) >> 8;
|
||||
}
|
||||
break;
|
||||
case LEFT_SIDE:
|
||||
DECORRELATE(a,a-b)
|
||||
case RIGHT_SIDE:
|
||||
DECORRELATE(a+b,b)
|
||||
case MID_SIDE:
|
||||
DECORRELATE( (a-=b>>1) + b, a)
|
||||
}
|
||||
#endif
|
||||
|
||||
*data_size = (int8_t *)samples - (int8_t *)data;
|
||||
// av_log(s->avctx, AV_LOG_DEBUG, "data size: %d\n", *data_size);
|
||||
|
||||
// s->last_blocksize = s->blocksize;
|
||||
end:
|
||||
i= (get_bits_count(&s->gb)+7)/8;
|
||||
if(i > buf_size){
|
||||
av_log(s->avctx, AV_LOG_ERROR, "overread: %d\n", i - buf_size);
|
||||
s->bitstream_size=0;
|
||||
s->bitstream_index=0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(s->bitstream_size){
|
||||
s->bitstream_index += i;
|
||||
s->bitstream_size -= i;
|
||||
return input_buf_size;
|
||||
}else
|
||||
return i;
|
||||
}
|
||||
|
||||
static av_cold int flac_decode_close(AVCodecContext *avctx)
|
||||
{
|
||||
FLACContext *s = avctx->priv_data;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < s->channels; i++)
|
||||
{
|
||||
av_freep(&s->decoded[i]);
|
||||
}
|
||||
av_freep(&s->bitstream);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void flac_flush(AVCodecContext *avctx){
|
||||
FLACContext *s = avctx->priv_data;
|
||||
|
||||
s->bitstream_size=
|
||||
s->bitstream_index= 0;
|
||||
}
|
||||
|
||||
AVCodec flac_decoder = {
|
||||
"flac",
|
||||
CODEC_TYPE_AUDIO,
|
||||
CODEC_ID_FLAC,
|
||||
sizeof(FLACContext),
|
||||
flac_decode_init,
|
||||
NULL,
|
||||
flac_decode_close,
|
||||
flac_decode_frame,
|
||||
CODEC_CAP_DELAY,
|
||||
.flush= flac_flush,
|
||||
.long_name= NULL_IF_CONFIG_SMALL("FLAC (Free Lossless Audio Codec)"),
|
||||
};
|
57
src/add-ons/media/plugins/avcodec/libavcodec/flac.h
Normal file
57
src/add-ons/media/plugins/avcodec/libavcodec/flac.h
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* FLAC (Free Lossless Audio Codec) decoder/demuxer common functions
|
||||
* Copyright (c) 2008 Justin Ruggles
|
||||
*
|
||||
* 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 flac.h
|
||||
* FLAC (Free Lossless Audio Codec) decoder/demuxer common functions
|
||||
*/
|
||||
|
||||
#ifndef FFMPEG_FLAC_H
|
||||
#define FFMPEG_FLAC_H
|
||||
|
||||
#include "avcodec.h"
|
||||
|
||||
/**
|
||||
* Data needed from the Streaminfo header for use by the raw FLAC demuxer
|
||||
* and/or the FLAC decoder.
|
||||
*/
|
||||
#define FLACSTREAMINFO \
|
||||
int min_blocksize; /**< minimum block size, in samples */\
|
||||
int max_blocksize; /**< maximum block size, in samples */\
|
||||
int max_framesize; /**< maximum frame size, in bytes */\
|
||||
int samplerate; /**< sample rate */\
|
||||
int channels; /**< number of channels */\
|
||||
int bps; /**< bits-per-sample */\
|
||||
|
||||
typedef struct FLACStreaminfo {
|
||||
FLACSTREAMINFO
|
||||
} FLACStreaminfo;
|
||||
|
||||
/**
|
||||
* Parse the Streaminfo metadata block
|
||||
* @param[out] avctx codec context to set basic stream parameters
|
||||
* @param[out] s where parsed information is stored
|
||||
* @param[in] buffer pointer to start of 34-byte streaminfo data
|
||||
*/
|
||||
void ff_flac_parse_streaminfo(AVCodecContext *avctx, struct FLACStreaminfo *s,
|
||||
const uint8_t *buffer);
|
||||
|
||||
#endif /* FFMPEG_FLAC_H */
|
1310
src/add-ons/media/plugins/avcodec/libavcodec/flacenc.c
Normal file
1310
src/add-ons/media/plugins/avcodec/libavcodec/flacenc.c
Normal file
File diff suppressed because it is too large
Load Diff
259
src/add-ons/media/plugins/avcodec/libavcodec/flashsv.c
Normal file
259
src/add-ons/media/plugins/avcodec/libavcodec/flashsv.c
Normal file
@ -0,0 +1,259 @@
|
||||
/*
|
||||
* Flash Screen Video decoder
|
||||
* Copyright (C) 2004 Alex Beregszaszi
|
||||
* Copyright (C) 2006 Benjamin Larsson
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file flashsv.c
|
||||
* Flash Screen Video decoder
|
||||
* @author Alex Beregszaszi
|
||||
* @author Benjamin Larsson
|
||||
*/
|
||||
|
||||
/* Bitstream description
|
||||
* The picture is divided into blocks that are zlib compressed.
|
||||
*
|
||||
* The decoder is fed complete frames, the frameheader contains:
|
||||
* 4bits of block width
|
||||
* 12bits of frame width
|
||||
* 4bits of block height
|
||||
* 12bits of frame height
|
||||
*
|
||||
* Directly after the header are the compressed blocks. The blocks
|
||||
* have their compressed size represented with 16bits in the beginnig.
|
||||
* If the size = 0 then the block is unchanged from the previous frame.
|
||||
* All blocks are decompressed until the buffer is consumed.
|
||||
*
|
||||
* Encoding ideas, a basic encoder would just use a fixed block size.
|
||||
* Block sizes can be multipels of 16, from 16 to 256. The blocks don't
|
||||
* have to be quadratic. A brute force search with a set of diffrent
|
||||
* block sizes should give a better result then to just use a fixed size.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "avcodec.h"
|
||||
#include "bitstream.h"
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
typedef struct FlashSVContext {
|
||||
AVCodecContext *avctx;
|
||||
AVFrame frame;
|
||||
int image_width, image_height;
|
||||
int block_width, block_height;
|
||||
uint8_t* tmpblock;
|
||||
int block_size;
|
||||
z_stream zstream;
|
||||
} FlashSVContext;
|
||||
|
||||
|
||||
static void copy_region(uint8_t *sptr, uint8_t *dptr,
|
||||
int dx, int dy, int h, int w, int stride)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = dx+h; i > dx; i--)
|
||||
{
|
||||
memcpy(dptr+(i*stride)+dy*3, sptr, w*3);
|
||||
sptr += w*3;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static av_cold int flashsv_decode_init(AVCodecContext *avctx)
|
||||
{
|
||||
FlashSVContext *s = avctx->priv_data;
|
||||
int zret; // Zlib return code
|
||||
|
||||
s->avctx = avctx;
|
||||
s->zstream.zalloc = Z_NULL;
|
||||
s->zstream.zfree = Z_NULL;
|
||||
s->zstream.opaque = Z_NULL;
|
||||
zret = inflateInit(&(s->zstream));
|
||||
if (zret != Z_OK) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Inflate init error: %d\n", zret);
|
||||
return 1;
|
||||
}
|
||||
avctx->pix_fmt = PIX_FMT_BGR24;
|
||||
s->frame.data[0] = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int flashsv_decode_frame(AVCodecContext *avctx,
|
||||
void *data, int *data_size,
|
||||
const uint8_t *buf, int buf_size)
|
||||
{
|
||||
FlashSVContext *s = avctx->priv_data;
|
||||
int h_blocks, v_blocks, h_part, v_part, i, j;
|
||||
GetBitContext gb;
|
||||
|
||||
/* no supplementary picture */
|
||||
if (buf_size == 0)
|
||||
return 0;
|
||||
|
||||
if(s->frame.data[0])
|
||||
avctx->release_buffer(avctx, &s->frame);
|
||||
|
||||
init_get_bits(&gb, buf, buf_size * 8);
|
||||
|
||||
/* start to parse the bitstream */
|
||||
s->block_width = 16* (get_bits(&gb, 4)+1);
|
||||
s->image_width = get_bits(&gb,12);
|
||||
s->block_height= 16* (get_bits(&gb, 4)+1);
|
||||
s->image_height= get_bits(&gb,12);
|
||||
|
||||
/* calculate amount of blocks and the size of the border blocks */
|
||||
h_blocks = s->image_width / s->block_width;
|
||||
h_part = s->image_width % s->block_width;
|
||||
v_blocks = s->image_height / s->block_height;
|
||||
v_part = s->image_height % s->block_height;
|
||||
|
||||
/* the block size could change between frames, make sure the buffer
|
||||
* is large enough, if not, get a larger one */
|
||||
if(s->block_size < s->block_width*s->block_height) {
|
||||
if (s->tmpblock != NULL)
|
||||
av_free(s->tmpblock);
|
||||
if ((s->tmpblock = av_malloc(3*s->block_width*s->block_height)) == NULL) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Can't allocate decompression buffer.\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
s->block_size = s->block_width*s->block_height;
|
||||
|
||||
/* init the image size once */
|
||||
if((avctx->width==0) && (avctx->height==0)){
|
||||
avctx->width = s->image_width;
|
||||
avctx->height = s->image_height;
|
||||
}
|
||||
|
||||
/* check for changes of image width and image height */
|
||||
if ((avctx->width != s->image_width) || (avctx->height != s->image_height)) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Frame width or height differs from first frames!\n");
|
||||
av_log(avctx, AV_LOG_ERROR, "fh = %d, fv %d vs ch = %d, cv = %d\n",avctx->height,
|
||||
avctx->width,s->image_height,s->image_width);
|
||||
return -1;
|
||||
}
|
||||
|
||||
av_log(avctx, AV_LOG_DEBUG, "image: %dx%d block: %dx%d num: %dx%d part: %dx%d\n",
|
||||
s->image_width, s->image_height, s->block_width, s->block_height,
|
||||
h_blocks, v_blocks, h_part, v_part);
|
||||
|
||||
s->frame.reference = 1;
|
||||
s->frame.buffer_hints = FF_BUFFER_HINTS_VALID;
|
||||
if (avctx->get_buffer(avctx, &s->frame) < 0) {
|
||||
av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* loop over all block columns */
|
||||
for (j = 0; j < v_blocks + (v_part?1:0); j++)
|
||||
{
|
||||
|
||||
int hp = j*s->block_height; // horiz position in frame
|
||||
int hs = (j<v_blocks)?s->block_height:v_part; // size of block
|
||||
|
||||
|
||||
/* loop over all block rows */
|
||||
for (i = 0; i < h_blocks + (h_part?1:0); i++)
|
||||
{
|
||||
int wp = i*s->block_width; // vert position in frame
|
||||
int ws = (i<h_blocks)?s->block_width:h_part; // size of block
|
||||
|
||||
/* get the size of the compressed zlib chunk */
|
||||
int size = get_bits(&gb, 16);
|
||||
|
||||
if (size == 0) {
|
||||
/* no change, don't do anything */
|
||||
} else {
|
||||
/* decompress block */
|
||||
int ret = inflateReset(&(s->zstream));
|
||||
if (ret != Z_OK)
|
||||
{
|
||||
av_log(avctx, AV_LOG_ERROR, "error in decompression (reset) of block %dx%d\n", i, j);
|
||||
/* return -1; */
|
||||
}
|
||||
s->zstream.next_in = buf+(get_bits_count(&gb)/8);
|
||||
s->zstream.avail_in = size;
|
||||
s->zstream.next_out = s->tmpblock;
|
||||
s->zstream.avail_out = s->block_size*3;
|
||||
ret = inflate(&(s->zstream), Z_FINISH);
|
||||
if (ret == Z_DATA_ERROR)
|
||||
{
|
||||
av_log(avctx, AV_LOG_ERROR, "Zlib resync occurred\n");
|
||||
inflateSync(&(s->zstream));
|
||||
ret = inflate(&(s->zstream), Z_FINISH);
|
||||
}
|
||||
|
||||
if ((ret != Z_OK) && (ret != Z_STREAM_END))
|
||||
{
|
||||
av_log(avctx, AV_LOG_ERROR, "error in decompression of block %dx%d: %d\n", i, j, ret);
|
||||
/* return -1; */
|
||||
}
|
||||
copy_region(s->tmpblock, s->frame.data[0], s->image_height-(hp+hs+1), wp, hs, ws, s->frame.linesize[0]);
|
||||
skip_bits(&gb, 8*size); /* skip the consumed bits */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*data_size = sizeof(AVFrame);
|
||||
*(AVFrame*)data = s->frame;
|
||||
|
||||
if ((get_bits_count(&gb)/8) != buf_size)
|
||||
av_log(avctx, AV_LOG_ERROR, "buffer not fully consumed (%d != %d)\n",
|
||||
buf_size, (get_bits_count(&gb)/8));
|
||||
|
||||
/* report that the buffer was completely consumed */
|
||||
return buf_size;
|
||||
}
|
||||
|
||||
|
||||
static av_cold int flashsv_decode_end(AVCodecContext *avctx)
|
||||
{
|
||||
FlashSVContext *s = avctx->priv_data;
|
||||
inflateEnd(&(s->zstream));
|
||||
/* release the frame if needed */
|
||||
if (s->frame.data[0])
|
||||
avctx->release_buffer(avctx, &s->frame);
|
||||
|
||||
/* free the tmpblock */
|
||||
if (s->tmpblock != NULL)
|
||||
av_free(s->tmpblock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
AVCodec flashsv_decoder = {
|
||||
"flashsv",
|
||||
CODEC_TYPE_VIDEO,
|
||||
CODEC_ID_FLASHSV,
|
||||
sizeof(FlashSVContext),
|
||||
flashsv_decode_init,
|
||||
NULL,
|
||||
flashsv_decode_end,
|
||||
flashsv_decode_frame,
|
||||
CODEC_CAP_DR1,
|
||||
.pix_fmts = (enum PixelFormat[]){PIX_FMT_BGR24, PIX_FMT_NONE},
|
||||
.long_name = NULL_IF_CONFIG_SMALL("Flash Screen Video v1"),
|
||||
};
|
298
src/add-ons/media/plugins/avcodec/libavcodec/flashsvenc.c
Normal file
298
src/add-ons/media/plugins/avcodec/libavcodec/flashsvenc.c
Normal file
@ -0,0 +1,298 @@
|
||||
/*
|
||||
* Flash Screen Video encoder
|
||||
* Copyright (C) 2004 Alex Beregszaszi
|
||||
* Copyright (C) 2006 Benjamin Larsson
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/* Encoding development sponsored by http://fh-campuswien.ac.at */
|
||||
|
||||
/**
|
||||
* @file flashsvenc.c
|
||||
* Flash Screen Video encoder
|
||||
* @author Alex Beregszaszi
|
||||
* @author Benjamin Larsson
|
||||
*/
|
||||
|
||||
/* Bitstream description
|
||||
* The picture is divided into blocks that are zlib-compressed.
|
||||
*
|
||||
* The decoder is fed complete frames, the frameheader contains:
|
||||
* 4bits of block width
|
||||
* 12bits of frame width
|
||||
* 4bits of block height
|
||||
* 12bits of frame height
|
||||
*
|
||||
* Directly after the header are the compressed blocks. The blocks
|
||||
* have their compressed size represented with 16bits in the beginig.
|
||||
* If the size = 0 then the block is unchanged from the previous frame.
|
||||
* All blocks are decompressed until the buffer is consumed.
|
||||
*
|
||||
* Encoding ideas, a basic encoder would just use a fixed block size.
|
||||
* Block sizes can be multipels of 16, from 16 to 256. The blocks don't
|
||||
* have to be quadratic. A brute force search with a set of different
|
||||
* block sizes should give a better result than to just use a fixed size.
|
||||
*/
|
||||
|
||||
/* TODO:
|
||||
* Don't reencode the frame in brute force mode if the frame is a dupe. Speed up.
|
||||
* Make the difference check faster.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <zlib.h>
|
||||
|
||||
#include "avcodec.h"
|
||||
#include "bitstream.h"
|
||||
#include "bytestream.h"
|
||||
|
||||
|
||||
typedef struct FlashSVContext {
|
||||
AVCodecContext *avctx;
|
||||
uint8_t *previous_frame;
|
||||
AVFrame frame;
|
||||
int image_width, image_height;
|
||||
int block_width, block_height;
|
||||
uint8_t* tmpblock;
|
||||
uint8_t* encbuffer;
|
||||
int block_size;
|
||||
z_stream zstream;
|
||||
int last_key_frame;
|
||||
} FlashSVContext;
|
||||
|
||||
static int copy_region_enc(uint8_t *sptr, uint8_t *dptr,
|
||||
int dx, int dy, int h, int w, int stride, uint8_t *pfptr) {
|
||||
int i,j;
|
||||
uint8_t *nsptr;
|
||||
uint8_t *npfptr;
|
||||
int diff = 0;
|
||||
|
||||
for (i = dx+h; i > dx; i--) {
|
||||
nsptr = sptr+(i*stride)+dy*3;
|
||||
npfptr = pfptr+(i*stride)+dy*3;
|
||||
for (j=0 ; j<w*3 ; j++) {
|
||||
diff |=npfptr[j]^nsptr[j];
|
||||
dptr[j] = nsptr[j];
|
||||
}
|
||||
dptr += w*3;
|
||||
}
|
||||
if (diff)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static av_cold int flashsv_encode_init(AVCodecContext *avctx)
|
||||
{
|
||||
FlashSVContext *s = avctx->priv_data;
|
||||
|
||||
s->avctx = avctx;
|
||||
|
||||
if ((avctx->width > 4095) || (avctx->height > 4095)) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Input dimensions too large, input must be max 4096x4096 !\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (avcodec_check_dimensions(avctx, avctx->width, avctx->height) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Needed if zlib unused or init aborted before deflateInit
|
||||
memset(&(s->zstream), 0, sizeof(z_stream));
|
||||
|
||||
s->last_key_frame=0;
|
||||
|
||||
s->image_width = avctx->width;
|
||||
s->image_height = avctx->height;
|
||||
|
||||
s->tmpblock = av_mallocz(3*256*256);
|
||||
s->encbuffer = av_mallocz(s->image_width*s->image_height*3);
|
||||
|
||||
if (!s->tmpblock || !s->encbuffer) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Memory allocation failed.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int encode_bitstream(FlashSVContext *s, AVFrame *p, uint8_t *buf, int buf_size,
|
||||
int block_width, int block_height, uint8_t *previous_frame, int* I_frame) {
|
||||
|
||||
PutBitContext pb;
|
||||
int h_blocks, v_blocks, h_part, v_part, i, j;
|
||||
int buf_pos, res;
|
||||
int pred_blocks = 0;
|
||||
|
||||
init_put_bits(&pb, buf, buf_size*8);
|
||||
|
||||
put_bits(&pb, 4, (block_width/16)-1);
|
||||
put_bits(&pb, 12, s->image_width);
|
||||
put_bits(&pb, 4, (block_height/16)-1);
|
||||
put_bits(&pb, 12, s->image_height);
|
||||
flush_put_bits(&pb);
|
||||
buf_pos=4;
|
||||
|
||||
h_blocks = s->image_width / block_width;
|
||||
h_part = s->image_width % block_width;
|
||||
v_blocks = s->image_height / block_height;
|
||||
v_part = s->image_height % block_height;
|
||||
|
||||
/* loop over all block columns */
|
||||
for (j = 0; j < v_blocks + (v_part?1:0); j++)
|
||||
{
|
||||
|
||||
int hp = j*block_height; // horiz position in frame
|
||||
int hs = (j<v_blocks)?block_height:v_part; // size of block
|
||||
|
||||
/* loop over all block rows */
|
||||
for (i = 0; i < h_blocks + (h_part?1:0); i++)
|
||||
{
|
||||
int wp = i*block_width; // vert position in frame
|
||||
int ws = (i<h_blocks)?block_width:h_part; // size of block
|
||||
int ret=Z_OK;
|
||||
uint8_t *ptr;
|
||||
|
||||
ptr = buf+buf_pos;
|
||||
|
||||
//copy the block to the temp buffer before compression (if it differs from the previous frame's block)
|
||||
res = copy_region_enc(p->data[0], s->tmpblock, s->image_height-(hp+hs+1), wp, hs, ws, p->linesize[0], previous_frame);
|
||||
|
||||
if (res || *I_frame) {
|
||||
unsigned long zsize;
|
||||
zsize = 3*block_width*block_height;
|
||||
ret = compress2(ptr+2, &zsize, s->tmpblock, 3*ws*hs, 9);
|
||||
|
||||
|
||||
//ret = deflateReset(&(s->zstream));
|
||||
if (ret != Z_OK)
|
||||
av_log(s->avctx, AV_LOG_ERROR, "error while compressing block %dx%d\n", i, j);
|
||||
|
||||
bytestream_put_be16(&ptr,(unsigned int)zsize);
|
||||
buf_pos += zsize+2;
|
||||
//av_log(avctx, AV_LOG_ERROR, "buf_pos = %d\n", buf_pos);
|
||||
} else {
|
||||
pred_blocks++;
|
||||
bytestream_put_be16(&ptr,0);
|
||||
buf_pos += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pred_blocks)
|
||||
*I_frame = 0;
|
||||
else
|
||||
*I_frame = 1;
|
||||
|
||||
return buf_pos;
|
||||
}
|
||||
|
||||
|
||||
static int flashsv_encode_frame(AVCodecContext *avctx, uint8_t *buf, int buf_size, void *data)
|
||||
{
|
||||
FlashSVContext * const s = avctx->priv_data;
|
||||
AVFrame *pict = data;
|
||||
AVFrame * const p = &s->frame;
|
||||
uint8_t *pfptr;
|
||||
int res;
|
||||
int I_frame = 0;
|
||||
int opt_w, opt_h;
|
||||
|
||||
*p = *pict;
|
||||
|
||||
/* First frame needs to be a keyframe */
|
||||
if (avctx->frame_number == 0) {
|
||||
s->previous_frame = av_mallocz(FFABS(p->linesize[0])*s->image_height);
|
||||
if (!s->previous_frame) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Memory allocation failed.\n");
|
||||
return -1;
|
||||
}
|
||||
I_frame = 1;
|
||||
}
|
||||
|
||||
if (p->linesize[0] < 0)
|
||||
pfptr = s->previous_frame - ((s->image_height-1) * p->linesize[0]);
|
||||
else
|
||||
pfptr = s->previous_frame;
|
||||
|
||||
/* Check the placement of keyframes */
|
||||
if (avctx->gop_size > 0) {
|
||||
if (avctx->frame_number >= s->last_key_frame + avctx->gop_size) {
|
||||
I_frame = 1;
|
||||
}
|
||||
}
|
||||
|
||||
opt_w=4;
|
||||
opt_h=4;
|
||||
|
||||
if (buf_size < s->image_width*s->image_height*3) {
|
||||
//Conservative upper bound check for compressed data
|
||||
av_log(avctx, AV_LOG_ERROR, "buf_size %d < %d\n", buf_size, s->image_width*s->image_height*3);
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = encode_bitstream(s, p, buf, buf_size, opt_w*16, opt_h*16, pfptr, &I_frame);
|
||||
|
||||
//save the current frame
|
||||
if(p->linesize[0] > 0)
|
||||
memcpy(s->previous_frame, p->data[0], s->image_height*p->linesize[0]);
|
||||
else
|
||||
memcpy(s->previous_frame, p->data[0] + p->linesize[0] * (s->image_height-1), s->image_height*FFABS(p->linesize[0]));
|
||||
|
||||
//mark the frame type so the muxer can mux it correctly
|
||||
if (I_frame) {
|
||||
p->pict_type = FF_I_TYPE;
|
||||
p->key_frame = 1;
|
||||
s->last_key_frame = avctx->frame_number;
|
||||
av_log(avctx, AV_LOG_DEBUG, "Inserting key frame at frame %d\n",avctx->frame_number);
|
||||
} else {
|
||||
p->pict_type = FF_P_TYPE;
|
||||
p->key_frame = 0;
|
||||
}
|
||||
|
||||
avctx->coded_frame = p;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static av_cold int flashsv_encode_end(AVCodecContext *avctx)
|
||||
{
|
||||
FlashSVContext *s = avctx->priv_data;
|
||||
|
||||
deflateEnd(&(s->zstream));
|
||||
|
||||
av_free(s->encbuffer);
|
||||
av_free(s->previous_frame);
|
||||
av_free(s->tmpblock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
AVCodec flashsv_encoder = {
|
||||
"flashsv",
|
||||
CODEC_TYPE_VIDEO,
|
||||
CODEC_ID_FLASHSV,
|
||||
sizeof(FlashSVContext),
|
||||
flashsv_encode_init,
|
||||
flashsv_encode_frame,
|
||||
flashsv_encode_end,
|
||||
.pix_fmts = (enum PixelFormat[]){PIX_FMT_BGR24, PIX_FMT_NONE},
|
||||
.long_name = NULL_IF_CONFIG_SMALL("Flash Screen Video"),
|
||||
};
|
||||
|
@ -2,20 +2,21 @@
|
||||
* FLI/FLC Animation Video Decoder
|
||||
* Copyright (C) 2003, 2004 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
|
||||
* 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
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
@ -26,7 +27,8 @@
|
||||
* variations, visit:
|
||||
* http://www.compuphase.com/flic.htm
|
||||
*
|
||||
* This decoder outputs PAL8 colorspace data. To use this decoder, be
|
||||
* This decoder outputs PAL8/RGB555/RGB565 and maybe one day RGB24
|
||||
* colorspace data, depending on the FLC. To use this decoder, be
|
||||
* sure that your demuxer sends the FLI file header to the decoder via
|
||||
* the extradata chunk in AVCodecContext. The chunk should be 128 bytes
|
||||
* large. The only exception is for FLI files from the game "Magic Carpet",
|
||||
@ -38,9 +40,8 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "avcodec.h"
|
||||
#include "bswap.h"
|
||||
#include "avcodec.h"
|
||||
|
||||
#define FLI_256_COLOR 4
|
||||
#define FLI_DELTA 7
|
||||
@ -50,12 +51,21 @@
|
||||
#define FLI_BRUN 15
|
||||
#define FLI_COPY 16
|
||||
#define FLI_MINI 18
|
||||
#define FLI_DTA_BRUN 25
|
||||
#define FLI_DTA_COPY 26
|
||||
#define FLI_DTA_LC 27
|
||||
|
||||
#define LE_16(x) ((((uint8_t*)(x))[1] << 8) | ((uint8_t*)(x))[0])
|
||||
#define LE_32(x) ((((uint8_t*)(x))[3] << 24) | \
|
||||
(((uint8_t*)(x))[2] << 16) | \
|
||||
(((uint8_t*)(x))[1] << 8) | \
|
||||
((uint8_t*)(x))[0])
|
||||
#define FLI_TYPE_CODE (0xAF11)
|
||||
#define FLC_FLX_TYPE_CODE (0xAF12)
|
||||
#define FLC_DTA_TYPE_CODE (0xAF44) /* Marks an "Extended FLC" comes from Dave's Targa Animator (DTA) */
|
||||
#define FLC_MAGIC_CARPET_SYNTHETIC_TYPE_CODE (0xAF13)
|
||||
|
||||
#define CHECK_PIXEL_PTR(n) \
|
||||
if (pixel_ptr + n > pixel_limit) { \
|
||||
av_log (s->avctx, AV_LOG_INFO, "Problem: pixel_ptr >= pixel_limit (%d >= %d)\n", \
|
||||
pixel_ptr + n, pixel_limit); \
|
||||
return -1; \
|
||||
} \
|
||||
|
||||
typedef struct FlicDecodeContext {
|
||||
AVCodecContext *avctx;
|
||||
@ -66,23 +76,47 @@ typedef struct FlicDecodeContext {
|
||||
int fli_type; /* either 0xAF11 or 0xAF12, affects palette resolution */
|
||||
} FlicDecodeContext;
|
||||
|
||||
static int flic_decode_init(AVCodecContext *avctx)
|
||||
static av_cold int flic_decode_init(AVCodecContext *avctx)
|
||||
{
|
||||
FlicDecodeContext *s = (FlicDecodeContext *)avctx->priv_data;
|
||||
FlicDecodeContext *s = avctx->priv_data;
|
||||
unsigned char *fli_header = (unsigned char *)avctx->extradata;
|
||||
int depth;
|
||||
|
||||
s->avctx = avctx;
|
||||
avctx->pix_fmt = PIX_FMT_PAL8;
|
||||
avctx->has_b_frames = 0;
|
||||
|
||||
s->fli_type = AV_RL16(&fli_header[4]); /* Might be overridden if a Magic Carpet FLC */
|
||||
|
||||
depth = 0;
|
||||
if (s->avctx->extradata_size == 12) {
|
||||
/* special case for magic carpet FLIs */
|
||||
s->fli_type = 0xAF13;
|
||||
} else if (s->avctx->extradata_size == 128) {
|
||||
s->fli_type = LE_16(&fli_header[4]);
|
||||
} else {
|
||||
s->fli_type = FLC_MAGIC_CARPET_SYNTHETIC_TYPE_CODE;
|
||||
depth = 8;
|
||||
} else if (s->avctx->extradata_size != 128) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Expected extradata of 12 or 128 bytes\n");
|
||||
return -1;
|
||||
} else {
|
||||
depth = AV_RL16(&fli_header[12]);
|
||||
}
|
||||
|
||||
if (depth == 0) {
|
||||
depth = 8; /* Some FLC generators set depth to zero, when they mean 8Bpp. Fix up here */
|
||||
}
|
||||
|
||||
if ((s->fli_type == FLC_FLX_TYPE_CODE) && (depth == 16)) {
|
||||
depth = 15; /* Original Autodesk FLX's say the depth is 16Bpp when it is really 15Bpp */
|
||||
}
|
||||
|
||||
switch (depth) {
|
||||
case 8 : avctx->pix_fmt = PIX_FMT_PAL8; break;
|
||||
case 15 : avctx->pix_fmt = PIX_FMT_RGB555; break;
|
||||
case 16 : avctx->pix_fmt = PIX_FMT_RGB565; break;
|
||||
case 24 : avctx->pix_fmt = PIX_FMT_BGR24; /* Supposedly BGR, but havent any files to test with */
|
||||
av_log(avctx, AV_LOG_ERROR, "24Bpp FLC/FLX is unsupported due to no test files.\n");
|
||||
return -1;
|
||||
break;
|
||||
default :
|
||||
av_log(avctx, AV_LOG_ERROR, "Unknown FLC/FLX depth of %d Bpp is unsupported.\n",depth);
|
||||
return -1;
|
||||
}
|
||||
|
||||
s->frame.data[0] = NULL;
|
||||
@ -91,11 +125,11 @@ static int flic_decode_init(AVCodecContext *avctx)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int flic_decode_frame(AVCodecContext *avctx,
|
||||
void *data, int *data_size,
|
||||
uint8_t *buf, int buf_size)
|
||||
static int flic_decode_frame_8BPP(AVCodecContext *avctx,
|
||||
void *data, int *data_size,
|
||||
const uint8_t *buf, int buf_size)
|
||||
{
|
||||
FlicDecodeContext *s = (FlicDecodeContext *)avctx->priv_data;
|
||||
FlicDecodeContext *s = avctx->priv_data;
|
||||
|
||||
int stream_ptr = 0;
|
||||
int stream_ptr_after_color_chunk;
|
||||
@ -122,10 +156,11 @@ static int flic_decode_frame(AVCodecContext *avctx,
|
||||
int starting_line;
|
||||
signed short line_packets;
|
||||
int y_ptr;
|
||||
signed char byte_run;
|
||||
int byte_run;
|
||||
int pixel_skip;
|
||||
int pixel_countdown;
|
||||
unsigned char *pixels;
|
||||
int pixel_limit;
|
||||
|
||||
s->frame.reference = 1;
|
||||
s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
|
||||
@ -135,37 +170,37 @@ static int flic_decode_frame(AVCodecContext *avctx,
|
||||
}
|
||||
|
||||
pixels = s->frame.data[0];
|
||||
pixel_limit = s->avctx->height * s->frame.linesize[0];
|
||||
|
||||
frame_size = LE_32(&buf[stream_ptr]);
|
||||
frame_size = AV_RL32(&buf[stream_ptr]);
|
||||
stream_ptr += 6; /* skip the magic number */
|
||||
num_chunks = LE_16(&buf[stream_ptr]);
|
||||
num_chunks = AV_RL16(&buf[stream_ptr]);
|
||||
stream_ptr += 10; /* skip padding */
|
||||
|
||||
frame_size -= 16;
|
||||
|
||||
/* iterate through the chunks */
|
||||
while ((frame_size > 0) && (num_chunks > 0)) {
|
||||
chunk_size = LE_32(&buf[stream_ptr]);
|
||||
chunk_size = AV_RL32(&buf[stream_ptr]);
|
||||
stream_ptr += 4;
|
||||
chunk_type = LE_16(&buf[stream_ptr]);
|
||||
chunk_type = AV_RL16(&buf[stream_ptr]);
|
||||
stream_ptr += 2;
|
||||
|
||||
switch (chunk_type) {
|
||||
case FLI_256_COLOR:
|
||||
case FLI_COLOR:
|
||||
stream_ptr_after_color_chunk = stream_ptr + chunk_size - 6;
|
||||
s->new_palette = 1;
|
||||
|
||||
/* check special case: If this file is from the Magic Carpet
|
||||
* game and uses 6-bit colors even though it reports 256-color
|
||||
/* check special case: If this file is from the Magic Carpet
|
||||
* game and uses 6-bit colors even though it reports 256-color
|
||||
* chunks in a 0xAF12-type file (fli_type is set to 0xAF13 during
|
||||
* initialization) */
|
||||
if ((chunk_type == FLI_256_COLOR) && (s->fli_type != 0xAF13))
|
||||
if ((chunk_type == FLI_256_COLOR) && (s->fli_type != FLC_MAGIC_CARPET_SYNTHETIC_TYPE_CODE))
|
||||
color_shift = 0;
|
||||
else
|
||||
color_shift = 2;
|
||||
/* set up the palette */
|
||||
color_packets = LE_16(&buf[stream_ptr]);
|
||||
color_packets = AV_RL16(&buf[stream_ptr]);
|
||||
stream_ptr += 2;
|
||||
palette_ptr = 0;
|
||||
for (i = 0; i < color_packets; i++) {
|
||||
@ -180,15 +215,19 @@ static int flic_decode_frame(AVCodecContext *avctx,
|
||||
color_changes = 256;
|
||||
|
||||
for (j = 0; j < color_changes; j++) {
|
||||
unsigned int entry;
|
||||
|
||||
/* wrap around, for good measure */
|
||||
if (palette_ptr >= 256)
|
||||
if ((unsigned)palette_ptr >= 256)
|
||||
palette_ptr = 0;
|
||||
|
||||
r = buf[stream_ptr++] << color_shift;
|
||||
g = buf[stream_ptr++] << color_shift;
|
||||
b = buf[stream_ptr++] << color_shift;
|
||||
s->palette[palette_ptr++] = (r << 16) | (g << 8) | b;
|
||||
entry = (r << 16) | (g << 8) | b;
|
||||
if (s->palette[palette_ptr] != entry)
|
||||
s->new_palette = 1;
|
||||
s->palette[palette_ptr++] = entry;
|
||||
}
|
||||
}
|
||||
|
||||
@ -202,14 +241,20 @@ static int flic_decode_frame(AVCodecContext *avctx,
|
||||
|
||||
case FLI_DELTA:
|
||||
y_ptr = 0;
|
||||
compressed_lines = LE_16(&buf[stream_ptr]);
|
||||
compressed_lines = AV_RL16(&buf[stream_ptr]);
|
||||
stream_ptr += 2;
|
||||
while (compressed_lines > 0) {
|
||||
line_packets = LE_16(&buf[stream_ptr]);
|
||||
line_packets = AV_RL16(&buf[stream_ptr]);
|
||||
stream_ptr += 2;
|
||||
if (line_packets < 0) {
|
||||
if ((line_packets & 0xC000) == 0xC000) {
|
||||
// line skip opcode
|
||||
line_packets = -line_packets;
|
||||
y_ptr += line_packets * s->frame.linesize[0];
|
||||
} else if ((line_packets & 0xC000) == 0x4000) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Undefined opcode (%x) in DELTA_FLI\n", line_packets);
|
||||
} else if ((line_packets & 0xC000) == 0x8000) {
|
||||
// "last byte" opcode
|
||||
pixels[y_ptr + s->frame.linesize[0] - 1] = line_packets & 0xff;
|
||||
} else {
|
||||
compressed_lines--;
|
||||
pixel_ptr = y_ptr;
|
||||
@ -219,16 +264,18 @@ static int flic_decode_frame(AVCodecContext *avctx,
|
||||
pixel_skip = buf[stream_ptr++];
|
||||
pixel_ptr += pixel_skip;
|
||||
pixel_countdown -= pixel_skip;
|
||||
byte_run = buf[stream_ptr++];
|
||||
byte_run = (signed char)(buf[stream_ptr++]);
|
||||
if (byte_run < 0) {
|
||||
byte_run = -byte_run;
|
||||
palette_idx1 = buf[stream_ptr++];
|
||||
palette_idx2 = buf[stream_ptr++];
|
||||
CHECK_PIXEL_PTR(byte_run);
|
||||
for (j = 0; j < byte_run; j++, pixel_countdown -= 2) {
|
||||
pixels[pixel_ptr++] = palette_idx1;
|
||||
pixels[pixel_ptr++] = palette_idx2;
|
||||
}
|
||||
} else {
|
||||
CHECK_PIXEL_PTR(byte_run * 2);
|
||||
for (j = 0; j < byte_run * 2; j++, pixel_countdown--) {
|
||||
palette_idx1 = buf[stream_ptr++];
|
||||
pixels[pixel_ptr++] = palette_idx1;
|
||||
@ -243,12 +290,12 @@ static int flic_decode_frame(AVCodecContext *avctx,
|
||||
|
||||
case FLI_LC:
|
||||
/* line compressed */
|
||||
starting_line = LE_16(&buf[stream_ptr]);
|
||||
starting_line = AV_RL16(&buf[stream_ptr]);
|
||||
stream_ptr += 2;
|
||||
y_ptr = 0;
|
||||
y_ptr += starting_line * s->frame.linesize[0];
|
||||
|
||||
compressed_lines = LE_16(&buf[stream_ptr]);
|
||||
compressed_lines = AV_RL16(&buf[stream_ptr]);
|
||||
stream_ptr += 2;
|
||||
while (compressed_lines > 0) {
|
||||
pixel_ptr = y_ptr;
|
||||
@ -260,15 +307,17 @@ static int flic_decode_frame(AVCodecContext *avctx,
|
||||
pixel_skip = buf[stream_ptr++];
|
||||
pixel_ptr += pixel_skip;
|
||||
pixel_countdown -= pixel_skip;
|
||||
byte_run = buf[stream_ptr++];
|
||||
byte_run = (signed char)(buf[stream_ptr++]);
|
||||
if (byte_run > 0) {
|
||||
CHECK_PIXEL_PTR(byte_run);
|
||||
for (j = 0; j < byte_run; j++, pixel_countdown--) {
|
||||
palette_idx1 = buf[stream_ptr++];
|
||||
pixels[pixel_ptr++] = palette_idx1;
|
||||
}
|
||||
} else {
|
||||
} else if (byte_run < 0) {
|
||||
byte_run = -byte_run;
|
||||
palette_idx1 = buf[stream_ptr++];
|
||||
CHECK_PIXEL_PTR(byte_run);
|
||||
for (j = 0; j < byte_run; j++, pixel_countdown--) {
|
||||
pixels[pixel_ptr++] = palette_idx1;
|
||||
}
|
||||
@ -298,25 +347,27 @@ static int flic_decode_frame(AVCodecContext *avctx,
|
||||
stream_ptr++;
|
||||
pixel_countdown = s->avctx->width;
|
||||
while (pixel_countdown > 0) {
|
||||
byte_run = buf[stream_ptr++];
|
||||
byte_run = (signed char)(buf[stream_ptr++]);
|
||||
if (byte_run > 0) {
|
||||
palette_idx1 = buf[stream_ptr++];
|
||||
CHECK_PIXEL_PTR(byte_run);
|
||||
for (j = 0; j < byte_run; j++) {
|
||||
pixels[pixel_ptr++] = palette_idx1;
|
||||
pixel_countdown--;
|
||||
if (pixel_countdown < 0)
|
||||
av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n",
|
||||
pixel_countdown);
|
||||
av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) at line %d\n",
|
||||
pixel_countdown, lines);
|
||||
}
|
||||
} else { /* copy bytes if byte_run < 0 */
|
||||
byte_run = -byte_run;
|
||||
CHECK_PIXEL_PTR(byte_run);
|
||||
for (j = 0; j < byte_run; j++) {
|
||||
palette_idx1 = buf[stream_ptr++];
|
||||
pixels[pixel_ptr++] = palette_idx1;
|
||||
pixel_countdown--;
|
||||
if (pixel_countdown < 0)
|
||||
av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n",
|
||||
pixel_countdown);
|
||||
av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) at line %d\n",
|
||||
pixel_countdown, lines);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -362,9 +413,8 @@ static int flic_decode_frame(AVCodecContext *avctx,
|
||||
"and final chunk ptr = %d\n", buf_size, stream_ptr);
|
||||
|
||||
/* make the palette available on the way out */
|
||||
// if (s->new_palette) {
|
||||
if (1) {
|
||||
memcpy(s->frame.data[1], s->palette, AVPALETTE_SIZE);
|
||||
memcpy(s->frame.data[1], s->palette, AVPALETTE_SIZE);
|
||||
if (s->new_palette) {
|
||||
s->frame.palette_has_changed = 1;
|
||||
s->new_palette = 0;
|
||||
}
|
||||
@ -375,7 +425,308 @@ static int flic_decode_frame(AVCodecContext *avctx,
|
||||
return buf_size;
|
||||
}
|
||||
|
||||
static int flic_decode_end(AVCodecContext *avctx)
|
||||
static int flic_decode_frame_15_16BPP(AVCodecContext *avctx,
|
||||
void *data, int *data_size,
|
||||
const uint8_t *buf, int buf_size)
|
||||
{
|
||||
/* Note, the only difference between the 15Bpp and 16Bpp */
|
||||
/* Format is the pixel format, the packets are processed the same. */
|
||||
FlicDecodeContext *s = avctx->priv_data;
|
||||
|
||||
int stream_ptr = 0;
|
||||
int pixel_ptr;
|
||||
unsigned char palette_idx1;
|
||||
|
||||
unsigned int frame_size;
|
||||
int num_chunks;
|
||||
|
||||
unsigned int chunk_size;
|
||||
int chunk_type;
|
||||
|
||||
int i, j;
|
||||
|
||||
int lines;
|
||||
int compressed_lines;
|
||||
signed short line_packets;
|
||||
int y_ptr;
|
||||
int byte_run;
|
||||
int pixel_skip;
|
||||
int pixel_countdown;
|
||||
unsigned char *pixels;
|
||||
int pixel;
|
||||
int pixel_limit;
|
||||
|
||||
s->frame.reference = 1;
|
||||
s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
|
||||
if (avctx->reget_buffer(avctx, &s->frame) < 0) {
|
||||
av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
pixels = s->frame.data[0];
|
||||
pixel_limit = s->avctx->height * s->frame.linesize[0];
|
||||
|
||||
frame_size = AV_RL32(&buf[stream_ptr]);
|
||||
stream_ptr += 6; /* skip the magic number */
|
||||
num_chunks = AV_RL16(&buf[stream_ptr]);
|
||||
stream_ptr += 10; /* skip padding */
|
||||
|
||||
frame_size -= 16;
|
||||
|
||||
/* iterate through the chunks */
|
||||
while ((frame_size > 0) && (num_chunks > 0)) {
|
||||
chunk_size = AV_RL32(&buf[stream_ptr]);
|
||||
stream_ptr += 4;
|
||||
chunk_type = AV_RL16(&buf[stream_ptr]);
|
||||
stream_ptr += 2;
|
||||
|
||||
switch (chunk_type) {
|
||||
case FLI_256_COLOR:
|
||||
case FLI_COLOR:
|
||||
/* For some reason, it seems that non-palettized flics do
|
||||
* include one of these chunks in their first frame.
|
||||
* Why I do not know, it seems rather extraneous. */
|
||||
/* av_log(avctx, AV_LOG_ERROR, "Unexpected Palette chunk %d in non-paletised FLC\n",chunk_type);*/
|
||||
stream_ptr = stream_ptr + chunk_size - 6;
|
||||
break;
|
||||
|
||||
case FLI_DELTA:
|
||||
case FLI_DTA_LC:
|
||||
y_ptr = 0;
|
||||
compressed_lines = AV_RL16(&buf[stream_ptr]);
|
||||
stream_ptr += 2;
|
||||
while (compressed_lines > 0) {
|
||||
line_packets = AV_RL16(&buf[stream_ptr]);
|
||||
stream_ptr += 2;
|
||||
if (line_packets < 0) {
|
||||
line_packets = -line_packets;
|
||||
y_ptr += line_packets * s->frame.linesize[0];
|
||||
} else {
|
||||
compressed_lines--;
|
||||
pixel_ptr = y_ptr;
|
||||
pixel_countdown = s->avctx->width;
|
||||
for (i = 0; i < line_packets; i++) {
|
||||
/* account for the skip bytes */
|
||||
pixel_skip = buf[stream_ptr++];
|
||||
pixel_ptr += (pixel_skip*2); /* Pixel is 2 bytes wide */
|
||||
pixel_countdown -= pixel_skip;
|
||||
byte_run = (signed char)(buf[stream_ptr++]);
|
||||
if (byte_run < 0) {
|
||||
byte_run = -byte_run;
|
||||
pixel = AV_RL16(&buf[stream_ptr]);
|
||||
stream_ptr += 2;
|
||||
CHECK_PIXEL_PTR(byte_run);
|
||||
for (j = 0; j < byte_run; j++, pixel_countdown -= 2) {
|
||||
*((signed short*)(&pixels[pixel_ptr])) = pixel;
|
||||
pixel_ptr += 2;
|
||||
}
|
||||
} else {
|
||||
CHECK_PIXEL_PTR(byte_run);
|
||||
for (j = 0; j < byte_run; j++, pixel_countdown--) {
|
||||
*((signed short*)(&pixels[pixel_ptr])) = AV_RL16(&buf[stream_ptr]);
|
||||
stream_ptr += 2;
|
||||
pixel_ptr += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
y_ptr += s->frame.linesize[0];
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case FLI_LC:
|
||||
av_log(avctx, AV_LOG_ERROR, "Unexpected FLI_LC chunk in non-paletised FLC\n");
|
||||
stream_ptr = stream_ptr + chunk_size - 6;
|
||||
break;
|
||||
|
||||
case FLI_BLACK:
|
||||
/* set the whole frame to 0x0000 which is black in both 15Bpp and 16Bpp modes. */
|
||||
memset(pixels, 0x0000,
|
||||
s->frame.linesize[0] * s->avctx->height);
|
||||
break;
|
||||
|
||||
case FLI_BRUN:
|
||||
y_ptr = 0;
|
||||
for (lines = 0; lines < s->avctx->height; lines++) {
|
||||
pixel_ptr = y_ptr;
|
||||
/* disregard the line packets; instead, iterate through all
|
||||
* pixels on a row */
|
||||
stream_ptr++;
|
||||
pixel_countdown = (s->avctx->width * 2);
|
||||
|
||||
while (pixel_countdown > 0) {
|
||||
byte_run = (signed char)(buf[stream_ptr++]);
|
||||
if (byte_run > 0) {
|
||||
palette_idx1 = buf[stream_ptr++];
|
||||
CHECK_PIXEL_PTR(byte_run);
|
||||
for (j = 0; j < byte_run; j++) {
|
||||
pixels[pixel_ptr++] = palette_idx1;
|
||||
pixel_countdown--;
|
||||
if (pixel_countdown < 0)
|
||||
av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) (linea%d)\n",
|
||||
pixel_countdown, lines);
|
||||
}
|
||||
} else { /* copy bytes if byte_run < 0 */
|
||||
byte_run = -byte_run;
|
||||
CHECK_PIXEL_PTR(byte_run);
|
||||
for (j = 0; j < byte_run; j++) {
|
||||
palette_idx1 = buf[stream_ptr++];
|
||||
pixels[pixel_ptr++] = palette_idx1;
|
||||
pixel_countdown--;
|
||||
if (pixel_countdown < 0)
|
||||
av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) at line %d\n",
|
||||
pixel_countdown, lines);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Now FLX is strange, in that it is "byte" as opposed to "pixel" run length compressed.
|
||||
* This does not give us any good oportunity to perform word endian conversion
|
||||
* during decompression. So if it is required (i.e., this is not a LE target, we do
|
||||
* a second pass over the line here, swapping the bytes.
|
||||
*/
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
pixel_ptr = y_ptr;
|
||||
pixel_countdown = s->avctx->width;
|
||||
while (pixel_countdown > 0) {
|
||||
*((signed short*)(&pixels[pixel_ptr])) = AV_RL16(&buf[pixel_ptr]);
|
||||
pixel_ptr += 2;
|
||||
}
|
||||
#endif
|
||||
y_ptr += s->frame.linesize[0];
|
||||
}
|
||||
break;
|
||||
|
||||
case FLI_DTA_BRUN:
|
||||
y_ptr = 0;
|
||||
for (lines = 0; lines < s->avctx->height; lines++) {
|
||||
pixel_ptr = y_ptr;
|
||||
/* disregard the line packets; instead, iterate through all
|
||||
* pixels on a row */
|
||||
stream_ptr++;
|
||||
pixel_countdown = s->avctx->width; /* Width is in pixels, not bytes */
|
||||
|
||||
while (pixel_countdown > 0) {
|
||||
byte_run = (signed char)(buf[stream_ptr++]);
|
||||
if (byte_run > 0) {
|
||||
pixel = AV_RL16(&buf[stream_ptr]);
|
||||
stream_ptr += 2;
|
||||
CHECK_PIXEL_PTR(byte_run);
|
||||
for (j = 0; j < byte_run; j++) {
|
||||
*((signed short*)(&pixels[pixel_ptr])) = pixel;
|
||||
pixel_ptr += 2;
|
||||
pixel_countdown--;
|
||||
if (pixel_countdown < 0)
|
||||
av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n",
|
||||
pixel_countdown);
|
||||
}
|
||||
} else { /* copy pixels if byte_run < 0 */
|
||||
byte_run = -byte_run;
|
||||
CHECK_PIXEL_PTR(byte_run);
|
||||
for (j = 0; j < byte_run; j++) {
|
||||
*((signed short*)(&pixels[pixel_ptr])) = AV_RL16(&buf[stream_ptr]);
|
||||
stream_ptr += 2;
|
||||
pixel_ptr += 2;
|
||||
pixel_countdown--;
|
||||
if (pixel_countdown < 0)
|
||||
av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n",
|
||||
pixel_countdown);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
y_ptr += s->frame.linesize[0];
|
||||
}
|
||||
break;
|
||||
|
||||
case FLI_COPY:
|
||||
case FLI_DTA_COPY:
|
||||
/* copy the chunk (uncompressed frame) */
|
||||
if (chunk_size - 6 > (unsigned int)(s->avctx->width * s->avctx->height)*2) {
|
||||
av_log(avctx, AV_LOG_ERROR, "In chunk FLI_COPY : source data (%d bytes) " \
|
||||
"bigger than image, skipping chunk\n", chunk_size - 6);
|
||||
stream_ptr += chunk_size - 6;
|
||||
} else {
|
||||
|
||||
for (y_ptr = 0; y_ptr < s->frame.linesize[0] * s->avctx->height;
|
||||
y_ptr += s->frame.linesize[0]) {
|
||||
|
||||
pixel_countdown = s->avctx->width;
|
||||
pixel_ptr = 0;
|
||||
while (pixel_countdown > 0) {
|
||||
*((signed short*)(&pixels[y_ptr + pixel_ptr])) = AV_RL16(&buf[stream_ptr+pixel_ptr]);
|
||||
pixel_ptr += 2;
|
||||
pixel_countdown--;
|
||||
}
|
||||
stream_ptr += s->avctx->width*2;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case FLI_MINI:
|
||||
/* some sort of a thumbnail? disregard this chunk... */
|
||||
stream_ptr += chunk_size - 6;
|
||||
break;
|
||||
|
||||
default:
|
||||
av_log(avctx, AV_LOG_ERROR, "Unrecognized chunk type: %d\n", chunk_type);
|
||||
break;
|
||||
}
|
||||
|
||||
frame_size -= chunk_size;
|
||||
num_chunks--;
|
||||
}
|
||||
|
||||
/* by the end of the chunk, the stream ptr should equal the frame
|
||||
* size (minus 1, possibly); if it doesn't, issue a warning */
|
||||
if ((stream_ptr != buf_size) && (stream_ptr != buf_size - 1))
|
||||
av_log(avctx, AV_LOG_ERROR, "Processed FLI chunk where chunk size = %d " \
|
||||
"and final chunk ptr = %d\n", buf_size, stream_ptr);
|
||||
|
||||
|
||||
*data_size=sizeof(AVFrame);
|
||||
*(AVFrame*)data = s->frame;
|
||||
|
||||
return buf_size;
|
||||
}
|
||||
|
||||
static int flic_decode_frame_24BPP(AVCodecContext *avctx,
|
||||
void *data, int *data_size,
|
||||
const uint8_t *buf, int buf_size)
|
||||
{
|
||||
av_log(avctx, AV_LOG_ERROR, "24Bpp FLC Unsupported due to lack of test files.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int flic_decode_frame(AVCodecContext *avctx,
|
||||
void *data, int *data_size,
|
||||
const uint8_t *buf, int buf_size)
|
||||
{
|
||||
if (avctx->pix_fmt == PIX_FMT_PAL8) {
|
||||
return flic_decode_frame_8BPP(avctx, data, data_size,
|
||||
buf, buf_size);
|
||||
}
|
||||
else if ((avctx->pix_fmt == PIX_FMT_RGB555) ||
|
||||
(avctx->pix_fmt == PIX_FMT_RGB565)) {
|
||||
return flic_decode_frame_15_16BPP(avctx, data, data_size,
|
||||
buf, buf_size);
|
||||
}
|
||||
else if (avctx->pix_fmt == PIX_FMT_BGR24) {
|
||||
return flic_decode_frame_24BPP(avctx, data, data_size,
|
||||
buf, buf_size);
|
||||
}
|
||||
|
||||
/* Should not get here, ever as the pix_fmt is processed */
|
||||
/* in flic_decode_init and the above if should deal with */
|
||||
/* the finite set of possibilites allowable by here. */
|
||||
/* But in case we do, just error out. */
|
||||
av_log(avctx, AV_LOG_ERROR, "Unknown FLC format, my science cannot explain how this happened.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static av_cold int flic_decode_end(AVCodecContext *avctx)
|
||||
{
|
||||
FlicDecodeContext *s = avctx->priv_data;
|
||||
|
||||
@ -395,5 +746,9 @@ AVCodec flic_decoder = {
|
||||
flic_decode_end,
|
||||
flic_decode_frame,
|
||||
CODEC_CAP_DR1,
|
||||
NULL
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
.long_name = NULL_IF_CONFIG_SMALL("Autodesk Animator Flic video"),
|
||||
};
|
||||
|
376
src/add-ons/media/plugins/avcodec/libavcodec/fraps.c
Normal file
376
src/add-ons/media/plugins/avcodec/libavcodec/fraps.c
Normal file
@ -0,0 +1,376 @@
|
||||
/*
|
||||
* Fraps FPS1 decoder
|
||||
* Copyright (c) 2005 Roine Gustafsson
|
||||
* Copyright (c) 2006 Konstantin Shishkov
|
||||
*
|
||||
* 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 fraps.c
|
||||
* Lossless Fraps 'FPS1' decoder
|
||||
* @author Roine Gustafsson <roine at users sf net>
|
||||
* @author Konstantin Shishkov
|
||||
*
|
||||
* Codec algorithm for version 0 is taken from Transcode <www.transcoding.org>
|
||||
*
|
||||
* Version 2 files support by Konstantin Shishkov
|
||||
*/
|
||||
|
||||
#include "avcodec.h"
|
||||
#include "bitstream.h"
|
||||
#include "huffman.h"
|
||||
#include "bytestream.h"
|
||||
#include "dsputil.h"
|
||||
|
||||
#define FPS_TAG MKTAG('F', 'P', 'S', 'x')
|
||||
|
||||
/**
|
||||
* local variable storage
|
||||
*/
|
||||
typedef struct FrapsContext{
|
||||
AVCodecContext *avctx;
|
||||
AVFrame frame;
|
||||
uint8_t *tmpbuf;
|
||||
DSPContext dsp;
|
||||
} FrapsContext;
|
||||
|
||||
|
||||
/**
|
||||
* initializes decoder
|
||||
* @param avctx codec context
|
||||
* @return 0 on success or negative if fails
|
||||
*/
|
||||
static av_cold int decode_init(AVCodecContext *avctx)
|
||||
{
|
||||
FrapsContext * const s = avctx->priv_data;
|
||||
|
||||
avctx->coded_frame = (AVFrame*)&s->frame;
|
||||
avctx->pix_fmt= PIX_FMT_NONE; /* set in decode_frame */
|
||||
|
||||
s->avctx = avctx;
|
||||
s->frame.data[0] = NULL;
|
||||
s->tmpbuf = NULL;
|
||||
|
||||
dsputil_init(&s->dsp, avctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Comparator - our nodes should ascend by count
|
||||
* but with preserved symbol order
|
||||
*/
|
||||
static int huff_cmp(const void *va, const void *vb){
|
||||
const Node *a = va, *b = vb;
|
||||
return (a->count - b->count)*256 + a->sym - b->sym;
|
||||
}
|
||||
|
||||
/**
|
||||
* decode Fraps v2 packed plane
|
||||
*/
|
||||
static int fraps2_decode_plane(FrapsContext *s, uint8_t *dst, int stride, int w,
|
||||
int h, const uint8_t *src, int size, int Uoff,
|
||||
const int step)
|
||||
{
|
||||
int i, j;
|
||||
GetBitContext gb;
|
||||
VLC vlc;
|
||||
Node nodes[512];
|
||||
|
||||
for(i = 0; i < 256; i++)
|
||||
nodes[i].count = bytestream_get_le32(&src);
|
||||
size -= 1024;
|
||||
if (ff_huff_build_tree(s->avctx, &vlc, 256, nodes, huff_cmp,
|
||||
FF_HUFFMAN_FLAG_ZERO_COUNT) < 0)
|
||||
return -1;
|
||||
/* we have built Huffman table and are ready to decode plane */
|
||||
|
||||
/* convert bits so they may be used by standard bitreader */
|
||||
s->dsp.bswap_buf((uint32_t *)s->tmpbuf, (const uint32_t *)src, size >> 2);
|
||||
|
||||
init_get_bits(&gb, s->tmpbuf, size * 8);
|
||||
for(j = 0; j < h; j++){
|
||||
for(i = 0; i < w*step; i += step){
|
||||
dst[i] = get_vlc2(&gb, vlc.table, 9, 3);
|
||||
/* lines are stored as deltas between previous lines
|
||||
* and we need to add 0x80 to the first lines of chroma planes
|
||||
*/
|
||||
if(j) dst[i] += dst[i - stride];
|
||||
else if(Uoff) dst[i] += 0x80;
|
||||
}
|
||||
dst += stride;
|
||||
}
|
||||
free_vlc(&vlc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* decode a frame
|
||||
* @param avctx codec context
|
||||
* @param data output AVFrame
|
||||
* @param data_size size of output data or 0 if no picture is returned
|
||||
* @param buf input data frame
|
||||
* @param buf_size size of input data frame
|
||||
* @return number of consumed bytes on success or negative if decode fails
|
||||
*/
|
||||
static int decode_frame(AVCodecContext *avctx,
|
||||
void *data, int *data_size,
|
||||
const uint8_t *buf, int buf_size)
|
||||
{
|
||||
FrapsContext * const s = avctx->priv_data;
|
||||
AVFrame *frame = data;
|
||||
AVFrame * const f = (AVFrame*)&s->frame;
|
||||
uint32_t header;
|
||||
unsigned int version,header_size;
|
||||
unsigned int x, y;
|
||||
const uint32_t *buf32;
|
||||
uint32_t *luma1,*luma2,*cb,*cr;
|
||||
uint32_t offs[4];
|
||||
int i, j, is_chroma, planes;
|
||||
|
||||
|
||||
header = AV_RL32(buf);
|
||||
version = header & 0xff;
|
||||
header_size = (header & (1<<30))? 8 : 4; /* bit 30 means pad to 8 bytes */
|
||||
|
||||
if (version > 2 && version != 4 && version != 5) {
|
||||
av_log(avctx, AV_LOG_ERROR,
|
||||
"This file is encoded with Fraps version %d. " \
|
||||
"This codec can only decode version 0, 1, 2 and 4.\n", version);
|
||||
return -1;
|
||||
}
|
||||
|
||||
buf+=4;
|
||||
if (header_size == 8)
|
||||
buf+=4;
|
||||
|
||||
switch(version) {
|
||||
case 0:
|
||||
default:
|
||||
/* Fraps v0 is a reordered YUV420 */
|
||||
avctx->pix_fmt = PIX_FMT_YUV420P;
|
||||
|
||||
if ( (buf_size != avctx->width*avctx->height*3/2+header_size) &&
|
||||
(buf_size != header_size) ) {
|
||||
av_log(avctx, AV_LOG_ERROR,
|
||||
"Invalid frame length %d (should be %d)\n",
|
||||
buf_size, avctx->width*avctx->height*3/2+header_size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (( (avctx->width % 8) != 0) || ( (avctx->height % 2) != 0 )) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Invalid frame size %dx%d\n",
|
||||
avctx->width, avctx->height);
|
||||
return -1;
|
||||
}
|
||||
|
||||
f->reference = 1;
|
||||
f->buffer_hints = FF_BUFFER_HINTS_VALID |
|
||||
FF_BUFFER_HINTS_PRESERVE |
|
||||
FF_BUFFER_HINTS_REUSABLE;
|
||||
if (avctx->reget_buffer(avctx, f)) {
|
||||
av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
|
||||
return -1;
|
||||
}
|
||||
/* bit 31 means same as previous pic */
|
||||
f->pict_type = (header & (1<<31))? FF_P_TYPE : FF_I_TYPE;
|
||||
f->key_frame = f->pict_type == FF_I_TYPE;
|
||||
|
||||
if (f->pict_type == FF_I_TYPE) {
|
||||
buf32=(const uint32_t*)buf;
|
||||
for(y=0; y<avctx->height/2; y++){
|
||||
luma1=(uint32_t*)&f->data[0][ y*2*f->linesize[0] ];
|
||||
luma2=(uint32_t*)&f->data[0][ (y*2+1)*f->linesize[0] ];
|
||||
cr=(uint32_t*)&f->data[1][ y*f->linesize[1] ];
|
||||
cb=(uint32_t*)&f->data[2][ y*f->linesize[2] ];
|
||||
for(x=0; x<avctx->width; x+=8){
|
||||
*(luma1++) = *(buf32++);
|
||||
*(luma1++) = *(buf32++);
|
||||
*(luma2++) = *(buf32++);
|
||||
*(luma2++) = *(buf32++);
|
||||
*(cr++) = *(buf32++);
|
||||
*(cb++) = *(buf32++);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
/* Fraps v1 is an upside-down BGR24 */
|
||||
avctx->pix_fmt = PIX_FMT_BGR24;
|
||||
|
||||
if ( (buf_size != avctx->width*avctx->height*3+header_size) &&
|
||||
(buf_size != header_size) ) {
|
||||
av_log(avctx, AV_LOG_ERROR,
|
||||
"Invalid frame length %d (should be %d)\n",
|
||||
buf_size, avctx->width*avctx->height*3+header_size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
f->reference = 1;
|
||||
f->buffer_hints = FF_BUFFER_HINTS_VALID |
|
||||
FF_BUFFER_HINTS_PRESERVE |
|
||||
FF_BUFFER_HINTS_REUSABLE;
|
||||
if (avctx->reget_buffer(avctx, f)) {
|
||||
av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
|
||||
return -1;
|
||||
}
|
||||
/* bit 31 means same as previous pic */
|
||||
f->pict_type = (header & (1<<31))? FF_P_TYPE : FF_I_TYPE;
|
||||
f->key_frame = f->pict_type == FF_I_TYPE;
|
||||
|
||||
if (f->pict_type == FF_I_TYPE) {
|
||||
for(y=0; y<avctx->height; y++)
|
||||
memcpy(&f->data[0][ (avctx->height-y)*f->linesize[0] ],
|
||||
&buf[y*avctx->width*3],
|
||||
f->linesize[0]);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
case 4:
|
||||
/**
|
||||
* Fraps v2 is Huffman-coded YUV420 planes
|
||||
* Fraps v4 is virtually the same
|
||||
*/
|
||||
avctx->pix_fmt = PIX_FMT_YUV420P;
|
||||
planes = 3;
|
||||
f->reference = 1;
|
||||
f->buffer_hints = FF_BUFFER_HINTS_VALID |
|
||||
FF_BUFFER_HINTS_PRESERVE |
|
||||
FF_BUFFER_HINTS_REUSABLE;
|
||||
if (avctx->reget_buffer(avctx, f)) {
|
||||
av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
|
||||
return -1;
|
||||
}
|
||||
/* skip frame */
|
||||
if(buf_size == 8) {
|
||||
f->pict_type = FF_P_TYPE;
|
||||
f->key_frame = 0;
|
||||
break;
|
||||
}
|
||||
f->pict_type = FF_I_TYPE;
|
||||
f->key_frame = 1;
|
||||
if ((AV_RL32(buf) != FPS_TAG)||(buf_size < (planes*1024 + 24))) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Fraps: error in data stream\n");
|
||||
return -1;
|
||||
}
|
||||
for(i = 0; i < planes; i++) {
|
||||
offs[i] = AV_RL32(buf + 4 + i * 4);
|
||||
if(offs[i] >= buf_size || (i && offs[i] <= offs[i - 1] + 1024)) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Fraps: plane %i offset is out of bounds\n", i);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
offs[planes] = buf_size;
|
||||
for(i = 0; i < planes; i++){
|
||||
is_chroma = !!i;
|
||||
s->tmpbuf = av_realloc(s->tmpbuf, offs[i + 1] - offs[i] - 1024 + FF_INPUT_BUFFER_PADDING_SIZE);
|
||||
if(fraps2_decode_plane(s, f->data[i], f->linesize[i], avctx->width >> is_chroma,
|
||||
avctx->height >> is_chroma, buf + offs[i], offs[i + 1] - offs[i], is_chroma, 1) < 0) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Error decoding plane %i\n", i);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
/* Virtually the same as version 4, but is for RGB24 */
|
||||
avctx->pix_fmt = PIX_FMT_BGR24;
|
||||
planes = 3;
|
||||
f->reference = 1;
|
||||
f->buffer_hints = FF_BUFFER_HINTS_VALID |
|
||||
FF_BUFFER_HINTS_PRESERVE |
|
||||
FF_BUFFER_HINTS_REUSABLE;
|
||||
if (avctx->reget_buffer(avctx, f)) {
|
||||
av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
|
||||
return -1;
|
||||
}
|
||||
/* skip frame */
|
||||
if(buf_size == 8) {
|
||||
f->pict_type = FF_P_TYPE;
|
||||
f->key_frame = 0;
|
||||
break;
|
||||
}
|
||||
f->pict_type = FF_I_TYPE;
|
||||
f->key_frame = 1;
|
||||
if ((AV_RL32(buf) != FPS_TAG)||(buf_size < (planes*1024 + 24))) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Fraps: error in data stream\n");
|
||||
return -1;
|
||||
}
|
||||
for(i = 0; i < planes; i++) {
|
||||
offs[i] = AV_RL32(buf + 4 + i * 4);
|
||||
if(offs[i] >= buf_size || (i && offs[i] <= offs[i - 1] + 1024)) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Fraps: plane %i offset is out of bounds\n", i);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
offs[planes] = buf_size;
|
||||
for(i = 0; i < planes; i++){
|
||||
s->tmpbuf = av_realloc(s->tmpbuf, offs[i + 1] - offs[i] - 1024 + FF_INPUT_BUFFER_PADDING_SIZE);
|
||||
if(fraps2_decode_plane(s, f->data[0] + i + (f->linesize[0] * (avctx->height - 1)), -f->linesize[0],
|
||||
avctx->width, avctx->height, buf + offs[i], offs[i + 1] - offs[i], 0, 3) < 0) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Error decoding plane %i\n", i);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
// convert pseudo-YUV into real RGB
|
||||
for(j = 0; j < avctx->height; j++){
|
||||
for(i = 0; i < avctx->width; i++){
|
||||
f->data[0][0 + i*3 + j*f->linesize[0]] += f->data[0][1 + i*3 + j*f->linesize[0]];
|
||||
f->data[0][2 + i*3 + j*f->linesize[0]] += f->data[0][1 + i*3 + j*f->linesize[0]];
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
*frame = *f;
|
||||
*data_size = sizeof(AVFrame);
|
||||
|
||||
return buf_size;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* closes decoder
|
||||
* @param avctx codec context
|
||||
* @return 0 on success or negative if fails
|
||||
*/
|
||||
static av_cold int decode_end(AVCodecContext *avctx)
|
||||
{
|
||||
FrapsContext *s = (FrapsContext*)avctx->priv_data;
|
||||
|
||||
if (s->frame.data[0])
|
||||
avctx->release_buffer(avctx, &s->frame);
|
||||
|
||||
av_freep(&s->tmpbuf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
AVCodec fraps_decoder = {
|
||||
"fraps",
|
||||
CODEC_TYPE_VIDEO,
|
||||
CODEC_ID_FRAPS,
|
||||
sizeof(FrapsContext),
|
||||
decode_init,
|
||||
NULL,
|
||||
decode_end,
|
||||
decode_frame,
|
||||
CODEC_CAP_DR1,
|
||||
.long_name = NULL_IF_CONFIG_SMALL("Fraps"),
|
||||
};
|
Loading…
Reference in New Issue
Block a user