[xiph-cvs] cvs commit: theora/lib block_inline.h decode.c encode.c encoder_internal.h frinit.c huffman.c misc_common.c pb.c pp.c toplevel.c
Monty
xiphmont at xiph.org
Sun Sep 22 19:01:29 PDT 2002
xiphmont 02/09/22 22:01:28
Modified: lib block_inline.h decode.c encode.c encoder_internal.h
frinit.c huffman.c misc_common.c pb.c pp.c
toplevel.c
Log:
First approximation of 'it all works'. Now for build system and apps.
Revision Changes Path
1.3 +4 -3 theora/lib/block_inline.h
Index: block_inline.h
===================================================================
RCS file: /usr/local/cvsroot/theora/lib/block_inline.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- block_inline.h 20 Sep 2002 22:01:43 -0000 1.2
+++ block_inline.h 23 Sep 2002 02:01:28 -0000 1.3
@@ -11,13 +11,13 @@
********************************************************************
function:
- last mod: $Id: block_inline.h,v 1.2 2002/09/20 22:01:43 xiphmont Exp $
+ last mod: $Id: block_inline.h,v 1.3 2002/09/23 02:01:28 xiphmont Exp $
********************************************************************/
static ogg_int32_t MBOrderMap[4] = { 0, 2, 3, 1 };
-static ogg_int32_t BlockOrderMap1[4][4] =
-{ { 0, 1, 3, 2 },
+static ogg_int32_t BlockOrderMap1[4][4] = {
+ { 0, 1, 3, 2 },
{ 0, 2, 3, 1 },
{ 0, 2, 3, 1 },
{ 3, 2, 0, 1 }
@@ -28,6 +28,7 @@
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 ){
<p><p>1.3 +729 -20 theora/lib/decode.c
Index: decode.c
===================================================================
RCS file: /usr/local/cvsroot/theora/lib/decode.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- decode.c 20 Sep 2002 22:01:43 -0000 1.2
+++ decode.c 23 Sep 2002 02:01:28 -0000 1.3
@@ -11,53 +11,78 @@
********************************************************************
function:
- last mod: $Id: decode.c,v 1.2 2002/09/20 22:01:43 xiphmont Exp $
+ last mod: $Id: decode.c,v 1.3 2002/09/23 02:01:28 xiphmont Exp $
********************************************************************/
#include <ogg/ogg.h>
#include "encoder_internal.h"
+#include "block_inline.h"
+
+CODING_MODE ModeAlphabet[MODE_METHODS-1][MAX_MODES] = {
+
+ /* Reserved for custom alphabet. */
+ { (CODING_MODE)0, (CODING_MODE)0,
+ (CODING_MODE)0, (CODING_MODE)0,
+ (CODING_MODE)0, (CODING_MODE)0,
+ (CODING_MODE)0, (CODING_MODE)0 },
+
+ /* 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){
- unsigned char VersionByte0; /* Must be 0 for VP30b and later */
unsigned char DctQMask;
unsigned char SpareBits; /* Spare cfg bits */
- unsigned char Unused;
/* Is the frame and inter frame or a key frame */
pbi->FrameType = oggpackB_read(&pbi->opb,1);
- /* unused bit */
- Unused = oggpackB_read(&pbi->opb,1);
-
/* Quality (Q) index */
DctQMask = oggpackB_read( &pbi->opb, 6 );
/* If the frame was a base frame then read the frame dimensions and
build a bitmap structure. */
if ( (pbi->FrameType == BASE_FRAME) ){
- /* Read the frame dimensions bytes (0,0 indicates vp31 or later) */
- VersionByte0 = oggpackB_read( &pbi->opb, 8 );
- pbi->Vp3VersionNo = oggpackB_read( &pbi->opb, 5 );
-
- /* we don't decode version 0 either */
- if(pbi->Vp3VersionNo > CURRENT_ENCODE_VERSION) return 0;
- if(pbi->Vp3VersionNo == 0) return 0;
-
- /* Initialise version specific quantiser values */
- InitQTables( pbi );
-
/* Read the type / coding method for the key frame. */
pbi->KeyFrameType = oggpackB_read( &pbi->opb, 1 );
SpareBits = oggpackB_read( &pbi->opb, 2 );
- InitHuffmanSet( pbi );
-
}
/* Set this frame quality value from Q Index */
@@ -80,7 +105,7 @@
}
}
-int LoadFrame(PB_INSTANCE *pbi){
+static int LoadFrame(PB_INSTANCE *pbi){
/* Load the frame header (including the frame size). */
if ( LoadFrameHeader(pbi) ){
@@ -91,4 +116,688 @@
return 0;
}
+
+static void DecodeModes (PB_INSTANCE *pbi,
+ ogg_uint32_t SBRows,
+ ogg_uint32_t SBCols){
+ 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 */
+
+ /* Read the coding method */
+ CodingScheme = oggpackB_read( &pbi->opb, MODE_METHOD_BITS );
+
+ /* 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++ ){
+ ModeAlphabet[0][ oggpackB_read( &pbi->opb, MODE_BITS) ] = i;
+ }
+ }
+
+ /* 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. */
+ CodingMethod = (CODING_MODE)oggpackB_read( &pbi->opb,
+ MODE_BITS );
+ }else{
+ ModeEntry = FrArrayUnpackMode(pbi);
+ CodingMethod = ModeAlphabet[CodingScheme][ 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){
+ ogg_int32_t MVectComponent;
+ ogg_uint32_t MVCode = 0;
+ ogg_uint32_t ExtraBits = 0;
+
+ /* Get group to which coded component belongs */
+ MVCode = oggpackB_read( &pbi->opb, 3 );
+
+ /* 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:
+ if ( oggpackB_read( &pbi->opb, 1 ))
+ MVectComponent = -2;
+ else
+ MVectComponent = 2;
+ break;
+ case 4:
+ if ( oggpackB_read( &pbi->opb, 1 ) )
+ MVectComponent = -3;
+ else
+ MVectComponent = 3;
+ break;
+ case 5:
+ ExtraBits = oggpackB_read( &pbi->opb, 2 );
+ MVectComponent = 4 + ExtraBits;
+ if ( oggpackB_read( &pbi->opb, 1 ) )
+ MVectComponent = -MVectComponent;
+ break;
+ case 6:
+ ExtraBits = oggpackB_read( &pbi->opb, 3 );
+ MVectComponent = 8 + ExtraBits;
+ if ( oggpackB_read( &pbi->opb, 1 ))
+ MVectComponent = -MVectComponent;
+ break;
+ case 7:
+ ExtraBits = oggpackB_read( &pbi->opb, 4 );
+ MVectComponent = 16 + ExtraBits;
+ if ( oggpackB_read( &pbi->opb, 1 ) )
+ MVectComponent = -MVectComponent;
+ break;
+ }
+
+ return MVectComponent;
+}
+
+static ogg_int32_t ExtractMVectorComponentB(PB_INSTANCE *pbi){
+ ogg_int32_t MVectComponent;
+
+ /* Get group to which coded component belongs */
+ MVectComponent = oggpackB_read( &pbi->opb, 5 );
+ if ( oggpackB_read( &pbi->opb, 1 ) )
+ MVectComponent = -MVectComponent;
+
+ return MVectComponent;
+}
+
+static void DecodeMVectors ( PB_INSTANCE *pbi,
+ ogg_uint32_t SBRows,
+ ogg_uint32_t SBCols ){
+ 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 */
+ if ( oggpackB_read( &pbi->opb, 1) == 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 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){
+ 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 ){
+
+ if ( oggpackB_read(opb,1) )
+ 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 ){
+ ogg_int32_t ExtraBits;
+ 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. */
+ ExtraBits = oggpackB_read(&pbi->opb, pbi->ExtraBitLengths_VP3x[Token]);
+
+ }
+
+ /* 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 ) {
+ ogg_int32_t ExtraBits;
+ 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. */
+ ExtraBits = oggpackB_read(&pbi->opb,pbi->ExtraBitLengths_VP3x[Token]);
+ }
+
+ /* 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){
+ 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 */
+ DcHuffChoice1 = oggpackB_read( &pbi->opb, DC_HUFF_CHOICE_BITS ) + DC_HUFF_OFFSET;
+ DcHuffChoice2 = oggpackB_read( &pbi->opb, DC_HUFF_CHOICE_BITS ) + 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 fro am 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. */
+ AcHuffIndex1 = oggpackB_read( &pbi->opb, AC_HUFF_CHOICE_BITS ) + AC_HUFF_OFFSET;
+ AcHuffIndex2 = oggpackB_read( &pbi->opb, AC_HUFF_CHOICE_BITS ) + 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);
+}
<p><p>1.6 +1 -7 theora/lib/encode.c
Index: encode.c
===================================================================
RCS file: /usr/local/cvsroot/theora/lib/encode.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- encode.c 20 Sep 2002 22:01:43 -0000 1.5
+++ encode.c 23 Sep 2002 02:01:28 -0000 1.6
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: encode.c,v 1.5 2002/09/20 22:01:43 xiphmont Exp $
+ last mod: $Id: encode.c,v 1.6 2002/09/23 02:01:28 xiphmont Exp $
********************************************************************/
@@ -1536,9 +1536,6 @@
/* Output the frame type (base/key frame or inter frame) */
oggpackB_write( opb, cpi->pb.FrameType, 1 );
- /* usused set to 0 allways */
- oggpackB_write( opb, 0, 1 );
-
/* Write out details of the current value of Q... variable resolution. */
for ( i = 0; i < Q_TABLE_SIZE; i++ ) {
if ( cpi->pb.ThisFrameQualityValue == cpi->pb.QThreshTable[i] ) {
@@ -1555,9 +1552,6 @@
/* If the frame was a base frame then write out the frame dimensions. */
if ( cpi->pb.FrameType == BASE_FRAME ) {
- oggpackB_write( opb, 0, 8 );
- oggpackB_write( opb, cpi->pb.Vp3VersionNo, 5 );
-
/* Key frame type / method */
oggpackB_write( opb, cpi->pb.KeyFrameType, 1 );
<p><p>1.6 +13 -31 theora/lib/encoder_internal.h
Index: encoder_internal.h
===================================================================
RCS file: /usr/local/cvsroot/theora/lib/encoder_internal.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- encoder_internal.h 20 Sep 2002 22:01:43 -0000 1.5
+++ encoder_internal.h 23 Sep 2002 02:01:28 -0000 1.6
@@ -11,12 +11,13 @@
********************************************************************
function:
- last mod: $Id: encoder_internal.h,v 1.5 2002/09/20 22:01:43 xiphmont Exp $
+ last mod: $Id: encoder_internal.h,v 1.6 2002/09/23 02:01:28 xiphmont Exp $
********************************************************************/
#include <ogg/ogg.h>
#include "huffman.h"
+#include "theora/theora.h"
#define CURRENT_ENCODE_VERSION 1
#define HUGE_ERROR (1<<28) /* Out of range test value */
@@ -57,10 +58,6 @@
#define MAX_MV_EXTENT 31 /* Max search distance in half pixel increments */
-typedef enum{
- SCP_CONFIGURE_PP
-} SCP_SETTINGS;
-
typedef struct CONFIG_TYPE{
/* The size of the surface we want to draw to */
ogg_uint32_t VideoFrameWidth;
@@ -261,15 +258,11 @@
/***********************************************************************/
/* Decoder and Frame Type Information */
- unsigned char Vp3VersionNo;
int DecoderErrorCode;
int FramesHaveBeenSkipped;
- int SkipYUVtoRGB; /* Skip conversion */
- int OutputRGB; /* Output To RGB */
-
- int PostProcessEnabled;
+ int PostProcessEnabled;
ogg_uint32_t PostProcessingLevel; /* Perform post processing */
/* Frame Info */
@@ -330,10 +323,6 @@
YUV_BUFFER_ENTRY *GoldenFrame;
YUV_BUFFER_ENTRY *LastFrameRecon;
YUV_BUFFER_ENTRY *PostProcessBuffer;
- YUV_BUFFER_ENTRY *ScaleBuffer; /* new buffer for testing new loop fi
- ltering scheme */
-
- unsigned char *bmp_dptr0;
ogg_int32_t *BoundingValuePtr;
@@ -468,7 +457,13 @@
short *ModifierPointer[4];
unsigned char *DataOutputInPtr;
+
+ /* fields to store some extra header information useful to the
+ application, but not really the codec */
+ int quality;
+ int target_bitrate;
+
} PB_INSTANCE;
typedef struct CP_INSTANCE {
@@ -667,21 +662,6 @@
} CP_INSTANCE;
-typedef struct{
- int YWidth;
- int YHeight;
- int YStride;
-
- int UVWidth;
- int UVHeight;
- int UVStride;
-
- char * YBuffer;
- char * UBuffer;
- char * VBuffer;
-
-} YUV_INPUT_BUFFER_CONFIG;
-
/*#define clamp255(x) (((ogg_int32_t)(x)&~0xff)?((ogg_int32_t)(x))>>31:(x))*/
#define clamp255(val) ( val<0 ? 0: ( val>255 ? 255:val ) )
@@ -692,6 +672,8 @@
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,
@@ -792,7 +774,7 @@
ogg_uint32_t SBCols,
ogg_uint32_t PixelsPerLine,
ogg_uint32_t *InterError,
- ogg_uint32_t *IntraError) ;
+ ogg_uint32_t *IntraError);
extern CODING_MODE FrArrayUnpackMode(PB_INSTANCE *pbi);
extern void CreateBlockMapping ( ogg_int32_t (*BlockMap)[4][4],
@@ -802,18 +784,18 @@
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 ConfigureQuality( CP_INSTANCE *cpi, ogg_uint32_t QualityValue ) ;
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 int LoadFrame(PB_INSTANCE *pbi);
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);
+
<p><p>1.3 +6 -3 theora/lib/frinit.c
Index: frinit.c
===================================================================
RCS file: /usr/local/cvsroot/theora/lib/frinit.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- frinit.c 20 Sep 2002 22:01:43 -0000 1.2
+++ frinit.c 23 Sep 2002 02:01:28 -0000 1.3
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: frinit.c,v 1.2 2002/09/20 22:01:43 xiphmont Exp $
+ last mod: $Id: frinit.c,v 1.3 2002/09/23 02:01:28 xiphmont Exp $
********************************************************************/
@@ -325,8 +325,11 @@
/*pbi->PostProcessingLevel = 0;
pbi->PostProcessingLevel = 4;
- pbi->PostProcessingLevel = 5;*/
- pbi->PostProcessingLevel = 6;
+ pbi->PostProcessingLevel = 5;
+ pbi->PostProcessingLevel = 6;*/
+
+ pbi->PostProcessingLevel = 0;
+
/* Set the frame size etc. */
<p><p>1.4 +16 -10 theora/lib/huffman.c
Index: huffman.c
===================================================================
RCS file: /usr/local/cvsroot/theora/lib/huffman.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- huffman.c 20 Sep 2002 22:01:43 -0000 1.3
+++ huffman.c 23 Sep 2002 02:01:28 -0000 1.4
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: huffman.c,v 1.3 2002/09/20 22:01:43 xiphmont Exp $
+ last mod: $Id: huffman.c,v 1.4 2002/09/23 02:01:28 xiphmont Exp $
********************************************************************/
@@ -189,19 +189,25 @@
void ClearHuffmanSet( PB_INSTANCE *pbi ){
int i;
- for ( i = 0; i < NUM_HUFF_TABLES; i++ ){
- if (pbi->HuffRoot_VP3x[i]) DestroyHuffTree(pbi->HuffRoot_VP3x[i]);
- if (pbi->HuffCodeArray_VP3x[i])
- _ogg_free (pbi->HuffCodeArray_VP3x[i]);
- if (pbi->HuffCodeLengthArray_VP3x[i])
- _ogg_free (pbi->HuffCodeLengthArray_VP3x[i]);
+ if (pbi->HuffRoot_VP3x){
+ for ( i = 0; i < NUM_HUFF_TABLES; i++ )
+ if (pbi->HuffRoot_VP3x[i]) DestroyHuffTree(pbi->HuffRoot_VP3x[i]);
+ _ogg_free(pbi->HuffRoot_VP3x);
}
- if(pbi->HuffRoot_VP3x)_ogg_free(pbi->HuffRoot_VP3x);
- if (pbi->HuffCodeArray_VP3x)
+ if (pbi->HuffCodeArray_VP3x){
+ for ( i = 0; i < NUM_HUFF_TABLES; i++ )
+ if (pbi->HuffCodeArray_VP3x[i])
+ _ogg_free (pbi->HuffCodeArray_VP3x[i]);
_ogg_free (pbi->HuffCodeArray_VP3x);
- if (pbi->HuffCodeLengthArray_VP3x)
+ }
+
+ if (pbi->HuffCodeLengthArray_VP3x) {
+ for ( i = 0; i < NUM_HUFF_TABLES; i++ )
+ if (pbi->HuffCodeLengthArray_VP3x[i])
+ _ogg_free (pbi->HuffCodeLengthArray_VP3x[i]);
_ogg_free (pbi->HuffCodeLengthArray_VP3x);
+ }
pbi->HuffRoot_VP3x=NULL;
pbi->HuffCodeArray_VP3x=NULL;
<p><p>1.6 +1 -13 theora/lib/misc_common.c
Index: misc_common.c
===================================================================
RCS file: /usr/local/cvsroot/theora/lib/misc_common.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- misc_common.c 20 Sep 2002 22:01:43 -0000 1.5
+++ misc_common.c 23 Sep 2002 02:01:28 -0000 1.6
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: misc_common.c,v 1.5 2002/09/20 22:01:43 xiphmont Exp $
+ last mod: $Id: misc_common.c,v 1.6 2002/09/23 02:01:28 xiphmont Exp $
********************************************************************/
@@ -285,18 +285,6 @@
UpdateQC( cpi, cpi->pb.ThisFrameQualityValue );
cpi->pb.LastFrameQualityValue = cpi->pb.ThisFrameQualityValue;
}
-}
-
-void ConfigureQuality( CP_INSTANCE *cpi, ogg_uint32_t QualityValue ) {
- /* Default first frame quality */
-
- /* Set the worst case quality value. */
- /* Note that the actual quality is determined by lookup into the
- quantiser table QThreshTable[] */
- cpi->Configuration.MaxQ = 63 - QualityValue;
-
- /* Set the default Active MaxQ. */
- cpi->Configuration.ActiveMaxQ = cpi->Configuration.MaxQ;
}
void CopyBackExtraFrags(CP_INSTANCE *cpi){
<p><p>1.2 +1 -6 theora/lib/pb.c
Index: pb.c
===================================================================
RCS file: /usr/local/cvsroot/theora/lib/pb.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- pb.c 20 Sep 2002 09:30:32 -0000 1.1
+++ pb.c 23 Sep 2002 02:01:28 -0000 1.2
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: pb.c,v 1.1 2002/09/20 09:30:32 xiphmont Exp $
+ last mod: $Id: pb.c,v 1.2 2002/09/23 02:01:28 xiphmont Exp $
********************************************************************/
@@ -35,8 +35,6 @@
_ogg_free(pbi->dequant_UV_coeffs);
if(pbi->dequant_Inter_coeffs)
_ogg_free(pbi->dequant_Inter_coeffs);
- if(pbi->ScaleBuffer)
- _ogg_free(pbi->ScaleBuffer);
if(pbi->dequant_InterUV_coeffs)
_ogg_free(pbi->dequant_InterUV_coeffs);
@@ -49,7 +47,6 @@
pbi->dequant_UV_coeffs = 0;
pbi->dequant_InterUV_coeffs = 0;
pbi->dequant_Inter_coeffs = 0;
- pbi->ScaleBuffer = 0;
}
@@ -114,6 +111,4 @@
pbi->DecoderErrorCode = 0;
pbi->KeyFrameType = DCT_KEY_FRAME;
pbi->FramesHaveBeenSkipped = 0;
- pbi->SkipYUVtoRGB = 0;
- pbi->OutputRGB = 0;
}
<p><p>1.5 +54 -54 theora/lib/pp.c
Index: pp.c
===================================================================
RCS file: /usr/local/cvsroot/theora/lib/pp.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- pp.c 20 Sep 2002 22:01:43 -0000 1.4
+++ pp.c 23 Sep 2002 02:01:28 -0000 1.5
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: pp.c,v 1.4 2002/09/20 22:01:43 xiphmont Exp $
+ last mod: $Id: pp.c,v 1.5 2002/09/23 02:01:28 xiphmont Exp $
********************************************************************/
@@ -677,63 +677,63 @@
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 ){
+ /* 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];
- /* 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;
+ 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;
}
-
- Src += PlaneLineStep;
- Des += PlaneLineStep;
+ CurrentFrag ++;
}
- CurrentFrag ++;
}
}
<p><p>1.6 +232 -85 theora/lib/toplevel.c
Index: toplevel.c
===================================================================
RCS file: /usr/local/cvsroot/theora/lib/toplevel.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- toplevel.c 20 Sep 2002 22:01:43 -0000 1.5
+++ toplevel.c 23 Sep 2002 02:01:28 -0000 1.6
@@ -11,7 +11,7 @@
********************************************************************
function:
- last mod: $Id: toplevel.c,v 1.5 2002/09/20 22:01:43 xiphmont Exp $
+ last mod: $Id: toplevel.c,v 1.6 2002/09/23 02:01:28 xiphmont Exp $
********************************************************************/
@@ -27,7 +27,7 @@
#define VERSION_MINOR 1
#define VERSION_SUB 0
-#define CommentString "Xiph.Org libTheora I 20020916 0 0 0"
+#define CommentString "Xiph.Org libTheora I 20020916 3 1 0"
static void EClearFragmentInfo(CP_INSTANCE * cpi){
if(cpi->extra_fragments)
@@ -309,6 +309,9 @@
/* Initialise bit packing mechanism. */
oggpackB_reset(&cpi->oggbuffer);
+
+ /* mark as video frame */
+ oggpackB_write(&cpi->oggbuffer,0,1);
/* Write out the frame header information including size. */
WriteFrameHeader(cpi);
@@ -400,10 +403,6 @@
static void CompressFirstFrame(CP_INSTANCE *cpi) {
ogg_uint32_t i;
- /* if not AutoKeyframing cpi->ForceKeyFrameEvery = is frequency */
- if(!cpi->AutoKeyFrameEnabled)
- cpi->ForceKeyFrameEvery = cpi->KeyFrameFrequency;
-
/* set up context of key frame sizes and distances for more local
datarate control */
for( i = 0 ; i < KEY_FRAME_CONTEXT ; i ++ ) {
@@ -496,7 +495,7 @@
cpi->ThisFrameTargetBytes = (ogg_int32_t) cpi->frame_target_rate +
( (cpi->KeyFrameDataTarget - cpi->frame_target_rate) *
cpi->LastKeyFrame / cpi->ForceKeyFrameEvery );
-
+
if ( cpi->ThisFrameTargetBytes > cpi->KeyFrameDataTarget )
cpi->ThisFrameTargetBytes = cpi->KeyFrameDataTarget;
@@ -755,13 +754,7 @@
}
}
}
-
-/********************** The toplevel ***********************/
-
-const char *theora_encode_version(void){
- return CommentString;
-}
-
+
static int _ilog(unsigned int v){
int ret=0;
while(v){
@@ -771,6 +764,17 @@
return(ret);
}
+
+/********************** The toplevel: encode ***********************/
+
+const char *theora_version_string(void){
+ return CommentString;
+}
+
+ogg_uint32_t theora_version_number(void){
+ return (VERSION_MAJOR<<16) + (VERSION_MINOR<<8) + (VERSION_SUB);
+}
+
int theora_encode_init(theora_state *th, theora_info *c){
int i;
@@ -786,11 +790,17 @@
InitTmpBuffers(&cpi->pb);
InitPPInstance(&cpi->pp);
+ /* some extras useful to the API */
+ cpi->pb.target_bitrate=c->target_bitrate;
+ cpi->pb.quality=c->quality;
+
/* Initialise Configuration structure to legal values */
- cpi->Configuration.BaseQ = 32;
- cpi->Configuration.FirstFrameQ = 32;
- cpi->Configuration.MaxQ = 32;
- cpi->Configuration.ActiveMaxQ = 32;
+ if(c->quality>63)c->quality=63;
+ if(c->quality<0)c->quality=32;
+ cpi->Configuration.BaseQ = c->quality;
+ cpi->Configuration.FirstFrameQ = c->quality;
+ cpi->Configuration.MaxQ = c->quality;
+ cpi->Configuration.ActiveMaxQ = c->quality;
cpi->MVChangeFactor = 14;
cpi->FourMvChangeFactor = 8;
@@ -807,15 +817,27 @@
cpi->InterPrediction = 1;
cpi->MotionCompensation = 1;
cpi->ThreshMapThreshold = 5;
- cpi->QuickCompress = 1;
cpi->MaxConsDroppedFrames = 1;
- cpi->Sharpness = 2;
-
- cpi->PreProcFilterLevel = 2;
+ cpi->Sharpness = c->sharpness;
+
+ /* Set encoder flags. */
+ /* if not AutoKeyframing cpi->ForceKeyFrameEvery = is frequency */
+ cpi->AutoKeyFrameEnabled = c->keyframe_auto_p;
+ if(!cpi->AutoKeyFrameEnabled)
+ c->keyframe_frequency_force = c->keyframe_frequency;
+
+ cpi->ForceKeyFrameEvery = c->keyframe_frequency_force;
+ cpi->KeyFrameFrequency = c->keyframe_frequency;
+ cpi->DropFramesAllowed = c->droppedframes_p;
+ cpi->QuickCompress = c->quickcompress_p;
+ cpi->MinimumDistanceToKeyFrame = c->keyframe_mindistance;
+ cpi->PreProcFilterLevel = c->noise_sensitivity;
+ cpi->AutoKeyFrameThreshold = c->keyframe_auto_threshold;
+
/* Set up default values for QTargetModifier[Q_TABLE_SIZE] table */
for ( i = 0; i < Q_TABLE_SIZE; i++ )
- cpi->QTargetModifier[Q_TABLE_SIZE] = 1.0;
+ cpi->QTargetModifier[i] = 1.0;
/* Set up an encode buffer */
oggpackB_writeinit(&cpi->oggbuffer);
@@ -823,9 +845,6 @@
cpi->pb.Configuration.HFragPixels = 8;
cpi->pb.Configuration.VFragPixels = 8;
- /* set the version number */
- cpi->pb.Vp3VersionNo = CURRENT_ENCODE_VERSION;
-
/* Set the video frame size. */
cpi->pb.YPlaneSize = 0xFFF;
cpi->pb.Configuration.VideoFrameHeight = 0xFFF;
@@ -837,17 +856,11 @@
cpi->ScanConfig.VideoFrameWidth = cpi->pb.Configuration.VideoFrameWidth;
/* Set data rate related variables. */
- cpi->Configuration.TargetBandwidth = (c->target_bitrate * 1000) / 8;
-
- /* Set the target minimum key frame frequency */
- cpi->KeyFrameFrequency = c->keyframe_frequency;
+ cpi->Configuration.TargetBandwidth = (c->target_bitrate) / 8;
/* Set key frame data rate target */
- cpi->KeyFrameDataTarget = (c->keyframe_data_target_bitrate * 1000) / 8;
+ cpi->KeyFrameDataTarget = (c->keyframe_data_target_bitrate) / 8;
- /* Set the quality settings. */
- ConfigureQuality( cpi, c->quality );
-
/* Set the frame rate variables. */
cpi->Configuration.OutputFrameRateN = c->fps_numerator;
cpi->Configuration.OutputFrameRateD = c->fps_denominator;
@@ -863,6 +876,12 @@
cpi->frame_target_rate = cpi->Configuration.TargetBandwidth /
cpi->Configuration.OutputFrameRate;
+ /* Set key frame data rate target; this is nominal keyframe size */
+ cpi->KeyFrameDataTarget = (c->keyframe_data_target_bitrate *
+ cpi->Configuration.OutputFrameRateN /
+ cpi->Configuration.OutputFrameRateD ) / 8;
+
+
/* Initialise image format details */
InitFrameDetails(&cpi->pb);
EInitFragmentInfo(cpi);
@@ -882,16 +901,6 @@
/* Initialise the pre-processor module. */
ScanYUVInit(&cpi->pp, &(cpi->ScanConfig));
- /* Set encoder flags. */
- cpi->DropFramesAllowed = c->droppedframes_p;
- cpi->QuickCompress = c->quickcompress_p;
- cpi->AutoKeyFrameEnabled = 1;
- cpi->MinimumDistanceToKeyFrame = c->keyframe_mindistance;
- cpi->ForceKeyFrameEvery = c->keyframe_force_freq;
- cpi->PreProcFilterLevel = c->noise_sensitivity;
- cpi->AutoKeyFrameThreshold = c->keyframe_auto_threshold;
- cpi->Sharpness = c->sharpness;
-
/* don't go too nuts on keyframe spacing; impose a high limit to
make certain the granulepos encoding strategy works */
if(cpi->ForceKeyFrameEvery>32768)cpi->ForceKeyFrameEvery=32768;
@@ -936,53 +945,51 @@
return 0;
}
-int theora_encode_YUVin( CP_INSTANCE *cpi,
- YUV_INPUT_BUFFER_CONFIG *YuvInputData){
+int theora_encode_YUVin(theora_state *t,
+ yuv_buffer *yuv){
ogg_int32_t i;
unsigned char *LocalDataPtr;
unsigned char *InputDataPtr;
+ CP_INSTANCE *cpi=(CP_INSTANCE *)(t->internal);
- if(!cpi->readyflag)return -1;
- if(cpi->doneflag)return -1;
+ if(!cpi->readyflag)return OC_EINVAL;
+ if(cpi->doneflag)return OC_EINVAL;
/* If frame size has changed, abort out for now */
- if (YuvInputData->YHeight != (int)cpi->pb.Configuration.VideoFrameHeight ||
- YuvInputData->YWidth != (int)cpi->pb.Configuration.VideoFrameWidth )
+ if (yuv->y_height != (int)cpi->pb.Configuration.VideoFrameHeight ||
+ yuv->y_width != (int)cpi->pb.Configuration.VideoFrameWidth )
return(-1);
/* Copy over input YUV to internal YUV buffers. */
/* First copy over the Y data */
LocalDataPtr = cpi->yuv1ptr;
- InputDataPtr = (unsigned char *)YuvInputData->YBuffer;
- for ( i = 0; i < YuvInputData->YHeight; i++ ){
- memcpy( LocalDataPtr, InputDataPtr, YuvInputData->YWidth );
- LocalDataPtr += YuvInputData->YWidth;
- InputDataPtr += YuvInputData->YStride;
+ InputDataPtr = yuv->y;
+ for ( i = 0; i < yuv->y_height; i++ ){
+ memcpy( LocalDataPtr, InputDataPtr, yuv->y_width );
+ LocalDataPtr += yuv->y_width;
+ InputDataPtr += yuv->y_stride;
}
/* Now copy over the U data */
- LocalDataPtr = &cpi->yuv1ptr[(YuvInputData->YHeight * YuvInputData->YWidth)];
- InputDataPtr = (unsigned char *)YuvInputData->UBuffer;
- for ( i = 0; i < YuvInputData->UVHeight; i++ ){
- memcpy( LocalDataPtr, InputDataPtr, YuvInputData->UVWidth );
- LocalDataPtr += YuvInputData->UVWidth;
- InputDataPtr += YuvInputData->UVStride;
+ LocalDataPtr = &cpi->yuv1ptr[(yuv->y_height * yuv->y_width)];
+ InputDataPtr = yuv->u;
+ for ( i = 0; i < yuv->uv_height; i++ ){
+ memcpy( LocalDataPtr, InputDataPtr, yuv->uv_width );
+ LocalDataPtr += yuv->uv_width;
+ InputDataPtr += yuv->uv_stride;
}
/* Now copy over the V data */
LocalDataPtr =
- &cpi->yuv1ptr[((YuvInputData->YHeight*YuvInputData->YWidth)*5)/4];
- InputDataPtr = (unsigned char *)YuvInputData->VBuffer;
- for ( i = 0; i < YuvInputData->UVHeight; i++ ){
- memcpy( LocalDataPtr, InputDataPtr, YuvInputData->UVWidth );
- LocalDataPtr += YuvInputData->UVWidth;
- InputDataPtr += YuvInputData->UVStride;
+ &cpi->yuv1ptr[((yuv->y_height*yuv->y_width)*5)/4];
+ InputDataPtr = yuv->v;
+ for ( i = 0; i < yuv->uv_height; i++ ){
+ memcpy( LocalDataPtr, InputDataPtr, yuv->uv_width );
+ LocalDataPtr += yuv->uv_width;
+ InputDataPtr += yuv->uv_stride;
}
- /* Mark this as a video frame */
- oggpackB_write(&cpi->oggbuffer,0,1);
-
/* Special case for first frame */
if ( cpi->ThisIsFirstFrame ){
CompressFirstFrame(cpi);
@@ -1004,7 +1011,8 @@
return 0;
}
-int theora_encode_packetout( CP_INSTANCE *cpi, int last_p, ogg_packet *op){
+int theora_encode_packetout( theora_state *t, int last_p, ogg_packet *op){
+ CP_INSTANCE *cpi=(CP_INSTANCE *)(t->internal);
long bytes=oggpackB_bytes(&cpi->oggbuffer);
if(!bytes)return(0);
@@ -1028,8 +1036,8 @@
return 1;
}
-int theora_encode_header(CP_INSTANCE *cpi, ogg_packet *op){
- /* width, height, fps, granule_shift, version */
+int theora_encode_header(theora_state *t, ogg_packet *op){
+ CP_INSTANCE *cpi=(CP_INSTANCE *)(t->internal);
oggpackB_reset(&cpi->oggbuffer);
oggpackB_write(&cpi->oggbuffer,0x80,8);
@@ -1040,6 +1048,10 @@
oggpackB_write(&cpi->oggbuffer,'r',8);
oggpackB_write(&cpi->oggbuffer,'a',8);
+ oggpackB_write(&cpi->oggbuffer,VERSION_MAJOR,8);
+ oggpackB_write(&cpi->oggbuffer,VERSION_MINOR,8);
+ oggpackB_write(&cpi->oggbuffer,VERSION_SUB,8);
+
oggpackB_write(&cpi->oggbuffer,cpi->ScanConfig.VideoFrameWidth,16);
oggpackB_write(&cpi->oggbuffer,cpi->ScanConfig.VideoFrameHeight,16);
oggpackB_write(&cpi->oggbuffer,cpi->Configuration.OutputFrameRateN,32);
@@ -1047,9 +1059,8 @@
oggpackB_write(&cpi->oggbuffer,cpi->keyframe_granule_shift,5);
- oggpackB_write(&cpi->oggbuffer,VERSION_MAJOR,8);
- oggpackB_write(&cpi->oggbuffer,VERSION_MINOR,8);
- oggpackB_write(&cpi->oggbuffer,VERSION_SUB,8);
+ oggpackB_write(&cpi->oggbuffer,cpi->pb.target_bitrate,24);
+ oggpackB_write(&cpi->oggbuffer,cpi->pb.quality,6);
op->packet=oggpackB_get_buffer(&cpi->oggbuffer);
op->bytes=oggpackB_bytes(&cpi->oggbuffer);
@@ -1065,18 +1076,154 @@
return(0);
}
-void theora_encode_clear(CP_INSTANCE *cpi){
- if(cpi){
+void theora_encode_clear(theora_state *t){
+ if(t){
+ CP_INSTANCE *cpi=(CP_INSTANCE *)(t->internal);
+
+ if(cpi){
+
+ ClearHuffmanSet(&cpi->pb);
+ ClearFragmentInfo(&cpi->pb);
+ ClearFrameInfo(&cpi->pb);
+ EClearFragmentInfo(cpi);
+ EClearFrameInfo(cpi);
+ ClearTmpBuffers(&cpi->pb);
+ ClearPPInstance(&cpi->pp);
+
+ }
+ t->internal=NULL;
+ }
+}
+
+int theora_decode_header(theora_info *c, ogg_packet *op){
+ int ret;
+ oggpack_buffer opb;
+ oggpackB_readinit(&opb,op->packet,op->bytes);
+ memset(c,0,sizeof(*c));
+
+ if(!op->b_o_s)return(OC_BADHEADER);
+ {
+ char id[6];
+ int i;
+ int typeflag=oggpackB_read(&opb,8);
+
+ if(typeflag!=0x80)return(OC_NOTFORMAT);
- ClearHuffmanSet(&cpi->pb);
- ClearFragmentInfo(&cpi->pb);
- ClearFrameInfo(&cpi->pb);
- EClearFragmentInfo(cpi);
- EClearFrameInfo(cpi);
- ClearTmpBuffers(&cpi->pb);
- ClearPPInstance(&cpi->pp);
+ for(i=0;i<6;i++)
+ id[i]=(char)oggpackB_read(&opb,8);
+ if(memcmp(id,"theora",6))return(OC_NOTFORMAT);
+
+ c->version_major=oggpackB_read(&opb,8);
+ c->version_minor=oggpackB_read(&opb,8);
+ c->version_subminor=oggpackB_read(&opb,8);
+
+ if(c->version_major!=VERSION_MAJOR)return(OC_VERSION);
+ if(c->version_minor>VERSION_MINOR)return(OC_VERSION);
}
+
+ c->width=oggpackB_read(&opb,16);
+ c->height=oggpackB_read(&opb,16);
+ c->fps_numerator=oggpackB_read(&opb,32);
+ c->fps_denominator=oggpackB_read(&opb,32);
+
+ c->keyframe_frequency_force=1<<oggpackB_read(&opb,5);
+
+ c->target_bitrate=oggpackB_read(&opb,24);
+ c->quality=ret=oggpackB_read(&opb,6);
+
+ if(ret==-1)return(OC_BADHEADER);
+
+ return(0);
}
+int theora_decode_init(theora_state *th, theora_info *c){
+ PB_INSTANCE *pbi;
+
+ th->internal=pbi=_ogg_calloc(1,sizeof(*pbi));
+
+ InitPBInstance(pbi);
+ pbi->Configuration.VideoFrameWidth = c->width;
+ pbi->Configuration.VideoFrameHeight = c->height;
+
+ InitFrameDetails(pbi);
+
+ pbi->LastFrameQualityValue = 0;
+ pbi->DecoderErrorCode = 0;
+
+ pbi->Configuration.HFragPixels = 8;
+ pbi->Configuration.VFragPixels = 8;
+
+ /* Clear down the YUVtoRGB conversion skipped list. */
+ memset(pbi->skipped_display_fragments, 0, pbi->UnitFragments );
+
+ /* Initialise version specific quantiser values */
+ InitQTables( pbi );
+
+ /* Huffman setup */
+ InitHuffmanSet( pbi );
+
+
+ return(0);
+
+}
+
+void theora_decode_clear(theora_state *th){
+
+ if(th){
+ if(th->internal){
+ PB_INSTANCE *pbi=(PB_INSTANCE *)(th->internal);
+
+ ClearFragmentInfo(pbi);
+ ClearFrameInfo(pbi);
+ ClearPBInstance(pbi);
+
+ }
+ }
+}
+
+int theora_decode_packetin(theora_state *th,ogg_packet *op){
+ int ret;
+ PB_INSTANCE *pbi=(PB_INSTANCE *)(th->internal);
+
+ pbi->DecoderErrorCode = 0;
+ oggpackB_readinit(&pbi->opb,op->packet,op->bytes);
+
+ /* verify that this is a video frame */
+ if(oggpackB_read(&pbi->opb,1)==0){
+ ret=LoadAndDecode(pbi);
+ if(ret)return ret;
+
+ if(pbi->PostProcessingLevel)
+ PostProcess(pbi);
+
+ return(0);
+ }
+
+ return OC_BADPACKET;
+}
+
+int theora_decode_YUVout(theora_state *th,yuv_buffer *yuv){
+ PB_INSTANCE *pbi=(PB_INSTANCE *)(th->internal);
+
+ yuv->y_width = pbi->Configuration.VideoFrameWidth;
+ yuv->y_height = pbi->Configuration.VideoFrameHeight;
+ yuv->y_stride = pbi->Configuration.YStride;
+
+ yuv->uv_width = pbi->Configuration.VideoFrameWidth / 2;
+ yuv->uv_height = pbi->Configuration.VideoFrameHeight / 2;
+ yuv->uv_stride = pbi->Configuration.UVStride;
+
+ if(pbi->PostProcessingLevel){
+ yuv->y = &pbi->PostProcessBuffer[pbi->ReconYDataOffset];
+ yuv->u = &pbi->PostProcessBuffer[pbi->ReconUDataOffset];
+ yuv->v = &pbi->PostProcessBuffer[pbi->ReconVDataOffset];
+ }else{
+ yuv->y = &pbi->LastFrameRecon[pbi->ReconYDataOffset];
+ yuv->u = &pbi->LastFrameRecon[pbi->ReconUDataOffset];
+ yuv->v = &pbi->LastFrameRecon[pbi->ReconVDataOffset];
+ }
+
+ return 0;
+}
<p><p>--- >8 ----
List archives: http://www.xiph.org/archives/
Ogg project homepage: http://www.xiph.org/ogg/
To unsubscribe from this list, send a message to 'cvs-request at xiph.org'
containing only the word 'unsubscribe' in the body. No subject is needed.
Unsubscribe messages sent to the list will be ignored/filtered.
More information about the commits
mailing list