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 * 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 * const dest,ptrdiff_t dest_stride)28 void SuperRes_C(const void* /*coefficients*/, void* const source,
29 const ptrdiff_t source_stride, const int height,
30 const int downscaled_width, const int upscaled_width,
31 const int initial_subpixel_x, const int step, void* const dest,
32 ptrdiff_t dest_stride) {
33 assert(step <= 1 << kSuperResScaleBits);
34 auto* src = static_cast<Pixel*>(source) - DivideBy2(kSuperResFilterTaps);
35 auto* dst = static_cast<Pixel*>(dest);
36 int y = height;
37 do {
38 ExtendLine<Pixel>(src + DivideBy2(kSuperResFilterTaps), downscaled_width,
39 kSuperResHorizontalBorder, kSuperResHorizontalBorder);
40 // If (original) upscaled_width is <= 9, the downscaled_width may be
41 // upscaled_width - 1 (i.e. 8, 9), and become the same (i.e. 4) when
42 // subsampled via RightShiftWithRounding. This leads to an edge case where
43 // |step| == 1 << 14.
44 int subpixel_x = initial_subpixel_x;
45 int x = 0;
46 do {
47 int sum = 0;
48 const Pixel* const src_x = &src[subpixel_x >> kSuperResScaleBits];
49 const int src_x_subpixel =
50 (subpixel_x & kSuperResScaleMask) >> kSuperResExtraBits;
51 // The sign of each tap is: - + - + + - + -
52 sum -= src_x[0] * kUpscaleFilterUnsigned[src_x_subpixel][0];
53 sum += src_x[1] * kUpscaleFilterUnsigned[src_x_subpixel][1];
54 sum -= src_x[2] * kUpscaleFilterUnsigned[src_x_subpixel][2];
55 sum += src_x[3] * kUpscaleFilterUnsigned[src_x_subpixel][3];
56 sum += src_x[4] * kUpscaleFilterUnsigned[src_x_subpixel][4];
57 sum -= src_x[5] * kUpscaleFilterUnsigned[src_x_subpixel][5];
58 sum += src_x[6] * kUpscaleFilterUnsigned[src_x_subpixel][6];
59 sum -= src_x[7] * kUpscaleFilterUnsigned[src_x_subpixel][7];
60 dst[x] = Clip3(RightShiftWithRounding(sum, kFilterBits), 0,
61 (1 << bitdepth) - 1);
62 subpixel_x += step;
63 } while (++x < upscaled_width);
64 src += source_stride;
65 dst += dest_stride;
66 } while (--y != 0);
67 }
68
Init8bpp()69 void Init8bpp() {
70 Dsp* dsp = dsp_internal::GetWritableDspTable(8);
71 assert(dsp != nullptr);
72 dsp->super_res_coefficients = nullptr;
73 #if LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS
74 dsp->super_res = SuperRes_C<8, uint8_t>;
75 #else // !LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS
76 static_cast<void>(dsp);
77 #ifndef LIBGAV1_Dsp8bpp_SuperRes
78 dsp->super_res = SuperRes_C<8, uint8_t>;
79 #endif
80 #endif // LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS
81 }
82
83 #if LIBGAV1_MAX_BITDEPTH >= 10
Init10bpp()84 void Init10bpp() {
85 Dsp* dsp = dsp_internal::GetWritableDspTable(10);
86 assert(dsp != nullptr);
87 dsp->super_res_coefficients = nullptr;
88 #if LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS
89 dsp->super_res = SuperRes_C<10, uint16_t>;
90 #else // !LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS
91 static_cast<void>(dsp);
92 #ifndef LIBGAV1_Dsp10bpp_SuperRes
93 dsp->super_res = SuperRes_C<10, uint16_t>;
94 #endif
95 #endif // LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS
96 }
97 #endif
98
99 } // namespace
100
SuperResInit_C()101 void SuperResInit_C() {
102 Init8bpp();
103 #if LIBGAV1_MAX_BITDEPTH >= 10
104 Init10bpp();
105 #endif
106 }
107
108 } // namespace dsp
109 } // namespace libgav1
110