| /* getpic.c, picture decoding */ |
| |
| /* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */ |
| |
| /* |
| * Disclaimer of Warranty |
| * |
| * These software programs are available to the user without any license fee or |
| * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims |
| * any and all warranties, whether express, implied, or statuary, including any |
| * implied warranties or merchantability or of fitness for a particular |
| * purpose. In no event shall the copyright-holder be liable for any |
| * incidental, punitive, or consequential damages of any kind whatsoever |
| * arising from the use of these programs. |
| * |
| * This disclaimer of warranty extends to the user of these programs and user's |
| * customers, employees, agents, transferees, successors, and assigns. |
| * |
| * The MPEG Software Simulation Group does not represent or warrant that the |
| * programs furnished hereunder are free of infringement of any third-party |
| * patents. |
| * |
| * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware, |
| * are subject to royalty fees to patent holders. Many of these patents are |
| * general enough such that they are unavoidable regardless of implementation |
| * design. |
| * |
| */ |
| |
| #include <stdio.h> |
| |
| #include "config.h" |
| #include "global.h" |
| |
| /* private prototypes*/ |
| static void picture_data _ANSI_ARGS_((int framenum)); |
| static void macroblock_modes _ANSI_ARGS_((int *pmacroblock_type, int *pstwtype, |
| int *pstwclass, int *pmotion_type, int *pmotion_vector_count, int *pmv_format, int *pdmv, |
| int *pmvscale, int *pdct_type)); |
| static void Clear_Block _ANSI_ARGS_((int comp)); |
| static void Sum_Block _ANSI_ARGS_((int comp)); |
| static void Saturate _ANSI_ARGS_((short *bp)); |
| static void Add_Block _ANSI_ARGS_((int comp, int bx, int by, |
| int dct_type, int addflag)); |
| static void Update_Picture_Buffers _ANSI_ARGS_((void)); |
| static void frame_reorder _ANSI_ARGS_((int bitstream_framenum, |
| int sequence_framenum)); |
| static void Decode_SNR_Macroblock _ANSI_ARGS_((int *SNRMBA, int *SNRMBAinc, |
| int MBA, int MBAmax, int *dct_type)); |
| |
| static void motion_compensation _ANSI_ARGS_((int MBA, int macroblock_type, |
| int motion_type, int PMV[2][2][2], int motion_vertical_field_select[2][2], |
| int dmvector[2], int stwtype, int dct_type)); |
| |
| static void skipped_macroblock _ANSI_ARGS_((int dc_dct_pred[3], |
| int PMV[2][2][2], int *motion_type, int motion_vertical_field_select[2][2], |
| int *stwtype, int *macroblock_type)); |
| |
| static int slice _ANSI_ARGS_((int framenum, int MBAmax)); |
| |
| static int start_of_slice _ANSI_ARGS_ ((int MBAmax, int *MBA, |
| int *MBAinc, int dc_dct_pred[3], int PMV[2][2][2])); |
| |
| static int decode_macroblock _ANSI_ARGS_((int *macroblock_type, |
| int *stwtype, int *stwclass, int *motion_type, int *dct_type, |
| int PMV[2][2][2], int dc_dct_pred[3], |
| int motion_vertical_field_select[2][2], int dmvector[2])); |
| |
| |
| /* decode one frame or field picture */ |
| void Decode_Picture(bitstream_framenum, sequence_framenum) |
| int bitstream_framenum, sequence_framenum; |
| { |
| |
| if (picture_structure==FRAME_PICTURE && Second_Field) |
| { |
| /* recover from illegal number of field pictures */ |
| printf("odd number of field pictures\n"); |
| Second_Field = 0; |
| } |
| |
| /* IMPLEMENTATION: update picture buffer pointers */ |
| Update_Picture_Buffers(); |
| |
| #ifdef VERIFY |
| Check_Headers(bitstream_framenum, sequence_framenum); |
| #endif /* VERIFY */ |
| |
| /* ISO/IEC 13818-4 section 2.4.5.4 "frame buffer intercept method" */ |
| /* (section number based on November 1995 (Dallas) draft of the |
| conformance document) */ |
| if(Ersatz_Flag) |
| Substitute_Frame_Buffer(bitstream_framenum, sequence_framenum); |
| |
| /* form spatial scalable picture */ |
| |
| /* form spatial scalable picture */ |
| /* ISO/IEC 13818-2 section 7.7: Spatial scalability */ |
| if (base.pict_scal && !Second_Field) |
| { |
| Spatial_Prediction(); |
| } |
| |
| /* decode picture data ISO/IEC 13818-2 section 6.2.3.7 */ |
| picture_data(bitstream_framenum); |
| |
| /* write or display current or previously decoded reference frame */ |
| /* ISO/IEC 13818-2 section 6.1.1.11: Frame reordering */ |
| frame_reorder(bitstream_framenum, sequence_framenum); |
| |
| if (picture_structure!=FRAME_PICTURE) |
| Second_Field = !Second_Field; |
| } |
| |
| |
| /* decode all macroblocks of the current picture */ |
| /* stages described in ISO/IEC 13818-2 section 7 */ |
| static void picture_data(framenum) |
| int framenum; |
| { |
| int MBAmax; |
| int ret; |
| |
| /* number of macroblocks per picture */ |
| MBAmax = mb_width*mb_height; |
| |
| if (picture_structure!=FRAME_PICTURE) |
| MBAmax>>=1; /* field picture has half as mnay macroblocks as frame */ |
| |
| for(;;) |
| { |
| if((ret=slice(framenum, MBAmax))<0) |
| return; |
| } |
| |
| } |
| |
| |
| |
| /* decode all macroblocks of the current picture */ |
| /* ISO/IEC 13818-2 section 6.3.16 */ |
| static int slice(framenum, MBAmax) |
| int framenum, MBAmax; |
| { |
| int MBA; |
| int MBAinc, macroblock_type, motion_type, dct_type; |
| int dc_dct_pred[3]; |
| int PMV[2][2][2], motion_vertical_field_select[2][2]; |
| int dmvector[2]; |
| int stwtype, stwclass; |
| int SNRMBA, SNRMBAinc; |
| int ret; |
| |
| MBA = 0; /* macroblock address */ |
| MBAinc = 0; |
| |
| if((ret=start_of_slice(MBAmax, &MBA, &MBAinc, dc_dct_pred, PMV))!=1) |
| return(ret); |
| |
| if (Two_Streams && enhan.scalable_mode==SC_SNR) |
| { |
| SNRMBA=0; |
| SNRMBAinc=0; |
| } |
| |
| Fault_Flag=0; |
| |
| for (;;) |
| { |
| |
| /* this is how we properly exit out of picture */ |
| if (MBA>=MBAmax) |
| return(-1); /* all macroblocks decoded */ |
| |
| #ifdef TRACE |
| if (Trace_Flag) |
| printf("frame %d, MB %d\n",framenum,MBA); |
| #endif /* TRACE */ |
| |
| #ifdef DISPLAY |
| if (!progressive_frame && picture_structure==FRAME_PICTURE |
| && MBA==(MBAmax>>1) && framenum!=0 && Output_Type==T_X11 |
| && !Display_Progressive_Flag) |
| { |
| Display_Second_Field(); |
| } |
| #endif |
| |
| ld = &base; |
| |
| if (MBAinc==0) |
| { |
| if (base.scalable_mode==SC_DP && base.priority_breakpoint==1) |
| ld = &enhan; |
| |
| if (!Show_Bits(23) || Fault_Flag) /* next_start_code or fault */ |
| { |
| resync: /* if Fault_Flag: resynchronize to next next_start_code */ |
| Fault_Flag = 0; |
| return(0); /* trigger: go to next slice */ |
| } |
| else /* neither next_start_code nor Fault_Flag */ |
| { |
| if (base.scalable_mode==SC_DP && base.priority_breakpoint==1) |
| ld = &enhan; |
| |
| /* decode macroblock address increment */ |
| MBAinc = Get_macroblock_address_increment(); |
| |
| if (Fault_Flag) goto resync; |
| } |
| } |
| |
| if (MBA>=MBAmax) |
| { |
| /* MBAinc points beyond picture dimensions */ |
| if (!Quiet_Flag) |
| printf("Too many macroblocks in picture\n"); |
| return(-1); |
| } |
| |
| if (MBAinc==1) /* not skipped */ |
| { |
| ret = decode_macroblock(¯oblock_type, &stwtype, &stwclass, |
| &motion_type, &dct_type, PMV, dc_dct_pred, |
| motion_vertical_field_select, dmvector); |
| |
| if(ret==-1) |
| return(-1); |
| |
| if(ret==0) |
| goto resync; |
| |
| } |
| else /* MBAinc!=1: skipped macroblock */ |
| { |
| /* ISO/IEC 13818-2 section 7.6.6 */ |
| skipped_macroblock(dc_dct_pred, PMV, &motion_type, |
| motion_vertical_field_select, &stwtype, ¯oblock_type); |
| } |
| |
| /* SCALABILITY: SNR */ |
| /* ISO/IEC 13818-2 section 7.8 */ |
| /* NOTE: we currently ignore faults encountered in this routine */ |
| if (Two_Streams && enhan.scalable_mode==SC_SNR) |
| Decode_SNR_Macroblock(&SNRMBA, &SNRMBAinc, MBA, MBAmax, &dct_type); |
| |
| /* ISO/IEC 13818-2 section 7.6 */ |
| motion_compensation(MBA, macroblock_type, motion_type, PMV, |
| motion_vertical_field_select, dmvector, stwtype, dct_type); |
| |
| |
| /* advance to next macroblock */ |
| MBA++; |
| MBAinc--; |
| |
| /* SCALABILITY: SNR */ |
| if (Two_Streams && enhan.scalable_mode==SC_SNR) |
| { |
| SNRMBA++; |
| SNRMBAinc--; |
| } |
| |
| if (MBA>=MBAmax) |
| return(-1); /* all macroblocks decoded */ |
| } |
| } |
| |
| |
| /* ISO/IEC 13818-2 section 6.3.17.1: Macroblock modes */ |
| static void macroblock_modes(pmacroblock_type,pstwtype,pstwclass, |
| pmotion_type,pmotion_vector_count,pmv_format,pdmv,pmvscale,pdct_type) |
| int *pmacroblock_type, *pstwtype, *pstwclass; |
| int *pmotion_type, *pmotion_vector_count, *pmv_format, *pdmv, *pmvscale; |
| int *pdct_type; |
| { |
| int macroblock_type; |
| int stwtype, stwcode, stwclass; |
| int motion_type = 0; |
| int motion_vector_count, mv_format, dmv, mvscale; |
| int dct_type; |
| static unsigned char stwc_table[3][4] |
| = { {6,3,7,4}, {2,1,5,4}, {2,5,7,4} }; |
| static unsigned char stwclass_table[9] |
| = {0, 1, 2, 1, 1, 2, 3, 3, 4}; |
| |
| /* get macroblock_type */ |
| macroblock_type = Get_macroblock_type(); |
| |
| if (Fault_Flag) return; |
| |
| /* get spatial_temporal_weight_code */ |
| if (macroblock_type & MB_WEIGHT) |
| { |
| if (spatial_temporal_weight_code_table_index==0) |
| stwtype = 4; |
| else |
| { |
| stwcode = Get_Bits(2); |
| #ifdef TRACE |
| if (Trace_Flag) |
| { |
| printf("spatial_temporal_weight_code ("); |
| Print_Bits(stwcode,2,2); |
| printf("): %d\n",stwcode); |
| } |
| #endif /* TRACE */ |
| stwtype = stwc_table[spatial_temporal_weight_code_table_index-1][stwcode]; |
| } |
| } |
| else |
| stwtype = (macroblock_type & MB_CLASS4) ? 8 : 0; |
| |
| /* SCALABILITY: derive spatial_temporal_weight_class (Table 7-18) */ |
| stwclass = stwclass_table[stwtype]; |
| |
| /* get frame/field motion type */ |
| if (macroblock_type & (MACROBLOCK_MOTION_FORWARD|MACROBLOCK_MOTION_BACKWARD)) |
| { |
| if (picture_structure==FRAME_PICTURE) /* frame_motion_type */ |
| { |
| motion_type = frame_pred_frame_dct ? MC_FRAME : Get_Bits(2); |
| #ifdef TRACE |
| if (!frame_pred_frame_dct && Trace_Flag) |
| { |
| printf("frame_motion_type ("); |
| Print_Bits(motion_type,2,2); |
| printf("): %s\n",motion_type==MC_FIELD?"Field": |
| motion_type==MC_FRAME?"Frame": |
| motion_type==MC_DMV?"Dual_Prime":"Invalid"); |
| } |
| #endif /* TRACE */ |
| } |
| else /* field_motion_type */ |
| { |
| motion_type = Get_Bits(2); |
| #ifdef TRACE |
| if (Trace_Flag) |
| { |
| printf("field_motion_type ("); |
| Print_Bits(motion_type,2,2); |
| printf("): %s\n",motion_type==MC_FIELD?"Field": |
| motion_type==MC_16X8?"16x8 MC": |
| motion_type==MC_DMV?"Dual_Prime":"Invalid"); |
| } |
| #endif /* TRACE */ |
| } |
| } |
| else if ((macroblock_type & MACROBLOCK_INTRA) && concealment_motion_vectors) |
| { |
| /* concealment motion vectors */ |
| motion_type = (picture_structure==FRAME_PICTURE) ? MC_FRAME : MC_FIELD; |
| } |
| #if 0 |
| else |
| { |
| printf("maroblock_modes(): unknown macroblock type\n"); |
| motion_type = -1; |
| } |
| #endif |
| |
| /* derive motion_vector_count, mv_format and dmv, (table 6-17, 6-18) */ |
| if (picture_structure==FRAME_PICTURE) |
| { |
| motion_vector_count = (motion_type==MC_FIELD && stwclass<2) ? 2 : 1; |
| mv_format = (motion_type==MC_FRAME) ? MV_FRAME : MV_FIELD; |
| } |
| else |
| { |
| motion_vector_count = (motion_type==MC_16X8) ? 2 : 1; |
| mv_format = MV_FIELD; |
| } |
| |
| dmv = (motion_type==MC_DMV); /* dual prime */ |
| |
| /* field mv predictions in frame pictures have to be scaled |
| * ISO/IEC 13818-2 section 7.6.3.1 Decoding the motion vectors |
| * IMPLEMENTATION: mvscale is derived for later use in motion_vectors() |
| * it displaces the stage: |
| * |
| * if((mv_format=="field")&&(t==1)&&(picture_structure=="Frame picture")) |
| * prediction = PMV[r][s][t] DIV 2; |
| */ |
| |
| mvscale = ((mv_format==MV_FIELD) && (picture_structure==FRAME_PICTURE)); |
| |
| /* get dct_type (frame DCT / field DCT) */ |
| dct_type = (picture_structure==FRAME_PICTURE) |
| && (!frame_pred_frame_dct) |
| && (macroblock_type & (MACROBLOCK_PATTERN|MACROBLOCK_INTRA)) |
| ? Get_Bits(1) |
| : 0; |
| |
| #ifdef TRACE |
| if (Trace_Flag && (picture_structure==FRAME_PICTURE) |
| && (!frame_pred_frame_dct) |
| && (macroblock_type & (MACROBLOCK_PATTERN|MACROBLOCK_INTRA))) |
| printf("dct_type (%d): %s\n",dct_type,dct_type?"Field":"Frame"); |
| #endif /* TRACE */ |
| |
| /* return values */ |
| *pmacroblock_type = macroblock_type; |
| *pstwtype = stwtype; |
| *pstwclass = stwclass; |
| *pmotion_type = motion_type; |
| *pmotion_vector_count = motion_vector_count; |
| *pmv_format = mv_format; |
| *pdmv = dmv; |
| *pmvscale = mvscale; |
| *pdct_type = dct_type; |
| } |
| |
| |
| /* move/add 8x8-Block from block[comp] to backward_reference_frame */ |
| /* copy reconstructed 8x8 block from block[comp] to current_frame[] |
| * ISO/IEC 13818-2 section 7.6.8: Adding prediction and coefficient data |
| * This stage also embodies some of the operations implied by: |
| * - ISO/IEC 13818-2 section 7.6.7: Combining predictions |
| * - ISO/IEC 13818-2 section 6.1.3: Macroblock |
| */ |
| static void Add_Block(comp,bx,by,dct_type,addflag) |
| int comp,bx,by,dct_type,addflag; |
| { |
| int cc,i, j, iincr; |
| unsigned char *rfp; |
| short *bp; |
| |
| |
| /* derive color component index */ |
| /* equivalent to ISO/IEC 13818-2 Table 7-1 */ |
| cc = (comp<4) ? 0 : (comp&1)+1; /* color component index */ |
| |
| if (cc==0) |
| { |
| /* luminance */ |
| |
| if (picture_structure==FRAME_PICTURE) |
| if (dct_type) |
| { |
| /* field DCT coding */ |
| rfp = current_frame[0] |
| + Coded_Picture_Width*(by+((comp&2)>>1)) + bx + ((comp&1)<<3); |
| iincr = (Coded_Picture_Width<<1) - 8; |
| } |
| else |
| { |
| /* frame DCT coding */ |
| rfp = current_frame[0] |
| + Coded_Picture_Width*(by+((comp&2)<<2)) + bx + ((comp&1)<<3); |
| iincr = Coded_Picture_Width - 8; |
| } |
| else |
| { |
| /* field picture */ |
| rfp = current_frame[0] |
| + (Coded_Picture_Width<<1)*(by+((comp&2)<<2)) + bx + ((comp&1)<<3); |
| iincr = (Coded_Picture_Width<<1) - 8; |
| } |
| } |
| else |
| { |
| /* chrominance */ |
| |
| /* scale coordinates */ |
| if (chroma_format!=CHROMA444) |
| bx >>= 1; |
| if (chroma_format==CHROMA420) |
| by >>= 1; |
| if (picture_structure==FRAME_PICTURE) |
| { |
| if (dct_type && (chroma_format!=CHROMA420)) |
| { |
| /* field DCT coding */ |
| rfp = current_frame[cc] |
| + Chroma_Width*(by+((comp&2)>>1)) + bx + (comp&8); |
| iincr = (Chroma_Width<<1) - 8; |
| } |
| else |
| { |
| /* frame DCT coding */ |
| rfp = current_frame[cc] |
| + Chroma_Width*(by+((comp&2)<<2)) + bx + (comp&8); |
| iincr = Chroma_Width - 8; |
| } |
| } |
| else |
| { |
| /* field picture */ |
| rfp = current_frame[cc] |
| + (Chroma_Width<<1)*(by+((comp&2)<<2)) + bx + (comp&8); |
| iincr = (Chroma_Width<<1) - 8; |
| } |
| } |
| |
| bp = ld->block[comp]; |
| |
| if (addflag) |
| { |
| for (i=0; i<8; i++) |
| { |
| for (j=0; j<8; j++) |
| { |
| *rfp = Clip[*bp++ + *rfp]; |
| rfp++; |
| } |
| |
| rfp+= iincr; |
| } |
| } |
| else |
| { |
| for (i=0; i<8; i++) |
| { |
| for (j=0; j<8; j++) |
| *rfp++ = Clip[*bp++ + 128]; |
| |
| rfp+= iincr; |
| } |
| } |
| } |
| |
| |
| /* ISO/IEC 13818-2 section 7.8 */ |
| static void Decode_SNR_Macroblock(SNRMBA, SNRMBAinc, MBA, MBAmax, dct_type) |
| int *SNRMBA, *SNRMBAinc; |
| int MBA, MBAmax; |
| int *dct_type; |
| { |
| int SNRmacroblock_type, SNRcoded_block_pattern, SNRdct_type, dummy; |
| int slice_vert_pos_ext, quantizer_scale_code, comp, code; |
| |
| ld = &enhan; |
| |
| if (*SNRMBAinc==0) |
| { |
| if (!Show_Bits(23)) /* next_start_code */ |
| { |
| next_start_code(); |
| code = Show_Bits(32); |
| |
| if (code<SLICE_START_CODE_MIN || code>SLICE_START_CODE_MAX) |
| { |
| /* only slice headers are allowed in picture_data */ |
| if (!Quiet_Flag) |
| printf("SNR: Premature end of picture\n"); |
| return; |
| } |
| |
| Flush_Buffer32(); |
| |
| /* decode slice header (may change quantizer_scale) */ |
| slice_vert_pos_ext = slice_header(); |
| |
| /* decode macroblock address increment */ |
| *SNRMBAinc = Get_macroblock_address_increment(); |
| |
| /* set current location */ |
| *SNRMBA = |
| ((slice_vert_pos_ext<<7) + (code&255) - 1)*mb_width + *SNRMBAinc - 1; |
| |
| *SNRMBAinc = 1; /* first macroblock in slice: not skipped */ |
| } |
| else /* not next_start_code */ |
| { |
| if (*SNRMBA>=MBAmax) |
| { |
| if (!Quiet_Flag) |
| printf("Too many macroblocks in picture\n"); |
| return; |
| } |
| |
| /* decode macroblock address increment */ |
| *SNRMBAinc = Get_macroblock_address_increment(); |
| } |
| } |
| |
| if (*SNRMBA!=MBA) |
| { |
| /* streams out of sync */ |
| if (!Quiet_Flag) |
| printf("Cant't synchronize streams\n"); |
| return; |
| } |
| |
| if (*SNRMBAinc==1) /* not skipped */ |
| { |
| macroblock_modes(&SNRmacroblock_type, &dummy, &dummy, |
| &dummy, &dummy, &dummy, &dummy, &dummy, |
| &SNRdct_type); |
| |
| if (SNRmacroblock_type & MACROBLOCK_PATTERN) |
| *dct_type = SNRdct_type; |
| |
| if (SNRmacroblock_type & MACROBLOCK_QUANT) |
| { |
| quantizer_scale_code = Get_Bits(5); |
| ld->quantizer_scale = |
| ld->q_scale_type ? Non_Linear_quantizer_scale[quantizer_scale_code] : quantizer_scale_code<<1; |
| } |
| |
| /* macroblock_pattern */ |
| if (SNRmacroblock_type & MACROBLOCK_PATTERN) |
| { |
| SNRcoded_block_pattern = Get_coded_block_pattern(); |
| |
| if (chroma_format==CHROMA422) |
| SNRcoded_block_pattern = (SNRcoded_block_pattern<<2) | Get_Bits(2); /* coded_block_pattern_1 */ |
| else if (chroma_format==CHROMA444) |
| SNRcoded_block_pattern = (SNRcoded_block_pattern<<6) | Get_Bits(6); /* coded_block_pattern_2 */ |
| } |
| else |
| SNRcoded_block_pattern = 0; |
| |
| /* decode blocks */ |
| for (comp=0; comp<block_count; comp++) |
| { |
| Clear_Block(comp); |
| |
| if (SNRcoded_block_pattern & (1<<(block_count-1-comp))) |
| Decode_MPEG2_Non_Intra_Block(comp); |
| } |
| } |
| else /* SNRMBAinc!=1: skipped macroblock */ |
| { |
| for (comp=0; comp<block_count; comp++) |
| Clear_Block(comp); |
| } |
| |
| ld = &base; |
| } |
| |
| |
| |
| /* IMPLEMENTATION: set scratch pad macroblock to zero */ |
| static void Clear_Block(comp) |
| int comp; |
| { |
| short *Block_Ptr; |
| int i; |
| |
| Block_Ptr = ld->block[comp]; |
| |
| for (i=0; i<64; i++) |
| *Block_Ptr++ = 0; |
| } |
| |
| |
| /* SCALABILITY: add SNR enhancement layer block data to base layer */ |
| /* ISO/IEC 13818-2 section 7.8.3.4: Addition of coefficients from the two layes */ |
| static void Sum_Block(comp) |
| int comp; |
| { |
| short *Block_Ptr1, *Block_Ptr2; |
| int i; |
| |
| Block_Ptr1 = base.block[comp]; |
| Block_Ptr2 = enhan.block[comp]; |
| |
| for (i=0; i<64; i++) |
| *Block_Ptr1++ += *Block_Ptr2++; |
| } |
| |
| |
| /* limit coefficients to -2048..2047 */ |
| /* ISO/IEC 13818-2 section 7.4.3 and 7.4.4: Saturation and Mismatch control */ |
| static void Saturate(Block_Ptr) |
| short *Block_Ptr; |
| { |
| int i, sum, val; |
| |
| sum = 0; |
| |
| /* ISO/IEC 13818-2 section 7.4.3: Saturation */ |
| for (i=0; i<64; i++) |
| { |
| val = Block_Ptr[i]; |
| |
| if (val>2047) |
| val = 2047; |
| else if (val<-2048) |
| val = -2048; |
| |
| Block_Ptr[i] = val; |
| sum+= val; |
| } |
| |
| /* ISO/IEC 13818-2 section 7.4.4: Mismatch control */ |
| if ((sum&1)==0) |
| Block_Ptr[63]^= 1; |
| |
| } |
| |
| |
| /* reuse old picture buffers as soon as they are no longer needed |
| based on life-time axioms of MPEG */ |
| static void Update_Picture_Buffers() |
| { |
| int cc; /* color component index */ |
| unsigned char *tmp; /* temporary swap pointer */ |
| |
| for (cc=0; cc<3; cc++) |
| { |
| /* B pictures do not need to be save for future reference */ |
| if (picture_coding_type==B_TYPE) |
| { |
| current_frame[cc] = auxframe[cc]; |
| } |
| else |
| { |
| /* only update at the beginning of the coded frame */ |
| if (!Second_Field) |
| { |
| tmp = forward_reference_frame[cc]; |
| |
| /* the previously decoded reference frame is stored |
| coincident with the location where the backward |
| reference frame is stored (backwards prediction is not |
| needed in P pictures) */ |
| forward_reference_frame[cc] = backward_reference_frame[cc]; |
| |
| /* update pointer for potential future B pictures */ |
| backward_reference_frame[cc] = tmp; |
| } |
| |
| /* can erase over old backward reference frame since it is not used |
| in a P picture, and since any subsequent B pictures will use the |
| previously decoded I or P frame as the backward_reference_frame */ |
| current_frame[cc] = backward_reference_frame[cc]; |
| } |
| |
| /* IMPLEMENTATION: |
| one-time folding of a line offset into the pointer which stores the |
| memory address of the current frame saves offsets and conditional |
| branches throughout the remainder of the picture processing loop */ |
| if (picture_structure==BOTTOM_FIELD) |
| current_frame[cc]+= (cc==0) ? Coded_Picture_Width : Chroma_Width; |
| } |
| } |
| |
| |
| /* store last frame */ |
| |
| void Output_Last_Frame_of_Sequence(Framenum) |
| int Framenum; |
| { |
| if (Second_Field) |
| printf("last frame incomplete, not stored\n"); |
| else |
| Write_Frame(backward_reference_frame,Framenum-1); |
| } |
| |
| |
| |
| static void frame_reorder(Bitstream_Framenum, Sequence_Framenum) |
| int Bitstream_Framenum, Sequence_Framenum; |
| { |
| /* tracking variables to insure proper output in spatial scalability */ |
| static int Oldref_progressive_frame, Newref_progressive_frame; |
| |
| if (Sequence_Framenum!=0) |
| { |
| if (picture_structure==FRAME_PICTURE || Second_Field) |
| { |
| if (picture_coding_type==B_TYPE) |
| Write_Frame(auxframe,Bitstream_Framenum-1); |
| else |
| { |
| Newref_progressive_frame = progressive_frame; |
| progressive_frame = Oldref_progressive_frame; |
| |
| Write_Frame(forward_reference_frame,Bitstream_Framenum-1); |
| |
| Oldref_progressive_frame = progressive_frame = Newref_progressive_frame; |
| } |
| } |
| #ifdef DISPLAY |
| else if (Output_Type==T_X11) |
| { |
| if(!Display_Progressive_Flag) |
| Display_Second_Field(); |
| } |
| #endif |
| } |
| else |
| Oldref_progressive_frame = progressive_frame; |
| |
| } |
| |
| |
| /* ISO/IEC 13818-2 section 7.6 */ |
| static void motion_compensation(MBA, macroblock_type, motion_type, PMV, |
| motion_vertical_field_select, dmvector, stwtype, dct_type) |
| int MBA; |
| int macroblock_type; |
| int motion_type; |
| int PMV[2][2][2]; |
| int motion_vertical_field_select[2][2]; |
| int dmvector[2]; |
| int stwtype; |
| int dct_type; |
| { |
| int bx, by; |
| int comp; |
| |
| /* derive current macroblock position within picture */ |
| /* ISO/IEC 13818-2 section 6.3.1.6 and 6.3.1.7 */ |
| bx = 16*(MBA%mb_width); |
| by = 16*(MBA/mb_width); |
| |
| /* motion compensation */ |
| if (!(macroblock_type & MACROBLOCK_INTRA)) |
| form_predictions(bx,by,macroblock_type,motion_type,PMV, |
| motion_vertical_field_select,dmvector,stwtype); |
| |
| /* SCALABILITY: Data Partitioning */ |
| if (base.scalable_mode==SC_DP) |
| ld = &base; |
| |
| /* copy or add block data into picture */ |
| for (comp=0; comp<block_count; comp++) |
| { |
| /* SCALABILITY: SNR */ |
| /* ISO/IEC 13818-2 section 7.8.3.4: Addition of coefficients from |
| the two a layers */ |
| if (Two_Streams && enhan.scalable_mode==SC_SNR) |
| Sum_Block(comp); /* add SNR enhancement layer data to base layer */ |
| |
| /* MPEG-2 saturation and mismatch control */ |
| /* base layer could be MPEG-1 stream, enhancement MPEG-2 SNR */ |
| /* ISO/IEC 13818-2 section 7.4.3 and 7.4.4: Saturation and Mismatch control */ |
| if ((Two_Streams && enhan.scalable_mode==SC_SNR) || ld->MPEG2_Flag) |
| Saturate(ld->block[comp]); |
| |
| /* ISO/IEC 13818-2 section Annex A: inverse DCT */ |
| if (Reference_IDCT_Flag) |
| Reference_IDCT(ld->block[comp]); |
| else |
| Fast_IDCT(ld->block[comp]); |
| |
| /* ISO/IEC 13818-2 section 7.6.8: Adding prediction and coefficient data */ |
| Add_Block(comp,bx,by,dct_type,(macroblock_type & MACROBLOCK_INTRA)==0); |
| } |
| |
| } |
| |
| |
| |
| /* ISO/IEC 13818-2 section 7.6.6 */ |
| static void skipped_macroblock(dc_dct_pred, PMV, motion_type, |
| motion_vertical_field_select, stwtype, macroblock_type) |
| int dc_dct_pred[3]; |
| int PMV[2][2][2]; |
| int *motion_type; |
| int motion_vertical_field_select[2][2]; |
| int *stwtype; |
| int *macroblock_type; |
| { |
| int comp; |
| |
| /* SCALABILITY: Data Paritioning */ |
| if (base.scalable_mode==SC_DP) |
| ld = &base; |
| |
| for (comp=0; comp<block_count; comp++) |
| Clear_Block(comp); |
| |
| /* reset intra_dc predictors */ |
| /* ISO/IEC 13818-2 section 7.2.1: DC coefficients in intra blocks */ |
| dc_dct_pred[0]=dc_dct_pred[1]=dc_dct_pred[2]=0; |
| |
| /* reset motion vector predictors */ |
| /* ISO/IEC 13818-2 section 7.6.3.4: Resetting motion vector predictors */ |
| if (picture_coding_type==P_TYPE) |
| PMV[0][0][0]=PMV[0][0][1]=PMV[1][0][0]=PMV[1][0][1]=0; |
| |
| /* derive motion_type */ |
| if (picture_structure==FRAME_PICTURE) |
| *motion_type = MC_FRAME; |
| else |
| { |
| *motion_type = MC_FIELD; |
| |
| /* predict from field of same parity */ |
| /* ISO/IEC 13818-2 section 7.6.6.1 and 7.6.6.3: P field picture and B field |
| picture */ |
| motion_vertical_field_select[0][0]=motion_vertical_field_select[0][1] = |
| (picture_structure==BOTTOM_FIELD); |
| } |
| |
| /* skipped I are spatial-only predicted, */ |
| /* skipped P and B are temporal-only predicted */ |
| /* ISO/IEC 13818-2 section 7.7.6: Skipped macroblocks */ |
| *stwtype = (picture_coding_type==I_TYPE) ? 8 : 0; |
| |
| /* IMPLEMENTATION: clear MACROBLOCK_INTRA */ |
| *macroblock_type&= ~MACROBLOCK_INTRA; |
| |
| } |
| |
| |
| /* return==-1 means go to next picture */ |
| /* the expression "start of slice" is used throughout the normative |
| body of the MPEG specification */ |
| static int start_of_slice(MBAmax, MBA, MBAinc, |
| dc_dct_pred, PMV) |
| int MBAmax; |
| int *MBA; |
| int *MBAinc; |
| int dc_dct_pred[3]; |
| int PMV[2][2][2]; |
| { |
| unsigned int code; |
| int slice_vert_pos_ext; |
| |
| ld = &base; |
| |
| Fault_Flag = 0; |
| |
| next_start_code(); |
| code = Show_Bits(32); |
| |
| if (code<SLICE_START_CODE_MIN || code>SLICE_START_CODE_MAX) |
| { |
| /* only slice headers are allowed in picture_data */ |
| if (!Quiet_Flag) |
| printf("start_of_slice(): Premature end of picture\n"); |
| |
| return(-1); /* trigger: go to next picture */ |
| } |
| |
| Flush_Buffer32(); |
| |
| /* decode slice header (may change quantizer_scale) */ |
| slice_vert_pos_ext = slice_header(); |
| |
| |
| /* SCALABILITY: Data Partitioning */ |
| if (base.scalable_mode==SC_DP) |
| { |
| ld = &enhan; |
| next_start_code(); |
| code = Show_Bits(32); |
| |
| if (code<SLICE_START_CODE_MIN || code>SLICE_START_CODE_MAX) |
| { |
| /* only slice headers are allowed in picture_data */ |
| if (!Quiet_Flag) |
| printf("DP: Premature end of picture\n"); |
| return(-1); /* trigger: go to next picture */ |
| } |
| |
| Flush_Buffer32(); |
| |
| /* decode slice header (may change quantizer_scale) */ |
| slice_vert_pos_ext = slice_header(); |
| |
| if (base.priority_breakpoint!=1) |
| ld = &base; |
| } |
| |
| /* decode macroblock address increment */ |
| *MBAinc = Get_macroblock_address_increment(); |
| |
| if (Fault_Flag) |
| { |
| printf("start_of_slice(): MBAinc unsuccessful\n"); |
| return(0); /* trigger: go to next slice */ |
| } |
| |
| /* set current location */ |
| /* NOTE: the arithmetic used to derive macroblock_address below is |
| * equivalent to ISO/IEC 13818-2 section 6.3.17: Macroblock |
| */ |
| *MBA = ((slice_vert_pos_ext<<7) + (code&255) - 1)*mb_width + *MBAinc - 1; |
| *MBAinc = 1; /* first macroblock in slice: not skipped */ |
| |
| /* reset all DC coefficient and motion vector predictors */ |
| /* reset all DC coefficient and motion vector predictors */ |
| /* ISO/IEC 13818-2 section 7.2.1: DC coefficients in intra blocks */ |
| dc_dct_pred[0]=dc_dct_pred[1]=dc_dct_pred[2]=0; |
| |
| /* ISO/IEC 13818-2 section 7.6.3.4: Resetting motion vector predictors */ |
| 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; |
| |
| /* successfull: trigger decode macroblocks in slice */ |
| return(1); |
| } |
| |
| |
| /* ISO/IEC 13818-2 sections 7.2 through 7.5 */ |
| static int decode_macroblock(macroblock_type, stwtype, stwclass, |
| motion_type, dct_type, PMV, dc_dct_pred, |
| motion_vertical_field_select, dmvector) |
| int *macroblock_type; |
| int *stwtype; |
| int *stwclass; |
| int *motion_type; |
| int *dct_type; |
| int PMV[2][2][2]; |
| int dc_dct_pred[3]; |
| int motion_vertical_field_select[2][2]; |
| int dmvector[2]; |
| { |
| /* locals */ |
| int quantizer_scale_code; |
| int comp; |
| |
| int motion_vector_count; |
| int mv_format; |
| int dmv; |
| int mvscale; |
| int coded_block_pattern; |
| |
| /* SCALABILITY: Data Patitioning */ |
| if (base.scalable_mode==SC_DP) |
| { |
| if (base.priority_breakpoint<=2) |
| ld = &enhan; |
| else |
| ld = &base; |
| } |
| |
| /* ISO/IEC 13818-2 section 6.3.17.1: Macroblock modes */ |
| macroblock_modes(macroblock_type, stwtype, stwclass, |
| motion_type, &motion_vector_count, &mv_format, &dmv, &mvscale, |
| dct_type); |
| |
| if (Fault_Flag) return(0); /* trigger: go to next slice */ |
| |
| if (*macroblock_type & MACROBLOCK_QUANT) |
| { |
| quantizer_scale_code = Get_Bits(5); |
| |
| #ifdef TRACE |
| if (Trace_Flag) |
| { |
| printf("quantiser_scale_code ("); |
| Print_Bits(quantizer_scale_code,5,5); |
| printf("): %d\n",quantizer_scale_code); |
| } |
| #endif /* TRACE */ |
| |
| /* ISO/IEC 13818-2 section 7.4.2.2: Quantizer scale factor */ |
| if (ld->MPEG2_Flag) |
| ld->quantizer_scale = |
| ld->q_scale_type ? Non_Linear_quantizer_scale[quantizer_scale_code] |
| : (quantizer_scale_code << 1); |
| else |
| ld->quantizer_scale = quantizer_scale_code; |
| |
| /* SCALABILITY: Data Partitioning */ |
| if (base.scalable_mode==SC_DP) |
| /* make sure base.quantizer_scale is valid */ |
| base.quantizer_scale = ld->quantizer_scale; |
| } |
| |
| /* motion vectors */ |
| |
| |
| /* ISO/IEC 13818-2 section 6.3.17.2: Motion vectors */ |
| |
| /* decode forward motion vectors */ |
| if ((*macroblock_type & MACROBLOCK_MOTION_FORWARD) |
| || ((*macroblock_type & MACROBLOCK_INTRA) |
| && concealment_motion_vectors)) |
| { |
| if (ld->MPEG2_Flag) |
| motion_vectors(PMV,dmvector,motion_vertical_field_select, |
| 0,motion_vector_count,mv_format,f_code[0][0]-1,f_code[0][1]-1, |
| dmv,mvscale); |
| else |
| motion_vector(PMV[0][0],dmvector, |
| forward_f_code-1,forward_f_code-1,0,0,full_pel_forward_vector); |
| } |
| |
| if (Fault_Flag) return(0); /* trigger: go to next slice */ |
| |
| /* decode backward motion vectors */ |
| if (*macroblock_type & MACROBLOCK_MOTION_BACKWARD) |
| { |
| if (ld->MPEG2_Flag) |
| motion_vectors(PMV,dmvector,motion_vertical_field_select, |
| 1,motion_vector_count,mv_format,f_code[1][0]-1,f_code[1][1]-1,0, |
| mvscale); |
| else |
| motion_vector(PMV[0][1],dmvector, |
| backward_f_code-1,backward_f_code-1,0,0,full_pel_backward_vector); |
| } |
| |
| if (Fault_Flag) return(0); /* trigger: go to next slice */ |
| |
| if ((*macroblock_type & MACROBLOCK_INTRA) && concealment_motion_vectors) |
| Flush_Buffer(1); /* remove marker_bit */ |
| |
| if (base.scalable_mode==SC_DP && base.priority_breakpoint==3) |
| ld = &enhan; |
| |
| /* macroblock_pattern */ |
| /* ISO/IEC 13818-2 section 6.3.17.4: Coded block pattern */ |
| if (*macroblock_type & MACROBLOCK_PATTERN) |
| { |
| coded_block_pattern = Get_coded_block_pattern(); |
| |
| if (chroma_format==CHROMA422) |
| { |
| /* coded_block_pattern_1 */ |
| coded_block_pattern = (coded_block_pattern<<2) | Get_Bits(2); |
| |
| #ifdef TRACE |
| if (Trace_Flag) |
| { |
| printf("coded_block_pattern_1: "); |
| Print_Bits(coded_block_pattern,2,2); |
| printf(" (%d)\n",coded_block_pattern&3); |
| } |
| #endif /* TRACE */ |
| } |
| else if (chroma_format==CHROMA444) |
| { |
| /* coded_block_pattern_2 */ |
| coded_block_pattern = (coded_block_pattern<<6) | Get_Bits(6); |
| |
| #ifdef TRACE |
| if (Trace_Flag) |
| { |
| printf("coded_block_pattern_2: "); |
| Print_Bits(coded_block_pattern,6,6); |
| printf(" (%d)\n",coded_block_pattern&63); |
| } |
| #endif /* TRACE */ |
| } |
| } |
| else |
| coded_block_pattern = (*macroblock_type & MACROBLOCK_INTRA) ? |
| (1<<block_count)-1 : 0; |
| |
| if (Fault_Flag) return(0); /* trigger: go to next slice */ |
| |
| /* decode blocks */ |
| for (comp=0; comp<block_count; comp++) |
| { |
| /* SCALABILITY: Data Partitioning */ |
| if (base.scalable_mode==SC_DP) |
| ld = &base; |
| |
| Clear_Block(comp); |
| |
| if (coded_block_pattern & (1<<(block_count-1-comp))) |
| { |
| if (*macroblock_type & MACROBLOCK_INTRA) |
| { |
| if (ld->MPEG2_Flag) |
| Decode_MPEG2_Intra_Block(comp,dc_dct_pred); |
| else |
| Decode_MPEG1_Intra_Block(comp,dc_dct_pred); |
| } |
| else |
| { |
| if (ld->MPEG2_Flag) |
| Decode_MPEG2_Non_Intra_Block(comp); |
| else |
| Decode_MPEG1_Non_Intra_Block(comp); |
| } |
| |
| if (Fault_Flag) return(0); /* trigger: go to next slice */ |
| } |
| } |
| |
| if(picture_coding_type==D_TYPE) |
| { |
| /* remove end_of_macroblock (always 1, prevents startcode emulation) */ |
| /* ISO/IEC 11172-2 section 2.4.2.7 and 2.4.3.6 */ |
| marker_bit("D picture end_of_macroblock bit"); |
| } |
| |
| /* reset intra_dc predictors */ |
| /* ISO/IEC 13818-2 section 7.2.1: DC coefficients in intra blocks */ |
| if (!(*macroblock_type & MACROBLOCK_INTRA)) |
| dc_dct_pred[0]=dc_dct_pred[1]=dc_dct_pred[2]=0; |
| |
| /* reset motion vector predictors */ |
| if ((*macroblock_type & MACROBLOCK_INTRA) && !concealment_motion_vectors) |
| { |
| /* intra mb without concealment motion vectors */ |
| /* ISO/IEC 13818-2 section 7.6.3.4: Resetting motion vector predictors */ |
| 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; |
| } |
| |
| /* special "No_MC" macroblock_type case */ |
| /* ISO/IEC 13818-2 section 7.6.3.5: Prediction in P pictures */ |
| if ((picture_coding_type==P_TYPE) |
| && !(*macroblock_type & (MACROBLOCK_MOTION_FORWARD|MACROBLOCK_INTRA))) |
| { |
| /* non-intra mb without forward mv in a P picture */ |
| /* ISO/IEC 13818-2 section 7.6.3.4: Resetting motion vector predictors */ |
| PMV[0][0][0]=PMV[0][0][1]=PMV[1][0][0]=PMV[1][0][1]=0; |
| |
| /* derive motion_type */ |
| /* ISO/IEC 13818-2 section 6.3.17.1: Macroblock modes, frame_motion_type */ |
| if (picture_structure==FRAME_PICTURE) |
| *motion_type = MC_FRAME; |
| else |
| { |
| *motion_type = MC_FIELD; |
| /* predict from field of same parity */ |
| motion_vertical_field_select[0][0] = (picture_structure==BOTTOM_FIELD); |
| } |
| } |
| |
| if (*stwclass==4) |
| { |
| /* purely spatially predicted macroblock */ |
| /* ISO/IEC 13818-2 section 7.7.5.1: Resetting motion vector predictions */ |
| 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; |
| } |
| |
| /* successfully decoded macroblock */ |
| return(1); |
| |
| } /* decode_macroblock */ |
| |
| |