📄 encoder.h
字号:
#ifndef _ENCODER_H_
#define _ENCODER_H_
#include "../mp4v.h"
#include "../common/common.h"
#include "../image/image.h"
// indicates no quantizer changes in INTRA_Q/INTER_Q modes
#define NO_CHANGE 64
void select_optcode_encoder(uint32_t cpu_flags);
int RMP4_enc_open(MP4V_ENC_PARAM * pParam);
int RMP4_enc_close(Encoder * pEnc);
int RMP4_enc_processing(Encoder * pEnc, MP4V_ENC_FRAME * pFrame);
// Added by David, 2002
#define TRB_Max 4
int RateControlInit(RateControl *rc, int32_t target_rate, int32_t reaction_delay_factor, int framerate,
int max_quant, int min_quant, double buffered_delay, int rc_mode, int quant, int quality);
int GetEstimatedQ(RateControl *rc);
int RateControlGetQ(RateControl *rc, const int32_t coding_type, const int32_t BVOP_following);
int RateControlUpdate(RateControl *rc, int16_t quant, const int32_t frame_size, const int32_t vop_type);
void find_distortion(RateControl *rc, uint8_t *org, uint8_t *rec, int32_t width, int32_t height);
void find_vop_properties(RateControl *rc, uint8_t *src, uint8_t *rec, uint32_t width, uint32_t height,\
MACROBLOCK *pMBs, uint32_t mb_width, uint32_t mb_height);
static __inline int IVOP_encode(Encoder * pEnc);
static __inline int PVOP_encode(Encoder * pEnc, bool force_inter);
static __inline int BVOP_encode(Encoder * pEnc, uint32_t TRB, uint32_t TRD);
#define Dark_threshold 30
#define Bright_threshold 180
static int DQtab[4] =
{
-1, -2, 1, 2
};
__inline void setMB_quant(const int32_t vop_type, MACROBLOCK *pMBs, uint32_t iquant, uint32_t iMB_number)
{
uint32_t i;
switch(vop_type)
{
case I_VOP:
for(i=0; i<iMB_number; i++)
{
pMBs->quant = iquant;
pMBs->dquant = NO_CHANGE;
pMBs->mode = MODE_INTRA;
pMBs ++;
}
break;
case P_VOP:
for(i=0; i<iMB_number; i++)
{
pMBs->quant = iquant;
pMBs->dquant = NO_CHANGE;
pMBs ++;
}
break;
case B_VOP:
for(i=0; i<iMB_number; i++)
{
pMBs->quant = iquant;
pMBs->dquant = NO_CHANGE;
pMBs ++;
}
break;
}
}
/*******************************************
* Measure complexity of VOP to be encoded
* David, Sigma Designs
* Apr.29, 2002
*******************************************/
__inline int32_t Complexity_I(MACROBLOCK *pMBs, int32_t iHsize, int32_t iVsize)
{
int32_t x, y;
MACROBLOCK *pMB;
int32_t complex = 0;
int32_t cur_cmp;
int32_t bright;
int32_t mean_complex;
int32_t mean_bright = 0;
int32_t inverse_mean_bright;
int32_t half_mean_bright;
int32_t double_mean_bright;
int32_t add_comp;
int32_t num_mb = iVsize*iHsize;
for(y=0; y<iVsize; y++)
{
pMB = pMBs+y*iHsize;
for(x=0; x<iHsize; x++)
{
cur_cmp = pMB->dev16;
mean_bright += pMB->mean16;
pMB->mb_complex = cur_cmp;
complex += cur_cmp;
pMB++;
}
}
mean_complex = complex/num_mb;
mean_bright = mean_bright / num_mb;
inverse_mean_bright = (1<<16)/mean_bright+1;
half_mean_bright = mean_bright >> 1;
if(half_mean_bright < Dark_threshold)
half_mean_bright = Dark_threshold;
double_mean_bright = mean_bright << 1;
if(double_mean_bright > Bright_threshold)
double_mean_bright = Bright_threshold;
for(y=0; y<iVsize; y++)
{
pMB = pMBs+y*iHsize;
for(x=0; x<iHsize; x++)
{
bright = pMB->mean16;
add_comp = 0;
if(bright > Bright_threshold && bright > double_mean_bright)
add_comp = ((bright-mean_bright)*mean_complex*inverse_mean_bright)>>16;
if(bright < Dark_threshold&& bright < half_mean_bright)
add_comp = ((mean_bright - bright)*mean_complex*inverse_mean_bright)>>16;
pMB->mb_complex += add_comp;
complex += add_comp;
pMB++;
}
}
mean_complex = complex/num_mb;
return mean_complex;
}
__inline int Complexity_P(MACROBLOCK *pMBs, int iHsize, int iVsize)
{
int x, y;
MACROBLOCK *pMB;
int complex = 0;
int mode;
int cur_cmp;
int mean_complex;
int32_t mean_bright = 0;
int32_t bright;
int32_t inverse_mean_bright;
int32_t half_mean_bright;
int32_t double_mean_bright;
int32_t add_comp;
int32_t num_mb = iVsize*iHsize;
for(y=0; y<iVsize; y++)
{
pMB = pMBs+y*iHsize;
for(x=0; x<iHsize; x++)
{
mode = pMB->mode;
mean_bright += pMB->mean16;
if(mode == MODE_INTER || mode == MODE_INTER_Q)
cur_cmp = pMB->sad16;
else if(mode == MODE_INTER4V)
cur_cmp = pMB->sad8_mb;
else //INTRA
{
cur_cmp = pMB->dev16;
}
cur_cmp ++;
pMB->mb_complex += cur_cmp;
complex += cur_cmp;
pMB ++;
}
}
mean_complex = complex/num_mb;
mean_bright = mean_bright/num_mb + 1;
inverse_mean_bright = (1<<16)/mean_bright+1;
half_mean_bright = mean_bright >> 1;
if(half_mean_bright < Dark_threshold)
half_mean_bright = Dark_threshold;
double_mean_bright = mean_bright << 1;
if(double_mean_bright > Bright_threshold)
double_mean_bright = Bright_threshold;
for(y=0; y<iVsize; y++)
{
pMB = pMBs+y*iHsize;
for(x=0; x<iHsize; x++)
{
mode = pMB->mode;
bright = pMB->mean16;
add_comp = 0;
if(mode != MODE_INTRA)
{
if(bright > Bright_threshold && bright > double_mean_bright)
add_comp = ((bright-mean_bright)*mean_complex*inverse_mean_bright)>>16;
if(bright < Dark_threshold&& bright < half_mean_bright)
add_comp = ((mean_bright - bright)*mean_complex*inverse_mean_bright)>>16;
pMB->mb_complex += add_comp;
complex += add_comp;
}
pMB ++;
}
}
mean_complex = complex/num_mb;
return mean_complex;
}
__inline int Complexity_B(MACROBLOCK *pMBs, int iHsize, int iVsize)
{
int32_t x, y;
MACROBLOCK *pMB;
int32_t complex = 0;
int32_t cur_cmp;
int32_t mean_complex;
int32_t mean_bright = 0;
int32_t bright;
int32_t inverse_mean_bright;
int32_t half_mean_bright;
int32_t double_mean_bright;
int32_t add_comp;
int32_t num_mb = iVsize*iHsize;
for(y=0; y<iVsize; y++)
{
pMB = pMBs+y*iHsize;
for(x=0; x<iHsize; x++)
{
cur_cmp = pMB->sad16;
mean_bright += pMB->mean16;
cur_cmp ++;
complex += cur_cmp;
pMB->mb_complex += cur_cmp;
pMB++;
}
}
mean_complex = complex/num_mb;
mean_bright = mean_bright/num_mb+1;
inverse_mean_bright = (1<<16)/mean_bright+1;
half_mean_bright = mean_bright >> 1;
if(half_mean_bright < Dark_threshold)
half_mean_bright = Dark_threshold;
double_mean_bright = mean_bright << 1;
if(double_mean_bright > Bright_threshold)
double_mean_bright = Bright_threshold;
for(y=0; y<iVsize; y++)
{
pMB = pMBs+y*iHsize;
for(x=0; x<iHsize; x++)
{
bright = pMB->mean16;
if(bright > Bright_threshold && bright > half_mean_bright)
add_comp = ((bright-mean_bright)*mean_complex*inverse_mean_bright)>>16;
if(bright < Dark_threshold&& bright < double_mean_bright)
add_comp = ((mean_bright - bright)*mean_complex*inverse_mean_bright)>>16;
pMB->mb_complex += add_comp;
complex += add_comp;
pMB ++;
}
}
mean_complex = complex / num_mb;
return mean_complex;
}
/*******************************************
* Measure Activity of Encoded Image
* For P-only or PB decision
* David, Sigma Designs
* Feb.21, 2002
*******************************************/
__inline int measureActivity(MACROBLOCK *pMBs, int iHsize, int iVsize, int iQuant,
int32_t *iMvCurVOP, int32_t *iMvCount)
{
int32_t x, y;
MACROBLOCK *pMB;
int32_t act = 0;
int32_t mode;
int32_t cur_act = 0;
*iMvCount = 0;
*iMvCurVOP = 0;
for(y=0; y<iVsize; y++)
{
pMB = pMBs+y*iHsize;
for(x=0; x<iHsize; x++)
{
mode = pMB->mode;
if(mode == MODE_INTER || mode == MODE_INTER_Q)
cur_act = abs(pMB->mvs[0].x) + abs(pMB->mvs[0].y);
else
{
if(mode == MODE_INTER4V)
cur_act = (abs(pMB->mvs[0].x) + abs(pMB->mvs[0].y) +
abs(pMB->mvs[1].x) + abs(pMB->mvs[1].y) +
abs(pMB->mvs[2].x) + abs(pMB->mvs[2].y) +
abs(pMB->mvs[3].x) + abs(pMB->mvs[3].y)
)>>2;
else
cur_act = 0;
}
act += cur_act;
pMB->mb_complex = cur_act*iQuant;
if(cur_act)
{
(*iMvCurVOP) += cur_act;
(*iMvCount) ++;
}
pMB++;
}
}
#ifdef _STAT_
printf("\niMVvop=%d, iMvcount=%d\n", *iMvCurVOP, *iMvCount);
#endif
if(*iMvCount == 0)
*iMvCount = 1;
return (act/(iVsize*iHsize));
}
/*******************************************
* Measure Activity of Encoded Image
* For P-only or PB decision
* Measure the motion activity of BVOP
* David, Sigma Designs
* Feb.21, 2002
*******************************************/
__inline int measureActivity_B(MACROBLOCK *pMBs, int iHsize, int iVsize, int iQuant)
{
int x, y;
MACROBLOCK *pMB;
int act = 0;
int act_for, act_back;
int cur_act = 0;
int mode;
for(y=0; y<iVsize; y++)
for(x=0; x<iHsize; x++)
{
pMB = pMBs+y*iHsize+x;
mode = pMB->mode;
if(mode == MBM_B_FWDFRM)
cur_act = abs(pMB->mvs[0].x) + abs(pMB->mvs[0].y);
else
{
if(mode == MBM_B_BAKFRM)
cur_act = abs(pMB->mvs[1].x) + abs(pMB->mvs[1].y);
else
{
if(mode == MBM_B_AVEFRM || mode == MBM_B_DIRECT)
{
act_for = abs(pMB->mvs[0].x) + abs(pMB->mvs[0].y);
act_back = abs(pMB->mvs[1].x) + abs(pMB->mvs[1].y);
if(act_for > act_back)
cur_act = act_for;
else
cur_act = act_back;
}
else
cur_act = 0;
}
}
act += cur_act;
pMB->mb_complex = cur_act;
}
return (act/(iVsize*iHsize));
}
static __inline uint8_t get_fcode(uint16_t sr)
{
if (sr <= 16)
return 1;
else if (sr <= 32)
return 2;
else if (sr <= 64)
return 3;
else if (sr <= 128)
return 4;
else if (sr <= 256)
return 5;
else if (sr <= 512)
return 6;
else if (sr <= 1024)
return 7;
else
return 0;
}
__inline uint8_t * align_malloc(uint32_t size)
{
uint8_t * mem, *mem_ptr;
mem = (uint8_t *)malloc(size+32);
mem_ptr = (uint8_t *)(((uint32_t)mem + 16)&(~15));
*(mem_ptr-1) = mem_ptr - mem;
return mem_ptr;
}
__inline void align_free(uint8_t *mem_ptr)
{
uint8_t *mem = mem_ptr - *(mem_ptr-1);
free(mem);
}
#define ENC_VALIDATE(X) if(!(X)) return MP4V_ERR_FORMAT
#endif /* _ENCODER_H_ */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -