⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mbprediction.c

📁 quicktime linux播放器v1
💻 C
字号:
 /******************************************************************************  *                                                                            *  *  This file is part of XviD, a free MPEG-4 video encoder/decoder            *  *                                                                            *  *  XviD is an implementation of a part of one or more MPEG-4 Video tools     *  *  as specified in ISO/IEC 14496-2 standard.  Those intending to use this    *  *  software module in hardware or software products are advised that its     *  *  use may infringe existing patents or copyrights, and any such use         *  *  would be at such party's own risk.  The original developer of this        *  *  software module and his/her company, and subsequent editors and their     *  *  companies, will have no liability for use of this software or             *  *  modifications or derivatives thereof.                                     *  *                                                                            *  *  XviD is free software; you can redistribute it and/or modify it           *  *  under the terms of the GNU General Public License as published by         *  *  the Free Software Foundation; either version 2 of the License, or         *  *  (at your option) any later version.                                       *  *                                                                            *  *  XviD is distributed in the hope that it will be useful, but               *  *  WITHOUT ANY WARRANTY; without even the implied warranty of                *  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *  *  GNU General Public License for more details.                              *  *                                                                            *  *  You should have received a copy of the GNU General Public License         *  *  along with this program; if not, write to the Free Software               *  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA  *  *                                                                            *  ******************************************************************************/ /******************************************************************************  *                                                                            *  *  mbprediction.c                                                            *  *                                                                            *  *  Copyright (C) 2001 - Michael Militzer <isibaar@xvid.org>                  *  *  Copyright (C) 2001 - Peter Ross <pross@cs.rmit.edu.au>                    *  *                                                                            *  *  For more information visit the XviD homepage: http://www.xvid.org         *  *                                                                            *  ******************************************************************************/ /******************************************************************************  *                                                                            *  *  Revision history:                                                         *  *                                                                            *  *  17.11.2001 initial version                                                *  *                                                                            *  ******************************************************************************/#include <assert.h>#include "enctypes.h"#include "enc_mbfunctions.h"#define MIN(X, Y) ((X)<(Y)?(X):(Y))#define MAX(X, Y) ((X)>(Y)?(X):(Y))#define _div_div(a, b) (a>0) ? (a+(b>>1))/b : (a-(b>>1))/b/* 	scale 'predictor coefficient' to match the current coefficient       scaled_coeff = (pred_coeff * pred_quant) // current_quant */#define _rescale(predict_quant, current_quant, coeff)   (coeff != 0) ?  \	_div_div((coeff) * (predict_quant), (current_quant))    : 0static const int16_t default_acdc_values[15] = { 1024,    0, 0, 0, 0, 0, 0, 0,    0, 0, 0, 0, 0, 0, 0};static __inline uint8_t calc_cbp_intra(int16_t codes[6][64])/*                 PLEASE NOTE:    This function has been duplicated in MBTransQuant and MBPrediction    to enforce modularity*/{    uint8_t i, j;    uint8_t cbp = 0;	uint8_t shl_val[6] = {32, 16, 8, 4, 2, 1};    for (i = 0; i < 6; i++) {		for (j = 1; j < 64; j++) {			int16_t value = codes[i][j];			if (value != 0) {				cbp |= shl_val[i];				break;			}		}    }    return cbp;}static __inline int8_t get_dc_scaler(int8_t quant, bool lum)/*                 PLEASE NOTE:    This function has been duplicated in MBTransQuant and MBPrediction    to enforce modularity*/    {    int8_t dc_scaler;	if(quant > 0 && quant < 5) {        dc_scaler = 8;		return dc_scaler;	}	if(quant < 25 && !lum) {        dc_scaler = (quant + 13) >> 1;		return dc_scaler;	}	if(quant < 9) {        dc_scaler = quant << 1;		return dc_scaler;	}    if(quant < 25) {        dc_scaler = quant + 8;		return dc_scaler;	}	if(lum)		dc_scaler = (quant << 1) - 16;	else        dc_scaler = quant - 6;    return dc_scaler;}/* calculate the pmv (predicted motion vector)	(take the median of surrounding motion vectors)		(x,y) = the macroblock	block = the block within the macroblock*/static __inline void get_pmv(const Macroblock * const pMBs,							const uint32_t x, const uint32_t y,							const uint32_t x_dim,							const uint32_t block,							int32_t * const pred_x, int32_t * const pred_y)/*                 PLEASE NOTE:    This function has been duplicated in MBMotionEstComp and MBPrediction    to enforce modularity*/    {    int x1, x2, x3;	int y1, y2, y3;    int xin1, xin2, xin3;    int yin1, yin2, yin3;    int vec1, vec2, vec3;    uint32_t index = x + y * x_dim;	// first row (special case)    if (y == 0 && (block == 0 || block == 1))    {		if (x == 0 && block == 0)		// first column		{			*pred_x = 0;			*pred_y = 0;			return;		}		if (block == 1)		{			MotionVector mv = pMBs[index].mvs[0];			*pred_x = mv.x;			*pred_y = mv.y;			return;		}		// else		{			MotionVector mv = pMBs[index - 1].mvs[1];			*pred_x = mv.x;			*pred_y = mv.y;			return;		}    }	/*		MODE_INTER, vm18 page 48		MODE_INTER4V vm18 page 51					(x,y-1)		(x+1,y-1)					[   |   ]	[	|   ]					[ 2 | 3 ]	[ 2 |   ]		(x-1,y)		(x,y)		(x+1,y)		[   | 1 ]	[ 0 | 1 ]	[ 0 |   ]		[   | 3 ]	[ 2 | 3 ]	[	|   ]	*/    switch (block)    {	case 0:		xin1 = x - 1;	yin1 = y;		vec1 = 1;		xin2 = x;		yin2 = y - 1;	vec2 = 2;		xin3 = x + 1;	yin3 = y - 1;	vec3 = 2;		break;	case 1:		xin1 = x;		yin1 = y;		vec1 = 0;		xin2 = x;		yin2 = y - 1;   vec2 = 3;		xin3 = x + 1;	yin3 = y - 1;	vec3 = 2;	    break;	case 2:		xin1 = x - 1;	yin1 = y;		vec1 = 3;		xin2 = x;		yin2 = y;		vec2 = 0;		xin3 = x;		yin3 = y;		vec3 = 1;	    break;	default:		xin1 = x;		yin1 = y;		vec1 = 2;		xin2 = x;		yin2 = y;		vec2 = 0;		xin3 = x;		yin3 = y;		vec3 = 1;    }	if (xin1 < 0 || /* yin1 < 0  || */ xin1 >= (int32_t)x_dim)	{	    x1 = 0;		y1 = 0;	}	else	{		const MotionVector * const mv = &(pMBs[xin1 + yin1 * x_dim].mvs[vec1]); 		x1 = mv->x;		y1 = mv->y;	}	if (xin2 < 0 || /* yin2 < 0 || */ xin2 >= (int32_t)x_dim)	{		x2 = 0;		y2 = 0;	}	else	{		const MotionVector * const mv = &(pMBs[xin2 + yin2 * x_dim].mvs[vec2]); 		x2 = mv->x;		y2 = mv->y;	}	if (xin3 < 0 || /* yin3 < 0 || */ xin3 >= (int32_t)x_dim)	{	    x3 = 0;		y3 = 0;	}	else	{		const MotionVector * const mv = &(pMBs[xin3 + yin3 * x_dim].mvs[vec3]); 		x3 = mv->x;		y3 = mv->y;	}	// median	*pred_x = MIN(MAX(x1, x2), MIN(MAX(x2, x3), MAX(x1, x3)));	*pred_y = MIN(MAX(y1, y2), MIN(MAX(y2, y3), MAX(y1, y3)));}/*  perform dc/ac prediction on a single block  returns how much is saved by performing ac prediction	[  diag  ] [   top   ]	[  left  ] [ current ]*/static int32_t calc_acdc_prediction(Macroblock *pMBs, uint16_t x, uint16_t y,									uint16_t x_dim, uint8_t block, int16_t dct_codes[64],									uint8_t iDcScaler, int32_t current_quant){    int16_t *left, *top, *diag, *current;    int32_t left_quant = current_quant;    int32_t top_quant = current_quant;    const int16_t *pLeft = default_acdc_values;    const int16_t *pTop = default_acdc_values;    const int16_t *pDiag = default_acdc_values;    int16_t *pCurrent;    int32_t S1 = 0, S2 = 0;    uint8_t i;    uint32_t index = x + y * x_dim;    int16_t dc_pred;    uint8_t *acpred_direction = &pMBs[index].acpred_directions[block];	left = top = diag = current = 0;	/* grab left,top and diag macroblocks */	/* left macroblock */    if(x && (pMBs[index - 1].mode == MODE_INTRA 		|| pMBs[index - 1].mode == MODE_INTRA_Q)) {		left = pMBs[index - 1].pred_values[0];		left_quant = pMBs[index - 1].aquant;	}    	/* top macroblock */		if(y && (pMBs[index - x_dim].mode == MODE_INTRA 		|| pMBs[index - x_dim].mode == MODE_INTRA_Q)) {		top = pMBs[index - x_dim].pred_values[0];		top_quant = pMBs[index - x_dim].aquant;    }    	/* diag macroblock */		if(x && y && (pMBs[index - 1 - x_dim].mode == MODE_INTRA 		|| pMBs[index - 1 - x_dim].mode == MODE_INTRA_Q)) {		diag = pMBs[index - 1 - x_dim].pred_values[0];	}    current = pMBs[index].pred_values[0];	pCurrent = current + block * MBPRED_SIZE;    	/* now grab pLeft, pTop, pDiag _blocks_ */		switch (block) {		case 0: 		if(left)			pLeft = left + MBPRED_SIZE;				if(top)			pTop = top + (MBPRED_SIZE << 1);				if(diag)			pDiag = diag + 3 * MBPRED_SIZE;				break;		case 1:		pLeft = current;		left_quant = current_quant;				if(top) {			pTop = top + 3 * MBPRED_SIZE;			pDiag = top + (MBPRED_SIZE << 1);		}				break;		case 2:		if(left) {			pLeft = left + 3 * MBPRED_SIZE;			pDiag = left + MBPRED_SIZE;		}				pTop = current;		top_quant = current_quant;				break;		case 3:		pLeft = current + (MBPRED_SIZE << 1);		left_quant = current_quant;				pTop = current + MBPRED_SIZE;		top_quant = current_quant;				pDiag = current;				break;		case 4:		if(left)			pLeft = left + (MBPRED_SIZE << 2);				if(top)			pTop = top + (MBPRED_SIZE << 2);				if(diag)			pDiag = diag + (MBPRED_SIZE << 2);				break;		case 5:		if(left)			pLeft = left + 5 * MBPRED_SIZE;		if(top)			pTop = top + 5 * MBPRED_SIZE;		if(diag)			pDiag = diag + 5 * MBPRED_SIZE;		break;	}        /*	determine ac prediction direction & dc predictor */    if(abs(pLeft[0] - pDiag[0]) < abs(pDiag[0] - pTop[0])) {		*acpred_direction = 1;             // vertical		dc_pred = _div_div(pTop[0], iDcScaler);    }    else {		*acpred_direction = 2;             // horizontal		dc_pred = _div_div(pLeft[0], iDcScaler);    }    	/* store current coeffs to pred_values[] */    pCurrent[0] = dct_codes[0] * iDcScaler;	for(i = 1; i < 8; i++) {		pCurrent[i] = dct_codes[i];//	    assert(pCurrent[i] >= -256);//		assert(pCurrent[i] <= 256);		pCurrent[i + 7] = dct_codes[i * 8];//		assert(pCurrent[i + 7] >= -256);//		assert(pCurrent[i + 7] <= 256);    }	/* 	subtract DC/AC prediction from current values	whilst calculating S1/S2 	   	S1/S2 are used  to determine if its worth predicting for AC		S1 = sum of all (dct_codes - prediction)		S2 = sum of all dct_codes	*/	dct_codes[0] -= dc_pred;	if(*acpred_direction == 1) {		for(i = 1; i < 8; i++) {			int16_t level;//			assert(pTop[i] >= -256);//			assert(pTop[i] <= 256);			level = dct_codes[i];			S2 += abs(level);			level -= _rescale(top_quant, current_quant, pTop[i]);			S1 += abs(level);			dct_codes[i] = level;		}	}    else {		for(i = 1; i < 8; i++) {			int16_t level;//			assert(pLeft[i + 7] >= -256);//			assert(pLeft[i + 7] <= 256);			level = dct_codes[i*8];			S2 += abs(level);			level -= _rescale(left_quant, current_quant,pLeft[i + 7]);			S1 += abs(level);			dct_codes[i*8] = level;		}    }        return S2 - S1;}void MBPrediction(const MBParam *pParam, uint16_t x_pos, uint16_t y_pos,				  uint16_t x_dim, int16_t qcoeff[][64], Macroblock *MB_array){    int8_t i, mv_count, iDcScaler, iQuant = pParam->quant;	int32_t pred_x, pred_y, S = 0;	int16_t qcoeff_backup[6][64];    Macroblock *pMB = &MB_array[x_pos + y_pos * x_dim];    if((pMB->mode == MODE_INTRA) || (pMB->mode == MODE_INTRA_Q)) {		memcpy(qcoeff_backup, qcoeff, sizeof(qcoeff_backup));		for(i = 0; i < 6; i++) {   			iDcScaler = get_dc_scaler(iQuant, (i < 4) ? 1 : 0);			S += calc_acdc_prediction(MB_array, x_pos, y_pos, x_dim, i,                      qcoeff[i], iDcScaler, iQuant);		}		/* if its not worth performing ac prediction, restore coeff		   values and 'disable' ac prediction. */		if(S < 0) {			for(i = 0; i < 6; i++) {				pMB->acpred_directions[i] = 0;				memcpy(&qcoeff[i][1], &qcoeff_backup[i][1], 63 * sizeof(int16_t));			}		}		pMB->cbp = calc_cbp_intra(qcoeff);    }    else {	    mv_count = (pMB->mode == MODE_INTER4V) ? 4 : 1;		for(i = 0; i < mv_count; i++) {			get_pmv(MB_array, x_pos, y_pos, x_dim, i, &pred_x, &pred_y);			pMB->pmvs[i].x = pMB->mvs[i].x - pred_x;			pMB->pmvs[i].y = pMB->mvs[i].y - pred_y;		}    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -