h266parse: Parse and process SEI registered user data
Similar to h264parse and h265parse, this patch improves the element to parse the SEI registered user data from NAL units. The core structure of H266 SEI for ITU-T T.35 is the same as the other parsers, so we can re-use the same logic. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/9365>
This commit is contained in:
parent
65c88ff18f
commit
e44bab9fe9
@ -11,6 +11,6 @@ variables:
|
||||
|
||||
CHECKS_TAG: '2025-05-24.0'
|
||||
|
||||
ABI_CHECK_TAG: '2025-07-12.0'
|
||||
ABI_CHECK_TAG: '2025-07-15.0'
|
||||
|
||||
WINDOWS_TAG: '2025-06-30.0'
|
||||
|
@ -1512,6 +1512,55 @@ error:
|
||||
return GST_H266_PARSER_ERROR;
|
||||
}
|
||||
|
||||
static GstH266ParserResult
|
||||
gst_h266_parser_parse_registered_user_data (GstH266Parser * parser,
|
||||
GstH266RegisteredUserData * rud, NalReader * nr, guint payload_size)
|
||||
{
|
||||
guint8 *data = NULL;
|
||||
guint i;
|
||||
|
||||
rud->data = NULL;
|
||||
rud->size = 0;
|
||||
|
||||
if (payload_size < 2) {
|
||||
GST_WARNING ("Too small payload size %d", payload_size);
|
||||
return GST_H266_PARSER_BROKEN_DATA;
|
||||
}
|
||||
|
||||
READ_UINT8 (nr, rud->country_code, 8);
|
||||
--payload_size;
|
||||
|
||||
if (rud->country_code == 0xFF) {
|
||||
READ_UINT8 (nr, rud->country_code_extension, 8);
|
||||
--payload_size;
|
||||
} else {
|
||||
rud->country_code_extension = 0;
|
||||
}
|
||||
|
||||
if (payload_size < 1) {
|
||||
GST_WARNING ("No more remaining payload data to store");
|
||||
return GST_H266_PARSER_BROKEN_DATA;
|
||||
}
|
||||
|
||||
data = g_malloc (payload_size);
|
||||
for (i = 0; i < payload_size; ++i) {
|
||||
READ_UINT8 (nr, data[i], 8);
|
||||
}
|
||||
|
||||
GST_MEMDUMP ("SEI user data", data, payload_size);
|
||||
|
||||
rud->data = data;
|
||||
rud->size = payload_size;
|
||||
return GST_H266_PARSER_OK;
|
||||
|
||||
error:
|
||||
{
|
||||
GST_WARNING ("error parsing \"Registered User Data\"");
|
||||
g_free (data);
|
||||
return GST_H266_PARSER_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
static GstH266ParserResult
|
||||
gst_h266_parser_parse_du_info (GstH266DUInfo * dui, NalReader * nr,
|
||||
const GstH266BufferingPeriod * bp, guint8 TemporalId)
|
||||
@ -5818,6 +5867,10 @@ gst_h266_parser_parse_sei_message (GstH266SEIMessage * sei, NalReader * nr,
|
||||
res = gst_h266_parser_parse_pic_timing (&sei->payload.pic_timing, nr,
|
||||
&parser->buffering_period.payload.buffering_period, nal_tid);
|
||||
break;
|
||||
case GST_H266_SEI_REGISTERED_USER_DATA:
|
||||
res = gst_h266_parser_parse_registered_user_data (parser,
|
||||
&sei->payload.registered_user_data, nr, payload_size >> 3);
|
||||
break;
|
||||
case GST_H266_SEI_DU_INFO:
|
||||
if (!parser->last_buffering_period) {
|
||||
GST_WARNING ("No buffering_period SEI.");
|
||||
|
@ -448,6 +448,7 @@ typedef struct _GstH266DCI GstH266DCI;
|
||||
|
||||
typedef struct _GstH266BufferingPeriod GstH266BufferingPeriod;
|
||||
typedef struct _GstH266PicTiming GstH266PicTiming;
|
||||
typedef struct _GstH266RegisteredUserData GstH266RegisteredUserData;
|
||||
typedef struct _GstH266DUInfo GstH266DUInfo;
|
||||
typedef struct _GstH266ScalableNesting GstH266ScalableNesting;
|
||||
typedef struct _GstH266SubPicLevelInfo GstH266SubPicLevelInfo;
|
||||
@ -3072,6 +3073,28 @@ struct _GstH266PicTiming {
|
||||
guint8 display_elemental_periods_minus1;
|
||||
};
|
||||
|
||||
/**
|
||||
* GstH266RegisteredUserData:
|
||||
*
|
||||
* The User data registered by Rec. ITU-T T.35 SEI message.
|
||||
*
|
||||
* @country_code: an itu_t_t35_country_code.
|
||||
* @country_code_extension: an itu_t_t35_country_code_extension_byte.
|
||||
* Should be ignored when @country_code is not 0xff
|
||||
* @size: the size of @data in bytes
|
||||
* @data: the data of itu_t_t35_payload_byte
|
||||
* excluding @country_code and @country_code_extension
|
||||
*
|
||||
* Since: 1.28
|
||||
*/
|
||||
struct _GstH266RegisteredUserData
|
||||
{
|
||||
guint8 country_code;
|
||||
guint8 country_code_extension;
|
||||
guint size;
|
||||
const guint8 *data;
|
||||
};
|
||||
|
||||
/**
|
||||
* GstH266DUInfo:
|
||||
*
|
||||
@ -3232,6 +3255,7 @@ struct _GstH266FrameFieldInfo {
|
||||
* @scalable_nesting: scalable nesting sei of #GstH266ScalableNesting.
|
||||
* @subpic_level_info: subpicture level info sei of #GstH266SubPicLevelInfo.
|
||||
* @frame_field_info: frame field info sei of #GstH266FrameFieldInfo.
|
||||
* @registered_user_data: registered user data sei of #GstH266RegisteredUserData. (Since: 1.28)
|
||||
*
|
||||
* Since: 1.26
|
||||
*/
|
||||
@ -3247,7 +3271,19 @@ struct _GstH266SEIMessage
|
||||
GstH266SubPicLevelInfo subpic_level_info;
|
||||
GstH266FrameFieldInfo frame_field_info;
|
||||
|
||||
/**
|
||||
* _GstH266SEIMessage.payload.registered_user_data:
|
||||
*
|
||||
* Registered user data sei of #GstH266RegisteredUserData.
|
||||
*
|
||||
* Since: 1.28
|
||||
*/
|
||||
GstH266RegisteredUserData registered_user_data;
|
||||
|
||||
/* ... could implement more */
|
||||
|
||||
/*< private >*/
|
||||
gpointer padding[GST_PADDING_LARGE];
|
||||
} payload;
|
||||
};
|
||||
|
||||
|
@ -162,6 +162,10 @@ static gboolean gst_h266_parse_set_caps (GstBaseParse * parse, GstCaps * caps);
|
||||
static GstCaps *gst_h266_parse_get_caps (GstBaseParse * parse,
|
||||
GstCaps * filter);
|
||||
|
||||
static void
|
||||
gst_h266_parse_process_sei_user_data (GstH266Parse * h266parse,
|
||||
GstH266RegisteredUserData * rud);
|
||||
|
||||
static void
|
||||
gst_h266_parse_class_init (GstH266ParseClass * klass)
|
||||
{
|
||||
@ -618,6 +622,10 @@ gst_h266_parse_process_sei (GstH266Parse * h266parse, GstH266NalUnit * nalu)
|
||||
case GST_H266_SEI_SUBPIC_LEVEL_INFO:
|
||||
/* FIXME */
|
||||
break;
|
||||
case GST_H266_SEI_REGISTERED_USER_DATA:
|
||||
gst_h266_parse_process_sei_user_data (h266parse,
|
||||
&sei.payload.registered_user_data);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -3319,6 +3327,35 @@ gst_h266_parse_get_caps (GstBaseParse * parse, GstCaps * filter)
|
||||
return res;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_h266_parse_process_sei_user_data (GstH266Parse * h266parse,
|
||||
GstH266RegisteredUserData * rud)
|
||||
{
|
||||
guint16 provider_code;
|
||||
GstByteReader br;
|
||||
GstVideoParseUtilsField field = GST_VIDEO_PARSE_UTILS_FIELD_1;
|
||||
|
||||
/* only US and UK country codes are currently supported */
|
||||
switch (rud->country_code) {
|
||||
case ITU_T_T35_COUNTRY_CODE_US:
|
||||
break;
|
||||
default:
|
||||
GST_LOG_OBJECT (h266parse, "Unsupported country code %d",
|
||||
rud->country_code);
|
||||
return;
|
||||
}
|
||||
|
||||
if (rud->data == NULL || rud->size < 2)
|
||||
return;
|
||||
|
||||
gst_byte_reader_init (&br, rud->data, rud->size);
|
||||
|
||||
provider_code = gst_byte_reader_get_uint16_be_unchecked (&br);
|
||||
|
||||
gst_video_parse_user_data ((GstElement *) h266parse, &h266parse->user_data,
|
||||
&br, field, provider_code);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_h266_parse_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec)
|
||||
|
Loading…
x
Reference in New Issue
Block a user