1*09537850SAkhilesh Sanikop // Copyright 2019 The libgav1 Authors
2*09537850SAkhilesh Sanikop //
3*09537850SAkhilesh Sanikop // Licensed under the Apache License, Version 2.0 (the "License");
4*09537850SAkhilesh Sanikop // you may not use this file except in compliance with the License.
5*09537850SAkhilesh Sanikop // You may obtain a copy of the License at
6*09537850SAkhilesh Sanikop //
7*09537850SAkhilesh Sanikop // http://www.apache.org/licenses/LICENSE-2.0
8*09537850SAkhilesh Sanikop //
9*09537850SAkhilesh Sanikop // Unless required by applicable law or agreed to in writing, software
10*09537850SAkhilesh Sanikop // distributed under the License is distributed on an "AS IS" BASIS,
11*09537850SAkhilesh Sanikop // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*09537850SAkhilesh Sanikop // See the License for the specific language governing permissions and
13*09537850SAkhilesh Sanikop // limitations under the License.
14*09537850SAkhilesh Sanikop
15*09537850SAkhilesh Sanikop #include "src/dsp/film_grain.h"
16*09537850SAkhilesh Sanikop
17*09537850SAkhilesh Sanikop #include <algorithm>
18*09537850SAkhilesh Sanikop #include <cassert>
19*09537850SAkhilesh Sanikop #include <cstddef>
20*09537850SAkhilesh Sanikop #include <cstdint>
21*09537850SAkhilesh Sanikop #include <cstring>
22*09537850SAkhilesh Sanikop
23*09537850SAkhilesh Sanikop #include "src/dsp/constants.h"
24*09537850SAkhilesh Sanikop #include "src/dsp/dsp.h"
25*09537850SAkhilesh Sanikop #include "src/dsp/film_grain_common.h"
26*09537850SAkhilesh Sanikop #include "src/utils/array_2d.h"
27*09537850SAkhilesh Sanikop #include "src/utils/common.h"
28*09537850SAkhilesh Sanikop #include "src/utils/compiler_attributes.h"
29*09537850SAkhilesh Sanikop #include "src/utils/constants.h"
30*09537850SAkhilesh Sanikop #include "src/utils/memory.h"
31*09537850SAkhilesh Sanikop #include "src/utils/types.h"
32*09537850SAkhilesh Sanikop
33*09537850SAkhilesh Sanikop namespace libgav1 {
34*09537850SAkhilesh Sanikop namespace dsp {
35*09537850SAkhilesh Sanikop namespace film_grain {
36*09537850SAkhilesh Sanikop namespace {
37*09537850SAkhilesh Sanikop
38*09537850SAkhilesh Sanikop template <int bitdepth>
InitializeScalingLookupTable_C(int num_points,const uint8_t point_value[],const uint8_t point_scaling[],int16_t * scaling_lut,const int scaling_lut_length)39*09537850SAkhilesh Sanikop void InitializeScalingLookupTable_C(int num_points, const uint8_t point_value[],
40*09537850SAkhilesh Sanikop const uint8_t point_scaling[],
41*09537850SAkhilesh Sanikop int16_t* scaling_lut,
42*09537850SAkhilesh Sanikop const int scaling_lut_length) {
43*09537850SAkhilesh Sanikop if (num_points == 0) {
44*09537850SAkhilesh Sanikop memset(scaling_lut, 0, sizeof(scaling_lut[0]) * scaling_lut_length);
45*09537850SAkhilesh Sanikop return;
46*09537850SAkhilesh Sanikop }
47*09537850SAkhilesh Sanikop constexpr int index_shift = (bitdepth == kBitdepth10) ? 2 : 0;
48*09537850SAkhilesh Sanikop static_assert(sizeof(scaling_lut[0]) == 2, "");
49*09537850SAkhilesh Sanikop Memset(scaling_lut, point_scaling[0],
50*09537850SAkhilesh Sanikop std::max(static_cast<int>(point_value[0]), 1) << index_shift);
51*09537850SAkhilesh Sanikop for (int i = 0; i < num_points - 1; ++i) {
52*09537850SAkhilesh Sanikop const int delta_y = point_scaling[i + 1] - point_scaling[i];
53*09537850SAkhilesh Sanikop const int delta_x = point_value[i + 1] - point_value[i];
54*09537850SAkhilesh Sanikop const int delta = delta_y * ((65536 + (delta_x >> 1)) / delta_x);
55*09537850SAkhilesh Sanikop for (int x = 0; x < delta_x; ++x) {
56*09537850SAkhilesh Sanikop const int v = point_scaling[i] + ((x * delta + 32768) >> 16);
57*09537850SAkhilesh Sanikop assert(v >= 0 && v <= UINT8_MAX);
58*09537850SAkhilesh Sanikop const int lut_index = (point_value[i] + x) << index_shift;
59*09537850SAkhilesh Sanikop scaling_lut[lut_index] = v;
60*09537850SAkhilesh Sanikop }
61*09537850SAkhilesh Sanikop }
62*09537850SAkhilesh Sanikop const int16_t last_point_value = point_value[num_points - 1];
63*09537850SAkhilesh Sanikop const int x_base = last_point_value << index_shift;
64*09537850SAkhilesh Sanikop Memset(&scaling_lut[x_base], point_scaling[num_points - 1],
65*09537850SAkhilesh Sanikop scaling_lut_length - x_base);
66*09537850SAkhilesh Sanikop // Fill in the gaps.
67*09537850SAkhilesh Sanikop if (bitdepth == kBitdepth10) {
68*09537850SAkhilesh Sanikop for (int x = 4; x < x_base + 4; x += 4) {
69*09537850SAkhilesh Sanikop const int start = scaling_lut[x - 4];
70*09537850SAkhilesh Sanikop const int end = scaling_lut[x];
71*09537850SAkhilesh Sanikop const int delta = end - start;
72*09537850SAkhilesh Sanikop scaling_lut[x - 3] = start + RightShiftWithRounding(delta, 2);
73*09537850SAkhilesh Sanikop scaling_lut[x - 2] = start + RightShiftWithRounding(2 * delta, 2);
74*09537850SAkhilesh Sanikop scaling_lut[x - 1] = start + RightShiftWithRounding(3 * delta, 2);
75*09537850SAkhilesh Sanikop }
76*09537850SAkhilesh Sanikop }
77*09537850SAkhilesh Sanikop }
78*09537850SAkhilesh Sanikop
79*09537850SAkhilesh Sanikop // Section 7.18.3.5.
80*09537850SAkhilesh Sanikop template <int bitdepth>
ScaleLut(const int16_t * scaling_lut,int index)81*09537850SAkhilesh Sanikop int ScaleLut(const int16_t* scaling_lut, int index) {
82*09537850SAkhilesh Sanikop if (bitdepth <= kBitdepth10) {
83*09537850SAkhilesh Sanikop assert(index < kScalingLookupTableSize << (bitdepth - 2));
84*09537850SAkhilesh Sanikop return scaling_lut[index];
85*09537850SAkhilesh Sanikop }
86*09537850SAkhilesh Sanikop // Performs a piecewise linear interpolation into the scaling table.
87*09537850SAkhilesh Sanikop const int shift = bitdepth - kBitdepth8;
88*09537850SAkhilesh Sanikop const int quotient = index >> shift;
89*09537850SAkhilesh Sanikop const int remainder = index - (quotient << shift);
90*09537850SAkhilesh Sanikop assert(quotient + 1 < kScalingLookupTableSize);
91*09537850SAkhilesh Sanikop const int start = scaling_lut[quotient];
92*09537850SAkhilesh Sanikop const int end = scaling_lut[quotient + 1];
93*09537850SAkhilesh Sanikop return start + RightShiftWithRounding((end - start) * remainder, shift);
94*09537850SAkhilesh Sanikop }
95*09537850SAkhilesh Sanikop
96*09537850SAkhilesh Sanikop // Applies an auto-regressive filter to the white noise in luma_grain.
97*09537850SAkhilesh Sanikop template <int bitdepth, typename GrainType>
ApplyAutoRegressiveFilterToLumaGrain_C(const FilmGrainParams & params,void * luma_grain_buffer)98*09537850SAkhilesh Sanikop void ApplyAutoRegressiveFilterToLumaGrain_C(const FilmGrainParams& params,
99*09537850SAkhilesh Sanikop void* luma_grain_buffer) {
100*09537850SAkhilesh Sanikop auto* luma_grain = static_cast<GrainType*>(luma_grain_buffer);
101*09537850SAkhilesh Sanikop const int grain_min = GetGrainMin<bitdepth>();
102*09537850SAkhilesh Sanikop const int grain_max = GetGrainMax<bitdepth>();
103*09537850SAkhilesh Sanikop const int auto_regression_coeff_lag = params.auto_regression_coeff_lag;
104*09537850SAkhilesh Sanikop assert(auto_regression_coeff_lag > 0 && auto_regression_coeff_lag <= 3);
105*09537850SAkhilesh Sanikop // A pictorial representation of the auto-regressive filter for various values
106*09537850SAkhilesh Sanikop // of auto_regression_coeff_lag. The letter 'O' represents the current sample.
107*09537850SAkhilesh Sanikop // (The filter always operates on the current sample with filter
108*09537850SAkhilesh Sanikop // coefficient 1.) The letters 'X' represent the neighboring samples that the
109*09537850SAkhilesh Sanikop // filter operates on.
110*09537850SAkhilesh Sanikop //
111*09537850SAkhilesh Sanikop // auto_regression_coeff_lag == 3:
112*09537850SAkhilesh Sanikop // X X X X X X X
113*09537850SAkhilesh Sanikop // X X X X X X X
114*09537850SAkhilesh Sanikop // X X X X X X X
115*09537850SAkhilesh Sanikop // X X X O
116*09537850SAkhilesh Sanikop // auto_regression_coeff_lag == 2:
117*09537850SAkhilesh Sanikop // X X X X X
118*09537850SAkhilesh Sanikop // X X X X X
119*09537850SAkhilesh Sanikop // X X O
120*09537850SAkhilesh Sanikop // auto_regression_coeff_lag == 1:
121*09537850SAkhilesh Sanikop // X X X
122*09537850SAkhilesh Sanikop // X O
123*09537850SAkhilesh Sanikop // auto_regression_coeff_lag == 0:
124*09537850SAkhilesh Sanikop // O
125*09537850SAkhilesh Sanikop //
126*09537850SAkhilesh Sanikop // Note that if auto_regression_coeff_lag is 0, the filter is the identity
127*09537850SAkhilesh Sanikop // filter and therefore can be skipped. This implementation assumes it is not
128*09537850SAkhilesh Sanikop // called in that case.
129*09537850SAkhilesh Sanikop const int shift = params.auto_regression_shift;
130*09537850SAkhilesh Sanikop for (int y = kAutoRegressionBorder; y < kLumaHeight; ++y) {
131*09537850SAkhilesh Sanikop for (int x = kAutoRegressionBorder; x < kLumaWidth - kAutoRegressionBorder;
132*09537850SAkhilesh Sanikop ++x) {
133*09537850SAkhilesh Sanikop int sum = 0;
134*09537850SAkhilesh Sanikop int pos = 0;
135*09537850SAkhilesh Sanikop int delta_row = -auto_regression_coeff_lag;
136*09537850SAkhilesh Sanikop // The last iteration (delta_row == 0) is shorter and is handled
137*09537850SAkhilesh Sanikop // separately.
138*09537850SAkhilesh Sanikop do {
139*09537850SAkhilesh Sanikop int delta_column = -auto_regression_coeff_lag;
140*09537850SAkhilesh Sanikop do {
141*09537850SAkhilesh Sanikop const int coeff = params.auto_regression_coeff_y[pos];
142*09537850SAkhilesh Sanikop sum += luma_grain[(y + delta_row) * kLumaWidth + (x + delta_column)] *
143*09537850SAkhilesh Sanikop coeff;
144*09537850SAkhilesh Sanikop ++pos;
145*09537850SAkhilesh Sanikop } while (++delta_column <= auto_regression_coeff_lag);
146*09537850SAkhilesh Sanikop } while (++delta_row < 0);
147*09537850SAkhilesh Sanikop // Last iteration: delta_row == 0.
148*09537850SAkhilesh Sanikop {
149*09537850SAkhilesh Sanikop int delta_column = -auto_regression_coeff_lag;
150*09537850SAkhilesh Sanikop do {
151*09537850SAkhilesh Sanikop const int coeff = params.auto_regression_coeff_y[pos];
152*09537850SAkhilesh Sanikop sum += luma_grain[y * kLumaWidth + (x + delta_column)] * coeff;
153*09537850SAkhilesh Sanikop ++pos;
154*09537850SAkhilesh Sanikop } while (++delta_column < 0);
155*09537850SAkhilesh Sanikop }
156*09537850SAkhilesh Sanikop luma_grain[y * kLumaWidth + x] = Clip3(
157*09537850SAkhilesh Sanikop luma_grain[y * kLumaWidth + x] + RightShiftWithRounding(sum, shift),
158*09537850SAkhilesh Sanikop grain_min, grain_max);
159*09537850SAkhilesh Sanikop }
160*09537850SAkhilesh Sanikop }
161*09537850SAkhilesh Sanikop }
162*09537850SAkhilesh Sanikop
163*09537850SAkhilesh Sanikop template <int bitdepth, typename GrainType, int auto_regression_coeff_lag,
164*09537850SAkhilesh Sanikop bool use_luma>
ApplyAutoRegressiveFilterToChromaGrains_C(const FilmGrainParams & params,const void * LIBGAV1_RESTRICT luma_grain_buffer,int subsampling_x,int subsampling_y,void * LIBGAV1_RESTRICT u_grain_buffer,void * LIBGAV1_RESTRICT v_grain_buffer)165*09537850SAkhilesh Sanikop void ApplyAutoRegressiveFilterToChromaGrains_C(
166*09537850SAkhilesh Sanikop const FilmGrainParams& params,
167*09537850SAkhilesh Sanikop const void* LIBGAV1_RESTRICT luma_grain_buffer, int subsampling_x,
168*09537850SAkhilesh Sanikop int subsampling_y, void* LIBGAV1_RESTRICT u_grain_buffer,
169*09537850SAkhilesh Sanikop void* LIBGAV1_RESTRICT v_grain_buffer) {
170*09537850SAkhilesh Sanikop static_assert(
171*09537850SAkhilesh Sanikop auto_regression_coeff_lag >= 0 && auto_regression_coeff_lag <= 3,
172*09537850SAkhilesh Sanikop "Unsupported autoregression lag for chroma.");
173*09537850SAkhilesh Sanikop const auto* luma_grain = static_cast<const GrainType*>(luma_grain_buffer);
174*09537850SAkhilesh Sanikop const int grain_min = GetGrainMin<bitdepth>();
175*09537850SAkhilesh Sanikop const int grain_max = GetGrainMax<bitdepth>();
176*09537850SAkhilesh Sanikop auto* u_grain = static_cast<GrainType*>(u_grain_buffer);
177*09537850SAkhilesh Sanikop auto* v_grain = static_cast<GrainType*>(v_grain_buffer);
178*09537850SAkhilesh Sanikop const int shift = params.auto_regression_shift;
179*09537850SAkhilesh Sanikop const int chroma_height =
180*09537850SAkhilesh Sanikop (subsampling_y == 0) ? kMaxChromaHeight : kMinChromaHeight;
181*09537850SAkhilesh Sanikop const int chroma_width =
182*09537850SAkhilesh Sanikop (subsampling_x == 0) ? kMaxChromaWidth : kMinChromaWidth;
183*09537850SAkhilesh Sanikop for (int y = kAutoRegressionBorder; y < chroma_height; ++y) {
184*09537850SAkhilesh Sanikop const int luma_y =
185*09537850SAkhilesh Sanikop ((y - kAutoRegressionBorder) << subsampling_y) + kAutoRegressionBorder;
186*09537850SAkhilesh Sanikop for (int x = kAutoRegressionBorder;
187*09537850SAkhilesh Sanikop x < chroma_width - kAutoRegressionBorder; ++x) {
188*09537850SAkhilesh Sanikop int sum_u = 0;
189*09537850SAkhilesh Sanikop int sum_v = 0;
190*09537850SAkhilesh Sanikop int pos = 0;
191*09537850SAkhilesh Sanikop int delta_row = -auto_regression_coeff_lag;
192*09537850SAkhilesh Sanikop do {
193*09537850SAkhilesh Sanikop int delta_column = -auto_regression_coeff_lag;
194*09537850SAkhilesh Sanikop do {
195*09537850SAkhilesh Sanikop if (delta_row == 0 && delta_column == 0) {
196*09537850SAkhilesh Sanikop break;
197*09537850SAkhilesh Sanikop }
198*09537850SAkhilesh Sanikop const int coeff_u = params.auto_regression_coeff_u[pos];
199*09537850SAkhilesh Sanikop const int coeff_v = params.auto_regression_coeff_v[pos];
200*09537850SAkhilesh Sanikop sum_u +=
201*09537850SAkhilesh Sanikop u_grain[(y + delta_row) * chroma_width + (x + delta_column)] *
202*09537850SAkhilesh Sanikop coeff_u;
203*09537850SAkhilesh Sanikop sum_v +=
204*09537850SAkhilesh Sanikop v_grain[(y + delta_row) * chroma_width + (x + delta_column)] *
205*09537850SAkhilesh Sanikop coeff_v;
206*09537850SAkhilesh Sanikop ++pos;
207*09537850SAkhilesh Sanikop } while (++delta_column <= auto_regression_coeff_lag);
208*09537850SAkhilesh Sanikop } while (++delta_row <= 0);
209*09537850SAkhilesh Sanikop if (use_luma) {
210*09537850SAkhilesh Sanikop int luma = 0;
211*09537850SAkhilesh Sanikop const int luma_x = ((x - kAutoRegressionBorder) << subsampling_x) +
212*09537850SAkhilesh Sanikop kAutoRegressionBorder;
213*09537850SAkhilesh Sanikop int i = 0;
214*09537850SAkhilesh Sanikop do {
215*09537850SAkhilesh Sanikop int j = 0;
216*09537850SAkhilesh Sanikop do {
217*09537850SAkhilesh Sanikop luma += luma_grain[(luma_y + i) * kLumaWidth + (luma_x + j)];
218*09537850SAkhilesh Sanikop } while (++j <= subsampling_x);
219*09537850SAkhilesh Sanikop } while (++i <= subsampling_y);
220*09537850SAkhilesh Sanikop luma = SubsampledValue(luma, subsampling_x + subsampling_y);
221*09537850SAkhilesh Sanikop const int coeff_u = params.auto_regression_coeff_u[pos];
222*09537850SAkhilesh Sanikop const int coeff_v = params.auto_regression_coeff_v[pos];
223*09537850SAkhilesh Sanikop sum_u += luma * coeff_u;
224*09537850SAkhilesh Sanikop sum_v += luma * coeff_v;
225*09537850SAkhilesh Sanikop }
226*09537850SAkhilesh Sanikop u_grain[y * chroma_width + x] = Clip3(
227*09537850SAkhilesh Sanikop u_grain[y * chroma_width + x] + RightShiftWithRounding(sum_u, shift),
228*09537850SAkhilesh Sanikop grain_min, grain_max);
229*09537850SAkhilesh Sanikop v_grain[y * chroma_width + x] = Clip3(
230*09537850SAkhilesh Sanikop v_grain[y * chroma_width + x] + RightShiftWithRounding(sum_v, shift),
231*09537850SAkhilesh Sanikop grain_min, grain_max);
232*09537850SAkhilesh Sanikop }
233*09537850SAkhilesh Sanikop }
234*09537850SAkhilesh Sanikop }
235*09537850SAkhilesh Sanikop
236*09537850SAkhilesh Sanikop // This implementation is for the condition overlap_flag == false.
237*09537850SAkhilesh Sanikop template <int bitdepth, typename GrainType>
ConstructNoiseStripes_C(const void * LIBGAV1_RESTRICT grain_buffer,int grain_seed,int width,int height,int subsampling_x,int subsampling_y,void * LIBGAV1_RESTRICT noise_stripes_buffer)238*09537850SAkhilesh Sanikop void ConstructNoiseStripes_C(const void* LIBGAV1_RESTRICT grain_buffer,
239*09537850SAkhilesh Sanikop int grain_seed, int width, int height,
240*09537850SAkhilesh Sanikop int subsampling_x, int subsampling_y,
241*09537850SAkhilesh Sanikop void* LIBGAV1_RESTRICT noise_stripes_buffer) {
242*09537850SAkhilesh Sanikop auto* noise_stripes =
243*09537850SAkhilesh Sanikop static_cast<Array2DView<GrainType>*>(noise_stripes_buffer);
244*09537850SAkhilesh Sanikop const auto* grain = static_cast<const GrainType*>(grain_buffer);
245*09537850SAkhilesh Sanikop const int half_width = DivideBy2(width + 1);
246*09537850SAkhilesh Sanikop const int half_height = DivideBy2(height + 1);
247*09537850SAkhilesh Sanikop assert(half_width > 0);
248*09537850SAkhilesh Sanikop assert(half_height > 0);
249*09537850SAkhilesh Sanikop static_assert(kLumaWidth == kMaxChromaWidth,
250*09537850SAkhilesh Sanikop "kLumaWidth width should be equal to kMaxChromaWidth");
251*09537850SAkhilesh Sanikop const int grain_width =
252*09537850SAkhilesh Sanikop (subsampling_x == 0) ? kMaxChromaWidth : kMinChromaWidth;
253*09537850SAkhilesh Sanikop const int plane_width = (width + subsampling_x) >> subsampling_x;
254*09537850SAkhilesh Sanikop constexpr int kNoiseStripeHeight = 34;
255*09537850SAkhilesh Sanikop int luma_num = 0;
256*09537850SAkhilesh Sanikop int y = 0;
257*09537850SAkhilesh Sanikop do {
258*09537850SAkhilesh Sanikop GrainType* const noise_stripe = (*noise_stripes)[luma_num];
259*09537850SAkhilesh Sanikop uint16_t seed = grain_seed;
260*09537850SAkhilesh Sanikop seed ^= ((luma_num * 37 + 178) & 255) << 8;
261*09537850SAkhilesh Sanikop seed ^= ((luma_num * 173 + 105) & 255);
262*09537850SAkhilesh Sanikop int x = 0;
263*09537850SAkhilesh Sanikop do {
264*09537850SAkhilesh Sanikop const int rand = GetFilmGrainRandomNumber(8, &seed);
265*09537850SAkhilesh Sanikop const int offset_x = rand >> 4;
266*09537850SAkhilesh Sanikop const int offset_y = rand & 15;
267*09537850SAkhilesh Sanikop const int plane_offset_x =
268*09537850SAkhilesh Sanikop (subsampling_x != 0) ? 6 + offset_x : 9 + offset_x * 2;
269*09537850SAkhilesh Sanikop const int plane_offset_y =
270*09537850SAkhilesh Sanikop (subsampling_y != 0) ? 6 + offset_y : 9 + offset_y * 2;
271*09537850SAkhilesh Sanikop int i = 0;
272*09537850SAkhilesh Sanikop do {
273*09537850SAkhilesh Sanikop // Section 7.18.3.5 says:
274*09537850SAkhilesh Sanikop // noiseStripe[ lumaNum ][ 0 ] is 34 samples high and w samples
275*09537850SAkhilesh Sanikop // wide (a few additional samples across are actually written to
276*09537850SAkhilesh Sanikop // the array, but these are never read) ...
277*09537850SAkhilesh Sanikop //
278*09537850SAkhilesh Sanikop // Note: The warning in the parentheses also applies to
279*09537850SAkhilesh Sanikop // noiseStripe[ lumaNum ][ 1 ] and noiseStripe[ lumaNum ][ 2 ].
280*09537850SAkhilesh Sanikop //
281*09537850SAkhilesh Sanikop // Writes beyond the width of each row could happen below. To
282*09537850SAkhilesh Sanikop // prevent those writes, we clip the number of pixels to copy against
283*09537850SAkhilesh Sanikop // the remaining width.
284*09537850SAkhilesh Sanikop const int copy_size =
285*09537850SAkhilesh Sanikop std::min(kNoiseStripeHeight >> subsampling_x,
286*09537850SAkhilesh Sanikop plane_width - (x << (1 - subsampling_x)));
287*09537850SAkhilesh Sanikop memcpy(&noise_stripe[i * plane_width + (x << (1 - subsampling_x))],
288*09537850SAkhilesh Sanikop &grain[(plane_offset_y + i) * grain_width + plane_offset_x],
289*09537850SAkhilesh Sanikop copy_size * sizeof(noise_stripe[0]));
290*09537850SAkhilesh Sanikop } while (++i < (kNoiseStripeHeight >> subsampling_y));
291*09537850SAkhilesh Sanikop x += 16;
292*09537850SAkhilesh Sanikop } while (x < half_width);
293*09537850SAkhilesh Sanikop
294*09537850SAkhilesh Sanikop ++luma_num;
295*09537850SAkhilesh Sanikop y += 16;
296*09537850SAkhilesh Sanikop } while (y < half_height);
297*09537850SAkhilesh Sanikop }
298*09537850SAkhilesh Sanikop
299*09537850SAkhilesh Sanikop // This implementation is for the condition overlap_flag == true.
300*09537850SAkhilesh Sanikop template <int bitdepth, typename GrainType>
ConstructNoiseStripesWithOverlap_C(const void * LIBGAV1_RESTRICT grain_buffer,int grain_seed,int width,int height,int subsampling_x,int subsampling_y,void * LIBGAV1_RESTRICT noise_stripes_buffer)301*09537850SAkhilesh Sanikop void ConstructNoiseStripesWithOverlap_C(
302*09537850SAkhilesh Sanikop const void* LIBGAV1_RESTRICT grain_buffer, int grain_seed, int width,
303*09537850SAkhilesh Sanikop int height, int subsampling_x, int subsampling_y,
304*09537850SAkhilesh Sanikop void* LIBGAV1_RESTRICT noise_stripes_buffer) {
305*09537850SAkhilesh Sanikop auto* noise_stripes =
306*09537850SAkhilesh Sanikop static_cast<Array2DView<GrainType>*>(noise_stripes_buffer);
307*09537850SAkhilesh Sanikop const auto* grain = static_cast<const GrainType*>(grain_buffer);
308*09537850SAkhilesh Sanikop const int half_width = DivideBy2(width + 1);
309*09537850SAkhilesh Sanikop const int half_height = DivideBy2(height + 1);
310*09537850SAkhilesh Sanikop assert(half_width > 0);
311*09537850SAkhilesh Sanikop assert(half_height > 0);
312*09537850SAkhilesh Sanikop static_assert(kLumaWidth == kMaxChromaWidth,
313*09537850SAkhilesh Sanikop "kLumaWidth width should be equal to kMaxChromaWidth");
314*09537850SAkhilesh Sanikop const int grain_width =
315*09537850SAkhilesh Sanikop (subsampling_x == 0) ? kMaxChromaWidth : kMinChromaWidth;
316*09537850SAkhilesh Sanikop const int plane_width = (width + subsampling_x) >> subsampling_x;
317*09537850SAkhilesh Sanikop constexpr int kNoiseStripeHeight = 34;
318*09537850SAkhilesh Sanikop int luma_num = 0;
319*09537850SAkhilesh Sanikop int y = 0;
320*09537850SAkhilesh Sanikop do {
321*09537850SAkhilesh Sanikop GrainType* const noise_stripe = (*noise_stripes)[luma_num];
322*09537850SAkhilesh Sanikop uint16_t seed = grain_seed;
323*09537850SAkhilesh Sanikop seed ^= ((luma_num * 37 + 178) & 255) << 8;
324*09537850SAkhilesh Sanikop seed ^= ((luma_num * 173 + 105) & 255);
325*09537850SAkhilesh Sanikop // Begin special iteration for x == 0.
326*09537850SAkhilesh Sanikop const int rand = GetFilmGrainRandomNumber(8, &seed);
327*09537850SAkhilesh Sanikop const int offset_x = rand >> 4;
328*09537850SAkhilesh Sanikop const int offset_y = rand & 15;
329*09537850SAkhilesh Sanikop const int plane_offset_x =
330*09537850SAkhilesh Sanikop (subsampling_x != 0) ? 6 + offset_x : 9 + offset_x * 2;
331*09537850SAkhilesh Sanikop const int plane_offset_y =
332*09537850SAkhilesh Sanikop (subsampling_y != 0) ? 6 + offset_y : 9 + offset_y * 2;
333*09537850SAkhilesh Sanikop // The overlap computation only occurs when x > 0, so it is omitted here.
334*09537850SAkhilesh Sanikop int i = 0;
335*09537850SAkhilesh Sanikop do {
336*09537850SAkhilesh Sanikop const int copy_size =
337*09537850SAkhilesh Sanikop std::min(kNoiseStripeHeight >> subsampling_x, plane_width);
338*09537850SAkhilesh Sanikop memcpy(&noise_stripe[i * plane_width],
339*09537850SAkhilesh Sanikop &grain[(plane_offset_y + i) * grain_width + plane_offset_x],
340*09537850SAkhilesh Sanikop copy_size * sizeof(noise_stripe[0]));
341*09537850SAkhilesh Sanikop } while (++i < (kNoiseStripeHeight >> subsampling_y));
342*09537850SAkhilesh Sanikop // End special iteration for x == 0.
343*09537850SAkhilesh Sanikop for (int x = 16; x < half_width; x += 16) {
344*09537850SAkhilesh Sanikop const int rand = GetFilmGrainRandomNumber(8, &seed);
345*09537850SAkhilesh Sanikop const int offset_x = rand >> 4;
346*09537850SAkhilesh Sanikop const int offset_y = rand & 15;
347*09537850SAkhilesh Sanikop const int plane_offset_x =
348*09537850SAkhilesh Sanikop (subsampling_x != 0) ? 6 + offset_x : 9 + offset_x * 2;
349*09537850SAkhilesh Sanikop const int plane_offset_y =
350*09537850SAkhilesh Sanikop (subsampling_y != 0) ? 6 + offset_y : 9 + offset_y * 2;
351*09537850SAkhilesh Sanikop int i = 0;
352*09537850SAkhilesh Sanikop do {
353*09537850SAkhilesh Sanikop int j = 0;
354*09537850SAkhilesh Sanikop int grain_sample =
355*09537850SAkhilesh Sanikop grain[(plane_offset_y + i) * grain_width + plane_offset_x];
356*09537850SAkhilesh Sanikop // The first pixel(s) of each segment of the noise_stripe are subject to
357*09537850SAkhilesh Sanikop // the "overlap" computation.
358*09537850SAkhilesh Sanikop if (subsampling_x == 0) {
359*09537850SAkhilesh Sanikop // Corresponds to the line in the spec:
360*09537850SAkhilesh Sanikop // if (j < 2 && x > 0)
361*09537850SAkhilesh Sanikop // j = 0
362*09537850SAkhilesh Sanikop int old = noise_stripe[i * plane_width + x * 2];
363*09537850SAkhilesh Sanikop grain_sample = old * 27 + grain_sample * 17;
364*09537850SAkhilesh Sanikop grain_sample =
365*09537850SAkhilesh Sanikop Clip3(RightShiftWithRounding(grain_sample, 5),
366*09537850SAkhilesh Sanikop GetGrainMin<bitdepth>(), GetGrainMax<bitdepth>());
367*09537850SAkhilesh Sanikop noise_stripe[i * plane_width + x * 2] = grain_sample;
368*09537850SAkhilesh Sanikop
369*09537850SAkhilesh Sanikop // This check prevents overwriting for the iteration j = 1. The
370*09537850SAkhilesh Sanikop // continue applies to the i-loop.
371*09537850SAkhilesh Sanikop if (x * 2 + 1 >= plane_width) continue;
372*09537850SAkhilesh Sanikop // j = 1
373*09537850SAkhilesh Sanikop grain_sample =
374*09537850SAkhilesh Sanikop grain[(plane_offset_y + i) * grain_width + plane_offset_x + 1];
375*09537850SAkhilesh Sanikop old = noise_stripe[i * plane_width + x * 2 + 1];
376*09537850SAkhilesh Sanikop grain_sample = old * 17 + grain_sample * 27;
377*09537850SAkhilesh Sanikop grain_sample =
378*09537850SAkhilesh Sanikop Clip3(RightShiftWithRounding(grain_sample, 5),
379*09537850SAkhilesh Sanikop GetGrainMin<bitdepth>(), GetGrainMax<bitdepth>());
380*09537850SAkhilesh Sanikop noise_stripe[i * plane_width + x * 2 + 1] = grain_sample;
381*09537850SAkhilesh Sanikop j = 2;
382*09537850SAkhilesh Sanikop } else {
383*09537850SAkhilesh Sanikop // Corresponds to the line in the spec:
384*09537850SAkhilesh Sanikop // if (j == 0 && x > 0)
385*09537850SAkhilesh Sanikop const int old = noise_stripe[i * plane_width + x];
386*09537850SAkhilesh Sanikop grain_sample = old * 23 + grain_sample * 22;
387*09537850SAkhilesh Sanikop grain_sample =
388*09537850SAkhilesh Sanikop Clip3(RightShiftWithRounding(grain_sample, 5),
389*09537850SAkhilesh Sanikop GetGrainMin<bitdepth>(), GetGrainMax<bitdepth>());
390*09537850SAkhilesh Sanikop noise_stripe[i * plane_width + x] = grain_sample;
391*09537850SAkhilesh Sanikop j = 1;
392*09537850SAkhilesh Sanikop }
393*09537850SAkhilesh Sanikop // The following covers the rest of the loop over j as described in the
394*09537850SAkhilesh Sanikop // spec.
395*09537850SAkhilesh Sanikop //
396*09537850SAkhilesh Sanikop // Section 7.18.3.5 says:
397*09537850SAkhilesh Sanikop // noiseStripe[ lumaNum ][ 0 ] is 34 samples high and w samples
398*09537850SAkhilesh Sanikop // wide (a few additional samples across are actually written to
399*09537850SAkhilesh Sanikop // the array, but these are never read) ...
400*09537850SAkhilesh Sanikop //
401*09537850SAkhilesh Sanikop // Note: The warning in the parentheses also applies to
402*09537850SAkhilesh Sanikop // noiseStripe[ lumaNum ][ 1 ] and noiseStripe[ lumaNum ][ 2 ].
403*09537850SAkhilesh Sanikop //
404*09537850SAkhilesh Sanikop // Writes beyond the width of each row could happen below. To
405*09537850SAkhilesh Sanikop // prevent those writes, we clip the number of pixels to copy against
406*09537850SAkhilesh Sanikop // the remaining width.
407*09537850SAkhilesh Sanikop const int copy_size =
408*09537850SAkhilesh Sanikop std::min(kNoiseStripeHeight >> subsampling_x,
409*09537850SAkhilesh Sanikop plane_width - (x << (1 - subsampling_x))) -
410*09537850SAkhilesh Sanikop j;
411*09537850SAkhilesh Sanikop memcpy(&noise_stripe[i * plane_width + (x << (1 - subsampling_x)) + j],
412*09537850SAkhilesh Sanikop &grain[(plane_offset_y + i) * grain_width + plane_offset_x + j],
413*09537850SAkhilesh Sanikop copy_size * sizeof(noise_stripe[0]));
414*09537850SAkhilesh Sanikop } while (++i < (kNoiseStripeHeight >> subsampling_y));
415*09537850SAkhilesh Sanikop }
416*09537850SAkhilesh Sanikop
417*09537850SAkhilesh Sanikop ++luma_num;
418*09537850SAkhilesh Sanikop y += 16;
419*09537850SAkhilesh Sanikop } while (y < half_height);
420*09537850SAkhilesh Sanikop }
421*09537850SAkhilesh Sanikop
422*09537850SAkhilesh Sanikop template <int bitdepth, typename GrainType>
WriteOverlapLine_C(const GrainType * LIBGAV1_RESTRICT noise_stripe_row,const GrainType * LIBGAV1_RESTRICT noise_stripe_row_prev,int plane_width,int grain_coeff,int old_coeff,GrainType * LIBGAV1_RESTRICT noise_image_row)423*09537850SAkhilesh Sanikop inline void WriteOverlapLine_C(
424*09537850SAkhilesh Sanikop const GrainType* LIBGAV1_RESTRICT noise_stripe_row,
425*09537850SAkhilesh Sanikop const GrainType* LIBGAV1_RESTRICT noise_stripe_row_prev, int plane_width,
426*09537850SAkhilesh Sanikop int grain_coeff, int old_coeff,
427*09537850SAkhilesh Sanikop GrainType* LIBGAV1_RESTRICT noise_image_row) {
428*09537850SAkhilesh Sanikop int x = 0;
429*09537850SAkhilesh Sanikop do {
430*09537850SAkhilesh Sanikop int grain = noise_stripe_row[x];
431*09537850SAkhilesh Sanikop const int old = noise_stripe_row_prev[x];
432*09537850SAkhilesh Sanikop grain = old * old_coeff + grain * grain_coeff;
433*09537850SAkhilesh Sanikop grain = Clip3(RightShiftWithRounding(grain, 5), GetGrainMin<bitdepth>(),
434*09537850SAkhilesh Sanikop GetGrainMax<bitdepth>());
435*09537850SAkhilesh Sanikop noise_image_row[x] = grain;
436*09537850SAkhilesh Sanikop } while (++x < plane_width);
437*09537850SAkhilesh Sanikop }
438*09537850SAkhilesh Sanikop
439*09537850SAkhilesh Sanikop template <int bitdepth, typename GrainType>
ConstructNoiseImageOverlap_C(const void * LIBGAV1_RESTRICT noise_stripes_buffer,int width,int height,int subsampling_x,int subsampling_y,void * LIBGAV1_RESTRICT noise_image_buffer)440*09537850SAkhilesh Sanikop void ConstructNoiseImageOverlap_C(
441*09537850SAkhilesh Sanikop const void* LIBGAV1_RESTRICT noise_stripes_buffer, int width, int height,
442*09537850SAkhilesh Sanikop int subsampling_x, int subsampling_y,
443*09537850SAkhilesh Sanikop void* LIBGAV1_RESTRICT noise_image_buffer) {
444*09537850SAkhilesh Sanikop const auto* noise_stripes =
445*09537850SAkhilesh Sanikop static_cast<const Array2DView<GrainType>*>(noise_stripes_buffer);
446*09537850SAkhilesh Sanikop auto* noise_image = static_cast<Array2D<GrainType>*>(noise_image_buffer);
447*09537850SAkhilesh Sanikop const int plane_width = (width + subsampling_x) >> subsampling_x;
448*09537850SAkhilesh Sanikop const int plane_height = (height + subsampling_y) >> subsampling_y;
449*09537850SAkhilesh Sanikop const int stripe_height = 32 >> subsampling_y;
450*09537850SAkhilesh Sanikop const int stripe_mask = stripe_height - 1;
451*09537850SAkhilesh Sanikop int y = stripe_height;
452*09537850SAkhilesh Sanikop int luma_num = 1;
453*09537850SAkhilesh Sanikop if (subsampling_y == 0) {
454*09537850SAkhilesh Sanikop // Begin complete stripes section. This is when we are guaranteed to have
455*09537850SAkhilesh Sanikop // two overlap rows in each stripe.
456*09537850SAkhilesh Sanikop for (; y < (plane_height & ~stripe_mask); ++luma_num, y += stripe_height) {
457*09537850SAkhilesh Sanikop const GrainType* noise_stripe = (*noise_stripes)[luma_num];
458*09537850SAkhilesh Sanikop const GrainType* noise_stripe_prev = (*noise_stripes)[luma_num - 1];
459*09537850SAkhilesh Sanikop // First overlap row.
460*09537850SAkhilesh Sanikop WriteOverlapLine_C<bitdepth>(noise_stripe,
461*09537850SAkhilesh Sanikop &noise_stripe_prev[32 * plane_width],
462*09537850SAkhilesh Sanikop plane_width, 17, 27, (*noise_image)[y]);
463*09537850SAkhilesh Sanikop // Second overlap row.
464*09537850SAkhilesh Sanikop WriteOverlapLine_C<bitdepth>(&noise_stripe[plane_width],
465*09537850SAkhilesh Sanikop &noise_stripe_prev[(32 + 1) * plane_width],
466*09537850SAkhilesh Sanikop plane_width, 27, 17, (*noise_image)[y + 1]);
467*09537850SAkhilesh Sanikop }
468*09537850SAkhilesh Sanikop // End complete stripes section.
469*09537850SAkhilesh Sanikop
470*09537850SAkhilesh Sanikop const int remaining_height = plane_height - y;
471*09537850SAkhilesh Sanikop // Either one partial stripe remains (remaining_height > 0),
472*09537850SAkhilesh Sanikop // OR image is less than one stripe high (remaining_height < 0),
473*09537850SAkhilesh Sanikop // OR all stripes are completed (remaining_height == 0).
474*09537850SAkhilesh Sanikop if (remaining_height <= 0) {
475*09537850SAkhilesh Sanikop return;
476*09537850SAkhilesh Sanikop }
477*09537850SAkhilesh Sanikop const GrainType* noise_stripe = (*noise_stripes)[luma_num];
478*09537850SAkhilesh Sanikop const GrainType* noise_stripe_prev = (*noise_stripes)[luma_num - 1];
479*09537850SAkhilesh Sanikop WriteOverlapLine_C<bitdepth>(noise_stripe,
480*09537850SAkhilesh Sanikop &noise_stripe_prev[32 * plane_width],
481*09537850SAkhilesh Sanikop plane_width, 17, 27, (*noise_image)[y]);
482*09537850SAkhilesh Sanikop
483*09537850SAkhilesh Sanikop // Check if second overlap row is in the image.
484*09537850SAkhilesh Sanikop if (remaining_height > 1) {
485*09537850SAkhilesh Sanikop WriteOverlapLine_C<bitdepth>(&noise_stripe[plane_width],
486*09537850SAkhilesh Sanikop &noise_stripe_prev[(32 + 1) * plane_width],
487*09537850SAkhilesh Sanikop plane_width, 27, 17, (*noise_image)[y + 1]);
488*09537850SAkhilesh Sanikop }
489*09537850SAkhilesh Sanikop } else { // |subsampling_y| == 1
490*09537850SAkhilesh Sanikop // No special checks needed for partial stripes, because if one exists, the
491*09537850SAkhilesh Sanikop // first and only overlap row is guaranteed to exist.
492*09537850SAkhilesh Sanikop for (; y < plane_height; ++luma_num, y += stripe_height) {
493*09537850SAkhilesh Sanikop const GrainType* noise_stripe = (*noise_stripes)[luma_num];
494*09537850SAkhilesh Sanikop const GrainType* noise_stripe_prev = (*noise_stripes)[luma_num - 1];
495*09537850SAkhilesh Sanikop WriteOverlapLine_C<bitdepth>(noise_stripe,
496*09537850SAkhilesh Sanikop &noise_stripe_prev[16 * plane_width],
497*09537850SAkhilesh Sanikop plane_width, 22, 23, (*noise_image)[y]);
498*09537850SAkhilesh Sanikop }
499*09537850SAkhilesh Sanikop }
500*09537850SAkhilesh Sanikop }
501*09537850SAkhilesh Sanikop
502*09537850SAkhilesh Sanikop template <int bitdepth, typename GrainType, typename Pixel>
BlendNoiseWithImageLuma_C(const void * LIBGAV1_RESTRICT noise_image_ptr,int min_value,int max_luma,int scaling_shift,int width,int height,int start_height,const int16_t * scaling_lut_y,const void * source_plane_y,ptrdiff_t source_stride_y,void * dest_plane_y,ptrdiff_t dest_stride_y)503*09537850SAkhilesh Sanikop void BlendNoiseWithImageLuma_C(const void* LIBGAV1_RESTRICT noise_image_ptr,
504*09537850SAkhilesh Sanikop int min_value, int max_luma, int scaling_shift,
505*09537850SAkhilesh Sanikop int width, int height, int start_height,
506*09537850SAkhilesh Sanikop const int16_t* scaling_lut_y,
507*09537850SAkhilesh Sanikop const void* source_plane_y,
508*09537850SAkhilesh Sanikop ptrdiff_t source_stride_y, void* dest_plane_y,
509*09537850SAkhilesh Sanikop ptrdiff_t dest_stride_y) {
510*09537850SAkhilesh Sanikop const auto* noise_image =
511*09537850SAkhilesh Sanikop static_cast<const Array2D<GrainType>*>(noise_image_ptr);
512*09537850SAkhilesh Sanikop const auto* in_y = static_cast<const Pixel*>(source_plane_y);
513*09537850SAkhilesh Sanikop source_stride_y /= sizeof(Pixel);
514*09537850SAkhilesh Sanikop auto* out_y = static_cast<Pixel*>(dest_plane_y);
515*09537850SAkhilesh Sanikop dest_stride_y /= sizeof(Pixel);
516*09537850SAkhilesh Sanikop
517*09537850SAkhilesh Sanikop int y = 0;
518*09537850SAkhilesh Sanikop do {
519*09537850SAkhilesh Sanikop int x = 0;
520*09537850SAkhilesh Sanikop do {
521*09537850SAkhilesh Sanikop const int orig = in_y[y * source_stride_y + x];
522*09537850SAkhilesh Sanikop int noise = noise_image[kPlaneY][y + start_height][x];
523*09537850SAkhilesh Sanikop noise = RightShiftWithRounding(
524*09537850SAkhilesh Sanikop ScaleLut<bitdepth>(scaling_lut_y, orig) * noise, scaling_shift);
525*09537850SAkhilesh Sanikop out_y[y * dest_stride_y + x] = Clip3(orig + noise, min_value, max_luma);
526*09537850SAkhilesh Sanikop } while (++x < width);
527*09537850SAkhilesh Sanikop } while (++y < height);
528*09537850SAkhilesh Sanikop }
529*09537850SAkhilesh Sanikop
530*09537850SAkhilesh Sanikop // This function is for the case params_.chroma_scaling_from_luma == false.
531*09537850SAkhilesh Sanikop template <int bitdepth, typename GrainType, typename Pixel>
BlendNoiseWithImageChroma_C(Plane plane,const FilmGrainParams & params,const void * LIBGAV1_RESTRICT noise_image_ptr,int min_value,int max_chroma,int width,int height,int start_height,int subsampling_x,int subsampling_y,const int16_t * scaling_lut_uv,const void * source_plane_y,ptrdiff_t source_stride_y,const void * source_plane_uv,ptrdiff_t source_stride_uv,void * dest_plane_uv,ptrdiff_t dest_stride_uv)532*09537850SAkhilesh Sanikop void BlendNoiseWithImageChroma_C(
533*09537850SAkhilesh Sanikop Plane plane, const FilmGrainParams& params,
534*09537850SAkhilesh Sanikop const void* LIBGAV1_RESTRICT noise_image_ptr, int min_value, int max_chroma,
535*09537850SAkhilesh Sanikop int width, int height, int start_height, int subsampling_x,
536*09537850SAkhilesh Sanikop int subsampling_y, const int16_t* scaling_lut_uv,
537*09537850SAkhilesh Sanikop const void* source_plane_y, ptrdiff_t source_stride_y,
538*09537850SAkhilesh Sanikop const void* source_plane_uv, ptrdiff_t source_stride_uv,
539*09537850SAkhilesh Sanikop void* dest_plane_uv, ptrdiff_t dest_stride_uv) {
540*09537850SAkhilesh Sanikop const auto* noise_image =
541*09537850SAkhilesh Sanikop static_cast<const Array2D<GrainType>*>(noise_image_ptr);
542*09537850SAkhilesh Sanikop
543*09537850SAkhilesh Sanikop const int chroma_width = (width + subsampling_x) >> subsampling_x;
544*09537850SAkhilesh Sanikop const int chroma_height = (height + subsampling_y) >> subsampling_y;
545*09537850SAkhilesh Sanikop
546*09537850SAkhilesh Sanikop const auto* in_y = static_cast<const Pixel*>(source_plane_y);
547*09537850SAkhilesh Sanikop source_stride_y /= sizeof(Pixel);
548*09537850SAkhilesh Sanikop const auto* in_uv = static_cast<const Pixel*>(source_plane_uv);
549*09537850SAkhilesh Sanikop source_stride_uv /= sizeof(Pixel);
550*09537850SAkhilesh Sanikop auto* out_uv = static_cast<Pixel*>(dest_plane_uv);
551*09537850SAkhilesh Sanikop dest_stride_uv /= sizeof(Pixel);
552*09537850SAkhilesh Sanikop
553*09537850SAkhilesh Sanikop const int offset = (plane == kPlaneU) ? params.u_offset : params.v_offset;
554*09537850SAkhilesh Sanikop const int luma_multiplier =
555*09537850SAkhilesh Sanikop (plane == kPlaneU) ? params.u_luma_multiplier : params.v_luma_multiplier;
556*09537850SAkhilesh Sanikop const int multiplier =
557*09537850SAkhilesh Sanikop (plane == kPlaneU) ? params.u_multiplier : params.v_multiplier;
558*09537850SAkhilesh Sanikop
559*09537850SAkhilesh Sanikop const int scaling_shift = params.chroma_scaling;
560*09537850SAkhilesh Sanikop start_height >>= subsampling_y;
561*09537850SAkhilesh Sanikop int y = 0;
562*09537850SAkhilesh Sanikop do {
563*09537850SAkhilesh Sanikop int x = 0;
564*09537850SAkhilesh Sanikop do {
565*09537850SAkhilesh Sanikop const int luma_x = x << subsampling_x;
566*09537850SAkhilesh Sanikop const int luma_y = y << subsampling_y;
567*09537850SAkhilesh Sanikop const int luma_next_x = std::min(luma_x + 1, width - 1);
568*09537850SAkhilesh Sanikop int average_luma;
569*09537850SAkhilesh Sanikop if (subsampling_x != 0) {
570*09537850SAkhilesh Sanikop average_luma = RightShiftWithRounding(
571*09537850SAkhilesh Sanikop in_y[luma_y * source_stride_y + luma_x] +
572*09537850SAkhilesh Sanikop in_y[luma_y * source_stride_y + luma_next_x],
573*09537850SAkhilesh Sanikop 1);
574*09537850SAkhilesh Sanikop } else {
575*09537850SAkhilesh Sanikop average_luma = in_y[luma_y * source_stride_y + luma_x];
576*09537850SAkhilesh Sanikop }
577*09537850SAkhilesh Sanikop const int orig = in_uv[y * source_stride_uv + x];
578*09537850SAkhilesh Sanikop const int combined = average_luma * luma_multiplier + orig * multiplier;
579*09537850SAkhilesh Sanikop const int merged =
580*09537850SAkhilesh Sanikop Clip3((combined >> 6) + LeftShift(offset, bitdepth - kBitdepth8), 0,
581*09537850SAkhilesh Sanikop (1 << bitdepth) - 1);
582*09537850SAkhilesh Sanikop int noise = noise_image[plane][y + start_height][x];
583*09537850SAkhilesh Sanikop noise = RightShiftWithRounding(
584*09537850SAkhilesh Sanikop ScaleLut<bitdepth>(scaling_lut_uv, merged) * noise, scaling_shift);
585*09537850SAkhilesh Sanikop out_uv[y * dest_stride_uv + x] =
586*09537850SAkhilesh Sanikop Clip3(orig + noise, min_value, max_chroma);
587*09537850SAkhilesh Sanikop } while (++x < chroma_width);
588*09537850SAkhilesh Sanikop } while (++y < chroma_height);
589*09537850SAkhilesh Sanikop }
590*09537850SAkhilesh Sanikop
591*09537850SAkhilesh Sanikop // This function is for the case params_.chroma_scaling_from_luma == true.
592*09537850SAkhilesh Sanikop // This further implies that scaling_lut_u == scaling_lut_v == scaling_lut_y.
593*09537850SAkhilesh Sanikop template <int bitdepth, typename GrainType, typename Pixel>
BlendNoiseWithImageChromaWithCfl_C(Plane plane,const FilmGrainParams & params,const void * LIBGAV1_RESTRICT noise_image_ptr,int min_value,int max_chroma,int width,int height,int start_height,int subsampling_x,int subsampling_y,const int16_t * scaling_lut,const void * source_plane_y,ptrdiff_t source_stride_y,const void * source_plane_uv,ptrdiff_t source_stride_uv,void * dest_plane_uv,ptrdiff_t dest_stride_uv)594*09537850SAkhilesh Sanikop void BlendNoiseWithImageChromaWithCfl_C(
595*09537850SAkhilesh Sanikop Plane plane, const FilmGrainParams& params,
596*09537850SAkhilesh Sanikop const void* LIBGAV1_RESTRICT noise_image_ptr, int min_value, int max_chroma,
597*09537850SAkhilesh Sanikop int width, int height, int start_height, int subsampling_x,
598*09537850SAkhilesh Sanikop int subsampling_y, const int16_t* scaling_lut, const void* source_plane_y,
599*09537850SAkhilesh Sanikop ptrdiff_t source_stride_y, const void* source_plane_uv,
600*09537850SAkhilesh Sanikop ptrdiff_t source_stride_uv, void* dest_plane_uv, ptrdiff_t dest_stride_uv) {
601*09537850SAkhilesh Sanikop const auto* noise_image =
602*09537850SAkhilesh Sanikop static_cast<const Array2D<GrainType>*>(noise_image_ptr);
603*09537850SAkhilesh Sanikop const auto* in_y = static_cast<const Pixel*>(source_plane_y);
604*09537850SAkhilesh Sanikop source_stride_y /= sizeof(Pixel);
605*09537850SAkhilesh Sanikop const auto* in_uv = static_cast<const Pixel*>(source_plane_uv);
606*09537850SAkhilesh Sanikop source_stride_uv /= sizeof(Pixel);
607*09537850SAkhilesh Sanikop auto* out_uv = static_cast<Pixel*>(dest_plane_uv);
608*09537850SAkhilesh Sanikop dest_stride_uv /= sizeof(Pixel);
609*09537850SAkhilesh Sanikop
610*09537850SAkhilesh Sanikop const int chroma_width = (width + subsampling_x) >> subsampling_x;
611*09537850SAkhilesh Sanikop const int chroma_height = (height + subsampling_y) >> subsampling_y;
612*09537850SAkhilesh Sanikop const int scaling_shift = params.chroma_scaling;
613*09537850SAkhilesh Sanikop start_height >>= subsampling_y;
614*09537850SAkhilesh Sanikop int y = 0;
615*09537850SAkhilesh Sanikop do {
616*09537850SAkhilesh Sanikop int x = 0;
617*09537850SAkhilesh Sanikop do {
618*09537850SAkhilesh Sanikop const int luma_x = x << subsampling_x;
619*09537850SAkhilesh Sanikop const int luma_y = y << subsampling_y;
620*09537850SAkhilesh Sanikop const int luma_next_x = std::min(luma_x + 1, width - 1);
621*09537850SAkhilesh Sanikop int average_luma;
622*09537850SAkhilesh Sanikop if (subsampling_x != 0) {
623*09537850SAkhilesh Sanikop average_luma = RightShiftWithRounding(
624*09537850SAkhilesh Sanikop in_y[luma_y * source_stride_y + luma_x] +
625*09537850SAkhilesh Sanikop in_y[luma_y * source_stride_y + luma_next_x],
626*09537850SAkhilesh Sanikop 1);
627*09537850SAkhilesh Sanikop } else {
628*09537850SAkhilesh Sanikop average_luma = in_y[luma_y * source_stride_y + luma_x];
629*09537850SAkhilesh Sanikop }
630*09537850SAkhilesh Sanikop const int orig_uv = in_uv[y * source_stride_uv + x];
631*09537850SAkhilesh Sanikop int noise_uv = noise_image[plane][y + start_height][x];
632*09537850SAkhilesh Sanikop noise_uv = RightShiftWithRounding(
633*09537850SAkhilesh Sanikop ScaleLut<bitdepth>(scaling_lut, average_luma) * noise_uv,
634*09537850SAkhilesh Sanikop scaling_shift);
635*09537850SAkhilesh Sanikop out_uv[y * dest_stride_uv + x] =
636*09537850SAkhilesh Sanikop Clip3(orig_uv + noise_uv, min_value, max_chroma);
637*09537850SAkhilesh Sanikop } while (++x < chroma_width);
638*09537850SAkhilesh Sanikop } while (++y < chroma_height);
639*09537850SAkhilesh Sanikop }
640*09537850SAkhilesh Sanikop
Init8bpp()641*09537850SAkhilesh Sanikop void Init8bpp() {
642*09537850SAkhilesh Sanikop Dsp* const dsp = dsp_internal::GetWritableDspTable(8);
643*09537850SAkhilesh Sanikop assert(dsp != nullptr);
644*09537850SAkhilesh Sanikop #if LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS
645*09537850SAkhilesh Sanikop // LumaAutoRegressionFunc
646*09537850SAkhilesh Sanikop dsp->film_grain.luma_auto_regression[0] =
647*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToLumaGrain_C<kBitdepth8, int8_t>;
648*09537850SAkhilesh Sanikop dsp->film_grain.luma_auto_regression[1] =
649*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToLumaGrain_C<kBitdepth8, int8_t>;
650*09537850SAkhilesh Sanikop dsp->film_grain.luma_auto_regression[2] =
651*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToLumaGrain_C<kBitdepth8, int8_t>;
652*09537850SAkhilesh Sanikop
653*09537850SAkhilesh Sanikop // ChromaAutoRegressionFunc
654*09537850SAkhilesh Sanikop // Chroma autoregression should never be called when lag is 0 and use_luma is
655*09537850SAkhilesh Sanikop // false.
656*09537850SAkhilesh Sanikop dsp->film_grain.chroma_auto_regression[0][0] = nullptr;
657*09537850SAkhilesh Sanikop dsp->film_grain.chroma_auto_regression[0][1] =
658*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToChromaGrains_C<kBitdepth8, int8_t, 1, false>;
659*09537850SAkhilesh Sanikop dsp->film_grain.chroma_auto_regression[0][2] =
660*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToChromaGrains_C<kBitdepth8, int8_t, 2, false>;
661*09537850SAkhilesh Sanikop dsp->film_grain.chroma_auto_regression[0][3] =
662*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToChromaGrains_C<kBitdepth8, int8_t, 3, false>;
663*09537850SAkhilesh Sanikop dsp->film_grain.chroma_auto_regression[1][0] =
664*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToChromaGrains_C<kBitdepth8, int8_t, 0, true>;
665*09537850SAkhilesh Sanikop dsp->film_grain.chroma_auto_regression[1][1] =
666*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToChromaGrains_C<kBitdepth8, int8_t, 1, true>;
667*09537850SAkhilesh Sanikop dsp->film_grain.chroma_auto_regression[1][2] =
668*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToChromaGrains_C<kBitdepth8, int8_t, 2, true>;
669*09537850SAkhilesh Sanikop dsp->film_grain.chroma_auto_regression[1][3] =
670*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToChromaGrains_C<kBitdepth8, int8_t, 3, true>;
671*09537850SAkhilesh Sanikop
672*09537850SAkhilesh Sanikop // ConstructNoiseStripesFunc
673*09537850SAkhilesh Sanikop dsp->film_grain.construct_noise_stripes[0] =
674*09537850SAkhilesh Sanikop ConstructNoiseStripes_C<kBitdepth8, int8_t>;
675*09537850SAkhilesh Sanikop dsp->film_grain.construct_noise_stripes[1] =
676*09537850SAkhilesh Sanikop ConstructNoiseStripesWithOverlap_C<kBitdepth8, int8_t>;
677*09537850SAkhilesh Sanikop
678*09537850SAkhilesh Sanikop // ConstructNoiseImageOverlapFunc
679*09537850SAkhilesh Sanikop dsp->film_grain.construct_noise_image_overlap =
680*09537850SAkhilesh Sanikop ConstructNoiseImageOverlap_C<kBitdepth8, int8_t>;
681*09537850SAkhilesh Sanikop
682*09537850SAkhilesh Sanikop // InitializeScalingLutFunc
683*09537850SAkhilesh Sanikop dsp->film_grain.initialize_scaling_lut =
684*09537850SAkhilesh Sanikop InitializeScalingLookupTable_C<kBitdepth8>;
685*09537850SAkhilesh Sanikop
686*09537850SAkhilesh Sanikop // BlendNoiseWithImageLumaFunc
687*09537850SAkhilesh Sanikop dsp->film_grain.blend_noise_luma =
688*09537850SAkhilesh Sanikop BlendNoiseWithImageLuma_C<kBitdepth8, int8_t, uint8_t>;
689*09537850SAkhilesh Sanikop
690*09537850SAkhilesh Sanikop // BlendNoiseWithImageChromaFunc
691*09537850SAkhilesh Sanikop dsp->film_grain.blend_noise_chroma[0] =
692*09537850SAkhilesh Sanikop BlendNoiseWithImageChroma_C<kBitdepth8, int8_t, uint8_t>;
693*09537850SAkhilesh Sanikop dsp->film_grain.blend_noise_chroma[1] =
694*09537850SAkhilesh Sanikop BlendNoiseWithImageChromaWithCfl_C<kBitdepth8, int8_t, uint8_t>;
695*09537850SAkhilesh Sanikop #else // !LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS
696*09537850SAkhilesh Sanikop static_cast<void>(dsp);
697*09537850SAkhilesh Sanikop #ifndef LIBGAV1_Dsp8bpp_FilmGrainAutoregressionLuma
698*09537850SAkhilesh Sanikop dsp->film_grain.luma_auto_regression[0] =
699*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToLumaGrain_C<kBitdepth8, int8_t>;
700*09537850SAkhilesh Sanikop dsp->film_grain.luma_auto_regression[1] =
701*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToLumaGrain_C<kBitdepth8, int8_t>;
702*09537850SAkhilesh Sanikop dsp->film_grain.luma_auto_regression[2] =
703*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToLumaGrain_C<kBitdepth8, int8_t>;
704*09537850SAkhilesh Sanikop #endif
705*09537850SAkhilesh Sanikop #ifndef LIBGAV1_Dsp8bpp_FilmGrainAutoregressionChroma
706*09537850SAkhilesh Sanikop // Chroma autoregression should never be called when lag is 0 and use_luma is
707*09537850SAkhilesh Sanikop // false.
708*09537850SAkhilesh Sanikop dsp->film_grain.chroma_auto_regression[0][0] = nullptr;
709*09537850SAkhilesh Sanikop dsp->film_grain.chroma_auto_regression[0][1] =
710*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToChromaGrains_C<kBitdepth8, int8_t, 1, false>;
711*09537850SAkhilesh Sanikop dsp->film_grain.chroma_auto_regression[0][2] =
712*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToChromaGrains_C<kBitdepth8, int8_t, 2, false>;
713*09537850SAkhilesh Sanikop dsp->film_grain.chroma_auto_regression[0][3] =
714*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToChromaGrains_C<kBitdepth8, int8_t, 3, false>;
715*09537850SAkhilesh Sanikop dsp->film_grain.chroma_auto_regression[1][0] =
716*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToChromaGrains_C<kBitdepth8, int8_t, 0, true>;
717*09537850SAkhilesh Sanikop dsp->film_grain.chroma_auto_regression[1][1] =
718*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToChromaGrains_C<kBitdepth8, int8_t, 1, true>;
719*09537850SAkhilesh Sanikop dsp->film_grain.chroma_auto_regression[1][2] =
720*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToChromaGrains_C<kBitdepth8, int8_t, 2, true>;
721*09537850SAkhilesh Sanikop dsp->film_grain.chroma_auto_regression[1][3] =
722*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToChromaGrains_C<kBitdepth8, int8_t, 3, true>;
723*09537850SAkhilesh Sanikop #endif
724*09537850SAkhilesh Sanikop #ifndef LIBGAV1_Dsp8bpp_FilmGrainConstructNoiseStripes
725*09537850SAkhilesh Sanikop dsp->film_grain.construct_noise_stripes[0] =
726*09537850SAkhilesh Sanikop ConstructNoiseStripes_C<kBitdepth8, int8_t>;
727*09537850SAkhilesh Sanikop dsp->film_grain.construct_noise_stripes[1] =
728*09537850SAkhilesh Sanikop ConstructNoiseStripesWithOverlap_C<kBitdepth8, int8_t>;
729*09537850SAkhilesh Sanikop #endif
730*09537850SAkhilesh Sanikop #ifndef LIBGAV1_Dsp8bpp_FilmGrainConstructNoiseImageOverlap
731*09537850SAkhilesh Sanikop dsp->film_grain.construct_noise_image_overlap =
732*09537850SAkhilesh Sanikop ConstructNoiseImageOverlap_C<kBitdepth8, int8_t>;
733*09537850SAkhilesh Sanikop #endif
734*09537850SAkhilesh Sanikop #ifndef LIBGAV1_Dsp8bpp_FilmGrainInitializeScalingLutFunc
735*09537850SAkhilesh Sanikop dsp->film_grain.initialize_scaling_lut =
736*09537850SAkhilesh Sanikop InitializeScalingLookupTable_C<kBitdepth8>;
737*09537850SAkhilesh Sanikop #endif
738*09537850SAkhilesh Sanikop #ifndef LIBGAV1_Dsp8bpp_FilmGrainBlendNoiseLuma
739*09537850SAkhilesh Sanikop dsp->film_grain.blend_noise_luma =
740*09537850SAkhilesh Sanikop BlendNoiseWithImageLuma_C<kBitdepth8, int8_t, uint8_t>;
741*09537850SAkhilesh Sanikop #endif
742*09537850SAkhilesh Sanikop #ifndef LIBGAV1_Dsp8bpp_FilmGrainBlendNoiseChroma
743*09537850SAkhilesh Sanikop dsp->film_grain.blend_noise_chroma[0] =
744*09537850SAkhilesh Sanikop BlendNoiseWithImageChroma_C<kBitdepth8, int8_t, uint8_t>;
745*09537850SAkhilesh Sanikop #endif
746*09537850SAkhilesh Sanikop #ifndef LIBGAV1_Dsp8bpp_FilmGrainBlendNoiseChromaWithCfl
747*09537850SAkhilesh Sanikop dsp->film_grain.blend_noise_chroma[1] =
748*09537850SAkhilesh Sanikop BlendNoiseWithImageChromaWithCfl_C<kBitdepth8, int8_t, uint8_t>;
749*09537850SAkhilesh Sanikop #endif
750*09537850SAkhilesh Sanikop #endif // LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS
751*09537850SAkhilesh Sanikop }
752*09537850SAkhilesh Sanikop
753*09537850SAkhilesh Sanikop #if LIBGAV1_MAX_BITDEPTH >= 10
Init10bpp()754*09537850SAkhilesh Sanikop void Init10bpp() {
755*09537850SAkhilesh Sanikop Dsp* const dsp = dsp_internal::GetWritableDspTable(10);
756*09537850SAkhilesh Sanikop assert(dsp != nullptr);
757*09537850SAkhilesh Sanikop #if LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS
758*09537850SAkhilesh Sanikop
759*09537850SAkhilesh Sanikop // LumaAutoRegressionFunc
760*09537850SAkhilesh Sanikop dsp->film_grain.luma_auto_regression[0] =
761*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToLumaGrain_C<kBitdepth10, int16_t>;
762*09537850SAkhilesh Sanikop dsp->film_grain.luma_auto_regression[1] =
763*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToLumaGrain_C<kBitdepth10, int16_t>;
764*09537850SAkhilesh Sanikop dsp->film_grain.luma_auto_regression[2] =
765*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToLumaGrain_C<kBitdepth10, int16_t>;
766*09537850SAkhilesh Sanikop
767*09537850SAkhilesh Sanikop // ChromaAutoRegressionFunc
768*09537850SAkhilesh Sanikop // Chroma autoregression should never be called when lag is 0 and use_luma is
769*09537850SAkhilesh Sanikop // false.
770*09537850SAkhilesh Sanikop dsp->film_grain.chroma_auto_regression[0][0] = nullptr;
771*09537850SAkhilesh Sanikop dsp->film_grain.chroma_auto_regression[0][1] =
772*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToChromaGrains_C<kBitdepth10, int16_t, 1, false>;
773*09537850SAkhilesh Sanikop dsp->film_grain.chroma_auto_regression[0][2] =
774*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToChromaGrains_C<kBitdepth10, int16_t, 2, false>;
775*09537850SAkhilesh Sanikop dsp->film_grain.chroma_auto_regression[0][3] =
776*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToChromaGrains_C<kBitdepth10, int16_t, 3, false>;
777*09537850SAkhilesh Sanikop dsp->film_grain.chroma_auto_regression[1][0] =
778*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToChromaGrains_C<kBitdepth10, int16_t, 0, true>;
779*09537850SAkhilesh Sanikop dsp->film_grain.chroma_auto_regression[1][1] =
780*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToChromaGrains_C<kBitdepth10, int16_t, 1, true>;
781*09537850SAkhilesh Sanikop dsp->film_grain.chroma_auto_regression[1][2] =
782*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToChromaGrains_C<kBitdepth10, int16_t, 2, true>;
783*09537850SAkhilesh Sanikop dsp->film_grain.chroma_auto_regression[1][3] =
784*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToChromaGrains_C<kBitdepth10, int16_t, 3, true>;
785*09537850SAkhilesh Sanikop
786*09537850SAkhilesh Sanikop // ConstructNoiseStripesFunc
787*09537850SAkhilesh Sanikop dsp->film_grain.construct_noise_stripes[0] =
788*09537850SAkhilesh Sanikop ConstructNoiseStripes_C<kBitdepth10, int16_t>;
789*09537850SAkhilesh Sanikop dsp->film_grain.construct_noise_stripes[1] =
790*09537850SAkhilesh Sanikop ConstructNoiseStripesWithOverlap_C<kBitdepth10, int16_t>;
791*09537850SAkhilesh Sanikop
792*09537850SAkhilesh Sanikop // ConstructNoiseImageOverlapFunc
793*09537850SAkhilesh Sanikop dsp->film_grain.construct_noise_image_overlap =
794*09537850SAkhilesh Sanikop ConstructNoiseImageOverlap_C<kBitdepth10, int16_t>;
795*09537850SAkhilesh Sanikop
796*09537850SAkhilesh Sanikop // InitializeScalingLutFunc
797*09537850SAkhilesh Sanikop dsp->film_grain.initialize_scaling_lut =
798*09537850SAkhilesh Sanikop InitializeScalingLookupTable_C<kBitdepth10>;
799*09537850SAkhilesh Sanikop
800*09537850SAkhilesh Sanikop // BlendNoiseWithImageLumaFunc
801*09537850SAkhilesh Sanikop dsp->film_grain.blend_noise_luma =
802*09537850SAkhilesh Sanikop BlendNoiseWithImageLuma_C<kBitdepth10, int16_t, uint16_t>;
803*09537850SAkhilesh Sanikop
804*09537850SAkhilesh Sanikop // BlendNoiseWithImageChromaFunc
805*09537850SAkhilesh Sanikop dsp->film_grain.blend_noise_chroma[0] =
806*09537850SAkhilesh Sanikop BlendNoiseWithImageChroma_C<kBitdepth10, int16_t, uint16_t>;
807*09537850SAkhilesh Sanikop dsp->film_grain.blend_noise_chroma[1] =
808*09537850SAkhilesh Sanikop BlendNoiseWithImageChromaWithCfl_C<kBitdepth10, int16_t, uint16_t>;
809*09537850SAkhilesh Sanikop #else // !LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS
810*09537850SAkhilesh Sanikop static_cast<void>(dsp);
811*09537850SAkhilesh Sanikop #ifndef LIBGAV1_Dsp10bpp_FilmGrainAutoregressionLuma
812*09537850SAkhilesh Sanikop dsp->film_grain.luma_auto_regression[0] =
813*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToLumaGrain_C<kBitdepth10, int16_t>;
814*09537850SAkhilesh Sanikop dsp->film_grain.luma_auto_regression[1] =
815*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToLumaGrain_C<kBitdepth10, int16_t>;
816*09537850SAkhilesh Sanikop dsp->film_grain.luma_auto_regression[2] =
817*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToLumaGrain_C<kBitdepth10, int16_t>;
818*09537850SAkhilesh Sanikop #endif
819*09537850SAkhilesh Sanikop #ifndef LIBGAV1_Dsp10bpp_FilmGrainAutoregressionChroma
820*09537850SAkhilesh Sanikop // Chroma autoregression should never be called when lag is 0 and use_luma is
821*09537850SAkhilesh Sanikop // false.
822*09537850SAkhilesh Sanikop dsp->film_grain.chroma_auto_regression[0][0] = nullptr;
823*09537850SAkhilesh Sanikop dsp->film_grain.chroma_auto_regression[0][1] =
824*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToChromaGrains_C<kBitdepth10, int16_t, 1, false>;
825*09537850SAkhilesh Sanikop dsp->film_grain.chroma_auto_regression[0][2] =
826*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToChromaGrains_C<kBitdepth10, int16_t, 2, false>;
827*09537850SAkhilesh Sanikop dsp->film_grain.chroma_auto_regression[0][3] =
828*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToChromaGrains_C<kBitdepth10, int16_t, 3, false>;
829*09537850SAkhilesh Sanikop dsp->film_grain.chroma_auto_regression[1][0] =
830*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToChromaGrains_C<kBitdepth10, int16_t, 0, true>;
831*09537850SAkhilesh Sanikop dsp->film_grain.chroma_auto_regression[1][1] =
832*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToChromaGrains_C<kBitdepth10, int16_t, 1, true>;
833*09537850SAkhilesh Sanikop dsp->film_grain.chroma_auto_regression[1][2] =
834*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToChromaGrains_C<kBitdepth10, int16_t, 2, true>;
835*09537850SAkhilesh Sanikop dsp->film_grain.chroma_auto_regression[1][3] =
836*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToChromaGrains_C<kBitdepth10, int16_t, 3, true>;
837*09537850SAkhilesh Sanikop #endif
838*09537850SAkhilesh Sanikop #ifndef LIBGAV1_Dsp10bpp_FilmGrainConstructNoiseStripes
839*09537850SAkhilesh Sanikop dsp->film_grain.construct_noise_stripes[0] =
840*09537850SAkhilesh Sanikop ConstructNoiseStripes_C<kBitdepth10, int16_t>;
841*09537850SAkhilesh Sanikop dsp->film_grain.construct_noise_stripes[1] =
842*09537850SAkhilesh Sanikop ConstructNoiseStripesWithOverlap_C<kBitdepth10, int16_t>;
843*09537850SAkhilesh Sanikop #endif
844*09537850SAkhilesh Sanikop #ifndef LIBGAV1_Dsp10bpp_FilmGrainConstructNoiseImageOverlap
845*09537850SAkhilesh Sanikop dsp->film_grain.construct_noise_image_overlap =
846*09537850SAkhilesh Sanikop ConstructNoiseImageOverlap_C<kBitdepth10, int16_t>;
847*09537850SAkhilesh Sanikop #endif
848*09537850SAkhilesh Sanikop #ifndef LIBGAV1_Dsp10bpp_FilmGrainInitializeScalingLutFunc
849*09537850SAkhilesh Sanikop dsp->film_grain.initialize_scaling_lut =
850*09537850SAkhilesh Sanikop InitializeScalingLookupTable_C<kBitdepth10>;
851*09537850SAkhilesh Sanikop #endif
852*09537850SAkhilesh Sanikop #ifndef LIBGAV1_Dsp10bpp_FilmGrainBlendNoiseLuma
853*09537850SAkhilesh Sanikop dsp->film_grain.blend_noise_luma =
854*09537850SAkhilesh Sanikop BlendNoiseWithImageLuma_C<kBitdepth10, int16_t, uint16_t>;
855*09537850SAkhilesh Sanikop #endif
856*09537850SAkhilesh Sanikop #ifndef LIBGAV1_Dsp10bpp_FilmGrainBlendNoiseChroma
857*09537850SAkhilesh Sanikop dsp->film_grain.blend_noise_chroma[0] =
858*09537850SAkhilesh Sanikop BlendNoiseWithImageChroma_C<kBitdepth10, int16_t, uint16_t>;
859*09537850SAkhilesh Sanikop #endif
860*09537850SAkhilesh Sanikop #ifndef LIBGAV1_Dsp10bpp_FilmGrainBlendNoiseChromaWithCfl
861*09537850SAkhilesh Sanikop dsp->film_grain.blend_noise_chroma[1] =
862*09537850SAkhilesh Sanikop BlendNoiseWithImageChromaWithCfl_C<kBitdepth10, int16_t, uint16_t>;
863*09537850SAkhilesh Sanikop #endif
864*09537850SAkhilesh Sanikop #endif // LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS
865*09537850SAkhilesh Sanikop }
866*09537850SAkhilesh Sanikop #endif // LIBGAV1_MAX_BITDEPTH >= 10
867*09537850SAkhilesh Sanikop
868*09537850SAkhilesh Sanikop #if LIBGAV1_MAX_BITDEPTH == 12
Init12bpp()869*09537850SAkhilesh Sanikop void Init12bpp() {
870*09537850SAkhilesh Sanikop Dsp* const dsp = dsp_internal::GetWritableDspTable(12);
871*09537850SAkhilesh Sanikop assert(dsp != nullptr);
872*09537850SAkhilesh Sanikop #if LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS
873*09537850SAkhilesh Sanikop
874*09537850SAkhilesh Sanikop // LumaAutoRegressionFunc
875*09537850SAkhilesh Sanikop dsp->film_grain.luma_auto_regression[0] =
876*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToLumaGrain_C<kBitdepth12, int16_t>;
877*09537850SAkhilesh Sanikop dsp->film_grain.luma_auto_regression[1] =
878*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToLumaGrain_C<kBitdepth12, int16_t>;
879*09537850SAkhilesh Sanikop dsp->film_grain.luma_auto_regression[2] =
880*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToLumaGrain_C<kBitdepth12, int16_t>;
881*09537850SAkhilesh Sanikop
882*09537850SAkhilesh Sanikop // ChromaAutoRegressionFunc
883*09537850SAkhilesh Sanikop // Chroma autoregression should never be called when lag is 0 and use_luma is
884*09537850SAkhilesh Sanikop // false.
885*09537850SAkhilesh Sanikop dsp->film_grain.chroma_auto_regression[0][0] = nullptr;
886*09537850SAkhilesh Sanikop dsp->film_grain.chroma_auto_regression[0][1] =
887*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToChromaGrains_C<kBitdepth12, int16_t, 1, false>;
888*09537850SAkhilesh Sanikop dsp->film_grain.chroma_auto_regression[0][2] =
889*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToChromaGrains_C<kBitdepth12, int16_t, 2, false>;
890*09537850SAkhilesh Sanikop dsp->film_grain.chroma_auto_regression[0][3] =
891*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToChromaGrains_C<kBitdepth12, int16_t, 3, false>;
892*09537850SAkhilesh Sanikop dsp->film_grain.chroma_auto_regression[1][0] =
893*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToChromaGrains_C<kBitdepth12, int16_t, 0, true>;
894*09537850SAkhilesh Sanikop dsp->film_grain.chroma_auto_regression[1][1] =
895*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToChromaGrains_C<kBitdepth12, int16_t, 1, true>;
896*09537850SAkhilesh Sanikop dsp->film_grain.chroma_auto_regression[1][2] =
897*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToChromaGrains_C<kBitdepth12, int16_t, 2, true>;
898*09537850SAkhilesh Sanikop dsp->film_grain.chroma_auto_regression[1][3] =
899*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToChromaGrains_C<kBitdepth12, int16_t, 3, true>;
900*09537850SAkhilesh Sanikop
901*09537850SAkhilesh Sanikop // ConstructNoiseStripesFunc
902*09537850SAkhilesh Sanikop dsp->film_grain.construct_noise_stripes[0] =
903*09537850SAkhilesh Sanikop ConstructNoiseStripes_C<kBitdepth12, int16_t>;
904*09537850SAkhilesh Sanikop dsp->film_grain.construct_noise_stripes[1] =
905*09537850SAkhilesh Sanikop ConstructNoiseStripesWithOverlap_C<kBitdepth12, int16_t>;
906*09537850SAkhilesh Sanikop
907*09537850SAkhilesh Sanikop // ConstructNoiseImageOverlapFunc
908*09537850SAkhilesh Sanikop dsp->film_grain.construct_noise_image_overlap =
909*09537850SAkhilesh Sanikop ConstructNoiseImageOverlap_C<kBitdepth12, int16_t>;
910*09537850SAkhilesh Sanikop
911*09537850SAkhilesh Sanikop // InitializeScalingLutFunc
912*09537850SAkhilesh Sanikop dsp->film_grain.initialize_scaling_lut =
913*09537850SAkhilesh Sanikop InitializeScalingLookupTable_C<kBitdepth12>;
914*09537850SAkhilesh Sanikop
915*09537850SAkhilesh Sanikop // BlendNoiseWithImageLumaFunc
916*09537850SAkhilesh Sanikop dsp->film_grain.blend_noise_luma =
917*09537850SAkhilesh Sanikop BlendNoiseWithImageLuma_C<kBitdepth12, int16_t, uint16_t>;
918*09537850SAkhilesh Sanikop
919*09537850SAkhilesh Sanikop // BlendNoiseWithImageChromaFunc
920*09537850SAkhilesh Sanikop dsp->film_grain.blend_noise_chroma[0] =
921*09537850SAkhilesh Sanikop BlendNoiseWithImageChroma_C<kBitdepth12, int16_t, uint16_t>;
922*09537850SAkhilesh Sanikop dsp->film_grain.blend_noise_chroma[1] =
923*09537850SAkhilesh Sanikop BlendNoiseWithImageChromaWithCfl_C<kBitdepth12, int16_t, uint16_t>;
924*09537850SAkhilesh Sanikop #else // !LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS
925*09537850SAkhilesh Sanikop static_cast<void>(dsp);
926*09537850SAkhilesh Sanikop #ifndef LIBGAV1_Dsp12bpp_FilmGrainAutoregressionLuma
927*09537850SAkhilesh Sanikop dsp->film_grain.luma_auto_regression[0] =
928*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToLumaGrain_C<kBitdepth12, int16_t>;
929*09537850SAkhilesh Sanikop dsp->film_grain.luma_auto_regression[1] =
930*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToLumaGrain_C<kBitdepth12, int16_t>;
931*09537850SAkhilesh Sanikop dsp->film_grain.luma_auto_regression[2] =
932*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToLumaGrain_C<kBitdepth12, int16_t>;
933*09537850SAkhilesh Sanikop #endif
934*09537850SAkhilesh Sanikop #ifndef LIBGAV1_Dsp12bpp_FilmGrainAutoregressionChroma
935*09537850SAkhilesh Sanikop // Chroma autoregression should never be called when lag is 0 and use_luma is
936*09537850SAkhilesh Sanikop // false.
937*09537850SAkhilesh Sanikop dsp->film_grain.chroma_auto_regression[0][0] = nullptr;
938*09537850SAkhilesh Sanikop dsp->film_grain.chroma_auto_regression[0][1] =
939*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToChromaGrains_C<kBitdepth12, int16_t, 1, false>;
940*09537850SAkhilesh Sanikop dsp->film_grain.chroma_auto_regression[0][2] =
941*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToChromaGrains_C<kBitdepth12, int16_t, 2, false>;
942*09537850SAkhilesh Sanikop dsp->film_grain.chroma_auto_regression[0][3] =
943*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToChromaGrains_C<kBitdepth12, int16_t, 3, false>;
944*09537850SAkhilesh Sanikop dsp->film_grain.chroma_auto_regression[1][0] =
945*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToChromaGrains_C<kBitdepth12, int16_t, 0, true>;
946*09537850SAkhilesh Sanikop dsp->film_grain.chroma_auto_regression[1][1] =
947*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToChromaGrains_C<kBitdepth12, int16_t, 1, true>;
948*09537850SAkhilesh Sanikop dsp->film_grain.chroma_auto_regression[1][2] =
949*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToChromaGrains_C<kBitdepth12, int16_t, 2, true>;
950*09537850SAkhilesh Sanikop dsp->film_grain.chroma_auto_regression[1][3] =
951*09537850SAkhilesh Sanikop ApplyAutoRegressiveFilterToChromaGrains_C<kBitdepth12, int16_t, 3, true>;
952*09537850SAkhilesh Sanikop #endif
953*09537850SAkhilesh Sanikop #ifndef LIBGAV1_Dsp12bpp_FilmGrainConstructNoiseStripes
954*09537850SAkhilesh Sanikop dsp->film_grain.construct_noise_stripes[0] =
955*09537850SAkhilesh Sanikop ConstructNoiseStripes_C<kBitdepth12, int16_t>;
956*09537850SAkhilesh Sanikop dsp->film_grain.construct_noise_stripes[1] =
957*09537850SAkhilesh Sanikop ConstructNoiseStripesWithOverlap_C<kBitdepth12, int16_t>;
958*09537850SAkhilesh Sanikop #endif
959*09537850SAkhilesh Sanikop #ifndef LIBGAV1_Dsp12bpp_FilmGrainConstructNoiseImageOverlap
960*09537850SAkhilesh Sanikop dsp->film_grain.construct_noise_image_overlap =
961*09537850SAkhilesh Sanikop ConstructNoiseImageOverlap_C<kBitdepth12, int16_t>;
962*09537850SAkhilesh Sanikop #endif
963*09537850SAkhilesh Sanikop #ifndef LIBGAV1_Dsp12bpp_FilmGrainInitializeScalingLutFunc
964*09537850SAkhilesh Sanikop dsp->film_grain.initialize_scaling_lut =
965*09537850SAkhilesh Sanikop InitializeScalingLookupTable_C<kBitdepth12>;
966*09537850SAkhilesh Sanikop #endif
967*09537850SAkhilesh Sanikop #ifndef LIBGAV1_Dsp12bpp_FilmGrainBlendNoiseLuma
968*09537850SAkhilesh Sanikop dsp->film_grain.blend_noise_luma =
969*09537850SAkhilesh Sanikop BlendNoiseWithImageLuma_C<kBitdepth12, int16_t, uint16_t>;
970*09537850SAkhilesh Sanikop #endif
971*09537850SAkhilesh Sanikop #ifndef LIBGAV1_Dsp12bpp_FilmGrainBlendNoiseChroma
972*09537850SAkhilesh Sanikop dsp->film_grain.blend_noise_chroma[0] =
973*09537850SAkhilesh Sanikop BlendNoiseWithImageChroma_C<kBitdepth12, int16_t, uint16_t>;
974*09537850SAkhilesh Sanikop #endif
975*09537850SAkhilesh Sanikop #ifndef LIBGAV1_Dsp12bpp_FilmGrainBlendNoiseChromaWithCfl
976*09537850SAkhilesh Sanikop dsp->film_grain.blend_noise_chroma[1] =
977*09537850SAkhilesh Sanikop BlendNoiseWithImageChromaWithCfl_C<kBitdepth12, int16_t, uint16_t>;
978*09537850SAkhilesh Sanikop #endif
979*09537850SAkhilesh Sanikop #endif // LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS
980*09537850SAkhilesh Sanikop }
981*09537850SAkhilesh Sanikop #endif // LIBGAV1_MAX_BITDEPTH == 12
982*09537850SAkhilesh Sanikop
983*09537850SAkhilesh Sanikop } // namespace
984*09537850SAkhilesh Sanikop } // namespace film_grain
985*09537850SAkhilesh Sanikop
FilmGrainInit_C()986*09537850SAkhilesh Sanikop void FilmGrainInit_C() {
987*09537850SAkhilesh Sanikop film_grain::Init8bpp();
988*09537850SAkhilesh Sanikop #if LIBGAV1_MAX_BITDEPTH >= 10
989*09537850SAkhilesh Sanikop film_grain::Init10bpp();
990*09537850SAkhilesh Sanikop #endif
991*09537850SAkhilesh Sanikop #if LIBGAV1_MAX_BITDEPTH == 12
992*09537850SAkhilesh Sanikop film_grain::Init12bpp();
993*09537850SAkhilesh Sanikop #endif
994*09537850SAkhilesh Sanikop }
995*09537850SAkhilesh Sanikop
996*09537850SAkhilesh Sanikop } // namespace dsp
997*09537850SAkhilesh Sanikop } // namespace libgav1
998