diff --git a/ChangeLog b/ChangeLog index e0398c402e..dc9498c096 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2005-07-27 Ronald S. Bultje + + * ext/ffmpeg/gstffmpegcodecmap.h: + * ext/ffmpeg/gstffmpegdec.c: (gst_ffmpegdec_connect), + (gst_ffmpegdec_frame), (gst_ffmpegdec_chain): + * ext/ffmpeg/gstffmpegdemux.c: (gst_ffmpegdemux_loop): + * ext/ffmpeg/gstffmpegenc.c: (gst_ffmpegenc_link), + (gst_ffmpegenc_chain_video): + * ext/ffmpeg/gstffmpegmux.c: (gst_ffmpegmux_loop): + Use special functions for timestamp-conversion again, since we + otherwise don't handle clocktimenone correctly (#311593). + 2005-07-24 Ronald S. Bultje * ext/ffmpeg/gstffmpegcodecmap.c: (gst_ffmpeg_caps_to_codecid): diff --git a/ext/ffmpeg/gstffmpegcodecmap.h b/ext/ffmpeg/gstffmpegcodecmap.h index 8b6822fab9..9a7858e8cd 100644 --- a/ext/ffmpeg/gstffmpegcodecmap.h +++ b/ext/ffmpeg/gstffmpegcodecmap.h @@ -132,4 +132,37 @@ gst_ffmpeg_img_convert (AVPicture * dst, int dst_pix_fmt, const AVPicture * src, int src_pix_fmt, int src_width, int src_height); +/* + * Convert from/to a GStreamer <-> FFMpeg timestamp. + */ +static inline guint64 +gst_ffmpeg_time_ff_to_gst (gint64 pts, AVRational base) +{ + guint64 out; + + if (pts == AV_NOPTS_VALUE){ + out = GST_CLOCK_TIME_NONE; + } else { + AVRational bq = { 1, GST_SECOND }; + out = av_rescale_q (pts, base, bq); + } + + return out; +} + +static inline gint64 +gst_ffmpeg_time_gst_to_ff (guint64 time, AVRational base) +{ + gint64 out; + + if (!GST_CLOCK_TIME_IS_VALID (time)) { + out = AV_NOPTS_VALUE; + } else { + AVRational bq; + out = av_rescale_q (time, bq, base); + } + + return out; +} + #endif /* __GST_FFMPEG_CODECMAP_H__ */ diff --git a/ext/ffmpeg/gstffmpegdec.c b/ext/ffmpeg/gstffmpegdec.c index 031a1b22f5..0753b207ef 100644 --- a/ext/ffmpeg/gstffmpegdec.c +++ b/ext/ffmpeg/gstffmpegdec.c @@ -453,6 +453,10 @@ gst_ffmpegdec_connect (GstPad * pad, const GstCaps * caps) /* get size and so */ gst_ffmpeg_caps_with_codecid (oclass->in_plugin->id, oclass->in_plugin->type, caps, ffmpegdec->context); + if (!ffmpegdec->context->time_base.den) { + ffmpegdec->context->time_base.num = 1; + ffmpegdec->context->time_base.den = 25; + } /* get pixel aspect ratio if it's set */ structure = gst_caps_get_structure (caps, 0); @@ -807,7 +811,8 @@ gst_ffmpegdec_frame (GstFFMpegDec * ffmpegdec, (2 * ffmpegdec->context->channels * ffmpegdec->context->sample_rate); ffmpegdec->next_ts += GST_BUFFER_DURATION (outbuf); - *in_ts += GST_BUFFER_DURATION (outbuf); + if (GST_CLOCK_TIME_IS_VALID (*in_ts)) + *in_ts += GST_BUFFER_DURATION (outbuf); } else if (len > 0 && have_data == 0) { /* cache output, because it may be used for caching (in-place) */ ffmpegdec->last_buffer = outbuf; @@ -972,10 +977,8 @@ gst_ffmpegdec_chain (GstPad * pad, GstData * _data) if (ffmpegdec->pctx) { gint res; gint64 ffpts; - AVRational bq = { 1, 1000000000 }; - - ffpts = av_rescale_q (in_ts, bq, ffmpegdec->context->time_base); + ffpts = gst_ffmpeg_time_gst_to_ff (in_ts, ffmpegdec->context->time_base); res = av_parser_parse (ffmpegdec->pctx, ffmpegdec->context, &data, &size, bdata, bsize, ffpts, ffpts); @@ -983,8 +986,8 @@ gst_ffmpegdec_chain (GstPad * pad, GstData * _data) GST_DEBUG_OBJECT (ffmpegdec, "Parsed video frame, res=%d, size=%d", res, size); - in_ts = av_rescale_q (in_ts, ffmpegdec->context->time_base, bq); - + in_ts = gst_ffmpeg_time_ff_to_gst (ffmpegdec->pctx->pts, + ffmpegdec->context->time_base); if (res == 0 || size == 0) break; else { diff --git a/ext/ffmpeg/gstffmpegdemux.c b/ext/ffmpeg/gstffmpegdemux.c index b7710b31a5..de76d981f9 100644 --- a/ext/ffmpeg/gstffmpegdemux.c +++ b/ext/ffmpeg/gstffmpegdemux.c @@ -655,12 +655,11 @@ gst_ffmpegdemux_loop (GstElement * element) memcpy (GST_BUFFER_DATA (outbuf), pkt.data, pkt.size); GST_BUFFER_SIZE (outbuf) = pkt.size; - if (pkt.pts != AV_NOPTS_VALUE) { - AVRational bq = { 1, GST_SECOND }; - GST_BUFFER_TIMESTAMP (outbuf) = av_rescale_q (pkt.pts, - demux->context->streams[pkt.stream_index]->time_base, bq); + GST_BUFFER_TIMESTAMP (outbuf) = + gst_ffmpeg_time_ff_to_gst (pkt.pts, + demux->context->streams[pkt.stream_index]->time_base); + if (GST_BUFFER_TIMESTAMP_IS_VALID (outbuf)) demux->last_ts[stream->index] = GST_BUFFER_TIMESTAMP (outbuf); - } if (pkt.flags & PKT_FLAG_KEY) GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_KEY_UNIT); diff --git a/ext/ffmpeg/gstffmpegenc.c b/ext/ffmpeg/gstffmpegenc.c index cbd87ba85b..ca859f2178 100644 --- a/ext/ffmpeg/gstffmpegenc.c +++ b/ext/ffmpeg/gstffmpegenc.c @@ -385,10 +385,10 @@ gst_ffmpegenc_link (GstPad * pad, const GstCaps * caps) /* fetch pix_fmt and so on */ gst_ffmpeg_caps_with_codectype (oclass->in_plugin->type, caps, ffmpegenc->context); - - /* FIXME: prevent nego errors because of fixed-caps */ - if (!ffmpegenc->context->time_base.den) - ffmpegenc->context->time_base.den = DEFAULT_FRAME_RATE_BASE * 25; + if (!ffmpegenc->context->time_base.den) { + ffmpegenc->context->time_base.den = 25; + ffmpegenc->context->time_base.num = 1; + } pix_fmt = ffmpegenc->context->pix_fmt; @@ -480,8 +480,8 @@ gst_ffmpegenc_chain_video (GstPad * pad, GstData * _data) g_return_if_fail (frame_size == GST_BUFFER_SIZE (inbuf)); ffmpegenc->picture->pts = - av_rescale_q (GST_BUFFER_TIMESTAMP (inbuf), - bq, ffmpegenc->context->time_base); + gst_ffmpeg_time_gst_to_ff (GST_BUFFER_TIMESTAMP (inbuf), + ffmpegenc->context->time_base); outbuf = gst_buffer_new_and_alloc (ffmpegenc->buffer_size); ret_size = avcodec_encode_video (ffmpegenc->context, diff --git a/ext/ffmpeg/gstffmpegmux.c b/ext/ffmpeg/gstffmpegmux.c index 839ec5fe87..18583f9859 100644 --- a/ext/ffmpeg/gstffmpegmux.c +++ b/ext/ffmpeg/gstffmpegmux.c @@ -481,8 +481,8 @@ gst_ffmpegmux_loop (GstElement * element) ffmpegmux->context->streams[bufnum]->codec->frame_number++; /* set time */ - pkt.pts = av_rescale_q (GST_BUFFER_TIMESTAMP (buf), - bq, ffmpegmux->context->streams[bufnum]->time_base); + pkt.pts = gst_ffmpeg_time_gst_to_ff (GST_BUFFER_TIMESTAMP (buf), + ffmpegmux->context->streams[bufnum]->time_base); pkt.dts = pkt.pts; pkt.data = GST_BUFFER_DATA (buf); pkt.size = GST_BUFFER_SIZE (buf);