source: 3DVCSoftware/branches/HTM-6.0-dev0/source/Lib/TLibCommon/TComAdaptiveLoopFilter.cpp @ 312

Last change on this file since 312 was 296, checked in by tech, 11 years ago

Reintegrated branch 5.1-dev0 rev. 295.

  • Property svn:eol-style set to native
File size: 61.1 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
49// ====================================================================================================================
50// Tables
51// ====================================================================================================================
52
53Int TComAdaptiveLoopFilter::weightsShape1Sym[ALF_MAX_NUM_COEF+1] = 
54{ 
55              2,
56              2,
57           2, 2, 2,
58  2, 2, 2, 2, 1, 
59              1
60};
61Int* TComAdaptiveLoopFilter::weightsTabShapes[NUM_ALF_FILTER_SHAPE] =
62{
63  weightsShape1Sym
64};
65Int TComAdaptiveLoopFilter::m_sqrFiltLengthTab[NUM_ALF_FILTER_SHAPE] =
66{
67  ALF_FILTER_LEN
68};
69Int depthIntShape1Sym[ALF_MAX_NUM_COEF+1] = 
70{
71              6,
72              7,
73           7, 8, 7,
74  5, 6, 7, 8, 9, 
75              9 
76};
77Int* pDepthIntTabShapes[NUM_ALF_FILTER_SHAPE] =
78{ 
79  depthIntShape1Sym
80};
81
82Int kTableShape1[ALF_MAX_NUM_COEF+1] = 
83{     
84              2,
85              3,
86           3, 4, 3,
87  1, 2, 3, 4, 1, 
88              3
89};
90Int* kTableTabShapes[NUM_ALF_FILTER_SHAPE] =
91{ 
92  kTableShape1
93};
94
95// ====================================================================================================================
96// Constructor / destructor / create / destroy
97// ====================================================================================================================
98
99const AlfCUCtrlInfo& AlfCUCtrlInfo::operator= (const AlfCUCtrlInfo& src)
100{
101  this->cu_control_flag = src.cu_control_flag;
102  this->alf_max_depth   = src.alf_max_depth;
103  this->num_alf_cu_flag = src.num_alf_cu_flag;
104  this->alf_cu_flag     = src.alf_cu_flag;
105  return *this;
106}
107
108/// AlfCUCtrlInfo
109Void AlfCUCtrlInfo::reset()
110{
111  cu_control_flag= 0;
112  num_alf_cu_flag= 0;
113  alf_max_depth = 0;
114  alf_cu_flag.clear();
115}
116
117/// ALFParam
118const ALFParam& ALFParam::operator= (const ALFParam& src)
119{
120  if(this->componentID < 0)
121  {
122    this->create(src.componentID);
123  }
124  this->copy(src);
125  return *this;
126}
127
128Void ALFParam::create(Int cID)
129{
130  const Int numCoef = ALF_MAX_NUM_COEF;
131
132  this->componentID       = cID;
133  this->alf_flag          = 0;
134  this->filters_per_group = 1; // this value keeps 1 for chroma componenet
135  this->startSecondFilter = -1;
136  this->predMethod        = -1;
137  this->minKStart         = -1;
138  this->filterPattern     = NULL;
139  this->nbSPred           = NULL;
140  this->kMinTab           = NULL;
141  this->coeffmulti        = NULL;
142  this->filter_shape      = 0;
143  this->num_coeff         = numCoef;
144
145  switch(cID)
146  {
147  case ALF_Y:
148    {
149      this->coeffmulti = new Int*[NO_VAR_BINS];
150      for(Int i=0; i< NO_VAR_BINS; i++)
151      {
152        this->coeffmulti[i] = new Int[numCoef];
153        ::memset(this->coeffmulti[i], 0, sizeof(Int)*numCoef);
154      }
155      this->filterPattern = new Int[NO_VAR_BINS];
156      ::memset(this->filterPattern, 0, sizeof(Int)*NO_VAR_BINS);
157
158      this->nbSPred       = new Int[NO_VAR_BINS];
159      ::memset(this->nbSPred, 0, sizeof(Int)*NO_VAR_BINS);
160
161      this->kMinTab       = new Int[42];
162    }
163    break;
164  case ALF_Cb:
165  case ALF_Cr:
166    {
167      this->coeffmulti = new Int*[1];
168      this->coeffmulti[0] = new Int[numCoef];
169    }
170    break;
171  default:
172    {
173      printf("Not a legal component ID\n");
174      assert(0);
175      exit(-1);
176    }
177  }
178}
179
180Void ALFParam::destroy()
181{
182  if(this->componentID >=0)
183  {
184    switch(this->componentID)
185    {
186    case ALF_Y:
187      {
188        for(Int i=0; i< NO_VAR_BINS; i++)
189        {
190          delete[] this->coeffmulti[i];
191        }
192        delete[] this->coeffmulti;
193        delete[] this->filterPattern;
194        delete[] this->nbSPred;
195        delete[] this->kMinTab;
196      }
197      break;
198    case ALF_Cb:
199    case ALF_Cr:
200      {
201        delete[] this->coeffmulti[0];
202        delete[] this->coeffmulti;
203      }
204      break;
205    default:
206      {
207        printf("Not a legal component ID\n");
208        assert(0);
209        exit(-1);
210      }
211    }
212
213  }
214}
215
216Void ALFParam::copy(const ALFParam& src)
217{
218  const Int numCoef = ALF_MAX_NUM_COEF;
219
220  this->componentID       = src.componentID;
221  this->alf_flag          = src.alf_flag;
222  if(this->alf_flag == 1)
223  {
224    this->filters_per_group = src.filters_per_group;
225    this->filter_shape      = src.filter_shape;
226    this->num_coeff         = src.num_coeff;
227
228    switch(this->componentID)
229    {
230    case ALF_Cb:
231    case ALF_Cr:
232      {
233        ::memcpy(this->coeffmulti[0], src.coeffmulti[0], sizeof(Int)*numCoef);
234      }
235      break;
236    case ALF_Y:
237      {
238        this->startSecondFilter = src.startSecondFilter;
239        this->predMethod        = src.predMethod;
240        this->minKStart         = src.minKStart;
241        ::memcpy(this->filterPattern, src.filterPattern, sizeof(Int)*NO_VAR_BINS);
242        ::memcpy(this->nbSPred, src.nbSPred, sizeof(Int)*NO_VAR_BINS);
243        ::memcpy(this->kMinTab, src.kMinTab, sizeof(Int)*42);
244
245        for(Int i=0; i< (Int)NO_VAR_BINS; i++)
246        {
247          ::memcpy(this->coeffmulti[i], src.coeffmulti[i], sizeof(Int)*numCoef);
248        }
249
250      }
251      break;
252    default:
253      {
254        printf("not a legal component ID\n");
255        assert(0);
256        exit(-1);
257      }
258
259    }
260  }
261  else
262  {
263    //reset
264    this->filters_per_group = 0;
265    this->filter_shape      = 0;
266    this->num_coeff         = 0;
267  }
268}
269
270/// AlfUnitParam
271AlfUnitParam::AlfUnitParam()
272{
273  this->mergeType = ALF_MERGE_DISABLED;
274  this->isEnabled = false;
275  this->isNewFilt = false;
276  this->storedFiltIdx = -1;
277  this->alfFiltParam = NULL;
278
279}
280
281
282
283const AlfUnitParam& AlfUnitParam::operator= (const AlfUnitParam& src)
284{
285  this->mergeType = src.mergeType;
286  this->isEnabled = src.isEnabled;
287  this->isNewFilt = src.isNewFilt;
288  this->storedFiltIdx = src.storedFiltIdx;
289  this->alfFiltParam = src.alfFiltParam; // just a pointer assignment and no additional memory allocation
290
291  return *this;
292}
293
294Bool AlfUnitParam::operator == (const AlfUnitParam& cmp)
295{
296  if( isEnabled != cmp.isEnabled)
297  {
298    return false;
299  }
300
301  //enable flags are the same
302  if(!isEnabled)
303  {
304    return true;
305  }
306
307  //both enabled
308  assert(alfFiltParam->alf_flag == 1);
309
310  const Int numCoef = ALF_MAX_NUM_COEF;
311  ALFParam* cmpAlfParam = cmp.alfFiltParam;
312
313  if(alfFiltParam->componentID == ALF_Y)
314  {
315    if(alfFiltParam->filters_per_group != cmpAlfParam->filters_per_group)
316    {
317      return false;
318    }
319    if(alfFiltParam->predMethod != cmpAlfParam->predMethod)
320    {
321      return false;
322    }
323    if(alfFiltParam->minKStart != cmpAlfParam->minKStart)
324    {
325      return false;
326    }
327    if(alfFiltParam->filters_per_group == 2)
328    {
329      if(alfFiltParam->startSecondFilter != cmpAlfParam->startSecondFilter)
330      {
331        return false;
332      }
333    }
334    if (alfFiltParam->filters_per_group > 1)
335    {
336      for (Int i=0; i<NO_VAR_BINS; i++)
337      {
338        if (alfFiltParam->filterPattern[i] != cmpAlfParam->filterPattern[i])
339        {
340          return false;
341        } 
342      }
343    }     
344    for (Int i=0; i<alfFiltParam->filters_per_group; i++)
345    {
346      if (alfFiltParam->nbSPred[i] != cmpAlfParam->nbSPred[i])
347      {
348        return false;
349      } 
350    }
351  }
352  for(Int f=0; f< alfFiltParam->filters_per_group; f++)
353  {
354    for(Int i=0; i< numCoef; i++)
355    {
356      if(alfFiltParam->coeffmulti[f][i] != cmpAlfParam->coeffmulti[f][i])
357      {
358        return false;
359      }
360    }
361  }
362
363  return true;
364}
365
366
367/// AlfParamSet
368Void AlfParamSet::init()
369{
370  destroy(); 
371  create();
372}
373
374Void AlfParamSet::releaseALFParam()
375{
376  for(Int c=0; c< NUM_ALF_COMPONENT; c++)
377  {
378    if(alfUnitParam[c] != NULL)
379    {
380      for(Int n=0; n< numLCU; n++)
381      {
382        if(alfUnitParam[c][n].alfFiltParam != NULL)
383        {
384          delete alfUnitParam[c][n].alfFiltParam;
385          alfUnitParam[c][n].alfFiltParam = NULL;
386        }
387      }
388    }
389  }
390
391}
392
393Void AlfParamSet::createALFParam()
394{
395  for(Int c=0; c< NUM_ALF_COMPONENT; c++)
396  {
397    for(Int n=0; n< numLCU; n++)
398    {
399      alfUnitParam[c][n].alfFiltParam = new ALFParam(c);
400    }
401  }
402}
403
404/** Create ALF parameter set
405 * \param [in] width number of LCU in width
406 * \param [in] height number of LCU in height
407 * \param [in] num number of LCU in one picture
408 */
409Void AlfParamSet::create(Int width, Int height, Int num)
410{
411  numLCU = num;
412  numLCUInHeight = height;
413  numLCUInWidth  = width;
414
415  for(Int c=0; c< NUM_ALF_COMPONENT; c++)
416  {
417    isEnabled[c] = false;
418    isUniParam[c]= false;
419    if(num !=0)
420    {
421      alfUnitParam[c] = new AlfUnitParam[num];
422    }
423    else
424    {
425      alfUnitParam[c] = NULL;
426    }
427  }
428
429}
430
431Void AlfParamSet::destroy()
432{
433  for(Int c=0; c< NUM_ALF_COMPONENT; c++)
434  {
435    if(alfUnitParam[c] != NULL)
436    {
437      delete[] alfUnitParam[c];
438      alfUnitParam[c] = NULL;
439    }
440  }
441}
442
443
444
445
446
447TComAdaptiveLoopFilter::TComAdaptiveLoopFilter()
448{
449  m_pcTempPicYuv = NULL;
450  m_iSGDepth     = 0;
451  m_pcPic        = NULL;
452  m_ppSliceAlfLCUs = NULL;
453  m_pvpAlfLCU    = NULL;
454  m_pvpSliceTileAlfLCU = NULL;
455  for(Int c=0; c< NUM_ALF_COMPONENT; c++)
456  {
457    m_alfFiltInfo[c] = NULL;
458  }
459  m_varImg = NULL;
460  m_filterCoeffSym = NULL;
461
462}
463
464Void TComAdaptiveLoopFilter:: xError(const char *text, int code)
465{
466  fprintf(stderr, "%s\n", text);
467  exit(code);
468}
469
470Void TComAdaptiveLoopFilter:: no_mem_exit(const char *where)
471{
472  char errortext[200];
473  sprintf(errortext, "Could not allocate memory: %s",where);
474  xError (errortext, 100);
475}
476
477Void TComAdaptiveLoopFilter::initMatrix_Pel(Pel ***m2D, int d1, int d2)
478{
479  int i;
480 
481  if(!(*m2D = (Pel **) calloc(d1, sizeof(Pel *))))
482  {
483    FATAL_ERROR_0("initMatrix_Pel: memory allocation problem\n", -1);
484  }
485  if(!((*m2D)[0] = (Pel *) calloc(d1 * d2, sizeof(Pel))))
486  {
487    FATAL_ERROR_0("initMatrix_Pel: memory allocation problem\n", -1);
488  }
489 
490  for(i = 1; i < d1; i++)
491  {
492    (*m2D)[i] = (*m2D)[i-1] + d2;
493  }
494}
495
496Void TComAdaptiveLoopFilter::initMatrix_int(int ***m2D, int d1, int d2)
497{
498  int i;
499 
500  if(!(*m2D = (int **) calloc(d1, sizeof(int *))))
501  {
502    FATAL_ERROR_0("initMatrix_int: memory allocation problem\n", -1);
503  }
504  if(!((*m2D)[0] = (int *) calloc(d1 * d2, sizeof(int))))
505  {
506    FATAL_ERROR_0("initMatrix_int: memory allocation problem\n", -1);
507  }
508 
509  for(i = 1; i < d1; i++)
510  {
511    (*m2D)[i] = (*m2D)[i-1] + d2;
512  }
513}
514
515Void TComAdaptiveLoopFilter::destroyMatrix_int(int **m2D)
516{
517  if(m2D)
518  {
519    if(m2D[0])
520    {
521      free(m2D[0]);
522    }
523    else
524    {
525      FATAL_ERROR_0("destroyMatrix_int: memory free problem\n", -1);
526    }
527    free(m2D);
528  } 
529  else
530  {
531    FATAL_ERROR_0("destroyMatrix_int: memory free problem\n", -1);
532  }
533}
534
535Void TComAdaptiveLoopFilter::destroyMatrix_Pel(Pel **m2D)
536{
537  if(m2D)
538  {
539    if(m2D[0])
540    {
541      free(m2D[0]);
542    }
543    else
544    {
545      FATAL_ERROR_0("destroyMatrix_Pel: memory free problem\n", -1);
546    }
547    free(m2D);
548  } 
549  else
550  {
551    FATAL_ERROR_0("destroyMatrix_Pel: memory free problem\n", -1);
552  }
553}
554
555Void TComAdaptiveLoopFilter::initMatrix_double(double ***m2D, int d1, int d2)
556{
557  int i;
558 
559  if(!(*m2D = (double **) calloc(d1, sizeof(double *))))
560  {
561    FATAL_ERROR_0("initMatrix_double: memory allocation problem\n", -1);
562  }
563  if(!((*m2D)[0] = (double *) calloc(d1 * d2, sizeof(double))))
564  {
565    FATAL_ERROR_0("initMatrix_double: memory allocation problem\n", -1);
566  }
567 
568  for(i = 1; i < d1; i++)
569  {
570    (*m2D)[i] = (*m2D)[i-1] + d2;
571  }
572}
573
574Void TComAdaptiveLoopFilter::initMatrix3D_double(double ****m3D, int d1, int d2, int d3)
575{
576  int  j;
577 
578  if(!((*m3D) = (double ***) calloc(d1, sizeof(double **))))
579  {
580    FATAL_ERROR_0("initMatrix3D_double: memory allocation problem\n", -1);
581  }
582 
583  for(j = 0; j < d1; j++)
584  {
585    initMatrix_double((*m3D) + j, d2, d3);
586  }
587}
588
589
590Void TComAdaptiveLoopFilter::initMatrix4D_double(double *****m4D, int d1, int d2, int d3, int d4)
591{
592  int  j;
593 
594  if(!((*m4D) = (double ****) calloc(d1, sizeof(double ***))))
595  {
596    FATAL_ERROR_0("initMatrix4D_double: memory allocation problem\n", -1);
597  }
598 
599  for(j = 0; j < d1; j++)
600  {
601    initMatrix3D_double((*m4D) + j, d2, d3, d4);
602  }
603}
604
605
606Void TComAdaptiveLoopFilter::destroyMatrix_double(double **m2D)
607{
608  if(m2D)
609  {
610    if(m2D[0])
611    {
612      free(m2D[0]);
613    }
614    else
615    {
616      FATAL_ERROR_0("destroyMatrix_double: memory free problem\n", -1);
617    }
618    free(m2D);
619  } 
620  else
621  {
622    FATAL_ERROR_0("destroyMatrix_double: memory free problem\n", -1);
623  }
624}
625
626Void TComAdaptiveLoopFilter::destroyMatrix3D_double(double ***m3D, int d1)
627{
628  int i;
629 
630  if(m3D)
631  {
632    for(i = 0; i < d1; i++)
633    {
634      destroyMatrix_double(m3D[i]);
635    }
636    free(m3D);
637  } 
638  else
639  {
640    FATAL_ERROR_0("destroyMatrix3D_double: memory free problem\n", -1);
641  }
642}
643
644
645Void TComAdaptiveLoopFilter::destroyMatrix4D_double(double ****m4D, int d1, int d2)
646{
647  int  j;
648 
649  if(m4D)
650  {
651    for(j = 0; j < d1; j++)
652    {
653      destroyMatrix3D_double(m4D[j], d2);
654    }
655    free(m4D);
656  } 
657  else
658  {
659    FATAL_ERROR_0("destroyMatrix4D_double: memory free problem\n", -1);
660  }
661}
662
663Void TComAdaptiveLoopFilter::create( Int iPicWidth, Int iPicHeight, UInt uiMaxCUWidth, UInt uiMaxCUHeight, UInt uiMaxCUDepth )
664{
665  destroy();
666  if ( !m_pcTempPicYuv )
667  {
668    m_pcTempPicYuv = new TComPicYuv;
669    m_pcTempPicYuv->create( iPicWidth, iPicHeight, uiMaxCUWidth, uiMaxCUHeight, uiMaxCUDepth );
670  }
671  m_img_height = iPicHeight;
672  m_img_width = iPicWidth;
673  initMatrix_Pel(&(m_varImg), m_img_height, m_img_width);
674  initMatrix_int(&m_filterCoeffSym, NO_VAR_BINS, ALF_MAX_NUM_COEF);
675  UInt uiNumLCUsInWidth   = m_img_width  / uiMaxCUWidth;
676  UInt uiNumLCUsInHeight  = m_img_height / uiMaxCUHeight;
677
678  uiNumLCUsInWidth  += ( m_img_width % uiMaxCUWidth ) ? 1 : 0;
679  uiNumLCUsInHeight += ( m_img_height % uiMaxCUHeight ) ? 1 : 0;
680
681  m_uiNumCUsInFrame = uiNumLCUsInWidth* uiNumLCUsInHeight; 
682
683  m_numLCUInPicWidth = uiNumLCUsInWidth;
684  m_numLCUInPicHeight= uiNumLCUsInHeight;
685  m_lcuHeight = uiMaxCUHeight;
686  m_lineIdxPadBot = m_lcuHeight - 4 - 3; // DFRegion, Vertical Taps
687  m_lineIdxPadTop = m_lcuHeight - 4; // DFRegion
688
689  m_lcuHeightChroma = m_lcuHeight>>1;
690  m_lineIdxPadBotChroma = m_lcuHeightChroma - 2 - 3; // DFRegion, Vertical Taps
691  m_lineIdxPadTopChroma = m_lcuHeightChroma - 2 ; // DFRegion
692
693  createLCUAlfInfo();
694}
695
696Void TComAdaptiveLoopFilter::destroy()
697{
698  if ( m_pcTempPicYuv )
699  {
700    m_pcTempPicYuv->destroy();
701    delete m_pcTempPicYuv;
702    m_pcTempPicYuv = NULL;
703  }
704  if(m_varImg != NULL)
705  {
706    destroyMatrix_Pel( m_varImg );
707    m_varImg = NULL;
708  }
709  if(m_filterCoeffSym != NULL)
710  {
711    destroyMatrix_int(m_filterCoeffSym);
712    m_filterCoeffSym = NULL;
713  }
714  destroyLCUAlfInfo();
715
716}
717
718
719// --------------------------------------------------------------------------------------------------------------------
720// interface function for actual ALF process
721// --------------------------------------------------------------------------------------------------------------------
722
723/** ALF reconstruction process for one picture
724 * \param [in, out] pcPic the decoded/filtered picture (input: decoded picture; output filtered picture)
725 * \param [in] vAlfCUCtrlParam ALF CU-on/off control parameters
726 * \param [in] isAlfCoefInSlice ALF coefficient in slice (true) or ALF coefficient in APS (false)
727 */
728Void TComAdaptiveLoopFilter::ALFProcess(TComPic* pcPic, std::vector<AlfCUCtrlInfo>& vAlfCUCtrlParam, Bool isAlfCoefInSlice)
729{
730  TComPicYuv* pcPicYuvRec    = pcPic->getPicYuvRec();
731  TComPicYuv* pcPicYuvExtRec = m_pcTempPicYuv;
732  pcPicYuvRec   ->copyToPic          ( pcPicYuvExtRec );
733  pcPicYuvExtRec->setBorderExtension ( false );
734  pcPicYuvExtRec->extendPicBorder    ();
735
736  Int lumaStride   = pcPicYuvExtRec->getStride();
737  Int chromaStride = pcPicYuvExtRec->getCStride();
738
739  for(Int compIdx =0; compIdx < NUM_ALF_COMPONENT; compIdx++)
740  {
741    Pel* pDec         = getPicBuf(pcPicYuvExtRec, compIdx);
742    Pel* pRest        = getPicBuf(pcPicYuvRec, compIdx);
743    Int  stride       = (compIdx == ALF_Y)?(lumaStride):(chromaStride);
744    Int  formatShift = (compIdx == ALF_Y)?(0):(1);
745
746    ALFParam** alfLCUParamComp = m_alfFiltInfo[compIdx];
747
748    if(!isEnabledComponent(alfLCUParamComp))
749    {
750      continue;
751    }
752
753    switch(compIdx)
754    {
755    case ALF_Cb:
756    case ALF_Cr:
757      {
758        recALF(compIdx, alfLCUParamComp, pDec, pRest, stride, formatShift, NULL, false);
759      }
760      break;
761    case ALF_Y:
762      {
763        std::vector<AlfCUCtrlInfo>* alfCUCtrlParam = NULL;
764        if(!isAlfCoefInSlice)
765        {
766          alfCUCtrlParam = &vAlfCUCtrlParam;
767          assignAlfOnOffControlFlags(pcPic, *alfCUCtrlParam);
768        }
769
770        memset(&m_varImg[0][0], 0, sizeof(Pel)*(m_img_height*m_img_width));
771
772        //calcOneRegionVar(m_varImg, pDec, stride, false, 0, m_img_height, 0, m_img_width);
773        recALF(compIdx, alfLCUParamComp, pDec, pRest, stride, formatShift, alfCUCtrlParam, true);
774      }
775      break;
776    default:
777      {
778        printf("Not a legal component ID for ALF\n");
779        assert(0);
780        exit(-1);
781      }
782    }
783  }
784
785}
786
787/** Check the filter process of one component is enable
788 * \param [in] alfLCUParam ALF parameters
789 */
790Bool TComAdaptiveLoopFilter::isEnabledComponent(ALFParam** alfLCUParam)
791{
792  Bool isEnabled = false;
793  for(Int n=0; n< m_uiNumCUsInFrame; n++)
794  {
795    if(alfLCUParam[n]->alf_flag == 1)
796    {
797      isEnabled = true;
798      break;
799    }
800  }
801  return isEnabled;
802}
803
804
805/** ALF Reconstruction for each component
806 * \param [in] compIdx color component index
807 * \param [in] alfLCUParams alf parameters
808 * \param [in] pDec decoded picture
809 * \param [in, out] pRest filtered picture
810 * \param [in] stride picture stride in memory
811 * \param [in] formatShift luma component (false) or chroma component (1)
812 * \param [in] alfCUCtrlParam ALF CU-on/off control parameters
813 * \param [in] caculateBAIdx calculate BA filter index (true) or BA filter index array is ready (false)
814 */
815Void TComAdaptiveLoopFilter::recALF(Int compIdx, ALFParam** alfLCUParams,Pel* pDec, Pel* pRest, Int stride, Int formatShift
816                                  , std::vector<AlfCUCtrlInfo>* alfCUCtrlParam //default: NULL
817                                  , Bool caculateBAIdx //default: false
818                                    )
819{
820  for(Int s=0; s< m_uiNumSlicesInPic; s++)
821  {
822    if(!m_pcPic->getValidSlice(s))
823    {
824      continue;
825    }
826    Int numTilesInSlice = (Int)m_pvpSliceTileAlfLCU[s].size();
827    for(Int t=0; t< numTilesInSlice; t++)
828    {
829      std::vector<AlfLCUInfo*> & vpAlfLCU = m_pvpSliceTileAlfLCU[s][t];
830      Pel* pSrc = pDec;
831
832      if(m_bUseNonCrossALF)
833      {
834        pSrc = getPicBuf(m_pcSliceYuvTmp, compIdx);
835        copyRegion(vpAlfLCU, pSrc, pDec, stride, formatShift);
836        extendRegionBorder(vpAlfLCU, pSrc, stride, formatShift);
837      }
838
839      Bool isOnOffCtrlEnabled = (alfCUCtrlParam == NULL)?(false):(  (*alfCUCtrlParam)[s].cu_control_flag == 1 );
840
841      if(isOnOffCtrlEnabled)
842      {
843        assert(compIdx == ALF_Y);
844        filterRegionCUControl(alfLCUParams, vpAlfLCU, pSrc, pRest, stride, caculateBAIdx);
845      }
846      else
847      {
848        filterRegion(compIdx, alfLCUParams, vpAlfLCU, pSrc, pRest, stride, formatShift, caculateBAIdx);
849      }
850    } //tile
851  } //slice
852}
853
854
855/** assign ALC CU-On/Off Control parameters
856 * \param [in, out] pcPic picture data
857 * \param [in] vAlfCUCtrlParam ALF CU-on/off control parameters
858 */
859Void TComAdaptiveLoopFilter::assignAlfOnOffControlFlags(TComPic* pcPic, std::vector<AlfCUCtrlInfo>& vAlfCUCtrlParam)
860{
861  if(m_uiNumSlicesInPic == 1)
862  {
863    AlfCUCtrlInfo* pcAlfCtrlParam = &(vAlfCUCtrlParam[0]);
864    if(pcAlfCtrlParam->cu_control_flag)
865    {
866      UInt idx = 0;
867      for(UInt uiCUAddr = 0; uiCUAddr < pcPic->getNumCUsInFrame(); uiCUAddr++)
868      {
869        TComDataCU *pcCU = pcPic->getCU(uiCUAddr);
870        setAlfCtrlFlags(pcAlfCtrlParam, pcCU, 0, 0, idx);
871      }
872    }
873  }
874  else
875  {
876    transferCtrlFlagsFromAlfParam(vAlfCUCtrlParam);
877  }
878
879}
880
881// ====================================================================================================================
882// Protected member functions
883// ====================================================================================================================
884
885/**
886 \param filter         filter coefficient
887 \param filterLength   filter length
888 \param isChroma       1: chroma, 0: luma
889 */
890Void TComAdaptiveLoopFilter::checkFilterCoeffValue( Int *filter, Int filterLength, Bool isChroma )
891{
892#if LCUALF_QP_DEPENDENT_BITS
893  Int alfPrecisionBit = getAlfPrecisionBit( m_alfQP );
894
895  Int maxValueNonCenter = 1 * (1 << alfPrecisionBit) - 1;
896  Int minValueNonCenter = 0 - 1 * (1 << alfPrecisionBit);
897
898  Int maxValueCenter    = 2 * (1 << alfPrecisionBit) - 1;
899#else
900  Int maxValueNonCenter = 1 * (1 << ALF_NUM_BIT_SHIFT) - 1;
901  Int minValueNonCenter = 0 - 1 * (1 << ALF_NUM_BIT_SHIFT);
902
903  Int maxValueCenter    = 2 * (1 << ALF_NUM_BIT_SHIFT) - 1;
904#endif
905  Int minValueCenter    = 0 ; 
906
907  for(Int i = 0; i < filterLength-1; i++)
908  {
909    filter[i] = Clip3(minValueNonCenter, maxValueNonCenter, filter[i]);
910  }
911
912  filter[filterLength-1] = Clip3(minValueCenter, maxValueCenter, filter[filterLength-1]);
913}
914
915
916static Pel Clip_post(int high, int val)
917{
918  return (Pel)(((val > high)? high: val));
919}
920
921
922Void TComAdaptiveLoopFilter::setAlfCtrlFlags(AlfCUCtrlInfo* pAlfParam, TComDataCU *pcCU, UInt uiAbsPartIdx, UInt uiDepth, UInt &idx)
923{
924  TComPic* pcPic = pcCU->getPic();
925  UInt uiCurNumParts    = pcPic->getNumPartInCU() >> (uiDepth<<1);
926  UInt uiQNumParts      = uiCurNumParts>>2;
927 
928  Bool bBoundary = false;
929  UInt uiLPelX   = pcCU->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiAbsPartIdx] ];
930  UInt uiRPelX   = uiLPelX + (g_uiMaxCUWidth>>uiDepth)  - 1;
931  UInt uiTPelY   = pcCU->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiAbsPartIdx] ];
932  UInt uiBPelY   = uiTPelY + (g_uiMaxCUHeight>>uiDepth) - 1;
933 
934  if( ( uiRPelX >= pcCU->getSlice()->getSPS()->getPicWidthInLumaSamples() ) || ( uiBPelY >= pcCU->getSlice()->getSPS()->getPicHeightInLumaSamples() ) )
935  {
936    bBoundary = true;
937  }
938 
939  if( ( ( uiDepth < pcCU->getDepth( uiAbsPartIdx ) ) && ( uiDepth < g_uiMaxCUDepth - g_uiAddCUDepth ) ) || bBoundary )
940  {
941    UInt uiIdx = uiAbsPartIdx;
942    for ( UInt uiPartUnitIdx = 0; uiPartUnitIdx < 4; uiPartUnitIdx++ )
943    {
944      uiLPelX   = pcCU->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiIdx] ];
945      uiTPelY   = pcCU->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiIdx] ];
946     
947      if( ( uiLPelX < pcCU->getSlice()->getSPS()->getPicWidthInLumaSamples() ) && ( uiTPelY < pcCU->getSlice()->getSPS()->getPicHeightInLumaSamples() ) )
948      {
949        setAlfCtrlFlags(pAlfParam, pcCU, uiIdx, uiDepth+1, idx);
950      }
951      uiIdx += uiQNumParts;
952    }
953   
954    return;
955  }
956 
957  if( uiDepth <= pAlfParam->alf_max_depth || pcCU->isFirstAbsZorderIdxInDepth(uiAbsPartIdx, pAlfParam->alf_max_depth))
958  {
959    if (uiDepth > pAlfParam->alf_max_depth)
960    {
961      pcCU->setAlfCtrlFlagSubParts(pAlfParam->alf_cu_flag[idx], uiAbsPartIdx, pAlfParam->alf_max_depth);
962    }
963    else
964    {
965      pcCU->setAlfCtrlFlagSubParts(pAlfParam->alf_cu_flag[idx], uiAbsPartIdx, uiDepth );
966    }
967    idx++;
968  }
969}
970
971/** Initialize the variables for one ALF LCU
972 * \param rAlfLCU to-be-initialized ALF LCU
973 * \param sliceID slice index
974 * \param tileID tile index
975 * \param pcCU CU data pointer
976 * \param maxNumSUInLCU maximum number of SUs in one LCU
977 */
978Void TComAdaptiveLoopFilter::InitAlfLCUInfo(AlfLCUInfo& rAlfLCU, Int sliceID, Int tileID, TComDataCU* pcCU, UInt maxNumSUInLCU)
979{
980  //pcCU
981  rAlfLCU.pcCU     = pcCU;
982  //sliceID
983  rAlfLCU.sliceID = sliceID;
984  //tileID
985  rAlfLCU.tileID  = tileID;
986
987  //numSGU, vpAlfBLock;
988  std::vector<NDBFBlockInfo>& vNDBFBlock = *(pcCU->getNDBFilterBlocks());
989  rAlfLCU.vpAlfBlock.clear();
990  rAlfLCU.numSGU = 0;
991  for(Int i=0; i< vNDBFBlock.size(); i++)
992  {
993    if( vNDBFBlock[i].sliceID == sliceID)
994    {
995      rAlfLCU.vpAlfBlock.push_back( &(vNDBFBlock[i])  );
996      rAlfLCU.numSGU ++;
997    }
998  }
999  //startSU
1000  rAlfLCU.startSU = rAlfLCU.vpAlfBlock.front()->startSU;
1001  //endSU
1002  rAlfLCU.endSU   = rAlfLCU.vpAlfBlock.back()->endSU;
1003  //bAllSUsInLCUInSameSlice
1004  rAlfLCU.bAllSUsInLCUInSameSlice = (rAlfLCU.startSU == 0)&&( rAlfLCU.endSU == maxNumSUInLCU -1);
1005}
1006
1007/** create and initialize variables for picture ALF processing
1008 * \param pcPic picture-level data pointer
1009 * \param numSlicesInPic number of slices in picture
1010 */
1011Void TComAdaptiveLoopFilter::createPicAlfInfo(TComPic* pcPic, Int numSlicesInPic, Int alfQP)
1012{
1013  m_uiNumSlicesInPic = numSlicesInPic;
1014  m_iSGDepth         = pcPic->getSliceGranularityForNDBFilter();
1015
1016  m_bUseNonCrossALF = ( pcPic->getIndependentSliceBoundaryForNDBFilter() || pcPic->getIndependentTileBoundaryForNDBFilter());
1017  m_pcPic = pcPic;
1018
1019  m_isNonCrossSlice = pcPic->getIndependentSliceBoundaryForNDBFilter(); 
1020  m_suWidth = pcPic->getMinCUWidth();
1021  m_suHeight= pcPic->getMinCUHeight();
1022  m_alfQP = alfQP; 
1023    m_ppSliceAlfLCUs = new AlfLCUInfo*[m_uiNumSlicesInPic];
1024    m_pvpAlfLCU = new std::vector< AlfLCUInfo* >[m_uiNumSlicesInPic];
1025    m_pvpSliceTileAlfLCU = new std::vector< std::vector< AlfLCUInfo* > >[m_uiNumSlicesInPic];
1026
1027    for(Int s=0; s< m_uiNumSlicesInPic; s++)
1028    {
1029      m_ppSliceAlfLCUs[s] = NULL;
1030      if(!pcPic->getValidSlice(s))
1031      {
1032        continue;
1033      }
1034
1035      std::vector< TComDataCU* >& vSliceLCUPointers = pcPic->getOneSliceCUDataForNDBFilter(s);
1036      Int                         numLCU           = (Int)vSliceLCUPointers.size();
1037
1038      //create Alf LCU info
1039      m_ppSliceAlfLCUs[s] = new AlfLCUInfo[numLCU];
1040      for(Int i=0; i< numLCU; i++)
1041      {
1042        TComDataCU* pcCU       = vSliceLCUPointers[i];
1043        if(pcCU->getPic()==0)
1044        {
1045          continue;
1046        }
1047        Int         currTileID = pcPic->getPicSym()->getTileIdxMap(pcCU->getAddr());
1048
1049        InitAlfLCUInfo(m_ppSliceAlfLCUs[s][i], s, currTileID, pcCU, pcPic->getNumPartInCU());
1050      }
1051
1052      //distribute Alf LCU info pointers to slice container
1053      std::vector< AlfLCUInfo* >&    vpSliceAlfLCU     = m_pvpAlfLCU[s]; 
1054      vpSliceAlfLCU.reserve(numLCU);
1055      vpSliceAlfLCU.resize(0);
1056      std::vector< std::vector< AlfLCUInfo* > > &vpSliceTileAlfLCU = m_pvpSliceTileAlfLCU[s];
1057      Int prevTileID = -1;
1058      Int numValidTilesInSlice = 0;
1059
1060      for(Int i=0; i< numLCU; i++)
1061      {
1062        AlfLCUInfo* pcAlfLCU = &(m_ppSliceAlfLCUs[s][i]);
1063
1064        //container of Alf LCU pointers for slice processing
1065        vpSliceAlfLCU.push_back( pcAlfLCU);
1066
1067        if(pcAlfLCU->tileID != prevTileID)
1068        {
1069          if(prevTileID == -1 || pcPic->getIndependentTileBoundaryForNDBFilter())
1070          {
1071            prevTileID = pcAlfLCU->tileID;
1072            numValidTilesInSlice ++;
1073            vpSliceTileAlfLCU.resize(numValidTilesInSlice);
1074          }
1075        }
1076        //container of Alf LCU pointers for tile processing
1077        vpSliceTileAlfLCU[numValidTilesInSlice-1].push_back(pcAlfLCU);
1078      }
1079
1080      assert( vpSliceAlfLCU.size() == numLCU);
1081    }
1082 
1083    if(m_bUseNonCrossALF)
1084    {
1085      m_pcSliceYuvTmp = pcPic->getYuvPicBufferForIndependentBoundaryProcessing();
1086    }
1087
1088}
1089
1090/** Destroy ALF slice units
1091 */
1092Void TComAdaptiveLoopFilter::destroyPicAlfInfo()
1093{
1094    for(Int s=0; s< m_uiNumSlicesInPic; s++)
1095    {
1096      if(m_ppSliceAlfLCUs[s] != NULL)
1097      {
1098        delete[] m_ppSliceAlfLCUs[s];
1099        m_ppSliceAlfLCUs[s] = NULL;
1100      }
1101    }
1102    delete[] m_ppSliceAlfLCUs;
1103    m_ppSliceAlfLCUs = NULL;
1104
1105    delete[] m_pvpAlfLCU;
1106    m_pvpAlfLCU = NULL;
1107
1108    delete[] m_pvpSliceTileAlfLCU;
1109    m_pvpSliceTileAlfLCU = NULL;
1110}
1111
1112
1113/** Copy ALF CU control flags from ALF parameters for slices
1114 * \param [in] vAlfParamSlices ALF CU control parameters
1115 */
1116Void TComAdaptiveLoopFilter::transferCtrlFlagsFromAlfParam(std::vector<AlfCUCtrlInfo>& vAlfParamSlices)
1117{
1118  assert(m_uiNumSlicesInPic == vAlfParamSlices.size());
1119
1120  for(UInt s=0; s< m_uiNumSlicesInPic; s++)
1121  {
1122    AlfCUCtrlInfo& rAlfParam = vAlfParamSlices[s];
1123    transferCtrlFlagsFromAlfParamOneSlice( m_pvpAlfLCU[s], 
1124      (rAlfParam.cu_control_flag ==1)?true:false, 
1125      rAlfParam.alf_max_depth, 
1126      rAlfParam.alf_cu_flag
1127      );
1128  }
1129}
1130/** Copy ALF CU control flags from ALF CU control parameters for one slice
1131 * \param [in] vpAlfLCU ALF LCU data container
1132 * \param [in] bCUCtrlEnabled true for ALF CU control enabled
1133 * \param [in] iAlfDepth ALF CU control depth
1134 * \param [in] vCtrlFlags ALF CU control flags
1135 */
1136Void TComAdaptiveLoopFilter::transferCtrlFlagsFromAlfParamOneSlice(std::vector< AlfLCUInfo* > &vpAlfLCU, Bool bCUCtrlEnabled, Int iAlfDepth, std::vector<UInt>& vCtrlFlags)
1137{
1138
1139  if(!bCUCtrlEnabled)
1140  {
1141    for(Int idx=0; idx< vpAlfLCU.size(); idx++)
1142    {
1143      AlfLCUInfo& cAlfLCU = *(vpAlfLCU[idx]);
1144      if(cAlfLCU.pcCU==0)
1145      {
1146        return;
1147      }
1148      if( cAlfLCU.bAllSUsInLCUInSameSlice)
1149      {
1150        cAlfLCU.pcCU->setAlfCtrlFlagSubParts(1, 0, 0);
1151      }
1152      else
1153      {
1154        for(UInt uiCurrSU= cAlfLCU.startSU; uiCurrSU<= cAlfLCU.endSU; uiCurrSU++)
1155        {
1156          cAlfLCU.pcCU->setAlfCtrlFlag(uiCurrSU, 1);
1157        }
1158      }
1159    }
1160    return;
1161  }
1162
1163  UInt uiNumCtrlFlags = 0;
1164  for(Int idx=0; idx< vpAlfLCU.size(); idx++)
1165  {
1166    AlfLCUInfo& cAlfLCU = *(vpAlfLCU[idx]);
1167
1168    if(cAlfLCU.pcCU==NULL)
1169    {
1170      continue;
1171    }
1172    uiNumCtrlFlags += (UInt)getCtrlFlagsFromAlfParam(&cAlfLCU, iAlfDepth, &(vCtrlFlags[uiNumCtrlFlags]) );
1173  }
1174}
1175
1176/** Copy region pixels
1177 * \param vpAlfLCU ALF LCU data container
1178 * \param pPicDst destination picture buffer
1179 * \param pPicSrc source picture buffer
1180 * \param stride stride size of picture buffer
1181 * \param formatShift region size adjustment according to component size
1182 */
1183Void TComAdaptiveLoopFilter::copyRegion(std::vector< AlfLCUInfo* > &vpAlfLCU, Pel* pPicDst, Pel* pPicSrc, Int stride, Int formatShift)
1184{
1185  Int extSize = 4;
1186  Int posX, posY, width, height, offset;
1187  Pel *pPelDst, *pPelSrc;
1188 
1189  for(Int idx =0; idx < vpAlfLCU.size(); idx++)
1190  {
1191    AlfLCUInfo& cAlfLCU = *(vpAlfLCU[idx]);
1192    for(Int n=0; n < cAlfLCU.numSGU; n++)
1193    {
1194      NDBFBlockInfo& rSGU = cAlfLCU[n];
1195
1196      posX     = (Int)(rSGU.posX   >> formatShift);
1197      posY     = (Int)(rSGU.posY   >> formatShift);
1198      width    = (Int)(rSGU.width  >> formatShift);
1199      height   = (Int)(rSGU.height >> formatShift);
1200      offset   = ( (posY- extSize) * stride)+ (posX -extSize);
1201      pPelDst  = pPicDst + offset;   
1202      pPelSrc  = pPicSrc + offset;   
1203
1204      for(Int j=0; j< (height + (extSize<<1)); j++)
1205      {
1206        ::memcpy(pPelDst, pPelSrc, sizeof(Pel)*(width + (extSize<<1)));
1207        pPelDst += stride;
1208        pPelSrc += stride;
1209      }
1210    }
1211  }
1212}
1213
1214/** Extend region boundary
1215 * \param [in] vpAlfLCU ALF LCU data container
1216 * \param [in,out] pPelSrc picture buffer
1217 * \param [in] stride stride size of picture buffer
1218 * \param [in] formatShift region size adjustment according to component size
1219 */
1220Void TComAdaptiveLoopFilter::extendRegionBorder(std::vector< AlfLCUInfo* > &vpAlfLCU, Pel* pPelSrc, Int stride, Int formatShift)
1221{
1222  UInt extSize = 4;
1223  UInt width, height;
1224  UInt posX, posY;
1225  Pel* pPel;
1226  Bool* pbAvail;
1227  for(Int idx = 0; idx < vpAlfLCU.size(); idx++)
1228  {
1229    AlfLCUInfo& rAlfLCU = *(vpAlfLCU[idx]);
1230    for(Int n =0; n < rAlfLCU.numSGU; n++)
1231    {
1232      NDBFBlockInfo& rSGU = rAlfLCU[n];
1233      if(rSGU.allBordersAvailable)
1234      {
1235        continue;
1236      }
1237      posX     = rSGU.posX >> formatShift;
1238      posY     = rSGU.posY >> formatShift;
1239      width    = rSGU.width >> formatShift;
1240      height   = rSGU.height >> formatShift;
1241      pbAvail  = rSGU.isBorderAvailable;   
1242      pPel     = pPelSrc + (posY * stride)+ posX;   
1243      extendBorderCoreFunction(pPel, stride, pbAvail, width, height, extSize);
1244    }
1245  }
1246}
1247
1248/** Core function for extending slice/tile boundary
1249 * \param [in, out] pPel processing block pointer
1250 * \param [in] stride picture buffer stride
1251 * \param [in] pbAvail neighboring blocks availabilities
1252 * \param [in] width block width
1253 * \param [in] height block height
1254 * \param [in] extSize boundary extension size
1255 */
1256Void TComAdaptiveLoopFilter::extendBorderCoreFunction(Pel* pPel, Int stride, Bool* pbAvail, UInt width, UInt height, UInt extSize)
1257{
1258  Pel* pPelDst;
1259  Pel* pPelSrc;
1260  Int i, j;
1261
1262  for(Int pos =0; pos < NUM_SGU_BORDER; pos++)
1263  {
1264    if(pbAvail[pos])
1265    {
1266      continue;
1267    }
1268
1269    switch(pos)
1270    {
1271    case SGU_L:
1272      {
1273        pPelDst = pPel - extSize;
1274        pPelSrc = pPel;
1275        for(j=0; j< height; j++)
1276        {
1277          for(i=0; i< extSize; i++)
1278          {
1279            pPelDst[i] = *pPelSrc;
1280          }
1281          pPelDst += stride;
1282          pPelSrc += stride;
1283        }
1284      }
1285      break;
1286    case SGU_R:
1287      {
1288        pPelDst = pPel + width;
1289        pPelSrc = pPelDst -1;
1290        for(j=0; j< height; j++)
1291        {
1292          for(i=0; i< extSize; i++)
1293          {
1294            pPelDst[i] = *pPelSrc;
1295          }
1296          pPelDst += stride;
1297          pPelSrc += stride;
1298        }
1299
1300      }
1301      break;
1302    case SGU_T:
1303      {
1304        pPelSrc = pPel;
1305        pPelDst = pPel - stride;
1306        for(j=0; j< extSize; j++)
1307        {
1308          ::memcpy(pPelDst, pPelSrc, sizeof(Pel)*width);
1309          pPelDst -= stride;
1310        }
1311      }
1312      break;
1313    case SGU_B:
1314      {
1315        pPelDst = pPel + height*stride;
1316        pPelSrc = pPelDst - stride;
1317        for(j=0; j< extSize; j++)
1318        {
1319          ::memcpy(pPelDst, pPelSrc, sizeof(Pel)*width);
1320          pPelDst += stride;
1321        }
1322
1323      }
1324      break;
1325    case SGU_TL:
1326      {
1327        if( (!pbAvail[SGU_T]) && (!pbAvail[SGU_L]))
1328        {
1329          pPelSrc = pPel  - extSize;
1330          pPelDst = pPelSrc - stride;
1331          for(j=0; j< extSize; j++)
1332          {
1333            ::memcpy(pPelDst, pPelSrc, sizeof(Pel)*extSize);
1334            pPelDst -= stride;
1335          }         
1336        }
1337      }
1338      break;
1339    case SGU_TR:
1340      {
1341        if( (!pbAvail[SGU_T]) && (!pbAvail[SGU_R]))
1342        {
1343          pPelSrc = pPel + width;
1344          pPelDst = pPelSrc - stride;
1345          for(j=0; j< extSize; j++)
1346          {
1347            ::memcpy(pPelDst, pPelSrc, sizeof(Pel)*extSize);
1348            pPelDst -= stride;
1349          }
1350
1351        }
1352
1353      }
1354      break;
1355    case SGU_BL:
1356      {
1357        if( (!pbAvail[SGU_B]) && (!pbAvail[SGU_L]))
1358        {
1359          pPelDst = pPel + height*stride; pPelDst-= extSize;
1360          pPelSrc = pPelDst - stride;
1361          for(j=0; j< extSize; j++)
1362          {
1363            ::memcpy(pPelDst, pPelSrc, sizeof(Pel)*extSize);
1364            pPelDst += stride;
1365          }
1366
1367        }
1368      }
1369      break;
1370    case SGU_BR:
1371      {
1372        if( (!pbAvail[SGU_B]) && (!pbAvail[SGU_R]))
1373        {
1374          pPelDst = pPel + height*stride; pPelDst += width;
1375          pPelSrc = pPelDst - stride;
1376          for(j=0; j< extSize; j++)
1377          {
1378            ::memcpy(pPelDst, pPelSrc, sizeof(Pel)*extSize);
1379            pPelDst += stride;
1380          }
1381        }
1382      }
1383      break;
1384    default:
1385      {
1386        printf("Not a legal neighboring availability\n");
1387        assert(0);
1388        exit(-1);
1389      }
1390    }
1391  }
1392}
1393
1394/** Assign ALF on/off-control flags from ALF parameters to CU data
1395 * \param [in] pcAlfLCU processing ALF LCU data pointer
1396 * \param [in] alfDepth ALF on/off-control depth
1397 * \param [in] pFlags on/off-control flags buffer in ALF parameters
1398 */
1399Int TComAdaptiveLoopFilter::getCtrlFlagsFromAlfParam(AlfLCUInfo* pcAlfLCU, Int alfDepth, UInt* pFlags)
1400{
1401
1402  const UInt startSU               = pcAlfLCU->startSU;
1403  const UInt endSU                 = pcAlfLCU->endSU;
1404  const Bool bAllSUsInLCUInSameSlice = pcAlfLCU->bAllSUsInLCUInSameSlice;
1405  const UInt maxNumSUInLCU         = m_pcPic->getNumPartInCU();
1406
1407  TComDataCU* pcCU = pcAlfLCU->pcCU;
1408  Int   numCUCtrlFlags = 0;
1409
1410  UInt  currSU, CUDepth, setDepth, ctrlNumSU;
1411  UInt  alfFlag;
1412
1413  currSU = startSU;
1414  if( bAllSUsInLCUInSameSlice ) 
1415  {
1416    while(currSU < maxNumSUInLCU)
1417    {
1418      //depth of this CU
1419      CUDepth = pcCU->getDepth(currSU);
1420
1421      //choose the min. depth for ALF
1422      setDepth   = (alfDepth < CUDepth)?(alfDepth):(CUDepth);
1423      ctrlNumSU = maxNumSUInLCU >> (setDepth << 1);
1424
1425      alfFlag= pFlags[numCUCtrlFlags];
1426
1427      pcCU->setAlfCtrlFlagSubParts(alfFlag, currSU, (UInt)setDepth);
1428
1429      numCUCtrlFlags++;
1430      currSU += ctrlNumSU;
1431    }
1432    return numCUCtrlFlags;
1433  }
1434
1435
1436  UInt  LCUX    = pcCU->getCUPelX();
1437  UInt  LCUY    = pcCU->getCUPelY();
1438
1439  Bool  bFirst, bValidCU;
1440  UInt  idx, LPelXSU, TPelYSU;
1441
1442  bFirst= true;
1443  while(currSU <= endSU)
1444  {
1445    //check picture boundary
1446    while(!( LCUX + g_auiRasterToPelX[ g_auiZscanToRaster[currSU] ] < m_img_width  ) || 
1447          !( LCUY + g_auiRasterToPelY[ g_auiZscanToRaster[currSU] ] < m_img_height )
1448      )
1449    {
1450      currSU++;
1451      if(currSU >= maxNumSUInLCU || currSU > endSU)
1452      {
1453        break;
1454      }
1455    }
1456
1457    if(currSU >= maxNumSUInLCU || currSU > endSU)
1458    {
1459      break;
1460    }
1461
1462    //depth of this CU
1463    CUDepth = pcCU->getDepth(currSU);
1464
1465    //choose the min. depth for ALF
1466    setDepth   = (alfDepth < CUDepth)?(alfDepth):(CUDepth);
1467    ctrlNumSU = maxNumSUInLCU >> (setDepth << 1);
1468
1469    if(bFirst)
1470    {
1471      if(currSU !=0 )
1472      {
1473        currSU = ((UInt)(currSU/ctrlNumSU))* ctrlNumSU;
1474      }
1475      bFirst = false;
1476    }
1477
1478    //alf flag for this CU
1479    alfFlag= pFlags[numCUCtrlFlags];
1480
1481    bValidCU = false;
1482    for(idx = currSU; idx < currSU + ctrlNumSU; idx++)
1483    {
1484      if(idx < startSU || idx > endSU)
1485      {
1486        continue;
1487      }
1488
1489      LPelXSU   = LCUX + g_auiRasterToPelX[ g_auiZscanToRaster[idx] ];
1490      TPelYSU   = LCUY + g_auiRasterToPelY[ g_auiZscanToRaster[idx] ];
1491
1492      if( !( LPelXSU < m_img_width )  || !( TPelYSU < m_img_height )  )
1493      {
1494        continue;
1495      }
1496
1497      bValidCU = true;
1498      pcCU->setAlfCtrlFlag(idx, alfFlag);
1499    }
1500
1501    if(bValidCU)
1502    {
1503      numCUCtrlFlags++;
1504    }
1505
1506    currSU += ctrlNumSU;
1507  }
1508
1509  return numCUCtrlFlags;
1510}
1511
1512/** reconstruct ALF luma coefficient
1513 * \param [in] alfLCUParam ALF parameters
1514 * \param [out] filterCoeff reconstructed luma coefficients
1515 */
1516Void TComAdaptiveLoopFilter::reconstructLumaCoefficients(ALFParam* alfLCUParam, Int** filterCoeff)
1517{
1518  Int sum, coeffPred, ind;
1519#if LCUALF_QP_DEPENDENT_BITS
1520  Int alfPrecisionBit = getAlfPrecisionBit( m_alfQP );
1521#endif
1522  const Int* filtMag = NULL;
1523  filtMag = weightsTabShapes[0];
1524
1525  // Undo intra-filter prediction
1526  for(ind = 0; ind < alfLCUParam->filters_per_group; ind++)
1527  {
1528    sum = 0;
1529
1530    for(Int i = 0; i < alfLCUParam->num_coeff-2; i++)
1531    {
1532      sum += (filtMag[i] * alfLCUParam->coeffmulti[ind][i]);
1533      filterCoeff[ind][i] = alfLCUParam->coeffmulti[ind][i];
1534    }
1535
1536    if(alfLCUParam->nbSPred[ind] == 0)
1537    {
1538      if((alfLCUParam->predMethod==0)|(ind==0))
1539      {
1540#if LCUALF_QP_DEPENDENT_BITS
1541        coeffPred = ((1<<alfPrecisionBit)-sum) >> 2;
1542#else
1543        coeffPred = ((1<<ALF_NUM_BIT_SHIFT)-sum) >> 2;
1544#endif
1545      }
1546      else
1547      {
1548        coeffPred = (0-sum) >> 2;
1549      }
1550
1551      filterCoeff[ind][alfLCUParam->num_coeff-2] = coeffPred + alfLCUParam->coeffmulti[ind][alfLCUParam->num_coeff-2];
1552    }
1553    else
1554    {
1555      filterCoeff[ind][alfLCUParam->num_coeff-2] = alfLCUParam->coeffmulti[ind][alfLCUParam->num_coeff-2];
1556    }
1557
1558    sum += filtMag[alfLCUParam->num_coeff-2] * filterCoeff[ind][alfLCUParam->num_coeff-2];
1559
1560    if((alfLCUParam->predMethod==0)|(ind==0))
1561    {
1562#if LCUALF_QP_DEPENDENT_BITS
1563      coeffPred = (1<<alfPrecisionBit)-sum;
1564#else
1565      coeffPred = (1<<ALF_NUM_BIT_SHIFT)-sum;
1566#endif
1567    }
1568    else
1569    {
1570      coeffPred = -sum;
1571    }
1572
1573    filterCoeff[ind][alfLCUParam->num_coeff-1] = coeffPred + alfLCUParam->coeffmulti[ind][alfLCUParam->num_coeff-1];
1574  }
1575
1576
1577  // Undo inter-filter prediction
1578  for(ind = 1; ind < alfLCUParam->filters_per_group; ind++)
1579  {
1580    if(alfLCUParam->predMethod)
1581    {
1582      // Prediction
1583      for(Int i = 0; i < alfLCUParam->num_coeff; i++)
1584      {
1585        filterCoeff[ind][i] = (int)(filterCoeff[ind][i] + filterCoeff[ind - 1][i]);
1586      }
1587    }
1588  }
1589
1590}
1591
1592
1593/** reconstruct ALF chroma coefficient
1594 * \param [in] alfLCUParam ALF parameters
1595 * \param [out] filterCoeff reconstructed chroma coefficients
1596 */
1597Void TComAdaptiveLoopFilter::reconstructChromaCoefficients(ALFParam* alfLCUParam, Int** filterCoeff)
1598{
1599  Int sum = 0;
1600  Int i, coeffPred;
1601  const Int* filtMag = NULL;
1602  filtMag = weightsTabShapes[0];
1603
1604  for(i=0; i<alfLCUParam->num_coeff-1; i++)
1605  {
1606    sum += (filtMag[i] * alfLCUParam->coeffmulti[0][i]);
1607    filterCoeff[0][i] = alfLCUParam->coeffmulti[0][i];
1608  }
1609
1610#if LCUALF_QP_DEPENDENT_BITS
1611  Int alfPrecisionBit = getAlfPrecisionBit( m_alfQP );
1612  coeffPred = (1<<alfPrecisionBit) - sum;
1613#else
1614  coeffPred = (1<<ALF_NUM_BIT_SHIFT) - sum;
1615#endif
1616  filterCoeff[0][alfLCUParam->num_coeff-1] = coeffPred + alfLCUParam->coeffmulti[0][alfLCUParam->num_coeff-1];
1617}
1618
1619
1620/** reconstruct ALF coefficient
1621 * \param [in] compIdx component index
1622 * \param [in] alfLCUParam ALF parameters
1623 * \param [out] filterCoeff reconstructed coefficients
1624 * \param [out] varIndTab the merged groups in block-based adaptation mode
1625 */
1626Void TComAdaptiveLoopFilter::reconstructCoefInfo(Int compIdx, ALFParam* alfLCUParam, Int** filterCoeff, Int* varIndTab)
1627{
1628  switch(compIdx)
1629  {
1630  case ALF_Cb:
1631  case ALF_Cr:
1632    {
1633      alfLCUParam->filters_per_group = 1;
1634      reconstructChromaCoefficients(alfLCUParam, filterCoeff);
1635    }
1636    break;
1637  case ALF_Y:
1638    {
1639      ::memset(varIndTab, 0, NO_VAR_BINS * sizeof(Int));
1640      if(alfLCUParam->filters_per_group > 1)
1641      {
1642        for(Int i = 1; i < NO_VAR_BINS; ++i)
1643        {
1644          if(alfLCUParam->filterPattern[i])
1645          {
1646            varIndTab[i] = varIndTab[i-1] + 1;
1647          }
1648          else
1649          {
1650            varIndTab[i] = varIndTab[i-1];
1651          }
1652        }
1653      }
1654      reconstructLumaCoefficients(alfLCUParam, filterCoeff);
1655    }
1656    break;
1657  default:
1658    {
1659      printf("not legal component ID for ALF\n");
1660      assert(0);
1661      exit(-1);
1662    }
1663  }
1664
1665}
1666
1667
1668/** filter process with CU-On/Off control
1669 * \param [in] alfLCUParam ALF parameters
1670 * \param [in] regionLCUInfo ALF CU-on/off control parameters
1671 * \param [in] pDec decoded picture
1672 * \param [out] pRest filtered picture
1673 * \param [in] stride picture stride in memory
1674 * \param [in] caculateBAIdx calculate BA filter index (true) or BA filter index array is ready (false)
1675 */
1676Void TComAdaptiveLoopFilter::filterRegionCUControl(ALFParam** alfLCUParams, std::vector<AlfLCUInfo*>& regionLCUInfo, Pel* pDec, Pel* pRest, Int stride, Bool caculateBAIdx)
1677{
1678  Int ypos, xpos, currSU, startSU, endSU, lcuX, lcuY;
1679  Int yposEnd, xposEnd;
1680
1681  for(Int i=0; i< (Int)regionLCUInfo.size(); i++)
1682  {
1683    AlfLCUInfo& alfLCUinfo = *(regionLCUInfo[i]); 
1684    TComDataCU* pcCU = alfLCUinfo.pcCU;
1685    Int addr = pcCU->getAddr();
1686
1687    ALFParam* alfParam = alfLCUParams[addr];
1688
1689    if(alfParam->alf_flag == 1)
1690    {
1691      lcuX    = pcCU->getCUPelX();
1692      lcuY    = pcCU->getCUPelY();
1693
1694      if(caculateBAIdx)
1695      {
1696        xposEnd = lcuX + g_uiMaxCUWidth;
1697        yposEnd = lcuY + g_uiMaxCUHeight;
1698
1699        if(xposEnd > m_img_width)
1700        {
1701          xposEnd = m_img_width;
1702        }
1703
1704        if(yposEnd > m_img_height)
1705        {
1706          yposEnd = m_img_height;
1707        }
1708
1709        calcOneRegionVar(m_varImg, pDec, stride, (alfParam->filters_per_group == 1), lcuY, yposEnd, lcuX, xposEnd);       
1710      }
1711
1712      //reconstruct ALF coefficients & related parameters
1713      reconstructCoefInfo(ALF_Y, alfParam, m_filterCoeffSym, m_varIndTab);
1714
1715      startSU = alfLCUinfo.startSU;
1716      endSU   = alfLCUinfo.endSU;
1717
1718
1719      for(currSU= startSU; currSU<= endSU; currSU++)
1720      {
1721        xpos  = lcuX + g_auiRasterToPelX[ g_auiZscanToRaster[currSU] ];
1722        ypos  = lcuY + g_auiRasterToPelY[ g_auiZscanToRaster[currSU] ];
1723        if( !( xpos < m_img_width )  || !( ypos < m_img_height )  )
1724        {
1725          continue;
1726        }
1727
1728        if(pcCU->getAlfCtrlFlag(currSU))
1729        {
1730          filterOneCompRegion(pRest, pDec, stride, false, ypos, ypos+m_suHeight, xpos, xpos+m_suWidth, m_filterCoeffSym, m_varIndTab, m_varImg);
1731        }
1732      }
1733
1734    } //alf_flag == 1
1735  }
1736
1737}
1738
1739
1740/** filter process without CU-On/Off control
1741 * \param [in] alfLCUParam ALF parameters
1742 * \param [in] regionLCUInfo ALF CU-on/off control parameters
1743 * \param [in] pDec decoded picture
1744 * \param [out] pRest filtered picture
1745 * \param [in] stride picture stride in memory
1746 * \param [in] formatShift luma component (0) or chroma component (1)
1747 * \param [in] caculateBAIdx calculate BA filter index (true) or BA filter index array is ready (false)
1748 */
1749Void TComAdaptiveLoopFilter::filterRegion(Int compIdx, ALFParam** alfLCUParams, std::vector<AlfLCUInfo*>& regionLCUInfo, Pel* pDec, Pel* pRest, Int stride, Int formatShift, Bool caculateBAIdx)
1750{
1751  Int height, width;
1752  Int ypos, xpos,  lcuX, lcuY;
1753  Int yposEnd, xposEnd;
1754
1755  for(Int i=0; i< regionLCUInfo.size(); i++)
1756  {
1757    AlfLCUInfo& alfLCUinfo = *(regionLCUInfo[i]); 
1758    TComDataCU* pcCU = alfLCUinfo.pcCU;
1759    Int addr = pcCU->getAddr();
1760
1761    ALFParam* alfParam = alfLCUParams[addr];
1762
1763    if(alfParam->alf_flag == 1)
1764    {
1765      lcuX    = pcCU->getCUPelX();
1766      lcuY    = pcCU->getCUPelY();
1767
1768      if(caculateBAIdx)
1769      {
1770        assert(compIdx == ALF_Y);
1771
1772        xposEnd = lcuX + g_uiMaxCUWidth;
1773        yposEnd = lcuY + g_uiMaxCUHeight;
1774
1775        if(xposEnd > m_img_width)
1776        {
1777          xposEnd = m_img_width;
1778        }
1779
1780        if(yposEnd > m_img_height)
1781        {
1782          yposEnd = m_img_height;
1783        }
1784
1785        calcOneRegionVar(m_varImg, pDec, stride, (alfParam->filters_per_group == 1), lcuY, yposEnd, lcuX, xposEnd);       
1786      }
1787
1788      //reconstruct ALF coefficients & related parameters
1789      reconstructCoefInfo(compIdx, alfParam, m_filterCoeffSym, m_varIndTab);
1790
1791      //filtering process
1792      for(Int j=0; j< alfLCUinfo.numSGU; j++)
1793      {
1794        ypos    = (Int)(alfLCUinfo[j].posY   >> formatShift);
1795        xpos    = (Int)(alfLCUinfo[j].posX   >> formatShift);
1796        height = (Int)(alfLCUinfo[j].height >> formatShift);
1797        width  = (Int)(alfLCUinfo[j].width  >> formatShift);
1798
1799        filterOneCompRegion(pRest, pDec, stride, (compIdx!=ALF_Y), ypos, ypos+height, xpos, xpos+width, m_filterCoeffSym, m_varIndTab, m_varImg);
1800      }
1801    } //alf_flag == 1
1802  }
1803}
1804
1805
1806/** predict chroma center coefficient
1807 * \param [in] coeff ALF chroma coefficient
1808 * \param [in] numCoef number of chroma coefficients
1809 */
1810Void TComAdaptiveLoopFilter::predictALFCoeffChroma(Int* coeff, Int numCoef)
1811{
1812  Int sum=0;
1813  for(Int i=0; i< numCoef-1;i++)
1814  {
1815    sum += (2* coeff[i]);
1816  }
1817
1818#if LCUALF_QP_DEPENDENT_BITS
1819  Int alfPrecisionBit = getAlfPrecisionBit( m_alfQP );
1820  Int pred = (1<<alfPrecisionBit) - (sum);
1821#else
1822  Int pred = (1<<ALF_NUM_BIT_SHIFT) - (sum);
1823#endif
1824  coeff[numCoef-1] = coeff[numCoef-1] - pred;
1825}
1826
1827/** filtering pixels
1828 * \param [out] imgRes filtered picture
1829 * \param [in] imgPad decoded picture
1830 * \param [in] stride picture stride in memory
1831 * \param [in] isChroma chroma component (true) or luma component (false)
1832 * \param [in] yPos y position of the top-left pixel in one to-be-filtered region
1833 * \param [in] yPosEnd y position of the right-bottom pixel in one to-be-filtered region
1834 * \param [in] xPos x position of the top-left pixel in one to-be-filtered region
1835 * \param [in] xPosEnd x position of the right-bottom pixel in one to-be-filtered region
1836 * \param [in] filterSet filter coefficients
1837 * \param [in] mergeTable the merged groups in block-based adaptation mode
1838 * \param [in] varImg BA filter index array
1839 */
1840Void TComAdaptiveLoopFilter::filterOneCompRegion(Pel *imgRes, Pel *imgPad, Int stride, Bool isChroma
1841                                                , Int yPos, Int yPosEnd, Int xPos, Int xPosEnd
1842                                                , Int** filterSet, Int* mergeTable, Pel** varImg
1843                                                )
1844{
1845#if LCUALF_QP_DEPENDENT_BITS 
1846  Int alfPrecisionBit = getAlfPrecisionBit( m_alfQP );
1847  Int numBitsMinus1   = alfPrecisionBit;
1848  Int offset          = (1<<(alfPrecisionBit-1));
1849#else
1850  static Int numBitsMinus1= (Int)ALF_NUM_BIT_SHIFT;
1851  static Int offset       = (1<<( (Int)ALF_NUM_BIT_SHIFT-1));
1852#endif
1853  static Int shiftHeight  = (Int)(log((double)VAR_SIZE_H)/log(2.0));
1854  static Int shiftWidth   = (Int)(log((double)VAR_SIZE_W)/log(2.0));
1855
1856  Pel *imgPad1,*imgPad2,*imgPad3, *imgPad4, *imgPad5, *imgPad6;
1857  Pel *var = varImg[yPos>>shiftHeight] + (xPos>>shiftWidth);;
1858  Int i, j, pixelInt;
1859  Int *coef = NULL;
1860
1861  coef    = filterSet[0];
1862  imgPad += (yPos*stride);
1863  imgRes += (yPos*stride);
1864
1865  Int yLineInLCU;
1866  Int paddingLine;
1867  //Int varInd = 0;
1868  Int lcuHeight     = isChroma ? m_lcuHeightChroma     : m_lcuHeight;
1869  Int lineIdxPadBot = isChroma ? m_lineIdxPadBotChroma : m_lineIdxPadBot;
1870  Int lineIdxPadTop = isChroma ? m_lineIdxPadTopChroma : m_lineIdxPadTop;
1871  Int img_height    = isChroma ? m_img_height>>1       : m_img_height;
1872
1873  for(i= yPos; i< yPosEnd; i++)
1874  {
1875    yLineInLCU = i % lcuHeight;
1876
1877    if(isChroma && yLineInLCU == 0 && i>0)
1878    {
1879      paddingLine = yLineInLCU + 2;
1880      imgPad1 = imgPad + stride;
1881      imgPad2 = imgPad - stride;
1882      imgPad3 = imgPad + 2*stride;
1883      imgPad4 = imgPad - 2*stride;
1884      imgPad5 = (paddingLine < 3) ? imgPad : imgPad + 3*stride;
1885      imgPad6 = (paddingLine < 3) ? imgPad : imgPad - min(paddingLine, 3)*stride;
1886    }
1887    else if(yLineInLCU<lineIdxPadBot || i-yLineInLCU+lcuHeight >= img_height)
1888    {
1889      imgPad1 = imgPad +   stride;
1890      imgPad2 = imgPad -   stride;
1891      imgPad3 = imgPad + 2*stride;
1892      imgPad4 = imgPad - 2*stride;
1893      imgPad5 = imgPad + 3*stride;
1894      imgPad6 = imgPad - 3*stride;
1895    }
1896    else if (yLineInLCU<lineIdxPadTop)
1897    {
1898      paddingLine = - yLineInLCU + lineIdxPadTop - 1;
1899      imgPad1 = (paddingLine < 1) ? imgPad : imgPad + min(paddingLine, 1)*stride;
1900      imgPad2 = (paddingLine < 1) ? imgPad : imgPad - stride;
1901      imgPad3 = (paddingLine < 2) ? imgPad : imgPad + min(paddingLine, 2)*stride;
1902      imgPad4 = (paddingLine < 2) ? imgPad : imgPad - 2*stride;
1903      imgPad5 = (paddingLine < 3) ? imgPad : imgPad + min(paddingLine, 3)*stride;
1904      imgPad6 = (paddingLine < 3) ? imgPad : imgPad - 3*stride;
1905    }
1906    else
1907    {
1908      paddingLine = yLineInLCU - lineIdxPadTop ;
1909      imgPad1 = (paddingLine < 1) ? imgPad : imgPad + stride;
1910      imgPad2 = (paddingLine < 1) ? imgPad : imgPad - min(paddingLine, 1)*stride;
1911      imgPad3 = (paddingLine < 2) ? imgPad : imgPad + 2*stride;
1912      imgPad4 = (paddingLine < 2) ? imgPad : imgPad - min(paddingLine, 2)*stride;
1913      imgPad5 = (paddingLine < 3) ? imgPad : imgPad + 3*stride;
1914      imgPad6 = (paddingLine < 3) ? imgPad : imgPad - min(paddingLine, 3)*stride;
1915    } 
1916
1917    if(!isChroma)
1918    {
1919      var = varImg[i>>shiftHeight] + (xPos>>shiftWidth);
1920    }
1921
1922    for(j= xPos; j< xPosEnd ; j++)
1923    {
1924      if (!isChroma && j % VAR_SIZE_W==0) 
1925      {
1926        coef = filterSet[mergeTable[*(var++)]];
1927      }
1928
1929      pixelInt  = coef[0]* (imgPad5[] + imgPad6[]);
1930
1931      pixelInt += coef[1]* (imgPad3[] + imgPad4[]);
1932
1933      pixelInt += coef[2]* (imgPad1[j-1] + imgPad2[j+1]);
1934      pixelInt += coef[3]* (imgPad1[] + imgPad2[]);
1935      pixelInt += coef[4]* (imgPad1[j+1] + imgPad2[j-1]);
1936
1937      pixelInt += coef[5]* (imgPad[j+4] + imgPad[j-4]);
1938      pixelInt += coef[6]* (imgPad[j+3] + imgPad[j-3]);
1939      pixelInt += coef[7]* (imgPad[j+2] + imgPad[j-2]);
1940      pixelInt += coef[8]* (imgPad[j+1] + imgPad[j-1]);
1941      pixelInt += coef[9]* (imgPad[]);
1942
1943      pixelInt=(Int)((pixelInt+offset) >> numBitsMinus1);
1944      imgRes[j] = Clip( pixelInt );
1945    }
1946
1947    imgPad += stride;
1948    imgRes += stride;
1949  } 
1950}
1951
1952#if LCUALF_QP_DEPENDENT_BITS
1953/** filtering pixels
1954 * \param [in] qp quantization parameter
1955 */
1956Int  TComAdaptiveLoopFilter::getAlfPrecisionBit(Int qp)
1957{
1958  Int alfPrecisionBit = 8;
1959
1960  if (qp < ALF_QP1)
1961  {
1962    alfPrecisionBit = 8;
1963  }
1964  else if (qp < ALF_QP2)
1965  {
1966    alfPrecisionBit = 7;
1967  }
1968  else if (qp < ALF_QP3)
1969  {
1970    alfPrecisionBit = 6;
1971  }
1972  else
1973  {
1974    alfPrecisionBit = 5;
1975  }
1976
1977  return alfPrecisionBit;
1978}
1979#endif
1980
1981/** filtering pixels
1982 * \param [out] imgYvar BA filter index array
1983 * \param [in] imgYpad decoded picture
1984 * \param [in] stride picture stride in memory
1985 * \param [in] isOnlyOneGroup only one filter is used (true) or multiple filters are used (false)
1986 * \param [in] yPos y position of the top-left pixel in one to-be-filtered region
1987 * \param [in] yPosEnd y position of the right-bottom pixel in one to-be-filtered region
1988 * \param [in] xPos x position of the top-left pixel in one to-be-filtered region
1989 * \param [in] xPosEnd x position of the right-bottom pixel in one to-be-filtered region
1990 */
1991Void TComAdaptiveLoopFilter::calcOneRegionVar(Pel **imgYvar, Pel *imgYpad, Int stride, Bool isOnlyOneGroup, Int yPos, Int yPosEnd, Int xPos, Int xPosEnd)
1992{
1993
1994  static Int shiftH = (Int)(log((double)VAR_SIZE_H)/log(2.0));
1995  static Int shiftW = (Int)(log((double)VAR_SIZE_W)/log(2.0));
1996  static Int varMax = (Int)NO_VAR_BINS-1; 
1997  static Int th[NO_VAR_BINS] = {0, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5}; 
1998  static Int avgVarTab[3][6] = { {0,  1,  2,  3,  4,  5,},
1999  {0,  6,  7,  8,  9, 10,},
2000  {0, 11, 12, 13, 14, 15}   };
2001
2002  Int i, j, avgVar, vertical, horizontal, direction, yOffset;
2003  Pel *imgYPadCur, *imgYPadUp, *imgYPadDown;
2004
2005  if (isOnlyOneGroup)
2006  {
2007    for(i = yPos; i < yPosEnd; i=i+4)
2008    {
2009      for(j = xPos; j < xPosEnd; j=j+4)
2010      {
2011        imgYvar[i>>shiftH][j>>shiftW] = 0;
2012      }
2013    }
2014    return;
2015  }
2016
2017  for(i = yPos; i < yPosEnd; i=i+4)
2018  {
2019    yOffset     = (i*stride) + stride;
2020    imgYPadCur  = &imgYpad[yOffset];
2021    imgYPadUp   = &imgYpad[yOffset + stride];
2022    imgYPadDown = &imgYpad[yOffset - stride];
2023
2024    for(j = xPos; j < xPosEnd; j=j+4)
2025    {
2026      // Compute at sub-sample by 2
2027      vertical   =  abs((imgYPadCur[j+1]<<1) - imgYPadDown[j+1] - imgYPadUp [j+1]);
2028      horizontal =  abs((imgYPadCur[j+1]<<1) - imgYPadCur [j+2] - imgYPadCur[]);
2029
2030      vertical   += abs((imgYPadCur[j+2]<<1) - imgYPadDown[j+2] - imgYPadUp [j+2]);
2031      horizontal += abs((imgYPadCur[j+2]<<1) - imgYPadCur [j+3] - imgYPadCur[j+1]);
2032
2033      vertical   += abs((imgYPadCur[j+1+stride]<<1) - imgYPadDown[j+1+stride] - imgYPadUp [j+1+stride]);
2034      horizontal += abs((imgYPadCur[j+1+stride]<<1) - imgYPadCur [j+2+stride] - imgYPadCur[j+stride  ]);
2035
2036      vertical   += abs((imgYPadCur[j+2+stride]<<1) - imgYPadDown[j+2+stride] - imgYPadUp [j+2+stride]);
2037      horizontal += abs((imgYPadCur[j+2+stride]<<1) - imgYPadCur [j+3+stride] - imgYPadCur[j+1+stride]);
2038
2039      direction = 0;
2040      if (vertical > 2*horizontal) 
2041      {
2042        direction = 1; //vertical
2043      }
2044      if (horizontal > 2*vertical)
2045      {
2046        direction = 2; //horizontal
2047      }
2048
2049      avgVar = (vertical + horizontal) >> 2;
2050      avgVar = (Pel) Clip_post( varMax, avgVar>>(g_uiBitIncrement+1) );
2051      avgVar = th[avgVar];
2052      avgVar = avgVarTab[direction][avgVar];
2053      imgYvar[i>>shiftH][j>>shiftW] = avgVar;
2054    }
2055  }
2056}
2057
2058
2059Void TComAdaptiveLoopFilter::resetLCUAlfInfo()
2060{
2061  //reset to all off
2062  for(Int compIdx = 0; compIdx < NUM_ALF_COMPONENT; compIdx++)
2063  {
2064    for(Int n=0; n< m_uiNumCUsInFrame; n++)
2065    {
2066      m_alfFiltInfo[compIdx][n]->alf_flag = 0;
2067    }
2068  }
2069
2070}
2071
2072Void TComAdaptiveLoopFilter::createLCUAlfInfo()
2073{
2074  for(Int compIdx = 0; compIdx < NUM_ALF_COMPONENT; compIdx++)
2075  {
2076    m_alfFiltInfo[compIdx] = new ALFParam*[m_uiNumCUsInFrame];
2077    for(Int n=0; n< m_uiNumCUsInFrame; n++)
2078    {
2079      m_alfFiltInfo[compIdx][n] = new ALFParam(compIdx);
2080    }
2081  }
2082
2083  resetLCUAlfInfo();
2084}
2085
2086Void TComAdaptiveLoopFilter::destroyLCUAlfInfo()
2087{
2088  for(Int compIdx = 0; compIdx < NUM_ALF_COMPONENT; compIdx++)
2089  {
2090    if(m_alfFiltInfo[compIdx] != NULL)
2091    {
2092      for(Int n=0; n< m_uiNumCUsInFrame; n++)
2093      {
2094        delete m_alfFiltInfo[compIdx][n];
2095      }
2096      delete[] m_alfFiltInfo[compIdx];
2097      m_alfFiltInfo[compIdx] = NULL;
2098    }
2099  }
2100}
2101
2102Pel* TComAdaptiveLoopFilter::getPicBuf(TComPicYuv* pPicYuv, Int compIdx)
2103{
2104  Pel* pBuf = NULL;
2105  switch(compIdx)
2106  {
2107  case ALF_Y:
2108    {
2109      pBuf = pPicYuv->getLumaAddr();
2110    }
2111    break;
2112  case ALF_Cb:
2113    {
2114      pBuf = pPicYuv->getCbAddr();
2115    }
2116    break;
2117  case ALF_Cr:
2118    {
2119      pBuf = pPicYuv->getCrAddr();
2120    }
2121    break;
2122  default:
2123    {
2124      printf("Not a legal component ID for ALF\n");
2125      assert(0);
2126      exit(-1);
2127    }
2128  }
2129
2130  return pBuf;
2131}
2132
2133
2134
2135/** PCM LF disable process.
2136 * \param pcPic picture (TComPic) pointer
2137 * \returns Void
2138 *
2139 * \note Replace filtered sample values of PCM mode blocks with the transmitted and reconstructed ones.
2140 */
2141Void TComAdaptiveLoopFilter::PCMLFDisableProcess (TComPic* pcPic)
2142{
2143  xPCMRestoration(pcPic);
2144}
2145
2146/** Picture-level PCM restoration.
2147 * \param pcPic picture (TComPic) pointer
2148 * \returns Void
2149 */
2150Void TComAdaptiveLoopFilter::xPCMRestoration(TComPic* pcPic)
2151{
2152  Bool  bPCMFilter = (pcPic->getSlice(0)->getSPS()->getUsePCM() && pcPic->getSlice(0)->getSPS()->getPCMFilterDisableFlag())? true : false;
2153
2154#if LOSSLESS_CODING
2155  if(bPCMFilter || pcPic->getSlice(0)->getSPS()->getUseLossless())
2156#else
2157  if(bPCMFilter)
2158#endif
2159  {
2160    for( UInt uiCUAddr = 0; uiCUAddr < pcPic->getNumCUsInFrame() ; uiCUAddr++ )
2161    {
2162      TComDataCU* pcCU = pcPic->getCU(uiCUAddr);
2163
2164      xPCMCURestoration(pcCU, 0, 0); 
2165    } 
2166  }
2167}
2168
2169/** PCM CU restoration.
2170 * \param pcCU pointer to current CU
2171 * \param uiAbsPartIdx part index
2172 * \param uiDepth CU depth
2173 * \returns Void
2174 */
2175Void TComAdaptiveLoopFilter::xPCMCURestoration ( TComDataCU* pcCU, UInt uiAbsZorderIdx, UInt uiDepth )
2176{
2177  TComPic* pcPic     = pcCU->getPic();
2178  UInt uiCurNumParts = pcPic->getNumPartInCU() >> (uiDepth<<1);
2179  UInt uiQNumParts   = uiCurNumParts>>2;
2180
2181  // go to sub-CU
2182  if( pcCU->getDepth(uiAbsZorderIdx) > uiDepth )
2183  {
2184    for ( UInt uiPartIdx = 0; uiPartIdx < 4; uiPartIdx++, uiAbsZorderIdx+=uiQNumParts )
2185    {
2186      UInt uiLPelX   = pcCU->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiAbsZorderIdx] ];
2187      UInt uiTPelY   = pcCU->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiAbsZorderIdx] ];
2188      if( ( uiLPelX < pcCU->getSlice()->getSPS()->getPicWidthInLumaSamples() ) && ( uiTPelY < pcCU->getSlice()->getSPS()->getPicHeightInLumaSamples() ) )
2189        xPCMCURestoration( pcCU, uiAbsZorderIdx, uiDepth+1 );
2190    }
2191    return;
2192  }
2193
2194  // restore PCM samples
2195#if LOSSLESS_CODING
2196  if ((pcCU->getIPCMFlag(uiAbsZorderIdx)) || pcCU->isLosslessCoded( uiAbsZorderIdx))
2197#else
2198  if (pcCU->getIPCMFlag(uiAbsZorderIdx))
2199#endif
2200  {
2201    xPCMSampleRestoration (pcCU, uiAbsZorderIdx, uiDepth, TEXT_LUMA    );
2202    xPCMSampleRestoration (pcCU, uiAbsZorderIdx, uiDepth, TEXT_CHROMA_U);
2203    xPCMSampleRestoration (pcCU, uiAbsZorderIdx, uiDepth, TEXT_CHROMA_V);
2204  }
2205}
2206
2207/** PCM sample restoration.
2208 * \param pcCU pointer to current CU
2209 * \param uiAbsPartIdx part index
2210 * \param uiDepth CU depth
2211 * \param ttText texture component type
2212 * \returns Void
2213 */
2214Void TComAdaptiveLoopFilter::xPCMSampleRestoration (TComDataCU* pcCU, UInt uiAbsZorderIdx, UInt uiDepth, TextType ttText)
2215{
2216  TComPicYuv* pcPicYuvRec = pcCU->getPic()->getPicYuvRec();
2217  Pel* piSrc;
2218  Pel* piPcm;
2219  UInt uiStride;
2220  UInt uiWidth;
2221  UInt uiHeight;
2222  UInt uiPcmLeftShiftBit; 
2223  UInt uiX, uiY;
2224  UInt uiMinCoeffSize = pcCU->getPic()->getMinCUWidth()*pcCU->getPic()->getMinCUHeight();
2225  UInt uiLumaOffset   = uiMinCoeffSize*uiAbsZorderIdx;
2226  UInt uiChromaOffset = uiLumaOffset>>2;
2227
2228  if( ttText == TEXT_LUMA )
2229  {
2230    piSrc = pcPicYuvRec->getLumaAddr( pcCU->getAddr(), uiAbsZorderIdx);
2231    piPcm = pcCU->getPCMSampleY() + uiLumaOffset;
2232    uiStride  = pcPicYuvRec->getStride();
2233    uiWidth  = (g_uiMaxCUWidth >> uiDepth);
2234    uiHeight = (g_uiMaxCUHeight >> uiDepth);
2235#if LOSSLESS_CODING
2236    if ( pcCU->isLosslessCoded(uiAbsZorderIdx) )
2237    {
2238      uiPcmLeftShiftBit = 0;
2239    }
2240    else
2241#endif
2242    {
2243        uiPcmLeftShiftBit = g_uiBitDepth + g_uiBitIncrement - pcCU->getSlice()->getSPS()->getPCMBitDepthLuma();
2244    }
2245  }
2246  else
2247  {
2248    if( ttText == TEXT_CHROMA_U )
2249    {
2250      piSrc = pcPicYuvRec->getCbAddr( pcCU->getAddr(), uiAbsZorderIdx );
2251      piPcm = pcCU->getPCMSampleCb() + uiChromaOffset;
2252    }
2253    else
2254    {
2255      piSrc = pcPicYuvRec->getCrAddr( pcCU->getAddr(), uiAbsZorderIdx );
2256      piPcm = pcCU->getPCMSampleCr() + uiChromaOffset;
2257    }
2258
2259    uiStride = pcPicYuvRec->getCStride();
2260    uiWidth  = ((g_uiMaxCUWidth >> uiDepth)/2);
2261    uiHeight = ((g_uiMaxCUWidth >> uiDepth)/2);
2262#if LOSSLESS_CODING
2263    if ( pcCU->isLosslessCoded(uiAbsZorderIdx) )
2264    {
2265      uiPcmLeftShiftBit = 0;
2266    }
2267    else
2268#endif
2269    {
2270      uiPcmLeftShiftBit = g_uiBitDepth + g_uiBitIncrement - pcCU->getSlice()->getSPS()->getPCMBitDepthChroma();
2271    }
2272  }
2273
2274  for( uiY = 0; uiY < uiHeight; uiY++ )
2275  {
2276    for( uiX = 0; uiX < uiWidth; uiX++ )
2277    {
2278      piSrc[uiX] = (piPcm[uiX] << uiPcmLeftShiftBit);
2279    }
2280    piPcm += uiWidth;
2281    piSrc += uiStride;
2282  }
2283}
2284//! \}
Note: See TracBrowser for help on using the repository browser.