Coverage Report

Created: 2026-04-01 07:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vvdec/source/Lib/CommonLib/MotionInfo.h
Line
Count
Source
1
/* -----------------------------------------------------------------------------
2
The copyright in this software is being made available under the Clear BSD
3
License, included below. No patent rights, trademark rights and/or 
4
other Intellectual Property Rights other than the copyrights concerning 
5
the Software are granted under this license.
6
7
The Clear BSD License
8
9
Copyright (c) 2018-2026, Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. & The VVdeC Authors.
10
All rights reserved.
11
12
Redistribution and use in source and binary forms, with or without modification,
13
are permitted (subject to the limitations in the disclaimer below) provided that
14
the following conditions are met:
15
16
     * Redistributions of source code must retain the above copyright notice,
17
     this list of conditions and the following disclaimer.
18
19
     * Redistributions in binary form must reproduce the above copyright
20
     notice, this list of conditions and the following disclaimer in the
21
     documentation and/or other materials provided with the distribution.
22
23
     * Neither the name of the copyright holder nor the names of its
24
     contributors may be used to endorse or promote products derived from this
25
     software without specific prior written permission.
26
27
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
28
THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
29
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
31
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
32
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
33
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
34
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
35
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
36
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38
POSSIBILITY OF SUCH DAMAGE.
39
40
41
------------------------------------------------------------------------------------------- */
42
43
/** \file     MotionInfo.h
44
    \brief    motion information handling classes (header)
45
    \todo     MvField seems to be better to be inherited from Mv
46
*/
47
48
#pragma once
49
50
#include "CommonDef.h"
51
#include "Mv.h"
52
53
namespace vvdec
54
{
55
56
// need miInvalid to be able to distinguish between different motion types, e.g. history, colocated or just motion info
57
static inline bool isMotionInvalid( int refIdx, const int miInvalid )
58
0
{
59
0
  static_assert( MH_NOT_VALID == -1 && MI_NOT_VALID == -1 && MF_NOT_VALID == -1 && CO_NOT_VALID == -1, "All not-valid motion need to be nagative for current impl!" );
60
0
  return refIdx < 0;
61
0
}
Unexecuted instantiation: vvdec.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: vvdecimpl.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: Buffer.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: InterpolationFilter.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: LoopFilter.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: PicListManager.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: Picture.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: RdCost.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: Rom.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: SampleAdaptiveOffset.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: Slice.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: Unit.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: UnitTools.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: DecLib.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: DecLibParser.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: DecLibRecon.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: DecSlice.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: HLSyntaxReader.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: SEIread.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: InitX86.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: AdaptiveLoopFilter_sse41.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: Buffer_sse41.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: InterPred_sse41.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: InterpolationFilter_sse41.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: IntraPred_sse41.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: LoopFilter_sse41.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: Picture_sse41.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: Quant_sse41.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: RdCost_sse41.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: SampleAdaptiveOffset_sse41.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: Trafo_sse41.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: AdaptiveLoopFilter_avx2.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: Buffer_avx2.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: InterPred_avx2.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: InterpolationFilter_avx2.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: IntraPred_avx2.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: LoopFilter_avx2.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: Picture_avx2.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: Quant_avx2.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: RdCost_avx2.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: SampleAdaptiveOffset_avx2.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: Trafo_avx2.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: AdaptiveLoopFilter.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: CodingStructure.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: InterPrediction.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: IntraPrediction.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: MatrixIntraPrediction.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: PicYuvMD5.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: Quant.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: Reshape.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: TrQuant.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: TrQuant_EMT.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: UnitPartitioner.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: WeightPrediction.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: CABACReader.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: DecCu.cpp:vvdec::isMotionInvalid(int, int)
Unexecuted instantiation: ContextModelling.cpp:vvdec::isMotionInvalid(int, int)
62
63
// need miInvalid to be able to distinguish between different motion types, e.g. history, colocated or just motion info
64
static inline bool isMotionValid( int refIdx, const int miInvalid )
65
0
{
66
0
  return !isMotionInvalid( refIdx, miInvalid );
67
0
}
Unexecuted instantiation: vvdec.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: vvdecimpl.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: Buffer.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: InterpolationFilter.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: LoopFilter.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: PicListManager.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: Picture.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: RdCost.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: Rom.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: SampleAdaptiveOffset.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: Slice.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: Unit.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: UnitTools.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: DecLib.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: DecLibParser.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: DecLibRecon.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: DecSlice.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: HLSyntaxReader.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: SEIread.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: InitX86.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: AdaptiveLoopFilter_sse41.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: Buffer_sse41.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: InterPred_sse41.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: InterpolationFilter_sse41.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: IntraPred_sse41.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: LoopFilter_sse41.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: Picture_sse41.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: Quant_sse41.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: RdCost_sse41.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: SampleAdaptiveOffset_sse41.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: Trafo_sse41.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: AdaptiveLoopFilter_avx2.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: Buffer_avx2.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: InterPred_avx2.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: InterpolationFilter_avx2.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: IntraPred_avx2.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: LoopFilter_avx2.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: Picture_avx2.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: Quant_avx2.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: RdCost_avx2.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: SampleAdaptiveOffset_avx2.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: Trafo_avx2.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: AdaptiveLoopFilter.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: CodingStructure.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: InterPrediction.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: IntraPrediction.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: MatrixIntraPrediction.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: PicYuvMD5.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: Quant.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: Reshape.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: TrQuant.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: TrQuant_EMT.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: UnitPartitioner.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: WeightPrediction.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: CABACReader.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: DecCu.cpp:vvdec::isMotionValid(int, int)
Unexecuted instantiation: ContextModelling.cpp:vvdec::isMotionValid(int, int)
68
69
// ====================================================================================================================
70
// Type definition
71
// ====================================================================================================================
72
73
/// parameters for AMVP
74
struct AMVPInfo
75
{
76
  Mv       mvCand[ AMVP_MAX_NUM_CANDS_MEM ];  ///< array of motion vector predictor candidates
77
  unsigned numCand;                       ///< number of motion vector predictor candidates
78
};
79
80
struct AffineAMVPInfo
81
{
82
  Mv       mvCandLT[ AMVP_MAX_NUM_CANDS_MEM ];  ///< array of affine motion vector predictor candidates for left-top corner
83
  Mv       mvCandRT[ AMVP_MAX_NUM_CANDS_MEM ];  ///< array of affine motion vector predictor candidates for right-top corner
84
  Mv       mvCandLB[ AMVP_MAX_NUM_CANDS_MEM ];  ///< array of affine motion vector predictor candidates for left-bottom corner
85
  unsigned numCand;                       ///< number of motion vector predictor candidates
86
};
87
88
// ====================================================================================================================
89
// Class definition
90
// ====================================================================================================================
91
92
/// class for motion vector with reference index
93
struct MvField
94
{
95
  Mv     mv;
96
  int8_t mfRefIdx = MF_NOT_VALID;
97
98
0
  MvField() = default;
99
0
  MvField( Mv const & cMv, const int iRefIdx ) : mv( cMv ), mfRefIdx(   iRefIdx ) {}
100
101
  void setMvField( Mv const & cMv, const int iRefIdx )
102
0
  {
103
    //CHECKD( iRefIdx == MF_NOT_VALID && cMv != Mv(0,0), "Must not happen." );
104
0
    mv     = cMv;
105
0
    mfRefIdx = iRefIdx;
106
0
  }
107
108
  bool operator==( const MvField& other ) const
109
0
  {
110
0
    //CHECKD( mfRefIdx == MF_NOT_VALID && mv != Mv(0,0), "Error in operator== of MvField." );
111
0
    //CHECKD( other.mfRefIdx == MF_NOT_VALID && other.mv != Mv(0,0), "Error in operator== of MvField." );
112
0
    return mfRefIdx == other.mfRefIdx && mv == other.mv;
113
0
  }
114
  bool operator!=( const MvField& other ) const
115
0
  {
116
0
    //CHECKD( mfRefIdx == MF_NOT_VALID && mv != Mv(0,0), "Error in operator!= of MvField." );
117
0
    //CHECKD( other.mfRefIdx == MF_NOT_VALID && other.mv != Mv(0,0), "Error in operator!= of MvField." );
118
0
    return mfRefIdx != other.mfRefIdx || mv != other.mv;
119
0
  }
120
};
121
122
struct MotionInfo
123
{
124
  Mv       mv      [NUM_REF_PIC_LIST_01];
125
  int8_t   miRefIdx[NUM_REF_PIC_LIST_01] = { MI_NOT_VALID, MI_NOT_VALID };
126
127
  bool operator==( const MotionInfo &mi ) const
128
0
  {
129
0
    if( miRefIdx[0] != mi.miRefIdx[0] ) return false;
130
0
    if( isMotionValid( miRefIdx[0], MI_NOT_VALID ) && mv[0] != mi.mv[0] ) return false;
131
132
0
    if( miRefIdx[1] != mi.miRefIdx[1] ) return false;
133
0
    if( isMotionValid( miRefIdx[1], MI_NOT_VALID ) && mv[1] != mi.mv[1] ) return false;
134
135
0
    return true;
136
0
  }
137
138
  bool operator!=( const MotionInfo &mi ) const
139
0
  {
140
0
    return !( *this == mi );
141
0
  }
142
143
  bool isInter() const
144
0
  {
145
0
    return interDir() != 0;
146
0
  }
147
148
  int interDir() const
149
0
  {
150
0
    int
151
0
    interDir  = isMotionInvalid( miRefIdx[0], MI_NOT_VALID ) ? 0 : 1;
152
0
    interDir += isMotionInvalid( miRefIdx[1], MI_NOT_VALID ) ? 0 : 2;
153
0
    return interDir;
154
0
  }
155
};
156
157
struct ColocatedMotionInfo
158
{
159
  Mv       mv      [NUM_REF_PIC_LIST_01];
160
  int8_t   coRefIdx[NUM_REF_PIC_LIST_01] = { CO_NOT_VALID, CO_NOT_VALID };
161
162
  int interDir() const
163
0
  {
164
0
    int
165
0
    interDir  = isMotionInvalid( coRefIdx[0], CO_NOT_VALID ) ? 0 : 1;
166
0
    interDir += isMotionInvalid( coRefIdx[1], CO_NOT_VALID ) ? 0 : 2;
167
0
    return interDir;
168
0
  }
169
170
  bool isInter() const
171
0
  {
172
0
    return interDir() != 0;
173
0
  }
174
175
  ColocatedMotionInfo &operator=( const MotionInfo &rhs )
176
0
  {
177
0
    static_assert( sizeof( MotionInfo ) == sizeof( ColocatedMotionInfo ), "MotionInfo and ColocatedMotionInfo require the same memory layout" );
178
0
    static_assert( std::is_standard_layout<MotionInfo>         ::value &&
179
0
                   std::is_standard_layout<ColocatedMotionInfo>::value,
180
0
                   "offsetof is only valid for standard layout types" );
181
0
    static_assert( offsetof( MotionInfo, mv )       == offsetof( ColocatedMotionInfo, mv ) &&
182
0
                   offsetof( MotionInfo, miRefIdx ) == offsetof( ColocatedMotionInfo, coRefIdx ),
183
0
                   "MotionInfo and ColocatedMotionInfo require the same memory layout" );
184
185
0
    memcpy( NO_WARNING_class_memaccess( this ), &rhs, sizeof( MotionInfo ) );
186
187
0
    return *this;
188
0
  }
189
};
190
191
struct HPMVInfo
192
{
193
  Mv       mv      [NUM_REF_PIC_LIST_01];
194
  int8_t   mhRefIdx[NUM_REF_PIC_LIST_01] = { MH_NOT_VALID, MH_NOT_VALID };
195
196
  uint8_t  BcwIdx       = 0;
197
  bool     useAltHpelIf = false;
198
199
0
  HPMVInfo() = default;
200
  HPMVInfo( const MotionInfo& mi, uint8_t BcwIdx, bool useAltHpelIf )
201
0
  {
202
0
    mv[0] = mi.mv[0];
203
0
    mv[1] = mi.mv[1];
204
205
0
    mhRefIdx[0] = mi.miRefIdx[0];
206
0
    mhRefIdx[1] = mi.miRefIdx[1];
207
208
0
    this->BcwIdx       = BcwIdx;
209
0
    this->useAltHpelIf = useAltHpelIf;
210
0
  }
211
212
  bool operator==( const HPMVInfo& mi ) const
213
0
  {
214
0
    if( mhRefIdx[0] != mi.mhRefIdx[0] ) return false;
215
0
    if( isMotionValid( mhRefIdx[0], MH_NOT_VALID ) && mv[0] != mi.mv[0] ) return false;
216
217
0
    if( mhRefIdx[1] != mi.mhRefIdx[1] ) return false;
218
0
    if( isMotionValid (mhRefIdx[1], MH_NOT_VALID ) && mv[1] != mi.mv[1] ) return false;
219
220
0
    return true;
221
0
  }
222
223
  bool operator!=( const HPMVInfo& mi ) const
224
0
  {
225
0
    return !( *this == mi );
226
0
  }
227
228
  int interDir() const
229
0
  {
230
0
    int
231
0
    interDir  = isMotionInvalid( mhRefIdx[0], MH_NOT_VALID ) ? 0 : 1;
232
0
    interDir += isMotionInvalid( mhRefIdx[1], MH_NOT_VALID ) ? 0 : 2;
233
0
    return interDir;
234
0
  }
235
};
236
237
struct MotionHist
238
{
239
  static_vector<HPMVInfo, MAX_NUM_HMVP_CANDS> motionLut;
240
  static_vector<HPMVInfo, MAX_NUM_HMVP_CANDS> motionLutIbc;
241
  
242
  static void addMiToLut( static_vector<HPMVInfo, MAX_NUM_HMVP_CANDS>& lut, const HPMVInfo &mi )
243
0
  {
244
0
    size_t currCnt = lut.size();
245
246
0
    bool pruned      = false;
247
0
    int  sameCandIdx = 0;
248
249
0
    for( int idx = 0; idx < currCnt; idx++ )
250
0
    {
251
0
      if( lut[idx] == mi )
252
0
      {
253
0
        sameCandIdx = idx;
254
0
        pruned = true;
255
0
        break;
256
0
      }
257
0
    }
258
259
0
    if( pruned || currCnt == lut.capacity() )
260
0
    {
261
0
      lut.erase( lut.begin() + sameCandIdx );
262
0
    }
263
264
0
    lut.push_back( mi );
265
0
  }
266
};
267
268
}