/* getvlc.c, variable length decoding */ /* Copyright (C) 1994, MPEG Software Simulation Group. All Rights Reserved. */ /* * Disclaimer of Warranty * * These software programs are available to the user without any license fee or * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims * any and all warranties, whether express, implied, or statuary, including any * implied warranties or merchantability or of fitness for a particular * purpose. In no event shall the copyright-holder be liable for any * incidental, punitive, or consequential damages of any kind whatsoever * arising from the use of these programs. * * This disclaimer of warranty extends to the user of these programs and user's * customers, employees, agents, transferees, successors, and assigns. * * The MPEG Software Simulation Group does not represent or warrant that the * programs furnished hereunder are free of infringement of any third-party * patents. * * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware, * are subject to royalty fees to patent holders. Many of these patents are * general enough such that they are unavoidable regardless of implementation * design. * */ #include #include "config.h" #include "global.h" #include "getvlc.h" /* private prototypes */ static int getIMBtype _ANSI_ARGS_((void)); static int getPMBtype _ANSI_ARGS_((void)); static int getBMBtype _ANSI_ARGS_((void)); static int getDMBtype _ANSI_ARGS_((void)); static int getspIMBtype _ANSI_ARGS_((void)); static int getspPMBtype _ANSI_ARGS_((void)); static int getspBMBtype _ANSI_ARGS_((void)); static int getSNRMBtype _ANSI_ARGS_((void)); int getMBtype() { int mb_type; if (ld->scalable_mode == SC_SNR) mb_type = getSNRMBtype(); else { switch (pict_type) { case I_TYPE: mb_type = ld->pict_scal ? getspIMBtype() : getIMBtype(); break; case P_TYPE: mb_type = ld->pict_scal ? getspPMBtype() : getPMBtype(); break; case B_TYPE: mb_type = ld->pict_scal ? getspBMBtype() : getBMBtype(); break; case D_TYPE: /* MPEG-1 only, not implemented */ mb_type = getDMBtype(); break; } } return mb_type; } static int getIMBtype() { #ifdef TRACE if (trace) printf("mb_type(I) "); #endif if (getbits1()) { #ifdef TRACE if (trace) printf("(1): Intra (1)\n"); #endif return 1; } if (!getbits1()) { if (!quiet) fprintf(stderr, "Invalid macroblock_type code\n"); fault = 1; } #ifdef TRACE if (trace) printf("(01): Intra, Quant (17)\n"); #endif return 17; } #ifdef TRACE static char *MBdescr[] = { "", "Intra", "No MC, Coded", "", "Bwd, Not Coded", "", "Bwd, Coded", "", "Fwd, Not Coded", "", "Fwd, Coded", "", "Interp, Not Coded", "", "Interp, Coded", "", "", "Intra, Quant", "No MC, Coded, Quant", "", "", "", "Bwd, Coded, Quant", "", "", "", "Fwd, Coded, Quant", "", "", "", "Interp, Coded, Quant", "" }; #endif static int getPMBtype() { int code; #ifdef TRACE if (trace) printf("mb_type(P) ("); #endif if ((code = showbits(6)) >= 8) { code >>= 3; flushbits(PMBtab0[code].len); #ifdef TRACE if (trace) { printbits(code, 3, PMBtab0[code].len); printf("): %s (%d)\n", MBdescr[PMBtab0[code].val], PMBtab0[code].val); } #endif return PMBtab0[code].val; } if (code == 0) { if (!quiet) fprintf(stderr, "Invalid macroblock_type code\n"); fault = 1; return 0; } flushbits(PMBtab1[code].len); #ifdef TRACE if (trace) { printbits(code, 6, PMBtab1[code].len); printf("): %s (%d)\n", MBdescr[PMBtab1[code].val], PMBtab1[code].val); } #endif return PMBtab1[code].val; } static int getBMBtype() { int code; #ifdef TRACE if (trace) printf("mb_type(B) ("); #endif if ((code = showbits(6)) >= 8) { code >>= 2; flushbits(BMBtab0[code].len); #ifdef TRACE if (trace) { printbits(code, 4, BMBtab0[code].len); printf("): %s (%d)\n", MBdescr[BMBtab0[code].val], BMBtab0[code].val); } #endif return BMBtab0[code].val; } if (code == 0) { if (!quiet) fprintf(stderr, "Invalid macroblock_type code\n"); fault = 1; return 0; } flushbits(BMBtab1[code].len); #ifdef TRACE if (trace) { printbits(code, 6, BMBtab1[code].len); printf("): %s (%d)\n", MBdescr[BMBtab1[code].val], BMBtab1[code].val); } #endif return BMBtab1[code].val; } static int getDMBtype() { if (!getbits1()) { if (!quiet) fprintf(stderr, "Invalid macroblock_type code\n"); fault = 1; } return 1; } /* macroblock_type for pictures with spatial scalability */ static int getspIMBtype() { int code; #ifdef TRACE if (trace) printf("mb_type(I,spat) ("); #endif code = showbits(4); if (code == 0) { if (!quiet) fprintf(stderr, "Invalid macroblock_type code\n"); fault = 1; return 0; } #ifdef TRACE if (trace) { printbits(code, 4, spIMBtab[code].len); printf("): %02x\n", spIMBtab[code].val); } #endif flushbits(spIMBtab[code].len); return spIMBtab[code].val; } static int getspPMBtype() { int code; #ifdef TRACE if (trace) printf("mb_type(P,spat) ("); #endif code = showbits(7); if (code < 2) { if (!quiet) fprintf(stderr, "Invalid macroblock_type code\n"); fault = 1; return 0; } if (code >= 16) { code >>= 3; flushbits(spPMBtab0[code].len); #ifdef TRACE if (trace) { printbits(code, 4, spPMBtab0[code].len); printf("): %02x\n", spPMBtab0[code].val); } #endif return spPMBtab0[code].val; } flushbits(spPMBtab1[code].len); #ifdef TRACE if (trace) { printbits(code, 7, spPMBtab1[code].len); printf("): %02x\n", spPMBtab1[code].val); } #endif return spPMBtab1[code].val; } static int getspBMBtype() { int code; VLCtab *p; #ifdef TRACE if (trace) printf("mb_type(B,spat) ("); #endif code = showbits(9); if (code >= 64) p = &spBMBtab0[(code >> 5) - 2]; else if (code >= 16) p = &spBMBtab1[(code >> 2) - 4]; else if (code >= 8) p = &spBMBtab2[code - 8]; else { if (!quiet) fprintf(stderr, "Invalid macroblock_type code\n"); fault = 1; return 0; } flushbits(p->len); #ifdef TRACE if (trace) { printbits(code, 9, p->len); printf("): %02x\n", p->val); } #endif return p->val; } static int getSNRMBtype() { int code; code = showbits(3); if (code == 0) { if (!quiet) fprintf(stderr, "Invalid macroblock_type code\n"); fault = 1; return 0; } flushbits(SNRMBtab[code].len); return SNRMBtab[code].val; } int getMV() { int code; #ifdef TRACE if (trace) printf("motion_code ("); #endif if (getbits1()) { #ifdef TRACE if (trace) printf("0): 0\n"); #endif return 0; } if ((code = showbits(9)) >= 64) { code >>= 6; flushbits(MVtab0[code].len); #ifdef TRACE if (trace) { printbits(code, 3, MVtab0[code].len); printf("%d): %d\n", showbits(1), showbits(1) ? -MVtab0[code].val : MVtab0[code].val); } #endif return getbits1()? -MVtab0[code].val : MVtab0[code].val; } if (code >= 24) { code >>= 3; flushbits(MVtab1[code].len); #ifdef TRACE if (trace) { printbits(code, 6, MVtab1[code].len); printf("%d): %d\n", showbits(1), showbits(1) ? -MVtab1[code].val : MVtab1[code].val); } #endif return getbits1()? -MVtab1[code].val : MVtab1[code].val; } if ((code -= 12) < 0) { if (!quiet) fprintf(stderr, "Invalid motion_vector code\n"); fault = 1; return 0; } flushbits(MVtab2[code].len); #ifdef TRACE if (trace) { printbits(code + 12, 9, MVtab2[code].len); printf("%d): %d\n", showbits(1), showbits(1) ? -MVtab2[code].val : MVtab2[code].val); } #endif return getbits1()? -MVtab2[code].val : MVtab2[code].val; } /* get differential motion vector (for dual prime prediction) */ int getDMV() { #ifdef TRACE if (trace) printf("dmvector ("); #endif if (getbits(1)) { #ifdef TRACE if (trace) printf(showbits(1) ? "11): -1\n" : "10): 1\n"); #endif return getbits(1) ? -1 : 1; } else { #ifdef TRACE if (trace) printf("0): 0\n"); #endif return 0; } } int getCBP() { int code; #ifdef TRACE if (trace) printf("coded_block_pattern_420 ("); #endif if ((code = showbits(9)) >= 128) { code >>= 4; flushbits(CBPtab0[code].len); #ifdef TRACE if (trace) { printbits(code, 5, CBPtab0[code].len); printf("): "); printbits(CBPtab0[code].val, 6, 6); printf(" (%d)\n", CBPtab0[code].val); } #endif return CBPtab0[code].val; } if (code >= 8) { code >>= 1; flushbits(CBPtab1[code].len); #ifdef TRACE if (trace) { printbits(code, 8, CBPtab1[code].len); printf("): "); printbits(CBPtab1[code].val, 6, 6); printf(" (%d)\n", CBPtab1[code].val); } #endif return CBPtab1[code].val; } if (code < 1) { if (!quiet) fprintf(stderr, "Invalid coded_block_pattern code\n"); fault = 1; return 0; } flushbits(CBPtab2[code].len); #ifdef TRACE if (trace) { printbits(code, 9, CBPtab2[code].len); printf("): "); printbits(CBPtab2[code].val, 6, 6); printf(" (%d)\n", CBPtab2[code].val); } #endif return CBPtab2[code].val; } int getMBA() { int code, val; #ifdef TRACE if (trace) printf("macroblock_address_increment ("); #endif val = 0; while ((code = showbits(11)) < 24) { if (code != 15) { /* if not macroblock_stuffing */ if (code == 8) { /* if macroblock_escape */ #ifdef TRACE if (trace) printf("00000001000 "); #endif val += 33; } else { if (!quiet) fprintf(stderr, "Invalid macroblock_address_increment code\n"); fault = 1; return 1; } } #ifdef TRACE else if (trace) printf("00000001111 "); #endif flushbits(11); } if (code >= 1024) { flushbits(1); #ifdef TRACE if (trace) printf("1): %d\n", val + 1); #endif return val + 1; } if (code >= 128) { code >>= 6; flushbits(MBAtab1[code].len); #ifdef TRACE if (trace) { printbits(code, 5, MBAtab1[code].len); printf("): %d\n", val + MBAtab1[code].val); } #endif return val + MBAtab1[code].val; } code -= 24; flushbits(MBAtab2[code].len); #ifdef TRACE if (trace) { printbits(code + 24, 11, MBAtab2[code].len); printf("): %d\n", val + MBAtab2[code].val); } #endif return val + MBAtab2[code].val; } int getDClum() { int code, size, val; #ifdef TRACE if (trace) printf("dct_dc_size_luminance: ("); #endif /* decode length */ code = showbits(5); if (code < 31) { size = DClumtab0[code].val; flushbits(DClumtab0[code].len); #ifdef TRACE if (trace) { printbits(code, 5, DClumtab0[code].len); printf("): %d", size); } #endif } else { code = showbits(9) - 0x1f0; size = DClumtab1[code].val; flushbits(DClumtab1[code].len); #ifdef TRACE if (trace) { printbits(code + 0x1f0, 9, DClumtab1[code].len); printf("): %d", size); } #endif } #ifdef TRACE if (trace) printf(", dct_dc_differential ("); #endif if (size == 0) val = 0; else { val = getbits(size); #ifdef TRACE if (trace) printbits(val, size, size); #endif if ((val & (1 << (size - 1))) == 0) val -= (1 << size) - 1; } #ifdef TRACE if (trace) printf("): %d\n", val); #endif return val; } int getDCchrom() { int code, size, val; #ifdef TRACE if (trace) printf("dct_dc_size_chrominance: ("); #endif /* decode length */ code = showbits(5); if (code < 31) { size = DCchromtab0[code].val; flushbits(DCchromtab0[code].len); #ifdef TRACE if (trace) { printbits(code, 5, DCchromtab0[code].len); printf("): %d", size); } #endif } else { code = showbits(10) - 0x3e0; size = DCchromtab1[code].val; flushbits(DCchromtab1[code].len); #ifdef TRACE if (trace) { printbits(code + 0x3e0, 10, DCchromtab1[code].len); printf("): %d", size); } #endif } #ifdef TRACE if (trace) printf(", dct_dc_differential ("); #endif if (size == 0) val = 0; else { val = getbits(size); #ifdef TRACE if (trace) printbits(val, size, size); #endif if ((val & (1 << (size - 1))) == 0) val -= (1 << size) - 1; } #ifdef TRACE if (trace) printf("): %d\n", val); #endif return val; }