Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/FFmpeg/FFmpeg.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2017-05-19 11:44:59 +0300
committerAnton Khirnov <anton@khirnov.net>2020-04-10 16:52:22 +0300
commitec7f33a38e341807c0ff9530e4dc7e175a86f437 (patch)
treeecb68bac55d7bfd820da689579ccf4cd2b29f3f8 /libavcodec/h264_sei.c
parent1e9615c5d4d1697816037057133b20da4fd9e57b (diff)
h264_sei: parse the picture timing SEIs correctly
Those SEIs refer to the currently active SPS. However, since the SEI NALUs precede the coded picture data in the bitstream, the active SPS is in general not known when we are decoding the SEI. Therefore, store the content of the picture timing SEIs and actually parse it when the active SPS is known.
Diffstat (limited to 'libavcodec/h264_sei.c')
-rw-r--r--libavcodec/h264_sei.c82
1 files changed, 48 insertions, 34 deletions
diff --git a/libavcodec/h264_sei.c b/libavcodec/h264_sei.c
index 32d13985f3..870dd90717 100644
--- a/libavcodec/h264_sei.c
+++ b/libavcodec/h264_sei.c
@@ -54,30 +54,22 @@ void ff_h264_sei_uninit(H264SEIContext *h)
av_buffer_unref(&h->a53_caption.buf_ref);
}
-static int decode_picture_timing(H264SEIPictureTiming *h, GetBitContext *gb,
- const H264ParamSets *ps, void *logctx)
+int ff_h264_sei_process_picture_timing(H264SEIPictureTiming *h, const SPS *sps,
+ void *logctx)
{
- int i;
- const SPS *sps = ps->sps;
-
- for (i = 0; i<MAX_SPS_COUNT; i++)
- if ((!sps || !sps->log2_max_frame_num) && ps->sps_list[i])
- sps = (const SPS *)ps->sps_list[i]->data;
+ GetBitContext gb;
- if (!sps) {
- av_log(logctx, AV_LOG_ERROR, "SPS unavailable in decode_picture_timing\n");
- return AVERROR_PS_NOT_FOUND;
- }
+ init_get_bits(&gb, h->payload, h->payload_size_bits);
if (sps->nal_hrd_parameters_present_flag ||
sps->vcl_hrd_parameters_present_flag) {
- h->cpb_removal_delay = get_bits_long(gb, sps->cpb_removal_delay_length);
- h->dpb_output_delay = get_bits_long(gb, sps->dpb_output_delay_length);
+ h->cpb_removal_delay = get_bits_long(&gb, sps->cpb_removal_delay_length);
+ h->dpb_output_delay = get_bits_long(&gb, sps->dpb_output_delay_length);
}
if (sps->pic_struct_present_flag) {
unsigned int i, num_clock_ts;
- h->pic_struct = get_bits(gb, 4);
+ h->pic_struct = get_bits(&gb, 4);
h->ct_type = 0;
if (h->pic_struct > H264_SEI_PIC_STRUCT_FRAME_TRIPLING)
@@ -86,38 +78,38 @@ static int decode_picture_timing(H264SEIPictureTiming *h, GetBitContext *gb,
num_clock_ts = sei_num_clock_ts_table[h->pic_struct];
h->timecode_cnt = 0;
for (i = 0; i < num_clock_ts; i++) {
- if (get_bits(gb, 1)) { /* clock_timestamp_flag */
+ if (get_bits(&gb, 1)) { /* clock_timestamp_flag */
H264SEITimeCode *tc = &h->timecode[h->timecode_cnt++];
unsigned int full_timestamp_flag;
unsigned int counting_type, cnt_dropped_flag;
- h->ct_type |= 1 << get_bits(gb, 2);
- skip_bits(gb, 1); /* nuit_field_based_flag */
- counting_type = get_bits(gb, 5); /* counting_type */
- full_timestamp_flag = get_bits(gb, 1);
- skip_bits(gb, 1); /* discontinuity_flag */
- cnt_dropped_flag = get_bits(gb, 1); /* cnt_dropped_flag */
+ h->ct_type |= 1 << get_bits(&gb, 2);
+ skip_bits(&gb, 1); /* nuit_field_based_flag */
+ counting_type = get_bits(&gb, 5); /* counting_type */
+ full_timestamp_flag = get_bits(&gb, 1);
+ skip_bits(&gb, 1); /* discontinuity_flag */
+ cnt_dropped_flag = get_bits(&gb, 1); /* cnt_dropped_flag */
if (cnt_dropped_flag && counting_type > 1 && counting_type < 7)
tc->dropframe = 1;
- tc->frame = get_bits(gb, 8); /* n_frames */
+ tc->frame = get_bits(&gb, 8); /* n_frames */
if (full_timestamp_flag) {
tc->full = 1;
- tc->seconds = get_bits(gb, 6); /* seconds_value 0..59 */
- tc->minutes = get_bits(gb, 6); /* minutes_value 0..59 */
- tc->hours = get_bits(gb, 5); /* hours_value 0..23 */
+ tc->seconds = get_bits(&gb, 6); /* seconds_value 0..59 */
+ tc->minutes = get_bits(&gb, 6); /* minutes_value 0..59 */
+ tc->hours = get_bits(&gb, 5); /* hours_value 0..23 */
} else {
tc->seconds = tc->minutes = tc->hours = tc->full = 0;
- if (get_bits(gb, 1)) { /* seconds_flag */
- tc->seconds = get_bits(gb, 6);
- if (get_bits(gb, 1)) { /* minutes_flag */
- tc->minutes = get_bits(gb, 6);
- if (get_bits(gb, 1)) /* hours_flag */
- tc->hours = get_bits(gb, 5);
+ if (get_bits(&gb, 1)) { /* seconds_flag */
+ tc->seconds = get_bits(&gb, 6);
+ if (get_bits(&gb, 1)) { /* minutes_flag */
+ tc->minutes = get_bits(&gb, 6);
+ if (get_bits(&gb, 1)) /* hours_flag */
+ tc->hours = get_bits(&gb, 5);
}
}
}
if (sps->time_offset_length > 0)
- skip_bits(gb,
+ skip_bits(&gb,
sps->time_offset_length); /* time_offset */
}
}
@@ -126,6 +118,28 @@ static int decode_picture_timing(H264SEIPictureTiming *h, GetBitContext *gb,
h->ct_type, h->pic_struct);
}
+ return 0;
+}
+
+static int decode_picture_timing(H264SEIPictureTiming *h, GetBitContext *gb,
+ void *logctx)
+{
+ int index = get_bits_count(gb);
+ int size_bits = get_bits_left(gb);
+ int size = (size_bits + 7) / 8;
+
+ if (index & 7) {
+ av_log(logctx, AV_LOG_ERROR, "Unaligned SEI payload\n");
+ return AVERROR_INVALIDDATA;
+ }
+ if (size > sizeof(h->payload)) {
+ av_log(logctx, AV_LOG_ERROR, "Picture timing SEI payload too large\n");
+ return AVERROR_INVALIDDATA;
+ }
+ memcpy(h->payload, gb->buffer + index / 8, size);
+
+ h->payload_size_bits = size_bits;
+
h->present = 1;
return 0;
}
@@ -436,7 +450,7 @@ int ff_h264_sei_decode(H264SEIContext *h, GetBitContext *gb,
switch (type) {
case H264_SEI_TYPE_PIC_TIMING: // Picture timing SEI
- ret = decode_picture_timing(&h->picture_timing, &gb_payload, ps, logctx);
+ ret = decode_picture_timing(&h->picture_timing, &gb_payload, logctx);
break;
case H264_SEI_TYPE_USER_DATA_REGISTERED:
ret = decode_registered_user_data(h, &gb_payload, logctx, size);