source: 3DVCSoftware/trunk/source/Lib/TLibCommon/TComPicYuv.cpp @ 56

Last change on this file since 56 was 56, checked in by hschwarz, 12 years ago

updated trunk (move to HM6.1)

  • Property svn:eol-style set to native
File size: 15.1 KB
Line 
1/* The copyright in this software is being made available under the BSD
2 * License, included below. This software may be subject to other third party
3 * and contributor rights, including patent rights, and no such rights are
4 * granted under this license. 
5 *
6 * Copyright (c) 2010-2012, ITU/ISO/IEC
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are met:
11 *
12 *  * Redistributions of source code must retain the above copyright notice,
13 *    this list of conditions and the following disclaimer.
14 *  * Redistributions in binary form must reproduce the above copyright notice,
15 *    this list of conditions and the following disclaimer in the documentation
16 *    and/or other materials provided with the distribution.
17 *  * Neither the name of the ITU/ISO/IEC nor the names of its contributors may
18 *    be used to endorse or promote products derived from this software without
19 *    specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
31 * THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34/** \file     TComPicYuv.cpp
35    \brief    picture YUV buffer class
36*/
37
38#include <cstdlib>
39#include <assert.h>
40#include <memory.h>
41
42#ifdef __APPLE__
43#include <malloc/malloc.h>
44#else
45#include <malloc.h>
46#endif
47
48#include "TComPicYuv.h"
49
50//! \ingroup TLibCommon
51//! \{
52
53TComPicYuv::TComPicYuv()
54{
55  m_apiPicBufY      = NULL;   // Buffer (including margin)
56  m_apiPicBufU      = NULL;
57  m_apiPicBufV      = NULL;
58 
59  m_piPicOrgY       = NULL;    // m_apiPicBufY + m_iMarginLuma*getStride() + m_iMarginLuma
60  m_piPicOrgU       = NULL;
61  m_piPicOrgV       = NULL;
62 
63  m_bIsBorderExtended = false;
64}
65
66TComPicYuv::~TComPicYuv()
67{
68}
69
70Void TComPicYuv::create( Int iPicWidth, Int iPicHeight, UInt uiMaxCUWidth, UInt uiMaxCUHeight, UInt uiMaxCUDepth )
71{
72  m_iPicWidth       = iPicWidth;
73  m_iPicHeight      = iPicHeight;
74 
75  // --> After config finished!
76  m_iCuWidth        = uiMaxCUWidth;
77  m_iCuHeight       = uiMaxCUHeight;
78
79  m_iNumCuInWidth   = m_iPicWidth / m_iCuWidth;
80  m_iNumCuInWidth  += ( m_iPicWidth % m_iCuWidth ) ? 1 : 0;
81
82  m_uiMaxCuDepth = uiMaxCUDepth;
83
84  m_iBaseUnitWidth  = uiMaxCUWidth  >> uiMaxCUDepth;
85  m_iBaseUnitHeight = uiMaxCUHeight >> uiMaxCUDepth;
86
87  Int numCuInWidth  = m_iPicWidth  / m_iCuWidth  + (m_iPicWidth  % m_iCuWidth  != 0);
88  Int numCuInHeight = m_iPicHeight / m_iCuHeight + (m_iPicHeight % m_iCuHeight != 0);
89 
90  m_iLumaMarginX    = g_uiMaxCUWidth  + PICYUV_PAD; // for 16-byte alignment
91  m_iLumaMarginY    = g_uiMaxCUHeight + PICYUV_PAD;  // margin for 8-tap filter and infinite padding
92 
93  m_iChromaMarginX  = m_iLumaMarginX>>1;
94  m_iChromaMarginY  = m_iLumaMarginY>>1;
95 
96  m_apiPicBufY      = (Pel*)xMalloc( Pel, ( m_iPicWidth       + (m_iLumaMarginX  <<1)) * ( m_iPicHeight       + (m_iLumaMarginY  <<1)));
97  m_apiPicBufU      = (Pel*)xMalloc( Pel, ((m_iPicWidth >> 1) + (m_iChromaMarginX<<1)) * ((m_iPicHeight >> 1) + (m_iChromaMarginY<<1)));
98  m_apiPicBufV      = (Pel*)xMalloc( Pel, ((m_iPicWidth >> 1) + (m_iChromaMarginX<<1)) * ((m_iPicHeight >> 1) + (m_iChromaMarginY<<1)));
99 
100  m_piPicOrgY       = m_apiPicBufY + m_iLumaMarginY   * getStride()  + m_iLumaMarginX;
101  m_piPicOrgU       = m_apiPicBufU + m_iChromaMarginY * getCStride() + m_iChromaMarginX;
102  m_piPicOrgV       = m_apiPicBufV + m_iChromaMarginY * getCStride() + m_iChromaMarginX;
103 
104  m_bIsBorderExtended = false;
105 
106  m_cuOffsetY = new Int[numCuInWidth * numCuInHeight];
107  m_cuOffsetC = new Int[numCuInWidth * numCuInHeight];
108  for (Int cuRow = 0; cuRow < numCuInHeight; cuRow++)
109  {
110    for (Int cuCol = 0; cuCol < numCuInWidth; cuCol++)
111    {
112      m_cuOffsetY[cuRow * numCuInWidth + cuCol] = getStride() * cuRow * m_iCuHeight + cuCol * m_iCuWidth;
113      m_cuOffsetC[cuRow * numCuInWidth + cuCol] = getCStride() * cuRow * (m_iCuHeight / 2) + cuCol * (m_iCuWidth / 2);
114    }
115  }
116 
117  m_buOffsetY = new Int[(size_t)1 << (2 * uiMaxCUDepth)];
118  m_buOffsetC = new Int[(size_t)1 << (2 * uiMaxCUDepth)];
119  for (Int buRow = 0; buRow < (1 << uiMaxCUDepth); buRow++)
120  {
121    for (Int buCol = 0; buCol < (1 << uiMaxCUDepth); buCol++)
122    {
123      m_buOffsetY[(buRow << uiMaxCUDepth) + buCol] = getStride() * buRow * (uiMaxCUHeight >> uiMaxCUDepth) + buCol * (uiMaxCUWidth  >> uiMaxCUDepth);
124      m_buOffsetC[(buRow << uiMaxCUDepth) + buCol] = getCStride() * buRow * (uiMaxCUHeight / 2 >> uiMaxCUDepth) + buCol * (uiMaxCUWidth / 2 >> uiMaxCUDepth);
125    }
126  }
127  return;
128}
129
130Void TComPicYuv::destroy()
131{
132  m_piPicOrgY       = NULL;
133  m_piPicOrgU       = NULL;
134  m_piPicOrgV       = NULL;
135 
136  if( m_apiPicBufY ){ xFree( m_apiPicBufY );    m_apiPicBufY = NULL; }
137  if( m_apiPicBufU ){ xFree( m_apiPicBufU );    m_apiPicBufU = NULL; }
138  if( m_apiPicBufV ){ xFree( m_apiPicBufV );    m_apiPicBufV = NULL; }
139
140  delete[] m_cuOffsetY;
141  delete[] m_cuOffsetC;
142  delete[] m_buOffsetY;
143  delete[] m_buOffsetC;
144}
145
146Void TComPicYuv::createLuma( Int iPicWidth, Int iPicHeight, UInt uiMaxCUWidth, UInt uiMaxCUHeight, UInt uiMaxCUDepth )
147{
148  m_iPicWidth       = iPicWidth;
149  m_iPicHeight      = iPicHeight;
150 
151  // --> After config finished!
152  m_iCuWidth        = uiMaxCUWidth;
153  m_iCuHeight       = uiMaxCUHeight;
154  m_uiMaxCuDepth    = uiMaxCUDepth;
155
156  m_iNumCuInWidth   = m_iPicWidth / m_iCuWidth;
157  m_iNumCuInWidth  += ( m_iPicWidth % m_iCuWidth ) ? 1 : 0;
158
159  m_iBaseUnitWidth  = uiMaxCUWidth  >> uiMaxCUDepth;
160  m_iBaseUnitHeight = uiMaxCUHeight >> uiMaxCUDepth;
161
162 
163  Int numCuInWidth  = m_iPicWidth  / m_iCuWidth  + (m_iPicWidth  % m_iCuWidth  != 0);
164  Int numCuInHeight = m_iPicHeight / m_iCuHeight + (m_iPicHeight % m_iCuHeight != 0);
165 
166  m_iLumaMarginX    = g_uiMaxCUWidth  + PICYUV_PAD; // for 16-byte alignment
167  m_iLumaMarginY    = g_uiMaxCUHeight + PICYUV_PAD;  // margin for 8-tap filter and infinite padding
168 
169  m_apiPicBufY      = (Pel*)xMalloc( Pel, ( m_iPicWidth       + (m_iLumaMarginX  <<1)) * ( m_iPicHeight       + (m_iLumaMarginY  <<1)));
170  m_piPicOrgY       = m_apiPicBufY + m_iLumaMarginY   * getStride()  + m_iLumaMarginX;
171 
172  m_cuOffsetY = new Int[numCuInWidth * numCuInHeight];
173  m_cuOffsetC = NULL;
174  for (Int cuRow = 0; cuRow < numCuInHeight; cuRow++)
175  {
176    for (Int cuCol = 0; cuCol < numCuInWidth; cuCol++)
177    {
178      m_cuOffsetY[cuRow * numCuInWidth + cuCol] = getStride() * cuRow * m_iCuHeight + cuCol * m_iCuWidth;
179    }
180  }
181 
182  m_buOffsetY = new Int[(size_t)1 << (2 * uiMaxCUDepth)];
183  m_buOffsetC = NULL;
184  for (Int buRow = 0; buRow < (1 << uiMaxCUDepth); buRow++)
185  {
186    for (Int buCol = 0; buCol < (1 << uiMaxCUDepth); buCol++)
187    {
188      m_buOffsetY[(buRow << uiMaxCUDepth) + buCol] = getStride() * buRow * (uiMaxCUHeight >> uiMaxCUDepth) + buCol * (uiMaxCUWidth  >> uiMaxCUDepth);
189    }
190  }
191  return;
192}
193
194Void TComPicYuv::destroyLuma()
195{
196  m_piPicOrgY       = NULL;
197 
198  if( m_apiPicBufY ){ xFree( m_apiPicBufY );    m_apiPicBufY = NULL; }
199 
200  delete[] m_cuOffsetY;
201  delete[] m_buOffsetY;
202}
203
204Void  TComPicYuv::copyToPic (TComPicYuv*  pcPicYuvDst)
205{
206  assert( m_iPicWidth  == pcPicYuvDst->getWidth()  );
207  assert( m_iPicHeight == pcPicYuvDst->getHeight() );
208 
209  ::memcpy ( pcPicYuvDst->getBufY(), m_apiPicBufY, sizeof (Pel) * ( m_iPicWidth       + (m_iLumaMarginX   << 1)) * ( m_iPicHeight       + (m_iLumaMarginY   << 1)) );
210  ::memcpy ( pcPicYuvDst->getBufU(), m_apiPicBufU, sizeof (Pel) * ((m_iPicWidth >> 1) + (m_iChromaMarginX << 1)) * ((m_iPicHeight >> 1) + (m_iChromaMarginY << 1)) );
211  ::memcpy ( pcPicYuvDst->getBufV(), m_apiPicBufV, sizeof (Pel) * ((m_iPicWidth >> 1) + (m_iChromaMarginX << 1)) * ((m_iPicHeight >> 1) + (m_iChromaMarginY << 1)) );
212  return;
213}
214
215Void  TComPicYuv::copyToPicLuma (TComPicYuv*  pcPicYuvDst)
216{
217  assert( m_iPicWidth  == pcPicYuvDst->getWidth()  );
218  assert( m_iPicHeight == pcPicYuvDst->getHeight() );
219 
220  ::memcpy ( pcPicYuvDst->getBufY(), m_apiPicBufY, sizeof (Pel) * ( m_iPicWidth       + (m_iLumaMarginX   << 1)) * ( m_iPicHeight       + (m_iLumaMarginY   << 1)) );
221  return;
222}
223
224Void  TComPicYuv::copyToPicCb (TComPicYuv*  pcPicYuvDst)
225{
226  assert( m_iPicWidth  == pcPicYuvDst->getWidth()  );
227  assert( m_iPicHeight == pcPicYuvDst->getHeight() );
228 
229  ::memcpy ( pcPicYuvDst->getBufU(), m_apiPicBufU, sizeof (Pel) * ((m_iPicWidth >> 1) + (m_iChromaMarginX << 1)) * ((m_iPicHeight >> 1) + (m_iChromaMarginY << 1)) );
230  return;
231}
232
233Void  TComPicYuv::copyToPicCr (TComPicYuv*  pcPicYuvDst)
234{
235  assert( m_iPicWidth  == pcPicYuvDst->getWidth()  );
236  assert( m_iPicHeight == pcPicYuvDst->getHeight() );
237 
238  ::memcpy ( pcPicYuvDst->getBufV(), m_apiPicBufV, sizeof (Pel) * ((m_iPicWidth >> 1) + (m_iChromaMarginX << 1)) * ((m_iPicHeight >> 1) + (m_iChromaMarginY << 1)) );
239  return;
240}
241
242
243Void TComPicYuv::getLumaMinMax( Int *pMin, Int *pMax )
244{
245  Pel*  piY   = getLumaAddr();
246  Int   iMin  = (1<<(g_uiBitDepth))-1;
247  Int   iMax  = 0;
248  Int   x, y;
249 
250  for ( y = 0; y < m_iPicHeight; y++ )
251  {
252    for ( x = 0; x < m_iPicWidth; x++ )
253    {
254      if ( piY[x] < iMin ) iMin = piY[x];
255      if ( piY[x] > iMax ) iMax = piY[x];
256    }
257    piY += getStride();
258  }
259 
260  *pMin = iMin;
261  *pMax = iMax;
262}
263
264Void TComPicYuv::extendPicBorder ()
265{
266  if ( m_bIsBorderExtended ) return;
267 
268  xExtendPicCompBorder( getLumaAddr(), getStride(),  getWidth(),      getHeight(),      m_iLumaMarginX,   m_iLumaMarginY   );
269  xExtendPicCompBorder( getCbAddr()  , getCStride(), getWidth() >> 1, getHeight() >> 1, m_iChromaMarginX, m_iChromaMarginY );
270  xExtendPicCompBorder( getCrAddr()  , getCStride(), getWidth() >> 1, getHeight() >> 1, m_iChromaMarginX, m_iChromaMarginY );
271 
272  m_bIsBorderExtended = true;
273}
274
275Void TComPicYuv::xExtendPicCompBorder  (Pel* piTxt, Int iStride, Int iWidth, Int iHeight, Int iMarginX, Int iMarginY)
276{
277  Int   x, y;
278  Pel*  pi;
279 
280  pi = piTxt;
281  for ( y = 0; y < iHeight; y++)
282  {
283    for ( x = 0; x < iMarginX; x++ )
284    {
285      pi[ -iMarginX + x ] = pi[0];
286      pi[    iWidth + x ] = pi[iWidth-1];
287    }
288    pi += iStride;
289  }
290 
291  pi -= (iStride + iMarginX);
292  for ( y = 0; y < iMarginY; y++ )
293  {
294    ::memcpy( pi + (y+1)*iStride, pi, sizeof(Pel)*(iWidth + (iMarginX<<1)) );
295  }
296 
297  pi -= ((iHeight-1) * iStride);
298  for ( y = 0; y < iMarginY; y++ )
299  {
300    ::memcpy( pi - (y+1)*iStride, pi, sizeof(Pel)*(iWidth + (iMarginX<<1)) );
301  }
302}
303
304
305Void TComPicYuv::dump (char* pFileName, Bool bAdd)
306{
307  FILE* pFile;
308  if (!bAdd)
309  {
310    pFile = fopen (pFileName, "wb");
311  }
312  else
313  {
314    pFile = fopen (pFileName, "ab");
315  }
316 
317  Int     shift = g_uiBitIncrement;
318  Int     offset = (shift>0)?(1<<(shift-1)):0;
319 
320  Int   x, y;
321  UChar uc;
322 
323  Pel*  piY   = getLumaAddr();
324  Pel*  piCb  = getCbAddr();
325  Pel*  piCr  = getCrAddr();
326 
327  Pel  iMax = ((1<<(g_uiBitDepth))-1);
328 
329  for ( y = 0; y < m_iPicHeight; y++ )
330  {
331    for ( x = 0; x < m_iPicWidth; x++ )
332    {
333      uc = (UChar)Clip3<Pel>(0, iMax, (piY[x]+offset)>>shift);
334     
335      fwrite( &uc, sizeof(UChar), 1, pFile );
336    }
337    piY += getStride();
338  }
339 
340  for ( y = 0; y < m_iPicHeight >> 1; y++ )
341  {
342    for ( x = 0; x < m_iPicWidth >> 1; x++ )
343    {
344      uc = (UChar)Clip3<Pel>(0, iMax, (piCb[x]+offset)>>shift);
345      fwrite( &uc, sizeof(UChar), 1, pFile );
346    }
347    piCb += getCStride();
348  }
349 
350  for ( y = 0; y < m_iPicHeight >> 1; y++ )
351  {
352    for ( x = 0; x < m_iPicWidth >> 1; x++ )
353    {
354      uc = (UChar)Clip3<Pel>(0, iMax, (piCr[x]+offset)>>shift);
355      fwrite( &uc, sizeof(UChar), 1, pFile );
356    }
357    piCr += getCStride();
358  }
359 
360  fclose(pFile);
361}
362
363#if FIXED_ROUNDING_FRAME_MEMORY
364Void TComPicYuv::xFixedRoundingPic()
365{
366  Int   x, y;
367  Pel*  pRec    = getLumaAddr();
368  Int   iStride = getStride();
369  Int   iWidth  = getWidth();
370  Int   iHeight = getHeight();
371#if FULL_NBIT
372  Int   iOffset  = ((g_uiBitDepth-8)>0)?(1<<(g_uiBitDepth-8-1)):0;
373  Int   iMask   = (~0<<(g_uiBitDepth-8));
374  Int   iMaxBdi = g_uiBASE_MAX<<(g_uiBitDepth-8);
375#else
376  Int   iOffset  = (g_uiBitIncrement>0)?(1<<(g_uiBitIncrement-1)):0;
377  Int   iMask   = (~0<<g_uiBitIncrement);
378  Int   iMaxBdi = g_uiBASE_MAX<<g_uiBitIncrement;
379#endif
380
381  for( y = 0; y < iHeight; y++ )
382  {
383    for( x = 0; x < iWidth; x++ )
384    {
385#if IBDI_NOCLIP_RANGE
386      pRec[x] = ( pRec[x] + iOffset ) & iMask;
387#else
388      pRec[x] = ( pRec[x]+iOffset>iMaxBdi)? iMaxBdi : ((pRec[x]+iOffset) & iMask);
389#endif
390    }
391    pRec += iStride;
392  }
393
394  iHeight >>= 1;
395  iWidth  >>= 1;
396  iStride >>= 1;
397  pRec  = getCbAddr();
398
399  for( y = 0; y < iHeight; y++ )
400  {
401    for( x = 0; x < iWidth; x++ )
402    {
403#if IBDI_NOCLIP_RANGE
404      pRec[x] = ( pRec[x] + iOffset ) & iMask;
405#else
406      pRec[x] = ( pRec[x]+iOffset>iMaxBdi)? iMaxBdi : ((pRec[x]+iOffset) & iMask);
407#endif
408    }
409    pRec += iStride;
410  }
411
412  pRec  = getCrAddr();
413
414  for( y = 0; y < iHeight; y++ )
415  {
416    for( x = 0; x < iWidth; x++ )
417    {
418#if IBDI_NOCLIP_RANGE
419      pRec[x] = ( pRec[x] + iOffset ) & iMask;
420#else
421      pRec[x] = ( pRec[x]+iOffset>iMaxBdi)? iMaxBdi : ((pRec[x]+iOffset) & iMask);
422#endif
423    }
424    pRec += iStride;
425  }
426}
427#endif
428
429Void
430TComPicYuv::getTopLeftSamplePos( Int iCuAddr, Int iAbsZorderIdx, Int& riX, Int& riY )
431{
432  Int iRastPartIdx    = g_auiZscanToRaster[iAbsZorderIdx];
433  Int iCuSizeInBases  = m_iCuWidth   / m_iBaseUnitWidth;
434  Int iCuX            = iCuAddr      % m_iNumCuInWidth;
435  Int iCuY            = iCuAddr      / m_iNumCuInWidth;
436  Int iBaseX          = iRastPartIdx % iCuSizeInBases;
437  Int iBaseY          = iRastPartIdx / iCuSizeInBases;
438  riX                 = iCuX * m_iCuWidth  + iBaseX * m_iBaseUnitWidth;
439  riY                 = iCuY * m_iCuHeight + iBaseY * m_iBaseUnitHeight; 
440}
441
442Void
443TComPicYuv::getCUAddrAndPartIdx( Int iX, Int iY, Int& riCuAddr, Int& riAbsZorderIdx )
444{
445  Int iCuX            = iX / m_iCuWidth;
446  Int iCuY            = iY / m_iCuHeight;
447  Int iBaseX          = ( iX - iCuX * m_iCuWidth  ) / m_iBaseUnitWidth;
448  Int iBaseY          = ( iY - iCuY * m_iCuHeight ) / m_iBaseUnitHeight;
449  Int iCuSizeInBases  = m_iCuWidth                  / m_iBaseUnitWidth;
450  riCuAddr            = iCuY   * m_iNumCuInWidth + iCuX;
451  Int iRastPartIdx    = iBaseY * iCuSizeInBases  + iBaseX;
452  riAbsZorderIdx      = g_auiRasterToZscan[ iRastPartIdx ];
453}
454
455Void TComPicYuv::setLumaTo( Pel pVal )
456{
457  xSetPels( getLumaAddr(), getStride(), getWidth(), getHeight() >> 1, pVal );
458}
459
460Void TComPicYuv::setChromaTo( Pel pVal )
461{
462  xSetPels( getCbAddr(), getCStride(), getWidth() >> 1, getHeight() >> 1, pVal ); 
463  xSetPels( getCrAddr(), getCStride(), getWidth() >> 1, getHeight() >> 1, pVal );
464}
465
466Void TComPicYuv::xSetPels( Pel* piPelSource , Int iSourceStride, Int iWidth, Int iHeight, Pel iVal )
467{
468  for (Int iYPos = 0; iYPos < iHeight; iYPos++)
469  {
470    for (Int iXPos = 0; iXPos < iWidth; iXPos++)
471    {
472      piPelSource[iXPos] = iVal; 
473    }
474    piPelSource += iSourceStride; 
475  }
476}
477
478//! \}
Note: See TracBrowser for help on using the repository browser.