source: 3DVCSoftware/branches/HTM-10.0-dev0/source/Lib/TLibCommon/TComSampleAdaptiveOffset.cpp @ 854

Last change on this file since 854 was 854, checked in by tech, 10 years ago

Integrated following MV-HEVC HLS 7 items:

H_MV_HLS7_GEN Stub for further integrations (not tested)
H_MV_HLS_7_OUTPUT_LAYERS_5_10_22_27
Output layer sets, various

(VPS/P0300/alt output layer flag) #27 Change alt output layer flag to be signalled within the loop of output layer sets, from JCTVC-P0300-v2. Decision: Adopt.
(VPS/P0156/Num of output_layer_flag) #10 Proposal 3: The output_layer_flag[ i ][ j ] is signalled for j equal to 0 to NumLayersInIdList[ lsIdx ] inclusive. It was remarked that we might be able to just assume that the top layer is always output; however, this was not entirely clear , so the safe thing to do may be to also send the flag for this layer.
(VPS/P0295/Default output layer sets) #5 Discussion from (P0110). Decision: Three-state approach (text in P0295, decoder shall allow 3 to be present and shall treat 3 the same as the value 2).

H_MV_HLS_7_HRD_P0156_7 (HRD/P0156/MaxSubLayersInLayerSetMinus1) #7 Proposal 1: signal, in the VPS extension, the DPB parameters for an output layer set for sub-DPBs only up to the maximum temporal sub-layers in the corresponding layer set
H_MV_HLS_7_VPS_P0048_14
(VPS/P0048/profile_ref_minus1 rem) #14 Remove profile_ref_minus1 from the VPS extension, from JCTVC-P0048
H_MV_HLS_7_VPS_P0076_15 (VPS/P0076/video signal info move) #15 Move video signal information syntax structure earlier in the VPS VUI.
H_MV_HLS_7_SPS_P0155_16_32
(SPS/P0155/sps_sub_layer_ordering_info) #16, #32 Not signal the sps_max_num_reorder_pics[], sps_max_latency_increase_plus1[], and sps_max_dec_pic_buffering_minus1[] syntax elements in the SPS when nuh_layer_id > 0.
H_MV_HLS_7_GEN_P0166_PPS_EXTENSION (GEN/P0166/pps_extension) #17 Add PPS extension type flags for conditional presence of syntax extensions per extension type, aligned with the SPS extension type flags, from JCTVC-P0166. Further align the SPS extension type flags syntax between RExt and MV-HEVC/SHVC
H_MV_HLS_7_FIX_SET_DPB_SIZE
Fix derivation dpb size parameters
H_MV_HLS_7_RESERVED_FLAGS Added flags

(SPS/P0312/SHVC reserved flag) The flag will be used for the syntax vert_phase_position_enable_flag in SHVC draft
(VPS/O0215/SHVC reserved flag): this flag will be used for the syntax cross_layer_phase_alignment_flag in SHVC draft.
(VPS VUI/O0199,P0312/SHVC reserved flags) the 3 reserved bits will be used for the syntaxes single_layer_for_non_irap_flag, higher_layer_irap_skip_flag and vert_phase_position_not_in_use_flag in SHVC draft.

H_MV_FIX_VPS_LAYER_ID_NOT_EQUAL_ZERO Discard VPS with nuh_layer_Id > 0
H_MV_HLS_7_MISC_P0130_EOS
(MISC/P0130/EOS NAL layer id) #19 Require that end of bitstream NAL unit shall have nuh_layer_id equal to 0, from JCTVC-P0130. Decoders shall allow an end of bitstream NAL unit with nuh_layer_id > 0 to be present, and shall ignore the NAL unit.
H_MV_HLS_7_MISC_P0182_13 (MISC/P0182/BL PS Compatibility flag) #13 Define the flag (in VPS VUI) with the proposed semantics, without specifying an associated extraction process. Editors to select the position in the VPS VUI.
H_MV_HLS_7_MISC_P0068_21
(MISC/P0068/all irap idr flag) #21 Add flag in VUI to indicate that all IRAP pictures are IDRs and that all layer pictures in an AU are IDR aligned, from JCTVC-P0068 proposal 1.
H_MV_HLS_7_FIX_INFER_CROSS_LAYER_IRAP_ALIGNED_FLAG Fix inference of cross_layer_irap_aligned_flag
H_MV_HLS_7_MISC_P0079_18
(MISC/P0079/NumActiveRefLayerPics) #18 Modification of derivation of variable NumActiveRefLayerPics.

File size: 24.0 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-2014, ITU/ISO/IEC
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are met:
11 *
12 *  * Redistributions of source code must retain the above copyright notice,
13 *    this list of conditions and the following disclaimer.
14 *  * Redistributions in binary form must reproduce the above copyright notice,
15 *    this list of conditions and the following disclaimer in the documentation
16 *    and/or other materials provided with the distribution.
17 *  * Neither the name of the ITU/ISO/IEC nor the names of its contributors may
18 *    be used to endorse or promote products derived from this software without
19 *    specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
31 * THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34/** \file     TComSampleAdaptiveOffset.cpp
35    \brief    sample adaptive offset class
36*/
37
38#include "TComSampleAdaptiveOffset.h"
39#include <string.h>
40#include <stdlib.h>
41#include <stdio.h>
42#include <math.h>
43
44//! \ingroup TLibCommon
45//! \{
46UInt g_saoMaxOffsetQVal[NUM_SAO_COMPONENTS];
47
48SAOOffset::SAOOffset()
49{ 
50  reset();
51}
52
53SAOOffset::~SAOOffset()
54{
55
56}
57
58Void SAOOffset::reset()
59{
60  modeIdc = SAO_MODE_OFF;
61  typeIdc = -1;
62  typeAuxInfo = -1;
63  ::memset(offset, 0, sizeof(Int)* MAX_NUM_SAO_CLASSES);
64}
65
66const SAOOffset& SAOOffset::operator= (const SAOOffset& src)
67{
68  modeIdc = src.modeIdc;
69  typeIdc = src.typeIdc;
70  typeAuxInfo = src.typeAuxInfo;
71  ::memcpy(offset, src.offset, sizeof(Int)* MAX_NUM_SAO_CLASSES);
72
73  return *this;
74}
75
76
77SAOBlkParam::SAOBlkParam()
78{
79  reset();
80}
81
82SAOBlkParam::~SAOBlkParam()
83{
84
85}
86
87Void SAOBlkParam::reset()
88{
89  for(Int compIdx=0; compIdx< 3; compIdx++)
90  {
91    offsetParam[compIdx].reset();
92  }
93}
94
95const SAOBlkParam& SAOBlkParam::operator= (const SAOBlkParam& src)
96{
97  for(Int compIdx=0; compIdx< 3; compIdx++)
98  {
99    offsetParam[compIdx] = src.offsetParam[compIdx];
100  }
101  return *this;
102
103}
104
105TComSampleAdaptiveOffset::TComSampleAdaptiveOffset()
106{
107  m_tempPicYuv = NULL;
108  for(Int compIdx=0; compIdx < NUM_SAO_COMPONENTS; compIdx++)
109  {
110    m_offsetClipTable[compIdx] = NULL;
111  }
112  m_signTable = NULL; 
113
114 
115  m_lineBufWidth = 0;
116  m_signLineBuf1 = NULL;
117  m_signLineBuf2 = NULL;
118}
119
120
121TComSampleAdaptiveOffset::~TComSampleAdaptiveOffset()
122{
123  destroy();
124 
125  if (m_signLineBuf1) delete[] m_signLineBuf1; m_signLineBuf1 = NULL;
126  if (m_signLineBuf2) delete[] m_signLineBuf2; m_signLineBuf2 = NULL;
127}
128
129Void TComSampleAdaptiveOffset::create( Int picWidth, Int picHeight, UInt maxCUWidth, UInt maxCUHeight, UInt maxCUDepth )
130{
131  destroy();
132
133  m_picWidth = picWidth;   
134  m_picHeight= picHeight;
135  m_maxCUWidth= maxCUWidth; 
136  m_maxCUHeight= maxCUHeight;
137
138  m_numCTUInWidth = (m_picWidth/m_maxCUWidth) + ((m_picWidth % m_maxCUWidth)?1:0);
139  m_numCTUInHeight= (m_picHeight/m_maxCUHeight) + ((m_picHeight % m_maxCUHeight)?1:0);
140  m_numCTUsPic = m_numCTUInHeight*m_numCTUInWidth;
141
142  //temporary picture buffer
143  if ( !m_tempPicYuv )
144  {
145    m_tempPicYuv = new TComPicYuv;
146    m_tempPicYuv->create( m_picWidth, m_picHeight, m_maxCUWidth, m_maxCUHeight, maxCUDepth );
147  }
148
149  //bit-depth related
150  for(Int compIdx =0; compIdx < NUM_SAO_COMPONENTS; compIdx++)
151  {
152    Int bitDepthSample = (compIdx == SAO_Y)?g_bitDepthY:g_bitDepthC;
153    m_offsetStepLog2  [compIdx] = max(bitDepthSample - MAX_SAO_TRUNCATED_BITDEPTH, 0);
154    g_saoMaxOffsetQVal[compIdx] = (1<<(min(bitDepthSample,MAX_SAO_TRUNCATED_BITDEPTH)-5))-1; //Table 9-32, inclusive
155  }
156
157  //look-up table for clipping
158  for(Int compIdx =0; compIdx < NUM_SAO_COMPONENTS; compIdx++)
159  {
160    Int bitDepthSample = (compIdx == SAO_Y)?g_bitDepthY:g_bitDepthC; //exclusive
161    Int maxSampleValue = (1<< bitDepthSample); //exclusive
162    Int maxOffsetValue = (g_saoMaxOffsetQVal[compIdx] << m_offsetStepLog2[compIdx]); 
163
164    m_offsetClipTable[compIdx] = new Int[(maxSampleValue + maxOffsetValue -1)+ (maxOffsetValue)+1 ]; //positive & negative range plus 0
165    m_offsetClip[compIdx] = &(m_offsetClipTable[compIdx][maxOffsetValue]);
166
167    //assign clipped values
168    Int* offsetClipPtr = m_offsetClip[compIdx];
169    for(Int k=0; k< maxSampleValue; k++)
170    {
171      *(offsetClipPtr + k) = k;
172    }
173    for(Int k=0; k< maxOffsetValue; k++ )
174    {
175      *(offsetClipPtr + maxSampleValue+ k) = maxSampleValue-1;
176      *(offsetClipPtr -k -1 )              = 0;
177    }
178    if(compIdx == SAO_Y) //g_bitDepthY is always larger than or equal to g_bitDepthC
179    {
180      m_signTable = new Short[ 2*(maxSampleValue-1) + 1 ];
181      m_sign = &(m_signTable[maxSampleValue-1]);
182
183      m_sign[0] = 0;
184      for(Int k=1; k< maxSampleValue; k++)
185      {
186        m_sign[k] = 1;
187        m_sign[-k]= -1;
188      }
189    }
190  } 
191
192}
193
194Void TComSampleAdaptiveOffset::destroy()
195{
196  if ( m_tempPicYuv )
197  {
198    m_tempPicYuv->destroy();
199    delete m_tempPicYuv;
200    m_tempPicYuv = NULL;
201  }
202
203  for(Int compIdx=0; compIdx < NUM_SAO_COMPONENTS; compIdx++)
204  {
205    if(m_offsetClipTable[compIdx])
206    {
207      delete[] m_offsetClipTable[compIdx]; m_offsetClipTable[compIdx] = NULL;
208    }
209  }
210  if( m_signTable )
211  {
212    delete[] m_signTable; m_signTable = NULL;
213  }
214}
215
216Void TComSampleAdaptiveOffset::invertQuantOffsets(Int compIdx, Int typeIdc, Int typeAuxInfo, Int* dstOffsets, Int* srcOffsets)
217{
218  Int codedOffset[MAX_NUM_SAO_CLASSES];
219
220  ::memcpy(codedOffset, srcOffsets, sizeof(Int)*MAX_NUM_SAO_CLASSES);
221  ::memset(dstOffsets, 0, sizeof(Int)*MAX_NUM_SAO_CLASSES);
222
223  if(typeIdc == SAO_TYPE_START_BO)
224  {
225    for(Int i=0; i< 4; i++)
226    {
227      dstOffsets[(typeAuxInfo+ i)%NUM_SAO_BO_CLASSES] = codedOffset[(typeAuxInfo+ i)%NUM_SAO_BO_CLASSES]*(1<<m_offsetStepLog2[compIdx]);
228    }
229  }
230  else //EO
231  {
232    for(Int i=0; i< NUM_SAO_EO_CLASSES; i++)
233    {
234      dstOffsets[i] = codedOffset[i] *(1<<m_offsetStepLog2[compIdx]);
235    }
236    assert(dstOffsets[SAO_CLASS_EO_PLAIN] == 0); //keep EO plain offset as zero
237  }
238
239}
240
241Int TComSampleAdaptiveOffset::getMergeList(TComPic* pic, Int ctu, SAOBlkParam* blkParams, std::vector<SAOBlkParam*>& mergeList)
242{
243  Int ctuX = ctu % m_numCTUInWidth;
244  Int ctuY = ctu / m_numCTUInWidth;
245  Int mergedCTUPos;
246  Int numValidMergeCandidates = 0;
247
248  for(Int mergeType=0; mergeType< NUM_SAO_MERGE_TYPES; mergeType++)
249  {
250    SAOBlkParam* mergeCandidate = NULL;
251
252    switch(mergeType)
253    {
254    case SAO_MERGE_ABOVE:
255      {
256        if(ctuY > 0)
257        {
258          mergedCTUPos = ctu- m_numCTUInWidth;
259          if( pic->getSAOMergeAvailability(ctu, mergedCTUPos) )
260          {
261            mergeCandidate = &(blkParams[mergedCTUPos]);
262          }
263        }
264      }
265      break;
266    case SAO_MERGE_LEFT:
267      {
268        if(ctuX > 0)
269        {
270          mergedCTUPos = ctu- 1;
271          if( pic->getSAOMergeAvailability(ctu, mergedCTUPos) )
272          {
273            mergeCandidate = &(blkParams[mergedCTUPos]);
274          }
275        }
276      }
277      break;
278    default:
279      {
280        printf("not a supported merge type");
281        assert(0);
282        exit(-1);
283      }
284    }
285
286    mergeList.push_back(mergeCandidate);
287    if (mergeCandidate != NULL)
288    {
289      numValidMergeCandidates++;
290    }
291  }
292
293  return numValidMergeCandidates;
294}
295
296
297Void TComSampleAdaptiveOffset::reconstructBlkSAOParam(SAOBlkParam& recParam, std::vector<SAOBlkParam*>& mergeList)
298{
299  for(Int compIdx=0; compIdx< NUM_SAO_COMPONENTS; compIdx++)
300  {
301    SAOOffset& offsetParam = recParam[compIdx];
302
303    if(offsetParam.modeIdc == SAO_MODE_OFF)
304    {
305      continue;
306    }
307
308    switch(offsetParam.modeIdc)
309    {
310    case SAO_MODE_NEW:
311      {
312        invertQuantOffsets(compIdx, offsetParam.typeIdc, offsetParam.typeAuxInfo, offsetParam.offset, offsetParam.offset);
313      }
314      break;
315    case SAO_MODE_MERGE:
316      {
317        SAOBlkParam* mergeTarget = mergeList[offsetParam.typeIdc];
318        assert(mergeTarget != NULL);
319
320        offsetParam = (*mergeTarget)[compIdx];
321      }
322      break;
323    default:
324      {
325        printf("Not a supported mode");
326        assert(0);
327        exit(-1);
328      }
329    }
330  }
331}
332
333Void TComSampleAdaptiveOffset::reconstructBlkSAOParams(TComPic* pic, SAOBlkParam* saoBlkParams)
334{
335  m_picSAOEnabled[SAO_Y] = m_picSAOEnabled[SAO_Cb] = m_picSAOEnabled[SAO_Cr] = false;
336
337  for(Int ctu=0; ctu< m_numCTUsPic; ctu++)
338  {
339    std::vector<SAOBlkParam*> mergeList;
340    getMergeList(pic, ctu, saoBlkParams, mergeList);
341
342    reconstructBlkSAOParam(saoBlkParams[ctu], mergeList);
343
344    for(Int compIdx=0; compIdx< NUM_SAO_COMPONENTS; compIdx++)
345    {
346      if(saoBlkParams[ctu][compIdx].modeIdc != SAO_MODE_OFF)
347      {
348        m_picSAOEnabled[compIdx] = true;
349      }
350    }
351  }
352
353
354}
355
356
357Void TComSampleAdaptiveOffset::offsetBlock(Int compIdx, Int typeIdx, Int* offset 
358                                          , Pel* srcBlk, Pel* resBlk, Int srcStride, Int resStride,  Int width, Int height
359                                          , Bool isLeftAvail,  Bool isRightAvail, Bool isAboveAvail, Bool isBelowAvail, Bool isAboveLeftAvail, Bool isAboveRightAvail, Bool isBelowLeftAvail, Bool isBelowRightAvail)
360{
361  if(m_lineBufWidth != m_maxCUWidth)
362  {
363    m_lineBufWidth = m_maxCUWidth;
364   
365    if (m_signLineBuf1) delete[] m_signLineBuf1; m_signLineBuf1 = NULL;
366    m_signLineBuf1 = new Char[m_lineBufWidth+1];
367   
368    if (m_signLineBuf2) delete[] m_signLineBuf2; m_signLineBuf2 = NULL;
369    m_signLineBuf2 = new Char[m_lineBufWidth+1];
370  }
371
372  Int* offsetClip = m_offsetClip[compIdx];
373
374  Int x,y, startX, startY, endX, endY, edgeType;
375  Int firstLineStartX, firstLineEndX, lastLineStartX, lastLineEndX;
376  Char signLeft, signRight, signDown;
377
378  Pel* srcLine = srcBlk;
379  Pel* resLine = resBlk;
380
381  switch(typeIdx)
382  {
383  case SAO_TYPE_EO_0:
384    {
385      offset += 2;
386      startX = isLeftAvail ? 0 : 1;
387      endX   = isRightAvail ? width : (width -1);
388      for (y=0; y< height; y++)
389      {
390        signLeft = (Char)m_sign[srcLine[startX] - srcLine[startX-1]];
391        for (x=startX; x< endX; x++)
392        {
393          signRight = (Char)m_sign[srcLine[x] - srcLine[x+1]]; 
394          edgeType =  signRight + signLeft;
395          signLeft  = -signRight;
396
397          resLine[x] = offsetClip[srcLine[x] + offset[edgeType]];
398        }
399        srcLine  += srcStride;
400        resLine += resStride;
401      }
402
403    }
404    break;
405  case SAO_TYPE_EO_90:
406    {
407      offset += 2;
408      Char *signUpLine = m_signLineBuf1;
409
410      startY = isAboveAvail ? 0 : 1;
411      endY   = isBelowAvail ? height : height-1;
412      if (!isAboveAvail)
413      {
414        srcLine += srcStride;
415        resLine += resStride;
416      }
417
418      Pel* srcLineAbove= srcLine- srcStride;
419      for (x=0; x< width; x++)
420      {
421        signUpLine[x] = (Char)m_sign[srcLine[x] - srcLineAbove[x]];
422      }
423
424      Pel* srcLineBelow;
425      for (y=startY; y<endY; y++)
426      {
427        srcLineBelow= srcLine+ srcStride;
428
429        for (x=0; x< width; x++)
430        {
431          signDown  = (Char)m_sign[srcLine[x] - srcLineBelow[x]]; 
432          edgeType = signDown + signUpLine[x];
433          signUpLine[x]= -signDown;
434
435          resLine[x] = offsetClip[srcLine[x] + offset[edgeType]];
436        }
437        srcLine += srcStride;
438        resLine += resStride;
439      }
440
441    }
442    break;
443  case SAO_TYPE_EO_135:
444    {
445      offset += 2;
446      Char *signUpLine, *signDownLine, *signTmpLine;
447
448      signUpLine  = m_signLineBuf1;
449      signDownLine= m_signLineBuf2;
450
451      startX = isLeftAvail ? 0 : 1 ;
452      endX   = isRightAvail ? width : (width-1);
453
454      //prepare 2nd line's upper sign
455      Pel* srcLineBelow= srcLine+ srcStride;
456      for (x=startX; x< endX+1; x++)
457      {
458        signUpLine[x] = (Char)m_sign[srcLineBelow[x] - srcLine[x- 1]];
459      }
460
461      //1st line
462      Pel* srcLineAbove= srcLine- srcStride;
463      firstLineStartX = isAboveLeftAvail ? 0 : 1;
464      firstLineEndX   = isAboveAvail? endX: 1;
465      for(x= firstLineStartX; x< firstLineEndX; x++)
466      {
467        edgeType  =  m_sign[srcLine[x] - srcLineAbove[x- 1]] - signUpLine[x+1];
468        resLine[x] = offsetClip[srcLine[x] + offset[edgeType]];
469      }
470      srcLine  += srcStride;
471      resLine  += resStride;
472
473
474      //middle lines
475      for (y= 1; y< height-1; y++)
476      {
477        srcLineBelow= srcLine+ srcStride;
478
479        for (x=startX; x<endX; x++)
480        {
481          signDown =  (Char)m_sign[srcLine[x] - srcLineBelow[x+ 1]] ;
482          edgeType =  signDown + signUpLine[x];
483          resLine[x] = offsetClip[srcLine[x] + offset[edgeType]];
484
485          signDownLine[x+1] = -signDown; 
486        }
487        signDownLine[startX] = (Char)m_sign[srcLineBelow[startX] - srcLine[startX-1]];
488
489        signTmpLine  = signUpLine;
490        signUpLine   = signDownLine;
491        signDownLine = signTmpLine;
492
493        srcLine += srcStride;
494        resLine += resStride;
495      }
496
497      //last line
498      srcLineBelow= srcLine+ srcStride;
499      lastLineStartX = isBelowAvail ? startX : (width -1);
500      lastLineEndX   = isBelowRightAvail ? width : (width -1);
501      for(x= lastLineStartX; x< lastLineEndX; x++)
502      {
503        edgeType =  m_sign[srcLine[x] - srcLineBelow[x+ 1]] + signUpLine[x];
504        resLine[x] = offsetClip[srcLine[x] + offset[edgeType]];
505
506      }
507    }
508    break;
509  case SAO_TYPE_EO_45:
510    {
511      offset += 2;
512      Char *signUpLine = m_signLineBuf1+1;
513
514      startX = isLeftAvail ? 0 : 1;
515      endX   = isRightAvail ? width : (width -1);
516
517      //prepare 2nd line upper sign
518      Pel* srcLineBelow= srcLine+ srcStride;
519      for (x=startX-1; x< endX; x++)
520      {
521        signUpLine[x] = (Char)m_sign[srcLineBelow[x] - srcLine[x+1]];
522      }
523
524
525      //first line
526      Pel* srcLineAbove= srcLine- srcStride;
527      firstLineStartX = isAboveAvail ? startX : (width -1 );
528      firstLineEndX   = isAboveRightAvail ? width : (width-1);
529      for(x= firstLineStartX; x< firstLineEndX; x++)
530      {
531        edgeType = m_sign[srcLine[x] - srcLineAbove[x+1]] -signUpLine[x-1];
532        resLine[x] = offsetClip[srcLine[x] + offset[edgeType]];
533      }
534      srcLine += srcStride;
535      resLine += resStride;
536
537      //middle lines
538      for (y= 1; y< height-1; y++)
539      {
540        srcLineBelow= srcLine+ srcStride;
541
542        for(x= startX; x< endX; x++)
543        {
544          signDown =  (Char)m_sign[srcLine[x] - srcLineBelow[x-1]] ;
545          edgeType =  signDown + signUpLine[x];
546          resLine[x] = offsetClip[srcLine[x] + offset[edgeType]];
547          signUpLine[x-1] = -signDown; 
548        }
549        signUpLine[endX-1] = (Char)m_sign[srcLineBelow[endX-1] - srcLine[endX]];
550        srcLine  += srcStride;
551        resLine += resStride;
552      }
553
554      //last line
555      srcLineBelow= srcLine+ srcStride;
556      lastLineStartX = isBelowLeftAvail ? 0 : 1;
557      lastLineEndX   = isBelowAvail ? endX : 1;
558      for(x= lastLineStartX; x< lastLineEndX; x++)
559      {
560        edgeType = m_sign[srcLine[x] - srcLineBelow[x-1]] + signUpLine[x];
561        resLine[x] = offsetClip[srcLine[x] + offset[edgeType]];
562
563      }
564    }
565    break;
566  case SAO_TYPE_BO:
567    {
568      Int shiftBits = ((compIdx == SAO_Y)?g_bitDepthY:g_bitDepthC)- NUM_SAO_BO_CLASSES_LOG2;
569      for (y=0; y< height; y++)
570      {
571        for (x=0; x< width; x++)
572        {
573          resLine[x] = offsetClip[ srcLine[x] + offset[srcLine[x] >> shiftBits] ];
574        }
575        srcLine += srcStride;
576        resLine += resStride;
577      }
578    }
579    break;
580  default:
581    {
582      printf("Not a supported SAO types\n");
583      assert(0);
584      exit(-1);
585    }
586  }
587
588
589}
590
591Void TComSampleAdaptiveOffset::offsetCTU(Int ctu, TComPicYuv* srcYuv, TComPicYuv* resYuv, SAOBlkParam& saoblkParam, TComPic* pPic)
592{
593  Bool isLeftAvail,isRightAvail,isAboveAvail,isBelowAvail,isAboveLeftAvail,isAboveRightAvail,isBelowLeftAvail,isBelowRightAvail;
594
595  if( 
596    (saoblkParam[SAO_Y ].modeIdc == SAO_MODE_OFF) &&
597    (saoblkParam[SAO_Cb].modeIdc == SAO_MODE_OFF) &&
598    (saoblkParam[SAO_Cr].modeIdc == SAO_MODE_OFF)
599    )
600  {
601    return;
602  }
603
604  //block boundary availability
605  pPic->getPicSym()->deriveLoopFilterBoundaryAvailibility(ctu, isLeftAvail,isRightAvail,isAboveAvail,isBelowAvail,isAboveLeftAvail,isAboveRightAvail,isBelowLeftAvail,isBelowRightAvail);
606
607  Int yPos   = (ctu / m_numCTUInWidth)*m_maxCUHeight;
608  Int xPos   = (ctu % m_numCTUInWidth)*m_maxCUWidth;
609  Int height = (yPos + m_maxCUHeight > m_picHeight)?(m_picHeight- yPos):m_maxCUHeight;
610  Int width  = (xPos + m_maxCUWidth  > m_picWidth )?(m_picWidth - xPos):m_maxCUWidth;
611
612  for(Int compIdx= 0; compIdx < NUM_SAO_COMPONENTS; compIdx++)
613  {
614    SAOOffset& ctbOffset = saoblkParam[compIdx];
615
616    if(ctbOffset.modeIdc != SAO_MODE_OFF)
617    {
618      Bool isLuma     = (compIdx == SAO_Y);
619      Int  formatShift= isLuma?0:1;
620
621      Int  blkWidth   = (width  >> formatShift);
622      Int  blkHeight  = (height >> formatShift);
623      Int  blkYPos    = (yPos   >> formatShift);
624      Int  blkXPos    = (xPos   >> formatShift);
625
626      Int  srcStride = isLuma?srcYuv->getStride():srcYuv->getCStride();
627      Pel* srcBlk    = getPicBuf(srcYuv, compIdx)+ (yPos >> formatShift)*srcStride+ (xPos >> formatShift);
628
629      Int  resStride  = isLuma?resYuv->getStride():resYuv->getCStride();
630      Pel* resBlk     = getPicBuf(resYuv, compIdx)+ blkYPos*resStride+ blkXPos;
631
632      offsetBlock( compIdx, ctbOffset.typeIdc, ctbOffset.offset
633                  , srcBlk, resBlk, srcStride, resStride, blkWidth, blkHeight
634                  , isLeftAvail, isRightAvail
635                  , isAboveAvail, isBelowAvail
636                  , isAboveLeftAvail, isAboveRightAvail
637                  , isBelowLeftAvail, isBelowRightAvail
638                  );
639    }
640  } //compIdx
641
642}
643
644
645Void TComSampleAdaptiveOffset::SAOProcess(TComPic* pDecPic)
646{
647  if(!m_picSAOEnabled[SAO_Y] && !m_picSAOEnabled[SAO_Cb] && !m_picSAOEnabled[SAO_Cr])
648  {
649    return;
650  }
651  TComPicYuv* resYuv = pDecPic->getPicYuvRec();
652  TComPicYuv* srcYuv = m_tempPicYuv;
653  resYuv->copyToPic(srcYuv);
654  for(Int ctu= 0; ctu < m_numCTUsPic; ctu++)
655  {
656    offsetCTU(ctu, srcYuv, resYuv, (pDecPic->getPicSym()->getSAOBlkParam())[ctu], pDecPic);
657  } //ctu
658}
659
660
661Pel* TComSampleAdaptiveOffset::getPicBuf(TComPicYuv* pPicYuv, Int compIdx)
662{
663  Pel* pBuf = NULL;
664  switch(compIdx)
665  {
666  case SAO_Y:
667    {
668      pBuf = pPicYuv->getLumaAddr();
669    }
670    break;
671  case SAO_Cb:
672    {
673      pBuf = pPicYuv->getCbAddr();
674    }
675    break;
676  case SAO_Cr:
677    {
678      pBuf = pPicYuv->getCrAddr();
679    }
680    break;
681  default:
682    {
683      printf("Not a legal component ID for SAO\n");
684      assert(0);
685      exit(-1);
686    }
687  }
688
689  return pBuf;
690}
691
692/** PCM LF disable process.
693 * \param pcPic picture (TComPic) pointer
694 * \returns Void
695 *
696 * \note Replace filtered sample values of PCM mode blocks with the transmitted and reconstructed ones.
697 */
698Void TComSampleAdaptiveOffset::PCMLFDisableProcess (TComPic* pcPic)
699{
700  xPCMRestoration(pcPic);
701}
702
703/** Picture-level PCM restoration.
704 * \param pcPic picture (TComPic) pointer
705 * \returns Void
706 */
707Void TComSampleAdaptiveOffset::xPCMRestoration(TComPic* pcPic)
708{
709  Bool  bPCMFilter = (pcPic->getSlice(0)->getSPS()->getUsePCM() && pcPic->getSlice(0)->getSPS()->getPCMFilterDisableFlag())? true : false;
710
711  if(bPCMFilter || pcPic->getSlice(0)->getPPS()->getTransquantBypassEnableFlag())
712  {
713    for( UInt uiCUAddr = 0; uiCUAddr < pcPic->getNumCUsInFrame() ; uiCUAddr++ )
714    {
715      TComDataCU* pcCU = pcPic->getCU(uiCUAddr);
716
717      xPCMCURestoration(pcCU, 0, 0); 
718    } 
719  }
720}
721
722/** PCM CU restoration.
723 * \param pcCU pointer to current CU
724 * \param uiAbsPartIdx part index
725 * \param uiDepth CU depth
726 * \returns Void
727 */
728Void TComSampleAdaptiveOffset::xPCMCURestoration ( TComDataCU* pcCU, UInt uiAbsZorderIdx, UInt uiDepth )
729{
730  TComPic* pcPic     = pcCU->getPic();
731  UInt uiCurNumParts = pcPic->getNumPartInCU() >> (uiDepth<<1);
732  UInt uiQNumParts   = uiCurNumParts>>2;
733
734  // go to sub-CU
735  if( pcCU->getDepth(uiAbsZorderIdx) > uiDepth )
736  {
737    for ( UInt uiPartIdx = 0; uiPartIdx < 4; uiPartIdx++, uiAbsZorderIdx+=uiQNumParts )
738    {
739      UInt uiLPelX   = pcCU->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiAbsZorderIdx] ];
740      UInt uiTPelY   = pcCU->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiAbsZorderIdx] ];
741      if( ( uiLPelX < pcCU->getSlice()->getSPS()->getPicWidthInLumaSamples() ) && ( uiTPelY < pcCU->getSlice()->getSPS()->getPicHeightInLumaSamples() ) )
742        xPCMCURestoration( pcCU, uiAbsZorderIdx, uiDepth+1 );
743    }
744    return;
745  }
746
747  // restore PCM samples
748  if ((pcCU->getIPCMFlag(uiAbsZorderIdx)&& pcPic->getSlice(0)->getSPS()->getPCMFilterDisableFlag()) || pcCU->isLosslessCoded( uiAbsZorderIdx))
749  {
750    xPCMSampleRestoration (pcCU, uiAbsZorderIdx, uiDepth, TEXT_LUMA    );
751    xPCMSampleRestoration (pcCU, uiAbsZorderIdx, uiDepth, TEXT_CHROMA_U);
752    xPCMSampleRestoration (pcCU, uiAbsZorderIdx, uiDepth, TEXT_CHROMA_V);
753  }
754}
755
756/** PCM sample restoration.
757 * \param pcCU pointer to current CU
758 * \param uiAbsPartIdx part index
759 * \param uiDepth CU depth
760 * \param ttText texture component type
761 * \returns Void
762 */
763Void TComSampleAdaptiveOffset::xPCMSampleRestoration (TComDataCU* pcCU, UInt uiAbsZorderIdx, UInt uiDepth, TextType ttText)
764{
765  TComPicYuv* pcPicYuvRec = pcCU->getPic()->getPicYuvRec();
766  Pel* piSrc;
767  Pel* piPcm;
768  UInt uiStride;
769  UInt uiWidth;
770  UInt uiHeight;
771  UInt uiPcmLeftShiftBit; 
772  UInt uiX, uiY;
773  UInt uiMinCoeffSize = pcCU->getPic()->getMinCUWidth()*pcCU->getPic()->getMinCUHeight();
774  UInt uiLumaOffset   = uiMinCoeffSize*uiAbsZorderIdx;
775  UInt uiChromaOffset = uiLumaOffset>>2;
776
777  if( ttText == TEXT_LUMA )
778  {
779    piSrc = pcPicYuvRec->getLumaAddr( pcCU->getAddr(), uiAbsZorderIdx);
780    piPcm = pcCU->getPCMSampleY() + uiLumaOffset;
781    uiStride  = pcPicYuvRec->getStride();
782    uiWidth  = (g_uiMaxCUWidth >> uiDepth);
783    uiHeight = (g_uiMaxCUHeight >> uiDepth);
784    if ( pcCU->isLosslessCoded(uiAbsZorderIdx) && !pcCU->getIPCMFlag(uiAbsZorderIdx) )
785    {
786      uiPcmLeftShiftBit = 0;
787    }
788    else
789    {
790      uiPcmLeftShiftBit = g_bitDepthY - pcCU->getSlice()->getSPS()->getPCMBitDepthLuma();
791    }
792  }
793  else
794  {
795    if( ttText == TEXT_CHROMA_U )
796    {
797      piSrc = pcPicYuvRec->getCbAddr( pcCU->getAddr(), uiAbsZorderIdx );
798      piPcm = pcCU->getPCMSampleCb() + uiChromaOffset;
799    }
800    else
801    {
802      piSrc = pcPicYuvRec->getCrAddr( pcCU->getAddr(), uiAbsZorderIdx );
803      piPcm = pcCU->getPCMSampleCr() + uiChromaOffset;
804    }
805
806    uiStride = pcPicYuvRec->getCStride();
807    uiWidth  = ((g_uiMaxCUWidth >> uiDepth)/2);
808    uiHeight = ((g_uiMaxCUWidth >> uiDepth)/2);
809    if ( pcCU->isLosslessCoded(uiAbsZorderIdx) && !pcCU->getIPCMFlag(uiAbsZorderIdx) )
810    {
811      uiPcmLeftShiftBit = 0;
812    }
813    else
814    {
815      uiPcmLeftShiftBit = g_bitDepthC - pcCU->getSlice()->getSPS()->getPCMBitDepthChroma();
816    }
817  }
818
819  for( uiY = 0; uiY < uiHeight; uiY++ )
820  {
821    for( uiX = 0; uiX < uiWidth; uiX++ )
822    {
823      piSrc[uiX] = (piPcm[uiX] << uiPcmLeftShiftBit);
824    }
825    piPcm += uiWidth;
826    piSrc += uiStride;
827  }
828}
829
830//! \}
Note: See TracBrowser for help on using the repository browser.