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 seq_pts;
|
||||||
GstClockTime gop_pts;
|
GstClockTime gop_pts;
|
||||||
GstClockTime pts_diff;
|
GstClockTime pts_diff;
|
||||||
|
GstClockTime max_pts;
|
||||||
// anchor sync time base for any picture type,
|
// anchor sync time base for any picture type,
|
||||||
// it is time base of backward reference frame
|
// it is time base of backward reference frame
|
||||||
GstClockTime last_sync_time;
|
GstClockTime last_sync_time;
|
||||||
|
@ -314,8 +315,6 @@ decode_sequence(GstVaapiDecoderMpeg4 *decoder, const guint8 *buf, guint buf_size
|
||||||
priv->profile_changed = TRUE;
|
priv->profile_changed = TRUE;
|
||||||
}
|
}
|
||||||
priv->seq_pts = gst_adapter_prev_timestamp(priv->adapter, NULL);
|
priv->seq_pts = gst_adapter_prev_timestamp(priv->adapter, NULL);
|
||||||
priv->calculate_pts_diff = TRUE;
|
|
||||||
|
|
||||||
priv->size_changed = TRUE;
|
priv->size_changed = TRUE;
|
||||||
|
|
||||||
return GST_VAAPI_DECODER_STATUS_SUCCESS;
|
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);
|
priv->closed_gop, priv->broken_link);
|
||||||
|
|
||||||
gop_time = gop.hours * 3600 + gop.minutes * 60 + gop.seconds;
|
gop_time = gop.hours * 3600 + gop.minutes * 60 + gop.seconds;
|
||||||
priv->gop_pts = gop_time * GST_SECOND;
|
|
||||||
priv->last_sync_time = gop_time;
|
priv->last_sync_time = gop_time;
|
||||||
priv->sync_time = gop_time;
|
priv->sync_time = gop_time;
|
||||||
|
|
||||||
if (priv->calculate_pts_diff) {
|
if (priv->gop_pts != GST_CLOCK_TIME_NONE)
|
||||||
priv->pts_diff = priv->seq_pts - priv->gop_pts;
|
priv->pts_diff += gop_time * GST_SECOND - priv->gop_pts;
|
||||||
priv->calculate_pts_diff = FALSE;
|
priv->gop_pts = gop_time * GST_SECOND;
|
||||||
}
|
priv->calculate_pts_diff = TRUE;
|
||||||
|
|
||||||
priv->is_first_field = TRUE;
|
priv->is_first_field = TRUE;
|
||||||
|
|
||||||
return GST_VAAPI_DECODER_STATUS_SUCCESS;
|
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
|
static GstVaapiDecoderStatus
|
||||||
decode_picture(GstVaapiDecoderMpeg4 *decoder, const guint8 *buf, guint buf_size)
|
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;
|
priv->prev_t_ref = priv->svh_hdr.temporal_reference;
|
||||||
}
|
}
|
||||||
else {
|
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 */
|
/* Update presentation time, 6.3.5 */
|
||||||
if(vop_hdr->coding_type != GST_MPEG4_B_VOP) {
|
if(vop_hdr->coding_type != GST_MPEG4_B_VOP) {
|
||||||
// increment basing on decoding order
|
// 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;
|
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 */
|
/* Update reference pictures */
|
||||||
/* XXX: consider priv->vol_hdr.low_delay, consider packed video frames for DivX/XviD */
|
/* 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->sub_buffer = NULL;
|
||||||
priv->seq_pts = GST_CLOCK_TIME_NONE;
|
priv->seq_pts = GST_CLOCK_TIME_NONE;
|
||||||
priv->gop_pts = GST_CLOCK_TIME_NONE;
|
priv->gop_pts = GST_CLOCK_TIME_NONE;
|
||||||
|
priv->max_pts = GST_CLOCK_TIME_NONE;
|
||||||
priv->pts_diff = 0;
|
priv->pts_diff = 0;
|
||||||
priv->calculate_pts_diff = TRUE;
|
priv->calculate_pts_diff = TRUE;
|
||||||
priv->is_constructed = FALSE;
|
priv->is_constructed = FALSE;
|
||||||
|
|
Loading…
Reference in a new issue