theora codec based on theora cvs as of today
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@6727 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
6cb226fd44
commit
dd05a93c1b
28
src/add-ons/media/plugins/theora/libtheora/Jamfile
Normal file
28
src/add-ons/media/plugins/theora/libtheora/Jamfile
Normal file
@ -0,0 +1,28 @@
|
||||
SubDir OBOS_TOP src add-ons media plugins theora libtheora ;
|
||||
|
||||
SubDirHdrs [ FDirName $(SUBDIR) .. .. ogg libogg ] ;
|
||||
|
||||
SubDirCcFlags -DPACKAGE=\\\"libtheora\\\" -DVERSION=\\\"0.0\\\" ;
|
||||
SubDirCcFlags -D_REENTRANT -DPIC -DTRUE=true ;
|
||||
|
||||
StaticLibrary theora :
|
||||
blockmap.c
|
||||
comment.c
|
||||
dct.c
|
||||
dct_decode.c
|
||||
dct_encode.c
|
||||
decode.c
|
||||
encode.c
|
||||
frarray.c
|
||||
frinit.c
|
||||
huffman.c
|
||||
idct.c
|
||||
mcomp.c
|
||||
misc_common.c
|
||||
pb.c
|
||||
pp.c
|
||||
quant.c
|
||||
reconstruct.c
|
||||
scan.c
|
||||
toplevel.c
|
||||
;
|
38
src/add-ons/media/plugins/theora/libtheora/block_inline.h
Normal file
38
src/add-ons/media/plugins/theora/libtheora/block_inline.h
Normal file
@ -0,0 +1,38 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2003 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function:
|
||||
last mod: $Id: block_inline.h,v 1.1 2004/02/24 13:50:13 shatty Exp $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#include "encoder_internal.h"
|
||||
|
||||
static ogg_int32_t MBOrderMap[4] = { 0, 2, 3, 1 };
|
||||
static ogg_int32_t BlockOrderMap1[4][4] = {
|
||||
{ 0, 1, 3, 2 },
|
||||
{ 0, 2, 3, 1 },
|
||||
{ 0, 2, 3, 1 },
|
||||
{ 3, 2, 0, 1 }
|
||||
};
|
||||
|
||||
static ogg_int32_t QuadMapToIndex1( ogg_int32_t (*BlockMap)[4][4],
|
||||
ogg_uint32_t SB, ogg_uint32_t MB,
|
||||
ogg_uint32_t B ){
|
||||
return BlockMap[SB][MBOrderMap[MB]][BlockOrderMap1[MB][B]];
|
||||
}
|
||||
|
||||
|
||||
static ogg_int32_t QuadMapToMBTopLeft( ogg_int32_t (*BlockMap)[4][4],
|
||||
ogg_uint32_t SB, ogg_uint32_t MB ){
|
||||
return BlockMap[SB][MBOrderMap[MB]][0];
|
||||
}
|
100
src/add-ons/media/plugins/theora/libtheora/blockmap.c
Normal file
100
src/add-ons/media/plugins/theora/libtheora/blockmap.c
Normal file
@ -0,0 +1,100 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2003 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function:
|
||||
last mod: $Id: blockmap.c,v 1.1 2004/02/24 13:50:13 shatty Exp $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#include "encoder_internal.h"
|
||||
|
||||
static void CreateMapping ( ogg_int32_t (*BlockMap)[4][4],
|
||||
ogg_uint32_t FirstSB,
|
||||
ogg_uint32_t FirstFrag, ogg_uint32_t HFrags,
|
||||
ogg_uint32_t VFrags ){
|
||||
ogg_uint32_t i, j;
|
||||
ogg_uint32_t xpos;
|
||||
ogg_uint32_t ypos;
|
||||
ogg_uint32_t SBrow, SBcol;
|
||||
ogg_uint32_t SBRows, SBCols;
|
||||
ogg_uint32_t MB, B;
|
||||
|
||||
ogg_uint32_t SB=FirstSB;
|
||||
ogg_uint32_t FragIndex=FirstFrag;
|
||||
|
||||
/* Set Super-Block dimensions */
|
||||
SBRows = VFrags/4 + ( VFrags%4 ? 1 : 0 );
|
||||
SBCols = HFrags/4 + ( HFrags%4 ? 1 : 0 );
|
||||
|
||||
/* Map each Super-Block */
|
||||
for ( SBrow=0; SBrow<SBRows; SBrow++ ){
|
||||
for ( SBcol=0; SBcol<SBCols; SBcol++ ){
|
||||
/* Y co-ordinate of Super-Block in Block units */
|
||||
ypos = SBrow<<2;
|
||||
|
||||
/* Map Blocks within this Super-Block */
|
||||
for ( i=0; (i<4) && (ypos<VFrags); i++, ypos++ ){
|
||||
/* X co-ordinate of Super-Block in Block units */
|
||||
xpos = SBcol<<2;
|
||||
|
||||
for ( j=0; (j<4) && (xpos<HFrags); j++, xpos++ ){
|
||||
if ( i<2 ){
|
||||
MB = ( j<2 ? 0 : 1 );
|
||||
}else{
|
||||
MB = ( j<2 ? 2 : 3 );
|
||||
}
|
||||
|
||||
if ( i%2 ){
|
||||
B = ( j%2 ? 3 : 2 );
|
||||
}else{
|
||||
B = ( j%2 ? 1 : 0 );
|
||||
}
|
||||
|
||||
/* Set mapping and move to next fragment */
|
||||
BlockMap[SB][MB][B] = FragIndex++;
|
||||
}
|
||||
|
||||
/* Move to first fragment in next row in Super-Block */
|
||||
FragIndex += HFrags-j;
|
||||
}
|
||||
|
||||
/* Move on to next Super-Block */
|
||||
SB++;
|
||||
FragIndex -= i*HFrags-j;
|
||||
}
|
||||
|
||||
/* Move to first Super-Block in next row */
|
||||
FragIndex += 3*HFrags;
|
||||
}
|
||||
}
|
||||
|
||||
void CreateBlockMapping ( ogg_int32_t (*BlockMap)[4][4],
|
||||
ogg_uint32_t YSuperBlocks,
|
||||
ogg_uint32_t UVSuperBlocks,
|
||||
ogg_uint32_t HFrags, ogg_uint32_t VFrags ) {
|
||||
ogg_uint32_t i, j;
|
||||
|
||||
for ( i=0; i<YSuperBlocks + UVSuperBlocks * 2; i++ ){
|
||||
for ( j=0; j<4; j++ ) {
|
||||
BlockMap[i][j][0] = -1;
|
||||
BlockMap[i][j][1] = -1;
|
||||
BlockMap[i][j][2] = -1;
|
||||
BlockMap[i][j][3] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
CreateMapping ( BlockMap, 0, 0, HFrags, VFrags );
|
||||
CreateMapping ( BlockMap, YSuperBlocks, HFrags*VFrags, HFrags/2, VFrags/2 );
|
||||
CreateMapping ( BlockMap, YSuperBlocks + UVSuperBlocks, (HFrags*VFrags*5)/4,
|
||||
HFrags/2, VFrags/2 );
|
||||
}
|
||||
|
110
src/add-ons/media/plugins/theora/libtheora/comment.c
Normal file
110
src/add-ons/media/plugins/theora/libtheora/comment.c
Normal file
@ -0,0 +1,110 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2003 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: read/write and client interface for comment header packet
|
||||
last mod: $Id: comment.c,v 1.1 2004/02/24 13:50:13 shatty Exp $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "encoder_internal.h"
|
||||
|
||||
void theora_comment_init(theora_comment *tc){
|
||||
memset(tc,0,sizeof(*tc));
|
||||
}
|
||||
|
||||
void theora_comment_add(theora_comment *tc,char *comment){
|
||||
tc->user_comments=_ogg_realloc(tc->user_comments,
|
||||
(tc->comments+2)*sizeof(*tc->user_comments));
|
||||
tc->comment_lengths=_ogg_realloc(tc->comment_lengths,
|
||||
(tc->comments+2)*sizeof(*tc->comment_lengths));
|
||||
tc->comment_lengths[tc->comments]=strlen(comment);
|
||||
tc->user_comments[tc->comments]=_ogg_malloc(tc->comment_lengths[tc->comments]+1);
|
||||
strcpy(tc->user_comments[tc->comments], comment);
|
||||
tc->comments++;
|
||||
tc->user_comments[tc->comments]=NULL;
|
||||
}
|
||||
|
||||
void theora_comment_add_tag(theora_comment *tc, char *tag, char *value){
|
||||
char *comment=_ogg_malloc(strlen(tag)+strlen(value)+2); /* +2 for = and \0 */
|
||||
strcpy(comment, tag);
|
||||
strcat(comment, "=");
|
||||
strcat(comment, value);
|
||||
theora_comment_add(tc, comment);
|
||||
_ogg_free(comment);
|
||||
}
|
||||
|
||||
/* This is more or less the same as strncasecmp - but that doesn't exist
|
||||
* everywhere, and this is a fairly trivial function, so we include it */
|
||||
static int tagcompare(const char *s1, const char *s2, int n){
|
||||
int c=0;
|
||||
while(c < n){
|
||||
if(toupper(s1[c]) != toupper(s2[c]))
|
||||
return !0;
|
||||
c++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *theora_comment_query(theora_comment *tc, char *tag, int count){
|
||||
long i;
|
||||
int found = 0;
|
||||
int taglen = strlen(tag)+1; /* +1 for the = we append */
|
||||
char *fulltag = _ogg_malloc(taglen+ 1);
|
||||
|
||||
strcpy(fulltag, tag);
|
||||
strcat(fulltag, "=");
|
||||
|
||||
for(i=0;i<tc->comments;i++){
|
||||
if(!tagcompare(tc->user_comments[i], fulltag, taglen)){
|
||||
if(count == found){
|
||||
_ogg_free(fulltag);
|
||||
/* We return a pointer to the data, not a copy */
|
||||
return tc->user_comments[i] + taglen;
|
||||
}
|
||||
else
|
||||
found++;
|
||||
}
|
||||
}
|
||||
_ogg_free(fulltag);
|
||||
return NULL; /* didn't find anything */
|
||||
}
|
||||
|
||||
int theora_comment_query_count(theora_comment *tc, char *tag){
|
||||
int i,count=0;
|
||||
int taglen = strlen(tag)+1; /* +1 for the = we append */
|
||||
char *fulltag = _ogg_malloc(taglen+1);
|
||||
strcpy(fulltag,tag);
|
||||
strcat(fulltag, "=");
|
||||
|
||||
for(i=0;i<tc->comments;i++){
|
||||
if(!tagcompare(tc->user_comments[i], fulltag, taglen))
|
||||
count++;
|
||||
}
|
||||
_ogg_free(fulltag);
|
||||
return count;
|
||||
}
|
||||
|
||||
void theora_comment_clear(theora_comment *tc){
|
||||
if(tc){
|
||||
long i;
|
||||
for(i=0;i<tc->comments;i++)
|
||||
if(tc->user_comments[i])_ogg_free(tc->user_comments[i]);
|
||||
if(tc->user_comments)_ogg_free(tc->user_comments);
|
||||
if(tc->comment_lengths)_ogg_free(tc->comment_lengths);
|
||||
if(tc->vendor)_ogg_free(tc->vendor);
|
||||
}
|
||||
memset(tc,0,sizeof(*tc));
|
||||
}
|
||||
|
253
src/add-ons/media/plugins/theora/libtheora/dct.c
Normal file
253
src/add-ons/media/plugins/theora/libtheora/dct.c
Normal file
@ -0,0 +1,253 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2003 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function:
|
||||
last mod: $Id: dct.c,v 1.1 2004/02/24 13:50:13 shatty Exp $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#include "encoder_internal.h"
|
||||
|
||||
static ogg_int32_t xC1S7 = 64277;
|
||||
static ogg_int32_t xC2S6 = 60547;
|
||||
static ogg_int32_t xC3S5 = 54491;
|
||||
static ogg_int32_t xC4S4 = 46341;
|
||||
static ogg_int32_t xC5S3 = 36410;
|
||||
static ogg_int32_t xC6S2 = 25080;
|
||||
static ogg_int32_t xC7S1 = 12785;
|
||||
|
||||
#define SIGNBITDUPPED(X) ((signed )(((X) & 0x80000000)) >> 31)
|
||||
#define DOROUND(X) ( (SIGNBITDUPPED(X) & (0xffff)) + (X) )
|
||||
|
||||
void fdct_short ( ogg_int16_t * InputData, ogg_int16_t * OutputData ){
|
||||
int loop;
|
||||
|
||||
ogg_int32_t is07, is12, is34, is56;
|
||||
ogg_int32_t is0734, is1256;
|
||||
ogg_int32_t id07, id12, id34, id56;
|
||||
|
||||
ogg_int32_t irot_input_x, irot_input_y;
|
||||
ogg_int32_t icommon_product1; /* Re-used product (c4s4 * (s12 - s56)). */
|
||||
ogg_int32_t icommon_product2; /* Re-used product (c4s4 * (d12 + d56)). */
|
||||
|
||||
ogg_int32_t temp1, temp2; /* intermediate variable for computation */
|
||||
|
||||
ogg_int32_t InterData[64];
|
||||
ogg_int32_t *ip = InterData;
|
||||
ogg_int16_t * op = OutputData;
|
||||
for (loop = 0; loop < 8; loop++){
|
||||
/* Pre calculate some common sums and differences. */
|
||||
is07 = InputData[0] + InputData[7];
|
||||
is12 = InputData[1] + InputData[2];
|
||||
is34 = InputData[3] + InputData[4];
|
||||
is56 = InputData[5] + InputData[6];
|
||||
|
||||
id07 = InputData[0] - InputData[7];
|
||||
id12 = InputData[1] - InputData[2];
|
||||
id34 = InputData[3] - InputData[4];
|
||||
id56 = InputData[5] - InputData[6];
|
||||
|
||||
is0734 = is07 + is34;
|
||||
is1256 = is12 + is56;
|
||||
|
||||
/* Pre-Calculate some common product terms. */
|
||||
icommon_product1 = xC4S4*(is12 - is56);
|
||||
icommon_product1 = DOROUND(icommon_product1);
|
||||
icommon_product1>>=16;
|
||||
|
||||
icommon_product2 = xC4S4*(id12 + id56);
|
||||
icommon_product2 = DOROUND(icommon_product2);
|
||||
icommon_product2>>=16;
|
||||
|
||||
|
||||
ip[0] = (xC4S4*(is0734 + is1256));
|
||||
ip[0] = DOROUND(ip[0]);
|
||||
ip[0] >>= 16;
|
||||
|
||||
ip[4] = (xC4S4*(is0734 - is1256));
|
||||
ip[4] = DOROUND(ip[4]);
|
||||
ip[4] >>= 16;
|
||||
|
||||
/* Define inputs to rotation for outputs 2 and 6 */
|
||||
irot_input_x = id12 - id56;
|
||||
irot_input_y = is07 - is34;
|
||||
|
||||
/* Apply rotation for outputs 2 and 6. */
|
||||
temp1=xC6S2*irot_input_x;
|
||||
temp1=DOROUND(temp1);
|
||||
temp1>>=16;
|
||||
temp2=xC2S6*irot_input_y;
|
||||
temp2=DOROUND(temp2);
|
||||
temp2>>=16;
|
||||
ip[2] = temp1 + temp2;
|
||||
|
||||
temp1=xC6S2*irot_input_y;
|
||||
temp1=DOROUND(temp1);
|
||||
temp1>>=16;
|
||||
temp2=xC2S6*irot_input_x ;
|
||||
temp2=DOROUND(temp2);
|
||||
temp2>>=16;
|
||||
ip[6] = temp1 -temp2 ;
|
||||
|
||||
/* Define inputs to rotation for outputs 1 and 7 */
|
||||
irot_input_x = icommon_product1 + id07;
|
||||
irot_input_y = -( id34 + icommon_product2 );
|
||||
|
||||
/* Apply rotation for outputs 1 and 7. */
|
||||
|
||||
temp1=xC1S7*irot_input_x;
|
||||
temp1=DOROUND(temp1);
|
||||
temp1>>=16;
|
||||
temp2=xC7S1*irot_input_y;
|
||||
temp2=DOROUND(temp2);
|
||||
temp2>>=16;
|
||||
ip[1] = temp1 - temp2;
|
||||
|
||||
temp1=xC7S1*irot_input_x;
|
||||
temp1=DOROUND(temp1);
|
||||
temp1>>=16;
|
||||
temp2=xC1S7*irot_input_y ;
|
||||
temp2=DOROUND(temp2);
|
||||
temp2>>=16;
|
||||
ip[7] = temp1 + temp2 ;
|
||||
|
||||
/* Define inputs to rotation for outputs 3 and 5 */
|
||||
irot_input_x = id07 - icommon_product1;
|
||||
irot_input_y = id34 - icommon_product2;
|
||||
|
||||
/* Apply rotation for outputs 3 and 5. */
|
||||
temp1=xC3S5*irot_input_x;
|
||||
temp1=DOROUND(temp1);
|
||||
temp1>>=16;
|
||||
temp2=xC5S3*irot_input_y ;
|
||||
temp2=DOROUND(temp2);
|
||||
temp2>>=16;
|
||||
ip[3] = temp1 - temp2 ;
|
||||
|
||||
temp1=xC5S3*irot_input_x;
|
||||
temp1=DOROUND(temp1);
|
||||
temp1>>=16;
|
||||
temp2=xC3S5*irot_input_y;
|
||||
temp2=DOROUND(temp2);
|
||||
temp2>>=16;
|
||||
ip[5] = temp1 + temp2;
|
||||
|
||||
/* Increment data pointer for next row. */
|
||||
InputData += 8 ;
|
||||
ip += 8; /* advance pointer to next row */
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* Performed DCT on rows, now transform the columns */
|
||||
ip = InterData;
|
||||
for (loop = 0; loop < 8; loop++){
|
||||
/* Pre calculate some common sums and differences. */
|
||||
is07 = ip[0 * 8] + ip[7 * 8];
|
||||
is12 = ip[1 * 8] + ip[2 * 8];
|
||||
is34 = ip[3 * 8] + ip[4 * 8];
|
||||
is56 = ip[5 * 8] + ip[6 * 8];
|
||||
|
||||
id07 = ip[0 * 8] - ip[7 * 8];
|
||||
id12 = ip[1 * 8] - ip[2 * 8];
|
||||
id34 = ip[3 * 8] - ip[4 * 8];
|
||||
id56 = ip[5 * 8] - ip[6 * 8];
|
||||
|
||||
is0734 = is07 + is34;
|
||||
is1256 = is12 + is56;
|
||||
|
||||
/* Pre-Calculate some common product terms. */
|
||||
icommon_product1 = xC4S4*(is12 - is56) ;
|
||||
icommon_product2 = xC4S4*(id12 + id56) ;
|
||||
icommon_product1 = DOROUND(icommon_product1);
|
||||
icommon_product2 = DOROUND(icommon_product2);
|
||||
icommon_product1>>=16;
|
||||
icommon_product2>>=16;
|
||||
|
||||
|
||||
temp1 = xC4S4*(is0734 + is1256) ;
|
||||
temp2 = xC4S4*(is0734 - is1256) ;
|
||||
temp1 = DOROUND(temp1);
|
||||
temp2 = DOROUND(temp2);
|
||||
temp1>>=16;
|
||||
temp2>>=16;
|
||||
op[0*8] = (ogg_int16_t) temp1;
|
||||
op[4*8] = (ogg_int16_t) temp2;
|
||||
|
||||
/* Define inputs to rotation for outputs 2 and 6 */
|
||||
irot_input_x = id12 - id56;
|
||||
irot_input_y = is07 - is34;
|
||||
|
||||
/* Apply rotation for outputs 2 and 6. */
|
||||
temp1=xC6S2*irot_input_x;
|
||||
temp1=DOROUND(temp1);
|
||||
temp1>>=16;
|
||||
temp2=xC2S6*irot_input_y;
|
||||
temp2=DOROUND(temp2);
|
||||
temp2>>=16;
|
||||
op[2*8] = (ogg_int16_t) (temp1 + temp2);
|
||||
|
||||
temp1=xC6S2*irot_input_y;
|
||||
temp1=DOROUND(temp1);
|
||||
temp1>>=16;
|
||||
temp2=xC2S6*irot_input_x ;
|
||||
temp2=DOROUND(temp2);
|
||||
temp2>>=16;
|
||||
op[6*8] = (ogg_int16_t) (temp1 -temp2) ;
|
||||
|
||||
/* Define inputs to rotation for outputs 1 and 7 */
|
||||
irot_input_x = icommon_product1 + id07;
|
||||
irot_input_y = -( id34 + icommon_product2 );
|
||||
|
||||
/* Apply rotation for outputs 1 and 7. */
|
||||
temp1=xC1S7*irot_input_x;
|
||||
temp1=DOROUND(temp1);
|
||||
temp1>>=16;
|
||||
temp2=xC7S1*irot_input_y;
|
||||
temp2=DOROUND(temp2);
|
||||
temp2>>=16;
|
||||
op[1*8] = (ogg_int16_t) (temp1 - temp2);
|
||||
|
||||
temp1=xC7S1*irot_input_x;
|
||||
temp1=DOROUND(temp1);
|
||||
temp1>>=16;
|
||||
temp2=xC1S7*irot_input_y ;
|
||||
temp2=DOROUND(temp2);
|
||||
temp2>>=16;
|
||||
op[7*8] = (ogg_int16_t) (temp1 + temp2);
|
||||
|
||||
/* Define inputs to rotation for outputs 3 and 5 */
|
||||
irot_input_x = id07 - icommon_product1;
|
||||
irot_input_y = id34 - icommon_product2;
|
||||
|
||||
/* Apply rotation for outputs 3 and 5. */
|
||||
temp1=xC3S5*irot_input_x;
|
||||
temp1=DOROUND(temp1);
|
||||
temp1>>=16;
|
||||
temp2=xC5S3*irot_input_y ;
|
||||
temp2=DOROUND(temp2);
|
||||
temp2>>=16;
|
||||
op[3*8] = (ogg_int16_t) (temp1 - temp2) ;
|
||||
|
||||
temp1=xC5S3*irot_input_x;
|
||||
temp1=DOROUND(temp1);
|
||||
temp1>>=16;
|
||||
temp2=xC3S5*irot_input_y;
|
||||
temp2=DOROUND(temp2);
|
||||
temp2>>=16;
|
||||
op[5*8] = (ogg_int16_t) (temp1 + temp2);
|
||||
|
||||
/* Increment data pointer for next column. */
|
||||
ip ++;
|
||||
op ++;
|
||||
}
|
||||
}
|
1198
src/add-ons/media/plugins/theora/libtheora/dct_decode.c
Normal file
1198
src/add-ons/media/plugins/theora/libtheora/dct_decode.c
Normal file
File diff suppressed because it is too large
Load Diff
557
src/add-ons/media/plugins/theora/libtheora/dct_encode.c
Normal file
557
src/add-ons/media/plugins/theora/libtheora/dct_encode.c
Normal file
@ -0,0 +1,557 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2003 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function:
|
||||
last mod: $Id: dct_encode.c,v 1.1 2004/02/24 13:50:13 shatty Exp $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "encoder_internal.h"
|
||||
|
||||
static int ModeUsesMC[MAX_MODES] = { 0, 0, 1, 1, 1, 0, 1, 1 };
|
||||
|
||||
static void Sub8 (unsigned char *FiltPtr, unsigned char *ReconPtr,
|
||||
ogg_int16_t *DctInputPtr, unsigned char *old_ptr1,
|
||||
unsigned char *new_ptr1, ogg_uint32_t PixelsPerLine,
|
||||
ogg_uint32_t ReconPixelsPerLine ) {
|
||||
int i;
|
||||
|
||||
/* For each block row */
|
||||
for ( i=0; i<BLOCK_HEIGHT_WIDTH; i++ ){
|
||||
DctInputPtr[0] = (ogg_int16_t)((int)(FiltPtr[0]) - ((int)ReconPtr[0]) );
|
||||
DctInputPtr[1] = (ogg_int16_t)((int)(FiltPtr[1]) - ((int)ReconPtr[1]) );
|
||||
DctInputPtr[2] = (ogg_int16_t)((int)(FiltPtr[2]) - ((int)ReconPtr[2]) );
|
||||
DctInputPtr[3] = (ogg_int16_t)((int)(FiltPtr[3]) - ((int)ReconPtr[3]) );
|
||||
DctInputPtr[4] = (ogg_int16_t)((int)(FiltPtr[4]) - ((int)ReconPtr[4]) );
|
||||
DctInputPtr[5] = (ogg_int16_t)((int)(FiltPtr[5]) - ((int)ReconPtr[5]) );
|
||||
DctInputPtr[6] = (ogg_int16_t)((int)(FiltPtr[6]) - ((int)ReconPtr[6]) );
|
||||
DctInputPtr[7] = (ogg_int16_t)((int)(FiltPtr[7]) - ((int)ReconPtr[7]) );
|
||||
|
||||
/* Update the screen canvas in one step*/
|
||||
((ogg_uint32_t*)old_ptr1)[0] = ((ogg_uint32_t*)new_ptr1)[0];
|
||||
((ogg_uint32_t*)old_ptr1)[1] = ((ogg_uint32_t*)new_ptr1)[1];
|
||||
|
||||
/* Start next row */
|
||||
new_ptr1 += PixelsPerLine;
|
||||
old_ptr1 += PixelsPerLine;
|
||||
FiltPtr += PixelsPerLine;
|
||||
ReconPtr += ReconPixelsPerLine;
|
||||
DctInputPtr += BLOCK_HEIGHT_WIDTH;
|
||||
}
|
||||
}
|
||||
|
||||
static void Sub8_128 (unsigned char *FiltPtr, ogg_int16_t *DctInputPtr,
|
||||
unsigned char *old_ptr1, unsigned char *new_ptr1,
|
||||
ogg_uint32_t PixelsPerLine ) {
|
||||
int i;
|
||||
/* For each block row */
|
||||
for ( i=0; i<BLOCK_HEIGHT_WIDTH; i++ ){
|
||||
/* INTRA mode so code raw image data */
|
||||
/* We convert the data to 8 bit signed (by subtracting 128) as
|
||||
this reduces the internal precision requirments in the DCT
|
||||
transform. */
|
||||
DctInputPtr[0] = (ogg_int16_t)((int)(FiltPtr[0]) - 128);
|
||||
DctInputPtr[1] = (ogg_int16_t)((int)(FiltPtr[1]) - 128);
|
||||
DctInputPtr[2] = (ogg_int16_t)((int)(FiltPtr[2]) - 128);
|
||||
DctInputPtr[3] = (ogg_int16_t)((int)(FiltPtr[3]) - 128);
|
||||
DctInputPtr[4] = (ogg_int16_t)((int)(FiltPtr[4]) - 128);
|
||||
DctInputPtr[5] = (ogg_int16_t)((int)(FiltPtr[5]) - 128);
|
||||
DctInputPtr[6] = (ogg_int16_t)((int)(FiltPtr[6]) - 128);
|
||||
DctInputPtr[7] = (ogg_int16_t)((int)(FiltPtr[7]) - 128);
|
||||
|
||||
/* Update the screen canvas in one step */
|
||||
((ogg_uint32_t*)old_ptr1)[0] = ((ogg_uint32_t*)new_ptr1)[0];
|
||||
((ogg_uint32_t*)old_ptr1)[1] = ((ogg_uint32_t*)new_ptr1)[1];
|
||||
|
||||
/* Start next row */
|
||||
new_ptr1 += PixelsPerLine;
|
||||
old_ptr1 += PixelsPerLine;
|
||||
FiltPtr += PixelsPerLine;
|
||||
DctInputPtr += BLOCK_HEIGHT_WIDTH;
|
||||
}
|
||||
}
|
||||
|
||||
static void Sub8Av2 (unsigned char *FiltPtr, unsigned char *ReconPtr1,
|
||||
unsigned char *ReconPtr2, ogg_int16_t *DctInputPtr,
|
||||
unsigned char *old_ptr1, unsigned char *new_ptr1,
|
||||
ogg_uint32_t PixelsPerLine,
|
||||
ogg_uint32_t ReconPixelsPerLine ) {
|
||||
int i;
|
||||
|
||||
/* For each block row */
|
||||
for ( i=0; i<BLOCK_HEIGHT_WIDTH; i++ ) {
|
||||
DctInputPtr[0] = (ogg_int16_t)
|
||||
((int)(FiltPtr[0]) - (((int)ReconPtr1[0] + (int)ReconPtr2[0]) / 2) );
|
||||
DctInputPtr[1] = (ogg_int16_t)
|
||||
((int)(FiltPtr[1]) - (((int)ReconPtr1[1] + (int)ReconPtr2[1]) / 2) );
|
||||
DctInputPtr[2] = (ogg_int16_t)
|
||||
((int)(FiltPtr[2]) - (((int)ReconPtr1[2] + (int)ReconPtr2[2]) / 2) );
|
||||
DctInputPtr[3] = (ogg_int16_t)
|
||||
((int)(FiltPtr[3]) - (((int)ReconPtr1[3] + (int)ReconPtr2[3]) / 2) );
|
||||
DctInputPtr[4] = (ogg_int16_t)
|
||||
((int)(FiltPtr[4]) - (((int)ReconPtr1[4] + (int)ReconPtr2[4]) / 2) );
|
||||
DctInputPtr[5] = (ogg_int16_t)
|
||||
((int)(FiltPtr[5]) - (((int)ReconPtr1[5] + (int)ReconPtr2[5]) / 2) );
|
||||
DctInputPtr[6] = (ogg_int16_t)
|
||||
((int)(FiltPtr[6]) - (((int)ReconPtr1[6] + (int)ReconPtr2[6]) / 2) );
|
||||
DctInputPtr[7] = (ogg_int16_t)
|
||||
((int)(FiltPtr[7]) - (((int)ReconPtr1[7] + (int)ReconPtr2[7]) / 2) );
|
||||
|
||||
/* Update the screen canvas in one step */
|
||||
((ogg_uint32_t*)old_ptr1)[0] = ((ogg_uint32_t*)new_ptr1)[0];
|
||||
((ogg_uint32_t*)old_ptr1)[1] = ((ogg_uint32_t*)new_ptr1)[1];
|
||||
|
||||
/* Start next row */
|
||||
new_ptr1 += PixelsPerLine;
|
||||
old_ptr1 += PixelsPerLine;
|
||||
FiltPtr += PixelsPerLine;
|
||||
ReconPtr1 += ReconPixelsPerLine;
|
||||
ReconPtr2 += ReconPixelsPerLine;
|
||||
DctInputPtr += BLOCK_HEIGHT_WIDTH;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned char TokenizeDctValue (ogg_int16_t DataValue,
|
||||
ogg_uint32_t * TokenListPtr ){
|
||||
unsigned char tokens_added = 0;
|
||||
ogg_uint32_t AbsDataVal = abs( (ogg_int32_t)DataValue );
|
||||
|
||||
/* Values are tokenised as category value and a number of additional
|
||||
bits that define the position within the category. */
|
||||
|
||||
if ( DataValue == 0 ) return 0;
|
||||
|
||||
if ( AbsDataVal == 1 ){
|
||||
if ( DataValue == 1 )
|
||||
TokenListPtr[0] = ONE_TOKEN;
|
||||
else
|
||||
TokenListPtr[0] = MINUS_ONE_TOKEN;
|
||||
tokens_added = 1;
|
||||
} else if ( AbsDataVal == 2 ) {
|
||||
if ( DataValue == 2 )
|
||||
TokenListPtr[0] = TWO_TOKEN;
|
||||
else
|
||||
TokenListPtr[0] = MINUS_TWO_TOKEN;
|
||||
tokens_added = 1;
|
||||
} else if ( AbsDataVal <= MAX_SINGLE_TOKEN_VALUE ) {
|
||||
TokenListPtr[0] = LOW_VAL_TOKENS + (AbsDataVal - DCT_VAL_CAT2_MIN);
|
||||
if ( DataValue > 0 )
|
||||
TokenListPtr[1] = 0;
|
||||
else
|
||||
TokenListPtr[1] = 1;
|
||||
tokens_added = 2;
|
||||
} else if ( AbsDataVal <= 8 ) {
|
||||
/* Bit 1 determines sign, Bit 0 the value */
|
||||
TokenListPtr[0] = DCT_VAL_CATEGORY3;
|
||||
if ( DataValue > 0 )
|
||||
TokenListPtr[1] = (AbsDataVal - DCT_VAL_CAT3_MIN);
|
||||
else
|
||||
TokenListPtr[1] = (0x02) + (AbsDataVal - DCT_VAL_CAT3_MIN);
|
||||
tokens_added = 2;
|
||||
} else if ( AbsDataVal <= 12 ) {
|
||||
/* Bit 2 determines sign, Bit 0-2 the value */
|
||||
TokenListPtr[0] = DCT_VAL_CATEGORY4;
|
||||
if ( DataValue > 0 )
|
||||
TokenListPtr[1] = (AbsDataVal - DCT_VAL_CAT4_MIN);
|
||||
else
|
||||
TokenListPtr[1] = (0x04) + (AbsDataVal - DCT_VAL_CAT4_MIN);
|
||||
tokens_added = 2;
|
||||
} else if ( AbsDataVal <= 20 ) {
|
||||
/* Bit 3 determines sign, Bit 0-2 the value */
|
||||
TokenListPtr[0] = DCT_VAL_CATEGORY5;
|
||||
if ( DataValue > 0 )
|
||||
TokenListPtr[1] = (AbsDataVal - DCT_VAL_CAT5_MIN);
|
||||
else
|
||||
TokenListPtr[1] = (0x08) + (AbsDataVal - DCT_VAL_CAT5_MIN);
|
||||
tokens_added = 2;
|
||||
} else if ( AbsDataVal <= 36 ) {
|
||||
/* Bit 4 determines sign, Bit 0-3 the value */
|
||||
TokenListPtr[0] = DCT_VAL_CATEGORY6;
|
||||
if ( DataValue > 0 )
|
||||
TokenListPtr[1] = (AbsDataVal - DCT_VAL_CAT6_MIN);
|
||||
else
|
||||
TokenListPtr[1] = (0x010) + (AbsDataVal - DCT_VAL_CAT6_MIN);
|
||||
tokens_added = 2;
|
||||
} else if ( AbsDataVal <= 68 ) {
|
||||
/* Bit 5 determines sign, Bit 0-4 the value */
|
||||
TokenListPtr[0] = DCT_VAL_CATEGORY7;
|
||||
if ( DataValue > 0 )
|
||||
TokenListPtr[1] = (AbsDataVal - DCT_VAL_CAT7_MIN);
|
||||
else
|
||||
TokenListPtr[1] = (0x20) + (AbsDataVal - DCT_VAL_CAT7_MIN);
|
||||
tokens_added = 2;
|
||||
} else if ( AbsDataVal <= 511 ) {
|
||||
/* Bit 9 determines sign, Bit 0-8 the value */
|
||||
TokenListPtr[0] = DCT_VAL_CATEGORY8;
|
||||
if ( DataValue > 0 )
|
||||
TokenListPtr[1] = (AbsDataVal - DCT_VAL_CAT8_MIN);
|
||||
else
|
||||
TokenListPtr[1] = (0x200) + (AbsDataVal - DCT_VAL_CAT8_MIN);
|
||||
tokens_added = 2;
|
||||
} else {
|
||||
TokenListPtr[0] = DCT_VAL_CATEGORY8;
|
||||
if ( DataValue > 0 )
|
||||
TokenListPtr[1] = (511 - DCT_VAL_CAT8_MIN);
|
||||
else
|
||||
TokenListPtr[1] = (0x200) + (511 - DCT_VAL_CAT8_MIN);
|
||||
tokens_added = 2;
|
||||
}
|
||||
|
||||
/* Return the total number of tokens added */
|
||||
return tokens_added;
|
||||
}
|
||||
|
||||
static unsigned char TokenizeDctRunValue (unsigned char RunLength,
|
||||
ogg_int16_t DataValue,
|
||||
ogg_uint32_t * TokenListPtr ){
|
||||
unsigned char tokens_added = 0;
|
||||
ogg_uint32_t AbsDataVal = abs( (ogg_int32_t)DataValue );
|
||||
|
||||
/* Values are tokenised as category value and a number of additional
|
||||
bits that define the category. */
|
||||
if ( DataValue == 0 ) return 0;
|
||||
if ( AbsDataVal == 1 ) {
|
||||
/* Zero runs of 1-5 */
|
||||
if ( RunLength <= 5 ) {
|
||||
TokenListPtr[0] = DCT_RUN_CATEGORY1 + (RunLength - 1);
|
||||
if ( DataValue > 0 )
|
||||
TokenListPtr[1] = 0;
|
||||
else
|
||||
TokenListPtr[1] = 1;
|
||||
} else if ( RunLength <= 9 ) {
|
||||
/* Zero runs of 6-9 */
|
||||
TokenListPtr[0] = DCT_RUN_CATEGORY1B;
|
||||
if ( DataValue > 0 )
|
||||
TokenListPtr[1] = (RunLength - 6);
|
||||
else
|
||||
TokenListPtr[1] = 0x04 + (RunLength - 6);
|
||||
} else {
|
||||
/* Zero runs of 10-17 */
|
||||
TokenListPtr[0] = DCT_RUN_CATEGORY1C;
|
||||
if ( DataValue > 0 )
|
||||
TokenListPtr[1] = (RunLength - 10);
|
||||
else
|
||||
TokenListPtr[1] = 0x08 + (RunLength - 10);
|
||||
}
|
||||
tokens_added = 2;
|
||||
} else if ( AbsDataVal <= 3 ) {
|
||||
if ( RunLength == 1 ) {
|
||||
TokenListPtr[0] = DCT_RUN_CATEGORY2;
|
||||
|
||||
/* Extra bits token bit 1 indicates sign, bit 0 indicates value */
|
||||
if ( DataValue > 0 )
|
||||
TokenListPtr[1] = (AbsDataVal - 2);
|
||||
else
|
||||
TokenListPtr[1] = (0x02) + (AbsDataVal - 2);
|
||||
tokens_added = 2;
|
||||
}else{
|
||||
TokenListPtr[0] = DCT_RUN_CATEGORY2 + 1;
|
||||
|
||||
/* Extra bits token. */
|
||||
/* bit 2 indicates sign, bit 1 indicates value, bit 0 indicates
|
||||
run length */
|
||||
if ( DataValue > 0 )
|
||||
TokenListPtr[1] = ((AbsDataVal - 2) << 1) + (RunLength - 2);
|
||||
else
|
||||
TokenListPtr[1] = (0x04) + ((AbsDataVal - 2) << 1) + (RunLength - 2);
|
||||
tokens_added = 2;
|
||||
}
|
||||
} else {
|
||||
tokens_added = 2; /* ERROR */
|
||||
/*IssueWarning( "Bad Input to TokenizeDctRunValue" );*/
|
||||
}
|
||||
|
||||
/* Return the total number of tokens added */
|
||||
return tokens_added;
|
||||
}
|
||||
|
||||
static unsigned char TokenizeDctBlock (ogg_int16_t * RawData,
|
||||
ogg_uint32_t * TokenListPtr ) {
|
||||
ogg_uint32_t i;
|
||||
unsigned char run_count;
|
||||
unsigned char token_count = 0; /* Number of tokens crated. */
|
||||
ogg_uint32_t AbsData;
|
||||
|
||||
|
||||
/* Tokenize the block */
|
||||
for( i = 0; i < BLOCK_SIZE; i++ ){
|
||||
run_count = 0;
|
||||
|
||||
/* Look for a zero run. */
|
||||
/* NOTE the use of & instead of && which is faster (and
|
||||
equivalent) in this instance. */
|
||||
/* NO, NO IT ISN'T --Monty */
|
||||
while( (i < BLOCK_SIZE) && (!RawData[i]) ){
|
||||
run_count++;
|
||||
i++;
|
||||
}
|
||||
|
||||
/* If we have reached the end of the block then code EOB */
|
||||
if ( i == BLOCK_SIZE ){
|
||||
TokenListPtr[token_count] = DCT_EOB_TOKEN;
|
||||
token_count++;
|
||||
}else{
|
||||
/* If we have a short zero run followed by a low data value code
|
||||
the two as a composite token. */
|
||||
if ( run_count ){
|
||||
AbsData = abs(RawData[i]);
|
||||
|
||||
if ( ((AbsData == 1) && (run_count <= 17)) ||
|
||||
((AbsData <= 3) && (run_count <= 3)) ) {
|
||||
/* Tokenise the run and subsequent value combination value */
|
||||
token_count += TokenizeDctRunValue( run_count,
|
||||
RawData[i],
|
||||
&TokenListPtr[token_count] );
|
||||
}else{
|
||||
|
||||
/* Else if we have a long non-EOB run or a run followed by a
|
||||
value token > MAX_RUN_VAL then code the run and token
|
||||
seperately */
|
||||
if ( run_count <= 8 )
|
||||
TokenListPtr[token_count] = DCT_SHORT_ZRL_TOKEN;
|
||||
else
|
||||
TokenListPtr[token_count] = DCT_ZRL_TOKEN;
|
||||
|
||||
token_count++;
|
||||
TokenListPtr[token_count] = run_count - 1;
|
||||
token_count++;
|
||||
|
||||
/* Now tokenize the value */
|
||||
token_count += TokenizeDctValue( RawData[i],
|
||||
&TokenListPtr[token_count] );
|
||||
}
|
||||
}else{
|
||||
/* Else there was NO zero run. */
|
||||
/* Tokenise the value */
|
||||
token_count += TokenizeDctValue( RawData[i],
|
||||
&TokenListPtr[token_count] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the total number of tokens (including additional bits
|
||||
tokens) used. */
|
||||
return token_count;
|
||||
}
|
||||
|
||||
ogg_uint32_t DPCMTokenizeBlock (CP_INSTANCE *cpi,
|
||||
ogg_int32_t FragIndex){
|
||||
ogg_uint32_t token_count;
|
||||
|
||||
if ( GetFrameType(&cpi->pb) == BASE_FRAME ){
|
||||
/* Key frame so code block in INTRA mode. */
|
||||
cpi->pb.CodingMode = CODE_INTRA;
|
||||
}else{
|
||||
/* Get Motion vector and mode for this block. */
|
||||
cpi->pb.CodingMode = cpi->pb.FragCodingMethod[FragIndex];
|
||||
}
|
||||
|
||||
/* Tokenise the dct data. */
|
||||
token_count = TokenizeDctBlock( cpi->pb.QFragData[FragIndex],
|
||||
cpi->pb.TokenList[FragIndex] );
|
||||
|
||||
cpi->FragTokenCounts[FragIndex] = token_count;
|
||||
cpi->TotTokenCount += token_count;
|
||||
|
||||
/* Return number of pixels coded (i.e. 8x8). */
|
||||
return BLOCK_SIZE;
|
||||
}
|
||||
|
||||
static int AllZeroDctData( Q_LIST_ENTRY * QuantList ){
|
||||
ogg_uint32_t i;
|
||||
|
||||
for ( i = 0; i < 64; i ++ )
|
||||
if ( QuantList[i] != 0 )
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void MotionBlockDifference (CP_INSTANCE * cpi, unsigned char * FiltPtr,
|
||||
ogg_int16_t *DctInputPtr, ogg_int32_t MvDevisor,
|
||||
unsigned char* old_ptr1, unsigned char* new_ptr1,
|
||||
ogg_uint32_t FragIndex,ogg_uint32_t PixelsPerLine,
|
||||
ogg_uint32_t ReconPixelsPerLine) {
|
||||
|
||||
ogg_int32_t MvShift;
|
||||
ogg_int32_t MvModMask;
|
||||
ogg_int32_t AbsRefOffset;
|
||||
ogg_int32_t AbsXOffset;
|
||||
ogg_int32_t AbsYOffset;
|
||||
ogg_int32_t MVOffset; /* Baseline motion vector offset */
|
||||
ogg_int32_t ReconPtr2Offset; /* Offset for second reconstruction in
|
||||
half pixel MC */
|
||||
unsigned char *ReconPtr1; /* DCT reconstructed image pointers */
|
||||
unsigned char *ReconPtr2; /* Pointer used in half pixel MC */
|
||||
|
||||
|
||||
switch(MvDevisor) {
|
||||
case 2:
|
||||
MvShift = 1;
|
||||
MvModMask = 1;
|
||||
break;
|
||||
case 4:
|
||||
MvShift = 2;
|
||||
MvModMask = 3;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
cpi->MVector.x = cpi->pb.FragMVect[FragIndex].x;
|
||||
cpi->MVector.y = cpi->pb.FragMVect[FragIndex].y;
|
||||
|
||||
/* Set up the baseline offset for the motion vector. */
|
||||
MVOffset = ((cpi->MVector.y / MvDevisor) * ReconPixelsPerLine) +
|
||||
(cpi->MVector.x / MvDevisor);
|
||||
|
||||
/* Work out the offset of the second reference position for 1/2
|
||||
pixel interpolation. For the U and V planes the MV specifies 1/4
|
||||
pixel accuracy. This is adjusted to 1/2 pixel as follows ( 0->0,
|
||||
1/4->1/2, 1/2->1/2, 3/4->1/2 ). */
|
||||
ReconPtr2Offset = 0;
|
||||
AbsXOffset = cpi->MVector.x % MvDevisor;
|
||||
AbsYOffset = cpi->MVector.y % MvDevisor;
|
||||
|
||||
if ( AbsXOffset ) {
|
||||
if ( cpi->MVector.x > 0 )
|
||||
ReconPtr2Offset += 1;
|
||||
else
|
||||
ReconPtr2Offset -= 1;
|
||||
}
|
||||
|
||||
if ( AbsYOffset ) {
|
||||
if ( cpi->MVector.y > 0 )
|
||||
ReconPtr2Offset += ReconPixelsPerLine;
|
||||
else
|
||||
ReconPtr2Offset -= ReconPixelsPerLine;
|
||||
}
|
||||
|
||||
if ( cpi->pb.CodingMode==CODE_GOLDEN_MV ) {
|
||||
ReconPtr1 = &cpi->
|
||||
pb.GoldenFrame[cpi->pb.recon_pixel_index_table[FragIndex]];
|
||||
} else {
|
||||
ReconPtr1 = &cpi->
|
||||
pb.LastFrameRecon[cpi->pb.recon_pixel_index_table[FragIndex]];
|
||||
}
|
||||
|
||||
ReconPtr1 += MVOffset;
|
||||
ReconPtr2 = ReconPtr1 + ReconPtr2Offset;
|
||||
|
||||
AbsRefOffset = abs((int)(ReconPtr1 - ReconPtr2));
|
||||
|
||||
/* Is the MV offset exactly pixel alligned */
|
||||
if ( AbsRefOffset == 0 ){
|
||||
Sub8( FiltPtr, ReconPtr1, DctInputPtr, old_ptr1, new_ptr1,
|
||||
PixelsPerLine, ReconPixelsPerLine );
|
||||
} else {
|
||||
/* Fractional pixel MVs. */
|
||||
/* Note that we only use two pixel values even for the diagonal */
|
||||
Sub8Av2(FiltPtr, ReconPtr1,ReconPtr2,DctInputPtr, old_ptr1,
|
||||
new_ptr1, PixelsPerLine, ReconPixelsPerLine );
|
||||
}
|
||||
}
|
||||
|
||||
void TransformQuantizeBlock (CP_INSTANCE *cpi, ogg_int32_t FragIndex,
|
||||
ogg_uint32_t PixelsPerLine ) {
|
||||
unsigned char *new_ptr1; /* Pointers into current frame */
|
||||
unsigned char *old_ptr1; /* Pointers into old frame */
|
||||
unsigned char *FiltPtr; /* Pointers to srf filtered pixels */
|
||||
ogg_int16_t *DctInputPtr; /* Pointer into buffer containing input to DCT */
|
||||
int LeftEdge; /* Flag if block at left edge of component */
|
||||
ogg_uint32_t ReconPixelsPerLine; /* Line length for recon buffers. */
|
||||
|
||||
unsigned char *ReconPtr1; /* DCT reconstructed image pointers */
|
||||
ogg_int32_t MvDevisor; /* Defines MV resolution (2 = 1/2
|
||||
pixel for Y or 4 = 1/4 for UV) */
|
||||
|
||||
new_ptr1 = &cpi->yuv1ptr[cpi->pb.pixel_index_table[FragIndex]];
|
||||
old_ptr1 = &cpi->yuv0ptr[cpi->pb.pixel_index_table[FragIndex]];
|
||||
DctInputPtr = cpi->DCTDataBuffer;
|
||||
|
||||
/* Set plane specific values */
|
||||
if (FragIndex < (ogg_int32_t)cpi->pb.YPlaneFragments){
|
||||
ReconPixelsPerLine = cpi->pb.YStride;
|
||||
MvDevisor = 2; /* 1/2 pixel accuracy in Y */
|
||||
}else{
|
||||
ReconPixelsPerLine = cpi->pb.UVStride;
|
||||
MvDevisor = 4; /* UV planes at 1/2 resolution of Y */
|
||||
}
|
||||
|
||||
/* adjusted / filtered pointers */
|
||||
FiltPtr = &cpi->ConvDestBuffer[cpi->pb.pixel_index_table[FragIndex]];
|
||||
|
||||
if ( GetFrameType(&cpi->pb) == BASE_FRAME ) {
|
||||
/* Key frame so code block in INTRA mode. */
|
||||
cpi->pb.CodingMode = CODE_INTRA;
|
||||
}else{
|
||||
/* Get Motion vector and mode for this block. */
|
||||
cpi->pb.CodingMode = cpi->pb.FragCodingMethod[FragIndex];
|
||||
}
|
||||
|
||||
/* Selection of Quantiser matirx and set other plane related values. */
|
||||
if ( FragIndex < (ogg_int32_t)cpi->pb.YPlaneFragments ){
|
||||
LeftEdge = !(FragIndex%cpi->pb.HFragments);
|
||||
|
||||
/* Select the approrpriate Y quantiser matrix */
|
||||
if ( cpi->pb.CodingMode == CODE_INTRA )
|
||||
select_Y_quantiser(&cpi->pb);
|
||||
else
|
||||
select_Inter_quantiser(&cpi->pb);
|
||||
}else{
|
||||
LeftEdge = !((FragIndex-cpi->pb.YPlaneFragments)%(cpi->pb.HFragments>>1));
|
||||
|
||||
/* Select the approrpriate UV quantiser matrix */
|
||||
if ( cpi->pb.CodingMode == CODE_INTRA )
|
||||
select_UV_quantiser(&cpi->pb);
|
||||
else
|
||||
select_Inter_quantiser(&cpi->pb);
|
||||
}
|
||||
|
||||
if ( ModeUsesMC[cpi->pb.CodingMode] ){
|
||||
|
||||
MotionBlockDifference(cpi, FiltPtr, DctInputPtr, MvDevisor,
|
||||
old_ptr1, new_ptr1, FragIndex, PixelsPerLine,
|
||||
ReconPixelsPerLine);
|
||||
|
||||
} else if ( (cpi->pb.CodingMode==CODE_INTER_NO_MV ) ||
|
||||
( cpi->pb.CodingMode==CODE_USING_GOLDEN ) ) {
|
||||
if ( cpi->pb.CodingMode==CODE_INTER_NO_MV ) {
|
||||
ReconPtr1 = &cpi->
|
||||
pb.LastFrameRecon[cpi->pb.recon_pixel_index_table[FragIndex]];
|
||||
} else {
|
||||
ReconPtr1 = &cpi->
|
||||
pb.GoldenFrame[cpi->pb.recon_pixel_index_table[FragIndex]];
|
||||
}
|
||||
|
||||
Sub8( FiltPtr, ReconPtr1, DctInputPtr, old_ptr1, new_ptr1,
|
||||
PixelsPerLine, ReconPixelsPerLine );
|
||||
} else if ( cpi->pb.CodingMode==CODE_INTRA ) {
|
||||
Sub8_128(FiltPtr, DctInputPtr, old_ptr1, new_ptr1, PixelsPerLine);
|
||||
|
||||
}
|
||||
|
||||
/* Proceed to encode the data into the encode buffer if the encoder
|
||||
is enabled. */
|
||||
/* Perform a 2D DCT transform on the data. */
|
||||
fdct_short( cpi->DCTDataBuffer, cpi->DCT_codes );
|
||||
|
||||
/* Quantize that transform data. */
|
||||
quantize ( &cpi->pb, cpi->DCT_codes, cpi->pb.QFragData[FragIndex] );
|
||||
|
||||
if ( (cpi->pb.CodingMode == CODE_INTER_NO_MV) &&
|
||||
( AllZeroDctData(cpi->pb.QFragData[FragIndex]) ) ) {
|
||||
cpi->pb.display_fragments[FragIndex] = 0;
|
||||
}
|
||||
|
||||
}
|
838
src/add-ons/media/plugins/theora/libtheora/decode.c
Normal file
838
src/add-ons/media/plugins/theora/libtheora/decode.c
Normal file
@ -0,0 +1,838 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2003 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function:
|
||||
last mod: $Id: decode.c,v 1.1 2004/02/24 13:50:13 shatty Exp $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include "encoder_internal.h"
|
||||
#include "block_inline.h"
|
||||
|
||||
static const CODING_MODE ModeAlphabet[MODE_METHODS-2][MAX_MODES] = {
|
||||
|
||||
/* Last motion vector dominates */
|
||||
{ CODE_INTER_LAST_MV, CODE_INTER_PRIOR_LAST,
|
||||
CODE_INTER_PLUS_MV, CODE_INTER_NO_MV,
|
||||
CODE_INTRA, CODE_USING_GOLDEN,
|
||||
CODE_GOLDEN_MV, CODE_INTER_FOURMV },
|
||||
|
||||
{ CODE_INTER_LAST_MV, CODE_INTER_PRIOR_LAST,
|
||||
CODE_INTER_NO_MV, CODE_INTER_PLUS_MV,
|
||||
CODE_INTRA, CODE_USING_GOLDEN,
|
||||
CODE_GOLDEN_MV, CODE_INTER_FOURMV },
|
||||
|
||||
{ CODE_INTER_LAST_MV, CODE_INTER_PLUS_MV,
|
||||
CODE_INTER_PRIOR_LAST, CODE_INTER_NO_MV,
|
||||
CODE_INTRA, CODE_USING_GOLDEN,
|
||||
CODE_GOLDEN_MV, CODE_INTER_FOURMV },
|
||||
|
||||
{ CODE_INTER_LAST_MV, CODE_INTER_PLUS_MV,
|
||||
CODE_INTER_NO_MV, CODE_INTER_PRIOR_LAST,
|
||||
CODE_INTRA, CODE_USING_GOLDEN,
|
||||
CODE_GOLDEN_MV, CODE_INTER_FOURMV },
|
||||
|
||||
/* No motion vector dominates */
|
||||
{ CODE_INTER_NO_MV, CODE_INTER_LAST_MV,
|
||||
CODE_INTER_PRIOR_LAST, CODE_INTER_PLUS_MV,
|
||||
CODE_INTRA, CODE_USING_GOLDEN,
|
||||
CODE_GOLDEN_MV, CODE_INTER_FOURMV },
|
||||
|
||||
{ CODE_INTER_NO_MV, CODE_USING_GOLDEN,
|
||||
CODE_INTER_LAST_MV, CODE_INTER_PRIOR_LAST,
|
||||
CODE_INTER_PLUS_MV, CODE_INTRA,
|
||||
CODE_GOLDEN_MV, CODE_INTER_FOURMV },
|
||||
|
||||
};
|
||||
|
||||
int GetFrameType(PB_INSTANCE *pbi){
|
||||
return pbi->FrameType;
|
||||
}
|
||||
|
||||
static int LoadFrameHeader(PB_INSTANCE *pbi){
|
||||
long ret;
|
||||
unsigned char DctQMask;
|
||||
unsigned char SpareBits; /* Spare cfg bits */
|
||||
|
||||
/* Is the frame and inter frame or a key frame */
|
||||
theora_read(pbi->opb,1,&ret);
|
||||
pbi->FrameType = (unsigned char)ret;
|
||||
|
||||
/* Quality (Q) index */
|
||||
theora_read(pbi->opb,6,&ret);
|
||||
DctQMask = (unsigned char)ret;
|
||||
|
||||
/* spare bit for possible additional Q indicies - should be 0 */
|
||||
theora_read(pbi->opb,1,&ret);
|
||||
SpareBits = (unsigned char)ret;
|
||||
|
||||
if ( (pbi->FrameType == BASE_FRAME) ){
|
||||
/* Read the type / coding method for the key frame. */
|
||||
theora_read(pbi->opb,1,&ret);
|
||||
pbi->KeyFrameType = (unsigned char)ret;
|
||||
|
||||
theora_read(pbi->opb,2,&ret);
|
||||
SpareBits = (unsigned char)ret;
|
||||
|
||||
}
|
||||
|
||||
/* Set this frame quality value from Q Index */
|
||||
pbi->ThisFrameQualityValue = pbi->QThreshTable[DctQMask];
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void SetFrameType( PB_INSTANCE *pbi,unsigned char FrType ){
|
||||
/* Set the appropriate frame type according to the request. */
|
||||
switch ( FrType ){
|
||||
|
||||
case BASE_FRAME:
|
||||
pbi->FrameType = FrType;
|
||||
break;
|
||||
|
||||
default:
|
||||
pbi->FrameType = FrType;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int LoadFrame(PB_INSTANCE *pbi){
|
||||
|
||||
/* Load the frame header (including the frame size). */
|
||||
if ( LoadFrameHeader(pbi) ){
|
||||
/* Read in the updated block map */
|
||||
QuadDecodeDisplayFragments( pbi );
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void DecodeModes (PB_INSTANCE *pbi,
|
||||
ogg_uint32_t SBRows,
|
||||
ogg_uint32_t SBCols){
|
||||
long ret;
|
||||
ogg_int32_t FragIndex;
|
||||
ogg_uint32_t MB;
|
||||
ogg_uint32_t SBrow;
|
||||
ogg_uint32_t SBcol;
|
||||
ogg_uint32_t SB=0;
|
||||
CODING_MODE CodingMethod;
|
||||
|
||||
ogg_uint32_t UVRow;
|
||||
ogg_uint32_t UVColumn;
|
||||
ogg_uint32_t UVFragOffset;
|
||||
|
||||
ogg_uint32_t CodingScheme;
|
||||
|
||||
ogg_uint32_t MBListIndex = 0;
|
||||
|
||||
ogg_uint32_t i;
|
||||
|
||||
/* If the frame is an intra frame then all blocks have mode intra. */
|
||||
if ( GetFrameType(pbi) == BASE_FRAME ){
|
||||
for ( i = 0; i < pbi->UnitFragments; i++ ){
|
||||
pbi->FragCodingMethod[i] = CODE_INTRA;
|
||||
}
|
||||
}else{
|
||||
ogg_uint32_t ModeEntry; /* Mode bits read */
|
||||
CODING_MODE CustomModeAlphabet[MAX_MODES];
|
||||
const CODING_MODE *ModeList;
|
||||
|
||||
/* Read the coding method */
|
||||
theora_read(pbi->opb, MODE_METHOD_BITS, &ret);
|
||||
CodingScheme=ret;
|
||||
|
||||
/* If the coding method is method 0 then we have to read in a
|
||||
custom coding scheme */
|
||||
if ( CodingScheme == 0 ){
|
||||
/* Read the coding scheme. */
|
||||
for ( i = 0; i < MAX_MODES; i++ ){
|
||||
theora_read(pbi->opb, MODE_BITS, &ret);
|
||||
CustomModeAlphabet[ret]=i;
|
||||
}
|
||||
ModeList=CustomModeAlphabet;
|
||||
}
|
||||
else{
|
||||
ModeList=ModeAlphabet[CodingScheme-1];
|
||||
}
|
||||
|
||||
/* Unravel the quad-tree */
|
||||
for ( SBrow=0; SBrow<SBRows; SBrow++ ){
|
||||
for ( SBcol=0; SBcol<SBCols; SBcol++ ){
|
||||
for ( MB=0; MB<4; MB++ ){
|
||||
/* There may be MB's lying out of frame which must be
|
||||
ignored. For these MB's top left block will have a negative
|
||||
Fragment Index. */
|
||||
if ( QuadMapToMBTopLeft(pbi->BlockMap, SB,MB) >= 0){
|
||||
/* Is the Macro-Block coded: */
|
||||
if ( pbi->MBCodedFlags[MBListIndex++] ){
|
||||
/* Upack the block level modes and motion vectors */
|
||||
FragIndex = QuadMapToMBTopLeft( pbi->BlockMap, SB, MB );
|
||||
|
||||
/* Unpack the mode. */
|
||||
if ( CodingScheme == (MODE_METHODS-1) ){
|
||||
/* This is the fall back coding scheme. */
|
||||
/* Simply MODE_BITS bits per mode entry. */
|
||||
theora_read(pbi->opb, MODE_BITS, &ret);
|
||||
CodingMethod = (CODING_MODE)ret;
|
||||
}else{
|
||||
ModeEntry = FrArrayUnpackMode(pbi);
|
||||
CodingMethod = ModeList[ModeEntry];
|
||||
}
|
||||
|
||||
/* Note the coding mode for each block in macro block. */
|
||||
pbi->FragCodingMethod[FragIndex] = CodingMethod;
|
||||
pbi->FragCodingMethod[FragIndex + 1] = CodingMethod;
|
||||
pbi->FragCodingMethod[FragIndex + pbi->HFragments] =
|
||||
CodingMethod;
|
||||
pbi->FragCodingMethod[FragIndex + pbi->HFragments + 1] =
|
||||
CodingMethod;
|
||||
|
||||
/* Matching fragments in the U and V planes */
|
||||
UVRow = (FragIndex / (pbi->HFragments * 2));
|
||||
UVColumn = (FragIndex % pbi->HFragments) / 2;
|
||||
UVFragOffset = (UVRow * (pbi->HFragments / 2)) + UVColumn;
|
||||
pbi->FragCodingMethod[pbi->YPlaneFragments + UVFragOffset] =
|
||||
CodingMethod;
|
||||
pbi->FragCodingMethod[pbi->YPlaneFragments +
|
||||
pbi->UVPlaneFragments + UVFragOffset] =
|
||||
CodingMethod;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Next Super-Block */
|
||||
SB++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static ogg_int32_t ExtractMVectorComponentA(PB_INSTANCE *pbi){
|
||||
long ret;
|
||||
ogg_int32_t MVectComponent;
|
||||
ogg_uint32_t MVCode = 0;
|
||||
ogg_uint32_t ExtraBits = 0;
|
||||
|
||||
/* Get group to which coded component belongs */
|
||||
theora_read(pbi->opb, 3, &ret);
|
||||
MVCode=ret;
|
||||
|
||||
/* Now extract the appropriate number of bits to identify the component */
|
||||
switch ( MVCode ){
|
||||
case 0:
|
||||
MVectComponent = 0;
|
||||
break;
|
||||
case 1:
|
||||
MVectComponent = 1;
|
||||
break;
|
||||
case 2:
|
||||
MVectComponent = -1;
|
||||
break;
|
||||
case 3:
|
||||
theora_read(pbi->opb,1,&ret);
|
||||
if (ret)
|
||||
MVectComponent = -2;
|
||||
else
|
||||
MVectComponent = 2;
|
||||
break;
|
||||
case 4:
|
||||
theora_read(pbi->opb,1,&ret);
|
||||
if (ret)
|
||||
MVectComponent = -3;
|
||||
else
|
||||
MVectComponent = 3;
|
||||
break;
|
||||
case 5:
|
||||
theora_read(pbi->opb,2,&ret);
|
||||
ExtraBits=ret;
|
||||
MVectComponent = 4 + ExtraBits;
|
||||
theora_read(pbi->opb,1,&ret);
|
||||
if (ret)
|
||||
MVectComponent = -MVectComponent;
|
||||
break;
|
||||
case 6:
|
||||
theora_read(pbi->opb,3,&ret);
|
||||
ExtraBits=ret;
|
||||
MVectComponent = 8 + ExtraBits;
|
||||
theora_read(pbi->opb,1,&ret);
|
||||
if (ret)
|
||||
MVectComponent = -MVectComponent;
|
||||
break;
|
||||
case 7:
|
||||
theora_read(pbi->opb,4,&ret);
|
||||
ExtraBits=ret;
|
||||
MVectComponent = 16 + ExtraBits;
|
||||
theora_read(pbi->opb,1,&ret);
|
||||
if (ret)
|
||||
MVectComponent = -MVectComponent;
|
||||
break;
|
||||
}
|
||||
|
||||
return MVectComponent;
|
||||
}
|
||||
|
||||
static ogg_int32_t ExtractMVectorComponentB(PB_INSTANCE *pbi){
|
||||
long ret;
|
||||
ogg_int32_t MVectComponent;
|
||||
|
||||
/* Get group to which coded component belongs */
|
||||
theora_read(pbi->opb,5,&ret);
|
||||
MVectComponent=ret;
|
||||
theora_read(pbi->opb,1,&ret);
|
||||
if (ret)
|
||||
MVectComponent = -MVectComponent;
|
||||
|
||||
return MVectComponent;
|
||||
}
|
||||
|
||||
static void DecodeMVectors ( PB_INSTANCE *pbi,
|
||||
ogg_uint32_t SBRows,
|
||||
ogg_uint32_t SBCols ){
|
||||
long ret;
|
||||
ogg_int32_t FragIndex;
|
||||
ogg_uint32_t MB;
|
||||
ogg_uint32_t SBrow;
|
||||
ogg_uint32_t SBcol;
|
||||
ogg_uint32_t SB=0;
|
||||
ogg_uint32_t CodingMethod;
|
||||
|
||||
MOTION_VECTOR MVect[6];
|
||||
MOTION_VECTOR TmpMVect;
|
||||
MOTION_VECTOR LastInterMV;
|
||||
MOTION_VECTOR PriorLastInterMV;
|
||||
ogg_int32_t (*ExtractMVectorComponent)(PB_INSTANCE *pbi);
|
||||
|
||||
ogg_uint32_t UVRow;
|
||||
ogg_uint32_t UVColumn;
|
||||
ogg_uint32_t UVFragOffset;
|
||||
|
||||
ogg_uint32_t MBListIndex = 0;
|
||||
|
||||
/* Should not be decoding motion vectors if in INTRA only mode. */
|
||||
if ( GetFrameType(pbi) == BASE_FRAME ){
|
||||
return;
|
||||
}
|
||||
|
||||
/* set the default motion vector to 0,0 */
|
||||
MVect[0].x = 0;
|
||||
MVect[0].y = 0;
|
||||
LastInterMV.x = 0;
|
||||
LastInterMV.y = 0;
|
||||
PriorLastInterMV.x = 0;
|
||||
PriorLastInterMV.y = 0;
|
||||
|
||||
/* Read the entropy method used and set up the appropriate decode option */
|
||||
theora_read(pbi->opb, 1, &ret);
|
||||
if ( ret == 0 )
|
||||
ExtractMVectorComponent = ExtractMVectorComponentA;
|
||||
else
|
||||
ExtractMVectorComponent = ExtractMVectorComponentB;
|
||||
|
||||
/* Unravel the quad-tree */
|
||||
for ( SBrow=0; SBrow<SBRows; SBrow++ ){
|
||||
|
||||
for ( SBcol=0; SBcol<SBCols; SBcol++ ){
|
||||
for ( MB=0; MB<4; MB++ ){
|
||||
/* There may be MB's lying out of frame which must be
|
||||
ignored. For these MB's the top left block will have a
|
||||
negative Fragment. */
|
||||
if ( QuadMapToMBTopLeft(pbi->BlockMap, SB,MB) >= 0 ) {
|
||||
/* Is the Macro-Block further coded: */
|
||||
if ( pbi->MBCodedFlags[MBListIndex++] ){
|
||||
/* Upack the block level modes and motion vectors */
|
||||
FragIndex = QuadMapToMBTopLeft( pbi->BlockMap, SB, MB );
|
||||
|
||||
/* Clear the motion vector before we start. */
|
||||
MVect[0].x = 0;
|
||||
MVect[0].y = 0;
|
||||
|
||||
/* Unpack the mode (and motion vectors if necessary). */
|
||||
CodingMethod = pbi->FragCodingMethod[FragIndex];
|
||||
|
||||
/* Read the motion vector or vectors if present. */
|
||||
if ( (CodingMethod == CODE_INTER_PLUS_MV) ||
|
||||
(CodingMethod == CODE_GOLDEN_MV) ){
|
||||
MVect[0].x = ExtractMVectorComponent(pbi);
|
||||
MVect[1].x = MVect[0].x;
|
||||
MVect[2].x = MVect[0].x;
|
||||
MVect[3].x = MVect[0].x;
|
||||
MVect[4].x = MVect[0].x;
|
||||
MVect[5].x = MVect[0].x;
|
||||
MVect[0].y = ExtractMVectorComponent(pbi);
|
||||
MVect[1].y = MVect[0].y;
|
||||
MVect[2].y = MVect[0].y;
|
||||
MVect[3].y = MVect[0].y;
|
||||
MVect[4].y = MVect[0].y;
|
||||
MVect[5].y = MVect[0].y;
|
||||
}else if ( CodingMethod == CODE_INTER_FOURMV ){
|
||||
/* Extrac the 4 Y MVs */
|
||||
MVect[0].x = ExtractMVectorComponent(pbi);
|
||||
MVect[0].y = ExtractMVectorComponent(pbi);
|
||||
|
||||
MVect[1].x = ExtractMVectorComponent(pbi);
|
||||
MVect[1].y = ExtractMVectorComponent(pbi);
|
||||
|
||||
MVect[2].x = ExtractMVectorComponent(pbi);
|
||||
MVect[2].y = ExtractMVectorComponent(pbi);
|
||||
|
||||
MVect[3].x = ExtractMVectorComponent(pbi);
|
||||
MVect[3].y = ExtractMVectorComponent(pbi);
|
||||
|
||||
/* Calculate the U and V plane MVs as the average of the
|
||||
Y plane MVs. */
|
||||
/* First .x component */
|
||||
MVect[4].x = MVect[0].x + MVect[1].x + MVect[2].x + MVect[3].x;
|
||||
if ( MVect[4].x >= 0 )
|
||||
MVect[4].x = (MVect[4].x + 2) / 4;
|
||||
else
|
||||
MVect[4].x = (MVect[4].x - 2) / 4;
|
||||
MVect[5].x = MVect[4].x;
|
||||
/* Then .y component */
|
||||
MVect[4].y = MVect[0].y + MVect[1].y + MVect[2].y + MVect[3].y;
|
||||
if ( MVect[4].y >= 0 )
|
||||
MVect[4].y = (MVect[4].y + 2) / 4;
|
||||
else
|
||||
MVect[4].y = (MVect[4].y - 2) / 4;
|
||||
MVect[5].y = MVect[4].y;
|
||||
}
|
||||
|
||||
/* Keep track of last and prior last inter motion vectors. */
|
||||
if ( CodingMethod == CODE_INTER_PLUS_MV ){
|
||||
PriorLastInterMV.x = LastInterMV.x;
|
||||
PriorLastInterMV.y = LastInterMV.y;
|
||||
LastInterMV.x = MVect[0].x;
|
||||
LastInterMV.y = MVect[0].y;
|
||||
}else if ( CodingMethod == CODE_INTER_LAST_MV ){
|
||||
/* Use the last coded Inter motion vector. */
|
||||
MVect[0].x = LastInterMV.x;
|
||||
MVect[1].x = MVect[0].x;
|
||||
MVect[2].x = MVect[0].x;
|
||||
MVect[3].x = MVect[0].x;
|
||||
MVect[4].x = MVect[0].x;
|
||||
MVect[5].x = MVect[0].x;
|
||||
MVect[0].y = LastInterMV.y;
|
||||
MVect[1].y = MVect[0].y;
|
||||
MVect[2].y = MVect[0].y;
|
||||
MVect[3].y = MVect[0].y;
|
||||
MVect[4].y = MVect[0].y;
|
||||
MVect[5].y = MVect[0].y;
|
||||
}else if ( CodingMethod == CODE_INTER_PRIOR_LAST ){
|
||||
/* Use the next-to-last coded Inter motion vector. */
|
||||
MVect[0].x = PriorLastInterMV.x;
|
||||
MVect[1].x = MVect[0].x;
|
||||
MVect[2].x = MVect[0].x;
|
||||
MVect[3].x = MVect[0].x;
|
||||
MVect[4].x = MVect[0].x;
|
||||
MVect[5].x = MVect[0].x;
|
||||
MVect[0].y = PriorLastInterMV.y;
|
||||
MVect[1].y = MVect[0].y;
|
||||
MVect[2].y = MVect[0].y;
|
||||
MVect[3].y = MVect[0].y;
|
||||
MVect[4].y = MVect[0].y;
|
||||
MVect[5].y = MVect[0].y;
|
||||
|
||||
/* Swap the prior and last MV cases over */
|
||||
TmpMVect.x = PriorLastInterMV.x;
|
||||
TmpMVect.y = PriorLastInterMV.y;
|
||||
PriorLastInterMV.x = LastInterMV.x;
|
||||
PriorLastInterMV.y = LastInterMV.y;
|
||||
LastInterMV.x = TmpMVect.x;
|
||||
LastInterMV.y = TmpMVect.y;
|
||||
}else if ( CodingMethod == CODE_INTER_FOURMV ){
|
||||
/* Update last MV and prior last mv */
|
||||
PriorLastInterMV.x = LastInterMV.x;
|
||||
PriorLastInterMV.y = LastInterMV.y;
|
||||
LastInterMV.x = MVect[3].x;
|
||||
LastInterMV.y = MVect[3].y;
|
||||
}
|
||||
|
||||
/* Note the coding mode and vector for each block in the
|
||||
current macro block. */
|
||||
pbi->FragMVect[FragIndex].x = MVect[0].x;
|
||||
pbi->FragMVect[FragIndex].y = MVect[0].y;
|
||||
|
||||
pbi->FragMVect[FragIndex + 1].x = MVect[1].x;
|
||||
pbi->FragMVect[FragIndex + 1].y = MVect[1].y;
|
||||
|
||||
pbi->FragMVect[FragIndex + pbi->HFragments].x = MVect[2].x;
|
||||
pbi->FragMVect[FragIndex + pbi->HFragments].y = MVect[2].y;
|
||||
|
||||
pbi->FragMVect[FragIndex + pbi->HFragments + 1].x = MVect[3].x;
|
||||
pbi->FragMVect[FragIndex + pbi->HFragments + 1].y = MVect[3].y;
|
||||
|
||||
/* Matching fragments in the U and V planes */
|
||||
UVRow = (FragIndex / (pbi->HFragments * 2));
|
||||
UVColumn = (FragIndex % pbi->HFragments) / 2;
|
||||
UVFragOffset = (UVRow * (pbi->HFragments / 2)) + UVColumn;
|
||||
|
||||
pbi->FragMVect[pbi->YPlaneFragments + UVFragOffset].x = MVect[4].x;
|
||||
pbi->FragMVect[pbi->YPlaneFragments + UVFragOffset].y = MVect[4].y;
|
||||
|
||||
pbi->FragMVect[pbi->YPlaneFragments + pbi->UVPlaneFragments +
|
||||
UVFragOffset].x = MVect[5].x;
|
||||
pbi->FragMVect[pbi->YPlaneFragments + pbi->UVPlaneFragments +
|
||||
UVFragOffset].y = MVect[5].y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Next Super-Block */
|
||||
SB++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static ogg_uint32_t ExtractToken(oggpack_buffer *opb,
|
||||
HUFF_ENTRY * CurrentRoot){
|
||||
long ret;
|
||||
ogg_uint32_t Token;
|
||||
/* Loop searches down through tree based upon bits read from the
|
||||
bitstream */
|
||||
/* until it hits a leaf at which point we have decoded a token */
|
||||
while ( CurrentRoot->Value < 0 ){
|
||||
|
||||
theora_read(opb, 1, &ret);
|
||||
if (ret)
|
||||
CurrentRoot = CurrentRoot->OneChild;
|
||||
else
|
||||
CurrentRoot = CurrentRoot->ZeroChild;
|
||||
|
||||
}
|
||||
Token = CurrentRoot->Value;
|
||||
return Token;
|
||||
}
|
||||
|
||||
static void UnpackAndExpandDcToken( PB_INSTANCE *pbi,
|
||||
Q_LIST_ENTRY *ExpandedBlock,
|
||||
unsigned char * CoeffIndex ){
|
||||
long ret;
|
||||
ogg_int32_t ExtraBits = 0;
|
||||
ogg_uint32_t Token;
|
||||
|
||||
Token = ExtractToken(pbi->opb, pbi->HuffRoot_VP3x[pbi->DcHuffChoice]);
|
||||
|
||||
|
||||
/* Now.. if we are using the DCT optimised coding system, extract any
|
||||
* assosciated additional bits token.
|
||||
*/
|
||||
if ( pbi->ExtraBitLengths_VP3x[Token] > 0 ){
|
||||
/* Extract the appropriate number of extra bits. */
|
||||
theora_read(pbi->opb,pbi->ExtraBitLengths_VP3x[Token], &ret);
|
||||
ExtraBits = ret;
|
||||
}
|
||||
|
||||
/* Take token dependant action */
|
||||
if ( Token >= DCT_SHORT_ZRL_TOKEN ) {
|
||||
/* "Value", "zero run" and "zero run value" tokens */
|
||||
ExpandToken(ExpandedBlock, CoeffIndex, Token, ExtraBits );
|
||||
if ( *CoeffIndex >= BLOCK_SIZE )
|
||||
pbi->BlocksToDecode --;
|
||||
} else if ( Token == DCT_EOB_TOKEN ){
|
||||
*CoeffIndex = BLOCK_SIZE;
|
||||
pbi->BlocksToDecode --;
|
||||
}else{
|
||||
/* Special action and EOB tokens */
|
||||
switch ( Token ){
|
||||
case DCT_EOB_PAIR_TOKEN:
|
||||
pbi->EOB_Run = 1;
|
||||
*CoeffIndex = BLOCK_SIZE;
|
||||
pbi->BlocksToDecode --;
|
||||
break;
|
||||
case DCT_EOB_TRIPLE_TOKEN:
|
||||
pbi->EOB_Run = 2;
|
||||
*CoeffIndex = BLOCK_SIZE;
|
||||
pbi->BlocksToDecode --;
|
||||
break;
|
||||
case DCT_REPEAT_RUN_TOKEN:
|
||||
pbi->EOB_Run = ExtraBits + 3;
|
||||
*CoeffIndex = BLOCK_SIZE;
|
||||
pbi->BlocksToDecode --;
|
||||
break;
|
||||
case DCT_REPEAT_RUN2_TOKEN:
|
||||
pbi->EOB_Run = ExtraBits + 7;
|
||||
*CoeffIndex = BLOCK_SIZE;
|
||||
pbi->BlocksToDecode --;
|
||||
break;
|
||||
case DCT_REPEAT_RUN3_TOKEN:
|
||||
pbi->EOB_Run = ExtraBits + 15;
|
||||
*CoeffIndex = BLOCK_SIZE;
|
||||
pbi->BlocksToDecode --;
|
||||
break;
|
||||
case DCT_REPEAT_RUN4_TOKEN:
|
||||
pbi->EOB_Run = ExtraBits - 1;
|
||||
*CoeffIndex = BLOCK_SIZE;
|
||||
pbi->BlocksToDecode --;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void UnpackAndExpandAcToken( PB_INSTANCE *pbi,
|
||||
Q_LIST_ENTRY * ExpandedBlock,
|
||||
unsigned char * CoeffIndex ) {
|
||||
long ret;
|
||||
ogg_int32_t ExtraBits = 0;
|
||||
ogg_uint32_t Token;
|
||||
|
||||
Token = ExtractToken(pbi->opb, pbi->HuffRoot_VP3x[pbi->ACHuffChoice]);
|
||||
|
||||
/* Now.. if we are using the DCT optimised coding system, extract any
|
||||
* assosciated additional bits token.
|
||||
*/
|
||||
if ( pbi->ExtraBitLengths_VP3x[Token] > 0 ){
|
||||
/* Extract the appropriate number of extra bits. */
|
||||
theora_read(pbi->opb,pbi->ExtraBitLengths_VP3x[Token], &ret);
|
||||
ExtraBits = ret;
|
||||
}
|
||||
|
||||
/* Take token dependant action */
|
||||
if ( Token >= DCT_SHORT_ZRL_TOKEN ){
|
||||
/* "Value", "zero run" and "zero run value" tokens */
|
||||
ExpandToken(ExpandedBlock, CoeffIndex, Token, ExtraBits );
|
||||
if ( *CoeffIndex >= BLOCK_SIZE )
|
||||
pbi->BlocksToDecode --;
|
||||
} else if ( Token == DCT_EOB_TOKEN ) {
|
||||
*CoeffIndex = BLOCK_SIZE;
|
||||
pbi->BlocksToDecode --;
|
||||
} else {
|
||||
/* Special action and EOB tokens */
|
||||
switch ( Token ) {
|
||||
case DCT_EOB_PAIR_TOKEN:
|
||||
pbi->EOB_Run = 1;
|
||||
*CoeffIndex = BLOCK_SIZE;
|
||||
pbi->BlocksToDecode --;
|
||||
break;
|
||||
case DCT_EOB_TRIPLE_TOKEN:
|
||||
pbi->EOB_Run = 2;
|
||||
*CoeffIndex = BLOCK_SIZE;
|
||||
pbi->BlocksToDecode --;
|
||||
break;
|
||||
case DCT_REPEAT_RUN_TOKEN:
|
||||
pbi->EOB_Run = ExtraBits + 3;
|
||||
*CoeffIndex = BLOCK_SIZE;
|
||||
pbi->BlocksToDecode --;
|
||||
break;
|
||||
case DCT_REPEAT_RUN2_TOKEN:
|
||||
pbi->EOB_Run = ExtraBits + 7;
|
||||
*CoeffIndex = BLOCK_SIZE;
|
||||
pbi->BlocksToDecode --;
|
||||
break;
|
||||
case DCT_REPEAT_RUN3_TOKEN:
|
||||
pbi->EOB_Run = ExtraBits + 15;
|
||||
*CoeffIndex = BLOCK_SIZE;
|
||||
pbi->BlocksToDecode --;
|
||||
break;
|
||||
case DCT_REPEAT_RUN4_TOKEN:
|
||||
pbi->EOB_Run = ExtraBits - 1;
|
||||
*CoeffIndex = BLOCK_SIZE;
|
||||
pbi->BlocksToDecode --;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void UnPackVideo (PB_INSTANCE *pbi){
|
||||
long ret;
|
||||
ogg_int32_t EncodedCoeffs = 1;
|
||||
ogg_int32_t FragIndex;
|
||||
ogg_int32_t * CodedBlockListPtr;
|
||||
ogg_int32_t * CodedBlockListEnd;
|
||||
|
||||
unsigned char AcHuffIndex1;
|
||||
unsigned char AcHuffIndex2;
|
||||
unsigned char AcHuffChoice1;
|
||||
unsigned char AcHuffChoice2;
|
||||
|
||||
unsigned char DcHuffChoice1;
|
||||
unsigned char DcHuffChoice2;
|
||||
|
||||
|
||||
/* Bail out immediately if a decode error has already been reported. */
|
||||
if ( pbi->DecoderErrorCode ) return;
|
||||
|
||||
/* Clear down the array that indicates the current coefficient index
|
||||
for each block. */
|
||||
memset(pbi->FragCoeffs, 0, pbi->UnitFragments);
|
||||
memset(pbi->FragCoefEOB, 0, pbi->UnitFragments);
|
||||
|
||||
/* Clear down the pbi->QFragData structure for all coded blocks. */
|
||||
ClearDownQFragData(pbi);
|
||||
|
||||
/* Note the number of blocks to decode */
|
||||
pbi->BlocksToDecode = pbi->CodedBlockIndex;
|
||||
|
||||
/* Get the DC huffman table choice for Y and then UV */
|
||||
theora_read(pbi->opb,DC_HUFF_CHOICE_BITS,&ret);
|
||||
DcHuffChoice1 = ret + DC_HUFF_OFFSET;
|
||||
theora_read(pbi->opb,DC_HUFF_CHOICE_BITS,&ret);
|
||||
DcHuffChoice2 = ret + DC_HUFF_OFFSET;
|
||||
|
||||
/* UnPack DC coefficients / tokens */
|
||||
CodedBlockListPtr = pbi->CodedBlockList;
|
||||
CodedBlockListEnd = &pbi->CodedBlockList[pbi->CodedBlockIndex];
|
||||
while ( CodedBlockListPtr < CodedBlockListEnd ) {
|
||||
/* Get the block data index */
|
||||
FragIndex = *CodedBlockListPtr;
|
||||
pbi->FragCoefEOB[FragIndex] = pbi->FragCoeffs[FragIndex];
|
||||
|
||||
/* Select the appropriate huffman table offset according to
|
||||
whether the token is from a Y or UV block */
|
||||
if ( FragIndex < (ogg_int32_t)pbi->YPlaneFragments )
|
||||
pbi->DcHuffChoice = DcHuffChoice1;
|
||||
else
|
||||
pbi->DcHuffChoice = DcHuffChoice2;
|
||||
|
||||
/* If we are in the middle of an EOB run */
|
||||
if ( pbi->EOB_Run ){
|
||||
/* Mark the current block as fully expanded and decrement
|
||||
EOB_RUN count */
|
||||
pbi->FragCoeffs[FragIndex] = BLOCK_SIZE;
|
||||
pbi->EOB_Run --;
|
||||
pbi->BlocksToDecode --;
|
||||
}else{
|
||||
/* Else unpack a DC token */
|
||||
UnpackAndExpandDcToken( pbi,
|
||||
pbi->QFragData[FragIndex],
|
||||
&pbi->FragCoeffs[FragIndex] );
|
||||
}
|
||||
CodedBlockListPtr++;
|
||||
}
|
||||
|
||||
/* Get the AC huffman table choice for Y and then for UV. */
|
||||
|
||||
theora_read(pbi->opb,AC_HUFF_CHOICE_BITS,&ret);
|
||||
AcHuffIndex1 = ret + AC_HUFF_OFFSET;
|
||||
theora_read(pbi->opb,AC_HUFF_CHOICE_BITS,&ret);
|
||||
AcHuffIndex2 = ret + AC_HUFF_OFFSET;
|
||||
|
||||
/* Unpack Lower AC coefficients. */
|
||||
while ( EncodedCoeffs < 64 ) {
|
||||
/* Repeatedly scan through the list of blocks. */
|
||||
CodedBlockListPtr = pbi->CodedBlockList;
|
||||
CodedBlockListEnd = &pbi->CodedBlockList[pbi->CodedBlockIndex];
|
||||
|
||||
/* Huffman table selection based upon which AC coefficient we are on */
|
||||
if ( EncodedCoeffs <= AC_TABLE_2_THRESH ){
|
||||
AcHuffChoice1 = AcHuffIndex1;
|
||||
AcHuffChoice2 = AcHuffIndex2;
|
||||
}else if ( EncodedCoeffs <= AC_TABLE_3_THRESH ){
|
||||
AcHuffChoice1 = AcHuffIndex1 + AC_HUFF_CHOICES;
|
||||
AcHuffChoice2 = AcHuffIndex2 + AC_HUFF_CHOICES;
|
||||
} else if ( EncodedCoeffs <= AC_TABLE_4_THRESH ){
|
||||
AcHuffChoice1 = AcHuffIndex1 + (AC_HUFF_CHOICES * 2);
|
||||
AcHuffChoice2 = AcHuffIndex2 + (AC_HUFF_CHOICES * 2);
|
||||
} else {
|
||||
AcHuffChoice1 = AcHuffIndex1 + (AC_HUFF_CHOICES * 3);
|
||||
AcHuffChoice2 = AcHuffIndex2 + (AC_HUFF_CHOICES * 3);
|
||||
}
|
||||
|
||||
while( CodedBlockListPtr < CodedBlockListEnd ) {
|
||||
/* Get the linear index for the current fragment. */
|
||||
FragIndex = *CodedBlockListPtr;
|
||||
|
||||
/* Should we decode a token for this block on this pass. */
|
||||
if ( pbi->FragCoeffs[FragIndex] <= EncodedCoeffs ) {
|
||||
pbi->FragCoefEOB[FragIndex] = pbi->FragCoeffs[FragIndex];
|
||||
/* If we are in the middle of an EOB run */
|
||||
if ( pbi->EOB_Run ) {
|
||||
/* Mark the current block as fully expanded and decrement
|
||||
EOB_RUN count */
|
||||
pbi->FragCoeffs[FragIndex] = BLOCK_SIZE;
|
||||
pbi->EOB_Run --;
|
||||
pbi->BlocksToDecode --;
|
||||
}else{
|
||||
/* Else unpack an AC token */
|
||||
/* Work out which huffman table to use, then decode a token */
|
||||
if ( FragIndex < (ogg_int32_t)pbi->YPlaneFragments )
|
||||
pbi->ACHuffChoice = AcHuffChoice1;
|
||||
else
|
||||
pbi->ACHuffChoice = AcHuffChoice2;
|
||||
|
||||
UnpackAndExpandAcToken( pbi, pbi->QFragData[FragIndex],
|
||||
&pbi->FragCoeffs[FragIndex] );
|
||||
}
|
||||
}
|
||||
CodedBlockListPtr++;
|
||||
}
|
||||
|
||||
/* Test for condition where there are no blocks left with any
|
||||
tokesn to decode */
|
||||
if ( !pbi->BlocksToDecode )
|
||||
break;
|
||||
|
||||
EncodedCoeffs ++;
|
||||
}
|
||||
}
|
||||
|
||||
static void DecodeData(PB_INSTANCE *pbi){
|
||||
ogg_uint32_t i;
|
||||
|
||||
/* Bail out immediately if a decode error has already been reported. */
|
||||
if ( pbi->DecoderErrorCode ) return;
|
||||
|
||||
/* Clear down the macro block level mode and MV arrays. */
|
||||
for ( i = 0; i < pbi->UnitFragments; i++ ){
|
||||
pbi->FragCodingMethod[i] = CODE_INTER_NO_MV; /* Default coding mode */
|
||||
pbi->FragMVect[i].x = 0;
|
||||
pbi->FragMVect[i].y = 0;
|
||||
}
|
||||
|
||||
/* Zero Decoder EOB run count */
|
||||
pbi->EOB_Run = 0;
|
||||
|
||||
/* Make a not of the number of coded blocks this frame */
|
||||
pbi->CodedBlocksThisFrame = pbi->CodedBlockIndex;
|
||||
|
||||
/* Decode the modes data */
|
||||
DecodeModes( pbi, pbi->YSBRows, pbi->YSBCols);
|
||||
|
||||
/* Unpack and decode the motion vectors. */
|
||||
DecodeMVectors ( pbi, pbi->YSBRows, pbi->YSBCols);
|
||||
|
||||
/* Unpack and decode the actual video data. */
|
||||
UnPackVideo(pbi);
|
||||
|
||||
/* Reconstruct and display the frame */
|
||||
ReconRefFrames(pbi);
|
||||
|
||||
}
|
||||
|
||||
|
||||
int LoadAndDecode(PB_INSTANCE *pbi){
|
||||
int LoadFrameOK;
|
||||
|
||||
/* Reset the DC predictors. */
|
||||
pbi->InvLastIntraDC = 0;
|
||||
pbi->InvLastInterDC = 0;
|
||||
|
||||
/* Load the next frame. */
|
||||
LoadFrameOK = LoadFrame(pbi);
|
||||
|
||||
if ( LoadFrameOK ){
|
||||
if ( (pbi->ThisFrameQualityValue != pbi->LastFrameQualityValue) ){
|
||||
/* Initialise DCT tables. */
|
||||
UpdateQ( pbi, pbi->ThisFrameQualityValue );
|
||||
pbi->LastFrameQualityValue = pbi->ThisFrameQualityValue;
|
||||
}
|
||||
|
||||
|
||||
/* Decode the data into the fragment buffer. */
|
||||
DecodeData(pbi);
|
||||
return(0);
|
||||
}
|
||||
|
||||
return(OC_BADPACKET);
|
||||
}
|
1491
src/add-ons/media/plugins/theora/libtheora/encode.c
Normal file
1491
src/add-ons/media/plugins/theora/libtheora/encode.c
Normal file
File diff suppressed because it is too large
Load Diff
800
src/add-ons/media/plugins/theora/libtheora/encoder_internal.h
Normal file
800
src/add-ons/media/plugins/theora/libtheora/encoder_internal.h
Normal file
@ -0,0 +1,800 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2003 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function:
|
||||
last mod: $Id: encoder_internal.h,v 1.1 2004/02/24 13:50:13 shatty Exp $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#ifndef ENCODER_INTERNAL_H
|
||||
#define ENCODER_INTERNAL_H
|
||||
|
||||
#include <theora/theora.h>
|
||||
#include "huffman.h"
|
||||
|
||||
#ifndef LIBOGG2
|
||||
#define theora_read(x,y,z) ( *z = oggpackB_read(x,y) )
|
||||
#else
|
||||
#define theora_read(x,y,z) ( oggpackB_read(x,y,z) )
|
||||
#endif
|
||||
|
||||
#define CURRENT_ENCODE_VERSION 1
|
||||
#define HUGE_ERROR (1<<28) /* Out of range test value */
|
||||
|
||||
/* Baseline dct height and width. */
|
||||
#define BLOCK_HEIGHT_WIDTH 8
|
||||
#define HFRAGPIXELS 8
|
||||
#define VFRAGPIXELS 8
|
||||
|
||||
/* Baseline dct block size */
|
||||
#define BLOCK_SIZE (BLOCK_HEIGHT_WIDTH * BLOCK_HEIGHT_WIDTH)
|
||||
|
||||
/* Border is for unrestricted mv's */
|
||||
#define UMV_BORDER 16
|
||||
#define STRIDE_EXTRA (UMV_BORDER * 2)
|
||||
#define Q_TABLE_SIZE 64
|
||||
|
||||
#define BASE_FRAME 0
|
||||
#define NORMAL_FRAME 1
|
||||
|
||||
#define MAX_MODES 8
|
||||
#define MODE_BITS 3
|
||||
#define MODE_METHODS 8
|
||||
#define MODE_METHOD_BITS 3
|
||||
|
||||
/* Different key frame types/methods */
|
||||
#define DCT_KEY_FRAME 0
|
||||
|
||||
#define KEY_FRAME_CONTEXT 5
|
||||
|
||||
/* Preprocessor defines */
|
||||
#define MAX_PREV_FRAMES 16
|
||||
|
||||
/* Number of search sites for a 4-step search (at pixel accuracy) */
|
||||
#define MAX_SEARCH_SITES 33
|
||||
|
||||
#define VERY_BEST_Q 10
|
||||
#define MIN_BPB_FACTOR 0.3
|
||||
#define MAX_BPB_FACTOR 3.0
|
||||
|
||||
#define MAX_MV_EXTENT 31 /* Max search distance in half pixel increments */
|
||||
|
||||
typedef struct CONFIG_TYPE2{
|
||||
double OutputFrameRate;
|
||||
ogg_uint32_t TargetBandwidth;
|
||||
ogg_uint32_t KeyFrameDataTarget ; /* Data rate target for key frames */
|
||||
|
||||
ogg_uint32_t FirstFrameQ;
|
||||
ogg_uint32_t BaseQ;
|
||||
ogg_uint32_t MaxQ; /* Absolute Max Q allowed. */
|
||||
ogg_uint32_t ActiveMaxQ; /* Currently active Max Q */
|
||||
|
||||
} CONFIG_TYPE2;
|
||||
|
||||
typedef struct coeffNode{
|
||||
int i;
|
||||
struct coeffNode *next;
|
||||
} COEFFNODE;
|
||||
|
||||
typedef struct{
|
||||
unsigned char * Yuv0ptr;
|
||||
unsigned char * Yuv1ptr;
|
||||
unsigned char * SrfWorkSpcPtr;
|
||||
unsigned char * disp_fragments;
|
||||
|
||||
ogg_uint32_t * RegionIndex; /* Gives pixel index for top left of
|
||||
each block */
|
||||
ogg_uint32_t VideoFrameHeight;
|
||||
ogg_uint32_t VideoFrameWidth;
|
||||
|
||||
} SCAN_CONFIG_DATA;
|
||||
|
||||
typedef unsigned char YUV_BUFFER_ENTRY;
|
||||
|
||||
typedef struct{
|
||||
ogg_int32_t x;
|
||||
ogg_int32_t y;
|
||||
} MOTION_VECTOR;
|
||||
|
||||
typedef MOTION_VECTOR COORDINATE;
|
||||
|
||||
typedef ogg_int16_t Q_LIST_ENTRY;
|
||||
|
||||
typedef struct PP_INSTANCE {
|
||||
ogg_uint32_t PrevFrameLimit;
|
||||
|
||||
ogg_uint32_t *ScanPixelIndexTable;
|
||||
signed char *ScanDisplayFragments;
|
||||
|
||||
signed char *PrevFragments[MAX_PREV_FRAMES];
|
||||
|
||||
ogg_uint32_t *FragScores; /* The individual frame difference ratings. */
|
||||
signed char *SameGreyDirPixels;
|
||||
signed char *BarBlockMap;
|
||||
|
||||
/* Number of pixels changed by diff threshold in row of a fragment. */
|
||||
unsigned char *FragDiffPixels;
|
||||
|
||||
unsigned char *PixelScores;
|
||||
unsigned char *PixelChangedMap;
|
||||
unsigned char *ChLocals;
|
||||
ogg_int16_t *yuv_differences;
|
||||
ogg_int32_t *RowChangedPixels;
|
||||
signed char *TmpCodedMap;
|
||||
|
||||
/* Plane pointers and dimension variables */
|
||||
unsigned char * YPlanePtr0;
|
||||
unsigned char * YPlanePtr1;
|
||||
unsigned char * UPlanePtr0;
|
||||
unsigned char * UPlanePtr1;
|
||||
unsigned char * VPlanePtr0;
|
||||
unsigned char * VPlanePtr1;
|
||||
|
||||
ogg_uint32_t VideoYPlaneWidth;
|
||||
ogg_uint32_t VideoYPlaneHeight;
|
||||
ogg_uint32_t VideoUVPlaneWidth;
|
||||
ogg_uint32_t VideoUVPlaneHeight;
|
||||
|
||||
ogg_uint32_t VideoYPlaneStride;
|
||||
ogg_uint32_t VideoUPlaneStride;
|
||||
ogg_uint32_t VideoVPlaneStride;
|
||||
|
||||
/* Scan control variables. */
|
||||
unsigned char HFragPixels;
|
||||
unsigned char VFragPixels;
|
||||
|
||||
ogg_uint32_t ScanFrameFragments;
|
||||
ogg_uint32_t ScanYPlaneFragments;
|
||||
ogg_uint32_t ScanUVPlaneFragments;
|
||||
ogg_uint32_t ScanHFragments;
|
||||
ogg_uint32_t ScanVFragments;
|
||||
|
||||
ogg_uint32_t YFramePixels;
|
||||
ogg_uint32_t UVFramePixels;
|
||||
|
||||
ogg_uint32_t SgcThresh;
|
||||
|
||||
ogg_uint32_t OutputBlocksUpdated;
|
||||
ogg_uint32_t KFIndicator;
|
||||
|
||||
/* The pre-processor scan configuration. */
|
||||
SCAN_CONFIG_DATA ScanConfig;
|
||||
|
||||
ogg_int32_t SRFGreyThresh;
|
||||
ogg_int32_t SRFColThresh;
|
||||
ogg_int32_t SgcLevelThresh;
|
||||
ogg_int32_t SuvcLevelThresh;
|
||||
|
||||
ogg_uint32_t NoiseSupLevel;
|
||||
|
||||
/* Block Thresholds. */
|
||||
ogg_uint32_t PrimaryBlockThreshold;
|
||||
unsigned char LineSearchTripTresh;
|
||||
|
||||
int PAKEnabled;
|
||||
|
||||
int LevelThresh;
|
||||
int NegLevelThresh;
|
||||
int SrfThresh;
|
||||
int NegSrfThresh;
|
||||
int HighChange;
|
||||
int NegHighChange;
|
||||
|
||||
/* Threshold lookup tables */
|
||||
unsigned char SrfPakThreshTable[512];
|
||||
unsigned char SrfThreshTable[512];
|
||||
unsigned char SgcThreshTable[512];
|
||||
|
||||
/* Variables controlling S.A.D. break outs. */
|
||||
ogg_uint32_t GrpLowSadThresh;
|
||||
ogg_uint32_t GrpHighSadThresh;
|
||||
ogg_uint32_t ModifiedGrpLowSadThresh;
|
||||
ogg_uint32_t ModifiedGrpHighSadThresh;
|
||||
|
||||
ogg_int32_t PlaneHFragments;
|
||||
ogg_int32_t PlaneVFragments;
|
||||
ogg_int32_t PlaneHeight;
|
||||
ogg_int32_t PlaneWidth;
|
||||
ogg_int32_t PlaneStride;
|
||||
|
||||
ogg_uint32_t BlockThreshold;
|
||||
ogg_uint32_t BlockSgcThresh;
|
||||
double UVBlockThreshCorrection;
|
||||
double UVSgcCorrection;
|
||||
|
||||
double YUVPlaneCorrectionFactor;
|
||||
double AbsDiff_ScoreMultiplierTable[256];
|
||||
unsigned char NoiseScoreBoostTable[256];
|
||||
unsigned char MaxLineSearchLen;
|
||||
|
||||
ogg_int32_t YuvDiffsCircularBufferSize;
|
||||
ogg_int32_t ChLocalsCircularBufferSize;
|
||||
ogg_int32_t PixelMapCircularBufferSize;
|
||||
|
||||
} PP_INSTANCE;
|
||||
|
||||
|
||||
typedef enum{
|
||||
CODE_INTER_NO_MV = 0x0, /* INTER prediction, (0,0) motion
|
||||
vector implied. */
|
||||
CODE_INTRA = 0x1, /* INTRA i.e. no prediction. */
|
||||
CODE_INTER_PLUS_MV = 0x2, /* INTER prediction, non zero motion
|
||||
vector. */
|
||||
CODE_INTER_LAST_MV = 0x3, /* Use Last Motion vector */
|
||||
CODE_INTER_PRIOR_LAST = 0x4, /* Prior last motion vector */
|
||||
CODE_USING_GOLDEN = 0x5, /* 'Golden frame' prediction (no MV). */
|
||||
CODE_GOLDEN_MV = 0x6, /* 'Golden frame' prediction plus MV. */
|
||||
CODE_INTER_FOURMV = 0x7 /* Inter prediction 4MV per macro block. */
|
||||
} CODING_MODE;
|
||||
|
||||
typedef struct HUFF_ENTRY {
|
||||
struct HUFF_ENTRY *ZeroChild;
|
||||
struct HUFF_ENTRY *OneChild;
|
||||
struct HUFF_ENTRY *Previous;
|
||||
struct HUFF_ENTRY *Next;
|
||||
ogg_int32_t Value;
|
||||
ogg_uint32_t Frequency;
|
||||
|
||||
} HUFF_ENTRY;
|
||||
|
||||
typedef struct codec_setup_info {
|
||||
ogg_uint32_t QThreshTable[Q_TABLE_SIZE];
|
||||
Q_LIST_ENTRY DcScaleFactorTable[Q_TABLE_SIZE];
|
||||
Q_LIST_ENTRY Y_coeffs[64];
|
||||
Q_LIST_ENTRY UV_coeffs[64];
|
||||
Q_LIST_ENTRY Inter_coeffs[64];
|
||||
|
||||
HUFF_ENTRY *HuffRoot[NUM_HUFF_TABLES];
|
||||
} codec_setup_info;
|
||||
|
||||
typedef struct PB_INSTANCE {
|
||||
oggpack_buffer *opb;
|
||||
theora_info info;
|
||||
/* how far do we shift the granulepos to seperate out P frame counts? */
|
||||
int keyframe_granule_shift;
|
||||
|
||||
|
||||
/***********************************************************************/
|
||||
/* Decoder and Frame Type Information */
|
||||
|
||||
int DecoderErrorCode;
|
||||
int FramesHaveBeenSkipped;
|
||||
|
||||
int PostProcessEnabled;
|
||||
ogg_uint32_t PostProcessingLevel; /* Perform post processing */
|
||||
|
||||
/* Frame Info */
|
||||
CODING_MODE CodingMode;
|
||||
unsigned char FrameType;
|
||||
unsigned char KeyFrameType;
|
||||
ogg_uint32_t QualitySetting;
|
||||
ogg_uint32_t FrameQIndex; /* Quality specified as a
|
||||
table index */
|
||||
ogg_uint32_t ThisFrameQualityValue; /* Quality value for this frame */
|
||||
ogg_uint32_t LastFrameQualityValue; /* Last Frame's Quality */
|
||||
ogg_int32_t CodedBlockIndex; /* Number of Coded Blocks */
|
||||
ogg_uint32_t CodedBlocksThisFrame; /* Index into coded blocks */
|
||||
ogg_uint32_t FrameSize; /* The number of bytes in the frame. */
|
||||
|
||||
/**********************************************************************/
|
||||
/* Frame Size & Index Information */
|
||||
|
||||
ogg_uint32_t YPlaneSize;
|
||||
ogg_uint32_t UVPlaneSize;
|
||||
ogg_uint32_t YStride;
|
||||
ogg_uint32_t UVStride;
|
||||
ogg_uint32_t VFragments;
|
||||
ogg_uint32_t HFragments;
|
||||
ogg_uint32_t UnitFragments;
|
||||
ogg_uint32_t YPlaneFragments;
|
||||
ogg_uint32_t UVPlaneFragments;
|
||||
|
||||
ogg_uint32_t ReconYPlaneSize;
|
||||
ogg_uint32_t ReconUVPlaneSize;
|
||||
|
||||
ogg_uint32_t YDataOffset;
|
||||
ogg_uint32_t UDataOffset;
|
||||
ogg_uint32_t VDataOffset;
|
||||
ogg_uint32_t ReconYDataOffset;
|
||||
ogg_uint32_t ReconUDataOffset;
|
||||
ogg_uint32_t ReconVDataOffset;
|
||||
ogg_uint32_t YSuperBlocks; /* Number of SuperBlocks in a Y frame */
|
||||
ogg_uint32_t UVSuperBlocks; /* Number of SuperBlocks in a U or V frame */
|
||||
ogg_uint32_t SuperBlocks; /* Total number of SuperBlocks in a
|
||||
Y,U,V frame */
|
||||
|
||||
ogg_uint32_t YSBRows; /* Number of rows of SuperBlocks in a
|
||||
Y frame */
|
||||
ogg_uint32_t YSBCols; /* Number of cols of SuperBlocks in a
|
||||
Y frame */
|
||||
ogg_uint32_t UVSBRows; /* Number of rows of SuperBlocks in a
|
||||
U or V frame */
|
||||
ogg_uint32_t UVSBCols; /* Number of cols of SuperBlocks in a
|
||||
U or V frame */
|
||||
|
||||
ogg_uint32_t YMacroBlocks; /* Number of Macro-Blocks in Y component */
|
||||
ogg_uint32_t UVMacroBlocks; /* Number of Macro-Blocks in U/V component */
|
||||
ogg_uint32_t MacroBlocks; /* Total number of Macro-Blocks */
|
||||
|
||||
/**********************************************************************/
|
||||
/* Frames */
|
||||
YUV_BUFFER_ENTRY *ThisFrameRecon;
|
||||
YUV_BUFFER_ENTRY *GoldenFrame;
|
||||
YUV_BUFFER_ENTRY *LastFrameRecon;
|
||||
YUV_BUFFER_ENTRY *PostProcessBuffer;
|
||||
|
||||
/**********************************************************************/
|
||||
/* Fragment Information */
|
||||
ogg_uint32_t *pixel_index_table; /* start address of first
|
||||
pixel of fragment in
|
||||
source */
|
||||
ogg_uint32_t *recon_pixel_index_table; /* start address of first
|
||||
pixel in recon buffer */
|
||||
|
||||
unsigned char *display_fragments; /* Fragment update map */
|
||||
unsigned char *skipped_display_fragments;/* whether fragment YUV
|
||||
Conversion and update is to be
|
||||
skipped */
|
||||
ogg_int32_t *CodedBlockList; /* A list of fragment indices for
|
||||
coded blocks. */
|
||||
MOTION_VECTOR *FragMVect; /* fragment motion vectors */
|
||||
|
||||
ogg_uint32_t *FragTokenCounts; /* Number of tokens per fragment */
|
||||
ogg_uint32_t (*TokenList)[128]; /* Fragment Token Pointers */
|
||||
|
||||
ogg_int32_t *FragmentVariances;
|
||||
ogg_uint32_t *FragQIndex; /* Fragment Quality used in
|
||||
PostProcess */
|
||||
Q_LIST_ENTRY (*PPCoefBuffer)[64]; /* PostProcess Buffer for
|
||||
coefficients data */
|
||||
|
||||
unsigned char *FragCoeffs; /* # of coeffs decoded so far for
|
||||
fragment */
|
||||
unsigned char *FragCoefEOB; /* Position of last non 0 coef
|
||||
within QFragData */
|
||||
Q_LIST_ENTRY (*QFragData)[64]; /* Fragment Coefficients
|
||||
Array Pointers */
|
||||
CODING_MODE *FragCodingMethod; /* coding method for the
|
||||
fragment */
|
||||
|
||||
/***********************************************************************/
|
||||
/* pointers to addresses used for allocation and deallocation the
|
||||
others are rounded up to the nearest 32 bytes */
|
||||
|
||||
COEFFNODE *_Nodes;
|
||||
ogg_uint32_t *transIndex; /* ptr to table of
|
||||
transposed indexes */
|
||||
|
||||
/***********************************************************************/
|
||||
ogg_int32_t bumpLast;
|
||||
|
||||
/* Macro Block and SuperBlock Information */
|
||||
ogg_int32_t (*BlockMap)[4][4]; /* super block + sub macro
|
||||
block + sub frag ->
|
||||
FragIndex */
|
||||
|
||||
/* Coded flag arrays and counters for them */
|
||||
unsigned char *SBCodedFlags;
|
||||
unsigned char *SBFullyFlags;
|
||||
unsigned char *MBCodedFlags;
|
||||
unsigned char *MBFullyFlags;
|
||||
|
||||
/**********************************************************************/
|
||||
ogg_uint32_t EOB_Run;
|
||||
|
||||
COORDINATE *FragCoordinates;
|
||||
MOTION_VECTOR MVector;
|
||||
ogg_int32_t ReconPtr2Offset; /* Offset for second reconstruction
|
||||
in half pixel MC */
|
||||
Q_LIST_ENTRY *quantized_list;
|
||||
ogg_int16_t *ReconDataBuffer;
|
||||
Q_LIST_ENTRY InvLastIntraDC;
|
||||
Q_LIST_ENTRY InvLastInterDC;
|
||||
Q_LIST_ENTRY LastIntraDC;
|
||||
Q_LIST_ENTRY LastInterDC;
|
||||
|
||||
ogg_uint32_t BlocksToDecode; /* Blocks to be decoded this frame */
|
||||
ogg_uint32_t DcHuffChoice; /* Huffman table selection variables */
|
||||
unsigned char ACHuffChoice;
|
||||
ogg_uint32_t QuadMBListIndex;
|
||||
|
||||
ogg_int32_t ByteCount;
|
||||
|
||||
ogg_uint32_t bit_pattern;
|
||||
unsigned char bits_so_far;
|
||||
unsigned char NextBit;
|
||||
ogg_int32_t BitsLeft;
|
||||
|
||||
ogg_int16_t *DequantBuffer;
|
||||
|
||||
ogg_int32_t fp_quant_InterUV_coeffs[64];
|
||||
ogg_int32_t fp_quant_InterUV_round[64];
|
||||
ogg_int32_t fp_ZeroBinSize_InterUV[64];
|
||||
|
||||
ogg_int16_t *TmpReconBuffer;
|
||||
ogg_int16_t *TmpDataBuffer;
|
||||
|
||||
/* Loop filter bounding values */
|
||||
ogg_int32_t FiltBoundingValue[512];
|
||||
|
||||
/* Dequantiser and rounding tables */
|
||||
ogg_uint32_t QThreshTable[Q_TABLE_SIZE];
|
||||
Q_LIST_ENTRY DcScaleFactorTable[Q_TABLE_SIZE];
|
||||
Q_LIST_ENTRY Y_coeffs[64];
|
||||
Q_LIST_ENTRY UV_coeffs[64];
|
||||
Q_LIST_ENTRY Inter_coeffs[64];
|
||||
Q_LIST_ENTRY *dequant_InterUV_coeffs;
|
||||
unsigned int quant_index[64];
|
||||
ogg_int32_t quant_Y_coeffs[64];
|
||||
ogg_int32_t quant_UV_coeffs[64];
|
||||
ogg_int32_t fp_quant_Y_coeffs[64]; /* used in reiniting quantizers */
|
||||
|
||||
HUFF_ENTRY *HuffRoot_VP3x[NUM_HUFF_TABLES];
|
||||
ogg_uint32_t *HuffCodeArray_VP3x[NUM_HUFF_TABLES];
|
||||
unsigned char *HuffCodeLengthArray_VP3x[NUM_HUFF_TABLES];
|
||||
unsigned char *ExtraBitLengths_VP3x;
|
||||
|
||||
/* Quantiser and rounding tables */
|
||||
ogg_int32_t fp_quant_UV_coeffs[64];
|
||||
ogg_int32_t fp_quant_Inter_coeffs[64];
|
||||
ogg_int32_t fp_quant_Y_round[64];
|
||||
ogg_int32_t fp_quant_UV_round[64];
|
||||
ogg_int32_t fp_quant_Inter_round[64];
|
||||
ogg_int32_t fp_ZeroBinSize_Y[64];
|
||||
ogg_int32_t fp_ZeroBinSize_UV[64];
|
||||
ogg_int32_t fp_ZeroBinSize_Inter[64];
|
||||
ogg_int32_t *fquant_coeffs;
|
||||
ogg_int32_t *fquant_round;
|
||||
ogg_int32_t *fquant_ZbSize;
|
||||
Q_LIST_ENTRY *dequant_Y_coeffs;
|
||||
Q_LIST_ENTRY *dequant_UV_coeffs;
|
||||
Q_LIST_ENTRY *dequant_Inter_coeffs;
|
||||
Q_LIST_ENTRY *dequant_coeffs;
|
||||
|
||||
/* Predictor used in choosing entropy table for decoding block patterns. */
|
||||
unsigned char BlockPatternPredictor;
|
||||
|
||||
short Modifier[4][512];
|
||||
short *ModifierPointer[4];
|
||||
|
||||
unsigned char *DataOutputInPtr;
|
||||
|
||||
|
||||
} PB_INSTANCE;
|
||||
|
||||
typedef struct CP_INSTANCE {
|
||||
|
||||
/* Compressor Configuration */
|
||||
SCAN_CONFIG_DATA ScanConfig;
|
||||
CONFIG_TYPE2 Configuration;
|
||||
int GoldenFrameEnabled;
|
||||
int InterPrediction;
|
||||
int MotionCompensation;
|
||||
|
||||
ogg_uint32_t LastKeyFrame ;
|
||||
ogg_int32_t DropCount ;
|
||||
ogg_int32_t MaxConsDroppedFrames ;
|
||||
ogg_int32_t DropFrameTriggerBytes;
|
||||
int DropFrameCandidate;
|
||||
|
||||
/* Compressor Statistics */
|
||||
double TotErrScore;
|
||||
ogg_int64_t KeyFrameCount; /* Count of key frames. */
|
||||
ogg_int64_t TotKeyFrameBytes;
|
||||
ogg_uint32_t LastKeyFrameSize;
|
||||
ogg_uint32_t PriorKeyFrameSize[KEY_FRAME_CONTEXT];
|
||||
ogg_uint32_t PriorKeyFrameDistance[KEY_FRAME_CONTEXT];
|
||||
ogg_int32_t FrameQuality[6];
|
||||
int DecoderErrorCode; /* Decoder error flag. */
|
||||
ogg_int32_t ThreshMapThreshold;
|
||||
ogg_int32_t TotalMotionScore;
|
||||
ogg_int64_t TotalByteCount;
|
||||
ogg_int32_t FixedQ;
|
||||
|
||||
/* Frame Statistics */
|
||||
signed char InterCodeCount;
|
||||
ogg_int64_t CurrentFrame;
|
||||
ogg_int64_t CarryOver ;
|
||||
ogg_uint32_t LastFrameSize;
|
||||
ogg_uint32_t FrameBitCount;
|
||||
int ThisIsFirstFrame;
|
||||
int ThisIsKeyFrame;
|
||||
|
||||
ogg_int32_t MotionScore;
|
||||
ogg_uint32_t RegulationBlocks;
|
||||
ogg_int32_t RecoveryMotionScore;
|
||||
int RecoveryBlocksAdded ;
|
||||
double ProportionRecBlocks;
|
||||
double MaxRecFactor ;
|
||||
|
||||
/* Rate Targeting variables. */
|
||||
ogg_uint32_t ThisFrameTargetBytes;
|
||||
double BpbCorrectionFactor;
|
||||
|
||||
/* Up regulation variables */
|
||||
ogg_uint32_t FinalPassLastPos; /* Used to regulate a final
|
||||
unrestricted high quality
|
||||
pass. */
|
||||
ogg_uint32_t LastEndSB; /* Where we were in the loop
|
||||
last time. */
|
||||
ogg_uint32_t ResidueLastEndSB; /* Where we were in the residue
|
||||
update loop last time. */
|
||||
|
||||
/* Controlling Block Selection */
|
||||
ogg_uint32_t MVChangeFactor;
|
||||
ogg_uint32_t FourMvChangeFactor;
|
||||
ogg_uint32_t MinImprovementForNewMV;
|
||||
ogg_uint32_t ExhaustiveSearchThresh;
|
||||
ogg_uint32_t MinImprovementForFourMV;
|
||||
ogg_uint32_t FourMVThreshold;
|
||||
|
||||
/* Module shared data structures. */
|
||||
ogg_int32_t frame_target_rate;
|
||||
ogg_int32_t BaseLineFrameTargetRate;
|
||||
ogg_int32_t min_blocks_per_frame;
|
||||
ogg_uint32_t tot_bytes_old;
|
||||
|
||||
/*********************************************************************/
|
||||
/* Frames Used in the selecetive convolution filtering of the Y plane. */
|
||||
unsigned char *ConvDestBuffer;
|
||||
YUV_BUFFER_ENTRY *yuv0ptr;
|
||||
YUV_BUFFER_ENTRY *yuv1ptr;
|
||||
/*********************************************************************/
|
||||
|
||||
/*********************************************************************/
|
||||
/* Token Buffers */
|
||||
ogg_uint32_t *OptimisedTokenListEb; /* Optimised token list extra bits */
|
||||
unsigned char *OptimisedTokenList; /* Optimised token list. */
|
||||
unsigned char *OptimisedTokenListHi; /* Optimised token list huffman
|
||||
table index */
|
||||
|
||||
unsigned char *OptimisedTokenListPl; /* Plane to which the token
|
||||
belongs Y = 0 or UV = 1 */
|
||||
ogg_int32_t OptimisedTokenCount; /* Count of Optimized tokens */
|
||||
ogg_uint32_t RunHuffIndex; /* Huffman table in force at
|
||||
the start of a run */
|
||||
ogg_uint32_t RunPlaneIndex; /* The plane (Y=0 UV=1) to
|
||||
which the first token in
|
||||
an EOB run belonged. */
|
||||
|
||||
|
||||
ogg_uint32_t TotTokenCount;
|
||||
ogg_int32_t TokensToBeCoded;
|
||||
ogg_int32_t TokensCoded;
|
||||
/********************************************************************/
|
||||
|
||||
/* SuperBlock, MacroBLock and Fragment Information */
|
||||
/* Coded flag arrays and counters for them */
|
||||
unsigned char *PartiallyCodedFlags;
|
||||
unsigned char *PartiallyCodedMbPatterns;
|
||||
unsigned char *UncodedMbFlags;
|
||||
|
||||
unsigned char *extra_fragments; /* extra updates not
|
||||
recommended by pre-processor */
|
||||
ogg_int16_t *OriginalDC;
|
||||
|
||||
ogg_uint32_t *FragmentLastQ; /* Array used to keep track of
|
||||
quality at which each
|
||||
fragment was last
|
||||
updated. */
|
||||
unsigned char *FragTokens;
|
||||
ogg_uint32_t *FragTokenCounts; /* Number of tokens per fragment */
|
||||
|
||||
ogg_uint32_t *RunHuffIndices;
|
||||
ogg_uint32_t *LastCodedErrorScore;
|
||||
ogg_uint32_t *ModeList;
|
||||
MOTION_VECTOR *MVList;
|
||||
|
||||
unsigned char *BlockCodedFlags;
|
||||
|
||||
ogg_uint32_t MvListCount;
|
||||
ogg_uint32_t ModeListCount;
|
||||
|
||||
|
||||
unsigned char *DataOutputBuffer;
|
||||
/*********************************************************************/
|
||||
|
||||
ogg_uint32_t RunLength;
|
||||
ogg_uint32_t MaxBitTarget; /* Cut off target for rate capping */
|
||||
double BitRateCapFactor; /* Factor relating normal frame target
|
||||
to cut off target. */
|
||||
|
||||
unsigned char MBCodingMode; /* Coding mode flags */
|
||||
|
||||
ogg_int32_t MVPixelOffsetY[MAX_SEARCH_SITES];
|
||||
ogg_uint32_t InterTripOutThresh;
|
||||
unsigned char MVEnabled;
|
||||
ogg_uint32_t MotionVectorSearchCount;
|
||||
ogg_uint32_t FrameMVSearcOunt;
|
||||
ogg_int32_t MVSearchSteps;
|
||||
ogg_int32_t MVOffsetX[MAX_SEARCH_SITES];
|
||||
ogg_int32_t MVOffsetY[MAX_SEARCH_SITES];
|
||||
ogg_int32_t HalfPixelRef2Offset[9]; /* Offsets for half pixel
|
||||
compensation */
|
||||
signed char HalfPixelXOffset[9]; /* Half pixel MV offsets for X */
|
||||
signed char HalfPixelYOffset[9]; /* Half pixel MV offsets for Y */
|
||||
|
||||
ogg_uint32_t bit_pattern ;
|
||||
unsigned char bits_so_far ;
|
||||
ogg_uint32_t lastval ;
|
||||
ogg_uint32_t lastrun ;
|
||||
|
||||
Q_LIST_ENTRY *quantized_list;
|
||||
|
||||
MOTION_VECTOR MVector;
|
||||
ogg_uint32_t TempBitCount;
|
||||
ogg_int16_t *DCT_codes; /* Buffer that stores the result of
|
||||
Forward DCT */
|
||||
ogg_int16_t *DCTDataBuffer; /* Input data buffer for Forward DCT */
|
||||
|
||||
/* Motion compensation related variables */
|
||||
ogg_uint32_t MvMaxExtent;
|
||||
|
||||
double QTargetModifier[Q_TABLE_SIZE];
|
||||
|
||||
/* instances (used for reconstructing buffers and to hold tokens etc.) */
|
||||
PP_INSTANCE pp; /* preprocessor */
|
||||
PB_INSTANCE pb; /* playback */
|
||||
|
||||
/* ogg bitpacker for use in packet coding, other API state */
|
||||
oggpack_buffer *oggbuffer;
|
||||
#ifdef LIBOGG2 /* Remember, this is just until we drop libogg1 */
|
||||
ogg_buffer_state *oggbufferstate;
|
||||
#endif
|
||||
int readyflag;
|
||||
int packetflag;
|
||||
int doneflag;
|
||||
|
||||
} CP_INSTANCE;
|
||||
|
||||
#define clamp255(x) ((unsigned char)((((x)<0)-1) & ((x) | -((x)>255))))
|
||||
|
||||
extern void ConfigurePP( PP_INSTANCE *ppi, int Level ) ;
|
||||
extern ogg_uint32_t YUVAnalyseFrame( PP_INSTANCE *ppi,
|
||||
ogg_uint32_t * KFIndicator );
|
||||
|
||||
extern void ClearPPInstance(PP_INSTANCE *ppi);
|
||||
extern void InitPPInstance(PP_INSTANCE *ppi);
|
||||
extern int GetFrameType(PB_INSTANCE *pbi);
|
||||
extern void InitPBInstance(PB_INSTANCE *pbi);
|
||||
extern void ClearPBInstance(PB_INSTANCE *pbi);
|
||||
|
||||
|
||||
extern void IDctSlow( Q_LIST_ENTRY * InputData,
|
||||
ogg_int16_t *QuantMatrix,
|
||||
ogg_int16_t * OutputData ) ;
|
||||
|
||||
extern void IDct10( Q_LIST_ENTRY * InputData,
|
||||
ogg_int16_t *QuantMatrix,
|
||||
ogg_int16_t * OutputData );
|
||||
|
||||
extern void IDct1( Q_LIST_ENTRY * InputData,
|
||||
ogg_int16_t *QuantMatrix,
|
||||
ogg_int16_t * OutputData );
|
||||
|
||||
extern void ReconIntra( PB_INSTANCE *pbi, unsigned char * ReconPtr,
|
||||
ogg_int16_t * ChangePtr, ogg_uint32_t LineStep );
|
||||
|
||||
extern void ReconInter( PB_INSTANCE *pbi, unsigned char * ReconPtr,
|
||||
unsigned char * RefPtr, ogg_int16_t * ChangePtr,
|
||||
ogg_uint32_t LineStep ) ;
|
||||
|
||||
extern void ReconInterHalfPixel2( PB_INSTANCE *pbi, unsigned char * ReconPtr,
|
||||
unsigned char * RefPtr1,
|
||||
unsigned char * RefPtr2,
|
||||
ogg_int16_t * ChangePtr,
|
||||
ogg_uint32_t LineStep ) ;
|
||||
|
||||
extern void SetupLoopFilter(PB_INSTANCE *pbi);
|
||||
extern void CopyBlock(unsigned char *src,
|
||||
unsigned char *dest,
|
||||
unsigned int srcstride);
|
||||
extern void LoopFilter(PB_INSTANCE *pbi);
|
||||
extern void ReconRefFrames (PB_INSTANCE *pbi);
|
||||
extern void ExpandToken( Q_LIST_ENTRY * ExpandedBlock,
|
||||
unsigned char * CoeffIndex, ogg_uint32_t Token,
|
||||
ogg_int32_t ExtraBits );
|
||||
extern void ClearDownQFragData(PB_INSTANCE *pbi);
|
||||
extern void select_Y_quantiser ( PB_INSTANCE *pbi );
|
||||
extern void select_Inter_quantiser ( PB_INSTANCE *pbi );
|
||||
extern void select_UV_quantiser ( PB_INSTANCE *pbi );
|
||||
extern void select_InterUV_quantiser ( PB_INSTANCE *pbi );
|
||||
extern void quantize( PB_INSTANCE *pbi,
|
||||
ogg_int16_t * DCT_block,
|
||||
Q_LIST_ENTRY * quantized_list);
|
||||
extern void UpdateQ( PB_INSTANCE *pbi, ogg_uint32_t NewQ );
|
||||
extern void UpdateQC( CP_INSTANCE *cpi, ogg_uint32_t NewQ );
|
||||
extern void fdct_short ( ogg_int16_t * InputData, ogg_int16_t * OutputData );
|
||||
extern ogg_uint32_t DPCMTokenizeBlock (CP_INSTANCE *cpi,
|
||||
ogg_int32_t FragIndex);
|
||||
extern void TransformQuantizeBlock (CP_INSTANCE *cpi, ogg_int32_t FragIndex,
|
||||
ogg_uint32_t PixelsPerLine ) ;
|
||||
extern void ClearFragmentInfo(PB_INSTANCE * pbi);
|
||||
extern void InitFragmentInfo(PB_INSTANCE * pbi);
|
||||
extern void ClearFrameInfo(PB_INSTANCE * pbi);
|
||||
extern void InitFrameInfo(PB_INSTANCE * pbi, unsigned int FrameSize);
|
||||
extern void InitializeFragCoordinates(PB_INSTANCE *pbi);
|
||||
extern void InitFrameDetails(PB_INSTANCE *pbi);
|
||||
extern void WriteQTables(PB_INSTANCE *pbi,oggpack_buffer *opb);
|
||||
extern int ReadQTables(codec_setup_info *ci,oggpack_buffer* opb);
|
||||
extern void CopyQTables(PB_INSTANCE *pbi, codec_setup_info *ci);
|
||||
extern void InitQTables( PB_INSTANCE *pbi );
|
||||
extern void InitHuffmanSet( PB_INSTANCE *pbi );
|
||||
extern void ClearHuffmanSet( PB_INSTANCE *pbi );
|
||||
extern int ReadHuffmanTrees(codec_setup_info *ci, oggpack_buffer *opb);
|
||||
extern void WriteHuffmanTrees(HUFF_ENTRY *HuffRoot[NUM_HUFF_TABLES],
|
||||
oggpack_buffer *opb);
|
||||
extern void InitHuffmanTrees(PB_INSTANCE *pbi, const codec_setup_info *ci);
|
||||
extern void ClearHuffmanTrees(HUFF_ENTRY *HuffRoot[NUM_HUFF_TABLES]);
|
||||
extern void QuadDecodeDisplayFragments ( PB_INSTANCE *pbi );
|
||||
extern void PackAndWriteDFArray( CP_INSTANCE *cpi );
|
||||
extern void UpdateFragQIndex(PB_INSTANCE *pbi);
|
||||
extern void PostProcess(PB_INSTANCE *pbi);
|
||||
extern void InitMotionCompensation ( CP_INSTANCE *cpi );
|
||||
extern ogg_uint32_t GetMBIntraError (CP_INSTANCE *cpi, ogg_uint32_t FragIndex,
|
||||
ogg_uint32_t PixelsPerLine ) ;
|
||||
extern ogg_uint32_t GetMBInterError (CP_INSTANCE *cpi,
|
||||
unsigned char * SrcPtr,
|
||||
unsigned char * RefPtr,
|
||||
ogg_uint32_t FragIndex,
|
||||
ogg_int32_t LastXMV,
|
||||
ogg_int32_t LastYMV,
|
||||
ogg_uint32_t PixelsPerLine ) ;
|
||||
extern void WriteFrameHeader( CP_INSTANCE *cpi) ;
|
||||
extern ogg_uint32_t GetMBMVInterError (CP_INSTANCE *cpi,
|
||||
unsigned char * RefFramePtr,
|
||||
ogg_uint32_t FragIndex,
|
||||
ogg_uint32_t PixelsPerLine,
|
||||
ogg_int32_t *MVPixelOffset,
|
||||
MOTION_VECTOR *MV );
|
||||
extern ogg_uint32_t GetMBMVExhaustiveSearch (CP_INSTANCE *cpi,
|
||||
unsigned char * RefFramePtr,
|
||||
ogg_uint32_t FragIndex,
|
||||
ogg_uint32_t PixelsPerLine,
|
||||
MOTION_VECTOR *MV );
|
||||
extern ogg_uint32_t GetFOURMVExhaustiveSearch (CP_INSTANCE *cpi,
|
||||
unsigned char * RefFramePtr,
|
||||
ogg_uint32_t FragIndex,
|
||||
ogg_uint32_t PixelsPerLine,
|
||||
MOTION_VECTOR *MV ) ;
|
||||
extern ogg_uint32_t EncodeData(CP_INSTANCE *cpi);
|
||||
extern ogg_uint32_t PickIntra( CP_INSTANCE *cpi,
|
||||
ogg_uint32_t SBRows,
|
||||
ogg_uint32_t SBCols);
|
||||
extern ogg_uint32_t PickModes(CP_INSTANCE *cpi,
|
||||
ogg_uint32_t SBRows,
|
||||
ogg_uint32_t SBCols,
|
||||
ogg_uint32_t PixelsPerLine,
|
||||
ogg_uint32_t *InterError,
|
||||
ogg_uint32_t *IntraError);
|
||||
|
||||
extern CODING_MODE FrArrayUnpackMode(PB_INSTANCE *pbi);
|
||||
extern void CreateBlockMapping ( ogg_int32_t (*BlockMap)[4][4],
|
||||
ogg_uint32_t YSuperBlocks,
|
||||
ogg_uint32_t UVSuperBlocks,
|
||||
ogg_uint32_t HFrags, ogg_uint32_t VFrags );
|
||||
extern void UpRegulateDataStream (CP_INSTANCE *cpi, ogg_uint32_t RegulationQ,
|
||||
ogg_int32_t RecoveryBlocks ) ;
|
||||
extern void RegulateQ( CP_INSTANCE *cpi, ogg_int32_t UpdateScore );
|
||||
extern void CopyBackExtraFrags(CP_INSTANCE *cpi);
|
||||
extern void UpdateUMVBorder( PB_INSTANCE *pbi,
|
||||
unsigned char * DestReconPtr );
|
||||
extern void PInitFrameInfo(PP_INSTANCE * ppi);
|
||||
extern int GetFrameType(PB_INSTANCE *pbi);
|
||||
extern void SetFrameType( PB_INSTANCE *pbi,unsigned char FrType );
|
||||
extern double GetEstimatedBpb( CP_INSTANCE *cpi, ogg_uint32_t TargetQ );
|
||||
extern void ClearTmpBuffers(PB_INSTANCE * pbi);
|
||||
extern void InitTmpBuffers(PB_INSTANCE * pbi);
|
||||
extern void ScanYUVInit( PP_INSTANCE * ppi,
|
||||
SCAN_CONFIG_DATA * ScanConfigPtr);
|
||||
extern int LoadAndDecode(PB_INSTANCE *pbi);
|
||||
#endif
|
120
src/add-ons/media/plugins/theora/libtheora/encoder_lookup.h
Normal file
120
src/add-ons/media/plugins/theora/libtheora/encoder_lookup.h
Normal file
@ -0,0 +1,120 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2003 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: simple static lookups for VP3 frame encoder
|
||||
last mod: $Id: encoder_lookup.h,v 1.1 2004/02/24 13:50:13 shatty Exp $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#include "encoder_internal.h"
|
||||
|
||||
ogg_uint32_t MvPattern[(MAX_MV_EXTENT * 2) + 1] = {
|
||||
0x000000ff, 0x000000fd, 0x000000fb, 0x000000f9,
|
||||
0x000000f7, 0x000000f5, 0x000000f3, 0x000000f1,
|
||||
0x000000ef, 0x000000ed, 0x000000eb, 0x000000e9,
|
||||
0x000000e7, 0x000000e5, 0x000000e3, 0x000000e1,
|
||||
0x0000006f, 0x0000006d, 0x0000006b, 0x00000069,
|
||||
0x00000067, 0x00000065, 0x00000063, 0x00000061,
|
||||
0x0000002f, 0x0000002d, 0x0000002b, 0x00000029,
|
||||
0x00000009, 0x00000007, 0x00000002, 0x00000000,
|
||||
0x00000001, 0x00000006, 0x00000008, 0x00000028,
|
||||
0x0000002a, 0x0000002c, 0x0000002e, 0x00000060,
|
||||
0x00000062, 0x00000064, 0x00000066, 0x00000068,
|
||||
0x0000006a, 0x0000006c, 0x0000006e, 0x000000e0,
|
||||
0x000000e2, 0x000000e4, 0x000000e6, 0x000000e8,
|
||||
0x000000ea, 0x000000ec, 0x000000ee, 0x000000f0,
|
||||
0x000000f2, 0x000000f4, 0x000000f6, 0x000000f8,
|
||||
0x000000fa, 0x000000fc, 0x000000fe,
|
||||
};
|
||||
|
||||
ogg_uint32_t MvBits[(MAX_MV_EXTENT * 2) + 1] = {
|
||||
8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8,
|
||||
7, 7, 7, 7, 7, 7, 7, 7,
|
||||
6, 6, 6, 6, 4, 4, 3, 3,
|
||||
3, 4, 4, 6, 6, 6, 6, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8,
|
||||
};
|
||||
|
||||
ogg_uint32_t MvPattern2[(MAX_MV_EXTENT * 2) + 1] = {
|
||||
0x0000003f, 0x0000003d, 0x0000003b, 0x00000039,
|
||||
0x00000037, 0x00000035, 0x00000033, 0x00000031,
|
||||
0x0000002f, 0x0000002d, 0x0000002b, 0x00000029,
|
||||
0x00000027, 0x00000025, 0x00000023, 0x00000021,
|
||||
0x0000001f, 0x0000001d, 0x0000001b, 0x00000019,
|
||||
0x00000017, 0x00000015, 0x00000013, 0x00000011,
|
||||
0x0000000f, 0x0000000d, 0x0000000b, 0x00000009,
|
||||
0x00000007, 0x00000005, 0x00000003, 0x00000000,
|
||||
0x00000002, 0x00000004, 0x00000006, 0x00000008,
|
||||
0x0000000a, 0x0000000c, 0x0000000e, 0x00000010,
|
||||
0x00000012, 0x00000014, 0x00000016, 0x00000018,
|
||||
0x0000001a, 0x0000001c, 0x0000001e, 0x00000020,
|
||||
0x00000022, 0x00000024, 0x00000026, 0x00000028,
|
||||
0x0000002a, 0x0000002c, 0x0000002e, 0x00000030,
|
||||
0x00000032, 0x00000034, 0x00000036, 0x00000038,
|
||||
0x0000003a, 0x0000003c, 0x0000003e,
|
||||
};
|
||||
|
||||
ogg_uint32_t MvBits2[(MAX_MV_EXTENT * 2) + 1] = {
|
||||
6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6,
|
||||
};
|
||||
|
||||
ogg_uint32_t ModeBitPatterns[MAX_MODES] = {
|
||||
0x00, 0x02, 0x06, 0x0E, 0x1E, 0x3E, 0x7E, 0x7F };
|
||||
|
||||
ogg_int32_t ModeBitLengths[MAX_MODES] = {
|
||||
1, 2, 3, 4, 5, 6, 7, 7 };
|
||||
|
||||
unsigned char ModeSchemes[MODE_METHODS-2][MAX_MODES] = {
|
||||
/* Last Mv dominates */
|
||||
{ 3, 4, 2, 0, 1, 5, 6, 7 }, /* L P M N I G GM 4 */
|
||||
{ 2, 4, 3, 0, 1, 5, 6, 7 }, /* L P N M I G GM 4 */
|
||||
{ 3, 4, 1, 0, 2, 5, 6, 7 }, /* L M P N I G GM 4 */
|
||||
{ 2, 4, 1, 0, 3, 5, 6, 7 }, /* L M N P I G GM 4 */
|
||||
|
||||
/* No MV dominates */
|
||||
{ 0, 4, 3, 1, 2, 5, 6, 7 }, /* N L P M I G GM 4 */
|
||||
{ 0, 5, 4, 2, 3, 1, 6, 7 }, /* N G L P M I GM 4 */
|
||||
|
||||
};
|
||||
|
||||
|
||||
ogg_uint32_t MvThreshTable[Q_TABLE_SIZE] = {
|
||||
65, 65, 65, 65, 50, 50, 50, 50,
|
||||
40, 40, 40, 40, 40, 40, 40, 40,
|
||||
30, 30, 30, 30, 30, 30, 30, 30,
|
||||
20, 20, 20, 20, 20, 20, 20, 20,
|
||||
15, 15, 15, 15, 15, 15, 15, 15,
|
||||
10, 10, 10, 10, 10, 10, 10, 10,
|
||||
5, 5, 5, 5, 5, 5, 5, 5,
|
||||
0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
ogg_uint32_t MVChangeFactorTable[Q_TABLE_SIZE] = {
|
||||
11, 11, 11, 11, 12, 12, 12, 12,
|
||||
13, 13, 13, 13, 13, 13, 13, 13,
|
||||
14, 14, 14, 14, 14, 14, 14, 14,
|
||||
14, 14, 14, 14, 14, 14, 14, 14,
|
||||
14, 14, 14, 14, 14, 14, 14, 14,
|
||||
14, 14, 14, 14, 14, 14, 14, 14,
|
||||
15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15
|
||||
};
|
614
src/add-ons/media/plugins/theora/libtheora/frarray.c
Normal file
614
src/add-ons/media/plugins/theora/libtheora/frarray.c
Normal file
@ -0,0 +1,614 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2003 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function:
|
||||
last mod: $Id: frarray.c,v 1.1 2004/02/24 13:50:13 shatty Exp $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include "encoder_internal.h"
|
||||
#include "block_inline.h"
|
||||
|
||||
static ogg_uint32_t FrArrayCodeSBRun( CP_INSTANCE *cpi, ogg_uint32_t value ){
|
||||
ogg_uint32_t CodedVal = 0;
|
||||
ogg_uint32_t CodedBits = 0;
|
||||
|
||||
/* Coding scheme:
|
||||
Codeword RunLength
|
||||
0 1
|
||||
10x 2-3
|
||||
110x 4-5
|
||||
1110xx 6-9
|
||||
11110xxx 10-17
|
||||
111110xxxx 18-33
|
||||
111111xxxxxxxxxxxx 34-4129 */
|
||||
|
||||
if ( value == 1 ){
|
||||
CodedVal = 0;
|
||||
CodedBits = 1;
|
||||
} else if ( value <= 3 ) {
|
||||
CodedVal = 0x0004 + (value - 2);
|
||||
CodedBits = 3;
|
||||
} else if ( value <= 5 ) {
|
||||
CodedVal = 0x000C + (value - 4);
|
||||
CodedBits = 4;
|
||||
} else if ( value <= 9 ) {
|
||||
CodedVal = 0x0038 + (value - 6);
|
||||
CodedBits = 6;
|
||||
} else if ( value <= 17 ) {
|
||||
CodedVal = 0x00F0 + (value - 10);
|
||||
CodedBits = 8;
|
||||
} else if ( value <= 33 ) {
|
||||
CodedVal = 0x03E0 + (value - 18);
|
||||
CodedBits = 10;
|
||||
} else {
|
||||
CodedVal = 0x3F000 + (value - 34);
|
||||
CodedBits = 18;
|
||||
}
|
||||
|
||||
/* Add the bits to the encode holding buffer. */
|
||||
oggpackB_write( cpi->oggbuffer, CodedVal, (ogg_uint32_t)CodedBits );
|
||||
|
||||
return CodedBits;
|
||||
}
|
||||
|
||||
static ogg_uint32_t FrArrayCodeBlockRun( CP_INSTANCE *cpi,
|
||||
ogg_uint32_t value ) {
|
||||
ogg_uint32_t CodedVal = 0;
|
||||
ogg_uint32_t CodedBits = 0;
|
||||
|
||||
/* Coding scheme:
|
||||
Codeword RunLength
|
||||
0x 1-2
|
||||
10x 3-4
|
||||
110x 5-6
|
||||
1110xx 7-10
|
||||
11110xx 11-14
|
||||
11111xxxx 15-30 */
|
||||
|
||||
if ( value <= 2 ) {
|
||||
CodedVal = value - 1;
|
||||
CodedBits = 2;
|
||||
} else if ( value <= 4 ) {
|
||||
CodedVal = 0x0004 + (value - 3);
|
||||
CodedBits = 3;
|
||||
|
||||
} else if ( value <= 6 ) {
|
||||
CodedVal = 0x000C + (value - 5);
|
||||
CodedBits = 4;
|
||||
|
||||
} else if ( value <= 10 ) {
|
||||
CodedVal = 0x0038 + (value - 7);
|
||||
CodedBits = 6;
|
||||
|
||||
} else if ( value <= 14 ) {
|
||||
CodedVal = 0x0078 + (value - 11);
|
||||
CodedBits = 7;
|
||||
} else {
|
||||
CodedVal = 0x01F0 + (value - 15);
|
||||
CodedBits = 9;
|
||||
}
|
||||
|
||||
/* Add the bits to the encode holding buffer. */
|
||||
oggpackB_write( cpi->oggbuffer, CodedVal, (ogg_uint32_t)CodedBits );
|
||||
|
||||
return CodedBits;
|
||||
}
|
||||
|
||||
void PackAndWriteDFArray( CP_INSTANCE *cpi ){
|
||||
ogg_uint32_t i;
|
||||
unsigned char val;
|
||||
ogg_uint32_t run_count;
|
||||
|
||||
ogg_uint32_t SB, MB, B; /* Block, MB and SB loop variables */
|
||||
ogg_uint32_t BListIndex = 0;
|
||||
ogg_uint32_t LastSbBIndex = 0;
|
||||
ogg_int32_t DfBlockIndex; /* Block index in display_fragments */
|
||||
|
||||
/* Initialise workspaces */
|
||||
memset( cpi->pb.SBFullyFlags, 1, cpi->pb.SuperBlocks);
|
||||
memset( cpi->pb.SBCodedFlags, 0, cpi->pb.SuperBlocks );
|
||||
memset( cpi->PartiallyCodedFlags, 0, cpi->pb.SuperBlocks );
|
||||
memset( cpi->BlockCodedFlags, 0, cpi->pb.UnitFragments);
|
||||
|
||||
for( SB = 0; SB < cpi->pb.SuperBlocks; SB++ ) {
|
||||
/* Check for coded blocks and macro-blocks */
|
||||
for ( MB=0; MB<4; MB++ ) {
|
||||
/* If MB in frame */
|
||||
if ( QuadMapToMBTopLeft(cpi->pb.BlockMap,SB,MB) >= 0 ) {
|
||||
for ( B=0; B<4; B++ ) {
|
||||
DfBlockIndex = QuadMapToIndex1( cpi->pb.BlockMap,SB, MB, B );
|
||||
|
||||
/* Does Block lie in frame: */
|
||||
if ( DfBlockIndex >= 0 ) {
|
||||
/* In Frame: If it is not coded then this SB is only
|
||||
partly coded.: */
|
||||
if ( cpi->pb.display_fragments[DfBlockIndex] ) {
|
||||
cpi->pb.SBCodedFlags[SB] = 1; /* SB at least partly coded */
|
||||
cpi->BlockCodedFlags[BListIndex] = 1; /* Block is coded */
|
||||
}else{
|
||||
cpi->pb.SBFullyFlags[SB] = 0; /* SB not fully coded */
|
||||
cpi->BlockCodedFlags[BListIndex] = 0; /* Block is not coded */
|
||||
}
|
||||
|
||||
BListIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Is the SB fully coded or uncoded.
|
||||
If so then backup BListIndex and MBListIndex */
|
||||
if ( cpi->pb.SBFullyFlags[SB] || !cpi->pb.SBCodedFlags[SB] ) {
|
||||
BListIndex = LastSbBIndex; /* Reset to values from previous SB */
|
||||
}else{
|
||||
cpi->PartiallyCodedFlags[SB] = 1; /* Set up list of partially
|
||||
coded SBs */
|
||||
LastSbBIndex = BListIndex;
|
||||
}
|
||||
}
|
||||
|
||||
/* Code list of partially coded Super-Block. */
|
||||
val = cpi->PartiallyCodedFlags[0];
|
||||
oggpackB_write( cpi->oggbuffer, (ogg_uint32_t)val, 1);
|
||||
i = 0;
|
||||
while ( i < cpi->pb.SuperBlocks ) {
|
||||
run_count = 0;
|
||||
while ( (i<cpi->pb.SuperBlocks) && (cpi->PartiallyCodedFlags[i]==val) ) {
|
||||
i++;
|
||||
run_count++;
|
||||
}
|
||||
|
||||
/* Code the run */
|
||||
FrArrayCodeSBRun( cpi, run_count );
|
||||
val = ( val == 0 ) ? 1 : 0;
|
||||
}
|
||||
|
||||
/* RLC Super-Block fully/not coded. */
|
||||
i = 0;
|
||||
|
||||
/* Skip partially coded blocks */
|
||||
while( (i < cpi->pb.SuperBlocks) && cpi->PartiallyCodedFlags[i] )
|
||||
i++;
|
||||
|
||||
if ( i < cpi->pb.SuperBlocks ) {
|
||||
val = cpi->pb.SBFullyFlags[i];
|
||||
oggpackB_write( cpi->oggbuffer, (ogg_uint32_t)val, 1);
|
||||
|
||||
while ( i < cpi->pb.SuperBlocks ) {
|
||||
run_count = 0;
|
||||
while ( (i < cpi->pb.SuperBlocks) && (cpi->pb.SBFullyFlags[i] == val) ) {
|
||||
i++;
|
||||
/* Skip partially coded blocks */
|
||||
while( (i < cpi->pb.SuperBlocks) && cpi->PartiallyCodedFlags[i] )
|
||||
i++;
|
||||
run_count++;
|
||||
}
|
||||
|
||||
/* Code the run */
|
||||
FrArrayCodeSBRun( cpi, run_count );
|
||||
val = ( val == 0 ) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now code the block flags */
|
||||
if ( BListIndex > 0 ) {
|
||||
/* Code the block flags start value */
|
||||
val = cpi->BlockCodedFlags[0];
|
||||
oggpackB_write( cpi->oggbuffer, (ogg_uint32_t)val, 1);
|
||||
|
||||
/* Now code the block flags. */
|
||||
for ( i = 0; i < BListIndex; ) {
|
||||
run_count = 0;
|
||||
while ( (cpi->BlockCodedFlags[i] == val) && (i < BListIndex) ) {
|
||||
i++;
|
||||
run_count++;
|
||||
}
|
||||
|
||||
FrArrayCodeBlockRun( cpi, run_count );
|
||||
val = ( val == 0 ) ? 1 : 0;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void FrArrayDeCodeInit(PB_INSTANCE *pbi){
|
||||
/* Initialise the decoding of a run. */
|
||||
pbi->bit_pattern = 0;
|
||||
pbi->bits_so_far = 0;
|
||||
}
|
||||
|
||||
static int FrArrayDeCodeBlockRun( PB_INSTANCE *pbi, ogg_uint32_t bit_value,
|
||||
ogg_int32_t * run_value ){
|
||||
int ret_val = 0;
|
||||
|
||||
/* Add in the new bit value. */
|
||||
pbi->bits_so_far++;
|
||||
pbi->bit_pattern = (pbi->bit_pattern << 1) + (bit_value & 1);
|
||||
|
||||
/* Coding scheme:
|
||||
Codeword RunLength
|
||||
0x 1-2
|
||||
10x 3-4
|
||||
110x 5-6
|
||||
1110xx 7-10
|
||||
11110xx 11-14
|
||||
11111xxxx 15-30
|
||||
*/
|
||||
|
||||
switch ( pbi->bits_so_far ){
|
||||
case 2:
|
||||
/* If bit 1 is clear */
|
||||
if ( !(pbi->bit_pattern & 0x0002) ){
|
||||
ret_val = 1;
|
||||
*run_value = (pbi->bit_pattern & 0x0001) + 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
/* If bit 1 is clear */
|
||||
if ( !(pbi->bit_pattern & 0x0002) ){
|
||||
ret_val = 1;
|
||||
*run_value = (pbi->bit_pattern & 0x0001) + 3;
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
/* If bit 1 is clear */
|
||||
if ( !(pbi->bit_pattern & 0x0002) ){
|
||||
ret_val = 1;
|
||||
*run_value = (pbi->bit_pattern & 0x0001) + 5;
|
||||
}
|
||||
break;
|
||||
|
||||
case 6:
|
||||
/* If bit 2 is clear */
|
||||
if ( !(pbi->bit_pattern & 0x0004) ){
|
||||
ret_val = 1;
|
||||
*run_value = (pbi->bit_pattern & 0x0003) + 7;
|
||||
}
|
||||
break;
|
||||
|
||||
case 7:
|
||||
/* If bit 2 is clear */
|
||||
if ( !(pbi->bit_pattern & 0x0004) ){
|
||||
ret_val = 1;
|
||||
*run_value = (pbi->bit_pattern & 0x0003) + 11;
|
||||
}
|
||||
break;
|
||||
|
||||
case 9:
|
||||
ret_val = 1;
|
||||
*run_value = (pbi->bit_pattern & 0x000F) + 15;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
static int FrArrayDeCodeSBRun (PB_INSTANCE *pbi, ogg_uint32_t bit_value,
|
||||
ogg_int32_t * run_value ){
|
||||
int ret_val = 0;
|
||||
|
||||
/* Add in the new bit value. */
|
||||
pbi->bits_so_far++;
|
||||
pbi->bit_pattern = (pbi->bit_pattern << 1) + (bit_value & 1);
|
||||
|
||||
/* Coding scheme:
|
||||
Codeword RunLength
|
||||
0 1
|
||||
10x 2-3
|
||||
110x 4-5
|
||||
1110xx 6-9
|
||||
11110xxx 10-17
|
||||
111110xxxx 18-33
|
||||
111111xxxxxxxxxxxx 34-4129
|
||||
*/
|
||||
|
||||
switch ( pbi->bits_so_far ){
|
||||
case 1:
|
||||
if ( pbi->bit_pattern == 0 ){
|
||||
ret_val = 1;
|
||||
*run_value = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
/* Bit 1 clear */
|
||||
if ( !(pbi->bit_pattern & 0x0002) ){
|
||||
ret_val = 1;
|
||||
*run_value = (pbi->bit_pattern & 0x0001) + 2;
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
/* Bit 1 clear */
|
||||
if ( !(pbi->bit_pattern & 0x0002) ){
|
||||
ret_val = 1;
|
||||
*run_value = (pbi->bit_pattern & 0x0001) + 4;
|
||||
}
|
||||
break;
|
||||
|
||||
case 6:
|
||||
/* Bit 2 clear */
|
||||
if ( !(pbi->bit_pattern & 0x0004) ){
|
||||
ret_val = 1;
|
||||
*run_value = (pbi->bit_pattern & 0x0003) + 6;
|
||||
}
|
||||
break;
|
||||
|
||||
case 8:
|
||||
/* Bit 3 clear */
|
||||
if ( !(pbi->bit_pattern & 0x0008) ){
|
||||
ret_val = 1;
|
||||
*run_value = (pbi->bit_pattern & 0x0007) + 10;
|
||||
}
|
||||
break;
|
||||
|
||||
case 10:
|
||||
/* Bit 4 clear */
|
||||
if ( !(pbi->bit_pattern & 0x0010) ){
|
||||
ret_val = 1;
|
||||
*run_value = (pbi->bit_pattern & 0x000F) + 18;
|
||||
}
|
||||
break;
|
||||
|
||||
case 18:
|
||||
ret_val = 1;
|
||||
*run_value = (pbi->bit_pattern & 0x0FFF) + 34;
|
||||
break;
|
||||
|
||||
default:
|
||||
ret_val = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
static void GetNextBInit(PB_INSTANCE *pbi){
|
||||
long ret;
|
||||
|
||||
theora_read(pbi->opb,1,&ret);
|
||||
pbi->NextBit = (unsigned char)ret;
|
||||
|
||||
/* Read run length */
|
||||
FrArrayDeCodeInit(pbi);
|
||||
do theora_read(pbi->opb,1,&ret);
|
||||
while (FrArrayDeCodeBlockRun(pbi,ret,&pbi->BitsLeft)==0);
|
||||
|
||||
}
|
||||
|
||||
static unsigned char GetNextBBit (PB_INSTANCE *pbi){
|
||||
long ret;
|
||||
if ( !pbi->BitsLeft ){
|
||||
/* Toggle the value. */
|
||||
pbi->NextBit = ( pbi->NextBit == 1 ) ? 0 : 1;
|
||||
|
||||
/* Read next run */
|
||||
FrArrayDeCodeInit(pbi);
|
||||
do theora_read(pbi->opb,1,&ret);
|
||||
while (FrArrayDeCodeBlockRun(pbi,ret,&pbi->BitsLeft)==0);
|
||||
|
||||
}
|
||||
|
||||
/* Have read a bit */
|
||||
pbi->BitsLeft--;
|
||||
|
||||
/* Return next bit value */
|
||||
return pbi->NextBit;
|
||||
}
|
||||
|
||||
static void GetNextSbInit(PB_INSTANCE *pbi){
|
||||
long ret;
|
||||
|
||||
theora_read(pbi->opb,1,&ret);
|
||||
pbi->NextBit = (unsigned char)ret;
|
||||
|
||||
/* Read run length */
|
||||
FrArrayDeCodeInit(pbi);
|
||||
do theora_read(pbi->opb,1,&ret);
|
||||
while (FrArrayDeCodeSBRun(pbi,ret,&pbi->BitsLeft)==0);
|
||||
|
||||
}
|
||||
|
||||
static unsigned char GetNextSbBit (PB_INSTANCE *pbi){
|
||||
long ret;
|
||||
|
||||
if ( !pbi->BitsLeft ){
|
||||
/* Toggle the value. */
|
||||
pbi->NextBit = ( pbi->NextBit == 1 ) ? 0 : 1;
|
||||
|
||||
/* Read next run */
|
||||
FrArrayDeCodeInit(pbi);
|
||||
do theora_read(pbi->opb,1,&ret);
|
||||
while (FrArrayDeCodeSBRun(pbi,ret,&pbi->BitsLeft)==0);
|
||||
|
||||
}
|
||||
|
||||
/* Have read a bit */
|
||||
pbi->BitsLeft--;
|
||||
|
||||
/* Return next bit value */
|
||||
return pbi->NextBit;
|
||||
}
|
||||
|
||||
void QuadDecodeDisplayFragments ( PB_INSTANCE *pbi ){
|
||||
ogg_uint32_t SB, MB, B;
|
||||
int DataToDecode;
|
||||
|
||||
ogg_int32_t dfIndex;
|
||||
ogg_uint32_t MBIndex = 0;
|
||||
|
||||
/* Reset various data structures common to key frames and inter frames. */
|
||||
pbi->CodedBlockIndex = 0;
|
||||
memset ( pbi->display_fragments, 0, pbi->UnitFragments );
|
||||
|
||||
/* For "Key frames" mark all blocks as coded and return. */
|
||||
/* Else initialise the ArrayPtr array to 0 (all blocks uncoded by default) */
|
||||
if ( GetFrameType(pbi) == BASE_FRAME ) {
|
||||
memset( pbi->SBFullyFlags, 1, pbi->SuperBlocks );
|
||||
memset( pbi->SBCodedFlags, 1, pbi->SuperBlocks );
|
||||
memset( pbi->MBCodedFlags, 0, pbi->MacroBlocks );
|
||||
}else{
|
||||
memset( pbi->SBFullyFlags, 0, pbi->SuperBlocks );
|
||||
memset( pbi->MBCodedFlags, 0, pbi->MacroBlocks );
|
||||
|
||||
/* Un-pack the list of partially coded Super-Blocks */
|
||||
GetNextSbInit(pbi);
|
||||
for( SB = 0; SB < pbi->SuperBlocks; SB++){
|
||||
pbi->SBCodedFlags[SB] = GetNextSbBit (pbi);
|
||||
}
|
||||
|
||||
/* Scan through the list of super blocks. Unless all are marked
|
||||
as partially coded we have more to do. */
|
||||
DataToDecode = 0;
|
||||
for ( SB=0; SB<pbi->SuperBlocks; SB++ ) {
|
||||
if ( !pbi->SBCodedFlags[SB] ) {
|
||||
DataToDecode = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Are there further block map bits to decode ? */
|
||||
if ( DataToDecode ) {
|
||||
/* Un-pack the Super-Block fully coded flags. */
|
||||
GetNextSbInit(pbi);
|
||||
for( SB = 0; SB < pbi->SuperBlocks; SB++) {
|
||||
/* Skip blocks already marked as partially coded */
|
||||
while( (SB < pbi->SuperBlocks) && pbi->SBCodedFlags[SB] )
|
||||
SB++;
|
||||
|
||||
if ( SB < pbi->SuperBlocks ) {
|
||||
pbi->SBFullyFlags[SB] = GetNextSbBit (pbi);
|
||||
|
||||
if ( pbi->SBFullyFlags[SB] ) /* If SB is fully coded. */
|
||||
pbi->SBCodedFlags[SB] = 1; /* Mark the SB as coded */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Scan through the list of coded super blocks. If at least one
|
||||
is marked as partially coded then we have a block list to
|
||||
decode. */
|
||||
for ( SB=0; SB<pbi->SuperBlocks; SB++ ) {
|
||||
if ( pbi->SBCodedFlags[SB] && !pbi->SBFullyFlags[SB] ) {
|
||||
/* Initialise the block list decoder. */
|
||||
GetNextBInit(pbi);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Decode the block data from the bit stream. */
|
||||
for ( SB=0; SB<pbi->SuperBlocks; SB++ ){
|
||||
for ( MB=0; MB<4; MB++ ){
|
||||
/* If MB is in the frame */
|
||||
if ( QuadMapToMBTopLeft(pbi->BlockMap, SB,MB) >= 0 ){
|
||||
/* Only read block level data if SB was fully or partially coded */
|
||||
if ( pbi->SBCodedFlags[SB] ) {
|
||||
for ( B=0; B<4; B++ ){
|
||||
/* If block is valid (in frame)... */
|
||||
dfIndex = QuadMapToIndex1( pbi->BlockMap, SB, MB, B );
|
||||
if ( dfIndex >= 0 ){
|
||||
if ( pbi->SBFullyFlags[SB] )
|
||||
pbi->display_fragments[dfIndex] = 1;
|
||||
else
|
||||
pbi->display_fragments[dfIndex] = GetNextBBit(pbi);
|
||||
|
||||
/* Create linear list of coded block indices */
|
||||
if ( pbi->display_fragments[dfIndex] ) {
|
||||
pbi->MBCodedFlags[MBIndex] = 1;
|
||||
pbi->CodedBlockList[pbi->CodedBlockIndex] = dfIndex;
|
||||
pbi->CodedBlockIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
MBIndex++;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CODING_MODE FrArrayUnpackMode(PB_INSTANCE *pbi){
|
||||
long ret;
|
||||
/* Coding scheme:
|
||||
Token Codeword Bits
|
||||
Entry 0 (most frequent) 0 1
|
||||
Entry 1 10 2
|
||||
Entry 2 110 3
|
||||
Entry 3 1110 4
|
||||
Entry 4 11110 5
|
||||
Entry 5 111110 6
|
||||
Entry 6 1111110 7
|
||||
Entry 7 1111111 7
|
||||
*/
|
||||
|
||||
/* Initialise the decoding. */
|
||||
pbi->bits_so_far = 0;
|
||||
|
||||
theora_read(pbi->opb,1,&ret);
|
||||
pbi->bit_pattern = ret;
|
||||
|
||||
/* Do we have a match */
|
||||
if ( pbi->bit_pattern == 0 )
|
||||
return (CODING_MODE)0;
|
||||
|
||||
/* Get the next bit */
|
||||
theora_read(pbi->opb,1,&ret);
|
||||
pbi->bit_pattern = (pbi->bit_pattern << 1) | ret;
|
||||
|
||||
/* Do we have a match */
|
||||
if ( pbi->bit_pattern == 0x0002 )
|
||||
return (CODING_MODE)1;
|
||||
|
||||
theora_read(pbi->opb,1,&ret);
|
||||
pbi->bit_pattern = (pbi->bit_pattern << 1) | ret;
|
||||
|
||||
/* Do we have a match */
|
||||
if ( pbi->bit_pattern == 0x0006 )
|
||||
return (CODING_MODE)2;
|
||||
|
||||
theora_read(pbi->opb,1,&ret);
|
||||
pbi->bit_pattern = (pbi->bit_pattern << 1) | ret;
|
||||
|
||||
/* Do we have a match */
|
||||
if ( pbi->bit_pattern == 0x000E )
|
||||
return (CODING_MODE)3;
|
||||
|
||||
theora_read(pbi->opb,1,&ret);
|
||||
pbi->bit_pattern = (pbi->bit_pattern << 1) | ret;
|
||||
|
||||
/* Do we have a match */
|
||||
if ( pbi->bit_pattern == 0x001E )
|
||||
return (CODING_MODE)4;
|
||||
|
||||
theora_read(pbi->opb,1,&ret);
|
||||
pbi->bit_pattern = (pbi->bit_pattern << 1) | ret;
|
||||
|
||||
/* Do we have a match */
|
||||
if ( pbi->bit_pattern == 0x003E )
|
||||
return (CODING_MODE)5;
|
||||
|
||||
theora_read(pbi->opb,1,&ret);
|
||||
pbi->bit_pattern = (pbi->bit_pattern << 1) | ret;
|
||||
|
||||
/* Do we have a match */
|
||||
if ( pbi->bit_pattern == 0x007E )
|
||||
return (CODING_MODE)6;
|
||||
else
|
||||
return (CODING_MODE)7;
|
||||
}
|
||||
|
394
src/add-ons/media/plugins/theora/libtheora/frinit.c
Normal file
394
src/add-ons/media/plugins/theora/libtheora/frinit.c
Normal file
@ -0,0 +1,394 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2003 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function:
|
||||
last mod: $Id: frinit.c,v 1.1 2004/02/24 13:50:13 shatty Exp $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "encoder_internal.h"
|
||||
|
||||
|
||||
void InitializeFragCoordinates(PB_INSTANCE *pbi){
|
||||
|
||||
ogg_uint32_t i, j;
|
||||
|
||||
ogg_uint32_t HorizFrags = pbi->HFragments;
|
||||
ogg_uint32_t VertFrags = pbi->VFragments;
|
||||
ogg_uint32_t StartFrag = 0;
|
||||
|
||||
/* Y */
|
||||
|
||||
for(i = 0; i< VertFrags; i++){
|
||||
for(j = 0; j< HorizFrags; j++){
|
||||
|
||||
ogg_uint32_t ThisFrag = i * HorizFrags + j;
|
||||
pbi->FragCoordinates[ ThisFrag ].x=j * BLOCK_HEIGHT_WIDTH;
|
||||
pbi->FragCoordinates[ ThisFrag ].y=i * BLOCK_HEIGHT_WIDTH;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* U */
|
||||
HorizFrags >>= 1;
|
||||
VertFrags >>= 1;
|
||||
StartFrag = pbi->YPlaneFragments;
|
||||
|
||||
for(i = 0; i< VertFrags; i++) {
|
||||
for(j = 0; j< HorizFrags; j++) {
|
||||
ogg_uint32_t ThisFrag = StartFrag + i * HorizFrags + j;
|
||||
pbi->FragCoordinates[ ThisFrag ].x=j * BLOCK_HEIGHT_WIDTH;
|
||||
pbi->FragCoordinates[ ThisFrag ].y=i * BLOCK_HEIGHT_WIDTH;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* V */
|
||||
StartFrag = pbi->YPlaneFragments + pbi->UVPlaneFragments;
|
||||
for(i = 0; i< VertFrags; i++) {
|
||||
for(j = 0; j< HorizFrags; j++) {
|
||||
ogg_uint32_t ThisFrag = StartFrag + i * HorizFrags + j;
|
||||
pbi->FragCoordinates[ ThisFrag ].x=j * BLOCK_HEIGHT_WIDTH;
|
||||
pbi->FragCoordinates[ ThisFrag ].y=i * BLOCK_HEIGHT_WIDTH;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void CalcPixelIndexTable( PB_INSTANCE *pbi){
|
||||
ogg_uint32_t i;
|
||||
ogg_uint32_t * PixelIndexTablePtr;
|
||||
|
||||
/* Calculate the pixel index table for normal image buffers */
|
||||
PixelIndexTablePtr = pbi->pixel_index_table;
|
||||
for ( i = 0; i < pbi->YPlaneFragments; i++ ) {
|
||||
PixelIndexTablePtr[ i ] =
|
||||
((i / pbi->HFragments) * VFRAGPIXELS *
|
||||
pbi->info.width);
|
||||
PixelIndexTablePtr[ i ] +=
|
||||
((i % pbi->HFragments) * HFRAGPIXELS);
|
||||
}
|
||||
|
||||
PixelIndexTablePtr = &pbi->pixel_index_table[pbi->YPlaneFragments];
|
||||
for ( i = 0; i < ((pbi->HFragments >> 1) * pbi->VFragments); i++ ) {
|
||||
PixelIndexTablePtr[ i ] =
|
||||
((i / (pbi->HFragments / 2) ) *
|
||||
(VFRAGPIXELS *
|
||||
(pbi->info.width / 2)) );
|
||||
PixelIndexTablePtr[ i ] +=
|
||||
((i % (pbi->HFragments / 2) ) *
|
||||
HFRAGPIXELS) + pbi->YPlaneSize;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* Now calculate the pixel index table for image reconstruction buffers */
|
||||
PixelIndexTablePtr = pbi->recon_pixel_index_table;
|
||||
for ( i = 0; i < pbi->YPlaneFragments; i++ ){
|
||||
PixelIndexTablePtr[ i ] =
|
||||
((i / pbi->HFragments) * VFRAGPIXELS *
|
||||
pbi->YStride);
|
||||
PixelIndexTablePtr[ i ] +=
|
||||
((i % pbi->HFragments) * HFRAGPIXELS) +
|
||||
pbi->ReconYDataOffset;
|
||||
}
|
||||
|
||||
/* U blocks */
|
||||
PixelIndexTablePtr = &pbi->recon_pixel_index_table[pbi->YPlaneFragments];
|
||||
for ( i = 0; i < pbi->UVPlaneFragments; i++ ) {
|
||||
PixelIndexTablePtr[ i ] =
|
||||
((i / (pbi->HFragments / 2) ) *
|
||||
(VFRAGPIXELS * (pbi->UVStride)) );
|
||||
PixelIndexTablePtr[ i ] +=
|
||||
((i % (pbi->HFragments / 2) ) *
|
||||
HFRAGPIXELS) + pbi->ReconUDataOffset;
|
||||
}
|
||||
|
||||
/* V blocks */
|
||||
PixelIndexTablePtr =
|
||||
&pbi->recon_pixel_index_table[pbi->YPlaneFragments +
|
||||
pbi->UVPlaneFragments];
|
||||
|
||||
for ( i = 0; i < pbi->UVPlaneFragments; i++ ) {
|
||||
PixelIndexTablePtr[ i ] =
|
||||
((i / (pbi->HFragments / 2) ) *
|
||||
(VFRAGPIXELS * (pbi->UVStride)) );
|
||||
PixelIndexTablePtr[ i ] +=
|
||||
((i % (pbi->HFragments / 2) ) * HFRAGPIXELS) +
|
||||
pbi->ReconVDataOffset;
|
||||
}
|
||||
}
|
||||
|
||||
void ClearFragmentInfo(PB_INSTANCE * pbi){
|
||||
|
||||
/* free prior allocs if present */
|
||||
if(pbi->display_fragments) _ogg_free(pbi->display_fragments);
|
||||
if(pbi->pixel_index_table) _ogg_free(pbi->pixel_index_table);
|
||||
if(pbi->recon_pixel_index_table) _ogg_free(pbi->recon_pixel_index_table);
|
||||
if(pbi->FragTokenCounts) _ogg_free(pbi->FragTokenCounts);
|
||||
if(pbi->CodedBlockList) _ogg_free(pbi->CodedBlockList);
|
||||
if(pbi->FragMVect) _ogg_free(pbi->FragMVect);
|
||||
if(pbi->FragCoeffs) _ogg_free(pbi->FragCoeffs);
|
||||
if(pbi->FragCoefEOB) _ogg_free(pbi->FragCoefEOB);
|
||||
if(pbi->skipped_display_fragments) _ogg_free(pbi->skipped_display_fragments);
|
||||
if(pbi->QFragData) _ogg_free(pbi->QFragData);
|
||||
if(pbi->TokenList) _ogg_free(pbi->TokenList);
|
||||
if(pbi->FragCodingMethod) _ogg_free(pbi->FragCodingMethod);
|
||||
if(pbi->FragCoordinates) _ogg_free(pbi->FragCoordinates);
|
||||
|
||||
if(pbi->FragQIndex) _ogg_free(pbi->FragQIndex);
|
||||
if(pbi->PPCoefBuffer) _ogg_free(pbi->PPCoefBuffer);
|
||||
if(pbi->FragmentVariances) _ogg_free(pbi->FragmentVariances);
|
||||
|
||||
if(pbi->BlockMap) _ogg_free(pbi->BlockMap);
|
||||
|
||||
if(pbi->SBCodedFlags) _ogg_free(pbi->SBCodedFlags);
|
||||
if(pbi->SBFullyFlags) _ogg_free(pbi->SBFullyFlags);
|
||||
if(pbi->MBFullyFlags) _ogg_free(pbi->MBFullyFlags);
|
||||
if(pbi->MBCodedFlags) _ogg_free(pbi->MBCodedFlags);
|
||||
|
||||
if(pbi->_Nodes) _ogg_free(pbi->_Nodes);
|
||||
pbi->_Nodes = 0;
|
||||
|
||||
pbi->QFragData = 0;
|
||||
pbi->TokenList = 0;
|
||||
pbi->skipped_display_fragments = 0;
|
||||
pbi->FragCoeffs = 0;
|
||||
pbi->FragCoefEOB = 0;
|
||||
pbi->display_fragments = 0;
|
||||
pbi->pixel_index_table = 0;
|
||||
pbi->recon_pixel_index_table = 0;
|
||||
pbi->FragTokenCounts = 0;
|
||||
pbi->CodedBlockList = 0;
|
||||
pbi->FragCodingMethod = 0;
|
||||
pbi->FragMVect = 0;
|
||||
pbi->MBCodedFlags = 0;
|
||||
pbi->MBFullyFlags = 0;
|
||||
pbi->BlockMap = 0;
|
||||
|
||||
pbi->SBCodedFlags = 0;
|
||||
pbi->SBFullyFlags = 0;
|
||||
pbi->QFragData = 0;
|
||||
pbi->TokenList = 0;
|
||||
pbi->skipped_display_fragments = 0;
|
||||
pbi->FragCoeffs = 0;
|
||||
pbi->FragCoefEOB = 0;
|
||||
pbi->display_fragments = 0;
|
||||
pbi->pixel_index_table = 0;
|
||||
pbi->recon_pixel_index_table = 0;
|
||||
pbi->FragTokenCounts = 0;
|
||||
pbi->CodedBlockList = 0;
|
||||
pbi->FragCodingMethod = 0;
|
||||
pbi->FragCoordinates = 0;
|
||||
pbi->FragMVect = 0;
|
||||
|
||||
pbi->PPCoefBuffer=0;
|
||||
pbi->PPCoefBuffer=0;
|
||||
pbi->FragQIndex = 0;
|
||||
pbi->FragQIndex = 0;
|
||||
pbi->FragmentVariances= 0;
|
||||
pbi->FragmentVariances = 0 ;
|
||||
}
|
||||
|
||||
void InitFragmentInfo(PB_INSTANCE * pbi){
|
||||
|
||||
/* clear any existing info */
|
||||
ClearFragmentInfo(pbi);
|
||||
|
||||
/* Perform Fragment Allocations */
|
||||
pbi->display_fragments =
|
||||
_ogg_malloc(pbi->UnitFragments * sizeof(*pbi->display_fragments));
|
||||
|
||||
pbi->pixel_index_table =
|
||||
_ogg_malloc(pbi->UnitFragments * sizeof(*pbi->pixel_index_table));
|
||||
|
||||
pbi->recon_pixel_index_table =
|
||||
_ogg_malloc(pbi->UnitFragments * sizeof(*pbi->recon_pixel_index_table));
|
||||
|
||||
pbi->FragTokenCounts =
|
||||
_ogg_malloc(pbi->UnitFragments * sizeof(*pbi->FragTokenCounts));
|
||||
|
||||
pbi->CodedBlockList =
|
||||
_ogg_malloc(pbi->UnitFragments * sizeof(*pbi->CodedBlockList));
|
||||
|
||||
pbi->FragMVect =
|
||||
_ogg_malloc(pbi->UnitFragments * sizeof(*pbi->FragMVect));
|
||||
|
||||
pbi->FragCoeffs =
|
||||
_ogg_malloc(pbi->UnitFragments * sizeof(*pbi->FragCoeffs));
|
||||
|
||||
pbi->FragCoefEOB =
|
||||
_ogg_malloc(pbi->UnitFragments * sizeof(*pbi->FragCoefEOB));
|
||||
|
||||
pbi->skipped_display_fragments =
|
||||
_ogg_malloc(pbi->UnitFragments * sizeof(*pbi->skipped_display_fragments));
|
||||
|
||||
pbi->QFragData =
|
||||
_ogg_malloc(pbi->UnitFragments * sizeof(*pbi->QFragData));
|
||||
|
||||
pbi->TokenList =
|
||||
_ogg_malloc(pbi->UnitFragments * sizeof(*pbi->TokenList));
|
||||
|
||||
pbi->FragCodingMethod =
|
||||
_ogg_malloc(pbi->UnitFragments * sizeof(*pbi->FragCodingMethod));
|
||||
|
||||
pbi->FragCoordinates =
|
||||
_ogg_malloc(pbi->UnitFragments * sizeof(*pbi->FragCoordinates));
|
||||
|
||||
pbi->FragQIndex =
|
||||
_ogg_malloc(pbi->UnitFragments * sizeof(*pbi->FragQIndex));
|
||||
|
||||
pbi->PPCoefBuffer =
|
||||
_ogg_malloc(pbi->UnitFragments * sizeof(*pbi->PPCoefBuffer));
|
||||
|
||||
pbi->FragmentVariances =
|
||||
_ogg_malloc(pbi->UnitFragments * sizeof(*pbi->FragmentVariances));
|
||||
|
||||
pbi->_Nodes =
|
||||
_ogg_malloc(pbi->UnitFragments * sizeof(*pbi->_Nodes));
|
||||
|
||||
/* Super Block Initialization */
|
||||
pbi->SBCodedFlags =
|
||||
_ogg_malloc(pbi->SuperBlocks * sizeof(*pbi->SBCodedFlags));
|
||||
|
||||
pbi->SBFullyFlags =
|
||||
_ogg_malloc(pbi->SuperBlocks * sizeof(*pbi->SBFullyFlags));
|
||||
|
||||
/* Macro Block Initialization */
|
||||
pbi->MBCodedFlags =
|
||||
_ogg_malloc(pbi->MacroBlocks * sizeof(*pbi->MBCodedFlags));
|
||||
|
||||
pbi->MBFullyFlags =
|
||||
_ogg_malloc(pbi->MacroBlocks * sizeof(*pbi->MBFullyFlags));
|
||||
|
||||
pbi->BlockMap =
|
||||
_ogg_malloc(pbi->SuperBlocks * sizeof(*pbi->BlockMap));
|
||||
|
||||
}
|
||||
|
||||
void ClearFrameInfo(PB_INSTANCE * pbi){
|
||||
if(pbi->ThisFrameRecon )
|
||||
_ogg_free(pbi->ThisFrameRecon );
|
||||
if(pbi->GoldenFrame)
|
||||
_ogg_free(pbi->GoldenFrame);
|
||||
if(pbi->LastFrameRecon)
|
||||
_ogg_free(pbi->LastFrameRecon);
|
||||
if(pbi->PostProcessBuffer)
|
||||
_ogg_free(pbi->PostProcessBuffer);
|
||||
|
||||
|
||||
pbi->ThisFrameRecon = 0;
|
||||
pbi->GoldenFrame = 0;
|
||||
pbi->LastFrameRecon = 0;
|
||||
pbi->PostProcessBuffer = 0;
|
||||
|
||||
|
||||
pbi->ThisFrameRecon = 0;
|
||||
pbi->GoldenFrame = 0;
|
||||
pbi->LastFrameRecon = 0;
|
||||
pbi->PostProcessBuffer = 0;
|
||||
|
||||
}
|
||||
|
||||
void InitFrameInfo(PB_INSTANCE * pbi, unsigned int FrameSize){
|
||||
|
||||
/* clear any existing info */
|
||||
ClearFrameInfo(pbi);
|
||||
|
||||
/* allocate frames */
|
||||
pbi->ThisFrameRecon =
|
||||
_ogg_malloc(FrameSize*sizeof(*pbi->ThisFrameRecon));
|
||||
|
||||
pbi->GoldenFrame =
|
||||
_ogg_malloc(FrameSize*sizeof(*pbi->GoldenFrame));
|
||||
|
||||
pbi->LastFrameRecon =
|
||||
_ogg_malloc(FrameSize*sizeof(*pbi->LastFrameRecon));
|
||||
|
||||
pbi->PostProcessBuffer =
|
||||
_ogg_malloc(FrameSize*sizeof(*pbi->PostProcessBuffer));
|
||||
|
||||
}
|
||||
|
||||
void InitFrameDetails(PB_INSTANCE *pbi){
|
||||
int FrameSize;
|
||||
|
||||
/*pbi->PostProcessingLevel = 0;
|
||||
pbi->PostProcessingLevel = 4;
|
||||
pbi->PostProcessingLevel = 5;
|
||||
pbi->PostProcessingLevel = 6;*/
|
||||
|
||||
pbi->PostProcessingLevel = 0;
|
||||
|
||||
|
||||
/* Set the frame size etc. */
|
||||
|
||||
pbi->YPlaneSize = pbi->info.width *
|
||||
pbi->info.height;
|
||||
pbi->UVPlaneSize = pbi->YPlaneSize / 4;
|
||||
pbi->HFragments = pbi->info.width / HFRAGPIXELS;
|
||||
pbi->VFragments = pbi->info.height / VFRAGPIXELS;
|
||||
pbi->UnitFragments = ((pbi->VFragments * pbi->HFragments)*3)/2;
|
||||
pbi->YPlaneFragments = pbi->HFragments * pbi->VFragments;
|
||||
pbi->UVPlaneFragments = pbi->YPlaneFragments / 4;
|
||||
|
||||
pbi->YStride = (pbi->info.width + STRIDE_EXTRA);
|
||||
pbi->UVStride = pbi->YStride / 2;
|
||||
pbi->ReconYPlaneSize = pbi->YStride *
|
||||
(pbi->info.height + STRIDE_EXTRA);
|
||||
pbi->ReconUVPlaneSize = pbi->ReconYPlaneSize / 4;
|
||||
FrameSize = pbi->ReconYPlaneSize + 2 * pbi->ReconUVPlaneSize;
|
||||
|
||||
pbi->YDataOffset = 0;
|
||||
pbi->UDataOffset = pbi->YPlaneSize;
|
||||
pbi->VDataOffset = pbi->YPlaneSize + pbi->UVPlaneSize;
|
||||
pbi->ReconYDataOffset =
|
||||
(pbi->YStride * UMV_BORDER) + UMV_BORDER;
|
||||
pbi->ReconUDataOffset = pbi->ReconYPlaneSize +
|
||||
(pbi->UVStride * (UMV_BORDER/2)) + (UMV_BORDER/2);
|
||||
pbi->ReconVDataOffset = pbi->ReconYPlaneSize + pbi->ReconUVPlaneSize +
|
||||
(pbi->UVStride * (UMV_BORDER/2)) + (UMV_BORDER/2);
|
||||
|
||||
/* Image dimensions in Super-Blocks */
|
||||
pbi->YSBRows = (pbi->info.height/32) +
|
||||
( pbi->info.height%32 ? 1 : 0 );
|
||||
pbi->YSBCols = (pbi->info.width/32) +
|
||||
( pbi->info.width%32 ? 1 : 0 );
|
||||
pbi->UVSBRows = ((pbi->info.height/2)/32) +
|
||||
( (pbi->info.height/2)%32 ? 1 : 0 );
|
||||
pbi->UVSBCols = ((pbi->info.width/2)/32) +
|
||||
( (pbi->info.width/2)%32 ? 1 : 0 );
|
||||
|
||||
/* Super-Blocks per component */
|
||||
pbi->YSuperBlocks = pbi->YSBRows * pbi->YSBCols;
|
||||
pbi->UVSuperBlocks = pbi->UVSBRows * pbi->UVSBCols;
|
||||
pbi->SuperBlocks = pbi->YSuperBlocks+2*pbi->UVSuperBlocks;
|
||||
|
||||
/* Useful externals */
|
||||
pbi->YMacroBlocks = ((pbi->VFragments+1)/2)*((pbi->HFragments+1)/2);
|
||||
pbi->UVMacroBlocks = ((pbi->VFragments/2+1)/2)*((pbi->HFragments/2+1)/2);
|
||||
pbi->MacroBlocks = pbi->YMacroBlocks+2*pbi->UVMacroBlocks;
|
||||
|
||||
InitFragmentInfo(pbi);
|
||||
InitFrameInfo(pbi, FrameSize);
|
||||
InitializeFragCoordinates(pbi);
|
||||
|
||||
/* Configure mapping between quad-tree and fragments */
|
||||
CreateBlockMapping ( pbi->BlockMap, pbi->YSuperBlocks,
|
||||
pbi->UVSuperBlocks, pbi->HFragments, pbi->VFragments);
|
||||
|
||||
/* Re-initialise the pixel index table. */
|
||||
|
||||
CalcPixelIndexTable( pbi );
|
||||
|
||||
}
|
||||
|
309
src/add-ons/media/plugins/theora/libtheora/huffman.c
Normal file
309
src/add-ons/media/plugins/theora/libtheora/huffman.c
Normal file
@ -0,0 +1,309 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2003 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function:
|
||||
last mod: $Id: huffman.c,v 1.1 2004/02/24 13:50:13 shatty Exp $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "encoder_internal.h"
|
||||
#include "hufftables.h"
|
||||
|
||||
static void CreateHuffmanList(HUFF_ENTRY ** HuffRoot,
|
||||
ogg_uint32_t HIndex, ogg_uint32_t *FreqList ) {
|
||||
int i;
|
||||
HUFF_ENTRY *entry_ptr;
|
||||
HUFF_ENTRY *search_ptr;
|
||||
|
||||
/* Create a HUFF entry for token zero. */
|
||||
HuffRoot[HIndex] = (HUFF_ENTRY *)_ogg_calloc(1,sizeof(*HuffRoot[HIndex]));
|
||||
|
||||
HuffRoot[HIndex]->Previous = NULL;
|
||||
HuffRoot[HIndex]->Next = NULL;
|
||||
HuffRoot[HIndex]->ZeroChild = NULL;
|
||||
HuffRoot[HIndex]->OneChild = NULL;
|
||||
HuffRoot[HIndex]->Value = 0;
|
||||
HuffRoot[HIndex]->Frequency = FreqList[0];
|
||||
|
||||
if ( HuffRoot[HIndex]->Frequency == 0 )
|
||||
HuffRoot[HIndex]->Frequency = 1;
|
||||
|
||||
/* Now add entries for all the other possible tokens. */
|
||||
for ( i = 1; i < MAX_ENTROPY_TOKENS; i++ ) {
|
||||
entry_ptr = (HUFF_ENTRY *)_ogg_calloc(1,sizeof(*entry_ptr));
|
||||
|
||||
entry_ptr->Value = i;
|
||||
entry_ptr->Frequency = FreqList[i];
|
||||
entry_ptr->ZeroChild = NULL;
|
||||
entry_ptr->OneChild = NULL;
|
||||
|
||||
/* Force min value of 1. This prevents the tree getting too deep. */
|
||||
if ( entry_ptr->Frequency == 0 )
|
||||
entry_ptr->Frequency = 1;
|
||||
|
||||
if ( entry_ptr->Frequency <= HuffRoot[HIndex]->Frequency ){
|
||||
entry_ptr->Next = HuffRoot[HIndex];
|
||||
HuffRoot[HIndex]->Previous = entry_ptr;
|
||||
entry_ptr->Previous = NULL;
|
||||
HuffRoot[HIndex] = entry_ptr;
|
||||
}else{
|
||||
search_ptr = HuffRoot[HIndex];
|
||||
while ( (search_ptr->Next != NULL) &&
|
||||
(search_ptr->Frequency < entry_ptr->Frequency) ){
|
||||
search_ptr = (HUFF_ENTRY *)search_ptr->Next;
|
||||
}
|
||||
|
||||
if ( search_ptr->Frequency < entry_ptr->Frequency ){
|
||||
entry_ptr->Next = NULL;
|
||||
entry_ptr->Previous = search_ptr;
|
||||
search_ptr->Next = entry_ptr;
|
||||
}else{
|
||||
entry_ptr->Next = search_ptr;
|
||||
entry_ptr->Previous = search_ptr->Previous;
|
||||
search_ptr->Previous->Next = entry_ptr;
|
||||
search_ptr->Previous = entry_ptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void CreateCodeArray( HUFF_ENTRY * HuffRoot,
|
||||
ogg_uint32_t *HuffCodeArray,
|
||||
unsigned char *HuffCodeLengthArray,
|
||||
ogg_uint32_t CodeValue,
|
||||
unsigned char CodeLength ) {
|
||||
|
||||
/* If we are at a leaf then fill in a code array entry. */
|
||||
if ( ( HuffRoot->ZeroChild == NULL ) && ( HuffRoot->OneChild == NULL ) ){
|
||||
HuffCodeArray[HuffRoot->Value] = CodeValue;
|
||||
HuffCodeLengthArray[HuffRoot->Value] = CodeLength;
|
||||
}else{
|
||||
/* Recursive calls to scan down the tree. */
|
||||
CodeLength++;
|
||||
CreateCodeArray(HuffRoot->ZeroChild, HuffCodeArray, HuffCodeLengthArray,
|
||||
((CodeValue << 1) + 0), CodeLength);
|
||||
CreateCodeArray(HuffRoot->OneChild, HuffCodeArray, HuffCodeLengthArray,
|
||||
((CodeValue << 1) + 1), CodeLength);
|
||||
}
|
||||
}
|
||||
|
||||
static void BuildHuffmanTree( HUFF_ENTRY **HuffRoot,
|
||||
ogg_uint32_t *HuffCodeArray,
|
||||
unsigned char *HuffCodeLengthArray,
|
||||
ogg_uint32_t HIndex,
|
||||
ogg_uint32_t *FreqList ){
|
||||
|
||||
HUFF_ENTRY *entry_ptr;
|
||||
HUFF_ENTRY *search_ptr;
|
||||
|
||||
/* First create a sorted linked list representing the frequencies of
|
||||
each token. */
|
||||
CreateHuffmanList( HuffRoot, HIndex, FreqList );
|
||||
|
||||
/* Now build the tree from the list. */
|
||||
|
||||
/* While there are at least two items left in the list. */
|
||||
while ( HuffRoot[HIndex]->Next != NULL ){
|
||||
/* Create the new node as the parent of the first two in the list. */
|
||||
entry_ptr = (HUFF_ENTRY *)_ogg_calloc(1,sizeof(*entry_ptr));
|
||||
entry_ptr->Value = -1;
|
||||
entry_ptr->Frequency = HuffRoot[HIndex]->Frequency +
|
||||
HuffRoot[HIndex]->Next->Frequency ;
|
||||
entry_ptr->ZeroChild = HuffRoot[HIndex];
|
||||
entry_ptr->OneChild = HuffRoot[HIndex]->Next;
|
||||
|
||||
/* If there are still more items in the list then insert the new
|
||||
node into the list. */
|
||||
if (entry_ptr->OneChild->Next != NULL ){
|
||||
/* Set up the provisional 'new root' */
|
||||
HuffRoot[HIndex] = entry_ptr->OneChild->Next;
|
||||
HuffRoot[HIndex]->Previous = NULL;
|
||||
|
||||
/* Now scan through the remaining list to insert the new entry
|
||||
at the appropriate point. */
|
||||
if ( entry_ptr->Frequency <= HuffRoot[HIndex]->Frequency ){
|
||||
entry_ptr->Next = HuffRoot[HIndex];
|
||||
HuffRoot[HIndex]->Previous = entry_ptr;
|
||||
entry_ptr->Previous = NULL;
|
||||
HuffRoot[HIndex] = entry_ptr;
|
||||
}else{
|
||||
search_ptr = HuffRoot[HIndex];
|
||||
while ( (search_ptr->Next != NULL) &&
|
||||
(search_ptr->Frequency < entry_ptr->Frequency) ){
|
||||
search_ptr = search_ptr->Next;
|
||||
}
|
||||
|
||||
if ( search_ptr->Frequency < entry_ptr->Frequency ){
|
||||
entry_ptr->Next = NULL;
|
||||
entry_ptr->Previous = search_ptr;
|
||||
search_ptr->Next = entry_ptr;
|
||||
}else{
|
||||
entry_ptr->Next = search_ptr;
|
||||
entry_ptr->Previous = search_ptr->Previous;
|
||||
search_ptr->Previous->Next = entry_ptr;
|
||||
search_ptr->Previous = entry_ptr;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
/* Build has finished. */
|
||||
entry_ptr->Next = NULL;
|
||||
entry_ptr->Previous = NULL;
|
||||
HuffRoot[HIndex] = entry_ptr;
|
||||
}
|
||||
|
||||
/* Delete the Next/Previous properties of the children (PROB NOT NEC). */
|
||||
entry_ptr->ZeroChild->Next = NULL;
|
||||
entry_ptr->ZeroChild->Previous = NULL;
|
||||
entry_ptr->OneChild->Next = NULL;
|
||||
entry_ptr->OneChild->Previous = NULL;
|
||||
|
||||
}
|
||||
|
||||
/* Now build a code array from the tree. */
|
||||
CreateCodeArray( HuffRoot[HIndex], HuffCodeArray,
|
||||
HuffCodeLengthArray, 0, 0);
|
||||
}
|
||||
|
||||
static void DestroyHuffTree(HUFF_ENTRY *root_ptr){
|
||||
if (root_ptr){
|
||||
if ( root_ptr->ZeroChild )
|
||||
DestroyHuffTree(root_ptr->ZeroChild);
|
||||
|
||||
if ( root_ptr->OneChild )
|
||||
DestroyHuffTree(root_ptr->OneChild);
|
||||
|
||||
_ogg_free(root_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
void ClearHuffmanSet( PB_INSTANCE *pbi ){
|
||||
int i;
|
||||
|
||||
ClearHuffmanTrees(pbi->HuffRoot_VP3x);
|
||||
|
||||
for ( i = 0; i < NUM_HUFF_TABLES; i++ )
|
||||
if (pbi->HuffCodeArray_VP3x[i])
|
||||
_ogg_free (pbi->HuffCodeArray_VP3x[i]);
|
||||
|
||||
for ( i = 0; i < NUM_HUFF_TABLES; i++ )
|
||||
if (pbi->HuffCodeLengthArray_VP3x[i])
|
||||
_ogg_free (pbi->HuffCodeLengthArray_VP3x[i]);
|
||||
}
|
||||
|
||||
void InitHuffmanSet( PB_INSTANCE *pbi ){
|
||||
int i;
|
||||
|
||||
ClearHuffmanSet(pbi);
|
||||
|
||||
pbi->ExtraBitLengths_VP3x = ExtraBitLengths_VP31;
|
||||
|
||||
for ( i = 0; i < NUM_HUFF_TABLES; i++ ){
|
||||
pbi->HuffCodeArray_VP3x[i] =
|
||||
_ogg_calloc(MAX_ENTROPY_TOKENS,
|
||||
sizeof(*pbi->HuffCodeArray_VP3x[i]));
|
||||
pbi->HuffCodeLengthArray_VP3x[i] =
|
||||
_ogg_calloc(MAX_ENTROPY_TOKENS,
|
||||
sizeof(*pbi->HuffCodeLengthArray_VP3x[i]));
|
||||
BuildHuffmanTree( pbi->HuffRoot_VP3x,
|
||||
pbi->HuffCodeArray_VP3x[i],
|
||||
pbi->HuffCodeLengthArray_VP3x[i],
|
||||
i, FrequencyCounts_VP3[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static int ReadHuffTree(HUFF_ENTRY * HuffRoot, int depth,
|
||||
oggpack_buffer *opb) {
|
||||
long bit;
|
||||
long ret;
|
||||
theora_read(opb,1,&bit);
|
||||
if(bit < 0) return OC_BADHEADER;
|
||||
else if(!bit) {
|
||||
int ret;
|
||||
if (++depth > 32) return OC_BADHEADER;
|
||||
HuffRoot->ZeroChild = (HUFF_ENTRY *)_ogg_calloc(1, sizeof(HUFF_ENTRY));
|
||||
ret = ReadHuffTree(HuffRoot->ZeroChild, depth, opb);
|
||||
if (ret < 0) return ret;
|
||||
HuffRoot->OneChild = (HUFF_ENTRY *)_ogg_calloc(1, sizeof(HUFF_ENTRY));
|
||||
ret = ReadHuffTree(HuffRoot->OneChild, depth, opb);
|
||||
if (ret < 0) return ret;
|
||||
HuffRoot->Value = -1;
|
||||
} else {
|
||||
HuffRoot->ZeroChild = NULL;
|
||||
HuffRoot->OneChild = NULL;
|
||||
theora_read(opb,5,&ret);
|
||||
HuffRoot->Value=ret;;
|
||||
if (HuffRoot->Value < 0) return OC_BADHEADER;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ReadHuffmanTrees(codec_setup_info *ci, oggpack_buffer *opb) {
|
||||
int i;
|
||||
for (i=0; i<NUM_HUFF_TABLES; i++) {
|
||||
int ret;
|
||||
ci->HuffRoot[i] = (HUFF_ENTRY *)_ogg_calloc(1, sizeof(HUFF_ENTRY));
|
||||
ret = ReadHuffTree(ci->HuffRoot[i], 0, opb);
|
||||
if (ret) return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void WriteHuffTree(HUFF_ENTRY *HuffRoot, oggpack_buffer *opb) {
|
||||
if (HuffRoot->Value >= 0) {
|
||||
oggpackB_write(opb, 1, 1);
|
||||
oggpackB_write(opb, HuffRoot->Value, 5);
|
||||
} else {
|
||||
oggpackB_write(opb, 0, 1);
|
||||
WriteHuffTree(HuffRoot->ZeroChild, opb);
|
||||
WriteHuffTree(HuffRoot->OneChild, opb);
|
||||
}
|
||||
}
|
||||
|
||||
void WriteHuffmanTrees(HUFF_ENTRY *HuffRoot[NUM_HUFF_TABLES],
|
||||
oggpack_buffer *opb) {
|
||||
int i;
|
||||
for(i=0; i<NUM_HUFF_TABLES; i++) {
|
||||
WriteHuffTree(HuffRoot[i], opb);
|
||||
}
|
||||
}
|
||||
|
||||
static HUFF_ENTRY *CopyHuffTree(const HUFF_ENTRY *HuffSrc) {
|
||||
if(HuffSrc){
|
||||
HUFF_ENTRY *HuffDst;
|
||||
HuffDst = (HUFF_ENTRY *)_ogg_calloc(1, sizeof(HUFF_ENTRY));
|
||||
HuffDst->Value = HuffSrc->Value;
|
||||
if (HuffSrc->Value < 0) {
|
||||
HuffDst->ZeroChild = CopyHuffTree(HuffSrc->ZeroChild);
|
||||
HuffDst->OneChild = CopyHuffTree(HuffSrc->OneChild);
|
||||
}
|
||||
return HuffDst;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void InitHuffmanTrees(PB_INSTANCE *pbi, const codec_setup_info *ci) {
|
||||
int i;
|
||||
pbi->ExtraBitLengths_VP3x = ExtraBitLengths_VP31;
|
||||
for(i=0; i<NUM_HUFF_TABLES; i++){
|
||||
pbi->HuffRoot_VP3x[i] = CopyHuffTree(ci->HuffRoot[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void ClearHuffmanTrees(HUFF_ENTRY *HuffRoot[NUM_HUFF_TABLES]){
|
||||
int i;
|
||||
for(i=0; i<NUM_HUFF_TABLES; i++) {
|
||||
DestroyHuffTree(HuffRoot[i]);
|
||||
HuffRoot[i] = NULL;
|
||||
}
|
||||
}
|
74
src/add-ons/media/plugins/theora/libtheora/huffman.h
Normal file
74
src/add-ons/media/plugins/theora/libtheora/huffman.h
Normal file
@ -0,0 +1,74 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2003 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function:
|
||||
last mod: $Id: huffman.h,v 1.1 2004/02/24 13:50:13 shatty Exp $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
/********************************************************************
|
||||
* Constants
|
||||
********************************************************************/
|
||||
#define NUM_HUFF_TABLES 80
|
||||
#define DC_HUFF_OFFSET 0
|
||||
#define AC_HUFF_OFFSET 16
|
||||
#define AC_TABLE_2_THRESH 5
|
||||
#define AC_TABLE_3_THRESH 14
|
||||
#define AC_TABLE_4_THRESH 27
|
||||
|
||||
#define DC_HUFF_CHOICES 16
|
||||
#define DC_HUFF_CHOICE_BITS 4
|
||||
|
||||
#define AC_HUFF_CHOICES 16
|
||||
#define AC_HUFF_CHOICE_BITS 4
|
||||
|
||||
/* Constants assosciated with entropy tokenisation. */
|
||||
#define MAX_SINGLE_TOKEN_VALUE 6
|
||||
#define DCT_VAL_CAT2_MIN 3
|
||||
#define DCT_VAL_CAT3_MIN 7
|
||||
#define DCT_VAL_CAT4_MIN 9
|
||||
#define DCT_VAL_CAT5_MIN 13
|
||||
#define DCT_VAL_CAT6_MIN 21
|
||||
#define DCT_VAL_CAT7_MIN 37
|
||||
#define DCT_VAL_CAT8_MIN 69
|
||||
|
||||
#define DCT_EOB_TOKEN 0
|
||||
#define DCT_EOB_PAIR_TOKEN 1
|
||||
#define DCT_EOB_TRIPLE_TOKEN 2
|
||||
#define DCT_REPEAT_RUN_TOKEN 3
|
||||
#define DCT_REPEAT_RUN2_TOKEN 4
|
||||
#define DCT_REPEAT_RUN3_TOKEN 5
|
||||
#define DCT_REPEAT_RUN4_TOKEN 6
|
||||
|
||||
#define DCT_SHORT_ZRL_TOKEN 7
|
||||
#define DCT_ZRL_TOKEN 8
|
||||
|
||||
#define ONE_TOKEN 9 /* Special tokens for -1,1,-2,2 */
|
||||
#define MINUS_ONE_TOKEN 10
|
||||
#define TWO_TOKEN 11
|
||||
#define MINUS_TWO_TOKEN 12
|
||||
|
||||
#define LOW_VAL_TOKENS (MINUS_TWO_TOKEN + 1)
|
||||
#define DCT_VAL_CATEGORY3 (LOW_VAL_TOKENS + 4)
|
||||
#define DCT_VAL_CATEGORY4 (DCT_VAL_CATEGORY3 + 1)
|
||||
#define DCT_VAL_CATEGORY5 (DCT_VAL_CATEGORY4 + 1)
|
||||
#define DCT_VAL_CATEGORY6 (DCT_VAL_CATEGORY5 + 1)
|
||||
#define DCT_VAL_CATEGORY7 (DCT_VAL_CATEGORY6 + 1)
|
||||
#define DCT_VAL_CATEGORY8 (DCT_VAL_CATEGORY7 + 1)
|
||||
|
||||
#define DCT_RUN_CATEGORY1 (DCT_VAL_CATEGORY8 + 1)
|
||||
#define DCT_RUN_CATEGORY1B (DCT_RUN_CATEGORY1 + 5)
|
||||
#define DCT_RUN_CATEGORY1C (DCT_RUN_CATEGORY1B + 1)
|
||||
#define DCT_RUN_CATEGORY2 (DCT_RUN_CATEGORY1C + 1)
|
||||
|
||||
/* 35 */
|
||||
#define MAX_ENTROPY_TOKENS (DCT_RUN_CATEGORY2 + 2)
|
1034
src/add-ons/media/plugins/theora/libtheora/hufftables.h
Normal file
1034
src/add-ons/media/plugins/theora/libtheora/hufftables.h
Normal file
File diff suppressed because it is too large
Load Diff
472
src/add-ons/media/plugins/theora/libtheora/idct.c
Normal file
472
src/add-ons/media/plugins/theora/libtheora/idct.c
Normal file
@ -0,0 +1,472 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2003 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function:
|
||||
last mod: $Id: idct.c,v 1.1 2004/02/24 13:50:13 shatty Exp $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include "encoder_internal.h"
|
||||
#include "quant_lookup.h"
|
||||
|
||||
#define IdctAdjustBeforeShift 8
|
||||
#define xC1S7 64277
|
||||
#define xC2S6 60547
|
||||
#define xC3S5 54491
|
||||
#define xC4S4 46341
|
||||
#define xC5S3 36410
|
||||
#define xC6S2 25080
|
||||
#define xC7S1 12785
|
||||
|
||||
static void dequant_slow( ogg_int16_t * dequant_coeffs,
|
||||
ogg_int16_t * quantized_list,
|
||||
ogg_int32_t * DCT_block) {
|
||||
int i;
|
||||
for(i=0;i<64;i++)
|
||||
DCT_block[dequant_index[i]] = quantized_list[i] * dequant_coeffs[i];
|
||||
}
|
||||
|
||||
void IDctSlow( Q_LIST_ENTRY * InputData,
|
||||
ogg_int16_t *QuantMatrix,
|
||||
ogg_int16_t * OutputData ) {
|
||||
ogg_int32_t IntermediateData[64];
|
||||
ogg_int32_t * ip = IntermediateData;
|
||||
ogg_int16_t * op = OutputData;
|
||||
|
||||
ogg_int32_t _A, _B, _C, _D, _Ad, _Bd, _Cd, _Dd, _E, _F, _G, _H;
|
||||
ogg_int32_t _Ed, _Gd, _Add, _Bdd, _Fd, _Hd;
|
||||
ogg_int32_t t1, t2;
|
||||
|
||||
int loop;
|
||||
|
||||
dequant_slow( QuantMatrix, InputData, IntermediateData);
|
||||
|
||||
/* Inverse DCT on the rows now */
|
||||
for ( loop = 0; loop < 8; loop++){
|
||||
/* Check for non-zero values */
|
||||
if ( ip[0] | ip[1] | ip[2] | ip[3] | ip[4] | ip[5] | ip[6] | ip[7] ) {
|
||||
t1 = (xC1S7 * ip[1]);
|
||||
t2 = (xC7S1 * ip[7]);
|
||||
t1 >>= 16;
|
||||
t2 >>= 16;
|
||||
_A = t1 + t2;
|
||||
|
||||
t1 = (xC7S1 * ip[1]);
|
||||
t2 = (xC1S7 * ip[7]);
|
||||
t1 >>= 16;
|
||||
t2 >>= 16;
|
||||
_B = t1 - t2;
|
||||
|
||||
t1 = (xC3S5 * ip[3]);
|
||||
t2 = (xC5S3 * ip[5]);
|
||||
t1 >>= 16;
|
||||
t2 >>= 16;
|
||||
_C = t1 + t2;
|
||||
|
||||
t1 = (xC3S5 * ip[5]);
|
||||
t2 = (xC5S3 * ip[3]);
|
||||
t1 >>= 16;
|
||||
t2 >>= 16;
|
||||
_D = t1 - t2;
|
||||
|
||||
t1 = (xC4S4 * (_A - _C));
|
||||
t1 >>= 16;
|
||||
_Ad = t1;
|
||||
|
||||
t1 = (xC4S4 * (_B - _D));
|
||||
t1 >>= 16;
|
||||
_Bd = t1;
|
||||
|
||||
|
||||
_Cd = _A + _C;
|
||||
_Dd = _B + _D;
|
||||
|
||||
t1 = (xC4S4 * (ip[0] + ip[4]));
|
||||
t1 >>= 16;
|
||||
_E = t1;
|
||||
|
||||
t1 = (xC4S4 * (ip[0] - ip[4]));
|
||||
t1 >>= 16;
|
||||
_F = t1;
|
||||
|
||||
t1 = (xC2S6 * ip[2]);
|
||||
t2 = (xC6S2 * ip[6]);
|
||||
t1 >>= 16;
|
||||
t2 >>= 16;
|
||||
_G = t1 + t2;
|
||||
|
||||
t1 = (xC6S2 * ip[2]);
|
||||
t2 = (xC2S6 * ip[6]);
|
||||
t1 >>= 16;
|
||||
t2 >>= 16;
|
||||
_H = t1 - t2;
|
||||
|
||||
|
||||
_Ed = _E - _G;
|
||||
_Gd = _E + _G;
|
||||
|
||||
_Add = _F + _Ad;
|
||||
_Bdd = _Bd - _H;
|
||||
|
||||
_Fd = _F - _Ad;
|
||||
_Hd = _Bd + _H;
|
||||
|
||||
/* Final sequence of operations over-write original inputs. */
|
||||
ip[0] = (ogg_int16_t)((_Gd + _Cd ) >> 0);
|
||||
ip[7] = (ogg_int16_t)((_Gd - _Cd ) >> 0);
|
||||
|
||||
ip[1] = (ogg_int16_t)((_Add + _Hd ) >> 0);
|
||||
ip[2] = (ogg_int16_t)((_Add - _Hd ) >> 0);
|
||||
|
||||
ip[3] = (ogg_int16_t)((_Ed + _Dd ) >> 0);
|
||||
ip[4] = (ogg_int16_t)((_Ed - _Dd ) >> 0);
|
||||
|
||||
ip[5] = (ogg_int16_t)((_Fd + _Bdd ) >> 0);
|
||||
ip[6] = (ogg_int16_t)((_Fd - _Bdd ) >> 0);
|
||||
|
||||
}
|
||||
|
||||
ip += 8; /* next row */
|
||||
}
|
||||
|
||||
ip = IntermediateData;
|
||||
|
||||
for ( loop = 0; loop < 8; loop++){
|
||||
/* Check for non-zero values (bitwise or faster than ||) */
|
||||
if ( ip[0 * 8] | ip[1 * 8] | ip[2 * 8] | ip[3 * 8] |
|
||||
ip[4 * 8] | ip[5 * 8] | ip[6 * 8] | ip[7 * 8] ) {
|
||||
|
||||
t1 = (xC1S7 * ip[1*8]);
|
||||
t2 = (xC7S1 * ip[7*8]);
|
||||
t1 >>= 16;
|
||||
t2 >>= 16;
|
||||
_A = t1 + t2;
|
||||
|
||||
t1 = (xC7S1 * ip[1*8]);
|
||||
t2 = (xC1S7 * ip[7*8]);
|
||||
t1 >>= 16;
|
||||
t2 >>= 16;
|
||||
_B = t1 - t2;
|
||||
|
||||
t1 = (xC3S5 * ip[3*8]);
|
||||
t2 = (xC5S3 * ip[5*8]);
|
||||
t1 >>= 16;
|
||||
t2 >>= 16;
|
||||
_C = t1 + t2;
|
||||
|
||||
t1 = (xC3S5 * ip[5*8]);
|
||||
t2 = (xC5S3 * ip[3*8]);
|
||||
t1 >>= 16;
|
||||
t2 >>= 16;
|
||||
_D = t1 - t2;
|
||||
|
||||
t1 = (xC4S4 * (_A - _C));
|
||||
t1 >>= 16;
|
||||
_Ad = t1;
|
||||
|
||||
t1 = (xC4S4 * (_B - _D));
|
||||
t1 >>= 16;
|
||||
_Bd = t1;
|
||||
|
||||
|
||||
_Cd = _A + _C;
|
||||
_Dd = _B + _D;
|
||||
|
||||
t1 = (xC4S4 * (ip[0*8] + ip[4*8]));
|
||||
t1 >>= 16;
|
||||
_E = t1;
|
||||
|
||||
t1 = (xC4S4 * (ip[0*8] - ip[4*8]));
|
||||
t1 >>= 16;
|
||||
_F = t1;
|
||||
|
||||
t1 = (xC2S6 * ip[2*8]);
|
||||
t2 = (xC6S2 * ip[6*8]);
|
||||
t1 >>= 16;
|
||||
t2 >>= 16;
|
||||
_G = t1 + t2;
|
||||
|
||||
t1 = (xC6S2 * ip[2*8]);
|
||||
t2 = (xC2S6 * ip[6*8]);
|
||||
t1 >>= 16;
|
||||
t2 >>= 16;
|
||||
_H = t1 - t2;
|
||||
|
||||
_Ed = _E - _G;
|
||||
_Gd = _E + _G;
|
||||
|
||||
_Add = _F + _Ad;
|
||||
_Bdd = _Bd - _H;
|
||||
|
||||
_Fd = _F - _Ad;
|
||||
_Hd = _Bd + _H;
|
||||
|
||||
_Gd += IdctAdjustBeforeShift;
|
||||
_Add += IdctAdjustBeforeShift;
|
||||
_Ed += IdctAdjustBeforeShift;
|
||||
_Fd += IdctAdjustBeforeShift;
|
||||
|
||||
/* Final sequence of operations over-write original inputs. */
|
||||
op[0*8] = (ogg_int16_t)((_Gd + _Cd ) >> 4);
|
||||
op[7*8] = (ogg_int16_t)((_Gd - _Cd ) >> 4);
|
||||
|
||||
op[1*8] = (ogg_int16_t)((_Add + _Hd ) >> 4);
|
||||
op[2*8] = (ogg_int16_t)((_Add - _Hd ) >> 4);
|
||||
|
||||
op[3*8] = (ogg_int16_t)((_Ed + _Dd ) >> 4);
|
||||
op[4*8] = (ogg_int16_t)((_Ed - _Dd ) >> 4);
|
||||
|
||||
op[5*8] = (ogg_int16_t)((_Fd + _Bdd ) >> 4);
|
||||
op[6*8] = (ogg_int16_t)((_Fd - _Bdd ) >> 4);
|
||||
}else{
|
||||
op[0*8] = 0;
|
||||
op[7*8] = 0;
|
||||
op[1*8] = 0;
|
||||
op[2*8] = 0;
|
||||
op[3*8] = 0;
|
||||
op[4*8] = 0;
|
||||
op[5*8] = 0;
|
||||
op[6*8] = 0;
|
||||
}
|
||||
|
||||
ip++; /* next column */
|
||||
op++;
|
||||
}
|
||||
}
|
||||
|
||||
/************************
|
||||
x x x x 0 0 0 0
|
||||
x x x 0 0 0 0 0
|
||||
x x 0 0 0 0 0 0
|
||||
x 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
*************************/
|
||||
|
||||
static void dequant_slow10( ogg_int16_t * dequant_coeffs,
|
||||
ogg_int16_t * quantized_list,
|
||||
ogg_int32_t * DCT_block){
|
||||
int i;
|
||||
memset(DCT_block,0, 128);
|
||||
for(i=0;i<10;i++)
|
||||
DCT_block[dequant_index[i]] = quantized_list[i] * dequant_coeffs[i];
|
||||
|
||||
}
|
||||
|
||||
void IDct10( Q_LIST_ENTRY * InputData,
|
||||
ogg_int16_t *QuantMatrix,
|
||||
ogg_int16_t * OutputData ){
|
||||
ogg_int32_t IntermediateData[64];
|
||||
ogg_int32_t * ip = IntermediateData;
|
||||
ogg_int16_t * op = OutputData;
|
||||
|
||||
ogg_int32_t _A, _B, _C, _D, _Ad, _Bd, _Cd, _Dd, _E, _F, _G, _H;
|
||||
ogg_int32_t _Ed, _Gd, _Add, _Bdd, _Fd, _Hd;
|
||||
ogg_int32_t t1, t2;
|
||||
|
||||
int loop;
|
||||
|
||||
dequant_slow10( QuantMatrix, InputData, IntermediateData);
|
||||
|
||||
/* Inverse DCT on the rows now */
|
||||
for ( loop = 0; loop < 4; loop++){
|
||||
/* Check for non-zero values */
|
||||
if ( ip[0] | ip[1] | ip[2] | ip[3] ){
|
||||
t1 = (xC1S7 * ip[1]);
|
||||
t1 >>= 16;
|
||||
_A = t1;
|
||||
|
||||
t1 = (xC7S1 * ip[1]);
|
||||
t1 >>= 16;
|
||||
_B = t1 ;
|
||||
|
||||
t1 = (xC3S5 * ip[3]);
|
||||
t1 >>= 16;
|
||||
_C = t1;
|
||||
|
||||
t2 = (xC5S3 * ip[3]);
|
||||
t2 >>= 16;
|
||||
_D = -t2;
|
||||
|
||||
|
||||
t1 = (xC4S4 * (_A - _C));
|
||||
t1 >>= 16;
|
||||
_Ad = t1;
|
||||
|
||||
t1 = (xC4S4 * (_B - _D));
|
||||
t1 >>= 16;
|
||||
_Bd = t1;
|
||||
|
||||
|
||||
_Cd = _A + _C;
|
||||
_Dd = _B + _D;
|
||||
|
||||
t1 = (xC4S4 * ip[0] );
|
||||
t1 >>= 16;
|
||||
_E = t1;
|
||||
|
||||
_F = t1;
|
||||
|
||||
t1 = (xC2S6 * ip[2]);
|
||||
t1 >>= 16;
|
||||
_G = t1;
|
||||
|
||||
t1 = (xC6S2 * ip[2]);
|
||||
t1 >>= 16;
|
||||
_H = t1 ;
|
||||
|
||||
|
||||
_Ed = _E - _G;
|
||||
_Gd = _E + _G;
|
||||
|
||||
_Add = _F + _Ad;
|
||||
_Bdd = _Bd - _H;
|
||||
|
||||
_Fd = _F - _Ad;
|
||||
_Hd = _Bd + _H;
|
||||
|
||||
/* Final sequence of operations over-write original inputs. */
|
||||
ip[0] = (ogg_int16_t)((_Gd + _Cd ) >> 0);
|
||||
ip[7] = (ogg_int16_t)((_Gd - _Cd ) >> 0);
|
||||
|
||||
ip[1] = (ogg_int16_t)((_Add + _Hd ) >> 0);
|
||||
ip[2] = (ogg_int16_t)((_Add - _Hd ) >> 0);
|
||||
|
||||
ip[3] = (ogg_int16_t)((_Ed + _Dd ) >> 0);
|
||||
ip[4] = (ogg_int16_t)((_Ed - _Dd ) >> 0);
|
||||
|
||||
ip[5] = (ogg_int16_t)((_Fd + _Bdd ) >> 0);
|
||||
ip[6] = (ogg_int16_t)((_Fd - _Bdd ) >> 0);
|
||||
|
||||
}
|
||||
|
||||
ip += 8; /* next row */
|
||||
}
|
||||
|
||||
ip = IntermediateData;
|
||||
|
||||
for ( loop = 0; loop < 8; loop++) {
|
||||
/* Check for non-zero values (bitwise or faster than ||) */
|
||||
if ( ip[0 * 8] | ip[1 * 8] | ip[2 * 8] | ip[3 * 8] ) {
|
||||
|
||||
t1 = (xC1S7 * ip[1*8]);
|
||||
t1 >>= 16;
|
||||
_A = t1 ;
|
||||
|
||||
t1 = (xC7S1 * ip[1*8]);
|
||||
t1 >>= 16;
|
||||
_B = t1 ;
|
||||
|
||||
t1 = (xC3S5 * ip[3*8]);
|
||||
t1 >>= 16;
|
||||
_C = t1 ;
|
||||
|
||||
t2 = (xC5S3 * ip[3*8]);
|
||||
t2 >>= 16;
|
||||
_D = - t2;
|
||||
|
||||
|
||||
t1 = (xC4S4 * (_A - _C));
|
||||
t1 >>= 16;
|
||||
_Ad = t1;
|
||||
|
||||
t1 = (xC4S4 * (_B - _D));
|
||||
t1 >>= 16;
|
||||
_Bd = t1;
|
||||
|
||||
|
||||
_Cd = _A + _C;
|
||||
_Dd = _B + _D;
|
||||
|
||||
t1 = (xC4S4 * ip[0*8]);
|
||||
t1 >>= 16;
|
||||
_E = t1;
|
||||
_F = t1;
|
||||
|
||||
t1 = (xC2S6 * ip[2*8]);
|
||||
t1 >>= 16;
|
||||
_G = t1;
|
||||
|
||||
t1 = (xC6S2 * ip[2*8]);
|
||||
t1 >>= 16;
|
||||
_H = t1;
|
||||
|
||||
|
||||
_Ed = _E - _G;
|
||||
_Gd = _E + _G;
|
||||
|
||||
_Add = _F + _Ad;
|
||||
_Bdd = _Bd - _H;
|
||||
|
||||
_Fd = _F - _Ad;
|
||||
_Hd = _Bd + _H;
|
||||
|
||||
_Gd += IdctAdjustBeforeShift;
|
||||
_Add += IdctAdjustBeforeShift;
|
||||
_Ed += IdctAdjustBeforeShift;
|
||||
_Fd += IdctAdjustBeforeShift;
|
||||
|
||||
/* Final sequence of operations over-write original inputs. */
|
||||
op[0*8] = (ogg_int16_t)((_Gd + _Cd ) >> 4);
|
||||
op[7*8] = (ogg_int16_t)((_Gd - _Cd ) >> 4);
|
||||
|
||||
op[1*8] = (ogg_int16_t)((_Add + _Hd ) >> 4);
|
||||
op[2*8] = (ogg_int16_t)((_Add - _Hd ) >> 4);
|
||||
|
||||
op[3*8] = (ogg_int16_t)((_Ed + _Dd ) >> 4);
|
||||
op[4*8] = (ogg_int16_t)((_Ed - _Dd ) >> 4);
|
||||
|
||||
op[5*8] = (ogg_int16_t)((_Fd + _Bdd ) >> 4);
|
||||
op[6*8] = (ogg_int16_t)((_Fd - _Bdd ) >> 4);
|
||||
}else{
|
||||
op[0*8] = 0;
|
||||
op[7*8] = 0;
|
||||
op[1*8] = 0;
|
||||
op[2*8] = 0;
|
||||
op[3*8] = 0;
|
||||
op[4*8] = 0;
|
||||
op[5*8] = 0;
|
||||
op[6*8] = 0;
|
||||
}
|
||||
|
||||
ip++; /* next column */
|
||||
op++;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************
|
||||
x 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0
|
||||
**************************/
|
||||
|
||||
void IDct1( Q_LIST_ENTRY * InputData,
|
||||
ogg_int16_t *QuantMatrix,
|
||||
ogg_int16_t * OutputData ){
|
||||
int loop;
|
||||
|
||||
ogg_int16_t OutD;
|
||||
|
||||
OutD=(ogg_int16_t) ((ogg_int32_t)(InputData[0]*QuantMatrix[0]+15)>>5);
|
||||
|
||||
for(loop=0;loop<64;loop++)
|
||||
OutputData[loop]=OutD;
|
||||
|
||||
}
|
947
src/add-ons/media/plugins/theora/libtheora/mcomp.c
Normal file
947
src/add-ons/media/plugins/theora/libtheora/mcomp.c
Normal file
@ -0,0 +1,947 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2003 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function:
|
||||
last mod: $Id: mcomp.c,v 1.1 2004/02/24 13:50:13 shatty Exp $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "encoder_internal.h"
|
||||
|
||||
/* Initialises motion compentsation. */
|
||||
void InitMotionCompensation ( CP_INSTANCE *cpi ){
|
||||
int i;
|
||||
int SearchSite=0;
|
||||
int Len;
|
||||
int LineStepY = (ogg_int32_t)cpi->pb.YStride;
|
||||
|
||||
Len=((MAX_MV_EXTENT/2)+1)/2;
|
||||
|
||||
|
||||
/* How many search stages are there. */
|
||||
cpi->MVSearchSteps = 0;
|
||||
|
||||
/* Set up offsets arrays used in half pixel correction. */
|
||||
cpi->HalfPixelRef2Offset[0] = -LineStepY - 1;
|
||||
cpi->HalfPixelRef2Offset[1] = -LineStepY;
|
||||
cpi->HalfPixelRef2Offset[2] = -LineStepY + 1;
|
||||
cpi->HalfPixelRef2Offset[3] = - 1;
|
||||
cpi->HalfPixelRef2Offset[4] = 0;
|
||||
cpi->HalfPixelRef2Offset[5] = 1;
|
||||
cpi->HalfPixelRef2Offset[6] = LineStepY - 1;
|
||||
cpi->HalfPixelRef2Offset[7] = LineStepY;
|
||||
cpi->HalfPixelRef2Offset[8] = LineStepY + 1;
|
||||
|
||||
cpi->HalfPixelXOffset[0] = -1;
|
||||
cpi->HalfPixelXOffset[1] = 0;
|
||||
cpi->HalfPixelXOffset[2] = 1;
|
||||
cpi->HalfPixelXOffset[3] = -1;
|
||||
cpi->HalfPixelXOffset[4] = 0;
|
||||
cpi->HalfPixelXOffset[5] = 1;
|
||||
cpi->HalfPixelXOffset[6] = -1;
|
||||
cpi->HalfPixelXOffset[7] = 0;
|
||||
cpi->HalfPixelXOffset[8] = 1;
|
||||
|
||||
cpi->HalfPixelYOffset[0] = -1;
|
||||
cpi->HalfPixelYOffset[1] = -1;
|
||||
cpi->HalfPixelYOffset[2] = -1;
|
||||
cpi->HalfPixelYOffset[3] = 0;
|
||||
cpi->HalfPixelYOffset[4] = 0;
|
||||
cpi->HalfPixelYOffset[5] = 0;
|
||||
cpi->HalfPixelYOffset[6] = 1;
|
||||
cpi->HalfPixelYOffset[7] = 1;
|
||||
cpi->HalfPixelYOffset[8] = 1;
|
||||
|
||||
|
||||
/* Generate offsets for 8 search sites per step. */
|
||||
while ( Len>0 ) {
|
||||
/* Another step. */
|
||||
cpi->MVSearchSteps += 1;
|
||||
|
||||
/* Compute offsets for search sites. */
|
||||
cpi->MVOffsetX[SearchSite] = -Len;
|
||||
cpi->MVOffsetY[SearchSite++] = -Len;
|
||||
cpi->MVOffsetX[SearchSite] = 0;
|
||||
cpi->MVOffsetY[SearchSite++] = -Len;
|
||||
cpi->MVOffsetX[SearchSite] = Len;
|
||||
cpi->MVOffsetY[SearchSite++] = -Len;
|
||||
cpi->MVOffsetX[SearchSite] = -Len;
|
||||
cpi->MVOffsetY[SearchSite++] = 0;
|
||||
cpi->MVOffsetX[SearchSite] = Len;
|
||||
cpi->MVOffsetY[SearchSite++] = 0;
|
||||
cpi->MVOffsetX[SearchSite] = -Len;
|
||||
cpi->MVOffsetY[SearchSite++] = Len;
|
||||
cpi->MVOffsetX[SearchSite] = 0;
|
||||
cpi->MVOffsetY[SearchSite++] = Len;
|
||||
cpi->MVOffsetX[SearchSite] = Len;
|
||||
cpi->MVOffsetY[SearchSite++] = Len;
|
||||
|
||||
/* Contract. */
|
||||
Len /= 2;
|
||||
}
|
||||
|
||||
/* Compute pixel index offsets. */
|
||||
for ( i=SearchSite-1; i>=0; i-- )
|
||||
cpi->MVPixelOffsetY[i] = (cpi->MVOffsetY[i]*LineStepY) + cpi->MVOffsetX[i];
|
||||
}
|
||||
|
||||
static ogg_uint32_t GetInterErr (unsigned char * NewDataPtr,
|
||||
unsigned char * RefDataPtr1,
|
||||
unsigned char * RefDataPtr2,
|
||||
ogg_uint32_t PixelsPerLine ) {
|
||||
ogg_uint32_t i;
|
||||
ogg_int32_t XSum=0;
|
||||
ogg_int32_t XXSum=0;
|
||||
ogg_int32_t DiffVal;
|
||||
ogg_int32_t AbsRefOffset = abs((int)(RefDataPtr1 - RefDataPtr2));
|
||||
|
||||
/* Mode of interpolation chosen based upon on the offset of the
|
||||
second reference pointer */
|
||||
if ( AbsRefOffset == 0 ) {
|
||||
for ( i=0; i<BLOCK_HEIGHT_WIDTH; i++ ) {
|
||||
DiffVal = ((int)NewDataPtr[0]) - (int)RefDataPtr1[0];
|
||||
XSum += DiffVal;
|
||||
|
||||
/* negative array indexes are strictly forbidden by ANSI C and C99 */
|
||||
XXSum += DiffVal*DiffVal;
|
||||
|
||||
DiffVal = ((int)NewDataPtr[1]) - (int)RefDataPtr1[1];
|
||||
XSum += DiffVal;
|
||||
XXSum += DiffVal*DiffVal;
|
||||
|
||||
DiffVal = ((int)NewDataPtr[2]) - (int)RefDataPtr1[2];
|
||||
XSum += DiffVal;
|
||||
XXSum += DiffVal*DiffVal;
|
||||
|
||||
DiffVal = ((int)NewDataPtr[3]) - (int)RefDataPtr1[3];
|
||||
XSum += DiffVal;
|
||||
XXSum += DiffVal*DiffVal;
|
||||
|
||||
DiffVal = ((int)NewDataPtr[4]) - (int)RefDataPtr1[4];
|
||||
XSum += DiffVal;
|
||||
XXSum += DiffVal*DiffVal;
|
||||
|
||||
DiffVal = ((int)NewDataPtr[5]) - (int)RefDataPtr1[5];
|
||||
XSum += DiffVal;
|
||||
XXSum += DiffVal*DiffVal;
|
||||
|
||||
DiffVal = ((int)NewDataPtr[6]) - (int)RefDataPtr1[6];
|
||||
XSum += DiffVal;
|
||||
XXSum += DiffVal*DiffVal;
|
||||
|
||||
DiffVal = ((int)NewDataPtr[7]) - (int)RefDataPtr1[7];
|
||||
XSum += DiffVal;
|
||||
XXSum += DiffVal*DiffVal;
|
||||
|
||||
/* Step to next row of block. */
|
||||
NewDataPtr += PixelsPerLine;
|
||||
RefDataPtr1 += STRIDE_EXTRA + PixelsPerLine;
|
||||
}
|
||||
|
||||
}else{
|
||||
|
||||
/* Simple two reference interpolation */
|
||||
for ( i=0; i<BLOCK_HEIGHT_WIDTH; i++ ) {
|
||||
DiffVal = ((int)NewDataPtr[0]) -
|
||||
(((int)RefDataPtr1[0] + (int)RefDataPtr2[0]) / 2);
|
||||
XSum += DiffVal;
|
||||
XXSum += DiffVal*DiffVal;
|
||||
|
||||
DiffVal = ((int)NewDataPtr[1]) -
|
||||
(((int)RefDataPtr1[1] + (int)RefDataPtr2[1]) / 2);
|
||||
XSum += DiffVal;
|
||||
XXSum += DiffVal*DiffVal;
|
||||
|
||||
DiffVal = ((int)NewDataPtr[2]) -
|
||||
(((int)RefDataPtr1[2] + (int)RefDataPtr2[2]) / 2);
|
||||
XSum += DiffVal;
|
||||
XXSum += DiffVal*DiffVal;
|
||||
|
||||
DiffVal = ((int)NewDataPtr[3]) -
|
||||
(((int)RefDataPtr1[3] + (int)RefDataPtr2[3]) / 2);
|
||||
XSum += DiffVal;
|
||||
XXSum += DiffVal*DiffVal;
|
||||
|
||||
DiffVal = ((int)NewDataPtr[4]) -
|
||||
(((int)RefDataPtr1[4] + (int)RefDataPtr2[4]) / 2);
|
||||
XSum += DiffVal;
|
||||
XXSum += DiffVal*DiffVal;
|
||||
|
||||
DiffVal = ((int)NewDataPtr[5]) -
|
||||
(((int)RefDataPtr1[5] + (int)RefDataPtr2[5]) / 2);
|
||||
XSum += DiffVal;
|
||||
XXSum += DiffVal*DiffVal;
|
||||
|
||||
DiffVal = ((int)NewDataPtr[6]) -
|
||||
(((int)RefDataPtr1[6] + (int)RefDataPtr2[6]) / 2);
|
||||
XSum += DiffVal;
|
||||
XXSum += DiffVal*DiffVal;
|
||||
|
||||
DiffVal = ((int)NewDataPtr[7]) -
|
||||
(((int)RefDataPtr1[7] + (int)RefDataPtr2[7]) / 2);
|
||||
XSum += DiffVal;
|
||||
XXSum += DiffVal*DiffVal;
|
||||
|
||||
/* Step to next row of block. */
|
||||
NewDataPtr += PixelsPerLine;
|
||||
RefDataPtr1 += STRIDE_EXTRA+PixelsPerLine;
|
||||
RefDataPtr2 += STRIDE_EXTRA+PixelsPerLine;
|
||||
}
|
||||
}
|
||||
|
||||
/* Compute and return population variance as mis-match metric. */
|
||||
return (( (XXSum<<6) - XSum*XSum ));
|
||||
}
|
||||
|
||||
static ogg_uint32_t GetSumAbsDiffs (unsigned char * NewDataPtr,
|
||||
unsigned char * RefDataPtr,
|
||||
ogg_uint32_t PixelsPerLine,
|
||||
ogg_uint32_t ErrorSoFar) {
|
||||
ogg_uint32_t i;
|
||||
ogg_uint32_t DiffVal = ErrorSoFar;
|
||||
|
||||
/* Decide on standard or MMX implementation */
|
||||
for ( i=0; i < BLOCK_HEIGHT_WIDTH; i++ ) {
|
||||
DiffVal += abs( ((int)NewDataPtr[0]) - ((int)RefDataPtr[0]) );
|
||||
DiffVal += abs( ((int)NewDataPtr[1]) - ((int)RefDataPtr[1]) );
|
||||
DiffVal += abs( ((int)NewDataPtr[2]) - ((int)RefDataPtr[2]) );
|
||||
DiffVal += abs( ((int)NewDataPtr[3]) - ((int)RefDataPtr[3]) );
|
||||
DiffVal += abs( ((int)NewDataPtr[4]) - ((int)RefDataPtr[4]) );
|
||||
DiffVal += abs( ((int)NewDataPtr[5]) - ((int)RefDataPtr[5]) );
|
||||
DiffVal += abs( ((int)NewDataPtr[6]) - ((int)RefDataPtr[6]) );
|
||||
DiffVal += abs( ((int)NewDataPtr[7]) - ((int)RefDataPtr[7]) );
|
||||
|
||||
/* Step to next row of block. */
|
||||
NewDataPtr += PixelsPerLine;
|
||||
RefDataPtr += STRIDE_EXTRA+PixelsPerLine;
|
||||
}
|
||||
|
||||
return DiffVal;
|
||||
}
|
||||
|
||||
static ogg_uint32_t GetNextSumAbsDiffs (unsigned char * NewDataPtr,
|
||||
unsigned char * RefDataPtr,
|
||||
ogg_uint32_t PixelsPerLine,
|
||||
ogg_uint32_t ErrorSoFar,
|
||||
ogg_uint32_t BestSoFar ) {
|
||||
ogg_uint32_t i;
|
||||
ogg_uint32_t DiffVal = ErrorSoFar;
|
||||
|
||||
for ( i=0; i < BLOCK_HEIGHT_WIDTH; i++ ) {
|
||||
DiffVal += abs( ((int)NewDataPtr[0]) - ((int)RefDataPtr[0]) );
|
||||
DiffVal += abs( ((int)NewDataPtr[1]) - ((int)RefDataPtr[1]) );
|
||||
DiffVal += abs( ((int)NewDataPtr[2]) - ((int)RefDataPtr[2]) );
|
||||
DiffVal += abs( ((int)NewDataPtr[3]) - ((int)RefDataPtr[3]) );
|
||||
DiffVal += abs( ((int)NewDataPtr[4]) - ((int)RefDataPtr[4]) );
|
||||
DiffVal += abs( ((int)NewDataPtr[5]) - ((int)RefDataPtr[5]) );
|
||||
DiffVal += abs( ((int)NewDataPtr[6]) - ((int)RefDataPtr[6]) );
|
||||
DiffVal += abs( ((int)NewDataPtr[7]) - ((int)RefDataPtr[7]) );
|
||||
|
||||
if ( DiffVal > BestSoFar )break;
|
||||
|
||||
/* Step to next row of block. */
|
||||
NewDataPtr += PixelsPerLine;
|
||||
RefDataPtr += STRIDE_EXTRA+PixelsPerLine;
|
||||
}
|
||||
|
||||
return DiffVal;
|
||||
}
|
||||
|
||||
static ogg_uint32_t GetHalfPixelSumAbsDiffs (unsigned char * SrcData,
|
||||
unsigned char * RefDataPtr1,
|
||||
unsigned char * RefDataPtr2,
|
||||
ogg_uint32_t PixelsPerLine,
|
||||
ogg_uint32_t ErrorSoFar,
|
||||
ogg_uint32_t BestSoFar ) {
|
||||
|
||||
ogg_uint32_t i;
|
||||
ogg_uint32_t DiffVal = ErrorSoFar;
|
||||
ogg_int32_t RefOffset = (int)(RefDataPtr1 - RefDataPtr2);
|
||||
ogg_uint32_t RefPixelsPerLine = PixelsPerLine + STRIDE_EXTRA;
|
||||
|
||||
if ( RefOffset == 0 ) {
|
||||
/* Simple case as for non 0.5 pixel */
|
||||
DiffVal += GetSumAbsDiffs( SrcData, RefDataPtr1, PixelsPerLine,
|
||||
ErrorSoFar);
|
||||
} else {
|
||||
for ( i=0; i < BLOCK_HEIGHT_WIDTH; i++ ) {
|
||||
DiffVal += abs( ((int)SrcData[0]) - (((int)RefDataPtr1[0] +
|
||||
(int)RefDataPtr2[0]) / 2) );
|
||||
DiffVal += abs( ((int)SrcData[1]) - (((int)RefDataPtr1[1] +
|
||||
(int)RefDataPtr2[1]) / 2) );
|
||||
DiffVal += abs( ((int)SrcData[2]) - (((int)RefDataPtr1[2] +
|
||||
(int)RefDataPtr2[2]) / 2) );
|
||||
DiffVal += abs( ((int)SrcData[3]) - (((int)RefDataPtr1[3] +
|
||||
(int)RefDataPtr2[3]) / 2) );
|
||||
DiffVal += abs( ((int)SrcData[4]) - (((int)RefDataPtr1[4] +
|
||||
(int)RefDataPtr2[4]) / 2) );
|
||||
DiffVal += abs( ((int)SrcData[5]) - (((int)RefDataPtr1[5] +
|
||||
(int)RefDataPtr2[5]) / 2) );
|
||||
DiffVal += abs( ((int)SrcData[6]) - (((int)RefDataPtr1[6] +
|
||||
(int)RefDataPtr2[6]) / 2) );
|
||||
DiffVal += abs( ((int)SrcData[7]) - (((int)RefDataPtr1[7] +
|
||||
(int)RefDataPtr2[7]) / 2) );
|
||||
|
||||
if ( DiffVal > BestSoFar ) break;
|
||||
|
||||
/* Step to next row of block. */
|
||||
SrcData += PixelsPerLine;
|
||||
RefDataPtr1 += RefPixelsPerLine;
|
||||
RefDataPtr2 += RefPixelsPerLine;
|
||||
}
|
||||
}
|
||||
|
||||
return DiffVal;
|
||||
}
|
||||
|
||||
static ogg_uint32_t GetIntraError (unsigned char * DataPtr,
|
||||
ogg_uint32_t PixelsPerLine ) {
|
||||
ogg_uint32_t i;
|
||||
ogg_uint32_t XSum=0;
|
||||
ogg_uint32_t XXSum=0;
|
||||
unsigned char *DiffPtr;
|
||||
|
||||
/* Loop expanded out for speed. */
|
||||
DiffPtr = DataPtr;
|
||||
|
||||
for ( i=0; i<BLOCK_HEIGHT_WIDTH; i++ ) {
|
||||
|
||||
/* Examine alternate pixel locations. */
|
||||
XSum += DiffPtr[0];
|
||||
XXSum += DiffPtr[0]*DiffPtr[0];
|
||||
XSum += DiffPtr[1];
|
||||
XXSum += DiffPtr[1]*DiffPtr[1];
|
||||
XSum += DiffPtr[2];
|
||||
XXSum += DiffPtr[2]*DiffPtr[2];
|
||||
XSum += DiffPtr[3];
|
||||
XXSum += DiffPtr[3]*DiffPtr[3];
|
||||
XSum += DiffPtr[4];
|
||||
XXSum += DiffPtr[4]*DiffPtr[4];
|
||||
XSum += DiffPtr[5];
|
||||
XXSum += DiffPtr[5]*DiffPtr[5];
|
||||
XSum += DiffPtr[6];
|
||||
XXSum += DiffPtr[6]*DiffPtr[6];
|
||||
XSum += DiffPtr[7];
|
||||
XXSum += DiffPtr[7]*DiffPtr[7];
|
||||
|
||||
/* Step to next row of block. */
|
||||
DiffPtr += PixelsPerLine;
|
||||
}
|
||||
|
||||
/* Compute population variance as mis-match metric. */
|
||||
return (( (XXSum<<6) - XSum*XSum ) );
|
||||
}
|
||||
|
||||
ogg_uint32_t GetMBIntraError (CP_INSTANCE *cpi, ogg_uint32_t FragIndex,
|
||||
ogg_uint32_t PixelsPerLine ) {
|
||||
ogg_uint32_t LocalFragIndex = FragIndex;
|
||||
ogg_uint32_t IntraError = 0;
|
||||
|
||||
/* Add together the intra errors for those blocks in the macro block
|
||||
that are coded (Y only) */
|
||||
if ( cpi->pb.display_fragments[LocalFragIndex] )
|
||||
IntraError +=
|
||||
GetIntraError(&cpi->
|
||||
ConvDestBuffer[cpi->pb.pixel_index_table[LocalFragIndex]],
|
||||
PixelsPerLine );
|
||||
|
||||
|
||||
LocalFragIndex++;
|
||||
if ( cpi->pb.display_fragments[LocalFragIndex] )
|
||||
IntraError +=
|
||||
GetIntraError(&cpi->
|
||||
ConvDestBuffer[cpi->pb.pixel_index_table[LocalFragIndex]],
|
||||
PixelsPerLine );
|
||||
|
||||
LocalFragIndex = FragIndex + cpi->pb.HFragments;
|
||||
if ( cpi->pb.display_fragments[LocalFragIndex] )
|
||||
IntraError +=
|
||||
GetIntraError(&cpi->
|
||||
ConvDestBuffer[cpi->pb.pixel_index_table[LocalFragIndex]],
|
||||
PixelsPerLine );
|
||||
|
||||
LocalFragIndex++;
|
||||
if ( cpi->pb.display_fragments[LocalFragIndex] )
|
||||
IntraError +=
|
||||
GetIntraError(&cpi->
|
||||
ConvDestBuffer[cpi->pb.pixel_index_table[LocalFragIndex]],
|
||||
PixelsPerLine );
|
||||
|
||||
return IntraError;
|
||||
}
|
||||
|
||||
ogg_uint32_t GetMBInterError (CP_INSTANCE *cpi,
|
||||
unsigned char * SrcPtr,
|
||||
unsigned char * RefPtr,
|
||||
ogg_uint32_t FragIndex,
|
||||
ogg_int32_t LastXMV,
|
||||
ogg_int32_t LastYMV,
|
||||
ogg_uint32_t PixelsPerLine ) {
|
||||
ogg_uint32_t RefPixelsPerLine = cpi->pb.YStride;
|
||||
ogg_uint32_t LocalFragIndex = FragIndex;
|
||||
ogg_int32_t PixelIndex;
|
||||
ogg_int32_t RefPixelIndex;
|
||||
ogg_int32_t RefPixelOffset;
|
||||
ogg_int32_t RefPtr2Offset;
|
||||
|
||||
ogg_uint32_t InterError = 0;
|
||||
|
||||
unsigned char * SrcPtr1;
|
||||
unsigned char * RefPtr1;
|
||||
|
||||
/* Work out pixel offset into source buffer. */
|
||||
PixelIndex = cpi->pb.pixel_index_table[LocalFragIndex];
|
||||
|
||||
/* Work out the pixel offset in reference buffer for the default
|
||||
motion vector */
|
||||
RefPixelIndex = cpi->pb.recon_pixel_index_table[LocalFragIndex];
|
||||
RefPixelOffset = ((LastYMV/2) * RefPixelsPerLine) + (LastXMV/2);
|
||||
|
||||
/* Work out the second reference pointer offset. */
|
||||
RefPtr2Offset = 0;
|
||||
if ( LastXMV % 2 ) {
|
||||
if ( LastXMV > 0 )
|
||||
RefPtr2Offset += 1;
|
||||
else
|
||||
RefPtr2Offset -= 1;
|
||||
}
|
||||
if ( LastYMV % 2 ) {
|
||||
if ( LastYMV > 0 )
|
||||
RefPtr2Offset += RefPixelsPerLine;
|
||||
else
|
||||
RefPtr2Offset -= RefPixelsPerLine;
|
||||
}
|
||||
|
||||
/* Add together the errors for those blocks in the macro block that
|
||||
are coded (Y only) */
|
||||
if ( cpi->pb.display_fragments[LocalFragIndex] ) {
|
||||
SrcPtr1 = &SrcPtr[PixelIndex];
|
||||
RefPtr1 = &RefPtr[RefPixelIndex + RefPixelOffset];
|
||||
InterError += GetInterErr( SrcPtr1, RefPtr1,
|
||||
&RefPtr1[RefPtr2Offset], PixelsPerLine );
|
||||
}
|
||||
|
||||
LocalFragIndex++;
|
||||
if ( cpi->pb.display_fragments[LocalFragIndex] ) {
|
||||
PixelIndex = cpi->pb.pixel_index_table[LocalFragIndex];
|
||||
RefPixelIndex = cpi->pb.recon_pixel_index_table[LocalFragIndex];
|
||||
SrcPtr1 = &SrcPtr[PixelIndex];
|
||||
RefPtr1 = &RefPtr[RefPixelIndex + RefPixelOffset];
|
||||
InterError += GetInterErr( SrcPtr1, RefPtr1,
|
||||
&RefPtr1[RefPtr2Offset], PixelsPerLine );
|
||||
|
||||
}
|
||||
|
||||
LocalFragIndex = FragIndex + cpi->pb.HFragments;
|
||||
if ( cpi->pb.display_fragments[LocalFragIndex] ) {
|
||||
PixelIndex = cpi->pb.pixel_index_table[LocalFragIndex];
|
||||
RefPixelIndex = cpi->pb.recon_pixel_index_table[LocalFragIndex];
|
||||
SrcPtr1 = &SrcPtr[PixelIndex];
|
||||
RefPtr1 = &RefPtr[RefPixelIndex + RefPixelOffset];
|
||||
InterError += GetInterErr( SrcPtr1, RefPtr1,
|
||||
&RefPtr1[RefPtr2Offset], PixelsPerLine );
|
||||
}
|
||||
|
||||
LocalFragIndex++;
|
||||
if ( cpi->pb.display_fragments[LocalFragIndex] ) {
|
||||
PixelIndex = cpi->pb.pixel_index_table[LocalFragIndex];
|
||||
RefPixelIndex = cpi->pb.recon_pixel_index_table[LocalFragIndex];
|
||||
SrcPtr1 = &SrcPtr[PixelIndex];
|
||||
RefPtr1 = &RefPtr[RefPixelIndex + RefPixelOffset];
|
||||
InterError += GetInterErr( SrcPtr1, RefPtr1,
|
||||
&RefPtr1[RefPtr2Offset], PixelsPerLine );
|
||||
}
|
||||
return InterError;
|
||||
}
|
||||
|
||||
ogg_uint32_t GetMBMVInterError (CP_INSTANCE *cpi,
|
||||
unsigned char * RefFramePtr,
|
||||
ogg_uint32_t FragIndex,
|
||||
ogg_uint32_t PixelsPerLine,
|
||||
ogg_int32_t *MVPixelOffset,
|
||||
MOTION_VECTOR *MV ) {
|
||||
ogg_uint32_t Error = 0;
|
||||
ogg_uint32_t MinError;
|
||||
ogg_uint32_t InterMVError = 0;
|
||||
|
||||
ogg_int32_t i;
|
||||
ogg_int32_t x=0, y=0;
|
||||
ogg_int32_t step;
|
||||
ogg_int32_t SearchSite=0;
|
||||
|
||||
unsigned char *SrcPtr[4] = {NULL,NULL,NULL,NULL};
|
||||
unsigned char *RefPtr=NULL;
|
||||
unsigned char *CandidateBlockPtr=NULL;
|
||||
unsigned char *BestBlockPtr=NULL;
|
||||
|
||||
ogg_uint32_t RefRow2Offset = cpi->pb.YStride * 8;
|
||||
|
||||
int MBlockDispFrags[4];
|
||||
|
||||
/* Half pixel variables */
|
||||
ogg_int32_t HalfPixelError;
|
||||
ogg_int32_t BestHalfPixelError;
|
||||
unsigned char BestHalfOffset;
|
||||
unsigned char * RefDataPtr1;
|
||||
unsigned char * RefDataPtr2;
|
||||
|
||||
/* Note which of the four blocks in the macro block are to be
|
||||
included in the search. */
|
||||
MBlockDispFrags[0] =
|
||||
cpi->pb.display_fragments[FragIndex];
|
||||
MBlockDispFrags[1] =
|
||||
cpi->pb.display_fragments[FragIndex + 1];
|
||||
MBlockDispFrags[2] =
|
||||
cpi->pb.display_fragments[FragIndex + cpi->pb.HFragments];
|
||||
MBlockDispFrags[3] =
|
||||
cpi->pb.display_fragments[FragIndex + cpi->pb.HFragments + 1];
|
||||
|
||||
/* Set up the source pointers for the four source blocks. */
|
||||
SrcPtr[0] = &cpi->ConvDestBuffer[cpi->pb.pixel_index_table[FragIndex]];
|
||||
SrcPtr[1] = SrcPtr[0] + 8;
|
||||
SrcPtr[2] = SrcPtr[0] + (PixelsPerLine * 8);
|
||||
SrcPtr[3] = SrcPtr[2] + 8;
|
||||
|
||||
/* Set starting reference point for search. */
|
||||
RefPtr = &RefFramePtr[cpi->pb.recon_pixel_index_table[FragIndex]];
|
||||
|
||||
/* Check the 0,0 candidate. */
|
||||
if ( MBlockDispFrags[0] ) {
|
||||
Error = GetSumAbsDiffs( SrcPtr[0], RefPtr,
|
||||
PixelsPerLine, Error);
|
||||
}
|
||||
if ( MBlockDispFrags[1] ) {
|
||||
Error = GetSumAbsDiffs( SrcPtr[1], RefPtr + 8,
|
||||
PixelsPerLine, Error);
|
||||
}
|
||||
if ( MBlockDispFrags[2] ) {
|
||||
Error = GetSumAbsDiffs( SrcPtr[2], RefPtr + RefRow2Offset,
|
||||
PixelsPerLine, Error);
|
||||
}
|
||||
if ( MBlockDispFrags[3] ) {
|
||||
Error = GetSumAbsDiffs( SrcPtr[3], RefPtr + RefRow2Offset + 8,
|
||||
PixelsPerLine, Error);
|
||||
}
|
||||
|
||||
/* Set starting values to results of 0, 0 vector. */
|
||||
MinError = Error;
|
||||
BestBlockPtr = RefPtr;
|
||||
x = 0;
|
||||
y = 0;
|
||||
MV->x = 0;
|
||||
MV->y = 0;
|
||||
|
||||
/* Proceed through N-steps. */
|
||||
for ( step=0; step<cpi->MVSearchSteps; step++ ) {
|
||||
/* Search the 8-neighbours at distance pertinent to current step.*/
|
||||
for ( i=0; i<8; i++ ) {
|
||||
/* Set pointer to next candidate matching block. */
|
||||
CandidateBlockPtr = RefPtr + MVPixelOffset[SearchSite];
|
||||
|
||||
/* Reset error */
|
||||
Error = 0;
|
||||
|
||||
/* Get the score for the current offset */
|
||||
if ( MBlockDispFrags[0] ) {
|
||||
Error = GetSumAbsDiffs( SrcPtr[0], CandidateBlockPtr,
|
||||
PixelsPerLine, Error);
|
||||
}
|
||||
|
||||
if ( MBlockDispFrags[1] && (Error < MinError) ) {
|
||||
Error = GetNextSumAbsDiffs( SrcPtr[1], CandidateBlockPtr + 8,
|
||||
PixelsPerLine, Error, MinError );
|
||||
}
|
||||
|
||||
if ( MBlockDispFrags[2] && (Error < MinError) ) {
|
||||
Error = GetNextSumAbsDiffs( SrcPtr[2], CandidateBlockPtr + RefRow2Offset,
|
||||
PixelsPerLine, Error, MinError );
|
||||
}
|
||||
|
||||
if ( MBlockDispFrags[3] && (Error < MinError) ) {
|
||||
Error = GetNextSumAbsDiffs( SrcPtr[3],
|
||||
CandidateBlockPtr + RefRow2Offset + 8,
|
||||
PixelsPerLine, Error, MinError );
|
||||
}
|
||||
|
||||
if ( Error < MinError ) {
|
||||
/* Remember best match. */
|
||||
MinError = Error;
|
||||
BestBlockPtr = CandidateBlockPtr;
|
||||
|
||||
/* Where is it. */
|
||||
x = MV->x + cpi->MVOffsetX[SearchSite];
|
||||
y = MV->y + cpi->MVOffsetY[SearchSite];
|
||||
}
|
||||
|
||||
/* Move to next search location. */
|
||||
SearchSite += 1;
|
||||
}
|
||||
|
||||
/* Move to best location this step. */
|
||||
RefPtr = BestBlockPtr;
|
||||
MV->x = x;
|
||||
MV->y = y;
|
||||
}
|
||||
|
||||
/* Factor vectors to 1/2 pixel resoultion. */
|
||||
MV->x = (MV->x * 2);
|
||||
MV->y = (MV->y * 2);
|
||||
|
||||
/* Now do the half pixel pass */
|
||||
BestHalfOffset = 4; /* Default to the no offset case. */
|
||||
BestHalfPixelError = MinError;
|
||||
|
||||
/* Get the half pixel error for each half pixel offset */
|
||||
for ( i=0; i < 9; i++ ) {
|
||||
HalfPixelError = 0;
|
||||
|
||||
if ( MBlockDispFrags[0] ) {
|
||||
RefDataPtr1 = BestBlockPtr;
|
||||
RefDataPtr2 = RefDataPtr1 + cpi->HalfPixelRef2Offset[i];
|
||||
HalfPixelError =
|
||||
GetHalfPixelSumAbsDiffs( SrcPtr[0], RefDataPtr1, RefDataPtr2,
|
||||
PixelsPerLine, HalfPixelError, BestHalfPixelError );
|
||||
}
|
||||
|
||||
if ( MBlockDispFrags[1] && (HalfPixelError < BestHalfPixelError) ) {
|
||||
RefDataPtr1 = BestBlockPtr + 8;
|
||||
RefDataPtr2 = RefDataPtr1 + cpi->HalfPixelRef2Offset[i];
|
||||
HalfPixelError =
|
||||
GetHalfPixelSumAbsDiffs( SrcPtr[1], RefDataPtr1, RefDataPtr2,
|
||||
PixelsPerLine, HalfPixelError, BestHalfPixelError );
|
||||
}
|
||||
|
||||
if ( MBlockDispFrags[2] && (HalfPixelError < BestHalfPixelError) ) {
|
||||
RefDataPtr1 = BestBlockPtr + RefRow2Offset;
|
||||
RefDataPtr2 = RefDataPtr1 + cpi->HalfPixelRef2Offset[i];
|
||||
HalfPixelError =
|
||||
GetHalfPixelSumAbsDiffs( SrcPtr[2], RefDataPtr1, RefDataPtr2,
|
||||
PixelsPerLine, HalfPixelError, BestHalfPixelError );
|
||||
}
|
||||
|
||||
if ( MBlockDispFrags[3] && (HalfPixelError < BestHalfPixelError) ) {
|
||||
RefDataPtr1 = BestBlockPtr + RefRow2Offset + 8;
|
||||
RefDataPtr2 = RefDataPtr1 + cpi->HalfPixelRef2Offset[i];
|
||||
HalfPixelError =
|
||||
GetHalfPixelSumAbsDiffs( SrcPtr[3], RefDataPtr1, RefDataPtr2,
|
||||
PixelsPerLine, HalfPixelError, BestHalfPixelError );
|
||||
}
|
||||
|
||||
if ( HalfPixelError < BestHalfPixelError ) {
|
||||
BestHalfOffset = (unsigned char)i;
|
||||
BestHalfPixelError = HalfPixelError;
|
||||
}
|
||||
}
|
||||
|
||||
/* Half pixel adjust the MV */
|
||||
MV->x += cpi->HalfPixelXOffset[BestHalfOffset];
|
||||
MV->y += cpi->HalfPixelYOffset[BestHalfOffset];
|
||||
|
||||
/* Get the error score for the chosen 1/2 pixel offset as a variance. */
|
||||
InterMVError = GetMBInterError( cpi, cpi->ConvDestBuffer, RefFramePtr,
|
||||
FragIndex, MV->x, MV->y, PixelsPerLine );
|
||||
|
||||
/* Return score of best matching block. */
|
||||
return InterMVError;
|
||||
}
|
||||
|
||||
ogg_uint32_t GetMBMVExhaustiveSearch (CP_INSTANCE *cpi,
|
||||
unsigned char * RefFramePtr,
|
||||
ogg_uint32_t FragIndex,
|
||||
ogg_uint32_t PixelsPerLine,
|
||||
MOTION_VECTOR *MV ) {
|
||||
ogg_uint32_t Error = 0;
|
||||
ogg_uint32_t MinError = HUGE_ERROR;
|
||||
ogg_uint32_t InterMVError = 0;
|
||||
|
||||
ogg_int32_t i, j;
|
||||
ogg_int32_t x=0, y=0;
|
||||
|
||||
unsigned char *SrcPtr[4] = {NULL,NULL,NULL,NULL};
|
||||
unsigned char *RefPtr;
|
||||
unsigned char *CandidateBlockPtr=NULL;
|
||||
unsigned char *BestBlockPtr=NULL;
|
||||
|
||||
ogg_uint32_t RefRow2Offset = cpi->pb.YStride * 8;
|
||||
|
||||
int MBlockDispFrags[4];
|
||||
|
||||
/* Half pixel variables */
|
||||
ogg_int32_t HalfPixelError;
|
||||
ogg_int32_t BestHalfPixelError;
|
||||
unsigned char BestHalfOffset;
|
||||
unsigned char * RefDataPtr1;
|
||||
unsigned char * RefDataPtr2;
|
||||
|
||||
/* Note which of the four blocks in the macro block are to be
|
||||
included in the search. */
|
||||
MBlockDispFrags[0] = cpi->
|
||||
pb.display_fragments[FragIndex];
|
||||
MBlockDispFrags[1] = cpi->
|
||||
pb.display_fragments[FragIndex + 1];
|
||||
MBlockDispFrags[2] = cpi->
|
||||
pb.display_fragments[FragIndex + cpi->pb.HFragments];
|
||||
MBlockDispFrags[3] = cpi->
|
||||
pb.display_fragments[FragIndex + cpi->pb.HFragments + 1];
|
||||
|
||||
/* Set up the source pointers for the four source blocks. */
|
||||
SrcPtr[0] = &cpi->
|
||||
ConvDestBuffer[cpi->pb.pixel_index_table[FragIndex]];
|
||||
SrcPtr[1] = SrcPtr[0] + 8;
|
||||
SrcPtr[2] = SrcPtr[0] + (PixelsPerLine * 8);
|
||||
SrcPtr[3] = SrcPtr[2] + 8;
|
||||
|
||||
RefPtr = &RefFramePtr[cpi->pb.recon_pixel_index_table[FragIndex]];
|
||||
RefPtr = RefPtr - ((MAX_MV_EXTENT/2) * cpi->
|
||||
pb.YStride) - (MAX_MV_EXTENT/2);
|
||||
|
||||
/* Search each pixel alligned site */
|
||||
for ( i = 0; i < (ogg_int32_t)MAX_MV_EXTENT; i ++ ) {
|
||||
/* Starting position in row */
|
||||
CandidateBlockPtr = RefPtr;
|
||||
|
||||
for ( j = 0; j < (ogg_int32_t)MAX_MV_EXTENT; j++ ) {
|
||||
/* Reset error */
|
||||
Error = 0;
|
||||
|
||||
/* Summ errors for each block. */
|
||||
if ( MBlockDispFrags[0] ) {
|
||||
Error = GetSumAbsDiffs( SrcPtr[0], CandidateBlockPtr,
|
||||
PixelsPerLine, Error);
|
||||
}
|
||||
if ( MBlockDispFrags[1] ){
|
||||
Error = GetSumAbsDiffs( SrcPtr[1], CandidateBlockPtr + 8,
|
||||
PixelsPerLine, Error);
|
||||
}
|
||||
if ( MBlockDispFrags[2] ){
|
||||
Error = GetSumAbsDiffs( SrcPtr[2], CandidateBlockPtr + RefRow2Offset,
|
||||
PixelsPerLine, Error);
|
||||
}
|
||||
if ( MBlockDispFrags[3] ){
|
||||
Error = GetSumAbsDiffs( SrcPtr[3], CandidateBlockPtr + RefRow2Offset + 8,
|
||||
PixelsPerLine, Error);
|
||||
}
|
||||
|
||||
/* Was this the best so far */
|
||||
if ( Error < MinError ) {
|
||||
MinError = Error;
|
||||
BestBlockPtr = CandidateBlockPtr;
|
||||
x = 16 + j - MAX_MV_EXTENT;
|
||||
y = 16 + i - MAX_MV_EXTENT;
|
||||
}
|
||||
|
||||
/* Move the the next site */
|
||||
CandidateBlockPtr ++;
|
||||
}
|
||||
|
||||
/* Move on to the next row. */
|
||||
RefPtr += cpi->pb.YStride;
|
||||
|
||||
}
|
||||
|
||||
/* Factor vectors to 1/2 pixel resoultion. */
|
||||
MV->x = (x * 2);
|
||||
MV->y = (y * 2);
|
||||
|
||||
/* Now do the half pixel pass */
|
||||
BestHalfOffset = 4; /* Default to the no offset case. */
|
||||
BestHalfPixelError = MinError;
|
||||
|
||||
/* Get the half pixel error for each half pixel offset */
|
||||
for ( i=0; i < 9; i++ ) {
|
||||
HalfPixelError = 0;
|
||||
|
||||
if ( MBlockDispFrags[0] ) {
|
||||
RefDataPtr1 = BestBlockPtr;
|
||||
RefDataPtr2 = RefDataPtr1 + cpi->HalfPixelRef2Offset[i];
|
||||
HalfPixelError =
|
||||
GetHalfPixelSumAbsDiffs( SrcPtr[0], RefDataPtr1, RefDataPtr2,
|
||||
PixelsPerLine, HalfPixelError, BestHalfPixelError );
|
||||
}
|
||||
|
||||
if ( MBlockDispFrags[1] && (HalfPixelError < BestHalfPixelError) ) {
|
||||
RefDataPtr1 = BestBlockPtr + 8;
|
||||
RefDataPtr2 = RefDataPtr1 + cpi->HalfPixelRef2Offset[i];
|
||||
HalfPixelError =
|
||||
GetHalfPixelSumAbsDiffs( SrcPtr[1], RefDataPtr1, RefDataPtr2,
|
||||
PixelsPerLine, HalfPixelError, BestHalfPixelError );
|
||||
}
|
||||
|
||||
if ( MBlockDispFrags[2] && (HalfPixelError < BestHalfPixelError) ) {
|
||||
RefDataPtr1 = BestBlockPtr + RefRow2Offset;
|
||||
RefDataPtr2 = RefDataPtr1 + cpi->HalfPixelRef2Offset[i];
|
||||
HalfPixelError =
|
||||
GetHalfPixelSumAbsDiffs( SrcPtr[2], RefDataPtr1, RefDataPtr2,
|
||||
PixelsPerLine, HalfPixelError, BestHalfPixelError );
|
||||
}
|
||||
|
||||
if ( MBlockDispFrags[3] && (HalfPixelError < BestHalfPixelError) ) {
|
||||
RefDataPtr1 = BestBlockPtr + RefRow2Offset + 8;
|
||||
RefDataPtr2 = RefDataPtr1 + cpi->HalfPixelRef2Offset[i];
|
||||
HalfPixelError =
|
||||
GetHalfPixelSumAbsDiffs( SrcPtr[3], RefDataPtr1, RefDataPtr2,
|
||||
PixelsPerLine, HalfPixelError, BestHalfPixelError );
|
||||
}
|
||||
|
||||
if ( HalfPixelError < BestHalfPixelError ){
|
||||
BestHalfOffset = (unsigned char)i;
|
||||
BestHalfPixelError = HalfPixelError;
|
||||
}
|
||||
}
|
||||
|
||||
/* Half pixel adjust the MV */
|
||||
MV->x += cpi->HalfPixelXOffset[BestHalfOffset];
|
||||
MV->y += cpi->HalfPixelYOffset[BestHalfOffset];
|
||||
|
||||
/* Get the error score for the chosen 1/2 pixel offset as a variance. */
|
||||
InterMVError = GetMBInterError( cpi, cpi->ConvDestBuffer, RefFramePtr,
|
||||
FragIndex, MV->x, MV->y, PixelsPerLine );
|
||||
|
||||
/* Return score of best matching block. */
|
||||
return InterMVError;
|
||||
}
|
||||
|
||||
static ogg_uint32_t GetBMVExhaustiveSearch (CP_INSTANCE *cpi,
|
||||
unsigned char * RefFramePtr,
|
||||
ogg_uint32_t FragIndex,
|
||||
ogg_uint32_t PixelsPerLine,
|
||||
MOTION_VECTOR *MV ) {
|
||||
ogg_uint32_t Error = 0;
|
||||
ogg_uint32_t MinError = HUGE_ERROR;
|
||||
ogg_uint32_t InterMVError = 0;
|
||||
|
||||
ogg_int32_t i, j;
|
||||
ogg_int32_t x=0, y=0;
|
||||
|
||||
unsigned char *SrcPtr = NULL;
|
||||
unsigned char *RefPtr;
|
||||
unsigned char *CandidateBlockPtr=NULL;
|
||||
unsigned char *BestBlockPtr=NULL;
|
||||
|
||||
/* Half pixel variables */
|
||||
ogg_int32_t HalfPixelError;
|
||||
ogg_int32_t BestHalfPixelError;
|
||||
unsigned char BestHalfOffset;
|
||||
unsigned char * RefDataPtr2;
|
||||
|
||||
/* Set up the source pointer for the block. */
|
||||
SrcPtr = &cpi->
|
||||
ConvDestBuffer[cpi->pb.pixel_index_table[FragIndex]];
|
||||
|
||||
RefPtr = &RefFramePtr[cpi->pb.recon_pixel_index_table[FragIndex]];
|
||||
RefPtr = RefPtr - ((MAX_MV_EXTENT/2) *
|
||||
cpi->pb.YStride) - (MAX_MV_EXTENT/2);
|
||||
|
||||
/* Search each pixel alligned site */
|
||||
for ( i = 0; i < (ogg_int32_t)MAX_MV_EXTENT; i ++ ) {
|
||||
/* Starting position in row */
|
||||
CandidateBlockPtr = RefPtr;
|
||||
|
||||
for ( j = 0; j < (ogg_int32_t)MAX_MV_EXTENT; j++ ){
|
||||
/* Get the block error score. */
|
||||
Error = GetSumAbsDiffs( SrcPtr, CandidateBlockPtr,
|
||||
PixelsPerLine, 0);
|
||||
|
||||
/* Was this the best so far */
|
||||
if ( Error < MinError ) {
|
||||
MinError = Error;
|
||||
BestBlockPtr = CandidateBlockPtr;
|
||||
x = 16 + j - MAX_MV_EXTENT;
|
||||
y = 16 + i - MAX_MV_EXTENT;
|
||||
}
|
||||
|
||||
/* Move the the next site */
|
||||
CandidateBlockPtr ++;
|
||||
}
|
||||
|
||||
/* Move on to the next row. */
|
||||
RefPtr += cpi->pb.YStride;
|
||||
}
|
||||
|
||||
/* Factor vectors to 1/2 pixel resoultion. */
|
||||
MV->x = (x * 2);
|
||||
MV->y = (y * 2);
|
||||
|
||||
/* Now do the half pixel pass */
|
||||
BestHalfOffset = 4; /* Default to the no offset case. */
|
||||
BestHalfPixelError = MinError;
|
||||
|
||||
/* Get the half pixel error for each half pixel offset */
|
||||
for ( i=0; i < 9; i++ ) {
|
||||
RefDataPtr2 = BestBlockPtr + cpi->HalfPixelRef2Offset[i];
|
||||
HalfPixelError =
|
||||
GetHalfPixelSumAbsDiffs( SrcPtr, BestBlockPtr, RefDataPtr2,
|
||||
PixelsPerLine, 0, BestHalfPixelError );
|
||||
|
||||
if ( HalfPixelError < BestHalfPixelError ){
|
||||
BestHalfOffset = (unsigned char)i;
|
||||
BestHalfPixelError = HalfPixelError;
|
||||
}
|
||||
}
|
||||
|
||||
/* Half pixel adjust the MV */
|
||||
MV->x += cpi->HalfPixelXOffset[BestHalfOffset];
|
||||
MV->y += cpi->HalfPixelYOffset[BestHalfOffset];
|
||||
|
||||
/* Get the variance score at the chosen offset */
|
||||
RefDataPtr2 = BestBlockPtr + cpi->HalfPixelRef2Offset[BestHalfOffset];
|
||||
|
||||
InterMVError =
|
||||
GetInterErr( SrcPtr, BestBlockPtr, RefDataPtr2, PixelsPerLine );
|
||||
|
||||
/* Return score of best matching block. */
|
||||
return InterMVError;
|
||||
}
|
||||
|
||||
ogg_uint32_t GetFOURMVExhaustiveSearch (CP_INSTANCE *cpi,
|
||||
unsigned char * RefFramePtr,
|
||||
ogg_uint32_t FragIndex,
|
||||
ogg_uint32_t PixelsPerLine,
|
||||
MOTION_VECTOR *MV ) {
|
||||
ogg_uint32_t InterMVError;
|
||||
|
||||
/* For the moment the 4MV mode is only deemd to be valid if all four
|
||||
Y blocks are to be updated */
|
||||
/* This May be adapted later. */
|
||||
if ( cpi->pb.display_fragments[FragIndex] &&
|
||||
cpi->pb.display_fragments[FragIndex + 1] &&
|
||||
cpi->pb.display_fragments[FragIndex + cpi->pb.HFragments] &&
|
||||
cpi->pb.display_fragments[FragIndex + cpi->pb.HFragments + 1] ) {
|
||||
|
||||
/* Reset the error score. */
|
||||
InterMVError = 0;
|
||||
|
||||
/* Get the error component from each coded block */
|
||||
InterMVError +=
|
||||
GetBMVExhaustiveSearch(cpi, RefFramePtr, FragIndex,
|
||||
PixelsPerLine, &(MV[0]) );
|
||||
InterMVError +=
|
||||
GetBMVExhaustiveSearch(cpi, RefFramePtr, (FragIndex + 1),
|
||||
PixelsPerLine, &(MV[1]) );
|
||||
InterMVError +=
|
||||
GetBMVExhaustiveSearch(cpi, RefFramePtr,
|
||||
(FragIndex + cpi->pb.HFragments),
|
||||
PixelsPerLine, &(MV[2]) );
|
||||
InterMVError +=
|
||||
GetBMVExhaustiveSearch(cpi, RefFramePtr,
|
||||
(FragIndex + cpi->pb.HFragments + 1),
|
||||
PixelsPerLine, &(MV[3]) );
|
||||
}else{
|
||||
InterMVError = HUGE_ERROR;
|
||||
}
|
||||
|
||||
/* Return score of best matching block. */
|
||||
return InterMVError;
|
||||
}
|
||||
|
337
src/add-ons/media/plugins/theora/libtheora/misc_common.c
Normal file
337
src/add-ons/media/plugins/theora/libtheora/misc_common.c
Normal file
@ -0,0 +1,337 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2003 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function:
|
||||
last mod: $Id: misc_common.c,v 1.1 2004/02/24 13:50:13 shatty Exp $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include "encoder_internal.h"
|
||||
#include "block_inline.h"
|
||||
|
||||
#define FIXED_Q 150
|
||||
#define MAX_UP_REG_LOOPS 2
|
||||
|
||||
/* Gives the initial bytes per block estimate for each Q value */
|
||||
double BpbTable[Q_TABLE_SIZE] = {
|
||||
0.42, 0.45, 0.46, 0.49, 0.51, 0.53, 0.56, 0.58,
|
||||
0.61, 0.64, 0.68, 0.71, 0.74, 0.77, 0.80, 0.84,
|
||||
0.89, 0.92, 0.98, 1.01, 1.04, 1.13, 1.17, 1.23,
|
||||
1.28, 1.34, 1.41, 1.45, 1.51, 1.59, 1.69, 1.80,
|
||||
1.84, 1.94, 2.02, 2.15, 2.23, 2.34, 2.44, 2.50,
|
||||
2.69, 2.80, 2.87, 3.04, 3.16, 3.29, 3.59, 3.66,
|
||||
3.86, 3.94, 4.22, 4.50, 4.64, 4.70, 5.24, 5.34,
|
||||
5.61, 5.87, 6.11, 6.41, 6.71, 6.99, 7.36, 7.69
|
||||
};
|
||||
|
||||
double KfBpbTable[Q_TABLE_SIZE] = {
|
||||
0.74, 0.81, 0.88, 0.94, 1.00, 1.06, 1.14, 1.19,
|
||||
1.27, 1.34, 1.42, 1.49, 1.54, 1.59, 1.66, 1.73,
|
||||
1.80, 1.87, 1.97, 2.01, 2.08, 2.21, 2.25, 2.36,
|
||||
2.39, 2.50, 2.55, 2.65, 2.71, 2.82, 2.95, 3.01,
|
||||
3.11, 3.19, 3.31, 3.42, 3.58, 3.66, 3.78, 3.89,
|
||||
4.11, 4.26, 4.36, 4.39, 4.63, 4.76, 4.85, 5.04,
|
||||
5.26, 5.29, 5.47, 5.64, 5.76, 6.05, 6.35, 6.67,
|
||||
6.91, 7.17, 7.40, 7.56, 8.02, 8.45, 8.86, 9.38
|
||||
};
|
||||
|
||||
double GetEstimatedBpb( CP_INSTANCE *cpi, ogg_uint32_t TargetQ ){
|
||||
ogg_uint32_t i;
|
||||
ogg_int32_t ThreshTableIndex = Q_TABLE_SIZE - 1;
|
||||
double BytesPerBlock;
|
||||
|
||||
/* Search for the Q table index that matches the given Q. */
|
||||
for ( i = 0; i < Q_TABLE_SIZE; i++ ) {
|
||||
if ( TargetQ >= cpi->pb.QThreshTable[i] ) {
|
||||
ThreshTableIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Adjust according to Q shift and type of frame */
|
||||
if ( GetFrameType(&cpi->pb) == BASE_FRAME ) {
|
||||
/* Get primary prediction */
|
||||
BytesPerBlock = KfBpbTable[ThreshTableIndex];
|
||||
} else {
|
||||
/* Get primary prediction */
|
||||
BytesPerBlock = BpbTable[ThreshTableIndex];
|
||||
BytesPerBlock = BytesPerBlock * cpi->BpbCorrectionFactor;
|
||||
}
|
||||
|
||||
return BytesPerBlock;
|
||||
}
|
||||
|
||||
static void UpRegulateMB( CP_INSTANCE *cpi, ogg_uint32_t RegulationQ,
|
||||
ogg_uint32_t SB, ogg_uint32_t MB, int NoCheck ) {
|
||||
ogg_int32_t FragIndex;
|
||||
ogg_uint32_t B;
|
||||
|
||||
/* Variables used in calculating corresponding row,col and index in
|
||||
UV planes */
|
||||
ogg_uint32_t UVRow;
|
||||
ogg_uint32_t UVColumn;
|
||||
ogg_uint32_t UVFragOffset;
|
||||
|
||||
/* There may be MB's lying out of frame which must be ignored. For
|
||||
these MB's Top left block will have a negative Fragment Index. */
|
||||
if ( QuadMapToMBTopLeft(cpi->pb.BlockMap, SB, MB ) >= 0 ) {
|
||||
/* Up regulate the component blocks Y then UV. */
|
||||
for ( B=0; B<4; B++ ){
|
||||
FragIndex = QuadMapToIndex1( cpi->pb.BlockMap, SB, MB, B );
|
||||
|
||||
if ( ( !cpi->pb.display_fragments[FragIndex] ) &&
|
||||
( (NoCheck) || (cpi->FragmentLastQ[FragIndex] > RegulationQ) ) ){
|
||||
cpi->pb.display_fragments[FragIndex] = 1;
|
||||
cpi->extra_fragments[FragIndex] = 1;
|
||||
cpi->FragmentLastQ[FragIndex] = RegulationQ;
|
||||
cpi->MotionScore++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check the two UV blocks */
|
||||
FragIndex = QuadMapToMBTopLeft(cpi->pb.BlockMap, SB, MB );
|
||||
|
||||
UVRow = (FragIndex / (cpi->pb.HFragments * 2));
|
||||
UVColumn = (FragIndex % cpi->pb.HFragments) / 2;
|
||||
UVFragOffset = (UVRow * (cpi->pb.HFragments / 2)) + UVColumn;
|
||||
|
||||
FragIndex = cpi->pb.YPlaneFragments + UVFragOffset;
|
||||
if ( ( !cpi->pb.display_fragments[FragIndex] ) &&
|
||||
( (NoCheck) || (cpi->FragmentLastQ[FragIndex] > RegulationQ) ) ) {
|
||||
cpi->pb.display_fragments[FragIndex] = 1;
|
||||
cpi->extra_fragments[FragIndex] = 1;
|
||||
cpi->FragmentLastQ[FragIndex] = RegulationQ;
|
||||
cpi->MotionScore++;
|
||||
}
|
||||
|
||||
FragIndex += cpi->pb.UVPlaneFragments;
|
||||
if ( ( !cpi->pb.display_fragments[FragIndex] ) &&
|
||||
( (NoCheck) || (cpi->FragmentLastQ[FragIndex] > RegulationQ) ) ) {
|
||||
cpi->pb.display_fragments[FragIndex] = 1;
|
||||
cpi->extra_fragments[FragIndex] = 1;
|
||||
cpi->FragmentLastQ[FragIndex] = RegulationQ;
|
||||
cpi->MotionScore++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void UpRegulateBlocks (CP_INSTANCE *cpi, ogg_uint32_t RegulationQ,
|
||||
ogg_int32_t RecoveryBlocks,
|
||||
ogg_uint32_t * LastSB, ogg_uint32_t * LastMB ) {
|
||||
|
||||
ogg_uint32_t LoopTimesRound = 0;
|
||||
ogg_uint32_t MaxSB = cpi->pb.YSBRows *
|
||||
cpi->pb.YSBCols; /* Tot super blocks in image */
|
||||
ogg_uint32_t SB, MB; /* Super-Block and macro block indices. */
|
||||
|
||||
/* First scan for blocks for which a residue update is outstanding. */
|
||||
while ( (cpi->MotionScore < RecoveryBlocks) &&
|
||||
(LoopTimesRound < MAX_UP_REG_LOOPS) ) {
|
||||
LoopTimesRound++;
|
||||
|
||||
for ( SB = (*LastSB); SB < MaxSB; SB++ ) {
|
||||
/* Check its four Macro-Blocks */
|
||||
for ( MB=(*LastMB); MB<4; MB++ ) {
|
||||
/* Mark relevant blocks for update */
|
||||
UpRegulateMB( cpi, RegulationQ, SB, MB, 0 );
|
||||
|
||||
/* Keep track of the last refresh MB. */
|
||||
(*LastMB) += 1;
|
||||
if ( (*LastMB) == 4 )
|
||||
(*LastMB) = 0;
|
||||
|
||||
/* Termination clause */
|
||||
if (cpi->MotionScore >= RecoveryBlocks) {
|
||||
/* Make sure we don't stall at SB level */
|
||||
if ( *LastMB == 0 )
|
||||
SB++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Termination clause */
|
||||
if (cpi->MotionScore >= RecoveryBlocks)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Update super block start index */
|
||||
if ( SB >= MaxSB){
|
||||
(*LastSB) = 0;
|
||||
}else{
|
||||
(*LastSB) = SB;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UpRegulateDataStream (CP_INSTANCE *cpi, ogg_uint32_t RegulationQ,
|
||||
ogg_int32_t RecoveryBlocks ) {
|
||||
ogg_uint32_t LastPassMBPos = 0;
|
||||
ogg_uint32_t StdLastMBPos = 0;
|
||||
|
||||
ogg_uint32_t MaxSB = cpi->pb.YSBRows *
|
||||
cpi->pb.YSBCols; /* Tot super blocks in image */
|
||||
|
||||
ogg_uint32_t SB=0; /* Super-Block index */
|
||||
ogg_uint32_t MB; /* Macro-Block index */
|
||||
|
||||
/* Decduct the number of blocks in an MB / 2 from the recover block count.
|
||||
This will compensate for the fact that once we start checking an MB
|
||||
we test every block in that macro block */
|
||||
if ( RecoveryBlocks > 3 )
|
||||
RecoveryBlocks -= 3;
|
||||
|
||||
/* Up regulate blocks last coded at higher Q */
|
||||
UpRegulateBlocks( cpi, RegulationQ, RecoveryBlocks,
|
||||
&cpi->LastEndSB, &StdLastMBPos );
|
||||
|
||||
/* If we have still not used up the minimum number of blocks and are
|
||||
at the minimum Q then run through a final pass of the data to
|
||||
insure that each block gets a final refresh. */
|
||||
if ( (RegulationQ == VERY_BEST_Q) &&
|
||||
(cpi->MotionScore < RecoveryBlocks) ) {
|
||||
if ( cpi->FinalPassLastPos < MaxSB ) {
|
||||
for ( SB = cpi->FinalPassLastPos; SB < MaxSB; SB++ ) {
|
||||
/* Check its four Macro-Blocks */
|
||||
for ( MB=LastPassMBPos; MB<4; MB++ ) {
|
||||
/* Mark relevant blocks for update */
|
||||
UpRegulateMB( cpi, RegulationQ, SB, MB, 1 );
|
||||
|
||||
/* Keep track of the last refresh MB. */
|
||||
LastPassMBPos += 1;
|
||||
if ( LastPassMBPos == 4 ) {
|
||||
LastPassMBPos = 0;
|
||||
|
||||
/* Increment SB index */
|
||||
cpi->FinalPassLastPos += 1;
|
||||
}
|
||||
|
||||
/* Termination clause */
|
||||
if (cpi->MotionScore >= RecoveryBlocks)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Termination clause */
|
||||
if (cpi->MotionScore >= RecoveryBlocks)
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RegulateQ( CP_INSTANCE *cpi, ogg_int32_t UpdateScore ) {
|
||||
double TargetUnitScoreBytes = (double)cpi->ThisFrameTargetBytes /
|
||||
(double)UpdateScore;
|
||||
double PredUnitScoreBytes;
|
||||
double LastBitError = 10000.0; /* Silly high number */
|
||||
ogg_uint32_t QIndex = Q_TABLE_SIZE - 1;
|
||||
ogg_uint32_t i;
|
||||
|
||||
/* Search for the best Q for the target bitrate. */
|
||||
for ( i = 0; i < Q_TABLE_SIZE; i++ ) {
|
||||
PredUnitScoreBytes = GetEstimatedBpb( cpi, cpi->pb.QThreshTable[i] );
|
||||
if ( PredUnitScoreBytes > TargetUnitScoreBytes ) {
|
||||
if ( (PredUnitScoreBytes - TargetUnitScoreBytes) <= LastBitError ) {
|
||||
QIndex = i;
|
||||
} else {
|
||||
QIndex = i - 1;
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
LastBitError = TargetUnitScoreBytes - PredUnitScoreBytes;
|
||||
}
|
||||
}
|
||||
|
||||
/* QIndex should now indicate the optimal Q. */
|
||||
cpi->pb.ThisFrameQualityValue = cpi->pb.QThreshTable[QIndex];
|
||||
|
||||
/* Apply range restrictions for key frames. */
|
||||
if ( GetFrameType(&cpi->pb) == BASE_FRAME ) {
|
||||
if ( cpi->pb.ThisFrameQualityValue > cpi->pb.QThreshTable[20] )
|
||||
cpi->pb.ThisFrameQualityValue = cpi->pb.QThreshTable[20];
|
||||
else if ( cpi->pb.ThisFrameQualityValue < cpi->pb.QThreshTable[50] )
|
||||
cpi->pb.ThisFrameQualityValue = cpi->pb.QThreshTable[50];
|
||||
}
|
||||
|
||||
/* Limit the Q value to the maximum available value */
|
||||
if (cpi->pb.ThisFrameQualityValue >
|
||||
cpi->pb.QThreshTable[cpi->Configuration.ActiveMaxQ]) {
|
||||
cpi->pb.ThisFrameQualityValue =
|
||||
(ogg_uint32_t)cpi->pb.QThreshTable[cpi->Configuration.ActiveMaxQ];
|
||||
}
|
||||
|
||||
if(cpi->FixedQ) {
|
||||
if ( GetFrameType(&cpi->pb) == BASE_FRAME ) {
|
||||
cpi->pb.ThisFrameQualityValue = cpi->pb.QThreshTable[43];
|
||||
cpi->pb.ThisFrameQualityValue = cpi->FixedQ;
|
||||
} else {
|
||||
cpi->pb.ThisFrameQualityValue = cpi->FixedQ;
|
||||
}
|
||||
}
|
||||
|
||||
/* If th quantiser value has changed then re-initialise it */
|
||||
if ( cpi->pb.ThisFrameQualityValue != cpi->pb.LastFrameQualityValue ) {
|
||||
/* Initialise quality tables. */
|
||||
UpdateQC( cpi, cpi->pb.ThisFrameQualityValue );
|
||||
cpi->pb.LastFrameQualityValue = cpi->pb.ThisFrameQualityValue;
|
||||
}
|
||||
}
|
||||
|
||||
void CopyBackExtraFrags(CP_INSTANCE *cpi){
|
||||
ogg_uint32_t i,j;
|
||||
unsigned char * SrcPtr;
|
||||
unsigned char * DestPtr;
|
||||
ogg_uint32_t PlaneLineStep;
|
||||
ogg_uint32_t PixelIndex;
|
||||
|
||||
/* Copy back for Y plane. */
|
||||
PlaneLineStep = cpi->pb.info.width;
|
||||
for ( i = 0; i < cpi->pb.YPlaneFragments; i++ ) {
|
||||
/* We are only interested in updated fragments. */
|
||||
if ( cpi->extra_fragments[i] ) {
|
||||
/* Get the start index for the fragment. */
|
||||
PixelIndex = cpi->pb.pixel_index_table[i];
|
||||
SrcPtr = &cpi->yuv1ptr[PixelIndex];
|
||||
DestPtr = &cpi->ConvDestBuffer[PixelIndex];
|
||||
|
||||
for ( j = 0; j < VFRAGPIXELS; j++ ) {
|
||||
memcpy( DestPtr, SrcPtr, HFRAGPIXELS);
|
||||
|
||||
SrcPtr += PlaneLineStep;
|
||||
DestPtr += PlaneLineStep;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Now the U and V planes */
|
||||
PlaneLineStep = cpi->pb.info.width / 2;
|
||||
for ( i = cpi->pb.YPlaneFragments;
|
||||
i < (cpi->pb.YPlaneFragments + (2 * cpi->pb.UVPlaneFragments)) ;
|
||||
i++ ) {
|
||||
|
||||
/* We are only interested in updated fragments. */
|
||||
if ( cpi->extra_fragments[i] ) {
|
||||
/* Get the start index for the fragment. */
|
||||
PixelIndex = cpi->pb.pixel_index_table[i];
|
||||
SrcPtr = &cpi->yuv1ptr[PixelIndex];
|
||||
DestPtr = &cpi->ConvDestBuffer[PixelIndex];
|
||||
|
||||
for ( j = 0; j < VFRAGPIXELS; j++ ) {
|
||||
memcpy( DestPtr, SrcPtr, HFRAGPIXELS);
|
||||
SrcPtr += PlaneLineStep;
|
||||
DestPtr += PlaneLineStep;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
117
src/add-ons/media/plugins/theora/libtheora/pb.c
Normal file
117
src/add-ons/media/plugins/theora/libtheora/pb.c
Normal file
@ -0,0 +1,117 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2003 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function:
|
||||
last mod: $Id: pb.c,v 1.1 2004/02/24 13:50:13 shatty Exp $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "encoder_internal.h"
|
||||
|
||||
void ClearTmpBuffers(PB_INSTANCE * pbi){
|
||||
|
||||
if(pbi->ReconDataBuffer)
|
||||
_ogg_free(pbi->ReconDataBuffer);
|
||||
if(pbi->DequantBuffer)
|
||||
_ogg_free(pbi->DequantBuffer);
|
||||
if(pbi->TmpDataBuffer)
|
||||
_ogg_free(pbi->TmpDataBuffer);
|
||||
if(pbi->TmpReconBuffer)
|
||||
_ogg_free(pbi->TmpReconBuffer);
|
||||
if(pbi->dequant_Y_coeffs)
|
||||
_ogg_free(pbi->dequant_Y_coeffs);
|
||||
if(pbi->dequant_UV_coeffs)
|
||||
_ogg_free(pbi->dequant_UV_coeffs);
|
||||
if(pbi->dequant_Inter_coeffs)
|
||||
_ogg_free(pbi->dequant_Inter_coeffs);
|
||||
if(pbi->dequant_InterUV_coeffs)
|
||||
_ogg_free(pbi->dequant_InterUV_coeffs);
|
||||
|
||||
|
||||
pbi->ReconDataBuffer=0;
|
||||
pbi->DequantBuffer = 0;
|
||||
pbi->TmpDataBuffer = 0;
|
||||
pbi->TmpReconBuffer = 0;
|
||||
pbi->dequant_Y_coeffs = 0;
|
||||
pbi->dequant_UV_coeffs = 0;
|
||||
pbi->dequant_InterUV_coeffs = 0;
|
||||
pbi->dequant_Inter_coeffs = 0;
|
||||
|
||||
}
|
||||
|
||||
void InitTmpBuffers(PB_INSTANCE * pbi){
|
||||
|
||||
/* clear any existing info */
|
||||
ClearTmpBuffers(pbi);
|
||||
|
||||
/* Adjust the position of all of our temporary */
|
||||
pbi->ReconDataBuffer =
|
||||
_ogg_malloc(64*sizeof(*pbi->ReconDataBuffer));
|
||||
|
||||
pbi->DequantBuffer =
|
||||
_ogg_malloc(64 * sizeof(*pbi->DequantBuffer));
|
||||
|
||||
pbi->TmpDataBuffer =
|
||||
_ogg_malloc(64 * sizeof(*pbi->TmpDataBuffer));
|
||||
|
||||
pbi->TmpReconBuffer =
|
||||
_ogg_malloc(64 * sizeof(*pbi->TmpReconBuffer));
|
||||
|
||||
pbi->dequant_Y_coeffs =
|
||||
_ogg_malloc(64 * sizeof(*pbi->dequant_Y_coeffs));
|
||||
|
||||
pbi->dequant_UV_coeffs =
|
||||
_ogg_malloc(64 * sizeof(*pbi->dequant_UV_coeffs));
|
||||
|
||||
pbi->dequant_Inter_coeffs =
|
||||
_ogg_malloc(64 * sizeof(*pbi->dequant_Inter_coeffs));
|
||||
|
||||
pbi->dequant_InterUV_coeffs =
|
||||
_ogg_malloc(64 * sizeof(*pbi->dequant_InterUV_coeffs));
|
||||
|
||||
}
|
||||
|
||||
void ClearPBInstance(PB_INSTANCE *pbi){
|
||||
if(pbi){
|
||||
ClearTmpBuffers(pbi);
|
||||
if (pbi->opb) {
|
||||
_ogg_free(pbi->opb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InitPBInstance(PB_INSTANCE *pbi){
|
||||
/* initialize whole structure to 0 */
|
||||
memset(pbi, 0, sizeof(*pbi));
|
||||
|
||||
InitTmpBuffers(pbi);
|
||||
|
||||
/* allocate memory for the oggpack_buffer */
|
||||
#ifndef LIBOGG2
|
||||
pbi->opb = _ogg_malloc(sizeof(oggpack_buffer));
|
||||
#else
|
||||
pbi->opb = _ogg_malloc(oggpack_buffersize());
|
||||
#endif
|
||||
|
||||
/* variables needing initialization (not being set to 0) */
|
||||
|
||||
pbi->ModifierPointer[0] = &pbi->Modifier[0][255];
|
||||
pbi->ModifierPointer[1] = &pbi->Modifier[1][255];
|
||||
pbi->ModifierPointer[2] = &pbi->Modifier[2][255];
|
||||
pbi->ModifierPointer[3] = &pbi->Modifier[3][255];
|
||||
|
||||
pbi->DecoderErrorCode = 0;
|
||||
pbi->KeyFrameType = DCT_KEY_FRAME;
|
||||
pbi->FramesHaveBeenSkipped = 0;
|
||||
}
|
951
src/add-ons/media/plugins/theora/libtheora/pp.c
Normal file
951
src/add-ons/media/plugins/theora/libtheora/pp.c
Normal file
@ -0,0 +1,951 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2003 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function:
|
||||
last mod: $Id: pp.c,v 1.1 2004/02/24 13:50:13 shatty Exp $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "encoder_internal.h"
|
||||
#include "pp.h"
|
||||
|
||||
#define MAX(a, b) ((a>b)?a:b)
|
||||
#define MIN(a, b) ((a<b)?a:b)
|
||||
#define PP_QUALITY_THRESH 49
|
||||
|
||||
static ogg_int32_t SharpenModifier[ Q_TABLE_SIZE ] =
|
||||
{ -12, -11, -10, -10, -9, -9, -9, -9,
|
||||
-6, -6, -6, -6, -6, -6, -6, -6,
|
||||
-4, -4, -4, -4, -4, -4, -4, -4,
|
||||
-2, -2, -2, -2, -2, -2, -2, -2,
|
||||
-2, -2, -2, -2, -2, -2, -2, -2,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
static ogg_uint32_t DcQuantScaleV1[ Q_TABLE_SIZE ] = {
|
||||
22, 20, 19, 18, 17, 17, 16, 16,
|
||||
15, 15, 14, 14, 13, 13, 12, 12,
|
||||
11, 11, 10, 10, 9, 9, 9, 8,
|
||||
8, 8, 7, 7, 7, 6, 6, 6,
|
||||
6, 5, 5, 5, 5, 4, 4, 4,
|
||||
4, 4, 3, 3, 3, 3, 3, 3,
|
||||
3, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 1, 1, 1, 1, 1, 1, 1
|
||||
};
|
||||
|
||||
static ogg_uint32_t *DeringModifierV1=DcQuantScaleV1;
|
||||
|
||||
static void PClearFrameInfo(PP_INSTANCE * ppi){
|
||||
int i;
|
||||
|
||||
if(ppi->ScanPixelIndexTable) _ogg_free(ppi->ScanPixelIndexTable);
|
||||
ppi->ScanPixelIndexTable=0;
|
||||
|
||||
if(ppi->ScanDisplayFragments) _ogg_free(ppi->ScanDisplayFragments);
|
||||
ppi->ScanDisplayFragments=0;
|
||||
|
||||
for(i = 0 ; i < MAX_PREV_FRAMES ; i ++)
|
||||
if(ppi->PrevFragments[i]){
|
||||
_ogg_free(ppi->PrevFragments[i]);
|
||||
ppi->PrevFragments[i]=0;
|
||||
}
|
||||
|
||||
if(ppi->FragScores) _ogg_free(ppi->FragScores);
|
||||
ppi->FragScores=0;
|
||||
|
||||
if(ppi->SameGreyDirPixels) _ogg_free(ppi->SameGreyDirPixels);
|
||||
ppi->SameGreyDirPixels=0;
|
||||
|
||||
if(ppi->FragDiffPixels) _ogg_free(ppi->FragDiffPixels);
|
||||
ppi->FragDiffPixels=0;
|
||||
|
||||
if(ppi->BarBlockMap) _ogg_free(ppi->BarBlockMap);
|
||||
ppi->BarBlockMap=0;
|
||||
|
||||
if(ppi->TmpCodedMap) _ogg_free(ppi->TmpCodedMap);
|
||||
ppi->TmpCodedMap=0;
|
||||
|
||||
if(ppi->RowChangedPixels) _ogg_free(ppi->RowChangedPixels);
|
||||
ppi->RowChangedPixels=0;
|
||||
|
||||
if(ppi->PixelScores) _ogg_free(ppi->PixelScores);
|
||||
ppi->PixelScores=0;
|
||||
|
||||
if(ppi->PixelChangedMap) _ogg_free(ppi->PixelChangedMap);
|
||||
ppi->PixelChangedMap=0;
|
||||
|
||||
if(ppi->ChLocals) _ogg_free(ppi->ChLocals);
|
||||
ppi->ChLocals=0;
|
||||
|
||||
if(ppi->yuv_differences) _ogg_free(ppi->yuv_differences);
|
||||
ppi->yuv_differences=0;
|
||||
|
||||
}
|
||||
|
||||
void PInitFrameInfo(PP_INSTANCE * ppi){
|
||||
int i;
|
||||
PClearFrameInfo(ppi);
|
||||
|
||||
ppi->ScanPixelIndexTable =
|
||||
_ogg_malloc(ppi->ScanFrameFragments*sizeof(*ppi->ScanPixelIndexTable));
|
||||
|
||||
ppi->ScanDisplayFragments =
|
||||
_ogg_malloc(ppi->ScanFrameFragments*sizeof(*ppi->ScanDisplayFragments));
|
||||
|
||||
for(i = 0 ; i < MAX_PREV_FRAMES ; i ++)
|
||||
ppi->PrevFragments[i] =
|
||||
_ogg_malloc(ppi->ScanFrameFragments*sizeof(*ppi->PrevFragments));
|
||||
|
||||
ppi->FragScores =
|
||||
_ogg_malloc(ppi->ScanFrameFragments*sizeof(*ppi->FragScores));
|
||||
|
||||
ppi->SameGreyDirPixels =
|
||||
_ogg_malloc(ppi->ScanFrameFragments*sizeof(*ppi->SameGreyDirPixels));
|
||||
|
||||
ppi->FragDiffPixels =
|
||||
_ogg_malloc(ppi->ScanFrameFragments*sizeof(*ppi->FragScores));
|
||||
|
||||
ppi->BarBlockMap=
|
||||
_ogg_malloc(3 * ppi->ScanHFragments*sizeof(*ppi->BarBlockMap));
|
||||
|
||||
ppi->TmpCodedMap =
|
||||
_ogg_malloc(ppi->ScanHFragments*sizeof(*ppi->TmpCodedMap));
|
||||
|
||||
ppi->RowChangedPixels =
|
||||
_ogg_malloc(3 * ppi->ScanConfig.VideoFrameHeight*
|
||||
sizeof(*ppi->RowChangedPixels));
|
||||
|
||||
ppi->PixelScores =
|
||||
_ogg_malloc(ppi->ScanConfig.VideoFrameWidth*
|
||||
sizeof(*ppi->PixelScores) * PSCORE_CB_ROWS);
|
||||
|
||||
ppi->PixelChangedMap =
|
||||
_ogg_malloc(ppi->ScanConfig.VideoFrameWidth*
|
||||
sizeof(*ppi->PixelChangedMap) * PMAP_CB_ROWS);
|
||||
|
||||
ppi->ChLocals =
|
||||
_ogg_malloc(ppi->ScanConfig.VideoFrameWidth*
|
||||
sizeof(*ppi->ChLocals) * CHLOCALS_CB_ROWS);
|
||||
|
||||
ppi->yuv_differences =
|
||||
_ogg_malloc(ppi->ScanConfig.VideoFrameWidth*
|
||||
sizeof(*ppi->yuv_differences) * YDIFF_CB_ROWS);
|
||||
}
|
||||
|
||||
void ClearPPInstance(PP_INSTANCE *ppi){
|
||||
PClearFrameInfo(ppi);
|
||||
}
|
||||
|
||||
|
||||
void InitPPInstance(PP_INSTANCE *ppi){
|
||||
|
||||
memset(ppi,0,sizeof(*ppi));
|
||||
|
||||
/* Initializations */
|
||||
ppi->PrevFrameLimit = 3; /* Must not exceed MAX_PREV_FRAMES (Note
|
||||
that this number includes the current
|
||||
frame so "1 = no effect") */
|
||||
|
||||
/* Scan control variables. */
|
||||
ppi->HFragPixels = 8;
|
||||
ppi->VFragPixels = 8;
|
||||
|
||||
ppi->SRFGreyThresh = 4;
|
||||
ppi->SRFColThresh = 5;
|
||||
ppi->NoiseSupLevel = 3;
|
||||
ppi->SgcLevelThresh = 3;
|
||||
ppi->SuvcLevelThresh = 4;
|
||||
|
||||
/* Variables controlling S.A.D. breakouts. */
|
||||
ppi->GrpLowSadThresh = 10;
|
||||
ppi->GrpHighSadThresh = 64;
|
||||
ppi->PrimaryBlockThreshold = 5;
|
||||
ppi->SgcThresh = 16; /* (Default values for 8x8 blocks). */
|
||||
|
||||
ppi->UVBlockThreshCorrection = 1.25;
|
||||
ppi->UVSgcCorrection = 1.5;
|
||||
|
||||
ppi->MaxLineSearchLen = MAX_SEARCH_LINE_LEN;
|
||||
}
|
||||
|
||||
static void DeringBlockStrong(unsigned char *SrcPtr,
|
||||
unsigned char *DstPtr,
|
||||
ogg_int32_t Pitch,
|
||||
ogg_uint32_t FragQIndex,
|
||||
ogg_uint32_t *QuantScale){
|
||||
|
||||
ogg_int16_t UDMod[72];
|
||||
ogg_int16_t LRMod[72];
|
||||
unsigned int j,k,l;
|
||||
const unsigned char * Src;
|
||||
unsigned int QValue = QuantScale[FragQIndex];
|
||||
|
||||
unsigned char p;
|
||||
unsigned char pl;
|
||||
unsigned char pr;
|
||||
unsigned char pu;
|
||||
unsigned char pd;
|
||||
|
||||
int al;
|
||||
int ar;
|
||||
int au;
|
||||
int ad;
|
||||
|
||||
int atot;
|
||||
int B;
|
||||
int newVal;
|
||||
|
||||
const unsigned char *curRow = SrcPtr - 1; /* avoid negative array indexes */
|
||||
unsigned char *dstRow = DstPtr;
|
||||
const unsigned char *lastRow = SrcPtr-Pitch;
|
||||
const unsigned char *nextRow = SrcPtr+Pitch;
|
||||
|
||||
unsigned int rowOffset = 0;
|
||||
unsigned int round = (1<<6);
|
||||
|
||||
int High;
|
||||
int Low;
|
||||
int TmpMod;
|
||||
|
||||
int Sharpen = SharpenModifier[FragQIndex];
|
||||
High = 3 * QValue;
|
||||
if(High>32)High=32;
|
||||
Low = 0;
|
||||
|
||||
|
||||
/* Initialize the Mod Data */
|
||||
Src = SrcPtr-Pitch;
|
||||
for(k=0;k<9;k++){
|
||||
for(j=0;j<8;j++){
|
||||
|
||||
TmpMod = 32 + QValue - (abs(Src[j+Pitch]-Src[j]));
|
||||
|
||||
if(TmpMod< -64)
|
||||
TmpMod = Sharpen;
|
||||
|
||||
else if(TmpMod<Low)
|
||||
TmpMod = Low;
|
||||
|
||||
else if(TmpMod>High)
|
||||
TmpMod = High;
|
||||
|
||||
UDMod[k*8+j] = (ogg_int16_t)TmpMod;
|
||||
}
|
||||
Src +=Pitch;
|
||||
}
|
||||
|
||||
Src = SrcPtr-1;
|
||||
|
||||
for(k=0;k<8;k++){
|
||||
for(j=0;j<9;j++){
|
||||
TmpMod = 32 + QValue - (abs(Src[j+1]-Src[j]));
|
||||
|
||||
if(TmpMod< -64 )
|
||||
TmpMod = Sharpen;
|
||||
|
||||
else if(TmpMod<0)
|
||||
TmpMod = Low;
|
||||
|
||||
else if(TmpMod>High)
|
||||
TmpMod = High;
|
||||
|
||||
LRMod[k*9+j] = (ogg_int16_t)TmpMod;
|
||||
}
|
||||
Src+=Pitch;
|
||||
}
|
||||
|
||||
for(k=0;k<8;k++){
|
||||
/* In the case that this function called with same buffer for
|
||||
source and destination, To keep the c and the mmx version to have
|
||||
consistant results, intermediate buffer is used to store the
|
||||
eight pixel value before writing them to destination
|
||||
(i.e. Overwriting souce for the speical case) */
|
||||
for(l=0;l<8;l++){
|
||||
|
||||
atot = 128;
|
||||
B = round;
|
||||
p = curRow[ rowOffset +l +1];
|
||||
|
||||
pl = curRow[ rowOffset +l];
|
||||
al = LRMod[k*9+l];
|
||||
atot -= al;
|
||||
B += al * pl;
|
||||
|
||||
pu = lastRow[ rowOffset +l];
|
||||
au = UDMod[k*8+l];
|
||||
atot -= au;
|
||||
B += au * pu;
|
||||
|
||||
pd = nextRow[ rowOffset +l];
|
||||
ad = UDMod[(k+1)*8+l];
|
||||
atot -= ad;
|
||||
B += ad * pd;
|
||||
|
||||
pr = curRow[ rowOffset +l+2];
|
||||
ar = LRMod[k*9+l+1];
|
||||
atot -= ar;
|
||||
B += ar * pr;
|
||||
|
||||
newVal = ( atot * p + B) >> 7;
|
||||
|
||||
dstRow[ rowOffset +l]= clamp255( newVal );
|
||||
}
|
||||
rowOffset += Pitch;
|
||||
}
|
||||
}
|
||||
|
||||
static void DeringBlockWeak(unsigned char *SrcPtr,
|
||||
unsigned char *DstPtr,
|
||||
ogg_int32_t Pitch,
|
||||
ogg_uint32_t FragQIndex,
|
||||
ogg_uint32_t *QuantScale){
|
||||
|
||||
ogg_int16_t UDMod[72];
|
||||
ogg_int16_t LRMod[72];
|
||||
unsigned int j,k;
|
||||
const unsigned char * Src;
|
||||
unsigned int QValue = QuantScale[FragQIndex];
|
||||
|
||||
unsigned char p;
|
||||
unsigned char pl;
|
||||
unsigned char pr;
|
||||
unsigned char pu;
|
||||
unsigned char pd;
|
||||
|
||||
int al;
|
||||
int ar;
|
||||
int au;
|
||||
int ad;
|
||||
|
||||
int atot;
|
||||
int B;
|
||||
int newVal;
|
||||
|
||||
const unsigned char *curRow = SrcPtr-1;
|
||||
unsigned char *dstRow = DstPtr;
|
||||
const unsigned char *lastRow = SrcPtr-Pitch;
|
||||
const unsigned char *nextRow = SrcPtr+Pitch;
|
||||
|
||||
unsigned int rowOffset = 0;
|
||||
unsigned int round = (1<<6);
|
||||
|
||||
int High;
|
||||
int Low;
|
||||
int TmpMod;
|
||||
int Sharpen = SharpenModifier[FragQIndex];
|
||||
|
||||
High = 3 * QValue;
|
||||
if(High>24)
|
||||
High=24;
|
||||
Low = 0 ;
|
||||
|
||||
/* Initialize the Mod Data */
|
||||
Src=SrcPtr-Pitch;
|
||||
for(k=0;k<9;k++) {
|
||||
for(j=0;j<8;j++) {
|
||||
|
||||
TmpMod = 32 + QValue - 2*(abs(Src[j+Pitch]-Src[j]));
|
||||
|
||||
if(TmpMod< -64)
|
||||
TmpMod = Sharpen;
|
||||
|
||||
else if(TmpMod<Low)
|
||||
TmpMod = Low;
|
||||
|
||||
else if(TmpMod>High)
|
||||
TmpMod = High;
|
||||
|
||||
UDMod[k*8+j] = (ogg_int16_t)TmpMod;
|
||||
}
|
||||
Src +=Pitch;
|
||||
}
|
||||
|
||||
Src = SrcPtr-1;
|
||||
|
||||
for(k=0;k<8;k++){
|
||||
for(j=0;j<9;j++){
|
||||
TmpMod = 32 + QValue - 2*(abs(Src[j+1]-Src[j]));
|
||||
|
||||
if(TmpMod< -64 )
|
||||
TmpMod = Sharpen;
|
||||
|
||||
else if(TmpMod<Low)
|
||||
TmpMod = Low;
|
||||
|
||||
else if(TmpMod>High)
|
||||
TmpMod = High;
|
||||
|
||||
LRMod[k*9+j] = (ogg_int16_t)TmpMod;
|
||||
}
|
||||
Src+=Pitch;
|
||||
}
|
||||
|
||||
for(k=0;k<8;k++) {
|
||||
for(j=0;j<8;j++){
|
||||
atot = 128;
|
||||
B = round;
|
||||
p = curRow[ rowOffset +j+1];
|
||||
|
||||
pl = curRow[ rowOffset +j];
|
||||
al = LRMod[k*9+j];
|
||||
atot -= al;
|
||||
B += al * pl;
|
||||
|
||||
pu = lastRow[ rowOffset +j];
|
||||
au = UDMod[k*8+j];
|
||||
atot -= au;
|
||||
B += au * pu;
|
||||
|
||||
pd = nextRow[ rowOffset +j];
|
||||
ad = UDMod[(k+1)*8+j];
|
||||
atot -= ad;
|
||||
B += ad * pd;
|
||||
|
||||
pr = curRow[ rowOffset +j+2];
|
||||
ar = LRMod[k*9+j+1];
|
||||
atot -= ar;
|
||||
B += ar * pr;
|
||||
|
||||
newVal = ( atot * p + B) >> 7;
|
||||
|
||||
dstRow[ rowOffset +j] = clamp255( newVal );
|
||||
}
|
||||
|
||||
rowOffset += Pitch;
|
||||
}
|
||||
}
|
||||
|
||||
static void DeringFrame(PB_INSTANCE *pbi,
|
||||
unsigned char *Src, unsigned char *Dst){
|
||||
ogg_uint32_t col,row;
|
||||
unsigned char *SrcPtr;
|
||||
unsigned char *DestPtr;
|
||||
ogg_uint32_t BlocksAcross,BlocksDown;
|
||||
ogg_uint32_t *QuantScale;
|
||||
ogg_uint32_t Block;
|
||||
ogg_uint32_t LineLength;
|
||||
|
||||
ogg_int32_t Thresh1,Thresh2,Thresh3,Thresh4;
|
||||
|
||||
Thresh1 = 384;
|
||||
Thresh2 = 4 * Thresh1;
|
||||
Thresh3 = 5 * Thresh2/4;
|
||||
Thresh4 = 5 * Thresh2/2;
|
||||
|
||||
QuantScale = DeringModifierV1;
|
||||
|
||||
BlocksAcross = pbi->HFragments;
|
||||
BlocksDown = pbi->VFragments;
|
||||
|
||||
SrcPtr = Src + pbi->ReconYDataOffset;
|
||||
DestPtr = Dst + pbi->ReconYDataOffset;
|
||||
LineLength = pbi->YStride;
|
||||
|
||||
Block = 0;
|
||||
|
||||
for ( row = 0 ; row < BlocksDown; row ++){
|
||||
for (col = 0; col < BlocksAcross; col ++){
|
||||
ogg_uint32_t Quality = pbi->FragQIndex[Block];
|
||||
ogg_int32_t Variance = pbi->FragmentVariances[Block];
|
||||
|
||||
if( pbi->PostProcessingLevel >5 && Variance > Thresh3 ){
|
||||
DeringBlockStrong(SrcPtr + 8 * col, DestPtr + 8 * col,
|
||||
LineLength,Quality,QuantScale);
|
||||
|
||||
if( (col > 0 &&
|
||||
pbi->FragmentVariances[Block-1] > Thresh4 ) ||
|
||||
(col + 1 < BlocksAcross &&
|
||||
pbi->FragmentVariances[Block+1] > Thresh4 ) ||
|
||||
(row + 1 < BlocksDown &&
|
||||
pbi->FragmentVariances[Block+BlocksAcross] > Thresh4) ||
|
||||
(row > 0 &&
|
||||
pbi->FragmentVariances[Block-BlocksAcross] > Thresh4) ){
|
||||
|
||||
DeringBlockStrong(SrcPtr + 8 * col, DestPtr + 8 * col,
|
||||
LineLength,Quality,QuantScale);
|
||||
DeringBlockStrong(SrcPtr + 8 * col, DestPtr + 8 * col,
|
||||
LineLength,Quality,QuantScale);
|
||||
}
|
||||
} else if(Variance > Thresh2 ) {
|
||||
|
||||
DeringBlockStrong(SrcPtr + 8 * col, DestPtr + 8 * col,
|
||||
LineLength,Quality,QuantScale);
|
||||
} else if(Variance > Thresh1 ) {
|
||||
|
||||
DeringBlockWeak(SrcPtr + 8 * col, DestPtr + 8 * col,
|
||||
LineLength,Quality,QuantScale);
|
||||
|
||||
} else {
|
||||
|
||||
CopyBlock(SrcPtr + 8 * col, DestPtr + 8 * col, LineLength);
|
||||
|
||||
}
|
||||
|
||||
++Block;
|
||||
|
||||
}
|
||||
SrcPtr += 8 * LineLength;
|
||||
DestPtr += 8 * LineLength;
|
||||
}
|
||||
|
||||
/* Then U */
|
||||
|
||||
BlocksAcross /= 2;
|
||||
BlocksDown /= 2;
|
||||
LineLength /= 2;
|
||||
|
||||
SrcPtr = Src + pbi->ReconUDataOffset;
|
||||
DestPtr = Dst + pbi->ReconUDataOffset;
|
||||
for ( row = 0 ; row < BlocksDown; row ++) {
|
||||
for (col = 0; col < BlocksAcross; col ++) {
|
||||
ogg_uint32_t Quality = pbi->FragQIndex[Block];
|
||||
ogg_int32_t Variance = pbi->FragmentVariances[Block];
|
||||
|
||||
if( pbi->PostProcessingLevel >5 && Variance > Thresh4 ) {
|
||||
DeringBlockStrong(SrcPtr + 8 * col, DestPtr + 8 * col,
|
||||
LineLength,Quality,QuantScale);
|
||||
DeringBlockStrong(SrcPtr + 8 * col, DestPtr + 8 * col,
|
||||
LineLength,Quality,QuantScale);
|
||||
DeringBlockStrong(SrcPtr + 8 * col, DestPtr + 8 * col,
|
||||
LineLength,Quality,QuantScale);
|
||||
|
||||
}else if(Variance > Thresh2 ){
|
||||
DeringBlockStrong(SrcPtr + 8 * col, DestPtr + 8 * col,
|
||||
LineLength,Quality,QuantScale);
|
||||
}else if(Variance > Thresh1 ){
|
||||
DeringBlockWeak(SrcPtr + 8 * col, DestPtr + 8 * col,
|
||||
LineLength,Quality,QuantScale);
|
||||
}else{
|
||||
CopyBlock(SrcPtr + 8 * col, DestPtr + 8 * col, LineLength);
|
||||
}
|
||||
|
||||
++Block;
|
||||
|
||||
}
|
||||
SrcPtr += 8 * LineLength;
|
||||
DestPtr += 8 * LineLength;
|
||||
}
|
||||
|
||||
/* Then V */
|
||||
SrcPtr = Src + pbi->ReconVDataOffset;
|
||||
DestPtr = Dst + pbi->ReconVDataOffset;
|
||||
|
||||
for ( row = 0 ; row < BlocksDown; row ++){
|
||||
for (col = 0; col < BlocksAcross; col ++){
|
||||
|
||||
ogg_uint32_t Quality = pbi->FragQIndex[Block];
|
||||
ogg_int32_t Variance = pbi->FragmentVariances[Block];
|
||||
|
||||
|
||||
if( pbi->PostProcessingLevel >5 && Variance > Thresh4 ) {
|
||||
DeringBlockStrong(SrcPtr + 8 * col, DestPtr + 8 * col,
|
||||
LineLength,Quality,QuantScale);
|
||||
DeringBlockStrong(SrcPtr + 8 * col, DestPtr + 8 * col,
|
||||
LineLength,Quality,QuantScale);
|
||||
DeringBlockStrong(SrcPtr + 8 * col, DestPtr + 8 * col,
|
||||
LineLength,Quality,QuantScale);
|
||||
|
||||
}else if(Variance > Thresh2 ){
|
||||
DeringBlockStrong(SrcPtr + 8 * col, DestPtr + 8 * col,
|
||||
LineLength,Quality,QuantScale);
|
||||
}else if(Variance > Thresh1 ){
|
||||
DeringBlockWeak(SrcPtr + 8 * col, DestPtr + 8 * col,
|
||||
LineLength,Quality,QuantScale);
|
||||
}else{
|
||||
CopyBlock(SrcPtr + 8 * col, DestPtr + 8 * col, LineLength);
|
||||
}
|
||||
|
||||
++Block;
|
||||
|
||||
}
|
||||
SrcPtr += 8 * LineLength;
|
||||
DestPtr += 8 * LineLength;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void UpdateFragQIndex(PB_INSTANCE *pbi){
|
||||
|
||||
ogg_uint32_t ThisFrameQIndex;
|
||||
ogg_uint32_t i;
|
||||
|
||||
/* Check this frame quality index */
|
||||
ThisFrameQIndex = pbi->FrameQIndex;
|
||||
|
||||
|
||||
/* It is not a key frame, so only reset those are coded */
|
||||
for( i = 0; i < pbi->UnitFragments; i++ )
|
||||
if( pbi->display_fragments[i])
|
||||
pbi->FragQIndex[i] = ThisFrameQIndex;
|
||||
|
||||
}
|
||||
|
||||
static void DeblockLoopFilteredBand(PB_INSTANCE *pbi,
|
||||
unsigned char *SrcPtr,
|
||||
unsigned char *DesPtr,
|
||||
ogg_uint32_t PlaneLineStep,
|
||||
ogg_uint32_t FragsAcross,
|
||||
ogg_uint32_t StartFrag,
|
||||
ogg_uint32_t *QuantScale){
|
||||
ogg_uint32_t j,k;
|
||||
ogg_uint32_t CurrentFrag=StartFrag;
|
||||
ogg_int32_t QStep;
|
||||
ogg_int32_t FLimit;
|
||||
unsigned char *Src, *Des;
|
||||
ogg_int32_t x[10];
|
||||
ogg_int32_t Sum1, Sum2;
|
||||
|
||||
while(CurrentFrag < StartFrag + FragsAcross){
|
||||
|
||||
Src=SrcPtr+8*(CurrentFrag-StartFrag)-PlaneLineStep*5;
|
||||
Des=DesPtr+8*(CurrentFrag-StartFrag)-PlaneLineStep*4;
|
||||
|
||||
QStep = QuantScale[pbi->FragQIndex[CurrentFrag+FragsAcross]];
|
||||
FLimit = ( QStep * 3 ) >> 2;
|
||||
|
||||
for( j=0; j<8 ; j++){
|
||||
x[0] = Src[0];
|
||||
x[1] = Src[PlaneLineStep];
|
||||
x[2] = Src[PlaneLineStep*2];
|
||||
x[3] = Src[PlaneLineStep*3];
|
||||
x[4] = Src[PlaneLineStep*4];
|
||||
x[5] = Src[PlaneLineStep*5];
|
||||
x[6] = Src[PlaneLineStep*6];
|
||||
x[7] = Src[PlaneLineStep*7];
|
||||
x[8] = Src[PlaneLineStep*8];
|
||||
x[9] = Src[PlaneLineStep*9];
|
||||
|
||||
Sum1=Sum2=0;
|
||||
|
||||
for(k=1;k<=4;k++){
|
||||
Sum1 += abs(x[k]-x[k-1]);
|
||||
Sum2 += abs(x[k+4]-x[k+5]);
|
||||
}
|
||||
|
||||
pbi->FragmentVariances[CurrentFrag] +=((Sum1>255)?255:Sum1);
|
||||
pbi->FragmentVariances[CurrentFrag + FragsAcross] += ((Sum2>255)?255:Sum2);
|
||||
|
||||
if( Sum1 < FLimit &&
|
||||
Sum2 < FLimit &&
|
||||
(x[5] - x[4]) < QStep &&
|
||||
(x[4] - x[5]) < QStep ){
|
||||
|
||||
/* low pass filtering (LPF7: 1 1 1 2 1 1 1) */
|
||||
Des[0 ] = (x[0] + x[0] +x[0] + x[1] * 2 +
|
||||
x[2] + x[3] +x[4] + 4) >> 3;
|
||||
Des[PlaneLineStep ] = (x[0] + x[0] +x[1] + x[2] * 2 +
|
||||
x[3] + x[4] +x[5] + 4) >> 3;
|
||||
Des[PlaneLineStep*2] = (x[0] + x[1] +x[2] + x[3] * 2 +
|
||||
x[4] + x[5] +x[6] + 4) >> 3;
|
||||
Des[PlaneLineStep*3] = (x[1] + x[2] +x[3] + x[4] * 2 +
|
||||
x[5] + x[6] +x[7] + 4) >> 3;
|
||||
Des[PlaneLineStep*4] = (x[2] + x[3] +x[4] + x[5] * 2 +
|
||||
x[6] + x[7] +x[8] + 4) >> 3;
|
||||
Des[PlaneLineStep*5] = (x[3] + x[4] +x[5] + x[6] * 2 +
|
||||
x[7] + x[8] +x[9] + 4) >> 3;
|
||||
Des[PlaneLineStep*6] = (x[4] + x[5] +x[6] + x[7] * 2 +
|
||||
x[8] + x[9] +x[9] + 4) >> 3;
|
||||
Des[PlaneLineStep*7] = (x[5] + x[6] +x[7] + x[8] * 2 +
|
||||
x[9] + x[9] +x[9] + 4) >> 3;
|
||||
|
||||
}else {
|
||||
/* copy the pixels to destination */
|
||||
Des[0 ]= (unsigned char)x[1];
|
||||
Des[PlaneLineStep ]= (unsigned char)x[2];
|
||||
Des[PlaneLineStep*2]= (unsigned char)x[3];
|
||||
Des[PlaneLineStep*3]= (unsigned char)x[4];
|
||||
Des[PlaneLineStep*4]= (unsigned char)x[5];
|
||||
Des[PlaneLineStep*5]= (unsigned char)x[6];
|
||||
Des[PlaneLineStep*6]= (unsigned char)x[7];
|
||||
Des[PlaneLineStep*7]= (unsigned char)x[8];
|
||||
}
|
||||
Src ++;
|
||||
Des ++;
|
||||
}
|
||||
|
||||
|
||||
/* done with filtering the horizontal edge, now let's do the
|
||||
vertical one */
|
||||
/* skip the first one */
|
||||
if(CurrentFrag==StartFrag)
|
||||
CurrentFrag++;
|
||||
else{
|
||||
Des=DesPtr-8*PlaneLineStep+8*(CurrentFrag-StartFrag);
|
||||
Src=Des-5;
|
||||
Des-=4;
|
||||
|
||||
QStep = QuantScale[pbi->FragQIndex[CurrentFrag]];
|
||||
FLimit = ( QStep * 3 ) >> 2;
|
||||
|
||||
for( j=0; j<8 ; j++){
|
||||
x[0] = Src[0];
|
||||
x[1] = Src[1];
|
||||
x[2] = Src[2];
|
||||
x[3] = Src[3];
|
||||
x[4] = Src[4];
|
||||
x[5] = Src[5];
|
||||
x[6] = Src[6];
|
||||
x[7] = Src[7];
|
||||
x[8] = Src[8];
|
||||
x[9] = Src[9];
|
||||
|
||||
Sum1=Sum2=0;
|
||||
|
||||
for(k=1;k<=4;k++){
|
||||
Sum1 += abs(x[k]-x[k-1]);
|
||||
Sum2 += abs(x[k+4]-x[k+5]);
|
||||
}
|
||||
|
||||
pbi->FragmentVariances[CurrentFrag-1] += ((Sum1>255)?255:Sum1);
|
||||
pbi->FragmentVariances[CurrentFrag] += ((Sum2>255)?255:Sum2);
|
||||
|
||||
if( Sum1 < FLimit &&
|
||||
Sum2 < FLimit &&
|
||||
(x[5] - x[4]) < QStep &&
|
||||
(x[4] - x[5]) < QStep ){
|
||||
|
||||
/* low pass filtering (LPF7: 1 1 1 2 1 1 1) */
|
||||
Des[0] = (x[0] + x[0] +x[0] + x[1] * 2 + x[2] + x[3] +x[4] + 4) >> 3;
|
||||
Des[1] = (x[0] + x[0] +x[1] + x[2] * 2 + x[3] + x[4] +x[5] + 4) >> 3;
|
||||
Des[2] = (x[0] + x[1] +x[2] + x[3] * 2 + x[4] + x[5] +x[6] + 4) >> 3;
|
||||
Des[3] = (x[1] + x[2] +x[3] + x[4] * 2 + x[5] + x[6] +x[7] + 4) >> 3;
|
||||
Des[4] = (x[2] + x[3] +x[4] + x[5] * 2 + x[6] + x[7] +x[8] + 4) >> 3;
|
||||
Des[5] = (x[3] + x[4] +x[5] + x[6] * 2 + x[7] + x[8] +x[9] + 4) >> 3;
|
||||
Des[6] = (x[4] + x[5] +x[6] + x[7] * 2 + x[8] + x[9] +x[9] + 4) >> 3;
|
||||
Des[7] = (x[5] + x[6] +x[7] + x[8] * 2 + x[9] + x[9] +x[9] + 4) >> 3;
|
||||
}
|
||||
|
||||
Src += PlaneLineStep;
|
||||
Des += PlaneLineStep;
|
||||
}
|
||||
CurrentFrag ++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void DeblockVerticalEdgesInLoopFilteredBand(PB_INSTANCE *pbi,
|
||||
unsigned char *SrcPtr,
|
||||
unsigned char *DesPtr,
|
||||
ogg_uint32_t PlaneLineStep,
|
||||
ogg_uint32_t FragsAcross,
|
||||
ogg_uint32_t StartFrag,
|
||||
ogg_uint32_t *QuantScale){
|
||||
ogg_uint32_t j,k;
|
||||
ogg_uint32_t CurrentFrag=StartFrag;
|
||||
ogg_int32_t QStep;
|
||||
ogg_int32_t FLimit;
|
||||
unsigned char *Src, *Des;
|
||||
ogg_int32_t x[10];
|
||||
ogg_int32_t Sum1, Sum2;
|
||||
|
||||
while(CurrentFrag < StartFrag + FragsAcross-1) {
|
||||
|
||||
Src=SrcPtr+8*(CurrentFrag-StartFrag+1)-5;
|
||||
Des=DesPtr+8*(CurrentFrag-StartFrag+1)-4;
|
||||
|
||||
QStep = QuantScale[pbi->FragQIndex[CurrentFrag+1]];
|
||||
FLimit = ( QStep * 3)>>2 ;
|
||||
|
||||
for( j=0; j<8 ; j++){
|
||||
x[0] = Src[0];
|
||||
x[1] = Src[1];
|
||||
x[2] = Src[2];
|
||||
x[3] = Src[3];
|
||||
x[4] = Src[4];
|
||||
x[5] = Src[5];
|
||||
x[6] = Src[6];
|
||||
x[7] = Src[7];
|
||||
x[8] = Src[8];
|
||||
x[9] = Src[9];
|
||||
|
||||
Sum1=Sum2=0;
|
||||
|
||||
for(k=1;k<=4;k++){
|
||||
Sum1 += abs(x[k]-x[k-1]);
|
||||
Sum2 += abs(x[k+4]-x[k+5]);
|
||||
}
|
||||
|
||||
pbi->FragmentVariances[CurrentFrag] += ((Sum1>255)?255:Sum1);
|
||||
pbi->FragmentVariances[CurrentFrag+1] += ((Sum2>255)?255:Sum2);
|
||||
|
||||
|
||||
if( Sum1 < FLimit &&
|
||||
Sum2 < FLimit &&
|
||||
(x[5] - x[4]) < QStep &&
|
||||
(x[4] - x[5]) < QStep ){
|
||||
|
||||
/* low pass filtering (LPF7: 1 1 1 2 1 1 1) */
|
||||
Des[0] = (x[0] + x[0] +x[0] + x[1] * 2 + x[2] + x[3] +x[4] + 4) >> 3;
|
||||
Des[1] = (x[0] + x[0] +x[1] + x[2] * 2 + x[3] + x[4] +x[5] + 4) >> 3;
|
||||
Des[2] = (x[0] + x[1] +x[2] + x[3] * 2 + x[4] + x[5] +x[6] + 4) >> 3;
|
||||
Des[3] = (x[1] + x[2] +x[3] + x[4] * 2 + x[5] + x[6] +x[7] + 4) >> 3;
|
||||
Des[4] = (x[2] + x[3] +x[4] + x[5] * 2 + x[6] + x[7] +x[8] + 4) >> 3;
|
||||
Des[5] = (x[3] + x[4] +x[5] + x[6] * 2 + x[7] + x[8] +x[9] + 4) >> 3;
|
||||
Des[6] = (x[4] + x[5] +x[6] + x[7] * 2 + x[8] + x[9] +x[9] + 4) >> 3;
|
||||
Des[7] = (x[5] + x[6] +x[7] + x[8] * 2 + x[9] + x[9] +x[9] + 4) >> 3;
|
||||
}
|
||||
Src +=PlaneLineStep;
|
||||
Des +=PlaneLineStep;
|
||||
|
||||
}
|
||||
CurrentFrag ++;
|
||||
}
|
||||
}
|
||||
|
||||
static void DeblockPlane(PB_INSTANCE *pbi,
|
||||
unsigned char *SourceBuffer,
|
||||
unsigned char *DestinationBuffer,
|
||||
ogg_uint32_t Channel ){
|
||||
|
||||
ogg_uint32_t i,k;
|
||||
ogg_uint32_t PlaneLineStep=0;
|
||||
ogg_uint32_t StartFrag =0;
|
||||
ogg_uint32_t PixelIndex=0;
|
||||
unsigned char * SrcPtr=0, * DesPtr=0;
|
||||
ogg_uint32_t FragsAcross=0;
|
||||
ogg_uint32_t FragsDown=0;
|
||||
ogg_uint32_t *QuantScale=0;
|
||||
|
||||
switch( Channel ){
|
||||
case 0:
|
||||
/* Get the parameters */
|
||||
PlaneLineStep = pbi->YStride;
|
||||
FragsAcross = pbi->HFragments;
|
||||
FragsDown = pbi->VFragments;
|
||||
StartFrag = 0;
|
||||
PixelIndex = pbi->ReconYDataOffset;
|
||||
SrcPtr = & SourceBuffer[PixelIndex];
|
||||
DesPtr = & DestinationBuffer[PixelIndex];
|
||||
break;
|
||||
|
||||
case 1:
|
||||
/* Get the parameters */
|
||||
PlaneLineStep = pbi->UVStride;
|
||||
FragsAcross = pbi->HFragments / 2;
|
||||
FragsDown = pbi->VFragments / 2;
|
||||
StartFrag = pbi->YPlaneFragments;
|
||||
|
||||
PixelIndex = pbi->ReconUDataOffset;
|
||||
SrcPtr = & SourceBuffer[PixelIndex];
|
||||
DesPtr = & DestinationBuffer[PixelIndex];
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Get the parameters */
|
||||
PlaneLineStep = pbi->UVStride;
|
||||
FragsAcross = pbi->HFragments / 2;
|
||||
FragsDown = pbi->VFragments / 2;
|
||||
StartFrag = pbi->YPlaneFragments + pbi->UVPlaneFragments;
|
||||
|
||||
PixelIndex = pbi->ReconVDataOffset;
|
||||
SrcPtr = & SourceBuffer[PixelIndex];
|
||||
DesPtr = & DestinationBuffer[PixelIndex];
|
||||
break;
|
||||
}
|
||||
|
||||
QuantScale = DcQuantScaleV1;
|
||||
|
||||
for(i=0;i<4;i++)
|
||||
memcpy(DesPtr+i*PlaneLineStep, SrcPtr+i*PlaneLineStep, PlaneLineStep);
|
||||
|
||||
k = 1;
|
||||
|
||||
while( k < FragsDown ){
|
||||
|
||||
SrcPtr += 8*PlaneLineStep;
|
||||
DesPtr += 8*PlaneLineStep;
|
||||
|
||||
/* Filter both the horizontal and vertical block edges inside the band */
|
||||
DeblockLoopFilteredBand(pbi, SrcPtr, DesPtr, PlaneLineStep,
|
||||
FragsAcross, StartFrag, QuantScale);
|
||||
|
||||
/* Move Pointers */
|
||||
StartFrag += FragsAcross;
|
||||
|
||||
k ++;
|
||||
}
|
||||
|
||||
/* The Last band */
|
||||
for(i=0;i<4;i++)
|
||||
memcpy(DesPtr+(i+4)*PlaneLineStep,
|
||||
SrcPtr+(i+4)*PlaneLineStep,
|
||||
PlaneLineStep);
|
||||
|
||||
DeblockVerticalEdgesInLoopFilteredBand(pbi,SrcPtr,DesPtr,PlaneLineStep,
|
||||
FragsAcross,StartFrag,QuantScale);
|
||||
|
||||
}
|
||||
|
||||
static void DeblockFrame(PB_INSTANCE *pbi, unsigned char *SourceBuffer,
|
||||
unsigned char *DestinationBuffer){
|
||||
|
||||
memset(pbi->FragmentVariances, 0 , sizeof(ogg_int32_t) * pbi->UnitFragments);
|
||||
|
||||
|
||||
UpdateFragQIndex(pbi);
|
||||
|
||||
|
||||
SetupLoopFilter(pbi);
|
||||
|
||||
/* Y */
|
||||
DeblockPlane( pbi, SourceBuffer, DestinationBuffer, 0);
|
||||
|
||||
/* U */
|
||||
DeblockPlane( pbi, SourceBuffer, DestinationBuffer, 1);
|
||||
|
||||
/* V */
|
||||
DeblockPlane( pbi, SourceBuffer, DestinationBuffer, 2);
|
||||
|
||||
}
|
||||
|
||||
void PostProcess(PB_INSTANCE *pbi){
|
||||
|
||||
switch (pbi->PostProcessingLevel){
|
||||
case 8:
|
||||
/* on a slow machine, use a simpler and faster deblocking filter */
|
||||
DeblockFrame(pbi, pbi->LastFrameRecon,pbi->PostProcessBuffer);
|
||||
break;
|
||||
|
||||
case 6:
|
||||
DeblockFrame(pbi, pbi->LastFrameRecon,pbi->PostProcessBuffer);
|
||||
UpdateUMVBorder(pbi, pbi->PostProcessBuffer );
|
||||
DeringFrame(pbi, pbi->PostProcessBuffer, pbi->PostProcessBuffer);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
DeblockFrame(pbi, pbi->LastFrameRecon,pbi->PostProcessBuffer);
|
||||
UpdateUMVBorder(pbi, pbi->PostProcessBuffer );
|
||||
DeringFrame(pbi, pbi->PostProcessBuffer, pbi->PostProcessBuffer);
|
||||
break;
|
||||
case 4:
|
||||
DeblockFrame(pbi, pbi->LastFrameRecon, pbi->PostProcessBuffer);
|
||||
break;
|
||||
case 1:
|
||||
UpdateFragQIndex(pbi);
|
||||
break;
|
||||
|
||||
case 0:
|
||||
break;
|
||||
|
||||
default:
|
||||
DeblockFrame(pbi, pbi->LastFrameRecon, pbi->PostProcessBuffer);
|
||||
UpdateUMVBorder(pbi, pbi->PostProcessBuffer );
|
||||
DeringFrame(pbi, pbi->PostProcessBuffer, pbi->PostProcessBuffer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
48
src/add-ons/media/plugins/theora/libtheora/pp.h
Normal file
48
src/add-ons/media/plugins/theora/libtheora/pp.h
Normal file
@ -0,0 +1,48 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2003 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function:
|
||||
last mod: $Id: pp.h,v 1.1 2004/02/24 13:50:13 shatty Exp $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
/* Constants. */
|
||||
#define INTERNAL_BLOCK_HEIGHT 8
|
||||
#define INTERNAL_BLOCK_WIDTH 8
|
||||
|
||||
|
||||
/* NEW Line search values. */
|
||||
#define UP 0
|
||||
#define DOWN 1
|
||||
#define LEFT 2
|
||||
#define RIGHT 3
|
||||
|
||||
#define FIRST_ROW 0
|
||||
#define NOT_EDGE_ROW 1
|
||||
#define LAST_ROW 2
|
||||
|
||||
#define YDIFF_CB_ROWS (INTERNAL_BLOCK_HEIGHT * 3)
|
||||
#define CHLOCALS_CB_ROWS (INTERNAL_BLOCK_HEIGHT * 3)
|
||||
#define PMAP_CB_ROWS (INTERNAL_BLOCK_HEIGHT * 3)
|
||||
#define PSCORE_CB_ROWS (INTERNAL_BLOCK_HEIGHT * 4)
|
||||
|
||||
/* Status values in block coding map */
|
||||
#define CANDIDATE_BLOCK_LOW -2
|
||||
#define CANDIDATE_BLOCK -1
|
||||
#define BLOCK_NOT_CODED 0
|
||||
#define BLOCK_CODED_BAR 3
|
||||
#define BLOCK_CODED_SGC 4
|
||||
#define BLOCK_CODED_LOW 4
|
||||
#define BLOCK_CODED 5
|
||||
|
||||
#define MAX_PREV_FRAMES 16
|
||||
#define MAX_SEARCH_LINE_LEN 7
|
693
src/add-ons/media/plugins/theora/libtheora/quant.c
Normal file
693
src/add-ons/media/plugins/theora/libtheora/quant.c
Normal file
@ -0,0 +1,693 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2003 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function:
|
||||
last mod: $Id: quant.c,v 1.1 2004/02/24 13:50:13 shatty Exp $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include "encoder_internal.h"
|
||||
#include "quant_lookup.h"
|
||||
|
||||
static ogg_uint32_t QThreshTableV1[Q_TABLE_SIZE] = {
|
||||
500, 450, 400, 370, 340, 310, 285, 265,
|
||||
245, 225, 210, 195, 185, 180, 170, 160,
|
||||
150, 145, 135, 130, 125, 115, 110, 107,
|
||||
100, 96, 93, 89, 85, 82, 75, 74,
|
||||
70, 68, 64, 60, 57, 56, 52, 50,
|
||||
49, 45, 44, 43, 40, 38, 37, 35,
|
||||
33, 32, 30, 29, 28, 25, 24, 22,
|
||||
21, 19, 18, 17, 15, 13, 12, 10
|
||||
};
|
||||
|
||||
static Q_LIST_ENTRY DcScaleFactorTableV1[ Q_TABLE_SIZE ] = {
|
||||
220, 200, 190, 180, 170, 170, 160, 160,
|
||||
150, 150, 140, 140, 130, 130, 120, 120,
|
||||
110, 110, 100, 100, 90, 90, 90, 80,
|
||||
80, 80, 70, 70, 70, 60, 60, 60,
|
||||
60, 50, 50, 50, 50, 40, 40, 40,
|
||||
40, 40, 30, 30, 30, 30, 30, 30,
|
||||
30, 20, 20, 20, 20, 20, 20, 20,
|
||||
20, 10, 10, 10, 10, 10, 10, 10
|
||||
};
|
||||
|
||||
/* dbm -- defined some alternative tables to test header packing */
|
||||
#define NEW_QTABLES 0
|
||||
#if NEW_QTABLES
|
||||
|
||||
static Q_LIST_ENTRY Y_coeffsV1[64] =
|
||||
{
|
||||
8, 16, 16, 16, 20, 20, 20, 20,
|
||||
16, 16, 16, 16, 20, 20, 20, 20,
|
||||
16, 16, 16, 16, 22, 22, 22, 22,
|
||||
16, 16, 16, 16, 22, 22, 22, 22,
|
||||
20, 20, 22, 22, 24, 24, 24, 24,
|
||||
20, 20, 22, 22, 24, 24, 24, 24,
|
||||
20, 20, 22, 22, 24, 24, 24, 24,
|
||||
20, 20, 22, 22, 24, 24, 24, 24
|
||||
};
|
||||
|
||||
static Q_LIST_ENTRY UV_coeffsV1[64] =
|
||||
{ 17, 18, 24, 47, 99, 99, 99, 99,
|
||||
18, 21, 26, 66, 99, 99, 99, 99,
|
||||
24, 26, 56, 99, 99, 99, 99, 99,
|
||||
47, 66, 99, 99, 99, 99, 99, 99,
|
||||
99, 99, 99, 99, 99, 99, 99, 99,
|
||||
99, 99, 99, 99, 99, 99, 99, 99,
|
||||
99, 99, 99, 99, 99, 99, 99, 99,
|
||||
99, 99, 99, 99, 99, 99, 99, 99
|
||||
};
|
||||
|
||||
/* Different matrices for different encoder versions */
|
||||
static Q_LIST_ENTRY Inter_coeffsV1[64] =
|
||||
{
|
||||
12, 16, 16, 16, 20, 20, 20, 20,
|
||||
16, 16, 16, 16, 20, 20, 20, 20,
|
||||
16, 16, 16, 16, 22, 22, 22, 22,
|
||||
16, 16, 16, 16, 22, 22, 22, 22,
|
||||
20, 20, 22, 22, 24, 24, 24, 24,
|
||||
20, 20, 22, 22, 24, 24, 24, 24,
|
||||
20, 20, 22, 22, 24, 24, 24, 24,
|
||||
20, 20, 22, 22, 24, 24, 24, 24
|
||||
};
|
||||
|
||||
#else /* these are the old VP3 values: */
|
||||
|
||||
static Q_LIST_ENTRY Y_coeffsV1[64] ={
|
||||
16, 11, 10, 16, 24, 40, 51, 61,
|
||||
12, 12, 14, 19, 26, 58, 60, 55,
|
||||
14, 13, 16, 24, 40, 57, 69, 56,
|
||||
14, 17, 22, 29, 51, 87, 80, 62,
|
||||
18, 22, 37, 58, 68, 109, 103, 77,
|
||||
24, 35, 55, 64, 81, 104, 113, 92,
|
||||
49, 64, 78, 87, 103, 121, 120, 101,
|
||||
72, 92, 95, 98, 112, 100, 103, 99
|
||||
};
|
||||
|
||||
static Q_LIST_ENTRY UV_coeffsV1[64] ={
|
||||
17, 18, 24, 47, 99, 99, 99, 99,
|
||||
18, 21, 26, 66, 99, 99, 99, 99,
|
||||
24, 26, 56, 99, 99, 99, 99, 99,
|
||||
47, 66, 99, 99, 99, 99, 99, 99,
|
||||
99, 99, 99, 99, 99, 99, 99, 99,
|
||||
99, 99, 99, 99, 99, 99, 99, 99,
|
||||
99, 99, 99, 99, 99, 99, 99, 99,
|
||||
99, 99, 99, 99, 99, 99, 99, 99
|
||||
};
|
||||
|
||||
/* Different matrices for different encoder versions */
|
||||
static Q_LIST_ENTRY Inter_coeffsV1[64] ={
|
||||
16, 16, 16, 20, 24, 28, 32, 40,
|
||||
16, 16, 20, 24, 28, 32, 40, 48,
|
||||
16, 20, 24, 28, 32, 40, 48, 64,
|
||||
20, 24, 28, 32, 40, 48, 64, 64,
|
||||
24, 28, 32, 40, 48, 64, 64, 64,
|
||||
28, 32, 40, 48, 64, 64, 64, 96,
|
||||
32, 40, 48, 64, 64, 64, 96, 128,
|
||||
40, 48, 64, 64, 64, 96, 128, 128
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
void WriteQTables(PB_INSTANCE *pbi,oggpack_buffer* opb) {
|
||||
int x;
|
||||
for(x=0; x<64; x++) {
|
||||
oggpackB_write(opb, pbi->QThreshTable[x],16);
|
||||
}
|
||||
for(x=0; x<64; x++) {
|
||||
oggpackB_write(opb, pbi->DcScaleFactorTable[x],16);
|
||||
}
|
||||
for(x=0; x<64; x++) {
|
||||
oggpackB_write(opb, pbi->Y_coeffs[x],8);
|
||||
}
|
||||
for(x=0; x<64; x++) {
|
||||
oggpackB_write(opb, pbi->UV_coeffs[x],8);
|
||||
}
|
||||
for(x=0; x<64; x++) {
|
||||
oggpackB_write(opb, pbi->Inter_coeffs[x],8);
|
||||
}
|
||||
}
|
||||
|
||||
int ReadQTables(codec_setup_info *ci, oggpack_buffer* opb) {
|
||||
long bits;
|
||||
int x;
|
||||
for(x=0; x<Q_TABLE_SIZE; x++) {
|
||||
theora_read(opb,16,&bits);
|
||||
if(bits<0)return OC_BADHEADER;
|
||||
ci->QThreshTable[x]=bits;
|
||||
}
|
||||
for(x=0; x<Q_TABLE_SIZE; x++) {
|
||||
theora_read(opb,16,&bits);
|
||||
if(bits<0)return OC_BADHEADER;
|
||||
ci->DcScaleFactorTable[x]=(Q_LIST_ENTRY)bits;
|
||||
}
|
||||
for(x=0; x<64; x++) {
|
||||
theora_read(opb,8,&bits);
|
||||
if(bits<0)return OC_BADHEADER;
|
||||
ci->Y_coeffs[x]=(Q_LIST_ENTRY)bits;
|
||||
}
|
||||
for(x=0; x<64; x++) {
|
||||
theora_read(opb,8,&bits);
|
||||
if(bits<0)return OC_BADHEADER;
|
||||
ci->UV_coeffs[x]=(Q_LIST_ENTRY)bits;
|
||||
}
|
||||
for(x=0; x<64; x++) {
|
||||
theora_read(opb,8,&bits);
|
||||
if(bits<0)return OC_BADHEADER;
|
||||
ci->Inter_coeffs[x]=(Q_LIST_ENTRY)bits;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CopyQTables(PB_INSTANCE *pbi, codec_setup_info *ci) {
|
||||
memcpy(pbi->QThreshTable, ci->QThreshTable, sizeof(pbi->QThreshTable));
|
||||
memcpy(pbi->DcScaleFactorTable, ci->DcScaleFactorTable,
|
||||
sizeof(pbi->DcScaleFactorTable));
|
||||
memcpy(pbi->Y_coeffs, ci->Y_coeffs, sizeof(pbi->Y_coeffs));
|
||||
memcpy(pbi->UV_coeffs, ci->UV_coeffs, sizeof(pbi->UV_coeffs));
|
||||
memcpy(pbi->Inter_coeffs, ci->Inter_coeffs, sizeof(pbi->Inter_coeffs));
|
||||
}
|
||||
|
||||
/* Initialize custom qtables using the VP31 values.
|
||||
Someday we can change the quant tables to be adaptive, or just plain
|
||||
better.*/
|
||||
void InitQTables( PB_INSTANCE *pbi ){
|
||||
memcpy(pbi->QThreshTable, QThreshTableV1, sizeof(pbi->QThreshTable));
|
||||
memcpy(pbi->DcScaleFactorTable, DcScaleFactorTableV1,
|
||||
sizeof(pbi->DcScaleFactorTable));
|
||||
memcpy(pbi->Y_coeffs, Y_coeffsV1, sizeof(pbi->Y_coeffs));
|
||||
memcpy(pbi->UV_coeffs, UV_coeffsV1, sizeof(pbi->UV_coeffs));
|
||||
memcpy(pbi->Inter_coeffs, Inter_coeffsV1, sizeof(pbi->Inter_coeffs));
|
||||
}
|
||||
|
||||
static void BuildQuantIndex_Generic(PB_INSTANCE *pbi){
|
||||
ogg_int32_t i,j;
|
||||
|
||||
/* invert the dequant index into the quant index */
|
||||
for ( i = 0; i < BLOCK_SIZE; i++ ){
|
||||
j = dequant_index[i];
|
||||
pbi->quant_index[j] = i;
|
||||
}
|
||||
}
|
||||
|
||||
static void init_quantizer ( CP_INSTANCE *cpi,
|
||||
ogg_uint32_t scale_factor,
|
||||
unsigned char QIndex ){
|
||||
int i;
|
||||
double ZBinFactor;
|
||||
double RoundingFactor;
|
||||
|
||||
double temp_fp_quant_coeffs;
|
||||
double temp_fp_quant_round;
|
||||
double temp_fp_ZeroBinSize;
|
||||
PB_INSTANCE *pbi = &cpi->pb;
|
||||
|
||||
Q_LIST_ENTRY * Inter_coeffs;
|
||||
Q_LIST_ENTRY * Y_coeffs;
|
||||
Q_LIST_ENTRY * UV_coeffs;
|
||||
Q_LIST_ENTRY * DcScaleFactorTable;
|
||||
Q_LIST_ENTRY * UVDcScaleFactorTable;
|
||||
|
||||
/* Notes on setup of quantisers. The initial multiplication by
|
||||
the scale factor is done in the ogg_int32_t domain to insure that the
|
||||
precision in the quantiser is the same as in the inverse
|
||||
quantiser where all calculations are integer. The "<< 2" is a
|
||||
normalisation factor for the forward DCT transform. */
|
||||
|
||||
/* New version rounding and ZB characteristics. */
|
||||
Inter_coeffs = Inter_coeffsV1;
|
||||
Y_coeffs = Y_coeffsV1;
|
||||
UV_coeffs = UV_coeffsV1;
|
||||
DcScaleFactorTable = DcScaleFactorTableV1;
|
||||
UVDcScaleFactorTable = DcScaleFactorTableV1;
|
||||
ZBinFactor = 0.9;
|
||||
|
||||
switch(cpi->pb.info.sharpness){
|
||||
case 0:
|
||||
ZBinFactor = 0.65;
|
||||
if ( scale_factor <= 50 )
|
||||
RoundingFactor = 0.499;
|
||||
else
|
||||
RoundingFactor = 0.46;
|
||||
break;
|
||||
case 1:
|
||||
ZBinFactor = 0.75;
|
||||
if ( scale_factor <= 50 )
|
||||
RoundingFactor = 0.476;
|
||||
else
|
||||
RoundingFactor = 0.400;
|
||||
break;
|
||||
|
||||
default:
|
||||
ZBinFactor = 0.9;
|
||||
if ( scale_factor <= 50 )
|
||||
RoundingFactor = 0.476;
|
||||
else
|
||||
RoundingFactor = 0.333;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Use fixed multiplier for intra Y DC */
|
||||
temp_fp_quant_coeffs =
|
||||
(((ogg_uint32_t)(DcScaleFactorTable[QIndex] * Y_coeffs[0])/100) << 2);
|
||||
if ( temp_fp_quant_coeffs < MIN_LEGAL_QUANT_ENTRY * 2 )
|
||||
temp_fp_quant_coeffs = MIN_LEGAL_QUANT_ENTRY * 2;
|
||||
|
||||
temp_fp_quant_round = temp_fp_quant_coeffs * RoundingFactor;
|
||||
pbi->fp_quant_Y_round[0] = (ogg_int32_t) (0.5 + temp_fp_quant_round);
|
||||
|
||||
temp_fp_ZeroBinSize = temp_fp_quant_coeffs * ZBinFactor;
|
||||
pbi->fp_ZeroBinSize_Y[0] = (ogg_int32_t) (0.5 + temp_fp_ZeroBinSize);
|
||||
|
||||
temp_fp_quant_coeffs = 1.0 / temp_fp_quant_coeffs;
|
||||
pbi->fp_quant_Y_coeffs[0] = (0.5 + SHIFT16 * temp_fp_quant_coeffs);
|
||||
|
||||
/* Intra UV */
|
||||
temp_fp_quant_coeffs =
|
||||
(((ogg_uint32_t)(UVDcScaleFactorTable[QIndex] * UV_coeffs[0])/100) << 2);
|
||||
if ( temp_fp_quant_coeffs < MIN_LEGAL_QUANT_ENTRY * 2)
|
||||
temp_fp_quant_coeffs = MIN_LEGAL_QUANT_ENTRY * 2;
|
||||
|
||||
temp_fp_quant_round = temp_fp_quant_coeffs * RoundingFactor;
|
||||
pbi->fp_quant_UV_round[0] = (0.5 + temp_fp_quant_round);
|
||||
|
||||
temp_fp_ZeroBinSize = temp_fp_quant_coeffs * ZBinFactor;
|
||||
pbi->fp_ZeroBinSize_UV[0] = (0.5 + temp_fp_ZeroBinSize);
|
||||
|
||||
temp_fp_quant_coeffs = 1.0 / temp_fp_quant_coeffs;
|
||||
pbi->fp_quant_UV_coeffs[0]= (0.5 + SHIFT16 * temp_fp_quant_coeffs);
|
||||
|
||||
/* Inter Y */
|
||||
temp_fp_quant_coeffs =
|
||||
(((ogg_uint32_t)(DcScaleFactorTable[QIndex] * Inter_coeffs[0])/100) << 2);
|
||||
if ( temp_fp_quant_coeffs < MIN_LEGAL_QUANT_ENTRY * 4)
|
||||
temp_fp_quant_coeffs = MIN_LEGAL_QUANT_ENTRY * 4;
|
||||
|
||||
temp_fp_quant_round = temp_fp_quant_coeffs * RoundingFactor;
|
||||
pbi->fp_quant_Inter_round[0]= (0.5 + temp_fp_quant_round);
|
||||
|
||||
temp_fp_ZeroBinSize = temp_fp_quant_coeffs * ZBinFactor;
|
||||
pbi->fp_ZeroBinSize_Inter[0]= (0.5 + temp_fp_ZeroBinSize);
|
||||
|
||||
temp_fp_quant_coeffs= 1.0 / temp_fp_quant_coeffs;
|
||||
pbi->fp_quant_Inter_coeffs[0]= (0.5 + SHIFT16 * temp_fp_quant_coeffs);
|
||||
|
||||
/* Inter UV */
|
||||
temp_fp_quant_coeffs =
|
||||
(((ogg_uint32_t)(UVDcScaleFactorTable[QIndex] * Inter_coeffs[0])/100) << 2);
|
||||
if ( temp_fp_quant_coeffs < MIN_LEGAL_QUANT_ENTRY * 4)
|
||||
temp_fp_quant_coeffs = MIN_LEGAL_QUANT_ENTRY * 4;
|
||||
|
||||
temp_fp_quant_round = temp_fp_quant_coeffs * RoundingFactor;
|
||||
pbi->fp_quant_InterUV_round[0]= (0.5 + temp_fp_quant_round);
|
||||
|
||||
temp_fp_ZeroBinSize = temp_fp_quant_coeffs * ZBinFactor;
|
||||
pbi->fp_ZeroBinSize_InterUV[0]= (0.5 + temp_fp_ZeroBinSize);
|
||||
|
||||
temp_fp_quant_coeffs= 1.0 / temp_fp_quant_coeffs;
|
||||
pbi->fp_quant_InterUV_coeffs[0]=
|
||||
(0.5 + SHIFT16 * temp_fp_quant_coeffs);
|
||||
|
||||
for ( i = 1; i < 64; i++ ){
|
||||
/* now scale coefficients by required compression factor */
|
||||
/* Intra Y */
|
||||
temp_fp_quant_coeffs =
|
||||
(((ogg_uint32_t)(scale_factor * Y_coeffs[i]) / 100 ) << 2 );
|
||||
if ( temp_fp_quant_coeffs < (MIN_LEGAL_QUANT_ENTRY) )
|
||||
temp_fp_quant_coeffs = (MIN_LEGAL_QUANT_ENTRY);
|
||||
|
||||
temp_fp_quant_round = temp_fp_quant_coeffs * RoundingFactor;
|
||||
pbi->fp_quant_Y_round[i] = (0.5 + temp_fp_quant_round);
|
||||
|
||||
temp_fp_ZeroBinSize = temp_fp_quant_coeffs * ZBinFactor;
|
||||
pbi->fp_ZeroBinSize_Y[i] = (0.5 + temp_fp_ZeroBinSize);
|
||||
|
||||
temp_fp_quant_coeffs = 1.0 / temp_fp_quant_coeffs;
|
||||
pbi->fp_quant_Y_coeffs[i] = (0.5 + SHIFT16 * temp_fp_quant_coeffs);
|
||||
|
||||
/* Intra UV */
|
||||
temp_fp_quant_coeffs =
|
||||
(((ogg_uint32_t)(scale_factor * UV_coeffs[i]) / 100 ) << 2 );
|
||||
if ( temp_fp_quant_coeffs < (MIN_LEGAL_QUANT_ENTRY))
|
||||
temp_fp_quant_coeffs = (MIN_LEGAL_QUANT_ENTRY);
|
||||
|
||||
temp_fp_quant_round = temp_fp_quant_coeffs * RoundingFactor;
|
||||
pbi->fp_quant_UV_round[i] = (0.5 + temp_fp_quant_round);
|
||||
|
||||
temp_fp_ZeroBinSize = temp_fp_quant_coeffs * ZBinFactor;
|
||||
pbi->fp_ZeroBinSize_UV[i] = (0.5 + temp_fp_ZeroBinSize);
|
||||
|
||||
temp_fp_quant_coeffs = 1.0 / temp_fp_quant_coeffs;
|
||||
pbi->fp_quant_UV_coeffs[i]= (0.5 + SHIFT16 * temp_fp_quant_coeffs);
|
||||
|
||||
/* Inter Y */
|
||||
temp_fp_quant_coeffs =
|
||||
(((ogg_uint32_t)(scale_factor * Inter_coeffs[i]) / 100 ) << 2 );
|
||||
if ( temp_fp_quant_coeffs < (MIN_LEGAL_QUANT_ENTRY * 2) )
|
||||
temp_fp_quant_coeffs = (MIN_LEGAL_QUANT_ENTRY * 2);
|
||||
|
||||
temp_fp_quant_round = temp_fp_quant_coeffs * RoundingFactor;
|
||||
pbi->fp_quant_Inter_round[i]= (0.5 + temp_fp_quant_round);
|
||||
|
||||
temp_fp_ZeroBinSize = temp_fp_quant_coeffs * ZBinFactor;
|
||||
pbi->fp_ZeroBinSize_Inter[i]= (0.5 + temp_fp_ZeroBinSize);
|
||||
|
||||
temp_fp_quant_coeffs = 1.0 / temp_fp_quant_coeffs;
|
||||
pbi->fp_quant_Inter_coeffs[i]= (0.5 + SHIFT16 * temp_fp_quant_coeffs);
|
||||
|
||||
/* Inter UV */
|
||||
temp_fp_quant_coeffs =
|
||||
(((ogg_uint32_t)(scale_factor * Inter_coeffs[i]) / 100 ) << 2 );
|
||||
if ( temp_fp_quant_coeffs < (MIN_LEGAL_QUANT_ENTRY * 2) )
|
||||
temp_fp_quant_coeffs = (MIN_LEGAL_QUANT_ENTRY * 2);
|
||||
|
||||
temp_fp_quant_round = temp_fp_quant_coeffs * RoundingFactor;
|
||||
pbi->fp_quant_InterUV_round[i]= (0.5 + temp_fp_quant_round);
|
||||
|
||||
temp_fp_ZeroBinSize = temp_fp_quant_coeffs * ZBinFactor;
|
||||
pbi->fp_ZeroBinSize_InterUV[i]= (0.5 + temp_fp_ZeroBinSize);
|
||||
|
||||
temp_fp_quant_coeffs = 1.0 / temp_fp_quant_coeffs;
|
||||
pbi->fp_quant_InterUV_coeffs[i]= (0.5 + SHIFT16 * temp_fp_quant_coeffs);
|
||||
|
||||
}
|
||||
|
||||
pbi->fquant_coeffs = pbi->fp_quant_Y_coeffs;
|
||||
|
||||
}
|
||||
|
||||
void select_Y_quantiser ( PB_INSTANCE *pbi ){
|
||||
pbi->fquant_coeffs = pbi->fp_quant_Y_coeffs;
|
||||
pbi->fquant_round = pbi->fp_quant_Y_round;
|
||||
pbi->fquant_ZbSize = pbi->fp_ZeroBinSize_Y;
|
||||
}
|
||||
|
||||
void select_Inter_quantiser ( PB_INSTANCE *pbi ){
|
||||
pbi->fquant_coeffs = pbi->fp_quant_Inter_coeffs;
|
||||
pbi->fquant_round = pbi->fp_quant_Inter_round;
|
||||
pbi->fquant_ZbSize = pbi->fp_ZeroBinSize_Inter;
|
||||
}
|
||||
|
||||
void select_UV_quantiser ( PB_INSTANCE *pbi ){
|
||||
pbi->fquant_coeffs = pbi->fp_quant_UV_coeffs;
|
||||
pbi->fquant_round = pbi->fp_quant_UV_round;
|
||||
pbi->fquant_ZbSize = pbi->fp_quant_UV_round;
|
||||
}
|
||||
|
||||
void select_InterUV_quantiser ( PB_INSTANCE *pbi ){
|
||||
pbi->fquant_coeffs = pbi->fp_quant_InterUV_coeffs;
|
||||
pbi->fquant_round = pbi->fp_quant_InterUV_round;
|
||||
pbi->fquant_ZbSize = pbi->fp_ZeroBinSize_InterUV;
|
||||
}
|
||||
|
||||
void quantize( PB_INSTANCE *pbi,
|
||||
ogg_int16_t * DCT_block,
|
||||
Q_LIST_ENTRY * quantized_list){
|
||||
ogg_uint32_t i; /* Row index */
|
||||
Q_LIST_ENTRY val; /* Quantised value. */
|
||||
|
||||
ogg_int32_t * FquantRoundPtr = pbi->fquant_round;
|
||||
ogg_int32_t * FquantCoeffsPtr = pbi->fquant_coeffs;
|
||||
ogg_int32_t * FquantZBinSizePtr = pbi->fquant_ZbSize;
|
||||
ogg_int16_t * DCT_blockPtr = DCT_block;
|
||||
ogg_uint32_t * QIndexPtr = (ogg_uint32_t *)pbi->quant_index;
|
||||
ogg_int32_t temp;
|
||||
|
||||
/* Set the quantized_list to default to 0 */
|
||||
memset( quantized_list, 0, 64 * sizeof(Q_LIST_ENTRY) );
|
||||
|
||||
/* Note that we add half divisor to effect rounding on positive number */
|
||||
for( i = 0; i < VFRAGPIXELS; i++) {
|
||||
/* Column 0 */
|
||||
if ( DCT_blockPtr[0] >= FquantZBinSizePtr[0] ) {
|
||||
temp = FquantCoeffsPtr[0] * ( DCT_blockPtr[0] + FquantRoundPtr[0] ) ;
|
||||
val = (Q_LIST_ENTRY) (temp>>16);
|
||||
quantized_list[QIndexPtr[0]] = ( val > 511 ) ? 511 : val;
|
||||
} else if ( DCT_blockPtr[0] <= -FquantZBinSizePtr[0] ) {
|
||||
temp = FquantCoeffsPtr[0] *
|
||||
( DCT_blockPtr[0] - FquantRoundPtr[0] ) + MIN16;
|
||||
val = (Q_LIST_ENTRY) (temp>>16);
|
||||
quantized_list[QIndexPtr[0]] = ( val < -511 ) ? -511 : val;
|
||||
}
|
||||
|
||||
/* Column 1 */
|
||||
if ( DCT_blockPtr[1] >= FquantZBinSizePtr[1] ) {
|
||||
temp = FquantCoeffsPtr[1] *
|
||||
( DCT_blockPtr[1] + FquantRoundPtr[1] ) ;
|
||||
val = (Q_LIST_ENTRY) (temp>>16);
|
||||
quantized_list[QIndexPtr[1]] = ( val > 511 ) ? 511 : val;
|
||||
} else if ( DCT_blockPtr[1] <= -FquantZBinSizePtr[1] ) {
|
||||
temp = FquantCoeffsPtr[1] *
|
||||
( DCT_blockPtr[1] - FquantRoundPtr[1] ) + MIN16;
|
||||
val = (Q_LIST_ENTRY) (temp>>16);
|
||||
quantized_list[QIndexPtr[1]] = ( val < -511 ) ? -511 : val;
|
||||
}
|
||||
|
||||
/* Column 2 */
|
||||
if ( DCT_blockPtr[2] >= FquantZBinSizePtr[2] ) {
|
||||
temp = FquantCoeffsPtr[2] *
|
||||
( DCT_blockPtr[2] + FquantRoundPtr[2] ) ;
|
||||
val = (Q_LIST_ENTRY) (temp>>16);
|
||||
quantized_list[QIndexPtr[2]] = ( val > 511 ) ? 511 : val;
|
||||
} else if ( DCT_blockPtr[2] <= -FquantZBinSizePtr[2] ) {
|
||||
temp = FquantCoeffsPtr[2] *
|
||||
( DCT_blockPtr[2] - FquantRoundPtr[2] ) + MIN16;
|
||||
val = (Q_LIST_ENTRY) (temp>>16);
|
||||
quantized_list[QIndexPtr[2]] = ( val < -511 ) ? -511 : val;
|
||||
}
|
||||
|
||||
/* Column 3 */
|
||||
if ( DCT_blockPtr[3] >= FquantZBinSizePtr[3] ) {
|
||||
temp = FquantCoeffsPtr[3] *
|
||||
( DCT_blockPtr[3] + FquantRoundPtr[3] ) ;
|
||||
val = (Q_LIST_ENTRY) (temp>>16);
|
||||
quantized_list[QIndexPtr[3]] = ( val > 511 ) ? 511 : val;
|
||||
} else if ( DCT_blockPtr[3] <= -FquantZBinSizePtr[3] ) {
|
||||
temp = FquantCoeffsPtr[3] *
|
||||
( DCT_blockPtr[3] - FquantRoundPtr[3] ) + MIN16;
|
||||
val = (Q_LIST_ENTRY) (temp>>16);
|
||||
quantized_list[QIndexPtr[3]] = ( val < -511 ) ? -511 : val;
|
||||
}
|
||||
|
||||
/* Column 4 */
|
||||
if ( DCT_blockPtr[4] >= FquantZBinSizePtr[4] ) {
|
||||
temp = FquantCoeffsPtr[4] *
|
||||
( DCT_blockPtr[4] + FquantRoundPtr[4] ) ;
|
||||
val = (Q_LIST_ENTRY) (temp>>16);
|
||||
quantized_list[QIndexPtr[4]] = ( val > 511 ) ? 511 : val;
|
||||
} else if ( DCT_blockPtr[4] <= -FquantZBinSizePtr[4] ) {
|
||||
temp = FquantCoeffsPtr[4] *
|
||||
( DCT_blockPtr[4] - FquantRoundPtr[4] ) + MIN16;
|
||||
val = (Q_LIST_ENTRY) (temp>>16);
|
||||
quantized_list[QIndexPtr[4]] = ( val < -511 ) ? -511 : val;
|
||||
}
|
||||
|
||||
/* Column 5 */
|
||||
if ( DCT_blockPtr[5] >= FquantZBinSizePtr[5] ) {
|
||||
temp = FquantCoeffsPtr[5] *
|
||||
( DCT_blockPtr[5] + FquantRoundPtr[5] ) ;
|
||||
val = (Q_LIST_ENTRY) (temp>>16);
|
||||
quantized_list[QIndexPtr[5]] = ( val > 511 ) ? 511 : val;
|
||||
} else if ( DCT_blockPtr[5] <= -FquantZBinSizePtr[5] ) {
|
||||
temp = FquantCoeffsPtr[5] *
|
||||
( DCT_blockPtr[5] - FquantRoundPtr[5] ) + MIN16;
|
||||
val = (Q_LIST_ENTRY) (temp>>16);
|
||||
quantized_list[QIndexPtr[5]] = ( val < -511 ) ? -511 : val;
|
||||
}
|
||||
|
||||
/* Column 6 */
|
||||
if ( DCT_blockPtr[6] >= FquantZBinSizePtr[6] ) {
|
||||
temp = FquantCoeffsPtr[6] *
|
||||
( DCT_blockPtr[6] + FquantRoundPtr[6] ) ;
|
||||
val = (Q_LIST_ENTRY) (temp>>16);
|
||||
quantized_list[QIndexPtr[6]] = ( val > 511 ) ? 511 : val;
|
||||
} else if ( DCT_blockPtr[6] <= -FquantZBinSizePtr[6] ) {
|
||||
temp = FquantCoeffsPtr[6] *
|
||||
( DCT_blockPtr[6] - FquantRoundPtr[6] ) + MIN16;
|
||||
val = (Q_LIST_ENTRY) (temp>>16);
|
||||
quantized_list[QIndexPtr[6]] = ( val < -511 ) ? -511 : val;
|
||||
}
|
||||
|
||||
/* Column 7 */
|
||||
if ( DCT_blockPtr[7] >= FquantZBinSizePtr[7] ) {
|
||||
temp = FquantCoeffsPtr[7] *
|
||||
( DCT_blockPtr[7] + FquantRoundPtr[7] ) ;
|
||||
val = (Q_LIST_ENTRY) (temp>>16);
|
||||
quantized_list[QIndexPtr[7]] = ( val > 511 ) ? 511 : val;
|
||||
} else if ( DCT_blockPtr[7] <= -FquantZBinSizePtr[7] ) {
|
||||
temp = FquantCoeffsPtr[7] *
|
||||
( DCT_blockPtr[7] - FquantRoundPtr[7] ) + MIN16;
|
||||
val = (Q_LIST_ENTRY) (temp>>16);
|
||||
quantized_list[QIndexPtr[7]] = ( val < -511 ) ? -511 : val;
|
||||
}
|
||||
|
||||
FquantRoundPtr += 8;
|
||||
FquantCoeffsPtr += 8;
|
||||
FquantZBinSizePtr += 8;
|
||||
DCT_blockPtr += 8;
|
||||
QIndexPtr += 8;
|
||||
}
|
||||
}
|
||||
|
||||
static void init_dequantizer ( PB_INSTANCE *pbi,
|
||||
ogg_uint32_t scale_factor,
|
||||
unsigned char QIndex ){
|
||||
int i, j;
|
||||
|
||||
Q_LIST_ENTRY * Inter_coeffs;
|
||||
Q_LIST_ENTRY * Y_coeffs;
|
||||
Q_LIST_ENTRY * UV_coeffs;
|
||||
Q_LIST_ENTRY * DcScaleFactorTable;
|
||||
Q_LIST_ENTRY * UVDcScaleFactorTable;
|
||||
|
||||
Inter_coeffs = pbi->Inter_coeffs;
|
||||
Y_coeffs = pbi->Y_coeffs;
|
||||
UV_coeffs = pbi->UV_coeffs;
|
||||
DcScaleFactorTable = pbi->DcScaleFactorTable;
|
||||
UVDcScaleFactorTable = pbi->DcScaleFactorTable;
|
||||
|
||||
/* invert the dequant index into the quant index
|
||||
the dxer has a different order than the cxer. */
|
||||
BuildQuantIndex_Generic(pbi);
|
||||
|
||||
/* Reorder dequantisation coefficients into dct zigzag order. */
|
||||
for ( i = 0; i < BLOCK_SIZE; i++ ) {
|
||||
j = pbi->quant_index[i];
|
||||
pbi->dequant_Y_coeffs[j] = Y_coeffs[i];
|
||||
}
|
||||
for ( i = 0; i < BLOCK_SIZE; i++ ){
|
||||
j = pbi->quant_index[i];
|
||||
pbi->dequant_Inter_coeffs[j] = Inter_coeffs[i];
|
||||
}
|
||||
for ( i = 0; i < BLOCK_SIZE; i++ ){
|
||||
j = pbi->quant_index[i];
|
||||
pbi->dequant_UV_coeffs[j] = UV_coeffs[i];
|
||||
}
|
||||
for ( i = 0; i < BLOCK_SIZE; i++ ){
|
||||
j = pbi->quant_index[i];
|
||||
pbi->dequant_InterUV_coeffs[j] = Inter_coeffs[i];
|
||||
}
|
||||
|
||||
/* Intra Y */
|
||||
pbi->dequant_Y_coeffs[0] =
|
||||
((DcScaleFactorTable[QIndex] * pbi->dequant_Y_coeffs[0])/100);
|
||||
if ( pbi->dequant_Y_coeffs[0] < MIN_DEQUANT_VAL * 2 )
|
||||
pbi->dequant_Y_coeffs[0] = MIN_DEQUANT_VAL * 2;
|
||||
pbi->dequant_Y_coeffs[0] =
|
||||
pbi->dequant_Y_coeffs[0] << IDCT_SCALE_FACTOR;
|
||||
|
||||
/* Intra UV */
|
||||
pbi->dequant_UV_coeffs[0] =
|
||||
((UVDcScaleFactorTable[QIndex] * pbi->dequant_UV_coeffs[0])/100);
|
||||
if ( pbi->dequant_UV_coeffs[0] < MIN_DEQUANT_VAL * 2 )
|
||||
pbi->dequant_UV_coeffs[0] = MIN_DEQUANT_VAL * 2;
|
||||
pbi->dequant_UV_coeffs[0] =
|
||||
pbi->dequant_UV_coeffs[0] << IDCT_SCALE_FACTOR;
|
||||
|
||||
/* Inter Y */
|
||||
pbi->dequant_Inter_coeffs[0] =
|
||||
((DcScaleFactorTable[QIndex] * pbi->dequant_Inter_coeffs[0])/100);
|
||||
if ( pbi->dequant_Inter_coeffs[0] < MIN_DEQUANT_VAL * 4 )
|
||||
pbi->dequant_Inter_coeffs[0] = MIN_DEQUANT_VAL * 4;
|
||||
pbi->dequant_Inter_coeffs[0] =
|
||||
pbi->dequant_Inter_coeffs[0] << IDCT_SCALE_FACTOR;
|
||||
|
||||
/* Inter UV */
|
||||
pbi->dequant_InterUV_coeffs[0] =
|
||||
((UVDcScaleFactorTable[QIndex] * pbi->dequant_InterUV_coeffs[0])/100);
|
||||
if ( pbi->dequant_InterUV_coeffs[0] < MIN_DEQUANT_VAL * 4 )
|
||||
pbi->dequant_InterUV_coeffs[0] = MIN_DEQUANT_VAL * 4;
|
||||
pbi->dequant_InterUV_coeffs[0] =
|
||||
pbi->dequant_InterUV_coeffs[0] << IDCT_SCALE_FACTOR;
|
||||
|
||||
for ( i = 1; i < 64; i++ ){
|
||||
/* now scale coefficients by required compression factor */
|
||||
pbi->dequant_Y_coeffs[i] =
|
||||
(( scale_factor * pbi->dequant_Y_coeffs[i] ) / 100);
|
||||
if ( pbi->dequant_Y_coeffs[i] < MIN_DEQUANT_VAL )
|
||||
pbi->dequant_Y_coeffs[i] = MIN_DEQUANT_VAL;
|
||||
pbi->dequant_Y_coeffs[i] =
|
||||
pbi->dequant_Y_coeffs[i] << IDCT_SCALE_FACTOR;
|
||||
|
||||
pbi->dequant_UV_coeffs[i] =
|
||||
(( scale_factor * pbi->dequant_UV_coeffs[i] ) / 100);
|
||||
if ( pbi->dequant_UV_coeffs[i] < MIN_DEQUANT_VAL )
|
||||
pbi->dequant_UV_coeffs[i] = MIN_DEQUANT_VAL;
|
||||
pbi->dequant_UV_coeffs[i] =
|
||||
pbi->dequant_UV_coeffs[i] << IDCT_SCALE_FACTOR;
|
||||
|
||||
pbi->dequant_Inter_coeffs[i] =
|
||||
(( scale_factor * pbi->dequant_Inter_coeffs[i] ) / 100);
|
||||
if ( pbi->dequant_Inter_coeffs[i] < (MIN_DEQUANT_VAL * 2) )
|
||||
pbi->dequant_Inter_coeffs[i] = MIN_DEQUANT_VAL * 2;
|
||||
pbi->dequant_Inter_coeffs[i] =
|
||||
pbi->dequant_Inter_coeffs[i] << IDCT_SCALE_FACTOR;
|
||||
|
||||
pbi->dequant_InterUV_coeffs[i] =
|
||||
(( scale_factor * pbi->dequant_InterUV_coeffs[i] ) / 100);
|
||||
if ( pbi->dequant_InterUV_coeffs[i] < (MIN_DEQUANT_VAL * 2) )
|
||||
pbi->dequant_InterUV_coeffs[i] = MIN_DEQUANT_VAL * 2;
|
||||
pbi->dequant_InterUV_coeffs[i] =
|
||||
pbi->dequant_InterUV_coeffs[i] << IDCT_SCALE_FACTOR;
|
||||
}
|
||||
|
||||
pbi->dequant_coeffs = pbi->dequant_Y_coeffs;
|
||||
}
|
||||
|
||||
void UpdateQ( PB_INSTANCE *pbi, ogg_uint32_t NewQ ){
|
||||
ogg_uint32_t qscale;
|
||||
|
||||
/* Do bounds checking and convert to a float. */
|
||||
qscale = NewQ;
|
||||
if ( qscale < pbi->QThreshTable[Q_TABLE_SIZE-1] )
|
||||
qscale = pbi->QThreshTable[Q_TABLE_SIZE-1];
|
||||
else if ( qscale > pbi->QThreshTable[0] )
|
||||
qscale = pbi->QThreshTable[0];
|
||||
|
||||
/* Set the inter/intra descision control variables. */
|
||||
pbi->FrameQIndex = Q_TABLE_SIZE - 1;
|
||||
while ( (ogg_int32_t) pbi->FrameQIndex >= 0 ) {
|
||||
if ( (pbi->FrameQIndex == 0) ||
|
||||
( pbi->QThreshTable[pbi->FrameQIndex] >= NewQ) )
|
||||
break;
|
||||
pbi->FrameQIndex --;
|
||||
}
|
||||
|
||||
/* Re-initialise the q tables for forward and reverse transforms. */
|
||||
init_dequantizer ( pbi, qscale, (unsigned char) pbi->FrameQIndex );
|
||||
}
|
||||
|
||||
void UpdateQC( CP_INSTANCE *cpi, ogg_uint32_t NewQ ){
|
||||
ogg_uint32_t qscale;
|
||||
PB_INSTANCE *pbi = &cpi->pb;
|
||||
|
||||
/* Do bounds checking and convert to a float. */
|
||||
qscale = NewQ;
|
||||
if ( qscale < pbi->QThreshTable[Q_TABLE_SIZE-1] )
|
||||
qscale = pbi->QThreshTable[Q_TABLE_SIZE-1];
|
||||
else if ( qscale > pbi->QThreshTable[0] )
|
||||
qscale = pbi->QThreshTable[0];
|
||||
|
||||
/* Set the inter/intra descision control variables. */
|
||||
pbi->FrameQIndex = Q_TABLE_SIZE - 1;
|
||||
while ((ogg_int32_t) pbi->FrameQIndex >= 0 ) {
|
||||
if ( (pbi->FrameQIndex == 0) ||
|
||||
( pbi->QThreshTable[pbi->FrameQIndex] >= NewQ) )
|
||||
break;
|
||||
pbi->FrameQIndex --;
|
||||
}
|
||||
|
||||
/* Re-initialise the q tables for forward and reverse transforms. */
|
||||
init_quantizer ( cpi, qscale, (unsigned char) pbi->FrameQIndex );
|
||||
init_dequantizer ( pbi, qscale, (unsigned char) pbi->FrameQIndex );
|
||||
}
|
37
src/add-ons/media/plugins/theora/libtheora/quant_lookup.h
Normal file
37
src/add-ons/media/plugins/theora/libtheora/quant_lookup.h
Normal file
@ -0,0 +1,37 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2003 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function:
|
||||
last mod: $Id: quant_lookup.h,v 1.1 2004/02/24 13:50:13 shatty Exp $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#include "encoder_internal.h"
|
||||
|
||||
#define MIN16 ((1<<16)-1)
|
||||
#define SHIFT16 (1<<16)
|
||||
|
||||
#define MIN_LEGAL_QUANT_ENTRY 8
|
||||
#define MIN_DEQUANT_VAL 2
|
||||
#define IDCT_SCALE_FACTOR 2 /* Shift left bits to improve IDCT precision */
|
||||
#define OLD_SCHEME 1
|
||||
|
||||
static ogg_uint32_t dequant_index[64] = {
|
||||
0, 1, 8, 16, 9, 2, 3, 10,
|
||||
17, 24, 32, 25, 18, 11, 4, 5,
|
||||
12, 19, 26, 33, 40, 48, 41, 34,
|
||||
27, 20, 13, 6, 7, 14, 21, 28,
|
||||
35, 42, 49, 56, 57, 50, 43, 36,
|
||||
29, 22, 15, 23, 30, 37, 44, 51,
|
||||
58, 59, 52, 45, 38, 31, 39, 46,
|
||||
53, 60, 61, 54, 47, 55, 62, 63
|
||||
};
|
85
src/add-ons/media/plugins/theora/libtheora/reconstruct.c
Normal file
85
src/add-ons/media/plugins/theora/libtheora/reconstruct.c
Normal file
@ -0,0 +1,85 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2003 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function:
|
||||
last mod: $Id: reconstruct.c,v 1.1 2004/02/24 13:50:13 shatty Exp $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#include "encoder_internal.h"
|
||||
|
||||
void ReconIntra( PB_INSTANCE *pbi, unsigned char * ReconPtr,
|
||||
ogg_int16_t * ChangePtr, ogg_uint32_t LineStep ) {
|
||||
ogg_uint32_t i;
|
||||
|
||||
for ( i = 0; i < BLOCK_HEIGHT_WIDTH; i++ ){
|
||||
/* Convert the data back to 8 bit unsigned */
|
||||
/* Saturate the output to unsigend 8 bit values */
|
||||
ReconPtr[0] = clamp255( ChangePtr[0] + 128 );
|
||||
ReconPtr[1] = clamp255( ChangePtr[1] + 128 );
|
||||
ReconPtr[2] = clamp255( ChangePtr[2] + 128 );
|
||||
ReconPtr[3] = clamp255( ChangePtr[3] + 128 );
|
||||
ReconPtr[4] = clamp255( ChangePtr[4] + 128 );
|
||||
ReconPtr[5] = clamp255( ChangePtr[5] + 128 );
|
||||
ReconPtr[6] = clamp255( ChangePtr[6] + 128 );
|
||||
ReconPtr[7] = clamp255( ChangePtr[7] + 128 );
|
||||
|
||||
ReconPtr += LineStep;
|
||||
ChangePtr += BLOCK_HEIGHT_WIDTH;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ReconInter( PB_INSTANCE *pbi, unsigned char * ReconPtr,
|
||||
unsigned char * RefPtr, ogg_int16_t * ChangePtr,
|
||||
ogg_uint32_t LineStep ) {
|
||||
ogg_uint32_t i;
|
||||
|
||||
for ( i = 0; i < BLOCK_HEIGHT_WIDTH; i++) {
|
||||
ReconPtr[0] = clamp255(RefPtr[0] + ChangePtr[0]);
|
||||
ReconPtr[1] = clamp255(RefPtr[1] + ChangePtr[1]);
|
||||
ReconPtr[2] = clamp255(RefPtr[2] + ChangePtr[2]);
|
||||
ReconPtr[3] = clamp255(RefPtr[3] + ChangePtr[3]);
|
||||
ReconPtr[4] = clamp255(RefPtr[4] + ChangePtr[4]);
|
||||
ReconPtr[5] = clamp255(RefPtr[5] + ChangePtr[5]);
|
||||
ReconPtr[6] = clamp255(RefPtr[6] + ChangePtr[6]);
|
||||
ReconPtr[7] = clamp255(RefPtr[7] + ChangePtr[7]);
|
||||
|
||||
ChangePtr += BLOCK_HEIGHT_WIDTH;
|
||||
ReconPtr += LineStep;
|
||||
RefPtr += LineStep;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ReconInterHalfPixel2( PB_INSTANCE *pbi, unsigned char * ReconPtr,
|
||||
unsigned char * RefPtr1, unsigned char * RefPtr2,
|
||||
ogg_int16_t * ChangePtr, ogg_uint32_t LineStep ) {
|
||||
ogg_uint32_t i;
|
||||
|
||||
for ( i = 0; i < BLOCK_HEIGHT_WIDTH; i++ ){
|
||||
ReconPtr[0] = clamp255((((int)RefPtr1[0] + (int)RefPtr2[0]) >> 1) + ChangePtr[0] );
|
||||
ReconPtr[1] = clamp255((((int)RefPtr1[1] + (int)RefPtr2[1]) >> 1) + ChangePtr[1] );
|
||||
ReconPtr[2] = clamp255((((int)RefPtr1[2] + (int)RefPtr2[2]) >> 1) + ChangePtr[2] );
|
||||
ReconPtr[3] = clamp255((((int)RefPtr1[3] + (int)RefPtr2[3]) >> 1) + ChangePtr[3] );
|
||||
ReconPtr[4] = clamp255((((int)RefPtr1[4] + (int)RefPtr2[4]) >> 1) + ChangePtr[4] );
|
||||
ReconPtr[5] = clamp255((((int)RefPtr1[5] + (int)RefPtr2[5]) >> 1) + ChangePtr[5] );
|
||||
ReconPtr[6] = clamp255((((int)RefPtr1[6] + (int)RefPtr2[6]) >> 1) + ChangePtr[6] );
|
||||
ReconPtr[7] = clamp255((((int)RefPtr1[7] + (int)RefPtr2[7]) >> 1) + ChangePtr[7] );
|
||||
|
||||
ChangePtr += BLOCK_HEIGHT_WIDTH;
|
||||
ReconPtr += LineStep;
|
||||
RefPtr1 += LineStep;
|
||||
RefPtr2 += LineStep;
|
||||
}
|
||||
|
||||
}
|
2351
src/add-ons/media/plugins/theora/libtheora/scan.c
Normal file
2351
src/add-ons/media/plugins/theora/libtheora/scan.c
Normal file
File diff suppressed because it is too large
Load Diff
148
src/add-ons/media/plugins/theora/libtheora/theora/theora.h
Normal file
148
src/add-ons/media/plugins/theora/libtheora/theora/theora.h
Normal file
@ -0,0 +1,148 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2003 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function:
|
||||
last mod: $Id: theora.h,v 1.1 2004/02/24 13:50:14 shatty Exp $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#ifndef _O_THEORA_H_
|
||||
#define _O_THEORA_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef LIBOGG2
|
||||
#include <ogg/ogg.h>
|
||||
#else
|
||||
#include <ogg2/ogg.h>
|
||||
/* This is temporary until libogg2 is more complete */
|
||||
ogg_buffer_state *ogg_buffer_create(void);
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
int y_width;
|
||||
int y_height;
|
||||
int y_stride;
|
||||
|
||||
int uv_width;
|
||||
int uv_height;
|
||||
int uv_stride;
|
||||
char *y;
|
||||
char *u;
|
||||
char *v;
|
||||
|
||||
} yuv_buffer;
|
||||
|
||||
typedef enum {
|
||||
OC_CS_UNSPECIFIED,
|
||||
OC_CS_ITU_REC_470M,
|
||||
OC_CS_ITU_REC_470BG,
|
||||
} theora_colorspace;
|
||||
|
||||
typedef struct {
|
||||
ogg_uint32_t width;
|
||||
ogg_uint32_t height;
|
||||
ogg_uint32_t frame_width;
|
||||
ogg_uint32_t frame_height;
|
||||
ogg_uint32_t offset_x;
|
||||
ogg_uint32_t offset_y;
|
||||
ogg_uint32_t fps_numerator;
|
||||
ogg_uint32_t fps_denominator;
|
||||
ogg_uint32_t aspect_numerator;
|
||||
ogg_uint32_t aspect_denominator;
|
||||
theora_colorspace colorspace;
|
||||
int target_bitrate;
|
||||
int quality;
|
||||
int quick_p; /* quick encode/decode */
|
||||
|
||||
/* decode only */
|
||||
unsigned char version_major;
|
||||
unsigned char version_minor;
|
||||
unsigned char version_subminor;
|
||||
|
||||
void *codec_setup;
|
||||
|
||||
/* encode only */
|
||||
int dropframes_p;
|
||||
int keyframe_auto_p;
|
||||
ogg_uint32_t keyframe_frequency;
|
||||
ogg_uint32_t keyframe_frequency_force; /* also used for decode init to
|
||||
get granpos shift correct */
|
||||
ogg_uint32_t keyframe_data_target_bitrate;
|
||||
ogg_int32_t keyframe_auto_threshold;
|
||||
ogg_uint32_t keyframe_mindistance;
|
||||
ogg_int32_t noise_sensitivity;
|
||||
ogg_int32_t sharpness;
|
||||
|
||||
} theora_info;
|
||||
|
||||
typedef struct{
|
||||
theora_info *i;
|
||||
ogg_int64_t granulepos;
|
||||
|
||||
void *internal_encode;
|
||||
void *internal_decode;
|
||||
|
||||
} theora_state;
|
||||
|
||||
typedef struct theora_comment{
|
||||
char **user_comments;
|
||||
int *comment_lengths;
|
||||
int comments;
|
||||
char *vendor;
|
||||
|
||||
} theora_comment;
|
||||
|
||||
#define OC_FAULT -1
|
||||
#define OC_EINVAL -10
|
||||
#define OC_BADHEADER -20
|
||||
#define OC_NOTFORMAT -21
|
||||
#define OC_VERSION -22
|
||||
#define OC_IMPL -23
|
||||
#define OC_BADPACKET -24
|
||||
#define OC_NEWPACKET -25
|
||||
|
||||
extern const char *theora_version_string(void);
|
||||
extern ogg_uint32_t theora_version_number(void);
|
||||
extern int theora_encode_init(theora_state *th, theora_info *c);
|
||||
extern int theora_encode_YUVin(theora_state *t, yuv_buffer *yuv);
|
||||
extern int theora_encode_packetout( theora_state *t, int last_p,
|
||||
ogg_packet *op);
|
||||
extern int theora_encode_header(theora_state *t, ogg_packet *op);
|
||||
extern int theora_encode_comment(theora_comment *tc, ogg_packet *op);
|
||||
extern int theora_encode_tables(theora_state *t, ogg_packet *op);
|
||||
extern int theora_decode_header(theora_info *ci, theora_comment *cc,
|
||||
ogg_packet *op);
|
||||
extern int theora_decode_init(theora_state *th, theora_info *c);
|
||||
extern int theora_decode_packetin(theora_state *th,ogg_packet *op);
|
||||
extern int theora_decode_YUVout(theora_state *th,yuv_buffer *yuv);
|
||||
extern double theora_granule_time(theora_state *th,ogg_int64_t granulepos);
|
||||
extern void theora_info_init(theora_info *c);
|
||||
extern void theora_info_clear(theora_info *c);
|
||||
extern void theora_clear(theora_state *t);
|
||||
|
||||
extern void theora_comment_init(theora_comment *tc);
|
||||
extern void theora_comment_add(theora_comment *tc, char *comment);
|
||||
extern void theora_comment_add_tag(theora_comment *tc,
|
||||
char *tag, char *value);
|
||||
extern char *theora_comment_query(theora_comment *tc, char *tag, int count);
|
||||
extern int theora_comment_query_count(theora_comment *tc, char *tag);
|
||||
extern void theora_comment_clear(theora_comment *tc);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _O_THEORA_H_ */
|
1565
src/add-ons/media/plugins/theora/libtheora/toplevel.c
Normal file
1565
src/add-ons/media/plugins/theora/libtheora/toplevel.c
Normal file
File diff suppressed because it is too large
Load Diff
40
src/add-ons/media/plugins/theora/libtheora/toplevel_lookup.h
Normal file
40
src/add-ons/media/plugins/theora/libtheora/toplevel_lookup.h
Normal file
@ -0,0 +1,40 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2003 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function:
|
||||
last mod: $Id: toplevel_lookup.h,v 1.1 2004/02/24 13:50:13 shatty Exp $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#include "encoder_internal.h"
|
||||
|
||||
ogg_uint32_t PriorKeyFrameWeight[KEY_FRAME_CONTEXT] = { 1,2,3,4,5 };
|
||||
|
||||
/* Data structures controlling addition of residue blocks */
|
||||
ogg_uint32_t ResidueErrorThresh[Q_TABLE_SIZE] = {
|
||||
750, 700, 650, 600, 590, 580, 570, 560,
|
||||
550, 540, 530, 520, 510, 500, 490, 480,
|
||||
470, 460, 450, 440, 430, 420, 410, 400,
|
||||
390, 380, 370, 360, 350, 340, 330, 320,
|
||||
310, 300, 290, 280, 270, 260, 250, 245,
|
||||
240, 235, 230, 225, 220, 215, 210, 205,
|
||||
200, 195, 190, 185, 180, 175, 170, 165,
|
||||
160, 155, 150, 145, 140, 135, 130, 130 };
|
||||
ogg_uint32_t ResidueBlockFactor[Q_TABLE_SIZE] = {
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2 };
|
284
src/add-ons/media/plugins/theora/theoraCodecPlugin.cpp
Normal file
284
src/add-ons/media/plugins/theora/theoraCodecPlugin.cpp
Normal file
@ -0,0 +1,284 @@
|
||||
#include <stdio.h>
|
||||
#include <Autolock.h>
|
||||
#include <DataIO.h>
|
||||
#include <Locker.h>
|
||||
#include <MediaFormats.h>
|
||||
#include <MediaRoster.h>
|
||||
#include <vector>
|
||||
#include "theoraCodecPlugin.h"
|
||||
#include "OggTheoraFormats.h"
|
||||
|
||||
#define TRACE_THIS 1
|
||||
#if TRACE_THIS
|
||||
#define TRACE printf
|
||||
#else
|
||||
#define TRACE(a...)
|
||||
#endif
|
||||
|
||||
#define DECODE_BUFFER_SIZE (32 * 1024)
|
||||
|
||||
|
||||
static media_format
|
||||
theora_decoded_media_format()
|
||||
{
|
||||
media_format format;
|
||||
format.type = B_MEDIA_RAW_VIDEO;
|
||||
init_theora_media_raw_video_format(&format.u.raw_video);
|
||||
return format;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* TheoraDecoder
|
||||
*/
|
||||
|
||||
|
||||
TheoraDecoder::TheoraDecoder()
|
||||
{
|
||||
TRACE("TheoraDecoder::TheoraDecoder\n");
|
||||
theora_info_init(&fInfo);
|
||||
theora_comment_init(&fComment);
|
||||
fStartTime = 0;
|
||||
memset(&fOutput, sizeof(fOutput), 0);
|
||||
}
|
||||
|
||||
|
||||
TheoraDecoder::~TheoraDecoder()
|
||||
{
|
||||
TRACE("TheoraDecoder::~TheoraDecoder\n");
|
||||
theora_info_clear(&fInfo);
|
||||
theora_comment_clear(&fComment);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TheoraDecoder::GetCodecInfo(media_codec_info *info)
|
||||
{
|
||||
strncpy(info->short_name, "theora-libtheora", sizeof(info->short_name));
|
||||
strncpy(info->pretty_name, "theora decoder[libtheora], by Andrew Bachmann", sizeof(info->pretty_name));
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
TheoraDecoder::Setup(media_format *inputFormat,
|
||||
const void *infoBuffer, int32 infoSize)
|
||||
{
|
||||
TRACE("TheoraDecoder::Setup\n");
|
||||
if (!format_is_compatible(theora_encoded_media_format(),*inputFormat)) {
|
||||
return B_MEDIA_BAD_FORMAT;
|
||||
}
|
||||
// grab header packets from meta data
|
||||
if (inputFormat->MetaDataSize() != sizeof(std::vector<ogg_packet>)) {
|
||||
TRACE("TheoraDecoder::Setup not called with ogg_packet<vector> meta data: not theora\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
std::vector<ogg_packet> * packets = (std::vector<ogg_packet> *)inputFormat->MetaData();
|
||||
if (packets->size() != 3) {
|
||||
TRACE("TheoraDecoder::Setup not called with three ogg_packets: not theora\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
// parse header packet
|
||||
if (theora_decode_header(&fInfo,&fComment,&(*packets)[0]) != 0) {
|
||||
TRACE("TheoraDecoder::Setup: theora_synthesis_headerin failed: not theora header\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
// parse comment packet
|
||||
if (theora_decode_header(&fInfo,&fComment,&(*packets)[1]) != 0) {
|
||||
TRACE("theoraDecoder::Setup: theora_synthesis_headerin failed: not theora comment\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
// parse codec setup packet
|
||||
if (theora_decode_header(&fInfo,&fComment,&(*packets)[2]) != 0) {
|
||||
TRACE("theoraDecoder::Setup: theora_synthesis_headerin failed: not theora codec setup\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
// initialize decoder
|
||||
theora_decode_init(&fState,&fInfo);
|
||||
// setup default output
|
||||
media_format requested_format = theora_decoded_media_format();
|
||||
((media_raw_video_format)requested_format.u.raw_video) = inputFormat->u.encoded_video.output;
|
||||
return NegotiateOutputFormat(&requested_format);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
TheoraDecoder::NegotiateOutputFormat(media_format *ioDecodedFormat)
|
||||
{
|
||||
TRACE("TheoraDecoder::NegotiateOutputFormat\n");
|
||||
// BMediaTrack::DecodedFormat
|
||||
// Pass in ioFormat the format that you want (with wildcards
|
||||
// as applicable). The codec will find and return in ioFormat
|
||||
// its best matching format.
|
||||
//
|
||||
// BMediaDecoder::SetOutputFormat
|
||||
// sets the format the decoder should output. On return,
|
||||
// the outputFormat is changed to match the actual format
|
||||
// that will be output; this can be different if you
|
||||
// specified any wildcards.
|
||||
//
|
||||
// Be R5 behavior seems to be that we can never fail. If we
|
||||
// don't support the requested format, just return one we do.
|
||||
media_format format = theora_decoded_media_format();
|
||||
if (fInfo.fps_denominator != 0) {
|
||||
format.u.raw_video.field_rate =
|
||||
(double)fInfo.fps_numerator / (double)fInfo.fps_denominator;
|
||||
}
|
||||
format.u.raw_video.first_active = fInfo.offset_y;
|
||||
format.u.raw_video.last_active = fInfo.offset_y + fInfo.frame_height;
|
||||
format.u.raw_video.pixel_width_aspect = fInfo.aspect_numerator;
|
||||
format.u.raw_video.pixel_height_aspect = fInfo.aspect_denominator;
|
||||
format.u.raw_video.display.line_width = fInfo.frame_width;
|
||||
format.u.raw_video.display.line_count = fInfo.frame_height;
|
||||
if (!format_is_compatible(format,*ioDecodedFormat)) {
|
||||
*ioDecodedFormat = format;
|
||||
}
|
||||
ioDecodedFormat->SpecializeTo(&format);
|
||||
// setup output variables
|
||||
fOutput = ioDecodedFormat->u.raw_video;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
TheoraDecoder::Seek(uint32 seekTo,
|
||||
int64 seekFrame, int64 *frame,
|
||||
bigtime_t seekTime, bigtime_t *time)
|
||||
{
|
||||
TRACE("TheoraDecoder::Seek\n");
|
||||
// throw the old samples away!
|
||||
/* int samples = theora_synthesis_pcmout(&fDspState,&pcm);
|
||||
theora_synthesis_read(&fDspState,samples);
|
||||
*/
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
TheoraDecoder::Decode(void *buffer, int64 *frameCount,
|
||||
media_header *mediaHeader, media_decode_info *info /* = 0 */)
|
||||
{
|
||||
TRACE("TheoraDecoder::Decode\n");
|
||||
debugger("in");
|
||||
status_t status = B_OK;
|
||||
|
||||
bool synced = false;
|
||||
|
||||
// get a new packet
|
||||
void *chunkBuffer;
|
||||
int32 chunkSize;
|
||||
media_header mh;
|
||||
status = GetNextChunk(&chunkBuffer, &chunkSize, &mh);
|
||||
if (status == B_LAST_BUFFER_ERROR) {
|
||||
goto done;
|
||||
}
|
||||
if (status != B_OK) {
|
||||
TRACE("TheoraDecoder::Decode: GetNextChunk failed\n");
|
||||
return status;
|
||||
}
|
||||
if (chunkSize != sizeof(ogg_packet)) {
|
||||
TRACE("TheoraDecoder::Decode: chunk not ogg_packet-sized\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
// decode the packet
|
||||
{
|
||||
ogg_packet * packet = static_cast<ogg_packet*>(chunkBuffer);
|
||||
// push the packet in and get the decoded yuv output
|
||||
theora_decode_packetin(&fState, packet);
|
||||
yuv_buffer yuv;
|
||||
theora_decode_YUVout(&fState, &yuv);
|
||||
// now copy the decoded yuv output to the buffer
|
||||
uint8 * out = static_cast<uint8 *>(buffer);
|
||||
// the following represents a simple YV12 [YUV12?] -> YUY2 [YCbCr422] transform
|
||||
// it possibly (probably) doesn't work when bytes_per_line != line_width
|
||||
uint draw_bytes_per_line = yuv.y_width + yuv.uv_width*2;
|
||||
uint bytes_per_line = draw_bytes_per_line;
|
||||
for (uint line = 0 ; line < fOutput.display.line_count ; line++) {
|
||||
char * y = yuv.y;
|
||||
char * u = yuv.u;
|
||||
char * v = yuv.v;
|
||||
for (uint pos = 0 ; pos < draw_bytes_per_line ; pos += 4) {
|
||||
out[pos] = *(y++);
|
||||
out[pos+1] = *(u++);
|
||||
out[pos+2] = *(y++);
|
||||
out[pos+3] = *(v++);
|
||||
}
|
||||
out += bytes_per_line;
|
||||
yuv.y += yuv.y_stride;
|
||||
if (line % 2 == 1) {
|
||||
yuv.u += yuv.uv_stride;
|
||||
yuv.v += yuv.uv_stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!synced) {
|
||||
if (mh.start_time > 0) {
|
||||
mediaHeader->start_time = mh.start_time - (bigtime_t) (1000000LL / fOutput.field_rate);
|
||||
synced = true;
|
||||
}
|
||||
}
|
||||
done:
|
||||
if (!synced) {
|
||||
mediaHeader->start_time = fStartTime;
|
||||
}
|
||||
fStartTime = (bigtime_t) mediaHeader->start_time + (bigtime_t) (1000000LL / fOutput.field_rate);
|
||||
|
||||
*frameCount = 1;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* TheoraDecoderPlugin
|
||||
*/
|
||||
|
||||
|
||||
Decoder *
|
||||
TheoraDecoderPlugin::NewDecoder(uint index)
|
||||
{
|
||||
static BLocker locker;
|
||||
static bool initdone = false;
|
||||
BAutolock lock(locker);
|
||||
if (!initdone) {
|
||||
initdone = true;
|
||||
}
|
||||
return new TheoraDecoder;
|
||||
}
|
||||
|
||||
static media_format theora_formats[1];
|
||||
|
||||
status_t
|
||||
TheoraDecoderPlugin::GetSupportedFormats(media_format ** formats, size_t * count)
|
||||
{
|
||||
media_format_description description = theora_description();
|
||||
media_format format = theora_encoded_media_format();
|
||||
|
||||
BMediaFormats mediaFormats;
|
||||
status_t result = mediaFormats.InitCheck();
|
||||
if (result != B_OK) {
|
||||
return result;
|
||||
}
|
||||
result = mediaFormats.MakeFormatFor(&description, 1, &format);
|
||||
if (result != B_OK) {
|
||||
return result;
|
||||
}
|
||||
theora_formats[0] = format;
|
||||
|
||||
*formats = theora_formats;
|
||||
*count = 1;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* instantiate_plugin
|
||||
*/
|
||||
|
||||
|
||||
MediaPlugin *instantiate_plugin()
|
||||
{
|
||||
return new TheoraDecoderPlugin;
|
||||
}
|
45
src/add-ons/media/plugins/theora/theoraCodecPlugin.h
Normal file
45
src/add-ons/media/plugins/theora/theoraCodecPlugin.h
Normal file
@ -0,0 +1,45 @@
|
||||
#ifndef _THEORA_CODEC_PLUGIN_H_
|
||||
#define _THEORA_CODEC_PLUGIN_H_
|
||||
|
||||
#include "DecoderPlugin.h"
|
||||
|
||||
#include "libtheora/theora/theora.h"
|
||||
|
||||
class TheoraDecoder : public Decoder
|
||||
{
|
||||
public:
|
||||
TheoraDecoder();
|
||||
~TheoraDecoder();
|
||||
|
||||
void GetCodecInfo(media_codec_info *info);
|
||||
status_t Setup(media_format *inputFormat,
|
||||
const void *infoBuffer, int32 infoSize);
|
||||
|
||||
status_t NegotiateOutputFormat(media_format *ioDecodedFormat);
|
||||
|
||||
status_t Seek(uint32 seekTo,
|
||||
int64 seekFrame, int64 *frame,
|
||||
bigtime_t seekTime, bigtime_t *time);
|
||||
|
||||
|
||||
status_t Decode(void *buffer, int64 *frameCount,
|
||||
media_header *mediaHeader, media_decode_info *info);
|
||||
|
||||
private:
|
||||
theora_info fInfo;
|
||||
theora_comment fComment;
|
||||
theora_state fState;
|
||||
|
||||
bigtime_t fStartTime;
|
||||
media_raw_video_format fOutput;
|
||||
};
|
||||
|
||||
|
||||
class TheoraDecoderPlugin : public DecoderPlugin
|
||||
{
|
||||
public:
|
||||
Decoder * NewDecoder(uint index);
|
||||
status_t GetSupportedFormats(media_format ** formats, size_t * count);
|
||||
};
|
||||
|
||||
#endif _THEORA_CODEC_PLUGIN_H_
|
Loading…
Reference in New Issue
Block a user