• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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