Files
UnrealEngine/Engine/Source/Runtime/AVEncoder/Private/Decoders/vdecmpeg4/M4MotionVectorMgr.h
2025-05-18 13:04:45 +08:00

146 lines
3.1 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "vdecmpeg4.h"
#include "M4Decoder.h"
#include "M4Memory.h"
#include "M4Global.h"
#include "M4MemOps.h"
namespace vdecmpeg4
{
class M4MotionVectorMgr
{
public:
//! Creation
static M4MotionVectorMgr* create(M4Decoder* pDecoder, M4MemHandler& memSys);
//! Destruction
static void destroy(M4MotionVectorMgr*& pMgr, M4MemHandler& memSys);
// -----------------------------------------------------------------------------------------
//! Init members for current frame
void init();
//! Read the motion vector residual from the bitstream
void readMvForward(M4_MB* mb);
//! Add the residual to the prediction
void predictAddForward(M4_MB* mb, int32 mbx, int32 mby);
//! Add predictor and input motion vector based on forward/backward code
void addMv(M4_VECTOR& res, uint16 code, const M4_VECTOR& inputMv, const M4_VECTOR& predictor)
{
int32 scale_fac = 1 << (code - 1);
int32 high = (32 * scale_fac) - 1;
int32 low = (-32 * scale_fac);
int32 range = (64 * scale_fac);
res.x = predictor.x + inputMv.x;
res.y = predictor.y + inputMv.y;
if (res.x < low)
{
res.x += range;
}
else if (res.x > high)
{
res.x -= range;
}
if (res.y < low)
{
res.y += range;
}
else if (res.y > high)
{
res.y -= range;
}
}
//! Add predicted motion vector to FORWARD prediction
void addMvForward(M4_VECTOR& res, const M4_VECTOR& inputMv, const M4_VECTOR& predictor)
{
// Add input motion vector to predictor
res.x = inputMv.x + predictor.x;
res.y = inputMv.y + predictor.y;
// clipping
if (res.x < mMvClipLow)
{
res.x += mMvClipRange;
}
else if (res.x > mMvClipHigh)
{
res.x -= mMvClipRange;
}
if (res.y < mMvClipLow)
{
res.y += mMvClipRange;
}
else if (res.y > mMvClipHigh)
{
res.y -= mMvClipRange;
}
}
//! Read motion vector residual from file
void readMv(M4_VECTOR& res, uint16 code)
{
// Get the differential motion vector (MVDx, MVDy) from the bitstream
res.x = mDecoder->mBitstreamParser.getMv(code);
res.y = mDecoder->mBitstreamParser.getMv(code);
}
//! Zero motion vector
static const M4_VECTOR MV_ZERO;
void* operator new(size_t sz, M4MemHandler& memSys);
void operator delete(void* ptr);
private:
//! Default constructor
M4MotionVectorMgr(M4Decoder* decoder);
//! Destructor
~M4MotionVectorMgr()
{
}
//! motion vector prediction
void _predictMv(M4_VECTOR& res, int32 mbx, int32 mby, uint32 block);
//! Default constructor
M4MotionVectorMgr();
//! Copy-constructor not implemented
M4MotionVectorMgr(const M4MotionVectorMgr &pObj);
//! Assignment operator not implemented
const M4MotionVectorMgr &operator=(const M4MotionVectorMgr &pObj);
int32 mMvClipHigh; //!< motion vector upper border
int32 mMvClipLow; //!< motion vector lower border
int32 mMvClipRange; //!< motion vector range
//! Reference to our decoder class
M4Decoder* mDecoder;
M4_MEMORY_HANDLER
};
//! GENERIC: Set all motion vectors to 0
inline void M4MotionVectorClear(M4_MB* mb)
{
FMemory::Memzero(mb->mFMv, sizeof(M4_VECTOR)*4);
mb->mMvResidual = 0;
}
}