146 lines
3.1 KiB
C++
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;
|
|
}
|
|
|
|
}
|
|
|