📄 scan.c
字号:
/******************************************************************** * * * 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: last mod: $Id: scan.c 11442 2006-05-27 17:28:08Z giles $ ********************************************************************/#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, signed char *InternalFragmentsPtr, signed 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 ){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -