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)
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);
* 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)
{
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,
typedef struct _GstH265SliceHdr GstH265SliceHdr;
typedef struct _GstH265PicTiming GstH265PicTiming;
+typedef struct _GstH265RegisteredUserData GstH265RegisteredUserData;
typedef struct _GstH265BufferingPeriod GstH265BufferingPeriod;
typedef struct _GstH265RecoveryPoint GstH265RecoveryPoint;
typedef struct _GstH265TimeCode GstH265TimeCode;
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
union {
GstH265BufferingPeriod buffering_period;
GstH265PicTiming pic_timing;
+ GstH265RegisteredUserData registered_user_data;
GstH265RecoveryPoint recovery_point;
GstH265TimeCode time_code;
GstH265MasteringDisplayColourVolume mastering_display_colour_volume;
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)
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;
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)
GstH265Parse *h265parse;
GstBuffer *buffer;
GstEvent *event;
+ GstBuffer *parse_buffer = NULL;
h265parse = GST_H265_PARSE (parse);
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;
}
}
+ 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;
#include <gst/base/gstbaseparse.h>
#include <gst/codecparsers/gsth265parser.h>
#include <gst/video/video.h>
+#include "gstvideoparseutils.h"
G_BEGIN_DECLS
/* AU state */
gboolean picture_start;
+ GstVideoParseUserData user_data;
+
/* props */
gint interval;