diff options
author | Mathieu Duponchelle <mathieu@centricular.com> | 2019-03-28 22:02:02 +0100 |
---|---|---|
committer | Mathieu Duponchelle <mduponchelle1@gmail.com> | 2019-04-01 10:02:33 +0000 |
commit | 7c425cf3395cc0063daeb0bc0e289732c4339c68 (patch) | |
tree | c7daec21fbd50294ba57a96cc7f379b556c9416e | |
parent | 2b218da805f92509494398031ef546a7cea28f76 (diff) |
h264parse: forward time codes
This transforms time codes from the timing SEI into
GstVideoTimeCodeMeta
-rw-r--r-- | gst-libs/gst/codecparsers/gsth264parser.h | 15 | ||||
-rw-r--r-- | gst/videoparsers/gsth264parse.c | 91 | ||||
-rw-r--r-- | gst/videoparsers/gsth264parse.h | 5 |
3 files changed, 107 insertions, 4 deletions
diff --git a/gst-libs/gst/codecparsers/gsth264parser.h b/gst-libs/gst/codecparsers/gsth264parser.h index 1914470b5e..671b5e5fd2 100644 --- a/gst-libs/gst/codecparsers/gsth264parser.h +++ b/gst-libs/gst/codecparsers/gsth264parser.h @@ -307,6 +307,21 @@ typedef enum GST_H264_S_SI_SLICE = 9 } GstH264SliceType; +/** + * GstH264CtType + * + * Mapping of ct_type to source picture scan + * + * Since: 1.16 + */ + +typedef enum +{ + GST_H264_CT_TYPE_PROGRESSIVE = 0, + GST_H264_CT_TYPE_INTERLACED = 1, + GST_H264_CT_TYPE_UNKNOWN = 2, +} GstCtType; + typedef struct _GstH264NalParser GstH264NalParser; typedef struct _GstH264NalUnit GstH264NalUnit; diff --git a/gst/videoparsers/gsth264parse.c b/gst/videoparsers/gsth264parse.c index fe500337aa..3654516d81 100644 --- a/gst/videoparsers/gsth264parse.c +++ b/gst/videoparsers/gsth264parse.c @@ -539,14 +539,30 @@ gst_h264_parse_process_sei (GstH264Parse * h264parse, GstH264NalUnit * nalu) sei = g_array_index (messages, GstH264SEIMessage, i); switch (sei.payloadType) { case GST_H264_SEI_PIC_TIMING: + { + guint j; h264parse->sei_pic_struct_pres_flag = sei.payload.pic_timing.pic_struct_present_flag; h264parse->sei_cpb_removal_delay = sei.payload.pic_timing.cpb_removal_delay; - if (h264parse->sei_pic_struct_pres_flag) + if (h264parse->sei_pic_struct_pres_flag) { h264parse->sei_pic_struct = sei.payload.pic_timing.pic_struct; + } + + h264parse->num_clock_timestamp = 0; + + for (j = 0; j < 3; j++) { + if (sei.payload.pic_timing.clock_timestamp_flag[j]) { + memcpy (&h264parse-> + clock_timestamp[h264parse->num_clock_timestamp++], + &sei.payload.pic_timing.clock_timestamp[j], + sizeof (GstH264ClockTimestamp)); + } + } + GST_LOG_OBJECT (h264parse, "pic timing updated"); break; + } case GST_H264_SEI_BUF_PERIOD: if (h264parse->ts_trn_nb == GST_CLOCK_TIME_NONE || h264parse->dts == GST_CLOCK_TIME_NONE) @@ -1894,15 +1910,20 @@ gst_h264_parse_update_src_caps (GstH264Parse * h264parse, GstCaps * caps) "height", G_TYPE_INT, height, NULL); /* upstream overrides */ - if (s && gst_structure_has_field (s, "framerate")) + if (s && gst_structure_has_field (s, "framerate")) { gst_structure_get_fraction (s, "framerate", &fps_num, &fps_den); + } /* but not necessarily or reliably this */ if (fps_den > 0) { + GstStructure *s2; gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION, fps_num, fps_den, NULL); - gst_base_parse_set_frame_rate (GST_BASE_PARSE (h264parse), - fps_num, fps_den, 0, 0); + s2 = gst_caps_get_structure (caps, 0); + gst_structure_get_fraction (s2, "framerate", &h264parse->parsed_fps_n, + &h264parse->parsed_fps_d); + gst_base_parse_set_frame_rate (GST_BASE_PARSE (h264parse), fps_num, + fps_den, 0, 0); if (fps_num > 0) { latency = gst_util_uint64_scale (GST_SECOND, fps_den, fps_num); gst_base_parse_set_latency (GST_BASE_PARSE (h264parse), latency, @@ -2550,6 +2571,68 @@ gst_h264_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame) } #endif + { + guint i = 0; + + for (i = 0; i < h264parse->num_clock_timestamp; i++) { + GstH264ClockTimestamp *tim = &h264parse->clock_timestamp[i]; + GstVideoTimeCodeFlags flags = 0; + gint field_count = -1; + + /* Table D-1 */ + switch (h264parse->sei_pic_struct) { + case GST_H264_SEI_PIC_STRUCT_FRAME: + case GST_H264_SEI_PIC_STRUCT_TOP_FIELD: + case GST_H264_SEI_PIC_STRUCT_BOTTOM_FIELD: + field_count = h264parse->sei_pic_struct; + break; + case GST_H264_SEI_PIC_STRUCT_TOP_BOTTOM: + field_count = i + 1; + break; + case GST_H264_SEI_PIC_STRUCT_BOTTOM_TOP: + field_count = 2 - i; + break; + case GST_H264_SEI_PIC_STRUCT_TOP_BOTTOM_TOP: + field_count = i % 2 ? 2 : 1; + break; + case GST_H264_SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM: + field_count = i % 2 ? 1 : 2; + break; + case GST_H264_SEI_PIC_STRUCT_FRAME_DOUBLING: + case GST_H264_SEI_PIC_STRUCT_FRAME_TRIPLING: + field_count = 0; + break; + } + + if (field_count == -1) { + GST_WARNING_OBJECT (parse, + "failed to determine field count for timecode"); + field_count = 0; + } + + /* dropping of the two lowest (value 0 and 1) n_frames + * counts when seconds_value is equal to 0 and + * minutes_value is not an integer multiple of 10 */ + if (tim->counting_type == 4) + flags |= GST_VIDEO_TIME_CODE_FLAGS_DROP_FRAME; + + if (tim->ct_type == GST_H264_CT_TYPE_INTERLACED) + flags |= GST_VIDEO_TIME_CODE_FLAGS_INTERLACED; + + gst_buffer_add_video_time_code_meta_full (buffer, + h264parse->parsed_fps_n, + h264parse->parsed_fps_d, + NULL, + flags, + tim->hours_flag ? tim->hours_value : 0, + tim->minutes_flag ? tim->minutes_value : 0, + tim->seconds_flag ? tim->seconds_value : 0, + tim->n_frames, field_count); + } + + h264parse->num_clock_timestamp = 0; + } + gst_h264_parse_reset_frame (h264parse); return GST_FLOW_OK; diff --git a/gst/videoparsers/gsth264parse.h b/gst/videoparsers/gsth264parse.h index 61a996d17d..3d4d8e28d1 100644 --- a/gst/videoparsers/gsth264parse.h +++ b/gst/videoparsers/gsth264parse.h @@ -59,6 +59,7 @@ struct _GstH264Parse gint fps_num, fps_den; gint upstream_par_n, upstream_par_d; gint parsed_par_n, parsed_par_d; + gint parsed_fps_n, parsed_fps_d; /* current codec_data in output caps, if any */ GstBuffer *codec_data; /* input codec_data, if any */ @@ -95,6 +96,10 @@ struct _GstH264Parse GstBuffer *sps_nals[GST_H264_MAX_SPS_COUNT]; GstBuffer *pps_nals[GST_H264_MAX_PPS_COUNT]; + /* collected SEI timestamps */ + guint num_clock_timestamp; + GstH264ClockTimestamp clock_timestamp[3]; + /* Infos we need to keep track of */ guint32 sei_cpb_removal_delay; guint8 sei_pic_struct; |