/******************************************************************* MPEG Video sequance header reading routine *******************************************************************/ #include "scan.h" #define SEQUENCE_HEADER_C #include "sequence_header.h" int read_sequence_header(VIDEO_STREAM *in, SEQUENCE_HEADER *out); int sequence_header_to_bgr_conversion_parameter(SEQUENCE_HEADER *in, BGR_CONVERSION_PARAMETER *out, M2V_CONFIG *prm); int sequence_header_to_read_picture_header_option(SEQUENCE_HEADER *in, READ_PICTURE_HEADER_OPTION *out); int sequence_header_to_read_slice_header_option(SEQUENCE_HEADER *in, READ_SLICE_HEADER_OPTION *out); int sequence_header_to_read_macroblock_option(SEQUENCE_HEADER *in, READ_MACROBLOCK_OPTION *out); int sequence_header_to_read_block_option(SEQUENCE_HEADER *in, READ_BLOCK_OPTION *out); int sequence_header_to_mc_parameter(SEQUENCE_HEADER *in, MC_PARAMETER *out); int read_sequence_header(VIDEO_STREAM *in, SEQUENCE_HEADER *out) { int i; int code; out->orig_h_size = vs_get_bits(in, 12); out->orig_v_size = vs_get_bits(in, 12); out->aspect_ratio = vs_get_bits(in, 4); out->picture_rate = vs_get_bits(in, 4); out->bit_rate = vs_get_bits(in, 18); vs_get_bits(in, 1); /* marker bit */ out->vbv_buffer_size = vs_get_bits(in, 10); out->mpeg1 = vs_get_bits(in, 1); out->has_intra_quantizer_matrix = vs_get_bits(in, 1); if(out->has_intra_quantizer_matrix){ for(i=0;i<64;i++){ out->iqm[i] = vs_get_bits(in, 8); } } out->has_nonintra_quantizer_matrix = vs_get_bits(in, 1); if(out->has_nonintra_quantizer_matrix){ for(i=0;i<64;i++){ out->nqm[i] = vs_get_bits(in, 8); } } while(vs_next_start_code(in)){ code = vs_read_bits(in, 32); if(code != 0x1b5){ break; } vs_erase_bits(in, 32); code = vs_get_bits(in, 4); switch(code){ case 1: out->has_sequence_extension = 1; out->se.profile_and_level = vs_get_bits(in, 8); out->se.progressive = vs_get_bits(in, 1); out->se.chroma_format = vs_get_bits(in, 2); out->orig_h_size += vs_get_bits(in, 2) << 12; out->orig_v_size += vs_get_bits(in, 2) << 12; out->bit_rate += vs_get_bits(in, 12) << 18; vs_erase_bits(in, 1); /* marker bits */ out->vbv_buffer_size += vs_get_bits(in, 8) << 10; out->se.low_delay = vs_get_bits(in, 1); out->se.frame_rate_ext_n = vs_get_bits(in, 2); out->se.frame_rate_ext_d = vs_get_bits(in, 2); break; case 2: out->has_sequence_display_extension = 1; out->sd.video_format = vs_get_bits(in, 3); out->sd.has_color_description = vs_get_bits(in, 1); if(out->sd.has_color_description){ out->sd.color_primaries = vs_get_bits(in, 8); out->sd.transfer_characteristics = vs_get_bits(in, 8); out->sd.matrix_coefficients = vs_get_bits(in, 8); } out->sd.display_h_size = vs_get_bits(in, 14); vs_erase_bits(in, 1); out->sd.display_v_size = vs_get_bits(in, 14); break; case 5: out->has_sequence_scalable_extension = 1; out->ss.scalable_mode = vs_get_bits(in, 2); out->ss.layer = vs_get_bits(in, 4); if(out->ss.scalable_mode == 1){ out->ss.lower_layer_prediction_h_size = vs_get_bits(in, 14); out->ss.lower_layer_prediction_v_size = vs_get_bits(in, 14); out->ss.h_subsampling_facter_m = vs_get_bits(in, 5); out->ss.h_subsampling_facter_n = vs_get_bits(in, 5); out->ss.v_subsampling_facter_m = vs_get_bits(in, 5); out->ss.v_subsampling_facter_n = vs_get_bits(in, 5); }else if(out->ss.scalable_mode == 3){ out->ss.picture_mux_enable = vs_get_bits(in, 1); out->ss.mux_to_progressive_sequence = vs_get_bits(in, 1); out->ss.pixture_mux_order = vs_get_bits(in, 3); out->ss.pixture_mux_facter = vs_get_bits(in, 3); } break; default: break; } } out->h_size = out->orig_h_size + 15; out->h_size >>= 4; out->h_size <<= 4; if(out->has_sequence_extension && (out->se.progressive == 0)){ out->v_size = out->orig_v_size + 31; out->v_size >>= 5; out->v_size <<= 5; }else{ out->v_size = out->orig_v_size + 15; out->v_size >>= 4; out->v_size <<= 4; } return 1; } int sequence_header_to_bgr_conversion_parameter(SEQUENCE_HEADER *in, BGR_CONVERSION_PARAMETER *out, M2V_CONFIG *prm) { static const int table[8][2][5] = { { { /* RV GU GV BU */ 103219, -12257, -30659, 121621, }, /* straight conversion */ { /* RV GU GV BU */ 117504, -13954, -34903, 138453, }, /* re-map conversion */ }, /* no sequence_display_extension */ { { /* RV GU GV BU */ 103219, -12257, -30659, 121621, }, /* straight conversion */ { /* RV GU GV BU */ 117504, -13954, -34903, 138453, }, /* re-map conversion */ }, /* ITU-R Rec. 709 */ { { /* RV GU GV BU */ 91881, -22553, -46801, 116129, }, /* straight conversion */ { /* RV GU GV BU */ 104597, -25675, -53279, 132201, }, /* re-map conversion */ }, /* unspecified video */ { { /* RV GU GV BU */ 91881, -22553, -46801, 116129, }, /* straight conversion */ { /* RV GU GV BU */ 104597, -25675, -53279, 132201, }, /* re-map conversion */ }, /* reserved */ { { /* RV GU GV BU */ 91750, -21749, -46652, 116654, }, /* straight conversion */ { /* RV GU GV BU */ 104448, -24759, -53109, 132798, }, /* re-map conversion */ }, /* FCC */ { { /* RV GU GV BU */ 91881, -22553, -46801, 116129, }, /* straight conversion */ { /* RV GU GV BU */ 104597, -25675, -53279, 132201, }, /* re-map conversion */ }, /* ITU-R Rec. 624-4 System B, G */ { { /* RV GU GV BU */ 91881, -22553, -46801, 116129, }, /* straight conversion */ { /* RV GU GV BU */ 104597, -25675, -53279, 132201, }, /* re-map conversion */ }, /* SMPTE 170M */ { { /* RV GU GV BU */ 103284, -14851, -31235, 119668, }, /* straight conversion */ { /* RV GU GV BU */ 117579, -16907, -35559, 136230, }, /* re-map conversion */ }, /* SMPTE 240 */ }; static const int y_offset[2] = { 0, 16, }; static const int y_gain[2] = { 65536, 76309, }; if(in->has_sequence_display_extension){ out->yo = y_offset[prm->bt601]; out->yg = y_gain[prm->bt601]; out->rv = table[in->sd.matrix_coefficients][prm->bt601][0]; out->gu = table[in->sd.matrix_coefficients][prm->bt601][1]; out->gv = table[in->sd.matrix_coefficients][prm->bt601][2]; out->bu = table[in->sd.matrix_coefficients][prm->bt601][3]; }else{ out->yo = y_offset[prm->bt601]; out->yg = y_gain[prm->bt601]; out->rv = table[0][prm->bt601][0]; out->gu = table[0][prm->bt601][1]; out->gv = table[0][prm->bt601][2]; out->bu = table[0][prm->bt601][3]; } out->width = in->orig_h_size; out->height = in->orig_v_size; out->in_step = in->h_size; return 1; } int sequence_header_to_read_picture_header_option(SEQUENCE_HEADER *in, READ_PICTURE_HEADER_OPTION *out) { if(in->has_sequence_extension){ out->progressive_sequence = in->se.progressive; }else{ out->progressive_sequence = 1; } return 1; } int sequence_header_to_read_slice_header_option(SEQUENCE_HEADER *in, READ_SLICE_HEADER_OPTION *out) { out->v_size = in->v_size; if(in->has_sequence_scalable_extension){ out->scalable_mode = in->ss.scalable_mode; }else{ out->scalable_mode = -1; } return 1; } int sequence_header_to_read_macroblock_option(SEQUENCE_HEADER *in, READ_MACROBLOCK_OPTION *out) { if(in->has_sequence_extension){ out->chroma_format = in->se.chroma_format; }else{ out->chroma_format = 1; } if(in->has_sequence_scalable_extension){ out->scalable_mode = in->ss.scalable_mode; }else{ out->scalable_mode = -1; } return 1; } int sequence_header_to_read_block_option(SEQUENCE_HEADER *in, READ_BLOCK_OPTION *out) { int i; if(in->has_sequence_extension){ out->chroma_format = in->se.chroma_format; }else{ out->chroma_format = 1; } if(in->has_intra_quantizer_matrix){ for(i=0;i<64;i++){ out->quantizer_weight[0][scan_table[0][i]] = in->iqm[i]; out->quantizer_weight[2][scan_table[0][i]] = in->iqm[i]; } }else{ memcpy(out->quantizer_weight[0], default_intra_quantizer_matrix, 64); memcpy(out->quantizer_weight[2], default_intra_quantizer_matrix, 64); } if(in->has_nonintra_quantizer_matrix){ for(i=0;i<64;i++){ out->quantizer_weight[1][scan_table[0][i]] = in->nqm[i]; out->quantizer_weight[3][scan_table[0][i]] = in->nqm[i]; } }else{ memset(out->quantizer_weight[1], 16, 64); memset(out->quantizer_weight[3], 16, 64); } return 1; } int sequence_header_to_mc_parameter(SEQUENCE_HEADER *in, MC_PARAMETER *out) { if(in->has_sequence_extension){ out->chroma_format = in->se.chroma_format; }else{ out->chroma_format = 1; } return 1; }