/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 | | |