xref: /aosp_15_r20/external/libgav1/src/dsp/motion_vector_search.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/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