--- /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 <omega@cse.ogi.edu>
+ * 2000,2005 Wim Taymans <wim@fluendo.com>
+ *
+ * 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 <gqueue.h>
+#include "common.h"
+#include "gstdevsoundsrc.h"
+
+#include <glib_global.h>
+#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;
+
+ }
+