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

📄 mbcoding.c

📁 网络MPEG4IP流媒体开发源代码
💻 C
字号:
#include <stdlib.h>#include "../portab.h"#include "bitstream.h"#include "zigzag.h"#include "vlc_codes.h"#include "mbcoding.h"#include "../utils/mbfunctions.h"#define ABS(X) (((X)>0)?(X):-(X))#define CLIP(X,A) (X > A) ? (A) : (X)VLC intra_table[65536]; VLC inter_table[65536];VLC DCT3Dintra[4096];VLC DCT3Dinter[4096];static int16_t clip_table[4096];#ifdef MPEG4IPextern void h263_encode_coeff(	Bitstream *bs,	int16_t block[64],	const uint16_t *zigzag,	uint16_t intra);#endifvoid init_vlc_tables(void){	int32_t k, l, i, intra, last;	VLC *vlc[2];	VLC **coeff_ptr;	VLC *vlc1, *vlc2;	vlc1 = DCT3Dintra;	vlc2 = DCT3Dinter;		vlc[0] = intra_table;	vlc[1] = inter_table;		// initialize the clipping table	for(i = -2048; i < 2048; i++) {		clip_table[i + 2048] = i;		if(i < -255)			clip_table[i + 2048] = -255;		if(i > 255)			clip_table[i + 2048] = 255;	}		// generate encoding vlc lookup tables	for(i = 0; i < 4; i++) {		intra = i % 2;		last = i / 2;		coeff_ptr = coeff_vlc[last + 2 * intra];					for(k = -255; k < 256; k++) { // level			int8_t *max_level_ptr = max_level[last + 2 * intra];			int8_t *max_run_ptr = max_run[last + 2 * intra];				for(l = 0; l < 64; l++) { // run				int32_t level = k;				uint32_t run = l;							if((abs(level) <= max_level_ptr[run]) &&				   (run <= max_run_ptr[abs(level)])) { // level < max_level and run < max_run													   						vlc[intra]->code = 0;						vlc[intra]->len = 0;						goto loop_end;				}				else {					if(level > 0)					     // correct level						level -= max_level_ptr[run];					else						level += max_level_ptr[run];					if((abs(level) <= max_level_ptr[run]) &&					   (run <= max_run_ptr[abs(level)])) {												vlc[intra]->code = 0x06;						vlc[intra]->len = 8;						goto loop_end;					}					if(level > 0)					    // still here?						level += max_level_ptr[run];    // restore level					else						level -= max_level_ptr[run];					run -= max_run_ptr[abs(level)] + 1; // and change run					if((abs(level) <= max_level_ptr[run]) &&					   (run <= max_run_ptr[abs(level)])) {												vlc[intra]->code = 0x0e;						vlc[intra]->len = 9;						goto loop_end;					}					run += max_run_ptr[abs(level)] + 1;				}				vlc[intra]->code = (uint32_t) ((l << 14) | (0x1e + last) << 20) |											  (1 << 13) | ((k & 0xfff) << 1) | 1;				vlc[intra]->len = 30;				vlc[intra]++;				continue;loop_end:				if(level != 0) {					vlc[intra]->code = (vlc[intra]->code << (coeff_ptr[run][abs(level) - 1].len + 1)) |									   (coeff_ptr[run][abs(level) - 1].code << 1);					vlc[intra]->len = (coeff_ptr[run][abs(level) - 1].len + 1) + vlc[intra]->len;					if(level < 0)						vlc[intra]->code += 1;				}				vlc[intra]++;			}		}	}	for(i = 0; i < 4096; i++) {		if(i >= 512) {			*vlc1 = DCT3Dtab3[(i >> 5) - 16];			*vlc2 = DCT3Dtab0[(i >> 5) - 16];		}		else if(i >= 128) {			*vlc1 = DCT3Dtab4[(i >> 2) - 32];			*vlc2 = DCT3Dtab1[(i >> 2) - 32];		}		else if(i >= 8) {			*vlc1 = DCT3Dtab5[i - 8];			*vlc2 = DCT3Dtab2[i - 8];		}		else {			*vlc1 = ERRtab[i];			*vlc2 = ERRtab[i];		}		vlc1++;		vlc2++;	}	DCT3D[0] = DCT3Dinter;	DCT3D[1] = DCT3Dintra;}static __inline void CodeVector(Bitstream *bs,				int16_t value,				int16_t f_code,				Statistics *pStat){	const int scale_factor = 1 << (f_code - 1);	const int cmp = scale_factor << 5;	if(value < (-1 * cmp))		value += 64 * scale_factor;		if(value > (cmp - 1))		value -= 64 * scale_factor;	pStat->iMvSum += value * value;	pStat->iMvCount++;	if (value == 0) {		BitstreamPutBits(bs, mb_motion_table[32].code, mb_motion_table[32].len);	} else {		uint16_t length, code, mv_res, sign;				length = 16 << f_code;		f_code--;				sign = (value < 0);		if(value >= length)			value -= 2 * length;		else if(value < -length)			value += 2 * length;		if(sign)			value = -value;		value--;		mv_res = value & ((1 << f_code) - 1);		code = ((value - mv_res) >> f_code) + 1;		if(sign)			code = -code;		code += 32;		BitstreamPutBits(bs, mb_motion_table[code].code, mb_motion_table[code].len);				if(f_code)			BitstreamPutBits(bs, mv_res, f_code);	}}static __inline void CodeCoeff(Bitstream *bs,			       int16_t qcoeff[64],			       VLC *table,			       const uint16_t *zigzag,			       uint16_t intra){	uint32_t j, last;	short v;	VLC *vlc;		j = intra;	last = intra;	while((v = qcoeff[zigzag[j]]) == 0) j++;    	do {		// count zeroes		vlc = table + 64*255 + (clip_table[2048+v] << 6) + j - last;		last = ++j;		while(j < 64 && (v = qcoeff[zigzag[j]]) == 0) j++;						// write code		if(j != 64) {			BitstreamPutBits(bs, vlc->code, vlc->len);		} else {			vlc += 64*511;			BitstreamPutBits(bs, vlc->code, vlc->len);			break;		}	} while(1);}static void CodeBlockIntra(const MBParam * pParam,			   const MACROBLOCK *pMB,			   int16_t qcoeff[6*64],			   Bitstream * bs,			   Statistics * pStat){	uint32_t i, mcbpc, cbpy, bits;	cbpy = pMB->cbp >> 2;	// write mcbpc	if(pParam->coding_type == I_VOP) {		mcbpc = ((pMB->mode >> 1) & 3) | ((pMB->cbp & 3) << 2);		BitstreamPutBits(bs, mcbpc_intra_tab[mcbpc].code, mcbpc_intra_tab[mcbpc].len);	}	else {		mcbpc = (pMB->mode & 7) | ((pMB->cbp & 3) << 3);		BitstreamPutBits(bs, mcbpc_inter_tab[mcbpc].code, mcbpc_inter_tab[mcbpc].len);	}#ifdef MPEG4IP	if ((pParam->global_flags & XVID_SHORT_HEADERS) == 0) {#endif		// ac prediction flag		if(pMB->acpred_directions[0])			BitstreamPutBits(bs, 1, 1);		else			BitstreamPutBits(bs, 0, 1);#ifdef MPEG4IP	}#endif	// write cbpy	BitstreamPutBits (bs, cbpy_tab[cbpy].code, cbpy_tab[cbpy].len);	// write dquant	if(pMB->mode == MODE_INTRA_Q)		BitstreamPutBits(bs, pMB->dquant, 2);	// write interlacing	if (pParam->global_flags & XVID_INTERLACING)	{		BitstreamPutBit(bs, pMB->field_dct);	}	// code block coeffs	for(i = 0; i < 6; i++)	{#ifdef MPEG4IP		if ((pParam->global_flags & XVID_SHORT_HEADERS) != 0) {			// H.263			uint16_t dcq = qcoeff[i*64] & 0xFF;			if (dcq < 1) {				dcq = 1;			} else if (dcq == 128) {				dcq = 255;	/* gets remapped */			} else if (dcq > 254) {				dcq = 254;	/* need to clamp value */			} 						// DEBUG			printf("xvid-h263 b %u start %u dc %d dccode %u\n",				i, BitstreamPos(bs), qcoeff[i*64], dcq);			BitstreamPutBits(bs, dcq, 8);			if (pMB->cbp & (1 << (5 - i))) {				bits = BitstreamPos(bs);				h263_encode_coeff(bs,					  &qcoeff[i*64],					  scan_tables[0],					  1);				pStat->iTextBits += BitstreamPos(bs) - bits;			}		} else { #endif			// MPEG-4			if (i < 4) {				BitstreamPutBits(bs,						 dcy_tab[qcoeff[i*64 + 0] + 255].code,						 dcy_tab[qcoeff[i*64 + 0] + 255].len);			} else {				BitstreamPutBits(bs,						 dcc_tab[qcoeff[i*64 + 0] + 255].code,						 dcc_tab[qcoeff[i*64 + 0] + 255].len);			}			if (pMB->cbp & (1 << (5 - i))) {				bits = BitstreamPos(bs);				CodeCoeff(bs,					  &qcoeff[i*64],					  intra_table,					  scan_tables[pMB->acpred_directions[i]],					  1);				pStat->iTextBits += BitstreamPos(bs) - bits;			}#ifdef MPEG4IP		}#endif	}}static void CodeBlockInter(const MBParam * pParam,			   const MACROBLOCK *pMB,			   int16_t qcoeff[6*64],			   Bitstream * bs,			   Statistics * pStat){	int32_t i;	uint32_t bits, mcbpc, cbpy;	mcbpc = (pMB->mode & 7) | ((pMB->cbp & 3) << 3);	cbpy = 15 - (pMB->cbp >> 2);	// write mcbpc	BitstreamPutBits(bs, mcbpc_inter_tab[mcbpc].code, mcbpc_inter_tab[mcbpc].len);	// write cbpy	BitstreamPutBits(bs, cbpy_tab[cbpy].code, cbpy_tab[cbpy].len);	// write dquant	if(pMB->mode == MODE_INTER_Q)		BitstreamPutBits(bs, pMB->dquant, 2);    	// interlacing	if (pParam->global_flags & XVID_INTERLACING)	{		BitstreamPutBit(bs, pMB->field_dct);		DEBUG1("codep: field_dct: ", pMB->field_dct);		// if inter block, write field ME flag		if (pMB->mode == MODE_INTER || pMB->mode == MODE_INTER_Q)		{			BitstreamPutBit(bs, pMB->field_pred);			DEBUG1("codep: field_pred: ", pMB->field_pred);			// write field prediction references			if (pMB->field_pred)			{				BitstreamPutBit(bs, pMB->field_for_top);				BitstreamPutBit(bs, pMB->field_for_bot);			}		}	}	// code motion vector(s)	for(i = 0; i < (pMB->mode == MODE_INTER4V ? 4 : 1); i++)	{		CodeVector(bs, pMB->pmvs[i].x, pParam->fixed_code, pStat);		CodeVector(bs, pMB->pmvs[i].y, pParam->fixed_code, pStat);	}	bits = BitstreamPos(bs);		// code block coeffs	for(i = 0; i < 6; i++)		if(pMB->cbp & (1 << (5 - i)))#ifdef MPEG4IP			if ((pParam->global_flags & XVID_SHORT_HEADERS) != 0) {				h263_encode_coeff(bs, &qcoeff[i*64], scan_tables[0], 0);			} else {				CodeCoeff(bs, &qcoeff[i*64], inter_table, scan_tables[0], 0);			}#else			CodeCoeff(bs, &qcoeff[i*64], inter_table, scan_tables[0], 0);#endif	bits = BitstreamPos(bs) - bits;	pStat->iTextBits += bits;}void MBCoding(const MBParam * pParam,	      MACROBLOCK *pMB,	      int16_t qcoeff[6*64], 	      Bitstream * bs,	      Statistics * pStat){	int intra = (pMB->mode == MODE_INTRA || pMB->mode == MODE_INTRA_Q);	if(pParam->coding_type == P_VOP) {		if(pMB->cbp == 0 && pMB->mode == MODE_INTER &&		   pMB->mvs[0].x == 0 && pMB->mvs[0].y == 0)		{			BitstreamPutBit(bs, 1);		// not_coded			return;		}		else			BitstreamPutBit(bs, 0);		// coded	}	if(intra)		CodeBlockIntra(pParam, pMB, qcoeff, bs, pStat);	else		CodeBlockInter(pParam, pMB, qcoeff, bs, pStat);}/*************************************************************** * decoding stuff starts here                                  * ***************************************************************//* * For IVOP addbits == 0 * For PVOP addbits == fcode - 1 * For BVOP addbits == max(fcode,bcode) - 1 * returns true or false */int check_resync_marker(Bitstream * bs, int addbits){	uint32_t nbits;	uint32_t code;	uint32_t nbitsresyncmarker = NUMBITS_VP_RESYNC_MARKER + addbits;	nbits = BitstreamNumBitsToByteAlign(bs);	code = BitstreamShowBits(bs, nbits);	if (code == (((uint32_t)1 << (nbits - 1)) - 1))	{		return BitstreamShowBitsFromByteAlign(bs, nbitsresyncmarker) == RESYNC_MARKER;	}	return 0;}int get_mcbpc_intra(Bitstream * bs){	uint32_t index;		while((index = BitstreamShowBits(bs, 9)) == 1)		BitstreamSkip(bs, 9);	index >>= 3;	BitstreamSkip(bs, mcbpc_intra_table[index].len);	return mcbpc_intra_table[index].code;}int get_mcbpc_inter(Bitstream * bs){	uint32_t index;		while((index = CLIP(BitstreamShowBits(bs, 9), 256)) == 1)		BitstreamSkip(bs, 9);	BitstreamSkip(bs,  mcbpc_inter_table[index].len);	return mcbpc_inter_table[index].code;}int get_cbpy(Bitstream * bs, int intra){	int cbpy;	uint32_t index = BitstreamShowBits(bs, 6);	BitstreamSkip(bs, cbpy_table[index].len);	cbpy = cbpy_table[index].code;	if(!intra)		cbpy = 15 - cbpy;	return cbpy;}int get_mv_data(Bitstream * bs){	uint32_t index;	if(BitstreamGetBit(bs))		return 0;		index = BitstreamShowBits(bs, 12);	if(index >= 512)	{		index = (index >> 8) - 2;		BitstreamSkip(bs, TMNMVtab0[index].len);		return TMNMVtab0[index].code;	}		if(index >= 128)	{		index = (index >> 2) - 32;		BitstreamSkip(bs, TMNMVtab1[index].len);		return TMNMVtab1[index].code;	}	index -= 4; 	BitstreamSkip(bs, TMNMVtab2[index].len);	return TMNMVtab2[index].code;}int get_mv(Bitstream * bs, int fcode){	int data;	int res;	int mv;	int scale_fac = 1 << (fcode - 1);	data = get_mv_data(bs);		if(scale_fac == 1 || data == 0)		return data;	res = BitstreamGetBits(bs, fcode - 1);	mv = ((ABS(data) - 1) * scale_fac) + res + 1;		return data < 0 ? -mv : mv;}int get_dc_dif(Bitstream * bs, uint32_t dc_size){	int code = BitstreamGetBits(bs, dc_size);	int msb = code >> (dc_size - 1);	if(msb == 0)		return (-1 * (code^((1 << dc_size) - 1)));	return code;}int get_dc_size_lum(Bitstream * bs){	int code, i;	code = BitstreamShowBits(bs, 11);	for(i = 11; i > 3; i--) {		if(code == 1) {			BitstreamSkip(bs, i);			return i + 1;		}		code >>= 1;	}	BitstreamSkip(bs, dc_lum_tab[code].len);	return dc_lum_tab[code].code;}int get_dc_size_chrom(Bitstream * bs){	uint32_t code, i;	code = BitstreamShowBits(bs, 12);	for(i = 12; i > 2; i--) {		if(code == 1) {			BitstreamSkip(bs, i);			return i;		}		code >>= 1;	}	return 3 - BitstreamGetBits(bs, 2);}void get_intra_block(Bitstream * bs, int16_t * block, int direction, int coeff) {	const uint16_t * scan = scan_tables[ direction ];	int level;	int run;	int last;	do	{		level = get_coeff(bs, &run, &last, 1, 0);		if (run == -1)		{			DEBUG("fatal: invalid run");			break;		}		coeff += run;		block[ scan[coeff] ] = level;		if (level < -127 || level > 127)		{			DEBUG1("warning: intra_overflow", level);		}		coeff++;	} while (!last);}void get_inter_block(Bitstream * bs, int16_t * block) {	const uint16_t * scan = scan_tables[0];	int p;	int level;	int run;	int last;	p = 0;	do	{		level = get_coeff(bs, &run, &last, 0, 0);		if (run == -1)		{			DEBUG("fatal: invalid run");			break;		}		p += run;		block[ scan[p] ] = level;		if (level < -127 || level > 127)		{			DEBUG1("warning: inter_overflow", level);		}		p++;	} while (!last);}

⌨️ 快捷键说明

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