From: Mark Nauwelaerts Date: Wed, 8 Oct 2008 14:20:37 +0000 (+0000) Subject: ext/ffmpeg/: Add some more width/height/channels/rate limitations to caps to cater... X-Git-Tag: 1.19.3~499^2~1480 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=cc082f9b325ad499cf3bd19d8b04f56de588d4c4;p=platform%2Fupstream%2Fgstreamer.git ext/ffmpeg/: Add some more width/height/channels/rate limitations to caps to cater for more automagic negotiation. A... Original commit message from CVS: * ext/ffmpeg/gstffmpegcodecmap.c: (gst_ff_vid_caps_new), (gst_ff_aud_caps_new), (gst_ffmpeg_codecid_to_caps), (gst_ffmpeg_codectype_to_caps): * ext/ffmpeg/gstffmpegcodecmap.h: * ext/ffmpeg/gstffmpegdec.c: (gst_ffmpegdec_negotiate), (gst_ffmpegdec_register): * ext/ffmpeg/gstffmpegenc.c: (gst_ffmpegenc_getcaps), (gst_ffmpegenc_register): Add some more width/height/channels/rate limitations to caps to cater for more automagic negotiation. Addresses #532422. --- diff --git a/ChangeLog b/ChangeLog index 42a679e..21b30db 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,18 @@ 2008-10-08 Mark Nauwelaerts + * ext/ffmpeg/gstffmpegcodecmap.c: (gst_ff_vid_caps_new), + (gst_ff_aud_caps_new), (gst_ffmpeg_codecid_to_caps), + (gst_ffmpeg_codectype_to_caps): + * ext/ffmpeg/gstffmpegcodecmap.h: + * ext/ffmpeg/gstffmpegdec.c: (gst_ffmpegdec_negotiate), + (gst_ffmpegdec_register): + * ext/ffmpeg/gstffmpegenc.c: (gst_ffmpegenc_getcaps), + (gst_ffmpegenc_register): + Add some more width/height/channels/rate limitations to caps + to cater for more automagic negotiation. Addresses #532422. + +2008-10-08 Mark Nauwelaerts + * configure.ac: * ext/Makefile.am: * ext/libswscale/Makefile.am: diff --git a/ext/ffmpeg/gstffmpegcodecmap.c b/ext/ffmpeg/gstffmpegcodecmap.c index 02001e0..2b51f1a 100644 --- a/ext/ffmpeg/gstffmpegcodecmap.c +++ b/ext/ffmpeg/gstffmpegcodecmap.c @@ -87,14 +87,28 @@ gst_ff_vid_caps_new (AVCodecContext * context, enum CodecID codec_id, va_list var_args; gint i; - if (context != NULL) { + /* fixed, non probing context */ + if (context != NULL && context->width != -1) { caps = gst_caps_new_simple (mimetype, "width", G_TYPE_INT, context->width, "height", G_TYPE_INT, context->height, "framerate", GST_TYPE_FRACTION, context->time_base.den, context->time_base.num, NULL); - } else { + } else if (context) { + /* so we are after restricted caps in this case */ switch (codec_id) { + case CODEC_ID_H261: + { + caps = gst_caps_new_simple (mimetype, + "width", G_TYPE_INT, 352, + "height", G_TYPE_INT, 288, + "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL); + gst_caps_append (caps, gst_caps_new_simple (mimetype, + "width", G_TYPE_INT, 176, + "height", G_TYPE_INT, 144, + "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL)); + break; + } case CODEC_ID_H263: { /* 128x96, 176x144, 352x288, 704x576, and 1408x1152. slightly reordered @@ -131,21 +145,37 @@ gst_ff_vid_caps_new (AVCodecContext * context, enum CodecID codec_id, "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL); gst_caps_append (caps, temp); - } + } break; } - default: + case CODEC_ID_DNXHD: + { caps = gst_caps_new_simple (mimetype, - "width", GST_TYPE_INT_RANGE, 16, 4096, - "height", GST_TYPE_INT_RANGE, 16, 4096, + "width", G_TYPE_INT, 1920, + "height", G_TYPE_INT, 1080, "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL); + gst_caps_append (caps, gst_caps_new_simple (mimetype, + "width", G_TYPE_INT, 1280, + "height", G_TYPE_INT, 720, + "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL)); + break; + } + default: break; } } + /* no fixed caps or special restrictions applied; + * default unfixed setting */ + if (!caps) + caps = gst_caps_new_simple (mimetype, + "width", GST_TYPE_INT_RANGE, 16, 4096, + "height", GST_TYPE_INT_RANGE, 16, 4096, + "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL); + for (i = 0; i < gst_caps_get_size (caps); i++) { - structure = gst_caps_get_structure (caps, i); va_start (var_args, fieldname); + structure = gst_caps_get_structure (caps, i); gst_structure_set_valist (structure, fieldname, var_args); va_end (var_args); } @@ -162,36 +192,94 @@ gst_ff_aud_caps_new (AVCodecContext * context, enum CodecID codec_id, { GstCaps *caps = NULL; GstStructure *structure = NULL; + gint i; va_list var_args; - if (context != NULL) { + /* fixed, non-probing context */ + if (context != NULL && context->channels != -1) { caps = gst_caps_new_simple (mimetype, "rate", G_TYPE_INT, context->sample_rate, "channels", G_TYPE_INT, context->channels, NULL); } else { - gint maxchannels; - /* Until decoders/encoders expose the maximum number of channels - * they support, we whitelist them here. */ - switch (codec_id) { - case CODEC_ID_AC3: - case CODEC_ID_AAC: - case CODEC_ID_DTS: - maxchannels = 6; - break; - default: - maxchannels = 2; - } + gint maxchannels = 2; + const gint *rates = NULL; + gint n_rates = 0; - caps = gst_caps_new_simple (mimetype, - "rate", GST_TYPE_INT_RANGE, 8000, 96000, - "channels", GST_TYPE_INT_RANGE, 1, maxchannels, NULL); + if (context) + /* so we must be after restricted caps in this particular case */ + switch (codec_id) { + case CODEC_ID_MP2: + { + const static gint l_rates[] = + { 48000, 44100, 32000, 24000, 22050, 16000 }; + n_rates = G_N_ELEMENTS (l_rates); + rates = l_rates; + break; + } + case CODEC_ID_AC3: + { + const static gint l_rates[] = { 48000, 44100, 32000 }; + n_rates = G_N_ELEMENTS (l_rates); + rates = l_rates; + maxchannels = 6; + break; + } + case CODEC_ID_ADPCM_SWF: + { + const static gint l_rates[] = { 11025, 22050, 44100 }; + n_rates = G_N_ELEMENTS (l_rates); + rates = l_rates; + break; + } + case CODEC_ID_ROQ_DPCM: + { + const static gint l_rates[] = { 22050 }; + n_rates = G_N_ELEMENTS (l_rates); + rates = l_rates; + break; + } + case CODEC_ID_ADPCM_G726: + maxchannels = 1; + break; + case CODEC_ID_AAC: + case CODEC_ID_DTS: + /* Until decoders/encoders expose the maximum number of channels + * they support, we whitelist them here. */ + maxchannels = 6; + break; + default: + break; + } + if (maxchannels == 1) + caps = gst_caps_new_simple (mimetype, + "channels", G_TYPE_INT, maxchannels, NULL); + else + caps = gst_caps_new_simple (mimetype, + "channels", GST_TYPE_INT_RANGE, 1, maxchannels, NULL); + if (n_rates) { + GValue list = { 0, }; + GstStructure *structure; + + g_value_init (&list, GST_TYPE_LIST); + for (i = 0; i < n_rates; i++) { + GValue v = { 0, }; + + g_value_init (&v, G_TYPE_INT); + g_value_set_int (&v, rates[i]); + gst_value_list_append_value (&list, &v); + g_value_unset (&v); + } + structure = gst_caps_get_structure (caps, 0); + gst_structure_set_value (structure, "rate", &list); + g_value_unset (&list); + } else + gst_caps_set_simple (caps, "rate", GST_TYPE_INT_RANGE, 8000, 96000, NULL); } - structure = gst_caps_get_structure (caps, 0); - - if (structure) { + for (i = 0; i < gst_caps_get_size (caps); i++) { va_start (var_args, fieldname); + structure = gst_caps_get_structure (caps, i); gst_structure_set_valist (structure, fieldname, var_args); va_end (var_args); } @@ -428,7 +516,8 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, break; case CODEC_ID_RAWVIDEO: - caps = gst_ffmpeg_codectype_to_caps (CODEC_TYPE_VIDEO, context, codec_id); + caps = gst_ffmpeg_codectype_to_caps (CODEC_TYPE_VIDEO, context, codec_id, + encode); break; case CODEC_ID_MSMPEG4V1: @@ -1366,7 +1455,7 @@ gst_ffmpeg_smpfmt_to_caps (enum SampleFormat sample_fmt, GstCaps * gst_ffmpeg_codectype_to_caps (enum CodecType codec_type, - AVCodecContext * context, enum CodecID codec_id) + AVCodecContext * context, enum CodecID codec_id, gboolean encode) { GstCaps *caps; @@ -1374,14 +1463,17 @@ gst_ffmpeg_codectype_to_caps (enum CodecType codec_type, case CODEC_TYPE_VIDEO: if (context) { caps = gst_ffmpeg_pixfmt_to_caps (context->pix_fmt, - context->width == -1 ? NULL : context, codec_id); + 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++) { - temp = gst_ffmpeg_pixfmt_to_caps (i, NULL, codec_id); + 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); } @@ -1396,10 +1488,12 @@ gst_ffmpeg_codectype_to_caps (enum CodecType codec_type, } else { GstCaps *temp; enum SampleFormat i; + AVCodecContext ctx = { 0, }; + ctx.channels = -1; caps = gst_caps_new_empty (); for (i = 0; i <= SAMPLE_FMT_S16; i++) { - temp = gst_ffmpeg_smpfmt_to_caps (i, NULL, codec_id); + temp = gst_ffmpeg_smpfmt_to_caps (i, encode ? &ctx : NULL, codec_id); if (temp != NULL) { gst_caps_append (caps, temp); } diff --git a/ext/ffmpeg/gstffmpegcodecmap.h b/ext/ffmpeg/gstffmpegcodecmap.h index 252b5de..605b279 100644 --- a/ext/ffmpeg/gstffmpegcodecmap.h +++ b/ext/ffmpeg/gstffmpegcodecmap.h @@ -45,7 +45,8 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, GstCaps * gst_ffmpeg_codectype_to_caps (enum CodecType codec_type, AVCodecContext *context, - enum CodecID codec_id); + enum CodecID codec_id, + gboolean encode); /* * caps_to_codecid () transforms a GstCaps that belongs to diff --git a/ext/ffmpeg/gstffmpegdec.c b/ext/ffmpeg/gstffmpegdec.c index 8ef83da..bbb81a8 100644 --- a/ext/ffmpeg/gstffmpegdec.c +++ b/ext/ffmpeg/gstffmpegdec.c @@ -1046,7 +1046,7 @@ gst_ffmpegdec_negotiate (GstFFMpegDec * ffmpegdec) } caps = gst_ffmpeg_codectype_to_caps (oclass->in_plugin->type, - ffmpegdec->context, oclass->in_plugin->id); + ffmpegdec->context, oclass->in_plugin->id, FALSE); if (caps == NULL) goto no_caps; @@ -2497,8 +2497,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); + srccaps = gst_ffmpeg_codectype_to_caps (in_plugin->type, NULL, + in_plugin->id, FALSE); } if (!srccaps) { GST_WARNING ("Couldn't get source caps for decoder %s", diff --git a/ext/ffmpeg/gstffmpegenc.c b/ext/ffmpeg/gstffmpegenc.c index bc51699..087a68c 100644 --- a/ext/ffmpeg/gstffmpegenc.c +++ b/ext/ffmpeg/gstffmpegenc.c @@ -286,6 +286,7 @@ gst_ffmpegenc_getcaps (GstPad * pad) AVCodecContext *ctx = NULL; enum PixelFormat pixfmt; GstCaps *caps = NULL; + gint i; GST_DEBUG_OBJECT (ffmpegenc, "getting caps"); @@ -317,9 +318,20 @@ gst_ffmpegenc_getcaps (GstPad * pad) _shut_up_I_am_probing = TRUE; #endif GST_DEBUG_OBJECT (ffmpegenc, "probing caps"); - for (pixfmt = 0; pixfmt < PIX_FMT_NB; pixfmt++) { + i = pixfmt = 0; + /* check pixfmt until deemed finished */ + for (pixfmt = 0;; pixfmt++) { GstCaps *tmpcaps; + /* override looping all pixfmt if codec declares pixfmts; + * these may not properly check and report supported pixfmt during _init */ + if (oclass->in_plugin->pix_fmts) { + if ((pixfmt = oclass->in_plugin->pix_fmts[i++]) == PIX_FMT_NONE) + break; + } + if (pixfmt >= PIX_FMT_NB) + break; + /* need to start with a fresh codec_context each time around, since * codec_close may have released stuff causing the next pass to segfault */ ctx = avcodec_alloc_context (); @@ -344,7 +356,7 @@ gst_ffmpegenc_getcaps (GstPad * pad) if (!caps) caps = gst_caps_new_empty (); tmpcaps = gst_ffmpeg_codectype_to_caps (oclass->in_plugin->type, ctx, - oclass->in_plugin->id); + oclass->in_plugin->id, TRUE); if (tmpcaps) gst_caps_append (caps, tmpcaps); else @@ -1018,8 +1030,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); + sinkcaps = gst_ffmpeg_codectype_to_caps (in_plugin->type, NULL, + in_plugin->id, TRUE); } if (!sinkcaps) { GST_WARNING ("Couldn't get sink caps for encoder %s",