Coverage Report

Created: 2026-04-01 07:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/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();
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
private:
199
  int                             *m_bitDepths;
200
  ChromaFormat                    m_inputChromaFormat;
201
  bool                            m_doAnalysis[ComponentID::MAX_NUM_COMP] = { true, true, true };
202
203
  Canny                           m_edgeDetector;
204
  Morph                           m_morphOperation;
205
  double                          m_lowIntensityRatio            = 0.1;           // supress everything below 0.1*maxIntensityOffset
206
207
  CoeffBuf                        * m_dctGrainBlockList;
208
  TCoeff                          * m_coeffBuf;
209
  int                             m_numDctGrainBlocks;
210
211
  std::vector<double>             coeffs;
212
  std::vector<double>             scalingVec;
213
  std::vector<int>                quantVec;
214
215
  std::vector<int>                vecMean;
216
  std::vector<int>                vecVar;
217
218
  double                          meanSquaredDctGrain[DATA_BASE_SIZE][DATA_BASE_SIZE];
219
220
  /* Interval points for fitFunction */
221
  std::vector<int>                vec_mean_intensity;
222
  std::vector<int>                vec_variance_intensity;
223
  std::vector<int>                element_number_per_interval;
224
  std::vector<int>                tmp_data_x;
225
  std::vector<int>                tmp_data_y;
226
227
  static constexpr double         m_tapFilter[3]                = { 1, 2, 1 };
228
  static constexpr double         m_normTap                     = 4.0;
229
230
  // fg model parameters
231
  int                             m_log2ScaleFactor;
232
  std::vector<std::array<int, 3>> finalIntervalsandScalingFactors;   // lower_bound, upper_bound, scaling_factor
233
  SeiFgc::CompModel               m_compModel[ComponentID::MAX_NUM_COMP];
234
235
  const PelStorage                *m_originalBuf             = nullptr;
236
  const PelStorage                *m_workingBuf              = nullptr;
237
  PelStorage                      *m_maskBuf                 = nullptr;
238
  PelStorage                      *m_grainEstimateBuf        = nullptr;
239
  PelStorage                      *m_workingBufSubsampled2   = nullptr;
240
  PelStorage                      *m_maskSubsampled2         = nullptr;
241
  PelStorage                      *m_workingBufSubsampled4   = nullptr;
242
  PelStorage                      *m_maskSubsampled4         = nullptr;
243
  PelStorage                      *m_maskUpsampled           = nullptr;
244
  // for DCT
245
  TCoeff                          *m_DCTinout                = nullptr;
246
  TCoeff                          *m_DCTtemp                 = nullptr;
247
248
  void findMask ( ComponentID compID );
249
250
  void blockTransform ( CoeffBuf& currentCoeffBuf,
251
                        int offsetX,
252
                        int offsetY,
253
                        uint32_t bitDepth,
254
                        ComponentID compId );
255
256
  void adaptiveSampling ( int bins,
257
                          double threshold,
258
                          std::vector<int>& significantIndices,
259
                          bool isRow,
260
                          int startIdx );
261
262
  void estimateCutoffFreqAdaptive ( ComponentID compID );
263
264
  void estimateScalingFactors ( uint32_t bitDepth,
265
                                ComponentID compID );
266
267
  bool fitFunction ( int order,
268
                     int bitDepth,
269
                     bool second_pass );
270
271
  void avgScalingVec ( int bitDepth );
272
273
  bool lloydMax ( double& distortion,
274
                  int bitDepth );
275
276
  void quantize ( std::vector<double>& quantizedVec,
277
                  double& distortion,
278
                  double partition[],
279
                  double codebook[] );
280
281
  void extendPoints ( int bitDepth );
282
283
  void setEstimatedParameters ( uint32_t bitDepth,
284
                                ComponentID compID );
285
286
  void defineIntervalsAndScalings ( int bitDepth );
287
288
  void scaleDown ( int bitDepth );
289
290
  void confirmIntervals ( );
291
292
  long double ldpow ( long double n,
293
                      unsigned p );
294
295
  int countEdges ( int windowSize,
296
                   int offsetX,
297
                   int offsetY,
298
                   ComponentID compID );
299
300
  void subsample ( PelStorage& output,
301
                   const int factor = 2,
302
                   const int padding = 0, 
303
                   ComponentID compID = COMP_Y ) const;
304
305
  void upsample ( const PelStorage& input,
306
                  const int factor = 2,
307
                  const int padding = 0,
308
                  ComponentID compID = COMP_Y ) const;
309
310
  void combineMasks ( ComponentID compId );
311
312
  void suppressLowIntensity ( const PelStorage& buff1,
313
                              PelStorage& buff2,
314
                              uint32_t bitDepth,
315
                              ComponentID compId );
316
317
  double (*calcVar) ( const Pel* org,
318
                      const ptrdiff_t origStride,
319
                      const int w,
320
                      const int h );
321
322
  int (*calcMean) ( const Pel* org,
323
                    const ptrdiff_t origStride,
324
                    const int w,
325
                    const int h );
326
327
  void (*fastDCT2_64) ( const TCoeff* src,
328
                        TCoeff* dst,
329
                        int shift,
330
                        int line,
331
                        int iSkipLine,
332
                        int iSkipLine2 );
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
};
340
341
} // namespace vvenc
342
343
#endif // __SEIFILMGRAINANALYZER__
344
345