⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 encode.c

📁 从FFMPEG转换而来的H264解码程序,VC下编译..
💻 C
📖 第 1 页 / 共 4 页
字号:
/********************************************************************
 *                                                                  *
 * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE.   *
 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
 *                                                                  *
 * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2003                *
 * by the Xiph.Org Foundation http://www.xiph.org/                  *
 *                                                                  *
 ********************************************************************

  function:

 ********************************************************************/

#include <stdlib.h>
#include <string.h>
#include "codec_internal.h"
#include "encoder_lookup.h"
#include "block_inline.h"

#define PUR 8
#define PU 4
#define PUL 2
#define PL 1
#define HIGHBITDUPPED(X) (((ogg_int16_t) X)  >> 15)

static ogg_uint32_t QuadCodeComponent ( CP_INSTANCE *cpi,
				 ogg_uint32_t FirstSB,
				 ogg_uint32_t SBRows,
				 ogg_uint32_t SBCols,
				 ogg_uint32_t PixelsPerLine ){

  ogg_int32_t	FragIndex;      /* Fragment number */
  ogg_uint32_t	MB, B;	        /* Macro-Block, Block indices */
  ogg_uint32_t	SBrow;          /* Super-Block row number */
  ogg_uint32_t	SBcol;          /* Super-Block row number */
  ogg_uint32_t	SB=FirstSB;     /* Super-Block index, initialised to first
			           of this component */
  ogg_uint32_t	coded_pixels=0;	/* Number of pixels coded */
  int           MBCodedFlag;

  /* actually transform and quantize the image now that we've decided
     on the modes Parse in quad-tree ordering */

  SB=FirstSB;
  for ( SBrow=0; SBrow<SBRows; SBrow++ ) {
    for ( SBcol=0; SBcol<SBCols; SBcol++ ) {
      /* Check its four Macro-Blocks  */
      for ( MB=0; MB<4; MB++ ) {

	if ( QuadMapToMBTopLeft(cpi->pb.BlockMap,SB,MB) >= 0 ) {

	  MBCodedFlag = 0;

	  /*  Now actually code the blocks */
	  for ( B=0; B<4; B++ ) {
	    FragIndex = QuadMapToIndex1( cpi->pb.BlockMap, SB, MB, B );

	    /* Does Block lie in frame: */
	    if ( FragIndex >= 0 ) {
	      /* In Frame: Is it coded: */
	      if ( cpi->pb.display_fragments[FragIndex] ) {

                /* transform and quantize block */
		TransformQuantizeBlock( cpi, FragIndex, PixelsPerLine );

                /* Has the block got struck off (no MV and no data
		   generated after DCT) If not then mark it and the
		   assosciated MB as coded. */
		if ( cpi->pb.display_fragments[FragIndex] ) {
		  /* Create linear list of coded block indices */
		  cpi->pb.CodedBlockList[cpi->pb.CodedBlockIndex] = FragIndex;
		  cpi->pb.CodedBlockIndex++;

		  /* MB is still coded */
		  MBCodedFlag = 1;
		  cpi->MBCodingMode = cpi->pb.FragCodingMethod[FragIndex];

		}
	      }
	    }
	  }
	  /* If the MB is marked as coded and we are in the Y plane then */
          /* the mode list needs to be updated. */
	  if ( MBCodedFlag && (FirstSB == 0) ){
	    /* Make a note of the selected mode in the mode list */
	    cpi->ModeList[cpi->ModeListCount] = cpi->MBCodingMode;
	    cpi->ModeListCount++;
	  }
	}
      }

      SB++;

    }
  }

  /* Return number of pixels coded */
  return coded_pixels;
}

static void EncodeDcTokenList (CP_INSTANCE *cpi) {
  ogg_int32_t   i,j;
  ogg_uint32_t  Token;
  ogg_uint32_t  ExtraBitsToken;
  ogg_uint32_t  HuffIndex;

  ogg_uint32_t  BestDcBits;
  ogg_uint32_t  DcHuffChoice[2];
  ogg_uint32_t  EntropyTableBits[2][DC_HUFF_CHOICES];

  oggpack_buffer *opb=cpi->oggbuffer;

  /* Clear table data structure */
  memset ( EntropyTableBits, 0, sizeof(ogg_uint32_t)*DC_HUFF_CHOICES*2 );

  /* Analyse token list to see which is the best entropy table to use */
  for ( i = 0; i < cpi->OptimisedTokenCount; i++ ) {
    /* Count number of bits for each table option */
    Token = (ogg_uint32_t)cpi->OptimisedTokenList[i];
    for ( j = 0; j < DC_HUFF_CHOICES; j++ ){
      EntropyTableBits[cpi->OptimisedTokenListPl[i]][j] +=
	cpi->pb.HuffCodeLengthArray_VP3x[DC_HUFF_OFFSET + j][Token];
    }
  }

  /* Work out which table option is best for Y */
  BestDcBits = EntropyTableBits[0][0];
  DcHuffChoice[0] = 0;
  for ( j = 1; j < DC_HUFF_CHOICES; j++ ) {
    if ( EntropyTableBits[0][j] < BestDcBits ) {
      BestDcBits = EntropyTableBits[0][j];
      DcHuffChoice[0] = j;
    }
  }

  /* Add the DC huffman table choice to the bitstream */
  oggpackB_write( opb, DcHuffChoice[0], DC_HUFF_CHOICE_BITS );

  /* Work out which table option is best for UV */
  BestDcBits = EntropyTableBits[1][0];
  DcHuffChoice[1] = 0;
  for ( j = 1; j < DC_HUFF_CHOICES; j++ ) {
    if ( EntropyTableBits[1][j] < BestDcBits ) {
      BestDcBits = EntropyTableBits[1][j];
      DcHuffChoice[1] = j;
    }
  }

  /* Add the DC huffman table choice to the bitstream */
  oggpackB_write( opb, DcHuffChoice[1], DC_HUFF_CHOICE_BITS );

  /* Encode the token list */
  for ( i = 0; i < cpi->OptimisedTokenCount; i++ ) {

    /* Get the token and extra bits */
    Token = (ogg_uint32_t)cpi->OptimisedTokenList[i];
    ExtraBitsToken = (ogg_uint32_t)cpi->OptimisedTokenListEb[i];

    /* Select the huffman table */
    if ( cpi->OptimisedTokenListPl[i] == 0)
      HuffIndex = (ogg_uint32_t)DC_HUFF_OFFSET + (ogg_uint32_t)DcHuffChoice[0];
    else
      HuffIndex = (ogg_uint32_t)DC_HUFF_OFFSET + (ogg_uint32_t)DcHuffChoice[1];

    /* Add the bits to the encode holding buffer. */
    cpi->FrameBitCount += cpi->pb.HuffCodeLengthArray_VP3x[HuffIndex][Token];
    oggpackB_write( opb, cpi->pb.HuffCodeArray_VP3x[HuffIndex][Token],
		     (ogg_uint32_t)cpi->
		     pb.HuffCodeLengthArray_VP3x[HuffIndex][Token] );

    /* If the token is followed by an extra bits token then code it */
    if ( cpi->pb.ExtraBitLengths_VP3x[Token] > 0 ) {
      /* Add the bits to the encode holding buffer.  */
      cpi->FrameBitCount += cpi->pb.ExtraBitLengths_VP3x[Token];
      oggpackB_write( opb, ExtraBitsToken,
		       (ogg_uint32_t)cpi->pb.ExtraBitLengths_VP3x[Token] );
    }
  }

  /* Reset the count of second order optimised tokens */
  cpi->OptimisedTokenCount = 0;
}

static void EncodeAcTokenList (CP_INSTANCE *cpi) {
  ogg_int32_t   i,j;
  ogg_uint32_t  Token;
  ogg_uint32_t  ExtraBitsToken;
  ogg_uint32_t  HuffIndex;

  ogg_uint32_t  BestAcBits;
  ogg_uint32_t  AcHuffChoice[2];
  ogg_uint32_t  EntropyTableBits[2][AC_HUFF_CHOICES];

  oggpack_buffer *opb=cpi->oggbuffer;

  memset ( EntropyTableBits, 0, sizeof(ogg_uint32_t)*AC_HUFF_CHOICES*2 );

  /* Analyse token list to see which is the best entropy table to use */
  for ( i = 0; i < cpi->OptimisedTokenCount; i++ ) {
    /* Count number of bits for each table option */
    Token = (ogg_uint32_t)cpi->OptimisedTokenList[i];
    HuffIndex = cpi->OptimisedTokenListHi[i];
    for ( j = 0; j < AC_HUFF_CHOICES; j++ ) {
      EntropyTableBits[cpi->OptimisedTokenListPl[i]][j] +=
	cpi->pb.HuffCodeLengthArray_VP3x[HuffIndex + j][Token];
    }
  }

  /* Select the best set of AC tables for Y */
  BestAcBits = EntropyTableBits[0][0];
  AcHuffChoice[0] = 0;
  for ( j = 1; j < AC_HUFF_CHOICES; j++ ) {
    if ( EntropyTableBits[0][j] < BestAcBits ) {
      BestAcBits = EntropyTableBits[0][j];
      AcHuffChoice[0] = j;
    }
  }

  /* Add the AC-Y huffman table choice to the bitstream */
  oggpackB_write( opb, AcHuffChoice[0], AC_HUFF_CHOICE_BITS );

  /* Select the best set of AC tables for UV */
  BestAcBits = EntropyTableBits[1][0];
  AcHuffChoice[1] = 0;
  for ( j = 1; j < AC_HUFF_CHOICES; j++ ) {
    if ( EntropyTableBits[1][j] < BestAcBits ) {
      BestAcBits = EntropyTableBits[1][j];
      AcHuffChoice[1] = j;
    }
  }

  /* Add the AC-UV huffman table choice to the bitstream */
  oggpackB_write( opb, AcHuffChoice[1], AC_HUFF_CHOICE_BITS );

  /* Encode the token list */
  for ( i = 0; i < cpi->OptimisedTokenCount; i++ ) {
    /* Get the token and extra bits */
    Token = (ogg_uint32_t)cpi->OptimisedTokenList[i];
    ExtraBitsToken = (ogg_uint32_t)cpi->OptimisedTokenListEb[i];

    /* Select the huffman table */
    HuffIndex = (ogg_uint32_t)cpi->OptimisedTokenListHi[i] +
      AcHuffChoice[cpi->OptimisedTokenListPl[i]];

    /* Add the bits to the encode holding buffer. */
    cpi->FrameBitCount += cpi->pb.HuffCodeLengthArray_VP3x[HuffIndex][Token];
    oggpackB_write( opb, cpi->pb.HuffCodeArray_VP3x[HuffIndex][Token],
		     (ogg_uint32_t)cpi->
		     pb.HuffCodeLengthArray_VP3x[HuffIndex][Token] );

    /* If the token is followed by an extra bits token then code it */
    if ( cpi->pb.ExtraBitLengths_VP3x[Token] > 0 ) {
      /* Add the bits to the encode holding buffer. */
      cpi->FrameBitCount += cpi->pb.ExtraBitLengths_VP3x[Token];
      oggpackB_write( opb, ExtraBitsToken,
		       (ogg_uint32_t)cpi->pb.ExtraBitLengths_VP3x[Token] );
    }
  }

  /* Reset the count of second order optimised tokens */
  cpi->OptimisedTokenCount = 0;
}

static void PackModes (CP_INSTANCE *cpi) {
  ogg_uint32_t  i,j;
  unsigned char   ModeIndex;
  unsigned char  *SchemeList;

  unsigned char   BestModeSchemes[MAX_MODES];
  ogg_int32_t   ModeCount[MAX_MODES];
  ogg_int32_t     TmpFreq = -1;
  ogg_int32_t     TmpIndex = -1;

  ogg_uint32_t    BestScheme;
  ogg_uint32_t  BestSchemeScore;
  ogg_uint32_t  SchemeScore;

  oggpack_buffer *opb=cpi->oggbuffer;

  /* Build a frequency map for the modes in this frame */
  memset( ModeCount, 0, MAX_MODES*sizeof(ogg_int32_t) );
  for ( i = 0; i < cpi->ModeListCount; i++ )
    ModeCount[cpi->ModeList[i]] ++;

  /* Order the modes from most to least frequent.  Store result as
     scheme 0 */
  for ( j = 0; j < MAX_MODES; j++ ) {
    TmpFreq = -1;  /* need to re-initialize for each loop */
    /* Find the most frequent */
    for ( i = 0; i < MAX_MODES; i++ ) {
      /* Is this the best scheme so far ??? */
      if ( ModeCount[i] > TmpFreq ) {
	TmpFreq = ModeCount[i];
	TmpIndex = i;
      }
    }
    /* I don't know if the above loop ever fails to match, but it's
       better safe than sorry.  Plus this takes care of gcc warning */
    if ( TmpIndex != -1 ) {
    ModeCount[TmpIndex] = -1;
    BestModeSchemes[TmpIndex] = (unsigned char)j;
  }
  }

  /* Default/ fallback scheme uses MODE_BITS bits per mode entry */
  BestScheme = (MODE_METHODS - 1);
  BestSchemeScore = cpi->ModeListCount * 3;
  /* Get a bit score for the available schemes. */
  for (  j = 0; j < (MODE_METHODS - 1); j++ ) {

    /* Reset the scheme score */
    if ( j == 0 ){
      /* Scheme 0 additional cost of sending frequency order */
      SchemeScore = 24;
      SchemeList = BestModeSchemes;
    } else {
      SchemeScore = 0;
      SchemeList = ModeSchemes[j-1];
    }

    /* Find the total bits to code using each avaialable scheme */
    for ( i = 0; i < cpi->ModeListCount; i++ )
      SchemeScore += ModeBitLengths[SchemeList[cpi->ModeList[i]]];

    /* Is this the best scheme so far ??? */
    if ( SchemeScore < BestSchemeScore ) {
      BestSchemeScore = SchemeScore;
      BestScheme = j;
    }
  }

  /* Encode the best scheme. */
  oggpackB_write( opb, BestScheme, (ogg_uint32_t)MODE_METHOD_BITS );

  /* If the chosen schems is scheme 0 send details of the mode
     frequency order */
  if ( BestScheme == 0 ) {
    for ( j = 0; j < MAX_MODES; j++ )
      /* Note that the last two entries are implicit */
      oggpackB_write( opb, BestModeSchemes[j], (ogg_uint32_t)MODE_BITS );
    SchemeList = BestModeSchemes;
  }
  else {
    SchemeList = ModeSchemes[BestScheme-1];
  }

  /* Are we using one of the alphabet based schemes or the fallback scheme */
  if ( BestScheme < (MODE_METHODS - 1)) {
    /* Pack and encode the Mode list */
    for ( i = 0; i < cpi->ModeListCount; i++ ) {
      /* Add the appropriate mode entropy token. */
      ModeIndex = SchemeList[cpi->ModeList[i]];
      oggpackB_write( opb, ModeBitPatterns[ModeIndex],
		       (ogg_uint32_t)ModeBitLengths[ModeIndex] );
    }
  }else{
    /* Fall back to MODE_BITS per entry */
    for ( i = 0; i < cpi->ModeListCount; i++ ) {
      /* Add the appropriate mode entropy token. */
      oggpackB_write( opb, cpi->ModeList[i], MODE_BITS  );
    }
  }
}

static void PackMotionVectors (CP_INSTANCE *cpi) {
  ogg_int32_t  i;
  ogg_uint32_t MethodBits[2] = {0,0};
  ogg_uint32_t * MvBitsPtr;
  ogg_uint32_t * MvPatternPtr;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -