Coverage Report

Created: 2026-07-16 06:32

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();
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
171
  PelStorage* m_dilationBuf = nullptr;
172
  PelStorage* m_dilationBuf2 = nullptr;
173
  PelStorage* m_dilationBuf4 = nullptr;
174
};
175
176
177
class FGAnalyzer
178
{
179
public:
180
  FGAnalyzer( bool enableOpt = true );
181
  ~FGAnalyzer();
182
183
  int                             prevAnalysisPoc                = -1;
184
185
  void init( const int                        width,
186
             const int                        height,
187
             const ChromaFormat               inputChroma,
188
             const int                        *outputBitDepths,
189
             const bool doAnalysis[] );
190
  void destroy        ();
191
192
  void estimateGrainParameters ( Picture* pic );
193
194
0
  int getLog2scaleFactor()  { return m_log2ScaleFactor; };
195
196
0
  SeiFgc::CompModel  getCompModel( int idx ) { return m_compModel[idx];  };
197
198
  double (*calcVar) ( const Pel* org,
199
                      const ptrdiff_t origStride,
200
                      const int w,
201
                      const int h );
202
203
  int (*calcMean) ( const Pel* org,
204
                    const ptrdiff_t origStride,
205
                    const int w,
206
                    const int h );
207
208
  void (*fastDCT2_64) ( const TCoeff* src,
209
                        TCoeff* dst,
210
                        int shift,
211
                        int line,
212
                        int iSkipLine,
213
                        int iSkipLine2 );
214
215
private:
216
  int                             *m_bitDepths;
217
  ChromaFormat                    m_inputChromaFormat;
218
  bool                            m_doAnalysis[ComponentID::MAX_NUM_COMP] = { true, true, true };
219
220
  Canny                           m_edgeDetector;
221
  Morph                           m_morphOperation;
222
  double                          m_lowIntensityRatio            = 0.1;           // supress everything below 0.1*maxIntensityOffset
223
224
  CoeffBuf                        * m_dctGrainBlockList;
225
  TCoeff                          * m_coeffBuf;
226
  int                             m_numDctGrainBlocks;
227
228
  std::vector<double>             coeffs;
229
  std::vector<double>             scalingVec;
230
  std::vector<int>                quantVec;
231
232
  std::vector<int>                vecMean;
233
  std::vector<int>                vecVar;
234
235
  double                          meanSquaredDctGrain[DATA_BASE_SIZE][DATA_BASE_SIZE];
236
237
  /* Interval points for fitFunction */
238
  std::vector<int>                vec_mean_intensity;
239
  std::vector<int>                vec_variance_intensity;
240
  std::vector<int>                element_number_per_interval;
241
  std::vector<int>                tmp_data_x;
242
  std::vector<int>                tmp_data_y;
243
244
  static constexpr double         m_tapFilter[3]                = { 1, 2, 1 };
245
  static constexpr double         m_normTap                     = 4.0;
246
247
  // fg model parameters
248
  int                             m_log2ScaleFactor;
249
  std::vector<std::array<int, 3>> finalIntervalsandScalingFactors;   // lower_bound, upper_bound, scaling_factor
250
  SeiFgc::CompModel               m_compModel[ComponentID::MAX_NUM_COMP];
251
252
  const PelStorage                *m_originalBuf             = nullptr;
253
  const PelStorage                *m_workingBuf              = nullptr;
254
  PelStorage                      *m_maskBuf                 = nullptr;
255
  PelStorage                      *m_grainEstimateBuf        = nullptr;
256
  PelStorage                      *m_workingBufSubsampled2   = nullptr;
257
  PelStorage                      *m_maskSubsampled2         = nullptr;
258
  PelStorage                      *m_workingBufSubsampled4   = nullptr;
259
  PelStorage                      *m_maskSubsampled4         = nullptr;
260
  PelStorage                      *m_maskUpsampled           = nullptr;
261
  // for DCT
262
  TCoeff                          *m_DCTinout                = nullptr;
263
  TCoeff                          *m_DCTtemp                 = nullptr;
264
265
  void findMask ( ComponentID compID );
266
267
  void blockTransform ( CoeffBuf& currentCoeffBuf,
268
                        int offsetX,
269
                        int offsetY,
270
                        uint32_t bitDepth,
271
                        ComponentID compId );
272
273
  void adaptiveSampling ( int bins,
274
                          double threshold,
275
                          std::vector<int>& significantIndices,
276
                          bool isRow,
277
                          int startIdx );
278
279
  void estimateCutoffFreqAdaptive ( ComponentID compID );
280
281
  void estimateScalingFactors ( uint32_t bitDepth,
282
                                ComponentID compID );
283
284
  bool fitFunction ( int order,
285
                     int bitDepth,
286
                     bool second_pass );
287
288
  void avgScalingVec ( int bitDepth );
289
290
  bool lloydMax ( double& distortion,
291
                  int bitDepth );
292
293
  void quantize ( std::vector<double>& quantizedVec,
294
                  double& distortion,
295
                  double partition[],
296
                  double codebook[] );
297
298
  void extendPoints ( int bitDepth );
299
300
  void setEstimatedParameters ( uint32_t bitDepth,
301
                                ComponentID compID );
302
303
  void defineIntervalsAndScalings ( int bitDepth );
304
305
  void scaleDown ( int bitDepth );
306
307
  void confirmIntervals ( );
308
309
  long double ldpow ( long double n,
310
                      unsigned p );
311
312
  int countEdges ( int windowSize,
313
                   int offsetX,
314
                   int offsetY,
315
                   ComponentID compID );
316
317
  void subsample ( PelStorage& output,
318
                   const int factor = 2,
319
                   const int padding = 0, 
320
                   ComponentID compID = COMP_Y ) const;
321
322
  void upsample ( const PelStorage& input,
323
                  const int factor = 2,
324
                  const int padding = 0,
325
                  ComponentID compID = COMP_Y ) const;
326
327
  void combineMasks ( ComponentID compId );
328
329
  void suppressLowIntensity ( const PelStorage& buff1,
330
                              PelStorage& buff2,
331
                              uint32_t bitDepth,
332
                              ComponentID compId );
333
334
#if ENABLE_SIMD_OPT_FGA && defined( TARGET_SIMD_X86 )
335
  void initFGAnalyzerX86();
336
  template <X86_VEXT vext>
337
  void _initFGAnalyzerX86();
338
#endif
339
#if ENABLE_SIMD_OPT_FGA && defined( TARGET_SIMD_ARM )
340
  void initFGAnalyzerARM();
341
  template <ARM_VEXT vext>
342
  void _initFGAnalyzerARM();
343
#endif
344
};
345
346
} // namespace vvenc
347
348
#endif // __SEIFILMGRAINANALYZER__
349
350