📄 umc_me.cpp
字号:
}
return tmp;
}
bool MeBase::EstimateFrame(MeParams *par, MeFrame *res)
{
//check and save input
m_MePar = par;
bool no_skip = false;
switch(m_stream_type)
{
case MPEG2_VIDEO:
GetPredictor = &UMC::MeBase::GetPredictorMPEG2;
break;
case VC1_VIDEO:
if(m_MePar->SearchDirection == forward_search)
GetPredictor = &UMC::MeBase::GetMedianHibrid;
else
GetPredictor = &UMC::MeBase::GetMedian;
break;
default:
assert(0);
}
if(!CheckParams(false))
return false;
//estimate
m_pRefFrameY =m_MePar->pRefFY[0] ;
m_pRefFrameYDwn4 = m_pRefFrameFYDwn4;
m_predictor_index = 0;
for(Ipp32s y=0; y<m_HeightMB; y++){
for(Ipp32s x=0; x<m_WidthMB; x++){
m_CurMB = MeMV(x,y);
m_adr = m_WidthMB*y + x;
mbSkippedStatus = non_skipped;
no_skip = !m_MePar->toProcessSkipped || ((m_stream_type == MPEG2_VIDEO) && (x == 0 || x == m_WidthMB - 1 || m_ResMB[m_adr-1].MbType == MbIntra));
if(m_MePar->SearchDirection == forward_search)
{
m_CurPrediction = (this->*(GetPredictor))();
if(!no_skip)
{
if(EstimateSkipped())
{
mbSkippedStatus = skipped_forward;
MakeMbModeDecision();
continue;
}
}
EstimateMB();
}
else if(m_MePar->SearchDirection == bidir_search)
{
m_pRefFrameY =m_MePar->pRefBY[0] ;
m_predictor_index = m_MePar->MbPart & Mb8x8 ? 4 : 1;
m_CurPredictionB = m_CurPrediction = (this->*(GetPredictor))();
if(!no_skip)
{
if(EstimateSkipped())
{
mbSkippedStatus = skipped_backward;
MakeMbModeDecision();
continue;
}
}
m_pRefFrameY =m_MePar->pRefFY[0] ;
m_predictor_index = 0;
m_CurPredictionF = m_CurPrediction = (this->*(GetPredictor))();
if(!no_skip)
{
if(EstimateSkipped())
{
mbSkippedStatus = skipped_forward;
MakeMbModeDecision();
continue;
}
if(EstimateSkippedBidir())
{
mbSkippedStatus = skipped_bidir;
MakeMbModeDecision();
continue;
}
}
//direct MB:
if(m_MePar->toProcessDirect)
{
m_CurPrediction = m_MVDirectFW[m_adr];
m_CurPredictionB = m_MVDirectBW[m_adr];
if(EstimateSkippedBidir())
{
mbSkippedStatus = direct;
MakeMbModeDecision();
continue;
}
}
//non-skipped MB:
m_pRefFrameY =m_MePar->pRefBY[0] ;
m_pRefFrameYDwn4 = m_pRefFrameBYDwn4;
m_CurPrediction = m_CurPredictionB;
EstimateMB();
memcpy(&(m_BestBCost[0][0]), &(m_BestCost[0]), 5*sizeof(m_BestCost[0]));
memcpy(&(m_BestBMV[0][0]), &(m_BestMV[0]), 5*sizeof(m_BestMV[0]));
m_pRefFrameY =m_MePar->pRefFY[0] ;
m_pRefFrameYDwn4 = m_pRefFrameFYDwn4;
m_CurPrediction = m_CurPredictionF;
EstimateMB();
}//if(m_MePar->SearchDirection == bidir_search)
else assert(0);
MakeMbModeDecision();
}
}
//save results
res->NumOfMVs = m_NumOfMVs;
res->MBs = m_ResMB;
return true;
}
void MeBase::Close()
{
Ipp32s i;
for(i = 0; i < MaxRefFrame; i++)
{
if(m_BestBCost[i])free(m_BestBCost[i]);
if(m_BestBMV[i])free(m_BestBMV[i]);
}
if(m_BestBCost)free(m_BestBCost);
if(m_BestBMV)free(m_BestBMV);
if(m_BestCost)free(m_BestCost);
if(m_BestMV)free(m_BestMV);
if(m_16x16buf)free(m_16x16buf);
if(m_16x16bufB)free(m_16x16bufB);
if(m_bufAvrg)free(m_bufAvrg);
if(m_ResMB)free(m_ResMB);
if(m_pSrcFrameYDwn4)free(m_pSrcFrameYDwn4);
if(m_pRefFrameFYDwn4)free(m_pRefFrameFYDwn4);
if(m_pRefFrameBYDwn4)free(m_pRefFrameBYDwn4);
if(m_MVDirectFW)free(m_MVDirectFW);
if(m_MVDirectBW)free(m_MVDirectBW);
m_16x16buf= NULL;
m_16x16bufB = NULL;
m_bufAvrg = NULL;
m_ResMB= NULL;
m_pSrcFrameYDwn4= NULL;
m_pRefFrameFYDwn4 = NULL;
m_pRefFrameBYDwn4 = NULL;
m_BestCost = NULL;
m_BestMV = NULL;
m_BestBCost = NULL;
m_BestBMV = NULL;
m_MVDirectFW = NULL;
m_MVDirectBW = NULL;
}
bool MeBase::CheckParams(bool FirsCall)
{
if(FirsCall){
Ipp32s NumOfMVs=0;
if(m_MeParInit->MbPart & Mb16x16) NumOfMVs = 1;
if(m_MeParInit->MbPart & Mb8x8) NumOfMVs = 4;
if(m_MeParInit->SearchDirection == bidir_search) NumOfMVs *= 2;
if(m_MeParInit->CostMetrics != SAD && m_MeParInit->CostMetrics != SADT) return false;
m_CostMetrics = m_MeParInit->CostMetrics;
//check capabilities
if( (m_MeParInit->width&7) || (m_MeParInit->height&7)) return false;
// if( m_MeParInit->refPadding<32 ||(m_MeParInit->refPadding&15) ) return false;
// if( m_MeParInit->refPadding!=32) return false; // TODO: fix this
m_WidthMB = (m_MeParInit->width+15)/16;
m_HeightMB = (m_MeParInit->height+15)/16;
m_Padding = m_MeParInit->refPadding;
m_NumOfMVs = NumOfMVs;
return true;
}
Ipp32s NumOfMVs=0;
if(m_MePar->MbPart & Mb16x16) NumOfMVs = 1;
if(m_MePar->MbPart & Mb8x8) NumOfMVs = 4;
if(m_MePar->SearchDirection == bidir_search) NumOfMVs *= 2;
//temporary!!!
//if(m_MePar->SkippedMetrics != maxad) m_MePar->SkippedMetrics = maxad;
// if(m_MePar->SkippedMetrics != maxad && m_MePar->SkippedMetrics != sad) return false;
if(m_MePar->SkippedMetrics == maxad) m_SkippedThreshold = 2;
else if(m_MePar->SkippedMetrics == sad) m_SkippedThreshold = 60;
else if(m_MePar->SkippedMetrics == sadt)m_SkippedThreshold = m_MePar->Quant;
//check actual request
//check if current input parameters violate Init agreement
if(m_NumOfMVs < NumOfMVs) return false;
if( m_MePar->SearchRange.x < 8 || m_MePar->SearchRange.x > 256 ||
m_MePar->SearchRange.y < 8 || m_MePar->SearchRange.y > 256)return false;
if( m_MePar->Interpolation != Vc1QpBicubic && m_MePar->Interpolation != Bilinear) return false;
if( m_MePar->MbPart & Mb16x8 || m_MePar->MbPart & Mb8x16 ||
m_MePar->MbPart & Mb4x4 || m_MePar->MbPart & Mb8x8) return false;
//if( m_MePar->PixelType == HalfPixel) return false;
m_SearchRangeX = 4*m_MePar->SearchRange.x;
m_SearchRangeY = 4*m_MePar->SearchRange.y;
m_PicRange.top_left.x = m_MePar->PicRange.top_left.x;
m_PicRange.top_left.y = m_MePar->PicRange.top_left.y;
m_PicRange.bottom_right.x = m_MePar->PicRange.bottom_right.x;
m_PicRange.bottom_right.y = m_MePar->PicRange.bottom_right.y;
m_SrcStep = m_MePar->srcStep;
m_RefStep = m_MePar->refStep;
if(m_MePar->SearchDirection == bidir_search && m_pRefFrameBYDwn4 == NULL) return false;
//check input ptrs
if( m_MePar->pSrcY == NULL) return false;
if( (m_MePar->SearchDirection == forward_search || m_MePar->SearchDirection == bidir_search)&& (m_MePar->pRefFY==NULL || m_MePar->pRefFY[0]==NULL)) return false;
if( m_MePar->SearchDirection == bidir_search && (m_MePar->pRefBY==NULL || m_MePar->pRefBY[0]==NULL)) return false;
//check stupid errors
if((m_MePar->MbPart & Mb16x16) && (m_MePar->MbPart & Mb8x8) ||
!(m_MePar->MbPart & Mb16x16) && !(m_MePar->MbPart & Mb8x8)) return false;
if(m_MePar->SearchDirection != forward_search && m_MePar->SearchDirection != bidir_search) return false;
if(m_MePar->PixelType != IntegerPixel && m_MePar->PixelType != HalfPixel && m_MePar->PixelType != QuarterPixel) return false;
if(m_MePar->PixelType == HalfPixel && m_MePar->Interpolation != Bilinear)return false;
// if(m_MePar->PixelType != HalfPixel && m_MePar->PixelType != IntegerPixel && m_MePar->Interpolation == MpegInterpolation)return false;
if(!m_MePar->SetSpeedQualityParams()) return false;
m_pSrcFrameY = m_MePar->pSrcY;
//temporary: no process skipped macroblocks
m_MePar->toProcessSkipped = false;
//m_pRefFrameY =m_MePar->pRefFY[0] ;
DownsampleReference();
return true;
}
template<typename T> void MeBase::DownSamplePicture4(const T* pSrc, IppiSize srcSize, Ipp32s srcStep, T* pDst)
{
if((srcSize.height&3)!=0 && (srcSize.width&3)!=0)
assert(0);
for(Ipp32s y=0; y<srcSize.height/4; y++)
for(Ipp32s x=0; x<srcSize.width/4; x++){
Ipp32s avg = 0;
for(Ipp32s i=0; i<4; i++)
for(Ipp32s j=0; j<4; j++){
avg += *(pSrc + (4*y+i)*srcStep/sizeof(T) + 4*x+j);
}
*(pDst+y*srcStep/(4*sizeof(T))+x) = (T)((avg+8)/16);
}
}
void MeBase::DownsampleReference()
{
//Sleep(100); //to workaround bag in MS encoder about padding
IppiSize srcSize = {16*m_WidthMB,16*m_HeightMB};
IppiRect srcRoi = {0,0,srcSize.width,srcSize.height};
IppiSize srcRoiDwn = {srcSize.width/4,srcSize.height/4};
IppiSize refSize = {srcSize.width+m_Padding*2,srcSize.height+m_Padding*2};
IppiRect refRoi = {0,0,refSize.width,refSize.height};
IppiSize refRoiDwn = {refSize.width/4,refSize.height/4};
ippiResize_8u_C1R(m_pSrcFrameY, srcSize, m_SrcStepDwn4, srcRoi, m_pSrcFrameYDwn4, m_SrcStepDwn4/4, srcRoiDwn, 1/4., 1/4., IPPI_INTER_SUPER);
ippiResize_8u_C1R(m_MePar->pRefFY[0]-m_Padding-m_Padding*m_RefStepDwn4, refSize, m_RefStepDwn4, refRoi, m_pRefFrameFYDwn4, m_RefStepDwn4/4, refRoiDwn, 1/4., 1/4., IPPI_INTER_SUPER);
if(m_MePar->SearchDirection == bidir_search)
ippiResize_8u_C1R(m_MePar->pRefBY[0]-m_Padding-m_Padding*m_RefStepDwn4, refSize, m_RefStepDwn4, refRoi, m_pRefFrameBYDwn4, m_RefStepDwn4/4, refRoiDwn, 1/4., 1/4., IPPI_INTER_SUPER);
}
Ipp32s MeBase::GetT2()
{
Ipp32s T2, SadA=IPP_MAX_32S, SadB=IPP_MAX_32S, SadC=IPP_MAX_32S, SadCol=IPP_MAX_32S;
if(m_CurMB.y != 0) SadA = m_ResMB[m_adr-m_WidthMB].MbCosts[0];
if(m_CurMB.y != 0 && m_CurMB.x < m_WidthMB-1) SadB = m_ResMB[m_adr-m_WidthMB+1].MbCosts[0];
if(m_CurMB.x != 0) SadC = m_ResMB[m_adr-1].MbCosts[0];
T2 = 6*IPP_MIN(IPP_MIN(SadA,SadB), IPP_MIN(SadC,SadCol))/5 + 128;
//T2 = IPP_MIN(IPP_MIN(SadA,SadB), IPP_MIN(SadC,SadCol));
return T2;
}
inline void MeBase::ResetBestCost()
{
for(int i=0; i<sizeof(m_BestCost)/sizeof(Ipp32s); i++)
m_BestCost[i] = IPP_MAX_32S;
}
Ipp32s MeBase::WeightMV(MeMV mv)
{
Ipp32s d = abs(mv.x-m_CurPrediction.x) + abs(mv.y-m_CurPrediction.y);
Ipp32s cost;
for(cost=7; cost>=0; cost--)
if(d > (1<<cost))break;
return 4*cost;
//return 0;
}
template<MeMbPart mt, MeInPixType pix> inline void MeBase::CalcCost(const Ipp8u* pSrc,Ipp32s srcStep,const Ipp8u* pRef,Ipp32s refStep,MeCost * cost, Ipp32s mc_type, MeCostEnum cst)
{
switch(cst)
{
case SAD:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -