From b9d0c7110f5a47a206db45fd8ce4657a47d9ccb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= <sebastian.droege@collabora.co.uk> Date: Tue, 11 Dec 2012 16:54:09 +0000 Subject: [PATCH] avcodecmap: Take generic samplerate limitations into account --- ext/libav/gstavcodecmap.c | 176 +++++++++++++++++++++++++------------- 1 file changed, 116 insertions(+), 60 deletions(-) diff --git a/ext/libav/gstavcodecmap.c b/ext/libav/gstavcodecmap.c index 87d484a948..cb1d3d141a 100644 --- a/ext/libav/gstavcodecmap.c +++ b/ext/libav/gstavcodecmap.c @@ -282,8 +282,9 @@ gst_ff_vid_caps_new (AVCodecContext * context, enum CodecID codec_id, /* same for audio - now with channels/sample rate */ static GstCaps * -gst_ff_aud_caps_new (AVCodecContext * context, enum CodecID codec_id, - gboolean encode, const char *mimetype, const char *fieldname, ...) +gst_ff_aud_caps_new (AVCodecContext * context, AVCodec * codec, + enum CodecID codec_id, gboolean encode, const char *mimetype, + const char *fieldname, ...) { GstCaps *caps = NULL; GstStructure *structure = NULL; @@ -424,8 +425,32 @@ gst_ff_aud_caps_new (AVCodecContext * context, enum CodecID codec_id, structure = gst_caps_get_structure (caps, 0); gst_structure_set_value (structure, "rate", &list); g_value_unset (&list); - } else + } else if (codec && codec->supported_samplerates + && codec->supported_samplerates[0]) { + GValue va = { 0, }; + GValue v = { 0, }; + + if (!codec->supported_samplerates[1]) { + gst_caps_set_simple (caps, "rate", G_TYPE_INT, + codec->supported_samplerates[0], NULL); + } else { + const int *rates = codec->supported_samplerates; + + g_value_init (&va, GST_TYPE_LIST); + g_value_init (&v, G_TYPE_INT); + + while (*rates) { + g_value_set_int (&v, *rates); + gst_value_list_append_value (&va, &v); + rates++; + } + gst_caps_set_value (caps, "rate", &va); + g_value_unset (&va); + g_value_unset (&v); + } + } else { gst_caps_set_simple (caps, "rate", GST_TYPE_INT_RANGE, 4000, 96000, NULL); + } } else { caps = gst_caps_new_empty_simple (mimetype); } @@ -573,20 +598,21 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, case CODEC_ID_MP1: /* FIXME: bitrate */ - caps = gst_ff_aud_caps_new (context, codec_id, encode, "audio/mpeg", + caps = gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/mpeg", "mpegversion", G_TYPE_INT, 1, "layer", G_TYPE_INT, 1, NULL); break; case CODEC_ID_MP2: /* FIXME: bitrate */ - caps = gst_ff_aud_caps_new (context, codec_id, encode, "audio/mpeg", + caps = gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/mpeg", "mpegversion", G_TYPE_INT, 1, "layer", G_TYPE_INT, 2, NULL); break; case CODEC_ID_MP3: if (encode) { /* FIXME: bitrate */ - caps = gst_ff_aud_caps_new (context, codec_id, encode, "audio/mpeg", + caps = + gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/mpeg", "mpegversion", G_TYPE_INT, 1, "layer", G_TYPE_INT, 3, NULL); } else { /* Decodes MPEG-1 layer 1/2/3. Samplerate, channels et al are @@ -599,14 +625,14 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, case CODEC_ID_MUSEPACK7: caps = - gst_ff_aud_caps_new (context, codec_id, encode, + gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-ffmpeg-parsed-musepack", "streamversion", G_TYPE_INT, 7, NULL); break; case CODEC_ID_MUSEPACK8: caps = - gst_ff_aud_caps_new (context, codec_id, encode, + gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-ffmpeg-parsed-musepack", "streamversion", G_TYPE_INT, 8, NULL); break; @@ -614,41 +640,44 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, case CODEC_ID_AC3: /* FIXME: bitrate */ caps = - gst_ff_aud_caps_new (context, codec_id, encode, "audio/x-ac3", NULL); + gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-ac3", + NULL); break; case CODEC_ID_EAC3: /* FIXME: bitrate */ caps = - gst_ff_aud_caps_new (context, codec_id, encode, "audio/x-eac3", NULL); + gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-eac3", + NULL); break; case CODEC_ID_TRUEHD: caps = - gst_ff_aud_caps_new (context, codec_id, encode, "audio/x-true-hd", - NULL); + gst_ff_aud_caps_new (context, NULL, codec_id, encode, + "audio/x-true-hd", NULL); break; case CODEC_ID_ATRAC1: caps = - gst_ff_aud_caps_new (context, codec_id, encode, + gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-vnd.sony.atrac1", NULL); break; case CODEC_ID_ATRAC3: caps = - gst_ff_aud_caps_new (context, codec_id, encode, + gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-vnd.sony.atrac3", NULL); break; case CODEC_ID_DTS: caps = - gst_ff_aud_caps_new (context, codec_id, encode, "audio/x-dts", NULL); + gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-dts", + NULL); break; case CODEC_ID_APE: caps = - gst_ff_aud_caps_new (context, codec_id, encode, + gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-ffmpeg-parsed-ape", NULL); if (context) { gst_caps_set_simple (caps, @@ -658,12 +687,14 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, case CODEC_ID_MLP: caps = - gst_ff_aud_caps_new (context, codec_id, encode, "audio/x-mlp", NULL); + gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-mlp", + NULL); break; case CODEC_ID_IMC: caps = - gst_ff_aud_caps_new (context, codec_id, encode, "audio/x-imc", NULL); + gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-imc", + NULL); break; /* MJPEG is normal JPEG, Motion-JPEG and Quicktime MJPEG-A. MJPEGB @@ -776,7 +807,8 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, case CODEC_ID_DVAUDIO: caps = - gst_ff_aud_caps_new (context, codec_id, encode, "audio/x-dv", NULL); + gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-dv", + NULL); break; case CODEC_ID_DVVIDEO: @@ -826,21 +858,24 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, gint version = (codec_id == CODEC_ID_WMAV1) ? 1 : 2; if (context) { - caps = gst_ff_aud_caps_new (context, codec_id, encode, "audio/x-wma", - "wmaversion", G_TYPE_INT, version, - "block_align", G_TYPE_INT, context->block_align, - "bitrate", G_TYPE_INT, context->bit_rate, NULL); + caps = + gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-wma", + "wmaversion", G_TYPE_INT, version, "block_align", G_TYPE_INT, + context->block_align, "bitrate", G_TYPE_INT, context->bit_rate, + NULL); } else { - caps = gst_ff_aud_caps_new (context, codec_id, encode, "audio/x-wma", - "wmaversion", G_TYPE_INT, version, - "block_align", GST_TYPE_INT_RANGE, 0, G_MAXINT, - "bitrate", GST_TYPE_INT_RANGE, 0, G_MAXINT, NULL); + caps = + gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-wma", + "wmaversion", G_TYPE_INT, version, "block_align", + GST_TYPE_INT_RANGE, 0, G_MAXINT, "bitrate", GST_TYPE_INT_RANGE, 0, + G_MAXINT, NULL); } } break; case CODEC_ID_WMAPRO: { - caps = gst_ff_aud_caps_new (context, codec_id, encode, "audio/x-wma", + caps = + gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-wma", "wmaversion", G_TYPE_INT, 3, NULL); break; } @@ -848,7 +883,8 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, case CODEC_ID_WMAVOICE: { caps = - gst_ff_aud_caps_new (context, codec_id, encode, "audio/x-wms", NULL); + gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-wms", + NULL); break; } @@ -857,7 +893,8 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, { gint version = (codec_id == CODEC_ID_MACE3) ? 3 : 6; - caps = gst_ff_aud_caps_new (context, codec_id, encode, "audio/x-mace", + caps = + gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-mace", "maceversion", G_TYPE_INT, version, NULL); } break; @@ -951,7 +988,8 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, case CODEC_ID_AAC: { caps = - gst_ff_aud_caps_new (context, codec_id, encode, "audio/mpeg", NULL); + gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/mpeg", + NULL); if (!encode) { GValue arr = { 0, }; @@ -993,7 +1031,7 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, break; } case CODEC_ID_AAC_LATM: /* LATM/LOAS AAC syntax */ - caps = gst_ff_aud_caps_new (context, codec_id, encode, "audio/mpeg", + caps = gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/mpeg", "mpegversion", G_TYPE_INT, 4, "stream-format", G_TYPE_STRING, "loas", NULL); break; @@ -1098,7 +1136,8 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, break; case CODEC_ID_QDM2: caps = - gst_ff_aud_caps_new (context, codec_id, encode, "audio/x-qdm2", NULL); + gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-qdm2", + NULL); break; case CODEC_ID_MSZH: @@ -1239,13 +1278,14 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, case CODEC_ID_TRUESPEECH: caps = - gst_ff_aud_caps_new (context, codec_id, encode, "audio/x-truespeech", - NULL); + gst_ff_aud_caps_new (context, NULL, codec_id, encode, + "audio/x-truespeech", NULL); break; case CODEC_ID_QCELP: caps = - gst_ff_aud_caps_new (context, codec_id, encode, "audio/qcelp", NULL); + gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/qcelp", + NULL); break; case CODEC_ID_AMV: @@ -1341,7 +1381,8 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, break; } - caps = gst_ff_aud_caps_new (context, codec_id, encode, "audio/x-raw", + caps = + gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-raw", "format", G_TYPE_STRING, gst_audio_format_to_string (format), "layout", G_TYPE_STRING, "interleaved", NULL); } @@ -1349,18 +1390,20 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, case CODEC_ID_PCM_MULAW: caps = - gst_ff_aud_caps_new (context, codec_id, encode, "audio/x-mulaw", + gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-mulaw", NULL); break; case CODEC_ID_PCM_ALAW: caps = - gst_ff_aud_caps_new (context, codec_id, encode, "audio/x-alaw", NULL); + gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-alaw", + NULL); break; case CODEC_ID_ADPCM_G722: caps = - gst_ff_aud_caps_new (context, codec_id, encode, "audio/G722", NULL); + gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/G722", + NULL); if (context) gst_caps_set_simple (caps, "block_align", G_TYPE_INT, context->block_align, @@ -1370,7 +1413,8 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, case CODEC_ID_ADPCM_G726: { /* the G726 decoder can also handle G721 */ - caps = gst_ff_aud_caps_new (context, codec_id, encode, "audio/x-adpcm", + caps = + gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-adpcm", "layout", G_TYPE_STRING, "g726", NULL); if (context) gst_caps_set_simple (caps, @@ -1503,7 +1547,8 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, /* FIXME: someone please check whether we need additional properties * in this caps definition. */ - caps = gst_ff_aud_caps_new (context, codec_id, encode, "audio/x-adpcm", + caps = + gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-adpcm", "layout", G_TYPE_STRING, layout, NULL); if (context) gst_caps_set_simple (caps, @@ -1513,34 +1558,39 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, break; case CODEC_ID_AMR_NB: - caps = gst_ff_aud_caps_new (context, codec_id, encode, "audio/AMR", NULL); + caps = + gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/AMR", + NULL); break; case CODEC_ID_AMR_WB: caps = - gst_ff_aud_caps_new (context, codec_id, encode, "audio/AMR-WB", NULL); + gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/AMR-WB", + NULL); break; case CODEC_ID_GSM: caps = - gst_ff_aud_caps_new (context, codec_id, encode, "audio/x-gsm", NULL); + gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-gsm", + NULL); break; case CODEC_ID_GSM_MS: caps = - gst_ff_aud_caps_new (context, codec_id, encode, "audio/ms-gsm", NULL); + gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/ms-gsm", + NULL); break; case CODEC_ID_NELLYMOSER: caps = - gst_ff_aud_caps_new (context, codec_id, encode, "audio/x-nellymoser", - NULL); + gst_ff_aud_caps_new (context, NULL, codec_id, encode, + "audio/x-nellymoser", NULL); break; case CODEC_ID_SIPR: { caps = - gst_ff_aud_caps_new (context, codec_id, encode, "audio/x-sipro", + gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-sipro", NULL); if (context) { gst_caps_set_simple (caps, @@ -1572,7 +1622,7 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, /* FIXME: properties? */ caps = - gst_ff_aud_caps_new (context, codec_id, encode, + gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-pn-realaudio", "raversion", G_TYPE_INT, version, NULL); if (context) { gst_caps_set_simple (caps, @@ -1609,7 +1659,8 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, /* FIXME: someone please check whether we need additional properties * in this caps definition. */ - caps = gst_ff_aud_caps_new (context, codec_id, encode, "audio/x-dpcm", + caps = + gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-dpcm", "layout", G_TYPE_STRING, layout, NULL); if (context) gst_caps_set_simple (caps, @@ -1624,7 +1675,8 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, case CODEC_ID_ALAC: caps = - gst_ff_aud_caps_new (context, codec_id, encode, "audio/x-alac", NULL); + gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-alac", + NULL); if (context) { gst_caps_set_simple (caps, "samplesize", G_TYPE_INT, context->bits_per_coded_sample, NULL); @@ -1648,7 +1700,8 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, break; case CODEC_ID_TTA: caps = - gst_ff_aud_caps_new (context, codec_id, encode, "audio/x-tta", NULL); + gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-tta", + NULL); if (context) { gst_caps_set_simple (caps, "samplesize", G_TYPE_INT, context->bits_per_coded_sample, NULL); @@ -1656,8 +1709,8 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, break; case CODEC_ID_TWINVQ: caps = - gst_ff_aud_caps_new (context, codec_id, encode, "audio/x-twin-vq", - NULL); + gst_ff_aud_caps_new (context, NULL, codec_id, encode, + "audio/x-twin-vq", NULL); break; default: GST_DEBUG ("Unknown codec ID %d, please add mapping here", codec_id); @@ -1681,7 +1734,8 @@ gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, break; case AVMEDIA_TYPE_AUDIO: mime = g_strdup_printf ("audio/x-gst-av-%s", codec->name); - caps = gst_ff_aud_caps_new (context, codec_id, encode, mime, NULL); + caps = + gst_ff_aud_caps_new (context, NULL, codec_id, encode, mime, NULL); if (context) gst_caps_set_simple (caps, "block_align", G_TYPE_INT, context->block_align, @@ -1784,7 +1838,7 @@ gst_ffmpeg_smpfmt_to_audioformat (enum AVSampleFormat sample_fmt) static GstCaps * gst_ffmpeg_smpfmt_to_caps (enum AVSampleFormat sample_fmt, - AVCodecContext * context, enum CodecID codec_id) + AVCodecContext * context, AVCodec * codec, enum CodecID codec_id) { GstCaps *caps = NULL; GstAudioFormat format; @@ -1792,7 +1846,7 @@ gst_ffmpeg_smpfmt_to_caps (enum AVSampleFormat sample_fmt, format = gst_ffmpeg_smpfmt_to_audioformat (sample_fmt); if (format != GST_AUDIO_FORMAT_UNKNOWN) { - caps = gst_ff_aud_caps_new (context, codec_id, TRUE, "audio/x-raw", + caps = gst_ff_aud_caps_new (context, codec, codec_id, TRUE, "audio/x-raw", "format", G_TYPE_STRING, gst_audio_format_to_string (format), "layout", G_TYPE_STRING, "interleaved", NULL); GST_LOG ("caps for sample_fmt=%d: %" GST_PTR_FORMAT, sample_fmt, caps); @@ -1862,9 +1916,11 @@ gst_ffmpeg_codectype_to_audio_caps (AVCodecContext * context, if (context) { /* Specific codec context */ - caps = gst_ffmpeg_smpfmt_to_caps (context->sample_fmt, context, codec_id); + caps = + gst_ffmpeg_smpfmt_to_caps (context->sample_fmt, context, codec, + codec_id); } else { - caps = gst_ff_aud_caps_new (context, codec_id, TRUE, "audio/x-raw", + caps = gst_ff_aud_caps_new (context, codec, codec_id, TRUE, "audio/x-raw", "layout", G_TYPE_STRING, "interleaved", NULL); gst_ffmpeg_audio_set_sample_fmts (caps, codec ? codec->sample_fmts : NULL);