#ifndef X265_ANALYSIS_H
#define X265_ANALYSIS_H
#include "common.h"
#include "predict.h"
#include "quant.h"
#include "yuv.h"
#include "shortyuv.h"
#include "cudata.h"
#include "entropy.h"
#include "search.h"
namespace X265_NS {
class Entropy;
struct SplitData
{
uint32_t splitRefs;
uint32_t mvCost[2];
uint64_t sa8dCost;
void initSplitCUData()
{
splitRefs = 0;
mvCost[0] = 0;
mvCost[1] = 0;
sa8dCost = 0;
}
};
class Analysis : public Search
{
public:
enum {
PRED_MERGE,
PRED_SKIP,
PRED_INTRA,
PRED_2Nx2N,
PRED_BIDIR,
PRED_Nx2N,
PRED_2NxN,
PRED_SPLIT,
PRED_2NxnU,
PRED_2NxnD,
PRED_nLx2N,
PRED_nRx2N,
PRED_INTRA_NxN,
PRED_LOSSLESS,
MAX_PRED_TYPES
};
struct ModeDepth
{
Mode pred[MAX_PRED_TYPES];
Mode* bestMode;
Yuv fencYuv;
CUDataMemPool cuMemPool;
};
class PMODE : public BondedTaskGroup
{
public:
Analysis& master;
const CUGeom& cuGeom;
int modes[MAX_PRED_TYPES];
PMODE(Analysis& m, const CUGeom& g) : master(m), cuGeom(g) {}
void processTasks(int workerThreadId);
protected:
PMODE operator=(const PMODE&);
};
void processPmode(PMODE& pmode, Analysis& slave);
ModeDepth m_modeDepth[NUM_CU_DEPTH];
bool m_bTryLossless;
bool m_bChromaSa8d;
bool m_bHD;
Analysis();
bool create(ThreadLocalData* tld);
void destroy();
Mode& compressCTU(CUData& ctu, Frame& frame, const CUGeom& cuGeom, const Entropy& initialContext);
int32_t loadTUDepth(CUGeom cuGeom, CUData parentCTU);
protected:
analysis_inter_data* m_reuseInterDataCTU;
int32_t* m_reuseRef;
uint8_t* m_reuseDepth;
uint8_t* m_reuseModes;
uint8_t* m_reusePartSize;
uint8_t* m_reuseMergeFlag;
uint32_t m_splitRefIdx[4];
uint64_t* cacheCost;
analysis2PassFrameData* m_multipassAnalysis;
uint8_t* m_multipassDepth;
MV* m_multipassMv[2];
int* m_multipassMvpIdx[2];
int32_t* m_multipassRef[2];
uint8_t* m_multipassModes;
uint8_t m_evaluateInter;
uint8_t* m_additionalCtuInfo;
int* m_prevCtuInfoChange;
void qprdRefine(const CUData& parentCTU, const CUGeom& cuGeom, int32_t qp, int32_t lqp);
void compressIntraCU(const CUData& parentCTU, const CUGeom& cuGeom, int32_t qp);
uint32_t compressInterCU_dist(const CUData& parentCTU, const CUGeom& cuGeom, int32_t qp);
SplitData compressInterCU_rd0_4(const CUData& parentCTU, const CUGeom& cuGeom, int32_t qp);
SplitData compressInterCU_rd5_6(const CUData& parentCTU, const CUGeom& cuGeom, int32_t qp);
void recodeCU(const CUData& parentCTU, const CUGeom& cuGeom, int32_t qp, int32_t origqp = -1);
void checkMerge2Nx2N_rd0_4(Mode& skip, Mode& merge, const CUGeom& cuGeom);
void checkMerge2Nx2N_rd5_6(Mode& skip, Mode& merge, const CUGeom& cuGeom);
void checkInter_rd0_4(Mode& interMode, const CUGeom& cuGeom, PartSize partSize, uint32_t refmask[2]);
void checkInter_rd5_6(Mode& interMode, const CUGeom& cuGeom, PartSize partSize, uint32_t refmask[2]);
void checkBidir2Nx2N(Mode& inter2Nx2N, Mode& bidir2Nx2N, const CUGeom& cuGeom);
void tryLossless(const CUGeom& cuGeom);
void addSplitFlagCost(Mode& mode, uint32_t depth);
uint32_t topSkipMinDepth(const CUData& parentCTU, const CUGeom& cuGeom);
bool recursionDepthCheck(const CUData& parentCTU, const CUGeom& cuGeom, const Mode& bestMode);
bool complexityCheckCU(const Mode& bestMode);
void encodeResidue(const CUData& parentCTU, const CUGeom& cuGeom);
int calculateQpforCuSize(const CUData& ctu, const CUGeom& cuGeom, int32_t complexCheck = 0, double baseQP = -1);
void calculateNormFactor(CUData& ctu, int qp);
void normFactor(const pixel* src, uint32_t blockSize, CUData& ctu, int qp, TextType ttype);
void collectPUStatistics(const CUData& ctu, const CUGeom& cuGeom);
inline void checkBestMode(Mode& mode, uint32_t depth)
{
ModeDepth& md = m_modeDepth[depth];
if (md.bestMode)
{
if (mode.rdCost < md.bestMode->rdCost)
md.bestMode = &mode;
}
else
md.bestMode = &mode;
}
int findSameContentRefCount(const CUData& parentCTU, const CUGeom& cuGeom);
};
struct ThreadLocalData
{
Analysis analysis;
void destroy() { analysis.destroy(); }
};
}
#endif