mp4_block.c

来自「实现在linux下的mpeg4编解码」· C语言 代码 · 共 525 行

C
525
字号
/************************************************************************** *                                                                        * * This code has been developed by Andrea Graziani. This software 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 (including Project Mayo), will have no liability for use of  * * this software or modifications or derivatives thereof.                 * *                                                                        * * Project Mayo gives users of the Codec a license to this software       * * module or modifications thereof for use in hardware or software        * * products claiming conformance to the MPEG-4 Video Standard as          * * described in the Open DivX license.                                    * *                                                                        * * The complete Open DivX license can be found at                         * * http://www.projectmayo.com/opendivx/license.php                        * *                                                                        * **************************************************************************//***  Copyright (C) 2001 - Project Mayo * * Andrea Graziani (Ag) * * DivX Advanced Research Center <darc@projectmayo.com>***//// mp4_block.c //#include <math.h>#include <stdlib.h>#include <assert.h>#include "mp4_vars.h"#include "getbits.h"#include "clearblock.h"#include "mp4_iquant.h"#include "mp4_predict.h"#include "mp4_vld.h"#include "debug.h"#include "mp4_block.h"/** ***/static int getDCsizeLum();static int getDCsizeChr();static int getDCdiff();static void setDCscaler(int block_num);static int getACdir();/***/// Purpose: texture decoding of block_numint block(int block_num, int coded){	int i;	int dct_dc_size, dct_dc_diff;	int intraFlag = ((mp4_state->hdr.derived_mb_type == INTRA) || 		(mp4_state->hdr.derived_mb_type == INTRA_Q)) ? 1 : 0;	event_t event;	clearblock(ld->block); // clearblock	if (intraFlag)	{		setDCscaler(block_num); // calculate DC scaler		if (block_num < 4) {			dct_dc_size = getDCsizeLum();			if (dct_dc_size != 0) 				dct_dc_diff = getDCdiff(dct_dc_size);			else 				dct_dc_diff = 0;			if (dct_dc_size > 8)				getbits1(); // marker bit		}		else {			dct_dc_size = getDCsizeChr();			if (dct_dc_size != 0)				dct_dc_diff = getDCdiff(dct_dc_size);			else 				dct_dc_diff = 0;			if (dct_dc_size > 8)				getbits1(); // marker bit		}		ld->block[0] = (short) dct_dc_diff;//		_Print("DC diff: %d\n", dct_dc_diff);	}	if (intraFlag)	{		// dc reconstruction, prediction direction		dc_recon(block_num, &ld->block[0]);	}	if (coded) 	{		unsigned int * zigzag; // zigzag scan dir		if ((intraFlag) && (mp4_state->hdr.ac_pred_flag == 1)) {			if (mp4_state->coeff_pred.predict_dir == TOP)				zigzag = mp4_tables->alternate_horizontal_scan;			else				zigzag = mp4_tables->alternate_vertical_scan;		}		else {			zigzag = mp4_tables->zig_zag_scan;		}		i = intraFlag ? 1 : 0;		do // event vld		{			event = vld_event(intraFlag);/***			if (event.run == -1)			{				printf("Error: invalid vld code\n");				exit(201);			}***/						i+= event.run;			ld->block[zigzag[i]] = (short) event.level;//			_Print("Vld Event: Run Level Last %d %d %d\n", event.run, event.level, event.last);			i++;		} while (! event.last);	}	if (intraFlag)	{		// ac reconstruction		// ac_rescaling(...)		ac_recon(block_num, &ld->block[0]);	}#ifdef _DEBUG_B_ACDC	if (intraFlag)	{		int i;		_Print("After AcDcRecon:\n");		_Print("   x ");		for (i = 1; i < 64; i++) {			if ((i != 0) && ((i % 8) == 0))				_Print("\n");			_Print("%4d ", ld->block[i]);		}		_Print("\n");	}#endif // _DEBUG_ACDC	if (mp4_state->hdr.quant_type == 0)	{		// inverse quantization		iquant(ld->block, intraFlag);	}	else 	{		_Error("Error: MPEG-2 inverse quantization NOT implemented\n");		exit(110);	}#ifdef _DEBUG_B_QUANT	{		int i;		_Print("After IQuant:\n");		_Print("   x ");		for (i = 1; i < 64; i++) {			if ((i != 0) && ((i % 8) == 0))				_Print("\n");			_Print("%4d ", ld->block[i]);		}		_Print("\n");	}#endif // _DEBUG_B_QUANT	// inverse dct	idct(ld->block);	return 1;}/***/int blockIntra(int block_num, int coded){	int i;	int dct_dc_size, dct_dc_diff;	event_t event;	clearblock(ld->block); // clearblock	// dc coeff	setDCscaler(block_num); // calculate DC scaler	if (block_num < 4) {		dct_dc_size = getDCsizeLum();		if (dct_dc_size != 0) 			dct_dc_diff = getDCdiff(dct_dc_size);		else 			dct_dc_diff = 0;		if (dct_dc_size > 8)			getbits1(); // marker bit	}	else {		dct_dc_size = getDCsizeChr();		if (dct_dc_size != 0)			dct_dc_diff = getDCdiff(dct_dc_size);		else 			dct_dc_diff = 0;		if (dct_dc_size > 8)			getbits1(); // marker bit	}	ld->block[0] = (short) dct_dc_diff;	// dc reconstruction, prediction direction	dc_recon(block_num, &ld->block[0]);	if (coded) 	{		unsigned int * zigzag; // zigzag scan dir		if (mp4_state->hdr.ac_pred_flag == 1) {			if (mp4_state->coeff_pred.predict_dir == TOP)				zigzag = mp4_tables->alternate_horizontal_scan;			else				zigzag = mp4_tables->alternate_vertical_scan;		}		else {			zigzag = mp4_tables->zig_zag_scan;		}		i = 1;		do // event vld		{			event = vld_intra_dct();/***			if (event.run == -1)			{				printf("Error: invalid vld code\n");				exit(201);			}***/						i+= event.run;			ld->block[zigzag[i]] = (short) event.level;//			_Print("Vld Event: Run Level Last %d %d %d\n", event.run, event.level, event.last);			i++;		} while (! event.last);	}	// ac reconstruction	mp4_state->hdr.intrablock_rescaled = ac_rescaling(block_num, &ld->block[0]);	if (! mp4_state->hdr.intrablock_rescaled)	{		ac_recon(block_num, &ld->block[0]);	}	ac_store(block_num, &ld->block[0]);	if (mp4_state->hdr.quant_type == 0)	{		iquant(ld->block, 1);	}	else 	{		iquant_typefirst(ld->block);	}	// inverse dct	idct(ld->block);	return 1;}/***/int blockInter(int block_num, int coded){	event_t event;	unsigned int * zigzag = mp4_tables->zig_zag_scan; // zigzag scan dir	int i;		clearblock(ld->block); // clearblock	// inverse quant type	if (mp4_state->hdr.quant_type == 0) 	{		int q_scale = mp4_state->hdr.quantizer;		int q_2scale = q_scale << 1;		int q_add = (q_scale & 1) ? q_scale : (q_scale - 1);					i = 0;		do // event vld		{			event = vld_inter_dct();			/***			if (event.run == -1)			{			printf("Error: invalid vld code\n");			exit(201);			}			***/						i+= event.run;			if (event.level > 0) {				ld->block[zigzag[i]] = (q_2scale * event.level) + q_add;			}			else {				ld->block[zigzag[i]] = (q_2scale * event.level) - q_add;			}						// _Print("Vld Event: Run Level Last %d %d %d\n", event.run, event.level, event.last);						i++;		} while (! event.last);	}	else 	{		int k, m = 0;		i = 0;		// event vld		do 		{			event = vld_inter_dct();			i+= event.run;				k = (event.level > 0) ? 1 : -1;			assert(ld->block[zigzag[i]] < 2047);			assert(ld->block[zigzag[i]] > -2048);			ld->block[zigzag[i]] = ((2 * event.level + k) * mp4_state->hdr.quantizer * 				mp4_tables->nonintra_quant_matrix[zigzag[i]]) >> 4;			assert(ld->block[zigzag[i]] < 2047);			assert(ld->block[zigzag[i]] > -2048);			m ^= ld->block[zigzag[i]];						// _Print("Vld Event: Run Level Last %d %d %d\n", event.run, event.level, event.last);						i++;		} while (! event.last);		if (!(m%2)) ld->block[63] ^= 1;	}	// inverse dct	idct(ld->block);			return 1;}/***/static int getDCsizeLum(){	int code;	// [Ag][note] bad code	if (showbits(11) == 1) {		flushbits(11);		return 12;	}  if (showbits(10) == 1) {    flushbits(10);    return 11;  }  if (showbits(9) == 1) {    flushbits(9);    return 10;	}	if (showbits(8) == 1) {		flushbits(8);		return 9;	}	if (showbits(7) == 1) {		flushbits(7);		return 8;	}	if (showbits(6) == 1) {		flushbits(6);		return 7;	}  	if (showbits(5) == 1) {		flushbits(5);		return 6;	}	if (showbits(4) == 1) {		flushbits(4);		return 5;	}	code = showbits(3);	if (code == 1) {		flushbits(3);		return 4;	} else if (code == 2) {		flushbits(3);		return 3;	} else if (code == 3) {		flushbits(3);		return 0;	}  code = showbits(2);  if (code == 2) {		flushbits(2);		return 2;	} else if (code == 3) {		flushbits(2);		return 1;	}     	return 0;}static int getDCsizeChr(){	// [Ag][note] bad code	if (showbits(12) == 1) {		flushbits(12);		return 12;	}	if (showbits(11) == 1) {		flushbits(11);		return 11;	}	if (showbits(10) == 1) {		flushbits(10);		return 10;	}	if (showbits(9) == 1) {		flushbits(9);		return 9;	}	if (showbits(8) == 1) {		flushbits(8);		return 8;	}	if (showbits(7) == 1) {		flushbits(7);		return 7;	}	if (showbits(6) == 1) {		flushbits(6);		return 6;	}	if (showbits(5) == 1) {		flushbits(5);		return 5;	}	if (showbits(4) == 1) {		flushbits(4);		return 4;	} 	if (showbits(3) == 1) {		flushbits(3);		return 3;	} 	return (3 - getbits(2));}/***/static int getDCdiff(int dct_dc_size){	int code = getbits(dct_dc_size);	int msb = code >> (dct_dc_size - 1);	if (msb == 0) {		return (-1 * (code^((int) pow(2.0,(double) dct_dc_size) - 1)));	}  else { 		return code;	}}/***/static void setDCscaler(int block_num) {	int type = (block_num < 4) ? 0 : 1;	int quant = mp4_state->hdr.quantizer;	if (type == 0) {		if (quant > 0 && quant < 5) 			mp4_state->hdr.dc_scaler = 8;		else if (quant > 4 && quant < 9) 			mp4_state->hdr.dc_scaler = (2 * quant);		else if (quant > 8 && quant < 25) 			mp4_state->hdr.dc_scaler = (quant + 8);		else 			mp4_state->hdr.dc_scaler = (2 * quant - 16);	}  else {		if (quant > 0 && quant < 5) 			mp4_state->hdr.dc_scaler = 8;		else if (quant > 4 && quant < 25) 			mp4_state->hdr.dc_scaler = ((quant + 13) / 2);		else 			mp4_state->hdr.dc_scaler = (quant - 6);	}}/***/

⌨️ 快捷键说明

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