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