1 /* ------------------------------------------------------------------
2  * Copyright (C) 1998-2009 PacketVideo
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13  * express or implied.
14  * See the License for the specific language governing permissions
15  * and limitations under the License.
16  * -------------------------------------------------------------------
17  */
18 
19 #include <string.h>
20 
21 #include "avclib_common.h"
22 
23 #define MAX_QP 51
24 #define MB_BLOCK_SIZE 16
25 
26 // NOTE: these 3 tables are for funtion GetStrength() only
27 const static int ININT_STRENGTH[4] = {0x04040404, 0x03030303, 0x03030303, 0x03030303};
28 
29 
30 // NOTE: these 3 tables are for funtion EdgeLoop() only
31 // NOTE: to change the tables below for instance when the QP doubling is changed from 6 to 8 values
32 
33 const static int ALPHA_TABLE[52]  = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 5, 6,  7, 8, 9, 10, 12, 13, 15, 17,  20, 22, 25, 28, 32, 36, 40, 45,  50, 56, 63, 71, 80, 90, 101, 113,  127, 144, 162, 182, 203, 226, 255, 255} ;
34 const static int BETA_TABLE[52]   = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 3,  3, 3, 3, 4, 4, 4, 6, 6,   7, 7, 8, 8, 9, 9, 10, 10,  11, 11, 12, 12, 13, 13, 14, 14,   15, 15, 16, 16, 17, 17, 18, 18} ;
35 const static int CLIP_TAB[52][5]  =
36 {
37     { 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0},
38     { 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0},
39     { 0, 0, 0, 0, 0}, { 0, 0, 0, 1, 1}, { 0, 0, 0, 1, 1}, { 0, 0, 0, 1, 1}, { 0, 0, 0, 1, 1}, { 0, 0, 1, 1, 1}, { 0, 0, 1, 1, 1}, { 0, 1, 1, 1, 1},
40     { 0, 1, 1, 1, 1}, { 0, 1, 1, 1, 1}, { 0, 1, 1, 1, 1}, { 0, 1, 1, 2, 2}, { 0, 1, 1, 2, 2}, { 0, 1, 1, 2, 2}, { 0, 1, 1, 2, 2}, { 0, 1, 2, 3, 3},
41     { 0, 1, 2, 3, 3}, { 0, 2, 2, 3, 3}, { 0, 2, 2, 4, 4}, { 0, 2, 3, 4, 4}, { 0, 2, 3, 4, 4}, { 0, 3, 3, 5, 5}, { 0, 3, 4, 6, 6}, { 0, 3, 4, 6, 6},
42     { 0, 4, 5, 7, 7}, { 0, 4, 5, 8, 8}, { 0, 4, 6, 9, 9}, { 0, 5, 7, 10, 10}, { 0, 6, 8, 11, 11}, { 0, 6, 8, 13, 13}, { 0, 7, 10, 14, 14}, { 0, 8, 11, 16, 16},
43     { 0, 9, 12, 18, 18}, { 0, 10, 13, 20, 20}, { 0, 11, 15, 23, 23}, { 0, 13, 17, 25, 25}
44 };
45 
46 // NOTE: this table is only QP clipping, index = QP + video->FilterOffsetA/B, clipped to [0, 51]
47 //       video->FilterOffsetA/B is in {-12, 12]
48 const static int QP_CLIP_TAB[76] =
49 {
50     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,              // [-12, 0]
51     1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
52     13, 14, 15, 16, 17, 18, 19, 20, 21,
53     22, 23, 24, 25, 26, 27, 28, 29, 30,
54     31, 32, 33, 34, 35, 36, 37, 38, 39,
55     40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // [1, 51]
56     51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51      // [52,63]
57 };
58 
59 static void DeblockMb(AVCCommonObj *video, int mb_x, int mb_y, uint8 *SrcY, uint8 *SrcU, uint8 *SrcV);
60 //static void GetStrength(AVCCommonObj *video, uint8 *Strength, AVCMacroblock* MbP, AVCMacroblock* MbQ, int dir, int edge);
61 static void GetStrength_Edge0(uint8 *Strength, AVCMacroblock* MbP, AVCMacroblock* MbQ, int dir);
62 static void GetStrength_VerticalEdges(uint8 *Strength, AVCMacroblock* MbQ);
63 static void GetStrength_HorizontalEdges(uint8 Strength[12], AVCMacroblock* MbQ);
64 static void EdgeLoop_Luma_vertical(uint8* SrcPtr, uint8 *Strength, int Alpha, int Beta, int *clipTable, int pitch);
65 static void EdgeLoop_Luma_horizontal(uint8* SrcPtr, uint8 *Strength, int Alpha, int Beta, int *clipTable, int pitch);
66 static void EdgeLoop_Chroma_vertical(uint8* SrcPtr, uint8 *Strength, int Alpha, int Beta, int *clipTable, int pitch);
67 static void EdgeLoop_Chroma_horizontal(uint8* SrcPtr, uint8 *Strength, int Alpha, int Beta, int *clipTable, int pitch);
68 
69 /*
70  *****************************************************************************************
71  * \brief Filter all macroblocks in order of increasing macroblock address.
72  *****************************************************************************************
73 */
74 
DeblockPicture(AVCCommonObj * video)75 OSCL_EXPORT_REF AVCStatus DeblockPicture(AVCCommonObj *video)
76 {
77     uint   i, j;
78     int   pitch = video->currPic->pitch, pitch_c, width;
79     uint8 *SrcY, *SrcU, *SrcV;
80 
81     SrcY = video->currPic->Sl;      // pointers to source
82     SrcU = video->currPic->Scb;
83     SrcV = video->currPic->Scr;
84     pitch_c = pitch >> 1;
85     width = video->currPic->width;
86 
87     for (i = 0; i < video->PicHeightInMbs; i++)
88     {
89         for (j = 0; j < video->PicWidthInMbs; j++)
90         {
91             DeblockMb(video, j, i, SrcY, SrcU, SrcV);
92             // update SrcY, SrcU, SrcV
93             SrcY += MB_BLOCK_SIZE;
94             SrcU += (MB_BLOCK_SIZE >> 1);
95             SrcV += (MB_BLOCK_SIZE >> 1);
96         }
97 
98         SrcY += ((pitch << 4) - width);
99         SrcU += ((pitch_c << 3) - (width >> 1));
100         SrcV += ((pitch_c << 3) - (width >> 1));
101     }
102 
103     return AVC_SUCCESS;
104 }
105 
106 #ifdef MB_BASED_DEBLOCK
107 /*
108  *****************************************************************************************
109  * \brief Filter one macroblocks in a fast macroblock memory and copy it to frame
110  *****************************************************************************************
111 */
MBInLoopDeblock(AVCCommonObj * video)112 void MBInLoopDeblock(AVCCommonObj *video)
113 {
114     AVCPictureData *currPic = video->currPic;
115 #ifdef USE_PRED_BLOCK
116     uint8 *predCb, *predCr, *pred_block;
117     int i, j, dst_width, dst_height, dst_widthc, dst_heightc;
118 #endif
119     int pitch = currPic->pitch;
120     int x_pos = video->mb_x;
121     int y_pos = video->mb_y;
122     uint8 *curL, *curCb, *curCr;
123     int offset;
124 
125     offset = (y_pos << 4) * pitch;
126 
127     curL = currPic->Sl + offset + (x_pos << 4);
128 
129     offset >>= 2;
130     offset += (x_pos << 3);
131 
132     curCb = currPic->Scb + offset;
133     curCr = currPic->Scr + offset;
134 
135 #ifdef USE_PRED_BLOCK
136     pred_block = video->pred;
137 
138     /* 1. copy neighboring pixels from frame to the video->pred_block */
139     if (y_pos) /* not the 0th row */
140     {
141         /* copy to the top 4 lines of the macroblock */
142         curL -= (pitch << 2); /* go back 4 lines */
143 
144         memcpy(pred_block + 4, curL, 16);
145         curL += pitch;
146         memcpy(pred_block + 24, curL, 16);
147         curL += pitch;
148         memcpy(pred_block + 44, curL, 16);
149         curL += pitch;
150         memcpy(pred_block + 64, curL, 16);
151         curL += pitch;
152 
153         curCb -= (pitch << 1); /* go back 4 lines chroma */
154         curCr -= (pitch << 1);
155 
156         pred_block += 400;
157 
158         memcpy(pred_block + 4, curCb, 8);
159         curCb += (pitch >> 1);
160         memcpy(pred_block + 16, curCb, 8);
161         curCb += (pitch >> 1);
162         memcpy(pred_block + 28, curCb, 8);
163         curCb += (pitch >> 1);
164         memcpy(pred_block + 40, curCb, 8);
165         curCb += (pitch >> 1);
166 
167         pred_block += 144;
168         memcpy(pred_block + 4, curCr, 8);
169         curCr += (pitch >> 1);
170         memcpy(pred_block + 16, curCr, 8);
171         curCr += (pitch >> 1);
172         memcpy(pred_block + 28, curCr, 8);
173         curCr += (pitch >> 1);
174         memcpy(pred_block + 40, curCr, 8);
175         curCr += (pitch >> 1);
176 
177         pred_block = video->pred;
178     }
179 
180     /* 2. perform deblocking. */
181     DeblockMb(video, x_pos, y_pos, pred_block + 84, pred_block + 452, pred_block + 596);
182 
183     /* 3. copy it back to the frame and update pred_block */
184     predCb = pred_block + 400;
185     predCr = predCb + 144;
186 
187     /* find the range of the block inside pred_block to be copied back */
188     if (y_pos)  /* the first row */
189     {
190         curL -= (pitch << 2);
191         curCb -= (pitch << 1);
192         curCr -= (pitch << 1);
193 
194         dst_height = 20;
195         dst_heightc = 12;
196     }
197     else
198     {
199         pred_block += 80;
200         predCb += 48;
201         predCr += 48;
202         dst_height = 16;
203         dst_heightc = 8;
204     }
205 
206     if (x_pos) /* find the width */
207     {
208         curL -= 4;
209         curCb -= 4;
210         curCr -= 4;
211         if (x_pos == (int)(video->PicWidthInMbs - 1))
212         {
213             dst_width = 20;
214             dst_widthc = 12;
215         }
216         else
217         {
218             dst_width = 16;
219             dst_widthc = 8;
220         }
221     }
222     else
223     {
224         pred_block += 4;
225         predCb += 4;
226         predCr += 4;
227         dst_width = 12;
228         dst_widthc = 4;
229     }
230 
231     /* perform copy */
232     for (j = 0; j < dst_height; j++)
233     {
234         memcpy(curL, pred_block, dst_width);
235         curL += pitch;
236         pred_block += 20;
237     }
238     for (j = 0; j < dst_heightc; j++)
239     {
240         memcpy(curCb, predCb, dst_widthc);
241         memcpy(curCr, predCr, dst_widthc);
242         curCb += (pitch >> 1);
243         curCr += (pitch >> 1);
244         predCb += 12;
245         predCr += 12;
246     }
247 
248     if (x_pos != (int)(video->PicWidthInMbs - 1)) /* now copy from the right-most 4 columns to the left-most 4 columns */
249     {
250         pred_block = video->pred;
251         for (i = 0; i < 20; i += 4)
252         {
253             *((uint32*)pred_block) = *((uint32*)(pred_block + 16));
254             pred_block += 20;
255             *((uint32*)pred_block) = *((uint32*)(pred_block + 16));
256             pred_block += 20;
257             *((uint32*)pred_block) = *((uint32*)(pred_block + 16));
258             pred_block += 20;
259             *((uint32*)pred_block) = *((uint32*)(pred_block + 16));
260             pred_block += 20;
261         }
262 
263         for (i = 0; i < 24; i += 4)
264         {
265             *((uint32*)pred_block) = *((uint32*)(pred_block + 8));
266             pred_block += 12;
267             *((uint32*)pred_block) = *((uint32*)(pred_block + 8));
268             pred_block += 12;
269             *((uint32*)pred_block) = *((uint32*)(pred_block + 8));
270             pred_block += 12;
271             *((uint32*)pred_block) = *((uint32*)(pred_block + 8));
272             pred_block += 12;
273         }
274 
275     }
276 #else
277     DeblockMb(video, x_pos, y_pos, curL, curCb, curCr);
278 #endif
279 
280     return ;
281 }
282 #endif
283 
284 /*
285  *****************************************************************************************
286  * \brief Deblocking filter for one macroblock.
287  *****************************************************************************************
288  */
289 
DeblockMb(AVCCommonObj * video,int mb_x,int mb_y,uint8 * SrcY,uint8 * SrcU,uint8 * SrcV)290 void DeblockMb(AVCCommonObj *video, int mb_x, int mb_y, uint8 *SrcY, uint8 *SrcU, uint8 *SrcV)
291 {
292     AVCMacroblock *MbP, *MbQ;
293     int     edge, QP, QPC;
294     int     filterLeftMbEdgeFlag = (mb_x != 0);
295     int     filterTopMbEdgeFlag  = (mb_y != 0);
296     int     pitch = video->currPic->pitch;
297     int     indexA, indexB;
298     int     *tmp;
299     int     Alpha, Beta, Alpha_c, Beta_c;
300     int     mbNum = mb_y * video->PicWidthInMbs + mb_x;
301     int     *clipTable, *clipTable_c, *qp_clip_tab;
302     uint8   Strength[16];
303     void*     str;
304 
305     MbQ = &(video->mblock[mbNum]);      // current Mb
306 
307 
308     // If filter is disabled, return
309     if (video->sliceHdr->disable_deblocking_filter_idc == 1) return;
310 
311     if (video->sliceHdr->disable_deblocking_filter_idc == 2)
312     {
313         // don't filter at slice boundaries
314         filterLeftMbEdgeFlag = mb_is_available(video->mblock, video->PicSizeInMbs, mbNum - 1, mbNum);
315         filterTopMbEdgeFlag  = mb_is_available(video->mblock, video->PicSizeInMbs, mbNum - video->PicWidthInMbs, mbNum);
316     }
317 
318     /* NOTE: edge=0 and edge=1~3 are separate cases because of the difference of MbP, index A and indexB calculation */
319     /*       for edge = 1~3, MbP, indexA and indexB remain the same, and thus there is no need to re-calculate them for each edge */
320 
321     qp_clip_tab = (int *)QP_CLIP_TAB + 12;
322 
323     /* 1.VERTICAL EDGE + MB BOUNDARY (edge = 0) */
324     if (filterLeftMbEdgeFlag)
325     {
326         MbP = MbQ - 1;
327         //GetStrength(video, Strength, MbP, MbQ, 0, 0); // Strength for 4 blks in 1 stripe, 0 => vertical edge
328         GetStrength_Edge0(Strength, MbP, MbQ, 0);
329 
330         str = (void*)Strength; //de-ref type-punned pointer fix
331         if (*((uint32*)str))    // only if one of the 4 Strength bytes is != 0
332         {
333             QP = (MbP->QPy + MbQ->QPy + 1) >> 1; // Average QP of the two blocks;
334             indexA = QP + video->FilterOffsetA;
335             indexB = QP + video->FilterOffsetB;
336             indexA = qp_clip_tab[indexA]; // IClip(0, MAX_QP, QP+video->FilterOffsetA)
337             indexB = qp_clip_tab[indexB]; // IClip(0, MAX_QP, QP+video->FilterOffsetB)
338 
339             Alpha  = ALPHA_TABLE[indexA];
340             Beta = BETA_TABLE[indexB];
341             clipTable = (int *) CLIP_TAB[indexA];
342 
343             if (Alpha > 0 && Beta > 0)
344 #ifdef USE_PRED_BLOCK
345                 EdgeLoop_Luma_vertical(SrcY, Strength,  Alpha, Beta, clipTable, 20);
346 #else
347                 EdgeLoop_Luma_vertical(SrcY, Strength,  Alpha, Beta, clipTable, pitch);
348 #endif
349 
350             QPC = (MbP->QPc + MbQ->QPc + 1) >> 1;
351             indexA = QPC + video->FilterOffsetA;
352             indexB = QPC + video->FilterOffsetB;
353             indexA = qp_clip_tab[indexA]; // IClip(0, MAX_QP, QP+video->FilterOffsetA)
354             indexB = qp_clip_tab[indexB]; // IClip(0, MAX_QP, QP+video->FilterOffsetB)
355 
356             Alpha  = ALPHA_TABLE[indexA];
357             Beta = BETA_TABLE[indexB];
358             clipTable = (int *) CLIP_TAB[indexA];
359             if (Alpha > 0 && Beta > 0)
360             {
361 #ifdef USE_PRED_BLOCK
362                 EdgeLoop_Chroma_vertical(SrcU, Strength, Alpha, Beta, clipTable, 12);
363                 EdgeLoop_Chroma_vertical(SrcV, Strength, Alpha, Beta, clipTable, 12);
364 #else
365                 EdgeLoop_Chroma_vertical(SrcU, Strength, Alpha, Beta, clipTable, pitch >> 1);
366                 EdgeLoop_Chroma_vertical(SrcV, Strength, Alpha, Beta, clipTable, pitch >> 1);
367 #endif
368             }
369         }
370 
371     } /* end of: if(filterLeftMbEdgeFlag) */
372 
373     /* 2.VERTICAL EDGE (no boundary), the edges are all inside a MB */
374     /* First calculate the necesary parameters all at once, outside the loop */
375     MbP = MbQ;
376 
377     indexA = MbQ->QPy + video->FilterOffsetA;
378     indexB = MbQ->QPy + video->FilterOffsetB;
379     //  index
380     indexA = qp_clip_tab[indexA]; // IClip(0, MAX_QP, QP+video->FilterOffsetA)
381     indexB = qp_clip_tab[indexB]; // IClip(0, MAX_QP, QP+video->FilterOffsetB)
382 
383     Alpha = ALPHA_TABLE[indexA];
384     Beta = BETA_TABLE[indexB];
385     clipTable = (int *)CLIP_TAB[indexA];
386 
387     /* Save Alpha,  Beta and clipTable for future use, with the obselete variables filterLeftMbEdgeFlag, mbNum amd tmp */
388     filterLeftMbEdgeFlag = Alpha;
389     mbNum = Beta;
390     tmp = clipTable;
391 
392     indexA = MbQ->QPc + video->FilterOffsetA;
393     indexB = MbQ->QPc + video->FilterOffsetB;
394     indexA = qp_clip_tab[indexA]; // IClip(0, MAX_QP, QP+video->FilterOffsetA)
395     indexB = qp_clip_tab[indexB]; // IClip(0, MAX_QP, QP+video->FilterOffsetB)
396 
397     Alpha_c  = ALPHA_TABLE[indexA];
398     Beta_c = BETA_TABLE[indexB];
399     clipTable_c = (int *)CLIP_TAB[indexA];
400 
401     GetStrength_VerticalEdges(Strength + 4, MbQ); // Strength for 4 blks in 1 stripe, 0 => vertical edge
402 
403     for (edge = 1; edge < 4; edge++)  // 4 vertical strips of 16 pel
404     {
405         //GetStrength_VerticalEdges(video, Strength, MbP, MbQ, 0, edge); // Strength for 4 blks in 1 stripe, 0 => vertical edge
406         if (*((int*)(Strength + (edge << 2))))   // only if one of the 4 Strength bytes is != 0
407         {
408             if (Alpha > 0 && Beta > 0)
409 #ifdef USE_PRED_BLOCK
410                 EdgeLoop_Luma_vertical(SrcY + (edge << 2), Strength + (edge << 2),  Alpha, Beta, clipTable, 20);
411 #else
412                 EdgeLoop_Luma_vertical(SrcY + (edge << 2), Strength + (edge << 2),  Alpha, Beta, clipTable, pitch);
413 #endif
414 
415             if (!(edge & 1) && Alpha_c > 0 && Beta_c > 0)
416             {
417 #ifdef USE_PRED_BLOCK
418                 EdgeLoop_Chroma_vertical(SrcU + (edge << 1), Strength + (edge << 2), Alpha_c, Beta_c, clipTable_c, 12);
419                 EdgeLoop_Chroma_vertical(SrcV + (edge << 1), Strength + (edge << 2), Alpha_c, Beta_c, clipTable_c, 12);
420 #else
421                 EdgeLoop_Chroma_vertical(SrcU + (edge << 1), Strength + (edge << 2), Alpha_c, Beta_c, clipTable_c, pitch >> 1);
422                 EdgeLoop_Chroma_vertical(SrcV + (edge << 1), Strength + (edge << 2), Alpha_c, Beta_c, clipTable_c, pitch >> 1);
423 #endif
424             }
425         }
426 
427     } //end edge
428 
429 
430 
431     /* 3.HORIZONTAL EDGE + MB BOUNDARY (edge = 0) */
432     if (filterTopMbEdgeFlag)
433     {
434         MbP = MbQ - video->PicWidthInMbs;
435         //GetStrength(video, Strength, MbP, MbQ, 1, 0); // Strength for 4 blks in 1 stripe, 0 => vertical edge
436         GetStrength_Edge0(Strength, MbP, MbQ, 1);
437         str = (void*)Strength; //de-ref type-punned pointer fix
438         if (*((uint32*)str))    // only if one of the 4 Strength bytes is != 0
439         {
440             QP = (MbP->QPy + MbQ->QPy + 1) >> 1; // Average QP of the two blocks;
441             indexA = QP + video->FilterOffsetA;
442             indexB = QP + video->FilterOffsetB;
443             indexA = qp_clip_tab[indexA]; // IClip(0, MAX_QP, QP+video->FilterOffsetA)
444             indexB = qp_clip_tab[indexB]; // IClip(0, MAX_QP, QP+video->FilterOffsetB)
445 
446             Alpha  = ALPHA_TABLE[indexA];
447             Beta = BETA_TABLE[indexB];
448             clipTable = (int *)CLIP_TAB[indexA];
449 
450             if (Alpha > 0 && Beta > 0)
451             {
452 #ifdef USE_PRED_BLOCK
453                 EdgeLoop_Luma_horizontal(SrcY, Strength,  Alpha, Beta, clipTable, 20);
454 #else
455                 EdgeLoop_Luma_horizontal(SrcY, Strength,  Alpha, Beta, clipTable, pitch);
456 #endif
457             }
458 
459             QPC = (MbP->QPc + MbQ->QPc + 1) >> 1;
460             indexA = QPC + video->FilterOffsetA;
461             indexB = QPC + video->FilterOffsetB;
462             indexA = qp_clip_tab[indexA]; // IClip(0, MAX_QP, QP+video->FilterOffsetA)
463             indexB = qp_clip_tab[indexB]; // IClip(0, MAX_QP, QP+video->FilterOffsetB)
464 
465             Alpha  = ALPHA_TABLE[indexA];
466             Beta = BETA_TABLE[indexB];
467             clipTable = (int *)CLIP_TAB[indexA];
468             if (Alpha > 0 && Beta > 0)
469             {
470 #ifdef USE_PRED_BLOCK
471                 EdgeLoop_Chroma_horizontal(SrcU, Strength, Alpha, Beta, clipTable, 12);
472                 EdgeLoop_Chroma_horizontal(SrcV, Strength, Alpha, Beta, clipTable, 12);
473 #else
474                 EdgeLoop_Chroma_horizontal(SrcU, Strength, Alpha, Beta, clipTable, pitch >> 1);
475                 EdgeLoop_Chroma_horizontal(SrcV, Strength, Alpha, Beta, clipTable, pitch >> 1);
476 #endif
477             }
478         }
479 
480     } /* end of: if(filterTopMbEdgeFlag) */
481 
482 
483     /* 4.HORIZONTAL EDGE (no boundary), the edges are inside a MB */
484     MbP = MbQ;
485 
486     /* Recover Alpha,  Beta and clipTable for edge!=0 with the variables filterLeftMbEdgeFlag, mbNum and tmp */
487     /* Note that Alpha_c, Beta_c and clipTable_c for chroma is already calculated */
488     Alpha = filterLeftMbEdgeFlag;
489     Beta = mbNum;
490     clipTable = tmp;
491 
492     GetStrength_HorizontalEdges(Strength + 4, MbQ); // Strength for 4 blks in 1 stripe, 0 => vertical edge
493 
494     for (edge = 1; edge < 4; edge++)  // 4 horicontal strips of 16 pel
495     {
496         //GetStrength(video, Strength, MbP, MbQ, 1, edge); // Strength for 4 blks in 1 stripe   1 => horizontal edge
497         if (*((int*)(Strength + (edge << 2)))) // only if one of the 4 Strength bytes is != 0
498         {
499             if (Alpha > 0 && Beta > 0)
500             {
501 #ifdef USE_PRED_BLOCK
502                 EdgeLoop_Luma_horizontal(SrcY + (edge << 2)*20, Strength + (edge << 2),  Alpha, Beta, clipTable, 20);
503 #else
504                 EdgeLoop_Luma_horizontal(SrcY + (edge << 2)*pitch, Strength + (edge << 2),  Alpha, Beta, clipTable, pitch);
505 #endif
506             }
507 
508             if (!(edge & 1) && Alpha_c > 0 && Beta_c > 0)
509             {
510 #ifdef USE_PRED_BLOCK
511                 EdgeLoop_Chroma_horizontal(SrcU + (edge << 1)*12, Strength + (edge << 2), Alpha_c, Beta_c, clipTable_c, 12);
512                 EdgeLoop_Chroma_horizontal(SrcV + (edge << 1)*12, Strength + (edge << 2), Alpha_c, Beta_c, clipTable_c, 12);
513 #else
514                 EdgeLoop_Chroma_horizontal(SrcU + (edge << 1)*(pitch >> 1), Strength + (edge << 2), Alpha_c, Beta_c, clipTable_c, pitch >> 1);
515                 EdgeLoop_Chroma_horizontal(SrcV + (edge << 1)*(pitch >> 1), Strength + (edge << 2), Alpha_c, Beta_c, clipTable_c, pitch >> 1);
516 #endif
517             }
518         }
519 
520     } //end edge
521 
522     return;
523 }
524 
525 /*
526  *****************************************************************************************************
527  * \brief   returns a buffer of 4 Strength values for one stripe in a mb (for different Frame types)
528  *****************************************************************************************************
529 */
530 
GetStrength_Edge0(uint8 * Strength,AVCMacroblock * MbP,AVCMacroblock * MbQ,int dir)531 void GetStrength_Edge0(uint8 *Strength, AVCMacroblock* MbP, AVCMacroblock* MbQ, int dir)
532 {
533     int tmp;
534     int16 *ptrQ, *ptrP;
535     void* vptr;
536     uint8 *pStrength;
537     void* refIdx;
538 
539     if (MbP->mbMode == AVC_I4 || MbP->mbMode == AVC_I16 ||
540             MbQ->mbMode == AVC_I4 || MbQ->mbMode == AVC_I16)
541     {
542 
543         *((int*)Strength) = ININT_STRENGTH[0];      // Start with Strength=3. or Strength=4 for Mb-edge
544 
545     }
546     else // if not intra or SP-frame
547     {
548         *((int*)Strength) = 0;
549 
550         if (dir == 0)  // Vertical Edge 0
551         {
552 
553             //1. Check the ref_frame_id
554             refIdx = (void*) MbQ->RefIdx; //de-ref type-punned pointer fix
555             ptrQ = (int16*)refIdx;
556             refIdx = (void*)MbP->RefIdx; //de-ref type-punned pointer fix
557             ptrP = (int16*)refIdx;
558             pStrength = Strength;
559             if (ptrQ[0] != ptrP[1]) pStrength[0] = 1;
560             if (ptrQ[2] != ptrP[3]) pStrength[2] = 1;
561             pStrength[1] = pStrength[0];
562             pStrength[3] = pStrength[2];
563 
564             //2. Check the non-zero coeff blocks (4x4)
565             if (MbQ->nz_coeff[0] != 0 || MbP->nz_coeff[3] != 0) pStrength[0] = 2;
566             if (MbQ->nz_coeff[4] != 0 || MbP->nz_coeff[7] != 0) pStrength[1] = 2;
567             if (MbQ->nz_coeff[8] != 0 || MbP->nz_coeff[11] != 0) pStrength[2] = 2;
568             if (MbQ->nz_coeff[12] != 0 || MbP->nz_coeff[15] != 0) pStrength[3] = 2;
569 
570             //3. Only need to check the mv difference
571             vptr = (void*)MbQ->mvL0;  // for deref type-punned pointer
572             ptrQ = (int16*)vptr;
573             ptrP = (int16*)(MbP->mvL0 + 3); // points to 4x4 block #3 (the 4th column)
574 
575             // 1st blk
576             if (*pStrength == 0)
577             {
578                 // check |mv difference| >= 4
579                 tmp = *ptrQ++ - *ptrP++;
580                 if (tmp < 0) tmp = -tmp;
581                 if (tmp >= 4) *pStrength = 1;
582 
583                 tmp = *ptrQ-- - *ptrP--;
584                 if (tmp < 0) tmp = -tmp;
585                 if (tmp >= 4) *pStrength = 1;
586             }
587 
588             pStrength++;
589             ptrQ += 8;
590             ptrP += 8;
591 
592             // 2nd blk
593             if (*pStrength == 0)
594             {
595                 // check |mv difference| >= 4
596                 tmp = *ptrQ++ - *ptrP++;
597                 if (tmp < 0) tmp = -tmp;
598                 if (tmp >= 4) *pStrength = 1;
599 
600                 tmp = *ptrQ-- - *ptrP--;
601                 if (tmp < 0) tmp = -tmp;
602                 if (tmp >= 4) *pStrength = 1;
603             }
604 
605             pStrength++;
606             ptrQ += 8;
607             ptrP += 8;
608 
609             // 3rd blk
610             if (*pStrength == 0)
611             {
612                 // check |mv difference| >= 4
613                 tmp = *ptrQ++ - *ptrP++;
614                 if (tmp < 0) tmp = -tmp;
615                 if (tmp >= 4) *pStrength = 1;
616 
617                 tmp = *ptrQ-- - *ptrP--;
618                 if (tmp < 0) tmp = -tmp;
619                 if (tmp >= 4) *pStrength = 1;
620             }
621 
622             pStrength++;
623             ptrQ += 8;
624             ptrP += 8;
625 
626             // 4th blk
627             if (*pStrength == 0)
628             {
629                 // check |mv difference| >= 4
630                 tmp = *ptrQ++ - *ptrP++;
631                 if (tmp < 0) tmp = -tmp;
632                 if (tmp >= 4) *pStrength = 1;
633 
634                 tmp = *ptrQ-- - *ptrP--;
635                 if (tmp < 0) tmp = -tmp;
636                 if (tmp >= 4) *pStrength = 1;
637             }
638         }
639         else   // Horizontal Edge 0
640         {
641 
642             //1. Check the ref_frame_id
643             refIdx = (void*)MbQ->RefIdx;  //de-ref type-punned pointer
644             ptrQ = (int16*)refIdx;
645             refIdx = (void*)MbP->RefIdx;  //de-ref type-punned pointer
646             ptrP = (int16*)refIdx;
647             pStrength = Strength;
648             if (ptrQ[0] != ptrP[2]) pStrength[0] = 1;
649             if (ptrQ[1] != ptrP[3]) pStrength[2] = 1;
650             pStrength[1] = pStrength[0];
651             pStrength[3] = pStrength[2];
652 
653             //2. Check the non-zero coeff blocks (4x4)
654             if (MbQ->nz_coeff[0] != 0 || MbP->nz_coeff[12] != 0) pStrength[0] = 2;
655             if (MbQ->nz_coeff[1] != 0 || MbP->nz_coeff[13] != 0) pStrength[1] = 2;
656             if (MbQ->nz_coeff[2] != 0 || MbP->nz_coeff[14] != 0) pStrength[2] = 2;
657             if (MbQ->nz_coeff[3] != 0 || MbP->nz_coeff[15] != 0) pStrength[3] = 2;
658 
659             //3. Only need to check the mv difference
660             vptr = (void*)MbQ->mvL0;
661             ptrQ = (int16*)vptr;
662             ptrP = (int16*)(MbP->mvL0 + 12); // points to 4x4 block #12 (the 4th row)
663 
664             // 1st blk
665             if (*pStrength == 0)
666             {
667                 // check |mv difference| >= 4
668                 tmp = *ptrQ++ - *ptrP++;
669                 if (tmp < 0) tmp = -tmp;
670                 if (tmp >= 4) *pStrength = 1;
671 
672                 tmp = *ptrQ-- - *ptrP--;
673                 if (tmp < 0) tmp = -tmp;
674                 if (tmp >= 4) *pStrength = 1;
675             }
676 
677             pStrength++;
678             ptrQ += 2;
679             ptrP += 2;
680 
681             // 2nd blk
682             if (*pStrength  == 0)
683             {
684                 // check |mv difference| >= 4
685                 tmp = *ptrQ++ - *ptrP++;
686                 if (tmp < 0) tmp = -tmp;
687                 if (tmp >= 4) *pStrength = 1;
688 
689                 tmp = *ptrQ-- - *ptrP--;
690                 if (tmp < 0) tmp = -tmp;
691                 if (tmp >= 4) *pStrength = 1;
692             }
693 
694             pStrength++;
695             ptrQ += 2;
696             ptrP += 2;
697 
698             // 3rd blk
699             if (*pStrength  == 0)
700             {
701                 // check |mv difference| >= 4
702                 tmp = *ptrQ++ - *ptrP++;
703                 if (tmp < 0) tmp = -tmp;
704                 if (tmp >= 4) *pStrength = 1;
705 
706                 tmp = *ptrQ-- - *ptrP--;
707                 if (tmp < 0) tmp = -tmp;
708                 if (tmp >= 4) *pStrength = 1;
709             }
710 
711             pStrength++;
712             ptrQ += 2;
713             ptrP += 2;
714 
715             // 4th blk
716             if (*pStrength  == 0)
717             {
718                 // check |mv difference| >= 4
719                 tmp = *ptrQ++ - *ptrP++;
720                 if (tmp < 0) tmp = -tmp;
721                 if (tmp >= 4) *pStrength = 1;
722 
723                 tmp = *ptrQ-- - *ptrP--;
724                 if (tmp < 0) tmp = -tmp;
725                 if (tmp >= 4) *pStrength = 1;
726             }
727 
728         } /* end of: else if(dir == 0) */
729 
730     } /* end of: if( !(MbP->mbMode == AVC_I4 ...) */
731 }
732 
733 
GetStrength_VerticalEdges(uint8 * Strength,AVCMacroblock * MbQ)734 void GetStrength_VerticalEdges(uint8 *Strength, AVCMacroblock* MbQ)
735 {
736     int     idx, tmp;
737     int16   *ptr, *pmvx, *pmvy;
738     uint8   *pnz;
739     uint8   *pStrength, *pStr;
740     void* refIdx;
741 
742     if (MbQ->mbMode == AVC_I4 || MbQ->mbMode == AVC_I16)
743     {
744         *((int*)Strength)     = ININT_STRENGTH[1];      // Start with Strength=3. or Strength=4 for Mb-edge
745         *((int*)(Strength + 4)) = ININT_STRENGTH[2];
746         *((int*)(Strength + 8)) = ININT_STRENGTH[3];
747     }
748     else   // Not intra or SP-frame
749     {
750 
751         *((int*)Strength)     = 0; // for non-intra MB, strength = 0, 1 or 2.
752         *((int*)(Strength + 4)) = 0;
753         *((int*)(Strength + 8)) = 0;
754 
755         //1. Check the ref_frame_id
756         refIdx = (void*)MbQ->RefIdx;  //de-ref type-punned pointer fix
757         ptr = (int16*)refIdx;
758         pStrength = Strength;
759         if (ptr[0] != ptr[1]) pStrength[4] = 1;
760         if (ptr[2] != ptr[3]) pStrength[6] = 1;
761         pStrength[5] = pStrength[4];
762         pStrength[7] = pStrength[6];
763 
764         //2. Check the nz_coeff block and mv difference
765         pmvx = (int16*)(MbQ->mvL0 + 1); // points to 4x4 block #1,not #0
766         pmvy = pmvx + 1;
767         for (idx = 0; idx < 4; idx += 2) // unroll the loop, make 4 iterations to 2
768         {
769             // first/third row : 1,2,3 or 9,10,12
770             // Strength = 2 for a whole row
771             pnz = MbQ->nz_coeff + (idx << 2);
772             if (*pnz++ != 0) *pStrength = 2;
773             if (*pnz++ != 0)
774             {
775                 *pStrength = 2;
776                 *(pStrength + 4) = 2;
777             }
778             if (*pnz++ != 0)
779             {
780                 *(pStrength + 4) = 2;
781                 *(pStrength + 8) = 2;
782             }
783             if (*pnz != 0) *(pStrength + 8) = 2;
784 
785             // Then Strength = 1
786             if (*pStrength == 0)
787             {
788                 //within the same 8x8 block, no need to check the reference id
789                 //only need to check the |mv difference| >= 4
790                 tmp = *pmvx - *(pmvx - 2);
791                 if (tmp < 0) tmp = -tmp;
792                 if (tmp >= 4) *pStrength = 1;
793 
794                 tmp = *pmvy - *(pmvy - 2);
795                 if (tmp < 0) tmp = -tmp;
796                 if (tmp >= 4) *pStrength = 1;
797             }
798 
799             pmvx += 2;
800             pmvy += 2;
801             pStr = pStrength + 4;
802 
803             if (*pStr == 0)
804             {
805                 //check the |mv difference| >= 4
806                 tmp = *pmvx - *(pmvx - 2);
807                 if (tmp < 0) tmp = -tmp;
808                 if (tmp >= 4) *pStr = 1;
809 
810                 tmp = *pmvy - *(pmvy - 2);
811                 if (tmp < 0) tmp = -tmp;
812                 if (tmp >= 4) *pStr = 1;
813             }
814 
815             pmvx += 2;
816             pmvy += 2;
817             pStr = pStrength + 8;
818 
819             if (*pStr == 0)
820             {
821                 //within the same 8x8 block, no need to check the reference id
822                 //only need to check the |mv difference| >= 4
823                 tmp = *pmvx - *(pmvx - 2);
824                 if (tmp < 0) tmp = -tmp;
825                 if (tmp >= 4) *pStr = 1;
826 
827                 tmp = *pmvy - *(pmvy - 2);
828                 if (tmp < 0) tmp = -tmp;
829                 if (tmp >= 4) *pStr = 1;
830             }
831 
832             // Second/fourth row: 5,6,7 or 14,15,16
833             // Strength = 2 for a whole row
834             pnz = MbQ->nz_coeff + ((idx + 1) << 2);
835             if (*pnz++ != 0) *(pStrength + 1) = 2;
836             if (*pnz++ != 0)
837             {
838                 *(pStrength + 1) = 2;
839                 *(pStrength + 5) = 2;
840             }
841             if (*pnz++ != 0)
842             {
843                 *(pStrength + 5) = 2;
844                 *(pStrength + 9) = 2;
845             }
846             if (*pnz != 0) *(pStrength + 9) = 2;
847 
848             // Then Strength = 1
849             pmvx += 4;
850             pmvy += 4;
851             pStr = pStrength + 1;
852             if (*pStr == 0)
853             {
854                 //within the same 8x8 block, no need to check the reference id
855                 //only need to check the |mv difference| >= 4
856                 tmp = *pmvx - *(pmvx - 2);
857                 if (tmp < 0) tmp = -tmp;
858                 if (tmp >= 4) *pStr = 1;
859 
860                 tmp = *pmvy - *(pmvy - 2);
861                 if (tmp < 0) tmp = -tmp;
862                 if (tmp >= 4) *pStr = 1;
863             }
864 
865             pmvx += 2;
866             pmvy += 2;
867             pStr = pStrength + 5;
868 
869             if (*pStr == 0)
870             {
871                 //check the |mv difference| >= 4
872                 tmp = *pmvx - *(pmvx - 2);
873                 if (tmp < 0) tmp = -tmp;
874                 if (tmp >= 4) *pStr = 1;
875 
876                 tmp = *pmvy - *(pmvy - 2);
877                 if (tmp < 0) tmp = -tmp;
878                 if (tmp >= 4) *pStr = 1;
879             }
880 
881             pmvx += 2;
882             pmvy += 2;
883             pStr = pStrength + 9;
884 
885             if (*pStr == 0)
886             {
887                 //within the same 8x8 block, no need to check the reference id
888                 //only need to check the |mv difference| >= 4
889                 tmp = *pmvx - *(pmvx - 2);
890                 if (tmp < 0) tmp = -tmp;
891                 if (tmp >= 4) *pStr = 1;
892 
893                 tmp = *pmvy - *(pmvy - 2);
894                 if (tmp < 0) tmp = -tmp;
895                 if (tmp >= 4) *pStr = 1;
896             }
897 
898             // update some variables for the next two rows
899             pmvx += 4;
900             pmvy += 4;
901             pStrength += 2;
902 
903         } /* end of: for(idx=0; idx<2; idx++) */
904 
905     } /* end of: else if( MbQ->mbMode == AVC_I4 ...) */
906 }
907 
908 
GetStrength_HorizontalEdges(uint8 Strength[12],AVCMacroblock * MbQ)909 void GetStrength_HorizontalEdges(uint8 Strength[12], AVCMacroblock* MbQ)
910 {
911     int     idx, tmp;
912     int16   *ptr, *pmvx, *pmvy;
913     uint8   *pStrength, *pStr;
914     void* refIdx;
915 
916     if (MbQ->mbMode == AVC_I4 || MbQ->mbMode == AVC_I16)
917     {
918         *((int*)Strength)     = ININT_STRENGTH[1];      // Start with Strength=3. or Strength=4 for Mb-edge
919         *((int*)(Strength + 4)) = ININT_STRENGTH[2];
920         *((int*)(Strength + 8)) = ININT_STRENGTH[3];
921     }
922     else   // Not intra or SP-frame
923     {
924 
925         *((int*)Strength)     = 0; // for non-intra MB, strength = 0, 1 or 2.
926         *((int*)(Strength + 4)) = 0; // for non-intra MB, strength = 0, 1 or 2.
927         *((int*)(Strength + 8)) = 0; // for non-intra MB, strength = 0, 1 or 2.
928 
929 
930         //1. Check the ref_frame_id
931         refIdx = (void*) MbQ->RefIdx; // de-ref type-punned fix
932         ptr = (int16*) refIdx;
933         pStrength = Strength;
934         if (ptr[0] != ptr[2]) pStrength[4] = 1;
935         if (ptr[1] != ptr[3]) pStrength[6] = 1;
936         pStrength[5] = pStrength[4];
937         pStrength[7] = pStrength[6];
938 
939         //2. Check the nz_coeff block and mv difference
940         pmvx = (int16*)(MbQ->mvL0 + 4); // points to 4x4 block #4,not #0
941         pmvy = pmvx + 1;
942         for (idx = 0; idx < 4; idx += 2) // unroll the loop, make 4 iterations to 2
943         {
944             // first/third row : 1,2,3 or 9,10,12
945             // Strength = 2 for a whole row
946             if (MbQ->nz_coeff[idx] != 0) *pStrength = 2;
947             if (MbQ->nz_coeff[4+idx] != 0)
948             {
949                 *pStrength = 2;
950                 *(pStrength + 4) = 2;
951             }
952             if (MbQ->nz_coeff[8+idx] != 0)
953             {
954                 *(pStrength + 4) = 2;
955                 *(pStrength + 8) = 2;
956             }
957             if (MbQ->nz_coeff[12+idx] != 0) *(pStrength + 8) = 2;
958 
959             // Then Strength = 1
960             if (*pStrength == 0)
961             {
962                 //within the same 8x8 block, no need to check the reference id
963                 //only need to check the |mv difference| >= 4
964                 tmp = *pmvx - *(pmvx - 8);
965                 if (tmp < 0) tmp = -tmp;
966                 if (tmp >= 4) *pStrength = 1;
967 
968                 tmp = *pmvy - *(pmvy - 8);
969                 if (tmp < 0) tmp = -tmp;
970                 if (tmp >= 4) *pStrength = 1;
971             }
972 
973             pmvx += 8;
974             pmvy += 8;
975             pStr = pStrength + 4;
976 
977             if (*pStr == 0)
978             {
979                 //check the |mv difference| >= 4
980                 tmp = *pmvx - *(pmvx - 8);
981                 if (tmp < 0) tmp = -tmp;
982                 if (tmp >= 4) *pStr = 1;
983 
984                 tmp = *pmvy - *(pmvy - 8);
985                 if (tmp < 0) tmp = -tmp;
986                 if (tmp >= 4) *pStr = 1;
987             }
988 
989             pmvx += 8;
990             pmvy += 8;
991             pStr = pStrength + 8;
992 
993             if (*pStr == 0)
994             {
995                 //within the same 8x8 block, no need to check the reference id
996                 //only need to check the |mv difference| >= 4
997                 tmp = *pmvx - *(pmvx - 8);
998                 if (tmp < 0) tmp = -tmp;
999                 if (tmp >= 4) *pStr = 1;
1000 
1001                 tmp = *pmvy - *(pmvy - 8);
1002                 if (tmp < 0) tmp = -tmp;
1003                 if (tmp >= 4) *pStr = 1;
1004             }
1005 
1006             // Second/fourth row: 5,6,7 or 14,15,16
1007             // Strength = 2 for a whole row
1008             if (MbQ->nz_coeff[idx+1] != 0) *(pStrength + 1) = 2;
1009             if (MbQ->nz_coeff[4+idx+1] != 0)
1010             {
1011                 *(pStrength + 1) = 2;
1012                 *(pStrength + 5) = 2;
1013             }
1014             if (MbQ->nz_coeff[8+idx+1] != 0)
1015             {
1016                 *(pStrength + 5) = 2;
1017                 *(pStrength + 9) = 2;
1018             }
1019             if (MbQ->nz_coeff[12+idx+1] != 0) *(pStrength + 9) = 2;
1020 
1021             // Then Strength = 1
1022             pmvx -= 14;
1023             pmvy -= 14; // -14 = -16 + 2
1024             pStr = pStrength + 1;
1025             if (*pStr == 0)
1026             {
1027                 //within the same 8x8 block, no need to check the reference id
1028                 //only need to check the |mv difference| >= 4
1029                 tmp = *pmvx - *(pmvx - 8);
1030                 if (tmp < 0) tmp = -tmp;
1031                 if (tmp >= 4) *pStr = 1;
1032 
1033                 tmp = *pmvy - *(pmvy - 8);
1034                 if (tmp < 0) tmp = -tmp;
1035                 if (tmp >= 4) *pStr = 1;
1036             }
1037 
1038             pmvx += 8;
1039             pmvy += 8;
1040             pStr = pStrength + 5;
1041 
1042             if (*pStr == 0)
1043             {
1044                 //check the |mv difference| >= 4
1045                 tmp = *pmvx - *(pmvx - 8);
1046                 if (tmp < 0) tmp = -tmp;
1047                 if (tmp >= 4) *pStr = 1;
1048 
1049                 tmp = *pmvy - *(pmvy - 8);
1050                 if (tmp < 0) tmp = -tmp;
1051                 if (tmp >= 4) *pStr = 1;
1052             }
1053 
1054             pmvx += 8;
1055             pmvy += 8;
1056             pStr = pStrength + 9;
1057 
1058             if (*pStr == 0)
1059             {
1060                 //within the same 8x8 block, no need to check the reference id
1061                 //only need to check the |mv difference| >= 4
1062                 tmp = *pmvx - *(pmvx - 8);
1063                 if (tmp < 0) tmp = -tmp;
1064                 if (tmp >= 4) *pStr = 1;
1065 
1066                 tmp = *pmvy - *(pmvy - 8);
1067                 if (tmp < 0) tmp = -tmp;
1068                 if (tmp >= 4) *pStr = 1;
1069             }
1070 
1071             // update some variables for the next two rows
1072             pmvx -= 14;
1073             pmvy -= 14; // -14 = -16 + 2
1074             pStrength += 2;
1075 
1076         } /* end of: for(idx=0; idx<2; idx++) */
1077 
1078     } /* end of: else if( MbQ->mbMode == AVC_I4 ...) */
1079 }
1080 
1081 /*
1082  *****************************************************************************************
1083  * \brief  Filters one edge of 16 (luma) or 8 (chroma) pel
1084  *****************************************************************************************
1085 */
1086 
EdgeLoop_Luma_horizontal(uint8 * SrcPtr,uint8 * Strength,int Alpha,int Beta,int * clipTable,int pitch)1087 void EdgeLoop_Luma_horizontal(uint8* SrcPtr, uint8 *Strength, int Alpha, int Beta, int *clipTable, int pitch)
1088 {
1089     int  pel, ap = 0, aq = 0, Strng;
1090     int  C0, c0, dif, AbsDelta, tmp, tmp1;
1091     int  L2 = 0, L1, L0, R0, R1, R2 = 0, RL0;
1092 
1093 
1094     if (Strength[0] == 4)  /* INTRA strong filtering */
1095     {
1096         for (pel = 0; pel < 16; pel++)
1097         {
1098             R0  = SrcPtr[0];
1099             R1  = SrcPtr[pitch];
1100             L0  = SrcPtr[-pitch];
1101             L1  = SrcPtr[-(pitch<<1)];
1102 
1103             // |R0 - R1| < Beta
1104             tmp1 = R0 - R1;
1105             if (tmp1 < 0) tmp1 = -tmp1;
1106             tmp = (tmp1 - Beta);
1107 
1108             //|L0 - L1| < Beta
1109             tmp1 = L0 - L1;
1110             if (tmp1 < 0) tmp1 = -tmp1;
1111             tmp &= (tmp1 - Beta);
1112 
1113             //|R0 - L0| < Alpha
1114             AbsDelta = R0 - L0;
1115             if (AbsDelta < 0) AbsDelta = -AbsDelta;
1116             tmp &= (AbsDelta - Alpha);
1117 
1118             if (tmp < 0)
1119             {
1120                 AbsDelta -= ((Alpha >> 2) + 2);
1121                 R2 = SrcPtr[pitch<<1]; //inc2
1122                 L2 = SrcPtr[-(pitch+(pitch<<1))]; // -inc3
1123 
1124                 // |R0 - R2| < Beta && |R0 - L0| < (Alpha/4 + 2)
1125                 tmp = R0 - R2;
1126                 if (tmp < 0) tmp = -tmp;
1127                 aq = AbsDelta & (tmp - Beta);
1128 
1129                 // |L0 - L2| < Beta && |R0 - L0| < (Alpha/4 + 2)
1130                 tmp = L0 - L2;
1131                 if (tmp < 0) tmp = -tmp;
1132                 ap = AbsDelta & (tmp - Beta);
1133 
1134                 if (aq < 0)
1135                 {
1136                     tmp = R1 + R0 + L0;
1137                     SrcPtr[0] = (L1 + (tmp << 1) +  R2 + 4) >> 3;
1138                     tmp += R2;
1139                     SrcPtr[pitch]  = (tmp + 2) >> 2;
1140                     SrcPtr[pitch<<1] = (((SrcPtr[(pitch+(pitch<<1))] + R2) << 1) + tmp + 4) >> 3;
1141                 }
1142                 else
1143                     SrcPtr[0] = ((R1 << 1) + R0 + L1 + 2) >> 2;
1144 
1145                 if (ap < 0)
1146                 {
1147                     tmp = L1 + R0 + L0;
1148                     SrcPtr[-pitch]  = (R1 + (tmp << 1) +  L2 + 4) >> 3;
1149                     tmp += L2;
1150                     SrcPtr[-(pitch<<1)] = (tmp + 2) >> 2;
1151                     SrcPtr[-(pitch+(pitch<<1))] = (((SrcPtr[-(pitch<<2)] + L2) << 1) + tmp + 4) >> 3;
1152                 }
1153                 else
1154                     SrcPtr[-pitch] = ((L1 << 1) + L0 + R1 + 2) >> 2;
1155 
1156             } /* if(tmp < 0) */
1157 
1158             SrcPtr ++; // Increment to next set of pixel
1159 
1160         } /* end of: for(pel=0; pel<16; pel++) */
1161 
1162     } /* if(Strength[0] == 4) */
1163 
1164     else   /* Normal filtering */
1165     {
1166         for (pel = 0; pel < 16; pel++)
1167         {
1168             Strng = Strength[pel >> 2];
1169             if (Strng)
1170             {
1171                 R0  = SrcPtr[0];
1172                 R1  = SrcPtr[pitch];
1173                 L0  = SrcPtr[-pitch];
1174                 L1  = SrcPtr[-(pitch<<1)]; // inc2
1175 
1176                 //|R0 - L0| < Alpha
1177                 tmp1 = R0 - L0;
1178                 if (tmp1 < 0) tmp1 = -tmp1;
1179                 tmp = (tmp1 - Alpha);
1180 
1181                 // |R0 - R1| < Beta
1182                 tmp1 = R0 - R1;
1183                 if (tmp1 < 0) tmp1 = -tmp1;
1184                 tmp &= (tmp1 - Beta);
1185 
1186                 //|L0 - L1| < Beta
1187                 tmp1 = L0 - L1;
1188                 if (tmp1 < 0) tmp1 = -tmp1;
1189                 tmp &= (tmp1 - Beta);
1190 
1191                 if (tmp < 0)
1192                 {
1193                     R2 = SrcPtr[pitch<<1]; //inc2
1194                     L2 = SrcPtr[-(pitch+(pitch<<1))]; // -inc3
1195 
1196                     // |R0 - R2| < Beta
1197                     tmp = R0 - R2;
1198                     if (tmp < 0) tmp = -tmp;
1199                     aq = tmp - Beta;
1200 
1201                     // |L0 - L2| < Beta
1202                     tmp = L0 - L2;
1203                     if (tmp < 0) tmp = -tmp;
1204                     ap = tmp - Beta;
1205 
1206 
1207                     c0 = C0 = clipTable[Strng];
1208                     if (ap < 0) c0++;
1209                     if (aq < 0) c0++;
1210 
1211                     //dif = IClip(-c0, c0, ((Delta << 2) + (L1 - R1) + 4) >> 3);
1212                     dif = (((R0 - L0) << 2) + (L1 - R1) + 4) >> 3;
1213                     tmp = dif + c0;
1214                     if ((uint)tmp > (uint)c0 << 1)
1215                     {
1216                         tmp = ~(tmp >> 31);
1217                         dif = (tmp & (c0 << 1)) - c0;
1218                     }
1219 
1220                     //SrcPtr[0]    = (uint8)IClip(0, 255, R0 - dif);
1221                     //SrcPtr[-inc] = (uint8)IClip(0, 255, L0 + dif);
1222                     RL0 = R0 + L0;
1223                     R0 -= dif;
1224                     L0 += dif;
1225                     if ((uint)R0 > 255)
1226                     {
1227                         tmp = ~(R0 >> 31);
1228                         R0 = tmp & 255;
1229                     }
1230                     if ((uint)L0 > 255)
1231                     {
1232                         tmp = ~(L0 >> 31);
1233                         L0 = tmp & 255;
1234                     }
1235                     SrcPtr[-pitch] = L0;
1236                     SrcPtr[0] = R0;
1237 
1238                     if (C0 != 0) /* Multiple zeros in the clip tables */
1239                     {
1240                         if (aq < 0)  // SrcPtr[inc]   += IClip(-C0, C0,(R2 + ((RL0 + 1) >> 1) - (R1<<1)) >> 1);
1241                         {
1242                             R2 = (R2 + ((RL0 + 1) >> 1) - (R1 << 1)) >> 1;
1243                             tmp = R2 + C0;
1244                             if ((uint)tmp > (uint)C0 << 1)
1245                             {
1246                                 tmp = ~(tmp >> 31);
1247                                 R2 = (tmp & (C0 << 1)) - C0;
1248                             }
1249                             SrcPtr[pitch] += R2;
1250                         }
1251 
1252                         if (ap < 0)  //SrcPtr[-inc2] += IClip(-C0, C0,(L2 + ((RL0 + 1) >> 1) - (L1<<1)) >> 1);
1253                         {
1254                             L2 = (L2 + ((RL0 + 1) >> 1) - (L1 << 1)) >> 1;
1255                             tmp = L2 + C0;
1256                             if ((uint)tmp > (uint)C0 << 1)
1257                             {
1258                                 tmp = ~(tmp >> 31);
1259                                 L2 = (tmp & (C0 << 1)) - C0;
1260                             }
1261                             SrcPtr[-(pitch<<1)] += L2;
1262                         }
1263                     }
1264 
1265                 } /* if(tmp < 0) */
1266 
1267             } /* end of:  if((Strng = Strength[pel >> 2])) */
1268 
1269             SrcPtr ++; // Increment to next set of pixel
1270 
1271         } /* for(pel=0; pel<16; pel++) */
1272 
1273     } /* else if(Strength[0] == 4) */
1274 }
1275 
EdgeLoop_Luma_vertical(uint8 * SrcPtr,uint8 * Strength,int Alpha,int Beta,int * clipTable,int pitch)1276 void EdgeLoop_Luma_vertical(uint8* SrcPtr, uint8 *Strength, int Alpha, int Beta, int *clipTable, int pitch)
1277 {
1278     int  pel, ap = 1, aq = 1;
1279     int  C0, c0, dif, AbsDelta, Strng, tmp, tmp1;
1280     int  L2 = 0, L1, L0, R0, R1, R2 = 0;
1281     uint8 *ptr, *ptr1;
1282     uint R_in, L_in;
1283     uint R_out, L_out;
1284 
1285 
1286     if (Strength[0] == 4)  /* INTRA strong filtering */
1287     {
1288 
1289         for (pel = 0; pel < 16; pel++)
1290         {
1291 
1292             // Read 8 pels
1293             R_in = *((uint *)SrcPtr);       // R_in = {R3, R2, R1, R0}
1294             L_in = *((uint *)(SrcPtr - 4)); // L_in = {L0, L1, L2, L3}
1295             R1   = (R_in >> 8) & 0xff;
1296             R0   = R_in & 0xff;
1297             L0   = L_in >> 24;
1298             L1   = (L_in >> 16) & 0xff;
1299 
1300             // |R0 - R1| < Beta
1301             tmp1 = (R_in & 0xff) - R1;
1302             if (tmp1 < 0) tmp1 = -tmp1;
1303             tmp = (tmp1 - Beta);
1304 
1305 
1306             //|L0 - L1| < Beta
1307             tmp1 = (L_in >> 24) - L1;
1308             if (tmp1 < 0) tmp1 = -tmp1;
1309             tmp &= (tmp1 - Beta);
1310 
1311             //|R0 - L0| < Alpha
1312             AbsDelta = (R_in & 0xff) - (L_in >> 24);
1313             if (AbsDelta < 0) AbsDelta = -AbsDelta;
1314             tmp &= (AbsDelta - Alpha);
1315 
1316             if (tmp < 0)
1317             {
1318                 AbsDelta -= ((Alpha >> 2) + 2);
1319                 R2   = (R_in >> 16) & 0xff;
1320                 L2   = (L_in >> 8) & 0xff;
1321 
1322                 // |R0 - R2| < Beta && |R0 - L0| < (Alpha/4 + 2)
1323                 tmp1 = (R_in & 0xff) - R2;
1324                 if (tmp1 < 0) tmp1 = -tmp1;
1325                 aq = AbsDelta & (tmp1 - Beta);
1326 
1327                 // |L0 - L2| < Beta && |R0 - L0| < (Alpha/4 + 2)
1328                 tmp1 = (L_in >> 24) - L2;
1329                 if (tmp1 < 0) tmp1 = -tmp1;
1330                 ap = AbsDelta & (tmp1 - Beta);
1331 
1332 
1333                 ptr = SrcPtr;
1334                 if (aq < 0)
1335                 {
1336                     R_out = (R_in >> 24) << 24; // Keep R3 at the fourth byte
1337 
1338                     tmp  = R0 + L0 + R1;
1339                     R_out |= (((tmp << 1) +  L1 + R2 + 4) >> 3);
1340                     tmp += R2;
1341                     R_out |= (((tmp + 2) >> 2) << 8);
1342                     tmp1 = ((R_in >> 24) + R2) << 1;
1343                     R_out |= (((tmp1 + tmp + 4) >> 3) << 16);
1344 
1345                     *((uint *)SrcPtr) = R_out;
1346                 }
1347                 else
1348                     *ptr = ((R1 << 1) + R0 + L1 + 2) >> 2;
1349 
1350 
1351                 if (ap < 0)
1352                 {
1353                     L_out = (L_in << 24) >> 24; // Keep L3 at the first byte
1354 
1355                     tmp  = R0 + L0 + L1;
1356                     L_out |= ((((tmp << 1) + R1 + L2 + 4) >> 3) << 24);
1357                     tmp += L2;
1358                     L_out |= (((tmp + 2) >> 2) << 16);
1359                     tmp1 = ((L_in & 0xff) + L2) << 1;
1360                     L_out |= (((tmp1 + tmp + 4) >> 3) << 8);
1361 
1362                     *((uint *)(SrcPtr - 4)) = L_out;
1363                 }
1364                 else
1365                     *(--ptr) = ((L1 << 1) + L0 + R1 + 2) >> 2;
1366 
1367             } /* if(tmp < 0) */
1368 
1369             SrcPtr += pitch;    // Increment to next set of pixel
1370 
1371         } /* end of: for(pel=0; pel<16; pel++) */
1372 
1373     } /* if(Strength[0] == 4) */
1374 
1375     else   /* Normal filtering */
1376     {
1377 
1378         for (pel = 0; pel < 16; pel++)
1379         {
1380             Strng = Strength[pel >> 2];
1381             if (Strng)
1382             {
1383                 // Read 8 pels
1384                 R_in = *((uint *)SrcPtr);       // R_in = {R3, R2, R1, R0}
1385                 L_in = *((uint *)(SrcPtr - 4)); // L_in = {L0, L1, L2, L3}
1386                 R1   = (R_in >> 8) & 0xff;
1387                 R0   = R_in & 0xff;
1388                 L0   = L_in >> 24;
1389                 L1   = (L_in >> 16) & 0xff;
1390 
1391                 //|R0 - L0| < Alpha
1392                 tmp = R0 - L0;
1393                 if (tmp < 0) tmp = -tmp;
1394                 tmp -= Alpha;
1395 
1396                 // |R0 - R1| < Beta
1397                 tmp1 = R0 - R1;
1398                 if (tmp1 < 0) tmp1 = -tmp1;
1399                 tmp &= (tmp1 - Beta);
1400 
1401                 //|L0 - L1| < Beta
1402                 tmp1 = L0 - L1;
1403                 if (tmp1 < 0) tmp1 = -tmp1;
1404                 tmp &= (tmp1 - Beta);
1405 
1406                 if (tmp < 0)
1407                 {
1408                     L2 = SrcPtr[-3];
1409                     R2 = SrcPtr[2];
1410 
1411                     // |R0 - R2| < Beta
1412                     tmp = R0 - R2;
1413                     if (tmp < 0) tmp = -tmp;
1414                     aq = tmp - Beta;
1415 
1416                     // |L0 - L2| < Beta
1417                     tmp = L0 - L2;
1418                     if (tmp < 0) tmp = -tmp;
1419                     ap = tmp - Beta;
1420 
1421 
1422                     c0 = C0 = clipTable[Strng];
1423                     if (ap < 0) c0++;
1424                     if (aq < 0) c0++;
1425 
1426                     //dif = IClip(-c0, c0, ((Delta << 2) + (L1 - R1) + 4) >> 3);
1427                     dif = (((R0 - L0) << 2) + (L1 - R1) + 4) >> 3;
1428                     tmp = dif + c0;
1429                     if ((uint)tmp > (uint)c0 << 1)
1430                     {
1431                         tmp = ~(tmp >> 31);
1432                         dif = (tmp & (c0 << 1)) - c0;
1433                     }
1434 
1435                     ptr = SrcPtr;
1436                     ptr1 = SrcPtr - 1;
1437                     //SrcPtr[0]    = (uint8)IClip(0, 255, R0 - dif);
1438                     //SrcPtr[-inc] = (uint8)IClip(0, 255, L0 + dif);
1439                     R_in = R0 - dif;
1440                     L_in = L0 + dif; /* cannot re-use R0 and L0 here */
1441                     if ((uint)R_in > 255)
1442                     {
1443                         tmp = ~((int)R_in >> 31);
1444                         R_in = tmp & 255;
1445                     }
1446                     if ((uint)L_in > 255)
1447                     {
1448                         tmp = ~((int)L_in >> 31);
1449                         L_in = tmp & 255;
1450                     }
1451                     *ptr1-- = L_in;
1452                     *ptr++  = R_in;
1453 
1454                     if (C0 != 0) // Multiple zeros in the clip tables
1455                     {
1456                         if (ap < 0)  //SrcPtr[-inc2] += IClip(-C0, C0,(L2 + ((RL0 + 1) >> 1) - (L1<<1)) >> 1);
1457                         {
1458                             L2 = (L2 + ((R0 + L0 + 1) >> 1) - (L1 << 1)) >> 1;
1459                             tmp = L2 + C0;
1460                             if ((uint)tmp > (uint)C0 << 1)
1461                             {
1462                                 tmp = ~(tmp >> 31);
1463                                 L2 = (tmp & (C0 << 1)) - C0;
1464                             }
1465                             *ptr1 += L2;
1466                         }
1467 
1468                         if (aq < 0)  // SrcPtr[inc] += IClip(-C0, C0,(R2 + ((RL0 + 1) >> 1) - (R1<<1)) >> 1);
1469                         {
1470                             R2 = (R2 + ((R0 + L0 + 1) >> 1) - (R1 << 1)) >> 1;
1471                             tmp = R2 + C0;
1472                             if ((uint)tmp > (uint)C0 << 1)
1473                             {
1474                                 tmp = ~(tmp >> 31);
1475                                 R2 = (tmp & (C0 << 1)) - C0;
1476                             }
1477                             *ptr += R2;
1478                         }
1479                     }
1480 
1481                 } /* if(tmp < 0) */
1482 
1483             } /* end of:  if((Strng = Strength[pel >> 2])) */
1484 
1485             SrcPtr += pitch;    // Increment to next set of pixel
1486 
1487         } /* for(pel=0; pel<16; pel++) */
1488 
1489     } /* else if(Strength[0] == 4) */
1490 
1491 }
1492 
EdgeLoop_Chroma_vertical(uint8 * SrcPtr,uint8 * Strength,int Alpha,int Beta,int * clipTable,int pitch)1493 void EdgeLoop_Chroma_vertical(uint8* SrcPtr, uint8 *Strength, int Alpha, int Beta, int *clipTable, int pitch)
1494 {
1495     int     pel, Strng;
1496     int     c0, dif;
1497     int     L1, L0, R0, R1, tmp, tmp1;
1498     uint8   *ptr;
1499     uint    R_in, L_in;
1500 
1501 
1502     for (pel = 0; pel < 16; pel++)
1503     {
1504         Strng = Strength[pel>>2];
1505         if (Strng)
1506         {
1507             // Read 8 pels
1508             R_in = *((uint *)SrcPtr);       // R_in = {R3, R2, R1, R0}
1509             L_in = *((uint *)(SrcPtr - 4)); // L_in = {L0, L1, L2, L3}
1510             R1   = (R_in >> 8) & 0xff;
1511             R0   = R_in & 0xff;
1512             L0   = L_in >> 24;
1513             L1   = (L_in >> 16) & 0xff;
1514 
1515             // |R0 - R1| < Beta
1516             tmp1 = R0 - R1;
1517             if (tmp1 < 0) tmp1 = -tmp1;
1518             tmp = (tmp1 - Beta);
1519 
1520             //|L0 - L1| < Beta
1521             tmp1 = L0 - L1;
1522             if (tmp1 < 0) tmp1 = -tmp1;
1523             tmp &= (tmp1 - Beta);
1524 
1525             //|R0 - L0| < Alpha
1526             tmp1 = R0 - L0;
1527             if (tmp1 < 0) tmp1 = -tmp1;
1528             tmp &= (tmp1 - Alpha);
1529 
1530             if (tmp < 0)
1531             {
1532                 ptr = SrcPtr;
1533                 if (Strng == 4) /* INTRA strong filtering */
1534                 {
1535                     *ptr-- = ((R1 << 1) + R0 + L1 + 2) >> 2;
1536                     *ptr   = ((L1 << 1) + L0 + R1 + 2) >> 2;
1537                 }
1538                 else  /* normal filtering */
1539                 {
1540                     c0  = clipTable[Strng] + 1;
1541                     //dif = IClip(-c0, c0, ((Delta << 2) + (L1 - R1) + 4) >> 3);
1542                     dif = (((R0 - L0) << 2) + (L1 - R1) + 4) >> 3;
1543                     tmp = dif + c0;
1544                     if ((uint)tmp > (uint)c0 << 1)
1545                     {
1546                         tmp = ~(tmp >> 31);
1547                         dif = (tmp & (c0 << 1)) - c0;
1548                     }
1549 
1550                     //SrcPtr[0]    = (uint8)IClip(0, 255, R0 - dif);
1551                     //SrcPtr[-inc] = (uint8)IClip(0, 255, L0 + dif);
1552                     L0 += dif;
1553                     R0 -= dif;
1554                     if ((uint)L0 > 255)
1555                     {
1556                         tmp = ~(L0 >> 31);
1557                         L0 = tmp & 255;
1558                     }
1559                     if ((uint)R0 > 255)
1560                     {
1561                         tmp = ~(R0 >> 31);
1562                         R0 = tmp & 255;
1563                     }
1564 
1565                     *ptr-- = R0;
1566                     *ptr = L0;
1567                 }
1568             }
1569             pel ++;
1570             SrcPtr += pitch;   // Increment to next set of pixel
1571 
1572         } /* end of: if((Strng = Strength[pel >> 2])) */
1573         else
1574         {
1575             pel += 3;
1576             SrcPtr += (pitch << 1); //PtrInc << 1;
1577         }
1578 
1579     } /* end of: for(pel=0; pel<16; pel++) */
1580 }
1581 
1582 
EdgeLoop_Chroma_horizontal(uint8 * SrcPtr,uint8 * Strength,int Alpha,int Beta,int * clipTable,int pitch)1583 void EdgeLoop_Chroma_horizontal(uint8* SrcPtr, uint8 *Strength, int Alpha, int Beta, int *clipTable, int pitch)
1584 {
1585     int  pel, Strng;
1586     int  c0, dif;
1587     int  L1, L0, R0, R1, tmp, tmp1;
1588 
1589     for (pel = 0; pel < 16; pel++)
1590     {
1591         Strng = Strength[pel>>2];
1592         if (Strng)
1593         {
1594             R0  = SrcPtr[0];
1595             L0  = SrcPtr[-pitch];
1596             L1  = SrcPtr[-(pitch<<1)]; //inc2
1597             R1  = SrcPtr[pitch];
1598 
1599             // |R0 - R1| < Beta
1600             tmp1 = R0 - R1;
1601             if (tmp1 < 0) tmp1 = -tmp1;
1602             tmp = (tmp1 - Beta);
1603 
1604             //|L0 - L1| < Beta
1605             tmp1 = L0 - L1;
1606             if (tmp1 < 0) tmp1 = -tmp1;
1607             tmp &= (tmp1 - Beta);
1608 
1609             //|R0 - L0| < Alpha
1610             tmp1 = R0 - L0;
1611             if (tmp1 < 0) tmp1 = -tmp1;
1612             tmp &= (tmp1 - Alpha);
1613 
1614             if (tmp < 0)
1615             {
1616                 if (Strng == 4) /* INTRA strong filtering */
1617                 {
1618                     SrcPtr[0]      = ((R1 << 1) + R0 + L1 + 2) >> 2;
1619                     SrcPtr[-pitch] = ((L1 << 1) + L0 + R1 + 2) >> 2;
1620                 }
1621                 else  /* normal filtering */
1622                 {
1623                     c0  = clipTable[Strng] + 1;
1624                     //dif = IClip(-c0, c0, ((Delta << 2) + (L1 - R1) + 4) >> 3);
1625                     dif = (((R0 - L0) << 2) + (L1 - R1) + 4) >> 3;
1626                     tmp = dif + c0;
1627                     if ((uint)tmp > (uint)c0 << 1)
1628                     {
1629                         tmp = ~(tmp >> 31);
1630                         dif = (tmp & (c0 << 1)) - c0;
1631                     }
1632 
1633                     //SrcPtr[-inc] = (uint8)IClip(0, 255, L0 + dif);
1634                     //SrcPtr[0]    = (uint8)IClip(0, 255, R0 - dif);
1635                     L0 += dif;
1636                     R0 -= dif;
1637                     if ((uint)L0 > 255)
1638                     {
1639                         tmp = ~(L0 >> 31);
1640                         L0 = tmp & 255;
1641                     }
1642                     if ((uint)R0 > 255)
1643                     {
1644                         tmp = ~(R0 >> 31);
1645                         R0 = tmp & 255;
1646                     }
1647                     SrcPtr[0] = R0;
1648                     SrcPtr[-pitch] = L0;
1649                 }
1650             }
1651 
1652             pel ++;
1653             SrcPtr ++; // Increment to next set of pixel
1654 
1655         } /* end of: if((Strng = Strength[pel >> 2])) */
1656         else
1657         {
1658             pel += 3;
1659             SrcPtr += 2;
1660         }
1661 
1662     } /* end of: for(pel=0; pel<16; pel++) */
1663 }
1664 
1665 
1666 
1667 
1668