h265parse: add support for SEI registered user data

This commit is contained in:
Aaron Boxer 2019-05-08 11:06:40 -04:00
parent b7558bd190
commit 40212aaf00
4 changed files with 125 additions and 1 deletions

View file

@ -1132,6 +1132,53 @@ error:
return GST_H265_PARSER_ERROR;
}
static GstH265ParserResult
gst_h265_parser_parse_registered_user_data (GstH265Parser * parser,
GstH265RegisteredUserData * rud, NalReader * nr, guint payload_size)
{
guint8 *data = NULL;
guint i;
rud->data = NULL;
rud->size = 0;
if (payload_size < 2)
return GST_H265_PARSER_ERROR;
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 < 8)
return GST_H265_PARSER_ERROR;
data = g_malloc (payload_size);
for (i = 0; i < payload_size / 8; ++i) {
READ_UINT8 (nr, data[i], 8);
}
GST_MEMDUMP ("SEI user data", data, payload_size / 8);
rud->data = data;
rud->size = payload_size;
return GST_H265_PARSER_OK;
error:
{
GST_WARNING ("error parsing \"Registered User Data\"");
g_free (data);
return GST_H265_PARSER_ERROR;
}
}
static GstH265ParserResult
gst_h265_parser_parse_time_code (GstH265Parser * parser,
GstH265TimeCode * tc, NalReader * nr)
@ -2472,6 +2519,10 @@ gst_h265_parser_parse_sei_message (GstH265Parser * parser,
res = gst_h265_parser_parse_pic_timing (parser,
&sei->payload.pic_timing, nr);
break;
case GST_H265_SEI_REGISTERED_USER_DATA:
res = gst_h265_parser_parse_registered_user_data (parser,
&sei->payload.registered_user_data, nr, payloadSizeBytes);
break;
case GST_H265_SEI_RECOVERY_POINT:
res = gst_h265_parser_parse_recovery_point (parser,
&sei->payload.recovery_point, nr);

View file

@ -271,6 +271,7 @@ typedef enum
* GstH265SEIPayloadType:
* @GST_H265_SEI_BUF_PERIOD: Buffering Period SEI Message
* @GST_H265_SEI_PIC_TIMING: Picture Timing SEI Message
* @GST_H265_SEI_REGISTERED_USER_DATA: Registered user data (D.2.5)
* @GST_H265_SEI_RECOVERY_POINT: Recovery Point SEI Message (D.3.8)
* @GST_H265_SEI_TIME_CODE: Time code SEI message (D.2.27) (Since: 1.16)
* @GST_H265_SEI_MASTERING_DISPLAY_COLOUR_VOLUME: Mastering display colour volume information SEI message (D.2.28) (Since: 1.18)
@ -283,6 +284,7 @@ typedef enum
{
GST_H265_SEI_BUF_PERIOD = 0,
GST_H265_SEI_PIC_TIMING = 1,
GST_H265_SEI_REGISTERED_USER_DATA = 4,
GST_H265_SEI_RECOVERY_POINT = 6,
GST_H265_SEI_TIME_CODE = 136,
GST_H265_SEI_MASTERING_DISPLAY_COLOUR_VOLUME = 137,
@ -373,6 +375,7 @@ typedef struct _GstH265ShortTermRefPicSet GstH265ShortTermRefPicSet;
typedef struct _GstH265SliceHdr GstH265SliceHdr;
typedef struct _GstH265PicTiming GstH265PicTiming;
typedef struct _GstH265RegisteredUserData GstH265RegisteredUserData;
typedef struct _GstH265BufferingPeriod GstH265BufferingPeriod;
typedef struct _GstH265RecoveryPoint GstH265RecoveryPoint;
typedef struct _GstH265TimeCode GstH265TimeCode;
@ -1226,6 +1229,15 @@ struct _GstH265RecoveryPoint
guint8 broken_link_flag;
};
struct _GstH265RegisteredUserData
{
guint8 country_code;
guint8 country_code_extension;
const guint8 *data;
guint size;
};
/**
* GstH265TimeCode:
* The time code SEI message provides time code information similar to that
@ -1297,6 +1309,7 @@ struct _GstH265SEIMessage
union {
GstH265BufferingPeriod buffering_period;
GstH265PicTiming pic_timing;
GstH265RegisteredUserData registered_user_data;
GstH265RecoveryPoint recovery_point;
GstH265TimeCode time_code;
GstH265MasteringDisplayColourVolume mastering_display_colour_volume;

View file

@ -114,6 +114,9 @@ static GstCaps *gst_h265_parse_get_caps (GstBaseParse * parse,
static gboolean gst_h265_parse_event (GstBaseParse * parse, GstEvent * event);
static gboolean gst_h265_parse_src_event (GstBaseParse * parse,
GstEvent * event);
static void
gst_h265_parse_process_sei_user_data (GstH265Parse * h265parse,
GstH265RegisteredUserData * rud);
static void
gst_h265_parse_class_init (GstH265ParseClass * klass)
@ -570,6 +573,10 @@ gst_h265_parse_process_sei (GstH265Parse * h265parse, GstH265NalUnit * nalu)
case GST_H265_SEI_PIC_TIMING:
h265parse->sei_pic_struct = sei.payload.pic_timing.pic_struct;
break;
case GST_H265_SEI_REGISTERED_USER_DATA:
gst_h265_parse_process_sei_user_data (h265parse,
&sei.payload.registered_user_data);
break;
case GST_H265_SEI_BUF_PERIOD:
/* FIXME */
break;
@ -672,6 +679,39 @@ gst_h265_parse_process_sei (GstH265Parse * h265parse, GstH265NalUnit * nalu)
g_array_free (messages, TRUE);
}
static void
gst_h265_parse_process_sei_user_data (GstH265Parse * h265parse,
GstH265RegisteredUserData * rud)
{
guint16 provider_code;
GstByteReader br;
GstVideoParseUtilsField field = GST_VIDEO_PARSE_UTILS_FIELD_1;
/* only US country code is currently supported */
switch (rud->country_code) {
case ITU_T_T35_COUNTRY_CODE_US:
break;
default:
GST_LOG_OBJECT (h265parse, "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);
if (h265parse->sei_pic_struct ==
(guint8) GST_H265_SEI_PIC_STRUCT_BOTTOM_FIELD)
field = GST_VIDEO_PARSE_UTILS_FIELD_1;
gst_video_parse_user_data ((GstElement *) h265parse, &h265parse->user_data,
&br, field, provider_code);
}
/* caller guarantees 2 bytes of nal payload */
static gboolean
gst_h265_parse_process_nal (GstH265Parse * h265parse, GstH265NalUnit * nalu)
@ -2565,6 +2605,7 @@ gst_h265_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
GstH265Parse *h265parse;
GstBuffer *buffer;
GstEvent *event;
GstBuffer *parse_buffer = NULL;
h265parse = GST_H265_PARSE (parse);
@ -2671,9 +2712,9 @@ gst_h265_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
guint i = 0;
for (i = 0; i < h265parse->time_code.num_clock_ts; i++) {
GstVideoTimeCodeFlags flags = 0;
gint field_count = -1;
guint n_frames;
GstVideoTimeCodeFlags flags = 0;
if (!h265parse->time_code.clock_timestamp_flag[i])
break;
@ -2742,6 +2783,22 @@ gst_h265_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
}
}
if (frame->out_buffer) {
parse_buffer = frame->out_buffer =
gst_buffer_make_writable (frame->out_buffer);
} else {
parse_buffer = frame->buffer = gst_buffer_make_writable (frame->buffer);
}
if (h265parse->sei_pic_struct != GST_H265_SEI_PIC_STRUCT_FRAME) {
GST_BUFFER_FLAG_SET (parse_buffer, GST_VIDEO_BUFFER_FLAG_INTERLACED);
if (h265parse->sei_pic_struct == GST_H265_SEI_PIC_STRUCT_TOP_FIELD)
GST_BUFFER_FLAG_SET (parse_buffer, GST_VIDEO_BUFFER_FLAG_TFF);
}
gst_video_push_user_data ((GstElement *) h265parse, &h265parse->user_data,
parse_buffer);
gst_h265_parse_reset_frame (h265parse);
return GST_FLOW_OK;

View file

@ -25,6 +25,7 @@
#include <gst/base/gstbaseparse.h>
#include <gst/codecparsers/gsth265parser.h>
#include <gst/video/video.h>
#include "gstvideoparseutils.h"
G_BEGIN_DECLS
@ -108,6 +109,8 @@ struct _GstH265Parse
/* AU state */
gboolean picture_start;
GstVideoParseUserData user_data;
/* props */
gint interval;