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:
shatty 2004-02-24 13:50:14 +00:00
parent 6cb226fd44
commit dd05a93c1b
31 changed files with 16078 additions and 0 deletions

View 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
;

View 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];
}

View 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 );
}

View 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));
}

View 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 ++;
}
}

File diff suppressed because it is too large Load Diff

View 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;
}
}

View 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);
}

File diff suppressed because it is too large Load Diff

View 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

View 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
};

View 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;
}

View 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 );
}

View 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;
}
}

View 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)

File diff suppressed because it is too large Load Diff

View 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;
}

View 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;
}

View 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;
}
}
}
}

View 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;
}

View 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;
}
}

View 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

View 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 );
}

View 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
};

View 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;
}
}

File diff suppressed because it is too large Load Diff

View 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_ */

File diff suppressed because it is too large Load Diff

View 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 };

View 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;
}

View 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_