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.
This commit is contained in:
Mark Nauwelaerts 2008-10-08 14:20:37 +00:00
parent d0877c48e4
commit cc082f9b32
5 changed files with 160 additions and 40 deletions

View file

@ -1,3 +1,16 @@
2008-10-08 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
* 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 <mark.nauwelaerts@collabora.co.uk> 2008-10-08 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
* configure.ac: * configure.ac:

View file

@ -87,14 +87,28 @@ gst_ff_vid_caps_new (AVCodecContext * context, enum CodecID codec_id,
va_list var_args; va_list var_args;
gint i; gint i;
if (context != NULL) { /* fixed, non probing context */
if (context != NULL && context->width != -1) {
caps = gst_caps_new_simple (mimetype, caps = gst_caps_new_simple (mimetype,
"width", G_TYPE_INT, context->width, "width", G_TYPE_INT, context->width,
"height", G_TYPE_INT, context->height, "height", G_TYPE_INT, context->height,
"framerate", GST_TYPE_FRACTION, "framerate", GST_TYPE_FRACTION,
context->time_base.den, context->time_base.num, NULL); 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) { 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: case CODEC_ID_H263:
{ {
/* 128x96, 176x144, 352x288, 704x576, and 1408x1152. slightly reordered /* 128x96, 176x144, 352x288, 704x576, and 1408x1152. slightly reordered
@ -134,18 +148,34 @@ gst_ff_vid_caps_new (AVCodecContext * context, enum CodecID codec_id,
} }
break; break;
} }
default: case CODEC_ID_DNXHD:
{
caps = gst_caps_new_simple (mimetype, caps = gst_caps_new_simple (mimetype,
"width", GST_TYPE_INT_RANGE, 16, 4096, "width", G_TYPE_INT, 1920,
"height", GST_TYPE_INT_RANGE, 16, 4096, "height", G_TYPE_INT, 1080,
"framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL); "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; 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++) { for (i = 0; i < gst_caps_get_size (caps); i++) {
structure = gst_caps_get_structure (caps, i);
va_start (var_args, fieldname); va_start (var_args, fieldname);
structure = gst_caps_get_structure (caps, i);
gst_structure_set_valist (structure, fieldname, var_args); gst_structure_set_valist (structure, fieldname, var_args);
va_end (var_args); va_end (var_args);
} }
@ -162,36 +192,94 @@ gst_ff_aud_caps_new (AVCodecContext * context, enum CodecID codec_id,
{ {
GstCaps *caps = NULL; GstCaps *caps = NULL;
GstStructure *structure = NULL; GstStructure *structure = NULL;
gint i;
va_list var_args; va_list var_args;
if (context != NULL) { /* fixed, non-probing context */
if (context != NULL && context->channels != -1) {
caps = gst_caps_new_simple (mimetype, caps = gst_caps_new_simple (mimetype,
"rate", G_TYPE_INT, context->sample_rate, "rate", G_TYPE_INT, context->sample_rate,
"channels", G_TYPE_INT, context->channels, NULL); "channels", G_TYPE_INT, context->channels, NULL);
} else { } else {
gint maxchannels; gint maxchannels = 2;
/* Until decoders/encoders expose the maximum number of channels const gint *rates = NULL;
* they support, we whitelist them here. */ gint n_rates = 0;
if (context)
/* so we must be after restricted caps in this particular case */
switch (codec_id) { 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: 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_AAC:
case CODEC_ID_DTS: case CODEC_ID_DTS:
/* Until decoders/encoders expose the maximum number of channels
* they support, we whitelist them here. */
maxchannels = 6; maxchannels = 6;
break; break;
default: default:
maxchannels = 2; break;
} }
if (maxchannels == 1)
caps = gst_caps_new_simple (mimetype,
"channels", G_TYPE_INT, maxchannels, NULL);
else
caps = gst_caps_new_simple (mimetype, caps = gst_caps_new_simple (mimetype,
"rate", GST_TYPE_INT_RANGE, 8000, 96000,
"channels", GST_TYPE_INT_RANGE, 1, maxchannels, NULL); "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); for (i = 0; i < gst_caps_get_size (caps); i++) {
if (structure) {
va_start (var_args, fieldname); va_start (var_args, fieldname);
structure = gst_caps_get_structure (caps, i);
gst_structure_set_valist (structure, fieldname, var_args); gst_structure_set_valist (structure, fieldname, var_args);
va_end (var_args); va_end (var_args);
} }
@ -428,7 +516,8 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id,
break; break;
case CODEC_ID_RAWVIDEO: 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; break;
case CODEC_ID_MSMPEG4V1: case CODEC_ID_MSMPEG4V1:
@ -1366,7 +1455,7 @@ gst_ffmpeg_smpfmt_to_caps (enum SampleFormat sample_fmt,
GstCaps * GstCaps *
gst_ffmpeg_codectype_to_caps (enum CodecType codec_type, 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; GstCaps *caps;
@ -1374,14 +1463,17 @@ gst_ffmpeg_codectype_to_caps (enum CodecType codec_type,
case CODEC_TYPE_VIDEO: case CODEC_TYPE_VIDEO:
if (context) { if (context) {
caps = gst_ffmpeg_pixfmt_to_caps (context->pix_fmt, caps = gst_ffmpeg_pixfmt_to_caps (context->pix_fmt,
context->width == -1 ? NULL : context, codec_id); context, codec_id);
} else { } else {
GstCaps *temp; GstCaps *temp;
enum PixelFormat i; enum PixelFormat i;
AVCodecContext ctx = { 0, };
caps = gst_caps_new_empty (); caps = gst_caps_new_empty ();
for (i = 0; i < PIX_FMT_NB; i++) { 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) { if (temp != NULL) {
gst_caps_append (caps, temp); gst_caps_append (caps, temp);
} }
@ -1396,10 +1488,12 @@ gst_ffmpeg_codectype_to_caps (enum CodecType codec_type,
} else { } else {
GstCaps *temp; GstCaps *temp;
enum SampleFormat i; enum SampleFormat i;
AVCodecContext ctx = { 0, };
ctx.channels = -1;
caps = gst_caps_new_empty (); caps = gst_caps_new_empty ();
for (i = 0; i <= SAMPLE_FMT_S16; i++) { 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) { if (temp != NULL) {
gst_caps_append (caps, temp); gst_caps_append (caps, temp);
} }

View file

@ -45,7 +45,8 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id,
GstCaps * GstCaps *
gst_ffmpeg_codectype_to_caps (enum CodecType codec_type, gst_ffmpeg_codectype_to_caps (enum CodecType codec_type,
AVCodecContext *context, AVCodecContext *context,
enum CodecID codec_id); enum CodecID codec_id,
gboolean encode);
/* /*
* caps_to_codecid () transforms a GstCaps that belongs to * caps_to_codecid () transforms a GstCaps that belongs to

View file

@ -1046,7 +1046,7 @@ 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, oclass->in_plugin->id); ffmpegdec->context, oclass->in_plugin->id, FALSE);
if (caps == NULL) if (caps == NULL)
goto no_caps; goto no_caps;
@ -2497,8 +2497,8 @@ gst_ffmpegdec_register (GstPlugin * plugin)
if (in_plugin->type == CODEC_TYPE_VIDEO) { if (in_plugin->type == CODEC_TYPE_VIDEO) {
srccaps = gst_caps_from_string ("video/x-raw-rgb; video/x-raw-yuv"); srccaps = gst_caps_from_string ("video/x-raw-rgb; video/x-raw-yuv");
} else { } else {
srccaps = srccaps = gst_ffmpeg_codectype_to_caps (in_plugin->type, NULL,
gst_ffmpeg_codectype_to_caps (in_plugin->type, NULL, in_plugin->id); in_plugin->id, FALSE);
} }
if (!srccaps) { if (!srccaps) {
GST_WARNING ("Couldn't get source caps for decoder %s", GST_WARNING ("Couldn't get source caps for decoder %s",

View file

@ -286,6 +286,7 @@ gst_ffmpegenc_getcaps (GstPad * pad)
AVCodecContext *ctx = NULL; AVCodecContext *ctx = NULL;
enum PixelFormat pixfmt; enum PixelFormat pixfmt;
GstCaps *caps = NULL; GstCaps *caps = NULL;
gint i;
GST_DEBUG_OBJECT (ffmpegenc, "getting caps"); GST_DEBUG_OBJECT (ffmpegenc, "getting caps");
@ -317,9 +318,20 @@ gst_ffmpegenc_getcaps (GstPad * pad)
_shut_up_I_am_probing = TRUE; _shut_up_I_am_probing = TRUE;
#endif #endif
GST_DEBUG_OBJECT (ffmpegenc, "probing caps"); 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; 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 /* need to start with a fresh codec_context each time around, since
* codec_close may have released stuff causing the next pass to segfault */ * codec_close may have released stuff causing the next pass to segfault */
ctx = avcodec_alloc_context (); ctx = avcodec_alloc_context ();
@ -344,7 +356,7 @@ gst_ffmpegenc_getcaps (GstPad * pad)
if (!caps) if (!caps)
caps = gst_caps_new_empty (); caps = gst_caps_new_empty ();
tmpcaps = gst_ffmpeg_codectype_to_caps (oclass->in_plugin->type, ctx, tmpcaps = gst_ffmpeg_codectype_to_caps (oclass->in_plugin->type, ctx,
oclass->in_plugin->id); oclass->in_plugin->id, TRUE);
if (tmpcaps) if (tmpcaps)
gst_caps_append (caps, tmpcaps); gst_caps_append (caps, tmpcaps);
else else
@ -1018,8 +1030,8 @@ gst_ffmpegenc_register (GstPlugin * plugin)
sinkcaps = gst_caps_from_string sinkcaps = gst_caps_from_string
("video/x-raw-rgb; video/x-raw-yuv; video/x-raw-gray"); ("video/x-raw-rgb; video/x-raw-yuv; video/x-raw-gray");
} else { } else {
sinkcaps = sinkcaps = gst_ffmpeg_codectype_to_caps (in_plugin->type, NULL,
gst_ffmpeg_codectype_to_caps (in_plugin->type, NULL, in_plugin->id); in_plugin->id, TRUE);
} }
if (!sinkcaps) { if (!sinkcaps) {
GST_WARNING ("Couldn't get sink caps for encoder %s", GST_WARNING ("Couldn't get sink caps for encoder %s",