diff options
Diffstat (limited to 'audio/gstsbcparse.c')
-rw-r--r-- | audio/gstsbcparse.c | 186 |
1 files changed, 170 insertions, 16 deletions
diff --git a/audio/gstsbcparse.c b/audio/gstsbcparse.c index 5097a85f..e204870b 100644 --- a/audio/gstsbcparse.c +++ b/audio/gstsbcparse.c @@ -28,6 +28,7 @@ #include <string.h> #include "gstsbcparse.h" +#include "gstsbcutil.h" GST_DEBUG_CATEGORY_STATIC(sbc_parse_debug); #define GST_CAT_DEFAULT sbc_parse_debug @@ -54,6 +55,170 @@ static GstStaticPadTemplate sbc_parse_src_factory = "subbands = (int) { 4, 8 }, " "allocation = (string) { snr, loudness }")); +/* + Creates a fixed caps from the caps given. + +*/ +static GstCaps* sbc_parse_select_caps(GstSbcParse *parse, GstCaps *caps) +{ + GstCaps *result; + GstStructure *structure; + const GValue *value; + gboolean error = FALSE; + gint temp, rate, channels, blocks, subbands; + const gchar* allocation = NULL; + const gchar* mode = NULL; + const gchar* error_message = NULL; + + structure = gst_caps_get_structure(caps, 0); + + /* rate */ + if (!gst_structure_has_field(structure, "rate")) { + error = TRUE; + error_message = "no rate."; + goto error; + } else { + value = gst_structure_get_value(structure, "rate"); + if (GST_VALUE_HOLDS_LIST(value)) { + temp = gst_sbc_select_rate_from_list(value); + } else if (GST_VALUE_HOLDS_INT_RANGE(value)) { + temp = gst_sbc_select_rate_from_range(value); + } else { + temp = g_value_get_int(value); + } + rate = temp; + } + + /* channels */ + if (!gst_structure_has_field(structure, "channels")) { + error = TRUE; + error_message = "no channels."; + goto error; + } else { + value = gst_structure_get_value(structure, "channels"); + if (GST_VALUE_HOLDS_LIST(value)) { + temp = gst_sbc_select_channels_from_list(value); + } else if (GST_VALUE_HOLDS_INT_RANGE(value)) { + temp = gst_sbc_select_channels_from_range(value); + } else { + temp = g_value_get_int(value); + } + channels = temp; + } + + /* blocks */ + if (!gst_structure_has_field(structure, "blocks")) { + error = TRUE; + error_message = "no blocks."; + goto error; + } else { + value = gst_structure_get_value(structure, "blocks"); + if (GST_VALUE_HOLDS_LIST(value)) { + temp = gst_sbc_select_blocks_from_list(value); + } else if (GST_VALUE_HOLDS_INT_RANGE(value)) { + temp = gst_sbc_select_blocks_from_range(value); + } else { + temp = g_value_get_int(value); + } + blocks = temp; + } + + /* subbands */ + if (!gst_structure_has_field(structure, "subbands")) { + error = TRUE; + error_message = "no subbands."; + goto error; + } else { + value = gst_structure_get_value(structure, "subbands"); + if (GST_VALUE_HOLDS_LIST(value)) { + temp = gst_sbc_select_subbands_from_list(value); + } else if (GST_VALUE_HOLDS_INT_RANGE(value)) { + temp = gst_sbc_select_subbands_from_range(value); + } else { + temp = g_value_get_int(value); + } + subbands = temp; + } + + /* allocation */ + if (!gst_structure_has_field(structure, "allocation")) { + error = TRUE; + error_message = "no allocation."; + goto error; + } else { + value = gst_structure_get_value(structure, "allocation"); + if (GST_VALUE_HOLDS_LIST(value)) { + allocation = gst_sbc_get_allocation_from_list(value); + } else { + allocation = g_value_get_string(value); + } + } + + /* mode */ + if (!gst_structure_has_field(structure, "mode")) { + error = TRUE; + error_message = "no mode."; + goto error; + } else { + value = gst_structure_get_value(structure, "mode"); + if (GST_VALUE_HOLDS_LIST(value)) { + mode = gst_sbc_get_mode_from_list(value); + } else { + mode = g_value_get_string(value); + } + } + +error: + if (error) { + GST_ERROR_OBJECT (parse, "Invalid input caps: %s", + error_message); + return NULL; + } + + + result = gst_caps_new_simple("audio/x-sbc", + "rate", G_TYPE_INT, rate, + "channels", G_TYPE_INT, channels, + "mode", G_TYPE_STRING, mode, + "blocks", G_TYPE_INT, blocks, + "subbands", G_TYPE_INT, subbands, + "allocation", G_TYPE_STRING, allocation, + NULL); + parse->sbc.rate = rate; + parse->sbc.channels = channels; + parse->sbc.blocks = blocks; + parse->sbc.subbands = subbands; + parse->sbc.joint = gst_sbc_get_mode_int(mode); + parse->sbc.allocation = gst_sbc_get_allocation_mode_int(allocation); + + return result; +} + +static gboolean sbc_parse_sink_setcaps(GstPad * pad, GstCaps * caps) +{ + GstSbcParse *parse; + GstCaps *inter, *other, *srccaps; + + parse = GST_SBC_PARSE(GST_PAD_PARENT(pad)); + + other = gst_pad_peer_get_caps(parse->srcpad); + if (other == NULL) + other = gst_caps_new_any(); + + inter = gst_caps_intersect(caps, other); + srccaps = sbc_parse_select_caps(parse, inter); + if (srccaps == NULL) + return FALSE; + + gst_pad_set_caps(parse->srcpad, srccaps); + + gst_caps_unref(inter); + gst_caps_unref(other); + gst_caps_unref(srccaps); + + return TRUE; +} + static GstFlowReturn sbc_parse_chain(GstPad *pad, GstBuffer *buffer) { GstSbcParse *parse = GST_SBC_PARSE(gst_pad_get_parent(pad)); @@ -78,31 +243,20 @@ static GstFlowReturn sbc_parse_chain(GstPad *pad, GstBuffer *buffer) while (offset < size) { GstBuffer *output; - GstPadTemplate *template; - GstCaps *caps, *temp; + GstCaps *temp; int consumed; consumed = sbc_parse(&parse->sbc, data + offset, size - offset); if (consumed <= 0) break; - caps = gst_caps_new_simple("audio/x-sbc", - "rate", G_TYPE_INT, parse->sbc.rate, - "channels", G_TYPE_INT, parse->sbc.channels, - NULL); - template = gst_static_pad_template_get(&sbc_parse_src_factory); - - temp = gst_caps_intersect(caps, - gst_pad_template_get_caps(template)); - - gst_caps_unref(caps); + temp = GST_PAD_CAPS(parse->srcpad); res = gst_pad_alloc_buffer_and_set_caps(parse->srcpad, GST_BUFFER_OFFSET_NONE, consumed, temp, &output); - gst_caps_unref(temp); if (res != GST_FLOW_OK) goto done; @@ -141,7 +295,6 @@ static GstStateChangeReturn sbc_parse_change_state(GstElement *element, } sbc_init(&parse->sbc, 0); break; - case GST_STATE_CHANGE_PAUSED_TO_READY: GST_DEBUG("Finish subband codec"); if (parse->buffer) { @@ -150,7 +303,6 @@ static GstStateChangeReturn sbc_parse_change_state(GstElement *element, } sbc_finish(&parse->sbc); break; - default: break; } @@ -180,13 +332,15 @@ static void gst_sbc_parse_class_init(GstSbcParseClass *klass) element_class->change_state = GST_DEBUG_FUNCPTR(sbc_parse_change_state); GST_DEBUG_CATEGORY_INIT(sbc_parse_debug, "sbcparse", 0, - "SBC parsing element"); + "SBC parsing element"); } static void gst_sbc_parse_init(GstSbcParse *self, GstSbcParseClass *klass) { self->sinkpad = gst_pad_new_from_static_template(&sbc_parse_sink_factory, "sink"); gst_pad_set_chain_function(self->sinkpad, GST_DEBUG_FUNCPTR(sbc_parse_chain)); + gst_pad_set_setcaps_function (self->sinkpad, + GST_DEBUG_FUNCPTR (sbc_parse_sink_setcaps)); gst_element_add_pad(GST_ELEMENT(self), self->sinkpad); self->srcpad = gst_pad_new_from_static_template(&sbc_parse_src_factory, "src"); |