// // C++ Implementation: k9requant // // Description: // // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #include "k9requant.h" #include "getvlc.h" #include "putvlc.h" #include "ac.h" // 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 THREAD // #define LOG_RATE_CONTROL // some stats // #define DEMO // demo mode // #define STAT // print stats on exit // #define USE_FD // use 2 lasts args for input/output paths #define NDEBUG // turns off asserts #define REMOVE_BYTE_STUFFING // removes series of 0x00 // #define USE_GLOBAL_REGISTER // assign registers to bit buffers #define MAX_ERRORS 0 // if above copy slice //#define CHANGE_BRIGHTNESS //add a param to command line, changing brightness: _will_not_recompress_, disables max_errors //#define WIN // for windows fixes, use with USE_FD // params: // if not defined, non intra block in p frames are requantised // if defined and >= 0, we keep coeff. in pos 0..n-1 in scan order // and coeff which would have been non-null if requantised // if defined and < 0 we drop max 1/x coeffs. // experimental, looks better when undefined // #define P_FRAME_NON_INTRA_DROP 8 // params for fact = 1.0, fact = 3.0 and fact = 10.0 // we'll make a linear interpolation between static const int i_factors[3] = { 5, 15, 65 }; static const int p_factors[3] = { 5, 25, 85 }; static const int b_factors[3] = { 25, 45, 105 }; static const double i_min_stresses[3] = { 0.70, 0.40, 0.00 }; static const double p_min_stresses[3] = { 0.60, 0.35, 0.00 }; static const double b_min_stresses[3] = { 0.00, 0.00, 0.00 }; // factor up to which alt table will be used // (though alt_table gives better psnr up to factor around ~2.5 // the result is less pleasing to watch than normal table // so this is disabled) static const double max_alt_table = 0.0; // includes #include #include #include #include #include #ifndef USE_FD #include #include #endif // quant table #include "qTable.h" // 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 #ifndef NDEBUG #define DEB(msg) fprintf (stderr, "%s:%d " msg, __FILE__, __LINE__) #define DEBF(format, args...) fprintf (stderr, "%s:%d " format, __FILE__, __LINE__, args) #else #define DEB(msg) #ifdef WIN #define DEBF(format, args) #else #define DEBF(format, args...) #endif #endif #ifndef THREAD #define LOG(msg) fprintf (stderr, msg) #ifdef WIN #define LOGF(format, arg1) fprintf (stderr, format, arg1) #else #define LOGF(format, args...) fprintf (stderr, format, args) #endif #endif /*#define MOV_READ \ mloka1 = rbuf - cbuf; if (mloka1) memmove(orbuf, cbuf, mloka1);\ cbuf = rbuf = orbuf; rbuf += mloka1; */ #ifdef STAT #define RETURN \ assert(rbuf >= cbuf);\ mloka1 = rbuf - cbuf;\ if (mloka1) { COPY(mloka1); }\ WRITE \ free(orbuf); \ free(owbuf); \ \ LOG("Stats:\n");\ \ LOGF("Wanted fact_x: %.1f\n", fact_x);\ \ LOGF("cnt_i: %.0f ", (float)cnt_i); \ if (cnt_i) LOGF("ori_i: %.0f new_i: %.0f fact_i: %.1f\n", (float)ori_i, (float)new_i, (float)ori_i/(float)new_i); \ else LOG("\n");\ \ LOGF("cnt_p: %.0f ", (float)cnt_p); \ if (cnt_p) LOGF("ori_p: %.0f new_p: %.0f fact_p: %.1f cnt_p_i: %.0f cnt_p_ni: %.0f propor: %.1f i\n", \ (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 LOG("\n");\ \ LOGF("cnt_b: %.0f ", (float)cnt_b); \ if (cnt_b) LOGF("ori_b: %.0f new_b: %.0f fact_b: %.1f cnt_b_i: %.0f cnt_b_ni: %.0f propor: %.1f i\n", \ (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 LOG("\n");\ \ LOGF("Final fact_x: %.1f\n", (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 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) #ifdef P_FRAME_NON_INTRA_DROP #if (P_FRAME_NON_INTRA_DROP < 0) #undef UPDATE_VAL #define UPDATE_VAL #define SAVE_VAL #define WRITE_VAL \ blk->level = val; \ blk->run = i - li - 1; \ li = i; \ blk++; #else #define SAVE_VAL oval = val; #define WRITE_VAL \ if ((val) || (i < P_FRAME_NON_INTRA_DROP)) \ { \ blk->level = oval; \ blk->run = i - li - 1; \ li = i; \ blk++; \ } #endif #else #define SAVE_VAL #define WRITE_VAL \ if (val) \ { \ blk->level = val; \ blk->run = i - li - 1; \ li = i; \ blk++; \ } #endif #define UPDATE_VAL \ val = curTable[val]; int quantisers[42] = { 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 72, 80, 88, 96, 104, 112 }; 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 }; 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 }; k9requant::k9requant() { cbuf=rbuf=orbuf=wbuf=NULL; quant_table_id = &quant_table_id_data[2048]; rqt_run=false; initvar(); } void k9requant::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); } void k9requant::Refill_bits(void) { assert((rbuf - cbuf) >= 1); inbitbuf |= cbuf[0] << (24 - inbitcnt); inbitcnt += 8; SEEKR(1) } void k9requant::Flush_Bits(uint n) { assert(inbitcnt >= n); inbitbuf <<= n; inbitcnt -= n; assert( (!n) || ((n>0) && !(inbitbuf & 0x1)) ); while (unlikely(inbitcnt < 24)) Refill_bits(); } uint k9requant::Show_Bits(uint n) { return ((unsigned int)inbitbuf) >> (32 - n); } uint k9requant::Get_Bits(uint n) { uint Val = Show_Bits(n); Flush_Bits(n); return Val; } uint k9requant::Copy_Bits(uint n) { uint Val = Get_Bits(n); putbits(Val, n); return Val; } void k9requant::flush_read_buffer() { int i = inbitcnt & 0x7; if (i) { if (inbitbuf >> (32 - i)) { DEBF("illegal inbitbuf: 0x%08X, %i, 0x%02X, %i\n", inbitbuf, inbitcnt, (inbitbuf >> (32 - i)), i); sliceError++; } inbitbuf <<= i; inbitcnt -= i; } SEEKR(-1 * (inbitcnt >> 3)); inbitcnt = 0; } void k9requant::flush_write_buffer() { if (outbitcnt != 8) putbits(0, outbitcnt); } /////---- begin ext mpeg code int k9requant::scale_quant(double quant ) { int iquant; #ifdef DEMO if ((gopCount & 0x7F) < 10) // gop is ~ 0.5 sec, so 5 sec every ~minute (127 * 0.5 = 63.5 sec) { if (q_scale_type) return 112; else return 62; } #endif 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; } int k9requant::increment_quant(int quant) { #ifdef DEMO if ((gopCount & 0x7F) < 10) { if (q_scale_type) return 112; else return 62; } #endif if (q_scale_type) { if (quant < 1 || quant > 112) { DEBF("illegal quant: %d\n", quant); if (quant > 112) quant = 112; else if (quant < 1) quant = 1; DEBF("illegal quant changed to : %d\n", quant); sliceError++; } quant = map_non_linear_mquant[quant] + 1; if (quant > 31) quant = 31; quant = non_linear_mquant_table[quant]; } else { if ((quant & 1) || (quant < 2) || (quant > 62)) { DEBF("illegal quant: %d\n", quant); if (quant & 1) quant--; if (quant > 62) quant = 62; else if (quant < 2) quant = 2; DEBF("illegal quant changed to : %d\n", quant); sliceError++; } quant += 2; if (quant > 62) quant = 62; } return quant; } int k9requant::intmax( int x, int y ) { return x < y ? y : x; } int k9requant::intmin( int x, int y ) { return x < y ? x : y; } int k9requant::getNewQuant(int curQuant, int intra) { #ifdef CHANGE_BRIGHTNESS return curQuant; #else int mquant = 0; double cStress; switch (picture_coding_type) { case I_TYPE: cStress = (stress_factor - i_min_stress) / (1.0 - i_min_stress); mquant = intmax(scale_quant(curQuant + i_factor*cStress), increment_quant(curQuant)); break; case P_TYPE: cStress = (stress_factor - p_min_stress) / (1.0 - p_min_stress); if (intra) // since it might be used as a ref, treat it as an I frame block mquant = intmax(scale_quant(curQuant + i_factor*cStress), increment_quant(curQuant)); else mquant = intmax(scale_quant(curQuant + p_factor*cStress), increment_quant(curQuant)); break; case B_TYPE: cStress = (stress_factor - b_min_stress) / (1.0 - b_min_stress); mquant = intmax(scale_quant(curQuant + b_factor*cStress), increment_quant(curQuant)); break; default: assert(0); break; } assert(mquant >= curQuant); return mquant; #endif } int k9requant::isNotEmpty(RunLevel *blk) { return (blk->level); } // return != 0 if error int k9requant::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\n", run); sliceError++; return 1; } if(level==0 || level>2047) { DEBF("illegal level: %d\n", 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 int k9requant::putACfirst(int run, int val) { if (run==0 && (val==1 || val==-1)) { putbits(2|((val<0) ? 1 : 0), 2); return 0; } else return putAC(run,val,0); } void k9requant::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); } void k9requant::putcbp(int cbp) { assert(cbp > 0 && cbp < 64); putbits(cbptable[cbp].code,cbptable[cbp].len); } void k9requant::putmbtype(int mb_type) { putbits(mbtypetab[picture_coding_type-1][mb_type].code, mbtypetab[picture_coding_type-1][mb_type].len); } int k9requant::get_macroblock_modes () { 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; } } int k9requant::get_quantizer_scale () { 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\n", 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; } void k9requant::get_motion_delta (const int f_code) { #define bit_buf (inbitbuf) const MVtab * tab; if (bit_buf & 0x80000000) { COPYBITS (bit_buf, bits, 1); return; } else if (bit_buf >= 0x0c000000) { tab = MV_4 + UBITS (bit_buf, 4); COPYBITS (bit_buf, bits, tab->len + 1); if (f_code) COPYBITS (bit_buf, bits, f_code); return; } else { tab = MV_10 + UBITS (bit_buf, 10); COPYBITS (bit_buf, bits, tab->len + 1); if (f_code) COPYBITS (bit_buf, bits, f_code); return; } } void k9requant::get_dmv () { const DMVtab * tab; tab = DMV_2 + UBITS (bit_buf, 2); COPYBITS (bit_buf, bits, tab->len); return; } int k9requant::get_coded_block_pattern () { #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; } } int k9requant::get_luma_dc_dct_diff () { #define bit_buf (inbitbuf) #ifdef CHANGE_BRIGHTNESS #define DOBITS(x, y, z) DUMPBITS(x, y, z) #else #define DOBITS(x, y, z) COPYBITS(x, y, z) #endif 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) { DOBITS (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); DOBITS (bit_buf, bits, size); return dc_diff; } else { DOBITS (bit_buf, bits, 3); return 0; } } else { tab = DC_long + (UBITS (bit_buf, 9) - 0x1e0); size = tab->size; DOBITS (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); DOBITS (bit_buf, bits, size); return dc_diff; } } int k9requant::get_chroma_dc_dct_diff () { #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; } } void k9requant::get_intra_block_B14 () { #define bit_buf (inbitbuf) 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; val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1); UPDATE_VAL if (val) { if (putAC(i - li - 1, val, 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) { sliceError++; break; /* illegal, check needed to avoid buffer overflow */ } DUMPBITS (bit_buf, bits, 12); val = SBITS (bit_buf, 12); UPDATE_VAL if (val) { if (putAC(i - li - 1, val, 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; } sliceError++; break; /* illegal, check needed to avoid buffer overflow */ } COPYBITS (bit_buf, bits, 2); /* end of block code */ } void k9requant::get_intra_block_B15 () { #define bit_buf (inbitbuf) 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; val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1); UPDATE_VAL if (val) { if (putAC(i - li - 1, val, 1)) break; li = i; } DUMPBITS (bit_buf, bits, 1); continue; } else { if (i >= 128) break; /* end of block */ i += (UBITS (bit_buf, 12) & 0x3F) - 64; if (i >= 64) { sliceError++; break; /* illegal, check against buffer overflow */ } DUMPBITS (bit_buf, bits, 12); val = SBITS (bit_buf, 12); UPDATE_VAL if (val) { if (putAC(i - li - 1, val, 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; } sliceError++; break; /* illegal, check needed to avoid buffer overflow */ } COPYBITS (bit_buf, bits, 4); /* end of block code */ } int k9requant::get_non_intra_block_rq (RunLevel *blk) { #define bit_buf (inbitbuf) //int q = quantizer_scale; //int 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; val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1); UPDATE_VAL if (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) { sliceError++; break; /* illegal, check needed to avoid buffer overflow */ } DUMPBITS (bit_buf, bits, 12); val = SBITS (bit_buf, 12); UPDATE_VAL if (val) { 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; } sliceError++; break; /* illegal, check needed to avoid buffer overflow */ } DUMPBITS (bit_buf, bits, 2); /* dump end of block code */ blk->level = 0; return i; } int k9requant::get_non_intra_block_sav (RunLevel *blk, int cc) { #define bit_buf (inbitbuf) int i, li; int val; const DCTtab * tab; #ifdef P_FRAME_NON_INTRA_DROP #if (P_FRAME_NON_INTRA_DROP < 0) RunLevel *oblk = blk; #else int oval; #endif #endif 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); SAVE_VAL if (li == -1) { if (abs(val) < abs(mb_sav_lev)) { mb_sav_c = cc; mb_sav_lev = val; mb_sav_run = i - li - 1; } } UPDATE_VAL WRITE_VAL 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) { sliceError++; break; /* illegal, check needed to avoid buffer overflow */ } DUMPBITS (bit_buf, bits, 12); val = SBITS (bit_buf, 12); SAVE_VAL if (li == -1) { if (abs(val) < abs(mb_sav_lev)) { mb_sav_c = cc; mb_sav_lev = val; mb_sav_run = i - li - 1; } } UPDATE_VAL WRITE_VAL 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; } sliceError++; break; /* illegal, check needed to avoid buffer overflow */ } DUMPBITS (bit_buf, bits, 2); /* dump end of block code */ #ifdef P_FRAME_NON_INTRA_DROP #if (P_FRAME_NON_INTRA_DROP < 0) blk -= (int)((blk - oblk) * (stress_factor / P_FRAME_NON_INTRA_DROP)); #ifdef DEMO if ((gopCount & 0x7F) < 10) blk = oblk; #endif #endif #endif blk->level = 0; return i; } #ifdef P_FRAME_NON_INTRA_DROP int k9requant::get_non_intra_block_drop (RunLevel *blk, int cc) { #define bit_buf (inbitbuf) int i, li; int val; const DCTtab * tab; #if (P_FRAME_NON_INTRA_DROP < 0) RunLevel *oblk = blk; #else int oval; #endif 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); SAVE_VAL UPDATE_VAL WRITE_VAL 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) { sliceError++; break; /* illegal, check needed to avoid buffer overflow */ } DUMPBITS (bit_buf, bits, 12); val = SBITS (bit_buf, 12); SAVE_VAL UPDATE_VAL WRITE_VAL 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; } sliceError++; break; /* illegal, check needed to avoid buffer overflow */ } DUMPBITS (bit_buf, bits, 2); /* dump end of block code */ #if (P_FRAME_NON_INTRA_DROP < 0) blk -= (int)((blk - oblk) * (stress_factor / P_FRAME_NON_INTRA_DROP)); #ifdef DEMO if ((gopCount & 0x7F) < 10) blk = oblk; #endif #endif blk->level = 0; return i; } #endif #ifdef CHANGE_BRIGHTNESS void k9requant::putDC(const sVLCtable *tab, int val) { int absval, size; absval = abs(val); size = 0; while (absval) { absval >>= 1; size++; } putbits(tab[size].code,tab[size].len); if (size!=0) { if (val>=0) absval = val; else absval = val + (1< (255 << intra_dc_precision)) val = 255 << intra_dc_precision; else if (val < 0) val = 0; bri = val - (128 << intra_dc_precision); new_dc_pred = val; dc_reset = 0; } else { val = bri + old_dc_pred; old_dc_pred = val; val += delta_bright << intra_dc_precision; if (val > (255 << intra_dc_precision)) val = 255 << intra_dc_precision; else if (val < 0) val = 0; bri = val - new_dc_pred; new_dc_pred = val; } putDC(DClumtab, bri); } #else if (cc == 0) get_luma_dc_dct_diff (); #endif else get_chroma_dc_dct_diff (); if (intra_vlc_format) get_intra_block_B15 (); else get_intra_block_B14 (); } void k9requant::slice_non_intra_DCT (int cur_block) { #ifdef P_FRAME_NON_INTRA_DROP if (picture_coding_type == P_TYPE) { if ((h_offset == 0) || (h_offset == horizontal_size_value - 16)) get_non_intra_block_sav(block[cur_block], cur_block); else get_non_intra_block_drop(block[cur_block], cur_block); } else get_non_intra_block_rq(block[cur_block]); #else if ((picture_coding_type == P_TYPE) && ((h_offset == 0) || (h_offset == horizontal_size_value - 16))) get_non_intra_block_sav(block[cur_block], cur_block); else get_non_intra_block_rq(block[cur_block]); #endif } void k9requant::motion_fr_frame ( uint f_code[2] ) { get_motion_delta (f_code[0]); get_motion_delta (f_code[1]); } void k9requant::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]); } void k9requant::motion_fr_dmv ( uint f_code[2] ) { get_motion_delta (f_code[0]); get_dmv (); get_motion_delta (f_code[1]); get_dmv (); } void k9requant::motion_fr_conceal ( ) { get_motion_delta (f_code[0][0]); get_motion_delta (f_code[0][1]); COPYBITS (bit_buf, bits, 1); } void k9requant::motion_fi_field ( uint f_code[2] ) { COPYBITS (bit_buf, bits, 1); get_motion_delta (f_code[0]); get_motion_delta (f_code[1]); } void k9requant::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]); } void k9requant::motion_fi_dmv ( uint f_code[2] ) { get_motion_delta (f_code[0]); get_dmv (); get_motion_delta (f_code[1]); get_dmv (); } void k9requant::motion_fi_conceal () { COPYBITS (bit_buf, bits, 1); get_motion_delta (f_code[0][0]); get_motion_delta (f_code[0][1]); COPYBITS (bit_buf, bits, 1); } void k9requant::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; } }*/ if (macroblock_modes & (MACROBLOCK_MOTION_FORWARD | MACROBLOCK_MOTION_BACKWARD)) { if (picture_structure == FRAME_PICTURE) { if (frame_pred_frame_dct == 0) { putbits((macroblock_modes & MOTION_TYPE_MASK) / MOTION_TYPE_BASE, 2); } } else { putbits((macroblock_modes & MOTION_TYPE_MASK) / MOTION_TYPE_BASE, 2); } } if ((picture_structure == FRAME_PICTURE) && (frame_pred_frame_dct == 0) && (macroblock_modes & (MACROBLOCK_INTRA | MACROBLOCK_PATTERN))) { putbits(macroblock_modes & DCT_TYPE_INTERLACED ? 1 : 0, 1); } } void k9requant::put_quantiser(int quantiser) { putbits(q_scale_type ? map_non_linear_mquant[quantiser] : quantiser >> 1, 5); last_coded_scale = quantiser; } void k9requant::putaddrinc(int addrinc) { mb_out += addrinc; //LOGF("mb_out: %i\n", mb_out); if (mb_out > (horizontal_size_value >> 4)) { sliceError++; //LOGF("mb_out: %i, hsv: %i, curo: %i\n", mb_out, horizontal_size_value, (int)outbytecnt + (wbuf - owbuf)); } while (addrinc>33) { putbits(0x08,11); /* macroblock_escape */ addrinc-= 33; } assert( addrinc >= 1 && addrinc <= 33 ); putbits(addrinctab[addrinc-1].code,addrinctab[addrinc-1].len); } int k9requant::slice_init (int code) { #define bit_buf (inbitbuf) int offset; const MBAtab * mba; mb_out = 0; v_offset = (code - 1) * 16; quantizer_scale = get_quantizer_scale (); new_quantizer_scale = getNewQuant(quantizer_scale, 0); put_quantiser(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; DUMPBITS (bit_buf, bits, 11); continue; default: /* error */ sliceError++; return 1; } } mb_add = offset + mba->mba + 1; mb_skip = 0; COPYBITS (bit_buf, bits, 1); DUMPBITS(bit_buf, bits, mba->len); 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; } void k9requant::mpeg2_slice ( const int code ) { #define bit_buf (inbitbuf) #ifdef CHANGE_BRIGHTNESS dc_reset = 1; #endif 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 (); 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 new_quantizer_scale = getNewQuant(quantizer_scale, 1); if (last_coded_scale == new_quantizer_scale) macroblock_modes &= 0xFFFFFFEF; // remove MACROBLOCK_QUANT else macroblock_modes |= MACROBLOCK_QUANT; //add MACROBLOCK_QUANT putaddrinc(mb_add + mb_skip); mb_skip = 0; putmbdata(macroblock_modes); if (macroblock_modes & MACROBLOCK_QUANT) put_quantiser(new_quantizer_scale); if (concealment_motion_vectors) { if (picture_structure == FRAME_PICTURE) motion_fr_conceal (); else motion_fi_conceal (); } curTable = quant_tables[quant_equ[quantizer_scale]][quant_equ[new_quantizer_scale]]; if (!curTable) { /*DEBF("Inv. curTable: qs: %i nqs: %i qe_qs: %i qe_nqs: %i\n", quantizer_scale, new_quantizer_scale, quant_equ[quantizer_scale], quant_equ[new_quantizer_scale]);*/ curTable = quant_table_id; } 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, *o_wbuf; uint32 n_outbitcnt, n_outbitbuf, o_outbitcnt, o_outbitbuf; #ifdef CHANGE_BRIGHTNESS dc_reset = 1; #endif #define PUSH_BIT_IO \ o_owbuf = owbuf; o_wbuf = wbuf; \ o_outbitcnt = outbitcnt; o_outbitbuf = outbitbuf; \ owbuf = wbuf = n_owbuf; \ outbitcnt = BITS_IN_BUF; outbitbuf = 0; #define POP_BIT_IO \ n_wbuf = wbuf; \ n_outbitcnt = outbitcnt; n_outbitbuf = outbitbuf; \ owbuf = o_owbuf; wbuf = o_wbuf; \ outbitcnt = o_outbitcnt; outbitbuf = o_outbitbuf; PUSH_BIT_IO 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; } POP_BIT_IO // 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 new_quantizer_scale = getNewQuant(quantizer_scale, 0); if (macroblock_modes & MACROBLOCK_PATTERN) { int coded_block_pattern = get_coded_block_pattern (); mb_sav_lev = 0xFFFF; curTable = quant_tables[quant_equ[quantizer_scale]][quant_equ[new_quantizer_scale]]; if (!curTable) { /*DEBF("Inv. curTable: qs: %i nqs: %i qe_qs: %i qe_nqs: %i\n", quantizer_scale, new_quantizer_scale, quant_equ[quantizer_scale], quant_equ[new_quantizer_scale]);*/ curTable = quant_table_id; } if (coded_block_pattern & 0x20) { slice_non_intra_DCT(0); if (isNotEmpty(block[0])) new_coded_block_pattern |= 0x20; } if (coded_block_pattern & 0x10) { slice_non_intra_DCT(1); if (isNotEmpty(block[1])) new_coded_block_pattern |= 0x10; } if (coded_block_pattern & 0x08) { slice_non_intra_DCT(2); if (isNotEmpty(block[2])) new_coded_block_pattern |= 0x08; } if (coded_block_pattern & 0x04) { slice_non_intra_DCT(3); if (isNotEmpty(block[3])) new_coded_block_pattern |= 0x04; } if (coded_block_pattern & 0x02) { slice_non_intra_DCT(4); if (isNotEmpty(block[4])) new_coded_block_pattern |= 0x02; } if (coded_block_pattern & 0x01) { slice_non_intra_DCT(5); if (isNotEmpty(block[5])) new_coded_block_pattern |= 0x01; } #ifdef P_FRAME_NON_INTRA_DROP if (picture_coding_type == P_TYPE) new_quantizer_scale = quantizer_scale; #endif if (!new_coded_block_pattern) { macroblock_modes &= 0xFFFFFFED; // remove MACROBLOCK_PATTERN and MACROBLOCK_QUANT flag if ( (picture_coding_type == P_TYPE) && !(macroblock_modes & MACROBLOCK_MOTION_FORWARD)) { assert(n_wbuf == n_owbuf); assert(n_outbitcnt == BITS_IN_BUF); if ((h_offset == 0) || (h_offset == horizontal_size_value - 16)) // can't skip last mb { // we can't transmit mv (0,0) since PMV could be different than 0 for last block // so we transmit the single smallest coeff. instead unrequantised // anyway this is likely to take no more bit than transmiting a null mv.... assert((mb_sav_lev) && (mb_sav_lev != 0xFFFF)); new_coded_block_pattern = 1 << (5 - mb_sav_c); macroblock_modes |= MACROBLOCK_PATTERN; new_quantizer_scale = quantizer_scale; block[mb_sav_c][0].run = mb_sav_run; block[mb_sav_c][0].level = mb_sav_lev; block[mb_sav_c][1].run = 0; block[mb_sav_c][1].level = 0; } else { mb_skip += mb_add; goto skip_mb; } } } } 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) ); putaddrinc(mb_add + mb_skip); mb_skip = 0; putmbdata(macroblock_modes); if (macroblock_modes & MACROBLOCK_QUANT) put_quantiser(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]); } } skip_mb: 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; DUMPBITS (bit_buf, bits, 11); continue; default: /* end of slice, or error */ //LOGF("hoffset: %i, hsv: %i, curo: %i\n", h_offset, horizontal_size_value, (int)outbytecnt + (wbuf - owbuf)); if (h_offset != 0) sliceError++; return; } } DUMPBITS (bit_buf, bits, mba->len); //PPP mba_inc += mba->mba; mb_add = mba_inc + 1; #ifdef CHANGE_BRIGHTNESS if (mba_inc) dc_reset = 1; #endif if (mba_inc) do { NEXT_MACROBLOCK; } while (--mba_inc); } } /////---- end ext mpeg code void k9requant::run () { uint8 ID, found; int64 greedyFactor, greedyFactor2; int i; #ifdef DEMO gopCount = 0; #endif #ifdef LOG_RATE_CONTROL LOG_FILE = fopen("Logfile.txt", "w"); #endif #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 #ifdef USE_FD if (argc < 3) { USAGE } ifd = fopen(argv[argc - 2], "rb"); ofd = fopen(argv[argc - 1], "wb"); if (!ifd) { LOGF("Bad input path! (%s)\n", argv[argc - 2]); return 2; } if (!ofd) { LOGF("Bad output path! (%s)\n", argv[argc - 1]); return 2; } argc -= 2; #endif #ifndef THREAD rbuf = cbuf = orbuf = malloc(BUF_SIZE); wbuf = owbuf = malloc(BUF_SIZE); inbytecnt = outbytecnt = 0; eof = 0; #endif validPicHeader = 0; validSeqHeader = 0; validExtHeader = 0; #ifndef THREAD // argument parsing #ifdef CHANGE_BRIGHTNESS if (argc < 5) { USAGE } delta_bright = atoi(argv[4]); #else if (argc < 4) { USAGE } #endif fact_x = atof(argv[1]); sscanf(argv[3], "%lld", &orim2vsize); #endif #ifdef THREAD orim2vsize=rqt_visize; fact_x = rqt_fact; #endif greedyFactor = orim2vsize / 100; greedyFactor2 = orim2vsize / 50; #ifndef THREAD if (fact_x <= 1.0) { unsigned char buf[4096]; while(1) { int i = read(0, buf, 4096); if (i > 0) write(1, buf, i); else return 0; } } #endif if (fact_x > 10.0) fact_x = 10.0; // factor and stresses setting initRequant(); // fill quant table // id table for (i = -2048; i <= 2047; i++) quant_table_id[i] = i; // other tables for (i = 0; i < 42; i++) { int q = quantisers[i]; int j; for (j = i + 1; j < 42; j++) { int nq = quantisers[j]; int k; short *cTab = quant_tables[quant_equ[q]][quant_equ[nq]]; for (k = -2048; k <= 2047; k++) { int ov = k*q; int t = ov / nq; if (fact_x <= max_alt_table) { int t2, t3; int d, d2, d3; int nv, nv2, nv3; t2 = t + 1; t3 = t - 1; nv = t * nq; nv2 = t2 * nq; nv3 = t3 * nq; d = abs(nv - ov); d2 = abs(nv2 - ov); d3 = abs(nv3 - ov); if (d2 < d) { d = d2; t = t2; } if (d3 < d) t = t3; } if (t > 2047) t = 2047; else if (t < -2048) t = -2048; cTab[k] = t; } } } #ifndef THREAD LOG("M2VRequantiser by Makira.\n"); #ifdef WIN fprintf(stderr, "Using %f as factor, %lld as m2v size.\n", fact_x, orim2vsize); #else LOGF("Using %f as factor, %lld as m2v size.\n", fact_x, orim2vsize); #endif #endif // recoding while(1) { // get next start code prefix found = 0; while (!found) { #ifndef REMOVE_BYTE_STUFFING LOCK(3) #else LOCK(8) if ( (cbuf[7] == 0) && (cbuf[6] == 0) && (cbuf[5] == 0) && (cbuf[4] == 0) && (cbuf[3] == 0) && (cbuf[2] == 0) && (cbuf[1] == 0) && (cbuf[0] == 0) ) { SEEKR(1) } else #endif 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\n", picture_coding_type); validPicHeader = 0; } else { validPicHeader = 1; cbuf[1] |= 0x7; cbuf[2] = 0xFF; cbuf[3] |= 0xF8; // vbv_delay is now 0xFFFF } validExtHeader = 0; 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\n", horizontal_size_value, vertical_size_value); validSeqHeader = 0; } else validSeqHeader = 1; validPicHeader = 0; validExtHeader = 0; 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\n", 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) #ifdef DEMO gopCount++; #endif } else if ((ID >= 0x01) && (ID <= 0xAF) && validPicHeader && validSeqHeader && validExtHeader) // slice { uint8 *outTemp = wbuf, *inTemp = cbuf; int64 threshold; bytediff = (outbytecnt + (wbuf - owbuf)) - ((inbytecnt - (rbuf - cbuf)) / fact_x); if (inbytecnt < greedyFactor2) threshold = inbytecnt >> 1; else if (orim2vsize - inbytecnt < greedyFactor2) threshold = (orim2vsize - inbytecnt) >> 1; else threshold = greedyFactor; if (threshold < 1024) threshold = 1024; stress_factor = (float)(bytediff + threshold) / (float)(threshold << 1); if (stress_factor > 1.0f) stress_factor = 1.0f; else if (stress_factor < 0.0f) stress_factor = 0.0f; #ifdef LOG_RATE_CONTROL /*fprintf(LOG_FILE, "%f%%: Requested: %f Current: %f Delta: %lld Threshold: %f Stress: %f\n", (float)(100.0f*inbytecnt)/orim2vsize, // percent (float)fact_x, // requested (float)(inbytecnt - (rbuf - cbuf))/(float)(outbytecnt + (wbuf - owbuf)), // current (long long)bytediff, // delta (float)threshold, // threshold stress_factor // Stress );*/ fprintf(LOG_FILE, "inb: %.0f inb_c: %.0f oub: %.0f oub_c: %.0f cur: %.3f dif: %.0f thr: %.0f str: %.03f\n", (float)inbytecnt, (float)(inbytecnt - (rbuf - cbuf)), (float)outbytecnt, (float)(outbytecnt + (wbuf - owbuf)), (float)(inbytecnt - (rbuf - cbuf))/(float)(outbytecnt + (wbuf - owbuf)), (float)bytediff, (float)threshold, (float)stress_factor ); #endif #ifndef CHANGE_BRIGHTNESS if ( ((picture_coding_type == I_TYPE) && ( stress_factor > i_min_stress)) || ((picture_coding_type == P_TYPE) && ( stress_factor > p_min_stress)) || ((picture_coding_type == B_TYPE) && ( stress_factor > b_min_stress)) #ifdef DEMO || ((gopCount & 0x7F) < 10) #endif ) #endif { // 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 #ifndef CHANGE_BRIGHTNESS 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)\n", sliceError, MAX_ERRORS); } #endif // in this case, we'll just use the original slice ! tc_memcpy(outTemp, inTemp, cbuf - inTemp); wbuf = outTemp + (cbuf - inTemp); // adjust outbytecnt outbytecnt -= (wbuf - outTemp) - (cbuf - inTemp); } #endif #ifdef STAT #ifdef LOG_RATE_CONTROL if (picture_coding_type == I_TYPE) fprintf(LOG_FILE, "-I-\n"); #endif 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)\n", ID); if (!validSeqHeader) DEBF("missing seq header (%02X)\n", ID); if (!validExtHeader) DEBF("missing ext header (%02X)\n", ID); } #endif if (rbuf - orbuf > MAX_READ) { MOV_READ } if (wbuf - owbuf > MIN_WRITE) { WRITE } } #ifdef LOG_RATE_CONTROL fclose(LOG_FILE); #endif rqt_run=false; // keeps gcc happy return ; } void k9requant::initvar() { cbuf = NULL; rbuf = NULL; wbuf = NULL; orbuf = NULL; owbuf = NULL; inbitcnt = outbitcnt = 0; inbitbuf = outbitbuf = 0; inbytecnt = outbytecnt = 0; fact_x = 0; mloka1 = mloka2 = eof = 0; orim2vsize = 0; bytediff = 0; stress_factor = 0; i_factor = 0; p_factor = 0; b_factor = 0; i_min_stress = 0; p_min_stress = 0; b_min_stress = 0; quant_table_id = &quant_table_id_data[2048]; horizontal_size_value = 0; vertical_size_value = 0; picture_coding_type = 0; memset( f_code,0 , sizeof(f_code)); intra_dc_precision = 0; picture_structure = 0; frame_pred_frame_dct = 0; concealment_motion_vectors = 0; q_scale_type = 0; intra_vlc_format = 0; alternate_scan = 0; validPicHeader = 0; validSeqHeader = 0; validExtHeader = 0; sliceError = 0; quantizer_scale = 0; new_quantizer_scale = 0; last_coded_scale = 0; h_offset = v_offset = 0; mb_skip = mb_add = 0; mb_out = 0; mb_sav_run = mb_sav_lev = mb_sav_c = 0; curTable = NULL; memset( block, 0, sizeof(block)); } void k9requant::initRequant() { int i; if (fact_x <= 1.0) { i_factor = i_factors[0]; p_factor = p_factors[0]; b_factor = b_factors[0]; i_min_stress = i_min_stresses[0]; p_min_stress = p_min_stresses[0]; b_min_stress = b_min_stresses[0]; } else if (fact_x >= 10.0) { i_factor = i_factors[2]; p_factor = p_factors[2]; b_factor = b_factors[2]; i_min_stress = i_min_stresses[2]; p_min_stress = p_min_stresses[2]; b_min_stress = b_min_stresses[2]; } else if (fact_x <= 3.0) // 1.0 .. 3.0 { double inter = (fact_x - 1.0)/(3.0 - 1.0); i_factor = i_factors[0] + inter * (i_factors[1] - i_factors[0]); p_factor = p_factors[0] + inter * (p_factors[1] - p_factors[0]); b_factor = b_factors[0] + inter * (b_factors[1] - b_factors[0]); i_min_stress = i_min_stresses[0] + inter * (i_min_stresses[1] - i_min_stresses[0]); p_min_stress = p_min_stresses[0] + inter * (p_min_stresses[1] - p_min_stresses[0]); b_min_stress = b_min_stresses[0] + inter * (b_min_stresses[1] - b_min_stresses[0]); } else // 3.0 .. 10.0 { double inter = (fact_x - 3.0)/(10.0 - 3.0); i_factor = i_factors[1] + inter * (i_factors[2] - i_factors[1]); p_factor = p_factors[1] + inter * (p_factors[2] - p_factors[1]); b_factor = b_factors[1] + inter * (b_factors[2] - b_factors[1]); i_min_stress = i_min_stresses[1] + inter * (i_min_stresses[2] - i_min_stresses[1]); p_min_stress = p_min_stresses[1] + inter * (p_min_stresses[2] - p_min_stresses[1]); b_min_stress = b_min_stresses[1] + inter * (b_min_stresses[2] - b_min_stresses[1]); } /*LOGF( "i_factor: %i p_factor: %i b_factor: %i\n" "i_min_stress: %.02f p_min_stress: %.02f b_min_stress: %.02f\n", i_factor, p_factor, b_factor, i_min_stress, p_min_stress, b_min_stress);*/ } bool k9requant::lock( int64 x) { if (unlikely ((x) > (rbuf - cbuf))) { if (likely (wbuf)) { TQMutexLocker locker( &mutw ); //mutw.lock(); rqt_wcnt = wbuf - owbuf; condw.wakeAll(); //mutw.unlock(); } //mutr.lock(); TQMutexLocker locker( &mutr ); while (!rqt_rcnt) { condr.wait( &mutr); if (rqt_stop==true) { //mutr.unlock(); return false; } } cbuf = rqt_rptr; //src buffer rbuf =orbuf = cbuf; rbuf += rqt_rcnt + 3; // end of src buffer rqt_rcnt = 0; owbuf = rqt_wptr; // dest buffer inbytecnt = rqt_inbytes; outbytecnt = rqt_outbytes; orim2vsize = rqt_visize; //mutr.unlock(); wbuf = owbuf; if ( fact_x < rqt_fact) { fact_x=rqt_fact; initRequant(); } fact_x=rqt_fact; } return true; }