source: SHVCSoftware/branches/SHM-dev/source/Lib/TLibCommon/TCom3DAsymLUT.cpp @ 1550

Last change on this file since 1550 was 1549, checked in by seregin, 9 years ago

port rev 4732, update copyright notice to include 2016

File size: 14.3 KB
Line 
1/* The copyright in this software is being made available under the BSD
2 * License, included below. This software may be subject to other third party
3 * and contributor rights, including patent rights, and no such rights are
4 * granted under this license.
5 *
6 * Copyright (c) 2010-2016, 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     TCom3DAsymLUT.cpp
35    \brief    TCom3DAsymLUT class
36*/
37
38#include <cstdio>
39#include <cstdlib>
40#include <cstring>
41#include <cmath>
42#include <algorithm>
43
44#include "CommonDef.h"
45#include "TCom3DAsymLUT.h"
46#include "TComPicYuv.h"
47
48#if CGS_3D_ASYMLUT
49const Int TCom3DAsymLUT::m_nVertexIdxOffset[4][3] = { { 0 , 0 , 0 } , { 0 , 1 , 0 } , { 0 , 1 , 1 } , { 1 , 1 , 1 } };
50
51TCom3DAsymLUT::TCom3DAsymLUT()
52{
53  m_pCuboid = NULL;
54  m_nResQuanBit = 0;
55#if R0164_CGS_LUT_BUGFIX_CHECK
56  m_pCuboidExplicit = NULL;
57  m_pCuboidFilled = NULL;
58#endif
59}
60
61TCom3DAsymLUT::~TCom3DAsymLUT()
62{
63  destroy();
64}
65
66Void TCom3DAsymLUT::create( Int nMaxOctantDepth, Int nInputBitDepth, Int nInputBitDepthC, Int nOutputBitDepth, Int nOutputBitDepthC, Int nMaxYPartNumLog2, Int nAdaptCThresholdU, Int nAdaptCThresholdV )
67{
68  m_nMaxOctantDepth = nMaxOctantDepth;
69  m_nInputBitDepthY = nInputBitDepth;
70  m_nOutputBitDepthY = nOutputBitDepth;
71  m_nInputBitDepthC = nInputBitDepthC;
72  m_nOutputBitDepthC = nOutputBitDepthC;
73  m_nDeltaBitDepthC = m_nOutputBitDepthC - m_nInputBitDepthC;
74  m_nDeltaBitDepth = m_nOutputBitDepthY - m_nInputBitDepthY;
75  m_nMaxYPartNumLog2 = nMaxYPartNumLog2;
76  m_nMaxPartNumLog2 = 3 * m_nMaxOctantDepth + m_nMaxYPartNumLog2;
77
78  xUpdatePartitioning( nMaxOctantDepth, nMaxYPartNumLog2, nAdaptCThresholdU, nAdaptCThresholdV );
79
80  m_nYSize = 1 << ( m_nMaxOctantDepth + m_nMaxYPartNumLog2 );
81  m_nUSize = 1 << m_nMaxOctantDepth;
82  m_nVSize = 1 << m_nMaxOctantDepth;
83  assert( m_nYSize > 0 && m_nUSize > 0 && m_nVSize > 0 );
84
85  if( m_pCuboid != NULL )
86  {
87    destroy();
88  }
89  xAllocate3DArray( m_pCuboid , m_nYSize , m_nUSize , m_nVSize );
90
91#if R0164_CGS_LUT_BUGFIX_CHECK
92  xAllocate3DArray( m_pCuboidExplicit , m_nYSize , m_nUSize , m_nVSize );
93  xAllocate3DArray( m_pCuboidFilled   , m_nYSize , m_nUSize , m_nVSize );
94#endif
95}
96
97Void TCom3DAsymLUT::destroy()
98{
99  xFree3DArray( m_pCuboid );
100#if R0164_CGS_LUT_BUGFIX_CHECK
101  xFree3DArray( m_pCuboidExplicit );
102  xFree3DArray( m_pCuboidFilled   );
103#endif
104}
105
106
107Void TCom3DAsymLUT::xUpdatePartitioning( Int nCurOctantDepth, Int nCurYPartNumLog2, Int nAdaptCThresholdU, Int nAdaptCThresholdV  )
108{
109  assert( nCurOctantDepth <= m_nMaxOctantDepth );
110  assert( nCurYPartNumLog2 + nCurOctantDepth <= m_nMaxYPartNumLog2 + m_nMaxOctantDepth );
111
112  m_nCurOctantDepth = nCurOctantDepth;
113  m_nCurYPartNumLog2 = nCurYPartNumLog2;
114  m_nYShift2Idx = m_nInputBitDepthY - m_nCurOctantDepth - m_nCurYPartNumLog2;
115  m_nUShift2Idx = m_nVShift2Idx = m_nInputBitDepthC - m_nCurOctantDepth;
116
117  m_nMappingShift = 10 + m_nInputBitDepthY - m_nOutputBitDepthY; 
118  m_nAdaptCThresholdU = nAdaptCThresholdU;
119  m_nAdaptCThresholdV = nAdaptCThresholdV;
120
121  m_nMappingOffset = 1 << ( m_nMappingShift - 1 );
122
123#if R0179_ENC_OPT_3DLUT_SIZE
124  m_nYSize = 1 << ( m_nCurOctantDepth + m_nCurYPartNumLog2 );
125  m_nUSize = 1 << m_nCurOctantDepth;
126  m_nVSize = 1 << m_nCurOctantDepth;
127#endif
128}
129
130Void TCom3DAsymLUT::colorMapping( TComPicYuv * pcPic, TComPicYuv * pcPicDst )
131{
132  Int nWidth = pcPic->getWidth(COMPONENT_Y);
133  Int nHeight = pcPic->getHeight(COMPONENT_Y);
134  Int nStrideY = pcPic->getStride(COMPONENT_Y);
135  Int nStrideC = pcPic->getStride(COMPONENT_Cb);
136  Pel * pY = pcPic->getAddr(COMPONENT_Y);
137  Pel * pU = pcPic->getAddr(COMPONENT_Cb);
138  Pel * pV = pcPic->getAddr(COMPONENT_Cr);
139
140  Int nDstStrideY = pcPicDst->getStride(COMPONENT_Y);
141  Int nDstStrideC = pcPicDst->getStride(COMPONENT_Cb);
142  Pel * pYDst = pcPicDst->getAddr(COMPONENT_Y);
143  Pel * pUDst = pcPicDst->getAddr(COMPONENT_Cb);
144  Pel * pVDst = pcPicDst->getAddr(COMPONENT_Cr);
145
146  Pel *pUPrev = pU;
147  Pel *pVPrev = pV;
148  Pel *pUNext = pU+nStrideC;
149  Pel *pVNext = pV+nStrideC;
150
151  // alignment padding
152  pcPic->setBorderExtension( false );
153  pcPic->extendPicBorder();
154
155  Pel iMaxValY = (1<<getOutputBitDepthY())-1;
156  Pel iMaxValC = (1<<getOutputBitDepthC())-1;
157  for( Int y = 0 ; y < nHeight ; y += 2 )
158  {
159    for( Int xY = 0 , xC = 0 ; xY < nWidth ; xY += 2 , xC++ )
160    {
161      Pel srcY00 = pY[xY];
162      Pel srcY01 = pY[xY+1];
163      Pel srcY10 = pY[xY+nStrideY];
164      Pel srcY11 = pY[xY+nStrideY+1];
165      Pel srcYaver;
166      Pel srcU = pU[xC];
167      Pel srcV = pV[xC];
168      Pel dstY00, dstY01, dstY10, dstY11;
169
170      // alignment
171      srcYaver =  (srcY00 + srcY10 + 1 ) >> 1;
172      Pel srcUP0 = pUPrev[xC];
173      Pel srcVP0 = pVPrev[xC];       
174      Pel tmpU =  (srcUP0 + srcU + (srcU<<1) + 2 ) >> 2;
175      Pel tmpV =  (srcVP0 + srcV + (srcV<<1) + 2 ) >> 2;
176      dstY00 = xMapY( srcY00 , tmpU , tmpV );
177      Pel a = pU[xC+1] + srcU;
178      tmpU =  ((a<<1) + a + srcUP0 + pUPrev[xC+1] + 4 ) >> 3;
179      Pel b = pV[xC+1] + srcV;
180      tmpV =  ((b<<1) + b + srcVP0 + pVPrev[xC+1] + 4 ) >> 3;
181      dstY01 = xMapY( srcY01 , tmpU , tmpV );
182
183      srcUP0 = pUNext[xC];
184      srcVP0 = pVNext[xC];
185      tmpU =  (srcUP0 + srcU + (srcU<<1) + 2 ) >> 2;
186      tmpV =  (srcVP0 + srcV + (srcV<<1) + 2 ) >> 2;
187      dstY10 = xMapY( srcY10 , tmpU , tmpV );
188      tmpU =  ((a<<1) + a + srcUP0 + pUNext[xC+1] + 4 ) >> 3;
189      tmpV =  ((b<<1) + b + srcVP0 + pVNext[xC+1] + 4 ) >> 3;
190      dstY11 = xMapY( srcY11 , tmpU , tmpV );
191
192      SYUVP dstUV = xMapUV( srcYaver , srcU , srcV );
193      pYDst[xY] = Clip3((Pel)0, iMaxValY, dstY00 );
194      pYDst[xY+1] = Clip3((Pel)0, iMaxValY, dstY01 );
195      pYDst[xY+nDstStrideY] = Clip3((Pel)0, iMaxValY, dstY10 );
196      pYDst[xY+nDstStrideY+1] = Clip3((Pel)0, iMaxValY, dstY11 );
197      pUDst[xC] = Clip3((Pel)0, iMaxValC, dstUV.U );
198      pVDst[xC] = Clip3((Pel)0, iMaxValC, dstUV.V );
199    }
200    pY += nStrideY + nStrideY;
201
202    // alignment
203    pUPrev = pU;
204    pVPrev = pV;
205    pU = pUNext;
206    pV = pVNext;
207    pUNext += nStrideC;
208    pVNext += nStrideC;
209
210    pYDst += nDstStrideY + nDstStrideY;
211    pUDst += nDstStrideC;
212    pVDst += nDstStrideC;
213  }
214}
215
216SYUVP TCom3DAsymLUT::xGetCuboidVertexPredA( Int yIdx , Int uIdx , Int vIdx , Int nVertexIdx )
217{
218  assert( nVertexIdx < 4 );
219 
220  SYUVP sPred;
221
222  sPred.Y = sPred.U = sPred.V = 0;
223
224  if( nVertexIdx == 0 )
225  {
226    sPred.Y = xGetNormCoeffOne() << ( m_nOutputBitDepthY - m_nInputBitDepthY );
227  }
228  else if( nVertexIdx == 1 )
229  {
230    sPred.U = xGetNormCoeffOne() << ( m_nOutputBitDepthY - m_nInputBitDepthY );
231  }
232  else if( nVertexIdx == 2 )
233  {
234    sPred.V = xGetNormCoeffOne() << ( m_nOutputBitDepthY - m_nInputBitDepthY );
235  }
236
237  return sPred;
238}
239
240SYUVP  TCom3DAsymLUT::xGetCuboidVertexPredAll( Int yIdx , Int uIdx , Int vIdx , Int nVertexIdx , SCuboid *** pCurCuboid )
241{
242  SCuboid***  pCuboid = pCurCuboid ? pCurCuboid : m_pCuboid ;
243
244  SYUVP sPred;
245  if( yIdx == 0 )
246  {
247    sPred.Y = nVertexIdx == 0 ? 1024 : 0;
248    sPred.U = nVertexIdx == 1 ? 1024 : 0;
249    sPred.V = nVertexIdx == 2 ? 1024 : 0;
250  }
251  else
252  {
253    sPred = pCuboid[yIdx-1][uIdx][vIdx].P[nVertexIdx];
254  }
255
256  return sPred ;
257}
258
259SYUVP TCom3DAsymLUT::getCuboidVertexResTree( Int yIdx , Int uIdx , Int vIdx , Int nVertexIdx )
260{
261  const SYUVP & rYUVP = m_pCuboid[yIdx][uIdx][vIdx].P[nVertexIdx];
262  SYUVP sPred = xGetCuboidVertexPredAll( yIdx , uIdx , vIdx , nVertexIdx );
263
264  SYUVP sResidue;
265  sResidue.Y = ( rYUVP.Y - sPred.Y ) >> m_nResQuanBit;
266  sResidue.U = ( rYUVP.U - sPred.U ) >> m_nResQuanBit;
267  sResidue.V = ( rYUVP.V - sPred.V ) >> m_nResQuanBit;
268  return( sResidue );
269}
270
271Void TCom3DAsymLUT::setCuboidVertexResTree( Int yIdx , Int uIdx , Int vIdx , Int nVertexIdx , Int deltaY , Int deltaU , Int deltaV )
272{
273  SYUVP & rYUVP = m_pCuboid[yIdx][uIdx][vIdx].P[nVertexIdx];
274  SYUVP sPred = xGetCuboidVertexPredAll( yIdx , uIdx , vIdx , nVertexIdx );
275
276  rYUVP.Y = sPred.Y + ( deltaY << m_nResQuanBit );
277  rYUVP.U = sPred.U + ( deltaU << m_nResQuanBit );
278  rYUVP.V = sPred.V + ( deltaV << m_nResQuanBit );
279
280  // LUT coefficients are less than 12-bit
281  assert( -2048 <= rYUVP.Y && rYUVP.Y <= 2047 );
282  assert( -2048 <= rYUVP.U && rYUVP.U <= 2047 );
283  assert( -2048 <= rYUVP.V && rYUVP.V <= 2047 );
284}
285
286Pel TCom3DAsymLUT::xMapY( Pel y , Pel u , Pel v )
287{
288  const SCuboid & rCuboid = m_pCuboid[xGetYIdx(y)][xGetUIdx(u)][xGetVIdx(v)];
289  Pel dstY = ( ( rCuboid.P[0].Y * y + rCuboid.P[1].Y * u + rCuboid.P[2].Y * v + m_nMappingOffset ) >> m_nMappingShift ) + rCuboid.P[3].Y;
290
291  return( dstY );
292}
293
294SYUVP TCom3DAsymLUT::xMapUV( Pel y , Pel u , Pel v )
295{
296  const SCuboid & rCuboid = m_pCuboid[xGetYIdx(y)][xGetUIdx(u)][xGetVIdx(v)];
297  SYUVP dst;
298  dst.Y = 0;
299  dst.U = ( ( rCuboid.P[0].U * y + rCuboid.P[1].U * u + rCuboid.P[2].U * v + m_nMappingOffset ) >> m_nMappingShift ) + rCuboid.P[3].U;
300  dst.V = ( ( rCuboid.P[0].V * y + rCuboid.P[1].V * u + rCuboid.P[2].V * v + m_nMappingOffset ) >> m_nMappingShift ) + rCuboid.P[3].V;
301
302  return( dst );
303}
304
305Void TCom3DAsymLUT::xSaveCuboids( SCuboid *** pSrcCuboid )
306{
307#if R0179_ENC_OPT_3DLUT_SIZE
308  memcpy( m_pCuboid[0][0] , pSrcCuboid[0][0] , sizeof( SCuboid ) * getMaxYSize() * getMaxCSize() * getMaxCSize() );
309#else
310  memcpy( m_pCuboid[0][0] , pSrcCuboid[0][0] , sizeof( SCuboid ) * m_nYSize * m_nUSize * m_nVSize );
311#endif
312}
313
314Void TCom3DAsymLUT::copy3DAsymLUT( TCom3DAsymLUT * pSrc )
315{
316  assert( pSrc->getMaxOctantDepth() == getMaxOctantDepth() && pSrc->getMaxYPartNumLog2() == getMaxYPartNumLog2() );
317  xUpdatePartitioning( pSrc->getCurOctantDepth(), pSrc->getCurYPartNumLog2(), pSrc->getAdaptChromaThresholdU(), pSrc->getAdaptChromaThresholdV() );
318  setResQuantBit( pSrc->getResQuantBit() );
319  xSaveCuboids( pSrc->m_pCuboid );
320}
321
322#if R0164_CGS_LUT_BUGFIX_CHECK
323Void TCom3DAsymLUT::xInitCuboids( )
324{
325  // All vertices are initialized as non-exlicitly-encoded
326  for( Int yIdx = 0 ; yIdx < m_nYSize ; yIdx++ )
327  {
328    for( Int uIdx = 0 ; uIdx < m_nUSize ; uIdx++ )
329    {
330      for( Int vIdx = 0 ; vIdx < m_nVSize ; vIdx++ )
331      { 
332        m_pCuboidExplicit[yIdx][uIdx][vIdx] = false;
333        m_pCuboidFilled[yIdx][uIdx][vIdx]   = false;
334      }
335    }
336  }
337}
338
339Void TCom3DAsymLUT::xCuboidsFilledCheck( Int yIdx , Int uIdx , Int vIdx )
340{
341  if ( m_pCuboidFilled[yIdx][uIdx][vIdx] == false )
342  {
343    if( yIdx > 0) 
344      assert ( m_pCuboidFilled[yIdx-1][uIdx][vIdx] );
345
346    for ( Int nVertexIdx=0 ; nVertexIdx<4 ; nVertexIdx++ )
347      m_pCuboid[yIdx][uIdx][vIdx].P[nVertexIdx] = yIdx == 0 ? xGetCuboidVertexPredA( yIdx , uIdx , vIdx , nVertexIdx ): xGetCuboidVertexPredAll( yIdx , uIdx , vIdx , nVertexIdx );
348
349    m_pCuboidFilled[yIdx][uIdx][vIdx] = true ;
350  }
351}
352
353
354Void TCom3DAsymLUT::xCuboidsFilledCheck( Bool bDecode )
355{
356  Int ySize = 1 << ( getCurOctantDepth() + getCurYPartNumLog2() );
357  Int uSize = 1 << getCurOctantDepth();
358  Int vSize = 1 << getCurOctantDepth();
359  for( Int yIdx = 0 ; yIdx < ySize ; yIdx++ )
360  {
361    for( Int uIdx = 0 ; uIdx < uSize ; uIdx++ )
362    {
363      for( Int vIdx = 0 ; vIdx < vSize ; vIdx++ )
364      { 
365        if ( bDecode )
366          xCuboidsFilledCheck( yIdx , uIdx , vIdx );
367
368        assert( m_pCuboidFilled[yIdx][uIdx][vIdx] );
369      }
370    }
371  }
372
373}
374#endif
375
376Bool TCom3DAsymLUT::isRefLayer( UInt uiRefLayerId )
377{
378  Bool bIsRefLayer = false;
379  for( UInt i = 0 ; i < m_vRefLayerId.size() ; i++ )
380  {
381    if( m_vRefLayerId[i] == uiRefLayerId )
382    {
383      bIsRefLayer = true;
384      break;
385    }
386  }
387
388  return( bIsRefLayer );
389}
390
391#if R0164_CGS_LUT_BUGFIX_CHECK
392Void  TCom3DAsymLUT::display( Bool bFilled )
393{
394  Int ySize = 1 << ( getCurOctantDepth() + getCurYPartNumLog2() );
395  Int uSize = 1 << getCurOctantDepth();
396  Int vSize = 1 << getCurOctantDepth();
397  Int vIdx=0;
398
399  printf("\n");
400  printf("3DLut Explicit flag:\n");
401  for( Int uIdx = 0 ; uIdx < uSize ; uIdx++ )
402  {
403    for( Int yIdx = 0 ; yIdx < ySize ; yIdx++ )
404    {
405      printf("%d\t", m_pCuboidExplicit[yIdx][uIdx][vIdx] );
406    }
407    printf("\n");
408  }
409
410  printf("3DLut values (explicit):\n");
411  for( Int uIdx = 0 ; uIdx < uSize ; uIdx++ )
412  {
413    for( Int yIdx = 0 ; yIdx < ySize ; yIdx++ )
414    {
415      if ( m_pCuboidExplicit[yIdx][uIdx][vIdx] )  printf("%d\t", m_pCuboid[yIdx][uIdx][vIdx].P[0].Y );
416      else                                        printf("?\t", m_pCuboid[yIdx][uIdx][vIdx].P[0].Y );
417    }
418    printf("\n");
419  }
420
421  printf("3DLut values (all):\n");
422  for( Int uIdx = 0 ; uIdx < uSize ; uIdx++ )
423  {
424    for( Int yIdx = 0 ; yIdx < ySize ; yIdx++ )
425    {
426      if ( bFilled ) {
427        if ( m_pCuboidFilled[yIdx][uIdx][vIdx] )  printf("%d\t"  , m_pCuboid[yIdx][uIdx][vIdx].P[0].Y );
428        else                                      printf("unk\t" , m_pCuboid[yIdx][uIdx][vIdx].P[0].Y );
429      }
430      else
431        printf("%d\t"  , m_pCuboid[yIdx][uIdx][vIdx].P[0].Y );
432    }
433    printf("\n");
434  }
435
436}
437#endif
438
439#endif
440
Note: See TracBrowser for help on using the repository browser.