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

📄 encode.c

📁 从FFMPEG转换而来的H264解码程序,VC下编译..
💻 C
📖 第 1 页 / 共 4 页
字号:

  oggpack_buffer *opb=cpi->oggbuffer;

  /* Choose the coding method */
  MvBitsPtr = &MvBits[MAX_MV_EXTENT];
  for ( i = 0; i < (ogg_int32_t)cpi->MvListCount; i++ ) {
    MethodBits[0] += MvBitsPtr[cpi->MVList[i].x];
    MethodBits[0] += MvBitsPtr[cpi->MVList[i].y];
    MethodBits[1] += 12; /* Simple six bits per mv component fallback
                             mechanism */
  }

  /* Select entropy table */
  if ( MethodBits[0] < MethodBits[1] ) {
    oggpackB_write( opb, 0, 1 );
    MvBitsPtr = &MvBits[MAX_MV_EXTENT];
    MvPatternPtr = &MvPattern[MAX_MV_EXTENT];
  }else{
    oggpackB_write( opb, 1, 1 );
    MvBitsPtr = &MvBits2[MAX_MV_EXTENT];
    MvPatternPtr = &MvPattern2[MAX_MV_EXTENT];
  }

  /* Pack and encode the motion vectors */
  for ( i = 0; i < (ogg_int32_t)cpi->MvListCount; i++ ) {
    oggpackB_write( opb, MvPatternPtr[cpi->MVList[i].x],
		     (ogg_uint32_t)MvBitsPtr[cpi->MVList[i].x] );
    oggpackB_write( opb, MvPatternPtr[cpi->MVList[i].y],
		     (ogg_uint32_t)MvBitsPtr[cpi->MVList[i].y] );
  }
}

static void PackEOBRun( CP_INSTANCE *cpi) {
  if(cpi->RunLength == 0)
        return;

  /* Note the appropriate EOB or EOB run token and any extra bits in
     the optimised token list.  Use the huffman index assosciated with
     the first token in the run */

  /* Mark out which plane the block belonged to */
  cpi->OptimisedTokenListPl[cpi->OptimisedTokenCount] =
    (unsigned char)cpi->RunPlaneIndex;

  /* Note the huffman index to be used */
  cpi->OptimisedTokenListHi[cpi->OptimisedTokenCount] =
    (unsigned char)cpi->RunHuffIndex;

  if ( cpi->RunLength <= 3 ) {
    if ( cpi->RunLength == 1 ) {
      cpi->OptimisedTokenList[cpi->OptimisedTokenCount] = DCT_EOB_TOKEN;
    } else if ( cpi->RunLength == 2 ) {
      cpi->OptimisedTokenList[cpi->OptimisedTokenCount] = DCT_EOB_PAIR_TOKEN;
    } else {
      cpi->OptimisedTokenList[cpi->OptimisedTokenCount] = DCT_EOB_TRIPLE_TOKEN;
    }

    cpi->RunLength = 0;

  } else {

    /* Choose a token appropriate to the run length. */
    if ( cpi->RunLength < 8 ) {
      cpi->OptimisedTokenList[cpi->OptimisedTokenCount] =
	DCT_REPEAT_RUN_TOKEN;
      cpi->OptimisedTokenListEb[cpi->OptimisedTokenCount] =
	cpi->RunLength - 4;
      cpi->RunLength = 0;
    } else if ( cpi->RunLength < 16 ) {
      cpi->OptimisedTokenList[cpi->OptimisedTokenCount] =
	DCT_REPEAT_RUN2_TOKEN;
      cpi->OptimisedTokenListEb[cpi->OptimisedTokenCount] =
	cpi->RunLength - 8;
      cpi->RunLength = 0;
    } else if ( cpi->RunLength < 32 ) {
      cpi->OptimisedTokenList[cpi->OptimisedTokenCount] =
	DCT_REPEAT_RUN3_TOKEN;
      cpi->OptimisedTokenListEb[cpi->OptimisedTokenCount] =
	cpi->RunLength - 16;
      cpi->RunLength = 0;
    } else if ( cpi->RunLength < 4096) {
      cpi->OptimisedTokenList[cpi->OptimisedTokenCount] =
	DCT_REPEAT_RUN4_TOKEN;
      cpi->OptimisedTokenListEb[cpi->OptimisedTokenCount] =
	cpi->RunLength;
      cpi->RunLength = 0;
    }

  }

  cpi->OptimisedTokenCount++;
  /* Reset run EOB length */
  cpi->RunLength = 0;
}

static void PackToken ( CP_INSTANCE *cpi, ogg_int32_t FragmentNumber,
		 ogg_uint32_t HuffIndex ) {
  ogg_uint32_t Token =
    cpi->pb.TokenList[FragmentNumber][cpi->FragTokens[FragmentNumber]];
  ogg_uint32_t ExtraBitsToken =
    cpi->pb.TokenList[FragmentNumber][cpi->FragTokens[FragmentNumber] + 1];
  ogg_uint32_t OneOrTwo;
  ogg_uint32_t OneOrZero;

  /* Update the record of what coefficient we have got up to for this
     block and unpack the encoded token back into the quantised data
     array. */
  if ( Token == DCT_EOB_TOKEN )
    cpi->pb.FragCoeffs[FragmentNumber] = BLOCK_SIZE;
  else
    ExpandToken( cpi->pb.QFragData[FragmentNumber],
		 &cpi->pb.FragCoeffs[FragmentNumber],
		 Token, ExtraBitsToken );

  /* Update record of tokens coded and where we are in this fragment. */
  /* Is there an extra bits token */
  OneOrTwo= 1 + ( cpi->pb.ExtraBitLengths_VP3x[Token] > 0 );
  /* Advance to the next real token. */
  cpi->FragTokens[FragmentNumber] += (unsigned char)OneOrTwo;

  /* Update the counts of tokens coded */
  cpi->TokensCoded += OneOrTwo;
  cpi->TokensToBeCoded -= OneOrTwo;

  OneOrZero = ( FragmentNumber < (ogg_int32_t)cpi->pb.YPlaneFragments );

  if ( Token == DCT_EOB_TOKEN ) {
    if ( cpi->RunLength == 0 ) {
      cpi->RunHuffIndex = HuffIndex;
      cpi->RunPlaneIndex = 1 -  OneOrZero;
    }
    cpi->RunLength++;

    /* we have exceeded our longest run length  xmit an eob run token; */
    if ( cpi->RunLength == 4095 ) PackEOBRun(cpi);

  }else{

    /* If we have an EOB run then code it up first */
    if ( cpi->RunLength > 0 ) PackEOBRun( cpi);

    /* Mark out which plane the block belonged to */
    cpi->OptimisedTokenListPl[cpi->OptimisedTokenCount] =
      (unsigned char)(1 - OneOrZero);

    /* Note the token, extra bits and hufman table in the optimised
       token list */
    cpi->OptimisedTokenList[cpi->OptimisedTokenCount] =
      (unsigned char)Token;
    cpi->OptimisedTokenListEb[cpi->OptimisedTokenCount] =
      ExtraBitsToken;
    cpi->OptimisedTokenListHi[cpi->OptimisedTokenCount] =
      (unsigned char)HuffIndex;

    cpi->OptimisedTokenCount++;
  }
}

static ogg_uint32_t GetBlockReconErrorSlow( CP_INSTANCE *cpi,
				     ogg_int32_t BlockIndex ) {
  ogg_uint32_t  ErrorVal;

  unsigned char * SrcDataPtr =
    &cpi->ConvDestBuffer[cpi->pb.pixel_index_table[BlockIndex]];
  unsigned char * RecDataPtr =
    &cpi->pb.LastFrameRecon[cpi->pb.recon_pixel_index_table[BlockIndex]];
  ogg_int32_t   SrcStride;
  ogg_int32_t   RecStride;

  /* Is the block a Y block or a UV block. */
  if ( BlockIndex < (ogg_int32_t)cpi->pb.YPlaneFragments ) {
    SrcStride = cpi->pb.info.width;
    RecStride = cpi->pb.YStride;
  }else{
    SrcStride = cpi->pb.info.width >> 1;
    RecStride = cpi->pb.UVStride;
  }

  ErrorVal = dsp_static_sad8x8 (SrcDataPtr, SrcStride, RecDataPtr, RecStride);

  return ErrorVal;
}

static void PackCodedVideo (CP_INSTANCE *cpi) {
  ogg_int32_t i;
  ogg_int32_t EncodedCoeffs = 1;
  ogg_int32_t FragIndex;
  ogg_uint32_t HuffIndex; /* Index to group of tables used to code a token */

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

  cpi->TokensToBeCoded = cpi->TotTokenCount;
  cpi->TokensCoded = 0;

  /* Calculate the bit rate at which this frame should be capped. */
  cpi->MaxBitTarget = (ogg_uint32_t)((double)(cpi->ThisFrameTargetBytes * 8) *
				     cpi->BitRateCapFactor);

  /* Blank the various fragment data structures before we start. */
  memset(cpi->pb.FragCoeffs, 0, cpi->pb.UnitFragments);
  memset(cpi->FragTokens, 0, cpi->pb.UnitFragments);

  /* Clear down the QFragData structure for all coded blocks. */
  ClearDownQFragData(&cpi->pb);

  /* The tree is not needed (implicit) for key frames */
  if ( GetFrameType(&cpi->pb) != KEY_FRAME ){
    /* Pack the quad tree fragment mapping. */
    PackAndWriteDFArray( cpi );
  }

  /* Note the number of bits used to code the tree itself. */
  cpi->FrameBitCount = oggpackB_bytes(cpi->oggbuffer) << 3;

  /* Mode and MV data not needed for key frames. */
  if ( GetFrameType(&cpi->pb) != KEY_FRAME ){
    /* Pack and code the mode list. */
    PackModes(cpi);
    /* Pack the motion vectors */
    PackMotionVectors (cpi);
  }

  cpi->FrameBitCount = oggpackB_bytes(cpi->oggbuffer) << 3;

  /* Optimise the DC tokens */
  for ( i = 0; i < cpi->pb.CodedBlockIndex; i++ ) {
    /* Get the linear index for the current fragment. */
    FragIndex = cpi->pb.CodedBlockList[i];

    cpi->pb.FragCoefEOB[FragIndex]=(unsigned char)EncodedCoeffs;
    PackToken(cpi, FragIndex, DC_HUFF_OFFSET );

  }

  /* Pack any outstanding EOB tokens */
  PackEOBRun(cpi);

  /* Now output the optimised DC token list using the appropriate
     entropy tables. */
  EncodeDcTokenList(cpi);

  /* Work out the number of DC bits coded */

  /* Optimise the AC tokens */
  while ( EncodedCoeffs < 64 ) {
    /* Huffman table adjustment based upon coefficient number. */
    if ( EncodedCoeffs <= AC_TABLE_2_THRESH )
      HuffIndex = AC_HUFF_OFFSET;
    else if ( EncodedCoeffs <= AC_TABLE_3_THRESH )
      HuffIndex = AC_HUFF_OFFSET + AC_HUFF_CHOICES;
    else if ( EncodedCoeffs <= AC_TABLE_4_THRESH )
      HuffIndex = AC_HUFF_OFFSET + (AC_HUFF_CHOICES * 2);
    else
      HuffIndex = AC_HUFF_OFFSET + (AC_HUFF_CHOICES * 3);

    /* Repeatedly scan through the list of blocks. */
    for ( i = 0; i < cpi->pb.CodedBlockIndex; i++ ) {
      /* Get the linear index for the current fragment. */
      FragIndex = cpi->pb.CodedBlockList[i];

      /* Should we code a token for this block on this pass. */
      if ( cpi->FragTokens[FragIndex] < cpi->FragTokenCounts[FragIndex]
	   && cpi->pb.FragCoeffs[FragIndex] <= EncodedCoeffs ) {
	/* Bit pack and a token for this block */
        cpi->pb.FragCoefEOB[FragIndex]=(unsigned char)EncodedCoeffs;
	PackToken( cpi, FragIndex, HuffIndex );
      }
    }

    EncodedCoeffs ++;
  }

  /* Pack any outstanding EOB tokens */
  PackEOBRun(cpi);

  /* Now output the optimised AC token list using the appropriate
     entropy tables. */
  EncodeAcTokenList(cpi);

}

static ogg_uint32_t QuadCodeDisplayFragments (CP_INSTANCE *cpi) {
  ogg_int32_t   i,j;
  ogg_uint32_t	coded_pixels=0;
  int           QIndex;
  int k,m,n;

  /* predictor multiplier up-left, up, up-right,left, shift
     Entries are packed in the order L, UL, U, UR, with missing entries
      moved to the end (before the shift parameters). */
  static const ogg_int16_t pc[16][6]={
    {0,0,0,0,0,0},
    {1,0,0,0,0,0},      /* PL */
    {1,0,0,0,0,0},      /* PUL */
    {1,0,0,0,0,0},      /* PUL|PL */
    {1,0,0,0,0,0},      /* PU */
    {1,1,0,0,1,1},      /* PU|PL */
    {0,1,0,0,0,0},      /* PU|PUL */
    {29,-26,29,0,5,31}, /* PU|PUL|PL */
    {1,0,0,0,0,0},      /* PUR */
    {75,53,0,0,7,127},  /* PUR|PL */
    {1,1,0,0,1,1},      /* PUR|PUL */
    {75,0,53,0,7,127},  /* PUR|PUL|PL */
    {1,0,0,0,0,0},      /* PUR|PU */
    {75,0,53,0,7,127},  /* PUR|PU|PL */
    {3,10,3,0,4,15},    /* PUR|PU|PUL */
    {29,-26,29,0,5,31}  /* PUR|PU|PUL|PL */
  };

  /* boundary case bit masks. */
  static const int bc_mask[8]={
    /* normal case no boundary condition */
    PUR|PU|PUL|PL,
    /* left column */
    PUR|PU,
    /* top row */
    PL,
    /* top row, left column */
    0,
    /* right column */
    PU|PUL|PL,
    /* right and left column */
    PU,
    /* top row, right column */
    PL,
    /* top row, right and left column */
    0
  };

  /* value left value up-left, value up, value up-right, missing
      values skipped. */
  int v[4];

  /* fragment number left, up-left, up, up-right */
  int fn[4];

  /* predictor count. */
  int pcount;

  /*which predictor constants to use */
  ogg_int16_t wpc;

  /* last used inter predictor (Raster Order) */
  ogg_int16_t Last[3];	/* last value used for given frame */

  int FragsAcross=cpi->pb.HFragments;
  int FragsDown = cpi->pb.VFragments;
  int FromFragment,ToFragment;
  ogg_int32_t	FragIndex;
  int WhichFrame;
  int WhichCase;

  static const ogg_int16_t Mode2Frame[] = {
    1,	/* CODE_INTER_NO_MV	0 => Encoded diff from same MB last frame  */
    0,	/* CODE_INTRA		1 => DCT Encoded Block */
    1,	/* CODE_INTER_PLUS_MV	2 => Encoded diff from included MV MB last frame */
    1,	/* CODE_INTER_LAST_MV	3 => Encoded diff from MRU MV MB last frame */
    1,	/* CODE_INTER_PRIOR_MV	4 => Encoded diff from included 4 separate MV blocks */
    2,	/* CODE_USING_GOLDEN	5 => Encoded diff from same MB golden frame */
    2,	/* CODE_GOLDEN_MV	6 => Encoded diff from included MV MB golden frame */
    1	/* CODE_INTER_FOUR_MV	7 => Encoded diff from included 4 separate MV blocks */
  };

  ogg_int16_t PredictedDC;

  /* Initialise the coded block indices variables. These allow
     subsequent linear access to the quad tree ordered list of coded
     blocks */
  cpi->pb.CodedBlockIndex = 0;

  /* Set the inter/intra descision control variables. */

⌨️ 快捷键说明

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