X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fcbs_h265_syntax_template.c;h=5d216aad3655f6a8aba8c4f6db24227f9900584d;hb=985c0dac674846721ec8ff23344c16ac7d1c9a1e;hp=48fae82d048fad35495810d9198cd2de0d776685;hpb=d1c55fc46019229b5526768ffdb0e1e67beb21ff;p=ffmpeg diff --git a/libavcodec/cbs_h265_syntax_template.c b/libavcodec/cbs_h265_syntax_template.c index 48fae82d048..5d216aad365 100644 --- a/libavcodec/cbs_h265_syntax_template.c +++ b/libavcodec/cbs_h265_syntax_template.c @@ -1369,6 +1369,7 @@ static int FUNC(slice_segment_header)(CodedBitstreamContext *ctx, RWContext *rw, if (current->nal_unit_header.nal_unit_type != HEVC_NAL_IDR_W_RADL && current->nal_unit_header.nal_unit_type != HEVC_NAL_IDR_N_LP) { const H265RawSTRefPicSet *rps; + int dpb_slots_remaining; ub(sps->log2_max_pic_order_cnt_lsb_minus4 + 4, slice_pic_order_cnt_lsb); @@ -1387,6 +1388,22 @@ static int FUNC(slice_segment_header)(CodedBitstreamContext *ctx, RWContext *rw, rps = &sps->st_ref_pic_set[0]; } + dpb_slots_remaining = HEVC_MAX_DPB_SIZE - 1 - + rps->num_negative_pics - rps->num_positive_pics; + if (pps->pps_curr_pic_ref_enabled_flag && + (sps->sample_adaptive_offset_enabled_flag || + !pps->pps_deblocking_filter_disabled_flag || + pps->deblocking_filter_override_enabled_flag)) { + // This picture will occupy two DPB slots. + if (dpb_slots_remaining == 0) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid stream: " + "short-term ref pic set contains too many pictures " + "to use with current picture reference enabled.\n"); + return AVERROR_INVALIDDATA; + } + --dpb_slots_remaining; + } + num_pic_total_curr = 0; for (i = 0; i < rps->num_negative_pics; i++) if (rps->used_by_curr_pic_s0_flag[i]) @@ -1399,13 +1416,15 @@ static int FUNC(slice_segment_header)(CodedBitstreamContext *ctx, RWContext *rw, unsigned int idx_size; if (sps->num_long_term_ref_pics_sps > 0) { - ue(num_long_term_sps, 0, sps->num_long_term_ref_pics_sps); + ue(num_long_term_sps, 0, FFMIN(sps->num_long_term_ref_pics_sps, + dpb_slots_remaining)); idx_size = av_log2(sps->num_long_term_ref_pics_sps - 1) + 1; + dpb_slots_remaining -= current->num_long_term_sps; } else { infer(num_long_term_sps, 0); idx_size = 0; } - ue(num_long_term_pics, 0, HEVC_MAX_REFS - current->num_long_term_sps); + ue(num_long_term_pics, 0, dpb_slots_remaining); for (i = 0; i < current->num_long_term_sps + current->num_long_term_pics; i++) { @@ -1596,10 +1615,9 @@ static int FUNC(slice_segment_header)(CodedBitstreamContext *ctx, RWContext *rw, return 0; } -static int FUNC(sei_buffering_period)(CodedBitstreamContext *ctx, RWContext *rw, - H265RawSEIBufferingPeriod *current, - uint32_t *payload_size, - int *more_data) +static int FUNC(sei_buffering_period) + (CodedBitstreamContext *ctx, RWContext *rw, + H265RawSEIBufferingPeriod *current, SEIMessageState *sei) { CodedBitstreamH265Context *h265 = ctx->priv_data; const H265RawSPS *sps; @@ -1687,7 +1705,7 @@ static int FUNC(sei_buffering_period)(CodedBitstreamContext *ctx, RWContext *rw, #ifdef READ end_pos = get_bits_count(rw); - if (cbs_h265_payload_extension_present(rw, *payload_size, + if (cbs_h265_payload_extension_present(rw, sei->payload_size, end_pos - start_pos)) flag(use_alt_cpb_params_flag); else @@ -1695,20 +1713,21 @@ static int FUNC(sei_buffering_period)(CodedBitstreamContext *ctx, RWContext *rw, #else // If unknown extension data exists, then use_alt_cpb_params_flag is // coded in the bitstream and must be written even if it's 0. - if (current->use_alt_cpb_params_flag || *more_data) { + if (current->use_alt_cpb_params_flag || sei->extension_present) { flag(use_alt_cpb_params_flag); // Ensure this bit is not the last in the payload by making the // more_data_in_payload() check evaluate to true, so it may not // be mistaken as something else by decoders. - *more_data = 1; + sei->extension_present = 1; } #endif return 0; } -static int FUNC(sei_pic_timing)(CodedBitstreamContext *ctx, RWContext *rw, - H265RawSEIPicTiming *current) +static int FUNC(sei_pic_timing) + (CodedBitstreamContext *ctx, RWContext *rw, + H265RawSEIPicTiming *current, SEIMessageState *sei) { CodedBitstreamH265Context *h265 = ctx->priv_data; const H265RawSPS *sps; @@ -1782,8 +1801,9 @@ static int FUNC(sei_pic_timing)(CodedBitstreamContext *ctx, RWContext *rw, return 0; } -static int FUNC(sei_pan_scan_rect)(CodedBitstreamContext *ctx, RWContext *rw, - H265RawSEIPanScanRect *current) +static int FUNC(sei_pan_scan_rect) + (CodedBitstreamContext *ctx, RWContext *rw, + H265RawSEIPanScanRect *current, SEIMessageState *sei) { int err, i; @@ -1808,72 +1828,9 @@ static int FUNC(sei_pan_scan_rect)(CodedBitstreamContext *ctx, RWContext *rw, return 0; } -static int FUNC(sei_user_data_registered)(CodedBitstreamContext *ctx, RWContext *rw, - H265RawSEIUserDataRegistered *current, - uint32_t *payload_size) -{ - int err, i, j; - - HEADER("User Data Registered ITU-T T.35"); - - u(8, itu_t_t35_country_code, 0x00, 0xff); - if (current->itu_t_t35_country_code != 0xff) - i = 1; - else { - u(8, itu_t_t35_country_code_extension_byte, 0x00, 0xff); - i = 2; - } - -#ifdef READ - if (*payload_size < i) { - av_log(ctx->log_ctx, AV_LOG_ERROR, - "Invalid SEI user data registered payload.\n"); - return AVERROR_INVALIDDATA; - } - current->data_length = *payload_size - i; -#else - *payload_size = i + current->data_length; -#endif - - allocate(current->data, current->data_length); - for (j = 0; j < current->data_length; j++) - xu(8, itu_t_t35_payload_byte[i], current->data[j], 0x00, 0xff, 1, i + j); - - return 0; -} - -static int FUNC(sei_user_data_unregistered)(CodedBitstreamContext *ctx, RWContext *rw, - H265RawSEIUserDataUnregistered *current, - uint32_t *payload_size) -{ - int err, i; - - HEADER("User Data Unregistered"); - -#ifdef READ - if (*payload_size < 16) { - av_log(ctx->log_ctx, AV_LOG_ERROR, - "Invalid SEI user data unregistered payload.\n"); - return AVERROR_INVALIDDATA; - } - current->data_length = *payload_size - 16; -#else - *payload_size = 16 + current->data_length; -#endif - - for (i = 0; i < 16; i++) - us(8, uuid_iso_iec_11578[i], 0x00, 0xff, 1, i); - - allocate(current->data, current->data_length); - - for (i = 0; i < current->data_length; i++) - xu(8, user_data_payload_byte[i], current->data[i], 0x00, 0xff, 1, i); - - return 0; -} - -static int FUNC(sei_recovery_point)(CodedBitstreamContext *ctx, RWContext *rw, - H265RawSEIRecoveryPoint *current) +static int FUNC(sei_recovery_point) + (CodedBitstreamContext *ctx, RWContext *rw, + H265RawSEIRecoveryPoint *current, SEIMessageState *sei) { int err; @@ -1887,8 +1844,9 @@ static int FUNC(sei_recovery_point)(CodedBitstreamContext *ctx, RWContext *rw, return 0; } -static int FUNC(sei_display_orientation)(CodedBitstreamContext *ctx, RWContext *rw, - H265RawSEIDisplayOrientation *current) +static int FUNC(sei_display_orientation) + (CodedBitstreamContext *ctx, RWContext *rw, + H265RawSEIDisplayOrientation *current, SEIMessageState *sei) { int err; @@ -1905,8 +1863,9 @@ static int FUNC(sei_display_orientation)(CodedBitstreamContext *ctx, RWContext * return 0; } -static int FUNC(sei_active_parameter_sets)(CodedBitstreamContext *ctx, RWContext *rw, - H265RawSEIActiveParameterSets *current) +static int FUNC(sei_active_parameter_sets) + (CodedBitstreamContext *ctx, RWContext *rw, + H265RawSEIActiveParameterSets *current, SEIMessageState *sei) { CodedBitstreamH265Context *h265 = ctx->priv_data; const H265RawVPS *vps; @@ -1941,8 +1900,9 @@ static int FUNC(sei_active_parameter_sets)(CodedBitstreamContext *ctx, RWContext return 0; } -static int FUNC(sei_decoded_picture_hash)(CodedBitstreamContext *ctx, RWContext *rw, - H265RawSEIDecodedPictureHash *current) +static int FUNC(sei_decoded_picture_hash) + (CodedBitstreamContext *ctx, RWContext *rw, + H265RawSEIDecodedPictureHash *current, SEIMessageState *sei) { CodedBitstreamH265Context *h265 = ctx->priv_data; const H265RawSPS *sps = h265->active_sps; @@ -1972,8 +1932,9 @@ static int FUNC(sei_decoded_picture_hash)(CodedBitstreamContext *ctx, RWContext return 0; } -static int FUNC(sei_time_code)(CodedBitstreamContext *ctx, RWContext *rw, - H265RawSEITimeCode *current) +static int FUNC(sei_time_code) + (CodedBitstreamContext *ctx, RWContext *rw, + H265RawSEITimeCode *current, SEIMessageState *sei) { int err, i; @@ -2022,58 +1983,9 @@ static int FUNC(sei_time_code)(CodedBitstreamContext *ctx, RWContext *rw, return 0; } -static int FUNC(sei_mastering_display)(CodedBitstreamContext *ctx, RWContext *rw, - H265RawSEIMasteringDisplayColourVolume *current) -{ - int err, c; - - HEADER("Mastering Display Colour Volume"); - - for (c = 0; c < 3; c++) { - us(16, display_primaries_x[c], 0, 50000, 1, c); - us(16, display_primaries_y[c], 0, 50000, 1, c); - } - - u(16, white_point_x, 0, 50000); - u(16, white_point_y, 0, 50000); - - u(32, max_display_mastering_luminance, - 1, MAX_UINT_BITS(32)); - u(32, min_display_mastering_luminance, - 0, current->max_display_mastering_luminance - 1); - - return 0; -} - -static int FUNC(sei_content_light_level)(CodedBitstreamContext *ctx, RWContext *rw, - H265RawSEIContentLightLevelInfo *current) -{ - int err; - - HEADER("Content Light Level"); - - ub(16, max_content_light_level); - ub(16, max_pic_average_light_level); - - return 0; -} - -static int FUNC(sei_alternative_transfer_characteristics)(CodedBitstreamContext *ctx, - RWContext *rw, - H265RawSEIAlternativeTransferCharacteristics *current) -{ - int err; - - HEADER("Alternative Transfer Characteristics"); - - ub(8, preferred_transfer_characteristics); - - return 0; -} - -static int FUNC(sei_alpha_channel_info)(CodedBitstreamContext *ctx, - RWContext *rw, - H265RawSEIAlphaChannelInfo *current) +static int FUNC(sei_alpha_channel_info) + (CodedBitstreamContext *ctx, RWContext *rw, + H265RawSEIAlphaChannelInfo *current, SEIMessageState *sei) { int err, length; @@ -2099,144 +2011,10 @@ static int FUNC(sei_alpha_channel_info)(CodedBitstreamContext *ctx, return 0; } -static int FUNC(payload_extension)(CodedBitstreamContext *ctx, RWContext *rw, - H265RawExtensionData *current, uint32_t payload_size, - int cur_pos) -{ - int err; - size_t byte_length, k; - -#ifdef READ - GetBitContext tmp; - int bits_left, payload_zero_bits; - - if (!cbs_h265_payload_extension_present(rw, payload_size, cur_pos)) - return 0; - - bits_left = 8 * payload_size - cur_pos; - tmp = *rw; - if (bits_left > 8) - skip_bits_long(&tmp, bits_left - 8); - payload_zero_bits = get_bits(&tmp, FFMIN(bits_left, 8)); - if (!payload_zero_bits) - return AVERROR_INVALIDDATA; - payload_zero_bits = ff_ctz(payload_zero_bits); - current->bit_length = bits_left - payload_zero_bits - 1; - allocate(current->data, (current->bit_length + 7) / 8); -#endif - - byte_length = (current->bit_length + 7) / 8; - for (k = 0; k < byte_length; k++) { - int length = FFMIN(current->bit_length - k * 8, 8); - xu(length, reserved_payload_extension_data, current->data[k], - 0, MAX_UINT_BITS(length), 0); - } - - return 0; -} - -static int FUNC(sei_payload)(CodedBitstreamContext *ctx, RWContext *rw, - H265RawSEIPayload *current, int prefix) -{ - int err, i; - int start_position, current_position; - int more_data = !!current->extension_data.bit_length; - -#ifdef READ - start_position = get_bits_count(rw); -#else - start_position = put_bits_count(rw); -#endif - - switch (current->payload_type) { -#define SEI_TYPE_CHECK_VALID(name, prefix_valid, suffix_valid) do { \ - if (prefix && !prefix_valid) { \ - av_log(ctx->log_ctx, AV_LOG_ERROR, "SEI type %s invalid " \ - "as prefix SEI!\n", #name); \ - return AVERROR_INVALIDDATA; \ - } \ - if (!prefix && !suffix_valid) { \ - av_log(ctx->log_ctx, AV_LOG_ERROR, "SEI type %s invalid " \ - "as suffix SEI!\n", #name); \ - return AVERROR_INVALIDDATA; \ - } \ - } while (0) -#define SEI_TYPE_N(type, prefix_valid, suffix_valid, name) \ - case HEVC_SEI_TYPE_ ## type: \ - SEI_TYPE_CHECK_VALID(name, prefix_valid, suffix_valid); \ - CHECK(FUNC(sei_ ## name)(ctx, rw, ¤t->payload.name)); \ - break -#define SEI_TYPE_S(type, prefix_valid, suffix_valid, name) \ - case HEVC_SEI_TYPE_ ## type: \ - SEI_TYPE_CHECK_VALID(name, prefix_valid, suffix_valid); \ - CHECK(FUNC(sei_ ## name)(ctx, rw, ¤t->payload.name, \ - ¤t->payload_size)); \ - break -#define SEI_TYPE_E(type, prefix_valid, suffix_valid, name) \ - case HEVC_SEI_TYPE_ ## type: \ - SEI_TYPE_CHECK_VALID(name, prefix_valid, suffix_valid); \ - CHECK(FUNC(sei_ ## name)(ctx, rw, ¤t->payload.name, \ - ¤t->payload_size, \ - &more_data)); \ - break - - SEI_TYPE_E(BUFFERING_PERIOD, 1, 0, buffering_period); - SEI_TYPE_N(PICTURE_TIMING, 1, 0, pic_timing); - SEI_TYPE_N(PAN_SCAN_RECT, 1, 0, pan_scan_rect); - SEI_TYPE_S(USER_DATA_REGISTERED_ITU_T_T35, - 1, 1, user_data_registered); - SEI_TYPE_S(USER_DATA_UNREGISTERED, 1, 1, user_data_unregistered); - SEI_TYPE_N(RECOVERY_POINT, 1, 0, recovery_point); - SEI_TYPE_N(DISPLAY_ORIENTATION, 1, 0, display_orientation); - SEI_TYPE_N(ACTIVE_PARAMETER_SETS, 1, 0, active_parameter_sets); - SEI_TYPE_N(DECODED_PICTURE_HASH, 0, 1, decoded_picture_hash); - SEI_TYPE_N(TIME_CODE, 1, 0, time_code); - SEI_TYPE_N(MASTERING_DISPLAY_INFO, 1, 0, mastering_display); - SEI_TYPE_N(CONTENT_LIGHT_LEVEL_INFO, 1, 0, content_light_level); - SEI_TYPE_N(ALTERNATIVE_TRANSFER_CHARACTERISTICS, - 1, 0, alternative_transfer_characteristics); - SEI_TYPE_N(ALPHA_CHANNEL_INFO, 1, 0, alpha_channel_info); - -#undef SEI_TYPE - default: - { -#ifdef READ - current->payload.other.data_length = current->payload_size; -#endif - allocate(current->payload.other.data, current->payload.other.data_length); - - for (i = 0; i < current->payload_size; i++) - xu(8, payload_byte[i], current->payload.other.data[i], 0, 255, - 1, i); - } - } - - // more_data_in_payload() -#ifdef READ - current_position = get_bits_count(rw) - start_position; - if (current_position < 8 * current->payload_size) { -#else - current_position = put_bits_count(rw) - start_position; - if (byte_alignment(rw) || more_data) { -#endif - CHECK(FUNC(payload_extension)(ctx, rw, ¤t->extension_data, - current->payload_size, current_position)); - fixed(1, bit_equal_to_one, 1); - while (byte_alignment(rw)) - fixed(1, bit_equal_to_zero, 0); - } - -#ifdef WRITE - current->payload_size = (put_bits_count(rw) - start_position) >> 3; -#endif - - return 0; -} - static int FUNC(sei)(CodedBitstreamContext *ctx, RWContext *rw, H265RawSEI *current, int prefix) { - int err, k; + int err; if (prefix) HEADER("Prefix Supplemental Enhancement Information"); @@ -2247,72 +2025,7 @@ static int FUNC(sei)(CodedBitstreamContext *ctx, RWContext *rw, prefix ? HEVC_NAL_SEI_PREFIX : HEVC_NAL_SEI_SUFFIX)); -#ifdef READ - for (k = 0; k < H265_MAX_SEI_PAYLOADS; k++) { - uint32_t payload_type = 0; - uint32_t payload_size = 0; - uint32_t tmp; - - while (show_bits(rw, 8) == 0xff) { - fixed(8, ff_byte, 0xff); - payload_type += 255; - } - xu(8, last_payload_type_byte, tmp, 0, 254, 0); - payload_type += tmp; - - while (show_bits(rw, 8) == 0xff) { - fixed(8, ff_byte, 0xff); - payload_size += 255; - } - xu(8, last_payload_size_byte, tmp, 0, 254, 0); - payload_size += tmp; - - current->payload[k].payload_type = payload_type; - current->payload[k].payload_size = payload_size; - - current->payload_count++; - CHECK(FUNC(sei_payload)(ctx, rw, ¤t->payload[k], prefix)); - - if (!cbs_h2645_read_more_rbsp_data(rw)) - break; - } - if (k >= H265_MAX_SEI_PAYLOADS) { - av_log(ctx->log_ctx, AV_LOG_ERROR, "Too many payloads in " - "SEI message: found %d.\n", k); - return AVERROR_INVALIDDATA; - } -#else - for (k = 0; k < current->payload_count; k++) { - PutBitContext start_state; - uint32_t tmp; - int need_size, i; - - // Somewhat clumsy: we write the payload twice when - // we don't know the size in advance. This will mess - // with trace output, but is otherwise harmless. - start_state = *rw; - need_size = !current->payload[k].payload_size; - for (i = 0; i < 1 + need_size; i++) { - *rw = start_state; - - tmp = current->payload[k].payload_type; - while (tmp >= 255) { - fixed(8, ff_byte, 0xff); - tmp -= 255; - } - xu(8, last_payload_type_byte, tmp, 0, 254, 0); - - tmp = current->payload[k].payload_size; - while (tmp >= 255) { - fixed(8, ff_byte, 0xff); - tmp -= 255; - } - xu(8, last_payload_size_byte, tmp, 0, 254, 0); - - CHECK(FUNC(sei_payload)(ctx, rw, ¤t->payload[k], prefix)); - } - } -#endif + CHECK(FUNC_SEI(message_list)(ctx, rw, ¤t->message_list, prefix)); CHECK(FUNC(rbsp_trailing_bits)(ctx, rw));