mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-19 14:56:36 +00:00
ext/ffmpeg/gstffmpegdec.c: Backported some fixes from 0.8. Most importantly, use demuxer's timestamping information i...
Original commit message from CVS: * ext/ffmpeg/gstffmpegdec.c: (gst_ffmpegdec_init), (gst_ffmpegdec_close), (gst_ffmpegdec_open), (gst_ffmpegdec_setcaps), (gst_ffmpegdec_negotiate), (gst_ffmpegdec_frame), (gst_ffmpegdec_sink_event), (gst_ffmpegdec_chain): Backported some fixes from 0.8. Most importantly, use demuxer's timestamping information if we use its framerate value. Makes divx play properly again among other things (#319616, #313970, #317596). Did not backport memory leak fix.
This commit is contained in:
parent
9645689256
commit
13a44d4f6a
2 changed files with 69 additions and 34 deletions
13
ChangeLog
13
ChangeLog
|
@ -1,3 +1,16 @@
|
||||||
|
2005-10-26 Tim-Philipp Müller <tim at centricular dot net>
|
||||||
|
|
||||||
|
* ext/ffmpeg/gstffmpegdec.c: (gst_ffmpegdec_init),
|
||||||
|
(gst_ffmpegdec_close), (gst_ffmpegdec_open),
|
||||||
|
(gst_ffmpegdec_setcaps), (gst_ffmpegdec_negotiate),
|
||||||
|
(gst_ffmpegdec_frame), (gst_ffmpegdec_sink_event),
|
||||||
|
(gst_ffmpegdec_chain):
|
||||||
|
Backported some fixes from 0.8. Most importantly, use
|
||||||
|
demuxer's timestamping information if we use its framerate
|
||||||
|
value. Makes divx play properly again among other things
|
||||||
|
(#319616, #313970, #317596). Did not backport memory leak
|
||||||
|
fix.
|
||||||
|
|
||||||
2005-10-24 Thomas Vander Stichele <thomas at apestaart dot org>
|
2005-10-24 Thomas Vander Stichele <thomas at apestaart dot org>
|
||||||
|
|
||||||
* configure.ac:
|
* configure.ac:
|
||||||
|
|
|
@ -53,7 +53,8 @@ struct _GstFFMpegDec
|
||||||
gboolean opened;
|
gboolean opened;
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
gint width, height, fps, fps_base;
|
gint width, height;
|
||||||
|
gdouble fps, old_fps;
|
||||||
enum PixelFormat pix_fmt;
|
enum PixelFormat pix_fmt;
|
||||||
} video;
|
} video;
|
||||||
struct {
|
struct {
|
||||||
|
@ -284,6 +285,9 @@ gst_ffmpegdec_init (GstFFMpegDec * ffmpegdec)
|
||||||
ffmpegdec->hurry_up = ffmpegdec->lowres = 0;
|
ffmpegdec->hurry_up = ffmpegdec->lowres = 0;
|
||||||
|
|
||||||
ffmpegdec->last_buffer = NULL;
|
ffmpegdec->last_buffer = NULL;
|
||||||
|
|
||||||
|
ffmpegdec->format.video.fps = -1.0;
|
||||||
|
ffmpegdec->format.video.old_fps = -1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -394,6 +398,9 @@ gst_ffmpegdec_close (GstFFMpegDec *ffmpegdec)
|
||||||
av_parser_close (ffmpegdec->pctx);
|
av_parser_close (ffmpegdec->pctx);
|
||||||
ffmpegdec->pctx = NULL;
|
ffmpegdec->pctx = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ffmpegdec->format.video.fps = -1.0;
|
||||||
|
ffmpegdec->format.video.old_fps = -1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@ -423,8 +430,6 @@ gst_ffmpegdec_open (GstFFMpegDec *ffmpegdec)
|
||||||
case CODEC_TYPE_VIDEO:
|
case CODEC_TYPE_VIDEO:
|
||||||
ffmpegdec->format.video.width = 0;
|
ffmpegdec->format.video.width = 0;
|
||||||
ffmpegdec->format.video.height = 0;
|
ffmpegdec->format.video.height = 0;
|
||||||
ffmpegdec->format.video.fps = 0;
|
|
||||||
ffmpegdec->format.video.fps_base = 0;
|
|
||||||
ffmpegdec->format.video.pix_fmt = PIX_FMT_NB;
|
ffmpegdec->format.video.pix_fmt = PIX_FMT_NB;
|
||||||
break;
|
break;
|
||||||
case CODEC_TYPE_AUDIO:
|
case CODEC_TYPE_AUDIO:
|
||||||
|
@ -475,7 +480,8 @@ gst_ffmpegdec_setcaps (GstPad * pad, GstCaps * caps)
|
||||||
gst_ffmpeg_caps_with_codecid (oclass->in_plugin->id,
|
gst_ffmpeg_caps_with_codecid (oclass->in_plugin->id,
|
||||||
oclass->in_plugin->type, caps, ffmpegdec->context);
|
oclass->in_plugin->type, caps, ffmpegdec->context);
|
||||||
|
|
||||||
if (!ffmpegdec->context->time_base.den) {
|
if (!ffmpegdec->context->time_base.den ||
|
||||||
|
!ffmpegdec->context->time_base.num) {
|
||||||
GST_DEBUG ("forcing 25/1 framerate");
|
GST_DEBUG ("forcing 25/1 framerate");
|
||||||
ffmpegdec->context->time_base.num = 1;
|
ffmpegdec->context->time_base.num = 1;
|
||||||
ffmpegdec->context->time_base.den = 25;
|
ffmpegdec->context->time_base.den = 25;
|
||||||
|
@ -490,6 +496,15 @@ gst_ffmpegdec_setcaps (GstPad * pad, GstCaps * caps)
|
||||||
gst_value_init_and_copy (ffmpegdec->par, par);
|
gst_value_init_and_copy (ffmpegdec->par, par);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (gst_structure_has_field (structure, "framerate")) {
|
||||||
|
ffmpegdec->format.video.old_fps = ffmpegdec->format.video.fps;
|
||||||
|
gst_structure_get_double (structure, "framerate",
|
||||||
|
&ffmpegdec->format.video.fps);
|
||||||
|
} else {
|
||||||
|
ffmpegdec->format.video.old_fps = ffmpegdec->format.video.fps;
|
||||||
|
ffmpegdec->format.video.fps = -1.0;
|
||||||
|
}
|
||||||
|
|
||||||
/* do *not* draw edges */
|
/* do *not* draw edges */
|
||||||
ffmpegdec->context->flags |= CODEC_FLAG_EMU_EDGE;
|
ffmpegdec->context->flags |= CODEC_FLAG_EMU_EDGE;
|
||||||
|
|
||||||
|
@ -612,21 +627,16 @@ gst_ffmpegdec_negotiate (GstFFMpegDec * ffmpegdec)
|
||||||
case CODEC_TYPE_VIDEO:
|
case CODEC_TYPE_VIDEO:
|
||||||
if (ffmpegdec->format.video.width == ffmpegdec->context->width &&
|
if (ffmpegdec->format.video.width == ffmpegdec->context->width &&
|
||||||
ffmpegdec->format.video.height == ffmpegdec->context->height &&
|
ffmpegdec->format.video.height == ffmpegdec->context->height &&
|
||||||
ffmpegdec->format.video.fps == ffmpegdec->context->time_base.den &&
|
ffmpegdec->format.video.fps == ffmpegdec->format.video.old_fps &&
|
||||||
ffmpegdec->format.video.fps_base ==
|
|
||||||
ffmpegdec->context->time_base.num &&
|
|
||||||
ffmpegdec->format.video.pix_fmt == ffmpegdec->context->pix_fmt)
|
ffmpegdec->format.video.pix_fmt == ffmpegdec->context->pix_fmt)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
GST_DEBUG ("Renegotiating video from %dx%d@%d/%dfps to %dx%d@%d/%dfps",
|
GST_DEBUG ("Renegotiating video from %dx%d@%0.2ffps to %dx%d@%0.2ffps",
|
||||||
ffmpegdec->format.video.width, ffmpegdec->format.video.height,
|
ffmpegdec->format.video.width, ffmpegdec->format.video.height,
|
||||||
ffmpegdec->format.video.fps, ffmpegdec->format.video.fps_base,
|
ffmpegdec->format.video.old_fps, ffmpegdec->context->width,
|
||||||
ffmpegdec->context->width, ffmpegdec->context->height,
|
ffmpegdec->context->height, ffmpegdec->format.video.old_fps);
|
||||||
ffmpegdec->context->time_base.den,
|
|
||||||
ffmpegdec->context->time_base.num);
|
|
||||||
ffmpegdec->format.video.width = ffmpegdec->context->width;
|
ffmpegdec->format.video.width = ffmpegdec->context->width;
|
||||||
ffmpegdec->format.video.height = ffmpegdec->context->height;
|
ffmpegdec->format.video.height = ffmpegdec->context->height;
|
||||||
ffmpegdec->format.video.fps = ffmpegdec->context->time_base.den;
|
ffmpegdec->format.video.old_fps = ffmpegdec->format.video.fps;
|
||||||
ffmpegdec->format.video.fps_base = ffmpegdec->context->time_base.num;
|
|
||||||
ffmpegdec->format.video.pix_fmt = ffmpegdec->context->pix_fmt;
|
ffmpegdec->format.video.pix_fmt = ffmpegdec->context->pix_fmt;
|
||||||
break;
|
break;
|
||||||
case CODEC_TYPE_AUDIO:
|
case CODEC_TYPE_AUDIO:
|
||||||
|
@ -647,11 +657,17 @@ gst_ffmpegdec_negotiate (GstFFMpegDec * ffmpegdec)
|
||||||
caps = gst_ffmpeg_codectype_to_caps (oclass->in_plugin->type,
|
caps = gst_ffmpeg_codectype_to_caps (oclass->in_plugin->type,
|
||||||
ffmpegdec->context);
|
ffmpegdec->context);
|
||||||
|
|
||||||
/* add in pixel-aspect-ratio if we have it,
|
if (caps) {
|
||||||
* prefer ffmpeg par over sink par (since it's provided
|
/* If a demuxer provided a framerate then use it (#313970) */
|
||||||
|
if (ffmpegdec->format.video.fps != -1.0) {
|
||||||
|
gst_structure_set (gst_caps_get_structure (caps, 0), "framerate",
|
||||||
|
G_TYPE_DOUBLE, ffmpegdec->format.video.fps, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add pixel-aspect-ratio if we have it. Prefer
|
||||||
|
* ffmpeg PAR over sink PAR (since it's provided
|
||||||
* by the codec, which is more often correct).
|
* by the codec, which is more often correct).
|
||||||
*/
|
*/
|
||||||
if (caps) {
|
|
||||||
if (ffmpegdec->context->sample_aspect_ratio.num &&
|
if (ffmpegdec->context->sample_aspect_ratio.num &&
|
||||||
ffmpegdec->context->sample_aspect_ratio.den) {
|
ffmpegdec->context->sample_aspect_ratio.den) {
|
||||||
GST_DEBUG ("setting ffmpeg provided pixel-aspect-ratio");
|
GST_DEBUG ("setting ffmpeg provided pixel-aspect-ratio");
|
||||||
|
@ -690,7 +706,7 @@ gst_ffmpegdec_negotiate (GstFFMpegDec * ffmpegdec)
|
||||||
static gint
|
static gint
|
||||||
gst_ffmpegdec_frame (GstFFMpegDec * ffmpegdec,
|
gst_ffmpegdec_frame (GstFFMpegDec * ffmpegdec,
|
||||||
guint8 * data, guint size, gint * got_data, guint64 * in_ts,
|
guint8 * data, guint size, gint * got_data, guint64 * in_ts,
|
||||||
GstFlowReturn * ret)
|
GstBuffer * inbuf, GstFlowReturn * ret)
|
||||||
{
|
{
|
||||||
GstFFMpegDecClass *oclass =
|
GstFFMpegDecClass *oclass =
|
||||||
(GstFFMpegDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec));
|
(GstFFMpegDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec));
|
||||||
|
@ -756,7 +772,7 @@ gst_ffmpegdec_frame (GstFFMpegDec * ffmpegdec,
|
||||||
} else if (len >= 0 && have_data > 0) {
|
} else if (len >= 0 && have_data > 0) {
|
||||||
/* libavcodec constantly crashes on stupid buffer allocation
|
/* libavcodec constantly crashes on stupid buffer allocation
|
||||||
* errors inside. This drives me crazy, so we let it allocate
|
* errors inside. This drives me crazy, so we let it allocate
|
||||||
* it's own buffers and copy to our own buffer afterwards... */
|
* its own buffers and copy to our own buffer afterwards... */
|
||||||
|
|
||||||
if (ffmpegdec->picture->opaque != NULL) {
|
if (ffmpegdec->picture->opaque != NULL) {
|
||||||
outbuf = (GstBuffer *) ffmpegdec->picture->opaque;
|
outbuf = (GstBuffer *) ffmpegdec->picture->opaque;
|
||||||
|
@ -794,21 +810,27 @@ gst_ffmpegdec_frame (GstFFMpegDec * ffmpegdec,
|
||||||
if (!ffmpegdec->picture->key_frame) {
|
if (!ffmpegdec->picture->key_frame) {
|
||||||
GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
|
GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_BUFFER_TIMESTAMP (outbuf) = ffmpegdec->next_ts;
|
|
||||||
if (ffmpegdec->context->time_base.num != 0 &&
|
|
||||||
ffmpegdec->context->time_base.den != 0) {
|
|
||||||
GST_BUFFER_DURATION (outbuf) = GST_SECOND *
|
|
||||||
ffmpegdec->context->time_base.num /
|
|
||||||
ffmpegdec->context->time_base.den;
|
|
||||||
|
|
||||||
/* Take repeat_pict into account */
|
/* If we have used the framerate from the demuxer then
|
||||||
GST_BUFFER_DURATION (outbuf) += GST_BUFFER_DURATION (outbuf)
|
* also use the demuxer's timestamp information (#317596) */
|
||||||
* ffmpegdec->picture->repeat_pict / 2;
|
if (ffmpegdec->format.video.fps != -1.0 && inbuf != NULL) {
|
||||||
|
gst_buffer_stamp (outbuf, inbuf);
|
||||||
ffmpegdec->next_ts += GST_BUFFER_DURATION (outbuf);
|
|
||||||
} else {
|
} else {
|
||||||
ffmpegdec->next_ts = GST_CLOCK_TIME_NONE;
|
GST_BUFFER_TIMESTAMP (outbuf) = ffmpegdec->next_ts;
|
||||||
|
if (ffmpegdec->context->time_base.num != 0 &&
|
||||||
|
ffmpegdec->context->time_base.den != 0) {
|
||||||
|
GST_BUFFER_DURATION (outbuf) = GST_SECOND *
|
||||||
|
ffmpegdec->context->time_base.num /
|
||||||
|
ffmpegdec->context->time_base.den;
|
||||||
|
|
||||||
|
/* Take repeat_pict into account */
|
||||||
|
GST_BUFFER_DURATION (outbuf) += GST_BUFFER_DURATION (outbuf)
|
||||||
|
* ffmpegdec->picture->repeat_pict / 2;
|
||||||
|
|
||||||
|
ffmpegdec->next_ts += GST_BUFFER_DURATION (outbuf);
|
||||||
|
} else {
|
||||||
|
ffmpegdec->next_ts = GST_CLOCK_TIME_NONE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} 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) {
|
||||||
|
@ -919,7 +941,7 @@ gst_ffmpegdec_sink_event (GstPad * pad, GstEvent * event)
|
||||||
do {
|
do {
|
||||||
GstFlowReturn ret;
|
GstFlowReturn ret;
|
||||||
len = gst_ffmpegdec_frame (ffmpegdec, NULL, 0, &have_data,
|
len = gst_ffmpegdec_frame (ffmpegdec, NULL, 0, &have_data,
|
||||||
&ffmpegdec->next_ts, &ret);
|
&ffmpegdec->next_ts, NULL, &ret);
|
||||||
if (len < 0 || have_data == 0)
|
if (len < 0 || have_data == 0)
|
||||||
break;
|
break;
|
||||||
} while (try++ < 10);
|
} while (try++ < 10);
|
||||||
|
@ -1047,7 +1069,7 @@ gst_ffmpegdec_chain (GstPad * pad, GstBuffer * inbuf)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((len = gst_ffmpegdec_frame (ffmpegdec, data, size,
|
if ((len = gst_ffmpegdec_frame (ffmpegdec, data, size,
|
||||||
&have_data, &in_ts, &ret)) < 0 || ret != GST_FLOW_OK)
|
&have_data, &in_ts, inbuf, &ret)) < 0 || ret != GST_FLOW_OK)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (!ffmpegdec->pctx) {
|
if (!ffmpegdec->pctx) {
|
||||||
|
|
Loading…
Reference in a new issue