From 9fc91546ea91af0b6f14418b8ec26abf64b0cc72 Mon Sep 17 00:00:00 2001 From: Edward Hervey Date: Thu, 29 Jan 2009 07:48:19 +0100 Subject: [PATCH] Only use valid SampleFormat for audio encoders/decoders. For a given AVCodec, when the sample_fmts field is non-NULL, that means that that codec can only handle a specific set of SampleFormat. With this patch, we now look for its presence and create the proper pad template caps. Fixes #569441 --- ext/ffmpeg/gstffmpegcodecmap.c | 110 +++++++++++++++++++++++++++-------------- ext/ffmpeg/gstffmpegcodecmap.h | 10 ++++ ext/ffmpeg/gstffmpegdec.c | 4 +- ext/ffmpeg/gstffmpegenc.c | 4 +- 4 files changed, 87 insertions(+), 41 deletions(-) diff --git a/ext/ffmpeg/gstffmpegcodecmap.c b/ext/ffmpeg/gstffmpegcodecmap.c index d29ec1c..4b2c123 100644 --- a/ext/ffmpeg/gstffmpegcodecmap.c +++ b/ext/ffmpeg/gstffmpegcodecmap.c @@ -1624,6 +1624,75 @@ gst_ffmpeg_smpfmt_to_caps (enum SampleFormat sample_fmt, return caps; } +GstCaps * +gst_ffmpeg_codectype_to_audio_caps (AVCodecContext * context, + enum CodecID codec_id, gboolean encode, AVCodec * codec) +{ + GstCaps *caps = NULL; + + GST_DEBUG ("context:%p, codec_id:%d, encode:%d, codec:%p", + context, codec_id, encode, codec); + if (codec) + GST_DEBUG ("sample_fmts:%p, samplerates:%p", + codec->sample_fmts, codec->supported_samplerates); + + if (context) { + /* Specific codec context */ + caps = gst_ffmpeg_smpfmt_to_caps (context->sample_fmt, context, codec_id); + } else if (codec && codec->sample_fmts) { + GstCaps *temp; + int i; + + caps = gst_caps_new_empty (); + for (i = 0; codec->sample_fmts[i] != -1; i++) { + temp = + gst_ffmpeg_smpfmt_to_caps (codec->sample_fmts[0], context, codec_id); + if (temp != NULL) + gst_caps_append (caps, temp); + } + } else { + GstCaps *temp; + enum SampleFormat i; + AVCodecContext ctx = { 0, }; + + ctx.channels = -1; + caps = gst_caps_new_empty (); + for (i = 0; i <= SAMPLE_FMT_DBL; i++) { + temp = gst_ffmpeg_smpfmt_to_caps (i, encode ? &ctx : NULL, codec_id); + if (temp != NULL) { + gst_caps_append (caps, temp); + } + } + } + return caps; +} + +GstCaps * +gst_ffmpeg_codectype_to_video_caps (AVCodecContext * context, + enum CodecID codec_id, gboolean encode, AVCodec * codec) +{ + GstCaps *caps; + + if (context) { + caps = gst_ffmpeg_pixfmt_to_caps (context->pix_fmt, context, codec_id); + } else { + GstCaps *temp; + enum PixelFormat i; + AVCodecContext ctx = { 0, }; + + caps = gst_caps_new_empty (); + for (i = 0; i < PIX_FMT_NB; i++) { + ctx.width = -1; + ctx.pix_fmt = i; + temp = gst_ffmpeg_pixfmt_to_caps (i, encode ? &ctx : NULL, codec_id); + if (temp != NULL) { + gst_caps_append (caps, temp); + } + } + } + return caps; +} + /* Convert a FFMPEG codec Type and optional AVCodecContext * to a GstCaps. If the context is ommitted, no fixed values * for video/audio size will be included in the GstCaps @@ -1639,47 +1708,14 @@ gst_ffmpeg_codectype_to_caps (enum CodecType codec_type, switch (codec_type) { case CODEC_TYPE_VIDEO: - if (context) { - caps = gst_ffmpeg_pixfmt_to_caps (context->pix_fmt, context, codec_id); - } else { - GstCaps *temp; - enum PixelFormat i; - AVCodecContext ctx = { 0, }; - - caps = gst_caps_new_empty (); - for (i = 0; i < PIX_FMT_NB; i++) { - ctx.width = -1; - ctx.pix_fmt = i; - temp = gst_ffmpeg_pixfmt_to_caps (i, encode ? &ctx : NULL, codec_id); - if (temp != NULL) { - gst_caps_append (caps, temp); - } - } - } + caps = + gst_ffmpeg_codectype_to_video_caps (context, codec_id, encode, NULL); break; - case CODEC_TYPE_AUDIO: - if (context) { - caps = - gst_ffmpeg_smpfmt_to_caps (context->sample_fmt, context, codec_id); - } else { - GstCaps *temp; - enum SampleFormat i; - AVCodecContext ctx = { 0, }; - - ctx.channels = -1; - caps = gst_caps_new_empty (); - for (i = 0; i <= SAMPLE_FMT_DBL; i++) { - temp = gst_ffmpeg_smpfmt_to_caps (i, encode ? &ctx : NULL, codec_id); - if (temp != NULL) { - gst_caps_append (caps, temp); - } - } - } + caps = + gst_ffmpeg_codectype_to_audio_caps (context, codec_id, encode, NULL); break; - default: - /* .. */ caps = NULL; break; } diff --git a/ext/ffmpeg/gstffmpegcodecmap.h b/ext/ffmpeg/gstffmpegcodecmap.h index 46c5171..f72c6fa 100644 --- a/ext/ffmpeg/gstffmpegcodecmap.h +++ b/ext/ffmpeg/gstffmpegcodecmap.h @@ -49,6 +49,16 @@ gst_ffmpeg_codectype_to_caps (enum CodecType codec_type, AVCodecContext *context, enum CodecID codec_id, gboolean encode); +GstCaps * +gst_ffmpeg_codectype_to_audio_caps (AVCodecContext *context, + enum CodecID codec_id, + gboolean encode, + AVCodec *codec); +GstCaps * +gst_ffmpeg_codectype_to_video_caps (AVCodecContext *context, + enum CodecID codec_id, + gboolean encode, + AVCodec *codec); /* * caps_to_codecid () transforms a GstCaps that belongs to diff --git a/ext/ffmpeg/gstffmpegdec.c b/ext/ffmpeg/gstffmpegdec.c index dc80c3b..8b451a4 100644 --- a/ext/ffmpeg/gstffmpegdec.c +++ b/ext/ffmpeg/gstffmpegdec.c @@ -2563,8 +2563,8 @@ gst_ffmpegdec_register (GstPlugin * plugin) if (in_plugin->type == CODEC_TYPE_VIDEO) { srccaps = gst_caps_from_string ("video/x-raw-rgb; video/x-raw-yuv"); } else { - srccaps = gst_ffmpeg_codectype_to_caps (in_plugin->type, NULL, - in_plugin->id, FALSE); + srccaps = gst_ffmpeg_codectype_to_audio_caps (NULL, + in_plugin->id, FALSE, in_plugin); } if (!srccaps) { GST_WARNING ("Couldn't get source caps for decoder %s", in_plugin->name); diff --git a/ext/ffmpeg/gstffmpegenc.c b/ext/ffmpeg/gstffmpegenc.c index 446c7b0..2e3fb64 100644 --- a/ext/ffmpeg/gstffmpegenc.c +++ b/ext/ffmpeg/gstffmpegenc.c @@ -1029,8 +1029,8 @@ gst_ffmpegenc_register (GstPlugin * plugin) sinkcaps = gst_caps_from_string ("video/x-raw-rgb; video/x-raw-yuv; video/x-raw-gray"); } else { - sinkcaps = gst_ffmpeg_codectype_to_caps (in_plugin->type, NULL, - in_plugin->id, TRUE); + sinkcaps = gst_ffmpeg_codectype_to_audio_caps (NULL, + in_plugin->id, TRUE, in_plugin); } if (!sinkcaps) { GST_WARNING ("Couldn't get sink caps for encoder %s", in_plugin->name); -- 2.7.4