ext/ffmpeg/: debug recurring events at LOG level do some timestamp setting heuristics on the pcache, with the net res...

Original commit message from CVS:

* ext/ffmpeg/gstffmpegcodecmap.c: (gst_ffmpeg_codecid_to_caps),
(gst_ffmpeg_smpfmt_to_caps):
* ext/ffmpeg/gstffmpegdec.c: (gst_ffmpegdec_setcaps),
(gst_ffmpegdec_negotiate), (gst_ffmpegdec_frame),
(gst_ffmpegdec_chain):
debug recurring events at LOG level
do some timestamp setting heuristics on the pcache, with the
net result of having more buffers have approximately correct
timestamps.
This allows playback of h263/3gp files taking fps from the demuxer,
which before always set GST_CLOCK_TIME_NONE as timestamp.
This commit is contained in:
Thomas Vander Stichele 2006-02-06 17:51:41 +00:00
parent a479380146
commit 823bc0ce7f
4 changed files with 74 additions and 22 deletions

View file

@ -1,3 +1,17 @@
2006-02-06 Thomas Vander Stichele <thomas at apestaart dot org>
* ext/ffmpeg/gstffmpegcodecmap.c: (gst_ffmpeg_codecid_to_caps),
(gst_ffmpeg_smpfmt_to_caps):
* ext/ffmpeg/gstffmpegdec.c: (gst_ffmpegdec_setcaps),
(gst_ffmpegdec_negotiate), (gst_ffmpegdec_frame),
(gst_ffmpegdec_chain):
debug recurring events at LOG level
do some timestamp setting heuristics on the pcache, with the
net result of having more buffers have approximately correct
timestamps.
This allows playback of h263/3gp files taking fps from the demuxer,
which before always set GST_CLOCK_TIME_NONE as timestamp.
2006-02-04 Tim-Philipp Müller <tim at centricular dot net> 2006-02-04 Tim-Philipp Müller <tim at centricular dot net>
* ext/ffmpeg/gstffmpegcodecmap.c: (gst_ffmpeg_get_palette): * ext/ffmpeg/gstffmpegcodecmap.c: (gst_ffmpeg_get_palette):

2
common

@ -1 +1 @@
Subproject commit 79d67fe009b6120b82d51df860c78e8361f02aea Subproject commit 58567e5519f2d00a4592491db1a6e8302993279e

View file

@ -840,7 +840,7 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id,
gst_ffmpeg_set_palette (caps, context); gst_ffmpeg_set_palette (caps, context);
} }
GST_DEBUG ("caps for codec_id=%d: %" GST_PTR_FORMAT, codec_id, caps); GST_LOG ("caps for codec_id=%d: %" GST_PTR_FORMAT, codec_id, caps);
} else { } else {
GST_WARNING ("No caps found for codec_id=%d", codec_id); GST_WARNING ("No caps found for codec_id=%d", codec_id);
@ -1024,7 +1024,7 @@ gst_ffmpeg_smpfmt_to_caps (enum SampleFormat sample_fmt,
if (caps != NULL) { if (caps != NULL) {
char *str = gst_caps_to_string (caps); char *str = gst_caps_to_string (caps);
GST_DEBUG ("caps for sample_fmt=%d: %s", sample_fmt, str); GST_LOG ("caps for sample_fmt=%d: %s", sample_fmt, str);
g_free (str); g_free (str);
} else { } else {
GST_WARNING ("No caps found for sample_fmt=%d", sample_fmt); GST_WARNING ("No caps found for sample_fmt=%d", sample_fmt);

View file

@ -476,7 +476,7 @@ gst_ffmpegdec_setcaps (GstPad * pad, GstCaps * caps)
const GValue *fps; const GValue *fps;
gboolean ret = TRUE; gboolean ret = TRUE;
GST_DEBUG ("setcaps called"); GST_DEBUG_OBJECT (pad, "setcaps called");
/* close old session */ /* close old session */
gst_ffmpegdec_close (ffmpegdec); gst_ffmpegdec_close (ffmpegdec);
@ -515,8 +515,11 @@ gst_ffmpegdec_setcaps (GstPad * pad, GstCaps * caps)
if (fps != NULL && GST_VALUE_HOLDS_FRACTION (fps)) { if (fps != NULL && GST_VALUE_HOLDS_FRACTION (fps)) {
ffmpegdec->format.video.fps_n = gst_value_get_fraction_numerator (fps); ffmpegdec->format.video.fps_n = gst_value_get_fraction_numerator (fps);
ffmpegdec->format.video.fps_d = gst_value_get_fraction_denominator (fps); ffmpegdec->format.video.fps_d = gst_value_get_fraction_denominator (fps);
GST_DEBUG_OBJECT (ffmpegdec, "Using framerate %d/%d from incoming caps\n",
ffmpegdec->format.video.fps_n, ffmpegdec->format.video.fps_d);
} else { } else {
ffmpegdec->format.video.fps_n = -1; ffmpegdec->format.video.fps_n = -1;
GST_DEBUG_OBJECT (ffmpegdec, "Using framerate from codec\n");
} }
/* do *not* draw edges */ /* do *not* draw edges */
@ -725,8 +728,8 @@ gst_ffmpegdec_negotiate (GstFFMpegDec * ffmpegdec)
ffmpegdec->format.video.fps_d == ffmpegdec->format.video.old_fps_d && ffmpegdec->format.video.fps_d == ffmpegdec->format.video.old_fps_d &&
ffmpegdec->format.video.pix_fmt == ffmpegdec->context->pix_fmt) ffmpegdec->format.video.pix_fmt == ffmpegdec->context->pix_fmt)
return TRUE; return TRUE;
GST_DEBUG GST_DEBUG_OBJECT (ffmpegdec,
("Renegotiating video from %dx%d@ %d/%d fps to %dx%d@ %d/%d fps", "Renegotiating video from %dx%d@ %d/%d fps to %dx%d@ %d/%d fps",
ffmpegdec->format.video.width, ffmpegdec->format.video.height, ffmpegdec->format.video.width, ffmpegdec->format.video.height,
ffmpegdec->format.video.old_fps_n, ffmpegdec->format.video.old_fps_n, ffmpegdec->format.video.old_fps_n, ffmpegdec->format.video.old_fps_n,
ffmpegdec->context->width, ffmpegdec->context->height, ffmpegdec->context->width, ffmpegdec->context->height,
@ -796,7 +799,7 @@ gst_ffmpegdec_frame (GstFFMpegDec * ffmpegdec,
if (ffmpegdec->context->codec == NULL) if (ffmpegdec->context->codec == NULL)
return -1; return -1;
GST_DEBUG_OBJECT (ffmpegdec, GST_LOG_OBJECT (ffmpegdec,
"data:%p, size:%d, *in_ts:%" GST_TIME_FORMAT " inbuf:%p inbuf.ts:%" "data:%p, size:%d, *in_ts:%" GST_TIME_FORMAT " inbuf:%p inbuf.ts:%"
GST_TIME_FORMAT, data, size, GST_TIME_ARGS (*in_ts), inbuf, GST_TIME_FORMAT, data, size, GST_TIME_ARGS (*in_ts), inbuf,
GST_TIME_ARGS ((inbuf) ? GST_BUFFER_TIMESTAMP (inbuf) : 0)); GST_TIME_ARGS ((inbuf) ? GST_BUFFER_TIMESTAMP (inbuf) : 0));
@ -823,8 +826,9 @@ gst_ffmpegdec_frame (GstFFMpegDec * ffmpegdec,
|| (oclass->in_plugin->id == CODEC_ID_MSZH) || (oclass->in_plugin->id == CODEC_ID_MSZH)
|| (oclass->in_plugin->id == CODEC_ID_ZLIB) || (oclass->in_plugin->id == CODEC_ID_ZLIB)
|| (oclass->in_plugin->id == CODEC_ID_VP3); || (oclass->in_plugin->id == CODEC_ID_VP3);
GST_DEBUG_OBJECT (ffmpegdec, GST_LOG_OBJECT (ffmpegdec,
"Decoded video: len=%d, have_data=%d, is_keyframe:%d, is_itype:%d, is_reference:%d", "Decoded video: len=%d, have_data=%d, "
"is_keyframe:%d, is_itype:%d, is_reference:%d",
len, have_data, iskeyframe, is_itype, is_reference); len, have_data, iskeyframe, is_itype, is_reference);
if (ffmpegdec->waiting_for_key) { if (ffmpegdec->waiting_for_key) {
@ -844,7 +848,7 @@ gst_ffmpegdec_frame (GstFFMpegDec * ffmpegdec,
if (!(oclass->in_plugin->capabilities & CODEC_CAP_DELAY) || if (!(oclass->in_plugin->capabilities & CODEC_CAP_DELAY) ||
((iskeyframe || !GST_CLOCK_TIME_IS_VALID (ffmpegdec->next_ts)) && ((iskeyframe || !GST_CLOCK_TIME_IS_VALID (ffmpegdec->next_ts)) &&
GST_CLOCK_TIME_IS_VALID (*in_ts))) { GST_CLOCK_TIME_IS_VALID (*in_ts))) {
GST_DEBUG_OBJECT (ffmpegdec, "setting next_ts to %" GST_TIME_FORMAT, GST_LOG_OBJECT (ffmpegdec, "setting next_ts to %" GST_TIME_FORMAT,
GST_TIME_ARGS (*in_ts)); GST_TIME_ARGS (*in_ts));
ffmpegdec->next_ts = *in_ts; ffmpegdec->next_ts = *in_ts;
*in_ts = GST_CLOCK_TIME_NONE; *in_ts = GST_CLOCK_TIME_NONE;
@ -922,8 +926,12 @@ gst_ffmpegdec_frame (GstFFMpegDec * ffmpegdec,
/* If we have used the framerate from the demuxer then /* If we have used the framerate from the demuxer then
* also use the demuxer's timestamp information (#317596) */ * also use the demuxer's timestamp information (#317596) */
if (ffmpegdec->format.video.fps_n != -1 && inbuf != NULL) { if (ffmpegdec->format.video.fps_n != -1 && inbuf != NULL) {
GST_LOG_OBJECT (ffmpegdec, "using incoming buffer's timestamps");
GST_LOG_OBJECT (ffmpegdec, "incoming timestamp %" GST_TIME_FORMAT,
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (inbuf)));
gst_buffer_stamp (outbuf, inbuf); gst_buffer_stamp (outbuf, inbuf);
} else { } else {
GST_LOG_OBJECT (ffmpegdec, "using decoder's timestamps");
GST_BUFFER_TIMESTAMP (outbuf) = ffmpegdec->next_ts; GST_BUFFER_TIMESTAMP (outbuf) = ffmpegdec->next_ts;
if (ffmpegdec->context->time_base.num != 0 && if (ffmpegdec->context->time_base.num != 0 &&
ffmpegdec->context->time_base.den != 0) { ffmpegdec->context->time_base.den != 0) {
@ -940,9 +948,12 @@ gst_ffmpegdec_frame (GstFFMpegDec * ffmpegdec,
GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf))); GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)));
ffmpegdec->next_ts += GST_BUFFER_DURATION (outbuf); ffmpegdec->next_ts += GST_BUFFER_DURATION (outbuf);
} else { } else {
GST_DEBUG_OBJECT (ffmpegdec, "setting next_ts to NONE");
ffmpegdec->next_ts = GST_CLOCK_TIME_NONE; ffmpegdec->next_ts = GST_CLOCK_TIME_NONE;
} }
} }
GST_LOG_OBJECT (ffmpegdec, "outgoing timestamp %" GST_TIME_FORMAT,
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)));
} else if (ffmpegdec->picture->pict_type != -1 && } else if (ffmpegdec->picture->pict_type != -1 &&
oclass->in_plugin->capabilities & CODEC_CAP_DELAY) { oclass->in_plugin->capabilities & CODEC_CAP_DELAY) {
/* update time for skip-frame */ /* update time for skip-frame */
@ -967,6 +978,7 @@ gst_ffmpegdec_frame (GstFFMpegDec * ffmpegdec,
GST_TIME_ARGS (dur)); GST_TIME_ARGS (dur));
ffmpegdec->next_ts += dur; ffmpegdec->next_ts += dur;
} else { } else {
GST_DEBUG_OBJECT (ffmpegdec, "setting next_ts to NONE");
ffmpegdec->next_ts = GST_CLOCK_TIME_NONE; ffmpegdec->next_ts = GST_CLOCK_TIME_NONE;
} }
} }
@ -1028,8 +1040,8 @@ gst_ffmpegdec_frame (GstFFMpegDec * ffmpegdec,
} }
if (have_data) { if (have_data) {
GST_DEBUG_OBJECT (ffmpegdec, "Decoded data, now pushing (%" GST_LOG_OBJECT (ffmpegdec, "Decoded data, now pushing with timestamp %"
GST_TIME_FORMAT ")", GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf))); GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)));
gst_buffer_set_caps (outbuf, GST_PAD_CAPS (ffmpegdec->srcpad)); gst_buffer_set_caps (outbuf, GST_PAD_CAPS (ffmpegdec->srcpad));
*ret = gst_pad_push (ffmpegdec->srcpad, outbuf); *ret = gst_pad_push (ffmpegdec->srcpad, outbuf);
@ -1137,7 +1149,7 @@ gst_ffmpegdec_chain (GstPad * pad, GstBuffer * inbuf)
if (!ffmpegdec->opened) if (!ffmpegdec->opened)
goto not_negotiated; goto not_negotiated;
GST_DEBUG_OBJECT (ffmpegdec, GST_LOG_OBJECT (ffmpegdec,
"Received new data of size %d, time %" GST_TIME_FORMAT " next_ts %" "Received new data of size %d, time %" GST_TIME_FORMAT " next_ts %"
GST_TIME_FORMAT, GST_BUFFER_SIZE (inbuf), GST_TIME_FORMAT, GST_BUFFER_SIZE (inbuf),
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (inbuf)), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (inbuf)),
@ -1145,9 +1157,32 @@ gst_ffmpegdec_chain (GstPad * pad, GstBuffer * inbuf)
/* parse cache joining */ /* parse cache joining */
if (ffmpegdec->pcache) { if (ffmpegdec->pcache) {
GstClockTime timestamp = GST_CLOCK_TIME_NONE;
GstClockTime duration = GST_CLOCK_TIME_NONE;
/* decide on resulting timestamp/duration before we give away our ref */
/* since the cache is all data that did not result in an outgoing frame,
* we should timestamp with the new incoming buffer. This is probably
* not entirely correct though, but better than nothing. */
if (GST_BUFFER_TIMESTAMP_IS_VALID (inbuf))
timestamp = GST_BUFFER_TIMESTAMP (inbuf);
if (GST_BUFFER_DURATION_IS_VALID (ffmpegdec->pcache)
&& GST_BUFFER_DURATION_IS_VALID (inbuf))
duration = GST_BUFFER_DURATION (ffmpegdec->pcache) +
GST_BUFFER_DURATION (inbuf);
inbuf = gst_buffer_join (ffmpegdec->pcache, inbuf); inbuf = gst_buffer_join (ffmpegdec->pcache, inbuf);
/* inbuf = gst_buffer_span (ffmpegdec->pcache, 0, inbuf, */ /* inbuf = gst_buffer_span (ffmpegdec->pcache, 0, inbuf, */
/* GST_BUFFER_SIZE (ffmpegdec->pcache) + GST_BUFFER_SIZE (inbuf)); */ /* GST_BUFFER_SIZE (ffmpegdec->pcache) + GST_BUFFER_SIZE (inbuf)); */
/* update time info as appropriate */
GST_BUFFER_TIMESTAMP (inbuf) = timestamp;
GST_BUFFER_DURATION (inbuf) = duration;
GST_LOG_OBJECT (ffmpegdec, "joined parse cache, inbuf now has ts %" GST_TIME_FORMAT
" and duration %" GST_TIME_FORMAT, GST_TIME_ARGS (timestamp),
GST_TIME_ARGS (duration));
ffmpegdec->pcache = NULL; ffmpegdec->pcache = NULL;
bdata = GST_BUFFER_DATA (inbuf); bdata = GST_BUFFER_DATA (inbuf);
bsize = GST_BUFFER_SIZE (inbuf); bsize = GST_BUFFER_SIZE (inbuf);
@ -1176,7 +1211,7 @@ gst_ffmpegdec_chain (GstPad * pad, GstBuffer * inbuf)
res = av_parser_parse (ffmpegdec->pctx, ffmpegdec->context, res = av_parser_parse (ffmpegdec->pctx, ffmpegdec->context,
&data, &size, bdata, bsize, ffpts, ffpts); &data, &size, bdata, bsize, ffpts, ffpts);
GST_DEBUG_OBJECT (ffmpegdec, "Parsed video frame, res=%d, size=%d", GST_LOG_OBJECT (ffmpegdec, "Parsed video frame, res=%d, size=%d",
res, size); res, size);
in_ts = gst_ffmpeg_time_ff_to_gst (ffmpegdec->pctx->pts, in_ts = gst_ffmpeg_time_ff_to_gst (ffmpegdec->pctx->pts,
@ -1207,10 +1242,13 @@ gst_ffmpegdec_chain (GstPad * pad, GstBuffer * inbuf)
} while (bsize > 0); } while (bsize > 0);
if ((ffmpegdec->pctx || oclass->in_plugin->id == CODEC_ID_MP3) && bsize > 0) { if ((ffmpegdec->pctx || oclass->in_plugin->id == CODEC_ID_MP3) && bsize > 0) {
GST_DEBUG_OBJECT (ffmpegdec, "Keeping %d bytes of data", bsize); GST_LOG_OBJECT (ffmpegdec, "Keeping %d bytes of data", bsize);
ffmpegdec->pcache = gst_buffer_create_sub (inbuf, ffmpegdec->pcache = gst_buffer_create_sub (inbuf,
GST_BUFFER_SIZE (inbuf) - bsize, bsize); GST_BUFFER_SIZE (inbuf) - bsize, bsize);
/* we keep timestamp, even though all we really know is that the correct
* timestamp is not below the one from inbuf */
GST_BUFFER_TIMESTAMP (ffmpegdec->pcache) = GST_BUFFER_TIMESTAMP (inbuf);
} else if (bsize > 0) { } else if (bsize > 0) {
GST_DEBUG_OBJECT (ffmpegdec, "Dropping %d bytes of data", bsize); GST_DEBUG_OBJECT (ffmpegdec, "Dropping %d bytes of data", bsize);
} }