1 /*
2 * Copyright(c) 2018 Intel Corporation
3 * SPDX - License - Identifier: BSD - 2 - Clause - Patent
4 */
5 
6 
7 #include "EbSampleAdaptiveOffset_C.h"
8 #include "EbUtility.h"
9 
clipToSigned8Bit(int x)10 static int clipToSigned8Bit(int x)
11 {
12 #if 1
13     if (x < -128) return -128;
14     if (x > 127) return 127;
15 #endif
16     return x;
17 }
18 
19 /********************************************
20 * GatherSaoStatisticsLcu_62x62_16bit
21 * collects Sao Statistics
22 ********************************************/
GatherSaoStatisticsLcu_62x62_16bit(EB_U16 * inputSamplePtr,EB_U32 inputStride,EB_U16 * reconSamplePtr,EB_U32 reconStride,EB_U32 lcuWidth,EB_U32 lcuHeight,EB_S32 * boDiff,EB_U16 * boCount,EB_S32 eoDiff[SAO_EO_TYPES][SAO_EO_CATEGORIES+1],EB_U16 eoCount[SAO_EO_TYPES][SAO_EO_CATEGORIES+1])23 EB_ERRORTYPE GatherSaoStatisticsLcu_62x62_16bit(
24 	EB_U16                   *inputSamplePtr,        // input parameter, source Picture Ptr
25 	EB_U32                   inputStride,           // input parameter, source stride
26 	EB_U16                   *reconSamplePtr,        // input parameter, deblocked Picture Ptr
27 	EB_U32                   reconStride,           // input parameter, deblocked stride
28 	EB_U32                   lcuWidth,              // input parameter, LCU width
29 	EB_U32                   lcuHeight,             // input parameter, LCU height
30 	EB_S32                  *boDiff,                // output parameter, used to store Band Offset diff, boDiff[SAO_BO_INTERVALS]
31 	EB_U16                  *boCount,										// output parameter, used to store Band Offset count, boCount[SAO_BO_INTERVALS]
32 	EB_S32                   eoDiff[SAO_EO_TYPES][SAO_EO_CATEGORIES + 1],     // output parameter, used to store Edge Offset diff, eoDiff[SAO_EO_TYPES] [SAO_EO_CATEGORIES]
33 	EB_U16                   eoCount[SAO_EO_TYPES][SAO_EO_CATEGORIES + 1])    // output parameter, used to store Edge Offset count, eoCount[SAO_EO_TYPES] [SAO_EO_CATEGORIES]
34 {
35 	EB_ERRORTYPE    return_error = EB_ErrorNone;
36 
37 	EB_S32          diff;
38 	EB_U32          boIndex, eoType, eoIndex;
39 	EB_S16          signLeft, signRight, signTop, signBottom, signTopLeft, signBottomRight, signTopRight, signBottomLeft;
40 
41 	EB_U16          *temporalInputSamplePtr;
42 	EB_U16          *temporalReconSamplePtr;
43 
44 	EB_U32          i = 0;
45 	EB_U32          j = 0;
46 
47 	EB_U32 boShift = 5;
48 
49 	// Intialize SAO Arrays
50 
51 	// BO
52 	for (boIndex = 0; boIndex < SAO_BO_INTERVALS; ++boIndex) {
53 
54 		boDiff[boIndex] = 0;
55 		boCount[boIndex] = 0;
56 	}
57 
58 	// EO
59 	for (eoType = 0; eoType < SAO_EO_TYPES; ++eoType) {
60 		for (eoIndex = 0; eoIndex < SAO_EO_CATEGORIES + 1; ++eoIndex) {
61 
62 			eoDiff[eoType][eoIndex] = 0;
63 			eoCount[eoType][eoIndex] = 0;
64 
65 		}
66 	}
67 
68 
69 	temporalInputSamplePtr = inputSamplePtr + 1 + inputStride;
70 	temporalReconSamplePtr = reconSamplePtr + 1 + reconStride;
71 
72 	for (j = 0; j < lcuHeight - 2; j++) {
73 		for (i = 0; i < lcuWidth - 2; i++) {
74 
75 			diff = temporalInputSamplePtr[i] - temporalReconSamplePtr[i];
76 
77 			//BO
78 			boIndex = temporalReconSamplePtr[i] >> boShift;
79 			boDiff[boIndex] += diff;
80 			boCount[boIndex] ++;
81 
82 			//EO-0
83 			signLeft = SIGN(temporalReconSamplePtr[i], temporalReconSamplePtr[(EB_S32)(i - 1)]);
84 			signRight = SIGN(temporalReconSamplePtr[i], temporalReconSamplePtr[i + 1]);
85 			eoIndex = signRight + signLeft + 2;
86 			eoDiff[0][eoIndex] += diff;
87 			eoCount[0][eoIndex] ++;
88 
89 			//EO-90
90 			signTop = SIGN(temporalReconSamplePtr[i], temporalReconSamplePtr[(EB_S32)(i - reconStride)]);
91 			signBottom = SIGN(temporalReconSamplePtr[i], temporalReconSamplePtr[i + reconStride]);
92 			eoIndex = signTop + signBottom + 2;
93 			eoDiff[1][eoIndex] += diff;
94 			eoCount[1][eoIndex] ++;
95 
96 			//EO-45
97 			signTopRight = SIGN(temporalReconSamplePtr[i], temporalReconSamplePtr[(EB_S32)(i - reconStride + 1)]);
98 			signBottomLeft = SIGN(temporalReconSamplePtr[i], temporalReconSamplePtr[i + reconStride - 1]);
99 			eoIndex = signTopRight + signBottomLeft + 2;
100 			eoDiff[3][eoIndex] += diff;
101 			eoCount[3][eoIndex] ++;
102 
103 			//EO-135
104 			signTopLeft = SIGN(temporalReconSamplePtr[i], temporalReconSamplePtr[(EB_S32)(i - reconStride - 1)]);
105 			signBottomRight = SIGN(temporalReconSamplePtr[i], temporalReconSamplePtr[i + reconStride + 1]);
106 			eoIndex = signTopLeft + signBottomRight + 2;
107 			eoDiff[2][eoIndex] += diff;
108 			eoCount[2][eoIndex] ++;
109 		}
110 
111 		temporalInputSamplePtr += inputStride;
112 		temporalReconSamplePtr += reconStride;
113 
114 	}
115 	for (eoType = 0; eoType < SAO_EO_TYPES; ++eoType) {
116 		eoDiff[eoType][2] = eoDiff[eoType][3];
117 		eoDiff[eoType][3] = eoDiff[eoType][4];
118 		eoCount[eoType][2] = eoCount[eoType][3];
119 		eoCount[eoType][3] = eoCount[eoType][4];
120 	}
121 
122 	return return_error;
123 }
124 
GatherSaoStatisticsLcuLossy_62x62(EB_U8 * inputSamplePtr,EB_U32 inputStride,EB_U8 * reconSamplePtr,EB_U32 reconStride,EB_U32 lcuWidth,EB_U32 lcuHeight,EB_S32 * boDiff,EB_U16 * boCount,EB_S32 eoDiff[SAO_EO_TYPES][SAO_EO_CATEGORIES+1],EB_U16 eoCount[SAO_EO_TYPES][SAO_EO_CATEGORIES+1])125 EB_ERRORTYPE GatherSaoStatisticsLcuLossy_62x62(
126     EB_U8                   *inputSamplePtr,        // input parameter, source Picture Ptr
127     EB_U32                   inputStride,           // input parameter, source stride
128     EB_U8                   *reconSamplePtr,        // input parameter, deblocked Picture Ptr
129     EB_U32                   reconStride,           // input parameter, deblocked stride
130     EB_U32                   lcuWidth,              // input parameter, LCU width
131     EB_U32                   lcuHeight,             // input parameter, LCU height
132     EB_S32                  *boDiff,                // output parameter, used to store Band Offset diff, boDiff[SAO_BO_INTERVALS]
133     EB_U16                  *boCount,										// output parameter, used to store Band Offset count, boCount[SAO_BO_INTERVALS]
134     EB_S32                   eoDiff[SAO_EO_TYPES][SAO_EO_CATEGORIES + 1],     // output parameter, used to store Edge Offset diff, eoDiff[SAO_EO_TYPES] [SAO_EO_CATEGORIES]
135     EB_U16                   eoCount[SAO_EO_TYPES][SAO_EO_CATEGORIES + 1])    // output parameter, used to store Edge Offset count, eoCount[SAO_EO_TYPES] [SAO_EO_CATEGORIES]
136 {
137     EB_ERRORTYPE    return_error = EB_ErrorNone;
138 
139     EB_S32          diff;
140     EB_U32          boIndex, eoType, eoIndex;
141     EB_S16          signLeft, signRight, signTop, signBottom, signTopLeft, signBottomRight, signTopRight, signBottomLeft;
142 
143     EB_U8          *temporalInputSamplePtr;
144     EB_U8          *temporalReconSamplePtr;
145 
146     EB_U32          i = 0;
147     EB_U32          j = 0;
148 
149     EB_U32 boShift = 3;
150 
151     // Intialize SAO Arrays
152 
153     // BO
154     for (boIndex = 0; boIndex < SAO_BO_INTERVALS; ++boIndex) {
155 
156         boDiff[boIndex] = 0;
157         boCount[boIndex] = 0;
158     }
159 
160     // EO
161     for (eoType = 0; eoType < SAO_EO_TYPES; ++eoType) {
162         for (eoIndex = 0; eoIndex < SAO_EO_CATEGORIES + 1; ++eoIndex) {
163 
164             eoDiff[eoType][eoIndex] = 0;
165             eoCount[eoType][eoIndex] = 0;
166 
167         }
168     }
169 
170 
171     temporalInputSamplePtr = inputSamplePtr + 1 + inputStride;
172     temporalReconSamplePtr = reconSamplePtr + 1 + reconStride;
173 
174     for (j = 0; j < lcuHeight - 2; j++) {
175         for (i = 0; i < lcuWidth - 2; i++) {
176 
177             diff = temporalInputSamplePtr[i] - temporalReconSamplePtr[i];
178 
179             //BO
180             boIndex = temporalReconSamplePtr[i] >> boShift;
181             boDiff[boIndex] += clipToSigned8Bit(diff);
182             boCount[boIndex] ++;
183 
184             //EO-0
185             signLeft = SIGN(temporalReconSamplePtr[i], temporalReconSamplePtr[(EB_S32)(i - 1)]);
186             signRight = SIGN(temporalReconSamplePtr[i], temporalReconSamplePtr[i + 1]);
187             eoIndex = signRight + signLeft + 2;
188             eoDiff[0][eoIndex] += clipToSigned8Bit(diff);
189             eoCount[0][eoIndex] ++;
190 
191             //EO-90
192             signTop = SIGN(temporalReconSamplePtr[i], temporalReconSamplePtr[(EB_S32)(i - reconStride)]);
193             signBottom = SIGN(temporalReconSamplePtr[i], temporalReconSamplePtr[i + reconStride]);
194             eoIndex = signTop + signBottom + 2;
195             eoDiff[1][eoIndex] += clipToSigned8Bit(diff);
196             eoCount[1][eoIndex] ++;
197 
198             //EO-45
199             signTopRight = SIGN(temporalReconSamplePtr[i], temporalReconSamplePtr[(EB_S32)(i - reconStride + 1)]);
200             signBottomLeft = SIGN(temporalReconSamplePtr[i], temporalReconSamplePtr[i + reconStride - 1]);
201             eoIndex = signTopRight + signBottomLeft + 2;
202             eoDiff[3][eoIndex] += clipToSigned8Bit(diff);
203             eoCount[3][eoIndex] ++;
204 
205             //EO-135
206             signTopLeft = SIGN(temporalReconSamplePtr[i], temporalReconSamplePtr[(EB_S32)(i - reconStride - 1)]);
207             signBottomRight = SIGN(temporalReconSamplePtr[i], temporalReconSamplePtr[i + reconStride + 1]);
208             eoIndex = signTopLeft + signBottomRight + 2;
209             eoDiff[2][eoIndex] += clipToSigned8Bit(diff);
210             eoCount[2][eoIndex] ++;
211         }
212 
213         temporalInputSamplePtr += inputStride;
214         temporalReconSamplePtr += reconStride;
215 
216     }
217     for (eoType = 0; eoType < SAO_EO_TYPES; ++eoType) {
218         eoDiff[eoType][2] = eoDiff[eoType][3];
219         eoDiff[eoType][3] = eoDiff[eoType][4];
220         eoCount[eoType][2] = eoCount[eoType][3];
221         eoCount[eoType][3] = eoCount[eoType][4];
222     }
223 
224     return return_error;
225 }
226 
GatherSaoStatisticsLcu_OnlyEo_90_45_135_Lossy(EB_U8 * inputSamplePtr,EB_U32 inputStride,EB_U8 * reconSamplePtr,EB_U32 reconStride,EB_U32 lcuWidth,EB_U32 lcuHeight,EB_S32 eoDiff[SAO_EO_TYPES][SAO_EO_CATEGORIES+1],EB_U16 eoCount[SAO_EO_TYPES][SAO_EO_CATEGORIES+1])227 EB_ERRORTYPE GatherSaoStatisticsLcu_OnlyEo_90_45_135_Lossy(
228     EB_U8                   *inputSamplePtr,        // input parameter, source Picture Ptr
229     EB_U32                   inputStride,           // input parameter, source stride
230     EB_U8                   *reconSamplePtr,        // input parameter, deblocked Picture Ptr
231     EB_U32                   reconStride,           // input parameter, deblocked stride
232     EB_U32                   lcuWidth,              // input parameter, LCU width
233     EB_U32                   lcuHeight,             // input parameter, LCU height
234     EB_S32                   eoDiff[SAO_EO_TYPES][SAO_EO_CATEGORIES + 1],     // output parameter, used to store Edge Offset diff, eoDiff[SAO_EO_TYPES] [SAO_EO_CATEGORIES]
235     EB_U16                   eoCount[SAO_EO_TYPES][SAO_EO_CATEGORIES + 1])    // output parameter, used to store Edge Offset count, eoCount[SAO_EO_TYPES] [SAO_EO_CATEGORIES]
236 {
237     EB_ERRORTYPE    return_error = EB_ErrorNone;
238 
239     EB_S32          diff;
240     EB_U32          eoType, eoIndex;
241     EB_S16          signTop, signBottom, signTopLeft, signBottomRight, signTopRight, signBottomLeft;
242 
243     EB_U8          *temporalInputSamplePtr;
244     EB_U8          *temporalReconSamplePtr;
245 
246     EB_U32          i = 0;
247     EB_U32          j = 0;
248 
249 
250     // Intialize SAO Arrays
251 
252     // EO
253     for (eoType = 0; eoType < SAO_EO_TYPES; ++eoType) {
254         for (eoIndex = 0; eoIndex < SAO_EO_CATEGORIES + 1; ++eoIndex) {
255 
256             eoDiff[eoType][eoIndex] = 0;
257             eoCount[eoType][eoIndex] = 0;
258 
259         }
260     }
261 
262 
263     temporalInputSamplePtr = inputSamplePtr + 1 + inputStride;
264     temporalReconSamplePtr = reconSamplePtr + 1 + reconStride;
265 
266     for (j = 0; j < lcuHeight - 2; j++) {
267         for (i = 0; i < lcuWidth - 2; i++) {
268 
269             diff = temporalInputSamplePtr[i] - temporalReconSamplePtr[i];
270 
271             //EO-90
272             signTop = SIGN(temporalReconSamplePtr[i], temporalReconSamplePtr[(EB_S32)(i - reconStride)]);
273             signBottom = SIGN(temporalReconSamplePtr[i], temporalReconSamplePtr[i + reconStride]);
274             eoIndex = signTop + signBottom + 2;
275             eoDiff[1][eoIndex] += clipToSigned8Bit(diff);
276             eoCount[1][eoIndex] ++;
277 
278             //EO-45
279             signTopRight = SIGN(temporalReconSamplePtr[i], temporalReconSamplePtr[(EB_S32)(i - reconStride + 1)]);
280             signBottomLeft = SIGN(temporalReconSamplePtr[i], temporalReconSamplePtr[i + reconStride - 1]);
281             eoIndex = signTopRight + signBottomLeft + 2;
282             eoDiff[3][eoIndex] += clipToSigned8Bit(diff);
283             eoCount[3][eoIndex] ++;
284 
285             //EO-135
286             signTopLeft = SIGN(temporalReconSamplePtr[i], temporalReconSamplePtr[(EB_S32)(i - reconStride - 1)]);
287             signBottomRight = SIGN(temporalReconSamplePtr[i], temporalReconSamplePtr[i + reconStride + 1]);
288             eoIndex = signTopLeft + signBottomRight + 2;
289             eoDiff[2][eoIndex] += clipToSigned8Bit(diff);
290             eoCount[2][eoIndex] ++;
291         }
292 
293         temporalInputSamplePtr += inputStride;
294         temporalReconSamplePtr += reconStride;
295 
296     }
297     for (eoType = 0; eoType < SAO_EO_TYPES; ++eoType) {
298         eoDiff[eoType][2] = eoDiff[eoType][3];
299         eoDiff[eoType][3] = eoDiff[eoType][4];
300         eoCount[eoType][2] = eoCount[eoType][3];
301         eoCount[eoType][3] = eoCount[eoType][4];
302     }
303 
304     return return_error;
305 }
306 
307 /********************************************
308 *
309 * collects Sao Statistics
310 ********************************************/
GatherSaoStatisticsLcu_62x62_OnlyEo_90_45_135_16bit(EB_U16 * inputSamplePtr,EB_U32 inputStride,EB_U16 * reconSamplePtr,EB_U32 reconStride,EB_U32 lcuWidth,EB_U32 lcuHeight,EB_S32 eoDiff[SAO_EO_TYPES][SAO_EO_CATEGORIES+1],EB_U16 eoCount[SAO_EO_TYPES][SAO_EO_CATEGORIES+1])311 EB_ERRORTYPE GatherSaoStatisticsLcu_62x62_OnlyEo_90_45_135_16bit(
312     EB_U16                   *inputSamplePtr,        // input parameter, source Picture Ptr
313     EB_U32                   inputStride,           // input parameter, source stride
314     EB_U16                   *reconSamplePtr,        // input parameter, deblocked Picture Ptr
315     EB_U32                   reconStride,           // input parameter, deblocked stride
316     EB_U32                   lcuWidth,              // input parameter, LCU width
317     EB_U32                   lcuHeight,             // input parameter, LCU height
318     EB_S32                   eoDiff[SAO_EO_TYPES][SAO_EO_CATEGORIES + 1],    // output parameter, used to store Edge Offset diff, eoDiff[SAO_EO_TYPES] [SAO_EO_CATEGORIES]
319     EB_U16                   eoCount[SAO_EO_TYPES][SAO_EO_CATEGORIES + 1])   // output parameter, used to store Edge Offset count, eoCount[SAO_EO_TYPES] [SAO_EO_CATEGORIES]
320 
321 {
322     EB_ERRORTYPE    return_error = EB_ErrorNone;
323 
324     EB_S32          diff;
325     EB_U32  eoType, eoIndex;
326 
327     EB_S16 signTop, signBottom, signTopLeft, signBottomRight, signTopRight, signBottomLeft;
328 
329     EB_U16          *temporalInputSamplePtr;
330     EB_U16          *temporalReconSamplePtr;
331 
332     EB_U32          i = 0;
333     EB_U32          j = 0;
334 
335     // Intialize SAO Arrays
336     // EO
337     for (eoType = 0; eoType < SAO_EO_TYPES; ++eoType) {
338         for (eoIndex = 0; eoIndex < SAO_EO_CATEGORIES + 1; ++eoIndex) {
339             eoDiff[eoType][eoIndex] = 0;
340             eoCount[eoType][eoIndex] = 0;
341 
342         }
343     }
344 
345     temporalInputSamplePtr = inputSamplePtr + 1 + inputStride;
346     temporalReconSamplePtr = reconSamplePtr + 1 + reconStride;
347 
348     for (j = 0; j < lcuHeight - 2; j++)
349     {
350         for (i = 0; i < lcuWidth - 2; i++)
351         {
352             diff = temporalInputSamplePtr[i] - temporalReconSamplePtr[i];
353 
354             //EO-90
355             signTop = SIGN(temporalReconSamplePtr[i], temporalReconSamplePtr[(EB_S32)(i - reconStride)]);
356             signBottom = SIGN(temporalReconSamplePtr[i], temporalReconSamplePtr[i + reconStride]);
357             eoIndex = signTop + signBottom + 2;
358             eoDiff[1][eoIndex] += diff;
359             eoCount[1][eoIndex] ++;
360 
361             //EO-45
362             signTopRight = SIGN(temporalReconSamplePtr[i], temporalReconSamplePtr[(EB_S32)(i - reconStride + 1)]);
363             signBottomLeft = SIGN(temporalReconSamplePtr[i], temporalReconSamplePtr[i + reconStride - 1]);
364             eoIndex = signTopRight + signBottomLeft + 2;
365             eoDiff[3][eoIndex] += diff;
366             eoCount[3][eoIndex] ++;
367 
368             //EO-135
369             signTopLeft = SIGN(temporalReconSamplePtr[i], temporalReconSamplePtr[(EB_S32)(i - reconStride - 1)]);
370             signBottomRight = SIGN(temporalReconSamplePtr[i], temporalReconSamplePtr[i + reconStride + 1]);
371             eoIndex = signTopLeft + signBottomRight + 2;
372             eoDiff[2][eoIndex] += diff;
373             eoCount[2][eoIndex] ++;
374         }
375 
376         temporalInputSamplePtr += inputStride;
377         temporalReconSamplePtr += reconStride;
378     }
379     for (eoType = 0; eoType < SAO_EO_TYPES; ++eoType) {
380         eoDiff[eoType][2] = eoDiff[eoType][3];
381         eoDiff[eoType][3] = eoDiff[eoType][4];
382         eoCount[eoType][2] = eoCount[eoType][3];
383         eoCount[eoType][3] = eoCount[eoType][4];
384     }
385 
386 
387     return return_error;
388 }
389 
390 /********************************************
391 * SAOApplyBO
392 *   applies BO SAO for the whole LCU
393 ********************************************/
SAOApplyBO(EB_U8 * reconSamplePtr,EB_U32 reconStride,EB_U32 saoBandPosition,EB_S8 * saoOffsetPtr,EB_U32 lcuHeight,EB_U32 lcuWidth)394 EB_ERRORTYPE SAOApplyBO(
395     EB_U8                           *reconSamplePtr,
396     EB_U32                           reconStride,
397     EB_U32                           saoBandPosition,
398     EB_S8                           *saoOffsetPtr,
399     EB_U32                           lcuHeight,
400     EB_U32                           lcuWidth)
401 {
402     EB_ERRORTYPE return_error = EB_ErrorNone;
403     EB_U32  lcuWidthCount = 0;
404     EB_U32  lcuHeightCount = 0;
405     EB_U32  boIndex;
406 
407 
408     while (lcuHeightCount < lcuHeight) {
409         while (lcuWidthCount < lcuWidth) {
410 
411             boIndex = reconSamplePtr[lcuWidthCount] >> 3;
412             reconSamplePtr[lcuWidthCount] = (boIndex < saoBandPosition || boIndex > saoBandPosition + SAO_BO_LEN - 1) ?
413                 reconSamplePtr[lcuWidthCount] :
414                 (EB_U8)CLIP3(0, MAX_SAMPLE_VALUE, reconSamplePtr[lcuWidthCount] + saoOffsetPtr[boIndex - saoBandPosition]);
415 
416             ++lcuWidthCount;
417         }
418 
419         lcuWidthCount = 0;
420 
421         ++lcuHeightCount;
422 
423         reconSamplePtr += reconStride;
424     }
425     return return_error;
426 }
427 /********************************************
428 * SAOApplyBO16bit
429 *   applies BO SAO for the whole LCU
430 ********************************************/
SAOApplyBO16bit(EB_U16 * reconSamplePtr,EB_U32 reconStride,EB_U32 saoBandPosition,EB_S8 * saoOffsetPtr,EB_U32 lcuHeight,EB_U32 lcuWidth)431 EB_ERRORTYPE SAOApplyBO16bit(
432     EB_U16                          *reconSamplePtr,
433     EB_U32                           reconStride,
434     EB_U32                           saoBandPosition,
435     EB_S8                           *saoOffsetPtr,
436     EB_U32                           lcuHeight,
437     EB_U32                           lcuWidth)
438 {
439     EB_ERRORTYPE return_error = EB_ErrorNone;
440     EB_U32  lcuWidthCount = 0;
441     EB_U32  lcuHeightCount = 0;
442     EB_U32  boIndex;
443 
444 
445     while (lcuHeightCount < lcuHeight) {
446         while (lcuWidthCount < lcuWidth) {
447 
448             boIndex = reconSamplePtr[lcuWidthCount] >> 5;
449             reconSamplePtr[lcuWidthCount] = (boIndex < saoBandPosition || boIndex > saoBandPosition + SAO_BO_LEN - 1) ?
450                 reconSamplePtr[lcuWidthCount] :
451                 (EB_U16)CLIP3(0, MAX_SAMPLE_VALUE_10BIT, reconSamplePtr[lcuWidthCount] + saoOffsetPtr[boIndex - saoBandPosition]);
452 
453             ++lcuWidthCount;
454         }
455 
456         lcuWidthCount = 0;
457 
458         ++lcuHeightCount;
459 
460         reconSamplePtr += reconStride;
461     }
462     return return_error;
463 }
464 
465 
466 /********************************************
467 * SAOApplyEO_0
468 *   applies EO 0 SAO for the whole LCU
469 ********************************************/
SAOApplyEO_0(EB_U8 * reconSamplePtr,EB_U32 reconStride,EB_U8 * temporalBufferLeft,EB_S8 * saoOffsetPtr,EB_U32 lcuHeight,EB_U32 lcuWidth)470 EB_ERRORTYPE SAOApplyEO_0(
471     EB_U8                           *reconSamplePtr,
472     EB_U32                           reconStride,
473     EB_U8                           *temporalBufferLeft,
474     EB_S8                           *saoOffsetPtr,
475     EB_U32                           lcuHeight,
476     EB_U32                           lcuWidth)
477 {
478     EB_ERRORTYPE return_error = EB_ErrorNone;
479     EB_S16  signLeft, signRight;
480     EB_U32  eoIndex;
481 
482     EB_U32  i = 0, j = 0;
483 
484     for (j = 0; j<lcuHeight; j++) {
485 
486         signLeft = SIGN(reconSamplePtr[0], temporalBufferLeft[j]);
487 
488         for (i = 0; i<lcuWidth; i++) {
489 
490             signRight = SIGN(reconSamplePtr[i], reconSamplePtr[i + 1]);
491             eoIndex = signLeft + signRight + 2;
492             signLeft = -signRight;
493 
494             reconSamplePtr[i] = (EB_U8)CLIP3(0, MAX_SAMPLE_VALUE, reconSamplePtr[i] + saoOffsetPtr[eoIndex]);
495 
496         }
497         reconSamplePtr += reconStride;
498     }
499 
500     return return_error;
501 }
502 /********************************************
503 * SAOApplyEO_0_16bit
504 *   applies EO 0 SAO for the whole LCU
505 ********************************************/
SAOApplyEO_0_16bit(EB_U16 * reconSamplePtr,EB_U32 reconStride,EB_U16 * temporalBufferLeft,EB_S8 * saoOffsetPtr,EB_U32 lcuHeight,EB_U32 lcuWidth)506 EB_ERRORTYPE SAOApplyEO_0_16bit(
507     EB_U16                           *reconSamplePtr,
508     EB_U32                           reconStride,
509     EB_U16                           *temporalBufferLeft,
510     EB_S8                           *saoOffsetPtr,
511     EB_U32                           lcuHeight,
512     EB_U32                           lcuWidth)
513 {
514     EB_ERRORTYPE return_error = EB_ErrorNone;
515     EB_S16  signLeft, signRight;
516     EB_U32  eoIndex;
517 
518     EB_U32  i = 0, j = 0;
519 
520     for (j = 0; j<lcuHeight; j++) {
521 
522         signLeft = SIGN(reconSamplePtr[0], temporalBufferLeft[j]);
523 
524         for (i = 0; i<lcuWidth; i++) {
525 
526             signRight = SIGN(reconSamplePtr[i], reconSamplePtr[i + 1]);
527             eoIndex = signLeft + signRight + 2;
528             signLeft = -signRight;
529 
530             reconSamplePtr[i] = (EB_U16)CLIP3(0, MAX_SAMPLE_VALUE_10BIT, reconSamplePtr[i] + saoOffsetPtr[eoIndex]);
531 
532         }
533         reconSamplePtr += reconStride;
534     }
535 
536     return return_error;
537 }
538 
539 
540 /********************************************
541 * SAOApplyEO_90
542 *   applies EO 90 SAO for the whole LCU
543 ********************************************/
SAOApplyEO_90(EB_U8 * reconSamplePtr,EB_U32 reconStride,EB_U8 * temporalBufferUpper,EB_S8 * saoOffsetPtr,EB_U32 lcuHeight,EB_U32 lcuWidth)544 EB_ERRORTYPE SAOApplyEO_90(
545     EB_U8                           *reconSamplePtr,
546     EB_U32                           reconStride,
547     EB_U8                           *temporalBufferUpper,
548     EB_S8                           *saoOffsetPtr,
549     EB_U32                           lcuHeight,
550     EB_U32                           lcuWidth)
551 {
552     EB_ERRORTYPE return_error = EB_ErrorNone;
553     EB_S16  signBottom;
554     EB_U32  eoIndex;
555 
556     EB_U32  i = 0, j = 0;
557     EB_U32  lcuColumn;
558     EB_S16  signTop[MAX_LCU_SIZE];
559 
560 
561     for (lcuColumn = 0; lcuColumn < lcuWidth; ++lcuColumn) {
562         signTop[lcuColumn] = SIGN(reconSamplePtr[lcuColumn], temporalBufferUpper[lcuColumn]);
563     }
564 
565     for (j = 0; j<lcuHeight; j++) {
566 
567         for (i = 0; i<lcuWidth; i++) {
568 
569             signBottom = SIGN(reconSamplePtr[i], reconSamplePtr[i + reconStride]);
570             eoIndex = signTop[i] + signBottom + 2;
571             signTop[i] = -signBottom;
572 
573             reconSamplePtr[i] = (EB_U8)CLIP3(0, MAX_SAMPLE_VALUE, reconSamplePtr[i] + saoOffsetPtr[eoIndex]);
574         }
575 
576 
577         reconSamplePtr += reconStride;
578     }
579 
580     return return_error;
581 
582 }
583 /********************************************
584 * SAOApplyEO_90_16bit
585 *   applies EO 90 SAO for the whole LCU
586 ********************************************/
SAOApplyEO_90_16bit(EB_U16 * reconSamplePtr,EB_U32 reconStride,EB_U16 * temporalBufferUpper,EB_S8 * saoOffsetPtr,EB_U32 lcuHeight,EB_U32 lcuWidth)587 EB_ERRORTYPE SAOApplyEO_90_16bit(
588     EB_U16                           *reconSamplePtr,
589     EB_U32                           reconStride,
590     EB_U16                           *temporalBufferUpper,
591     EB_S8                           *saoOffsetPtr,
592     EB_U32                           lcuHeight,
593     EB_U32                           lcuWidth)
594 {
595     EB_ERRORTYPE return_error = EB_ErrorNone;
596     EB_S16  signBottom;
597     EB_U32  eoIndex;
598 
599     EB_U32  i = 0, j = 0;
600     EB_U32  lcuColumn;
601     EB_S16  signTop[MAX_LCU_SIZE];
602 
603 
604     for (lcuColumn = 0; lcuColumn < lcuWidth; ++lcuColumn) {
605         signTop[lcuColumn] = SIGN(reconSamplePtr[lcuColumn], temporalBufferUpper[lcuColumn]);
606     }
607 
608     for (j = 0; j<lcuHeight; j++) {
609 
610         for (i = 0; i<lcuWidth; i++) {
611 
612             signBottom = SIGN(reconSamplePtr[i], reconSamplePtr[i + reconStride]);
613             eoIndex = signTop[i] + signBottom + 2;
614             signTop[i] = -signBottom;
615 
616             reconSamplePtr[i] = (EB_U16)CLIP3(0, MAX_SAMPLE_VALUE_10BIT, reconSamplePtr[i] + saoOffsetPtr[eoIndex]);
617         }
618 
619 
620         reconSamplePtr += reconStride;
621     }
622 
623     return return_error;
624 
625 }
626 /********************************************
627 * SAOApplyEO_135
628 *   applies EO 135 SAO for the whole LCU
629 ********************************************/
SAOApplyEO_135(EB_U8 * reconSamplePtr,EB_U32 reconStride,EB_U8 * temporalBufferLeft,EB_U8 * temporalBufferUpper,EB_S8 * saoOffsetPtr,EB_U32 lcuHeight,EB_U32 lcuWidth)630 EB_ERRORTYPE SAOApplyEO_135(
631     EB_U8                           *reconSamplePtr,
632     EB_U32                           reconStride,
633     EB_U8                           *temporalBufferLeft,
634     EB_U8                           *temporalBufferUpper,
635     EB_S8                           *saoOffsetPtr,
636     EB_U32                           lcuHeight,
637     EB_U32                           lcuWidth)
638 {
639     EB_ERRORTYPE return_error = EB_ErrorNone;
640     EB_S16  signBottomRight;
641     EB_U32  eoIndex;
642     EB_U32  lcuColumn;
643     EB_S16  signTopLeft[MAX_LCU_SIZE] = { 0 }, signTopLeftTemp[MAX_LCU_SIZE + 1] = { 0 }, signTopLeftSwap[MAX_LCU_SIZE] = { 0 };
644 
645     EB_U32  lcuWidthCount = 0;
646     EB_U32  lcuHeightCount = 0;
647 
648 
649     for (lcuColumn = lcuWidthCount; lcuColumn < lcuWidth; ++lcuColumn) {
650         signTopLeft[lcuColumn] = SIGN(reconSamplePtr[lcuColumn], temporalBufferUpper[(EB_S32)(lcuColumn - 1)]);
651     }
652 
653     while (lcuHeightCount < lcuHeight) {
654 
655         while (lcuWidthCount < lcuWidth) {
656 
657             signBottomRight = SIGN(reconSamplePtr[lcuWidthCount], reconSamplePtr[lcuWidthCount + reconStride + 1]);
658             eoIndex = signTopLeft[lcuWidthCount] + signBottomRight + 2;
659             signTopLeftTemp[lcuWidthCount + 1] = -signBottomRight;
660 
661             reconSamplePtr[lcuWidthCount] = (EB_U8)CLIP3(0, MAX_SAMPLE_VALUE, reconSamplePtr[lcuWidthCount] + saoOffsetPtr[eoIndex]);
662 
663             ++lcuWidthCount;
664         }
665 
666         lcuWidthCount = 0;
667 
668         signTopLeftTemp[lcuWidthCount] = SIGN(reconSamplePtr[reconStride + lcuWidthCount], temporalBufferLeft[lcuHeightCount]);
669 
670         EB_MEMCPY(signTopLeftSwap, signTopLeft, sizeof(EB_S16) * MAX_LCU_SIZE);
671         EB_MEMCPY(signTopLeft, signTopLeftTemp, sizeof(EB_S16) * MAX_LCU_SIZE);
672         EB_MEMCPY(signTopLeftTemp, signTopLeftSwap, sizeof(EB_S16) * MAX_LCU_SIZE);
673 
674         ++lcuHeightCount;
675 
676         reconSamplePtr += reconStride;
677     }
678 
679     return return_error;
680 
681 }
682 /********************************************
683 * SAOApplyEO_135
684 *   applies EO 135 SAO for the whole LCU
685 ********************************************/
SAOApplyEO_135_16bit(EB_U16 * reconSamplePtr,EB_U32 reconStride,EB_U16 * temporalBufferLeft,EB_U16 * temporalBufferUpper,EB_S8 * saoOffsetPtr,EB_U32 lcuHeight,EB_U32 lcuWidth)686 EB_ERRORTYPE SAOApplyEO_135_16bit(
687     EB_U16                           *reconSamplePtr,
688     EB_U32                           reconStride,
689     EB_U16                          *temporalBufferLeft,
690     EB_U16                           *temporalBufferUpper,
691     EB_S8                           *saoOffsetPtr,
692     EB_U32                           lcuHeight,
693     EB_U32                           lcuWidth)
694 {
695     EB_ERRORTYPE return_error = EB_ErrorNone;
696     EB_S16  signBottomRight;
697     EB_U32  eoIndex;
698     EB_U32  lcuColumn;
699     EB_S16  signTopLeft[MAX_LCU_SIZE] = { 0 }, signTopLeftTemp[MAX_LCU_SIZE + 1] = { 0 }, signTopLeftSwap[MAX_LCU_SIZE] = { 0 };
700 
701     EB_U32  lcuWidthCount = 0;
702     EB_U32  lcuHeightCount = 0;
703 
704 
705     for (lcuColumn = lcuWidthCount; lcuColumn < lcuWidth; ++lcuColumn) {
706         signTopLeft[lcuColumn] = SIGN(reconSamplePtr[lcuColumn], temporalBufferUpper[(EB_S32)(lcuColumn - 1)]);
707     }
708 
709     while (lcuHeightCount < lcuHeight) {
710 
711         while (lcuWidthCount < lcuWidth) {
712 
713             signBottomRight = SIGN(reconSamplePtr[lcuWidthCount], reconSamplePtr[lcuWidthCount + reconStride + 1]);
714             eoIndex = signTopLeft[lcuWidthCount] + signBottomRight + 2;
715             signTopLeftTemp[lcuWidthCount + 1] = -signBottomRight;
716 
717             reconSamplePtr[lcuWidthCount] = (EB_U16)CLIP3(0, MAX_SAMPLE_VALUE_10BIT, reconSamplePtr[lcuWidthCount] + saoOffsetPtr[eoIndex]);
718 
719             ++lcuWidthCount;
720         }
721 
722         lcuWidthCount = 0;
723 
724         signTopLeftTemp[lcuWidthCount] = SIGN(reconSamplePtr[reconStride + lcuWidthCount], temporalBufferLeft[lcuHeightCount]);
725 
726         EB_MEMCPY(signTopLeftSwap, signTopLeft, sizeof(EB_S16) * MAX_LCU_SIZE);
727         EB_MEMCPY(signTopLeft, signTopLeftTemp, sizeof(EB_S16) * MAX_LCU_SIZE);
728         EB_MEMCPY(signTopLeftTemp, signTopLeftSwap, sizeof(EB_S16) * MAX_LCU_SIZE);
729 
730         ++lcuHeightCount;
731 
732         reconSamplePtr += reconStride;
733     }
734 
735     return return_error;
736 
737 }
738 /********************************************
739 * SAOApplyEO_45
740 *   applies EO 45 SAO for the whole LCU
741 ********************************************/
SAOApplyEO_45(EB_U8 * reconSamplePtr,EB_U32 reconStride,EB_U8 * temporalBufferLeft,EB_U8 * temporalBufferUpper,EB_S8 * saoOffsetPtr,EB_U32 lcuHeight,EB_U32 lcuWidth)742 EB_ERRORTYPE SAOApplyEO_45(
743     EB_U8                           *reconSamplePtr,
744     EB_U32                           reconStride,
745     EB_U8                           *temporalBufferLeft,
746     EB_U8                           *temporalBufferUpper,
747     EB_S8                           *saoOffsetPtr,
748     EB_U32                           lcuHeight,
749     EB_U32                           lcuWidth
750     )
751 {
752     EB_ERRORTYPE return_error = EB_ErrorNone;
753     EB_S16  signBottomLeft;
754     EB_U32  eoIndex;
755     EB_U32  lcuColumn;
756 
757     EB_S16 signTopRight[MAX_LCU_SIZE + 1];
758 
759     EB_U32  lcuWidthCount = 0;
760     EB_U32  lcuHeightCount = 0;
761 
762 
763     for (lcuColumn = lcuWidthCount; lcuColumn < lcuWidth + 1; ++lcuColumn) {
764         signTopRight[lcuColumn] = SIGN(reconSamplePtr[(EB_S32)(lcuColumn - 1)], temporalBufferUpper[lcuColumn]);
765     }
766 
767     while (lcuHeightCount < lcuHeight) {
768 
769         signBottomLeft = SIGN(reconSamplePtr[lcuWidthCount], temporalBufferLeft[lcuHeightCount + 1]);
770         eoIndex = signTopRight[lcuWidthCount + 1] + signBottomLeft + 2;
771         signTopRight[lcuWidthCount] = -signBottomLeft;
772 
773         reconSamplePtr[lcuWidthCount] = (EB_U8)CLIP3(0, MAX_SAMPLE_VALUE, reconSamplePtr[lcuWidthCount] + saoOffsetPtr[eoIndex]);
774 
775         ++lcuWidthCount;
776 
777         while (lcuWidthCount < lcuWidth) {
778 
779             signBottomLeft = SIGN(reconSamplePtr[lcuWidthCount], reconSamplePtr[lcuWidthCount + reconStride - 1]);
780             eoIndex = signTopRight[lcuWidthCount + 1] + signBottomLeft + 2;
781             signTopRight[lcuWidthCount] = -signBottomLeft;
782 
783             reconSamplePtr[lcuWidthCount] = (EB_U8)CLIP3(0, MAX_SAMPLE_VALUE, reconSamplePtr[lcuWidthCount] + saoOffsetPtr[eoIndex]);
784 
785             ++lcuWidthCount;
786         }
787 
788         signTopRight[lcuWidth] = SIGN(reconSamplePtr[lcuWidth - 1 + reconStride], reconSamplePtr[lcuWidth]);
789 
790         lcuWidthCount = 0;
791 
792         ++lcuHeightCount;
793 
794         reconSamplePtr += reconStride;
795     }
796 
797     return return_error;
798 
799 }
800 /********************************************
801 * SAOApplyEO_45_16bit
802 *   applies EO 45 SAO for the whole LCU
803 ********************************************/
SAOApplyEO_45_16bit(EB_U16 * reconSamplePtr,EB_U32 reconStride,EB_U16 * temporalBufferLeft,EB_U16 * temporalBufferUpper,EB_S8 * saoOffsetPtr,EB_U32 lcuHeight,EB_U32 lcuWidth)804 EB_ERRORTYPE SAOApplyEO_45_16bit(
805     EB_U16                           *reconSamplePtr,
806     EB_U32                           reconStride,
807     EB_U16                           *temporalBufferLeft,
808     EB_U16                           *temporalBufferUpper,
809     EB_S8                           *saoOffsetPtr,
810     EB_U32                           lcuHeight,
811     EB_U32                           lcuWidth
812     )
813 {
814     EB_ERRORTYPE return_error = EB_ErrorNone;
815     EB_S16  signBottomLeft;
816     EB_U32  eoIndex;
817     EB_U32  lcuColumn;
818 
819     EB_S16 signTopRight[MAX_LCU_SIZE + 1];
820 
821     EB_U32  lcuWidthCount = 0;
822     EB_U32  lcuHeightCount = 0;
823 
824 
825     for (lcuColumn = lcuWidthCount; lcuColumn < lcuWidth + 1; ++lcuColumn) {
826         signTopRight[lcuColumn] = SIGN(reconSamplePtr[(EB_S32)(lcuColumn - 1)], temporalBufferUpper[lcuColumn]);
827     }
828 
829     while (lcuHeightCount < lcuHeight) {
830 
831         signBottomLeft = SIGN(reconSamplePtr[lcuWidthCount], temporalBufferLeft[lcuHeightCount + 1]);
832         eoIndex = signTopRight[lcuWidthCount + 1] + signBottomLeft + 2;
833         signTopRight[lcuWidthCount] = -signBottomLeft;
834 
835         reconSamplePtr[lcuWidthCount] = (EB_U16)CLIP3(0, MAX_SAMPLE_VALUE_10BIT, reconSamplePtr[lcuWidthCount] + saoOffsetPtr[eoIndex]);
836 
837         ++lcuWidthCount;
838 
839         while (lcuWidthCount < lcuWidth) {
840 
841             signBottomLeft = SIGN(reconSamplePtr[lcuWidthCount], reconSamplePtr[lcuWidthCount + reconStride - 1]);
842             eoIndex = signTopRight[lcuWidthCount + 1] + signBottomLeft + 2;
843             signTopRight[lcuWidthCount] = -signBottomLeft;
844 
845             reconSamplePtr[lcuWidthCount] = (EB_U16)CLIP3(0, MAX_SAMPLE_VALUE_10BIT, reconSamplePtr[lcuWidthCount] + saoOffsetPtr[eoIndex]);
846 
847             ++lcuWidthCount;
848         }
849 
850         signTopRight[lcuWidth] = SIGN(reconSamplePtr[lcuWidth - 1 + reconStride], reconSamplePtr[lcuWidth]);
851 
852         lcuWidthCount = 0;
853 
854         ++lcuHeightCount;
855 
856         reconSamplePtr += reconStride;
857     }
858 
859     return return_error;
860 
861 }
862