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

📄 decode.c

📁 从FFMPEG转换而来的H264解码程序,VC下编译..
💻 C
📖 第 1 页 / 共 2 页
字号:
	    /* Keep track of last and prior last inter motion vectors. */
	    if ( CodingMethod == CODE_INTER_PLUS_MV ){
	      PriorLastInterMV.x = LastInterMV.x;
	      PriorLastInterMV.y = LastInterMV.y;
	      LastInterMV.x = MVect[0].x;
	      LastInterMV.y = MVect[0].y;
	    }else if ( CodingMethod == CODE_INTER_LAST_MV ){
	      /* Use the last coded Inter motion vector. */
	      MVect[0].x = LastInterMV.x;
	      MVect[1].x = MVect[0].x;
	      MVect[2].x = MVect[0].x;
	      MVect[3].x = MVect[0].x;
	      MVect[4].x = MVect[0].x;
	      MVect[5].x = MVect[0].x;
	      MVect[0].y = LastInterMV.y;
	      MVect[1].y = MVect[0].y;
	      MVect[2].y = MVect[0].y;
	      MVect[3].y = MVect[0].y;
	      MVect[4].y = MVect[0].y;
	      MVect[5].y = MVect[0].y;
	    }else if ( CodingMethod == CODE_INTER_PRIOR_LAST ){
              /* Use the next-to-last coded Inter motion vector. */
	      MVect[0].x = PriorLastInterMV.x;
	      MVect[1].x = MVect[0].x;
	      MVect[2].x = MVect[0].x;
	      MVect[3].x = MVect[0].x;
	      MVect[4].x = MVect[0].x;
	      MVect[5].x = MVect[0].x;
	      MVect[0].y = PriorLastInterMV.y;
	      MVect[1].y = MVect[0].y;
	      MVect[2].y = MVect[0].y;
	      MVect[3].y = MVect[0].y;
	      MVect[4].y = MVect[0].y;
	      MVect[5].y = MVect[0].y;

	      /* Swap the prior and last MV cases over */
	      TmpMVect.x = PriorLastInterMV.x;
	      TmpMVect.y = PriorLastInterMV.y;
	      PriorLastInterMV.x = LastInterMV.x;
	      PriorLastInterMV.y = LastInterMV.y;
	      LastInterMV.x = TmpMVect.x;
	      LastInterMV.y = TmpMVect.y;
	    }else if ( CodingMethod == CODE_INTER_FOURMV ){
	      /* Update last MV and prior last mv */
	      PriorLastInterMV.x = LastInterMV.x;
	      PriorLastInterMV.y = LastInterMV.y;
	      LastInterMV.x = MVect[3].x;
	      LastInterMV.y = MVect[3].y;
	    }

	    /* Note the coding mode and vector for each block in the
               current macro block. */
	    pbi->FragMVect[FragIndex].x = MVect[0].x;
	    pbi->FragMVect[FragIndex].y = MVect[0].y;

	    pbi->FragMVect[FragIndex + 1].x = MVect[1].x;
	    pbi->FragMVect[FragIndex + 1].y = MVect[1].y;

	    pbi->FragMVect[FragIndex + pbi->HFragments].x = MVect[2].x;
	    pbi->FragMVect[FragIndex + pbi->HFragments].y = MVect[2].y;

	    pbi->FragMVect[FragIndex + pbi->HFragments + 1].x = MVect[3].x;
	    pbi->FragMVect[FragIndex + pbi->HFragments + 1].y = MVect[3].y;

	    /* Matching fragments in the U and V planes */
	    UVRow = (FragIndex / (pbi->HFragments * 2));
	    UVColumn = (FragIndex % pbi->HFragments) / 2;
	    UVFragOffset = (UVRow * (pbi->HFragments / 2)) + UVColumn;

	    pbi->FragMVect[pbi->YPlaneFragments + UVFragOffset].x = MVect[4].x;
	    pbi->FragMVect[pbi->YPlaneFragments + UVFragOffset].y = MVect[4].y;

	    pbi->FragMVect[pbi->YPlaneFragments + pbi->UVPlaneFragments +
			  UVFragOffset].x = MVect[5].x;
	    pbi->FragMVect[pbi->YPlaneFragments + pbi->UVPlaneFragments +
			  UVFragOffset].y = MVect[5].y;
	  }
	}
      }

      /* Next Super-Block */
      SB++;
    }
  }
}

static ogg_uint32_t ExtractToken(oggpack_buffer *opb,
				 HUFF_ENTRY * CurrentRoot){
  long ret;
  ogg_uint32_t Token;
  /* Loop searches down through tree based upon bits read from the
     bitstream */
  /* until it hits a leaf at which point we have decoded a token */
  while ( CurrentRoot->Value < 0 ){

    theora_read(opb, 1, &ret);
    if (ret)
      CurrentRoot = CurrentRoot->OneChild;
    else
      CurrentRoot = CurrentRoot->ZeroChild;

  }
  Token = CurrentRoot->Value;
  return Token;
}

static void UnpackAndExpandDcToken( PB_INSTANCE *pbi,
				    Q_LIST_ENTRY *ExpandedBlock,
				    unsigned char * CoeffIndex ){
  long			ret;
  ogg_int32_t           ExtraBits = 0;
  ogg_uint32_t          Token;

  Token = ExtractToken(pbi->opb, pbi->HuffRoot_VP3x[pbi->DcHuffChoice]);


  /* Now.. if we are using the DCT optimised coding system, extract any
   *  assosciated additional bits token.
   */
  if ( pbi->ExtraBitLengths_VP3x[Token] > 0 ){
    /* Extract the appropriate number of extra bits. */
    theora_read(pbi->opb,pbi->ExtraBitLengths_VP3x[Token], &ret);
    ExtraBits = ret;
  }

  /* Take token dependant action */
  if ( Token >= DCT_SHORT_ZRL_TOKEN ) {
    /* "Value", "zero run" and "zero run value" tokens */
    ExpandToken(ExpandedBlock, CoeffIndex, Token, ExtraBits );
    if ( *CoeffIndex >= BLOCK_SIZE )
      pbi->BlocksToDecode --;
  } else if ( Token == DCT_EOB_TOKEN ){
    *CoeffIndex = BLOCK_SIZE;
    pbi->BlocksToDecode --;
  }else{
    /* Special action and EOB tokens */
    switch ( Token ){
    case DCT_EOB_PAIR_TOKEN:
      pbi->EOB_Run = 1;
      *CoeffIndex = BLOCK_SIZE;
      pbi->BlocksToDecode --;
      break;
    case DCT_EOB_TRIPLE_TOKEN:
      pbi->EOB_Run = 2;
      *CoeffIndex = BLOCK_SIZE;
      pbi->BlocksToDecode --;
      break;
    case DCT_REPEAT_RUN_TOKEN:
      pbi->EOB_Run = ExtraBits + 3;
      *CoeffIndex = BLOCK_SIZE;
      pbi->BlocksToDecode --;
      break;
    case DCT_REPEAT_RUN2_TOKEN:
      pbi->EOB_Run = ExtraBits + 7;
      *CoeffIndex = BLOCK_SIZE;
      pbi->BlocksToDecode --;
      break;
    case DCT_REPEAT_RUN3_TOKEN:
      pbi->EOB_Run = ExtraBits + 15;
      *CoeffIndex = BLOCK_SIZE;
      pbi->BlocksToDecode --;
      break;
    case DCT_REPEAT_RUN4_TOKEN:
      pbi->EOB_Run = ExtraBits - 1;
      *CoeffIndex = BLOCK_SIZE;
      pbi->BlocksToDecode --;
      break;
    }
  }
}

static void UnpackAndExpandAcToken( PB_INSTANCE *pbi,
				    Q_LIST_ENTRY * ExpandedBlock,
				    unsigned char * CoeffIndex  ) {
  long                  ret;
  ogg_int32_t           ExtraBits = 0;
  ogg_uint32_t          Token;

  Token = ExtractToken(pbi->opb, pbi->HuffRoot_VP3x[pbi->ACHuffChoice]);

  /* Now.. if we are using the DCT optimised coding system, extract any
   *  assosciated additional bits token.
   */
  if ( pbi->ExtraBitLengths_VP3x[Token] > 0 ){
    /* Extract the appropriate number of extra bits. */
    theora_read(pbi->opb,pbi->ExtraBitLengths_VP3x[Token], &ret);
    ExtraBits = ret;
  }

  /* Take token dependant action */
  if ( Token >= DCT_SHORT_ZRL_TOKEN ){
    /* "Value", "zero run" and "zero run value" tokens */
    ExpandToken(ExpandedBlock, CoeffIndex, Token, ExtraBits );
    if ( *CoeffIndex >= BLOCK_SIZE )
      pbi->BlocksToDecode --;
  } else if ( Token == DCT_EOB_TOKEN ) {
    *CoeffIndex = BLOCK_SIZE;
    pbi->BlocksToDecode --;
  } else {
    /* Special action and EOB tokens */
    switch ( Token ) {
    case DCT_EOB_PAIR_TOKEN:
      pbi->EOB_Run = 1;
      *CoeffIndex = BLOCK_SIZE;
      pbi->BlocksToDecode --;
      break;
    case DCT_EOB_TRIPLE_TOKEN:
      pbi->EOB_Run = 2;
      *CoeffIndex = BLOCK_SIZE;
      pbi->BlocksToDecode --;
      break;
    case DCT_REPEAT_RUN_TOKEN:
      pbi->EOB_Run = ExtraBits + 3;
      *CoeffIndex = BLOCK_SIZE;
      pbi->BlocksToDecode --;
      break;
    case DCT_REPEAT_RUN2_TOKEN:
      pbi->EOB_Run = ExtraBits + 7;
      *CoeffIndex = BLOCK_SIZE;
      pbi->BlocksToDecode --;
      break;
    case DCT_REPEAT_RUN3_TOKEN:
      pbi->EOB_Run = ExtraBits + 15;
      *CoeffIndex = BLOCK_SIZE;
      pbi->BlocksToDecode --;
      break;
    case DCT_REPEAT_RUN4_TOKEN:
      pbi->EOB_Run = ExtraBits - 1;
      *CoeffIndex = BLOCK_SIZE;
      pbi->BlocksToDecode --;
      break;
    }
  }
}

static void UnPackVideo (PB_INSTANCE *pbi){
  long ret;
  ogg_int32_t       EncodedCoeffs = 1;
  ogg_int32_t       FragIndex;
  ogg_int32_t *     CodedBlockListPtr;
  ogg_int32_t *     CodedBlockListEnd;

  unsigned char     AcHuffIndex1;
  unsigned char     AcHuffIndex2;
  unsigned char     AcHuffChoice1;
  unsigned char     AcHuffChoice2;

  unsigned char     DcHuffChoice1;
  unsigned char     DcHuffChoice2;


  /* Bail out immediately if a decode error has already been reported. */
  if ( pbi->DecoderErrorCode ) return;

  /* Clear down the array that indicates the current coefficient index
     for each block. */
  memset(pbi->FragCoeffs, 0, pbi->UnitFragments);
  memset(pbi->FragCoefEOB, 0, pbi->UnitFragments);

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

  /* Note the number of blocks to decode */
  pbi->BlocksToDecode = pbi->CodedBlockIndex;

  /* Get the DC huffman table choice for Y and then UV */
  theora_read(pbi->opb,DC_HUFF_CHOICE_BITS,&ret);
  DcHuffChoice1 = ret + DC_HUFF_OFFSET;
  theora_read(pbi->opb,DC_HUFF_CHOICE_BITS,&ret);
  DcHuffChoice2 = ret + DC_HUFF_OFFSET;

  /* UnPack DC coefficients / tokens */
  CodedBlockListPtr = pbi->CodedBlockList;
  CodedBlockListEnd = &pbi->CodedBlockList[pbi->CodedBlockIndex];
  while ( CodedBlockListPtr < CodedBlockListEnd  ) {
    /* Get the block data index */
    FragIndex = *CodedBlockListPtr;
    pbi->FragCoefEOB[FragIndex] = pbi->FragCoeffs[FragIndex];

    /* Select the appropriate huffman table offset according to
       whether the token is from a Y or UV block */
    if ( FragIndex < (ogg_int32_t)pbi->YPlaneFragments )
      pbi->DcHuffChoice = DcHuffChoice1;
    else
      pbi->DcHuffChoice = DcHuffChoice2;

    /* If we are in the middle of an EOB run */
    if ( pbi->EOB_Run ){
      /* Mark the current block as fully expanded and decrement
         EOB_RUN count */
      pbi->FragCoeffs[FragIndex] = BLOCK_SIZE;
      pbi->EOB_Run --;
      pbi->BlocksToDecode --;
    }else{
      /* Else unpack a DC token */
      UnpackAndExpandDcToken( pbi,
			      pbi->QFragData[FragIndex],
			      &pbi->FragCoeffs[FragIndex] );
    }
    CodedBlockListPtr++;
  }

  /* Get the AC huffman table choice for Y and then for UV. */

  theora_read(pbi->opb,AC_HUFF_CHOICE_BITS,&ret);
  AcHuffIndex1 = ret + AC_HUFF_OFFSET;
  theora_read(pbi->opb,AC_HUFF_CHOICE_BITS,&ret);
  AcHuffIndex2 = ret + AC_HUFF_OFFSET;

  /* Unpack Lower AC coefficients. */
  while ( EncodedCoeffs < 64 ) {
    /* Repeatedly scan through the list of blocks. */
    CodedBlockListPtr = pbi->CodedBlockList;
    CodedBlockListEnd = &pbi->CodedBlockList[pbi->CodedBlockIndex];

    /* Huffman table selection based upon which AC coefficient we are on */
    if ( EncodedCoeffs <= AC_TABLE_2_THRESH ){
      AcHuffChoice1 = AcHuffIndex1;
      AcHuffChoice2 = AcHuffIndex2;
    }else if ( EncodedCoeffs <= AC_TABLE_3_THRESH ){
      AcHuffChoice1 = AcHuffIndex1 + AC_HUFF_CHOICES;
      AcHuffChoice2 = AcHuffIndex2 + AC_HUFF_CHOICES;
    } else if ( EncodedCoeffs <= AC_TABLE_4_THRESH ){
      AcHuffChoice1 = AcHuffIndex1 + (AC_HUFF_CHOICES * 2);
      AcHuffChoice2 = AcHuffIndex2 + (AC_HUFF_CHOICES * 2);
    } else {
      AcHuffChoice1 = AcHuffIndex1 + (AC_HUFF_CHOICES * 3);
      AcHuffChoice2 = AcHuffIndex2 + (AC_HUFF_CHOICES * 3);
    }

    while( CodedBlockListPtr < CodedBlockListEnd ) {
      /* Get the linear index for the current fragment. */
      FragIndex = *CodedBlockListPtr;

      /* Should we decode a token for this block on this pass. */
      if ( pbi->FragCoeffs[FragIndex] <= EncodedCoeffs ) {
	pbi->FragCoefEOB[FragIndex] = pbi->FragCoeffs[FragIndex];
	/* If we are in the middle of an EOB run */
	if ( pbi->EOB_Run ) {
	  /* Mark the current block as fully expanded and decrement
             EOB_RUN count */
	  pbi->FragCoeffs[FragIndex] = BLOCK_SIZE;
	  pbi->EOB_Run --;
	  pbi->BlocksToDecode --;
	}else{
	  /* Else unpack an AC token */
	  /* Work out which huffman table to use, then decode a token */
	  if ( FragIndex < (ogg_int32_t)pbi->YPlaneFragments )
	    pbi->ACHuffChoice = AcHuffChoice1;
	  else
	    pbi->ACHuffChoice = AcHuffChoice2;

	  UnpackAndExpandAcToken( pbi, pbi->QFragData[FragIndex],
				  &pbi->FragCoeffs[FragIndex] );
	}
      }
      CodedBlockListPtr++;
    }

    /* Test for condition where there are no blocks left with any
       tokesn to decode */
    if ( !pbi->BlocksToDecode )
      break;

    EncodedCoeffs ++;
  }
}

static void DecodeData(PB_INSTANCE *pbi){
  ogg_uint32_t i;

  /* Bail out immediately if a decode error has already been reported. */
  if ( pbi->DecoderErrorCode ) return;

  /* Clear down the macro block level mode and MV arrays. */
  for ( i = 0; i < pbi->UnitFragments; i++ ){
    pbi->FragCodingMethod[i] = CODE_INTER_NO_MV; /* Default coding mode */
    pbi->FragMVect[i].x = 0;
    pbi->FragMVect[i].y = 0;
  }

  /* Zero Decoder EOB run count */
  pbi->EOB_Run = 0;

  /* Make a note 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 ){
      pbi->LastFrameQualityValue = pbi->ThisFrameQualityValue;

    /* Decode the data into the fragment buffer. */
    DecodeData(pbi);
    return(0);
  }

  return(OC_BADPACKET);
}

⌨️ 快捷键说明

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