|
|
|
@@ -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); |
|
|
|
|