From 67927465e64010ef8a835e47040794a4ea51067a Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Fri, 17 Dec 2004 11:32:45 +0000 Subject: [PATCH] ext/ffmpeg/gstffmpegenc.c: Move setup of sink caps (accepted formats) to a separate function rather than doing it on ... Original commit message from CVS: * ext/ffmpeg/gstffmpegenc.c: (gst_ffmpegenc_base_init), (gst_ffmpegenc_init), (gst_ffmpegenc_getcaps), (gst_ffmpegenc_link): Move setup of sink caps (accepted formats) to a separate function rather than doing it on initialization. --- ChangeLog | 8 ++++ ext/ffmpeg/gstffmpegenc.c | 95 +++++++++++++++++++++++++++++++++-------------- 2 files changed, 76 insertions(+), 27 deletions(-) diff --git a/ChangeLog b/ChangeLog index 799de07..0a9eb70 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2004-12-17 Ronald S. Bultje + + * ext/ffmpeg/gstffmpegenc.c: (gst_ffmpegenc_base_init), + (gst_ffmpegenc_init), (gst_ffmpegenc_getcaps), + (gst_ffmpegenc_link): + Move setup of sink caps (accepted formats) to a separate function + rather than doing it on initialization. + 2004-12-16 Ronald S. Bultje * ext/ffmpeg/gstffmpegcodecmap.c: (gst_ffmpeg_codecid_to_caps), diff --git a/ext/ffmpeg/gstffmpegenc.c b/ext/ffmpeg/gstffmpegenc.c index 543ef58..3d77415 100644 --- a/ext/ffmpeg/gstffmpegenc.c +++ b/ext/ffmpeg/gstffmpegenc.c @@ -64,6 +64,7 @@ struct _GstFFMpegEncClass AVCodec *in_plugin; GstPadTemplate *srctempl, *sinktempl; + GstCaps *sinkcaps; }; typedef struct @@ -130,8 +131,9 @@ static void gst_ffmpegenc_base_init (GstFFMpegEncClass * klass); static void gst_ffmpegenc_init (GstFFMpegEnc * ffmpegenc); static void gst_ffmpegenc_dispose (GObject * object); -static GstPadLinkReturn -gst_ffmpegenc_connect (GstPad * pad, const GstCaps * caps); +static GstPadLinkReturn gst_ffmpegenc_link (GstPad * pad, + const GstCaps * caps); +static GstCaps * gst_ffmpegenc_getcaps (GstPad * pad); static void gst_ffmpegenc_chain_video (GstPad * pad, GstData * _data); static void gst_ffmpegenc_chain_audio (GstPad * pad, GstData * _data); @@ -154,7 +156,6 @@ gst_ffmpegenc_base_init (GstFFMpegEncClass * klass) GstFFMpegEncClassParams *params; GstElementDetails details; GstPadTemplate *srctempl, *sinktempl; - AVCodecContext *ctx; params = g_hash_table_lookup (enc_global_plugins, GINT_TO_POINTER (G_OBJECT_CLASS_TYPE (gobject_class))); @@ -178,28 +179,6 @@ gst_ffmpegenc_base_init (GstFFMpegEncClass * klass) g_free (details.klass); g_free (details.description); - /* get pix_fmt for this encoder */ - if (params->in_plugin->type == CODEC_TYPE_VIDEO && - (ctx = avcodec_alloc_context ()) != NULL) { - ctx->width = 384; - ctx->height = 288; - ctx->frame_rate_base = DEFAULT_FRAME_RATE_BASE; - ctx->frame_rate = 25 * DEFAULT_FRAME_RATE_BASE; - ctx->bit_rate = 350 * 1000; - /* makes it silent */ - ctx->strict_std_compliance = -1; - - if (avcodec_open (ctx, params->in_plugin) >= 0) { - gst_caps_free (params->sinkcaps); - ctx->width = -1; - params->sinkcaps = - gst_ffmpeg_codectype_to_caps (params->in_plugin->type, ctx); - } - /* FIXME: ffmpeg likes to crash on this */ - //avcodec_close (ctx); - av_free (ctx); - } - /* pad templates */ sinktempl = gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, params->sinkcaps); @@ -212,6 +191,7 @@ gst_ffmpegenc_base_init (GstFFMpegEncClass * klass) klass->in_plugin = params->in_plugin; klass->srctempl = srctempl; klass->sinktempl = sinktempl; + klass->sinkcaps = NULL; } static void @@ -262,7 +242,8 @@ gst_ffmpegenc_init (GstFFMpegEnc * ffmpegenc) /* setup pads */ ffmpegenc->sinkpad = gst_pad_new_from_template (oclass->sinktempl, "sink"); - gst_pad_set_link_function (ffmpegenc->sinkpad, gst_ffmpegenc_connect); + gst_pad_set_link_function (ffmpegenc->sinkpad, gst_ffmpegenc_link); + gst_pad_set_getcaps_function (ffmpegenc->sinkpad, gst_ffmpegenc_getcaps); ffmpegenc->srcpad = gst_pad_new_from_template (oclass->srctempl, "src"); gst_pad_use_explicit_caps (ffmpegenc->srcpad); @@ -304,8 +285,68 @@ gst_ffmpegenc_dispose (GObject * object) av_free (ffmpegenc->picture); } +static GstCaps * +gst_ffmpegenc_getcaps (GstPad * pad) +{ + GstFFMpegEnc *ffmpegenc = (GstFFMpegEnc *) gst_pad_get_parent (pad); + GstFFMpegEncClass *oclass = + (GstFFMpegEncClass *) G_OBJECT_GET_CLASS (ffmpegenc); + AVCodecContext *ctx; + enum PixelFormat pixfmt; + GstCaps *caps = NULL; + + /* audio needs no special care */ + if (oclass->in_plugin->type == CODEC_TYPE_AUDIO) { + return gst_caps_copy (gst_pad_get_pad_template_caps (pad)); + } + + /* cached */ + if (oclass->sinkcaps) { + return gst_caps_copy (oclass->sinkcaps); + } + + /* create cache etc. */ + ctx = avcodec_alloc_context (); + if (!ctx) { + return gst_caps_copy (gst_pad_get_pad_template_caps (pad)); + } + + /* set some default properties */ + ctx->width = 384; + ctx->height = 288; + ctx->frame_rate_base = DEFAULT_FRAME_RATE_BASE; + ctx->frame_rate = 25 * DEFAULT_FRAME_RATE_BASE; + ctx->bit_rate = 350 * 1000; + /* makes it silent */ + ctx->strict_std_compliance = -1; + + for (pixfmt = 0; pixfmt < PIX_FMT_NB; pixfmt++) { + ctx->pix_fmt = pixfmt; + if (avcodec_open (ctx, oclass->in_plugin) >= 0 && + ctx->pix_fmt == pixfmt) { + ctx->width = -1; + if (!caps) + caps = gst_caps_new_empty (); + gst_caps_append (caps, + gst_ffmpeg_codectype_to_caps (oclass->in_plugin->type, ctx)); + } + /* FIXME: ffmpeg likes to crash on this */ + avcodec_close (ctx); + } + av_free (ctx); + + /* make sure we have something */ + if (!caps) { + return gst_caps_copy (gst_pad_get_pad_template_caps (pad)); + } + + oclass->sinkcaps = gst_caps_copy (caps); + + return caps; +} + static GstPadLinkReturn -gst_ffmpegenc_connect (GstPad * pad, const GstCaps * caps) +gst_ffmpegenc_link (GstPad * pad, const GstCaps * caps) { GstCaps *other_caps; GstCaps *allowed_caps; -- 2.7.4