mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 20:21:24 +00:00
mpeg4: fix timestamp issues on too fast playback.
Improve generation of presentation timestamps to be less sensitive to input stream errors. In practise, GOP is also a synchronization point for PTS calculation. Signed-off-by: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
This commit is contained in:
parent
449606efc5
commit
1632b40982
1 changed files with 61 additions and 8 deletions
|
@ -73,6 +73,7 @@ struct _GstVaapiDecoderMpeg4Private {
|
|||
GstClockTime seq_pts;
|
||||
GstClockTime gop_pts;
|
||||
GstClockTime pts_diff;
|
||||
GstClockTime max_pts;
|
||||
// anchor sync time base for any picture type,
|
||||
// it is time base of backward reference frame
|
||||
GstClockTime last_sync_time;
|
||||
|
@ -314,8 +315,6 @@ decode_sequence(GstVaapiDecoderMpeg4 *decoder, const guint8 *buf, guint buf_size
|
|||
priv->profile_changed = TRUE;
|
||||
}
|
||||
priv->seq_pts = gst_adapter_prev_timestamp(priv->adapter, NULL);
|
||||
priv->calculate_pts_diff = TRUE;
|
||||
|
||||
priv->size_changed = TRUE;
|
||||
|
||||
return GST_VAAPI_DECODER_STATUS_SUCCESS;
|
||||
|
@ -419,19 +418,64 @@ decode_gop(GstVaapiDecoderMpeg4 *decoder, const guint8 *buf, guint buf_size)
|
|||
priv->closed_gop, priv->broken_link);
|
||||
|
||||
gop_time = gop.hours * 3600 + gop.minutes * 60 + gop.seconds;
|
||||
priv->gop_pts = gop_time * GST_SECOND;
|
||||
priv->last_sync_time = gop_time;
|
||||
priv->sync_time = gop_time;
|
||||
|
||||
if (priv->calculate_pts_diff) {
|
||||
priv->pts_diff = priv->seq_pts - priv->gop_pts;
|
||||
priv->calculate_pts_diff = FALSE;
|
||||
}
|
||||
|
||||
if (priv->gop_pts != GST_CLOCK_TIME_NONE)
|
||||
priv->pts_diff += gop_time * GST_SECOND - priv->gop_pts;
|
||||
priv->gop_pts = gop_time * GST_SECOND;
|
||||
priv->calculate_pts_diff = TRUE;
|
||||
priv->is_first_field = TRUE;
|
||||
|
||||
return GST_VAAPI_DECODER_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
calculate_pts_diff(GstVaapiDecoderMpeg4 *decoder,
|
||||
GstMpeg4VideoObjectLayer *vol_hdr,
|
||||
GstMpeg4VideoObjectPlane *vop_hdr)
|
||||
{
|
||||
GstVaapiDecoderMpeg4Private * const priv = decoder->priv;
|
||||
GstClockTime frame_timestamp;
|
||||
|
||||
frame_timestamp = gst_adapter_prev_timestamp(priv->adapter, NULL);
|
||||
if (frame_timestamp && frame_timestamp != GST_CLOCK_TIME_NONE) {
|
||||
/* Buffer with timestamp */
|
||||
if (priv->max_pts != GST_CLOCK_TIME_NONE &&
|
||||
frame_timestamp < priv->max_pts) {
|
||||
frame_timestamp = priv->max_pts +
|
||||
gst_util_uint64_scale((vol_hdr->fixed_vop_rate ?
|
||||
vol_hdr->fixed_vop_time_increment : 1),
|
||||
GST_SECOND,
|
||||
vol_hdr->vop_time_increment_resolution);
|
||||
}
|
||||
} else {
|
||||
/* Buffer without timestamp set */
|
||||
if (priv->max_pts == GST_CLOCK_TIME_NONE) /* first buffer */
|
||||
frame_timestamp = 0;
|
||||
else {
|
||||
GstClockTime tmp_pts;
|
||||
tmp_pts = priv->pts_diff + priv->gop_pts +
|
||||
vop_hdr->modulo_time_base * GST_SECOND +
|
||||
gst_util_uint64_scale(vop_hdr->time_increment,
|
||||
GST_SECOND,
|
||||
vol_hdr->vop_time_increment_resolution);
|
||||
if (tmp_pts > priv->max_pts)
|
||||
frame_timestamp = tmp_pts;
|
||||
else
|
||||
frame_timestamp = priv->max_pts +
|
||||
gst_util_uint64_scale((vol_hdr->fixed_vop_rate ?
|
||||
vol_hdr->fixed_vop_time_increment : 1),
|
||||
GST_SECOND,
|
||||
vol_hdr->vop_time_increment_resolution);
|
||||
}
|
||||
}
|
||||
|
||||
priv->pts_diff = frame_timestamp -
|
||||
(priv->gop_pts + vop_hdr->modulo_time_base * GST_SECOND +
|
||||
gst_util_uint64_scale(vop_hdr->time_increment, GST_SECOND,
|
||||
vol_hdr->vop_time_increment_resolution));
|
||||
}
|
||||
|
||||
static GstVaapiDecoderStatus
|
||||
decode_picture(GstVaapiDecoderMpeg4 *decoder, const guint8 *buf, guint buf_size)
|
||||
|
@ -555,6 +599,12 @@ decode_picture(GstVaapiDecoderMpeg4 *decoder, const guint8 *buf, guint buf_size)
|
|||
priv->prev_t_ref = priv->svh_hdr.temporal_reference;
|
||||
}
|
||||
else {
|
||||
/* Update priv->pts_diff */
|
||||
if (priv->calculate_pts_diff) {
|
||||
calculate_pts_diff(decoder, vol_hdr, vop_hdr);
|
||||
priv->calculate_pts_diff = FALSE;
|
||||
}
|
||||
|
||||
/* Update presentation time, 6.3.5 */
|
||||
if(vop_hdr->coding_type != GST_MPEG4_B_VOP) {
|
||||
// increment basing on decoding order
|
||||
|
@ -575,6 +625,8 @@ decode_picture(GstVaapiDecoderMpeg4 *decoder, const guint8 *buf, guint buf_size)
|
|||
}
|
||||
}
|
||||
picture->pts = pts + priv->pts_diff;
|
||||
if (priv->max_pts == GST_CLOCK_TIME_NONE || priv->max_pts < picture->pts)
|
||||
priv->max_pts = picture->pts;
|
||||
|
||||
/* Update reference pictures */
|
||||
/* XXX: consider priv->vol_hdr.low_delay, consider packed video frames for DivX/XviD */
|
||||
|
@ -1058,6 +1110,7 @@ gst_vaapi_decoder_mpeg4_init(GstVaapiDecoderMpeg4 *decoder)
|
|||
priv->sub_buffer = NULL;
|
||||
priv->seq_pts = GST_CLOCK_TIME_NONE;
|
||||
priv->gop_pts = GST_CLOCK_TIME_NONE;
|
||||
priv->max_pts = GST_CLOCK_TIME_NONE;
|
||||
priv->pts_diff = 0;
|
||||
priv->calculate_pts_diff = TRUE;
|
||||
priv->is_constructed = FALSE;
|
||||
|
|
Loading…
Reference in a new issue