1 /********************************************************************
3 * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
4 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
5 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
6 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
8 * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2003 *
9 * by the Xiph.Org Foundation http://www.xiph.org/ *
11 ********************************************************************
16 ********************************************************************/
20 #include "codec_internal.h"
24 #define MAX(a, b) ((a>b)?a:b)
25 #define MIN(a, b) ((a<b)?a:b)
26 #define PP_QUALITY_THRESH 49
28 static const ogg_int32_t SharpenModifier
[ Q_TABLE_SIZE
] =
29 { -12, -11, -10, -10, -9, -9, -9, -9,
30 -6, -6, -6, -6, -6, -6, -6, -6,
31 -4, -4, -4, -4, -4, -4, -4, -4,
32 -2, -2, -2, -2, -2, -2, -2, -2,
33 -2, -2, -2, -2, -2, -2, -2, -2,
34 0, 0, 0, 0, 0, 0, 0, 0,
35 0, 0, 0, 0, 0, 0, 0, 0,
36 0, 0, 0, 0, 0, 0, 0, 0
39 static const ogg_uint32_t DcQuantScaleV1
[ Q_TABLE_SIZE
] = {
40 22, 20, 19, 18, 17, 17, 16, 16,
41 15, 15, 14, 14, 13, 13, 12, 12,
42 11, 11, 10, 10, 9, 9, 9, 8,
43 8, 8, 7, 7, 7, 6, 6, 6,
44 6, 5, 5, 5, 5, 4, 4, 4,
45 4, 4, 3, 3, 3, 3, 3, 3,
46 3, 2, 2, 2, 2, 2, 2, 2,
47 2, 1, 1, 1, 1, 1, 1, 1
50 static const ogg_uint32_t
* const DeringModifierV1
=DcQuantScaleV1
;
52 static void PClearFrameInfo(PP_INSTANCE
* ppi
){
55 if(ppi
->ScanPixelIndexTable
) _ogg_free(ppi
->ScanPixelIndexTable
);
56 ppi
->ScanPixelIndexTable
=0;
58 if(ppi
->ScanDisplayFragments
) _ogg_free(ppi
->ScanDisplayFragments
);
59 ppi
->ScanDisplayFragments
=0;
61 for(i
= 0 ; i
< MAX_PREV_FRAMES
; i
++)
62 if(ppi
->PrevFragments
[i
]){
63 _ogg_free(ppi
->PrevFragments
[i
]);
64 ppi
->PrevFragments
[i
]=0;
67 if(ppi
->FragScores
) _ogg_free(ppi
->FragScores
);
70 if(ppi
->SameGreyDirPixels
) _ogg_free(ppi
->SameGreyDirPixels
);
71 ppi
->SameGreyDirPixels
=0;
73 if(ppi
->FragDiffPixels
) _ogg_free(ppi
->FragDiffPixels
);
74 ppi
->FragDiffPixels
=0;
76 if(ppi
->BarBlockMap
) _ogg_free(ppi
->BarBlockMap
);
79 if(ppi
->TmpCodedMap
) _ogg_free(ppi
->TmpCodedMap
);
82 if(ppi
->RowChangedPixels
) _ogg_free(ppi
->RowChangedPixels
);
83 ppi
->RowChangedPixels
=0;
85 if(ppi
->PixelScores
) _ogg_free(ppi
->PixelScores
);
88 if(ppi
->PixelChangedMap
) _ogg_free(ppi
->PixelChangedMap
);
89 ppi
->PixelChangedMap
=0;
91 if(ppi
->ChLocals
) _ogg_free(ppi
->ChLocals
);
94 if(ppi
->yuv_differences
) _ogg_free(ppi
->yuv_differences
);
95 ppi
->yuv_differences
=0;
99 void PInitFrameInfo(PP_INSTANCE
* ppi
){
101 PClearFrameInfo(ppi
);
103 ppi
->ScanPixelIndexTable
=
104 _ogg_malloc(ppi
->ScanFrameFragments
*sizeof(*ppi
->ScanPixelIndexTable
));
106 ppi
->ScanDisplayFragments
=
107 _ogg_malloc(ppi
->ScanFrameFragments
*sizeof(*ppi
->ScanDisplayFragments
));
109 for(i
= 0 ; i
< MAX_PREV_FRAMES
; i
++)
110 ppi
->PrevFragments
[i
] =
111 _ogg_malloc(ppi
->ScanFrameFragments
*sizeof(*ppi
->PrevFragments
));
114 _ogg_malloc(ppi
->ScanFrameFragments
*sizeof(*ppi
->FragScores
));
116 ppi
->SameGreyDirPixels
=
117 _ogg_malloc(ppi
->ScanFrameFragments
*sizeof(*ppi
->SameGreyDirPixels
));
119 ppi
->FragDiffPixels
=
120 _ogg_malloc(ppi
->ScanFrameFragments
*sizeof(*ppi
->FragScores
));
123 _ogg_malloc(3 * ppi
->ScanHFragments
*sizeof(*ppi
->BarBlockMap
));
126 _ogg_malloc(ppi
->ScanHFragments
*sizeof(*ppi
->TmpCodedMap
));
128 ppi
->RowChangedPixels
=
129 _ogg_malloc(3 * ppi
->ScanConfig
.VideoFrameHeight
*
130 sizeof(*ppi
->RowChangedPixels
));
133 _ogg_malloc(ppi
->ScanConfig
.VideoFrameWidth
*
134 sizeof(*ppi
->PixelScores
) * PSCORE_CB_ROWS
);
136 ppi
->PixelChangedMap
=
137 _ogg_malloc(ppi
->ScanConfig
.VideoFrameWidth
*
138 sizeof(*ppi
->PixelChangedMap
) * PMAP_CB_ROWS
);
141 _ogg_malloc(ppi
->ScanConfig
.VideoFrameWidth
*
142 sizeof(*ppi
->ChLocals
) * CHLOCALS_CB_ROWS
);
144 ppi
->yuv_differences
=
145 _ogg_malloc(ppi
->ScanConfig
.VideoFrameWidth
*
146 sizeof(*ppi
->yuv_differences
) * YDIFF_CB_ROWS
);
149 void ClearPPInstance(PP_INSTANCE
*ppi
){
150 PClearFrameInfo(ppi
);
154 void InitPPInstance(PP_INSTANCE
*ppi
, DspFunctions
*funcs
){
156 memset(ppi
,0,sizeof(*ppi
));
158 memcpy(&ppi
->dsp
, funcs
, sizeof(DspFunctions
));
160 /* Initializations */
161 ppi
->PrevFrameLimit
= 3; /* Must not exceed MAX_PREV_FRAMES (Note
162 that this number includes the current
163 frame so "1 = no effect") */
165 /* Scan control variables. */
166 ppi
->HFragPixels
= 8;
167 ppi
->VFragPixels
= 8;
169 ppi
->SRFGreyThresh
= 4;
170 ppi
->SRFColThresh
= 5;
171 ppi
->NoiseSupLevel
= 3;
172 ppi
->SgcLevelThresh
= 3;
173 ppi
->SuvcLevelThresh
= 4;
175 /* Variables controlling S.A.D. breakouts. */
176 ppi
->GrpLowSadThresh
= 10;
177 ppi
->GrpHighSadThresh
= 64;
178 ppi
->PrimaryBlockThreshold
= 5;
179 ppi
->SgcThresh
= 16; /* (Default values for 8x8 blocks). */
181 ppi
->UVBlockThreshCorrection
= 1.25;
182 ppi
->UVSgcCorrection
= 1.5;
184 ppi
->MaxLineSearchLen
= MAX_SEARCH_LINE_LEN
;
187 static void DeringBlockStrong(unsigned char *SrcPtr
,
188 unsigned char *DstPtr
,
190 ogg_uint32_t FragQIndex
,
191 const ogg_uint32_t
*QuantScale
){
193 ogg_int16_t UDMod
[72];
194 ogg_int16_t LRMod
[72];
196 const unsigned char * Src
;
197 unsigned int QValue
= QuantScale
[FragQIndex
];
214 const unsigned char *curRow
= SrcPtr
- 1; /* avoid negative array indexes */
215 unsigned char *dstRow
= DstPtr
;
216 const unsigned char *lastRow
= SrcPtr
-Pitch
;
217 const unsigned char *nextRow
= SrcPtr
+Pitch
;
219 unsigned int rowOffset
= 0;
220 unsigned int round
= (1<<6);
226 int Sharpen
= SharpenModifier
[FragQIndex
];
232 /* Initialize the Mod Data */
237 TmpMod
= 32 + QValue
- (abs(Src
[j
+Pitch
]-Src
[j
]));
248 UDMod
[k
*8+j
] = (ogg_int16_t
)TmpMod
;
257 TmpMod
= 32 + QValue
- (abs(Src
[j
+1]-Src
[j
]));
268 LRMod
[k
*9+j
] = (ogg_int16_t
)TmpMod
;
274 /* In the case that this function called with same buffer for
275 source and destination, To keep the c and the mmx version to have
276 consistant results, intermediate buffer is used to store the
277 eight pixel value before writing them to destination
278 (i.e. Overwriting souce for the speical case) */
283 p
= curRow
[ rowOffset
+l
+1];
285 pl
= curRow
[ rowOffset
+l
];
290 pu
= lastRow
[ rowOffset
+l
];
295 pd
= nextRow
[ rowOffset
+l
];
296 ad
= UDMod
[(k
+1)*8+l
];
300 pr
= curRow
[ rowOffset
+l
+2];
305 newVal
= ( atot
* p
+ B
) >> 7;
307 dstRow
[ rowOffset
+l
]= clamp255( newVal
);
313 static void DeringBlockWeak(unsigned char *SrcPtr
,
314 unsigned char *DstPtr
,
316 ogg_uint32_t FragQIndex
,
317 const ogg_uint32_t
*QuantScale
){
319 ogg_int16_t UDMod
[72];
320 ogg_int16_t LRMod
[72];
322 const unsigned char * Src
;
323 unsigned int QValue
= QuantScale
[FragQIndex
];
340 const unsigned char *curRow
= SrcPtr
-1;
341 unsigned char *dstRow
= DstPtr
;
342 const unsigned char *lastRow
= SrcPtr
-Pitch
;
343 const unsigned char *nextRow
= SrcPtr
+Pitch
;
345 unsigned int rowOffset
= 0;
346 unsigned int round
= (1<<6);
351 int Sharpen
= SharpenModifier
[FragQIndex
];
358 /* Initialize the Mod Data */
363 TmpMod
= 32 + QValue
- 2*(abs(Src
[j
+Pitch
]-Src
[j
]));
374 UDMod
[k
*8+j
] = (ogg_int16_t
)TmpMod
;
383 TmpMod
= 32 + QValue
- 2*(abs(Src
[j
+1]-Src
[j
]));
394 LRMod
[k
*9+j
] = (ogg_int16_t
)TmpMod
;
403 p
= curRow
[ rowOffset
+j
+1];
405 pl
= curRow
[ rowOffset
+j
];
410 pu
= lastRow
[ rowOffset
+j
];
415 pd
= nextRow
[ rowOffset
+j
];
416 ad
= UDMod
[(k
+1)*8+j
];
420 pr
= curRow
[ rowOffset
+j
+2];
425 newVal
= ( atot
* p
+ B
) >> 7;
427 dstRow
[ rowOffset
+j
] = clamp255( newVal
);
434 static void DeringFrame(PB_INSTANCE
*pbi
,
435 unsigned char *Src
, unsigned char *Dst
){
436 ogg_uint32_t col
,row
;
437 unsigned char *SrcPtr
;
438 unsigned char *DestPtr
;
439 ogg_uint32_t BlocksAcross
,BlocksDown
;
440 const ogg_uint32_t
*QuantScale
;
442 ogg_uint32_t LineLength
;
444 ogg_int32_t Thresh1
,Thresh2
,Thresh3
,Thresh4
;
447 Thresh2
= 4 * Thresh1
;
448 Thresh3
= 5 * Thresh2
/4;
449 Thresh4
= 5 * Thresh2
/2;
451 QuantScale
= DeringModifierV1
;
453 BlocksAcross
= pbi
->HFragments
;
454 BlocksDown
= pbi
->VFragments
;
456 SrcPtr
= Src
+ pbi
->ReconYDataOffset
;
457 DestPtr
= Dst
+ pbi
->ReconYDataOffset
;
458 LineLength
= pbi
->YStride
;
462 for ( row
= 0 ; row
< BlocksDown
; row
++){
463 for (col
= 0; col
< BlocksAcross
; col
++){
464 ogg_uint32_t Quality
= pbi
->FragQIndex
[Block
];
465 ogg_int32_t Variance
= pbi
->FragmentVariances
[Block
];
467 if( pbi
->PostProcessingLevel
>5 && Variance
> Thresh3
){
468 DeringBlockStrong(SrcPtr
+ 8 * col
, DestPtr
+ 8 * col
,
469 LineLength
,Quality
,QuantScale
);
472 pbi
->FragmentVariances
[Block
-1] > Thresh4
) ||
473 (col
+ 1 < BlocksAcross
&&
474 pbi
->FragmentVariances
[Block
+1] > Thresh4
) ||
475 (row
+ 1 < BlocksDown
&&
476 pbi
->FragmentVariances
[Block
+BlocksAcross
] > Thresh4
) ||
478 pbi
->FragmentVariances
[Block
-BlocksAcross
] > Thresh4
) ){
480 DeringBlockStrong(SrcPtr
+ 8 * col
, DestPtr
+ 8 * col
,
481 LineLength
,Quality
,QuantScale
);
482 DeringBlockStrong(SrcPtr
+ 8 * col
, DestPtr
+ 8 * col
,
483 LineLength
,Quality
,QuantScale
);
485 } else if(Variance
> Thresh2
) {
487 DeringBlockStrong(SrcPtr
+ 8 * col
, DestPtr
+ 8 * col
,
488 LineLength
,Quality
,QuantScale
);
489 } else if(Variance
> Thresh1
) {
491 DeringBlockWeak(SrcPtr
+ 8 * col
, DestPtr
+ 8 * col
,
492 LineLength
,Quality
,QuantScale
);
496 dsp_copy8x8(pbi
->dsp
, SrcPtr
+ 8 * col
, DestPtr
+ 8 * col
, LineLength
);
503 SrcPtr
+= 8 * LineLength
;
504 DestPtr
+= 8 * LineLength
;
513 SrcPtr
= Src
+ pbi
->ReconUDataOffset
;
514 DestPtr
= Dst
+ pbi
->ReconUDataOffset
;
515 for ( row
= 0 ; row
< BlocksDown
; row
++) {
516 for (col
= 0; col
< BlocksAcross
; col
++) {
517 ogg_uint32_t Quality
= pbi
->FragQIndex
[Block
];
518 ogg_int32_t Variance
= pbi
->FragmentVariances
[Block
];
520 if( pbi
->PostProcessingLevel
>5 && Variance
> Thresh4
) {
521 DeringBlockStrong(SrcPtr
+ 8 * col
, DestPtr
+ 8 * col
,
522 LineLength
,Quality
,QuantScale
);
523 DeringBlockStrong(SrcPtr
+ 8 * col
, DestPtr
+ 8 * col
,
524 LineLength
,Quality
,QuantScale
);
525 DeringBlockStrong(SrcPtr
+ 8 * col
, DestPtr
+ 8 * col
,
526 LineLength
,Quality
,QuantScale
);
528 }else if(Variance
> Thresh2
){
529 DeringBlockStrong(SrcPtr
+ 8 * col
, DestPtr
+ 8 * col
,
530 LineLength
,Quality
,QuantScale
);
531 }else if(Variance
> Thresh1
){
532 DeringBlockWeak(SrcPtr
+ 8 * col
, DestPtr
+ 8 * col
,
533 LineLength
,Quality
,QuantScale
);
535 dsp_copy8x8(pbi
->dsp
, SrcPtr
+ 8 * col
, DestPtr
+ 8 * col
, LineLength
);
541 SrcPtr
+= 8 * LineLength
;
542 DestPtr
+= 8 * LineLength
;
546 SrcPtr
= Src
+ pbi
->ReconVDataOffset
;
547 DestPtr
= Dst
+ pbi
->ReconVDataOffset
;
549 for ( row
= 0 ; row
< BlocksDown
; row
++){
550 for (col
= 0; col
< BlocksAcross
; col
++){
552 ogg_uint32_t Quality
= pbi
->FragQIndex
[Block
];
553 ogg_int32_t Variance
= pbi
->FragmentVariances
[Block
];
556 if( pbi
->PostProcessingLevel
>5 && Variance
> Thresh4
) {
557 DeringBlockStrong(SrcPtr
+ 8 * col
, DestPtr
+ 8 * col
,
558 LineLength
,Quality
,QuantScale
);
559 DeringBlockStrong(SrcPtr
+ 8 * col
, DestPtr
+ 8 * col
,
560 LineLength
,Quality
,QuantScale
);
561 DeringBlockStrong(SrcPtr
+ 8 * col
, DestPtr
+ 8 * col
,
562 LineLength
,Quality
,QuantScale
);
564 }else if(Variance
> Thresh2
){
565 DeringBlockStrong(SrcPtr
+ 8 * col
, DestPtr
+ 8 * col
,
566 LineLength
,Quality
,QuantScale
);
567 }else if(Variance
> Thresh1
){
568 DeringBlockWeak(SrcPtr
+ 8 * col
, DestPtr
+ 8 * col
,
569 LineLength
,Quality
,QuantScale
);
571 dsp_copy8x8(pbi
->dsp
, SrcPtr
+ 8 * col
, DestPtr
+ 8 * col
, LineLength
);
577 SrcPtr
+= 8 * LineLength
;
578 DestPtr
+= 8 * LineLength
;
584 void UpdateFragQIndex(PB_INSTANCE
*pbi
){
586 ogg_uint32_t ThisFrameQIndex
;
589 /* Check this frame quality index */
590 ThisFrameQIndex
= pbi
->FrameQIndex
;
593 /* It is not a key frame, so only reset those are coded */
594 for( i
= 0; i
< pbi
->UnitFragments
; i
++ )
595 if( pbi
->display_fragments
[i
])
596 pbi
->FragQIndex
[i
] = ThisFrameQIndex
;
600 static void DeblockLoopFilteredBand(PB_INSTANCE
*pbi
,
601 unsigned char *SrcPtr
,
602 unsigned char *DesPtr
,
603 ogg_uint32_t PlaneLineStep
,
604 ogg_uint32_t FragsAcross
,
605 ogg_uint32_t StartFrag
,
606 const ogg_uint32_t
*QuantScale
){
608 ogg_uint32_t CurrentFrag
=StartFrag
;
611 unsigned char *Src
, *Des
;
613 ogg_int32_t Sum1
, Sum2
;
615 while(CurrentFrag
< StartFrag
+ FragsAcross
){
617 Src
=SrcPtr
+8*(CurrentFrag
-StartFrag
)-PlaneLineStep
*5;
618 Des
=DesPtr
+8*(CurrentFrag
-StartFrag
)-PlaneLineStep
*4;
620 QStep
= QuantScale
[pbi
->FragQIndex
[CurrentFrag
+FragsAcross
]];
621 FLimit
= ( QStep
* 3 ) >> 2;
623 for( j
=0; j
<8 ; j
++){
625 x
[1] = Src
[PlaneLineStep
];
626 x
[2] = Src
[PlaneLineStep
*2];
627 x
[3] = Src
[PlaneLineStep
*3];
628 x
[4] = Src
[PlaneLineStep
*4];
629 x
[5] = Src
[PlaneLineStep
*5];
630 x
[6] = Src
[PlaneLineStep
*6];
631 x
[7] = Src
[PlaneLineStep
*7];
632 x
[8] = Src
[PlaneLineStep
*8];
633 x
[9] = Src
[PlaneLineStep
*9];
638 Sum1
+= abs(x
[k
]-x
[k
-1]);
639 Sum2
+= abs(x
[k
+4]-x
[k
+5]);
642 pbi
->FragmentVariances
[CurrentFrag
] +=((Sum1
>255)?255:Sum1
);
643 pbi
->FragmentVariances
[CurrentFrag
+ FragsAcross
] += ((Sum2
>255)?255:Sum2
);
647 (x
[5] - x
[4]) < QStep
&&
648 (x
[4] - x
[5]) < QStep
){
650 /* low pass filtering (LPF7: 1 1 1 2 1 1 1) */
651 Des
[0 ] = (x
[0] + x
[0] +x
[0] + x
[1] * 2 +
652 x
[2] + x
[3] +x
[4] + 4) >> 3;
653 Des
[PlaneLineStep
] = (x
[0] + x
[0] +x
[1] + x
[2] * 2 +
654 x
[3] + x
[4] +x
[5] + 4) >> 3;
655 Des
[PlaneLineStep
*2] = (x
[0] + x
[1] +x
[2] + x
[3] * 2 +
656 x
[4] + x
[5] +x
[6] + 4) >> 3;
657 Des
[PlaneLineStep
*3] = (x
[1] + x
[2] +x
[3] + x
[4] * 2 +
658 x
[5] + x
[6] +x
[7] + 4) >> 3;
659 Des
[PlaneLineStep
*4] = (x
[2] + x
[3] +x
[4] + x
[5] * 2 +
660 x
[6] + x
[7] +x
[8] + 4) >> 3;
661 Des
[PlaneLineStep
*5] = (x
[3] + x
[4] +x
[5] + x
[6] * 2 +
662 x
[7] + x
[8] +x
[9] + 4) >> 3;
663 Des
[PlaneLineStep
*6] = (x
[4] + x
[5] +x
[6] + x
[7] * 2 +
664 x
[8] + x
[9] +x
[9] + 4) >> 3;
665 Des
[PlaneLineStep
*7] = (x
[5] + x
[6] +x
[7] + x
[8] * 2 +
666 x
[9] + x
[9] +x
[9] + 4) >> 3;
669 /* copy the pixels to destination */
670 Des
[0 ]= (unsigned char)x
[1];
671 Des
[PlaneLineStep
]= (unsigned char)x
[2];
672 Des
[PlaneLineStep
*2]= (unsigned char)x
[3];
673 Des
[PlaneLineStep
*3]= (unsigned char)x
[4];
674 Des
[PlaneLineStep
*4]= (unsigned char)x
[5];
675 Des
[PlaneLineStep
*5]= (unsigned char)x
[6];
676 Des
[PlaneLineStep
*6]= (unsigned char)x
[7];
677 Des
[PlaneLineStep
*7]= (unsigned char)x
[8];
684 /* done with filtering the horizontal edge, now let's do the
686 /* skip the first one */
687 if(CurrentFrag
==StartFrag
)
690 Des
=DesPtr
-8*PlaneLineStep
+8*(CurrentFrag
-StartFrag
);
694 QStep
= QuantScale
[pbi
->FragQIndex
[CurrentFrag
]];
695 FLimit
= ( QStep
* 3 ) >> 2;
697 for( j
=0; j
<8 ; j
++){
712 Sum1
+= abs(x
[k
]-x
[k
-1]);
713 Sum2
+= abs(x
[k
+4]-x
[k
+5]);
716 pbi
->FragmentVariances
[CurrentFrag
-1] += ((Sum1
>255)?255:Sum1
);
717 pbi
->FragmentVariances
[CurrentFrag
] += ((Sum2
>255)?255:Sum2
);
721 (x
[5] - x
[4]) < QStep
&&
722 (x
[4] - x
[5]) < QStep
){
724 /* low pass filtering (LPF7: 1 1 1 2 1 1 1) */
725 Des
[0] = (x
[0] + x
[0] +x
[0] + x
[1] * 2 + x
[2] + x
[3] +x
[4] + 4) >> 3;
726 Des
[1] = (x
[0] + x
[0] +x
[1] + x
[2] * 2 + x
[3] + x
[4] +x
[5] + 4) >> 3;
727 Des
[2] = (x
[0] + x
[1] +x
[2] + x
[3] * 2 + x
[4] + x
[5] +x
[6] + 4) >> 3;
728 Des
[3] = (x
[1] + x
[2] +x
[3] + x
[4] * 2 + x
[5] + x
[6] +x
[7] + 4) >> 3;
729 Des
[4] = (x
[2] + x
[3] +x
[4] + x
[5] * 2 + x
[6] + x
[7] +x
[8] + 4) >> 3;
730 Des
[5] = (x
[3] + x
[4] +x
[5] + x
[6] * 2 + x
[7] + x
[8] +x
[9] + 4) >> 3;
731 Des
[6] = (x
[4] + x
[5] +x
[6] + x
[7] * 2 + x
[8] + x
[9] +x
[9] + 4) >> 3;
732 Des
[7] = (x
[5] + x
[6] +x
[7] + x
[8] * 2 + x
[9] + x
[9] +x
[9] + 4) >> 3;
735 Src
+= PlaneLineStep
;
736 Des
+= PlaneLineStep
;
743 static void DeblockVerticalEdgesInLoopFilteredBand(PB_INSTANCE
*pbi
,
744 unsigned char *SrcPtr
,
745 unsigned char *DesPtr
,
746 ogg_uint32_t PlaneLineStep
,
747 ogg_uint32_t FragsAcross
,
748 ogg_uint32_t StartFrag
,
749 const ogg_uint32_t
*QuantScale
){
751 ogg_uint32_t CurrentFrag
=StartFrag
;
754 unsigned char *Src
, *Des
;
756 ogg_int32_t Sum1
, Sum2
;
758 while(CurrentFrag
< StartFrag
+ FragsAcross
-1) {
760 Src
=SrcPtr
+8*(CurrentFrag
-StartFrag
+1)-5;
761 Des
=DesPtr
+8*(CurrentFrag
-StartFrag
+1)-4;
763 QStep
= QuantScale
[pbi
->FragQIndex
[CurrentFrag
+1]];
764 FLimit
= ( QStep
* 3)>>2 ;
766 for( j
=0; j
<8 ; j
++){
781 Sum1
+= abs(x
[k
]-x
[k
-1]);
782 Sum2
+= abs(x
[k
+4]-x
[k
+5]);
785 pbi
->FragmentVariances
[CurrentFrag
] += ((Sum1
>255)?255:Sum1
);
786 pbi
->FragmentVariances
[CurrentFrag
+1] += ((Sum2
>255)?255:Sum2
);
791 (x
[5] - x
[4]) < QStep
&&
792 (x
[4] - x
[5]) < QStep
){
794 /* low pass filtering (LPF7: 1 1 1 2 1 1 1) */
795 Des
[0] = (x
[0] + x
[0] +x
[0] + x
[1] * 2 + x
[2] + x
[3] +x
[4] + 4) >> 3;
796 Des
[1] = (x
[0] + x
[0] +x
[1] + x
[2] * 2 + x
[3] + x
[4] +x
[5] + 4) >> 3;
797 Des
[2] = (x
[0] + x
[1] +x
[2] + x
[3] * 2 + x
[4] + x
[5] +x
[6] + 4) >> 3;
798 Des
[3] = (x
[1] + x
[2] +x
[3] + x
[4] * 2 + x
[5] + x
[6] +x
[7] + 4) >> 3;
799 Des
[4] = (x
[2] + x
[3] +x
[4] + x
[5] * 2 + x
[6] + x
[7] +x
[8] + 4) >> 3;
800 Des
[5] = (x
[3] + x
[4] +x
[5] + x
[6] * 2 + x
[7] + x
[8] +x
[9] + 4) >> 3;
801 Des
[6] = (x
[4] + x
[5] +x
[6] + x
[7] * 2 + x
[8] + x
[9] +x
[9] + 4) >> 3;
802 Des
[7] = (x
[5] + x
[6] +x
[7] + x
[8] * 2 + x
[9] + x
[9] +x
[9] + 4) >> 3;
812 static void DeblockPlane(PB_INSTANCE
*pbi
,
813 unsigned char *SourceBuffer
,
814 unsigned char *DestinationBuffer
,
815 ogg_uint32_t Channel
){
818 ogg_uint32_t PlaneLineStep
=0;
819 ogg_uint32_t StartFrag
=0;
820 ogg_uint32_t PixelIndex
=0;
821 unsigned char * SrcPtr
=0, * DesPtr
=0;
822 ogg_uint32_t FragsAcross
=0;
823 ogg_uint32_t FragsDown
=0;
824 const ogg_uint32_t
*QuantScale
=0;
828 /* Get the parameters */
829 PlaneLineStep
= pbi
->YStride
;
830 FragsAcross
= pbi
->HFragments
;
831 FragsDown
= pbi
->VFragments
;
833 PixelIndex
= pbi
->ReconYDataOffset
;
834 SrcPtr
= & SourceBuffer
[PixelIndex
];
835 DesPtr
= & DestinationBuffer
[PixelIndex
];
839 /* Get the parameters */
840 PlaneLineStep
= pbi
->UVStride
;
841 FragsAcross
= pbi
->HFragments
/ 2;
842 FragsDown
= pbi
->VFragments
/ 2;
843 StartFrag
= pbi
->YPlaneFragments
;
845 PixelIndex
= pbi
->ReconUDataOffset
;
846 SrcPtr
= & SourceBuffer
[PixelIndex
];
847 DesPtr
= & DestinationBuffer
[PixelIndex
];
851 /* Get the parameters */
852 PlaneLineStep
= pbi
->UVStride
;
853 FragsAcross
= pbi
->HFragments
/ 2;
854 FragsDown
= pbi
->VFragments
/ 2;
855 StartFrag
= pbi
->YPlaneFragments
+ pbi
->UVPlaneFragments
;
857 PixelIndex
= pbi
->ReconVDataOffset
;
858 SrcPtr
= & SourceBuffer
[PixelIndex
];
859 DesPtr
= & DestinationBuffer
[PixelIndex
];
863 QuantScale
= DcQuantScaleV1
;
866 memcpy(DesPtr
+i
*PlaneLineStep
, SrcPtr
+i
*PlaneLineStep
, PlaneLineStep
);
870 while( k
< FragsDown
){
872 SrcPtr
+= 8*PlaneLineStep
;
873 DesPtr
+= 8*PlaneLineStep
;
875 /* Filter both the horizontal and vertical block edges inside the band */
876 DeblockLoopFilteredBand(pbi
, SrcPtr
, DesPtr
, PlaneLineStep
,
877 FragsAcross
, StartFrag
, QuantScale
);
880 StartFrag
+= FragsAcross
;
887 memcpy(DesPtr
+(i
+4)*PlaneLineStep
,
888 SrcPtr
+(i
+4)*PlaneLineStep
,
891 DeblockVerticalEdgesInLoopFilteredBand(pbi
,SrcPtr
,DesPtr
,PlaneLineStep
,
892 FragsAcross
,StartFrag
,QuantScale
);
896 static void DeblockFrame(PB_INSTANCE
*pbi
, unsigned char *SourceBuffer
,
897 unsigned char *DestinationBuffer
){
899 memset(pbi
->FragmentVariances
, 0 , sizeof(ogg_int32_t
) * pbi
->UnitFragments
);
902 UpdateFragQIndex(pbi
);
905 SetupLoopFilter(pbi
);
908 DeblockPlane( pbi
, SourceBuffer
, DestinationBuffer
, 0);
911 DeblockPlane( pbi
, SourceBuffer
, DestinationBuffer
, 1);
914 DeblockPlane( pbi
, SourceBuffer
, DestinationBuffer
, 2);
918 void PostProcess(PB_INSTANCE
*pbi
){
920 switch (pbi
->PostProcessingLevel
){
922 /* on a slow machine, use a simpler and faster deblocking filter */
923 DeblockFrame(pbi
, pbi
->LastFrameRecon
,pbi
->PostProcessBuffer
);
927 DeblockFrame(pbi
, pbi
->LastFrameRecon
,pbi
->PostProcessBuffer
);
928 UpdateUMVBorder(pbi
, pbi
->PostProcessBuffer
);
929 DeringFrame(pbi
, pbi
->PostProcessBuffer
, pbi
->PostProcessBuffer
);
933 DeblockFrame(pbi
, pbi
->LastFrameRecon
,pbi
->PostProcessBuffer
);
934 UpdateUMVBorder(pbi
, pbi
->PostProcessBuffer
);
935 DeringFrame(pbi
, pbi
->PostProcessBuffer
, pbi
->PostProcessBuffer
);
938 DeblockFrame(pbi
, pbi
->LastFrameRecon
, pbi
->PostProcessBuffer
);
941 UpdateFragQIndex(pbi
);
948 DeblockFrame(pbi
, pbi
->LastFrameRecon
, pbi
->PostProcessBuffer
);
949 UpdateUMVBorder(pbi
, pbi
->PostProcessBuffer
);
950 DeringFrame(pbi
, pbi
->PostProcessBuffer
, pbi
->PostProcessBuffer
);