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