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 we know the frame duration, and if we are not in one of the zero
* latency pattern, add one frame of latency */
gst_buffer_unref (buf);
}
+static GstClockTime
+gst_h264_parse_get_duration (GstH264Parse * h264parse, gboolean frame)
+{
+ GstClockTime ret = GST_CLOCK_TIME_NONE;
+ GstH264SPS *sps = h264parse->nalparser->last_sps;
+ gint duration = 1;
+
+ if (!frame) {
+ GST_LOG_OBJECT (h264parse, "no frame data -> 0 duration");
+ ret = 0;
+ goto done;
+ }
+
+ if (!sps) {
+ GST_DEBUG_OBJECT (h264parse, "referred SPS invalid");
+ goto fps_duration;
+ } else if (!sps->vui_parameters_present_flag) {
+ GST_DEBUG_OBJECT (h264parse, "unable to compute duration: VUI not present");
+ goto fps_duration;
+ } else if (!sps->vui_parameters.timing_info_present_flag) {
+ GST_DEBUG_OBJECT (h264parse,
+ "unable to compute duration: timing info not present");
+ goto fps_duration;
+ } else if (sps->vui_parameters.time_scale == 0) {
+ GST_DEBUG_OBJECT (h264parse,
+ "unable to compute duration: time_scale = 0 "
+ "(this is forbidden in spec; bitstream probably contains error)");
+ goto fps_duration;
+ }
+
+ if (h264parse->sei_pic_struct_pres_flag &&
+ h264parse->sei_pic_struct != (guint8) - 1) {
+ /* Note that when h264parse->sei_pic_struct == -1 (unspecified), there
+ * are ways to infer its value. This is related to computing the
+ * TopFieldOrderCnt and BottomFieldOrderCnt, which looks
+ * complicated and thus not implemented for the time being. Yet
+ * the value we have here is correct for many applications
+ */
+ switch (h264parse->sei_pic_struct) {
+ case GST_H264_SEI_PIC_STRUCT_TOP_FIELD:
+ case GST_H264_SEI_PIC_STRUCT_BOTTOM_FIELD:
+ duration = 1;
+ break;
+ case GST_H264_SEI_PIC_STRUCT_FRAME:
+ case GST_H264_SEI_PIC_STRUCT_TOP_BOTTOM:
+ case GST_H264_SEI_PIC_STRUCT_BOTTOM_TOP:
+ duration = 2;
+ break;
+ case GST_H264_SEI_PIC_STRUCT_TOP_BOTTOM_TOP:
+ case GST_H264_SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM:
+ duration = 3;
+ break;
+ case GST_H264_SEI_PIC_STRUCT_FRAME_DOUBLING:
+ duration = 4;
+ break;
+ case GST_H264_SEI_PIC_STRUCT_FRAME_TRIPLING:
+ duration = 6;
+ break;
+ default:
+ GST_DEBUG_OBJECT (h264parse,
+ "h264parse->sei_pic_struct of unknown value %d. Not parsed",
+ h264parse->sei_pic_struct);
+ break;
+ }
+ } else {
+ duration = h264parse->field_pic_flag ? 1 : 2;
+ }
+
+ GST_LOG_OBJECT (h264parse, "frame tick duration %d", duration);
+
+ ret = gst_util_uint64_scale (duration * GST_SECOND,
+ sps->vui_parameters.num_units_in_tick, sps->vui_parameters.time_scale);
+ /* sanity check */
+ if (ret < GST_MSECOND) {
+ GST_DEBUG_OBJECT (h264parse, "discarding dur %" GST_TIME_FORMAT,
+ GST_TIME_ARGS (ret));
+ goto fps_duration;
+ }
+
+done:
+ return ret;
+
+fps_duration:
+ if (h264parse->parsed_fps_d > 0 && h264parse->parsed_fps_n > 0)
+ ret =
+ gst_util_uint64_scale (GST_SECOND, h264parse->parsed_fps_d,
+ h264parse->parsed_fps_n);
+ goto done;
+}
+
static void
gst_h264_parse_get_timestamp (GstH264Parse * h264parse,
GstClockTime * out_ts, GstClockTime * out_dur, gboolean frame)
/* don't mess with timestamps if provided by upstream,
* particularly since our ts not that good they handle seeking etc */
- if (h264parse->do_ts)
+ if (h264parse->do_ts) {
gst_h264_parse_get_timestamp (h264parse,
&GST_BUFFER_DTS (buffer), &GST_BUFFER_DURATION (buffer),
h264parse->frame_start);
+ }
+
+ /* We don't want to let baseparse select a duration itself based
+ * solely on the framerate, as we have more per-frame information
+ * available */
+ if (!GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DURATION (buffer))) {
+ GST_BUFFER_DURATION (buffer) =
+ gst_h264_parse_get_duration (h264parse, h264parse->frame_start);
+ }
if (h264parse->keyframe)
GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);