static void gst_deinterleave_set_pads_caps (GstDeinterleave * self, GstCaps * caps) { GList *l; GstStructure *s; gint i; for (l = self->srcpads, i = 0; l; l = l->next, i++) { GstPad *pad = GST_PAD (l->data); GstCaps *srccaps; /* Set channel position if we know it */ if (self->keep_positions) { GstAudioChannelPosition pos[1] = { GST_AUDIO_CHANNEL_POSITION_NONE }; srccaps = gst_caps_copy (caps); s = gst_caps_get_structure (srccaps, 0); if (self->pos) gst_audio_set_channel_positions (s, &self->pos[i]); else gst_audio_set_channel_positions (s, pos); } else { srccaps = caps; } gst_pad_set_caps (pad, srccaps); if (self->keep_positions) gst_caps_unref (srccaps); } }
static gboolean gst_a52dec_reneg (GstA52Dec * a52dec, GstPad * pad) { GstAudioChannelPosition *pos; gint channels = gst_a52dec_channels (a52dec->using_channels, &pos); GstCaps *caps = NULL; gboolean result = FALSE; if (!channels) goto done; GST_INFO_OBJECT (a52dec, "reneg channels:%d rate:%d", channels, a52dec->sample_rate); caps = gst_caps_new_simple ("audio/x-raw-float", "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, SAMPLE_WIDTH, "channels", G_TYPE_INT, channels, "rate", G_TYPE_INT, a52dec->sample_rate, NULL); gst_audio_set_channel_positions (gst_caps_get_structure (caps, 0), pos); g_free (pos); if (!gst_pad_set_caps (pad, caps)) goto done; result = TRUE; done: if (caps) gst_caps_unref (caps); return result; }
gint main (gint argc, gchar * argv[]) { gchar *str; GstCaps *caps; GstAudioChannelPosition pos[2] = { GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT }; /* register multichannel type */ gst_init (&argc, &argv); gst_audio_channel_position_get_type (); /* test some caps-string conversions */ caps = gst_caps_new_simple ("audio/x-raw-int", "channels", G_TYPE_INT, 2, NULL); str = gst_caps_to_string (caps); g_print ("Test caps #1: %s\n", str); g_free (str); gst_audio_set_channel_positions (gst_caps_get_structure (caps, 0), pos); str = gst_caps_to_string (caps); g_print ("Test caps #2: %s\n", str); g_free (str); gst_caps_unref (caps); return 0; }
static gboolean gst_dtsdec_renegotiate (GstDtsDec * dts) { GstAudioChannelPosition *pos; GstCaps *caps = gst_caps_from_string (DTS_CAPS); gint channels = gst_dtsdec_channels (dts->using_channels, &pos); gboolean result = FALSE; if (!channels) goto done; GST_INFO ("dtsdec renegotiate, channels=%d, rate=%d", channels, dts->sample_rate); gst_caps_set_simple (caps, "channels", G_TYPE_INT, channels, "rate", G_TYPE_INT, (gint) dts->sample_rate, NULL); gst_audio_set_channel_positions (gst_caps_get_structure (caps, 0), pos); g_free (pos); if (!gst_pad_set_caps (dts->srcpad, caps)) goto done; result = TRUE; done: if (caps) { gst_caps_unref (caps); } return result; }
/* if channels are less than or equal to 8, we set a default layout, * otherwise set layout to an array of GST_AUDIO_CHANNEL_POSITION_NONE */ void gst_jack_set_layout_on_caps (GstCaps ** caps, gint channels) { int c; GValue pos = { 0 }; GValue chanpos = { 0 }; gst_caps_unref (*caps); if (channels <= 8) { g_assert (channels >= 1); gst_audio_set_channel_positions (gst_caps_get_structure (*caps, 0), default_positions[channels - 1]); } else { g_value_init (&chanpos, GST_TYPE_ARRAY); g_value_init (&pos, GST_TYPE_AUDIO_CHANNEL_POSITION); for (c = 0; c < channels; c++) { g_value_set_enum (&pos, GST_AUDIO_CHANNEL_POSITION_NONE); gst_value_array_append_value (&chanpos, &pos); } g_value_unset (&pos); gst_structure_set_value (gst_caps_get_structure (*caps, 0), "channel-positions", &chanpos); g_value_unset (&chanpos); } gst_caps_ref (*caps); }
static void sink_handoff_float32 (GstElement * element, GstBuffer * buffer, GstPad * pad, gpointer user_data) { gint i; gfloat *data; GstCaps *caps; gint n = GPOINTER_TO_INT (user_data); fail_unless (GST_IS_BUFFER (buffer)); fail_unless_equals_int (GST_BUFFER_SIZE (buffer), 48000 * 2 * sizeof (gfloat)); fail_unless_equals_int (GST_BUFFER_DURATION (buffer), GST_SECOND); caps = gst_caps_new_simple ("audio/x-raw-float", "width", G_TYPE_INT, 32, "channels", G_TYPE_INT, 2, "rate", G_TYPE_INT, 48000, "endianness", G_TYPE_INT, G_BYTE_ORDER, NULL); if (n == 0) { GstAudioChannelPosition pos[2] = { GST_AUDIO_CHANNEL_POSITION_NONE, GST_AUDIO_CHANNEL_POSITION_NONE }; gst_audio_set_channel_positions (gst_caps_get_structure (caps, 0), pos); } else if (n == 1) { GstAudioChannelPosition pos[2] = { GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT }; gst_audio_set_channel_positions (gst_caps_get_structure (caps, 0), pos); } else if (n == 2) { GstAudioChannelPosition pos[2] = { GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, GST_AUDIO_CHANNEL_POSITION_REAR_CENTER }; gst_audio_set_channel_positions (gst_caps_get_structure (caps, 0), pos); } fail_unless (gst_caps_is_equal (caps, GST_BUFFER_CAPS (buffer))); gst_caps_unref (caps); data = (gfloat *) GST_BUFFER_DATA (buffer); 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); } have_data++; }
static void gst_deinterleave_add_new_pads (GstDeinterleave * self, GstCaps * caps) { GstPad *pad; guint i; for (i = 0; i < self->channels; i++) { gchar *name = g_strdup_printf ("src%d", i); GstCaps *srccaps; GstStructure *s; pad = gst_pad_new_from_static_template (&src_template, name); g_free (name); /* Set channel position if we know it */ if (self->keep_positions) { GstAudioChannelPosition pos[1] = { GST_AUDIO_CHANNEL_POSITION_NONE }; srccaps = gst_caps_copy (caps); s = gst_caps_get_structure (srccaps, 0); if (self->pos) gst_audio_set_channel_positions (s, &self->pos[i]); else gst_audio_set_channel_positions (s, pos); } else { srccaps = caps; } gst_pad_set_caps (pad, srccaps); gst_pad_use_fixed_caps (pad); gst_pad_set_query_function (pad, GST_DEBUG_FUNCPTR (gst_deinterleave_src_query)); gst_pad_set_active (pad, TRUE); gst_element_add_pad (GST_ELEMENT (self), pad); self->srcpads = g_list_prepend (self->srcpads, gst_object_ref (pad)); if (self->keep_positions) gst_caps_unref (srccaps); } gst_element_no_more_pads (GST_ELEMENT (self)); self->srcpads = g_list_reverse (self->srcpads); }
static void src_handoff_float32 (GstElement * element, GstBuffer * buffer, GstPad * pad, gpointer user_data) { gint n = GPOINTER_TO_INT (user_data); GstCaps *caps; gfloat *data; gint i; if (GST_PAD_CAPS (pad)) caps = gst_caps_ref (GST_PAD_CAPS (pad)); else { caps = gst_caps_new_simple ("audio/x-raw-float", "width", G_TYPE_INT, 32, "channels", G_TYPE_INT, 1, "rate", G_TYPE_INT, 48000, "endianness", G_TYPE_INT, G_BYTE_ORDER, NULL); if (n == 2) { GstAudioChannelPosition pos[1] = { GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT }; gst_audio_set_channel_positions (gst_caps_get_structure (caps, 0), pos); } else if (n == 3) { GstAudioChannelPosition pos[1] = { GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT }; gst_audio_set_channel_positions (gst_caps_get_structure (caps, 0), pos); } } data = g_new (gfloat, 48000); GST_BUFFER_MALLOCDATA (buffer) = (guint8 *) data; GST_BUFFER_DATA (buffer) = (guint8 *) data; GST_BUFFER_SIZE (buffer) = 48000 * sizeof (gfloat); GST_BUFFER_OFFSET (buffer) = GST_BUFFER_OFFSET_NONE; GST_BUFFER_TIMESTAMP (buffer) = GST_CLOCK_TIME_NONE; GST_BUFFER_OFFSET_END (buffer) = GST_BUFFER_OFFSET_NONE; GST_BUFFER_DURATION (buffer) = GST_SECOND; GST_BUFFER_CAPS (buffer) = caps; for (i = 0; i < 48000; i++) data[i] = (n % 2 == 0) ? -1.0 : 1.0; }
static gboolean gst_wavpack_dec_sink_set_caps (GstPad * pad, GstCaps * caps) { GstWavpackDec *dec = GST_WAVPACK_DEC (gst_pad_get_parent (pad)); GstStructure *structure = gst_caps_get_structure (caps, 0); /* Check if we can set the caps here already */ if (gst_structure_get_int (structure, "channels", &dec->channels) && gst_structure_get_int (structure, "rate", &dec->sample_rate) && gst_structure_get_int (structure, "width", &dec->depth)) { GstCaps *caps; GstAudioChannelPosition *pos; caps = gst_caps_new_simple ("audio/x-raw-int", "rate", G_TYPE_INT, dec->sample_rate, "channels", G_TYPE_INT, dec->channels, "depth", G_TYPE_INT, dec->depth, "width", G_TYPE_INT, 32, "endianness", G_TYPE_INT, G_BYTE_ORDER, "signed", G_TYPE_BOOLEAN, TRUE, NULL); /* If we already have the channel layout set from upstream * take this */ if (gst_structure_has_field (structure, "channel-positions")) { pos = gst_audio_get_channel_positions (structure); if (pos != NULL && dec->channels > 2) { GstStructure *new_str = gst_caps_get_structure (caps, 0); gst_audio_set_channel_positions (new_str, pos); dec->channel_mask = gst_wavpack_get_channel_mask_from_positions (pos, dec->channels); } if (pos != NULL) g_free (pos); } GST_DEBUG_OBJECT (dec, "setting caps %" GST_PTR_FORMAT, caps); /* should always succeed */ gst_pad_set_caps (dec->srcpad, caps); gst_caps_unref (caps); /* send GST_TAG_AUDIO_CODEC and GST_TAG_BITRATE tags before something * is decoded or after the format has changed */ gst_wavpack_dec_post_tags (dec); } gst_object_unref (dec); return TRUE; }
static gboolean gst_dvdlpcmdec_set_outcaps (GstDvdLpcmDec * dvdlpcmdec) { gboolean res = TRUE; GstCaps *src_caps; GstAudioChannelPosition *pos; /* Build caps to set on the src pad, which we know from the incoming caps */ src_caps = gst_caps_new_simple ("audio/x-raw-int", "rate", G_TYPE_INT, dvdlpcmdec->rate, "channels", G_TYPE_INT, dvdlpcmdec->channels, "endianness", G_TYPE_INT, G_BIG_ENDIAN, "depth", G_TYPE_INT, dvdlpcmdec->out_width, "width", G_TYPE_INT, dvdlpcmdec->out_width, "signed", G_TYPE_BOOLEAN, TRUE, NULL); pos = get_audio_channel_positions (dvdlpcmdec); if (pos) { gst_audio_set_channel_positions (gst_caps_get_structure (src_caps, 0), pos); g_free (pos); } GST_DEBUG_OBJECT (dvdlpcmdec, "Set rate %d, channels %d, width %d (out %d)", dvdlpcmdec->rate, dvdlpcmdec->channels, dvdlpcmdec->width, dvdlpcmdec->out_width); res = gst_pad_set_caps (dvdlpcmdec->srcpad, src_caps); if (res) { GST_DEBUG_OBJECT (dvdlpcmdec, "Successfully set output caps: %" GST_PTR_FORMAT, src_caps); gst_dvdlpcmdec_send_tags (dvdlpcmdec); } else { GST_DEBUG_OBJECT (dvdlpcmdec, "Failed to set output caps: %" GST_PTR_FORMAT, src_caps); } gst_caps_unref (src_caps); return res; }
GstRingBufferSpec * gst_pulse_channel_map_to_gst (const pa_channel_map * map, GstRingBufferSpec * spec) { int i; GstAudioChannelPosition *pos; gboolean invalid = FALSE; g_return_val_if_fail (map->channels == spec->channels, NULL); pos = g_new0 (GstAudioChannelPosition, spec->channels + 1); for (i = 0; i < spec->channels; i++) { if (map->map[i] == PA_CHANNEL_POSITION_INVALID) { invalid = TRUE; break; } else if ((int) map->map[i] < (int) GST_AUDIO_CHANNEL_POSITION_NUM) { pos[i] = pa_to_gst_pos[map->map[i] + 1]; } else { invalid = TRUE; break; } } if (!invalid && !gst_audio_check_channel_positions (pos, spec->channels)) invalid = TRUE; if (invalid) { for (i = 0; i < spec->channels; i++) pos[i] = GST_AUDIO_CHANNEL_POSITION_NONE; } gst_audio_set_channel_positions (gst_caps_get_structure (spec->caps, 0), pos); g_free (pos); return spec; }
static GstFlowReturn vorbis_handle_identification_packet (GstVorbisDec * vd) { GstCaps *caps; const GstAudioChannelPosition *pos = NULL; gint width = GST_VORBIS_DEC_DEFAULT_SAMPLE_WIDTH; switch (vd->vi.channels) { case 1: case 2: /* nothing */ break; case 3: case 4: case 5: case 6: case 7: case 8: pos = gst_vorbis_channel_positions[vd->vi.channels - 1]; break; default:{ gint i; GstAudioChannelPosition *posn = g_new (GstAudioChannelPosition, vd->vi.channels); GST_ELEMENT_WARNING (GST_ELEMENT (vd), STREAM, DECODE, (NULL), ("Using NONE channel layout for more than 8 channels")); for (i = 0; i < vd->vi.channels; i++) posn[i] = GST_AUDIO_CHANNEL_POSITION_NONE; pos = posn; } } /* negotiate width with downstream */ caps = gst_pad_get_allowed_caps (vd->srcpad); if (caps) { if (!gst_caps_is_empty (caps)) { GstStructure *s; s = gst_caps_get_structure (caps, 0); /* template ensures 16 or 32 */ gst_structure_get_int (s, "width", &width); GST_INFO_OBJECT (vd, "using %s with %d channels and %d bit audio depth", gst_structure_get_name (s), vd->vi.channels, width); } gst_caps_unref (caps); } vd->width = width >> 3; /* select a copy_samples function, this way we can have specialized versions * for mono/stereo and avoid the depth switch in tremor case */ vd->copy_samples = get_copy_sample_func (vd->vi.channels, vd->width); caps = gst_caps_copy (gst_pad_get_pad_template_caps (vd->srcpad)); gst_caps_set_simple (caps, "rate", G_TYPE_INT, vd->vi.rate, "channels", G_TYPE_INT, vd->vi.channels, "width", G_TYPE_INT, width, NULL); if (pos) { gst_audio_set_channel_positions (gst_caps_get_structure (caps, 0), pos); } if (vd->vi.channels > 8) { g_free ((GstAudioChannelPosition *) pos); } gst_pad_set_caps (vd->srcpad, caps); gst_caps_unref (caps); return GST_FLOW_OK; }
static gboolean gst_rtp_g722_depay_setcaps (GstBaseRTPDepayload * depayload, GstCaps * caps) { GstStructure *structure; GstRtpG722Depay *rtpg722depay; gint clock_rate, payload, samplerate; gint channels; GstCaps *srccaps; gboolean res; const gchar *channel_order; const GstRTPChannelOrder *order; rtpg722depay = GST_RTP_G722_DEPAY (depayload); structure = gst_caps_get_structure (caps, 0); payload = 96; gst_structure_get_int (structure, "payload", &payload); switch (payload) { case GST_RTP_PAYLOAD_G722: channels = 1; clock_rate = 8000; samplerate = 16000; break; default: /* no fixed mapping, we need clock-rate */ channels = 0; clock_rate = 0; samplerate = 0; break; } /* caps can overwrite defaults */ clock_rate = gst_rtp_g722_depay_parse_int (structure, "clock-rate", clock_rate); if (clock_rate == 0) goto no_clockrate; if (clock_rate == 8000) samplerate = 16000; if (samplerate == 0) samplerate = clock_rate; channels = gst_rtp_g722_depay_parse_int (structure, "encoding-params", channels); if (channels == 0) { channels = gst_rtp_g722_depay_parse_int (structure, "channels", channels); if (channels == 0) { /* channels defaults to 1 otherwise */ channels = 1; } } depayload->clock_rate = clock_rate; rtpg722depay->rate = samplerate; rtpg722depay->channels = channels; srccaps = gst_caps_new_simple ("audio/G722", "rate", G_TYPE_INT, samplerate, "channels", G_TYPE_INT, channels, NULL); /* add channel positions */ channel_order = gst_structure_get_string (structure, "channel-order"); order = gst_rtp_channels_get_by_order (channels, channel_order); if (order) { gst_audio_set_channel_positions (gst_caps_get_structure (srccaps, 0), order->pos); } else { GstAudioChannelPosition *pos; GST_ELEMENT_WARNING (rtpg722depay, STREAM, DECODE, (NULL), ("Unknown channel order '%s' for %d channels", GST_STR_NULL (channel_order), channels)); /* create default NONE layout */ pos = gst_rtp_channels_create_default (channels); gst_audio_set_channel_positions (gst_caps_get_structure (srccaps, 0), pos); g_free (pos); } res = gst_pad_set_caps (depayload->srcpad, srccaps); gst_caps_unref (srccaps); return res; /* ERRORS */ no_clockrate: { GST_ERROR_OBJECT (depayload, "no clock-rate specified"); return FALSE; } }
static gboolean gst_lv2_filter_setup (GstAudioFilter * gsp, const GstAudioInfo * info) { GstLV2Filter *self; GstLV2FilterClass *oclass; GstAudioFilterClass *audiofilter_class; gint i; audiofilter_class = GST_AUDIO_FILTER_GET_CLASS (gsp); self = (GstLV2Filter *) gsp; oclass = (GstLV2FilterClass *) audiofilter_class; g_return_val_if_fail (self->activated == FALSE, FALSE); GST_DEBUG_OBJECT (self, "instantiating the plugin at %d Hz", GST_AUDIO_INFO_RATE (info)); if (self->instance) lilv_instance_free (self->instance); if (!(self->instance = lilv_plugin_instantiate (oclass->plugin, GST_AUDIO_INFO_RATE (info), NULL))) goto no_instance; /* connect the control ports */ for (i = 0; i < oclass->control_in_ports->len; i++) lilv_instance_connect_port (self->instance, g_array_index (oclass->control_in_ports, GstLV2FilterPort, i).index, &(self->ports.control.in[i])); for (i = 0; i < oclass->control_out_ports->len; i++) lilv_instance_connect_port (self->instance, g_array_index (oclass->control_out_ports, GstLV2FilterPort, i).index, &(self->ports.control.out[i])); /* FIXME Handle audio channel positionning while negotiating CAPS */ #if 0 /* set input group pad audio channel position */ for (i = 0; i < oclass->in_groups->len; ++i) { group = &g_array_index (oclass->in_groups, GstLV2FilterGroup, i); if (group->has_roles) { if ((positions = gst_lv2_filter_build_positions (group))) { if ((pad = gst_element_get_static_pad (GST_ELEMENT (gsp), lilv_node_as_string (group->symbol)))) { GST_INFO_OBJECT (self, "set audio channel positions on sink pad %s", lilv_node_as_string (group->symbol)); s = gst_caps_get_structure (caps, 0); gst_audio_set_channel_positions (s, positions); gst_object_unref (pad); } g_free (positions); positions = NULL; } } } /* set output group pad audio channel position */ for (i = 0; i < oclass->out_groups->len; ++i) { group = &g_array_index (oclass->out_groups, GstLV2FilterGroup, i); if (group->has_roles) { if ((positions = gst_lv2_filter_build_positions (group))) { if ((pad = gst_element_get_static_pad (GST_ELEMENT (gsp), lilv_node_as_string (group->symbol)))) { GST_INFO_OBJECT (self, "set audio channel positions on src pad %s", lilv_node_as_string (group->symbol)); s = gst_caps_get_structure (caps, 0); gst_audio_set_channel_positions (s, positions); gst_object_unref (pad); } g_free (positions); positions = NULL; } } } #endif lilv_instance_activate (self->instance); self->activated = TRUE; return TRUE; no_instance: { GST_ERROR_OBJECT (gsp, "could not create instance"); return FALSE; } }
void test_multichannel_checks() { GstAudioChannelPosition pos_2_mixed[2] = { GST_AUDIO_CHANNEL_POSITION_FRONT_MONO, GST_AUDIO_CHANNEL_POSITION_NONE }; GstAudioChannelPosition pos_2_none[2] = { GST_AUDIO_CHANNEL_POSITION_NONE, GST_AUDIO_CHANNEL_POSITION_NONE }; GstAudioChannelPosition pos_2_flr[2] = { GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT }; GstAudioChannelPosition pos_2_frr[2] = { GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT }; GstStructure *s; xmlfile = "test_multichannel_checks"; std_log(LOG_FILENAME_LINE, "Test Started test_multichannel_checks"); s = gst_structure_new ("audio/x-raw-int", "channels", G_TYPE_INT, 2, NULL); /* this should not work and issue a warning: FRONT_MONO + NONE */ // _gst_check_expecting_log = TRUE; // gst_audio_set_channel_positions (s, pos_2_mixed); // _gst_check_expecting_log = FALSE; // fail_if (structure_contains_channel_positions (s)); /* this should work: NONE + NONE */ gst_audio_set_channel_positions (s, pos_2_none); fail_unless (structure_contains_channel_positions (s)); gst_structure_remove_field (s, "channel-positions"); /* this should also work: FRONT_LEFT + FRONT_RIGHT */ gst_audio_set_channel_positions (s, pos_2_flr); fail_unless (structure_contains_channel_positions (s)); gst_structure_remove_field (s, "channel-positions"); /* this should not work and issue a warning: FRONT_RIGHT twice */ // _gst_check_expecting_log = TRUE; // gst_audio_set_channel_positions (s, pos_2_frr); // _gst_check_expecting_log = FALSE; /* FIXME: did I misunderstand _set_structure_channel_positions_list? */ #if 0 /* this should not work and issue a warning: FRONT_RIGHT twice */ _gst_check_expecting_log = TRUE; gst_audio_set_structure_channel_positions_list (s, pos_2_frr, 2); _gst_check_expecting_log = FALSE; /* this should not work and issue a warning: FRONT_MONO + NONE */ _gst_check_expecting_log = TRUE; gst_audio_set_structure_channel_positions_list (s, pos_2_mixed, 2); _gst_check_expecting_log = FALSE; /* this should not work either (channel count mismatch) */ _gst_check_expecting_log = TRUE; gst_audio_set_structure_channel_positions_list (s, pos_2_none, 44); _gst_check_expecting_log = FALSE; fail_if (structure_contains_channel_positions (s)); #endif gst_structure_free (s); std_log(LOG_FILENAME_LINE, "Test Successful"); create_xml(0); }
static void caps_add_channel_configuration (GstCaps * caps, const GstStructure * in_structure, gint min_chans, gint max_chans) { GstAudioChannelPosition pos[8] = { 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_LFE, GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT, GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT }; GstStructure *s = NULL; gint c; if (min_chans == max_chans && max_chans <= 2) { s = get_channel_free_structure (in_structure); gst_structure_set (s, "channels", G_TYPE_INT, max_chans, NULL); gst_caps_append_structure (caps, s); return; } g_assert (min_chans >= 1); /* mono and stereo don't need channel configurations */ if (min_chans == 2) { s = get_channel_free_structure (in_structure); gst_structure_set (s, "channels", G_TYPE_INT, 2, NULL); gst_caps_append_structure (caps, s); } else if (min_chans == 1 && max_chans >= 2) { s = get_channel_free_structure (in_structure); gst_structure_set (s, "channels", GST_TYPE_INT_RANGE, 1, 2, NULL); gst_caps_append_structure (caps, s); } /* don't know whether to use 2.1 or 3.0 here - but I suspect * alsa might work around that/fix it somehow. Can we tell alsa * what our channel layout is like? */ if (max_chans >= 3 && min_chans <= 3) { GstAudioChannelPosition pos_21[3] = { GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_LFE }; s = get_channel_free_structure (in_structure); gst_structure_set (s, "channels", G_TYPE_INT, 3, NULL); gst_audio_set_channel_positions (s, pos_21); gst_caps_append_structure (caps, s); } /* everything else (4, 6, 8 channels) needs a channel layout */ for (c = MAX (4, min_chans); c <= 8; c += 2) { if (max_chans >= c) { s = get_channel_free_structure (in_structure); gst_structure_set (s, "channels", G_TYPE_INT, c, NULL); gst_audio_set_channel_positions (s, pos); gst_caps_append_structure (caps, s); } } for (c = MAX (9, min_chans); c <= max_chans; ++c) { GstAudioChannelPosition *ch_layout; guint i; ch_layout = g_new (GstAudioChannelPosition, c); for (i = 0; i < c; ++i) { ch_layout[i] = GST_AUDIO_CHANNEL_POSITION_NONE; } s = get_channel_free_structure (in_structure); gst_structure_set (s, "channels", G_TYPE_INT, c, NULL); gst_audio_set_channel_positions (s, ch_layout); gst_caps_append_structure (caps, s); g_free (ch_layout); } }
static gboolean dmo_audiodec_sink_setcaps (GstPad * pad, GstCaps * caps) { DMOAudioDec *dec = (DMOAudioDec *) gst_pad_get_parent (pad); DMOAudioDecClass *klass = (DMOAudioDecClass *) G_OBJECT_GET_CLASS (dec); GstStructure *s = gst_caps_get_structure (caps, 0); gchar *dll; gint size; WAVEFORMATEX * hdr = NULL; const GValue *v; GstBuffer *extradata = NULL; GstCaps *out; gboolean ret = FALSE; guint32 fourcc; GST_DEBUG_OBJECT (dec, "setcaps called with %" GST_PTR_FORMAT, caps); Check_FS_Segment (); if (dec->ctx) { DMO_AudioDecoder_Destroy (dec->ctx); dec->ctx = NULL; } /* read data */ if (!gst_structure_get_int (s, "bitrate", &dec->bitrate) || !gst_structure_get_int (s, "block_align", &dec->block_align) || !gst_structure_get_int (s, "rate", &dec->rate) || !gst_structure_get_int (s, "channels", &dec->channels) || !gst_structure_get_int (s, "depth", &dec->depth)) { goto beach; } if ((v = gst_structure_get_value (s, "codec_data"))) extradata = gst_value_get_buffer (v); if (!gst_structure_get_fourcc (s, "format", &fourcc)) fourcc = klass->entry->format; /* set up dll initialization */ dll = g_strdup_printf ("%s.dll", klass->entry->dll); size = sizeof (WAVEFORMATEX) + (extradata ? GST_BUFFER_SIZE (extradata) : 0); hdr = g_malloc0 (size); if (extradata) { /* Codec data is appended after our header */ memcpy (((guchar *) hdr) + sizeof (WAVEFORMATEX), GST_BUFFER_DATA (extradata), GST_BUFFER_SIZE (extradata)); hdr->cbSize = GST_BUFFER_SIZE (extradata); } hdr->wFormatTag = fourcc; hdr->nChannels = dec->channels; hdr->nSamplesPerSec = dec->rate; hdr->nAvgBytesPerSec = dec->bitrate / 8; hdr->nBlockAlign = dec->block_align; hdr->wBitsPerSample = dec->depth; GST_DEBUG ("Will now open %s using %d bps %d channels", dll, dec->bitrate, dec->channels); if (!(dec->ctx = DMO_AudioDecoder_Open (dll, &klass->entry->guid, hdr))) { GST_ERROR ("Failed to open DLL %s", dll); g_free (dll); g_free (hdr); goto beach; } g_free (dll); g_free (hdr); DMO_AudioDecoder_GetOutputInfos (dec->ctx, &dec->out_buffer_size, &dec->out_align); DMO_AudioDecoder_GetInputInfos (dec->ctx, &dec->in_buffer_size, &dec->in_align, &dec->lookahead); /* negotiate output */ out = gst_caps_from_string (klass->entry->srccaps); gst_caps_set_simple (out, "width", G_TYPE_INT, dec->depth, "depth", G_TYPE_INT, dec->depth, "rate", G_TYPE_INT, dec->rate, "channels", G_TYPE_INT, dec->channels, NULL); if (dec->channels > 2 && dec->channels <= 11) { GstAudioChannelPosition pos[] = { GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, GST_AUDIO_CHANNEL_POSITION_LFE, GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER, GST_AUDIO_CHANNEL_POSITION_REAR_CENTER, GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT, GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT }; gst_audio_set_channel_positions (gst_caps_get_structure (out, 0), pos); } if (!gst_pad_set_caps (dec->srcpad, out)) { gst_caps_unref (out); GST_ERROR ("Failed to negotiate output"); goto beach; } gst_caps_unref (out); ret = TRUE; beach: gst_object_unref (dec); return ret; }
static GstCaps * gst_openal_helper_probe_caps (ALCcontext * ctx) { static const struct { gint count; GstAudioChannelPosition pos[8]; } chans[] = { { 1, { GST_AUDIO_CHANNEL_POSITION_FRONT_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_LFE, 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_LFE, 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_LFE, 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; ALCcontext *old; GstCaps *caps; old = pushContext (ctx); 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 val = alGetEnumValue (fmt32[i]); if (checkALError () != AL_NO_ERROR || val == 0 || val == -1) continue; structure = gst_structure_new ("audio/x-raw-float", "endianness", G_TYPE_INT, G_BYTE_ORDER, "rate", GST_TYPE_INT_RANGE, OPENAL_MIN_RATE, OPENAL_MAX_RATE, "width", G_TYPE_INT, 32, NULL); gst_structure_set (structure, "channels", G_TYPE_INT, chans[i].count, NULL); if (chans[i].count > 2) gst_audio_set_channel_positions (structure, chans[i].pos); gst_caps_append_structure (caps, structure); } } for (i = 0; fmt16[i]; i++) { ALenum val = alGetEnumValue (fmt16[i]); if (checkALError () != AL_NO_ERROR || val == 0 || val == -1) continue; structure = gst_structure_new ("audio/x-raw-int", "endianness", G_TYPE_INT, G_BYTE_ORDER, "rate", GST_TYPE_INT_RANGE, OPENAL_MIN_RATE, OPENAL_MAX_RATE, "width", G_TYPE_INT, 16, "depth", G_TYPE_INT, 16, "signed", G_TYPE_BOOLEAN, TRUE, NULL); gst_structure_set (structure, "channels", G_TYPE_INT, chans[i].count, NULL); if (chans[i].count > 2) gst_audio_set_channel_positions (structure, chans[i].pos); gst_caps_append_structure (caps, structure); } for (i = 0; fmt8[i]; i++) { ALenum val = alGetEnumValue (fmt8[i]); if (checkALError () != AL_NO_ERROR || val == 0 || val == -1) continue; structure = gst_structure_new ("audio/x-raw-int", "rate", GST_TYPE_INT_RANGE, OPENAL_MIN_RATE, OPENAL_MAX_RATE, "width", G_TYPE_INT, 8, "depth", G_TYPE_INT, 8, "signed", G_TYPE_BOOLEAN, FALSE, NULL); gst_structure_set (structure, "channels", G_TYPE_INT, chans[i].count, NULL); if (chans[i].count > 2) gst_audio_set_channel_positions (structure, chans[i].pos); gst_caps_append_structure (caps, structure); } } else { if (alIsExtensionPresent ("AL_EXT_FLOAT32")) { structure = gst_structure_new ("audio/x-raw-float", "endianness", G_TYPE_INT, G_BYTE_ORDER, "rate", GST_TYPE_INT_RANGE, OPENAL_MIN_RATE, OPENAL_MAX_RATE, "width", G_TYPE_INT, 32, "channels", GST_TYPE_INT_RANGE, 1, 2, NULL); gst_caps_append_structure (caps, structure); } structure = gst_structure_new ("audio/x-raw-int", "endianness", G_TYPE_INT, G_BYTE_ORDER, "rate", GST_TYPE_INT_RANGE, OPENAL_MIN_RATE, OPENAL_MAX_RATE, "width", G_TYPE_INT, 16, "depth", G_TYPE_INT, 16, "signed", G_TYPE_BOOLEAN, TRUE, "channels", GST_TYPE_INT_RANGE, 1, 2, NULL); gst_caps_append_structure (caps, structure); structure = gst_structure_new ("audio/x-raw-int", "rate", GST_TYPE_INT_RANGE, OPENAL_MIN_RATE, OPENAL_MAX_RATE, "width", G_TYPE_INT, 8, "depth", G_TYPE_INT, 8, "signed", G_TYPE_BOOLEAN, FALSE, "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 val = alGetEnumValue (fmtmulaw[i]); if (checkALError () != AL_NO_ERROR || val == 0 || val == -1) continue; structure = gst_structure_new ("audio/x-mulaw", "rate", GST_TYPE_INT_RANGE, OPENAL_MIN_RATE, OPENAL_MAX_RATE, NULL); gst_structure_set (structure, "channels", G_TYPE_INT, chans[i].count, NULL); if (chans[i].count > 2) gst_audio_set_channel_positions (structure, chans[i].pos); 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, ctx); return caps; }
static GstFlowReturn gst_opus_dec_parse_header (GstOpusDec * dec, GstBuffer * buf) { const guint8 *data = GST_BUFFER_DATA (buf); GstCaps *caps; const GstAudioChannelPosition *pos = NULL; if (!gst_opus_header_is_id_header (buf)) { GST_ERROR_OBJECT (dec, "Header is not an Opus ID header"); return GST_FLOW_ERROR; } if (!(dec->n_channels == 0 || dec->n_channels == data[9])) { GST_ERROR_OBJECT (dec, "Opus ID header has invalid channels"); return GST_FLOW_ERROR; } dec->n_channels = data[9]; dec->pre_skip = GST_READ_UINT16_LE (data + 10); dec->r128_gain = GST_READ_UINT16_LE (data + 16); dec->r128_gain_volume = gst_opus_dec_get_r128_volume (dec->r128_gain); GST_INFO_OBJECT (dec, "Found pre-skip of %u samples, R128 gain %d (volume %f)", dec->pre_skip, dec->r128_gain, dec->r128_gain_volume); dec->channel_mapping_family = data[18]; if (dec->channel_mapping_family == 0) { /* implicit mapping */ GST_INFO_OBJECT (dec, "Channel mapping family 0, implicit mapping"); dec->n_streams = dec->n_stereo_streams = 1; dec->channel_mapping[0] = 0; dec->channel_mapping[1] = 1; } else { dec->n_streams = data[19]; dec->n_stereo_streams = data[20]; memcpy (dec->channel_mapping, data + 21, dec->n_channels); if (dec->channel_mapping_family == 1) { GST_INFO_OBJECT (dec, "Channel mapping family 1, Vorbis mapping"); switch (dec->n_channels) { case 1: case 2: /* nothing */ break; case 3: case 4: case 5: case 6: case 7: case 8: pos = gst_opus_channel_positions[dec->n_channels - 1]; break; default:{ gint i; GstAudioChannelPosition *posn = g_new (GstAudioChannelPosition, dec->n_channels); GST_ELEMENT_WARNING (GST_ELEMENT (dec), STREAM, DECODE, (NULL), ("Using NONE channel layout for more than 8 channels")); for (i = 0; i < dec->n_channels; i++) posn[i] = GST_AUDIO_CHANNEL_POSITION_NONE; pos = posn; } } } else { GST_INFO_OBJECT (dec, "Channel mapping family %d", dec->channel_mapping_family); } } caps = gst_opus_dec_negotiate (dec); if (pos) { GST_DEBUG_OBJECT (dec, "Setting channel positions on caps"); gst_audio_set_channel_positions (gst_caps_get_structure (caps, 0), pos); } if (dec->n_channels > 8) { g_free ((GstAudioChannelPosition *) pos); } GST_INFO_OBJECT (dec, "Setting src caps to %" GST_PTR_FORMAT, caps); gst_pad_set_caps (GST_AUDIO_DECODER_SRC_PAD (dec), caps); gst_caps_unref (caps); return GST_FLOW_OK; }