static void sink_handoff_float32 (GstElement * element, GstBuffer * buffer, GstPad * pad, gpointer user_data) { gint i; GstMapInfo map; gfloat *data; GstCaps *caps, *ccaps; gint n = GPOINTER_TO_INT (user_data); guint64 mask; fail_unless (GST_IS_BUFFER (buffer)); gst_buffer_map (buffer, &map, GST_MAP_READ); data = (gfloat *) map.data; fail_unless_equals_int (map.size, 48000 * 2 * sizeof (gfloat)); fail_unless_equals_int (GST_BUFFER_DURATION (buffer), GST_SECOND); if (n == 0) { GstAudioChannelPosition pos[2] = { GST_AUDIO_CHANNEL_POSITION_NONE, GST_AUDIO_CHANNEL_POSITION_NONE }; gst_audio_channel_positions_to_mask (pos, 2, FALSE, &mask); } else if (n == 1) { GstAudioChannelPosition pos[2] = { GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT }; gst_audio_channel_positions_to_mask (pos, 2, FALSE, &mask); } else if (n == 2) { GstAudioChannelPosition pos[2] = { GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, GST_AUDIO_CHANNEL_POSITION_REAR_CENTER }; gst_audio_channel_positions_to_mask (pos, 2, FALSE, &mask); } else { g_assert_not_reached (); } caps = gst_caps_new_simple ("audio/x-raw", "format", G_TYPE_STRING, GST_AUDIO_NE (F32), "channels", G_TYPE_INT, 2, "rate", G_TYPE_INT, 48000, "layout", G_TYPE_STRING, "interleaved", "channel-mask", GST_TYPE_BITMASK, mask, NULL); ccaps = gst_pad_get_current_caps (pad); fail_unless (gst_caps_is_equal (caps, ccaps)); gst_caps_unref (ccaps); gst_caps_unref (caps); #ifdef HAVE_VALGRIND if (!(RUNNING_ON_VALGRIND)) #endif for (i = 0; i < 48000 * 2; i += 2) { fail_unless_equals_float (data[i], -1.0); fail_unless_equals_float (data[i + 1], 1.0); } gst_buffer_unmap (buffer, &map); have_data++; }
static gboolean gst_interleave_channel_positions_to_mask (GValueArray * positions, gint default_ordering_map[64], guint64 * mask) { gint i; guint channels; GstAudioChannelPosition *pos; gboolean ret; channels = positions->n_values; pos = g_new (GstAudioChannelPosition, channels); for (i = 0; i < channels; i++) { GValue *val; val = g_value_array_get_nth (positions, i); pos[i] = g_value_get_enum (val); } /* sort the default ordering map according to the position order */ for (i = 0; i < channels; i++) { default_ordering_map[i] = i; } g_qsort_with_data (default_ordering_map, channels, sizeof (*default_ordering_map), compare_positions, pos); ret = gst_audio_channel_positions_to_mask (pos, channels, FALSE, mask); g_free (pos); return ret; }
static GstCaps * gst_fdkaacenc_get_caps (GstAudioEncoder * enc, GstCaps * filter) { GstCaps *res, *caps; gint i; caps = gst_caps_new_empty (); for (i = 0; i < G_N_ELEMENTS (channel_layouts); i++) { guint64 channel_mask; GstCaps *tmp = gst_caps_make_writable (gst_pad_get_pad_template_caps (GST_AUDIO_ENCODER_SINK_PAD (enc))); if (channel_layouts[i].channels == 1) { gst_caps_set_simple (tmp, "channels", G_TYPE_INT, channel_layouts[i].channels, NULL); } else { gst_audio_channel_positions_to_mask (channel_layouts[i].positions, channel_layouts[i].channels, FALSE, &channel_mask); gst_caps_set_simple (tmp, "channels", G_TYPE_INT, channel_layouts[i].channels, "channel-mask", GST_TYPE_BITMASK, channel_mask, NULL); } gst_caps_append (caps, tmp); } res = gst_audio_encoder_proxy_getcaps (enc, caps, filter); gst_caps_unref (caps); return res; }
static gboolean gst_interleave_channel_positions_to_mask (GValueArray * positions, guint64 * mask) { gint i; guint channels; GstAudioChannelPosition *pos; gboolean ret; channels = positions->n_values; pos = g_new (GstAudioChannelPosition, channels); for (i = 0; i < channels; i++) { GValue *val; val = g_value_array_get_nth (positions, i); pos[i] = g_value_get_enum (val); } ret = gst_audio_channel_positions_to_mask (pos, channels, FALSE, mask); g_free (pos); return ret; }
static GstCaps * gst_openal_helper_probe_caps (ALCcontext * context) { static const struct { gint count; GstAudioChannelPosition positions[8]; } chans[] = { { 1, { GST_AUDIO_CHANNEL_POSITION_MONO} }, { 2, { GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT} }, { 4, { GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT} }, { 6, { GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, GST_AUDIO_CHANNEL_POSITION_LFE1, GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT} }, { 7, { GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, GST_AUDIO_CHANNEL_POSITION_LFE1, GST_AUDIO_CHANNEL_POSITION_REAR_CENTER, GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT, GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT} }, { 8, { GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, GST_AUDIO_CHANNEL_POSITION_LFE1, GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT, GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT} },}; GstStructure *structure; guint64 channel_mask; GstCaps *caps; ALCcontext *old; old = pushContext (context); caps = gst_caps_new_empty (); if (alIsExtensionPresent ("AL_EXT_MCFORMATS")) { const char *fmt32[] = { "AL_FORMAT_MONO_FLOAT32", "AL_FORMAT_STEREO_FLOAT32", "AL_FORMAT_QUAD32", "AL_FORMAT_51CHN32", "AL_FORMAT_61CHN32", "AL_FORMAT_71CHN32", NULL }, *fmt16[] = { "AL_FORMAT_MONO16", "AL_FORMAT_STEREO16", "AL_FORMAT_QUAD16", "AL_FORMAT_51CHN16", "AL_FORMAT_61CHN16", "AL_FORMAT_71CHN16", NULL}, *fmt8[] = { "AL_FORMAT_MONO8", "AL_FORMAT_STEREO8", "AL_FORMAT_QUAD8", "AL_FORMAT_51CHN8", "AL_FORMAT_61CHN8", "AL_FORMAT_71CHN8", NULL}; int i; if (alIsExtensionPresent ("AL_EXT_FLOAT32")) { for (i = 0; fmt32[i]; i++) { ALenum value = alGetEnumValue (fmt32[i]); if (checkALError () != AL_NO_ERROR || value == 0 || value == -1) continue; structure = gst_structure_new ("audio/x-raw", "format", G_TYPE_STRING, GST_AUDIO_NE (F32), "rate", GST_TYPE_INT_RANGE, OPENAL_MIN_RATE, OPENAL_MAX_RATE, "channels", G_TYPE_INT, chans[i].count, NULL); if (chans[i].count > 2) { gst_audio_channel_positions_to_mask (chans[i].positions, chans[i].count, FALSE, &channel_mask); gst_structure_set (structure, "channel-mask", GST_TYPE_BITMASK, channel_mask, NULL); } gst_caps_append_structure (caps, structure); } } for (i = 0; fmt16[i]; i++) { ALenum value = alGetEnumValue (fmt16[i]); if (checkALError () != AL_NO_ERROR || value == 0 || value == -1) continue; structure = gst_structure_new ("audio/x-raw", "format", G_TYPE_STRING, GST_AUDIO_NE (S16), "rate", GST_TYPE_INT_RANGE, OPENAL_MIN_RATE, OPENAL_MAX_RATE, "channels", G_TYPE_INT, chans[i].count, NULL); if (chans[i].count > 2) { gst_audio_channel_positions_to_mask (chans[i].positions, chans[i].count, FALSE, &channel_mask); gst_structure_set (structure, "channel-mask", GST_TYPE_BITMASK, channel_mask, NULL); } gst_caps_append_structure (caps, structure); } for (i = 0; fmt8[i]; i++) { ALenum value = alGetEnumValue (fmt8[i]); if (checkALError () != AL_NO_ERROR || value == 0 || value == -1) continue; structure = gst_structure_new ("audio/x-raw", "format", G_TYPE_STRING, G_STRINGIFY (U8), "rate", GST_TYPE_INT_RANGE, OPENAL_MIN_RATE, OPENAL_MAX_RATE, "channels", G_TYPE_INT, chans[i].count, NULL); if (chans[i].count > 2) { gst_audio_channel_positions_to_mask (chans[i].positions, chans[i].count, FALSE, &channel_mask); gst_structure_set (structure, "channel-mask", GST_TYPE_BITMASK, channel_mask, NULL); } gst_caps_append_structure (caps, structure); } } else { if (alIsExtensionPresent ("AL_EXT_FLOAT32")) { structure = gst_structure_new ("audio/x-raw", "format", G_TYPE_STRING, GST_AUDIO_NE (F32), "rate", GST_TYPE_INT_RANGE, OPENAL_MIN_RATE, OPENAL_MAX_RATE, "channels", GST_TYPE_INT_RANGE, 1, 2, NULL); gst_caps_append_structure (caps, structure); } structure = gst_structure_new ("audio/x-raw", "format", G_TYPE_STRING, GST_AUDIO_NE (S16), "rate", GST_TYPE_INT_RANGE, OPENAL_MIN_RATE, OPENAL_MAX_RATE, "channels", GST_TYPE_INT_RANGE, 1, 2, NULL); gst_caps_append_structure (caps, structure); structure = gst_structure_new ("audio/x-raw", "format", G_TYPE_STRING, G_STRINGIFY (U8), "rate", GST_TYPE_INT_RANGE, OPENAL_MIN_RATE, OPENAL_MAX_RATE, "channels", GST_TYPE_INT_RANGE, 1, 2, NULL); gst_caps_append_structure (caps, structure); } if (alIsExtensionPresent ("AL_EXT_double")) { structure = gst_structure_new ("audio/x-raw", "format", G_TYPE_STRING, GST_AUDIO_NE (F64), "rate", GST_TYPE_INT_RANGE, OPENAL_MIN_RATE, OPENAL_MAX_RATE, "channels", GST_TYPE_INT_RANGE, 1, 2, NULL); gst_caps_append_structure (caps, structure); } if (alIsExtensionPresent ("AL_EXT_IMA4")) { structure = gst_structure_new ("audio/x-adpcm", "layout", G_TYPE_STRING, "ima", "rate", GST_TYPE_INT_RANGE, OPENAL_MIN_RATE, OPENAL_MAX_RATE, "channels", GST_TYPE_INT_RANGE, 1, 2, NULL); gst_caps_append_structure (caps, structure); } if (alIsExtensionPresent ("AL_EXT_ALAW")) { structure = gst_structure_new ("audio/x-alaw", "rate", GST_TYPE_INT_RANGE, OPENAL_MIN_RATE, OPENAL_MAX_RATE, "channels", GST_TYPE_INT_RANGE, 1, 2, NULL); gst_caps_append_structure (caps, structure); } if (alIsExtensionPresent ("AL_EXT_MULAW_MCFORMATS")) { const char *fmtmulaw[] = { "AL_FORMAT_MONO_MULAW", "AL_FORMAT_STEREO_MULAW", "AL_FORMAT_QUAD_MULAW", "AL_FORMAT_51CHN_MULAW", "AL_FORMAT_61CHN_MULAW", "AL_FORMAT_71CHN_MULAW", NULL }; int i; for (i = 0; fmtmulaw[i]; i++) { ALenum value = alGetEnumValue (fmtmulaw[i]); if (checkALError () != AL_NO_ERROR || value == 0 || value == -1) continue; structure = gst_structure_new ("audio/x-mulaw", "rate", GST_TYPE_INT_RANGE, OPENAL_MIN_RATE, OPENAL_MAX_RATE, "channels", G_TYPE_INT, chans[i].count, NULL); if (chans[i].count > 2) { gst_audio_channel_positions_to_mask (chans[i].positions, chans[i].count, FALSE, &channel_mask); gst_structure_set (structure, "channel-mask", GST_TYPE_BITMASK, channel_mask, NULL); } gst_caps_append_structure (caps, structure); } } else if (alIsExtensionPresent ("AL_EXT_MULAW")) { structure = gst_structure_new ("audio/x-mulaw", "rate", GST_TYPE_INT_RANGE, OPENAL_MIN_RATE, OPENAL_MAX_RATE, "channels", GST_TYPE_INT_RANGE, 1, 2, NULL); gst_caps_append_structure (caps, structure); } popContext (old, context); return caps; }
static gboolean gst_fdkaacenc_set_format (GstAudioEncoder * enc, GstAudioInfo * info) { GstFdkAacEnc *self = GST_FDKAACENC (enc); gboolean ret = FALSE; GstCaps *allowed_caps; GstCaps *src_caps; AACENC_ERROR err; gint transmux = 0, aot = AOT_AAC_LC; gint mpegversion = 4; CHANNEL_MODE channel_mode; AACENC_InfoStruct enc_info = { 0 }; gint bitrate; if (self->enc) { /* drain */ gst_fdkaacenc_handle_frame (enc, NULL); aacEncClose (&self->enc); } allowed_caps = gst_pad_get_allowed_caps (GST_AUDIO_ENCODER_SRC_PAD (self)); GST_DEBUG_OBJECT (self, "allowed caps: %" GST_PTR_FORMAT, allowed_caps); if (allowed_caps && gst_caps_get_size (allowed_caps) > 0) { GstStructure *s = gst_caps_get_structure (allowed_caps, 0); const gchar *str = NULL; if ((str = gst_structure_get_string (s, "stream-format"))) { if (strcmp (str, "adts") == 0) { GST_DEBUG_OBJECT (self, "use ADTS format for output"); transmux = 2; } else if (strcmp (str, "adif") == 0) { GST_DEBUG_OBJECT (self, "use ADIF format for output"); transmux = 1; } else if (strcmp (str, "raw") == 0) { GST_DEBUG_OBJECT (self, "use RAW format for output"); transmux = 0; } } gst_structure_get_int (s, "mpegversion", &mpegversion); } if (allowed_caps) gst_caps_unref (allowed_caps); err = aacEncOpen (&self->enc, 0, GST_AUDIO_INFO_CHANNELS (info)); if (err != AACENC_OK) { GST_ERROR_OBJECT (self, "Unable to open encoder: %d\n", err); return FALSE; } aot = AOT_AAC_LC; if ((err = aacEncoder_SetParam (self->enc, AACENC_AOT, aot)) != AACENC_OK) { GST_ERROR_OBJECT (self, "Unable to set AOT %d: %d\n", aot, err); return FALSE; } if ((err = aacEncoder_SetParam (self->enc, AACENC_SAMPLERATE, GST_AUDIO_INFO_RATE (info))) != AACENC_OK) { GST_ERROR_OBJECT (self, "Unable to set sample rate %d: %d\n", GST_AUDIO_INFO_RATE (info), err); return FALSE; } if (GST_AUDIO_INFO_CHANNELS (info) == 1) { channel_mode = MODE_1; self->need_reorder = FALSE; self->aac_positions = NULL; } else { guint64 in_channel_mask, out_channel_mask; gint i; for (i = 0; i < G_N_ELEMENTS (channel_layouts); i++) { if (channel_layouts[i].channels != GST_AUDIO_INFO_CHANNELS (info)) continue; gst_audio_channel_positions_to_mask (&GST_AUDIO_INFO_POSITION (info, 0), GST_AUDIO_INFO_CHANNELS (info), FALSE, &in_channel_mask); gst_audio_channel_positions_to_mask (channel_layouts[i].positions, channel_layouts[i].channels, FALSE, &out_channel_mask); if (in_channel_mask == out_channel_mask) { channel_mode = channel_layouts[i].mode; self->need_reorder = memcmp (channel_layouts[i].positions, &GST_AUDIO_INFO_POSITION (info, 0), GST_AUDIO_INFO_CHANNELS (info) * sizeof (GstAudioChannelPosition)) != 0; self->aac_positions = channel_layouts[i].positions; break; } } if (i == G_N_ELEMENTS (channel_layouts)) { GST_ERROR_OBJECT (self, "Couldn't find a valid channel layout"); return FALSE; } } if ((err = aacEncoder_SetParam (self->enc, AACENC_CHANNELMODE, channel_mode)) != AACENC_OK) { GST_ERROR_OBJECT (self, "Unable to set channel mode %d: %d", channel_mode, err); return FALSE; } /* MPEG channel order */ if ((err = aacEncoder_SetParam (self->enc, AACENC_CHANNELORDER, 0)) != AACENC_OK) { GST_ERROR_OBJECT (self, "Unable to set channel order %d: %d", channel_mode, err); return FALSE; } bitrate = self->bitrate; /* See * http://wiki.hydrogenaud.io/index.php?title=Fraunhofer_FDK_AAC#Recommended_Sampling_Rate_and_Bitrate_Combinations */ if (bitrate == 0) { if (GST_AUDIO_INFO_CHANNELS (info) == 1) { if (GST_AUDIO_INFO_RATE (info) < 16000) { bitrate = 8000; } else if (GST_AUDIO_INFO_RATE (info) == 16000) { bitrate = 16000; } else if (GST_AUDIO_INFO_RATE (info) < 32000) { bitrate = 24000; } else if (GST_AUDIO_INFO_RATE (info) == 32000) { bitrate = 32000; } else if (GST_AUDIO_INFO_RATE (info) <= 44100) { bitrate = 56000; } else { bitrate = 160000; } } else if (GST_AUDIO_INFO_CHANNELS (info) == 2) { if (GST_AUDIO_INFO_RATE (info) < 16000) { bitrate = 16000; } else if (GST_AUDIO_INFO_RATE (info) == 16000) { bitrate = 24000; } else if (GST_AUDIO_INFO_RATE (info) < 22050) { bitrate = 32000; } else if (GST_AUDIO_INFO_RATE (info) < 32000) { bitrate = 40000; } else if (GST_AUDIO_INFO_RATE (info) == 32000) { bitrate = 96000; } else if (GST_AUDIO_INFO_RATE (info) <= 44100) { bitrate = 112000; } else { bitrate = 320000; } } else { /* 5, 5.1 */ if (GST_AUDIO_INFO_RATE (info) < 32000) { bitrate = 160000; } else if (GST_AUDIO_INFO_RATE (info) <= 44100) { bitrate = 240000; } else { bitrate = 320000; } } } if ((err = aacEncoder_SetParam (self->enc, AACENC_TRANSMUX, transmux)) != AACENC_OK) { GST_ERROR_OBJECT (self, "Unable to set transmux %d: %d", transmux, err); return FALSE; } if ((err = aacEncoder_SetParam (self->enc, AACENC_BITRATE, bitrate)) != AACENC_OK) { GST_ERROR_OBJECT (self, "Unable to set bitrate %d: %d", bitrate, err); return FALSE; } if ((err = aacEncEncode (self->enc, NULL, NULL, NULL, NULL)) != AACENC_OK) { GST_ERROR_OBJECT (self, "Unable to initialize encoder: %d", err); return FALSE; } if ((err = aacEncInfo (self->enc, &enc_info)) != AACENC_OK) { GST_ERROR_OBJECT (self, "Unable to get encoder info: %d", err); return FALSE; } gst_audio_encoder_set_frame_max (enc, 1); gst_audio_encoder_set_frame_samples_min (enc, enc_info.frameLength); gst_audio_encoder_set_frame_samples_max (enc, enc_info.frameLength); gst_audio_encoder_set_hard_min (enc, FALSE); self->outbuf_size = enc_info.maxOutBufBytes; self->samples_per_frame = enc_info.frameLength; src_caps = gst_caps_new_simple ("audio/mpeg", "mpegversion", G_TYPE_INT, mpegversion, "channels", G_TYPE_INT, GST_AUDIO_INFO_CHANNELS (info), "framed", G_TYPE_BOOLEAN, TRUE, "rate", G_TYPE_INT, GST_AUDIO_INFO_RATE (info), NULL); /* raw */ if (transmux == 0) { GstBuffer *codec_data = gst_buffer_new_wrapped (g_memdup (enc_info.confBuf, enc_info.confSize), enc_info.confSize); gst_caps_set_simple (src_caps, "codec_data", GST_TYPE_BUFFER, codec_data, "stream-format", G_TYPE_STRING, "raw", NULL); gst_buffer_unref (codec_data); } else if (transmux == 1) { gst_caps_set_simple (src_caps, "stream-format", G_TYPE_STRING, "adif", NULL); } else if (transmux == 2) { gst_caps_set_simple (src_caps, "stream-format", G_TYPE_STRING, "adts", NULL); } else { g_assert_not_reached (); } gst_codec_utils_aac_caps_set_level_and_profile (src_caps, enc_info.confBuf, enc_info.confSize); ret = gst_audio_encoder_set_output_format (enc, src_caps); gst_caps_unref (src_caps); return ret; }
/** * gst_audio_info_to_caps: * @info: a #GstAudioInfo * * Convert the values of @info into a #GstCaps. * * Returns: (transfer full): the new #GstCaps containing the * info of @info. */ GstCaps * gst_audio_info_to_caps (const GstAudioInfo * info) { GstCaps *caps; const gchar *format; const gchar *layout; GstAudioFlags flags; g_return_val_if_fail (info != NULL, NULL); g_return_val_if_fail (info->finfo != NULL, NULL); g_return_val_if_fail (info->finfo->format != GST_AUDIO_FORMAT_UNKNOWN, NULL); format = gst_audio_format_to_string (info->finfo->format); g_return_val_if_fail (format != NULL, NULL); if (info->layout == GST_AUDIO_LAYOUT_INTERLEAVED) layout = "interleaved"; else if (info->layout == GST_AUDIO_LAYOUT_NON_INTERLEAVED) layout = "non-interleaved"; else g_return_val_if_reached (NULL); flags = info->flags; if ((flags & GST_AUDIO_FLAG_UNPOSITIONED) && info->channels > 1 && info->position[0] != GST_AUDIO_CHANNEL_POSITION_NONE) { flags &= ~GST_AUDIO_FLAG_UNPOSITIONED; g_warning ("Unpositioned audio channel position flag set but " "channel positions present"); } else if (!(flags & GST_AUDIO_FLAG_UNPOSITIONED) && info->channels > 1 && info->position[0] == GST_AUDIO_CHANNEL_POSITION_NONE) { flags |= GST_AUDIO_FLAG_UNPOSITIONED; g_warning ("Unpositioned audio channel position flag not set " "but no channel positions present"); } caps = gst_caps_new_simple ("audio/x-raw", "format", G_TYPE_STRING, format, "layout", G_TYPE_STRING, layout, "rate", G_TYPE_INT, info->rate, "channels", G_TYPE_INT, info->channels, NULL); if (info->channels > 1 || info->position[0] != GST_AUDIO_CHANNEL_POSITION_MONO) { guint64 channel_mask = 0; if ((flags & GST_AUDIO_FLAG_UNPOSITIONED)) { channel_mask = 0; } else { if (!gst_audio_channel_positions_to_mask (info->position, info->channels, TRUE, &channel_mask)) goto invalid_channel_positions; } if (info->channels == 1 && info->position[0] == GST_AUDIO_CHANNEL_POSITION_MONO) { /* Default mono special case */ } else { gst_caps_set_simple (caps, "channel-mask", GST_TYPE_BITMASK, channel_mask, NULL); } } return caps; invalid_channel_positions: { GST_ERROR ("Invalid channel positions"); gst_caps_unref (caps); return NULL; } }
static gboolean gst_osx_audio_sink_allowed_caps (GstOsxAudioSink * osxsink) { gint i, channels; gboolean spdif_allowed; AudioChannelLayout *layout; GstElementClass *element_class; GstPadTemplate *pad_template; GstCaps *caps, *in_caps; guint64 channel_mask = 0; GstAudioChannelPosition *pos = osxsink->channel_positions; /* First collect info about the HW capabilites and preferences */ spdif_allowed = gst_core_audio_audio_device_is_spdif_avail (osxsink->device_id); layout = gst_core_audio_audio_device_get_channel_layout (osxsink->device_id); GST_DEBUG_OBJECT (osxsink, "Selected device ID: %u SPDIF allowed: %d", (unsigned) osxsink->device_id, spdif_allowed); if (layout) { channels = MIN (layout->mNumberChannelDescriptions, GST_OSX_AUDIO_MAX_CHANNEL); } else { GST_WARNING_OBJECT (osxsink, "This driver does not support " "kAudioDevicePropertyPreferredChannelLayout."); channels = 2; } switch (channels) { case 0: pos[0] = GST_AUDIO_CHANNEL_POSITION_NONE; break; case 1: pos[0] = GST_AUDIO_CHANNEL_POSITION_MONO; break; case 2: pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT; pos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT; channel_mask |= GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_LEFT); channel_mask |= GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_RIGHT); break; default: channels = MIN (layout->mNumberChannelDescriptions, GST_OSX_AUDIO_MAX_CHANNEL); for (i = 0; i < channels; i++) { switch (layout->mChannelDescriptions[i].mChannelLabel) { case kAudioChannelLabel_Left: pos[i] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT; break; case kAudioChannelLabel_Right: pos[i] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT; break; case kAudioChannelLabel_Center: pos[i] = GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER; break; case kAudioChannelLabel_LFEScreen: pos[i] = GST_AUDIO_CHANNEL_POSITION_LFE1; break; case kAudioChannelLabel_LeftSurround: pos[i] = GST_AUDIO_CHANNEL_POSITION_REAR_LEFT; break; case kAudioChannelLabel_RightSurround: pos[i] = GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT; break; case kAudioChannelLabel_RearSurroundLeft: pos[i] = GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT; break; case kAudioChannelLabel_RearSurroundRight: pos[i] = GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT; break; case kAudioChannelLabel_CenterSurround: pos[i] = GST_AUDIO_CHANNEL_POSITION_REAR_CENTER; break; default: GST_WARNING_OBJECT (osxsink, "unrecognized channel: %d", (int) layout->mChannelDescriptions[i].mChannelLabel); channel_mask = 0; channels = 2; break; } } } g_free (layout); /* Recover the template caps */ element_class = GST_ELEMENT_GET_CLASS (osxsink); pad_template = gst_element_class_get_pad_template (element_class, "sink"); in_caps = gst_pad_template_get_caps (pad_template); /* Create the allowed subset */ caps = gst_caps_new_empty (); for (i = 0; i < gst_caps_get_size (in_caps); i++) { GstStructure *in_s, *out_s; in_s = gst_caps_get_structure (in_caps, i); if (gst_structure_has_name (in_s, "audio/x-ac3") || gst_structure_has_name (in_s, "audio/x-dts")) { if (spdif_allowed) { gst_caps_append_structure (caps, gst_structure_copy (in_s)); } } gst_audio_channel_positions_to_mask (pos, channels, false, &channel_mask); out_s = gst_structure_copy (in_s); gst_structure_remove_fields (out_s, "channels", "channel-mask", NULL); gst_structure_set (out_s, "channels", G_TYPE_INT, channels, "channel-mask", GST_TYPE_BITMASK, channel_mask, NULL); gst_caps_append_structure (caps, out_s); } if (osxsink->cached_caps) { gst_caps_unref (osxsink->cached_caps); } osxsink->cached_caps = caps; osxsink->channels = channels; return TRUE; }
static gboolean gst_raw_audio_parse_config_to_caps (GstRawAudioParse * raw_audio_parse, GstCaps ** caps, GstRawAudioParseConfig * config) { gboolean ret = TRUE; GstAudioChannelPosition *channel_positions; g_assert (caps != NULL); if (config->bpf == 0) { GST_ERROR_OBJECT (raw_audio_parse, "cannot convert config to caps - config not filled with valid values"); *caps = NULL; return FALSE; } channel_positions = config->needs_channel_reordering ? &(config-> reordered_channel_positions[0]) : &(config->channel_positions[0]); switch (config->format) { case GST_RAW_AUDIO_PARSE_FORMAT_PCM: { GstAudioInfo info; gst_audio_info_init (&info); gst_audio_info_set_format (&info, config->pcm_format, config->sample_rate, config->num_channels, channel_positions); *caps = gst_audio_info_to_caps (&info); break; } case GST_RAW_AUDIO_PARSE_FORMAT_ALAW: case GST_RAW_AUDIO_PARSE_FORMAT_MULAW: { guint64 channel_mask; if (!gst_audio_channel_positions_to_mask (channel_positions, config->num_channels, TRUE, &channel_mask)) { GST_ERROR_OBJECT (raw_audio_parse, "invalid channel positions"); ret = FALSE; break; } *caps = gst_caps_new_simple ( (config->format == GST_RAW_AUDIO_PARSE_FORMAT_ALAW) ? "audio/x-alaw" : "audio/x-mulaw", "rate", G_TYPE_INT, config->sample_rate, "channels", G_TYPE_INT, config->num_channels, "channel-mask", GST_TYPE_BITMASK, channel_mask, NULL); break; } default: g_assert_not_reached (); ret = FALSE; } if (!ret) *caps = NULL; return ret; }