// Adapted into transcode by Tilmann Bitterberg // Code from libmpeg2 and mpeg2enc copyright by their respective owners // New code and modifications copyright Antoine Missout // Thanks to Sven Goethel for error resilience patches // Released under GPL license, see gnu.org // toggles: // #define STAT // print stats on exit #define NDEBUG // turns off asserts #define REMOVE_BYTE_STUFFING // removes 0x 00 00 00 00 00 00 used in cbr streams (look for 6 0x00 and remove 1 0x00) /* 4 0x00 might be legit, for exemple: 00 00 01 b5 14 82 00 01 00 00 00 00 01 b8 .. .. these two: -- -- are part of the seq. header ext. AFAIK 5 0x00 should never happen except for byte stuffing but to be safe look for 6 */ // #define USE_FD // use 2 lasts args for input/output paths #define REACT_DELAY (1024.0*128.0) #define MAX_ERRORS 0 // notes: // // - intra block: // - the quantiser is increment by one step // // - non intra block: // - in P_FRAME we keep the original quantiser but drop the last coefficient // if there is more than one // - in B_FRAME we multiply the quantiser by a factor // // - I_FRAME is recoded when we're 5.0 * REACT_DELAY late // - P_FRAME is recoded when we're 2.5 * REACT_DELAY late // - B_FRAME are always recoded // if we're getting *very* late (60 * REACT_DELAY) // // - intra blocks quantiser is incremented two step // - drop a few coefficients but always keep the first one // includes #include "transcode.h" #include #include // useful constants #define I_TYPE 1 #define P_TYPE 2 #define B_TYPE 3 // gcc #ifdef HAVE_BUILTIN_EXPECT #define likely(x) __builtin_expect ((x) != 0, 1) #define unlikely(x) __builtin_expect ((x) != 0, 0) #else #define likely(x) (x) #define unlikely(x) (x) #endif int verbose = TC_QUIET; #define EXE "tcrequant" #ifndef PACKAGE # define PACKAGE "transcode" #endif #ifndef VERSION # define VERSION "1.0.0" #endif // user defined types //typedef unsigned int uint; typedef unsigned char uint8; typedef unsigned short uint16; typedef unsigned int uint32; typedef unsigned long long uint64; typedef char int8; typedef short int16; typedef int int32; typedef long long int64; typedef signed int sint; typedef signed char sint8; typedef signed short sint16; typedef signed int sint32; typedef signed long long sint64; #define BITS_IN_BUF (8) // global variables static uint8 *cbuf, *rbuf, *wbuf, *orbuf, *owbuf; static int inbitcnt, outbitcnt; static uint32 inbitbuf, outbitbuf; static uint64 inbytecnt, outbytecnt; static float fact_x; static int mloka1; static int ifd, ofd; #ifdef STAT static uint64 ori_i, ori_p, ori_b; static uint64 new_i, new_p, new_b; static uint64 cnt_i, cnt_p, cnt_b; static uint64 cnt_p_i, cnt_p_ni; static uint64 cnt_b_i, cnt_b_ni; #endif // mpeg2 state // seq header static uint horizontal_size_value; static uint vertical_size_value; // pic header static uint picture_coding_type; // pic code ext static uint f_code[2][2]; static uint intra_dc_precision; static uint picture_structure; static uint frame_pred_frame_dct; static uint concealment_motion_vectors; static uint q_scale_type; static uint intra_vlc_format; static uint alternate_scan; // error static int validPicHeader; static int validSeqHeader; static int validExtHeader; static int sliceError; // slice or mb static uint quantizer_scale; static uint new_quantizer_scale; static uint last_coded_scale; static int h_offset, v_offset; // rate static double quant_corr; // block data typedef struct { uint8 run; short level; } RunLevel; static RunLevel block[6][65]; // terminated by level = 0, so we need 64+1 // end mpeg2 state #ifndef NDEBUG #define DEB(msg) tc_log_msg(EXE, "%s:%d " msg, __FILE__, __LINE__) #define DEBF(format, args...) tc_log_msg(EXE, "%s:%d " format, __FILE__, __LINE__, args) #else #define DEB(msg) #define DEBF(format, args...) #endif #define LOG(msg) do { if (verbose > 1) tc_log_msg(EXE, msg); } while (0) #define LOGF(format, args...) do { if (verbose > 1) tc_log_msg(EXE, format, args); } while (0) #define BUF_SIZE (16*1024*1024) #define MIN_READ (1*1024*1024) #define MIN_WRITE (1*1024*1024) #define WRITE \ mloka1 = wbuf - owbuf; \ write(ofd, owbuf, mloka1); \ outbytecnt += mloka1; \ wbuf = owbuf; \ mloka1 = rbuf - cbuf; if (mloka1) memmove(orbuf, cbuf, mloka1);\ cbuf = rbuf = orbuf; rbuf += mloka1; #define LOCK(x) \ while (unlikely(x > (rbuf-cbuf))) \ { \ assert(rbuf + MIN_READ < orbuf + BUF_SIZE); \ mloka1 = read(ifd, rbuf, MIN_READ); \ if (mloka1 <= 0) { RETURN } \ inbytecnt += mloka1; \ rbuf += mloka1; \ } #ifdef STAT #define RETURN \ assert(rbuf >= cbuf);\ mloka1 = rbuf - cbuf;\ if (mloka1) { COPY(mloka1); }\ WRITE \ free(orbuf); \ free(owbuf); \ \ LOG("Stats:");\ \ LOGF("Wanted fact_x: %.1f", fact_x);\ \ if (cnt_i) LOGF("cnt_i: %.0f ori_i: %.0f new_i: %.0f fact_i: %.1f", (float)cnt_i, (float)ori_i, (float)new_i, (float)ori_i/(float)new_i); \ else LOGF("cnt_i: %.0f", (float)cnt_i);\ \ if (cnt_p) LOGF("cnt_p: %.0f ori_p: %.0f new_p: %.0f fact_p: %.1f cnt_p_i: %.0f cnt_p_ni: %.0f propor: %.1f i", \ (float)cnt_p, (float)ori_p, (float)new_p, (float)ori_p/(float)new_p, (float)cnt_p_i, (float)cnt_p_ni, (float)cnt_p_i/((float)cnt_p_i+(float)cnt_p_ni)); \ else LOGF("cnt_p: %.0f", (float)cnt_p); \ \ if (cnt_b) LOGF("cnt_b: %.0f ori_b: %.0f new_b: %.0f fact_b: %.1f cnt_b_i: %.0f cnt_b_ni: %.0f propor: %.1f i\n", \ (float)cnt_b, (float)ori_b, (float)new_b, (float)ori_b/(float)new_b, (float)cnt_b_i, (float)cnt_b_ni, (float)cnt_b_i/((float)cnt_b_i+(float)cnt_b_ni)); \ else LOGF("cnt_b: %.0f", (float)cnt_b); \ \ LOGF("Final fact_x: %.1f", (float)inbytecnt/(float)outbytecnt);\ exit(0); #else #define RETURN \ assert(rbuf >= cbuf);\ mloka1 = rbuf - cbuf;\ if (mloka1) { COPY(mloka1); }\ WRITE \ free(orbuf); \ free(owbuf); \ exit(0); #endif #define COPY(x)\ assert(x > 0); \ assert(wbuf + x < owbuf + BUF_SIZE); \ assert(cbuf + x < orbuf + BUF_SIZE); \ assert(cbuf + x >= orbuf); \ assert(wbuf + x >= orbuf); \ ac_memcpy(wbuf, cbuf, x);\ cbuf += x; \ wbuf += x; #define SEEKR(x)\ cbuf += x; \ assert (cbuf <= rbuf); \ assert (cbuf < orbuf + BUF_SIZE); \ assert (cbuf >= orbuf); #define SEEKW(x)\ wbuf += x; \ assert (wbuf < owbuf + BUF_SIZE); \ assert (wbuf >= owbuf); static inline void putbits(uint val, int n) { assert(n < 32); assert(!(val & (0xffffffffU << n))); while (unlikely(n >= outbitcnt)) { wbuf[0] = (outbitbuf << outbitcnt ) | (val >> (n - outbitcnt)); SEEKW(1); n -= outbitcnt; outbitbuf = 0; val &= ~(0xffffffffU << n); outbitcnt = BITS_IN_BUF; } if (likely(n)) { outbitbuf = (outbitbuf << n) | val; outbitcnt -= n; } assert(outbitcnt > 0); assert(outbitcnt <= BITS_IN_BUF); } static inline void Refill_bits(void) { assert((rbuf - cbuf) >= 1); inbitbuf |= cbuf[0] << (24 - inbitcnt); inbitcnt += 8; SEEKR(1) } static inline void Flush_Bits(uint n) { assert(inbitcnt >= n); inbitbuf <<= n; inbitcnt -= n; assert( (!n) || ((n>0) && !(inbitbuf & 0x1)) ); while (unlikely(inbitcnt < 24)) Refill_bits(); } static inline uint Show_Bits(uint n) { return ((unsigned int)inbitbuf) >> (32 - n); } static inline uint Get_Bits(uint n) { uint Val = Show_Bits(n); Flush_Bits(n); return Val; } static inline uint Copy_Bits(uint n) { uint Val = Get_Bits(n); putbits(Val, n); return Val; } static inline void flush_read_buffer(void) { int i = inbitcnt & 0x7; if (i) { if (inbitbuf >> (32 - i)) { DEBF("illegal inbitbuf: 0x%08X, %i, 0x%02X, %i", inbitbuf, inbitcnt, (inbitbuf >> (32 - i)), i); sliceError++; } inbitbuf <<= i; inbitcnt -= i; } SEEKR(-1 * (inbitcnt >> 3)); inbitcnt = 0; } static inline void flush_write_buffer(void) { if (outbitcnt != 8) putbits(0, outbitcnt); } /////---- begin ext mpeg code const uint8 non_linear_mquant_table[32] = { 0, 1, 2, 3, 4, 5, 6, 7, 8,10,12,14,16,18,20,22, 24,28,32,36,40,44,48,52, 56,64,72,80,88,96,104,112 }; const uint8 map_non_linear_mquant[113] = { 0,1,2,3,4,5,6,7,8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,16,16, 16,17,17,17,18,18,18,18,19,19,19,19,20,20,20,20,21,21,21,21,22,22, 22,22,23,23,23,23,24,24,24,24,24,24,24,25,25,25,25,25,25,25,26,26, 26,26,26,26,26,26,27,27,27,27,27,27,27,27,28,28,28,28,28,28,28,29, 29,29,29,29,29,29,29,29,29,30,30,30,30,30,30,30,31,31,31,31,31 }; static int scale_quant(double quant ) { int iquant; if (q_scale_type) { iquant = (int) floor(quant+0.5); /* clip mquant to legal (linear) range */ if (iquant<1) iquant = 1; if (iquant>112) iquant = 112; iquant = non_linear_mquant_table[map_non_linear_mquant[iquant]]; } else { /* clip mquant to legal (linear) range */ iquant = (int)floor(quant+0.5); if (iquant<2) iquant = 2; if (iquant>62) iquant = 62; iquant = (iquant/2)*2; // Must be *even* } return iquant; } static int increment_quant(int quant) { if (q_scale_type) { //assert(quant >= 1 && quant <= 112); if (quant < 1 || quant > 112) { DEBF("illegal quant: %d", quant); if (quant > 112) quant = 112; else if (quant < 1) quant = 1; DEBF("illegal quant changed to : %d", quant); sliceError++; } quant = map_non_linear_mquant[quant] + 1; if (quant_corr < -60.0f) quant++; if (quant > 31) quant = 31; quant = non_linear_mquant_table[quant]; } else { // assert(!(quant & 1)); if ((quant & 1) || (quant < 2) || (quant > 62)) { DEBF("illegal quant: %d", quant); if (quant & 1) quant--; if (quant > 62) quant = 62; else if (quant < 2) quant = 2; DEBF("illegal quant changed to : %d", quant); sliceError++; } quant += 2; if (quant_corr < -60.0f) quant += 2; if (quant > 62) quant = 62; } return quant; } static inline int intmax( register int x, register int y ) { return x < y ? y : x; } static inline int intmin( register int x, register int y ) { return x < y ? x : y; } static int getNewQuant(int curQuant) { double calc_quant, quant_to_use; int mquant = 0; calc_quant = curQuant * fact_x; quant_corr = (((inbytecnt - (rbuf - cbuf)) / fact_x) - (outbytecnt + (wbuf - owbuf))) / REACT_DELAY; quant_to_use = calc_quant - quant_corr; switch (picture_coding_type) { case I_TYPE: case P_TYPE: mquant = increment_quant(curQuant); break; case B_TYPE: mquant = intmax(scale_quant(quant_to_use), increment_quant(curQuant)); break; default: assert(0); break; } /* LOGF("type: %s orig_quant: %3i calc_quant: %7.1f quant_corr: %7.1f using_quant: %3i", (picture_coding_type == I_TYPE ? "I_TYPE" : (picture_coding_type == P_TYPE ? "P_TYPE" : "B_TYPE")), (int)curQuant, (float)calc_quant, (float)quant_corr, (int)mquant); */ assert(mquant >= curQuant); return mquant; } static inline int isNotEmpty(RunLevel *blk) { return (blk->level); } #include "putvlc.h" // return != 0 if error static int putAC(int run, int signed_level, int vlcformat) { int level, len; const VLCtable *ptab = NULL; level = (signed_level<0) ? -signed_level : signed_level; /* abs(signed_level) */ // assert(!(run<0 || run>63 || level==0 || level>2047)); if(run<0 || run>63) { DEBF("illegal run: %d", run); sliceError++; return 1; } if(level==0 || level>2047) { DEBF("illegal level: %d", level); sliceError++; return 1; } len = 0; if (run<2 && level<41) { if (vlcformat) ptab = &dct_code_tab1a[run][level-1]; else ptab = &dct_code_tab1[run][level-1]; len = ptab->len; } else if (run<32 && level<6) { if (vlcformat) ptab = &dct_code_tab2a[run-2][level-1]; else ptab = &dct_code_tab2[run-2][level-1]; len = ptab->len; } if (len) /* a VLC code exists */ { putbits(ptab->code, len); putbits(signed_level<0, 1); /* sign */ } else { putbits(1l, 6); /* Escape */ putbits(run, 6); /* 6 bit code for run */ putbits(((uint)signed_level) & 0xFFF, 12); } return 0; } // return != 0 if error static inline int putACfirst(int run, int val) { if (run==0 && (val==1 || val==-1)) { putbits(2|(val<0),2); return 0; } else return putAC(run,val,0); } static void putnonintrablk(RunLevel *blk) { assert(blk->level); if (putACfirst(blk->run, blk->level)) return; blk++; while(blk->level) { if (putAC(blk->run, blk->level, 0)) return; blk++; } putbits(2,2); } static inline void putcbp(int cbp) { putbits(cbptable[cbp].code,cbptable[cbp].len); } static void putmbtype(int mb_type) { putbits(mbtypetab[picture_coding_type-1][mb_type].code, mbtypetab[picture_coding_type-1][mb_type].len); } #include #include "getvlc.h" static int non_linear_quantizer_scale [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 18, 20, 22, 24, 28, 32, 36, 40, 44, 48, 52, 56, 64, 72, 80, 88, 96, 104, 112 }; static inline int get_macroblock_modes(void) { int macroblock_modes; const MBtab * tab; switch (picture_coding_type) { case I_TYPE: tab = MB_I + UBITS (bit_buf, 1); DUMPBITS (bit_buf, bits, tab->len); macroblock_modes = tab->modes; if ((! (frame_pred_frame_dct)) && (picture_structure == FRAME_PICTURE)) { macroblock_modes |= UBITS (bit_buf, 1) * DCT_TYPE_INTERLACED; DUMPBITS (bit_buf, bits, 1); } return macroblock_modes; case P_TYPE: tab = MB_P + UBITS (bit_buf, 5); DUMPBITS (bit_buf, bits, tab->len); macroblock_modes = tab->modes; if (picture_structure != FRAME_PICTURE) { if (macroblock_modes & MACROBLOCK_MOTION_FORWARD) { macroblock_modes |= UBITS (bit_buf, 2) * MOTION_TYPE_BASE; DUMPBITS (bit_buf, bits, 2); } return macroblock_modes; } else if (frame_pred_frame_dct) { if (macroblock_modes & MACROBLOCK_MOTION_FORWARD) macroblock_modes |= MC_FRAME; return macroblock_modes; } else { if (macroblock_modes & MACROBLOCK_MOTION_FORWARD) { macroblock_modes |= UBITS (bit_buf, 2) * MOTION_TYPE_BASE; DUMPBITS (bit_buf, bits, 2); } if (macroblock_modes & (MACROBLOCK_INTRA | MACROBLOCK_PATTERN)) { macroblock_modes |= UBITS (bit_buf, 1) * DCT_TYPE_INTERLACED; DUMPBITS (bit_buf, bits, 1); } return macroblock_modes; } case B_TYPE: tab = MB_B + UBITS (bit_buf, 6); DUMPBITS (bit_buf, bits, tab->len); macroblock_modes = tab->modes; if (picture_structure != FRAME_PICTURE) { if (! (macroblock_modes & MACROBLOCK_INTRA)) { macroblock_modes |= UBITS (bit_buf, 2) * MOTION_TYPE_BASE; DUMPBITS (bit_buf, bits, 2); } return macroblock_modes; } else if (frame_pred_frame_dct) { /* if (! (macroblock_modes & MACROBLOCK_INTRA)) */ macroblock_modes |= MC_FRAME; return macroblock_modes; } else { if (macroblock_modes & MACROBLOCK_INTRA) goto intra; macroblock_modes |= UBITS (bit_buf, 2) * MOTION_TYPE_BASE; DUMPBITS (bit_buf, bits, 2); if (macroblock_modes & (MACROBLOCK_INTRA | MACROBLOCK_PATTERN)) { intra: macroblock_modes |= UBITS (bit_buf, 1) * DCT_TYPE_INTERLACED; DUMPBITS (bit_buf, bits, 1); } return macroblock_modes; } default: return 0; } } static inline int get_quantizer_scale(void) { int quantizer_scale_code; quantizer_scale_code = UBITS (bit_buf, 5); DUMPBITS (bit_buf, bits, 5); if (!quantizer_scale_code) { DEBF("illegal quant scale code: %d", quantizer_scale_code); sliceError++; quantizer_scale_code++; } if (q_scale_type) return non_linear_quantizer_scale[quantizer_scale_code]; else return quantizer_scale_code << 1; } static inline int get_motion_delta (const int f_code) { #define bit_buf (inbitbuf) int delta; int sign; const MVtab * tab; if (bit_buf & 0x80000000) { COPYBITS (bit_buf, bits, 1); return 0; } else if (bit_buf >= 0x0c000000) { tab = MV_4 + UBITS (bit_buf, 4); delta = (tab->delta << f_code) + 1; COPYBITS (bit_buf, bits, tab->len); sign = SBITS (bit_buf, 1); COPYBITS (bit_buf, bits, 1); if (f_code) delta += UBITS (bit_buf, f_code); COPYBITS (bit_buf, bits, f_code); return (delta ^ sign) - sign; } else { tab = MV_10 + UBITS (bit_buf, 10); delta = (tab->delta << f_code) + 1; COPYBITS (bit_buf, bits, tab->len); sign = SBITS (bit_buf, 1); COPYBITS (bit_buf, bits, 1); if (f_code) { delta += UBITS (bit_buf, f_code); COPYBITS (bit_buf, bits, f_code); } return (delta ^ sign) - sign; } } static inline int get_dmv(void) { const DMVtab * tab; tab = DMV_2 + UBITS (bit_buf, 2); COPYBITS (bit_buf, bits, tab->len); return tab->dmv; } static inline int get_coded_block_pattern(void) { #define bit_buf (inbitbuf) const CBPtab * tab; if (bit_buf >= 0x20000000) { tab = CBP_7 + (UBITS (bit_buf, 7) - 16); DUMPBITS (bit_buf, bits, tab->len); return tab->cbp; } else { tab = CBP_9 + UBITS (bit_buf, 9); DUMPBITS (bit_buf, bits, tab->len); return tab->cbp; } } static inline int get_luma_dc_dct_diff(void) { #define bit_buf (inbitbuf) const DCtab * tab; int size; int dc_diff; if (bit_buf < 0xf8000000) { tab = DC_lum_5 + UBITS (bit_buf, 5); size = tab->size; if (size) { COPYBITS (bit_buf, bits, tab->len); //dc_diff = UBITS (bit_buf, size) - UBITS (SBITS (~bit_buf, 1), size); dc_diff = UBITS (bit_buf, size); if (!(dc_diff >> (size - 1))) dc_diff = (dc_diff + 1) - (1 << size); COPYBITS (bit_buf, bits, size); return dc_diff; } else { COPYBITS (bit_buf, bits, 3); return 0; } } else { tab = DC_long + (UBITS (bit_buf, 9) - 0x1e0); size = tab->size; COPYBITS (bit_buf, bits, tab->len); //dc_diff = UBITS (bit_buf, size) - UBITS (SBITS (~bit_buf, 1), size); dc_diff = UBITS (bit_buf, size); if (!(dc_diff >> (size - 1))) dc_diff = (dc_diff + 1) - (1 << size); COPYBITS (bit_buf, bits, size); return dc_diff; } } static inline int get_chroma_dc_dct_diff(void) { #define bit_buf (inbitbuf) const DCtab * tab; int size; int dc_diff; if (bit_buf < 0xf8000000) { tab = DC_chrom_5 + UBITS (bit_buf, 5); size = tab->size; if (size) { COPYBITS (bit_buf, bits, tab->len); //dc_diff = UBITS (bit_buf, size) - UBITS (SBITS (~bit_buf, 1), size); dc_diff = UBITS (bit_buf, size); if (!(dc_diff >> (size - 1))) dc_diff = (dc_diff + 1) - (1 << size); COPYBITS (bit_buf, bits, size); return dc_diff; } else { COPYBITS (bit_buf, bits, 2); return 0; } } else { tab = DC_long + (UBITS (bit_buf, 10) - 0x3e0); size = tab->size; COPYBITS (bit_buf, bits, tab->len + 1); //dc_diff = UBITS (bit_buf, size) - UBITS (SBITS (~bit_buf, 1), size); dc_diff = UBITS (bit_buf, size); if (!(dc_diff >> (size - 1))) dc_diff = (dc_diff + 1) - (1 << size); COPYBITS (bit_buf, bits, size); return dc_diff; } } static void get_intra_block_B14(void) { #define bit_buf (inbitbuf) int q = quantizer_scale, nq = new_quantizer_scale, tst = (nq / q) + ((nq % q) ? 1 : 0); int i, li; int val; const DCTtab * tab; li = i = 0; while (1) { if (bit_buf >= 0x28000000) { tab = DCT_B14AC_5 + (UBITS (bit_buf, 5) - 5); i += tab->run; if (i >= 64) break; /* end of block */ normal_code: DUMPBITS (bit_buf, bits, tab->len); val = tab->level; if (val >= tst) { val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1); if (putAC(i - li - 1, (val * q) / nq, 0)) break; li = i; } DUMPBITS (bit_buf, bits, 1); continue; } else if (bit_buf >= 0x04000000) { tab = DCT_B14_8 + (UBITS (bit_buf, 8) - 4); i += tab->run; if (i < 64) goto normal_code; /* escape code */ i += (UBITS (bit_buf, 12) & 0x3F) - 64; if (i >= 64) break; /* illegal, check needed to avoid buffer overflow */ DUMPBITS (bit_buf, bits, 12); val = SBITS (bit_buf, 12); if (abs(val) >= tst) { if (putAC(i - li - 1, (val * q) / nq, 0)) break; li = i; } DUMPBITS (bit_buf, bits, 12); continue; } else if (bit_buf >= 0x02000000) { tab = DCT_B14_10 + (UBITS (bit_buf, 10) - 8); i += tab->run; if (i < 64) goto normal_code; } else if (bit_buf >= 0x00800000) { tab = DCT_13 + (UBITS (bit_buf, 13) - 16); i += tab->run; if (i < 64) goto normal_code; } else if (bit_buf >= 0x00200000) { tab = DCT_15 + (UBITS (bit_buf, 15) - 16); i += tab->run; if (i < 64) goto normal_code; } else { tab = DCT_16 + UBITS (bit_buf, 16); DUMPBITS (bit_buf, bits, 16); i += tab->run; if (i < 64) goto normal_code; } break; /* illegal, check needed to avoid buffer overflow */ } COPYBITS (bit_buf, bits, 2); /* end of block code */ } static void get_intra_block_B15(void) { #define bit_buf (inbitbuf) int q = quantizer_scale, nq = new_quantizer_scale, tst = (nq / q) + ((nq % q) ? 1 : 0); int i, li; int val; const DCTtab * tab; li = i = 0; while (1) { if (bit_buf >= 0x04000000) { tab = DCT_B15_8 + (UBITS (bit_buf, 8) - 4); i += tab->run; if (i < 64) { normal_code: DUMPBITS (bit_buf, bits, tab->len); val = tab->level; if (val >= tst) { val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1); if (putAC(i - li - 1, (val * q) / nq, 1)) break; li = i; } DUMPBITS (bit_buf, bits, 1); continue; } else { i += (UBITS (bit_buf, 12) & 0x3F) - 64; if (i >= 64) break; /* illegal, check against buffer overflow */ DUMPBITS (bit_buf, bits, 12); val = SBITS (bit_buf, 12); if (abs(val) >= tst) { if (putAC(i - li - 1, (val * q) / nq, 1)) break; li = i; } DUMPBITS (bit_buf, bits, 12); continue; } } else if (bit_buf >= 0x02000000) { tab = DCT_B15_10 + (UBITS (bit_buf, 10) - 8); i += tab->run; if (i < 64) goto normal_code; } else if (bit_buf >= 0x00800000) { tab = DCT_13 + (UBITS (bit_buf, 13) - 16); i += tab->run; if (i < 64) goto normal_code; } else if (bit_buf >= 0x00200000) { tab = DCT_15 + (UBITS (bit_buf, 15) - 16); i += tab->run; if (i < 64) goto normal_code; } else { tab = DCT_16 + UBITS (bit_buf, 16); DUMPBITS (bit_buf, bits, 16); i += tab->run; if (i < 64) goto normal_code; } break; /* illegal, check needed to avoid buffer overflow */ } COPYBITS (bit_buf, bits, 4); /* end of block code */ } static int get_non_intra_block_drop (RunLevel *blk) { #define bit_buf (inbitbuf) int i, li; int val; const DCTtab * tab; RunLevel *sblk = blk + 1; li = i = -1; if (bit_buf >= 0x28000000) { tab = DCT_B14DC_5 + (UBITS (bit_buf, 5) - 5); goto entry_1; } else goto entry_2; while (1) { if (bit_buf >= 0x28000000) { tab = DCT_B14AC_5 + (UBITS (bit_buf, 5) - 5); entry_1: i += tab->run; if (i >= 64) break; /* end of block */ normal_code: DUMPBITS (bit_buf, bits, tab->len); val = tab->level; val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1); /* if (bitstream_get (1)) val = -val; */ blk->level = val; blk->run = i - li - 1; li = i; blk++; DUMPBITS (bit_buf, bits, 1); continue; } entry_2: if (bit_buf >= 0x04000000) { tab = DCT_B14_8 + (UBITS (bit_buf, 8) - 4); i += tab->run; if (i < 64) goto normal_code; /* escape code */ i += (UBITS (bit_buf, 12) & 0x3F) - 64; if (i >= 64) break; /* illegal, check needed to avoid buffer overflow */ DUMPBITS (bit_buf, bits, 12); val = SBITS (bit_buf, 12); blk->level = val; blk->run = i - li - 1; li = i; blk++; DUMPBITS (bit_buf, bits, 12); continue; } else if (bit_buf >= 0x02000000) { tab = DCT_B14_10 + (UBITS (bit_buf, 10) - 8); i += tab->run; if (i < 64) goto normal_code; } else if (bit_buf >= 0x00800000) { tab = DCT_13 + (UBITS (bit_buf, 13) - 16); i += tab->run; if (i < 64) goto normal_code; } else if (bit_buf >= 0x00200000) { tab = DCT_15 + (UBITS (bit_buf, 15) - 16); i += tab->run; if (i < 64) goto normal_code; } else { tab = DCT_16 + UBITS (bit_buf, 16); DUMPBITS (bit_buf, bits, 16); i += tab->run; if (i < 64) goto normal_code; } break; /* illegal, check needed to avoid buffer overflow */ } DUMPBITS (bit_buf, bits, 2); /* dump end of block code */ // remove last coeff if (blk != sblk) { blk--; // remove more coeffs if very late if ((quant_corr < -60.0f) && (blk != sblk)) { blk--; if ((quant_corr < -80.0f) && (blk != sblk)) { blk--; if ((quant_corr < -100.0f) && (blk != sblk)) { blk--; if ((quant_corr < -120.0f) && (blk != sblk)) blk--; } } } } blk->level = 0; return i; } static int get_non_intra_block_rq (RunLevel *blk) { #define bit_buf (inbitbuf) int q = quantizer_scale, nq = new_quantizer_scale, tst = (nq / q) + ((nq % q) ? 1 : 0); int i, li; int val; const DCTtab * tab; li = i = -1; if (bit_buf >= 0x28000000) { tab = DCT_B14DC_5 + (UBITS (bit_buf, 5) - 5); goto entry_1; } else goto entry_2; while (1) { if (bit_buf >= 0x28000000) { tab = DCT_B14AC_5 + (UBITS (bit_buf, 5) - 5); entry_1: i += tab->run; if (i >= 64) break; /* end of block */ normal_code: DUMPBITS (bit_buf, bits, tab->len); val = tab->level; if (val >= tst) { val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1); blk->level = (val * q) / nq; blk->run = i - li - 1; li = i; blk++; } //if ( ((val) && (tab->level < tst)) || ((!val) && (tab->level >= tst)) ) // LOGF("level: %i val: %i tst : %i q: %i nq : %i", tab->level, val, tst, q, nq); DUMPBITS (bit_buf, bits, 1); continue; } entry_2: if (bit_buf >= 0x04000000) { tab = DCT_B14_8 + (UBITS (bit_buf, 8) - 4); i += tab->run; if (i < 64) goto normal_code; /* escape code */ i += (UBITS (bit_buf, 12) & 0x3F) - 64; if (i >= 64) break; /* illegal, check needed to avoid buffer overflow */ DUMPBITS (bit_buf, bits, 12); val = SBITS (bit_buf, 12); if (abs(val) >= tst) { blk->level = (val * q) / nq; blk->run = i - li - 1; li = i; blk++; } DUMPBITS (bit_buf, bits, 12); continue; } else if (bit_buf >= 0x02000000) { tab = DCT_B14_10 + (UBITS (bit_buf, 10) - 8); i += tab->run; if (i < 64) goto normal_code; } else if (bit_buf >= 0x00800000) { tab = DCT_13 + (UBITS (bit_buf, 13) - 16); i += tab->run; if (i < 64) goto normal_code; } else if (bit_buf >= 0x00200000) { tab = DCT_15 + (UBITS (bit_buf, 15) - 16); i += tab->run; if (i < 64) goto normal_code; } else { tab = DCT_16 + UBITS (bit_buf, 16); DUMPBITS (bit_buf, bits, 16); i += tab->run; if (i < 64) goto normal_code; } break; /* illegal, check needed to avoid buffer overflow */ } DUMPBITS (bit_buf, bits, 2); /* dump end of block code */ blk->level = 0; return i; } static inline void slice_intra_DCT (const int cc) { if (cc == 0) get_luma_dc_dct_diff (); else get_chroma_dc_dct_diff (); if (intra_vlc_format) get_intra_block_B15 (); else get_intra_block_B14 (); } static inline void slice_non_intra_DCT (int cur_block) { if (picture_coding_type == P_TYPE) get_non_intra_block_drop(block[cur_block]); else get_non_intra_block_rq(block[cur_block]); } static void motion_fr_frame(uint f_code[2]) { get_motion_delta (f_code[0]); get_motion_delta (f_code[1]); } static void motion_fr_field(uint f_code[2]) { COPYBITS (bit_buf, bits, 1); get_motion_delta (f_code[0]); get_motion_delta (f_code[1]); COPYBITS (bit_buf, bits, 1); get_motion_delta (f_code[0]); get_motion_delta (f_code[1]); } static void motion_fr_dmv(uint f_code[2]) { get_motion_delta (f_code[0]); get_dmv (); get_motion_delta (f_code[1]); get_dmv (); } /* like motion_frame, but parsing without actual motion compensation */ static void motion_fr_conceal(void) { get_motion_delta (f_code[0][0]); get_motion_delta (f_code[0][1]); COPYBITS (bit_buf, bits, 1); /* remove marker_bit */ } static void motion_fi_field(uint f_code[2]) { COPYBITS (bit_buf, bits, 1); get_motion_delta (f_code[0]); get_motion_delta (f_code[1]); } static void motion_fi_16x8(uint f_code[2]) { COPYBITS (bit_buf, bits, 1); get_motion_delta (f_code[0]); get_motion_delta (f_code[1]); COPYBITS (bit_buf, bits, 1); get_motion_delta (f_code[0]); get_motion_delta (f_code[1]); } static void motion_fi_dmv(uint f_code[2]) { get_motion_delta (f_code[0]); get_dmv (); get_motion_delta (f_code[1]); get_dmv (); } static void motion_fi_conceal(void) { COPYBITS (bit_buf, bits, 1); /* remove field_select */ get_motion_delta (f_code[0][0]); get_motion_delta (f_code[0][1]); COPYBITS (bit_buf, bits, 1); /* remove marker_bit */ } #define MOTION_CALL(routine,direction) \ do { \ if ((direction) & MACROBLOCK_MOTION_FORWARD) \ routine (f_code[0]); \ if ((direction) & MACROBLOCK_MOTION_BACKWARD) \ routine (f_code[1]); \ } while (0) #define NEXT_MACROBLOCK \ do { \ h_offset += 16; \ if (h_offset == horizontal_size_value) \ { \ v_offset += 16; \ if (v_offset > (vertical_size_value - 16)) return; \ h_offset = 0; \ } \ } while (0) static void putmbdata(int macroblock_modes) { putmbtype(macroblock_modes & 0x1F); switch (picture_coding_type) { case I_TYPE: if ((! (frame_pred_frame_dct)) && (picture_structure == FRAME_PICTURE)) putbits(macroblock_modes & DCT_TYPE_INTERLACED ? 1 : 0, 1); break; case P_TYPE: if (picture_structure != FRAME_PICTURE) { if (macroblock_modes & MACROBLOCK_MOTION_FORWARD) putbits((macroblock_modes & MOTION_TYPE_MASK) / MOTION_TYPE_BASE, 2); break; } else if (frame_pred_frame_dct) break; else { if (macroblock_modes & MACROBLOCK_MOTION_FORWARD) putbits((macroblock_modes & MOTION_TYPE_MASK) / MOTION_TYPE_BASE, 2); if (macroblock_modes & (MACROBLOCK_INTRA | MACROBLOCK_PATTERN)) putbits(macroblock_modes & DCT_TYPE_INTERLACED ? 1 : 0, 1); break; } case B_TYPE: if (picture_structure != FRAME_PICTURE) { if (! (macroblock_modes & MACROBLOCK_INTRA)) putbits((macroblock_modes & MOTION_TYPE_MASK) / MOTION_TYPE_BASE, 2); break; } else if (frame_pred_frame_dct) break; else { if (macroblock_modes & MACROBLOCK_INTRA) goto intra; putbits((macroblock_modes & MOTION_TYPE_MASK) / MOTION_TYPE_BASE, 2); if (macroblock_modes & (MACROBLOCK_INTRA | MACROBLOCK_PATTERN)) { intra: putbits(macroblock_modes & DCT_TYPE_INTERLACED ? 1 : 0, 1); } break; } } } static inline void put_quantiser(int quantiser) { putbits(q_scale_type ? map_non_linear_mquant[quantiser] : quantiser >> 1, 5); last_coded_scale = quantiser; } static inline int slice_init (int code) { #define bit_buf (inbitbuf) int offset; const MBAtab * mba; v_offset = (code - 1) * 16; quantizer_scale = get_quantizer_scale (); if (picture_coding_type == P_TYPE) new_quantizer_scale = quantizer_scale; else new_quantizer_scale = getNewQuant(quantizer_scale); put_quantiser(new_quantizer_scale); /*LOGF("************************\nstart of slice %i in %s picture. ori quant: %i new quant: %i", code, (picture_coding_type == I_TYPE ? "I_TYPE" : (picture_coding_type == P_TYPE ? "P_TYPE" : "B_TYPE")), quantizer_scale, new_quantizer_scale);*/ /* ignore intra_slice and all the extra data */ while (bit_buf & 0x80000000) { DUMPBITS (bit_buf, bits, 9); } /* decode initial macroblock address increment */ offset = 0; while (1) { if (bit_buf >= 0x08000000) { mba = MBA_5 + (UBITS (bit_buf, 6) - 2); break; } else if (bit_buf >= 0x01800000) { mba = MBA_11 + (UBITS (bit_buf, 12) - 24); break; } else switch (UBITS (bit_buf, 12)) { case 8: /* macroblock_escape */ offset += 33; COPYBITS (bit_buf, bits, 11); continue; default: /* error */ return 1; } } COPYBITS (bit_buf, bits, mba->len + 1); h_offset = (offset + mba->mba) << 4; while (h_offset - (int)horizontal_size_value >= 0) { h_offset -= horizontal_size_value; v_offset += 16; } if (v_offset > (vertical_size_value - 16)) return 1; return 0; } static void mpeg2_slice(const int code) { #define bit_buf (inbitbuf) if (slice_init (code)) return; while (1) { int macroblock_modes; int mba_inc; const MBAtab * mba; macroblock_modes = get_macroblock_modes (); if (macroblock_modes & MACROBLOCK_QUANT) quantizer_scale = get_quantizer_scale (); //LOGF("blk %i : ", h_offset >> 4); if (macroblock_modes & MACROBLOCK_INTRA) { #ifdef STAT if (picture_coding_type == P_TYPE) cnt_p_i++; else if (picture_coding_type == B_TYPE) cnt_b_i++; #endif //LOG("intra "); if (macroblock_modes & MACROBLOCK_QUANT) LOGF("got new quant: %i ", quantizer_scale); new_quantizer_scale = increment_quant(quantizer_scale); if (last_coded_scale == new_quantizer_scale) macroblock_modes &= 0xFFFFFFEF; // remove MACROBLOCK_QUANT else macroblock_modes |= MACROBLOCK_QUANT; //add MACROBLOCK_QUANT putmbdata(macroblock_modes); if (macroblock_modes & MACROBLOCK_QUANT) put_quantiser(new_quantizer_scale); //if (macroblock_modes & MACROBLOCK_QUANT) LOGF("put new quant: %i ", new_quantizer_scale); if (concealment_motion_vectors) { if (picture_structure == FRAME_PICTURE) motion_fr_conceal (); else motion_fi_conceal (); } slice_intra_DCT ( 0); slice_intra_DCT ( 0); slice_intra_DCT ( 0); slice_intra_DCT ( 0); slice_intra_DCT ( 1); slice_intra_DCT ( 2); } else { int new_coded_block_pattern = 0; // begin saving data int batb; uint8 n_owbuf[32], *n_wbuf, *o_owbuf = owbuf, *o_wbuf = wbuf; uint32 n_outbitcnt, n_outbitbuf, o_outbitcnt = outbitcnt, o_outbitbuf = outbitbuf; outbitbuf = 0; outbitcnt = BITS_IN_BUF; owbuf = wbuf = n_owbuf; if (picture_structure == FRAME_PICTURE) switch (macroblock_modes & MOTION_TYPE_MASK) { case MC_FRAME: MOTION_CALL (motion_fr_frame, macroblock_modes); break; case MC_FIELD: MOTION_CALL (motion_fr_field, macroblock_modes); break; case MC_DMV: MOTION_CALL (motion_fr_dmv, MACROBLOCK_MOTION_FORWARD); break; } else switch (macroblock_modes & MOTION_TYPE_MASK) { case MC_FIELD: MOTION_CALL (motion_fi_field, macroblock_modes); break; case MC_16X8: MOTION_CALL (motion_fi_16x8, macroblock_modes); break; case MC_DMV: MOTION_CALL (motion_fi_dmv, MACROBLOCK_MOTION_FORWARD); break; } assert(wbuf - owbuf < 32); n_wbuf = wbuf; n_outbitcnt = outbitcnt; n_outbitbuf = outbitbuf; assert(owbuf == n_owbuf); outbitcnt = o_outbitcnt; outbitbuf = o_outbitbuf; owbuf = o_owbuf; wbuf = o_wbuf; // end saving data #ifdef STAT if (picture_coding_type == P_TYPE) cnt_p_ni++; else if (picture_coding_type == B_TYPE) cnt_b_ni++; #endif if (picture_coding_type == P_TYPE) new_quantizer_scale = quantizer_scale; else new_quantizer_scale = getNewQuant(quantizer_scale); //LOG("non intra "); if (macroblock_modes & MACROBLOCK_QUANT) LOGF("got new quant: %i ", quantizer_scale); if (macroblock_modes & MACROBLOCK_PATTERN) { int coded_block_pattern = get_coded_block_pattern (); if (coded_block_pattern & 0x20) slice_non_intra_DCT(0); if (coded_block_pattern & 0x10) slice_non_intra_DCT(1); if (coded_block_pattern & 0x08) slice_non_intra_DCT(2); if (coded_block_pattern & 0x04) slice_non_intra_DCT(3); if (coded_block_pattern & 0x02) slice_non_intra_DCT(4); if (coded_block_pattern & 0x01) slice_non_intra_DCT(5); if (picture_coding_type == B_TYPE) { if (coded_block_pattern & 0x20) if (isNotEmpty(block[0])) new_coded_block_pattern |= 0x20; if (coded_block_pattern & 0x10) if (isNotEmpty(block[1])) new_coded_block_pattern |= 0x10; if (coded_block_pattern & 0x08) if (isNotEmpty(block[2])) new_coded_block_pattern |= 0x08; if (coded_block_pattern & 0x04) if (isNotEmpty(block[3])) new_coded_block_pattern |= 0x04; if (coded_block_pattern & 0x02) if (isNotEmpty(block[4])) new_coded_block_pattern |= 0x02; if (coded_block_pattern & 0x01) if (isNotEmpty(block[5])) new_coded_block_pattern |= 0x01; if (!new_coded_block_pattern) macroblock_modes &= 0xFFFFFFED; // remove MACROBLOCK_PATTERN and MACROBLOCK_QUANT flag } else new_coded_block_pattern = coded_block_pattern; } if (last_coded_scale == new_quantizer_scale) macroblock_modes &= 0xFFFFFFEF; // remove MACROBLOCK_QUANT else if (macroblock_modes & MACROBLOCK_PATTERN) macroblock_modes |= MACROBLOCK_QUANT; //add MACROBLOCK_QUANT assert( (macroblock_modes & MACROBLOCK_PATTERN) || !(macroblock_modes & MACROBLOCK_QUANT) ); putmbdata(macroblock_modes); if (macroblock_modes & MACROBLOCK_QUANT) put_quantiser(new_quantizer_scale); //if (macroblock_modes & MACROBLOCK_PATTERN) LOG("coded "); //if (macroblock_modes & MACROBLOCK_QUANT) LOGF("put new quant: %i ", new_quantizer_scale); // put saved motion data... for (batb = 0; batb < (n_wbuf - n_owbuf); batb++) putbits(n_owbuf[batb], 8); putbits(n_outbitbuf, BITS_IN_BUF - n_outbitcnt); // end saved motion data... if (macroblock_modes & MACROBLOCK_PATTERN) { putcbp(new_coded_block_pattern); if (new_coded_block_pattern & 0x20) putnonintrablk(block[0]); if (new_coded_block_pattern & 0x10) putnonintrablk(block[1]); if (new_coded_block_pattern & 0x08) putnonintrablk(block[2]); if (new_coded_block_pattern & 0x04) putnonintrablk(block[3]); if (new_coded_block_pattern & 0x02) putnonintrablk(block[4]); if (new_coded_block_pattern & 0x01) putnonintrablk(block[5]); } } //LOGF("o: %i c: %i n: %i", quantizer_scale, last_coded_scale, new_quantizer_scale); NEXT_MACROBLOCK; mba_inc = 0; while (1) { if (bit_buf >= 0x10000000) { mba = MBA_5 + (UBITS (bit_buf, 5) - 2); break; } else if (bit_buf >= 0x03000000) { mba = MBA_11 + (UBITS (bit_buf, 11) - 24); break; } else switch (UBITS (bit_buf, 11)) { case 8: /* macroblock_escape */ mba_inc += 33; COPYBITS (bit_buf, bits, 11); continue; default: /* end of slice, or error */ return; } } COPYBITS (bit_buf, bits, mba->len); mba_inc += mba->mba; if (mba_inc) do { NEXT_MACROBLOCK; } while (--mba_inc); } } /////---- end ext mpeg code void version(void) { /* print id string to stderr */ fprintf(stderr, "%s (%s v%s) (C) 2001-2003 Antoine Missout\n", EXE, PACKAGE, VERSION); } static void usage(int status) { version(); fprintf(stderr,"\nUsage: %s [options]\n", EXE); fprintf(stderr," -i name input file name [stdin]\n"); fprintf(stderr," -o file output file name [stdout]\n"); fprintf(stderr," -d mode verbosity mode\n"); fprintf(stderr," -f factor requantize factor [1.5]\n"); fprintf(stderr," -b N remove byte stuffing [1]\n"); fprintf(stderr," -v print version\n"); exit(status); } int main (int argc, char *argv[]) { uint8 ID, found; int ch; char *ifile=NULL, *ofile=NULL; int byte_stuff; #ifdef STAT ori_i = ori_p = ori_b = 0; new_i = new_p = new_b = 0; cnt_i = cnt_p = cnt_b = 0; cnt_p_i = cnt_p_ni = 0; cnt_b_i = cnt_b_ni = 0; #endif // default fact_x = 1.25; byte_stuff = 1; libtc_init(&argc, &argv); while ((ch = getopt(argc, argv, "b:d:i:o:f:v?h")) != -1) { switch (ch) { case 'i': if(optarg[0]=='-') usage(EXIT_FAILURE); ifile = optarg; break; case 'o': if(optarg[0]=='-') usage(EXIT_FAILURE); ofile = optarg; break; case 'f': if(optarg[0]=='-') usage(EXIT_FAILURE); fact_x = atof(optarg); break; case 'd': if(optarg[0]=='-') usage(EXIT_FAILURE); verbose = atoi(optarg); break; case 'b': if(optarg[0]=='-') usage(EXIT_FAILURE); byte_stuff = atoi(optarg); break; case 'v': version(); exit(0); break; case 'h': case '?': default: usage(EXIT_SUCCESS); break; } } // while if (ifile) { if ( (ifd = open(ifile, O_RDONLY, 0)) < 0) { tc_log_warn(EXE, "Cannot open input file: %s", strerror(errno)); } } else { ifd = STDIN_FILENO; } if (ofile) { if ( (ofd = open(ofile, O_WRONLY | O_CREAT | O_TRUNC, 0644))<0) { tc_log_warn(EXE, "Cannot open output file: %s", strerror(errno)); } } else { ofd = STDOUT_FILENO; } rbuf = cbuf = orbuf = tc_malloc(BUF_SIZE); wbuf = owbuf = tc_malloc(BUF_SIZE); if (!orbuf || !owbuf) { tc_log_error(EXE, "malloc() failed at %s:%d", __FILE__, __LINE__); exit (1); } inbytecnt = outbytecnt = 0; validPicHeader = 0; validSeqHeader = 0; validExtHeader = 0; if (fact_x < 1.0) fact_x = 1.0; else if (fact_x > 900.0) fact_x = 900.0; byte_stuff = !!byte_stuff; LOG("MPEG2 Requantiser by Makira."); LOGF("Using %f as factor.", fact_x); // recoding while(1) { // get next start code prefix found = 0; while (!found) { if (!byte_stuff) { LOCK(3) } else { LOCK(6) if ( (cbuf[0] == 0) && (cbuf[1] == 0) && (cbuf[2] == 0) && (cbuf[3] == 0) && (cbuf[4] == 0) && (cbuf[5] == 0) ) { SEEKR(1) } } if ( (cbuf[0] == 0) && (cbuf[1] == 0) && (cbuf[2] == 1) ) found = 1; // start code ! else { COPY(1) } // continue search } COPY(3) // get start code LOCK(1) ID = cbuf[0]; COPY(1) if (ID == 0x00) // pic header { LOCK(4) picture_coding_type = (cbuf[1] >> 3) & 0x7; if (picture_coding_type < 1 || picture_coding_type > 3) { DEBF("illegal picture_coding_type: %i", picture_coding_type); validPicHeader = 0; } else { validPicHeader = 1; cbuf[1] |= 0x7; cbuf[2] = 0xFF; cbuf[3] |= 0xF8; // vbv_delay is now 0xFFFF } COPY(4) } else if (ID == 0xB3) // seq header { LOCK(8) horizontal_size_value = (cbuf[0] << 4) | (cbuf[1] >> 4); vertical_size_value = ((cbuf[1] & 0xF) << 8) | cbuf[2]; if ( horizontal_size_value > 720 || horizontal_size_value < 352 || vertical_size_value > 576 || vertical_size_value < 480 || (horizontal_size_value & 0xF) || (vertical_size_value & 0xF)) { DEBF("illegal size, hori: %i verti: %i", horizontal_size_value, vertical_size_value); validSeqHeader = 0; } else validSeqHeader = 1; COPY(8) } else if (ID == 0xB5) // extension { LOCK(1) if ((cbuf[0] >> 4) == 0x8) // pic coding ext { LOCK(5) f_code[0][0] = (cbuf[0] & 0xF) - 1; f_code[0][1] = (cbuf[1] >> 4) - 1; f_code[1][0] = (cbuf[1] & 0xF) - 1; f_code[1][1] = (cbuf[2] >> 4) - 1; intra_dc_precision = (cbuf[2] >> 2) & 0x3; picture_structure = cbuf[2] & 0x3; frame_pred_frame_dct = (cbuf[3] >> 6) & 0x1; concealment_motion_vectors = (cbuf[3] >> 5) & 0x1; q_scale_type = (cbuf[3] >> 4) & 0x1; intra_vlc_format = (cbuf[3] >> 3) & 0x1; alternate_scan = (cbuf[3] >> 2) & 0x1; if ( (f_code[0][0] > 8 && f_code[0][0] < 14) || (f_code[0][1] > 8 && f_code[0][1] < 14) || (f_code[1][0] > 8 && f_code[1][0] < 14) || (f_code[1][1] > 8 && f_code[1][1] < 14) || picture_structure == 0) { DEBF("illegal ext, f_code[0][0]: %i f_code[0][1]: %i f_code[1][0]: %i f_code[1][1]: %i picture_structure:%i", f_code[0][0], f_code[0][1], f_code[1][0], f_code[1][1], picture_structure); validExtHeader = 0; } else validExtHeader = 1; COPY(5) } else { COPY(1) } } else if (ID == 0xB8) // gop header { LOCK(4) COPY(4) } else if ((ID >= 0x01) && (ID <= 0xAF) && validPicHeader && validSeqHeader && validExtHeader) // slice { uint8 *outTemp = wbuf, *inTemp = cbuf; quant_corr = (((inbytecnt - (rbuf - cbuf)) / fact_x) - (outbytecnt + (wbuf - owbuf))) / REACT_DELAY; if ( ((picture_coding_type == B_TYPE) && (quant_corr < 2.5f)) // don't recompress if we're in advance! || ((picture_coding_type == P_TYPE) && (quant_corr < -2.5f)) || ((picture_coding_type == I_TYPE) && (quant_corr < -5.0f)) ) { uint8 *nsc = cbuf; int fsc = 0, toLock; // lock all the slice while (!fsc) { toLock = nsc - cbuf + 3; LOCK(toLock) if ( (nsc[0] == 0) && (nsc[1] == 0) && (nsc[2] == 1) ) fsc = 1; // start code ! else nsc++; // continue search } // init error sliceError = 0; // init bit buffer inbitbuf = 0; inbitcnt = 0; outbitbuf = 0; outbitcnt = BITS_IN_BUF; // get 32 bits Refill_bits(); Refill_bits(); Refill_bits(); Refill_bits(); // begin bit level recoding mpeg2_slice(ID); flush_read_buffer(); flush_write_buffer(); // end bit level recoding /*LOGF("type: %s code: %02i in : %6i out : %6i diff : %6i fact: %2.2f", (picture_coding_type == I_TYPE ? "I_TYPE" : (picture_coding_type == P_TYPE ? "P_TYPE" : "B_TYPE")), ID, cbuf - inTemp, wbuf - outTemp, (wbuf - outTemp) - (cbuf - inTemp), (float)(cbuf - inTemp) / (float)(wbuf - outTemp));*/ if ((wbuf - outTemp > cbuf - inTemp) || (sliceError > MAX_ERRORS)) // yes that might happen, rarely { #ifndef NDEBUG if (sliceError > MAX_ERRORS) { DEBF("sliceError (%i) > MAX_ERRORS (%i)", sliceError, MAX_ERRORS); } #endif /*LOGF("*** slice bigger than before !! (type: %s code: %i in : %i out : %i diff : %i)", (picture_coding_type == I_TYPE ? "I_TYPE" : (picture_coding_type == P_TYPE ? "P_TYPE" : "B_TYPE")), ID, cbuf - inTemp, wbuf - outTemp, (wbuf - outTemp) - (cbuf - inTemp));*/ // in this case, we'll just use the original slice ! ac_memcpy(outTemp, inTemp, cbuf - inTemp); wbuf = outTemp + (cbuf - inTemp); // adjust outbytecnt outbytecnt -= (wbuf - outTemp) - (cbuf - inTemp); } #ifdef STAT switch(picture_coding_type) { case I_TYPE: ori_i += cbuf - inTemp; new_i += (wbuf - outTemp > cbuf - inTemp) ? (cbuf - inTemp) : (wbuf - outTemp); cnt_i ++; break; case P_TYPE: ori_p += cbuf - inTemp; new_p += (wbuf - outTemp > cbuf - inTemp) ? (cbuf - inTemp) : (wbuf - outTemp); cnt_p ++; break; case B_TYPE: ori_b += cbuf - inTemp; new_b += (wbuf - outTemp > cbuf - inTemp) ? (cbuf - inTemp) : (wbuf - outTemp); cnt_b ++; break; default: assert(0); break; } #endif } } #ifndef NDEBUG if ((ID >= 0x01) && (ID <= 0xAF) && (!validPicHeader || !validSeqHeader || !validExtHeader)) { if (!validPicHeader) DEBF("missing pic header (%02X)", ID); if (!validSeqHeader) DEBF("missing seq header (%02X)", ID); if (!validExtHeader) DEBF("missing ext header (%02X)", ID); } #endif if (wbuf - owbuf > MIN_WRITE) { WRITE } } // keeps gcc happy return 0; } #include "libtc/static_xio.h"