source: 3DVCSoftware/trunk/source/Lib/TLibCommon/TComAdaptiveLoopFilter.cpp @ 2

Last change on this file since 2 was 2, checked in by hhi, 13 years ago

inital import

  • Property svn:eol-style set to native
File size: 96.8 KB
Line 
1
2
3/** \file     TComAdaptiveLoopFilter.cpp
4    \brief    adaptive loop filter class
5*/
6
7#include "TComAdaptiveLoopFilter.h"
8#include <string.h>
9#include <stdlib.h>
10#include <stdio.h>
11#include <math.h>
12
13// ====================================================================================================================
14// Tables
15// ====================================================================================================================
16
17#if TI_ALF_MAX_VSIZE_7
18Int TComAdaptiveLoopFilter::m_pattern9x9Sym[39] = 
19#else
20Int TComAdaptiveLoopFilter::m_pattern9x9Sym[41] = 
21#endif
22{
23                   0,
24               1,  2,  3,
25           4,  5,  6,  7,  8,
26       9, 10, 11, 12, 13, 14, 15,
27#if TI_ALF_MAX_VSIZE_7
28      16, 17, 18, 19, 18, 17, 16,
29#else
30  16, 17, 18, 19, 20, 19, 18, 17, 16,
31#endif
32      15, 14, 13, 12, 11, 10,  9, 
33           8,  7,  6,  5,  4,
34               3,  2,  1,
35                   0
36};
37 
38#if TI_ALF_MAX_VSIZE_7
39Int TComAdaptiveLoopFilter::m_weights9x9Sym[21] = 
40#else
41Int TComAdaptiveLoopFilter::m_weights9x9Sym[22] = 
42#endif
43{
44#if !TI_ALF_MAX_VSIZE_7
45                   2,
46#endif
47               2,  2,  2,   
48           2,  2,  2,  2,  2, 
49       2,  2,  2,  2,  2,  2,  2, 
50   2,  2,  2,  2,  1,  1
51};
52
53#if TI_ALF_MAX_VSIZE_7
54Int TComAdaptiveLoopFilter::m_pattern9x9Sym_Quart[42] = 
55{
56   0,  0,  0,  0,  0,  0,  0,  0,  0,
57   0,  0,  0,  1,  2,  3,  0,  0,  0,
58   0,  0,  4,  5,  6,  7,  8,  0,  0, 
59   0,  9, 10, 11, 12, 13, 14, 15,  0,
60  16, 17, 18, 19, 20, 21
61};
62#else
63Int TComAdaptiveLoopFilter::m_pattern9x9Sym_Quart[42] = 
64{
65   0,  0,  0,  0,  1,  0,  0,  0,  0,
66   0,  0,  0,  2,  3,  4,  0,  0,  0,
67   0,  0,  5,  6,  7,  8,  9,  0,  0, 
68   0, 10, 11, 12, 13, 14, 15, 16,  0,
69  17, 18, 19, 20, 21, 22
70};
71#endif
72
73Int TComAdaptiveLoopFilter::m_pattern7x7Sym[25] = 
74{
75                   0,
76             1,  2,  3,
77       4,  5,  6,  7,  8,
78       9, 10, 11, 12, 11, 10, 9,
79           8,  7,  6,  5,  4,
80           3,  2,  1,
81             0
82};
83
84Int TComAdaptiveLoopFilter::m_weights7x7Sym[14] = 
85{
86                  2, 
87              2,  2,  2,   
88        2,  2,  2,  2,  2,   
89      2,  2,  2,  1,  1
90};
91
92Int TComAdaptiveLoopFilter::m_pattern7x7Sym_Quart[42] = 
93{
94   0,  0,  0,  0,  0,  0,  0,  0,  0,
95   0,  0,  0,  0,  1,  0,  0,  0,  0,
96   0,  0,  0,  2,  3,  4,  0,  0,  0,
97   0,  0,  5,  6,  7,  8,  9,  0,  0, 
98   0, 10, 11, 12, 13, 14, 
99};
100
101Int TComAdaptiveLoopFilter::m_pattern5x5Sym[13] = 
102{
103                   0,
104             1,  2,  3,
105       4,  5,  6,  5,  4,
106               3,  2,  1,
107             0
108};
109
110Int TComAdaptiveLoopFilter::m_weights5x5Sym[8] = 
111{
112           2, 
113        2, 2, 2,
114     2, 2, 1, 1
115};
116
117Int TComAdaptiveLoopFilter::m_pattern5x5Sym_Quart[45] = 
118{
119   0,  0,  0,  0,  0,  0,  0,  0,  0,
120   0,  0,  0,  0,  0,  0,  0,  0,  0,
121   0,  0,  0,  0,  1,  0,  0,  0,  0,
122   0,  0,  0,  2,  3,  4,  0,  0,  0,
123   0,  0,  5,  6,  7,  8,  0,  0,  0, 
124};
125
126#if TI_ALF_MAX_VSIZE_7
127Int TComAdaptiveLoopFilter::m_pattern9x9Sym_9[39] = 
128#else
129Int TComAdaptiveLoopFilter::m_pattern9x9Sym_9[41] = 
130#endif
131{
132#if !TI_ALF_MAX_VSIZE_7
133                   4,
134#endif
135              12, 13, 14, 
136          20, 21, 22, 23, 24, 
137      28, 29, 30, 31, 32, 33, 34,     
138  36, 37, 38, 39, 40, 39, 38, 37, 36, 
139      34, 33, 32, 31, 30, 29, 28, 
140          24, 23, 22, 21, 20, 
141              14, 13, 12,
142#if !TI_ALF_MAX_VSIZE_7
143                   4, 
144#endif
145};
146
147Int TComAdaptiveLoopFilter::m_pattern9x9Sym_7[25] = 
148{   
149               13,   
150           21, 22, 23, 
151       29, 30, 31, 32, 33,       
152   37, 38, 39, 40, 39, 38, 37, 
153       33, 32, 31, 30, 29,   
154           23, 22, 21, 
155               13 
156                     
157};
158
159Int TComAdaptiveLoopFilter::m_pattern9x9Sym_5[13] = 
160{
161          22, 
162      30, 31, 32,   
163  38, 39, 40, 39, 38, 
164      32, 31, 30, 
165          22, 
166 };
167
168Int* TComAdaptiveLoopFilter::m_patternTab_filt[NO_TEST_FILT] =
169{
170  m_pattern9x9Sym_9, m_pattern9x9Sym_7, m_pattern9x9Sym_5
171}; 
172
173Int* TComAdaptiveLoopFilter::m_patternTab[NO_TEST_FILT] =
174{
175  m_pattern9x9Sym, m_pattern7x7Sym, m_pattern5x5Sym
176}; 
177
178Int* TComAdaptiveLoopFilter::m_patternMapTab[NO_TEST_FILT] =
179{
180  m_pattern9x9Sym_Quart, m_pattern7x7Sym_Quart, m_pattern5x5Sym_Quart
181};
182
183Int* TComAdaptiveLoopFilter::m_weightsTab[NO_TEST_FILT] =
184{
185  m_weights9x9Sym, m_weights7x7Sym, m_weights5x5Sym
186};
187
188Int TComAdaptiveLoopFilter::m_flTab[NO_TEST_FILT] =
189{
190  9/2, 7/2, 5/2
191};
192
193Int TComAdaptiveLoopFilter::m_sqrFiltLengthTab[NO_TEST_FILT] =
194{
195  SQR_FILT_LENGTH_9SYM, SQR_FILT_LENGTH_7SYM, SQR_FILT_LENGTH_5SYM
196};
197
198#if TI_ALF_MAX_VSIZE_7
199Int depthInt9x9Sym[21] = 
200#else
201Int depthInt9x9Sym[22] = 
202#endif
203{
204#if !TI_ALF_MAX_VSIZE_7
205              5, 
206#endif
207           5, 6, 5, 
208        5, 6, 7, 6, 5,
209     5, 6, 7, 8, 7, 6, 5,
210  5, 6, 7, 8, 9, 9 
211};
212
213Int depthInt7x7Sym[14] = 
214{
215           4, 
216        4, 5, 4, 
217     4, 5, 6, 5, 4, 
218  4, 5, 6, 7, 7 
219};
220
221Int depthInt5x5Sym[8] = 
222{
223        3,   
224     3, 4, 3,
225  3, 4, 5, 5 
226};
227
228Int* pDepthIntTab[NO_TEST_FILT] =
229{
230  depthInt5x5Sym, depthInt7x7Sym, depthInt9x9Sym
231};
232
233// scaling factor for quantization of filter coefficients (9x9)
234const Int TComAdaptiveLoopFilter::m_aiSymmetricMag9x9[41] =
235{
236  2, 2, 2, 2, 2, 2, 2, 2, 2,
237  2, 2, 2, 2, 2, 2, 2, 2, 2,
238  2, 2, 2, 2, 2, 2, 2, 2, 2,
239  2, 2, 2, 2, 2, 2, 2, 2, 2,
240  2, 2, 2, 2, 1
241};
242
243// scaling factor for quantization of filter coefficients (7x7)
244const Int TComAdaptiveLoopFilter::m_aiSymmetricMag7x7[25] =
245{
246  2, 2, 2, 2, 2, 2, 2,
247  2, 2, 2, 2, 2, 2, 2,
248  2, 2, 2, 2, 2, 2, 2,
249  2, 2, 2, 1
250};
251
252// scaling factor for quantization of filter coefficients (5x5)
253const Int TComAdaptiveLoopFilter::m_aiSymmetricMag5x5[13] =
254{
255  2, 2, 2, 2, 2,
256  2, 2, 2, 2, 2,
257  2, 2, 1
258};
259
260#if TI_ALF_MAX_VSIZE_7
261const Int TComAdaptiveLoopFilter::m_aiSymmetricMag9x7[32] =
262{
263  2, 2, 2, 2, 2, 2, 2, 2, 2,
264  2, 2, 2, 2, 2, 2, 2, 2, 2,
265  2, 2, 2, 2, 2, 2, 2, 2, 2,
266  2, 2, 2, 2, 1
267};
268#endif
269
270// ====================================================================================================================
271// Constructor / destructor / create / destroy
272// ====================================================================================================================
273
274TComAdaptiveLoopFilter::TComAdaptiveLoopFilter()
275{
276  m_pcTempPicYuv = NULL;
277#if MTK_NONCROSS_INLOOP_FILTER
278  m_bUseNonCrossALF = false;
279#endif
280#if SB_MEM_FIX
281  m_bIsCreated = false;
282#endif
283}
284
285Void TComAdaptiveLoopFilter:: xError(const char *text, int code)
286{
287  fprintf(stderr, "%s\n", text);
288  exit(code);
289}
290
291Void TComAdaptiveLoopFilter:: no_mem_exit(const char *where)
292{
293  char errortext[200];
294  sprintf(errortext, "Could not allocate memory: %s",where);
295  xError (errortext, 100);
296}
297
298Void TComAdaptiveLoopFilter::initMatrix_imgpel(imgpel ***m2D, int d1, int d2)
299{
300  int i;
301 
302  if(!(*m2D = (imgpel **) calloc(d1, sizeof(imgpel *))))
303    FATAL_ERROR_0("initMatrix_imgpel: memory allocation problem\n", -1);
304  if(!((*m2D)[0] = (imgpel *) calloc(d1 * d2, sizeof(imgpel))))
305    FATAL_ERROR_0("initMatrix_imgpel: memory allocation problem\n", -1);
306 
307  for(i = 1; i < d1; i++)
308    (*m2D)[i] = (*m2D)[i-1] + d2;
309}
310
311Void TComAdaptiveLoopFilter::initMatrix_int(int ***m2D, int d1, int d2)
312{
313  int i;
314 
315  if(!(*m2D = (int **) calloc(d1, sizeof(int *))))
316    FATAL_ERROR_0("initMatrix_int: memory allocation problem\n", -1);
317  if(!((*m2D)[0] = (int *) calloc(d1 * d2, sizeof(int))))
318    FATAL_ERROR_0("initMatrix_int: memory allocation problem\n", -1);
319 
320  for(i = 1; i < d1; i++)
321    (*m2D)[i] = (*m2D)[i-1] + d2;
322}
323
324Void TComAdaptiveLoopFilter::destroyMatrix_int(int **m2D)
325{
326  if(m2D)
327  {
328    if(m2D[0])
329      free(m2D[0]);
330    else
331      FATAL_ERROR_0("destroyMatrix_int: memory free problem\n", -1);
332    free(m2D);
333  } 
334  else
335  {
336    FATAL_ERROR_0("destroyMatrix_int: memory free problem\n", -1);
337  }
338}
339
340Void TComAdaptiveLoopFilter::destroyMatrix_imgpel(imgpel **m2D)
341{
342  if(m2D)
343  {
344    if(m2D[0])
345      free(m2D[0]);
346    else
347      FATAL_ERROR_0("destroyMatrix_imgpel: memory free problem\n", -1);
348    free(m2D);
349  } 
350  else
351  {
352    FATAL_ERROR_0("destroyMatrix_imgpel: memory free problem\n", -1);
353  }
354}
355
356Void TComAdaptiveLoopFilter::get_mem2Dpel(imgpel ***array2D, int rows, int columns)
357{
358  int i;
359 
360  if((*array2D      = (imgpel**)calloc(rows,        sizeof(imgpel*))) == NULL)
361    no_mem_exit("get_mem2Dpel: array2D");
362  if(((*array2D)[0] = (imgpel* )calloc(rows*columns,sizeof(imgpel ))) == NULL)
363    no_mem_exit("get_mem2Dpel: array2D");
364 
365  for(i=1 ; i<rows ; i++)
366    (*array2D)[i] =  (*array2D)[i-1] + columns  ;
367}
368
369Void TComAdaptiveLoopFilter::free_mem2Dpel(imgpel **array2D)
370{
371  if (array2D)
372  {
373    if (array2D[0])
374      free (array2D[0]);
375    else xError ("free_mem2Dpel: trying to free unused memory",100);
376   
377    free (array2D);
378  }
379  else
380  {
381    xError ("free_mem2Dpel: trying to free unused memory",100);
382  }
383}
384
385Void TComAdaptiveLoopFilter::initMatrix_double(double ***m2D, int d1, int d2)
386{
387  int i;
388 
389  if(!(*m2D = (double **) calloc(d1, sizeof(double *))))
390    FATAL_ERROR_0("initMatrix_double: memory allocation problem\n", -1);
391  if(!((*m2D)[0] = (double *) calloc(d1 * d2, sizeof(double))))
392    FATAL_ERROR_0("initMatrix_double: memory allocation problem\n", -1);
393 
394  for(i = 1; i < d1; i++)
395    (*m2D)[i] = (*m2D)[i-1] + d2;
396}
397
398Void TComAdaptiveLoopFilter::initMatrix3D_double(double ****m3D, int d1, int d2, int d3)
399{
400  int  j;
401 
402  if(!((*m3D) = (double ***) calloc(d1, sizeof(double **))))
403    FATAL_ERROR_0("initMatrix3D_double: memory allocation problem\n", -1);
404 
405  for(j = 0; j < d1; j++)
406    initMatrix_double((*m3D) + j, d2, d3);
407}
408
409
410Void TComAdaptiveLoopFilter::initMatrix4D_double(double *****m4D, int d1, int d2, int d3, int d4)
411{
412  int  j;
413 
414  if(!((*m4D) = (double ****) calloc(d1, sizeof(double ***))))
415    FATAL_ERROR_0("initMatrix4D_double: memory allocation problem\n", -1);
416 
417  for(j = 0; j < d1; j++)
418    initMatrix3D_double((*m4D) + j, d2, d3, d4);
419}
420
421
422Void TComAdaptiveLoopFilter::destroyMatrix_double(double **m2D)
423{
424  if(m2D)
425  {
426    if(m2D[0])
427      free(m2D[0]);
428    else
429      FATAL_ERROR_0("destroyMatrix_double: memory free problem\n", -1);
430    free(m2D);
431  } 
432  else
433  {
434    FATAL_ERROR_0("destroyMatrix_double: memory free problem\n", -1);
435  }
436}
437
438Void TComAdaptiveLoopFilter::destroyMatrix3D_double(double ***m3D, int d1)
439{
440  int i;
441 
442  if(m3D)
443  {
444    for(i = 0; i < d1; i++)
445      destroyMatrix_double(m3D[i]);
446    free(m3D);
447  } 
448  else
449  {
450    FATAL_ERROR_0("destroyMatrix3D_double: memory free problem\n", -1);
451  }
452}
453
454
455Void TComAdaptiveLoopFilter::destroyMatrix4D_double(double ****m4D, int d1, int d2)
456{
457  int  j;
458 
459  if(m4D)
460  {
461    for(j = 0; j < d1; j++)
462      destroyMatrix3D_double(m4D[j], d2);
463    free(m4D);
464  } 
465  else
466  {
467    FATAL_ERROR_0("destroyMatrix4D_double: memory free problem\n", -1);
468  }
469}
470
471Void TComAdaptiveLoopFilter::create( Int iPicWidth, Int iPicHeight, UInt uiMaxCUWidth, UInt uiMaxCUHeight, UInt uiMaxCUDepth )
472{
473#if SB_MEM_FIX
474  m_bIsCreated = true;
475#endif
476  if ( !m_pcTempPicYuv )
477  {
478    m_pcTempPicYuv = new TComPicYuv;
479    m_pcTempPicYuv->create( iPicWidth, iPicHeight, uiMaxCUWidth, uiMaxCUHeight, uiMaxCUDepth );
480  }
481  m_img_height = iPicHeight;
482  m_img_width = iPicWidth;
483#if !MQT_BA_RA
484  initMatrix_imgpel(&m_imgY_var, m_img_height, m_img_width); 
485#endif
486  initMatrix_int(&m_imgY_temp, m_img_height+2*VAR_SIZE+3, m_img_width+2*VAR_SIZE+3);
487#if MQT_BA_RA
488  initMatrix_int(&m_imgY_ver, m_img_height+2*VAR_SIZE+3, m_img_width+2*VAR_SIZE+3);
489  initMatrix_int(&m_imgY_hor, m_img_height+2*VAR_SIZE+3, m_img_width+2*VAR_SIZE+3);
490  for(Int i=0; i< NUM_ALF_CLASS_METHOD; i++)
491  {
492    get_mem2Dpel(&(m_varImgMethods[i]), m_img_width, m_img_width);
493  }
494#endif   
495
496  initMatrix_int(&m_filterCoeffSym, NO_VAR_BINS, MAX_SQR_FILT_LENGTH);
497  initMatrix_int(&m_filterCoeffPrevSelected, NO_VAR_BINS, MAX_SQR_FILT_LENGTH); 
498  initMatrix_int(&m_filterCoeffTmp, NO_VAR_BINS, MAX_SQR_FILT_LENGTH);     
499  initMatrix_int(&m_filterCoeffSymTmp, NO_VAR_BINS, MAX_SQR_FILT_LENGTH);   
500
501#if MTK_NONCROSS_INLOOP_FILTER
502  m_uiNumLCUsInWidth   = m_img_width  / uiMaxCUWidth;
503  m_uiNumLCUsInHeight  = m_img_height / uiMaxCUHeight;
504
505  m_uiNumLCUsInWidth  += ( m_img_width % uiMaxCUWidth ) ? 1 : 0;
506  m_uiNumLCUsInHeight += ( m_img_height % uiMaxCUHeight ) ? 1 : 0;
507#endif
508
509#if MQT_BA_RA
510  createRegionIndexMap(m_varImgMethods[ALF_RA], m_img_width, m_img_height);
511#endif
512}
513
514Void TComAdaptiveLoopFilter::destroy()
515{
516#if SB_MEM_FIX
517  m_bIsCreated = false ;
518#endif
519  if ( m_pcTempPicYuv )
520  {
521    m_pcTempPicYuv->destroy();
522    delete m_pcTempPicYuv;
523  }
524#if !MQT_BA_RA
525  destroyMatrix_imgpel(m_imgY_var); 
526#endif
527  destroyMatrix_int(m_imgY_temp);
528
529#if MQT_BA_RA
530  destroyMatrix_int(m_imgY_ver);
531  destroyMatrix_int(m_imgY_hor);
532  for(Int i=0; i< NUM_ALF_CLASS_METHOD; i++)
533  {
534    free_mem2Dpel(m_varImgMethods[i]);
535  }
536#endif 
537  destroyMatrix_int(m_filterCoeffSym);
538  destroyMatrix_int(m_filterCoeffPrevSelected);
539  destroyMatrix_int(m_filterCoeffTmp);
540  destroyMatrix_int(m_filterCoeffSymTmp);
541}
542
543// ====================================================================================================================
544// Public member functions
545// ====================================================================================================================
546
547#if TI_ALF_MAX_VSIZE_7
548Int TComAdaptiveLoopFilter::ALFTapHToTapV(Int tapH)
549{
550  return min<UInt>(tapH, 7);
551}
552
553Int TComAdaptiveLoopFilter::ALFFlHToFlV(Int flH)
554{
555  return min<UInt>(flH, 7/2);
556}
557
558Int TComAdaptiveLoopFilter::ALFTapHToNumCoeff(Int tapH)
559{
560  Int num_coeff;
561 
562  num_coeff = (Int)(tapH*tapH)/4 + 2;
563  if (tapH == 9)
564    num_coeff -= 1;
565  else
566    assert(tapH < 9);
567 
568  return num_coeff;
569}
570#endif
571
572// --------------------------------------------------------------------------------------------------------------------
573// allocate / free / copy functions
574// --------------------------------------------------------------------------------------------------------------------
575
576Void TComAdaptiveLoopFilter::allocALFParam(ALFParam* pAlfParam)
577{
578  pAlfParam->alf_flag = 0;
579 
580  pAlfParam->coeff        = new Int[ALF_MAX_NUM_COEF];
581  pAlfParam->coeff_chroma = new Int[ALF_MAX_NUM_COEF_C];
582 
583  ::memset(pAlfParam->coeff,        0, sizeof(Int)*ALF_MAX_NUM_COEF   );
584  ::memset(pAlfParam->coeff_chroma, 0, sizeof(Int)*ALF_MAX_NUM_COEF_C );
585  pAlfParam->coeffmulti = new Int*[NO_VAR_BINS];
586  for (int i=0; i<NO_VAR_BINS; i++)
587  {
588    pAlfParam->coeffmulti[i] = new Int[ALF_MAX_NUM_COEF];
589    ::memset(pAlfParam->coeffmulti[i],        0, sizeof(Int)*ALF_MAX_NUM_COEF );
590  }
591#if TSB_ALF_HEADER
592  pAlfParam->num_cus_in_frame = m_uiNumCUsInFrame;
593  pAlfParam->num_alf_cu_flag  = 0;
594  pAlfParam->alf_cu_flag      = new UInt[(m_uiNumCUsInFrame << ((g_uiMaxCUDepth-1)*2))];
595#endif
596
597#if MQT_BA_RA
598  pAlfParam->alf_pcr_region_flag = 0;
599#endif
600}
601
602Void TComAdaptiveLoopFilter::freeALFParam(ALFParam* pAlfParam)
603{
604  assert(pAlfParam != NULL);
605 
606  if (pAlfParam->coeff != NULL)
607  {
608    delete[] pAlfParam->coeff;
609    pAlfParam->coeff = NULL;
610  }
611 
612  if (pAlfParam->coeff_chroma != NULL)
613  {
614    delete[] pAlfParam->coeff_chroma;
615    pAlfParam->coeff_chroma = NULL;
616  }
617  for (int i=0; i<NO_VAR_BINS; i++)
618  {
619    delete[] pAlfParam->coeffmulti[i];
620    pAlfParam->coeffmulti[i] = NULL;
621  }
622  delete[] pAlfParam->coeffmulti;
623  pAlfParam->coeffmulti = NULL;
624#if TSB_ALF_HEADER
625  if(pAlfParam->alf_cu_flag != NULL)
626  {
627    delete[] pAlfParam->alf_cu_flag;
628    pAlfParam->alf_cu_flag = NULL;
629  }
630#endif
631}
632
633Void TComAdaptiveLoopFilter::copyALFParam(ALFParam* pDesAlfParam, ALFParam* pSrcAlfParam)
634{
635  pDesAlfParam->alf_flag = pSrcAlfParam->alf_flag;
636  pDesAlfParam->cu_control_flag = pSrcAlfParam->cu_control_flag;
637  pDesAlfParam->chroma_idc = pSrcAlfParam->chroma_idc;
638  pDesAlfParam->tap = pSrcAlfParam->tap;
639#if TI_ALF_MAX_VSIZE_7
640  pDesAlfParam->tapV = pSrcAlfParam->tapV;
641#endif
642  pDesAlfParam->num_coeff = pSrcAlfParam->num_coeff;
643  pDesAlfParam->tap_chroma = pSrcAlfParam->tap_chroma;
644  pDesAlfParam->num_coeff_chroma = pSrcAlfParam->num_coeff_chroma;
645
646#if MQT_BA_RA
647  pDesAlfParam->alf_pcr_region_flag = pSrcAlfParam->alf_pcr_region_flag;
648#endif
649
650  ::memcpy(pDesAlfParam->coeff, pSrcAlfParam->coeff, sizeof(Int)*ALF_MAX_NUM_COEF);
651  ::memcpy(pDesAlfParam->coeff_chroma, pSrcAlfParam->coeff_chroma, sizeof(Int)*ALF_MAX_NUM_COEF_C);
652  pDesAlfParam->realfiltNo = pSrcAlfParam->realfiltNo;
653  pDesAlfParam->filtNo = pSrcAlfParam->filtNo;
654  ::memcpy(pDesAlfParam->filterPattern, pSrcAlfParam->filterPattern, sizeof(Int)*NO_VAR_BINS);
655  pDesAlfParam->startSecondFilter = pSrcAlfParam->startSecondFilter;
656  pDesAlfParam->noFilters = pSrcAlfParam->noFilters;
657 
658  //Coeff send related
659  pDesAlfParam->filters_per_group_diff = pSrcAlfParam->filters_per_group_diff; //this can be updated using codedVarBins
660  pDesAlfParam->filters_per_group = pSrcAlfParam->filters_per_group; //this can be updated using codedVarBins
661  ::memcpy(pDesAlfParam->codedVarBins, pSrcAlfParam->codedVarBins, sizeof(Int)*NO_VAR_BINS);
662  pDesAlfParam->forceCoeff0 = pSrcAlfParam->forceCoeff0;
663  pDesAlfParam->predMethod = pSrcAlfParam->predMethod;
664  for (int i=0; i<NO_VAR_BINS; i++)
665  {
666    ::memcpy(pDesAlfParam->coeffmulti[i], pSrcAlfParam->coeffmulti[i], sizeof(Int)*ALF_MAX_NUM_COEF);
667  }
668 
669#if TSB_ALF_HEADER
670  pDesAlfParam->num_alf_cu_flag = pSrcAlfParam->num_alf_cu_flag;
671  ::memcpy(pDesAlfParam->alf_cu_flag, pSrcAlfParam->alf_cu_flag, sizeof(UInt)*pSrcAlfParam->num_alf_cu_flag);
672#endif
673}
674
675// --------------------------------------------------------------------------------------------------------------------
676// prediction of filter coefficients
677// --------------------------------------------------------------------------------------------------------------------
678
679Void TComAdaptiveLoopFilter::predictALFCoeff( ALFParam* pAlfParam)
680{
681  Int i, sum, pred, tap, N;
682  const Int* pFiltMag = NULL;
683 
684  tap = pAlfParam->tap;
685#if TI_ALF_MAX_VSIZE_7
686  Int tapV = pAlfParam->tapV;
687#endif
688 
689  switch(tap)
690  {
691    case 5:
692      pFiltMag = m_aiSymmetricMag5x5;
693      break;
694    case 7:
695      pFiltMag = m_aiSymmetricMag7x7;
696      break;
697    case 9:
698#if TI_ALF_MAX_VSIZE_7
699      pFiltMag = m_aiSymmetricMag9x7;
700#else
701      pFiltMag = m_aiSymmetricMag9x9;
702#endif
703      break;
704    default:
705      assert(0);
706      break;
707  }
708#if TI_ALF_MAX_VSIZE_7
709  N = (tap * tapV + 1) >> 1;
710#else
711  N = (tap * tap + 1) >> 1;
712#endif
713  sum=0;
714  for(i=0; i<N-1;i++)
715  {
716    sum+=pFiltMag[i]*pAlfParam->coeff[i];
717  }
718  pred=(1<<ALF_NUM_BIT_SHIFT)-sum;
719  pAlfParam->coeff[N-1]=pred-pAlfParam->coeff[N-1];
720}
721
722Void TComAdaptiveLoopFilter::predictALFCoeffChroma( ALFParam* pAlfParam )
723{
724  Int i, sum, pred, tap, N;
725  const Int* pFiltMag = NULL;
726 
727  tap = pAlfParam->tap_chroma;
728  switch(tap)
729  {
730    case 5:
731      pFiltMag = m_aiSymmetricMag5x5;
732      break;
733    case 7:
734      pFiltMag = m_aiSymmetricMag7x7;
735      break;
736    case 9:
737      pFiltMag = m_aiSymmetricMag9x9;
738      break;
739    default:
740      assert(0);
741      break;
742  }
743  N = (tap*tap+1)>>1;
744  sum=0;
745  for(i=0; i<N;i++)
746  {
747    sum+=pFiltMag[i]*pAlfParam->coeff_chroma[i];
748  }
749  pred=(1<<ALF_NUM_BIT_SHIFT)-(sum-pAlfParam->coeff_chroma[N-1]);
750  pAlfParam->coeff_chroma[N-1]=pred-pAlfParam->coeff_chroma[N-1];
751}
752
753// --------------------------------------------------------------------------------------------------------------------
754// interface function for actual ALF process
755// --------------------------------------------------------------------------------------------------------------------
756
757/**
758 \param pcPic         picture (TComPic) class (input/output)
759 \param pcAlfParam    ALF parameter
760 \todo   for temporal buffer, it uses residual picture buffer, which may not be safe. Make it be safer.
761 */
762Void TComAdaptiveLoopFilter::ALFProcess(TComPic* pcPic, ALFParam* pcAlfParam)
763{
764  if(!pcAlfParam->alf_flag)
765  {
766    return;
767  }
768 
769  TComPicYuv* pcPicYuvRec    = pcPic->getPicYuvRec();
770  TComPicYuv* pcPicYuvExtRec = m_pcTempPicYuv;
771#if MTK_NONCROSS_INLOOP_FILTER
772  if(!m_bUseNonCrossALF)
773  {
774#endif     
775  pcPicYuvRec   ->copyToPic          ( pcPicYuvExtRec );
776  pcPicYuvExtRec->setBorderExtension ( false );
777  pcPicYuvExtRec->extendPicBorder    ();
778#if MTK_NONCROSS_INLOOP_FILTER
779  }
780#endif
781
782#if TSB_ALF_HEADER
783  if(pcAlfParam->cu_control_flag)
784  {
785    UInt idx = 0;
786#if MTK_NONCROSS_INLOOP_FILTER
787    if(!m_bUseNonCrossALF)
788    {
789#endif
790    for(UInt uiCUAddr = 0; uiCUAddr < pcPic->getNumCUsInFrame(); uiCUAddr++)
791    {
792      TComDataCU *pcCU = pcPic->getCU(uiCUAddr);
793      setAlfCtrlFlags(pcAlfParam, pcCU, 0, 0, idx);
794    }
795#if MTK_NONCROSS_INLOOP_FILTER
796    }
797    else
798    {
799      setAlfCtrlFlagsforSlices(pcAlfParam, idx);
800    }
801#endif
802
803  }
804#endif
805  xALFLuma_qc(pcPic, pcAlfParam, pcPicYuvExtRec, pcPicYuvRec);
806 
807  if(pcAlfParam->chroma_idc)
808  {
809    predictALFCoeffChroma(pcAlfParam);
810    xALFChroma( pcAlfParam, pcPicYuvExtRec, pcPicYuvRec);
811  }
812}
813
814// ====================================================================================================================
815// Protected member functions
816// ====================================================================================================================
817
818// --------------------------------------------------------------------------------------------------------------------
819// ALF for luma
820// --------------------------------------------------------------------------------------------------------------------
821Void TComAdaptiveLoopFilter::xALFLuma_qc(TComPic* pcPic, ALFParam* pcAlfParam, TComPicYuv* pcPicDec, TComPicYuv* pcPicRest)
822{
823  Int    LumaStride = pcPicDec->getStride();
824  imgpel* pDec = (imgpel*)pcPicDec->getLumaAddr();
825  imgpel* pRest = (imgpel*)pcPicRest->getLumaAddr();
826 
827  //Decode and reconst filter coefficients
828  DecFilter_qc(pDec,pcAlfParam,LumaStride);
829  //set maskImg using cu adaptive one.
830
831#if MQT_BA_RA
832  m_uiVarGenMethod = pcAlfParam->alf_pcr_region_flag;
833  m_imgY_var       = m_varImgMethods[m_uiVarGenMethod];
834#endif
835
836#if MTK_NONCROSS_INLOOP_FILTER
837  memset(m_imgY_temp[0],0,sizeof(int)*(m_img_height+2*VAR_SIZE)*(m_img_width+2*VAR_SIZE));
838  if(!m_bUseNonCrossALF)
839  {
840    calcVar(0, 0, m_imgY_var, pDec, FILTER_LENGTH/2, VAR_SIZE, m_img_height, m_img_width, LumaStride);
841#endif
842
843
844  if(pcAlfParam->cu_control_flag)
845  {
846    xCUAdaptive_qc(pcPic, pcAlfParam, pRest, pDec, LumaStride);
847  } 
848  else
849  {
850    //then do whole frame filtering
851    filterFrame(pRest, pDec, pcAlfParam->realfiltNo, LumaStride);
852  }
853#if MTK_NONCROSS_INLOOP_FILTER
854  }
855  else
856  {
857    for(UInt s=0; s< m_uiNumSlicesInPic; s++)
858    {
859      CAlfSlice* pSlice = &(m_pSlice[s]);
860
861      pSlice->copySliceLuma((Pel*)pDec, (Pel*)pRest, LumaStride);
862      pSlice->extendSliceBorderLuma((Pel*)pDec, LumaStride, (UInt)EXTEND_NUM_PEL);
863
864#if MQT_BA_RA
865      if(m_uiVarGenMethod != ALF_RA)
866      {
867#endif
868        calcVarforOneSlice(pSlice, m_imgY_var, pDec, FILTER_LENGTH/2, VAR_SIZE, LumaStride);
869#if MQT_BA_RA
870      }
871#endif
872      xFilterOneSlice(pSlice, pDec, pRest, LumaStride, pcAlfParam);
873
874    }
875  }
876#endif
877
878}
879
880
881Void TComAdaptiveLoopFilter::DecFilter_qc(imgpel* imgY_rec,ALFParam* pcAlfParam, int Stride)
882{
883  int i;
884  int numBits = NUM_BITS; 
885#if !MTK_NONCROSS_INLOOP_FILTER
886  int fl=FILTER_LENGTH/2;
887#endif
888  int **pfilterCoeffSym;
889  pfilterCoeffSym= m_filterCoeffSym;
890 
891  if(pcAlfParam->filtNo>=0)
892  {
893    //// Reconstruct filter coefficients
894    reconstructFilterCoeffs( pcAlfParam, pfilterCoeffSym, numBits);
895  }
896  else
897  {
898    for(i = 0; i < NO_VAR_BINS; i++)
899    {
900      pcAlfParam->varIndTab[i]=0;
901      memset(pfilterCoeffSym[i],0,sizeof(int)*MAX_SQR_FILT_LENGTH);
902    }
903  }
904  getCurrentFilter(pfilterCoeffSym,pcAlfParam);
905#if !MTK_NONCROSS_INLOOP_FILTER
906  memset(m_imgY_temp[0],0,sizeof(int)*(m_img_height+2*VAR_SIZE)*(m_img_width+2*VAR_SIZE));
907 
908  calcVar(m_imgY_var, imgY_rec, fl, VAR_SIZE, m_img_height, m_img_width, Stride);
909#endif
910}
911
912Void TComAdaptiveLoopFilter::getCurrentFilter(int **filterCoeffSym,ALFParam* pcAlfParam)
913{ 
914  int i,  k, varInd;
915  int *patternMap;
916  int *patternMapTab[3]={m_pattern9x9Sym_Quart, m_pattern7x7Sym_Quart, m_pattern5x5Sym_Quart};
917  {
918    for(varInd=0; varInd<NO_VAR_BINS; ++varInd)
919    {
920      memset(m_filterCoeffPrevSelected[varInd],0,sizeof(int)*MAX_SQR_FILT_LENGTH);
921    }
922    patternMap=patternMapTab[pcAlfParam->realfiltNo];
923    for(varInd=0; varInd<NO_VAR_BINS; ++varInd)
924    {
925      k=0;
926      for(i = 0; i < MAX_SQR_FILT_LENGTH; i++)
927      {
928        if (patternMap[i]>0)
929        {
930          m_filterCoeffPrevSelected[varInd][i]=filterCoeffSym[pcAlfParam->varIndTab[varInd]][k];
931          k++;
932        }
933        else
934        {
935          m_filterCoeffPrevSelected[varInd][i]=0;
936        }
937      }
938    }
939  }
940}
941
942Void TComAdaptiveLoopFilter::reconstructFilterCoeffs(ALFParam* pcAlfParam,int **pfilterCoeffSym, int bit_depth)
943{
944  int i, src, ind;
945 
946  // Copy non zero filters in filterCoeffTmp
947  for(ind = 0; ind < pcAlfParam->filters_per_group_diff; ++ind)
948  {
949    for(i = 0; i < pcAlfParam->num_coeff; i++)
950      m_filterCoeffTmp[ind][i] = pcAlfParam->coeffmulti[ind][i];
951  }
952  // Undo prediction
953  for(ind = 0; ind < pcAlfParam->filters_per_group_diff; ++ind)
954  {
955    if((!pcAlfParam->predMethod) || (ind == 0)) 
956    {
957      memcpy(m_filterCoeffSymTmp[ind],m_filterCoeffTmp[ind],sizeof(int)*pcAlfParam->num_coeff);
958    }
959    else
960    {
961      // Prediction
962      for(i = 0; i < pcAlfParam->num_coeff; ++i)
963        m_filterCoeffSymTmp[ind][i] = (int)(m_filterCoeffTmp[ind][i] + m_filterCoeffSymTmp[ind - 1][i]);
964    }
965  }
966 
967  // Inverse quantization
968  // Add filters forced to zero
969  if(pcAlfParam->forceCoeff0)
970  {
971    assert(pcAlfParam->filters_per_group_diff < pcAlfParam->filters_per_group);
972    src = 0;
973    for(ind = 0; ind < pcAlfParam->filters_per_group; ++ind)
974    {
975      if(pcAlfParam->codedVarBins[ind])
976      {
977        memcpy(pfilterCoeffSym[ind],m_filterCoeffSymTmp[src],sizeof(int)*pcAlfParam->num_coeff);
978        ++src;
979      }
980      else
981      {
982        memset(pfilterCoeffSym[ind],0,sizeof(int)*pcAlfParam->num_coeff);
983      }
984    }
985    assert(src == pcAlfParam->filters_per_group_diff);
986  }
987  else
988  {
989    assert(pcAlfParam->filters_per_group_diff == pcAlfParam->filters_per_group);
990    for(ind = 0; ind < pcAlfParam->filters_per_group; ++ind)
991      memcpy(pfilterCoeffSym[ind],m_filterCoeffSymTmp[ind],sizeof(int)*pcAlfParam->num_coeff);
992  }
993}
994
995
996static imgpel Clip_post(int high, int val)
997{
998  return (imgpel)(((val > high)? high: val));
999}
1000#if MTK_NONCROSS_INLOOP_FILTER
1001Void TComAdaptiveLoopFilter::calcVar(int ypos, int xpos, imgpel **imgY_var, imgpel *imgY_pad, int pad_size, int fl, int img_height, int img_width, int img_stride)
1002#else
1003Void TComAdaptiveLoopFilter::calcVar(imgpel **imgY_var, imgpel *imgY_pad, int pad_size, int fl, int img_height, int img_width, int img_stride)
1004#endif
1005{
1006
1007#if MQT_BA_RA
1008  if(m_uiVarGenMethod == ALF_RA)
1009  {
1010    return;
1011  }
1012
1013  static Int shift_h     = (Int)(log((double)VAR_SIZE_H)/log(2.0));
1014  static Int shift_w     = (Int)(log((double)VAR_SIZE_W)/log(2.0));
1015
1016#if MTK_NONCROSS_INLOOP_FILTER
1017  Int start_height = ypos;
1018  Int start_width  = xpos;
1019  Int end_height   = ypos + img_height;
1020  Int end_width    = xpos + img_width;
1021#else
1022  Int start_height = 0;
1023  Int start_width = 0;
1024  Int end_height = img_height;
1025  Int end_width = img_width;
1026#endif
1027  Int i, j;
1028  Int *p_imgY_temp;
1029#if FULL_NBIT
1030  Int shift= (11+ g_uiBitIncrement + g_uiBitDepth - 8);
1031#else
1032  Int shift= (11+ g_uiBitIncrement);
1033#endif
1034  Int fl2plusOne= (VAR_SIZE<<1)+1; //3
1035  Int pad_offset = pad_size-fl-1;
1036  Int var_max= NO_VAR_BINS-1;
1037  Int mult_fact_int_tab[4]= {1,114,41,21};
1038  Int mult_fact_int = mult_fact_int_tab[VAR_SIZE];
1039  Int avg_var;
1040  Int vertical, horizontal;
1041  Int direction;
1042  Int step1 = NO_VAR_BINS/3 - 1;
1043  Int th[NO_VAR_BINS] = {0, 1, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4}; 
1044
1045  for(i = 1+start_height; i < end_height + fl2plusOne; i++)
1046  {
1047    Int yoffset = (pad_offset+i-pad_size) * img_stride + pad_offset-pad_size;
1048    imgpel *p_imgY_pad = &imgY_pad[yoffset];
1049    imgpel *p_imgY_pad_up   = &imgY_pad[yoffset + img_stride];
1050    imgpel *p_imgY_pad_down = &imgY_pad[yoffset - img_stride];
1051    p_imgY_temp = (Int*)&m_imgY_temp[i-1][start_width];
1052    for(j = 1+start_width; j < end_width +fl2plusOne; j++) 
1053    {
1054      vertical = abs((p_imgY_pad[j]<<1) - p_imgY_pad_down[j] - p_imgY_pad_up[j]);
1055      horizontal = abs((p_imgY_pad[j]<<1) - p_imgY_pad[j+1] - p_imgY_pad[j-1]);
1056      m_imgY_ver[i-1][j-1] = vertical;
1057      m_imgY_hor[i-1][j-1] = horizontal;
1058      *(p_imgY_temp++) = vertical + horizontal;
1059    }
1060
1061    for(j = 1+start_width; j < end_width + fl2plusOne; j=j+4) 
1062    {
1063      m_imgY_temp [i-1][j] =  (m_imgY_temp [i-1][j-1] + m_imgY_temp [i-1][j+4])
1064        + ((m_imgY_temp [i-1][j] + m_imgY_temp [i-1][j+3]) << 1)
1065        + ((m_imgY_temp [i-1][j+1] + m_imgY_temp [i-1][j+2]) * 3);
1066      m_imgY_ver[i-1][j] = m_imgY_ver[i-1][j] + m_imgY_ver[i-1][j+1] + m_imgY_ver[i-1][j+2] + m_imgY_ver[i-1][j+3];     
1067      m_imgY_hor[i-1][j] = m_imgY_hor[i-1][j] + m_imgY_hor[i-1][j+1] + m_imgY_hor[i-1][j+2] + m_imgY_hor[i-1][j+3];   
1068    }
1069  }
1070
1071  for(i = 1+start_height; i < end_height + 1; i=i+4)
1072  {
1073    for(j = 1+start_width; j < end_width + 1; j=j+4) 
1074    {
1075      m_imgY_temp [i-1][j-1] =  (m_imgY_temp [i-1][j]+m_imgY_temp [i+4][j])
1076        + ((m_imgY_temp [i][j]+m_imgY_temp [i+3][j]) << 1)
1077        + ((m_imgY_temp [i+1][j]+m_imgY_temp [i+2][j]) * 3);
1078
1079      m_imgY_ver[i-1][j-1] = m_imgY_ver[i][j] + m_imgY_ver[i+1][j] + m_imgY_ver[i+2][j] + m_imgY_ver[i+3][j]; 
1080      m_imgY_hor[i-1][j-1] = m_imgY_hor[i][j] + m_imgY_hor[i+1][j] + m_imgY_hor[i+2][j] + m_imgY_hor[i+3][j];   
1081      avg_var = m_imgY_temp [i-1][j-1]>>(shift_h + shift_w);
1082      avg_var = (imgpel) Clip_post(var_max, (avg_var * mult_fact_int)>>shift);
1083      avg_var = th[avg_var];
1084
1085      direction = 0;
1086      if (m_imgY_ver[i-1][j-1] > 2*m_imgY_hor[i-1][j-1]) direction = 1; //vertical
1087      if (m_imgY_hor[i-1][j-1] > 2*m_imgY_ver[i-1][j-1]) direction = 2; //horizontal
1088
1089      avg_var = Clip_post(step1, (Int) avg_var ) + (step1+1)*direction; 
1090      imgY_var[(i - 1)>>shift_h][(j - 1)>>shift_w] = avg_var;   
1091    }
1092  }
1093
1094#else
1095
1096  int i, j, ii, jj;
1097  int sum;
1098  int *p_imgY_temp;
1099#if FULL_NBIT
1100  int shift= (11+ g_uiBitIncrement + g_uiBitDepth - 8);
1101#else
1102  int shift= (11+ g_uiBitIncrement);
1103#endif
1104  int fl2plusOne= (VAR_SIZE<<1)+1;
1105  int pad_offset = pad_size-fl-1;
1106  int var_max= NO_VAR_BINS-1;
1107  int mult_fact_int_tab[4]= {1,114,41,21};
1108  int mult_fact_int = mult_fact_int_tab[VAR_SIZE];
1109 
1110  if (VAR_SIZE ==0)
1111  {
1112    imgpel *p_imgY_var;
1113#if FULL_NBIT
1114    shift = g_uiBitIncrement + g_uiBitDepth - 8;
1115#else
1116    shift = g_uiBitIncrement;
1117#endif
1118    //current
1119    for(i = 1; i < img_height + fl2plusOne; i++)
1120    {
1121      imgpel *p_imgY_pad = &imgY_pad[(pad_offset+i-pad_size) * img_stride + pad_offset-pad_size];
1122      imgpel *p_imgY_pad_up   = &imgY_pad[(pad_offset+i+1-pad_size) * img_stride + pad_offset-pad_size];
1123      imgpel *p_imgY_pad_down = &imgY_pad[(pad_offset+i-1-pad_size) * img_stride + pad_offset-pad_size];
1124      p_imgY_temp = (int*)&m_imgY_temp[i-1][0];
1125#if MTK_NONCROSS_INLOOP_FILTER
1126      p_imgY_var  = &imgY_var [ypos+ i-1][xpos];
1127#else
1128      p_imgY_var  = &imgY_var [i-1][0];
1129#endif
1130      for(j = 1; j < img_width +fl2plusOne; j++)
1131      {
1132        *(p_imgY_temp) = abs((p_imgY_pad[j]<<1) - p_imgY_pad[j+1] - p_imgY_pad[j-1])+
1133        abs((p_imgY_pad[j]<<1) - p_imgY_pad_down[j] - p_imgY_pad_up[j]);
1134        *(p_imgY_var++) =(imgpel) Clip_post(var_max, (int) ((*(p_imgY_temp++))>>shift));
1135      }
1136    }
1137    return;
1138  }
1139 
1140  //current
1141  for(i = 1; i < img_height + fl2plusOne; i++)
1142  {
1143    imgpel *p_imgY_pad = &imgY_pad[(pad_offset+i-pad_size) * img_stride + pad_offset-pad_size];
1144    imgpel *p_imgY_pad_up   = &imgY_pad[(pad_offset+i+1-pad_size) * img_stride + pad_offset-pad_size];
1145    imgpel *p_imgY_pad_down = &imgY_pad[(pad_offset+i-1-pad_size) * img_stride + pad_offset-pad_size];
1146    p_imgY_temp = (int*)&m_imgY_temp[i-1][0];
1147    for(j = 1; j < img_width +fl2plusOne; j++)
1148    {
1149      *(p_imgY_temp++) = abs((p_imgY_pad[j]<<1) - p_imgY_pad[j+1] - p_imgY_pad[j-1])+
1150        abs((p_imgY_pad[j]<<1) - p_imgY_pad_down[j] - p_imgY_pad_up[j]);
1151    }
1152  }
1153  {
1154    //int temp;
1155    int sum_0=0;
1156    int y=img_height+((VAR_SIZE+1)<<1);
1157
1158    int *p_imgY_temp_sum;
1159    i = fl;
1160    j = fl;
1161
1162    memset(m_imgY_temp[y],0,sizeof(int)*(img_width+((VAR_SIZE+1)<<1)));
1163    //--------------------------------------------------------------------------------------------
1164
1165    for(ii = i - fl; ii <= i + fl; ii++)
1166    {
1167      p_imgY_temp= (int*)&m_imgY_temp[ii][j - fl];
1168      p_imgY_temp_sum=(int*)&m_imgY_temp[y][j - fl];
1169      for(jj = j - fl; jj <= j + fl; jj++)
1170      {
1171        *(p_imgY_temp_sum++) += *(p_imgY_temp++);
1172      }
1173    }
1174    p_imgY_temp_sum=(int*)&m_imgY_temp[y][j - fl];
1175    for(jj = j - fl; jj <= j + fl; jj++)
1176      sum_0+=*(p_imgY_temp_sum++);
1177#if MTK_NONCROSS_INLOOP_FILTER
1178    imgY_var[ypos+ i - fl][xpos+ j - fl] 
1179#else
1180    imgY_var[i - fl][j - fl] 
1181#endif
1182    = (imgpel) Clip_post(var_max, (int) ((sum_0 * mult_fact_int)>>shift));
1183    //--------------------------------------------------------------------------------------------
1184    sum = sum_0;
1185    for(j = fl+1; j < img_width + fl; ++j)
1186    {
1187      int k=j+fl;
1188      for(ii = i - fl; ii <= i + fl; ii++)
1189        m_imgY_temp[y][k] += (m_imgY_temp[ii][k]);
1190
1191      sum += (m_imgY_temp[y][k]-m_imgY_temp[y][j - fl-1]);
1192#if MTK_NONCROSS_INLOOP_FILTER
1193      imgY_var[ypos+ i - fl][xpos+ j - fl] 
1194#else
1195      imgY_var[i - fl][j - fl] 
1196#endif
1197      = (imgpel) Clip_post(var_max, (int) ((sum * mult_fact_int)>>shift));
1198
1199    }
1200    //--------------------------------------------------------------------------------------------
1201
1202    for(i = fl+1; i < img_height + fl; ++i)
1203    {
1204#if MTK_NONCROSS_INLOOP_FILTER
1205      imgpel  *pimgY_var= &imgY_var[ypos+ i-fl][xpos];
1206#else
1207      imgpel  *pimgY_var= &imgY_var[i-fl][0];
1208#endif
1209      int *p_imgY_temp1;
1210      int *p_imgY_temp2;
1211      sum = sum_0;
1212      j= fl;
1213      p_imgY_temp1= (int*)&m_imgY_temp[i+fl  ][j - fl];
1214      p_imgY_temp2= (int*)&m_imgY_temp[i-fl-1][j - fl];
1215      p_imgY_temp_sum=(int*)&m_imgY_temp[y][j - fl];
1216      for(jj = j - fl; jj <= j + fl; jj++)
1217      {
1218        int diff = *(p_imgY_temp1++)-*(p_imgY_temp2++);
1219        *(p_imgY_temp_sum++) += diff;
1220        sum += diff;
1221      }
1222      sum_0=sum;
1223
1224      *(pimgY_var++) = (imgpel) Clip_post(var_max, (int) ((sum * mult_fact_int)>>shift));
1225      //--------------------------------------------------------------------------------------------
1226      p_imgY_temp_sum=(int*)m_imgY_temp[y];
1227      for(j = fl+1; j < img_width + fl; ++j)
1228      {
1229        int k = j+fl;
1230        p_imgY_temp_sum[k] += (m_imgY_temp[i + fl][k]-m_imgY_temp[i-fl-1][k]);
1231        sum += (p_imgY_temp_sum[k]-p_imgY_temp_sum[j-fl-1]);
1232        *(pimgY_var++) = (imgpel) Clip_post(var_max, (int) ((sum * mult_fact_int)>>shift));
1233      }
1234    }
1235  }
1236#endif
1237}
1238
1239
1240#if MQT_BA_RA
1241
1242Void TComAdaptiveLoopFilter::createRegionIndexMap(imgpel **imgYVar, Int imgWidth, Int imgHeight)
1243{
1244  int varStepSizeWidth = VAR_SIZE_W;
1245  int varStepSizeHeight = VAR_SIZE_H;
1246  int shiftHeight = (int)(log((double)varStepSizeHeight)/log(2.0));
1247  int shiftWidth = (int)(log((double)varStepSizeWidth)/log(2.0));
1248
1249  int i, j;
1250  int regionTable[NO_VAR_BINS] = {0, 1, 4, 5, 15, 2, 3, 6, 14, 11, 10, 7, 13, 12,  9,  8}; 
1251  int xInterval;
1252  int yInterval;
1253  int yIndex;
1254  int yIndexOffset;
1255  int yStartLine;
1256  int yEndLine;
1257
1258  xInterval = ((( (imgWidth+63)/64) + 1) / 4 * 64)>>shiftWidth; 
1259  yInterval = ((((imgHeight+63)/64) + 1) / 4 * 64)>>shiftHeight;
1260
1261  for (yIndex = 0; yIndex < 4 ; yIndex++)
1262  {
1263    yIndexOffset = yIndex * 4;
1264    yStartLine = yIndex * yInterval;
1265    yEndLine   = (yIndex == 3) ? imgHeight>>shiftHeight : (yStartLine+yInterval);
1266
1267    for(i = yStartLine; i < yEndLine ; i++)
1268    {
1269      for(j = 0; j < xInterval ; j++)
1270      {
1271        imgYVar[i][j] = regionTable[yIndexOffset+0];     
1272      }
1273
1274      for(j = xInterval; j < xInterval*2 ; j++)
1275      {
1276        imgYVar[i][j] = regionTable[yIndexOffset+1];     
1277      }
1278
1279      for(j = xInterval*2; j < xInterval*3 ; j++)
1280      {
1281        imgYVar[i][j] = regionTable[yIndexOffset+2];     
1282      }
1283
1284      for(j = xInterval*3; j < imgWidth>>shiftWidth ; j++)
1285      {
1286        imgYVar[i][j] = regionTable[yIndexOffset+3];     
1287      }
1288    }
1289  }
1290
1291}
1292
1293Void TComAdaptiveLoopFilter::filterFrame(imgpel *imgYRecPost, imgpel *imgYRec, int filtNo, int stride)
1294{
1295  Int varStepSizeWidth = VAR_SIZE_W;
1296  Int varStepSizeHeight = VAR_SIZE_H;
1297  Int shiftHeight = (Int)(log((double)varStepSizeHeight)/log(2.0));
1298
1299  Int i, j, pixelInt;
1300  imgpel *pImgYVar,*pImgYPad;
1301  Int maxVal=g_uiIBDI_MAX;
1302  imgpel *pImgYPad1,*pImgYPad2,*pImgYPad3,*pImgYPad4,*pImgYPad5,*pImgYPad6;
1303  Int lastCoef= MAX_SQR_FILT_LENGTH-1;
1304  Int *coef = m_filterCoeffPrevSelected[0];
1305  Int numBitsMinus1= NUM_BITS-1;
1306  Int offset = (1<<(NUM_BITS-2));
1307
1308  switch(filtNo)
1309  {
1310  case 2:
1311    for (i = 0; i < m_img_height; i++)
1312    {
1313      pImgYVar = m_imgY_var[i>>shiftHeight];
1314      pImgYPad = imgYRec + i*stride;
1315      {
1316        pImgYPad1 = imgYRec + (i+1)*stride;
1317        pImgYPad2 = imgYRec + (i-1)*stride;
1318        pImgYPad3 = imgYRec + (i+2)*stride;
1319        pImgYPad4 = imgYRec + (i-2)*stride;
1320        pImgYPad5 = imgYRec + (i+3)*stride;
1321        pImgYPad6 = imgYRec + (i-3)*stride;
1322      }
1323
1324      for (j = 0; j < m_img_width; j++)
1325      {
1326        if (j%varStepSizeWidth==0) coef = m_filterCoeffPrevSelected[*(pImgYVar++)];
1327        pixelInt=coef[lastCoef];
1328
1329        pixelInt += coef[22]* (pImgYPad3[j]+pImgYPad4[j]);
1330
1331        pixelInt += coef[30]* (pImgYPad1[j+1]+pImgYPad2[j-1]);
1332        pixelInt += coef[31]* (pImgYPad1[j]  +pImgYPad2[j]);
1333        pixelInt += coef[32]* (pImgYPad1[j-1]+pImgYPad2[j+1]);
1334
1335        pixelInt += coef[38]* (pImgYPad[j-2]+pImgYPad[j+2]);
1336        pixelInt += coef[39]* (pImgYPad[j-1]+pImgYPad[j+1]);
1337        pixelInt += coef[40]* (pImgYPad[j]);
1338
1339        pixelInt=(Int)((pixelInt+offset) >> (numBitsMinus1));
1340        imgYRecPost[i*stride + j]=max(0, min(pixelInt,maxVal));
1341      }
1342    }
1343    break;
1344
1345  case 1:
1346    for (i = 0; i < m_img_height; i++)
1347    {
1348      pImgYVar = m_imgY_var[i>>shiftHeight];
1349      pImgYPad = imgYRec + i*stride;
1350      {
1351        pImgYPad1 = imgYRec + (i+1)*stride;
1352        pImgYPad2 = imgYRec + (i-1)*stride;
1353        pImgYPad3 = imgYRec + (i+2)*stride;
1354        pImgYPad4 = imgYRec + (i-2)*stride;
1355        pImgYPad5 = imgYRec + (i+3)*stride;
1356        pImgYPad6 = imgYRec + (i-3)*stride;
1357      }
1358
1359      for (j = 0; j < m_img_width; j++)
1360      {
1361        if (j%varStepSizeWidth==0) coef = m_filterCoeffPrevSelected[*(pImgYVar++)];
1362        pixelInt=coef[lastCoef];
1363
1364        pixelInt += coef[13]* (imgYRec[(i+3)*stride + j]+imgYRec[(i-3)*stride + j]);
1365
1366        pixelInt += coef[21]* (pImgYPad3[j+1]+pImgYPad4[j-1]);
1367        pixelInt += coef[22]* (pImgYPad3[j]+pImgYPad4[j]);
1368        pixelInt += coef[23]* (pImgYPad3[j-1]+pImgYPad4[j+1]);
1369
1370        pixelInt += coef[29]* (pImgYPad1[j+2]+pImgYPad2[j-2]);
1371        pixelInt += coef[30]* (pImgYPad1[j+1]+pImgYPad2[j-1]);
1372        pixelInt += coef[31]* (pImgYPad1[j]+pImgYPad2[j]);
1373        pixelInt += coef[32]* (pImgYPad1[j-1]+pImgYPad2[j+1]);
1374        pixelInt += coef[33]* (pImgYPad1[j-2]+pImgYPad2[j+2]);
1375
1376        pixelInt += coef[37]* (pImgYPad[j+3]+pImgYPad[j-3]);
1377        pixelInt += coef[38]* (pImgYPad[j+2]+pImgYPad[j-2]);
1378        pixelInt += coef[39]* (pImgYPad[j+1]+pImgYPad[j-1]);
1379        pixelInt += coef[40]* (pImgYPad[j]);
1380
1381        pixelInt=(Int)((pixelInt+offset) >> (numBitsMinus1));
1382        imgYRecPost[i*stride + j]=max(0, min(pixelInt,maxVal));
1383      }
1384    }
1385    break;
1386
1387  case 0:
1388    for (i = 0; i < m_img_height; i++)
1389    {
1390      pImgYVar = m_imgY_var[i>>shiftHeight];
1391      pImgYPad = imgYRec + i*stride;
1392      {
1393        pImgYPad1 = imgYRec + (i+1)*stride;
1394        pImgYPad2 = imgYRec + (i-1)*stride;
1395        pImgYPad3 = imgYRec + (i+2)*stride;
1396        pImgYPad4 = imgYRec + (i-2)*stride;
1397        pImgYPad5 = imgYRec + (i+3)*stride;
1398        pImgYPad6 = imgYRec + (i-3)*stride;
1399      }
1400
1401      for (j = 0; j < m_img_width; j++)
1402      {
1403        if (j%varStepSizeWidth==0) coef = m_filterCoeffPrevSelected[*(pImgYVar++)];
1404        pixelInt=coef[lastCoef];
1405
1406#if !TI_ALF_MAX_VSIZE_7
1407        pixelInt += coef[4]* (imgYRec[(i+4)*stride + j]+imgYRec[(i-4)*stride + j]);
1408#endif       
1409        pixelInt += coef[12]* (pImgYPad5[j+1]+pImgYPad6[j-1]);
1410        pixelInt += coef[13]* (pImgYPad5[j]+pImgYPad6[j]);
1411        pixelInt += coef[14]* (pImgYPad5[j-1]+pImgYPad6[j+1]);
1412
1413        pixelInt += coef[20]* (pImgYPad3[j+2]+pImgYPad4[j-2]);
1414        pixelInt += coef[21]* (pImgYPad3[j+1]+pImgYPad4[j-1]);
1415        pixelInt += coef[22]* (pImgYPad3[j]+pImgYPad4[j]);
1416        pixelInt += coef[23]* (pImgYPad3[j-1]+pImgYPad4[j+1]);
1417        pixelInt += coef[24]* (pImgYPad3[j-2]+pImgYPad4[j+2]);
1418
1419        pixelInt += coef[28]* (pImgYPad1[j+3]+pImgYPad2[j-3]);
1420        pixelInt += coef[29]* (pImgYPad1[j+2]+pImgYPad2[j-2]);
1421        pixelInt += coef[30]* (pImgYPad1[j+1]+pImgYPad2[j-1]);
1422        pixelInt += coef[31]* (pImgYPad1[j]+pImgYPad2[j]);
1423        pixelInt += coef[32]* (pImgYPad1[j-1]+pImgYPad2[j+1]);
1424        pixelInt += coef[33]* (pImgYPad1[j-2]+pImgYPad2[j+2]);
1425        pixelInt += coef[34]* (pImgYPad1[j-3]+pImgYPad2[j+3]);
1426
1427        pixelInt += coef[36]* (pImgYPad[j+4]+pImgYPad[j-4]);
1428        pixelInt += coef[37]* (pImgYPad[j+3]+pImgYPad[j-3]);
1429        pixelInt += coef[38]* (pImgYPad[j+2]+pImgYPad[j-2]);
1430        pixelInt += coef[39]* (pImgYPad[j+1]+pImgYPad[j-1]);
1431        pixelInt += coef[40]* (pImgYPad[j]);
1432
1433        pixelInt=(Int)((pixelInt+offset) >> (numBitsMinus1));
1434        imgYRecPost[i*stride + j]=max(0, min(pixelInt,maxVal));
1435      }
1436    }
1437    break;
1438  }
1439}
1440
1441Void TComAdaptiveLoopFilter::subfilterFrame(imgpel *imgYRecPost, imgpel *imgYRec, int filtNo, int startHeight, int endHeight, int startWidth, int endWidth, int stride)
1442{
1443  Int varStepSizeWidth = VAR_SIZE_W;
1444  Int varStepSizeHeight = VAR_SIZE_H;
1445  Int shiftHeight = (Int)(log((double)varStepSizeHeight)/log(2.0));
1446  Int shiftWidth = (Int)(log((double)varStepSizeWidth)/log(2.0));
1447  Int i, j, pixelInt;
1448  imgpel *pImgYVar,*pImgYPad;
1449  imgpel *pImgYPad1,*pImgYPad2,*pImgYPad3,*pImgYPad4,*pImgYPad5,*pImgYPad6;
1450  Int maxVal=g_uiIBDI_MAX;
1451  Int lastCoef= MAX_SQR_FILT_LENGTH-1;
1452  Int *coef = m_filterCoeffPrevSelected[0];
1453  Int numBitsMinus1= NUM_BITS-1;
1454  Int offset = (1<<(NUM_BITS-2));
1455
1456  switch(filtNo)
1457  {
1458  case 2:
1459    for (i =  startHeight; i < endHeight; i++)
1460    {
1461      pImgYVar = m_imgY_var[i>>shiftHeight] + (startWidth>>shiftWidth);
1462      pImgYPad = imgYRec + i*stride;
1463      {
1464        pImgYPad1 = imgYRec + (i+1)*stride;
1465        pImgYPad2 = imgYRec + (i-1)*stride;
1466        pImgYPad3 = imgYRec + (i+2)*stride;
1467        pImgYPad4 = imgYRec + (i-2)*stride;
1468        pImgYPad5 = imgYRec + (i+3)*stride;
1469        pImgYPad6 = imgYRec + (i-3)*stride;
1470      }
1471
1472      for (j = startWidth; j < endWidth; j++)
1473      {
1474        if (j%varStepSizeWidth==0) coef = m_filterCoeffPrevSelected[*(pImgYVar++)];
1475        pixelInt=coef[lastCoef];
1476
1477        pixelInt += coef[22]* (pImgYPad3[j]+pImgYPad4[j]);
1478
1479        pixelInt += coef[30]* (pImgYPad1[j+1]+pImgYPad2[j-1]);
1480        pixelInt += coef[31]* (pImgYPad1[j]  +pImgYPad2[j]);
1481        pixelInt += coef[32]* (pImgYPad1[j-1]+pImgYPad2[j+1]);
1482
1483        pixelInt += coef[38]* (pImgYPad[j-2]+pImgYPad[j+2]);
1484        pixelInt += coef[39]* (pImgYPad[j-1]+pImgYPad[j+1]);
1485        pixelInt += coef[40]* (pImgYPad[j]);
1486
1487        pixelInt=(Int)((pixelInt+offset) >> (numBitsMinus1));
1488        imgYRecPost[i*stride + j]=max(0, min(pixelInt,maxVal));
1489      }
1490    }
1491    break;
1492
1493  case 1:
1494    for (i =  startHeight; i < endHeight; i++)
1495    {
1496      pImgYVar = m_imgY_var[i>>shiftHeight] + (startWidth>>shiftWidth);
1497      pImgYPad = imgYRec + i*stride;
1498      {
1499        pImgYPad1 = imgYRec + (i+1)*stride;
1500        pImgYPad2 = imgYRec + (i-1)*stride;
1501        pImgYPad3 = imgYRec + (i+2)*stride;
1502        pImgYPad4 = imgYRec + (i-2)*stride;
1503        pImgYPad5 = imgYRec + (i+3)*stride;
1504        pImgYPad6 = imgYRec + (i-3)*stride;
1505      }
1506
1507      for (j = startWidth; j < endWidth; j++)
1508      {
1509        if (j%varStepSizeWidth==0) coef = m_filterCoeffPrevSelected[*(pImgYVar++)];
1510        pixelInt=coef[lastCoef];
1511
1512        pixelInt += coef[13]* (imgYRec[(i+3)*stride + j]+imgYRec[(i-3)*stride + j]);
1513
1514        pixelInt += coef[21]* (pImgYPad3[j+1]+pImgYPad4[j-1]);
1515        pixelInt += coef[22]* (pImgYPad3[j]+pImgYPad4[j]);
1516        pixelInt += coef[23]* (pImgYPad3[j-1]+pImgYPad4[j+1]);
1517
1518        pixelInt += coef[29]* (pImgYPad1[j+2]+pImgYPad2[j-2]);
1519        pixelInt += coef[30]* (pImgYPad1[j+1]+pImgYPad2[j-1]);
1520        pixelInt += coef[31]* (pImgYPad1[j]+pImgYPad2[j]);
1521        pixelInt += coef[32]* (pImgYPad1[j-1]+pImgYPad2[j+1]);
1522        pixelInt += coef[33]* (pImgYPad1[j-2]+pImgYPad2[j+2]);
1523
1524        pixelInt += coef[37]* (pImgYPad[j+3]+pImgYPad[j-3]);
1525        pixelInt += coef[38]* (pImgYPad[j+2]+pImgYPad[j-2]);
1526        pixelInt += coef[39]* (pImgYPad[j+1]+pImgYPad[j-1]);
1527        pixelInt += coef[40]* (pImgYPad[j]);
1528
1529        pixelInt=(Int)((pixelInt+offset) >> (numBitsMinus1));
1530        imgYRecPost[i*stride + j]=max(0, min(pixelInt,maxVal));
1531      }
1532    }
1533    break;
1534
1535  case 0:
1536    for (i =  startHeight; i < endHeight; i++)
1537    {
1538      pImgYVar = m_imgY_var[i>>shiftHeight] + (startWidth>>shiftWidth);
1539      pImgYPad = imgYRec + i*stride;
1540      {
1541        pImgYPad1 = imgYRec + (i+1)*stride;
1542        pImgYPad2 = imgYRec + (i-1)*stride;
1543        pImgYPad3 = imgYRec + (i+2)*stride;
1544        pImgYPad4 = imgYRec + (i-2)*stride;
1545        pImgYPad5 = imgYRec + (i+3)*stride;
1546        pImgYPad6 = imgYRec + (i-3)*stride;
1547      }
1548
1549      for (j = startWidth; j < endWidth; j++)
1550      {
1551        if (j%varStepSizeWidth==0) coef = m_filterCoeffPrevSelected[*(pImgYVar++)];
1552        pixelInt=coef[lastCoef];
1553
1554#if !TI_ALF_MAX_VSIZE_7
1555        pixelInt += coef[4]* (imgYRec[(i+4)*stride + j]+imgYRec[(i-4)*stride + j]);
1556#endif       
1557        pixelInt += coef[12]* (pImgYPad5[j+1]+pImgYPad6[j-1]);
1558        pixelInt += coef[13]* (pImgYPad5[j]+pImgYPad6[j]);
1559        pixelInt += coef[14]* (pImgYPad5[j-1]+pImgYPad6[j+1]);
1560
1561        pixelInt += coef[20]* (pImgYPad3[j+2]+pImgYPad4[j-2]);
1562        pixelInt += coef[21]* (pImgYPad3[j+1]+pImgYPad4[j-1]);
1563        pixelInt += coef[22]* (pImgYPad3[j]+pImgYPad4[j]);
1564        pixelInt += coef[23]* (pImgYPad3[j-1]+pImgYPad4[j+1]);
1565        pixelInt += coef[24]* (pImgYPad3[j-2]+pImgYPad4[j+2]);
1566
1567        pixelInt += coef[28]* (pImgYPad1[j+3]+pImgYPad2[j-3]);
1568        pixelInt += coef[29]* (pImgYPad1[j+2]+pImgYPad2[j-2]);
1569        pixelInt += coef[30]* (pImgYPad1[j+1]+pImgYPad2[j-1]);
1570        pixelInt += coef[31]* (pImgYPad1[j]+pImgYPad2[j]);
1571        pixelInt += coef[32]* (pImgYPad1[j-1]+pImgYPad2[j+1]);
1572        pixelInt += coef[33]* (pImgYPad1[j-2]+pImgYPad2[j+2]);
1573        pixelInt += coef[34]* (pImgYPad1[j-3]+pImgYPad2[j+3]);
1574
1575        pixelInt += coef[36]* (pImgYPad[j+4]+pImgYPad[j-4]);
1576        pixelInt += coef[37]* (pImgYPad[j+3]+pImgYPad[j-3]);
1577        pixelInt += coef[38]* (pImgYPad[j+2]+pImgYPad[j-2]);
1578        pixelInt += coef[39]* (pImgYPad[j+1]+pImgYPad[j-1]);
1579        pixelInt += coef[40]* (pImgYPad[j]);
1580
1581        pixelInt=(Int)((pixelInt+offset) >> (numBitsMinus1));
1582        imgYRecPost[i*stride + j]=max(0, min(pixelInt,maxVal));
1583      }
1584    }
1585    break;
1586  }
1587}
1588#else
1589
1590Void TComAdaptiveLoopFilter::filterFrame(imgpel *imgY_rec_post, imgpel *imgY_rec, int filtNo, int Stride)
1591{
1592  int i, j, ii, jj, pixelInt,m=0;
1593  imgpel *p_imgY_var,*p_imgY_pad;
1594  int max_val=g_uiIBDI_MAX;
1595  int fl=FILTER_LENGTH/2;
1596  int *pattern=m_pattern9x9Sym;
1597  int fl_temp;
1598  int last_coef= MAX_SQR_FILT_LENGTH-1;
1599  imgpel *im1,*im2;
1600  int *coef;
1601  int num_bits_minus_1= NUM_BITS-1;
1602  int offset = (1<<(NUM_BITS-2));
1603  int *pattern_fix=m_patternTab_filt[filtNo];
1604  fl_temp=m_flTab[filtNo];
1605#if TI_ALF_MAX_VSIZE_7
1606  Int fl_tempV = ALFFlHToFlV(fl_temp);
1607#endif
1608 
1609  // Filter
1610  for (i = fl; i < m_img_height+fl; i++)
1611  {
1612    p_imgY_var = m_imgY_var[i-fl];
1613    p_imgY_pad = imgY_rec + (i-fl)*Stride;
1614    for (j = fl; j < m_img_width+fl; j++)
1615    {
1616      coef = m_filterCoeffPrevSelected[*(p_imgY_var++)];
1617      pixelInt=coef[last_coef];
1618      pattern=pattern_fix;
1619
1620#if TI_ALF_MAX_VSIZE_7
1621      for (ii = -fl_tempV, m = fl_temp - fl_tempV; ii < 0; ii++, m++)
1622#else
1623      for (ii = -fl_temp, m = 0; ii < 0; ii++, m++)
1624#endif
1625      {
1626        im1= &(imgY_rec[(i-fl+ii)*Stride + j-fl-m]);
1627        im2= &(imgY_rec[(i-fl-ii)*Stride + j-fl+m]);
1628        for (jj=-m; jj<=m; jj++)
1629          pixelInt+=((*(im1++)+ *(im2--))*coef[*(pattern++)]);
1630      }
1631
1632      im1= &(p_imgY_pad[(j-fl)-fl_temp]);
1633      im2= &(p_imgY_pad[(j-fl)+fl_temp]);
1634      for (jj=0; jj<fl_temp; jj++)
1635        pixelInt+=((*(im1++)+ *(im2--))*coef[*(pattern++)]);
1636
1637      pixelInt+=(p_imgY_pad[j-fl]*coef[*(pattern++)]);
1638      pixelInt=(int)((pixelInt+offset) >> (num_bits_minus_1));
1639      imgY_rec_post[(i-fl)*Stride + j-fl]=max(0, min(pixelInt,max_val));
1640    }
1641  }
1642}
1643
1644Void TComAdaptiveLoopFilter::subfilterFrame(imgpel *imgY_rec_post, imgpel *imgY_rec, int filtNo, int start_height, int end_height, int start_width, int end_width, int Stride)
1645{
1646  int i, j, ii, jj, pixelInt,m=0;
1647  imgpel *p_imgY_var,*p_imgY_pad;
1648  int max_val=g_uiIBDI_MAX;
1649  int fl=FILTER_LENGTH/2;
1650  int *pattern=m_pattern9x9Sym;
1651  int fl_temp;
1652  int last_coef= MAX_SQR_FILT_LENGTH-1;
1653  imgpel *im1,*im2;
1654  int *coef;
1655  int num_bits_minus_1= NUM_BITS-1;
1656  int offset = (1<<(NUM_BITS-2));
1657  int *pattern_fix=m_patternTab_filt[filtNo];
1658  fl_temp=m_flTab[filtNo];
1659#if TI_ALF_MAX_VSIZE_7
1660  Int fl_tempV = ALFFlHToFlV(fl_temp);
1661#endif
1662 
1663  // Filter
1664  for (i = fl + start_height; i < end_height+fl; i++)
1665  {
1666    p_imgY_var = m_imgY_var[i-fl] + start_width;
1667    p_imgY_pad = imgY_rec + (i-fl)*Stride;
1668    for (j = fl + start_width; j < end_width+fl; j++)
1669    {
1670      coef = m_filterCoeffPrevSelected[*(p_imgY_var++)];
1671      pixelInt=coef[last_coef];
1672      pattern=pattern_fix;
1673
1674#if TI_ALF_MAX_VSIZE_7
1675      for (ii = -fl_tempV, m = fl_temp - fl_tempV; ii < 0; ii++, m++)
1676#else
1677      for (ii = -fl_temp, m = 0; ii < 0; ii++, m++)
1678#endif
1679      {
1680        im1= &(imgY_rec[(i-fl+ii)*Stride + j-fl-m]);
1681        im2= &(imgY_rec[(i-fl-ii)*Stride + j-fl+m]);
1682        for (jj=-m; jj<=m; jj++)
1683          pixelInt+=((*(im1++)+ *(im2--))*coef[*(pattern++)]);
1684      }
1685
1686      im1= &(p_imgY_pad[(j-fl)-fl_temp]);
1687      im2= &(p_imgY_pad[(j-fl)+fl_temp]);
1688      for (jj=0; jj<fl_temp; jj++)
1689        pixelInt+=((*(im1++)+ *(im2--))*coef[*(pattern++)]);
1690
1691      pixelInt+=(p_imgY_pad[j-fl]*coef[*(pattern++)]);
1692      pixelInt=(int)((pixelInt+offset) >> (num_bits_minus_1));
1693      imgY_rec_post[(i-fl)*Stride + j-fl]=max(0, min(pixelInt,max_val));
1694    }
1695  }
1696}
1697
1698#endif
1699
1700
1701Void TComAdaptiveLoopFilter::xCUAdaptive_qc(TComPic* pcPic, ALFParam* pcAlfParam, imgpel *imgY_rec_post, imgpel *imgY_rec, Int Stride)
1702{
1703  // for every CU, call CU-adaptive ALF process
1704  for( UInt uiCUAddr = 0; uiCUAddr < pcPic->getNumCUsInFrame() ; uiCUAddr++ )
1705  {
1706    TComDataCU* pcCU = pcPic->getCU( uiCUAddr );
1707    xSubCUAdaptive_qc(pcCU, pcAlfParam, imgY_rec_post, imgY_rec, 0, 0, Stride);
1708  }
1709}
1710
1711Void TComAdaptiveLoopFilter::xSubCUAdaptive_qc(TComDataCU* pcCU, ALFParam* pcAlfParam, imgpel *imgY_rec_post, imgpel *imgY_rec, UInt uiAbsPartIdx, UInt uiDepth, Int Stride)
1712{
1713  TComPic* pcPic = pcCU->getPic();
1714 
1715  Bool bBoundary = false;
1716  UInt uiLPelX   = pcCU->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiAbsPartIdx] ];
1717  UInt uiRPelX   = uiLPelX + (g_uiMaxCUWidth>>uiDepth)  - 1;
1718  UInt uiTPelY   = pcCU->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiAbsPartIdx] ];
1719  UInt uiBPelY   = uiTPelY + (g_uiMaxCUHeight>>uiDepth) - 1;
1720 
1721  // check picture boundary
1722  if ( ( uiRPelX >= pcCU->getSlice()->getSPS()->getWidth() ) || ( uiBPelY >= pcCU->getSlice()->getSPS()->getHeight() ) )
1723  {
1724    bBoundary = true;
1725  }
1726 
1727  // go to sub-CU?
1728  if ( ( ( uiDepth < pcCU->getDepth( uiAbsPartIdx ) ) && ( uiDepth < (g_uiMaxCUDepth-g_uiAddCUDepth) ) ) || bBoundary )
1729  {
1730    UInt uiQNumParts = ( pcPic->getNumPartInCU() >> (uiDepth<<1) )>>2;
1731    for ( UInt uiPartUnitIdx = 0; uiPartUnitIdx < 4; uiPartUnitIdx++, uiAbsPartIdx+=uiQNumParts )
1732    {
1733      uiLPelX   = pcCU->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiAbsPartIdx] ];
1734      uiTPelY   = pcCU->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiAbsPartIdx] ];
1735     
1736      if( ( uiLPelX < pcCU->getSlice()->getSPS()->getWidth() ) && ( uiTPelY < pcCU->getSlice()->getSPS()->getHeight() ) )
1737        xSubCUAdaptive_qc(pcCU, pcAlfParam, imgY_rec_post, imgY_rec, uiAbsPartIdx, uiDepth+1, Stride);
1738    }
1739    return;
1740  }
1741 
1742  // check maskImagedec
1743  if ( pcCU->getAlfCtrlFlag(uiAbsPartIdx) )
1744  {
1745    subfilterFrame(imgY_rec_post, imgY_rec, pcAlfParam->realfiltNo, uiTPelY, min(uiBPelY+1,(unsigned int)(m_img_height)), uiLPelX, min(uiRPelX+1,(unsigned int)(m_img_width)), Stride);
1746  }
1747}
1748
1749// --------------------------------------------------------------------------------------------------------------------
1750// ALF for chroma
1751// --------------------------------------------------------------------------------------------------------------------
1752
1753Void TComAdaptiveLoopFilter::xALFChroma(ALFParam* pcAlfParam, TComPicYuv* pcPicDec, TComPicYuv* pcPicRest)
1754{
1755  if((pcAlfParam->chroma_idc>>1)&0x01)
1756  {
1757#if MTK_NONCROSS_INLOOP_FILTER
1758    if(!m_bUseNonCrossALF)
1759      xFrameChroma(0, 0, (m_img_height>>1), (m_img_width>>1), pcPicDec, pcPicRest, pcAlfParam->coeff_chroma, pcAlfParam->tap_chroma, 0);
1760    else
1761    {
1762      Int iStride   = pcPicRest->getCStride();
1763      Pel* pDec     = pcPicDec->getCbAddr();
1764      Pel* pRest    = pcPicRest->getCbAddr();
1765
1766      for(UInt s=0; s< m_uiNumSlicesInPic; s++)
1767      {
1768        CAlfSlice* pSlice = &(m_pSlice[s]);
1769        pSlice->copySliceChroma(pDec, pRest, iStride);
1770        pSlice->extendSliceBorderChroma(pDec, iStride, (UInt)EXTEND_NUM_PEL_C);
1771        xFrameChromaforOneSlice(pSlice, ALF_Cb, pcPicDec, pcPicRest, pcAlfParam->coeff_chroma, pcAlfParam->tap_chroma);
1772      }
1773    }
1774#else
1775    xFrameChroma(pcPicDec, pcPicRest, pcAlfParam->coeff_chroma, pcAlfParam->tap_chroma, 0);
1776#endif
1777  }
1778 
1779  if(pcAlfParam->chroma_idc&0x01)
1780  {
1781#if MTK_NONCROSS_INLOOP_FILTER
1782    if(!m_bUseNonCrossALF)
1783      xFrameChroma(0, 0, (m_img_height>>1), (m_img_width>>1), pcPicDec, pcPicRest, pcAlfParam->coeff_chroma, pcAlfParam->tap_chroma, 1);
1784    else
1785    {
1786      Int iStride   = pcPicRest->getCStride();
1787      Pel* pDec     = pcPicDec->getCrAddr();
1788      Pel* pRest    = pcPicRest->getCrAddr();
1789      for(UInt s=0; s< m_uiNumSlicesInPic; s++)
1790      {
1791        CAlfSlice* pSlice = &(m_pSlice[s]);
1792        pSlice->copySliceChroma(pDec, pRest, iStride);
1793        pSlice->extendSliceBorderChroma(pDec, iStride, (UInt)EXTEND_NUM_PEL_C);
1794        xFrameChromaforOneSlice(pSlice, ALF_Cr, pcPicDec, pcPicRest, pcAlfParam->coeff_chroma, pcAlfParam->tap_chroma);
1795      }
1796    }
1797#else
1798    xFrameChroma(pcPicDec, pcPicRest, pcAlfParam->coeff_chroma, pcAlfParam->tap_chroma, 1);
1799#endif
1800  }
1801}
1802
1803/**
1804 \param pcPicDec    picture before ALF
1805 \param pcPicRest   picture after  ALF
1806 \param qh          filter coefficient
1807 \param iTap        filter tap
1808 \param iColor      0 for Cb and 1 for Cr
1809 */
1810#if MTK_NONCROSS_INLOOP_FILTER
1811Void TComAdaptiveLoopFilter::xFrameChroma(Int ypos, Int xpos, Int iHeight, Int iWidth, TComPicYuv* pcPicDec, TComPicYuv* pcPicRest, Int *qh, Int iTap, Int iColor )
1812#else
1813Void TComAdaptiveLoopFilter::xFrameChroma( TComPicYuv* pcPicDec, TComPicYuv* pcPicRest, Int *qh, Int iTap, Int iColor )
1814#endif
1815{
1816  Int i, x, y, value, N, offset;
1817  //  Pel PixSum[ALF_MAX_NUM_COEF_C];// th
1818  Pel PixSum[ALF_MAX_NUM_COEF]; 
1819 
1820  N      = (iTap*iTap+1)>>1;
1821  offset = iTap>>1;
1822#if !MTK_NONCROSS_INLOOP_FILTER
1823  Int iHeight = pcPicRest->getHeight() >> 1;
1824  Int iWidth = pcPicRest->getWidth() >> 1;
1825#endif 
1826  Pel* pDec;
1827  Int iDecStride = pcPicDec->getCStride();
1828 
1829  Pel* pRest;
1830  Int iRestStride = pcPicRest->getCStride();
1831 
1832  Int iShift = g_uiBitDepth + g_uiBitIncrement - 8;
1833 
1834  if (iColor)
1835  {
1836    pDec = pcPicDec->getCrAddr();
1837    pRest = pcPicRest->getCrAddr();
1838  }
1839  else
1840  {
1841    pDec = pcPicDec->getCbAddr();
1842    pRest = pcPicRest->getCbAddr();
1843  }
1844#if MTK_NONCROSS_INLOOP_FILTER
1845  if(m_bUseNonCrossALF)
1846  {
1847    pDec  += ( ypos*iDecStride  + xpos);
1848    pRest += ( ypos*iRestStride + xpos);
1849  }
1850  else
1851  {
1852    assert(ypos ==0 && xpos ==0);
1853    assert(iHeight == pcPicRest->getHeight() >> 1);
1854    assert(iWidth  == pcPicRest->getWidth()  >> 1);
1855  }
1856#endif
1857
1858  Pel* pTmpDec1, *pTmpDec2;
1859  Pel* pTmpPixSum;
1860 
1861  switch(iTap)
1862  {
1863    case 5:
1864    {
1865      Int iJump = iDecStride - 4;
1866      pDec -= iDecStride*2;
1867      for (y = 0; y < iHeight; y++)
1868      {
1869        for (x = 0; x < iWidth; x++)
1870        {
1871          pTmpDec1 = pDec+x-2;
1872          pTmpDec2 = pTmpDec1+4+(4*iDecStride);
1873          pTmpPixSum = PixSum;
1874         
1875          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
1876          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
1877          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
1878          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
1879          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
1880          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
1881          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
1882          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
1883          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
1884          pTmpPixSum++; pTmpDec1 += iJump; pTmpDec2 -= iJump;
1885         
1886          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
1887          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
1888          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
1889          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
1890          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
1891          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
1892          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
1893          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
1894          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
1895          pTmpPixSum++; pTmpDec1 += iJump; pTmpDec2 -= iJump;
1896         
1897          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
1898          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
1899          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
1900          pTmpPixSum++; pTmpDec1++;
1901          *pTmpPixSum = (*pTmpDec1);
1902         
1903          value = 0;
1904          for(i=0; i<N; i++)
1905          {
1906            value += qh[i]*PixSum[i];
1907          }
1908          // DC offset
1909          value += qh[N] << iShift;
1910          value = (value + ALF_ROUND_OFFSET)>>ALF_NUM_BIT_SHIFT;
1911         
1912          pRest[x] = (Pel) Clip(value);
1913        }
1914        pRest += iRestStride;
1915        pDec += iDecStride;
1916      }
1917    }
1918      break;
1919    case 7:
1920    {
1921      Int iJump = iDecStride - 6;
1922      pDec -= iDecStride*3;
1923      for (y = 0; y < iHeight; y++)
1924      {
1925        for (x = 0; x < iWidth; x++)
1926        {
1927          pTmpDec1 = pDec+x-3;
1928          pTmpDec2 = pTmpDec1+6+(6*iDecStride);
1929          pTmpPixSum = PixSum;
1930         
1931          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
1932          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
1933          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
1934          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
1935          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
1936          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
1937          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
1938          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
1939          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
1940          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
1941          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
1942          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
1943          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
1944          pTmpPixSum++; pTmpDec1 += iJump; pTmpDec2 -= iJump;
1945         
1946          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
1947          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
1948          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
1949          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
1950          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
1951          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
1952          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
1953          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
1954          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
1955          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
1956          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
1957          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
1958          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
1959          pTmpPixSum++; pTmpDec1 += iJump; pTmpDec2 -= iJump;
1960         
1961          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
1962          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
1963          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
1964          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
1965          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
1966          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
1967          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
1968          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
1969          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
1970          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
1971          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
1972          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
1973          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
1974          pTmpPixSum++; pTmpDec1 += iJump; pTmpDec2 -= iJump;
1975         
1976          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
1977          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
1978          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
1979          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
1980          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
1981          pTmpPixSum++; pTmpDec1++;
1982          *pTmpPixSum = (*pTmpDec1);
1983         
1984          value = 0;
1985          for(i=0; i<N; i++)
1986          {
1987            value += qh[i]*PixSum[i];
1988          }
1989          // DC offset
1990          value += qh[N] << iShift;
1991          value = (value + ALF_ROUND_OFFSET)>>ALF_NUM_BIT_SHIFT;
1992         
1993          pRest[x] = (Pel) Clip(value);
1994        }
1995        pRest += iRestStride;
1996        pDec += iDecStride;
1997      }
1998    }
1999      break;
2000    case 9:
2001    {
2002      Int iJump = iDecStride - 8;
2003      pDec -= iDecStride*4;
2004      for (y = 0; y < iHeight; y++)
2005      {
2006        for (x = 0; x < iWidth; x++)
2007        {
2008          pTmpDec1 = pDec+x-4;
2009          pTmpDec2 = pTmpDec1+8+(8*iDecStride);
2010          pTmpPixSum = PixSum;
2011         
2012          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
2013          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
2014          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
2015          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
2016          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
2017          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
2018          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
2019          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
2020          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
2021          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
2022          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
2023          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
2024          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
2025          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
2026          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
2027          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
2028          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
2029          pTmpPixSum++; pTmpDec1 += iJump; pTmpDec2 -= iJump;
2030         
2031          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
2032          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
2033          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
2034          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
2035          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
2036          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
2037          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
2038          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
2039          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
2040          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
2041          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
2042          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
2043          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
2044          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
2045          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
2046          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
2047          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
2048          pTmpPixSum++; pTmpDec1 += iJump; pTmpDec2 -= iJump;
2049         
2050          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
2051          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
2052          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
2053          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
2054          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
2055          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
2056          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
2057          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
2058          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
2059          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
2060          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
2061          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
2062          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
2063          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
2064          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
2065          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
2066          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
2067          pTmpPixSum++; pTmpDec1 += iJump; pTmpDec2 -= iJump;
2068         
2069          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
2070          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
2071          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
2072          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
2073          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
2074          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
2075          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
2076          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
2077          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
2078          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
2079          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
2080          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
2081          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
2082          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
2083          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
2084          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
2085          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
2086          pTmpPixSum++; pTmpDec1 += iJump; pTmpDec2 -= iJump;
2087         
2088         
2089          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
2090          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
2091          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
2092          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
2093          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
2094          pTmpPixSum++; pTmpDec1++; pTmpDec2--;
2095          *pTmpPixSum = ((*pTmpDec1) + (*pTmpDec2));
2096          pTmpPixSum++; pTmpDec1++;
2097          *pTmpPixSum =(*pTmpDec1);
2098         
2099          value = 0;
2100          for(i=0; i<N; i++)
2101          {
2102            value += qh[i]*PixSum[i];
2103          }
2104          // DC offset
2105          value += qh[N] << iShift;
2106          value = (value + ALF_ROUND_OFFSET)>>ALF_NUM_BIT_SHIFT;
2107         
2108          pRest[x] = (Pel) Clip(value);
2109        }
2110        pRest += iRestStride;
2111        pDec += iDecStride;
2112      }
2113    }
2114      break;
2115    default:
2116      assert(0);
2117      break;
2118  }
2119}
2120
2121#if TSB_ALF_HEADER
2122Void TComAdaptiveLoopFilter::setNumCUsInFrame(TComPic *pcPic)
2123{
2124  m_uiNumCUsInFrame = pcPic->getNumCUsInFrame();
2125}
2126
2127Void TComAdaptiveLoopFilter::setAlfCtrlFlags(ALFParam *pAlfParam, TComDataCU *pcCU, UInt uiAbsPartIdx, UInt uiDepth, UInt &idx)
2128{
2129  TComPic* pcPic = pcCU->getPic();
2130  UInt uiCurNumParts    = pcPic->getNumPartInCU() >> (uiDepth<<1);
2131  UInt uiQNumParts      = uiCurNumParts>>2;
2132 
2133  Bool bBoundary = false;
2134  UInt uiLPelX   = pcCU->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiAbsPartIdx] ];
2135  UInt uiRPelX   = uiLPelX + (g_uiMaxCUWidth>>uiDepth)  - 1;
2136  UInt uiTPelY   = pcCU->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiAbsPartIdx] ];
2137  UInt uiBPelY   = uiTPelY + (g_uiMaxCUHeight>>uiDepth) - 1;
2138 
2139  if( ( uiRPelX >= pcCU->getSlice()->getSPS()->getWidth() ) || ( uiBPelY >= pcCU->getSlice()->getSPS()->getHeight() ) )
2140  {
2141    bBoundary = true;
2142  }
2143 
2144  if( ( ( uiDepth < pcCU->getDepth( uiAbsPartIdx ) ) && ( uiDepth < g_uiMaxCUDepth - g_uiAddCUDepth ) ) || bBoundary )
2145  {
2146    UInt uiIdx = uiAbsPartIdx;
2147    for ( UInt uiPartUnitIdx = 0; uiPartUnitIdx < 4; uiPartUnitIdx++ )
2148    {
2149      uiLPelX   = pcCU->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiIdx] ];
2150      uiTPelY   = pcCU->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiIdx] ];
2151     
2152      if( ( uiLPelX < pcCU->getSlice()->getSPS()->getWidth() ) && ( uiTPelY < pcCU->getSlice()->getSPS()->getHeight() ) )
2153      {
2154        setAlfCtrlFlags(pAlfParam, pcCU, uiIdx, uiDepth+1, idx);
2155      }
2156      uiIdx += uiQNumParts;
2157    }
2158   
2159    return;
2160  }
2161 
2162  if( uiDepth <= pAlfParam->alf_max_depth || pcCU->isFirstAbsZorderIdxInDepth(uiAbsPartIdx, pAlfParam->alf_max_depth))
2163  {
2164    if (uiDepth > pAlfParam->alf_max_depth)
2165    {
2166      pcCU->setAlfCtrlFlagSubParts(pAlfParam->alf_cu_flag[idx], uiAbsPartIdx, pAlfParam->alf_max_depth);
2167    }
2168    else
2169    {
2170      pcCU->setAlfCtrlFlagSubParts(pAlfParam->alf_cu_flag[idx], uiAbsPartIdx, uiDepth );
2171    }
2172    idx++;
2173  }
2174}
2175#endif
2176
2177#if MTK_NONCROSS_INLOOP_FILTER
2178
2179
2180Void TComAdaptiveLoopFilter::createSlice()
2181{
2182  m_pSlice = new CAlfSlice[m_uiNumSlicesInPic];
2183
2184  for(Int i=0; i< m_uiNumSlicesInPic; i++)
2185  {
2186    m_pSlice[i].init(m_uiNumLCUsInWidth, m_uiNumLCUsInHeight);
2187  }
2188
2189}
2190Void TComAdaptiveLoopFilter::destroySlice()
2191{
2192  delete[] m_pSlice;
2193}
2194
2195
2196
2197Void TComAdaptiveLoopFilter::setAlfCtrlFlagsforSlices(ALFParam *pcAlfParam, UInt &idx)
2198{
2199
2200  for(UInt s=0; s< m_uiNumSlicesInPic; s++)
2201  {
2202    CAlfSlice* pSlice = &(m_pSlice[s]);
2203    setAlfCtrlFlagsforOneSlice(pSlice, pcAlfParam, idx);
2204  }
2205}
2206
2207Void TComAdaptiveLoopFilter::setAlfCtrlFlagsforOneSlice(CAlfSlice* pSlice, ALFParam *pcAlfParam, UInt &idx)
2208{
2209
2210  for(Int i=0; i< pSlice->getNumLCUs(); i++)
2211  { 
2212    CAlfCU*     pAlfCU = &((*pSlice)[i]);
2213    TComDataCU* pcCU = pAlfCU->getCU();
2214
2215    setAlfCtrlFlags(pcAlfParam, pcCU, 0, 0, idx);
2216  }
2217
2218}
2219
2220
2221
2222
2223Void TComAdaptiveLoopFilter::calcVarforOneSlice(CAlfSlice* pSlice, imgpel **imgY_var, imgpel *imgY_pad, Int pad_size, Int fl, Int img_stride)
2224{ 
2225  Int iHeight, iWidth;
2226#if !MQT_BA_RA
2227  Int iPelPosOffset;
2228#endif
2229  Int ypos, xpos;
2230
2231  for(Int i=0; i< pSlice->getNumLCUs(); i++)
2232  { 
2233    CAlfCU* pAlfCU = &((*pSlice)[i]);
2234
2235    ypos    = pAlfCU->getCU()->getCUPelY();
2236    xpos    = pAlfCU->getCU()->getCUPelX();
2237    iHeight = pAlfCU->getHeight();
2238    iWidth  = pAlfCU->getWidth();
2239
2240#if MQT_BA_RA
2241    calcVar(ypos, xpos, imgY_var, imgY_pad, pad_size, fl, iHeight, iWidth, img_stride);
2242#else
2243    iPelPosOffset = (ypos * img_stride) + xpos;
2244
2245    calcVar(ypos, xpos, imgY_var, imgY_pad+ iPelPosOffset, pad_size, fl, iHeight, iWidth, img_stride);
2246#endif
2247  }
2248}
2249
2250
2251Void TComAdaptiveLoopFilter::xFrameChromaforOneSlice(CAlfSlice* pSlice, Int ComponentID, TComPicYuv* pcPicDec, TComPicYuv* pcPicRest, Int *qh, Int iTap)
2252{
2253  Int iColor = (ComponentID == ALF_Cb)?(0):(1);
2254
2255  Int iHeight, iWidth;
2256  Int ypos, xpos;
2257
2258  for(Int i=0; i< pSlice->getNumLCUs(); i++)
2259  { 
2260    CAlfCU* pAlfCU = &((*pSlice)[i]);
2261
2262    ypos    = (pAlfCU->getCU()->getCUPelY() >> 1);
2263    xpos    = (pAlfCU->getCU()->getCUPelX() >> 1);
2264    iHeight = (pAlfCU->getHeight() >> 1);
2265    iWidth  = (pAlfCU->getWidth() >> 1);
2266
2267    xFrameChroma(ypos, xpos, iHeight, iWidth, pcPicDec, pcPicRest, qh, iTap, iColor );
2268  }
2269
2270}
2271
2272
2273//-------------- CAlfCU ---------------------//
2274Void CAlfCU::init(TComPic* pcPic, UInt uiCUAddr, UInt uiStartCU, UInt uiEndCU, UInt uiNumCUWidth, UInt uiNumCUHeight)
2275{
2276  m_uiCUAddr = uiCUAddr;
2277  m_pcCU = pcPic->getCU(m_uiCUAddr);
2278
2279  UInt uiPicWidth = m_pcCU->getSlice()->getSPS()->getWidth();
2280  UInt uiPicHeight= m_pcCU->getSlice()->getSPS()->getHeight();
2281  UInt uiLPelX    = m_pcCU->getCUPelX();
2282  UInt uiTPelY    = m_pcCU->getCUPelY();
2283  UInt uiRPelX    = uiLPelX + g_uiMaxCUWidth  - 1;
2284  UInt uiBPelY    = uiTPelY + g_uiMaxCUHeight - 1;
2285
2286  m_uiWidth      = (uiRPelX >= uiPicWidth)? (uiPicWidth - uiLPelX):(uiRPelX - uiLPelX +1);
2287  m_uiHeight     = (uiBPelY >= uiPicHeight)?(uiPicHeight- uiTPelY):(uiBPelY - uiTPelY +1);
2288
2289  //check CU border status
2290  assignBorderStatus(uiStartCU, uiEndCU, uiNumCUWidth, uiNumCUHeight);
2291
2292}
2293
2294
2295Void CAlfCU::assignBorderStatus(UInt uiStartCU, UInt uiEndCU, UInt uiNumCUWidth, UInt uiNumCUHeight)
2296{
2297
2298  memset(m_aiCUBorderFlag, 0, NUM_PADDING_REGION*sizeof(Int));
2299
2300  for(UInt pos = 0; pos < NUM_PADDING_REGION; pos++)
2301  {
2302    Int& riVal = m_aiCUBorderFlag[pos];
2303
2304    switch(pos)
2305    {
2306    case PRP_L:
2307      {
2308        riVal = (m_uiCUAddr % uiNumCUWidth ==0)?(true):
2309          (
2310          (m_uiCUAddr-1 < uiStartCU)?(true):(false)
2311          );
2312      }
2313      break;
2314    case PRP_R:
2315      {
2316        riVal = ( (m_uiCUAddr+1) % uiNumCUWidth  == 0)?(true):
2317          (
2318          (m_uiCUAddr+1 > uiEndCU)?(true):(false)
2319          );
2320      }
2321      break;
2322    case PRP_T:
2323      {
2324        riVal = ( m_uiCUAddr< uiNumCUWidth )?(true):
2325          (
2326          ( m_uiCUAddr - uiNumCUWidth < uiStartCU)?(true):(false)
2327          );
2328      }
2329      break;
2330    case PRP_B:
2331      {
2332        riVal = ( m_uiCUAddr >= (uiNumCUWidth* (uiNumCUHeight-1)) )?(true):
2333          (
2334          ( m_uiCUAddr + uiNumCUWidth > uiEndCU)?(true):(false)
2335          );
2336      }
2337      break;
2338    case PRP_LT:
2339      riVal = ( m_aiCUBorderFlag[PRP_L]==1 && m_aiCUBorderFlag[PRP_T]==1 )?(1):(0);
2340      break;
2341    case PRP_RT:
2342      riVal = ( m_aiCUBorderFlag[PRP_R]==1 && m_aiCUBorderFlag[PRP_T]==1 )?(1):(0);
2343      if(riVal)
2344      {
2345        if( !( (m_uiCUAddr+1) % uiNumCUWidth  == 0) && !( m_uiCUAddr< uiNumCUWidth )) 
2346        {
2347          Int iAddr = (Int)m_uiCUAddr - (Int)uiNumCUWidth +1;
2348          if( iAddr >= (Int)uiStartCU && iAddr <= (Int)uiEndCU)
2349            riVal = 0;
2350        }
2351
2352      }
2353      break;
2354    case PRP_LB:
2355      riVal = ( m_aiCUBorderFlag[PRP_L]==1 && m_aiCUBorderFlag[PRP_B]==1 )?(1):(0);
2356      if(riVal)
2357      {
2358        if( !(m_uiCUAddr % uiNumCUWidth ==0)  && !( m_uiCUAddr >= (uiNumCUWidth* (uiNumCUHeight-1)) )) 
2359        {
2360          Int iAddr = (Int)m_uiCUAddr + (Int)uiNumCUWidth -1;
2361          if( iAddr >= (Int)uiStartCU && iAddr <= (Int)uiEndCU)
2362            riVal = 0;
2363
2364        }
2365      }
2366
2367      break;
2368    case PRP_RB:
2369      riVal = ( m_aiCUBorderFlag[PRP_R]==1 && m_aiCUBorderFlag[PRP_B]==1 )?(1):(0);
2370      break;
2371    default:
2372      assert(0);
2373      exit(-1);
2374    }
2375
2376
2377  }
2378
2379}
2380
2381
2382Void CAlfCU::extendCUBorder(Pel* pCUPel, UInt uiCUWidth, UInt uiCUHeight, Int iStride, UInt uiExtSize)
2383{
2384  Int* piExtFlag  = m_aiCUBorderFlag;
2385
2386  Pel* pPelDst;
2387  Pel* pPelSrc;
2388  UInt i, j, pos;
2389
2390
2391  for(pos =0; pos < NUM_PADDING_REGION; pos++)
2392  {
2393    if(piExtFlag[pos] ==0)
2394      continue;
2395
2396    switch(pos)
2397    {
2398    case PRP_L:
2399      {
2400        pPelDst = pCUPel - uiExtSize;
2401        pPelSrc = pCUPel;
2402
2403        for(j=0; j< uiCUHeight; j++)
2404        {
2405          for(i=0; i< uiExtSize; i++)
2406            pPelDst[i] = *pPelSrc;
2407
2408          pPelDst += iStride;
2409          pPelSrc += iStride;
2410
2411        }
2412
2413      }
2414      break;
2415    case PRP_R:
2416      {
2417        pPelDst = pCUPel + uiCUWidth;
2418        pPelSrc = pPelDst -1;
2419
2420
2421        for(j=0; j< uiCUHeight; j++)
2422        {
2423          for(i=0; i< uiExtSize; i++)
2424            pPelDst[i] = *pPelSrc;
2425
2426          pPelDst += iStride;
2427          pPelSrc += iStride;
2428        }
2429
2430      }
2431      break;
2432    case PRP_T:
2433      {
2434        pPelSrc = pCUPel;
2435        pPelDst = pCUPel - iStride;
2436
2437        for(j=0; j< uiExtSize; j++)
2438        {
2439          ::memcpy(pPelDst, pPelSrc, sizeof(Pel)*uiCUWidth);
2440          pPelDst -= iStride;
2441        }
2442
2443      }
2444      break;
2445    case PRP_B:
2446      {
2447        pPelDst = pCUPel + uiCUHeight*iStride;
2448        pPelSrc = pPelDst - iStride;
2449
2450        for(j=0; j< uiExtSize; j++)
2451        {
2452          ::memcpy(pPelDst, pPelSrc, sizeof(Pel)*uiCUWidth);
2453          pPelDst += iStride;
2454        }
2455
2456      }
2457      break;
2458    case PRP_LT:
2459      {
2460
2461        pPelSrc = pCUPel  - uiExtSize;
2462        pPelDst = pPelSrc - iStride;
2463
2464        for(j=0; j< uiExtSize; j++)
2465        {
2466          ::memcpy(pPelDst, pPelSrc, sizeof(Pel)*uiExtSize);
2467          pPelDst -= iStride;
2468        }
2469
2470      }
2471      break;
2472    case PRP_RT:
2473      {
2474        pPelSrc = pCUPel + uiCUWidth;
2475        pPelDst = pPelSrc - iStride;
2476
2477        for(j=0; j< uiExtSize; j++)
2478        {
2479          ::memcpy(pPelDst, pPelSrc, sizeof(Pel)*uiExtSize);
2480          pPelDst -= iStride;
2481        }
2482
2483      }
2484      break;
2485    case PRP_LB:
2486      {
2487        pPelDst = pCUPel + uiCUHeight*iStride; pPelDst-= uiExtSize;
2488        pPelSrc = pPelDst - iStride;
2489
2490        for(j=0; j< uiExtSize; j++)
2491        {
2492          ::memcpy(pPelDst, pPelSrc, sizeof(Pel)*uiExtSize);
2493          pPelDst += iStride;
2494        }
2495
2496      }
2497      break;
2498    case PRP_RB:
2499      {
2500        pPelDst = pCUPel + uiCUHeight*iStride; pPelDst += uiCUWidth;
2501        pPelSrc = pPelDst - iStride;
2502
2503        for(j=0; j< uiExtSize; j++)
2504        {
2505          ::memcpy(pPelDst, pPelSrc, sizeof(Pel)*uiExtSize);
2506          pPelDst += iStride;
2507        }
2508
2509      }
2510      break;
2511    default:
2512      {
2513        assert(0);
2514        exit(-1);
2515      }
2516
2517    }
2518  }
2519
2520
2521
2522}
2523
2524
2525//-------------- CAlfSlice -----------------//
2526
2527Void CAlfSlice::init(UInt uiNumLCUsInPicWidth, UInt uiNumLCUsInPicHeight)
2528{
2529  m_uiNumLCUsInPicWidth = uiNumLCUsInPicWidth;
2530  m_uiNumLCUsInPicHeight= uiNumLCUsInPicHeight;
2531}
2532Void CAlfSlice::create(TComPic* pcPic, Int iSliceID, UInt uiStartLCU, UInt uiEndLCU)
2533{
2534  m_iSliceID    = iSliceID;
2535  m_uiStartLCU  = uiStartLCU;
2536  m_uiEndLCU    = uiEndLCU;
2537
2538  m_uiNumLCUs= uiEndLCU - uiStartLCU +1;
2539
2540  m_pcAlfCU = new CAlfCU[m_uiNumLCUs];
2541
2542  for(UInt uiAddr= m_uiStartLCU; uiAddr <=  m_uiEndLCU; uiAddr++)
2543  {
2544    m_pcAlfCU[uiAddr - m_uiStartLCU].init(pcPic, uiAddr, m_uiStartLCU, m_uiEndLCU, m_uiNumLCUsInPicWidth, m_uiNumLCUsInPicHeight);
2545  }
2546
2547}
2548
2549Void CAlfSlice::destroy()
2550{
2551  if(m_pcAlfCU != NULL)
2552  {
2553    delete[] m_pcAlfCU;
2554    m_pcAlfCU = NULL;
2555  }
2556}
2557
2558
2559
2560Void CAlfSlice::extendSliceBorderLuma(Pel* pPelSrc, Int iStride, UInt uiExtSize)
2561{
2562  UInt idx; 
2563  Pel* pPelTmp;
2564  CAlfCU* pcAlfCU;
2565  UInt uiTPelY, uiLPelX;
2566  UInt uiWidth, uiHeight;
2567
2568
2569  for(idx = 0; idx < m_uiNumLCUs; idx++)
2570  {
2571    pcAlfCU = &(m_pcAlfCU[idx]);
2572
2573    uiTPelY = pcAlfCU->getCU()->getCUPelY();
2574    uiLPelX = pcAlfCU->getCU()->getCUPelX();
2575    uiWidth = pcAlfCU->getWidth();
2576    uiHeight= pcAlfCU->getHeight();
2577
2578    pPelTmp   = pPelSrc + (uiTPelY*iStride)+ uiLPelX;
2579
2580    pcAlfCU->extendCUBorder(pPelTmp, uiWidth, uiHeight, iStride, uiExtSize);
2581  }
2582}
2583
2584
2585Void CAlfSlice::extendSliceBorderChroma(Pel* pPelSrc, Int iStride, UInt uiExtSize)
2586{
2587  UInt idx; 
2588  Pel* pPelTmp;
2589  CAlfCU* pcAlfCU;
2590  UInt uiTPelY, uiLPelX;
2591  UInt uiWidth, uiHeight;
2592
2593
2594  for(idx = 0; idx < m_uiNumLCUs; idx++)
2595  {
2596    pcAlfCU = &(m_pcAlfCU[idx]);
2597
2598    uiTPelY = (pcAlfCU->getCU()->getCUPelY() >> 1);
2599    uiLPelX = (pcAlfCU->getCU()->getCUPelX() >> 1);
2600    uiWidth = (pcAlfCU->getWidth() >> 1);
2601    uiHeight= (pcAlfCU->getHeight() >> 1);
2602
2603    pPelTmp   = pPelSrc + (uiTPelY*iStride)+ uiLPelX;
2604
2605    pcAlfCU->extendCUBorder(pPelTmp, uiWidth, uiHeight, iStride, uiExtSize);
2606  }
2607}
2608
2609
2610
2611Void CAlfSlice::copySliceLuma(Pel* pPicDst, Pel* pPicSrc, Int iStride )
2612{
2613  UInt uiLPelX, uiTPelY;
2614  UInt uiPelOffset;
2615  Int  iWidth, iHeight;
2616  Pel* pPelDst;
2617  Pel* pPelSrc;
2618  CAlfCU* pcAlfCU;
2619
2620  for(UInt i=0; i< m_uiNumLCUs; i++)
2621  {
2622    pcAlfCU = &(m_pcAlfCU[i]);
2623
2624    uiLPelX = pcAlfCU->getCU()->getCUPelX();
2625    uiTPelY = pcAlfCU->getCU()->getCUPelY();
2626    iWidth  = (Int)pcAlfCU->getWidth();
2627    iHeight = (Int)pcAlfCU->getHeight();
2628
2629    uiPelOffset = uiTPelY* iStride + uiLPelX;
2630
2631    pPelDst = pPicDst + uiPelOffset;
2632    pPelSrc = pPicSrc + uiPelOffset;
2633
2634    for(Int j=0; j< iHeight; j++)
2635    {
2636      ::memcpy(pPelDst, pPelSrc, sizeof(Pel)*iWidth);
2637      pPelDst += iStride;
2638      pPelSrc += iStride;
2639    }
2640
2641
2642
2643  }
2644
2645}
2646
2647
2648Void CAlfSlice::copySliceChroma(Pel* pPicDst, Pel* pPicSrc, Int iStride )
2649{
2650  UInt uiLPelX, uiTPelY;
2651  UInt uiPelOffset;
2652  Int  iWidth, iHeight;
2653  Pel* pPelDst;
2654  Pel* pPelSrc;
2655  CAlfCU* pcAlfCU;
2656
2657  for(UInt i=0; i< m_uiNumLCUs; i++)
2658  {
2659    pcAlfCU = &(m_pcAlfCU[i]);
2660
2661    uiLPelX = (pcAlfCU->getCU()->getCUPelX())>>1;
2662    uiTPelY = (pcAlfCU->getCU()->getCUPelY())>>1;
2663    iWidth  = (Int)(pcAlfCU->getWidth()>>1 );
2664    iHeight = (Int)(pcAlfCU->getHeight()>>1);
2665
2666    uiPelOffset = uiTPelY* iStride + uiLPelX;
2667
2668    pPelDst = pPicDst + uiPelOffset;
2669    pPelSrc = pPicSrc + uiPelOffset;
2670
2671    for(Int j=0; j< iHeight; j++)
2672    {
2673      ::memcpy(pPelDst, pPelSrc, sizeof(Pel)*iWidth);
2674      pPelDst += iStride;
2675      pPelSrc += iStride;
2676    }
2677
2678
2679
2680  }
2681
2682}
2683
2684
2685
2686
2687Void TComAdaptiveLoopFilter::xFilterOneSlice(CAlfSlice* pSlice, imgpel* pDec, imgpel* pRest, Int iStride, ALFParam* pcAlfParam)
2688{
2689
2690
2691  //set maskImg using cu adaptive one.
2692  if(pcAlfParam->cu_control_flag)
2693  {
2694    UInt uiNumLCU = pSlice->getNumLCUs();
2695    for(UInt i=0; i< uiNumLCU; i++)
2696    {
2697      CAlfCU*     pAlfCU = &((*pSlice)[i]);
2698      TComDataCU* pcCU   = pAlfCU->getCU();
2699      xSubCUAdaptive_qc(pcCU, pcAlfParam, pRest, pDec, 0, 0, iStride);
2700    }
2701
2702  } 
2703  else
2704  {
2705    //then do whole frame filtering
2706    UInt uiNumLCU = pSlice->getNumLCUs();
2707    Int  iTPelY,  iLPelX;
2708    Int  iWidth, iHeight;
2709
2710
2711    for(UInt i=0; i< uiNumLCU; i++)
2712    {
2713      CAlfCU*     pAlfCU = &((*pSlice)[i]);
2714      TComDataCU* pcCU   = pAlfCU->getCU();
2715
2716      iTPelY = (Int)pcCU->getCUPelY();
2717      iLPelX = (Int)pcCU->getCUPelX();
2718      iHeight= pAlfCU->getHeight();
2719      iWidth = pAlfCU->getWidth();
2720
2721      subfilterFrame(pRest, pDec, pcAlfParam->realfiltNo, iTPelY, iTPelY+ iHeight, iLPelX, iLPelX+ iWidth, iStride);
2722
2723    }
2724
2725
2726
2727
2728  }
2729
2730
2731}
2732
2733#endif
2734
2735#if MTK_SAO
2736const Int TComSampleAdaptiveOffset::m_aiNumPartsInRow[5] =
2737{
2738  1,     //level 0
2739  2,     //level 1
2740  4,     //level 2
2741  8,     //level 3
2742  16     //level 4
2743};
2744
2745const Int TComSampleAdaptiveOffset::m_aiNumPartsLevel[5] =
2746{
2747  1,      //level 0
2748  4,      //level 1
2749  16,     //level 2
2750  64,     //level 3
2751  256     //level 4
2752};
2753
2754const Int TComSampleAdaptiveOffset::m_aiNumCulPartsLevel[5] =
2755{
2756  1,    //level 0
2757  5,    //level 1
2758  21,   //level 2
2759  85,   //level 3
2760  341,  //level 4
2761};
2762
2763const UInt TComSampleAdaptiveOffset::m_auiEoTable[9] =
2764{
2765  1, //0   
2766  2, //1   
2767  0, //2
2768  3, //3
2769  4, //4
2770  0, //5 
2771  0, //6 
2772  0, //7
2773  0
2774};
2775
2776const UInt TComSampleAdaptiveOffset::m_iWeightAO[MAX_NUM_SAO_TYPE] =
2777{
2778  2,
2779  2,
2780  2,
2781  2,
2782  1,
2783  1
2784};
2785
2786
2787const UInt TComSampleAdaptiveOffset::m_auiEoTable2D[9] =
2788{
2789  1, //0   
2790  2, //1   
2791  3, //2
2792  0, //3
2793  0, //4
2794  0, //5 
2795  4, //6 
2796  5, //7
2797  6
2798};
2799
2800Int TComSampleAdaptiveOffset::m_iNumClass[MAX_NUM_SAO_TYPE] =
2801{
2802  SAO_EO_LEN,
2803  SAO_EO_LEN,
2804  SAO_EO_LEN,
2805  SAO_EO_LEN,
2806  SAO_BO_LEN,
2807  SAO_BO_LEN
2808};
2809
2810UInt TComSampleAdaptiveOffset::m_uiMaxDepth = AO_MAX_DEPTH;
2811
2812/** Create SampleAdaptiveOffset memory.
2813 * \param uiSourceWidth, uiSourceHeight, uiMaxCUWidth, uiMaxCUHeight, uiMaxCUDepth
2814 */
2815Void TComSampleAdaptiveOffset::create( UInt uiSourceWidth, UInt uiSourceHeight, UInt uiMaxCUWidth, UInt uiMaxCUHeight, UInt uiMaxCUDepth)
2816{
2817
2818  m_iPicWidth   = uiSourceWidth;
2819  m_iPicHeight  = uiSourceHeight; 
2820
2821  m_uiMaxCUWidth   = uiMaxCUWidth;
2822  m_uiMaxCUHeight  = uiMaxCUHeight;
2823  //  m_uiMaxCUWidth   = 16;
2824  //  m_uiMaxCUHeight  = 16;
2825
2826  m_iNumCuInWidth   = m_iPicWidth / m_uiMaxCUWidth;
2827  m_iNumCuInWidth  += ( m_iPicWidth % m_uiMaxCUWidth ) ? 1 : 0;
2828
2829  m_iNumCuInHeight  = m_iPicHeight / m_uiMaxCUHeight;
2830  m_iNumCuInHeight += ( m_iPicHeight % m_uiMaxCUHeight ) ? 1 : 0;
2831
2832  xCreateQAOParts();
2833
2834
2835  UInt auiTable[2][LUMA_GROUP_NUM] = 
2836  {{0, 0, 0, 0, 0, 0, 0, 0,
2837  1, 2, 3, 4, 5, 6, 7, 8,
2838  9,10,11,12,13,14,15,16,
2839  0, 0, 0, 0, 0, 0, 0, 0},
2840
2841  {1, 2, 3, 4, 5, 6, 7, 8,
2842  0, 0, 0, 0, 0, 0, 0, 0,
2843  0, 0, 0, 0, 0, 0, 0, 0,
2844  9,10,11,12,13,14,15,16}};
2845
2846
2847  UInt uiInternalBitDepth = g_uiBitDepth+g_uiBitIncrement;
2848  UInt uiPixelRange = 1<<uiInternalBitDepth;
2849  UInt uiBoRangeShift = uiInternalBitDepth - MTK_QAO_BO_BITS;
2850
2851  m_ppLumaTableBo0 = new Pel [uiPixelRange];
2852  m_ppLumaTableBo1 = new Pel [uiPixelRange];
2853  for (Int k2=0; k2<uiPixelRange; k2++)
2854  {
2855    m_ppLumaTableBo0[k2] = auiTable[0][k2>>uiBoRangeShift];
2856    m_ppLumaTableBo1[k2] = auiTable[1][k2>>uiBoRangeShift];
2857  }
2858
2859
2860  m_iUpBuff1 = new Int[m_iPicWidth+2];
2861  m_iUpBuff2 = new Int[m_iPicWidth+2];
2862  m_iUpBufft = new Int[m_iPicWidth+2];
2863
2864  Pel i;
2865
2866
2867  UInt uiMaxY  = 255   << g_uiBitIncrement;
2868  UInt uiMinY  = 0   << g_uiBitIncrement;
2869
2870
2871  Int iCcTableRange = CRANGE >> (4-g_uiBitIncrement);
2872
2873  for(i=0;i<iCcTableRange;i++)
2874  {
2875    m_pClipTableBase[i+CRANGE_EXT] = i;
2876  }
2877
2878  for(i=0;i<uiMinY+CRANGE_EXT;i++)
2879  {
2880    m_pClipTableBase[i] = uiMinY;
2881  }
2882  for(i=uiMaxY+CRANGE_EXT;i<CRANGE_ALL;i++)
2883  {
2884    m_pClipTableBase[i] = uiMaxY;
2885  }
2886
2887  m_pClipTable = &(m_pClipTableBase[CRANGE_EXT]);
2888
2889
2890}
2891
2892
2893/** destroy SampleAdaptiveOffset memory.
2894 * \param
2895 */
2896Void TComSampleAdaptiveOffset::destroy()
2897{
2898
2899  if (m_ppLumaTableBo0)
2900  {
2901    delete[] m_ppLumaTableBo0; m_ppLumaTableBo0 = NULL;
2902  }
2903  if (m_ppLumaTableBo1)
2904  {
2905    delete[] m_ppLumaTableBo1; m_ppLumaTableBo1 = NULL;
2906  }
2907
2908  xDestroyQAOParts();
2909  if (m_iUpBuff1)
2910  {
2911    delete [] m_iUpBuff1; m_iUpBuff1 = NULL;
2912  }
2913  if (m_iUpBuff2)
2914  {
2915    delete [] m_iUpBuff2; m_iUpBuff2 = NULL;
2916  }
2917  if (m_iUpBufft)
2918  {
2919    delete [] m_iUpBufft; m_iUpBufft = NULL;
2920  }
2921
2922}
2923
2924
2925
2926/** Initialize SampleAdaptiveOffset data.
2927 * \param SAOParam
2928 */
2929Void TComSampleAdaptiveOffset::InitSao(SAOParam* pSaoParam)
2930{
2931  pSaoParam->psSaoPart      = m_psQAOPart;
2932  pSaoParam->iMaxSplitLevel = m_uiMaxSplitLevel;
2933
2934  resetQTPart();
2935
2936
2937}
2938
2939/** Create QAO Parts.
2940 * \param
2941 */
2942Void TComSampleAdaptiveOffset::xCreateQAOParts()
2943{
2944  Int iMaxSplitLevelHeight    = (Int)(logf((float)m_iNumCuInHeight)/logf(2.0));
2945  Int iMaxSplitLevelWidth     = (Int)(logf((float)m_iNumCuInWidth )/logf(2.0));
2946
2947  //find the max split level of IMQALF
2948  m_uiMaxSplitLevel= (iMaxSplitLevelHeight < iMaxSplitLevelWidth)?(iMaxSplitLevelHeight):(iMaxSplitLevelWidth);
2949  m_uiMaxSplitLevel= (m_uiMaxSplitLevel< m_uiMaxDepth)?(m_uiMaxSplitLevel):(m_uiMaxDepth);
2950
2951  m_psQAOPart= new SAOQTPart[ m_aiNumCulPartsLevel[m_uiMaxSplitLevel] ];
2952
2953  xInitALfOnePart(0, 0, 0, 
2954    -1, 
2955    0, m_iNumCuInWidth-1, 
2956    0, m_iNumCuInHeight-1);
2957
2958  //add subpart list
2959  Int i;
2960  Int NumSubPart;
2961  Int part_level;
2962  Int part_row;
2963  Int part_col;
2964  for(i=0; i< m_aiNumCulPartsLevel[m_uiMaxSplitLevel]; i++)
2965  {
2966    Idx2LevelRowCol(i, &part_level, &part_row, &part_col);
2967
2968    NumSubPart = m_aiNumPartsLevel[m_uiMaxSplitLevel - part_level];
2969
2970    m_psQAOPart[i].pSubPartList       = new Int[NumSubPart];
2971    m_psQAOPart[i].iLengthSubPartList = 0;
2972
2973    xMakeSubPartList(part_level, part_row, part_col, 
2974      m_psQAOPart[i].pSubPartList, 
2975      m_psQAOPart[i].iLengthSubPartList, 
2976      1);
2977
2978  }
2979  xSetQTPartCUInfo();
2980
2981  m_iNumTotalParts = m_aiNumCulPartsLevel[m_uiMaxSplitLevel];
2982
2983}
2984
2985/** Set QT Part CU Info.
2986 * \param
2987 */
2988Void TComSampleAdaptiveOffset::xSetQTPartCUInfo()
2989{
2990
2991  Int         i, j;
2992  SAOQTPart*  pAlfPart;
2993
2994
2995  for(i=0; i< m_aiNumCulPartsLevel[m_uiMaxSplitLevel]; i++)
2996  {
2997
2998    pAlfPart              = &(m_psQAOPart[i]);
2999    pAlfPart->bEnableFlag =  0;
3000    pAlfPart->iBestType   = -1;
3001    pAlfPart->iLength     =  0;
3002    for (j=0;j<MAX_NUM_QAO_CLASS;j++)
3003    {
3004      pAlfPart->iOffset[j] = 0;
3005    }
3006
3007    pAlfPart->part_xs = pAlfPart->StartCUX * (Int)(m_uiMaxCUWidth);
3008    pAlfPart->part_ys = pAlfPart->StartCUY * (Int)(m_uiMaxCUHeight);
3009
3010    //part_xe, part_ye
3011    pAlfPart->part_xe = pAlfPart->part_xs + 
3012      ( (Int)(m_uiMaxCUWidth) * (pAlfPart->EndCUX- pAlfPart->StartCUX + 1) ) -1;
3013    pAlfPart->part_ye = pAlfPart->part_ys + 
3014      ( (Int)(m_uiMaxCUHeight)* (pAlfPart->EndCUY- pAlfPart->StartCUY + 1)) -1;
3015
3016    if(pAlfPart->part_xe > m_iPicWidth-1)
3017      pAlfPart->part_xe = m_iPicWidth -1;
3018
3019    if(pAlfPart->part_ye > m_iPicHeight-1)
3020      pAlfPart->part_ye = m_iPicHeight-1;
3021
3022
3023    pAlfPart->part_width = pAlfPart->part_xe - pAlfPart->part_xs +1;
3024    pAlfPart->part_height= pAlfPart->part_ye - pAlfPart->part_ys +1;
3025
3026  }
3027
3028
3029
3030}
3031
3032/** Destroy QAO Parts.
3033 * \param
3034 */
3035Void TComSampleAdaptiveOffset::xDestroyQAOParts()
3036{
3037
3038  int i;
3039  for(i=0; i< m_aiNumCulPartsLevel[m_uiMaxSplitLevel]; i++)
3040  {
3041    //        freeALFParam( &(m_psAlfPart[i].sAlfParam) );
3042
3043    if (m_psQAOPart[i].pSubPartList)
3044    {
3045      delete[] m_psQAOPart[i].pSubPartList;    m_psQAOPart[i].pSubPartList = NULL;
3046
3047    }
3048
3049  }
3050
3051  if (m_psQAOPart)
3052  {
3053    delete[] m_psQAOPart; m_psQAOPart = NULL;
3054  }
3055}
3056
3057
3058/** Initialize ALf One Part.
3059 * \param iPartLevel, iPartRow, iPartCol, iParentPartIdx, StartCUX, EndCUX, StartCUY, EndCUX, StartCUY, EndCUY
3060 */
3061Void TComSampleAdaptiveOffset::xInitALfOnePart(Int iPartLevel, Int iPartRow, Int iPartCol, Int iParentPartIdx, Int StartCUX, Int EndCUX, Int StartCUY, Int EndCUY)
3062{
3063  Int             part_idx    = LevelRowCol2Idx(iPartLevel, iPartRow, iPartCol);
3064  SAOQTPart*      pAlfPart       = &(m_psQAOPart[part_idx]);
3065
3066  //    allocALFParam( &(pAlfPart->sAlfParam) );
3067
3068  pAlfPart->PartIdx   = part_idx;
3069  pAlfPart->PartLevel = iPartLevel;
3070  pAlfPart->PartRow   = iPartRow;
3071  pAlfPart->PartCol   = iPartCol;
3072
3073  pAlfPart->StartCUX  = StartCUX;
3074  pAlfPart->EndCUX    = EndCUX;
3075  pAlfPart->StartCUY  = StartCUY;
3076  pAlfPart->EndCUY    = EndCUY;
3077
3078  pAlfPart->UpPartIdx = iParentPartIdx;
3079
3080
3081  if(pAlfPart->PartLevel != m_uiMaxSplitLevel)
3082  {
3083    pAlfPart->bBottomLevel = false;
3084
3085    Int DownLevel   = iPartLevel+1;
3086    Int DownRowStart= (iPartRow << 1);
3087    Int DownColStart= (iPartCol << 1);
3088
3089    Int DownRow_Idx, DownCol_Idx;
3090    Int NumCUWidth, NumCUHeight;
3091    Int NumCULeft;
3092    Int NumCUTop;
3093
3094    Int DownStartCUX, DownStartCUY;
3095    Int DownEndCUX, DownEndCUY;
3096
3097    NumCUWidth = EndCUX - StartCUX +1;
3098    NumCUHeight= EndCUY - StartCUY +1;
3099
3100    NumCULeft=  (NumCUWidth >>  1);
3101    NumCUTop=   (NumCUHeight >> 1);
3102
3103    //part 00
3104    DownStartCUX=   StartCUX;
3105    DownEndCUX=     DownStartCUX + NumCULeft -1;
3106    DownStartCUY=   StartCUY;
3107    DownEndCUY=     DownStartCUY + NumCUTop -1;
3108
3109    DownRow_Idx= DownRowStart + 0;
3110    DownCol_Idx= DownColStart + 0;
3111
3112    pAlfPart->DownPartsIdx[0]= LevelRowCol2Idx(DownLevel, DownRow_Idx, DownCol_Idx);
3113
3114    xInitALfOnePart(DownLevel, DownRow_Idx, DownCol_Idx, 
3115      part_idx, 
3116      DownStartCUX, DownEndCUX, DownStartCUY, DownEndCUY);
3117
3118
3119    //part 01
3120    DownStartCUX=   StartCUX + NumCULeft;
3121    DownEndCUX=     EndCUX;
3122    DownStartCUY=   StartCUY;
3123    DownEndCUY=     DownStartCUY + NumCUTop -1;
3124
3125    DownRow_Idx= DownRowStart + 0;
3126    DownCol_Idx= DownColStart + 1;
3127
3128    pAlfPart->DownPartsIdx[1]= LevelRowCol2Idx(DownLevel, DownRow_Idx, DownCol_Idx);
3129
3130    xInitALfOnePart(DownLevel, DownRow_Idx, DownCol_Idx, 
3131      part_idx, 
3132      DownStartCUX, DownEndCUX, DownStartCUY, DownEndCUY);
3133
3134
3135
3136    //part 10
3137    DownStartCUX=   StartCUX;
3138    DownEndCUX=     DownStartCUX + NumCULeft -1;
3139    DownStartCUY=   StartCUY + NumCUTop;
3140    DownEndCUY=     EndCUY;
3141
3142    DownRow_Idx= DownRowStart + 1;
3143    DownCol_Idx= DownColStart + 0;
3144
3145    pAlfPart->DownPartsIdx[2]= LevelRowCol2Idx(DownLevel, DownRow_Idx, DownCol_Idx);
3146
3147    xInitALfOnePart(DownLevel, DownRow_Idx, DownCol_Idx, 
3148      part_idx, 
3149      DownStartCUX, DownEndCUX, DownStartCUY, DownEndCUY);
3150
3151
3152
3153    //part 11
3154    DownStartCUX=   StartCUX+ NumCULeft;
3155    DownEndCUX=     EndCUX;
3156    DownStartCUY=   StartCUY + NumCUTop;
3157    DownEndCUY=     EndCUY;
3158
3159    DownRow_Idx= DownRowStart + 1;
3160    DownCol_Idx= DownColStart + 1;
3161
3162    pAlfPart->DownPartsIdx[3]= LevelRowCol2Idx(DownLevel, DownRow_Idx, DownCol_Idx);
3163
3164    xInitALfOnePart(DownLevel, DownRow_Idx, DownCol_Idx, 
3165      part_idx, 
3166      DownStartCUX, DownEndCUX, DownStartCUY, DownEndCUY);
3167
3168
3169
3170  }
3171  else
3172  {
3173    pAlfPart->bBottomLevel = true;
3174    pAlfPart->DownPartsIdx[0]=pAlfPart->DownPartsIdx[1]= pAlfPart->DownPartsIdx[2]= pAlfPart->DownPartsIdx[3]= -1; 
3175  }
3176
3177}
3178
3179
3180/** Make Sub Part List.
3181 * \param  iPartLevel,  iPartRow,  iPartCol,  pList,  rListLength, NumPartInRow
3182 */
3183Void TComSampleAdaptiveOffset::xMakeSubPartList(Int iPartLevel, Int iPartRow, Int iPartCol, Int* pList, Int& rListLength, Int NumPartInRow)
3184{
3185
3186  if(iPartLevel != m_uiMaxSplitLevel)
3187  {
3188    xMakeSubPartList(iPartLevel+1, iPartRow*2, iPartCol*2, 
3189      pList, rListLength,
3190      NumPartInRow*2);
3191
3192  }
3193  else  //bottom level
3194  {
3195
3196    Int part_idx;
3197    Int i,j;
3198
3199    for(j= iPartRow; j< iPartRow + NumPartInRow; j++)
3200    {
3201      for(i= iPartCol; i< iPartCol + NumPartInRow; i++)
3202      {
3203        part_idx= LevelRowCol2Idx(iPartLevel, j, i);
3204        pList[rListLength]= part_idx;
3205        rListLength++;
3206      }
3207    }
3208
3209  }
3210
3211}
3212
3213
3214inline int xSign(int x)
3215{
3216  return ((x >> 31) | ((int)( (((unsigned int) -x)) >> 31)));
3217}
3218
3219/** Adaptive offset process for Cu
3220 * \param  iAddr, iPartIdx
3221 */
3222Void TComSampleAdaptiveOffset::AoProcessCu(Int iAddr, Int iPartIdx)
3223{
3224  Int x,y;
3225  TComDataCU *pTmpCu = m_pcPic->getCU(iAddr);
3226  Pel* pRec       = m_pcPic->getPicYuvRec()->getLumaAddr(iAddr);
3227  Int  iStride    = m_pcPic->getStride();
3228  Int  iLcuWidth  = m_uiMaxCUWidth;
3229  Int  iLcuHeight = m_uiMaxCUHeight;
3230  UInt uiLPelX    = pTmpCu->getCUPelX();
3231  UInt uiRPelX    = uiLPelX + iLcuWidth;
3232  UInt uiTPelY    = pTmpCu->getCUPelY();
3233  UInt uiBPelY    = uiTPelY + iLcuHeight;
3234  Int  iAoType    = m_psQAOPart[iPartIdx].iBestType;
3235  Int  iSignLeft;
3236  Int  iSignRight;
3237  Int  iSignDown;
3238  Int  iSignDown1;
3239  Int  iSignDown2;
3240  UInt uiEdgeType;
3241
3242  uiRPelX    = uiRPelX > m_iPicWidth ? m_iPicWidth : uiRPelX;
3243  uiBPelY    = uiBPelY > m_iPicHeight? m_iPicHeight: uiBPelY;
3244  iLcuWidth  = uiRPelX - uiLPelX;
3245  iLcuHeight = uiBPelY - uiTPelY;
3246
3247  switch (iAoType)
3248  {
3249  case SAO_EO_0:
3250    {
3251      for (y=0; y<iLcuHeight; y++)
3252      {
3253        iSignLeft  = xSign(pRec[1] - pRec[0]);
3254        for (x=1; x<iLcuWidth-1; x++)
3255        {
3256          iSignRight =  xSign(pRec[x] - pRec[x+1]); 
3257          uiEdgeType =  iSignRight + iSignLeft + 2;
3258          iSignLeft  = -iSignRight;
3259
3260          pRec[x] = m_pClipTable[pRec[x] + m_iOffsetEo[uiEdgeType]];
3261        }
3262        pRec += iStride;
3263      }
3264      break;
3265    }
3266  case SAO_EO_1:
3267    {
3268      pRec += iStride;
3269      for (x=0; x< iLcuWidth; x++)
3270      {
3271        m_iUpBuff1[x] = xSign(pRec[x] - pRec[x-iStride]);
3272      }
3273      for (y=1; y<iLcuHeight-1; y++)
3274      {
3275        for (x=0; x<iLcuWidth; x++)
3276        {
3277          iSignDown  =  xSign(pRec[x] - pRec[x+iStride]); 
3278          uiEdgeType =  iSignDown + m_iUpBuff1[x] + 2;
3279          m_iUpBuff1[x]= -iSignDown;
3280
3281          pRec[x] = m_pClipTable[pRec[x] + m_iOffsetEo[uiEdgeType]];
3282        }
3283        pRec += iStride;
3284      }
3285      break;
3286    }
3287  case SAO_EO_2:
3288    {
3289      pRec += iStride;
3290      for (x=1; x<iLcuWidth; x++)
3291      {
3292        m_iUpBuff1[x] = xSign(pRec[x] - pRec[x-iStride-1]);
3293      }
3294      for (y=1; y<iLcuHeight-1; y++)
3295      {
3296        iSignDown2 = xSign(pRec[iStride] - pRec[0]);
3297
3298        for (x=1; x<iLcuWidth-1; x++)
3299        {
3300          iSignDown1      =  xSign(pRec[x] - pRec[x+iStride+1]) ;
3301          uiEdgeType      =  iSignDown1 + m_iUpBuff1[x] + 2;
3302          m_iUpBufft[x+1] = -iSignDown1; 
3303          pRec[x] = m_pClipTable[pRec[x] + m_iOffsetEo[uiEdgeType]];
3304        }
3305        m_iUpBufft[1] = iSignDown2;
3306
3307        ipSwap     = m_iUpBuff1;
3308        m_iUpBuff1 = m_iUpBufft;
3309        m_iUpBufft = ipSwap;
3310
3311        pRec += iStride;
3312      }
3313      break;
3314    } 
3315  case SAO_EO_3:
3316    {
3317      pRec += iStride;
3318      for (x=0; x<iLcuWidth-1; x++)
3319      {
3320        m_iUpBuff1[x] = xSign(pRec[x] - pRec[x-iStride+1]);
3321      }
3322      for (y=1; y<iLcuHeight-1; y++)
3323      {
3324        for (x=1; x<iLcuWidth-1; x++)
3325        {
3326          iSignDown1      =  xSign(pRec[x] - pRec[x+iStride-1]) ;
3327          uiEdgeType      =  iSignDown1 + m_iUpBuff1[x] + 2;
3328          m_iUpBuff1[x-1]   = -iSignDown1; 
3329          pRec[x] = m_pClipTable[pRec[x] + m_iOffsetEo[uiEdgeType]];
3330        }
3331        m_iUpBuff1[iLcuWidth-2] = xSign(pRec[iLcuWidth-2 + iStride] - pRec[iLcuWidth-1]);
3332
3333        pRec += iStride;
3334      } 
3335      break;
3336    }   
3337  case SAO_BO_0:
3338  case SAO_BO_1:
3339    {
3340      for (y=0; y<iLcuHeight; y++)
3341      {
3342        for (x=0; x<iLcuWidth; x++)
3343        {
3344          pRec[x] = m_iOffsetBo[pRec[x]];
3345        }
3346        pRec += iStride;
3347      }
3348      break;
3349    }
3350  default: break;
3351
3352  }
3353}
3354
3355
3356/** run adaptive offset One Part
3357 * \param  uiPartIdx, pcPicYuvDst, pcPicYuvSrc
3358 */
3359Void TComSampleAdaptiveOffset::xAoOnePart(UInt uiPartIdx, TComPicYuv* pcPicYuvDst, TComPicYuv* pcPicYuvSrc)
3360{
3361  int  i;
3362  UInt uiEdgeType, uiTypeIdx;
3363  Pel* ppLumaTable = NULL;
3364
3365  static Int iOffset[LUMA_GROUP_NUM];
3366  Int LcuIdxX;
3367  Int LcuIdxY;
3368  Int iAddr;
3369  Int iFrameWidthInCU = m_pcPic->getFrameWidthInCU();
3370
3371  if(m_psQAOPart[uiPartIdx].bEnableFlag)
3372  {
3373    uiTypeIdx = m_psQAOPart[uiPartIdx].iBestType;
3374    if (uiTypeIdx == SAO_BO_0 || uiTypeIdx == SAO_BO_1)
3375    {
3376      for (i=0;i<m_psQAOPart[uiPartIdx].iLength;i++)
3377        iOffset[i+1] = m_psQAOPart[uiPartIdx].iOffset[i] << (g_uiBitIncrement-m_uiAoBitDepth);
3378
3379      if (uiTypeIdx == SAO_BO_0 )
3380      {
3381        ppLumaTable = m_ppLumaTableBo0;
3382      }
3383      if (uiTypeIdx == SAO_BO_1 )
3384      {
3385        ppLumaTable = m_ppLumaTableBo1;
3386      }
3387
3388      for (i=0;i<(1<<(g_uiBitIncrement+8));i++)
3389      {
3390        m_iOffsetBo[i] = m_pClipTable[i + iOffset[ppLumaTable[i]]];
3391      }
3392
3393    }
3394    if (uiTypeIdx == SAO_EO_0 || uiTypeIdx == SAO_EO_1 || uiTypeIdx == SAO_EO_2 || uiTypeIdx == SAO_EO_3)
3395    {
3396      for (i=0;i<m_psQAOPart[uiPartIdx].iLength;i++)
3397      {
3398        iOffset[i+1] = m_psQAOPart[uiPartIdx].iOffset[i] << (g_uiBitIncrement-m_uiAoBitDepth);
3399      }
3400      for (uiEdgeType=0;uiEdgeType<6;uiEdgeType++)
3401      {
3402        m_iOffsetEo[uiEdgeType]= iOffset[m_auiEoTable[uiEdgeType]];
3403      }
3404    }
3405    for (LcuIdxY = m_psQAOPart[uiPartIdx].StartCUY; LcuIdxY<= m_psQAOPart[uiPartIdx].EndCUY; LcuIdxY++)
3406    {
3407      for (LcuIdxX = m_psQAOPart[uiPartIdx].StartCUX; LcuIdxX<= m_psQAOPart[uiPartIdx].EndCUX; LcuIdxX++)
3408      {
3409        iAddr = LcuIdxY * iFrameWidthInCU + LcuIdxX;
3410        AoProcessCu(iAddr, uiPartIdx);
3411      }
3412    }
3413  }
3414}
3415
3416
3417/** Process QuadTree adaptive offset
3418 * \param  uiPartIdx, pcPicYuvRec, pcPicYuvExt
3419 */
3420Void TComSampleAdaptiveOffset::xProcessQuadTreeAo(UInt uiPartIdx, TComPicYuv* pcPicYuvRec, TComPicYuv* pcPicYuvExt)
3421{
3422
3423  SAOQTPart*  pQAOPart= &(m_psQAOPart[uiPartIdx]);
3424
3425  if (!pQAOPart->bSplit)
3426  {
3427    if (pQAOPart->bEnableFlag)
3428    {
3429      xAoOnePart(uiPartIdx, pcPicYuvRec, pcPicYuvExt);
3430    }
3431    else
3432    {
3433    }
3434    return;
3435  }
3436
3437  if (pQAOPart->PartLevel < m_uiMaxSplitLevel)
3438  {
3439    xProcessQuadTreeAo(pQAOPart->DownPartsIdx[0], pcPicYuvRec, pcPicYuvExt);
3440    xProcessQuadTreeAo(pQAOPart->DownPartsIdx[1], pcPicYuvRec, pcPicYuvExt);
3441    xProcessQuadTreeAo(pQAOPart->DownPartsIdx[2], pcPicYuvRec, pcPicYuvExt);
3442    xProcessQuadTreeAo(pQAOPart->DownPartsIdx[3], pcPicYuvRec, pcPicYuvExt);
3443  }
3444}
3445
3446
3447/** reset QT Part
3448 * \param 
3449 */
3450Void TComSampleAdaptiveOffset::resetQTPart()
3451{
3452  Int iPartIdx, i;
3453  for (iPartIdx=0; iPartIdx<m_iNumTotalParts; iPartIdx++)
3454  {
3455    m_psQAOPart[iPartIdx].bEnableFlag = 0;
3456    m_psQAOPart[iPartIdx].bSplit = 0;
3457    m_psQAOPart[iPartIdx].iBestType = -1;
3458    m_psQAOPart[iPartIdx].iLength = 0;
3459    for (i=0;i<MAX_NUM_QAO_CLASS;i++)
3460    {
3461      m_psQAOPart[iPartIdx].iOffset[i] = 0;
3462    }
3463  }
3464
3465}
3466
3467
3468/** copy Qao Data
3469 * \param SAOParam* pcQaoParam 
3470 */
3471Void TComSampleAdaptiveOffset::copyQaoData(SAOParam* pcQaoParam )
3472{
3473  pcQaoParam->bSaoFlag  = m_bSaoFlag;
3474  pcQaoParam->psSaoPart = m_psQAOPart;
3475  pcQaoParam->iMaxSplitLevel = (Int) m_uiMaxSplitLevel;
3476
3477  for(Int j=0;j<MAX_NUM_SAO_TYPE;j++)
3478  {
3479    pcQaoParam->iNumClass[j] = m_iNumClass[j];
3480  }
3481
3482}
3483/** Sample adaptive offset Process
3484 * \param pcPic, pcQaoParam 
3485 */
3486Void TComSampleAdaptiveOffset::SAOProcess(TComPic* pcPic, SAOParam* pcQaoParam)
3487{
3488
3489  if (pcQaoParam->bSaoFlag)
3490  {
3491    if (g_uiBitIncrement>1)
3492    {
3493      m_uiAoBitDepth = 1;
3494    }
3495    else
3496    {
3497      m_uiAoBitDepth = 0;
3498    }
3499    m_pcPic = pcPic;
3500    TComPicYuv* pcPicYuvRec = m_pcPic->getPicYuvRec();
3501    TComPicYuv* pcPicYuvExt = NULL;
3502
3503
3504    {
3505      xProcessQuadTreeAo( 0, pcPicYuvRec,  pcPicYuvExt);
3506    }
3507
3508    m_pcPic = NULL;
3509  }
3510
3511
3512
3513}
3514
3515
3516
3517
3518#endif // MTK_SAO
Note: See TracBrowser for help on using the repository browser.