diff options
author | Sebastian Dröge <slomo@circular-chaos.org> | 2008-12-13 07:55:40 +0000 |
---|---|---|
committer | Sebastian Dröge <slomo@circular-chaos.org> | 2008-12-13 07:55:40 +0000 |
commit | 616c0eb07fb215eb9a2e6b910bde0d0353235053 (patch) | |
tree | 7eb5cda0ddf08f79390b13b3fc2dd386aa371028 | |
parent | f1e4282538bceaab920818d54676cdf41ab0e165 (diff) | |
download | gst-libav-616c0eb07fb215eb9a2e6b910bde0d0353235053.tar.gz |
ext/ffmpeg/: Set the channel layout if it's exposed by the decoder.
Original commit message from CVS:
* ext/ffmpeg/Makefile.am:
* ext/ffmpeg/gstffmpegcodecmap.c: (gst_ff_channel_layout_to_gst),
(gst_ff_aud_caps_new):
* ext/ffmpeg/gstffmpegcodecmap.h:
Set the channel layout if it's exposed by the decoder.
Fixes bug #548002.
-rw-r--r-- | ChangeLog | 9 | ||||
-rw-r--r-- | ext/ffmpeg/Makefile.am | 2 | ||||
-rw-r--r-- | ext/ffmpeg/gstffmpegcodecmap.c | 115 | ||||
-rw-r--r-- | ext/ffmpeg/gstffmpegcodecmap.h | 2 |
4 files changed, 123 insertions, 5 deletions
@@ -1,5 +1,14 @@ 2008-12-13 Sebastian Dröge <sebastian.droege@collabora.co.uk> + * ext/ffmpeg/Makefile.am: + * ext/ffmpeg/gstffmpegcodecmap.c: (gst_ff_channel_layout_to_gst), + (gst_ff_aud_caps_new): + * ext/ffmpeg/gstffmpegcodecmap.h: + Set the channel layout if it's exposed by the decoder. + Fixes bug #548002. + +2008-12-13 Sebastian Dröge <sebastian.droege@collabora.co.uk> + * ffmpegrev: Update ffmpeg revision to 16086 and update to the corresponding swscale revision. diff --git a/ext/ffmpeg/Makefile.am b/ext/ffmpeg/Makefile.am index aa0fba7..736ebf7 100644 --- a/ext/ffmpeg/Makefile.am +++ b/ext/ffmpeg/Makefile.am @@ -15,7 +15,7 @@ libgstffmpeg_la_SOURCES = gstffmpeg.c \ libgstffmpeg_la_CFLAGS = $(GST_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) \ $(FFMPEG_CFLAGS) -libgstffmpeg_la_LIBADD = $(FFMPEG_LIBS) $(GST_BASE_LIBS) $(LIBM) $(WIN32_LIBS) -lz -lbz2 +libgstffmpeg_la_LIBADD = $(FFMPEG_LIBS) $(GST_BASE_LIBS) $(GST_PLUGINS_BASE_LIBS) -lgstaudio-$(GST_MAJORMINOR) $(LIBM) $(WIN32_LIBS) -lz -lbz2 libgstffmpeg_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) $(DARWIN_LDFLAGS) libgstffmpeg_la_LIBTOOLFLAGS = --tag=disable-static diff --git a/ext/ffmpeg/gstffmpegcodecmap.c b/ext/ffmpeg/gstffmpegcodecmap.c index 73a4a80..ed2e01f 100644 --- a/ext/ffmpeg/gstffmpegcodecmap.c +++ b/ext/ffmpeg/gstffmpegcodecmap.c @@ -70,6 +70,98 @@ gst_ffmpeg_set_palette (GstCaps * caps, AVCodecContext * context) } } +/* IMPORTANT: Keep this sorted by the ffmpeg channel masks */ +static const struct +{ + guint64 ff; + GstAudioChannelPosition gst; +} _ff_to_gst_layout[] = { + { + CH_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT}, { + CH_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT}, { + CH_FRONT_CENTER, GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER}, { + CH_LOW_FREQUENCY, GST_AUDIO_CHANNEL_POSITION_LFE}, { + CH_BACK_LEFT, GST_AUDIO_CHANNEL_POSITION_REAR_LEFT}, { + CH_BACK_RIGHT, GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT}, { + CH_FRONT_LEFT_OF_CENTER, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER}, { + CH_FRONT_RIGHT_OF_CENTER, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER}, { + CH_BACK_CENTER, GST_AUDIO_CHANNEL_POSITION_REAR_CENTER}, { + CH_SIDE_LEFT, GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT}, { + CH_SIDE_RIGHT, GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT}, { + CH_TOP_CENTER, GST_AUDIO_CHANNEL_POSITION_NONE}, { + CH_TOP_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_NONE}, { + CH_TOP_FRONT_CENTER, GST_AUDIO_CHANNEL_POSITION_NONE}, { + CH_TOP_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_NONE}, { + CH_TOP_BACK_LEFT, GST_AUDIO_CHANNEL_POSITION_NONE}, { + CH_TOP_BACK_CENTER, GST_AUDIO_CHANNEL_POSITION_NONE}, { + CH_TOP_BACK_RIGHT, GST_AUDIO_CHANNEL_POSITION_NONE}, { + CH_STEREO_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT}, { + CH_STEREO_RIGHT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT} +}; + +static GstAudioChannelPosition * +gst_ff_channel_layout_to_gst (guint64 channel_layout, guint channels) +{ + guint nchannels = 0, i, j; + GstAudioChannelPosition *pos = NULL; + gboolean none_layout = FALSE; + + for (i = 0; i < 64; i++) { + if ((channel_layout & (G_GUINT64_CONSTANT (1) << i)) != 0) { + nchannels++; + } + } + + if (channel_layout == 0) { + nchannels = channels; + none_layout = TRUE; + } + + if (nchannels != channels) { + GST_ERROR ("Number of channels is different (%u != %u)", channels, + nchannels); + return NULL; + } + + pos = g_new (GstAudioChannelPosition, nchannels); + + for (i = 0, j = 0; i < G_N_ELEMENTS (_ff_to_gst_layout); i++) { + if ((channel_layout & _ff_to_gst_layout[i].ff) != 0) { + pos[j++] = _ff_to_gst_layout[i].gst; + + if (_ff_to_gst_layout[i].gst == GST_AUDIO_CHANNEL_POSITION_NONE) + none_layout = TRUE; + } + } + + if (j != nchannels) { + GST_WARNING ("Unknown channels in channel layout - assuming NONE layout"); + none_layout = TRUE; + } + + if (!gst_audio_check_channel_positions (pos, nchannels)) { + GST_ERROR ("Invalid channel layout - assuming NONE layout"); + none_layout = TRUE; + } + + if (none_layout) { + if (nchannels == 1) { + pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_MONO; + } else if (nchannels == 2) { + pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT; + pos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT; + } else { + for (i = 0; i < nchannels; i++) + pos[i] = GST_AUDIO_CHANNEL_POSITION_NONE; + } + } + + if (nchannels == 1 && pos[0] == GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER) + pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_MONO; + + return pos; +} + /* this macro makes a caps width fixed or unfixed width/height * properties depending on whether we've got a context. * @@ -197,9 +289,19 @@ gst_ff_aud_caps_new (AVCodecContext * context, enum CodecID codec_id, /* fixed, non-probing context */ if (context != NULL && context->channels != -1) { + GstAudioChannelPosition *pos; + caps = gst_caps_new_simple (mimetype, "rate", G_TYPE_INT, context->sample_rate, "channels", G_TYPE_INT, context->channels, NULL); + + pos = + gst_ff_channel_layout_to_gst (context->channel_layout, + context->channels); + if (pos != NULL) { + gst_audio_set_channel_positions (gst_caps_get_structure (caps, 0), pos); + g_free (pos); + } } else { gint maxchannels = 2; const gint *rates = NULL; @@ -243,6 +345,11 @@ gst_ff_aud_caps_new (AVCodecContext * context, enum CodecID codec_id, default: 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 */ @@ -1396,7 +1503,7 @@ gst_ffmpeg_pixfmt_to_caps (enum PixelFormat pix_fmt, AVCodecContext * context, } if (caps != NULL) { - GST_DEBUG ("caps for pix_fmt=%d: %"GST_PTR_FORMAT, pix_fmt, caps); + GST_DEBUG ("caps for pix_fmt=%d: %" GST_PTR_FORMAT, pix_fmt, caps); } else { GST_LOG ("No caps found for pix_fmt=%d", pix_fmt); } @@ -1439,7 +1546,7 @@ gst_ffmpeg_smpfmt_to_caps (enum SampleFormat sample_fmt, } if (caps != NULL) { - GST_LOG ("caps for sample_fmt=%d: %"GST_PTR_FORMAT, sample_fmt, caps); + GST_LOG ("caps for sample_fmt=%d: %" GST_PTR_FORMAT, sample_fmt, caps); } else { GST_LOG ("No caps found for sample_fmt=%d", sample_fmt); } @@ -2769,9 +2876,9 @@ gst_ffmpeg_caps_to_codecid (const GstCaps * caps, AVCodecContext * context) } if (id != CODEC_ID_NONE) { - GST_DEBUG ("The id=%d belongs to the caps %"GST_PTR_FORMAT, id, caps); + GST_DEBUG ("The id=%d belongs to the caps %" GST_PTR_FORMAT, id, caps); } else { - GST_WARNING ("Couldn't figure out the id for caps %"GST_PTR_FORMAT, caps); + GST_WARNING ("Couldn't figure out the id for caps %" GST_PTR_FORMAT, caps); } return id; diff --git a/ext/ffmpeg/gstffmpegcodecmap.h b/ext/ffmpeg/gstffmpegcodecmap.h index 08b7ae5..cf98216 100644 --- a/ext/ffmpeg/gstffmpegcodecmap.h +++ b/ext/ffmpeg/gstffmpegcodecmap.h @@ -27,6 +27,8 @@ #endif #include <gst/gst.h> +#include <gst/audio/multichannel.h> + /* * _codecid_to_caps () gets the GstCaps that belongs to * a certain CodecID for a pad with compressed data. |