ext/ffmpeg/gstffmpegdec.c: Fix timestamping for out-of-order incoming buffers. Instead of blindly copying the incomin...

Original commit message from CVS:
* ext/ffmpeg/gstffmpegdec.c: (gst_ffmpegdec_init),
(gst_ffmpegdec_open), (gst_ffmpegdec_save_incoming_values),
(gst_ffmpegdec_get_best_values), (gst_ffmpegdec_video_frame),
(gst_ffmpegdec_sink_event):
Fix timestamping for out-of-order incoming buffers. Instead of blindly
copying the incoming buffer timestamps on the outgoing buffers we cache
the latest 2 incoming buffer timestamps and duration and make a wise
choice as to what the outgoing buffer timestamp and duration should be.
Fixes 
This commit is contained in:
Edward Hervey 2007-05-02 16:06:09 +00:00
parent 4b2f21c351
commit 0fcacdde8c
3 changed files with 94 additions and 1 deletions

View file

@ -1,3 +1,15 @@
2007-05-02 Edward Hervey <edward@fluendo.com>
* ext/ffmpeg/gstffmpegdec.c: (gst_ffmpegdec_init),
(gst_ffmpegdec_open), (gst_ffmpegdec_save_incoming_values),
(gst_ffmpegdec_get_best_values), (gst_ffmpegdec_video_frame),
(gst_ffmpegdec_sink_event):
Fix timestamping for out-of-order incoming buffers. Instead of blindly
copying the incoming buffer timestamps on the outgoing buffers we cache
the latest 2 incoming buffer timestamps and duration and make a wise
choice as to what the outgoing buffer timestamp and duration should be.
Fixes #342962
2007-04-25 Edward Hervey <edward@fluendo.com>
* ext/ffmpeg/gstffmpegcodecmap.c: (gst_ffmpeg_codecid_to_caps),

2
common

@ -1 +1 @@
Subproject commit a19d235c89d99ca7849078d501129f521e30d98d
Subproject commit 61edc2dc7b8eba179d85a6545e46e0d65239e94d

View file

@ -88,6 +88,11 @@ struct _GstFFMpegDec
/* clipping segment */
GstSegment segment;
/* out-of-order incoming buffer special handling */
gboolean outoforder;
GstClockTime tstamp1, tstamp2;
GstClockTime dur1, dur2;
};
typedef struct _GstFFMpegDecClass GstFFMpegDecClass;
@ -310,6 +315,9 @@ gst_ffmpegdec_init (GstFFMpegDec * ffmpegdec)
ffmpegdec->format.video.fps_n = -1;
ffmpegdec->format.video.old_fps_n = -1;
gst_segment_init (&ffmpegdec->segment, GST_FORMAT_TIME);
ffmpegdec->tstamp1 = ffmpegdec->tstamp2 = GST_CLOCK_TIME_NONE;
ffmpegdec->dur1 = ffmpegdec->dur2 = GST_CLOCK_TIME_NONE;
}
static void
@ -522,6 +530,11 @@ gst_ffmpegdec_open (GstFFMpegDec * ffmpegdec)
default:
break;
}
/* out-of-order incoming buffer handling */
if ((oclass->in_plugin->id == CODEC_ID_H264) && (ffmpegdec->context->extradata_size != 0))
ffmpegdec->outoforder = TRUE;
ffmpegdec->next_ts = GST_CLOCK_TIME_NONE;
ffmpegdec->last_buffer = NULL;
/* FIXME, reset_qos holds the LOCK */
@ -826,6 +839,64 @@ no_par:
}
}
static void
gst_ffmpegdec_save_incoming_values (GstFFMpegDec * ffmpegdec, GstClockTime timestamp,
GstClockTime duration)
{
GST_LOG_OBJECT (ffmpegdec, "BEFORE timestamp:%"GST_TIME_FORMAT"/%"GST_TIME_FORMAT
" duration:%"GST_TIME_FORMAT"/%"GST_TIME_FORMAT,
GST_TIME_ARGS (ffmpegdec->tstamp1), GST_TIME_ARGS (ffmpegdec->tstamp2),
GST_TIME_ARGS (ffmpegdec->dur1), GST_TIME_ARGS (ffmpegdec->dur2));
/* shift previous new values to oldest */
if (ffmpegdec->tstamp2 != GST_CLOCK_TIME_NONE)
ffmpegdec->tstamp1 = ffmpegdec->tstamp2;
ffmpegdec->dur1 = ffmpegdec->dur2;
/* store new values */
ffmpegdec->tstamp2 = timestamp;
ffmpegdec->dur2 = duration;
GST_LOG_OBJECT (ffmpegdec, "AFTER timestamp:%"GST_TIME_FORMAT"/%"GST_TIME_FORMAT
" duration:%"GST_TIME_FORMAT"/%"GST_TIME_FORMAT,
GST_TIME_ARGS (ffmpegdec->tstamp1), GST_TIME_ARGS (ffmpegdec->tstamp2),
GST_TIME_ARGS (ffmpegdec->dur1), GST_TIME_ARGS (ffmpegdec->dur2));
}
static void
gst_ffmpegdec_get_best_values (GstFFMpegDec * ffmpegdec, GstClockTime *timestamp,
GstClockTime *duration)
{
/* Best timestamp is the smallest valid timestamp */
if (ffmpegdec->tstamp1 == GST_CLOCK_TIME_NONE) {
*timestamp = ffmpegdec->tstamp2;
ffmpegdec->tstamp2 = GST_CLOCK_TIME_NONE;
} else if (ffmpegdec->tstamp2 == GST_CLOCK_TIME_NONE) {
*timestamp = ffmpegdec->tstamp1;
ffmpegdec->tstamp1 = GST_CLOCK_TIME_NONE;
} else if (ffmpegdec->tstamp1 < ffmpegdec->tstamp2) {
*timestamp = ffmpegdec->tstamp1;
ffmpegdec->tstamp1 = GST_CLOCK_TIME_NONE;
} else {
*timestamp = ffmpegdec->tstamp2;
ffmpegdec->tstamp2 = GST_CLOCK_TIME_NONE;
}
/* Best duration is the oldest valid one */
if (ffmpegdec->dur1 == GST_CLOCK_TIME_NONE) {
*duration = ffmpegdec->dur2;
ffmpegdec->dur2 = GST_CLOCK_TIME_NONE;
} else {
*duration = ffmpegdec->dur1;
ffmpegdec->dur1 = GST_CLOCK_TIME_NONE;
}
GST_LOG_OBJECT (ffmpegdec, "Returning timestamp:%"GST_TIME_FORMAT" duration:%"GST_TIME_FORMAT,
GST_TIME_ARGS (*timestamp),
GST_TIME_ARGS (*duration));
}
static gboolean
gst_ffmpegdec_negotiate (GstFFMpegDec * ffmpegdec)
{
@ -1222,6 +1293,10 @@ gst_ffmpegdec_video_frame (GstFFMpegDec * ffmpegdec,
ffmpegdec->context->opaque = ffmpegdec;
/* incoming out-of-order buffer timestamp buffering */
if (ffmpegdec->outoforder)
gst_ffmpegdec_save_incoming_values (ffmpegdec, in_timestamp, in_duration);
/* run QoS code, returns FALSE if we can skip decoding this
* frame entirely. */
if (G_UNLIKELY (!gst_ffmpegdec_do_qos (ffmpegdec, in_timestamp,
@ -1272,6 +1347,10 @@ gst_ffmpegdec_video_frame (GstFFMpegDec * ffmpegdec,
if (G_UNLIKELY (*ret != GST_FLOW_OK))
goto no_output;
/* Special handling for out-of-order incoming buffers */
if (ffmpegdec->outoforder)
gst_ffmpegdec_get_best_values (ffmpegdec, &in_timestamp, &in_duration);
/*
* Timestamps:
*
@ -1707,6 +1786,8 @@ gst_ffmpegdec_sink_event (GstPad * pad, GstEvent * event)
gst_ffmpegdec_flush_pcache (ffmpegdec);
ffmpegdec->waiting_for_key = TRUE;
gst_segment_init (&ffmpegdec->segment, GST_FORMAT_TIME);
ffmpegdec->tstamp1 = ffmpegdec->tstamp2 = GST_CLOCK_TIME_NONE;
ffmpegdec->dur1 = ffmpegdec->dur2 = GST_CLOCK_TIME_NONE;
break;
}
case GST_EVENT_NEWSEGMENT:{