mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-25 11:11:08 +00:00
audiodecoder: copy rate and channels from input before fixating output caps
For default caps generation when handling gap events that are sent before any buffer, try to use caps that are closer to what upstream provided to avoid fixating rate or channels to 1 as default. So there are the steps: 1) Try to set rate, channels and channel-mask from upstream if provided 2) Fixate the rate and channels to the default rate and channels from audio lib 3) Fixate the caps just to be sure everything is fixed 4) If no channel-mask was provided and channels > 2, use a default channel-mask (taken from audioconvert code) https://bugzilla.gnome.org/show_bug.cgi?id=722144
This commit is contained in:
parent
ae4338bd35
commit
695ddbd56f
1 changed files with 124 additions and 0 deletions
|
@ -279,6 +279,69 @@ struct _GstAudioDecoderPrivate
|
|||
GList *pending_events;
|
||||
};
|
||||
|
||||
//* Default channel layouts taken from audioconvert */
|
||||
static const GstAudioChannelPosition default_positions[8][8] = {
|
||||
/* 1 channel */
|
||||
{
|
||||
GST_AUDIO_CHANNEL_POSITION_MONO,
|
||||
},
|
||||
/* 2 channels */
|
||||
{
|
||||
GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
|
||||
GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
|
||||
},
|
||||
/* 3 channels (2.1) */
|
||||
{
|
||||
GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
|
||||
GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
|
||||
GST_AUDIO_CHANNEL_POSITION_LFE1,
|
||||
},
|
||||
/* 4 channels (4.0) */
|
||||
{
|
||||
GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
|
||||
GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
|
||||
GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
|
||||
GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
|
||||
},
|
||||
/* 5 channels */
|
||||
{
|
||||
GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
|
||||
GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
|
||||
GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
|
||||
GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
|
||||
GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
|
||||
},
|
||||
/* 6 channels (5.1) */
|
||||
{
|
||||
GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
|
||||
GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
|
||||
GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
|
||||
GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
|
||||
GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
|
||||
GST_AUDIO_CHANNEL_POSITION_LFE1,
|
||||
},
|
||||
/* 7 channels (6.1) */
|
||||
{
|
||||
GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
|
||||
GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
|
||||
GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
|
||||
GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
|
||||
GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
|
||||
GST_AUDIO_CHANNEL_POSITION_LFE1,
|
||||
GST_AUDIO_CHANNEL_POSITION_REAR_CENTER,
|
||||
},
|
||||
/* 8 channels (7.1) */
|
||||
{
|
||||
GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
|
||||
GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
|
||||
GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
|
||||
GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
|
||||
GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
|
||||
GST_AUDIO_CHANNEL_POSITION_LFE1,
|
||||
GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT,
|
||||
GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT,
|
||||
}
|
||||
};
|
||||
|
||||
static void gst_audio_decoder_finalize (GObject * object);
|
||||
static void gst_audio_decoder_set_property (GObject * object,
|
||||
|
@ -1761,6 +1824,12 @@ static gboolean
|
|||
gst_audio_decoder_negotiate_default_caps (GstAudioDecoder * dec)
|
||||
{
|
||||
GstCaps *caps;
|
||||
gint i;
|
||||
gint channels = 0;
|
||||
gint rate;
|
||||
guint64 channel_mask = 0;
|
||||
gint caps_size;
|
||||
GstStructure *structure;
|
||||
|
||||
caps = gst_pad_get_current_caps (dec->srcpad);
|
||||
if (caps && !gst_audio_info_from_caps (&dec->priv->ctx.info, caps))
|
||||
|
@ -1770,7 +1839,62 @@ gst_audio_decoder_negotiate_default_caps (GstAudioDecoder * dec)
|
|||
if (!caps || gst_caps_is_empty (caps) || gst_caps_is_any (caps))
|
||||
return FALSE;
|
||||
|
||||
/* before fixating, try to use whatever upstream provided */
|
||||
caps_size = gst_caps_get_size (caps);
|
||||
if (dec->priv->ctx.input_caps) {
|
||||
GstCaps *sinkcaps = dec->priv->ctx.input_caps;
|
||||
GstStructure *structure = gst_caps_get_structure (sinkcaps, 0);
|
||||
|
||||
if (gst_structure_get_int (structure, "rate", &rate)) {
|
||||
for (i = 0; i < caps_size; i++) {
|
||||
gst_structure_set (gst_caps_get_structure (caps, i), "rate",
|
||||
G_TYPE_INT, rate, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (gst_structure_get_int (structure, "channels", &channels)) {
|
||||
for (i = 0; i < caps_size; i++) {
|
||||
gst_structure_set (gst_caps_get_structure (caps, i), "channels",
|
||||
G_TYPE_INT, channels, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (gst_structure_get (structure, "channel-mask", GST_TYPE_BITMASK,
|
||||
&channel_mask, NULL)) {
|
||||
for (i = 0; i < caps_size; i++) {
|
||||
gst_structure_set (gst_caps_get_structure (caps, i), "channel-mask",
|
||||
GST_TYPE_BITMASK, channel_mask, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < caps_size; i++) {
|
||||
structure = gst_caps_get_structure (caps, i);
|
||||
gst_structure_fixate_field_nearest_int (structure,
|
||||
"channels", GST_AUDIO_DEF_CHANNELS);
|
||||
gst_structure_fixate_field_nearest_int (structure,
|
||||
"rate", GST_AUDIO_DEF_RATE);
|
||||
}
|
||||
caps = gst_caps_fixate (caps);
|
||||
structure = gst_caps_get_structure (caps, 0);
|
||||
|
||||
/* Need to add a channel-mask if channels > 2 */
|
||||
gst_structure_get_int (structure, "channels", &channels);
|
||||
if (channels > 2 && !gst_structure_has_field (structure, "channel-mask")) {
|
||||
if (channels <= 8) {
|
||||
channel_mask = 0;
|
||||
for (i = 0; i < channels; i++)
|
||||
channel_mask |=
|
||||
G_GUINT64_CONSTANT (1) << default_positions[channels - 1][i];
|
||||
|
||||
gst_structure_set (structure, "channel-mask",
|
||||
GST_TYPE_BITMASK, channel_mask, NULL);
|
||||
} else {
|
||||
GST_WARNING_OBJECT (dec, "No default channel-mask for %d channels",
|
||||
channels);
|
||||
}
|
||||
}
|
||||
|
||||
if (!caps || !gst_audio_info_from_caps (&dec->priv->ctx.info, caps))
|
||||
return FALSE;
|
||||
|
||||
|
|
Loading…
Reference in a new issue