Quoting Mark Thompson (2017-07-29 23:16:30) > --- > libavcodec/cbs.c | 1 + > libavcodec/cbs_internal.h | 1 + > libavcodec/cbs_mpeg2.c | 355 > ++++++++++++++++++++++++++++++++++++++++++ > libavcodec/cbs_mpeg2.h | 208 +++++++++++++++++++++++++ > libavcodec/cbs_mpeg2_syntax.c | 340 ++++++++++++++++++++++++++++++++++++++++ > 5 files changed, 905 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);
Are you sure this will not do anything untoward (like a zero or overflow in unit_size, or an infinite loop) for corrupted streams? The behaviour of avpriv_find_start_code() in such cases is not immediately obvious to me. > + > + 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) leaking unit_data? > +const CodedBitstreamType ff_cbs_type_mpeg2 = { > + .codec_id = AV_CODEC_ID_MPEG2VIDEO, > + > + .priv_data_size = 1, //sizeof(CodedBitstreamMPEG2Context), Already mentioned on IRC. > + > + .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..e031fa455 > --- /dev/null > +++ b/libavcodec/cbs_mpeg2.h > @@ -0,0 +1,208 @@ > +/* > + * 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 <stddef.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; > + MPEG2RawQuantMatrixExtension quant_matrix; > + MPEG2RawPictureCodingExtension picture_coding; > + } data; > +} 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; Does this get freed? Same for user_data. -- Anton Khirnov _______________________________________________ libav-devel mailing list libav-devel@libav.org https://lists.libav.org/mailman/listinfo/libav-devel