source: 3DVCSoftware/trunk/source/Lib/TLibEncoder/TEncAdaptiveLoopFilter.cpp @ 5

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

Clean version with cfg-files

  • Property svn:eol-style set to native
File size: 143.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-2011, ISO/IEC
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are met:
11 *
12 *  * Redistributions of source code must retain the above copyright notice,
13 *    this list of conditions and the following disclaimer.
14 *  * Redistributions in binary form must reproduce the above copyright notice,
15 *    this list of conditions and the following disclaimer in the documentation
16 *    and/or other materials provided with the distribution.
17 *  * Neither the name of the ISO/IEC nor the names of its contributors may
18 *    be used to endorse or promote products derived from this software without
19 *    specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
31 * THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34
35
36/** \file     TEncAdaptiveLoopFilter.cpp
37 \brief    estimation part of adaptive loop filter class
38 */
39#include "TEncAdaptiveLoopFilter.h"
40#include <string.h>
41#include <stdlib.h>
42#include <stdio.h>
43#include <math.h>
44
45// ====================================================================================================================
46// Constants
47// ====================================================================================================================
48
49#define ALF_NUM_OF_REDESIGN 3
50
51// ====================================================================================================================
52// Tables
53// ====================================================================================================================
54
55const Int TEncAdaptiveLoopFilter::m_aiSymmetricArray9x9[81] =
56{
57   0,  1,  2,  3,  4,  5,  6,  7,  8,
58   9, 10, 11, 12, 13, 14, 15, 16, 17,
59  18, 19, 20, 21, 22, 23, 24, 25, 26,
60  27, 28, 29, 30, 31, 32, 33, 34, 35,
61  36, 37, 38, 39, 40, 39, 38, 37, 36,
62  35, 34, 33, 32, 31, 30, 29, 28, 27,
63  26, 25, 24, 23, 22, 21, 20, 19, 18,
64  17, 16, 15, 14, 13, 12, 11, 10,  9,
65   8,  7,  6,  5,  4,  3,  2,  1,  0
66};
67
68const Int TEncAdaptiveLoopFilter::m_aiSymmetricArray7x7[49] =
69{
70  0,  1,  2,  3,  4,  5,  6,
71  7,  8,  9, 10, 11, 12, 13,
72  14, 15, 16, 17, 18, 19, 20,
73  21, 22, 23, 24, 23, 22, 21,
74  20, 19, 18, 17, 16, 15, 14,
75  13, 12, 11, 10,  9,  8,  7,
76  6,  5,  4,  3,  2,  1,  0,
77};
78
79const Int TEncAdaptiveLoopFilter::m_aiSymmetricArray5x5[25] =
80{
81  0,  1,  2,  3,  4,
82  5,  6,  7,  8,  9,
83  10, 11, 12, 11, 10,
84  9,  8,  7,  6,  5,
85  4,  3,  2,  1,  0,
86};
87
88#if TI_ALF_MAX_VSIZE_7
89const Int TEncAdaptiveLoopFilter::m_aiSymmetricArray9x7[63] =
90{
91   0,  1,  2,  3,  4,  5,  6,  7,  8,
92   9, 10, 11, 12, 13, 14, 15, 16, 17,
93  18, 19, 20, 21, 22, 23, 24, 25, 26,
94  27, 28, 29, 30, 31, 30, 29, 28, 27,
95  26, 25, 24, 23, 22, 21, 20, 19, 18,
96  17, 16, 15, 14, 13, 12, 11, 10,  9,
97   8,  7,  6,  5,  4,  3,  2,  1,  0
98};
99#endif
100
101#if MQT_ALF_NPASS
102#if TI_ALF_MAX_VSIZE_7
103Int TEncAdaptiveLoopFilter::m_aiTapPos9x9_In9x9Sym[21] =
104#else
105Int TEncAdaptiveLoopFilter::m_aiTapPos9x9_In9x9Sym[22] =
106#endif
107{
108#if TI_ALF_MAX_VSIZE_7
109                  0,  1,  2,
110              3,  4,  5,  6,  7,
111          8,  9, 10, 11, 12, 13, 14,
112     15, 16, 17, 18, 19, 20
113#else
114                   0,
115               1,  2,  3,
116           4,  5,  6,  7,  8,
117       9, 10, 11, 12, 13, 14, 15,
118  16, 17, 18, 19, 20, 21
119#endif
120};
121
122Int TEncAdaptiveLoopFilter::m_aiTapPos7x7_In9x9Sym[14] =
123{                 
124#if TI_ALF_MAX_VSIZE_7
125                  1,   
126              4,  5,  6,   
127          9, 10, 11, 12, 13,   
128     16, 17, 18, 19, 20
129
130#else
131
132               2,
133           5,  6,  7,
134      10, 11, 12, 13, 14,
135  17, 18, 19, 20, 21
136#endif
137};
138
139Int TEncAdaptiveLoopFilter::m_aiTapPos5x5_In9x9Sym[8]  =
140{
141
142#if TI_ALF_MAX_VSIZE_7
143            5,
144       10, 11, 12, 
145   17, 18, 19, 20
146#else
147           6,
148      11, 12, 13,
149  18, 19, 20, 21
150
151#endif
152
153};
154
155Int* TEncAdaptiveLoopFilter::m_iTapPosTabIn9x9Sym[NO_TEST_FILT] =
156{
157  m_aiTapPos9x9_In9x9Sym, m_aiTapPos7x7_In9x9Sym, m_aiTapPos5x5_In9x9Sym
158};
159#endif
160
161// ====================================================================================================================
162// Constructor / destructor
163// ====================================================================================================================
164
165TEncAdaptiveLoopFilter::TEncAdaptiveLoopFilter()
166{
167  m_ppdAlfCorr = NULL;
168  m_pdDoubleAlfCoeff = NULL;
169  m_pcPic = NULL;
170  m_pcEntropyCoder = NULL;
171  m_pcBestAlfParam = NULL;
172  m_pcTempAlfParam = NULL;
173  m_pcPicYuvBest = NULL;
174  m_pcPicYuvTmp = NULL;
175#if MTK_NONCROSS_INLOOP_FILTER
176  m_pcSliceYuvTmp = NULL;
177#endif
178#if MQT_BA_RA && MQT_ALF_NPASS
179  m_aiFilterCoeffSaved = NULL;
180#endif
181}
182
183// ====================================================================================================================
184// Public member functions
185// ====================================================================================================================
186
187#if MQT_BA_RA && MQT_ALF_NPASS
188Void TEncAdaptiveLoopFilter::createAlfGlobalBuffers(Int iALFEncodePassReduction)
189{
190  if(iALFEncodePassReduction)
191  {
192    for(Int i=0; i< NUM_ALF_CLASS_METHOD; i++)
193    {
194      m_aiFilterCoeffSavedMethods[i] = new Int**[9];
195      for(Int j=0; j< 9; j++)
196      {
197        m_aiFilterCoeffSavedMethods[i][j] = new Int*[NO_VAR_BINS];
198        for(Int k=0; k< NO_VAR_BINS; k++)
199        {
200          m_aiFilterCoeffSavedMethods[i][j][k] = new Int[MAX_SQR_FILT_LENGTH];
201        }
202      }
203    }
204
205  }
206}
207
208Void TEncAdaptiveLoopFilter::destroyAlfGlobalBuffers()
209{
210  if(m_iALFEncodePassReduction)
211  {
212    for(Int i=0; i< NUM_ALF_CLASS_METHOD; i++)
213    {
214      for(Int j=0; j< 9; j++)
215      {
216        for(Int k=0; k< NO_VAR_BINS; k++)
217        {
218          delete[] m_aiFilterCoeffSavedMethods[i][j][k];
219        }
220        delete[] m_aiFilterCoeffSavedMethods[i][j];
221      }
222      delete[] m_aiFilterCoeffSavedMethods[i];
223    }
224
225  }
226
227}
228#endif
229
230/**
231 \param pcPic           picture (TComPic) pointer
232 \param pcEntropyCoder  entropy coder class
233 */
234Void TEncAdaptiveLoopFilter::startALFEnc( TComPic* pcPic, TEncEntropy* pcEntropyCoder )
235{
236  m_pcPic = pcPic;
237  m_pcEntropyCoder = pcEntropyCoder;
238 
239  m_eSliceType = pcPic->getSlice(0)->getSliceType();
240  m_iPicNalReferenceIdc = (pcPic->getSlice(0)->isReferenced() ? 1 :0);
241 
242  m_uiNumSCUInCU = m_pcPic->getNumPartInCU();
243 
244  xInitParam();
245  xCreateTmpAlfCtrlFlags();
246 
247  Int iWidth = pcPic->getPicYuvOrg()->getWidth();
248  Int iHeight = pcPic->getPicYuvOrg()->getHeight();
249 
250  m_pcPicYuvTmp = new TComPicYuv();
251  m_pcPicYuvTmp->createLuma(iWidth, iHeight, g_uiMaxCUWidth, g_uiMaxCUHeight, g_uiMaxCUDepth);
252  m_pcPicYuvBest = pcPic->getPicYuvPred();
253 
254  m_pcBestAlfParam = new ALFParam;
255  m_pcTempAlfParam = new ALFParam;
256  allocALFParam(m_pcBestAlfParam);
257  allocALFParam(m_pcTempAlfParam);
258  m_im_width = iWidth;
259  m_im_height = iHeight;
260 
261  // init qc_filter
262  initMatrix4D_double(&m_EGlobalSym, NO_TEST_FILT,  NO_VAR_BINS, MAX_SQR_FILT_LENGTH, MAX_SQR_FILT_LENGTH);
263  initMatrix3D_double(&m_yGlobalSym, NO_TEST_FILT, NO_VAR_BINS, MAX_SQR_FILT_LENGTH); 
264  initMatrix_int(&m_filterCoeffSymQuant, NO_VAR_BINS, MAX_SQR_FILT_LENGTH); 
265 
266  m_pixAcc = (double *) calloc(NO_VAR_BINS, sizeof(double));
267#if !MQT_BA_RA
268  get_mem2Dpel(&m_varImg, m_im_height, m_im_width);
269#endif
270  get_mem2Dpel(&m_maskImg, m_im_height, m_im_width);
271 
272  initMatrix_double(&m_E_temp, MAX_SQR_FILT_LENGTH, MAX_SQR_FILT_LENGTH);//
273  m_y_temp = (double *) calloc(MAX_SQR_FILT_LENGTH, sizeof(double));//
274  initMatrix3D_double(&m_E_merged, NO_VAR_BINS, MAX_SQR_FILT_LENGTH, MAX_SQR_FILT_LENGTH);//
275  initMatrix_double(&m_y_merged, NO_VAR_BINS, MAX_SQR_FILT_LENGTH); //
276  m_pixAcc_merged = (double *) calloc(NO_VAR_BINS, sizeof(double));//
277 
278  m_filterCoeffQuantMod = (int *) calloc(MAX_SQR_FILT_LENGTH, sizeof(int));//
279  m_filterCoeff = (double *) calloc(MAX_SQR_FILT_LENGTH, sizeof(double));//
280  m_filterCoeffQuant = (int *) calloc(MAX_SQR_FILT_LENGTH, sizeof(int));//
281  initMatrix_int(&m_diffFilterCoeffQuant, NO_VAR_BINS, MAX_SQR_FILT_LENGTH);//
282  initMatrix_int(&m_FilterCoeffQuantTemp, NO_VAR_BINS, MAX_SQR_FILT_LENGTH);//
283 
284  m_tempALFp = new ALFParam;
285  allocALFParam(m_tempALFp);
286  m_pcDummyEntropyCoder = m_pcEntropyCoder;
287
288#if MTK_NONCROSS_INLOOP_FILTER
289  if( m_bUseNonCrossALF )
290  {
291    m_pcSliceYuvTmp = new TComPicYuv();
292    m_pcSliceYuvTmp->create(iWidth, iHeight, g_uiMaxCUWidth, g_uiMaxCUHeight, g_uiMaxCUDepth);
293  }
294#endif
295
296
297}
298
299Void TEncAdaptiveLoopFilter::endALFEnc()
300{
301  xUninitParam();
302  xDestroyTmpAlfCtrlFlags();
303 
304  m_pcPicYuvTmp->destroyLuma();
305  delete m_pcPicYuvTmp;
306  m_pcPicYuvTmp = NULL;
307  m_pcPic = NULL;
308  m_pcEntropyCoder = NULL;
309 
310  freeALFParam(m_pcBestAlfParam);
311  freeALFParam(m_pcTempAlfParam);
312  delete m_pcBestAlfParam;
313  delete m_pcTempAlfParam;
314  // delete qc filters
315  destroyMatrix4D_double(m_EGlobalSym, NO_TEST_FILT,  NO_VAR_BINS);
316  destroyMatrix3D_double(m_yGlobalSym, NO_TEST_FILT);
317  destroyMatrix_int(m_filterCoeffSymQuant);
318 
319  free(m_pixAcc);
320#if !MQT_BA_RA
321  free_mem2Dpel(m_varImg);
322#endif
323  free_mem2Dpel(m_maskImg);
324 
325  destroyMatrix3D_double(m_E_merged, NO_VAR_BINS);
326  destroyMatrix_double(m_y_merged);
327  destroyMatrix_double(m_E_temp);
328  free(m_pixAcc_merged);
329 
330  free(m_filterCoeffQuantMod);
331  free(m_y_temp);
332 
333  free(m_filterCoeff);
334  free(m_filterCoeffQuant);
335  destroyMatrix_int(m_diffFilterCoeffQuant);
336  destroyMatrix_int(m_FilterCoeffQuantTemp);
337 
338  freeALFParam(m_tempALFp);
339  delete m_tempALFp;
340
341#if MTK_NONCROSS_INLOOP_FILTER
342
343  if(m_bUseNonCrossALF)
344  {
345    m_pcSliceYuvTmp->destroy();
346    delete m_pcSliceYuvTmp;
347    m_pcSliceYuvTmp = NULL;
348  }
349#endif
350
351}
352
353/**
354 \param pcAlfParam           ALF parameter
355 \param dLambda              lambda value for RD cost computation
356 \retval ruiDist             distortion
357 \retval ruiBits             required bits
358 \retval ruiMaxAlfCtrlDepth  optimal partition depth
359 */
360Void TEncAdaptiveLoopFilter::ALFProcess( ALFParam* pcAlfParam, Double dLambda, UInt64& ruiDist, UInt64& ruiBits, UInt& ruiMaxAlfCtrlDepth )
361{
362  Int tap, num_coef;
363 
364  // set global variables
365  tap         = ALF_MAX_NUM_TAP;
366#if TI_ALF_MAX_VSIZE_7
367  Int tapV = TComAdaptiveLoopFilter::ALFTapHToTapV(tap);
368  num_coef = (tap * tapV + 1) >> 1;
369#else
370  num_coef    = (tap*tap+1)>>1;
371#endif
372  num_coef    = num_coef + 1; // DC offset
373 
374  // set lambda
375  m_dLambdaLuma   = dLambda;
376  m_dLambdaChroma = dLambda;
377 
378  TComPicYuv* pcPicOrg = m_pcPic->getPicYuvOrg();
379 
380  // extend image for filtering
381  TComPicYuv* pcPicYuvRec    = m_pcPic->getPicYuvRec();
382  TComPicYuv* pcPicYuvExtRec = m_pcTempPicYuv;
383 
384  pcPicYuvRec->copyToPic(pcPicYuvExtRec);
385#if MTK_NONCROSS_INLOOP_FILTER
386  if(!m_bUseNonCrossALF)
387  {
388#endif 
389  pcPicYuvExtRec->setBorderExtension( false );
390  pcPicYuvExtRec->extendPicBorder   ();
391#if MTK_NONCROSS_INLOOP_FILTER
392  }
393#endif 
394 
395  // set min cost
396  UInt64 uiMinRate = MAX_INT;
397  UInt64 uiMinDist = MAX_INT;
398  Double dMinCost  = MAX_DOUBLE;
399 
400  UInt64  uiOrigRate;
401  UInt64  uiOrigDist;
402  Double  dOrigCost;
403 
404  // calc original cost
405  xCalcRDCost( pcPicOrg, pcPicYuvRec, NULL, uiOrigRate, uiOrigDist, dOrigCost );
406  m_pcBestAlfParam->alf_flag = 0;
407  m_pcBestAlfParam->cu_control_flag = 0;
408 
409  // initialize temp_alfps
410  m_pcTempAlfParam->alf_flag        = 1;
411  m_pcTempAlfParam->tap             = tap;
412#if TI_ALF_MAX_VSIZE_7
413  m_pcTempAlfParam->tapV            = tapV;
414#endif
415  m_pcTempAlfParam->num_coeff       = num_coef;
416  m_pcTempAlfParam->chroma_idc      = 0;
417  m_pcTempAlfParam->cu_control_flag = 0;
418 
419#if MQT_ALF_NPASS
420  setALFEncodingParam(m_pcPic);
421#endif
422
423  // adaptive in-loop wiener filtering
424  xEncALFLuma_qc( pcPicOrg, pcPicYuvExtRec, pcPicYuvRec, uiMinRate, uiMinDist, dMinCost );
425 
426  // cu-based filter on/off control
427  xCUAdaptiveControl_qc( pcPicOrg, pcPicYuvExtRec, pcPicYuvRec, uiMinRate, uiMinDist, dMinCost );
428 
429  // adaptive tap-length
430  xFilterTapDecision_qc( pcPicOrg, pcPicYuvExtRec, pcPicYuvRec, uiMinRate, uiMinDist, dMinCost );
431 
432  // compute RD cost
433  xCalcRDCost( pcPicOrg, pcPicYuvRec, m_pcBestAlfParam, uiMinRate, uiMinDist, dMinCost );
434 
435  // compare RD cost to non-ALF case
436  if( dMinCost < dOrigCost )
437  {
438    m_pcBestAlfParam->alf_flag = 1;
439   
440    ruiBits = uiMinRate;
441    ruiDist = uiMinDist;
442  }
443  else
444  {
445    m_pcBestAlfParam->alf_flag        = 0;
446    m_pcBestAlfParam->cu_control_flag = 0;
447   
448    uiMinRate = uiOrigRate;
449    uiMinDist = uiOrigDist;
450    dMinCost = dMinCost;
451   
452    m_pcEntropyCoder->setAlfCtrl(false);
453    pcPicYuvExtRec->copyToPicLuma(pcPicYuvRec);
454   
455    ruiBits = uiOrigRate;
456    ruiDist = uiOrigDist;
457  }
458 
459  // if ALF works
460  if( m_pcBestAlfParam->alf_flag )
461  {
462    // predict ALF coefficients
463    predictALFCoeff( m_pcBestAlfParam );
464   
465    // do additional ALF process for chroma
466    xEncALFChroma( uiMinRate, pcPicOrg, pcPicYuvExtRec, pcPicYuvRec, ruiDist, ruiBits );
467  }
468 
469  // copy to best storage
470  copyALFParam(pcAlfParam, m_pcBestAlfParam);
471 
472  // store best depth
473  ruiMaxAlfCtrlDepth = m_pcEntropyCoder->getMaxAlfCtrlDepth();
474}
475
476// ====================================================================================================================
477// Protected member functions
478// ====================================================================================================================
479
480Void TEncAdaptiveLoopFilter::xEncALFChroma( UInt64 uiLumaRate, TComPicYuv* pcPicOrg, TComPicYuv* pcPicDec, TComPicYuv* pcPicRest, UInt64& ruiDist, UInt64& ruiBits )
481{
482  // restriction for non-referenced B-slice
483  if (m_eSliceType == B_SLICE && m_iPicNalReferenceIdc == 0)
484  {
485    return;
486  }
487 
488  Int tap, num_coef;
489 
490  // set global variables
491  tap         = ALF_MAX_NUM_TAP_C;
492  num_coef    = (tap*tap+1)>>1;
493  num_coef    = num_coef + 1; // DC offset
494 
495  // set min cost
496  UInt64 uiMinRate = uiLumaRate;
497  UInt64 uiMinDist = MAX_INT;
498  Double dMinCost  = MAX_DOUBLE;
499 
500  // calc original cost
501  copyALFParam(m_pcTempAlfParam, m_pcBestAlfParam);
502  xCalcRDCostChroma(pcPicOrg, pcPicRest, m_pcTempAlfParam, uiMinRate, uiMinDist, dMinCost);
503 
504  // initialize temp_alfps
505  m_pcTempAlfParam->chroma_idc = 3;
506  m_pcTempAlfParam->tap_chroma       = tap;
507  m_pcTempAlfParam->num_coeff_chroma = num_coef;
508 
509  // Adaptive in-loop wiener filtering for chroma
510  xFilteringFrameChroma(pcPicOrg, pcPicDec, pcPicRest);
511 
512  // filter on/off decision for chroma
513  Int iCWidth = (pcPicOrg->getWidth()>>1);
514  Int iCHeight = (pcPicOrg->getHeight()>>1);
515  Int iCStride = pcPicOrg->getCStride();
516  UInt64 uiFiltDistCb = xCalcSSD(pcPicOrg->getCbAddr(), pcPicRest->getCbAddr(), iCWidth, iCHeight, iCStride);
517  UInt64 uiFiltDistCr = xCalcSSD(pcPicOrg->getCrAddr(), pcPicRest->getCrAddr(), iCWidth, iCHeight, iCStride);
518  UInt64 uiOrgDistCb = xCalcSSD(pcPicOrg->getCbAddr(), pcPicDec->getCbAddr(), iCWidth, iCHeight, iCStride);
519  UInt64 uiOrgDistCr = xCalcSSD(pcPicOrg->getCrAddr(), pcPicDec->getCrAddr(), iCWidth, iCHeight, iCStride);
520 
521  m_pcTempAlfParam->chroma_idc = 0;
522  if(uiOrgDistCb > uiFiltDistCb)
523    m_pcTempAlfParam->chroma_idc += 2;
524  if(uiOrgDistCr  > uiFiltDistCr )
525    m_pcTempAlfParam->chroma_idc += 1;
526 
527  if(m_pcTempAlfParam->chroma_idc)
528  {
529    if(m_pcTempAlfParam->chroma_idc!=3)
530    {
531      // chroma filter re-design
532      xFilteringFrameChroma(pcPicOrg, pcPicDec, pcPicRest);
533    }
534   
535    UInt64 uiRate, uiDist;
536    Double dCost;
537    xCalcRDCostChroma(pcPicOrg, pcPicRest, m_pcTempAlfParam, uiRate, uiDist, dCost);
538   
539    if( dCost < dMinCost )
540    {
541      copyALFParam(m_pcBestAlfParam, m_pcTempAlfParam);
542      predictALFCoeffChroma(m_pcBestAlfParam);
543     
544      ruiBits += uiRate;
545      ruiDist += uiDist;
546    }
547    else
548    {
549      m_pcBestAlfParam->chroma_idc = 0;
550     
551      if((m_pcTempAlfParam->chroma_idc>>1)&0x01)
552        pcPicDec->copyToPicCb(pcPicRest);
553      if(m_pcTempAlfParam->chroma_idc&0x01)
554        pcPicDec->copyToPicCr(pcPicRest);
555     
556      ruiBits += uiMinRate;
557      ruiDist += uiMinDist;
558    }
559  }
560  else
561  {
562    m_pcBestAlfParam->chroma_idc = 0;
563   
564    ruiBits += uiMinRate;
565    ruiDist += uiMinDist;
566   
567    pcPicDec->copyToPicCb(pcPicRest);
568    pcPicDec->copyToPicCr(pcPicRest);
569  }
570}
571
572// ====================================================================================================================
573// Private member functions
574// ====================================================================================================================
575
576Void TEncAdaptiveLoopFilter::xInitParam()
577{
578  Int i, j;
579 
580  if (m_ppdAlfCorr != NULL)
581  {
582    for (i = 0; i < ALF_MAX_NUM_COEF; i++)
583    {
584      for (j = 0; j < ALF_MAX_NUM_COEF+1; j++)
585      {
586        m_ppdAlfCorr[i][j] = 0;
587      }
588    }
589  }
590  else
591  {
592    m_ppdAlfCorr = new Double*[ALF_MAX_NUM_COEF];
593    for (i = 0; i < ALF_MAX_NUM_COEF; i++)
594    {
595      m_ppdAlfCorr[i] = new Double[ALF_MAX_NUM_COEF+1];
596      for (j = 0; j < ALF_MAX_NUM_COEF+1; j++)
597      {
598        m_ppdAlfCorr[i][j] = 0;
599      }
600    }
601  }
602 
603  if (m_pdDoubleAlfCoeff != NULL)
604  {
605    for (i = 0; i < ALF_MAX_NUM_COEF; i++)
606    {
607      m_pdDoubleAlfCoeff[i] = 0;
608    }
609  }
610  else
611  {
612    m_pdDoubleAlfCoeff = new Double[ALF_MAX_NUM_COEF];
613    for (i = 0; i < ALF_MAX_NUM_COEF; i++)
614    {
615      m_pdDoubleAlfCoeff[i] = 0;
616    }
617  }
618}
619
620Void TEncAdaptiveLoopFilter::xUninitParam()
621{
622  Int i;
623 
624  if (m_ppdAlfCorr != NULL)
625  {
626    for (i = 0; i < ALF_MAX_NUM_COEF; i++)
627    {
628      delete[] m_ppdAlfCorr[i];
629      m_ppdAlfCorr[i] = NULL;
630    }
631    delete[] m_ppdAlfCorr;
632    m_ppdAlfCorr = NULL;
633  }
634 
635  if (m_pdDoubleAlfCoeff != NULL)
636  {
637    delete[] m_pdDoubleAlfCoeff;
638    m_pdDoubleAlfCoeff = NULL;
639  }
640}
641
642Void TEncAdaptiveLoopFilter::xCreateTmpAlfCtrlFlags()
643{
644  for( UInt uiCUAddr = 0; uiCUAddr < m_pcPic->getNumCUsInFrame() ; uiCUAddr++ )
645  {
646    TComDataCU* pcCU = m_pcPic->getCU( uiCUAddr );
647    pcCU->createTmpAlfCtrlFlag();
648  }
649}
650
651Void TEncAdaptiveLoopFilter::xDestroyTmpAlfCtrlFlags()
652{
653  for( UInt uiCUAddr = 0; uiCUAddr < m_pcPic->getNumCUsInFrame() ; uiCUAddr++ )
654  {
655    TComDataCU* pcCU = m_pcPic->getCU( uiCUAddr );
656    pcCU->destroyTmpAlfCtrlFlag();
657  }
658}
659
660Void TEncAdaptiveLoopFilter::xCopyTmpAlfCtrlFlagsTo()
661{
662  for( UInt uiCUAddr = 0; uiCUAddr < m_pcPic->getNumCUsInFrame() ; uiCUAddr++ )
663  {
664    TComDataCU* pcCU = m_pcPic->getCU( uiCUAddr );
665    pcCU->copyAlfCtrlFlagFromTmp();
666  }
667}
668
669Void TEncAdaptiveLoopFilter::xCopyTmpAlfCtrlFlagsFrom()
670{
671  for( UInt uiCUAddr = 0; uiCUAddr < m_pcPic->getNumCUsInFrame() ; uiCUAddr++ )
672  {
673    TComDataCU* pcCU = m_pcPic->getCU( uiCUAddr );
674    pcCU->copyAlfCtrlFlagToTmp();
675  }
676}
677
678Void TEncAdaptiveLoopFilter::xEncodeCUAlfCtrlFlags()
679{
680  for( UInt uiCUAddr = 0; uiCUAddr < m_pcPic->getNumCUsInFrame() ; uiCUAddr++ )
681  {
682    TComDataCU* pcCU = m_pcPic->getCU( uiCUAddr );
683    xEncodeCUAlfCtrlFlag(pcCU, 0, 0);
684  }
685}
686
687Void TEncAdaptiveLoopFilter::xEncodeCUAlfCtrlFlag(TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth)
688{
689  Bool bBoundary = false;
690  UInt uiLPelX   = pcCU->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiAbsPartIdx] ];
691  UInt uiRPelX   = uiLPelX + (g_uiMaxCUWidth>>uiDepth)  - 1;
692  UInt uiTPelY   = pcCU->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiAbsPartIdx] ];
693  UInt uiBPelY   = uiTPelY + (g_uiMaxCUHeight>>uiDepth) - 1;
694 
695#if AD_HOCS_SLICES 
696  if( ( uiRPelX >= pcCU->getSlice()->getSPS()->getWidth() ) || ( uiBPelY >= pcCU->getSlice()->getSPS()->getHeight() ) )
697#else 
698  if( ( uiRPelX >= pcCU->getSlice()->getSPS()->getWidth() ) || ( uiBPelY >= pcCU->getSlice()->getSPS()->getHeight() ) )
699#endif 
700  {
701    bBoundary = true;
702  }
703 
704  if( ( ( uiDepth < pcCU->getDepth( uiAbsPartIdx ) ) && ( uiDepth < (g_uiMaxCUDepth-g_uiAddCUDepth) ) ) || bBoundary )
705  {
706    UInt uiQNumParts = ( m_pcPic->getNumPartInCU() >> (uiDepth<<1) )>>2;
707    for ( UInt uiPartUnitIdx = 0; uiPartUnitIdx < 4; uiPartUnitIdx++, uiAbsPartIdx+=uiQNumParts )
708    {
709      uiLPelX   = pcCU->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiAbsPartIdx] ];
710      uiTPelY   = pcCU->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiAbsPartIdx] ];
711     
712#if AD_HOCS_SLICES     
713      if( ( uiLPelX < pcCU->getSlice()->getSPS()->getWidth() ) && ( uiTPelY < pcCU->getSlice()->getSPS()->getHeight() ) )
714#else
715      if( ( uiLPelX < pcCU->getSlice()->getSPS()->getWidth() ) && ( uiTPelY < pcCU->getSlice()->getSPS()->getHeight() ) )
716#endif     
717        xEncodeCUAlfCtrlFlag(pcCU, uiAbsPartIdx, uiDepth+1);
718    }
719    return;
720  }
721 
722  m_pcEntropyCoder->encodeAlfCtrlFlag(pcCU, uiAbsPartIdx);
723}
724#if MTK_NONCROSS_INLOOP_FILTER
725Void TEncAdaptiveLoopFilter::xCalcCorrelationFunc(Int ypos, Int xpos, Pel* pOrg, Pel* pCmp, Int iTap, Int iWidth, Int iHeight, Int iOrgStride, Int iCmpStride, Bool bSymmCopyBlockMatrix)
726#else
727Void TEncAdaptiveLoopFilter::xCalcCorrelationFunc(Pel* pOrg, Pel* pCmp, Int iTap, Int iWidth, Int iHeight, Int iOrgStride, Int iCmpStride)
728#endif
729{
730  //Patch should be extended before this point................
731  //ext_offset  = tap>>1;
732 
733#if TI_ALF_MAX_VSIZE_7
734  Int iTapV   = TComAdaptiveLoopFilter::ALFTapHToTapV(iTap);
735  Int N       = (iTap * iTapV + 1) >> 1;
736  Int offsetV = iTapV >> 1;
737#else
738  Int N      = (iTap*iTap+1)>>1;
739#endif
740  Int offset = iTap>>1;
741 
742  const Int* pFiltPos;
743 
744  switch(iTap)
745  {
746    case 5:
747      pFiltPos = m_aiSymmetricArray5x5;
748      break;
749    case 7:
750      pFiltPos = m_aiSymmetricArray7x7;
751      break;
752    case 9:
753#if TI_ALF_MAX_VSIZE_7
754      pFiltPos = m_aiSymmetricArray9x7;
755#else
756      pFiltPos = m_aiSymmetricArray9x9;
757#endif
758      break;
759    default:
760#if TI_ALF_MAX_VSIZE_7
761      pFiltPos = m_aiSymmetricArray9x7;
762#else
763      pFiltPos = m_aiSymmetricArray9x9;
764#endif
765      assert(0);
766      break;
767  }
768 
769  Pel* pTerm = new Pel[N];
770 
771  Int i, j;
772#if MTK_NONCROSS_INLOOP_FILTER
773  for (Int y = ypos; y < ypos + iHeight; y++)
774  {
775    for (Int x = xpos; x < xpos + iWidth; x++)
776    {
777#else   
778  for (Int y = 0; y < iHeight; y++)
779  {
780    for (Int x = 0; x < iWidth; x++)
781    {
782#endif
783      i = 0;
784      ::memset(pTerm, 0, sizeof(Pel)*N);
785#if TI_ALF_MAX_VSIZE_7
786      for (Int yy = y - offsetV; yy <= y + offsetV; yy++)
787#else
788      for(Int yy=y-offset; yy<=y+offset; yy++)
789#endif
790      {
791        for(Int xx=x-offset; xx<=x+offset; xx++)
792        {
793          pTerm[pFiltPos[i]] += pCmp[xx + yy*iCmpStride];
794          i++;
795        }
796      }
797     
798      for(j=0; j<N; j++)
799      {
800        m_ppdAlfCorr[j][j] += pTerm[j]*pTerm[j];
801        for(i=j+1; i<N; i++)
802          m_ppdAlfCorr[j][i] += pTerm[j]*pTerm[i];
803       
804        // DC offset
805        m_ppdAlfCorr[j][N]   += pTerm[j];
806        m_ppdAlfCorr[j][N+1] += pOrg[x+y*iOrgStride]*pTerm[j];
807      }
808      // DC offset
809      for(i=0; i<N; i++)
810        m_ppdAlfCorr[N][i] += pTerm[i];
811      m_ppdAlfCorr[N][N]   += 1;
812      m_ppdAlfCorr[N][N+1] += pOrg[x+y*iOrgStride];
813    }
814  }
815#if MTK_NONCROSS_INLOOP_FILTER
816  if(bSymmCopyBlockMatrix)
817  {
818#endif
819  for(j=0; j<N-1; j++)
820  {
821    for(i=j+1; i<N; i++)
822      m_ppdAlfCorr[i][j] = m_ppdAlfCorr[j][i];
823  }
824#if MTK_NONCROSS_INLOOP_FILTER
825  }
826#endif
827
828  delete[] pTerm;
829  pTerm = NULL;
830}
831
832#if IBDI_DISTORTION
833UInt64 TEncAdaptiveLoopFilter::xCalcSSD(Pel* pOrg, Pel* pCmp, Int iWidth, Int iHeight, Int iStride )
834{
835  UInt64 uiSSD = 0;
836  Int x, y;
837
838  Int iShift = g_uiBitIncrement;
839  Int iOffset = (g_uiBitIncrement>0)? (1<<(g_uiBitIncrement-1)):0;
840  Int iTemp;
841
842  for( y = 0; y < iHeight; y++ )
843  {
844    for( x = 0; x < iWidth; x++ )
845    {
846      iTemp = ((pOrg[x]+iOffset)>>iShift) - ((pCmp[x]+iOffset)>>iShift); uiSSD += iTemp * iTemp;
847    }
848    pOrg += iStride;
849    pCmp += iStride;
850  }
851
852  return uiSSD;;
853}
854#else
855UInt64 TEncAdaptiveLoopFilter::xCalcSSD(Pel* pOrg, Pel* pCmp, Int iWidth, Int iHeight, Int iStride )
856{
857  UInt64 uiSSD = 0;
858  Int x, y;
859 
860  UInt uiShift = g_uiBitIncrement<<1;
861  Int iTemp;
862 
863  for( y = 0; y < iHeight; y++ )
864  {
865    for( x = 0; x < iWidth; x++ )
866    {
867      iTemp = pOrg[x] - pCmp[x]; uiSSD += ( iTemp * iTemp ) >> uiShift;
868    }
869    pOrg += iStride;
870    pCmp += iStride;
871  }
872 
873  return uiSSD;;
874}
875#endif
876
877Int TEncAdaptiveLoopFilter::xGauss(Double **a, Int N)
878{
879  Int i, j, k;
880  Double t;
881 
882  for(k=0; k<N; k++)
883  {
884    if (a[k][k] <0.000001)
885      return 1;
886  }
887 
888  for(k=0; k<N-1; k++)
889  {
890    for(i=k+1;i<N; i++)
891    {
892      t=a[i][k]/a[k][k];
893      for(j=k+1; j<=N; j++)
894      {
895        a[i][j] -= t * a[k][j];
896        if(i==j && fabs(a[i][j])<0.000001) return 1;
897      }
898    }
899  }
900  for(i=N-1; i>=0; i--)
901  {
902    t = a[i][N];
903    for(j=i+1; j<N; j++)
904      t -= a[i][j] * a[j][N];
905    a[i][N] = t / a[i][i];
906  }
907  return 0;
908}
909
910Void TEncAdaptiveLoopFilter::xFilterCoefQuickSort( Double *coef_data, Int *coef_num, Int upper, Int lower )
911{
912  Double mid, tmp_data;
913  Int i, j, tmp_num;
914 
915  i = upper;
916  j = lower;
917  mid = coef_data[(lower+upper)>>1];
918  do
919  {
920    while( coef_data[i] < mid ) i++;
921    while( mid < coef_data[j] ) j--;
922    if( i <= j )
923    {
924      tmp_data = coef_data[i];
925      tmp_num  = coef_num[i];
926      coef_data[i] = coef_data[j];
927      coef_num[i]  = coef_num[j];
928      coef_data[j] = tmp_data;
929      coef_num[j]  = tmp_num;
930      i++;
931      j--;
932    }
933  } while( i <= j );
934  if ( upper < j ) xFilterCoefQuickSort(coef_data, coef_num, upper, j);
935  if ( i < lower ) xFilterCoefQuickSort(coef_data, coef_num, i, lower);
936}
937
938Void TEncAdaptiveLoopFilter::xQuantFilterCoef(Double* h, Int* qh, Int tap, int bit_depth)
939{
940  Int i, N;
941  Int max_value, min_value;
942  Double dbl_total_gain;
943  Int total_gain, q_total_gain;
944  Int upper, lower;
945  Double *dh;
946  Int    *nc;
947  const Int    *pFiltMag;
948 
949  switch(tap)
950  {
951    case 5:
952      pFiltMag = m_aiSymmetricMag5x5;
953      break;
954    case 7:
955      pFiltMag = m_aiSymmetricMag7x7;
956      break;
957    case 9:
958#if TI_ALF_MAX_VSIZE_7
959      pFiltMag = m_aiSymmetricMag9x7;
960#else
961      pFiltMag = m_aiSymmetricMag9x9;
962#endif
963      break;
964    default:
965#if TI_ALF_MAX_VSIZE_7
966      pFiltMag = m_aiSymmetricMag9x7;
967#else
968      pFiltMag = m_aiSymmetricMag9x9;
969#endif
970      assert(0);
971      break;
972  }
973 
974#if TI_ALF_MAX_VSIZE_7
975  Int tapV = TComAdaptiveLoopFilter::ALFTapHToTapV(tap);
976  N = (tap * tapV + 1) >> 1;
977#else
978  N = (tap*tap+1)>>1;
979#endif
980 
981  dh = new Double[N];
982  nc = new Int[N];
983 
984  max_value =   (1<<(1+ALF_NUM_BIT_SHIFT))-1;
985  min_value = 0-(1<<(1+ALF_NUM_BIT_SHIFT));
986 
987  dbl_total_gain=0.0;
988  q_total_gain=0;
989  for(i=0; i<N; i++)
990  {
991    if(h[i]>=0.0)
992      qh[i] =  (Int)( h[i]*(1<<ALF_NUM_BIT_SHIFT)+0.5);
993    else
994      qh[i] = -(Int)(-h[i]*(1<<ALF_NUM_BIT_SHIFT)+0.5);
995   
996    dh[i] = (Double)qh[i]/(Double)(1<<ALF_NUM_BIT_SHIFT) - h[i];
997    dh[i]*=pFiltMag[i];
998    dbl_total_gain += h[i]*pFiltMag[i];
999    q_total_gain   += qh[i]*pFiltMag[i];
1000    nc[i] = i;
1001  }
1002 
1003  // modification of quantized filter coefficients
1004  total_gain = (Int)(dbl_total_gain*(1<<ALF_NUM_BIT_SHIFT)+0.5);
1005 
1006  if( q_total_gain != total_gain )
1007  {
1008    xFilterCoefQuickSort(dh, nc, 0, N-1);
1009    if( q_total_gain > total_gain )
1010    {
1011      upper = N-1;
1012      while( q_total_gain > total_gain+1 )
1013      {
1014        i = nc[upper%N];
1015        qh[i]--;
1016        q_total_gain -= pFiltMag[i];
1017        upper--;
1018      }
1019      if( q_total_gain == total_gain+1 )
1020      {
1021        if(dh[N-1]>0)
1022          qh[N-1]--;
1023        else
1024        {
1025          i=nc[upper%N];
1026          qh[i]--;
1027          qh[N-1]++;
1028        }
1029      }
1030    }
1031    else if( q_total_gain < total_gain )
1032    {
1033      lower = 0;
1034      while( q_total_gain < total_gain-1 )
1035      {
1036        i=nc[lower%N];
1037        qh[i]++;
1038        q_total_gain += pFiltMag[i];
1039        lower++;
1040      }
1041      if( q_total_gain == total_gain-1 )
1042      {
1043        if(dh[N-1]<0)
1044          qh[N-1]++;
1045        else
1046        {
1047          i=nc[lower%N];
1048          qh[i]++;
1049          qh[N-1]--;
1050        }
1051      }
1052    }
1053  }
1054 
1055  // set of filter coefficients
1056  for(i=0; i<N; i++)
1057  {
1058    qh[i] = Max(min_value,Min(max_value, qh[i]));
1059  }
1060 
1061  // DC offset
1062  //  max_value = Min(  (1<<(3+Max(img_bitdepth_luma,img_bitdepth_chroma)))-1, (1<<14)-1);
1063  //  min_value = Max( -(1<<(3+Max(img_bitdepth_luma,img_bitdepth_chroma))),  -(1<<14)  );
1064  max_value = Min(  (1<<(3+g_uiBitDepth + g_uiBitIncrement))-1, (1<<14)-1);
1065  min_value = Max( -(1<<(3+g_uiBitDepth + g_uiBitIncrement)),  -(1<<14)  );
1066 
1067  qh[N] =  (h[N]>=0.0)? (Int)( h[N]*(1<<(ALF_NUM_BIT_SHIFT-bit_depth+8)) + 0.5) : -(Int)(-h[N]*(1<<(ALF_NUM_BIT_SHIFT-bit_depth+8)) + 0.5);
1068  qh[N] = Max(min_value,Min(max_value, qh[N]));
1069 
1070  delete[] dh;
1071  dh = NULL;
1072 
1073  delete[] nc;
1074  nc = NULL;
1075}
1076
1077Void TEncAdaptiveLoopFilter::xClearFilterCoefInt(Int* qh, Int N)
1078{
1079  // clear
1080  memset( qh, 0, sizeof( Int ) * N );
1081 
1082  // center pos
1083  qh[N-2]  = 1<<ALF_NUM_BIT_SHIFT;
1084}
1085
1086Void TEncAdaptiveLoopFilter::xCalcRDCost(ALFParam* pAlfParam, UInt64& ruiRate, UInt64 uiDist, Double& rdCost)
1087{
1088  if(pAlfParam != NULL)
1089  {
1090    Int* piTmpCoef;
1091    piTmpCoef = new Int[ALF_MAX_NUM_COEF];
1092   
1093    memcpy(piTmpCoef, pAlfParam->coeff, sizeof(Int)*pAlfParam->num_coeff);
1094   
1095    predictALFCoeff(pAlfParam);
1096   
1097    m_pcEntropyCoder->resetEntropy();
1098    m_pcEntropyCoder->resetBits();
1099    m_pcEntropyCoder->encodeAlfParam(pAlfParam);
1100   
1101    if(pAlfParam->cu_control_flag)
1102    {
1103#if TSB_ALF_HEADER
1104      m_pcEntropyCoder->encodeAlfCtrlParam(pAlfParam);
1105#else
1106      xEncodeCUAlfCtrlFlags();
1107#endif
1108    }
1109    ruiRate = m_pcEntropyCoder->getNumberOfWrittenBits();
1110    memcpy(pAlfParam->coeff, piTmpCoef, sizeof(int)*pAlfParam->num_coeff);
1111    delete[] piTmpCoef;
1112    piTmpCoef = NULL;
1113  }
1114  else
1115  {
1116    ruiRate = 1;
1117  }
1118 
1119  rdCost      = (Double)(ruiRate) * m_dLambdaLuma + (Double)(uiDist);
1120}
1121
1122Void TEncAdaptiveLoopFilter::xCalcRDCost(TComPicYuv* pcPicOrg, TComPicYuv* pcPicCmp, ALFParam* pAlfParam, UInt64& ruiRate, UInt64& ruiDist, Double& rdCost)
1123{
1124  if(pAlfParam != NULL)
1125  {
1126    Int* piTmpCoef;
1127    piTmpCoef = new Int[ALF_MAX_NUM_COEF];
1128   
1129    memcpy(piTmpCoef, pAlfParam->coeff, sizeof(Int)*pAlfParam->num_coeff);
1130   
1131    predictALFCoeff(pAlfParam);
1132   
1133    m_pcEntropyCoder->resetEntropy();
1134    m_pcEntropyCoder->resetBits();
1135    m_pcEntropyCoder->encodeAlfParam(pAlfParam);
1136   
1137    if(pAlfParam->cu_control_flag)
1138    {
1139#if TSB_ALF_HEADER
1140      m_pcEntropyCoder->encodeAlfCtrlParam(pAlfParam);
1141#else
1142      xEncodeCUAlfCtrlFlags();
1143#endif
1144    }
1145    ruiRate = m_pcEntropyCoder->getNumberOfWrittenBits();
1146    memcpy(pAlfParam->coeff, piTmpCoef, sizeof(int)*pAlfParam->num_coeff);
1147    delete[] piTmpCoef;
1148    piTmpCoef = NULL;
1149  }
1150  else
1151  {
1152    ruiRate = 1;
1153  }
1154 
1155  ruiDist     = xCalcSSD(pcPicOrg->getLumaAddr(), pcPicCmp->getLumaAddr(), pcPicOrg->getWidth(), pcPicOrg->getHeight(), pcPicOrg->getStride());
1156  rdCost      = (Double)(ruiRate) * m_dLambdaLuma + (Double)(ruiDist);
1157}
1158
1159Void TEncAdaptiveLoopFilter::xCalcRDCostChroma(TComPicYuv* pcPicOrg, TComPicYuv* pcPicCmp, ALFParam* pAlfParam, UInt64& ruiRate, UInt64& ruiDist, Double& rdCost)
1160{
1161  if(pAlfParam->chroma_idc)
1162  {
1163    Int* piTmpCoef;
1164    piTmpCoef = new Int[ALF_MAX_NUM_COEF_C];
1165   
1166    memcpy(piTmpCoef, pAlfParam->coeff_chroma, sizeof(Int)*pAlfParam->num_coeff_chroma);
1167   
1168    predictALFCoeffChroma(pAlfParam);
1169   
1170    m_pcEntropyCoder->resetEntropy();
1171    m_pcEntropyCoder->resetBits();
1172    m_pcEntropyCoder->encodeAlfParam(pAlfParam);
1173   
1174    if(pAlfParam->cu_control_flag)
1175    {
1176#if TSB_ALF_HEADER
1177      m_pcEntropyCoder->encodeAlfCtrlParam(pAlfParam);
1178#else
1179      xEncodeCUAlfCtrlFlags();
1180#endif
1181    }
1182    ruiRate = m_pcEntropyCoder->getNumberOfWrittenBits();
1183    memcpy(pAlfParam->coeff_chroma, piTmpCoef, sizeof(int)*pAlfParam->num_coeff_chroma);
1184    delete[] piTmpCoef;
1185    piTmpCoef = NULL;
1186  }
1187  ruiDist = 0;
1188  ruiDist += xCalcSSD(pcPicOrg->getCbAddr(), pcPicCmp->getCbAddr(), (pcPicOrg->getWidth()>>1), (pcPicOrg->getHeight()>>1), pcPicOrg->getCStride());
1189  ruiDist += xCalcSSD(pcPicOrg->getCrAddr(), pcPicCmp->getCrAddr(), (pcPicOrg->getWidth()>>1), (pcPicOrg->getHeight()>>1), pcPicOrg->getCStride());
1190  rdCost  = (Double)(ruiRate) * m_dLambdaChroma + (Double)(ruiDist);
1191}
1192
1193Void TEncAdaptiveLoopFilter::xFilteringFrameChroma(TComPicYuv* pcPicOrg, TComPicYuv* pcPicDec, TComPicYuv* pcPicRest)
1194{
1195  Int    i, tap, N, err_code;
1196  Int* qh;
1197 
1198  tap  = m_pcTempAlfParam->tap_chroma;
1199  N    = m_pcTempAlfParam->num_coeff_chroma;
1200  qh   = m_pcTempAlfParam->coeff_chroma;
1201 
1202  // initialize correlation
1203  for(i=0; i<N; i++)
1204    memset(m_ppdAlfCorr[i], 0, sizeof(Double)*(N+1));
1205 
1206  if ((m_pcTempAlfParam->chroma_idc>>1)&0x01)
1207  {
1208    Pel* pOrg = pcPicOrg->getCbAddr();
1209    Pel* pCmp = pcPicDec->getCbAddr();
1210#if MTK_NONCROSS_INLOOP_FILTER
1211    if(!m_bUseNonCrossALF)
1212      xCalcCorrelationFunc(0, 0, pOrg, pCmp, tap, (pcPicOrg->getWidth()>>1), (pcPicOrg->getHeight()>>1), pcPicOrg->getCStride(), pcPicDec->getCStride(), true);
1213    else
1214      xCalcCorrelationFuncforChromaSlices(ALF_Cb, pOrg, pCmp, tap, pcPicOrg->getCStride(), pcPicDec->getCStride());
1215#else       
1216    xCalcCorrelationFunc(pOrg, pCmp, tap, (pcPicOrg->getWidth()>>1), (pcPicOrg->getHeight()>>1), pcPicOrg->getCStride(), pcPicDec->getCStride());
1217#endif
1218  }
1219  if ((m_pcTempAlfParam->chroma_idc)&0x01)
1220  {
1221    Pel* pOrg = pcPicOrg->getCrAddr();
1222    Pel* pCmp = pcPicDec->getCrAddr();
1223#if MTK_NONCROSS_INLOOP_FILTER
1224    if(!m_bUseNonCrossALF)
1225      xCalcCorrelationFunc(0, 0, pOrg, pCmp, tap, (pcPicOrg->getWidth()>>1), (pcPicOrg->getHeight()>>1), pcPicOrg->getCStride(), pcPicDec->getCStride(), true);
1226    else
1227      xCalcCorrelationFuncforChromaSlices(ALF_Cr, pOrg, pCmp, tap, pcPicOrg->getCStride(), pcPicDec->getCStride());
1228#else
1229    xCalcCorrelationFunc(pOrg, pCmp, tap, (pcPicOrg->getWidth()>>1), (pcPicOrg->getHeight()>>1), pcPicOrg->getCStride(), pcPicDec->getCStride());
1230#endif
1231  }
1232 
1233  err_code = xGauss(m_ppdAlfCorr, N);
1234 
1235  if(err_code)
1236  {
1237    xClearFilterCoefInt(qh, N);
1238  }
1239  else
1240  {
1241    for(i=0; i<N; i++)
1242      m_pdDoubleAlfCoeff[i] = m_ppdAlfCorr[i][N];
1243   
1244    xQuantFilterCoef(m_pdDoubleAlfCoeff, qh, tap, g_uiBitDepth + g_uiBitIncrement);
1245  }
1246 
1247 
1248  if ((m_pcTempAlfParam->chroma_idc>>1)&0x01)
1249  {
1250#if MTK_NONCROSS_INLOOP_FILTER
1251    if(! m_bUseNonCrossALF)
1252      xFrameChroma(0, 0, (pcPicRest->getHeight() >> 1), (pcPicRest->getWidth() >>1), pcPicDec, pcPicRest, qh, tap, 0);
1253    else
1254      xFrameChromaforSlices(ALF_Cb, pcPicDec, pcPicRest, qh, tap);
1255#else
1256    xFrameChroma(pcPicDec, pcPicRest, qh, tap, 0);
1257#endif
1258  }
1259  if ((m_pcTempAlfParam->chroma_idc)&0x01)
1260  {
1261#if MTK_NONCROSS_INLOOP_FILTER
1262    if(! m_bUseNonCrossALF)
1263      xFrameChroma(0, 0, (pcPicRest->getHeight() >> 1), (pcPicRest->getWidth() >>1), pcPicDec, pcPicRest, qh, tap, 1);
1264    else
1265      xFrameChromaforSlices(ALF_Cr, pcPicDec, pcPicRest, qh, tap);
1266#else
1267    xFrameChroma(pcPicDec, pcPicRest, qh, tap, 1);
1268#endif
1269  }
1270 
1271  if(m_pcTempAlfParam->chroma_idc<3)
1272  {
1273    if(m_pcTempAlfParam->chroma_idc==1)
1274    {
1275      pcPicDec->copyToPicCb(pcPicRest);
1276    }
1277    if(m_pcTempAlfParam->chroma_idc==2)
1278    {
1279      pcPicDec->copyToPicCr(pcPicRest);
1280    }
1281  }
1282 
1283}
1284
1285Void TEncAdaptiveLoopFilter::xCopyDecToRestCUs(TComPicYuv* pcPicDec, TComPicYuv* pcPicRest)
1286{
1287  for( UInt uiCUAddr = 0; uiCUAddr < m_pcPic->getNumCUsInFrame() ; uiCUAddr++ )
1288  {
1289    TComDataCU* pcCU = m_pcPic->getCU( uiCUAddr );
1290    xCopyDecToRestCU(pcCU, 0, 0, pcPicDec, pcPicRest);
1291  }
1292}
1293
1294Void TEncAdaptiveLoopFilter::xCopyDecToRestCU(TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth, TComPicYuv* pcPicDec, TComPicYuv* pcPicRest)
1295{
1296  Bool bBoundary = false;
1297  UInt uiLPelX   = pcCU->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiAbsPartIdx] ];
1298  UInt uiRPelX   = uiLPelX + (g_uiMaxCUWidth>>uiDepth)  - 1;
1299  UInt uiTPelY   = pcCU->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiAbsPartIdx] ];
1300  UInt uiBPelY   = uiTPelY + (g_uiMaxCUHeight>>uiDepth) - 1;
1301 
1302  if( ( uiRPelX >= pcCU->getSlice()->getSPS()->getWidth() ) || ( uiBPelY >= pcCU->getSlice()->getSPS()->getHeight() ) )
1303  {
1304    bBoundary = true;
1305  }
1306 
1307  if( ( ( uiDepth < pcCU->getDepth( uiAbsPartIdx ) ) && ( uiDepth < (g_uiMaxCUDepth-g_uiAddCUDepth) ) ) || bBoundary )
1308  {
1309    UInt uiQNumParts = ( m_pcPic->getNumPartInCU() >> (uiDepth<<1) )>>2;
1310    for ( UInt uiPartUnitIdx = 0; uiPartUnitIdx < 4; uiPartUnitIdx++, uiAbsPartIdx+=uiQNumParts )
1311    {
1312      uiLPelX   = pcCU->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiAbsPartIdx] ];
1313      uiTPelY   = pcCU->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiAbsPartIdx] ];
1314     
1315      if( ( uiLPelX < pcCU->getSlice()->getSPS()->getWidth() ) && ( uiTPelY < pcCU->getSlice()->getSPS()->getHeight() ) )     
1316        xCopyDecToRestCU(pcCU, uiAbsPartIdx, uiDepth+1, pcPicDec, pcPicRest);
1317    }
1318    return;
1319  }
1320 
1321  if (!pcCU->getAlfCtrlFlag(uiAbsPartIdx))
1322  {
1323    UInt uiCUAddr = pcCU->getAddr();
1324   
1325    Int iWidth = pcCU->getWidth(uiAbsPartIdx);
1326    Int iHeight = pcCU->getHeight(uiAbsPartIdx);
1327   
1328    Pel* pRec = pcPicDec->getLumaAddr(uiCUAddr, uiAbsPartIdx);
1329    Pel* pFilt = pcPicRest->getLumaAddr(uiCUAddr, uiAbsPartIdx);
1330   
1331    Int iRecStride = pcPicDec->getStride();
1332    Int iFiltStride = pcPicRest->getStride();
1333   
1334    for (Int y = 0; y < iHeight; y++)
1335    {
1336      for (Int x = 0; x < iWidth; x++)
1337      {
1338        pFilt[x] = pRec[x];
1339      }
1340      pRec += iRecStride;
1341      pFilt += iFiltStride;
1342    }
1343  }
1344}
1345
1346Void TEncAdaptiveLoopFilter::xcollectStatCodeFilterCoeffForce0(int **pDiffQFilterCoeffIntPP, int fl, int sqrFiltLength, 
1347                                                               int filters_per_group, int bitsVarBin[])
1348{
1349  int i, k, kMin, kStart, minBits, ind, scanPos, maxScanVal, coeffVal, 
1350  *pDepthInt=NULL, kMinTab[MAX_SQR_FILT_LENGTH], bitsCoeffScan[MAX_SCAN_VAL][MAX_EXP_GOLOMB],
1351  minKStart, minBitsKStart, bitsKStart;
1352 
1353  pDepthInt=pDepthIntTab[fl-2];
1354 
1355  maxScanVal=0;
1356  for (i=0; i<sqrFiltLength; i++)
1357  {
1358    maxScanVal=max(maxScanVal, pDepthInt[i]);
1359  }
1360 
1361  // vlc for all
1362  memset(bitsCoeffScan, 0, MAX_SCAN_VAL * MAX_EXP_GOLOMB * sizeof(int));
1363  for(ind=0; ind<filters_per_group; ++ind)
1364  {
1365    for(i = 0; i < sqrFiltLength; i++)
1366    {     
1367      scanPos=pDepthInt[i]-1;
1368      coeffVal=abs(pDiffQFilterCoeffIntPP[ind][i]);
1369      for (k=1; k<15; k++)
1370      {
1371        bitsCoeffScan[scanPos][k] += lengthGolomb(coeffVal, k);
1372      }
1373    }
1374  }
1375 
1376  minBitsKStart=0;
1377  minKStart = -1;
1378  for (k=1; k<8; k++)
1379  { 
1380    bitsKStart=0; kStart=k;
1381    for (scanPos=0; scanPos<maxScanVal; scanPos++)
1382    {
1383      kMin=kStart; minBits=bitsCoeffScan[scanPos][kMin];
1384     
1385      if (bitsCoeffScan[scanPos][kStart+1]<minBits)
1386      {
1387        kMin=kStart+1; minBits=bitsCoeffScan[scanPos][kMin];
1388      }
1389      kStart=kMin;
1390      bitsKStart+=minBits;
1391    }
1392    if (bitsKStart<minBitsKStart || k==1)
1393    {
1394      minBitsKStart=bitsKStart;
1395      minKStart=k;
1396    }
1397  }
1398 
1399  kStart = minKStart; 
1400  for (scanPos=0; scanPos<maxScanVal; scanPos++)
1401  {
1402    kMin=kStart; minBits=bitsCoeffScan[scanPos][kMin];
1403   
1404    if (bitsCoeffScan[scanPos][kStart+1]<minBits)
1405    {
1406      kMin = kStart+1; 
1407      minBits = bitsCoeffScan[scanPos][kMin];
1408    }
1409   
1410    kMinTab[scanPos] = kMin;
1411    kStart = kMin;
1412  }
1413 
1414  for(ind=0; ind<filters_per_group; ++ind)
1415  {
1416    bitsVarBin[ind]=0;
1417    for(i = 0; i < sqrFiltLength; i++)
1418    {
1419      scanPos=pDepthInt[i]-1;
1420      bitsVarBin[ind] += lengthGolomb(abs(pDiffQFilterCoeffIntPP[ind][i]), kMinTab[scanPos]);
1421    }
1422  }
1423}
1424
1425Void TEncAdaptiveLoopFilter::xdecideCoeffForce0(int codedVarBins[NO_VAR_BINS], double errorForce0Coeff[], double errorForce0CoeffTab[NO_VAR_BINS][2], int bitsVarBin[NO_VAR_BINS], double lambda, int filters_per_fr)
1426{
1427  int filtNo;
1428  double lagrangianDiff;
1429  int ind;
1430 
1431  errorForce0Coeff[0]=errorForce0Coeff[1]=0;
1432  for (ind=0; ind<16; ind++) codedVarBins[ind]=0;
1433 
1434  for(filtNo=0; filtNo<filters_per_fr; filtNo++)
1435  {
1436    // No coeffcient prediction bits used
1437#if ENABLE_FORCECOEFF0
1438    lagrangianDiff=errorForce0CoeffTab[filtNo][0]-(errorForce0CoeffTab[filtNo][1]+lambda*bitsVarBin[filtNo]);
1439    codedVarBins[filtNo]=(lagrangianDiff>0)? 1 : 0;
1440    errorForce0Coeff[0]+=errorForce0CoeffTab[filtNo][codedVarBins[filtNo]];
1441    errorForce0Coeff[1]+=errorForce0CoeffTab[filtNo][1];
1442#else
1443    lagrangianDiff=errorForce0CoeffTab[filtNo][0]-(errorForce0CoeffTab[filtNo][1]+lambda*bitsVarBin[filtNo]);
1444    codedVarBins[filtNo]= 1;
1445    errorForce0Coeff[0]+=errorForce0CoeffTab[filtNo][codedVarBins[filtNo]];
1446    errorForce0Coeff[1]+=errorForce0CoeffTab[filtNo][1];
1447#endif
1448  }   
1449}
1450
1451double TEncAdaptiveLoopFilter::xfindBestCoeffCodMethod(int codedVarBins[NO_VAR_BINS], int *forceCoeff0, 
1452                                                       int **filterCoeffSymQuant, int fl, int sqrFiltLength, 
1453                                                       int filters_per_fr, double errorForce0CoeffTab[NO_VAR_BINS][2], 
1454                                                       double *errorQuant, double lambda)
1455
1456{
1457  int bitsVarBin[NO_VAR_BINS], createBistream, coeffBits, coeffBitsForce0;
1458  double errorForce0Coeff[2], lagrangianForce0, lagrangian;
1459 
1460  xcollectStatCodeFilterCoeffForce0(filterCoeffSymQuant, fl, sqrFiltLength, 
1461                                    filters_per_fr, bitsVarBin);
1462 
1463  xdecideCoeffForce0(codedVarBins, errorForce0Coeff, errorForce0CoeffTab, bitsVarBin, lambda, filters_per_fr);
1464 
1465  coeffBitsForce0 = xsendAllFiltersPPPredForce0(filterCoeffSymQuant, fl, sqrFiltLength, 
1466                                                filters_per_fr, codedVarBins, createBistream=0, m_tempALFp);
1467 
1468  coeffBits = xsendAllFiltersPPPred(filterCoeffSymQuant, fl, sqrFiltLength, filters_per_fr, 
1469                                    createBistream=0, m_tempALFp);
1470 
1471  lagrangianForce0=errorForce0Coeff[0]+lambda*coeffBitsForce0;
1472  lagrangian=errorForce0Coeff[1]+lambda*coeffBits;
1473  if (lagrangianForce0<lagrangian)
1474  {
1475    *errorQuant=errorForce0Coeff[0];
1476    *forceCoeff0=1;
1477    return(lagrangianForce0);
1478  }
1479  else
1480  {
1481    *errorQuant=errorForce0Coeff[1];
1482    *forceCoeff0=0;
1483    return(lagrangian);
1484  }
1485}
1486
1487Int TEncAdaptiveLoopFilter::xsendAllFiltersPPPred(int **FilterCoeffQuant, int fl, int sqrFiltLength, 
1488                                                  int filters_per_group, int createBistream, ALFParam* ALFp)
1489{
1490  int ind, bit_ct = 0, bit_ct0 = 0, i;
1491  int predMethod = 0;
1492  int force0 = 0;
1493  Int64 Newbit_ct;
1494 
1495  bit_ct0 = xcodeFilterCoeff(FilterCoeffQuant, fl, sqrFiltLength, filters_per_group, 0);
1496 
1497  for(ind = 0; ind < filters_per_group; ++ind)
1498  {
1499    if(ind == 0)
1500    {
1501      for(i = 0; i < sqrFiltLength; i++)
1502        m_diffFilterCoeffQuant[ind][i] = FilterCoeffQuant[ind][i];
1503    }
1504    else
1505    {
1506      for(i = 0; i < sqrFiltLength; i++)
1507        m_diffFilterCoeffQuant[ind][i] = FilterCoeffQuant[ind][i] - FilterCoeffQuant[ind-1][i];
1508    }
1509  }
1510 
1511  if(xcodeFilterCoeff(m_diffFilterCoeffQuant, fl, sqrFiltLength, filters_per_group, 0) >= bit_ct0)
1512  {
1513    predMethod = 0; 
1514    if(filters_per_group > 1)
1515      bit_ct += lengthPredFlags(force0, predMethod, NULL, 0, createBistream);
1516    bit_ct += xcodeFilterCoeff(FilterCoeffQuant, fl, sqrFiltLength, filters_per_group, createBistream);
1517  }
1518  else
1519  {
1520    predMethod = 1;
1521    if(filters_per_group > 1)
1522      bit_ct += lengthPredFlags(force0, predMethod, NULL, 0, createBistream);
1523    bit_ct += xcodeFilterCoeff(m_diffFilterCoeffQuant, fl, sqrFiltLength, filters_per_group, createBistream);
1524  }
1525 
1526  ALFp->forceCoeff0 = 0;
1527  ALFp->filters_per_group_diff = filters_per_group;
1528  ALFp->filters_per_group = filters_per_group;
1529  ALFp->predMethod = predMethod;
1530  ALFp->num_coeff = sqrFiltLength;
1531  if (ALFp->num_coeff == SQR_FILT_LENGTH_5SYM)
1532    ALFp->realfiltNo=2;
1533  else if (ALFp->num_coeff == SQR_FILT_LENGTH_7SYM)
1534    ALFp->realfiltNo=1;
1535  else
1536    ALFp->realfiltNo=0;
1537 
1538  for(ind = 0; ind < filters_per_group; ++ind)
1539  {
1540    for(i = 0; i < sqrFiltLength; i++)
1541    {
1542      if (predMethod) ALFp->coeffmulti[ind][i] = m_diffFilterCoeffQuant[ind][i];
1543      else ALFp->coeffmulti[ind][i] = FilterCoeffQuant[ind][i];
1544    }
1545  }
1546  m_pcDummyEntropyCoder->codeFiltCountBit(ALFp, &Newbit_ct);
1547 
1548 
1549  //  return(bit_ct);
1550  return ((Int)Newbit_ct);
1551}
1552
1553
1554Int TEncAdaptiveLoopFilter::xsendAllFiltersPPPredForce0(int **FilterCoeffQuant, int fl, int sqrFiltLength, int filters_per_group, 
1555                                                        int codedVarBins[NO_VAR_BINS], int createBistream, ALFParam* ALFp)
1556{
1557  int ind, bit_ct=0, bit_ct0, i, j;
1558  int filters_per_group_temp, filters_per_group_diff;
1559  int chosenPred = 0;
1560  int force0 = 1;
1561  Int64 Newbit_ct;
1562 
1563  i = 0;
1564  for(ind = 0; ind < filters_per_group; ind++)
1565  {
1566    if(codedVarBins[ind] == 1)
1567    {
1568      for(j = 0; j < sqrFiltLength; j++)
1569        m_FilterCoeffQuantTemp[i][j]=FilterCoeffQuant[ind][j];
1570      i++;
1571    }
1572  }
1573  filters_per_group_diff = filters_per_group_temp = i;
1574 
1575  for(ind = 0; ind < filters_per_group; ++ind)
1576  {
1577    if(ind == 0)
1578    {
1579      for(i = 0; i < sqrFiltLength; i++)
1580        m_diffFilterCoeffQuant[ind][i] = m_FilterCoeffQuantTemp[ind][i];
1581    }
1582    else
1583    {
1584      for(i = 0; i < sqrFiltLength; i++)
1585        m_diffFilterCoeffQuant[ind][i] = m_FilterCoeffQuantTemp[ind][i] - m_FilterCoeffQuantTemp[ind-1][i];
1586    }
1587  }
1588 
1589  if(!((filters_per_group_temp == 0) && (filters_per_group == 1)))
1590  {
1591    bit_ct0 = xcodeFilterCoeff(m_FilterCoeffQuantTemp, fl, sqrFiltLength, filters_per_group_temp, 0);
1592   
1593    if(xcodeFilterCoeff(m_diffFilterCoeffQuant, fl, sqrFiltLength, filters_per_group_diff, 0) >= bit_ct0)
1594    {
1595      chosenPred = 0;
1596      bit_ct += lengthPredFlags(force0, chosenPred, codedVarBins, filters_per_group, createBistream);
1597      bit_ct += xcodeFilterCoeff(m_FilterCoeffQuantTemp, fl, sqrFiltLength, filters_per_group_temp, createBistream);
1598    }
1599    else
1600    {
1601      chosenPred = 1;
1602      bit_ct += lengthPredFlags(force0, chosenPred, codedVarBins, filters_per_group, createBistream);
1603      bit_ct += xcodeFilterCoeff(m_diffFilterCoeffQuant, fl, sqrFiltLength, filters_per_group_temp, createBistream);
1604    }
1605  }
1606  ALFp->forceCoeff0 = 1;
1607  ALFp->predMethod = chosenPred;
1608  ALFp->filters_per_group_diff = filters_per_group_diff;
1609  ALFp->filters_per_group = filters_per_group;
1610  ALFp->num_coeff = sqrFiltLength;
1611  if (ALFp->num_coeff == SQR_FILT_LENGTH_5SYM)
1612    ALFp->realfiltNo=2;
1613  else if (ALFp->num_coeff == SQR_FILT_LENGTH_7SYM)
1614    ALFp->realfiltNo=1;
1615  else
1616    ALFp->realfiltNo=0;
1617 
1618  for(ind = 0; ind < filters_per_group; ++ind)
1619  {
1620    ALFp->codedVarBins[ind] = codedVarBins[ind];
1621  }
1622  for(ind = 0; ind < filters_per_group_diff; ++ind)
1623  {
1624    for(i = 0; i < sqrFiltLength; i++)
1625    {
1626      if (chosenPred) ALFp->coeffmulti[ind][i] = m_diffFilterCoeffQuant[ind][i];
1627      else ALFp->coeffmulti[ind][i] = m_FilterCoeffQuantTemp[ind][i];
1628    }
1629  }
1630  m_pcDummyEntropyCoder->codeFiltCountBit(ALFp, &Newbit_ct);
1631 
1632  return ((Int)Newbit_ct);
1633}
1634
1635//filtNo==-1/realfiltNo, noFilters=filters_per_frames, realfiltNo=filtNo
1636Int TEncAdaptiveLoopFilter::xcodeAuxInfo(int filtNo, int noFilters, int varIndTab[NO_VAR_BINS], int frNo, int createBitstream,int realfiltNo, ALFParam* ALFp)
1637{
1638  int i, filterPattern[NO_VAR_BINS], startSecondFilter=0, bitCt=0, codePrediction;
1639  Int64 NewbitCt;
1640 
1641  codePrediction = 0;
1642 
1643  //send realfiltNo (tap related)
1644  ALFp->realfiltNo = realfiltNo;
1645  ALFp->filtNo = filtNo;
1646 
1647  if(filtNo >= 0)
1648  {
1649    // decide startSecondFilter and filterPattern
1650    if(noFilters > 1)
1651    {
1652      memset(filterPattern, 0, NO_VAR_BINS * sizeof(int)); 
1653      for(i = 1; i < NO_VAR_BINS; ++i)
1654      {
1655        if(varIndTab[i] != varIndTab[i-1])
1656        {
1657          filterPattern[i] = 1;
1658          startSecondFilter = i;
1659        }
1660      }
1661      memcpy (ALFp->filterPattern, filterPattern, NO_VAR_BINS * sizeof(int));
1662      ALFp->startSecondFilter = startSecondFilter;
1663    }
1664   
1665    //send noFilters (filters_per_frame)
1666    //0: filters_per_frame = 1
1667    //1: filters_per_frame = 2
1668    //2: filters_per_frame > 2 (exact number from filterPattern)
1669
1670    ALFp->noFilters = min(noFilters-1,2);
1671    if (noFilters<=0) printf("error\n");
1672  }
1673  m_pcDummyEntropyCoder->codeAuxCountBit(ALFp, &NewbitCt);
1674  bitCt = (int) NewbitCt;
1675  return(bitCt);
1676}
1677
1678Int   TEncAdaptiveLoopFilter::xcodeFilterCoeff(int **pDiffQFilterCoeffIntPP, int fl, int sqrFiltLength, 
1679                                               int filters_per_group, int createBitstream)
1680{
1681  int i, k, kMin, kStart, minBits, ind, scanPos, maxScanVal, coeffVal, len = 0,
1682  *pDepthInt=NULL, kMinTab[MAX_SQR_FILT_LENGTH], bitsCoeffScan[MAX_SCAN_VAL][MAX_EXP_GOLOMB],
1683  minKStart, minBitsKStart, bitsKStart;
1684 
1685  pDepthInt = pDepthIntTab[fl-2];
1686 
1687  maxScanVal = 0;
1688  for(i = 0; i < sqrFiltLength; i++)
1689  {
1690    maxScanVal = max(maxScanVal, pDepthInt[i]);
1691  }
1692 
1693  // vlc for all
1694  memset(bitsCoeffScan, 0, MAX_SCAN_VAL * MAX_EXP_GOLOMB * sizeof(int));
1695  for(ind=0; ind<filters_per_group; ++ind)
1696  {
1697    for(i = 0; i < sqrFiltLength; i++)
1698    {     
1699      scanPos=pDepthInt[i]-1;
1700      coeffVal=abs(pDiffQFilterCoeffIntPP[ind][i]);
1701      for (k=1; k<15; k++)
1702      {
1703        bitsCoeffScan[scanPos][k]+=lengthGolomb(coeffVal, k);
1704      }
1705    }
1706  }
1707 
1708  minBitsKStart = 0;
1709  minKStart = -1;
1710  for(k = 1; k < 8; k++)
1711  { 
1712    bitsKStart = 0; 
1713    kStart = k;
1714    for(scanPos = 0; scanPos < maxScanVal; scanPos++)
1715    {
1716      kMin = kStart; 
1717      minBits = bitsCoeffScan[scanPos][kMin];
1718     
1719      if(bitsCoeffScan[scanPos][kStart+1] < minBits)
1720      {
1721        kMin = kStart + 1; 
1722        minBits = bitsCoeffScan[scanPos][kMin];
1723      }
1724      kStart = kMin;
1725      bitsKStart += minBits;
1726    }
1727    if((bitsKStart < minBitsKStart) || (k == 1))
1728    {
1729      minBitsKStart = bitsKStart;
1730      minKStart = k;
1731    }
1732  }
1733 
1734  kStart = minKStart; 
1735  for(scanPos = 0; scanPos < maxScanVal; scanPos++)
1736  {
1737    kMin = kStart; 
1738    minBits = bitsCoeffScan[scanPos][kMin];
1739   
1740    if(bitsCoeffScan[scanPos][kStart+1] < minBits)
1741    {
1742      kMin = kStart + 1; 
1743      minBits = bitsCoeffScan[scanPos][kMin];
1744    }
1745   
1746    kMinTab[scanPos] = kMin;
1747    kStart = kMin;
1748  }
1749 
1750  // Coding parameters
1751  //  len += lengthFilterCodingParams(minKStart, maxScanVal, kMinTab, createBitstream);
1752  len += (3 + maxScanVal);
1753 
1754  // Filter coefficients
1755  len += lengthFilterCoeffs(sqrFiltLength, filters_per_group, pDepthInt, pDiffQFilterCoeffIntPP, 
1756                            kMinTab, createBitstream);
1757 
1758  return len;
1759}
1760
1761Int TEncAdaptiveLoopFilter::lengthGolomb(int coeffVal, int k)
1762{
1763  int m = 2 << (k - 1);
1764  int q = coeffVal / m;
1765  if(coeffVal != 0)
1766    return(q + 2 + k);
1767  else
1768    return(q + 1 + k);
1769}
1770
1771Int TEncAdaptiveLoopFilter::lengthPredFlags(int force0, int predMethod, int codedVarBins[NO_VAR_BINS], 
1772                                            int filters_per_group, int createBitstream)
1773{
1774  int bit_cnt = 0;
1775 
1776  if(force0)
1777    bit_cnt = 2 + filters_per_group;
1778  else
1779    bit_cnt = 2;
1780  return bit_cnt;
1781 
1782}
1783//important
1784Int TEncAdaptiveLoopFilter::lengthFilterCoeffs(int sqrFiltLength, int filters_per_group, int pDepthInt[], 
1785                                               int **FilterCoeff, int kMinTab[], int createBitstream)
1786{
1787  int ind, scanPos, i;
1788  int bit_cnt = 0;
1789 
1790  for(ind = 0; ind < filters_per_group; ++ind)
1791  {
1792    for(i = 0; i < sqrFiltLength; i++)
1793    {
1794      scanPos = pDepthInt[i] - 1;
1795      bit_cnt += lengthGolomb(abs(FilterCoeff[ind][i]), kMinTab[scanPos]);
1796    }
1797  }
1798  return bit_cnt;
1799}
1800
1801Void   TEncAdaptiveLoopFilter::xEncALFLuma_qc ( TComPicYuv* pcPicOrg, TComPicYuv* pcPicDec, TComPicYuv* pcPicRest, UInt64& ruiMinRate, UInt64& ruiMinDist, Double& rdMinCost )
1802{
1803  //pcPicDec: extended decoded
1804  //pcPicRest: original decoded: filtered signal will be stored
1805 
1806  UInt64  uiRate;
1807  UInt64  uiDist;
1808  Double dCost;
1809#if !MQT_ALF_NPASS
1810  Int    Height = pcPicOrg->getHeight();
1811  Int    Width = pcPicOrg->getWidth();
1812#endif
1813  Int    LumaStride = pcPicOrg->getStride();
1814  imgpel* pOrg = (imgpel*) pcPicOrg->getLumaAddr();
1815  imgpel* pRest = (imgpel*) pcPicRest->getLumaAddr();
1816  imgpel* pDec = (imgpel*) pcPicDec->getLumaAddr();
1817
1818  Int tap               = ALF_MIN_NUM_TAP;
1819  m_pcTempAlfParam->tap = tap;
1820#if TI_ALF_MAX_VSIZE_7
1821  m_pcTempAlfParam->tapV = TComAdaptiveLoopFilter::ALFTapHToTapV(m_pcTempAlfParam->tap);
1822  m_pcTempAlfParam->num_coeff = TComAdaptiveLoopFilter::ALFTapHToNumCoeff(m_pcTempAlfParam->tap);
1823#else
1824  m_pcTempAlfParam->num_coeff = (Int)tap*tap/4 + 2; 
1825#endif
1826
1827#if MQT_BA_RA
1828
1829#if MQT_ALF_NPASS
1830
1831  static Bool   bFirst = true;
1832  static Int*   apiVarIndTabBest[NUM_ALF_CLASS_METHOD];
1833  static Int**  appiBestCoeffSet[NUM_ALF_CLASS_METHOD];
1834
1835  static Double***  adBestySym;
1836  static Double**** adBestESym;
1837  static Double**   adBestpixAcc; 
1838
1839  if(bFirst)
1840  {
1841    if(m_iALFEncodePassReduction)
1842    {
1843      initMatrix4D_double(&adBestESym,NUM_ALF_CLASS_METHOD,  NO_VAR_BINS, MAX_SQR_FILT_LENGTH, MAX_SQR_FILT_LENGTH);
1844      initMatrix3D_double(&adBestySym,NUM_ALF_CLASS_METHOD,  NO_VAR_BINS, MAX_SQR_FILT_LENGTH); 
1845      initMatrix_double  (&adBestpixAcc,NUM_ALF_CLASS_METHOD,  NO_VAR_BINS );
1846
1847      for(Int i=0; i< NUM_ALF_CLASS_METHOD; i++)
1848      {
1849
1850        apiVarIndTabBest[i] = new Int[NO_VAR_BINS];
1851        appiBestCoeffSet[i] = new Int*[NO_VAR_BINS];
1852        for(Int j=0; j< NO_VAR_BINS; j++)
1853        {
1854          appiBestCoeffSet[i][j]= new Int[MAX_SQR_FILT_LENGTH];
1855        }
1856      }
1857    }
1858
1859    bFirst = false;
1860  }
1861
1862  Int         ibestfiltNo[NUM_ALF_CLASS_METHOD];
1863  Int         ibestfilters_per_fr[NUM_ALF_CLASS_METHOD];
1864  Int64       iDist;
1865  Int64       iMinMethodDist = MAX_INT;
1866  UInt64      uiMinMethodRate;
1867  Double      dMinMethodCost = MAX_DOUBLE;
1868#endif
1869  Int       iBestClassMethod = ALF_RA;
1870  Double    adExtraCostReduction[NUM_ALF_CLASS_METHOD];
1871  ALFParam  cFrmAlfParam        [NUM_ALF_CLASS_METHOD];
1872  ALFParam* pcAlfParam = NULL;
1873
1874  for(Int i=0; i< NUM_ALF_CLASS_METHOD; i++)
1875  {
1876    pcAlfParam = &(cFrmAlfParam[i]);
1877    allocALFParam(pcAlfParam);
1878
1879    pcAlfParam->alf_flag        = 1;
1880    pcAlfParam->chroma_idc      = 0;
1881    pcAlfParam->cu_control_flag = 0;
1882    pcAlfParam->tap = tap;
1883#if TI_ALF_MAX_VSIZE_7
1884    pcAlfParam->tapV = TComAdaptiveLoopFilter::ALFTapHToTapV(pcAlfParam->tap);
1885    pcAlfParam->num_coeff = TComAdaptiveLoopFilter::ALFTapHToNumCoeff(pcAlfParam->tap);
1886#else
1887    pcAlfParam->num_coeff = (Int)tap*tap/4 + 2; 
1888#endif
1889
1890    switch(i)
1891    {
1892    case ALF_RA:
1893      {
1894        adExtraCostReduction[i] = (double)(m_im_height * m_im_width) * m_dLambdaLuma * 2.0 / 4096.0;
1895      }
1896      break;
1897    default:
1898      {
1899        adExtraCostReduction[i] = 0.0;
1900      }
1901      break;
1902    }
1903
1904  }
1905
1906  for(Int i=0; i< NUM_ALF_CLASS_METHOD; i++)
1907  {
1908    pcAlfParam       = &(cFrmAlfParam[i]);
1909    m_varImg         = m_varImgMethods[i];
1910    m_uiVarGenMethod = pcAlfParam->alf_pcr_region_flag = i;
1911#if MQT_ALF_NPASS
1912    if(m_iALFEncodePassReduction)
1913    {
1914      m_aiFilterCoeffSaved = m_aiFilterCoeffSavedMethods[m_uiVarGenMethod];
1915    }
1916    setInitialMask(pcPicOrg, pcPicDec);
1917#else
1918    for (Int i=0; i<Height; i++)
1919    {
1920      for (Int j=0; j<Width; j++)
1921      {
1922        m_maskImg[i][j] = 1;
1923      }
1924    }
1925#if MTK_NONCROSS_INLOOP_FILTER
1926    if(!m_bUseNonCrossALF)
1927      calcVar(0, 0, m_varImg, pDec, 9/2, VAR_SIZE, Height, Width, LumaStride);
1928    else
1929      calcVarforSlices(m_varImg, pDec, 9/2, VAR_SIZE, LumaStride);
1930#else
1931    calcVar(m_varImg, pDec, 9/2, VAR_SIZE, Height, Width, LumaStride);
1932#endif
1933#endif
1934
1935#if MQT_ALF_NPASS
1936    if(m_iALFEncodePassReduction)
1937    {
1938      xFirstEstimateFilteringFrameLumaAllTap(pOrg, pDec, LumaStride, 
1939        pcAlfParam, apiVarIndTabBest[i], appiBestCoeffSet[i],
1940        ibestfiltNo[i], ibestfilters_per_fr[i], 
1941        adBestySym[i], adBestESym[i], adBestpixAcc[i],
1942        uiRate, iDist, dCost);
1943
1944    }
1945    else
1946    {
1947#endif
1948      xFirstFilteringFrameLuma(pOrg, pDec, (imgpel*)m_pcPicYuvTmp->getLumaAddr(), pcAlfParam, pcAlfParam->tap, LumaStride); 
1949#if MQT_ALF_NPASS
1950    }
1951#endif
1952
1953#if MQT_ALF_NPASS
1954    if(!m_iALFEncodePassReduction)
1955    {
1956#endif
1957      xCalcRDCost(pcPicOrg, m_pcPicYuvTmp, pcAlfParam, uiRate, uiDist, dCost); 
1958#if MQT_ALF_NPASS
1959      iDist = (Int64)uiDist;
1960    }
1961#endif
1962
1963    dCost -= adExtraCostReduction[i];
1964
1965    if(dCost < dMinMethodCost)
1966    {
1967      iBestClassMethod = i;
1968      dMinMethodCost = dCost;
1969      uiMinMethodRate= uiRate;
1970      iMinMethodDist = iDist;
1971#if MQT_ALF_NPASS
1972      if(!m_iALFEncodePassReduction)
1973      {
1974#endif
1975        m_pcPicYuvTmp->copyToPicLuma(pcPicRest);
1976#if MQT_ALF_NPASS
1977      }
1978#endif
1979
1980    } 
1981
1982  }
1983
1984  dMinMethodCost += adExtraCostReduction[iBestClassMethod];
1985
1986
1987  m_varImg= m_varImgMethods[iBestClassMethod];
1988
1989  m_uiVarGenMethod = iBestClassMethod;
1990
1991#if MQT_ALF_NPASS
1992  if(m_iALFEncodePassReduction)
1993  {
1994
1995    m_aiFilterCoeffSaved = m_aiFilterCoeffSavedMethods[iBestClassMethod];
1996
1997    setInitialMask(pcPicOrg, pcPicDec);
1998
1999    m_pcBestAlfParam->alf_flag = 1;
2000    m_pcBestAlfParam->cu_control_flag = 0;
2001    m_pcBestAlfParam->chroma_idc = 0;
2002    m_pcBestAlfParam->alf_pcr_region_flag = iBestClassMethod;
2003
2004    m_pcBestAlfParam->tap = cFrmAlfParam[iBestClassMethod].tap;
2005#if TI_ALF_MAX_VSIZE_7
2006    m_pcBestAlfParam->tapV = TComAdaptiveLoopFilter::ALFTapHToTapV(pcAlfParam->tap);
2007    m_pcBestAlfParam->num_coeff = TComAdaptiveLoopFilter::ALFTapHToNumCoeff(pcAlfParam->tap);
2008#else
2009    m_pcBestAlfParam->num_coeff = (Int)tap*tap/4 + 2; 
2010#endif
2011
2012    xFirstFilteringFrameLuma(pOrg, pDec, pRest, m_pcBestAlfParam, m_pcBestAlfParam->tap, LumaStride); 
2013
2014
2015
2016    xCalcRDCost(pcPicOrg, pcPicRest, m_pcBestAlfParam, uiMinMethodRate, uiDist, dMinMethodCost);
2017    iMinMethodDist = (Int64)uiDist;
2018  }
2019  else
2020  {
2021#endif
2022    copyALFParam(m_pcBestAlfParam, &cFrmAlfParam[iBestClassMethod]); 
2023#if MQT_ALF_NPASS
2024
2025  }
2026#endif
2027
2028  ruiMinRate = uiMinMethodRate;
2029  ruiMinDist = (UInt64)iMinMethodDist;
2030  rdMinCost =  dMinMethodCost;
2031
2032
2033  for(Int i=0; i< NUM_ALF_CLASS_METHOD; i++)
2034  {
2035    freeALFParam(&cFrmAlfParam[i]);
2036  }
2037
2038#else 
2039
2040#if MQT_ALF_NPASS
2041  setInitialMask(pcPicOrg, pcPicDec);
2042#else
2043  for (Int i=0; i<Height; i++)
2044  {
2045    for (Int j=0; j<Width; j++)
2046    {
2047      m_maskImg[i][j] = 1;
2048    }
2049  }
2050#if MTK_NONCROSS_INLOOP_FILTER
2051  if(!m_bUseNonCrossALF)
2052    calcVar(0, 0, m_varImg, pDec, 9/2, VAR_SIZE, Height, Width, LumaStride);
2053  else
2054    calcVarforSlices(m_varImg, pDec, 9/2, VAR_SIZE, LumaStride);
2055#else
2056  calcVar(m_varImg, pDec, 9/2, VAR_SIZE, Height, Width, LumaStride);
2057#endif
2058#endif
2059
2060#if MQT_ALF_NPASS
2061  if(m_iALFEncodePassReduction)
2062  {
2063    xFirstFilteringFrameLumaAllTap(pOrg, pDec, pRest, LumaStride);
2064  }
2065  else
2066#endif
2067    xFirstFilteringFrameLuma(pOrg, pDec, pRest, m_pcTempAlfParam, m_pcTempAlfParam->tap, LumaStride); 
2068
2069  xCalcRDCost(pcPicOrg, pcPicRest, m_pcTempAlfParam, uiRate, uiDist, dCost); // change this function final coding
2070 
2071  if( dCost < rdMinCost)
2072  {
2073    ruiMinRate = uiRate;
2074    ruiMinDist = uiDist;
2075    rdMinCost = dCost;
2076    copyALFParam(m_pcBestAlfParam, m_pcTempAlfParam); 
2077  } 
2078
2079#endif
2080}
2081
2082Void   TEncAdaptiveLoopFilter::xFirstFilteringFrameLuma(imgpel* ImgOrg, imgpel* ImgDec, imgpel* ImgRest, ALFParam* ALFp, Int tap, Int Stride)
2083{
2084#if MTK_NONCROSS_INLOOP_FILTER
2085  if(!m_bUseNonCrossALF)
2086    xstoreInBlockMatrix(0, 0, m_im_height, m_im_width, true, true, ImgOrg, ImgDec, tap, Stride);
2087  else
2088    xstoreInBlockMatrixforSlices(ImgOrg, ImgDec, tap, Stride);
2089#else
2090  xstoreInBlockMatrix(ImgOrg, ImgDec, tap, Stride);
2091#endif
2092
2093
2094  xFilteringFrameLuma_qc(ImgOrg, ImgDec, ImgRest, ALFp, tap, Stride);
2095}
2096
2097
2098#if MTK_NONCROSS_INLOOP_FILTER
2099Void   TEncAdaptiveLoopFilter::xstoreInBlockMatrix(Int ypos, Int xpos, Int iheight, Int iwidth, Bool bResetBlockMatrix, Bool bSymmCopyBlockMatrix, imgpel* ImgOrg, imgpel* ImgDec, Int tap, Int Stride)
2100#else
2101Void   TEncAdaptiveLoopFilter::xstoreInBlockMatrix(imgpel* ImgOrg, imgpel* ImgDec, Int tap, Int Stride)
2102#endif
2103{
2104#if MQT_BA_RA
2105  Int var_step_size_w = VAR_SIZE_W;
2106  Int var_step_size_h = VAR_SIZE_H;
2107#endif
2108
2109  Int i,j,k,l,varInd,ii,jj;
2110  Int x, y;
2111  Int fl =tap/2;
2112#if TI_ALF_MAX_VSIZE_7
2113  Int flV = TComAdaptiveLoopFilter::ALFFlHToFlV(fl);
2114  Int sqrFiltLength = TComAdaptiveLoopFilter::ALFTapHToNumCoeff(tap);
2115#else
2116  Int sqrFiltLength=(((tap*tap)/4 + 1) + 1);
2117#endif
2118  Int fl2=9/2; //extended size at each side of the frame
2119  Int ELocal[MAX_SQR_FILT_LENGTH];
2120  Int yLocal;
2121  Int *p_pattern;
2122  Int filtNo =2; 
2123  double **E,*yy;
2124#if MTK_NONCROSS_INLOOP_FILTER
2125  static Int count_valid;
2126#else
2127  Int count_valid=0;
2128#endif
2129  if (tap==9)
2130    filtNo =0;
2131  else if (tap==7)
2132    filtNo =1;
2133 
2134  p_pattern= m_patternTab[filtNo];
2135 
2136#if MTK_NONCROSS_INLOOP_FILTER
2137  if(bResetBlockMatrix)
2138  {
2139    count_valid = 0;
2140#endif
2141  memset( m_pixAcc, 0,sizeof(double)*NO_VAR_BINS);
2142  for (varInd=0; varInd<NO_VAR_BINS; varInd++)
2143  {
2144    memset(m_yGlobalSym[filtNo][varInd],0,sizeof(double)*MAX_SQR_FILT_LENGTH);
2145    for (k=0; k<sqrFiltLength; k++)
2146    {
2147      memset(m_EGlobalSym[filtNo][varInd][k],0,sizeof(double)*MAX_SQR_FILT_LENGTH);
2148    }
2149  }
2150  for (i = fl2; i < m_im_height+fl2; i++)
2151  {
2152    for (j = fl2; j < m_im_width+fl2; j++)
2153    {
2154      if (m_maskImg[i-fl2][j-fl2] == 1)
2155      {
2156        count_valid++;
2157      }
2158    }
2159  }
2160#if MTK_NONCROSS_INLOOP_FILTER
2161  }
2162#endif
2163
2164  {
2165#if MTK_NONCROSS_INLOOP_FILTER
2166    x = y = fl2; //cytsai: shall x, y  be removed ?
2167
2168    for (i= ypos; i< ypos + iheight; i++)
2169    {
2170      for (j= xpos; j< xpos + iwidth; j++)
2171      {
2172#else
2173    for (i=0,y=fl2; i<m_im_height; i++,y++)
2174    {
2175      for (j=0,x=fl2; j<m_im_width; j++,x++)
2176      {
2177#endif
2178#if MQT_ALF_NPASS
2179        Int condition = (m_maskImg[i][j] == 1);
2180        if (m_iDesignCurrentFilter)
2181        {
2182          condition = (m_maskImg[i][j] == 0 && count_valid > 0);
2183        }
2184        if(!condition)
2185        {
2186#else
2187        if (m_maskImg[i][j] == 0 && count_valid > 0)
2188        {
2189
2190        }
2191        else
2192        {
2193#endif
2194#if MQT_BA_RA
2195          varInd = m_varImg[i/var_step_size_h][j/var_step_size_w];
2196#else
2197          varInd=min(m_varImg[i][j], NO_VAR_BINS-1);
2198#endif
2199          k=0; 
2200          memset(ELocal, 0, sqrFiltLength*sizeof(int));
2201#if TI_ALF_MAX_VSIZE_7
2202          for (ii = -flV; ii < 0; ii++)
2203#else
2204          for (ii=-fl; ii<0; ii++)
2205#endif
2206          {
2207            for (jj=-fl-ii; jj<=fl+ii; jj++)
2208            { 
2209              ELocal[p_pattern[k++]]+=(ImgDec[(i+ii)*Stride + (j+jj)]+ImgDec[(i-ii)*Stride + (j-jj)]);
2210            }
2211          }
2212          for (jj=-fl; jj<0; jj++)
2213            ELocal[p_pattern[k++]]+=(ImgDec[(i)*Stride + (j+jj)]+ImgDec[(i)*Stride + (j-jj)]);
2214          ELocal[p_pattern[k++]]+=ImgDec[(i)*Stride + (j)];
2215          ELocal[sqrFiltLength-1]=1;
2216          yLocal=ImgOrg[(i)*Stride + (j)];
2217
2218          m_pixAcc[varInd]+=(yLocal*yLocal);
2219          E= m_EGlobalSym[filtNo][varInd];
2220          yy= m_yGlobalSym[filtNo][varInd];
2221
2222          for (k=0; k<sqrFiltLength; k++)
2223          {
2224            for (l=k; l<sqrFiltLength; l++)
2225              E[k][l]+=(double)(ELocal[k]*ELocal[l]);
2226            yy[k]+=(double)(ELocal[k]*yLocal);
2227          }
2228        }
2229      }
2230    }
2231  }
2232
2233#if MTK_NONCROSS_INLOOP_FILTER
2234  if(bSymmCopyBlockMatrix)
2235  {
2236#endif
2237
2238  // Matrix EGlobalSeq is symmetric, only part of it is calculated
2239  for (varInd=0; varInd<NO_VAR_BINS; varInd++)
2240  {
2241    double **pE = m_EGlobalSym[filtNo][varInd];
2242    for (k=1; k<sqrFiltLength; k++)
2243    {
2244      for (l=0; l<k; l++)
2245      {
2246        pE[k][l]=pE[l][k];
2247      }
2248    }
2249  }
2250#if MTK_NONCROSS_INLOOP_FILTER
2251  }
2252#endif
2253
2254}
2255
2256Void   TEncAdaptiveLoopFilter::xFilteringFrameLuma_qc(imgpel* ImgOrg, imgpel* imgY_pad, imgpel* ImgFilt, ALFParam* ALFp, Int tap, Int Stride)
2257{
2258  int  filtNo,filters_per_fr;
2259  static double **ySym, ***ESym;
2260  int lambda_val = (Int) m_dLambdaLuma;
2261  lambda_val = lambda_val * (1<<(2*g_uiBitIncrement));
2262  if (tap==9)
2263    filtNo =0;
2264  else if (tap==7)
2265    filtNo =1;
2266  else
2267    filtNo=2;
2268 
2269  ESym=m_EGlobalSym[filtNo]; 
2270  ySym=m_yGlobalSym[filtNo];
2271 
2272  xfindBestFilterVarPred(ySym, ESym, m_pixAcc, m_filterCoeffSym, m_filterCoeffSymQuant, filtNo, &filters_per_fr,
2273                         m_varIndTab, NULL, m_varImg, m_maskImg, NULL, lambda_val);
2274 
2275  // g_filterCoeffPrevSelected = g_filterCoeffSym
2276  xcalcPredFilterCoeff(filtNo);
2277 
2278  //filter the frame with g_filterCoeffPrevSelected
2279#if MTK_NONCROSS_INLOOP_FILTER
2280  if(!m_bUseNonCrossALF)
2281    xfilterFrame_en(0, 0, m_im_height, m_im_width, imgY_pad, ImgFilt, filtNo, Stride);
2282  else
2283    xfilterSlices_en(imgY_pad, ImgFilt, filtNo, Stride);
2284#else
2285  xfilterFrame_en(imgY_pad, ImgFilt, filtNo, Stride);
2286#endif
2287
2288  xcodeFiltCoeff(m_filterCoeffSymQuant, filtNo, m_varIndTab, filters_per_fr,0, ALFp);
2289}
2290
2291#if MTK_NONCROSS_INLOOP_FILTER
2292Void TEncAdaptiveLoopFilter::xfilterFrame_en(int ypos, int xpos, int iheight, int iwidth, imgpel* ImgDec, imgpel* ImgRest,int filtNo, int Stride)
2293#else
2294Void TEncAdaptiveLoopFilter::xfilterFrame_en(imgpel* ImgDec, imgpel* ImgRest,int filtNo, int Stride)
2295#endif
2296{
2297#if MQT_BA_RA
2298  imgpel *imgY_rec = ImgDec;
2299  imgpel *p_imgY_pad, *p_imgY_pad0;
2300  int var_step_size_w = VAR_SIZE_W;
2301  int var_step_size_h = VAR_SIZE_H;
2302  int i,j,y,x;
2303#else
2304  int i,j,ii,jj,y,x;
2305#endif
2306  int  *pattern; 
2307  int fl, fl_temp, sqrFiltLength;
2308  int pixelInt;
2309  int offset = (1<<(NUM_BITS - 2));
2310 
2311  pattern=m_patternTab_filt[filtNo];
2312  fl_temp=m_flTab[filtNo];
2313#if !MQT_BA_RA
2314#if TI_ALF_MAX_VSIZE_7
2315  Int fl_tempV = TComAdaptiveLoopFilter::ALFFlHToFlV(fl_temp);
2316#endif
2317#endif
2318  sqrFiltLength=MAX_SQR_FILT_LENGTH;  fl=FILTER_LENGTH/2;
2319 
2320#if MTK_NONCROSS_INLOOP_FILTER
2321  for (y= ypos, i = fl+ ypos; i < ypos+ iheight+ fl; i++, y++)
2322  {
2323    for (x= xpos, j = fl+ xpos; j < xpos+ iwidth+ fl; j++, x++)
2324    {
2325#else
2326  for (y=0, i = fl; i < m_im_height+fl; i++, y++)
2327  {
2328    for (x=0, j = fl; j < m_im_width+fl; j++, x++)
2329    {
2330#endif
2331#if MQT_BA_RA
2332      int varInd=m_varImg[y/var_step_size_h][x/var_step_size_w];
2333#else
2334      int varInd=m_varImg[i-fl][j-fl];
2335      imgpel *im1,*im2;
2336#endif
2337      int *coef = m_filterCoeffPrevSelected[varInd];
2338      pattern=m_patternTab_filt[filtNo];
2339      pixelInt= m_filterCoeffPrevSelected[varInd][sqrFiltLength-1]; 
2340
2341#if MQT_BA_RA
2342      if (filtNo == 2) //5x5
2343      {
2344        pixelInt += coef[22]* (imgY_rec[(i-fl+2)*Stride + j-fl]+imgY_rec[(i-fl-2)*Stride + j-fl]);
2345
2346        pixelInt += coef[30]* (imgY_rec[(i-fl+1)*Stride + j-fl+1]+imgY_rec[(i-fl-1)*Stride + j-fl-1]);
2347        pixelInt += coef[31]* (imgY_rec[(i-fl+1)*Stride + j-fl]  +imgY_rec[(i-fl-1)*Stride + j-fl]);
2348        pixelInt += coef[32]* (imgY_rec[(i-fl+1)*Stride + j-fl-1]+imgY_rec[(i-fl-1)*Stride + j-fl+1]);
2349
2350        pixelInt += coef[38]* (imgY_rec[(i-fl)*Stride + j-fl-2]+imgY_rec[(i-fl)*Stride + j-fl+2]);
2351        pixelInt += coef[39]* (imgY_rec[(i-fl)*Stride + j-fl-1]+imgY_rec[(i-fl)*Stride + j-fl+1]);
2352        pixelInt += coef[40]* (imgY_rec[(i-fl)*Stride + j-fl]);
2353      }
2354      else if (filtNo == 1) //7x7
2355      {
2356        pixelInt += coef[13]* (imgY_rec[(i-fl+3)*Stride + j-fl]+imgY_rec[(i-fl-3)*Stride + j-fl]);
2357
2358        p_imgY_pad = imgY_rec + (i-fl+2)*Stride;
2359        p_imgY_pad0 = imgY_rec + (i-fl-2)*Stride;
2360        pixelInt += coef[21]* (p_imgY_pad[j-fl+1]+p_imgY_pad0[j-fl-1]);
2361        pixelInt += coef[22]* (p_imgY_pad[j-fl]+p_imgY_pad0[j-fl]);
2362        pixelInt += coef[23]* (p_imgY_pad[j-fl-1]+p_imgY_pad0[j-fl+1]);
2363
2364        p_imgY_pad = imgY_rec + (i-fl+1)*Stride;
2365        p_imgY_pad0 = imgY_rec + (i-fl-1)*Stride;
2366        pixelInt += coef[29]* (p_imgY_pad[j-fl+2]+p_imgY_pad0[j-fl-2]);
2367        pixelInt += coef[30]* (p_imgY_pad[j-fl+1]+p_imgY_pad0[j-fl-1]);
2368        pixelInt += coef[31]* (p_imgY_pad[j-fl]+p_imgY_pad0[j-fl]);
2369        pixelInt += coef[32]* (p_imgY_pad[j-fl-1]+p_imgY_pad0[j-fl+1]);
2370        pixelInt += coef[33]* (p_imgY_pad[j-fl-2]+p_imgY_pad0[j-fl+2]);
2371
2372        p_imgY_pad = imgY_rec + (i-fl)*Stride;
2373        pixelInt += coef[37]* (p_imgY_pad[j-fl+3]+p_imgY_pad[j-fl-3]);
2374        pixelInt += coef[38]* (p_imgY_pad[j-fl+2]+p_imgY_pad[j-fl-2]);
2375        pixelInt += coef[39]* (p_imgY_pad[j-fl+1]+p_imgY_pad[j-fl-1]);
2376        pixelInt += coef[40]* (p_imgY_pad[j-fl]);
2377
2378      }
2379      else
2380      {
2381#if !TI_ALF_MAX_VSIZE_7
2382        pixelInt += coef[4]* (imgY_rec[(i-fl+4)*Stride + j-fl]+imgY_rec[(i-fl-4)*Stride + j-fl]);
2383#endif         
2384        p_imgY_pad = imgY_rec + (i-fl+3)*Stride;
2385        p_imgY_pad0 = imgY_rec + (i-fl-3)*Stride;
2386        pixelInt += coef[12]* (p_imgY_pad[j-fl+1]+p_imgY_pad0[j-fl-1]);
2387        pixelInt += coef[13]* (p_imgY_pad[j-fl]+p_imgY_pad0[j-fl]);
2388        pixelInt += coef[14]* (p_imgY_pad[j-fl-1]+p_imgY_pad0[j-fl+1]);
2389
2390        p_imgY_pad = imgY_rec + (i-fl+2)*Stride;
2391        p_imgY_pad0 = imgY_rec + (i-fl-2)*Stride;
2392        pixelInt += coef[20]* (p_imgY_pad[j-fl+2]+p_imgY_pad0[j-fl-2]);
2393        pixelInt += coef[21]* (p_imgY_pad[j-fl+1]+p_imgY_pad0[j-fl-1]);
2394        pixelInt += coef[22]* (p_imgY_pad[j-fl]+p_imgY_pad0[j-fl]);
2395        pixelInt += coef[23]* (p_imgY_pad[j-fl-1]+p_imgY_pad0[j-fl+1]);
2396        pixelInt += coef[24]* (p_imgY_pad[j-fl-2]+p_imgY_pad0[j-fl+2]);
2397
2398        p_imgY_pad = imgY_rec + (i-fl+1)*Stride;
2399        p_imgY_pad0 = imgY_rec + (i-fl-1)*Stride;
2400        pixelInt += coef[28]* (p_imgY_pad[j-fl+3]+p_imgY_pad0[j-fl-3]);
2401        pixelInt += coef[29]* (p_imgY_pad[j-fl+2]+p_imgY_pad0[j-fl-2]);
2402        pixelInt += coef[30]* (p_imgY_pad[j-fl+1]+p_imgY_pad0[j-fl-1]);
2403        pixelInt += coef[31]* (p_imgY_pad[j-fl]+p_imgY_pad0[j-fl]);
2404        pixelInt += coef[32]* (p_imgY_pad[j-fl-1]+p_imgY_pad0[j-fl+1]);
2405        pixelInt += coef[33]* (p_imgY_pad[j-fl-2]+p_imgY_pad0[j-fl+2]);
2406        pixelInt += coef[34]* (p_imgY_pad[j-fl-3]+p_imgY_pad0[j-fl+3]);
2407
2408        p_imgY_pad = imgY_rec + (i-fl)*Stride;
2409        pixelInt += coef[36]* (p_imgY_pad[j-fl+4]+p_imgY_pad[j-fl-4]);
2410        pixelInt += coef[37]* (p_imgY_pad[j-fl+3]+p_imgY_pad[j-fl-3]);
2411        pixelInt += coef[38]* (p_imgY_pad[j-fl+2]+p_imgY_pad[j-fl-2]);
2412        pixelInt += coef[39]* (p_imgY_pad[j-fl+1]+p_imgY_pad[j-fl-1]);
2413        pixelInt += coef[40]* (p_imgY_pad[j-fl]);
2414
2415      }
2416#else
2417
2418#if TI_ALF_MAX_VSIZE_7
2419      for (ii = -fl_tempV; ii < 0; ii++)
2420#else
2421      for (ii=-fl_temp; ii<0; ii++)
2422#endif
2423      {
2424        im1= &(ImgDec[(y+ii)*Stride + x-fl_temp-ii]);
2425        im2= &(ImgDec[(y-ii)*Stride + x+fl_temp+ii]);
2426        for (jj=-fl_temp-ii; jj<=fl_temp+ii; jj++,im1++,im2--)
2427          pixelInt+=((*im1+ *im2)*coef[*(pattern++)]);
2428      }
2429      im1= &(ImgDec[y*Stride + x-fl_temp]);
2430      im2= &(ImgDec[y*Stride + x+fl_temp]);
2431      for (jj=-fl_temp; jj<0; jj++,im1++,im2--)
2432        pixelInt+=((*im1+ *im2)*coef[*(pattern++)]);
2433      pixelInt+=(ImgDec[y*Stride + x]*coef[*(pattern++)]);
2434#endif 
2435
2436      pixelInt=(int)((pixelInt+offset) >> (NUM_BITS - 1));
2437      ImgRest[y*Stride + x] = Clip3(0, g_uiIBDI_MAX, pixelInt);
2438    }
2439  }
2440}
2441
2442Void TEncAdaptiveLoopFilter::xfindBestFilterVarPred(double **ySym, double ***ESym, double *pixAcc, int **filterCoeffSym, int **filterCoeffSymQuant, int filtNo, int *filters_per_fr_best, int varIndTab[], imgpel **imgY_rec, imgpel **varImg, imgpel **maskImg, imgpel **imgY_pad, double lambda_val)
2443{
2444  int filters_per_fr, firstFilt, coded, forceCoeff0,
2445  interval[NO_VAR_BINS][2], intervalBest[NO_VAR_BINS][2];
2446  int i, k, varInd;
2447  static double ***E_temp, **y_temp, *pixAcc_temp;
2448  static int **FilterCoeffQuantTemp;
2449  double  error, lambda, lagrangian, lagrangianMin;
2450 
2451  int sqrFiltLength;
2452  int *pattern, *patternMap, *weights;
2453  int numBits, coeffBits;
2454  double errorForce0CoeffTab[NO_VAR_BINS][2];
2455  int  codedVarBins[NO_VAR_BINS], createBistream /*, forceCoeff0 */;
2456  int  usePrevFilt[NO_VAR_BINS], usePrevFiltDefault[NO_VAR_BINS];
2457  static int first=0;
2458 
2459  for (i = 0; i < NO_VAR_BINS; i++)
2460    usePrevFiltDefault[i]=usePrevFilt[i]=1;
2461  lambda = lambda_val;
2462  sqrFiltLength=MAX_SQR_FILT_LENGTH;
2463 
2464  if (first==0)
2465  {
2466    initMatrix3D_double(&E_temp, NO_VAR_BINS, MAX_SQR_FILT_LENGTH, MAX_SQR_FILT_LENGTH);
2467    initMatrix_double(&y_temp, NO_VAR_BINS, MAX_SQR_FILT_LENGTH); 
2468    pixAcc_temp = (double *) calloc(NO_VAR_BINS, sizeof(double));
2469    initMatrix_int(&FilterCoeffQuantTemp, NO_VAR_BINS, MAX_SQR_FILT_LENGTH);
2470    first=1;
2471  }
2472 
2473  sqrFiltLength=m_sqrFiltLengthTab[filtNo];   
2474  Int fl = m_flTab[filtNo];
2475  weights=m_weightsTab[filtNo];               
2476  patternMap=m_patternMapTab[filtNo]; 
2477  pattern=m_patternTab[filtNo];
2478 
2479  memcpy(pixAcc_temp,pixAcc,sizeof(double)*NO_VAR_BINS);
2480  for (varInd=0; varInd<NO_VAR_BINS; varInd++)
2481  {
2482    memcpy(y_temp[varInd],ySym[varInd],sizeof(double)*sqrFiltLength);
2483    for (k=0; k<sqrFiltLength; k++)
2484      memcpy(E_temp[varInd][k],ESym[varInd][k],sizeof(double)*sqrFiltLength);
2485  }
2486 
2487  // zero all variables
2488  memset(varIndTab,0,sizeof(int)*NO_VAR_BINS);
2489 
2490  for(i = 0; i < NO_VAR_BINS; i++)
2491  {
2492    memset(filterCoeffSym[i],0,sizeof(int)*MAX_SQR_FILT_LENGTH);
2493    memset(filterCoeffSymQuant[i],0,sizeof(int)*MAX_SQR_FILT_LENGTH);
2494  }
2495 
2496  firstFilt=1;  lagrangianMin=0;
2497  filters_per_fr=NO_FILTERS;
2498 
2499  while(filters_per_fr>=1)
2500  {
2501    findFilterGroupingError(E_temp, y_temp, pixAcc_temp, interval, sqrFiltLength, filters_per_fr);
2502    findFilterCoeff(E_temp, y_temp, pixAcc_temp, filterCoeffSym, filterCoeffSymQuant, interval,
2503                    varIndTab, sqrFiltLength, filters_per_fr, weights, numBits=NUM_BITS,  errorForce0CoeffTab);
2504    lagrangian=xfindBestCoeffCodMethod(codedVarBins, &forceCoeff0, filterCoeffSymQuant, fl, 
2505                                       sqrFiltLength, filters_per_fr, errorForce0CoeffTab, &error, lambda);
2506   
2507    if (lagrangian<lagrangianMin || firstFilt==1)
2508    {
2509      firstFilt=0;
2510      lagrangianMin=lagrangian;
2511
2512      (*filters_per_fr_best)=filters_per_fr;
2513      memcpy(intervalBest, interval, NO_VAR_BINS*2*sizeof(int));
2514    }
2515    filters_per_fr--;
2516  }
2517 
2518  findFilterCoeff(E_temp, y_temp, pixAcc_temp, filterCoeffSym, filterCoeffSymQuant, intervalBest,
2519                  varIndTab, sqrFiltLength, (*filters_per_fr_best), weights, numBits=NUM_BITS, errorForce0CoeffTab);
2520 
2521  xfindBestCoeffCodMethod(codedVarBins, &forceCoeff0, filterCoeffSymQuant, fl, sqrFiltLength, 
2522                          (*filters_per_fr_best), errorForce0CoeffTab, &error, lambda);
2523 
2524  coded=1;
2525  if (forceCoeff0==1 && (*filters_per_fr_best)==1)
2526  {
2527    coded=0;
2528    coeffBits = xcodeAuxInfo(-1, (*filters_per_fr_best), varIndTab, 0, createBistream=0,filtNo, m_tempALFp);
2529  }
2530  else
2531  {
2532    coeffBits = xcodeAuxInfo(filtNo, (*filters_per_fr_best), varIndTab, 0, createBistream=0,filtNo, m_tempALFp);
2533  }
2534
2535  if (forceCoeff0==0)
2536  {
2537    coeffBits += xsendAllFiltersPPPred(filterCoeffSymQuant, fl, sqrFiltLength, 
2538      (*filters_per_fr_best), createBistream=0, m_tempALFp);
2539  }
2540  else
2541  {
2542    if ((*filters_per_fr_best)==1)
2543    {
2544      for(varInd=0; varInd<(*filters_per_fr_best); varInd++)
2545      {
2546        memset(filterCoeffSym[varInd],0,sizeof(int)*MAX_SQR_FILT_LENGTH);
2547        memset(filterCoeffSymQuant[varInd],0,sizeof(int)*MAX_SQR_FILT_LENGTH);
2548      }
2549    }
2550    else
2551    {
2552      coeffBits += xsendAllFiltersPPPredForce0(filterCoeffSymQuant, fl, sqrFiltLength, 
2553        (*filters_per_fr_best), codedVarBins, createBistream=0, m_tempALFp);
2554
2555      for(varInd=0; varInd<(*filters_per_fr_best); varInd++)
2556      {
2557        if (codedVarBins[varInd]==0)
2558        {
2559          memset(filterCoeffSym[varInd],0,sizeof(int)*MAX_SQR_FILT_LENGTH);
2560          memset(filterCoeffSymQuant[varInd],0,sizeof(int)*MAX_SQR_FILT_LENGTH);
2561        }
2562      }
2563    }
2564  }
2565}
2566
2567
2568Void TEncAdaptiveLoopFilter::xcalcPredFilterCoeff(int filtNo)
2569{
2570  int *patternMap, varInd, i, k;
2571 
2572  patternMap=m_patternMapTab[filtNo];
2573  for(varInd=0; varInd<NO_VAR_BINS; ++varInd)
2574  {
2575    k=0;
2576    for(i = 0; i < MAX_SQR_FILT_LENGTH; i++)
2577    {
2578      if (patternMap[i]>0)
2579      {
2580        m_filterCoeffPrevSelected[varInd][i]=m_filterCoeffSym[m_varIndTab[varInd]][k];
2581        k++;
2582      }
2583      else
2584      {
2585        m_filterCoeffPrevSelected[varInd][i]=0;
2586      }
2587#if MQT_ALF_NPASS
2588      if (m_iALFEncodePassReduction && (!m_iUsePreviousFilter || !m_iDesignCurrentFilter))
2589      {
2590        if((m_iCurrentPOC%m_iGOPSize) == 0)
2591        {
2592          m_aiFilterCoeffSaved[0][varInd][i] = m_aiFilterCoeffSaved[m_iGOPSize][varInd][i]; 
2593          m_aiFilterCoeffSaved[m_iGOPSize][varInd][i] = m_filterCoeffPrevSelected[varInd][i]; 
2594        }
2595        else
2596        {
2597          m_aiFilterCoeffSaved[m_iCurrentPOC%m_iGOPSize][varInd][i] = m_filterCoeffPrevSelected[varInd][i];
2598        }
2599      }
2600#endif
2601    }
2602  }
2603}
2604
2605#if MQT_ALF_NPASS
2606UInt TEncAdaptiveLoopFilter::xcodeFiltCoeff(int **filterCoeffSymQuant, int filtNo, int varIndTab[], int filters_per_fr_best, int frNo, ALFParam* ALFp)
2607#else
2608Void TEncAdaptiveLoopFilter::xcodeFiltCoeff(int **filterCoeffSymQuant, int filtNo, int varIndTab[], int filters_per_fr_best, int frNo, ALFParam* ALFp)
2609#endif
2610{
2611  int varInd, forceCoeff0, codedVarBins[NO_VAR_BINS], coeffBits, createBistream,   sqrFiltLength=m_sqrFiltLengthTab[filtNo], 
2612  fl=m_flTab[filtNo], coded;
2613 
2614  ALFp->filters_per_group_diff = filters_per_fr_best;
2615  ALFp->filters_per_group = filters_per_fr_best;
2616 
2617  for(varInd=0; varInd<filters_per_fr_best; varInd++)
2618  {
2619    codedVarBins[varInd] = 1;
2620  }
2621  memcpy (ALFp->codedVarBins, codedVarBins, sizeof(int)*NO_VAR_BINS);
2622  forceCoeff0=0;
2623  for(varInd=0; varInd<filters_per_fr_best; varInd++)
2624  {
2625    if (codedVarBins[varInd] == 0)
2626    {
2627      forceCoeff0=1;
2628      break;
2629    }
2630  }
2631
2632  coded=1;
2633  if (forceCoeff0==1 && filters_per_fr_best==1)
2634  {
2635    coded=0;
2636    coeffBits = xcodeAuxInfo(-1, filters_per_fr_best, varIndTab, frNo, createBistream=1,filtNo, ALFp);
2637  }
2638  else
2639  {
2640    coeffBits = xcodeAuxInfo(filtNo, filters_per_fr_best, varIndTab, frNo, createBistream=1,filtNo, ALFp);
2641  }
2642 
2643  ALFp->forceCoeff0 = forceCoeff0;
2644  ALFp->predMethod = 0;
2645  ALFp->num_coeff = sqrFiltLength;
2646  ALFp->realfiltNo=filtNo;
2647  if (filters_per_fr_best <= 1)
2648  {
2649    ALFp->forceCoeff0 = 0;
2650    ALFp->predMethod = 0;
2651  }
2652 
2653  if (forceCoeff0==0) 
2654  {
2655    coeffBits += xsendAllFiltersPPPred(filterCoeffSymQuant, fl, sqrFiltLength, 
2656                                       filters_per_fr_best, createBistream=1, ALFp);
2657  }
2658  else if (filters_per_fr_best>1)
2659  {
2660    coeffBits += xsendAllFiltersPPPredForce0(filterCoeffSymQuant, fl, sqrFiltLength, 
2661                                             filters_per_fr_best, codedVarBins, createBistream=1, ALFp);
2662  }
2663
2664#if MQT_ALF_NPASS
2665  return (UInt)coeffBits;
2666#endif
2667}
2668
2669
2670
2671#if TSB_ALF_HEADER
2672Void TEncAdaptiveLoopFilter::xSetCUAlfCtrlFlags_qc(UInt uiAlfCtrlDepth, TComPicYuv* pcPicOrg, TComPicYuv* pcPicDec, TComPicYuv* pcPicRest, UInt64& ruiDist, ALFParam *pAlfParam)
2673#else
2674Void TEncAdaptiveLoopFilter::xSetCUAlfCtrlFlags_qc(UInt uiAlfCtrlDepth, TComPicYuv* pcPicOrg, TComPicYuv* pcPicDec, TComPicYuv* pcPicRest, UInt64& ruiDist)
2675#endif
2676{
2677  ruiDist = 0;
2678#if TSB_ALF_HEADER
2679  pAlfParam->num_alf_cu_flag = 0;
2680#endif
2681 
2682  for( UInt uiCUAddr = 0; uiCUAddr < m_pcPic->getNumCUsInFrame() ; uiCUAddr++ )
2683  {
2684    TComDataCU* pcCU = m_pcPic->getCU( uiCUAddr );
2685#if TSB_ALF_HEADER
2686    xSetCUAlfCtrlFlag_qc(pcCU, 0, 0, uiAlfCtrlDepth, pcPicOrg, pcPicDec, pcPicRest, ruiDist, pAlfParam);
2687#else
2688    xSetCUAlfCtrlFlag_qc(pcCU, 0, 0, uiAlfCtrlDepth, pcPicOrg, pcPicDec, pcPicRest, ruiDist);
2689#endif
2690  }
2691}
2692
2693#if TSB_ALF_HEADER
2694Void TEncAdaptiveLoopFilter::xSetCUAlfCtrlFlag_qc(TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth, UInt uiAlfCtrlDepth, TComPicYuv* pcPicOrg, TComPicYuv* pcPicDec, TComPicYuv* pcPicRest, UInt64& ruiDist, ALFParam *pAlfParam)
2695#else
2696Void TEncAdaptiveLoopFilter::xSetCUAlfCtrlFlag_qc(TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth, UInt uiAlfCtrlDepth, TComPicYuv* pcPicOrg, TComPicYuv* pcPicDec, TComPicYuv* pcPicRest, UInt64& ruiDist)
2697#endif
2698{
2699  Bool bBoundary = false;
2700  UInt uiLPelX   = pcCU->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiAbsPartIdx] ];
2701  UInt uiRPelX   = uiLPelX + (g_uiMaxCUWidth>>uiDepth)  - 1;
2702  UInt uiTPelY   = pcCU->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiAbsPartIdx] ];
2703  UInt uiBPelY   = uiTPelY + (g_uiMaxCUHeight>>uiDepth) - 1;
2704 
2705  if( ( uiRPelX >= pcCU->getSlice()->getSPS()->getWidth() ) || ( uiBPelY >= pcCU->getSlice()->getSPS()->getHeight() ) )
2706  {
2707    bBoundary = true;
2708  }
2709 
2710  if( ( ( uiDepth < pcCU->getDepth( uiAbsPartIdx ) ) && ( uiDepth < (g_uiMaxCUDepth-g_uiAddCUDepth) ) ) || bBoundary )
2711  {
2712    UInt uiQNumParts = ( m_pcPic->getNumPartInCU() >> (uiDepth<<1) )>>2;
2713    for ( UInt uiPartUnitIdx = 0; uiPartUnitIdx < 4; uiPartUnitIdx++, uiAbsPartIdx+=uiQNumParts )
2714    {
2715      uiLPelX   = pcCU->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiAbsPartIdx] ];
2716      uiTPelY   = pcCU->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiAbsPartIdx] ];
2717     
2718      if( ( uiLPelX < pcCU->getSlice()->getSPS()->getWidth() ) && ( uiTPelY < pcCU->getSlice()->getSPS()->getHeight() ) )
2719#if TSB_ALF_HEADER
2720        xSetCUAlfCtrlFlag_qc(pcCU, uiAbsPartIdx, uiDepth+1, uiAlfCtrlDepth, pcPicOrg, pcPicDec, pcPicRest, ruiDist, pAlfParam);
2721#else
2722      xSetCUAlfCtrlFlag_qc(pcCU, uiAbsPartIdx, uiDepth+1, uiAlfCtrlDepth, pcPicOrg, pcPicDec, pcPicRest, ruiDist);
2723#endif
2724    }
2725    return;
2726  }
2727 
2728  if( uiDepth > uiAlfCtrlDepth && !pcCU->isFirstAbsZorderIdxInDepth(uiAbsPartIdx, uiAlfCtrlDepth))
2729  {
2730    return;
2731  }
2732 
2733  UInt uiCUAddr = pcCU->getAddr();
2734  UInt64 uiRecSSD = 0;
2735  UInt64 uiFiltSSD = 0;
2736 
2737  Int iWidth;
2738  Int iHeight;
2739  UInt uiSetDepth;
2740 
2741  if (uiDepth > uiAlfCtrlDepth && pcCU->isFirstAbsZorderIdxInDepth(uiAbsPartIdx, uiAlfCtrlDepth))
2742  {
2743    iWidth = g_uiMaxCUWidth >> uiAlfCtrlDepth;
2744    iHeight = g_uiMaxCUHeight >> uiAlfCtrlDepth;
2745   
2746    uiRPelX   = uiLPelX + iWidth  - 1;
2747    uiBPelY   = uiTPelY + iHeight - 1;
2748
2749    if( uiRPelX >= pcCU->getSlice()->getSPS()->getWidth() )
2750    {
2751      iWidth = pcCU->getSlice()->getSPS()->getWidth() - uiLPelX;
2752    }
2753   
2754    if( uiBPelY >= pcCU->getSlice()->getSPS()->getHeight() )
2755    {
2756      iHeight = pcCU->getSlice()->getSPS()->getHeight() - uiTPelY;
2757    }
2758   
2759    uiSetDepth = uiAlfCtrlDepth;
2760  }
2761  else
2762  {
2763    iWidth = pcCU->getWidth(uiAbsPartIdx);
2764    iHeight = pcCU->getHeight(uiAbsPartIdx);
2765    uiSetDepth = uiDepth;
2766  }
2767 
2768  Pel* pOrg = pcPicOrg->getLumaAddr(uiCUAddr, uiAbsPartIdx);
2769  Pel* pRec = pcPicDec->getLumaAddr(uiCUAddr, uiAbsPartIdx);
2770  Pel* pFilt = pcPicRest->getLumaAddr(uiCUAddr, uiAbsPartIdx);
2771 
2772  uiRecSSD  += xCalcSSD( pOrg, pRec,  iWidth, iHeight, pcPicOrg->getStride() );
2773  uiFiltSSD += xCalcSSD( pOrg, pFilt, iWidth, iHeight, pcPicOrg->getStride() );
2774 
2775  if (uiFiltSSD < uiRecSSD)
2776  {
2777    ruiDist += uiFiltSSD;
2778    pcCU->setAlfCtrlFlagSubParts(1, uiAbsPartIdx, uiSetDepth);
2779#if TSB_ALF_HEADER
2780    pAlfParam->alf_cu_flag[pAlfParam->num_alf_cu_flag]=1;
2781#endif
2782    for (int i=uiTPelY ;i<=min(uiBPelY,(unsigned int)(pcPicOrg->getHeight()-1))  ;i++)
2783    {
2784      for (int j=uiLPelX ;j<=min(uiRPelX,(unsigned int)(pcPicOrg->getWidth()-1)) ;j++)
2785      { 
2786        m_maskImg[i][j]=1;
2787      }
2788    }
2789  }
2790  else
2791  {
2792    ruiDist += uiRecSSD;
2793    pcCU->setAlfCtrlFlagSubParts(0, uiAbsPartIdx, uiSetDepth);
2794#if TSB_ALF_HEADER
2795    pAlfParam->alf_cu_flag[pAlfParam->num_alf_cu_flag]=0;
2796#endif
2797    for (int i=uiTPelY ;i<=min(uiBPelY,(unsigned int)(pcPicOrg->getHeight()-1))  ;i++)
2798    {
2799      for (int j=uiLPelX ;j<=min(uiRPelX,(unsigned int)(pcPicOrg->getWidth()-1)) ;j++)
2800      { 
2801        m_maskImg[i][j]=0;
2802      }
2803    }
2804  }
2805#if TSB_ALF_HEADER
2806  pAlfParam->num_alf_cu_flag++;
2807#endif
2808}
2809
2810Void TEncAdaptiveLoopFilter::xReDesignFilterCoeff_qc(TComPicYuv* pcPicOrg, TComPicYuv* pcPicDec, TComPicYuv* pcPicRest, Bool bReadCorr)
2811{
2812 
2813  Int tap = m_pcTempAlfParam->tap;
2814  Int    LumaStride = pcPicOrg->getStride();
2815  imgpel* pOrg = (imgpel*)pcPicOrg->getLumaAddr();
2816  imgpel* pDec = (imgpel*)pcPicDec->getLumaAddr();
2817  imgpel* pRest = (imgpel*)pcPicRest->getLumaAddr();
2818  xFirstFilteringFrameLuma(pOrg, pDec, pRest, m_pcTempAlfParam, tap, LumaStride); 
2819 
2820}
2821Void TEncAdaptiveLoopFilter::xCUAdaptiveControl_qc(TComPicYuv* pcPicOrg, TComPicYuv* pcPicDec, TComPicYuv* pcPicRest, UInt64& ruiMinRate, UInt64& ruiMinDist, Double& rdMinCost)
2822{
2823#if MQT_ALF_NPASS
2824  imgpel** maskImgTemp;
2825
2826  if(m_iALFEncodePassReduction == 2)
2827  {
2828    get_mem2Dpel(&maskImgTemp, m_im_height, m_im_width);
2829  }
2830#endif
2831
2832  m_pcEntropyCoder->setAlfCtrl(true);
2833 
2834  UInt uiBestDepth = 0;
2835 
2836  ALFParam cFrmAlfParam;
2837  allocALFParam(&cFrmAlfParam);
2838  copyALFParam(&cFrmAlfParam, m_pcBestAlfParam);
2839 
2840  for (UInt uiDepth = 0; uiDepth < g_uiMaxCUDepth; uiDepth++)
2841  {
2842    m_pcEntropyCoder->setMaxAlfCtrlDepth(uiDepth);
2843    pcPicRest->copyToPicLuma(m_pcPicYuvTmp);
2844    copyALFParam(m_pcTempAlfParam, &cFrmAlfParam);
2845    m_pcTempAlfParam->cu_control_flag = 1;
2846   
2847#if MQT_ALF_NPASS
2848    for (UInt uiRD = 0; uiRD <= m_iALFNumOfRedesign; uiRD++)
2849#else
2850    for (UInt uiRD = 0; uiRD <= ALF_NUM_OF_REDESIGN; uiRD++)
2851#endif
2852    {
2853      if (uiRD)
2854      {
2855        // re-design filter coefficients
2856        xReDesignFilterCoeff_qc(pcPicOrg, pcPicDec, m_pcPicYuvTmp, true); //use filtering of mine
2857      }
2858     
2859      UInt64 uiRate, uiDist;
2860      Double dCost;
2861     //m_pcPicYuvTmp: filtered signal, pcPicDec: orig reconst
2862#if TSB_ALF_HEADER
2863      xSetCUAlfCtrlFlags_qc(uiDepth, pcPicOrg, pcPicDec, m_pcPicYuvTmp, uiDist, m_pcTempAlfParam); //set up varImg here
2864#else
2865      xSetCUAlfCtrlFlags_qc(uiDepth, pcPicOrg, pcPicDec, m_pcPicYuvTmp, uiDist); //set up varImg here
2866#endif
2867     
2868      xCalcRDCost(m_pcTempAlfParam, uiRate, uiDist, dCost);
2869     
2870      if (dCost < rdMinCost)
2871      {
2872        uiBestDepth = uiDepth;
2873        rdMinCost = dCost;
2874        ruiMinDist = uiDist;
2875        ruiMinRate = uiRate;
2876        m_pcPicYuvTmp->copyToPicLuma(m_pcPicYuvBest);
2877        copyALFParam(m_pcBestAlfParam, m_pcTempAlfParam);
2878        //save maskImg
2879        xCopyTmpAlfCtrlFlagsFrom();
2880#if MQT_ALF_NPASS
2881        if(m_iALFEncodePassReduction == 2)
2882        {
2883          ::memcpy(maskImgTemp[0], m_maskImg[0], sizeof(imgpel)*m_im_height* m_im_width);
2884        }
2885#endif
2886      }
2887    }
2888  }
2889 
2890  if (m_pcBestAlfParam->cu_control_flag)
2891  {
2892#if MQT_ALF_NPASS
2893    if(m_iALFEncodePassReduction == 2)
2894    {
2895      UInt uiDepth = uiBestDepth;
2896      ::memcpy(m_maskImg[0], maskImgTemp[0], sizeof(imgpel)*m_im_height* m_im_width);
2897      xCopyTmpAlfCtrlFlagsTo();
2898 
2899      copyALFParam(&cFrmAlfParam, m_pcBestAlfParam);
2900
2901      m_pcEntropyCoder->setAlfCtrl(true);
2902      m_pcEntropyCoder->setMaxAlfCtrlDepth(uiDepth);
2903      copyALFParam(m_pcTempAlfParam, &cFrmAlfParam);
2904
2905      xReDesignFilterCoeff_qc(pcPicOrg, pcPicDec, m_pcPicYuvTmp, true); //use filtering of mine
2906
2907      UInt64 uiRate, uiDist;
2908      Double dCost;
2909
2910#if TSB_ALF_HEADER
2911      xSetCUAlfCtrlFlags_qc(uiDepth, pcPicOrg, pcPicDec, m_pcPicYuvTmp, uiDist, m_pcTempAlfParam); //set up varImg here
2912#else
2913      xSetCUAlfCtrlFlags_qc(uiDepth, pcPicOrg, pcPicDec, m_pcPicYuvTmp, uiDist); //set up varImg here
2914#endif
2915
2916      xCalcRDCost(m_pcTempAlfParam, uiRate, uiDist, dCost);
2917
2918      if (dCost < rdMinCost)
2919      {
2920        rdMinCost = dCost;
2921        ruiMinDist = uiDist;
2922        ruiMinRate = uiRate;
2923        m_pcPicYuvTmp->copyToPicLuma(m_pcPicYuvBest);
2924        copyALFParam(m_pcBestAlfParam, m_pcTempAlfParam);
2925        xCopyTmpAlfCtrlFlagsFrom();
2926      }
2927    }
2928#endif
2929
2930    m_pcEntropyCoder->setAlfCtrl(true);
2931    m_pcEntropyCoder->setMaxAlfCtrlDepth(uiBestDepth);
2932    xCopyTmpAlfCtrlFlagsTo();
2933    m_pcPicYuvBest->copyToPicLuma(pcPicRest);//copy m_pcPicYuvBest to pcPicRest
2934    xCopyDecToRestCUs(pcPicDec, pcPicRest); //pcPicRest = pcPicDec
2935  }
2936  else
2937  {
2938    m_pcEntropyCoder->setAlfCtrl(false);
2939    m_pcEntropyCoder->setMaxAlfCtrlDepth(0);
2940  }
2941  freeALFParam(&cFrmAlfParam);
2942
2943#if MQT_ALF_NPASS
2944  if(m_iALFEncodePassReduction == 2)
2945  {
2946    free_mem2Dpel(maskImgTemp);
2947  }
2948#endif
2949}
2950
2951
2952Void TEncAdaptiveLoopFilter::xFilterTapDecision_qc(TComPicYuv* pcPicOrg, TComPicYuv* pcPicDec, TComPicYuv* pcPicRest, UInt64& ruiMinRate, UInt64& ruiMinDist, Double& rdMinCost)
2953{
2954#if MQT_ALF_NPASS
2955  if(m_iALFEncodePassReduction)
2956  {
2957    return;  // filter tap has been decided in xEncALFLuma_qc
2958  }
2959#endif
2960
2961  // restriction for non-referenced B-slice
2962  if (m_eSliceType == B_SLICE && m_iPicNalReferenceIdc == 0)
2963  {
2964    return;
2965  }
2966 
2967  UInt64 uiRate, uiDist;
2968  Double dCost;
2969 
2970  if (m_pcBestAlfParam->cu_control_flag)
2971  {
2972    xCopyTmpAlfCtrlFlagsFrom();
2973  }
2974 
2975  Bool bChanged = false;
2976  for (Int iTap = ALF_MIN_NUM_TAP; iTap <= ALF_MAX_NUM_TAP; iTap += 2)
2977  {
2978    copyALFParam(m_pcTempAlfParam, m_pcBestAlfParam);
2979    m_pcTempAlfParam->tap = iTap;
2980#if TI_ALF_MAX_VSIZE_7
2981    m_pcTempAlfParam->tapV = TComAdaptiveLoopFilter::ALFTapHToTapV(m_pcTempAlfParam->tap);
2982    m_pcTempAlfParam->num_coeff = TComAdaptiveLoopFilter::ALFTapHToNumCoeff(m_pcTempAlfParam->tap); 
2983#else
2984    m_pcTempAlfParam->num_coeff = (Int)(iTap*iTap/4) + 2; 
2985#endif
2986   
2987    if (m_pcTempAlfParam->cu_control_flag)
2988    {
2989      xReDesignFilterCoeff_qc(pcPicOrg, pcPicDec, m_pcPicYuvTmp, false);
2990#if TSB_ALF_HEADER
2991      xSetCUAlfCtrlFlags_qc(m_pcEntropyCoder->getMaxAlfCtrlDepth(), pcPicOrg, pcPicDec, m_pcPicYuvTmp, uiDist, m_pcTempAlfParam);
2992#else
2993      xSetCUAlfCtrlFlags_qc(m_pcEntropyCoder->getMaxAlfCtrlDepth(), pcPicOrg, pcPicDec, m_pcPicYuvTmp, uiDist);
2994#endif
2995      xCalcRDCost(m_pcTempAlfParam, uiRate, uiDist, dCost);
2996    }
2997
2998    else
2999    {
3000      Int    Height = pcPicOrg->getHeight();
3001      Int    Width = pcPicOrg->getWidth();
3002      for (Int i=0; i<Height; i++)
3003      {
3004        for (Int j=0; j<Width; j++)
3005        {
3006          m_maskImg[i][j] = 1;
3007        }
3008      }
3009      xReDesignFilterCoeff_qc(pcPicOrg, pcPicDec, m_pcPicYuvTmp, false);
3010
3011      xCalcRDCost(pcPicOrg, m_pcPicYuvTmp, m_pcTempAlfParam, uiRate, uiDist, dCost);
3012    }
3013
3014    if (dCost < rdMinCost)
3015    {
3016      rdMinCost = dCost;
3017      ruiMinDist = uiDist;
3018      ruiMinRate = uiRate;
3019      m_pcPicYuvTmp->copyToPicLuma(m_pcPicYuvBest);
3020      copyALFParam(m_pcBestAlfParam, m_pcTempAlfParam);
3021      bChanged = true;
3022      if (m_pcTempAlfParam->cu_control_flag)
3023      {
3024        xCopyTmpAlfCtrlFlagsFrom();
3025      }
3026    }
3027  }
3028 
3029  if (m_pcBestAlfParam->cu_control_flag)
3030  {
3031    xCopyTmpAlfCtrlFlagsTo();
3032    if (bChanged)
3033    {
3034      m_pcPicYuvBest->copyToPicLuma(pcPicRest);
3035      xCopyDecToRestCUs(pcPicDec, pcPicRest);
3036    }
3037  }
3038  else if (m_pcBestAlfParam->tap > ALF_MIN_NUM_TAP)
3039  {
3040    m_pcPicYuvBest->copyToPicLuma(pcPicRest);
3041  }
3042 
3043  copyALFParam(m_pcTempAlfParam, m_pcBestAlfParam);
3044}
3045
3046
3047#define ROUND(a)  (((a) < 0)? (int)((a) - 0.5) : (int)((a) + 0.5))
3048#define REG              0.0001
3049#define REG_SQR          0.0000001
3050
3051//Find filter coeff related
3052Int TEncAdaptiveLoopFilter::gnsCholeskyDec(double **inpMatr, double outMatr[MAX_SQR_FILT_LENGTH][MAX_SQR_FILT_LENGTH], int noEq)
3053{ 
3054  int 
3055  i, j, k;     /* Looping Variables */
3056  double 
3057  scale;       /* scaling factor for each row */
3058  double 
3059  invDiag[MAX_SQR_FILT_LENGTH];  /* Vector of the inverse of diagonal entries of outMatr */
3060 
3061 
3062  /*
3063   *  Cholesky decomposition starts
3064   */
3065 
3066  for(i = 0; i < noEq; i++)
3067  {
3068    for(j = i; j < noEq; j++)
3069    {
3070      /* Compute the scaling factor */
3071      scale=inpMatr[i][j];
3072      if ( i > 0) for( k = i - 1 ; k >= 0 ; k--)
3073        scale -= outMatr[k][j] * outMatr[k][i];
3074     
3075      /* Compute i'th row of outMatr */
3076      if(i==j)
3077      {
3078        if(scale <= REG_SQR ) // if(scale <= 0 )  /* If inpMatr is singular */
3079        {
3080          return(0);
3081        }
3082        else              /* Normal operation */
3083          invDiag[i] =  1.0/(outMatr[i][i]=sqrt(scale));
3084      }
3085      else
3086      {
3087        outMatr[i][j] = scale*invDiag[i]; /* Upper triangular part          */
3088        outMatr[j][i] = 0.0;              /* Lower triangular part set to 0 */
3089      }                   
3090    }
3091  }
3092  return(1); /* Signal that Cholesky factorization is successfully performed */
3093}
3094
3095
3096Void TEncAdaptiveLoopFilter::gnsTransposeBacksubstitution(double U[MAX_SQR_FILT_LENGTH][MAX_SQR_FILT_LENGTH], double rhs[], double x[], int order)
3097{
3098  int 
3099  i,j;              /* Looping variables */
3100  double 
3101  sum;              /* Holds backsubstitution from already handled rows */
3102 
3103  /* Backsubstitution starts */
3104  x[0] = rhs[0]/U[0][0];               /* First row of U'                   */
3105  for (i = 1; i < order; i++)
3106  {         /* For the rows 1..order-1           */
3107   
3108    for (j = 0, sum = 0.0; j < i; j++) /* Backsubst already solved unknowns */
3109      sum += x[j]*U[j][i];
3110   
3111    x[i]=(rhs[i] - sum)/U[i][i];       /* i'th component of solution vect.  */
3112  }
3113}
3114
3115
3116
3117Void  TEncAdaptiveLoopFilter::gnsBacksubstitution(double R[MAX_SQR_FILT_LENGTH][MAX_SQR_FILT_LENGTH], double z[MAX_SQR_FILT_LENGTH], int R_size, double A[MAX_SQR_FILT_LENGTH])
3118{
3119  int i, j;
3120  double sum;
3121 
3122  R_size--;
3123 
3124  A[R_size] = z[R_size] / R[R_size][R_size];
3125 
3126  for (i = R_size-1; i >= 0; i--)
3127  {
3128    for (j = i+1, sum = 0.0; j <= R_size; j++)
3129      sum += R[i][j] * A[j];
3130   
3131    A[i] = (z[i] - sum) / R[i][i];
3132  }
3133}
3134
3135
3136Int TEncAdaptiveLoopFilter::gnsSolveByChol(double **LHS, double *rhs, double *x, int noEq)
3137{ 
3138  double aux[MAX_SQR_FILT_LENGTH];     /* Auxiliary vector */
3139  double U[MAX_SQR_FILT_LENGTH][MAX_SQR_FILT_LENGTH];    /* Upper triangular Cholesky factor of LHS */
3140  int  i, singular;          /* Looping variable */
3141 
3142  /* The equation to be solved is LHSx = rhs */
3143 
3144  /* Compute upper triangular U such that U'*U = LHS */
3145  if(gnsCholeskyDec(LHS, U, noEq)) /* If Cholesky decomposition has been successful */
3146  {
3147    singular=1;
3148    /* Now, the equation is  U'*U*x = rhs, where U is upper triangular
3149     * Solve U'*aux = rhs for aux
3150     */
3151    gnsTransposeBacksubstitution(U, rhs, aux, noEq);         
3152   
3153    /* The equation is now U*x = aux, solve it for x (new motion coefficients) */
3154    gnsBacksubstitution(U, aux, noEq, x);   
3155   
3156  }
3157  else /* LHS was singular */ 
3158  {
3159    singular=0;
3160   
3161    /* Regularize LHS */
3162    for(i=0; i<noEq; i++)
3163      LHS[i][i] += REG;
3164    /* Compute upper triangular U such that U'*U = regularized LHS */
3165    singular = gnsCholeskyDec(LHS, U, noEq);
3166    /* Solve  U'*aux = rhs for aux */ 
3167    gnsTransposeBacksubstitution(U, rhs, aux, noEq);   
3168   
3169    /* Solve U*x = aux for x */
3170    gnsBacksubstitution(U, aux, noEq, x);
3171  } 
3172  return(singular);
3173}
3174
3175
3176//////////////////////////////////////////////////////////////////////////////////////////
3177
3178
3179Void TEncAdaptiveLoopFilter::add_A(double **Amerged, double ***A, int start, int stop, int size)
3180{ 
3181  int
3182  i, j, ind;          /* Looping variable */
3183 
3184  for (i=0; i<size; i++)
3185  {
3186    for (j=0; j<size; j++)
3187    {
3188      Amerged[i][j]=0;
3189      for (ind=start; ind<=stop; ind++)
3190      {
3191        Amerged[i][j]+=A[ind][i][j];
3192      }
3193    }
3194  }
3195}
3196
3197Void TEncAdaptiveLoopFilter::add_b(double *bmerged, double **b, int start, int stop, int size)
3198{ 
3199  int
3200  i, ind;          /* Looping variable */
3201 
3202  for (i=0; i<size; i++)
3203  {
3204    bmerged[i]=0;
3205    for (ind=start; ind<=stop; ind++)
3206    {
3207      bmerged[i]+=b[ind][i];
3208    }
3209  }
3210}
3211
3212double TEncAdaptiveLoopFilter::calculateErrorCoeffProvided(double **A, double *b, double *c, int size)
3213{
3214  int i, j;
3215  double error, sum=0;
3216 
3217  error=0;
3218  for (i=0; i<size; i++)   //diagonal
3219  {
3220    sum=0;
3221    for (j=i+1; j<size; j++)
3222      sum+=(A[j][i]+A[i][j])*c[j];
3223    error+=(A[i][i]*c[i]+sum-2*b[i])*c[i];
3224  }
3225 
3226  return(error);
3227}
3228
3229double TEncAdaptiveLoopFilter::calculateErrorAbs(double **A, double *b, double y, int size)
3230{
3231  int i;
3232  double error, sum;
3233  double c[MAX_SQR_FILT_LENGTH];
3234 
3235  gnsSolveByChol(A, b, c, size);
3236 
3237  sum=0;
3238  for (i=0; i<size; i++)
3239  {
3240    sum+=c[i]*b[i];
3241  }
3242  error=y-sum;
3243 
3244  return(error);
3245}
3246
3247double TEncAdaptiveLoopFilter::mergeFiltersGreedy(double **yGlobalSeq, double ***EGlobalSeq, double *pixAccGlobalSeq, int intervalBest[NO_VAR_BINS][2], int sqrFiltLength, int noIntervals)
3248{
3249  int first, ind, ind1, ind2, i, j, bestToMerge ;
3250  double error, error1, error2, errorMin;
3251  static double pixAcc_temp, error_tab[NO_VAR_BINS],error_comb_tab[NO_VAR_BINS];
3252  static int indexList[NO_VAR_BINS], available[NO_VAR_BINS], noRemaining;
3253  if (noIntervals == NO_FILTERS)
3254  {
3255    noRemaining=NO_VAR_BINS;
3256    for (ind=0; ind<NO_VAR_BINS; ind++)
3257    {
3258      indexList[ind]=ind; 
3259      available[ind]=1;
3260      m_pixAcc_merged[ind]=pixAccGlobalSeq[ind];
3261      memcpy(m_y_merged[ind],yGlobalSeq[ind],sizeof(double)*sqrFiltLength);
3262      for (i=0; i<sqrFiltLength; i++)
3263      {
3264        memcpy(m_E_merged[ind][i],EGlobalSeq[ind][i],sizeof(double)*sqrFiltLength);
3265      }
3266    }
3267  }
3268  // Try merging different matrices
3269  if (noIntervals == NO_FILTERS)
3270  {
3271    for (ind=0; ind<NO_VAR_BINS; ind++)
3272    {
3273      error_tab[ind]=calculateErrorAbs(m_E_merged[ind], m_y_merged[ind], m_pixAcc_merged[ind], sqrFiltLength);
3274    }
3275    for (ind=0; ind<NO_VAR_BINS-1; ind++)
3276    {
3277      ind1=indexList[ind];
3278      ind2=indexList[ind+1];
3279     
3280      error1=error_tab[ind1];
3281      error2=error_tab[ind2];
3282     
3283      pixAcc_temp=m_pixAcc_merged[ind1]+m_pixAcc_merged[ind2];
3284      for (i=0; i<sqrFiltLength; i++)
3285      {
3286        m_y_temp[i]=m_y_merged[ind1][i]+m_y_merged[ind2][i];
3287        for (j=0; j<sqrFiltLength; j++)
3288        {
3289          m_E_temp[i][j]=m_E_merged[ind1][i][j]+m_E_merged[ind2][i][j];
3290        }
3291      }
3292      error_comb_tab[ind1]=calculateErrorAbs(m_E_temp, m_y_temp, pixAcc_temp, sqrFiltLength)-error1-error2;
3293    }
3294  }
3295  while (noRemaining>noIntervals)
3296  {
3297    errorMin=0; first=1;
3298    bestToMerge = 0;
3299    for (ind=0; ind<noRemaining-1; ind++)
3300    {
3301      error = error_comb_tab[indexList[ind]];
3302      if ((error<errorMin || first==1))
3303      {
3304        errorMin=error;
3305        bestToMerge=ind;
3306        first=0;
3307      }
3308    }
3309    ind1=indexList[bestToMerge];
3310    ind2=indexList[bestToMerge+1];
3311    m_pixAcc_merged[ind1]+=m_pixAcc_merged[ind2];
3312    for (i=0; i<sqrFiltLength; i++)
3313    {
3314      m_y_merged[ind1][i]+=m_y_merged[ind2][i];
3315      for (j=0; j<sqrFiltLength; j++)
3316      {
3317        m_E_merged[ind1][i][j]+=m_E_merged[ind2][i][j];
3318      }
3319    }
3320    available[ind2]=0;
3321   
3322    //update error tables
3323    error_tab[ind1]=error_comb_tab[ind1]+error_tab[ind1]+error_tab[ind2];
3324    if (indexList[bestToMerge] > 0)
3325    {
3326      ind1=indexList[bestToMerge-1];
3327      ind2=indexList[bestToMerge];
3328      error1=error_tab[ind1];
3329      error2=error_tab[ind2];
3330      pixAcc_temp=m_pixAcc_merged[ind1]+m_pixAcc_merged[ind2];
3331      for (i=0; i<sqrFiltLength; i++)
3332      {
3333        m_y_temp[i]=m_y_merged[ind1][i]+m_y_merged[ind2][i];
3334        for (j=0; j<sqrFiltLength; j++)
3335        {
3336          m_E_temp[i][j]=m_E_merged[ind1][i][j]+m_E_merged[ind2][i][j];
3337        }
3338      }
3339      error_comb_tab[ind1]=calculateErrorAbs(m_E_temp, m_y_temp, pixAcc_temp, sqrFiltLength)-error1-error2;
3340    }
3341    if (indexList[bestToMerge+1] < NO_VAR_BINS-1)
3342    {
3343      ind1=indexList[bestToMerge];
3344      ind2=indexList[bestToMerge+2];
3345      error1=error_tab[ind1];
3346      error2=error_tab[ind2];
3347      pixAcc_temp=m_pixAcc_merged[ind1]+m_pixAcc_merged[ind2];
3348      for (i=0; i<sqrFiltLength; i++)
3349      {
3350        m_y_temp[i]=m_y_merged[ind1][i]+m_y_merged[ind2][i];
3351        for (j=0; j<sqrFiltLength; j++)
3352        {
3353          m_E_temp[i][j]=m_E_merged[ind1][i][j]+m_E_merged[ind2][i][j];
3354        }
3355      }
3356      error_comb_tab[ind1]=calculateErrorAbs(m_E_temp, m_y_temp, pixAcc_temp, sqrFiltLength)-error1-error2;
3357    }
3358   
3359    ind=0;
3360    for (i=0; i<NO_VAR_BINS; i++)
3361    {
3362      if (available[i]==1)
3363      {
3364        indexList[ind]=i;
3365        ind++;
3366      }
3367    }
3368    noRemaining--;
3369  }
3370 
3371 
3372  errorMin=0;
3373  for (ind=0; ind<noIntervals; ind++)
3374  {
3375    errorMin+=error_tab[indexList[ind]];
3376  }
3377 
3378  for (ind=0; ind<noIntervals-1; ind++)
3379  {
3380    intervalBest[ind][0]=indexList[ind]; intervalBest[ind][1]=indexList[ind+1]-1;
3381  }
3382 
3383  intervalBest[noIntervals-1][0]=indexList[noIntervals-1]; 
3384  intervalBest[noIntervals-1][1]=NO_VAR_BINS-1;
3385 
3386  return(errorMin);
3387}
3388
3389
3390
3391double TEncAdaptiveLoopFilter::findFilterGroupingError(double ***EGlobalSeq, double **yGlobalSeq, double *pixAccGlobalSeq, int intervalBest[NO_VAR_BINS][2], int sqrFiltLength, int filters_per_fr)
3392{
3393  double error;
3394 
3395  // find best filters for each frame group
3396  error = 0;
3397  error += mergeFiltersGreedy(yGlobalSeq, EGlobalSeq, pixAccGlobalSeq, intervalBest, sqrFiltLength, filters_per_fr);
3398 
3399  return(error);
3400}
3401
3402
3403Void TEncAdaptiveLoopFilter::roundFiltCoeff(int *FilterCoeffQuan, double *FilterCoeff, int sqrFiltLength, int factor)
3404{
3405  int i;
3406  double diff; 
3407  int diffInt, sign; 
3408 
3409  for(i = 0; i < sqrFiltLength; i++)
3410  {
3411    sign               = (FilterCoeff[i]>0) ?  1: -1; 
3412    diff               = FilterCoeff[i]*sign; 
3413    diffInt            = (int)(diff*(double)factor+0.5); 
3414    FilterCoeffQuan[i] = diffInt*sign;
3415  }
3416}
3417
3418Double TEncAdaptiveLoopFilter::QuantizeIntegerFilterPP(double *filterCoeff, int *filterCoeffQuant, double **E, double *y, int sqrFiltLength, int *weights, int bit_depth)
3419{
3420  double error;
3421 
3422  int factor = (1<<(bit_depth-1)), i; 
3423  int quantCoeffSum, minInd, targetCoeffSumInt, k, diff;
3424  double targetCoeffSum, errMin;
3425 
3426  gnsSolveByChol(E, y, filterCoeff, sqrFiltLength);
3427  targetCoeffSum=0;
3428  for (i=0; i<sqrFiltLength; i++)
3429  {
3430    targetCoeffSum+=(weights[i]*filterCoeff[i]*factor);
3431  }
3432  targetCoeffSumInt=ROUND(targetCoeffSum);
3433  roundFiltCoeff(filterCoeffQuant, filterCoeff, sqrFiltLength, factor);
3434  quantCoeffSum=0;
3435  for (i=0; i<sqrFiltLength; i++)
3436  {
3437    quantCoeffSum+=weights[i]*filterCoeffQuant[i];
3438  }
3439 
3440  int count=0;
3441  while(quantCoeffSum!=targetCoeffSumInt && count < 10)
3442  {
3443    if (quantCoeffSum>targetCoeffSumInt)
3444    {
3445      diff=quantCoeffSum-targetCoeffSumInt;
3446      errMin=0; minInd=-1;
3447      for (k=0; k<sqrFiltLength; k++)
3448      {
3449        if (weights[k]<=diff)
3450        {
3451          for (i=0; i<sqrFiltLength; i++)
3452          {
3453            m_filterCoeffQuantMod[i]=filterCoeffQuant[i];
3454          }
3455          m_filterCoeffQuantMod[k]--;
3456          for (i=0; i<sqrFiltLength; i++)
3457          {
3458            filterCoeff[i]=(double)m_filterCoeffQuantMod[i]/(double)factor;
3459          }
3460          error=calculateErrorCoeffProvided(E, y, filterCoeff, sqrFiltLength);
3461          if (error<errMin || minInd==-1)
3462          {
3463            errMin=error;
3464            minInd=k;
3465          }
3466        } // if (weights(k)<=diff){
3467      } // for (k=0; k<sqrFiltLength; k++){
3468      filterCoeffQuant[minInd]--;
3469    }
3470    else
3471    {
3472      diff=targetCoeffSumInt-quantCoeffSum;
3473      errMin=0; minInd=-1;
3474      for (k=0; k<sqrFiltLength; k++)
3475      {
3476        if (weights[k]<=diff)
3477        {
3478          for (i=0; i<sqrFiltLength; i++)
3479          {
3480            m_filterCoeffQuantMod[i]=filterCoeffQuant[i];
3481          }
3482          m_filterCoeffQuantMod[k]++;
3483          for (i=0; i<sqrFiltLength; i++)
3484          {
3485            filterCoeff[i]=(double)m_filterCoeffQuantMod[i]/(double)factor;
3486          }
3487          error=calculateErrorCoeffProvided(E, y, filterCoeff, sqrFiltLength);
3488          if (error<errMin || minInd==-1)
3489          {
3490            errMin=error;
3491            minInd=k;
3492          }
3493        } // if (weights(k)<=diff){
3494      } // for (k=0; k<sqrFiltLength; k++){
3495      filterCoeffQuant[minInd]++;
3496    }
3497   
3498    quantCoeffSum=0;
3499    for (i=0; i<sqrFiltLength; i++)
3500    {
3501      quantCoeffSum+=weights[i]*filterCoeffQuant[i];
3502    }
3503  }
3504  if( count == 10 )
3505  {
3506    for (i=0; i<sqrFiltLength; i++)
3507    {
3508      filterCoeffQuant[i] = 0;
3509    }
3510  }
3511 
3512  for (i=0; i<sqrFiltLength; i++)
3513  {
3514    filterCoeff[i]=(double)filterCoeffQuant[i]/(double)factor;
3515  }
3516 
3517  error=calculateErrorCoeffProvided(E, y, filterCoeff, sqrFiltLength);
3518  return(error);
3519}
3520
3521Double 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, int bit_depth, double errorTabForce0Coeff[NO_VAR_BINS][2])
3522{
3523  static double pixAcc_temp;
3524  double error;
3525  int k, filtNo;
3526 
3527  error = 0;
3528  for(filtNo = 0; filtNo < filters_per_fr; filtNo++)
3529  {
3530    add_A(m_E_temp, EGlobalSeq, intervalBest[filtNo][0], intervalBest[filtNo][1], sqrFiltLength);
3531    add_b(m_y_temp, yGlobalSeq, intervalBest[filtNo][0], intervalBest[filtNo][1], sqrFiltLength);
3532   
3533    pixAcc_temp = 0;   
3534    for(k = intervalBest[filtNo][0]; k <= intervalBest[filtNo][1]; k++)
3535      pixAcc_temp += pixAccGlobalSeq[k];
3536   
3537    // Find coeffcients
3538    errorTabForce0Coeff[filtNo][1] = pixAcc_temp + QuantizeIntegerFilterPP(m_filterCoeff, m_filterCoeffQuant, m_E_temp, m_y_temp, sqrFiltLength, weights, bit_depth);
3539    errorTabForce0Coeff[filtNo][0] = pixAcc_temp;
3540    error += errorTabForce0Coeff[filtNo][1];
3541   
3542    for(k = 0; k < sqrFiltLength; k++)
3543    {
3544      filterCoeffSeq[filtNo][k] = m_filterCoeffQuant[k];
3545      filterCoeffQuantSeq[filtNo][k] = m_filterCoeffQuant[k];
3546    }
3547  }
3548 
3549  for(filtNo = 0; filtNo < filters_per_fr; filtNo++)
3550  {
3551    for(k = intervalBest[filtNo][0]; k <= intervalBest[filtNo][1]; k++)
3552      varIndTab[k] = filtNo;
3553  }
3554 
3555  return(error);
3556}
3557
3558#if MQT_ALF_NPASS
3559Void TEncAdaptiveLoopFilter::setALFEncodingParam(TComPic *pcPic)
3560{
3561  if(m_iALFEncodePassReduction)
3562  {
3563    m_iALFNumOfRedesign = 0;
3564    m_iCurrentPOC = m_pcPic->getPOC();
3565
3566    if((m_eSliceType == I_SLICE) || (m_iGOPSize==8 && (m_iCurrentPOC % 4 == 0)))
3567    {
3568      m_iUsePreviousFilter = 0;
3569    }
3570    else
3571    {
3572      m_iUsePreviousFilter = 1;
3573    }
3574  }
3575  else
3576  {
3577    m_iALFNumOfRedesign = ALF_NUM_OF_REDESIGN;
3578  }
3579  m_iDesignCurrentFilter = 1;
3580
3581}
3582
3583Void TEncAdaptiveLoopFilter::xcalcPredFilterCoeffPrev(Int filtNo)
3584{
3585  int varInd, i;
3586
3587  for(varInd=0; varInd<NO_VAR_BINS; ++varInd)
3588  {
3589    for(i = 0; i < MAX_SQR_FILT_LENGTH; i++)
3590    {
3591      m_filterCoeffPrevSelected[varInd][i]=m_aiFilterCoeffSaved[m_iFilterIdx][varInd][i];
3592    }
3593  }
3594}
3595
3596Void TEncAdaptiveLoopFilter::setFilterIdx(Int index)
3597{
3598  if (m_iGOPSize == 8)
3599  {
3600    if ((m_iCurrentPOC % m_iGOPSize) == 0)
3601    {
3602      Int FiltTable[2] = {0, m_iGOPSize};
3603      m_iFilterIdx = FiltTable[index]; 
3604    }
3605    if ((m_iCurrentPOC % m_iGOPSize) == 4)
3606    {
3607      Int FiltTable[2] = {0, m_iGOPSize};
3608      m_iFilterIdx = FiltTable[index]; 
3609    }
3610    if ((m_iCurrentPOC % m_iGOPSize) == 2)
3611    {
3612      Int FiltTable[2] = {0, 4};
3613      m_iFilterIdx = FiltTable[index]; 
3614    }
3615    if ((m_iCurrentPOC % m_iGOPSize) == 6)
3616    {
3617      Int FiltTable[2] = {4, m_iGOPSize};
3618      m_iFilterIdx = FiltTable[index]; 
3619    }
3620    if ((m_iCurrentPOC % m_iGOPSize) == 1)
3621    {
3622      Int FiltTable[2] = {0, 2};
3623      m_iFilterIdx = FiltTable[index]; 
3624    }
3625    if ((m_iCurrentPOC % m_iGOPSize) == 3)
3626    {
3627      Int FiltTable[2] = {2, 4};
3628      m_iFilterIdx = FiltTable[index]; 
3629    }
3630    if ((m_iCurrentPOC % m_iGOPSize) == 5)
3631    {
3632      Int FiltTable[2] = {4, 6};
3633      m_iFilterIdx = FiltTable[index]; 
3634    }
3635    if ((m_iCurrentPOC % m_iGOPSize) == 7)
3636    {
3637      Int FiltTable[2] = {6, m_iGOPSize};
3638      m_iFilterIdx = FiltTable[index]; 
3639    }
3640  }
3641  else
3642  {
3643    Int FiltTable[2] = {0, m_iGOPSize};
3644    m_iFilterIdx = FiltTable[index]; 
3645  }
3646}
3647
3648Void TEncAdaptiveLoopFilter::setInitialMask(TComPicYuv* pcPicOrg, TComPicYuv* pcPicDec)
3649{
3650  Int Height = pcPicOrg->getHeight();
3651  Int Width = pcPicOrg->getWidth();
3652  Int LumaStride = pcPicOrg->getStride();
3653  imgpel* pDec = (imgpel*)pcPicDec->getLumaAddr();
3654
3655#if MTK_NONCROSS_INLOOP_FILTER
3656  if(!m_bUseNonCrossALF)
3657    calcVar(0, 0, m_varImg, pDec, 9/2, VAR_SIZE, Height, Width, LumaStride);
3658  else
3659    calcVarforSlices(m_varImg, pDec, 9/2, VAR_SIZE, LumaStride);
3660#else
3661  calcVar(m_varImg, pDec, 9/2, VAR_SIZE, Height, Width, LumaStride);
3662#endif
3663
3664  if(!m_iALFEncodePassReduction || !m_iUsePreviousFilter)
3665  {
3666    for(Int y=0; y<Height; y++)
3667    {
3668      for(Int x=0; x<Width; x++)
3669      {
3670        m_maskImg[y][x] = 1;
3671      }
3672    }
3673  }
3674  else
3675  {
3676    Int uiBestDepth=0;
3677    UInt64 uiRate, uiDist, uiMinRate, uiMinDist;
3678    Double dCost, dMinCost = MAX_DOUBLE;
3679    //imgpel* pOrg = (imgpel*)pcPicOrg->getLumaAddr();
3680    imgpel* pRest = (imgpel*)m_pcPicYuvTmp->getLumaAddr();
3681
3682    Int iTap = 9;
3683    Int filtNo = 0;
3684    m_pcTempAlfParam->cu_control_flag = 0;
3685    m_pcTempAlfParam->tap = iTap;
3686#if TI_ALF_MAX_VSIZE_7
3687    m_pcTempAlfParam->tapV      = TComAdaptiveLoopFilter::ALFTapHToTapV(iTap);
3688    m_pcTempAlfParam->num_coeff = TComAdaptiveLoopFilter::ALFTapHToNumCoeff(iTap);
3689#else
3690    m_pcTempAlfParam->num_coeff = iTap*iTap/4 + 2;
3691#endif
3692
3693    for (Int index=0; index<2; index++)
3694    {
3695      setFilterIdx(index);
3696      xcalcPredFilterCoeffPrev(filtNo);
3697#if MTK_NONCROSS_INLOOP_FILTER
3698      if(!m_bUseNonCrossALF)
3699        xfilterFrame_en(0, 0, Height, Width, pDec, pRest, filtNo, LumaStride);
3700      else
3701        xfilterSlices_en(pDec, pRest, filtNo, LumaStride);
3702#else
3703      xfilterFrame_en(pDec, pRest, filtNo, LumaStride);
3704#endif
3705      xCalcRDCost(pcPicOrg, m_pcPicYuvTmp, NULL, uiRate, uiDist, dCost);
3706      if (dCost < dMinCost)
3707      {
3708        dMinCost  = dCost;
3709        uiMinDist = uiDist;
3710        uiMinRate = uiRate;
3711        m_pcPicYuvTmp->copyToPicLuma(m_pcPicYuvBest);
3712        copyALFParam(m_pcBestAlfParam, m_pcTempAlfParam);
3713      }
3714    }
3715    m_pcPicYuvBest->copyToPicLuma(m_pcPicYuvTmp);
3716
3717    m_pcEntropyCoder->setAlfCtrl(true);
3718    Int maxDepth = g_uiMaxCUDepth;
3719    if (pcPicOrg->getWidth() < 1000) maxDepth = 2;
3720    for (UInt uiDepth = 0; uiDepth < maxDepth; uiDepth++)
3721    {
3722      m_pcEntropyCoder->setMaxAlfCtrlDepth(uiDepth);
3723      copyALFParam(m_pcTempAlfParam, m_pcBestAlfParam);
3724      m_pcTempAlfParam->cu_control_flag = 1;
3725
3726#if TSB_ALF_HEADER
3727      xSetCUAlfCtrlFlags_qc(uiDepth, pcPicOrg, pcPicDec, m_pcPicYuvTmp, uiDist, m_pcTempAlfParam); //set up varImg here
3728#else
3729      xSetCUAlfCtrlFlags_qc(uiDepth, pcPicOrg, pcPicDec, m_pcPicYuvTmp, uiDist); //set up varImg here
3730#endif
3731      m_pcEntropyCoder->resetEntropy();
3732      m_pcEntropyCoder->resetBits();
3733      xEncodeCUAlfCtrlFlags();
3734      uiRate = m_pcEntropyCoder->getNumberOfWrittenBits();
3735      dCost  = (Double)(uiRate) * m_dLambdaLuma + (Double)(uiDist);
3736
3737      if (dCost < dMinCost)
3738      {
3739        uiBestDepth = uiDepth;
3740        dMinCost    = dCost;
3741        uiMinDist   = uiDist;
3742        uiMinRate   = uiRate;
3743        copyALFParam(m_pcBestAlfParam, m_pcTempAlfParam);
3744        //save maskImg
3745        xCopyTmpAlfCtrlFlagsFrom();
3746      }
3747    }
3748
3749    copyALFParam(m_pcTempAlfParam, m_pcBestAlfParam);
3750    m_iDesignCurrentFilter = 0; // design filter for subsequent slices
3751    xReDesignFilterCoeff_qc(pcPicOrg, pcPicDec, m_pcPicYuvTmp, true);
3752    m_iDesignCurrentFilter = 1;
3753
3754    if (m_pcBestAlfParam->cu_control_flag)
3755    {
3756      m_pcEntropyCoder->setAlfCtrl(true);
3757      m_pcEntropyCoder->setMaxAlfCtrlDepth(uiBestDepth);
3758      xCopyTmpAlfCtrlFlagsTo();
3759    }
3760    else
3761    {
3762      m_pcEntropyCoder->setAlfCtrl(false);
3763      m_pcEntropyCoder->setMaxAlfCtrlDepth(0);
3764      for(Int y=0; y<Height; y++)
3765      {
3766        for(Int x=0; x<Width; x++)
3767        {
3768          m_maskImg[y][x] = 1;
3769        }
3770      }
3771    }
3772  }
3773}
3774
3775#if MQT_BA_RA
3776Void  TEncAdaptiveLoopFilter::xFirstEstimateFilteringFrameLumaAllTap(imgpel* ImgOrg, imgpel* ImgDec, Int Stride, 
3777                                                                     ALFParam* pcAlfSaved,
3778                                                                     Int* aiVarIndTabBest,
3779                                                                     Int** ppiBestCoeffSet,
3780                                                                     Int& ibestfiltNo,
3781                                                                     Int& ibestfilters_per_fr,
3782                                                                     Double**  ppdBesty,
3783                                                                     Double*** pppdBestE,
3784                                                                     Double*   pdBestpixAcc,
3785                                                                     UInt64& ruiRate,
3786                                                                     Int64& riDist,
3787                                                                     Double& rdCost
3788                                                                     )
3789#else
3790Void   TEncAdaptiveLoopFilter::xFirstFilteringFrameLumaAllTap(imgpel* ImgOrg, imgpel* ImgDec, imgpel* ImgRest, Int Stride)
3791#endif
3792{
3793#if !MQT_BA_RA
3794  static Bool bFirst = true;
3795  static Int  aiVarIndTabBest[NO_VAR_BINS];
3796#endif
3797  static Double **ySym, ***ESym;
3798#if !MQT_BA_RA
3799  static Int**  ppiBestCoeffSet;
3800
3801  if(bFirst)
3802  {
3803    initMatrix_int(&ppiBestCoeffSet, NO_VAR_BINS, MAX_SQR_FILT_LENGTH);
3804    bFirst = false;
3805  }
3806#endif
3807
3808  Int    lambda_val = ((Int) m_dLambdaLuma) * (1<<(2*g_uiBitIncrement));
3809#if MQT_BA_RA
3810  Int    filtNo, filters_per_fr;
3811#else
3812  Int    filtNo, ibestfiltNo=0, filters_per_fr, ibestfilters_per_fr=0;
3813#endif
3814  Int64  iEstimatedDist;
3815  UInt64 uiRate;
3816  Double dEstimatedCost, dEstimatedMinCost = MAX_DOUBLE;;
3817  Bool   bMatrixBaseReady  = false;
3818  m_iMatrixBaseFiltNo = 0; 
3819#if MQT_BA_RA
3820  m_pcTempAlfParam->alf_flag = 1;
3821  m_pcTempAlfParam->cu_control_flag = 0;
3822  m_pcTempAlfParam->chroma_idc = 0;
3823#endif
3824  for(Int iTap = ALF_MAX_NUM_TAP; iTap>=ALF_MIN_NUM_TAP; iTap -= 2)
3825  {
3826    m_pcTempAlfParam->tap = iTap;
3827#if TI_ALF_MAX_VSIZE_7
3828    m_pcTempAlfParam->tapV      = TComAdaptiveLoopFilter::ALFTapHToTapV(iTap);
3829    m_pcTempAlfParam->num_coeff = TComAdaptiveLoopFilter::ALFTapHToNumCoeff(iTap);
3830#else
3831    m_pcTempAlfParam->num_coeff = iTap*iTap/4 + 2;
3832#endif
3833    if (iTap==9)
3834    {
3835      filtNo = 0;
3836    }
3837    else if (iTap==7)
3838    {
3839      filtNo = 1;
3840    }
3841    else
3842    {
3843      filtNo = 2;
3844    }
3845
3846    ESym     = m_EGlobalSym     [filtNo];
3847    ySym     = m_yGlobalSym     [filtNo];
3848
3849    if( bMatrixBaseReady )
3850    {
3851      xretriveBlockMatrix(m_pcTempAlfParam->num_coeff, m_iTapPosTabIn9x9Sym[filtNo], 
3852                          m_EGlobalSym[m_iMatrixBaseFiltNo], ESym, 
3853                          m_yGlobalSym[m_iMatrixBaseFiltNo], ySym);
3854
3855    }
3856    else
3857#if MTK_NONCROSS_INLOOP_FILTER
3858    {
3859      if(!m_bUseNonCrossALF)
3860        xstoreInBlockMatrix(0, 0, m_im_height, m_im_width, true, true, ImgOrg, ImgDec, iTap, Stride);
3861      else
3862        xstoreInBlockMatrixforSlices(ImgOrg, ImgDec, iTap, Stride);
3863    }
3864#else
3865    xstoreInBlockMatrix(ImgOrg, ImgDec, iTap, Stride);
3866#endif
3867    if(filtNo == m_iMatrixBaseFiltNo)
3868    {
3869      bMatrixBaseReady = true;
3870    }
3871
3872    xfindBestFilterVarPred(ySym, ESym, m_pixAcc, m_filterCoeffSym, m_filterCoeffSymQuant, filtNo, &filters_per_fr, 
3873                           m_varIndTab, NULL, m_varImg, m_maskImg, NULL, lambda_val);
3874
3875    uiRate         = xcodeFiltCoeff(m_filterCoeffSymQuant, filtNo, m_varIndTab, filters_per_fr,0, m_pcTempAlfParam);
3876    iEstimatedDist = xEstimateFiltDist(filters_per_fr, m_varIndTab, ESym, ySym, m_filterCoeffSym, m_pcTempAlfParam->num_coeff);
3877    dEstimatedCost = (Double)(uiRate) * m_dLambdaLuma + (Double)(iEstimatedDist);
3878
3879    if(dEstimatedCost < dEstimatedMinCost)
3880    {
3881      dEstimatedMinCost   = dEstimatedCost;
3882      ibestfiltNo         = filtNo;
3883      ibestfilters_per_fr = filters_per_fr;
3884#if MQT_BA_RA
3885      ruiRate = uiRate;
3886      riDist  = iEstimatedDist;
3887      rdCost  = dEstimatedMinCost;
3888
3889      copyALFParam(pcAlfSaved, m_pcTempAlfParam); 
3890#else
3891      copyALFParam(m_pcBestAlfParam, m_pcTempAlfParam); 
3892#endif
3893      ::memcpy(aiVarIndTabBest, m_varIndTab, sizeof(Int)*NO_VAR_BINS);
3894      for(Int i=0; i< ibestfilters_per_fr; i++ )
3895      {
3896        ::memcpy( ppiBestCoeffSet[i], m_filterCoeffSym[i], sizeof(Int) * m_pcTempAlfParam->num_coeff);
3897      }
3898    }
3899  }
3900
3901  filtNo         = ibestfiltNo;
3902  filters_per_fr = ibestfilters_per_fr;
3903  ::memcpy(m_varIndTab, aiVarIndTabBest, sizeof(Int)*NO_VAR_BINS);
3904  for(Int i=0; i< filters_per_fr; i++ )
3905  {
3906#if MQT_BA_RA
3907    ::memcpy(m_filterCoeffSym[i], ppiBestCoeffSet[i], sizeof(Int) * pcAlfSaved->num_coeff);
3908#else
3909    ::memcpy(m_filterCoeffSym[i], ppiBestCoeffSet[i], sizeof(Int) * m_pcTempAlfParam->num_coeff);
3910#endif
3911  }
3912
3913  xcalcPredFilterCoeff(filtNo);
3914
3915#if MQT_BA_RA
3916
3917
3918  ::memset( pdBestpixAcc, 0,sizeof(double)*NO_VAR_BINS);
3919  for (Int varInd=0; varInd<NO_VAR_BINS; varInd++)
3920  {
3921    ::memset(ppdBesty[varInd],0,sizeof(double)*MAX_SQR_FILT_LENGTH);
3922    for (Int k=0; k< pcAlfSaved->num_coeff; k++)
3923    {
3924      ::memset(pppdBestE[varInd][k],0,sizeof(double)*MAX_SQR_FILT_LENGTH);
3925    }
3926  }
3927  ESym     = m_EGlobalSym     [filtNo];
3928  ySym     = m_yGlobalSym     [filtNo];
3929
3930  ::memcpy( pdBestpixAcc, m_pixAcc ,sizeof(double)*NO_VAR_BINS);
3931  for (Int varInd=0; varInd<NO_VAR_BINS; varInd++)
3932  {
3933    ::memcpy(ppdBesty[varInd],ySym[varInd],sizeof(double)*MAX_SQR_FILT_LENGTH);
3934    for (Int k=0; k< pcAlfSaved->num_coeff; k++)
3935    {
3936      ::memcpy(pppdBestE[varInd][k],ESym[varInd][k],sizeof(double)*MAX_SQR_FILT_LENGTH);
3937    }
3938  }
3939
3940
3941#else
3942
3943  filtNo         = ibestfiltNo;
3944  filters_per_fr = ibestfilters_per_fr;
3945  copyALFParam(m_pcTempAlfParam, m_pcBestAlfParam);
3946  ::memcpy(m_varIndTab, aiVarIndTabBest, sizeof(Int)*NO_VAR_BINS);
3947  for(Int i=0; i< filters_per_fr; i++ )
3948  {
3949    ::memcpy(m_filterCoeffSym[i], ppiBestCoeffSet[i], sizeof(Int) * m_pcTempAlfParam->num_coeff);
3950  }
3951
3952  xcalcPredFilterCoeff(filtNo);
3953#if MTK_NONCROSS_INLOOP_FILTER
3954  if(!m_bUseNonCrossALF)
3955    xfilterFrame_en(0, 0, m_im_height, m_im_width, ImgDec, ImgRest, filtNo, Stride);
3956  else
3957    xfilterSlices_en(ImgDec, ImgRest, filtNo, Stride);
3958#else
3959  xfilterFrame_en(ImgDec, ImgRest, filtNo, Stride);
3960#endif
3961
3962#endif
3963}
3964
3965Void TEncAdaptiveLoopFilter::xretriveBlockMatrix(Int iNumTaps, 
3966                                                 Int* piTapPosInMaxFilter, 
3967                                                 Double*** pppdEBase, Double*** pppdETarget, 
3968                                                 Double**  ppdyBase,  Double** ppdyTarget )
3969{
3970  Int varInd;
3971  Int i, j, r, c;
3972
3973  Double** ppdSrcE;
3974  Double** ppdDstE;
3975  Double*  pdSrcy;
3976  Double*  pdDsty;
3977
3978  for (varInd=0; varInd< NO_VAR_BINS; varInd++)
3979  {
3980    ppdSrcE = pppdEBase  [varInd];
3981    ppdDstE = pppdETarget[varInd];
3982    pdSrcy  = ppdyBase   [varInd];
3983    pdDsty  = ppdyTarget [varInd];
3984
3985    for(j=0; j< iNumTaps; j++)
3986    {
3987      r = piTapPosInMaxFilter[j];
3988
3989      for(i=j; i< iNumTaps; i++)
3990      {
3991        c = piTapPosInMaxFilter[i];
3992
3993        //auto-correlation retrieval
3994        ppdDstE[j][i] = ppdSrcE[r][c];
3995
3996      }
3997
3998      //cross-correlation retrieval
3999      pdDsty[j] = pdSrcy[r];
4000
4001    }
4002
4003    //symmetric copy
4004    for(j=1; j< iNumTaps; j++)
4005      for(i=0; i< j; i++)
4006        ppdDstE[j][i] = ppdDstE[i][j];
4007
4008  }
4009
4010}
4011
4012Int64 TEncAdaptiveLoopFilter::xFastFiltDistEstimation(Double** ppdE, Double* pdy, Int* piCoeff, Int iFiltLength)
4013{
4014  //static memory
4015  static Bool     bFirst = true;
4016  static Double*  pdcoeff;
4017  if(bFirst)
4018  {
4019    pdcoeff= new Double[MAX_SQR_FILT_LENGTH];       
4020    bFirst= false;
4021  }
4022
4023  //variable
4024  Int    i,j;
4025  Int64  iDist;
4026  Double dDist, dsum;
4027
4028
4029  for(i=0; i< iFiltLength; i++)
4030    pdcoeff[i]= (Double)piCoeff[i] / (Double)(1<< (NUM_BITS - 1) );
4031
4032
4033  dDist =0;
4034  for(i=0; i< iFiltLength; i++)
4035  {
4036    dsum= ((Double)ppdE[i][i]) * pdcoeff[i];
4037    for(j=i+1; j< iFiltLength; j++)
4038      dsum += (Double)(2*ppdE[i][j])* pdcoeff[j];
4039
4040    dDist += ((dsum - 2.0 * pdy[i])* pdcoeff[i] );
4041  }
4042
4043
4044  UInt uiShift = g_uiBitIncrement<<1;
4045  if(dDist < 0)
4046  {
4047    iDist = -(((Int64)(-dDist + 0.5)) >> uiShift);
4048  }
4049  else //dDist >=0
4050  {
4051    iDist= ((Int64)(dDist+0.5)) >> uiShift;
4052  }
4053
4054  return iDist;
4055
4056}
4057
4058Int64 TEncAdaptiveLoopFilter::xEstimateFiltDist(Int filters_per_fr, Int* VarIndTab, 
4059                                                Double*** pppdE, Double** ppdy, 
4060                                                Int** ppiCoeffSet, Int iFiltLength)
4061
4062{
4063  Int64     iDist;
4064  Double**  ppdDstE;
4065  Double**  ppdSrcE;
4066  Double*   pdDsty; 
4067  Double*   pdSrcy;
4068  Int       f, j, i, varInd;
4069  Int*      piCoeff;
4070
4071  //clean m_E_merged & m_y_merged
4072  for(f=0; f< filters_per_fr; f++)
4073  {
4074    for(j =0; j < iFiltLength; j++)
4075    {
4076      //clean m_E_merged one line
4077      for(i=0; i < iFiltLength; i++)
4078        m_E_merged[f][j][i] = 0;
4079
4080      //clean m_y_merged
4081      m_y_merged[f][j] = 0;
4082    }
4083  }
4084
4085
4086  //merge correlation values
4087  for (varInd=0; varInd< NO_VAR_BINS; varInd++)
4088  {
4089    ppdSrcE = pppdE[varInd];
4090    ppdDstE = m_E_merged[ VarIndTab[varInd] ];
4091
4092    pdSrcy  = ppdy[varInd];
4093    pdDsty  = m_y_merged[ VarIndTab[varInd] ];
4094
4095    for(j=0; j< iFiltLength; j++)
4096    {
4097      for(i=0; i< iFiltLength; i++)
4098        ppdDstE[j][i] += ppdSrcE[j][i];
4099
4100      pdDsty[j] += pdSrcy[j];
4101    }
4102  }
4103
4104  //estimate distortion reduction by using FFDE (JCTVC-C143)
4105  iDist = 0;
4106  for(f=0; f< filters_per_fr; f++)
4107  {
4108    piCoeff = ppiCoeffSet[f];
4109    ppdDstE = m_E_merged [f];
4110    pdDsty  = m_y_merged [f];
4111
4112    iDist += xFastFiltDistEstimation(ppdDstE, pdDsty, piCoeff, iFiltLength);
4113  }
4114
4115
4116  return iDist;
4117
4118}
4119#endif
4120
4121#if MTK_NONCROSS_INLOOP_FILTER
4122
4123Void TEncAdaptiveLoopFilter::calcVarforSlices(imgpel **varmap, imgpel *imgY_Dec, Int pad_size, Int fl, Int img_stride)
4124{
4125#if MQT_BA_RA
4126  if(m_uiVarGenMethod == ALF_RA)
4127  {
4128    return;
4129  }
4130#endif
4131
4132  Pel* pPicSrc   = (Pel *)imgY_Dec;
4133  Pel* pPicSlice = m_pcSliceYuvTmp->getLumaAddr();
4134
4135  for(UInt s=0; s< m_uiNumSlicesInPic; s++)
4136  {
4137    CAlfSlice* pSlice = &(m_pSlice[s]);
4138
4139    pSlice->copySliceLuma(pPicSlice, pPicSrc, img_stride);
4140    pSlice->extendSliceBorderLuma(pPicSlice, img_stride, (UInt)EXTEND_NUM_PEL);
4141    calcVarforOneSlice(pSlice, varmap, (imgpel*)pPicSlice, pad_size, fl, img_stride);
4142  }
4143}
4144
4145
4146
4147Void TEncAdaptiveLoopFilter::xfilterSlices_en(imgpel* ImgDec, imgpel* ImgRest,int filtNo, int iStride)
4148{
4149  Pel* pPicSrc   = (Pel *)ImgDec;
4150  Pel* pPicSlice = m_pcSliceYuvTmp->getLumaAddr();
4151
4152  for(UInt s=0; s< m_uiNumSlicesInPic; s++)
4153  {
4154    CAlfSlice* pSlice = &(m_pSlice[s]);
4155
4156    pSlice->copySliceLuma(pPicSlice, pPicSrc, iStride);
4157    pSlice->extendSliceBorderLuma(pPicSlice, iStride, EXTEND_NUM_PEL);
4158
4159    xfilterOneSlice_en(pSlice, (imgpel*)pPicSlice, ImgRest, filtNo, iStride);
4160  }
4161}
4162
4163
4164Void TEncAdaptiveLoopFilter::xfilterOneSlice_en(CAlfSlice* pSlice, imgpel* ImgDec, imgpel* ImgRest,int filtNo, int iStride)
4165{
4166  UInt uiNumLCUs = pSlice->getNumLCUs();
4167
4168  Int iHeight, iWidth;
4169  Int ypos, xpos;
4170
4171  for(UInt i=0; i< uiNumLCUs; i++)
4172  {
4173    CAlfCU* pcAlfCU = &((*pSlice)[i]);
4174
4175    ypos    = pcAlfCU->getCU()->getCUPelY();
4176    xpos    = pcAlfCU->getCU()->getCUPelX();
4177    iHeight = pcAlfCU->getHeight();
4178    iWidth  = pcAlfCU->getWidth();
4179
4180    xfilterFrame_en(ypos, xpos, iHeight, iWidth, ImgDec, ImgRest, filtNo, iStride);
4181  }
4182}
4183
4184
4185
4186Void   TEncAdaptiveLoopFilter::xstoreInBlockMatrixforSlices(imgpel* ImgOrg, imgpel* ImgDec, Int tap, Int iStride)
4187{
4188  Pel* pPicSrc   = (Pel *)ImgDec;
4189  Pel* pPicSlice = m_pcSliceYuvTmp->getLumaAddr();
4190
4191  for(UInt s=0; s< m_uiNumSlicesInPic; s++)
4192  {
4193    CAlfSlice* pSlice = &(m_pSlice[s]);
4194    pSlice->copySliceLuma(pPicSlice, pPicSrc, iStride);
4195    pSlice->extendSliceBorderLuma(pPicSlice, iStride, (UInt)EXTEND_NUM_PEL);
4196    xstoreInBlockMatrixforOneSlice(pSlice, ImgOrg, (imgpel*)pPicSlice, tap, iStride, (s==0), (s== m_uiNumSlicesInPic-1));
4197  }
4198}
4199
4200Void   TEncAdaptiveLoopFilter::xstoreInBlockMatrixforOneSlice(CAlfSlice* pSlice, 
4201                                                              imgpel* ImgOrg, imgpel* ImgDec, 
4202                                                              Int tap, Int iStride, 
4203                                                              Bool bFirstSlice, 
4204                                                              Bool bLastSlice
4205                                                              )
4206{
4207
4208
4209  UInt uiNumLCUs = pSlice->getNumLCUs();
4210
4211  Int iHeight, iWidth;
4212  Int ypos, xpos;
4213  Bool bFirstLCU, bLastLCU;
4214
4215  for(UInt i=0; i< uiNumLCUs; i++)
4216  {
4217    bFirstLCU = (i==0);
4218    bLastLCU  = (i== uiNumLCUs -1);
4219
4220    CAlfCU* pcAlfCU = &((*pSlice)[i]);
4221    ypos    = pcAlfCU->getCU()->getCUPelY();
4222    xpos    = pcAlfCU->getCU()->getCUPelX();
4223    iHeight = pcAlfCU->getHeight();
4224    iWidth  = pcAlfCU->getWidth();
4225
4226    xstoreInBlockMatrix(ypos, xpos, iHeight, iWidth, 
4227      (bFirstSlice && bFirstLCU),(bLastSlice && bLastLCU),
4228      ImgOrg, ImgDec,tap, iStride);
4229  }
4230}
4231
4232
4233
4234Void TEncAdaptiveLoopFilter::xCalcCorrelationFuncforChromaSlices(Int ComponentID, Pel* pOrg, Pel* pCmp, Int iTap, Int iOrgStride, Int iCmpStride)
4235{
4236
4237  assert(iOrgStride == iCmpStride);
4238
4239  Pel* pPicSrc   = pCmp;
4240  Pel* pPicSlice = (ComponentID == ALF_Cb)?(m_pcSliceYuvTmp->getCbAddr()):(m_pcSliceYuvTmp->getCrAddr());
4241
4242  for(UInt s=0; s< m_uiNumSlicesInPic; s++)
4243  {
4244    CAlfSlice* pSlice = &(m_pSlice[s]);
4245
4246    pSlice->copySliceChroma(pPicSlice, pPicSrc, iCmpStride);
4247    pSlice->extendSliceBorderChroma(pPicSlice, iCmpStride, (UInt)EXTEND_NUM_PEL_C);
4248
4249    xCalcCorrelationFuncforChromaOneSlice(pSlice, pOrg, pPicSlice, iTap, iCmpStride,(s==m_uiNumSlicesInPic-1));
4250  }
4251}
4252
4253Void TEncAdaptiveLoopFilter::xCalcCorrelationFuncforChromaOneSlice(CAlfSlice* pSlice, Pel* pOrg, Pel* pCmp, Int iTap, Int iStride, Bool bLastSlice)
4254{
4255  UInt uiNumLCUs = pSlice->getNumLCUs();
4256
4257  Int iHeight, iWidth;
4258  Int ypos, xpos;
4259  Bool bLastLCU;
4260
4261  for(UInt i=0; i< uiNumLCUs; i++)
4262  {
4263    bLastLCU  = (i== uiNumLCUs -1);
4264
4265    CAlfCU* pcAlfCU = &((*pSlice)[i]);
4266    ypos    = ( pcAlfCU->getCU()->getCUPelY() >> 1 );
4267    xpos    = ( pcAlfCU->getCU()->getCUPelX() >> 1 );
4268    iHeight = (Int)( pcAlfCU->getHeight() >> 1);
4269    iWidth  = (Int)( pcAlfCU->getWidth() >> 1);
4270
4271    xCalcCorrelationFunc(ypos, xpos, pOrg, pCmp, iTap, iWidth, iHeight, iStride, iStride, (bLastSlice && bLastLCU ) );
4272  }
4273}
4274
4275Void TEncAdaptiveLoopFilter::xFrameChromaforSlices(Int ComponentID, TComPicYuv* pcPicDecYuv, TComPicYuv* pcPicRestYuv, Int *qh, Int iTap )
4276{
4277  Pel* pPicDec   = (ComponentID == ALF_Cb)?(    pcPicDecYuv->getCbAddr()):(    pcPicDecYuv->getCrAddr());
4278  //  Pel* pPicRest  = (ComponentID == ALF_Cb)?(   pcPicRestYuv->getCbAddr()):(   pcPicRestYuv->getCrAddr());
4279  Pel* pPicSlice = (ComponentID == ALF_Cb)?(m_pcSliceYuvTmp->getCbAddr()):(m_pcSliceYuvTmp->getCrAddr());
4280
4281  Int iStride = pcPicDecYuv->getCStride();
4282
4283  assert(iStride == pcPicRestYuv->getCStride());
4284
4285  for(UInt s=0; s< m_uiNumSlicesInPic; s++)
4286  {
4287    CAlfSlice* pSlice = &(m_pSlice[s]);
4288
4289    pSlice->copySliceChroma(pPicSlice, pPicDec, iStride);
4290    pSlice->extendSliceBorderChroma(pPicSlice, iStride, (UInt)EXTEND_NUM_PEL_C);
4291
4292    xFrameChromaforOneSlice(pSlice, ComponentID, m_pcSliceYuvTmp, pcPicRestYuv, qh, iTap);
4293  }
4294}
4295
4296#endif
4297
4298
4299#if MTK_SAO
4300inline Double xRoundIbdi2(Double x)
4301{
4302  return ((x)>0) ? (Int)(((Int)(x)+(1<<(g_uiBitIncrement-1)))/(1<<g_uiBitIncrement)) : ((Int)(((Int)(x)-(1<<(g_uiBitIncrement-1)))/(1<<g_uiBitIncrement)));
4303}
4304
4305inline Double xRoundIbdi(Double x)
4306{
4307  return (g_uiBitIncrement >0 ? xRoundIbdi2((x)) : ((x)>=0 ? ((Int)((x)+0.5)) : ((Int)((x)-0.5)))) ;
4308}
4309
4310/** run QAO One Part.
4311 * \param  pQAOOnePart, iPartIdx
4312 */
4313Void TEncSampleAdaptiveOffset::xQAOOnePart(SAOQTPart* pQAOOnePart, Int iPartIdx)
4314{
4315  Int iTypeIdx;
4316  Int iNumTotalType = MAX_NUM_SAO_TYPE;
4317
4318  Int64 iEstDist;
4319  Int64 iOffsetOrg;
4320  Int64 iOffset;
4321  Int64 iCount;
4322  Int iClassIdx;
4323  Int uiShift = g_uiBitIncrement << 1;
4324  Double dAreaWeight =  (pQAOOnePart->part_xe - pQAOOnePart->part_xs + 1) * (pQAOOnePart->part_ye - pQAOOnePart->part_ys + 1);
4325  Double dComplexityCost = 0;
4326  Int    iQaoPara1 = SAO_RDCO;
4327
4328  UInt uiDepth = pQAOOnePart->PartLevel;
4329
4330  //   m_iDistOrg [iPartIdx] = 0;
4331
4332  m_iDistOrg [iPartIdx] =  (Int64)((Double)(iQaoPara1)/10000 * m_dLambdaLuma * dAreaWeight);
4333
4334  for (iTypeIdx=-1; iTypeIdx<iNumTotalType; iTypeIdx++)
4335  {
4336    if( m_bUseSBACRD )
4337    {
4338      m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST]); // pcCU->getDepth(0) ==> m_puhDepth[uiIdx]
4339      m_pcRDGoOnSbacCoder->resetBits();
4340    }
4341    else
4342    {
4343      m_pcEntropyCoder->resetEntropy();
4344      m_pcEntropyCoder->resetBits();
4345    }
4346
4347    iEstDist = 0;
4348
4349    m_pcEntropyCoder->m_pcEntropyCoderIf->codeAoUvlc(iTypeIdx+1);
4350
4351    if (iTypeIdx>=0)
4352    {
4353
4354      for(iClassIdx=1; iClassIdx < m_iNumClass[iTypeIdx]+1; iClassIdx++)
4355      {
4356        if(m_iCount [iPartIdx][iTypeIdx][iClassIdx])
4357        {
4358          m_iOffset[iPartIdx][iTypeIdx][iClassIdx]    = (Int64) xRoundIbdi((Double)(m_iOffsetOrg[iPartIdx][iTypeIdx][iClassIdx]<<m_uiAoBitDepth) / (Double)m_iCount [iPartIdx][iTypeIdx][iClassIdx]);
4359        }
4360        else
4361        {
4362          m_iOffsetOrg[iPartIdx][iTypeIdx][iClassIdx] = 0;
4363          m_iOffset[iPartIdx][iTypeIdx][iClassIdx] = 0;
4364        }
4365
4366        iCount     =  m_iCount [iPartIdx][iTypeIdx][iClassIdx];
4367        iOffset    =  m_iOffset[iPartIdx][iTypeIdx][iClassIdx] << (g_uiBitIncrement-m_uiAoBitDepth);
4368        iOffsetOrg =  m_iOffsetOrg[iPartIdx][iTypeIdx][iClassIdx];
4369        iEstDist   += (( iCount*iOffset*iOffset-iOffsetOrg*iOffset*2 ) >> uiShift);
4370        m_pcEntropyCoder->m_pcEntropyCoderIf->codeAoSvlc((Int)m_iOffset[iPartIdx][iTypeIdx][iClassIdx]);
4371      }
4372      m_iDist[iPartIdx][iTypeIdx] = iEstDist;
4373      m_iRate[iPartIdx][iTypeIdx] = m_pcEntropyCoder->getNumberOfWrittenBits();
4374
4375      m_dCost[iPartIdx][iTypeIdx] = (Double)((Double)m_iDist[iPartIdx][iTypeIdx] + m_dLambdaLuma * (Double) m_iRate[iPartIdx][iTypeIdx]);
4376      dComplexityCost = (Double)(iQaoPara1)/10000 * m_dLambdaLuma * (Double)m_iWeightAO[iTypeIdx] * dAreaWeight;
4377      m_dCost[iPartIdx][iTypeIdx] = (Double)((Double)m_iDist[iPartIdx][iTypeIdx] + m_dLambdaLuma * (Double) m_iRate[iPartIdx][iTypeIdx]) + dComplexityCost;
4378
4379      //       printf("\n%3d:%10.f, %10.0f, %10.0f",iPartIdx,(Double)m_iDist[iPartIdx][iTypeIdx], dComplexityCost);
4380
4381      // printf("\n%d, %d, %6d, %6d, %f", iPartIdx, iTypeIdx, (Int)m_iDist[iPartIdx][iTypeIdx], (Int)m_iRate[iPartIdx][iTypeIdx], m_dCost[iPartIdx][iTypeIdx]);
4382      if(m_dCost[iPartIdx][iTypeIdx] < m_dCostPartBest[iPartIdx])
4383      {
4384        m_iDistOrg [iPartIdx] = (Int64)dComplexityCost;
4385        m_dCostPartBest[iPartIdx] = m_dCost[iPartIdx][iTypeIdx];
4386        m_iTypePartBest[iPartIdx] = iTypeIdx;
4387        if( m_bUseSBACRD )
4388          m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[pQAOOnePart->PartLevel][CI_TEMP_BEST] );
4389      }
4390    }
4391    else
4392    {
4393
4394      if(m_iDistOrg[iPartIdx] < m_dCostPartBest[iPartIdx] )
4395      {
4396        m_dCostPartBest[iPartIdx] = (Double) m_iDistOrg[iPartIdx] + m_pcEntropyCoder->getNumberOfWrittenBits()*m_dLambdaLuma ; 
4397        m_iTypePartBest[iPartIdx] = -1;
4398        if( m_bUseSBACRD )
4399          m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[pQAOOnePart->PartLevel][CI_TEMP_BEST] );
4400      }
4401    }
4402  }
4403
4404  pQAOOnePart->bProcessed = true;
4405  pQAOOnePart->bSplit     = false;
4406  pQAOOnePart->iMinDist   =        m_iTypePartBest[iPartIdx] >= 0 ? m_iDist[iPartIdx][m_iTypePartBest[iPartIdx]] : m_iDistOrg[iPartIdx];
4407  pQAOOnePart->iMinRate   = (Int) (m_iTypePartBest[iPartIdx] >= 0 ? m_iRate[iPartIdx][m_iTypePartBest[iPartIdx]] : 0);
4408  pQAOOnePart->dMinCost   = pQAOOnePart->iMinDist + m_dLambdaLuma * pQAOOnePart->iMinRate;
4409  pQAOOnePart->iBestType  = m_iTypePartBest[iPartIdx];
4410  if (pQAOOnePart->iBestType != -1)
4411  {
4412    pQAOOnePart->bEnableFlag =  1;
4413    pQAOOnePart->iLength = m_iNumClass[m_psQAOPart[iPartIdx].iBestType];
4414    for (Int i=0; i<pQAOOnePart->iLength ; i++)
4415      pQAOOnePart->iOffset[i] = (Int) m_iOffset[iPartIdx][pQAOOnePart->iBestType][i+1];
4416  }
4417  else
4418  {
4419    pQAOOnePart->bEnableFlag =  0;
4420    pQAOOnePart->iLength     =  0;
4421  }
4422
4423}
4424
4425/** run Part Tree Disable.
4426 * \param  pQAOOnePart, iPartIdx
4427 */
4428Void TEncSampleAdaptiveOffset::xPartTreeDisable(Int iPartIdx)
4429{
4430  SAOQTPart*  pQAOPart= &(m_psQAOPart[iPartIdx]);
4431
4432  pQAOPart->bEnableFlag = false;
4433  pQAOPart->bSplit      = false;
4434  pQAOPart->iLength     =  0;
4435  pQAOPart->iBestType   = -1;
4436
4437  if (pQAOPart->PartLevel < m_uiMaxSplitLevel)
4438  {
4439    for (Int i=0; i<NUM_DOWN_PART; i++)
4440    {
4441      xPartTreeDisable(pQAOPart->DownPartsIdx[i]);
4442    }
4443  }
4444
4445}
4446
4447/** run QuadTree Decision Function.
4448 * \param  iPartIdx, pcPicOrg, pcPicDec, pcPicRest, &dCostFinal
4449 */
4450Void TEncSampleAdaptiveOffset::xQuadTreeDecisionFunc(Int iPartIdx, TComPicYuv* pcPicOrg, TComPicYuv* pcPicDec, TComPicYuv* pcPicRest, Double &dCostFinal)
4451{
4452  SAOQTPart*  pQAOPart= &(m_psQAOPart[iPartIdx]);
4453  UInt uiDepth = pQAOPart->PartLevel;
4454  UInt uhNextDepth = uiDepth+1;
4455
4456  if (iPartIdx == 0)
4457  {
4458    dCostFinal = 0;
4459  }
4460
4461  //QAO for this part
4462  if(!pQAOPart->bProcessed)
4463  {
4464    xQAOOnePart (pQAOPart, iPartIdx);
4465  }
4466
4467  //QAO for sub 4 parts
4468  if (pQAOPart->PartLevel < m_uiMaxSplitLevel)
4469  {
4470    Double      dCostNotSplit = m_dLambdaLuma + pQAOPart->dMinCost;
4471    Double      dCostSplit    = m_dLambdaLuma;
4472
4473    for (Int i=0; i< NUM_DOWN_PART ;i++)
4474    {
4475      if( m_bUseSBACRD ) 
4476      {
4477        if ( 0 == iPartIdx) //initialize RD with previous depth buffer
4478          m_pppcRDSbacCoder[uhNextDepth][CI_CURR_BEST]->load(m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST]);
4479        else
4480          m_pppcRDSbacCoder[uhNextDepth][CI_CURR_BEST]->load(m_pppcRDSbacCoder[uhNextDepth][CI_NEXT_BEST]);
4481      } 
4482      xQuadTreeDecisionFunc(pQAOPart->DownPartsIdx[i], pcPicOrg, pcPicDec, pcPicRest, dCostFinal);
4483      dCostSplit += dCostFinal;
4484      if( m_bUseSBACRD )
4485      {
4486        m_pppcRDSbacCoder[uhNextDepth][CI_NEXT_BEST]->store(m_pppcRDSbacCoder[uiDepth][CI_TEMP_BEST]);
4487      }
4488    }
4489
4490
4491    if(dCostSplit < dCostNotSplit)
4492    {
4493      dCostFinal = dCostSplit;
4494      pQAOPart->bSplit      = true;
4495      pQAOPart->bEnableFlag = false;
4496      pQAOPart->iLength     =  0;
4497      pQAOPart->iBestType   = -1;
4498    }
4499    else
4500    {
4501      dCostFinal = dCostNotSplit;
4502      pQAOPart->bSplit = false;
4503      for (Int i=0; i<NUM_DOWN_PART; i++)
4504      {
4505        xPartTreeDisable(pQAOPart->DownPartsIdx[i]);
4506      }
4507    }
4508  }
4509  else
4510  {
4511    dCostFinal = pQAOPart->dMinCost;
4512  }
4513}
4514/** destory TEncSampleAdaptiveOffset class.
4515 * \param 
4516 */
4517Void TEncSampleAdaptiveOffset::destoryEncBuffer()
4518{
4519
4520    for (Int i=0;i<m_iNumTotalParts;i++)
4521    {
4522      for (Int j=0;j<MAX_NUM_SAO_TYPE;j++)
4523      {
4524        if (m_iCount [i][j])
4525        {
4526          delete [] m_iCount [i][j]; 
4527        }
4528        if (m_iOffset[i][j])
4529        {
4530          delete [] m_iOffset[i][j]; 
4531        }
4532        if (m_iOffsetOrg[i][j])
4533        {
4534          delete [] m_iOffsetOrg[i][j]; 
4535        }
4536      }
4537      if (m_iRate[i])
4538      {
4539        delete [] m_iRate[i];
4540      }
4541      if (m_iDist[i])
4542      {
4543        delete [] m_iDist[i]; 
4544      }
4545      if (m_dCost[i])
4546      {
4547        delete [] m_dCost[i]; 
4548      }
4549      if (m_iCount [i])
4550      {
4551        delete [] m_iCount [i]; 
4552      }
4553      if (m_iOffset[i])
4554      {
4555        delete [] m_iOffset[i]; 
4556      }
4557      if (m_iOffsetOrg[i])
4558      {
4559        delete [] m_iOffsetOrg[i]; 
4560      }
4561
4562    }
4563    if (m_iDistOrg)
4564    {
4565      delete [] m_iDistOrg ; m_iDistOrg = NULL;
4566    }
4567    if (m_dCostPartBest)
4568    {
4569      delete [] m_dCostPartBest ; m_dCostPartBest = NULL;
4570    }
4571    if (m_iTypePartBest)
4572    {
4573      delete [] m_iTypePartBest ; m_iTypePartBest = NULL;
4574    }
4575    if (m_iRate)
4576    {
4577      delete [] m_iRate ; m_iRate = NULL;
4578    }
4579    if (m_iDist)
4580    {
4581      delete [] m_iDist ; m_iDist = NULL;
4582    }
4583    if (m_dCost)
4584    {
4585      delete [] m_dCost ; m_dCost = NULL;
4586    }
4587    if (m_iCount)
4588    {
4589      delete [] m_iCount  ; m_iCount = NULL;
4590    }
4591    if (m_iOffset)
4592    {
4593      delete [] m_iOffset ; m_iOffset = NULL;
4594    }
4595    if (m_iOffsetOrg)
4596    {
4597      delete [] m_iOffsetOrg ; m_iOffsetOrg = NULL;
4598    }
4599
4600
4601}
4602Void TEncSampleAdaptiveOffset::createEncBuffer()
4603{
4604    m_iDistOrg = new Int64 [m_iNumTotalParts]; 
4605    m_dCostPartBest = new Double [m_iNumTotalParts]; 
4606    m_iTypePartBest = new Int [m_iNumTotalParts]; 
4607
4608    m_iRate = new Int64* [m_iNumTotalParts];
4609    m_iDist = new Int64* [m_iNumTotalParts];
4610    m_dCost = new Double*[m_iNumTotalParts];
4611
4612    m_iCount  = new Int64 **[m_iNumTotalParts];
4613    m_iOffset = new Int64 **[m_iNumTotalParts];
4614    m_iOffsetOrg = new Int64 **[m_iNumTotalParts];
4615
4616    for (Int i=0;i<m_iNumTotalParts;i++)
4617    {
4618      m_iRate[i] = new Int64  [MAX_NUM_SAO_TYPE];
4619      m_iDist[i] = new Int64  [MAX_NUM_SAO_TYPE]; 
4620      m_dCost[i] = new Double [MAX_NUM_SAO_TYPE]; 
4621
4622      m_iCount [i] = new Int64 *[MAX_NUM_SAO_TYPE]; 
4623      m_iOffset[i] = new Int64 *[MAX_NUM_SAO_TYPE]; 
4624      m_iOffsetOrg[i] = new Int64 *[MAX_NUM_SAO_TYPE]; 
4625
4626      for (Int j=0;j<MAX_NUM_SAO_TYPE;j++)
4627      {
4628        m_iCount [i][j] = new Int64 [MAX_NUM_QAO_CLASS]; 
4629        m_iOffset[i][j] = new Int64 [MAX_NUM_QAO_CLASS]; 
4630        m_iOffsetOrg[i][j]=  new Int64 [MAX_NUM_QAO_CLASS]; 
4631      }
4632    }
4633
4634}
4635
4636/** start Sao Encoder.
4637 * \param pcPic, pcEntropyCoder, pppcRDSbacCoder, pcRDGoOnSbacCoder
4638 */
4639Void TEncSampleAdaptiveOffset::startSaoEnc( TComPic* pcPic, TEncEntropy* pcEntropyCoder, TEncSbac*** pppcRDSbacCoder, TEncSbac* pcRDGoOnSbacCoder)
4640{
4641  if( pcRDGoOnSbacCoder )
4642    m_bUseSBACRD = true;
4643  else
4644    m_bUseSBACRD = false;
4645
4646  m_pcPic = pcPic;
4647  m_pcEntropyCoder = pcEntropyCoder;
4648
4649  m_pppcRDSbacCoder = pppcRDSbacCoder;
4650  m_pcRDGoOnSbacCoder = pcRDGoOnSbacCoder;
4651  m_pcEntropyCoder->resetEntropy();
4652  m_pcEntropyCoder->resetBits();
4653
4654  if( m_bUseSBACRD )
4655  {
4656    m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[0][CI_NEXT_BEST]);
4657    m_pppcRDSbacCoder[0][CI_CURR_BEST]->load( m_pppcRDSbacCoder[0][CI_NEXT_BEST]);
4658  }
4659
4660  m_bSaoFlag = 0;
4661  for (Int i=0;i<m_iNumTotalParts;i++)
4662  {
4663    m_dCostPartBest[i] = MAX_DOUBLE;
4664    m_iTypePartBest[i] = -1;
4665    m_iDistOrg[i] = 0;
4666    for (Int j=0;j<MAX_NUM_SAO_TYPE;j++)
4667    {
4668      m_iDist[i][j] = 0;
4669      m_iRate[i][j] = 0;
4670      m_dCost[i][j] = 0;
4671      for (Int k=0;k<MAX_NUM_QAO_CLASS;k++)
4672      {
4673        m_iCount [i][j][k] = 0;
4674        m_iOffset[i][j][k] = 0;
4675        m_iOffsetOrg[i][j][k] = 0;
4676      } 
4677    }
4678  }
4679
4680  for(Int i=0; i< m_aiNumCulPartsLevel[m_uiMaxSplitLevel]; i++)
4681  {
4682    m_psQAOPart[i].bEnableFlag   =  0;
4683    m_psQAOPart[i].iBestType     = -1;
4684    m_psQAOPart[i].iLength       =  0;
4685    m_psQAOPart[i].bSplit        =  false; 
4686    m_psQAOPart[i].bProcessed    = false;
4687    m_psQAOPart[i].dMinCost      = MAX_DOUBLE;
4688    m_psQAOPart[i].iMinDist      = MAX_INT;
4689    m_psQAOPart[i].iMinRate      = MAX_INT;
4690
4691    for (Int j=0;j<MAX_NUM_QAO_CLASS;j++)
4692    {
4693      m_psQAOPart[i].iOffset[j] = 0;
4694    }
4695  }
4696
4697  for(Int i=0; i< m_aiNumCulPartsLevel[m_uiMaxSplitLevel]; i++)
4698  {
4699    m_psQAOPart[i].bEnableFlag   =  0;
4700    m_psQAOPart[i].iBestType     = -1;
4701    m_psQAOPart[i].iLength       =  0;
4702    for (Int j=0;j<MAX_NUM_QAO_CLASS;j++)
4703    {
4704      m_psQAOPart[i].iOffset[j] = 0;
4705    }
4706  }
4707
4708}
4709
4710/** end Sao Encoder.
4711 * \param
4712 */
4713Void TEncSampleAdaptiveOffset::endSaoEnc()
4714{
4715  m_pcPic = NULL;
4716  m_pcEntropyCoder = NULL;
4717}
4718
4719inline int xSign(int x)
4720{
4721  return ((x >> 31) | ((int)( (((unsigned int) -x)) >> 31)));
4722}
4723/** calculate Ao Stats Cu
4724 * \param iAddr, iPartIdx
4725 */
4726Void TEncSampleAdaptiveOffset::calcAoStatsCu(Int iAddr, Int iPartIdx)
4727{
4728  Int x,y;
4729  TComDataCU *pTmpCu = m_pcPic->getCU(iAddr);
4730  TComSPS *pTmpSPS =  m_pcPic->getSlice(0)->getSPS();
4731
4732
4733  Pel* pOrg      ;
4734  Pel* pRec      ;
4735  Int iStride    =  m_pcPic->getStride();
4736  Int iLcuWidth  = pTmpSPS->getMaxCUHeight();
4737  Int iLcuHeight = pTmpSPS->getMaxCUWidth();
4738  Int iPicWidth  = pTmpSPS->getWidth();
4739  Int iPicHeight = pTmpSPS->getHeight();
4740  UInt uiLPelX   = pTmpCu->getCUPelX();
4741  UInt uiRPelX   = uiLPelX + iLcuWidth;
4742  UInt uiTPelY   = pTmpCu->getCUPelY();
4743  UInt uiBPelY   = uiTPelY + iLcuHeight;
4744  uiRPelX    = uiRPelX > iPicWidth ? iPicWidth : uiRPelX;
4745  uiBPelY    = uiBPelY > iPicHeight? iPicHeight: uiBPelY;
4746  iLcuWidth  = uiRPelX - uiLPelX;
4747  iLcuHeight = uiBPelY - uiTPelY;
4748  Int64* iStats ;
4749  Int64* iCount ;
4750  Int iClassIdx;
4751
4752
4753  //   if(m_iAoType == BO_0 || m_iAoType == BO_1)
4754  {
4755    iStats = m_iOffsetOrg[iPartIdx][SAO_BO_0];
4756    iCount = m_iCount    [iPartIdx][SAO_BO_0];
4757
4758    pOrg      = m_pcPic->getPicYuvOrg()->getLumaAddr(iAddr);
4759    pRec      = m_pcPic->getPicYuvRec()->getLumaAddr(iAddr);
4760
4761    for (y=0; y<iLcuHeight; y++)
4762    {
4763      for (x=0; x<iLcuWidth; x++)
4764      {
4765        iClassIdx =  m_ppLumaTableBo0[pRec[x]];
4766        if (iClassIdx)
4767        {
4768          iStats[iClassIdx] += (pOrg[x] - pRec[x]); 
4769          iCount[iClassIdx] ++;
4770        }
4771      }
4772      pOrg += iStride;
4773      pRec += iStride;
4774    }
4775
4776    iStats = m_iOffsetOrg[iPartIdx][SAO_BO_1];
4777    iCount = m_iCount    [iPartIdx][SAO_BO_1];
4778
4779    pOrg      = m_pcPic->getPicYuvOrg()->getLumaAddr(iAddr);
4780    pRec      = m_pcPic->getPicYuvRec()->getLumaAddr(iAddr);
4781
4782    for (y=0; y<iLcuHeight; y++)
4783    {
4784      for (x=0; x<iLcuWidth; x++)
4785      {
4786        iClassIdx =  m_ppLumaTableBo1[pRec[x]];
4787        if (iClassIdx)
4788        {
4789          iStats[iClassIdx] += (pOrg[x] - pRec[x]); 
4790          iCount[iClassIdx] ++;
4791        }
4792      }
4793      pOrg += iStride;
4794      pRec += iStride;
4795    }
4796  }
4797
4798  Int iSignLeft;
4799  Int iSignRight;
4800  Int iSignDown;
4801  Int iSignDown1;
4802  Int iSignDown2;
4803
4804  UInt uiEdgeType;
4805
4806  //   if (m_iAoType == EO_0  || m_iAoType == EO_1 || m_iAoType == EO_2 || m_iAoType == EO_3)
4807  {
4808    //     if (m_iAoType == EO_0  )
4809    {
4810      iStats = m_iOffsetOrg[iPartIdx][SAO_EO_0];
4811      iCount = m_iCount    [iPartIdx][SAO_EO_0];
4812
4813      pOrg      = m_pcPic->getPicYuvOrg()->getLumaAddr(iAddr);
4814      pRec      = m_pcPic->getPicYuvRec()->getLumaAddr(iAddr);
4815      for (y=0; y<iLcuHeight; y++)
4816      {
4817        iSignLeft  = xSign(pRec[1] - pRec[0]);
4818        for (x=1; x<iLcuWidth-1; x++)
4819        {
4820          iSignRight =  xSign(pRec[x] - pRec[x+1]); 
4821          uiEdgeType =  iSignRight + iSignLeft + 2;
4822          iSignLeft  = -iSignRight;
4823
4824          iStats[m_auiEoTable[uiEdgeType]] += (pOrg[x] - pRec[x]);
4825          iCount[m_auiEoTable[uiEdgeType]] ++;
4826        }
4827        pOrg += iStride;
4828        pRec += iStride;
4829      }
4830    }
4831
4832    //     if (m_iAoType == EO_1  )
4833    {
4834      iStats = m_iOffsetOrg[iPartIdx][SAO_EO_1];
4835      iCount = m_iCount    [iPartIdx][SAO_EO_1];
4836
4837      pOrg      = m_pcPic->getPicYuvOrg()->getLumaAddr(iAddr);
4838      pRec      = m_pcPic->getPicYuvRec()->getLumaAddr(iAddr);
4839      pOrg += iStride;
4840      pRec += iStride;
4841
4842      for (x=0; x< iLcuWidth; x++)
4843      {
4844        m_iUpBuff1[x] = xSign(pRec[x] - pRec[x-iStride]);
4845      }
4846
4847      for (y=1; y<iLcuHeight-1; y++)
4848      {
4849        for (x=0; x<iLcuWidth; x++)
4850        {
4851
4852          iSignDown  =  xSign(pRec[x] - pRec[x+iStride]); 
4853          uiEdgeType =  iSignDown + m_iUpBuff1[x] + 2;
4854          m_iUpBuff1[x]= -iSignDown;
4855
4856          iStats[m_auiEoTable[uiEdgeType]] += (pOrg[x] - pRec[x]);
4857          iCount[m_auiEoTable[uiEdgeType]] ++;
4858
4859        }
4860        pOrg += iStride;
4861        pRec += iStride;
4862      }
4863    }
4864    //     if (m_iAoType == EO_2  )
4865    {
4866      iStats = m_iOffsetOrg[iPartIdx][SAO_EO_2];
4867      iCount = m_iCount    [iPartIdx][SAO_EO_2];
4868
4869      pOrg      = m_pcPic->getPicYuvOrg()->getLumaAddr(iAddr);
4870      pRec      = m_pcPic->getPicYuvRec()->getLumaAddr(iAddr);
4871      pOrg += iStride;
4872      pRec += iStride;
4873      for (x=1; x<iLcuWidth; x++)
4874      {
4875        m_iUpBuff1[x] = xSign(pRec[x] - pRec[x-iStride-1]);
4876      }
4877      for (y=1; y<iLcuHeight-1; y++)
4878      {
4879        iSignDown2 = xSign(pRec[iStride] - pRec[0]);
4880        for (x=1; x<iLcuWidth-1; x++)
4881        {
4882          iSignDown1      =  xSign(pRec[x] - pRec[x+iStride+1]) ;
4883          uiEdgeType      =  iSignDown1 + m_iUpBuff1[x] + 2;
4884          m_iUpBufft[x+1] = -iSignDown1; 
4885          iStats[m_auiEoTable[uiEdgeType]] += (pOrg[x] - pRec[x]);
4886          iCount[m_auiEoTable[uiEdgeType]] ++;
4887        }
4888        m_iUpBufft[1] = iSignDown2;
4889        ipSwap     = m_iUpBuff1;
4890        m_iUpBuff1 = m_iUpBufft;
4891        m_iUpBufft = ipSwap;
4892
4893        pRec += iStride;
4894        pOrg += iStride;
4895      }
4896    } 
4897    //     if (m_iAoType == EO_3  )
4898    {
4899      iStats = m_iOffsetOrg[iPartIdx][SAO_EO_3];
4900      iCount = m_iCount    [iPartIdx][SAO_EO_3];
4901
4902      pOrg      = m_pcPic->getPicYuvOrg()->getLumaAddr(iAddr);
4903      pRec      = m_pcPic->getPicYuvRec()->getLumaAddr(iAddr);
4904      pOrg += iStride;
4905      pRec += iStride;
4906      for (x=0; x<iLcuWidth-1; x++)
4907      {
4908        m_iUpBuff1[x] = xSign(pRec[x] - pRec[x-iStride+1]);
4909      }
4910
4911      for (y=1; y<iLcuHeight-1; y++)
4912      {
4913        for (x=1; x<iLcuWidth-1; x++)
4914        {
4915          iSignDown1      =  xSign(pRec[x] - pRec[x+iStride-1]) ;
4916          uiEdgeType      =  iSignDown1 + m_iUpBuff1[x] + 2;
4917          m_iUpBuff1[x-1]   = -iSignDown1; 
4918          iStats[m_auiEoTable[uiEdgeType]] += (pOrg[x] - pRec[x]);
4919          iCount[m_auiEoTable[uiEdgeType]] ++;
4920        }
4921        m_iUpBuff1[iLcuWidth-2] = xSign(pRec[iLcuWidth-2 + iStride] - pRec[iLcuWidth-1]);
4922
4923        pRec += iStride;
4924        pOrg += iStride;
4925      } 
4926    } 
4927  }
4928
4929}
4930
4931/** run get QAO Stats
4932 * \param pcPicYuvOrg, pcPicYuvRec, pcPicYuvExt
4933 */
4934Void TEncSampleAdaptiveOffset::xGetQAOStats(TComPicYuv* pcPicYuvOrg, TComPicYuv* pcPicYuvRec, TComPicYuv* pcPicYuvExt)
4935{
4936  Int iLevelIdx, iPartIdx, iTypeIdx, iClassIdx;
4937  Int i;
4938  Int iNumTotalType = MAX_NUM_SAO_TYPE;
4939  Int LcuIdxX;
4940  Int LcuIdxY;
4941  Int iAddr;
4942  Int iFrameWidthInCU = m_pcPic->getFrameWidthInCU();
4943  Int iDownPartIdx;
4944  Int iPartStart;
4945  Int iPartEnd;
4946
4947  if (m_uiMaxSplitLevel == 0)
4948  {
4949    iPartIdx = 0;
4950    for (LcuIdxY = m_psQAOPart[iPartIdx].StartCUY; LcuIdxY<= m_psQAOPart[iPartIdx].EndCUY; LcuIdxY++)
4951    {
4952      for (LcuIdxX = m_psQAOPart[iPartIdx].StartCUX; LcuIdxX<= m_psQAOPart[iPartIdx].EndCUX; LcuIdxX++)
4953      {
4954        iAddr = LcuIdxY*iFrameWidthInCU + LcuIdxX;
4955        calcAoStatsCu(iAddr, iPartIdx);
4956      }
4957    }
4958
4959  }
4960  else
4961  {
4962    for(iPartIdx=m_aiNumCulPartsLevel[m_uiMaxSplitLevel-1]; iPartIdx<m_aiNumCulPartsLevel[m_uiMaxSplitLevel]; iPartIdx++)
4963    {
4964      for (LcuIdxY = m_psQAOPart[iPartIdx].StartCUY; LcuIdxY<= m_psQAOPart[iPartIdx].EndCUY; LcuIdxY++)
4965      {
4966        for (LcuIdxX = m_psQAOPart[iPartIdx].StartCUX; LcuIdxX<= m_psQAOPart[iPartIdx].EndCUX; LcuIdxX++)
4967        {
4968          iAddr = LcuIdxY*iFrameWidthInCU + LcuIdxX;
4969          calcAoStatsCu(iAddr, iPartIdx);
4970        }
4971      }
4972    }
4973    for (iLevelIdx=m_uiMaxSplitLevel-1; iLevelIdx>=0; iLevelIdx--)
4974    {
4975      iPartStart = (iLevelIdx > 0) ? m_aiNumCulPartsLevel[iLevelIdx-1] : 0;
4976      iPartEnd   = m_aiNumCulPartsLevel[iLevelIdx];
4977      for(iPartIdx = iPartStart; iPartIdx < iPartEnd; iPartIdx++)
4978      {
4979        for (i=0; i<NUM_DOWN_PART; i++)
4980        {
4981          iDownPartIdx = m_psQAOPart[iPartIdx].DownPartsIdx[i];
4982          for (iTypeIdx=0; iTypeIdx<iNumTotalType; iTypeIdx++)
4983          {
4984            for (iClassIdx=0; iClassIdx<m_iNumClass[iTypeIdx]+1; iClassIdx++)
4985            {
4986              m_iOffsetOrg[iPartIdx][iTypeIdx][iClassIdx] += m_iOffsetOrg[iDownPartIdx][iTypeIdx][iClassIdx];
4987              m_iCount [iPartIdx][iTypeIdx][iClassIdx]    += m_iCount [iDownPartIdx][iTypeIdx][iClassIdx];
4988            }
4989          }
4990        }
4991      }
4992    }
4993  }
4994}
4995
4996/** Sample adaptive offset Process
4997 * \param dLambda
4998 */
4999Void TEncSampleAdaptiveOffset::SAOProcess( Double dLambda)
5000{
5001  // set lambda
5002  TComPicYuv* pcPicYuvOrg = m_pcPic->getPicYuvOrg();
5003  TComPicYuv* pcPicYuvRec = m_pcPic->getPicYuvRec();
5004
5005  TComPicYuv* pcPicYuvExt = NULL;
5006
5007  m_eSliceType           =  m_pcPic->getSlice(0)->getSliceType();
5008  m_iPicNalReferenceIdc  = (m_pcPic->getSlice(0)->isReferenced() ? 1 :0);
5009
5010  m_dLambdaLuma    = dLambda;
5011  m_dLambdaChroma  = dLambda;
5012
5013  if (g_uiBitIncrement>1)
5014  {
5015    m_uiAoBitDepth = 1;
5016  }
5017  else
5018  {
5019    m_uiAoBitDepth = 0;
5020  }
5021
5022  Double dCostFinal = 0;
5023
5024  xGetQAOStats(pcPicYuvOrg, pcPicYuvRec, pcPicYuvExt);
5025  xQuadTreeDecisionFunc(0, pcPicYuvOrg, pcPicYuvRec, pcPicYuvExt, dCostFinal);
5026  m_bSaoFlag = dCostFinal < m_iDistOrg[0] ? 1:0;
5027
5028
5029  if(m_bSaoFlag)
5030  {
5031    xProcessQuadTreeAo( 0, pcPicYuvRec,  pcPicYuvExt);
5032  }
5033
5034}
5035
5036
5037#endif
Note: See TracBrowser for help on using the repository browser.