cscanyuv.c 86 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750
  1. /****************************************************************************
  2. *
  3. * Module Title : SCAN_YUV
  4. *
  5. * Description : Content analysis and scoring functions for YUV 411. .
  6. *
  7. * AUTHOR : Paul Wilkins
  8. *
  9. *****************************************************************************
  10. * Revision History
  11. *
  12. * 1.12 PGW 27 Apr 01 Changes to use last frame coded list passed in from codec.
  13. * 1.11 PGW 28 Feb 01 Removal of requirement for a seperate pre-processor output buffer.
  14. * 1.10 PGW 04 Oct 00 Bug fixes to SadPass2() and changes to how it is called.
  15. * Changes to ConsolidateDiffScanResults()
  16. * 1.09 PGW 29 Aug 00 Correction to defaults in SetVcapLevelOffset()
  17. * 1.08 JBB 03 Aug 00 Cleaned up a bit (memset full buffer)
  18. * Fixed Problem with Pak Filter wrapping over edges
  19. * 1.07 PGW 24 Jul 00 Added column scan funtion. Experiment with PAK off.
  20. * Tweaks to filter thresholds.
  21. * 1.06 PGW 10 Jul 00 Changes to RowDiffScan() to reduce number of conditionals.
  22. * 1.05 PGW 22/06/00 Filtering threshold tweaks.
  23. * 1.04 JBB 30/05/00 Removed hard coded size limits
  24. * 1.03 YX 13/04/00 Comment out some if() testings
  25. * 1.02 PGW 16/03/00 Changes to SetVcapLevelOffset() to provide
  26. * various pre-set filter levels.
  27. * 1.01 PGW 12/07/99 Changes to reduce uneccessary dependancies.
  28. * 1.00 PGW 14/06/99 Configuration baseline
  29. *
  30. *****************************************************************************
  31. */
  32. /****************************************************************************
  33. * Header Frames
  34. *****************************************************************************
  35. */
  36. #define STRICT /* Strict type checking. */
  37. #include <stdio.h>
  38. #include <string.h>
  39. #include <math.h>
  40. #include "preproc.h"
  41. /****************************************************************************
  42. * Module constants.
  43. *****************************************************************************
  44. */
  45. #define MIN_STEP_THRESH 6
  46. #define SCORE_MULT_LOW 0.5
  47. #define SCORE_MULT_MEDIUM 2.0
  48. #define SCORE_MULT_HIGH 4
  49. /****************************************************************************
  50. * Explicit Imports
  51. *****************************************************************************
  52. */
  53. extern void ClearMmxState(PP_INSTANCE *ppi);
  54. /****************************************************************************
  55. * Exported Global Variables
  56. *****************************************************************************
  57. */
  58. UINT32 LineLengthScores[ MAX_SEARCH_LINE_LEN + 1 ] = { 0, 0, 0, 0, 2, 4, 12, 24 };
  59. UINT32 BodyNeighbourScore = 8;
  60. double DiffDevisor = 0.0625; // 1/16
  61. UINT8 LineSearchTripTresh = 16;
  62. double LowVarianceThresh = 200.0;
  63. /****************************************************************************
  64. * Foreward References
  65. *****************************************************************************
  66. */
  67. BOOL RowSadScan( PP_INSTANCE *ppi, UINT8 * YuvPtr1, UINT8 * YuvPtr2, INT8 * DispFragPtr );
  68. BOOL ColSadScan( PP_INSTANCE *ppi, UINT8 * YuvPtr1, UINT8 * YuvPtr2, INT8 * DispFragPtr );
  69. void RowDiffScan( PP_INSTANCE *ppi, UINT8 * YuvPtr1, UINT8 * YuvPtr2,
  70. INT16 * YUVDiffPtr, UINT8 * bits_map_ptr,
  71. INT8 * SgcPtr, INT8 * DispFragPtr,
  72. UINT8 * FDiffPixels, INT32 * RowDiffsPtr,
  73. UINT8 * ChLocalsPtr, BOOL EdgeRow );
  74. void SadPass2( PP_INSTANCE *ppi, INT32 RowNumber, INT8 * DispFragPtr );
  75. void ConsolidateDiffScanResults( PP_INSTANCE *ppi, UINT8 * FDiffPixels, INT8 * SgcScores, INT8 * DispFragPtr1 );
  76. void RowChangedLocalsScan( PP_INSTANCE *ppi, UINT8 * PixelMapPtr, UINT8 * ChLocalsPtr, INT8 * DispFragPtr,
  77. UINT8 RowType );
  78. void NoiseScoreRow( PP_INSTANCE *ppi, UINT8 * PixelMapPtr, UINT8 * ChLocalsPtr,
  79. INT16 * YUVDiffsPtr,
  80. UINT8 * PixelNoiseScorePtr,
  81. UINT32 * FragScorePtr,
  82. INT8 * DispFragPtr,
  83. INT32 * RowDiffsPtr );
  84. void PrimaryEdgeScoreRow( PP_INSTANCE *ppi,
  85. UINT8 * ChangedLocalsPtr, INT16 * YUVDiffsPtr,
  86. UINT8 * PixelNoiseScorePtr,
  87. UINT32 * FragScorePtr,
  88. INT8 * DispFragPtr,
  89. UINT8 RowType );
  90. void LineSearchScoreRow( PP_INSTANCE *ppi,
  91. UINT8 * ChangedLocalsPtr, INT16 * YUVDiffsPtr,
  92. UINT8 * PixelNoiseScorePtr,
  93. UINT32 * FragScorePtr,
  94. INT8 * DispFragPtr,
  95. INT32 RowNumber );
  96. UINT8 LineSearchScorePixel( PP_INSTANCE *ppi, UINT8 * ChangedLocalsPtr, INT32 RowNumber, INT32 ColNumber );
  97. void PixelLineSearch( PP_INSTANCE *ppi, UINT8 * ChangedLocalsPtr, INT32 RowNumber, INT32 ColNumber, UINT8 direction, UINT32 * line_length );
  98. double GetLocalVarianceMultiplier( PP_INSTANCE *ppi, INT16 * YUVDiffPtr, UINT32 PlaneLineLength );
  99. //void RowCopy( PP_INSTANCE *ppi, UINT32 BlockMapIndex );
  100. UINT8 ApplyPakLowPass( PP_INSTANCE *ppi, UINT8 * SrcPtr );
  101. /****************************************************************************
  102. * Module Statics
  103. *****************************************************************************
  104. */
  105. /****************************************************************************
  106. *
  107. * ROUTINE : InitScanMapArrays
  108. *
  109. * INPUTS : None.
  110. *
  111. * OUTPUTS : None.
  112. *
  113. * RETURNS : None.
  114. *
  115. * FUNCTION : Initialise the display and score maps
  116. *
  117. * SPECIAL NOTES : None.
  118. *
  119. *
  120. * ERRORS : None.
  121. *
  122. ****************************************************************************/
  123. void InitScanMapArrays(PP_INSTANCE *ppi)
  124. {
  125. INT32 i;
  126. UINT8 StepThresh;
  127. /* Clear down the fragment level map arrays for the current frame. */
  128. memset( ppi->FragScores, 0, ppi->ScanFrameFragments * sizeof(UINT32) );
  129. memset( ppi->SameGreyDirPixels, 0, ppi->ScanFrameFragments );
  130. memset( ppi->FragDiffPixels, 0, ppi->ScanFrameFragments );
  131. memset( (void *)ppi->RowChangedPixels, 0, 3* ppi->ScanConfig.VideoFrameHeight * sizeof(INT32) );
  132. // Clear down blocks coded worspace.
  133. memset( ppi->ScanDisplayFragments, BLOCK_NOT_CODED, ppi->ScanFrameFragments );
  134. // Threshold used in setting up ppi->NoiseScoreBoostTable[]
  135. StepThresh = (UINT8)(ppi->SRFGreyThresh >> 1);
  136. if ( StepThresh < MIN_STEP_THRESH )
  137. StepThresh = MIN_STEP_THRESH;
  138. ppi->SrfThresh = (int)ppi->SRFGreyThresh;
  139. // Set up various tables used to tweak pixel score values and scoring rules
  140. // based upon absolute value of a pixel change
  141. for ( i = 0; i < 256; i++ )
  142. {
  143. // Score multiplier table indexed by absolute difference.
  144. ppi->AbsDiff_ScoreMultiplierTable[i] = (double)i * DiffDevisor;
  145. if ( ppi->AbsDiff_ScoreMultiplierTable[i] < SCORE_MULT_LOW )
  146. ppi->AbsDiff_ScoreMultiplierTable[i] = SCORE_MULT_LOW;
  147. else if ( ppi->AbsDiff_ScoreMultiplierTable[i] > SCORE_MULT_HIGH )
  148. ppi->AbsDiff_ScoreMultiplierTable[i] = SCORE_MULT_HIGH;
  149. // Table that facilitates a relaxation of the changed locals rules in
  150. // NoiseScoreRow() for pixels that have changed by a large amount.
  151. if ( i < (ppi->SrfThresh + StepThresh) )
  152. ppi->NoiseScoreBoostTable[i] = 0;
  153. else if ( i < (ppi->SrfThresh + (StepThresh * 4)) )
  154. ppi->NoiseScoreBoostTable[i] = 1;
  155. else if ( i < (ppi->SrfThresh + (StepThresh * 6)) )
  156. ppi->NoiseScoreBoostTable[i] = 2;
  157. else
  158. ppi->NoiseScoreBoostTable[i] = 3;
  159. }
  160. // Set various other threshold parameters.
  161. // Set variables that control access to the line search algorithms.
  162. LineSearchTripTresh = 16;
  163. if ( LineSearchTripTresh > ppi->PrimaryBlockThreshold )
  164. LineSearchTripTresh = (UINT8)(ppi->PrimaryBlockThreshold + 1);
  165. // Adjust line search length if block threshold low
  166. ppi->MaxLineSearchLen = MAX_SEARCH_LINE_LEN;
  167. while ( (ppi->MaxLineSearchLen > 0) && (LineLengthScores[ppi->MaxLineSearchLen-1] > ppi->PrimaryBlockThreshold) )
  168. ppi->MaxLineSearchLen -= 1;
  169. // Initialise the level, srf and PAK threshold table pointers..
  170. ppi->SrfThreshTablePtr = &(ppi->SrfThreshTable[255]);
  171. ppi->SgcThreshTablePtr = &(ppi->SgcThreshTable[255]);
  172. ppi->SrfPakThreshTablePtr = &(ppi->SrfPakThreshTable[255]);
  173. }
  174. /****************************************************************************
  175. *
  176. * ROUTINE : AnalysePlane
  177. *
  178. * INPUTS : PlanePtr0/1 Pointers to the first pixel in the plane
  179. * for source and reference images
  180. * FragArrayOffset Start offset in fragment arrays.
  181. * PWidth Width of an image plane in pixels.
  182. * PHeight Height of image plane in pixels
  183. * PStride Plane stride (the number to be added to
  184. * a pixel index to get to the corresponding
  185. * pixel in the next line (can be different
  186. * from PWidth))
  187. * OUTPUTS : None.
  188. *
  189. * RETURNS : None.
  190. *
  191. * FUNCTION : Analyses and filters the image plane defined by the inputs.
  192. *
  193. * SPECIAL NOTES : None.
  194. *
  195. *
  196. * ERRORS : None.
  197. *
  198. ****************************************************************************/
  199. void AnalysePlane( PP_INSTANCE *ppi, UINT8 * PlanePtr0, UINT8 * PlanePtr1, UINT32 FragArrayOffset, UINT32 PWidth, UINT32 PHeight, UINT32 PStride )
  200. {
  201. UINT8 * RawPlanePtr0;
  202. UINT8 * RawPlanePtr1;
  203. INT16 * YUVDiffsPtr;
  204. INT16 * YUVDiffsPtr1;
  205. INT16 * YUVDiffsPtr2;
  206. UINT32 FragIndex;
  207. UINT32 ScoreFragIndex1;
  208. UINT32 ScoreFragIndex2;
  209. UINT32 ScoreFragIndex3;
  210. UINT32 ScoreFragIndex4;
  211. BOOL UpdatedOrCandidateBlocks = FALSE;
  212. UINT8 * ChLocalsPtr0;
  213. UINT8 * ChLocalsPtr1;
  214. UINT8 * ChLocalsPtr2;
  215. UINT8 * PixelsChangedPtr0;
  216. UINT8 * PixelsChangedPtr1;
  217. UINT8 * PixelScoresPtr1;
  218. UINT8 * PixelScoresPtr2;
  219. // UINT8 * PixelScoresPtr4;
  220. INT8 * DispFragPtr0;
  221. INT8 * DispFragPtr1;
  222. INT8 * DispFragPtr2;
  223. UINT32 * FragScoresPtr1;
  224. UINT32 * FragScoresPtr2;
  225. INT32 * RowDiffsPtr;
  226. INT32 * RowDiffsPtr1;
  227. INT32 * RowDiffsPtr2;
  228. INT32 i,j;
  229. INT32 RowNumber1;
  230. INT32 RowNumber2;
  231. INT32 RowNumber3;
  232. INT32 RowNumber4;
  233. BOOL EdgeRow;
  234. INT32 LineSearchRowNumber = 0;
  235. // Variables used as temporary stores for frequently used values.
  236. INT32 Row0Mod3;
  237. INT32 Row1Mod3;
  238. INT32 Row2Mod3;
  239. INT32 BlockRowPixels;
  240. /* Set pixel difference threshold */
  241. if ( FragArrayOffset == 0 )
  242. {
  243. /* Luminance */
  244. ppi->LevelThresh = (int)ppi->SgcLevelThresh;
  245. ppi->NegLevelThresh = -ppi->LevelThresh;
  246. ppi->SrfThresh = (int)ppi->SRFGreyThresh;
  247. ppi->NegSrfThresh = -ppi->SrfThresh;
  248. // Scores correction for Y pixels.
  249. ppi->YUVPlaneCorrectionFactor = 1.0;
  250. ppi->BlockThreshold = ppi->PrimaryBlockThreshold;
  251. ppi->BlockSgcThresh = ppi->SgcThresh;
  252. }
  253. else
  254. {
  255. /* Chrominance */
  256. ppi->LevelThresh = (int)ppi->SuvcLevelThresh;
  257. ppi->NegLevelThresh = -ppi->LevelThresh;
  258. ppi->SrfThresh = (int)ppi->SRFColThresh;
  259. ppi->NegSrfThresh = -ppi->SrfThresh;
  260. // Scores correction for UV pixels.
  261. ppi->YUVPlaneCorrectionFactor = 1.5;
  262. // Block threholds different for subsampled U and V blocks
  263. ppi->BlockThreshold = (UINT32)(ppi->PrimaryBlockThreshold / ppi->UVBlockThreshCorrection);
  264. ppi->BlockSgcThresh = (UINT32)(ppi->SgcThresh / ppi->UVSgcCorrection);
  265. }
  266. // Initialise the SRF thresh table and pointer.
  267. memset( ppi->SrfThreshTable, 1, 512 );
  268. for ( i = ppi->NegSrfThresh; i <= ppi->SrfThresh; i++ )
  269. {
  270. ppi->SrfThreshTablePtr[i] = 0;
  271. }
  272. // Initialise the PAK thresh table.
  273. for ( i = -255; i <= 255; i++ )
  274. {
  275. if ( ppi->SrfThreshTablePtr[i] && (i <= ppi->HighChange) && (i >= ppi->NegHighChange) )
  276. ppi->SrfPakThreshTablePtr[i] = 1;
  277. else
  278. ppi->SrfPakThreshTablePtr[i] = 0;
  279. }
  280. // Initialise the SGc lookup table
  281. for ( i = -255; i <= 255; i++ )
  282. {
  283. if ( i <= ppi->NegLevelThresh )
  284. ppi->SgcThreshTablePtr[i] = -1;
  285. else if ( i >= ppi->LevelThresh )
  286. ppi->SgcThreshTablePtr[i] = 1;
  287. else
  288. ppi->SgcThreshTablePtr[i] = 0;
  289. }
  290. // Set up plane dimension variables
  291. ppi->PlaneHFragments = PWidth / ppi->HFragPixels;
  292. ppi->PlaneVFragments = PHeight / ppi->VFragPixels;
  293. ppi->PlaneWidth = PWidth;
  294. ppi->PlaneHeight = PHeight;
  295. ppi->PlaneStride = PStride;
  296. // Set up local pointers into the raw image data.
  297. RawPlanePtr0 = (UINT8 *)PlanePtr0;
  298. RawPlanePtr1 = (UINT8 *)PlanePtr1;
  299. // Note size and endo points for circular buffers.
  300. ppi->YuvDiffsCircularBufferSize = YDIFF_CB_ROWS * ppi->PlaneWidth;
  301. ppi->ChLocalsCircularBufferSize = CHLOCALS_CB_ROWS * ppi->PlaneWidth;
  302. ppi->PixelMapCircularBufferSize = PMAP_CB_ROWS * ppi->PlaneWidth;
  303. // Set high change thresh where PAK not needed;
  304. ppi->HighChange = ppi->SrfThresh * 4;
  305. ppi->NegHighChange = -ppi->HighChange;
  306. // Set up row difference pointers.
  307. RowDiffsPtr = ppi->RowChangedPixels;
  308. RowDiffsPtr1 = ppi->RowChangedPixels;
  309. RowDiffsPtr2 = ppi->RowChangedPixels;
  310. BlockRowPixels = ppi->PlaneWidth * ppi->VFragPixels;
  311. for ( i = 0; i < (ppi->PlaneVFragments + 4); i++ )
  312. {
  313. RowNumber1 = (i - 1);
  314. RowNumber2 = (i - 2);
  315. RowNumber3 = (i - 3);
  316. RowNumber4 = (i - 4);
  317. // Pre calculate some frequently used values
  318. Row0Mod3 = i % 3;
  319. Row1Mod3 = RowNumber1 % 3;
  320. Row2Mod3 = RowNumber2 % 3;
  321. // For row diff scan last two iterations are invalid
  322. if ( i < ppi->PlaneVFragments )
  323. {
  324. FragIndex = (i * ppi->PlaneHFragments) + FragArrayOffset;
  325. YUVDiffsPtr = &ppi->yuv_differences[Row0Mod3 * BlockRowPixels];
  326. PixelsChangedPtr0 = (UINT8 *)(&ppi->PixelChangedMap[Row0Mod3 * BlockRowPixels]);
  327. DispFragPtr0 = &ppi->ScanDisplayFragments[FragIndex];
  328. ChLocalsPtr0 = (UINT8 *)(&ppi->ChLocals[Row0Mod3 * BlockRowPixels]);
  329. }
  330. // Set up the changed locals pointer to trail behind by one row of fragments.
  331. if ( i > 0 )
  332. {
  333. // For last iteration the ch locals and noise scans are invalid
  334. if ( RowNumber1 < ppi->PlaneVFragments )
  335. {
  336. ScoreFragIndex1 = (RowNumber1 * ppi->PlaneHFragments) + FragArrayOffset;
  337. ChLocalsPtr1 = (UINT8 *)(&ppi->ChLocals[Row1Mod3 * BlockRowPixels]);
  338. PixelsChangedPtr1 = (UINT8 *)(&ppi->PixelChangedMap[(Row1Mod3) * BlockRowPixels]);
  339. PixelScoresPtr1 = &ppi->PixelScores[(RowNumber1 % 4) * BlockRowPixels];
  340. YUVDiffsPtr1 = &ppi->yuv_differences[Row1Mod3 * BlockRowPixels];
  341. FragScoresPtr1 = &ppi->FragScores[ScoreFragIndex1];
  342. DispFragPtr1 = &ppi->ScanDisplayFragments[ScoreFragIndex1];
  343. }
  344. if ( RowNumber2 >= 0 )
  345. {
  346. ScoreFragIndex2 = (RowNumber2 * ppi->PlaneHFragments) + FragArrayOffset;
  347. ChLocalsPtr2 = (UINT8 *)(&ppi->ChLocals[Row2Mod3 * BlockRowPixels]);
  348. YUVDiffsPtr2 = &ppi->yuv_differences[Row2Mod3 * BlockRowPixels];
  349. PixelScoresPtr2 = &ppi->PixelScores[(RowNumber2 % 4) * BlockRowPixels];
  350. FragScoresPtr2 = &ppi->FragScores[ScoreFragIndex2];
  351. DispFragPtr2 = &ppi->ScanDisplayFragments[ScoreFragIndex2];
  352. }
  353. else
  354. {
  355. ChLocalsPtr2 = NULL;
  356. }
  357. }
  358. else
  359. {
  360. ChLocalsPtr1 = NULL;
  361. ChLocalsPtr2 = NULL;
  362. }
  363. // Fast break out test for obvious yes and no cases in this row of blocks
  364. if ( i < ppi->PlaneVFragments )
  365. {
  366. UpdatedOrCandidateBlocks = RowSadScan( ppi, RawPlanePtr0, RawPlanePtr1, DispFragPtr0 );
  367. if( ColSadScan( ppi, RawPlanePtr0, RawPlanePtr1, DispFragPtr0 ) )
  368. UpdatedOrCandidateBlocks = TRUE;
  369. // SadPass2( ppi, i, DispFragPtr0 );
  370. }
  371. else // ????? Not needed now as we always do RowSadScan etc.
  372. {
  373. // Make sure we still call other functions if RowSadScan() etc. disabled
  374. UpdatedOrCandidateBlocks = TRUE;
  375. }
  376. // Consolidation and fast break ot tests at Row 1 level
  377. if ( (i > 0) && (RowNumber1 < ppi->PlaneVFragments) )
  378. {
  379. // Mark as coded any candidate block that lies adjacent to a coded block.
  380. SadPass2( ppi, RowNumber1, DispFragPtr1 );
  381. // Check results of diff scan in last set of blocks.
  382. // Eliminate NO cases and add in +SGC cases
  383. ConsolidateDiffScanResults( ppi, &ppi->FragDiffPixels[ScoreFragIndex1], &ppi->SameGreyDirPixels[ScoreFragIndex1], DispFragPtr1 );
  384. }
  385. for ( j = 0; j < ppi->VFragPixels; j++ )
  386. {
  387. // Last two iterations do not apply
  388. if ( i < ppi->PlaneVFragments )
  389. {
  390. /* Is the current fragment at an edge. */
  391. EdgeRow = ( ( (i == 0) && (j == 0) ) ||
  392. ( (i == (ppi->PlaneVFragments - 1)) && (j == (ppi->VFragPixels - 1)) ) );
  393. // Clear the arrays that will be used for the changed pixels maps
  394. memset( PixelsChangedPtr0, 0, ppi->PlaneWidth );
  395. // Difference scan and map each row
  396. if ( UpdatedOrCandidateBlocks )
  397. {
  398. // Scan the row for interesting differences
  399. // Also clear the array that will be used for changed locals map
  400. RowDiffScan( ppi, RawPlanePtr0, RawPlanePtr1,
  401. YUVDiffsPtr, PixelsChangedPtr0,
  402. &ppi->SameGreyDirPixels[FragIndex],
  403. DispFragPtr0, &ppi->FragDiffPixels[FragIndex],
  404. RowDiffsPtr, ChLocalsPtr0, EdgeRow);
  405. }
  406. else
  407. {
  408. // Clear the array that will be used for changed locals map
  409. memset( ChLocalsPtr0, 0, ppi->PlaneWidth );
  410. }
  411. // The actual image plane pointers must be incremented by stride as this may be
  412. // different (more) than the plane width. Our own internal buffers use ppi->PlaneWidth.
  413. RawPlanePtr0 += ppi->PlaneStride;
  414. RawPlanePtr1 += ppi->PlaneStride;
  415. PixelsChangedPtr0 += ppi->PlaneWidth;
  416. ChLocalsPtr0 += ppi->PlaneWidth;
  417. YUVDiffsPtr += ppi->PlaneWidth;
  418. RowDiffsPtr++;
  419. }
  420. // Run behind calculating the changed locals data and noise scores.
  421. if ( ChLocalsPtr1 != NULL )
  422. {
  423. // Last few iterations do not apply
  424. if ( RowNumber1 < ppi->PlaneVFragments )
  425. {
  426. // Blank the next row in the pixel scores data structure.
  427. memset( PixelScoresPtr1, 0, ppi->PlaneWidth );
  428. // Don't bother doing anything if there are no changed pixels in this row
  429. if ( *RowDiffsPtr1 )
  430. {
  431. // Last valid row is a special case
  432. if ( i < ppi->PlaneVFragments )
  433. RowChangedLocalsScan( ppi, PixelsChangedPtr1, ChLocalsPtr1, DispFragPtr1, (UINT8)( (((i-1)==0) && (j==0)) ? FIRST_ROW : NOT_EDGE_ROW) );
  434. else
  435. RowChangedLocalsScan( ppi, PixelsChangedPtr1, ChLocalsPtr1, DispFragPtr1, (UINT8)((j==(ppi->VFragPixels-1)) ? LAST_ROW : NOT_EDGE_ROW) );
  436. NoiseScoreRow( ppi, PixelsChangedPtr1, ChLocalsPtr1, YUVDiffsPtr1,
  437. PixelScoresPtr1, FragScoresPtr1, DispFragPtr1, RowDiffsPtr1 );
  438. }
  439. ChLocalsPtr1 += ppi->PlaneWidth;
  440. PixelsChangedPtr1 += ppi->PlaneWidth;
  441. YUVDiffsPtr1 += ppi->PlaneWidth;
  442. PixelScoresPtr1 += ppi->PlaneWidth;
  443. RowDiffsPtr1 ++;
  444. }
  445. // Run edge enhancement algorithms
  446. if ( RowNumber2 < ppi->PlaneVFragments )
  447. {
  448. if ( ChLocalsPtr2 != NULL )
  449. {
  450. // Don't bother doing anything if there are no changed pixels in this row
  451. if ( *RowDiffsPtr2 )
  452. {
  453. if ( RowNumber1 < ppi->PlaneVFragments )
  454. {
  455. PrimaryEdgeScoreRow( ppi, ChLocalsPtr2, YUVDiffsPtr2,
  456. PixelScoresPtr2, FragScoresPtr2, DispFragPtr2,
  457. (UINT8)( (((i-2)==0) && (j==0)) ? FIRST_ROW : NOT_EDGE_ROW) );
  458. }
  459. else
  460. {
  461. // Edge enhancement
  462. PrimaryEdgeScoreRow( ppi, ChLocalsPtr2, YUVDiffsPtr2,
  463. PixelScoresPtr2, FragScoresPtr2, DispFragPtr2,
  464. (UINT8)((j==(ppi->VFragPixels-1)) ? LAST_ROW : NOT_EDGE_ROW) );
  465. }
  466. // Recursive line search
  467. LineSearchScoreRow( ppi, ChLocalsPtr2, YUVDiffsPtr2,
  468. PixelScoresPtr2, FragScoresPtr2, DispFragPtr2,
  469. LineSearchRowNumber );
  470. }
  471. ChLocalsPtr2 += ppi->PlaneWidth;
  472. YUVDiffsPtr2 += ppi->PlaneWidth;
  473. PixelScoresPtr2 += ppi->PlaneWidth;
  474. LineSearchRowNumber += 1;
  475. RowDiffsPtr2 ++;
  476. }
  477. }
  478. }
  479. }
  480. // BAR algorithm
  481. if ( (RowNumber3 >= 0) && (RowNumber3 < ppi->PlaneVFragments) )
  482. {
  483. ScoreFragIndex3 = (RowNumber3 * ppi->PlaneHFragments) + FragArrayOffset;
  484. RowBarEnhBlockMap(ppi, &ppi->FragScores[ScoreFragIndex3],
  485. &ppi->SameGreyDirPixels[ScoreFragIndex3],
  486. &ppi->ScanDisplayFragments[ScoreFragIndex3],
  487. &ppi->BarBlockMap[(RowNumber3 % 3) * ppi->PlaneHFragments],
  488. RowNumber3 );
  489. }
  490. // BAR copy back and "ppi->SRF filtering" or "pixel copy back"
  491. if ( (RowNumber4 >= 0) && (RowNumber4 < ppi->PlaneVFragments) )
  492. {
  493. // BAR copy back stage must lag by one more row to avoid BAR blocks
  494. // being used in BAR descisions.
  495. ScoreFragIndex4 = (RowNumber4 * ppi->PlaneHFragments) + FragArrayOffset;
  496. BarCopyBack(ppi, &ppi->ScanDisplayFragments[ScoreFragIndex4],
  497. &ppi->BarBlockMap[(RowNumber4 % 3) * ppi->PlaneHFragments]);
  498. /*
  499. // "Apply ppi->SRF filtering to" or "copy back" pixels.
  500. PixelScoresPtr4 = &ppi->PixelScores[(RowNumber4 % 4) * BlockRowPixels];
  501. */
  502. // Copy over the data from any blocks marked for update into the output buffer.
  503. //RowCopy(ppi, ScoreFragIndex4);
  504. }
  505. }
  506. }
  507. /****************************************************************************
  508. *
  509. * ROUTINE : RowSadScan
  510. *
  511. * INPUTS : UINT8 * YuvPtr1, YuvPtr2
  512. * Pointers into current and previous frame
  513. *
  514. * OUTPUTS : INT8 * DispFragPtr
  515. * Fragment update map (-1 = ???, 0 = No, >0 = Yes)
  516. *
  517. * RETURNS : TRUE if row contains Candidate or coded blocsk else FALSE
  518. *
  519. * FUNCTION : Preliminary fast scan based upon local SAD scores of 4 pixel groups
  520. *
  521. * SPECIAL NOTES : None.
  522. *
  523. *
  524. * ERRORS : None.
  525. *
  526. ****************************************************************************/
  527. BOOL RowSadScan( PP_INSTANCE *ppi, UINT8 * YuvPtr1, UINT8 * YuvPtr2, INT8 * DispFragPtr )
  528. {
  529. INT32 i, j;
  530. UINT32 GrpSad;
  531. UINT32 LocalGrpLowSadThresh = ppi->ModifiedGrpLowSadThresh;
  532. UINT32 LocalGrpHighSadThresh = ppi->ModifiedGrpHighSadThresh;
  533. INT8 * LocalDispFragPtr;
  534. UINT32 * LocalYuvPtr1;
  535. UINT32 * LocalYuvPtr2;
  536. BOOL InterestingBlocksInRow = FALSE;
  537. // For each row of pixels in the row of blocks
  538. for ( j = 0; j < ppi->VFragPixels; j++ )
  539. {
  540. // Set local block map pointer.
  541. LocalDispFragPtr = DispFragPtr;
  542. // Set the local pixel data pointers for this row.
  543. LocalYuvPtr1 = (UINT32 *)YuvPtr1;
  544. LocalYuvPtr2 = (UINT32 *)YuvPtr2;
  545. // Scan along the row of pixels
  546. // If the block to which a group of pixels belongs is already marked for update then do nothing.
  547. for ( i = 0; i < ppi->PlaneHFragments; i ++ )
  548. {
  549. if ( *LocalDispFragPtr <= BLOCK_NOT_CODED )
  550. {
  551. // Calculate the SAD score for the block row
  552. GrpSad = ppi->RowSAD((UINT8 *)LocalYuvPtr1,(UINT8 *)LocalYuvPtr2);
  553. // Now test the group SAD score
  554. if ( GrpSad > LocalGrpLowSadThresh )
  555. {
  556. // If SAD very high we must update else we have candidate block
  557. if ( GrpSad > LocalGrpHighSadThresh )
  558. {
  559. // Force update
  560. *LocalDispFragPtr = BLOCK_CODED;
  561. }
  562. else
  563. {
  564. // Possible Update required
  565. *LocalDispFragPtr = CANDIDATE_BLOCK;
  566. }
  567. InterestingBlocksInRow = TRUE;
  568. }
  569. }
  570. /********** PGW 27/APR/2001 ***********/
  571. else
  572. InterestingBlocksInRow = TRUE;
  573. LocalDispFragPtr++;
  574. LocalYuvPtr1 += 2;
  575. LocalYuvPtr2 += 2;
  576. }
  577. // Increment the base data pointers to the start of the next line.
  578. YuvPtr1 += ppi->PlaneStride;
  579. YuvPtr2 += ppi->PlaneStride;
  580. }
  581. // This code is PC specific
  582. if ( ppi->MmxEnabled )
  583. {
  584. ClearMmxState(ppi);
  585. }
  586. return InterestingBlocksInRow;
  587. }
  588. /****************************************************************************
  589. *
  590. * ROUTINE : ColSadScan
  591. *
  592. * INPUTS : UINT8 * YuvPtr1, YuvPtr2
  593. * Pointers into current and previous frame
  594. *
  595. * OUTPUTS : INT8 * DispFragPtr
  596. * Fragment update map (-1 = ???, 0 = No, >0 = Yes)
  597. *
  598. * RETURNS : TRUE if row contains Candidate or coded blocsk else FALSE
  599. *
  600. * FUNCTION : Preliminary fast scan based upon local SAD scores of 4 pixel groups
  601. *
  602. * SPECIAL NOTES : None.
  603. *
  604. *
  605. * ERRORS : None.
  606. *
  607. ****************************************************************************/
  608. BOOL ColSadScan( PP_INSTANCE *ppi, UINT8 * YuvPtr1, UINT8 * YuvPtr2, INT8 * DispFragPtr )
  609. {
  610. INT32 i;
  611. UINT32 MaxSad;
  612. UINT32 LocalGrpLowSadThresh = ppi->ModifiedGrpLowSadThresh;
  613. UINT32 LocalGrpHighSadThresh = ppi->ModifiedGrpHighSadThresh;
  614. INT8 * LocalDispFragPtr;
  615. UINT8 * LocalYuvPtr1;
  616. UINT8 * LocalYuvPtr2;
  617. BOOL InterestingBlocksInRow = FALSE;
  618. // Set the local pixel data pointers for this row.
  619. LocalYuvPtr1 = YuvPtr1;
  620. LocalYuvPtr2 = YuvPtr2;
  621. // Set local block map pointer.
  622. LocalDispFragPtr = DispFragPtr;
  623. // Scan along the row of blocks
  624. for ( i = 0; i < ppi->PlaneHFragments; i ++ )
  625. {
  626. // Skip if block already marked to be coded.
  627. if ( *LocalDispFragPtr <= BLOCK_NOT_CODED )
  628. {
  629. // Calculate the SAD score for the block column
  630. MaxSad = ppi->ColSAD( ppi, (UINT8 *)LocalYuvPtr1,(UINT8 *)LocalYuvPtr2 );
  631. // Now test the group SAD score
  632. if ( MaxSad > LocalGrpLowSadThresh )
  633. {
  634. // If SAD very high we must update else we have candidate block
  635. if ( MaxSad > LocalGrpHighSadThresh )
  636. {
  637. // Force update
  638. *LocalDispFragPtr = BLOCK_CODED;
  639. }
  640. else
  641. {
  642. // Possible Update required
  643. *LocalDispFragPtr = CANDIDATE_BLOCK;
  644. }
  645. InterestingBlocksInRow = TRUE;
  646. }
  647. }
  648. /********** PGW 27/APR/2001 ***********/
  649. else
  650. InterestingBlocksInRow = TRUE;
  651. // Increment the block map pointer.
  652. LocalDispFragPtr++;
  653. // Step data pointers on ready for next block
  654. LocalYuvPtr1 += ppi->HFragPixels;
  655. LocalYuvPtr2 += ppi->HFragPixels;
  656. }
  657. // This code is PC specific
  658. if ( ppi->MmxEnabled )
  659. {
  660. ClearMmxState(ppi);
  661. }
  662. return InterestingBlocksInRow;
  663. }
  664. /****************************************************************************
  665. *
  666. * ROUTINE : SadPass2
  667. *
  668. * INPUTS : UINT32 RowNumber
  669. * Fragment row number
  670. * INT8 * DispFragPtr
  671. * Fragment update map (-1 = ???, 0 = No, >0 = Yes)
  672. *
  673. * OUTPUTS : INT8 * DispFragPtr
  674. * Fragment update map (-1 = ???, 0 = No, >0 = Yes)
  675. * RETURNS :
  676. *
  677. * FUNCTION : This second pass should only be used when speed is critical.
  678. * The function revisits the classification of CANDIDATE_BLOCKS
  679. * if they are adjacent to one or more CODED_BLOCKS.
  680. *
  681. * SPECIAL NOTES : None.
  682. *
  683. *
  684. * ERRORS : None.
  685. *
  686. ****************************************************************************/
  687. void SadPass2( PP_INSTANCE *ppi, INT32 RowNumber, INT8 * DispFragPtr )
  688. {
  689. INT32 i;
  690. // First row
  691. if ( RowNumber == 0 )
  692. {
  693. // First block in row.
  694. if ( DispFragPtr[0] == CANDIDATE_BLOCK )
  695. {
  696. if ( (DispFragPtr[1] == BLOCK_CODED) ||
  697. (DispFragPtr[ppi->PlaneHFragments] == BLOCK_CODED) ||
  698. (DispFragPtr[ppi->PlaneHFragments+1] == BLOCK_CODED) )
  699. {
  700. ppi->TmpCodedMap[0] = BLOCK_CODED_LOW;
  701. }
  702. else
  703. {
  704. ppi->TmpCodedMap[0] = DispFragPtr[0];
  705. }
  706. }
  707. else
  708. {
  709. ppi->TmpCodedMap[0] = DispFragPtr[0];
  710. }
  711. // All but first and last in row
  712. for ( i = 1; (i < ppi->PlaneHFragments-1); i++ )
  713. {
  714. if ( DispFragPtr[i] == CANDIDATE_BLOCK )
  715. {
  716. if ( (DispFragPtr[i-1] == BLOCK_CODED) ||
  717. (DispFragPtr[i+1] == BLOCK_CODED) ||
  718. (DispFragPtr[i+ppi->PlaneHFragments] == BLOCK_CODED) ||
  719. (DispFragPtr[i+ppi->PlaneHFragments-1] == BLOCK_CODED) ||
  720. (DispFragPtr[i+ppi->PlaneHFragments+1] == BLOCK_CODED) )
  721. {
  722. ppi->TmpCodedMap[i] = BLOCK_CODED_LOW;
  723. }
  724. else
  725. {
  726. ppi->TmpCodedMap[i] = DispFragPtr[i];
  727. }
  728. }
  729. else
  730. {
  731. ppi->TmpCodedMap[i] = DispFragPtr[i];
  732. }
  733. }
  734. // Last block in row.
  735. i = ppi->PlaneHFragments-1;
  736. if ( DispFragPtr[i] == CANDIDATE_BLOCK )
  737. {
  738. if ( (DispFragPtr[i-1] == BLOCK_CODED) ||
  739. (DispFragPtr[i+ppi->PlaneHFragments] == BLOCK_CODED) ||
  740. (DispFragPtr[i+ppi->PlaneHFragments-1] == BLOCK_CODED) )
  741. {
  742. ppi->TmpCodedMap[i] = BLOCK_CODED_LOW;
  743. }
  744. else
  745. {
  746. ppi->TmpCodedMap[i] = DispFragPtr[i];
  747. }
  748. }
  749. else
  750. {
  751. ppi->TmpCodedMap[i] = DispFragPtr[i];
  752. }
  753. }
  754. // General case
  755. else if ( RowNumber < (ppi->PlaneVFragments - 1) )
  756. {
  757. // First block in row.
  758. if ( DispFragPtr[0] == CANDIDATE_BLOCK )
  759. {
  760. if ( (DispFragPtr[1] == BLOCK_CODED) ||
  761. (DispFragPtr[(-ppi->PlaneHFragments)] == BLOCK_CODED) ||
  762. (DispFragPtr[(-ppi->PlaneHFragments)+1] == BLOCK_CODED) ||
  763. (DispFragPtr[ppi->PlaneHFragments] == BLOCK_CODED) ||
  764. (DispFragPtr[ppi->PlaneHFragments+1] == BLOCK_CODED) )
  765. {
  766. ppi->TmpCodedMap[0] = BLOCK_CODED_LOW;
  767. }
  768. else
  769. {
  770. ppi->TmpCodedMap[0] = DispFragPtr[0];
  771. }
  772. }
  773. else
  774. {
  775. ppi->TmpCodedMap[0] = DispFragPtr[0];
  776. }
  777. // All but first and last in row
  778. for ( i = 1; (i < ppi->PlaneHFragments-1); i++ )
  779. {
  780. if ( DispFragPtr[i] == CANDIDATE_BLOCK )
  781. {
  782. if ( (DispFragPtr[i-1] == BLOCK_CODED) ||
  783. (DispFragPtr[i+1] == BLOCK_CODED) ||
  784. (DispFragPtr[i-ppi->PlaneHFragments] == BLOCK_CODED) ||
  785. (DispFragPtr[i-ppi->PlaneHFragments-1] == BLOCK_CODED) ||
  786. (DispFragPtr[i-ppi->PlaneHFragments+1] == BLOCK_CODED) ||
  787. (DispFragPtr[i+ppi->PlaneHFragments] == BLOCK_CODED) ||
  788. (DispFragPtr[i+ppi->PlaneHFragments-1] == BLOCK_CODED) ||
  789. (DispFragPtr[i+ppi->PlaneHFragments+1] == BLOCK_CODED) )
  790. {
  791. ppi->TmpCodedMap[i] = BLOCK_CODED_LOW;
  792. }
  793. else
  794. {
  795. ppi->TmpCodedMap[i] = DispFragPtr[i];
  796. }
  797. }
  798. else
  799. {
  800. ppi->TmpCodedMap[i] = DispFragPtr[i];
  801. }
  802. }
  803. // Last block in row.
  804. i = ppi->PlaneHFragments-1;
  805. if ( DispFragPtr[i] == CANDIDATE_BLOCK )
  806. {
  807. if ( (DispFragPtr[i-1] == BLOCK_CODED) ||
  808. (DispFragPtr[i-ppi->PlaneHFragments] == BLOCK_CODED) ||
  809. (DispFragPtr[i-ppi->PlaneHFragments-1] == BLOCK_CODED) ||
  810. (DispFragPtr[i+ppi->PlaneHFragments] == BLOCK_CODED) ||
  811. (DispFragPtr[i+ppi->PlaneHFragments-1] == BLOCK_CODED) )
  812. {
  813. ppi->TmpCodedMap[i] = BLOCK_CODED_LOW;
  814. }
  815. else
  816. {
  817. ppi->TmpCodedMap[i] = DispFragPtr[i];
  818. }
  819. }
  820. else
  821. {
  822. ppi->TmpCodedMap[i] = DispFragPtr[i];
  823. }
  824. }
  825. // Last row
  826. else
  827. {
  828. // First block in row.
  829. if ( DispFragPtr[0] == CANDIDATE_BLOCK )
  830. {
  831. if ( (DispFragPtr[1] == BLOCK_CODED) ||
  832. (DispFragPtr[(-ppi->PlaneHFragments)] == BLOCK_CODED) ||
  833. (DispFragPtr[(-ppi->PlaneHFragments)+1] == BLOCK_CODED))
  834. {
  835. ppi->TmpCodedMap[0] = BLOCK_CODED_LOW;
  836. }
  837. else
  838. {
  839. ppi->TmpCodedMap[0] = DispFragPtr[0];
  840. }
  841. }
  842. else
  843. {
  844. ppi->TmpCodedMap[0] = DispFragPtr[0];
  845. }
  846. // All but first and last in row
  847. for ( i = 1; (i < ppi->PlaneHFragments-1); i++ )
  848. {
  849. if ( DispFragPtr[i] == CANDIDATE_BLOCK )
  850. {
  851. if ( (DispFragPtr[i-1] == BLOCK_CODED) ||
  852. (DispFragPtr[i+1] == BLOCK_CODED) ||
  853. (DispFragPtr[i-ppi->PlaneHFragments] == BLOCK_CODED) ||
  854. (DispFragPtr[i-ppi->PlaneHFragments-1] == BLOCK_CODED) ||
  855. (DispFragPtr[i-ppi->PlaneHFragments+1] == BLOCK_CODED) )
  856. {
  857. ppi->TmpCodedMap[i] = BLOCK_CODED_LOW;
  858. }
  859. else
  860. {
  861. ppi->TmpCodedMap[i] = DispFragPtr[i];
  862. }
  863. }
  864. else
  865. {
  866. ppi->TmpCodedMap[i] = DispFragPtr[i];
  867. }
  868. }
  869. // Last block in row.
  870. i = ppi->PlaneHFragments-1;
  871. if ( DispFragPtr[i] == CANDIDATE_BLOCK )
  872. {
  873. if ( (DispFragPtr[i-1] == BLOCK_CODED) ||
  874. (DispFragPtr[i-ppi->PlaneHFragments] == BLOCK_CODED) ||
  875. (DispFragPtr[i-ppi->PlaneHFragments-1] == BLOCK_CODED) )
  876. {
  877. ppi->TmpCodedMap[i] = BLOCK_CODED_LOW;
  878. }
  879. else
  880. {
  881. ppi->TmpCodedMap[i] = DispFragPtr[i];
  882. }
  883. }
  884. else
  885. {
  886. ppi->TmpCodedMap[i] = DispFragPtr[i];
  887. }
  888. }
  889. // Now copy back the modified Fragment data
  890. memcpy( &DispFragPtr[0], &ppi->TmpCodedMap[0], (ppi->PlaneHFragments) );
  891. }
  892. /****************************************************************************
  893. *
  894. * ROUTINE : RowDiffScan
  895. *
  896. * INPUTS : UINT8 * YuvPtr1, YuvPtr2
  897. * Pointers into current and previous frame
  898. * BOOL EdgeRow
  899. * Is this row an edge row.
  900. *
  901. * OUTPUTS : UINT16 * YUVDiffsPtr
  902. * Differnece map
  903. * UINT8 * bits_map_ptr
  904. * Pixels changed map
  905. * UINT8 * SgcPtr
  906. * Level change score.
  907. * INT8 * DispFragPtr
  908. * Block update map.
  909. * INT32 * RowDiffsPtr
  910. * Total sig changes for row
  911. * UINT8 * ChLocalsPtr
  912. * Changed locals data structure
  913. *
  914. *
  915. * RETURNS :
  916. *
  917. * FUNCTION : Initial pixel differences scan
  918. *
  919. * SPECIAL NOTES : None.
  920. *
  921. *
  922. * ERRORS : None.
  923. *
  924. ****************************************************************************/
  925. void RowDiffScan( PP_INSTANCE *ppi, UINT8 * YuvPtr1, UINT8 * YuvPtr2,
  926. INT16 * YUVDiffsPtr, UINT8 * bits_map_ptr,
  927. INT8 * SgcPtr, INT8 * DispFragPtr,
  928. UINT8 * FDiffPixels, INT32 * RowDiffsPtr,
  929. UINT8 * ChLocalsPtr, BOOL EdgeRow )
  930. {
  931. INT32 i,j;
  932. INT32 FragChangedPixels;
  933. UINT32 ZeroData[2] = { 0,0 };
  934. UINT8 OneData[8] = { 1,1,1,1,1,1,1,1 };
  935. UINT8 ChlocalsDummyData[8] = { 8,8,8,8,8,8,8,8 };
  936. INT16 Diff; // Temp local workspace.
  937. // Cannot use kernel if at edge or if PAK disabled
  938. if ( (!ppi->PAKEnabled) || EdgeRow )
  939. {
  940. for ( i = 0; i < ppi->PlaneWidth; i += ppi->HFragPixels )
  941. {
  942. // Reset count of pixels changed for the current fragment.
  943. FragChangedPixels = 0;
  944. // Test for break out conditions to save time.
  945. if (*DispFragPtr == CANDIDATE_BLOCK)
  946. {
  947. // Clear down entries in changed locals array
  948. ((UINT32 *)ChLocalsPtr)[0] = ((UINT32 *)ZeroData)[0];
  949. ((UINT32 *)ChLocalsPtr)[1] = ((UINT32 *)ZeroData)[1];
  950. for ( j = 0; j < ppi->HFragPixels; j++ )
  951. {
  952. // Take a local copy of the measured difference.
  953. Diff = ((INT16)YuvPtr1[j]) - ((INT16)YuvPtr2[j]);
  954. // Store the actual difference value
  955. YUVDiffsPtr[j] = Diff;
  956. // Test against the Level thresholds and record the results
  957. SgcPtr[0] += ppi->SgcThreshTablePtr[Diff];
  958. // Test against the SRF thresholds
  959. bits_map_ptr[j] = ppi->SrfThreshTablePtr[Diff];
  960. FragChangedPixels += ppi->SrfThreshTablePtr[Diff];
  961. }
  962. }
  963. else
  964. {
  965. // For EBO coded blocks mark all pixels as changed.
  966. if ( *DispFragPtr > BLOCK_NOT_CODED )
  967. {
  968. ((UINT32 *)bits_map_ptr)[0] = ((UINT32 *)OneData)[0];
  969. ((UINT32 *)ChLocalsPtr)[0] = ((UINT32 *)ChlocalsDummyData)[0];
  970. ((UINT32 *)bits_map_ptr)[1] = ((UINT32 *)OneData)[1];
  971. ((UINT32 *)ChLocalsPtr)[1] = ((UINT32 *)ChlocalsDummyData)[1];
  972. }
  973. else
  974. {
  975. ((UINT32 *)ChLocalsPtr)[0] = ((UINT32 *)ZeroData)[0];
  976. ((UINT32 *)ChLocalsPtr)[1] = ((UINT32 *)ZeroData)[1];
  977. }
  978. }
  979. *RowDiffsPtr += FragChangedPixels;
  980. *FDiffPixels += (UINT8)FragChangedPixels;
  981. YuvPtr1 += ppi->HFragPixels;
  982. YuvPtr2 += ppi->HFragPixels;
  983. bits_map_ptr += ppi->HFragPixels;
  984. ChLocalsPtr += ppi->HFragPixels;
  985. YUVDiffsPtr += ppi->HFragPixels;
  986. SgcPtr ++;
  987. FDiffPixels ++;
  988. // If we have a lot of changed pixels for this fragment on this row then
  989. // the fragment is almost sure to be picked (e.g. through the line search) so we
  990. // can mark it as selected and then ignore it.
  991. if (FragChangedPixels >= 7)
  992. {
  993. *DispFragPtr = BLOCK_CODED_LOW;
  994. }
  995. DispFragPtr++;
  996. }
  997. }
  998. else
  999. {
  1000. //*************************************************************
  1001. // First fragment of row !!
  1002. i = 0;
  1003. // Reset count of pixels changed for the current fragment.
  1004. FragChangedPixels = 0;
  1005. // Test for break out conditions to save time.
  1006. if (*DispFragPtr == CANDIDATE_BLOCK)
  1007. {
  1008. // Clear down entries in changed locals array
  1009. ((UINT32 *)ChLocalsPtr)[0] = ((UINT32 *)ZeroData)[0];
  1010. ((UINT32 *)ChLocalsPtr)[1] = ((UINT32 *)ZeroData)[1];
  1011. for ( j = 0; j < ppi->HFragPixels; j++ )
  1012. {
  1013. // Take a local copy of the measured difference.
  1014. Diff = ((INT16)YuvPtr1[j]) - ((INT16)YuvPtr2[j]);
  1015. // Store the actual difference value
  1016. YUVDiffsPtr[j] = Diff;
  1017. // Test against the Level thresholds and record the results
  1018. SgcPtr[0] += ppi->SgcThreshTablePtr[Diff];
  1019. // jbb added i+j > 0 and i+j < ppi->HFragPixels - 1 check
  1020. if (j>0 && ppi->SrfPakThreshTablePtr[Diff] )
  1021. Diff = (int)ApplyPakLowPass( ppi, &YuvPtr1[j] ) -
  1022. (int)ApplyPakLowPass( ppi, &YuvPtr2[j] );
  1023. // Test against the SRF thresholds
  1024. bits_map_ptr[j] = ppi->SrfThreshTablePtr[Diff];
  1025. FragChangedPixels += ppi->SrfThreshTablePtr[Diff];
  1026. }
  1027. }
  1028. else
  1029. {
  1030. // For EBO coded blocks mark all pixels as changed.
  1031. if ( *DispFragPtr > BLOCK_NOT_CODED )
  1032. {
  1033. ((UINT32 *)bits_map_ptr)[0] = ((UINT32 *)OneData)[0];
  1034. ((UINT32 *)ChLocalsPtr)[0] = ((UINT32 *)ChlocalsDummyData)[0];
  1035. ((UINT32 *)bits_map_ptr)[1] = ((UINT32 *)OneData)[1];
  1036. ((UINT32 *)ChLocalsPtr)[1] = ((UINT32 *)ChlocalsDummyData)[1];
  1037. }
  1038. else
  1039. {
  1040. ((UINT32 *)ChLocalsPtr)[0] = ((UINT32 *)ZeroData)[0];
  1041. ((UINT32 *)ChLocalsPtr)[1] = ((UINT32 *)ZeroData)[1];
  1042. }
  1043. }
  1044. *RowDiffsPtr += FragChangedPixels;
  1045. *FDiffPixels += (UINT8)FragChangedPixels;
  1046. YuvPtr1 += ppi->HFragPixels;
  1047. YuvPtr2 += ppi->HFragPixels;
  1048. bits_map_ptr += ppi->HFragPixels;
  1049. ChLocalsPtr += ppi->HFragPixels;
  1050. YUVDiffsPtr += ppi->HFragPixels;
  1051. SgcPtr ++;
  1052. FDiffPixels ++;
  1053. // If we have a lot of changed pixels for this fragment on this row then
  1054. // the fragment is almost sure to be picked (e.g. through the line search) so we
  1055. // can mark it as selected and then ignore it.
  1056. if (FragChangedPixels >= 7)
  1057. {
  1058. *DispFragPtr = BLOCK_CODED_LOW;
  1059. }
  1060. DispFragPtr++;
  1061. //*************************************************************
  1062. // Fragment in between!!
  1063. for ( i = ppi->HFragPixels ; i < ppi->PlaneWidth-ppi->HFragPixels; i += ppi->HFragPixels )
  1064. {
  1065. // Reset count of pixels changed for the current fragment.
  1066. FragChangedPixels = 0;
  1067. // Test for break out conditions to save time.
  1068. if (*DispFragPtr == CANDIDATE_BLOCK)
  1069. {
  1070. // Clear down entries in changed locals array
  1071. ((UINT32 *)ChLocalsPtr)[0] = ((UINT32 *)ZeroData)[0];
  1072. ((UINT32 *)ChLocalsPtr)[1] = ((UINT32 *)ZeroData)[1];
  1073. for ( j = 0; j < ppi->HFragPixels; j++ )
  1074. {
  1075. // Take a local copy of the measured difference.
  1076. Diff = ((INT16)YuvPtr1[j]) - ((INT16)YuvPtr2[j]);
  1077. // Store the actual difference value
  1078. YUVDiffsPtr[j] = Diff;
  1079. // Test against the Level thresholds and record the results
  1080. SgcPtr[0] += ppi->SgcThreshTablePtr[Diff];
  1081. // jbb added i+j > 0 and i+j < ppi->HFragPixels - 1 check
  1082. if (ppi->SrfPakThreshTablePtr[Diff] )
  1083. Diff = (int)ApplyPakLowPass( ppi, &YuvPtr1[j] ) -
  1084. (int)ApplyPakLowPass( ppi, &YuvPtr2[j] );
  1085. // Test against the SRF thresholds
  1086. bits_map_ptr[j] = ppi->SrfThreshTablePtr[Diff];
  1087. FragChangedPixels += ppi->SrfThreshTablePtr[Diff];
  1088. }
  1089. }
  1090. else
  1091. {
  1092. // For EBO coded blocks mark all pixels as changed.
  1093. if ( *DispFragPtr > BLOCK_NOT_CODED )
  1094. {
  1095. ((UINT32 *)bits_map_ptr)[0] = ((UINT32 *)OneData)[0];
  1096. ((UINT32 *)ChLocalsPtr)[0] = ((UINT32 *)ChlocalsDummyData)[0];
  1097. ((UINT32 *)bits_map_ptr)[1] = ((UINT32 *)OneData)[1];
  1098. ((UINT32 *)ChLocalsPtr)[1] = ((UINT32 *)ChlocalsDummyData)[1];
  1099. }
  1100. else
  1101. {
  1102. ((UINT32 *)ChLocalsPtr)[0] = ((UINT32 *)ZeroData)[0];
  1103. ((UINT32 *)ChLocalsPtr)[1] = ((UINT32 *)ZeroData)[1];
  1104. }
  1105. }
  1106. *RowDiffsPtr += FragChangedPixels;
  1107. *FDiffPixels += (UINT8)FragChangedPixels;
  1108. YuvPtr1 += ppi->HFragPixels;
  1109. YuvPtr2 += ppi->HFragPixels;
  1110. bits_map_ptr += ppi->HFragPixels;
  1111. ChLocalsPtr += ppi->HFragPixels;
  1112. YUVDiffsPtr += ppi->HFragPixels;
  1113. SgcPtr ++;
  1114. FDiffPixels ++;
  1115. // If we have a lot of changed pixels for this fragment on this row then
  1116. // the fragment is almost sure to be picked (e.g. through the line search) so we
  1117. // can mark it as selected and then ignore it.
  1118. if (FragChangedPixels >= 7)
  1119. {
  1120. *DispFragPtr = BLOCK_CODED_LOW;
  1121. }
  1122. DispFragPtr++;
  1123. }
  1124. //*************************************************************
  1125. //*************************************************************
  1126. // Last fragment of row !!
  1127. // Reset count of pixels changed for the current fragment.
  1128. FragChangedPixels = 0;
  1129. // Test for break out conditions to save time.
  1130. if (*DispFragPtr == CANDIDATE_BLOCK)
  1131. {
  1132. // Clear down entries in changed locals array
  1133. ((UINT32 *)ChLocalsPtr)[0] = ((UINT32 *)ZeroData)[0];
  1134. ((UINT32 *)ChLocalsPtr)[1] = ((UINT32 *)ZeroData)[1];
  1135. for ( j = 0; j < ppi->HFragPixels; j++ )
  1136. {
  1137. // Take a local copy of the measured difference.
  1138. Diff = ((INT16)YuvPtr1[j]) - ((INT16)YuvPtr2[j]);
  1139. // Store the actual difference value
  1140. YUVDiffsPtr[j] = Diff;
  1141. // Test against the Level thresholds and record the results
  1142. SgcPtr[0] += ppi->SgcThreshTablePtr[Diff];
  1143. // jbb added i+j > 0 and i+j < ppi->HFragPixels - 1 check
  1144. if (j<7 && ppi->SrfPakThreshTablePtr[Diff] )
  1145. Diff = (int)ApplyPakLowPass( ppi, &YuvPtr1[j] ) -
  1146. (int)ApplyPakLowPass( ppi, &YuvPtr2[j] );
  1147. // Test against the SRF thresholds
  1148. bits_map_ptr[j] = ppi->SrfThreshTablePtr[Diff];
  1149. FragChangedPixels += ppi->SrfThreshTablePtr[Diff];
  1150. }
  1151. }
  1152. else
  1153. {
  1154. // For EBO coded blocks mark all pixels as changed.
  1155. if ( *DispFragPtr > BLOCK_NOT_CODED )
  1156. {
  1157. ((UINT32 *)bits_map_ptr)[0] = ((UINT32 *)OneData)[0];
  1158. ((UINT32 *)ChLocalsPtr)[0] = ((UINT32 *)ChlocalsDummyData)[0];
  1159. ((UINT32 *)bits_map_ptr)[1] = ((UINT32 *)OneData)[1];
  1160. ((UINT32 *)ChLocalsPtr)[1] = ((UINT32 *)ChlocalsDummyData)[1];
  1161. }
  1162. else
  1163. {
  1164. ((UINT32 *)ChLocalsPtr)[0] = ((UINT32 *)ZeroData)[0];
  1165. ((UINT32 *)ChLocalsPtr)[1] = ((UINT32 *)ZeroData)[1];
  1166. }
  1167. }
  1168. // If we have a lot of changed pixels for this fragment on this row then
  1169. // the fragment is almost sure to be picked (e.g. through the line search) so we
  1170. // can mark it as selected and then ignore it.
  1171. *RowDiffsPtr += FragChangedPixels;
  1172. *FDiffPixels += (UINT8)FragChangedPixels;
  1173. // If we have a lot of changed pixels for this fragment on this row then
  1174. // the fragment is almost sure to be picked (e.g. through the line search) so we
  1175. // can mark it as selected and then ignore it.
  1176. if (FragChangedPixels >= 7)
  1177. {
  1178. *DispFragPtr = BLOCK_CODED_LOW;
  1179. }
  1180. DispFragPtr++;
  1181. //*************************************************************
  1182. }
  1183. }
  1184. /****************************************************************************
  1185. *
  1186. * ROUTINE : ConsolidateDiffScanResults
  1187. *
  1188. * INPUTS : UINT8 * FDiffPixels
  1189. * Fragment changed pixels records
  1190. * UINT8 * SgcScoresPtr
  1191. * Fragment SGC records
  1192. * INT8 * DispFragPtr
  1193. * Fragment update map (-1 = ???, 0 = No, 1 = Yes)
  1194. *
  1195. * OUTPUTS : UINT8 * DispFragPtr
  1196. * Fragment update map (-1 = ???, 0 = No, 1 = Yes)
  1197. * RETURNS :
  1198. *
  1199. * FUNCTION : Considers new information from difference scan and, if necessary,
  1200. * upates output map.
  1201. *
  1202. * SPECIAL NOTES : None.
  1203. *
  1204. *
  1205. * ERRORS : None.
  1206. *
  1207. ****************************************************************************/
  1208. void ConsolidateDiffScanResults( PP_INSTANCE *ppi, UINT8 * FDiffPixels, INT8 * SgcScoresPtr, INT8 * DispFragPtr )
  1209. {
  1210. INT32 i;
  1211. for ( i = 0; i < ppi->PlaneHFragments; i ++ )
  1212. {
  1213. // Consider only those blocks that were candidates in the
  1214. // difference scan. Ignore definite YES and NO cases.
  1215. if ( DispFragPtr[i] == CANDIDATE_BLOCK )
  1216. {
  1217. if ( ((UINT32)abs(SgcScoresPtr[i]) > ppi->BlockSgcThresh) )
  1218. {
  1219. // Block marked for update due to Sgc change
  1220. DispFragPtr[i] = BLOCK_CODED_SGC;
  1221. }
  1222. else if ( FDiffPixels[i] == 0 )
  1223. {
  1224. // Block marked for NO update as no/too few interesting pixels.
  1225. //DispFragPtr[i] = BLOCK_NOT_CODED;
  1226. // Block is no longer a candidate for the main tests but will
  1227. // still be considered a candidate in RowBarEnhBlockMap()
  1228. DispFragPtr[i] = CANDIDATE_BLOCK_LOW;
  1229. }
  1230. }
  1231. }
  1232. }
  1233. /****************************************************************************
  1234. *
  1235. * ROUTINE : RowChangedLocalsScan
  1236. *
  1237. * INPUTS : UINT8 * PixelMapPtr.
  1238. * UINT8 * ChLocalsPtr.
  1239. * INT8 * DispFragPtr
  1240. * UINT8 * RowType
  1241. *
  1242. * OUTPUTS : None.
  1243. *
  1244. * RETURNS :
  1245. *
  1246. * FUNCTION : Calculates changed locals for changed pixels
  1247. *
  1248. * SPECIAL NOTES : None.
  1249. *
  1250. *
  1251. * ERRORS : None.
  1252. *
  1253. ****************************************************************************/
  1254. void RowChangedLocalsScan( PP_INSTANCE *ppi, UINT8 * PixelMapPtr, UINT8 * ChLocalsPtr,
  1255. INT8 * DispFragPtr, UINT8 RowType )
  1256. {
  1257. UINT8 ChlocalsDummyData[8] = { 8,8,8,8,8,8,8,8 };
  1258. UINT8 changed_locals = 0;
  1259. UINT8 Score = 0;
  1260. UINT8 * PixelsChangedPtr0;
  1261. UINT8 * PixelsChangedPtr1;
  1262. UINT8 * PixelsChangedPtr2;
  1263. INT32 i, j;
  1264. INT32 LastRowIndex = ppi->PlaneWidth - 1;
  1265. // Set up the line based pointers into the bits changed map.
  1266. PixelsChangedPtr0 = PixelMapPtr - ppi->PlaneWidth;
  1267. if ( PixelsChangedPtr0 < ppi->PixelChangedMap )
  1268. PixelsChangedPtr0 += ppi->PixelMapCircularBufferSize;
  1269. PixelsChangedPtr0 -= 1;
  1270. PixelsChangedPtr1 = PixelMapPtr - 1;
  1271. PixelsChangedPtr2 = PixelMapPtr + ppi->PlaneWidth;
  1272. if ( PixelsChangedPtr2 >= (ppi->PixelChangedMap + ppi->PixelMapCircularBufferSize) )
  1273. PixelsChangedPtr2 -= ppi->PixelMapCircularBufferSize;
  1274. PixelsChangedPtr2 -= 1;
  1275. if ( RowType == NOT_EDGE_ROW )
  1276. {
  1277. // Scan through the row of pixels and calculate changed locals.
  1278. for ( i = 0; i < ppi->PlaneWidth; i += ppi->HFragPixels )
  1279. {
  1280. // Skip a group of 8 pixels if the assosciated fragment has no pixels of interest or
  1281. // if EBO is enabled and a breakout condition is met.
  1282. if ( *DispFragPtr == CANDIDATE_BLOCK )
  1283. {
  1284. for ( j = 0; j < ppi->HFragPixels; j++ )
  1285. {
  1286. changed_locals = 0;
  1287. // If the pixel itself has changed
  1288. if ( PixelsChangedPtr1[1] )
  1289. {
  1290. if ( (i > 0) || (j > 0) )
  1291. {
  1292. changed_locals += PixelsChangedPtr0[0];
  1293. changed_locals += PixelsChangedPtr1[0];
  1294. changed_locals += PixelsChangedPtr2[0];
  1295. }
  1296. changed_locals += PixelsChangedPtr0[1];
  1297. changed_locals += PixelsChangedPtr2[1];
  1298. if ( (i + j) < LastRowIndex )
  1299. {
  1300. changed_locals += PixelsChangedPtr0[2];
  1301. changed_locals += PixelsChangedPtr1[2];
  1302. changed_locals += PixelsChangedPtr2[2];
  1303. }
  1304. // Store the number of changed locals
  1305. *ChLocalsPtr |= changed_locals;
  1306. }
  1307. // Increment to next pixel in the row
  1308. ChLocalsPtr++;
  1309. PixelsChangedPtr0++;
  1310. PixelsChangedPtr1++;
  1311. PixelsChangedPtr2++;
  1312. }
  1313. }
  1314. else
  1315. {
  1316. if ( *DispFragPtr > BLOCK_NOT_CODED )
  1317. {
  1318. ((UINT32 *)ChLocalsPtr)[0] = ((UINT32 *)ChlocalsDummyData)[0];
  1319. ((UINT32 *)ChLocalsPtr)[1] = ((UINT32 *)ChlocalsDummyData)[1];
  1320. }
  1321. // Step pointers
  1322. ChLocalsPtr += ppi->HFragPixels;
  1323. PixelsChangedPtr0 += ppi->HFragPixels;
  1324. PixelsChangedPtr1 += ppi->HFragPixels;
  1325. PixelsChangedPtr2 += ppi->HFragPixels;
  1326. }
  1327. // Move on to next fragment.
  1328. DispFragPtr++;
  1329. }
  1330. }
  1331. else
  1332. {
  1333. // Scan through the row of pixels and calculate changed locals.
  1334. for ( i = 0; i < ppi->PlaneWidth; i += ppi->HFragPixels )
  1335. {
  1336. // Skip a group of 8 pixels if the assosciated fragment has no pixels of interest or
  1337. // if EBO is enabled and a breakout condition is met.
  1338. if ( *DispFragPtr == CANDIDATE_BLOCK )
  1339. {
  1340. for ( j = 0; j < ppi->HFragPixels; j++ )
  1341. {
  1342. changed_locals = 0;
  1343. // If the pixel itself has changed
  1344. if ( PixelsChangedPtr1[1] )
  1345. {
  1346. if ( RowType == FIRST_ROW )
  1347. {
  1348. if ( (i > 0) || (j > 0) )
  1349. {
  1350. changed_locals += PixelsChangedPtr1[0];
  1351. changed_locals += PixelsChangedPtr2[0];
  1352. }
  1353. changed_locals += PixelsChangedPtr2[1];
  1354. if ( (i + j) < LastRowIndex )
  1355. {
  1356. changed_locals += PixelsChangedPtr1[2];
  1357. changed_locals += PixelsChangedPtr2[2];
  1358. }
  1359. }
  1360. else // Last row
  1361. {
  1362. if ( (i > 0) || (j > 0 ) )
  1363. {
  1364. changed_locals += PixelsChangedPtr0[0];
  1365. changed_locals += PixelsChangedPtr1[0];
  1366. }
  1367. changed_locals += PixelsChangedPtr0[1];
  1368. if ( (i + j) < LastRowIndex )
  1369. {
  1370. changed_locals += PixelsChangedPtr0[2];
  1371. changed_locals += PixelsChangedPtr1[2];
  1372. }
  1373. }
  1374. // Store the number of changed locals
  1375. *ChLocalsPtr |= changed_locals;
  1376. }
  1377. // Increment to next pixel in the row
  1378. ChLocalsPtr++;
  1379. PixelsChangedPtr0++;
  1380. PixelsChangedPtr1++;
  1381. PixelsChangedPtr2++;
  1382. }
  1383. }
  1384. else
  1385. {
  1386. if ( *DispFragPtr > BLOCK_NOT_CODED )
  1387. {
  1388. ((UINT32 *)ChLocalsPtr)[0] = ((UINT32 *)ChlocalsDummyData)[0];
  1389. ((UINT32 *)ChLocalsPtr)[1] = ((UINT32 *)ChlocalsDummyData)[1];
  1390. }
  1391. // Step pointers
  1392. ChLocalsPtr += ppi->HFragPixels;
  1393. PixelsChangedPtr0 += ppi->HFragPixels;
  1394. PixelsChangedPtr1 += ppi->HFragPixels;
  1395. PixelsChangedPtr2 += ppi->HFragPixels;
  1396. }
  1397. // Move on to next fragment.
  1398. DispFragPtr++;
  1399. }
  1400. }
  1401. }
  1402. /****************************************************************************
  1403. *
  1404. * ROUTINE : NoiseScoreRow
  1405. *
  1406. * INPUTS : UINT8 * PixelMapPtr.
  1407. * INT16 * YUVDiffsPtr,
  1408. * UINT8 * PixelNoiseScorePtr
  1409. * UINT32 * FragScorePtr
  1410. * INT8 * DispFragPtr
  1411. * INT32 * RowDiffsPtr
  1412. *
  1413. * OUTPUTS : None.
  1414. *
  1415. * RETURNS :
  1416. *
  1417. * FUNCTION : Calculates the noise scores for a row of pixels.
  1418. *
  1419. * SPECIAL NOTES : None.
  1420. *
  1421. *
  1422. * ERRORS : None.
  1423. *
  1424. ****************************************************************************/
  1425. void NoiseScoreRow( PP_INSTANCE *ppi, UINT8 * PixelMapPtr, UINT8 * ChLocalsPtr,
  1426. INT16 * YUVDiffsPtr,
  1427. UINT8 * PixelNoiseScorePtr,
  1428. UINT32 * FragScorePtr,
  1429. INT8 * DispFragPtr,
  1430. INT32 * RowDiffsPtr )
  1431. {
  1432. INT32 i,j;
  1433. UINT8 changed_locals = 0;
  1434. INT32 Score;
  1435. UINT32 FragScore;
  1436. INT32 AbsDiff;
  1437. // For each pixel in the row
  1438. for ( i = 0; i < ppi->PlaneWidth; i += ppi->HFragPixels )
  1439. {
  1440. // Skip a group of 8 pixels if the assosciated fragment has no pixels of interest or
  1441. // if EBO is enabled and a breakout condition is met.
  1442. if ( *DispFragPtr == CANDIDATE_BLOCK )
  1443. {
  1444. // Reset the cumulative fragment score.
  1445. FragScore = 0;
  1446. // Pixels grouped along the row into fragments
  1447. for ( j = 0; j < ppi->HFragPixels; j++ )
  1448. {
  1449. if ( PixelMapPtr[j] )
  1450. {
  1451. AbsDiff = (INT32)( abs(YUVDiffsPtr[j]) );
  1452. changed_locals = ChLocalsPtr[j];
  1453. // Give this pixel a score based on changed locals and level of its own change.
  1454. Score = (1 + ((INT32)(changed_locals + ppi->NoiseScoreBoostTable[AbsDiff]) - ppi->NoiseSupLevel));
  1455. // For no zero scores adjust by a level based score multiplier.
  1456. if ( Score > 0 )
  1457. {
  1458. Score = (INT32)( (double)Score * ppi->AbsDiff_ScoreMultiplierTable[AbsDiff] );
  1459. if ( Score < 1 )
  1460. Score = 1;
  1461. }
  1462. else
  1463. {
  1464. // Set -ve values to 0
  1465. Score = 0;
  1466. // If there are no changed locals then clear the pixel changed flag and
  1467. // decrement the pixels changed in fragment count to speed later stages.
  1468. if ( changed_locals == 0 )
  1469. {
  1470. PixelMapPtr[j] = 0;
  1471. *RowDiffsPtr -= 1;
  1472. }
  1473. }
  1474. // Update the pixel scores etc.
  1475. PixelNoiseScorePtr[j] = (UINT8)Score;
  1476. FragScore += (UINT32)Score;
  1477. }
  1478. }
  1479. // Add fragment score (with plane correction factor) into main data structure
  1480. *FragScorePtr += (INT32)(FragScore * ppi->YUVPlaneCorrectionFactor);
  1481. // If score is greater than trip threshold then mark blcok for update.
  1482. if ( *FragScorePtr > ppi->BlockThreshold )
  1483. {
  1484. *DispFragPtr = BLOCK_CODED_LOW;
  1485. }
  1486. }
  1487. // Increment the various pointers
  1488. FragScorePtr++;
  1489. DispFragPtr++;
  1490. PixelNoiseScorePtr += ppi->HFragPixels;
  1491. PixelMapPtr += ppi->HFragPixels;
  1492. ChLocalsPtr += ppi->HFragPixels;
  1493. YUVDiffsPtr += ppi->HFragPixels;
  1494. }
  1495. }
  1496. /****************************************************************************
  1497. *
  1498. * ROUTINE : PrimaryEdgeScoreRow
  1499. *
  1500. * INPUTS : UINT8 * PixelMapPtr.
  1501. * INT16 * YUVDiffsPtr,
  1502. * UINT32 * FragScorePtr
  1503. * INT8 * DispFragPtr,
  1504. * UINT8 RowType
  1505. *
  1506. * OUTPUTS : None.
  1507. *
  1508. * RETURNS :
  1509. *
  1510. * FUNCTION : Calculates the primary edge scores for a row of pixels.
  1511. *
  1512. * SPECIAL NOTES : None.
  1513. *
  1514. *
  1515. * ERRORS : None.
  1516. *
  1517. ****************************************************************************/
  1518. void PrimaryEdgeScoreRow( PP_INSTANCE *ppi, UINT8 * ChangedLocalsPtr, INT16 * YUVDiffsPtr,
  1519. UINT8 * PixelNoiseScorePtr,
  1520. UINT32 * FragScorePtr,
  1521. INT8 * DispFragPtr,
  1522. UINT8 RowType )
  1523. {
  1524. UINT32 BodyNeighbours;
  1525. UINT32 AbsDiff;
  1526. UINT8 changed_locals = 0;
  1527. INT32 Score;
  1528. UINT32 FragScore;
  1529. UINT8 * CHLocalsPtr0;
  1530. UINT8 * CHLocalsPtr1;
  1531. UINT8 * CHLocalsPtr2;
  1532. INT32 i,j;
  1533. INT32 LastRowIndex = ppi->PlaneWidth - 1;
  1534. // Set up pointers into the current previous and next row of the changed locals data structure.
  1535. CHLocalsPtr0 = ChangedLocalsPtr - ppi->PlaneWidth;
  1536. if ( CHLocalsPtr0 < ppi->ChLocals )
  1537. CHLocalsPtr0 += ppi->ChLocalsCircularBufferSize;
  1538. CHLocalsPtr0 -= 1;
  1539. CHLocalsPtr1 = ChangedLocalsPtr - 1;
  1540. CHLocalsPtr2 = ChangedLocalsPtr + ppi->PlaneWidth;
  1541. if ( CHLocalsPtr2 >= (ppi->ChLocals + ppi->ChLocalsCircularBufferSize) )
  1542. CHLocalsPtr2 -= ppi->ChLocalsCircularBufferSize;
  1543. CHLocalsPtr2 -= 1;
  1544. /* The defining rule used here is as follows. */
  1545. /* An edge pixels has 3-5 changed locals. */
  1546. /* And one or more of these changed locals has itself got 7-8 changed locals. */
  1547. if ( RowType == NOT_EDGE_ROW )
  1548. {
  1549. /* Loop for all pixels in the row. */
  1550. for ( i = 0; i < ppi->PlaneWidth; i += ppi->HFragPixels )
  1551. {
  1552. // Does the fragment contain anything interesting to work with.
  1553. if ( *DispFragPtr == CANDIDATE_BLOCK )
  1554. {
  1555. // Reset the cumulative fragment score.
  1556. FragScore = 0;
  1557. // Pixels grouped along the row into fragments
  1558. for ( j = 0; j < ppi->HFragPixels; j++ )
  1559. {
  1560. // How many changed locals has the current pixel got.
  1561. changed_locals = ChangedLocalsPtr[j];
  1562. // Is the pixel a suitable candidate
  1563. if ( (changed_locals > 2) && (changed_locals < 6) )
  1564. {
  1565. // The pixel may qualify... have a closer look.
  1566. BodyNeighbours = 0;
  1567. // Count the number of "BodyNeighbours" .. Pixels
  1568. // that have 7 or more changed neighbours.
  1569. if ( (i > 0) || (j > 0 ) )
  1570. {
  1571. if ( CHLocalsPtr0[0] >= 7 )
  1572. BodyNeighbours++;
  1573. if ( CHLocalsPtr1[0] >= 7 )
  1574. BodyNeighbours++;
  1575. if ( CHLocalsPtr2[0] >= 7 )
  1576. BodyNeighbours++;
  1577. }
  1578. if ( CHLocalsPtr0[1] >= 7 )
  1579. BodyNeighbours++;
  1580. if ( CHLocalsPtr2[1] >= 7 )
  1581. BodyNeighbours++;
  1582. if ( (i + j) < LastRowIndex )
  1583. {
  1584. if ( CHLocalsPtr0[2] >= 7 )
  1585. BodyNeighbours++;
  1586. if ( CHLocalsPtr1[2] >= 7 )
  1587. BodyNeighbours++;
  1588. if ( CHLocalsPtr2[2] >= 7 )
  1589. BodyNeighbours++;
  1590. }
  1591. if ( BodyNeighbours > 0 )
  1592. {
  1593. AbsDiff = abs( YUVDiffsPtr[j] );
  1594. Score = (INT32)( (double)(BodyNeighbours * BodyNeighbourScore) *
  1595. ppi->AbsDiff_ScoreMultiplierTable[AbsDiff] );
  1596. if ( Score < 1 )
  1597. Score = 1;
  1598. /* Increment the score by a value determined by the number of body neighbours. */
  1599. PixelNoiseScorePtr[j] += (UINT8)Score;
  1600. FragScore += (UINT32)Score;
  1601. }
  1602. }
  1603. // Increment pointers into changed locals buffer
  1604. CHLocalsPtr0 ++;
  1605. CHLocalsPtr1 ++;
  1606. CHLocalsPtr2 ++;
  1607. }
  1608. // Add fragment score (with plane correction factor) into main data structure
  1609. *FragScorePtr += (INT32)(FragScore * ppi->YUVPlaneCorrectionFactor);
  1610. // If score is greater than trip threshold then mark blcok for update.
  1611. if ( *FragScorePtr > ppi->BlockThreshold )
  1612. {
  1613. *DispFragPtr = BLOCK_CODED_LOW;
  1614. }
  1615. }
  1616. else // Nothing to do for this fragment group
  1617. {
  1618. // Advance pointers into changed locals buffer
  1619. CHLocalsPtr0 += ppi->HFragPixels;
  1620. CHLocalsPtr1 += ppi->HFragPixels;
  1621. CHLocalsPtr2 += ppi->HFragPixels;
  1622. }
  1623. // Increment the various pointers
  1624. FragScorePtr++;
  1625. DispFragPtr++;
  1626. PixelNoiseScorePtr += ppi->HFragPixels;
  1627. ChangedLocalsPtr += ppi->HFragPixels;
  1628. YUVDiffsPtr += ppi->HFragPixels;
  1629. }
  1630. }
  1631. else // This is either the top or bottom row of pixels in a plane.
  1632. {
  1633. /* Loop for all pixels in the row. */
  1634. for ( i = 0; i < ppi->PlaneWidth; i += ppi->HFragPixels )
  1635. {
  1636. // Does the fragment contain anything interesting to work with.
  1637. if ( *DispFragPtr == CANDIDATE_BLOCK )
  1638. {
  1639. // Reset the cumulative fragment score.
  1640. FragScore = 0;
  1641. // Pixels grouped along the row into fragments
  1642. for ( j = 0; j < ppi->HFragPixels; j++ )
  1643. {
  1644. // How many changed locals has the current pixel got.
  1645. changed_locals = ChangedLocalsPtr[j];
  1646. // Is the pixel a suitable candidate
  1647. if ( (changed_locals > 2) && (changed_locals < 6) )
  1648. {
  1649. /* The pixel may qualify... have a closer look. */
  1650. BodyNeighbours = 0;
  1651. /* Count the number of "BodyNeighbours" .. Pixels
  1652. * that have 7 or more changed neighbours. */
  1653. if ( RowType == LAST_ROW )
  1654. {
  1655. // Test for cases where it could be the first pixel on the line
  1656. if ( (i > 0) || (j > 0) )
  1657. {
  1658. if ( CHLocalsPtr0[0] >= 7 )
  1659. BodyNeighbours++;
  1660. if ( CHLocalsPtr1[0] >= 7 )
  1661. BodyNeighbours++;
  1662. }
  1663. if ( CHLocalsPtr0[1] >= 7 )
  1664. BodyNeighbours++;
  1665. // Test for the end of line case
  1666. if ( (i + j) < LastRowIndex )
  1667. {
  1668. if ( CHLocalsPtr0[2] >= 7 )
  1669. BodyNeighbours++;
  1670. if ( CHLocalsPtr1[2] >= 7 )
  1671. BodyNeighbours++;
  1672. }
  1673. }
  1674. else // FIRST ROW
  1675. {
  1676. // Test for cases where it could be the first pixel on the line
  1677. if ( (i > 0) || (j > 0) )
  1678. {
  1679. if ( CHLocalsPtr1[0] >= 7 )
  1680. BodyNeighbours++;
  1681. if ( CHLocalsPtr2[0] >= 7 )
  1682. BodyNeighbours++;
  1683. }
  1684. // Test for the end of line case
  1685. if ( CHLocalsPtr2[1] >= 7 )
  1686. BodyNeighbours++;
  1687. if ( (i + j) < LastRowIndex )
  1688. {
  1689. if ( CHLocalsPtr1[2] >= 7 )
  1690. BodyNeighbours++;
  1691. if ( CHLocalsPtr2[2] >= 7 )
  1692. BodyNeighbours++;
  1693. }
  1694. }
  1695. // Allocate a score according to the number of Body neighbours.
  1696. if ( BodyNeighbours > 0 )
  1697. {
  1698. AbsDiff = abs( YUVDiffsPtr[j] );
  1699. Score = (INT32)( (double)(BodyNeighbours * BodyNeighbourScore) *
  1700. ppi->AbsDiff_ScoreMultiplierTable[AbsDiff] );
  1701. if ( Score < 1 )
  1702. Score = 1;
  1703. PixelNoiseScorePtr[j] += (UINT8)Score;
  1704. FragScore += (UINT32)Score;
  1705. }
  1706. }
  1707. // Increment pointers into changed locals buffer
  1708. CHLocalsPtr0 ++;
  1709. CHLocalsPtr1 ++;
  1710. CHLocalsPtr2 ++;
  1711. }
  1712. // Add fragment score (with plane correction factor) into main data structure
  1713. *FragScorePtr += (INT32)(FragScore * ppi->YUVPlaneCorrectionFactor);
  1714. // If score is greater than trip threshold then mark blcok for update.
  1715. if ( *FragScorePtr > ppi->BlockThreshold )
  1716. {
  1717. *DispFragPtr = BLOCK_CODED_LOW;
  1718. }
  1719. }
  1720. else // Nothing to do for this fragment group
  1721. {
  1722. // Advance pointers into changed locals buffer
  1723. CHLocalsPtr0 += ppi->HFragPixels;
  1724. CHLocalsPtr1 += ppi->HFragPixels;
  1725. CHLocalsPtr2 += ppi->HFragPixels;
  1726. }
  1727. // Increment the various pointers
  1728. FragScorePtr++;
  1729. DispFragPtr++;
  1730. PixelNoiseScorePtr += ppi->HFragPixels;
  1731. ChangedLocalsPtr += ppi->HFragPixels;
  1732. YUVDiffsPtr += ppi->HFragPixels;
  1733. }
  1734. }
  1735. }
  1736. /****************************************************************************
  1737. *
  1738. * ROUTINE : LineSearchScoreRow
  1739. *
  1740. * INPUTS : UINT8 * ChangedLocalsPtr.
  1741. * INT16 * YUVDiffsPtr,
  1742. * UINT32 * FragScorePtr
  1743. * UINT8 RowNumber
  1744. *
  1745. * OUTPUTS : None.
  1746. *
  1747. * RETURNS :
  1748. *
  1749. * FUNCTION : Calculates the line match scores for a row of pixels.
  1750. *
  1751. * SPECIAL NOTES : None.
  1752. *
  1753. *
  1754. * ERRORS : None.
  1755. *
  1756. ****************************************************************************/
  1757. void LineSearchScoreRow( PP_INSTANCE *ppi, UINT8 * ChangedLocalsPtr, INT16 * YUVDiffsPtr,
  1758. UINT8 * PixelNoiseScorePtr,
  1759. UINT32 * FragScorePtr,
  1760. INT8 * DispFragPtr,
  1761. INT32 RowNumber )
  1762. {
  1763. UINT32 AbsDiff;
  1764. UINT8 changed_locals = 0;
  1765. INT32 Score;
  1766. UINT32 FragScore;
  1767. INT32 i,j;
  1768. /* The defining rule used here is as follows. */
  1769. /* An edge pixels has 2-5 changed locals. */
  1770. /* And one or more of these changed locals has itself got 7-8 changed locals. */
  1771. /* Loop for all pixels in the row. */
  1772. for ( i = 0; i < ppi->PlaneWidth; i += ppi->HFragPixels )
  1773. {
  1774. // Does the fragment contain anything interesting to work with.
  1775. if ( *DispFragPtr == CANDIDATE_BLOCK )
  1776. {
  1777. // Reset the cumulative fragment score.
  1778. FragScore = 0;
  1779. // Pixels grouped along the row into fragments
  1780. for ( j = 0; j < ppi->HFragPixels; j++ )
  1781. {
  1782. // How many changed locals has the current pixel got.
  1783. changed_locals = ChangedLocalsPtr[j];
  1784. // Is the pixel a suitable candidate for edge enhancement
  1785. if ( (changed_locals > 1) && (changed_locals < 6) &&
  1786. (PixelNoiseScorePtr[j] < LineSearchTripTresh) )
  1787. {
  1788. Score = (INT32)LineSearchScorePixel( ppi, &ChangedLocalsPtr[j], RowNumber, i+j );
  1789. if ( Score )
  1790. {
  1791. AbsDiff = abs( YUVDiffsPtr[j] );
  1792. Score = (INT32)( (double)Score * ppi->AbsDiff_ScoreMultiplierTable[AbsDiff] );
  1793. if ( Score < 1 )
  1794. Score = 1;
  1795. PixelNoiseScorePtr[j] += (UINT8)Score;
  1796. FragScore += (UINT32)Score;
  1797. }
  1798. }
  1799. }
  1800. // Add fragment score (with plane correction factor) into main data structure
  1801. *FragScorePtr += (INT32)(FragScore * ppi->YUVPlaneCorrectionFactor);
  1802. // If score is greater than trip threshold then mark blcok for update.
  1803. if ( *FragScorePtr > ppi->BlockThreshold )
  1804. {
  1805. *DispFragPtr = BLOCK_CODED_LOW;
  1806. }
  1807. }
  1808. // Increment the various pointers
  1809. FragScorePtr++;
  1810. DispFragPtr++;
  1811. PixelNoiseScorePtr += ppi->HFragPixels;
  1812. ChangedLocalsPtr += ppi->HFragPixels;
  1813. YUVDiffsPtr += ppi->HFragPixels;
  1814. }
  1815. }
  1816. /****************************************************************************
  1817. *
  1818. * ROUTINE : LineSearchScorePixel
  1819. *
  1820. * INPUTS : UINT32 ChangedLocalsPtr (this pixels index.)
  1821. * INT32 RowNumber (Row number)
  1822. * INT32 ColNumber (Column number within a row)
  1823. *
  1824. * OUTPUTS : None.
  1825. *
  1826. * RETURNS : A pixel line search score
  1827. *
  1828. * FUNCTION : Returns a Line Search score for a pixel.
  1829. *
  1830. * SPECIAL NOTES : None.
  1831. *
  1832. *
  1833. * ERRORS : None.
  1834. *
  1835. ****************************************************************************/
  1836. UINT8 LineSearchScorePixel( PP_INSTANCE *ppi, UINT8 * ChangedLocalsPtr, INT32 RowNumber, INT32 ColNumber )
  1837. {
  1838. UINT32 line_length = 0;
  1839. UINT32 line_length2 = 0;
  1840. UINT32 line_length_score = 0;
  1841. UINT32 tmp_line_length = 0;
  1842. UINT32 tmp_line_length2 = 0;
  1843. // Look UP and Down
  1844. PixelLineSearch( ppi, ChangedLocalsPtr, RowNumber, ColNumber, UP, &tmp_line_length );
  1845. if (tmp_line_length < ppi->MaxLineSearchLen)
  1846. {
  1847. // Look DOWN
  1848. PixelLineSearch( ppi, ChangedLocalsPtr, RowNumber, ColNumber, DOWN, &tmp_line_length2 );
  1849. line_length = tmp_line_length + tmp_line_length2 - 1;
  1850. if ( line_length > ppi->MaxLineSearchLen )
  1851. line_length = ppi->MaxLineSearchLen;
  1852. }
  1853. else
  1854. line_length = tmp_line_length;
  1855. // If no max length line found then look left and right
  1856. if ( line_length < ppi->MaxLineSearchLen )
  1857. {
  1858. tmp_line_length = 0;
  1859. tmp_line_length2 = 0;
  1860. PixelLineSearch( ppi, ChangedLocalsPtr, RowNumber, ColNumber, LEFT, &tmp_line_length );
  1861. if (tmp_line_length < ppi->MaxLineSearchLen)
  1862. {
  1863. PixelLineSearch( ppi, ChangedLocalsPtr, RowNumber, ColNumber, RIGHT, &tmp_line_length2 );
  1864. line_length2 = tmp_line_length + tmp_line_length2 - 1;
  1865. if ( line_length2 > ppi->MaxLineSearchLen )
  1866. line_length2 = ppi->MaxLineSearchLen;
  1867. }
  1868. else
  1869. line_length2 = tmp_line_length;
  1870. }
  1871. /* Take the largest line length */
  1872. if ( line_length2 > line_length )
  1873. line_length = line_length2;
  1874. /* Create line length score */
  1875. line_length_score = LineLengthScores[line_length];
  1876. return (UINT8)line_length_score;
  1877. }
  1878. /****************************************************************************
  1879. *
  1880. * ROUTINE : PixelLineSearch
  1881. *
  1882. * INPUTS : UINT8 * ChangedLocalsPtr (Map entry for this pixel)
  1883. * INT32 RowNumber (Row number)
  1884. * INT32 ColNumber (Column number within a row)
  1885. * UINT8 direction
  1886. *
  1887. * OUTPUTS : UINT8 * line_length
  1888. *
  1889. * RETURNS : None
  1890. *
  1891. * FUNCTION : Recursive function for tracking along a line of pixels
  1892. * obeying a specific set of rules
  1893. *
  1894. * SPECIAL NOTES : None.
  1895. *
  1896. *
  1897. * ERRORS : None.
  1898. *
  1899. ****************************************************************************/
  1900. void PixelLineSearch( PP_INSTANCE *ppi, UINT8 * ChangedLocalsPtr, INT32 RowNumber, INT32 ColNumber, UINT8 direction, UINT32 * line_length )
  1901. {
  1902. // Exit if the pixel does not qualify or we have fallen off the edge
  1903. // of either the image plane or the row.
  1904. if ( ((*ChangedLocalsPtr) <= 1) ||
  1905. ((*ChangedLocalsPtr) >= 6) ||
  1906. (RowNumber < 0) ||
  1907. (RowNumber >= ppi->PlaneHeight) ||
  1908. (ColNumber < 0) ||
  1909. (ColNumber >= ppi->PlaneWidth) )
  1910. {
  1911. // If not then it isn't part of any line.
  1912. return;
  1913. }
  1914. if (*line_length < ppi->MaxLineSearchLen)
  1915. {
  1916. UINT32 TmpLineLength;
  1917. UINT32 BestLineLength;
  1918. UINT8 * search_ptr;
  1919. // Increment the line length to include this pixel.
  1920. *line_length += 1;
  1921. BestLineLength = *line_length;
  1922. // Continue search
  1923. // up
  1924. if ( direction == UP )
  1925. {
  1926. TmpLineLength = *line_length;
  1927. search_ptr = ChangedLocalsPtr - ppi->PlaneWidth;
  1928. if ( search_ptr < ppi->ChLocals )
  1929. search_ptr += ppi->ChLocalsCircularBufferSize;
  1930. PixelLineSearch( ppi, search_ptr, RowNumber - 1, ColNumber, direction, &TmpLineLength );
  1931. if ( TmpLineLength > BestLineLength )
  1932. BestLineLength = TmpLineLength;
  1933. }
  1934. // up and left
  1935. if ( (BestLineLength < ppi->MaxLineSearchLen) && ((direction == UP) || (direction == LEFT)) )
  1936. {
  1937. TmpLineLength = *line_length;
  1938. search_ptr = ChangedLocalsPtr - ppi->PlaneWidth;
  1939. if ( search_ptr < ppi->ChLocals )
  1940. search_ptr += ppi->ChLocalsCircularBufferSize;
  1941. search_ptr -= 1;
  1942. PixelLineSearch( ppi, search_ptr, RowNumber - 1, ColNumber - 1, direction, &TmpLineLength );
  1943. if ( TmpLineLength > BestLineLength )
  1944. BestLineLength = TmpLineLength;
  1945. }
  1946. // up and right
  1947. if ( (BestLineLength < ppi->MaxLineSearchLen) && ((direction == UP) || (direction == RIGHT)) )
  1948. {
  1949. TmpLineLength = *line_length;
  1950. search_ptr = ChangedLocalsPtr - ppi->PlaneWidth;
  1951. if ( search_ptr < ppi->ChLocals )
  1952. search_ptr += ppi->ChLocalsCircularBufferSize;
  1953. search_ptr += 1;
  1954. PixelLineSearch( ppi, search_ptr, RowNumber - 1, ColNumber + 1, direction, &TmpLineLength );
  1955. if ( TmpLineLength > BestLineLength )
  1956. BestLineLength = TmpLineLength;
  1957. }
  1958. // left
  1959. if ( (BestLineLength < ppi->MaxLineSearchLen) && ( direction == LEFT ) )
  1960. {
  1961. TmpLineLength = *line_length;
  1962. PixelLineSearch( ppi, ChangedLocalsPtr - 1, RowNumber, ColNumber - 1, direction, &TmpLineLength );
  1963. if ( TmpLineLength > BestLineLength )
  1964. BestLineLength = TmpLineLength;
  1965. }
  1966. // right
  1967. if ( (BestLineLength < ppi->MaxLineSearchLen) && ( direction == RIGHT ) )
  1968. {
  1969. TmpLineLength = *line_length;
  1970. PixelLineSearch( ppi, ChangedLocalsPtr + 1, RowNumber, ColNumber + 1, direction, &TmpLineLength );
  1971. if ( TmpLineLength > BestLineLength )
  1972. BestLineLength = TmpLineLength;
  1973. }
  1974. // Down...
  1975. if ( BestLineLength < ppi->MaxLineSearchLen )
  1976. {
  1977. TmpLineLength = *line_length;
  1978. // down
  1979. if ( direction == DOWN )
  1980. {
  1981. search_ptr = ChangedLocalsPtr + ppi->PlaneWidth;
  1982. if ( search_ptr >= (ppi->ChLocals + ppi->ChLocalsCircularBufferSize) )
  1983. search_ptr -= ppi->ChLocalsCircularBufferSize;
  1984. PixelLineSearch( ppi, search_ptr, RowNumber + 1, ColNumber, direction, &TmpLineLength );
  1985. if ( TmpLineLength > BestLineLength )
  1986. BestLineLength = TmpLineLength;
  1987. }
  1988. // down and left
  1989. if ( (BestLineLength < ppi->MaxLineSearchLen) && ((direction == DOWN) || (direction == LEFT)) )
  1990. {
  1991. TmpLineLength = *line_length;
  1992. search_ptr = ChangedLocalsPtr + ppi->PlaneWidth;
  1993. if ( search_ptr >= (ppi->ChLocals + ppi->ChLocalsCircularBufferSize) )
  1994. search_ptr -= ppi->ChLocalsCircularBufferSize;
  1995. search_ptr -= 1;
  1996. PixelLineSearch( ppi, search_ptr, RowNumber + 1, ColNumber - 1, direction, &TmpLineLength );
  1997. if ( TmpLineLength > BestLineLength )
  1998. BestLineLength = TmpLineLength;
  1999. }
  2000. // down and right
  2001. if ( (BestLineLength < ppi->MaxLineSearchLen) && ((direction == DOWN) || (direction == RIGHT)) )
  2002. {
  2003. TmpLineLength = *line_length;
  2004. search_ptr = ChangedLocalsPtr + ppi->PlaneWidth;
  2005. if ( search_ptr >= (ppi->ChLocals + ppi->ChLocalsCircularBufferSize) )
  2006. search_ptr -= ppi->ChLocalsCircularBufferSize;
  2007. search_ptr += 1;
  2008. PixelLineSearch( ppi, search_ptr, RowNumber + 1, ColNumber + 1, direction, &TmpLineLength );
  2009. if ( TmpLineLength > BestLineLength )
  2010. BestLineLength = TmpLineLength;
  2011. }
  2012. }
  2013. // Note the search value for this pixel.
  2014. *line_length = BestLineLength;
  2015. }
  2016. }
  2017. /****************************************************************************
  2018. *
  2019. * ROUTINE : ScanCalcPixelIndexTable
  2020. *
  2021. * INPUTS : Nonex.
  2022. *
  2023. * OUTPUTS : None.
  2024. *
  2025. * RETURNS : None
  2026. *
  2027. * FUNCTION : Initialises the pixel index table used in the scan module.
  2028. *
  2029. * SPECIAL NOTES : None.
  2030. *
  2031. *
  2032. * ERRORS : None.
  2033. *
  2034. ****************************************************************************/
  2035. void ScanCalcPixelIndexTable(PP_INSTANCE *ppi)
  2036. {
  2037. UINT32 i;
  2038. UINT32 * PixelIndexTablePtr = ppi->ScanPixelIndexTable;
  2039. /* If appropriate add on extra inices for U and V planes. */
  2040. for ( i = 0; i < (ppi->ScanYPlaneFragments); i++ )
  2041. {
  2042. PixelIndexTablePtr[ i ] = ((i / ppi->ScanHFragments) * ppi->VFragPixels * ppi->ScanConfig.VideoFrameWidth);
  2043. PixelIndexTablePtr[ i ] += ((i % ppi->ScanHFragments) * ppi->HFragPixels);
  2044. }
  2045. PixelIndexTablePtr = &ppi->ScanPixelIndexTable[ppi->ScanYPlaneFragments];
  2046. for ( i = 0; i < (ppi->ScanUVPlaneFragments * 2); i++ )
  2047. {
  2048. PixelIndexTablePtr[ i ] = ((i / (ppi->ScanHFragments >> 1) ) *
  2049. (ppi->VFragPixels * (ppi->ScanConfig.VideoFrameWidth >> 1)) );
  2050. PixelIndexTablePtr[ i ] += ((i % (ppi->ScanHFragments >> 1) ) * ppi->HFragPixels) + ppi->YFramePixels;
  2051. }
  2052. }
  2053. /****************************************************************************
  2054. *
  2055. * ROUTINE : SetVcapLevelOffset
  2056. *
  2057. * INPUTS : None
  2058. *
  2059. * OUTPUTS : None.
  2060. *
  2061. * RETURNS : None.
  2062. *
  2063. * FUNCTION : Configures VCAP parameters to one of a set of pre-defined
  2064. * alternatives.
  2065. *
  2066. * SPECIAL NOTES : None.
  2067. *
  2068. *
  2069. * ERRORS : None.
  2070. *
  2071. ****************************************************************************/
  2072. void SetVcapLevelOffset( PP_INSTANCE *ppi, INT32 Level )
  2073. {
  2074. switch ( Level )
  2075. {
  2076. case 0:
  2077. ppi->SRFGreyThresh = 1;
  2078. ppi->SRFColThresh = 1;
  2079. ppi->NoiseSupLevel = 2;
  2080. ppi->SgcLevelThresh = 1;
  2081. ppi->SuvcLevelThresh = 1;
  2082. ppi->GrpLowSadThresh = 6;
  2083. ppi->GrpHighSadThresh = 24;
  2084. ppi->PrimaryBlockThreshold = 2;
  2085. ppi->SgcThresh = 10;
  2086. ppi->PAKEnabled = FALSE;
  2087. break;
  2088. case 1:
  2089. ppi->SRFGreyThresh = 2;
  2090. ppi->SRFColThresh = 2;
  2091. ppi->NoiseSupLevel = 2;
  2092. ppi->SgcLevelThresh = 2;
  2093. ppi->SuvcLevelThresh = 2;
  2094. ppi->GrpLowSadThresh = 8;
  2095. ppi->GrpHighSadThresh = 32;
  2096. ppi->PrimaryBlockThreshold = 5;
  2097. ppi->SgcThresh = 12;
  2098. ppi->PAKEnabled = TRUE;
  2099. break;
  2100. case 2: // Default VP3 settings
  2101. ppi->SRFGreyThresh = 3;
  2102. ppi->SRFColThresh = 3;
  2103. ppi->NoiseSupLevel = 2;
  2104. ppi->SgcLevelThresh = 2;
  2105. ppi->SuvcLevelThresh = 2;
  2106. ppi->GrpLowSadThresh = 8;
  2107. ppi->GrpHighSadThresh = 32;
  2108. ppi->PrimaryBlockThreshold = 5;
  2109. ppi->SgcThresh = 16;
  2110. ppi->PAKEnabled = TRUE;
  2111. break;
  2112. case 3:
  2113. ppi->SRFGreyThresh = 4;
  2114. ppi->SRFColThresh = 4;
  2115. ppi->NoiseSupLevel = 3;
  2116. ppi->SgcLevelThresh = 3;
  2117. ppi->SuvcLevelThresh = 3;
  2118. ppi->GrpLowSadThresh = 10;
  2119. ppi->GrpHighSadThresh = 48;
  2120. ppi->PrimaryBlockThreshold = 5;
  2121. ppi->SgcThresh = 18;
  2122. ppi->PAKEnabled = TRUE;
  2123. break;
  2124. case 4:
  2125. ppi->SRFGreyThresh = 5;
  2126. ppi->SRFColThresh = 5;
  2127. ppi->NoiseSupLevel = 3;
  2128. ppi->SgcLevelThresh = 4;
  2129. ppi->SuvcLevelThresh = 4;
  2130. ppi->GrpLowSadThresh = 12;
  2131. ppi->GrpHighSadThresh = 48;
  2132. ppi->PrimaryBlockThreshold = 5;
  2133. ppi->SgcThresh = 20;
  2134. ppi->PAKEnabled = TRUE;
  2135. break;
  2136. case 5: // Default live narrow band settings
  2137. ppi->SRFGreyThresh = 6;
  2138. ppi->SRFColThresh = 6;
  2139. ppi->NoiseSupLevel = 3;
  2140. ppi->SgcLevelThresh = 4;
  2141. ppi->SuvcLevelThresh = 4;
  2142. ppi->GrpLowSadThresh = 12;
  2143. ppi->GrpHighSadThresh = 64;
  2144. ppi->PrimaryBlockThreshold = 10;
  2145. ppi->SgcThresh = 24;
  2146. ppi->PAKEnabled = TRUE;
  2147. break;
  2148. case 6: // Default live narrow band settings
  2149. ppi->SRFGreyThresh = 6;
  2150. ppi->SRFColThresh = 7;
  2151. ppi->NoiseSupLevel = 3;
  2152. ppi->SgcLevelThresh = 4;
  2153. ppi->SuvcLevelThresh = 4;
  2154. ppi->GrpLowSadThresh = 12;
  2155. ppi->GrpHighSadThresh = 64;
  2156. ppi->PrimaryBlockThreshold = 10;
  2157. ppi->SgcThresh = 24;
  2158. ppi->PAKEnabled = TRUE;
  2159. break;
  2160. default:
  2161. ppi->SRFGreyThresh = 3;
  2162. ppi->SRFColThresh = 3;
  2163. ppi->NoiseSupLevel = 2;
  2164. ppi->SgcLevelThresh = 2;
  2165. ppi->SuvcLevelThresh = 2;
  2166. ppi->GrpLowSadThresh = 10;
  2167. ppi->GrpHighSadThresh = 32;
  2168. ppi->PrimaryBlockThreshold = 5;
  2169. ppi->SgcThresh = 16;
  2170. ppi->PAKEnabled = TRUE;
  2171. break;
  2172. }
  2173. }
  2174. /****************************************************************************
  2175. *
  2176. * ROUTINE : GetLocalVarianceMultiplier
  2177. *
  2178. * INPUTS : INT16 * MasterYUVDiffPtr.
  2179. * UINT32 PlaneLineLength
  2180. *
  2181. *
  2182. * OUTPUTS : None.
  2183. *
  2184. * RETURNS : Pixel variance
  2185. *
  2186. * FUNCTION : Calculates a score correction based on local variance
  2187. *
  2188. * SPECIAL NOTES : None.
  2189. *
  2190. *
  2191. * ERRORS : None.
  2192. *
  2193. ****************************************************************************/
  2194. double GetLocalVarianceMultiplier( PP_INSTANCE *ppi, INT16 * MasterYUVDiffPtr, UINT32 PlaneLineLength )
  2195. {
  2196. INT32 XSum=0;
  2197. INT32 XXSum=0;
  2198. INT32 DiffVal;
  2199. double LocalVariance;
  2200. double VarMultiplier;
  2201. INT16 * YUVDiffPtr;
  2202. // Previous row (wrap back to top of buffer if necessary
  2203. YUVDiffPtr = MasterYUVDiffPtr - PlaneLineLength;
  2204. if ( YUVDiffPtr < ppi->yuv_differences )
  2205. YUVDiffPtr += ppi->YuvDiffsCircularBufferSize;
  2206. DiffVal = YUVDiffPtr[-1];
  2207. XSum += DiffVal;
  2208. XXSum += DiffVal * DiffVal;
  2209. DiffVal = YUVDiffPtr[0];
  2210. XSum += DiffVal;
  2211. XXSum += DiffVal * DiffVal;
  2212. DiffVal = YUVDiffPtr[1];
  2213. XSum += DiffVal;
  2214. XXSum += DiffVal * DiffVal;
  2215. // Current row
  2216. YUVDiffPtr = MasterYUVDiffPtr;
  2217. DiffVal = YUVDiffPtr[-1];
  2218. XSum += DiffVal;
  2219. XXSum += DiffVal * DiffVal;
  2220. DiffVal = YUVDiffPtr[0];
  2221. XSum += DiffVal;
  2222. XXSum += DiffVal * DiffVal;
  2223. DiffVal = YUVDiffPtr[1];
  2224. XSum += DiffVal;
  2225. XXSum += DiffVal * DiffVal;
  2226. // Last row (wrap back around if neeeded
  2227. YUVDiffPtr = MasterYUVDiffPtr + PlaneLineLength;
  2228. if ( YUVDiffPtr > &ppi->yuv_differences[ppi->YuvDiffsCircularBufferSize] )
  2229. YUVDiffPtr -= ppi->YuvDiffsCircularBufferSize;
  2230. DiffVal = YUVDiffPtr[-1];
  2231. XSum += DiffVal;
  2232. XXSum += DiffVal * DiffVal;
  2233. DiffVal = YUVDiffPtr[0];
  2234. XSum += DiffVal;
  2235. XXSum += DiffVal * DiffVal;
  2236. DiffVal = YUVDiffPtr[1];
  2237. XSum += DiffVal;
  2238. XXSum += DiffVal * DiffVal;
  2239. // Compute and return population variance as mis-match metric.
  2240. LocalVariance = ((double)XXSum * 0.1111) - ((double)XSum * (double)XSum * 0.012346);
  2241. if ( LocalVariance > 2 * LowVarianceThresh )
  2242. {
  2243. VarMultiplier = 1.5;
  2244. }
  2245. else if ( LocalVariance > LowVarianceThresh )
  2246. {
  2247. VarMultiplier = 1.0;
  2248. }
  2249. else
  2250. {
  2251. VarMultiplier = 0.5;
  2252. }
  2253. return VarMultiplier;
  2254. }
  2255. /****************************************************************************
  2256. *
  2257. * ROUTINE : ScalarRowSAD
  2258. *
  2259. * INPUTS : UINT8 * Src1
  2260. * UINT8 * Src2
  2261. *
  2262. *
  2263. * OUTPUTS : None.
  2264. *
  2265. * RETURNS : A Sum of the absolute difference value for a row of 4 pixels
  2266. *
  2267. * FUNCTION : Calculates a sum of the absolute difference for one or two groups of
  2268. * of 4 pixels. If two groups it returns the larger of the two values.
  2269. *
  2270. *
  2271. * SPECIAL NOTES : None.
  2272. *
  2273. *
  2274. * ERRORS : None.
  2275. *
  2276. ****************************************************************************/
  2277. UINT32 ScalarRowSAD( UINT8 * Src1, UINT8 * Src2 )
  2278. {
  2279. UINT32 SadValue;
  2280. UINT32 SadValue1;
  2281. SadValue = abs( Src1[0] - Src2[0] ) + abs( Src1[1] - Src2[1] ) +
  2282. abs( Src1[2] - Src2[2] ) + abs( Src1[3] - Src2[3] );
  2283. SadValue1 = abs( Src1[4] - Src2[4] ) + abs( Src1[5] - Src2[5] ) +
  2284. abs( Src1[6] - Src2[6] ) + abs( Src1[7] - Src2[7] );
  2285. SadValue = ( SadValue > SadValue1 ) ? SadValue : SadValue1;
  2286. return SadValue;
  2287. }
  2288. /****************************************************************************
  2289. *
  2290. * ROUTINE : ScalarColSAD
  2291. *
  2292. * INPUTS : PP_INSTANCE *ppi
  2293. * UINT8 * Src1
  2294. * UINT8 * Src2
  2295. *
  2296. *
  2297. * OUTPUTS : None.
  2298. *
  2299. * RETURNS : The maximum 4 pixel column SAD for an 8x8 block.
  2300. *
  2301. * FUNCTION : Calculates a SAD for each 4 pixel column in a block and
  2302. * returns the MAX value.
  2303. *
  2304. * SPECIAL NOTES : None.
  2305. *
  2306. *
  2307. * ERRORS : None.
  2308. *
  2309. ****************************************************************************/
  2310. UINT32 ScalarColSAD( PP_INSTANCE *ppi, UINT8 * Src1, UINT8 * Src2 )
  2311. {
  2312. UINT32 SadValue[8] = {0,0,0,0,0,0,0,0};
  2313. UINT32 SadValue2[8] = {0,0,0,0,0,0,0,0};
  2314. UINT32 MaxSad = 0;
  2315. UINT32 i;
  2316. for ( i = 0; i < 4; i++ )
  2317. {
  2318. SadValue[0] += abs(Src1[0] - Src2[0]);
  2319. SadValue[1] += abs(Src1[1] - Src2[1]);
  2320. SadValue[2] += abs(Src1[2] - Src2[2]);
  2321. SadValue[3] += abs(Src1[3] - Src2[3]);
  2322. SadValue[4] += abs(Src1[4] - Src2[4]);
  2323. SadValue[5] += abs(Src1[5] - Src2[5]);
  2324. SadValue[6] += abs(Src1[6] - Src2[6]);
  2325. SadValue[7] += abs(Src1[7] - Src2[7]);
  2326. Src1 += ppi->PlaneStride;
  2327. Src2 += ppi->PlaneStride;
  2328. }
  2329. for ( i = 0; i < 4; i++ )
  2330. {
  2331. SadValue2[0] += abs(Src1[0] - Src2[0]);
  2332. SadValue2[1] += abs(Src1[1] - Src2[1]);
  2333. SadValue2[2] += abs(Src1[2] - Src2[2]);
  2334. SadValue2[3] += abs(Src1[3] - Src2[3]);
  2335. SadValue2[4] += abs(Src1[4] - Src2[4]);
  2336. SadValue2[5] += abs(Src1[5] - Src2[5]);
  2337. SadValue2[6] += abs(Src1[6] - Src2[6]);
  2338. SadValue2[7] += abs(Src1[7] - Src2[7]);
  2339. Src1 += ppi->PlaneStride;
  2340. Src2 += ppi->PlaneStride;
  2341. }
  2342. for ( i = 0; i < 8; i++ )
  2343. {
  2344. if ( SadValue[i] > MaxSad )
  2345. MaxSad = SadValue[i];
  2346. if ( SadValue2[i] > MaxSad )
  2347. MaxSad = SadValue2[i];
  2348. }
  2349. return MaxSad;
  2350. }
  2351. /****************************************************************************
  2352. *
  2353. * ROUTINE : ApplyPakLowPass
  2354. *
  2355. * INPUTS : UINT8 * SrcPtr
  2356. * central point in kernel.
  2357. * OUTPUTS : None.
  2358. *
  2359. * RETURNS : Filtered value.
  2360. *
  2361. * FUNCTION : Applies a moderate low pass filter at the given location.
  2362. *
  2363. * SPECIAL NOTES : None.
  2364. *
  2365. *
  2366. * ERRORS : None.
  2367. *
  2368. ****************************************************************************/
  2369. UINT8 ApplyPakLowPass( PP_INSTANCE *ppi, UINT8 * SrcPtr )
  2370. {
  2371. UINT8 * SrcPtr1 = SrcPtr - 1;
  2372. UINT8 * SrcPtr0 = SrcPtr1 - ppi->PlaneStride; // Note the use of stride not width.
  2373. UINT8 * SrcPtr2 = SrcPtr1 + ppi->PlaneStride;
  2374. return (UINT8)( ( (UINT32)SrcPtr0[0] + (UINT32)SrcPtr0[1] + (UINT32)SrcPtr0[2] +
  2375. (UINT32)SrcPtr1[0] + (UINT32)SrcPtr1[2] +
  2376. (UINT32)SrcPtr2[0] + (UINT32)SrcPtr2[1] + (UINT32)SrcPtr2[2] ) >> 3 );
  2377. }