mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-20 23:36:38 +00:00
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:
parent
d0877c48e4
commit
cc082f9b32
5 changed files with 160 additions and 40 deletions
13
ChangeLog
13
ChangeLog
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
|
@ -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);
|
"framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
|
||||||
|
|
||||||
gst_caps_append (caps, temp);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
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;
|
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;
|
||||||
switch (codec_id) {
|
|
||||||
case CODEC_ID_AC3:
|
|
||||||
case CODEC_ID_AAC:
|
|
||||||
case CODEC_ID_DTS:
|
|
||||||
maxchannels = 6;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
maxchannels = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
caps = gst_caps_new_simple (mimetype,
|
if (context)
|
||||||
"rate", GST_TYPE_INT_RANGE, 8000, 96000,
|
/* so we must be after restricted caps in this particular case */
|
||||||
"channels", GST_TYPE_INT_RANGE, 1, maxchannels, NULL);
|
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);
|
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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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",
|
||||||
|
|
Loading…
Reference in a new issue