• 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_field_projection.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/reference_info.h"
26 #include "src/utils/types.h"
27 
28 namespace libgav1 {
29 namespace dsp {
30 namespace {
31 
32 // Silence unused function warnings when MotionFieldProjectionKernel_C is
33 // not used.
34 #if LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS ||                      \
35     !defined(LIBGAV1_Dsp8bpp_MotionFieldProjectionKernel) || \
36     (LIBGAV1_MAX_BITDEPTH >= 10 &&                           \
37      !defined(LIBGAV1_Dsp10bpp_MotionFieldProjectionKernel))
38 
39 // 7.9.2.
MotionFieldProjectionKernel_C(const ReferenceInfo & reference_info,int reference_to_current_with_sign,int dst_sign,int y8_start,int y8_end,int x8_start,int x8_end,TemporalMotionField * motion_field)40 void MotionFieldProjectionKernel_C(const ReferenceInfo& reference_info,
41                                    int reference_to_current_with_sign,
42                                    int dst_sign, int y8_start, int y8_end,
43                                    int x8_start, int x8_end,
44                                    TemporalMotionField* motion_field) {
45   const ptrdiff_t stride = motion_field->mv.columns();
46   // The column range has to be offset by kProjectionMvMaxHorizontalOffset since
47   // coordinates in that range could end up being position_x8 because of
48   // projection.
49   const int adjusted_x8_start =
50       std::max(x8_start - kProjectionMvMaxHorizontalOffset, 0);
51   const int adjusted_x8_end = std::min(
52       x8_end + kProjectionMvMaxHorizontalOffset, static_cast<int>(stride));
53   const int8_t* const reference_offsets =
54       reference_info.relative_distance_to.data();
55   const bool* const skip_references = reference_info.skip_references.data();
56   const int16_t* const projection_divisions =
57       reference_info.projection_divisions.data();
58   const ReferenceFrameType* source_reference_types =
59       &reference_info.motion_field_reference_frame[y8_start][0];
60   const MotionVector* mv = &reference_info.motion_field_mv[y8_start][0];
61   int8_t* dst_reference_offset = motion_field->reference_offset[y8_start];
62   MotionVector* dst_mv = motion_field->mv[y8_start];
63   assert(stride == motion_field->reference_offset.columns());
64   assert((y8_start & 7) == 0);
65 
66   int y8 = y8_start;
67   do {
68     const int y8_floor = (y8 & ~7) - y8;
69     const int y8_ceiling = std::min(y8_end - y8, y8_floor + 8);
70     int x8 = adjusted_x8_start;
71     do {
72       const int source_reference_type = source_reference_types[x8];
73       if (skip_references[source_reference_type]) continue;
74       MotionVector projection_mv;
75       // reference_to_current_with_sign could be 0.
76       GetMvProjection(mv[x8], reference_to_current_with_sign,
77                       projection_divisions[source_reference_type],
78                       &projection_mv);
79       // Do not update the motion vector if the block position is not valid or
80       // if position_x8 is outside the current range of x8_start and x8_end.
81       // Note that position_y8 will always be within the range of y8_start and
82       // y8_end.
83       const int position_y8 = Project(0, projection_mv.mv[0], dst_sign);
84       if (position_y8 < y8_floor || position_y8 >= y8_ceiling) continue;
85       const int x8_base = x8 & ~7;
86       const int x8_floor =
87           std::max(x8_start, x8_base - kProjectionMvMaxHorizontalOffset);
88       const int x8_ceiling =
89           std::min(x8_end, x8_base + 8 + kProjectionMvMaxHorizontalOffset);
90       const int position_x8 = Project(x8, projection_mv.mv[1], dst_sign);
91       if (position_x8 < x8_floor || position_x8 >= x8_ceiling) continue;
92       dst_mv[position_y8 * stride + position_x8] = mv[x8];
93       dst_reference_offset[position_y8 * stride + position_x8] =
94           reference_offsets[source_reference_type];
95     } while (++x8 < adjusted_x8_end);
96     source_reference_types += stride;
97     mv += stride;
98     dst_reference_offset += stride;
99     dst_mv += stride;
100   } while (++y8 < y8_end);
101 }
102 
103 #endif  // LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS ||
104         // !defined(LIBGAV1_Dsp8bpp_MotionFieldProjectionKernel) ||
105         // (LIBGAV1_MAX_BITDEPTH >= 10 &&
106         //  !defined(LIBGAV1_Dsp10bpp_MotionFieldProjectionKernel))
107 
Init8bpp()108 void Init8bpp() {
109 #if LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS || \
110     !defined(LIBGAV1_Dsp8bpp_MotionFieldProjectionKernel)
111   Dsp* const dsp = dsp_internal::GetWritableDspTable(8);
112   assert(dsp != nullptr);
113   dsp->motion_field_projection_kernel = MotionFieldProjectionKernel_C;
114 #endif
115 }
116 
117 #if LIBGAV1_MAX_BITDEPTH >= 10
Init10bpp()118 void Init10bpp() {
119 #if LIBGAV1_ENABLE_ALL_DSP_FUNCTIONS || \
120     !defined(LIBGAV1_Dsp10bpp_MotionFieldProjectionKernel)
121   Dsp* const dsp = dsp_internal::GetWritableDspTable(10);
122   assert(dsp != nullptr);
123   dsp->motion_field_projection_kernel = MotionFieldProjectionKernel_C;
124 #endif
125 }
126 #endif
127 
128 }  // namespace
129 
MotionFieldProjectionInit_C()130 void MotionFieldProjectionInit_C() {
131   Init8bpp();
132 #if LIBGAV1_MAX_BITDEPTH >= 10
133   Init10bpp();
134 #endif
135 }
136 
137 }  // namespace dsp
138 }  // namespace libgav1
139