diff options
author | Sebastian Dröge <sebastian.droege@collabora.co.uk> | 2012-12-11 17:25:41 +0000 |
---|---|---|
committer | Sebastian Dröge <sebastian.droege@collabora.co.uk> | 2012-12-11 17:25:41 +0000 |
commit | 64a2a8bdae4c06a0822a994438296b7295fa7da6 (patch) | |
tree | a19ce14ae83e2ca432244ccb26f4e1e9a0c95b83 /ext | |
parent | b9d0c7110f5a47a206db45fd8ce4657a47d9ccb4 (diff) | |
download | gstreamer-64a2a8bdae4c06a0822a994438296b7295fa7da6.tar.gz |
avcodecmap: Take channel layout constraints into account if possible
Diffstat (limited to 'ext')
-rw-r--r-- | ext/libav/gstavauddec.c | 3 | ||||
-rw-r--r-- | ext/libav/gstavcodecmap.c | 79 | ||||
-rw-r--r-- | ext/libav/gstavcodecmap.h | 2 |
3 files changed, 57 insertions, 27 deletions
diff --git a/ext/libav/gstavauddec.c b/ext/libav/gstavauddec.c index e795f117cb..5ed9eae167 100644 --- a/ext/libav/gstavauddec.c +++ b/ext/libav/gstavauddec.c @@ -360,7 +360,8 @@ gst_ffmpegauddec_negotiate (GstFFMpegAudDec * ffmpegdec, gboolean force) ffmpegdec->info.finfo->depth, ffmpegdec->context->sample_rate, ffmpegdec->context->channels, depth); - gst_ffmpeg_channel_layout_to_gst (ffmpegdec->context, pos); + gst_ffmpeg_channel_layout_to_gst (ffmpegdec->context->channel_layout, + ffmpegdec->context->channels, pos); memcpy (ffmpegdec->ffmpeg_layout, pos, sizeof (GstAudioChannelPosition) * ffmpegdec->context->channels); diff --git a/ext/libav/gstavcodecmap.c b/ext/libav/gstavcodecmap.c index cb1d3d141a..b9e6c67992 100644 --- a/ext/libav/gstavcodecmap.c +++ b/ext/libav/gstavcodecmap.c @@ -67,11 +67,10 @@ static const struct }; gboolean -gst_ffmpeg_channel_layout_to_gst (AVCodecContext * context, +gst_ffmpeg_channel_layout_to_gst (guint64 channel_layout, gint channels, GstAudioChannelPosition * pos) { - guint nchannels = 0, channels = context->channels; - guint64 channel_layout = context->channel_layout; + guint nchannels = 0; gboolean none_layout = FALSE; if (channel_layout == 0) { @@ -279,6 +278,20 @@ gst_ff_vid_caps_new (AVCodecContext * context, enum CodecID codec_id, return caps; } +static gint +get_nbits_set (guint64 n) +{ + gint i, x; + + x = 0; + for (i = 0; i < 64; i++) { + if ((n & (G_GUINT64_CONSTANT (1) << i))) + x++; + } + + return x; +} + /* same for audio - now with channels/sample rate */ static GstCaps * @@ -287,7 +300,6 @@ gst_ff_aud_caps_new (AVCodecContext * context, AVCodec * codec, const char *fieldname, ...) { GstCaps *caps = NULL; - GstStructure *structure = NULL; gint i; va_list var_args; @@ -299,7 +311,8 @@ gst_ff_aud_caps_new (AVCodecContext * context, AVCodec * codec, "rate", G_TYPE_INT, context->sample_rate, "channels", G_TYPE_INT, context->channels, NULL); - if (gst_ffmpeg_channel_layout_to_gst (context, pos)) { + if (gst_ffmpeg_channel_layout_to_gst (context->channel_layout, + context->channels, pos)) { guint64 mask; if (gst_audio_channel_positions_to_mask (pos, context->channels, FALSE, @@ -387,10 +400,6 @@ gst_ff_aud_caps_new (AVCodecContext * context, AVCodec * codec, break; } - /* TODO: handle context->channel_layouts here to set - * the list of channel layouts supported by the encoder. - * Unfortunately no encoder uses this yet.... - */ /* regardless of encode/decode, open up channels if applicable */ /* Until decoders/encoders expose the maximum number of channels * they support, we whitelist them here. */ @@ -403,15 +412,40 @@ gst_ff_aud_caps_new (AVCodecContext * context, AVCodec * codec, 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 (codec && codec->channel_layouts) { + const uint64_t *layouts = codec->channel_layouts; + GstAudioChannelPosition pos[64]; + + caps = gst_caps_new_empty (); + while (*layouts) { + gint nbits_set = get_nbits_set (*layouts); + + if (gst_ffmpeg_channel_layout_to_gst (*layouts, nbits_set, pos)) { + guint64 mask; + + if (gst_audio_channel_positions_to_mask (pos, nbits_set, FALSE, + &mask)) { + GstCaps *tmp = + gst_caps_new_simple (mimetype, "channel-mask", GST_TYPE_BITMASK, + mask, + "channels", G_TYPE_INT, nbits_set, NULL); + + gst_caps_append (caps, tmp); + } + } + layouts++; + } + } else { + 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++) { @@ -422,8 +456,7 @@ gst_ff_aud_caps_new (AVCodecContext * context, AVCodec * codec, 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); + gst_caps_set_value (caps, "rate", &list); g_value_unset (&list); } else if (codec && codec->supported_samplerates && codec->supported_samplerates[0]) { @@ -455,12 +488,9 @@ gst_ff_aud_caps_new (AVCodecContext * context, AVCodec * codec, caps = gst_caps_new_empty_simple (mimetype); } - 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); - } + va_start (var_args, fieldname); + gst_caps_set_simple_valist (caps, fieldname, var_args); + va_end (var_args); return caps; } @@ -1922,7 +1952,6 @@ gst_ffmpeg_codectype_to_audio_caps (AVCodecContext * context, } else { 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); } diff --git a/ext/libav/gstavcodecmap.h b/ext/libav/gstavcodecmap.h index 536bd1d379..fd2d43095f 100644 --- a/ext/libav/gstavcodecmap.h +++ b/ext/libav/gstavcodecmap.h @@ -137,7 +137,7 @@ gst_ffmpeg_formatid_get_codecids (const gchar *format_name, gboolean -gst_ffmpeg_channel_layout_to_gst (AVCodecContext * context, +gst_ffmpeg_channel_layout_to_gst (guint64 channel_layout, gint channels, GstAudioChannelPosition * pos); #endif /* __GST_FFMPEG_CODECMAP_H__ */ |