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

Last change on this file since 56 was 56, checked in by hschwarz, 13 years ago

updated trunk (move to HM6.1)

  • Property svn:eol-style set to native
File size: 113.3 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-2012, ITU/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 ITU/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/** \file     TComAdaptiveLoopFilter.cpp
35    \brief    adaptive loop filter class
36*/
37
38#include "TComAdaptiveLoopFilter.h"
39#include <string.h>
40#include <stdlib.h>
41#include <stdio.h>
42#include <math.h>
43
44//! \ingroup TLibCommon
45//! \{
46
47
48#if !LCU_SYNTAX_ALF
49ALFParam::~ALFParam()
50{
51  if (coeff_chroma != NULL)
52  {
53    delete[] coeff_chroma;
54  }
55  if (coeffmulti)
56  {
57    for (Int i=0; i<NO_VAR_BINS; i++)
58    {
59      if (coeffmulti[i] != NULL)
60      {
61        delete[] coeffmulti[i];
62      }
63    }
64    delete[] coeffmulti;
65  }
66
67  if (nbSPred != NULL)
68  {
69    delete[] nbSPred;
70  }
71  if (filterPattern != NULL)
72  {
73    delete[] filterPattern;
74  }
75}
76#endif
77
78// ====================================================================================================================
79// Tables
80// ====================================================================================================================
81
82#if ALF_SINGLE_FILTER_SHAPE
83Int TComAdaptiveLoopFilter::weightsShape1Sym[ALF_MAX_NUM_COEF+1] = 
84{ 
85              2,
86              2,
87           2, 2, 2,
88  2, 2, 2, 2, 1, 
89              1
90};
91Int* TComAdaptiveLoopFilter::weightsTabShapes[NUM_ALF_FILTER_SHAPE] =
92{
93  weightsShape1Sym
94};
95Int TComAdaptiveLoopFilter::m_sqrFiltLengthTab[NUM_ALF_FILTER_SHAPE] =
96{
97  ALF_FILTER_LEN
98};
99Int depthIntShape1Sym[ALF_MAX_NUM_COEF+1] = 
100{
101              6,
102              7,
103           7, 8, 7,
104  5, 6, 7, 8, 9, 
105              9 
106};
107Int* pDepthIntTabShapes[NUM_ALF_FILTER_SHAPE] =
108{ 
109  depthIntShape1Sym
110};
111#else
112//Shape0: Star5x5
113Int TComAdaptiveLoopFilter::weightsShape0Sym[10] = 
114{
115  2,    2,    2,   
116  2, 2, 2,       
117  2, 2, 1, 1
118};
119
120
121//Shape1: Cross9x9
122Int TComAdaptiveLoopFilter::weightsShape1Sym[10] = 
123{ 
124              2,
125              2,
126              2,
127              2,
128  2, 2, 2, 2, 1, 
129              1
130};
131
132
133Int* TComAdaptiveLoopFilter::weightsTabShapes[NUM_ALF_FILTER_SHAPE] =
134{
135  weightsShape0Sym, weightsShape1Sym
136};
137
138Int TComAdaptiveLoopFilter::m_sqrFiltLengthTab[NUM_ALF_FILTER_SHAPE] =
139{
140  9, 9
141};
142
143// Shape0
144Int depthIntShape0Sym[10] = 
145{
146  1,    3,    1,
147  3, 4, 3, 
148  3, 4, 5, 5                 
149};
150// Shape1
151Int depthIntShape1Sym[10] = 
152{
153              5,
154              6,
155              7,
156              8,
157  5, 6, 7, 8, 9, 
158              9 
159};
160
161
162Int* pDepthIntTabShapes[NUM_ALF_FILTER_SHAPE] =
163{ 
164  depthIntShape0Sym, depthIntShape1Sym
165};
166#endif
167
168#if LCU_SYNTAX_ALF
169Int kTableShape1[ALF_MAX_NUM_COEF+1] = 
170{     
171              2,
172              3,
173           3, 4, 3,
174  1, 2, 3, 4, 1, 
175              3
176};
177Int* kTableTabShapes[NUM_ALF_FILTER_SHAPE] =
178{ 
179  kTableShape1
180};
181#endif
182
183// ====================================================================================================================
184// Constructor / destructor / create / destroy
185// ====================================================================================================================
186
187const AlfCUCtrlInfo& AlfCUCtrlInfo::operator= (const AlfCUCtrlInfo& src)
188{
189  this->cu_control_flag = src.cu_control_flag;
190  this->alf_max_depth   = src.alf_max_depth;
191  this->num_alf_cu_flag = src.num_alf_cu_flag;
192  this->alf_cu_flag     = src.alf_cu_flag;
193  return *this;
194}
195
196#if LCU_SYNTAX_ALF
197/// AlfCUCtrlInfo
198Void AlfCUCtrlInfo::reset()
199{
200  cu_control_flag= 0;
201  num_alf_cu_flag= 0;
202  alf_max_depth = 0;
203  alf_cu_flag.clear();
204}
205
206/// ALFParam
207const ALFParam& ALFParam::operator= (const ALFParam& src)
208{
209  if(this->componentID < 0)
210  {
211    this->create(src.componentID);
212  }
213  this->copy(src);
214  return *this;
215}
216
217Void ALFParam::create(Int cID)
218{
219  const Int numCoef = ALF_MAX_NUM_COEF;
220
221  this->componentID       = cID;
222  this->alf_flag          = 0;
223  this->filters_per_group = 1; // this value keeps 1 for chroma componenet
224  this->startSecondFilter = -1;
225  this->predMethod        = -1;
226  this->minKStart         = -1;
227  this->filterPattern     = NULL;
228  this->nbSPred           = NULL;
229  this->kMinTab           = NULL;
230  this->coeffmulti        = NULL;
231  this->filter_shape      = 0;
232  this->num_coeff         = numCoef;
233
234  switch(cID)
235  {
236  case ALF_Y:
237    {
238      this->coeffmulti = new Int*[NO_VAR_BINS];
239      for(Int i=0; i< NO_VAR_BINS; i++)
240      {
241        this->coeffmulti[i] = new Int[numCoef];
242        ::memset(this->coeffmulti[i], 0, sizeof(Int)*numCoef);
243      }
244      this->filterPattern = new Int[NO_VAR_BINS];
245      ::memset(this->filterPattern, 0, sizeof(Int)*NO_VAR_BINS);
246
247      this->nbSPred       = new Int[NO_VAR_BINS];
248      ::memset(this->nbSPred, 0, sizeof(Int)*NO_VAR_BINS);
249
250      this->kMinTab       = new Int[42];
251    }
252    break;
253  case ALF_Cb:
254  case ALF_Cr:
255    {
256      this->coeffmulti = new Int*[1];
257      this->coeffmulti[0] = new Int[numCoef];
258    }
259    break;
260  default:
261    {
262      printf("Not a legal component ID\n");
263      assert(0);
264      exit(-1);
265    }
266  }
267}
268
269Void ALFParam::destroy()
270{
271  if(this->componentID >=0)
272  {
273    switch(this->componentID)
274    {
275    case ALF_Y:
276      {
277        for(Int i=0; i< NO_VAR_BINS; i++)
278        {
279          delete[] this->coeffmulti[i];
280        }
281        delete[] this->coeffmulti;
282        delete[] this->filterPattern;
283        delete[] this->nbSPred;
284        delete[] this->kMinTab;
285      }
286      break;
287    case ALF_Cb:
288    case ALF_Cr:
289      {
290        delete[] this->coeffmulti[0];
291        delete[] this->coeffmulti;
292      }
293      break;
294    default:
295      {
296        printf("Not a legal component ID\n");
297        assert(0);
298        exit(-1);
299      }
300    }
301
302  }
303}
304
305Void ALFParam::copy(const ALFParam& src)
306{
307  const Int numCoef = ALF_MAX_NUM_COEF;
308
309  this->componentID       = src.componentID;
310  this->alf_flag          = src.alf_flag;
311  if(this->alf_flag == 1)
312  {
313    this->filters_per_group = src.filters_per_group;
314    this->filter_shape      = src.filter_shape;
315    this->num_coeff         = src.num_coeff;
316
317    switch(this->componentID)
318    {
319    case ALF_Cb:
320    case ALF_Cr:
321      {
322        ::memcpy(this->coeffmulti[0], src.coeffmulti[0], sizeof(Int)*numCoef);
323      }
324      break;
325    case ALF_Y:
326      {
327        this->startSecondFilter = src.startSecondFilter;
328        this->predMethod        = src.predMethod;
329        this->minKStart         = src.minKStart;
330        ::memcpy(this->filterPattern, src.filterPattern, sizeof(Int)*NO_VAR_BINS);
331        ::memcpy(this->nbSPred, src.nbSPred, sizeof(Int)*NO_VAR_BINS);
332        ::memcpy(this->kMinTab, src.kMinTab, sizeof(Int)*42);
333
334        for(Int i=0; i< (Int)NO_VAR_BINS; i++)
335        {
336          ::memcpy(this->coeffmulti[i], src.coeffmulti[i], sizeof(Int)*numCoef);
337        }
338
339      }
340      break;
341    default:
342      {
343        printf("not a legal component ID\n");
344        assert(0);
345        exit(-1);
346      }
347
348    }
349  }
350  else
351  {
352    //reset
353    this->filters_per_group = 0;
354    this->filter_shape      = 0;
355    this->num_coeff         = 0;
356  }
357}
358
359/// AlfUnitParam
360AlfUnitParam::AlfUnitParam()
361{
362  this->mergeType = ALF_MERGE_DISABLED;
363  this->isEnabled = false;
364  this->isNewFilt = false;
365  this->storedFiltIdx = -1;
366  this->alfFiltParam = NULL;
367
368}
369
370
371
372const AlfUnitParam& AlfUnitParam::operator= (const AlfUnitParam& src)
373{
374  this->mergeType = src.mergeType;
375  this->isEnabled = src.isEnabled;
376  this->isNewFilt = src.isNewFilt;
377  this->storedFiltIdx = src.storedFiltIdx;
378  this->alfFiltParam = src.alfFiltParam; // just a pointer assignment and no additional memory allocation
379
380  return *this;
381}
382
383Bool AlfUnitParam::operator == (const AlfUnitParam& cmp)
384{
385  if( isEnabled != cmp.isEnabled)
386  {
387    return false;
388  }
389
390  //enable flags are the same
391  if(!isEnabled)
392  {
393    return true;
394  }
395
396  //both enabled
397  assert(alfFiltParam->alf_flag == 1);
398
399  const Int numCoef = ALF_MAX_NUM_COEF;
400  ALFParam* cmpAlfParam = cmp.alfFiltParam;
401
402  if(alfFiltParam->componentID == ALF_Y)
403  {
404    if(alfFiltParam->filters_per_group != cmpAlfParam->filters_per_group)
405    {
406      return false;
407    }
408    if(alfFiltParam->predMethod != cmpAlfParam->predMethod)
409    {
410      return false;
411    }
412    if(alfFiltParam->minKStart != cmpAlfParam->minKStart)
413    {
414      return false;
415    }
416    if(alfFiltParam->filters_per_group == 2)
417    {
418      if(alfFiltParam->startSecondFilter != cmpAlfParam->startSecondFilter)
419      {
420        return false;
421      }
422    }
423    if (alfFiltParam->filters_per_group > 1)
424    {
425      for (Int i=0; i<NO_VAR_BINS; i++)
426      {
427        if (alfFiltParam->filterPattern[i] != cmpAlfParam->filterPattern[i])
428        {
429          return false;
430        } 
431      }
432    }     
433    for (Int i=0; i<alfFiltParam->filters_per_group; i++)
434    {
435      if (alfFiltParam->nbSPred[i] != cmpAlfParam->nbSPred[i])
436      {
437        return false;
438      } 
439    }
440  }
441  for(Int f=0; f< alfFiltParam->filters_per_group; f++)
442  {
443    for(Int i=0; i< numCoef; i++)
444    {
445      if(alfFiltParam->coeffmulti[f][i] != cmpAlfParam->coeffmulti[f][i])
446      {
447        return false;
448      }
449    }
450  }
451
452  return true;
453}
454
455
456/// AlfParamSet
457Void AlfParamSet::init()
458{
459  destroy(); 
460  create();
461}
462
463Void AlfParamSet::releaseALFParam()
464{
465  for(Int c=0; c< NUM_ALF_COMPONENT; c++)
466  {
467    if(alfUnitParam[c] != NULL)
468    {
469      for(Int n=0; n< numLCU; n++)
470      {
471        if(alfUnitParam[c][n].alfFiltParam != NULL)
472        {
473          delete alfUnitParam[c][n].alfFiltParam;
474          alfUnitParam[c][n].alfFiltParam = NULL;
475        }
476      }
477    }
478  }
479
480}
481
482Void AlfParamSet::createALFParam()
483{
484  for(Int c=0; c< NUM_ALF_COMPONENT; c++)
485  {
486    for(Int n=0; n< numLCU; n++)
487    {
488      alfUnitParam[c][n].alfFiltParam = new ALFParam(c);
489    }
490  }
491}
492
493/** Create ALF parameter set
494 * \param [in] width number of LCU in width
495 * \param [in] height number of LCU in height
496 * \param [in] num number of LCU in one picture
497 */
498Void AlfParamSet::create(Int width, Int height, Int num)
499{
500  numLCU = num;
501  numLCUInHeight = height;
502  numLCUInWidth  = width;
503
504  for(Int c=0; c< NUM_ALF_COMPONENT; c++)
505  {
506    isEnabled[c] = false;
507    isUniParam[c]= false;
508    if(num !=0)
509    {
510      alfUnitParam[c] = new AlfUnitParam[num];
511    }
512    else
513    {
514      alfUnitParam[c] = NULL;
515    }
516  }
517
518}
519
520Void AlfParamSet::destroy()
521{
522  for(Int c=0; c< NUM_ALF_COMPONENT; c++)
523  {
524    if(alfUnitParam[c] != NULL)
525    {
526      delete[] alfUnitParam[c];
527      alfUnitParam[c] = NULL;
528    }
529  }
530}
531
532#endif
533
534
535
536
537TComAdaptiveLoopFilter::TComAdaptiveLoopFilter()
538{
539  m_pcTempPicYuv = NULL;
540  m_iSGDepth     = 0;
541  m_pcPic        = NULL;
542  m_ppSliceAlfLCUs = NULL;
543  m_pvpAlfLCU    = NULL;
544  m_pvpSliceTileAlfLCU = NULL;
545#if LCU_SYNTAX_ALF
546  for(Int c=0; c< NUM_ALF_COMPONENT; c++)
547  {
548    m_alfFiltInfo[c] = NULL;
549  }
550  m_varImg = NULL;
551  m_filterCoeffSym = NULL;
552#endif
553
554}
555
556Void TComAdaptiveLoopFilter:: xError(const char *text, int code)
557{
558  fprintf(stderr, "%s\n", text);
559  exit(code);
560}
561
562Void TComAdaptiveLoopFilter:: no_mem_exit(const char *where)
563{
564  char errortext[200];
565  sprintf(errortext, "Could not allocate memory: %s",where);
566  xError (errortext, 100);
567}
568
569Void TComAdaptiveLoopFilter::initMatrix_Pel(Pel ***m2D, int d1, int d2)
570{
571  int i;
572 
573  if(!(*m2D = (Pel **) calloc(d1, sizeof(Pel *))))
574  {
575    FATAL_ERROR_0("initMatrix_Pel: memory allocation problem\n", -1);
576  }
577  if(!((*m2D)[0] = (Pel *) calloc(d1 * d2, sizeof(Pel))))
578  {
579    FATAL_ERROR_0("initMatrix_Pel: memory allocation problem\n", -1);
580  }
581 
582  for(i = 1; i < d1; i++)
583  {
584    (*m2D)[i] = (*m2D)[i-1] + d2;
585  }
586}
587
588Void TComAdaptiveLoopFilter::initMatrix_int(int ***m2D, int d1, int d2)
589{
590  int i;
591 
592  if(!(*m2D = (int **) calloc(d1, sizeof(int *))))
593  {
594    FATAL_ERROR_0("initMatrix_int: memory allocation problem\n", -1);
595  }
596  if(!((*m2D)[0] = (int *) calloc(d1 * d2, sizeof(int))))
597  {
598    FATAL_ERROR_0("initMatrix_int: memory allocation problem\n", -1);
599  }
600 
601  for(i = 1; i < d1; i++)
602  {
603    (*m2D)[i] = (*m2D)[i-1] + d2;
604  }
605}
606
607Void TComAdaptiveLoopFilter::destroyMatrix_int(int **m2D)
608{
609  if(m2D)
610  {
611    if(m2D[0])
612    {
613      free(m2D[0]);
614    }
615    else
616    {
617      FATAL_ERROR_0("destroyMatrix_int: memory free problem\n", -1);
618    }
619    free(m2D);
620  } 
621  else
622  {
623    FATAL_ERROR_0("destroyMatrix_int: memory free problem\n", -1);
624  }
625}
626
627Void TComAdaptiveLoopFilter::destroyMatrix_Pel(Pel **m2D)
628{
629  if(m2D)
630  {
631    if(m2D[0])
632    {
633      free(m2D[0]);
634    }
635    else
636    {
637      FATAL_ERROR_0("destroyMatrix_Pel: memory free problem\n", -1);
638    }
639    free(m2D);
640  } 
641  else
642  {
643    FATAL_ERROR_0("destroyMatrix_Pel: memory free problem\n", -1);
644  }
645}
646
647Void TComAdaptiveLoopFilter::initMatrix_double(double ***m2D, int d1, int d2)
648{
649  int i;
650 
651  if(!(*m2D = (double **) calloc(d1, sizeof(double *))))
652  {
653    FATAL_ERROR_0("initMatrix_double: memory allocation problem\n", -1);
654  }
655  if(!((*m2D)[0] = (double *) calloc(d1 * d2, sizeof(double))))
656  {
657    FATAL_ERROR_0("initMatrix_double: memory allocation problem\n", -1);
658  }
659 
660  for(i = 1; i < d1; i++)
661  {
662    (*m2D)[i] = (*m2D)[i-1] + d2;
663  }
664}
665
666Void TComAdaptiveLoopFilter::initMatrix3D_double(double ****m3D, int d1, int d2, int d3)
667{
668  int  j;
669 
670  if(!((*m3D) = (double ***) calloc(d1, sizeof(double **))))
671  {
672    FATAL_ERROR_0("initMatrix3D_double: memory allocation problem\n", -1);
673  }
674 
675  for(j = 0; j < d1; j++)
676  {
677    initMatrix_double((*m3D) + j, d2, d3);
678  }
679}
680
681
682Void TComAdaptiveLoopFilter::initMatrix4D_double(double *****m4D, int d1, int d2, int d3, int d4)
683{
684  int  j;
685 
686  if(!((*m4D) = (double ****) calloc(d1, sizeof(double ***))))
687  {
688    FATAL_ERROR_0("initMatrix4D_double: memory allocation problem\n", -1);
689  }
690 
691  for(j = 0; j < d1; j++)
692  {
693    initMatrix3D_double((*m4D) + j, d2, d3, d4);
694  }
695}
696
697
698Void TComAdaptiveLoopFilter::destroyMatrix_double(double **m2D)
699{
700  if(m2D)
701  {
702    if(m2D[0])
703    {
704      free(m2D[0]);
705    }
706    else
707    {
708      FATAL_ERROR_0("destroyMatrix_double: memory free problem\n", -1);
709    }
710    free(m2D);
711  } 
712  else
713  {
714    FATAL_ERROR_0("destroyMatrix_double: memory free problem\n", -1);
715  }
716}
717
718Void TComAdaptiveLoopFilter::destroyMatrix3D_double(double ***m3D, int d1)
719{
720  int i;
721 
722  if(m3D)
723  {
724    for(i = 0; i < d1; i++)
725    {
726      destroyMatrix_double(m3D[i]);
727    }
728    free(m3D);
729  } 
730  else
731  {
732    FATAL_ERROR_0("destroyMatrix3D_double: memory free problem\n", -1);
733  }
734}
735
736
737Void TComAdaptiveLoopFilter::destroyMatrix4D_double(double ****m4D, int d1, int d2)
738{
739  int  j;
740 
741  if(m4D)
742  {
743    for(j = 0; j < d1; j++)
744    {
745      destroyMatrix3D_double(m4D[j], d2);
746    }
747    free(m4D);
748  } 
749  else
750  {
751    FATAL_ERROR_0("destroyMatrix4D_double: memory free problem\n", -1);
752  }
753}
754
755Void TComAdaptiveLoopFilter::create( Int iPicWidth, Int iPicHeight, UInt uiMaxCUWidth, UInt uiMaxCUHeight, UInt uiMaxCUDepth )
756{
757#if LCU_SYNTAX_ALF
758  destroy();
759#endif
760  if ( !m_pcTempPicYuv )
761  {
762    m_pcTempPicYuv = new TComPicYuv;
763    m_pcTempPicYuv->create( iPicWidth, iPicHeight, uiMaxCUWidth, uiMaxCUHeight, uiMaxCUDepth );
764  }
765  m_img_height = iPicHeight;
766  m_img_width = iPicWidth;
767#if LCU_SYNTAX_ALF
768  initMatrix_Pel(&(m_varImg), m_img_height, m_img_width);
769#else
770  for(Int i=0; i< NUM_ALF_CLASS_METHOD; i++)
771  {
772    initMatrix_Pel(&(m_varImgMethods[i]), m_img_height, m_img_width);
773  }
774#endif
775  initMatrix_int(&m_filterCoeffSym, NO_VAR_BINS, ALF_MAX_NUM_COEF);
776  UInt uiNumLCUsInWidth   = m_img_width  / uiMaxCUWidth;
777  UInt uiNumLCUsInHeight  = m_img_height / uiMaxCUHeight;
778
779  uiNumLCUsInWidth  += ( m_img_width % uiMaxCUWidth ) ? 1 : 0;
780  uiNumLCUsInHeight += ( m_img_height % uiMaxCUHeight ) ? 1 : 0;
781
782  m_uiNumCUsInFrame = uiNumLCUsInWidth* uiNumLCUsInHeight; 
783
784#if LCU_SYNTAX_ALF
785  m_numLCUInPicWidth = uiNumLCUsInWidth;
786  m_numLCUInPicHeight= uiNumLCUsInHeight;
787  m_lcuHeight = uiMaxCUHeight;
788#if ALF_SINGLE_FILTER_SHAPE
789  m_lineIdxPadBot = m_lcuHeight - 4 - 3; // DFRegion, Vertical Taps
790#else
791  m_lineIdxPadBot = m_lcuHeight - 4 - 4; // DFRegion, Vertical Taps
792#endif
793  m_lineIdxPadTop = m_lcuHeight - 4; // DFRegion
794
795  m_lcuHeightChroma = m_lcuHeight>>1;
796#if ALF_SINGLE_FILTER_SHAPE
797  m_lineIdxPadBotChroma = m_lcuHeightChroma - 2 - 3; // DFRegion, Vertical Taps
798#else
799  m_lineIdxPadBotChroma = m_lcuHeightChroma - 2 - 4; // DFRegion, Vertical Taps
800#endif
801  m_lineIdxPadTopChroma = m_lcuHeightChroma - 2 ; // DFRegion
802
803  createLCUAlfInfo();
804#else
805  createRegionIndexMap(m_varImgMethods[ALF_RA], m_img_width, m_img_height);
806#endif
807}
808
809Void TComAdaptiveLoopFilter::destroy()
810{
811  if ( m_pcTempPicYuv )
812  {
813    m_pcTempPicYuv->destroy();
814    delete m_pcTempPicYuv;
815#if LCU_SYNTAX_ALF
816    m_pcTempPicYuv = NULL;
817#endif
818  }
819#if LCU_SYNTAX_ALF
820  if(m_varImg != NULL)
821  {
822    destroyMatrix_Pel( m_varImg );
823    m_varImg = NULL;
824  }
825  if(m_filterCoeffSym != NULL)
826  {
827    destroyMatrix_int(m_filterCoeffSym);
828    m_filterCoeffSym = NULL;
829  }
830#else
831  for(Int i=0; i< NUM_ALF_CLASS_METHOD; i++)
832  {
833    destroyMatrix_Pel(m_varImgMethods[i]);
834  }
835  destroyMatrix_int(m_filterCoeffSym);
836#endif
837#if LCU_SYNTAX_ALF
838  destroyLCUAlfInfo();
839#endif
840
841}
842
843#if !LCU_SYNTAX_ALF
844// --------------------------------------------------------------------------------------------------------------------
845// allocate / free / copy functions
846// --------------------------------------------------------------------------------------------------------------------
847Void TComAdaptiveLoopFilter::allocALFParam(ALFParam* pAlfParam)
848{
849  pAlfParam->alf_flag = 0;
850  pAlfParam->coeff_chroma = new Int[ALF_MAX_NUM_COEF];
851  ::memset(pAlfParam->coeff_chroma, 0, sizeof(Int)*ALF_MAX_NUM_COEF );
852  pAlfParam->coeffmulti = new Int*[NO_VAR_BINS];
853  for (int i=0; i<NO_VAR_BINS; i++)
854  {
855    pAlfParam->coeffmulti[i] = new Int[ALF_MAX_NUM_COEF];
856    ::memset(pAlfParam->coeffmulti[i],        0, sizeof(Int)*ALF_MAX_NUM_COEF );
857  }
858  pAlfParam->nbSPred = new Int[NO_VAR_BINS];
859  ::memset(pAlfParam->nbSPred, 0, sizeof(Int)*NO_VAR_BINS);
860  pAlfParam->filterPattern = new Int[NO_VAR_BINS];
861  ::memset(pAlfParam->filterPattern, 0, sizeof(Int)*NO_VAR_BINS);
862  pAlfParam->alf_pcr_region_flag = 0;
863}
864
865Void TComAdaptiveLoopFilter::freeALFParam(ALFParam* pAlfParam)
866{
867  assert(pAlfParam != NULL);
868  if (pAlfParam->coeff_chroma != NULL)
869  {
870    delete[] pAlfParam->coeff_chroma;
871    pAlfParam->coeff_chroma = NULL;
872  }
873  for (int i=0; i<NO_VAR_BINS; i++)
874  {
875    delete[] pAlfParam->coeffmulti[i];
876    pAlfParam->coeffmulti[i] = NULL;
877  }
878  delete[] pAlfParam->coeffmulti;
879  pAlfParam->coeffmulti = NULL;
880
881  delete[] pAlfParam->nbSPred;
882  pAlfParam->nbSPred = NULL;
883
884  delete[] pAlfParam->filterPattern;
885  pAlfParam->filterPattern = NULL;
886}
887
888
889Void TComAdaptiveLoopFilter::copyALFParam(ALFParam* pDesAlfParam, ALFParam* pSrcAlfParam)
890{
891  pDesAlfParam->alf_flag = pSrcAlfParam->alf_flag;
892  pDesAlfParam->chroma_idc = pSrcAlfParam->chroma_idc;
893  pDesAlfParam->num_coeff = pSrcAlfParam->num_coeff;
894  pDesAlfParam->filter_shape_chroma = pSrcAlfParam->filter_shape_chroma;
895  pDesAlfParam->num_coeff_chroma = pSrcAlfParam->num_coeff_chroma;
896  pDesAlfParam->alf_pcr_region_flag = pSrcAlfParam->alf_pcr_region_flag;
897  ::memcpy(pDesAlfParam->coeff_chroma, pSrcAlfParam->coeff_chroma, sizeof(Int)*ALF_MAX_NUM_COEF);
898  pDesAlfParam->filter_shape = pSrcAlfParam->filter_shape;
899  ::memcpy(pDesAlfParam->filterPattern, pSrcAlfParam->filterPattern, sizeof(Int)*NO_VAR_BINS);
900  pDesAlfParam->startSecondFilter = pSrcAlfParam->startSecondFilter;
901
902  //Coeff send related
903  pDesAlfParam->filters_per_group = pSrcAlfParam->filters_per_group; //this can be updated using codedVarBins
904  pDesAlfParam->predMethod = pSrcAlfParam->predMethod;
905  ::memcpy(pDesAlfParam->nbSPred, pSrcAlfParam->nbSPred, sizeof(Int)*NO_VAR_BINS);
906  for (int i=0; i<NO_VAR_BINS; i++)
907  {
908    ::memcpy(pDesAlfParam->coeffmulti[i], pSrcAlfParam->coeffmulti[i], sizeof(Int)*ALF_MAX_NUM_COEF);
909  }
910}
911// --------------------------------------------------------------------------------------------------------------------
912// prediction of filter coefficients
913// --------------------------------------------------------------------------------------------------------------------
914
915Void TComAdaptiveLoopFilter::predictALFCoeffChroma( ALFParam* pAlfParam )
916{
917  Int i, sum, pred, N;
918  const Int* pFiltMag = NULL;
919  pFiltMag = weightsTabShapes[pAlfParam->filter_shape_chroma];
920  N = pAlfParam->num_coeff_chroma;
921  sum=0;
922  for(i=0; i<N;i++)
923  {
924    sum+=pFiltMag[i]*pAlfParam->coeff_chroma[i];
925  }
926  pred=(1<<ALF_NUM_BIT_SHIFT)-(sum-pAlfParam->coeff_chroma[N-1]);
927#if ALF_CHROMA_COEF_PRED_HARMONIZATION
928  pAlfParam->coeff_chroma[N-1]=pAlfParam->coeff_chroma[N-1] - pred;
929#else
930  pAlfParam->coeff_chroma[N-1]=pred-pAlfParam->coeff_chroma[N-1];
931#endif
932}
933
934#if ALF_CHROMA_COEF_PRED_HARMONIZATION
935Void TComAdaptiveLoopFilter::reconstructALFCoeffChroma( ALFParam* pAlfParam )
936{
937  Int i, sum, pred, N;
938  const Int* pFiltMag = NULL;
939  pFiltMag = weightsTabShapes[pAlfParam->filter_shape_chroma];
940  N = pAlfParam->num_coeff_chroma;
941  sum=0;
942  for(i=0; i<N;i++)
943  {
944    sum+=pFiltMag[i]*pAlfParam->coeff_chroma[i];
945  }
946  pred=(1<<ALF_NUM_BIT_SHIFT)-(sum-pAlfParam->coeff_chroma[N-1]);
947  pAlfParam->coeff_chroma[N-1]=pred+ pAlfParam->coeff_chroma[N-1];
948}
949#endif
950#endif
951
952// --------------------------------------------------------------------------------------------------------------------
953// interface function for actual ALF process
954// --------------------------------------------------------------------------------------------------------------------
955
956#if LCU_SYNTAX_ALF
957/** ALF reconstruction process for one picture
958 * \param [in, out] pcPic the decoded/filtered picture (input: decoded picture; output filtered picture)
959 * \param [in] vAlfCUCtrlParam ALF CU-on/off control parameters
960 * \param [in] isAlfCoefInSlice ALF coefficient in slice (true) or ALF coefficient in APS (false)
961 */
962Void TComAdaptiveLoopFilter::ALFProcess(TComPic* pcPic, std::vector<AlfCUCtrlInfo>& vAlfCUCtrlParam, Bool isAlfCoefInSlice)
963{
964  TComPicYuv* pcPicYuvRec    = pcPic->getPicYuvRec();
965  TComPicYuv* pcPicYuvExtRec = m_pcTempPicYuv;
966  pcPicYuvRec   ->copyToPic          ( pcPicYuvExtRec );
967  pcPicYuvExtRec->setBorderExtension ( false );
968  pcPicYuvExtRec->extendPicBorder    ();
969
970  Int lumaStride   = pcPicYuvExtRec->getStride();
971  Int chromaStride = pcPicYuvExtRec->getCStride();
972
973  for(Int compIdx =0; compIdx < NUM_ALF_COMPONENT; compIdx++)
974  {
975    Pel* pDec         = getPicBuf(pcPicYuvExtRec, compIdx);
976    Pel* pRest        = getPicBuf(pcPicYuvRec, compIdx);
977    Int  stride       = (compIdx == ALF_Y)?(lumaStride):(chromaStride);
978    Int  formatShift = (compIdx == ALF_Y)?(0):(1);
979
980    ALFParam** alfLCUParamComp = m_alfFiltInfo[compIdx];
981
982    if(!isEnabledComponent(alfLCUParamComp))
983    {
984      continue;
985    }
986
987    switch(compIdx)
988    {
989    case ALF_Cb:
990    case ALF_Cr:
991      {
992        recALF(compIdx, alfLCUParamComp, pDec, pRest, stride, formatShift, NULL, false);
993      }
994      break;
995    case ALF_Y:
996      {
997        std::vector<AlfCUCtrlInfo>* alfCUCtrlParam = NULL;
998        if(!isAlfCoefInSlice)
999        {
1000          alfCUCtrlParam = &vAlfCUCtrlParam;
1001          assignAlfOnOffControlFlags(pcPic, *alfCUCtrlParam);
1002        }
1003
1004        memset(&m_varImg[0][0], 0, sizeof(Pel)*(m_img_height*m_img_width));
1005
1006        //calcOneRegionVar(m_varImg, pDec, stride, false, 0, m_img_height, 0, m_img_width);
1007        recALF(compIdx, alfLCUParamComp, pDec, pRest, stride, formatShift, alfCUCtrlParam, true);
1008      }
1009      break;
1010    default:
1011      {
1012        printf("Not a legal component ID for ALF\n");
1013        assert(0);
1014        exit(-1);
1015      }
1016    }
1017  }
1018
1019}
1020
1021/** Check the filter process of one component is enable
1022 * \param [in] alfLCUParam ALF parameters
1023 */
1024Bool TComAdaptiveLoopFilter::isEnabledComponent(ALFParam** alfLCUParam)
1025{
1026  Bool isEnabled = false;
1027  for(Int n=0; n< m_uiNumCUsInFrame; n++)
1028  {
1029    if(alfLCUParam[n]->alf_flag == 1)
1030    {
1031      isEnabled = true;
1032      break;
1033    }
1034  }
1035  return isEnabled;
1036}
1037
1038
1039/** ALF Reconstruction for each component
1040 * \param [in] compIdx color component index
1041 * \param [in] alfLCUParams alf parameters
1042 * \param [in] pDec decoded picture
1043 * \param [in, out] pRest filtered picture
1044 * \param [in] stride picture stride in memory
1045 * \param [in] formatShift luma component (false) or chroma component (1)
1046 * \param [in] alfCUCtrlParam ALF CU-on/off control parameters
1047 * \param [in] caculateBAIdx calculate BA filter index (true) or BA filter index array is ready (false)
1048 */
1049Void TComAdaptiveLoopFilter::recALF(Int compIdx, ALFParam** alfLCUParams,Pel* pDec, Pel* pRest, Int stride, Int formatShift
1050                                  , std::vector<AlfCUCtrlInfo>* alfCUCtrlParam //default: NULL
1051                                  , Bool caculateBAIdx //default: false
1052                                    )
1053{
1054  for(Int s=0; s< m_uiNumSlicesInPic; s++)
1055  {
1056    if(!m_pcPic->getValidSlice(s))
1057    {
1058      continue;
1059    }
1060    Int numTilesInSlice = (Int)m_pvpSliceTileAlfLCU[s].size();
1061    for(Int t=0; t< numTilesInSlice; t++)
1062    {
1063      std::vector<AlfLCUInfo*> & vpAlfLCU = m_pvpSliceTileAlfLCU[s][t];
1064      Pel* pSrc = pDec;
1065
1066      if(m_bUseNonCrossALF)
1067      {
1068        pSrc = getPicBuf(m_pcSliceYuvTmp, compIdx);
1069        copyRegion(vpAlfLCU, pSrc, pDec, stride, formatShift);
1070        extendRegionBorder(vpAlfLCU, pSrc, stride, formatShift);
1071      }
1072
1073      Bool isOnOffCtrlEnabled = (alfCUCtrlParam == NULL)?(false):(  (*alfCUCtrlParam)[s].cu_control_flag == 1 );
1074
1075      if(isOnOffCtrlEnabled)
1076      {
1077        assert(compIdx == ALF_Y);
1078        filterRegionCUControl(alfLCUParams, vpAlfLCU, pSrc, pRest, stride, caculateBAIdx);
1079      }
1080      else
1081      {
1082        filterRegion(compIdx, alfLCUParams, vpAlfLCU, pSrc, pRest, stride, formatShift, caculateBAIdx);
1083      }
1084    } //tile
1085  } //slice
1086}
1087
1088
1089/** assign ALC CU-On/Off Control parameters
1090 * \param [in, out] pcPic picture data
1091 * \param [in] vAlfCUCtrlParam ALF CU-on/off control parameters
1092 */
1093Void TComAdaptiveLoopFilter::assignAlfOnOffControlFlags(TComPic* pcPic, std::vector<AlfCUCtrlInfo>& vAlfCUCtrlParam)
1094{
1095  if(m_uiNumSlicesInPic == 1)
1096  {
1097    AlfCUCtrlInfo* pcAlfCtrlParam = &(vAlfCUCtrlParam[0]);
1098    if(pcAlfCtrlParam->cu_control_flag)
1099    {
1100      UInt idx = 0;
1101      for(UInt uiCUAddr = 0; uiCUAddr < pcPic->getNumCUsInFrame(); uiCUAddr++)
1102      {
1103        TComDataCU *pcCU = pcPic->getCU(uiCUAddr);
1104        setAlfCtrlFlags(pcAlfCtrlParam, pcCU, 0, 0, idx);
1105      }
1106    }
1107  }
1108  else
1109  {
1110    transferCtrlFlagsFromAlfParam(vAlfCUCtrlParam);
1111  }
1112
1113}
1114
1115#else
1116
1117/**
1118 \param [in, out] pcPic         picture (TComPic) class (input/output)
1119 \param [in] pcAlfParam    ALF parameter
1120 \param [in,out] vAlfCUCtrlParam ALF CU control parameters
1121 \todo   for temporal buffer, it uses residual picture buffer, which may not be safe. Make it be safer.
1122 */
1123Void TComAdaptiveLoopFilter::ALFProcess(TComPic* pcPic, ALFParam* pcAlfParam, std::vector<AlfCUCtrlInfo>& vAlfCUCtrlParam)
1124{
1125  assert(m_uiNumSlicesInPic == vAlfCUCtrlParam.size());
1126  if(!pcAlfParam->alf_flag)
1127  {
1128    return;
1129  }
1130
1131  m_lcuHeight     = pcPic->getSlice(0)->getSPS()->getMaxCUHeight();
1132#if ALF_SINGLE_FILTER_SHAPE
1133  m_lineIdxPadBot = m_lcuHeight - 4 - 3;             // DFRegion, Vertical Taps
1134#else
1135  m_lineIdxPadBot = m_lcuHeight - 4 - 4;             // DFRegion, Vertical Taps
1136#endif
1137  m_lineIdxPadTop = m_lcuHeight - 4;                 // DFRegion
1138
1139  m_lcuHeightChroma     = m_lcuHeight>>1;
1140#if ALF_SINGLE_FILTER_SHAPE
1141  m_lineIdxPadBotChroma = m_lcuHeightChroma - 2 - 3; // DFRegion, Vertical Taps
1142#else
1143  m_lineIdxPadBotChroma = m_lcuHeightChroma - 2 - 4; // DFRegion, Vertical Taps
1144#endif
1145  m_lineIdxPadTopChroma = m_lcuHeightChroma - 2 ;    // DFRegion
1146
1147  TComPicYuv* pcPicYuvRec    = pcPic->getPicYuvRec();
1148  TComPicYuv* pcPicYuvExtRec = m_pcTempPicYuv;
1149    pcPicYuvRec   ->copyToPic          ( pcPicYuvExtRec );
1150    pcPicYuvExtRec->setBorderExtension ( false );
1151    pcPicYuvExtRec->extendPicBorder    ();
1152
1153  if(m_uiNumSlicesInPic == 1)
1154  {
1155    AlfCUCtrlInfo* pcAlfCtrlParam = &(vAlfCUCtrlParam[0]);
1156    if(pcAlfCtrlParam->cu_control_flag)
1157    {
1158      UInt idx = 0;
1159      for(UInt uiCUAddr = 0; uiCUAddr < pcPic->getNumCUsInFrame(); uiCUAddr++)
1160      {
1161        TComDataCU *pcCU = pcPic->getCU(uiCUAddr);
1162        setAlfCtrlFlags(pcAlfCtrlParam, pcCU, 0, 0, idx);
1163      }
1164    }
1165  }
1166  else
1167  {
1168    transferCtrlFlagsFromAlfParam(vAlfCUCtrlParam);
1169  }
1170  xALFLuma(pcPic, pcAlfParam, vAlfCUCtrlParam, pcPicYuvExtRec, pcPicYuvRec);
1171  if(pcAlfParam->chroma_idc)
1172  {
1173#if ALF_CHROMA_COEF_PRED_HARMONIZATION
1174    reconstructALFCoeffChroma(pcAlfParam);
1175#else
1176    predictALFCoeffChroma(pcAlfParam);
1177#endif
1178    checkFilterCoeffValue(pcAlfParam->coeff_chroma, pcAlfParam->num_coeff_chroma, true );
1179
1180    xALFChroma( pcAlfParam, pcPicYuvExtRec, pcPicYuvRec);
1181  }
1182}
1183#endif
1184// ====================================================================================================================
1185// Protected member functions
1186// ====================================================================================================================
1187
1188/**
1189 \param filter         filter coefficient
1190 \param filterLength   filter length
1191 \param isChroma       1: chroma, 0: luma
1192 */
1193Void TComAdaptiveLoopFilter::checkFilterCoeffValue( Int *filter, Int filterLength, Bool isChroma )
1194{
1195#if LCUALF_QP_DEPENDENT_BITS
1196  Int alfPrecisionBit = getAlfPrecisionBit( m_alfQP );
1197
1198  Int maxValueNonCenter = 1 * (1 << alfPrecisionBit) - 1;
1199  Int minValueNonCenter = 0 - 1 * (1 << alfPrecisionBit);
1200
1201  Int maxValueCenter    = 2 * (1 << alfPrecisionBit) - 1;
1202#else
1203  Int maxValueNonCenter = 1 * (1 << ALF_NUM_BIT_SHIFT) - 1;
1204  Int minValueNonCenter = 0 - 1 * (1 << ALF_NUM_BIT_SHIFT);
1205
1206  Int maxValueCenter    = 2 * (1 << ALF_NUM_BIT_SHIFT) - 1;
1207#endif
1208  Int minValueCenter    = 0 ; 
1209
1210  for(Int i = 0; i < filterLength-1; i++)
1211  {
1212    filter[i] = Clip3(minValueNonCenter, maxValueNonCenter, filter[i]);
1213  }
1214
1215  filter[filterLength-1] = Clip3(minValueCenter, maxValueCenter, filter[filterLength-1]);
1216}
1217
1218#if !LCU_SYNTAX_ALF
1219
1220Void TComAdaptiveLoopFilter::xALFLuma(TComPic* pcPic, ALFParam* pcAlfParam, std::vector<AlfCUCtrlInfo>& vAlfCUCtrlParam,TComPicYuv* pcPicDec, TComPicYuv* pcPicRest)
1221{
1222  Int    LumaStride = pcPicDec->getStride();
1223  Pel* pDec = pcPicDec->getLumaAddr();
1224  Pel* pRest = pcPicRest->getLumaAddr();
1225
1226  decodeFilterSet(pcAlfParam, m_varIndTab, m_filterCoeffSym);
1227
1228  m_uiVarGenMethod = pcAlfParam->alf_pcr_region_flag;
1229  m_varImg         = m_varImgMethods[m_uiVarGenMethod];
1230  calcVar(m_varImg, pRest, LumaStride, pcAlfParam->alf_pcr_region_flag);
1231
1232  if(!m_bUseNonCrossALF)
1233  {
1234    Bool bCUCtrlEnabled = false;
1235    for(UInt s=0; s< m_uiNumSlicesInPic; s++)
1236    {
1237      if(!pcPic->getValidSlice(s))
1238      {
1239        continue;
1240      }
1241      if( vAlfCUCtrlParam[s].cu_control_flag == 1)
1242      {
1243        bCUCtrlEnabled = true;
1244      }
1245    }
1246
1247    if(bCUCtrlEnabled) 
1248    {
1249      xCUAdaptive(pcPic, pcAlfParam->filter_shape, pRest, pDec, LumaStride);
1250    } 
1251    else
1252    {
1253      filterLuma(pRest, pDec, LumaStride, 0, m_img_height-1, 0, m_img_width-1,  pcAlfParam->filter_shape, m_filterCoeffSym, m_varIndTab, m_varImg);
1254    }
1255  }
1256  else
1257  {
1258    Pel* pTemp = m_pcSliceYuvTmp->getLumaAddr();
1259    for(UInt s=0; s< m_uiNumSlicesInPic; s++)
1260    {
1261      if(!pcPic->getValidSlice(s)) 
1262      {
1263        continue;
1264      }
1265      std::vector< std::vector<AlfLCUInfo*> > & vpSliceTileAlfLCU = m_pvpSliceTileAlfLCU[s];
1266
1267      for(Int t=0; t< (Int)vpSliceTileAlfLCU.size(); t++)
1268      {
1269        std::vector<AlfLCUInfo*> & vpAlfLCU = vpSliceTileAlfLCU[t];
1270
1271        copyRegion(vpAlfLCU, pTemp, pDec, LumaStride);
1272        extendRegionBorder(vpAlfLCU, pTemp, LumaStride);
1273        if(vAlfCUCtrlParam[s].cu_control_flag == 1)
1274        {
1275          xCUAdaptiveRegion(vpAlfLCU, pTemp, pRest, LumaStride, pcAlfParam->filter_shape, m_filterCoeffSym, m_varIndTab, m_varImg);
1276        }
1277        else
1278        {
1279          filterLumaRegion(vpAlfLCU, pTemp, pRest, LumaStride, pcAlfParam->filter_shape, m_filterCoeffSym, m_varIndTab, m_varImg);
1280        }
1281      }
1282    }
1283  }
1284}
1285
1286Void TComAdaptiveLoopFilter::decodeFilterSet(ALFParam* pcAlfParam, Int* varIndTab, Int** filterCoeff)
1287{
1288  // reconstruct merge table
1289  memset(m_varIndTab, 0, NO_VAR_BINS * sizeof(Int));
1290  if(pcAlfParam->filters_per_group > 1)
1291  {
1292    for(Int i = 1; i < NO_VAR_BINS; ++i)
1293    {
1294      if(pcAlfParam->filterPattern[i])
1295      {
1296        varIndTab[i] = varIndTab[i-1] + 1;
1297      }
1298      else
1299      {
1300        varIndTab[i] = varIndTab[i-1];
1301      }
1302    }
1303  }
1304  predictALFCoeffLuma( pcAlfParam);
1305  // reconstruct filter sets
1306  reconstructFilterCoeffs( pcAlfParam, filterCoeff);
1307
1308}
1309
1310
1311Void TComAdaptiveLoopFilter::filterLuma(Pel *pImgRes, Pel *pImgPad, Int stride, 
1312  Int ypos, Int yposEnd, Int xpos, Int xposEnd, 
1313  Int filtNo, Int** filterSet, Int* mergeTable, Pel** ppVarImg)
1314{
1315  static Int numBitsMinus1= (Int)ALF_NUM_BIT_SHIFT;
1316  static Int offset       = (1<<( (Int)ALF_NUM_BIT_SHIFT-1));
1317  static Int shiftHeight  = (Int)(log((double)VAR_SIZE_H)/log(2.0));
1318  static Int shiftWidth   = (Int)(log((double)VAR_SIZE_W)/log(2.0));
1319
1320  Pel *pImgPad1,*pImgPad2,*pImgPad3,*pImgPad4;
1321  Pel *pVar;
1322  Int i, j, pixelInt;
1323  Int *coef = NULL;
1324
1325  pImgPad    += (ypos*stride);
1326  pImgRes    += (ypos*stride);
1327
1328  Int yLineInLCU;
1329  Int paddingLine;
1330#if !ALF_SINGLE_FILTER_SHAPE
1331  Int varInd = 0;
1332#endif
1333  Int newCenterCoeff[4][NO_VAR_BINS];
1334
1335  for(i=0; i< 4; i++)
1336  {
1337    ::memset(&(newCenterCoeff[i][0]), 0, sizeof(Int)*NO_VAR_BINS);
1338  }
1339
1340#if ALF_SINGLE_FILTER_SHAPE
1341  if(filtNo == ALF_CROSS9x7_SQUARE3x3)
1342#else
1343  if(filtNo == ALF_CROSS9x9)
1344#endif
1345  {
1346    for (i=0; i<NO_VAR_BINS; i++)
1347    {
1348      coef = filterSet[i];
1349      //VB line 1
1350      newCenterCoeff[0][i] = coef[8] + ((coef[0] + coef[1] + coef[2] + coef[3])<<1);
1351      //VB line 2
1352      newCenterCoeff[1][i] = coef[8] + ((coef[0] + coef[1] + coef[2])<<1);
1353      //VB line 3
1354      newCenterCoeff[2][i] = coef[8] + ((coef[0] + coef[1])<<1);
1355      //VB line 4
1356      newCenterCoeff[3][i] = coef[8] + ((coef[0])<<1);
1357    }
1358  }
1359
1360
1361  switch(filtNo)
1362  {
1363#if !ALF_SINGLE_FILTER_SHAPE
1364  case ALF_STAR5x5:
1365    {
1366      for(i= ypos; i<= yposEnd; i++)
1367      {
1368
1369        yLineInLCU = i % m_lcuHeight;   
1370
1371        if (yLineInLCU<m_lineIdxPadBot || i-yLineInLCU+m_lcuHeight >= m_img_height)
1372        {
1373          pImgPad1 = pImgPad +   stride;
1374          pImgPad2 = pImgPad -   stride;
1375          pImgPad3 = pImgPad + 2*stride;
1376          pImgPad4 = pImgPad - 2*stride;
1377        }
1378        else if (yLineInLCU<m_lineIdxPadTop)
1379        {
1380          paddingLine = - yLineInLCU + m_lineIdxPadTop - 1;
1381          pImgPad1 = pImgPad + min(paddingLine, 1)*stride;
1382          pImgPad2 = pImgPad -   stride;
1383          pImgPad3 = pImgPad + min(paddingLine, 2)*stride;
1384          pImgPad4 = pImgPad - 2*stride;
1385        }
1386        else
1387        {
1388          paddingLine = yLineInLCU - m_lineIdxPadTop ;
1389          pImgPad1 = pImgPad + stride;
1390          pImgPad2 = pImgPad - min(paddingLine, 1)*stride;
1391          pImgPad3 = pImgPad + 2*stride;
1392          pImgPad4 = pImgPad - min(paddingLine, 2)*stride;
1393        } 
1394
1395        pVar = ppVarImg[i>>shiftHeight] + (xpos>>shiftWidth);
1396
1397        if ( (yLineInLCU == m_lineIdxPadTop || yLineInLCU == m_lineIdxPadTop-1) && i-yLineInLCU+m_lcuHeight < m_img_height ) 
1398        {
1399          for(j= xpos; j<= xposEnd; j++)
1400          {
1401            pImgRes[j] = pImgPad[j];
1402          }
1403        }
1404        else if ( (yLineInLCU == m_lineIdxPadTop+1 || yLineInLCU == m_lineIdxPadTop-2) && i-yLineInLCU+m_lcuHeight < m_img_height ) 
1405        {
1406          for(j= xpos; j<= xposEnd ; j++)
1407          {
1408            if (j % VAR_SIZE_W==0) 
1409            {
1410              coef = filterSet[mergeTable[*(pVar++)]];
1411            }
1412
1413            pixelInt  = 0;
1414
1415            pixelInt += coef[0]* (pImgPad3[j+2]+pImgPad4[j-2]);
1416            pixelInt += coef[1]* (pImgPad3[]+pImgPad4[]);
1417            pixelInt += coef[2]* (pImgPad3[j-2]+pImgPad4[j+2]);
1418
1419            pixelInt += coef[3]* (pImgPad1[j+1]+pImgPad2[j-1]);
1420            pixelInt += coef[4]* (pImgPad1[]+pImgPad2[]);
1421            pixelInt += coef[5]* (pImgPad1[j-1]+pImgPad2[j+1]);
1422
1423            pixelInt += coef[6]* (pImgPad[j+2]+pImgPad[j-2]);
1424            pixelInt += coef[7]* (pImgPad[j+1]+pImgPad[j-1]);
1425            pixelInt += coef[8]* (pImgPad[]);
1426
1427            pixelInt=(int)((pixelInt+offset) >> numBitsMinus1);
1428            pImgRes[j] = ( Clip( pixelInt ) + pImgPad[j] ) >> 1;
1429          }
1430        }
1431        else
1432        {
1433
1434        for(j= xpos; j<= xposEnd ; j++)
1435        {
1436          if (j % VAR_SIZE_W==0) 
1437          {
1438            coef = filterSet[mergeTable[*(pVar++)]];
1439          }
1440
1441          pixelInt  = 0;
1442
1443          pixelInt += coef[0]* (pImgPad3[j+2]+pImgPad4[j-2]);
1444          pixelInt += coef[1]* (pImgPad3[]+pImgPad4[]);
1445          pixelInt += coef[2]* (pImgPad3[j-2]+pImgPad4[j+2]);
1446
1447          pixelInt += coef[3]* (pImgPad1[j+1]+pImgPad2[j-1]);
1448          pixelInt += coef[4]* (pImgPad1[]+pImgPad2[]);
1449          pixelInt += coef[5]* (pImgPad1[j-1]+pImgPad2[j+1]);
1450
1451          pixelInt += coef[6]* (pImgPad[j+2]+pImgPad[j-2]);
1452          pixelInt += coef[7]* (pImgPad[j+1]+pImgPad[j-1]);
1453          pixelInt += coef[8]* (pImgPad[]);
1454
1455          pixelInt=(Int)((pixelInt+offset) >> numBitsMinus1);
1456          pImgRes[j] = Clip( pixelInt );
1457        }
1458
1459        }
1460
1461        pImgPad += stride;
1462        pImgRes += stride;
1463      }
1464    }
1465    break;
1466  case ALF_CROSS9x9:
1467    {
1468      Pel *pImgPad5, *pImgPad6, *pImgPad7, *pImgPad8;
1469#else
1470  case ALF_CROSS9x7_SQUARE3x3:
1471    {
1472      Pel *pImgPad5, *pImgPad6;
1473#endif
1474      for(i= ypos; i<= yposEnd; i++)
1475      {
1476        yLineInLCU = i % m_lcuHeight;   
1477
1478        if (yLineInLCU<m_lineIdxPadBot || i-yLineInLCU+m_lcuHeight >= m_img_height)
1479        {
1480          pImgPad1 = pImgPad +   stride;
1481          pImgPad2 = pImgPad -   stride;
1482          pImgPad3 = pImgPad + 2*stride;
1483          pImgPad4 = pImgPad - 2*stride;
1484          pImgPad5 = pImgPad + 3*stride;
1485          pImgPad6 = pImgPad - 3*stride;
1486#if !ALF_SINGLE_FILTER_SHAPE
1487          pImgPad7 = pImgPad + 4*stride;
1488          pImgPad8 = pImgPad - 4*stride;
1489#endif
1490        }
1491        else if (yLineInLCU<m_lineIdxPadTop)
1492        {
1493          paddingLine = - yLineInLCU + m_lineIdxPadTop - 1;
1494#if ALF_SINGLE_FILTER_SHAPE
1495          pImgPad1 = (paddingLine < 1) ? pImgPad : pImgPad + min(paddingLine, 1)*stride;
1496          pImgPad2 = (paddingLine < 1) ? pImgPad : pImgPad -   stride;
1497          pImgPad3 = (paddingLine < 2) ? pImgPad : pImgPad + min(paddingLine, 2)*stride;
1498          pImgPad4 = (paddingLine < 2) ? pImgPad : pImgPad - 2*stride;
1499          pImgPad5 = (paddingLine < 3) ? pImgPad : pImgPad + min(paddingLine, 3)*stride;
1500          pImgPad6 = (paddingLine < 3) ? pImgPad : pImgPad - 3*stride;
1501#else
1502          pImgPad1 = pImgPad + min(paddingLine, 1)*stride;
1503          pImgPad2 = pImgPad -   stride;
1504          pImgPad3 = pImgPad + min(paddingLine, 2)*stride;
1505          pImgPad4 = pImgPad - 2*stride;
1506          pImgPad5 = pImgPad + min(paddingLine, 3)*stride;
1507          pImgPad6 = pImgPad - 3*stride;
1508          pImgPad7 = pImgPad + min(paddingLine, 4)*stride;
1509          pImgPad8 = pImgPad - 4*stride;
1510#endif
1511        }
1512        else
1513        {
1514          paddingLine = yLineInLCU - m_lineIdxPadTop ;
1515#if ALF_SINGLE_FILTER_SHAPE
1516          pImgPad1 = (paddingLine < 1) ? pImgPad : pImgPad +   stride;
1517          pImgPad2 = (paddingLine < 1) ? pImgPad : pImgPad - min(paddingLine, 1)*stride;
1518          pImgPad3 = (paddingLine < 2) ? pImgPad : pImgPad + 2*stride;
1519          pImgPad4 = (paddingLine < 2) ? pImgPad : pImgPad - min(paddingLine, 2)*stride;
1520          pImgPad5 = (paddingLine < 3) ? pImgPad : pImgPad + 3*stride;
1521          pImgPad6 = (paddingLine < 3) ? pImgPad : pImgPad - min(paddingLine, 3)*stride;
1522#else
1523          pImgPad1 = pImgPad + stride;
1524          pImgPad2 = pImgPad - min(paddingLine, 1)*stride;
1525          pImgPad3 = pImgPad + 2*stride;
1526          pImgPad4 = pImgPad - min(paddingLine, 2)*stride;
1527          pImgPad5 = pImgPad + 3*stride;
1528          pImgPad6 = pImgPad - min(paddingLine, 3)*stride;
1529          pImgPad7 = pImgPad + 4*stride;
1530          pImgPad8 = pImgPad - min(paddingLine, 4)*stride;
1531#endif
1532        } 
1533
1534        pVar = ppVarImg[i>>shiftHeight] + (xpos>>shiftWidth);
1535
1536#if ALF_SINGLE_FILTER_SHAPE
1537        {
1538          for(j= xpos; j<= xposEnd ; j++)
1539          {
1540            if (j % VAR_SIZE_W==0) 
1541            {
1542              coef = filterSet[mergeTable[*(pVar++)]];
1543            }
1544
1545            pixelInt  = 0;
1546
1547            pixelInt += coef[0]* (pImgPad5[j]+pImgPad6[j]);
1548            pixelInt += coef[1]* (pImgPad3[j]+pImgPad4[j]);
1549            pixelInt += coef[2]* (pImgPad1[j-1]+pImgPad2[j+1]);
1550            pixelInt += coef[3]* (pImgPad1[j]+pImgPad2[j]);
1551            pixelInt += coef[4]* (pImgPad1[j+1]+pImgPad2[j-1]);
1552            pixelInt += coef[5]* (pImgPad[j+4]+pImgPad[j-4]);
1553            pixelInt += coef[6]* (pImgPad[j+3]+pImgPad[j-3]);
1554            pixelInt += coef[7]* (pImgPad[j+2]+pImgPad[j-2]);
1555            pixelInt += coef[8]* (pImgPad[j+1]+pImgPad[j-1]);
1556            pixelInt += coef[9]* (pImgPad[]);
1557
1558            pixelInt=(Int)((pixelInt+offset) >> numBitsMinus1);
1559            pImgRes[j] = Clip( pixelInt );
1560          }
1561        }
1562#else
1563        if ( (yLineInLCU == m_lineIdxPadTop || yLineInLCU == m_lineIdxPadTop-1) && i-yLineInLCU+m_lcuHeight < m_img_height ) 
1564        {
1565          for(j= xpos; j<= xposEnd ; j++)
1566          {
1567            if (j % VAR_SIZE_W==0) 
1568            {
1569              varInd = *(pVar++);
1570              coef = filterSet[mergeTable[varInd]];
1571            }
1572
1573            pixelInt  = 0;
1574
1575            pixelInt += coef[4]* (pImgPad[j+4]+pImgPad[j-4]);
1576            pixelInt += coef[5]* (pImgPad[j+3]+pImgPad[j-3]);
1577            pixelInt += coef[6]* (pImgPad[j+2]+pImgPad[j-2]);
1578            pixelInt += coef[7]* (pImgPad[j+1]+pImgPad[j-1]);
1579            pixelInt += newCenterCoeff[0][mergeTable[varInd]]* (pImgPad[j]);
1580
1581            pixelInt=(int)((pixelInt+offset) >> numBitsMinus1);
1582            pImgRes[j] = Clip( pixelInt );
1583          }
1584        }
1585        else if ( (yLineInLCU == m_lineIdxPadTop+1 || yLineInLCU == m_lineIdxPadTop-2) && i-yLineInLCU+m_lcuHeight < m_img_height ) 
1586        {
1587          for(j= xpos; j<= xposEnd ; j++)
1588          {
1589            if (j % VAR_SIZE_W==0) 
1590            {
1591              varInd = *(pVar++);
1592              coef = filterSet[mergeTable[varInd]];
1593            }
1594
1595            pixelInt  = 0;
1596
1597            pixelInt += coef[3]* (pImgPad1[j]+pImgPad2[j]);
1598
1599            pixelInt += coef[4]* (pImgPad[j+4]+pImgPad[j-4]);
1600            pixelInt += coef[5]* (pImgPad[j+3]+pImgPad[j-3]);
1601            pixelInt += coef[6]* (pImgPad[j+2]+pImgPad[j-2]);
1602            pixelInt += coef[7]* (pImgPad[j+1]+pImgPad[j-1]);
1603            pixelInt += newCenterCoeff[1][mergeTable[varInd]]* (pImgPad[j]);
1604
1605            pixelInt=(int)((pixelInt+offset) >> numBitsMinus1);
1606            pImgRes[j] = Clip( pixelInt );
1607          }
1608        }
1609        else if ( (yLineInLCU == m_lineIdxPadTop+2 || yLineInLCU == m_lineIdxPadTop-3) && i-yLineInLCU+m_lcuHeight < m_img_height ) 
1610        {
1611          for(j= xpos; j<= xposEnd ; j++)
1612          {
1613            if (j % VAR_SIZE_W==0) 
1614            {
1615              varInd = *(pVar++);
1616              coef = filterSet[mergeTable[varInd]];
1617            }
1618
1619            pixelInt  = 0;
1620
1621            pixelInt += coef[2]* (pImgPad3[j]+pImgPad4[j]);
1622
1623            pixelInt += coef[3]* (pImgPad1[j]+pImgPad2[j]);
1624
1625            pixelInt += coef[4]* (pImgPad[j+4]+pImgPad[j-4]);
1626            pixelInt += coef[5]* (pImgPad[j+3]+pImgPad[j-3]);
1627            pixelInt += coef[6]* (pImgPad[j+2]+pImgPad[j-2]);
1628            pixelInt += coef[7]* (pImgPad[j+1]+pImgPad[j-1]);
1629            pixelInt += newCenterCoeff[2][mergeTable[varInd]]* (pImgPad[]);
1630
1631            pixelInt=(int)((pixelInt+offset) >> numBitsMinus1);
1632            pImgRes[j] = Clip( pixelInt );
1633          }
1634        }
1635        else if ( (yLineInLCU == m_lineIdxPadTop+3 || yLineInLCU == m_lineIdxPadTop-4) && i-yLineInLCU+m_lcuHeight < m_img_height ) 
1636        {
1637          for(j= xpos; j<= xposEnd ; j++)
1638          {
1639            if (j % VAR_SIZE_W==0) 
1640            {
1641              varInd = *(pVar++);
1642              coef = filterSet[mergeTable[varInd]];
1643            }
1644
1645            pixelInt  = 0;
1646
1647            pixelInt += coef[1]* (pImgPad5[j]+pImgPad6[j]);
1648
1649            pixelInt += coef[2]* (pImgPad3[j]+pImgPad4[j]);
1650
1651            pixelInt += coef[3]* (pImgPad1[j]+pImgPad2[j]);
1652
1653            pixelInt += coef[4]* (pImgPad[j+4]+pImgPad[j-4]);
1654            pixelInt += coef[5]* (pImgPad[j+3]+pImgPad[j-3]);
1655            pixelInt += coef[6]* (pImgPad[j+2]+pImgPad[j-2]);
1656            pixelInt += coef[7]* (pImgPad[j+1]+pImgPad[j-1]);
1657            pixelInt += newCenterCoeff[3][mergeTable[varInd]]* (pImgPad[]);
1658
1659            pixelInt=(int)((pixelInt+offset) >> numBitsMinus1);
1660            pImgRes[j] = Clip( pixelInt );
1661          }
1662        }
1663        else
1664        {
1665          for(j= xpos; j<= xposEnd ; j++)
1666          {
1667            if (j % VAR_SIZE_W==0) 
1668            {
1669              coef = filterSet[mergeTable[*(pVar++)]];
1670            }
1671
1672            pixelInt  = 0;
1673
1674            pixelInt += coef[0]* (pImgPad7[j]+pImgPad8[j]);
1675
1676            pixelInt += coef[1]* (pImgPad5[j]+pImgPad6[j]);
1677
1678            pixelInt += coef[2]* (pImgPad3[j]+pImgPad4[j]);
1679
1680            pixelInt += coef[3]* (pImgPad1[j]+pImgPad2[j]);
1681
1682            pixelInt += coef[4]* (pImgPad[j+4]+pImgPad[j-4]);
1683            pixelInt += coef[5]* (pImgPad[j+3]+pImgPad[j-3]);
1684            pixelInt += coef[6]* (pImgPad[j+2]+pImgPad[j-2]);
1685            pixelInt += coef[7]* (pImgPad[j+1]+pImgPad[j-1]);
1686            pixelInt += coef[8]* (pImgPad[]);
1687
1688            pixelInt=(Int)((pixelInt+offset) >> numBitsMinus1);
1689            pImgRes[j] = Clip( pixelInt );
1690          }
1691        }
1692#endif
1693        pImgPad += stride;
1694        pImgRes += stride;
1695      }
1696    }
1697    break;
1698  default:
1699    {
1700      printf("Not a supported filter shape\n");
1701      assert(0);
1702      exit(1);
1703    }
1704  }
1705}
1706
1707
1708
1709Void TComAdaptiveLoopFilter::xCUAdaptive(TComPic* pcPic, Int filtNo, Pel *imgYFilt, Pel *imgYRec, Int Stride)
1710{
1711  // for every CU, call CU-adaptive ALF process
1712  for( UInt uiCUAddr = 0; uiCUAddr < pcPic->getNumCUsInFrame() ; uiCUAddr++ )
1713  {
1714    TComDataCU* pcCU = pcPic->getCU( uiCUAddr );
1715    xSubCUAdaptive(pcCU, filtNo, imgYFilt, imgYRec, 0, 0, Stride);
1716  }
1717}
1718
1719Void TComAdaptiveLoopFilter::xSubCUAdaptive(TComDataCU* pcCU, Int filtNo, Pel *imgYFilt, Pel *imgYRec, UInt uiAbsPartIdx, UInt uiDepth, Int Stride)
1720{
1721  TComPic* pcPic = pcCU->getPic();
1722
1723  if(pcPic==NULL)
1724  {
1725    return;
1726  }
1727  Bool bBoundary = false;
1728  UInt uiLPelX   = pcCU->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiAbsPartIdx] ];
1729  UInt uiRPelX   = uiLPelX + (g_uiMaxCUWidth>>uiDepth)  - 1;
1730  UInt uiTPelY   = pcCU->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiAbsPartIdx] ];
1731  UInt uiBPelY   = uiTPelY + (g_uiMaxCUHeight>>uiDepth) - 1;
1732
1733  // check picture boundary
1734  if ( ( uiRPelX >= m_img_width ) || ( uiBPelY >= m_img_height ) )
1735  {
1736    bBoundary = true;
1737  }
1738
1739  if ( ( ( uiDepth < pcCU->getDepth( uiAbsPartIdx ) ) && ( uiDepth < (g_uiMaxCUDepth-g_uiAddCUDepth) ) ) || bBoundary )
1740  {
1741    UInt uiQNumParts = ( pcPic->getNumPartInCU() >> (uiDepth<<1) )>>2;
1742    for ( UInt uiPartUnitIdx = 0; uiPartUnitIdx < 4; uiPartUnitIdx++, uiAbsPartIdx+=uiQNumParts )
1743    {
1744      uiLPelX   = pcCU->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiAbsPartIdx] ];
1745      uiTPelY   = pcCU->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiAbsPartIdx] ];
1746
1747      if( ( uiLPelX < m_img_width ) && ( uiTPelY < m_img_height ) )
1748        xSubCUAdaptive(pcCU, filtNo, imgYFilt, imgYRec, uiAbsPartIdx, uiDepth+1, Stride);
1749    }
1750    return;
1751  }
1752
1753  if ( pcCU->getAlfCtrlFlag(uiAbsPartIdx) )
1754  {
1755    filterLuma(imgYFilt, imgYRec, Stride, uiTPelY, min(uiBPelY,(unsigned int)(m_img_height-1)), uiLPelX, min(uiRPelX,(unsigned int)(m_img_width-1))
1756      ,filtNo, m_filterCoeffSym, m_varIndTab, m_varImg);
1757  }
1758}
1759
1760/** Predict ALF luma filter coefficients. Centre coefficient is always predicted. Left neighbour is predicted according to flag.
1761 */
1762Void TComAdaptiveLoopFilter::predictALFCoeffLuma(ALFParam* pcAlfParam)
1763{
1764  Int sum, coeffPred, ind;
1765  const Int* pFiltMag = NULL;
1766  pFiltMag = weightsTabShapes[pcAlfParam->filter_shape];
1767  for(ind = 0; ind < pcAlfParam->filters_per_group; ++ind)
1768  {
1769    sum = 0;
1770    for(Int i = 0; i < pcAlfParam->num_coeff-2; i++)
1771    {
1772      sum +=  pFiltMag[i]*pcAlfParam->coeffmulti[ind][i];
1773    }
1774    if(pcAlfParam->nbSPred[ind]==0)
1775    {
1776      if((pcAlfParam->predMethod==0)|(ind==0))
1777      {
1778        coeffPred = ((1<<ALF_NUM_BIT_SHIFT)-sum) >> 2;
1779      }
1780      else
1781      {
1782        coeffPred = (0-sum) >> 2;
1783      }
1784      pcAlfParam->coeffmulti[ind][pcAlfParam->num_coeff-2] = coeffPred + pcAlfParam->coeffmulti[ind][pcAlfParam->num_coeff-2];
1785    }
1786    sum += pFiltMag[pcAlfParam->num_coeff-2]*pcAlfParam->coeffmulti[ind][pcAlfParam->num_coeff-2];
1787    if((pcAlfParam->predMethod==0)|(ind==0))
1788    {
1789      coeffPred = (1<<ALF_NUM_BIT_SHIFT)-sum;
1790    }
1791    else
1792    {
1793      coeffPred = -sum;
1794    }
1795    pcAlfParam->coeffmulti[ind][pcAlfParam->num_coeff-1] = coeffPred + pcAlfParam->coeffmulti[ind][pcAlfParam->num_coeff-1];
1796  }
1797}
1798
1799Void TComAdaptiveLoopFilter::reconstructFilterCoeffs(ALFParam* pcAlfParam,int **pfilterCoeffSym)
1800{
1801  int i, ind;
1802
1803  // Copy non zero filters in filterCoeffTmp
1804  for(ind = 0; ind < pcAlfParam->filters_per_group; ++ind)
1805  {
1806    for(i = 0; i < pcAlfParam->num_coeff; i++)
1807    {
1808      pfilterCoeffSym[ind][i] = pcAlfParam->coeffmulti[ind][i];
1809    }
1810  }
1811  // Undo prediction
1812  for(ind = 1; ind < pcAlfParam->filters_per_group; ++ind)
1813  {
1814    if(pcAlfParam->predMethod)
1815    {
1816      // Prediction
1817      for(i = 0; i < pcAlfParam->num_coeff; ++i)
1818      {
1819        pfilterCoeffSym[ind][i] = (int)(pfilterCoeffSym[ind][i] + pfilterCoeffSym[ind - 1][i]);
1820      }
1821    }
1822  }
1823
1824  for(ind = 0; ind < pcAlfParam->filters_per_group; ind++)
1825  {
1826    checkFilterCoeffValue(pfilterCoeffSym[ind], pcAlfParam->num_coeff, false );
1827  }
1828}
1829
1830
1831#endif
1832
1833static Pel Clip_post(int high, int val)
1834{
1835  return (Pel)(((val > high)? high: val));
1836}
1837
1838#if !LCU_SYNTAX_ALF
1839
1840/** Calculate ALF grouping indices for block-based (BA) mode
1841 * \param [out] imgYvar grouping indices buffer
1842 * \param [in] imgYpad picture buffer
1843 * \param [in] stride picture stride size
1844 * \param [in] adaptationMode  ALF_BA or ALF_RA mode
1845 */
1846Void TComAdaptiveLoopFilter::calcVar(Pel **imgYvar, Pel *imgYpad, Int stride, Int adaptationMode)
1847{
1848  if(adaptationMode == ALF_RA) 
1849  {
1850    return;
1851  }
1852  static Int shiftH = (Int)(log((double)VAR_SIZE_H)/log(2.0));
1853  static Int shiftW = (Int)(log((double)VAR_SIZE_W)/log(2.0));
1854  static Int varmax = (Int)NO_VAR_BINS-1;
1855#if ALF_16_BA_GROUPS
1856  static Int th[NO_VAR_BINS] = {0, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5}; 
1857  static Int avgVarTab[3][6] = { {0,  1,  2,  3,  4,  5,},
1858  {0,  6,  7,  8,  9, 10,},
1859  {0, 11, 12, 13, 14, 15}   };
1860#else
1861  static Int step1  = (Int)((Int)(NO_VAR_BINS)/3) - 1; 
1862  static Int th[NO_VAR_BINS] = {0, 1, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4}; 
1863#endif 
1864  Int i, j, avgvar, vertical, horizontal,direction, yoffset;
1865  Pel *pimgYpad, *pimgYpadup, *pimgYpaddown;
1866
1867  for(i = 0; i < m_img_height - 3; i=i+4)
1868  {
1869    yoffset      = ((i)*stride) + stride;
1870    pimgYpad     = &imgYpad [yoffset];
1871    pimgYpadup   = &imgYpad [yoffset + stride];
1872    pimgYpaddown = &imgYpad [yoffset - stride];
1873
1874    for(j = 0; j < m_img_width - 3 ; j=j+4)
1875    {
1876      // Compute at sub-sample by 2
1877      vertical   =  abs((pimgYpad[j+1]<<1  ) - pimgYpaddown[j+1]   - pimgYpadup[j+1]);
1878      horizontal =  abs((pimgYpad[j+1]<<1  ) - pimgYpad    [j+2]   - pimgYpad  []);
1879
1880      vertical   += abs((pimgYpad[j+2]<<1  ) - pimgYpaddown[j+2]   - pimgYpadup[j+2]);
1881      horizontal += abs((pimgYpad[j+2]<<1  ) - pimgYpad    [j+3]   - pimgYpad  [j+1]);
1882
1883      vertical   += abs((pimgYpad[j+1+stride]<<1) - pimgYpaddown[j+1+stride] - pimgYpadup[j+1+stride]);
1884      horizontal += abs((pimgYpad[j+1+stride]<<1) - pimgYpad    [j+2+stride] - pimgYpad  [j+stride  ]);
1885
1886      vertical   += abs((pimgYpad[j+2+stride]<<1) - pimgYpaddown[j+2+stride] - pimgYpadup[j+2+stride]);
1887      horizontal += abs((pimgYpad[j+2+stride]<<1) - pimgYpad    [j+3+stride] - pimgYpad  [j+1+stride]);
1888
1889      direction = 0;
1890      if (vertical > 2*horizontal) 
1891      {
1892        direction = 1; //vertical
1893      }
1894      if (horizontal > 2*vertical)
1895      {
1896        direction = 2; //horizontal
1897      }
1898
1899      avgvar = (vertical + horizontal) >> 2;
1900      avgvar = (Pel) Clip_post(varmax, avgvar >>(g_uiBitIncrement+1));
1901      avgvar = th[avgvar];
1902#if ALF_16_BA_GROUPS
1903      avgvar = avgVarTab[direction][avgvar];
1904#else     
1905      avgvar = Clip_post(step1, (Int) avgvar ) + (step1+1)*direction;
1906#endif
1907      imgYvar[(i )>>shiftH][(j)>>shiftW] = avgvar;
1908    }
1909  }
1910}
1911
1912Void TComAdaptiveLoopFilter::createRegionIndexMap(Pel **imgYVar, Int imgWidth, Int imgHeight)
1913{
1914  int varStepSizeWidth = VAR_SIZE_W;
1915  int varStepSizeHeight = VAR_SIZE_H;
1916  int shiftHeight = (int)(log((double)varStepSizeHeight)/log(2.0));
1917  int shiftWidth = (int)(log((double)varStepSizeWidth)/log(2.0));
1918
1919  int i, j;
1920  int regionTable[NO_VAR_BINS] = {0, 1, 4, 5, 15, 2, 3, 6, 14, 11, 10, 7, 13, 12,  9,  8}; 
1921  int xInterval;
1922  int yInterval;
1923  int yIndex;
1924  int yIndexOffset;
1925  int yStartLine;
1926  int yEndLine;
1927
1928  xInterval = ((( (imgWidth+63)/64) + 1) / 4 * 64)>>shiftWidth; 
1929  yInterval = ((((imgHeight+63)/64) + 1) / 4 * 64)>>shiftHeight;
1930
1931  for (yIndex = 0; yIndex < 4 ; yIndex++)
1932  {
1933    yIndexOffset = yIndex * 4;
1934    yStartLine = yIndex * yInterval;
1935    yEndLine   = (yIndex == 3) ? imgHeight>>shiftHeight : (yStartLine+yInterval);
1936
1937    for(i = yStartLine; i < yEndLine ; i++)
1938    {
1939      for(j = 0; j < xInterval ; j++)
1940      {
1941        imgYVar[i][j] = regionTable[yIndexOffset+0];     
1942      }
1943
1944      for(j = xInterval; j < xInterval*2 ; j++)
1945      {
1946        imgYVar[i][j] = regionTable[yIndexOffset+1];     
1947      }
1948
1949      for(j = xInterval*2; j < xInterval*3 ; j++)
1950      {
1951        imgYVar[i][j] = regionTable[yIndexOffset+2];     
1952      }
1953
1954      for(j = xInterval*3; j < imgWidth>>shiftWidth ; j++)
1955      {
1956        imgYVar[i][j] = regionTable[yIndexOffset+3];     
1957      }
1958    }
1959  }
1960
1961}
1962
1963// --------------------------------------------------------------------------------------------------------------------
1964// ALF for chroma
1965// --------------------------------------------------------------------------------------------------------------------
1966
1967/**
1968 \param pcPicDec    picture before ALF
1969 \param pcPicRest   picture after  ALF
1970 \param qh          filter coefficient
1971 \param iTap        filter tap
1972 \param iColor      0 for Cb and 1 for Cr
1973 */
1974Void TComAdaptiveLoopFilter::filterChroma(Pel *pImgRes, Pel *pImgPad, Int stride, 
1975                                          Int ypos, Int yposEnd, Int xpos, Int xposEnd, 
1976                                          Int filtNo, Int* coef)
1977{
1978  static Int numBitsMinus1= (Int)ALF_NUM_BIT_SHIFT;
1979  static Int offset       = (1<<( (Int)ALF_NUM_BIT_SHIFT-1));
1980
1981  Pel *pImgPad1,*pImgPad2,*pImgPad3,*pImgPad4;
1982  Int i, j, pixelInt;
1983
1984  pImgPad    += (ypos*stride);
1985  pImgRes    += (ypos*stride);
1986
1987  Int imgHeightChroma = m_img_height>>1;
1988  Int yLineInLCU;
1989  Int paddingline;
1990  Int newCenterCoeff[4];
1991
1992  ::memset(newCenterCoeff, 0, sizeof(Int)*4);
1993#if ALF_SINGLE_FILTER_SHAPE
1994  if(filtNo == ALF_CROSS9x7_SQUARE3x3)
1995#else
1996  if (filtNo == ALF_CROSS9x9)
1997#endif
1998  {
1999    //VB line 1
2000    newCenterCoeff[0] = coef[8] + ((coef[0] + coef[1] + coef[2] + coef[3])<<1);
2001    //VB line 2
2002    newCenterCoeff[1] = coef[8] + ((coef[0] + coef[1] + coef[2])<<1);
2003    //VB line 3
2004    newCenterCoeff[2] = coef[8] + ((coef[0] + coef[1])<<1);
2005    //VB line 4
2006    newCenterCoeff[3] = coef[8] + ((coef[0])<<1);
2007  }
2008
2009  switch(filtNo)
2010  {
2011#if !ALF_SINGLE_FILTER_SHAPE
2012  case ALF_STAR5x5:
2013    {
2014      for(i= ypos; i<= yposEnd; i++)
2015      {
2016        yLineInLCU = i % m_lcuHeightChroma;
2017
2018        if (yLineInLCU < m_lineIdxPadBotChroma || i-yLineInLCU+m_lcuHeightChroma >= imgHeightChroma )
2019        {
2020          pImgPad1 = pImgPad + stride;
2021          pImgPad2 = pImgPad - stride;
2022          pImgPad3 = pImgPad + 2*stride;
2023          pImgPad4 = pImgPad - 2*stride;
2024        }
2025        else if (yLineInLCU < m_lineIdxPadTopChroma)
2026        {
2027          paddingline = - yLineInLCU + m_lineIdxPadTopChroma - 1;
2028          pImgPad1 = pImgPad + min(paddingline, 1)*stride;
2029          pImgPad2 = pImgPad - stride;
2030          pImgPad3 = pImgPad + min(paddingline, 2)*stride;
2031          pImgPad4 = pImgPad - 2*stride;
2032        }
2033        else
2034        {
2035          paddingline = yLineInLCU - m_lineIdxPadTopChroma ;
2036          pImgPad1 = pImgPad + stride;
2037          pImgPad2 = pImgPad - min(paddingline, 1)*stride;
2038          pImgPad3 = pImgPad + 2*stride;
2039          pImgPad4 = pImgPad - min(paddingline, 2)*stride;
2040        }
2041
2042        if ( (yLineInLCU == m_lineIdxPadTopChroma || yLineInLCU == m_lineIdxPadTopChroma-1) && i-yLineInLCU+m_lcuHeightChroma < imgHeightChroma ) 
2043        {
2044          for(j= xpos; j<= xposEnd ; j++)
2045          {
2046            pImgRes[j] = pImgPad[j];
2047          }
2048        }
2049        else if ( (yLineInLCU == m_lineIdxPadTopChroma+1 || yLineInLCU == m_lineIdxPadTopChroma-2) && i-yLineInLCU+m_lcuHeightChroma < imgHeightChroma ) 
2050        {
2051          for(j= xpos; j<= xposEnd ; j++)
2052          {
2053            pixelInt  = 0;
2054
2055            pixelInt += coef[0]* (pImgPad3[j+2]+pImgPad4[j-2]);
2056            pixelInt += coef[1]* (pImgPad3[]+pImgPad4[]);
2057            pixelInt += coef[2]* (pImgPad3[j-2]+pImgPad4[j+2]);
2058
2059            pixelInt += coef[3]* (pImgPad1[j+1]+pImgPad2[j-1]);
2060            pixelInt += coef[4]* (pImgPad1[]+pImgPad2[]);
2061            pixelInt += coef[5]* (pImgPad1[j-1]+pImgPad2[j+1]);
2062
2063            pixelInt += coef[6]* (pImgPad[j+2]+pImgPad[j-2]);
2064            pixelInt += coef[7]* (pImgPad[j+1]+pImgPad[j-1]);
2065            pixelInt += coef[8]* (pImgPad[]);
2066
2067            pixelInt=(Int)((pixelInt+offset) >> numBitsMinus1);
2068
2069            pImgRes[j] = (Clip( pixelInt ) + pImgPad[j]) >> 1;
2070          }
2071        }
2072        else
2073        {
2074
2075        for(j= xpos; j<= xposEnd ; j++)
2076        {
2077          pixelInt  = 0;
2078
2079          pixelInt += coef[0]* (pImgPad3[j+2]+pImgPad4[j-2]);
2080          pixelInt += coef[1]* (pImgPad3[]+pImgPad4[]);
2081          pixelInt += coef[2]* (pImgPad3[j-2]+pImgPad4[j+2]);
2082
2083          pixelInt += coef[3]* (pImgPad1[j+1]+pImgPad2[j-1]);
2084          pixelInt += coef[4]* (pImgPad1[]+pImgPad2[]);
2085          pixelInt += coef[5]* (pImgPad1[j-1]+pImgPad2[j+1]);
2086
2087          pixelInt += coef[6]* (pImgPad[j+2]+pImgPad[j-2]);
2088          pixelInt += coef[7]* (pImgPad[j+1]+pImgPad[j-1]);
2089          pixelInt += coef[8]* (pImgPad[]);
2090
2091          pixelInt=(Int)((pixelInt+offset) >> numBitsMinus1);
2092
2093          pImgRes[j] = Clip( pixelInt );
2094        }
2095
2096        }
2097        pImgPad += stride;
2098        pImgRes += stride;
2099      }
2100    }
2101    break;
2102  case ALF_CROSS9x9:
2103    {
2104      Pel *pImgPad5, *pImgPad6, *pImgPad7, *pImgPad8;
2105#else
2106  case ALF_CROSS9x7_SQUARE3x3:
2107    {
2108      Pel *pImgPad5, *pImgPad6;
2109#endif
2110      for(i= ypos; i<= yposEnd; i++)
2111      {
2112        yLineInLCU = i % m_lcuHeightChroma;
2113#if ALF_SINGLE_FILTER_SHAPE
2114        if (yLineInLCU<2 && i> 2)
2115#else
2116        if (yLineInLCU<2)
2117#endif
2118        {
2119          paddingline = yLineInLCU + 2 ;
2120          pImgPad1 = pImgPad + stride;
2121          pImgPad2 = pImgPad - stride;
2122          pImgPad3 = pImgPad + 2*stride;
2123          pImgPad4 = pImgPad - 2*stride;
2124#if ALF_SINGLE_FILTER_SHAPE
2125          pImgPad5 = (paddingline < 3) ? pImgPad : pImgPad + 3*stride;
2126          pImgPad6 = (paddingline < 3) ? pImgPad : pImgPad - min(paddingline, 3)*stride; 
2127#else
2128          pImgPad5 = pImgPad + 3*stride;
2129          pImgPad6 = pImgPad - min(paddingline, 3)*stride;
2130          pImgPad7 = pImgPad + 4*stride;
2131          pImgPad8 = pImgPad - min(paddingline, 4)*stride;
2132#endif
2133        }
2134        else if (yLineInLCU < m_lineIdxPadBotChroma || i-yLineInLCU+m_lcuHeightChroma >= imgHeightChroma )
2135        {
2136          pImgPad1 = pImgPad + stride;
2137          pImgPad2 = pImgPad - stride;
2138          pImgPad3 = pImgPad + 2*stride;
2139          pImgPad4 = pImgPad - 2*stride;
2140          pImgPad5 = pImgPad + 3*stride;
2141          pImgPad6 = pImgPad - 3*stride;
2142#if !ALF_SINGLE_FILTER_SHAPE
2143          pImgPad7 = pImgPad + 4*stride;
2144          pImgPad8 = pImgPad - 4*stride;
2145#endif
2146        }
2147        else if (yLineInLCU < m_lineIdxPadTopChroma)
2148        {
2149          paddingline = - yLineInLCU + m_lineIdxPadTopChroma - 1;
2150#if ALF_SINGLE_FILTER_SHAPE
2151          pImgPad1 = (paddingline < 1) ? pImgPad : pImgPad + min(paddingline, 1)*stride;
2152          pImgPad2 = (paddingline < 1) ? pImgPad : pImgPad -   stride;
2153          pImgPad3 = (paddingline < 2) ? pImgPad : pImgPad + min(paddingline, 2)*stride;
2154          pImgPad4 = (paddingline < 2) ? pImgPad : pImgPad - 2*stride;
2155          pImgPad5 = (paddingline < 3) ? pImgPad : pImgPad + min(paddingline, 3)*stride;
2156          pImgPad6 = (paddingline < 3) ? pImgPad : pImgPad - 3*stride;
2157#else
2158          pImgPad1 = pImgPad + min(paddingline, 1)*stride;
2159          pImgPad2 = pImgPad - stride;
2160          pImgPad3 = pImgPad + min(paddingline, 2)*stride;
2161          pImgPad4 = pImgPad - 2*stride;
2162          pImgPad5 = pImgPad + min(paddingline, 3)*stride;
2163          pImgPad6 = pImgPad - 3*stride;
2164          pImgPad7 = pImgPad + min(paddingline, 4)*stride;
2165          pImgPad8 = pImgPad - 4*stride;
2166#endif
2167        }
2168        else
2169        {
2170          paddingline = yLineInLCU - m_lineIdxPadTopChroma ;
2171#if ALF_SINGLE_FILTER_SHAPE
2172          pImgPad1 = (paddingline < 1) ? pImgPad : pImgPad +   stride;
2173          pImgPad2 = (paddingline < 1) ? pImgPad : pImgPad - min(paddingline, 1)*stride;
2174          pImgPad3 = (paddingline < 2) ? pImgPad : pImgPad + 2*stride;
2175          pImgPad4 = (paddingline < 2) ? pImgPad : pImgPad - min(paddingline, 2)*stride;
2176          pImgPad5 = (paddingline < 3) ? pImgPad : pImgPad + 3*stride;
2177          pImgPad6 = (paddingline < 3) ? pImgPad : pImgPad - min(paddingline, 3)*stride;
2178#else
2179          pImgPad1 = pImgPad + stride;
2180          pImgPad2 = pImgPad - min(paddingline, 1)*stride;
2181          pImgPad3 = pImgPad + 2*stride;
2182          pImgPad4 = pImgPad - min(paddingline, 2)*stride;
2183          pImgPad5 = pImgPad + 3*stride;
2184          pImgPad6 = pImgPad - min(paddingline, 3)*stride;
2185          pImgPad7 = pImgPad + 4*stride;
2186          pImgPad8 = pImgPad - min(paddingline, 4)*stride;
2187#endif
2188        }
2189
2190#if ALF_SINGLE_FILTER_SHAPE
2191          for(j= xpos; j<= xposEnd ; j++)
2192          {
2193            pixelInt  = 0;
2194
2195            pixelInt += coef[0]* (pImgPad5[j]+pImgPad6[j]);
2196            pixelInt += coef[1]* (pImgPad3[j]+pImgPad4[j]);
2197            pixelInt += coef[2]* (pImgPad1[j-1]+pImgPad2[j+1]);
2198            pixelInt += coef[3]* (pImgPad1[j]+pImgPad2[j]);
2199            pixelInt += coef[4]* (pImgPad1[j+1]+pImgPad2[j-1]);
2200            pixelInt += coef[5]* (pImgPad[j+4]+pImgPad[j-4]);
2201            pixelInt += coef[6]* (pImgPad[j+3]+pImgPad[j-3]);
2202            pixelInt += coef[7]* (pImgPad[j+2]+pImgPad[j-2]);
2203            pixelInt += coef[8]* (pImgPad[j+1]+pImgPad[j-1]);
2204            pixelInt += coef[9]* (pImgPad[]);
2205
2206            pixelInt=(Int)((pixelInt+offset) >> numBitsMinus1);
2207
2208            pImgRes[j] = Clip( pixelInt );
2209          }
2210#else
2211        if ( (yLineInLCU == m_lineIdxPadTopChroma || yLineInLCU == m_lineIdxPadTopChroma-1) && i-yLineInLCU+m_lcuHeightChroma < imgHeightChroma ) 
2212        {
2213          for(j= xpos; j<= xposEnd ; j++)
2214          {
2215            pixelInt  = 0;
2216
2217            pixelInt += coef[4]* (pImgPad[j+4]+pImgPad[j-4]);
2218            pixelInt += coef[5]* (pImgPad[j+3]+pImgPad[j-3]);
2219            pixelInt += coef[6]* (pImgPad[j+2]+pImgPad[j-2]);
2220            pixelInt += coef[7]* (pImgPad[j+1]+pImgPad[j-1]);
2221            pixelInt += newCenterCoeff[0]* (pImgPad[]);
2222
2223            pixelInt=(Int)((pixelInt+offset) >> numBitsMinus1);
2224
2225            pImgRes[j] = Clip( pixelInt );
2226          }
2227        }
2228        else if ( (yLineInLCU == m_lineIdxPadTopChroma+1 || yLineInLCU == m_lineIdxPadTopChroma-2) && i-yLineInLCU+m_lcuHeightChroma < imgHeightChroma ) 
2229        {
2230          for(j= xpos; j<= xposEnd ; j++)
2231          {
2232            pixelInt  = 0;
2233           
2234            pixelInt += coef[3]* (pImgPad1[j]+pImgPad2[j]);
2235
2236            pixelInt += coef[4]* (pImgPad[j+4]+pImgPad[j-4]);
2237            pixelInt += coef[5]* (pImgPad[j+3]+pImgPad[j-3]);
2238            pixelInt += coef[6]* (pImgPad[j+2]+pImgPad[j-2]);
2239            pixelInt += coef[7]* (pImgPad[j+1]+pImgPad[j-1]);
2240            pixelInt += newCenterCoeff[1]* (pImgPad[]);
2241
2242            pixelInt=(Int)((pixelInt+offset) >> numBitsMinus1);
2243
2244            pImgRes[j] = Clip( pixelInt );
2245          }
2246        }
2247        else if ( (yLineInLCU == 0 && i>0) || (yLineInLCU == m_lineIdxPadTopChroma-3 && i-yLineInLCU+m_lcuHeightChroma < imgHeightChroma) )
2248        {
2249          for(j= xpos; j<= xposEnd ; j++)
2250          {
2251            pixelInt  = 0;
2252
2253            pixelInt += coef[2]* (pImgPad3[j]+pImgPad4[j]);
2254
2255            pixelInt += coef[3]* (pImgPad1[j]+pImgPad2[j]);
2256
2257            pixelInt += coef[4]* (pImgPad[j+4]+pImgPad[j-4]);
2258            pixelInt += coef[5]* (pImgPad[j+3]+pImgPad[j-3]);
2259            pixelInt += coef[6]* (pImgPad[j+2]+pImgPad[j-2]);
2260            pixelInt += coef[7]* (pImgPad[j+1]+pImgPad[j-1]);
2261            pixelInt += newCenterCoeff[2]* (pImgPad[]);
2262
2263            pixelInt=(Int)((pixelInt+offset) >> numBitsMinus1);
2264
2265            pImgRes[j] = Clip( pixelInt );
2266          }
2267        }
2268        else if ( (yLineInLCU == 1 && i>1) || (yLineInLCU == m_lineIdxPadTopChroma-4 && i-yLineInLCU+m_lcuHeightChroma < imgHeightChroma) ) 
2269        {
2270          for(j= xpos; j<= xposEnd ; j++)
2271          {
2272            pixelInt  = 0;
2273
2274            pixelInt += coef[1]* (pImgPad5[j]+pImgPad6[j]);
2275
2276            pixelInt += coef[2]* (pImgPad3[j]+pImgPad4[j]);
2277
2278            pixelInt += coef[3]* (pImgPad1[j]+pImgPad2[j]);
2279
2280            pixelInt += coef[4]* (pImgPad[j+4]+pImgPad[j-4]);
2281            pixelInt += coef[5]* (pImgPad[j+3]+pImgPad[j-3]);
2282            pixelInt += coef[6]* (pImgPad[j+2]+pImgPad[j-2]);
2283            pixelInt += coef[7]* (pImgPad[j+1]+pImgPad[j-1]);
2284            pixelInt += newCenterCoeff[3]* (pImgPad[]);
2285
2286            pixelInt=(Int)((pixelInt+offset) >> numBitsMinus1);
2287
2288            pImgRes[j] = Clip( pixelInt );
2289          }
2290        }
2291        else
2292        {         
2293          for(j= xpos; j<= xposEnd ; j++)
2294          {
2295            pixelInt  = 0;
2296
2297            pixelInt += coef[0]* (pImgPad7[j]+pImgPad8[j]);
2298
2299            pixelInt += coef[1]* (pImgPad5[j]+pImgPad6[j]);
2300
2301            pixelInt += coef[2]* (pImgPad3[j]+pImgPad4[j]);
2302
2303            pixelInt += coef[3]* (pImgPad1[j]+pImgPad2[j]);
2304
2305            pixelInt += coef[4]* (pImgPad[j+4]+pImgPad[j-4]);
2306            pixelInt += coef[5]* (pImgPad[j+3]+pImgPad[j-3]);
2307            pixelInt += coef[6]* (pImgPad[j+2]+pImgPad[j-2]);
2308            pixelInt += coef[7]* (pImgPad[j+1]+pImgPad[j-1]);
2309            pixelInt += coef[8]* (pImgPad[]);
2310
2311            pixelInt=(Int)((pixelInt+offset) >> numBitsMinus1);
2312
2313            pImgRes[j] = Clip( pixelInt );
2314          }
2315        }
2316#endif
2317        pImgPad += stride;
2318        pImgRes += stride;
2319
2320      }
2321    }
2322
2323    break;
2324  default:
2325    {
2326      printf("Not a supported filter shape\n");
2327      assert(0);
2328      exit(1);
2329    }
2330  }
2331
2332}
2333
2334/** Chroma filtering for multi-slice picture
2335 * \param componentID slice parameters
2336 * \param pcPicDecYuv original picture
2337 * \param pcPicRestYuv picture before filtering
2338 * \param coeff filter coefficients
2339 * \param filtNo  filter shape
2340 * \param chromaFormatShift size adjustment for chroma (1 for 4:2:0 format)
2341 */
2342Void TComAdaptiveLoopFilter::xFilterChromaSlices(Int componentID, TComPicYuv* pcPicDecYuv, TComPicYuv* pcPicRestYuv, Int *coeff, Int filtNo, Int chromaFormatShift)
2343{
2344  Pel* pPicDec   = (componentID == ALF_Cb)?(    pcPicDecYuv->getCbAddr()):(    pcPicDecYuv->getCrAddr());
2345  Pel* pPicSlice = (componentID == ALF_Cb)?(m_pcSliceYuvTmp->getCbAddr()):(m_pcSliceYuvTmp->getCrAddr());
2346  Pel* pRest     = (componentID == ALF_Cb)?(   pcPicRestYuv->getCbAddr()):(   pcPicRestYuv->getCrAddr());
2347  Int  stride    = pcPicDecYuv->getCStride();
2348
2349  for(UInt s=0; s< m_uiNumSlicesInPic; s++)
2350  {
2351    if(!m_pcPic->getValidSlice(s))
2352    {
2353      continue;
2354    }
2355    std::vector< std::vector<AlfLCUInfo*> > & vpSliceTileAlfLCU = m_pvpSliceTileAlfLCU[s];
2356
2357    for(Int t=0; t< (Int)vpSliceTileAlfLCU.size(); t++)
2358    {
2359      std::vector<AlfLCUInfo*> & vpAlfLCU = vpSliceTileAlfLCU[t];
2360
2361      copyRegion(vpAlfLCU, pPicSlice, pPicDec, stride, chromaFormatShift);
2362      extendRegionBorder(vpAlfLCU, pPicSlice, stride, chromaFormatShift);
2363      filterChromaRegion(vpAlfLCU, pPicSlice, pRest, stride, coeff, filtNo, chromaFormatShift);
2364    }
2365  }
2366}
2367
2368/** Chroma filtering for one component in multi-slice picture
2369 * \param componentID slice parameters
2370 * \param pcPicDecYuv original picture
2371 * \param pcPicRestYuv picture before filtering
2372 * \param shape  filter shape
2373 * \param pCoeff filter coefficients
2374 */
2375Void TComAdaptiveLoopFilter::xFilterChromaOneCmp(Int componentID, TComPicYuv *pDecYuv, TComPicYuv *pRestYuv, Int shape, Int *pCoeff)
2376{
2377  Int chromaFormatShift = 1;
2378  if(!m_bUseNonCrossALF)
2379  {
2380    Pel* pDec    = (componentID == ALF_Cb)?(pDecYuv->getCbAddr()): (pDecYuv->getCrAddr());
2381    Pel* pRest   = (componentID == ALF_Cb)?(pRestYuv->getCbAddr()):(pRestYuv->getCrAddr());
2382    Int  iStride = pDecYuv->getCStride();
2383    filterChroma(pRest, pDec, iStride, 0, (Int)(m_img_height>>1) -1, 0, (Int)(m_img_width>>1)-1, shape, pCoeff);
2384  }
2385  else
2386  {
2387    xFilterChromaSlices(componentID, pDecYuv, pRestYuv, pCoeff, shape, chromaFormatShift);
2388  }
2389}
2390
2391/** Chroma filtering for  multi-slice picture
2392 * \param pcAlfParam ALF parameters
2393 * \param pcPicDec to-be-filtered picture buffer
2394 * \param pcPicRest filtered picture buffer
2395 */
2396Void TComAdaptiveLoopFilter::xALFChroma(ALFParam* pcAlfParam, TComPicYuv* pcPicDec, TComPicYuv* pcPicRest)
2397{
2398  if((pcAlfParam->chroma_idc>>1)&0x01)
2399  {
2400    xFilterChromaOneCmp(ALF_Cb, pcPicDec, pcPicRest, pcAlfParam->filter_shape_chroma, pcAlfParam->coeff_chroma);
2401  }
2402
2403  if(pcAlfParam->chroma_idc&0x01)
2404  {
2405    xFilterChromaOneCmp(ALF_Cr, pcPicDec, pcPicRest, pcAlfParam->filter_shape_chroma, pcAlfParam->coeff_chroma);
2406  }
2407}
2408
2409#endif
2410
2411Void TComAdaptiveLoopFilter::setAlfCtrlFlags(AlfCUCtrlInfo* pAlfParam, TComDataCU *pcCU, UInt uiAbsPartIdx, UInt uiDepth, UInt &idx)
2412{
2413  TComPic* pcPic = pcCU->getPic();
2414  UInt uiCurNumParts    = pcPic->getNumPartInCU() >> (uiDepth<<1);
2415  UInt uiQNumParts      = uiCurNumParts>>2;
2416 
2417  Bool bBoundary = false;
2418  UInt uiLPelX   = pcCU->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiAbsPartIdx] ];
2419  UInt uiRPelX   = uiLPelX + (g_uiMaxCUWidth>>uiDepth)  - 1;
2420  UInt uiTPelY   = pcCU->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiAbsPartIdx] ];
2421  UInt uiBPelY   = uiTPelY + (g_uiMaxCUHeight>>uiDepth) - 1;
2422 
2423  if( ( uiRPelX >= pcCU->getSlice()->getSPS()->getPicWidthInLumaSamples() ) || ( uiBPelY >= pcCU->getSlice()->getSPS()->getPicHeightInLumaSamples() ) )
2424  {
2425    bBoundary = true;
2426  }
2427 
2428  if( ( ( uiDepth < pcCU->getDepth( uiAbsPartIdx ) ) && ( uiDepth < g_uiMaxCUDepth - g_uiAddCUDepth ) ) || bBoundary )
2429  {
2430    UInt uiIdx = uiAbsPartIdx;
2431    for ( UInt uiPartUnitIdx = 0; uiPartUnitIdx < 4; uiPartUnitIdx++ )
2432    {
2433      uiLPelX   = pcCU->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiIdx] ];
2434      uiTPelY   = pcCU->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiIdx] ];
2435     
2436      if( ( uiLPelX < pcCU->getSlice()->getSPS()->getPicWidthInLumaSamples() ) && ( uiTPelY < pcCU->getSlice()->getSPS()->getPicHeightInLumaSamples() ) )
2437      {
2438        setAlfCtrlFlags(pAlfParam, pcCU, uiIdx, uiDepth+1, idx);
2439      }
2440      uiIdx += uiQNumParts;
2441    }
2442   
2443    return;
2444  }
2445 
2446  if( uiDepth <= pAlfParam->alf_max_depth || pcCU->isFirstAbsZorderIdxInDepth(uiAbsPartIdx, pAlfParam->alf_max_depth))
2447  {
2448    if (uiDepth > pAlfParam->alf_max_depth)
2449    {
2450      pcCU->setAlfCtrlFlagSubParts(pAlfParam->alf_cu_flag[idx], uiAbsPartIdx, pAlfParam->alf_max_depth);
2451    }
2452    else
2453    {
2454      pcCU->setAlfCtrlFlagSubParts(pAlfParam->alf_cu_flag[idx], uiAbsPartIdx, uiDepth );
2455    }
2456    idx++;
2457  }
2458}
2459
2460/** Initialize the variables for one ALF LCU
2461 * \param rAlfLCU to-be-initialized ALF LCU
2462 * \param sliceID slice index
2463 * \param tileID tile index
2464 * \param pcCU CU data pointer
2465 * \param maxNumSUInLCU maximum number of SUs in one LCU
2466 */
2467Void TComAdaptiveLoopFilter::InitAlfLCUInfo(AlfLCUInfo& rAlfLCU, Int sliceID, Int tileID, TComDataCU* pcCU, UInt maxNumSUInLCU)
2468{
2469  //pcCU
2470  rAlfLCU.pcCU     = pcCU;
2471  //sliceID
2472  rAlfLCU.sliceID = sliceID;
2473  //tileID
2474  rAlfLCU.tileID  = tileID;
2475
2476  //numSGU, vpAlfBLock;
2477  std::vector<NDBFBlockInfo>& vNDBFBlock = *(pcCU->getNDBFilterBlocks());
2478  rAlfLCU.vpAlfBlock.clear();
2479  rAlfLCU.numSGU = 0;
2480  for(Int i=0; i< vNDBFBlock.size(); i++)
2481  {
2482    if( vNDBFBlock[i].sliceID == sliceID)
2483    {
2484      rAlfLCU.vpAlfBlock.push_back( &(vNDBFBlock[i])  );
2485      rAlfLCU.numSGU ++;
2486    }
2487  }
2488  //startSU
2489  rAlfLCU.startSU = rAlfLCU.vpAlfBlock.front()->startSU;
2490  //endSU
2491  rAlfLCU.endSU   = rAlfLCU.vpAlfBlock.back()->endSU;
2492  //bAllSUsInLCUInSameSlice
2493  rAlfLCU.bAllSUsInLCUInSameSlice = (rAlfLCU.startSU == 0)&&( rAlfLCU.endSU == maxNumSUInLCU -1);
2494}
2495
2496/** create and initialize variables for picture ALF processing
2497 * \param pcPic picture-level data pointer
2498 * \param numSlicesInPic number of slices in picture
2499 */
2500#if LCU_SYNTAX_ALF
2501Void TComAdaptiveLoopFilter::createPicAlfInfo(TComPic* pcPic, Int numSlicesInPic, Int alfQP)
2502#else
2503Void TComAdaptiveLoopFilter::createPicAlfInfo(TComPic* pcPic, Int numSlicesInPic)
2504#endif
2505{
2506  m_uiNumSlicesInPic = numSlicesInPic;
2507  m_iSGDepth         = pcPic->getSliceGranularityForNDBFilter();
2508
2509  m_bUseNonCrossALF = ( pcPic->getIndependentSliceBoundaryForNDBFilter() || pcPic->getIndependentTileBoundaryForNDBFilter());
2510  m_pcPic = pcPic;
2511
2512#if LCU_SYNTAX_ALF
2513  m_isNonCrossSlice = pcPic->getIndependentSliceBoundaryForNDBFilter(); 
2514  m_suWidth = pcPic->getMinCUWidth();
2515  m_suHeight= pcPic->getMinCUHeight();
2516  m_alfQP = alfQP; 
2517#endif
2518#if !LCU_SYNTAX_ALF 
2519  if(m_uiNumSlicesInPic > 1 || m_bUseNonCrossALF)
2520  {
2521#endif
2522    m_ppSliceAlfLCUs = new AlfLCUInfo*[m_uiNumSlicesInPic];
2523    m_pvpAlfLCU = new std::vector< AlfLCUInfo* >[m_uiNumSlicesInPic];
2524    m_pvpSliceTileAlfLCU = new std::vector< std::vector< AlfLCUInfo* > >[m_uiNumSlicesInPic];
2525
2526    for(Int s=0; s< m_uiNumSlicesInPic; s++)
2527    {
2528      m_ppSliceAlfLCUs[s] = NULL;
2529      if(!pcPic->getValidSlice(s))
2530      {
2531        continue;
2532      }
2533
2534      std::vector< TComDataCU* >& vSliceLCUPointers = pcPic->getOneSliceCUDataForNDBFilter(s);
2535      Int                         numLCU           = (Int)vSliceLCUPointers.size();
2536
2537      //create Alf LCU info
2538      m_ppSliceAlfLCUs[s] = new AlfLCUInfo[numLCU];
2539      for(Int i=0; i< numLCU; i++)
2540      {
2541        TComDataCU* pcCU       = vSliceLCUPointers[i];
2542        if(pcCU->getPic()==0)
2543        {
2544          continue;
2545        }
2546        Int         currTileID = pcPic->getPicSym()->getTileIdxMap(pcCU->getAddr());
2547
2548        InitAlfLCUInfo(m_ppSliceAlfLCUs[s][i], s, currTileID, pcCU, pcPic->getNumPartInCU());
2549      }
2550
2551      //distribute Alf LCU info pointers to slice container
2552      std::vector< AlfLCUInfo* >&    vpSliceAlfLCU     = m_pvpAlfLCU[s]; 
2553      vpSliceAlfLCU.reserve(numLCU);
2554      vpSliceAlfLCU.resize(0);
2555      std::vector< std::vector< AlfLCUInfo* > > &vpSliceTileAlfLCU = m_pvpSliceTileAlfLCU[s];
2556      Int prevTileID = -1;
2557      Int numValidTilesInSlice = 0;
2558
2559      for(Int i=0; i< numLCU; i++)
2560      {
2561        AlfLCUInfo* pcAlfLCU = &(m_ppSliceAlfLCUs[s][i]);
2562
2563        //container of Alf LCU pointers for slice processing
2564        vpSliceAlfLCU.push_back( pcAlfLCU);
2565
2566        if(pcAlfLCU->tileID != prevTileID)
2567        {
2568          if(prevTileID == -1 || pcPic->getIndependentTileBoundaryForNDBFilter())
2569          {
2570            prevTileID = pcAlfLCU->tileID;
2571            numValidTilesInSlice ++;
2572            vpSliceTileAlfLCU.resize(numValidTilesInSlice);
2573          }
2574        }
2575        //container of Alf LCU pointers for tile processing
2576        vpSliceTileAlfLCU[numValidTilesInSlice-1].push_back(pcAlfLCU);
2577      }
2578
2579      assert( vpSliceAlfLCU.size() == numLCU);
2580    }
2581 
2582    if(m_bUseNonCrossALF)
2583    {
2584      m_pcSliceYuvTmp = pcPic->getYuvPicBufferForIndependentBoundaryProcessing();
2585    }
2586#if !LCU_SYNTAX_ALF
2587  }
2588#endif
2589
2590}
2591
2592/** Destroy ALF slice units
2593 */
2594Void TComAdaptiveLoopFilter::destroyPicAlfInfo()
2595{
2596#if !LCU_SYNTAX_ALF
2597  if(m_bUseNonCrossALF)
2598  {
2599#endif
2600    for(Int s=0; s< m_uiNumSlicesInPic; s++)
2601    {
2602      if(m_ppSliceAlfLCUs[s] != NULL)
2603      {
2604        delete[] m_ppSliceAlfLCUs[s];
2605        m_ppSliceAlfLCUs[s] = NULL;
2606      }
2607    }
2608    delete[] m_ppSliceAlfLCUs;
2609    m_ppSliceAlfLCUs = NULL;
2610
2611    delete[] m_pvpAlfLCU;
2612    m_pvpAlfLCU = NULL;
2613
2614    delete[] m_pvpSliceTileAlfLCU;
2615    m_pvpSliceTileAlfLCU = NULL;
2616#if !LCU_SYNTAX_ALF
2617  }
2618#endif
2619}
2620
2621#if !LCU_SYNTAX_ALF
2622/** ALF for cu-on/off-controlled region
2623 * \param vpAlfLCU ALF LCU information container
2624 * \param imgDec to-be-filtered picture buffer
2625 * \param imgRest filtered picture buffer
2626 * \param stride picture buffer stride size
2627 * \param filtNo filter shape
2628 * \param filterCoeff filter coefficients
2629 * \param mergeTable merge table for filter set
2630 * \param varImg BA index
2631 */
2632Void TComAdaptiveLoopFilter::xCUAdaptiveRegion(std::vector<AlfLCUInfo*> &vpAlfLCU, Pel* imgDec, Pel* imgRest, Int stride, Int filtNo, Int** filterCoeff, Int* mergeTable, Pel** varImg)
2633{
2634  UInt SUWidth   = m_pcPic->getMinCUWidth();
2635  UInt SUHeight  = m_pcPic->getMinCUHeight();
2636  UInt idx, startSU, endSU, currSU, LCUX, LCUY, LPelX, TPelY;
2637  TComDataCU* pcCU;
2638
2639  for(idx=0; idx< vpAlfLCU.size(); idx++)
2640  {
2641    AlfLCUInfo&    rAlfLCU = *(vpAlfLCU[idx]);
2642    pcCU                   = rAlfLCU.pcCU;
2643    startSU              = rAlfLCU.startSU;
2644    endSU                = rAlfLCU.endSU;
2645    LCUX                 = pcCU->getCUPelX();
2646    LCUY                 = pcCU->getCUPelY();
2647
2648    for(currSU= startSU; currSU<= endSU; currSU++)
2649    {
2650      LPelX   = LCUX + g_auiRasterToPelX[ g_auiZscanToRaster[currSU] ];
2651      TPelY   = LCUY + g_auiRasterToPelY[ g_auiZscanToRaster[currSU] ];
2652      if( !( LPelX < m_img_width )  || !( TPelY < m_img_height )  )
2653      {
2654        continue;
2655      }
2656      if(pcCU->getAlfCtrlFlag(currSU))
2657      {
2658        filterLuma(imgRest, imgDec, stride, TPelY, TPelY+ SUHeight-1, LPelX, LPelX+ SUWidth-1,  filtNo, m_filterCoeffSym, m_varIndTab, m_varImg);
2659      }
2660    }
2661  }
2662
2663}
2664
2665/** ALF for "non" cu-on/off-controlled region
2666 * \param vpAlfLCU ALF LCU information container
2667 * \param imgDec to-be-filtered picture buffer
2668 * \param imgRest filtered picture buffer
2669 * \param stride picture buffer stride size
2670 * \param filtNo filter shape
2671 * \param filterCoeff filter coefficients
2672 * \param mergeTable merge table for filter set
2673 * \param varImg BA index
2674 */
2675Void TComAdaptiveLoopFilter::filterLumaRegion(std::vector<AlfLCUInfo*> &vpAlfLCU, Pel* imgDec, Pel* imgRest, Int stride, Int filtNo, Int** filterCoeff, Int* mergeTable, Pel** varImg)
2676{
2677
2678  Int height, width;
2679  Int ypos, xpos;
2680
2681  for(Int i=0; i< vpAlfLCU.size(); i++)
2682  {
2683    AlfLCUInfo& rAlfLCU = *(vpAlfLCU[i]); 
2684    for(UInt j=0; j< rAlfLCU.numSGU; j++)
2685    {
2686      ypos   = (Int)(rAlfLCU[j].posY  );
2687      xpos   = (Int)(rAlfLCU[j].posX  );
2688      height = (Int)(rAlfLCU[j].height);
2689      width  = (Int)(rAlfLCU[j].width );
2690
2691      filterLuma(imgRest, imgDec, stride, ypos, ypos+ height-1, xpos, xpos+ width-1,  filtNo, filterCoeff, mergeTable, varImg);
2692    }
2693  }
2694}
2695
2696
2697/** Perform ALF for one chroma region
2698 * \param vpAlfLCU ALF LCU data container
2699 * \param pDec to-be-filtered picture buffer
2700 * \param pRest filtered picture buffer
2701 * \param stride picture buffer stride
2702 * \param coeff  filter coefficients
2703 * \param filtNo filter shape
2704 * \param chromaFormatShift chroma component size adjustment (1 for 4:2:0)
2705 */
2706Void TComAdaptiveLoopFilter::filterChromaRegion(std::vector<AlfLCUInfo*> &vpAlfLCU, Pel* pDec, Pel* pRest, Int stride, Int *coeff, Int filtNo, Int chromaFormatShift)
2707{
2708  Int height, width;
2709  Int ypos, xpos;
2710
2711  for(Int i=0; i< vpAlfLCU.size(); i++)
2712  {
2713    AlfLCUInfo& cAlfLCU = *(vpAlfLCU[i]);
2714    for(Int j=0; j< cAlfLCU.numSGU; j++)
2715    {
2716      ypos   = (Int)(cAlfLCU[j].posY   >> chromaFormatShift);
2717      xpos   = (Int)(cAlfLCU[j].posX   >> chromaFormatShift);
2718      height = (Int)(cAlfLCU[j].height >> chromaFormatShift);
2719      width  = (Int)(cAlfLCU[j].width  >> chromaFormatShift);
2720
2721      filterChroma(pRest, pDec, stride, ypos, ypos+ height -1, xpos, xpos+ width-1, filtNo, coeff);
2722    }
2723  }
2724}
2725
2726#endif
2727
2728/** Copy ALF CU control flags from ALF parameters for slices
2729 * \param [in] vAlfParamSlices ALF CU control parameters
2730 */
2731Void TComAdaptiveLoopFilter::transferCtrlFlagsFromAlfParam(std::vector<AlfCUCtrlInfo>& vAlfParamSlices)
2732{
2733  assert(m_uiNumSlicesInPic == vAlfParamSlices.size());
2734
2735  for(UInt s=0; s< m_uiNumSlicesInPic; s++)
2736  {
2737    AlfCUCtrlInfo& rAlfParam = vAlfParamSlices[s];
2738    transferCtrlFlagsFromAlfParamOneSlice( m_pvpAlfLCU[s], 
2739      (rAlfParam.cu_control_flag ==1)?true:false, 
2740      rAlfParam.alf_max_depth, 
2741      rAlfParam.alf_cu_flag
2742      );
2743  }
2744}
2745/** Copy ALF CU control flags from ALF CU control parameters for one slice
2746 * \param [in] vpAlfLCU ALF LCU data container
2747 * \param [in] bCUCtrlEnabled true for ALF CU control enabled
2748 * \param [in] iAlfDepth ALF CU control depth
2749 * \param [in] vCtrlFlags ALF CU control flags
2750 */
2751Void TComAdaptiveLoopFilter::transferCtrlFlagsFromAlfParamOneSlice(std::vector< AlfLCUInfo* > &vpAlfLCU, Bool bCUCtrlEnabled, Int iAlfDepth, std::vector<UInt>& vCtrlFlags)
2752{
2753
2754  if(!bCUCtrlEnabled)
2755  {
2756    for(Int idx=0; idx< vpAlfLCU.size(); idx++)
2757    {
2758      AlfLCUInfo& cAlfLCU = *(vpAlfLCU[idx]);
2759      if(cAlfLCU.pcCU==0)
2760      {
2761        return;
2762      }
2763      if( cAlfLCU.bAllSUsInLCUInSameSlice)
2764      {
2765        cAlfLCU.pcCU->setAlfCtrlFlagSubParts(1, 0, 0);
2766      }
2767      else
2768      {
2769        for(UInt uiCurrSU= cAlfLCU.startSU; uiCurrSU<= cAlfLCU.endSU; uiCurrSU++)
2770        {
2771          cAlfLCU.pcCU->setAlfCtrlFlag(uiCurrSU, 1);
2772        }
2773      }
2774    }
2775    return;
2776  }
2777
2778  UInt uiNumCtrlFlags = 0;
2779  for(Int idx=0; idx< vpAlfLCU.size(); idx++)
2780  {
2781    AlfLCUInfo& cAlfLCU = *(vpAlfLCU[idx]);
2782
2783    if(cAlfLCU.pcCU==NULL)
2784    {
2785      continue;
2786    }
2787    uiNumCtrlFlags += (UInt)getCtrlFlagsFromAlfParam(&cAlfLCU, iAlfDepth, &(vCtrlFlags[uiNumCtrlFlags]) );
2788  }
2789}
2790
2791/** Copy region pixels
2792 * \param vpAlfLCU ALF LCU data container
2793 * \param pPicDst destination picture buffer
2794 * \param pPicSrc source picture buffer
2795 * \param stride stride size of picture buffer
2796 * \param formatShift region size adjustment according to component size
2797 */
2798Void TComAdaptiveLoopFilter::copyRegion(std::vector< AlfLCUInfo* > &vpAlfLCU, Pel* pPicDst, Pel* pPicSrc, Int stride, Int formatShift)
2799{
2800  Int extSize = 4;
2801  Int posX, posY, width, height, offset;
2802  Pel *pPelDst, *pPelSrc;
2803 
2804  for(Int idx =0; idx < vpAlfLCU.size(); idx++)
2805  {
2806    AlfLCUInfo& cAlfLCU = *(vpAlfLCU[idx]);
2807    for(Int n=0; n < cAlfLCU.numSGU; n++)
2808    {
2809      NDBFBlockInfo& rSGU = cAlfLCU[n];
2810
2811      posX     = (Int)(rSGU.posX   >> formatShift);
2812      posY     = (Int)(rSGU.posY   >> formatShift);
2813      width    = (Int)(rSGU.width  >> formatShift);
2814      height   = (Int)(rSGU.height >> formatShift);
2815      offset   = ( (posY- extSize) * stride)+ (posX -extSize);
2816      pPelDst  = pPicDst + offset;   
2817      pPelSrc  = pPicSrc + offset;   
2818
2819      for(Int j=0; j< (height + (extSize<<1)); j++)
2820      {
2821        ::memcpy(pPelDst, pPelSrc, sizeof(Pel)*(width + (extSize<<1)));
2822        pPelDst += stride;
2823        pPelSrc += stride;
2824      }
2825    }
2826  }
2827}
2828
2829/** Extend region boundary
2830 * \param [in] vpAlfLCU ALF LCU data container
2831 * \param [in,out] pPelSrc picture buffer
2832 * \param [in] stride stride size of picture buffer
2833 * \param [in] formatShift region size adjustment according to component size
2834 */
2835Void TComAdaptiveLoopFilter::extendRegionBorder(std::vector< AlfLCUInfo* > &vpAlfLCU, Pel* pPelSrc, Int stride, Int formatShift)
2836{
2837  UInt extSize = 4;
2838  UInt width, height;
2839  UInt posX, posY;
2840  Pel* pPel;
2841  Bool* pbAvail;
2842  for(Int idx = 0; idx < vpAlfLCU.size(); idx++)
2843  {
2844    AlfLCUInfo& rAlfLCU = *(vpAlfLCU[idx]);
2845    for(Int n =0; n < rAlfLCU.numSGU; n++)
2846    {
2847      NDBFBlockInfo& rSGU = rAlfLCU[n];
2848#if LCU_SYNTAX_ALF
2849      if(rSGU.allBordersAvailable)
2850      {
2851        continue;
2852      }
2853#endif
2854      posX     = rSGU.posX >> formatShift;
2855      posY     = rSGU.posY >> formatShift;
2856      width    = rSGU.width >> formatShift;
2857      height   = rSGU.height >> formatShift;
2858      pbAvail  = rSGU.isBorderAvailable;   
2859      pPel     = pPelSrc + (posY * stride)+ posX;   
2860      extendBorderCoreFunction(pPel, stride, pbAvail, width, height, extSize);
2861    }
2862  }
2863}
2864
2865/** Core function for extending slice/tile boundary
2866 * \param [in, out] pPel processing block pointer
2867 * \param [in] stride picture buffer stride
2868 * \param [in] pbAvail neighboring blocks availabilities
2869 * \param [in] width block width
2870 * \param [in] height block height
2871 * \param [in] extSize boundary extension size
2872 */
2873Void TComAdaptiveLoopFilter::extendBorderCoreFunction(Pel* pPel, Int stride, Bool* pbAvail, UInt width, UInt height, UInt extSize)
2874{
2875  Pel* pPelDst;
2876  Pel* pPelSrc;
2877  Int i, j;
2878
2879  for(Int pos =0; pos < NUM_SGU_BORDER; pos++)
2880  {
2881    if(pbAvail[pos])
2882    {
2883      continue;
2884    }
2885
2886    switch(pos)
2887    {
2888    case SGU_L:
2889      {
2890        pPelDst = pPel - extSize;
2891        pPelSrc = pPel;
2892        for(j=0; j< height; j++)
2893        {
2894          for(i=0; i< extSize; i++)
2895          {
2896            pPelDst[i] = *pPelSrc;
2897          }
2898          pPelDst += stride;
2899          pPelSrc += stride;
2900        }
2901      }
2902      break;
2903    case SGU_R:
2904      {
2905        pPelDst = pPel + width;
2906        pPelSrc = pPelDst -1;
2907        for(j=0; j< height; j++)
2908        {
2909          for(i=0; i< extSize; i++)
2910          {
2911            pPelDst[i] = *pPelSrc;
2912          }
2913          pPelDst += stride;
2914          pPelSrc += stride;
2915        }
2916
2917      }
2918      break;
2919    case SGU_T:
2920      {
2921        pPelSrc = pPel;
2922        pPelDst = pPel - stride;
2923        for(j=0; j< extSize; j++)
2924        {
2925          ::memcpy(pPelDst, pPelSrc, sizeof(Pel)*width);
2926          pPelDst -= stride;
2927        }
2928      }
2929      break;
2930    case SGU_B:
2931      {
2932        pPelDst = pPel + height*stride;
2933        pPelSrc = pPelDst - stride;
2934        for(j=0; j< extSize; j++)
2935        {
2936          ::memcpy(pPelDst, pPelSrc, sizeof(Pel)*width);
2937          pPelDst += stride;
2938        }
2939
2940      }
2941      break;
2942    case SGU_TL:
2943      {
2944        if( (!pbAvail[SGU_T]) && (!pbAvail[SGU_L]))
2945        {
2946          pPelSrc = pPel  - extSize;
2947          pPelDst = pPelSrc - stride;
2948          for(j=0; j< extSize; j++)
2949          {
2950            ::memcpy(pPelDst, pPelSrc, sizeof(Pel)*extSize);
2951            pPelDst -= stride;
2952          }         
2953        }
2954      }
2955      break;
2956    case SGU_TR:
2957      {
2958        if( (!pbAvail[SGU_T]) && (!pbAvail[SGU_R]))
2959        {
2960          pPelSrc = pPel + width;
2961          pPelDst = pPelSrc - stride;
2962          for(j=0; j< extSize; j++)
2963          {
2964            ::memcpy(pPelDst, pPelSrc, sizeof(Pel)*extSize);
2965            pPelDst -= stride;
2966          }
2967
2968        }
2969
2970      }
2971      break;
2972    case SGU_BL:
2973      {
2974        if( (!pbAvail[SGU_B]) && (!pbAvail[SGU_L]))
2975        {
2976          pPelDst = pPel + height*stride; pPelDst-= extSize;
2977          pPelSrc = pPelDst - stride;
2978          for(j=0; j< extSize; j++)
2979          {
2980            ::memcpy(pPelDst, pPelSrc, sizeof(Pel)*extSize);
2981            pPelDst += stride;
2982          }
2983
2984        }
2985      }
2986      break;
2987    case SGU_BR:
2988      {
2989        if( (!pbAvail[SGU_B]) && (!pbAvail[SGU_R]))
2990        {
2991          pPelDst = pPel + height*stride; pPelDst += width;
2992          pPelSrc = pPelDst - stride;
2993          for(j=0; j< extSize; j++)
2994          {
2995            ::memcpy(pPelDst, pPelSrc, sizeof(Pel)*extSize);
2996            pPelDst += stride;
2997          }
2998        }
2999      }
3000      break;
3001    default:
3002      {
3003        printf("Not a legal neighboring availability\n");
3004        assert(0);
3005        exit(-1);
3006      }
3007    }
3008  }
3009}
3010
3011/** Assign ALF on/off-control flags from ALF parameters to CU data
3012 * \param [in] pcAlfLCU processing ALF LCU data pointer
3013 * \param [in] alfDepth ALF on/off-control depth
3014 * \param [in] pFlags on/off-control flags buffer in ALF parameters
3015 */
3016Int TComAdaptiveLoopFilter::getCtrlFlagsFromAlfParam(AlfLCUInfo* pcAlfLCU, Int alfDepth, UInt* pFlags)
3017{
3018
3019  const UInt startSU               = pcAlfLCU->startSU;
3020  const UInt endSU                 = pcAlfLCU->endSU;
3021  const Bool bAllSUsInLCUInSameSlice = pcAlfLCU->bAllSUsInLCUInSameSlice;
3022  const UInt maxNumSUInLCU         = m_pcPic->getNumPartInCU();
3023
3024  TComDataCU* pcCU = pcAlfLCU->pcCU;
3025  Int   numCUCtrlFlags = 0;
3026
3027  UInt  currSU, CUDepth, setDepth, ctrlNumSU;
3028  UInt  alfFlag;
3029
3030  currSU = startSU;
3031  if( bAllSUsInLCUInSameSlice ) 
3032  {
3033    while(currSU < maxNumSUInLCU)
3034    {
3035      //depth of this CU
3036      CUDepth = pcCU->getDepth(currSU);
3037
3038      //choose the min. depth for ALF
3039      setDepth   = (alfDepth < CUDepth)?(alfDepth):(CUDepth);
3040      ctrlNumSU = maxNumSUInLCU >> (setDepth << 1);
3041
3042      alfFlag= pFlags[numCUCtrlFlags];
3043
3044      pcCU->setAlfCtrlFlagSubParts(alfFlag, currSU, (UInt)setDepth);
3045
3046      numCUCtrlFlags++;
3047      currSU += ctrlNumSU;
3048    }
3049    return numCUCtrlFlags;
3050  }
3051
3052
3053  UInt  LCUX    = pcCU->getCUPelX();
3054  UInt  LCUY    = pcCU->getCUPelY();
3055
3056  Bool  bFirst, bValidCU;
3057  UInt  idx, LPelXSU, TPelYSU;
3058
3059  bFirst= true;
3060  while(currSU <= endSU)
3061  {
3062    //check picture boundary
3063    while(!( LCUX + g_auiRasterToPelX[ g_auiZscanToRaster[currSU] ] < m_img_width  ) || 
3064          !( LCUY + g_auiRasterToPelY[ g_auiZscanToRaster[currSU] ] < m_img_height )
3065      )
3066    {
3067      currSU++;
3068      if(currSU >= maxNumSUInLCU || currSU > endSU)
3069      {
3070        break;
3071      }
3072    }
3073
3074    if(currSU >= maxNumSUInLCU || currSU > endSU)
3075    {
3076      break;
3077    }
3078
3079    //depth of this CU
3080    CUDepth = pcCU->getDepth(currSU);
3081
3082    //choose the min. depth for ALF
3083    setDepth   = (alfDepth < CUDepth)?(alfDepth):(CUDepth);
3084    ctrlNumSU = maxNumSUInLCU >> (setDepth << 1);
3085
3086    if(bFirst)
3087    {
3088      if(currSU !=0 )
3089      {
3090        currSU = ((UInt)(currSU/ctrlNumSU))* ctrlNumSU;
3091      }
3092      bFirst = false;
3093    }
3094
3095    //alf flag for this CU
3096    alfFlag= pFlags[numCUCtrlFlags];
3097
3098    bValidCU = false;
3099    for(idx = currSU; idx < currSU + ctrlNumSU; idx++)
3100    {
3101      if(idx < startSU || idx > endSU)
3102      {
3103        continue;
3104      }
3105
3106      LPelXSU   = LCUX + g_auiRasterToPelX[ g_auiZscanToRaster[idx] ];
3107      TPelYSU   = LCUY + g_auiRasterToPelY[ g_auiZscanToRaster[idx] ];
3108
3109      if( !( LPelXSU < m_img_width )  || !( TPelYSU < m_img_height )  )
3110      {
3111        continue;
3112      }
3113
3114      bValidCU = true;
3115      pcCU->setAlfCtrlFlag(idx, alfFlag);
3116    }
3117
3118    if(bValidCU)
3119    {
3120      numCUCtrlFlags++;
3121    }
3122
3123    currSU += ctrlNumSU;
3124  }
3125
3126  return numCUCtrlFlags;
3127}
3128
3129#if LCU_SYNTAX_ALF
3130/** reconstruct ALF luma coefficient
3131 * \param [in] alfLCUParam ALF parameters
3132 * \param [out] filterCoeff reconstructed luma coefficients
3133 */
3134Void TComAdaptiveLoopFilter::reconstructLumaCoefficients(ALFParam* alfLCUParam, Int** filterCoeff)
3135{
3136  Int sum, coeffPred, ind;
3137#if LCUALF_QP_DEPENDENT_BITS
3138  Int alfPrecisionBit = getAlfPrecisionBit( m_alfQP );
3139#endif
3140  const Int* filtMag = NULL;
3141  filtMag = weightsTabShapes[0];
3142
3143  // Undo intra-filter prediction
3144  for(ind = 0; ind < alfLCUParam->filters_per_group; ind++)
3145  {
3146    sum = 0;
3147
3148    for(Int i = 0; i < alfLCUParam->num_coeff-2; i++)
3149    {
3150      sum += (filtMag[i] * alfLCUParam->coeffmulti[ind][i]);
3151      filterCoeff[ind][i] = alfLCUParam->coeffmulti[ind][i];
3152    }
3153
3154    if(alfLCUParam->nbSPred[ind] == 0)
3155    {
3156      if((alfLCUParam->predMethod==0)|(ind==0))
3157      {
3158#if LCUALF_QP_DEPENDENT_BITS
3159        coeffPred = ((1<<alfPrecisionBit)-sum) >> 2;
3160#else
3161        coeffPred = ((1<<ALF_NUM_BIT_SHIFT)-sum) >> 2;
3162#endif
3163      }
3164      else
3165      {
3166        coeffPred = (0-sum) >> 2;
3167      }
3168
3169      filterCoeff[ind][alfLCUParam->num_coeff-2] = coeffPred + alfLCUParam->coeffmulti[ind][alfLCUParam->num_coeff-2];
3170    }
3171    else
3172    {
3173      filterCoeff[ind][alfLCUParam->num_coeff-2] = alfLCUParam->coeffmulti[ind][alfLCUParam->num_coeff-2];
3174    }
3175
3176    sum += filtMag[alfLCUParam->num_coeff-2] * filterCoeff[ind][alfLCUParam->num_coeff-2];
3177
3178    if((alfLCUParam->predMethod==0)|(ind==0))
3179    {
3180#if LCUALF_QP_DEPENDENT_BITS
3181      coeffPred = (1<<alfPrecisionBit)-sum;
3182#else
3183      coeffPred = (1<<ALF_NUM_BIT_SHIFT)-sum;
3184#endif
3185    }
3186    else
3187    {
3188      coeffPred = -sum;
3189    }
3190
3191    filterCoeff[ind][alfLCUParam->num_coeff-1] = coeffPred + alfLCUParam->coeffmulti[ind][alfLCUParam->num_coeff-1];
3192  }
3193
3194
3195  // Undo inter-filter prediction
3196  for(ind = 1; ind < alfLCUParam->filters_per_group; ind++)
3197  {
3198    if(alfLCUParam->predMethod)
3199    {
3200      // Prediction
3201      for(Int i = 0; i < alfLCUParam->num_coeff; i++)
3202      {
3203        filterCoeff[ind][i] = (int)(filterCoeff[ind][i] + filterCoeff[ind - 1][i]);
3204      }
3205    }
3206  }
3207
3208}
3209
3210
3211/** reconstruct ALF chroma coefficient
3212 * \param [in] alfLCUParam ALF parameters
3213 * \param [out] filterCoeff reconstructed chroma coefficients
3214 */
3215Void TComAdaptiveLoopFilter::reconstructChromaCoefficients(ALFParam* alfLCUParam, Int** filterCoeff)
3216{
3217  Int sum = 0;
3218  Int i, coeffPred;
3219  const Int* filtMag = NULL;
3220  filtMag = weightsTabShapes[0];
3221
3222  for(i=0; i<alfLCUParam->num_coeff-1; i++)
3223  {
3224    sum += (filtMag[i] * alfLCUParam->coeffmulti[0][i]);
3225    filterCoeff[0][i] = alfLCUParam->coeffmulti[0][i];
3226  }
3227
3228#if LCUALF_QP_DEPENDENT_BITS
3229  Int alfPrecisionBit = getAlfPrecisionBit( m_alfQP );
3230  coeffPred = (1<<alfPrecisionBit) - sum;
3231#else
3232  coeffPred = (1<<ALF_NUM_BIT_SHIFT) - sum;
3233#endif
3234#if ALF_CHROMA_COEF_PRED_HARMONIZATION
3235  filterCoeff[0][alfLCUParam->num_coeff-1] = coeffPred + alfLCUParam->coeffmulti[0][alfLCUParam->num_coeff-1];
3236#else
3237  filterCoeff[0][alfLCUParam->num_coeff-1] = coeffPred - alfLCUParam->coeffmulti[0][alfLCUParam->num_coeff-1];
3238#endif
3239}
3240
3241
3242/** reconstruct ALF coefficient
3243 * \param [in] compIdx component index
3244 * \param [in] alfLCUParam ALF parameters
3245 * \param [out] filterCoeff reconstructed coefficients
3246 * \param [out] varIndTab the merged groups in block-based adaptation mode
3247 */
3248Void TComAdaptiveLoopFilter::reconstructCoefInfo(Int compIdx, ALFParam* alfLCUParam, Int** filterCoeff, Int* varIndTab)
3249{
3250  switch(compIdx)
3251  {
3252  case ALF_Cb:
3253  case ALF_Cr:
3254    {
3255      alfLCUParam->filters_per_group = 1;
3256      reconstructChromaCoefficients(alfLCUParam, filterCoeff);
3257    }
3258    break;
3259  case ALF_Y:
3260    {
3261      ::memset(varIndTab, 0, NO_VAR_BINS * sizeof(Int));
3262      if(alfLCUParam->filters_per_group > 1)
3263      {
3264        for(Int i = 1; i < NO_VAR_BINS; ++i)
3265        {
3266          if(alfLCUParam->filterPattern[i])
3267          {
3268            varIndTab[i] = varIndTab[i-1] + 1;
3269          }
3270          else
3271          {
3272            varIndTab[i] = varIndTab[i-1];
3273          }
3274        }
3275      }
3276      reconstructLumaCoefficients(alfLCUParam, filterCoeff);
3277    }
3278    break;
3279  default:
3280    {
3281      printf("not legal component ID for ALF\n");
3282      assert(0);
3283      exit(-1);
3284    }
3285  }
3286
3287}
3288
3289
3290/** filter process with CU-On/Off control
3291 * \param [in] alfLCUParam ALF parameters
3292 * \param [in] regionLCUInfo ALF CU-on/off control parameters
3293 * \param [in] pDec decoded picture
3294 * \param [out] pRest filtered picture
3295 * \param [in] stride picture stride in memory
3296 * \param [in] caculateBAIdx calculate BA filter index (true) or BA filter index array is ready (false)
3297 */
3298Void TComAdaptiveLoopFilter::filterRegionCUControl(ALFParam** alfLCUParams, std::vector<AlfLCUInfo*>& regionLCUInfo, Pel* pDec, Pel* pRest, Int stride, Bool caculateBAIdx)
3299{
3300  Int ypos, xpos, currSU, startSU, endSU, lcuX, lcuY;
3301  Int yposEnd, xposEnd;
3302
3303  for(Int i=0; i< (Int)regionLCUInfo.size(); i++)
3304  {
3305    AlfLCUInfo& alfLCUinfo = *(regionLCUInfo[i]); 
3306    TComDataCU* pcCU = alfLCUinfo.pcCU;
3307    Int addr = pcCU->getAddr();
3308
3309    ALFParam* alfParam = alfLCUParams[addr];
3310
3311    if(alfParam->alf_flag == 1)
3312    {
3313      lcuX    = pcCU->getCUPelX();
3314      lcuY    = pcCU->getCUPelY();
3315
3316      if(caculateBAIdx)
3317      {
3318        xposEnd = lcuX + g_uiMaxCUWidth;
3319        yposEnd = lcuY + g_uiMaxCUHeight;
3320
3321        if(xposEnd > m_img_width)
3322        {
3323          xposEnd = m_img_width;
3324        }
3325
3326        if(yposEnd > m_img_height)
3327        {
3328          yposEnd = m_img_height;
3329        }
3330
3331        calcOneRegionVar(m_varImg, pDec, stride, (alfParam->filters_per_group == 1), lcuY, yposEnd, lcuX, xposEnd);       
3332      }
3333
3334      //reconstruct ALF coefficients & related parameters
3335      reconstructCoefInfo(ALF_Y, alfParam, m_filterCoeffSym, m_varIndTab);
3336
3337      startSU = alfLCUinfo.startSU;
3338      endSU   = alfLCUinfo.endSU;
3339
3340
3341      for(currSU= startSU; currSU<= endSU; currSU++)
3342      {
3343        xpos  = lcuX + g_auiRasterToPelX[ g_auiZscanToRaster[currSU] ];
3344        ypos  = lcuY + g_auiRasterToPelY[ g_auiZscanToRaster[currSU] ];
3345        if( !( xpos < m_img_width )  || !( ypos < m_img_height )  )
3346        {
3347          continue;
3348        }
3349
3350        if(pcCU->getAlfCtrlFlag(currSU))
3351        {
3352          filterOneCompRegion(pRest, pDec, stride, false, ypos, ypos+m_suHeight, xpos, xpos+m_suWidth, m_filterCoeffSym, m_varIndTab, m_varImg);
3353        }
3354      }
3355
3356    } //alf_flag == 1
3357  }
3358
3359}
3360
3361
3362/** filter process without CU-On/Off control
3363 * \param [in] alfLCUParam ALF parameters
3364 * \param [in] regionLCUInfo ALF CU-on/off control parameters
3365 * \param [in] pDec decoded picture
3366 * \param [out] pRest filtered picture
3367 * \param [in] stride picture stride in memory
3368 * \param [in] formatShift luma component (0) or chroma component (1)
3369 * \param [in] caculateBAIdx calculate BA filter index (true) or BA filter index array is ready (false)
3370 */
3371Void TComAdaptiveLoopFilter::filterRegion(Int compIdx, ALFParam** alfLCUParams, std::vector<AlfLCUInfo*>& regionLCUInfo, Pel* pDec, Pel* pRest, Int stride, Int formatShift, Bool caculateBAIdx)
3372{
3373  Int height, width;
3374  Int ypos, xpos,  lcuX, lcuY;
3375  Int yposEnd, xposEnd;
3376
3377  for(Int i=0; i< regionLCUInfo.size(); i++)
3378  {
3379    AlfLCUInfo& alfLCUinfo = *(regionLCUInfo[i]); 
3380    TComDataCU* pcCU = alfLCUinfo.pcCU;
3381    Int addr = pcCU->getAddr();
3382
3383    ALFParam* alfParam = alfLCUParams[addr];
3384
3385    if(alfParam->alf_flag == 1)
3386    {
3387      lcuX    = pcCU->getCUPelX();
3388      lcuY    = pcCU->getCUPelY();
3389
3390      if(caculateBAIdx)
3391      {
3392        assert(compIdx == ALF_Y);
3393
3394        xposEnd = lcuX + g_uiMaxCUWidth;
3395        yposEnd = lcuY + g_uiMaxCUHeight;
3396
3397        if(xposEnd > m_img_width)
3398        {
3399          xposEnd = m_img_width;
3400        }
3401
3402        if(yposEnd > m_img_height)
3403        {
3404          yposEnd = m_img_height;
3405        }
3406
3407        calcOneRegionVar(m_varImg, pDec, stride, (alfParam->filters_per_group == 1), lcuY, yposEnd, lcuX, xposEnd);       
3408      }
3409
3410      //reconstruct ALF coefficients & related parameters
3411      reconstructCoefInfo(compIdx, alfParam, m_filterCoeffSym, m_varIndTab);
3412
3413      //filtering process
3414      for(Int j=0; j< alfLCUinfo.numSGU; j++)
3415      {
3416        ypos    = (Int)(alfLCUinfo[j].posY   >> formatShift);
3417        xpos    = (Int)(alfLCUinfo[j].posX   >> formatShift);
3418        height = (Int)(alfLCUinfo[j].height >> formatShift);
3419        width  = (Int)(alfLCUinfo[j].width  >> formatShift);
3420
3421        filterOneCompRegion(pRest, pDec, stride, (compIdx!=ALF_Y), ypos, ypos+height, xpos, xpos+width, m_filterCoeffSym, m_varIndTab, m_varImg);
3422      }
3423    } //alf_flag == 1
3424  }
3425}
3426
3427
3428/** predict chroma center coefficient
3429 * \param [in] coeff ALF chroma coefficient
3430 * \param [in] numCoef number of chroma coefficients
3431 */
3432Void TComAdaptiveLoopFilter::predictALFCoeffChroma(Int* coeff, Int numCoef)
3433{
3434  Int sum=0;
3435  for(Int i=0; i< numCoef-1;i++)
3436  {
3437    sum += (2* coeff[i]);
3438  }
3439
3440#if LCUALF_QP_DEPENDENT_BITS
3441  Int alfPrecisionBit = getAlfPrecisionBit( m_alfQP );
3442  Int pred = (1<<alfPrecisionBit) - (sum);
3443#else
3444  Int pred = (1<<ALF_NUM_BIT_SHIFT) - (sum);
3445#endif
3446#if ALF_CHROMA_COEF_PRED_HARMONIZATION
3447  coeff[numCoef-1] = coeff[numCoef-1] - pred;
3448#else
3449  coeff[numCoef-1] = pred- coeff[numCoef-1];
3450#endif
3451}
3452
3453#if ALF_SINGLE_FILTER_SHAPE
3454/** filtering pixels
3455 * \param [out] imgRes filtered picture
3456 * \param [in] imgPad decoded picture
3457 * \param [in] stride picture stride in memory
3458 * \param [in] isChroma chroma component (true) or luma component (false)
3459 * \param [in] yPos y position of the top-left pixel in one to-be-filtered region
3460 * \param [in] yPosEnd y position of the right-bottom pixel in one to-be-filtered region
3461 * \param [in] xPos x position of the top-left pixel in one to-be-filtered region
3462 * \param [in] xPosEnd x position of the right-bottom pixel in one to-be-filtered region
3463 * \param [in] filterSet filter coefficients
3464 * \param [in] mergeTable the merged groups in block-based adaptation mode
3465 * \param [in] varImg BA filter index array
3466 */
3467Void TComAdaptiveLoopFilter::filterOneCompRegion(Pel *imgRes, Pel *imgPad, Int stride, Bool isChroma
3468                                                , Int yPos, Int yPosEnd, Int xPos, Int xPosEnd
3469                                                , Int** filterSet, Int* mergeTable, Pel** varImg
3470                                                )
3471{
3472#if LCUALF_QP_DEPENDENT_BITS 
3473  Int alfPrecisionBit = getAlfPrecisionBit( m_alfQP );
3474  Int numBitsMinus1   = alfPrecisionBit;
3475  Int offset          = (1<<(alfPrecisionBit-1));
3476#else
3477  static Int numBitsMinus1= (Int)ALF_NUM_BIT_SHIFT;
3478  static Int offset       = (1<<( (Int)ALF_NUM_BIT_SHIFT-1));
3479#endif
3480  static Int shiftHeight  = (Int)(log((double)VAR_SIZE_H)/log(2.0));
3481  static Int shiftWidth   = (Int)(log((double)VAR_SIZE_W)/log(2.0));
3482
3483  Pel *imgPad1,*imgPad2,*imgPad3, *imgPad4, *imgPad5, *imgPad6;
3484  Pel *var = varImg[yPos>>shiftHeight] + (xPos>>shiftWidth);;
3485  Int i, j, pixelInt;
3486  Int *coef = NULL;
3487
3488  coef    = filterSet[0];
3489  imgPad += (yPos*stride);
3490  imgRes += (yPos*stride);
3491
3492  Int yLineInLCU;
3493  Int paddingLine;
3494  //Int varInd = 0;
3495  Int lcuHeight     = isChroma ? m_lcuHeightChroma     : m_lcuHeight;
3496  Int lineIdxPadBot = isChroma ? m_lineIdxPadBotChroma : m_lineIdxPadBot;
3497  Int lineIdxPadTop = isChroma ? m_lineIdxPadTopChroma : m_lineIdxPadTop;
3498  Int img_height    = isChroma ? m_img_height>>1       : m_img_height;
3499
3500  for(i= yPos; i< yPosEnd; i++)
3501  {
3502    yLineInLCU = i % lcuHeight;
3503
3504    if(isChroma && yLineInLCU == 0 && i>0)
3505    {
3506      paddingLine = yLineInLCU + 2;
3507      imgPad1 = imgPad + stride;
3508      imgPad2 = imgPad - stride;
3509      imgPad3 = imgPad + 2*stride;
3510      imgPad4 = imgPad - 2*stride;
3511      imgPad5 = (paddingLine < 3) ? imgPad : imgPad + 3*stride;
3512      imgPad6 = (paddingLine < 3) ? imgPad : imgPad - min(paddingLine, 3)*stride;
3513    }
3514    else if(yLineInLCU<lineIdxPadBot || i-yLineInLCU+lcuHeight >= img_height)
3515    {
3516      imgPad1 = imgPad +   stride;
3517      imgPad2 = imgPad -   stride;
3518      imgPad3 = imgPad + 2*stride;
3519      imgPad4 = imgPad - 2*stride;
3520      imgPad5 = imgPad + 3*stride;
3521      imgPad6 = imgPad - 3*stride;
3522    }
3523    else if (yLineInLCU<lineIdxPadTop)
3524    {
3525      paddingLine = - yLineInLCU + lineIdxPadTop - 1;
3526      imgPad1 = (paddingLine < 1) ? imgPad : imgPad + min(paddingLine, 1)*stride;
3527      imgPad2 = (paddingLine < 1) ? imgPad : imgPad - stride;
3528      imgPad3 = (paddingLine < 2) ? imgPad : imgPad + min(paddingLine, 2)*stride;
3529      imgPad4 = (paddingLine < 2) ? imgPad : imgPad - 2*stride;
3530      imgPad5 = (paddingLine < 3) ? imgPad : imgPad + min(paddingLine, 3)*stride;
3531      imgPad6 = (paddingLine < 3) ? imgPad : imgPad - 3*stride;
3532    }
3533    else
3534    {
3535      paddingLine = yLineInLCU - lineIdxPadTop ;
3536      imgPad1 = (paddingLine < 1) ? imgPad : imgPad + stride;
3537      imgPad2 = (paddingLine < 1) ? imgPad : imgPad - min(paddingLine, 1)*stride;
3538      imgPad3 = (paddingLine < 2) ? imgPad : imgPad + 2*stride;
3539      imgPad4 = (paddingLine < 2) ? imgPad : imgPad - min(paddingLine, 2)*stride;
3540      imgPad5 = (paddingLine < 3) ? imgPad : imgPad + 3*stride;
3541      imgPad6 = (paddingLine < 3) ? imgPad : imgPad - min(paddingLine, 3)*stride;
3542    } 
3543
3544    if(!isChroma)
3545    {
3546      var = varImg[i>>shiftHeight] + (xPos>>shiftWidth);
3547    }
3548
3549    for(j= xPos; j< xPosEnd ; j++)
3550    {
3551      if (!isChroma && j % VAR_SIZE_W==0) 
3552      {
3553        coef = filterSet[mergeTable[*(var++)]];
3554      }
3555
3556      pixelInt  = coef[0]* (imgPad5[] + imgPad6[]);
3557
3558      pixelInt += coef[1]* (imgPad3[] + imgPad4[]);
3559
3560      pixelInt += coef[2]* (imgPad1[j-1] + imgPad2[j+1]);
3561      pixelInt += coef[3]* (imgPad1[] + imgPad2[]);
3562      pixelInt += coef[4]* (imgPad1[j+1] + imgPad2[j-1]);
3563
3564      pixelInt += coef[5]* (imgPad[j+4] + imgPad[j-4]);
3565      pixelInt += coef[6]* (imgPad[j+3] + imgPad[j-3]);
3566      pixelInt += coef[7]* (imgPad[j+2] + imgPad[j-2]);
3567      pixelInt += coef[8]* (imgPad[j+1] + imgPad[j-1]);
3568      pixelInt += coef[9]* (imgPad[]);
3569
3570      pixelInt=(Int)((pixelInt+offset) >> numBitsMinus1);
3571      imgRes[j] = Clip( pixelInt );
3572    }
3573
3574    imgPad += stride;
3575    imgRes += stride;
3576  } 
3577}
3578#endif
3579
3580#if LCUALF_QP_DEPENDENT_BITS
3581/** filtering pixels
3582 * \param [in] qp quantization parameter
3583 */
3584Int  TComAdaptiveLoopFilter::getAlfPrecisionBit(Int qp)
3585{
3586  Int alfPrecisionBit = 8;
3587
3588  if (qp < ALF_QP1)
3589  {
3590    alfPrecisionBit = 8;
3591  }
3592  else if (qp < ALF_QP2)
3593  {
3594    alfPrecisionBit = 7;
3595  }
3596  else if (qp < ALF_QP3)
3597  {
3598    alfPrecisionBit = 6;
3599  }
3600  else
3601  {
3602    alfPrecisionBit = 5;
3603  }
3604
3605  return alfPrecisionBit;
3606}
3607#endif
3608
3609/** filtering pixels
3610 * \param [out] imgYvar BA filter index array
3611 * \param [in] imgYpad decoded picture
3612 * \param [in] stride picture stride in memory
3613 * \param [in] isOnlyOneGroup only one filter is used (true) or multiple filters are used (false)
3614 * \param [in] yPos y position of the top-left pixel in one to-be-filtered region
3615 * \param [in] yPosEnd y position of the right-bottom pixel in one to-be-filtered region
3616 * \param [in] xPos x position of the top-left pixel in one to-be-filtered region
3617 * \param [in] xPosEnd x position of the right-bottom pixel in one to-be-filtered region
3618 */
3619Void TComAdaptiveLoopFilter::calcOneRegionVar(Pel **imgYvar, Pel *imgYpad, Int stride, Bool isOnlyOneGroup, Int yPos, Int yPosEnd, Int xPos, Int xPosEnd)
3620{
3621
3622  static Int shiftH = (Int)(log((double)VAR_SIZE_H)/log(2.0));
3623  static Int shiftW = (Int)(log((double)VAR_SIZE_W)/log(2.0));
3624  static Int varMax = (Int)NO_VAR_BINS-1; 
3625#if ALF_16_BA_GROUPS
3626  static Int th[NO_VAR_BINS] = {0, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5}; 
3627  static Int avgVarTab[3][6] = { {0,  1,  2,  3,  4,  5,},
3628  {0,  6,  7,  8,  9, 10,},
3629  {0, 11, 12, 13, 14, 15}   };
3630#else
3631  static Int step   = (Int)((Int)(NO_VAR_BINS)/3) - 1; 
3632  static Int th[NO_VAR_BINS] = {0, 1, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4}; 
3633#endif
3634
3635  Int i, j, avgVar, vertical, horizontal, direction, yOffset;
3636  Pel *imgYPadCur, *imgYPadUp, *imgYPadDown;
3637
3638  if (isOnlyOneGroup)
3639  {
3640    for(i = yPos; i < yPosEnd; i=i+4)
3641    {
3642      for(j = xPos; j < xPosEnd; j=j+4)
3643      {
3644        imgYvar[i>>shiftH][j>>shiftW] = 0;
3645      }
3646    }
3647    return;
3648  }
3649
3650  for(i = yPos; i < yPosEnd; i=i+4)
3651  {
3652    yOffset     = (i*stride) + stride;
3653    imgYPadCur  = &imgYpad[yOffset];
3654    imgYPadUp   = &imgYpad[yOffset + stride];
3655    imgYPadDown = &imgYpad[yOffset - stride];
3656
3657    for(j = xPos; j < xPosEnd; j=j+4)
3658    {
3659      // Compute at sub-sample by 2
3660      vertical   =  abs((imgYPadCur[j+1]<<1) - imgYPadDown[j+1] - imgYPadUp [j+1]);
3661      horizontal =  abs((imgYPadCur[j+1]<<1) - imgYPadCur [j+2] - imgYPadCur[]);
3662
3663      vertical   += abs((imgYPadCur[j+2]<<1) - imgYPadDown[j+2] - imgYPadUp [j+2]);
3664      horizontal += abs((imgYPadCur[j+2]<<1) - imgYPadCur [j+3] - imgYPadCur[j+1]);
3665
3666      vertical   += abs((imgYPadCur[j+1+stride]<<1) - imgYPadDown[j+1+stride] - imgYPadUp [j+1+stride]);
3667      horizontal += abs((imgYPadCur[j+1+stride]<<1) - imgYPadCur [j+2+stride] - imgYPadCur[j+stride  ]);
3668
3669      vertical   += abs((imgYPadCur[j+2+stride]<<1) - imgYPadDown[j+2+stride] - imgYPadUp [j+2+stride]);
3670      horizontal += abs((imgYPadCur[j+2+stride]<<1) - imgYPadCur [j+3+stride] - imgYPadCur[j+1+stride]);
3671
3672      direction = 0;
3673      if (vertical > 2*horizontal) 
3674      {
3675        direction = 1; //vertical
3676      }
3677      if (horizontal > 2*vertical)
3678      {
3679        direction = 2; //horizontal
3680      }
3681
3682      avgVar = (vertical + horizontal) >> 2;
3683      avgVar = (Pel) Clip_post( varMax, avgVar>>(g_uiBitIncrement+1) );
3684      avgVar = th[avgVar];
3685#if ALF_16_BA_GROUPS
3686      avgVar = avgVarTab[direction][avgVar];
3687#else     
3688      avgVar = Clip_post(step, (Int)avgVar) + (step+1)*direction;
3689#endif
3690      imgYvar[i>>shiftH][j>>shiftW] = avgVar;
3691    }
3692  }
3693}
3694
3695
3696Void TComAdaptiveLoopFilter::resetLCUAlfInfo()
3697{
3698  //reset to all off
3699  for(Int compIdx = 0; compIdx < NUM_ALF_COMPONENT; compIdx++)
3700  {
3701    for(Int n=0; n< m_uiNumCUsInFrame; n++)
3702    {
3703      m_alfFiltInfo[compIdx][n]->alf_flag = 0;
3704    }
3705  }
3706
3707}
3708
3709Void TComAdaptiveLoopFilter::createLCUAlfInfo()
3710{
3711  for(Int compIdx = 0; compIdx < NUM_ALF_COMPONENT; compIdx++)
3712  {
3713    m_alfFiltInfo[compIdx] = new ALFParam*[m_uiNumCUsInFrame];
3714    for(Int n=0; n< m_uiNumCUsInFrame; n++)
3715    {
3716      m_alfFiltInfo[compIdx][n] = new ALFParam(compIdx);
3717    }
3718  }
3719
3720  resetLCUAlfInfo();
3721}
3722
3723Void TComAdaptiveLoopFilter::destroyLCUAlfInfo()
3724{
3725  for(Int compIdx = 0; compIdx < NUM_ALF_COMPONENT; compIdx++)
3726  {
3727    if(m_alfFiltInfo[compIdx] != NULL)
3728    {
3729      for(Int n=0; n< m_uiNumCUsInFrame; n++)
3730      {
3731        delete m_alfFiltInfo[compIdx][n];
3732      }
3733      delete[] m_alfFiltInfo[compIdx];
3734      m_alfFiltInfo[compIdx] = NULL;
3735    }
3736  }
3737}
3738
3739Pel* TComAdaptiveLoopFilter::getPicBuf(TComPicYuv* pPicYuv, Int compIdx)
3740{
3741  Pel* pBuf = NULL;
3742  switch(compIdx)
3743  {
3744  case ALF_Y:
3745    {
3746      pBuf = pPicYuv->getLumaAddr();
3747    }
3748    break;
3749  case ALF_Cb:
3750    {
3751      pBuf = pPicYuv->getCbAddr();
3752    }
3753    break;
3754  case ALF_Cr:
3755    {
3756      pBuf = pPicYuv->getCrAddr();
3757    }
3758    break;
3759  default:
3760    {
3761      printf("Not a legal component ID for ALF\n");
3762      assert(0);
3763      exit(-1);
3764    }
3765  }
3766
3767  return pBuf;
3768}
3769#endif
3770
3771
3772
3773/** PCM LF disable process.
3774 * \param pcPic picture (TComPic) pointer
3775 * \returns Void
3776 *
3777 * \note Replace filtered sample values of PCM mode blocks with the transmitted and reconstructed ones.
3778 */
3779Void TComAdaptiveLoopFilter::PCMLFDisableProcess (TComPic* pcPic)
3780{
3781  xPCMRestoration(pcPic);
3782}
3783
3784/** Picture-level PCM restoration.
3785 * \param pcPic picture (TComPic) pointer
3786 * \returns Void
3787 */
3788Void TComAdaptiveLoopFilter::xPCMRestoration(TComPic* pcPic)
3789{
3790  Bool  bPCMFilter = (pcPic->getSlice(0)->getSPS()->getUsePCM() && pcPic->getSlice(0)->getSPS()->getPCMFilterDisableFlag())? true : false;
3791
3792#if LOSSLESS_CODING
3793  if(bPCMFilter || pcPic->getSlice(0)->getSPS()->getUseLossless())
3794#else
3795  if(bPCMFilter)
3796#endif
3797  {
3798    for( UInt uiCUAddr = 0; uiCUAddr < pcPic->getNumCUsInFrame() ; uiCUAddr++ )
3799    {
3800      TComDataCU* pcCU = pcPic->getCU(uiCUAddr);
3801
3802      xPCMCURestoration(pcCU, 0, 0); 
3803    } 
3804  }
3805}
3806
3807/** PCM CU restoration.
3808 * \param pcCU pointer to current CU
3809 * \param uiAbsPartIdx part index
3810 * \param uiDepth CU depth
3811 * \returns Void
3812 */
3813Void TComAdaptiveLoopFilter::xPCMCURestoration ( TComDataCU* pcCU, UInt uiAbsZorderIdx, UInt uiDepth )
3814{
3815  TComPic* pcPic     = pcCU->getPic();
3816  UInt uiCurNumParts = pcPic->getNumPartInCU() >> (uiDepth<<1);
3817  UInt uiQNumParts   = uiCurNumParts>>2;
3818
3819  // go to sub-CU
3820  if( pcCU->getDepth(uiAbsZorderIdx) > uiDepth )
3821  {
3822    for ( UInt uiPartIdx = 0; uiPartIdx < 4; uiPartIdx++, uiAbsZorderIdx+=uiQNumParts )
3823    {
3824      UInt uiLPelX   = pcCU->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiAbsZorderIdx] ];
3825      UInt uiTPelY   = pcCU->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiAbsZorderIdx] ];
3826      if( ( uiLPelX < pcCU->getSlice()->getSPS()->getPicWidthInLumaSamples() ) && ( uiTPelY < pcCU->getSlice()->getSPS()->getPicHeightInLumaSamples() ) )
3827        xPCMCURestoration( pcCU, uiAbsZorderIdx, uiDepth+1 );
3828    }
3829    return;
3830  }
3831
3832  // restore PCM samples
3833#if LOSSLESS_CODING
3834  if ((pcCU->getIPCMFlag(uiAbsZorderIdx)) || pcCU->isLosslessCoded( uiAbsZorderIdx))
3835#else
3836  if (pcCU->getIPCMFlag(uiAbsZorderIdx))
3837#endif
3838  {
3839    xPCMSampleRestoration (pcCU, uiAbsZorderIdx, uiDepth, TEXT_LUMA    );
3840    xPCMSampleRestoration (pcCU, uiAbsZorderIdx, uiDepth, TEXT_CHROMA_U);
3841    xPCMSampleRestoration (pcCU, uiAbsZorderIdx, uiDepth, TEXT_CHROMA_V);
3842  }
3843}
3844
3845/** PCM sample restoration.
3846 * \param pcCU pointer to current CU
3847 * \param uiAbsPartIdx part index
3848 * \param uiDepth CU depth
3849 * \param ttText texture component type
3850 * \returns Void
3851 */
3852Void TComAdaptiveLoopFilter::xPCMSampleRestoration (TComDataCU* pcCU, UInt uiAbsZorderIdx, UInt uiDepth, TextType ttText)
3853{
3854  TComPicYuv* pcPicYuvRec = pcCU->getPic()->getPicYuvRec();
3855  Pel* piSrc;
3856  Pel* piPcm;
3857  UInt uiStride;
3858  UInt uiWidth;
3859  UInt uiHeight;
3860  UInt uiPcmLeftShiftBit; 
3861  UInt uiX, uiY;
3862  UInt uiMinCoeffSize = pcCU->getPic()->getMinCUWidth()*pcCU->getPic()->getMinCUHeight();
3863  UInt uiLumaOffset   = uiMinCoeffSize*uiAbsZorderIdx;
3864  UInt uiChromaOffset = uiLumaOffset>>2;
3865
3866  if( ttText == TEXT_LUMA )
3867  {
3868    piSrc = pcPicYuvRec->getLumaAddr( pcCU->getAddr(), uiAbsZorderIdx);
3869    piPcm = pcCU->getPCMSampleY() + uiLumaOffset;
3870    uiStride  = pcPicYuvRec->getStride();
3871    uiWidth  = (g_uiMaxCUWidth >> uiDepth);
3872    uiHeight = (g_uiMaxCUHeight >> uiDepth);
3873#if LOSSLESS_CODING
3874    if ( pcCU->isLosslessCoded(uiAbsZorderIdx) )
3875    {
3876      uiPcmLeftShiftBit = 0;
3877    }
3878    else
3879#endif
3880    {
3881        uiPcmLeftShiftBit = g_uiBitDepth + g_uiBitIncrement - pcCU->getSlice()->getSPS()->getPCMBitDepthLuma();
3882    }
3883  }
3884  else
3885  {
3886    if( ttText == TEXT_CHROMA_U )
3887    {
3888      piSrc = pcPicYuvRec->getCbAddr( pcCU->getAddr(), uiAbsZorderIdx );
3889      piPcm = pcCU->getPCMSampleCb() + uiChromaOffset;
3890    }
3891    else
3892    {
3893      piSrc = pcPicYuvRec->getCrAddr( pcCU->getAddr(), uiAbsZorderIdx );
3894      piPcm = pcCU->getPCMSampleCr() + uiChromaOffset;
3895    }
3896
3897    uiStride = pcPicYuvRec->getCStride();
3898    uiWidth  = ((g_uiMaxCUWidth >> uiDepth)/2);
3899    uiHeight = ((g_uiMaxCUWidth >> uiDepth)/2);
3900#if LOSSLESS_CODING
3901    if ( pcCU->isLosslessCoded(uiAbsZorderIdx) )
3902    {
3903      uiPcmLeftShiftBit = 0;
3904    }
3905    else
3906#endif
3907    {
3908      uiPcmLeftShiftBit = g_uiBitDepth + g_uiBitIncrement - pcCU->getSlice()->getSPS()->getPCMBitDepthChroma();
3909    }
3910  }
3911
3912  for( uiY = 0; uiY < uiHeight; uiY++ )
3913  {
3914    for( uiX = 0; uiX < uiWidth; uiX++ )
3915    {
3916      piSrc[uiX] = (piPcm[uiX] << uiPcmLeftShiftBit);
3917    }
3918    piPcm += uiWidth;
3919    piSrc += uiStride;
3920  }
3921}
3922//! \}
Note: See TracBrowser for help on using the repository browser.