postproc.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796
  1. /***************************************************************************
  2. *
  3. * Module Title : PostProc.c
  4. *
  5. * Description : Post Processing
  6. *
  7. ***************************************************************************/
  8. #define STRICT /* Strict type checking */
  9. /****************************************************************************
  10. * Header Files
  11. ****************************************************************************/
  12. #include "postp.h"
  13. #include "duck_mem.h"
  14. #include "stdlib.h"
  15. #include <math.h>
  16. #include <stddef.h>
  17. /****************************************************************************
  18. * Macros
  19. ****************************************************************************/
  20. #define Clamp255(x) (unsigned char) ( (x) < 0 ? 0 : ( (x) <= 255 ? (x) : 255 ) )
  21. // TODO: benski> need better checks for other compilers
  22. #if defined(_M_AMD64) || defined(__LP64__)
  23. #define ROUNDUP32(X) ( ( ( (uintptr_t) X ) + 31 )&( 0xFFFFFFFFFFFFFFE0 ) )
  24. #else //#elif //defined(_M_IX86)
  25. #define ROUNDUP32(X) ( ( ( (unsigned long) X ) + 31 )&( 0xFFFFFFE0 ) )
  26. #endif
  27. /****************************************************************************
  28. * Imports
  29. ****************************************************************************/
  30. extern void SimpleDeblockFrame(POSTPROC_INSTANCE *ppi, UINT8* SrcBuffer, UINT8* DestBuffer);
  31. extern void UpdateUMVBorder( POSTPROC_INSTANCE *ppi, UINT8 * DestReconPtr);
  32. extern void PostProcMachineSpecificConfig(UINT32 );
  33. extern void DeringFrame(POSTPROC_INSTANCE *ppi, UINT8 *Src, UINT8 *Dst);
  34. extern void DeringFrameInterlaced(POSTPROC_INSTANCE *ppi, UINT8 *Src, UINT8 *Dst);
  35. extern void DeblockFrame(POSTPROC_INSTANCE *ppi, UINT8 *SourceBuffer, UINT8 *DestinationBuffer);
  36. extern void DeblockFrameUsing7TapFilter(POSTPROC_INSTANCE *ppi, UINT8 *SourceBuffer, UINT8 *DestinationBuffer);
  37. extern void DeblockFrameInterlaced(POSTPROC_INSTANCE *ppi, UINT8 *SourceBuffer, UINT8 *DestinationBuffer);
  38. extern UINT32 DeringModifierV1[ Q_TABLE_SIZE ];
  39. extern UINT32 DeringModifierV2[ Q_TABLE_SIZE ];
  40. extern UINT32 *DCQuantScaleV2;
  41. extern UINT32 *DCQuantScaleUV;
  42. extern UINT32 *DCQuantScaleV1;
  43. extern UINT32 LoopFilterLimitValuesVp4[Q_TABLE_SIZE];
  44. extern UINT32 LoopFilterLimitValuesVp5[Q_TABLE_SIZE];
  45. extern UINT32 LoopFilterLimitValuesVp6[Q_TABLE_SIZE];
  46. extern UINT32 DeblockLimitValuesVp4[Q_TABLE_SIZE];
  47. extern UINT32 DeblockLimitValuesVp5[Q_TABLE_SIZE];
  48. extern UINT32 DeblockLimitValuesVp6[Q_TABLE_SIZE];
  49. extern UINT32 *LoopFilterLimitValuesV2;
  50. extern UINT32 *DeblockLimitValuesV2;
  51. /****************************************************************************
  52. * Exports
  53. ****************************************************************************/
  54. UINT8 LimitVal_VP31[VAL_RANGE * 3];
  55. void (*FilteringVert_12)(UINT32 QValue,UINT8 * Src, INT32 Pitch);
  56. void (*FilteringHoriz_12)(UINT32 QValue,UINT8 * Src, INT32 Pitch);
  57. void (*FilteringVert_8)(UINT32 QValue,UINT8 * Src, INT32 Pitch);
  58. void (*FilteringHoriz_8)(UINT32 QValue,UINT8 * Src, INT32 Pitch);
  59. void (*VerticalBand_4_5_Scale)(unsigned char * dest,unsigned int destPitch,unsigned int destWidth);
  60. void (*LastVerticalBand_4_5_Scale)(unsigned char * dest,unsigned int destPitch,unsigned int destWidth);
  61. void (*VerticalBand_3_5_Scale)(unsigned char * dest,unsigned int destPitch,unsigned int destWidth);
  62. void (*LastVerticalBand_3_5_Scale)(unsigned char * dest,unsigned int destPitch,unsigned int destWidth);
  63. void (*HorizontalLine_1_2_Scale)(const unsigned char * source,unsigned int sourceWidth,unsigned char * dest,unsigned int destWidth);
  64. void (*HorizontalLine_3_5_Scale)(const unsigned char * source,unsigned int sourceWidth,unsigned char * dest,unsigned int destWidth);
  65. void (*HorizontalLine_4_5_Scale)(const unsigned char * source,unsigned int sourceWidth,unsigned char * dest,unsigned int destWidth);
  66. void (*VerticalBand_1_2_Scale)(unsigned char * dest,unsigned int destPitch,unsigned int destWidth);
  67. void (*LastVerticalBand_1_2_Scale)(unsigned char * dest,unsigned int destPitch,unsigned int destWidth);
  68. void (*FilterHoriz_Simple)(xPB_INST ppi, UINT8 * PixelPtr, INT32 LineLength, INT32*);
  69. void (*FilterVert_Simple)(xPB_INST ppi, UINT8 * PixelPtr, INT32 LineLength, INT32*);
  70. void (*DeringBlockWeak)(xPB_INST, const UINT8 *, UINT8 *, INT32, UINT32, UINT32 *);
  71. void (*DeringBlockStrong)(xPB_INST, const UINT8 *, UINT8 *, INT32, UINT32, UINT32 *);
  72. void (*DeblockLoopFilteredBand)(xPB_INST, UINT8 *, UINT8 *, UINT32, UINT32, UINT32, UINT32 *);
  73. void (*DeblockNonFilteredBand)(xPB_INST, UINT8 *, UINT8 *, UINT32, UINT32, UINT32, UINT32 *);
  74. void (*DeblockNonFilteredBandNewFilter)(xPB_INST, UINT8 *, UINT8 *, UINT32, UINT32, UINT32, UINT32 *);
  75. INT32*(*SetupBoundingValueArray)(xPB_INST ppi, INT32 FLimit);
  76. INT32*(*SetupDeblockValueArray)(xPB_INST ppi, INT32 FLimit);
  77. void (*FilterHoriz)(xPB_INST ppi, UINT8 * PixelPtr, INT32 LineLength, INT32*);
  78. void (*FilterVert)(xPB_INST ppi, UINT8 * PixelPtr, INT32 LineLength, INT32*);
  79. void (*ClampLevels)( POSTPROC_INSTANCE *ppi,INT32 BlackClamp, INT32 WhiteClamp, UINT8 *Src, UINT8 *Dst);
  80. void (*FastDeInterlace)(UINT8 *SrcPtr, UINT8 *DstPtr, INT32 Width, INT32 Height, INT32 Stride);
  81. void (*PlaneAddNoise)( UINT8 *Start, UINT32 Width, UINT32 Height, INT32 Pitch, int q);
  82. /****************************************************************************
  83. *
  84. * ROUTINE : InitPostProcessing
  85. *
  86. * INPUTS : UINT32 *DCQuantScaleV2p :
  87. * UINT32 *DCQuantScaleUVp :
  88. * UINT32 *DCQuantScaleV1p :
  89. * UINT32 Version : Codec version number.
  90. *
  91. * OUTPUTS : None.
  92. *
  93. * RETURNS : void
  94. *
  95. * FUNCTION : Initialise pointers to version specific data tables &
  96. * set-up LUTs.
  97. *
  98. * SPECIAL NOTES : None
  99. *
  100. ****************************************************************************/
  101. void InitPostProcessing
  102. (
  103. UINT32 *DCQuantScaleV2p,
  104. UINT32 *DCQuantScaleUVp,
  105. UINT32 *DCQuantScaleV1p,
  106. UINT32 Version
  107. )
  108. {
  109. int i;
  110. for ( i=0; i<VAL_RANGE*3; i++ )
  111. {
  112. int x = i - VAL_RANGE;
  113. LimitVal_VP31[i] = Clamp255 ( x );
  114. }
  115. DCQuantScaleV2 = DCQuantScaleV2p;
  116. DCQuantScaleUV = DCQuantScaleUVp;
  117. DCQuantScaleV1 = DCQuantScaleV1p;
  118. for ( i=0 ; i<Q_TABLE_SIZE; i++ )
  119. DeringModifierV1[i] = DCQuantScaleV1[i];
  120. if ( Version >= 6 )
  121. {
  122. LoopFilterLimitValuesV2 = LoopFilterLimitValuesVp6;
  123. DeblockLimitValuesV2 = DeblockLimitValuesVp6;
  124. }
  125. else if ( Version >= 5 )
  126. {
  127. LoopFilterLimitValuesV2 = LoopFilterLimitValuesVp5;
  128. DeblockLimitValuesV2 = DeblockLimitValuesVp5;
  129. }
  130. else
  131. {
  132. LoopFilterLimitValuesV2 = LoopFilterLimitValuesVp4;
  133. DeblockLimitValuesV2 = DeblockLimitValuesVp4;
  134. }
  135. PostProcMachineSpecificConfig ( Version );
  136. }
  137. /****************************************************************************
  138. *
  139. * ROUTINE : DeInitPostProcessing
  140. *
  141. * INPUTS : None.
  142. *
  143. * OUTPUTS : None.
  144. *
  145. * RETURNS : void
  146. *
  147. * FUNCTION : De-initializes post-processing module.
  148. *
  149. * SPECIAL NOTES : Currently this function does nothing.
  150. *
  151. ****************************************************************************/
  152. void DeInitPostProcessing ( void )
  153. {
  154. return;
  155. }
  156. /****************************************************************************
  157. *
  158. * ROUTINE : DeletePostProcBuffers
  159. *
  160. * INPUTS : POSTPROC_INSTANCE *ppi : Pointer to post-processor instance.
  161. *
  162. * OUTPUTS : None.
  163. *
  164. * RETURNS : void
  165. *
  166. * FUNCTION : De-allocates buffers used by the post-processing module.
  167. *
  168. * SPECIAL NOTES : None.
  169. *
  170. ****************************************************************************/
  171. void DeletePostProcBuffers ( POSTPROC_INSTANCE *ppi )
  172. {
  173. if ( ppi->IntermediateBufferAlloc )
  174. duck_free ( ppi->IntermediateBufferAlloc );
  175. ppi->IntermediateBufferAlloc = 0;
  176. ppi->IntermediateBuffer = 0;
  177. if ( ppi->IntermediateBufferAlloc )
  178. duck_free ( ppi->IntermediateBufferAlloc );
  179. ppi->IntermediateBufferAlloc = 0;
  180. ppi->IntermediateBuffer = 0;
  181. if ( ppi->FiltBoundingValueAlloc )
  182. duck_free ( ppi->FiltBoundingValueAlloc );
  183. ppi->FiltBoundingValueAlloc = 0;
  184. ppi->FiltBoundingValue = 0;
  185. if ( ppi->DeblockBoundingValueAlloc )
  186. duck_free ( ppi->DeblockBoundingValueAlloc );
  187. ppi->DeblockBoundingValueAlloc = 0;
  188. ppi->DeblockBoundingValue = 0;
  189. if ( ppi->FragQIndexAlloc )
  190. duck_free ( ppi->FragQIndexAlloc );
  191. ppi->FragQIndexAlloc = 0;
  192. ppi->FragQIndex = 0;
  193. if ( ppi->FragmentVariancesAlloc )
  194. duck_free ( ppi->FragmentVariancesAlloc );
  195. ppi->FragmentVariancesAlloc = 0;
  196. ppi->FragmentVariances = 0;
  197. if ( ppi->FragDeblockingFlagAlloc )
  198. duck_free ( ppi->FragDeblockingFlagAlloc );
  199. ppi->FragDeblockingFlagAlloc = 0;
  200. ppi->FragDeblockingFlag = 0;
  201. }
  202. /****************************************************************************
  203. *
  204. * ROUTINE : AllocatePostProcBuffers
  205. *
  206. * INPUTS : POSTPROC_INSTANCE *ppi : Pointer to post-processor instance.
  207. *
  208. * OUTPUTS : None.
  209. *
  210. * RETURNS : INT32: TRUE: Success, FALSE Failure (Chenge to BOOL!!)
  211. *
  212. * FUNCTION : Allocates buffers used by the post-processing module.
  213. *
  214. * SPECIAL NOTES : Uses ROUNDUP32 to align allocated buffers to improve
  215. * cache performance.
  216. *
  217. ****************************************************************************/
  218. INT32 AllocatePostProcBuffers ( POSTPROC_INSTANCE *ppi )
  219. {
  220. DeletePostProcBuffers ( ppi );
  221. ppi->IntermediateBufferAlloc = (UINT8*)duck_malloc ( 32 + ppi->YStride *
  222. (ppi->Configuration.VideoFrameHeight + ppi->MVBorder*2) * 3/2 * sizeof(UINT8), DMEM_GENERAL);
  223. if ( !ppi->IntermediateBufferAlloc ) { DeletePostProcBuffers ( ppi ); return FALSE; };
  224. ppi->IntermediateBuffer = (UINT8 *)ROUNDUP32 ( ppi->IntermediateBufferAlloc );
  225. ppi->FiltBoundingValueAlloc = (INT32 *)duck_malloc(32+512*sizeof(INT32), DMEM_GENERAL);
  226. if ( !ppi->FiltBoundingValueAlloc ) { DeletePostProcBuffers ( ppi ); return FALSE; };
  227. ppi->FiltBoundingValue = (INT32 *)ROUNDUP32 ( ppi->FiltBoundingValueAlloc );
  228. ppi->DeblockBoundingValueAlloc = (INT32 *)duck_malloc(32+512*sizeof(INT32), DMEM_GENERAL);
  229. if ( !ppi->DeblockBoundingValueAlloc ) { DeletePostProcBuffers ( ppi ); return FALSE; };
  230. ppi->DeblockBoundingValue = (INT32 *)ROUNDUP32 ( ppi->DeblockBoundingValueAlloc );
  231. ppi->FragQIndexAlloc = (INT32 *)duck_malloc(32+ppi->UnitFragments*sizeof(INT32), DMEM_GENERAL);
  232. if ( !ppi->FragQIndexAlloc ) { DeletePostProcBuffers ( ppi ); return FALSE; };
  233. ppi->FragQIndex = (INT32 *)ROUNDUP32 ( ppi->FragQIndexAlloc );
  234. ppi->FragmentVariancesAlloc = (INT32 *)duck_malloc(32+ppi->UnitFragments*sizeof(INT32), DMEM_GENERAL);
  235. if ( !ppi->FragmentVariancesAlloc ) { DeletePostProcBuffers ( ppi ); return FALSE; };
  236. ppi->FragmentVariances = (INT32 *)ROUNDUP32 ( ppi->FragmentVariancesAlloc );
  237. ppi->FragDeblockingFlagAlloc = (UINT8 *)duck_malloc(32+ppi->UnitFragments*sizeof(UINT8), DMEM_GENERAL);
  238. if ( !ppi->FragDeblockingFlagAlloc ){ DeletePostProcBuffers ( ppi ); return FALSE; };
  239. ppi->FragDeblockingFlag = (UINT8 *)ROUNDUP32 ( ppi->FragDeblockingFlagAlloc );
  240. return TRUE;
  241. }
  242. /****************************************************************************
  243. *
  244. * ROUTINE : ChangePostProcConfiguration
  245. *
  246. * INPUTS : POSTPROC_INSTANCE *ppi : Pointer to post-processor instance.
  247. * CONFIG_TYPE *ConfigurationInit : Pointer to
  248. *
  249. * OUTPUTS : None.
  250. *
  251. * RETURNS : void
  252. *
  253. * FUNCTION : Initialize post-processor to with the setting passed in.
  254. *
  255. * SPECIAL NOTES : None.
  256. *
  257. ****************************************************************************/
  258. void ChangePostProcConfiguration ( POSTPROC_INSTANCE *ppi, CONFIG_TYPE *ConfigurationInit )
  259. {
  260. memcpy ((void *)&ppi->Configuration, (void *)ConfigurationInit, sizeof(CONFIG_TYPE) );
  261. ppi->HFragments = (ppi->Configuration.VideoFrameWidth >> 3);
  262. ppi->VFragments = (ppi->Configuration.VideoFrameHeight>> 3);
  263. ppi->YStride = ppi->Configuration.YStride;
  264. ppi->UVStride = ppi->Configuration.UVStride;
  265. ppi->YPlaneFragments = ppi->HFragments * ppi->VFragments;
  266. ppi->UVPlaneFragments = ppi->YPlaneFragments / 4;
  267. ppi->UnitFragments = ppi->YPlaneFragments + 2 * ppi->UVPlaneFragments;
  268. ppi->MVBorder = (ppi->YStride - 8*ppi->HFragments)/2;
  269. ppi->ReconYDataOffset = ppi->MVBorder * ppi->YStride + ppi->MVBorder;
  270. ppi->ReconYDataOffset = ppi->MVBorder * ppi->YStride + ppi->MVBorder;
  271. ppi->ReconUDataOffset =
  272. (ppi->YStride * (ppi->Configuration.VideoFrameHeight + ppi->MVBorder*2))
  273. + ppi->MVBorder / 2 * ppi->UVStride + ppi->MVBorder/2;
  274. ppi->ReconVDataOffset =
  275. (ppi->YStride * (ppi->Configuration.VideoFrameHeight + ppi->MVBorder*2))
  276. + (ppi->UVStride * (ppi->Configuration.VideoFrameHeight/2 + ppi->MVBorder))
  277. + ppi->MVBorder/2 * ppi->UVStride +ppi->MVBorder/2;
  278. AllocatePostProcBuffers ( ppi );
  279. }
  280. /****************************************************************************
  281. *
  282. * ROUTINE : CreatePostProcInstance
  283. *
  284. * INPUTS : CONFIG_TYPE *ConfigurationInit : Pointer to configuration.
  285. *
  286. * OUTPUTS : None.
  287. *
  288. * RETURNS : POSTPROC_INSTANCE *: Pointer to allocated & configured
  289. * post-processor instance.
  290. *
  291. * FUNCTION : Allocates space for and initializes a post-processor
  292. * instance.
  293. *
  294. * SPECIAL NOTES : None.
  295. *
  296. ****************************************************************************/
  297. POSTPROC_INSTANCE *CreatePostProcInstance ( CONFIG_TYPE *ConfigurationInit )
  298. {
  299. POSTPROC_INSTANCE *ppi;
  300. int postproc_size = sizeof ( POSTPROC_INSTANCE );
  301. ppi = (POSTPROC_INSTANCE *) duck_malloc ( postproc_size, DMEM_GENERAL );
  302. if ( !ppi )
  303. return 0;
  304. // initialize whole structure to 0
  305. memset ( (unsigned char *)ppi, 0, postproc_size );
  306. ChangePostProcConfiguration ( ppi, ConfigurationInit );
  307. ppi->AddNoiseMode = 1;
  308. return ppi;
  309. }
  310. /****************************************************************************
  311. *
  312. * ROUTINE : DeletePostProcInstance
  313. *
  314. * INPUTS : POSTPROC_INSTANCE **ppi : Pointer-to-pointer to post-processor instance.
  315. *
  316. * OUTPUTS : POSTPROC_INSTANCE **ppi : Pointer-to-pointer to post-processor instance.
  317. *
  318. * RETURNS : void.
  319. *
  320. * FUNCTION : Deletes post-processor instance & de-allocates memory.
  321. *
  322. * SPECIAL NOTES : Pointer to post-processor instance is set to NULL
  323. * on exit.
  324. *
  325. ****************************************************************************/
  326. void DeletePostProcInstance ( POSTPROC_INSTANCE **ppi )
  327. {
  328. if ( *ppi )
  329. {
  330. // Delete any other dynamically allocaed temporary buffers
  331. DeletePostProcBuffers ( *ppi );
  332. duck_free ( *ppi );
  333. *ppi = 0;
  334. }
  335. }
  336. /****************************************************************************
  337. *
  338. * ROUTINE : SetPPInterlacedMode
  339. *
  340. * INPUTS : POSTPROC_INSTANCE *ppi : Pointer to post-processor instance.
  341. * int Interlaced : 0=Non-interlaced, 1=Interlaced.
  342. *
  343. * OUTPUTS : None.
  344. *
  345. * RETURNS : void.
  346. *
  347. * FUNCTION : Set post-processor's Interlaced Mode to specified value.
  348. *
  349. * SPECIAL NOTES : None.
  350. *
  351. ****************************************************************************/
  352. void SetPPInterlacedMode ( POSTPROC_INSTANCE *ppi, int Interlaced )
  353. {
  354. ppi->Configuration.Interlaced = Interlaced;
  355. }
  356. /****************************************************************************
  357. *
  358. * ROUTINE : SetDeInterlaceMode
  359. *
  360. * INPUTS : POSTPROC_INSTANCE *ppi : Pointer to post-processor instance.
  361. * int DeInterlaceMode : Mode to use for de-interlacing.
  362. *
  363. * OUTPUTS : None.
  364. *
  365. * RETURNS : void.
  366. *
  367. * FUNCTION : Set post-processor's De-Interlace Mode to specified value.
  368. *
  369. * SPECIAL NOTES : None.
  370. *
  371. ****************************************************************************/
  372. void SetDeInterlaceMode ( POSTPROC_INSTANCE *ppi, int DeInterlaceMode )
  373. {
  374. ppi->DeInterlaceMode = DeInterlaceMode;
  375. }
  376. /****************************************************************************
  377. *
  378. * ROUTINE : SetDeInterlaceMode
  379. *
  380. * INPUTS : POSTPROC_INSTANCE *ppi : Pointer to post-processor instance.
  381. * int DeInterlaceMode : Mode to use for de-interlacing.
  382. *
  383. * OUTPUTS : None.
  384. *
  385. * RETURNS : void.
  386. *
  387. * FUNCTION : Set post-processor's De-Interlace Mode to specified value.
  388. *
  389. * SPECIAL NOTES : None.
  390. *
  391. ****************************************************************************/
  392. void SetAddNoiseMode(POSTPROC_INSTANCE *ppi, int AddNoiseMode)
  393. {
  394. ppi->AddNoiseMode = AddNoiseMode;
  395. }
  396. /****************************************************************************
  397. *
  398. * ROUTINE : UpdateFragQIndex
  399. *
  400. * INPUTS : POSTPROC_INSTANCE *ppi : Pointer to post-processor instance.
  401. *
  402. * OUTPUTS : None.
  403. *
  404. * RETURNS : void.
  405. *
  406. * FUNCTION : Update the QIndex for each updated block.
  407. *
  408. * SPECIAL NOTES : None.
  409. *
  410. ****************************************************************************/
  411. void UpdateFragQIndex ( POSTPROC_INSTANCE *ppi )
  412. {
  413. UINT32 i;
  414. UINT32 ThisFrameQIndex;
  415. // Mark coded blocks with Q-index
  416. ThisFrameQIndex = ppi->FrameQIndex;
  417. for ( i=0; i<ppi->UnitFragments; i++ )
  418. if ( blockCoded ( i ) )
  419. ppi->FragQIndex[i] = ThisFrameQIndex;
  420. }
  421. /****************************************************************************
  422. *
  423. * ROUTINE : Gaussian
  424. *
  425. * INPUTS : sigma ( standard deviation), mu ( mean) and x (value)
  426. *
  427. * OUTPUTS : None.
  428. *
  429. * RETURNS : void.
  430. *
  431. * FUNCTION : generate height of gaussian distribution curve with
  432. * deviation sigma and mean mu at position x
  433. *
  434. * SPECIAL NOTES : None.
  435. *
  436. ****************************************************************************/
  437. double gaussian(double sigma, double mu, double x)
  438. {
  439. return 1 / ( sigma * sqrt(2.0*3.14159265)) *
  440. (exp(-(x-mu)*(x-mu)/(2*sigma*sigma)));
  441. }
  442. /****************************************************************************
  443. *
  444. * ROUTINE : PlaneAddNoise_C
  445. *
  446. * INPUTS : UINT8 *Start starting address of buffer to add gaussian
  447. * noise to
  448. * UINT32 Width width of plane
  449. * UINT32 Height height of plane
  450. * INT32 Pitch distance between subsequent lines of frame
  451. * INT32 q quantizer used to determine amount of noise
  452. * to add
  453. *
  454. * OUTPUTS : None.
  455. *
  456. * RETURNS : void.
  457. *
  458. * FUNCTION : adds gaussian noise to a plane of pixels
  459. *
  460. * SPECIAL NOTES : None.
  461. *
  462. ****************************************************************************/
  463. void PlaneAddNoise_C( UINT8 *Start, UINT32 Width, UINT32 Height, INT32 Pitch, int q)
  464. {
  465. unsigned int i,j;
  466. INT32 Pitch4 = Pitch * 4;
  467. const int noiseAmount = 2;
  468. const int noiseAdder = 2 * noiseAmount + 1;
  469. unsigned char blackclamp[16];
  470. unsigned char whiteclamp[16];
  471. unsigned char bothclamp[16];
  472. char CharDist[300];
  473. char Rand[2048];
  474. double sigma;
  475. sigma = 1 + .8*(63-q) / 63.0;
  476. // set up a lookup table of 256 entries that matches
  477. // a gaussian distribution with sigma determined by q.
  478. //
  479. {
  480. double i,sum=0;
  481. int next,j;
  482. next=0;
  483. for(i=-32;i<32;i++)
  484. {
  485. int a = (int) (.5+256*gaussian(sigma,0,i));
  486. if(a)
  487. {
  488. for(j=0;j<a;j++)
  489. {
  490. CharDist[next+j]=(char) i;
  491. }
  492. next = next+j;
  493. }
  494. }
  495. for(next=next;next<256;next++)
  496. CharDist[next] = 0;
  497. }
  498. // generate a line of 2048 characters following our gaussian distribution
  499. for(i=0;i<2048;i++)
  500. {
  501. Rand[i]=CharDist[rand() & 0xff];
  502. }
  503. for(i=0;i<16;i++)
  504. {
  505. blackclamp[i]=-CharDist[0];
  506. whiteclamp[i]=-CharDist[0];
  507. bothclamp[i]=-2*CharDist[0];
  508. }
  509. for(i=0;i<Height;i++)
  510. {
  511. UINT8* Pos = Start + i *Pitch;
  512. INT8* Ref = (INT8 *) (Rand + (rand() & 0xff)); /* cast required on strict OSX-CW8 */
  513. for(j=0;j<Width;j++)
  514. {
  515. if(Pos[j] < -CharDist[0])
  516. Pos[j] = -CharDist[0];
  517. if(Pos[j] > 255-CharDist[0])
  518. Pos[j] = 255-CharDist[0];
  519. Pos[j]+=Ref[j];
  520. }
  521. }
  522. }
  523. /****************************************************************************
  524. *
  525. * ROUTINE : PostProcess
  526. *
  527. * INPUTS : POSTPROC_INSTANCE *ppi : Pointer to post-processor instance.
  528. * INT32 Vp3VersionNo : Encoder version used to code frame.
  529. * INT32 FrameType : Encoding method: Keyframe or non-Keyframe.
  530. * INT32 PostProcessingLevel : Level of post-processing to perform.
  531. * INT32 FrameQIndex : Q-index used to code frame.
  532. * UINT8 *LastFrameRecon : Pointer to last frame reconstruction buffer.
  533. * UINT8 *PostProcessBuffer : Pointer to last post-processing buffer.
  534. * UINT8 *FragInfo : Pointer to list of coded blocks.
  535. * UINT32 FragInfoElementSize : Size of each element.
  536. * UINT32 FragInfoCodedMask : Mask to get at whether fragment is coded.
  537. *
  538. * OUTPUTS : None.
  539. *
  540. * RETURNS : void.
  541. *
  542. * FUNCTION : Applies de-blocking and de-ringing filters to the frame.
  543. *
  544. * SPECIAL NOTES : None.
  545. *
  546. ****************************************************************************/
  547. void PostProcess
  548. (
  549. POSTPROC_INSTANCE *ppi,
  550. INT32 Vp3VersionNo,
  551. INT32 FrameType,
  552. INT32 PostProcessingLevel,
  553. INT32 FrameQIndex,
  554. UINT8 *LastFrameRecon,
  555. UINT8 *PostProcessBuffer,
  556. UINT8 *FragInfo,
  557. UINT32 FragInfoElementSize,
  558. UINT32 FragInfoCodedMask
  559. )
  560. {
  561. int ReconUVPlaneSize;
  562. // variables passed in per frame
  563. ppi->Vp3VersionNo = Vp3VersionNo;
  564. ppi->FrameType = FrameType;
  565. ppi->PostProcessingLevel = PostProcessingLevel;
  566. ppi->FrameQIndex = FrameQIndex;
  567. ppi->LastFrameRecon = LastFrameRecon;
  568. ppi->PostProcessBuffer = PostProcessBuffer;
  569. ppi->FragInfo = FragInfo;
  570. ppi->FragInfoElementSize = FragInfoElementSize;
  571. ppi->FragInfoCodedMask = FragInfoCodedMask;
  572. switch ( ppi->PostProcessingLevel )
  573. {
  574. case 8:
  575. // On a slow machine, use a simpler and faster deblocking filter
  576. UpdateFragQIndex ( ppi );
  577. if(ppi->Vp3VersionNo < 2)
  578. {
  579. DeblockFrame ( ppi, ppi->LastFrameRecon, ppi->PostProcessBuffer );
  580. }
  581. else
  582. {
  583. if ( ppi->Configuration.Interlaced && ppi->DeInterlaceMode )
  584. {
  585. SimpleDeblockFrame ( ppi, ppi->LastFrameRecon, ppi->IntermediateBuffer );
  586. ReconUVPlaneSize = ppi->VFragments*2*ppi->YStride;
  587. memcpy ( ppi->PostProcessBuffer+ppi->ReconUDataOffset, ppi->IntermediateBuffer+ppi->ReconUDataOffset, ReconUVPlaneSize );
  588. memcpy ( ppi->PostProcessBuffer+ppi->ReconVDataOffset, ppi->IntermediateBuffer+ppi->ReconVDataOffset, ReconUVPlaneSize );
  589. FastDeInterlace ( ppi->IntermediateBuffer+ppi->ReconYDataOffset,
  590. ppi->PostProcessBuffer+ppi->ReconYDataOffset,
  591. ppi->HFragments*8, ppi->VFragments*8, ppi->YStride );
  592. }
  593. else
  594. SimpleDeblockFrame ( ppi, ppi->LastFrameRecon, ppi->PostProcessBuffer );
  595. }
  596. break;
  597. case 6:
  598. case 5:
  599. if ( ppi->Vp3VersionNo < 5 )
  600. {
  601. UpdateFragQIndex ( ppi );
  602. }
  603. else
  604. {
  605. if ( ppi->Configuration.Interlaced )
  606. {
  607. if ( !ppi->DeInterlaceMode )
  608. {
  609. DeblockFrameInterlaced ( ppi, ppi->LastFrameRecon, ppi->PostProcessBuffer );
  610. UpdateUMVBorder ( ppi, ppi->PostProcessBuffer );
  611. DeringFrameInterlaced ( ppi, ppi->PostProcessBuffer, ppi->PostProcessBuffer );
  612. }
  613. else
  614. {
  615. DeblockFrameInterlaced ( ppi, ppi->LastFrameRecon, ppi->IntermediateBuffer );
  616. UpdateUMVBorder ( ppi, ppi->IntermediateBuffer );
  617. DeringFrameInterlaced ( ppi, ppi->IntermediateBuffer, ppi->IntermediateBuffer );
  618. ReconUVPlaneSize = ppi->VFragments*2*ppi->YStride;
  619. memcpy ( ppi->PostProcessBuffer+ppi->ReconUDataOffset, ppi->IntermediateBuffer+ppi->ReconUDataOffset, ReconUVPlaneSize );
  620. memcpy ( ppi->PostProcessBuffer+ppi->ReconVDataOffset, ppi->IntermediateBuffer+ppi->ReconVDataOffset, ReconUVPlaneSize );
  621. FastDeInterlace ( ppi->IntermediateBuffer+ppi->ReconYDataOffset,
  622. ppi->PostProcessBuffer+ppi->ReconYDataOffset,
  623. ppi->HFragments*8, ppi->VFragments*8, ppi->YStride);
  624. }
  625. break;
  626. }
  627. }
  628. DeblockFrame ( ppi, ppi->LastFrameRecon, ppi->PostProcessBuffer );
  629. UpdateUMVBorder ( ppi, ppi->PostProcessBuffer );
  630. DeringFrame ( ppi, ppi->PostProcessBuffer, ppi->PostProcessBuffer );
  631. if(ppi->AddNoiseMode&&PlaneAddNoise!=0)
  632. PlaneAddNoise(ppi->PostProcessBuffer + ppi->ReconYDataOffset,ppi->HFragments*8, ppi->VFragments*8,ppi->YStride,FrameQIndex);
  633. break;
  634. case 7:
  635. if ( ppi->Vp3VersionNo >= 5 )
  636. {
  637. if ( ppi->Configuration.Interlaced )
  638. {
  639. if ( !ppi->DeInterlaceMode )
  640. DeblockFrameInterlaced ( ppi, ppi->LastFrameRecon, ppi->PostProcessBuffer );
  641. else
  642. {
  643. DeblockFrameInterlaced ( ppi, ppi->LastFrameRecon, ppi->IntermediateBuffer );
  644. ReconUVPlaneSize = ppi->VFragments*2*ppi->YStride;
  645. memcpy ( ppi->PostProcessBuffer+ppi->ReconUDataOffset, ppi->IntermediateBuffer+ppi->ReconUDataOffset, ReconUVPlaneSize );
  646. memcpy ( ppi->PostProcessBuffer+ppi->ReconVDataOffset, ppi->IntermediateBuffer+ppi->ReconVDataOffset, ReconUVPlaneSize );
  647. FastDeInterlace ( ppi->IntermediateBuffer+ppi->ReconYDataOffset,
  648. ppi->PostProcessBuffer+ppi->ReconYDataOffset,
  649. ppi->HFragments*8, ppi->VFragments*8, ppi->YStride );
  650. }
  651. break;
  652. }
  653. }
  654. else
  655. {
  656. UpdateFragQIndex ( ppi );
  657. }
  658. DeblockFrame ( ppi, ppi->LastFrameRecon, ppi->PostProcessBuffer );
  659. UpdateUMVBorder ( ppi, ppi->PostProcessBuffer );
  660. DeringFrame ( ppi, ppi->PostProcessBuffer, ppi->PostProcessBuffer );
  661. break;
  662. case 4:
  663. if ( ppi->Vp3VersionNo >= 5 )
  664. {
  665. if ( ppi->Configuration.Interlaced )
  666. {
  667. if ( !ppi->DeInterlaceMode )
  668. DeblockFrameInterlaced ( ppi, ppi->LastFrameRecon, ppi->PostProcessBuffer );
  669. else
  670. {
  671. DeblockFrameInterlaced ( ppi, ppi->LastFrameRecon, ppi->IntermediateBuffer );
  672. ReconUVPlaneSize = ppi->VFragments*2*ppi->YStride;
  673. memcpy ( ppi->PostProcessBuffer+ppi->ReconUDataOffset, ppi->IntermediateBuffer+ppi->ReconUDataOffset, ReconUVPlaneSize );
  674. memcpy ( ppi->PostProcessBuffer+ppi->ReconVDataOffset, ppi->IntermediateBuffer+ppi->ReconVDataOffset, ReconUVPlaneSize );
  675. FastDeInterlace ( ppi->IntermediateBuffer+ppi->ReconYDataOffset,
  676. ppi->PostProcessBuffer+ppi->ReconYDataOffset,
  677. ppi->HFragments*8, ppi->VFragments*8, ppi->YStride );
  678. }
  679. break;
  680. }
  681. }
  682. else
  683. {
  684. UpdateFragQIndex ( ppi );
  685. }
  686. DeblockFrame ( ppi, ppi->LastFrameRecon, ppi->PostProcessBuffer );
  687. //PlaneAddNoise(ppi->PostProcessBuffer + ppi->ReconYDataOffset,ppi->HFragments*8, ppi->VFragments*8,ppi->YStride,FrameQIndex);
  688. break;
  689. case 1:
  690. UpdateFragQIndex ( ppi );
  691. break;
  692. case 0:
  693. if ( ppi->Configuration.Interlaced && ppi->DeInterlaceMode )
  694. {
  695. ReconUVPlaneSize = ppi->VFragments*2*ppi->YStride;
  696. memcpy ( ppi->PostProcessBuffer+ppi->ReconUDataOffset, ppi->LastFrameRecon+ppi->ReconUDataOffset, ReconUVPlaneSize );
  697. memcpy ( ppi->PostProcessBuffer+ppi->ReconVDataOffset, ppi->LastFrameRecon+ppi->ReconVDataOffset, ReconUVPlaneSize );
  698. FastDeInterlace ( ppi->LastFrameRecon+ppi->ReconYDataOffset,
  699. ppi->PostProcessBuffer+ppi->ReconYDataOffset,
  700. ppi->HFragments*8, ppi->VFragments*8, ppi->YStride );
  701. }
  702. break;
  703. default:
  704. DeblockFrame ( ppi, ppi->LastFrameRecon, ppi->PostProcessBuffer );
  705. UpdateUMVBorder ( ppi, ppi->PostProcessBuffer );
  706. DeringFrame ( ppi, ppi->PostProcessBuffer, ppi->PostProcessBuffer );
  707. break;
  708. }
  709. }