mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-22 17:51:16 +00:00
h265parse: Parse SEI unregistered user data
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5070>
This commit is contained in:
parent
6b339b5d39
commit
dd47fa53d8
7 changed files with 177 additions and 3 deletions
|
@ -4,14 +4,14 @@ event segment: format=TIME, start=0:00:00.066666666, offset=0:00:00.000000000, s
|
|||
event tag: GstTagList-stream, taglist=(taglist)"taglist\,\ video-codec\=\(string\)\"H.265\\\ /\\\ HEVC\"\,\ encoder\=\(string\)x265\,\ bitrate\=\(uint\)1547698\;";
|
||||
event tag: GstTagList-global, taglist=(taglist)"taglist\,\ datetime\=\(datetime\)2019-07-15T17:28:39Z\,\ container-format\=\(string\)\"ISO\\\ MP4/M4A\"\;";
|
||||
event tag: GstTagList-stream, taglist=(taglist)"taglist\,\ video-codec\=\(string\)\"H.265\\\ \\\(Main\\\ 10\\\ Profile\\\)\"\,\ encoder\=\(string\)x265\,\ bitrate\=\(uint\)1547698\;";
|
||||
buffer: dts=0:00:00.000000000, pts=0:00:00.066666666, dur=0:00:00.033333333, flags=discont marker header
|
||||
buffer: dts=0:00:00.000000000, pts=0:00:00.066666666, dur=0:00:00.033333333, flags=discont marker header, meta=GstVideoSEIUserDataUnregisteredMeta
|
||||
buffer: dts=0:00:00.033333333, pts=0:00:00.166666666, dur=0:00:00.033333333, flags=marker delta-unit
|
||||
buffer: dts=0:00:00.066666666, pts=0:00:00.133333333, dur=0:00:00.033333333, flags=marker delta-unit
|
||||
event flush-start: (no structure)
|
||||
event flush-stop: GstEventFlushStop, reset-time=(boolean)true;
|
||||
event segment: format=TIME, start=0:00:00.066666666, offset=0:00:00.000000000, stop=0:00:10.066666666, flags=0x201, time=0:00:00.000000000, base=0:00:00.000000000, position=0:00:00.066666666
|
||||
event tag: GstTagList-stream, taglist=(taglist)"taglist\,\ video-codec\=\(string\)\"H.265\\\ \\\(Main\\\ 10\\\ Profile\\\)\"\,\ encoder\=\(string\)x265\,\ bitrate\=\(uint\)1547698\;";
|
||||
buffer: dts=0:00:00.000000000, pts=0:00:00.066666666, dur=0:00:00.033333333, flags=discont marker header
|
||||
buffer: dts=0:00:00.000000000, pts=0:00:00.066666666, dur=0:00:00.033333333, flags=discont marker header, meta=GstVideoSEIUserDataUnregisteredMeta
|
||||
buffer: dts=0:00:00.033333333, pts=0:00:00.166666666, dur=0:00:00.033333333, flags=marker delta-unit
|
||||
buffer: dts=0:00:00.133333333, pts=0:00:00.266666666, dur=0:00:00.033333333, flags=marker delta-unit
|
||||
buffer: dts=0:00:00.233333333, pts=0:00:00.366666666, dur=0:00:00.033333333, flags=marker delta-unit
|
||||
|
|
|
@ -1102,8 +1102,8 @@ gst_h264_parser_parse_user_data_unregistered (GstH264NalParser * nalparser,
|
|||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
READ_UINT8 (nr, urud->uuid[i], 8);
|
||||
--payload_size;
|
||||
}
|
||||
payload_size -= 16;
|
||||
|
||||
urud->size = payload_size;
|
||||
|
||||
|
|
|
@ -1242,6 +1242,47 @@ error:
|
|||
}
|
||||
}
|
||||
|
||||
static GstH265ParserResult
|
||||
gst_h265_parser_parse_user_data_unregistered (GstH265Parser * parser,
|
||||
GstH265UserDataUnregistered * urud, NalReader * nr, guint payload_size)
|
||||
{
|
||||
guint8 *data = NULL;
|
||||
gint i;
|
||||
|
||||
if (payload_size < 16) {
|
||||
GST_WARNING ("Too small payload size %d", payload_size);
|
||||
return GST_H265_PARSER_BROKEN_DATA;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
READ_UINT8 (nr, urud->uuid[i], 8);
|
||||
}
|
||||
payload_size -= 16;
|
||||
|
||||
urud->size = payload_size;
|
||||
|
||||
data = g_malloc0 (payload_size);
|
||||
for (i = 0; i < payload_size; ++i) {
|
||||
READ_UINT8 (nr, data[i], 8);
|
||||
}
|
||||
|
||||
if (payload_size < 1) {
|
||||
GST_WARNING ("No more remaining payload data to store");
|
||||
g_clear_pointer (&data, g_free);
|
||||
return GST_H265_PARSER_BROKEN_DATA;
|
||||
}
|
||||
|
||||
urud->data = data;
|
||||
GST_MEMDUMP ("SEI user data unregistered", data, payload_size);
|
||||
return GST_H265_PARSER_OK;
|
||||
|
||||
error:
|
||||
{
|
||||
GST_WARNING ("error parsing \"User Data Unregistered\"");
|
||||
g_clear_pointer (&data, g_free);
|
||||
return GST_H265_PARSER_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
static GstH265ParserResult
|
||||
gst_h265_parser_parse_time_code (GstH265Parser * parser,
|
||||
|
@ -3067,6 +3108,10 @@ gst_h265_parser_parse_sei_message (GstH265Parser * parser,
|
|||
res = gst_h265_parser_parse_registered_user_data (parser,
|
||||
&sei->payload.registered_user_data, nr, payload_size >> 3);
|
||||
break;
|
||||
case GST_H265_SEI_USER_DATA_UNREGISTERED:
|
||||
res = gst_h265_parser_parse_user_data_unregistered (parser,
|
||||
&sei->payload.user_data_unregistered, nr, payload_size >> 3);
|
||||
break;
|
||||
case GST_H265_SEI_RECOVERY_POINT:
|
||||
res = gst_h265_parser_parse_recovery_point (parser,
|
||||
&sei->payload.recovery_point, nr);
|
||||
|
@ -3228,6 +3273,16 @@ gst_h265_sei_copy (GstH265SEIMessage * dst_sei,
|
|||
dst_rud->data = g_malloc (src_rud->size);
|
||||
memcpy ((guint8 *) dst_rud->data, src_rud->data, src_rud->size);
|
||||
}
|
||||
} else if (dst_sei->payloadType == GST_H265_SEI_USER_DATA_UNREGISTERED) {
|
||||
GstH265UserDataUnregistered *dst_udu =
|
||||
&dst_sei->payload.user_data_unregistered;
|
||||
const GstH265UserDataUnregistered *src_udu =
|
||||
&src_sei->payload.user_data_unregistered;
|
||||
|
||||
if (src_udu->size) {
|
||||
dst_udu->data = g_malloc (src_udu->size);
|
||||
memcpy ((guint8 *) dst_udu->data, src_udu->data, src_udu->size);
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
@ -3256,6 +3311,10 @@ gst_h265_sei_free (GstH265SEIMessage * sei)
|
|||
GstH265RegisteredUserData *rud = &sei->payload.registered_user_data;
|
||||
g_free ((guint8 *) rud->data);
|
||||
rud->data = NULL;
|
||||
} else if (sei->payloadType == GST_H265_SEI_USER_DATA_UNREGISTERED) {
|
||||
GstH265UserDataUnregistered *udu = &sei->payload.user_data_unregistered;
|
||||
g_free ((guint8 *) udu->data);
|
||||
udu->data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -348,11 +348,19 @@ typedef enum
|
|||
*
|
||||
* The type of SEI message.
|
||||
*/
|
||||
/**
|
||||
* GST_H265_SEI_USER_DATA_UNREGISTERED
|
||||
*
|
||||
* User data unregistered (D.2.7)
|
||||
*
|
||||
* Since: 1.24
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
GST_H265_SEI_BUF_PERIOD = 0,
|
||||
GST_H265_SEI_PIC_TIMING = 1,
|
||||
GST_H265_SEI_REGISTERED_USER_DATA = 4,
|
||||
GST_H265_SEI_USER_DATA_UNREGISTERED = 5,
|
||||
GST_H265_SEI_RECOVERY_POINT = 6,
|
||||
GST_H265_SEI_TIME_CODE = 136,
|
||||
GST_H265_SEI_MASTERING_DISPLAY_COLOUR_VOLUME = 137,
|
||||
|
@ -446,6 +454,7 @@ typedef struct _GstH265SliceHdr GstH265SliceHdr;
|
|||
|
||||
typedef struct _GstH265PicTiming GstH265PicTiming;
|
||||
typedef struct _GstH265RegisteredUserData GstH265RegisteredUserData;
|
||||
typedef struct _GstH265UserDataUnregistered GstH265UserDataUnregistered;
|
||||
typedef struct _GstH265BufferingPeriod GstH265BufferingPeriod;
|
||||
typedef struct _GstH265RecoveryPoint GstH265RecoveryPoint;
|
||||
typedef struct _GstH265TimeCode GstH265TimeCode;
|
||||
|
@ -1577,6 +1586,22 @@ struct _GstH265RegisteredUserData
|
|||
guint size;
|
||||
};
|
||||
|
||||
/**
|
||||
* GstH265UserDataUnregistered:
|
||||
* @uuid: an uuid_iso_iec_11578.
|
||||
* @data: the data of user_data_payload_byte
|
||||
* @size: the size of @data in bytes
|
||||
*
|
||||
* The User data unregistered SEI message syntax.
|
||||
*
|
||||
* Since: 1.24
|
||||
*/
|
||||
struct _GstH265UserDataUnregistered
|
||||
{
|
||||
guint8 uuid[16];
|
||||
const guint8 *data;
|
||||
guint size;
|
||||
};
|
||||
|
||||
/**
|
||||
* GstH265TimeCode:
|
||||
|
@ -1642,6 +1667,13 @@ struct _GstH265ContentLightLevel
|
|||
guint16 max_pic_average_light_level;
|
||||
};
|
||||
|
||||
/**
|
||||
* _GstH265SEIMessage.payload.user_data_unregistered:
|
||||
*
|
||||
* User Data Unregistered
|
||||
*
|
||||
* Since: 1.24
|
||||
*/
|
||||
struct _GstH265SEIMessage
|
||||
{
|
||||
GstH265SEIPayloadType payloadType;
|
||||
|
@ -1654,6 +1686,7 @@ struct _GstH265SEIMessage
|
|||
GstH265TimeCode time_code;
|
||||
GstH265MasteringDisplayColourVolume mastering_display_colour_volume;
|
||||
GstH265ContentLightLevel content_light_level;
|
||||
GstH265UserDataUnregistered user_data_unregistered;
|
||||
/* ... could implement more */
|
||||
} payload;
|
||||
};
|
||||
|
|
|
@ -121,6 +121,9 @@ static gboolean gst_h265_parse_src_event (GstBaseParse * parse,
|
|||
static void
|
||||
gst_h265_parse_process_sei_user_data (GstH265Parse * h265parse,
|
||||
GstH265RegisteredUserData * rud);
|
||||
static void
|
||||
gst_h265_parse_process_sei_user_data_unregistered (GstH265Parse * h265parse,
|
||||
GstH265UserDataUnregistered * urud);
|
||||
|
||||
static void
|
||||
gst_h265_parse_class_init (GstH265ParseClass * klass)
|
||||
|
@ -179,6 +182,7 @@ gst_h265_parse_finalize (GObject * object)
|
|||
{
|
||||
GstH265Parse *h265parse = GST_H265_PARSE (object);
|
||||
|
||||
gst_video_user_data_unregistered_clear (&h265parse->user_data_unregistered);
|
||||
g_object_unref (h265parse->frame_out);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
|
@ -581,6 +585,10 @@ gst_h265_parse_process_sei (GstH265Parse * h265parse, GstH265NalUnit * nalu)
|
|||
gst_h265_parse_process_sei_user_data (h265parse,
|
||||
&sei.payload.registered_user_data);
|
||||
break;
|
||||
case GST_H265_SEI_USER_DATA_UNREGISTERED:
|
||||
gst_h265_parse_process_sei_user_data_unregistered (h265parse,
|
||||
&sei.payload.user_data_unregistered);
|
||||
break;
|
||||
case GST_H265_SEI_BUF_PERIOD:
|
||||
/* FIXME */
|
||||
break;
|
||||
|
@ -709,6 +717,21 @@ gst_h265_parse_process_sei_user_data (GstH265Parse * h265parse,
|
|||
|
||||
}
|
||||
|
||||
static void
|
||||
gst_h265_parse_process_sei_user_data_unregistered (GstH265Parse * h265parse,
|
||||
GstH265UserDataUnregistered * urud)
|
||||
{
|
||||
GstByteReader br;
|
||||
|
||||
if (urud->data == NULL || urud->size < 1)
|
||||
return;
|
||||
|
||||
gst_byte_reader_init (&br, urud->data, urud->size);
|
||||
|
||||
gst_video_parse_user_data_unregistered ((GstElement *) h265parse,
|
||||
&h265parse->user_data_unregistered, &br, urud->uuid);
|
||||
}
|
||||
|
||||
/* caller guarantees 2 bytes of nal payload */
|
||||
static gboolean
|
||||
gst_h265_parse_process_nal (GstH265Parse * h265parse, GstH265NalUnit * nalu)
|
||||
|
@ -3098,6 +3121,9 @@ gst_h265_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
|
|||
gst_video_push_user_data ((GstElement *) h265parse, &h265parse->user_data,
|
||||
parse_buffer);
|
||||
|
||||
gst_video_push_user_data_unregistered ((GstElement *) h265parse,
|
||||
&h265parse->user_data_unregistered, parse_buffer);
|
||||
|
||||
gst_h265_parse_reset_frame (h265parse);
|
||||
|
||||
return GST_FLOW_OK;
|
||||
|
|
|
@ -115,6 +115,7 @@ struct _GstH265Parse
|
|||
gboolean picture_start;
|
||||
|
||||
GstVideoParseUserData user_data;
|
||||
GstVideoParseUserDataUnregistered user_data_unregistered;
|
||||
|
||||
/* props */
|
||||
gint interval;
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
*/
|
||||
|
||||
#include <gst/check/check.h>
|
||||
#include <gst/video/video-sei.h>
|
||||
#include "parser.h"
|
||||
|
||||
#define SRC_CAPS_TMPL "video/x-h265, parsed=(boolean)false"
|
||||
|
@ -1116,6 +1117,58 @@ GST_START_TEST (test_drain)
|
|||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_parse_sei_userdefinedunregistered)
|
||||
{
|
||||
GstVideoSEIUserDataUnregisteredMeta *meta;
|
||||
GstHarness *h;
|
||||
GstBuffer *buf;
|
||||
|
||||
const guint8 bytestream[] = {
|
||||
0x00, 0x00, 0x00, 0x01, 0x42, 0x01, 0x01, 0x04, 0x08, 0x00, 0x00, 0x03,
|
||||
0x00, 0x9e, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x1e, 0x90, 0x11, 0x08,
|
||||
0xb2, 0xca, 0xcd, 0x57, 0x95, 0xcd, 0xc0, 0x80, 0x80, 0x01, 0x00, 0x00,
|
||||
0x03, 0x00, 0x01, 0x00, 0x00, 0x03, 0x00, 0x19, 0x08, 0x00, 0x00, 0x00,
|
||||
0x01, 0x44, 0x01, 0xc1, 0x73, 0x18, 0x31, 0x08, 0x90,
|
||||
// SEI
|
||||
0x00, 0x00, 0x01, 0x4e, 0x01,
|
||||
0x05, // SEI Type.
|
||||
0x18, // SEI Payload size (16 UUID size + 8 payload size = 24).
|
||||
// SEI User Data Unregistered UUID.
|
||||
0xee, 0x2c, 0xa2, 0xde, 0x09, 0xb5, 0x17, 0x47, 0xdb, 0xbb, 0x55, 0xa4,
|
||||
0xfe, 0x7f, 0xc2, 0xfc,
|
||||
// SEI User Data Unregistered Payload.
|
||||
0x4e, 0x78, 0x32, 0x36, 0x35, 0x20, 0x28, 0x62,
|
||||
};
|
||||
const gsize bytestream_size = sizeof (bytestream);
|
||||
const guint8 uuid[] = {
|
||||
0xee, 0x2c, 0xa2, 0xde, 0x09, 0xb5, 0x17, 0x47, 0xdb, 0xbb, 0x55, 0xa4,
|
||||
0xfe, 0x7f, 0xc2, 0xfc
|
||||
};
|
||||
const guint8 payload[] = { 0x4e, 0x78, 0x32, 0x36, 0x35, 0x20, 0x28, 0x62 };
|
||||
|
||||
h = gst_harness_new ("h265parse");
|
||||
gst_harness_set_src_caps_str (h, "video/x-h265, stream-format=byte-stream");
|
||||
|
||||
buf = gst_buffer_new_and_alloc (bytestream_size);
|
||||
gst_buffer_fill (buf, 0, bytestream, bytestream_size);
|
||||
fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
|
||||
|
||||
gst_harness_push_event (h, gst_event_new_eos ());
|
||||
|
||||
buf = gst_harness_pull (h);
|
||||
meta = gst_buffer_get_video_sei_user_data_unregistered_meta (buf);
|
||||
fail_unless (meta != NULL);
|
||||
|
||||
fail_unless (memcmp (meta->uuid, uuid, 16) == 0);
|
||||
fail_unless_equals_int (meta->size, G_N_ELEMENTS (payload));
|
||||
fail_unless (memcmp (meta->data, payload, meta->size) == 0);
|
||||
|
||||
gst_buffer_unref (buf);
|
||||
|
||||
gst_harness_teardown (h);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
static Suite *
|
||||
h265parse_harnessed_suite (void)
|
||||
|
@ -1152,6 +1205,8 @@ h265parse_harnessed_suite (void)
|
|||
|
||||
tcase_add_test (tc_chain, test_drain);
|
||||
|
||||
tcase_add_test (tc_chain, test_parse_sei_userdefinedunregistered);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue