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

📄 scan.c

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

#define MAX_SEARCH_LINE_LEN                   7

#define SET8_0(ptr) \
  ((ogg_uint32_t *)ptr)[0] = 0x00000000; \
  ((ogg_uint32_t *)ptr)[1] = 0x00000000;
#define SET8_1(ptr) \
  ((ogg_uint32_t *)ptr)[0] = 0x01010101; \
  ((ogg_uint32_t *)ptr)[1] = 0x01010101;
#define SET8_8(ptr) \
  ((ogg_uint32_t *)ptr)[0] = 0x08080808; \
  ((ogg_uint32_t *)ptr)[1] = 0x08080808;

static ogg_uint32_t LineLengthScores[ MAX_SEARCH_LINE_LEN + 1 ] = {
  0, 0, 0, 0, 2, 4, 12, 24
};

static ogg_uint32_t BodyNeighbourScore = 8;
static double DiffDevisor = 0.0625;
#define HISTORY_BLOCK_FACTOR    2
#define MIN_STEP_THRESH 6
#define SCORE_MULT_LOW    0.5
#define SCORE_MULT_HIGH   4

#define UP      0
#define DOWN    1
#define LEFT    2
#define RIGHT   3

#define INTERNAL_BLOCK_HEIGHT   8
#define INTERNAL_BLOCK_WIDTH    8

#define BLOCK_NOT_CODED                       0
#define BLOCK_CODED_BAR                       3
#define BLOCK_CODED_SGC                       4
#define BLOCK_CODED_LOW                       4
#define BLOCK_CODED                           5

#define CANDIDATE_BLOCK_LOW                  -2
#define CANDIDATE_BLOCK                      -1

#define FIRST_ROW           0
#define NOT_EDGE_ROW        1
#define LAST_ROW            2

#define YDIFF_CB_ROWS                   (INTERNAL_BLOCK_HEIGHT * 3)
#define CHLOCALS_CB_ROWS                (INTERNAL_BLOCK_HEIGHT * 3)
#define PMAP_CB_ROWS                    (INTERNAL_BLOCK_HEIGHT * 3)

void ConfigurePP( PP_INSTANCE *ppi, int Level ) {
  switch ( Level ){
  case 0:
    ppi->SRFGreyThresh = 1;
    ppi->SRFColThresh = 1;
    ppi->NoiseSupLevel = 2;
    ppi->SgcLevelThresh = 1;
    ppi->SuvcLevelThresh = 1;
    ppi->GrpLowSadThresh = 6;
    ppi->GrpHighSadThresh = 24;
    ppi->PrimaryBlockThreshold = 2;
    ppi->SgcThresh = 10;

    ppi->PAKEnabled = 0;
    break;

  case 1:
    ppi->SRFGreyThresh = 2;
    ppi->SRFColThresh = 2;
    ppi->NoiseSupLevel = 2;
    ppi->SgcLevelThresh = 2;
    ppi->SuvcLevelThresh = 2;
    ppi->GrpLowSadThresh = 8;
    ppi->GrpHighSadThresh = 32;
    ppi->PrimaryBlockThreshold = 5;
    ppi->SgcThresh = 12;

    ppi->PAKEnabled = 1;
    break;

  case 2: /* Default VP3 settings */
    ppi->SRFGreyThresh = 3;
    ppi->SRFColThresh = 3;
    ppi->NoiseSupLevel = 2;
    ppi->SgcLevelThresh = 2;
    ppi->SuvcLevelThresh = 2;
    ppi->GrpLowSadThresh = 8;
    ppi->GrpHighSadThresh = 32;
    ppi->PrimaryBlockThreshold = 5;
    ppi->SgcThresh = 16;

    ppi->PAKEnabled = 1;
    break;

  case 3:
    ppi->SRFGreyThresh = 4;
    ppi->SRFColThresh = 4;
    ppi->NoiseSupLevel = 3;
    ppi->SgcLevelThresh = 3;
    ppi->SuvcLevelThresh = 3;
    ppi->GrpLowSadThresh = 10;
    ppi->GrpHighSadThresh = 48;
    ppi->PrimaryBlockThreshold = 5;
    ppi->SgcThresh = 18;

    ppi->PAKEnabled = 1;
    break;

  case 4:
    ppi->SRFGreyThresh = 5;
    ppi->SRFColThresh = 5;
    ppi->NoiseSupLevel = 3;
    ppi->SgcLevelThresh = 4;
    ppi->SuvcLevelThresh = 4;
    ppi->GrpLowSadThresh = 12;
    ppi->GrpHighSadThresh = 48;
    ppi->PrimaryBlockThreshold = 5;
    ppi->SgcThresh = 20;

    ppi->PAKEnabled = 1;
    break;

  case 5:
    ppi->SRFGreyThresh = 6;
    ppi->SRFColThresh = 6;
    ppi->NoiseSupLevel = 3;
    ppi->SgcLevelThresh = 4;
    ppi->SuvcLevelThresh = 4;
    ppi->GrpLowSadThresh = 12;
    ppi->GrpHighSadThresh = 64;
    ppi->PrimaryBlockThreshold = 10;
    ppi->SgcThresh = 24;

    ppi->PAKEnabled = 1;
    break;

  case 6:
    ppi->SRFGreyThresh = 6;
    ppi->SRFColThresh = 7;
    ppi->NoiseSupLevel = 3;
    ppi->SgcLevelThresh = 4;
    ppi->SuvcLevelThresh = 4;
    ppi->GrpLowSadThresh = 12;
    ppi->GrpHighSadThresh = 64;
    ppi->PrimaryBlockThreshold = 10;
    ppi->SgcThresh = 24;

    ppi->PAKEnabled = 1;
    break;

  default:
    ppi->SRFGreyThresh = 3;
    ppi->SRFColThresh = 3;
    ppi->NoiseSupLevel = 2;
    ppi->SgcLevelThresh = 2;
    ppi->SuvcLevelThresh = 2;
    ppi->GrpLowSadThresh = 10;
    ppi->GrpHighSadThresh = 32;
    ppi->PrimaryBlockThreshold = 5;
    ppi->SgcThresh = 16;
    ppi->PAKEnabled = 1;
    break;
  }
}

static void ScanCalcPixelIndexTable(PP_INSTANCE *ppi){
  ogg_uint32_t i;
  ogg_uint32_t * PixelIndexTablePtr = ppi->ScanPixelIndexTable;

  /* If appropriate add on extra inices for U and V planes. */
  for ( i = 0; i < (ppi->ScanYPlaneFragments); i++ ) {
    PixelIndexTablePtr[ i ] =
      ((i / ppi->ScanHFragments) *
       VFRAGPIXELS * ppi->ScanConfig.VideoFrameWidth);
    PixelIndexTablePtr[ i ] +=
      ((i % ppi->ScanHFragments) * HFRAGPIXELS);
  }

  PixelIndexTablePtr = &ppi->ScanPixelIndexTable[ppi->ScanYPlaneFragments];

  for ( i = 0; i < (ppi->ScanUVPlaneFragments * 2); i++ ){
    PixelIndexTablePtr[ i ] =
      ((i / (ppi->ScanHFragments >> 1) ) *
       (VFRAGPIXELS * (ppi->ScanConfig.VideoFrameWidth >> 1)) );
    PixelIndexTablePtr[ i ] +=
      ((i % (ppi->ScanHFragments >> 1) ) *
       HFRAGPIXELS) + ppi->YFramePixels;
    }
}

static void InitScanMapArrays(PP_INSTANCE *ppi){
  int i;
  unsigned char StepThresh;

  /* Clear down the fragment level map arrays for the current frame. */
  memset( ppi->FragScores, 0,
	  ppi->ScanFrameFragments * sizeof(*ppi->FragScores) );
  memset( ppi->SameGreyDirPixels, 0,
	  ppi->ScanFrameFragments );
  memset( ppi->FragDiffPixels, 0,
	  ppi->ScanFrameFragments );
  memset( ppi->RowChangedPixels, 0,
	  3* ppi->ScanConfig.VideoFrameHeight*sizeof(*ppi->RowChangedPixels));

  memset( ppi->ScanDisplayFragments, BLOCK_NOT_CODED, ppi->ScanFrameFragments);

  /* Threshold used in setting up ppi->NoiseScoreBoostTable[] */
  StepThresh = (unsigned int)(ppi->SRFGreyThresh >> 1);
  if ( StepThresh < MIN_STEP_THRESH )
    StepThresh = MIN_STEP_THRESH;
  ppi->SrfThresh = (int)ppi->SRFGreyThresh;

  /* Set up various tables used to tweak pixel score values and
     scoring rules based upon absolute value of a pixel change */
  for ( i = 0; i < 256; i++ ){
    /* Score multiplier table indexed by absolute difference. */
    ppi->AbsDiff_ScoreMultiplierTable[i] = (double)i * DiffDevisor;
    if ( ppi->AbsDiff_ScoreMultiplierTable[i] < SCORE_MULT_LOW )
      ppi->AbsDiff_ScoreMultiplierTable[i] = SCORE_MULT_LOW;
    else if ( ppi->AbsDiff_ScoreMultiplierTable[i] > SCORE_MULT_HIGH)
      ppi->AbsDiff_ScoreMultiplierTable[i] = SCORE_MULT_HIGH;

    /* Table that facilitates a relaxation of the changed locals rules
       in NoiseScoreRow() for pixels that have changed by a large
       amount. */
    if ( i < (ppi->SrfThresh + StepThresh) )
      ppi->NoiseScoreBoostTable[i] = 0;
    else if ( i < (ppi->SrfThresh + (StepThresh * 4)) )
      ppi->NoiseScoreBoostTable[i] = 1;
    else if ( i < (ppi->SrfThresh + (StepThresh * 6)) )
      ppi->NoiseScoreBoostTable[i] = 2;
    else
      ppi->NoiseScoreBoostTable[i] = 3;

  }

  /* Set various other threshold parameters. */

  /* Set variables that control access to the line search algorithms. */
  ppi->LineSearchTripTresh = 16;
  if ( ppi->LineSearchTripTresh > ppi->PrimaryBlockThreshold )
    ppi->LineSearchTripTresh = (unsigned int)(ppi->PrimaryBlockThreshold + 1);

  /* Adjust line search length if block threshold low */
  ppi->MaxLineSearchLen = MAX_SEARCH_LINE_LEN;
  while ( (ppi->MaxLineSearchLen > 0) &&
	  (LineLengthScores[ppi->MaxLineSearchLen-1] >
	   ppi->PrimaryBlockThreshold) )
    ppi->MaxLineSearchLen -= 1;

}

void ScanYUVInit( PP_INSTANCE *  ppi, SCAN_CONFIG_DATA * ScanConfigPtr){
  int i;

  /* Set up the various imported data structure pointers. */
  ppi->ScanConfig.Yuv0ptr = ScanConfigPtr->Yuv0ptr;
  ppi->ScanConfig.Yuv1ptr = ScanConfigPtr->Yuv1ptr;
  ppi->ScanConfig.SrfWorkSpcPtr = ScanConfigPtr->SrfWorkSpcPtr;
  ppi->ScanConfig.disp_fragments = ScanConfigPtr->disp_fragments;

  ppi->ScanConfig.RegionIndex = ScanConfigPtr->RegionIndex;

  ppi->ScanConfig.VideoFrameWidth = ScanConfigPtr->VideoFrameWidth;
  ppi->ScanConfig.VideoFrameHeight = ScanConfigPtr->VideoFrameHeight;

  /* UV plane sizes. */
  ppi->VideoUVPlaneWidth = ScanConfigPtr->VideoFrameWidth / 2;
  ppi->VideoUVPlaneHeight = ScanConfigPtr->VideoFrameHeight / 2;

  /* Note the size of each plane in pixels. */
  ppi->YFramePixels = ppi->ScanConfig.VideoFrameWidth *
    ppi->ScanConfig.VideoFrameHeight;
  ppi->UVFramePixels = ppi->VideoUVPlaneWidth * ppi->VideoUVPlaneHeight;

  /* Work out various fragment related values. */
  ppi->ScanYPlaneFragments = ppi->YFramePixels /
    (HFRAGPIXELS * VFRAGPIXELS);
  ppi->ScanUVPlaneFragments = ppi->UVFramePixels /
    (HFRAGPIXELS * VFRAGPIXELS);;
  ppi->ScanHFragments = ppi->ScanConfig.VideoFrameWidth / HFRAGPIXELS;
  ppi->ScanVFragments = ppi->ScanConfig.VideoFrameHeight / VFRAGPIXELS;
  ppi->ScanFrameFragments = ppi->ScanYPlaneFragments +
    (2 * ppi->ScanUVPlaneFragments);

  PInitFrameInfo(ppi);

  /* Set up the scan pixel index table. */
  ScanCalcPixelIndexTable(ppi);

  /* Initialise the previous frame block history lists */
  for ( i = 0; i < MAX_PREV_FRAMES; i++ )
    memset( ppi->PrevFragments[i], BLOCK_NOT_CODED, ppi->ScanFrameFragments);

  /* YUVAnalyseFrame() is not called for the first frame in a sequence
     (a key frame obviously).  This memset insures that for the second
     frame all blocks are marked for coding in line with the behaviour
     for other key frames. */
  memset( ppi->PrevFragments[ppi->PrevFrameLimit-1],
	  BLOCK_CODED, ppi->ScanFrameFragments );

  /* Initialise scan arrays */
  InitScanMapArrays(ppi);
}

static void SetFromPrevious(PP_INSTANCE *ppi) {
  unsigned int  i,j;

  /* We buld up the list of previously updated blocks in the zero
     index list of PrevFragments[] so we must start by reseting its
     contents */
  memset( ppi->PrevFragments[0], BLOCK_NOT_CODED, ppi->ScanFrameFragments );

  if ( ppi->PrevFrameLimit > 1 ){
    /* Now build up PrevFragments[0] from PrevFragments[1 to PrevFrameLimit] */
    for ( i = 0; i < ppi->ScanFrameFragments; i++ ){
      for ( j = 1; j < ppi->PrevFrameLimit; j++ ){
	if ( ppi->PrevFragments[j][i] > BLOCK_CODED_BAR ){
	  ppi->PrevFragments[0][i] = BLOCK_CODED;
	  break;
	}
      }
    }
  }
}

static void UpdatePreviousBlockLists(PP_INSTANCE *ppi) {
  int  i;

  /* Shift previous frame block lists along. */
  for ( i = ppi->PrevFrameLimit; i > 1; i-- ){
    memcpy( ppi->PrevFragments[i], ppi->PrevFragments[i-1],
	    ppi->ScanFrameFragments );
  }

  /* Now copy in this frames block list */
  memcpy( ppi->PrevFragments[1], ppi->ScanDisplayFragments,
	  ppi->ScanFrameFragments );
}

static void CreateOutputDisplayMap( PP_INSTANCE *ppi,
				    char *InternalFragmentsPtr,
				    char *RecentHistoryPtr,
				    unsigned char *ExternalFragmentsPtr ) {
  ogg_uint32_t i;
  ogg_uint32_t HistoryBlocksAdded = 0;
  ogg_uint32_t YBand =  (ppi->ScanYPlaneFragments/8);   /* 1/8th of Y image. */

  ppi->OutputBlocksUpdated = 0;
  for ( i = 0; i < ppi->ScanFrameFragments; i++ ) {
    if ( InternalFragmentsPtr[i] > BLOCK_NOT_CODED ) {
      ppi->OutputBlocksUpdated ++;
      ExternalFragmentsPtr[i] = 1;
    }else if ( RecentHistoryPtr[i] == BLOCK_CODED ){
      HistoryBlocksAdded ++;
      ExternalFragmentsPtr[i] = 1;
    }else{
      ExternalFragmentsPtr[i] = 0;
    }
  }

  /* Add in a weighting for the history blocks that have been added */
  ppi->OutputBlocksUpdated += (HistoryBlocksAdded / HISTORY_BLOCK_FACTOR);

  /* Now calculate a key frame candidate indicator.  This is based
     upon Y data only and ignores the top and bottom 1/8 of the
     image.  Also ignore history blocks and BAR blocks. */
  ppi->KFIndicator = 0;
  for ( i = YBand; i < (ppi->ScanYPlaneFragments - YBand); i++ )
    if ( InternalFragmentsPtr[i] > BLOCK_CODED_BAR )
      ppi->KFIndicator ++;

  /* Convert the KF score to a range 0-100 */
  ppi->KFIndicator = ((ppi->KFIndicator*100)/((ppi->ScanYPlaneFragments*3)/4));
}

static int RowSadScan( PP_INSTANCE *ppi,
		       unsigned char * YuvPtr1,
		       unsigned char * YuvPtr2,
		       signed char *  DispFragPtr){
  ogg_int32_t    i, j;
  ogg_uint32_t   GrpSad;

⌨️ 快捷键说明

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