[FFmpeg-devel] [PATCH 4/4 v2] avcodec/cbs_h265: add missing support for reserved_payload_extension_data SEI bits
James Almer
jamrial at gmail.com
Fri Apr 24 03:15:36 EEST 2020
Fixes ticket #8622
Signed-off-by: James Almer <jamrial at gmail.com>
---
libavcodec/cbs_h2645.c | 1 +
libavcodec/cbs_h265.h | 1 +
libavcodec/cbs_h265_syntax_template.c | 62 +++++++++++++++++++++++++--
3 files changed, 60 insertions(+), 4 deletions(-)
diff --git a/libavcodec/cbs_h2645.c b/libavcodec/cbs_h2645.c
index a60b3217a0..a464b04161 100644
--- a/libavcodec/cbs_h2645.c
+++ b/libavcodec/cbs_h2645.c
@@ -552,6 +552,7 @@ static void cbs_h265_free_sei_payload(H265RawSEIPayload *payload)
av_buffer_unref(&payload->payload.other.data_ref);
break;
}
+ av_buffer_unref(&payload->extension_data.data_ref);
}
static void cbs_h265_free_sei(void *opaque, uint8_t *content)
diff --git a/libavcodec/cbs_h265.h b/libavcodec/cbs_h265.h
index 2c1e153ad9..73897f77a4 100644
--- a/libavcodec/cbs_h265.h
+++ b/libavcodec/cbs_h265.h
@@ -715,6 +715,7 @@ typedef struct H265RawSEIPayload {
AVBufferRef *data_ref;
} other;
} payload;
+ H265RawExtensionData extension_data;
} H265RawSEIPayload;
typedef struct H265RawSEI {
diff --git a/libavcodec/cbs_h265_syntax_template.c b/libavcodec/cbs_h265_syntax_template.c
index 96b9acc1dc..2057527b1a 100644
--- a/libavcodec/cbs_h265_syntax_template.c
+++ b/libavcodec/cbs_h265_syntax_template.c
@@ -1560,6 +1560,7 @@ static int FUNC(slice_segment_header)(CodedBitstreamContext *ctx, RWContext *rw,
static int FUNC(sei_buffering_period)(CodedBitstreamContext *ctx, RWContext *rw,
H265RawSEIBufferingPeriod *current,
+ H265RawExtensionData *extension_data,
uint32_t *payload_size)
{
CodedBitstreamH265Context *h265 = ctx->priv_data;
@@ -1656,7 +1657,9 @@ static int FUNC(sei_buffering_period)(CodedBitstreamContext *ctx, RWContext *rw,
else
infer(use_alt_cpb_params_flag, 0);
#else
- if (current->use_alt_cpb_params_flag)
+ // If 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 || extension_data->bit_length)
flag(use_alt_cpb_params_flag);
#endif
@@ -2055,11 +2058,47 @@ 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, end_position;
+ int start_position, current_position, end_position;
#ifdef READ
start_position = get_bits_count(rw);
@@ -2091,8 +2130,15 @@ static int FUNC(sei_payload)(CodedBitstreamContext *ctx, RWContext *rw,
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->extension_data, \
+ ¤t->payload_size)); \
+ break
- SEI_TYPE_S(BUFFERING_PERIOD, 1, 0, buffering_period);
+ 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,
@@ -2123,7 +2169,15 @@ static int FUNC(sei_payload)(CodedBitstreamContext *ctx, RWContext *rw,
}
}
- if (byte_alignment(rw)) {
+#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) || current->extension_data.bit_length) {
+#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);
--
2.26.2
More information about the ffmpeg-devel
mailing list