}
static int FUNC(extension_data)(CodedBitstreamContext *ctx, RWContext *rw,
- H265RawPSExtensionData *current)
+ H265RawExtensionData *current)
{
int err;
size_t k;
}
#else
for (k = 0; k < current->bit_length; k++)
- xu(1, extension_data, current->data[k / 8] >> (7 - k % 8), 0, 1, 0);
+ xu(1, extension_data, current->data[k / 8] >> (7 - k % 8) & 1, 0, 1, 0);
#endif
return 0;
}
infer(inter_ref_pic_set_prediction_flag, 0);
if (current->inter_ref_pic_set_prediction_flag) {
- unsigned int ref_rps_idx, num_delta_pocs;
+ unsigned int ref_rps_idx, num_delta_pocs, num_ref_pics;
const H265RawSTRefPicSet *ref;
int delta_rps, d_poc;
int ref_delta_poc_s0[HEVC_MAX_REFS], ref_delta_poc_s1[HEVC_MAX_REFS];
ref_rps_idx = st_rps_idx - (current->delta_idx_minus1 + 1);
ref = &sps->st_ref_pic_set[ref_rps_idx];
num_delta_pocs = ref->num_negative_pics + ref->num_positive_pics;
+ av_assert0(num_delta_pocs < HEVC_MAX_DPB_SIZE);
flag(delta_rps_sign);
ue(abs_delta_rps_minus1, 0, INT16_MAX);
delta_rps = (1 - 2 * current->delta_rps_sign) *
(current->abs_delta_rps_minus1 + 1);
+ num_ref_pics = 0;
for (j = 0; j <= num_delta_pocs; j++) {
flags(used_by_curr_pic_flag[j], 1, j);
if (!current->used_by_curr_pic_flag[j])
flags(use_delta_flag[j], 1, j);
else
infer(use_delta_flag[j], 1);
+ if (current->use_delta_flag[j])
+ ++num_ref_pics;
+ }
+ if (num_ref_pics >= HEVC_MAX_DPB_SIZE) {
+ av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid stream: "
+ "short-term ref pic set %d "
+ "contains too many pictures.\n", st_rps_idx);
+ return AVERROR_INVALIDDATA;
}
// Since the stored form of an RPS here is actually the delta-step
return 0;
}
+static int FUNC(vui_parameters_default)(CodedBitstreamContext *ctx,
+ RWContext *rw, H265RawVUI *current,
+ H265RawSPS *sps)
+{
+ infer(aspect_ratio_idc, 0);
+
+ infer(video_format, 5);
+ infer(video_full_range_flag, 0);
+ infer(colour_primaries, 2);
+ infer(transfer_characteristics, 2);
+ infer(matrix_coefficients, 2);
+
+ infer(chroma_sample_loc_type_top_field, 0);
+ infer(chroma_sample_loc_type_bottom_field, 0);
+
+ infer(tiles_fixed_structure_flag, 0);
+ infer(motion_vectors_over_pic_boundaries_flag, 1);
+ infer(min_spatial_segmentation_idc, 0);
+ infer(max_bytes_per_pic_denom, 2);
+ infer(max_bits_per_min_cu_denom, 1);
+ infer(log2_max_mv_length_horizontal, 15);
+ infer(log2_max_mv_length_vertical, 15);
+
+ return 0;
+}
+
static int FUNC(sps)(CodedBitstreamContext *ctx, RWContext *rw,
H265RawSPS *current)
{
flag(vui_parameters_present_flag);
if (current->vui_parameters_present_flag)
CHECK(FUNC(vui_parameters)(ctx, rw, ¤t->vui, current));
+ else
+ CHECK(FUNC(vui_parameters_default)(ctx, rw, ¤t->vui, current));
flag(sps_extension_present_flag);
if (current->sps_extension_present_flag) {
flag(first_slice_segment_in_pic_flag);
if (current->nal_unit_header.nal_unit_type >= HEVC_NAL_BLA_W_LP &&
- current->nal_unit_header.nal_unit_type <= HEVC_NAL_IRAP_VCL23)
+ current->nal_unit_header.nal_unit_type <= HEVC_NAL_RSV_IRAP_VCL23)
flag(no_output_of_prior_pics_flag);
ue(slice_pic_parameter_set_id, 0, 63);
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);
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])
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_LONG_TERM_REF_PICS);
+ ue(num_long_term_pics, 0, dpb_slots_remaining);
for (i = 0; i < current->num_long_term_sps +
current->num_long_term_pics; i++) {
return 0;
}
-static int FUNC(sei_buffering_period)(CodedBitstreamContext *ctx, RWContext *rw,
- H265RawSEIBufferingPeriod *current,
- uint32_t *payload_size)
+static int FUNC(sei_buffering_period)
+ (CodedBitstreamContext *ctx, RWContext *rw,
+ H265RawSEIBufferingPeriod *current, SEIMessageState *sei)
{
CodedBitstreamH265Context *h265 = ctx->priv_data;
const H265RawSPS *sps;
int err, i, length;
#ifdef READ
- int start_pos, end_pos, bits_left;
+ int start_pos, end_pos;
start_pos = get_bits_count(rw);
#endif
}
#ifdef READ
- // payload_extension_present() - true if we are before the last 1-bit
- // in the payload structure, which must be in the last byte.
end_pos = get_bits_count(rw);
- bits_left = *payload_size * 8 - (end_pos - start_pos);
- if (bits_left > 0 &&
- (bits_left > 7 || ff_ctz(show_bits(rw, bits_left)) < bits_left - 1))
+ if (cbs_h265_payload_extension_present(rw, sei->payload_size,
+ end_pos - start_pos))
flag(use_alt_cpb_params_flag);
else
infer(use_alt_cpb_params_flag, 0);
#else
- if (current->use_alt_cpb_params_flag)
+ // 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 || 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.
+ 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;
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;
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;
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;
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;
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;
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;
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)
+static int FUNC(sei_alpha_channel_info)
+ (CodedBitstreamContext *ctx, RWContext *rw,
+ H265RawSEIAlphaChannelInfo *current, SEIMessageState *sei)
{
- 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_payload)(CodedBitstreamContext *ctx, RWContext *rw,
- H265RawSEIPayload *current, int prefix)
-{
- int err, i;
- int start_position, end_position;
-
-#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
-
- SEI_TYPE_S(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);
-
-#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);
- }
- }
-
- if (byte_alignment(rw)) {
- fixed(1, bit_equal_to_one, 1);
- while (byte_alignment(rw))
- fixed(1, bit_equal_to_zero, 0);
- }
-
-#ifdef READ
- end_position = get_bits_count(rw);
- if (end_position < start_position + 8 * current->payload_size) {
- av_log(ctx->log_ctx, AV_LOG_ERROR, "Incorrect SEI payload length: "
- "header %"PRIu32" bits, actually %d bits.\n",
- 8 * current->payload_size,
- end_position - start_position);
- return AVERROR_INVALIDDATA;
+ int err, length;
+
+ HEADER("Alpha Channel Information");
+
+ flag(alpha_channel_cancel_flag);
+ if (!current->alpha_channel_cancel_flag) {
+ ub(3, alpha_channel_use_idc);
+ ub(3, alpha_channel_bit_depth_minus8);
+ length = current->alpha_channel_bit_depth_minus8 + 9;
+ ub(length, alpha_transparent_value);
+ ub(length, alpha_opaque_value);
+ flag(alpha_channel_incr_flag);
+ flag(alpha_channel_clip_flag);
+ if (current->alpha_channel_clip_flag)
+ flag(alpha_channel_clip_type_flag);
+ } else {
+ infer(alpha_channel_use_idc, 2);
+ infer(alpha_channel_incr_flag, 0);
+ infer(alpha_channel_clip_flag, 0);
}
-#else
- end_position = put_bits_count(rw);
- current->payload_size = (end_position - 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");
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;
-
- 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;
- }
- current->payload_count = k + 1;
-#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));