www.pudn.com > mpeg4_DECORE.rar > DECORE.C


/************************************************************************** 
 *                                                                        * 
 * 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 
 * Adam Li 
 * Jonathan White 
 * 
 * DivX Advanced Research Center  
* 
**/ 
// decore.c // 
 
#include  
#include  
 
#if ( (defined (WIN32)) && (! defined (_DECORE)) ) 
#include  
#include  
#include  
#endif 
 
#include "gen_usetime.h" 
#include "debug.h" 
#include "mp4_vars.h" 
#include "getbits.h" 
#include "yuv2rgb.h" 
#include "decore.h" 
 
/** 
 * 
**/ 
 
/***/ 
 
static int flag_firstpicture = 1; 
 
/***/ 
 
int STDCALL decore(unsigned long handle, unsigned long dec_opt, 
	void *param1, void *param2) 
{ 
	if (handle)  
	{ 
		switch (dec_opt) 
		{ 
			case DEC_OPT_MEMORY_REQS: 
			{ 
				DEC_PARAM *dec_param = (DEC_PARAM *)param1; 
				DEC_MEM_REQS *dec_mem_reqs = (DEC_MEM_REQS *)param2; 
 
				int coded_y_size = ((dec_param->x_dim + 64) * (dec_param->y_dim + 64)); 
				int coded_c_size = (((dec_param->x_dim>>1) + 64) * ((dec_param->y_dim>>1) + 64)); 
				int display_y_size = (dec_param->x_dim * dec_param->y_dim); 
				int display_c_size = ((dec_param->x_dim * dec_param->y_dim) >> 2); 
				int edged_size = coded_y_size + (2 * coded_c_size); 
				int display_size = display_y_size + (2 * display_c_size); 
 
				dec_mem_reqs->mp4_edged_ref_buffers_size = edged_size; 
				dec_mem_reqs->mp4_edged_for_buffers_size = edged_size; 
				dec_mem_reqs->mp4_display_buffers_size = display_size; 
				dec_mem_reqs->mp4_state_size = sizeof(MP4_STATE); 
				dec_mem_reqs->mp4_tables_size = sizeof(MP4_TABLES); 
				dec_mem_reqs->mp4_stream_size = sizeof(MP4_STREAM); 
 
				return DEC_OK; 
			} 
			case DEC_OPT_INIT: 
			{ 
				DEC_PARAM *dec_param = (DEC_PARAM *) param1; 
 
				decore_init(dec_param->x_dim, dec_param->y_dim, dec_param->output_format, 
					dec_param->time_incr, dec_param->buffers); // init decoder resources 
 
				return DEC_OK; 
			} 
			break;  
			case DEC_OPT_RELEASE: 
			{ 
				decore_release(); 
 
				return DEC_OK; 
			} 
			break; 
			case DEC_OPT_SETPP: 
			{ 
				DEC_SET *dec_set = (DEC_SET *) param1; 
				int postproc_level = dec_set->postproc_level; 
 
				if ((postproc_level < 0) | (postproc_level > 100)) 
					return DEC_BAD_FORMAT; 
 
				if (postproc_level < 1) { 
					mp4_state->post_flag = 0; 
					return DEC_OK; 
				} 
				else  
				{ 
					mp4_state->post_flag = 1; 
 
					if (postproc_level < 10) { 
						mp4_state->pp_options = PP_DEBLOCK_Y_H; 
					} 
					else if (postproc_level < 20) { 
						mp4_state->pp_options = PP_DEBLOCK_Y_H | PP_DEBLOCK_Y_V; 
					} 
					else if (postproc_level < 30) { 
						mp4_state->pp_options = PP_DEBLOCK_Y_H | PP_DEBLOCK_Y_V | PP_DERING_Y; 
					} 
					else if (postproc_level < 40) { 
						mp4_state->pp_options = PP_DEBLOCK_Y_H | PP_DEBLOCK_Y_V | PP_DERING_Y | PP_DEBLOCK_C_H; 
					} 
					else if (postproc_level < 50) { 
						mp4_state->pp_options = PP_DEBLOCK_Y_H | PP_DEBLOCK_Y_V | PP_DERING_Y |  
							PP_DEBLOCK_C_H | PP_DEBLOCK_C_V; 
					} 
					else { 
						mp4_state->pp_options = PP_DEBLOCK_Y_H | PP_DEBLOCK_Y_V | PP_DERING_Y |  
							PP_DEBLOCK_C_H | PP_DEBLOCK_C_V | PP_DERING_C; 
					} 
				} 
 
				return DEC_OK; 
			} 
			break; 
			case DEC_OPT_SETOUT: 
			{ 
				DEC_PARAM *dec_param = (DEC_PARAM *) param1; 
 
				decore_setoutput(dec_param->output_format); 
 
				return DEC_OK; 
			} 
			break; 
			default: 
			{ 
				DEC_FRAME *dec_frame = (DEC_FRAME *) param1; 
 
				if (decore_frame(dec_frame->bitstream, dec_frame->length,  
					dec_frame->bmp, dec_frame->stride, dec_frame->render_flag)) 
					return DEC_OK; 
				else  
					return DEC_EXIT; 
			} 
			break; 
		} 
	} 
	return DEC_BAD_FORMAT; 
} 
 
/***/ 
 
int decore_alloc(DEC_BUFFERS buffers); 
 
static int decore_init(int hor_size, int ver_size, int output_format, 
											 int time_inc, DEC_BUFFERS buffers) 
{ 
	mp4_state = (MP4_STATE *) buffers.mp4_state; 
	mp4_tables = (MP4_TABLES *) buffers.mp4_tables; 
	ld = (MP4_STREAM *) buffers.mp4_stream; 
 
#ifndef _DECORE 
	// open input file 
	if ((ld->infile = open (mp4_state->infilename, O_RDONLY | O_BINARY)) < 0) { 
		_Print ("Input file %s not found\n", mp4_state->infilename); 
		exit(91); 
	} 
	initbits (NULL, 0); 
	mp4_state->juice_flag = 0; 
#else  
	mp4_state->juice_flag = 1; 
#endif // _DECORE 
 
	mp4_state->post_flag = 0; 
 
	// read first vol and vop 
	mp4_state->hdr.width = hor_size; 
	mp4_state->hdr.height = ver_size; 
	 
	mp4_state->hdr.quant_precision = 5; 
	mp4_state->hdr.bits_per_pixel = 8; 
	 
	mp4_state->hdr.quant_type = 0; 
	 
	if (flag_firstpicture == 1) { 
		mp4_state->hdr.time_increment_resolution = 15; 
		flag_firstpicture = 0; 
	} 
	mp4_state->hdr.complexity_estimation_disable = 1; 
 
	decore_alloc (buffers); 
	decore_setoutput (output_format); 
 
	return 1; 
} 
 
/***/ 
 
int decore_alloc(DEC_BUFFERS buffers) 
{ 
	mp4_state->hdr.picnum = 0; 
	mp4_state->hdr.mb_xsize = mp4_state->hdr.width / 16; 
	mp4_state->hdr.mb_ysize = mp4_state->hdr.height / 16; 
	mp4_state->hdr.mba_size = mp4_state->hdr.mb_xsize * mp4_state->hdr.mb_ysize; 
 
	// set picture dimension global vars 
	{ 
		mp4_state->horizontal_size = mp4_state->hdr.width; 
		mp4_state->vertical_size = mp4_state->hdr.height; 
 
		mp4_state->mb_width = mp4_state->horizontal_size / 16; 
		mp4_state->mb_height = mp4_state->vertical_size / 16; 
 
		mp4_state->coded_picture_width = mp4_state->horizontal_size + 64; 
		mp4_state->coded_picture_height = mp4_state->vertical_size + 64; 
		mp4_state->chrom_width = mp4_state->coded_picture_width >> 1; 
		mp4_state->chrom_height = mp4_state->coded_picture_height >> 1; 
	} 
 
	// init decoder 
	initdecoder (buffers); 
 
	return 1; 
} 
 
/***/ 
 
int decore_frame(unsigned char *stream, int length, unsigned char *bmp,  
	unsigned int stride, int render_flag) 
{ 
#ifndef _DECORE 
	mp4_state->juice_flag = 0; 
	_SetPrintCond(0, 1000, 0, 1000); 
	_Print("- Picture %d\r", mp4_state->hdr.picnum); 
#else 
	initbits (stream, length); 
#endif // _DECORE 
 
	// mp4_state->hdr.time_increment_resolution = 15; // [Ag][Review] This must be passed by the app! 
 
	getvolhdr(); 
	getgophdr();	 
 
	if (! getvophdr()) // read vop header 
		return 0; 
 
	get_mp4picture(bmp, stride, render_flag); // decode vop 
	mp4_state->hdr.picnum++; 
 
	return 1; 
} 
 
/***/ 
 
static int decore_release() 
{ 
	// closedecoder(); // [Ag][Review]  
 
	/* 
			I have to check and close the decoder only when it is really been opened:  
			for some reason VirtualDub first of all wants to close the decoder and this  
			cause a free(nothing) and a crash. 
	*/ 
#ifndef _DECORE 
	close (ld->infile); 
#endif // _DECORE 
 
	return 1; 
} 
 
/***/ 
 
int decore_setoutput(int output_format) 
{ 
	mp4_state->flag_invert = +1; 
 
	switch (output_format) 
	{ 
	case DEC_RGB32: 
		mp4_state->convert_yuv = yuv2rgb_32; 
		mp4_state->flag_invert = -1; 
		break; 
	case DEC_RGB32_INV: 
		mp4_state->convert_yuv = yuv2rgb_32; 
		mp4_state->flag_invert = +1; 
		break; 
	case DEC_RGB24: 
		mp4_state->convert_yuv = yuv2rgb_24; 
		mp4_state->flag_invert = -1; 
		break; 
	case DEC_RGB24_INV: 
		mp4_state->convert_yuv = yuv2rgb_24; 
		mp4_state->flag_invert = +1; 
		break; 
	case DEC_RGB555: 
		mp4_state->convert_yuv = yuv2rgb_555; 
		mp4_state->flag_invert = -1; 
		break; 
	case DEC_RGB555_INV: 
		mp4_state->convert_yuv = yuv2rgb_555; 
		mp4_state->flag_invert = +1; 
		break; 
	case DEC_RGB565: 
		mp4_state->convert_yuv = yuv2rgb_565; 
		mp4_state->flag_invert = -1; 
		break; 
	case DEC_RGB565_INV: 
		mp4_state->convert_yuv = yuv2rgb_565; 
		mp4_state->flag_invert = +1; 
		break; 
	case DEC_420: 
		mp4_state->convert_yuv = yuv12_out; 
		break; 
	case DEC_YUV2: 
		mp4_state->convert_yuv = yuy2_out; 
		break; 
	case DEC_UYVY: 
		mp4_state->convert_yuv = uyvy_out; 
		break; 
	} 
 
	return 1; 
} 
 
/** 
 *	for a console application 
**/ 
 
#ifndef _DECORE 
 
/***/ 
 
static int dec_reinit(); 
 
static void options (int *argcp, char **argvp[]); 
static void optionhelp (int *argcp); 
 
/*** 
 
int main (int argc, char *argv[]) 
{ 
	char * infilename = argv[1]; 
	mp4_state->output_flag = mp4_state->juice_flag = mp4_state->post_flag = 0; 
 
	// decode args from input line 
	optionhelp (&argc); 
  options (&argc, &argv); 
 
//	startTimer(); 
 
	dec_init(infilename, mp4_state->juice_hor, mp4_state->juice_ver); // init decoder resources 
 
	_SetPrintCond(0, 1000, 0, 1000); 
 
  while (dec_frame()) // cycle on decoding engine 
		; 
 
//	stopTimer(); 
//	displayTimer(mp4_hdr.picnum); 
 
  dec_release(); // release decoder resources 
 
  return 0; 
} 
 
***/ 
 
int main (int argc, char *argv[]) 
{ 
	char * infilename = argv[1]; 
	char outputfilename[256] = "Test.yuv"; 
 
	DEC_MEM_REQS decMemReqs; 
	DEC_PARAM decParam; 
 
	decParam.x_dim = 352; 
	decParam.y_dim = 288; 
	decParam.output_format = 0; 
	decParam.time_incr = 0; 
	 
	decore(1, DEC_OPT_MEMORY_REQS, &decParam, &decMemReqs); 
 
	decParam.buffers.mp4_edged_ref_buffers = malloc(decMemReqs.mp4_edged_ref_buffers_size); 
	decParam.buffers.mp4_edged_for_buffers = malloc(decMemReqs.mp4_edged_for_buffers_size); 
	decParam.buffers.mp4_display_buffers = malloc(decMemReqs.mp4_display_buffers_size); 
	decParam.buffers.mp4_state = malloc(decMemReqs.mp4_state_size); 
	decParam.buffers.mp4_tables = malloc(decMemReqs.mp4_tables_size); 
	decParam.buffers.mp4_stream = malloc(decMemReqs.mp4_stream_size); 
 
	memset(decParam.buffers.mp4_state, 0, decMemReqs.mp4_state_size); 
	memset(decParam.buffers.mp4_tables, 0, decMemReqs.mp4_tables_size); 
	memset(decParam.buffers.mp4_stream, 0, decMemReqs.mp4_stream_size); 
 
	((MP4_STATE *) decParam.buffers.mp4_state)->infilename = infilename; 
	((MP4_STATE *) decParam.buffers.mp4_state)->outputname = outputfilename; 
 
	decore(1, DEC_OPT_INIT, &decParam, NULL); 
 
	startTimer(); 
 
	// decode frames 
	{ 
		DEC_FRAME decFrame; 
 
		decFrame.bitstream = NULL; 
		decFrame.bmp = NULL; 
		decFrame.length = 0; 
		decFrame.render_flag = 0; 
 
		while ( decore(1, 0, &decFrame, NULL) == DEC_OK ) 
			; 
	} 
 
	stopTimer(); 
	displayTimer(mp4_state->hdr.picnum); 
 
	return 1; 
} 
 
/***/ 
 
static void options (int *argcp, char **argvp[]) 
{ 
	(*argvp)++; 
	(*argcp)--; 
 
  while (*argcp > 1 && (*argvp)[1][0] == '-') 
  { 
    switch (toupper ((*argvp)[1][1])) 
    { 
      case 'O': 
				mp4_state->output_flag = 1; 
        mp4_state->outputname = (*argvp)[2]; 
				(*argvp) += 2; 
				(*argcp) -= 2; 
				break; 
			case 'J': 
				mp4_state->juice_flag = 1; 
				mp4_state->juice_hor = atoi ((*argvp)[2]); 
				mp4_state->juice_ver = atoi ((*argvp)[3]); 
		    (*argvp) += 3; 
				(*argcp) -= 3; 
				break; 
      default: 
        printf ("Error: Undefined option -%c ignored\n", (*argvp)[1][1]); 
    } 
  } 
} 
 
/***/ 
 
static void optionhelp(int *argcp) 
{ 
  if (*argcp < 2) 
  { 
    _Print ("Usage: opendivx_dec bitstream {options} \n"); 
		_Print ("Options: -o {outputfilename} YUV concatenated file output\n"); 
		_Print ("         -j {hor_size ver_size} juice stream and its picture format\n"); 
    exit (0); 
  } 
} 
 
/*** 
 
int dec_init(char *infilename, int hor_size, int ver_size, DEC_BUFFERS buffers) 
{ 
	mp4_state = (MP4_STATE *) buffers.mp4_state; 
	mp4_tables = (MP4_TABLES *) buffers.mp4_tables; 
 
	// open input file 
	if ((mp4_state->ld.infile = open (infilename, O_RDONLY | O_BINARY)) < 0) { 
		_Print ("Input file %s not found\n", infilename); 
		exit(91); 
	} 
 
	initbits (NULL); 
 
	// read header info (contains info to correctly initialize the decoder) 
	getvolhdr(); 
 
	getgophdr(); 
	getvophdr(); // read vop header 
 
	decore_alloc(buffers); 
 
	return 1; 
} 
 
 
 
int dec_frame() 
{ 
	// decoded vop 
	get_mp4picture(NULL, 0, 0); 
	mp4_state->hdr.picnum++; 
 
	_Print("- Picture %d\r", mp4_state->hdr.picnum); 
 
	// read next vop header 
	getvolhdr(); 
	getgophdr(); 
	return getvophdr();  
} 
 
 
 
int dec_release() 
{ 
  close (mp4_state->ld.infile); 
	decore_release(); 
 
	return 1; 
} 
 
***/ 
 
int dec_reinit() 
{ 
  if (ld->infile != 0) 
    lseek (ld->infile, 0l, 0); 
  initbits (NULL, 0); 
 
	return 1; 
} 
 
/***/ 
 
#endif // !_DECORE