videoencoder: Add gst_video_encoder_set_min_pts()

For streams with reordered frames this can be used to ensure that there
is enough time to accomodate first DTS, which may be less than first PTS

https://bugzilla.gnome.org/show_bug.cgi?id=740575
This commit is contained in:
Matej Knopp 2014-11-26 21:06:57 +01:00 committed by Nicolas Dufresne
parent 5f23fae367
commit dc7b254805
3 changed files with 53 additions and 0 deletions

View file

@ -164,6 +164,11 @@ struct _GstVideoEncoderPrivate
GstTagList *tags;
gboolean tags_changed;
GstClockTime min_pts;
/* adjustment needed on pts, dts, segment start and stop to accomodate
* min_pts */
GstClockTime time_adjustment;
};
typedef struct _ForcedKeyUnitEvent ForcedKeyUnitEvent;
@ -343,6 +348,8 @@ gst_video_encoder_reset (GstVideoEncoder * encoder, gboolean hard)
priv->bytes = 0;
priv->time = 0;
priv->time_adjustment = GST_CLOCK_TIME_NONE;
if (hard) {
gst_segment_init (&encoder->input_segment, GST_FORMAT_TIME);
gst_segment_init (&encoder->output_segment, GST_FORMAT_TIME);
@ -455,6 +462,8 @@ gst_video_encoder_init (GstVideoEncoder * encoder, GstVideoEncoderClass * klass)
priv->min_latency = 0;
priv->max_latency = 0;
priv->min_pts = GST_CLOCK_TIME_NONE;
priv->time_adjustment = GST_CLOCK_TIME_NONE;
gst_video_encoder_reset (encoder, TRUE);
}
@ -885,8 +894,19 @@ gst_video_encoder_push_event (GstVideoEncoder * encoder, GstEvent * event)
break;
}
if (encoder->priv->time_adjustment != GST_CLOCK_TIME_NONE) {
segment.start += encoder->priv->time_adjustment;
if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
segment.stop += encoder->priv->time_adjustment;
}
}
encoder->output_segment = segment;
GST_VIDEO_ENCODER_STREAM_UNLOCK (encoder);
gst_event_unref (event);
event = gst_event_new_segment (&encoder->output_segment);
break;
}
default:
@ -1323,6 +1343,17 @@ gst_video_encoder_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
else
duration = GST_CLOCK_TIME_NONE;
if (priv->min_pts != GST_CLOCK_TIME_NONE
&& priv->time_adjustment == GST_CLOCK_TIME_NONE) {
if (cstart < priv->min_pts) {
priv->time_adjustment = priv->min_pts - cstart;
}
}
if (priv->time_adjustment != GST_CLOCK_TIME_NONE) {
cstart += priv->time_adjustment;
}
/* incoming DTS is not really relevant and does not make sense anyway,
* so pass along _NONE and maybe come up with something better later on */
frame = gst_video_encoder_new_frame (encoder, buf, cstart,
@ -2297,3 +2328,22 @@ gst_video_encoder_get_allocator (GstVideoEncoder * encoder,
if (params)
*params = encoder->priv->params;
}
/**
* Request minimal value for PTS passed to handle_frame.
*
* For streams with reordered frames this can be used to ensure that there
* is enough time to accomodate first DTS, which may be less than first PTS
*
* @encoder: a #GstVideoEncoder
* @min_pts: minimal PTS that will be passed to handle_frame
*
* Since 1.6
*/
void
gst_video_encoder_set_min_pts (GstVideoEncoder * encoder, GstClockTime min_pts)
{
g_return_if_fail (GST_IS_VIDEO_ENCODER (encoder));
encoder->priv->min_pts = min_pts;
encoder->priv->time_adjustment = GST_CLOCK_TIME_NONE;
}

View file

@ -333,6 +333,8 @@ void gst_video_encoder_get_allocator (GstVideoEncoder *encoder,
GstAllocator **allocator,
GstAllocationParams *params);
void gst_video_encoder_set_min_pts(GstVideoEncoder *encoder, GstClockTime min_pts);
G_END_DECLS
#endif

View file

@ -148,6 +148,7 @@ EXPORTS
gst_video_encoder_proxy_getcaps
gst_video_encoder_set_headers
gst_video_encoder_set_latency
gst_video_encoder_set_min_pts
gst_video_encoder_set_output_state
gst_video_event_is_force_key_unit
gst_video_event_new_downstream_force_key_unit