From 01b05306639f386efbf54467dc92af0fae20ecbf Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Thu, 18 Oct 2007 21:47:53 +0000 Subject: [PATCH] sbc: Fixes sbcparser element. --- ext/sbc/gstsbcparse.c | 182 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 169 insertions(+), 13 deletions(-) diff --git a/ext/sbc/gstsbcparse.c b/ext/sbc/gstsbcparse.c index f140dc5..f320962 100644 --- a/ext/sbc/gstsbcparse.c +++ b/ext/sbc/gstsbcparse.c @@ -28,6 +28,7 @@ #include #include "gstsbcparse.h" +#include "gstsbcutil.h" GST_DEBUG_CATEGORY_STATIC (sbc_parse_debug); #define GST_CAT_DEFAULT sbc_parse_debug @@ -54,6 +55,170 @@ GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, "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) { @@ -79,28 +244,19 @@ 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; @@ -138,7 +294,6 @@ sbc_parse_change_state (GstElement * element, GstStateChange transition) } sbc_init (&parse->sbc, 0); break; - case GST_STATE_CHANGE_PAUSED_TO_READY: GST_DEBUG ("Finish subband codec"); if (parse->buffer) { @@ -147,7 +302,6 @@ sbc_parse_change_state (GstElement * element, GstStateChange transition) } sbc_finish (&parse->sbc); break; - default: break; } @@ -189,6 +343,8 @@ gst_sbc_parse_init (GstSbcParse * self, GstSbcParseClass * klass) 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 = -- 2.7.4