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>
* configure.ac:

View file

@ -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;
}
case CODEC_ID_DNXHD:
{
caps = gst_caps_new_simple (mimetype,
"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:
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);
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);
}

View file

@ -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

View file

@ -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",

View file

@ -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",