📄 video_mpeg1.c
字号:
int r_size = pic.coding_ext.f_code[s][t] - 1; { // Read and compute the motion vector delta int motion_code = get_vlc(table_b10, "motion_code[r][s][0] (b10)"); if((pic.coding_ext.f_code[s][t] != 1) && (motion_code != 0)) { int motion_residual = GETBITS(r_size, "motion_residual[r][s][0]"); delta = ((abs(motion_code) - 1) << r_size) + motion_residual + 1; if(motion_code < 0) delta = - delta; } else { delta = motion_code; } } if(mb.dmv == 1) mb.dmvector[t] = get_vlc(table_b11, "dmvector[0] (b11)"); // Get the predictor prediction = pic.PMV[r][s][t]; if((t==1) && (mb.mv_format == MV_FORMAT_FIELD) && (pic.coding_ext.picture_structure == PIC_STRUCT_FRAME_PICTURE)) prediction = prediction >> 1; /* DIV */ { // Compute the resulting motion vector int f = 1 << r_size; int high = (16 * f) - 1; int low = ((-16) * f); int range = (32 * f); vector = prediction + delta; if(vector < low) vector = vector + range; if(vector > high) vector = vector - range; } // Update predictors if((t==1) && (mb.mv_format == MV_FORMAT_FIELD) && (pic.coding_ext.picture_structure == PIC_STRUCT_FRAME_PICTURE)) pic.PMV[r][s][t] = vector * 2; else pic.PMV[r][s][t] = vector; // Scale the vector so that it is always measured in half pels if(pic.header.full_pel_vector[s]) mb.vector[r][s][t] = vector << 1; else mb.vector[r][s][t] = vector; }}/* 6.2.5.2 Motion vectors */static inlinevoid motion_vectors(unsigned int s){ DPRINTF(3, "motion_vectors(%u)\n", s); /* This does not differ from MPEG-2 if: pic.coding_ext.picture_structure == PIC_STRUCT_FRAME_PICTURE && pic.coding_ext.frame_pred_frame_dct == 1 but these are all constant in MPEG1 so we set the following once at the start if the video sequence. mb.prediction_type = PRED_TYPE_FRAME_BASED; mb.motion_vector_count = 1; mb.mv_format = MV_FORMAT_FRAME; mb.dmv = 0; */ motion_vector(0, s);}/* 6.2.5.1 Macroblock modes */staticint macroblock_modes(void){ DPRINTF(3, "macroblock_modes\n"); if(pic.header.picture_coding_type == PIC_CODING_TYPE_I) { mb.modes.macroblock_type = get_vlc(table_b2, "macroblock_type (b2)"); } else if(pic.header.picture_coding_type == PIC_CODING_TYPE_P) { mb.modes.macroblock_type = get_vlc(table_b3, "macroblock_type (b3)"); } else if(pic.header.picture_coding_type == PIC_CODING_TYPE_B) { mb.modes.macroblock_type = get_vlc(table_b4, "macroblock_type (b4)"); } else { fprintf(stderr, "*** Unsupported picture type %02x\n", pic.header.picture_coding_type); return -1; //exit_program(-1); } if(mb.modes.macroblock_type == VLC_FAIL) { return -1; } mb.modes.macroblock_quant = mb.modes.macroblock_type & MACROBLOCK_QUANT; mb.modes.macroblock_motion_forward = mb.modes.macroblock_type & MACROBLOCK_MOTION_FORWARD; mb.modes.macroblock_motion_backward = mb.modes.macroblock_type & MACROBLOCK_MOTION_BACKWARD; mb.modes.macroblock_pattern = mb.modes.macroblock_type & MACROBLOCK_PATTERN; mb.modes.macroblock_intra = mb.modes.macroblock_type & MACROBLOCK_INTRA;#if 0 // MPEG2 mb.modes.spatial_temporal_weight_code_flag = mb.modes.macroblock_type & SPATIAL_TEMPORAL_WEIGHT_CODE_FLAG; DPRINTF(5, "spatial_temporal_weight_code_flag: %01x\n", mb.modes.spatial_temporal_weight_code_flag); if((mb.modes.spatial_temporal_weight_code_flag == 1) && ( 1 /*spatial_temporal_weight_code_table_index != 0*/)) { mb.modes.spatial_temporal_weight_code = GETBITS(2, "spatial_temporal_weight_code"); } if(mb.modes.macroblock_motion_forward || mb.modes.macroblock_motion_backward) { if(pic.coding_ext.picture_structure == PIC_STRUCT_FRAME_PICTURE) { if(pic.coding_ext.frame_pred_frame_dct == 0) { mb.modes.frame_motion_type = GETBITS(2, "frame_motion_type"); } else { /* frame_motion_type omitted from the bitstream */ mb.modes.frame_motion_type = 0x2; } } else { mb.modes.field_motion_type = GETBITS(2, "field_motion_type"); } } /* if(decode_dct_type) */ if((pic.coding_ext.picture_structure == PIC_STRUCT_FRAME_PICTURE) && (pic.coding_ext.frame_pred_frame_dct == 0) && (mb.modes.macroblock_intra || mb.modes.macroblock_pattern)) { mb.modes.dct_type = GETBITS(1, "dct_type"); } else { /* Table 6-19. Value of dct_type if dct_type is not in the bitstream.*/ if(pic.coding_ext.frame_pred_frame_dct == 1) { mb.modes.dct_type = 0; } /* else dct_type is unused, either field picture or mb not coded */ }#endif return 0;}/* 6.2.5 Macroblock */staticint macroblock(int new_slice){ uint16_t inc_add = 0; DPRINTF(3, "macroblock()\n"); // MPEG-1 start (this does not occur in an MPEG-2 stream) // (not a valid macroblock_escape code) while(nextbits(11) == 0x00F) { GETBITS(11, "macroblock_stuffing"); } // MPEG-1 end while(nextbits(11) == 0x008) { GETBITS(11, "macroblock_escape"); inc_add += 33; } mb.macroblock_address_increment = get_vlc(table_b1, "macroblock_address_increment"); if(mb.macroblock_address_increment == VLC_FAIL) { return -1; } mb.macroblock_address_increment += inc_add; seq.macroblock_address += mb.macroblock_address_increment; seq.mb_column = seq.macroblock_address % seq.mb_width; seq.mb_row = seq.macroblock_address / seq.mb_width; if(new_slice) /* There are never any skipped blocks at start of a slice */ mb.macroblock_address_increment = 1; DPRINTF(2, " Macroblock: %d, row: %d, col: %d\n", seq.macroblock_address, seq.mb_row, seq.mb_column); #ifdef DEBUG if(mb.macroblock_address_increment > 1) { DPRINTF(3, "Skipped %d macroblocks ", mb.macroblock_address_increment); }#endif /* Process all block that are skipped. (Do motion compensation) */ if(mb.macroblock_address_increment > 1) { int i; /* There is plenty of room to optimize this */ switch(pic.header.picture_coding_type) { case PIC_CODING_TYPE_I: fprintf(stderr, "*** skipped blocks in I-picture\n"); return -1; // Error parsing bitstream case PIC_CODING_TYPE_P: DPRINTF(3,"in P-picture\n"); /* Assume prediction is forward with a zero vector */ mb.modes.macroblock_motion_forward = 1; // Remove Me mb.modes.macroblock_motion_backward = 0; // Remove Me mb.modes.macroblock_type |= MACROBLOCK_MOTION_FORWARD; mb.modes.macroblock_type &= ~MACROBLOCK_MOTION_BACKWARD; reset_vectors(); // Instead of explicit set to zero. break; case PIC_CODING_TYPE_B: DPRINTF(3,"in B-frame\n"); /* Use previous macroblock modes and vectors. */ break; } /* We only get here for P or B picutes. */ i = mb.macroblock_address_increment; while( --i > 0 ) { seq.mb_column = (seq.macroblock_address - i) % seq.mb_width; seq.mb_row = (seq.macroblock_address - i) / seq.mb_width; /* Skipped blocks never have any DCT-coefficients, so there is no call to motion_comp_add_coeff */ motion_comp(); } seq.mb_column = seq.macroblock_address % seq.mb_width; seq.mb_row = seq.macroblock_address / seq.mb_width; } /* What kind of macroblock is this. */ if(macroblock_modes() == -1) { return -1; // Error parsing bitstream } if(mb.modes.macroblock_quant) { mb.quantiser_scale = GETBITS(5, "quantiser_scale_code"); } if(mb.modes.macroblock_intra == 0) { reset_dc_dct_pred(); DPRINTF(3, "non_intra macroblock\n"); } /* Decoding of motion vectors. */ // Reset predictors: when a macroblock is skipped in a P-picture. */ if(mb.macroblock_address_increment > 1) { reset_dc_dct_pred(); // Could be moved but fitts fine here if(pic.header.picture_coding_type == PIC_CODING_TYPE_P) reset_PMV(); } if(mb.modes.macroblock_motion_forward) motion_vectors(0); if(mb.modes.macroblock_motion_backward) motion_vectors(1); // Update predictors. if((mb.modes.macroblock_motion_forward == 0) && (mb.modes.macroblock_motion_backward == 0)) { // Is this correct? reset_PMV(); } switch (pic.header.picture_coding_type) { case PIC_CODING_TYPE_I: /* I-picture */ break; case PIC_CODING_TYPE_P: /* P-picture */ if(mb.modes.macroblock_intra) { reset_PMV(); reset_vectors(); } if((!mb.modes.macroblock_intra) && (!mb.modes.macroblock_motion_forward)) { reset_PMV(); /* Asume prediction is forward with a zero vector */ mb.modes.macroblock_motion_forward = 1; // Remove Me mb.modes.macroblock_motion_backward = 0; // Remove Me mb.modes.macroblock_type |= MACROBLOCK_MOTION_FORWARD; mb.modes.macroblock_type &= ~MACROBLOCK_MOTION_BACKWARD; reset_vectors(); // Instead of explicit set to zero. } break; case PIC_CODING_TYPE_B: /* B-picture */ if(mb.modes.macroblock_intra) { reset_PMV(); reset_vectors(); } break; } /* Pel reconstruction - motion compensation (if any) - decode coefficents - inverse quantisation - 'oddify' the coefficents - inverse transform - combine the data with motion compensated pels */ if(mb.modes.macroblock_intra) { unsigned int i; /* Intra blocks always have pattern coded for all sub blocks. The IDCT function writes directly to the output buffers. */ for(i = 0; i < 6; i++) { DPRINTF(4, "cbpindex: %d assumed\n", i); if(block_intra(i) == -1) return -1; // Error parsing bitstream /* Shortcut: write the IDCT data directly into the picture buffer */ { const int x = seq.mb_column; const int y = seq.mb_row; const int width = seq.mb_width * 16; //seq.horizontal_size; int d, stride; uint8_t *dst; if (mb.modes.dct_type) { d = 1; stride = width * 2; } else { d = 8; stride = width; } if(i < 4) { dst = &dst_image->y[x * 16 + y * width * 16]; dst = (i & 1) ? dst + 8 : dst; dst = (i >= 2) ? dst + width * d : dst; } else { stride = width / 2; // HACK alert !!! if(i == 4) dst = &dst_image->u[x * 8 + y * width/2 * 8]; else // i == 5 dst = &dst_image->v[x * 8 + y * width/2 * 8]; } mlib_VideoIDCT8x8_U8_S16(dst, (int16_t *)mb.QFS, stride); } } } else { /* Non-intra block */ motion_comp(); if(mb.modes.macroblock_pattern) { int i; if(coded_block_pattern() == -1) return -1; // Error parsing bitstream for(i = 0; i < 6; i++) { if(mb.cbp & (1<<(5-i))) { DPRINTF(4, "cbpindex: %d set\n", i); if(block_non_intra(i) == -1) return -1; // Error parsing bitstream //mlib_VideoIDCT8x8_S16_S16((int16_t *)mb.QFS, (int16_t *)mb.QFS); motion_comp_add_coeff(i); // do idtc and add in here } } } } return 0;}/* 6.2.4 Slice */int mpeg1_slice(void){ uint32_t slice_start_code; int new_slice = 1; DPRINTF(3, "slice\n"); reset_dc_dct_pred(); reset_PMV(); reset_vectors(); DPRINTF(3, "start of slice\n"); slice_start_code = GETBITS(32, "slice_start_code"); slice_data.slice_vertical_position = slice_start_code & 0xff; // Do we need to update seq.mb_col ??? seq.mb_row = slice_data.slice_vertical_position - 1; seq.macroblock_address = (seq.mb_row * seq.mb_width) - 1; mb.quantiser_scale = GETBITS(5, "quantiser_scale_code"); if(nextbits(1) == 1) { slice_data.intra_slice_flag = GETBITS(1, "intra_slice_flag"); slice_data.intra_slice = GETBITS(1, "intra_slice"); slice_data.reserved_bits = GETBITS(7, "reserved_bits"); while(nextbits(1) == 1) { slice_data.extra_bit_slice = GETBITS(1, "extra_bit_slice"); slice_data.extra_information_slice = GETBITS(8, "extra_information_slice"); } } slice_data.extra_bit_slice = GETBITS(1, "extra_bit_slice"); do { if( macroblock(new_slice) ) { //break; return -1; } new_slice = 0; } while(nextbits(23) != 0); next_start_code(); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -