diff options
Diffstat (limited to 'src/dsp/motion_vector_search.cc')
-rw-r--r-- | src/dsp/motion_vector_search.cc | 211 |
1 files changed, 211 insertions, 0 deletions
diff --git a/src/dsp/motion_vector_search.cc b/src/dsp/motion_vector_search.cc new file mode 100644 index 0000000..9402302 --- /dev/null +++ b/src/dsp/motion_vector_search.cc @@ -0,0 +1,211 @@ +// Copyright 2020 The libgav1 Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "src/dsp/motion_vector_search.h" + +#include <algorithm> +#include <cassert> +#include <cstddef> +#include <cstdint> + +#include "src/dsp/dsp.h" +#include "src/utils/common.h" +#include "src/utils/constants.h" +#include "src/utils/types.h" + +namespace libgav1 { +namespace dsp { +namespace { + +// Silence unused function warnings when the C functions are not used. +#if LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS || \ + !defined(LIBGAV1_Dsp8bpp_MotionVectorSearch) || \ + (LIBGAV1_MAX_BITDEPTH >= 10 && \ + !defined(LIBGAV1_Dsp10bpp_MotionVectorSearch)) + +void 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) { + // To facilitate the compilers, make a local copy of |reference_offsets|. + const int offsets[2] = {reference_offsets[0], reference_offsets[1]}; + int index = 0; + do { + candidate_mvs[index].mv64 = 0; + for (int i = 0; i < 2; ++i) { + // |offsets| non-zero check usually equals true and could be ignored. + if (offsets[i] != 0) { + GetMvProjection( + temporal_mvs[index], offsets[i], + kProjectionMvDivisionLookup[temporal_reference_offsets[index]], + &candidate_mvs[index].mv[i]); + for (auto& mv : candidate_mvs[index].mv[i].mv) { + // The next line is equivalent to: + // if ((mv & 1) != 0) mv += (mv > 0) ? -1 : 1; + mv = (mv - (mv >> 15)) & ~1; + } + } + } + } while (++index < count); +} + +void 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) { + // To facilitate the compilers, make a local copy of |reference_offsets|. + const int offsets[2] = {reference_offsets[0], reference_offsets[1]}; + int index = 0; + do { + candidate_mvs[index].mv64 = 0; + for (int i = 0; i < 2; ++i) { + // |offsets| non-zero check usually equals true and could be ignored. + if (offsets[i] != 0) { + GetMvProjection( + temporal_mvs[index], offsets[i], + kProjectionMvDivisionLookup[temporal_reference_offsets[index]], + &candidate_mvs[index].mv[i]); + for (auto& mv : candidate_mvs[index].mv[i].mv) { + // The next line is equivalent to: + // const int value = (std::abs(static_cast<int>(mv)) + 3) & ~7; + // const int sign = mv >> 15; + // mv = ApplySign(value, sign); + mv = (mv + 3 - (mv >> 15)) & ~7; + } + } + } + } while (++index < count); +} + +void 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) { + // To facilitate the compilers, make a local copy of |reference_offsets|. + const int offsets[2] = {reference_offsets[0], reference_offsets[1]}; + int index = 0; + do { + candidate_mvs[index].mv64 = 0; + for (int i = 0; i < 2; ++i) { + // |offsets| non-zero check usually equals true and could be ignored. + if (offsets[i] != 0) { + GetMvProjection( + temporal_mvs[index], offsets[i], + kProjectionMvDivisionLookup[temporal_reference_offsets[index]], + &candidate_mvs[index].mv[i]); + } + } + } while (++index < count); +} + +void 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) { + int index = 0; + do { + GetMvProjection( + temporal_mvs[index], reference_offset, + kProjectionMvDivisionLookup[temporal_reference_offsets[index]], + &candidate_mvs[index]); + for (auto& mv : candidate_mvs[index].mv) { + // The next line is equivalent to: + // if ((mv & 1) != 0) mv += (mv > 0) ? -1 : 1; + mv = (mv - (mv >> 15)) & ~1; + } + } while (++index < count); +} + +void 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) { + int index = 0; + do { + GetMvProjection( + temporal_mvs[index], reference_offset, + kProjectionMvDivisionLookup[temporal_reference_offsets[index]], + &candidate_mvs[index]); + for (auto& mv : candidate_mvs[index].mv) { + // The next line is equivalent to: + // const int value = (std::abs(static_cast<int>(mv)) + 3) & ~7; + // const int sign = mv >> 15; + // mv = ApplySign(value, sign); + mv = (mv + 3 - (mv >> 15)) & ~7; + } + } while (++index < count); +} + +void 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) { + int index = 0; + do { + GetMvProjection( + temporal_mvs[index], reference_offset, + kProjectionMvDivisionLookup[temporal_reference_offsets[index]], + &candidate_mvs[index]); + } while (++index < count); +} + +#endif // LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS || + // !defined(LIBGAV1_Dsp8bpp_MotionVectorSearch) || + // (LIBGAV1_MAX_BITDEPTH >= 10 && + // !defined(LIBGAV1_Dsp10bpp_MotionVectorSearch)) + +void Init8bpp() { +#if LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS || \ + !defined(LIBGAV1_Dsp8bpp_MotionVectorSearch) + Dsp* const dsp = dsp_internal::GetWritableDspTable(8); + assert(dsp != nullptr); + dsp->mv_projection_compound[0] = MvProjectionCompoundLowPrecision_C; + dsp->mv_projection_compound[1] = MvProjectionCompoundForceInteger_C; + dsp->mv_projection_compound[2] = MvProjectionCompoundHighPrecision_C; + dsp->mv_projection_single[0] = MvProjectionSingleLowPrecision_C; + dsp->mv_projection_single[1] = MvProjectionSingleForceInteger_C; + dsp->mv_projection_single[2] = MvProjectionSingleHighPrecision_C; +#endif +} + +#if LIBGAV1_MAX_BITDEPTH >= 10 +void Init10bpp() { +#if LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS || \ + !defined(LIBGAV1_Dsp10bpp_MotionVectorSearch) + Dsp* const dsp = dsp_internal::GetWritableDspTable(10); + assert(dsp != nullptr); + dsp->mv_projection_compound[0] = MvProjectionCompoundLowPrecision_C; + dsp->mv_projection_compound[1] = MvProjectionCompoundForceInteger_C; + dsp->mv_projection_compound[2] = MvProjectionCompoundHighPrecision_C; + dsp->mv_projection_single[0] = MvProjectionSingleLowPrecision_C; + dsp->mv_projection_single[1] = MvProjectionSingleForceInteger_C; + dsp->mv_projection_single[2] = MvProjectionSingleHighPrecision_C; +#endif +} +#endif + +} // namespace + +void MotionVectorSearchInit_C() { + Init8bpp(); +#if LIBGAV1_MAX_BITDEPTH >= 10 + Init10bpp(); +#endif +} + +} // namespace dsp +} // namespace libgav1 |