lavc: Add coded bitstream read/write support for MPEG-2

Also enable MPEG-2 support in the trace_headers filter.
This commit is contained in:
Mark Thompson 2017-05-04 23:03:03 +01:00
parent 768eb9182e
commit 2bc9ba8d3c
9 changed files with 975 additions and 2 deletions

4
configure vendored
View File

@ -1742,6 +1742,7 @@ CONFIG_EXTRA="
cbs cbs
cbs_h264 cbs_h264
cbs_h265 cbs_h265
cbs_mpeg2
dirac_parse dirac_parse
dvprofile dvprofile
faandct faandct
@ -1970,6 +1971,7 @@ threads_if_any="$THREADS_LIST"
# subsystems # subsystems
cbs_h264_select="cbs golomb" cbs_h264_select="cbs golomb"
cbs_h265_select="cbs golomb" cbs_h265_select="cbs golomb"
cbs_mpeg2_select="cbs"
dct_select="rdft" dct_select="rdft"
dirac_parse_select="golomb" dirac_parse_select="golomb"
error_resilience_select="me_cmp" error_resilience_select="me_cmp"
@ -2327,7 +2329,7 @@ h264_metadata_bsf_select="cbs_h264"
h264_redundant_pps_bsf_select="cbs_h264" h264_redundant_pps_bsf_select="cbs_h264"
hevc_metadata_bsf_select="cbs_h265" hevc_metadata_bsf_select="cbs_h265"
mjpeg2jpeg_bsf_select="jpegtables" mjpeg2jpeg_bsf_select="jpegtables"
trace_headers_bsf_select="cbs_h264 cbs_h265" trace_headers_bsf_select="cbs_h264 cbs_h265 cbs_mpeg2"
# external libraries # external libraries
avisynth_deps="LoadLibrary" avisynth_deps="LoadLibrary"

View File

@ -227,7 +227,7 @@ Log trace output containing all syntax elements in the coded stream
headers (everything above the level of individual coded blocks). headers (everything above the level of individual coded blocks).
This can be useful for debugging low-level stream issues. This can be useful for debugging low-level stream issues.
Supports H.264 and H.265. Supports H.264, H.265 and MPEG-2.
@section vp9_superframe @section vp9_superframe

View File

@ -56,6 +56,7 @@ OBJS-$(CONFIG_CABAC) += cabac.o
OBJS-$(CONFIG_CBS) += cbs.o OBJS-$(CONFIG_CBS) += cbs.o
OBJS-$(CONFIG_CBS_H264) += cbs_h2645.o h2645_parse.o OBJS-$(CONFIG_CBS_H264) += cbs_h2645.o h2645_parse.o
OBJS-$(CONFIG_CBS_H265) += cbs_h2645.o h2645_parse.o OBJS-$(CONFIG_CBS_H265) += cbs_h2645.o h2645_parse.o
OBJS-$(CONFIG_CBS_MPEG2) += cbs_mpeg2.o
OBJS-$(CONFIG_DCT) += dct.o dct32_fixed.o dct32_float.o OBJS-$(CONFIG_DCT) += dct.o dct32_fixed.o dct32_float.o
OBJS-$(CONFIG_ERROR_RESILIENCE) += error_resilience.o OBJS-$(CONFIG_ERROR_RESILIENCE) += error_resilience.o
OBJS-$(CONFIG_FAANDCT) += faandct.o OBJS-$(CONFIG_FAANDCT) += faandct.o

View File

@ -34,6 +34,9 @@ static const CodedBitstreamType *cbs_type_table[] = {
#if CONFIG_CBS_H265 #if CONFIG_CBS_H265
&ff_cbs_type_h265, &ff_cbs_type_h265,
#endif #endif
#if CONFIG_CBS_MPEG2
&ff_cbs_type_mpeg2,
#endif
}; };
int ff_cbs_init(CodedBitstreamContext *ctx, int ff_cbs_init(CodedBitstreamContext *ctx,

View File

@ -82,6 +82,7 @@ int ff_cbs_write_unsigned(CodedBitstreamContext *ctx, PutBitContext *pbc,
extern const CodedBitstreamType ff_cbs_type_h264; extern const CodedBitstreamType ff_cbs_type_h264;
extern const CodedBitstreamType ff_cbs_type_h265; extern const CodedBitstreamType ff_cbs_type_h265;
extern const CodedBitstreamType ff_cbs_type_mpeg2;
#endif /* AVCODEC_CBS_INTERNAL_H */ #endif /* AVCODEC_CBS_INTERNAL_H */

409
libavcodec/cbs_mpeg2.c Normal file
View File

@ -0,0 +1,409 @@
/*
* 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_template.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_template.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;
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;
// The start and end pointers point at to the byte following the
// start_code_identifier in the start code that they found.
if (end == frag->data + frag->data_size) {
// We didn't find a start code, so this is the final unit.
unit_size = end - (start - 1);
} else {
// Unit runs from start to the beginning of the start code
// pointed to by end (including any padding zeroes).
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) {
av_freep(&unit_data);
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 (MPEG2_START_IS_SLICE(unit->type)) {
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_header(CodedBitstreamContext *ctx,
CodedBitstreamUnit *unit,
PutBitContext *pbc)
{
int err;
switch (unit->type) {
#define START(start_code, type, func) \
case start_code: \
err = cbs_mpeg2_write_ ## func(ctx, pbc, unit->content); \
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);
return AVERROR_PATCHWELCOME;
}
return err;
}
static int cbs_mpeg2_write_slice(CodedBitstreamContext *ctx,
CodedBitstreamUnit *unit,
PutBitContext *pbc)
{
MPEG2RawSlice *slice = unit->content;
BitstreamContext bc;
size_t bits_left;
int err;
err = cbs_mpeg2_write_slice_header(ctx, pbc, &slice->header);
if (err < 0)
return err;
if (slice->data) {
if (slice->data_size * 8 + 8 > put_bits_left(pbc))
return AVERROR(ENOSPC);
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);
}
return 0;
}
static int cbs_mpeg2_write_unit(CodedBitstreamContext *ctx,
CodedBitstreamUnit *unit)
{
CodedBitstreamMPEG2Context *priv = ctx->priv_data;
PutBitContext pbc;
int err;
if (!priv->write_buffer) {
// Initial write buffer size is 1MB.
priv->write_buffer_size = 1024 * 1024;
reallocate_and_try_again:
err = av_reallocp(&priv->write_buffer, priv->write_buffer_size);
if (err < 0) {
av_log(ctx->log_ctx, AV_LOG_ERROR, "Unable to allocate a "
"sufficiently large write buffer (last attempt "
"%zu bytes).\n", priv->write_buffer_size);
return err;
}
}
init_put_bits(&pbc, priv->write_buffer, priv->write_buffer_size);
if (unit->type >= 0x01 && unit->type <= 0xaf)
err = cbs_mpeg2_write_slice(ctx, unit, &pbc);
else
err = cbs_mpeg2_write_header(ctx, unit, &pbc);
if (err == AVERROR(ENOSPC)) {
// Overflow.
priv->write_buffer_size *= 2;
goto reallocate_and_try_again;
}
if (err < 0) {
// Write failed for some other reason.
return err;
}
if (put_bits_count(&pbc) % 8)
unit->data_bit_padding = 8 - put_bits_count(&pbc) % 8;
else
unit->data_bit_padding = 0;
unit->data_size = (put_bits_count(&pbc) + 7) / 8;
flush_put_bits(&pbc);
err = av_reallocp(&unit->data, unit->data_size);
if (err < 0)
return err;
memcpy(unit->data, priv->write_buffer, unit->data_size);
return 0;
}
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)
{
if (MPEG2_START_IS_SLICE(unit->type)) {
MPEG2RawSlice *slice = unit->content;
av_freep(&slice->data);
av_freep(&slice->header.extra_information);
} else if (unit->type == MPEG2_START_USER_DATA) {
MPEG2RawUserData *user = unit->content;
av_freep(&user->user_data);
}
av_freep(&unit->content);
}
static void cbs_mpeg2_close(CodedBitstreamContext *ctx)
{
CodedBitstreamMPEG2Context *priv = ctx->priv_data;
av_freep(&priv->write_buffer);
}
const CodedBitstreamType ff_cbs_type_mpeg2 = {
.codec_id = AV_CODEC_ID_MPEG2VIDEO,
.priv_data_size = 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,
.close = &cbs_mpeg2_close,
};

216
libavcodec/cbs_mpeg2.h Normal file
View File

@ -0,0 +1,216 @@
/*
* 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,
};
#define MPEG2_START_IS_SLICE(type) \
((type) >= MPEG2_START_SLICE_MIN && \
(type) <= MPEG2_START_SLICE_MAX)
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;
} 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;
// Write buffer.
uint8_t *write_buffer;
size_t write_buffer_size;
} CodedBitstreamMPEG2Context;
#endif /* AVCODEC_CBS_MPEG2_H */

View File

@ -0,0 +1,340 @@
/*
* 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, &current->data.sequence);
case 2:
return FUNC(sequence_display_extension)
(ctx, rw, &current->data.sequence_display);
case 3:
return FUNC(quant_matrix_extension)
(ctx, rw, &current->data.quant_matrix);
case 8:
return FUNC(picture_coding_extension)
(ctx, rw, &current->data.picture_coding);
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;
}

View File

@ -112,6 +112,7 @@ static int trace_headers(AVBSFContext *bsf, AVPacket *out)
static const enum AVCodecID trace_headers_codec_ids[] = { static const enum AVCodecID trace_headers_codec_ids[] = {
AV_CODEC_ID_H264, AV_CODEC_ID_H264,
AV_CODEC_ID_HEVC, AV_CODEC_ID_HEVC,
AV_CODEC_ID_MPEG2VIDEO,
AV_CODEC_ID_NONE, AV_CODEC_ID_NONE,
}; };