From f88c9d555516c7a4fde152827db2ddcc5c56ccf9 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Thu, 18 Oct 2007 21:46:49 +0000 Subject: [PATCH] sbc: Fixes for gstsbcenc. --- ext/sbc/gstsbcenc.c | 157 +++++++++++++++++++++++++++++++++++++---- ext/sbc/gstsbcenc.h | 5 ++ ext/sbc/gstsbcutil.c | 162 +++++++++++++++++++++++-------------------- 3 files changed, 235 insertions(+), 89 deletions(-) diff --git a/ext/sbc/gstsbcenc.c b/ext/sbc/gstsbcenc.c index c911eb5385..e6c4d1f1e9 100644 --- a/ext/sbc/gstsbcenc.c +++ b/ext/sbc/gstsbcenc.c @@ -28,6 +28,13 @@ #include #include "gstsbcenc.h" +#include "gstsbcutil.h" + + +#define SBC_ENC_DEFAULT_MODE CFG_MODE_AUTO +#define SBC_ENC_DEFAULT_BLOCKS 16 +#define SBC_ENC_DEFAULT_SUB_BANDS 8 +#define SBC_ENC_DEFAULT_ALLOCATION CFG_ALLOCATION_AUTO GST_DEBUG_CATEGORY_STATIC (sbc_enc_debug); #define GST_CAT_DEFAULT sbc_enc_debug @@ -53,10 +60,33 @@ gst_sbc_mode_get_type (void) return sbc_mode_type; } +#define GST_TYPE_SBC_ALLOCATION (gst_sbc_allocation_get_type()) + +static GType +gst_sbc_allocation_get_type (void) +{ + static GType sbc_allocation_type = 0; + static GEnumValue sbc_allocations[] = { + {CFG_ALLOCATION_AUTO, "Auto", "auto"}, + {CFG_ALLOCATION_LOUDNESS, "Loudness", "loudness"}, + {CFG_ALLOCATION_SNR, "SNR", "snr"}, + {-1, NULL, NULL} + }; + + if (!sbc_allocation_type) + sbc_allocation_type = + g_enum_register_static ("GstSbcAllocation", sbc_allocations); + + return sbc_allocation_type; +} + enum { PROP_0, PROP_MODE, + PROP_ALLOCATION, + PROP_BLOCKS, + PROP_SUB_BANDS }; GST_BOILERPLATE (GstSbcEnc, gst_sbc_enc, GstElement, GST_TYPE_ELEMENT); @@ -85,28 +115,83 @@ GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, "subbands = (int) { 4, 8 }, " "allocation = (string) { snr, loudness }")); + +static GstCaps * +sbc_enc_generate_srcpad_caps (GstSbcEnc * enc, GstCaps * caps) +{ + gint rate; + gint channels; + GstCaps *src_caps; + GstStructure *structure; + + structure = gst_caps_get_structure (caps, 0); + + if (!gst_structure_get_int (structure, "rate", &rate)) + return NULL; + if (!gst_structure_get_int (structure, "channels", &channels)) + return NULL; + + enc->sbc.rate = rate; + enc->sbc.channels = channels; + + if (enc->mode == 0) + enc->sbc.joint = CFG_MODE_JOINT_STEREO; + else + enc->sbc.joint = enc->mode; + + enc->sbc.blocks = enc->blocks; + enc->sbc.subbands = enc->subbands; + if (enc->allocation == 0) + enc->sbc.allocation = CFG_ALLOCATION_LOUDNESS; + else + enc->sbc.allocation = enc->allocation; + + src_caps = gst_caps_new_simple ("audio/x-sbc", "rate", G_TYPE_INT, + enc->sbc.rate, "channels", G_TYPE_INT, + enc->sbc.channels, "mode", G_TYPE_STRING, + gst_sbc_get_mode_string (enc->sbc.joint), "subbands", + G_TYPE_INT, enc->sbc.subbands, "blocks", G_TYPE_INT, + enc->sbc.blocks, "allocation", G_TYPE_STRING, + gst_sbc_get_allocation_string (enc->sbc.allocation), NULL); + + return src_caps; +} + +static gboolean +sbc_enc_sink_setcaps (GstPad * pad, GstCaps * caps) +{ + GstSbcEnc *enc; + GstStructure *structure; + GstCaps *othercaps; + + enc = GST_SBC_ENC (GST_PAD_PARENT (pad)); + structure = gst_caps_get_structure (caps, 0); + + othercaps = sbc_enc_generate_srcpad_caps (enc, caps); + if (othercaps == NULL) + goto error; + + gst_pad_set_caps (enc->srcpad, othercaps); + gst_caps_unref (othercaps); + + return TRUE; + +error: + GST_ERROR_OBJECT (enc, "invalid input caps"); + return FALSE; +} + static GstFlowReturn sbc_enc_chain (GstPad * pad, GstBuffer * buffer) { GstSbcEnc *enc = GST_SBC_ENC (gst_pad_get_parent (pad)); GstFlowReturn res = GST_FLOW_OK; - GstStructure *structure; - gint rate, channels; guint size, offset = 0; guint8 *data; data = GST_BUFFER_DATA (buffer); size = GST_BUFFER_SIZE (buffer); - structure = gst_caps_get_structure (GST_PAD_CAPS (pad), 0); - gst_structure_get_int (structure, "rate", &rate); - gst_structure_get_int (structure, "channels", &channels); - - enc->sbc.rate = rate; - enc->sbc.channels = channels; - enc->sbc.subbands = 8; - enc->sbc.joint = 0; - while (offset < size) { GstBuffer *output; GstCaps *caps; @@ -186,11 +271,23 @@ gst_sbc_enc_set_property (GObject * object, guint prop_id, { GstSbcEnc *enc = GST_SBC_ENC (object); + /* TODO - CAN ONLY BE CHANGED ON READY AND BELOW */ + switch (prop_id) { case PROP_MODE: enc->mode = g_value_get_enum (value); break; - + case PROP_ALLOCATION: + enc->allocation = g_value_get_enum (value); + break; + case PROP_BLOCKS: + /* TODO - verify consistency */ + enc->blocks = g_value_get_int (value); + break; + case PROP_SUB_BANDS: + /* TODO - verify consistency */ + enc->subbands = g_value_get_int (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -207,7 +304,15 @@ gst_sbc_enc_get_property (GObject * object, guint prop_id, case PROP_MODE: g_value_set_enum (value, enc->mode); break; - + case PROP_ALLOCATION: + g_value_set_enum (value, enc->allocation); + break; + case PROP_BLOCKS: + g_value_set_int (value, enc->blocks); + break; + case PROP_SUB_BANDS: + g_value_set_int (value, enc->subbands); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -228,8 +333,23 @@ gst_sbc_enc_class_init (GstSbcEncClass * klass) element_class->change_state = GST_DEBUG_FUNCPTR (sbc_enc_change_state); g_object_class_install_property (object_class, PROP_MODE, - g_param_spec_enum ("mode", "Mode", "Encoding mode", - GST_TYPE_SBC_MODE, 0, G_PARAM_READWRITE)); + g_param_spec_enum ("mode", "Mode", + "Encoding mode", GST_TYPE_SBC_MODE, + SBC_ENC_DEFAULT_MODE, G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_ALLOCATION, + g_param_spec_enum ("allocation", "Allocation", + "Allocation mode", GST_TYPE_SBC_ALLOCATION, + SBC_ENC_DEFAULT_ALLOCATION, G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_BLOCKS, + g_param_spec_int ("blocks", "Blocks", + "Blocks", 0, G_MAXINT, SBC_ENC_DEFAULT_BLOCKS, G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_SUB_BANDS, + g_param_spec_int ("subbands", "Sub Bands", + "Sub Bands", 0, G_MAXINT, + SBC_ENC_DEFAULT_SUB_BANDS, G_PARAM_READWRITE)); GST_DEBUG_CATEGORY_INIT (sbc_enc_debug, "sbcenc", 0, "SBC encoding element"); } @@ -239,9 +359,16 @@ gst_sbc_enc_init (GstSbcEnc * self, GstSbcEncClass * klass) { self->sinkpad = gst_pad_new_from_static_template (&sbc_enc_sink_factory, "sink"); + gst_pad_set_setcaps_function (self->sinkpad, + GST_DEBUG_FUNCPTR (sbc_enc_sink_setcaps)); gst_element_add_pad (GST_ELEMENT (self), self->sinkpad); self->srcpad = gst_pad_new_from_static_template (&sbc_enc_src_factory, "src"); gst_pad_set_chain_function (self->sinkpad, GST_DEBUG_FUNCPTR (sbc_enc_chain)); gst_element_add_pad (GST_ELEMENT (self), self->srcpad); + + self->subbands = SBC_ENC_DEFAULT_SUB_BANDS; + self->blocks = SBC_ENC_DEFAULT_BLOCKS; + self->mode = SBC_ENC_DEFAULT_MODE; + self->allocation = SBC_ENC_DEFAULT_ALLOCATION; } diff --git a/ext/sbc/gstsbcenc.h b/ext/sbc/gstsbcenc.h index e7daf2d3af..0a95bcef2c 100644 --- a/ext/sbc/gstsbcenc.h +++ b/ext/sbc/gstsbcenc.h @@ -24,6 +24,8 @@ #include #include "sbc.h" +#include "ipc.h" + G_BEGIN_DECLS @@ -48,6 +50,9 @@ struct _GstSbcEnc { GstPad *srcpad; gint mode; + gint blocks; + gint allocation; + gint subbands; sbc_t sbc; }; diff --git a/ext/sbc/gstsbcutil.c b/ext/sbc/gstsbcutil.c index 706e7f5487..b0175b433d 100644 --- a/ext/sbc/gstsbcutil.c +++ b/ext/sbc/gstsbcutil.c @@ -32,154 +32,168 @@ * Selects one rate from a list of possible rates * TODO - use a better approach to this (it is selecting the last element) */ -gint gst_sbc_select_rate_from_list(const GValue *value) +gint +gst_sbc_select_rate_from_list (const GValue * value) { - guint size = gst_value_list_get_size(value); - return g_value_get_int(gst_value_list_get_value(value, size-1)); + guint size = gst_value_list_get_size (value); + return g_value_get_int (gst_value_list_get_value (value, size - 1)); } /* * Selects one rate from a range of possible rates * TODO - use a better approach to this (it is selecting the maximum value) */ -gint gst_sbc_select_rate_from_range(const GValue *value) +gint +gst_sbc_select_rate_from_range (const GValue * value) { - return gst_value_get_int_range_max(value); + return gst_value_get_int_range_max (value); } /* * Selects one number of channels from a list of possible numbers * TODO - use a better approach to this (it is selecting the last element) */ -gint gst_sbc_select_channels_from_list(const GValue *value) +gint +gst_sbc_select_channels_from_list (const GValue * value) { - guint size = gst_value_list_get_size(value); - return g_value_get_int(gst_value_list_get_value(value, size-1)); + guint size = gst_value_list_get_size (value); + return g_value_get_int (gst_value_list_get_value (value, size - 1)); } /* * Selects one number of channels option from a range of possible numbers * TODO - use a better approach to this (it is selecting the maximum value) */ -gint gst_sbc_select_channels_from_range(const GValue *value) +gint +gst_sbc_select_channels_from_range (const GValue * value) { - return gst_value_get_int_range_max(value); + return gst_value_get_int_range_max (value); } /* * Selects one number of blocks from a list of possible blocks * TODO - use a better approach to this (it is selecting the last element) */ -gint gst_sbc_select_blocks_from_list(const GValue *value) +gint +gst_sbc_select_blocks_from_list (const GValue * value) { - guint size = gst_value_list_get_size(value); - return g_value_get_int(gst_value_list_get_value(value, size-1)); + guint size = gst_value_list_get_size (value); + return g_value_get_int (gst_value_list_get_value (value, size - 1)); } /* * Selects one blocks option from a range of possible blocks * TODO - use a better approach to this (it is selecting the maximum value) */ -gint gst_sbc_select_blocks_from_range(const GValue *value) +gint +gst_sbc_select_blocks_from_range (const GValue * value) { - return gst_value_get_int_range_max(value); + return gst_value_get_int_range_max (value); } /* * Selects one number of subbands from a list * TODO - use a better approach to this (it is selecting the last element) */ -gint gst_sbc_select_subbands_from_list(const GValue *value) +gint +gst_sbc_select_subbands_from_list (const GValue * value) { - guint size = gst_value_list_get_size(value); - return g_value_get_int(gst_value_list_get_value(value, size-1)); + guint size = gst_value_list_get_size (value); + return g_value_get_int (gst_value_list_get_value (value, size - 1)); } /* * Selects one subbands option from a range * TODO - use a better approach to this (it is selecting the maximum value) */ -gint gst_sbc_select_subbands_from_range(const GValue *value) +gint +gst_sbc_select_subbands_from_range (const GValue * value) { - return gst_value_get_int_range_max(value); + return gst_value_get_int_range_max (value); } /* * Selects one allocation mode from the ones on the list * TODO - use a better approach */ -const gchar* gst_sbc_get_allocation_from_list(const GValue *value) +const gchar * +gst_sbc_get_allocation_from_list (const GValue * value) { - guint size = gst_value_list_get_size(value); - return g_value_get_string(gst_value_list_get_value(value, size-1)); + guint size = gst_value_list_get_size (value); + return g_value_get_string (gst_value_list_get_value (value, size - 1)); } /* * Selects one mode from the ones on the list * TODO - use a better aproach */ -const gchar* gst_sbc_get_mode_from_list(const GValue *value) +const gchar * +gst_sbc_get_mode_from_list (const GValue * value) { - guint size = gst_value_list_get_size(value); - return g_value_get_string(gst_value_list_get_value(value, size-1)); + guint size = gst_value_list_get_size (value); + return g_value_get_string (gst_value_list_get_value (value, size - 1)); } -gint gst_sbc_get_allocation_mode_int(const gchar* allocation) +gint +gst_sbc_get_allocation_mode_int (const gchar * allocation) { - if (g_ascii_strcasecmp(allocation, "loudness") == 0) - return CFG_ALLOCATION_LOUDNESS; - else if (g_ascii_strcasecmp(allocation, "snr") == 0) - return CFG_ALLOCATION_SNR; - else if (g_ascii_strcasecmp(allocation, "auto") == 0) - return CFG_ALLOCATION_AUTO; - else - return -1; + if (g_ascii_strcasecmp (allocation, "loudness") == 0) + return CFG_ALLOCATION_LOUDNESS; + else if (g_ascii_strcasecmp (allocation, "snr") == 0) + return CFG_ALLOCATION_SNR; + else if (g_ascii_strcasecmp (allocation, "auto") == 0) + return CFG_ALLOCATION_AUTO; + else + return -1; } -gint gst_sbc_get_mode_int(const gchar* mode) +gint +gst_sbc_get_mode_int (const gchar * mode) { - if (g_ascii_strcasecmp(mode, "joint") == 0) - return CFG_MODE_JOINT_STEREO; - else if (g_ascii_strcasecmp(mode, "stereo") == 0) - return CFG_MODE_STEREO; - else if (g_ascii_strcasecmp(mode, "dual") == 0) - return CFG_MODE_DUAL_CHANNEL; - else if (g_ascii_strcasecmp(mode, "mono") == 0) - return CFG_MODE_MONO; - else if (g_ascii_strcasecmp(mode, "auto") == 0) - return CFG_MODE_AUTO; - else - return -1; + if (g_ascii_strcasecmp (mode, "joint") == 0) + return CFG_MODE_JOINT_STEREO; + else if (g_ascii_strcasecmp (mode, "stereo") == 0) + return CFG_MODE_STEREO; + else if (g_ascii_strcasecmp (mode, "dual") == 0) + return CFG_MODE_DUAL_CHANNEL; + else if (g_ascii_strcasecmp (mode, "mono") == 0) + return CFG_MODE_MONO; + else if (g_ascii_strcasecmp (mode, "auto") == 0) + return CFG_MODE_AUTO; + else + return -1; } -const gchar* gst_sbc_get_mode_string(int joint) +const gchar * +gst_sbc_get_mode_string (int joint) { - switch (joint) { - case CFG_MODE_MONO: - return "mono"; - case CFG_MODE_DUAL_CHANNEL: - return "dual"; - case CFG_MODE_STEREO: - return "stereo"; - case CFG_MODE_JOINT_STEREO: - return "joint"; - case CFG_MODE_AUTO: - return NULL; /* TODO what should be selected here? */ - default: - return NULL; - } + switch (joint) { + case CFG_MODE_MONO: + return "mono"; + case CFG_MODE_DUAL_CHANNEL: + return "dual"; + case CFG_MODE_STEREO: + return "stereo"; + case CFG_MODE_JOINT_STEREO: + return "joint"; + case CFG_MODE_AUTO: + return NULL; /* TODO what should be selected here? */ + default: + return NULL; + } } -const gchar* gst_sbc_get_allocation_string(int alloc) +const gchar * +gst_sbc_get_allocation_string (int alloc) { - switch (alloc) { - case CFG_ALLOCATION_LOUDNESS: - return "loudness"; - case CFG_ALLOCATION_SNR: - return "snr"; - case CFG_ALLOCATION_AUTO: - return NULL; /* TODO what should be selected here? */ - default: - return NULL; - } + switch (alloc) { + case CFG_ALLOCATION_LOUDNESS: + return "loudness"; + case CFG_ALLOCATION_SNR: + return "snr"; + case CFG_ALLOCATION_AUTO: + return NULL; /* TODO what should be selected here? */ + default: + return NULL; + } }