summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Hervey <bilboed@bilboed.com>2007-05-02 16:06:09 +0000
committerEdward Hervey <bilboed@bilboed.com>2007-05-02 16:06:09 +0000
commit0fcacdde8c5ee4d6cd5994bb467982039c601a6b (patch)
tree39b882da1efd7874a81a2a2935e035168d396746
parent4b2f21c35143c306288cee94bf1802c2263ddbeb (diff)
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 #342962
-rw-r--r--ChangeLog12
m---------common0
-rw-r--r--ext/ffmpeg/gstffmpegdec.c81
3 files changed, 93 insertions, 0 deletions
diff --git a/ChangeLog b/ChangeLog
index 09c8141..d4cc80a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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),
diff --git a/common b/common
-Subproject a19d235c89d99ca7849078d501129f521e30d98
+Subproject 61edc2dc7b8eba179d85a6545e46e0d65239e94
diff --git a/ext/ffmpeg/gstffmpegdec.c b/ext/ffmpeg/gstffmpegdec.c
index 6ea54b0..5fbe7b5 100644
--- a/ext/ffmpeg/gstffmpegdec.c
+++ b/ext/ffmpeg/gstffmpegdec.c
@@ -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:{