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

📄 pictureb.cpp

📁 H.263的编码程序,加了CPU指令优化,VC版.
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include <stdio.h>
#include <math.h>
#include "block.h"
#include "mot_est.h"
#include "macroblock.h"
#include "vlc.h"
#include "image.h"
#include "bitstream.h"


int  findIntraSAD(unsigned char *curr, int lx_curr);
void chooseBmode(H263VencStatus *encoder, MCParam *MC);
int  setBtype(int a, int b, int c);
int  MB_Encode_B(H263VencStatus *encoder, int pix_x, int pix_y, MCParam *MC, 
				 INT16 *qcoeff_p);

/*!
*******************************************************************************
*
*   Name:          EncBfrm
*   Description:   Encode one B Picture
*   Input:          
*   Output:        
*   Last modified: 2003/1/8 by lcl
*
*******************************************************************************/
int EncBfrm(H263VencStatus *encoder, MCParam *MC)
{
	int     total_bits = 0;
	int     pix_x, pix_y;
	int     mb_x, mb_y;
	int     lines = encoder->lines;
	int     pels = encoder->pels;
	int     newgob;
	int     cod;
	int     cbp;
	INT16 qcoeff[384];
	int     dquant = 0;
	int     mb_mode;
	int     mb_type;
	int     gob_nbr = 0;
	int     gob_quant = encoder->total_Q;
	int  	TRP = encoder->TR - encoder->ref_pic*(encoder->B_frame+1);

	encoder->method.interpolate_lum(encoder);
	/* Search for forward MV */
	grabVec(encoder, MC, 0);
	/* Search for backward MV */
	grabVec(encoder, MC, 1);

	chooseBmode(encoder, MC);

    total_bits += EncPicHdrPlus(encoder);

	for (pix_y = 0, mb_y = 0; pix_y < lines; pix_y += 16, mb_y++)
	{
		newgob = 0;
		if (encoder->advanced_intra_coding && (pix_y == 0))
		{
			clear_coeff_top(encoder->rcoeff.top_lum, encoder->rcoeff.top_cb, encoder->rcoeff.top_cr);
			clear_coeff_top(encoder->coeff.top_lum, encoder->coeff.top_cb, encoder->coeff.top_cr);
		}
		if(encoder->gobsync && pix_y && mb_y%(encoder->gobsync) == 0)
		{
			gob_nbr++;
			total_bits += EncGOBHdr(&(encoder->putstrmctrl), gob_nbr, encoder->gfid, gob_quant, encoder->TRB, TRP);
			newgob = 1;
			if (encoder->advanced_intra_coding)
			{
				clear_coeff_top(encoder->rcoeff.top_lum, encoder->rcoeff.top_cb, encoder->rcoeff.top_cr);
				clear_coeff_top(encoder->coeff.top_lum, encoder->coeff.top_cb, encoder->coeff.top_cr);
			}
		}
		for (pix_x = 0, mb_x = 0; pix_x < pels; pix_x += 16, mb_x++)
		{
			if (encoder->advanced_intra_coding && pix_x == 0)
			{
				clear_coeff_left(encoder->rcoeff.left_lum, encoder->rcoeff.left_cr, encoder->rcoeff.left_cb);
				clear_coeff_left(encoder->coeff.left_lum, encoder->coeff.left_cr, encoder->coeff.left_cb);
			}
			mb_mode = (MC->mv_frame[0][mb_y+1][mb_x+1])->Mode; //!< set mode of current mb
			cod = 0;
			if (B_INTRA == mb_mode)
			{ 
				if (!encoder->advanced_intra_coding)
				{
					cbp = MB_Encode_I(encoder, pix_x, pix_y, qcoeff);
					mb_type = setBtype(mb_mode, cbp, dquant);
					total_bits += EncMBHdr_B(&(encoder->putstrmctrl), mb_type, cbp, dquant);         //!<   write MCBPC, CBPY, DQUANT
					total_bits += EncCoeff(&(encoder->putstrmctrl), 1, cbp, qcoeff, 64);          //!<   write coefficients
				}
				else
				{
					cbp = MB_Encode_AI(encoder, pix_x, pix_y, qcoeff);
					mb_type = setBtype(mb_mode, cbp, dquant);
					total_bits += EncMBHdr_B(&(encoder->putstrmctrl), mb_type, cbp, dquant);
					total_bits += EncCoeff(&(encoder->putstrmctrl), 2, cbp, qcoeff, 64);
				}
			}
			else
			{
				cbp = MB_Encode_B(encoder, pix_x, pix_y, MC, qcoeff);
				mb_type = setBtype(mb_mode, cbp, dquant);
				total_bits += EncMBHdr_B(&(encoder->putstrmctrl), mb_type, cbp, dquant);            //!<  write COD, MCBPC, CBPY, DQUANT
                total_bits += EncMVD_B(&(encoder->putstrmctrl), MC, mb_x, mb_y, mb_mode, newgob);   //!<  write MVD 
				total_bits += EncCoeff(&(encoder->putstrmctrl), 0, cbp, qcoeff, 64);        //!<  write coefficients   
				if (encoder->advanced_intra_coding)
				{
					set_coeff_inter(mb_x, encoder->rcoeff.top_lum, encoder->rcoeff.top_cr, encoder->rcoeff.top_cb,
						             encoder->rcoeff.left_lum, encoder->rcoeff.left_cr, encoder->rcoeff.left_cb);
				}
			}
		}
	}

	total_bits += alignbits(&(encoder->putstrmctrl));
	clear_buff(&(encoder->putstrmctrl));

	return total_bits;
}
/*!
*******************************************************************************
*
*   Name:          chooseBmode
*   Description:   choose prediction mode for a B frame
*   Input:          
*   Output:        
*   Last modified: 2003/1/8 by lcl
*
*******************************************************************************/
void chooseBmode(H263VencStatus *encoder, MCParam *MC)
{
	int i, j;
	int block;
	int pix_x, pix_y;
	int lx_curr = encoder->pels;
	int lx_ipol = encoder->mv_outside_frame ? encoder->pels * 2 + 64 : encoder->pels * 2;
	int lines = encoder->lines/16;
	int pels  = encoder->pels/16;
	int sadfwd;
	int sadbwd;
	int saddir;
	int sadbid;
	int sadmin;
	int sadintra;
	int trd;
	int trb;
	int dx, dy, dxf, dyf, dxb, dyb;
	unsigned char *curr;
	unsigned char *prev;
	unsigned char *next;

	trb = encoder->TRB - encoder->TRP[encoder->ref_index];
	if (trb < 0)
	{
		trb += 256;
	}
	trd = encoder->TRP[encoder->zero_index] - encoder->TRP[encoder->ref_index];
	if (trd < 0)
	{
		trd += 256;
	}
	for (j = 0, pix_y = 0; j < lines; j++, pix_y+=16)
	{
		for ( i = 0, pix_x = 0; i < pels; i++, pix_x+=16)
		{
			sadfwd = MC->mv_frame[0][j+1][i+1]->min_sad;
			sadbwd = MC->mv_frame[5][j+1][i+1]->min_sad;
			/* compute saddir */
			if (MC->mv_lastframe[0][j][i]->Mode == MODE_INTER4V || 
				MC->mv_lastframe[0][j][i]->Mode == MODE_INTER4V_Q)
			{
				saddir = 0;
				for (block = 0; block < 4; block++)
				{
					dx = (MC->mv_lastframe[block+1][j][i]->x*2+MC->mv_lastframe[block+1][j][i]->x_half);
					dy = (MC->mv_lastframe[block+1][j][i]->y*2+MC->mv_lastframe[block+1][j][i]->y_half);
					dxf = trb * dx / trd;
					dyf = trb * dy / trd;
					dxb = (trb - trd) * dx / trd;
					dyb = (trb - trd) * dy / trd;
					curr = encoder->BPicture[encoder->B_count].pLum +pix_y*lx_curr + pix_x;
					prev = encoder->prev_ipol + (dyf+2*pix_y+((block&2)<<3))*lx_ipol + dxf+2*pix_x+((block&1)<<4);
					next = encoder->next_ipol + (dyb+2*pix_y+((block&2)<<3))*lx_ipol + dxb+2*pix_x+((block&1)<<4);
					saddir += encoder->method.findbiSAD(prev, next, curr, lx_ipol, lx_curr, 8);
				}
			}
			else
			{
				dx = (MC->mv_lastframe[0][j][i]->x*2+MC->mv_lastframe[0][j][i]->x_half);
				dy = (MC->mv_lastframe[0][j][i]->y*2+MC->mv_lastframe[0][j][i]->y_half);
				dxf = trb * dx / trd;
				dyf = trb * dy / trd;
				dxb = (trb - trd) * dx / trd;
				dyb = (trb - trd) * dy / trd;
				curr = encoder->BPicture[encoder->B_count].pLum +pix_y*lx_curr + pix_x;
				prev = encoder->prev_ipol + (dyf+2*pix_y)*lx_ipol + dxf+2*pix_x;
				next = encoder->next_ipol + (dyb+2*pix_y)*lx_ipol + dxb+2*pix_x;
				saddir = encoder->method.findbiSAD(prev, next, curr, lx_ipol, lx_curr, 16);
			}
			/* compute sadbid */
			dxf = MC->mv_frame[0][j+1][i+1]->x*2 + MC->mv_frame[0][j+1][i+1]->x_half;
			dyf = MC->mv_frame[0][j+1][i+1]->y*2 + MC->mv_frame[0][j+1][i+1]->y_half;
			dxb = MC->mv_frame[5][j+1][i+1]->x*2 + MC->mv_frame[5][j+1][i+1]->x_half;
			dyb = MC->mv_frame[5][j+1][i+1]->y*2 + MC->mv_frame[5][j+1][i+1]->y_half;
			curr = encoder->BPicture[encoder->B_count].pLum + pix_y*lx_curr + pix_x;
			prev = encoder->prev_ipol + (dyf+2*pix_y)*lx_ipol + dxf+2*pix_x;
			next = encoder->next_ipol + (dyb+2*pix_y)*lx_ipol + dxb+2*pix_x;
			sadbid = encoder->method.findbiSAD(prev, next, curr, lx_ipol, lx_curr, 16);
			/* compute sadintra */
			curr = encoder->BPicture[encoder->B_count].pLum + pix_y*lx_curr + pix_x;
			sadintra = findIntraSAD(curr, lx_curr);

			/* mode decision */
			if ((saddir < sadfwd) && (saddir < sadbwd) && (saddir < sadbid))
			{
				MC->mv_frame[0][j+1][i+1]->Mode = B_DIRECT;
				sadmin = saddir;
				zeroVec(MC->mv_frame[0][j+1][i+1]);
				zeroVec(MC->mv_frame[5][j+1][i+1]);
			}
			else if((sadfwd < saddir) && (sadfwd < sadbwd) && (sadfwd <sadbid))
			{
				MC->mv_frame[0][j+1][i+1]->Mode = B_FORWARD;
				sadmin = sadfwd;
				zeroVec(MC->mv_frame[5][j+1][i+1]);
			}
			else if((sadbwd < saddir) && (sadbwd < sadfwd) && (sadbwd <sadbid))
			{
				MC->mv_frame[0][j+1][i+1]->Mode = B_BACKWARD;
				sadmin = sadbwd;
				zeroVec(MC->mv_frame[0][j+1][i+1]);
			}
			else
			{
				MC->mv_frame[0][j+1][i+1]->Mode = B_BIDIRECTIONAL;
				sadmin = sadbid;
			}
			
			if (sadintra < sadmin - 500)
			{
				MC->mv_frame[0][j+1][i+1]->Mode = B_INTRA;
				zeroVec(MC->mv_frame[0][j+1][i+1]);
				zeroVec(MC->mv_frame[5][j+1][i+1]);
			}
#ifdef PRINTMODE
			printf("%d  ", MC->mv_frame[0][j+1][i+1]->Mode);
#endif
		}
#ifdef PRINTMODE
		printf("\n");
#endif
	}
}

/*!
*******************************************************************************
*
*   Name:          setBtype
*   Description:   set MB type for B frames
*   Input:          
*   Output:        
*   Last modified: 2003/1/8 by lcl
*
*******************************************************************************/
int  setBtype(int a, int b, int c)
{
	int type = a * 3;

	if (b != 0)
	{
		type = c ? type+2 : type+1;
	}
	// intra and intra+q
	if ((13 == type) || (14 == type))
	{
		type--;
	}

	return type - 1;
}

/*!
*******************************************************************************
*
*   Name:          MB_Encode_B
*   Description:   Encode one Macroblock in for B frame(make diff,dct,Q,IQ,IDct,data-recon)
*   Input:         position of curr-MB, encoder structure, MV 
*   Output:        qcoeff_p
*   Side effect:   write reconstructive data to recon_pic in corresponding position
*   Return:        cbp
*   Last modified: 2003/1/8
*
*******************************************************************************/
int  MB_Encode_B(H263VencStatus *encoder, int pix_x, int pix_y, MCParam *MC, 
				 INT16 *qcoeff_p)
{
	int i, j;
	int flag = 32;
	unsigned char *curr_block;
	unsigned char *recon_block;
	unsigned char pred_block[64];
	INT16       diff_block[64];
	MB_structure curr_mb;
	MB_structure recon_mb;
	int trb;
	int trd;
	int dxf, dyf, dxb, dyb;
	MotionVector *MV;                    //!< pointer to MV of last P frame
	
	trb = encoder->TRB - encoder->TRP[encoder->ref_index];
	if (trb < 0)
	{
		trb += 256;
	}
	trd = encoder->TRP[encoder->zero_index] - encoder->TRP[encoder->ref_index];
	if (trd < 0)
	{
		trd += 256;
	}
	int           mb_x = pix_x/16;
	int           mb_y = pix_y/16;
	int           pred_mode = MC->mv_frame[0][mb_y+1][mb_x+1]->Mode;
	int           cbp = 0;
	int           pic_width = encoder->pels;
	int           rec_width = encoder->pels;
	int           lx_ipol = encoder->mv_outside_frame ? pic_width*2+64 : pic_width*2;
	int           lx_ref_c = encoder->mv_outside_frame ? pic_width/2+16 : pic_width/2;
	int           QP = encoder->total_Q;  
	int           sad_gate = QP * 8;
	
	unsigned char *prev_ipol = encoder->prev_ipol;
	unsigned char *next_ipol = encoder->next_ipol;
	Image         *ref_img   = &(encoder->frame_buf[encoder->ref_index]);
	Image         *next_img  = &(encoder->frame_buf[encoder->zero_index]);
	Image         *curr_img  = &(encoder->BPicture[encoder->B_count]);
	Image         *recon_img = &(encoder->BPicture[0]);


//! Find MB in the image
	curr_mb.pLum = curr_img->pLum + pix_y * pic_width + pix_x;
	curr_mb.pCb  = curr_img->pCb + pix_y * pic_width/4 + pix_x/2;
	curr_mb.pCr  = curr_img->pCr + pix_y * pic_width/4 + pix_x/2;

	recon_mb.pLum = recon_img->pLum + pix_y * rec_width + pix_x;
	recon_mb.pCb  = recon_img->pCb + pix_y * rec_width/4 + pix_x/2;
	recon_mb.pCr  = recon_img->pCr + pix_y * rec_width/4 + pix_x/2; 

	/* direct mode */
	if (B_DIRECT == pred_mode) 
	{
		//! Encode each block in the MB
		//!4 lum blocks
		for (i = 0; i < 16; i+=8)
		{
			for (j = 0; j < 16; j+=8)
			{
				curr_block = curr_mb.pLum + i*pic_width + j;
				recon_block = recon_mb.pLum + i*rec_width + j;
				
				MV = MC->mv_lastframe[0][mb_y][mb_x];
				if (MV->Mode == MODE_INTER4V || MV->Mode == MODE_INTER4V_Q)
				{
					MV = MC->mv_lastframe[(j>>3)+(i>>2)+1][mb_y][mb_x];
				}
				dxf = (MV->x*2 + MV->x_half) * trb / trd;
				dyf = (MV->y*2 + MV->y_half) * trb / trd;
				dxb = (MV->x*2 + MV->x_half) * (trb-trd) / trd;
				dyb = (MV->y*2 + MV->y_half) * (trb-trd) / trd;

				encoder->method.pred_lum_bid(pix_x+j, pix_y+i, dxf, dyf, dxb, dyb, prev_ipol, next_ipol, 
					lx_ipol, pred_block);
								
				encoder->method.make_diff(curr_block, pic_width, pred_block, diff_block);
				
				if (block_SAD(diff_block) > sad_gate)
				{
					encoder->method.DCT(diff_block, diff_block);
					if (encoder->method.Quant_blk_P(diff_block, qcoeff_p, QP)) 
					{
						cbp|=flag;
						encoder->method.DeQuant_blk_P(qcoeff_p, diff_block, QP);  
						encoder->method.IDCT(diff_block, diff_block);
						encoder->method.recon_pic(recon_block, rec_width, pred_block, diff_block);
					}
					else
					{
						encoder->method.block_copy1(recon_block, pred_block, rec_width);
					}
				}
				else
				{
					encoder->method.block_copy1(recon_block, pred_block, rec_width);
				}
				flag = flag >> 1;
				qcoeff_p+=64;			
			}
		}
		
		/* find both forward MV and backward MV for chrom blocks in direct mode */
		findchromMV_dir(encoder, MC, pix_x, pix_y, &dxf, &dyf, &dxb, &dyb); 
		
		//! Cb block
		curr_block = curr_mb.pCb;
		recon_block = recon_mb.pCb;
		
		encoder->method.pred_chrom_bid(pix_x/2, pix_y/2, ref_img->pCb, next_img->pCb, lx_ref_c, dxf, dyf, dxb, dyb, pred_block);
		
		encoder->method.make_diff(curr_block, pic_width/2, pred_block, diff_block);
		
		if (block_SAD(diff_block) > sad_gate)
		{			
			encoder->method.DCT(diff_block, diff_block);
			if (encoder->method.Quant_blk_P(diff_block, qcoeff_p, QP))               
			{
				cbp|=flag;
				encoder->method.DeQuant_blk_P (qcoeff_p, diff_block, QP);  
				encoder->method.IDCT(diff_block, diff_block);
				encoder->method.recon_pic(recon_block, rec_width/2, pred_block, diff_block);
			}
			else
			{
				encoder->method.block_copy1(recon_block, pred_block, rec_width/2);
			}
		}

⌨️ 快捷键说明

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