gboolean gst_core_audio_parse_channel_layout (AudioChannelLayout * layout, guint * channels, guint64 * channel_mask, GstAudioChannelPosition * pos) { g_assert (channels != NULL); g_assert (channel_mask != NULL); g_assert (layout != NULL); if (layout->mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelDescriptions) { switch (layout->mNumberChannelDescriptions) { case 0: if (pos) pos[0] = GST_AUDIO_CHANNEL_POSITION_NONE; *channels = 0; *channel_mask = 0; return TRUE; case 1: if (pos) pos[0] = GST_AUDIO_CHANNEL_POSITION_MONO; *channels = 1; *channel_mask = 0; return TRUE; case 2: if (pos) { pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT; pos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT; } *channels = 2; *channel_mask = GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_LEFT) | GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_RIGHT); return TRUE; default: _core_audio_parse_channel_descriptions (layout, channels, channel_mask, pos); return TRUE; } } else if (layout->mChannelLayoutTag == kAudioChannelLayoutTag_Mono) { if (pos) pos[0] = GST_AUDIO_CHANNEL_POSITION_MONO; *channels = 1; *channel_mask = 0; return TRUE; } else if (layout->mChannelLayoutTag == kAudioChannelLayoutTag_Stereo || layout->mChannelLayoutTag == kAudioChannelLayoutTag_StereoHeadphones || layout->mChannelLayoutTag == kAudioChannelLayoutTag_Binaural) { if (pos) { pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT; pos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT; } *channels = 2; *channel_mask = GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_LEFT) | GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_RIGHT); return TRUE; } else if (layout->mChannelLayoutTag == kAudioChannelLayoutTag_Quadraphonic) { if (pos) { pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT; pos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT; pos[2] = GST_AUDIO_CHANNEL_POSITION_SURROUND_LEFT; pos[3] = GST_AUDIO_CHANNEL_POSITION_SURROUND_RIGHT; } *channels = 4; *channel_mask = GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_LEFT) | GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_RIGHT) | GST_AUDIO_CHANNEL_POSITION_MASK (SURROUND_LEFT) | GST_AUDIO_CHANNEL_POSITION_MASK (SURROUND_RIGHT); return TRUE; } else if (layout->mChannelLayoutTag == kAudioChannelLayoutTag_Pentagonal) { if (pos) { pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT; pos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT; pos[2] = GST_AUDIO_CHANNEL_POSITION_SURROUND_LEFT; pos[3] = GST_AUDIO_CHANNEL_POSITION_SURROUND_RIGHT; pos[4] = GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER; } *channels = 5; *channel_mask = GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_LEFT) | GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_RIGHT) | GST_AUDIO_CHANNEL_POSITION_MASK (SURROUND_LEFT) | GST_AUDIO_CHANNEL_POSITION_MASK (SURROUND_RIGHT) | GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_CENTER); return TRUE; } else if (layout->mChannelLayoutTag == kAudioChannelLayoutTag_Cube) { if (pos) { pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT; pos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT; pos[2] = GST_AUDIO_CHANNEL_POSITION_REAR_LEFT; pos[3] = GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT; pos[4] = GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_LEFT; pos[5] = GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_RIGHT; pos[6] = GST_AUDIO_CHANNEL_POSITION_TOP_REAR_LEFT; pos[7] = GST_AUDIO_CHANNEL_POSITION_TOP_REAR_RIGHT; } *channels = 8; *channel_mask = GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_LEFT) | GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_RIGHT) | GST_AUDIO_CHANNEL_POSITION_MASK (REAR_LEFT) | GST_AUDIO_CHANNEL_POSITION_MASK (REAR_RIGHT) | GST_AUDIO_CHANNEL_POSITION_MASK (TOP_FRONT_LEFT) | GST_AUDIO_CHANNEL_POSITION_MASK (TOP_FRONT_RIGHT) | GST_AUDIO_CHANNEL_POSITION_MASK (TOP_REAR_LEFT) | GST_AUDIO_CHANNEL_POSITION_MASK (TOP_REAR_RIGHT); return TRUE; } else { GST_WARNING ("AudioChannelLayoutTag: %u not yet supported", layout->mChannelLayoutTag); *channels = 0; *channel_mask = 0; return FALSE; } }
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_pulsesrc_create_stream (GstPulseSrc * pulsesrc, GstCaps ** caps) { pa_channel_map channel_map; const pa_channel_map *m; GstStructure *s; gboolean need_channel_layout = FALSE; GstAudioRingBufferSpec spec; const gchar *name; s = gst_caps_get_structure (*caps, 0); gst_structure_get_int (s, "channels", &spec.info.channels); if (!gst_structure_has_field (s, "channel-mask")) { if (spec.info.channels == 1) { pa_channel_map_init_mono (&channel_map); } else if (spec.info.channels == 2) { gst_structure_set (s, "channel-mask", GST_TYPE_BITMASK, GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_LEFT) | GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_RIGHT), NULL); pa_channel_map_init_stereo (&channel_map); } else { need_channel_layout = TRUE; gst_structure_set (s, "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL); } } memset (&spec, 0, sizeof (GstAudioRingBufferSpec)); spec.latency_time = GST_SECOND; if (!gst_audio_ring_buffer_parse_caps (&spec, *caps)) goto invalid_caps; /* Keep the refcount of the caps at 1 to make them writable */ gst_caps_unref (spec.caps); if (!need_channel_layout && !gst_pulse_gst_to_channel_map (&channel_map, &spec)) { need_channel_layout = TRUE; gst_structure_set (s, "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL); memset (spec.info.position, 0xff, sizeof (spec.info.position)); } if (!gst_pulse_fill_sample_spec (&spec, &pulsesrc->sample_spec)) goto invalid_spec; pa_threaded_mainloop_lock (pulsesrc->mainloop); if (!pulsesrc->context) goto bad_context; name = "Record Stream"; if (pulsesrc->proplist) { if (!(pulsesrc->stream = pa_stream_new_with_proplist (pulsesrc->context, name, &pulsesrc->sample_spec, (need_channel_layout) ? NULL : &channel_map, pulsesrc->proplist))) goto create_failed; } else if (!(pulsesrc->stream = pa_stream_new (pulsesrc->context, name, &pulsesrc->sample_spec, (need_channel_layout) ? NULL : &channel_map))) goto create_failed; m = pa_stream_get_channel_map (pulsesrc->stream); gst_pulse_channel_map_to_gst (m, &spec); gst_audio_channel_positions_to_valid_order (spec.info.position, spec.info.channels); gst_caps_unref (*caps); *caps = gst_audio_info_to_caps (&spec.info); GST_DEBUG_OBJECT (pulsesrc, "Caps are %" GST_PTR_FORMAT, *caps); pa_stream_set_state_callback (pulsesrc->stream, gst_pulsesrc_stream_state_cb, pulsesrc); pa_stream_set_read_callback (pulsesrc->stream, gst_pulsesrc_stream_request_cb, pulsesrc); pa_stream_set_underflow_callback (pulsesrc->stream, gst_pulsesrc_stream_underflow_cb, pulsesrc); pa_stream_set_overflow_callback (pulsesrc->stream, gst_pulsesrc_stream_overflow_cb, pulsesrc); pa_stream_set_latency_update_callback (pulsesrc->stream, gst_pulsesrc_stream_latency_update_cb, pulsesrc); pa_threaded_mainloop_unlock (pulsesrc->mainloop); return TRUE; /* ERRORS */ invalid_caps: { GST_ELEMENT_ERROR (pulsesrc, RESOURCE, SETTINGS, ("Can't parse caps."), (NULL)); goto fail; } invalid_spec: { GST_ELEMENT_ERROR (pulsesrc, RESOURCE, SETTINGS, ("Invalid sample specification."), (NULL)); goto fail; } bad_context: { GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED, ("Bad context"), (NULL)); goto unlock_and_fail; } create_failed: { GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED, ("Failed to create stream: %s", pa_strerror (pa_context_errno (pulsesrc->context))), (NULL)); goto unlock_and_fail; } unlock_and_fail: { gst_pulsesrc_destroy_stream (pulsesrc); pa_threaded_mainloop_unlock (pulsesrc->mainloop); fail: return FALSE; } }
static GstCaps * gst_flite_test_src_fixate (GstBaseSrc * bsrc, GstCaps * caps) { GstStructure *structure; gint channels; caps = gst_caps_truncate (caps); caps = gst_caps_make_writable (caps); structure = gst_caps_get_structure (caps, 0); gst_structure_fixate_field_nearest_int (structure, "channels", 2); gst_structure_get_int (structure, "channels", &channels); if (channels == 1) { gst_structure_remove_field (structure, "channel-mask"); } else { guint64 channel_mask = 0; gint x = 63; if (!gst_structure_get (structure, "channel-mask", GST_TYPE_BITMASK, &channel_mask, NULL)) { switch (channels) { case 8: channel_mask = GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_LEFT) | GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_RIGHT) | GST_AUDIO_CHANNEL_POSITION_MASK (REAR_LEFT) | GST_AUDIO_CHANNEL_POSITION_MASK (REAR_RIGHT) | GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_CENTER) | GST_AUDIO_CHANNEL_POSITION_MASK (LFE1) | GST_AUDIO_CHANNEL_POSITION_MASK (SIDE_LEFT) | GST_AUDIO_CHANNEL_POSITION_MASK (SIDE_RIGHT); break; case 7: channel_mask = GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_LEFT) | GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_RIGHT) | GST_AUDIO_CHANNEL_POSITION_MASK (REAR_LEFT) | GST_AUDIO_CHANNEL_POSITION_MASK (REAR_RIGHT) | GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_CENTER) | GST_AUDIO_CHANNEL_POSITION_MASK (LFE1) | GST_AUDIO_CHANNEL_POSITION_MASK (REAR_CENTER); break; case 6: channel_mask = GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_LEFT) | GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_RIGHT) | GST_AUDIO_CHANNEL_POSITION_MASK (REAR_LEFT) | GST_AUDIO_CHANNEL_POSITION_MASK (REAR_RIGHT) | GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_CENTER) | GST_AUDIO_CHANNEL_POSITION_MASK (LFE1); break; case 5: channel_mask = GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_LEFT) | GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_RIGHT) | GST_AUDIO_CHANNEL_POSITION_MASK (REAR_LEFT) | GST_AUDIO_CHANNEL_POSITION_MASK (REAR_RIGHT) | GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_CENTER); break; case 4: channel_mask = GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_LEFT) | GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_RIGHT) | GST_AUDIO_CHANNEL_POSITION_MASK (REAR_LEFT) | GST_AUDIO_CHANNEL_POSITION_MASK (REAR_RIGHT); break; case 3: channel_mask = GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_LEFT) | GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_RIGHT) | GST_AUDIO_CHANNEL_POSITION_MASK (LFE1); break; case 2: channel_mask = GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_LEFT) | GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_RIGHT); break; default: channel_mask = 0; break; } } while (n_bits_set (channel_mask) > channels) { channel_mask &= ~(G_GUINT64_CONSTANT (1) << x); x--; } gst_structure_set (structure, "channel-mask", GST_TYPE_BITMASK, channel_mask, NULL); } return GST_BASE_SRC_CLASS (parent_class)->fixate (bsrc, caps); }