| /* |
| * This file is part of FFmpeg. |
| * |
| * FFmpeg is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2.1 of the License, or (at your option) any later version. |
| * |
| * FFmpeg is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with FFmpeg; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| static int FUNC(sequence_header)(CodedBitstreamContext *ctx, RWContext *rw, |
| MPEG2RawSequenceHeader *current) |
| { |
| CodedBitstreamMPEG2Context *mpeg2 = ctx->priv_data; |
| int err, i; |
| |
| HEADER("Sequence Header"); |
| |
| ui(8, sequence_header_code); |
| |
| uir(12, horizontal_size_value); |
| uir(12, vertical_size_value); |
| |
| mpeg2->horizontal_size = current->horizontal_size_value; |
| mpeg2->vertical_size = current->vertical_size_value; |
| |
| uir(4, aspect_ratio_information); |
| uir(4, frame_rate_code); |
| ui(18, bit_rate_value); |
| |
| marker_bit(); |
| |
| ui(10, vbv_buffer_size_value); |
| ui(1, constrained_parameters_flag); |
| |
| ui(1, load_intra_quantiser_matrix); |
| if (current->load_intra_quantiser_matrix) { |
| for (i = 0; i < 64; i++) |
| uirs(8, intra_quantiser_matrix[i], 1, i); |
| } |
| |
| ui(1, load_non_intra_quantiser_matrix); |
| if (current->load_non_intra_quantiser_matrix) { |
| for (i = 0; i < 64; i++) |
| uirs(8, non_intra_quantiser_matrix[i], 1, i); |
| } |
| |
| return 0; |
| } |
| |
| static int FUNC(user_data)(CodedBitstreamContext *ctx, RWContext *rw, |
| MPEG2RawUserData *current) |
| { |
| size_t k; |
| int err; |
| |
| HEADER("User Data"); |
| |
| ui(8, user_data_start_code); |
| |
| #ifdef READ |
| k = get_bits_left(rw); |
| av_assert0(k % 8 == 0); |
| current->user_data_length = k /= 8; |
| if (k > 0) { |
| current->user_data_ref = av_buffer_allocz(k + AV_INPUT_BUFFER_PADDING_SIZE); |
| if (!current->user_data_ref) |
| return AVERROR(ENOMEM); |
| current->user_data = current->user_data_ref->data; |
| } |
| #endif |
| |
| for (k = 0; k < current->user_data_length; k++) |
| uis(8, user_data[k], 1, k); |
| |
| return 0; |
| } |
| |
| static int FUNC(sequence_extension)(CodedBitstreamContext *ctx, RWContext *rw, |
| MPEG2RawSequenceExtension *current) |
| { |
| CodedBitstreamMPEG2Context *mpeg2 = ctx->priv_data; |
| int err; |
| |
| HEADER("Sequence Extension"); |
| |
| ui(8, profile_and_level_indication); |
| ui(1, progressive_sequence); |
| ui(2, chroma_format); |
| ui(2, horizontal_size_extension); |
| ui(2, vertical_size_extension); |
| |
| mpeg2->horizontal_size = (mpeg2->horizontal_size & 0xfff) | |
| current->horizontal_size_extension << 12; |
| mpeg2->vertical_size = (mpeg2->vertical_size & 0xfff) | |
| current->vertical_size_extension << 12; |
| mpeg2->progressive_sequence = current->progressive_sequence; |
| |
| ui(12, bit_rate_extension); |
| marker_bit(); |
| ui(8, vbv_buffer_size_extension); |
| ui(1, low_delay); |
| ui(2, frame_rate_extension_n); |
| ui(5, frame_rate_extension_d); |
| |
| return 0; |
| } |
| |
| static int FUNC(sequence_display_extension)(CodedBitstreamContext *ctx, RWContext *rw, |
| MPEG2RawSequenceDisplayExtension *current) |
| { |
| int err; |
| |
| HEADER("Sequence Display Extension"); |
| |
| ui(3, video_format); |
| |
| ui(1, colour_description); |
| if (current->colour_description) { |
| #ifdef READ |
| #define READ_AND_PATCH(name) do { \ |
| ui(8, name); \ |
| if (current->name == 0) { \ |
| current->name = 2; \ |
| av_log(ctx->log_ctx, AV_LOG_WARNING, "%s in a sequence display " \ |
| "extension had the invalid value 0. Setting it to 2 " \ |
| "(meaning unknown) instead.\n", #name); \ |
| } \ |
| } while (0) |
| READ_AND_PATCH(colour_primaries); |
| READ_AND_PATCH(transfer_characteristics); |
| READ_AND_PATCH(matrix_coefficients); |
| #undef READ_AND_PATCH |
| #else |
| uir(8, colour_primaries); |
| uir(8, transfer_characteristics); |
| uir(8, matrix_coefficients); |
| #endif |
| } else { |
| infer(colour_primaries, 2); |
| infer(transfer_characteristics, 2); |
| infer(matrix_coefficients, 2); |
| } |
| |
| ui(14, display_horizontal_size); |
| marker_bit(); |
| ui(14, display_vertical_size); |
| |
| return 0; |
| } |
| |
| static int FUNC(group_of_pictures_header)(CodedBitstreamContext *ctx, RWContext *rw, |
| MPEG2RawGroupOfPicturesHeader *current) |
| { |
| int err; |
| |
| HEADER("Group of Pictures Header"); |
| |
| ui(8, group_start_code); |
| |
| ui(25, time_code); |
| ui(1, closed_gop); |
| ui(1, broken_link); |
| |
| return 0; |
| } |
| |
| static int FUNC(extra_information)(CodedBitstreamContext *ctx, RWContext *rw, |
| MPEG2RawExtraInformation *current, |
| const char *element_name, const char *marker_name) |
| { |
| int err; |
| size_t k; |
| #ifdef READ |
| GetBitContext start = *rw; |
| uint8_t bit; |
| |
| for (k = 0; nextbits(1, 1, bit); k++) |
| skip_bits(rw, 1 + 8); |
| current->extra_information_length = k; |
| if (k > 0) { |
| *rw = start; |
| current->extra_information_ref = |
| av_buffer_allocz(k + AV_INPUT_BUFFER_PADDING_SIZE); |
| if (!current->extra_information_ref) |
| return AVERROR(ENOMEM); |
| current->extra_information = current->extra_information_ref->data; |
| } |
| #endif |
| |
| for (k = 0; k < current->extra_information_length; k++) { |
| bit(marker_name, 1); |
| xuia(8, element_name, |
| current->extra_information[k], 0, 255, 1, k); |
| } |
| |
| bit(marker_name, 0); |
| |
| return 0; |
| } |
| |
| static int FUNC(picture_header)(CodedBitstreamContext *ctx, RWContext *rw, |
| MPEG2RawPictureHeader *current) |
| { |
| int err; |
| |
| HEADER("Picture Header"); |
| |
| ui(8, picture_start_code); |
| |
| ui(10, temporal_reference); |
| uir(3, picture_coding_type); |
| ui(16, vbv_delay); |
| |
| if (current->picture_coding_type == 2 || |
| current->picture_coding_type == 3) { |
| ui(1, full_pel_forward_vector); |
| ui(3, forward_f_code); |
| } |
| |
| if (current->picture_coding_type == 3) { |
| ui(1, full_pel_backward_vector); |
| ui(3, backward_f_code); |
| } |
| |
| CHECK(FUNC(extra_information)(ctx, rw, ¤t->extra_information_picture, |
| "extra_information_picture[k]", "extra_bit_picture")); |
| |
| return 0; |
| } |
| |
| static int FUNC(picture_coding_extension)(CodedBitstreamContext *ctx, RWContext *rw, |
| MPEG2RawPictureCodingExtension *current) |
| { |
| CodedBitstreamMPEG2Context *mpeg2 = ctx->priv_data; |
| int err; |
| |
| HEADER("Picture Coding Extension"); |
| |
| uir(4, f_code[0][0]); |
| uir(4, f_code[0][1]); |
| uir(4, f_code[1][0]); |
| uir(4, f_code[1][1]); |
| |
| ui(2, intra_dc_precision); |
| ui(2, picture_structure); |
| ui(1, top_field_first); |
| ui(1, frame_pred_frame_dct); |
| ui(1, concealment_motion_vectors); |
| ui(1, q_scale_type); |
| ui(1, intra_vlc_format); |
| ui(1, alternate_scan); |
| ui(1, repeat_first_field); |
| ui(1, chroma_420_type); |
| ui(1, progressive_frame); |
| |
| if (mpeg2->progressive_sequence) { |
| if (current->repeat_first_field) { |
| if (current->top_field_first) |
| mpeg2->number_of_frame_centre_offsets = 3; |
| else |
| mpeg2->number_of_frame_centre_offsets = 2; |
| } else { |
| mpeg2->number_of_frame_centre_offsets = 1; |
| } |
| } else { |
| if (current->picture_structure == 1 || // Top field. |
| current->picture_structure == 2) { // Bottom field. |
| mpeg2->number_of_frame_centre_offsets = 1; |
| } else { |
| if (current->repeat_first_field) |
| mpeg2->number_of_frame_centre_offsets = 3; |
| else |
| mpeg2->number_of_frame_centre_offsets = 2; |
| } |
| } |
| |
| ui(1, composite_display_flag); |
| if (current->composite_display_flag) { |
| ui(1, v_axis); |
| ui(3, field_sequence); |
| ui(1, sub_carrier); |
| ui(7, burst_amplitude); |
| ui(8, sub_carrier_phase); |
| } |
| |
| return 0; |
| } |
| |
| static int FUNC(quant_matrix_extension)(CodedBitstreamContext *ctx, RWContext *rw, |
| MPEG2RawQuantMatrixExtension *current) |
| { |
| int err, i; |
| |
| HEADER("Quant Matrix Extension"); |
| |
| ui(1, load_intra_quantiser_matrix); |
| if (current->load_intra_quantiser_matrix) { |
| for (i = 0; i < 64; i++) |
| uirs(8, intra_quantiser_matrix[i], 1, i); |
| } |
| |
| ui(1, load_non_intra_quantiser_matrix); |
| if (current->load_non_intra_quantiser_matrix) { |
| for (i = 0; i < 64; i++) |
| uirs(8, non_intra_quantiser_matrix[i], 1, i); |
| } |
| |
| ui(1, load_chroma_intra_quantiser_matrix); |
| if (current->load_chroma_intra_quantiser_matrix) { |
| for (i = 0; i < 64; i++) |
| uirs(8, intra_quantiser_matrix[i], 1, i); |
| } |
| |
| ui(1, load_chroma_non_intra_quantiser_matrix); |
| if (current->load_chroma_non_intra_quantiser_matrix) { |
| for (i = 0; i < 64; i++) |
| uirs(8, chroma_non_intra_quantiser_matrix[i], 1, i); |
| } |
| |
| return 0; |
| } |
| |
| static int FUNC(picture_display_extension)(CodedBitstreamContext *ctx, RWContext *rw, |
| MPEG2RawPictureDisplayExtension *current) |
| { |
| CodedBitstreamMPEG2Context *mpeg2 = ctx->priv_data; |
| int err, i; |
| |
| HEADER("Picture Display Extension"); |
| |
| for (i = 0; i < mpeg2->number_of_frame_centre_offsets; i++) { |
| sis(16, frame_centre_horizontal_offset[i], 1, i); |
| marker_bit(); |
| sis(16, frame_centre_vertical_offset[i], 1, i); |
| marker_bit(); |
| } |
| |
| return 0; |
| } |
| |
| static int FUNC(extension_data)(CodedBitstreamContext *ctx, RWContext *rw, |
| MPEG2RawExtensionData *current) |
| { |
| int err; |
| |
| HEADER("Extension Data"); |
| |
| ui(8, extension_start_code); |
| ui(4, extension_start_code_identifier); |
| |
| switch (current->extension_start_code_identifier) { |
| case MPEG2_EXTENSION_SEQUENCE: |
| return FUNC(sequence_extension) |
| (ctx, rw, ¤t->data.sequence); |
| case MPEG2_EXTENSION_SEQUENCE_DISPLAY: |
| return FUNC(sequence_display_extension) |
| (ctx, rw, ¤t->data.sequence_display); |
| case MPEG2_EXTENSION_QUANT_MATRIX: |
| return FUNC(quant_matrix_extension) |
| (ctx, rw, ¤t->data.quant_matrix); |
| case MPEG2_EXTENSION_PICTURE_DISPLAY: |
| return FUNC(picture_display_extension) |
| (ctx, rw, ¤t->data.picture_display); |
| case MPEG2_EXTENSION_PICTURE_CODING: |
| return FUNC(picture_coding_extension) |
| (ctx, rw, ¤t->data.picture_coding); |
| default: |
| av_log(ctx->log_ctx, AV_LOG_ERROR, "Extension ID %d not supported.\n", |
| current->extension_start_code_identifier); |
| return AVERROR_PATCHWELCOME; |
| } |
| } |
| |
| static int FUNC(slice_header)(CodedBitstreamContext *ctx, RWContext *rw, |
| MPEG2RawSliceHeader *current) |
| { |
| CodedBitstreamMPEG2Context *mpeg2 = ctx->priv_data; |
| int err; |
| |
| HEADER("Slice Header"); |
| |
| ui(8, slice_vertical_position); |
| |
| if (mpeg2->vertical_size > 2800) |
| ui(3, slice_vertical_position_extension); |
| if (mpeg2->scalable) { |
| if (mpeg2->scalable_mode == 0) |
| ui(7, priority_breakpoint); |
| } |
| |
| uir(5, quantiser_scale_code); |
| |
| if (nextbits(1, 1, current->slice_extension_flag)) { |
| ui(1, slice_extension_flag); |
| ui(1, intra_slice); |
| ui(1, slice_picture_id_enable); |
| ui(6, slice_picture_id); |
| } |
| |
| CHECK(FUNC(extra_information)(ctx, rw, ¤t->extra_information_slice, |
| "extra_information_slice[k]", "extra_bit_slice")); |
| |
| return 0; |
| } |
| |
| static int FUNC(sequence_end)(CodedBitstreamContext *ctx, RWContext *rw, |
| MPEG2RawSequenceEnd *current) |
| { |
| int err; |
| |
| HEADER("Sequence End"); |
| |
| ui(8, sequence_end_code); |
| |
| return 0; |
| } |