/* * This source handles parsing and supervises decoding of the blocks and * passes the decoded data to the idct. */ #define NO_SANITY_CHECKS #include "video.h" #include "proto.h" #include "decoders.h" #define static /* External declarations. */ extern int zigzag_direct[]; /* *-------------------------------------------------------------- * * ParseReconBlock -- * * Parse values for block structure from bitstream. * n is an indication of the position of the block within * the macroblock (i.e. 0-5) and indicates the type of * block (i.e. luminance or chrominance). Reconstructs * coefficients from values parsed and puts in * block.dct_recon array in vid stream structure. * sparseFlag is set when the block contains only one * coeffictient and is used by the IDCT. * * Results: * * * Side effects: * Bit stream irreversibly parsed. * *-------------------------------------------------------------- */ #define DCT_recon blockPtr->dct_recon #define DCT_dc_y_past blockPtr->dct_dc_y_past #define DCT_dc_cr_past blockPtr->dct_dc_cr_past #define DCT_dc_cb_past blockPtr->dct_dc_cb_past void ParseReconBlock(int n) { Block *blockPtr = &curVidStream->block; int diff, level, run, pos, coeff, qscale; short int *reconptr=DCT_recon[0]; unsigned short *iqmatrixptr; if (bufLength < 100) correct_underflow(); clear64words(reconptr=DCT_recon[0]); if (curVidStream->mblock.mb_intra) { if (n < 4) { /* Get the luminance bits. */ /* Parse and decode size of first coefficient and itself. */ DecodeDCTDCSizeLum(diff); coeff = diff << 3; if (n == 0) { if (curVidStream->mblock.mb_address - curVidStream->mblock.past_intra_addr > 1) coeff += 1024; else coeff += DCT_dc_y_past; } else coeff += DCT_dc_y_past; DCT_dc_y_past = coeff; } else { /* Parse and decode size of first coefficient and itself. */ DecodeDCTDCSizeChrom(diff); coeff = diff << 3; if (n == 4) { if (curVidStream->mblock.mb_address - curVidStream->mblock.past_intra_addr > 1) coeff += 1024; else coeff += DCT_dc_cr_past; DCT_dc_cr_past = coeff; } else { if (curVidStream->mblock.mb_address - curVidStream->mblock.past_intra_addr > 1) coeff += 1024; else coeff += DCT_dc_cb_past; DCT_dc_cb_past = coeff; } } *reconptr = coeff; if (curVidStream->picture.code_type != 4) { recon_intra(curVidStream->intra_quant_matrix_ptr[curVidStream->slice.quant_scale], reconptr); } else j_rev_dct(reconptr); } else { /* not an intra-frame */ qscale = curVidStream->slice.quant_scale; DecodeDCTCoeffFirst(run, level); pos = zigzag_direct[run]; if (curVidStream->non_intra_default) { qscale <<= 4; reconptr[pos] = ((short)level * (short)qscale) >> 3; if (curVidStream->picture.code_type != 4) { recon_nonintra(qscale, run, reconptr); } else j_rev_dct(reconptr); } else { iqmatrixptr = curVidStream->non_intra_quant_matrix_ptr[qscale]; reconptr[pos] = ((short)level * iqmatrixptr[run]) >> 3; if (curVidStream->picture.code_type != 4) { recon_non2intra(run, iqmatrixptr, reconptr); } else j_rev_dct(reconptr); // eventually, the flush(2) must be applied here, too ? hmmm } } } #undef DCT_recon #undef DCT_dc_y_past #undef DCT_dc_cr_past #undef DCT_dc_cb_past /* *-------------------------------------------------------------- * * ParseAwayBlock -- * * Parses off block values, throwing them away. * Used with grayscale dithering. * * Results: * None. * * Side effects: * None. * * To do: * Move to sutils.s !! * *-------------------------------------------------------------- */ void ParseAwayBlock(int n) { unsigned int diff, run; int level; if (bufLength < 100) correct_underflow(); if (curVidStream->mblock.mb_intra) { /* If the block is a luminance block... */ if (n < 4) { /* Parse and decode size of first coefficient and itself. */ DecodeDCTDCSizeLum(diff); } /* Otherwise, block is chrominance block... */ else { /* Parse and decode size of first coefficient and itself. */ DecodeDCTDCSizeChrom(diff); } } /* Otherwise, block is not intracoded... */ else { /* Decode and set first coefficient. */ DecodeDCTCoeffFirst(run, level); } /* If picture is not D type (i.e. I, P, or B)... */ if (curVidStream->picture.code_type != 4) { /* While end of macroblock has not been reached... */ do { DecodeDCTCoeffNext(run, level); /* Get the dct_coeff_next */ } while (run != END_OF_BLOCK); /* End_of_block */ flush_bits(2); } }