X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fh264_sei.c;h=870dd90717ecdd657f7d1f1d0e9cdb68423bccee;hb=ba6cada92eb7c3446bfb1d4525031d405a052516;hp=d4eb9c0dab67c2bdf4802d2cdb0e7af62e4ee2d5;hpb=39278ff0de5b5e3397c22538978bffbb38ee099b;p=ffmpeg diff --git a/libavcodec/h264_sei.c b/libavcodec/h264_sei.c index d4eb9c0dab6..870dd90717e 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; ilog2_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; } @@ -247,14 +261,14 @@ static int decode_unregistered_user_data(H264SEIUnregistered *h, GetBitContext * uint8_t *user_data; int e, build, i; - if (size < 16 || size >= INT_MAX - 16) + if (size < 16 || size >= INT_MAX - 1) return AVERROR_INVALIDDATA; - user_data = av_malloc(16 + size + 1); + user_data = av_malloc(size + 1); if (!user_data) return AVERROR(ENOMEM); - for (i = 0; i < size + 16; i++) + for (i = 0; i < size; i++) user_data[i] = get_bits(gb, 8); user_data[i] = 0; @@ -407,9 +421,9 @@ int ff_h264_sei_decode(H264SEIContext *h, GetBitContext *gb, int master_ret = 0; while (get_bits_left(gb) > 16 && show_bits(gb, 16)) { + GetBitContext gb_payload; int type = 0; unsigned size = 0; - unsigned next; int ret = 0; do { @@ -429,35 +443,38 @@ int ff_h264_sei_decode(H264SEIContext *h, GetBitContext *gb, type, 8*size, get_bits_left(gb)); return AVERROR_INVALIDDATA; } - next = get_bits_count(gb) + 8 * size; + + ret = init_get_bits8(&gb_payload, gb->buffer + get_bits_count(gb) / 8, size); + if (ret < 0) + return ret; switch (type) { case H264_SEI_TYPE_PIC_TIMING: // Picture timing SEI - ret = decode_picture_timing(&h->picture_timing, gb, 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, logctx, size); + ret = decode_registered_user_data(h, &gb_payload, logctx, size); break; case H264_SEI_TYPE_USER_DATA_UNREGISTERED: - ret = decode_unregistered_user_data(&h->unregistered, gb, logctx, size); + ret = decode_unregistered_user_data(&h->unregistered, &gb_payload, logctx, size); break; case H264_SEI_TYPE_RECOVERY_POINT: - ret = decode_recovery_point(&h->recovery_point, gb, logctx); + ret = decode_recovery_point(&h->recovery_point, &gb_payload, logctx); break; case H264_SEI_TYPE_BUFFERING_PERIOD: - ret = decode_buffering_period(&h->buffering_period, gb, ps, logctx); + ret = decode_buffering_period(&h->buffering_period, &gb_payload, ps, logctx); break; case H264_SEI_TYPE_FRAME_PACKING: - ret = decode_frame_packing_arrangement(&h->frame_packing, gb); + ret = decode_frame_packing_arrangement(&h->frame_packing, &gb_payload); break; case H264_SEI_TYPE_DISPLAY_ORIENTATION: - ret = decode_display_orientation(&h->display_orientation, gb); + ret = decode_display_orientation(&h->display_orientation, &gb_payload); break; case H264_SEI_TYPE_GREEN_METADATA: - ret = decode_green_metadata(&h->green_metadata, gb); + ret = decode_green_metadata(&h->green_metadata, &gb_payload); break; case H264_SEI_TYPE_ALTERNATIVE_TRANSFER: - ret = decode_alternative_transfer(&h->alternative_transfer, gb); + ret = decode_alternative_transfer(&h->alternative_transfer, &gb_payload); break; default: av_log(logctx, AV_LOG_DEBUG, "unknown SEI type %d\n", type); @@ -467,10 +484,12 @@ int ff_h264_sei_decode(H264SEIContext *h, GetBitContext *gb, if (ret < 0) master_ret = ret; - skip_bits_long(gb, next - get_bits_count(gb)); + if (get_bits_left(&gb_payload) < 0) { + av_log(logctx, AV_LOG_WARNING, "SEI type %d overread by %d bits\n", + type, -get_bits_left(&gb_payload)); + } - // FIXME check bits here - align_get_bits(gb); + skip_bits_long(gb, 8 * size); } return master_ret;