diff -r 000000000000 -r 0e761a78d257 gst_plugins_symbian/gst/devsound/gstdevsoundsrc.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gst_plugins_symbian/gst/devsound/gstdevsoundsrc.c Thu Dec 17 08:53:32 2009 +0200 @@ -0,0 +1,1139 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000,2005 Wim Taymans + * + * gstdevsoundsrc.c: + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "common.h" +#include "gstdevsoundsrc.h" + +#include +#include "gstg711encoderinterface.h" +#include "gstspeechencoderconfig.h" +#include "gstg729encoderinterface.h" +#include "gstilbcencoderinterface.h" +#include "string.h" + +GST_DEBUG_CATEGORY_EXTERN (devsoundsrc_debug); +#define GST_CAT_DEFAULT devsoundsrc_debug + +/* elementfactory information */ +static const GstElementDetails gst_devsound_src_details= +GST_ELEMENT_DETAILS ("Audio Src (DEVSOUND)", + "Src/Audio", + "Record via Devsound", + " " +); + +static void gst_devsound_src_base_init(gpointer g_class); +static void gst_devsound_src_class_init(GstDevsoundSrcClass * klass); +static void gst_devsound_src_init(GstDevsoundSrc * devsoundsrc); + +static void gst_devsound_src_dispose(GObject * object); + +static void gst_devsound_src_get_property(GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); +static void gst_devsound_src_set_property(GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); + +static GstCaps *gst_devsound_src_getcaps(GstBaseSrc * bsrc); +static gboolean gst_devsound_src_setcaps(GstBaseSrc *bsrc, GstCaps *caps); + +static gboolean gst_devsound_src_start(GstBaseSrc * bsrc); +static gboolean gst_devsound_src_stop(GstBaseSrc * bsrc); +static gboolean gst_devsound_src_unlock(GstBaseSrc * bsrc); +static gboolean gst_devsound_src_unlock_stop(GstBaseSrc * bsrc); +static gboolean gst_devsound_src_is_seekable(GstBaseSrc * bsrc); +static gboolean gst_devsound_src_get_size(GstBaseSrc * src, guint64 * size); + +static GstFlowReturn gst_devsound_src_create(GstBaseSrc *src, guint64 offset, + guint size, GstBuffer **buf); +static void *StartDevSoundThread(void *threadid); + +/********************************* + * Speech Encoder Config Interface + * ******************************/ +static void gst_speech_encoder_config_handler_init(gpointer g_iface, + gpointer iface_data); +static gint gst_get_speech_encoder_bit_rate(guint* aBitrate); +static gint gst_get_speech_encoder_supported_bit_rates( + GList** aSupportedBitrates); +static gint gst_get_speech_encoder_vad_mode(gboolean* aVadMode); +static gint gst_set_speech_encoder_bit_rate(guint aBitrate); +static gint gst_set_speech_encoder_vad_mode(gboolean aVadMode); +static void gst_Apply_SpeechEncoder_Update(GstDevsoundSrc *devsoundsrc ); + + +/************************* + * G711 Encoder Interface + * ***********************/ +static void gst_g711_encoder_handler_init(gpointer g_iface, + gpointer iface_data); +static gint gst_get_g711_encoder_vad_mode(gboolean* aVadMode); +static gint gst_set_g711_encoder_mode(enum TG711EncodeMode aEncodeMode); +static gint gst_set_g711_vad_mode(gboolean aVadMode); +static void gst_Apply_G711Encoder_Update(GstDevsoundSrc *devsoundsrc ); + + +/************************* + * 729 Encoder Interface + * ***********************/ +static void gst_g729_encoder_handler_init(gpointer g_iface, + gpointer iface_data); +static gint gst_set_g729_vad_mode(TBool aVadMode); +static gint gst_get_g729_vad_mode(TBool* aVadMode); +static void gst_Apply_G729Encoder_Update(GstDevsoundSrc *devsoundsrc ); + + +/************************* + * ilbc Encoder Interface + * ***********************/ +static void gst_ilbc_encoder_handler_init(gpointer g_iface, + gpointer iface_data); +static gint gst_set_ilbc_encoder_mode(enum TIlbcEncodeMode aEncodeMode); +static gint gst_set_ilbc_vad_mode(gboolean aVadMode); +static gint gst_get_ilbc_vad_mode(gboolean* aVadMode); +static void gst_Apply_IlbcEncoder_Update(GstDevsoundSrc *devsoundsrc ); + + +static gint gst_devsound_src_get_rate(gint rate); + + +typedef struct _GstCustomIfaceUpdate GstCustomIfaceUpdate; + +struct _GstCustomIfaceUpdate{ +gboolean speechbitrateupdate; +gboolean speechvadmodeupdate; +gboolean g711encodermodeupdate; +gboolean g711vadmodeupdate; +gboolean g729vadmodeupdate; +gboolean ilbcencodermodeupdate; +gboolean ilbcvadmodeupdate; +}; +GstCustomIfaceUpdate customInfaceUpdate = {0,0,0,0,0,0,0}; + +guint speechbitrate; +gboolean speechvadmode; +enum TG711EncodeMode g711encodemode; +gboolean g711vadmode; +GList* supportedbitrates; +gint numofbitrates; +gboolean g729vadmode; +enum TIlbcEncodeMode ilbcencodemode; +gboolean ilbcvadmode; + +pthread_t ds_thread; +pthread_mutex_t create_mutex1; +pthread_cond_t create_condition1; + +enum consumer_thread_state_enum { + CONSUMER_THREAD_UNINITIALIZED, + CONSUMER_THREAD_INITIALIZING, + CONSUMER_THREAD_INITIALIZED +}; +enum consumer_thread_state_enum consumer_thread_state; + + + +GQueue* dataqueue= NULL; +GstBuffer* popBuffer= NULL; +int dataleft = 0; +int dataCopied = 0; + +enum command_to_consumer_thread_enum + { + OPEN = 2, + READDATA, + /*UPDATE,*/ + CLOSE + }; +enum command_to_consumer_thread_enum cmd; + +enum + { + LAST_SIGNAL + }; + +#define DEFAULT_DEVICE "default" + +enum + { + PROP_0, + PROP_DEVICE, + GAIN, + MAXGAIN, + CHANNELS, + LEFTBALANCE, + RIGHTBALANCE, + RATE, + PRIORITY, + PREFERENCE, + SAMPLESRECORDED + }; + +static GstStaticPadTemplate devsound_src_factory= + GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("audio/x-raw-int, " + "endianness = (int) { " G_STRINGIFY (G_BYTE_ORDER) " }, " + "signed = (boolean) TRUE, " + "width = (int) 16, " + "depth = (int) 16, " + "rate = (int) [ 8000, 48000 ]," + "channels = (int) [ 1, 2 ]; " + "audio/amr, " + "rate = (int) [ 8000, 48000 ], " + "channels = (int) [ 1, 2 ]; " + "audio/x-alaw, " + "rate = (int) [ 8000, 48000 ], " + "channels = (int) [ 1, 2 ]; " + "audio/g729, " + "rate = (int) [ 8000, 48000 ], " + "channels = (int) [ 1, 2 ]; " + "audio/ilbc, " + "rate = (int) [ 8000, 48000 ], " + "channels = (int) [ 1, 2 ]; " + "audio/x-mulaw, " + "rate = (int) [ 8000, 48000 ], " + "channels = (int) [ 1, 2 ]") + ); + +static GstElementClass *parent_class= NULL; + +static void gst_devsound_src_base_init(gpointer g_class) + { + GstElementClass *element_class= GST_ELEMENT_CLASS (g_class); + + gst_element_class_set_details(element_class, &gst_devsound_src_details); + + gst_element_class_add_pad_template(element_class, + gst_static_pad_template_get(&devsound_src_factory)); + } + +GType gst_devsound_src_get_type(void) + { + static GType devsoundsrc_type = 0; + + if (!devsoundsrc_type) + { + static const GTypeInfo devsoundsrc_info = + { + sizeof(GstDevsoundSrcClass), gst_devsound_src_base_init, NULL, + (GClassInitFunc) gst_devsound_src_class_init, NULL, NULL, + sizeof(GstDevsoundSrc), 0, + (GInstanceInitFunc) gst_devsound_src_init +, }; + + static const GInterfaceInfo speech_encoder_config_info = + { + gst_speech_encoder_config_handler_init, + NULL, + NULL + }; + + static const GInterfaceInfo g711_encoder_info = + { + gst_g711_encoder_handler_init, + NULL, + NULL + }; + + static const GInterfaceInfo g729_encoder_info = + { + gst_g729_encoder_handler_init, + NULL, + NULL + }; + + static const GInterfaceInfo ilbc_encoder_info = + { + gst_ilbc_encoder_handler_init, + NULL, + NULL + }; + + devsoundsrc_type = + g_type_register_static (GST_TYPE_PUSH_SRC, "GstDevsoundSrc", + &devsoundsrc_info, 0); + + g_type_add_interface_static (devsoundsrc_type, GST_TYPE_SPEECH_ENCODER_CONFIG, + &speech_encoder_config_info); + + g_type_add_interface_static (devsoundsrc_type, GST_TYPE_G711_ENCODER, + &g711_encoder_info); + + g_type_add_interface_static (devsoundsrc_type, GST_TYPE_G729_ENCODER, + &g729_encoder_info); + + g_type_add_interface_static (devsoundsrc_type, GST_TYPE_ILBC_ENCODER, + &ilbc_encoder_info); + + } + +return devsoundsrc_type; +} + +static void gst_devsound_src_dispose(GObject * object) + { + GstDevsoundSrc *devsoundsrc= GST_DEVSOUND_SRC (object); + G_OBJECT_CLASS (parent_class)->dispose (object); + } + +static void gst_devsound_src_class_init(GstDevsoundSrcClass * klass) + { + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + GstBaseSrcClass *gstbasesrc_class; + GstPushSrcClass *gstpushsrc_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + gstbasesrc_class = (GstBaseSrcClass *) klass; + gstpushsrc_class = (GstPushSrcClass *) klass; + + parent_class = g_type_class_peek_parent(klass); + + gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_devsound_src_dispose); + gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_devsound_src_get_property); + gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_devsound_src_set_property); + + g_object_class_install_property(gobject_class, PROP_DEVICE, + g_param_spec_string("device", "Device", "Devsound device ", + DEFAULT_DEVICE, G_PARAM_READWRITE)); + + g_object_class_install_property(gobject_class, GAIN, g_param_spec_int( + "gain", "Gain", "Devsound src gain", -1, G_MAXINT, -1, + G_PARAM_READWRITE)); + + g_object_class_install_property(gobject_class, MAXGAIN, g_param_spec_int( + "maxgain", "MaxGain", "Devsound src max gain", -1, G_MAXINT, -1, + G_PARAM_READABLE)); + + g_object_class_install_property(gobject_class, LEFTBALANCE, + g_param_spec_int("leftbalance", "Left Balance", "Left Balance", + -1, G_MAXINT, -1, G_PARAM_READWRITE)); + + g_object_class_install_property(gobject_class, RIGHTBALANCE, + g_param_spec_int("rightbalance", "Right Balance", + "Right Balance", -1, G_MAXINT, -1, G_PARAM_READWRITE)); + + g_object_class_install_property(gobject_class, SAMPLESRECORDED, + g_param_spec_int("samplesrecorded", "Samples Recorded", + "Samples Recorded", -1, G_MAXINT, -1, G_PARAM_READABLE)); + + g_object_class_install_property(gobject_class, PRIORITY, + g_param_spec_int("priority", "Priority", "Priority ", -1, + G_MAXINT, -1, + G_PARAM_READWRITE)); + + g_object_class_install_property(gobject_class, PREFERENCE, + g_param_spec_int("preference", "Preference", "Preference ", -1, + G_MAXINT, -1, + G_PARAM_READWRITE)); + + g_object_class_install_property(gobject_class, RATE, + g_param_spec_int("rate", "Rate", "Rate ", -1, + G_MAXINT, -1, + G_PARAM_READWRITE)); + + g_object_class_install_property(gobject_class, CHANNELS, + g_param_spec_int("channels", "Channels", "Channels ", -1, + G_MAXINT, -1, + G_PARAM_READWRITE)); + gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_devsound_src_start); + gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_devsound_src_stop); + gstbasesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_devsound_src_getcaps); + gstbasesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_devsound_src_setcaps); + + gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_devsound_src_create); + } + +static void gst_devsound_src_init(GstDevsoundSrc * devsoundsrc) + { + GST_DEBUG_OBJECT(devsoundsrc, "initializing devsoundsrc"); + //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) devsoundsrc, "gst_devsound_src_init ENTER ",NULL); + devsoundsrc->device = g_strdup(DEFAULT_DEVICE); + devsoundsrc->handle=NULL; + devsoundsrc->preference = 0; //default=>EMdaPriorityPreferenceNone; + devsoundsrc->priority = 0; //default=>EMdaPriorityNormal; + pthread_mutex_init(&create_mutex1, NULL); + pthread_cond_init(&create_condition1, NULL); + //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) devsoundsrc, "gst_devsound_src_init EXIT ",NULL); + } + +static void *StartDevSoundThread(void *threadarg) + { + GstDevsoundSrc *devsoundsrc= GST_DEVSOUND_SRC (threadarg); + int buffersize; + TUint8* gBuffer; + GstBuffer* pushBuffer= NULL; + //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) devsoundsrc, "StartDevSoundThread ",NULL); + open_devsound(&(devsoundsrc->handle)); + + getsupporteddatatypes(devsoundsrc); + +// TODO obtain mutex to update variable here??? + consumer_thread_state = CONSUMER_THREAD_INITIALIZED; + + //pre_init_setconf(devsoundsrc); + + //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) devsoundsrc, "After Record Init ",NULL); + + pthread_mutex_lock(&(create_mutex1)); + pthread_cond_signal(&(create_condition1)); + pthread_mutex_unlock(&(create_mutex1)); + + // Wait until we receive a command from the main thread + // TODO obtain mutex to read variable here??? + while ( cmd == OPEN ) + { + pthread_mutex_lock(&create_mutex1); + pthread_cond_wait(&create_condition1, &create_mutex1); + pthread_mutex_unlock(&create_mutex1); + } + + // This could happen if client creates sink and deletes it + // without putting it to play state + if ( cmd != CLOSE ) + { + initialize_devsound(devsoundsrc); + + recordinit(devsoundsrc->handle); + initproperties(devsoundsrc); + } + //cmd = READDATA; + while (1) + { + //set/get properties + //*************************************** + pre_init_setconf(devsoundsrc); + gst_Apply_SpeechEncoder_Update(devsoundsrc); + gst_Apply_G711Encoder_Update(devsoundsrc); + gst_Apply_G729Encoder_Update(devsoundsrc ); + gst_Apply_IlbcEncoder_Update(devsoundsrc ); + + populateproperties(devsoundsrc); + + supportedbitrates = devsoundsrc->supportedbitrates; + //numofbitrates = devsoundsrc->numofbitrates; + speechbitrate = devsoundsrc->speechbitrate; + speechvadmode = devsoundsrc->speechvadmode; + g711vadmode = devsoundsrc->g711vadmode; + g729vadmode = devsoundsrc->g729vadmode; + ilbcvadmode = devsoundsrc->ilbcvadmode; + + + //**************************************** + //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) devsoundsrc, "Before Buffer Alloc ",NULL); + buffersize = get_databuffer_size(devsoundsrc->handle); + get_databuffer(devsoundsrc->handle, &gBuffer); + pushBuffer = gst_buffer_new_and_alloc(buffersize); + //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) devsoundsrc, "After Buffer Alloc ",NULL); + if (GST_BUFFER_DATA(pushBuffer)) + { + memcpy(GST_BUFFER_DATA(pushBuffer),gBuffer,buffersize); + } + else + { + //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) devsoundsrc, "Push buffer alloc failed ",NULL); + } + + if (dataqueue) + { + GST_OBJECT_LOCK(devsoundsrc); + g_queue_push_head (dataqueue,pushBuffer); + GST_OBJECT_UNLOCK(devsoundsrc); + //signalmutex_create(devsoundsrc->handle); + if(dataqueue->length == 1 && (cmd != CLOSE)) + { + //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) devsoundsrc, "Before signal in DevSoundt ",NULL); + pthread_mutex_lock(&(create_mutex1)); + pthread_cond_signal(&(create_condition1)); + pthread_mutex_unlock(&(create_mutex1)); + //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) devsoundsrc, "After signal in DevSoundt ",NULL); + } + //cmd = READDATA; + //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) devsoundsrc, "Before DevSnd Wait ",NULL); + //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) devsoundsrc, "After DevSnd Wait ",NULL); + } + else + { + //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) devsoundsrc, "dataqueue is NULL, CLOSE now ",NULL); + cmd = CLOSE; + } + + switch (cmd) + { + case READDATA: + { + record_data(devsoundsrc->handle); + } + break; + case CLOSE: + { + //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) devsoundsrc, "Before Close DevSound ",NULL); + close_devsound(devsoundsrc); + //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) devsoundsrc, "After Close DevSound ",NULL); + devsoundsrc->handle= NULL; + //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) devsoundsrc, "After handle NULL ",NULL); + + pthread_mutex_lock(&(create_mutex1)); + pthread_cond_signal(&(create_condition1)); + pthread_mutex_unlock(&(create_mutex1)); + // TODO obtain mutex here + consumer_thread_state = CONSUMER_THREAD_UNINITIALIZED; + pthread_exit(NULL); + } + break; + default: + // TODO obtain mutex here + consumer_thread_state = CONSUMER_THREAD_UNINITIALIZED; + pthread_exit(NULL); + break; + } + } + // TODO obtain mutex here + consumer_thread_state = CONSUMER_THREAD_UNINITIALIZED; + pthread_exit(NULL); + } + +static void gst_devsound_src_set_property(GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) + { + GstDevsoundSrc *src; + + src = GST_DEVSOUND_SRC (object); + + switch (prop_id) + { + case PROP_DEVICE: + if (src->device) + g_free(src->device); + src->device = g_value_dup_string(value); + if (src->probed_caps) + { + gst_caps_unref(src->probed_caps); + src->probed_caps = NULL; + } + break; + case CHANNELS: + src->channels = g_value_get_int(value); + src->pending.channelsupdate = TRUE; + break; + case RATE: + src->rate = g_value_get_int(value); + //Convert rate to something devsound understands + src->rate = gst_devsound_src_get_rate(src->rate); + src->pending.rateupdate = TRUE; + break; + case GAIN: + src->gain = g_value_get_int(value); + src->pending.gainupdate = TRUE; + break; + case LEFTBALANCE: + src->leftbalance = g_value_get_int(value); + src->pending.leftbalanceupdate = TRUE; + break; + case RIGHTBALANCE: + src->rightbalance = g_value_get_int(value); + src->pending.rightbalanceupdate = TRUE; + break; + case PRIORITY: + src->priority = g_value_get_int(value); + src->pending.priorityupdate = TRUE; + break; + case PREFERENCE: + src->preference = g_value_get_int(value); + src->pending.preferenceupdate = TRUE; + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + } + +static void gst_devsound_src_get_property(GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) + { + GstDevsoundSrc *src; + + src = GST_DEVSOUND_SRC (object); + + switch (prop_id) + { + case PROP_DEVICE: + g_value_set_string(value, src->device); + break; + case CHANNELS: + g_value_set_int(value, src->channels); + break; + case RATE: + g_value_set_int(value, src->rate); + break; + case GAIN: + g_value_set_int(value, src->gain); + break; + case MAXGAIN: + g_value_set_int(value, src->maxgain); + break; + case SAMPLESRECORDED: + g_value_set_int(value, src->samplesrecorded); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + } + +static gboolean gst_devsound_src_setcaps(GstBaseSrc *bsrc, GstCaps *caps) + { + GstDevsoundSrc *devsoundsrc; + GstStructure *structure; + const gchar *mimetype; + int rate; + int channel; + + devsoundsrc = GST_DEVSOUND_SRC (bsrc); + //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) devsoundsrc, "gst_devsound_src_setcaps ENTER ",NULL); + structure = gst_caps_get_structure(caps, 0); + mimetype = gst_structure_get_name(structure); + + gst_structure_get_int(structure, "rate", &rate); + gst_structure_get_int(structure, "channels", &channel); + + devsoundsrc->rate = gst_devsound_src_get_rate(rate); + devsoundsrc->channels = channel; + + set_channels(devsoundsrc->handle, devsoundsrc->channels); + + set_rate(devsoundsrc->handle, devsoundsrc->rate); + + if (!strncmp(mimetype, "audio/x-raw-int", 15)) + { + devsoundsrc->fourcc = 0x36315020; //KMMFFourCCCodePCM16 + } + else if (!strncmp(mimetype, "audio/amr", 9)) + { + devsoundsrc->fourcc = 0x524d4120; //KMMFFourCCCodeAMR + } + else if (!strncmp(mimetype, "audio/x-mulaw", 13)|| + !strncmp(mimetype,"audio/x-alaw", 12)) + { + devsoundsrc->fourcc = 0x31313747; //KMccFourCCIdG711 + } + else if (!strncmp(mimetype, "audio/ilbc", 10)) + { + devsoundsrc->fourcc = 0x43424c49; //KMccFourCCIdILBC + } + else if (!strncmp(mimetype, "audio/g729", 10)) + { + devsoundsrc->fourcc = 0x39323747; //KMccFourCCIdG729 + } + else + { + devsoundsrc->fourcc = 0x36315020; //KMMFFourCCCodePCM16 + } + + set_fourcc(devsoundsrc->handle, devsoundsrc->fourcc); + //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) devsoundsrc, "Before Signal DevSound from STOP",NULL); + pthread_mutex_lock(&(create_mutex1)); + pthread_cond_signal(&(create_condition1)); + pthread_mutex_unlock(&(create_mutex1)); + //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) devsoundsrc, "After Signal DevSound from STOP ",NULL); + //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) devsoundsrc, "gst_devsound_src_setcaps EXIT ",NULL); + return TRUE; + } + +static GstCaps * gst_devsound_src_getcaps(GstBaseSrc * bsrc) + { + GstDevsoundSrc *devsoundsrc; + GstCaps *caps; + GstPadTemplate *pad_template; + + devsoundsrc = GST_DEVSOUND_SRC (bsrc); + + GST_DEBUG_OBJECT(devsoundsrc, "getcaps called"); + + pad_template = gst_static_pad_template_get(&devsound_src_factory); + caps = gst_caps_copy(gst_pad_template_get_caps(pad_template)); + + gst_object_unref(pad_template); + + return caps; + } + +static gboolean gst_devsound_src_start(GstBaseSrc * bsrc) + { + GstBuffer *tmp_gstbuffer=NULL; + GstDevsoundSrc *src= GST_DEVSOUND_SRC(bsrc); + //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) src, "gst_devsound_src_start ENTER ",NULL); + + if(dataqueue) + { + while (dataqueue->length) + { + tmp_gstbuffer = (GstBuffer*)g_queue_pop_tail(dataqueue); + gst_buffer_unref(tmp_gstbuffer); + } + g_queue_free(dataqueue); + dataqueue = NULL; + } + + if(dataqueue == NULL) + { + dataqueue = g_queue_new(); + } + + consumer_thread_state = CONSUMER_THREAD_INITIALIZING; + cmd = OPEN; + //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) src, "Before Thread Create ",NULL); + pthread_create(&ds_thread, NULL, StartDevSoundThread, (void *)src); + //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) src, "After Thread Create ",NULL); + //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) src, "Before Mutex Wait in START ",NULL); + if (consumer_thread_state == CONSUMER_THREAD_INITIALIZING) + { + pthread_mutex_lock(&create_mutex1); + pthread_cond_wait(&create_condition1, &create_mutex1); + pthread_mutex_unlock(&create_mutex1); + } + //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) src, "AFter Mutex Wait in START ",NULL); + //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) src, "gst_devsound_src_start EXIT ",NULL); + return TRUE; + /* ERRORS */ + } + +static gboolean gst_devsound_src_stop(GstBaseSrc * bsrc) + { + + GstDevsoundSrc *src= GST_DEVSOUND_SRC(bsrc); + //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) src, "gst_devsound_src_stop ENTER "); + cmd = CLOSE; + + //GST_OBJECT_LOCK (src); + pthread_mutex_lock(&(create_mutex1)); + pthread_cond_wait(&(create_condition1), &(create_mutex1)); + pthread_mutex_unlock(&(create_mutex1)); + //GST_OBJECT_UNLOCK (src); + + if (popBuffer) + { + gst_buffer_unref(popBuffer); + popBuffer = NULL; + dataleft = 0; //Arun'S changes + } + //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) src, "Before QUEUE Lock in STOP "); + GST_OBJECT_LOCK(src); + //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) src, "After QUEUE Lock in STOP "); + while (dataqueue->length) + { + //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) src, "Removing DATAQUEUE elements ENTER "); + popBuffer = (GstBuffer*)g_queue_pop_tail(dataqueue); + gst_buffer_unref(popBuffer); + popBuffer = NULL; + dataleft = 0; //Arun'S changes + //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) src, "Removing DATAQUEUE elements EXIT "); + } + //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) src, "Before Queue FREE "); + g_queue_free(dataqueue); + //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) src, "After Queue FREE "); + dataqueue = NULL; + GST_OBJECT_UNLOCK(src); + + pthread_mutex_destroy(&create_mutex1); + pthread_cond_destroy(&(create_condition1)); + + + g_free(src->device); + //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) src, "gst_devsound_src_stop EXIT "); + return TRUE; + } + +static gboolean gst_devsound_src_unlock(GstBaseSrc * bsrc) + { + GstDevsoundSrc *src= GST_DEVSOUND_SRC(bsrc); + + GST_LOG_OBJECT(src, "Flushing"); + GST_OBJECT_LOCK (src); + GST_OBJECT_UNLOCK (src); + + return TRUE; + } + +static gboolean gst_devsound_src_unlock_stop(GstBaseSrc * bsrc) + { + GstDevsoundSrc *src= GST_DEVSOUND_SRC(bsrc); + + GST_LOG_OBJECT(src, "No longer flushing"); + return TRUE; + } + +static GstFlowReturn gst_devsound_src_create(GstBaseSrc *src, guint64 offset, + guint size, GstBuffer **buf) + { + GstDevsoundSrc *dsrc= GST_DEVSOUND_SRC(src); + int bufferpos=0; + //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) dsrc, "gst_devsound_src_create ENTER "); + + //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) dsrc, "Before Buffer Alloc in CREATE ",NULL); + *buf = gst_buffer_try_new_and_alloc(size); + //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) dsrc, "AFter Buffer Alloc in CREATE ",NULL); + + while (size > 0) + { + if (dataleft >= size) + { + // if there is some data left in the popped buffer previously whose size + // is more then the buffer which is incoming fresh to get filled, fill it + //here. and if the data left in the popped buffer is 0, then unref it + //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) dsrc, "dataleft >=size in CREATE ", NULL); + memcpy(GST_BUFFER_DATA(*buf)+bufferpos,GST_BUFFER_DATA(popBuffer)+dataCopied,size); + bufferpos+=size; + dataCopied += size; + dataleft = GST_BUFFER_SIZE(popBuffer) - dataCopied; + size = 0; + if (dataleft == 0) + { + dataCopied = 0; + gst_buffer_unref(popBuffer); + popBuffer = NULL; + } + } + else + { + // if the dataleft in the popped buffer is greater then 0 and less then + // the size of data needed for the fresh buffer. copy the remaining data + // from the popped buffer and then unref it. + if (dataleft > 0) + { + //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) dsrc, "dataleft >0 in CREATE ",NULL); + memcpy(GST_BUFFER_DATA(*buf)+bufferpos,GST_BUFFER_DATA(popBuffer)+dataCopied,dataleft); + size -= dataleft; + bufferpos += dataleft; + dataCopied = 0; + dataleft = 0; + gst_buffer_unref(popBuffer); + popBuffer = NULL; + } + + // we wait here if the dataqueue length is 0 and we need data + // to be filled in the queue from the DevSound Thread + if (!dataqueue->length) + { + //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) dsrc, "Before WAIT in CREATE ",NULL); + cmd = READDATA; + pthread_mutex_lock(&(create_mutex1)); + pthread_cond_signal(&(create_condition1)); + pthread_mutex_unlock(&(create_mutex1)); + + pthread_mutex_lock(&(create_mutex1)); + pthread_cond_wait(&(create_condition1), &(create_mutex1)); + pthread_mutex_unlock(&(create_mutex1)); + //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) dsrc, "AFTER WAIT in CREATE ",NULL); + } + + //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) dsrc, "Before POP in CREATE ",NULL); + GST_OBJECT_LOCK(dsrc); + popBuffer = (GstBuffer*)g_queue_pop_tail(dataqueue); + GST_OBJECT_UNLOCK(dsrc); + //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) dsrc, "AFTER POP in CREATE ",NULL); + + // copy the data from the popped buffer based on how much of the incoming + //buffer size is left to fill. we might have filled the fresh buffer somewhat + // where the size of the fresh buffer is more then the data remaining in the + // popped buffer. + if (size < GST_BUFFER_SIZE(popBuffer)) + { + //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) dsrc, "SIZE < POPBUFFER CREATE ",NULL); + memcpy(GST_BUFFER_DATA(*buf)+ bufferpos,GST_BUFFER_DATA(popBuffer),size); + bufferpos+=size; + dataCopied = size; + dataleft = GST_BUFFER_SIZE(popBuffer) - dataCopied; + size = 0; + } + else + { + //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) dsrc, "SIZE >= POPBUFFER CREATE ",NULL); + memcpy(GST_BUFFER_DATA(*buf)+ bufferpos,GST_BUFFER_DATA(popBuffer),GST_BUFFER_SIZE(popBuffer)); + bufferpos+=GST_BUFFER_SIZE(popBuffer); + dataCopied = 0; + dataleft = 0; + size = size - GST_BUFFER_SIZE(popBuffer); + } + + if (!dataleft) + { + gst_buffer_unref(popBuffer); + popBuffer = NULL; + } + } + } + //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) dsrc, "gst_devsound_src_create EXIT ",NULL); + return GST_FLOW_OK; + } + +static gboolean gst_devsound_src_is_seekable(GstBaseSrc * bsrc) + { + GstDevsoundSrc *src= GST_DEVSOUND_SRC(bsrc); + return FALSE; + } + +static gboolean gst_devsound_src_get_size(GstBaseSrc * bsrc, guint64 * size) + { + GstDevsoundSrc *src= GST_DEVSOUND_SRC(bsrc); + return TRUE; + } + +static void gst_speech_encoder_config_handler_init(gpointer g_iface, + gpointer iface_data) + { + GstSpeechEncoderConfigIntfc *iface = + (GstSpeechEncoderConfigIntfc *) g_iface; + + iface->GetBitrate = gst_get_speech_encoder_bit_rate; + iface->GetSupportedBitrates = gst_get_speech_encoder_supported_bit_rates; + iface->GetVadMode = gst_get_speech_encoder_vad_mode; + iface->SetBitrate = gst_set_speech_encoder_bit_rate; + iface->SetVadMode = gst_set_speech_encoder_vad_mode; + + } + +static gint gst_get_speech_encoder_bit_rate(guint* aBitrate) + { + *aBitrate = speechbitrate; + return 0; + } +static gint gst_get_speech_encoder_supported_bit_rates( + GList** aSupportedBitrate) + { + *aSupportedBitrate = supportedbitrates; + return 0; + } +static gint gst_get_speech_encoder_vad_mode(gboolean* aVadMode) + { + *aVadMode = speechvadmode; + return 0; + } +static gint gst_set_speech_encoder_bit_rate(guint aBitrate) + { + speechbitrate = aBitrate; + customInfaceUpdate.speechbitrateupdate = TRUE; + return 0; + } + +static gint gst_set_speech_encoder_vad_mode(gboolean aVadMode) + { + speechvadmode = aVadMode; + customInfaceUpdate.speechvadmodeupdate = TRUE; + return 0; + } + + +static void gst_Apply_SpeechEncoder_Update(GstDevsoundSrc *devsoundsrc ) + { + if(customInfaceUpdate.speechbitrateupdate == TRUE) + { + set_speech_encoder_bit_rate(devsoundsrc->handle,speechbitrate); + customInfaceUpdate.speechbitrateupdate = FALSE; + } + if(customInfaceUpdate.speechvadmodeupdate == TRUE) + { + set_speech_encoder_vad_mode(devsoundsrc->handle,speechvadmode); + customInfaceUpdate.speechvadmodeupdate = FALSE; + } + } + +static void gst_g711_encoder_handler_init(gpointer g_iface, + gpointer iface_data) + { + GstG711EncoderIntfc *iface = (GstG711EncoderIntfc *) g_iface; + + iface->GetVadMode = gst_get_g711_encoder_vad_mode; + iface->SetEncoderMode = gst_set_g711_encoder_mode; + iface->SetVadMode = gst_set_g711_vad_mode; + + } + +static gint gst_get_g711_encoder_vad_mode(gboolean* aVadMode) + { + *aVadMode = g711vadmode; + return 0; + } + +static gint gst_set_g711_encoder_mode(enum TG711EncodeMode aEncodeMode) + { + g711encodemode = aEncodeMode; + customInfaceUpdate.g711encodermodeupdate = TRUE; + return 0; + } +static gint gst_set_g711_vad_mode(gboolean aVadMode) + { + g711vadmode = aVadMode; + customInfaceUpdate.g711vadmodeupdate = TRUE; + return 0; + } + + +static void gst_Apply_G711Encoder_Update(GstDevsoundSrc *devsoundsrc ) + { + + if(customInfaceUpdate.g711encodermodeupdate == TRUE) + { + set_g711_encoder_mode(devsoundsrc->handle,g711encodemode); + customInfaceUpdate.g711encodermodeupdate = FALSE; + } + if(customInfaceUpdate.g711vadmodeupdate == TRUE) + { + set_g711_vad_mode(devsoundsrc->handle,g711vadmode); + customInfaceUpdate.g711vadmodeupdate = FALSE; + } + } + +static void gst_g729_encoder_handler_init(gpointer g_iface, + gpointer iface_data) + { + + GstG729EncoderIntfc *iface = (GstG729EncoderIntfc *) g_iface; + + iface->GetVadMode = gst_get_g729_vad_mode; + iface->SetVadMode = gst_set_g729_vad_mode; + + } + +static gint gst_set_g729_vad_mode(TBool aVadMode) + { + g729vadmode = aVadMode; + customInfaceUpdate.g729vadmodeupdate = TRUE; + return 0; + } + +static gint gst_get_g729_vad_mode(TBool* aVadMode) + { + *aVadMode = g729vadmode; + return 0; + } +static void gst_Apply_G729Encoder_Update(GstDevsoundSrc *devsoundsrc ) + { + if(customInfaceUpdate.g729vadmodeupdate) + { + set_g729_vad_mode(devsoundsrc->handle,g729vadmode); + customInfaceUpdate.g729vadmodeupdate = FALSE; + } + + } + +static void gst_ilbc_encoder_handler_init(gpointer g_iface, + gpointer iface_data) + { + GstIlbcEncoderIntfc *iface = (GstIlbcEncoderIntfc *) g_iface; + + iface->GetVadMode = gst_get_ilbc_vad_mode; + iface->SetEncoderMode = gst_set_ilbc_encoder_mode; + iface->SetVadMode = gst_set_ilbc_vad_mode; + } + +static gint gst_set_ilbc_encoder_mode(enum TIlbcEncodeMode aEncodeMode) + { + ilbcencodemode = aEncodeMode; + return 0; + } + +static gint gst_set_ilbc_vad_mode(gboolean aVadMode) + { + ilbcvadmode = aVadMode; + return 0; + } + +static gint gst_get_ilbc_vad_mode(gboolean* aVadMode) + { + *aVadMode = ilbcvadmode; + return 0; + } + +static void gst_Apply_IlbcEncoder_Update(GstDevsoundSrc *devsoundsrc ) + { + if(customInfaceUpdate.ilbcencodermodeupdate) + { + set_ilbc_encoder_mode(devsoundsrc->handle,ilbcencodemode); + customInfaceUpdate.ilbcencodermodeupdate = FALSE; + } + if(customInfaceUpdate.ilbcvadmodeupdate) + { + set_ilbc_vad_mode(devsoundsrc->handle,ilbcvadmode); + customInfaceUpdate.ilbcvadmodeupdate = FALSE; + } + + } + +static gint gst_devsound_src_get_rate(gint rate) + { + gint result; + + switch (rate) + { + case 8000: + result=0x00000001;//EMMFSampleRate8000Hz; + break; + case 11025: + result=0x00000002;//EMMFSampleRate11025Hz; + break; + case 16000: + result=0x00000004;//EMMFSampleRate16000Hz; + break; + case 22050: + result=0x00000008;//EMMFSampleRate22050Hz; + break; + case 32000: + result=0x00000010;//EMMFSampleRate32000Hz; + break; + case 44100: + result=0x00000020;//EMMFSampleRate44100Hz; + break; + case 48000: + result=0x00000040;//EMMFSampleRate48000Hz; + break; + case 88200: + result=0x00000080;//EMMFSampleRate88200Hz; + break; + case 96000: + result= 0x00000100;//EMMFSampleRate96000Hz; + break; + case 12000: + result=0x00000200;//EMMFSampleRate12000Hz; + break; + case 24000: + result=0x00000400;//EMMFSampleRate24000Hz; + break; + case 64000: + result=0x00000800; //EMMFSampleRate64000Hz; + break; + default: + result=0x00000001;//EMMFSampleRate8000Hz; + break; + + } + return result; + + } +