/******************************************************************* 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, int remap); 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->h_size = get_bits(in, 12); out->v_size = get_bits(in, 12); out->aspect_ratio = get_bits(in, 4); out->picture_rate = get_bits(in, 4); out->bit_rate = get_bits(in, 18); get_bits(in, 1); /* marker bit */ out->vbv_buffer_size = get_bits(in, 10); out->mpeg1 = get_bits(in, 1); out->has_intra_quantizer_matrix = get_bits(in, 1); if(out->has_intra_quantizer_matrix){ for(i=0;i<64;i++){ out->iqm[i] = get_bits(in, 8); } } out->has_nonintra_quantizer_matrix = get_bits(in, 1); if(out->has_nonintra_quantizer_matrix){ for(i=0;i<64;i++){ out->nqm[i] = get_bits(in, 8); } } while(next_start_code(in)){ code = read_bits(in, 32); if(code != 0x1b5){ break; } erase_bits(in, 32); code = get_bits(in, 4); switch(code){ case 1: out->has_sequence_extension = 1; out->se.profile_and_level = get_bits(in, 8); out->se.progressive = get_bits(in, 1); out->se.chroma_format = get_bits(in, 2); out->h_size += get_bits(in, 2) << 12; out->v_size += get_bits(in, 2) << 12; out->bit_rate += get_bits(in, 12) << 18; out->vbv_buffer_size += get_bits(in, 8) << 10; out->se.low_delay = get_bits(in, 1); out->se.frame_rate_ext_n = get_bits(in, 2); out->se.frame_rate_ext_d = get_bits(in, 2); break; case 2: out->has_sequence_display_extension = 1; out->sd.video_format = get_bits(in, 3); out->sd.has_color_description = get_bits(in, 1); if(out->sd.has_color_description){ out->sd.color_primaries = get_bits(in, 8); out->sd.transfer_characteristics = get_bits(in, 8); out->sd.matrix_coefficients = get_bits(in, 8); } out->sd.display_h_size = get_bits(in, 14); out->sd.display_v_size = get_bits(in, 14); break; case 5: out->has_sequence_scalable_extension = 1; out->ss.scalable_mode = get_bits(in, 2); out->ss.layer = get_bits(in, 4); if(out->ss.scalable_mode == 1){ out->ss.lower_layer_prediction_h_size = get_bits(in, 14); out->ss.lower_layer_prediction_v_size = get_bits(in, 14); out->ss.h_subsampling_facter_m = get_bits(in, 5); out->ss.h_subsampling_facter_n = get_bits(in, 5); out->ss.v_subsampling_facter_m = get_bits(in, 5); out->ss.v_subsampling_facter_n = get_bits(in, 5); }else if(out->ss.scalable_mode == 3){ out->ss.picture_mux_enable = get_bits(in, 1); out->ss.mux_to_progressive_sequence = get_bits(in, 1); out->ss.pixture_mux_order = get_bits(in, 3); out->ss.pixture_mux_facter = get_bits(in, 3); } break; default: return 0; } } return 1; } int sequence_header_to_bgr_conversion_parameter(SEQUENCE_HEADER *in, BGR_CONVERSION_PARAMETER *out, int remap) { 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_extension){ out->chroma_format = in->se.chroma_format; out->progressive = in->se.progressive; }else{ out->chroma_format = 1; out->progressive = 1; } if(in->has_sequence_display_extension){ out->yo = y_offset[remap]; out->yg = y_gain[remap]; out->rv = table[in->sd.matrix_coefficients][remap][0]; out->gu = table[in->sd.matrix_coefficients][remap][1]; out->gv = table[in->sd.matrix_coefficients][remap][2]; out->bu = table[in->sd.matrix_coefficients][remap][3]; }else{ out->yo = y_offset[remap]; out->yg = y_gain[remap]; out->rv = table[0][remap][0]; out->gu = table[0][remap][1]; out->gv = table[0][remap][2]; out->bu = table[0][remap][3]; } 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; }