Coverage Report

Created: 2026-07-30 06:27

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/vvenc/source/Lib/CommonLib/Buffer.cpp
Line
Count
Source
1
/* -----------------------------------------------------------------------------
2
The copyright in this software is being made available under the Clear BSD
3
License, included below. No patent rights, trademark rights and/or 
4
other Intellectual Property Rights other than the copyrights concerning 
5
the Software are granted under this license.
6
7
The Clear BSD License
8
9
Copyright (c) 2019-2026, Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. & The VVenC Authors.
10
All rights reserved.
11
12
Redistribution and use in source and binary forms, with or without modification,
13
are permitted (subject to the limitations in the disclaimer below) provided that
14
the following conditions are met:
15
16
     * Redistributions of source code must retain the above copyright notice,
17
     this list of conditions and the following disclaimer.
18
19
     * Redistributions in binary form must reproduce the above copyright
20
     notice, this list of conditions and the following disclaimer in the
21
     documentation and/or other materials provided with the distribution.
22
23
     * Neither the name of the copyright holder nor the names of its
24
     contributors may be used to endorse or promote products derived from this
25
     software without specific prior written permission.
26
27
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
28
THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
29
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
31
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
32
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
33
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
34
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
35
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
36
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38
POSSIBILITY OF SUCH DAMAGE.
39
40
41
------------------------------------------------------------------------------------------- */
42
43
44
/** \file     Buffer.cpp
45
 *  \brief    Low-overhead class describing 2D memory layout
46
 */
47
48
#define DONT_UNDEF_SIZE_AWARE_PER_EL_OP
49
50
// unit needs to come first due to a forward declaration
51
#include "Unit.h"
52
#include "Slice.h"
53
#include "InterpolationFilter.h"
54
55
//! \ingroup CommonLib
56
//! \{
57
58
namespace vvenc {
59
60
void weightCiipCore( Pel* res, const Pel* src, const int numSamples, int numIntra )
61
0
{
62
0
  if( numIntra == 1 )
63
0
  {
64
0
    for (int n = 0; n < numSamples; n+=2)
65
0
    {
66
0
      res[n  ] = (res[n  ] + src[n  ] + 1) >> 1;
67
0
      res[n+1] = (res[n+1] + src[n+1] + 1) >> 1;
68
0
    }
69
0
  }
70
0
  else
71
0
  {
72
0
    const Pel* scale   = numIntra ? src : res;
73
0
    const Pel* unscale = numIntra ? res : src;
74
75
0
    for (int n = 0; n < numSamples; n+=2)
76
0
    {
77
0
      res[n  ] = (unscale[n  ] + 3*scale[n  ] + 2) >> 2;
78
0
      res[n+1] = (unscale[n+1] + 3*scale[n+1] + 2) >> 2;
79
0
    }
80
0
  }
81
0
}
82
83
template< unsigned inputSize, unsigned outputSize >
84
void mipMatrixMulCore( Pel* res, const Pel* input, const uint8_t* weight, const int maxVal, const int inputOffset, bool transpose )
85
257k
{
86
257k
  Pel buffer[ outputSize*outputSize];
87
88
257k
  int sum = 0;
89
2.32M
  for( int i = 0; i < inputSize; i++ )
90
2.06M
  {
91
2.06M
    sum += input[i];
92
2.06M
  }
93
257k
  const int offset = (1 << (MIP_SHIFT_MATRIX - 1)) - MIP_OFFSET_MATRIX * sum + (inputOffset << MIP_SHIFT_MATRIX);
94
257k
  CHECK( inputSize != 4 * (inputSize >> 2), "Error, input size not divisible by four" );
95
96
257k
  Pel* mat = transpose ? buffer : res;
97
257k
  unsigned posRes = 0;
98
16.4M
  for( unsigned n = 0; n < outputSize*outputSize; n++ )
99
16.1M
  {
100
16.1M
    int tmp0 = input[0] * weight[0];
101
16.1M
    int tmp1 = input[1] * weight[1];
102
16.1M
    int tmp2 = input[2] * weight[2];
103
16.1M
    int tmp3 = input[3] * weight[3];
104
16.1M
    if( 8 == inputSize )
105
16.1M
    {
106
16.1M
      tmp0 += input[4] * weight[4];
107
16.1M
      tmp1 += input[5] * weight[5];
108
16.1M
      tmp2 += input[6] * weight[6];
109
16.1M
      tmp3 += input[7] * weight[7];
110
16.1M
    }
111
16.1M
    mat[posRes++] = Clip3<int>( 0, maxVal, ((tmp0 + tmp1 + tmp2 + tmp3 + offset) >> MIP_SHIFT_MATRIX) );
112
113
16.1M
    weight += inputSize;
114
16.1M
  }
115
116
257k
  if( transpose )
117
117k
  {
118
1.04M
    for( int j = 0; j < outputSize; j++ )
119
924k
    {
120
8.26M
      for( int i = 0; i < outputSize; i++ )
121
7.34M
      {
122
7.34M
        res[j * outputSize + i] = buffer[i * outputSize + j];
123
7.34M
      }
124
924k
    }
125
117k
  }
126
257k
}
Unexecuted instantiation: void vvenc::mipMatrixMulCore<4u, 4u>(short*, short const*, unsigned char const*, int, int, bool)
void vvenc::mipMatrixMulCore<8u, 4u>(short*, short const*, unsigned char const*, int, int, bool)
Line
Count
Source
85
6.72k
{
86
6.72k
  Pel buffer[ outputSize*outputSize];
87
88
6.72k
  int sum = 0;
89
60.4k
  for( int i = 0; i < inputSize; i++ )
90
53.7k
  {
91
53.7k
    sum += input[i];
92
53.7k
  }
93
6.72k
  const int offset = (1 << (MIP_SHIFT_MATRIX - 1)) - MIP_OFFSET_MATRIX * sum + (inputOffset << MIP_SHIFT_MATRIX);
94
6.72k
  CHECK( inputSize != 4 * (inputSize >> 2), "Error, input size not divisible by four" );
95
96
6.72k
  Pel* mat = transpose ? buffer : res;
97
6.72k
  unsigned posRes = 0;
98
114k
  for( unsigned n = 0; n < outputSize*outputSize; n++ )
99
107k
  {
100
107k
    int tmp0 = input[0] * weight[0];
101
107k
    int tmp1 = input[1] * weight[1];
102
107k
    int tmp2 = input[2] * weight[2];
103
107k
    int tmp3 = input[3] * weight[3];
104
107k
    if( 8 == inputSize )
105
107k
    {
106
107k
      tmp0 += input[4] * weight[4];
107
107k
      tmp1 += input[5] * weight[5];
108
107k
      tmp2 += input[6] * weight[6];
109
107k
      tmp3 += input[7] * weight[7];
110
107k
    }
111
107k
    mat[posRes++] = Clip3<int>( 0, maxVal, ((tmp0 + tmp1 + tmp2 + tmp3 + offset) >> MIP_SHIFT_MATRIX) );
112
113
107k
    weight += inputSize;
114
107k
  }
115
116
6.72k
  if( transpose )
117
3.36k
  {
118
16.8k
    for( int j = 0; j < outputSize; j++ )
119
13.4k
    {
120
67.2k
      for( int i = 0; i < outputSize; i++ )
121
53.7k
      {
122
53.7k
        res[j * outputSize + i] = buffer[i * outputSize + j];
123
53.7k
      }
124
13.4k
    }
125
3.36k
  }
126
6.72k
}
void vvenc::mipMatrixMulCore<8u, 8u>(short*, short const*, unsigned char const*, int, int, bool)
Line
Count
Source
85
251k
{
86
251k
  Pel buffer[ outputSize*outputSize];
87
88
251k
  int sum = 0;
89
2.26M
  for( int i = 0; i < inputSize; i++ )
90
2.00M
  {
91
2.00M
    sum += input[i];
92
2.00M
  }
93
251k
  const int offset = (1 << (MIP_SHIFT_MATRIX - 1)) - MIP_OFFSET_MATRIX * sum + (inputOffset << MIP_SHIFT_MATRIX);
94
251k
  CHECK( inputSize != 4 * (inputSize >> 2), "Error, input size not divisible by four" );
95
96
251k
  Pel* mat = transpose ? buffer : res;
97
251k
  unsigned posRes = 0;
98
16.3M
  for( unsigned n = 0; n < outputSize*outputSize; n++ )
99
16.0M
  {
100
16.0M
    int tmp0 = input[0] * weight[0];
101
16.0M
    int tmp1 = input[1] * weight[1];
102
16.0M
    int tmp2 = input[2] * weight[2];
103
16.0M
    int tmp3 = input[3] * weight[3];
104
16.0M
    if( 8 == inputSize )
105
16.0M
    {
106
16.0M
      tmp0 += input[4] * weight[4];
107
16.0M
      tmp1 += input[5] * weight[5];
108
16.0M
      tmp2 += input[6] * weight[6];
109
16.0M
      tmp3 += input[7] * weight[7];
110
16.0M
    }
111
16.0M
    mat[posRes++] = Clip3<int>( 0, maxVal, ((tmp0 + tmp1 + tmp2 + tmp3 + offset) >> MIP_SHIFT_MATRIX) );
112
113
16.0M
    weight += inputSize;
114
16.0M
  }
115
116
251k
  if( transpose )
117
113k
  {
118
1.02M
    for( int j = 0; j < outputSize; j++ )
119
911k
    {
120
8.19M
      for( int i = 0; i < outputSize; i++ )
121
7.28M
      {
122
7.28M
        res[j * outputSize + i] = buffer[i * outputSize + j];
123
7.28M
      }
124
911k
    }
125
113k
  }
126
251k
}
127
128
template< typename T >
129
void addAvgCore( const T* src1, int src1Stride, const T* src2, int src2Stride, T* dest, int dstStride, int width, int height, unsigned rshift, int offset, const ClpRng& clpRng )
130
0
{
131
0
#define ADD_AVG_CORE_OP( ADDR ) dest[ADDR] = ClipPel( rightShiftU( ( src1[ADDR] + src2[ADDR] + offset ), rshift ), clpRng )
132
0
#define ADD_AVG_CORE_INC    \
133
0
  src1 += src1Stride;       \
134
0
  src2 += src2Stride;       \
135
0
  dest +=  dstStride;       \
136
0
137
0
  SIZE_AWARE_PER_EL_OP( ADD_AVG_CORE_OP, ADD_AVG_CORE_INC );
138
139
0
#undef ADD_AVG_CORE_OP
140
0
#undef ADD_AVG_CORE_INC
141
0
}
142
143
template<typename T>
144
void addWeightedAvgCore( const T* src1, int src1Stride, const T* src2, int src2Stride, T* dest, int destStride, int width, int height, unsigned rshift, int offset, int w0, int w1, const ClpRng& clpRng )
145
0
{
146
0
#define ADD_WGHT_AVG_OP( ADDR ) dest[ADDR] = ClipPel( rightShiftU( ( src1[ADDR]*w0 + src2[ADDR]*w1 + offset ), rshift ), clpRng )
147
0
#define ADD_WGHT_AVG_INC     \
148
0
    src1 += src1Stride; \
149
0
    src2 += src2Stride; \
150
0
    dest += destStride; \
151
0
152
0
  SIZE_AWARE_PER_EL_OP( ADD_WGHT_AVG_OP, ADD_WGHT_AVG_INC );
153
154
0
#undef ADD_WGHT_AVG_OP
155
0
#undef ADD_WGHT_AVG_INC
156
0
}
157
158
template<typename T>
159
void subsCore( const T* src0, int src0Stride, const T* src1, int src1Stride, T* dest, int destStride, int width, int height )
160
801k
{
161
801k
#define SUBS_INC                \
162
801k
  dest += destStride;  \
163
801k
  src0 += src0Stride;  \
164
801k
  src1 += src1Stride;  \
165
801k
166
369M
#define SUBS_OP( ADDR ) dest[ADDR] = src0[ADDR] - src1[ADDR]
167
168
369M
  SIZE_AWARE_PER_EL_OP( SUBS_OP, SUBS_INC );
169
170
801k
#undef SUBS_OP
171
801k
#undef SUBS_INC
172
801k
}
173
174
void removeHighFreq(int16_t* dst, int dstStride, const int16_t* src, int srcStride, int width, int height)
175
0
{
176
0
#define REM_HF_INC  \
177
0
 src += srcStride; \
178
0
 dst += dstStride; \
179
0
180
0
#define REM_HF_OP( ADDR )      dst[ADDR] =             2 * dst[ADDR] - src[ADDR]
181
182
0
 SIZE_AWARE_PER_EL_OP(REM_HF_OP, REM_HF_INC);
183
184
0
#undef REM_HF_INC
185
0
#undef REM_HF_OP
186
0
#undef REM_HF_OP_CLIP
187
0
}
188
189
template<typename T>
190
void reconstructCore( const T* src1, int src1Stride, const T* src2, int src2Stride, T* dest, int dstStride, int width, int height, const ClpRng& clpRng )
191
8.98k
{
192
3.75M
#define RECO_CORE_OP( ADDR ) dest[ADDR] = ClipPel( src1[ADDR] + src2[ADDR], clpRng )
193
8.98k
#define RECO_CORE_INC     \
194
8.98k
  src1 += src1Stride;     \
195
8.98k
  src2 += src2Stride;     \
196
8.98k
  dest +=  dstStride;     \
197
8.98k
198
3.75M
  SIZE_AWARE_PER_EL_OP( RECO_CORE_OP, RECO_CORE_INC );
199
200
8.98k
#undef RECO_CORE_OP
201
8.98k
#undef RECO_CORE_INC
202
8.98k
}
203
204
template<typename T>
205
void recoCore( const T* src1, const T* src2, T* dest, int numSamples, const ClpRng& clpRng )
206
2.25M
{
207
336M
  for( int n = 0; n < numSamples; n+=2)
208
334M
  {
209
334M
    dest[n]   = ClipPel( src1[n]   + src2[n], clpRng );
210
334M
    dest[n+1] = ClipPel( src1[n+1] + src2[n+1], clpRng );
211
334M
  }
212
2.25M
}
213
214
template<typename T>
215
void copyClipCore( const T* src, Pel* dst, int numSamples, const ClpRng& clpRng )
216
0
{
217
0
  for( int n = 0; n < numSamples; n+=2)
218
0
  {
219
0
    dst[n]   = ClipPel( src[n]   , clpRng );
220
0
    dst[n+1] = ClipPel( src[n+1] , clpRng );
221
0
  }
222
0
}
223
224
template< typename T >
225
void addAvgCore( const T* src1, const T* src2, T* dest, int numSamples, unsigned rshift, int offset, const ClpRng& clpRng )
226
0
{
227
0
  for( int n = 0; n < numSamples; n+=2)
228
0
  {
229
0
    dest[n]   = ClipPel( rightShiftU( ( src1[n]   + src2[n]   + offset ), rshift ), clpRng );
230
0
    dest[n+1] = ClipPel( rightShiftU( ( src1[n+1] + src2[n+1] + offset ), rshift ), clpRng );
231
0
  }
232
0
}
233
234
template< typename T >
235
void roundGeoCore( const T* src, T* dest, const int numSamples, unsigned rshift, int offset, const ClpRng &clpRng)
236
0
{
237
0
  for( int i = 0; i < numSamples; i+=2)
238
0
  {
239
0
    dest[i]   = ClipPel(rightShiftU(src[i  ] + offset, rshift), clpRng);
240
0
    dest[i+1] = ClipPel(rightShiftU(src[i+1] + offset, rshift), clpRng);
241
0
  }
242
0
}
243
244
template<typename T>
245
void linTfCore( const T* src, int srcStride, Pel* dst, int dstStride, int width, int height, int scale, unsigned shift, int offset, const ClpRng& clpRng, bool bClip )
246
205k
{
247
205k
#define LINTF_CORE_INC  \
248
205k
  src += srcStride;     \
249
205k
  dst += dstStride;     \
250
205k
251
205k
  if( bClip )
252
205k
  {
253
40.9M
#define LINTF_CORE_OP( ADDR ) dst[ADDR] = ( Pel ) ClipPel( rightShiftU( scale * src[ADDR], shift ) + offset, clpRng )
254
255
40.9M
  SIZE_AWARE_PER_EL_OP( LINTF_CORE_OP, LINTF_CORE_INC );
256
257
205k
#undef LINTF_CORE_OP
258
205k
  }
259
0
  else
260
0
  {
261
0
#define LINTF_CORE_OP( ADDR ) dst[ADDR] = ( Pel ) ( rightShiftU( scale * src[ADDR], shift ) + offset )
262
263
0
  SIZE_AWARE_PER_EL_OP( LINTF_CORE_OP, LINTF_CORE_INC );
264
265
0
#undef LINTF_CORE_OP
266
0
  }
267
205k
#undef LINTF_CORE_INC
268
205k
}
269
270
template<typename T, int N>
271
void transposeNxNCore( const Pel* src, int srcStride, Pel* dst, int dstStride )
272
7.13M
{
273
62.6M
  for( int i = 0; i < N; i++ )
274
55.5M
  {
275
493M
    for( int j = 0; j < N; j++ )
276
437M
    {
277
437M
      dst[j * dstStride] = src[j];
278
437M
    }
279
280
55.5M
    dst++;
281
55.5M
    src += srcStride;
282
55.5M
  }
283
7.13M
}
void vvenc::transposeNxNCore<short, 4>(short const*, int, short*, int)
Line
Count
Source
272
398k
{
273
1.99M
  for( int i = 0; i < N; i++ )
274
1.59M
  {
275
7.96M
    for( int j = 0; j < N; j++ )
276
6.36M
    {
277
6.36M
      dst[j * dstStride] = src[j];
278
6.36M
    }
279
280
1.59M
    dst++;
281
1.59M
    src += srcStride;
282
1.59M
  }
283
398k
}
void vvenc::transposeNxNCore<short, 8>(short const*, int, short*, int)
Line
Count
Source
272
6.74M
{
273
60.6M
  for( int i = 0; i < N; i++ )
274
53.9M
  {
275
485M
    for( int j = 0; j < N; j++ )
276
431M
    {
277
431M
      dst[j * dstStride] = src[j];
278
431M
    }
279
280
53.9M
    dst++;
281
53.9M
    src += srcStride;
282
53.9M
  }
283
6.74M
}
284
285
template<typename T>
286
void copyClipCore( const T* src, int srcStride, Pel* dst, int dstStride, int width, int height, const ClpRng& clpRng )
287
0
{
288
0
#define RECO_OP( ADDR ) dst[ADDR] = ClipPel( src[ADDR], clpRng )
289
0
#define RECO_INC      \
290
0
    src += srcStride; \
291
0
    dst += dstStride; \
292
0
293
0
  SIZE_AWARE_PER_EL_OP( RECO_OP, RECO_INC );
294
295
0
#undef RECO_OP
296
0
#undef RECO_INC
297
0
}
298
299
void copyBufferCore( const char* src, int srcStride, char* dst, int dstStride, int numBytes, int height)
300
8.57M
{
301
142M
  for( int i = 0; i < height; i++, src += srcStride, dst += dstStride )
302
134M
  {
303
134M
    memcpy( dst, src, numBytes );
304
134M
  }
305
8.57M
}
306
307
void applyLutCore( const Pel* src, const ptrdiff_t srcStride, Pel* dst, const ptrdiff_t dstStride, int width, int height, const Pel* lut )
308
0
{
309
0
#define RSP_SGNL_OP( ADDR ) dst[ADDR] = lut[src[ADDR]]
310
0
#define RSP_SGNL_INC        src      += srcStride; dst += dstStride;
311
312
0
  SIZE_AWARE_PER_EL_OP( RSP_SGNL_OP, RSP_SGNL_INC )
313
314
0
#undef RSP_SGNL_OP
315
0
#undef RSP_SGNL_INC
316
0
}
317
318
void fillMapPtr_Core( void** ptrMap, const ptrdiff_t mapStride, int width, int height, void* val )
319
444k
{
320
444k
  if( width == mapStride )
321
291k
  {
322
291k
    std::fill_n( ptrMap, width * height, val );
323
291k
  }
324
152k
  else
325
152k
  {
326
1.40M
    while( height-- )
327
1.25M
    {
328
1.25M
      std::fill_n( ptrMap, width, val );
329
1.25M
      ptrMap += mapStride;
330
1.25M
    }
331
152k
  }
332
444k
}
333
334
uint64_t AvgHighPassCore( const int width, const int height, const Pel* pSrc, const int iSrcStride)
335
10.8k
{
336
10.8k
  uint64_t saAct = 0;
337
878k
  for (int y = 1; y < height - 1; y++)
338
867k
  {
339
81.5M
    for (int x = 1; x < width - 1; x++) // center cols
340
80.7M
    {
341
80.7M
      const int s = 12 * (int) pSrc[x  ] - 2 * ((int) pSrc[x-1] + (int) pSrc[x+1] + (int) pSrc[x  -iSrcStride] + (int) pSrc[x  +iSrcStride])
342
80.7M
                             - ((int) pSrc[x-1-iSrcStride] + (int) pSrc[x+1-iSrcStride] + (int) pSrc[x-1+iSrcStride] + (int) pSrc[x+1+iSrcStride]);
343
80.7M
      saAct += abs (s);
344
80.7M
    }
345
867k
    pSrc += iSrcStride;
346
867k
  }
347
10.8k
  return saAct;
348
10.8k
}
349
350
uint64_t HDHighPassCore  (const int width, const int height,const Pel*  pSrc,const Pel* pSM1,const int iSrcStride,const int iSM1Stride)
351
0
{
352
0
  uint64_t taAct = 0;
353
0
  for (int y = 1; y < height - 1; y++)
354
0
  {
355
0
    for (int x = 1; x < width - 1; x++)  // cnt cols
356
0
    {
357
0
      const int t = (int) pSrc[x] - (int) pSM1[x];
358
0
      taAct += (1 + 3 * abs (t)) >> 1;
359
0
    }
360
0
    pSrc += iSrcStride;
361
0
    pSM1 += iSM1Stride;
362
0
  }
363
0
  return taAct;
364
0
}
365
366
uint64_t  HDHighPass2Core  (const int width, const int height,const Pel*  pSrc,const Pel* pSM1,const Pel* pSM2,const int iSrcStride,const int iSM1Stride,const int iSM2Stride)
367
0
{
368
0
  uint64_t taAct = 0;
369
0
  for (int y = 1; y < height - 1; y++)
370
0
  {
371
0
    for (int x = 1; x < width - 1; x++)  // cnt cols
372
0
    {
373
0
      const int t = (int) pSrc[x] - 2 * (int) pSM1[x] + (int) pSM2[x];
374
0
      taAct += abs (t);
375
0
    }
376
0
    pSrc += iSrcStride;
377
0
    pSM1 += iSM1Stride;
378
0
    pSM2 += iSM2Stride;
379
0
  }
380
0
  return taAct;
381
0
}
382
uint64_t AvgHighPassWithDownsamplingCore( const int width, const int height, const Pel* pSrc, const int iSrcStride)
383
0
{
384
0
  uint64_t saAct = 0;
385
0
  pSrc -= iSrcStride;
386
0
  pSrc -= iSrcStride;
387
0
 for (int y = 2; y < height - 2; y += 2)
388
0
 {
389
0
   for (int x = 2; x < width - 2; x += 2)
390
0
   {
391
0
     const int f = 12 * ((int)pSrc[ y   *iSrcStride + x  ] + (int)pSrc[ y   *iSrcStride + x+1] + (int)pSrc[(y+1)*iSrcStride + x  ] + (int)pSrc[(y+1)*iSrcStride + x+1])
392
0
                  - 3 * ((int)pSrc[(y-1)*iSrcStride + x  ] + (int)pSrc[(y-1)*iSrcStride + x+1] + (int)pSrc[(y+2)*iSrcStride + x  ] + (int)pSrc[(y+2)*iSrcStride + x+1])
393
0
                  - 3 * ((int)pSrc[ y   *iSrcStride + x-1] + (int)pSrc[ y   *iSrcStride + x+2] + (int)pSrc[(y+1)*iSrcStride + x-1] + (int)pSrc[(y+1)*iSrcStride + x+2])
394
0
                  - 2 * ((int)pSrc[(y-1)*iSrcStride + x-1] + (int)pSrc[(y-1)*iSrcStride + x+2] + (int)pSrc[(y+2)*iSrcStride + x-1] + (int)pSrc[(y+2)*iSrcStride + x+2])
395
0
                      - ((int)pSrc[(y-2)*iSrcStride + x-1] + (int)pSrc[(y-2)*iSrcStride + x  ] + (int)pSrc[(y-2)*iSrcStride + x+1] + (int)pSrc[(y-2)*iSrcStride + x+2]
396
0
                       + (int)pSrc[(y+3)*iSrcStride + x-1] + (int)pSrc[(y+3)*iSrcStride + x  ] + (int)pSrc[(y+3)*iSrcStride + x+1] + (int)pSrc[(y+3)*iSrcStride + x+2]
397
0
                       + (int)pSrc[(y-1)*iSrcStride + x-2] + (int)pSrc[ y   *iSrcStride + x-2] + (int)pSrc[(y+1)*iSrcStride + x-2] + (int)pSrc[(y+2)*iSrcStride + x-2]
398
0
                       + (int)pSrc[(y-1)*iSrcStride + x+3] + (int)pSrc[ y   *iSrcStride + x+3] + (int)pSrc[(y+1)*iSrcStride + x+3] + (int)pSrc[(y+2)*iSrcStride + x+3]);
399
0
     saAct += (uint64_t) abs(f);
400
0
   }
401
0
 }
402
0
 return saAct;
403
0
}
404
uint64_t AvgHighPassWithDownsamplingDiff1stCore (const int width, const int  height, const Pel* pSrc,const Pel* pSrcM1, const int iSrcStride, const int iSrcM1Stride)
405
0
{
406
0
  uint64_t taAct = 0;
407
0
  pSrc -= iSrcStride;
408
0
  pSrc -= iSrcStride;
409
0
  pSrcM1-=iSrcM1Stride;
410
0
  pSrcM1-=iSrcM1Stride;
411
412
0
  for (uint32_t y = 2; y < height-2; y += 2)
413
0
  {
414
0
    for (uint32_t x = 2; x < width-2; x += 2)
415
0
    {
416
0
      const int t = (int)pSrc  [y*iSrcStride + x] + (int)pSrc  [y*iSrcStride + x+1] + (int)pSrc  [(y+1)*iSrcStride + x] + (int)pSrc  [(y+1)*iSrcStride + x+1]
417
0
                 - ((int)pSrcM1[y*iSrcM1Stride + x] + (int)pSrcM1[y*iSrcM1Stride + x+1] + (int)pSrcM1[(y+1)*iSrcM1Stride + x] + (int)pSrcM1[(y+1)*iSrcM1Stride + x+1]);
418
0
      taAct += (1 + 3 * abs (t)) >> 1;
419
0
    }
420
0
  }
421
0
  return (taAct );
422
0
}
423
424
uint64_t AvgHighPassWithDownsamplingDiff2ndCore (const int width,const int height,const Pel* pSrc,const Pel* pSrcM1,const Pel* pSrcM2,const int iSrcStride,const int iSM1Stride,const int iSM2Stride)
425
0
{
426
0
  uint64_t taAct = 0;
427
428
0
  pSrc -= iSrcStride;
429
0
  pSrc -= iSrcStride;
430
0
  pSrcM1-=iSM1Stride;
431
0
  pSrcM1-=iSM1Stride;
432
0
  pSrcM2-=iSM2Stride;
433
0
  pSrcM2-=iSM2Stride;
434
435
0
  for (uint32_t y = 2; y < height-2; y += 2)
436
0
  {
437
0
    for (uint32_t x = 2; x < width-2; x += 2)
438
0
    {
439
0
      const int t = (int)pSrc  [y*iSrcStride + x] + (int)pSrc  [y*iSrcStride + x+1] + (int)pSrc  [(y+1)*iSrcStride + x] + (int)pSrc  [(y+1)*iSrcStride + x+1]
440
0
                            - 2 * ((int)pSrcM1[y*iSM1Stride + x] + (int)pSrcM1[y*iSM1Stride + x+1] + (int)pSrcM1[(y+1)*iSM1Stride + x] + (int)pSrcM1[(y+1)*iSM1Stride + x+1])
441
0
                            + (int)pSrcM2[y*iSM2Stride + x] + (int)pSrcM2[y*iSM2Stride + x+1] + (int)pSrcM2[(y+1)*iSM2Stride + x] + (int)pSrcM2[(y+1)*iSM2Stride + x+1];
442
0
      taAct += (uint64_t) abs(t);
443
0
    }
444
0
  }
445
0
  return (taAct);
446
0
}
447
448
PelBufferOps::PelBufferOps()
449
14
{
450
14
  addAvg            = addAvgCore<Pel>;
451
14
  reco              = recoCore<Pel>;
452
14
  copyClip          = copyClipCore<Pel>;
453
14
  roundGeo          = roundGeoCore<Pel>;
454
455
14
  addAvg4           = addAvgCore<Pel>;
456
14
  addAvg8           = addAvgCore<Pel>;
457
14
  addAvg16          = addAvgCore<Pel>;
458
459
14
  sub4              = subsCore<Pel>;
460
14
  sub8              = subsCore<Pel>;
461
462
14
  wghtAvg4          = addWeightedAvgCore<Pel>;
463
14
  wghtAvg8          = addWeightedAvgCore<Pel>;
464
465
14
  copyClip4         = copyClipCore<Pel>;
466
14
  copyClip8         = copyClipCore<Pel>;
467
468
14
  reco4             = reconstructCore<Pel>;
469
14
  reco8             = reconstructCore<Pel>;
470
471
14
  linTf4            = linTfCore<Pel>;
472
14
  linTf8            = linTfCore<Pel>;
473
474
14
  copyBuffer        = copyBufferCore;
475
476
14
  removeHighFreq8   = removeHighFreq;
477
14
  removeHighFreq4   = removeHighFreq;
478
479
14
  transpose4x4      = transposeNxNCore<Pel,4>;
480
14
  transpose8x8      = transposeNxNCore<Pel,8>;
481
14
  mipMatrixMul_4_4  = mipMatrixMulCore<4,4>;
482
14
  mipMatrixMul_8_4  = mipMatrixMulCore<8,4>;
483
14
  mipMatrixMul_8_8  = mipMatrixMulCore<8,8>;
484
14
  weightCiip        = weightCiipCore;
485
14
  roundIntVector    = nullptr;
486
487
14
  applyLut          = applyLutCore;
488
489
14
  fillPtrMap        = fillMapPtr_Core;
490
14
  AvgHighPassWithDownsampling = AvgHighPassWithDownsamplingCore;
491
14
  AvgHighPass = AvgHighPassCore;
492
14
  AvgHighPassWithDownsamplingDiff1st = AvgHighPassWithDownsamplingDiff1stCore;
493
14
  AvgHighPassWithDownsamplingDiff2nd = AvgHighPassWithDownsamplingDiff2ndCore;
494
14
  HDHighPass = HDHighPassCore;
495
14
  HDHighPass2 = HDHighPass2Core;
496
14
}
497
498
void PelBufferOps::initPelBufOps( bool enableOpt )
499
0
{
500
0
  if( isInitSIMDDone )
501
0
  {
502
0
    return;
503
0
  }
504
0
  isInitSIMDDone = true;
505
506
0
  if( enableOpt )
507
0
  {
508
0
#if ENABLE_SIMD_OPT_BUFFER
509
#  if defined( TARGET_SIMD_X86 )
510
    g_pelBufOP.initPelBufOpsX86();
511
#  endif
512
#  if defined( TARGET_SIMD_ARM )
513
    g_pelBufOP.initPelBufOpsARM();
514
#  endif
515
0
#endif   // ENABLE_SIMD_OPT_BUFFER
516
0
  }
517
0
}
518
519
PelBufferOps g_pelBufOP = PelBufferOps();
520
521
template<>
522
void AreaBuf<Pel>::addWeightedAvg(const AreaBuf<const Pel>& other1, const AreaBuf<const Pel>& other2, const ClpRng& clpRng, const int8_t BcwIdx)
523
0
{
524
0
  const int8_t w0 = getBcwWeight( BcwIdx, REF_PIC_LIST_0 );
525
0
  const int8_t w1 = getBcwWeight( BcwIdx, REF_PIC_LIST_1 );
526
0
  const int8_t log2WeightBase = g_BcwLog2WeightBase;
527
0
  const Pel* src0 = other1.buf;
528
0
  const Pel* src2 = other2.buf;
529
0
        Pel* dest =        buf;
530
531
0
  const int src1Stride = other1.stride;
532
0
  const int src2Stride = other2.stride;
533
0
  const int destStride =        stride;
534
0
  const int clipbd     = clpRng.bd;
535
0
  const int shiftNum   = std::max<int>( 2, ( IF_INTERNAL_PREC - clipbd ) ) + log2WeightBase;
536
0
  const int offset     = ( 1 << ( shiftNum - 1 ) ) + ( IF_INTERNAL_OFFS << log2WeightBase );
537
538
0
  if( ( width & 7 ) == 0 )
539
0
  {
540
0
    g_pelBufOP.wghtAvg8( src0, src1Stride, src2, src2Stride, dest, destStride, width, height, shiftNum, offset, w0, w1, clpRng );
541
0
  }
542
0
  else if( ( width & 3 ) == 0 )
543
0
  {
544
0
    g_pelBufOP.wghtAvg4( src0, src1Stride, src2, src2Stride, dest, destStride, width, height, shiftNum, offset, w0, w1, clpRng );
545
0
  }
546
0
  else
547
0
  {
548
0
#define WGHT_AVG_OP( ADDR ) dest[ADDR] = ClipPel( rightShiftU( ( src0[ADDR]*w0 + src2[ADDR]*w1 + offset ), shiftNum ), clpRng )
549
0
#define WGHT_AVG_INC    \
550
0
    src0 += src1Stride; \
551
0
    src2 += src2Stride; \
552
0
    dest += destStride; \
553
0
554
0
    SIZE_AWARE_PER_EL_OP( WGHT_AVG_OP, WGHT_AVG_INC );
555
556
0
#undef WGHT_AVG_OP
557
0
#undef WGHT_AVG_INC
558
0
  }
559
0
}
560
561
template<>
562
void AreaBuf<Pel>::rspSignal( const Pel* pLUT)
563
0
{
564
0
  g_pelBufOP.applyLut( buf, stride, buf, stride, width, height, pLUT );
565
0
}
566
567
568
template<>
569
void AreaBuf<Pel>::rspSignal( const AreaBuf<const Pel>& other, const Pel* pLUT)
570
0
{
571
0
  g_pelBufOP.applyLut( other.buf, other.stride, buf, stride, width, height, pLUT );
572
0
}
573
574
template<>
575
void AreaBuf<Pel>::scaleSignal(const int scale, const bool dir, const ClpRng& clpRng)
576
0
{
577
0
        Pel* dst = buf;
578
0
  const Pel* src = buf;
579
0
  const int maxAbsclipBD = (1<<clpRng.bd) - 1;
580
581
0
  if (dir) // forward
582
0
  {
583
0
    if (width == 1)
584
0
    {
585
0
      THROW("Blocks of width = 1 not supported");
586
0
    }
587
0
    else
588
0
    {
589
0
      for (unsigned y = 0; y < height; y++)
590
0
      {
591
0
        for (unsigned x = 0; x < width; x++)
592
0
        {
593
0
          int sign = src[x] >= 0 ? 1 : -1;
594
0
          int absval = sign * src[x];
595
0
          dst[x] = (Pel)Clip3(-maxAbsclipBD, maxAbsclipBD, sign * (((absval << CSCALE_FP_PREC) + (scale >> 1)) / scale));
596
0
        }
597
0
        dst += stride;
598
0
        src += stride;
599
0
      }
600
0
    }
601
0
  }
602
0
  else // inverse
603
0
  {
604
0
    for (unsigned y = 0; y < height; y++)
605
0
    {
606
0
      for (unsigned x = 0; x < width; x++)
607
0
      {
608
0
        int val    = Clip3<int>((-maxAbsclipBD - 1), maxAbsclipBD, (int)src[x]);
609
0
        int sign   = src[x] >= 0 ? 1 : -1;
610
0
        int absval = sign * val;
611
0
               val = sign * ((absval * scale + (1 << (CSCALE_FP_PREC - 1))) >> CSCALE_FP_PREC);
612
0
        if (sizeof(Pel) == 2) // avoid overflow when storing data
613
0
        {
614
0
          val = Clip3<int>(-32768, 32767, val);
615
0
        }
616
0
        dst[x] = (Pel)val;
617
0
      }
618
0
      dst += stride;
619
0
      src += stride;
620
0
    }
621
0
  }
622
0
}
623
624
template<>
625
void AreaBuf<Pel>::addAvg( const AreaBuf<const Pel>& other1, const AreaBuf<const Pel>& other2, const ClpRng& clpRng)
626
0
{
627
0
  const Pel* src0 = other1.buf;
628
0
  const Pel* src2 = other2.buf;
629
0
        Pel* dest =        buf;
630
631
0
  const unsigned src1Stride = other1.stride;
632
0
  const unsigned src2Stride = other2.stride;
633
0
  const unsigned destStride =        stride;
634
0
  const int      clipbd     = clpRng.bd;
635
0
  const unsigned shiftNum   = std::max<int>(2, (IF_INTERNAL_PREC - clipbd)) + 1;
636
0
  const int      offset     = (1 << (shiftNum - 1)) + 2 * IF_INTERNAL_OFFS;
637
638
0
#if ENABLE_SIMD_OPT_BUFFER
639
0
  if( destStride == width )
640
0
  {
641
0
    g_pelBufOP.addAvg(src0, src2, dest, width * height, shiftNum, offset, clpRng);
642
0
  }
643
0
  else if ((width & 15) == 0)
644
0
  {
645
0
    g_pelBufOP.addAvg16(src0, src1Stride, src2, src2Stride, dest, destStride, width, height, shiftNum, offset, clpRng);
646
0
  }
647
0
  else if( ( width & 7 ) == 0 )
648
0
  {
649
0
    g_pelBufOP.addAvg8( src0, src1Stride, src2, src2Stride, dest, destStride, width, height, shiftNum, offset, clpRng );
650
0
  }
651
0
  else if( ( width & 3 ) == 0 )
652
0
  {
653
0
    g_pelBufOP.addAvg4( src0, src1Stride, src2, src2Stride, dest, destStride, width, height, shiftNum, offset, clpRng );
654
0
  }
655
0
  else
656
0
#endif
657
0
  {
658
0
#define ADD_AVG_OP( ADDR ) dest[ADDR] = ClipPel( rightShiftU( ( src0[ADDR] + src2[ADDR] + offset ), shiftNum ), clpRng )
659
0
#define ADD_AVG_INC     \
660
0
    src0 += src1Stride; \
661
0
    src2 += src2Stride; \
662
0
    dest += destStride; \
663
0
664
0
    SIZE_AWARE_PER_EL_OP( ADD_AVG_OP, ADD_AVG_INC );
665
666
0
#undef ADD_AVG_OP
667
0
#undef ADD_AVG_INC
668
0
  }
669
0
}
670
671
template<>
672
void AreaBuf<Pel>::subtract( const AreaBuf<const Pel>& minuend, const AreaBuf<const Pel>& subtrahend )
673
801k
{
674
801k
  CHECKD( width  != minuend.width,     "Incompatible size" );
675
801k
  CHECKD( height != minuend.height,    "Incompatible size" );
676
801k
  CHECKD( width  != subtrahend.width,  "Incompatible size");
677
801k
  CHECKD( height != subtrahend.height, "Incompatible size");
678
  
679
801k
        Pel* dest =            buf;
680
801k
  const Pel* mins = minuend   .buf;
681
801k
  const Pel* subs = subtrahend.buf;
682
683
684
801k
#if ENABLE_SIMD_OPT_BUFFER
685
801k
  const unsigned destStride =            stride;
686
801k
  const unsigned minsStride = minuend.   stride;
687
801k
  const unsigned subsStride = subtrahend.stride;
688
689
801k
  if( ( width & 7 ) == 0 )
690
677k
  {
691
677k
    g_pelBufOP.sub8( mins, minsStride, subs, subsStride, dest, destStride, width, height );
692
677k
  }
693
124k
  else if( ( width & 3 ) == 0 )
694
124k
  {
695
124k
    g_pelBufOP.sub4( mins, minsStride, subs, subsStride, dest, destStride, width, height );
696
124k
  }
697
18.4E
  else
698
18.4E
#endif
699
18.4E
  {
700
18.4E
#define SUBS_INC                \
701
18.4E
    dest +=            stride;  \
702
18.4E
    mins += minuend   .stride;  \
703
18.4E
    subs += subtrahend.stride;  \
704
18.4E
705
18.4E
#define SUBS_OP( ADDR ) dest[ADDR] = mins[ADDR] - subs[ADDR]
706
707
18.4E
    SIZE_AWARE_PER_EL_OP( SUBS_OP, SUBS_INC );
708
709
18.4E
#undef SUBS_OP
710
18.4E
#undef SUBS_INC
711
18.4E
  }
712
801k
}
713
714
template<>
715
void AreaBuf<const Pel>::calcVarianceSplit( const AreaBuf<const Pel>& Org, const uint32_t  size, int& varh,int& varv) const
716
0
{
717
0
  CHECK( Org.width != Org.height, "Incompatible size!" );
718
0
  int stride = Org.stride;
719
0
  const Pel* src;
720
0
  Pel data;
721
0
  double variance=0;
722
0
  double mean=0;
723
0
  int64_t sum[4]={0,0,0,0};
724
0
  int64_t sum_sqr[4]={0,0,0,0};
725
0
  uint32_t halfsize =size>>1;
726
0
  uint32_t off[4]={0,halfsize,size*halfsize,size*halfsize+halfsize};
727
0
  int n,x,y;
728
729
0
  for( n = 0; n < 4; n++)
730
0
  {
731
0
    src = Org.buf+off[n];
732
0
    for( y = 0; y < halfsize; y++)
733
0
    {
734
0
      for(x = 0; x < halfsize; x++)
735
0
      {
736
0
        data=src[y*stride+x];
737
0
        sum[n]+=data;
738
0
        sum_sqr[n]+= data*data;
739
0
      }
740
0
    }
741
0
  }
742
0
  int num=size*(size>>1);
743
  // varhu
744
0
  mean=(double)(sum[0]+sum[1])/(num);
745
0
  variance =  (double)(sum_sqr[0]+sum_sqr[1])/(num) - (mean*mean);
746
0
  varh =(int)(variance+0.5);
747
  // varhl
748
0
  mean=(double)(sum[2]+sum[3])/(num);
749
0
  variance =  (double)(sum_sqr[2]+sum_sqr[3])/(num) - (mean*mean);
750
0
  varh +=(int)(variance+0.5);
751
  // varvl
752
0
  mean=(double)(sum[0]+sum[2])/(num);
753
0
  variance =  (double)(sum_sqr[0]+sum_sqr[2])/(num) - (mean*mean);
754
0
  varv =(int)(variance+0.5);
755
  // varvr
756
0
  mean=(double)(sum[1]+sum[3])/(num);
757
0
  variance =  (double)(sum_sqr[1]+sum_sqr[3])/(num) - (mean*mean);
758
0
  varv +=(int)(variance+0.5);
759
0
}
760
761
template<>
762
void AreaBuf<Pel>::copyClip( const AreaBuf<const Pel>& src, const ClpRng& clpRng )
763
0
{
764
0
  const Pel* srcp = src.buf;
765
0
        Pel* dest =     buf;
766
767
0
  const unsigned srcStride  = src.stride;
768
0
  const unsigned destStride = stride;
769
770
0
  if( destStride == width)
771
0
  {
772
0
    g_pelBufOP.copyClip(srcp, dest, width * height, clpRng);
773
0
  }
774
0
  else if ((width & 7) == 0)
775
0
  {
776
0
    g_pelBufOP.copyClip8(srcp, srcStride, dest, destStride, width, height, clpRng);
777
0
  }
778
0
  else if ((width & 3) == 0)
779
0
  {
780
0
    g_pelBufOP.copyClip4(srcp, srcStride, dest, destStride, width, height, clpRng);
781
0
  }
782
0
  else
783
0
  {
784
0
    for( int y = 0; y < height; y++ )
785
0
    {
786
0
      dest[0] = ClipPel( srcp[0], clpRng);
787
0
      dest[1] = ClipPel( srcp[1], clpRng);
788
0
      srcp += srcStride;
789
0
      dest += destStride;
790
0
    }                                                         \
791
0
  }
792
0
}
793
794
template<>
795
void AreaBuf<Pel>::reconstruct( const AreaBuf<const Pel>& pred, const AreaBuf<const Pel>& resi, const ClpRng& clpRng )
796
2.25M
{
797
2.25M
  const Pel* src1 = pred.buf;
798
2.25M
  const Pel* src2 = resi.buf;
799
2.25M
        Pel* dest =      buf;
800
801
2.25M
  const unsigned src1Stride = pred.stride;
802
2.25M
  const unsigned src2Stride = resi.stride;
803
2.25M
  const unsigned destStride =      stride;
804
2.25M
  if( src2Stride == width )
805
2.25M
  {
806
2.25M
    g_pelBufOP.reco( pred.buf, resi.buf, buf, width * height, clpRng );
807
2.25M
  }
808
8.98k
  else if( ( width & 7 ) == 0 )
809
5.62k
  {
810
5.62k
    g_pelBufOP.reco8( src1, src1Stride, src2, src2Stride, dest, destStride, width, height, clpRng );
811
5.62k
  }
812
3.36k
  else if( ( width & 3 ) == 0 )
813
3.36k
  {
814
3.36k
    g_pelBufOP.reco4( src1, src1Stride, src2, src2Stride, dest, destStride, width, height, clpRng );
815
3.36k
  }
816
18.4E
  else if( ( width & 1 ) == 0 )
817
0
  {
818
0
    for( int y = 0; y < height; y++ )
819
0
    {
820
0
      dest[0] = ClipPel( src1[0] + src2[0], clpRng);
821
0
      dest[1] = ClipPel( src1[1] + src2[1], clpRng);
822
0
      src1 += src1Stride;
823
0
      src2 += src2Stride;
824
0
      dest += destStride;
825
0
    }                        
826
0
  }
827
18.4E
  else
828
18.4E
  {
829
18.4E
    CHECKD( width != 1, "Expecting width to be '1'!" );
830
831
18.4E
    for( int y = 0; y < height; y++ )
832
0
    {
833
0
      dest[0] = ClipPel( src1[0] + src2[0], clpRng );
834
835
0
      src1 += src1Stride;
836
0
      src2 += src2Stride;
837
0
      dest += destStride;
838
0
    }
839
18.4E
  }
840
2.25M
}
841
842
template<>
843
void AreaBuf<Pel>::linearTransform( const int scale, const unsigned shift, const int offset, bool bClip, const ClpRng& clpRng )
844
205k
{
845
205k
  const Pel* src = buf;
846
205k
        Pel* dst = buf;
847
848
205k
  if( stride == width)
849
205k
  {
850
205k
    if( width > 2 && height > 2 )
851
193k
    {
852
193k
      g_pelBufOP.linTf8( src, stride<<2, dst, stride<<2, width<<2, height>>2, scale, shift, offset, clpRng, bClip );
853
193k
    }
854
12.2k
    else
855
12.2k
    {
856
12.2k
      g_pelBufOP.linTf4( src, stride<<1, dst, stride<<1, width<<1, height>>1, scale, shift, offset, clpRng, bClip );
857
12.2k
    }
858
205k
  }
859
0
  else if( ( width & 7 ) == 0 )
860
0
  {
861
0
    g_pelBufOP.linTf8( src, stride, dst, stride, width, height, scale, shift, offset, clpRng, bClip );
862
0
  }
863
0
  else if( ( width & 3 ) == 0 )
864
0
  {
865
0
    g_pelBufOP.linTf4( src, stride, dst, stride, width, height, scale, shift, offset, clpRng, bClip );
866
0
  }
867
0
  else
868
0
  {
869
0
    if( bClip )
870
0
    {
871
0
      for( int y = 0; y < height; y++ )
872
0
      {
873
0
        dst[0] = ( Pel ) ClipPel( rightShiftU( scale * src[0], shift ) + offset, clpRng );
874
0
        dst[1] = ( Pel ) ClipPel( rightShiftU( scale * src[1], shift ) + offset, clpRng );
875
0
        src += stride;
876
0
        dst += stride;
877
0
      }
878
0
    }
879
0
    else
880
0
    {
881
0
      for( int y = 0; y < height; y++ )
882
0
      {
883
0
        dst[0] = ( Pel ) ( rightShiftU( scale * src[0], shift ) + offset );
884
0
        dst[1] = ( Pel ) ( rightShiftU( scale * src[1], shift ) + offset );
885
0
        src += stride;
886
0
        dst += stride;
887
0
      }
888
0
    }
889
0
  }
890
205k
}
891
892
#if ENABLE_SIMD_OPT_BUFFER
893
894
template<>
895
void AreaBuf<Pel>::transposedFrom( const AreaBuf<const Pel>& other )
896
600k
{
897
600k
  CHECK( width != other.height || height != other.width, "Incompatible size" );
898
899
600k
  if( ( ( width | height ) & 7 ) == 0 )
900
484k
  {
901
484k
    const Pel* src = other.buf;
902
903
1.97M
    for( unsigned y = 0; y < other.height; y += 8 )
904
1.49M
    {
905
1.49M
      Pel* dst = buf + y;
906
907
8.23M
      for( unsigned x = 0; x < other.width; x += 8 )
908
6.74M
      {
909
6.74M
        g_pelBufOP.transpose8x8( &src[x], other.stride, dst, stride );
910
911
6.74M
        dst += 8 * stride;
912
6.74M
      }
913
914
1.49M
      src += 8 * other.stride;
915
1.49M
    }
916
484k
  }
917
116k
  else if( ( ( width | height ) & 3 ) == 0 )
918
106k
  {
919
106k
    const Pel* src = other.buf;
920
921
316k
    for( unsigned y = 0; y < other.height; y += 4 )
922
210k
    {
923
210k
      Pel* dst = buf + y;
924
925
608k
      for( unsigned x = 0; x < other.width; x += 4 )
926
398k
      {
927
398k
        g_pelBufOP.transpose4x4( &src[x], other.stride, dst, stride );
928
929
398k
        dst += 4 * stride;
930
398k
      }
931
932
210k
      src += 4 * other.stride;
933
210k
    }
934
106k
  }
935
9.93k
  else
936
9.93k
  {
937
9.93k
          Pel* dst =       buf;
938
9.93k
    const Pel* src = other.buf;
939
9.93k
    width          = other.height;
940
9.93k
    height         = other.width;
941
9.93k
    stride         = stride < width ? width : stride;
942
943
125k
    for( unsigned y = 0; y < other.height; y++ )
944
115k
    {
945
345k
      for( unsigned x = 0; x < other.width; x++ )
946
230k
      {
947
230k
        dst[y + x*stride] = src[x + y * other.stride];
948
230k
      }
949
115k
    }
950
9.93k
  }
951
600k
}
952
#endif
953
954
template<>
955
void AreaBuf<Pel>::weightCiip( const AreaBuf<const Pel>& intra, const int numIntra )
956
0
{
957
0
  CHECK(width == 2, "Width of 2 is not supported");
958
0
  g_pelBufOP.weightCiip( buf, intra.buf, width * height, numIntra );
959
0
}
960
961
template<>
962
void AreaBuf<MotionInfo>::fill( const MotionInfo& val )
963
22.7k
{
964
22.7k
  if( width == stride )
965
22.7k
  {
966
22.7k
    std::fill_n( buf, width * height, val );
967
22.7k
  }
968
0
  else
969
0
  {
970
0
    MotionInfo* dst = buf;
971
972
0
    for( int y = 0; y < height; y++, dst += stride )
973
0
    {
974
0
      std::fill_n( dst, width, val );
975
0
    }
976
0
  }
977
22.7k
}
978
979
PelStorage::PelStorage()
980
4.14M
{
981
16.5M
  for( uint32_t i = 0; i < MAX_NUM_COMP; i++ )
982
12.4M
  {
983
12.4M
    m_origin[i] = nullptr;
984
12.4M
  }
985
4.14M
}
986
987
PelStorage::~PelStorage()
988
4.14M
{
989
4.14M
  destroy();
990
4.14M
}
991
992
void PelStorage::create( const UnitArea& _UnitArea )
993
1.82M
{
994
1.82M
  create( _UnitArea.chromaFormat, _UnitArea.blocks[0] );
995
1.82M
  m_maxArea = _UnitArea;
996
1.82M
}
997
998
void PelStorage::create( const ChromaFormat &_chromaFormat, const Area& _area )
999
3.63M
{
1000
3.63M
  CHECK( !bufs.empty(), "Trying to re-create an already initialized buffer" );
1001
1002
3.63M
  chromaFormat = _chromaFormat;
1003
1004
3.63M
  const uint32_t numComp = getNumberValidComponents( _chromaFormat );
1005
1006
3.63M
  uint32_t bufSize = 0;
1007
12.9M
  for( uint32_t i = 0; i < numComp; i++ )
1008
9.35M
  {
1009
9.35M
    const ComponentID compID = ComponentID( i );
1010
9.35M
    const unsigned totalWidth  = _area.width  >> getComponentScaleX( compID, _chromaFormat );
1011
9.35M
    const unsigned totalHeight = _area.height >> getComponentScaleY( compID, _chromaFormat );
1012
1013
9.35M
    const uint32_t area = totalWidth * totalHeight;
1014
9.35M
    CHECK( !area, "Trying to create a buffer with zero area" );
1015
9.35M
    bufSize += area;
1016
9.35M
  }
1017
1018
3.63M
  bufSize += 1; // for SIMD DMVR on the bottom right corner, which overreads the lines by 1 sample
1019
1020
  //allocate one buffer
1021
3.63M
  m_origin[0] = ( Pel* ) xMalloc( Pel, bufSize );
1022
1023
3.63M
  Pel* topLeft = m_origin[0];
1024
12.9M
  for( uint32_t i = 0; i < numComp; i++ )
1025
9.35M
  {
1026
9.35M
    const ComponentID compID = ComponentID( i );
1027
9.35M
    const unsigned totalWidth  = _area.width  >> getComponentScaleX( compID, _chromaFormat );
1028
9.35M
    const unsigned totalHeight = _area.height >> getComponentScaleY( compID, _chromaFormat );
1029
9.35M
    const uint32_t area = totalWidth * totalHeight;
1030
1031
9.35M
    bufs.push_back( PelBuf( topLeft, totalWidth, totalWidth, totalHeight ) );
1032
9.35M
    topLeft += area;
1033
9.35M
  }
1034
1035
3.63M
  m_maxArea = UnitArea( _chromaFormat, _area );
1036
3.63M
}
1037
1038
void PelStorage::create( const ChromaFormat &_chromaFormat, const Area& _area, const unsigned _maxCUSize, const unsigned _margin, const unsigned _alignment, const bool _scaleChromaMargin )
1039
169k
{
1040
169k
  CHECK( !bufs.empty(), "Trying to re-create an already initialized buffer" );
1041
1042
169k
  chromaFormat = _chromaFormat;
1043
1044
169k
  const uint32_t numComp = getNumberValidComponents( _chromaFormat );
1045
1046
169k
  unsigned extHeight = _area.height;
1047
169k
  unsigned extWidth  = _area.width;
1048
1049
169k
  if( _maxCUSize )
1050
31.6k
  {
1051
31.6k
    extHeight = ( ( _area.height + _maxCUSize - 1 ) / _maxCUSize ) * _maxCUSize;
1052
31.6k
    extWidth  = ( ( _area.width  + _maxCUSize - 1 ) / _maxCUSize ) * _maxCUSize;
1053
31.6k
  }
1054
1055
598k
  for( uint32_t i = 0; i < numComp; i++ )
1056
429k
  {
1057
429k
    const ComponentID compID = ComponentID( i );
1058
429k
    const unsigned scaleX = getComponentScaleX( compID, _chromaFormat );
1059
429k
    const unsigned scaleY = getComponentScaleY( compID, _chromaFormat );
1060
1061
429k
    unsigned scaledHeight = extHeight >> scaleY;
1062
429k
    unsigned scaledWidth  = extWidth  >> scaleX;
1063
429k
    unsigned ymargin      = _margin >> (_scaleChromaMargin?scaleY:0);
1064
429k
    unsigned xmargin      = _margin >> (_scaleChromaMargin?scaleX:0);
1065
429k
    unsigned totalWidth   = scaledWidth + 2*xmargin;
1066
429k
    unsigned totalHeight  = scaledHeight +2*ymargin;
1067
1068
429k
    if( _alignment )
1069
240k
    {
1070
      // make sure buffer lines are align
1071
240k
      CHECK( _alignment != MEMORY_ALIGN_DEF_SIZE, "Unsupported alignment" );
1072
240k
      totalWidth = ( ( totalWidth + _alignment - 1 ) / _alignment ) * _alignment;
1073
240k
    }
1074
429k
    uint32_t area = totalWidth * totalHeight;
1075
429k
    CHECK( !area, "Trying to create a buffer with zero area" );
1076
1077
429k
    m_origin[i] = ( Pel* ) xMalloc( Pel, area );
1078
429k
    Pel* topLeft = m_origin[i] + totalWidth * ymargin + xmargin;
1079
429k
    bufs.push_back( PelBuf( topLeft, totalWidth, _area.width >> scaleX, _area.height >> scaleY ) );
1080
429k
  }
1081
1082
169k
  m_maxArea = UnitArea( _chromaFormat, _area );
1083
169k
}
1084
1085
void PelStorage::createFromBuf( PelUnitBuf buf )
1086
2.43k
{
1087
2.43k
  chromaFormat = buf.chromaFormat;
1088
1089
2.43k
  const uint32_t numCh = getNumberValidComponents( chromaFormat );
1090
1091
2.43k
  bufs.resize(numCh);
1092
1093
9.72k
  for( uint32_t i = 0; i < numCh; i++ )
1094
7.29k
  {
1095
7.29k
    PelBuf cPelBuf = buf.get( ComponentID( i ) );
1096
7.29k
    bufs[i] = PelBuf( cPelBuf.bufAt( 0, 0 ), cPelBuf.stride, cPelBuf.width, cPelBuf.height );
1097
7.29k
  }
1098
2.43k
}
1099
1100
void PelStorage::compactResize( const UnitArea& area )
1101
2.24M
{
1102
2.24M
  CHECK( bufs.size() < area.blocks.size(), "Cannot increase buffer size when compacting!" );
1103
1104
7.60M
  for( uint32_t i = 0; i < area.blocks.size(); i++ )
1105
5.35M
  {
1106
5.35M
    CHECK( m_maxArea.blocks[i].area() < area.blocks[i].area(), "Cannot increase buffer size when compacting!" );
1107
1108
5.35M
    bufs[i].Size::operator=( area.blocks[i].size() );
1109
5.35M
    bufs[i].stride = bufs[i].width;
1110
5.35M
  }
1111
2.24M
}
1112
1113
void PelStorage::takeOwnership( PelStorage& other )
1114
0
{
1115
0
  chromaFormat = other.chromaFormat;
1116
1117
0
  const uint32_t numCh = getNumberValidComponents( chromaFormat );
1118
1119
0
  bufs.resize(numCh);
1120
1121
0
  for( uint32_t i = 0; i < numCh; i++ )
1122
0
  {
1123
0
    PelBuf cPelBuf = other.get( ComponentID( i ) );
1124
0
    bufs[i] = PelBuf( cPelBuf.bufAt( 0, 0 ), cPelBuf.stride, cPelBuf.width, cPelBuf.height );
1125
0
    std::swap( m_origin[i], other.m_origin[i]);
1126
0
  }
1127
1128
0
  m_maxArea = other.m_maxArea;
1129
1130
0
  other.destroy();
1131
0
}
1132
1133
1134
void PelStorage::swap( PelStorage& other )
1135
0
{
1136
0
  const uint32_t numCh = getNumberValidComponents( chromaFormat );
1137
1138
0
  for( uint32_t i = 0; i < numCh; i++ )
1139
0
  {
1140
    // check this otherwise it would turn out to get very weird
1141
0
    CHECK( chromaFormat                   != other.chromaFormat                  , "Incompatible formats" );
1142
0
    CHECK( get( ComponentID( i ) )        != other.get( ComponentID( i ) )       , "Incompatible formats" );
1143
0
    CHECK( get( ComponentID( i ) ).stride != other.get( ComponentID( i ) ).stride, "Incompatible formats" );
1144
1145
0
    std::swap( bufs[i].buf,    other.bufs[i].buf );
1146
0
    std::swap( bufs[i].stride, other.bufs[i].stride );
1147
0
    std::swap( m_origin[i],    other.m_origin[i] );
1148
0
  }
1149
0
}
1150
1151
void PelStorage::destroy()
1152
7.93M
{
1153
7.93M
  chromaFormat = NUM_CHROMA_FORMAT;
1154
31.7M
  for( uint32_t i = 0; i < MAX_NUM_COMP; i++ )
1155
23.7M
  {
1156
23.7M
    if( m_origin[i] )
1157
4.06M
    {
1158
4.06M
      xFree( m_origin[i] );
1159
4.06M
      m_origin[i] = nullptr;
1160
4.06M
    }
1161
23.7M
  }
1162
7.93M
  bufs.clear();
1163
7.93M
}
1164
1165
PelBuf PelStorage::getBuf( const ComponentID CompID )
1166
16.1k
{
1167
16.1k
  return bufs[CompID];
1168
16.1k
}
1169
1170
const CPelBuf PelStorage::getBuf( const ComponentID CompID ) const
1171
0
{
1172
0
  return bufs[CompID];
1173
0
}
1174
1175
PelBuf PelStorage::getBuf( const CompArea& blk )
1176
21.1M
{
1177
21.1M
  const PelBuf& r = bufs[blk.compID];
1178
21.1M
  return PelBuf( r.buf + rsAddr( blk, r.stride ), r.stride, blk );
1179
21.1M
}
1180
1181
const CPelBuf PelStorage::getBuf( const CompArea& blk ) const
1182
27.9k
{
1183
27.9k
  const PelBuf& r = bufs[blk.compID];
1184
27.9k
  return CPelBuf( r.buf + rsAddr( blk, r.stride ), r.stride, blk );
1185
27.9k
}
1186
1187
PelUnitBuf PelStorage::getBuf( const UnitArea& unit )
1188
3.81k
{
1189
3.81k
  return ( chromaFormat == CHROMA_400 ) ? PelUnitBuf( chromaFormat, getBuf( unit.Y() ) ) : PelUnitBuf( chromaFormat, getBuf( unit.Y() ), getBuf( unit.Cb() ), getBuf( unit.Cr() ) );
1190
3.81k
}
1191
1192
const CPelUnitBuf PelStorage::getBuf( const UnitArea& unit ) const
1193
0
{
1194
0
  return ( chromaFormat == CHROMA_400 ) ? CPelUnitBuf( chromaFormat, getBuf( unit.Y() ) ) : CPelUnitBuf( chromaFormat, getBuf( unit.Y() ), getBuf( unit.Cb() ), getBuf( unit.Cr() ) );
1195
0
}
1196
1197
PelUnitBuf PelStorage::getBuf(const int strY, const int strCb, const int strCr, const UnitArea& unit)
1198
0
{
1199
0
  CHECKD( unit.Y().width > bufs[COMP_Y].width && unit.Y().height > bufs[COMP_Y].height, "unsuported request" );
1200
0
  CHECKD( strY > bufs[COMP_Y].stride, "unsuported request" );
1201
0
  CHECKD( strCb > bufs[COMP_Cb].stride, "unsuported request" );
1202
0
  CHECKD( strCr > bufs[COMP_Cr].stride, "unsuported request" );
1203
0
  return (chromaFormat == CHROMA_400) ? PelUnitBuf(chromaFormat, PelBuf( bufs[COMP_Y].buf, strY, unit.Y())) : PelUnitBuf(chromaFormat, PelBuf( bufs[COMP_Y].buf, strY, unit.Y()), PelBuf( bufs[COMP_Cb].buf, strCb, unit.Cb()), PelBuf( bufs[COMP_Cr].buf, strCr, unit.Cr()));
1204
0
}
1205
1206
const CPelUnitBuf PelStorage::getBuf(const int strY, const int strCb, const int strCr, const UnitArea& unit) const
1207
0
{
1208
0
  CHECKD( unit.Y().width > bufs[COMP_Y].width && unit.Y().height > bufs[COMP_Y].height, "unsuported request" );
1209
0
  CHECKD( strY > bufs[COMP_Y].stride, "unsuported request" );
1210
0
  CHECKD( strCb > bufs[COMP_Cb].stride, "unsuported request" );
1211
0
  CHECKD( strCr > bufs[COMP_Cr].stride, "unsuported request" );
1212
0
  return (chromaFormat == CHROMA_400) ? CPelUnitBuf(chromaFormat, CPelBuf( bufs[COMP_Y].buf, strY, unit.Y())) : CPelUnitBuf(chromaFormat, CPelBuf( bufs[COMP_Y].buf, strY, unit.Y()), CPelBuf( bufs[COMP_Cb].buf, strCb, unit.Cb()), CPelBuf( bufs[COMP_Cr].buf, strCr, unit.Cr()));
1213
0
}
1214
1215
PelUnitBuf PelStorage::getBufPart(const UnitArea& unit)
1216
0
{
1217
0
  CHECKD( unit.Y().width > bufs[COMP_Y].width && unit.Y().height > bufs[COMP_Y].height, "unsuported request" );
1218
0
  return (chromaFormat == CHROMA_400) ? PelUnitBuf(chromaFormat, PelBuf( bufs[COMP_Y].buf, bufs[COMP_Y].stride, unit.Y())) : PelUnitBuf(chromaFormat, PelBuf( bufs[COMP_Y].buf, bufs[COMP_Y].stride, unit.Y()), PelBuf( bufs[COMP_Cb].buf, bufs[COMP_Cb].stride, unit.Cb()), PelBuf( bufs[COMP_Cr].buf, bufs[COMP_Cr].stride, unit.Cr()));
1219
0
}
1220
1221
const CPelUnitBuf PelStorage::getBufPart(const UnitArea& unit) const
1222
0
{
1223
0
  CHECKD(unit.Y().width > bufs[COMP_Y].width && unit.Y().height > bufs[COMP_Y].height, "unsuported request");
1224
0
  return (chromaFormat == CHROMA_400) ? CPelUnitBuf(chromaFormat, CPelBuf(bufs[COMP_Y].buf, unit.Y().width, unit.Y())) : CPelUnitBuf(chromaFormat, CPelBuf(bufs[COMP_Y].buf, unit.Y().width, unit.Y()), CPelBuf(bufs[COMP_Cb].buf, unit.Cb().width, unit.Cb()), CPelBuf(bufs[COMP_Cr].buf, unit.Cr().width, unit.Cr()));
1225
0
}
1226
1227
const CPelUnitBuf PelStorage::getCompactBuf(const UnitArea& unit) const
1228
0
{
1229
0
  CHECKD( unit.Y().width > bufs[COMP_Y].width && unit.Y().height > bufs[COMP_Y].height, "unsuported request" );
1230
1231
0
  PelUnitBuf ret;
1232
0
  ret.chromaFormat = chromaFormat;
1233
0
  ret.bufs.resize_noinit( chromaFormat == CHROMA_400 ? 1 : 3 );
1234
  
1235
0
  ret.Y   ().buf = bufs[COMP_Y ].buf; ret.Y ().width = ret.Y ().stride = unit.Y ().width; ret.Y ().height = unit.Y ().height;
1236
0
  if( chromaFormat != CHROMA_400 )
1237
0
  {
1238
0
    ret.Cb().buf = bufs[COMP_Cb].buf; ret.Cb().width = ret.Cb().stride = unit.Cb().width; ret.Cb().height = unit.Cb().height;
1239
0
    ret.Cr().buf = bufs[COMP_Cr].buf; ret.Cr().width = ret.Cr().stride = unit.Cr().width; ret.Cr().height = unit.Cr().height;
1240
0
  }
1241
1242
0
  return ret;
1243
0
}
1244
1245
PelUnitBuf PelStorage::getCompactBuf(const UnitArea& unit)
1246
144k
{
1247
144k
  CHECKD( unit.Y().width > bufs[COMP_Y].width && unit.Y().height > bufs[COMP_Y].height, "unsuported request" );
1248
1249
144k
  PelUnitBuf ret;
1250
144k
  ret.chromaFormat = chromaFormat;
1251
144k
  ret.bufs.resize_noinit( chromaFormat == CHROMA_400 ? 1 : 3 );
1252
1253
144k
  ret.Y   ().buf = bufs[COMP_Y ].buf; ret.Y ().width = ret.Y ().stride = unit.Y ().width; ret.Y ().height = unit.Y ().height;
1254
144k
  if( chromaFormat != CHROMA_400 )
1255
144k
  {
1256
144k
    ret.Cb().buf = bufs[COMP_Cb].buf; ret.Cb().width = ret.Cb().stride = unit.Cb().width; ret.Cb().height = unit.Cb().height;
1257
144k
    ret.Cr().buf = bufs[COMP_Cr].buf; ret.Cr().width = ret.Cr().stride = unit.Cr().width; ret.Cr().height = unit.Cr().height;
1258
144k
  }
1259
1260
144k
  return ret;
1261
144k
}
1262
1263
const CPelBuf PelStorage::getCompactBuf(const CompArea& carea) const
1264
0
{
1265
0
  return CPelBuf( bufs[carea.compID].buf, carea.width, carea);
1266
0
}
1267
1268
PelBuf PelStorage::getCompactBuf(const CompArea& carea)
1269
0
{
1270
0
  return PelBuf( bufs[carea.compID].buf, carea.width, carea);
1271
0
}
1272
1273
void downsampleYuv(PelBuf& dest, const vvencYUVPlane& yuvPlaneIn, int downsampleStep)
1274
0
{
1275
0
  const int widthd = dest.width;
1276
0
  const int heightd = dest.height;
1277
0
  int difStride = dest.stride - dest.width;
1278
1279
0
  const int16_t* src = yuvPlaneIn.ptr;
1280
0
  const int instride = yuvPlaneIn.stride;
1281
0
  const int width = yuvPlaneIn.width;
1282
0
  int n = 0;
1283
0
  for (int j = 0; j < heightd; j++)
1284
0
  {
1285
0
    int i = 0;
1286
0
    for (i = 0; i < widthd; i++)
1287
0
    {
1288
0
      long int b = 0;
1289
0
      for (int r = 0; r < downsampleStep; r++)
1290
0
      {
1291
0
        int posr = width * r;
1292
0
        for (int n = 0; n < downsampleStep; n++)
1293
0
        {
1294
0
          b += src[posr + n];
1295
0
        }
1296
0
      }
1297
0
      src += downsampleStep;
1298
0
      dest.buf[n] = (int16_t)((b + 2) / (downsampleStep << 1));
1299
0
      n++;
1300
0
    }
1301
0
    n += difStride;
1302
0
    src = src - downsampleStep * i + width;
1303
1304
0
    src += (instride * (downsampleStep - 1));
1305
0
  }
1306
0
}
1307
1308
void copyPadToPelUnitBuf( PelUnitBuf pelUnitBuf, const vvencYUVBuffer& yuvBuffer, const ChromaFormat& chFmt )
1309
1.21k
{
1310
1.21k
  CHECK( pelUnitBuf.bufs.size() == 0, "pelUnitBuf not initialized" );
1311
1.21k
  pelUnitBuf.chromaFormat = chFmt;
1312
1.21k
  const int numComp = getNumberValidComponents( chFmt );
1313
4.86k
  for ( int i = 0; i < numComp; i++ )
1314
3.64k
  {
1315
3.64k
    const vvencYUVPlane& src = yuvBuffer.planes[ i ];
1316
3.64k
    CHECK( src.ptr == nullptr, "yuvBuffer not setup" );
1317
3.64k
    PelBuf& dest = pelUnitBuf.bufs[i];
1318
3.64k
    CHECK( dest.buf == nullptr, "yuvBuffer not setup" );
1319
1320
3.64k
    if (dest.width < src.width)
1321
0
    {
1322
0
      downsampleYuv(dest, src, 2);
1323
0
    }
1324
3.64k
    else
1325
3.64k
    {
1326
371k
      for (int y = 0; y < src.height; y++)
1327
367k
      {
1328
367k
        ::memcpy(dest.buf + y * dest.stride, src.ptr + y * src.stride, src.width * sizeof(int16_t));
1329
1330
        // pad right if required
1331
367k
        for (int x = src.width; x < dest.width; x++)
1332
0
        {
1333
0
          dest.buf[x + y * dest.stride] = dest.buf[src.width - 1 + y * dest.stride];
1334
0
        }
1335
367k
      }
1336
1337
      // pad bottom if required
1338
3.64k
      for (int y = src.height; y < dest.height; y++)
1339
0
      {
1340
0
        ::memcpy(dest.buf + y * dest.stride, dest.buf + (src.height - 1) * dest.stride, dest.width * sizeof(int16_t));
1341
0
      }
1342
3.64k
    }
1343
3.64k
  }
1344
1.21k
}
1345
1346
/*
1347
void setupPelUnitBuf( const YUVBuffer& yuvBuffer, PelUnitBuf& pelUnitBuf, const ChromaFormat& chFmt )
1348
{
1349
  CHECK( pelUnitBuf.bufs.size() != 0, "pelUnitBuf already in use" );
1350
  pelUnitBuf.chromaFormat = chFmt;
1351
  const int numComp = getNumberValidComponents( chFmt );
1352
  for ( int i = 0; i < numComp; i++ )
1353
  {
1354
    const YUVBuffer::Plane& yuvPlane = yuvBuffer.planes[ i ];
1355
    CHECK( yuvPlane.ptr == nullptr, "yuvBuffer not setup" );
1356
    PelBuf area( yuvPlane.ptr, yuvPlane.stride, yuvPlane.width, yuvPlane.height );
1357
    pelUnitBuf.bufs.push_back( area );
1358
  }
1359
}
1360
*/
1361
void setupYuvBuffer ( const PelUnitBuf& pelUnitBuf, vvencYUVBuffer& yuvBuffer, const Window* confWindow )
1362
0
{
1363
0
  const ChromaFormat chFmt = pelUnitBuf.chromaFormat;
1364
0
  const int numComp        = getNumberValidComponents( chFmt );
1365
0
  for ( int i = 0; i < numComp; i++ )
1366
0
  {
1367
0
    const ComponentID compId = ComponentID( i );
1368
0
          PelBuf area        = pelUnitBuf.get( compId );
1369
0
    const int sx             = getComponentScaleX( compId, chFmt );
1370
0
    const int sy             = getComponentScaleY( compId, chFmt );
1371
0
    vvencYUVPlane& yuvPlane = yuvBuffer.planes[ i ];
1372
0
    CHECK( yuvPlane.ptr != nullptr, "yuvBuffer already in use" );
1373
0
    yuvPlane.ptr             = area.bufAt( confWindow->winLeftOffset >> sx, confWindow->winTopOffset >> sy );
1374
0
    yuvPlane.width           = ( ( area.width  << sx ) - ( confWindow->winLeftOffset + confWindow->winRightOffset  ) ) >> sx;
1375
0
    yuvPlane.height          = ( ( area.height << sy ) - ( confWindow->winTopOffset  + confWindow->winBottomOffset ) ) >> sy;
1376
0
    yuvPlane.stride          = area.stride;
1377
0
  }
1378
0
}
1379
1380
} // namespace vvenc
1381
1382
//! \}
1383