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 + -
显示快捷键?