xref: /aosp_15_r20/external/libgav1/src/dsp/super_res.cc (revision 095378508e87ed692bf8dfeb34008b65b3735891)
1 // Copyright 2020 The libgav1 Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "src/dsp/super_res.h"
16 
17 #include <cassert>
18 
19 #include "src/dsp/dsp.h"
20 #include "src/utils/common.h"
21 #include "src/utils/constants.h"
22 
23 namespace libgav1 {
24 namespace dsp {
25 namespace {
26 
27 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 void SuperRes_C(const void* /*coefficients*/,
29                 void* LIBGAV1_RESTRICT const source,
30                 const ptrdiff_t source_stride, const int height,
31                 const int downscaled_width, const int upscaled_width,
32                 const int initial_subpixel_x, const int step,
33                 void* LIBGAV1_RESTRICT const dest, ptrdiff_t dest_stride) {
34   assert(step <= 1 << kSuperResScaleBits);
35   auto* src = static_cast<Pixel*>(source) - DivideBy2(kSuperResFilterTaps);
36   auto* dst = static_cast<Pixel*>(dest);
37   int y = height;
38   do {
39     ExtendLine<Pixel>(src + DivideBy2(kSuperResFilterTaps), downscaled_width,
40                       kSuperResHorizontalBorder, kSuperResHorizontalBorder);
41     // If (original) upscaled_width is <= 9, the downscaled_width may be
42     // upscaled_width - 1 (i.e. 8, 9), and become the same (i.e. 4) when
43     // subsampled via RightShiftWithRounding. This leads to an edge case where
44     // |step| == 1 << 14.
45     int subpixel_x = initial_subpixel_x;
46     int x = 0;
47     do {
48       int sum = 0;
49       const Pixel* const src_x = &src[subpixel_x >> kSuperResScaleBits];
50       const int src_x_subpixel =
51           (subpixel_x & kSuperResScaleMask) >> kSuperResExtraBits;
52       // The sign of each tap is: - + - + + - + -
53       sum -= src_x[0] * kUpscaleFilterUnsigned[src_x_subpixel][0];
54       sum += src_x[1] * kUpscaleFilterUnsigned[src_x_subpixel][1];
55       sum -= src_x[2] * kUpscaleFilterUnsigned[src_x_subpixel][2];
56       sum += src_x[3] * kUpscaleFilterUnsigned[src_x_subpixel][3];
57       sum += src_x[4] * kUpscaleFilterUnsigned[src_x_subpixel][4];
58       sum -= src_x[5] * kUpscaleFilterUnsigned[src_x_subpixel][5];
59       sum += src_x[6] * kUpscaleFilterUnsigned[src_x_subpixel][6];
60       sum -= src_x[7] * kUpscaleFilterUnsigned[src_x_subpixel][7];
61       dst[x] = Clip3(RightShiftWithRounding(sum, kFilterBits), 0,
62                      (1 << bitdepth) - 1);
63       subpixel_x += step;
64     } while (++x < upscaled_width);
65     src += source_stride;
66     dst += dest_stride;
67   } while (--y != 0);
68 }
69 
Init8bpp()70 void Init8bpp() {
71   Dsp* dsp = dsp_internal::GetWritableDspTable(8);
72   assert(dsp != nullptr);
73   dsp->super_res_coefficients = nullptr;
74 #if LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS
75   dsp->super_res = SuperRes_C<8, uint8_t>;
76 #else  // !LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS
77   static_cast<void>(dsp);
78 #ifndef LIBGAV1_Dsp8bpp_SuperRes
79   dsp->super_res = SuperRes_C<8, uint8_t>;
80 #endif
81 #endif  // LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS
82 }
83 
84 #if LIBGAV1_MAX_BITDEPTH >= 10
Init10bpp()85 void Init10bpp() {
86   Dsp* dsp = dsp_internal::GetWritableDspTable(10);
87   assert(dsp != nullptr);
88   dsp->super_res_coefficients = nullptr;
89 #if LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS
90   dsp->super_res = SuperRes_C<10, uint16_t>;
91 #else  // !LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS
92   static_cast<void>(dsp);
93 #ifndef LIBGAV1_Dsp10bpp_SuperRes
94   dsp->super_res = SuperRes_C<10, uint16_t>;
95 #endif
96 #endif  // LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS
97 }
98 #endif  // LIBGAV1_MAX_BITDEPTH >= 10
99 
100 #if LIBGAV1_MAX_BITDEPTH == 12
Init12bpp()101 void Init12bpp() {
102   Dsp* dsp = dsp_internal::GetWritableDspTable(12);
103   assert(dsp != nullptr);
104   dsp->super_res_coefficients = nullptr;
105 #if LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS
106   dsp->super_res = SuperRes_C<12, uint16_t>;
107 #else  // !LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS
108   static_cast<void>(dsp);
109 #ifndef LIBGAV1_Dsp12bpp_SuperRes
110   dsp->super_res = SuperRes_C<12, uint16_t>;
111 #endif
112 #endif  // LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS
113 }
114 #endif  // LIBGAV1_MAX_BITDEPTH == 12
115 
116 }  // namespace
117 
SuperResInit_C()118 void SuperResInit_C() {
119   Init8bpp();
120 #if LIBGAV1_MAX_BITDEPTH >= 10
121   Init10bpp();
122 #endif
123 #if LIBGAV1_MAX_BITDEPTH == 12
124   Init12bpp();
125 #endif
126 }
127 
128 }  // namespace dsp
129 }  // namespace libgav1
130