[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