summaryrefslogtreecommitdiffstats
path: root/audio/gstsbcparse.c
diff options
context:
space:
mode:
Diffstat (limited to 'audio/gstsbcparse.c')
-rw-r--r--audio/gstsbcparse.c186
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");