mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-18 07:47:17 +00:00
ffmpegdec: Correctly reorder audio channels to the GStreamer order if necessary
This commit is contained in:
parent
09efbe103f
commit
3d6c803917
3 changed files with 68 additions and 35 deletions
|
@ -102,46 +102,52 @@ static const struct
|
|||
CH_STEREO_RIGHT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT}
|
||||
};
|
||||
|
||||
static gboolean
|
||||
gst_ff_channel_layout_to_gst (guint64 channel_layout, guint channels,
|
||||
gboolean
|
||||
gst_ffmpeg_channel_layout_to_gst (AVCodecContext * context,
|
||||
GstAudioChannelPosition * pos)
|
||||
{
|
||||
guint nchannels = 0, i, j;
|
||||
guint nchannels = 0, channels = context->channels;
|
||||
guint64 channel_layout = context->channel_layout;
|
||||
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;
|
||||
}
|
||||
} else {
|
||||
guint i, j;
|
||||
|
||||
if (nchannels != channels) {
|
||||
GST_ERROR ("Number of channels is different (%u != %u)", channels,
|
||||
nchannels);
|
||||
return FALSE;
|
||||
}
|
||||
for (i = 0; i < 64; i++) {
|
||||
if ((channel_layout & (G_GUINT64_CONSTANT (1) << i)) != 0) {
|
||||
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 (nchannels != channels) {
|
||||
GST_ERROR ("Number of channels is different (%u != %u)", channels,
|
||||
nchannels);
|
||||
nchannels = channels;
|
||||
none_layout = TRUE;
|
||||
} else {
|
||||
|
||||
if (_ff_to_gst_layout[i].gst == GST_AUDIO_CHANNEL_POSITION_NONE)
|
||||
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 (j != nchannels) {
|
||||
GST_WARNING ("Unknown channels in channel layout - assuming NONE layout");
|
||||
none_layout = TRUE;
|
||||
}
|
||||
|
||||
if (!none_layout
|
||||
&& !gst_audio_check_valid_channel_positions (pos, nchannels, TRUE)) {
|
||||
&& !gst_audio_check_valid_channel_positions (pos, nchannels, FALSE)) {
|
||||
GST_ERROR ("Invalid channel layout %" G_GUINT64_FORMAT
|
||||
" - assuming NONE layout", channel_layout);
|
||||
none_layout = TRUE;
|
||||
|
@ -153,9 +159,9 @@ gst_ff_channel_layout_to_gst (guint64 channel_layout, guint channels,
|
|||
} else if (nchannels == 2) {
|
||||
pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
|
||||
pos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
|
||||
} else if (channel_layout == 0) {
|
||||
return FALSE;
|
||||
} else {
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < nchannels; i++)
|
||||
pos[i] = GST_AUDIO_CHANNEL_POSITION_NONE;
|
||||
}
|
||||
|
@ -322,17 +328,13 @@ gst_ff_aud_caps_new (AVCodecContext * context, enum CodecID codec_id,
|
|||
|
||||
/* fixed, non-probing context */
|
||||
if (context != NULL && context->channels != -1) {
|
||||
GstAudioInfo info;
|
||||
GstAudioChannelPosition pos[64];
|
||||
guint64 channel_layout = context->channel_layout;
|
||||
|
||||
gst_audio_info_init (&info);
|
||||
|
||||
caps = gst_caps_new_simple (mimetype,
|
||||
"rate", G_TYPE_INT, context->sample_rate,
|
||||
"channels", G_TYPE_INT, context->channels, NULL);
|
||||
|
||||
if (gst_ff_channel_layout_to_gst (channel_layout, context->channels, pos)) {
|
||||
if (gst_ffmpeg_channel_layout_to_gst (context, pos)) {
|
||||
guint64 mask;
|
||||
|
||||
if (gst_audio_channel_positions_to_mask (pos, context->channels, &mask)) {
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#include <libavcodec/avcodec.h>
|
||||
#endif
|
||||
#include <gst/gst.h>
|
||||
|
||||
#include <gst/audio/audio.h>
|
||||
#include <gst/video/video.h>
|
||||
|
||||
/*
|
||||
|
@ -127,5 +127,8 @@ gst_ffmpeg_formatid_get_codecids (const gchar *format_name,
|
|||
AVOutputFormat * plugin);
|
||||
|
||||
|
||||
gboolean
|
||||
gst_ffmpeg_channel_layout_to_gst (AVCodecContext * context,
|
||||
GstAudioChannelPosition * pos);
|
||||
|
||||
#endif /* __GST_FFMPEG_CODECMAP_H__ */
|
||||
|
|
|
@ -97,6 +97,8 @@ struct _GstFFMpegDec
|
|||
gint channels;
|
||||
gint samplerate;
|
||||
gint depth;
|
||||
|
||||
GstAudioChannelPosition ffmpeg_layout[64], gst_layout[64];
|
||||
} audio;
|
||||
} format;
|
||||
|
||||
|
@ -1350,13 +1352,18 @@ update_audio_context (GstFFMpegDec * ffmpegdec, gboolean force)
|
|||
{
|
||||
AVCodecContext *context = ffmpegdec->context;
|
||||
gint depth;
|
||||
GstAudioChannelPosition pos[64] = { 0, };
|
||||
|
||||
depth = av_smp_format_depth (context->sample_fmt);
|
||||
|
||||
gst_ffmpeg_channel_layout_to_gst (context, pos);
|
||||
|
||||
if (!force && ffmpegdec->format.audio.samplerate ==
|
||||
context->sample_rate &&
|
||||
ffmpegdec->format.audio.channels == context->channels &&
|
||||
ffmpegdec->format.audio.depth == depth)
|
||||
ffmpegdec->format.audio.depth == depth &&
|
||||
memcmp (ffmpegdec->format.audio.ffmpeg_layout, pos,
|
||||
sizeof (GstAudioChannelPosition) * context->channels) == 0)
|
||||
return FALSE;
|
||||
|
||||
GST_DEBUG_OBJECT (ffmpegdec,
|
||||
|
@ -1368,6 +1375,8 @@ update_audio_context (GstFFMpegDec * ffmpegdec, gboolean force)
|
|||
ffmpegdec->format.audio.samplerate = context->sample_rate;
|
||||
ffmpegdec->format.audio.channels = context->channels;
|
||||
ffmpegdec->format.audio.depth = depth;
|
||||
memcpy (ffmpegdec->format.audio.ffmpeg_layout, pos,
|
||||
sizeof (GstAudioChannelPosition) * context->channels);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -1389,6 +1398,13 @@ gst_ffmpegdec_audio_negotiate (GstFFMpegDec * ffmpegdec, gboolean force)
|
|||
if (caps == NULL)
|
||||
goto no_caps;
|
||||
|
||||
/* Get GStreamer channel layout */
|
||||
memcpy (ffmpegdec->format.audio.gst_layout,
|
||||
ffmpegdec->format.audio.ffmpeg_layout,
|
||||
sizeof (GstAudioChannelPosition) * ffmpegdec->format.audio.channels);
|
||||
gst_audio_channel_positions_to_valid_order (ffmpegdec->format.
|
||||
audio.gst_layout, ffmpegdec->format.audio.channels);
|
||||
|
||||
GST_LOG_OBJECT (ffmpegdec, "output caps %" GST_PTR_FORMAT, caps);
|
||||
|
||||
if (!gst_pad_set_caps (ffmpegdec->srcpad, caps))
|
||||
|
@ -2226,7 +2242,19 @@ gst_ffmpegdec_audio_frame (GstFFMpegDec * ffmpegdec,
|
|||
"Decode audio: len=%d, have_data=%d", len, have_data);
|
||||
|
||||
if (len >= 0 && have_data > 0) {
|
||||
/* FIXME: Reorder here */
|
||||
GstAudioFormat fmt;
|
||||
|
||||
/* Reorder channels to the GStreamer channel order */
|
||||
/* Only the width really matters here... and it's stored as depth */
|
||||
fmt =
|
||||
gst_audio_format_build_integer (TRUE, G_BYTE_ORDER,
|
||||
ffmpegdec->format.audio.depth, ffmpegdec->format.audio.depth);
|
||||
|
||||
gst_audio_reorder_channels (odata, have_data, fmt,
|
||||
ffmpegdec->format.audio.channels,
|
||||
ffmpegdec->format.audio.ffmpeg_layout,
|
||||
ffmpegdec->format.audio.gst_layout);
|
||||
|
||||
/* Buffer size */
|
||||
gst_buffer_unmap (*outbuf, odata, have_data);
|
||||
|
||||
|
|
Loading…
Reference in a new issue