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
MvProjectionCompoundLowPrecision_C(const MotionVector * LIBGAV1_RESTRICT const temporal_mvs,const int8_t * LIBGAV1_RESTRICT const temporal_reference_offsets,const int reference_offsets[2],const int count,CompoundMotionVector * LIBGAV1_RESTRICT const candidate_mvs)35 void MvProjectionCompoundLowPrecision_C(
36 const MotionVector* LIBGAV1_RESTRICT const temporal_mvs,
37 const int8_t* LIBGAV1_RESTRICT const temporal_reference_offsets,
38 const int reference_offsets[2], const int count,
39 CompoundMotionVector* LIBGAV1_RESTRICT const candidate_mvs) {
40 // To facilitate the compilers, make a local copy of |reference_offsets|.
41 const int offsets[2] = {reference_offsets[0], reference_offsets[1]};
42 int index = 0;
43 do {
44 candidate_mvs[index].mv64 = 0;
45 for (int i = 0; i < 2; ++i) {
46 // |offsets| non-zero check usually equals true and could be ignored.
47 if (offsets[i] != 0) {
48 GetMvProjection(
49 temporal_mvs[index], offsets[i],
50 kProjectionMvDivisionLookup[temporal_reference_offsets[index]],
51 &candidate_mvs[index].mv[i]);
52 for (auto& mv : candidate_mvs[index].mv[i].mv) {
53 // The next line is equivalent to:
54 // if ((mv & 1) != 0) mv += (mv > 0) ? -1 : 1;
55 mv = (mv - (mv >> 15)) & ~1;
56 }
57 }
58 }
59 } while (++index < count);
60 }
61
MvProjectionCompoundForceInteger_C(const MotionVector * LIBGAV1_RESTRICT const temporal_mvs,const int8_t * LIBGAV1_RESTRICT const temporal_reference_offsets,const int reference_offsets[2],const int count,CompoundMotionVector * LIBGAV1_RESTRICT const candidate_mvs)62 void MvProjectionCompoundForceInteger_C(
63 const MotionVector* LIBGAV1_RESTRICT const temporal_mvs,
64 const int8_t* LIBGAV1_RESTRICT const temporal_reference_offsets,
65 const int reference_offsets[2], const int count,
66 CompoundMotionVector* LIBGAV1_RESTRICT const candidate_mvs) {
67 // To facilitate the compilers, make a local copy of |reference_offsets|.
68 const int offsets[2] = {reference_offsets[0], reference_offsets[1]};
69 int index = 0;
70 do {
71 candidate_mvs[index].mv64 = 0;
72 for (int i = 0; i < 2; ++i) {
73 // |offsets| non-zero check usually equals true and could be ignored.
74 if (offsets[i] != 0) {
75 GetMvProjection(
76 temporal_mvs[index], offsets[i],
77 kProjectionMvDivisionLookup[temporal_reference_offsets[index]],
78 &candidate_mvs[index].mv[i]);
79 for (auto& mv : candidate_mvs[index].mv[i].mv) {
80 // The next line is equivalent to:
81 // const int value = (std::abs(static_cast<int>(mv)) + 3) & ~7;
82 // const int sign = mv >> 15;
83 // mv = ApplySign(value, sign);
84 mv = (mv + 3 - (mv >> 15)) & ~7;
85 }
86 }
87 }
88 } while (++index < count);
89 }
90
MvProjectionCompoundHighPrecision_C(const MotionVector * LIBGAV1_RESTRICT const temporal_mvs,const int8_t * LIBGAV1_RESTRICT const temporal_reference_offsets,const int reference_offsets[2],const int count,CompoundMotionVector * LIBGAV1_RESTRICT const candidate_mvs)91 void MvProjectionCompoundHighPrecision_C(
92 const MotionVector* LIBGAV1_RESTRICT const temporal_mvs,
93 const int8_t* LIBGAV1_RESTRICT const temporal_reference_offsets,
94 const int reference_offsets[2], const int count,
95 CompoundMotionVector* LIBGAV1_RESTRICT const candidate_mvs) {
96 // To facilitate the compilers, make a local copy of |reference_offsets|.
97 const int offsets[2] = {reference_offsets[0], reference_offsets[1]};
98 int index = 0;
99 do {
100 candidate_mvs[index].mv64 = 0;
101 for (int i = 0; i < 2; ++i) {
102 // |offsets| non-zero check usually equals true and could be ignored.
103 if (offsets[i] != 0) {
104 GetMvProjection(
105 temporal_mvs[index], offsets[i],
106 kProjectionMvDivisionLookup[temporal_reference_offsets[index]],
107 &candidate_mvs[index].mv[i]);
108 }
109 }
110 } while (++index < count);
111 }
112
MvProjectionSingleLowPrecision_C(const MotionVector * LIBGAV1_RESTRICT const temporal_mvs,const int8_t * LIBGAV1_RESTRICT const temporal_reference_offsets,const int reference_offset,const int count,MotionVector * LIBGAV1_RESTRICT const candidate_mvs)113 void MvProjectionSingleLowPrecision_C(
114 const MotionVector* LIBGAV1_RESTRICT const temporal_mvs,
115 const int8_t* LIBGAV1_RESTRICT const temporal_reference_offsets,
116 const int reference_offset, const int count,
117 MotionVector* LIBGAV1_RESTRICT const candidate_mvs) {
118 int index = 0;
119 do {
120 GetMvProjection(
121 temporal_mvs[index], reference_offset,
122 kProjectionMvDivisionLookup[temporal_reference_offsets[index]],
123 &candidate_mvs[index]);
124 for (auto& mv : candidate_mvs[index].mv) {
125 // The next line is equivalent to:
126 // if ((mv & 1) != 0) mv += (mv > 0) ? -1 : 1;
127 mv = (mv - (mv >> 15)) & ~1;
128 }
129 } while (++index < count);
130 }
131
MvProjectionSingleForceInteger_C(const MotionVector * LIBGAV1_RESTRICT const temporal_mvs,const int8_t * LIBGAV1_RESTRICT const temporal_reference_offsets,const int reference_offset,const int count,MotionVector * LIBGAV1_RESTRICT const candidate_mvs)132 void MvProjectionSingleForceInteger_C(
133 const MotionVector* LIBGAV1_RESTRICT const temporal_mvs,
134 const int8_t* LIBGAV1_RESTRICT const temporal_reference_offsets,
135 const int reference_offset, const int count,
136 MotionVector* LIBGAV1_RESTRICT 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 * LIBGAV1_RESTRICT const temporal_mvs,const int8_t * LIBGAV1_RESTRICT const temporal_reference_offsets,const int reference_offset,const int count,MotionVector * LIBGAV1_RESTRICT const candidate_mvs)153 void MvProjectionSingleHighPrecision_C(
154 const MotionVector* LIBGAV1_RESTRICT const temporal_mvs,
155 const int8_t* LIBGAV1_RESTRICT const temporal_reference_offsets,
156 const int reference_offset, const int count,
157 MotionVector* LIBGAV1_RESTRICT const candidate_mvs) {
158 int index = 0;
159 do {
160 GetMvProjection(
161 temporal_mvs[index], reference_offset,
162 kProjectionMvDivisionLookup[temporal_reference_offsets[index]],
163 &candidate_mvs[index]);
164 } while (++index < count);
165 }
166
167 #endif // LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS ||
168 // !defined(LIBGAV1_Dsp8bpp_MotionVectorSearch)
169
170 } // namespace
171
MotionVectorSearchInit_C()172 void MotionVectorSearchInit_C() {
173 #if LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS || \
174 !defined(LIBGAV1_Dsp8bpp_MotionVectorSearch)
175 Dsp* const dsp = dsp_internal::GetWritableDspTable(kBitdepth8);
176 assert(dsp != nullptr);
177 dsp->mv_projection_compound[0] = MvProjectionCompoundLowPrecision_C;
178 dsp->mv_projection_compound[1] = MvProjectionCompoundForceInteger_C;
179 dsp->mv_projection_compound[2] = MvProjectionCompoundHighPrecision_C;
180 dsp->mv_projection_single[0] = MvProjectionSingleLowPrecision_C;
181 dsp->mv_projection_single[1] = MvProjectionSingleForceInteger_C;
182 dsp->mv_projection_single[2] = MvProjectionSingleHighPrecision_C;
183 #endif
184 }
185
186 } // namespace dsp
187 } // namespace libgav1
188