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

📄 dct_decode.c

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


#define GOLDEN_FRAME_THRESH_Q   50
#define PUR 8
#define PU 4
#define PUL 2
#define PL 1
#define HIGHBITDUPPED(X) (((signed short) X)  >> 15)

/* in-loop filter tables. one of these is used in dct_decode.c */

static const unsigned char LoopFilterLimitValuesV1[Q_TABLE_SIZE] = {
  30, 25, 20, 20, 15, 15, 14, 14,
  13, 13, 12, 12, 11, 11, 10, 10,
  9,  9,  8,  8,  7,  7,  7,  7,
  6,  6,  6,  6,  5,  5,  5,  5,
  4,  4,  4,  4,  3,  3,  3,  3,
  2,  2,  2,  2,  2,  2,  2,  2,
  0,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  0,  0
};

const unsigned char LoopFilterLimitValuesV2[Q_TABLE_SIZE] = {
  30, 25, 20, 20, 15, 15, 14, 14,
  13, 13, 12, 12, 11, 11, 10, 10,
  9,  9,  8,  8,  7,  7,  7,  7,
  6,  6,  6,  6,  5,  5,  5,  5,
  4,  4,  4,  4,  3,  3,  3,  3,
  2,  2,  2,  2,  2,  2,  2,  2,
  2,  2,  2,  2,  2,  2,  2,  2,
  1,  1,  1,  1,  1,  1,  1,  1
};

static const int ModeUsesMC[MAX_MODES] = { 0, 0, 1, 1, 1, 0, 1, 1 };

void SetupBoundingValueArray_Generic(PB_INSTANCE *pbi,
					    ogg_int32_t FLimit){

  ogg_int32_t * BoundingValuePtr = pbi->FiltBoundingValue+256;
  ogg_int32_t i;

  /* Set up the bounding value array. */
  memset ( pbi->FiltBoundingValue, 0, (512*sizeof(*pbi->FiltBoundingValue)) );
  for ( i = 0; i < FLimit; i++ ){
    BoundingValuePtr[-i-FLimit] = (-FLimit+i);
    BoundingValuePtr[-i] = -i;
    BoundingValuePtr[i] = i;
    BoundingValuePtr[i+FLimit] = FLimit-i;
  }
  pbi->BoundingValuePtr=BoundingValuePtr;
}

/* handle the in-loop filter limit value table */

void WriteFilterTables(PB_INSTANCE *pbi, oggpack_buffer *opb){
  int i;
  int bits=5;
  oggpackB_write(opb, bits, 3);
  for(i=0;i<Q_TABLE_SIZE;i++)
    oggpackB_write(opb, pbi->LoopFilterLimits[i],bits);
}

int ReadFilterTables(codec_setup_info *ci, oggpack_buffer *opb){
  int i;
  int bits, value;

  theora_read(opb, 3, &bits);
  for(i=0;i<Q_TABLE_SIZE;i++){
    theora_read(opb,bits,&value);
    ci->LoopFilterLimitValues[i]=value;
  }
  if(bits<0)return OC_BADHEADER;

  return 0;
}

/* copy in-loop filter limits from the bitstream header into our instance */
void CopyFilterTables(PB_INSTANCE *pbi, codec_setup_info *ci){
  memcpy(pbi->LoopFilterLimits, ci->LoopFilterLimitValues, Q_TABLE_SIZE);
}

/* initialize the filter limits from our static table */
void InitFilterTables(PB_INSTANCE *pbi){
  memcpy(pbi->LoopFilterLimits, LoopFilterLimitValuesV1, Q_TABLE_SIZE);
}

void SetupLoopFilter(PB_INSTANCE *pbi){
  ogg_int32_t FLimit;

  /* nb: this was using the V2 values rather than V1
     we think is was a mistake; the results were not used */
  FLimit = pbi->LoopFilterLimits[pbi->FrameQIndex];
 dsp_funcs.SetupBoundingValueArray(pbi, FLimit);
}

static void ExpandKFBlock ( PB_INSTANCE *pbi, ogg_int32_t FragmentNumber ){
  ogg_uint32_t ReconPixelsPerLine;
  ogg_int32_t     ReconPixelIndex;

  /* Select the appropriate inverse Q matrix and line stride */
  if ( FragmentNumber<(ogg_int32_t)pbi->YPlaneFragments ){
    ReconPixelsPerLine = pbi->YStride;
    pbi->dequant_coeffs = pbi->dequant_Y_coeffs;
  }else if ( FragmentNumber<(ogg_int32_t)(pbi->YPlaneFragments + pbi->UVPlaneFragments) ){
    ReconPixelsPerLine = pbi->UVStride;
    pbi->dequant_coeffs = pbi->dequant_U_coeffs;
  }else{
    ReconPixelsPerLine = pbi->UVStride;
    pbi->dequant_coeffs = pbi->dequant_V_coeffs;
  }

  /* Set up pointer into the quantisation buffer. */
  pbi->quantized_list = &pbi->QFragData[FragmentNumber][0];

  /* Invert quantisation and DCT to get pixel data. */
  switch(pbi->FragCoefEOB[FragmentNumber]){
  case 0:case 1:
    dsp_funcs.IDct1( pbi->quantized_list, pbi->dequant_coeffs, pbi->ReconDataBuffer );
    break;
  case 2: case 3:case 4:case 5:case 6:case 7:case 8: case 9:case 10:
    dsp_funcs.IDct10( pbi->quantized_list, pbi->dequant_coeffs, pbi->ReconDataBuffer );
    break;
  default:
    dsp_funcs.IDctSlow( pbi->quantized_list, pbi->dequant_coeffs, pbi->ReconDataBuffer );
  }

  /* Convert fragment number to a pixel offset in a reconstruction buffer. */
  ReconPixelIndex = pbi->recon_pixel_index_table[FragmentNumber];

  /* Get the pixel index for the first pixel in the fragment. */
  dsp_static_recon_intra8x8 ((unsigned char *)(&pbi->ThisFrameRecon[ReconPixelIndex]),
              (ogg_int16_t *)pbi->ReconDataBuffer, ReconPixelsPerLine);

}

static void ExpandBlock ( PB_INSTANCE *pbi, ogg_int32_t FragmentNumber ){
  unsigned char *LastFrameRecPtr;   /* Pointer into previous frame
				       reconstruction. */
  unsigned char *LastFrameRecPtr2;  /* Pointer into previous frame
				       reconstruction for 1/2 pixel MC. */

  ogg_uint32_t   ReconPixelsPerLine; /* Pixels per line */
  ogg_int32_t    ReconPixelIndex;    /* Offset for block into a
                                        reconstruction buffer */
  ogg_int32_t    ReconPtr2Offset;    /* Offset for second
                                        reconstruction in half pixel
                                        MC */
  ogg_int32_t    MVOffset;           /* Baseline motion vector offset */
  ogg_int32_t    MvShift  ;          /* Shift to correct to 1/2 or 1/4 pixel */
  ogg_int32_t    MvModMask;          /* Mask to determine whether 1/2
                                        pixel is used */

  /* Get coding mode for this block */
  if ( GetFrameType(pbi) == KEY_FRAME ){
    pbi->CodingMode = CODE_INTRA;
  }else{
    /* Get Motion vector and mode for this block. */
    pbi->CodingMode = pbi->FragCodingMethod[FragmentNumber];
  }

  /* Select the appropriate inverse Q matrix and line stride */
  if ( FragmentNumber<(ogg_int32_t)pbi->YPlaneFragments ) {
    ReconPixelsPerLine = pbi->YStride;
    MvShift = 1;
    MvModMask = 0x00000001;

    /* Select appropriate dequantiser matrix. */
    if ( pbi->CodingMode == CODE_INTRA )
      pbi->dequant_coeffs = pbi->dequant_Y_coeffs;
    else
      pbi->dequant_coeffs = pbi->dequant_InterY_coeffs;
  }else{
    ReconPixelsPerLine = pbi->UVStride;
    MvShift = 2;
    MvModMask = 0x00000003;

    /* Select appropriate dequantiser matrix. */
    if ( pbi->CodingMode == CODE_INTRA )
      if ( FragmentNumber <
		(ogg_int32_t)(pbi->YPlaneFragments + pbi->UVPlaneFragments) )
        pbi->dequant_coeffs = pbi->dequant_U_coeffs;
      else
        pbi->dequant_coeffs = pbi->dequant_V_coeffs;
    else
      if ( FragmentNumber <
		(ogg_int32_t)(pbi->YPlaneFragments + pbi->UVPlaneFragments) )
        pbi->dequant_coeffs = pbi->dequant_InterU_coeffs;
    else
        pbi->dequant_coeffs = pbi->dequant_InterV_coeffs;
  }

  /* Set up pointer into the quantisation buffer. */
  pbi->quantized_list = &pbi->QFragData[FragmentNumber][0];

  /* Invert quantisation and DCT to get pixel data. */
  switch(pbi->FragCoefEOB[FragmentNumber]){
  case 0:case 1:
    dsp_funcs.IDct1( pbi->quantized_list, pbi->dequant_coeffs, pbi->ReconDataBuffer );
    break;
  case 2: case 3:case 4:case 5:case 6:case 7:case 8: case 9:case 10:
    dsp_funcs.IDct10( pbi->quantized_list, pbi->dequant_coeffs, pbi->ReconDataBuffer );
    break;
  default:
    dsp_funcs.IDctSlow( pbi->quantized_list, pbi->dequant_coeffs, pbi->ReconDataBuffer );
  }

  /* Convert fragment number to a pixel offset in a reconstruction buffer. */
  ReconPixelIndex = pbi->recon_pixel_index_table[FragmentNumber];

  /* Action depends on decode mode. */
  if ( pbi->CodingMode == CODE_INTER_NO_MV ){
    /* Inter with no motion vector */
    /* Reconstruct the pixel data using the last frame reconstruction
       and change data when the motion vector is (0,0), the recon is
       based on the lastframe without loop filtering---- for testing */
    dsp_static_recon_inter8x8 (&pbi->ThisFrameRecon[ReconPixelIndex],
		&pbi->LastFrameRecon[ReconPixelIndex],
		pbi->ReconDataBuffer, ReconPixelsPerLine );
  }else if ( ModeUsesMC[pbi->CodingMode] ) {
    /* The mode uses a motion vector. */
    /* Get vector from list */
    pbi->MVector.x = pbi->FragMVect[FragmentNumber].x;
    pbi->MVector.y = pbi->FragMVect[FragmentNumber].y;

    /* Work out the base motion vector offset and the 1/2 pixel offset
       if any.  For the U and V planes the MV specifies 1/4 pixel
       accuracy. This is adjusted to 1/2 pixel as follows ( 0->0,
       1/4->1/2, 1/2->1/2, 3/4->1/2 ). */
    MVOffset = 0;
    ReconPtr2Offset = 0;
    if ( pbi->MVector.x > 0 ){
      MVOffset = pbi->MVector.x >> MvShift;
      if ( pbi->MVector.x & MvModMask )
	ReconPtr2Offset += 1;
    } else if ( pbi->MVector.x < 0 ) {
      MVOffset -= (-pbi->MVector.x) >> MvShift;
      if ( (-pbi->MVector.x) & MvModMask )
	ReconPtr2Offset -= 1;
    }

    if ( pbi->MVector.y > 0 ){
      MVOffset += (pbi->MVector.y >>  MvShift) * ReconPixelsPerLine;
      if ( pbi->MVector.y & MvModMask )
	ReconPtr2Offset += ReconPixelsPerLine;
    } else if ( pbi->MVector.y < 0 ){
      MVOffset -= ((-pbi->MVector.y) >> MvShift) * ReconPixelsPerLine;
      if ( (-pbi->MVector.y) & MvModMask )
	ReconPtr2Offset -= ReconPixelsPerLine;
    }

    /* Set up the first of the two reconstruction buffer pointers. */
    if ( pbi->CodingMode==CODE_GOLDEN_MV ) {
      LastFrameRecPtr = &pbi->GoldenFrame[ReconPixelIndex] + MVOffset;
    }else{
      LastFrameRecPtr = &pbi->LastFrameRecon[ReconPixelIndex] + MVOffset;
    }

    /* Set up the second of the two reconstruction pointers. */
    LastFrameRecPtr2 = LastFrameRecPtr + ReconPtr2Offset;

    /* Select the appropriate reconstruction function */
    if ( (int)(LastFrameRecPtr - LastFrameRecPtr2) == 0 ) {
      /* Reconstruct the pixel dats from the reference frame and change data
	 (no half pixel in this case as the two references were the same. */
      dsp_static_recon_inter8x8 (
		  &pbi->ThisFrameRecon[ReconPixelIndex],
		  LastFrameRecPtr, pbi->ReconDataBuffer,
		  ReconPixelsPerLine );
    }else{
      /* Fractional pixel reconstruction. */
      /* Note that we only use two pixels per reconstruction even for
         the diagonal. */
      dsp_static_recon_inter8x8_half(&pbi->ThisFrameRecon[ReconPixelIndex],
			    LastFrameRecPtr, LastFrameRecPtr2,
			    pbi->ReconDataBuffer, ReconPixelsPerLine );
    }
  } else if ( pbi->CodingMode == CODE_USING_GOLDEN ){
    /* Golden frame with motion vector */
    /* Reconstruct the pixel data using the golden frame
       reconstruction and change data */
    dsp_static_recon_inter8x8 (&pbi->ThisFrameRecon[ReconPixelIndex],
		&pbi->GoldenFrame[ ReconPixelIndex ],
		pbi->ReconDataBuffer, ReconPixelsPerLine );
  } else {
    /* Simple Intra coding */
    /* Get the pixel index for the first pixel in the fragment. */
    dsp_static_recon_intra8x8 (&pbi->ThisFrameRecon[ReconPixelIndex],
		pbi->ReconDataBuffer, ReconPixelsPerLine );
  }
}

static void UpdateUMV_HBorders( PB_INSTANCE *pbi,
				unsigned char * DestReconPtr,
				ogg_uint32_t  PlaneFragOffset ) {
  ogg_uint32_t  i;
  ogg_uint32_t  PixelIndex;

  ogg_uint32_t  PlaneStride;
  ogg_uint32_t  BlockVStep;
  ogg_uint32_t  PlaneFragments;
  ogg_uint32_t  LineFragments;
  ogg_uint32_t  PlaneBorderWidth;

  unsigned char   *SrcPtr1;
  unsigned char   *SrcPtr2;
  unsigned char   *DestPtr1;
  unsigned char   *DestPtr2;

  /* Work out various plane specific values */
  if ( PlaneFragOffset == 0 ) {
    /* Y Plane */
    BlockVStep = (pbi->YStride *
		  (VFRAGPIXELS - 1));
    PlaneStride = pbi->YStride;
    PlaneBorderWidth = UMV_BORDER;
    PlaneFragments = pbi->YPlaneFragments;
    LineFragments = pbi->HFragments;
  }else{
    /* U or V plane. */
    BlockVStep = (pbi->UVStride *
		  (VFRAGPIXELS - 1));
    PlaneStride = pbi->UVStride;
    PlaneBorderWidth = UMV_BORDER / 2;
    PlaneFragments = pbi->UVPlaneFragments;
    LineFragments = pbi->HFragments / 2;
  }

  /* Setup the source and destination pointers for the top and bottom
     borders */
  PixelIndex = pbi->recon_pixel_index_table[PlaneFragOffset];
  SrcPtr1 = &DestReconPtr[ PixelIndex - PlaneBorderWidth ];
  DestPtr1 = SrcPtr1 - (PlaneBorderWidth * PlaneStride);

  PixelIndex = pbi->recon_pixel_index_table[PlaneFragOffset +
					   PlaneFragments - LineFragments] +
    BlockVStep;
  SrcPtr2 = &DestReconPtr[ PixelIndex - PlaneBorderWidth];
  DestPtr2 = SrcPtr2 + PlaneStride;

  /* Now copy the top and bottom source lines into each line of the
     respective borders */
  for ( i = 0; i < PlaneBorderWidth; i++ ) {
    memcpy( DestPtr1, SrcPtr1, PlaneStride );
    memcpy( DestPtr2, SrcPtr2, PlaneStride );
    DestPtr1 += PlaneStride;
    DestPtr2 += PlaneStride;
  }
}

static void UpdateUMV_VBorders( PB_INSTANCE *pbi,
				unsigned char * DestReconPtr,
				ogg_uint32_t  PlaneFragOffset ){
  ogg_uint32_t  i;
  ogg_uint32_t  PixelIndex;

  ogg_uint32_t  PlaneStride;
  ogg_uint32_t  LineFragments;
  ogg_uint32_t  PlaneBorderWidth;
  ogg_uint32_t   PlaneHeight;

  unsigned char   *SrcPtr1;
  unsigned char   *SrcPtr2;
  unsigned char   *DestPtr1;
  unsigned char   *DestPtr2;

  /* Work out various plane specific values */
  if ( PlaneFragOffset == 0 ) {
    /* Y Plane */
    PlaneStride = pbi->YStride;
    PlaneBorderWidth = UMV_BORDER;
    LineFragments = pbi->HFragments;
    PlaneHeight = pbi->info.height;
  }else{
    /* U or V plane. */
    PlaneStride = pbi->UVStride;
    PlaneBorderWidth = UMV_BORDER / 2;
    LineFragments = pbi->HFragments / 2;
    PlaneHeight = pbi->info.height / 2;
  }

  /* Setup the source data values and destination pointers for the
     left and right edge borders */
  PixelIndex = pbi->recon_pixel_index_table[PlaneFragOffset];
  SrcPtr1 = &DestReconPtr[ PixelIndex ];
  DestPtr1 = &DestReconPtr[ PixelIndex - PlaneBorderWidth ];

  PixelIndex = pbi->recon_pixel_index_table[PlaneFragOffset +
					   LineFragments - 1] +

⌨️ 快捷键说明

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