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

📄 decode.c

📁 从FFMPEG转换而来的H264解码程序,VC下编译..
💻 C
📖 第 1 页 / 共 2 页
字号:
/********************************************************************
 *                                                                  *
 * 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 <string.h>
#include "codec_internal.h"
#include "block_inline.h"

static const CODING_MODE  ModeAlphabet[MODE_METHODS-2][MAX_MODES] = {

  /* 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){
  long ret;
  int NQIndex;
  unsigned char  DctQIndex[3];
  unsigned char  SpareBits;       /* Spare cfg bits */

  /* Is the frame and inter frame or a key frame */
  theora_read(pbi->opb,1,&ret);
  pbi->FrameType = (unsigned char)ret;

  /* Quality (Q) index */
  NQIndex = 0;
  theora_read(pbi->opb,6,&ret);
  DctQIndex[NQIndex++] = (unsigned char)ret;

  theora_read(pbi->opb,1,&ret);
  SpareBits = (unsigned char)ret;
  if (SpareBits) {
    theora_read(pbi->opb,6,&ret);
    DctQIndex[NQIndex++] = (unsigned char)ret;
    theora_read(pbi->opb,1,&ret);
    SpareBits = (unsigned char)ret;
    if (SpareBits) {
      theora_read(pbi->opb,6,&ret);
      DctQIndex[NQIndex++] = (unsigned char)ret;
    }
  }

  if (NQIndex != 1) return OC_IMPL;

  if ( (pbi->FrameType == KEY_FRAME) ){
    /* Read the type / coding method for the key frame. */
    theora_read(pbi->opb,1,&ret);
    pbi->KeyFrameType = (unsigned char)ret;

    theora_read(pbi->opb,2,&ret);
    SpareBits = (unsigned char)ret;

    if (pbi->KeyFrameType || SpareBits) return OC_BADPACKET;
  }

  /* Set this frame quality value and tables from the coded Q Index */
  UpdateQ(pbi, DctQIndex[0]);

  return 1;
}

void SetFrameType( PB_INSTANCE *pbi,unsigned char FrType ){
  /* Set the appropriate frame type according to the request. */
  switch ( FrType ){

  case KEY_FRAME:
    pbi->FrameType = FrType;
    break;

  default:
    pbi->FrameType = FrType;
    break;
  }
}

static int LoadFrame(PB_INSTANCE *pbi){

  /* Load the frame header (including the frame size). */
  if ( LoadFrameHeader(pbi) ){
    /* Read in the updated block map */
    QuadDecodeDisplayFragments( pbi );
    return 1;
  }

  return 0;
}

static void DecodeModes (PB_INSTANCE *pbi,
			 ogg_uint32_t SBRows,
			 ogg_uint32_t SBCols){
  long ret;
  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) == KEY_FRAME ){
    for ( i = 0; i < pbi->UnitFragments; i++ ){
      pbi->FragCodingMethod[i] = CODE_INTRA;
    }
  }else{
    ogg_uint32_t  ModeEntry; /* Mode bits read */
    CODING_MODE         CustomModeAlphabet[MAX_MODES];
    const CODING_MODE  *ModeList;

    /* Read the coding method */
    theora_read(pbi->opb, MODE_METHOD_BITS, &ret);
    CodingScheme=ret;

    /* 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++ ){
        theora_read(pbi->opb, MODE_BITS, &ret);
        CustomModeAlphabet[ret]=i;
      }
      ModeList=CustomModeAlphabet;
    }
    else{
      ModeList=ModeAlphabet[CodingScheme-1];
    }

    /* 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. */
                theora_read(pbi->opb, MODE_BITS, &ret);
                CodingMethod = (CODING_MODE)ret;
	      }else{
		ModeEntry = FrArrayUnpackMode(pbi);
                CodingMethod = ModeList[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){
  long ret;
  ogg_int32_t   MVectComponent;
  ogg_uint32_t  MVCode = 0;
  ogg_uint32_t  ExtraBits = 0;

  /* Get group to which coded component belongs */
  theora_read(pbi->opb, 3, &ret);
  MVCode=ret;

  /*  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:
    theora_read(pbi->opb,1,&ret);
    if (ret)
      MVectComponent = -2;
    else
      MVectComponent = 2;
    break;
  case 4:
    theora_read(pbi->opb,1,&ret);
    if (ret)
      MVectComponent = -3;
    else
      MVectComponent = 3;
    break;
  case 5:
    theora_read(pbi->opb,2,&ret);
    ExtraBits=ret;
    MVectComponent = 4 + ExtraBits;
    theora_read(pbi->opb,1,&ret);
    if (ret)
      MVectComponent = -MVectComponent;
    break;
  case 6:
    theora_read(pbi->opb,3,&ret);
    ExtraBits=ret;
    MVectComponent = 8 + ExtraBits;
    theora_read(pbi->opb,1,&ret);
    if (ret)
      MVectComponent = -MVectComponent;
    break;
  case 7:
    theora_read(pbi->opb,4,&ret);
    ExtraBits=ret;
    MVectComponent = 16 + ExtraBits;
    theora_read(pbi->opb,1,&ret);
    if (ret)
      MVectComponent = -MVectComponent;
    break;
  }

  return MVectComponent;
}

static ogg_int32_t ExtractMVectorComponentB(PB_INSTANCE *pbi){
  long ret;
  ogg_int32_t   MVectComponent;

  /* Get group to which coded component belongs */
  theora_read(pbi->opb,5,&ret);
  MVectComponent=ret;
  theora_read(pbi->opb,1,&ret);
  if (ret)
    MVectComponent = -MVectComponent;

  return MVectComponent;
}

static void DecodeMVectors ( PB_INSTANCE *pbi,
			     ogg_uint32_t SBRows,
			     ogg_uint32_t SBCols ){
  long ret;
  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) == KEY_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 */
  theora_read(pbi->opb, 1, &ret);
  if ( ret == 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;
	    }

⌨️ 快捷键说明

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