📄 umc_mpeg2_enc_b.cpp
字号:
/*//////////////////////////////////////////////////////////////////////////////
//
// INTEL CORPORATION PROPRIETARY INFORMATION
// This software is supplied under the terms of a license agreement or
// nondisclosure agreement with Intel Corporation and may not be copied
// or disclosed except in accordance with the terms of that agreement.
// Copyright(c) 2002-2007 Intel Corporation. All Rights Reserved.
//
*/
#include "umc_defs.h"
#if defined (UMC_ENABLE_MPEG2_VIDEO_ENCODER)
#include "ippi.h"
#include "ipps.h"
#include "umc_mpeg2_enc_defs.h"
////////////////////////////////////////////////////////////////////////////////
/////////////////////////////// Coding B picture ///////////////////////////////
////////////////////////////////////////////////////////////////////////////////
using namespace UMC;
void MPEG2VideoEncoderBase::encodeB(Ipp32s numTh)
{
const Ipp8u *pRef[2]; // parity same/opposite
const Ipp8u *pRec[2]; // parity same/opposite
Ipp32s i, j, ic, jc, k, pred_ind;
Ipp32s macroblock_address_increment;
Ipp32s dc_dct_pred[3];
Ipp16s *pMBlock, *pDiff;
Ipp32s Count[12], CodedBlockPattern;
IppMotionVector2 vector[3][2] = {0,}; // top/bottom/frame F/B
MB_prediction_info pred_info[2];
MB_prediction_info *best = pred_info;
MB_prediction_info *curr = pred_info + 1;
Ipp32s me_bound_left[2], me_bound_right[2];
Ipp32s me_bound_top[2], me_bound_bottom[2];
Ipp32s me_bound_2_top[2], me_bound_1_bottom[2];
Ipp32s cur_offset;
const Ipp8u *YBlock;
const Ipp8u *UBlock;
const Ipp8u *VBlock;
Ipp32s mean_frm[4], mean_fld[4];
Ipp32s slice_past_intra_address;
Ipp32s slice_macroblock_address;
Ipp32s start_y;
Ipp32s start_uv;
Ipp32s stop_y;
Ipp32s skip_flag;
Ipp32s dir0, dir1;
dir0 = 2*B_count > encodeInfo.IPDistance ? 1 : 0;
dir1 = 1 ^ dir0;
CALC_START_STOP_ROWS
best->pDiff = threadSpec[numTh].pDiff;
curr->pDiff = threadSpec[numTh].pDiff1;
threadSpec[numTh].fieldCount = 0;
if (!bQuantiserChanged) {
Ipp32s mf, mb;
mb = B_count - encodeInfo.IPDistance;
mf = B_count;
for(j=start_y; j < stop_y; j += 16)
{
for(i=0; i < encodeInfo.info.clip_info.width; i += 16, k++)
{
pMBInfo[k].MV[0][0].x = pMBInfo[k].MV_P[0].x*mf/256;
pMBInfo[k].MV[0][0].y = pMBInfo[k].MV_P[0].y*mf/256;
pMBInfo[k].MV[0][1].x = pMBInfo[k].MV_P[0].x*mb/256;
pMBInfo[k].MV[0][1].y = pMBInfo[k].MV_P[0].y*mb/256;
pMBInfo[k].MV[1][0].x = pMBInfo[k].MV_P[1].x*mf/256;
pMBInfo[k].MV[1][0].y = pMBInfo[k].MV_P[1].y*mf/256;
pMBInfo[k].MV[1][1].x = pMBInfo[k].MV_P[1].x*mb/256;
pMBInfo[k].MV[1][1].y = pMBInfo[k].MV_P[1].y*mb/256;
}
}
k = (threads) ? (start_y/16)*MBcountH : 0;
}
for (j = start_y, jc = start_uv; j < stop_y; j += 16, jc += BlkHeight_c)
{
PutSliceHeader(j >> 4, numTh);
macroblock_address_increment = 1;
slice_macroblock_address = 0;
slice_past_intra_address = 0;
// reset predictors at the start of slice
dc_dct_pred[0] = dc_dct_pred[1] = dc_dct_pred[2] = ResetTbl[intra_dc_precision];
ippsZero_8u((Ipp8u*)threadSpec[numTh].PMV, sizeof(threadSpec[0].PMV));
BOUNDS_V(0,j)
BOUNDS_V(1,j)
if(picture_structure != FRAME_PICTURE) {
BOUNDS_V_FIELD(0,j)
BOUNDS_V_FIELD(1,j)
// to avoid reference below bottom in 16x8 mode when trying to skip MB
me_bound_1_bottom[0] = me_bound_bottom[0];
me_bound_1_bottom[1] = me_bound_bottom[1];
}
for(i=ic=0; i < encodeInfo.info.clip_info.width; i += 16, ic += BlkWidth_c)
{
Ipp32s goodpred = 0;
cur_offset = i + j * YFrameHSize;
YBlock = Y_src + i + j * YFrameHSize;
UBlock = U_src + ic + jc * UVFrameHSize;
VBlock = V_src + ic + jc * UVFrameHSize;
slice_macroblock_address = i >> 4;
if (bQuantiserChanged && pMBInfo[k].mb_type) {
best->pred_type = pMBInfo[k].prediction_type;
best->dct_type = pMBInfo[k].dct_type;
best->mb_type = pMBInfo[k].mb_type;
if (!(pMBInfo[k].mb_type & MB_INTRA)) {
pDiff = best->pDiff;
if (pMBInfo[k].prediction_type == MC_FRAME) {
SET_MOTION_VECTOR((&vector[2][0]), pMBInfo[k].MV[0][0].x, pMBInfo[k].MV[0][0].y);
SET_MOTION_VECTOR((&vector[2][1]), pMBInfo[k].MV[0][1].x, pMBInfo[k].MV[0][1].y);
if (pMBInfo[k].mb_type == (MB_FORWARD|MB_BACKWARD)) {
GETDIFF_FRAME_FB(Y, Y, l, pDiff);
}
else if (pMBInfo[k].mb_type & MB_FORWARD) {
GETDIFF_FRAME(Y, Y, l, pDiff, 0);
}
else { // if(pMBInfo[k].mb_type & MB_BACKWARD)
GETDIFF_FRAME(Y, Y, l, pDiff, 1);
}
VARMEAN_FRAME(pDiff, best->var, best->mean, best->var_sum);
} else {
Ipp32s mv_shift = (picture_structure == FRAME_PICTURE) ? 1 : 0;
SET_FIELD_VECTOR((&vector[0][0]), pMBInfo[k].MV[0][0].x, pMBInfo[k].MV[0][0].y >> mv_shift);
SET_FIELD_VECTOR((&vector[1][0]), pMBInfo[k].MV[1][0].x, pMBInfo[k].MV[1][0].y >> mv_shift);
SET_FIELD_VECTOR((&vector[0][1]), pMBInfo[k].MV[0][1].x, pMBInfo[k].MV[0][1].y >> mv_shift);
SET_FIELD_VECTOR((&vector[1][1]), pMBInfo[k].MV[1][1].x, pMBInfo[k].MV[1][1].y >> mv_shift);
if (pMBInfo[k].mb_type == (MB_FORWARD|MB_BACKWARD)) {
GETDIFF_FIELD_FB(Y, Y, l, pDiff);
}
else if (pMBInfo[k].mb_type & MB_FORWARD) {
GETDIFF_FIELD(Y, Y, l, pDiff, 0);
}
else { // if(pMBInfo[k].mb_type & MB_BACKWARD)
GETDIFF_FIELD(Y, Y, l, pDiff, 1);
}
VARMEAN_FIELD(pDiff, best->var, best->mean, best->var_sum);
}
}
goto encodeMB;
}
pMBInfo[k].mb_type = 0;
pMBInfo[k].dct_type = DCT_FRAME;
pMBInfo[k].prediction_type = MC_FRAME;
VARMEAN_FRAME_Y(curr->var, mean_frm, curr->var_sum);
pMBInfo[k].var_sum = curr->var_sum;
// try skip MB
if (i != 0 && i != MBcountH*16-16 &&
!(pMBInfo[k-1].mb_type & MB_INTRA)
&& (!(pMBInfo[k - 1].mb_type & MB_FORWARD)
|| i+((threadSpec[numTh].PMV[0][0].x+1)>>1)+15 < MBcountH*16)
&& (!(pMBInfo[k - 1].mb_type & MB_BACKWARD)
|| i+((threadSpec[numTh].PMV[0][1].x+1)>>1)+15 < MBcountH*16) )
{
Ipp32s blk;
Ipp32s var, mean;
Ipp32s mb_type;
pMBInfo[k].mv_field_sel[2][0] = curr_field;
pMBInfo[k].mv_field_sel[2][1] = curr_field;
mb_type = pMBInfo[k - 1].mb_type & (MB_FORWARD | MB_BACKWARD);
pMBInfo[k].mb_type = mb_type;
pDiff = threadSpec[numTh].pDiff;
SET_MOTION_VECTOR((&vector[2][0]), threadSpec[numTh].PMV[0][0].x, threadSpec[numTh].PMV[0][0].y);
SET_MOTION_VECTOR((&vector[2][1]), threadSpec[numTh].PMV[0][1].x, threadSpec[numTh].PMV[0][1].y);
if (mb_type == (MB_FORWARD|MB_BACKWARD))
{
GETDIFF_FRAME_FB(Y, Y, l, pDiff);
}
else if (mb_type & MB_FORWARD)
{
GETDIFF_FRAME(Y, Y, l, pDiff, 0);
}
else // if(mb_type & MB_BACKWARD)
{
GETDIFF_FRAME(Y, Y, l, pDiff, 1);
}
skip_flag = 1;
for (blk = 0; blk < 4; blk++) {
ippiVarSum8x8_16s32s_C1R(pDiff + frm_diff_off[blk], 32, &var, &mean);
if(var > varThreshold) {
skip_flag = 0;
break;
}
mean /= 8;
if(mean >= quantiser_scale_value || mean <= -quantiser_scale_value) {
skip_flag = 0;
break;
}
}
if (skip_flag) { // check UV
if (mb_type == (MB_FORWARD|MB_BACKWARD))
{
GETDIFF_FRAME_FB(U, UV, c, pDiff);
GETDIFF_FRAME_FB(V, UV, c, pDiff);
}
else if (mb_type & MB_FORWARD)
{
GETDIFF_FRAME(U, UV, c, pDiff, 0);
GETDIFF_FRAME(V, UV, c, pDiff, 0);
}
else // if(mb_type & MB_BACKWARD)
{
GETDIFF_FRAME(U, UV, c, pDiff, 1);
GETDIFF_FRAME(V, UV, c, pDiff, 1);
}
for (blk = 4; blk < block_count; blk++) {
ippiVarSum8x8_16s32s_C1R(pDiff + frm_diff_off[blk], 32, &var, &mean);
if(var > varThreshold) {
skip_flag = 0;
break;
}
mean /= 8;
if(mean >= quantiser_scale_value || mean <= -quantiser_scale_value) {
skip_flag = 0;
break;
}
}
}
if (skip_flag)
{
skip_macroblock:
//pMBInfo[k].cbp = -1;
macroblock_address_increment++;
ippsCopy_8u((Ipp8u*)threadSpec[numTh].PMV, (Ipp8u*)pMBInfo[k].MV, sizeof(threadSpec[0].PMV));
k++;
continue;
}
} // try skip
pMBInfo[k].mb_type = 0;
best->var_sum = (1 << 30);
//VARMEAN_FRAME_Y(curr->var, mean_frm, curr->var_sum);
curr->var_sum = SCALE_VAR_INTRA(curr->var_sum);
//var_intra_frame = curr->var_sum;
if(curr->var_sum < best->var_sum)
{
curr->mb_type = MB_INTRA;
curr->dct_type = DCT_FRAME;
SWAP_PTR(best, curr);
}
BOUNDS_H(dir0,i)
ME_FRAME(dir0, curr->var_sum, curr->pDiff, curr->dct_type);
curr->var_sum = SCALE_VAR(curr->var_sum, SC_VAR_1V);
if(curr->var_sum < best->var_sum)
{
curr->mb_type = dir0 == 0 ? MB_FORWARD : MB_BACKWARD;
curr->pred_type = MC_FRAME;
SWAP_PTR(best, curr);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -