ext/ffmpeg/gstffmpegdec.c: If we have a parser and we did not consume any of the bytes of a new buffer, make sure we ...

Original commit message from CVS:
* ext/ffmpeg/gstffmpegdec.c: (gst_ffmpegdec_frame),
(gst_ffmpegdec_chain):
If we have a parser and we did not consume any of the bytes of a new
buffer, make sure we submit the buffer again with its original timestamp
instead of a -1 timestamp. Fixes various h264 cases with reordered
frames.
If we have a discont and a timestamp but the first buffer after the
discont did not produce any data, make sure we set the timestamp on the
next buffer instead. Fixes initial timestamp on realaudio in many cases.
This commit is contained in:
Wim Taymans 2008-09-04 14:08:50 +00:00
parent 5162694c1e
commit d16e6f1ecc
2 changed files with 42 additions and 6 deletions

View file

@ -1,3 +1,15 @@
2008-09-04 Wim Taymans <wim.taymans@collabora.co.uk>
* ext/ffmpeg/gstffmpegdec.c: (gst_ffmpegdec_frame),
(gst_ffmpegdec_chain):
If we have a parser and we did not consume any of the bytes of a new
buffer, make sure we submit the buffer again with its original timestamp
instead of a -1 timestamp. Fixes various h264 cases with reordered
frames.
If we have a discont and a timestamp but the first buffer after the
discont did not produce any data, make sure we set the timestamp on the
next buffer instead. Fixes initial timestamp on realaudio in many cases.
2008-09-04 Wim Taymans <wim.taymans@collabora.co.uk>
* ext/ffmpeg/gstffmpegcodecmap.c: (nal_escape), (copy_config),

View file

@ -71,6 +71,7 @@ struct _GstFFMpegDec
} format;
gboolean waiting_for_key;
gboolean discont;
gboolean clear_ts;
guint64 next_ts;
guint64 in_ts;
GstClockTime last_out;
@ -1856,6 +1857,14 @@ gst_ffmpegdec_frame (GstFFMpegDec * ffmpegdec,
len =
gst_ffmpegdec_audio_frame (ffmpegdec, data, size, in_timestamp,
in_duration, &outbuf, ret);
/* if we did not get an output buffer and we have a pending discont, don't
* clear the input timestamps, we will put them on the next buffer because
* else we might create the first buffer with a very big timestamp gap. */
if (outbuf == NULL && ffmpegdec->discont) {
GST_DEBUG_OBJECT (ffmpegdec, "no buffer but keeping timestamp");
ffmpegdec->clear_ts = FALSE;
}
break;
default:
GST_ERROR_OBJECT (ffmpegdec, "Asked to decode non-audio/video frame !");
@ -1899,7 +1908,7 @@ gst_ffmpegdec_frame (GstFFMpegDec * ffmpegdec,
/* and off we go */
*ret = gst_pad_push (ffmpegdec->srcpad, outbuf);
} else {
/* reverse playback, queue frame till later */
/* reverse playback, queue frame till later when we get a discont. */
GST_DEBUG_OBJECT (ffmpegdec, "queued frame");
ffmpegdec->queued = g_list_prepend (ffmpegdec->queued, outbuf);
*ret = GST_FLOW_OK;
@ -2122,6 +2131,9 @@ gst_ffmpegdec_chain (GstPad * pad, GstBuffer * inbuf)
ffmpegdec->last_out = GST_CLOCK_TIME_NONE;
ffmpegdec->next_ts = GST_CLOCK_TIME_NONE;
}
/* by default we clear the input timestamp after decoding each frame so that
* interpollation can work. */
ffmpegdec->clear_ts = TRUE;
oclass = (GstFFMpegDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec));
@ -2198,9 +2210,16 @@ gst_ffmpegdec_chain (GstPad * pad, GstBuffer * inbuf)
GST_LOG_OBJECT (ffmpegdec, "consuming %d bytes. ts:%"
GST_TIME_FORMAT, size, GST_TIME_ARGS (ffmpegdec->pctx->pts));
/* there is output, set pointers for next round. */
bsize -= res;
bdata += res;
if (res) {
/* there is output, set pointers for next round. */
bsize -= res;
bdata += res;
}
else {
/* Parser did not consume any data, make sure we don't clear the
* timestamp for the next round */
ffmpegdec->clear_ts = FALSE;
}
/* if there is no output, we must break and wait for more data. also the
* timestamp in the context is not updated. */
@ -2279,8 +2298,13 @@ gst_ffmpegdec_chain (GstPad * pad, GstBuffer * inbuf)
/* make sure we don't use the same old timestamp for the next frame and let
* the interpollation take care of it. */
in_timestamp = GST_CLOCK_TIME_NONE;
in_duration = GST_CLOCK_TIME_NONE;
if (ffmpegdec->clear_ts) {
in_timestamp = GST_CLOCK_TIME_NONE;
in_duration = GST_CLOCK_TIME_NONE;
}
else {
ffmpegdec->clear_ts = TRUE;
}
GST_LOG_OBJECT (ffmpegdec, "Before (while bsize>0). bsize:%d , bdata:%p",
bsize, bdata);