Coverage Report

Created: 2026-08-31 06:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/vvenc/source/Lib/EncoderLib/SEIFilmGrainAnalyzer.h
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
#ifndef __SEIFILMGRAINANALYZER__
45
#define __SEIFILMGRAINANALYZER__
46
47
#pragma once
48
49
#include "CommonLib/Picture.h"
50
#include "CommonLib/SEI.h"
51
52
#include <numeric>
53
#include <cmath>
54
#include <algorithm>
55
#include <fstream>  // Include this for std::ofstream
56
57
//using namespace vvenc;
58
namespace vvenc {
59
60
#if defined(TARGET_SIMD_X86)  && ENABLE_SIMD_OPT_FGA
61
using namespace x86_simd;
62
#endif
63
  
64
static constexpr double   PI                     = 3.14159265358979323846;
65
static constexpr double   PI_2                   = 3.14159265358979323846 / 2.0;
66
static constexpr double   pi_8                   = PI / 8.0;
67
static constexpr double   pi_3_8                 = 3.0 * PI / 8.0;
68
static constexpr double   pi_5_8                 = 5.0 * PI / 8.0;
69
static constexpr double   pi_7_8                 = 7.0 * PI / 8.0;
70
71
static constexpr int      DATA_BASE_SIZE         = 64;
72
static constexpr int      INTERVAL_SIZE          = 16;
73
static constexpr int      MAX_INTERVAL_NUMBER    = (1 << 16) / INTERVAL_SIZE;
74
static constexpr int      MAXPAIRS               = 256;
75
76
static constexpr int      KERNELSIZE             = 3;     // Dilation and erosion kernel size
77
static constexpr int      CONV_WIDTH_S           = 3;
78
static constexpr int      CONV_HEIGHT_S          = 3;
79
// ====================================================================================================================
80
// Class definition
81
// ====================================================================================================================
82
83
class Canny
84
{
85
public:
86
  Canny();
87
  ~Canny();
88
89
  unsigned int      m_convWidthG = 5, m_convHeightG = 5;      // Pixel's row and col positions for Gauss filtering
90
  
91
  void init ( unsigned int width,
92
              unsigned int height,
93
              ChromaFormat inputChroma );
94
95
  void destroy ();
96
97
  void detect_edges ( const PelStorage* orig,
98
                      PelStorage* dest,
99
                      unsigned int uiBitDepth,
100
                      ComponentID compID );
101
102
private:
103
  double            m_lowThresholdRatio   = 0.1;               // low threshold rato
104
  int               m_highThresholdRatio  = 3;                 // high threshold rato
105
106
  PelStorage *m_orientationBuf = nullptr;
107
  PelStorage* m_gradientBufX = nullptr;
108
  PelStorage* m_gradientBufY = nullptr;
109
110
  void suppressNonMax ( PelStorage* buff1,
111
                        PelStorage* buff2,
112
                        unsigned int width,
113
                        unsigned int height,
114
                        ComponentID compID );
115
116
  void doubleThreshold ( PelStorage *buff,
117
                         unsigned int width,
118
                         unsigned int height,
119
                         unsigned int bitDepth,
120
                         ComponentID compID );
121
122
  void edgeTracking ( PelStorage* buff1,
123
                      unsigned int width,
124
                      unsigned int height,
125
                      unsigned int windowWidth,
126
                      unsigned int windowHeight,
127
                      unsigned int bitDepth,
128
                      ComponentID compID );
129
130
  void (*gradient) ( PelStorage* buff1,
131
                     PelStorage* buff2,
132
                     PelStorage *tmpBuf1,
133
                     PelStorage *tmpBuf2,
134
                     unsigned int width,
135
                     unsigned int height,
136
                     unsigned int bitDepth,
137
                     ComponentID compID);
138
139
#if ENABLE_SIMD_OPT_FGA && defined( TARGET_SIMD_X86 )
140
  void initFGACannyX86();
141
  template <X86_VEXT vext>
142
  void _initFGACannyX86();
143
#endif
144
};
145
146
class Morph
147
{
148
public:
149
  Morph( bool enableOpt = true );
150
  ~Morph();
151
152
  void init ( uint32_t width,
153
              uint32_t height );
154
155
  void destroy ();
156
157
  int (*dilation) ( PelStorage *buff,
158
                    PelStorage *Wbuf,
159
                    uint32_t bitDepth,
160
                    ComponentID compID,
161
                    int numIter,
162
                    int iter,
163
                    Pel Value );
164
165
#if ENABLE_SIMD_OPT_FGA && defined( TARGET_SIMD_X86 )
166
  void initFGAMorphX86();
167
  template <X86_VEXT vext>
168
  void _initFGAMorphX86();
169
#endif
170
#if ENABLE_SIMD_OPT_FGA && defined( TARGET_SIMD_ARM )
171
  void initFGAMorphARM();
172
  template <ARM_VEXT vext>
173
  void _initFGAMorphARM();
174
#endif
175
176
  PelStorage* m_dilationBuf = nullptr;
177
  PelStorage* m_dilationBuf2 = nullptr;
178
  PelStorage* m_dilationBuf4 = nullptr;
179
};
180
181
182
class FGAnalyzer
183
{
184
public:
185
  FGAnalyzer( bool enableOpt = true );
186
  ~FGAnalyzer();
187
188
  int                             prevAnalysisPoc                = -1;
189
190
  void init( const int                        width,
191
             const int                        height,
192
             const ChromaFormat               inputChroma,
193
             const int                        *outputBitDepths,
194
             const bool doAnalysis[] );
195
  void destroy        ();
196
197
  void estimateGrainParameters ( Picture* pic );
198
199
0
  int getLog2scaleFactor()  { return m_log2ScaleFactor; };
200
201
0
  SeiFgc::CompModel  getCompModel( int idx ) { return m_compModel[idx];  };
202
203
  double (*calcVar) ( const Pel* org,
204
                      const ptrdiff_t origStride,
205
                      const int w,
206
                      const int h );
207
208
  int (*calcMean) ( const Pel* org,
209
                    const ptrdiff_t origStride,
210
                    const int w,
211
                    const int h );
212
213
  void (*fastDCT2_64) ( const TCoeff* src,
214
                        TCoeff* dst,
215
                        int shift,
216
                        int line,
217
                        int iSkipLine,
218
                        int iSkipLine2 );
219
220
private:
221
  int                             *m_bitDepths;
222
  ChromaFormat                    m_inputChromaFormat;
223
  bool                            m_doAnalysis[ComponentID::MAX_NUM_COMP] = { true, true, true };
224
225
  Canny                           m_edgeDetector;
226
  Morph                           m_morphOperation;
227
  double                          m_lowIntensityRatio            = 0.1;           // supress everything below 0.1*maxIntensityOffset
228
229
  CoeffBuf                        * m_dctGrainBlockList;
230
  TCoeff                          * m_coeffBuf;
231
  int                             m_numDctGrainBlocks;
232
233
  std::vector<double>             coeffs;
234
  std::vector<double>             scalingVec;
235
  std::vector<int>                quantVec;
236
237
  std::vector<int>                vecMean;
238
  std::vector<int>                vecVar;
239
240
  double                          meanSquaredDctGrain[DATA_BASE_SIZE][DATA_BASE_SIZE];
241
242
  /* Interval points for fitFunction */
243
  std::vector<int>                vec_mean_intensity;
244
  std::vector<int>                vec_variance_intensity;
245
  std::vector<int>                element_number_per_interval;
246
  std::vector<int>                tmp_data_x;
247
  std::vector<int>                tmp_data_y;
248
249
  static constexpr double         m_tapFilter[3]                = { 1, 2, 1 };
250
  static constexpr double         m_normTap                     = 4.0;
251
252
  // fg model parameters
253
  int                             m_log2ScaleFactor;
254
  std::vector<std::array<int, 3>> finalIntervalsandScalingFactors;   // lower_bound, upper_bound, scaling_factor
255
  SeiFgc::CompModel               m_compModel[ComponentID::MAX_NUM_COMP];
256
257
  const PelStorage                *m_originalBuf             = nullptr;
258
  const PelStorage                *m_workingBuf              = nullptr;
259
  PelStorage                      *m_maskBuf                 = nullptr;
260
  PelStorage                      *m_grainEstimateBuf        = nullptr;
261
  PelStorage                      *m_workingBufSubsampled2   = nullptr;
262
  PelStorage                      *m_maskSubsampled2         = nullptr;
263
  PelStorage                      *m_workingBufSubsampled4   = nullptr;
264
  PelStorage                      *m_maskSubsampled4         = nullptr;
265
  PelStorage                      *m_maskUpsampled           = nullptr;
266
  // for DCT
267
  TCoeff                          *m_DCTinout                = nullptr;
268
  TCoeff                          *m_DCTtemp                 = nullptr;
269
270
  void findMask ( ComponentID compID );
271
272
  void blockTransform ( CoeffBuf& currentCoeffBuf,
273
                        int offsetX,
274
                        int offsetY,
275
                        uint32_t bitDepth,
276
                        ComponentID compId );
277
278
  void adaptiveSampling ( int bins,
279
                          double threshold,
280
                          std::vector<int>& significantIndices,
281
                          bool isRow,
282
                          int startIdx );
283
284
  void estimateCutoffFreqAdaptive ( ComponentID compID );
285
286
  void estimateScalingFactors ( uint32_t bitDepth,
287
                                ComponentID compID );
288
289
  bool fitFunction ( int order,
290
                     int bitDepth,
291
                     bool second_pass );
292
293
  void avgScalingVec ( int bitDepth );
294
295
  bool lloydMax ( double& distortion,
296
                  int bitDepth );
297
298
  void quantize ( std::vector<double>& quantizedVec,
299
                  double& distortion,
300
                  double partition[],
301
                  double codebook[] );
302
303
  void extendPoints ( int bitDepth );
304
305
  void setEstimatedParameters ( uint32_t bitDepth,
306
                                ComponentID compID );
307
308
  void defineIntervalsAndScalings ( int bitDepth );
309
310
  void scaleDown ( int bitDepth );
311
312
  void confirmIntervals ( );
313
314
  long double ldpow ( long double n,
315
                      unsigned p );
316
317
  int countEdges ( int windowSize,
318
                   int offsetX,
319
                   int offsetY,
320
                   ComponentID compID );
321
322
  void subsample ( PelStorage& output,
323
                   const int factor = 2,
324
                   const int padding = 0, 
325
                   ComponentID compID = COMP_Y ) const;
326
327
  void upsample ( const PelStorage& input,
328
                  const int factor = 2,
329
                  const int padding = 0,
330
                  ComponentID compID = COMP_Y ) const;
331
332
  void combineMasks ( ComponentID compId );
333
334
  void suppressLowIntensity ( const PelStorage& buff1,
335
                              PelStorage& buff2,
336
                              uint32_t bitDepth,
337
                              ComponentID compId );
338
339
#if ENABLE_SIMD_OPT_FGA && defined( TARGET_SIMD_X86 )
340
  void initFGAnalyzerX86();
341
  template <X86_VEXT vext>
342
  void _initFGAnalyzerX86();
343
#endif
344
#if ENABLE_SIMD_OPT_FGA && defined( TARGET_SIMD_ARM )
345
  void initFGAnalyzerARM();
346
  template <ARM_VEXT vext>
347
  void _initFGAnalyzerARM();
348
#endif
349
};
350
351
} // namespace vvenc
352
353
// Scalar reference for Morph::dilation. Global (not vvenc::) because this
354
// header's .cpp only does "using namespace vvenc;" rather than wrapping its
355
// definitions in the namespace. SIMD dilation implementations that need a
356
// fallback for widths their vectorized path can't handle delegate to it
357
// directly instead of duplicating the 3x3 test.
358
int dilation_core( vvenc::PelStorage* buff, vvenc::PelStorage* Wbuf, uint32_t bitDepth, vvenc::ComponentID compID,
359
                   int numIter, int iter, vvenc::Pel Value );
360
361
#endif // __SEIFILMGRAINANALYZER__
362
363