source: 3DVCSoftware/branches/HTM-6.2-dev1-Samsung/Lib/TLibEncoder/TEncAdaptiveLoopFilter.cpp @ 347

Last change on this file since 347 was 347, checked in by samsung-htm, 11 years ago

D0122 Integration

File size: 147.7 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     TEncAdaptiveLoopFilter.cpp
35 \brief    estimation part of adaptive loop filter class
36 */
37#include "TEncAdaptiveLoopFilter.h"
38#include <string.h>
39#include <stdlib.h>
40#include <stdio.h>
41#include <math.h>
42
43//! \ingroup TLibEncoder
44//! \{
45
46// ====================================================================================================================
47// Constants
48// ====================================================================================================================
49#define ALF_NUM_OF_REDESIGN 1
50// ====================================================================================================================
51// Tables
52// ====================================================================================================================
53const Int TEncAdaptiveLoopFilter::m_alfNumPartsInRowTab[5] =
54{
55  1,      //level 0
56  2,      //level 1
57  4,      //level 2
58  8,      //level 3
59  16      //level 4
60};
61
62const Int TEncAdaptiveLoopFilter::m_alfNumPartsLevelTab[5] =
63{
64  1,      //level 0
65  4,      //level 1
66  16,     //level 2
67  64,     //level 3
68  256     //level 4
69};
70
71const Int TEncAdaptiveLoopFilter::m_alfNumCulPartsLevelTab[5] =
72{
73  1,    //level 0
74  5,    //level 1
75  21,   //level 2
76  85,   //level 3
77  341,  //level 4
78};
79// ====================================================================================================================
80// Constructor / destructor
81// ====================================================================================================================
82
83///AlfCorrData
84AlfCorrData::AlfCorrData()
85{
86  this->componentID = -1;
87  this->ECorr  = NULL;
88  this->yCorr  = NULL;
89  this->pixAcc = NULL;
90}
91
92AlfCorrData::AlfCorrData(Int cIdx)
93{
94  const Int numCoef = ALF_MAX_NUM_COEF;
95  const Int maxNumGroups = NO_VAR_BINS;
96
97  Int numGroups = (cIdx == ALF_Y)?(maxNumGroups):(1);
98
99  this->componentID = cIdx;
100
101  this->ECorr = new Double**[numGroups];
102  this->yCorr = new Double*[numGroups];
103  this->pixAcc = new Double[numGroups];
104  for(Int g= 0; g< numGroups; g++)
105  {
106    this->yCorr[g] = new Double[numCoef];
107    for(Int j=0; j< numCoef; j++)
108    {
109      this->yCorr[g][j] = 0;
110    }
111
112    this->ECorr[g] = new Double*[numCoef];
113    for(Int i=0; i< numCoef; i++)
114    {
115      this->ECorr[g][i] = new Double[numCoef];
116      for(Int j=0; j< numCoef; j++)
117      {
118        this->ECorr[g][i][j] = 0;
119      }
120    }
121    this->pixAcc[g] = 0; 
122  }
123}
124
125AlfCorrData::~AlfCorrData()
126{
127  if(this->componentID >=0)
128  {
129    const Int numCoef = ALF_MAX_NUM_COEF;
130    const Int maxNumGroups = NO_VAR_BINS;
131
132    Int numGroups = (this->componentID == ALF_Y)?(maxNumGroups):(1);
133
134    for(Int g= 0; g< numGroups; g++)
135    {
136      for(Int i=0; i< numCoef; i++)
137      {
138        delete[] this->ECorr[g][i];
139      }
140      delete[] this->ECorr[g];
141      delete[] this->yCorr[g];
142    }
143    delete[] this->ECorr;
144    delete[] this->yCorr;
145    delete[] this->pixAcc;
146  }
147
148}
149
150AlfCorrData& AlfCorrData::operator += (const AlfCorrData& src)
151{
152  if(this->componentID >=0)
153  {
154    const Int numCoef = ALF_MAX_NUM_COEF;
155    const Int maxNumGroups = NO_VAR_BINS;
156
157    Int numGroups = (this->componentID == ALF_Y)?(maxNumGroups):(1);
158    for(Int g=0; g< numGroups; g++)
159    {
160      this->pixAcc[g] += src.pixAcc[g];
161
162      for(Int j=0; j< numCoef; j++)
163      {
164        this->yCorr[g][j] += src.yCorr[g][j];
165        for(Int i=0; i< numCoef; i++)
166        {
167          this->ECorr[g][j][i] += src.ECorr[g][j][i];
168        }
169      }
170    }
171  }
172
173  return *this;
174}
175
176
177Void AlfCorrData::reset()
178{
179  if(this->componentID >=0)
180  {
181    const Int numCoef = ALF_MAX_NUM_COEF;
182    const Int maxNumGroups = NO_VAR_BINS;
183
184    Int numGroups = (this->componentID == ALF_Y)?(maxNumGroups):(1);
185    for(Int g=0; g< numGroups; g++)
186    {
187      this->pixAcc[g] = 0;
188
189      for(Int j=0; j< numCoef; j++)
190      {
191        this->yCorr[g][j] = 0;
192        for(Int i=0; i< numCoef; i++)
193        {
194          this->ECorr[g][j][i] = 0;
195        }
196      }
197
198
199    }
200  }
201
202}
203
204Void AlfCorrData::mergeFrom(const AlfCorrData& src, Int* mergeTable, Bool doPixAccMerge)
205{
206  assert(componentID == src.componentID);
207
208  reset();
209
210  const Int numCoef = ALF_MAX_NUM_COEF;
211
212  Double **srcE, **dstE;
213  Double *srcy, *dsty;
214
215  switch(componentID)
216  {
217  case ALF_Cb:
218  case ALF_Cr:
219    {
220      srcE = src.ECorr  [0];
221      dstE = this->ECorr[0];
222
223      srcy  = src.yCorr[0];
224      dsty  = this->yCorr[0];
225
226      for(Int j=0; j< numCoef; j++)
227      {
228        for(Int i=0; i< numCoef; i++)
229        {
230          dstE[j][i] += srcE[j][i];
231        }
232
233        dsty[j] += srcy[j];
234      }
235      if(doPixAccMerge)
236      {
237        this->pixAcc[0] = src.pixAcc[0];
238      }
239    }
240    break;
241  case ALF_Y:
242    {
243      Int maxFilterSetSize = (Int)NO_VAR_BINS;
244      for (Int varInd=0; varInd< maxFilterSetSize; varInd++)
245      {
246        Int filtIdx = (mergeTable == NULL)?(0):(mergeTable[varInd]);
247        srcE = src.ECorr  [varInd];
248        dstE = this->ECorr[ filtIdx ];
249        srcy  = src.yCorr[varInd];
250        dsty  = this->yCorr[ filtIdx ];
251        for(Int j=0; j< numCoef; j++)
252        {
253          for(Int i=0; i< numCoef; i++)
254          {
255            dstE[j][i] += srcE[j][i];
256          }
257          dsty[j] += srcy[j];
258        }
259        if(doPixAccMerge)
260        {
261          this->pixAcc[filtIdx] += src.pixAcc[varInd];
262        }
263      }
264    }
265    break;
266  default:
267    {
268      printf("not a legal component ID\n");
269      assert(0);
270      exit(-1);
271    }
272  }
273}
274
275///AlfPicQTPart
276AlfPicQTPart::AlfPicQTPart()
277{
278  componentID = -1;
279  alfUnitParam = NULL; 
280  alfCorr = NULL;
281}
282
283AlfPicQTPart::~AlfPicQTPart()
284{
285  if(alfUnitParam != NULL)
286  {
287    if(alfUnitParam->alfFiltParam != NULL)
288    {
289      delete alfUnitParam->alfFiltParam;
290      alfUnitParam->alfFiltParam = NULL;
291    }
292    delete alfUnitParam;
293    alfUnitParam = NULL;
294  }
295  if(alfCorr != NULL)
296  {
297    delete alfCorr;
298    alfCorr = NULL;
299  }
300}
301
302AlfPicQTPart& AlfPicQTPart::operator= (const AlfPicQTPart& src)
303{
304  componentID = src.componentID;
305  partCUXS    = src.partCUXS;
306  partCUYS    = src.partCUYS;
307  partCUXE    = src.partCUXE;
308  partCUYE    = src.partCUYE;
309  partIdx     = src.partIdx;
310  partLevel   = src.partLevel;
311  partCol     = src.partCol;
312  partRow     = src.partRow;
313  for(Int i=0; i<4; i++)
314  {
315    childPartIdx[i] = src.childPartIdx[i];
316  }
317  parentPartIdx = src.parentPartIdx;
318
319  isBottomLevel = src.isBottomLevel;
320  isSplit       = src.isSplit;
321
322  isProcessed   = src.isProcessed;
323  splitMinCost  = src.splitMinCost;
324  splitMinDist  = src.splitMinDist;
325  splitMinRate  = src.splitMinRate;
326  selfMinCost   = src.selfMinCost;
327  selfMinDist   = src.selfMinDist;
328  selfMinRate   = src.selfMinRate;
329
330  numFilterBudget = src.numFilterBudget;
331
332  if(src.alfUnitParam != NULL)
333  {
334    if(alfUnitParam == NULL)
335    {
336      //create alfUnitparam
337      alfUnitParam = new AlfUnitParam;
338      alfUnitParam->alfFiltParam = new ALFParam(componentID);
339    }
340    //assign from src
341    alfUnitParam->mergeType = src.alfUnitParam->mergeType;
342    alfUnitParam->isEnabled = src.alfUnitParam->isEnabled;
343    alfUnitParam->isNewFilt = src.alfUnitParam->isNewFilt;
344    alfUnitParam->storedFiltIdx = src.alfUnitParam->storedFiltIdx;
345    *(alfUnitParam->alfFiltParam) = *(src.alfUnitParam->alfFiltParam);   
346  }
347  else
348  {
349    printf("source quad-tree partition info is not complete\n");
350    assert(0);
351    exit(-1);
352  }
353
354  if(src.alfCorr != NULL)
355  {
356    if(alfCorr == NULL)
357    {
358      alfCorr = new AlfCorrData(componentID);
359    }
360    alfCorr->reset();
361    (*alfCorr) += (*(src.alfCorr));
362  }
363  else
364  {
365    printf("source quad-tree partition info is not complete\n");
366    assert(0);
367    exit(-1);
368  }
369  return *this;
370}
371
372
373TEncAdaptiveLoopFilter::TEncAdaptiveLoopFilter()
374{
375  m_pcEntropyCoder = NULL;
376  m_pcPicYuvBest = NULL;
377  m_pcPicYuvTmp = NULL;
378
379  m_iALFMaxNumberFilters = NO_FILTERS;
380
381  m_bAlfCUCtrlEnabled = false;
382}
383
384// ====================================================================================================================
385// Public member functions
386// ====================================================================================================================
387
388/** convert Level Row Col to Idx
389 * \param   level,  row,  col
390 */
391Int TEncAdaptiveLoopFilter::convertLevelRowCol2Idx(Int level, Int row, Int col)
392{
393  Int idx;
394  if (level == 0)
395  {
396    idx = 0;
397  }
398  else if (level == 1)
399  {
400    idx = 1 + row*2 + col;
401  }
402  else if (level == 2)
403  {
404    idx = 5 + row*4 + col;
405  }
406  else if (level == 3)
407  {
408    idx = 21 + row*8 + col;
409  }
410  else // (level == 4)
411  {
412    idx = 85 + row*16 + col;
413  }
414  return idx;
415}
416
417/** convert quadtree Idx to Level, Row, and Col
418 * \param  idx,  *level,  *row,  *col
419 */
420Void TEncAdaptiveLoopFilter::convertIdx2LevelRowCol(Int idx, Int *level, Int *row, Int *col)
421{
422  if (idx == 0)
423  {
424    *level = 0;
425    *row = 0;
426    *col = 0;
427  }
428  else if (idx>=1 && idx<=4)
429  {
430    *level = 1;
431    *row = (idx-1) / 2;
432    *col = (idx-1) % 2;
433  }
434  else if (idx>=5 && idx<=20)
435  {
436    *level = 2;
437    *row = (idx-5) / 4;
438    *col = (idx-5) % 4;
439  }
440  else if (idx>=21 && idx<=84)
441  {
442    *level = 3;
443    *row = (idx-21) / 8;
444    *col = (idx-21) % 8;
445  }
446  else // (idx>=85 && idx<=340)
447  {
448    *level = 4;
449    *row = (idx-85) / 16;
450    *col = (idx-85) % 16;
451  }
452}
453
454/** Initial picture quad-tree
455 * \param [in] isPicBasedEncode picture quad-tree encoding is enabled or disabled
456 */
457Void TEncAdaptiveLoopFilter::initPicQuadTreePartition(Bool isPicBasedEncode)
458{
459  if (!isPicBasedEncode)
460  {
461    return;
462  }
463 
464  Int maxDepthInWidth   = (Int)(logf((float)(m_numLCUInPicWidth     ))/logf(2.0));
465  Int maxDepthInHeight  = (Int)(logf((float)(m_numLCUInPicHeight    ))/logf(2.0));
466  Int maxDepthInFilters = (Int)(logf((float)(m_iALFMaxNumberFilters ))/logf(2.0));
467  m_alfPQTMaxDepth = (maxDepthInWidth  > maxDepthInHeight ) ? maxDepthInHeight  : maxDepthInWidth ;
468  m_alfPQTMaxDepth = (m_alfPQTMaxDepth > maxDepthInFilters) ? maxDepthInFilters : m_alfPQTMaxDepth ;
469
470  for (Int compIdx = 0; compIdx < NUM_ALF_COMPONENT; compIdx++)
471  {
472    m_alfPQTPart[compIdx] = new AlfPicQTPart [ m_alfNumCulPartsLevelTab[m_alfPQTMaxDepth] ];
473    for (Int i = 0; i < m_alfNumCulPartsLevelTab[m_alfPQTMaxDepth]; i++ )
474    {
475      m_alfPQTPart[compIdx][i].alfCorr = new AlfCorrData(compIdx);
476      m_alfPQTPart[compIdx][i].alfUnitParam = new AlfUnitParam;
477      m_alfPQTPart[compIdx][i].alfUnitParam->alfFiltParam = new ALFParam(compIdx);
478    }
479
480  }
481  creatPQTPart(0, 0, 0, -1, 0, m_numLCUInPicWidth-1, 0, m_numLCUInPicHeight-1); 
482}
483
484/** Reset picture quad-tree variables
485 */
486Void TEncAdaptiveLoopFilter::resetPQTPart()
487{
488  Int compIdx, i;
489
490  for (compIdx = 0; compIdx < NUM_ALF_COMPONENT; compIdx++)
491  {
492    for (i = 0; i < m_alfNumCulPartsLevelTab[m_alfPQTMaxDepth]; i++ )
493    {
494      m_alfPQTPart[compIdx][i].isProcessed  = false;
495      m_alfPQTPart[compIdx][i].selfMinCost  = MAX_DOUBLE;
496      m_alfPQTPart[compIdx][i].splitMinCost = MAX_DOUBLE;     
497      //reset correlations
498      m_alfPQTPart[compIdx][i].alfCorr->reset();
499      //reset ALF unit param
500      m_alfPQTPart[compIdx][i].alfUnitParam->mergeType = ALF_MERGE_DISABLED;
501      m_alfPQTPart[compIdx][i].alfUnitParam->isEnabled = false;
502      m_alfPQTPart[compIdx][i].alfUnitParam->alfFiltParam->alf_flag = 0;
503    }
504  }
505}
506
507/** create picture quad-tree
508 * \param [in] partLevel quad-tree level
509 * \param [in] partRow row position at partLevel
510 * \param [in] partCol column position at partLevel
511 * \param [in] parentPartIdx parent partition index
512 * \param [in] partCUXS starting LCU X position
513 * \param [in] partCUXE ending LCU X position
514 * \param [in] partCUYS starting LCU Y position
515 * \param [in] partCUYE ending LCU Y position
516 */
517Void TEncAdaptiveLoopFilter::creatPQTPart(Int partLevel, Int partRow, Int partCol, Int parentPartIdx, Int partCUXS, Int partCUXE, Int partCUYS, Int partCUYE)
518{
519  Int partIdx = convertLevelRowCol2Idx(partLevel, partRow, partCol);
520
521  AlfPicQTPart *alfOnePartY, *alfOnePartCb, *alfOnePartCr;
522
523  alfOnePartY  = &(m_alfPQTPart[ALF_Y ][partIdx]);
524  alfOnePartCb = &(m_alfPQTPart[ALF_Cb][partIdx]);
525  alfOnePartCr = &(m_alfPQTPart[ALF_Cr][partIdx]);
526
527  // Y, Cb, Cr
528  alfOnePartY->partIdx   = alfOnePartCb->partIdx   = alfOnePartCr->partIdx   = partIdx;
529  alfOnePartY->partCol   = alfOnePartCb->partCol   = alfOnePartCr->partCol   = partCol;
530  alfOnePartY->partRow   = alfOnePartCb->partRow   = alfOnePartCr->partRow   = partRow;
531  alfOnePartY->partLevel = alfOnePartCb->partLevel = alfOnePartCr->partLevel = partLevel;
532
533  alfOnePartY->partCUXS  = alfOnePartCb->partCUXS  = alfOnePartCr->partCUXS  = partCUXS; 
534  alfOnePartY->partCUXE  = alfOnePartCb->partCUXE  = alfOnePartCr->partCUXE  = partCUXE;
535  alfOnePartY->partCUYS  = alfOnePartCb->partCUYS  = alfOnePartCr->partCUYS  = partCUYS;
536  alfOnePartY->partCUYE  = alfOnePartCb->partCUYE  = alfOnePartCr->partCUYE  = partCUYE;
537
538  alfOnePartY->parentPartIdx = alfOnePartCb->parentPartIdx = alfOnePartCr->parentPartIdx = parentPartIdx; 
539  alfOnePartY->isSplit       = alfOnePartCb->isSplit       = alfOnePartCr->isSplit       = false;
540
541#if LCUALF_FILTER_BUDGET_CONTROL_ENC
542  alfOnePartY->numFilterBudget = alfOnePartCb->numFilterBudget = alfOnePartCr->numFilterBudget = m_iALFMaxNumberFilters/m_alfNumPartsLevelTab[partLevel];
543#else
544  alfOnePartY->numFilterBudget = alfOnePartCb->numFilterBudget = alfOnePartCr->numFilterBudget = NO_VAR_BINS;
545#endif
546
547  alfOnePartY->componentID  = ALF_Y;
548  alfOnePartCb->componentID = ALF_Cb;
549  alfOnePartCr->componentID = ALF_Cr;
550
551  if (alfOnePartY->partLevel != m_alfPQTMaxDepth)
552  {
553    alfOnePartY->isBottomLevel = alfOnePartCb->isBottomLevel = alfOnePartCr->isBottomLevel = false;
554
555    Int downLevel    = partLevel + 1;
556    Int downRowStart = partRow << 1;
557    Int downColStart = partCol << 1;
558
559    Int downRowIdx, downColIdx;
560    Int numCULeft, numCUTop;
561    Int downStartCUX, downStartCUY, downEndCUX, downEndCUY;
562
563    numCULeft = (partCUXE - partCUXS + 1) >> 1 ;
564    numCUTop  = (partCUYE - partCUYS + 1) >> 1 ;
565
566    // ChildPart00
567    downStartCUX = partCUXS;
568    downEndCUX   = downStartCUX + numCULeft - 1;
569    downStartCUY = partCUYS;
570    downEndCUY   = downStartCUY + numCUTop  - 1;
571    downRowIdx   = downRowStart + 0;
572    downColIdx   = downColStart + 0;
573
574    alfOnePartY->childPartIdx[0] = alfOnePartCb->childPartIdx[0] = alfOnePartCr->childPartIdx[0] = convertLevelRowCol2Idx(downLevel, downRowIdx, downColIdx);
575    creatPQTPart(downLevel, downRowIdx, downColIdx, partIdx, downStartCUX, downEndCUX, downStartCUY, downEndCUY);
576
577    // ChildPart01
578    downStartCUX = partCUXS + numCULeft;
579    downEndCUX   = partCUXE;
580    downStartCUY = partCUYS;
581    downEndCUY   = downStartCUY + numCUTop  - 1;
582    downRowIdx   = downRowStart + 0;
583    downColIdx   = downColStart + 1;
584
585    alfOnePartY->childPartIdx[1] = alfOnePartCb->childPartIdx[1] = alfOnePartCr->childPartIdx[1] = convertLevelRowCol2Idx(downLevel, downRowIdx, downColIdx);
586    creatPQTPart(downLevel, downRowIdx, downColIdx, partIdx, downStartCUX, downEndCUX, downStartCUY, downEndCUY);
587
588    // ChildPart10
589    downStartCUX = partCUXS;
590    downEndCUX   = downStartCUX + numCULeft - 1;
591    downStartCUY = partCUYS + numCUTop;
592    downEndCUY   = partCUYE;
593    downRowIdx   = downRowStart + 1;
594    downColIdx   = downColStart + 0;
595
596    alfOnePartY->childPartIdx[2] = alfOnePartCb->childPartIdx[2] = alfOnePartCr->childPartIdx[2] = convertLevelRowCol2Idx(downLevel, downRowIdx, downColIdx);
597    creatPQTPart(downLevel, downRowIdx, downColIdx, partIdx, downStartCUX, downEndCUX, downStartCUY, downEndCUY);
598
599    // ChildPart11
600    downStartCUX = partCUXS + numCULeft;
601    downEndCUX   = partCUXE;
602    downStartCUY = partCUYS + numCUTop;
603    downEndCUY   = partCUYE;
604    downRowIdx   = downRowStart + 1;
605    downColIdx   = downColStart + 1;
606
607    alfOnePartY->childPartIdx[3] = alfOnePartCb->childPartIdx[3] = alfOnePartCr->childPartIdx[3] = convertLevelRowCol2Idx(downLevel, downRowIdx, downColIdx);
608    creatPQTPart(downLevel, downRowIdx, downColIdx, partIdx, downStartCUX, downEndCUX, downStartCUY, downEndCUY);
609  }
610  else
611  {
612    alfOnePartY->isBottomLevel = alfOnePartCb->isBottomLevel = alfOnePartCr->isBottomLevel = true;
613
614    alfOnePartY->childPartIdx[0] = alfOnePartCb->childPartIdx[0] = alfOnePartCr->childPartIdx[0] = -1;
615    alfOnePartY->childPartIdx[1] = alfOnePartCb->childPartIdx[1] = alfOnePartCr->childPartIdx[1] = -1;
616    alfOnePartY->childPartIdx[2] = alfOnePartCb->childPartIdx[2] = alfOnePartCr->childPartIdx[2] = -1;
617    alfOnePartY->childPartIdx[3] = alfOnePartCb->childPartIdx[3] = alfOnePartCr->childPartIdx[3] = -1;
618  }
619}
620
621/** create global buffers for ALF encoding
622 */
623Void TEncAdaptiveLoopFilter::createAlfGlobalBuffers()
624{
625  for(Int compIdx =0; compIdx < NUM_ALF_COMPONENT; compIdx++)
626  {
627    m_alfPicFiltUnits[compIdx] = new AlfUnitParam[m_uiNumCUsInFrame];
628    m_alfCorr[compIdx] = new AlfCorrData*[m_uiNumCUsInFrame];
629    for(Int n=0; n< m_uiNumCUsInFrame; n++)
630    {
631      m_alfCorr[compIdx][n]= new AlfCorrData(compIdx);
632      m_alfCorr[compIdx][n]->reset();
633    }
634
635    m_alfCorrMerged[compIdx] = new AlfCorrData(compIdx);
636
637  }
638
639
640  const Int numCoef = (Int)ALF_MAX_NUM_COEF;
641
642  for(Int i=0; i< (Int)NO_VAR_BINS; i++)
643  {
644    m_coeffNoFilter[i] = new Int[numCoef];
645  }
646
647  m_numSlicesDataInOneLCU = new Int[m_uiNumCUsInFrame];
648
649}
650
651/** destroy ALF global buffers
652 * This function is used to destroy the global ALF encoder buffers
653 */
654Void TEncAdaptiveLoopFilter::destroyAlfGlobalBuffers()
655{
656  for(Int compIdx =0; compIdx < NUM_ALF_COMPONENT; compIdx++)
657  {
658    delete[] m_alfPicFiltUnits[compIdx];
659    for(Int n=0; n< m_uiNumCUsInFrame; n++)
660    {
661      delete m_alfCorr[compIdx][n];
662    }
663
664    delete[] m_alfCorr[compIdx];
665    m_alfCorr[compIdx] = NULL;
666
667    delete m_alfCorrMerged[compIdx];
668  }
669
670  //const Int numCoef = (Int)ALF_MAX_NUM_COEF;
671
672  for(Int i=0; i< (Int)NO_VAR_BINS; i++)
673  {
674    delete[] m_coeffNoFilter[i];
675  }
676
677  delete[] m_numSlicesDataInOneLCU;
678
679}
680
681/** initialize ALF encoder at picture level
682 * \param [in] isAlfParamInSlice ALF parameters are coded in slice (true) or APS (false)
683 * \param [in] isPicBasedEncode picture-based encoding (true) or LCU-based encoding (false)
684 * \param [in] numSlices number of slices in current picture
685 * \param [in, out] alfParams ALF parameter set
686 * \param [in, out] alfCUCtrlParam ALF CU-on/off control parameters
687 */
688Void TEncAdaptiveLoopFilter::initALFEnc(Bool isAlfParamInSlice, Bool isPicBasedEncode, Int numSlices, AlfParamSet* & alfParams, std::vector<AlfCUCtrlInfo>* & alfCUCtrlParam)
689{
690  m_picBasedALFEncode = isPicBasedEncode;
691
692  if(isAlfParamInSlice) 
693  {
694    alfParams = new AlfParamSet[m_uiNumSlicesInPic];
695    Int numLCUs = m_uiNumCUsInFrame;
696
697    for(Int s=0; s< m_uiNumSlicesInPic; s++)
698    {
699      numLCUs = (Int)(m_pcPic->getOneSliceCUDataForNDBFilter(s).size());
700      alfParams[s].create(m_numLCUInPicWidth,m_numLCUInPicHeight, numLCUs );
701      alfParams[s].createALFParam();
702    }
703    alfCUCtrlParam = NULL; 
704  }
705  else //ALF parameter in APS
706  {
707    alfParams = NULL; //ALF parameters are handled by APS
708    alfCUCtrlParam = new std::vector<AlfCUCtrlInfo>;
709    alfCUCtrlParam->resize(numSlices);
710  }
711
712  resetPicAlfUnit();
713
714  if(m_picBasedALFEncode)
715  {
716    resetPQTPart(); 
717  }
718
719  const Int numCoef = (Int)ALF_MAX_NUM_COEF;
720#if LCUALF_QP_DEPENDENT_BITS
721  Int numBitShift = getAlfPrecisionBit( m_alfQP ); 
722#else
723  Int numBitShift = (Int)ALF_NUM_BIT_SHIFT;
724#endif
725  for(Int i=0; i< (Int)NO_VAR_BINS; i++)
726  {
727    ::memset(&(m_coeffNoFilter[i][0]), 0, sizeof(Int)*numCoef);
728    m_coeffNoFilter[i][numCoef-1] = (1 << numBitShift);
729  }
730
731}
732
733/** Uninitialize ALF encoder at picture level
734 * \param [in, out] alfParams ALF parameter set
735 * \param [in, out] alfCUCtrlParam ALF CU-on/off control parameters
736 */
737Void TEncAdaptiveLoopFilter::uninitALFEnc(AlfParamSet* & alfParams, std::vector<AlfCUCtrlInfo>* & alfCUCtrlParam)
738{
739  if(alfParams != NULL)
740  {
741    for(Int s=0; s< m_uiNumSlicesInPic; s++)
742    {
743      alfParams[s].releaseALFParam();
744    }
745    delete[] alfParams;
746    alfParams = NULL;
747  }
748
749  if(alfCUCtrlParam != NULL)
750  {
751    delete alfCUCtrlParam;
752    alfCUCtrlParam = NULL;
753  }
754}
755
756/** reset ALF unit parameters in current picture
757 */
758Void TEncAdaptiveLoopFilter::resetPicAlfUnit()
759{
760  for(Int compIdx =0; compIdx < NUM_ALF_COMPONENT; compIdx++)
761  {
762    for(Int i=0; i< m_uiNumCUsInFrame; i++)
763    {
764      AlfUnitParam& alfUnit = m_alfPicFiltUnits[compIdx][i];
765      alfUnit.mergeType = ALF_MERGE_DISABLED;
766      alfUnit.isEnabled = false;
767      alfUnit.isNewFilt = true;
768      alfUnit.alfFiltParam = m_alfFiltInfo[compIdx][i];
769
770      alfUnit.alfFiltParam->alf_flag = 0;
771    }
772  }
773}
774
775/**
776 \param pcPic           picture (TComPic) pointer
777 \param pcEntropyCoder  entropy coder class
778 */
779Void TEncAdaptiveLoopFilter::startALFEnc( TComPic* pcPic, TEncEntropy* pcEntropyCoder )
780{
781  m_pcEntropyCoder = pcEntropyCoder;
782  xCreateTmpAlfCtrlFlags();
783 
784  Int iWidth = pcPic->getPicYuvOrg()->getWidth();
785  Int iHeight = pcPic->getPicYuvOrg()->getHeight();
786 
787  m_pcPicYuvTmp = new TComPicYuv();
788  m_pcPicYuvTmp->createLuma(iWidth, iHeight, g_uiMaxCUWidth, g_uiMaxCUHeight, g_uiMaxCUDepth);
789  m_pcPicYuvBest = pcPic->getPicYuvPred();
790  initMatrix_int(&m_filterCoeffSymQuant, NO_VAR_BINS, ALF_MAX_NUM_COEF); 
791  initMatrix_Pel(&m_maskImg, m_img_height, m_img_width);
792  initMatrix_double(&m_E_temp, MAX_SQR_FILT_LENGTH, MAX_SQR_FILT_LENGTH);//
793  m_y_temp = (double *) calloc(MAX_SQR_FILT_LENGTH, sizeof(double));//
794  initMatrix3D_double(&m_E_merged, NO_VAR_BINS, MAX_SQR_FILT_LENGTH, MAX_SQR_FILT_LENGTH);//
795  initMatrix_double(&m_y_merged, NO_VAR_BINS, MAX_SQR_FILT_LENGTH); //
796  m_pixAcc_merged = (double *) calloc(NO_VAR_BINS, sizeof(double));//
797  m_filterCoeffQuantMod = (int *) calloc(ALF_MAX_NUM_COEF, sizeof(int));//
798  m_filterCoeff = (double *) calloc(ALF_MAX_NUM_COEF, sizeof(double));//
799  m_filterCoeffQuant = (int *) calloc(ALF_MAX_NUM_COEF, sizeof(int));//
800  initMatrix_int(&m_diffFilterCoeffQuant, NO_VAR_BINS, ALF_MAX_NUM_COEF);//
801  initMatrix_int(&m_FilterCoeffQuantTemp, NO_VAR_BINS, ALF_MAX_NUM_COEF);//
802
803  m_tempALFp = new ALFParam(ALF_Y);
804}
805
806Void TEncAdaptiveLoopFilter::endALFEnc()
807{
808  xDestroyTmpAlfCtrlFlags();
809 
810  m_pcPicYuvTmp->destroyLuma();
811  delete m_pcPicYuvTmp;
812  m_pcPicYuvTmp = NULL;
813  m_pcPic = NULL;
814  m_pcEntropyCoder = NULL;
815  destroyMatrix_int(m_filterCoeffSymQuant);
816  destroyMatrix_Pel(m_maskImg);
817  destroyMatrix3D_double(m_E_merged, NO_VAR_BINS);
818  destroyMatrix_double(m_y_merged);
819  destroyMatrix_double(m_E_temp);
820  free(m_pixAcc_merged);
821 
822  free(m_filterCoeffQuantMod);
823  free(m_y_temp);
824 
825  free(m_filterCoeff);
826  free(m_filterCoeffQuant);
827  destroyMatrix_int(m_diffFilterCoeffQuant);
828  destroyMatrix_int(m_FilterCoeffQuantTemp);
829 
830  delete m_tempALFp;
831}
832
833
834/** Assign output ALF parameters
835 * \param [in, out] alfParamSet ALF parameter set
836 * \param [in, out] alfCtrlParam ALF CU-on/off control parameters
837 */
838Void TEncAdaptiveLoopFilter::assignALFEncoderParam(AlfParamSet* alfParamSet, std::vector<AlfCUCtrlInfo>* alfCtrlParam)
839{
840  //assign CU control parameters
841  if(m_bAlfCUCtrlEnabled)
842  {
843    for(Int s=0; s< m_uiNumSlicesInPic; s++)
844    {
845      (*alfCtrlParam)[s]= m_vBestAlfCUCtrlParam[s];
846    }
847  }
848
849  //assign RDO results to alfParamSet
850  if(m_alfCoefInSlice)
851  {
852    for(Int s=0; s< m_uiNumSlicesInPic; s++)
853    {
854      if(!m_pcPic->getValidSlice(s))
855      {
856        continue;
857      }
858
859      if( m_bestAlfParamSet[s].isEnabled[ALF_Y] || m_bestAlfParamSet[s].isEnabled[ALF_Cb] || m_bestAlfParamSet[s].isEnabled[ALF_Cr])
860      {
861        m_bestAlfParamSet[s].isEnabled[ALF_Y] = true;
862      }
863
864      copyAlfParamSet(&(alfParamSet[s]), &(m_bestAlfParamSet[s]));
865    }
866  }
867  else
868  {
869    if( m_bestAlfParamSet->isEnabled[ALF_Y] || m_bestAlfParamSet->isEnabled[ALF_Cb] || m_bestAlfParamSet->isEnabled[ALF_Cr])
870    {
871      m_bestAlfParamSet->isEnabled[ALF_Y] = true;
872    }
873
874    copyAlfParamSet(alfParamSet, m_bestAlfParamSet);
875  }
876
877  if(m_alfCoefInSlice)
878  {
879    delete[] m_bestAlfParamSet;
880  }
881  else
882  {
883    delete m_bestAlfParamSet;
884  }
885}
886
887/** initialize ALF encoder configurations
888 * \param [in, out] alfParamSet ALF parameter set
889 * \param [in, out] alfCtrlParam ALF CU-on/off control parameters
890 */
891Void TEncAdaptiveLoopFilter::initALFEncoderParam(AlfParamSet* alfParamSet, std::vector<AlfCUCtrlInfo>* alfCtrlParam)
892{
893  //reset BA index map
894  memset(&m_varImg[0][0], 0, sizeof(Pel)*(m_img_height*m_img_width));
895
896  //reset mask
897  for(Int y=0; y< m_img_height; y++)
898  {
899    for(Int x=0; x< m_img_width; x++)
900    {
901      m_maskImg[y][x] = 1;
902    }
903  }
904  //get last valid slice index
905  for(Int s=0; s< m_uiNumSlicesInPic; s++)
906  {
907    if(m_pcPic->getValidSlice(s))
908    {
909      m_lastSliceIdx = s;
910    }
911  }
912  //reset alf CU control flags
913  m_bAlfCUCtrlEnabled = (alfCtrlParam != NULL)?true:false;
914  if(m_bAlfCUCtrlEnabled)
915  {
916    m_vBestAlfCUCtrlParam.resize(m_uiNumSlicesInPic);
917    for(Int s=0; s< m_uiNumSlicesInPic; s++)
918    {
919      m_vBestAlfCUCtrlParam[s].reset();
920    }
921  }
922  else
923  {
924    m_vBestAlfCUCtrlParam.clear();
925  }
926  //get number slices in each LCU
927  if(m_uiNumSlicesInPic == 1 || m_iSGDepth == 0)
928  {
929    for(Int n=0; n< m_uiNumCUsInFrame; n++)
930    {
931      m_numSlicesDataInOneLCU[n] = 1;
932    }
933  }
934  else
935  {
936    Int count;
937    Int prevSliceID = -1;
938
939    for(Int n=0; n< m_uiNumCUsInFrame; n++)
940    {
941      std::vector<NDBFBlockInfo>& vNDBFBlock = *(m_pcPic->getCU(n)->getNDBFilterBlocks());
942
943      count = 0;
944
945      for(Int i=0; i< (Int)vNDBFBlock.size(); i++)
946      {
947        if(vNDBFBlock[i].sliceID != prevSliceID)
948        {
949          prevSliceID = vNDBFBlock[i].sliceID;
950          count++;
951        }
952      }
953
954      m_numSlicesDataInOneLCU[n] = count;
955    }
956  }
957  //set redesign number
958  if(m_iALFEncodePassReduction)
959  {
960    m_iALFNumOfRedesign = 0;
961  }
962  else
963  {
964    m_iALFNumOfRedesign = ALF_NUM_OF_REDESIGN;
965  }
966
967  //initialize m_bestAlfParamSet
968  if(m_alfCoefInSlice)
969  {
970    m_bestAlfParamSet = new AlfParamSet[m_uiNumSlicesInPic];
971    for(Int s=0; s< m_uiNumSlicesInPic; s++)
972    {
973      m_bestAlfParamSet[s].create( alfParamSet[s].numLCUInWidth, alfParamSet[s].numLCUInHeight, alfParamSet[s].numLCU);
974    }
975  }
976  else
977  {
978    m_bestAlfParamSet = new AlfParamSet;
979    m_bestAlfParamSet->create( alfParamSet->numLCUInWidth, alfParamSet->numLCUInHeight, alfParamSet->numLCU);
980  }
981
982}
983
984/** copy ALF parameter set
985 * \param [out] dst destination ALF parameter set
986 * \param [in] src source ALF parameter set
987 */
988Void TEncAdaptiveLoopFilter::copyAlfParamSet(AlfParamSet* dst, AlfParamSet* src)
989{
990  dst->numLCU = src->numLCU;
991  dst->numLCUInWidth = src->numLCUInWidth;
992  dst->numLCUInHeight = src->numLCUInHeight;
993
994  for(Int compIdx =0; compIdx < NUM_ALF_COMPONENT; compIdx++)
995  {
996    dst->isEnabled[compIdx] = src->isEnabled[compIdx];
997    dst->isUniParam[compIdx] = src->isUniParam[compIdx];
998
999    for(Int n=0; n< src->numLCU; n++)
1000    {
1001      dst->alfUnitParam[compIdx][n].isEnabled = src->alfUnitParam[compIdx][n].isEnabled;
1002      dst->alfUnitParam[compIdx][n].isNewFilt = src->alfUnitParam[compIdx][n].isNewFilt;
1003      dst->alfUnitParam[compIdx][n].mergeType = src->alfUnitParam[compIdx][n].mergeType;
1004      dst->alfUnitParam[compIdx][n].storedFiltIdx = src->alfUnitParam[compIdx][n].storedFiltIdx;
1005      *(dst->alfUnitParam[compIdx][n].alfFiltParam) = *(src->alfUnitParam[compIdx][n].alfFiltParam);
1006    }
1007  }
1008}
1009
1010
1011/** ALF encoding process top function
1012 * \param [in, out] alfParamSet ALF parameter set
1013 * \param [in, out] alfCtrlParam ALF CU-on/off control parameters
1014 * \param [in] dLambdaLuma lambda value for luma RDO
1015 * \param [in] dLambdaChroma lambda value for chroma RDO
1016 */
1017#if ALF_CHROMA_LAMBDA
1018#if HHI_INTERVIEW_SKIP
1019Void TEncAdaptiveLoopFilter::ALFProcess( AlfParamSet* alfParamSet, std::vector<AlfCUCtrlInfo>* alfCtrlParam, Double lambdaLuma, Double lambdaChroma, Bool bInterviewSkip)
1020#else
1021Void TEncAdaptiveLoopFilter::ALFProcess( AlfParamSet* alfParamSet, std::vector<AlfCUCtrlInfo>* alfCtrlParam, Double lambdaLuma, Double lambdaChroma)
1022#endif
1023#else
1024#if HHI_INTERVIEW_SKIP
1025#else
1026Void TEncAdaptiveLoopFilter::ALFProcess( AlfParamSet* alfParamSet, std::vector<AlfCUCtrlInfo>* alfCtrlParam, Double lambda)
1027#endif
1028#endif
1029{
1030#if ALF_CHROMA_LAMBDA
1031  m_dLambdaLuma   = lambdaLuma;
1032  m_dLambdaChroma = lambdaChroma;
1033#else
1034  m_dLambdaLuma   = lambda;
1035  m_dLambdaChroma = lambda;
1036#endif
1037  TComPicYuv* yuvOrg    = m_pcPic->getPicYuvOrg();
1038  TComPicYuv* yuvRec    = m_pcPic->getPicYuvRec();
1039  TComPicYuv* yuvExtRec = m_pcTempPicYuv;
1040#if HHI_INTERVIEW_SKIP
1041  TComPicYuv* pUsedPelMap = NULL;
1042  if( bInterviewSkip )
1043  {
1044    pUsedPelMap = m_pcPic->getUsedPelsMap();
1045  }
1046#endif
1047
1048  //picture boundary padding
1049  yuvRec->copyToPic(yuvExtRec);
1050  yuvExtRec->setBorderExtension( false );
1051  yuvExtRec->extendPicBorder   ();
1052
1053  //initialize encoder parameters
1054  initALFEncoderParam(alfParamSet, alfCtrlParam);
1055
1056  //get LCU statistics
1057  getStatistics(yuvOrg, yuvExtRec);
1058
1059  //decide ALF parameters
1060#if HHI_INTERVIEW_SKIP
1061  decideParameters(yuvOrg, yuvExtRec, yuvRec, pUsedPelMap, m_bestAlfParamSet, alfCtrlParam);
1062#else
1063  decideParameters(yuvOrg, yuvExtRec, yuvRec, m_bestAlfParamSet, alfCtrlParam);
1064#endif
1065
1066  //assign best parameters
1067  assignALFEncoderParam(alfParamSet, alfCtrlParam);
1068}
1069
1070/** Check if the current LCU can be merged with neighboring LCU
1071 * \param [in] compIdx luma/chroma component index
1072 * \param [out] alfUnitPic ALF unit parameters for all LCUs in picture
1073 */
1074Void TEncAdaptiveLoopFilter::checkMerge(Int compIdx, AlfUnitParam* alfUnitPic)
1075{
1076  AlfUnitParam *alfUnitLeft, *alfUnitUp;
1077
1078  for(Int n=0; n< m_uiNumCUsInFrame; n++)
1079  {
1080    Int lcuPosX = (Int)(n % m_numLCUInPicWidth);
1081    Int lcuPosY = (Int)(n / m_numLCUInPicWidth);
1082
1083    AlfUnitParam& alfUnitCur = alfUnitPic[n];
1084
1085    //check merge left
1086    if( lcuPosX != 0)
1087    {
1088      alfUnitLeft = &(alfUnitPic[n - 1]);
1089      if(alfUnitCur == *alfUnitLeft)
1090      {
1091        alfUnitCur.mergeType = ALF_MERGE_LEFT;
1092        alfUnitCur.isEnabled = alfUnitLeft->isEnabled;
1093        alfUnitCur.isNewFilt = alfUnitLeft->isNewFilt;
1094        alfUnitCur.storedFiltIdx = alfUnitLeft->storedFiltIdx;
1095        *(alfUnitCur.alfFiltParam) = *(alfUnitLeft->alfFiltParam);
1096        continue;
1097      }
1098    }
1099
1100    //check merge up
1101    if(lcuPosY !=0 )
1102    {
1103      alfUnitUp = &(alfUnitPic[n - m_numLCUInPicWidth]);
1104      if(alfUnitCur == *alfUnitUp)
1105      {
1106        alfUnitCur.mergeType = ALF_MERGE_UP;
1107        alfUnitCur.isEnabled = alfUnitUp->isEnabled;
1108        alfUnitCur.isNewFilt = alfUnitUp->isNewFilt;
1109        alfUnitCur.storedFiltIdx = alfUnitUp->storedFiltIdx;
1110        *(alfUnitCur.alfFiltParam) = *(alfUnitUp->alfFiltParam);
1111        continue;
1112      }
1113    }
1114  }
1115
1116}
1117
1118/** Transfer ALF unit parameters for LCUs to to-be-coded ALF parameter set
1119 * \param [in] compIdx luma/chroma component index
1120 * \param [in] alfUnitPic ALF unit parameters for all LCUs in picture
1121 * \param [out] alfParamSet to-be-coded ALF parameter set
1122 */
1123Void TEncAdaptiveLoopFilter::transferToAlfParamSet(Int compIdx, AlfUnitParam* alfUnitPic, AlfParamSet* & alfParamSet)
1124{
1125
1126  Int countFiltOffLCU = 0, countNewFilts = 0;
1127
1128  AlfUnitParam* alfUnitParams = alfParamSet->alfUnitParam[compIdx];
1129  for(Int n=0; n< m_uiNumCUsInFrame; n++)
1130  {
1131    alfUnitParams[n] = alfUnitPic[n];
1132
1133
1134    if(alfUnitParams[n].alfFiltParam->alf_flag == 0)
1135    {
1136      countFiltOffLCU++;
1137    }
1138    else
1139    {
1140      Bool isNewFiltInSlice =   (alfUnitParams[n].mergeType == ALF_MERGE_DISABLED && alfUnitParams[n].isEnabled && alfUnitParams[n].isNewFilt);
1141      if( isNewFiltInSlice )
1142      {
1143        countNewFilts++;
1144      }
1145    }
1146  }
1147
1148  //slice-level parameters
1149  AlfUnitParam* firstAlfUnitInSlice = &(alfUnitParams[0]);
1150  if( countFiltOffLCU == m_uiNumCUsInFrame ) //number of filter-off LCU is equal to the number of LCUs in slice
1151  {
1152    alfParamSet->isEnabled [compIdx] = false;   
1153    alfParamSet->isUniParam[compIdx] = true; //uni-param, all off
1154    assert(firstAlfUnitInSlice->alfFiltParam->alf_flag == 0);
1155  }
1156  else
1157  {
1158    alfParamSet->isEnabled[compIdx] = true;
1159    if( countNewFilts == 1 && firstAlfUnitInSlice->alfFiltParam->alf_flag != 0 && countFiltOffLCU == 0)
1160    {
1161      alfParamSet->isUniParam[compIdx] = true;
1162    }
1163    else
1164    {
1165      alfParamSet->isUniParam[compIdx] = false;
1166    }
1167  }
1168
1169}
1170
1171/** Disable all ALF unit parameters in current component
1172 * \param [in] compIdx luma/chroma component index
1173 * \param [out] alfParamSet to-be-coded ALF parameter set
1174 * \param [in] alfUnitPic ALF unit parameters for all LCUs in picture
1175 */
1176Void TEncAdaptiveLoopFilter::disableComponentAlfParam(Int compIdx, AlfParamSet* alfParamSet, AlfUnitParam* alfUnitPic)
1177{
1178  alfParamSet->isEnabled [compIdx] = false;
1179  alfParamSet->isUniParam[compIdx] = true; //all off
1180
1181  for(Int lcuPos = 0; lcuPos < m_uiNumCUsInFrame; lcuPos++)
1182  {
1183    AlfUnitParam& alfunitParam = alfUnitPic[lcuPos];
1184
1185    alfunitParam.mergeType = ALF_MERGE_DISABLED; 
1186    alfunitParam.isEnabled = false; 
1187    alfunitParam.isNewFilt = false; 
1188    alfunitParam.storedFiltIdx = -1;
1189    alfunitParam.alfFiltParam->alf_flag = 0;
1190  }
1191
1192  //check merge-up and merge-left
1193  checkMerge(compIdx, alfUnitPic);
1194
1195  //transfer to AlfParamSet
1196  transferToAlfParamSet(compIdx, alfUnitPic, alfParamSet);
1197
1198}
1199
1200/** Picture-based encoding
1201 * \param [out] alfParamSet to-be-coded ALF parameter set
1202 * \param [in, out] alfPicQTPart picture quad-tree partition
1203 * \param [in] compIdx luma/chroma component index
1204 * \param [in] pOrg picture buffer for original picture
1205 * \param [in] pDec picture buffer for un-filtered picture
1206 * \param [out] pRest picture buffer for filtered picture
1207 * \param [in] stride stride size for 1-D picture memory
1208 * \param [in, out] alfCorrLCUs correlation values for LCUs
1209 */
1210#if HHI_INTERVIEW_SKIP
1211Void TEncAdaptiveLoopFilter::executePicBasedModeDecision(AlfParamSet* alfParamSet
1212                                                        , AlfPicQTPart* alfPicQTPart
1213                                                        , Int compIdx
1214                                                        , Pel* pOrg, Pel* pDec, Pel* pRest, Pel* pUsed, Int stride, Int formatShift
1215                                                        , AlfCorrData** alfCorrLCUs
1216                                                        )
1217#else
1218Void TEncAdaptiveLoopFilter::executePicBasedModeDecision(AlfParamSet* alfParamSet
1219                                                        , AlfPicQTPart* alfPicQTPart
1220                                                        , Int compIdx
1221                                                        , Pel* pOrg, Pel* pDec, Pel* pRest, Int stride, Int formatShift
1222                                                        , AlfCorrData** alfCorrLCUs
1223                                                        )
1224#endif
1225{
1226  if(compIdx != ALF_Y)
1227  {
1228    if(!alfParamSet->isEnabled[ALF_Y])
1229    {
1230      disableComponentAlfParam(compIdx, alfParamSet, m_alfPicFiltUnits[compIdx]);
1231      return;
1232    }
1233  }
1234
1235  Int picWidth = (m_img_width >> formatShift);
1236  Int picHeight= (m_img_height >> formatShift);
1237
1238  Int64  minDist = 0;
1239  Int64  minRate = 0;
1240  Double minCost = 0;
1241
1242  decideQTPartition(alfPicQTPart, alfCorrLCUs, 0, 0, minCost, minDist, minRate);
1243
1244  //patch quad-tree decision to m_alfPicFiltUnits (m_alfFiltInfo[compIdx])
1245  patchAlfUnitParams(alfPicQTPart, 0, m_alfPicFiltUnits[compIdx]);
1246
1247  //check merge-up and merge-left
1248  checkMerge(compIdx, m_alfPicFiltUnits[compIdx]);
1249
1250  //transfer to AlfParamSet
1251  transferToAlfParamSet(compIdx, m_alfPicFiltUnits[compIdx], alfParamSet);
1252
1253  //reconstruction
1254  recALF(compIdx, m_alfFiltInfo[compIdx], pDec, pRest, stride, formatShift, NULL, false);
1255
1256  Double lambda = (compIdx == ALF_Y)?(m_dLambdaLuma):(m_dLambdaChroma);
1257
1258
1259  std::vector<AlfCUCtrlInfo> alfCUCtrlParamTemp(m_vBestAlfCUCtrlParam); 
1260  minRate = calculateAlfParamSetRateRDO(compIdx, alfParamSet, &alfCUCtrlParamTemp);
1261#if HHI_INTERVIEW_SKIP
1262  minDist = xCalcSSD(pOrg, pRest, pUsed, picWidth, picHeight, stride);
1263#else
1264  minDist = xCalcSSD(pOrg, pRest, picWidth, picHeight, stride);
1265#endif
1266  minCost = (Double)minDist + lambda*((Double)minRate);
1267
1268  //block on/off control
1269  if(compIdx == ALF_Y && m_bAlfCUCtrlEnabled)
1270  {
1271#if HHI_INTERVIEW_SKIP
1272    decideBlockControl(pOrg, pDec, pRest, pUsed, stride, alfPicQTPart, alfParamSet, minRate, minDist, minCost);
1273#else
1274    decideBlockControl(pOrg, pDec, pRest, stride, alfPicQTPart, alfParamSet, minRate, minDist, minCost); 
1275#endif
1276  }
1277
1278  //get filter-off distortion, rate, cost
1279  AlfParamSet alfParamSetOff;
1280  for(Int s=0; s< m_uiNumSlicesInPic; s++)
1281  {
1282    alfCUCtrlParamTemp[s].reset();
1283  }
1284  alfParamSetOff.isEnabled[compIdx] = false;
1285  alfParamSetOff.isUniParam[compIdx] = true;
1286#if HHI_INTERVIEW_SKIP
1287  Int64  offDist = xCalcSSD(pOrg, pDec, pUsed, picWidth, picHeight, stride);
1288#else
1289  Int64  offDist = xCalcSSD(pOrg, pDec, picWidth, picHeight, stride);
1290#endif
1291  Int64  offRate = calculateAlfParamSetRateRDO(compIdx, &alfParamSetOff, &alfCUCtrlParamTemp);
1292  Double offCost = (Double)offDist + lambda*((Double)offRate);
1293
1294  if(offCost < minCost  )
1295  {
1296    //revert to filter-off results
1297    Pel* pelSrc = pDec;
1298    Pel* pelDst = pRest;
1299    for(Int y=0; y< picHeight; y++)
1300    {
1301      ::memcpy(pelDst, pelSrc, sizeof(Pel)*picWidth);
1302      pelSrc += stride;
1303      pelDst += stride;
1304    }
1305
1306    alfParamSet->isEnabled[compIdx] = false;
1307    alfParamSet->isUniParam[compIdx] = true; //all filter-off
1308  }
1309
1310}
1311
1312/** copy picture quadtree infromation
1313 * \param [out] alfPicQTPartDest destination part in picture quad tree
1314 * \param [in ] alfPicQTPartSrc source part in picture quad tree
1315 */
1316Void TEncAdaptiveLoopFilter::copyPicQT(AlfPicQTPart* alfPicQTPartDest, AlfPicQTPart* alfPicQTPartSrc)
1317{
1318  for (Int i=0; i< m_alfNumCulPartsLevelTab[m_alfPQTMaxDepth]; i++)
1319  {
1320    alfPicQTPartDest[i] = alfPicQTPartSrc[i];
1321  }
1322}
1323
1324/** copy pixel values for one rectangular region
1325 * \param [out] imgDest destination part in picture quad tree
1326 * \param [in ] imgSrc source part in picture quad tree
1327 * \param [in ] stride source part in picture quad tree
1328 * \param [in ] yPos starting y position
1329 * \param [in ] height region height
1330 * \param [in ] xPos starting x position
1331 * \param [in ] width region width
1332 */
1333Void TEncAdaptiveLoopFilter::copyPixelsInOneRegion(Pel* imgDest, Pel* imgSrc, Int stride, Int yPos, Int height, Int xPos, Int width)
1334{
1335  Int offset = (yPos*stride) + xPos;
1336  Pel *imgDestLine = imgDest + offset;
1337  Pel *imgSrcLine  = imgSrc  + offset;
1338
1339  for (Int j=0; j<height; j++)
1340  {
1341    ::memcpy(imgDestLine, imgSrcLine, sizeof(Pel)*width);
1342    imgDestLine += stride;
1343    imgSrcLine  += stride;
1344  }
1345}
1346
1347/** Re-design ALF parameters for picture quad-tree partitions
1348 * \param [out] alfPicQTPart picture quad-tree partition information
1349 * \param [in ] partIdx partition index
1350 * \param [in ] partLevel partition level
1351 */
1352Void TEncAdaptiveLoopFilter::reDesignQT(AlfPicQTPart *alfPicQTPart, Int partIdx, Int partLevel)
1353{
1354  AlfPicQTPart *alfPicQTOnePart = &(alfPicQTPart[partIdx]); 
1355  Int nextPartLevel = partLevel + 1;
1356
1357  if (!alfPicQTOnePart->isSplit)
1358  {
1359    if (alfPicQTOnePart->alfUnitParam->alfFiltParam->alf_flag)
1360    {
1361      executeModeDecisionOnePart(alfPicQTPart, m_alfCorr[ALF_Y], partIdx, partLevel) ;     
1362    }
1363  }
1364  else
1365  {
1366    for (Int i=0; i<4; i++)
1367    {
1368      reDesignQT(alfPicQTPart, alfPicQTOnePart->childPartIdx[i], nextPartLevel);
1369    }
1370  } 
1371}
1372
1373/** CU-on/off control decision
1374 * \param [in ] imgOrg picture buffer for original picture
1375 * \param [in ] imgDec picture buffer for un-filtered picture
1376 * \param [in ] imgRest picture buffer for filtered picture
1377 * \param [in ] stride buffer stride size for 1-D picture memory
1378 * \param [in, out] alfPicQTPart picture quad-tree partition information
1379 * \param [in, out] alfParamSet ALF parameter set
1380 * \param [in, out ] minRate minimum rate
1381 * \param [in, out ] minDist minimum distortion
1382 * \param [in, out ] minCost minimum RD cost
1383 */
1384#if HHI_INTERVIEW_SKIP
1385Void TEncAdaptiveLoopFilter::decideBlockControl(Pel* imgOrg, Pel* imgDec, Pel* imgRest, Pel* imgUsed, Int stride, AlfPicQTPart* alfPicQTPart, AlfParamSet* & alfParamSet, Int64 &minRate, Int64 &minDist, Double &minCost)
1386#else
1387Void TEncAdaptiveLoopFilter::decideBlockControl(Pel* imgOrg, Pel* imgDec, Pel* imgRest, Int stride, AlfPicQTPart* alfPicQTPart, AlfParamSet* & alfParamSet, Int64 &minRate, Int64 &minDist, Double &minCost)
1388#endif
1389{
1390  Int    rate, ctrlDepth;
1391  Double cost;
1392  UInt64 dist;
1393  Bool isChanged = false;
1394  Pel *imgYtemp = getPicBuf(m_pcPicYuvTmp, ALF_Y);
1395  Pel *imgYBest = getPicBuf(m_pcPicYuvBest, ALF_Y);
1396  std::vector<AlfCUCtrlInfo> vAlfCUCtrlParamTemp(m_vBestAlfCUCtrlParam); 
1397
1398  AlfPicQTPart *alfPicQTPartNoCtrl = new AlfPicQTPart [ m_alfNumCulPartsLevelTab[m_alfPQTMaxDepth] ];
1399  AlfPicQTPart *alfPicQTPartBest   = new AlfPicQTPart [ m_alfNumCulPartsLevelTab[m_alfPQTMaxDepth] ];
1400
1401  // backup data of PQT without block on/off
1402  copyPicQT(alfPicQTPartNoCtrl, alfPicQTPart);
1403
1404  for (ctrlDepth=0; ctrlDepth<4; ctrlDepth++)
1405  {       
1406    // Restore data from PQT without block on/off
1407    copyPixelsInOneRegion(imgYtemp, imgRest, stride, 0, m_img_height, 0, m_img_width);
1408    copyPicQT(alfPicQTPart, alfPicQTPartNoCtrl);
1409
1410    for (Int reDesignRun=0; reDesignRun <= m_iALFNumOfRedesign; reDesignRun++)
1411    {
1412      // re-design filter
1413      if (reDesignRun > 0)
1414      {
1415        // re-gather statistics
1416        getOneCompStatistics(m_alfCorr[ALF_Y], ALF_Y, imgOrg, imgDec, stride, 0, true);
1417
1418        // reDesign in each QT partition
1419        reDesignQT(alfPicQTPart, 0, 0);
1420
1421        //patch quad-tree decision to m_alfPicFiltUnits (m_alfFiltInfo[compIdx])
1422        patchAlfUnitParams(alfPicQTPart, 0, m_alfPicFiltUnits[ALF_Y]);
1423
1424        //reconstruction
1425        copyPixelsInOneRegion(imgYtemp, imgDec, stride, 0, m_img_height, 0, m_img_width);
1426        recALF(ALF_Y, m_alfFiltInfo[ALF_Y], imgDec, imgYtemp, stride, 0, NULL, false);
1427      }
1428
1429      // Gest distortion and decide on/off, Pel should be changed to TComPicYUV
1430#if HHI_INTERVIEW_SKIP
1431      setCUAlfCtrlFlags((UInt)ctrlDepth, imgOrg, imgDec, imgYtemp, imgUsed, stride, dist, vAlfCUCtrlParamTemp);
1432#else
1433      setCUAlfCtrlFlags((UInt)ctrlDepth, imgOrg, imgDec, imgYtemp, stride, dist, vAlfCUCtrlParamTemp);   
1434#endif
1435
1436      //patch quad-tree decision to m_alfPicFiltUnits (m_alfFiltInfo[compIdx])
1437      patchAlfUnitParams(alfPicQTPart, 0, m_alfPicFiltUnits[ALF_Y]);
1438
1439      //check merge-up and merge-left
1440      checkMerge(ALF_Y, m_alfPicFiltUnits[ALF_Y]);
1441
1442      //transfer to AlfParamSet
1443      transferToAlfParamSet(ALF_Y, m_alfPicFiltUnits[ALF_Y], alfParamSet);
1444
1445      rate = calculateAlfParamSetRateRDO(ALF_Y, alfParamSet, &vAlfCUCtrlParamTemp);
1446      cost = (Double)dist + m_dLambdaLuma * ((Double)rate);
1447
1448      if (cost < minCost)
1449      {
1450        isChanged     = true;
1451        minCost       = cost;
1452        minDist       = (Int64) dist;
1453        minRate       = rate;
1454
1455        m_vBestAlfCUCtrlParam = vAlfCUCtrlParamTemp;
1456        copyPixelsInOneRegion(imgYBest, imgYtemp, stride, 0, m_img_height, 0, m_img_width);
1457
1458        copyPicQT(alfPicQTPartBest, alfPicQTPart);
1459        xCopyTmpAlfCtrlFlagsFrom();
1460      }
1461
1462    }
1463  }
1464
1465  if (isChanged == true)
1466  {
1467    copyPicQT(alfPicQTPart, alfPicQTPartBest);
1468    xCopyTmpAlfCtrlFlagsTo();
1469
1470    copyPixelsInOneRegion(imgRest, imgYBest, stride, 0, m_img_height, 0, m_img_width);
1471    xCopyDecToRestCUs(imgDec, imgRest, stride);
1472  }
1473  else
1474  {
1475    copyPicQT(alfPicQTPart, alfPicQTPartNoCtrl);
1476  }
1477
1478  //patch quad-tree decision to m_alfPicFiltUnits (m_alfFiltInfo[compIdx])
1479  patchAlfUnitParams(alfPicQTPart, 0, m_alfPicFiltUnits[ALF_Y]);
1480
1481  //check merge-up and merge-left
1482  checkMerge(ALF_Y, m_alfPicFiltUnits[ALF_Y]);
1483
1484  //transfer to AlfParamSet
1485  transferToAlfParamSet(ALF_Y, m_alfPicFiltUnits[ALF_Y], alfParamSet);
1486
1487  delete [] alfPicQTPartNoCtrl;
1488  alfPicQTPartNoCtrl = NULL;
1489
1490  delete [] alfPicQTPartBest;
1491  alfPicQTPartBest = NULL;
1492}
1493
1494/** Copy ALF unit parameters from quad-tree partition to LCUs
1495 * \param [in] alfPicQTPart picture quad-tree partition information
1496 * \param [in] partIdx partition index
1497 * \param [out] alfUnitPic ALF unit parameters for LCUs
1498 */
1499Void TEncAdaptiveLoopFilter::patchAlfUnitParams(AlfPicQTPart* alfPicQTPart, Int partIdx, AlfUnitParam* alfUnitPic)
1500{
1501  AlfPicQTPart* alfQTPart = &(alfPicQTPart[partIdx]);
1502  //Int compIdx = alfQTPart->componentID;
1503
1504  if(alfQTPart->isSplit == false)
1505  {
1506    AlfUnitParam* alfpartParam = alfQTPart->alfUnitParam;
1507
1508    Int lcuPos;
1509    for(Int lcuPosY = alfQTPart->partCUYS; lcuPosY <= alfQTPart->partCUYE; lcuPosY++)
1510    {
1511      for(Int lcuPosX = alfQTPart->partCUXS; lcuPosX <= alfQTPart->partCUXE; lcuPosX++)
1512      {
1513        lcuPos = lcuPosY*m_numLCUInPicWidth + lcuPosX;
1514        AlfUnitParam& alfunitParam = alfUnitPic[lcuPos];
1515
1516        alfunitParam.mergeType = alfpartParam->mergeType; 
1517        alfunitParam.isEnabled = alfpartParam->isEnabled; 
1518        alfunitParam.isNewFilt = alfpartParam->isNewFilt; 
1519        alfunitParam.storedFiltIdx = alfpartParam->storedFiltIdx; //not used
1520        *(alfunitParam.alfFiltParam) = *(alfpartParam->alfFiltParam);
1521      }
1522    }
1523  }
1524  else
1525  {
1526    for(Int i=0; i< 4; i++)
1527    {
1528      patchAlfUnitParams(alfPicQTPart, alfQTPart->childPartIdx[i], alfUnitPic);     
1529    }
1530  }
1531}
1532
1533/** Decide picture quad-tree partition
1534 * \param [in, out] alfPicQTPart picture quad-tree partition information
1535 * \param [in, out] alfPicLCUCorr correlations for LCUs
1536 * \param [int] partIdx partition index
1537 * \param [int] partLevel partition level
1538 * \param [in, out] cost cost for one partition
1539 * \param [in, out] dist distortion for one partition
1540 * \param [in, out] rate bitrate for one partition
1541 */
1542Void TEncAdaptiveLoopFilter::decideQTPartition(AlfPicQTPart* alfPicQTPart, AlfCorrData** alfPicLCUCorr, Int partIdx, Int partLevel, Double &cost, Int64 &dist, Int64 &rate)
1543{
1544  AlfPicQTPart* alfPicQTOnePart = &(alfPicQTPart[partIdx]);
1545  Int nextPartLevel = partLevel + 1;
1546  Int childPartIdx;
1547  Double splitCost = 0;
1548  Int64  splitRate = 0;
1549  Int64  splitDist = 0; 
1550
1551  if (!alfPicQTOnePart->isProcessed)
1552  {
1553    executeModeDecisionOnePart(alfPicQTPart, alfPicLCUCorr, partIdx, partLevel);
1554
1555    alfPicQTOnePart->isProcessed = true;
1556  }
1557
1558  if (!alfPicQTOnePart->isBottomLevel) 
1559  {   
1560    for (Int i=0; i<4; i++)
1561    {     
1562      childPartIdx = alfPicQTOnePart->childPartIdx[i];
1563      decideQTPartition(alfPicQTPart, alfPicLCUCorr, childPartIdx, nextPartLevel, splitCost, splitDist, splitRate);     
1564    }
1565
1566    alfPicQTOnePart->splitMinCost = splitCost;
1567    alfPicQTOnePart->splitMinDist = splitDist;
1568    alfPicQTOnePart->splitMinRate = splitRate;
1569
1570    if (alfPicQTOnePart->splitMinCost < alfPicQTOnePart->selfMinCost)
1571    {
1572      alfPicQTOnePart->isSplit = true;
1573    }
1574    else
1575    { 
1576      alfPicQTOnePart->isSplit = false; 
1577    }
1578  }
1579  else
1580  {
1581    alfPicQTOnePart->isSplit = false;
1582    alfPicQTOnePart->splitMinCost = alfPicQTOnePart->selfMinCost;
1583    alfPicQTOnePart->splitMinDist = alfPicQTOnePart->selfMinDist;
1584    alfPicQTOnePart->splitMinRate = alfPicQTOnePart->selfMinRate;
1585  }
1586
1587  if (alfPicQTOnePart->isSplit)
1588  {
1589    cost += alfPicQTOnePart->splitMinCost;
1590    rate += alfPicQTOnePart->splitMinRate;
1591    dist += alfPicQTOnePart->splitMinDist;
1592  }
1593  else
1594  {
1595    cost += alfPicQTOnePart->selfMinCost;
1596    rate += alfPicQTOnePart->selfMinRate;
1597    dist += alfPicQTOnePart->selfMinDist;
1598  }
1599
1600}
1601
1602/** Mode decision process for one picture quad-tree partition
1603 * \param [in, out] alfPicQTPart picture quad-tree partition information
1604 * \param [in, out] alfPicLCUCorr correlations for LCUs
1605 * \param [int] partIdx partition index
1606 * \param [int] partLevel partition level
1607 */
1608Void TEncAdaptiveLoopFilter::executeModeDecisionOnePart(AlfPicQTPart *alfPicQTPart, AlfCorrData** alfPicLCUCorr, Int partIdx, Int partLevel)
1609{
1610  AlfPicQTPart* alfQTPart = &(alfPicQTPart[partIdx]);
1611  Int compIdx = alfQTPart->componentID;
1612  Double lambda = (compIdx == ALF_Y)?(m_dLambdaLuma):(m_dLambdaChroma);
1613
1614  //gather correlations
1615  alfQTPart->alfCorr->reset();
1616  for(Int lcuPosY = alfQTPart->partCUYS; lcuPosY <= alfQTPart->partCUYE; lcuPosY++)
1617  {
1618    for(Int lcuPosX = alfQTPart->partCUXS; lcuPosX <= alfQTPart->partCUXE; lcuPosX++)
1619    {
1620      *(alfQTPart->alfCorr) +=  *(alfPicLCUCorr[lcuPosY*m_numLCUInPicWidth + lcuPosX]);
1621    }
1622  }
1623
1624  //test filter on
1625  AlfUnitParam* alfPartUnitParam = alfQTPart->alfUnitParam;
1626  alfPartUnitParam->mergeType = ALF_MERGE_DISABLED;
1627  alfPartUnitParam->isEnabled = true;
1628  alfPartUnitParam->isNewFilt = true;
1629  alfPartUnitParam->storedFiltIdx = -1;
1630  alfPartUnitParam->alfFiltParam->alf_flag = 1;
1631  deriveFilterInfo(compIdx, alfQTPart->alfCorr, alfPartUnitParam->alfFiltParam, alfQTPart->numFilterBudget);
1632
1633  alfQTPart->selfMinDist = estimateFilterDistortion(compIdx, alfQTPart->alfCorr, m_filterCoeffSym, alfPartUnitParam->alfFiltParam->filters_per_group, m_varIndTab);
1634  alfQTPart->selfMinRate = calculateAlfUnitRateRDO(alfPartUnitParam);
1635  alfQTPart->selfMinCost = (Double)(alfQTPart->selfMinDist) + lambda*((Double)(alfQTPart->selfMinRate));
1636 
1637  alfQTPart->selfMinCost +=  ((lambda* 1.5)* ((Double)( (alfQTPart->partCUYE - alfQTPart->partCUYS+ 1)*(alfQTPart->partCUXE - alfQTPart->partCUXS +1) )));  //RDCO
1638 
1639
1640  //test filter off
1641  AlfUnitParam alfUnitParamTemp(*(alfQTPart->alfUnitParam));
1642  alfUnitParamTemp.mergeType = ALF_MERGE_DISABLED;
1643  alfUnitParamTemp.isEnabled = false;
1644  Int64  dist = estimateFilterDistortion(compIdx, alfQTPart->alfCorr);
1645  Int64  rate = calculateAlfUnitRateRDO(&alfUnitParamTemp);
1646  Double cost = (Double)dist + lambda*((Double)rate);
1647  if(cost < alfQTPart->selfMinCost)
1648  {
1649    alfQTPart->selfMinCost = cost;
1650    alfQTPart->selfMinDist = dist;
1651    alfQTPart->selfMinRate = rate;
1652    *(alfQTPart->alfUnitParam) = alfUnitParamTemp;
1653
1654    alfQTPart->alfUnitParam->alfFiltParam->alf_flag = 0;
1655  }
1656
1657}
1658
1659/** Derive filter coefficients
1660 * \param [in, out] alfPicQTPart picture quad-tree partition information
1661 * \param [in, out] alfPicLCUCorr correlations for LCUs
1662 * \param [int] partIdx partition index
1663 * \param [int] partLevel partition level
1664 */
1665Void TEncAdaptiveLoopFilter::deriveFilterInfo(Int compIdx, AlfCorrData* alfCorr, ALFParam* alfFiltParam, Int maxNumFilters)
1666{
1667  const Int filtNo = 0; 
1668  const Int numCoeff = ALF_MAX_NUM_COEF;
1669
1670  switch(compIdx)
1671  {
1672  case ALF_Y:
1673    {       
1674      Int lambdaForMerge = ((Int) m_dLambdaLuma) * (1<<(2*g_uiBitIncrement));
1675      Int numFilters;
1676
1677      ::memset(m_varIndTab, 0, sizeof(Int)*NO_VAR_BINS);
1678
1679      xfindBestFilterVarPred(alfCorr->yCorr, alfCorr->ECorr, alfCorr->pixAcc, m_filterCoeffSym, m_filterCoeffSymQuant, filtNo, &numFilters, m_varIndTab, NULL, m_varImg, m_maskImg, NULL, lambdaForMerge, maxNumFilters);
1680      xcodeFiltCoeff(m_filterCoeffSymQuant, filtNo, m_varIndTab, numFilters, alfFiltParam);
1681    }
1682    break;
1683  case ALF_Cb:
1684  case ALF_Cr:
1685    {
1686      static Double coef[ALF_MAX_NUM_COEF];
1687
1688      alfFiltParam->filters_per_group = 1;
1689
1690      gnsSolveByChol(alfCorr->ECorr[0], alfCorr->yCorr[0], coef, numCoeff);
1691      xQuantFilterCoef(coef, m_filterCoeffSym[0], filtNo, g_uiBitDepth + g_uiBitIncrement);
1692      ::memcpy(alfFiltParam->coeffmulti[0], m_filterCoeffSym[0], sizeof(Int)*numCoeff);
1693      predictALFCoeffChroma(alfFiltParam->coeffmulti[0]);
1694    }
1695    break;
1696  default:
1697    {
1698      printf("Not a legal component ID\n");
1699      assert(0);
1700      exit(-1);
1701    }
1702  }
1703
1704
1705}
1706
1707/** Estimate rate-distortion cost for ALF parameter set
1708 * \param [in] compIdx luma/chroma component index
1709 * \param [in] alfParamSet ALF parameter set
1710 * \param [in] alfCUCtrlParam CU-on/off control parameters
1711 */
1712Int TEncAdaptiveLoopFilter::calculateAlfParamSetRateRDO(Int compIdx, AlfParamSet* alfParamSet, std::vector<AlfCUCtrlInfo>* alfCUCtrlParam)
1713{
1714  Int rate = 0;
1715
1716  m_pcEntropyCoder->resetEntropy();
1717  m_pcEntropyCoder->resetBits();
1718
1719
1720  m_pcEntropyCoder->encodeAlfParamSet(alfParamSet, m_numLCUInPicWidth, m_uiNumCUsInFrame, 0, true, compIdx, compIdx);
1721
1722  if(m_bAlfCUCtrlEnabled)
1723  {
1724    for(Int s=0; s< m_uiNumSlicesInPic; s++)
1725    {
1726      m_pcEntropyCoder->encodeAlfCtrlParam( (*alfCUCtrlParam)[s], m_uiNumCUsInFrame);     
1727    }
1728  }
1729
1730  rate = m_pcEntropyCoder->getNumberOfWrittenBits();
1731
1732  return rate;
1733}
1734
1735/** Estimate rate-distortion cost for ALF unit parameters
1736 * \param [in] alfUnitParam ALF unit parameters
1737 * \param [in] numStoredFilters number of stored filter (set)
1738 */
1739Int TEncAdaptiveLoopFilter::calculateAlfUnitRateRDO(AlfUnitParam* alfUnitParam, Int numStoredFilters)
1740{
1741  Int rate = 0;
1742
1743  if(alfUnitParam->mergeType != ALF_MERGE_LEFT)
1744  {
1745    m_pcEntropyCoder->resetEntropy();
1746    m_pcEntropyCoder->resetBits();
1747
1748    m_pcEntropyCoder->encodeAlfFlag( (alfUnitParam->mergeType == ALF_MERGE_UP)?1:0);
1749
1750    if(alfUnitParam->mergeType != ALF_MERGE_UP)
1751    {
1752      m_pcEntropyCoder->encodeAlfFlag( (alfUnitParam->isEnabled)?1:0);
1753
1754      if(alfUnitParam->isEnabled)
1755      {
1756        if(numStoredFilters > 0)
1757        {
1758          m_pcEntropyCoder->encodeAlfFlag( (alfUnitParam->isNewFilt)?1:0);
1759        }
1760
1761        if(!(alfUnitParam->isNewFilt) && numStoredFilters > 0)
1762        {
1763          m_pcEntropyCoder->encodeAlfStoredFilterSetIdx(alfUnitParam->storedFiltIdx, numStoredFilters);
1764        }
1765        else
1766        {
1767          m_pcEntropyCoder->encodeAlfParam(alfUnitParam->alfFiltParam);
1768        }
1769
1770      }
1771    }
1772    rate = m_pcEntropyCoder->getNumberOfWrittenBits();
1773  }
1774  return rate;
1775}
1776
1777/** Estimate filtering distortion
1778 * \param [in] compIdx luma/chroma component index
1779 * \param [in] alfCorr correlations
1780 * \param [in] coeffSet filter coefficients
1781 * \param [in] filterSetSize number of filter set
1782 * \param [in] mergeTable merge table of filter set (only for luma BA)
1783 * \param [in] doPixAccMerge calculate pixel squared value (true) or not (false)
1784 */
1785Int64 TEncAdaptiveLoopFilter::estimateFilterDistortion(Int compIdx, AlfCorrData* alfCorr, Int** coeffSet, Int filterSetSize, Int* mergeTable, Bool doPixAccMerge)
1786{
1787  const Int numCoeff = (Int)ALF_MAX_NUM_COEF;
1788  AlfCorrData* alfMerged = m_alfCorrMerged[compIdx];
1789
1790  alfMerged->mergeFrom(*alfCorr, mergeTable, doPixAccMerge);
1791
1792  Int**     coeff = (coeffSet == NULL)?(m_coeffNoFilter):(coeffSet);
1793  Int64     iDist = 0;
1794  for(Int f=0; f< filterSetSize; f++)
1795  {
1796    iDist += xFastFiltDistEstimation(alfMerged->ECorr[f], alfMerged->yCorr[f], coeff[f], numCoeff);
1797  }
1798  return iDist;
1799}
1800
1801/** Mode decision for ALF unit in LCU-based encoding
1802 * \param [in] compIdx luma/chroma component index
1803 * \param [in] alfUnitPic ALF unit parmeters for LCUs in picture
1804 * \param [in] lcuIdx LCU index (order) in slice
1805 * \param [in] lcuPos LCU position in picture
1806 * \param [in] numLCUWidth number of width in LCU
1807 * \param [in, out] alfUnitParams ALF unit parameters for LCUs in slice
1808 * \param [in] alfCorr correlations
1809 * \param [in] storedFilters stored-filter buffer
1810 * \param [in] maxNumFilter constraint for number of filters
1811 * \param [in] lambda lagrangian multiplier for RDO
1812 * \param [in] isLeftUnitAvailable left ALF unit available (true) or not (false)
1813 * \param [in] isUpUnitAvailable upper ALF unit available (true) or not (false)
1814 */
1815Void TEncAdaptiveLoopFilter::decideLCUALFUnitParam(Int compIdx, AlfUnitParam* alfUnitPic, Int lcuIdx, Int lcuPos, Int numLCUWidth, AlfUnitParam* alfUnitParams, AlfCorrData* alfCorr, std::vector<ALFParam*>& storedFilters, Int maxNumFilter, Double lambda, Bool isLeftUnitAvailable, Bool isUpUnitAvailable)
1816{
1817  Int    numSliceDataInCurrLCU = m_numSlicesDataInOneLCU[lcuPos];
1818  Int    budgetNumFilters = (Int)(maxNumFilter/numSliceDataInCurrLCU);
1819  Int    numStoredFilters = (Int)storedFilters.size();
1820  Double cost, minCost = MAX_DOUBLE;
1821  Int64  dist;
1822  Int    rate;
1823
1824  AlfUnitParam& alfUnitParamCurr = alfUnitParams[lcuIdx];
1825
1826  ///--- new filter mode test ---
1827  AlfUnitParam alfUnitParamTemp(alfUnitParamCurr);
1828  alfUnitParamTemp.mergeType = ALF_MERGE_DISABLED;
1829  alfUnitParamTemp.isEnabled = true;
1830  alfUnitParamTemp.isNewFilt = true;
1831  alfUnitParamTemp.storedFiltIdx = -1;
1832  deriveFilterInfo(compIdx, alfCorr, alfUnitParamTemp.alfFiltParam, budgetNumFilters);
1833
1834  dist = estimateFilterDistortion(compIdx, alfCorr, m_filterCoeffSym, alfUnitParamTemp.alfFiltParam->filters_per_group, m_varIndTab);
1835  rate = calculateAlfUnitRateRDO(&alfUnitParamTemp, numStoredFilters);
1836  cost = (Double)dist + lambda*((Double)rate);
1837  if(cost < minCost)
1838  {
1839    minCost = cost;
1840    alfUnitParamCurr = alfUnitParamTemp;
1841
1842    alfUnitParamCurr.alfFiltParam->alf_flag = 1;
1843  }
1844
1845  if(numSliceDataInCurrLCU == 1)
1846  {
1847    if(numStoredFilters > 0)
1848    {
1849      ///--- stored filter mode test ---//
1850      alfUnitParamTemp = alfUnitParamCurr;
1851
1852      alfUnitParamTemp.mergeType = ALF_MERGE_DISABLED;
1853      alfUnitParamTemp.isEnabled = true;
1854      alfUnitParamTemp.isNewFilt = false;
1855
1856      for(Int i=0; i< numStoredFilters; i++)
1857      {
1858        ALFParam* storedALFParam = storedFilters[i];
1859
1860        alfUnitParamTemp.storedFiltIdx = i;
1861        alfUnitParamTemp.alfFiltParam  = storedALFParam;
1862
1863        assert(storedALFParam->alf_flag == 1);
1864
1865        reconstructCoefInfo(compIdx, storedALFParam, m_filterCoeffSym, m_varIndTab);
1866
1867        dist = estimateFilterDistortion(compIdx, alfCorr, m_filterCoeffSym, alfUnitParamTemp.alfFiltParam->filters_per_group, m_varIndTab);
1868        rate = calculateAlfUnitRateRDO(&alfUnitParamTemp, numStoredFilters);
1869        cost = (Double)dist + lambda*((Double)rate);
1870
1871        if(cost < minCost)
1872        {
1873          minCost = cost;
1874          alfUnitParamCurr = alfUnitParamTemp;
1875        }
1876      }
1877    }
1878
1879    /// merge-up test
1880    if(isUpUnitAvailable)
1881    {
1882      Int addrUp = lcuPos - m_numLCUInPicWidth;
1883      AlfUnitParam& alfUnitParamUp = alfUnitPic[addrUp];
1884
1885      if(alfUnitParamUp.alfFiltParam->alf_flag == 1)
1886      {
1887        alfUnitParamTemp = alfUnitParamUp;
1888        alfUnitParamTemp.mergeType    = ALF_MERGE_UP;
1889
1890        reconstructCoefInfo(compIdx, alfUnitParamTemp.alfFiltParam, m_filterCoeffSym, m_varIndTab);
1891        dist = estimateFilterDistortion(compIdx, alfCorr, m_filterCoeffSym, alfUnitParamTemp.alfFiltParam->filters_per_group, m_varIndTab);
1892        rate = calculateAlfUnitRateRDO(&alfUnitParamTemp, numStoredFilters);
1893        cost = (Double)dist + lambda*((Double)rate);
1894
1895        if(cost < minCost)
1896        {
1897          minCost = cost;
1898
1899          alfUnitParamCurr = alfUnitParamTemp;
1900        }
1901
1902      }
1903
1904    } //upper unit available
1905
1906
1907    /// merge-left test
1908    if(isLeftUnitAvailable)
1909    {
1910      Int addrLeft = lcuPos - 1;
1911      AlfUnitParam& alfUnitParamLeft = alfUnitPic[addrLeft];
1912
1913      if(alfUnitParamLeft.alfFiltParam->alf_flag == 1)
1914      {
1915        alfUnitParamTemp = alfUnitParamLeft;
1916        alfUnitParamTemp.mergeType    = ALF_MERGE_LEFT;
1917
1918        reconstructCoefInfo(compIdx, alfUnitParamTemp.alfFiltParam, m_filterCoeffSym, m_varIndTab);
1919        dist = estimateFilterDistortion(compIdx, alfCorr, m_filterCoeffSym, alfUnitParamTemp.alfFiltParam->filters_per_group, m_varIndTab);
1920        rate = calculateAlfUnitRateRDO(&alfUnitParamTemp, numStoredFilters);
1921        cost = (Double)dist + lambda*((Double)rate);
1922
1923        if(cost < minCost)
1924        {
1925          minCost = cost;
1926
1927          alfUnitParamCurr = alfUnitParamTemp;
1928        }
1929
1930      }
1931
1932    } //left unit available
1933
1934  }
1935}
1936
1937/** Choose the best ALF unit parameters when filter is not enabled.
1938 * \param [out] alfFiltOffParam ALF unit parameters for filter-off case
1939 * \param [in] lcuPos LCU position in picture
1940 * \param [in] alfUnitPic ALF unit parmeters for LCUs in picture
1941 * \param [in] isLeftUnitAvailable left ALF unit available (true) or not (false)
1942 * \param [in] isUpUnitAvailable upper ALF unit available (true) or not (false)
1943 */
1944Void TEncAdaptiveLoopFilter::getFiltOffAlfUnitParam(AlfUnitParam* alfFiltOffParam, Int lcuPos, AlfUnitParam* alfUnitPic, Bool isLeftUnitAvailable, Bool isUpUnitAvailable)
1945{
1946  Int    numSliceDataInCurrLCU = m_numSlicesDataInOneLCU[lcuPos];
1947
1948  if(numSliceDataInCurrLCU == 1)
1949  {
1950    if(isLeftUnitAvailable)
1951    {
1952      Int addrLeft = lcuPos - 1;
1953      AlfUnitParam& alfUnitParamLeft = alfUnitPic[addrLeft];
1954
1955      if(alfUnitParamLeft.alfFiltParam->alf_flag == 0)
1956      {
1957        alfFiltOffParam->mergeType    = ALF_MERGE_LEFT;
1958        alfFiltOffParam->isEnabled    = false;
1959        alfFiltOffParam->alfFiltParam = alfUnitParamLeft.alfFiltParam;
1960
1961        return;
1962      }
1963    }
1964
1965    if(isUpUnitAvailable)
1966    {
1967      Int addrUp = lcuPos - m_numLCUInPicWidth;
1968      AlfUnitParam& alfUnitParamUp = alfUnitPic[addrUp];
1969
1970      if(alfUnitParamUp.alfFiltParam->alf_flag == 0)
1971      {
1972        alfFiltOffParam->mergeType    = ALF_MERGE_UP;
1973        alfFiltOffParam->isEnabled    = false;
1974        alfFiltOffParam->alfFiltParam = alfUnitParamUp.alfFiltParam;
1975
1976        return;
1977      }
1978
1979    }
1980  }
1981
1982
1983  alfFiltOffParam->mergeType = ALF_MERGE_DISABLED;
1984  alfFiltOffParam->isEnabled = false;
1985  alfFiltOffParam->alfFiltParam = alfUnitPic[lcuPos].alfFiltParam;
1986
1987  return;
1988}
1989
1990/** Calculate distortion for ALF LCU
1991 * \param [in] skipLCUBottomLines true for considering skipping bottom LCU lines
1992 * \param [in] compIdx luma/chroma component index
1993 * \param [in] alfLCUInfo ALF LCU information
1994 * \param [in] picSrc source picture buffer
1995 * \param [in] picCmp to-be-compared picture buffer
1996 * \param [in] stride buffer stride size for 1-D pictrue memory
1997 * \param [in] formatShift 0 for luma and 1 for chroma (4:2:0)
1998 * \return the distortion
1999 */
2000#if HHI_INTERVIEW_SKIP
2001Int64 TEncAdaptiveLoopFilter::calcAlfLCUDist(Bool skipLCUBottomLines, Int compIdx, AlfLCUInfo& alfLCUInfo, Pel* picSrc, Pel* picCmp, Pel* picUsed, Int stride, Int formatShift)
2002#else
2003Int64 TEncAdaptiveLoopFilter::calcAlfLCUDist(Bool skipLCUBottomLines, Int compIdx, AlfLCUInfo& alfLCUInfo, Pel* picSrc, Pel* picCmp, Int stride, Int formatShift)
2004#endif
2005{
2006  Int64 dist = 0; 
2007  Int  posOffset, ypos, xpos, height, width;
2008  Pel* pelCmp;
2009  Pel* pelSrc;
2010#if HHI_INTERVIEW_SKIP
2011  Pel* pelUsed = NULL ;
2012#endif
2013#if LCUALF_AVOID_USING_BOTTOM_LINES_ENCODER
2014  Int endypos;
2015  Bool notSkipLinesBelowVB = true;
2016  Int lcuAddr = alfLCUInfo.pcCU->getAddr();
2017  if(skipLCUBottomLines)
2018  {
2019    if(lcuAddr + m_numLCUInPicWidth < m_uiNumCUsInFrame)
2020    {
2021      notSkipLinesBelowVB = false;
2022    }
2023  }
2024#endif
2025
2026  switch(compIdx)
2027  {
2028  case ALF_Cb:
2029  case ALF_Cr:
2030    {
2031      for(Int n=0; n< alfLCUInfo.numSGU; n++)
2032      {
2033        ypos    = (Int)(alfLCUInfo[n].posY   >> formatShift);
2034        xpos    = (Int)(alfLCUInfo[n].posX   >> formatShift);
2035        height  = (Int)(alfLCUInfo[n].height >> formatShift);
2036        width   = (Int)(alfLCUInfo[n].width  >> formatShift);
2037
2038#if LCUALF_AVOID_USING_BOTTOM_LINES_ENCODER
2039        if(!notSkipLinesBelowVB )
2040        {
2041          endypos = ypos+ height -1;
2042          Int iLineVBPos = m_lcuHeightChroma - 2;
2043          Int yEndLineInLCU = endypos % m_lcuHeightChroma;
2044          height = (yEndLineInLCU >= iLineVBPos) ? (height - 2) : height ; 
2045        }
2046#endif
2047
2048        posOffset = (ypos * stride) + xpos;
2049        pelCmp    = picCmp + posOffset;   
2050        pelSrc    = picSrc + posOffset;   
2051
2052
2053#if HHI_INTERVIEW_SKIP
2054        if( picUsed)
2055        {
2056          pelUsed   = picUsed+ posOffset;
2057        }
2058        dist  += xCalcSSD( pelSrc, pelCmp,  pelUsed, width, height, stride );
2059#else
2060        dist  += xCalcSSD( pelSrc, pelCmp,  width, height, stride );
2061#endif
2062      }
2063
2064    }
2065    break;
2066  case ALF_Y:
2067    {
2068      for(Int n=0; n< alfLCUInfo.numSGU; n++)
2069      {
2070        ypos    = (Int)(alfLCUInfo[n].posY);
2071        xpos    = (Int)(alfLCUInfo[n].posX);
2072        height  = (Int)(alfLCUInfo[n].height);
2073        width   = (Int)(alfLCUInfo[n].width);
2074
2075#if LCUALF_AVOID_USING_BOTTOM_LINES_ENCODER
2076        if(!notSkipLinesBelowVB)
2077        {
2078          endypos = ypos+ height -1;
2079          Int iLineVBPos = m_lcuHeight - 4;
2080          Int yEndLineInLCU = endypos % m_lcuHeight;
2081          height = (yEndLineInLCU >= iLineVBPos) ? (height - 4) : height ; 
2082        }
2083#endif
2084
2085        posOffset = (ypos * stride) + xpos;
2086        pelCmp    = picCmp + posOffset;   
2087        pelSrc    = picSrc + posOffset;   
2088
2089#if HHI_INTERVIEW_SKIP
2090        if( picUsed )
2091        {
2092          pelUsed   = picUsed+ posOffset;
2093        }
2094        dist  += xCalcSSD( pelSrc, pelCmp,  pelUsed, width, height, stride );
2095#else
2096        dist  += xCalcSSD( pelSrc, pelCmp,  width, height, stride );
2097#endif
2098      }
2099
2100    }
2101    break;
2102  default:
2103    {
2104      printf("not a legal component ID for ALF \n");
2105      assert(0);
2106      exit(-1);
2107    }
2108  }
2109
2110  return dist;
2111}
2112
2113/** Copy one ALF LCU region
2114 * \param [in] alfLCUInfo ALF LCU information
2115 * \param [out] picDst to-be-compared picture buffer
2116 * \param [in] picSrc source picture buffer
2117 * \param [in] stride buffer stride size for 1-D pictrue memory
2118 * \param [in] formatShift 0 for luma and 1 for chroma (4:2:0)
2119 */
2120Void TEncAdaptiveLoopFilter::copyOneAlfLCU(AlfLCUInfo& alfLCUInfo, Pel* picDst, Pel* picSrc, Int stride, Int formatShift)
2121{
2122  Int posOffset, ypos, xpos, height, width;
2123  Pel* pelDst;
2124  Pel* pelSrc;
2125
2126  for(Int n=0; n< alfLCUInfo.numSGU; n++)
2127  {
2128    ypos    = (Int)(alfLCUInfo[n].posY   >> formatShift);
2129    xpos    = (Int)(alfLCUInfo[n].posX   >> formatShift);
2130    height  = (Int)(alfLCUInfo[n].height >> formatShift);
2131    width   = (Int)(alfLCUInfo[n].width  >> formatShift);
2132
2133    posOffset  = ( ypos * stride)+ xpos;
2134    pelDst   = picDst  + posOffset;   
2135    pelSrc   = picSrc  + posOffset;   
2136
2137    for(Int j=0; j< height; j++)
2138    {
2139      ::memcpy(pelDst, pelSrc, sizeof(Pel)*width);
2140      pelDst += stride;
2141      pelSrc += stride;
2142    }
2143  }
2144
2145}
2146
2147/** Reconstruct ALF LCU pixels
2148 * \param [in] compIdx luma/chroma component index
2149 * \param [in] alfLCUInfo ALF LCU information
2150 * \param [in] alfUnitParam ALF unit parameters
2151 * \param [in] picDec picture buffer for un-filtered picture
2152 * \param [out] picRest picture buffer for reconstructed picture
2153 * \param [in] stride buffer stride size for 1-D pictrue memory
2154 * \param [in] formatShift 0 for luma and 1 for chroma (4:2:0)
2155 */
2156Void TEncAdaptiveLoopFilter::reconstructOneAlfLCU(Int compIdx, AlfLCUInfo& alfLCUInfo, AlfUnitParam* alfUnitParam, Pel* picDec, Pel* picRest, Int stride, Int formatShift)
2157{
2158  ALFParam* alfParam = alfUnitParam->alfFiltParam;
2159  Int ypos, xpos, height, width;
2160
2161  if( alfUnitParam->isEnabled)
2162  {
2163    assert(alfParam->alf_flag == 1);
2164
2165    //reconstruct ALF coefficients & related parameters
2166    reconstructCoefInfo(compIdx, alfParam, m_filterCoeffSym, m_varIndTab);
2167
2168    //filtering process
2169    for(Int n=0; n< alfLCUInfo.numSGU; n++)
2170    {
2171      ypos    = (Int)(alfLCUInfo[n].posY   >> formatShift);
2172      xpos    = (Int)(alfLCUInfo[n].posX   >> formatShift);
2173      height  = (Int)(alfLCUInfo[n].height >> formatShift);
2174      width   = (Int)(alfLCUInfo[n].width  >> formatShift);
2175
2176      filterOneCompRegion(picRest, picDec, stride, (compIdx!=ALF_Y), ypos, ypos+height, xpos, xpos+width, m_filterCoeffSym, m_varIndTab, m_varImg);
2177    }
2178  }
2179  else
2180  {
2181    copyOneAlfLCU(alfLCUInfo, picRest, picDec, stride, formatShift);
2182  }
2183}
2184
2185/** LCU-based mode decision
2186 * \param [in, out] alfParamSet ALF parameter set
2187 * \param [in] compIdx luma/chroma component index
2188 * \param [in] pOrg picture buffer for original picture
2189 * \param [in] pDec picture buffer for un-filtered picture
2190 * \param [out] pRest picture buffer for reconstructed picture
2191 * \param [in] stride buffer stride size for 1-D pictrue memory
2192 * \param [in] formatShift 0 for luma and 1 for chroma (4:2:0)
2193 * \param [in] alfCorrLCUs correlations for LCUs
2194 */
2195#if HHI_INTERVIEW_SKIP
2196Void TEncAdaptiveLoopFilter::executeLCUBasedModeDecision(AlfParamSet* alfParamSet
2197                                                        ,Int compIdx, Pel* pOrg, Pel* pDec, Pel* pRest, Pel* pUsed, Int stride, Int formatShift
2198                                                        ,AlfCorrData** alfCorrLCUs
2199                                                        )
2200#else
2201Void TEncAdaptiveLoopFilter::executeLCUBasedModeDecision(AlfParamSet* alfParamSet
2202                                                        ,Int compIdx, Pel* pOrg, Pel* pDec, Pel* pRest, Int stride, Int formatShift
2203                                                        ,AlfCorrData** alfCorrLCUs
2204                                                        )
2205#endif
2206{
2207  Double lambda = (compIdx == ALF_Y)?(m_dLambdaLuma):(m_dLambdaChroma);
2208  static Int* isProcessed = NULL;
2209
2210  AlfUnitParam* alfUnitPic = m_alfPicFiltUnits[compIdx];
2211
2212  Int64  distEnc, distOff;
2213  Int    rateEnc, rateOff;
2214  Double costEnc, costOff;
2215  Bool isLeftUnitAvailable, isUpUnitAvailable;
2216
2217  isProcessed = new Int[m_uiNumCUsInFrame];
2218  ::memset(isProcessed, 0, sizeof(Int)*m_uiNumCUsInFrame);
2219
2220#if LCUALF_FILTER_BUDGET_CONTROL_ENC
2221  Int numProcessedLCU = 0;
2222  m_alfFiltBudgetPerLcu = (Double)(m_iALFMaxNumberFilters) / (Double)(m_uiNumCUsInFrame);
2223  m_alfUsedFilterNum = 0;
2224#endif
2225
2226  for(Int s=0; s<= m_lastSliceIdx; s++)
2227  {
2228    if(!m_pcPic->getValidSlice(s))
2229    {
2230      continue;
2231    }
2232    Bool isAcrossSlice = (m_alfCoefInSlice)?(!m_isNonCrossSlice):(true);
2233    Int  numLCUWidth   = alfParamSet[s].numLCUInWidth;
2234
2235    AlfUnitParam* alfSliceUnitParams = alfParamSet[s].alfUnitParam[compIdx];
2236    std::vector<ALFParam*> storedFilters;
2237    storedFilters.clear(); //reset stored filter buffer at the slice beginning
2238
2239    Int u =0; //counter for LCU index in slice
2240    Int countFiltOffLCU = 0; //counter for number of LCU with filter-off mode
2241    Int countNewFilts = 0; //counter for number of LCU with new filter inside slice
2242
2243    Int numTilesInSlice = (Int)m_pvpSliceTileAlfLCU[s].size();
2244    for(Int t=0; t< numTilesInSlice; t++)
2245    {
2246      std::vector<AlfLCUInfo*> & vpAlfLCU = m_pvpSliceTileAlfLCU[s][t];
2247      Pel* pSrc = pDec;
2248
2249      if(m_bUseNonCrossALF)
2250      {
2251        pSrc = getPicBuf(m_pcSliceYuvTmp, compIdx);
2252        copyRegion(vpAlfLCU, pSrc, pDec, stride, formatShift);
2253        extendRegionBorder(vpAlfLCU, pSrc, stride, formatShift);
2254      }
2255
2256      Int numLCUs = (Int)vpAlfLCU.size();
2257      for(Int n=0; n< numLCUs; n++)
2258      {
2259        AlfLCUInfo*   alfLCU       = vpAlfLCU[n];                  //ALF LCU information
2260        TComDataCU*   pcCU         = alfLCU->pcCU;
2261        Int           addr         = pcCU->getAddr();              //real LCU addr
2262        AlfUnitParam* alfUnitParam = &(alfSliceUnitParams[u]);
2263
2264        if(isProcessed[addr] == 0)
2265        {
2266          Int           maxNumFilter = (Int)NO_VAR_BINS;   
2267
2268#if LCUALF_FILTER_BUDGET_CONTROL_ENC
2269          Bool          isOutOfFilterBudget = true;
2270          Double        usedFiltBudget = (numProcessedLCU == 0) ? 0.0 : (Double)m_alfUsedFilterNum / (Double)(numProcessedLCU);
2271          if ( (m_alfFiltBudgetPerLcu >= usedFiltBudget) && (m_alfUsedFilterNum < m_iALFMaxNumberFilters) )
2272          {
2273            isOutOfFilterBudget = false;
2274            Int leftNumFilt = m_iALFMaxNumberFilters - m_alfUsedFilterNum;
2275            Int avgNumFilt  = leftNumFilt / (m_uiNumCUsInFrame - numProcessedLCU) + 1 ;
2276            maxNumFilter = (leftNumFilt < avgNumFilt) ? leftNumFilt : avgNumFilt ;
2277          }
2278#endif
2279
2280          AlfCorrData*  alfCorr      = alfCorrLCUs[addr];            //ALF LCU correlation
2281          alfUnitParam->alfFiltParam = alfUnitPic[addr].alfFiltParam;
2282
2283          //mode decision
2284          isLeftUnitAvailable = (   (addr % m_numLCUInPicWidth != 0) && (u != 0));
2285          isUpUnitAvailable   = (((Int)(addr/m_numLCUInPicWidth) > 0) && ( ( (u - numLCUWidth) >= 0) || isAcrossSlice ));
2286
2287          decideLCUALFUnitParam(compIdx, alfUnitPic, u, addr, numLCUWidth, alfSliceUnitParams, alfCorr, storedFilters, maxNumFilter, lambda, isLeftUnitAvailable, isUpUnitAvailable);
2288          reconstructOneAlfLCU(compIdx, *alfLCU, alfUnitParam, pSrc, pRest, stride, formatShift);
2289#if HHI_INTERVIEW_SKIP
2290          distEnc = calcAlfLCUDist(!m_picBasedALFEncode, compIdx, *alfLCU, pOrg, pRest, pUsed, stride, formatShift);
2291#else
2292          distEnc = calcAlfLCUDist(!m_picBasedALFEncode, compIdx, *alfLCU, pOrg, pRest, stride, formatShift);
2293#endif
2294          rateEnc = calculateAlfUnitRateRDO(alfUnitParam, (Int)storedFilters.size());
2295          costEnc = (Double)distEnc + lambda*((Double)rateEnc);
2296          costEnc += ((lambda* 1.5)*1.0);  //RDCO
2297
2298          //v.s. filter off case
2299          AlfUnitParam alfUnitParamOff;
2300          getFiltOffAlfUnitParam(&alfUnitParamOff, addr, alfUnitPic, isLeftUnitAvailable, isUpUnitAvailable);
2301#if HHI_INTERVIEW_SKIP
2302          distOff = calcAlfLCUDist(!m_picBasedALFEncode, compIdx, *alfLCU, pOrg, pSrc, pUsed, stride, formatShift);
2303#else
2304          distOff = calcAlfLCUDist(!m_picBasedALFEncode, compIdx, *alfLCU, pOrg, pSrc, stride, formatShift);
2305#endif
2306          rateOff = calculateAlfUnitRateRDO(&alfUnitParamOff, (Int)storedFilters.size());
2307          costOff = (Double)distOff + lambda*((Double)rateOff);
2308
2309#if LCUALF_FILTER_BUDGET_CONTROL_ENC
2310          if( (costOff < costEnc)  ||  isOutOfFilterBudget)
2311#else
2312          if( costOff < costEnc)
2313#endif
2314          {
2315            //filter off. set alf_flag = 0, copy pDest to pRest
2316            *alfUnitParam = alfUnitParamOff;
2317            alfUnitParam->alfFiltParam->alf_flag = 0;
2318            copyOneAlfLCU(*alfLCU, pRest, pSrc, stride, formatShift);
2319          }
2320
2321          if(alfUnitParam->mergeType == ALF_MERGE_DISABLED)
2322          {
2323            if(alfUnitParam->isEnabled)
2324            {
2325              if(alfUnitParam->isNewFilt)
2326              {
2327                //update stored filter buffer
2328                storedFilters.push_back(alfUnitParam->alfFiltParam);
2329                assert(alfUnitParam->alfFiltParam->alf_flag == 1);
2330              }
2331            }
2332          }
2333
2334          alfUnitPic[addr] = *alfUnitParam;
2335
2336          isProcessed[addr] = 1;
2337
2338#if LCUALF_FILTER_BUDGET_CONTROL_ENC
2339          numProcessedLCU++;
2340          if(alfUnitParam->mergeType == ALF_MERGE_DISABLED && alfUnitParam->isEnabled && alfUnitParam->isNewFilt)
2341          {
2342            m_alfUsedFilterNum += alfUnitParam->alfFiltParam->filters_per_group;
2343          }
2344#endif
2345        }
2346        else
2347        {
2348          //keep the ALF parameters in LCU are the same
2349          *alfUnitParam = alfUnitPic[addr];
2350          reconstructOneAlfLCU(compIdx, *alfLCU, alfUnitParam, pSrc, pRest, stride, formatShift);
2351
2352#if LCUALF_FILTER_BUDGET_CONTROL_ENC
2353          if(alfUnitParam->mergeType == ALF_MERGE_DISABLED && alfUnitParam->isEnabled && alfUnitParam->isNewFilt)
2354          {
2355            m_alfUsedFilterNum += alfUnitParam->alfFiltParam->filters_per_group;
2356          }
2357#endif
2358        }
2359
2360        if(alfUnitParam->alfFiltParam->alf_flag == 0)
2361        {
2362          countFiltOffLCU++;
2363        }
2364        else
2365        {
2366          Bool isNewFiltInSlice =   (alfUnitParam->mergeType == ALF_MERGE_DISABLED && alfUnitParam->isEnabled && alfUnitParam->isNewFilt);
2367          Bool isMergeAcrossSlice = ( alfUnitParam->mergeType == ALF_MERGE_UP && (u-numLCUWidth < 0) );
2368
2369          if( isNewFiltInSlice || isMergeAcrossSlice )
2370          {
2371            countNewFilts++;
2372          }
2373        }
2374
2375        u++;     
2376
2377      } //LCU
2378    } //tile
2379
2380
2381    //slice-level parameters
2382    AlfUnitParam* firstAlfUnitInSlice = &(alfSliceUnitParams[0]);
2383    if( countFiltOffLCU == u ) //number of filter-off LCU is equal to the number of LCUs in slice
2384    {
2385      alfParamSet[s].isEnabled [compIdx] = false;   
2386      alfParamSet[s].isUniParam[compIdx] = true; //uni-param, all off
2387      assert(firstAlfUnitInSlice->alfFiltParam->alf_flag == 0);
2388    }
2389    else
2390    {
2391      alfParamSet[s].isEnabled[compIdx] = true;
2392      if( countNewFilts == 1 && firstAlfUnitInSlice->alfFiltParam->alf_flag != 0 && countFiltOffLCU == 0 )
2393      {
2394        alfParamSet[s].isUniParam[compIdx] = true;
2395      }
2396      else
2397      {
2398        alfParamSet[s].isUniParam[compIdx] = false;
2399      }
2400    }
2401  } //slice
2402
2403
2404  delete[] isProcessed;
2405  isProcessed = NULL;
2406}
2407
2408
2409/** Decide ALF parameter set for luma/chroma components (top function)
2410 * \param [in] pPicOrg picture buffer for original picture
2411 * \param [in] pPicDec picture buffer for un-filtered picture
2412 * \param [out] pPicRest picture buffer for reconstructed picture
2413 * \param [in, out] alfParamSet ALF parameter set
2414 * \param [in, out] alfCtrlParam ALF CU-on/off control parameters
2415 */
2416#if HHI_INTERVIEW_SKIP
2417Void TEncAdaptiveLoopFilter::decideParameters(TComPicYuv* pPicOrg, TComPicYuv* pPicDec, TComPicYuv* pPicRest, TComPicYuv* pUsedPelMap
2418                                            , AlfParamSet* alfParamSet
2419                                            , std::vector<AlfCUCtrlInfo>* alfCtrlParam)
2420#else
2421Void TEncAdaptiveLoopFilter::decideParameters(TComPicYuv* pPicOrg, TComPicYuv* pPicDec, TComPicYuv* pPicRest
2422                                            , AlfParamSet* alfParamSet
2423                                            , std::vector<AlfCUCtrlInfo>* alfCtrlParam)
2424#endif
2425{
2426  static Int lumaStride        = pPicOrg->getStride();
2427  static Int chromaStride      = pPicOrg->getCStride();
2428
2429  Pel *pOrg, *pDec, *pRest;
2430  Int stride, formatShift;
2431#if HHI_INTERVIEW_SKIP
2432  Pel *pUsed = NULL ;
2433#endif
2434
2435  for(Int compIdx = 0; compIdx < NUM_ALF_COMPONENT; compIdx++)
2436  {
2437    pOrg        = getPicBuf(pPicOrg, compIdx);
2438    pDec        = getPicBuf(pPicDec, compIdx);
2439    pRest       = getPicBuf(pPicRest, compIdx);
2440#if HHI_INTERVIEW_SKIP
2441    if( pUsedPelMap )
2442    {
2443      pUsed        = getPicBuf(pUsedPelMap, compIdx);
2444    }
2445#endif
2446    stride      = (compIdx == ALF_Y)?(lumaStride):(chromaStride);
2447    formatShift = (compIdx == ALF_Y)?(0):(1);
2448
2449    AlfCorrData** alfCorrComp     = m_alfCorr[compIdx];
2450
2451    if(!m_picBasedALFEncode) //lcu-based optimization
2452    {
2453#if HHI_INTERVIEW_SKIP
2454      executeLCUBasedModeDecision(alfParamSet, compIdx, pOrg, pDec, pRest, pUsed, stride, formatShift, alfCorrComp);
2455#else
2456      executeLCUBasedModeDecision(alfParamSet, compIdx, pOrg, pDec, pRest, stride, formatShift, alfCorrComp);
2457#endif
2458    }
2459    else //picture-based optimization
2460    {
2461      AlfPicQTPart* alfPicQTPart = m_alfPQTPart[compIdx];
2462#if HHI_INTERVIEW_SKIP
2463      executePicBasedModeDecision(alfParamSet, alfPicQTPart, compIdx, pOrg, pDec, pRest, pUsed, stride, formatShift, alfCorrComp);
2464#else
2465      executePicBasedModeDecision(alfParamSet, alfPicQTPart, compIdx, pOrg, pDec, pRest, stride, formatShift, alfCorrComp);
2466#endif
2467    } 
2468
2469  } //component
2470
2471}
2472
2473/** Gather correlations for all LCUs in picture
2474 * \param [in] pPicOrg picture buffer for original picture
2475 * \param [in] pPicDec picture buffer for un-filtered picture
2476 */
2477Void TEncAdaptiveLoopFilter::getStatistics(TComPicYuv* pPicOrg, TComPicYuv* pPicDec)
2478{
2479  Int lumaStride   = pPicOrg->getStride();
2480  Int chromaStride = pPicOrg->getCStride();
2481  const  Int chromaFormatShift = 1;
2482
2483  //calculate BA index
2484  calcOneRegionVar(m_varImg, getPicBuf(pPicDec, ALF_Y), lumaStride, false, 0, m_img_height, 0, m_img_width);
2485  for(Int compIdx = 0; compIdx < NUM_ALF_COMPONENT; compIdx++)
2486  {
2487    AlfCorrData** alfCorrComp = m_alfCorr[compIdx];
2488    Int          formatShift = (compIdx == ALF_Y)?(0):(chromaFormatShift);
2489    Int          stride      = (compIdx == ALF_Y)?(lumaStride):(chromaStride);
2490
2491    getOneCompStatistics(alfCorrComp, compIdx, getPicBuf(pPicOrg, compIdx), getPicBuf(pPicDec, compIdx), stride, formatShift, false);
2492  } 
2493}
2494
2495/** Gather correlations for all LCUs of one luma/chroma component in picture
2496 * \param [out] alfCorrComp correlations for LCUs
2497 * \param [in] compIdx luma/chroma component index
2498 * \param [in] imgOrg picture buffer for original picture
2499 * \param [in] imgDec picture buffer for un-filtered picture
2500 * \param [in] stride buffer stride size for 1-D pictrue memory
2501 * \param [in] formatShift 0 for luma and 1 for chroma (4:2:0)
2502 * \param [in] isRedesignPhase at re-design filter stage (true) or not (false)
2503 */
2504Void TEncAdaptiveLoopFilter::getOneCompStatistics(AlfCorrData** alfCorrComp, Int compIdx, Pel* imgOrg, Pel* imgDec, Int stride, Int formatShift, Bool isRedesignPhase)
2505{
2506
2507  // initialize to zero
2508  for(Int n=0; n< m_uiNumCUsInFrame; n++)
2509  {
2510    alfCorrComp[n]->reset();
2511  }
2512
2513  for(Int s=0; s<= m_lastSliceIdx; s++)
2514  {
2515    if(!m_pcPic->getValidSlice(s))
2516    {
2517      continue;
2518    }
2519    Int numTilesInSlice = (Int)m_pvpSliceTileAlfLCU[s].size();
2520    for(Int t=0; t< numTilesInSlice; t++)
2521    {
2522      std::vector<AlfLCUInfo*> & vpAlfLCU = m_pvpSliceTileAlfLCU[s][t];
2523      Pel* pSrc = imgDec;
2524
2525      if(m_bUseNonCrossALF)
2526      {
2527        pSrc = getPicBuf(m_pcSliceYuvTmp, compIdx);
2528        copyRegion(vpAlfLCU, pSrc, imgDec, stride, formatShift);
2529        extendRegionBorder(vpAlfLCU, pSrc, stride, formatShift);
2530      }
2531
2532      Int numLCUs = (Int)vpAlfLCU.size();
2533      for(Int n=0; n< numLCUs; n++)
2534      {
2535        AlfLCUInfo* alfLCU = vpAlfLCU[n];
2536        Int addr = alfLCU->pcCU->getAddr();
2537        getStatisticsOneLCU(!m_picBasedALFEncode, compIdx, alfLCU, alfCorrComp[addr], imgOrg, pSrc, stride, formatShift, isRedesignPhase);
2538      } //LCU
2539    } //tile
2540  } //slice
2541
2542}
2543
2544/** Gather correlations for one LCU
2545 * \param [out] alfCorrComp correlations for LCUs
2546 * \param [in] compIdx luma/chroma component index
2547 * \param [in] imgOrg picture buffer for original picture
2548 * \param [in] imgDec picture buffer for un-filtered picture
2549 * \param [in] stride buffer stride size for 1-D pictrue memory
2550 * \param [in] formatShift 0 for luma and 1 for chroma (4:2:0)
2551 * \param [in] isRedesignPhase at re-design filter stage (true) or not (false)
2552 */
2553Void TEncAdaptiveLoopFilter::getStatisticsOneLCU(Bool skipLCUBottomLines, Int compIdx, AlfLCUInfo* alfLCU, AlfCorrData* alfCorr, Pel* pPicOrg, Pel* pPicSrc, Int stride, Int formatShift, Bool isRedesignPhase)
2554{
2555  Int numBlocks = alfLCU->numSGU;
2556#if LCUALF_AVOID_USING_BOTTOM_LINES_ENCODER
2557  Int  lcuAddr = alfLCU->pcCU->getAddr();
2558  Bool notSkipLinesBelowVB = true;
2559  Int  endypos;
2560#endif
2561  Bool isLastBlock;
2562  Int ypos, xpos, height, width;
2563
2564#if LCUALF_AVOID_USING_BOTTOM_LINES_ENCODER
2565  if(skipLCUBottomLines)
2566  {
2567    if(lcuAddr + m_numLCUInPicWidth < m_uiNumCUsInFrame)
2568    {
2569      notSkipLinesBelowVB = false;
2570    }
2571  }
2572#endif
2573
2574  switch(compIdx)
2575  {
2576  case ALF_Cb:
2577  case ALF_Cr:
2578    {
2579      for(Int n=0; n< numBlocks; n++)
2580      {
2581        isLastBlock = (n== numBlocks-1);
2582        NDBFBlockInfo& AlfSGU = (*alfLCU)[n];
2583
2584        ypos   = (Int)(AlfSGU.posY  >> formatShift);
2585        xpos   = (Int)(AlfSGU.posX  >> formatShift);
2586        height = (Int)(AlfSGU.height>> formatShift);
2587        width  = (Int)(AlfSGU.width >> formatShift);
2588
2589#if LCUALF_AVOID_USING_BOTTOM_LINES_ENCODER
2590        if(!notSkipLinesBelowVB )
2591        {
2592          endypos = ypos+ height -1;
2593          Int iLineVBPos = m_lcuHeightChroma - 2;
2594          Int yEndLineInLCU = endypos % m_lcuHeightChroma;
2595          height = (yEndLineInLCU >= iLineVBPos) ? (height - 2) : height ; 
2596        }
2597#endif
2598
2599        calcCorrOneCompRegionChma(pPicOrg, pPicSrc, stride, ypos, xpos, height, width, alfCorr->ECorr[0], alfCorr->yCorr[0], isLastBlock);
2600      }
2601    }
2602    break;
2603  case ALF_Y:
2604    {
2605      Bool forceCollection = true;
2606
2607      if(isRedesignPhase)
2608      {
2609        Int numValidPels = 0;
2610        for(Int n=0; n< numBlocks; n++)
2611        {
2612          NDBFBlockInfo& AlfSGU = (*alfLCU)[n];
2613
2614          ypos   = (Int)(AlfSGU.posY  );
2615          xpos   = (Int)(AlfSGU.posX  );
2616          height = (Int)(AlfSGU.height);
2617          width  = (Int)(AlfSGU.width );
2618
2619          for (Int y = ypos; y < ypos+ height; y++)
2620          {
2621            for (Int x = xpos; x < xpos + width; x++)
2622            {
2623              if (m_maskImg[y][x] == 1)
2624              {
2625                numValidPels++;
2626              }
2627            }
2628          }
2629        }
2630
2631        if(numValidPels > 0)
2632        {
2633          forceCollection = false;
2634        }
2635      }
2636
2637      for(Int n=0; n< numBlocks; n++)
2638      {
2639        isLastBlock = (n== numBlocks-1);
2640        NDBFBlockInfo& AlfSGU = (*alfLCU)[n];
2641
2642        ypos   = (Int)(AlfSGU.posY  );
2643        xpos   = (Int)(AlfSGU.posX  );
2644        height = (Int)(AlfSGU.height);
2645        width  = (Int)(AlfSGU.width );
2646
2647#if LCUALF_AVOID_USING_BOTTOM_LINES_ENCODER
2648        endypos = ypos+ height -1;
2649        if(!notSkipLinesBelowVB)
2650        {
2651          Int iLineVBPos = m_lcuHeight - 4;
2652          Int yEndLineInLCU = endypos % m_lcuHeight;
2653          height = (yEndLineInLCU >= iLineVBPos) ? (height - 4) : height ; 
2654        }
2655#endif
2656
2657        calcCorrOneCompRegionLuma(pPicOrg, pPicSrc, stride, ypos, xpos, height, width, alfCorr->ECorr, alfCorr->yCorr, alfCorr->pixAcc, forceCollection, isLastBlock);
2658      }
2659    }
2660    break;
2661  default:
2662    {
2663      printf("Not a legal component index for ALF\n");
2664      assert(0);
2665      exit(-1);
2666    }
2667  }
2668}
2669
2670
2671/** Gather correlations for one region for chroma component
2672 * \param [in] imgOrg picture buffer for original picture
2673 * \param [in] imgPad picture buffer for un-filtered picture
2674 * \param [in] stride buffer stride size for 1-D pictrue memory
2675 * \param [in] yPos region starting y position
2676 * \param [in] xPos region starting x position
2677 * \param [in] height region height
2678 * \param [in] width region width
2679 * \param [out] eCorr auto-correlation matrix
2680 * \param [out] yCorr cross-correlation array
2681 * \param [in] isSymmCopyBlockMatrix symmetrically copy correlation values in eCorr (true) or not (false)
2682 */
2683Void TEncAdaptiveLoopFilter::calcCorrOneCompRegionChma(Pel* imgOrg, Pel* imgPad, Int stride
2684                                                     , Int yPos, Int xPos, Int height, Int width
2685                                                     , Double **eCorr, Double *yCorr, Bool isSymmCopyBlockMatrix
2686                                                      )
2687{
2688  Int yPosEnd = yPos + height;
2689  Int xPosEnd = xPos + width;
2690  Int N = ALF_MAX_NUM_COEF; //m_sqrFiltLengthTab[0];
2691
2692  Int imgHeightChroma = m_img_height>>1;
2693
2694  Int yLineInLCU, paddingLine;
2695  Int ELocal[ALF_MAX_NUM_COEF];
2696  Pel *imgPad1, *imgPad2, *imgPad3, *imgPad4, *imgPad5, *imgPad6;
2697  Int i, j, k, l, yLocal;
2698
2699  imgPad += (yPos*stride);
2700  imgOrg += (yPos*stride);
2701
2702  for (i= yPos; i< yPosEnd; i++)
2703  {
2704    yLineInLCU = i % m_lcuHeightChroma;
2705
2706    if (yLineInLCU==0 && i>0)
2707    {
2708      paddingLine = yLineInLCU + 2 ;
2709      imgPad1 = imgPad + stride;
2710      imgPad2 = imgPad - stride;
2711      imgPad3 = imgPad + 2*stride;
2712      imgPad4 = imgPad - 2*stride;
2713      imgPad5 = (paddingLine < 3) ? imgPad : imgPad + 3*stride;
2714      imgPad6 = (paddingLine < 3) ? imgPad : imgPad - min(paddingLine, 3)*stride;;
2715    }
2716    else if (yLineInLCU < m_lineIdxPadBotChroma || i-yLineInLCU+m_lcuHeightChroma >= imgHeightChroma )
2717    {
2718      imgPad1 = imgPad + stride;
2719      imgPad2 = imgPad - stride;
2720      imgPad3 = imgPad + 2*stride;
2721      imgPad4 = imgPad - 2*stride;
2722      imgPad5 = imgPad + 3*stride;
2723      imgPad6 = imgPad - 3*stride;
2724    }
2725    else if (yLineInLCU < m_lineIdxPadTopChroma)
2726    {
2727      paddingLine = - yLineInLCU + m_lineIdxPadTopChroma - 1;
2728      imgPad1 = (paddingLine < 1) ? imgPad : imgPad + min(paddingLine, 1)*stride;
2729      imgPad2 = (paddingLine < 1) ? imgPad : imgPad - stride;
2730      imgPad3 = (paddingLine < 2) ? imgPad : imgPad + min(paddingLine, 2)*stride;
2731      imgPad4 = (paddingLine < 2) ? imgPad : imgPad - 2*stride;
2732      imgPad5 = (paddingLine < 3) ? imgPad : imgPad + min(paddingLine, 3)*stride;
2733      imgPad6 = (paddingLine < 3) ? imgPad : imgPad - 3*stride;
2734    }
2735    else
2736    {
2737      paddingLine = yLineInLCU - m_lineIdxPadTopChroma ;
2738      imgPad1 = (paddingLine < 1) ? imgPad : imgPad + stride;
2739      imgPad2 = (paddingLine < 1) ? imgPad : imgPad - min(paddingLine, 1)*stride;
2740      imgPad3 = (paddingLine < 2) ? imgPad : imgPad + 2*stride;
2741      imgPad4 = (paddingLine < 2) ? imgPad : imgPad - min(paddingLine, 2)*stride;
2742      imgPad5 = (paddingLine < 3) ? imgPad : imgPad + 3*stride;
2743      imgPad6 = (paddingLine < 3) ? imgPad : imgPad - min(paddingLine, 3)*stride;
2744    }
2745
2746    for (j= xPos; j< xPosEnd; j++)
2747    {
2748      memset(ELocal, 0, N*sizeof(Int));
2749
2750      ELocal[0] = (imgPad5[j] + imgPad6[j]);
2751
2752      ELocal[1] = (imgPad3[j] + imgPad4[j]);
2753
2754      ELocal[2] = (imgPad1[j-1] + imgPad2[j+1]);
2755      ELocal[3] = (imgPad1[] + imgPad2[]);
2756      ELocal[4] = (imgPad1[j+1] + imgPad2[j-1]);
2757
2758      ELocal[5] = (imgPad[j+4] + imgPad[j-4]);
2759      ELocal[6] = (imgPad[j+3] + imgPad[j-3]);
2760      ELocal[7] = (imgPad[j+2] + imgPad[j-2]);
2761      ELocal[8] = (imgPad[j+1] + imgPad[j-1]);
2762      ELocal[9] = (imgPad[]);
2763
2764      yLocal= (Int)imgOrg[j];
2765
2766      for(k=0; k<N; k++)
2767      {
2768        eCorr[k][k] += ELocal[k]*ELocal[k];
2769        for(l=k+1; l<N; l++)
2770        {
2771          eCorr[k][l] += ELocal[k]*ELocal[l];
2772        }
2773
2774        yCorr[k] += yLocal*ELocal[k];
2775      }
2776    }
2777
2778    imgPad+= stride;
2779    imgOrg+= stride;
2780  }
2781
2782  if(isSymmCopyBlockMatrix)
2783  {
2784    for(j=0; j<N-1; j++)
2785    {
2786      for(i=j+1; i<N; i++)
2787      {
2788        eCorr[i][j] = eCorr[j][i];
2789      }
2790    }
2791  }
2792}
2793
2794/** Gather correlations for one region for luma component
2795 * \param [in] imgOrg picture buffer for original picture
2796 * \param [in] imgPad picture buffer for un-filtered picture
2797 * \param [in] stride buffer stride size for 1-D pictrue memory
2798 * \param [in] yPos region starting y position
2799 * \param [in] xPos region starting x position
2800 * \param [in] height region height
2801 * \param [in] width region width
2802 * \param [out] eCorr auto-correlation matrix
2803 * \param [out] yCorr cross-correlation array
2804 * \param [out] pixAcc pixel squared value
2805 * \param [in] isforceCollection all pixel are used for correlation calculation (true) or not (false)
2806 * \param [in] isSymmCopyBlockMatrix symmetrically copy correlation values in eCorr (true) or not (false)
2807 */
2808Void TEncAdaptiveLoopFilter::calcCorrOneCompRegionLuma(Pel* imgOrg, Pel* imgPad, Int stride
2809                                                      ,Int yPos, Int xPos, Int height, Int width
2810                                                      ,Double ***eCorr, Double **yCorr, Double *pixAcc
2811                                                      ,Bool isforceCollection, Bool isSymmCopyBlockMatrix
2812                                                      )
2813{
2814  Int yPosEnd = yPos + height;
2815  Int xPosEnd = xPos + width;
2816  Int yLineInLCU;
2817  Int paddingLine ;
2818  Int N = ALF_MAX_NUM_COEF; //m_sqrFiltLengthTab[0];
2819
2820  Int ELocal[ALF_MAX_NUM_COEF];
2821  Pel *imgPad1, *imgPad2, *imgPad3, *imgPad4, *imgPad5, *imgPad6;
2822  Int i, j, k, l, yLocal, varInd;
2823  Double **E;
2824  Double *yy;
2825
2826  imgPad += (yPos*stride);
2827  imgOrg += (yPos*stride);
2828
2829  for (i= yPos; i< yPosEnd; i++)
2830  {
2831    yLineInLCU = i % m_lcuHeight;
2832
2833    if (yLineInLCU<m_lineIdxPadBot || i-yLineInLCU+m_lcuHeight >= m_img_height)
2834    {
2835      imgPad1 = imgPad + stride;
2836      imgPad2 = imgPad - stride;
2837      imgPad3 = imgPad + 2*stride;
2838      imgPad4 = imgPad - 2*stride;
2839      imgPad5 = imgPad + 3*stride;
2840      imgPad6 = imgPad - 3*stride;
2841    }
2842    else if (yLineInLCU<m_lineIdxPadTop)
2843    {
2844      paddingLine = - yLineInLCU + m_lineIdxPadTop - 1;
2845      imgPad1 = (paddingLine < 1) ? imgPad : imgPad + min(paddingLine, 1)*stride;
2846      imgPad2 = (paddingLine < 1) ? imgPad : imgPad - stride;
2847      imgPad3 = (paddingLine < 2) ? imgPad : imgPad + min(paddingLine, 2)*stride;
2848      imgPad4 = (paddingLine < 2) ? imgPad : imgPad - 2*stride;
2849      imgPad5 = (paddingLine < 3) ? imgPad : imgPad + min(paddingLine, 3)*stride;
2850      imgPad6 = (paddingLine < 3) ? imgPad : imgPad - 3*stride;
2851    }
2852    else
2853    {
2854      paddingLine = yLineInLCU - m_lineIdxPadTop;
2855      imgPad1 = (paddingLine < 1) ? imgPad : imgPad + stride;
2856      imgPad2 = (paddingLine < 1) ? imgPad : imgPad - min(paddingLine, 1)*stride;
2857      imgPad3 = (paddingLine < 2) ? imgPad : imgPad + 2*stride;
2858      imgPad4 = (paddingLine < 2) ? imgPad : imgPad - min(paddingLine, 2)*stride;
2859      imgPad5 = (paddingLine < 3) ? imgPad : imgPad + 3*stride;
2860      imgPad6 = (paddingLine < 3) ? imgPad : imgPad - min(paddingLine, 3)*stride;
2861    }         
2862
2863    for (j= xPos; j< xPosEnd; j++)
2864    {
2865      if ( m_maskImg[i][j] || isforceCollection )
2866      {
2867        varInd = m_varImg[i/VAR_SIZE_H][j/VAR_SIZE_W];
2868        memset(ELocal, 0, N*sizeof(Int));
2869
2870        ELocal[0] = (imgPad5[j] + imgPad6[j]);
2871        ELocal[1] = (imgPad3[j] + imgPad4[j]);
2872
2873        ELocal[2] = (imgPad1[j-1] + imgPad2[j+1]);
2874        ELocal[3] = (imgPad1[] + imgPad2[]);
2875        ELocal[4] = (imgPad1[j+1] + imgPad2[j-1]);
2876
2877        ELocal[5] = (imgPad[j+4] + imgPad[j-4]);
2878        ELocal[6] = (imgPad[j+3] + imgPad[j-3]);
2879        ELocal[7] = (imgPad[j+2] + imgPad[j-2]);
2880        ELocal[8] = (imgPad[j+1] + imgPad[j-1]);
2881        ELocal[9] = (imgPad[]);
2882
2883        yLocal= imgOrg[j];
2884        pixAcc[varInd] += (yLocal*yLocal);
2885        E  = eCorr[varInd];
2886        yy = yCorr[varInd];
2887
2888        for (k=0; k<N; k++)
2889        {
2890          for (l=k; l<N; l++)
2891          {
2892            E[k][l]+=(double)(ELocal[k]*ELocal[l]);
2893          }
2894          yy[k]+=(double)(ELocal[k]*yLocal);
2895        }
2896      }
2897    }
2898    imgPad += stride;
2899    imgOrg += stride;
2900  }
2901
2902  if(isSymmCopyBlockMatrix)
2903  {
2904    for (varInd=0; varInd<NO_VAR_BINS; varInd++)
2905    {
2906      E = eCorr[varInd];
2907      for (k=1; k<N; k++)
2908      {
2909        for (l=0; l<k; l++)
2910        {
2911          E[k][l] = E[l][k];
2912        }
2913      }
2914    }
2915  }
2916
2917}
2918
2919
2920/** PCM LF disable process.
2921 * \param pcPic picture (TComPic) pointer
2922 * \returns Void
2923 *
2924 * \note Replace filtered sample values of PCM mode blocks with the transmitted and reconstructed ones.
2925 */
2926Void TEncAdaptiveLoopFilter::PCMLFDisableProcess (TComPic* pcPic)
2927{
2928  xPCMRestoration(pcPic);
2929}
2930
2931// ====================================================================================================================
2932// Protected member functions
2933// ====================================================================================================================
2934
2935// ====================================================================================================================
2936// Private member functions
2937// ====================================================================================================================
2938Void TEncAdaptiveLoopFilter::xCreateTmpAlfCtrlFlags()
2939{
2940  for( UInt uiCUAddr = 0; uiCUAddr < m_pcPic->getNumCUsInFrame() ; uiCUAddr++ )
2941  {
2942    TComDataCU* pcCU = m_pcPic->getCU( uiCUAddr );
2943    pcCU->createTmpAlfCtrlFlag();
2944  }
2945}
2946
2947Void TEncAdaptiveLoopFilter::xDestroyTmpAlfCtrlFlags()
2948{
2949  for( UInt uiCUAddr = 0; uiCUAddr < m_pcPic->getNumCUsInFrame() ; uiCUAddr++ )
2950  {
2951    TComDataCU* pcCU = m_pcPic->getCU( uiCUAddr );
2952    pcCU->destroyTmpAlfCtrlFlag();
2953  }
2954}
2955
2956Void TEncAdaptiveLoopFilter::xCopyTmpAlfCtrlFlagsTo()
2957{
2958  for( UInt uiCUAddr = 0; uiCUAddr < m_pcPic->getNumCUsInFrame() ; uiCUAddr++ )
2959  {
2960    TComDataCU* pcCU = m_pcPic->getCU( uiCUAddr );
2961    pcCU->copyAlfCtrlFlagFromTmp();
2962  }
2963}
2964
2965Void TEncAdaptiveLoopFilter::xCopyTmpAlfCtrlFlagsFrom()
2966{
2967  for( UInt uiCUAddr = 0; uiCUAddr < m_pcPic->getNumCUsInFrame() ; uiCUAddr++ )
2968  {
2969    TComDataCU* pcCU = m_pcPic->getCU( uiCUAddr );
2970    pcCU->copyAlfCtrlFlagToTmp();
2971  }
2972}
2973
2974/** Encode ALF CU control flags
2975 */
2976Void TEncAdaptiveLoopFilter::xEncodeCUAlfCtrlFlags(std::vector<AlfCUCtrlInfo> &vAlfCUCtrlParam)
2977{
2978  for(Int s=0; s< m_uiNumSlicesInPic; s++)
2979  {
2980    if(!m_pcPic->getValidSlice(s))
2981    {
2982      continue;
2983    }
2984
2985    AlfCUCtrlInfo& rCUCtrlInfo = vAlfCUCtrlParam[s];
2986    if(rCUCtrlInfo.cu_control_flag == 1)
2987    {
2988      for(Int i=0; i< (Int)rCUCtrlInfo.alf_cu_flag.size(); i++)
2989      {
2990        m_pcEntropyCoder->encodeAlfCtrlFlag(rCUCtrlInfo.alf_cu_flag[i]);
2991      }
2992    }
2993  }
2994}
2995Void TEncAdaptiveLoopFilter::xEncodeCUAlfCtrlFlag(TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth)
2996{
2997  Bool bBoundary = false;
2998  UInt uiLPelX   = pcCU->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiAbsPartIdx] ];
2999  UInt uiRPelX   = uiLPelX + (g_uiMaxCUWidth>>uiDepth)  - 1;
3000  UInt uiTPelY   = pcCU->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiAbsPartIdx] ];
3001  UInt uiBPelY   = uiTPelY + (g_uiMaxCUHeight>>uiDepth) - 1;
3002 
3003#if AD_HOCS_SLICES 
3004  if( ( uiRPelX >= pcCU->getSlice()->getSPS()->getPicWidthInLumaSamples() ) || ( uiBPelY >= pcCU->getSlice()->getSPS()->getPicHeightInLumaSamples() ) )
3005#else 
3006  if( ( uiRPelX >= pcCU->getSlice()->getSPS()->getPicWidthInLumaSamples() ) || ( uiBPelY >= pcCU->getSlice()->getSPS()->getPicHeightInLumaSamples() ) )
3007#endif 
3008  {
3009    bBoundary = true;
3010  }
3011 
3012  if( ( ( uiDepth < pcCU->getDepth( uiAbsPartIdx ) ) && ( uiDepth < (g_uiMaxCUDepth-g_uiAddCUDepth) ) ) || bBoundary )
3013  {
3014    UInt uiQNumParts = ( m_pcPic->getNumPartInCU() >> (uiDepth<<1) )>>2;
3015    for ( UInt uiPartUnitIdx = 0; uiPartUnitIdx < 4; uiPartUnitIdx++, uiAbsPartIdx+=uiQNumParts )
3016    {
3017      uiLPelX   = pcCU->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiAbsPartIdx] ];
3018      uiTPelY   = pcCU->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiAbsPartIdx] ];
3019     
3020#if AD_HOCS_SLICES     
3021      if( ( uiLPelX < pcCU->getSlice()->getSPS()->getPicWidthInLumaSamples() ) && ( uiTPelY < pcCU->getSlice()->getSPS()->getPicHeightInLumaSamples() ) )
3022#else
3023      if( ( uiLPelX < pcCU->getSlice()->getSPS()->getPicWidthInLumaSamples() ) && ( uiTPelY < pcCU->getSlice()->getSPS()->getPicHeightInLumaSamples() ) )
3024#endif     
3025        xEncodeCUAlfCtrlFlag(pcCU, uiAbsPartIdx, uiDepth+1);
3026    }
3027    return;
3028  }
3029 
3030  m_pcEntropyCoder->encodeAlfCtrlFlag(pcCU, uiAbsPartIdx);
3031}
3032
3033#if IBDI_DISTORTION
3034#if HHI_INTERVIEW_SKIP
3035UInt64 TEncAdaptiveLoopFilter::xCalcSSD(Pel* pOrg, Pel* pCmp, Pel* pUsed, Int iWidth, Int iHeight, Int iStride )
3036{
3037  UInt64 uiSSD = 0;
3038  Int x, y;
3039
3040  Int iShift = g_uiBitIncrement;
3041  Int iOffset = (g_uiBitIncrement>0)? (1<<(g_uiBitIncrement-1)):0;
3042  Int iTemp;
3043
3044  for( y = 0; y < iHeight; y++ )
3045  {
3046    for( x = 0; x < iWidth; x++ )
3047    {
3048      if ( pUsed ) // interview skipped
3049      {
3050        if( pUsed[x] )
3051        {
3052      iTemp = ((pOrg[x]+iOffset)>>iShift) - ((pCmp[x]+iOffset)>>iShift); uiSSD += iTemp * iTemp;
3053        }
3054      }
3055      else         // no interview skip
3056      {
3057          iTemp = ((pOrg[x]+iOffset)>>iShift) - ((pCmp[x]+iOffset)>>iShift); uiSSD += iTemp * iTemp;
3058      }
3059    }
3060    pOrg += iStride;
3061    pCmp += iStride;
3062    if(pUsed)
3063    {
3064      pUsed+= iStride;
3065    }
3066  }
3067
3068  return uiSSD;;
3069}
3070#else
3071UInt64 TEncAdaptiveLoopFilter::xCalcSSD(Pel* pOrg, Pel* pCmp, Int iWidth, Int iHeight, Int iStride )
3072{
3073  UInt64 uiSSD = 0;
3074  Int x, y;
3075 
3076  Int iShift = g_uiBitIncrement;
3077  Int iOffset = (g_uiBitIncrement>0)? (1<<(g_uiBitIncrement-1)):0;
3078  Int iTemp;
3079
3080  for( y = 0; y < iHeight; y++ )
3081  {
3082    for( x = 0; x < iWidth; x++ )
3083    {
3084      iTemp = ((pOrg[x]+iOffset)>>iShift) - ((pCmp[x]+iOffset)>>iShift); uiSSD += iTemp * iTemp;
3085    }
3086    pOrg += iStride;
3087    pCmp += iStride;
3088  }
3089
3090  return uiSSD;;
3091}
3092#endif
3093#else
3094#if HHI_INTERVIEW_SKIP
3095UInt64 TEncAdaptiveLoopFilter::xCalcSSD(Pel* pOrg, Pel* pCmp, Pel* pUsed, Int iWidth, Int iHeight, Int iStride )
3096{
3097  UInt64 uiSSD = 0;
3098  Int x, y;
3099
3100  UInt uiShift = g_uiBitIncrement<<1;
3101  Int iTemp =0 ;
3102
3103  for( y = 0; y < iHeight; y++ )
3104  {
3105    for( x = 0; x < iWidth; x++ )
3106    {
3107      if ( pUsed ) // interview skipped
3108      {
3109        if( pUsed[x] )
3110        {
3111          iTemp = pOrg[x] - pCmp[x]; uiSSD += ( iTemp * iTemp ) >> uiShift;
3112        }
3113      }
3114      else         // no interview skip
3115      {
3116          iTemp = pOrg[x] - pCmp[x]; uiSSD += ( iTemp * iTemp ) >> uiShift;
3117      }
3118    }
3119    pOrg += iStride;
3120    pCmp += iStride;
3121    if(pUsed)
3122    {
3123      pUsed+= iStride;
3124    }
3125  }
3126
3127  return uiSSD;;
3128}
3129#else
3130UInt64 TEncAdaptiveLoopFilter::xCalcSSD(Pel* pOrg, Pel* pCmp, Int iWidth, Int iHeight, Int iStride )
3131{
3132  UInt64 uiSSD = 0;
3133  Int x, y;
3134  UInt uiShift = g_uiBitIncrement<<1;
3135  Int iTemp;
3136 
3137  for( y = 0; y < iHeight; y++ )
3138  {
3139    for( x = 0; x < iWidth; x++ )
3140    {
3141      iTemp = pOrg[x] - pCmp[x]; uiSSD += ( iTemp * iTemp ) >> uiShift;
3142    }
3143    pOrg += iStride;
3144    pCmp += iStride;
3145  }
3146 
3147  return uiSSD;;
3148}
3149#endif
3150#endif
3151
3152Int TEncAdaptiveLoopFilter::xGauss(Double **a, Int N)
3153{
3154  Int i, j, k;
3155  Double t;
3156 
3157  for(k=0; k<N; k++)
3158  {
3159    if (a[k][k] <0.000001)
3160    {
3161      return 1;
3162    }
3163  }
3164 
3165  for(k=0; k<N-1; k++)
3166  {
3167    for(i=k+1;i<N; i++)
3168    {
3169      t=a[i][k]/a[k][k];
3170      for(j=k+1; j<=N; j++)
3171      {
3172        a[i][j] -= t * a[k][j];
3173        if(i==j && fabs(a[i][j])<0.000001) return 1;
3174      }
3175    }
3176  }
3177  for(i=N-1; i>=0; i--)
3178  {
3179    t = a[i][N];
3180    for(j=i+1; j<N; j++)
3181    {
3182      t -= a[i][j] * a[j][N];
3183    }
3184    a[i][N] = t / a[i][i];
3185  }
3186  return 0;
3187}
3188
3189Void TEncAdaptiveLoopFilter::xFilterCoefQuickSort( Double *coef_data, Int *coef_num, Int upper, Int lower )
3190{
3191  Double mid, tmp_data;
3192  Int i, j, tmp_num;
3193 
3194  i = upper;
3195  j = lower;
3196  mid = coef_data[(lower+upper)>>1];
3197  do
3198  {
3199    while( coef_data[i] < mid ) i++;
3200    while( mid < coef_data[j] ) j--;
3201    if( i <= j )
3202    {
3203      tmp_data = coef_data[i];
3204      tmp_num  = coef_num[i];
3205      coef_data[i] = coef_data[j];
3206      coef_num[i]  = coef_num[j];
3207      coef_data[j] = tmp_data;
3208      coef_num[j]  = tmp_num;
3209      i++;
3210      j--;
3211    }
3212  } while( i <= j );
3213  if ( upper < j ) 
3214  {
3215    xFilterCoefQuickSort(coef_data, coef_num, upper, j);
3216  }
3217  if ( i < lower ) 
3218  {
3219    xFilterCoefQuickSort(coef_data, coef_num, i, lower);
3220  }
3221}
3222
3223Void TEncAdaptiveLoopFilter::xQuantFilterCoef(Double* h, Int* qh, Int tap, int bit_depth)
3224{
3225  Int i, N;
3226  Int max_value, min_value;
3227  Double dbl_total_gain;
3228  Int total_gain, q_total_gain;
3229  Int upper, lower;
3230  Double *dh;
3231  Int    *nc;
3232  const Int    *pFiltMag;
3233#if LCUALF_QP_DEPENDENT_BITS
3234  Int alfPrecisionBit = getAlfPrecisionBit( m_alfQP );
3235#endif
3236
3237  N = m_sqrFiltLengthTab[tap];
3238  pFiltMag = weightsShape1Sym;
3239
3240  dh = new Double[N];
3241  nc = new Int[N];
3242 
3243#if LCUALF_QP_DEPENDENT_BITS 
3244  max_value =   (1<<(1+alfPrecisionBit))-1;
3245  min_value = 0-(1<<(1+alfPrecisionBit));
3246#else
3247  max_value =   (1<<(1+ALF_NUM_BIT_SHIFT))-1;
3248  min_value = 0-(1<<(1+ALF_NUM_BIT_SHIFT));
3249#endif
3250
3251  dbl_total_gain=0.0;
3252  q_total_gain=0;
3253  for(i=0; i<N; i++)
3254  {
3255    if(h[i]>=0.0)
3256    {
3257#if LCUALF_QP_DEPENDENT_BITS
3258      qh[i] =  (Int)( h[i]*(1<<alfPrecisionBit)+0.5);
3259#else
3260      qh[i] =  (Int)( h[i]*(1<<ALF_NUM_BIT_SHIFT)+0.5);
3261#endif
3262    }
3263    else
3264    {
3265#if LCUALF_QP_DEPENDENT_BITS
3266      qh[i] = -(Int)(-h[i]*(1<<alfPrecisionBit)+0.5);
3267#else
3268      qh[i] = -(Int)(-h[i]*(1<<ALF_NUM_BIT_SHIFT)+0.5);
3269#endif
3270    }
3271
3272#if LCUALF_QP_DEPENDENT_BITS
3273    dh[i] = (Double)qh[i]/(Double)(1<<alfPrecisionBit) - h[i];
3274#else
3275    dh[i] = (Double)qh[i]/(Double)(1<<ALF_NUM_BIT_SHIFT) - h[i];
3276#endif
3277    dh[i]*=pFiltMag[i];
3278    dbl_total_gain += h[i]*pFiltMag[i];
3279    q_total_gain   += qh[i]*pFiltMag[i];
3280    nc[i] = i;
3281  }
3282 
3283  // modification of quantized filter coefficients
3284#if LCUALF_QP_DEPENDENT_BITS
3285  total_gain = (Int)(dbl_total_gain*(1<<alfPrecisionBit)+0.5);
3286#else
3287  total_gain = (Int)(dbl_total_gain*(1<<ALF_NUM_BIT_SHIFT)+0.5);
3288#endif 
3289  if( q_total_gain != total_gain )
3290  {
3291    xFilterCoefQuickSort(dh, nc, 0, N-1);
3292    if( q_total_gain > total_gain )
3293    {
3294      upper = N-1;
3295      while( q_total_gain > total_gain+1 )
3296      {
3297        i = nc[upper%N];
3298        qh[i]--;
3299        q_total_gain -= pFiltMag[i];
3300        upper--;
3301      }
3302      if( q_total_gain == total_gain+1 )
3303      {
3304        if(dh[N-1]>0)
3305        {
3306          qh[N-1]--;
3307        }
3308        else
3309        {
3310          i=nc[upper%N];
3311          qh[i]--;
3312          qh[N-1]++;
3313        }
3314      }
3315    }
3316    else if( q_total_gain < total_gain )
3317    {
3318      lower = 0;
3319      while( q_total_gain < total_gain-1 )
3320      {
3321        i=nc[lower%N];
3322        qh[i]++;
3323        q_total_gain += pFiltMag[i];
3324        lower++;
3325      }
3326      if( q_total_gain == total_gain-1 )
3327      {
3328        if(dh[N-1]<0)
3329        {
3330          qh[N-1]++;
3331        }
3332        else
3333        {
3334          i=nc[lower%N];
3335          qh[i]++;
3336          qh[N-1]--;
3337        }
3338      }
3339    }
3340  }
3341 
3342  // set of filter coefficients
3343  for(i=0; i<N; i++)
3344  {
3345    qh[i] = max(min_value,min(max_value, qh[i]));
3346  }
3347
3348  checkFilterCoeffValue(qh, N, true);
3349
3350  delete[] dh;
3351  dh = NULL;
3352 
3353  delete[] nc;
3354  nc = NULL;
3355}
3356/** Restore the not-filtered pixels
3357 * \param [in] imgDec picture buffer before filtering
3358 * \param [out] imgRest picture buffer after filtering
3359 * \param [in] stride stride size for 1-D picture memory
3360 */
3361Void TEncAdaptiveLoopFilter::xCopyDecToRestCUs(Pel* imgDec, Pel* imgRest, Int stride)
3362{
3363
3364  if(m_uiNumSlicesInPic > 1)
3365  {
3366    Pel* pPicDecLuma  = imgDec;
3367    Pel* pPicRestLuma = imgRest;
3368    UInt SUWidth      = m_pcPic->getMinCUWidth();
3369    UInt SUHeight     = m_pcPic->getMinCUHeight();
3370
3371    UInt startSU, endSU, LCUX, LCUY, currSU, LPelX, TPelY;
3372    UInt posOffset;
3373    Pel *pDec, *pRest;
3374
3375    for(Int s=0; s< m_uiNumSlicesInPic; s++)
3376    {
3377      if(!m_pcPic->getValidSlice(s))
3378      {
3379        continue;
3380      }
3381      std::vector< AlfLCUInfo* >&  vpSliceAlfLCU = m_pvpAlfLCU[s]; 
3382      for(Int i=0; i< vpSliceAlfLCU.size(); i++)
3383      {
3384        AlfLCUInfo& rAlfLCU    = *(vpSliceAlfLCU[i]);
3385        TComDataCU* pcCU       = rAlfLCU.pcCU;
3386        startSU                = rAlfLCU.startSU;
3387        endSU                  = rAlfLCU.endSU;
3388        LCUX                 = pcCU->getCUPelX();
3389        LCUY                 = pcCU->getCUPelY();
3390
3391        for(currSU= startSU; currSU<= endSU; currSU++)
3392        {
3393          LPelX   = LCUX + g_auiRasterToPelX[ g_auiZscanToRaster[currSU] ];
3394          TPelY   = LCUY + g_auiRasterToPelY[ g_auiZscanToRaster[currSU] ];
3395          if( !( LPelX < m_img_width )  || !( TPelY < m_img_height )  )
3396          {
3397            continue;
3398          }
3399          if(!pcCU->getAlfCtrlFlag(currSU))
3400          {
3401            posOffset = TPelY*stride + LPelX;
3402            pDec = pPicDecLuma + posOffset;
3403            pRest= pPicRestLuma+ posOffset;
3404            for(Int y=0; y< SUHeight; y++)
3405            {
3406              ::memcpy(pRest, pDec, sizeof(Pel)*SUWidth);
3407              pDec += stride;
3408              pRest+= stride;
3409            }
3410          }
3411        }
3412      }
3413    }
3414    return;
3415  }
3416
3417  for( UInt uiCUAddr = 0; uiCUAddr < m_pcPic->getNumCUsInFrame() ; uiCUAddr++ )
3418  {
3419    TComDataCU* pcCU = m_pcPic->getCU( uiCUAddr );
3420    xCopyDecToRestCU(pcCU, 0, 0, imgDec, imgRest, stride);
3421  }
3422}
3423
3424Void TEncAdaptiveLoopFilter::xCopyDecToRestCU(TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth, Pel* imgDec, Pel* imgRest, Int stride)
3425{
3426  Bool bBoundary = false;
3427  UInt uiLPelX   = pcCU->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiAbsPartIdx] ];
3428  UInt uiRPelX   = uiLPelX + (g_uiMaxCUWidth>>uiDepth)  - 1;
3429  UInt uiTPelY   = pcCU->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiAbsPartIdx] ];
3430  UInt uiBPelY   = uiTPelY + (g_uiMaxCUHeight>>uiDepth) - 1;
3431 
3432  if( ( uiRPelX >= pcCU->getSlice()->getSPS()->getPicWidthInLumaSamples() ) || ( uiBPelY >= pcCU->getSlice()->getSPS()->getPicHeightInLumaSamples() ) )
3433  {
3434    bBoundary = true;
3435  }
3436 
3437  if( ( ( uiDepth < pcCU->getDepth( uiAbsPartIdx ) ) && ( uiDepth < (g_uiMaxCUDepth-g_uiAddCUDepth) ) ) || bBoundary )
3438  {
3439    UInt uiQNumParts = ( m_pcPic->getNumPartInCU() >> (uiDepth<<1) )>>2;
3440    for ( UInt uiPartUnitIdx = 0; uiPartUnitIdx < 4; uiPartUnitIdx++, uiAbsPartIdx+=uiQNumParts )
3441    {
3442      uiLPelX   = pcCU->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiAbsPartIdx] ];
3443      uiTPelY   = pcCU->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiAbsPartIdx] ];
3444     
3445      if( ( uiLPelX < pcCU->getSlice()->getSPS()->getPicWidthInLumaSamples() ) && ( uiTPelY < pcCU->getSlice()->getSPS()->getPicHeightInLumaSamples() ) )     
3446        xCopyDecToRestCU(pcCU, uiAbsPartIdx, uiDepth+1, imgDec, imgRest, stride);
3447    }
3448    return;
3449  }
3450 
3451  if (!pcCU->getAlfCtrlFlag(uiAbsPartIdx))
3452  {
3453    Int iWidth = pcCU->getWidth(uiAbsPartIdx);
3454    Int iHeight = pcCU->getHeight(uiAbsPartIdx);
3455    copyPixelsInOneRegion(imgRest, imgDec, stride, (Int)uiTPelY, iHeight, (Int)uiLPelX, iWidth);
3456  }
3457}
3458
3459double TEncAdaptiveLoopFilter::xfindBestCoeffCodMethod(int **filterCoeffSymQuant, int filter_shape, int sqrFiltLength, int filters_per_fr, double errorForce0CoeffTab[NO_VAR_BINS][2], 
3460  double lambda)
3461{
3462  Int coeffBits, i;
3463  Double error=0, lagrangian;
3464  coeffBits = xsendAllFiltersPPPred(filterCoeffSymQuant, filter_shape, sqrFiltLength, filters_per_fr, 
3465    0, m_tempALFp);
3466  for(i=0;i<filters_per_fr;i++)
3467  {
3468    error += errorForce0CoeffTab[i][1];
3469  }
3470  lagrangian = error + lambda * coeffBits;
3471  return (lagrangian);
3472}
3473
3474/** Predict ALF luma filter coefficients. Centre coefficient is always predicted. Determines if left neighbour should be predicted.
3475 */
3476Void TEncAdaptiveLoopFilter::predictALFCoeffLumaEnc(ALFParam* pcAlfParam, Int **pfilterCoeffSym, Int filter_shape)
3477{
3478#if LCUALF_QP_DEPENDENT_BITS
3479  Int alfPrecisionBit = getAlfPrecisionBit( m_alfQP );
3480#endif
3481  Int sum, coeffPred, ind;
3482  const Int* pFiltMag = NULL;
3483  pFiltMag = weightsTabShapes[filter_shape];
3484  for(ind = 0; ind < pcAlfParam->filters_per_group; ++ind)
3485  {
3486    sum = 0;
3487    for(Int i = 0; i < pcAlfParam->num_coeff-2; i++)
3488    {
3489      sum +=  pFiltMag[i]*pfilterCoeffSym[ind][i];
3490    }
3491
3492    if((pcAlfParam->predMethod==0)|(ind==0))
3493    {
3494#if LCUALF_QP_DEPENDENT_BITS
3495      coeffPred = ((1<<alfPrecisionBit)-sum) >> 2;
3496#else
3497      coeffPred = ((1<<ALF_NUM_BIT_SHIFT)-sum) >> 2;
3498#endif
3499    }
3500    else
3501    {
3502      coeffPred = (0-sum) >> 2;
3503    }
3504    if(abs(pfilterCoeffSym[ind][pcAlfParam->num_coeff-2]-coeffPred) < abs(pfilterCoeffSym[ind][pcAlfParam->num_coeff-2]))
3505    {
3506      pcAlfParam->nbSPred[ind] = 0; 
3507    }
3508    else
3509    {
3510      pcAlfParam->nbSPred[ind] = 1; 
3511      coeffPred = 0;
3512    }
3513    sum += pFiltMag[pcAlfParam->num_coeff-2]*pfilterCoeffSym[ind][pcAlfParam->num_coeff-2];
3514    pfilterCoeffSym[ind][pcAlfParam->num_coeff-2] -= coeffPred; 
3515    if((pcAlfParam->predMethod==0)|(ind==0))
3516    {
3517#if LCUALF_QP_DEPENDENT_BITS
3518      coeffPred = (1<<alfPrecisionBit)-sum;
3519#else
3520      coeffPred = (1<<ALF_NUM_BIT_SHIFT)-sum;
3521#endif
3522    }
3523    else
3524    {
3525      coeffPred = -sum;
3526    }
3527    pfilterCoeffSym[ind][pcAlfParam->num_coeff-1] -= coeffPred;
3528  }
3529}
3530
3531Int TEncAdaptiveLoopFilter::xsendAllFiltersPPPred(int **FilterCoeffQuant, int fl, int sqrFiltLength, 
3532                                                  int filters_per_group, int createBistream, ALFParam* ALFp)
3533{
3534  int ind, bit_ct = 0, bit_ct0 = 0, i;
3535  int predMethod = 0;
3536  int force0 = 0;
3537  Int64 Newbit_ct;
3538 
3539  for(ind = 0; ind < filters_per_group; ind++)
3540  {
3541    for(i = 0; i < sqrFiltLength; i++)
3542    {
3543      m_FilterCoeffQuantTemp[ind][i]=FilterCoeffQuant[ind][i];
3544    }
3545  }
3546  ALFp->filters_per_group = filters_per_group;
3547  ALFp->predMethod = 0;
3548  ALFp->num_coeff = sqrFiltLength;
3549  predictALFCoeffLumaEnc(ALFp, m_FilterCoeffQuantTemp, fl);
3550  Int nbFlagIntra[16];
3551  for(ind = 0; ind < filters_per_group; ind++)
3552  {
3553    nbFlagIntra[ind] = ALFp->nbSPred[ind];
3554  }
3555  bit_ct0 = xcodeFilterCoeff(m_FilterCoeffQuantTemp, fl, sqrFiltLength, filters_per_group, 0);
3556  for(ind = 0; ind < filters_per_group; ++ind)
3557  {
3558    if(ind == 0)
3559    {
3560      for(i = 0; i < sqrFiltLength; i++)
3561        m_diffFilterCoeffQuant[ind][i] = FilterCoeffQuant[ind][i];
3562    }
3563    else
3564    {
3565      for(i = 0; i < sqrFiltLength; i++)
3566        m_diffFilterCoeffQuant[ind][i] = FilterCoeffQuant[ind][i] - FilterCoeffQuant[ind-1][i];
3567    }
3568  }
3569  ALFp->predMethod = 1;
3570  predictALFCoeffLumaEnc(ALFp, m_diffFilterCoeffQuant, fl);
3571 
3572  if(xcodeFilterCoeff(m_diffFilterCoeffQuant, fl, sqrFiltLength, filters_per_group, 0) >= bit_ct0)
3573  {
3574    predMethod = 0; 
3575    if(filters_per_group > 1)
3576    {
3577      bit_ct += lengthPredFlags(force0, predMethod, NULL, 0, createBistream);
3578    }
3579    bit_ct += xcodeFilterCoeff(m_FilterCoeffQuantTemp, fl, sqrFiltLength, filters_per_group, createBistream);
3580  }
3581  else
3582  {
3583    predMethod = 1;
3584    if(filters_per_group > 1)
3585    {
3586      bit_ct += lengthPredFlags(force0, predMethod, NULL, 0, createBistream);
3587    }
3588    bit_ct += xcodeFilterCoeff(m_diffFilterCoeffQuant, fl, sqrFiltLength, filters_per_group, createBistream);
3589  }
3590  ALFp->filters_per_group = filters_per_group;
3591  ALFp->predMethod = predMethod;
3592  ALFp->num_coeff = sqrFiltLength;
3593  ALFp->filter_shape = fl;
3594  for(ind = 0; ind < filters_per_group; ++ind)
3595  {
3596    for(i = 0; i < sqrFiltLength; i++)
3597    {
3598      if (predMethod) ALFp->coeffmulti[ind][i] = m_diffFilterCoeffQuant[ind][i];
3599      else 
3600      {
3601        ALFp->coeffmulti[ind][i] = m_FilterCoeffQuantTemp[ind][i];
3602      }
3603    }
3604    if(predMethod==0)
3605    {
3606      ALFp->nbSPred[ind] = nbFlagIntra[ind];
3607    }
3608  }
3609  m_pcEntropyCoder->codeFiltCountBit(ALFp, &Newbit_ct);
3610 
3611  //  return(bit_ct);
3612  return ((Int)Newbit_ct);
3613}
3614
3615Int TEncAdaptiveLoopFilter::xcodeAuxInfo(int filters_per_fr, int varIndTab[NO_VAR_BINS], int filter_shape, ALFParam* ALFp)
3616{
3617  int i, filterPattern[NO_VAR_BINS], startSecondFilter=0, bitCt=0;
3618  Int64 NewbitCt;
3619
3620  //send realfiltNo (tap related)
3621  ALFp->filter_shape = filter_shape;
3622
3623  // decide startSecondFilter and filterPattern
3624  memset(filterPattern, 0, NO_VAR_BINS * sizeof(int)); 
3625  if(filters_per_fr > 1)
3626  {
3627    for(i = 1; i < NO_VAR_BINS; ++i)
3628    {
3629      if(varIndTab[i] != varIndTab[i-1])
3630      {
3631        filterPattern[i] = 1;
3632        startSecondFilter = i;
3633      }
3634    }
3635  }
3636  memcpy (ALFp->filterPattern, filterPattern, NO_VAR_BINS * sizeof(int));
3637  ALFp->startSecondFilter = startSecondFilter;
3638
3639  assert(filters_per_fr>0);
3640  m_pcEntropyCoder->codeAuxCountBit(ALFp, &NewbitCt);
3641
3642  bitCt = (int) NewbitCt;
3643  return(bitCt);
3644}
3645
3646Int   TEncAdaptiveLoopFilter::xcodeFilterCoeff(int **pDiffQFilterCoeffIntPP, int fl, int sqrFiltLength, 
3647                                               int filters_per_group, int createBitstream)
3648{
3649  int i, k, kMin, kStart, minBits, ind, scanPos, maxScanVal, coeffVal, len = 0,
3650    *pDepthInt=NULL, kMinTab[MAX_SCAN_VAL], bitsCoeffScan[MAX_SCAN_VAL][MAX_EXP_GOLOMB],
3651  minKStart, minBitsKStart, bitsKStart;
3652  Int minScanVal = MIN_SCAN_POS_CROSS;
3653  pDepthInt = pDepthIntTabShapes[fl];
3654 
3655  maxScanVal = 0;
3656  for(i = 0; i < sqrFiltLength; i++)
3657  {
3658    maxScanVal = max(maxScanVal, pDepthInt[i]);
3659  }
3660 
3661  // vlc for all
3662  memset(bitsCoeffScan, 0, MAX_SCAN_VAL * MAX_EXP_GOLOMB * sizeof(int));
3663  for(ind=0; ind<filters_per_group; ++ind)
3664  {
3665    for(i = 0; i < sqrFiltLength; i++)
3666    {     
3667      scanPos=pDepthInt[i]-1;
3668      coeffVal=abs(pDiffQFilterCoeffIntPP[ind][i]);
3669      for (k=1; k<15; k++)
3670      {
3671        bitsCoeffScan[scanPos][k]+=lengthGolomb(coeffVal, k);
3672      }
3673    }
3674  }
3675 
3676  minBitsKStart = 0;
3677  minKStart = -1;
3678  for(k = 1; k < 8; k++)
3679  { 
3680    bitsKStart = 0; 
3681    kStart = k;
3682    for(scanPos = minScanVal; scanPos < maxScanVal; scanPos++)
3683    {
3684      kMin = kStart; 
3685      minBits = bitsCoeffScan[scanPos][kMin];
3686     
3687      if(bitsCoeffScan[scanPos][kStart+1] < minBits)
3688      {
3689        kMin = kStart + 1; 
3690        minBits = bitsCoeffScan[scanPos][kMin];
3691      }
3692      kStart = kMin;
3693      bitsKStart += minBits;
3694    }
3695    if((bitsKStart < minBitsKStart) || (k == 1))
3696    {
3697      minBitsKStart = bitsKStart;
3698      minKStart = k;
3699    }
3700  }
3701 
3702  kStart = minKStart; 
3703  for(scanPos = minScanVal; scanPos < maxScanVal; scanPos++)
3704  {
3705    kMin = kStart; 
3706    minBits = bitsCoeffScan[scanPos][kMin];
3707   
3708    if(bitsCoeffScan[scanPos][kStart+1] < minBits)
3709    {
3710      kMin = kStart + 1; 
3711      minBits = bitsCoeffScan[scanPos][kMin];
3712    }
3713   
3714    kMinTab[scanPos] = kMin;
3715    kStart = kMin;
3716  }
3717 
3718  // Coding parameters
3719  //  len += lengthFilterCodingParams(minKStart, maxScanVal, kMinTab, createBitstream);
3720  if (filters_per_group == 1)
3721  {
3722    len += lengthFilterCoeffs(sqrFiltLength, filters_per_group, pDepthInt, pDiffQFilterCoeffIntPP, 
3723      kTableTabShapes[ALF_CROSS9x7_SQUARE3x3], createBitstream);
3724  }
3725  else
3726  {
3727  len += (3 + maxScanVal);
3728 
3729  // Filter coefficients
3730  len += lengthFilterCoeffs(sqrFiltLength, filters_per_group, pDepthInt, pDiffQFilterCoeffIntPP, 
3731                            kMinTab, createBitstream);
3732  }
3733
3734  return len;
3735}
3736
3737Int TEncAdaptiveLoopFilter::lengthGolomb(int coeffVal, int k)
3738{
3739  int m = 2 << (k - 1);
3740  int q = coeffVal / m;
3741  if(coeffVal != 0)
3742  {
3743    return(q + 2 + k);
3744  }
3745  else
3746  {
3747    return(q + 1 + k);
3748  }
3749}
3750
3751Int TEncAdaptiveLoopFilter::lengthPredFlags(int force0, int predMethod, int codedVarBins[NO_VAR_BINS], 
3752                                            int filters_per_group, int createBitstream)
3753{
3754  int bit_cnt = 0;
3755 
3756  if(force0)
3757  {
3758    bit_cnt = 2 + filters_per_group;
3759  }
3760  else
3761  {
3762    bit_cnt = 2;
3763  }
3764  return bit_cnt;
3765 
3766}
3767//important
3768Int TEncAdaptiveLoopFilter::lengthFilterCoeffs(int sqrFiltLength, int filters_per_group, int pDepthInt[], 
3769                                               int **FilterCoeff, int kMinTab[], int createBitstream)
3770{
3771  int ind, scanPos, i;
3772  int bit_cnt = 0;
3773 
3774  for(ind = 0; ind < filters_per_group; ++ind)
3775  {
3776    for(i = 0; i < sqrFiltLength; i++)
3777    {
3778      scanPos = pDepthInt[i] - 1;
3779      Int k = (filters_per_group == 1) ? kMinTab[i] : kMinTab[scanPos];
3780      bit_cnt += lengthGolomb(abs(FilterCoeff[ind][i]), k);
3781    }
3782  }
3783  return bit_cnt;
3784}
3785
3786
3787Void TEncAdaptiveLoopFilter::xfindBestFilterVarPred(double **ySym, double ***ESym, double *pixAcc, Int **filterCoeffSym, Int **filterCoeffSymQuant, Int filter_shape, Int *filters_per_fr_best, Int varIndTab[], Pel **imgY_rec, Pel **varImg, Pel **maskImg, Pel **imgY_pad, double lambda_val, Int numMaxFilters)
3788{
3789  Int filters_per_fr, firstFilt, interval[NO_VAR_BINS][2], intervalBest[NO_VAR_BINS][2];
3790  int i;
3791  double  lagrangian, lagrangianMin;
3792  int sqrFiltLength;
3793  int *weights;
3794  Int coeffBits;
3795  double errorForce0CoeffTab[NO_VAR_BINS][2];
3796 
3797  sqrFiltLength= m_sqrFiltLengthTab[filter_shape] ;
3798  weights = weightsTabShapes[filter_shape];
3799
3800  // zero all variables
3801  memset(varIndTab,0,sizeof(int)*NO_VAR_BINS);
3802
3803  for(i = 0; i < NO_VAR_BINS; i++)
3804  {
3805    memset(filterCoeffSym[i],0,sizeof(int)*ALF_MAX_NUM_COEF);
3806    memset(filterCoeffSymQuant[i],0,sizeof(int)*ALF_MAX_NUM_COEF);
3807  }
3808
3809  firstFilt=1;  lagrangianMin=0;
3810  filters_per_fr=NO_FILTERS;
3811
3812  while(filters_per_fr>=1)
3813  {
3814    mergeFiltersGreedy(ySym, ESym, pixAcc, interval, sqrFiltLength, filters_per_fr);
3815    findFilterCoeff(ESym, ySym, pixAcc, filterCoeffSym, filterCoeffSymQuant, interval,
3816      varIndTab, sqrFiltLength, filters_per_fr, weights, errorForce0CoeffTab);
3817
3818    lagrangian=xfindBestCoeffCodMethod(filterCoeffSymQuant, filter_shape, sqrFiltLength, filters_per_fr, errorForce0CoeffTab, lambda_val);
3819    if (lagrangian<lagrangianMin || firstFilt==1 || filters_per_fr == numMaxFilters)
3820    {
3821      firstFilt=0;
3822      lagrangianMin=lagrangian;
3823
3824      (*filters_per_fr_best)=filters_per_fr;
3825      memcpy(intervalBest, interval, NO_VAR_BINS*2*sizeof(int));
3826    }
3827    filters_per_fr--;
3828  }
3829  findFilterCoeff(ESym, ySym, pixAcc, filterCoeffSym, filterCoeffSymQuant, intervalBest,
3830    varIndTab, sqrFiltLength, (*filters_per_fr_best), weights, errorForce0CoeffTab);
3831
3832
3833  xfindBestCoeffCodMethod(filterCoeffSymQuant, filter_shape, sqrFiltLength, (*filters_per_fr_best), errorForce0CoeffTab, lambda_val);
3834  coeffBits = xcodeAuxInfo((*filters_per_fr_best), varIndTab, filter_shape, m_tempALFp);
3835  coeffBits += xsendAllFiltersPPPred(filterCoeffSymQuant, filter_shape, sqrFiltLength, (*filters_per_fr_best), 0, m_tempALFp);
3836
3837  if( *filters_per_fr_best == 1)
3838  {
3839    ::memset(varIndTab, 0, sizeof(Int)*NO_VAR_BINS);
3840  }
3841}
3842
3843
3844/** code filter coefficients
3845 * \param filterCoeffSymQuant filter coefficients buffer
3846 * \param filtNo filter No.
3847 * \param varIndTab[] merge index information
3848 * \param filters_per_fr_best the number of filters used in this picture
3849 * \param frNo
3850 * \param ALFp ALF parameters
3851 * \returns bitrate
3852 */
3853UInt TEncAdaptiveLoopFilter::xcodeFiltCoeff(Int **filterCoeffSymQuant, Int filter_shape, Int varIndTab[], Int filters_per_fr_best, ALFParam* ALFp)
3854{
3855  Int coeffBits;   
3856  Int sqrFiltLength = m_sqrFiltLengthTab[filter_shape] ; 
3857
3858  ALFp->filters_per_group = filters_per_fr_best;
3859
3860  coeffBits = xcodeAuxInfo(filters_per_fr_best, varIndTab, filter_shape, ALFp);
3861
3862
3863  ALFp->predMethod = 0;
3864  ALFp->num_coeff = sqrFiltLength;
3865  ALFp->filter_shape=filter_shape;
3866
3867  if (filters_per_fr_best <= 1)
3868  {
3869    ALFp->predMethod = 0;
3870  }
3871
3872  coeffBits += xsendAllFiltersPPPred(filterCoeffSymQuant, filter_shape, sqrFiltLength, 
3873    filters_per_fr_best, 1, ALFp);
3874
3875  return (UInt)coeffBits;
3876}
3877
3878Void TEncAdaptiveLoopFilter::getCtrlFlagsFromCU(AlfLCUInfo* pcAlfLCU, std::vector<UInt> *pvFlags, Int alfDepth, UInt maxNumSUInLCU)
3879{
3880  const UInt startSU               = pcAlfLCU->startSU;
3881  const UInt endSU                 = pcAlfLCU->endSU;
3882  const Bool bAllSUsInLCUInSameSlice = pcAlfLCU->bAllSUsInLCUInSameSlice;
3883
3884  TComDataCU* pcCU = pcAlfLCU->pcCU;
3885  UInt  currSU, CUDepth, setDepth, ctrlNumSU;
3886
3887  currSU = startSU;
3888
3889  if(bAllSUsInLCUInSameSlice)
3890  {
3891    while(currSU < maxNumSUInLCU)
3892    {
3893      //depth of this CU
3894      CUDepth = pcCU->getDepth(currSU);
3895
3896      //choose the min. depth for ALF
3897      setDepth   = (alfDepth < CUDepth)?(alfDepth):(CUDepth);
3898      ctrlNumSU = maxNumSUInLCU >> (setDepth << 1);
3899
3900      pvFlags->push_back(pcCU->getAlfCtrlFlag(currSU));
3901      currSU += ctrlNumSU;
3902    }
3903
3904    return;
3905  }
3906
3907
3908  const UInt  LCUX = pcCU->getCUPelX();
3909  const UInt  LCUY = pcCU->getCUPelY();
3910
3911  Bool  bFirst, bValidCU;
3912  UInt  idx, LPelXSU, TPelYSU;
3913
3914  bFirst= true;
3915  while(currSU <= endSU)
3916  {
3917    //check picture boundary
3918    while(!( LCUX + g_auiRasterToPelX[ g_auiZscanToRaster[currSU] ] < m_img_width  ) || 
3919          !( LCUY + g_auiRasterToPelY[ g_auiZscanToRaster[currSU] ] < m_img_height )
3920      )
3921    {
3922      currSU++;
3923
3924      if(currSU >= maxNumSUInLCU || currSU > endSU)
3925      {
3926        break;
3927      }
3928    }
3929
3930    if(currSU >= maxNumSUInLCU || currSU > endSU)
3931    {
3932      break;
3933    }
3934
3935    //depth of this CU
3936    CUDepth = pcCU->getDepth(currSU);
3937
3938    //choose the min. depth for ALF
3939    setDepth   = (alfDepth < CUDepth)?(alfDepth):(CUDepth);
3940    ctrlNumSU = maxNumSUInLCU >> (setDepth << 1);
3941
3942    if(bFirst)
3943    {
3944      if(currSU !=0 )
3945      {
3946        currSU = ((UInt)(currSU/ctrlNumSU))* ctrlNumSU;
3947      }
3948      bFirst = false;
3949    }
3950
3951    bValidCU = false;
3952    for(idx = currSU; idx < currSU + ctrlNumSU; idx++)
3953    {
3954      if(idx < startSU || idx > endSU)
3955      {
3956        continue;
3957      }
3958
3959      LPelXSU   = LCUX + g_auiRasterToPelX[ g_auiZscanToRaster[idx] ];
3960      TPelYSU   = LCUY + g_auiRasterToPelY[ g_auiZscanToRaster[idx] ];
3961
3962      if( !( LPelXSU < m_img_width )  || !( TPelYSU < m_img_height )  )
3963      {
3964        continue;
3965      }
3966
3967      bValidCU = true;
3968    }
3969
3970    if(bValidCU)
3971    {
3972      pvFlags->push_back(pcCU->getAlfCtrlFlag(currSU));
3973    }
3974
3975    currSU += ctrlNumSU;
3976  }
3977}
3978
3979
3980/** set ALF CU control flags
3981 * \param [in] uiAlfCtrlDepth ALF CU control depth
3982 * \param [in] pcPicOrg picture of original signal
3983 * \param [in] pcPicDec picture before filtering
3984 * \param [in] pcPicRest picture after filtering
3985 * \param [out] ruiDist distortion after CU control
3986 * \param [in,out]vAlfCUCtrlParam ALF CU control parameters
3987 */
3988#if HHI_INTERVIEW_SKIP
3989Void TEncAdaptiveLoopFilter::setCUAlfCtrlFlags(UInt uiAlfCtrlDepth, Pel* imgOrg, Pel* imgDec, Pel* imgRest, Pel* imgUsed, Int stride, UInt64& ruiDist, std::vector<AlfCUCtrlInfo>& vAlfCUCtrlParam)
3990#else
3991Void TEncAdaptiveLoopFilter::setCUAlfCtrlFlags(UInt uiAlfCtrlDepth, Pel* imgOrg, Pel* imgDec, Pel* imgRest, Int stride, UInt64& ruiDist, std::vector<AlfCUCtrlInfo>& vAlfCUCtrlParam)
3992#endif
3993{
3994  ruiDist = 0;
3995  std::vector<UInt> uiFlags;
3996
3997  //initial
3998  for(Int s=0; s< m_uiNumSlicesInPic; s++)
3999  {
4000    vAlfCUCtrlParam[s].cu_control_flag = 1;
4001    vAlfCUCtrlParam[s].alf_max_depth   = uiAlfCtrlDepth;
4002
4003    vAlfCUCtrlParam[s].alf_cu_flag.reserve(m_uiNumCUsInFrame << ((g_uiMaxCUDepth-1)*2));
4004    vAlfCUCtrlParam[s].alf_cu_flag.resize(0);
4005  }
4006
4007  //LCU-based on/off control
4008  for( UInt CUAddr = 0; CUAddr < m_pcPic->getNumCUsInFrame() ; CUAddr++ )
4009  {
4010    TComDataCU* pcCU = m_pcPic->getCU( CUAddr );
4011#if HHI_INTERVIEW_SKIP
4012    setCUAlfCtrlFlag(pcCU, 0, 0, uiAlfCtrlDepth, imgOrg, imgDec, imgRest, imgUsed, stride, ruiDist, vAlfCUCtrlParam[0].alf_cu_flag);
4013#else
4014    setCUAlfCtrlFlag(pcCU, 0, 0, uiAlfCtrlDepth, imgOrg, imgDec, imgRest, stride, ruiDist, vAlfCUCtrlParam[0].alf_cu_flag);
4015#endif
4016  }
4017  vAlfCUCtrlParam[0].num_alf_cu_flag = (UInt)(vAlfCUCtrlParam[0].alf_cu_flag.size());
4018
4019
4020  if(m_uiNumSlicesInPic > 1)
4021  {
4022    //reset the first slice on/off flags
4023    vAlfCUCtrlParam[0].alf_cu_flag.resize(0);
4024
4025    //distribute on/off flags to slices
4026    std::vector<UInt> vCtrlFlags;
4027    vCtrlFlags.reserve(1 << ((g_uiMaxCUDepth-1)*2));
4028
4029    for(Int s=0; s < m_uiNumSlicesInPic; s++)
4030    {
4031      if(!m_pcPic->getValidSlice(s))
4032      {
4033        continue;
4034      }
4035      std::vector< AlfLCUInfo* >& vpAlfLCU = m_pvpAlfLCU[s];
4036      for(Int i=0; i< vpAlfLCU.size(); i++)
4037      {
4038        //get on/off flags for one LCU
4039        vCtrlFlags.resize(0);
4040        getCtrlFlagsFromCU(vpAlfLCU[i], &vCtrlFlags, (Int)uiAlfCtrlDepth, m_pcPic->getNumPartInCU());
4041
4042        for(Int k=0; k< vCtrlFlags.size(); k++)
4043        {
4044          vAlfCUCtrlParam[s].alf_cu_flag.push_back( vCtrlFlags[k]);
4045        }
4046      } //i (LCU)
4047      vAlfCUCtrlParam[s].num_alf_cu_flag = (UInt)(vAlfCUCtrlParam[s].alf_cu_flag.size());
4048    } //s (Slice)
4049  }
4050}
4051
4052#if HHI_INTERVIEW_SKIP
4053Void TEncAdaptiveLoopFilter::setCUAlfCtrlFlag(TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth, UInt uiAlfCtrlDepth, Pel* imgOrg, Pel* imgDec, Pel* imgRest, Pel* imgUsed, Int stride, UInt64& ruiDist, std::vector<UInt>& vCUCtrlFlag)
4054#else
4055Void TEncAdaptiveLoopFilter::setCUAlfCtrlFlag(TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth, UInt uiAlfCtrlDepth, Pel* imgOrg, Pel* imgDec, Pel* imgRest, Int stride, UInt64& ruiDist, std::vector<UInt>& vCUCtrlFlag)
4056#endif
4057{
4058  Bool bBoundary = false;
4059  UInt uiLPelX   = pcCU->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiAbsPartIdx] ];
4060  UInt uiRPelX   = uiLPelX + (g_uiMaxCUWidth>>uiDepth)  - 1;
4061  UInt uiTPelY   = pcCU->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiAbsPartIdx] ];
4062  UInt uiBPelY   = uiTPelY + (g_uiMaxCUHeight>>uiDepth) - 1;
4063 
4064  if( ( uiRPelX >= pcCU->getSlice()->getSPS()->getPicWidthInLumaSamples() ) || ( uiBPelY >= pcCU->getSlice()->getSPS()->getPicHeightInLumaSamples() ) )
4065  {
4066    bBoundary = true;
4067  }
4068 
4069  if( ( ( uiDepth < pcCU->getDepth( uiAbsPartIdx ) ) && ( uiDepth < (g_uiMaxCUDepth-g_uiAddCUDepth) ) ) || bBoundary )
4070  {
4071    UInt uiQNumParts = ( m_pcPic->getNumPartInCU() >> (uiDepth<<1) )>>2;
4072    for ( UInt uiPartUnitIdx = 0; uiPartUnitIdx < 4; uiPartUnitIdx++, uiAbsPartIdx+=uiQNumParts )
4073    {
4074      uiLPelX   = pcCU->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiAbsPartIdx] ];
4075      uiTPelY   = pcCU->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiAbsPartIdx] ];
4076     
4077      if( ( uiLPelX < pcCU->getSlice()->getSPS()->getPicWidthInLumaSamples() ) && ( uiTPelY < pcCU->getSlice()->getSPS()->getPicHeightInLumaSamples() ) )
4078#if HHI_INTERVIEW_SKIP
4079        setCUAlfCtrlFlag(pcCU, uiAbsPartIdx, uiDepth+1, uiAlfCtrlDepth, imgOrg, imgDec, imgRest, imgUsed, stride, ruiDist, vCUCtrlFlag);
4080#else
4081        setCUAlfCtrlFlag(pcCU, uiAbsPartIdx, uiDepth+1, uiAlfCtrlDepth, imgOrg, imgDec, imgRest, stride, ruiDist, vCUCtrlFlag);
4082#endif
4083    }
4084    return;
4085  }
4086 
4087  if( uiDepth > uiAlfCtrlDepth && !pcCU->isFirstAbsZorderIdxInDepth(uiAbsPartIdx, uiAlfCtrlDepth))
4088  {
4089    return;
4090  }
4091  UInt64 uiRecSSD = 0;
4092  UInt64 uiFiltSSD = 0;
4093 
4094  Int iWidth;
4095  Int iHeight;
4096  UInt uiSetDepth;
4097 
4098  if (uiDepth > uiAlfCtrlDepth && pcCU->isFirstAbsZorderIdxInDepth(uiAbsPartIdx, uiAlfCtrlDepth))
4099  {
4100    iWidth = g_uiMaxCUWidth >> uiAlfCtrlDepth;
4101    iHeight = g_uiMaxCUHeight >> uiAlfCtrlDepth;
4102   
4103    uiRPelX   = uiLPelX + iWidth  - 1;
4104    uiBPelY   = uiTPelY + iHeight - 1;
4105
4106    if( uiRPelX >= pcCU->getSlice()->getSPS()->getPicWidthInLumaSamples() )
4107    {
4108      iWidth = pcCU->getSlice()->getSPS()->getPicWidthInLumaSamples() - uiLPelX;
4109    }
4110   
4111    if( uiBPelY >= pcCU->getSlice()->getSPS()->getPicHeightInLumaSamples() )
4112    {
4113      iHeight = pcCU->getSlice()->getSPS()->getPicHeightInLumaSamples() - uiTPelY;
4114    }
4115   
4116    uiSetDepth = uiAlfCtrlDepth;
4117  }
4118  else
4119  {
4120    iWidth = pcCU->getWidth(uiAbsPartIdx);
4121    iHeight = pcCU->getHeight(uiAbsPartIdx);
4122    uiSetDepth = uiDepth;
4123  }
4124 
4125  Int  offset = uiTPelY*stride + uiLPelX;
4126  Pel* pOrg  = imgOrg  + offset;
4127  Pel* pRec  = imgDec  + offset;
4128  Pel* pFilt = imgRest + offset;
4129
4130#if HHI_INTERVIEW_SKIP
4131  Pel* pUsed = NULL ;
4132  if( imgUsed )
4133  {
4134    pUsed = imgUsed + offset;
4135  }
4136  uiRecSSD  += xCalcSSD( pOrg, pRec,  pUsed, iWidth, iHeight, stride );
4137  uiFiltSSD += xCalcSSD( pOrg, pFilt, pUsed, iWidth, iHeight, stride );
4138#else
4139  uiRecSSD  += xCalcSSD( pOrg, pRec,  iWidth, iHeight, stride );
4140  uiFiltSSD += xCalcSSD( pOrg, pFilt, iWidth, iHeight, stride );
4141#endif
4142  if (uiFiltSSD < uiRecSSD)
4143  {
4144    ruiDist += uiFiltSSD;
4145    pcCU->setAlfCtrlFlagSubParts(1, uiAbsPartIdx, uiSetDepth);
4146    vCUCtrlFlag.push_back(1);
4147
4148    for (int i=uiTPelY ;i<=min(uiBPelY,(unsigned int)(m_img_height-1))  ;i++)
4149    {
4150      for (int j=uiLPelX ;j<=min(uiRPelX,(unsigned int)(m_img_width-1)) ;j++)
4151      { 
4152        m_maskImg[i][j]=1;
4153      }
4154    }
4155  }
4156  else
4157  {
4158    ruiDist += uiRecSSD;
4159    pcCU->setAlfCtrlFlagSubParts(0, uiAbsPartIdx, uiSetDepth);
4160    vCUCtrlFlag.push_back(0);
4161    for (int i=uiTPelY ;i<=min(uiBPelY,(unsigned int)(m_img_height-1))  ;i++)
4162    {
4163      for (int j=uiLPelX ;j<=min(uiRPelX,(unsigned int)(m_img_width-1)) ;j++)
4164      { 
4165        m_maskImg[i][j]=0;
4166      }
4167    }
4168  }
4169}
4170
4171
4172#define ROUND(a)  (((a) < 0)? (int)((a) - 0.5) : (int)((a) + 0.5))
4173#define REG              0.0001
4174#define REG_SQR          0.0000001
4175
4176//Find filter coeff related
4177Int TEncAdaptiveLoopFilter::gnsCholeskyDec(Double **inpMatr, Double outMatr[ALF_MAX_NUM_COEF][ALF_MAX_NUM_COEF], Int noEq)
4178{ 
4179  Int i, j, k;     /* Looping Variables */
4180  Double scale;       /* scaling factor for each row */
4181  Double invDiag[ALF_MAX_NUM_COEF];  /* Vector of the inverse of diagonal entries of outMatr */
4182 
4183  //  Cholesky decomposition starts
4184 
4185  for(i = 0; i < noEq; i++)
4186  {
4187    for(j = i; j < noEq; j++)
4188    {
4189      /* Compute the scaling factor */
4190      scale = inpMatr[i][j];
4191      if ( i > 0) 
4192      {
4193        for( k = i - 1 ; k >= 0 ; k--)
4194        {
4195          scale -= outMatr[k][j] * outMatr[k][i];
4196        }
4197      }
4198      /* Compute i'th row of outMatr */
4199      if(i == j)
4200      {
4201        if(scale <= REG_SQR ) // if(scale <= 0 )  /* If inpMatr is singular */
4202        {
4203          return 0;
4204        }
4205        else
4206        {
4207           /* Normal operation */
4208           invDiag[i] =  1.0 / (outMatr[i][i] = sqrt(scale));
4209        }
4210      }
4211      else
4212      {
4213        outMatr[i][j] = scale * invDiag[i]; /* Upper triangular part          */
4214        outMatr[j][i] = 0.0;              /* Lower triangular part set to 0 */
4215      }                   
4216    }
4217  }
4218  return 1; /* Signal that Cholesky factorization is successfully performed */
4219}
4220
4221
4222Void TEncAdaptiveLoopFilter::gnsTransposeBacksubstitution(Double U[ALF_MAX_NUM_COEF][ALF_MAX_NUM_COEF], Double rhs[], Double x[], Int order)
4223{
4224  Int i,j;              /* Looping variables */
4225  Double sum;              /* Holds backsubstitution from already handled rows */
4226 
4227  /* Backsubstitution starts */
4228  x[0] = rhs[0] / U[0][0];               /* First row of U'                   */
4229  for (i = 1; i < order; i++)
4230  {         /* For the rows 1..order-1           */
4231   
4232    for (j = 0, sum = 0.0; j < i; j++) /* Backsubst already solved unknowns */
4233    {
4234      sum += x[j] * U[j][i];
4235    }
4236    x[i] = (rhs[i] - sum) / U[i][i];       /* i'th component of solution vect.  */
4237  }
4238}
4239
4240Void  TEncAdaptiveLoopFilter::gnsBacksubstitution(Double R[ALF_MAX_NUM_COEF][ALF_MAX_NUM_COEF], Double z[ALF_MAX_NUM_COEF], Int R_size, Double A[MAX_SQR_FILT_LENGTH])
4241{
4242  Int i, j;
4243  Double sum;
4244 
4245  R_size--;
4246 
4247  A[R_size] = z[R_size] / R[R_size][R_size];
4248 
4249  for (i = R_size-1; i >= 0; i--)
4250  {
4251    for (j = i + 1, sum = 0.0; j <= R_size; j++)
4252    {
4253      sum += R[i][j] * A[j];
4254    }
4255   
4256    A[i] = (z[i] - sum) / R[i][i];
4257  }
4258}
4259
4260
4261Int TEncAdaptiveLoopFilter::gnsSolveByChol(Double **LHS, Double *rhs, Double *x, Int noEq)
4262{
4263  assert(noEq > 0);
4264
4265  Double aux[ALF_MAX_NUM_COEF];     /* Auxiliary vector */
4266  Double U[ALF_MAX_NUM_COEF][ALF_MAX_NUM_COEF];    /* Upper triangular Cholesky factor of LHS */
4267  Int  i, singular;          /* Looping variable */
4268 
4269  /* The equation to be solved is LHSx = rhs */
4270 
4271  /* Compute upper triangular U such that U'*U = LHS */
4272  if(gnsCholeskyDec(LHS, U, noEq)) /* If Cholesky decomposition has been successful */
4273  {
4274    singular = 1;
4275    /* Now, the equation is  U'*U*x = rhs, where U is upper triangular
4276     * Solve U'*aux = rhs for aux
4277     */
4278    gnsTransposeBacksubstitution(U, rhs, aux, noEq);         
4279   
4280    /* The equation is now U*x = aux, solve it for x (new motion coefficients) */
4281    gnsBacksubstitution(U, aux, noEq, x);   
4282   
4283  }
4284  else /* LHS was singular */ 
4285  {
4286    singular = 0;
4287   
4288    /* Regularize LHS */
4289    for(i=0; i < noEq; i++)
4290    {
4291      LHS[i][i] += REG;
4292    }
4293    /* Compute upper triangular U such that U'*U = regularized LHS */
4294    singular = gnsCholeskyDec(LHS, U, noEq);
4295    if ( singular == 1 )
4296    {
4297      /* Solve  U'*aux = rhs for aux */ 
4298      gnsTransposeBacksubstitution(U, rhs, aux, noEq);   
4299     
4300      /* Solve U*x = aux for x */
4301      gnsBacksubstitution(U, aux, noEq, x);     
4302    }
4303    else
4304    {
4305      x[0] = 1.0;
4306      for (i = 1; i < noEq; i++ )
4307      {
4308        x[i] = 0.0;
4309      }
4310    }
4311  } 
4312  return singular;
4313}
4314
4315Void TEncAdaptiveLoopFilter::add_A(Double **Amerged, Double ***A, Int start, Int stop, Int size)
4316{ 
4317  Int i, j, ind;          /* Looping variable */
4318 
4319  for (i = 0; i < size; i++)
4320  {
4321    for (j = 0; j < size; j++)
4322    {
4323      Amerged[i][j] = 0;
4324      for (ind = start; ind <= stop; ind++)
4325      {
4326        Amerged[i][j] += A[ind][i][j];
4327      }
4328    }
4329  }
4330}
4331
4332Void TEncAdaptiveLoopFilter::add_b(Double *bmerged, Double **b, Int start, Int stop, Int size)
4333{ 
4334  Int i, ind;          /* Looping variable */
4335 
4336  for (i = 0; i < size; i++)
4337  {
4338    bmerged[i] = 0;
4339    for (ind = start; ind <= stop; ind++)
4340    {
4341      bmerged[i] += b[ind][i];
4342    }
4343  }
4344}
4345
4346Double TEncAdaptiveLoopFilter::calculateErrorCoeffProvided(Double **A, Double *b, Double *c, Int size)
4347{
4348  Int i, j;
4349  Double error, sum = 0;
4350 
4351  error = 0;
4352  for (i = 0; i < size; i++)   //diagonal
4353  {
4354    sum = 0;
4355    for (j = i + 1; j < size; j++)
4356    {
4357      sum += (A[j][i] + A[i][j]) * c[j];
4358    }
4359    error += (A[i][i] * c[i] + sum - 2 * b[i]) * c[i];
4360  }
4361 
4362  return error;
4363}
4364
4365Double TEncAdaptiveLoopFilter::calculateErrorAbs(Double **A, Double *b, Double y, Int size)
4366{
4367  Int i;
4368  Double error, sum;
4369  Double c[ALF_MAX_NUM_COEF];
4370 
4371  gnsSolveByChol(A, b, c, size);
4372 
4373  sum = 0;
4374  for (i = 0; i < size; i++)
4375  {
4376    sum += c[i] * b[i];
4377  }
4378  error = y - sum;
4379 
4380  return error;
4381}
4382
4383Double TEncAdaptiveLoopFilter::mergeFiltersGreedy(Double **yGlobalSeq, Double ***EGlobalSeq, Double *pixAccGlobalSeq, Int intervalBest[NO_VAR_BINS][2], Int sqrFiltLength, Int noIntervals)
4384{
4385  Int first, ind, ind1, ind2, i, j, bestToMerge ;
4386  Double error, error1, error2, errorMin;
4387  static Double pixAcc_temp, error_tab[NO_VAR_BINS],error_comb_tab[NO_VAR_BINS];
4388  static Int indexList[NO_VAR_BINS], available[NO_VAR_BINS], noRemaining;
4389  if (noIntervals == NO_FILTERS)
4390  {
4391    noRemaining = NO_VAR_BINS;
4392    for (ind=0; ind<NO_VAR_BINS; ind++)
4393    {
4394      indexList[ind] = ind; 
4395      available[ind] = 1;
4396      m_pixAcc_merged[ind] = pixAccGlobalSeq[ind];
4397      memcpy(m_y_merged[ind], yGlobalSeq[ind], sizeof(Double)*sqrFiltLength);
4398      for (i=0; i < sqrFiltLength; i++)
4399      {
4400        memcpy(m_E_merged[ind][i], EGlobalSeq[ind][i], sizeof(Double)*sqrFiltLength);
4401      }
4402    }
4403  }
4404  // Try merging different matrices
4405  if (noIntervals == NO_FILTERS)
4406  {
4407    for (ind = 0; ind < NO_VAR_BINS; ind++)
4408    {
4409      error_tab[ind] = calculateErrorAbs(m_E_merged[ind], m_y_merged[ind], m_pixAcc_merged[ind], sqrFiltLength);
4410    }
4411    for (ind = 0; ind < NO_VAR_BINS - 1; ind++)
4412    {
4413      ind1 = indexList[ind];
4414      ind2 = indexList[ind+1];
4415     
4416      error1 = error_tab[ind1];
4417      error2 = error_tab[ind2];
4418     
4419      pixAcc_temp = m_pixAcc_merged[ind1] + m_pixAcc_merged[ind2];
4420      for (i = 0; i < sqrFiltLength; i++)
4421      {
4422        m_y_temp[i] = m_y_merged[ind1][i] + m_y_merged[ind2][i];
4423        for (j = 0; j < sqrFiltLength; j++)
4424        {
4425          m_E_temp[i][j] = m_E_merged[ind1][i][j] + m_E_merged[ind2][i][j];
4426        }
4427      }
4428      error_comb_tab[ind1] = calculateErrorAbs(m_E_temp, m_y_temp, pixAcc_temp, sqrFiltLength) - error1 - error2;
4429    }
4430  }
4431  while (noRemaining > noIntervals)
4432  {
4433    errorMin = 0; 
4434    first = 1;
4435    bestToMerge = 0;
4436    for (ind = 0; ind < noRemaining - 1; ind++)
4437    {
4438      error = error_comb_tab[indexList[ind]];
4439      if ((error < errorMin || first == 1))
4440      {
4441        errorMin = error;
4442        bestToMerge = ind;
4443        first = 0;
4444      }
4445    }
4446    ind1 = indexList[bestToMerge];
4447    ind2 = indexList[bestToMerge+1];
4448    m_pixAcc_merged[ind1] += m_pixAcc_merged[ind2];
4449    for (i = 0; i < sqrFiltLength; i++)
4450    {
4451      m_y_merged[ind1][i] += m_y_merged[ind2][i];
4452      for (j = 0; j < sqrFiltLength; j++)
4453      {
4454        m_E_merged[ind1][i][j] += m_E_merged[ind2][i][j];
4455      }
4456    }
4457    available[ind2] = 0;
4458   
4459    //update error tables
4460    error_tab[ind1] = error_comb_tab[ind1] + error_tab[ind1] + error_tab[ind2];
4461    if (indexList[bestToMerge] > 0)
4462    {
4463      ind1 = indexList[bestToMerge-1];
4464      ind2 = indexList[bestToMerge];
4465      error1 = error_tab[ind1];
4466      error2 = error_tab[ind2];
4467      pixAcc_temp = m_pixAcc_merged[ind1] + m_pixAcc_merged[ind2];
4468      for (i = 0; i < sqrFiltLength; i++)
4469      {
4470        m_y_temp[i] = m_y_merged[ind1][i] + m_y_merged[ind2][i];
4471        for (j = 0; j < sqrFiltLength; j++)
4472        {
4473          m_E_temp[i][j] = m_E_merged[ind1][i][j] + m_E_merged[ind2][i][j];
4474        }
4475      }
4476      error_comb_tab[ind1] = calculateErrorAbs(m_E_temp, m_y_temp, pixAcc_temp, sqrFiltLength) - error1 - error2;
4477    }
4478    if (indexList[bestToMerge+1] < NO_VAR_BINS - 1)
4479    {
4480      ind1 = indexList[bestToMerge];
4481      ind2 = indexList[bestToMerge+2];
4482      error1 = error_tab[ind1];
4483      error2 = error_tab[ind2];
4484      pixAcc_temp = m_pixAcc_merged[ind1] + m_pixAcc_merged[ind2];
4485      for (i=0; i<sqrFiltLength; i++)
4486      {
4487        m_y_temp[i] = m_y_merged[ind1][i] + m_y_merged[ind2][i];
4488        for (j=0; j < sqrFiltLength; j++)
4489        {
4490          m_E_temp[i][j] = m_E_merged[ind1][i][j] + m_E_merged[ind2][i][j];
4491        }
4492      }
4493      error_comb_tab[ind1] = calculateErrorAbs(m_E_temp, m_y_temp, pixAcc_temp, sqrFiltLength) - error1 - error2;
4494    }
4495   
4496    ind=0;
4497    for (i = 0; i < NO_VAR_BINS; i++)
4498    {
4499      if (available[i] == 1)
4500      {
4501        indexList[ind] = i;
4502        ind++;
4503      }
4504    }
4505    noRemaining--;
4506  }
4507 
4508  errorMin = 0;
4509  for (ind = 0; ind < noIntervals; ind++)
4510  {
4511    errorMin += error_tab[indexList[ind]];
4512  }
4513 
4514  for (ind = 0; ind < noIntervals - 1; ind++)
4515  {
4516    intervalBest[ind][0] = indexList[ind]; 
4517    intervalBest[ind][1] = indexList[ind+1] - 1;
4518  }
4519 
4520  intervalBest[noIntervals-1][0] = indexList[noIntervals-1]; 
4521  intervalBest[noIntervals-1][1] = NO_VAR_BINS-1;
4522 
4523  return(errorMin);
4524}
4525
4526Void TEncAdaptiveLoopFilter::roundFiltCoeff(Int *FilterCoeffQuan, Double *FilterCoeff, Int sqrFiltLength, Int factor)
4527{
4528  Int i;
4529  Double diff; 
4530  Int diffInt, sign; 
4531 
4532  for(i = 0; i < sqrFiltLength; i++)
4533  {
4534    sign = (FilterCoeff[i] > 0)? 1 : -1; 
4535    diff = FilterCoeff[i] * sign; 
4536    diffInt = (Int)(diff * (Double)factor + 0.5); 
4537    FilterCoeffQuan[i] = diffInt * sign;
4538  }
4539}
4540
4541Double TEncAdaptiveLoopFilter::QuantizeIntegerFilterPP(Double *filterCoeff, Int *filterCoeffQuant, Double **E, Double *y, Int sqrFiltLength, Int *weights)
4542{
4543  double error;
4544#if LCUALF_QP_DEPENDENT_BITS
4545  Int factor = (1<<(getAlfPrecisionBit(m_alfQP)));
4546#else
4547  Int factor = (1<<  ((Int)ALF_NUM_BIT_SHIFT)  );
4548#endif
4549  Int i;
4550  int quantCoeffSum, minInd, targetCoeffSumInt, k, diff;
4551  double targetCoeffSum, errMin;
4552 
4553  gnsSolveByChol(E, y, filterCoeff, sqrFiltLength);
4554  targetCoeffSum=0;
4555  for (i=0; i<sqrFiltLength; i++)
4556  {
4557    targetCoeffSum+=(weights[i]*filterCoeff[i]*factor);
4558  }
4559  targetCoeffSumInt=ROUND(targetCoeffSum);
4560  roundFiltCoeff(filterCoeffQuant, filterCoeff, sqrFiltLength, factor);
4561  quantCoeffSum=0;
4562  for (i=0; i<sqrFiltLength; i++)
4563  {
4564    quantCoeffSum+=weights[i]*filterCoeffQuant[i];
4565  }
4566 
4567  int count=0;
4568  while(quantCoeffSum!=targetCoeffSumInt && count < 10)
4569  {
4570    if (quantCoeffSum>targetCoeffSumInt)
4571    {
4572      diff=quantCoeffSum-targetCoeffSumInt;
4573      errMin=0; minInd=-1;
4574      for (k=0; k<sqrFiltLength; k++)
4575      {
4576        if (weights[k]<=diff)
4577        {
4578          for (i=0; i<sqrFiltLength; i++)
4579          {
4580            m_filterCoeffQuantMod[i]=filterCoeffQuant[i];
4581          }
4582          m_filterCoeffQuantMod[k]--;
4583          for (i=0; i<sqrFiltLength; i++)
4584          {
4585            filterCoeff[i]=(double)m_filterCoeffQuantMod[i]/(double)factor;
4586          }
4587          error=calculateErrorCoeffProvided(E, y, filterCoeff, sqrFiltLength);
4588          if (error<errMin || minInd==-1)
4589          {
4590            errMin=error;
4591            minInd=k;
4592          }
4593        } // if (weights(k)<=diff)
4594      } // for (k=0; k<sqrFiltLength; k++)
4595      filterCoeffQuant[minInd]--;
4596    }
4597    else
4598    {
4599      diff=targetCoeffSumInt-quantCoeffSum;
4600      errMin=0; minInd=-1;
4601      for (k=0; k<sqrFiltLength; k++)
4602      {
4603        if (weights[k]<=diff)
4604        {
4605          for (i=0; i<sqrFiltLength; i++)
4606          {
4607            m_filterCoeffQuantMod[i]=filterCoeffQuant[i];
4608          }
4609          m_filterCoeffQuantMod[k]++;
4610          for (i=0; i<sqrFiltLength; i++)
4611          {
4612            filterCoeff[i]=(double)m_filterCoeffQuantMod[i]/(double)factor;
4613          }
4614          error=calculateErrorCoeffProvided(E, y, filterCoeff, sqrFiltLength);
4615          if (error<errMin || minInd==-1)
4616          {
4617            errMin=error;
4618            minInd=k;
4619          }
4620        } // if (weights(k)<=diff)
4621      } // for (k=0; k<sqrFiltLength; k++)
4622      filterCoeffQuant[minInd]++;
4623    }
4624   
4625    quantCoeffSum=0;
4626    for (i=0; i<sqrFiltLength; i++)
4627    {
4628      quantCoeffSum+=weights[i]*filterCoeffQuant[i];
4629    }
4630  }
4631  if( count == 10 )
4632  {
4633    for (i=0; i<sqrFiltLength; i++)
4634    {
4635      filterCoeffQuant[i] = 0;
4636    }
4637  }
4638 
4639  checkFilterCoeffValue(filterCoeffQuant, sqrFiltLength, false);
4640
4641  for (i=0; i<sqrFiltLength; i++)
4642  {
4643    filterCoeff[i]=(double)filterCoeffQuant[i]/(double)factor;
4644  }
4645 
4646  error=calculateErrorCoeffProvided(E, y, filterCoeff, sqrFiltLength);
4647  return(error);
4648}
4649Double TEncAdaptiveLoopFilter::findFilterCoeff(double ***EGlobalSeq, double **yGlobalSeq, double *pixAccGlobalSeq, int **filterCoeffSeq, int **filterCoeffQuantSeq, int intervalBest[NO_VAR_BINS][2], int varIndTab[NO_VAR_BINS], int sqrFiltLength, int filters_per_fr, int *weights, double errorTabForce0Coeff[NO_VAR_BINS][2])
4650{
4651  static double pixAcc_temp;
4652  double error;
4653  int k, filtNo;
4654 
4655  error = 0;
4656  for(filtNo = 0; filtNo < filters_per_fr; filtNo++)
4657  {
4658    add_A(m_E_temp, EGlobalSeq, intervalBest[filtNo][0], intervalBest[filtNo][1], sqrFiltLength);
4659    add_b(m_y_temp, yGlobalSeq, intervalBest[filtNo][0], intervalBest[filtNo][1], sqrFiltLength);
4660   
4661    pixAcc_temp = 0;   
4662    for(k = intervalBest[filtNo][0]; k <= intervalBest[filtNo][1]; k++)
4663      pixAcc_temp += pixAccGlobalSeq[k];
4664   
4665    // Find coeffcients
4666    errorTabForce0Coeff[filtNo][1] = pixAcc_temp + QuantizeIntegerFilterPP(m_filterCoeff, m_filterCoeffQuant, m_E_temp, m_y_temp, sqrFiltLength, weights);
4667    errorTabForce0Coeff[filtNo][0] = pixAcc_temp;
4668    error += errorTabForce0Coeff[filtNo][1];
4669   
4670    for(k = 0; k < sqrFiltLength; k++)
4671    {
4672      filterCoeffSeq[filtNo][k] = m_filterCoeffQuant[k];
4673      filterCoeffQuantSeq[filtNo][k] = m_filterCoeffQuant[k];
4674    }
4675  }
4676 
4677  for(filtNo = 0; filtNo < filters_per_fr; filtNo++)
4678  {
4679    for(k = intervalBest[filtNo][0]; k <= intervalBest[filtNo][1]; k++)
4680      varIndTab[k] = filtNo;
4681  }
4682 
4683  return(error);
4684}
4685
4686
4687/** Estimate filtering distortion by correlation values and filter coefficients
4688 * \param ppdE auto-correlation matrix
4689 * \param pdy cross-correlation array
4690 * \param piCoeff  filter coefficients
4691 * \param iFiltLength numbr of filter taps
4692 * \returns estimated distortion
4693 */
4694Int64 TEncAdaptiveLoopFilter::xFastFiltDistEstimation(Double** ppdE, Double* pdy, Int* piCoeff, Int iFiltLength)
4695{
4696  //static memory
4697  Double pdcoeff[ALF_MAX_NUM_COEF];
4698  //variable
4699  Int    i,j;
4700  Int64  iDist;
4701  Double dDist, dsum;
4702#if LCUALF_QP_DEPENDENT_BITS
4703  Int alfPrecisionBit = getAlfPrecisionBit( m_alfQP );
4704#endif
4705
4706  for(i=0; i< iFiltLength; i++)
4707  {
4708#if LCUALF_QP_DEPENDENT_BITS
4709    pdcoeff[i]= (Double)piCoeff[i] / (Double)(1<<alfPrecisionBit);
4710#else
4711    pdcoeff[i]= (Double)piCoeff[i] / (Double)(1<< ((Int)ALF_NUM_BIT_SHIFT) );
4712#endif
4713  }
4714
4715  dDist =0;
4716  for(i=0; i< iFiltLength; i++)
4717  {
4718    dsum= ((Double)ppdE[i][i]) * pdcoeff[i];
4719    for(j=i+1; j< iFiltLength; j++)
4720    {
4721      dsum += (Double)(2*ppdE[i][j])* pdcoeff[j];
4722    }
4723
4724    dDist += ((dsum - 2.0 * pdy[i])* pdcoeff[i] );
4725  }
4726
4727
4728  UInt uiShift = g_uiBitIncrement<<1;
4729  if(dDist < 0)
4730  {
4731    iDist = -(((Int64)(-dDist + 0.5)) >> uiShift);
4732  }
4733  else //dDist >=0
4734  {
4735    iDist= ((Int64)(dDist+0.5)) >> uiShift;
4736  }
4737
4738  return iDist;
4739
4740}
4741
4742
4743
4744//! \}
Note: See TracBrowser for help on using the repository browser.