summaryrefslogtreecommitdiff
path: root/gst/videoparsers
diff options
context:
space:
mode:
authorMathieu Duponchelle <mathieu@centricular.com>2019-03-30 01:17:08 +0100
committerMathieu Duponchelle <mduponchelle1@gmail.com>2019-04-01 10:02:33 +0000
commit55bb8966e1508ab7b35b6a507ef90cc5f64d8486 (patch)
tree17b73b18a5e642a7d1b2851719701b067414de22 /gst/videoparsers
parent7c425cf3395cc0063daeb0bc0e289732c4339c68 (diff)
downloadgstreamer-plugins-bad-55bb8966e1508ab7b35b6a507ef90cc5f64d8486.tar.gz
h265parse: forward time codes
This transforms time code SEIs into GstVideoTimeCodeMeta
Diffstat (limited to 'gst/videoparsers')
-rw-r--r--gst/videoparsers/gsth265parse.c87
-rw-r--r--gst/videoparsers/gsth265parse.h7
2 files changed, 90 insertions, 4 deletions
diff --git a/gst/videoparsers/gsth265parse.c b/gst/videoparsers/gsth265parse.c
index c7fd8bf5b..b16f20d09 100644
--- a/gst/videoparsers/gsth265parse.c
+++ b/gst/videoparsers/gsth265parse.c
@@ -544,9 +544,14 @@ gst_h265_parse_process_sei (GstH265Parse * h265parse, GstH265NalUnit * nalu)
sei.payload.recovery_point.broken_link_flag);
h265parse->keyframe = TRUE;
break;
-
- case GST_H265_SEI_BUF_PERIOD:
+ case GST_H265_SEI_TIME_CODE:
+ memcpy (&h265parse->time_code, &sei.payload.time_code,
+ sizeof (GstH265TimeCode));
+ break;
case GST_H265_SEI_PIC_TIMING:
+ h265parse->sei_pic_struct = sei.payload.pic_timing.pic_struct;
+ break;
+ case GST_H265_SEI_BUF_PERIOD:
/* FIXME */
break;
}
@@ -1245,8 +1250,8 @@ gst_h265_parse_make_codec_data (GstH265Parse * h265parse)
}
data[6] |=
(pft->progressive_source_flag << 7) | (pft->interlaced_source_flag << 6) |
- (pft->non_packed_constraint_flag << 5) | (pft->
- frame_only_constraint_flag << 4);
+ (pft->
+ non_packed_constraint_flag << 5) | (pft->frame_only_constraint_flag << 4);
data[12] = pft->level_idc;
/* min_spatial_segmentation_idc */
GST_WRITE_UINT16_BE (data + 13, min_spatial_segmentation_idc);
@@ -1701,9 +1706,13 @@ gst_h265_parse_update_src_caps (GstH265Parse * h265parse, GstCaps * caps)
/* but not necessarily or reliably this */
if (fps_num > 0 && fps_den > 0) {
+ GstStructure *s2;
GST_INFO_OBJECT (h265parse, "setting framerate in caps");
gst_caps_set_simple (caps, "framerate",
GST_TYPE_FRACTION, fps_num, fps_den, NULL);
+ s2 = gst_caps_get_structure (caps, 0);
+ gst_structure_get_fraction (s2, "framerate", &h265parse->parsed_fps_n,
+ &h265parse->parsed_fps_d);
gst_base_parse_set_frame_rate (GST_BASE_PARSE (h265parse),
fps_num, fps_den, 0, 0);
latency = gst_util_uint64_scale (GST_SECOND, fps_den, fps_num);
@@ -2213,6 +2222,76 @@ 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;
+
+ if (!h265parse->time_code.clock_timestamp_flag[i])
+ break;
+
+ h265parse->time_code.clock_timestamp_flag[i] = 0;
+
+ /* Table D.2 */
+ switch (h265parse->sei_pic_struct) {
+ case GST_H265_SEI_PIC_STRUCT_FRAME:
+ case GST_H265_SEI_PIC_STRUCT_TOP_FIELD:
+ case GST_H265_SEI_PIC_STRUCT_BOTTOM_FIELD:
+ field_count = h265parse->sei_pic_struct;
+ break;
+ case GST_H265_SEI_PIC_STRUCT_TOP_BOTTOM:
+ case GST_H265_SEI_PIC_STRUCT_TOP_PAIRED_PREVIOUS_BOTTOM:
+ case GST_H265_SEI_PIC_STRUCT_TOP_PAIRED_NEXT_BOTTOM:
+ field_count = i + 1;
+ break;
+ case GST_H265_SEI_PIC_STRUCT_BOTTOM_TOP:
+ case GST_H265_SEI_PIC_STRUCT_BOTTOM_PAIRED_PREVIOUS_TOP:
+ case GST_H265_SEI_PIC_STRUCT_BOTTOM_PAIRED_NEXT_TOP:
+ field_count = 2 - i;
+ break;
+ case GST_H265_SEI_PIC_STRUCT_TOP_BOTTOM_TOP:
+ field_count = i % 2 ? 2 : 1;
+ break;
+ case GST_H265_SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM:
+ field_count = i % 2 ? 1 : 2;
+ break;
+ case GST_H265_SEI_PIC_STRUCT_FRAME_DOUBLING:
+ case GST_H265_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[ i ] counts when
+ * seconds_value[ i ] is equal to 0 and minutes_value[ i ] is not an integer
+ * multiple of 10 */
+ if (h265parse->time_code.counting_type[i] == 4)
+ flags |= GST_VIDEO_TIME_CODE_FLAGS_DROP_FRAME;
+
+ if (h265parse->sei_pic_struct != GST_H265_SEI_PIC_STRUCT_FRAME)
+ flags |= GST_VIDEO_TIME_CODE_FLAGS_INTERLACED;
+
+ gst_buffer_add_video_time_code_meta_full (buffer,
+ h265parse->parsed_fps_n,
+ h265parse->parsed_fps_d,
+ NULL,
+ flags,
+ h265parse->time_code.hours_flag[i] ? h265parse->time_code.
+ hours_value[i] : 0,
+ h265parse->time_code.minutes_flag[i] ? h265parse->time_code.
+ minutes_value[i] : 0,
+ h265parse->time_code.seconds_flag[i] ? h265parse->time_code.
+ seconds_value[i] : 0, h265parse->time_code.n_frames[i], field_count);
+ }
+ }
+
gst_h265_parse_reset_frame (h265parse);
return GST_FLOW_OK;
diff --git a/gst/videoparsers/gsth265parse.h b/gst/videoparsers/gsth265parse.h
index d27aac358..f52364984 100644
--- a/gst/videoparsers/gsth265parse.h
+++ b/gst/videoparsers/gsth265parse.h
@@ -52,6 +52,7 @@ struct _GstH265Parse
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 */
@@ -86,6 +87,12 @@ struct _GstH265Parse
GstBuffer *sps_nals[GST_H265_MAX_SPS_COUNT];
GstBuffer *pps_nals[GST_H265_MAX_PPS_COUNT];
+ /* Infos we need to keep track of */
+ guint8 sei_pic_struct;
+
+ /* Collected TimeCode SEI */
+ GstH265TimeCode time_code;
+
gboolean discont;
/* frame parsing */