source: 3DVCSoftware/tags/0.3/source/Lib/TLibCommon/TComAdaptiveLoopFilter.cpp @ 83

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

Clean version with cfg-files

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