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/motion_vector_search.h"
16
17 #include <algorithm>
18 #include <cassert>
19 #include <cstddef>
20 #include <cstdint>
21
22 #include "src/dsp/dsp.h"
23 #include "src/utils/common.h"
24 #include "src/utils/constants.h"
25 #include "src/utils/types.h"
26
27 namespace libgav1 {
28 namespace dsp {
29 namespace {
30
31 // Silence unused function warnings when the C functions are not used.
32 #if LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS || \
33 !defined(LIBGAV1_Dsp8bpp_MotionVectorSearch) || \
34 (LIBGAV1_MAX_BITDEPTH >= 10 && \
35 !defined(LIBGAV1_Dsp10bpp_MotionVectorSearch))
36
MvProjectionCompoundLowPrecision_C(const MotionVector * const temporal_mvs,const int8_t * const temporal_reference_offsets,const int reference_offsets[2],const int count,CompoundMotionVector * const candidate_mvs)37 void MvProjectionCompoundLowPrecision_C(
38 const MotionVector* const temporal_mvs,
39 const int8_t* const temporal_reference_offsets,
40 const int reference_offsets[2], const int count,
41 CompoundMotionVector* const candidate_mvs) {
42 // To facilitate the compilers, make a local copy of |reference_offsets|.
43 const int offsets[2] = {reference_offsets[0], reference_offsets[1]};
44 int index = 0;
45 do {
46 candidate_mvs[index].mv64 = 0;
47 for (int i = 0; i < 2; ++i) {
48 // |offsets| non-zero check usually equals true and could be ignored.
49 if (offsets[i] != 0) {
50 GetMvProjection(
51 temporal_mvs[index], offsets[i],
52 kProjectionMvDivisionLookup[temporal_reference_offsets[index]],
53 &candidate_mvs[index].mv[i]);
54 for (auto& mv : candidate_mvs[index].mv[i].mv) {
55 // The next line is equivalent to:
56 // if ((mv & 1) != 0) mv += (mv > 0) ? -1 : 1;
57 mv = (mv - (mv >> 15)) & ~1;
58 }
59 }
60 }
61 } while (++index < count);
62 }
63
MvProjectionCompoundForceInteger_C(const MotionVector * const temporal_mvs,const int8_t * const temporal_reference_offsets,const int reference_offsets[2],const int count,CompoundMotionVector * const candidate_mvs)64 void MvProjectionCompoundForceInteger_C(
65 const MotionVector* const temporal_mvs,
66 const int8_t* const temporal_reference_offsets,
67 const int reference_offsets[2], const int count,
68 CompoundMotionVector* const candidate_mvs) {
69 // To facilitate the compilers, make a local copy of |reference_offsets|.
70 const int offsets[2] = {reference_offsets[0], reference_offsets[1]};
71 int index = 0;
72 do {
73 candidate_mvs[index].mv64 = 0;
74 for (int i = 0; i < 2; ++i) {
75 // |offsets| non-zero check usually equals true and could be ignored.
76 if (offsets[i] != 0) {
77 GetMvProjection(
78 temporal_mvs[index], offsets[i],
79 kProjectionMvDivisionLookup[temporal_reference_offsets[index]],
80 &candidate_mvs[index].mv[i]);
81 for (auto& mv : candidate_mvs[index].mv[i].mv) {
82 // The next line is equivalent to:
83 // const int value = (std::abs(static_cast<int>(mv)) + 3) & ~7;
84 // const int sign = mv >> 15;
85 // mv = ApplySign(value, sign);
86 mv = (mv + 3 - (mv >> 15)) & ~7;
87 }
88 }
89 }
90 } while (++index < count);
91 }
92
MvProjectionCompoundHighPrecision_C(const MotionVector * const temporal_mvs,const int8_t * const temporal_reference_offsets,const int reference_offsets[2],const int count,CompoundMotionVector * const candidate_mvs)93 void MvProjectionCompoundHighPrecision_C(
94 const MotionVector* const temporal_mvs,
95 const int8_t* const temporal_reference_offsets,
96 const int reference_offsets[2], const int count,
97 CompoundMotionVector* const candidate_mvs) {
98 // To facilitate the compilers, make a local copy of |reference_offsets|.
99 const int offsets[2] = {reference_offsets[0], reference_offsets[1]};
100 int index = 0;
101 do {
102 candidate_mvs[index].mv64 = 0;
103 for (int i = 0; i < 2; ++i) {
104 // |offsets| non-zero check usually equals true and could be ignored.
105 if (offsets[i] != 0) {
106 GetMvProjection(
107 temporal_mvs[index], offsets[i],
108 kProjectionMvDivisionLookup[temporal_reference_offsets[index]],
109 &candidate_mvs[index].mv[i]);
110 }
111 }
112 } while (++index < count);
113 }
114
MvProjectionSingleLowPrecision_C(const MotionVector * const temporal_mvs,const int8_t * const temporal_reference_offsets,const int reference_offset,const int count,MotionVector * const candidate_mvs)115 void MvProjectionSingleLowPrecision_C(
116 const MotionVector* const temporal_mvs,
117 const int8_t* const temporal_reference_offsets, const int reference_offset,
118 const int count, MotionVector* const candidate_mvs) {
119 int index = 0;
120 do {
121 GetMvProjection(
122 temporal_mvs[index], reference_offset,
123 kProjectionMvDivisionLookup[temporal_reference_offsets[index]],
124 &candidate_mvs[index]);
125 for (auto& mv : candidate_mvs[index].mv) {
126 // The next line is equivalent to:
127 // if ((mv & 1) != 0) mv += (mv > 0) ? -1 : 1;
128 mv = (mv - (mv >> 15)) & ~1;
129 }
130 } while (++index < count);
131 }
132
MvProjectionSingleForceInteger_C(const MotionVector * const temporal_mvs,const int8_t * const temporal_reference_offsets,const int reference_offset,const int count,MotionVector * const candidate_mvs)133 void MvProjectionSingleForceInteger_C(
134 const MotionVector* const temporal_mvs,
135 const int8_t* const temporal_reference_offsets, const int reference_offset,
136 const int count, MotionVector* const candidate_mvs) {
137 int index = 0;
138 do {
139 GetMvProjection(
140 temporal_mvs[index], reference_offset,
141 kProjectionMvDivisionLookup[temporal_reference_offsets[index]],
142 &candidate_mvs[index]);
143 for (auto& mv : candidate_mvs[index].mv) {
144 // The next line is equivalent to:
145 // const int value = (std::abs(static_cast<int>(mv)) + 3) & ~7;
146 // const int sign = mv >> 15;
147 // mv = ApplySign(value, sign);
148 mv = (mv + 3 - (mv >> 15)) & ~7;
149 }
150 } while (++index < count);
151 }
152
MvProjectionSingleHighPrecision_C(const MotionVector * const temporal_mvs,const int8_t * const temporal_reference_offsets,const int reference_offset,const int count,MotionVector * const candidate_mvs)153 void MvProjectionSingleHighPrecision_C(
154 const MotionVector* const temporal_mvs,
155 const int8_t* const temporal_reference_offsets, const int reference_offset,
156 const int count, MotionVector* const candidate_mvs) {
157 int index = 0;
158 do {
159 GetMvProjection(
160 temporal_mvs[index], reference_offset,
161 kProjectionMvDivisionLookup[temporal_reference_offsets[index]],
162 &candidate_mvs[index]);
163 } while (++index < count);
164 }
165
166 #endif // LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS ||
167 // !defined(LIBGAV1_Dsp8bpp_MotionVectorSearch) ||
168 // (LIBGAV1_MAX_BITDEPTH >= 10 &&
169 // !defined(LIBGAV1_Dsp10bpp_MotionVectorSearch))
170
Init8bpp()171 void Init8bpp() {
172 #if LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS || \
173 !defined(LIBGAV1_Dsp8bpp_MotionVectorSearch)
174 Dsp* const dsp = dsp_internal::GetWritableDspTable(8);
175 assert(dsp != nullptr);
176 dsp->mv_projection_compound[0] = MvProjectionCompoundLowPrecision_C;
177 dsp->mv_projection_compound[1] = MvProjectionCompoundForceInteger_C;
178 dsp->mv_projection_compound[2] = MvProjectionCompoundHighPrecision_C;
179 dsp->mv_projection_single[0] = MvProjectionSingleLowPrecision_C;
180 dsp->mv_projection_single[1] = MvProjectionSingleForceInteger_C;
181 dsp->mv_projection_single[2] = MvProjectionSingleHighPrecision_C;
182 #endif
183 }
184
185 #if LIBGAV1_MAX_BITDEPTH >= 10
Init10bpp()186 void Init10bpp() {
187 #if LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS || \
188 !defined(LIBGAV1_Dsp10bpp_MotionVectorSearch)
189 Dsp* const dsp = dsp_internal::GetWritableDspTable(10);
190 assert(dsp != nullptr);
191 dsp->mv_projection_compound[0] = MvProjectionCompoundLowPrecision_C;
192 dsp->mv_projection_compound[1] = MvProjectionCompoundForceInteger_C;
193 dsp->mv_projection_compound[2] = MvProjectionCompoundHighPrecision_C;
194 dsp->mv_projection_single[0] = MvProjectionSingleLowPrecision_C;
195 dsp->mv_projection_single[1] = MvProjectionSingleForceInteger_C;
196 dsp->mv_projection_single[2] = MvProjectionSingleHighPrecision_C;
197 #endif
198 }
199 #endif
200
201 } // namespace
202
MotionVectorSearchInit_C()203 void MotionVectorSearchInit_C() {
204 Init8bpp();
205 #if LIBGAV1_MAX_BITDEPTH >= 10
206 Init10bpp();
207 #endif
208 }
209
210 } // namespace dsp
211 } // namespace libgav1
212