xref: /aosp_15_r20/external/libgav1/src/dsp/super_res.cc (revision 095378508e87ed692bf8dfeb34008b65b3735891)
1*09537850SAkhilesh Sanikop // Copyright 2020 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/super_res.h"
16*09537850SAkhilesh Sanikop 
17*09537850SAkhilesh Sanikop #include <cassert>
18*09537850SAkhilesh Sanikop 
19*09537850SAkhilesh Sanikop #include "src/dsp/dsp.h"
20*09537850SAkhilesh Sanikop #include "src/utils/common.h"
21*09537850SAkhilesh Sanikop #include "src/utils/constants.h"
22*09537850SAkhilesh Sanikop 
23*09537850SAkhilesh Sanikop namespace libgav1 {
24*09537850SAkhilesh Sanikop namespace dsp {
25*09537850SAkhilesh Sanikop namespace {
26*09537850SAkhilesh Sanikop 
27*09537850SAkhilesh Sanikop template <int bitdepth, typename Pixel>
SuperRes_C(const void *,void * LIBGAV1_RESTRICT const source,const ptrdiff_t source_stride,const int height,const int downscaled_width,const int upscaled_width,const int initial_subpixel_x,const int step,void * LIBGAV1_RESTRICT const dest,ptrdiff_t dest_stride)28*09537850SAkhilesh Sanikop void SuperRes_C(const void* /*coefficients*/,
29*09537850SAkhilesh Sanikop                 void* LIBGAV1_RESTRICT const source,
30*09537850SAkhilesh Sanikop                 const ptrdiff_t source_stride, const int height,
31*09537850SAkhilesh Sanikop                 const int downscaled_width, const int upscaled_width,
32*09537850SAkhilesh Sanikop                 const int initial_subpixel_x, const int step,
33*09537850SAkhilesh Sanikop                 void* LIBGAV1_RESTRICT const dest, ptrdiff_t dest_stride) {
34*09537850SAkhilesh Sanikop   assert(step <= 1 << kSuperResScaleBits);
35*09537850SAkhilesh Sanikop   auto* src = static_cast<Pixel*>(source) - DivideBy2(kSuperResFilterTaps);
36*09537850SAkhilesh Sanikop   auto* dst = static_cast<Pixel*>(dest);
37*09537850SAkhilesh Sanikop   int y = height;
38*09537850SAkhilesh Sanikop   do {
39*09537850SAkhilesh Sanikop     ExtendLine<Pixel>(src + DivideBy2(kSuperResFilterTaps), downscaled_width,
40*09537850SAkhilesh Sanikop                       kSuperResHorizontalBorder, kSuperResHorizontalBorder);
41*09537850SAkhilesh Sanikop     // If (original) upscaled_width is <= 9, the downscaled_width may be
42*09537850SAkhilesh Sanikop     // upscaled_width - 1 (i.e. 8, 9), and become the same (i.e. 4) when
43*09537850SAkhilesh Sanikop     // subsampled via RightShiftWithRounding. This leads to an edge case where
44*09537850SAkhilesh Sanikop     // |step| == 1 << 14.
45*09537850SAkhilesh Sanikop     int subpixel_x = initial_subpixel_x;
46*09537850SAkhilesh Sanikop     int x = 0;
47*09537850SAkhilesh Sanikop     do {
48*09537850SAkhilesh Sanikop       int sum = 0;
49*09537850SAkhilesh Sanikop       const Pixel* const src_x = &src[subpixel_x >> kSuperResScaleBits];
50*09537850SAkhilesh Sanikop       const int src_x_subpixel =
51*09537850SAkhilesh Sanikop           (subpixel_x & kSuperResScaleMask) >> kSuperResExtraBits;
52*09537850SAkhilesh Sanikop       // The sign of each tap is: - + - + + - + -
53*09537850SAkhilesh Sanikop       sum -= src_x[0] * kUpscaleFilterUnsigned[src_x_subpixel][0];
54*09537850SAkhilesh Sanikop       sum += src_x[1] * kUpscaleFilterUnsigned[src_x_subpixel][1];
55*09537850SAkhilesh Sanikop       sum -= src_x[2] * kUpscaleFilterUnsigned[src_x_subpixel][2];
56*09537850SAkhilesh Sanikop       sum += src_x[3] * kUpscaleFilterUnsigned[src_x_subpixel][3];
57*09537850SAkhilesh Sanikop       sum += src_x[4] * kUpscaleFilterUnsigned[src_x_subpixel][4];
58*09537850SAkhilesh Sanikop       sum -= src_x[5] * kUpscaleFilterUnsigned[src_x_subpixel][5];
59*09537850SAkhilesh Sanikop       sum += src_x[6] * kUpscaleFilterUnsigned[src_x_subpixel][6];
60*09537850SAkhilesh Sanikop       sum -= src_x[7] * kUpscaleFilterUnsigned[src_x_subpixel][7];
61*09537850SAkhilesh Sanikop       dst[x] = Clip3(RightShiftWithRounding(sum, kFilterBits), 0,
62*09537850SAkhilesh Sanikop                      (1 << bitdepth) - 1);
63*09537850SAkhilesh Sanikop       subpixel_x += step;
64*09537850SAkhilesh Sanikop     } while (++x < upscaled_width);
65*09537850SAkhilesh Sanikop     src += source_stride;
66*09537850SAkhilesh Sanikop     dst += dest_stride;
67*09537850SAkhilesh Sanikop   } while (--y != 0);
68*09537850SAkhilesh Sanikop }
69*09537850SAkhilesh Sanikop 
Init8bpp()70*09537850SAkhilesh Sanikop void Init8bpp() {
71*09537850SAkhilesh Sanikop   Dsp* dsp = dsp_internal::GetWritableDspTable(8);
72*09537850SAkhilesh Sanikop   assert(dsp != nullptr);
73*09537850SAkhilesh Sanikop   dsp->super_res_coefficients = nullptr;
74*09537850SAkhilesh Sanikop #if LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS
75*09537850SAkhilesh Sanikop   dsp->super_res = SuperRes_C<8, uint8_t>;
76*09537850SAkhilesh Sanikop #else  // !LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS
77*09537850SAkhilesh Sanikop   static_cast<void>(dsp);
78*09537850SAkhilesh Sanikop #ifndef LIBGAV1_Dsp8bpp_SuperRes
79*09537850SAkhilesh Sanikop   dsp->super_res = SuperRes_C<8, uint8_t>;
80*09537850SAkhilesh Sanikop #endif
81*09537850SAkhilesh Sanikop #endif  // LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS
82*09537850SAkhilesh Sanikop }
83*09537850SAkhilesh Sanikop 
84*09537850SAkhilesh Sanikop #if LIBGAV1_MAX_BITDEPTH >= 10
Init10bpp()85*09537850SAkhilesh Sanikop void Init10bpp() {
86*09537850SAkhilesh Sanikop   Dsp* dsp = dsp_internal::GetWritableDspTable(10);
87*09537850SAkhilesh Sanikop   assert(dsp != nullptr);
88*09537850SAkhilesh Sanikop   dsp->super_res_coefficients = nullptr;
89*09537850SAkhilesh Sanikop #if LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS
90*09537850SAkhilesh Sanikop   dsp->super_res = SuperRes_C<10, uint16_t>;
91*09537850SAkhilesh Sanikop #else  // !LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS
92*09537850SAkhilesh Sanikop   static_cast<void>(dsp);
93*09537850SAkhilesh Sanikop #ifndef LIBGAV1_Dsp10bpp_SuperRes
94*09537850SAkhilesh Sanikop   dsp->super_res = SuperRes_C<10, uint16_t>;
95*09537850SAkhilesh Sanikop #endif
96*09537850SAkhilesh Sanikop #endif  // LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS
97*09537850SAkhilesh Sanikop }
98*09537850SAkhilesh Sanikop #endif  // LIBGAV1_MAX_BITDEPTH >= 10
99*09537850SAkhilesh Sanikop 
100*09537850SAkhilesh Sanikop #if LIBGAV1_MAX_BITDEPTH == 12
Init12bpp()101*09537850SAkhilesh Sanikop void Init12bpp() {
102*09537850SAkhilesh Sanikop   Dsp* dsp = dsp_internal::GetWritableDspTable(12);
103*09537850SAkhilesh Sanikop   assert(dsp != nullptr);
104*09537850SAkhilesh Sanikop   dsp->super_res_coefficients = nullptr;
105*09537850SAkhilesh Sanikop #if LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS
106*09537850SAkhilesh Sanikop   dsp->super_res = SuperRes_C<12, uint16_t>;
107*09537850SAkhilesh Sanikop #else  // !LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS
108*09537850SAkhilesh Sanikop   static_cast<void>(dsp);
109*09537850SAkhilesh Sanikop #ifndef LIBGAV1_Dsp12bpp_SuperRes
110*09537850SAkhilesh Sanikop   dsp->super_res = SuperRes_C<12, uint16_t>;
111*09537850SAkhilesh Sanikop #endif
112*09537850SAkhilesh Sanikop #endif  // LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS
113*09537850SAkhilesh Sanikop }
114*09537850SAkhilesh Sanikop #endif  // LIBGAV1_MAX_BITDEPTH == 12
115*09537850SAkhilesh Sanikop 
116*09537850SAkhilesh Sanikop }  // namespace
117*09537850SAkhilesh Sanikop 
SuperResInit_C()118*09537850SAkhilesh Sanikop void SuperResInit_C() {
119*09537850SAkhilesh Sanikop   Init8bpp();
120*09537850SAkhilesh Sanikop #if LIBGAV1_MAX_BITDEPTH >= 10
121*09537850SAkhilesh Sanikop   Init10bpp();
122*09537850SAkhilesh Sanikop #endif
123*09537850SAkhilesh Sanikop #if LIBGAV1_MAX_BITDEPTH == 12
124*09537850SAkhilesh Sanikop   Init12bpp();
125*09537850SAkhilesh Sanikop #endif
126*09537850SAkhilesh Sanikop }
127*09537850SAkhilesh Sanikop 
128*09537850SAkhilesh Sanikop }  // namespace dsp
129*09537850SAkhilesh Sanikop }  // namespace libgav1
130