1 // Copyright 2019 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/average_blend.h"
16 
17 #include <cassert>
18 #include <cstddef>
19 #include <cstdint>
20 #include <type_traits>
21 
22 #include "src/dsp/dsp.h"
23 #include "src/utils/common.h"
24 
25 namespace libgav1 {
26 namespace dsp {
27 namespace {
28 
29 template <int bitdepth, typename Pixel>
AverageBlend_C(const void * prediction_0,const void * prediction_1,const int width,const int height,void * const dest,const ptrdiff_t dest_stride)30 void AverageBlend_C(const void* prediction_0, const void* prediction_1,
31                     const int width, const int height, void* const dest,
32                     const ptrdiff_t dest_stride) {
33   // 7.11.3.2 Rounding variables derivation process
34   //   2 * FILTER_BITS(7) - (InterRound0(3|5) + InterRound1(7))
35   constexpr int inter_post_round_bits = (bitdepth == 12) ? 2 : 4;
36   using PredType =
37       typename std::conditional<bitdepth == 8, int16_t, uint16_t>::type;
38   const auto* pred_0 = static_cast<const PredType*>(prediction_0);
39   const auto* pred_1 = static_cast<const PredType*>(prediction_1);
40   auto* dst = static_cast<Pixel*>(dest);
41   const ptrdiff_t dst_stride = dest_stride / sizeof(Pixel);
42 
43   int y = 0;
44   do {
45     int x = 0;
46     do {
47       // See warp.cc and convolve.cc for detailed prediction ranges.
48       int res = pred_0[x] + pred_1[x];
49       res -= (bitdepth == 8) ? 0 : kCompoundOffset + kCompoundOffset;
50       dst[x] = static_cast<Pixel>(
51           Clip3(RightShiftWithRounding(res, inter_post_round_bits + 1), 0,
52                 (1 << bitdepth) - 1));
53     } while (++x < width);
54 
55     dst += dst_stride;
56     pred_0 += width;
57     pred_1 += width;
58   } while (++y < height);
59 }
60 
Init8bpp()61 void Init8bpp() {
62   Dsp* const dsp = dsp_internal::GetWritableDspTable(8);
63   assert(dsp != nullptr);
64 #if LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS
65   dsp->average_blend = AverageBlend_C<8, uint8_t>;
66 #else  // !LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS
67   static_cast<void>(dsp);
68 #ifndef LIBGAV1_Dsp8bpp_AverageBlend
69   dsp->average_blend = AverageBlend_C<8, uint8_t>;
70 #endif
71 #endif  // LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS
72 }
73 
74 #if LIBGAV1_MAX_BITDEPTH >= 10
Init10bpp()75 void Init10bpp() {
76   Dsp* const dsp = dsp_internal::GetWritableDspTable(10);
77   assert(dsp != nullptr);
78 #if LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS
79 #ifndef LIBGAV1_Dsp10bpp_AverageBlend
80   dsp->average_blend = AverageBlend_C<10, uint16_t>;
81 #endif
82 #else  // !LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS
83   static_cast<void>(dsp);
84 #ifndef LIBGAV1_Dsp10bpp_AverageBlend
85   dsp->average_blend = AverageBlend_C<10, uint16_t>;
86 #endif
87 #endif  // LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS
88 }
89 #endif
90 
91 }  // namespace
92 
AverageBlendInit_C()93 void AverageBlendInit_C() {
94   Init8bpp();
95 #if LIBGAV1_MAX_BITDEPTH >= 10
96   Init10bpp();
97 #endif
98 }
99 
100 }  // namespace dsp
101 }  // namespace libgav1
102