--- libavcodec/cbs.c | 1 + libavcodec/cbs_internal.h | 1 + libavcodec/cbs_mpeg2.c | 355 ++++++++++++++++++++++++++++++++++++++++ libavcodec/cbs_mpeg2.h | 207 ++++++++++++++++++++++++ libavcodec/cbs_mpeg2_syntax.c | 367 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 931 insertions(+) create mode 100644 libavcodec/cbs_mpeg2.c create mode 100644 libavcodec/cbs_mpeg2.h create mode 100644 libavcodec/cbs_mpeg2_syntax.c
diff --git a/libavcodec/cbs.c b/libavcodec/cbs.c index 6030cfd48..2b98b519b 100644 --- a/libavcodec/cbs.c +++ b/libavcodec/cbs.c @@ -29,6 +29,7 @@ static const CodedBitstreamType *cbs_type_table[] = { &ff_cbs_type_h264, &ff_cbs_type_h265, + &ff_cbs_type_mpeg2, }; int ff_cbs_init(CodedBitstreamContext *ctx, diff --git a/libavcodec/cbs_internal.h b/libavcodec/cbs_internal.h index 46d41db6d..57c7f1e36 100644 --- a/libavcodec/cbs_internal.h +++ b/libavcodec/cbs_internal.h @@ -98,6 +98,7 @@ int ff_cbs_write_se_golomb(CodedBitstreamContext *ctx, PutBitContext *pbc, extern const CodedBitstreamType ff_cbs_type_h264; extern const CodedBitstreamType ff_cbs_type_h265; +extern const CodedBitstreamType ff_cbs_type_mpeg2; #endif /* AVCODEC_CBS_INTERNAL_H */ diff --git a/libavcodec/cbs_mpeg2.c b/libavcodec/cbs_mpeg2.c new file mode 100644 index 000000000..ef54311ae --- /dev/null +++ b/libavcodec/cbs_mpeg2.c @@ -0,0 +1,355 @@ +/* + * This file is part of Libav. + * + * Libav 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. + * + * Libav 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 Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/avassert.h" + +#include "cbs.h" +#include "cbs_internal.h" +#include "cbs_mpeg2.h" +#include "internal.h" + + +#define HEADER(name) do { \ + ff_cbs_trace_header(ctx, name); \ + } while (0) + +#define CHECK(call) do { \ + err = (call); \ + if (err < 0) \ + return err; \ + } while (0) + +#define FUNC_NAME(rw, codec, name) cbs_ ## codec ## _ ## rw ## _ ## name +#define FUNC_MPEG2(rw, name) FUNC_NAME(rw, mpeg2, name) +#define FUNC(name) FUNC_MPEG2(READWRITE, name) + + +#define READ +#define READWRITE read +#define RWContext BitstreamContext + +#define xui(width, name, var) do { \ + uint32_t value = 0; \ + CHECK(ff_cbs_read_unsigned(ctx, rw, width, #name, \ + &value, 0, (1 << width) - 1)); \ + var = value; \ + } while (0) + +#define ui(width, name) \ + xui(width, name, current->name) + +#define marker_bit() do { \ + av_unused int one = 1; \ + CHECK(ff_cbs_read_unsigned(ctx, rw, 1, "marker_bit", &one, 1, 1)); \ + } while (0) + +#define nextbits(width, compare, var) (var = bitstream_peek(rw, width), \ + var == (compare)) + +#include "cbs_mpeg2_syntax.c" + +#undef READ +#undef READWRITE +#undef RWContext +#undef xui +#undef ui +#undef marker_bit +#undef nextbits + + +#define WRITE +#define READWRITE write +#define RWContext PutBitContext + +#define xui(width, name, var) do { \ + CHECK(ff_cbs_write_unsigned(ctx, rw, width, #name, \ + var, 0, (1 << width) - 1)); \ + } while (0) + +#define ui(width, name) \ + xui(width, name, current->name) + +#define marker_bit() do { \ + CHECK(ff_cbs_write_unsigned(ctx, rw, 1, "marker_bit", 1, 1, 1)); \ + } while (0) + +#define nextbits(width, compare, var) (var) + +#include "cbs_mpeg2_syntax.c" + +#undef READ +#undef READWRITE +#undef RWContext +#undef xui +#undef ui +#undef marker_bit +#undef nextbits + + +static int cbs_mpeg2_split_fragment(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag, + int header) +{ + const uint8_t *start, *end; + uint8_t *unit_data; + uint32_t start_code = -1, next_start_code = -1; + size_t unit_size; + int err, i, unit_type; + + if (frag->nb_units != 0) + return AVERROR(EINVAL); + + start = avpriv_find_start_code(frag->data, frag->data + frag->data_size, + &start_code); + for (i = 0;; i++) { + end = avpriv_find_start_code(start, frag->data + frag->data_size, + &next_start_code); + + unit_type = start_code & 0xff; + + if (end == frag->data + frag->data_size) + unit_size = end - (start - 1); + else + unit_size = (end - 4) - (start - 1); + + unit_data = av_malloc(unit_size); + if (!unit_data) + return AVERROR(ENOMEM); + memcpy(unit_data, start - 1, unit_size); + + err = ff_cbs_insert_unit_data(ctx, frag, i, unit_type, + unit_data, unit_size); + if (err < 0) + return err; + + if (end == frag->data + frag->data_size) + break; + + start_code = next_start_code; + start = end; + } + + return 0; +} + +static int cbs_mpeg2_read_unit(CodedBitstreamContext *ctx, + CodedBitstreamUnit *unit) +{ + BitstreamContext bc; + int err; + + err = bitstream_init(&bc, unit->data, 8 * unit->data_size); + if (err < 0) + return err; + + if (unit->type >= 0x01 && unit->type <= 0xaf) { + MPEG2RawSlice *slice; + int pos, len; + + slice = av_mallocz(sizeof(*slice)); + if (!slice) + return AVERROR(ENOMEM); + err = cbs_mpeg2_read_slice_header(ctx, &bc, &slice->header); + if (err < 0) { + av_free(slice); + return err; + } + + pos = bitstream_tell(&bc); + len = unit->data_size; + + slice->data_size = len - pos / 8; + slice->data = av_malloc(slice->data_size); + if (!slice->data) { + av_free(slice); + return AVERROR(ENOMEM); + } + + memcpy(slice->data, + unit->data + pos / 8, slice->data_size); + slice->data_bit_start = pos % 8; + + unit->content = slice; + + } else { + switch (unit->type) { +#define START(start_code, type, func) \ + case start_code: \ + { \ + type *header; \ + header = av_mallocz(sizeof(*header)); \ + if (!header) \ + return AVERROR(ENOMEM); \ + err = cbs_mpeg2_read_ ## func(ctx, &bc, header); \ + if (err < 0) { \ + av_free(header); \ + return err; \ + } \ + unit->content = header; \ + } \ + break; + START(0x00, MPEG2RawPictureHeader, picture_header); + START(0xb2, MPEG2RawUserData, user_data); + START(0xb3, MPEG2RawSequenceHeader, sequence_header); + START(0xb5, MPEG2RawExtensionData, extension_data); + START(0xb8, MPEG2RawGroupOfPicturesHeader, group_of_pictures_header); +#undef START + default: + av_log(ctx->log_ctx, AV_LOG_ERROR, "Unknown start code %02x.\n", + unit->type); + return AVERROR_INVALIDDATA; + } + } + + return 0; +} + +static int cbs_mpeg2_write_unit(CodedBitstreamContext *ctx, + CodedBitstreamUnit *unit) +{ + PutBitContext pbc; + uint8_t *data; + size_t size; + int err; + + data = av_malloc(1 << 24); + if (!data) + return AVERROR(ENOMEM); + + init_put_bits(&pbc, data, 1 << 24); + + if (unit->type >= 0x01 && unit->type <= 0xaf) { + MPEG2RawSlice *slice = unit->content; + BitstreamContext bc; + size_t bits_left; + + err = cbs_mpeg2_write_slice_header(ctx, &pbc, &slice->header); + if (err < 0) + goto fail; + + if (slice->data) { + bitstream_init(&bc, slice->data, slice->data_size * 8); + bitstream_skip(&bc, slice->data_bit_start); + + while (bitstream_bits_left(&bc) > 15) + put_bits(&pbc, 16, bitstream_read(&bc, 16)); + + bits_left = bitstream_bits_left(&bc); + put_bits(&pbc, bits_left, bitstream_read(&bc, bits_left)); + + // Align with zeroes. + while (put_bits_count(&pbc) % 8 != 0) + put_bits(&pbc, 1, 0); + } + } else { + switch (unit->type) { +#define START(start_code, type, func) \ + case start_code: \ + err = cbs_mpeg2_write_ ## func(ctx, &pbc, unit->content); \ + if (err < 0) \ + goto fail; \ + break; + START(0x00, MPEG2RawPictureHeader, picture_header); + START(0xb2, MPEG2RawUserData, user_data); + START(0xb3, MPEG2RawSequenceHeader, sequence_header); + START(0xb5, MPEG2RawExtensionData, extension_data); + START(0xb8, MPEG2RawGroupOfPicturesHeader, group_of_pictures_header); +#undef START + default: + av_log(ctx->log_ctx, AV_LOG_ERROR, "Write unimplemented for start " + "code %02x.\n", unit->type); + err = AVERROR_PATCHWELCOME; + goto fail; + } + } + + if (put_bits_count(&pbc) % 8) + unit->data_bit_padding = 8 - put_bits_count(&pbc) % 8; + else + unit->data_bit_padding = 0; + + size = (put_bits_count(&pbc) + 7) / 8; + flush_put_bits(&pbc); + + av_freep(&unit->data); + + unit->data = av_realloc(data, size); + if (!unit->data) { + err = AVERROR(ENOMEM); + goto fail; + } + unit->data_size = size; + + return 0; + +fail: + av_free(data); + return err; +} + +static int cbs_mpeg2_assemble_fragment(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag) +{ + uint8_t *data; + size_t size, dp, sp; + int i; + + size = 0; + for (i = 0; i < frag->nb_units; i++) + size += 3 + frag->units[i].data_size; + + data = av_malloc(size); + if (!data) + return AVERROR(ENOMEM); + + dp = 0; + for (i = 0; i < frag->nb_units; i++) { + CodedBitstreamUnit *unit = &frag->units[i]; + + data[dp++] = 0; + data[dp++] = 0; + data[dp++] = 1; + + for (sp = 0; sp < unit->data_size; sp++) + data[dp++] = unit->data[sp]; + } + + av_assert0(dp == size); + + frag->data = data; + frag->data_size = size; + + return 0; +} + +static void cbs_mpeg2_free_unit(CodedBitstreamUnit *unit) +{ +} + +const CodedBitstreamType ff_cbs_type_mpeg2 = { + .codec_id = AV_CODEC_ID_MPEG2VIDEO, + + .priv_data_size = 1, //sizeof(CodedBitstreamMPEG2Context), + + .split_fragment = &cbs_mpeg2_split_fragment, + .read_unit = &cbs_mpeg2_read_unit, + .write_unit = &cbs_mpeg2_write_unit, + .assemble_fragment = &cbs_mpeg2_assemble_fragment, + + .free_unit = &cbs_mpeg2_free_unit, +}; diff --git a/libavcodec/cbs_mpeg2.h b/libavcodec/cbs_mpeg2.h new file mode 100644 index 000000000..721766d92 --- /dev/null +++ b/libavcodec/cbs_mpeg2.h @@ -0,0 +1,207 @@ +/* + * This file is part of Libav. + * + * Libav 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. + * + * Libav 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 Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_CBS_MPEG2_H +#define AVCODEC_CBS_MPEG2_H + +#include <stdint.h> + + +enum { + MPEG2_START_PICTURE = 0x00, + MPEG2_START_SLICE_MIN = 0x01, + MPEG2_START_SLICE_MAX = 0xaf, + MPEG2_START_USER_DATA = 0xb2, + MPEG2_START_SEQUENCE_HEADER = 0xb3, + MPEG2_START_SEQUENCE_ERROR = 0xb4, + MPEG2_START_EXTENSION = 0xb5, + MPEG2_START_SEQUENCE_END = 0xb7, + MPEG2_START_GROUP = 0xb8, +}; + +enum { + MPEG2_EXTENSION_SEQUENCE = 0x1, + MPEG2_EXTENSION_SEQUENCE_DISPLAY = 0x2, + MPEG2_EXTENSION_QUANT_MATRIX = 0x3, + MPEG2_EXTENSION_COPYRIGHT = 0x4, + MPEG2_EXTENSION_SEQUENCE_SCALABLE = 0x5, + MPEG2_EXTENSION_PICTURE_DISPLAY = 0x7, + MPEG2_EXTENSION_PICTURE_CODING = 0x8, + MPEG2_EXTENSION_PICTURE_SPATIAL_SCALABLE = 0x9, + MPEG2_EXTENSION_PICTURE_TEMPORAL_SCALABLE = 0xa, + MPEG2_EXTENSION_CAMAERA_PARAMETERS = 0xb, + MPEG2_EXTENSION_ITU_T = 0xc, +}; + + +typedef struct MPEG2RawSequenceHeader { + uint8_t sequence_header_code; + + uint16_t horizontal_size_value; + uint16_t vertical_size_value; + uint8_t aspect_ratio_information; + uint8_t frame_rate_code; + uint32_t bit_rate_value; + uint16_t vbv_buffer_size_value; + uint8_t constrained_parameters_flag; + + uint8_t load_intra_quantiser_matrix; + uint8_t intra_quantiser_matrix[64]; + uint8_t load_non_intra_quantiser_matrix; + uint8_t non_intra_quantiser_matrix[64]; +} MPEG2RawSequenceHeader; + +typedef struct MPEG2RawUserData { + uint8_t user_data_start_code; + + uint8_t *user_data; + size_t user_data_length; +} MPEG2RawUserData; + +typedef struct MPEG2RawSequenceExtension { + uint8_t profile_and_level_indication; + uint8_t progressive_sequence; + uint8_t chroma_format; + uint8_t horizontal_size_extension; + uint8_t vertical_size_extension; + uint16_t bit_rate_extension; + uint8_t vbv_buffer_size_extension; + uint8_t low_delay; + uint8_t frame_rate_extension_n; + uint8_t frame_rate_extension_d; +} MPEG2RawSequenceExtension; + +typedef struct MPEG2RawSequenceDisplayExtension { + uint8_t video_format; + + uint8_t colour_description; + uint8_t colour_primaries; + uint8_t transfer_characteristics; + uint8_t matrix_coefficients; + + uint16_t display_horizontal_size; + uint16_t display_vertical_size; +} MPEG2RawSequenceDisplayExtension; + +typedef struct MPEG2RawGroupOfPicturesHeader { + uint8_t group_start_code; + + uint32_t time_code; + uint8_t closed_gop; + uint8_t broken_link; +} MPEG2RawGroupOfPicturesHeader; + +typedef struct MPEG2RawPictureHeader { + uint8_t picture_start_code; + + uint16_t temporal_reference; + uint8_t picture_coding_type; + uint16_t vbv_delay; + + uint8_t full_pel_forward_vector; + uint8_t forward_f_code; + uint8_t full_pel_backward_vector; + uint8_t backward_f_code; + + uint8_t extra_bit_picture; +} MPEG2RawPictureHeader; + +typedef struct MPEG2RawPictureCodingExtension { + uint8_t f_code[2][2]; + + uint8_t intra_dc_precision; + uint8_t picture_structure; + uint8_t top_field_first; + uint8_t frame_pred_frame_dct; + uint8_t concealment_motion_vectors; + uint8_t q_scale_type; + uint8_t intra_vlc_format; + uint8_t alternate_scan; + uint8_t repeat_first_field; + uint8_t chroma_420_type; + uint8_t progressive_frame; + + uint8_t composite_display_flag; + uint8_t v_axis; + uint8_t field_sequence; + uint8_t sub_carrier; + uint8_t burst_amplitude; + uint8_t sub_carrier_phase; +} MPEG2RawPictureCodingExtension; + +typedef struct MPEG2RawQuantMatrixExtension { + uint8_t load_intra_quantiser_matrix; + uint8_t intra_quantiser_matrix[64]; + uint8_t load_non_intra_quantiser_matrix; + uint8_t non_intra_quantiser_matrix[64]; + uint8_t load_chroma_intra_quantiser_matrix; + uint8_t chroma_intra_quantiser_matrix[64]; + uint8_t load_chroma_non_intra_quantiser_matrix; + uint8_t chroma_non_intra_quantiser_matrix[64]; +} MPEG2RawQuantMatrixExtension; + +typedef struct MPEG2RawExtensionData { + uint8_t extension_start_code; + uint8_t extension_start_code_identifier; + + union { + MPEG2RawSequenceExtension sequence; + MPEG2RawSequenceDisplayExtension sequence_display; + MPEG2RawPictureCodingExtension picture_coding; + MPEG2RawQuantMatrixExtension quant_matrix; + }; +} MPEG2RawExtensionData; + +typedef struct MPEG2RawSliceHeader { + uint8_t slice_vertical_position; + + uint8_t slice_vertical_position_extension; + uint8_t priority_breakpoint; + + uint8_t quantiser_scale_code; + + uint8_t slice_extension_flag; + uint8_t intra_slice; + uint8_t slice_picture_id_enable; + uint8_t slice_picture_id; + + uint8_t extra_bit_slice; + + size_t extra_information_length; + uint8_t *extra_information; +} MPEG2RawSliceHeader; + +typedef struct MPEG2RawSlice { + MPEG2RawSliceHeader header; + + uint8_t *data; + size_t data_size; + int data_bit_start; +} MPEG2RawSlice; + + +typedef struct CodedBitstreamMPEG2Context { + // Elements stored in headers which are required for other decoding. + uint16_t horizontal_size; + uint16_t vertical_size; + uint8_t scalable; + uint8_t scalable_mode; +} CodedBitstreamMPEG2Context; + + +#endif /* AVCODEC_CBS_MPEG2_H */ diff --git a/libavcodec/cbs_mpeg2_syntax.c b/libavcodec/cbs_mpeg2_syntax.c new file mode 100644 index 000000000..89d9d8746 --- /dev/null +++ b/libavcodec/cbs_mpeg2_syntax.c @@ -0,0 +1,367 @@ +/* + * This file is part of Libav. + * + * Libav 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. + * + * Libav 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 Libav; 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); + + ui(12, horizontal_size_value); + ui(12, vertical_size_value); + + mpeg2->horizontal_size = current->horizontal_size_value; + mpeg2->vertical_size = current->vertical_size_value; + + ui(4, aspect_ratio_information); + ui(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++) + ui(8, intra_quantiser_matrix[i]); + } + + ui(1, load_non_intra_quantiser_matrix); + if (current->load_non_intra_quantiser_matrix) { + for (i = 0; i < 64; i++) + ui(8, non_intra_quantiser_matrix[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 = bitstream_bits_left(rw); + av_assert0(k % 8 == 0); + current->user_data_length = k /= 8; + if (k > 0) { + current->user_data = av_malloc(k); + if (!current->user_data) + return AVERROR(ENOMEM); + } +#endif + + for (k = 0; k < current->user_data_length; k++) + xui(8, user_data, current->user_data[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; + + 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) { + ui(8, colour_primaries); + ui(8, transfer_characteristics); + ui(8, matrix_coefficients); + } + + 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(picture_header)(CodedBitstreamContext *ctx, RWContext *rw, + MPEG2RawPictureHeader *current) +{ + int err; + + HEADER("Picture Header"); + + ui(8, picture_start_code); + + ui(10, temporal_reference); + ui(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); + } + + ui(1, extra_bit_picture); + + return 0; +} + +static int FUNC(picture_coding_extension)(CodedBitstreamContext *ctx, RWContext *rw, + MPEG2RawPictureCodingExtension *current) +{ + int err; + + HEADER("Picture Coding Extension"); + + ui(4, f_code[0][0]); + ui(4, f_code[0][1]); + ui(4, f_code[1][0]); + ui(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); + + 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++) + ui(8, intra_quantiser_matrix[i]); + } + + ui(1, load_non_intra_quantiser_matrix); + if (current->load_non_intra_quantiser_matrix) { + for (i = 0; i < 64; i++) + ui(8, non_intra_quantiser_matrix[i]); + } + + ui(1, load_chroma_intra_quantiser_matrix); + if (current->load_chroma_intra_quantiser_matrix) { + for (i = 0; i < 64; i++) + ui(8, intra_quantiser_matrix[i]); + } + + ui(1, load_chroma_non_intra_quantiser_matrix); + if (current->load_chroma_non_intra_quantiser_matrix) { + for (i = 0; i < 64; i++) + ui(8, chroma_non_intra_quantiser_matrix[i]); + } + + 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 1: + return FUNC(sequence_extension) + (ctx, rw, ¤t->sequence); + case 2: + return FUNC(sequence_display_extension) + (ctx, rw, ¤t->sequence_display); + case 3: + return FUNC(quant_matrix_extension) + (ctx, rw, ¤t->quant_matrix); + /* + case 4: + return FUNC(copyright_extension) + (ctx, rw, ¤t->copyright); + case 5: + return FUNC(sequence_scalable_extension) + (ctx, rw, ¤t->sequence_scalable); + + case 7: + return FUNC(picture_display_extension) + (ctx, rw, ¤t->picture_display); + */ + case 8: + return FUNC(picture_coding_extension) + (ctx, rw, ¤t->picture_coding); + /* + case 9: + return FUNC(picture_spatial_scalable_extension) + (ctx, rw, ¤t->picture_spatial_scalable); + case 10: + return FUNC(picture_temporal_scalable_extension) + (ctx, rw, ¤t->picture_temporal_scalable); + case 11: + return FUNC(camera_parameters_extension) + (ctx, rw, ¤t->camera_parameters); + case 12: + return FUNC(itu_t_extension) + (ctx, rw, ¤t->itu_t); + */ + + default: + av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid extension ID %d.\n", + current->extension_start_code_identifier); + return AVERROR_INVALIDDATA; + } +} + +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); + } + + ui(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); + + { + size_t k; +#ifdef READ + BitstreamContext start; + uint8_t bit; + start = *rw; + for (k = 0; nextbits(1, 1, bit); k++) + bitstream_skip(rw, 8); + current->extra_information_length = k; + if (k > 0) { + *rw = start; + current->extra_information = + av_malloc(current->extra_information_length); + if (!current->extra_information) + return AVERROR(ENOMEM); + for (k = 0; k < current->extra_information_length; k++) { + xui(1, extra_bit_slice, bit); + xui(8, extra_information_slice, + current->extra_information[k]); + } + } +#else + for (k = 0; k < current->extra_information_length; k++) { + xui(1, extra_bit_slice, 1); + xui(8, extra_information_slice, current->extra_information[k]); + } +#endif + } + } + ui(1, extra_bit_slice); + + return 0; +} -- 2.11.0 _______________________________________________ libav-devel mailing list libav-devel@libav.org https://lists.libav.org/mailman/listinfo/libav-devel