avcodecmap: Take channel layout constraints into account if possible

This commit is contained in:
Sebastian Dröge 2012-12-11 17:25:41 +00:00
parent b9d0c7110f
commit 64a2a8bdae
3 changed files with 57 additions and 27 deletions

View file

@ -360,7 +360,8 @@ gst_ffmpegauddec_negotiate (GstFFMpegAudDec * ffmpegdec, gboolean force)
ffmpegdec->info.finfo->depth, ffmpegdec->info.finfo->depth,
ffmpegdec->context->sample_rate, ffmpegdec->context->channels, 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, memcpy (ffmpegdec->ffmpeg_layout, pos,
sizeof (GstAudioChannelPosition) * ffmpegdec->context->channels); sizeof (GstAudioChannelPosition) * ffmpegdec->context->channels);

View file

@ -67,11 +67,10 @@ static const struct
}; };
gboolean gboolean
gst_ffmpeg_channel_layout_to_gst (AVCodecContext * context, gst_ffmpeg_channel_layout_to_gst (guint64 channel_layout, gint channels,
GstAudioChannelPosition * pos) GstAudioChannelPosition * pos)
{ {
guint nchannels = 0, channels = context->channels; guint nchannels = 0;
guint64 channel_layout = context->channel_layout;
gboolean none_layout = FALSE; gboolean none_layout = FALSE;
if (channel_layout == 0) { if (channel_layout == 0) {
@ -279,6 +278,20 @@ gst_ff_vid_caps_new (AVCodecContext * context, enum CodecID codec_id,
return caps; 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 /* same for audio - now with channels/sample rate
*/ */
static GstCaps * static GstCaps *
@ -287,7 +300,6 @@ gst_ff_aud_caps_new (AVCodecContext * context, AVCodec * codec,
const char *fieldname, ...) const char *fieldname, ...)
{ {
GstCaps *caps = NULL; GstCaps *caps = NULL;
GstStructure *structure = NULL;
gint i; gint i;
va_list var_args; va_list var_args;
@ -299,7 +311,8 @@ gst_ff_aud_caps_new (AVCodecContext * context, AVCodec * codec,
"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);
if (gst_ffmpeg_channel_layout_to_gst (context, pos)) { if (gst_ffmpeg_channel_layout_to_gst (context->channel_layout,
context->channels, pos)) {
guint64 mask; guint64 mask;
if (gst_audio_channel_positions_to_mask (pos, context->channels, FALSE, 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; 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 */ /* regardless of encode/decode, open up channels if applicable */
/* Until decoders/encoders expose the maximum number of channels /* Until decoders/encoders expose the maximum number of channels
* they support, we whitelist them here. */ * they support, we whitelist them here. */
@ -403,15 +412,40 @@ gst_ff_aud_caps_new (AVCodecContext * context, AVCodec * codec,
break; break;
} }
if (maxchannels == 1) if (codec && codec->channel_layouts) {
caps = gst_caps_new_simple (mimetype, const uint64_t *layouts = codec->channel_layouts;
"channels", G_TYPE_INT, maxchannels, NULL); GstAudioChannelPosition pos[64];
else
caps = gst_caps_new_simple (mimetype, caps = gst_caps_new_empty ();
"channels", GST_TYPE_INT_RANGE, 1, maxchannels, NULL); 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) { if (n_rates) {
GValue list = { 0, }; GValue list = { 0, };
GstStructure *structure;
g_value_init (&list, GST_TYPE_LIST); g_value_init (&list, GST_TYPE_LIST);
for (i = 0; i < n_rates; i++) { 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); gst_value_list_append_value (&list, &v);
g_value_unset (&v); g_value_unset (&v);
} }
structure = gst_caps_get_structure (caps, 0); gst_caps_set_value (caps, "rate", &list);
gst_structure_set_value (structure, "rate", &list);
g_value_unset (&list); g_value_unset (&list);
} else if (codec && codec->supported_samplerates } else if (codec && codec->supported_samplerates
&& codec->supported_samplerates[0]) { && codec->supported_samplerates[0]) {
@ -455,12 +488,9 @@ gst_ff_aud_caps_new (AVCodecContext * context, AVCodec * codec,
caps = gst_caps_new_empty_simple (mimetype); caps = gst_caps_new_empty_simple (mimetype);
} }
for (i = 0; i < gst_caps_get_size (caps); i++) { va_start (var_args, fieldname);
va_start (var_args, fieldname); gst_caps_set_simple_valist (caps, fieldname, var_args);
structure = gst_caps_get_structure (caps, i); va_end (var_args);
gst_structure_set_valist (structure, fieldname, var_args);
va_end (var_args);
}
return caps; return caps;
} }
@ -1922,7 +1952,6 @@ gst_ffmpeg_codectype_to_audio_caps (AVCodecContext * context,
} else { } else {
caps = gst_ff_aud_caps_new (context, codec, 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); "layout", G_TYPE_STRING, "interleaved", NULL);
gst_ffmpeg_audio_set_sample_fmts (caps, codec ? codec->sample_fmts : NULL); gst_ffmpeg_audio_set_sample_fmts (caps, codec ? codec->sample_fmts : NULL);
} }

View file

@ -137,7 +137,7 @@ gst_ffmpeg_formatid_get_codecids (const gchar *format_name,
gboolean gboolean
gst_ffmpeg_channel_layout_to_gst (AVCodecContext * context, gst_ffmpeg_channel_layout_to_gst (guint64 channel_layout, gint channels,
GstAudioChannelPosition * pos); GstAudioChannelPosition * pos);
#endif /* __GST_FFMPEG_CODECMAP_H__ */ #endif /* __GST_FFMPEG_CODECMAP_H__ */