faad: Update for the new raw audio caps

This commit is contained in:
Sebastian Dröge 2012-01-05 10:23:07 +01:00
parent ad63a0c6e3
commit dd38a639df
2 changed files with 37 additions and 34 deletions

View file

@ -41,7 +41,6 @@
#include <string.h> #include <string.h>
#include <gst/audio/audio.h> #include <gst/audio/audio.h>
#include <gst/audio/multichannel.h>
/* These are the correct types for these functions, as defined in the source, /* These are the correct types for these functions, as defined in the source,
* with types changed to match glib types, since those are defined for us. * with types changed to match glib types, since those are defined for us.
@ -98,6 +97,7 @@ static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
#define STATIC_RAW_CAPS(format) \ #define STATIC_RAW_CAPS(format) \
"audio/x-raw, " \ "audio/x-raw, " \
"format = (string) "GST_AUDIO_NE(format)", " \ "format = (string) "GST_AUDIO_NE(format)", " \
"layout = (string) interleaved, " \
"rate = (int) [ 8000, 96000 ], " \ "rate = (int) [ 8000, 96000 ], " \
"channels = (int) [ 1, 8 ]" "channels = (int) [ 1, 8 ]"
@ -375,27 +375,26 @@ init_failed:
} }
} }
static GstAudioChannelPosition * static gboolean
gst_faad_chanpos_to_gst (GstFaad * faad, guchar * fpos, guint num, gst_faad_chanpos_to_gst (GstFaad * faad, guchar * fpos,
gboolean * channel_map_failed) GstAudioChannelPosition * pos, guint num)
{ {
GstAudioChannelPosition *pos;
guint n; guint n;
gboolean unknown_channel = FALSE; gboolean unknown_channel = FALSE;
*channel_map_failed = FALSE;
/* special handling for the common cases for mono and stereo */ /* special handling for the common cases for mono and stereo */
if (num == 1 && fpos[0] == FRONT_CHANNEL_CENTER) { if (num == 1 && fpos[0] == FRONT_CHANNEL_CENTER) {
GST_DEBUG_OBJECT (faad, "mono common case; won't set channel positions"); GST_DEBUG_OBJECT (faad, "mono common case; won't set channel positions");
return NULL; pos[0] = GST_AUDIO_CHANNEL_POSITION_MONO;
return TRUE;
} else if (num == 2 && fpos[0] == FRONT_CHANNEL_LEFT } else if (num == 2 && fpos[0] == FRONT_CHANNEL_LEFT
&& fpos[1] == FRONT_CHANNEL_RIGHT) { && fpos[1] == FRONT_CHANNEL_RIGHT) {
GST_DEBUG_OBJECT (faad, "stereo common case; won't set channel positions"); GST_DEBUG_OBJECT (faad, "stereo common case; won't set channel positions");
return NULL; pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
pos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
return TRUE;
} }
pos = g_new (GstAudioChannelPosition, num);
for (n = 0; n < num; n++) { for (n = 0; n < num; n++) {
GST_DEBUG_OBJECT (faad, "faad channel %d as %d", n, fpos[n]); GST_DEBUG_OBJECT (faad, "faad channel %d as %d", n, fpos[n]);
switch (fpos[n]) { switch (fpos[n]) {
@ -408,7 +407,7 @@ gst_faad_chanpos_to_gst (GstFaad * faad, guchar * fpos, guint num,
case FRONT_CHANNEL_CENTER: case FRONT_CHANNEL_CENTER:
/* argh, mono = center */ /* argh, mono = center */
if (num == 1) if (num == 1)
pos[n] = GST_AUDIO_CHANNEL_POSITION_FRONT_MONO; pos[n] = GST_AUDIO_CHANNEL_POSITION_MONO;
else else
pos[n] = GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER; pos[n] = GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER;
break; break;
@ -428,7 +427,7 @@ gst_faad_chanpos_to_gst (GstFaad * faad, guchar * fpos, guint num,
pos[n] = GST_AUDIO_CHANNEL_POSITION_REAR_CENTER; pos[n] = GST_AUDIO_CHANNEL_POSITION_REAR_CENTER;
break; break;
case LFE_CHANNEL: case LFE_CHANNEL:
pos[n] = GST_AUDIO_CHANNEL_POSITION_LFE; pos[n] = GST_AUDIO_CHANNEL_POSITION_LFE1;
break; break;
default: default:
GST_DEBUG_OBJECT (faad, "unknown channel %d at %d", fpos[n], n); GST_DEBUG_OBJECT (faad, "unknown channel %d at %d", fpos[n], n);
@ -437,39 +436,39 @@ gst_faad_chanpos_to_gst (GstFaad * faad, guchar * fpos, guint num,
} }
} }
if (unknown_channel) { if (unknown_channel) {
g_free (pos);
pos = NULL;
switch (num) { switch (num) {
case 1:{ case 1:{
GST_DEBUG_OBJECT (faad, GST_DEBUG_OBJECT (faad,
"FAAD reports unknown 1 channel mapping. Forcing to mono"); "FAAD reports unknown 1 channel mapping. Forcing to mono");
pos[0] = GST_AUDIO_CHANNEL_POSITION_MONO;
break; break;
} }
case 2:{ case 2:{
GST_DEBUG_OBJECT (faad, GST_DEBUG_OBJECT (faad,
"FAAD reports unknown 2 channel mapping. Forcing to stereo"); "FAAD reports unknown 2 channel mapping. Forcing to stereo");
pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
pos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
break; break;
} }
default:{ default:{
GST_WARNING_OBJECT (faad, GST_WARNING_OBJECT (faad,
"Unsupported FAAD channel position 0x%x encountered", fpos[n]); "Unsupported FAAD channel position 0x%x encountered", fpos[n]);
*channel_map_failed = TRUE; return FALSE;
break; break;
} }
} }
} }
return pos; return TRUE;
} }
static gboolean static gboolean
gst_faad_update_caps (GstFaad * faad, faacDecFrameInfo * info) gst_faad_update_caps (GstFaad * faad, faacDecFrameInfo * info)
{ {
GstAudioChannelPosition *pos;
gboolean ret; gboolean ret;
gboolean channel_map_failed;
GstCaps *caps; GstCaps *caps;
gboolean fmt_change = FALSE; gboolean fmt_change = FALSE;
GstAudioInfo ainfo;
/* see if we need to renegotiate */ /* see if we need to renegotiate */
if (info->samplerate != faad->samplerate || if (info->samplerate != faad->samplerate ||
@ -479,40 +478,41 @@ gst_faad_update_caps (GstFaad * faad, faacDecFrameInfo * info)
gint i; gint i;
for (i = 0; i < info->channels; i++) { for (i = 0; i < info->channels; i++) {
if (info->channel_position[i] != faad->channel_positions[i]) if (info->channel_position[i] != faad->channel_positions[i]) {
fmt_change = TRUE; fmt_change = TRUE;
break;
}
} }
} }
if (G_LIKELY (!fmt_change)) if (G_LIKELY (!fmt_change))
return TRUE; return TRUE;
/* store new negotiation information */ /* store new negotiation information */
faad->samplerate = info->samplerate; faad->samplerate = info->samplerate;
faad->channels = info->channels; faad->channels = info->channels;
g_free (faad->channel_positions); g_free (faad->channel_positions);
faad->channel_positions = g_memdup (info->channel_position, faad->channels); faad->channel_positions = g_memdup (info->channel_position, faad->channels);
caps = gst_caps_new_simple ("audio/x-raw", /* FIXME: Use the GstAudioInfo of GstAudioDecoder for all of this */
"format", G_TYPE_STRING, GST_AUDIO_NE (S16), gst_audio_info_init (&ainfo);
"rate", G_TYPE_INT, faad->samplerate, gst_audio_info_set_format (&ainfo, GST_AUDIO_FORMAT_S16, faad->samplerate,
"channels", G_TYPE_INT, faad->channels, NULL); faad->channels, NULL);
faad->bps = 16 / 8; faad->bps = 16 / 8;
channel_map_failed = FALSE; if (!gst_faad_chanpos_to_gst (faad, faad->channel_positions,
pos = faad->aac_positions, faad->channels)) {
gst_faad_chanpos_to_gst (faad, faad->channel_positions, faad->channels,
&channel_map_failed);
if (channel_map_failed) {
GST_DEBUG_OBJECT (faad, "Could not map channel positions"); GST_DEBUG_OBJECT (faad, "Could not map channel positions");
gst_caps_unref (caps);
return FALSE; return FALSE;
} }
if (pos) { memcpy (ainfo.position, faad->aac_positions,
gst_audio_set_channel_positions (gst_caps_get_structure (caps, 0), pos); faad->channels * sizeof (GstAudioChannelPosition));
g_free (pos); gst_audio_channel_positions_to_valid_order (ainfo.position, faad->channels);
} memcpy (faad->gst_positions, ainfo.position,
faad->channels * sizeof (GstAudioChannelPosition));
caps = gst_audio_info_to_caps (&ainfo);
GST_DEBUG_OBJECT (faad, "New output caps: %" GST_PTR_FORMAT, caps); GST_DEBUG_OBJECT (faad, "New output caps: %" GST_PTR_FORMAT, caps);
@ -751,6 +751,8 @@ init:
/* FIXME, add bufferpool and allocator support to the base class */ /* FIXME, add bufferpool and allocator support to the base class */
outbuf = gst_buffer_new_allocate (NULL, info.samples * faad->bps, 0); outbuf = gst_buffer_new_allocate (NULL, info.samples * faad->bps, 0);
gst_buffer_fill (outbuf, 0, out, info.samples * faad->bps); gst_buffer_fill (outbuf, 0, out, info.samples * faad->bps);
gst_audio_buffer_reorder_channels (outbuf, GST_AUDIO_FORMAT_S16,
faad->channels, faad->aac_positions, faad->gst_positions);
ret = gst_audio_decoder_finish_frame (dec, outbuf, 1); ret = gst_audio_decoder_finish_frame (dec, outbuf, 1);
} }

View file

@ -49,6 +49,7 @@ typedef struct _GstFaad {
guint channels; /* number of channels of the last frame */ guint channels; /* number of channels of the last frame */
guint bps; /* bytes per sample */ guint bps; /* bytes per sample */
guchar *channel_positions; guchar *channel_positions;
GstAudioChannelPosition aac_positions[6], gst_positions[6];
guint8 fake_codec_data[2]; guint8 fake_codec_data[2];
guint32 last_header; guint32 last_header;