#include "../libzmpeg3.h" #ifndef __clang__ #ifdef __x86_64__ #define USE_MMX #endif #endif #ifdef USE_MMX #include "mmx.h" #if defined(__x86_64__) #define m_(v) (*(mmx_t*)(v)) #else #define m_(v) (*(char*)(v)) #endif #endif zslice_buffer_t:: slice_buffer_t() { data = new uint8_t[buffer_allocation=4096]; buffer_size = 0; buffer_position = 0; bits_size = 0; bits = 0; } zslice_buffer_t:: ~slice_buffer_t() { delete [] data; } uint8_t *zslice_buffer_t:: expand_buffer(int bfrsz) { long new_allocation = 2*buffer_allocation; uint8_t *new_buffer = new uint8_t[new_allocation]; if( bfrsz > 0 ) memcpy(new_buffer,data,bfrsz); delete [] data; data = new_buffer; buffer_allocation = new_allocation; buffer_size = buffer_allocation-bfrsz-4; return data + bfrsz; } void zslice_buffer_t:: fill_buffer(zbits_t *vstream) { uint8_t *sbp = data; vstream->next_byte_align(); demuxer_t *demux = vstream->demuxer; /* sync stream to zcode and access demuxer */ uint32_t zcode = vstream->show_bits32_noptr(); for( int i=32; i>0; ) *sbp++ = (zcode>>(i-=8)); vstream->reset(); buffer_size = buffer_allocation-(4+4); /* sizeof(zcode)+padding */ /* Read the slice into the buffer including the slice start code */ while( !vstream->eof() ) { if( buffer_size <= 0 ) sbp = expand_buffer(sbp - data); if( (zcode&0xff) != 0 ) { buffer_size -= 3; zcode = (zcode<<8) | (*sbp++ = demux->read_char()); zcode = (zcode<<8) | (*sbp++ = demux->read_char()); } else --buffer_size; zcode = (zcode<<8) | (*sbp++ = demux->read_char()); if( (zcode&0xffffff) == PACKET_START_CODE_PREFIX ) break; } /* finish trailing code as picture start code (0x100) */ *sbp++ = 0; buffer_size = sbp - data; /* reload stream bfr, position to start code */ vstream->reset(zcode); vstream->get_byte_noptr(); } /* limit coefficients to -2048..2047 */ /* move/add 8x8-Block from block[comp] to refframe */ int zslice_decoder_t:: add_block(int comp, int bx, int by, int dct_type, int addflag) { int cc, i, iincr; uint8_t *rfp; short *bp; /* color component index */ cc = (comp < 4) ? 0 : (comp & 1) + 1; if( cc == 0 ) { /* luminance */ if( video->pict_struct == video_t::pics_FRAME_PICTURE ) { if( dct_type ) { /* field DCT coding */ rfp = video->newframe[0] + video->coded_picture_width * (by + ((comp & 2) >> 1)) + bx + ((comp & 1) << 3); iincr = (video->coded_picture_width << 1); } else { /* frame DCT coding */ rfp = video->newframe[0] + video->coded_picture_width * (by + ((comp & 2) << 2)) + bx + ((comp & 1) << 3); iincr = video->coded_picture_width; } } else { /* field picture */ rfp = video->newframe[0] + (video->coded_picture_width << 1) * (by + ((comp & 2) << 2)) + bx + ((comp & 1) << 3); iincr = (video->coded_picture_width << 1); } } else { /* chrominance */ /* scale coordinates */ if( video->chroma_format != video_t::cfmt_444 ) bx >>= 1; if( video->chroma_format == video_t::cfmt_420 ) by >>= 1; if( video->pict_struct == video_t::pics_FRAME_PICTURE ) { if( dct_type && (video->chroma_format != video_t::cfmt_420) ) { /* field DCT coding */ rfp = video->newframe[cc] + video->chrom_width * (by + ((comp & 2) >> 1)) + bx + (comp & 8); iincr = (video->chrom_width << 1); } else { /* frame DCT coding */ rfp = video->newframe[cc] + video->chrom_width * (by + ((comp & 2) << 2)) + bx + (comp & 8); iincr = video->chrom_width; } } else { /* field picture */ rfp = video->newframe[cc] + (video->chrom_width << 1) * (by + ((comp & 2) << 2)) + bx + (comp & 8); iincr = (video->chrom_width << 1); } } bp = block[comp]; if( addflag ) { for( i=0; i<8; ++i ) { #ifndef USE_MMX rfp[0] = clip(bp[0] + rfp[0]); rfp[1] = clip(bp[1] + rfp[1]); rfp[2] = clip(bp[2] + rfp[2]); rfp[3] = clip(bp[3] + rfp[3]); rfp[4] = clip(bp[4] + rfp[4]); rfp[5] = clip(bp[5] + rfp[5]); rfp[6] = clip(bp[6] + rfp[6]); rfp[7] = clip(bp[7] + rfp[7]); #else movq_m2r(m_(rfp),mm1); /* rfp[0..7] */ pxor_r2r(mm3,mm3); /* zero */ pxor_r2r(mm4,mm4); /* zero */ movq_m2r(m_(bp+0),mm5); /* bp[0..3] */ movq_r2r(mm1,mm2); /* copy rfp[0..7] */ movq_m2r(m_(bp+4),mm6); /* bp[4..7] */ punpcklbw_r2r(mm3,mm1); /* rfp[0..3] */ punpckhbw_r2r(mm3,mm2); /* rfp[4..7] */ paddsw_r2r(mm5,mm1); /* + bp[0..3] */ paddsw_r2r(mm6,mm2); /* + bp[4..7] */ pcmpgtw_r2r(mm1,mm3); /* 1s to fields < 0 */ pcmpgtw_r2r(mm2,mm4); /* 1s to fields < 0 */ pandn_r2r(mm1,mm3); /* clip <0 = zero */ pandn_r2r(mm2,mm4); /* clip <0 = zero */ packuswb_r2r(mm4,mm3); /* pack/clip >255 = 255 */ movq_r2m(mm3,m_(rfp)); /* store rfp[0..7] */ #endif rfp += iincr; bp += 8; } } else { for( i=0; i<8; ++i ) { #ifndef USE_MMX rfp[0] = clip(bp[0] + 128); rfp[1] = clip(bp[1] + 128); rfp[2] = clip(bp[2] + 128); rfp[3] = clip(bp[3] + 128); rfp[4] = clip(bp[4] + 128); rfp[5] = clip(bp[5] + 128); rfp[6] = clip(bp[6] + 128); rfp[7] = clip(bp[7] + 128); #else static short i128[4] = { 128, 128, 128, 128 }; movq_m2r(m_(i128),mm1); /* 128,,128 */ pxor_r2r(mm3,mm3); /* zero */ pxor_r2r(mm4,mm4); /* zero */ movq_m2r(m_(bp+0),mm5); /* bp[0..3] */ movq_r2r(mm1,mm2); /* 128,,128 */ movq_m2r(m_(bp+4),mm6); /* bp[4..7] */ paddsw_r2r(mm5,mm1); /* + bp[0..3] */ paddsw_r2r(mm6,mm2); /* + bp[4..7] */ pcmpgtw_r2r(mm1,mm3); /* 1s to fields < 0 */ pcmpgtw_r2r(mm2,mm4); /* 1s to fields < 0 */ pandn_r2r(mm1,mm3); /* clip <0 = zero */ pandn_r2r(mm2,mm4); /* clip <0 = zero */ packuswb_r2r(mm4,mm3); /* pack/clip >255 = 255 */ movq_r2m(mm3,m_(rfp)); /* store rfp[0..7] */ #endif rfp+= iincr; bp += 8; } } #ifdef USE_MMX emms(); #endif return 0; } uint8_t zslice_decoder_t:: 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, }; int zslice_decoder_t:: decode_slice() { int comp; int mb_type, cbp, motion_type = 0, dct_type; int macroblock_address, mba_inc, mba_max; int slice_vert_pos_ext; uint32_t zcode; int dc_dct_pred[3]; int mv_count, mv_format, mvscale; int pmv[2][2][2], mv_field_sel[2][2]; int dmv, dmvector[2]; int qs; int stwtype, stwclass; int snr_cbp; int i; /* number of macroblocks per picture */ mba_max = video->mb_width * video->mb_height; /* field picture has half as many macroblocks as frame */ if( video->pict_struct != video_t::pics_FRAME_PICTURE ) mba_max >>= 1; macroblock_address = 0; /* first macroblock in slice is not skipped */ mba_inc = 0; fault = 0; zcode = slice_buffer->get_bits(32); /* decode slice header (may change quant_scale) */ slice_vert_pos_ext = get_slice_hdr(); /* reset all DC coefficient and motion vector predictors */ dc_dct_pred[0] = dc_dct_pred[1] = dc_dct_pred[2] = 0; pmv[0][0][0] = pmv[0][0][1] = pmv[1][0][0] = pmv[1][0][1] = 0; pmv[0][1][0] = pmv[0][1][1] = pmv[1][1][0] = pmv[1][1][1] = 0; for( i=0; !slice_buffer->eob(); ++i ) { if( mba_inc == 0 ) { if( !slice_buffer->show_bits(23) ) break; /* Done */ /* decode macroblock address increment */ mba_inc = get_macroblock_address(); if( fault ) return 1; if( i == 0 ) { /* Get the macroblock_address */ int mline = (slice_vert_pos_ext << 7) + (zcode&0xff) - 1; macroblock_address = mline * video->mb_width + mba_inc - 1; /* first macroblock in slice: not skipped */ mba_inc = 1; } } if( fault ) return 1; if( macroblock_address >= mba_max ) { /* mba_inc points beyond picture dimensions */ //zerr("too many macroblocks in picture\n"); */ return 1; } /* not skipped */ if( mba_inc == 1 ) { macroblock_modes(&mb_type, &stwtype, &stwclass, &motion_type, &mv_count, &mv_format, &dmv, &mvscale, &dct_type); if( fault ) return 1; if( mb_type & mb_QUANT ) { qs = slice_buffer->get_bits(5); if( video->mpeg2 ) quant_scale = video->qscale_type ? non_linear_mquant_table[qs] : (qs << 1); else quant_scale = qs; /* make sure quant_scale is valid */ if( video->scalable_mode == sc_DP ) quant_scale = quant_scale; /*???*/ } /* motion vectors */ /* decode forward motion vectors */ if( (mb_type & mb_FORWARD) || ((mb_type & mb_INTRA) && video->conceal_mv) ) { if( video->mpeg2 ) motion_vectors(pmv, dmvector, mv_field_sel, 0, mv_count, mv_format, video->h_forw_r_size, video->v_forw_r_size, dmv, mvscale); else motion_vector(pmv[0][0], dmvector, video->forw_r_size, video->forw_r_size, 0, 0, video->full_forw); } if( fault ) return 1; /* decode backward motion vectors */ if( mb_type & mb_BACKWARD ) { if( video->mpeg2 ) motion_vectors(pmv, dmvector, mv_field_sel, 1, mv_count, mv_format, video->h_back_r_size, video->v_back_r_size, 0, mvscale); else motion_vector(pmv[0][1], dmvector, video->back_r_size, video->back_r_size, 0, 0, video->full_back); } if( fault ) return 1; /* remove marker_bit */ if( (mb_type & mb_INTRA) && video->conceal_mv ) slice_buffer->flush_bit(); /* macroblock_pattern */ if( mb_type & mb_PATTERN ) { cbp = get_cbp(); if( video->chroma_format == video_t::cfmt_422 ) { /* coded_block_pattern_1 */ cbp = (cbp << 2) | slice_buffer->get_bits(2); } else if( video->chroma_format == video_t::cfmt_444 ) { /* coded_block_pattern_2 */ cbp = (cbp << 6) | slice_buffer->get_bits(6); } } else cbp = (mb_type & mb_INTRA) ? ((1 << video->blk_cnt) - 1) : 0; if( fault ) return 1; /* decode blocks */ clear_block(0, video->blk_cnt); for( comp=0; compblk_cnt; ++comp ) { if( cbp & (1 << (video->blk_cnt-comp-1)) ) { if( mb_type & mb_INTRA ) { if( video->mpeg2 ) get_mpg2_intra_block(comp, dc_dct_pred); else get_intra_block(comp, dc_dct_pred); } else { if( video->mpeg2 ) get_mpg2_inter_block(comp); else get_inter_block(comp); } if( fault ) return 1; } } /* reset intra_dc predictors */ if( !(mb_type & mb_INTRA) ) dc_dct_pred[0] = dc_dct_pred[1] = dc_dct_pred[2] = 0; /* reset motion vector predictors */ if( (mb_type & mb_INTRA) && !video->conceal_mv ) { /* intra mb without concealment motion vectors */ pmv[0][0][0] = pmv[0][0][1] = pmv[1][0][0] = pmv[1][0][1] = 0; pmv[0][1][0] = pmv[0][1][1] = pmv[1][1][0] = pmv[1][1][1] = 0; } if( (video->pict_type == video_t::pic_type_P) && !(mb_type & (mb_FORWARD | mb_INTRA)) ) { /* non-intra mb without forward mv in a P picture */ pmv[0][0][0] = pmv[0][0][1] = pmv[1][0][0] = pmv[1][0][1] = 0; /* derive motion_type */ if( video->pict_struct == video_t::pics_FRAME_PICTURE ) motion_type = mc_FRAME; else { motion_type = mc_FIELD; /* predict from field of same parity */ mv_field_sel[0][0] = video->pict_struct == video_t::pics_BOTTOM_FIELD ? 1 : 0; } } if( stwclass == 4 ) { /* purely spatially predicted macroblock */ pmv[0][0][0] = pmv[0][0][1] = pmv[1][0][0] = pmv[1][0][1] = 0; pmv[0][1][0] = pmv[0][1][1] = pmv[1][1][0] = pmv[1][1][1] = 0; } } else { /* mba_inc!=1: skipped macroblock */ clear_block(0, video->blk_cnt); /* reset intra_dc predictors */ dc_dct_pred[0] = dc_dct_pred[1] = dc_dct_pred[2] = 0; /* reset motion vector predictors */ if( video->pict_type == video_t::pic_type_P ) pmv[0][0][0] = pmv[0][0][1] = pmv[1][0][0] = pmv[1][0][1] = 0; /* derive motion_type */ if( video->pict_struct == video_t::pics_FRAME_PICTURE ) motion_type = mc_FRAME; else { motion_type = mc_FIELD; /* predict from field of same parity */ mv_field_sel[0][0] = mv_field_sel[0][1] = (video->pict_struct == video_t::pics_BOTTOM_FIELD) ? 1 : 0; } /* skipped I are spatial-only predicted, */ /* skipped P and B are temporal-only predicted */ stwtype = video->pict_type == video_t::pic_type_I ? 8 : 0; mb_type &= ~mb_INTRA; /* clear mb_INTRA */ cbp = 0; /* no block data */ } snr_cbp = 0; /* pixel coordinates of top left corner of current macroblock */ int mx = macroblock_address % video->mb_width; int my = macroblock_address / video->mb_width; /* thumbnails */ if( video->thumb && video->pict_type == video_t::pic_type_I ) { uint8_t *ap = video->tdat + 4*my*video->mb_width + 2*mx; uint8_t *bp = ap + 2*video->mb_width; if( (mb_type&mb_INTRA) != 0 ) { *ap = clip(128 + block[0][0]/8); ++ap; *ap = clip(128 + block[1][0]/8); *bp = clip(128 + block[2][0]/8); ++bp; *bp = clip(128 + block[3][0]/8); } else { *ap = clip(*ap + block[0][0]/8); ++ap; *ap = clip(*ap + block[1][0]/8); *bp = clip(*bp + block[2][0]/8); ++bp; *bp = clip(*bp + block[3][0]/8); } } /* skimming */ if( !video->skim ) { int bx = 16*mx, by = 16*my; /* motion compensation */ if( !(mb_type & mb_INTRA) ) video->reconstruct( bx, by, mb_type, motion_type, pmv, mv_field_sel, dmvector, stwtype); /* copy or add block data into picture */ for( comp=0; compblk_cnt; ++comp ) { if( (cbp | snr_cbp) & (1 << (video->blk_cnt-1-comp)) ) { idct_conversion(block[comp]); add_block(comp, bx, by, dct_type, !(mb_type & mb_INTRA) ? 1 : 0); } } } /* advance to next macroblock */ ++macroblock_address; --mba_inc; } return 0; } void zslice_decoder_t:: slice_loop() { while( !done ) { input_lock.lock(); while( !done ) { decode_slice(); video->put_slice_buffer(slice_buffer); if( get_active_slice_buffer() ) break; } } } void *zslice_decoder_t:: the_slice_loop(void *the_slice_decoder) { ((slice_decoder_t *)the_slice_decoder)->slice_loop(); return 0; } zslice_decoder_t:: slice_decoder_t() { owner = pthread_self(); video = 0; slice_buffer = 0; done = 0; input_lock.lock(); pthread_create(&tid,0,the_slice_loop, this); } zslice_decoder_t:: ~slice_decoder_t() { done = 1; input_lock.unlock(); pthread_join(tid, 0); } int zslice_decoder_t:: get_cbp() { int zcode; if( (zcode=slice_buffer->show_bits(9)) >= 128 ) { zcode >>= 4; slice_buffer->flush_bits(CBPtab0[zcode].len); return CBPtab0[zcode].val; } if( zcode >= 8 ) { zcode >>= 1; slice_buffer->flush_bits(CBPtab1[zcode].len); return CBPtab1[zcode].val; } if( zcode < 1 ) { //zerr("invalid coded_block_pattern code\n"); fault = 1; return 0; } slice_buffer->flush_bits(CBPtab2[zcode].len); return CBPtab2[zcode].val; } /* set block to zero */ int zslice_decoder_t:: clear_block(int comp, int size) { sparse[comp] = 1; memset(block[comp], 0, size*sizeof(block[0])); return 0; } int zslice_buffer_t:: get_dc_lum() { int zcode, size, val; zcode = show_bits(5); /* decode length */ if( zcode < 31 ) { size = DClumtab0[zcode].val; flush_bits(DClumtab0[zcode].len); } else { zcode = show_bits(9) - 0x1f0; size = DClumtab1[zcode].val; flush_bits(DClumtab1[zcode].len); } if( size ) { val = get_bits(size); if( (val & (1 << (size-1))) == 0 ) val -= (1 << size)-1; } else val = 0; return val; } int zslice_buffer_t:: get_dc_chrom() { int zcode, size, val; zcode = show_bits(5); /* decode length */ if( zcode < 31 ) { size = DCchromtab0[zcode].val; flush_bits(DCchromtab0[zcode].len); } else { zcode = show_bits(10) - 0x3e0; size = DCchromtab1[zcode].val; flush_bits(DCchromtab1[zcode].len); } if( size ) { val = get_bits(size); if( (val & (1 << (size-1))) == 0 ) val -= (1 << size)-1; } else val = 0; return val; } uint16_t *zslice_decoder_t::DCTlutab[3] = { 0, }; void zslice_decoder_t:: init_lut(uint16_t *&lutbl, DCTtab_t *tabn, DCTtab_t *tab0, DCTtab_t *tab1) { int i = 0; uint16_t *lut = new uint16_t[0x10000]; while( i < 0x0010 ) { lut[i] = 0; ++i; } while( i < 0x0020 ) { lut[i] = lu_pack(&DCTtab6[i - 16]); ++i; } while( i < 0x0040 ) { lut[i] = lu_pack(&DCTtab5[(i >> 1) - 16]); ++i; } while( i < 0x0080 ) { lut[i] = lu_pack(&DCTtab4[(i >> 2) - 16]); ++i; } while( i < 0x0100 ) { lut[i] = lu_pack(&DCTtab3[(i >> 3) - 16]); ++i; } while( i < 0x0200 ) { lut[i] = lu_pack(&DCTtab2[(i >> 4) - 16]); ++i; } while( i < 0x0400 ) { lut[i] = lu_pack( &tab1[(i >> 6) - 8]); ++i; } int tblsz = !tabn ? 0x10000 : 0x4000; while( i < tblsz ) { lut[i] = lu_pack( &tab0[(i >> 8) - 4]); ++i; } while( i <0x10000 ) { lut[i] = lu_pack( &tabn[(i >>12) - 4]); ++i; } lutbl = lut; } void zslice_decoder_t:: init_tables() { if( DCTlutab[0] ) return; init_lut(DCTlutab[0], DCTtabfirst, DCTtab0, DCTtab1); init_lut(DCTlutab[1], DCTtabnext , DCTtab0, DCTtab1); init_lut(DCTlutab[2], 0 , DCTtab0a, DCTtab1a); } /* decode one MPEG-1 coef */ inline int zslice_decoder_t:: get_coef(uint16_t *lut) { int v, s, i = idx; uint16_t zcode = slice_buffer->show_bits(16); uint16_t lu = lut[zcode]; if( !lu ) return fault = 1; int len = lu_len(lu); slice_buffer->flush_bits(len); int run = lu_run(lu); if( run >= 32 ) { /* escape */ if( run == 32 ) return -1; /* end of block */ i += slice_buffer->get_bits(6); if( (v = slice_buffer->get_bits(8)) < 128 ) { s = 0; if( !v ) v = slice_buffer->get_bits(8); } else { if( v == 128 ) v = slice_buffer->get_bits(8); s = 1; v = 256 - v; } } else { i += run; v = lu_level(lu); s = slice_buffer->get_bit(); } if( i >= 64 ) return fault = 1; val = v; sign = s; idx = i; return 0; } /* decode one MPEG-2 coef */ inline int zslice_decoder_t:: get_mpg2_coef(uint16_t *lut) { int v, s, i = idx; uint16_t zcode = slice_buffer->show_bits(16); uint16_t lu = lut[zcode]; if( !lu ) return fault = 1; int len = lu_len(lu); slice_buffer->flush_bits(len); int run = lu_run(lu); if( run >= 32 ) { /* escape */ if( run == 32 ) return -1; /* end of block */ i += slice_buffer->get_bits(6); v = slice_buffer->get_bits(12); if( (v & 2047) == 0 ) return fault = 1; s = (v >= 2048) ? 1 : 0; if( s != 0 ) v = 4096 - v; } else { i += run; v = lu_level(lu); s = slice_buffer->get_bit(); } if( i >= 64 ) return fault = 1; val = v; sign = s; idx = i; return 0; } /* decode one intra coded MPEG-1 block */ void zslice_decoder_t:: get_intra_block(int comp, int dc_dct_pred[]) { int dc_coef = /* decode DC coefficients */ comp < 4 ? (dc_dct_pred[0] += slice_buffer->get_dc_lum()) : comp == 4 ? (dc_dct_pred[1] += slice_buffer->get_dc_chrom()) : (dc_dct_pred[2] += slice_buffer->get_dc_chrom()) ; short *bp = block[comp]; bp[0] = dc_coef << 3; /* decode AC coefficients */ int *qmat = video->intra_quantizer_matrix; int j = 0; idx = 1; while( !get_coef(DCTlutab[1]) ) { j = video->zigzag_scan_table[idx++]; int v = (((val * quant_scale*qmat[j])>>3)-1) | 1; bp[j] = sign ? -v : v; } if( j > 0 ) /* not a sparse matrix ! */ sparse[comp] = 0; } /* decode one intra coded MPEG-2 block */ void zslice_decoder_t:: get_mpg2_intra_block(int comp, int dc_dct_pred[]) { int *qmat = (comp < 4 || video->chroma_format == video_t::cfmt_420) ? video->intra_quantizer_matrix : video->chroma_intra_quantizer_matrix; int dc_coef = /* decode DC coefficients */ comp < 4 ? (dc_dct_pred[0] += slice_buffer->get_dc_lum()) : !(comp&1) ? (dc_dct_pred[1] += slice_buffer->get_dc_chrom()) : (dc_dct_pred[2] += slice_buffer->get_dc_chrom()) ; /* with data partitioning, data always goes to base layer */ short *bp = block[comp]; bp[0] = dc_coef << (3 - video->dc_prec); uint8_t *scan_table = video->altscan ? video->alternate_scan_table : video->zigzag_scan_table; uint16_t *lutbl = !video->intravlc ? DCTlutab[1] : DCTlutab[2]; int j = 0; idx = 1; while( !get_mpg2_coef(lutbl) ) { /* decode AC coefficients */ j = scan_table[idx++]; int v = (val * quant_scale*qmat[j]) >> 4; bp[j] = sign ? -v : v; } if( j > 0 ) /* not a sparse matrix ! */ sparse[comp] = 0; } /* decode one non-intra coded MPEG-1 block */ void zslice_decoder_t:: get_inter_block(int comp) { short *bp = block[comp]; idx = 0; if( get_coef(DCTlutab[0])) return; int j = video->zigzag_scan_table[idx++]; int *qmat = video->non_intra_quantizer_matrix; int v = (((((val<<1) + 1) * quant_scale*qmat[j])>>4)-1) | 1; bp[j] = sign ? -v : v; /* decode AC coefficients */ while( !get_coef(DCTlutab[1]) ) { j = video->zigzag_scan_table[idx++]; v = (((((val<<1) + 1) * quant_scale*qmat[j])>>4)-1) | 1; bp[j] = sign ? -v : v; } if( j > 0 ) /* not a sparse matrix ! */ sparse[comp] = 0; } /* decode one non-intra coded MPEG-2 block */ void zslice_decoder_t:: get_mpg2_inter_block(int comp) { /* with data partitioning, data always goes to base layer */ short *bp = block[comp]; int *qmat = (comp < 4 || video->chroma_format == video_t::cfmt_420) ? video->non_intra_quantizer_matrix : video->chroma_non_intra_quantizer_matrix; uint8_t *scan_table = video->altscan ? video->alternate_scan_table : video->zigzag_scan_table; idx = 0; if( get_mpg2_coef(DCTlutab[0]) ) return; int j = scan_table[idx++]; int v = (((val << 1)+1) * quant_scale*qmat[j]) >> 5; bp[j] = sign ? -v : v ; /* decode AC coefficients */ while( !get_mpg2_coef(DCTlutab[1]) ) { j = scan_table[idx++]; int v = (((val << 1)+1) * quant_scale*qmat[j]) >> 5; bp[j] = sign ? -v : v ; } if( j > 0 ) /* not a sparse matrix ! */ sparse[comp] = 0; } void zmpeg3_t:: decode_slice(zslice_buffer_t *buffer) { decoder_lock.lock(); if( avail_slice_decoders ) { zslice_decoder_t *decoder = avail_slice_decoders; avail_slice_decoders = decoder->next; decoder->slice_buffer = buffer; decoder->video = buffer->video; if( !decoder_active_locked++ ) decoder_active.lock(); decoder->input_lock.unlock(); } else { buffer->next = active_slice_buffers; active_slice_buffers = buffer; } decoder_lock.unlock(); } int zslice_decoder_t:: get_active_slice_buffer() { int result; src->decoder_lock.lock(); zslice_buffer_t *buffer = src->active_slice_buffers; if( !buffer ) { next = src->avail_slice_decoders; src->avail_slice_decoders = this; if( !--src->decoder_active_locked ) src->decoder_active.unlock(); slice_buffer = 0; video = 0; result = 1; } else { src->active_slice_buffers = buffer->next; slice_buffer = buffer; video = buffer->video; result = 0; } src->decoder_lock.unlock(); return result; } void zmpeg3_t:: allocate_slice_decoders() { if( slice_decoders ) return; int count = cpus; if( count > MAX_CPUS ) count = MAX_CPUS; slice_decoders = new slice_decoder_t[count]; slice_decoder_t *decoder = &slice_decoders[0]; avail_slice_decoders = 0; for( int i=count; --i>=0; ++decoder ) { decoder->src = this; decoder->next = avail_slice_decoders; avail_slice_decoders = decoder; } total_slice_decoders = count; } void zmpeg3_t:: delete_slice_decoders() { if( !slice_decoders ) return; delete [] slice_decoders; slice_decoders = 0; total_slice_decoders = 0; } void zmpeg3_t:: reallocate_slice_decoders() { decoder_active.lock(); decoder_active.unlock(); decoder_lock.lock(); if( !decoder_active_locked ) { delete_slice_decoders(); allocate_slice_decoders(); } decoder_lock.unlock(); } void zvideo_t:: allocate_slice_buffers() { if( slice_buffers ) return; int count = 2*src->cpus; if( count > 2*MAX_CPUS ) count = 2*MAX_CPUS; slice_buffers = new slice_buffer_t[count]; slice_buffer_t *buffer = &slice_buffers[0]; avail_slice_buffers = 0; for( int i=count; --i>=0; ++buffer ) { buffer->next = avail_slice_buffers; avail_slice_buffers = buffer; } total_slice_buffers = count; } void zvideo_t:: delete_slice_buffers() { if( !slice_buffers ) return; delete [] slice_buffers; slice_buffers = 0; total_slice_buffers = 0; } void zvideo_t:: reallocate_slice_buffers() { slice_active.lock(); slice_active.unlock(); slice_lock.lock(); if( !slice_active_locked ) { delete_slice_buffers(); allocate_slice_buffers(); } slice_lock.unlock(); }