Mercurial > pidgin
changeset 12024:e67993da8a22
[gaim-migrate @ 14317]
I strongly suspect CruiseControl is going to yell at me for this.
A voice chat API, GUI + mediastreamer. This is what I'm using for Google Talk.
This doesn't actually do anything at all. There's no code in the Jabber plugin yet
to use this API (although it Works For Me). All it will do is compile and link.
If you're lucky.
To build this, you should install oRTP from Linphone, Speex and iLBC (also
from linphone, I believe). To not build this, ./configure --disable-vv.
Most of the configure.ac and Makefile.am hackery was lifted right out of
Linphone with a few modifications. It seems to work if you have everything
installed or if you --disable-vv. I haven't really tested not having
everything installed and not --disabling-vv.
It's kinda funky to include all of mediastreamer in the source tree like this,
but linphone doesn't build it as a separate library. I'll probably wind up
writing them a patch to build it as a .so so we can link it dynamically instead.
This code certainly isn't finished. It'll adapt as I progress on the Google code,
but it's certainly of more use here in CVS than in my personal tree.
committer: Tailor Script <tailor@pidgin.im>
line wrap: on
line diff
--- a/autogen.sh Wed Nov 09 07:58:36 2005 +0000 +++ b/autogen.sh Wed Nov 09 08:07:20 2005 +0000 @@ -58,7 +58,7 @@ fi done -aclocal $ACLOCAL_FLAGS || exit; +aclocal $ACLOCAL_FLAGS -I ./m4 || exit; autoheader || exit; automake --add-missing --copy; autoconf || exit;
--- a/configure.ac Wed Nov 09 07:58:36 2005 +0000 +++ b/configure.ac Wed Nov 09 08:07:20 2005 +0000 @@ -1447,6 +1447,89 @@ AC_SUBST(enable_doxygen) AC_SUBST(enable_dot) +dnl ############################################################################## +dnl ## Mediastreamer stuff ####################################################### +dnl ############################################################################## +AC_ARG_ENABLE(vv, [ --enable-vv enable Voice and Video support],,enable_vv=yes) +if test "x$enable_vv" = xyes; then + AC_DEFINE(HAVE_GLIB, 1, [Gaim always has GLib, but Linphone can be built without it]) + AM_CONDITIONAL(HAVE_VV, true) + + dnl enable truespeech codec support + AC_ARG_ENABLE(truespeech, + [ --enable-truespeech Turn on TrueSpeech support (x86 only)], + [case "${enableval}" in + yes) truespeech=true;; + no) truespeech=false;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-truespeech) ;; + esac],[truespeech=false]) + TRUESPEECH_CFLAGS= + if test x$truespeech = xtrue ; then + TRUESPEECH_CFLAGS=-DTRUESPEECH + fi + VV_CFLAGS="$VV_CFLAGS $TRUESPEECH_CFLAGS" + + found_sound=no + AC_CHECK_HEADERS(soundcard.h sys/soundcard.h machine/soundcard.h sys/audio.h) + if test "${ac_cv_header_sys_soundcard_h}" = "yes" || \ + test "${ac_cv_header_soundcard_h}" = "yes" || \ + test "${ac_cv_header_sys_audio_h}" = "yes" || \ + test "${ac_cv_header_machine_soundcard_h}" = "yes"; then + found_sound=yes + fi + if test "$found_sound" = "no"; then + AC_MSG_ERROR([Could not find a support sound driver]) + fi + if test "$alsa" = "true"; then + AC_CHECK_HEADERS(alsa/asoundlib.h, + [ AC_CHECK_LIB(asound,snd_pcm_open, + [ALSA_LIBS="-lasound" ; AC_DEFINE(__ALSA_ENABLED__,1,[Defined when alsa support is enabled]) ]) + ] + ) + fi + dnl Check for samplerate libraries + dnl Check for jack libraries (sound output plugin) + PKG_CHECK_MODULES(JACK,jack >= 0.15.0, + [ + dnl we've found jack devel files + PKG_CHECK_MODULES(SAMPLERATE, samplerate >= 0.0.13, [AC_DEFINE(__JACK_ENABLED__,1,[Jack support])] , + [echo "libsamplerate not found, jack support disabled."]) + VV_CFLAGS="$VV_CFLAGS $SAMPLERATE_CFLAGS" + VV_LIBS="$VV_LIBS $SAMPLERATE_LIBS" + ], + [echo "No jack support."] ) + VV_CFLAGS="$VV_CFLAGS $JACK_CFLAGS" + VV_LIBS="$VV_LIBS $JACK_LIBS" + + dnl check for installed version of speex + LP_CHECK_SPEEX + VV_CFLAGS="$VV_CFLAGS $SPEEX_CFLAGS" + VV_LIBS="$VV_LIBS $SPEEX_LIBS" + + dnl check for installed ilbc codec + LP_CHECK_ILBC + VV_CFLAGS="$VV_CFLAGS $ILBC_CFLAGS" + VV_LIBS="$VV_LIBS $ILBC_LIBS" + + PKG_CHECK_MODULES(ORTP, ortp, enable_ortp=yes, enable_ortp=no) + VV_CFLAGS="$VV_CFLAGS $ORTP_CFLAGS" + VV_LIBS="$VV_LIBS $ORTP_LIBS" + if test x$enable_ortp = xno; then + enable_vv=no + fi +else + enable_vv=no +fi + +if test x$enable_vv = xyes; then + AM_CONDITIONAL(HAVE_VV, true) +else + AM_CONDITIONAL(HAVE_VV, false) +fi + +AC_SUBST(VV_CFLAGS) +AC_SUBST(VV_LIBS) + AC_CONFIG_COMMANDS_PRE([ if test -e VERSION; then cp -p VERSION VERSION.ac-save @@ -1487,6 +1570,7 @@ po/Makefile.in sounds/Makefile src/Makefile + src/mediastreamer/Makefile src/protocols/Makefile src/protocols/bonjour/Makefile src/protocols/gg/Makefile
--- a/pixmaps/Makefile.am Wed Nov 09 07:58:36 2005 +0000 +++ b/pixmaps/Makefile.am Wed Nov 09 08:07:20 2005 +0000 @@ -25,6 +25,7 @@ offline.png \ online.png \ pause.png \ + phone.png \ send-im.png \ status-online.png \ status-offline.png \ @@ -77,7 +78,7 @@ gaimiconpix_DATA = away.png connect.png msgpend.png offline.png online.png msgunread.png info.png gaimdistpixdir = $(datadir)/pixmaps/gaim -gaimdistpix_DATA = logo.png tb_drag_arrow_down.xpm tb_drag_arrow_left.xpm tb_drag_arrow_right.xpm tb_drag_arrow_up.xpm typed.png typing.png status-online.png status-offline.png status-away.png status-invisible.png status-typing0.png status-typing1.png status-typing2.png status-typing3.png status-connect0.png status-connect1.png status-connect2.png status-connect3.png +gaimdistpix_DATA = logo.png tb_drag_arrow_down.xpm tb_drag_arrow_left.xpm tb_drag_arrow_right.xpm tb_drag_arrow_up.xpm typed.png typing.png status-online.png status-offline.png status-away.png status-invisible.png status-typing0.png status-typing1.png status-typing2.png status-typing3.png status-connect0.png status-connect1.png status-connect2.png status-connect3.png phone.png distpixmapdir = $(datadir)/pixmaps distpixmap_DATA = gaim.png
--- a/src/Makefile.am Wed Nov 09 07:58:36 2005 +0000 +++ b/src/Makefile.am Wed Nov 09 08:07:20 2005 +0000 @@ -55,8 +55,11 @@ win32/nsis/translations/trad-chinese.nsh \ win32/nsis/translations/vietnamese.nsh - +if HAVE_VV +SUBDIRS = protocols mediastreamer +else SUBDIRS = protocols +endif gaim_coresources = \ account.c \ @@ -74,6 +77,7 @@ ft.c \ imgstore.c \ log.c \ + media.c \ mime.c \ network.c \ ntlm.c \ @@ -120,6 +124,7 @@ ft.h \ imgstore.h \ log.h \ + media.h \ mime.h \ network.h \ notify.h \ @@ -260,6 +265,7 @@ gtkimhtmltoolbar.c \ gtklog.c \ gtkmain.c \ + gtkmedia.c \ gtkmenutray.c \ gtknotify.c \ gtkplugin.c \ @@ -305,6 +311,7 @@ gtkimhtml.h \ gtkimhtmltoolbar.h \ gtklog.h \ + gtkmedia.h \ gtkmenutray.h \ gtknotify.h \ gtkplugin.h \ @@ -329,7 +336,12 @@ $(gaim_coreheaders) \ $(gaim_headers) -gaim_DEPENDENCIES = @LIBOBJS@ $(STATIC_LINK_LIBS) +if HAVE_VV +MS_LIBS=$(top_srcdir)/src/mediastreamer/libmediastreamer.la +MS_INCLUDES=-I$(top_srcdir)/src/mediastreamer +endif + +gaim_DEPENDENCIES = @LIBOBJS@ $(STATIC_LINK_LIBS) mediastreamer/libmediastreamer.la gaim_LDFLAGS = -export-dynamic gaim_LDADD = \ @LIBOBJS@ \ @@ -341,7 +353,9 @@ $(SM_LIBS) \ $(INTLLIBS) \ $(GTKSPELL_LIBS) \ - $(STARTUP_NOTIFICATION_LIBS) + $(STARTUP_NOTIFICATION_LIBS) \ + $(VV_LIBS) \ + $(MS_LIBS) AM_CPPFLAGS = \ -DBR_PTHREADS=0 \ @@ -350,6 +364,8 @@ -DLOCALEDIR=\"$(datadir)/locale\" \ -DSYSCONFDIR=\"$(sysconfdir)\" \ -I$(top_srcdir)/plugins \ + $(MS_INCLUDES) \ + $(VV_CFLAGS) \ $(AUDIOFILE_CFLAGS) \ $(AO_CFLAGS) \ $(DEBUG_CFLAGS) \
--- a/src/core.c Wed Nov 09 07:58:36 2005 +0000 +++ b/src/core.c Wed Nov 09 08:07:20 2005 +0000 @@ -46,7 +46,6 @@ # include "dbus-server.h" #endif - struct GaimCore { char *ui; @@ -116,6 +115,9 @@ gaim_blist_init(); gaim_log_init(); gaim_buddy_icons_init(); +#ifdef HAVE_VV + gaim_media_init(); +#endif gaim_network_init(); gaim_privacy_init(); gaim_pounces_init();
--- a/src/gtkblist.c Wed Nov 09 07:58:36 2005 +0000 +++ b/src/gtkblist.c Wed Nov 09 08:07:20 2005 +0000 @@ -253,6 +253,11 @@ serv_send_file(b->account->gc, b->name, NULL); } +static void gtk_blist_menu_voice_chat_cb(GtkWidget *w, GaimBuddy *b) +{ + serv_voice_chat(b->account->gc, b->name); +} + static void gtk_blist_menu_autojoin_cb(GtkWidget *w, GaimChat *chat) { gaim_blist_node_set_bool((GaimBlistNode*)chat, "gtk-autojoin", @@ -973,6 +978,14 @@ buddy, 0, 0, NULL); } } + + if (prpl_info && prpl_info->media_prpl_ops && prpl_info->media_prpl_ops->call) { + gaim_new_item_from_stock(menu, _("Start _Voice Chat"), + GAIM_STOCK_VOICE_CHAT, + G_CALLBACK(gtk_blist_menu_voice_chat_cb), + buddy, 0, 0, NULL); + } + gaim_new_item_from_stock(menu, _("Add Buddy _Pounce"), NULL, G_CALLBACK(gtk_blist_menu_bp_cb), buddy, 0, 0, NULL);
--- a/src/gtkconv.c Wed Nov 09 07:58:36 2005 +0000 +++ b/src/gtkconv.c Wed Nov 09 08:07:20 2005 +0000 @@ -346,7 +346,6 @@ gtkconv = GAIM_GTK_CONVERSATION(conv); gtk_imhtml_clear(GTK_IMHTML(gtkconv->imhtml)); - return GAIM_CMD_STATUS_OK; }
--- a/src/gtkmain.c Wed Nov 09 07:58:36 2005 +0000 +++ b/src/gtkmain.c Wed Nov 09 08:07:20 2005 +0000 @@ -48,6 +48,7 @@ #include "gtkdialogs.h" #include "gtkeventloop.h" #include "gtkft.h" +#include "gtkmedia.h" #include "gtkidle.h" #include "gtknotify.h" #include "gtkplugin.h" @@ -268,6 +269,9 @@ gaim_gtk_privacy_init(); gaim_gtk_xfers_init(); gaim_gtk_roomlist_init(); +#ifdef HAEV_VV + gaim_gtk_media_init(); +#endif gaim_gtk_idle_init(); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/gtkmedia.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,134 @@ +/** + * @file gtkmedia.h Voice and Video API + * @ingroup gtkui + * + * gaim + * + * Gaim is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_VV + +#include "internal.h" +#include "gtkconv.h" +#include "gtkmedia.h" + +typedef struct { + GtkWidget *call_pane; + GtkWidget *bbox; +} GaimGtkVoiceChat; + + +static void gaim_gtk_media_new_voice_chat(GaimVoiceChat *vc) +{ + GaimGtkVoiceChat *gvc = g_new0(GaimGtkVoiceChat, 1); + gaim_voice_chat_set_ui_data(vc, gvc); + +} + +static void gaim_gtk_media_destroy(GaimVoiceChat *vc) +{ + GaimConversation *conv = gaim_conversation_new(GAIM_CONV_TYPE_IM, gaim_connection_get_account(gaim_voice_chat_get_connection(vc)), + gaim_voice_chat_get_name(vc)); + gaim_conversation_write(conv, NULL, _("Call ended."), GAIM_MESSAGE_SYSTEM, time(NULL)); + GaimGtkVoiceChat *gvc = (GaimGtkVoiceChat*)gaim_voice_chat_get_ui_data(vc); + gtk_widget_destroy(gvc->call_pane); + g_free(gvc); +} + +static void gaim_gtk_media_state_change(GaimVoiceChat *vc, GaimMediaState state) +{ + GaimGtkVoiceChat *gvc = (GaimGtkVoiceChat*)gaim_voice_chat_get_ui_data(vc); + GaimConversation *conv = gaim_conversation_new(GAIM_CONV_TYPE_IM, gaim_connection_get_account(gaim_voice_chat_get_connection(vc)), + gaim_voice_chat_get_name(vc)); + GaimGtkConversation *gtkconv = GAIM_GTK_CONVERSATION(conv); + GtkWidget *hbox, *bbox; + GtkWidget *button; + char *msg = NULL; + + switch (state) { + case GAIM_MEDIA_STATE_CALLING: + msg = g_strdup_printf(_("Calling %s"), gaim_voice_chat_get_name(vc)); + gaim_conversation_write(conv, NULL, msg, GAIM_MESSAGE_SYSTEM, time(NULL)); + g_free(msg); + hbox = gtk_hbox_new(FALSE, 6); + button = gtk_button_new_with_label(_("End Call")); + g_signal_connect_swapped(G_OBJECT(button), "clicked", G_CALLBACK(gaim_voice_chat_terminate), vc); + gvc->call_pane = hbox; + gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, 0, 0); + gtk_box_pack_end(GTK_BOX(gtkconv->tab_cont), hbox, FALSE, 0, 0); + gtk_widget_show_all(hbox); + break; + case GAIM_MEDIA_STATE_RECEIVING: + msg = g_strdup_printf(_("Receiving call from %s"), gaim_voice_chat_get_name(vc)); + gaim_conversation_write(conv, NULL, msg, GAIM_MESSAGE_SYSTEM, time(NULL)); + g_free(msg); + hbox = gtk_hbox_new(FALSE, 6); + bbox = gvc->bbox = gtk_hbutton_box_new(); + gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END); + gtk_box_set_spacing(GTK_BOX(bbox), 6); + gtk_container_add(GTK_CONTAINER(hbox), bbox); + button = gtk_button_new_with_label(_("Reject Call")); + g_signal_connect_swapped(G_OBJECT(button), "clicked", G_CALLBACK(gaim_voice_chat_reject), vc); + gvc->call_pane = hbox; + gtk_box_pack_end(GTK_BOX(bbox), button, FALSE, 0, 0); + gtk_box_pack_end(GTK_BOX(gtkconv->tab_cont), hbox, FALSE, 0, 0); + + button = gtk_button_new_with_label(_("Accept call")); + g_signal_connect_swapped(G_OBJECT(button), "clicked", G_CALLBACK(gaim_voice_chat_accept), vc); + gtk_box_pack_end(GTK_BOX(bbox), button, FALSE, 0, 0); + + gtk_widget_show_all(hbox); + break; + case GAIM_MEDIA_STATE_IN_PROGRESS: + msg = g_strdup_printf(_("Connected to %s"), gaim_voice_chat_get_name(vc)); + gaim_conversation_write(conv, NULL, msg, GAIM_MESSAGE_SYSTEM, time(NULL)); + g_free(msg); + if (gvc->bbox) { + gtk_widget_destroy(gvc->bbox); + gvc->bbox = NULL; + button = gtk_button_new_with_label(_("End Call")); + g_signal_connect_swapped(G_OBJECT(button), "clicked", G_CALLBACK(gaim_voice_chat_terminate), vc); + gtk_box_pack_end(GTK_BOX(gvc->call_pane), button, FALSE, 0, 0); + gtk_widget_show(button); + } + button = gtk_check_button_new_with_mnemonic(_("_Mute")); + gtk_box_pack_start(GTK_BOX(gvc->call_pane), button, FALSE, 0, 0); + gtk_widget_show(button); + break; + default: + break; + } +} + + +static GaimMediaUiOps ui_ops = +{ + gaim_gtk_media_new_voice_chat, + gaim_gtk_media_destroy, + gaim_gtk_media_state_change +}; + +void gaim_gtk_media_init(void) +{ + gaim_debug_info("gtkmedia","Initialising\n"); + gaim_media_set_ui_ops(&ui_ops); +} + +#endif /* HAVE_VV */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/gtkmedia.h Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,46 @@ +/** + * @file media.h Voice and Video API + * @ingroup core + * + * gaim + * + * Gaim is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _GAIM_GTK_MEDIA_H_ +#define _GAIM_GTK_MEDIA_H_ + +#ifdef HAVE_VV + +#include "media.h" + +/*************************************************************************** + * @name GTK+ Media API + ***************************************************************************/ +/*@{*/ + +/** + * Initializes the GTK+ webcam system. + */ +void gaim_gtk_media_init(void); +/*@}*/ + +#endif /* HAVE_VV */ + +#endif /* _GAIM_GTK_MEDIA_H_ */
--- a/src/gtkstock.c Wed Nov 09 07:58:36 2005 +0000 +++ b/src/gtkstock.c Wed Nov 09 08:07:20 2005 +0000 @@ -96,6 +96,7 @@ { GAIM_STOCK_TEXT_SMALLER, "buttons", "text_smaller.png" }, { GAIM_STOCK_TYPED, "gaim", "typed.png" }, { GAIM_STOCK_TYPING, "gaim", "typing.png" }, + { GAIM_STOCK_VOICE_CHAT, "gaim", "phone.png" }, { GAIM_STOCK_STATUS_ONLINE, "gaim", "status-online.png" }, { GAIM_STOCK_STATUS_OFFLINE, "gaim", "status-offline.png" }, { GAIM_STOCK_STATUS_AWAY, "gaim", "status-away.png" },
--- a/src/gtkstock.h Wed Nov 09 07:58:36 2005 +0000 +++ b/src/gtkstock.h Wed Nov 09 08:07:20 2005 +0000 @@ -87,6 +87,7 @@ #define GAIM_STOCK_TYPED "gaim-typed" #define GAIM_STOCK_TYPING "gaim-typing" #define GAIM_STOCK_UPLOAD "gaim-upload" +#define GAIM_STOCK_VOICE_CHAT "gaim-voice-chat" #define GAIM_STOCK_WARN "gaim-warn" /*@}*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/media.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,212 @@ +/** + * @file media.h Voice and Video API + * @ingroup core + * + * gaim + * + * Gaim is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_VV + +#include "media.h" +#include "mediastream.h" +#include "msilbcdec.h" + + +/* msrtpsend.o and msrtprecv.o aren't used within the core, so + * the linker chooses not to link them. I want plugins to be able + * to depend on them, so I reference symbols from them here. */ +static void * dummy1 = ms_rtp_send_new; +static void * dummy2 = ms_rtp_recv_new; + +struct _GaimVoiceChat { + GaimConnection *gc; + char *name; + + GaimMediaState state; + + void *proto_data; + void *ui_data; + + MSFilter *speaker; + MSFilter *microphone; + MSSync *timer; +}; + +static GaimMediaUiOps *media_ui_ops = NULL; + +void gaim_media_init() +{ + ms_init(); + ms_ilbc_codec_init(); + ms_speex_codec_init(); + ortp_init(); +} + +GaimVoiceChat *gaim_voice_chat_new(GaimConnection *gc, const char *name) +{ + GaimVoiceChat *vc = g_new0(GaimVoiceChat, 1); + SndCard *card; + + vc->gc = gc; + vc->name = g_strdup(name); + + card = snd_card_manager_get_card(snd_card_manager,0); + vc->speaker = snd_card_create_write_filter(card); + vc->microphone = snd_card_create_read_filter(card); + vc->timer = ms_timer_new(); + ms_sync_attach(vc->timer, vc->microphone); + if (media_ui_ops) + media_ui_ops->new_voice_chat(vc); + return vc; +} + + + +void gaim_voice_chat_destroy(GaimVoiceChat *vc) +{ + if (media_ui_ops) + media_ui_ops->destroy(vc); + g_free(vc); +} + +const char *gaim_voice_chat_get_name(GaimVoiceChat *vc) +{ + return vc->name; +} + +void gaim_voice_chat_set_name(GaimVoiceChat *vc, const char *name) +{ + g_free(vc->name); + vc->name = g_strdup(name); +} + +GaimConnection *gaim_voice_chat_get_connection(GaimVoiceChat *vc) +{ + return vc->gc; +} + +void *gaim_voice_chat_get_ui_data(GaimVoiceChat *vc) +{ + return vc->ui_data; +} + +void gaim_voice_chat_set_ui_data(GaimVoiceChat *vc, void *data) +{ + vc->ui_data = data; +} + +void *gaim_voice_chat_get_proto_data(GaimVoiceChat *vc) +{ + return vc->proto_data; +} + +void gaim_voice_chat_set_proto_data(GaimVoiceChat *vc, void *data) +{ + vc->proto_data = data; +} + +void gaim_media_set_ui_ops(GaimMediaUiOps *ops) +{ + media_ui_ops = ops; +} + +GaimMediaUiOps *gaim_media_get_ui_ops(void) +{ + return media_ui_ops; +} + + +GaimMediaState gaim_voice_chat_get_state(GaimVoiceChat *vc) +{ + return vc->state; +} + +void gaim_voice_chat_accept(GaimVoiceChat *vc) +{ + GaimConnection *gc = gaim_voice_chat_get_connection(vc); + GaimPluginProtocolInfo *prpl_info = NULL; + + prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl); + + if (!prpl_info->media_prpl_ops || !prpl_info->media_prpl_ops->accept) + return; + prpl_info->media_prpl_ops->accept(vc); +} + +void gaim_voice_chat_reject(GaimVoiceChat *vc) +{ + GaimConnection *gc = gaim_voice_chat_get_connection(vc); + GaimPluginProtocolInfo *prpl_info = NULL; + + prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl); + + if (!prpl_info->media_prpl_ops || !prpl_info->media_prpl_ops->reject) + return; + prpl_info->media_prpl_ops->reject(vc); +} + + +void gaim_voice_chat_terminate(GaimVoiceChat *vc) +{ + GaimConnection *gc = gaim_voice_chat_get_connection(vc); + GaimPluginProtocolInfo *prpl_info = NULL; + + prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl); + + if (!prpl_info->media_prpl_ops || !prpl_info->media_prpl_ops->terminate) + return; + prpl_info->media_prpl_ops->terminate(vc); +} + + +void gaim_voice_chat_set_state(GaimVoiceChat *vc, GaimMediaState state) +{ + vc->state = state; + printf("State: %d\n",vc); + if (media_ui_ops) + media_ui_ops->state_change(vc, state); +} + +void gaim_voice_chat_get_filters(GaimVoiceChat *vc, MSFilter **microphone, MSFilter **speaker) +{ + if (microphone) *microphone = vc->microphone; + if (speaker) *speaker = vc->speaker; +} + +MSSync *gaim_voice_chat_get_timer(GaimVoiceChat *vc) +{ + return vc->timer; +} + +void *gaim_voice_chat_start_streams(GaimVoiceChat *vc) +{ + GaimConnection *gc = gaim_voice_chat_get_connection(vc); + GaimPluginProtocolInfo *prpl_info = NULL; + + prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl); + + if (prpl_info->media_prpl_ops && prpl_info->media_prpl_ops->init_filters) + prpl_info->media_prpl_ops->init_filters(vc); + + ms_start(vc->timer); +} + +#endif /* HAVE_VV */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/media.h Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,226 @@ +/** + * @file media.h Voice and Video API + * @ingroup core + * + * gaim + * + * Gaim is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _GAIM_MEDIA_H_ +#define _GAIM_MEDIA_H_ + +typedef struct _GaimVoiceChat GaimVoiceChat; +typedef struct _GaimMediaPrplOps GaimMediaPrplOps; + +#include "connection.h" + +/* Forward declarations so I needn't #include mediastreamer headers in + * nearly every single file */ +struct _MSFilter; +struct _MSSync; + +/** + * The state of a VoiceChat that should be reflected in the UI + */ +typedef enum { + GAIM_MEDIA_STATE_CALLING, /**< An outgoing call is waiting to be answered */ + GAIM_MEDIA_STATE_RECEIVING, /**< An incoming call is waiting to be answered */ + GAIM_MEDIA_STATE_IN_PROGRESS, /**< The call is connected */ + GAIM_MEDIA_STATE_ERROR, /**< Some error occured */ +} GaimMediaState; + +/** + * UI Operations + */ +typedef struct { + void (*new_voice_chat)(GaimVoiceChat *vc); /**< A new voice chat is created */ + void (*destroy)(GaimVoiceChat *vc); /**< The voice chat has been destroyed */ + void (*state_change)(GaimVoiceChat *vc, GaimMediaState state); /**< The state of the voice chat has changed */ +} GaimMediaUiOps; + +/** + * PRPL Operations + */ +struct _GaimMediaPrplOps { + void (*call)(GaimConnection *gc, const char *who); /**< Request an outgoing call to 'who' */ + void (*init_filters)(GaimVoiceChat *); /**< Create the media stream for the call */ + void (*accept)(GaimVoiceChat *); /**< Accept an incoming call */ + void (*reject)(GaimVoiceChat *); /**< Reject an incoming call */ + void (*terminate)(GaimVoiceChat *); /**< Terminate an in-progress call */ +}; + +#ifdef HAVE_VV + +/** + * Initializes mediastreamer and ortp + */ +void gaim_media_init(void); + +/**************************************************************************/ +/** @name Voice Chat API **************************************************/ +/**************************************************************************/ +/*@{*/ + +/** + * Creates a new voice chat + * This function creates a new voice chat object, and tells the UI about it. The UI + * probably won't want to do anything, until the state is changed to Incoming or Outgoing, + * but the UI should initialize any data structures it needs on this call + * + * @param gc The connection this chat is happening on + * @param name The person on the other end of the call + * @return The new voice chat + */ +GaimVoiceChat *gaim_voice_chat_new(GaimConnection *gc, const char *name); + +/** + * Destroys a voice chat + * + * @param vc The voice chat to destroy + */ +void gaim_voice_chat_destroy(GaimVoiceChat *vc); + +/** + * Acessor function of the name of the other user on the voice chat + * + * @param vc The voice chat + * @return The name + */ +const char *gaim_voice_chat_get_name(GaimVoiceChat *vc); + +/** + * Accessor for the GaimConnection of the voice chat + * + * @param vc The voice chat + * @return The GaimConnection + */ +GaimConnection *gaim_voice_chat_get_connection(GaimVoiceChat *vc); + +/** + * Accessor for the UI data + * + * @param vc The voice chat + * @return The UI data + */ +void *gaim_voice_chat_get_ui_data(GaimVoiceChat *vc); + +/** + * Mutator for the UI Data + * + * @param vc The voice chat + * @param data The data + */ +void gaim_voice_chat_set_ui_data(GaimVoiceChat *vc, void *data); + +/** + * Accessor for the protocol data + * + * @param vc The voice chat + * @return The protocol data + */ +void *gaim_voice_chat_get_proto_data(GaimVoiceChat *vc); + +/** + * Mutator for the protocol data + * + * @param vc The voice chat + * @param data The protocol data + */ +void gaim_voice_chat_set_proto_data(GaimVoiceChat *vc, void *data); + +/** + * Accessor for the state + * + * @param vc The voice chat + * @return The state + */ +GaimMediaState gaim_voice_chat_get_state(GaimVoiceChat *vc); + +/** + * Mutator for the state + * + * @param vc The voice chat + * @param state The state + */ +void gaim_voice_chat_set_state(GaimVoiceChat *vc, GaimMediaState state); + +/** + * Accepts an incoming voice chat + * + * @param vc The voice chat + */ +void gaim_voice_chat_accept(GaimVoiceChat *vc); + +/** + * Rejects an incoming voice chat + * + * @param vc The voice chat + */ +void gaim_voice_chat_reject(GaimVoiceChat *vc); + +/** + * Terminates an in-progress voice chat + * + * @param vc The voice chat + */ +void gaim_voice_chat_terminate(GaimVoiceChat *vc); + +/** + * Accessor for the microphone and speaker MSFilter objects + * + * @param vc The voice chat + * @param microphone A pointer to return the microphone filter in, or NULL. + * @param speaker A poitner to reutrn the speaker filter in, or NULL. + */ +void gaim_voice_chat_get_filters(GaimVoiceChat *vc, struct _MSFilter **microphone, struct _MSFilter **speaker); + +/** + * Accessor for the Mediastreamer timer + * + * @param vc The voice chat + * @return The timer + */ +struct _MSSync *gaim_voice_chat_get_timer(GaimVoiceChat *vc); + +/*@}*/ + +/**************************************************************************/ +/** @name UI Registration Functions */ +/**************************************************************************/ +/*@{*/ + +/** + * Sets the UI operations structure to be used for the buddy list. + * + * @param ops The ops struct. + */ +void gaim_media_set_ui_ops(GaimMediaUiOps *ops); + +/** + * Returns the UI operations structure to be used for the buddy list. + * + * @return The UI operations structure. + */ +GaimMediaUiOps *gaim_media_get_ui_ops(void); + +/*@}*/ + +#endif /* HAVE_VV */ + +#endif /* _GAIM_MEDIA_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/Makefile.am Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,53 @@ +EXTRA_DIST=Makefile.ms + +noinst_LTLIBRARIES = libmediastreamer.la + +useless_files=mstcpserv.c mstcpserv.h mstcpclient.c mstcpclient.h + +libmediastreamer_la_SOURCES=msfilter.c msfilter.h msutils.h waveheader.h\ + mscodec.c mscodec.h \ + mssoundread.c mssoundread.h \ + mssoundwrite.c mssoundwrite.h \ + msbuffer.c msbuffer.h \ + msqueue.c msqueue.h \ + msfifo.c msfifo.h \ + ms.c ms.h\ + mssync.c mssync.h \ + msnosync.c msnosync.h \ + msread.c msread.h \ + mswrite.c mswrite.h \ + mscopy.c mscopy.h \ + msosswrite.c msosswrite.h \ + msossread.c msossread.h \ + msringplayer.c msringplayer.h \ + msrtprecv.c msrtprecv.h \ + msrtpsend.c msrtpsend.h \ + msAlawenc.c msAlawenc.h g711common.h \ + msAlawdec.c msAlawdec.h g711common.h \ + msMUlawenc.c msMUlawenc.h g711common.h \ + msMUlawdec.c msMUlawdec.h g711common.h \ + mstimer.c mstimer.h \ + msqdispatcher.c msqdispatcher.h \ + msfdispatcher.c msfdispatcher.h \ + sndcard.c sndcard.h \ + osscard.c osscard.h\ + hpuxsndcard.c \ + alsacard.c alsacard.h \ + jackcard.c jackcard.h \ + audiostream.c mediastream.h \ + msspeexenc.c msspeexenc.h msspeexdec.c msspeexdec.h \ + msilbcdec.c msilbcdec.h msilbcenc.c msilbcenc.h + +# msGSMdecoder.c msGSMdecoder.h +# msGSMencoder.c msGSMencoder.h +# msLPC10encoder.c msLPC10encoder.h +# msLPC10decoder.c msLPC10decoder.h + +libmediastreamer_la_LDFLAGS = -export-dynamic + +libmediastreamer_la_LIBADD= $(GLIB_LIBS) $(VV_LIBS) + +AM_CFLAGS=$(GLIB_CFLAGS) -DG_LOG_DOMAIN=\"MediaStreamer\" $(VV_CFLAGS) $(IPV6_CFLAGS) -DHAVE_GLIB + + +INCLUDES= -I$(top_srcdir) -I$(top_srcdir)/mediastreamer $(VV_CFLAGS) \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/affine.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,144 @@ +/* + * affine.c -- Affine Transforms for 2d objects + * Copyright (C) 2002 Charles Yates <charles.yates@pandora.be> + * Portions Copyright (C) 2003 Dan Dennedy <dan@dennedy.org> + * ported from C++ to C + * wrote affine_scale() + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "affine.h" + +static inline void Multiply( affine_transform_t *this, affine_transform_t *that ) +{ + double output[2][2]; + register int i, j; + + for ( i = 0; i < 2; i ++ ) + for ( j = 0; j < 2; j ++ ) + output[ i ][ j ] = this->matrix[ i ][ 0 ] * that->matrix[ j ][ 0 ] + + this->matrix[ i ][ 1 ] * that->matrix[ j ][ 1 ]; + + this->matrix[ 0 ][ 0 ] = output[ 0 ][ 0 ]; + this->matrix[ 0 ][ 1 ] = output[ 0 ][ 1 ]; + this->matrix[ 1 ][ 0 ] = output[ 1 ][ 0 ]; + this->matrix[ 1 ][ 1 ] = output[ 1 ][ 1 ]; +} + +void affine_transform_init( affine_transform_t *this ) +{ + this->matrix[ 0 ][ 0 ] = 1; + this->matrix[ 0 ][ 1 ] = 0; + this->matrix[ 1 ][ 0 ] = 0; + this->matrix[ 1 ][ 1 ] = 1; +} + +// Rotate by a given angle +void affine_transform_rotate( affine_transform_t *this, double angle ) +{ + affine_transform_t affine; + affine.matrix[ 0 ][ 0 ] = cos( angle * M_PI / 180 ); + affine.matrix[ 0 ][ 1 ] = 0 - sin( angle * M_PI / 180 ); + affine.matrix[ 1 ][ 0 ] = sin( angle * M_PI / 180 ); + affine.matrix[ 1 ][ 1 ] = cos( angle * M_PI / 180 ); + Multiply( this, &affine ); +} + +// Shear by a given value +void affine_transform_shear( affine_transform_t *this, double shear ) +{ + affine_transform_t affine; + affine.matrix[ 0 ][ 0 ] = 1; + affine.matrix[ 0 ][ 1 ] = shear; + affine.matrix[ 1 ][ 0 ] = 0; + affine.matrix[ 1 ][ 1 ] = 1; + Multiply( this, &affine ); +} + +void affine_transform_scale( affine_transform_t *this, double sx, double sy ) +{ + affine_transform_t affine; + affine.matrix[ 0 ][ 0 ] = sx; + affine.matrix[ 0 ][ 1 ] = 0; + affine.matrix[ 1 ][ 0 ] = 0; + affine.matrix[ 1 ][ 1 ] = sy; + Multiply( this, &affine ); +} + +// Obtain the mapped x coordinate of the input +double affine_transform_mapx( affine_transform_t *this, int x, int y ) +{ + return this->matrix[0][0] * x + this->matrix[0][1] * y; +} + +// Obtain the mapped y coordinate of the input +double affine_transform_mapy( affine_transform_t *this, int x, int y ) +{ + return this->matrix[1][0] * x + this->matrix[1][1] * y; +} + +#define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x))) + +void affine_scale( const unsigned char *src, unsigned char *dest, int src_width, int src_height, int dest_width, int dest_height, int bpp ) +{ + affine_transform_t affine; + double scale_x = (double) dest_width / (double) src_width; + double scale_y = (double) dest_height / (double) src_height; + register unsigned char *d = dest; + register const unsigned char *s = src; + register int i, j, k, x, y; + + affine_transform_init( &affine ); + + if ( scale_x <= 1.0 && scale_y <= 1.0 ) + { + affine_transform_scale( &affine, scale_x, scale_y ); + + for( j = 0; j < src_height; j++ ) + for( i = 0; i < src_width; i++ ) + { + x = (int) ( affine_transform_mapx( &affine, i - src_width/2, j - src_height/2 ) ); + y = (int) ( affine_transform_mapy( &affine, i - src_width/2, j - src_height/2 ) ); + x += dest_width/2; + x = CLAMP( x, 0, dest_width); + y += dest_height/2; + y = CLAMP( y, 0, dest_height); + s = src + (j*src_width*bpp) + i*bpp; // + (bpp-1); + d = dest + y*dest_width*bpp + x*bpp; + for ( k = 0; k < bpp; k++ ) + *d++ = *s++; + } + } + else if ( scale_x > 1.0 && scale_y > 1.0 ) + { + affine_transform_scale( &affine, 1.0/scale_x, 1.0/scale_y ); + + for( y = 0; y < dest_height; y++ ) + for( x = 0; x < dest_width; x++ ) + { + i = (int) ( affine_transform_mapx( &affine, x - dest_width/2, y - dest_height/2 ) ); + j = (int) ( affine_transform_mapy( &affine, x - dest_width/2, y - dest_height/2 ) ); + i += src_width/2; + i = CLAMP( i, 0, dest_width); + j += src_height/2; + j = CLAMP( j, 0, dest_height); + s = src + (j*src_width*bpp) + i*bpp; // + (bpp-1); + d = dest + y*dest_width*bpp + x*bpp; + for ( k = 0; k < bpp; k++ ) + *d++ = *s++; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/affine.h Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,43 @@ +/* + * affine.h -- Affine Transforms for 2d objects + * Copyright (C) 2002 Charles Yates <charles.yates@pandora.be> + * Portions Copyright (C) 2003 Dan Dennedy <dan@dennedy.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _AFFINE_H +#define _AFFINE_H + +#include <math.h> + +/** Affine transforms for 2d image manipulation. Current provides shearing and + rotating support. +*/ + +typedef struct { + double matrix[2][2]; +} affine_transform_t; + +void affine_transform_init( affine_transform_t *this ); +void affine_transform_rotate( affine_transform_t *this, double angle ); +void affine_transform_shear( affine_transform_t *this, double shear ); +void affine_transform_scale( affine_transform_t *this, double sx, double sy ); +double affine_transform_mapx( affine_transform_t *this, int x, int y ); +double affine_transform_mapy( affine_transform_t *this, int x, int y ); +void affine_scale( const unsigned char *src, unsigned char *dest, int src_width, int src_height, int dest_width, int dest_height, int bpp ); + +#endif +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/alsacard.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,640 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + +#include "alsacard.h" + +#ifdef HAVE_ALSA_ASOUNDLIB_H + +static gchar *over_pcmdev=NULL; + +#include "msossread.h" +#include "msosswrite.h" + +#include <signal.h> + +int __alsa_card_write(AlsaCard *obj,char *buf,int size); + +int alsa_set_params(AlsaCard *obj, int rw, int bits, int stereo, int rate) +{ + snd_pcm_hw_params_t *hwparams=NULL; + snd_pcm_sw_params_t *swparams=NULL; + snd_pcm_t *pcm_handle; + gint dir,exact_value; + gint channels; + gint fsize=0; + gint periods=8; + gint periodsize=256; + gint err; + int format; + + if (rw) { + pcm_handle=obj->write_handle; + } + else pcm_handle=obj->read_handle; + + /* Allocate the snd_pcm_hw_params_t structure on the stack. */ + snd_pcm_hw_params_alloca(&hwparams); + + /* Init hwparams with full configuration space */ + if (snd_pcm_hw_params_any(pcm_handle, hwparams) < 0) { + g_warning("alsa_set_params: Cannot configure this PCM device.\n"); + return(-1); + } + + if (snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) { + g_warning("alsa_set_params: Error setting access.\n"); + return(-1); + } + /* Set sample format */ +#ifdef WORDS_BIGENDIAN + format=SND_PCM_FORMAT_S16_BE; +#else + format=SND_PCM_FORMAT_S16_LE; +#endif + if (snd_pcm_hw_params_set_format(pcm_handle, hwparams, format) < 0) { + g_warning("alsa_set_params: Error setting format.\n"); + return(-1); + } + /* Set number of channels */ + if (stereo) channels=2; + else channels=1; + if (snd_pcm_hw_params_set_channels(pcm_handle, hwparams, channels) < 0) { + g_warning("alsa_set_params: Error setting channels.\n"); + return(-1); + } + /* Set sample rate. If the exact rate is not supported */ + /* by the hardware, use nearest possible rate. */ + exact_value=rate; + dir=0; + if ((err=snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &exact_value, &dir))<0){ + g_warning("alsa_set_params: Error setting rate to %i:%s",rate,snd_strerror(err)); + return -1; + } + if (dir != 0) { + g_warning("alsa_set_params: The rate %d Hz is not supported by your hardware.\n " + "==> Using %d Hz instead.\n", rate, exact_value); + } + /* choose greater period size when rate is high */ + periodsize=periodsize*(rate/8000); + + /* Set buffer size (in frames). The resulting latency is given by */ + /* latency = periodsize * periods / (rate * bytes_per_frame) */ + /* + fsize=periodsize * periods; + exact_value=fsize; + if ((err=snd_pcm_hw_params_set_buffer_size_near(pcm_handle, hwparams,&exact_value)) < 0) { + g_warning("alsa_set_params: Error setting buffer size:%s",snd_strerror(err)); + return(-1); + } + if (fsize!= exact_value) { + g_warning("alsa_set_params: The buffer size %d is not supported by your hardware.\n " + "==> Using %d instead.\n", fsize, exact_value); + } + */ + /* set period size */ + exact_value=periodsize; + dir=0; + if (snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &exact_value, &dir) < 0) { + g_warning("alsa_set_params: Error setting period size.\n"); + return(-1); + } + if (dir != 0) { + g_warning("alsa_set_params: The period size %d is not supported by your hardware.\n " + "==> Using %d instead.\n", periodsize, exact_value); + } + periodsize=exact_value; + /* Set number of periods. Periods used to be called fragments. */ + exact_value=periods; + dir=0; + if (snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &exact_value, &dir) < 0) { + g_warning("alsa_set_params: Error setting periods.\n"); + return(-1); + } + if (dir != 0) { + g_warning("alsa_set_params: The number of periods %d is not supported by your hardware.\n " + "==> Using %d instead.\n", periods, exact_value); + } + /* Apply HW parameter settings to */ + /* PCM device and prepare device */ + if ((err=snd_pcm_hw_params(pcm_handle, hwparams)) < 0) { + g_warning("alsa_set_params: Error setting HW params:%s",snd_strerror(err)); + return(-1); + } + /*prepare sw params */ + if (rw){ + snd_pcm_sw_params_alloca(&swparams); + snd_pcm_sw_params_current(pcm_handle, swparams); + if ((err=snd_pcm_sw_params_set_start_threshold(pcm_handle, swparams,periodsize*2 ))<0){ + g_warning("alsa_set_params: Error setting start threshold:%s",snd_strerror(err)); + return -1; + } + if ((err=snd_pcm_sw_params(pcm_handle, swparams))<0){ + g_warning("alsa_set_params: Error setting SW params:%s",snd_strerror(err)); + return(-1); + } + } + obj->frame_size=channels*(bits/8); + SND_CARD(obj)->bsize=periodsize*obj->frame_size; + //SND_CARD(obj)->bsize=4096; + obj->frames=periodsize; + g_message("alsa_set_params: blocksize=%i.",SND_CARD(obj)->bsize); + return SND_CARD(obj)->bsize; +} + +int alsa_card_open_r(AlsaCard *obj,int bits,int stereo,int rate) +{ + int bsize; + int err; + snd_pcm_t *pcm_handle; + gchar *pcmdev; + if (over_pcmdev!=NULL) pcmdev=over_pcmdev; + else pcmdev=obj->pcmdev; + + if (snd_pcm_open(&pcm_handle, pcmdev,SND_PCM_STREAM_CAPTURE,SND_PCM_NONBLOCK) < 0) { + g_warning("alsa_card_open_r: Error opening PCM device %s\n",obj->pcmdev ); + return -1; + } + g_return_val_if_fail(pcm_handle!=NULL,-1); + obj->read_handle=pcm_handle; + if ((bsize=alsa_set_params(obj,0,bits,stereo,rate))<0){ + snd_pcm_close(pcm_handle); + obj->read_handle=NULL; + return -1; + } + obj->readbuf=g_malloc0(bsize); + + err=snd_pcm_start(obj->read_handle); + if (err<0){ + g_warning("Cannot start read pcm: %s", snd_strerror(err)); + } + obj->readpos=0; + SND_CARD(obj)->bsize=bsize; + SND_CARD(obj)->flags|=SND_CARD_FLAGS_OPENED; + return 0; +} + +int alsa_card_open_w(AlsaCard *obj,int bits,int stereo,int rate) +{ + int err,bsize; + snd_pcm_t *pcm_handle; + gchar *pcmdev; + if (over_pcmdev!=NULL) pcmdev=over_pcmdev; + else pcmdev=obj->pcmdev; + + if (snd_pcm_open(&pcm_handle, pcmdev,SND_PCM_STREAM_PLAYBACK,SND_PCM_NONBLOCK) < 0) { + g_warning("alsa_card_open_w: Error opening PCM device %s\n", obj->pcmdev); + return -1; + } + obj->write_handle=pcm_handle; + if ((bsize=alsa_set_params(obj,1,bits,stereo,rate))<0){ + snd_pcm_close(pcm_handle); + obj->write_handle=NULL; + return -1; + } + obj->writebuf=g_malloc0(bsize); + + obj->writepos=0; + SND_CARD(obj)->bsize=bsize; + SND_CARD(obj)->flags|=SND_CARD_FLAGS_OPENED; + return 0; +} + + +void alsa_card_set_blocking_mode(AlsaCard *obj, gboolean yesno){ + if (obj->read_handle!=NULL) snd_pcm_nonblock(obj->read_handle,!yesno); + if (obj->write_handle!=NULL) snd_pcm_nonblock(obj->write_handle,!yesno); +} + +void alsa_card_close_r(AlsaCard *obj) +{ + if (obj->read_handle!=NULL){ + snd_pcm_close(obj->read_handle); + obj->read_handle=NULL; + g_free(obj->readbuf); + obj->readbuf=NULL; + } +} + +void alsa_card_close_w(AlsaCard *obj) +{ + if (obj->write_handle!=NULL){ + snd_pcm_close(obj->write_handle); + obj->write_handle=NULL; + g_free(obj->writebuf); + obj->writebuf=NULL; + } +} + +int alsa_card_probe(AlsaCard *obj,int bits,int stereo,int rate) +{ + int ret; + ret=alsa_card_open_w(obj,bits,stereo,rate); + if (ret<0) return -1; + ret=SND_CARD(obj)->bsize; + alsa_card_close_w(obj); + return ret; +} + + +void alsa_card_destroy(AlsaCard *obj) +{ + snd_card_uninit(SND_CARD(obj)); + g_free(obj->pcmdev); + if (obj->readbuf!=0) g_free(obj->readbuf); + if (obj->writebuf!=0) g_free(obj->writebuf); +} + +gboolean alsa_card_can_read(AlsaCard *obj) +{ + int frames; + g_return_val_if_fail(obj->read_handle!=NULL,0); + if (obj->readpos!=0) return TRUE; + if ( frames=snd_pcm_avail_update(obj->read_handle)>=obj->frames) return 1; + //g_message("frames=%i",frames); + return 0; +} + + + +int __alsa_card_read(AlsaCard *obj,char *buf,int bsize) +{ + int err; + sigset_t set; + sigemptyset(&set); + sigaddset(&set,SIGALRM); + sigprocmask(SIG_BLOCK,&set,NULL); + err=snd_pcm_readi(obj->read_handle,buf,bsize/obj->frame_size); + if (err<0) { + if (err!=-EPIPE){ + g_warning("alsa_card_read: snd_pcm_readi() failed:%s.",snd_strerror(err)); + } + snd_pcm_prepare(obj->read_handle); + err=snd_pcm_readi(obj->read_handle,buf,bsize/obj->frame_size); + if (err<0) g_warning("alsa_card_read: snd_pcm_readi() failed:%s.",snd_strerror(err)); + } + sigprocmask(SIG_UNBLOCK,&set,NULL); + return err*obj->frame_size; +} + +int alsa_card_read(AlsaCard *obj,char *buf,int size) +{ + int err; + gint bsize=SND_CARD(obj)->bsize; + g_return_val_if_fail(obj->read_handle!=NULL,-1); + if (size<bsize){ + gint canread=MIN(bsize-obj->readpos,size); + + if (obj->readpos==0){ + err=__alsa_card_read(obj,obj->readbuf,bsize); + } + + memcpy(buf,&obj->readbuf[obj->readpos],canread); + obj->readpos+=canread; + if (obj->readpos>=bsize) obj->readpos=0; + return canread; + }else{ + err=__alsa_card_read(obj,buf,size); + return err; + } + +} + +int __alsa_card_write(AlsaCard *obj,char *buf,int size) +{ + int err; + sigset_t set; + sigemptyset(&set); + sigaddset(&set,SIGALRM); + sigprocmask(SIG_BLOCK,&set,NULL); + if ((err=snd_pcm_writei(obj->write_handle,buf,size/obj->frame_size))<0){ + if (err!=-EPIPE){ + g_warning("alsa_card_write: snd_pcm_writei() failed:%s.",snd_strerror(err)); + } + snd_pcm_prepare(obj->write_handle); + err=snd_pcm_writei(obj->write_handle,buf,size/obj->frame_size); + if (err<0) g_warning("alsa_card_write: Error writing sound buffer (size=%i):%s",size,snd_strerror(err)); + + } + sigprocmask(SIG_UNBLOCK,&set,NULL); + return err; +} + +int alsa_card_write(AlsaCard *obj,char *buf,int size) +{ + int err; + gint bsize=SND_CARD(obj)->bsize; + g_return_val_if_fail(obj->write_handle!=NULL,-1); + if (size<bsize){ + gint canwrite; + + canwrite=MIN(bsize-obj->writepos,size); + memcpy(&obj->writebuf[obj->writepos],buf,canwrite); + obj->writepos+=canwrite; + if (obj->writepos>=bsize){ + err=__alsa_card_write(obj,obj->writebuf,bsize); + obj->writepos=0; + } + return canwrite; + }else{ + return __alsa_card_write(obj,buf,bsize); + } +} + +snd_mixer_t *alsa_mixer_open(AlsaCard *obj){ + snd_mixer_t *mixer=NULL; + int err; + err=snd_mixer_open(&mixer,0); + if (err<0){ + g_warning("Could not open alsa mixer: %s",snd_strerror(err)); + return NULL; + } + if ((err = snd_mixer_attach (mixer, obj->mixdev)) < 0){ + g_warning("Could not attach mixer to card: %s",snd_strerror(err)); + snd_mixer_close(mixer); + return NULL; + } + if ((err = snd_mixer_selem_register (mixer, NULL, NULL)) < 0){ + g_warning("snd_mixer_selem_register: %s",snd_strerror(err)); + snd_mixer_close(mixer); + return NULL; + } + if ((err = snd_mixer_load (mixer)) < 0){ + g_warning("snd_mixer_load: %s",snd_strerror(err)); + snd_mixer_close(mixer); + return NULL; + } + obj->mixer=mixer; + return mixer; +} + +void alsa_mixer_close(AlsaCard *obj){ + snd_mixer_close(obj->mixer); + obj->mixer=NULL; +} + +typedef enum {CAPTURE, PLAYBACK, CAPTURE_SWITCH, PLAYBACK_SWITCH} MixerAction; + +static gint get_mixer_element(snd_mixer_t *mixer,const char *name, MixerAction action){ + long value=0; + const char *elemname; + snd_mixer_elem_t *elem; + int err; + long sndMixerPMin; + long sndMixerPMax; + long newvol; + elem=snd_mixer_first_elem(mixer); + while (elem!=NULL){ + elemname=snd_mixer_selem_get_name(elem); + //g_message("Found alsa mixer element %s.",elemname); + if (strcmp(elemname,name)==0){ + switch (action){ + case CAPTURE: + if (snd_mixer_selem_has_capture_volume(elem)){ + snd_mixer_selem_get_playback_volume_range(elem, &sndMixerPMin, &sndMixerPMax); + err=snd_mixer_selem_get_capture_volume(elem,SND_MIXER_SCHN_UNKNOWN,&newvol); + newvol-=sndMixerPMin; + value=(100*newvol)/(sndMixerPMax-sndMixerPMin); + if (err<0) g_warning("Could not get capture volume for %s:%s",name,snd_strerror(err)); + //else g_message("Succesfully get capture level for %s.",elemname); + break; + } + break; + case PLAYBACK: + if (snd_mixer_selem_has_playback_volume(elem)){ + snd_mixer_selem_get_playback_volume_range(elem, &sndMixerPMin, &sndMixerPMax); + err=snd_mixer_selem_get_playback_volume(elem,SND_MIXER_SCHN_FRONT_LEFT,&newvol); + newvol-=sndMixerPMin; + value=(100*newvol)/(sndMixerPMax-sndMixerPMin); + if (err<0) g_warning("Could not get playback volume for %s:%s",name,snd_strerror(err)); + //else g_message("Succesfully get playback level for %s.",elemname); + break; + } + break; + case CAPTURE_SWITCH: + + break; + } + } + elem=snd_mixer_elem_next(elem); + } + + return value; +} + + +static void set_mixer_element(snd_mixer_t *mixer,const char *name, gint level,MixerAction action){ + const char *elemname; + snd_mixer_elem_t *elem; + int tmp; + long sndMixerPMin; + long sndMixerPMax; + long newvol; + + elem=snd_mixer_first_elem(mixer); + + while (elem!=NULL){ + elemname=snd_mixer_selem_get_name(elem); + //g_message("Found alsa mixer element %s.",elemname); + if (strcmp(elemname,name)==0){ + switch(action){ + case CAPTURE: + if (snd_mixer_selem_has_capture_volume(elem)){ + snd_mixer_selem_get_playback_volume_range(elem, &sndMixerPMin, &sndMixerPMax); + newvol=(((sndMixerPMax-sndMixerPMin)*level)/100)+sndMixerPMin; + snd_mixer_selem_set_capture_volume_all(elem,newvol); + //g_message("Succesfully set capture level for %s.",elemname); + return; + } + break; + case PLAYBACK: + if (snd_mixer_selem_has_playback_volume(elem)){ + snd_mixer_selem_get_playback_volume_range(elem, &sndMixerPMin, &sndMixerPMax); + newvol=(((sndMixerPMax-sndMixerPMin)*level)/100)+sndMixerPMin; + snd_mixer_selem_set_playback_volume_all(elem,newvol); + //g_message("Succesfully set playback level for %s.",elemname); + return; + } + break; + case CAPTURE_SWITCH: + if (snd_mixer_selem_has_capture_switch(elem)){ + snd_mixer_selem_set_capture_switch_all(elem,level); + //g_message("Succesfully set capture switch for %s.",elemname); + } + break; + case PLAYBACK_SWITCH: + if (snd_mixer_selem_has_playback_switch(elem)){ + snd_mixer_selem_set_playback_switch_all(elem,level); + //g_message("Succesfully set capture switch for %s.",elemname); + } + break; + + } + } + elem=snd_mixer_elem_next(elem); + } + + return ; +} + + +void alsa_card_set_level(AlsaCard *obj,gint way,gint a) +{ + snd_mixer_t *mixer; + mixer=alsa_mixer_open(obj); + if (mixer==NULL) return ; + switch(way){ + case SND_CARD_LEVEL_GENERAL: + set_mixer_element(mixer,"Master",a,PLAYBACK); + break; + case SND_CARD_LEVEL_INPUT: + set_mixer_element(mixer,"Capture",a,CAPTURE); + break; + case SND_CARD_LEVEL_OUTPUT: + set_mixer_element(mixer,"PCM",a,PLAYBACK); + break; + default: + g_warning("oss_card_set_level: unsupported command."); + } + alsa_mixer_close(obj); +} + +gint alsa_card_get_level(AlsaCard *obj,gint way) +{ + snd_mixer_t *mixer; + gint value; + mixer=alsa_mixer_open(obj); + if (mixer==NULL) return 0; + switch(way){ + case SND_CARD_LEVEL_GENERAL: + value=get_mixer_element(mixer,"Master",PLAYBACK); + break; + case SND_CARD_LEVEL_INPUT: + value=get_mixer_element(mixer,"Capture",CAPTURE); + break; + case SND_CARD_LEVEL_OUTPUT: + value=get_mixer_element(mixer,"PCM",PLAYBACK); + break; + default: + g_warning("oss_card_set_level: unsupported command."); + } + alsa_mixer_close(obj); + return value; +} + +void alsa_card_set_source(AlsaCard *obj,int source) +{ + snd_mixer_t *mixer; + mixer=alsa_mixer_open(obj); + if (mixer==NULL) return; + switch (source){ + case 'm': + set_mixer_element(mixer,"Mic",1,CAPTURE_SWITCH); + set_mixer_element(mixer,"Capture",1,CAPTURE_SWITCH); + break; + case 'l': + set_mixer_element(mixer,"Line",1,CAPTURE_SWITCH); + set_mixer_element(mixer,"Capture",1,CAPTURE_SWITCH); + break; + } +} + +MSFilter *alsa_card_create_read_filter(AlsaCard *card) +{ + MSFilter *f=ms_oss_read_new(); + ms_oss_read_set_device(MS_OSS_READ(f),SND_CARD(card)->index); + return f; +} + +MSFilter *alsa_card_create_write_filter(AlsaCard *card) +{ + MSFilter *f=ms_oss_write_new(); + ms_oss_write_set_device(MS_OSS_WRITE(f),SND_CARD(card)->index); + return f; +} + + +SndCard * alsa_card_new(gint devid) +{ + AlsaCard * obj; + SndCard *base; + int err; + gchar *name=NULL; + + /* carefull: this is an alsalib call despite its name! */ + err=snd_card_get_name(devid,&name); + if (err<0) { + return NULL; + } + obj= g_new0(AlsaCard,1); + base= SND_CARD(obj); + snd_card_init(base); + + base->card_name=g_strdup_printf("%s (Advanced Linux Sound Architecture)",name); + base->_probe=(SndCardOpenFunc)alsa_card_probe; + base->_open_r=(SndCardOpenFunc)alsa_card_open_r; + base->_open_w=(SndCardOpenFunc)alsa_card_open_w; + base->_can_read=(SndCardPollFunc)alsa_card_can_read; + base->_set_blocking_mode=(SndCardSetBlockingModeFunc)alsa_card_set_blocking_mode; + base->_read=(SndCardIOFunc)alsa_card_read; + base->_write=(SndCardIOFunc)alsa_card_write; + base->_close_r=(SndCardCloseFunc)alsa_card_close_r; + base->_close_w=(SndCardCloseFunc)alsa_card_close_w; + base->_set_rec_source=(SndCardMixerSetRecSourceFunc)alsa_card_set_source; + base->_set_level=(SndCardMixerSetLevelFunc)alsa_card_set_level; + base->_get_level=(SndCardMixerGetLevelFunc)alsa_card_get_level; + base->_destroy=(SndCardDestroyFunc)alsa_card_destroy; + base->_create_read_filter=(SndCardCreateFilterFunc)alsa_card_create_read_filter; + base->_create_write_filter=(SndCardCreateFilterFunc)alsa_card_create_write_filter; + + + obj->pcmdev=g_strdup_printf("plughw:%i,0",devid); + obj->mixdev=g_strdup_printf("hw:%i",devid); + obj->readbuf=NULL; + obj->writebuf=NULL; + return base; +} + + +gint alsa_card_manager_init(SndCardManager *m, gint index) +{ + gint devindex; + gint i; + gint found=0; + gchar *name=NULL; + for(devindex=0;index<MAX_SND_CARDS && devindex<MAX_SND_CARDS ;devindex++){ + if (snd_card_get_name(devindex,&name)==0){ + g_message("Found ALSA device: %s",name); + m->cards[index]=alsa_card_new(devindex); + m->cards[index]->index=index; + found++; + index++; + } + } + return found; +} + +void alsa_card_manager_set_default_pcm_device(const gchar *pcmdev){ + if (over_pcmdev!=NULL){ + g_free(over_pcmdev); + } + over_pcmdev=g_strdup(pcmdev); +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/alsacard.h Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,50 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + +#include <config.h> + +#ifdef HAVE_ALSA_ASOUNDLIB_H + +#include "sndcard.h" +#define ALSA_PCM_NEW_HW_PARAMS_API +#include <alsa/asoundlib.h> +struct _AlsaCard +{ + SndCard parent; + gchar *pcmdev; + gchar *mixdev; + snd_pcm_t *read_handle; + snd_pcm_t *write_handle; + gint frame_size; + gint frames; + gchar *readbuf; + gint readpos; + gchar *writebuf; + gint writepos; + snd_mixer_t *mixer; +}; + +typedef struct _AlsaCard AlsaCard; + +SndCard *alsa_card_new(gint dev_id); +gint alsa_card_manager_init(SndCardManager *m, gint index); +void alsa_card_manager_set_default_pcm_device(const gchar *pcmdev); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/audiostream.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,341 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + + +#include "mediastream.h" +#ifdef INET6 + #include <sys/types.h> + #include <sys/socket.h> + #include <netdb.h> +#endif + + +#define MAX_RTP_SIZE 1500 + +/* this code is not part of the library itself, it is part of the mediastream program */ +void audio_stream_free(AudioStream *stream) +{ + RtpSession *s; + RtpSession *destroyed=NULL; + if (stream->rtprecv!=NULL) { + s=ms_rtp_recv_get_session(MS_RTP_RECV(stream->rtprecv)); + if (s!=NULL){ + destroyed=s; + rtp_session_destroy(s); + } + ms_filter_destroy(stream->rtprecv); + } + if (stream->rtpsend!=NULL) { + s=ms_rtp_send_get_session(MS_RTP_SEND(stream->rtpsend)); + if (s!=NULL){ + if (s!=destroyed) + rtp_session_destroy(s); + } + ms_filter_destroy(stream->rtpsend); + } + if (stream->soundread!=NULL) ms_filter_destroy(stream->soundread); + if (stream->soundwrite!=NULL) ms_filter_destroy(stream->soundwrite); + if (stream->encoder!=NULL) ms_filter_destroy(stream->encoder); + if (stream->decoder!=NULL) ms_filter_destroy(stream->decoder); + if (stream->timer!=NULL) ms_sync_destroy(stream->timer); + g_free(stream); +} + +static int dtmf_tab[16]={'0','1','2','3','4','5','6','7','8','9','*','#','A','B','C','D'}; + +static void on_dtmf_received(RtpSession *s,gint dtmf,gpointer user_data) +{ + AudioStream *stream=(AudioStream*)user_data; + if (dtmf>15){ + g_warning("Unsupported telephone-event type."); + return; + } + g_message("Receiving dtmf %c.",dtmf_tab[dtmf]); + if (stream!=NULL){ + if (strcmp(stream->soundwrite->klass->name,"OssWrite")==0) + ms_oss_write_play_dtmf(MS_OSS_WRITE(stream->soundwrite),dtmf_tab[dtmf]); + } +} + +static void on_timestamp_jump(RtpSession *s,guint32* ts, gpointer user_data) +{ + g_warning("The remote sip-phone has send data with a future timestamp: %u," + "resynchronising session.",*ts); + rtp_session_reset(s); +} + +static const char *ip4local="0.0.0.0"; +static const char *ip6local="::"; + +const char *get_local_addr_for(const char *remote) +{ + const char *ret; +#ifdef INET6 + char num[8]; + struct addrinfo hints, *res0; + int err; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + err = getaddrinfo(remote,"8000", &hints, &res0); + if (err!=0) { + g_warning ("get_local_addr_for: %s", gai_strerror(err)); + return ip4local; + } + ret=(res0->ai_addr->sa_family==AF_INET6) ? ip6local : ip4local; + freeaddrinfo(res0); +#else + ret=ip4local; +#endif + return ret; +} + +void create_duplex_rtpsession(RtpProfile *profile, int locport,char *remip,int remport, + int payload,int jitt_comp, + RtpSession **recvsend){ + RtpSession *rtpr; + rtpr=rtp_session_new(RTP_SESSION_SENDRECV); + rtp_session_max_buf_size_set(rtpr,MAX_RTP_SIZE); + rtp_session_set_profile(rtpr,profile); + rtp_session_set_local_addr(rtpr,get_local_addr_for(remip),locport); + if (remport>0) rtp_session_set_remote_addr(rtpr,remip,remport); + rtp_session_set_scheduling_mode(rtpr,0); + rtp_session_set_blocking_mode(rtpr,0); + rtp_session_set_payload_type(rtpr,payload); + rtp_session_set_jitter_compensation(rtpr,jitt_comp); + rtp_session_enable_adaptive_jitter_compensation(rtpr,TRUE); + /*rtp_session_signal_connect(rtpr,"timestamp_jump",(RtpCallback)on_timestamp_jump,NULL);*/ + *recvsend=rtpr; +} + +void create_rtp_sessions(RtpProfile *profile, int locport,char *remip,int remport, + int payload,int jitt_comp, + RtpSession **recv, RtpSession **send){ + RtpSession *rtps,*rtpr; + PayloadType *pt; + /* creates two rtp filters to recv send streams (remote part)*/ + + rtps=rtp_session_new(RTP_SESSION_SENDONLY); + rtp_session_max_buf_size_set(rtps,MAX_RTP_SIZE); + rtp_session_set_profile(rtps,profile); +#ifdef INET6 + rtp_session_set_local_addr(rtps,"::",locport+2); +#else + rtp_session_set_local_addr(rtps,"0.0.0.0",locport+2); +#endif + rtp_session_set_remote_addr(rtps,remip,remport); + rtp_session_set_scheduling_mode(rtps,0); + rtp_session_set_blocking_mode(rtps,0); + rtp_session_set_payload_type(rtps,payload); + rtp_session_set_jitter_compensation(rtps,jitt_comp); + + rtpr=rtp_session_new(RTP_SESSION_RECVONLY); + rtp_session_max_buf_size_set(rtpr,MAX_RTP_SIZE); + rtp_session_set_profile(rtpr,profile); +#ifdef INET6 + rtp_session_set_local_addr(rtpr,"::",locport); +#else + rtp_session_set_local_addr(rtpr,"0.0.0.0",locport); +#endif + rtp_session_set_scheduling_mode(rtpr,0); + rtp_session_set_blocking_mode(rtpr,0); + rtp_session_set_payload_type(rtpr,payload); + rtp_session_set_jitter_compensation(rtpr,jitt_comp); + rtp_session_signal_connect(rtpr,"telephone-event",(RtpCallback)on_dtmf_received,NULL); + rtp_session_signal_connect(rtpr,"timestamp_jump",(RtpCallback)on_timestamp_jump,NULL); + *recv=rtpr; + *send=rtps; + +} + + +AudioStream * audio_stream_start_full(RtpProfile *profile, int locport,char *remip,int remport, + int payload,int jitt_comp, gchar *infile, gchar *outfile, SndCard *playcard, SndCard *captcard) +{ + AudioStream *stream=g_new0(AudioStream,1); + RtpSession *rtps,*rtpr; + PayloadType *pt; + + //create_rtp_sessions(profile,locport,remip,remport,payload,jitt_comp,&rtpr,&rtps); + + create_duplex_rtpsession(profile,locport,remip,remport,payload,jitt_comp,&rtpr); + rtp_session_signal_connect(rtpr,"telephone-event",(RtpCallback)on_dtmf_received,(gpointer)stream); + rtps=rtpr; + + stream->rtpsend=ms_rtp_send_new(); + ms_rtp_send_set_session(MS_RTP_SEND(stream->rtpsend),rtps); + stream->rtprecv=ms_rtp_recv_new(); + ms_rtp_recv_set_session(MS_RTP_RECV(stream->rtprecv),rtpr); + + + /* creates the local part */ + if (infile==NULL) stream->soundread=snd_card_create_read_filter(captcard); + else stream->soundread=ms_read_new(infile); + if (outfile==NULL) stream->soundwrite=snd_card_create_write_filter(playcard); + else stream->soundwrite=ms_write_new(outfile); + + /* creates the couple of encoder/decoder */ + pt=rtp_profile_get_payload(profile,payload); + if (pt==NULL){ + g_error("audiostream.c: undefined payload type."); + return NULL; + } + stream->encoder=ms_encoder_new_with_string_id(pt->mime_type); + stream->decoder=ms_decoder_new_with_string_id(pt->mime_type); + if ((stream->encoder==NULL) || (stream->decoder==NULL)){ + /* big problem: we have not a registered codec for this payload...*/ + audio_stream_free(stream); + g_error("mediastream.c: No decoder available for payload %i.",payload); + return NULL; + } + /* give the sound filters some properties */ + ms_filter_set_property(stream->soundread,MS_FILTER_PROPERTY_FREQ,&pt->clock_rate); + ms_filter_set_property(stream->soundwrite,MS_FILTER_PROPERTY_FREQ,&pt->clock_rate); + + /* give the encoder/decoder some parameters*/ + ms_filter_set_property(stream->encoder,MS_FILTER_PROPERTY_FREQ,&pt->clock_rate); + ms_filter_set_property(stream->encoder,MS_FILTER_PROPERTY_BITRATE,&pt->normal_bitrate); + ms_filter_set_property(stream->decoder,MS_FILTER_PROPERTY_FREQ,&pt->clock_rate); + ms_filter_set_property(stream->decoder,MS_FILTER_PROPERTY_BITRATE,&pt->normal_bitrate); + + ms_filter_set_property(stream->encoder,MS_FILTER_PROPERTY_FMTP, (void*)pt->fmtp); + ms_filter_set_property(stream->decoder,MS_FILTER_PROPERTY_FMTP,(void*)pt->fmtp); + /* create the synchronisation source */ + stream->timer=ms_timer_new(); + + /* and then connect all */ + ms_filter_add_link(stream->soundread,stream->encoder); + ms_filter_add_link(stream->encoder,stream->rtpsend); + ms_filter_add_link(stream->rtprecv,stream->decoder); + ms_filter_add_link(stream->decoder,stream->soundwrite); + + ms_sync_attach(stream->timer,stream->soundread); + ms_sync_attach(stream->timer,stream->rtprecv); + + /* and start */ + ms_start(stream->timer); + + return stream; +} + +static int defcard=0; + +void audio_stream_set_default_card(int cardindex){ + defcard=cardindex; +} + +AudioStream * audio_stream_start_with_files(RtpProfile *prof,int locport,char *remip, + int remport,int profile,int jitt_comp,gchar *infile, gchar*outfile) +{ + return audio_stream_start_full(prof,locport,remip,remport,profile,jitt_comp,infile,outfile,NULL,NULL); +} + +AudioStream * audio_stream_start(RtpProfile *prof,int locport,char *remip,int remport,int profile,int jitt_comp) +{ + SndCard *sndcard; + sndcard=snd_card_manager_get_card(snd_card_manager,defcard); + return audio_stream_start_full(prof,locport,remip,remport,profile,jitt_comp,NULL,NULL,sndcard,sndcard); +} + +AudioStream *audio_stream_start_with_sndcards(RtpProfile *prof,int locport,char *remip,int remport,int profile,int jitt_comp,SndCard *playcard, SndCard *captcard) +{ + g_return_val_if_fail(playcard!=NULL,NULL); + g_return_val_if_fail(captcard!=NULL,NULL); + return audio_stream_start_full(prof,locport,remip,remport,profile,jitt_comp,NULL,NULL,playcard,captcard); +} + +void audio_stream_set_rtcp_information(AudioStream *st, const char *cname){ + if (st->send_session!=NULL){ + rtp_session_set_source_description(st->send_session,cname,NULL,NULL,NULL,NULL,"linphone-" "2.0.0", // SME + "This is free software (GPL) !"); + } +} + +void audio_stream_stop(AudioStream * stream) +{ + + ms_stop(stream->timer); + ortp_global_stats_display(); + ms_sync_detach(stream->timer,stream->soundread); + ms_sync_detach(stream->timer,stream->rtprecv); + + ms_filter_remove_links(stream->soundread,stream->encoder); + ms_filter_remove_links(stream->encoder,stream->rtpsend); + ms_filter_remove_links(stream->rtprecv,stream->decoder); + ms_filter_remove_links(stream->decoder,stream->soundwrite); + + audio_stream_free(stream); +} + +RingStream * ring_start(gchar *file,gint interval,SndCard *sndcard) +{ + return ring_start_with_cb(file,interval,sndcard,NULL,NULL); +} + +RingStream * ring_start_with_cb(gchar *file,gint interval,SndCard *sndcard, MSFilterNotifyFunc func,gpointer user_data) +{ + RingStream *stream; + int tmp; + g_return_val_if_fail(sndcard!=NULL,NULL); + stream=g_new0(RingStream,1); + stream->source=ms_ring_player_new(file,interval); + if (stream->source==NULL) { + g_warning("Could not create ring player. Probably the ring file (%s) does not exist.",file); + return NULL; + } + if (func!=NULL) ms_filter_set_notify_func(MS_FILTER(stream->source),func,user_data); + stream->sndwrite=snd_card_create_write_filter(sndcard); + ms_filter_get_property(stream->source,MS_FILTER_PROPERTY_FREQ,&tmp); + ms_filter_set_property(stream->sndwrite,MS_FILTER_PROPERTY_FREQ,&tmp); + ms_filter_get_property(stream->source,MS_FILTER_PROPERTY_CHANNELS,&tmp); + ms_filter_set_property(stream->sndwrite,MS_FILTER_PROPERTY_CHANNELS,&tmp); + stream->timer=ms_timer_new(); + ms_filter_add_link(stream->source,stream->sndwrite); + ms_sync_attach(stream->timer,stream->source); + ms_start(stream->timer); + return stream; +} + +void ring_stop(RingStream *stream) +{ + ms_stop(stream->timer); + ms_sync_detach(stream->timer,stream->source); + ms_sync_destroy(stream->timer); + ms_filter_remove_links(stream->source,stream->sndwrite); + ms_filter_destroy(stream->source); + ms_filter_destroy(stream->sndwrite); + g_free(stream); +} + +/* returns the latency in samples if the audio device with id dev_id is openable in full duplex mode, else 0 */ +gint test_audio_dev(int dev_id) +{ + gint err; + SndCard *sndcard=snd_card_manager_get_card(snd_card_manager,dev_id); + if (sndcard==NULL) return -1; + err=snd_card_probe(sndcard,16,0,8000); + return err; /* return latency in number of sample */ +} + +gint audio_stream_send_dtmf(AudioStream *stream, gchar dtmf) +{ + ms_rtp_send_dtmf(MS_RTP_SEND(stream->rtpsend), dtmf); + ms_oss_write_play_dtmf(MS_OSS_WRITE(stream->soundwrite),dtmf); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/g711common.h Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,171 @@ +/* + * PCM - A-Law conversion + * Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org> + * + * Wrapper for linphone Codec class by Simon Morlat <simon.morlat@free.fr> + */ + +static inline int val_seg(int val) +{ + int r = 0; + val >>= 7; + if (val & 0xf0) { + val >>= 4; + r += 4; + } + if (val & 0x0c) { + val >>= 2; + r += 2; + } + if (val & 0x02) + r += 1; + return r; +} + +/* + * s16_to_alaw() - Convert a 16-bit linear PCM value to 8-bit A-law + * + * s16_to_alaw() accepts an 16-bit integer and encodes it as A-law data. + * + * Linear Input Code Compressed Code + * ------------------------ --------------- + * 0000000wxyza 000wxyz + * 0000001wxyza 001wxyz + * 000001wxyzab 010wxyz + * 00001wxyzabc 011wxyz + * 0001wxyzabcd 100wxyz + * 001wxyzabcde 101wxyz + * 01wxyzabcdef 110wxyz + * 1wxyzabcdefg 111wxyz + * + * For further information see John C. Bellamy's Digital Telephony, 1982, + * John Wiley & Sons, pps 98-111 and 472-476. + */ + +static inline unsigned char s16_to_alaw(int pcm_val) +{ + int mask; + int seg; + unsigned char aval; + + if (pcm_val >= 0) { + mask = 0xD5; + } else { + mask = 0x55; + pcm_val = -pcm_val; + if (pcm_val > 0x7fff) + pcm_val = 0x7fff; + } + + if (pcm_val < 256) + aval = pcm_val >> 4; + else { + /* Convert the scaled magnitude to segment number. */ + seg = val_seg(pcm_val); + aval = (seg << 4) | ((pcm_val >> (seg + 3)) & 0x0f); + } + return aval ^ mask; +} + +/* + * alaw_to_s16() - Convert an A-law value to 16-bit linear PCM + * + */ +static inline int alaw_to_s16(unsigned char a_val) +{ + int t; + int seg; + + a_val ^= 0x55; + t = a_val & 0x7f; + if (t < 16) + t = (t << 4) + 8; + else { + seg = (t >> 4) & 0x07; + t = ((t & 0x0f) << 4) + 0x108; + t <<= seg -1; + } + return ((a_val & 0x80) ? t : -t); +} +/* + * s16_to_ulaw() - Convert a linear PCM value to u-law + * + * In order to simplify the encoding process, the original linear magnitude + * is biased by adding 33 which shifts the encoding range from (0 - 8158) to + * (33 - 8191). The result can be seen in the following encoding table: + * + * Biased Linear Input Code Compressed Code + * ------------------------ --------------- + * 00000001wxyza 000wxyz + * 0000001wxyzab 001wxyz + * 000001wxyzabc 010wxyz + * 00001wxyzabcd 011wxyz + * 0001wxyzabcde 100wxyz + * 001wxyzabcdef 101wxyz + * 01wxyzabcdefg 110wxyz + * 1wxyzabcdefgh 111wxyz + * + * Each biased linear code has a leading 1 which identifies the segment + * number. The value of the segment number is equal to 7 minus the number + * of leading 0's. The quantization interval is directly available as the + * four bits wxyz. * The trailing bits (a - h) are ignored. + * + * Ordinarily the complement of the resulting code word is used for + * transmission, and so the code word is complemented before it is returned. + * + * For further information see John C. Bellamy's Digital Telephony, 1982, + * John Wiley & Sons, pps 98-111 and 472-476. + */ + +static inline unsigned char s16_to_ulaw(int pcm_val) /* 2's complement (16-bit range) */ +{ + int mask; + int seg; + unsigned char uval; + + if (pcm_val < 0) { + pcm_val = 0x84 - pcm_val; + mask = 0x7f; + } else { + pcm_val += 0x84; + mask = 0xff; + } + if (pcm_val > 0x7fff) + pcm_val = 0x7fff; + + /* Convert the scaled magnitude to segment number. */ + seg = val_seg(pcm_val); + + /* + * Combine the sign, segment, quantization bits; + * and complement the code word. + */ + uval = (seg << 4) | ((pcm_val >> (seg + 3)) & 0x0f); + return uval ^ mask; +} + +/* + * ulaw_to_s16() - Convert a u-law value to 16-bit linear PCM + * + * First, a biased linear code is derived from the code word. An unbiased + * output can then be obtained by subtracting 33 from the biased code. + * + * Note that this function expects to be passed the complement of the + * original code word. This is in keeping with ISDN conventions. + */ +static inline int ulaw_to_s16(unsigned char u_val) +{ + int t; + + /* Complement to obtain normal u-law value. */ + u_val = ~u_val; + + /* + * Extract and bias the quantization bits. Then + * shift up by the segment number and subtract out the bias. + */ + t = ((u_val & 0x0f) << 3) + 0x84; + t <<= (u_val & 0x70) >> 4; + + return ((u_val & 0x80) ? (0x84 - t) : (t - 0x84)); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/hpuxsndcard.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,301 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + +#include "sndcard.h" +#include "osscard.h" + +#ifdef HAVE_SYS_AUDIO_H +#include <sys/audio.h> + + +#include "msossread.h" +#include "msosswrite.h" + +#include <errno.h> +#include <fcntl.h> + + +int hpuxsnd_open(HpuxSndCard *obj, int bits,int stereo, int rate) +{ + int fd; + int p=0,cond=0; + int i=0; + int min_size=0,blocksize=512; + /* do a quick non blocking open to be sure that we are not going to be blocked here + for the eternity */ + fd=open(obj->dev_name,O_RDWR|O_NONBLOCK); + if (fd<0) return -EWOULDBLOCK; + close(fd); + /* open the device */ + fd=open(obj->dev_name,O_RDWR); + + g_return_val_if_fail(fd>0,-errno); + + ioctl(fd,AUDIO_RESET,0); + ioctl(fd,AUDIO_SET_SAMPLE_RATE,rate); + ioctl(fd,AUDIO_SET_CHANNELS,stereo); + p=AUDIO_FORMAT_LINEAR16BIT; + ioctl(fd,AUDIO_SET_DATA_FORMAT,p); + /* ioctl(fd,AUDIO_GET_RXBUFSIZE,&min_size); does not work ? */ + min_size=2048; + + g_message("dsp blocksize is %i.",min_size); + obj->fd=fd; + obj->readpos=0; + obj->writepos=0; + SND_CARD(obj)->bits=bits; + SND_CARD(obj)->stereo=stereo; + SND_CARD(obj)->rate=rate; + SND_CARD(obj)->bsize=min_size; + return fd; +} + +int hpux_snd_card_probe(HpuxSndCard *obj,int bits,int stereo,int rate) +{ + return 2048; +} + + +int hpux_snd_card_open(HpuxSndCard *obj,int bits,int stereo,int rate) +{ + int fd; + obj->ref++; + if (obj->fd==0){ + fd=hpuxsnd_open(obj,bits,stereo,rate); + if (fd<0) { + obj->fd=0; + obj->ref--; + return -1; + } + } + SND_CARD(obj)->flags|=SND_CARD_FLAGS_OPENED; + return 0; +} + +void hpux_snd_card_close(HpuxSndCard *obj) +{ + int i; + obj->ref--; + if (obj->ref==0) { + close(obj->fd); + obj->fd=0; + SND_CARD(obj)->flags&=~SND_CARD_FLAGS_OPENED; + + } +} + +void hpux_snd_card_destroy(HpuxSndCard *obj) +{ + snd_card_uninit(SND_CARD(obj)); + g_free(obj->dev_name); + g_free(obj->mixdev_name); +} + +gboolean hpux_snd_card_can_read(HpuxSndCard *obj) +{ + struct timeval tout={0,0}; + int err; + fd_set fdset; + FD_ZERO(&fdset); + FD_SET(obj->fd,&fdset); + err=select(obj->fd+1,&fdset,NULL,NULL,&tout); + if (err>0) return TRUE; + else return FALSE; +} + +int hpux_snd_card_read(HpuxSndCard *obj,char *buf,int size) +{ + int err; + gint bsize=SND_CARD(obj)->bsize; + if (size<bsize){ + gint canread=MIN(bsize-obj->readpos,size); + if (obj->readbuf==NULL) obj->readbuf=g_malloc0(bsize); + if (obj->readpos==0){ + err=read(obj->fd,obj->readbuf,bsize); + if (err<0) { + g_warning("hpux_snd_card_read: read() failed:%s.",strerror(errno)); + return -1; + } + } + + memcpy(buf,&obj->readbuf[obj->readpos],canread); + obj->readpos+=canread; + if (obj->readpos>=bsize) obj->readpos=0; + return canread; + }else{ + err=read(obj->fd,buf,size); + if (err<0) { + g_warning("hpux_snd_card_read: read-2() failed:%s.",strerror(errno)); + } + return err; + } + +} + +int hpux_snd_card_write(HpuxSndCard *obj,char *buf,int size) +{ + int err; + gint bsize=SND_CARD(obj)->bsize; + if (size<bsize){ + gint canwrite=MIN(bsize-obj->writepos,size); + if (obj->writebuf==NULL) obj->writebuf=g_malloc0(bsize); + + memcpy(&obj->writebuf[obj->writepos],buf,canwrite); + obj->writepos+=canwrite; + if (obj->writepos>=bsize){ + err=write(obj->fd,obj->writebuf,bsize); + } + return canwrite; + }else{ + return write(obj->fd,buf,bsize); + } +} + +#define SND_CARD_LEVEL_TO_HPUX_LEVEL(a) (((a)*2) - 100) +#define HPUX_LEVEL_TO_SND_CARD_LEVEL(a) (((a)+200)/2) +void hpux_snd_card_set_level(HpuxSndCard *obj,gint way,gint a) +{ + struct audio_gain gain; + int error,mix_fd; + + g_return_if_fail(obj->mixdev_name!=NULL); + memset(&gain,0,sizeof(struct audio_gain)); + switch(way){ + case SND_CARD_LEVEL_GENERAL: + gain.cgain[0].monitor_gain=SND_CARD_LEVEL_TO_HPUX_LEVEL(a); + gain.cgain[1].monitor_gain=SND_CARD_LEVEL_TO_HPUX_LEVEL(a); + break; + case SND_CARD_LEVEL_INPUT: + gain.cgain[0].receive_gain=SND_CARD_LEVEL_TO_HPUX_LEVEL(a); + gain.cgain[1].receive_gain=SND_CARD_LEVEL_TO_HPUX_LEVEL(a); + break; + case SND_CARD_LEVEL_OUTPUT: + gain.cgain[0].transmit_gain=SND_CARD_LEVEL_TO_HPUX_LEVEL(a); + gain.cgain[1].transmit_gain=SND_CARD_LEVEL_TO_HPUX_LEVEL(a); + break; + default: + g_warning("hpux_snd_card_set_level: unsupported command."); + return; + } + gain.channel_mask=AUDIO_CHANNEL_RIGHT|AUDIO_CHANNEL_LEFT; + mix_fd = open(obj->mixdev_name, O_WRONLY); + g_return_if_fail(mix_fd>0); + error=ioctl(mix_fd,AUDIO_SET_GAINS,&gain); + if (error<0){ + g_warning("hpux_snd_card_set_level: Could not set gains: %s",strerror(errno)); + } + close(mix_fd); +} + +gint hpux_snd_card_get_level(HpuxSndCard *obj,gint way) +{ + struct audio_gain gain; + int p=0,mix_fd,error; + g_return_if_fail(obj->mixdev_name!=NULL); + + gain.channel_mask=AUDIO_CHANNEL_RIGHT|AUDIO_CHANNEL_LEFT; + mix_fd = open(obj->mixdev_name, O_RDONLY); + g_return_if_fail(mix_fd>0); + error=ioctl(mix_fd,AUDIO_GET_GAINS,&gain); + if (error<0){ + g_warning("hpux_snd_card_set_level: Could not get gains: %s",strerror(errno)); + } + close(mix_fd); + + switch(way){ + case SND_CARD_LEVEL_GENERAL: + p=gain.cgain[0].monitor_gain; + break; + case SND_CARD_LEVEL_INPUT: + p=gain.cgain[0].receive_gain; + break; + case SND_CARD_LEVEL_OUTPUT: + p=gain.cgain[0].transmit_gain; + break; + default: + g_warning("hpux_snd_card_get_level: unsupported command."); + return -1; + } + return HPUX_LEVEL_TO_SND_CARD_LEVEL(p); +} + +void hpux_snd_card_set_source(HpuxSndCard *obj,int source) +{ + gint p=0; + gint mix_fd; + gint error=0; + g_return_if_fail(obj->mixdev_name!=NULL); + + mix_fd=open("/dev/audio",O_WRONLY); + g_return_if_fail(mix_fd>0); + switch(source){ + case 'm': + error=ioctl(mix_fd,AUDIO_SET_INPUT,AUDIO_IN_MIKE); + break; + case 'l': + error=ioctl(mix_fd,AUDIO_SET_INPUT,AUDIO_IN_LINE); + break; + default: + g_warning("hpux_snd_card_set_source: unsupported source."); + } + close(mix_fd); +} + +MSFilter *hpux_snd_card_create_read_filter(HpuxSndCard *card) +{ + MSFilter *f=ms_oss_read_new(); + ms_oss_read_set_device(MS_OSS_READ(f),SND_CARD(card)->index); + return f; +} + +MSFilter *hpux_snd_card_create_write_filter(HpuxSndCard *card) +{ + MSFilter *f=ms_oss_write_new(); + ms_oss_write_set_device(MS_OSS_WRITE(f),SND_CARD(card)->index); + return f; +} + + +SndCard * hpux_snd_card_new(char *devname, char *mixdev_name) +{ + HpuxSndCard * obj= g_new0(HpuxSndCard,1); + SndCard *base= SND_CARD(obj); + snd_card_init(base); + obj->dev_name=g_strdup(devname); + obj->mixdev_name=g_strdup( mixdev_name); + base->card_name=g_strdup(devname); + base->_probe=(SndCardOpenFunc)hpux_snd_card_probe; + base->_open_r=(SndCardOpenFunc)hpux_snd_card_open; + base->_open_w=(SndCardOpenFunc)hpux_snd_card_open; + base->_can_read=(SndCardPollFunc)hpux_snd_card_can_read; + base->_read=(SndCardIOFunc)hpux_snd_card_read; + base->_write=(SndCardIOFunc)hpux_snd_card_write; + base->_close_r=(SndCardCloseFunc)hpux_snd_card_close; + base->_close_w=(SndCardCloseFunc)hpux_snd_card_close; + base->_set_rec_source=(SndCardMixerSetRecSourceFunc)hpux_snd_card_set_source; + base->_set_level=(SndCardMixerSetLevelFunc)hpux_snd_card_set_level; + base->_get_level=(SndCardMixerGetLevelFunc)hpux_snd_card_get_level; + base->_destroy=(SndCardDestroyFunc)hpux_snd_card_destroy; + base->_create_read_filter=(SndCardCreateFilterFunc)hpux_snd_card_create_read_filter; + base->_create_write_filter=(SndCardCreateFilterFunc)hpux_snd_card_create_write_filter; + return base; +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/jackcard.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,574 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 + + JACK support + Copyright (C) 2004 Tobias Gehrig tobias@gehrig.tk +*/ + +#include "jackcard.h" + +#ifdef __JACK_ENABLED__ + +#include "msossread.h" +#include "msosswrite.h" + +#include <signal.h> + +#define READBUFFERSIZE 524288 +#define WRITEBUFFERSIZE 524288 +#define BSIZE 512 + +/** + * jack_shutdown: + * @arg: + * + * This is the shutdown callback for this JACK application. + * It is called by JACK if the server ever shuts down or + * decides to disconnect the client. + * + */ +void +jack_shutdown (void *arg) +{ + JackCard* obj = (JackCard*) arg; + + obj->jack_running = FALSE; + obj->jack_active = FALSE; + obj->read.port = NULL; + if (obj->read.open) + obj->read.init = TRUE; + obj->write.port = NULL; + if (obj->write.open) + obj->write.init = TRUE; +} + +int samplerate(jack_nframes_t rate, void *arg) +{ + JackCard* obj = (JackCard*) arg; + int error; + + obj->rate = rate; + if (obj->read.open) { + obj->read.data.src_ratio = (double)obj->read.rate / (double)obj->rate; + obj->read.data.input_frames = (long)((double)obj->read.frames/obj->read.data.src_ratio); + g_free(obj->read.data.data_in); + obj->read.data.data_in = malloc(obj->read.data.input_frames*sizeof(float)); + if (obj->read.src_state) + if ((error = src_set_ratio(obj->read.src_state, obj->read.data.src_ratio)) != 0) + g_warning("Error while resetting the write samplerate: %s", src_strerror(error)); + } + if (obj->write.open) { + obj->write.data.src_ratio = (double)obj->rate / (double)obj->write.rate; + obj->write.data.output_frames = (long)((double)obj->write.frames*obj->write.data.src_ratio); + g_free(obj->write.data.data_out); + obj->write.data.data_out = malloc(obj->write.data.output_frames*sizeof(float)); + if (obj->write.src_state) + if ((error = src_set_ratio(obj->write.src_state, obj->write.data.src_ratio)) != 0) + g_warning("Error while resetting the write samplerate: %s", src_strerror(error)); + } + return 0; +} + +/* + * The process callback for this JACK application. + * It is called by JACK at the appropriate times. + * @nframes : + * @arg : + */ +int +process (jack_nframes_t nframes, void *arg) +{ + JackCard* obj = (JackCard*) arg; + sample_t *out; + sample_t *in; + + if (obj->clear && !obj->write.can_process) { + out = (sample_t *) jack_port_get_buffer (obj->write.port, nframes); + memset (out, 0, nframes * sizeof(sample_t)); + obj->clear = FALSE; + } + + if (!obj->can_process) + return 0; + + if(obj->read.can_process) { + in = (sample_t *) jack_port_get_buffer (obj->read.port, nframes); + jack_ringbuffer_write (obj->read.buffer, (void *) in, sizeof(sample_t) * nframes); + } + + if (obj->write.can_process) { + out = (sample_t *) jack_port_get_buffer (obj->write.port, nframes); + memset (out, 0, nframes * sizeof(sample_t)); + if (obj->clear && jack_ringbuffer_read_space(obj->write.buffer) == 0) { + obj->write.can_process = FALSE; + if (!obj->read.open) + obj->can_process = FALSE; + obj->clear = FALSE; + return 0; + } + jack_ringbuffer_read (obj->write.buffer, (void *) out, sizeof(sample_t) * nframes); + } + return 0; +} + +int jack_init(JackCard* obj) +{ + char* client_name; + int error; + + if (!obj->jack_running) { + obj->client = NULL; + client_name = g_strdup_printf("linphone-%u", g_random_int()); + if ((obj->client = jack_client_new (client_name)) == NULL) { + g_warning("cannot create jack client"); + g_free(client_name); + return -1; + } + g_message("Found Jack Daemon"); + g_free(client_name); + + /* tell the JACK server to call `process()' whenever + there is work to be done. + */ + jack_set_process_callback (obj->client, process, obj); + + /* tell the JACK server to call `jack_shutdown()' if + it ever shuts down, either entirely, or if it + just decides to stop calling us. + */ + jack_on_shutdown (obj->client, jack_shutdown, obj); + jack_set_sample_rate_callback (obj->client, samplerate, obj); + obj->rate = jack_get_sample_rate (obj->client); + if (obj->rate == 0) { + g_warning ("rate is 0???"); + if (jack_client_close(obj->client) != 0) + g_warning("could not close client"); + return -1; + } + obj->buffer_size = jack_get_buffer_size(obj->client); + obj->jack_running = TRUE; + } + + if (!obj->jack_active) { + if (jack_activate (obj->client)) { + g_warning("cannot activate jack client"); + return -1; + } else obj->jack_active = TRUE; + } + + if (obj->read.init) { + if (!obj->read.port && (obj->read.port = jack_port_register (obj->client, "input", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0))==NULL) { + g_warning("error while trying to register input port"); + return -1; + } + if (!obj->read.phys_ports && (obj->read.phys_ports = jack_get_ports (obj->client, NULL, NULL, JackPortIsPhysical|JackPortIsOutput)) == NULL) { + g_warning("Cannot find any physical capture ports\n"); + jack_port_unregister(obj->client, obj->read.port); + obj->read.port = NULL; + return -1; + } + if (!jack_port_connected(obj->read.port)) + if ((error = jack_connect (obj->client, obj->read.phys_ports[0], jack_port_name (obj->read.port))) != 0) { + g_warning("cannot connect input ports: %s -> %s\n", jack_port_name (obj->read.port), obj->read.phys_ports[0]); + if (error == EEXIST) g_warning("connection already made"); + else { + jack_port_unregister(obj->client, obj->read.port); + obj->read.port = NULL; + return -1; + } + } + obj->read.init = FALSE; + } + + if (obj->write.init) { + if (!obj->write.port && (obj->write.port = jack_port_register (obj->client, "output", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0))==NULL) { + g_warning("error while trying to register output port"); + return -1; + } + if (!obj->write.phys_ports && (obj->write.phys_ports = jack_get_ports (obj->client, NULL, NULL, JackPortIsPhysical|JackPortIsInput)) == NULL) { + g_warning("Cannot find any physical playback ports\n"); + jack_port_unregister(obj->client, obj->write.port); + obj->write.port = NULL; + return -1; + } + if (!jack_port_connected(obj->write.port)) { + if ((error = jack_connect (obj->client, jack_port_name (obj->write.port), obj->write.phys_ports[0])) != 0) { + g_warning("cannot connect output ports: %s -> %s\n", jack_port_name (obj->write.port), obj->write.phys_ports[0]); + if (error == EEXIST) g_warning("connection already made"); + else { + jack_port_unregister(obj->client, obj->write.port); + obj->write.port = NULL; + return -1; + } + } + if ((error = jack_connect (obj->client, jack_port_name (obj->write.port), obj->write.phys_ports[1])) != 0) { + g_warning("cannot connect output ports: %s -> %s\n", jack_port_name (obj->write.port), obj->write.phys_ports[1]); + if (error == EEXIST) g_warning("connection already made"); + else { + jack_port_unregister(obj->client, obj->write.port); + obj->write.port = NULL; + return -1; + } + } + } + obj->write.init = FALSE; + } + return 0; +} + +int jack_card_open_r(JackCard *obj,int bits,int stereo,int rate) +{ + int channels = stereo + 1, bsize, error; + obj->read.init = TRUE; + if (jack_init(obj) != 0) return -1; + + obj->read.rate = rate; + obj->sample_size = bits / 8; + obj->frame_size = channels * obj->sample_size; + bsize = BSIZE; + obj->read.frames = bsize / 2; + SND_CARD(obj)->bsize = bsize; + SND_CARD(obj)->flags |= SND_CARD_FLAGS_OPENED; + obj->read.channels = channels; + if ((obj->read.src_state = src_new (SRC_SINC_FASTEST, channels, &error)) == NULL) + g_warning("Error while initializing the samplerate converter: %s", src_strerror(error)); + obj->read.data.src_ratio = (double)rate / (double)obj->rate; + obj->read.data.input_frames = (long)((double)obj->read.frames/obj->read.data.src_ratio); + obj->read.data.data_in = malloc(obj->read.data.input_frames*sizeof(float)); + obj->read.data.data_out = malloc(obj->read.frames*sizeof(float)); + obj->read.data.end_of_input = 0; + if (!obj->read.buffer) + obj->read.buffer = jack_ringbuffer_create(READBUFFERSIZE); + obj->read.can_process = TRUE; + obj->can_process = TRUE; + obj->read.open = TRUE; + obj->read.init = FALSE; + return 0; +} + +int jack_card_open_w(JackCard *obj,int bits,int stereo,int rate) +{ + int channels = stereo + 1, bsize, err; + obj->write.init = TRUE; + if (jack_init(obj) != 0) return -1; + + obj->write.rate = rate; + obj->sample_size = bits / 8; + obj->frame_size = channels * obj->sample_size; + bsize = BSIZE; + obj->write.frames = bsize / 2; + SND_CARD(obj)->bsize = bsize; + SND_CARD(obj)->flags |= SND_CARD_FLAGS_OPENED; + obj->write.channels = channels; + if ((obj->write.src_state = src_new (SRC_SINC_FASTEST, channels, &err)) == NULL) + g_warning("Error while initializing the samplerate converter: %s", src_strerror(err)); + obj->write.data.src_ratio = (double)obj->rate / (double)rate; + obj->write.data.data_in = malloc(obj->write.frames*sizeof(float)); + obj->write.data.end_of_input = 0; + obj->write.data.output_frames = (long)((double)obj->write.frames*obj->write.data.src_ratio); + obj->write.data.data_out = malloc(obj->write.data.output_frames*sizeof(float)); + if (!obj->write.buffer) + obj->write.buffer = jack_ringbuffer_create(WRITEBUFFERSIZE); + obj->write.can_process = TRUE; + obj->can_process = TRUE; + obj->write.open = TRUE; + obj->write.init = FALSE; + return 0; +} + +void jack_card_set_blocking_mode(JackCard *obj, gboolean yesno) +{ +} + +void jack_card_close_r(JackCard *obj) +{ + obj->read.open = FALSE; + obj->read.init = FALSE; + obj->read.can_process = FALSE; + if (!obj->write.open) + obj->can_process = FALSE; + if (obj->read.src_state) + obj->read.src_state = src_delete (obj->read.src_state); + g_free(obj->read.data.data_in); + g_free(obj->read.data.data_out); +} + +void jack_card_close_w(JackCard *obj) +{ + obj->write.open = FALSE; + obj->write.init = FALSE; + obj->clear = TRUE; + if (!obj->jack_running) { + obj->write.can_process = FALSE; + obj->can_process = FALSE; + } + if (obj->write.src_state) + obj->write.src_state = src_delete (obj->write.src_state); + g_free(obj->write.data.data_in); + g_free(obj->write.data.data_out); +} + +int jack_card_probe(JackCard *obj,int bits,int stereo,int rate) +{ + if (obj->jack_running) return BSIZE; + else if (jack_init(obj) == 0) return BSIZE; + else return -1; +} + +void jack_card_destroy(JackCard *obj) +{ + if (obj->jack_running) jack_client_close (obj->client); + snd_card_uninit(SND_CARD(obj)); + if (obj->read.buffer) { + jack_ringbuffer_free(obj->read.buffer); + obj->read.buffer = NULL; + } + if (obj->write.buffer) { + jack_ringbuffer_free(obj->write.buffer); + obj->write.buffer = NULL; + } + if (obj->read.phys_ports) { + g_free(obj->read.phys_ports); + obj->read.phys_ports = NULL; + } + if (obj->write.phys_ports) { + g_free(obj->write.phys_ports); + obj->write.phys_ports = NULL; + } +} + +gboolean jack_card_can_read(JackCard *obj) +{ + g_return_val_if_fail(obj->read.buffer!=NULL,0); + if (jack_ringbuffer_read_space(obj->read.buffer)>=(long)((double)obj->read.frames/obj->read.data.src_ratio)*sizeof(sample_t)) return TRUE; + else return FALSE; +} + +int jack_card_read(JackCard *obj,char *buf,int size) +{ + size_t bytes, can_read, i; + int error; + float norm, value; + + g_return_val_if_fail((obj->read.buffer!=NULL)&&(obj->read.src_state!=NULL),-1); + if (jack_init(obj) != 0) return -1; + size /= 2; + can_read = MIN(size, obj->read.frames); + // can_read = MIN(((long)((double)can_read / obj->read.data.src_ratio))*sizeof(sample_t), jack_ringbuffer_read_space(obj->read.buffer)); + can_read = ((long)((double)can_read / obj->read.data.src_ratio))*sizeof(sample_t); + obj->read.can_process = FALSE; + bytes = jack_ringbuffer_read (obj->read.buffer, (void *)obj->read.data.data_in, can_read); + obj->read.can_process = TRUE; + obj->read.data.input_frames = bytes / sizeof(sample_t); + can_read = MIN(size, obj->read.frames); + obj->read.data.output_frames = can_read; + if ((error = src_process(obj->read.src_state, &(obj->read.data))) != 0) + g_warning("error while samplerate conversion. error: %s", src_strerror(error)); + norm = obj->read.level*obj->level*(float)0x8000; + for (i=0; i < obj->read.data.output_frames_gen; i++) { + value = obj->read.data.data_out[i]*norm; + if (value >= 32767.0) + ((short*)buf)[i] = 32767; + else if (value <= -32768.0) + ((short*)buf)[i] = -32768; + else + ((short*)buf)[i] = (short)value; + } + bytes = obj->read.data.output_frames_gen * 2; + return bytes; +} + +int jack_card_write(JackCard *obj,char *buf,int size) +{ + size_t bytes, can_write, i; + int error; + float norm; + + g_return_val_if_fail((obj->write.buffer!=NULL)&&(obj->write.src_state!=NULL),-1); + if (jack_init(obj) != 0) return -1; + size /= 2; + can_write = MIN(size, obj->write.frames); + norm = obj->write.level*obj->level/(float)0x8000; + for (i=0; i<can_write; i++) { + obj->write.data.data_in[i] = (float)((short*)buf)[i]*norm; + } + obj->write.data.input_frames = can_write; + if ((error = src_process(obj->write.src_state, &(obj->write.data))) != 0) + g_warning("error while samplerate conversion. error: %s", src_strerror(error)); + obj->write.can_process = FALSE; + bytes = jack_ringbuffer_write (obj->write.buffer, (void *) obj->write.data.data_out, sizeof(sample_t)*obj->write.data.output_frames_gen); + obj->write.can_process = TRUE; + return bytes; +} + +void jack_card_set_level(JackCard *obj,gint way,gint a) +{ + switch(way){ + case SND_CARD_LEVEL_GENERAL: + obj->level = (float)a / 100.0; + break; + case SND_CARD_LEVEL_INPUT: + obj->read.level = (float)a / 100.0; + break; + case SND_CARD_LEVEL_OUTPUT: + obj->write.level = (float)a / 100.0; + break; + default: + g_warning("jack_card_set_level: unsupported command."); + } +} + +gint jack_card_get_level(JackCard *obj,gint way) +{ + gint value = 0; + + switch(way){ + case SND_CARD_LEVEL_GENERAL: + value = (gint)(obj->level*100.0); + break; + case SND_CARD_LEVEL_INPUT: + value = (gint)(obj->read.level*100.0); + break; + case SND_CARD_LEVEL_OUTPUT: + value = (gint)(obj->write.level*100.0); + break; + default: + g_warning("jack_card_get_level: unsupported command."); + } + return value; +} + +void jack_card_set_source(JackCard *obj,int source) +{ +} + +MSFilter *jack_card_create_read_filter(JackCard *card) +{ + MSFilter *f=ms_oss_read_new(); + ms_oss_read_set_device(MS_OSS_READ(f),SND_CARD(card)->index); + return f; +} + +MSFilter *jack_card_create_write_filter(JackCard *card) +{ + MSFilter *f=ms_oss_write_new(); + ms_oss_write_set_device(MS_OSS_WRITE(f),SND_CARD(card)->index); + return f; +} +SndCard * jack_card_new(jack_client_t *client) +{ + JackCard * obj; + SndCard *base; + + obj= g_new0(JackCard,1); + + if (!client) return NULL; + obj->client = client; + obj->jack_running = TRUE; + obj->jack_active = FALSE; + obj->can_process = FALSE; + obj->clear = TRUE; + obj->write.can_process = FALSE; + obj->write.open = FALSE; + obj->write.init = TRUE; + obj->write.port = NULL; + obj->write.phys_ports = NULL; + obj->write.buffer = NULL; + obj->read.can_process = FALSE; + obj->read.open = FALSE; + obj->read.init = TRUE; + obj->read.port = NULL; + obj->read.phys_ports = NULL; + obj->read.buffer = NULL; + + /* tell the JACK server to call `process()' whenever + there is work to be done. + */ + jack_set_process_callback (client, process, obj); + + /* tell the JACK server to call `jack_shutdown()' if + it ever shuts down, either entirely, or if it + just decides to stop calling us. + */ + jack_on_shutdown (client, jack_shutdown, obj); + + jack_set_sample_rate_callback (client, samplerate, obj); + + obj->rate = jack_get_sample_rate (client); + obj->buffer_size = jack_get_buffer_size(obj->client); + + jack_init(obj); + + base= SND_CARD(obj); + snd_card_init(base); + +#ifdef HAVE_GLIB + base->card_name=g_strdup_printf("JACK client"); +#else + base->card_name=malloc(100); + snprintf(base->card_name, 100, "JACK client"); +#endif + + base->_probe=(SndCardOpenFunc)jack_card_probe; + base->_open_r=(SndCardOpenFunc)jack_card_open_r; + base->_open_w=(SndCardOpenFunc)jack_card_open_w; + base->_can_read=(SndCardPollFunc)jack_card_can_read; + base->_set_blocking_mode=(SndCardSetBlockingModeFunc)jack_card_set_blocking_mode; + base->_read=(SndCardIOFunc)jack_card_read; + base->_write=(SndCardIOFunc)jack_card_write; + base->_close_r=(SndCardCloseFunc)jack_card_close_r; + base->_close_w=(SndCardCloseFunc)jack_card_close_w; + base->_set_rec_source=(SndCardMixerSetRecSourceFunc)jack_card_set_source; + base->_set_level=(SndCardMixerSetLevelFunc)jack_card_set_level; + base->_get_level=(SndCardMixerGetLevelFunc)jack_card_get_level; + base->_destroy=(SndCardDestroyFunc)jack_card_destroy; + base->_create_read_filter=(SndCardCreateFilterFunc)jack_card_create_read_filter; + base->_create_write_filter=(SndCardCreateFilterFunc)jack_card_create_write_filter; + + obj->read.buffer=NULL; + obj->write.buffer=NULL; + obj->buffer_size = 0; + obj->level = 1.0; + obj->write.level = 1.0; + obj->read.level = 1.0; + + return base; +} + + +gint jack_card_manager_init(SndCardManager *m, gint index) +{ + jack_client_t *client = NULL; + char* client_name; + + client_name=g_strdup_printf("linphone-%u", g_random_int()); + if ((client = jack_client_new (client_name))!= NULL) + { + g_message("Found Jack Daemon"); + g_free(client_name); + m->cards[index]=jack_card_new(client); + m->cards[index]->index=index; + return 1; + } else { + g_free(client_name); + return 0; + } +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/jackcard.h Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,81 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 + + JACK support + Copyright (C) 2004 Tobias Gehrig tobias@gehrig.tk +*/ + +#ifndef JACK_CARD_H +#define JACK_CARD_H + +#include <config.h> + +#ifdef __JACK_ENABLED__ + +#include "sndcard.h" + +#include <jack/jack.h> +#include <jack/ringbuffer.h> + +#include <samplerate.h> + +typedef jack_default_audio_sample_t sample_t; + +typedef struct { + jack_port_t *port; + const char **phys_ports; + float level; + jack_ringbuffer_t *buffer; + gint channels; + gint rate; + SRC_STATE* src_state; + SRC_DATA data; + size_t frames; + gboolean can_process; + gboolean open; + gboolean init; +} jackcard_mode_t; + +struct _JackCard +{ + SndCard parent; + + jack_client_t *client; + gboolean jack_running; + gboolean jack_active; + float level; + jack_nframes_t buffer_size; + gint sample_size; + gint frame_size; + gint rate; + gboolean can_process; + gboolean clear; + + jackcard_mode_t read, write; +}; + +typedef struct _JackCard JackCard; + +SndCard * jack_card_new(jack_client_t *client); + +gint jack_card_manager_init(SndCardManager *m, gint index); + +#endif + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/mediastream.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,114 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + +#include "mediastream.h" + +#include <signal.h> +#include <sys/types.h> +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +static int cond=1; + +void stop_handler(int signum) +{ + cond--; + if (cond<0) exit(-1); +} + +void parse_addr(gchar *addr, char **ip, int *port) +{ + char *semicolon; + gint iplen; + + *ip=NULL; + *port=0; + semicolon=strchr(addr,':'); + if (semicolon==NULL) return; + iplen=semicolon-addr; + *ip=g_malloc(iplen+1); + strncpy(*ip,addr,iplen); + (*ip)[iplen]='\0'; + *port=atoi(semicolon+1); +} + +char *usage="mediastream --local <port> --remote <ip:port> --payload <payload type>\n"; +void run_media_streams(gint localport, gchar *remote_ip, gint remoteport, gint payload); + +int main(int argc, char * argv[]) +{ + gint i; + gint localport=0,remoteport=0,payload=0; + gchar *ip; + gchar *tmp; + + /*create the rtp session */ + ortp_init(); + ortp_set_debug_file("oRTP",NULL); + rtp_profile_set_payload(&av_profile,115,&lpc1015); + rtp_profile_set_payload(&av_profile,110,&speex_nb); + + if (argc<4) { + printf(usage); + return -1; + } + for (i=1;i<argc;i++){ + if (strcmp(argv[i],"--local")==0){ + i++; + localport=atoi(argv[i]); + }else if (strcmp(argv[i],"--remote")==0){ + i++; + parse_addr(argv[i],&ip,&remoteport); + if (ip==NULL) { + printf(usage); + return -1; + } + printf("Remote addr: ip=%s port=%i\n",ip,remoteport); + }else if (strcmp(argv[i],"--payload")==0){ + i++; + payload=atoi(argv[i]); + } + } + tmp=getenv("defcard"); + if (tmp!=NULL) audio_stream_set_default_card(atoi(tmp)); + run_media_streams(localport,ip,remoteport,payload); + return 0; +} + +void run_media_streams(gint localport, gchar *remote_ip, gint remoteport, gint payload) +{ + AudioStream *audio; + ms_init(); + ms_speex_codec_init(); + signal(SIGINT,stop_handler); + + audio=audio_stream_start(&av_profile,localport,remote_ip,remoteport,payload,250); + while(cond) + { + /* sleep until we receive SIGINT */ + sleep(1); + } + + printf("stoping all...\n"); + + audio_stream_stop(audio); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/mediastream.h Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,128 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + + +#ifndef MEDIASTREAM_H +#define MEDIASTREAM_H + +#include "msrtprecv.h" +#include "msrtpsend.h" +#include "ms.h" +#include "msosswrite.h" +#include "msossread.h" +#include "msread.h" +#include "mswrite.h" +#include "mstimer.h" +#include "mscodec.h" +#include "msspeexdec.h" +#include "msringplayer.h" + + +struct _AudioStream +{ + MSSync *timer; + RtpSession *send_session; + RtpSession *recv_session; + MSFilter *soundread; + MSFilter *soundwrite; + MSFilter *encoder; + MSFilter *decoder; + MSFilter *rtprecv; + MSFilter *rtpsend; +}; + + +typedef struct _AudioStream AudioStream; + +struct _RingStream +{ + MSSync *timer; + MSFilter *source; + MSFilter *sndwrite; +}; + +typedef struct _RingStream RingStream; + +/* start a thread that does sampling->encoding->rtp_sending|rtp_receiving->decoding->playing */ +AudioStream *audio_stream_start (RtpProfile * prof, int locport, char *remip, + int remport, int profile, int jitt_comp); + +AudioStream *audio_stream_start_with_sndcards(RtpProfile * prof, int locport, char *remip4, + int remport, int profile, int jitt_comp, SndCard *playcard, SndCard *captcard); + +AudioStream *audio_stream_start_with_files (RtpProfile * prof, int locport, + char *remip4, int remport, + int profile, int jitt_comp, + gchar * infile, gchar * outfile); +void audio_stream_set_rtcp_information(AudioStream *st, const char *cname); + + +/* stop the above process*/ +void audio_stream_stop (AudioStream * stream); + +RingStream *ring_start (gchar * file, gint interval, SndCard *sndcard); +RingStream *ring_start_with_cb(gchar * file, gint interval, SndCard *sndcard, MSFilterNotifyFunc func,gpointer user_data); +void ring_stop (RingStream * stream); + +/* returns the latency in samples if the audio device with id dev_id is openable in full duplex mode, else 0 */ +gint test_audio_dev (int dev_id); + +/* send a dtmf */ +gint audio_stream_send_dtmf (AudioStream * stream, gchar dtmf); + +void audio_stream_set_default_card(int cardindex); + + +#ifdef VIDEO_ENABLED + +/***************** + Video Support + *****************/ + + + +struct _VideoStream +{ + MSSync *timer; + RtpSession *send_session; + RtpSession *recv_session; + MSFilter *source; + MSFilter *output; + MSFilter *encoder; + MSFilter *decoder; + MSFilter *rtprecv; + MSFilter *rtpsend; + gboolean show_local; +}; + + +typedef struct _VideoStream VideoStream; + +VideoStream *video_stream_start(RtpProfile *profile, int locport, char *remip4, int remport, + int payload, int jitt_comp, gboolean show_local, const gchar *source, const gchar *device); +void video_stream_set_rtcp_information(VideoStream *st, const char *cname); +void video_stream_stop (VideoStream * stream); + +VideoStream * video_preview_start(const gchar *source, const gchar *device); +void video_preview_stop(VideoStream *stream); + +#endif + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/ms.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,342 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 "ms.h" +#include "sndcard.h" +#include "mscodec.h" + +#include <sys/types.h> +#include <fcntl.h> +#include <unistd.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> + +#ifdef VIDEO_ENABLED +extern void ms_video_source_register_all(); +#endif +#ifdef HAVE_ILBC +extern void ms_ilbc_codec_init(); +#endif + +/** + * ms_init: + * + * + * Initialize the mediastreamer. This must be the first function called in a program + * using the mediastreamer library. + * + * + */ +void ms_init() +{ + if (!g_thread_supported()) g_thread_init (NULL); +#ifdef HAVE_GLIB + if (!g_module_supported()){ + g_error("GModule is not supported."); + } +#endif + /* initialize the oss subsystem */ + snd_card_manager_init(snd_card_manager); + /* register the statically linked codecs */ + ms_codec_register_all(); +#ifdef VIDEO_ENABLED + ms_video_source_register_all(); +#endif +#ifdef HAVE_ILBC + ms_ilbc_codec_init(); +#endif +} + + +static gint compare(gconstpointer a, gconstpointer b) +{ + MSFilter *f1=(MSFilter*)a,*f2=(MSFilter*)b; + if (f1->klass<f2->klass) return -1; + if (f1->klass==f2->klass) return 0; + /* if f1->klass>f2->klass ....*/ + return 1; +} + +static GList *g_list_append_if_new(GList *l,gpointer data) +{ + GList *res=l; + if (g_list_find(res,data)==NULL) + res=g_list_append(res,data); + return(res); +} + +static GList *get_nexts(MSFilter *f,GList *l) +{ + int i; + MSFifo *fifo; + MSQueue *q; + GList *res=l; + + /* check fifos*/ + for (i=0;i <f->klass->max_foutputs;i++) + { + fifo=f->outfifos[i]; + if (fifo!=NULL) res=g_list_append_if_new(res,(gpointer)fifo->next_data); + } + /* check queues*/ + for (i=0;i <f->klass->max_qoutputs;i++) + { + q=f->outqueues[i]; + if (q!=NULL) res=g_list_append_if_new(res,(gpointer)q->next_data); + } + return(res); +} + +/* compile graphs attached to a sync source*/ +int ms_compile(MSSync *sync) +{ + int i; + GList *list1=NULL,*list2=NULL,*elem; + GList *proc_chain=NULL; + MSFilter *f; + + /* first free the old list if we are just updating*/ + if (sync->execution_list!=NULL) g_list_free(sync->execution_list); + /* get the list of filters attached to this sync*/ + for (i=0;i<sync->filters;i++) + { + //printf("found filter !\n"); + list1=g_list_append(list1,sync->attached_filters[i]); + } + /* find the processing chain */ + while (list1!=NULL) + { + list2=NULL; + /* sort the list by types of filter*/ + list1=g_list_sort(list1,compare); + /* save into the processing chain list*/ + //printf("list1 :%i elements\n",g_list_length(list1)); + proc_chain=g_list_concat(proc_chain,list1); + /* get all following filters. They are appended to list2*/ + elem=list1; + while (elem!=NULL) + { + f=(MSFilter*)(elem->data); + /* check if filter 's status */ + if (f->klass->attributes & FILTER_CAN_SYNC) + { + sync->samples_per_tick=0; + } + list2=get_nexts(f,list2); + elem=g_list_next(elem); + } + list1=list2; + } + sync->execution_list=proc_chain; + sync->flags&=~MS_SYNC_NEED_UPDATE; + ms_trace("%i filters successfully compiled in a processing chain.",g_list_length(sync->execution_list)); + return 0; +} + +/*execute the processing chain attached to a sync source. It is called as a thread by ms_main()*/ +void *ms_thread_run(void *sync_ptr) +{ + MSSync *sync=(MSSync*) sync_ptr; + GList *filter; + MSFilter *f; + + + ms_sync_lock(sync); + while(sync->run) + { + //g_message("sync->run=%i",sync->run); + if (sync->samples_per_tick==0) ms_sync_suspend(sync); + if (sync->flags & MS_SYNC_NEED_UPDATE){ + ms_compile(sync); + ms_sync_setup(sync); + } + filter=sync->execution_list; + ms_sync_unlock(sync); + //ms_trace("Calling synchronisation"); + ms_sync_synchronize(sync); + while(filter!=NULL) + { + f=(MSFilter*)filter->data; + if (MS_FILTER_GET_CLASS(f)->attributes & FILTER_IS_SOURCE) + { + /* execute it once */ + ms_trace("Running source filter %s.",f->klass->name); + ms_filter_process(f); + } + else + { + /* make the filter process its input data until it has no more */ + while ( ms_filter_fifos_have_data(f) || ms_filter_queues_have_data(f) ) + { + ms_trace("Running filter %s.",f->klass->name); + ms_filter_process(f); + } + } + filter=g_list_next(filter); + } + ms_sync_lock(sync); + } + g_cond_signal(sync->stop_cond); /* signal that the sync thread has finished */ + ms_sync_unlock(sync); + g_message("Mediastreamer processing thread is exiting."); + return NULL; +} + +/* stop the processing chain attached to a sync source.*/ +void ms_thread_stop(MSSync *sync) +{ + if (sync->thread!=NULL) + { + if (sync->samples_per_tick==0) + { + /* to wakeup the thread */ + //g_cond_signal(sync->thread_cond); + } + g_mutex_lock(sync->lock); + sync->run=0; + sync->thread=NULL; + g_cond_wait(sync->stop_cond,sync->lock); + g_mutex_unlock(sync->lock); + } + //g_message("ms_thread_stop() finished."); +} + +/** + * ms_start: + * @sync: A synchronisation source to be started. + * + * Starts a thread that will shedule all processing chains attached to the synchronisation source @sync. + * + * + */ +void ms_start(MSSync *sync) +{ + if (sync->run==1) return; /*already running*/ + ms_compile(sync); + ms_sync_setup(sync); + /* this is to avoid race conditions, for example: + ms_start(sync); + ms_oss_write_start(ossw); + here tge ossw filter need to be compiled to run ms_oss_write_start() + */ + ms_trace("ms_start: creating new thread."); + sync->run=1; + sync->thread=g_thread_create((GThreadFunc)ms_thread_run,(gpointer)sync,TRUE,NULL); + if (sync->thread==NULL){ + g_warning("Could not create thread !"); + } +} + +/** + * ms_stop: + * @sync: A synchronisation source to be stopped. + * + * Stop the thread that was sheduling the processing chains attached to the synchronisation source @sync. + * The processing chains are kept unchanged, no object is freed. The synchronisation source can be restarted using ms_start(). + * + * + */ +void ms_stop(MSSync *sync) +{ + ms_thread_stop(sync); + ms_sync_unsetup(sync); +} + + +gint ms_load_plugin(gchar *path) +{ +#ifdef HAVE_GLIB + g_module_open(path,0); +#endif + return 0; +} + +gchar * ms_proc_get_param(gchar *parameter) +{ + gchar *file; + int fd; + int err,len; + gchar *p,*begin,*end; + gchar *ret; + fd=open("/proc/cpuinfo",O_RDONLY); + if (fd<0){ + g_warning("Could not open /proc/cpuinfo."); + return NULL; + } + file=g_malloc(1024); + err=read(fd,file,1024); + file[err-1]='\0'; + /* find the parameter */ + p=strstr(file,parameter); + if (p==NULL){ + /* parameter not found */ + g_free(file); + return NULL; + } + /* find the following ':' */ + p=strchr(p,':'); + if (p==NULL){ + g_free(file); + return NULL; + } + /* find the value*/ + begin=p+2; + end=strchr(begin,'\n'); + if (end==NULL) end=strchr(begin,'\0'); + len=end-begin+1; + ret=g_malloc(len+1); + snprintf(ret,len,"%s",begin); + //printf("%s=%s\n",parameter,ret); + g_free(file); + return ret; +} + +gint ms_proc_get_type() +{ + static int proc_type=0; + gchar *value; + if (proc_type==0){ + value=ms_proc_get_param("cpu family"); + if (value!=NULL) { + proc_type=atoi(value); + g_free(value); + }else return -1; + } + return proc_type; +} + +gint ms_proc_get_speed() +{ + char *value; + static int proc_speed=0; + if (proc_speed==0){ + value=ms_proc_get_param("cpu MHz"); + if (value!=NULL){ + proc_speed=atoi(value); + g_free(value); + }else return -1; + } + //printf("proc_speed=%i\n",proc_speed); + return proc_speed; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/ms.h Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,81 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + + + +#ifndef MS_H +#define MS_H +#include "msfilter.h" +#include "mssync.h" + + +void ms_init(); + +/* compile graphs attached to a sync source*/ +int ms_compile(MSSync *source); + + +/* stop the processing chain attached to a sync source.*/ +void ms_thread_stop(MSSync *sync); + + +/** + * function_name:ms_thread_run + * @sync: The synchronization source for all the set of graphs to run. + * + * Execute the processing chain attached to a sync source. This function loops indefinitely. + * The media streamer programmer can choose to execute this function directly, or to call ms_start(), + * that will start a thread for the synchronisation source. + * + * Returns: no return value. + */ +void *ms_thread_run(void *sync); + + +/** + * function_name:ms_start + * @sync: A synchronisation source to be started. + * + * Starts a thread that will shedule all processing chains attached to the synchronisation source @sync. + * + * Returns: no return value. + */ +void ms_start(MSSync *sync); + + +/** + * function_name:ms_stop + * @sync: A synchronisation source to be stopped. + * + * Stop the thread that was sheduling the processing chains attached to the synchronisation source @sync. + * The processing chains are kept unchanged, no object is freed. The synchronisation source can be restarted using ms_start(). + * + * Returns: no return value. + */ +void ms_stop(MSSync *sync); + + +gchar * ms_proc_get_param(gchar *parameter); +gint ms_proc_get_type(); +gint ms_proc_get_speed(); + + + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msAlawdec.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,132 @@ + /* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + + +#include <msAlawdec.h> +#include <g711common.h> + +extern MSFilter * ms_ALAWencoder_new(void); + +MSCodecInfo ALAWinfo={ + { + "ALAW codec", + 0, + MS_FILTER_AUDIO_CODEC, + ms_ALAWencoder_new, + "This is the classic A-law codec. Good quality, but only usable with high speed network connections." + }, + ms_ALAWencoder_new, + ms_ALAWdecoder_new, + 320, + 160, + 64000, + 8000, + 8, + "PCMA", + 1, + 1, +}; + +static MSALAWDecoderClass *ms_ALAWdecoder_class=NULL; + +MSFilter * ms_ALAWdecoder_new(void) +{ + MSALAWDecoder *r; + + r=g_new(MSALAWDecoder,1); + ms_ALAWdecoder_init(r); + if (ms_ALAWdecoder_class==NULL) + { + ms_ALAWdecoder_class=g_new(MSALAWDecoderClass,1); + ms_ALAWdecoder_class_init(ms_ALAWdecoder_class); + } + MS_FILTER(r)->klass=MS_FILTER_CLASS(ms_ALAWdecoder_class); + return(MS_FILTER(r)); +} + + +/* FOR INTERNAL USE*/ +void ms_ALAWdecoder_init(MSALAWDecoder *r) +{ + ms_filter_init(MS_FILTER(r)); + MS_FILTER(r)->infifos=r->f_inputs; + MS_FILTER(r)->outfifos=r->f_outputs; + MS_FILTER(r)->r_mingran=ALAW_DECODER_RMAXGRAN; + memset(r->f_inputs,0,sizeof(MSFifo*)*MSALAWDECODER_MAX_INPUTS); + memset(r->f_outputs,0,sizeof(MSFifo*)*MSALAWDECODER_MAX_INPUTS); + +} + +void ms_ALAWdecoder_class_init(MSALAWDecoderClass *klass) +{ + ms_filter_class_init(MS_FILTER_CLASS(klass)); + ms_filter_class_set_name(MS_FILTER_CLASS(klass),"ALAWDecoder"); + MS_FILTER_CLASS(klass)->info=(MSFilterInfo*)&ALAWinfo; + MS_FILTER_CLASS(klass)->max_finputs=MSALAWDECODER_MAX_INPUTS; + MS_FILTER_CLASS(klass)->max_foutputs=MSALAWDECODER_MAX_INPUTS; + MS_FILTER_CLASS(klass)->r_maxgran=ALAW_DECODER_RMAXGRAN; + MS_FILTER_CLASS(klass)->w_maxgran=ALAW_DECODER_WMAXGRAN; + MS_FILTER_CLASS(klass)->destroy=(MSFilterDestroyFunc)ms_ALAWdecoder_destroy; + MS_FILTER_CLASS(klass)->process=(MSFilterProcessFunc)ms_ALAWdecoder_process; +} + +void ms_ALAWdecoder_process(MSALAWDecoder *r) +{ + MSFifo *fi,*fo; + int inlen,outlen; + gchar *s,*d; + int i; + /* process output fifos, but there is only one for this class of filter*/ + + /* this is the simplest process function design: + the filter declares a r_mingran of ALAW_DECODER_RMAXGRAN, so the mediastreamer's + scheduler will call the process function each time there is ALAW_DECODER_RMAXGRAN + bytes to read in the input fifo. If there is more, then it will call it several + time in order to the fifo to be completetly processed. + This is very simple, but not very efficient because of the multiple call function + of MSFilterProcessFunc that may happen. + The MSAlawEncoder implements another design; see it. + */ + + fi=r->f_inputs[0]; + fo=r->f_outputs[0]; + g_return_if_fail(fi!=NULL); + g_return_if_fail(fo!=NULL); + + inlen=ms_fifo_get_read_ptr(fi,ALAW_DECODER_RMAXGRAN,(void**)&s); + if (s==NULL) return; + outlen=ms_fifo_get_write_ptr(fo,ALAW_DECODER_WMAXGRAN,(void**)&d); + if (d!=NULL) + { + for(i=0;i<ALAW_DECODER_RMAXGRAN;i++) + { + ((gint16*)d)[i]=alaw_to_s16( (unsigned char) s[i]); + } + } + else g_warning("MSALAWDecoder: Discarding samples !!"); + +} + + + +void ms_ALAWdecoder_destroy( MSALAWDecoder *obj) +{ + g_free(obj); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msAlawdec.h Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,65 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + +#ifndef MSALAWDECODER_H +#define MSALAWDECODER_H + +#include <msfilter.h> +#include <mscodec.h> + +/*this is the class that implements a ALAWdecoder filter*/ + +#define MSALAWDECODER_MAX_INPUTS 1 /* max output per filter*/ + + +typedef struct _MSALAWDecoder +{ + /* the MSALAWDecoder derivates from MSFilter, so the MSFilter object MUST be the first of the MSALAWDecoder object + in order to the object mechanism to work*/ + MSFilter filter; + MSFifo *f_inputs[MSALAWDECODER_MAX_INPUTS]; + MSFifo *f_outputs[MSALAWDECODER_MAX_INPUTS]; +} MSALAWDecoder; + +typedef struct _MSALAWDecoderClass +{ + /* the MSALAWDecoder derivates from MSFilter, so the MSFilter class MUST be the first of the MSALAWDecoder class + in order to the class mechanism to work*/ + MSFilterClass parent_class; +} MSALAWDecoderClass; + +/* PUBLIC */ +#define MS_ALAWDECODER(filter) ((MSALAWDecoder*)(filter)) +#define MS_ALAWDECODER_CLASS(klass) ((MSALAWDecoderClass*)(klass)) +MSFilter * ms_ALAWdecoder_new(void); + +/* FOR INTERNAL USE*/ +void ms_ALAWdecoder_init(MSALAWDecoder *r); +void ms_ALAWdecoder_class_init(MSALAWDecoderClass *klass); +void ms_ALAWdecoder_destroy( MSALAWDecoder *obj); +void ms_ALAWdecoder_process(MSALAWDecoder *r); + +/* tuning parameters :*/ +#define ALAW_DECODER_WMAXGRAN 320 +#define ALAW_DECODER_RMAXGRAN 160 + +extern MSCodecInfo ALAWinfo; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msAlawenc.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,124 @@ + /* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + + +#include "msAlawenc.h" +#include "g711common.h" + +extern MSCodecInfo ALAWinfo; + +static MSALAWEncoderClass *ms_ALAWencoder_class=NULL; + +MSFilter * ms_ALAWencoder_new(void) +{ + MSALAWEncoder *r; + + r=g_new(MSALAWEncoder,1); + ms_ALAWencoder_init(r); + if (ms_ALAWencoder_class==NULL) + { + ms_ALAWencoder_class=g_new(MSALAWEncoderClass,1); + ms_ALAWencoder_class_init(ms_ALAWencoder_class); + } + MS_FILTER(r)->klass=MS_FILTER_CLASS(ms_ALAWencoder_class); + return(MS_FILTER(r)); +} + + +/* FOR INTERNAL USE*/ +void ms_ALAWencoder_init(MSALAWEncoder *r) +{ + ms_filter_init(MS_FILTER(r)); + MS_FILTER(r)->infifos=r->f_inputs; + MS_FILTER(r)->outfifos=r->f_outputs; + MS_FILTER(r)->r_mingran=ALAW_ENCODER_RMAXGRAN; /* the filter can be called as soon as there is + something to process */ + memset(r->f_inputs,0,sizeof(MSFifo*)*MSALAWENCODER_MAX_INPUTS); + memset(r->f_outputs,0,sizeof(MSFifo*)*MSALAWENCODER_MAX_INPUTS); + +} + +void ms_ALAWencoder_class_init(MSALAWEncoderClass *klass) +{ + ms_filter_class_init(MS_FILTER_CLASS(klass)); + ms_filter_class_set_name(MS_FILTER_CLASS(klass),"ALAWEncoder"); + MS_FILTER_CLASS(klass)->info=(MSFilterInfo*)&ALAWinfo; + MS_FILTER_CLASS(klass)->max_finputs=MSALAWENCODER_MAX_INPUTS; + MS_FILTER_CLASS(klass)->max_foutputs=MSALAWENCODER_MAX_INPUTS; + MS_FILTER_CLASS(klass)->r_maxgran=ALAW_ENCODER_RMAXGRAN; + MS_FILTER_CLASS(klass)->w_maxgran=ALAW_ENCODER_WMAXGRAN; + MS_FILTER_CLASS(klass)->destroy=(MSFilterDestroyFunc)ms_ALAWencoder_destroy; + MS_FILTER_CLASS(klass)->process=(MSFilterProcessFunc)ms_ALAWencoder_process; +} + +void ms_ALAWencoder_process(MSALAWEncoder *r) +{ + MSFifo *fi,*fo; + int inlen,outlen; + gchar *s,*d; + int i; + /* process output fifos, but there is only one for this class of filter*/ + + /* this is the sophisticated design of the process function: + Here the filter declares that it can be called as soon as there is something + to read on the input fifo by setting r_mingran=0. + Then it ask for the fifo to get as many data as possible by calling: + inlen=ms_fifo_get_read_ptr(fi,0,(void**)&s); + This avoid multiple call to the process function to process all data available + on the input fifo... but the writing of the process function is a bit + more difficult, because althoug ms_fifo_get_read_ptr() returns N bytes, + we cannot ask ms_fifo_get_write_ptr to return N bytes if + N>MS_FILTER_CLASS(klass)->w_maxgran. This is forbidden by the MSFifo + mechanism. + This is an open issue. + For the moment what is done here is that ms_fifo_get_write_ptr() is called + several time with its maximum granularity in order to try to write the output. + ... + One solution: + -create a new function ms_fifo_get_rw_ptr(fifo1,p1, fifo2,p2) to + return the number of bytes able to being processed according to the input + and output fifo, and their respective data pointers + */ + + + fi=r->f_inputs[0]; + fo=r->f_outputs[0]; + + inlen=ms_fifo_get_read_ptr(fi,ALAW_ENCODER_RMAXGRAN,(void**)&s); + if (s==NULL) return; + outlen=ms_fifo_get_write_ptr(fo,ALAW_ENCODER_WMAXGRAN,(void**)&d); + if (d!=NULL) + { + for(i=0;i<ALAW_ENCODER_WMAXGRAN;i++) + { + d[i]=s16_to_alaw( *((gint16*)s) ); + s+=2; + } + } + else g_warning("MSALAWDecoder: Discarding samples !!"); + +} + + + +void ms_ALAWencoder_destroy( MSALAWEncoder *obj) +{ + g_free(obj); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msAlawenc.h Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,64 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + +#ifndef MSALAWENCODER_H +#define MSALAWENCODER_H + +#include "mscodec.h" + + +/*this is the class that implements a ALAWencoder filter*/ + +#define MSALAWENCODER_MAX_INPUTS 1 /* max output per filter*/ + + +typedef struct _MSALAWEncoder +{ + /* the MSALAWEncoder derivates from MSFilter, so the MSFilter object MUST be the first of the MSALAWEncoder object + in order to the object mechanism to work*/ + MSFilter filter; + MSFifo *f_inputs[MSALAWENCODER_MAX_INPUTS]; + MSFifo *f_outputs[MSALAWENCODER_MAX_INPUTS]; +} MSALAWEncoder; + +typedef struct _MSALAWEncoderClass +{ + /* the MSALAWEncoder derivates from MSFilter, so the MSFilter class MUST be the first of the MSALAWEncoder class + in order to the class mechanism to work*/ + MSFilterClass parent_class; +} MSALAWEncoderClass; + +/* PUBLIC */ +#define MS_ALAWENCODER(filter) ((MSALAWEncoder*)(filter)) +#define MS_ALAWENCODER_CLASS(klass) ((MSALAWEncoderClass*)(klass)) +MSFilter * ms_ALAWencoder_new(void); + +/* FOR INTERNAL USE*/ +void ms_ALAWencoder_init(MSALAWEncoder *r); +void ms_ALAWencoder_class_init(MSALAWEncoderClass *klass); +void ms_ALAWencoder_destroy( MSALAWEncoder *obj); +void ms_ALAWencoder_process(MSALAWEncoder *r); + +/* tuning parameters :*/ +#define ALAW_ENCODER_WMAXGRAN 160 +#define ALAW_ENCODER_RMAXGRAN 320 + + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msGSMdecoder.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,121 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + + +#include "msGSMdecoder.h" + +extern MSFilter * ms_GSMencoder_new(void); + +MSCodecInfo GSMinfo={ + { + "GSM codec", + 0, + MS_FILTER_AUDIO_CODEC, + ms_GSMencoder_new, + "This is the codec widely used in european mobile phones. This implementation was done by " + "Jutta Degener and Carsten Bormann." + }, + ms_GSMencoder_new, + ms_GSMdecoder_new, + 320, + 33, + 13800, + 8000, + 3, + "GSM", + 1, + 1, +}; + +static MSGSMDecoderClass *ms_GSMdecoder_class=NULL; + +MSFilter * ms_GSMdecoder_new(void) +{ + MSGSMDecoder *r; + + r=g_new(MSGSMDecoder,1); + ms_GSMdecoder_init(r); + if (ms_GSMdecoder_class==NULL) + { + ms_GSMdecoder_class=g_new(MSGSMDecoderClass,1); + ms_GSMdecoder_class_init(ms_GSMdecoder_class); + } + MS_FILTER(r)->klass=MS_FILTER_CLASS(ms_GSMdecoder_class); + return(MS_FILTER(r)); +} + + +/* FOR INTERNAL USE*/ +void ms_GSMdecoder_init(MSGSMDecoder *r) +{ + ms_filter_init(MS_FILTER(r)); + MS_FILTER(r)->infifos=r->f_inputs; + MS_FILTER(r)->outfifos=r->f_outputs; + MS_FILTER(r)->r_mingran=33; + memset(r->f_inputs,0,sizeof(MSFifo*)*MSGSMDECODER_MAX_INPUTS); + memset(r->f_outputs,0,sizeof(MSFifo*)*MSGSMDECODER_MAX_INPUTS); + r->gsm_handle=gsm_create(); +} + +void ms_GSMdecoder_class_init(MSGSMDecoderClass *klass) +{ + ms_filter_class_init(MS_FILTER_CLASS(klass)); + ms_filter_class_set_name(MS_FILTER_CLASS(klass),"GSMDecoder"); + MS_FILTER_CLASS(klass)->info=(MSFilterInfo*)&GSMinfo; + MS_FILTER_CLASS(klass)->max_finputs=MSGSMDECODER_MAX_INPUTS; + MS_FILTER_CLASS(klass)->max_foutputs=MSGSMDECODER_MAX_INPUTS; + MS_FILTER_CLASS(klass)->r_maxgran=33; + MS_FILTER_CLASS(klass)->w_maxgran=2*160; + MS_FILTER_CLASS(klass)->destroy=(MSFilterDestroyFunc)ms_GSMdecoder_destroy; + MS_FILTER_CLASS(klass)->process=(MSFilterProcessFunc)ms_GSMdecoder_process; +} + +void ms_GSMdecoder_process(MSGSMDecoder *r) +{ + MSFifo *fi,*fo; + int err1; + void *s,*d; + + /* process output fifos, but there is only one for this class of filter*/ + + fi=r->f_inputs[0]; + fo=r->f_outputs[0]; + if (fi!=NULL) + { + err1=ms_fifo_get_read_ptr(fi,33,&s); + if (err1>0) + { + err1=ms_fifo_get_write_ptr(fo,160*2,&d); + if (d!=NULL) gsm_decode(r->gsm_handle,s,(gsm_signal*)d); + } + + } +} + +void ms_GSMdecoder_uninit(MSGSMDecoder *obj) +{ + gsm_destroy(obj->gsm_handle); +} + +void ms_GSMdecoder_destroy( MSGSMDecoder *obj) +{ + ms_GSMdecoder_uninit(obj); + g_free(obj); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msGSMdecoder.h Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,64 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + + +#ifndef MSGSMDECODER_H +#define MSGSMDECODER_H + +#include <msfilter.h> +#include <mscodec.h> +#include <gsm.h> + +/*this is the class that implements a GSMdecoder filter*/ + +#define MSGSMDECODER_MAX_INPUTS 1 /* max output per filter*/ + + +typedef struct _MSGSMDecoder +{ + /* the MSGSMDecoder derivates from MSFilter, so the MSFilter object MUST be the first of the MSGSMDecoder object + in order to the object mechanism to work*/ + MSFilter filter; + MSFifo *f_inputs[MSGSMDECODER_MAX_INPUTS]; + MSFifo *f_outputs[MSGSMDECODER_MAX_INPUTS]; + gsm gsm_handle; +} MSGSMDecoder; + +typedef struct _MSGSMDecoderClass +{ + /* the MSGSMDecoder derivates from MSFilter, so the MSFilter class MUST be the first of the MSGSMDecoder class + in order to the class mechanism to work*/ + MSFilterClass parent_class; +} MSGSMDecoderClass; + +/* PUBLIC */ +#define MS_GSMDECODER(filter) ((MSGSMDecoder*)(filter)) +#define MS_GSMDECODER_CLASS(klass) ((MSGSMDecoderClass*)(klass)) +MSFilter * ms_GSMdecoder_new(void); + +/* FOR INTERNAL USE*/ +void ms_GSMdecoder_init(MSGSMDecoder *r); +void ms_GSMdecoder_class_init(MSGSMDecoderClass *klass); +void ms_GSMdecoder_destroy( MSGSMDecoder *obj); +void ms_GSMdecoder_process(MSGSMDecoder *r); + +extern MSCodecInfo GSMinfo; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msGSMencoder.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,101 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + + +#include "msGSMencoder.h" +#include "mscodec.h" + +extern MSCodecInfo GSMinfo; + +static MSGSMEncoderClass *ms_GSMencoder_class=NULL; + +MSFilter * ms_GSMencoder_new(void) +{ + MSGSMEncoder *r; + + r=g_new(MSGSMEncoder,1); + ms_GSMencoder_init(r); + if (ms_GSMencoder_class==NULL) + { + ms_GSMencoder_class=g_new(MSGSMEncoderClass,1); + ms_GSMencoder_class_init(ms_GSMencoder_class); + } + MS_FILTER(r)->klass=MS_FILTER_CLASS(ms_GSMencoder_class); + return(MS_FILTER(r)); +} + + +/* FOR INTERNAL USE*/ +void ms_GSMencoder_init(MSGSMEncoder *r) +{ + ms_filter_init(MS_FILTER(r)); + MS_FILTER(r)->infifos=r->f_inputs; + MS_FILTER(r)->outfifos=r->f_outputs; + MS_FILTER(r)->r_mingran=2*160; + memset(r->f_inputs,0,sizeof(MSFifo*)*MSGSMENCODER_MAX_INPUTS); + memset(r->f_outputs,0,sizeof(MSFifo*)*MSGSMENCODER_MAX_INPUTS); + r->gsm_handle=gsm_create(); +} + +void ms_GSMencoder_class_init(MSGSMEncoderClass *klass) +{ + ms_filter_class_init(MS_FILTER_CLASS(klass)); + ms_filter_class_set_name(MS_FILTER_CLASS(klass),"GSMEncoder"); + MS_FILTER_CLASS(klass)->max_finputs=MSGSMENCODER_MAX_INPUTS; + MS_FILTER_CLASS(klass)->max_foutputs=MSGSMENCODER_MAX_INPUTS; + MS_FILTER_CLASS(klass)->r_maxgran=2*160; + MS_FILTER_CLASS(klass)->w_maxgran=33; + MS_FILTER_CLASS(klass)->destroy=(MSFilterDestroyFunc)ms_GSMencoder_destroy; + MS_FILTER_CLASS(klass)->process=(MSFilterProcessFunc)ms_GSMencoder_process; + MS_FILTER_CLASS(klass)->info=MS_FILTER_INFO(&GSMinfo); +} + +void ms_GSMencoder_process(MSGSMEncoder *r) +{ + MSFifo *fi,*fo; + int err1; + void *s,*d; + + /* process output fifos, but there is only one for this class of filter*/ + + fi=r->f_inputs[0]; + fo=r->f_outputs[0]; + if (fi!=NULL) + { + err1=ms_fifo_get_read_ptr(fi,160*2,&s); + if (err1>0) + { + err1=ms_fifo_get_write_ptr(fo,33,&d); + if (d!=NULL) gsm_encode(r->gsm_handle,(gsm_signal*)s,(gsm_byte*)d); + } + + } +} + +void ms_GSMencoder_uninit(MSGSMEncoder *obj) +{ + gsm_destroy(obj->gsm_handle); +} + +void ms_GSMencoder_destroy( MSGSMEncoder *obj) +{ + ms_GSMencoder_uninit(obj); + g_free(obj); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msGSMencoder.h Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,61 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + + +#ifndef MSGSMENCODER_H +#define MSGSMENCODER_H + +#include "msfilter.h" +#include <gsm.h> + +/*this is the class that implements a GSMencoder filter*/ + +#define MSGSMENCODER_MAX_INPUTS 1 /* max output per filter*/ + + +typedef struct _MSGSMEncoder +{ + /* the MSGSMEncoder derivates from MSFilter, so the MSFilter object MUST be the first of the MSGSMEncoder object + in order to the object mechanism to work*/ + MSFilter filter; + MSFifo *f_inputs[MSGSMENCODER_MAX_INPUTS]; + MSFifo *f_outputs[MSGSMENCODER_MAX_INPUTS]; + gsm gsm_handle; +} MSGSMEncoder; + +typedef struct _MSGSMEncoderClass +{ + /* the MSGSMEncoder derivates from MSFilter, so the MSFilter class MUST be the first of the MSGSMEncoder class + in order to the class mechanism to work*/ + MSFilterClass parent_class; +} MSGSMEncoderClass; + +/* PUBLIC */ +#define MS_GSMENCODER(filter) ((MSGSMEncoder*)(filter)) +#define MS_GSMENCODER_CLASS(klass) ((MSGSMEncoderClass*)(klass)) +MSFilter * ms_GSMencoder_new(void); + +/* FOR INTERNAL USE*/ +void ms_GSMencoder_init(MSGSMEncoder *r); +void ms_GSMencoder_class_init(MSGSMEncoderClass *klass); +void ms_GSMencoder_destroy( MSGSMEncoder *obj); +void ms_GSMencoder_process(MSGSMEncoder *r); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msLPC10decoder.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,129 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + + +#include "msLPC10decoder.h" +#include "msLPC10encoder.h" +#include <stdlib.h> +#include <lpc10.h> + +extern MSFilter * ms_LPC10encoder_new(void); + +MSCodecInfo LPC10info={ + { + "LPC10-15 codec", + 0, + MS_FILTER_AUDIO_CODEC, + ms_LPC10encoder_new, + "A low quality but very low bit rate codec from the U.S. Department of Defense." + }, + ms_LPC10encoder_new, + ms_LPC10decoder_new, + 360, + 7, + 2400, + 8000, + 115, + "1015", + 1, + 1, +}; + +static MSLPC10DecoderClass *ms_LPC10decoder_class=NULL; + +MSFilter * ms_LPC10decoder_new(void) +{ + MSLPC10Decoder *r; + + r=g_new(MSLPC10Decoder,1); + ms_LPC10decoder_init(r); + if (ms_LPC10decoder_class==NULL) + { + ms_LPC10decoder_class=g_new(MSLPC10DecoderClass,1); + ms_LPC10decoder_class_init(ms_LPC10decoder_class); + } + MS_FILTER(r)->klass=MS_FILTER_CLASS(ms_LPC10decoder_class); + return(MS_FILTER(r)); +} + + +/* FOR INTERNAL USE*/ +void ms_LPC10decoder_init(MSLPC10Decoder *r) +{ + ms_filter_init(MS_FILTER(r)); + MS_FILTER(r)->infifos=r->f_inputs; + MS_FILTER(r)->outfifos=r->f_outputs; + MS_FILTER(r)->r_mingran=7; + memset(r->f_inputs,0,sizeof(MSFifo*)*MSLPC10DECODER_MAX_INPUTS); + memset(r->f_outputs,0,sizeof(MSFifo*)*MSLPC10DECODER_MAX_INPUTS); + r->lpc10_dec=create_lpc10_decoder_state(); +} + +void ms_LPC10decoder_class_init(MSLPC10DecoderClass *klass) +{ + ms_filter_class_init(MS_FILTER_CLASS(klass)); + ms_filter_class_set_name(MS_FILTER_CLASS(klass),"LPC10Dec"); + MS_FILTER_CLASS(klass)->max_finputs=MSLPC10DECODER_MAX_INPUTS; + MS_FILTER_CLASS(klass)->max_foutputs=MSLPC10DECODER_MAX_INPUTS; + MS_FILTER_CLASS(klass)->r_maxgran=7; + MS_FILTER_CLASS(klass)->w_maxgran=LPC10_SAMPLES_PER_FRAME*2; + MS_FILTER_CLASS(klass)->destroy=(MSFilterDestroyFunc)ms_LPC10decoder_destroy; + MS_FILTER_CLASS(klass)->process=(MSFilterProcessFunc)ms_LPC10decoder_process; + MS_FILTER_CLASS(klass)->info=(MSFilterInfo*)&LPC10info; +} + +void ms_LPC10decoder_process(MSLPC10Decoder *r) +{ + MSFifo *fi,*fo; + int err1; + void *s,*d; + float speech[LPC10_SAMPLES_PER_FRAME]; + INT32 bits[LPC10_BITS_IN_COMPRESSED_FRAME]; + + /* process output fifos, but there is only one for this class of filter*/ + + fi=r->f_inputs[0]; + fo=r->f_outputs[0]; + if (fi!=NULL) + { + err1=ms_fifo_get_read_ptr(fi,7,&s); + if (err1>0) + { + err1=ms_fifo_get_write_ptr(fo,LPC10_SAMPLES_PER_FRAME*2,&d); + if (d!=NULL) + { + read_bits(s, bits, LPC10_BITS_IN_COMPRESSED_FRAME); + lpc10_decode(bits,speech, r->lpc10_dec); + write_16bit_samples((INT16*)d, speech, LPC10_SAMPLES_PER_FRAME); + } + } + } +} + +void ms_LPC10decoder_uninit(MSLPC10Decoder *obj) +{ + free(obj->lpc10_dec); +} + +void ms_LPC10decoder_destroy( MSLPC10Decoder *obj) +{ + ms_LPC10decoder_uninit(obj); + g_free(obj); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msLPC10decoder.h Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,64 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + + +#ifndef MSLPC10DECODER_H +#define MSLPC10DECODER_H + +#include <msfilter.h> +#include <mscodec.h> +#include <lpc10.h> + +/*this is the class that implements a LPC10decoder filter*/ + +#define MSLPC10DECODER_MAX_INPUTS 1 /* max output per filter*/ + + +typedef struct _MSLPC10Decoder +{ + /* the MSLPC10Decoder derivates from MSFilter, so the MSFilter object MUST be the first of the MSLPC10Decoder object + in order to the object mechanism to work*/ + MSFilter filter; + MSFifo *f_inputs[MSLPC10DECODER_MAX_INPUTS]; + MSFifo *f_outputs[MSLPC10DECODER_MAX_INPUTS]; + struct lpc10_decoder_state *lpc10_dec; +} MSLPC10Decoder; + +typedef struct _MSLPC10DecoderClass +{ + /* the MSLPC10Decoder derivates from MSFilter, so the MSFilter class MUST be the first of the MSLPC10Decoder class + in order to the class mechanism to work*/ + MSFilterClass parent_class; +} MSLPC10DecoderClass; + +/* PUBLIC */ +#define MS_LPC10DECODER(filter) ((MSLPC10Decoder*)(filter)) +#define MS_LPC10DECODER_CLASS(klass) ((MSLPC10DecoderClass*)(klass)) +MSFilter * ms_LPC10decoder_new(void); + +/* FOR INTERNAL USE*/ +void ms_LPC10decoder_init(MSLPC10Decoder *r); +void ms_LPC10decoder_class_init(MSLPC10DecoderClass *klass); +void ms_LPC10decoder_destroy( MSLPC10Decoder *obj); +void ms_LPC10decoder_process(MSLPC10Decoder *r); + +extern MSCodecInfo LPC10info; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msLPC10encoder.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,251 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + +#include <stdlib.h> +#include "msLPC10encoder.h" +#include <lpc10.h> + + +extern MSCodecInfo LPC10info; + +/* The return value of each of these calls is the same as that + returned by fread/fwrite, which should be the number of samples + successfully read/written, not the number of bytes. */ + +int +read_16bit_samples(INT16 int16samples[], float speech[], int n) +{ + int i; + + /* Convert 16 bit integer samples to floating point values in the + range [-1,+1]. */ + + for (i = 0; i < n; i++) { + speech[i] = ((float) int16samples[i]) / 32768.0; + } + + return (n); +} + + + +int +write_16bit_samples(INT16 int16samples[], float speech[], int n) +{ + int i; + float real_sample; + + /* Convert floating point samples in range [-1,+1] to 16 bit + integers. */ + for (i = 0; i < n; i++) { + real_sample = 32768.0 * speech[i]; + if (real_sample < -32768.0) { + int16samples[i] = -32768; + } else if (real_sample > 32767.0) { + int16samples[i] = 32767; + } else { + int16samples[i] = real_sample; + } + } + return (n); +} + +/* + +Write the bits in bits[0] through bits[len-1] to file f, in "packed" +format. + +bits is expected to be an array of len integer values, where each +integer is 0 to represent a 0 bit, and any other value represents a 1 +bit. This bit string is written to the file f in the form of several +8 bit characters. If len is not a multiple of 8, then the last +character is padded with 0 bits -- the padding is in the least +significant bits of the last byte. The 8 bit characters are "filled" +in order from most significant bit to least significant. + +*/ + +void +write_bits(unsigned char *data, INT32 *bits, int len) +{ + int i; /* generic loop variable */ + unsigned char mask; /* The next bit position within the + variable "data" to place the next + bit. */ + + + /* Fill in the array bits. + * The first compressed output bit will be the most significant + * bit of the byte, so initialize mask to 0x80. The next byte of + * compressed data is initially 0, and the desired bits will be + * turned on below. + */ + mask = 0x80; + *data = 0; + + for (i = 0; i < len; i++) { + /* Turn on the next bit of output data, if necessary. */ + if (bits[i]) { + (*data) |= mask; + } + /* + * If the byte data is full, determined by mask becoming 0, + * then write the byte to the output file, and reinitialize + * data and mask for the next output byte. Also add the byte + * if (i == len-1), because if len is not a multiple of 8, + * then mask won't yet be 0. */ + mask >>= 1; + if ((mask == 0) || (i == len-1)) { + data++; + *data = 0; + mask = 0x80; + } + } +} + + + +/* + +Read bits from file f into bits[0] through bits[len-1], in "packed" +format. + +Read ceiling(len/8) characters from file f, if that many are available +to read, otherwise read to the end of the file. The first character's +8 bits, in order from MSB to LSB, are used to fill bits[0] through +bits[7]. The second character's bits are used to fill bits[8] through +bits[15], and so on. If ceiling(len/8) characters are available to +read, and len is not a multiple of 8, then some of the least +significant bits of the last character read are completely ignored. +Every entry of bits[] that is modified is changed to either a 0 or a +1. + +The number of bits successfully read is returned, and is always in the +range 0 to len, inclusive. If it is less than len, it will always be +a multiple of 8. + +*/ + +int +read_bits(unsigned char *data, INT32 *bits, int len) +{ + int i,ind=0; /* generic loop variable */ + int c=0; + + /* Unpack the array bits into coded_frame. */ + for (i = 0; i < len; i++) { + if ((i % 8) == 0) { + c = (int)(data[ind]); + ind++; + } + if (c & (0x80 >> (i & 7))) { + bits[i] = 1; + } else { + bits[i] = 0; + } + } + return (len); +} + + + + +static MSLPC10EncoderClass *ms_LPC10encoder_class=NULL; + +MSFilter * ms_LPC10encoder_new(void) +{ + MSLPC10Encoder *r; + + r=g_new(MSLPC10Encoder,1); + ms_LPC10encoder_init(r); + if (ms_LPC10encoder_class==NULL) + { + ms_LPC10encoder_class=g_new(MSLPC10EncoderClass,1); + ms_LPC10encoder_class_init(ms_LPC10encoder_class); + } + MS_FILTER(r)->klass=MS_FILTER_CLASS(ms_LPC10encoder_class); + return(MS_FILTER(r)); +} + + +/* FOR INTERNAL USE*/ +void ms_LPC10encoder_init(MSLPC10Encoder *r) +{ + ms_filter_init(MS_FILTER(r)); + MS_FILTER(r)->infifos=r->f_inputs; + MS_FILTER(r)->outfifos=r->f_outputs; + MS_FILTER(r)->r_mingran=LPC10_SAMPLES_PER_FRAME*2; + memset(r->f_inputs,0,sizeof(MSFifo*)*MSLPC10ENCODER_MAX_INPUTS); + memset(r->f_outputs,0,sizeof(MSFifo*)*MSLPC10ENCODER_MAX_INPUTS); + r->lpc10_enc=create_lpc10_encoder_state(); +} + +void ms_LPC10encoder_class_init(MSLPC10EncoderClass *klass) +{ + ms_filter_class_init(MS_FILTER_CLASS(klass)); + ms_filter_class_set_name(MS_FILTER_CLASS(klass),"LPC10Enc"); + MS_FILTER_CLASS(klass)->max_finputs=MSLPC10ENCODER_MAX_INPUTS; + MS_FILTER_CLASS(klass)->max_foutputs=MSLPC10ENCODER_MAX_INPUTS; + MS_FILTER_CLASS(klass)->r_maxgran=LPC10_SAMPLES_PER_FRAME*2; + MS_FILTER_CLASS(klass)->w_maxgran=7; + MS_FILTER_CLASS(klass)->destroy=(MSFilterDestroyFunc)ms_LPC10encoder_destroy; + MS_FILTER_CLASS(klass)->process=(MSFilterProcessFunc)ms_LPC10encoder_process; + MS_FILTER_CLASS(klass)->info=(MSFilterInfo*)&LPC10info; +} + +void ms_LPC10encoder_process(MSLPC10Encoder *r) +{ + MSFifo *fi,*fo; + int err1; + void *s,*d; + float speech[LPC10_SAMPLES_PER_FRAME]; + INT32 bits[LPC10_BITS_IN_COMPRESSED_FRAME]; + + /* process output fifos, but there is only one for this class of filter*/ + + fi=r->f_inputs[0]; + fo=r->f_outputs[0]; + if (fi!=NULL) + { + err1=ms_fifo_get_read_ptr(fi,LPC10_SAMPLES_PER_FRAME*2,&s); + if (err1>0) + { + err1=ms_fifo_get_write_ptr(fo,7,&d); + if (d!=NULL) + { + read_16bit_samples((INT16*)s, speech, LPC10_SAMPLES_PER_FRAME); + lpc10_encode(speech, bits, r->lpc10_enc); + write_bits(d, bits, LPC10_BITS_IN_COMPRESSED_FRAME); + } + } + + } +} + +void ms_LPC10encoder_uninit(MSLPC10Encoder *obj) +{ + free(obj->lpc10_enc); +} + +void ms_LPC10encoder_destroy( MSLPC10Encoder *obj) +{ + ms_LPC10encoder_uninit(obj); + g_free(obj); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msLPC10encoder.h Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,74 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + + +#ifndef MSLPC10ENCODER_H +#define MSLPC10ENCODER_H + +#include "mscodec.h" + + +int +read_16bit_samples(gint16 int16samples[], float speech[], int n); + +int +write_16bit_samples(gint16 int16samples[], float speech[], int n); + +void +write_bits(unsigned char *data, gint32 *bits, int len); + +int +read_bits(unsigned char *data, gint32 *bits, int len); + + +/*this is the class that implements a LPC10encoder filter*/ + +#define MSLPC10ENCODER_MAX_INPUTS 1 /* max output per filter*/ + + +typedef struct _MSLPC10Encoder +{ + /* the MSLPC10Encoder derivates from MSFilter, so the MSFilter object MUST be the first of the MSLPC10Encoder object + in order to the object mechanism to work*/ + MSFilter filter; + MSFifo *f_inputs[MSLPC10ENCODER_MAX_INPUTS]; + MSFifo *f_outputs[MSLPC10ENCODER_MAX_INPUTS]; + struct lpc10_encoder_state *lpc10_enc; +} MSLPC10Encoder; + +typedef struct _MSLPC10EncoderClass +{ + /* the MSLPC10Encoder derivates from MSFilter, so the MSFilter class MUST be the first of the MSLPC10Encoder class + in order to the class mechanism to work*/ + MSFilterClass parent_class; +} MSLPC10EncoderClass; + +/* PUBLIC */ +#define MS_LPC10ENCODER(filter) ((MSLPC10Encoder*)(filter)) +#define MS_LPC10ENCODER_CLASS(klass) ((MSLPC10EncoderClass*)(klass)) +MSFilter * ms_LPC10encoder_new(void); + +/* FOR INTERNAL USE*/ +void ms_LPC10encoder_init(MSLPC10Encoder *r); +void ms_LPC10encoder_class_init(MSLPC10EncoderClass *klass); +void ms_LPC10encoder_destroy( MSLPC10Encoder *obj); +void ms_LPC10encoder_process(MSLPC10Encoder *r); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msMUlawdec.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,130 @@ + /* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + + +#include <msMUlawdec.h> +#include <g711common.h> + +extern MSFilter * ms_MULAWencoder_new(void); + +MSCodecInfo MULAWinfo={ + { + "MULAW codec", + 0, + MS_FILTER_AUDIO_CODEC, + ms_MULAWencoder_new, + "This is the classic Mu-law codec. Good quality, but only usable with high speed network connections." + }, + ms_MULAWencoder_new, + ms_MULAWdecoder_new, + 320, + 160, + 64000, + 8000, + 0, + "PCMU", + 1, + 1 +}; + +static MSMULAWDecoderClass *ms_MULAWdecoder_class=NULL; + +MSFilter * ms_MULAWdecoder_new(void) +{ + MSMULAWDecoder *r; + + r=g_new(MSMULAWDecoder,1); + ms_MULAWdecoder_init(r); + if (ms_MULAWdecoder_class==NULL) + { + ms_MULAWdecoder_class=g_new(MSMULAWDecoderClass,1); + ms_MULAWdecoder_class_init(ms_MULAWdecoder_class); + } + MS_FILTER(r)->klass=MS_FILTER_CLASS(ms_MULAWdecoder_class); + return(MS_FILTER(r)); +} + + +/* FOR INTERNAL USE*/ +void ms_MULAWdecoder_init(MSMULAWDecoder *r) +{ + ms_filter_init(MS_FILTER(r)); + MS_FILTER(r)->infifos=r->f_inputs; + MS_FILTER(r)->outfifos=r->f_outputs; + MS_FILTER(r)->r_mingran=MULAW_DECODER_RMAXGRAN; + memset(r->f_inputs,0,sizeof(MSFifo*)*MSMULAWDECODER_MAX_INPUTS); + memset(r->f_outputs,0,sizeof(MSFifo*)*MSMULAWDECODER_MAX_INPUTS); + +} + +void ms_MULAWdecoder_class_init(MSMULAWDecoderClass *klass) +{ + ms_filter_class_init(MS_FILTER_CLASS(klass)); + ms_filter_class_set_name(MS_FILTER_CLASS(klass),"MULAWDecoder"); + MS_FILTER_CLASS(klass)->info=(MSFilterInfo*)&MULAWinfo; + MS_FILTER_CLASS(klass)->max_finputs=MSMULAWDECODER_MAX_INPUTS; + MS_FILTER_CLASS(klass)->max_foutputs=MSMULAWDECODER_MAX_INPUTS; + MS_FILTER_CLASS(klass)->r_maxgran=MULAW_DECODER_RMAXGRAN; + MS_FILTER_CLASS(klass)->w_maxgran=MULAW_DECODER_WMAXGRAN; + MS_FILTER_CLASS(klass)->destroy=(MSFilterDestroyFunc)ms_MULAWdecoder_destroy; + MS_FILTER_CLASS(klass)->process=(MSFilterProcessFunc)ms_MULAWdecoder_process; +} + +void ms_MULAWdecoder_process(MSMULAWDecoder *r) +{ + MSFifo *fi,*fo; + int inlen,outlen; + gchar *s,*d; + int i; + /* process output fifos, but there is only one for this class of filter*/ + + /* this is the simplest process function design: + the filter declares a r_mingran of MULAW_DECODER_RMAXGRAN, so the mediastreamer's + scheduler will call the process function each time there is MULAW_DECODER_RMAXGRAN + bytes to read in the input fifo. If there is more, then it will call it several + time in order to the fifo to be completetly processed. + This is very simple, but not very efficient because of the multiple call function + of MSFilterProcessFunc that may happen. + The MSAlawEncoder implements another design; see it. + */ + + fi=r->f_inputs[0]; + fo=r->f_outputs[0]; + + inlen=ms_fifo_get_read_ptr(fi,MULAW_DECODER_RMAXGRAN,(void**)&s); + if (s==NULL) g_error("ms_MULAWdecoder_process: internal error."); + outlen=ms_fifo_get_write_ptr(fo,MULAW_DECODER_WMAXGRAN,(void**)&d); + if (d!=NULL) + { + for(i=0;i<MULAW_DECODER_RMAXGRAN;i++) + { + *((gint16*)d)=ulaw_to_s16( (unsigned char) s[i]); + d+=2; + } + } + else g_warning("MSMULAWDecoder: Discarding samples !!"); +} + + + +void ms_MULAWdecoder_destroy( MSMULAWDecoder *obj) +{ + g_free(obj); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msMUlawdec.h Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,66 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + +#ifndef MSMULAWDECODER_H +#define MSMULAWDECODER_H + +#include <msfilter.h> +#include <mscodec.h> + +/*this is the class that implements a MULAWdecoder filter*/ + +#define MSMULAWDECODER_MAX_INPUTS 1 /* max output per filter*/ + + +typedef struct _MSMULAWDecoder +{ + /* the MSMULAWDecoder derivates from MSFilter, so the MSFilter object MUST be the first of the MSMULAWDecoder object + in order to the object mechanism to work*/ + MSFilter filter; + MSFifo *f_inputs[MSMULAWDECODER_MAX_INPUTS]; + MSFifo *f_outputs[MSMULAWDECODER_MAX_INPUTS]; +} MSMULAWDecoder; + +typedef struct _MSMULAWDecoderClass +{ + /* the MSMULAWDecoder derivates from MSFilter, so the MSFilter class MUST be the first of the MSMULAWDecoder class + in order to the class mechanism to work*/ + MSFilterClass parent_class; +} MSMULAWDecoderClass; + +/* PUBLIC */ +#define MS_MULAWDECODER(filter) ((MSMULAWDecoder*)(filter)) +#define MS_MULAWDECODER_CLASS(klass) ((MSMULAWDecoderClass*)(klass)) +MSFilter * ms_MULAWdecoder_new(void); + +/* FOR INTERNAL USE*/ +void ms_MULAWdecoder_init(MSMULAWDecoder *r); +void ms_MULAWdecoder_class_init(MSMULAWDecoderClass *klass); +void ms_MULAWdecoder_destroy( MSMULAWDecoder *obj); +void ms_MULAWdecoder_process(MSMULAWDecoder *r); + +/* tuning parameters :*/ +#define MULAW_DECODER_WMAXGRAN 320 +#define MULAW_DECODER_RMAXGRAN 160 + +extern MSCodecInfo MULAWinfo; + + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msMUlawenc.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,99 @@ + /* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + + +#include "msMUlawenc.h" +#include "g711common.h" + +extern MSCodecInfo MULAWinfo; + +static MSMULAWEncoderClass *ms_MULAWencoder_class=NULL; + +MSFilter * ms_MULAWencoder_new(void) +{ + MSMULAWEncoder *r; + + r=g_new(MSMULAWEncoder,1); + ms_MULAWencoder_init(r); + if (ms_MULAWencoder_class==NULL) + { + ms_MULAWencoder_class=g_new(MSMULAWEncoderClass,1); + ms_MULAWencoder_class_init(ms_MULAWencoder_class); + } + MS_FILTER(r)->klass=MS_FILTER_CLASS(ms_MULAWencoder_class); + return(MS_FILTER(r)); +} + + +/* FOR INTERNAL USE*/ +void ms_MULAWencoder_init(MSMULAWEncoder *r) +{ + ms_filter_init(MS_FILTER(r)); + MS_FILTER(r)->infifos=r->f_inputs; + MS_FILTER(r)->outfifos=r->f_outputs; + MS_FILTER(r)->r_mingran=MULAW_ENCODER_RMAXGRAN; /* the filter can be called as soon as there is + something to process */ + memset(r->f_inputs,0,sizeof(MSFifo*)*MSMULAWENCODER_MAX_INPUTS); + memset(r->f_outputs,0,sizeof(MSFifo*)*MSMULAWENCODER_MAX_INPUTS); + +} + +void ms_MULAWencoder_class_init(MSMULAWEncoderClass *klass) +{ + ms_filter_class_init(MS_FILTER_CLASS(klass)); + ms_filter_class_set_name(MS_FILTER_CLASS(klass),"MULAWEncoder"); + MS_FILTER_CLASS(klass)->info=(MSFilterInfo*)&MULAWinfo; + MS_FILTER_CLASS(klass)->max_finputs=MSMULAWENCODER_MAX_INPUTS; + MS_FILTER_CLASS(klass)->max_foutputs=MSMULAWENCODER_MAX_INPUTS; + MS_FILTER_CLASS(klass)->r_maxgran=MULAW_ENCODER_RMAXGRAN; + MS_FILTER_CLASS(klass)->w_maxgran=MULAW_ENCODER_WMAXGRAN; + MS_FILTER_CLASS(klass)->destroy=(MSFilterDestroyFunc)ms_MULAWencoder_destroy; + MS_FILTER_CLASS(klass)->process=(MSFilterProcessFunc)ms_MULAWencoder_process; +} + +void ms_MULAWencoder_process(MSMULAWEncoder *r) +{ + MSFifo *fi,*fo; + int inlen,outlen; + gchar *s,*d; + int i; + /* process output fifos, but there is only one for this class of filter*/ + + fi=r->f_inputs[0]; + fo=r->f_outputs[0]; + inlen=ms_fifo_get_read_ptr(fi,MULAW_ENCODER_RMAXGRAN,(void**)&s); + outlen=ms_fifo_get_write_ptr(fo,MULAW_ENCODER_WMAXGRAN,(void**)&d); + if (d!=NULL) + { + for(i=0;i<MULAW_ENCODER_WMAXGRAN;i++) + { + d[i]=s16_to_ulaw( *((gint16*)s) ); + s+=2; + } + } + else g_warning("MSMULAWDecoder: Discarding samples !!"); +} + + + +void ms_MULAWencoder_destroy( MSMULAWEncoder *obj) +{ + g_free(obj); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msMUlawenc.h Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,63 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + +#ifndef MSMULAWENCODER_H +#define MSMULAWENCODER_H + +#include "mscodec.h" + + +/*this is the class that implements a MULAWencoder filter*/ + +#define MSMULAWENCODER_MAX_INPUTS 1 /* max output per filter*/ + + +typedef struct _MSMULAWEncoder +{ + /* the MSMULAWEncoder derivates from MSFilter, so the MSFilter object MUST be the first of the MSMULAWEncoder object + in order to the object mechanism to work*/ + MSFilter filter; + MSFifo *f_inputs[MSMULAWENCODER_MAX_INPUTS]; + MSFifo *f_outputs[MSMULAWENCODER_MAX_INPUTS]; +} MSMULAWEncoder; + +typedef struct _MSMULAWEncoderClass +{ + /* the MSMULAWEncoder derivates from MSFilter, so the MSFilter class MUST be the first of the MSMULAWEncoder class + in order to the class mechanism to work*/ + MSFilterClass parent_class; +} MSMULAWEncoderClass; + +/* PUBLIC */ +#define MS_MULAWENCODER(filter) ((MSMULAWEncoder*)(filter)) +#define MS_MULAWENCODER_CLASS(klass) ((MSMULAWEncoderClass*)(klass)) +MSFilter * ms_MULAWencoder_new(void); + +/* FOR INTERNAL USE*/ +void ms_MULAWencoder_init(MSMULAWEncoder *r); +void ms_MULAWencoder_class_init(MSMULAWEncoderClass *klass); +void ms_MULAWencoder_destroy( MSMULAWEncoder *obj); +void ms_MULAWencoder_process(MSMULAWEncoder *r); + +/* tuning parameters :*/ +#define MULAW_ENCODER_WMAXGRAN 160 +#define MULAW_ENCODER_RMAXGRAN 320 + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msavdecoder.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,278 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + +#include "msavdecoder.h" +#include "mscodec.h" +extern MSFilter *ms_mpeg_encoder_new(); +extern MSFilter *ms_mpeg4_encoder_new(); +extern MSFilter *ms_h263_encoder_new(); + + +MSCodecInfo MPEGinfo={ + { + "MPEG1 codec", + 0, + MS_FILTER_VIDEO_CODEC, + ms_mpeg_encoder_new, + "This is a MPEG1 codec taken from the ffmpeg project." + }, + ms_mpeg_encoder_new, + ms_mpeg_decoder_new, + 0, + 0, + 0, /*bitrate */ + 0, /*sample freq */ + 0, + "MPV", + 1, + 1 +}; + +MSCodecInfo h263info={ + { + "H263 codec", + 0, + MS_FILTER_VIDEO_CODEC, + ms_h263_encoder_new, + "This is a H263 codec taken from the ffmpeg project." + }, + ms_h263_encoder_new, + ms_h263_decoder_new, + 0, + 0, + 0, /*bitrate */ + 0, /*sample freq */ + 0, + "H263", + 1, + 1 +}; + +MSCodecInfo MPEG4info={ + { + "MPEG4 codec", + 0, + MS_FILTER_VIDEO_CODEC, + ms_mpeg4_encoder_new, + "This is a MPEG4 codec taken from the ffmpeg project." + }, + ms_mpeg4_encoder_new, + ms_mpeg4_decoder_new, + 0, + 0, + 0, /*bitrate */ + 0, /*sample freq */ + 0, + "MP4V-ES", + 1, + 1 +}; + + +void ms_AVCodec_init() +{ + avcodec_init(); + avcodec_register_all(); + ms_filter_register((MSFilterInfo*)&h263info); + //ms_filter_register((MSFilterInfo*)&MPEG4info); +} + + +static MSAVDecoderClass *ms_avdecoder_class=NULL; + +MSFilter *ms_h263decoder_new() +{ + return ms_AVdecoder_new_with_codec(CODEC_ID_H263); +} + +MSFilter *ms_mpeg_decoder_new() +{ + return ms_AVdecoder_new_with_codec(CODEC_ID_MPEG1VIDEO); +} + +MSFilter *ms_mpeg4_decoder_new() +{ + return ms_AVdecoder_new_with_codec(CODEC_ID_MPEG4); +} + +MSFilter *ms_h263_decoder_new(){ + return ms_AVdecoder_new_with_codec(CODEC_ID_H263); +} + +MSFilter * ms_AVdecoder_new_with_codec(enum CodecID codec_id) +{ + MSAVDecoder *enc; + + enc=g_malloc0(sizeof(MSAVDecoder)); + if (ms_avdecoder_class==NULL) + { + ms_avdecoder_class=g_malloc0(sizeof(MSAVDecoderClass)); + ms_AVdecoder_class_init(ms_avdecoder_class); + } + MS_FILTER(enc)->klass=(MSFilterClass*)ms_avdecoder_class; + ms_AVdecoder_init(enc,avcodec_find_decoder(codec_id)); + return MS_FILTER(enc); +} + + +void ms_AVdecoder_init(MSAVDecoder *dec, AVCodec *codec) +{ + gint error; + + ms_filter_init(MS_FILTER(dec)); + MS_FILTER(dec)->inqueues=dec->q_inputs; + MS_FILTER(dec)->outqueues=dec->q_outputs; + avcodec_get_context_defaults(&dec->av_context); + dec->av_codec=codec; + dec->av_opened=0; + dec->skip_gob=1; + dec->obufwrap=NULL; +} + +void ms_AVdecoder_class_init(MSAVDecoderClass *klass) +{ + ms_filter_class_init(MS_FILTER_CLASS(klass)); + ms_filter_class_set_name( MS_FILTER_CLASS(klass),"AVdecoder"); + MS_FILTER_CLASS(klass)->max_qinputs=MSAVDECODER_MAX_INPUTS; + MS_FILTER_CLASS(klass)->max_qoutputs=MSAVDECODER_MAX_INPUTS; + MS_FILTER_CLASS(klass)->r_maxgran=0; + MS_FILTER_CLASS(klass)->w_maxgran=0; + MS_FILTER_CLASS(klass)->destroy=(MSFilterDestroyFunc)ms_AVdecoder_destroy; + MS_FILTER_CLASS(klass)->process=(MSFilterProcessFunc)ms_AVdecoder_process; +} + +void ms_AVdecoder_uninit(MSAVDecoder *dec) +{ + if (dec->obufwrap!=NULL) ms_buffer_destroy(dec->obufwrap); + if (dec->av_opened) avcodec_close(&dec->av_context); +} +void ms_AVdecoder_destroy( MSAVDecoder *obj) +{ + ms_AVdecoder_uninit(obj); + g_free(obj); +} + +gint ms_AVdecoder_set_format(MSAVDecoder *dec, gchar *fmt) +{ + gint format; + if (strcmp(fmt,"YUV420P")==0) format=PIX_FMT_YUV420P; + else if (strcmp(fmt,"YUV422")==0) format=PIX_FMT_YUV422; + else if (strcmp(fmt,"RGB24")==0) format=PIX_FMT_RGB24; + else if (strcmp(fmt,"BGR24")==0) format=PIX_FMT_BGR24; + else if (strcmp(fmt,"YUV422P")==0) format=PIX_FMT_YUV422P; + else if (strcmp(fmt,"YUV444P")==0) format=PIX_FMT_YUV444P; + else { + g_warning("ms_AVdecoder_set_format: unsupported format %s.",fmt); + return -1; + } + dec->output_pix_fmt=format; + return 0; +} + +void ms_AVdecoder_process(MSAVDecoder *r) +{ + AVFrame orig; + AVFrame transformed; + MSQueue *inq,*outq; + MSMessage *inm,*outm; + gint error; + gint got_picture; + gint len; + unsigned char *data; + AVCodecContext *ctx=&r->av_context; + gint gob_num; + + inq=r->q_inputs[0]; + outq=r->q_outputs[0]; + + /* get a picture from the input queue */ + inm=ms_queue_get(inq); + g_return_if_fail(inm!=NULL); + if (inm->size > 0) + { + guint32 *p = inm->data; + + if (!r->av_opened){ + error=avcodec_open(&r->av_context, r->av_codec); + if (error!=0) g_warning("avcodec_open() failed: %i",error); + else r->av_opened=1; + } + + gob_num = (ntohl(*p) >> 10) & 0x1f; + ms_trace("gob %i, size %i", gob_num, inm->size); + ms_trace("ms_AVdecoder_process: received %08x %08x", ntohl(p[0]), ntohl(p[1])); + + /* remove H.263 Payload Header */ + p[0] = htonl( ntohl(p[0]) & 0x0000ffff ); + + if (gob_num == 0){ + if (r->skip_gob == 0) + { + unsigned char *data = r->buf_compressed; + ms_trace("ms_AVdecoder_process: decoding %08x %08x %08x", ntohl(((unsigned int *)data)[0]), ntohl(((unsigned int *)data)[1]), ntohl(((unsigned int *)data)[2])); + while (r->buf_size > 0) { + len=avcodec_decode_video(&r->av_context,&orig,&got_picture,data,r->buf_size /*inm->size*/); + if (len<0) { + ms_warning("ms_AVdecoder_process: error %i.",len); + break; + } + if (got_picture) { + ms_trace("ms_AVdecoder_process: got_picture: width=%i height=%i fmt=%i", + ctx->width,ctx->height,ctx->pix_fmt); + /* set the image in the wanted format */ + outm=ms_message_alloc(); + if (r->obufwrap==NULL){ + r->obufwrap=ms_buffer_new(avpicture_get_size(r->output_pix_fmt,ctx->width,ctx->height)); + r->obufwrap->ref_count++; + } + ms_message_set_buf(outm,r->obufwrap); + avpicture_fill(&transformed,outm->data,r->output_pix_fmt,ctx->width,ctx->height); + img_convert(&transformed, r->output_pix_fmt, + &orig,ctx->pix_fmt,ctx->width,ctx->height); + ms_queue_put(outq,outm); + } + r->buf_size -= len; + data += len; + } + } + else { + r->skip_gob = 0; + } + memcpy(r->buf_compressed, inm->data, inm->size); + r->buf_size = inm->size; + } + else { + memcpy(r->buf_compressed + r->buf_size, inm->data, inm->size); + r->buf_size += inm->size; + } + } + ms_message_destroy(inm); +} + + +void ms_AVdecoder_set_width(MSAVDecoder *av,gint w) +{ + av->av_context.width=av->width=w; +} + +void ms_AVdecoder_set_height(MSAVDecoder *av,gint h) +{ + av->av_context.height=av->height=h; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msavdecoder.h Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,87 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + + +#ifndef MSAVDECODER_H +#define MSAVDECODER_H + +#include "msfilter.h" + + +#include <avcodec.h> + +/*this is the class that implements a AVdecoder filter*/ + +#define MSAVDECODER_MAX_INPUTS 1 /* max output per filter*/ + + +struct _MSAVDecoder +{ + /* the MSAVDecoder derivates from MSFilter, so the MSFilter object MUST be the first of the MSAVDecoder object + in order to the object mechanism to work*/ + MSFilter filter; + MSQueue *q_inputs[MSAVDECODER_MAX_INPUTS]; + MSQueue *q_outputs[MSAVDECODER_MAX_INPUTS]; + AVCodec *av_codec; /*the AVCodec from which this MSFilter is related */ + AVCodecContext av_context; /* the context of the AVCodec */ + gint av_opened; + int output_pix_fmt; + int width; + int height; + int skip_gob; + unsigned char buf_compressed[100000]; + int buf_size; + MSBuffer *obufwrap; /* alternate buffer, when format change is needed*/ +}; + +typedef struct _MSAVDecoder MSAVDecoder; + +struct _MSAVDecoderClass +{ + /* the MSAVDecoder derivates from MSFilter, so the MSFilter class MUST be the first of the MSAVDecoder class + in order to the class mechanism to work*/ + MSFilterClass parent_class; +}; + +typedef struct _MSAVDecoderClass MSAVDecoderClass; + +/* PUBLIC */ +#define MS_AVDECODER(filter) ((MSAVDecoder*)(filter)) +#define MS_AVDECODER_CLASS(klass) ((MSAVDecoderClass*)(klass)) + +MSFilter *ms_h263_decoder_new(); +MSFilter *ms_mpeg_decoder_new(); +MSFilter *ms_mpeg4_decoder_new(); +MSFilter * ms_AVdecoder_new_with_codec(enum CodecID codec_id); + +gint ms_AVdecoder_set_format(MSAVDecoder *dec, gchar *fmt); +void ms_AVdecoder_set_width(MSAVDecoder *av,gint w); +void ms_AVdecoder_set_height(MSAVDecoder *av,gint h); + +/* FOR INTERNAL USE*/ +void ms_AVdecoder_init(MSAVDecoder *r, AVCodec *codec); +void ms_AVdecoder_uninit(MSAVDecoder *enc); +void ms_AVdecoder_class_init(MSAVDecoderClass *klass); +void ms_AVdecoder_destroy( MSAVDecoder *obj); +void ms_AVdecoder_process(MSAVDecoder *r); + +void ms_AVCodec_init(); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msavencoder.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,235 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + +#include "msavencoder.h" +#include "msutils.h" + +extern MSCodecInfo MPEG4info; +extern MSCodecInfo MPEGinfo; +extern MSCodecInfo h263info; + +static MSAVEncoderClass *ms_avencoder_class=NULL; +static void ms_AVencoder_rtp_callback (AVCodecContext *ctx,void *data, int size, int packet_number); + +MSFilter *ms_h263_encoder_new() +{ + return ms_AVencoder_new_with_codec(CODEC_ID_H263,&h263info); +} + +MSFilter *ms_mpeg_encoder_new() +{ + return ms_AVencoder_new_with_codec(CODEC_ID_MPEG1VIDEO, &MPEGinfo); +} + +MSFilter *ms_mpeg4_encoder_new() +{ + return ms_AVencoder_new_with_codec(CODEC_ID_MPEG4,&MPEG4info); +} + +MSFilter * ms_AVencoder_new_with_codec(enum CodecID codec_id, MSCodecInfo *info) +{ + MSAVEncoder *enc; + AVCodec *avc; + enc=g_malloc0(sizeof(MSAVEncoder)); + if (ms_avencoder_class==NULL) + { + ms_avencoder_class=g_malloc0(sizeof(MSAVEncoderClass)); + ms_AVencoder_class_init(ms_avencoder_class); + } + MS_FILTER(enc)->klass=(MSFilterClass*)ms_avencoder_class; + avc=avcodec_find_encoder(codec_id); + if (avc==NULL) g_error("unknown av codec."); + ms_AVencoder_init(enc,avc); + return MS_FILTER(enc); +} + + +void ms_AVencoder_init(MSAVEncoder *enc, AVCodec *codec) +{ + gint error; + AVCodecContext *c=&enc->av_context; + + ms_filter_init(MS_FILTER(enc)); + MS_FILTER(enc)->inqueues=enc->q_inputs; + MS_FILTER(enc)->outqueues=enc->q_outputs; + /* put default values */ + memset(c, 0, sizeof(AVCodecContext)); + avcodec_get_context_defaults(c); + + /* put sample parameters */ + c->bit_rate = 400000; + /* resolution must be a multiple of two */ + c->width = VIDEO_SIZE_CIF_W; + c->height = VIDEO_SIZE_CIF_H; + /* frames per second */ + c->frame_rate = 15; + c->frame_rate_base = 1; + c->gop_size = 10; /* emit one intra frame every x frames */ + c->rtp_mode = 1; + c->rtp_payload_size = 1488; + c->opaque = (void *) enc; + c->rtp_callback = ms_AVencoder_rtp_callback; + c->pix_fmt=PIX_FMT_YUV420P; + + enc->av_opened=0; + enc->av_codec=codec; + enc->yuv_buf=NULL; + enc->comp_buf=NULL; + /*set default input format */ + ms_AVencoder_set_format(enc,"RGB24"); +} + +void ms_AVencoder_class_init(MSAVEncoderClass *klass) +{ + ms_filter_class_init(MS_FILTER_CLASS(klass)); + MS_FILTER_CLASS(klass)->info=0; + MS_FILTER_CLASS(klass)->max_qinputs=MSAVENCODER_MAX_INPUTS; + MS_FILTER_CLASS(klass)->max_qoutputs=MSAVENCODER_MAX_OUTPUTS; + MS_FILTER_CLASS(klass)->r_maxgran=0; + MS_FILTER_CLASS(klass)->w_maxgran=0; + MS_FILTER_CLASS(klass)->destroy=(MSFilterDestroyFunc)ms_AVencoder_destroy; + MS_FILTER_CLASS(klass)->process=(MSFilterProcessFunc)ms_AVencoder_process; + ms_filter_class_set_name(MS_FILTER_CLASS(klass),"AVEncoder"); + +} + +void ms_AVencoder_uninit(MSAVEncoder *enc) +{ + if (enc->av_opened) + avcodec_close(&enc->av_context); + if (enc->comp_buf!=NULL) { + ms_buffer_destroy(enc->comp_buf); + enc->comp_buf=NULL; + } + if (enc->yuv_buf!=NULL) { + ms_buffer_destroy(enc->yuv_buf); + enc->yuv_buf=NULL; + } + +} +void ms_AVencoder_destroy( MSAVEncoder *obj) +{ + ms_AVencoder_uninit(obj); + g_free(obj); +} + + +void ms_AVencoder_set_frame_rate(MSAVEncoder *obj, gint frame_rate, gint frame_rate_base) +{ + obj->av_context.frame_rate = frame_rate; + obj->av_context.frame_rate_base = frame_rate_base; +} + +static void ms_AVencoder_rtp_callback (AVCodecContext *ctx, void *data, int size, int packet_number) +{ + MSAVEncoder *r = MS_AVENCODER(ctx->opaque); + MSQueue *outq = r->q_outputs[0]; + MSMessage *outm; + guint32 *p = (guint32 *) data; + gint gob_num = (ntohl(*p) >> 10) & 0x1f; + + /*g_message("ms_AVencoder_rtp_callback: packet %i, size %i, GOB number %i", packet_number, size, gob_num);*/ + ms_trace("ms_AVencoder_rtp_callback: received %08x %08x", ntohl(p[0]), ntohl(p[1])); + /* set the H.263 Payload Header (RFC 2429) */ + p[0] = ntohl( (0x04000000) | (ntohl(p[0]) & 0x0000ffff) ); /* P=1, V=0, PLEN=0 */ + ms_trace("ms_AVencoder_rtp_callback: sending %08x %08x", ntohl(p[0]), ntohl(p[1])); + outm = ms_message_new(size); + memcpy(outm->data,data,size); + ms_queue_put(outq, outm); +} + +void ms_AVencoder_process(MSAVEncoder *r) +{ + AVFrame orig; + AVFrame pict; + AVCodecContext *c=&r->av_context; + MSQueue *inq,*outq; + MSMessage *inm,*outm; + gint error; + + inq=r->q_inputs[0]; + outq=r->q_outputs[0]; + + /* get a picture from the input queue */ + inm=ms_queue_get(inq); + g_return_if_fail(inm!=NULL); + + /* allocate a new image */ + if (r->yuv_buf==NULL){ + gint bsize = avpicture_get_size(c->pix_fmt,c->width,c->height); + r->yuv_buf=ms_buffer_new(bsize); + r->yuv_buf->ref_count++; + + r->comp_buf=ms_buffer_new(bsize/2); + r->comp_buf->ref_count++; + } + if (!r->av_opened || r->av_context.codec == NULL){ + error=avcodec_open(c, r->av_codec); + ms_trace("image format is %i.",c->pix_fmt); + if (error!=0) { + g_warning("avcodec_open() failed: %i",error); + return; + }else r->av_opened=1; + } + outm=ms_message_alloc(); + /* convert image if necessary */ + if (r->input_pix_fmt!=c->pix_fmt){ + ms_trace("Changing picture format."); + avpicture_fill((AVPicture*)&orig,inm->data,r->input_pix_fmt,c->width,c->height); + avpicture_fill((AVPicture*)&pict,r->yuv_buf->buffer,c->pix_fmt,c->width,c->height); + if (img_convert((AVPicture*)&pict,c->pix_fmt,(AVPicture*)&orig,r->input_pix_fmt,c->width,c->height) < 0) { + g_warning("img_convert failed"); + return; + } + //if (pict.data[0]==NULL) g_error("img_convert failed."); + ms_message_set_buf(outm,r->yuv_buf); + } + else + { + avpicture_fill((AVPicture*)&pict,inm->data,c->pix_fmt,c->width,c->height); + ms_message_set_buf(outm,inm->buffer); + } + /* timestamp used by ffmpeg, unset here */ + pict.pts=AV_NOPTS_VALUE; + error=avcodec_encode_video(c, r->comp_buf->buffer, r->comp_buf->size, &pict); + if (error<=0) ms_warning("ms_AVencoder_process: error %i.",error); + else ms_trace("ms_AVencoder_process: video encoding done"); + if (r->q_outputs[1]!=NULL) ms_queue_put(r->q_outputs[1],outm); + else ms_message_destroy(outm); + ms_message_destroy(inm); +} + +gint ms_AVencoder_set_format(MSAVEncoder *enc, gchar *fmt) +{ + gint format; + if (strcmp(fmt,"YUV420P")==0) format=PIX_FMT_YUV420P; + else if (strcmp(fmt,"YUV422")==0) format=PIX_FMT_YUV422; + else if (strcmp(fmt,"RGB24")==0) format=PIX_FMT_RGB24; + else if (strcmp(fmt,"BGR24")==0) format=PIX_FMT_BGR24; + else if (strcmp(fmt,"YUV422P")==0) format=PIX_FMT_YUV422P; + else if (strcmp(fmt,"YUV444P")==0) format=PIX_FMT_YUV444P; + else { + g_warning("ms_AVdecoder_set_format: unsupported format %s.",fmt); + return -1; + } + enc->input_pix_fmt=format; + + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msavencoder.h Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,90 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + + +#ifndef MSAVENCODER_H +#define MSAVENCODER_H + +#include "msfilter.h" +#include "mscodec.h" +#include <avcodec.h> + +/*this is the class that implements a AVencoder filter*/ + +#define MSAVENCODER_MAX_INPUTS 1 /* max output per filter*/ +#define MSAVENCODER_MAX_OUTPUTS 2 + +struct _MSAVEncoder +{ + /* the MSAVEncoder derivates from MSFilter, so the MSFilter object MUST be the first of the MSAVEncoder object + in order to the object mechanism to work*/ + MSFilter filter; + MSQueue *q_inputs[MSAVENCODER_MAX_INPUTS]; + MSQueue *q_outputs[MSAVENCODER_MAX_OUTPUTS]; + AVCodec *av_codec; /*the AVCodec from which this MSFilter is related */ + AVCodecContext av_context; /* the context of the AVCodec */ + gint input_pix_fmt; + gint av_opened; + MSBuffer *comp_buf; + MSBuffer *yuv_buf; +}; + +typedef struct _MSAVEncoder MSAVEncoder; +/* MSAVEncoder always outputs planar YUV and accept any incoming format you should setup using + ms_AVencoder_set_format() +q_outputs[0] is the compressed video stream output +q_outputs[1] is a YUV planar buffer of the image it receives in input. +*/ + + +struct _MSAVEncoderClass +{ + /* the MSAVEncoder derivates from MSFilter, so the MSFilter class MUST be the first of the MSAVEncoder class + in order to the class mechanism to work*/ + MSFilterClass parent_class; +}; + +typedef struct _MSAVEncoderClass MSAVEncoderClass; + +/* PUBLIC */ +#define MS_AVENCODER(filter) ((MSAVEncoder*)(filter)) +#define MS_AVENCODER_CLASS(klass) ((MSAVEncoderClass*)(klass)) + +MSFilter *ms_h263_encoder_new(); +MSFilter *ms_mpeg_encoder_new(); +MSFilter *ms_mpeg4_encoder_new(); +MSFilter * ms_AVencoder_new_with_codec(enum CodecID codec_id, MSCodecInfo *info); + +gint ms_AVencoder_set_format(MSAVEncoder *enc, gchar *fmt); + +#define ms_AVencoder_set_width(av,w) (av)->av_context.width=(w) +#define ms_AVencoder_set_height(av,h) (av)->av_context.height=(h) +#define ms_AVencoder_set_bit_rate(av,r) (av)->av_context.bit_rate=(r) + +void ms_AVencoder_set_frame_rate(MSAVEncoder *enc, gint frame_rate, gint frame_rate_base); + +/* FOR INTERNAL USE*/ +void ms_AVencoder_init(MSAVEncoder *r, AVCodec *codec); +void ms_AVencoder_uninit(MSAVEncoder *enc); +void ms_AVencoder_class_init(MSAVEncoderClass *klass); +void ms_AVencoder_destroy( MSAVEncoder *obj); +void ms_AVencoder_process(MSAVEncoder *r); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msbuffer.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,94 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + +#include "msbuffer.h" +#include "msutils.h" +#include <string.h> + + + +MSBuffer * ms_buffer_new(guint32 size) +{ + MSBuffer *buf; + buf=(MSBuffer*)g_malloc(sizeof(MSBuffer)+size); + buf->ref_count=0; + buf->size=size; + ms_trace("ms_buffer_new: Allocating buffer of %i bytes.",size); + /* allocate the data buffer: there is a lot of optmisation that can be done by using a pool of cached buffers*/ + buf->buffer=((char*)(buf))+sizeof(MSBuffer); /* to avoid to do two allocations, + buffer info and buffer are contigous.*/ + buf->flags=MS_BUFFER_CONTIGUOUS; + return(buf); +} + +MSBuffer *ms_buffer_alloc(gint flags) +{ + MSBuffer *buf; + buf=(MSBuffer*)g_malloc(sizeof(MSBuffer)); + buf->ref_count=0; + buf->size=0; + buf->buffer=NULL; + buf->flags=0; + return(buf); +} + + +void ms_buffer_destroy(MSBuffer *buf) +{ + if (buf->flags & MS_BUFFER_CONTIGUOUS){ + g_free(buf); + } + else { + g_free(buf->buffer); + g_free(buf); + } +} + +MSMessage *ms_message_alloc() +{ + MSMessage *m=g_malloc(sizeof(MSMessage)); + memset(m,0,sizeof(MSMessage)); + return m; +} + +MSMessage *ms_message_new(gint size) +{ + MSMessage *m=ms_message_alloc(); + MSBuffer *buf=ms_buffer_new(size); + ms_message_set_buf(m,buf); + return m; +} + +void ms_message_destroy(MSMessage *m) +{ + /* the buffer is freed if its ref_count goes to zero */ + if (m->buffer!=NULL){ + m->buffer->ref_count--; + if (m->buffer->ref_count==0) ms_buffer_destroy(m->buffer); + } + g_free(m); +} + +MSMessage * ms_message_dup(MSMessage *m) +{ + MSMessage *msg=ms_message_alloc(); + ms_message_set_buf(msg,m->buffer); + return msg; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msbuffer.h Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,75 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + + +#ifndef MSBUFFER_H +#define MSBUFFER_H +#include <config.h> + +#ifdef HAVE_GLIB +#include <glib.h> +#else +#include <uglib.h> +#endif + + +#define MS_BUFFER_LARGE 4092 + + +typedef struct _MSBuffer +{ + gchar *buffer; + guint32 size; + guint16 ref_count; + guint16 flags; +#define MS_BUFFER_CONTIGUOUS (1) +}MSBuffer; + +MSBuffer * ms_buffer_new(guint32 size); +void ms_buffer_destroy(MSBuffer *buf); + +struct _MSMessage +{ + MSBuffer *buffer; /* points to a MSBuffer */ + void *data; /*points to buffer->buffer */ + guint32 size; /* the size of the buffer to read in data. It may not be the + physical size (I mean buffer->buffer->size */ + struct _MSMessage *next; + struct _MSMessage *prev; /* MSMessage are queued into MSQueues */ +}; + +typedef struct _MSMessage MSMessage; + + +MSBuffer *ms_buffer_alloc(gint flags); +MSMessage *ms_message_new(gint size); + +#define ms_message_set_buf(m,b) do { (b)->ref_count++; (m)->buffer=(b); (m)->data=(b)->buffer; (m)->size=(b)->size; }while(0) +#define ms_message_unset_buf(m) do { (m)->buffer->ref_count--; (m)->buffer=NULL; (m)->size=0; (m)->data=NULL; } while(0) + +#define ms_message_size(m) (m)->size +void ms_message_destroy(MSMessage *m); + +MSMessage * ms_message_dup(MSMessage *m); + +/* allocate a single message without buffer */ +MSMessage *ms_message_alloc(); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/mscodec.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,257 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + + +#include "mscodec.h" + +#ifdef SME +#include "msGSMdecoder.h" +#include "msLPC10decoder.h" +#endif +#include "msMUlawdec.h" +#include "msAlawdec.h" + +#ifdef TRUESPEECH +extern MSCodecInfo TrueSpeechinfo; +#endif + +#ifdef VIDEO_ENABLED +extern void ms_AVCodec_init(); +#endif + +#define UDP_HDR_SZ 8 +#define RTP_HDR_SZ 12 +#define IP4_HDR_SZ 20 /*20 is the minimum, but there may be some options*/ + + + + +/* register all statically linked codecs */ +void ms_codec_register_all() +{ +// ms_filter_register(MS_FILTER_INFO(&GSMinfo)); +// ms_filter_register(MS_FILTER_INFO(&LPC10info)); + ms_filter_register(MS_FILTER_INFO(&MULAWinfo)); + ms_filter_register(MS_FILTER_INFO(&ALAWinfo)); +#ifdef TRUESPEECH + ms_filter_register(MS_FILTER_INFO(&TrueSpeechinfo)); +#endif +#ifdef VIDEO_ENABLED + ms_AVCodec_init(); +#endif + +} + +/* returns a list of MSCodecInfo */ +GList * ms_codec_get_all_audio() +{ + GList *audio_codecs=NULL; + GList *elem=filter_list; + MSFilterInfo *info; + while (elem!=NULL) + { + info=(MSFilterInfo *)elem->data; + if (info->type==MS_FILTER_AUDIO_CODEC){ + audio_codecs=g_list_append(audio_codecs,info); + } + elem=g_list_next(elem); + } + return audio_codecs; +} + + +MSCodecInfo * ms_audio_codec_info_get(gchar *name) +{ + GList *elem=filter_list; + MSFilterInfo *info; + while (elem!=NULL) + { + info=(MSFilterInfo *)elem->data; + if ( (info->type==MS_FILTER_AUDIO_CODEC) ){ + MSCodecInfo *codinfo=(MSCodecInfo *)info; + if (strcmp(codinfo->description,name)==0){ + return MS_CODEC_INFO(info); + } + } + elem=g_list_next(elem); + } + return NULL; +} + +MSCodecInfo * ms_video_codec_info_get(gchar *name) +{ + GList *elem=filter_list; + MSFilterInfo *info; + while (elem!=NULL) + { + info=(MSFilterInfo *)elem->data; + if ( (info->type==MS_FILTER_VIDEO_CODEC) ){ + MSCodecInfo *codinfo=(MSCodecInfo *)info; + if (strcmp(codinfo->description,name)==0){ + return MS_CODEC_INFO(info); + } + } + elem=g_list_next(elem); + } + return NULL; +} + +/* returns a list of MSCodecInfo */ +GList * ms_codec_get_all_video() +{ + GList *video_codecs=NULL; + GList *elem=filter_list; + MSFilterInfo *info; + while (elem!=NULL) + { + info=(MSFilterInfo *)elem->data; + if (info->type==MS_FILTER_VIDEO_CODEC){ + video_codecs=g_list_append(video_codecs,info); + } + elem=g_list_next(elem); + } + return video_codecs; +} + +MSFilter * ms_encoder_new(gchar *name) +{ + GList *elem=filter_list; + MSFilterInfo *info; + while (elem!=NULL) + { + info=(MSFilterInfo *)elem->data; + if ((info->type==MS_FILTER_AUDIO_CODEC) || (info->type==MS_FILTER_VIDEO_CODEC)){ + MSCodecInfo *codinfo=(MSCodecInfo *)elem->data; + if (strcmp(info->name,name)==0){ + return codinfo->encoder(); + } + } + elem=g_list_next(elem); + } + return NULL; +} + +MSFilter * ms_decoder_new(gchar *name) +{ + GList *elem=filter_list; + MSFilterInfo *info; + while (elem!=NULL) + { + info=(MSFilterInfo *)elem->data; + if ((info->type==MS_FILTER_AUDIO_CODEC) || (info->type==MS_FILTER_VIDEO_CODEC)){ + MSCodecInfo *codinfo=(MSCodecInfo *)elem->data; + if (strcmp(info->name,name)==0){ + return codinfo->decoder(); + } + } + elem=g_list_next(elem); + } + return NULL; +} + +MSFilter * ms_encoder_new_with_pt(gint pt) +{ + GList *elem=filter_list; + MSFilterInfo *info; + while (elem!=NULL) + { + info=(MSFilterInfo *)elem->data; + if ((info->type==MS_FILTER_AUDIO_CODEC) || (info->type==MS_FILTER_VIDEO_CODEC)){ + MSCodecInfo *codinfo=(MSCodecInfo *)elem->data; + if (codinfo->pt==pt){ + return codinfo->encoder(); + } + } + elem=g_list_next(elem); + } + return NULL; +} + +MSFilter * ms_decoder_new_with_pt(gint pt) +{ + GList *elem=filter_list; + MSFilterInfo *info; + while (elem!=NULL) + { + info=(MSFilterInfo *)elem->data; + if ((info->type==MS_FILTER_AUDIO_CODEC) || (info->type==MS_FILTER_VIDEO_CODEC)){ + MSCodecInfo *codinfo=(MSCodecInfo *)elem->data; + if (codinfo->pt==pt){ + return codinfo->decoder(); + } + } + elem=g_list_next(elem); + } + return NULL; +} + +MSFilter * ms_decoder_new_with_string_id(gchar *id) +{ + GList *elem=filter_list; + MSFilterInfo *info; + while (elem!=NULL) + { + info=(MSFilterInfo *)elem->data; + if ((info->type==MS_FILTER_AUDIO_CODEC) || (info->type==MS_FILTER_VIDEO_CODEC)){ + MSCodecInfo *codinfo=(MSCodecInfo *)elem->data; + if (strcasecmp(codinfo->description,id)==0){ + return codinfo->decoder(); + } + } + elem=g_list_next(elem); + } + return NULL; +} + +MSFilter * ms_encoder_new_with_string_id(gchar *id) +{ + GList *elem=filter_list; + MSFilterInfo *info; + while (elem!=NULL) + { + info=(MSFilterInfo *)elem->data; + if ((info->type==MS_FILTER_AUDIO_CODEC) || (info->type==MS_FILTER_VIDEO_CODEC)){ + MSCodecInfo *codinfo=(MSCodecInfo *)elem->data; + if (strcasecmp(codinfo->description,id)==0){ + return codinfo->encoder(); + } + } + elem=g_list_next(elem); + } + return NULL; +} +/* return 0 if codec can be used with bandwidth, -1 else*/ +int ms_codec_is_usable(MSCodecInfo *codec,double bandwidth) +{ + double codec_band; + double npacket; + double packet_size; + + if (((MSFilterInfo*)codec)->type==MS_FILTER_AUDIO_CODEC) + { + /* calculate the total bandwdith needed by codec (including headers for rtp, udp, ip)*/ + /* number of packet per second*/ + npacket=2.0*(double)(codec->rate)/(double)(codec->fr_size); + packet_size=(double)(codec->dt_size)+UDP_HDR_SZ+RTP_HDR_SZ+IP4_HDR_SZ; + codec_band=packet_size*8.0*npacket; + } + else return -1; + return(codec_band<bandwidth); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/mscodec.h Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,67 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + +#ifndef MSCODEC_H +#define MSCODEC_H + +#include "msfilter.h" + +struct _MSCodecInfo +{ + MSFilterInfo info; + MSFilterNewFunc encoder; + MSFilterNewFunc decoder; + gint fr_size; /* size in char of the uncompressed frame */ + gint dt_size; /* size in char of the compressed frame */ + gint bitrate; /* the minimum bit rate in bits/second */ + gint rate; /*frequency */ + gint pt; /* the payload type number associated with this codec*/ + gchar *description; /* a rtpmap field to describe the codec */ + guint is_usable:1; /* linphone set this flag to remember if it can use this codec considering the total bandwidth*/ + guint is_selected:1; /* linphone (user) set this flag if he allows this codec to be used*/ +}; + +typedef struct _MSCodecInfo MSCodecInfo; + +MSFilter * ms_encoder_new(gchar *name); +MSFilter * ms_decoder_new(gchar *name); + +MSFilter * ms_encoder_new_with_pt(gint pt); +MSFilter * ms_decoder_new_with_pt(gint pt); + +MSFilter * ms_encoder_new_with_string_id(gchar *id); +MSFilter * ms_decoder_new_with_string_id(gchar *id); + +/* return 0 if codec can be used with bandwidth, -1 else*/ +int ms_codec_is_usable(MSCodecInfo *codec,double bandwidth); + +GList * ms_codec_get_all_audio(); + +GList * ms_codec_get_all_video(); + +MSCodecInfo * ms_audio_codec_info_get(gchar *name); +MSCodecInfo * ms_video_codec_info_get(gchar *name); + +/* register all statically linked codecs */ +void ms_codec_register_all(); + +#define MS_CODEC_INFO(codinfo) ((MSCodecInfo*)codinfo) + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/mscopy.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,96 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + + +#include "mscopy.h" +#include <unistd.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <string.h> +#include <errno.h> + +static MSCopyClass *ms_copy_class=NULL; + +MSFilter * ms_copy_new(void) +{ + MSCopy *r; + + r=g_new(MSCopy,1); + ms_copy_init(r); + if (ms_copy_class==NULL) + { + ms_copy_class=g_new(MSCopyClass,1); + ms_copy_class_init(ms_copy_class); + } + MS_FILTER(r)->klass=MS_FILTER_CLASS(ms_copy_class); + return(MS_FILTER(r)); +} + + +/* FOR INTERNAL USE*/ +void ms_copy_init(MSCopy *r) +{ + ms_filter_init(MS_FILTER(r)); + MS_FILTER(r)->infifos=r->f_inputs; + MS_FILTER(r)->outfifos=r->f_outputs; + MS_FILTER(r)->r_mingran=MSCOPY_DEF_GRAN; + memset(r->f_inputs,0,sizeof(MSFifo*)*MSCOPY_MAX_INPUTS); + memset(r->f_outputs,0,sizeof(MSFifo*)*MSCOPY_MAX_INPUTS); +} + +void ms_copy_class_init(MSCopyClass *klass) +{ + ms_filter_class_init(MS_FILTER_CLASS(klass)); + ms_filter_class_set_name(MS_FILTER_CLASS(klass),"fifocopier"); + MS_FILTER_CLASS(klass)->max_finputs=MSCOPY_MAX_INPUTS; + MS_FILTER_CLASS(klass)->max_foutputs=MSCOPY_MAX_INPUTS; + MS_FILTER_CLASS(klass)->r_maxgran=MSCOPY_DEF_GRAN; + MS_FILTER_CLASS(klass)->w_maxgran=MSCOPY_DEF_GRAN; + MS_FILTER_CLASS(klass)->destroy=(MSFilterDestroyFunc)ms_copy_destroy; + MS_FILTER_CLASS(klass)->process=(MSFilterProcessFunc)ms_copy_process; +} + +void ms_copy_process(MSCopy *r) +{ + MSFifo *fi,*fo; + int err1; + gint gran=MS_FILTER(r)->klass->r_maxgran; + void *s,*d; + + /* process output fifos, but there is only one for this class of filter*/ + + fi=r->f_inputs[0]; + fo=r->f_outputs[0]; + if (fi!=NULL) + { + err1=ms_fifo_get_read_ptr(fi,gran,&s); + if (err1>0) err1=ms_fifo_get_write_ptr(fo,gran,&d); + if (err1>0) + { + memcpy(d,s,gran); + } + } +} + +void ms_copy_destroy( MSCopy *obj) +{ + g_free(obj); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/mscopy.h Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,61 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + + +#ifndef MSCOPY_H +#define MSCOPY_H + +#include "msfilter.h" + + +/*this is the class that implements a copy filter*/ + +#define MSCOPY_MAX_INPUTS 1 /* max output per filter*/ + +#define MSCOPY_DEF_GRAN 64 /* the default granularity*/ + +typedef struct _MSCopy +{ + /* the MSCopy derivates from MSFilter, so the MSFilter object MUST be the first of the MSCopy object + in order to the object mechanism to work*/ + MSFilter filter; + MSFifo *f_inputs[MSCOPY_MAX_INPUTS]; + MSFifo *f_outputs[MSCOPY_MAX_INPUTS]; +} MSCopy; + +typedef struct _MSCopyClass +{ + /* the MSCopy derivates from MSFilter, so the MSFilter class MUST be the first of the MSCopy class + in order to the class mechanism to work*/ + MSFilterClass parent_class; +} MSCopyClass; + +/* PUBLIC */ +#define MS_COPY(filter) ((MSCopy*)(filter)) +#define MS_COPY_CLASS(klass) ((MSCopyClass*)(klass)) +MSFilter * ms_copy_new(void); + +/* FOR INTERNAL USE*/ +void ms_copy_init(MSCopy *r); +void ms_copy_class_init(MSCopyClass *klass); +void ms_copy_destroy( MSCopy *obj); +void ms_copy_process(MSCopy *r); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msfdispatcher.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,94 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a dispatcher of the GNU Lesser 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 +*/ + + +#include "msfdispatcher.h" + +static MSFdispatcherClass *ms_fdispatcher_class=NULL; + +MSFilter * ms_fdispatcher_new(void) +{ + MSFdispatcher *obj; + obj=g_malloc(sizeof(MSFdispatcher)); + if (ms_fdispatcher_class==NULL){ + ms_fdispatcher_class=g_malloc(sizeof(MSFdispatcherClass)); + ms_fdispatcher_class_init(ms_fdispatcher_class); + } + MS_FILTER(obj)->klass=MS_FILTER_CLASS(ms_fdispatcher_class); + ms_fdispatcher_init(obj); + return MS_FILTER(obj); +} + + +void ms_fdispatcher_init(MSFdispatcher *obj) +{ + ms_filter_init(MS_FILTER(obj)); + MS_FILTER(obj)->infifos=obj->f_inputs; + MS_FILTER(obj)->outfifos=obj->f_outputs; + MS_FILTER(obj)->r_mingran=MS_FDISPATCHER_DEF_GRAN; + memset(obj->f_inputs,0,sizeof(MSFifo*)*MS_FDISPATCHER_MAX_INPUTS); + memset(obj->f_outputs,0,sizeof(MSFifo*)*MS_FDISPATCHER_MAX_OUTPUTS); +} + + + +void ms_fdispatcher_class_init(MSFdispatcherClass *klass) +{ + MSFilterClass *parent_class=MS_FILTER_CLASS(klass); + ms_filter_class_init(parent_class); + ms_filter_class_set_name(parent_class,"fdispatcher"); + parent_class->max_finputs=MS_FDISPATCHER_MAX_INPUTS; + parent_class->max_foutputs=MS_FDISPATCHER_MAX_OUTPUTS; + parent_class->r_maxgran=MS_FDISPATCHER_DEF_GRAN; + parent_class->w_maxgran=MS_FDISPATCHER_DEF_GRAN; + parent_class->destroy=(MSFilterDestroyFunc)ms_fdispatcher_destroy; + parent_class->process=(MSFilterProcessFunc)ms_fdispatcher_process; +} + + +void ms_fdispatcher_destroy( MSFdispatcher *obj) +{ + g_free(obj); +} + +void ms_fdispatcher_process(MSFdispatcher *obj) +{ + gint i; + MSFifo *inf=obj->f_inputs[0]; + + + if (inf!=NULL){ + void *s,*d; + /* dispatch fifos */ + while ( ms_fifo_get_read_ptr(inf,MS_FDISPATCHER_DEF_GRAN,&s) >0 ){ + for (i=0;i<MS_FDISPATCHER_MAX_OUTPUTS;i++){ + MSFifo *outf=obj->f_outputs[i]; + + if (outf!=NULL) + { + ms_fifo_get_write_ptr(outf,MS_FDISPATCHER_DEF_GRAN,&d); + if (d!=NULL) memcpy(d,s,MS_FDISPATCHER_DEF_GRAN); + } + } + } + } +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msfdispatcher.h Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,61 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a dispatcher of the GNU Lesser 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 +*/ + + +#ifndef MSFDISPATCHER_H +#define MSFDISPATCHER_H + +#include "msfilter.h" + + +/*this is the class that implements a fdispatcher filter*/ + +#define MS_FDISPATCHER_MAX_INPUTS 1 +#define MS_FDISPATCHER_MAX_OUTPUTS 5 +#define MS_FDISPATCHER_DEF_GRAN 64 /* the default granularity*/ + +typedef struct _MSFdispatcher +{ + /* the MSFdispatcher derivates from MSFilter, so the MSFilter object MUST be the first of the MSFdispatcher object + in order to the object mechanism to work*/ + MSFilter filter; + MSFifo *f_inputs[MS_FDISPATCHER_MAX_INPUTS]; + MSFifo *f_outputs[MS_FDISPATCHER_MAX_OUTPUTS]; +} MSFdispatcher; + +typedef struct _MSFdispatcherClass +{ + /* the MSFdispatcher derivates from MSFilter, so the MSFilter class MUST be the first of the MSFdispatcher class + in order to the class mechanism to work*/ + MSFilterClass parent_class; +} MSFdispatcherClass; + +/* PUBLIC */ +#define MS_FDISPATCHER(filter) ((MSFdispatcher*)(filter)) +#define MS_FDISPATCHER_CLASS(klass) ((MSFdispatcherClass*)(klass)) +MSFilter * ms_fdispatcher_new(void); + +/* FOR INTERNAL USE*/ +void ms_fdispatcher_init(MSFdispatcher *r); +void ms_fdispatcher_class_init(MSFdispatcherClass *klass); +void ms_fdispatcher_destroy( MSFdispatcher *obj); +void ms_fdispatcher_process(MSFdispatcher *r); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msfifo.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,168 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + +#include <errno.h> +#include <string.h> +#include "msutils.h" +#include "msfifo.h" + +MSFifo * ms_fifo_new(MSBuffer *buf, gint r_gran, gint w_gran, gint r_offset, gint w_offset) +{ + MSFifo *fifo; + gint saved_offset=MAX(r_gran+r_offset,w_offset); + + g_return_val_if_fail(saved_offset<=(buf->size),NULL); + fifo=g_malloc(sizeof(MSFifo)); + fifo->buffer=buf; + fifo->r_gran=r_gran; + fifo->w_gran=w_gran; + fifo->begin=fifo->wr_ptr=fifo->rd_ptr=buf->buffer+saved_offset; + fifo->readsize=0; + fifo->size=fifo->writesize=buf->size-saved_offset; + fifo->saved_offset= saved_offset; + fifo->r_end=fifo->w_end=buf->buffer+buf->size; + fifo->pre_end=fifo->w_end-saved_offset; + buf->ref_count++; + fifo->prev_data=NULL; + fifo->next_data=NULL; + ms_trace("fifo base=%x, begin=%x, end=%x, saved_offset=%i, size=%i" + ,fifo->buffer->buffer,fifo->begin,fifo->w_end,fifo->saved_offset,fifo->size); + return(fifo); +} + +MSFifo * ms_fifo_new_with_buffer(gint r_gran, gint w_gran, gint r_offset, gint w_offset, + gint min_fifo_size) +{ + MSFifo *fifo; + MSBuffer *buf; + gint saved_offset=MAX(r_gran+r_offset,w_offset); + gint fifo_size; + gint tmp; + if (min_fifo_size==0) min_fifo_size=w_gran; + + /* we must allocate a fifo with a size multiple of min_fifo_size, + with a saved_offset */ + if (min_fifo_size>MS_BUFFER_LARGE) + fifo_size=(min_fifo_size) + saved_offset; + else fifo_size=(6*min_fifo_size) + saved_offset; + buf=ms_buffer_new(fifo_size); + fifo=ms_fifo_new(buf,r_gran,w_gran,r_offset,w_offset); + ms_trace("fifo_size=%i",fifo_size); + return(fifo); +} + +void ms_fifo_destroy( MSFifo *fifo) +{ + g_free(fifo); +} + +void ms_fifo_destroy_with_buffer(MSFifo *fifo) +{ + ms_buffer_destroy(fifo->buffer); + ms_fifo_destroy(fifo); +} + +gint ms_fifo_get_read_ptr(MSFifo *fifo, gint bsize, void **ret_ptr) +{ + gchar *rnext; + + *ret_ptr=NULL; + //ms_trace("ms_fifo_get_read_ptr: entering."); + g_return_val_if_fail(bsize<=fifo->r_gran,-EINVAL); + + if (bsize>fifo->readsize) + { + ms_trace("Not enough data: bsize=%i, readsize=%i",bsize,fifo->readsize); + return (-ENODATA); + } + + rnext=fifo->rd_ptr+bsize; + if (rnext<=fifo->r_end){ + + *ret_ptr=fifo->rd_ptr; + fifo->rd_ptr=rnext; + }else{ + int unread=fifo->r_end-fifo->rd_ptr; + *ret_ptr=fifo->begin-unread; + memcpy(fifo->buffer->buffer,fifo->r_end-fifo->saved_offset,fifo->saved_offset); + fifo->rd_ptr=(char*)(*ret_ptr) + bsize; + fifo->r_end=fifo->w_end; /* this is important ! */ + ms_trace("moving read ptr to %x",fifo->rd_ptr); + + } + /* update write size*/ + fifo->writesize+=bsize; + fifo->readsize-=bsize; + return bsize; +} + + +void ms_fifo_update_write_ptr(MSFifo *fifo, gint written){ + gint reserved=fifo->wr_ptr-fifo->prev_wr_ptr; + gint unwritten; + g_return_if_fail(reserved>=0); + unwritten=reserved-written; + g_return_if_fail(unwritten>=0); + /* fix readsize and writesize */ + fifo->readsize-=unwritten; + fifo->writesize+=unwritten; + fifo->wr_ptr+=written; +} + +gint ms_fifo_get_write_ptr(MSFifo *fifo, gint bsize, void **ret_ptr) +{ + gchar *wnext; + + *ret_ptr=NULL; + //ms_trace("ms_fifo_get_write_ptr: Entering."); + g_return_val_if_fail(bsize<=fifo->w_gran,-EINVAL); + if (bsize>fifo->writesize) + { + ms_trace("Not enough space: bsize=%i, writesize=%i",bsize,fifo->writesize); + *ret_ptr=NULL; + return(-ENODATA); + } + wnext=fifo->wr_ptr+bsize; + if (wnext<=fifo->w_end){ + *ret_ptr=fifo->wr_ptr; + fifo->wr_ptr=wnext; + }else{ + *ret_ptr=fifo->begin; + fifo->r_end=fifo->wr_ptr; + fifo->wr_ptr=fifo->begin+bsize; + ms_trace("moving write ptr to %x",fifo->wr_ptr); + } + fifo->prev_wr_ptr=*ret_ptr; + /* update readsize*/ + fifo->readsize+=bsize; + fifo->writesize-=bsize; + //ms_trace("ms_fifo_get_write_ptr: readsize=%i, writesize=%i",fifo->readsize,fifo->writesize); + return bsize; +} + +gint ms_fifo_get_rw_ptr(MSFifo *f1,void **p1,gint minsize1, + MSFifo *f2,void **p2,gint minsize2) +{ + gint rbsize,wbsize; + + rbsize=MIN(f1->readsize,(f1->pre_end-f1->rd_ptr)); + wbsize=MIN(f2->writesize,(f2->w_end-f2->wr_ptr)); + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msfifo.h Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,73 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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_GLIB +#include <glib.h> +#else +#include "glist.h" +#endif +#include "msbuffer.h" + +typedef struct _MSFifo +{ + gint r_gran; /*maximum granularity for reading*/ + gint w_gran; /*maximum granularity for writing*/ + gchar * rd_ptr; /* read pointer on the position where there is something to read on the MSBuffer */ + guint32 readsize; + gchar * wr_ptr; + gchar * prev_wr_ptr; + guint32 writesize; /* write pointer on the position where it is possible to write on the MSBuffer */ + gchar * begin; /* rd_ptr et wr_ptr must all be >=begin*/ + guint32 size; /* the length of the fifo, but this may not be equal to buffer->size*/ + guint32 saved_offset; + gchar * pre_end; /* the end of the buffer that is copied at the begginning when we wrap around*/ + gchar * w_end; /* when a wr ptr is expected to exceed end_offset, + it must be wrapped around to go at the beginning of the buffer. This is the end of the buffer*/ + gchar * r_end; /* this is the last position written at the end of the fifo. If a read ptr is expected to + exceed this pointer, it must be put at the begginning of the buffer */ + void *prev_data; /*user data, usually the writing MSFilter*/ + void *next_data; /* user data, usually the reading MSFilter */ + MSBuffer *buffer; +} MSFifo; + +/* constructor*/ +/* r_gran: max granularity for reading (in number of bytes)*/ +/* w_gran: max granularity for writing (in number of bytes)*/ +/* r_offset: number of bytes that are kept available behind read pointer (for recursive filters)*/ +/* w_offset: number of bytes that are kept available behind write pointer (for recursive filters)*/ +/* buf is a MSBuffer that should be compatible with the above parameter*/ +MSFifo * ms_fifo_new(MSBuffer *buf, gint r_gran, gint w_gran, gint r_offset, gint w_offset); + +/*does the same that ms_fifo_new(), but also allocate a compatible buffer automatically*/ +MSFifo * ms_fifo_new_with_buffer(gint r_gran, gint w_gran, gint r_offset, gint w_offset, gint min_buffer_size); + +void ms_fifo_destroy( MSFifo *fifo); + +void ms_fifo_destroy_with_buffer(MSFifo *fifo); + +/* get data to read */ +gint ms_fifo_get_read_ptr(MSFifo *fifo, gint bsize, void **ret_ptr); + +/* get a buffer to write*/ +gint ms_fifo_get_write_ptr(MSFifo *fifo, gint bsize, void **ret_ptr); + +/* in case the buffer got by ms_fifo_get_write_ptr() could not be filled completely, you must +tell it by using this function */ +void ms_fifo_update_write_ptr(MSFifo *fifo, gint written);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msfilter.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,537 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + + +#include <errno.h> +#include "msfilter.h" + + + +void ms_filter_init(MSFilter *filter) +{ + filter->finputs=0; + filter->foutputs=0; + filter->qinputs=0; + filter->qoutputs=0; + filter->infifos=NULL; + filter->outfifos=NULL; + filter->inqueues=NULL; + filter->outqueues=NULL; + filter->lock=g_mutex_new(); + filter->min_fifo_size=0x7fff; + filter->notify_event=NULL; + filter->userdata=NULL; +} + +void ms_filter_uninit(MSFilter *filter) +{ + g_mutex_free(filter->lock); +} + +void ms_filter_class_init(MSFilterClass *filterclass) +{ + filterclass->name=NULL; + filterclass->max_finputs=0; + filterclass->max_foutputs=0; + filterclass->max_qinputs=0; + filterclass->max_qoutputs=0; + filterclass->r_maxgran=0; + filterclass->w_maxgran=0; + filterclass->r_offset=0; + filterclass->w_offset=0; + filterclass->set_property=NULL; + filterclass->get_property=NULL; + filterclass->setup=NULL; + filterclass->unsetup=NULL; + filterclass->process=NULL; + filterclass->destroy=NULL; + filterclass->attributes=0; + filterclass->ref_count=0; +} + +/* find output queue */ +gint find_oq(MSFilter *m1,MSQueue *oq) +{ + gint i; + + for (i=0;i<MS_FILTER_GET_CLASS(m1)->max_qoutputs;i++){ + if (m1->outqueues[i]==oq) return i; + } + + return -1; +} + +/* find input queue */ +gint find_iq(MSFilter *m1,MSQueue *iq) +{ + gint i; + for (i=0;i<MS_FILTER_GET_CLASS(m1)->max_qinputs;i++){ + if (m1->inqueues[i]==iq) return i; + } + return -1; +} + +/* find output fifo */ +gint find_of(MSFilter *m1,MSFifo *of) +{ + gint i; + for (i=0;i<MS_FILTER_GET_CLASS(m1)->max_foutputs;i++){ + if (m1->outfifos[i]==of) return i; + } + + return -1; +} + +/* find input fifo */ +gint find_if(MSFilter *m1,MSFifo *inf) +{ + gint i; + + for (i=0;i<MS_FILTER_GET_CLASS(m1)->max_finputs;i++){ + if (m1->infifos[i]==inf) return i; + } + + return -1; +} + +#define find_free_iq(_m1) find_iq(_m1,NULL) +#define find_free_oq(_m1) find_oq(_m1,NULL) +#define find_free_if(_m1) find_if(_m1,NULL) +#define find_free_of(_m1) find_of(_m1,NULL) + +int ms_filter_add_link(MSFilter *m1, MSFilter *m2) +{ + gint m1_q=-1; + gint m1_f=-1; + gint m2_q=-1; + gint m2_f=-1; + /* determine the type of link we can add */ + m1_q=find_free_oq(m1); + m1_f=find_free_of(m1); + m2_q=find_free_iq(m2); + m2_f=find_free_if(m2); + if ((m1_q!=-1) && (m2_q!=-1)){ + /* link with queues */ + ms_trace("m1_q=%i , m2_q=%i",m1_q,m2_q); + return ms_filter_link(m1,m1_q,m2,m2_q,LINK_QUEUE); + } + if ((m1_f!=-1) && (m2_f!=-1)){ + /* link with queues */ + ms_trace("m1_f=%i , m2_f=%i",m1_f,m2_f); + return ms_filter_link(m1,m1_f,m2,m2_f,LINK_FIFO); + } + g_warning("ms_filter_add_link: could not link."); + return -1; +} +/** + * ms_filter_link: + * @m1: A #MSFilter object. + * @pin1: The pin number on @m1. + * @m2: A #MSFilter object. + * @pin2: The pin number on @m2. + * @linktype: Type of connection, it may be #LINK_QUEUE, #LINK_FIFOS. + * + * This function links two MSFilter object between them. It must be used to make chains of filters. + * All data outgoing from pin1 of m1 will go to the input pin2 of m2. + * The way to communicate can be fifos or queues, depending of the nature of the filters. Filters can have + * multiple queue pins and multiple fifo pins, but most of them have only one queue input/output or only one + * fifo input/output. Fifos are usally used by filters doing audio processing, while queues are used by filters doing + * video processing. + * + * Returns: 0 if successfull, a negative value reprensenting the errno.h error. + */ +int ms_filter_link(MSFilter *m1, gint pin1, MSFilter *m2,gint pin2, int linktype) +{ + MSQueue *q; + MSFifo *fifo; + + g_message("ms_filter_add_link: %s,%i -> %s,%i",m1->klass->name,pin1,m2->klass->name,pin2); + switch(linktype) + { + case LINK_QUEUE: + /* Are filter m1 and m2 able to accept more queues connections ?*/ + g_return_val_if_fail(m1->qoutputs<MS_FILTER_GET_CLASS(m1)->max_qoutputs,-EMLINK); + g_return_val_if_fail(m2->qinputs<MS_FILTER_GET_CLASS(m2)->max_qinputs,-EMLINK); + /* Are filter m1 and m2 valid with their inputs and outputs ?*/ + g_return_val_if_fail(m1->outqueues!=NULL,-EFAULT); + g_return_val_if_fail(m2->inqueues!=NULL,-EFAULT); + /* are the requested pins exists ?*/ + g_return_val_if_fail(pin1<MS_FILTER_GET_CLASS(m1)->max_qoutputs,-EINVAL); + g_return_val_if_fail(pin2<MS_FILTER_GET_CLASS(m2)->max_qinputs,-EINVAL); + /* are the requested pins free ?*/ + g_return_val_if_fail(m1->outqueues[pin1]==NULL,-EBUSY); + g_return_val_if_fail(m2->inqueues[pin2]==NULL,-EBUSY); + + q=ms_queue_new(); + m1->outqueues[pin1]=m2->inqueues[pin2]=q; + m1->qoutputs++; + m2->qinputs++; + q->prev_data=(void*)m1; + q->next_data=(void*)m2; + break; + case LINK_FIFO: + /* Are filter m1 and m2 able to accept more fifo connections ?*/ + g_return_val_if_fail(m1->foutputs<MS_FILTER_GET_CLASS(m1)->max_foutputs,-EMLINK); + g_return_val_if_fail(m2->finputs<MS_FILTER_GET_CLASS(m2)->max_finputs,-EMLINK); + /* Are filter m1 and m2 valid with their inputs and outputs ?*/ + g_return_val_if_fail(m1->outfifos!=NULL,-EFAULT); + g_return_val_if_fail(m2->infifos!=NULL,-EFAULT); + /* are the requested pins exists ?*/ + g_return_val_if_fail(pin1<MS_FILTER_GET_CLASS(m1)->max_foutputs,-EINVAL); + g_return_val_if_fail(pin2<MS_FILTER_GET_CLASS(m2)->max_finputs,-EINVAL); + /* are the requested pins free ?*/ + g_return_val_if_fail(m1->outfifos[pin1]==NULL,-EBUSY); + g_return_val_if_fail(m2->infifos[pin2]==NULL,-EBUSY); + + if (MS_FILTER_GET_CLASS(m1)->attributes & FILTER_IS_SOURCE) + { + /* configure min_fifo_size */ + fifo=ms_fifo_new_with_buffer(MS_FILTER_GET_CLASS(m2)->r_maxgran, + MS_FILTER_GET_CLASS(m1)->w_maxgran, + MS_FILTER_GET_CLASS(m2)->r_offset, + MS_FILTER_GET_CLASS(m1)->w_offset, + MS_FILTER_GET_CLASS(m1)->w_maxgran); + m2->min_fifo_size=MS_FILTER_GET_CLASS(m1)->w_maxgran; + } + else + { + gint next_size; + ms_trace("ms_filter_add_link: min_fifo_size=%i",m1->min_fifo_size); + fifo=ms_fifo_new_with_buffer(MS_FILTER_GET_CLASS(m2)->r_maxgran, + MS_FILTER_GET_CLASS(m1)->w_maxgran, + MS_FILTER_GET_CLASS(m2)->r_offset, + MS_FILTER_GET_CLASS(m1)->w_offset, + m1->min_fifo_size); + if (MS_FILTER_GET_CLASS(m2)->r_maxgran>0){ + next_size=(m1->min_fifo_size* + (MS_FILTER_GET_CLASS(m2)->w_maxgran)) / + (MS_FILTER_GET_CLASS(m2)->r_maxgran); + }else next_size=m1->min_fifo_size; + ms_trace("ms_filter_add_link: next_size=%i",next_size); + m2->min_fifo_size=next_size; + } + + + m1->outfifos[pin1]=m2->infifos[pin2]=fifo; + m1->foutputs++; + m2->finputs++; + fifo->prev_data=(void*)m1; + fifo->next_data=(void*)m2; + break; + } + return 0; +} +/** + * ms_filter_unlink: + * @m1: A #MSFilter object. + * @pin1: The pin number on @m1. + * @m2: A #MSFilter object. + * @pin2: The pin number on @m2. + * @linktype: Type of connection, it may be #LINK_QUEUE, #LINK_FIFOS. + * + * Unlink @pin1 of filter @m1 from @pin2 of filter @m2. @linktype specifies what type of connection is removed. + * + * Returns: 0 if successfull, a negative value reprensenting the errno.h error. + */ +int ms_filter_unlink(MSFilter *m1, gint pin1, MSFilter *m2,gint pin2,gint linktype) +{ + switch(linktype) + { + case LINK_QUEUE: + /* Are filter m1 and m2 valid with their inputs and outputs ?*/ + g_return_val_if_fail(m1->outqueues!=NULL,-EFAULT); + g_return_val_if_fail(m2->inqueues!=NULL,-EFAULT); + /* are the requested pins exists ?*/ + g_return_val_if_fail(pin1<MS_FILTER_GET_CLASS(m1)->max_qoutputs,-EINVAL); + g_return_val_if_fail(pin2<MS_FILTER_GET_CLASS(m2)->max_qinputs,-EINVAL); + /* are the requested pins busy ?*/ + g_return_val_if_fail(m1->outqueues[pin1]!=NULL,-ENOENT); + g_return_val_if_fail(m2->inqueues[pin2]!=NULL,-ENOENT); + /* are the two pins connected together ?*/ + g_return_val_if_fail(m1->outqueues[pin1]==m2->inqueues[pin2],-EINVAL); + + ms_queue_destroy(m1->outqueues[pin1]); + m1->outqueues[pin1]=m2->inqueues[pin2]=NULL; + m1->qoutputs--; + m2->qinputs--; + + break; + case LINK_FIFO: + /* Are filter m1 and m2 valid with their inputs and outputs ?*/ + g_return_val_if_fail(m1->outfifos!=NULL,-EFAULT); + g_return_val_if_fail(m2->infifos!=NULL,-EFAULT); + /* are the requested pins exists ?*/ + g_return_val_if_fail(pin1<MS_FILTER_GET_CLASS(m1)->max_foutputs,-EINVAL); + g_return_val_if_fail(pin2<MS_FILTER_GET_CLASS(m2)->max_finputs,-EINVAL); + /* are the requested pins busy ?*/ + g_return_val_if_fail(m1->outfifos[pin1]!=NULL,-ENOENT); + g_return_val_if_fail(m2->infifos[pin2]!=NULL,-ENOENT); + /* are the two pins connected together ?*/ + g_return_val_if_fail(m1->outfifos[pin1]==m2->infifos[pin2],-EINVAL); + ms_fifo_destroy_with_buffer(m1->outfifos[pin1]); + m1->outfifos[pin1]=m2->infifos[pin2]=NULL; + m1->foutputs--; + m2->finputs--; + break; + } + return 0; +} + +/** + *ms_filter_remove_links: + *@m1: a filter + *@m2: another filter. + * + * Removes all links between m1 and m2. + * + *Returns: 0 if one more link have been removed, -1 if not. +**/ +gint ms_filter_remove_links(MSFilter *m1, MSFilter *m2) +{ + int i,j; + int removed=-1; + MSQueue *qo; + MSFifo *fo; + /* takes all outputs of m1, and removes the one that goes to m2 */ + if (m1->outqueues!=NULL){ + for (i=0;i<MS_FILTER_GET_CLASS(m1)->max_qoutputs;i++) + { + qo=m1->outqueues[i]; + if (qo!=NULL){ + MSFilter *rmf; + /* test if the queue connects to m2 */ + rmf=(MSFilter*)qo->next_data; + if (rmf==m2){ + j=find_iq(rmf,qo); + if (j==-1) g_error("Could not find input queue: impossible case."); + ms_filter_unlink(m1,i,m2,j,LINK_QUEUE); + removed=0; + } + } + } + } + if (m1->outfifos!=NULL){ + for (i=0;i<MS_FILTER_GET_CLASS(m1)->max_foutputs;i++) + { + fo=m1->outfifos[i]; + if (fo!=NULL){ + MSFilter *rmf; + /* test if the queue connects to m2 */ + rmf=(MSFilter*)fo->next_data; + if (rmf==m2){ + j=find_if(rmf,fo); + if (j==-1) g_error("Could not find input fifo: impossible case."); + ms_filter_unlink(m1,i,m2,j,LINK_FIFO); + removed=0; + } + } + } + } + return removed; +} + +/** + * ms_filter_fifos_have_data: + * @f: a #MSFilter object. + * + * Tells if the filter has enough data in its input fifos in order to be executed succesfully. + * + * Returns: 1 if it can be executed, 0 else. + */ +gint ms_filter_fifos_have_data(MSFilter *f) +{ + gint i,j; + gint max_inputs=f->klass->max_finputs; + gint con_inputs=f->finputs; + MSFifo *fifo; + /* test fifos */ + for(i=0,j=0; (i<max_inputs) && (j<con_inputs);i++) + { + fifo=f->infifos[i]; + if (fifo!=NULL) + { + j++; + if (fifo->readsize==0) return 0; + if (fifo->readsize>=f->r_mingran) return 1; + } + } + return 0; +} + +/** + * ms_filter_queues_have_data: + * @f: a #MSFilter object. + * + * Tells if the filter has enough data in its input queues in order to be executed succesfully. + * + * Returns: 1 if it can be executed, 0 else. + */ +gint ms_filter_queues_have_data(MSFilter *f) +{ + gint i,j; + gint max_inputs=f->klass->max_qinputs; + gint con_inputs=f->qinputs; + MSQueue *q; + /* test queues */ + for(i=0,j=0; (i<max_inputs) && (j<con_inputs);i++) + { + q=f->inqueues[i]; + if (q!=NULL) + { + j++; + if (ms_queue_can_get(q)) return 1; + } + } + return 0; +} + + + +void ms_filter_destroy(MSFilter *f) +{ + /* first check if the filter is disconnected from any others */ + g_return_if_fail(f->finputs==0); + g_return_if_fail(f->foutputs==0); + g_return_if_fail(f->qinputs==0); + g_return_if_fail(f->qoutputs==0); + f->klass->destroy(f); +} + +GList *filter_list=NULL; + +void ms_filter_register(MSFilterInfo *info) +{ + gpointer tmp; + tmp=g_list_find(filter_list,info); + if (tmp==NULL) filter_list=g_list_append(filter_list,(gpointer)info); +} + +void ms_filter_unregister(MSFilterInfo *info) +{ + filter_list=g_list_remove(filter_list,(gpointer)info); +} + +static gint compare_names(gpointer info, gpointer name) +{ + MSFilterInfo *i=(MSFilterInfo*) info; + return (strcmp(i->name,name)); +} + +MSFilterInfo * ms_filter_get_by_name(const gchar *name) +{ + GList *elem=g_list_find_custom(filter_list, + (gpointer)name,(GCompareFunc)compare_names); + if (elem!=NULL){ + return (MSFilterInfo*)elem->data; + } + return NULL; +} + + + +MSFilter * ms_filter_new_with_name(const gchar *name) +{ + MSFilterInfo *info=ms_filter_get_by_name(name); + if (info!=NULL) return info->constructor(); + g_warning("ms_filter_new_with_name: no filter named %s found.",name); + return NULL; +} + + +/* find the first codec in the left part of the stream */ +MSFilter * ms_filter_search_upstream_by_type(MSFilter *f,MSFilterType type) +{ + MSFilter *tmp=f; + MSFilterInfo *info; + + if ((tmp->infifos!=NULL) && (tmp->infifos[0]!=NULL)){ + tmp=(MSFilter*) tmp->infifos[0]->prev_data; + while(1){ + info=MS_FILTER_GET_CLASS(tmp)->info; + if (info!=NULL){ + if ( (info->type==type) ){ + return tmp; + } + } + if ((tmp->infifos!=NULL) && (tmp->infifos[0]!=NULL)) + tmp=(MSFilter*) tmp->infifos[0]->prev_data; + else break; + } + } + tmp=f; + if ((tmp->inqueues!=NULL) && (tmp->inqueues[0]!=NULL)){ + tmp=(MSFilter*) tmp->inqueues[0]->prev_data; + while(1){ + + info=MS_FILTER_GET_CLASS(tmp)->info; + if (info!=NULL){ + if ( (info->type==type)){ + return tmp; + } + }else g_warning("ms_filter_search_upstream_by_type: filter %s has no info." + ,MS_FILTER_GET_CLASS(tmp)->name); + if ((tmp->inqueues!=NULL) && (tmp->inqueues[0]!=NULL)) + tmp=(MSFilter*) tmp->inqueues[0]->prev_data; + else break; + } + } + return NULL; +} + + +int ms_filter_set_property(MSFilter *f, MSFilterProperty prop,void *value) +{ + if (f->klass->set_property!=NULL){ + return f->klass->set_property(f,prop,value); + } + return 0; +} + +int ms_filter_get_property(MSFilter *f, MSFilterProperty prop,void *value) +{ + if (f->klass->get_property!=NULL){ + return f->klass->get_property(f,prop,value); + } + return -1; +} + +void ms_filter_set_notify_func(MSFilter* filter,MSFilterNotifyFunc func, gpointer userdata) +{ + filter->notify_event=func; + filter->userdata=userdata; +} + +void ms_filter_notify_event(MSFilter *filter,gint event, gpointer arg) +{ + if (filter->notify_event!=NULL){ + filter->notify_event(filter,event,arg,filter->userdata); + } +} + +void swap_buffer(gchar *buffer, gint len) +{ + int i; + gchar tmp; + for (i=0;i<len;i+=2){ + tmp=buffer[i]; + buffer[i]=buffer[i+1]; + buffer[i+1]=tmp; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msfilter.h Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,201 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + + +#ifndef MSFILTER_H +#define MSFILTER_H + +#include <config.h> + +#ifdef HAVE_GLIB +#include <glib.h> +#include <gmodule.h> +#else +#undef VERSION +#undef PACKAGE +#include <uglib.h> +#endif + +#include <string.h> +#include "msutils.h" +#include "msfifo.h" +#include "msqueue.h" + +struct _MSFilter; +/*this is the abstract object and class for all filter types*/ +typedef gint (*MSFilterNotifyFunc)(struct _MSFilter*, gint event, gpointer arg, gpointer userdata); + +struct _MSFilter +{ + struct _MSFilterClass *klass; + GMutex *lock; + guchar finputs; /* number of connected fifo inputs*/ + guchar foutputs; /* number of connected fifo outputs*/ + guchar qinputs; /* number of connected queue inputs*/ + guchar qoutputs; /* number of connected queue outputs*/ + gint min_fifo_size; /* set when linking*/ + gint r_mingran; /* read minimum granularity (for fifos). + It can be zero so that the filter can accept any size of reading data*/ + MSFifo **infifos; /*pointer to a table of pointer to input fifos*/ + MSFifo **outfifos; /*pointer to a table of pointer to output fifos*/ + MSQueue **inqueues; /*pointer to a table of pointer to input queues*/ + MSQueue **outqueues; /*pointer to a table of pointer to output queues*/ + MSFilterNotifyFunc notify_event; + gpointer userdata; +}; + +typedef struct _MSFilter MSFilter; + +typedef enum{ + MS_FILTER_PROPERTY_FREQ, /* value is int */ + MS_FILTER_PROPERTY_BITRATE, /*value is int */ + MS_FILTER_PROPERTY_CHANNELS,/*value is int */ + MS_FILTER_PROPERTY_FMTP /* value is string */ +}MSFilterProperty; + +#define MS_FILTER_PROPERTY_STRING_MAX_SIZE 256 + +typedef MSFilter * (*MSFilterNewFunc)(void); +typedef void (*MSFilterProcessFunc)(MSFilter *); +typedef void (*MSFilterDestroyFunc)(MSFilter *); +typedef int (*MSFilterPropertyFunc)(MSFilter *,int ,void*); +typedef void (*MSFilterSetupFunc)(MSFilter *, void *); /*2nd arg is the sync */ + +typedef struct _MSFilterClass +{ + struct _MSFilterInfo *info; /*pointer to a filter_info */ + gchar *name; + guchar max_finputs; /* maximum number of fifo inputs*/ + guchar max_foutputs; /* maximum number of fifo outputs*/ + guchar max_qinputs; /* maximum number of queue inputs*/ + guchar max_qoutputs; /* maximum number of queue outputs*/ + gint r_maxgran; /* read maximum granularity (for fifos)*/ + gint w_maxgran; /* write maximum granularity (for fifos)*/ + gint r_offset; /* size of kept samples behind read pointer (for fifos)*/ + gint w_offset; /* size of kept samples behind write pointer (for fifos)*/ + MSFilterPropertyFunc set_property; + MSFilterPropertyFunc get_property; + MSFilterSetupFunc setup; /* called when attaching to sync */ + void (*process)(MSFilter *filter); + MSFilterSetupFunc unsetup; /* called when detaching from sync */ + void (*destroy)(MSFilter *filter); + guint attributes; +#define FILTER_HAS_FIFOS (0x0001) +#define FILTER_HAS_QUEUES (0x0001<<1) +#define FILTER_IS_SOURCE (0x0001<<2) +#define FILTER_IS_SINK (0x0001<<3) +#define FILTER_CAN_SYNC (0x0001<<4) + guint ref_count; /*number of object using the class*/ +} MSFilterClass; + + + +#define MS_FILTER(obj) ((MSFilter*)obj) +#define MS_FILTER_CLASS(klass) ((MSFilterClass*)klass) +#define MS_FILTER_GET_CLASS(obj) ((MSFilterClass*)((MS_FILTER(obj)->klass))) + +void ms_filter_class_init(MSFilterClass *filterclass); +void ms_filter_init(MSFilter *filter); + +#define ms_filter_class_set_attr(filter,flag) ((filter)->attributes|=(flag)) +#define ms_filter_class_unset_attr(filter,flag) ((filter)->attributes&=~(flag)) + +#define ms_filter_class_set_name(__klass,__name) (__klass)->name=g_strdup((__name)) +#define ms_filter_class_set_info(_klass,_info) (_klass)->info=(_info) +/* public*/ + +#define ms_filter_process(filter) ((filter)->klass->process((filter))) + +#define ms_filter_lock(filter) g_mutex_lock((filter)->lock) +#define ms_filter_unlock(filter) g_mutex_unlock((filter)->lock) +/* low level connect functions */ +int ms_filter_link(MSFilter *m1, gint pin1, MSFilter *m2,gint pin2, gint linktype); +int ms_filter_unlink(MSFilter *m1, gint pin1, MSFilter *m2,gint pin2,gint linktype); + +/* high level connect functions */ +int ms_filter_add_link(MSFilter *m1, MSFilter *m2); +int ms_filter_remove_links(MSFilter *m1, MSFilter *m2); + +void ms_filter_set_notify_func(MSFilter* filter,MSFilterNotifyFunc func, gpointer userdata); +void ms_filter_notify_event(MSFilter *filter,gint event, gpointer arg); + +int ms_filter_set_property(MSFilter *f,MSFilterProperty property, void *value); +int ms_filter_get_property(MSFilter *f,MSFilterProperty property, void *value); + + +gint ms_filter_fifos_have_data(MSFilter *f); +gint ms_filter_queues_have_data(MSFilter *f); + +void ms_filter_uninit(MSFilter *obj); +void ms_filter_destroy(MSFilter *f); + +#define ms_filter_get_mingran(f) ((f)->r_mingran) +#define ms_filter_set_mingran(f,gran) ((f)->r_mingran=(gran)) + +#define LINK_DEFAULT 0 +#define LINK_FIFO 1 +#define LINK_QUEUE 2 + + +#define MSFILTER_VERSION(a,b,c) (((a)<<2)|((b)<<1)|(c)) + +enum _MSFilterType +{ + MS_FILTER_DISK_IO, + MS_FILTER_AUDIO_CODEC, + MS_FILTER_VIDEO_CODEC, + MS_FILTER_NET_IO, + MS_FILTER_VIDEO_IO, + MS_FILTER_AUDIO_IO, + MS_FILTER_OTHER +}; + +typedef enum _MSFilterType MSFilterType; + + +/* find the first codec in the left part of the stream */ +MSFilter * ms_filter_search_upstream_by_type(MSFilter *f,MSFilterType type); + +struct _MSFilterInfo +{ + gchar *name; + gint version; + MSFilterType type; + MSFilterNewFunc constructor; + char *description; /*some textual information*/ +}; + +typedef struct _MSFilterInfo MSFilterInfo; + +void ms_filter_register(MSFilterInfo *finfo); +void ms_filter_unregister(MSFilterInfo *finfo); +MSFilterInfo * ms_filter_get_by_name(const gchar *name); + +MSFilter * ms_filter_new_with_name(const gchar *name); + + + +extern GList *filter_list; +#define MS_FILTER_INFO(obj) ((MSFilterInfo*)obj) + +void swap_buffer(gchar *buffer, gint len); + + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msilbcdec.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,194 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + +#include <config.h> + +#ifdef HAVE_ILBC + + +#include "msilbcdec.h" +#include "msilbcenc.h" +#include "mscodec.h" +#include <stdlib.h> +#include <stdio.h> + + + +extern MSFilter * ms_ilbc_encoder_new(void); + +MSCodecInfo ilbc_info={ + { + "iLBC codec", + 0, + MS_FILTER_AUDIO_CODEC, + ms_ilbc_encoder_new, + "A speech codec suitable for robust voice communication over IP" + }, + ms_ilbc_encoder_new, + ms_ilbc_decoder_new, + 0, /* not applicable, 2 modes */ + 0, /* not applicable, 2 modes */ + 15200, + 8000, + 97, + "iLBC", + 1, + 1, +}; + + +void ms_ilbc_codec_init() +{ + ms_filter_register(MS_FILTER_INFO(&ilbc_info)); +} + + + +static MSILBCDecoderClass *ms_ilbc_decoder_class=NULL; + +MSFilter * ms_ilbc_decoder_new(void) +{ + MSILBCDecoder *r; + + r=g_new(MSILBCDecoder,1); + ms_ilbc_decoder_init(r); + if (ms_ilbc_decoder_class==NULL) + { + ms_ilbc_decoder_class=g_new(MSILBCDecoderClass,1); + ms_ilbc_decoder_class_init(ms_ilbc_decoder_class); + } + MS_FILTER(r)->klass=MS_FILTER_CLASS(ms_ilbc_decoder_class); + return(MS_FILTER(r)); +} + + +int ms_ilbc_decoder_set_property(MSILBCDecoder *obj, MSFilterProperty prop, char *value) +{ + switch(prop){ + case MS_FILTER_PROPERTY_FMTP: + if (!value) return; + if (strstr(value,"ptime=20")!=NULL) obj->ms_per_frame=20; + else if (strstr(value,"ptime=30")!=NULL) obj->ms_per_frame=30; + else g_warning("Unrecognized fmtp parameter for ilbc encoder!"); + break; + } + return 0; +} +int ms_ilbc_decoder_get_property(MSILBCDecoder *obj, MSFilterProperty prop, char *value) +{ + switch(prop){ + case MS_FILTER_PROPERTY_FMTP: + if (obj->ms_per_frame==20) strncpy(value,"ptime=20",MS_FILTER_PROPERTY_STRING_MAX_SIZE); + if (obj->ms_per_frame==30) strncpy(value,"ptime=30",MS_FILTER_PROPERTY_STRING_MAX_SIZE); + break; + } + return 0; +} + +void ms_ilbc_decoder_setup(MSILBCDecoder *r) +{ + MSFilterClass *klass = NULL; + switch (r->ms_per_frame) { + case 20: + r->samples_per_frame = BLOCKL_20MS; + r->bytes_per_compressed_frame = NO_OF_BYTES_20MS; + break; + case 30: + r->samples_per_frame = BLOCKL_30MS; + r->bytes_per_compressed_frame = NO_OF_BYTES_30MS; + break; + default: + g_error("ms_ilbc_decoder_setup: Bad value for ptime (%i)",r->ms_per_frame); + } + g_message("Using ilbc decoder with %i ms frames mode.",r->ms_per_frame); + initDecode(&r->ilbc_dec, r->ms_per_frame /* ms frames */, /* user enhancer */ 0); +} + + +/* FOR INTERNAL USE*/ +void ms_ilbc_decoder_init(MSILBCDecoder *r) +{ + /* default bitrate */ + r->bitrate = 15200; + r->ms_per_frame = 30; + r->samples_per_frame = BLOCKL_20MS; + r->bytes_per_compressed_frame = NO_OF_BYTES_20MS; + + ms_filter_init(MS_FILTER(r)); + MS_FILTER(r)->inqueues=r->q_inputs; + MS_FILTER(r)->outfifos=r->f_outputs; + memset(r->q_inputs,0,sizeof(MSFifo*)*MSILBCDECODER_MAX_INPUTS); + memset(r->f_outputs,0,sizeof(MSFifo*)*MSILBCDECODER_MAX_INPUTS); +} + +void ms_ilbc_decoder_class_init(MSILBCDecoderClass *klass) +{ + ms_filter_class_init(MS_FILTER_CLASS(klass)); + ms_filter_class_set_name(MS_FILTER_CLASS(klass),"ILBCDec"); + MS_FILTER_CLASS(klass)->max_qinputs=MSILBCDECODER_MAX_INPUTS; + MS_FILTER_CLASS(klass)->max_foutputs=MSILBCDECODER_MAX_INPUTS; + MS_FILTER_CLASS(klass)->w_maxgran= ILBC_MAX_SAMPLES_PER_FRAME*2; + MS_FILTER_CLASS(klass)->destroy=(MSFilterDestroyFunc)ms_ilbc_decoder_destroy; + MS_FILTER_CLASS(klass)->set_property=(MSFilterPropertyFunc)ms_ilbc_decoder_set_property; + MS_FILTER_CLASS(klass)->get_property=(MSFilterPropertyFunc)ms_ilbc_decoder_get_property; + MS_FILTER_CLASS(klass)->setup=(MSFilterSetupFunc)ms_ilbc_decoder_setup; + MS_FILTER_CLASS(klass)->process=(MSFilterProcessFunc)ms_ilbc_decoder_process; + MS_FILTER_CLASS(klass)->info=(MSFilterInfo*)&ilbc_info; +} + +void ms_ilbc_decoder_process(MSILBCDecoder *r) +{ + MSFifo *fo; + MSQueue *qi; + int err1; + void *dst=NULL; + float speech[ILBC_MAX_SAMPLES_PER_FRAME]; + MSMessage *m; + + qi=r->q_inputs[0]; + fo=r->f_outputs[0]; + m=ms_queue_get(qi); + + ms_fifo_get_write_ptr(fo, r->samples_per_frame*2, &dst); + if (dst!=NULL){ + if (m->data!=NULL){ + if (m->size<r->bytes_per_compressed_frame) { + g_warning("Invalid ilbc frame ?"); + } + iLBC_decode(speech, m->data, &r->ilbc_dec, /* mode */1); + }else{ + iLBC_decode(speech,NULL, &r->ilbc_dec,0); + } + ilbc_write_16bit_samples((gint16*)dst, speech, r->samples_per_frame); + } + ms_message_destroy(m); +} + +void ms_ilbc_decoder_uninit(MSILBCDecoder *obj) +{ +} + +void ms_ilbc_decoder_destroy( MSILBCDecoder *obj) +{ + ms_ilbc_decoder_uninit(obj); + g_free(obj); +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msilbcdec.h Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,72 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + + +#ifndef MSILBCDECODER_H +#define MSILBCDECODER_H + +#include <msfilter.h> +#include <mscodec.h> +#include <iLBC_decode.h> + +/*this is the class that implements a ILBCdecoder filter*/ + +#define MSILBCDECODER_MAX_INPUTS 1 /* max output per filter*/ + + +typedef struct _MSILBCDecoder +{ + /* the MSILBCDecoder derivates from MSFilter, so the MSFilter object MUST be the first of the MSILBCDecoder object + in order to the object mechanism to work*/ + MSFilter filter; + MSQueue *q_inputs[MSILBCDECODER_MAX_INPUTS]; + MSFifo *f_outputs[MSILBCDECODER_MAX_INPUTS]; + iLBC_Dec_Inst_t ilbc_dec; + int bitrate; + int ms_per_frame; + int samples_per_frame; + int bytes_per_compressed_frame; +} MSILBCDecoder; + +typedef struct _MSILBCDecoderClass +{ + /* the MSILBCDecoder derivates from MSFilter, so the MSFilter class MUST be the first of the MSILBCDecoder class + in order to the class mechanism to work*/ + MSFilterClass parent_class; +} MSILBCDecoderClass; + +/* PUBLIC */ + +/* call this before if don't load the plugin dynamically */ +void ms_ilbc_codec_init(); + +#define MS_ILBCDECODER(filter) ((MSILBCDecoder*)(filter)) +#define MS_ILBCDECODER_CLASS(klass) ((MSILBCDecoderClass*)(klass)) +MSFilter * ms_ilbc_decoder_new(void); + +/* FOR INTERNAL USE*/ +void ms_ilbc_decoder_init(MSILBCDecoder *r); +void ms_ilbc_decoder_class_init(MSILBCDecoderClass *klass); +void ms_ilbc_decoder_destroy( MSILBCDecoder *obj); +void ms_ilbc_decoder_process(MSILBCDecoder *r); + +extern MSCodecInfo ilbc_info; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msilbcenc.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,245 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + +#include <config.h> + +#ifdef HAVE_ILBC + +#include <stdlib.h> +#include <stdio.h> +#include "msilbcenc.h" + +extern MSCodecInfo ilbc_info; + +/* The return value of each of these calls is the same as that + returned by fread/fwrite, which should be the number of samples + successfully read/written, not the number of bytes. */ + +int +ilbc_read_16bit_samples(gint16 int16samples[], float speech[], int n) +{ + int i; + + /* Convert 16 bit integer samples to floating point values in the + range [-1,+1]. */ + + for (i = 0; i < n; i++) { + speech[i] = int16samples[i]; + } + + return (n); +} + + + +int +ilbc_write_16bit_samples(gint16 int16samples[], float speech[], int n) +{ + int i; + float real_sample; + + /* Convert floating point samples in range [-1,+1] to 16 bit + integers. */ + for (i = 0; i < n; i++) { + float dtmp=speech[i]; + if (dtmp<MIN_SAMPLE) + dtmp=MIN_SAMPLE; + else if (dtmp>MAX_SAMPLE) + dtmp=MAX_SAMPLE; + int16samples[i] = (short) dtmp; + } + return (n); +} + +/* + +Write the bits in bits[0] through bits[len-1] to file f, in "packed" +format. + +bits is expected to be an array of len integer values, where each +integer is 0 to represent a 0 bit, and any other value represents a 1 +bit. This bit string is written to the file f in the form of several +8 bit characters. If len is not a multiple of 8, then the last +character is padded with 0 bits -- the padding is in the least +significant bits of the last byte. The 8 bit characters are "filled" +in order from most significant bit to least significant. + +*/ + +void +ilbc_write_bits(unsigned char *data, unsigned char *bits, int nbytes) +{ + memcpy(data, bits, nbytes); +} + + + +/* + +Read bits from file f into bits[0] through bits[len-1], in "packed" +format. + +*/ + +int +ilbc_read_bits(unsigned char *data, unsigned char *bits, int nbytes) +{ + + memcpy(bits, data, nbytes); + + return (nbytes); +} + + + + +static MSILBCEncoderClass *ms_ilbc_encoder_class=NULL; + +MSFilter * ms_ilbc_encoder_new(void) +{ + MSILBCEncoder *r; + + r=g_new(MSILBCEncoder,1); + ms_ilbc_encoder_init(r); + if (ms_ilbc_encoder_class==NULL) + { + ms_ilbc_encoder_class=g_new(MSILBCEncoderClass,1); + ms_ilbc_encoder_class_init(ms_ilbc_encoder_class); + } + MS_FILTER(r)->klass=MS_FILTER_CLASS(ms_ilbc_encoder_class); + return(MS_FILTER(r)); +} + + +int ms_ilbc_encoder_set_property(MSILBCEncoder *obj, MSFilterProperty prop, char *value) +{ + switch(prop){ + case MS_FILTER_PROPERTY_FMTP: + obj->ms_per_frame=30; +#if 0 // SME + if (strstr(value,"ptime=20")!=NULL) obj->ms_per_frame=20; + else if (strstr(value,"ptime=30")!=NULL) obj->ms_per_frame=30; + else g_warning("Unrecognized fmtp parameter for ilbc encoder!"); +#endif + break; + } + return 0; +} + + +int ms_ilbc_encoder_get_property(MSILBCEncoder *obj, MSFilterProperty prop, char *value) +{ + switch(prop){ + case MS_FILTER_PROPERTY_FMTP: + if (obj->ms_per_frame==20) strncpy(value,"ptime=20",MS_FILTER_PROPERTY_STRING_MAX_SIZE); + if (obj->ms_per_frame==30) strncpy(value,"ptime=30",MS_FILTER_PROPERTY_STRING_MAX_SIZE); + break; + } + return 0; +} + +void ms_ilbc_encoder_setup(MSILBCEncoder *r) +{ + MSFilterClass *klass = NULL; + switch (r->ms_per_frame) { + case 20: + r->samples_per_frame = BLOCKL_20MS; + r->bytes_per_compressed_frame = NO_OF_BYTES_20MS; + break; + case 30: + r->samples_per_frame = BLOCKL_30MS; + r->bytes_per_compressed_frame = NO_OF_BYTES_30MS; + break; + default: + g_error("Bad bitrate value (%i) for ilbc encoder!", r->ms_per_frame); + break; + } + MS_FILTER(r)->r_mingran= (r->samples_per_frame * 2); + g_message("Using ilbc encoder with %i ms frames mode.",r->ms_per_frame); + initEncode(&r->ilbc_enc, r->ms_per_frame /* ms frames */); +} + +/* FOR INTERNAL USE*/ +void ms_ilbc_encoder_init(MSILBCEncoder *r) +{ + /* default bitrate */ + r->bitrate = 15200; + r->ms_per_frame = 20; + r->samples_per_frame = BLOCKL_20MS; + r->bytes_per_compressed_frame = NO_OF_BYTES_20MS; + + ms_filter_init(MS_FILTER(r)); + MS_FILTER(r)->infifos=r->f_inputs; + MS_FILTER(r)->outqueues=r->q_outputs; + MS_FILTER(r)->r_mingran= (r->samples_per_frame * 2); + memset(r->f_inputs,0,sizeof(MSFifo*)*MSILBCENCODER_MAX_INPUTS); + memset(r->q_outputs,0,sizeof(MSFifo*)*MSILBCENCODER_MAX_INPUTS); +} + +void ms_ilbc_encoder_class_init(MSILBCEncoderClass *klass) +{ + ms_filter_class_init(MS_FILTER_CLASS(klass)); + ms_filter_class_set_name(MS_FILTER_CLASS(klass),"ILBCEnc"); + MS_FILTER_CLASS(klass)->max_finputs=MSILBCENCODER_MAX_INPUTS; + MS_FILTER_CLASS(klass)->max_qoutputs=MSILBCENCODER_MAX_INPUTS; + MS_FILTER_CLASS(klass)->r_maxgran=ILBC_MAX_SAMPLES_PER_FRAME*2; + MS_FILTER_CLASS(klass)->set_property=(MSFilterPropertyFunc)ms_ilbc_encoder_set_property; + MS_FILTER_CLASS(klass)->get_property=(MSFilterPropertyFunc)ms_ilbc_encoder_get_property; + MS_FILTER_CLASS(klass)->setup=(MSFilterSetupFunc)ms_ilbc_encoder_setup; + MS_FILTER_CLASS(klass)->destroy=(MSFilterDestroyFunc)ms_ilbc_encoder_destroy; + MS_FILTER_CLASS(klass)->process=(MSFilterProcessFunc)ms_ilbc_encoder_process; + MS_FILTER_CLASS(klass)->info=(MSFilterInfo*)&ilbc_info; +} + +void ms_ilbc_encoder_process(MSILBCEncoder *r) +{ + MSFifo *fi; + MSQueue *qo; + MSMessage *m; + void *src=NULL; + float speech[ILBC_MAX_SAMPLES_PER_FRAME]; + + /* process output fifos, but there is only one for this class of filter*/ + + qo=r->q_outputs[0]; + fi=r->f_inputs[0]; + ms_fifo_get_read_ptr(fi,r->samples_per_frame*2,&src); + if (src==NULL) { + g_warning( "src=%p\n", src); + return; + } + m=ms_message_new(r->bytes_per_compressed_frame); + + ilbc_read_16bit_samples((gint16*)src, speech, r->samples_per_frame); + iLBC_encode((unsigned char *)m->data, speech, &r->ilbc_enc); + ms_queue_put(qo,m); +} + +void ms_ilbc_encoder_uninit(MSILBCEncoder *obj) +{ +} + +void ms_ilbc_encoder_destroy( MSILBCEncoder *obj) +{ + ms_ilbc_encoder_uninit(obj); + g_free(obj); +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msilbcenc.h Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,84 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + + +#ifndef MSILBCENCODER_H +#define MSILBCENCODER_H + +#include "mscodec.h" +#include <iLBC_encode.h> + +#define ILBC_BITS_IN_COMPRESSED_FRAME 400 + +int +ilbc_read_16bit_samples(gint16 int16samples[], float speech[], int n); + +int +ilbc_write_16bit_samples(gint16 int16samples[], float speech[], int n); + +void +ilbc_write_bits(unsigned char *data, unsigned char *bits, int nbytes); + +int +ilbc_read_bits(unsigned char *data, unsigned char *bits, int nbytes); + + +/*this is the class that implements a ILBCencoder filter*/ + +#define MSILBCENCODER_MAX_INPUTS 1 /* max output per filter*/ + + +typedef struct _MSILBCEncoder +{ + /* the MSILBCEncoder derivates from MSFilter, so the MSFilter object MUST be the first of the MSILBCEncoder object + in order to the object mechanism to work*/ + MSFilter filter; + MSFifo *f_inputs[MSILBCENCODER_MAX_INPUTS]; + MSQueue *q_outputs[MSILBCENCODER_MAX_INPUTS]; + iLBC_Enc_Inst_t ilbc_enc; + int ilbc_encoded_bytes; + int bitrate; + int ms_per_frame; + int samples_per_frame; + int bytes_per_compressed_frame; +} MSILBCEncoder; + +typedef struct _MSILBCEncoderClass +{ + /* the MSILBCEncoder derivates from MSFilter, so the MSFilter class MUST be the first of the MSILBCEncoder class + in order to the class mechanism to work*/ + MSFilterClass parent_class; +} MSILBCEncoderClass; + +/* PUBLIC */ +#define MS_ILBCENCODER(filter) ((MSILBCEncoder*)(filter)) +#define MS_ILBCENCODER_CLASS(klass) ((MSILBCEncoderClass*)(klass)) +MSFilter * ms_ilbc_encoder_new(void); + +/* FOR INTERNAL USE*/ +void ms_ilbc_encoder_init(MSILBCEncoder *r); +void ms_ilbc_encoder_class_init(MSILBCEncoderClass *klass); +void ms_ilbc_encoder_destroy( MSILBCEncoder *obj); +void ms_ilbc_encoder_process(MSILBCEncoder *r); + +#define ILBC_MAX_BYTES_PER_COMPRESSED_FRAME NO_OF_BYTES_30MS +#define ILBC_MAX_SAMPLES_PER_FRAME BLOCKL_30MS + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msnosync.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,82 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + + +#include "msnosync.h" + +static MSNoSyncClass *ms_nosync_class=NULL; + +void ms_nosync_init(MSNoSync *sync) +{ + ms_sync_init(MS_SYNC(sync)); + MS_SYNC(sync)->attached_filters=sync->filters; + memset(sync->filters,0,MSNOSYNC_MAX_FILTERS*sizeof(MSFilter*)); + MS_SYNC(sync)->samples_per_tick=160; + sync->started=0; +} + +void ms_nosync_class_init(MSNoSyncClass *klass) +{ + ms_sync_class_init(MS_SYNC_CLASS(klass)); + MS_SYNC_CLASS(klass)->max_filters=MSNOSYNC_MAX_FILTERS; + MS_SYNC_CLASS(klass)->synchronize=(MSSyncSyncFunc)ms_nosync_synchronize; + MS_SYNC_CLASS(klass)->destroy=(MSSyncDestroyFunc)ms_nosync_destroy; + /* no need to overload these function*/ + MS_SYNC_CLASS(klass)->attach=ms_sync_attach_generic; + MS_SYNC_CLASS(klass)->detach=ms_sync_detach_generic; +} + +void ms_nosync_destroy(MSNoSync *nosync) +{ + g_free(nosync); +} + +/* the synchronization function that does nothing*/ +void ms_nosync_synchronize(MSNoSync *nosync) +{ + gint32 time; + if (nosync->started==0){ + gettimeofday(&nosync->start,NULL); + nosync->started=1; + } + gettimeofday(&nosync->current,NULL); + MS_SYNC(nosync)->ticks++; + /* update the time, we are supposed to work at 8000 Hz */ + time=((nosync->current.tv_sec-nosync->start.tv_sec)*1000) + + ((nosync->current.tv_usec-nosync->start.tv_usec)/1000); + MS_SYNC(nosync)->time=time; + return; +} + + +MSSync *ms_nosync_new() +{ + MSNoSync *nosync; + + nosync=g_malloc(sizeof(MSNoSync)); + ms_nosync_init(nosync); + if (ms_nosync_class==NULL) + { + ms_nosync_class=g_new(MSNoSyncClass,1); + ms_nosync_class_init(ms_nosync_class); + } + MS_SYNC(nosync)->klass=MS_SYNC_CLASS(ms_nosync_class); + return(MS_SYNC(nosync)); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msnosync.h Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,60 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + +#include "mssync.h" + +#include <sys/time.h> +#define MSNOSYNC_MAX_FILTERS 10 + +/* MSNoSync derivates from MSSync base class*/ + +typedef struct _MSNoSync +{ + /* the MSSync must be the first field of the object in order to the object mechanism to work*/ + MSSync sync; + MSFilter *filters[MSNOSYNC_MAX_FILTERS]; + int started; + struct timeval start,current; +} MSNoSync; + + +typedef struct _MSNoSyncClass +{ + /* the MSSyncClass must be the first field of the class in order to the class mechanism to work*/ + MSSyncClass parent_class; +} MSNoSyncClass; + + +/*private*/ + +void ms_nosync_init(MSNoSync *sync); +void ms_nosync_class_init(MSNoSyncClass *sync); + +void ms_nosync_destroy(MSNoSync *nosync); +void ms_nosync_synchronize(MSNoSync *nosync); + +/*public*/ + +/* casts a MSSync object into a MSNoSync */ +#define MS_NOSYNC(sync) ((MSNoSync*)(sync)) +/* casts a MSSync class into a MSNoSync class */ +#define MS_NOSYNC_CLASS(klass) ((MSNoSyncClass*)(klass)) + +MSSync *ms_nosync_new();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msossread.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,148 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + +#include "msossread.h" +#include "mssync.h" +#include <unistd.h> +#include <errno.h> +#include <sys/time.h> +#include <sys/types.h> + +MSFilterInfo oss_read_info={ + "OSS read", + 0, + MS_FILTER_AUDIO_IO, + ms_oss_read_new, + NULL +}; + +static MSOssReadClass *msossreadclass=NULL; + +MSFilter * ms_oss_read_new() +{ + MSOssRead *w; + + if (msossreadclass==NULL) + { + msossreadclass=g_new(MSOssReadClass,1); + ms_oss_read_class_init( msossreadclass ); + } + + w=g_new(MSOssRead,1); + MS_FILTER(w)->klass=MS_FILTER_CLASS(msossreadclass); + ms_oss_read_init(w); + + return(MS_FILTER(w)); +} + +/* FOR INTERNAL USE*/ +void ms_oss_read_init(MSOssRead *w) +{ + ms_sound_read_init(MS_SOUND_READ(w)); + MS_FILTER(w)->outfifos=w->f_outputs; + MS_FILTER(w)->outfifos[0]=NULL; + w->devid=0; + w->sndcard=NULL; + w->freq=8000; +} + +gint ms_oss_read_set_property(MSOssRead *f,MSFilterProperty prop, void *value) +{ + switch(prop){ + case MS_FILTER_PROPERTY_FREQ: + f->freq=((gint*)value)[0]; + break; + } + return 0; +} +void ms_oss_read_class_init(MSOssReadClass *klass) +{ + ms_sound_read_class_init(MS_SOUND_READ_CLASS(klass)); + MS_FILTER_CLASS(klass)->max_foutputs=1; /* one fifo output only */ + MS_FILTER_CLASS(klass)->setup=(MSFilterSetupFunc)ms_oss_read_setup; + MS_FILTER_CLASS(klass)->unsetup=(MSFilterSetupFunc)ms_oss_read_stop; + MS_FILTER_CLASS(klass)->process= (MSFilterProcessFunc)ms_oss_read_process; + MS_FILTER_CLASS(klass)->set_property=(MSFilterPropertyFunc)ms_oss_read_set_property; + MS_FILTER_CLASS(klass)->destroy= (MSFilterDestroyFunc)ms_oss_read_destroy; + MS_FILTER_CLASS(klass)->w_maxgran=MS_OSS_READ_MAX_GRAN; + MS_FILTER_CLASS(klass)->info=&oss_read_info; + MS_SOUND_READ_CLASS(klass)->set_device=(gint (*)(MSSoundRead*,gint))ms_oss_read_set_device; + MS_SOUND_READ_CLASS(klass)->start=(void (*)(MSSoundRead*))ms_oss_read_start; + MS_SOUND_READ_CLASS(klass)->stop=(void (*)(MSSoundRead*))ms_oss_read_stop; + ms_filter_class_set_name(MS_FILTER_CLASS(klass),"OssRead"); + //ms_filter_class_set_attr( MS_FILTER_CLASS(klass),FILTER_CAN_SYNC|FILTER_IS_SOURCE); +} + +void ms_oss_read_destroy( MSOssRead *obj) +{ + g_free(obj); +} + +void ms_oss_read_process(MSOssRead *f) +{ + MSFifo *fifo; + char *p; + fifo=f->f_outputs[0]; + + g_return_if_fail(f->sndcard!=NULL); + g_return_if_fail(f->gran>0); + + if (snd_card_can_read(f->sndcard)){ + int got; + ms_fifo_get_write_ptr(fifo,f->gran,(void**)&p); + g_return_if_fail(p!=NULL); + got=snd_card_read(f->sndcard,p,f->gran); + if (got>=0 && got!=f->gran) ms_fifo_update_write_ptr(fifo,got); + } +} + + +void ms_oss_read_start(MSOssRead *r) +{ + g_return_if_fail(r->devid!=-1); + r->sndcard=snd_card_manager_get_card(snd_card_manager,r->devid); + g_return_if_fail(r->sndcard!=NULL); + /* open the device for an audio telephony signal with minimum latency */ + snd_card_open_r(r->sndcard,16,0,r->freq); + r->gran=(512*r->freq)/8000; + +} + +void ms_oss_read_stop(MSOssRead *w) +{ + g_return_if_fail(w->devid!=-1); + g_return_if_fail(w->sndcard!=NULL); + snd_card_close_r(w->sndcard); + w->sndcard=NULL; +} + + +void ms_oss_read_setup(MSOssRead *f, MSSync *sync) +{ + f->sync=sync; + ms_oss_read_start(f); +} + + +gint ms_oss_read_set_device(MSOssRead *r,gint devid) +{ + r->devid=devid; + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msossread.h Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,77 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ +#ifndef MSOSSREAD_H +#define MSOSSREAD_H + +#include "mssoundread.h" +#include "sndcard.h" +#include "mssync.h" + + +/*this is the class that implements oss writing sink filter*/ + +#define MS_OSS_READ_MAX_INPUTS 1 /* max output per filter*/ + +#define MS_OSS_READ_MAX_GRAN (512*2) /* the maximum granularity*/ + +struct _MSOssRead +{ + /* the MSOssRead derivates from MSSoundRead so the MSSoundRead object MUST be the first of the MSOssRead object + in order to the object mechanism to work*/ + MSSoundRead filter; + MSFifo *f_outputs[MS_OSS_READ_MAX_INPUTS]; + MSSync *sync; + SndCard *sndcard; + gint freq; + gint devid; /* the sound device id it depends on*/ + gint gran; + gint flags; +#define START_REQUESTED 1 +#define STOP_REQUESTED 2 +}; + +typedef struct _MSOssRead MSOssRead; + +struct _MSOssReadClass +{ + /* the MSOssRead derivates from MSSoundRead, so the MSSoundRead class MUST be the first of the MSOssRead class + in order to the class mechanism to work*/ + MSSoundReadClass parent_class; +}; + +typedef struct _MSOssReadClass MSOssReadClass; + +/* PUBLIC */ +#define MS_OSS_READ(filter) ((MSOssRead*)(filter)) +#define MS_OSS_READ_CLASS(klass) ((MSOssReadClass*)(klass)) +MSFilter * ms_oss_read_new(void); +gint ms_oss_read_set_device(MSOssRead *w,gint devid); +void ms_oss_read_start(MSOssRead *w); +void ms_oss_read_stop(MSOssRead *w); + +/* FOR INTERNAL USE*/ +void ms_oss_read_init(MSOssRead *r); +void ms_oss_read_class_init(MSOssReadClass *klass); +void ms_oss_read_destroy( MSOssRead *obj); +void ms_oss_read_process(MSOssRead *f); +void ms_oss_read_setup(MSOssRead *f, MSSync *sync); + + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msosswrite.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,247 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + +#include "msosswrite.h" +#include "mssync.h" +#include <unistd.h> +#include <math.h> + +MSFilterInfo oss_write_info={ + "OSS write", + 0, + MS_FILTER_OTHER, + ms_oss_write_new, + NULL +}; + + +static MSOssWriteClass *msosswriteclass=NULL; + +MSFilter * ms_oss_write_new() +{ + MSOssWrite *w; + + if (msosswriteclass==NULL) + { + msosswriteclass=g_new(MSOssWriteClass,1); + ms_oss_write_class_init( msosswriteclass ); + } + w=g_new(MSOssWrite,1); + MS_FILTER(w)->klass=MS_FILTER_CLASS(msosswriteclass); + ms_oss_write_init(w); + return(MS_FILTER(w)); +} + +/* FOR INTERNAL USE*/ +void ms_oss_write_init(MSOssWrite *w) +{ + ms_sound_write_init(MS_SOUND_WRITE(w)); + MS_FILTER(w)->infifos=w->f_inputs; + MS_FILTER(w)->infifos[0]=NULL; + MS_FILTER(w)->r_mingran=512; /* very few cards can do that...*/ + w->devid=0; + w->sndcard=NULL; + w->freq=8000; + w->channels=1; + w->dtmf_time=-1; +} + +gint ms_oss_write_set_property(MSOssWrite *f,MSFilterProperty prop, void *value) +{ + switch(prop){ + case MS_FILTER_PROPERTY_FREQ: + f->freq=((gint*)value)[0]; + break; + case MS_FILTER_PROPERTY_CHANNELS: + f->channels=((gint*)value)[0]; + break; + } + return 0; +} + +void ms_oss_write_class_init(MSOssWriteClass *klass) +{ + ms_sound_write_class_init(MS_SOUND_WRITE_CLASS(klass)); + MS_FILTER_CLASS(klass)->max_finputs=1; /* one fifo input only */ + MS_FILTER_CLASS(klass)->r_maxgran=MS_OSS_WRITE_DEF_GRAN; + MS_FILTER_CLASS(klass)->process= (MSFilterProcessFunc)ms_oss_write_process; + MS_FILTER_CLASS(klass)->destroy= (MSFilterDestroyFunc)ms_oss_write_destroy; + MS_FILTER_CLASS(klass)->setup= (MSFilterSetupFunc)ms_oss_write_setup; + MS_FILTER_CLASS(klass)->unsetup= (MSFilterSetupFunc)ms_oss_write_stop; + MS_FILTER_CLASS(klass)->set_property=(MSFilterPropertyFunc)ms_oss_write_set_property; + MS_FILTER_CLASS(klass)->info=&oss_write_info; + MS_SOUND_WRITE_CLASS(klass)->set_device=(gint (*)(MSSoundWrite*,gint))ms_oss_write_set_device; + MS_SOUND_WRITE_CLASS(klass)->start=(void (*)(MSSoundWrite*))ms_oss_write_start; + MS_SOUND_WRITE_CLASS(klass)->stop=(void (*)(MSSoundWrite*))ms_oss_write_stop; + MS_SOUND_WRITE_CLASS(klass)->set_level=(void (*)(MSSoundWrite*, gint))ms_oss_write_set_level; + ms_filter_class_set_name(MS_FILTER_CLASS(klass),"OssWrite"); +} + +void ms_oss_write_destroy( MSOssWrite *obj) +{ + + g_free(obj); +} + +void ms_oss_write_process(MSOssWrite *f) +{ + MSFifo *fifo; + void *p; + int i; + gint gran=ms_filter_get_mingran(MS_FILTER(f)); + + /* always consume something */ + fifo=f->f_inputs[0]; + ms_fifo_get_read_ptr(fifo,gran,&p); + if (p==NULL) { + g_warning("Not enough data: gran=%i.",gran); + return; + } + g_return_if_fail(f->sndcard!=NULL); + if (f->dtmf_time!=-1){ + gint16 *buf=(gint16*)p; + /* generate a DTMF*/ + for(i=0;i<gran/2;i++){ + buf[i]=(gint16)(10000.0*sin(2*M_PI*(double)f->dtmf_time*f->lowfreq)); + buf[i]+=(gint16)(10000.0*sin(2*M_PI*(double)f->dtmf_time*f->highfreq)); + f->dtmf_time++; + //printf("buf[%i]=%i\n",i,buf[i]); + } + if (f->dtmf_time>f->dtmf_duration) f->dtmf_time=-1; /*finished*/ + } + snd_card_write(f->sndcard,p,gran); +} + +void ms_oss_write_start(MSOssWrite *w) +{ + gint bsize; + g_return_if_fail(w->devid!=-1); + w->sndcard=snd_card_manager_get_card(snd_card_manager,w->devid); + g_return_if_fail(w->sndcard!=NULL); + /* open the device for an audio telephony signal with minimum latency */ + snd_card_open_w(w->sndcard,16,w->channels==2,w->freq); + w->bsize=snd_card_get_bsize(w->sndcard); + //MS_FILTER(w)->r_mingran=w->bsize; + //ms_sync_set_samples_per_tick(MS_FILTER(w)->sync,bsize); +} + +void ms_oss_write_stop(MSOssWrite *w) +{ + g_return_if_fail(w->devid!=-1); + g_return_if_fail(w->sndcard!=NULL); + snd_card_close_w(w->sndcard); + w->sndcard=NULL; +} + +void ms_oss_write_set_level(MSOssWrite *w,gint a) +{ + +} + +gint ms_oss_write_set_device(MSOssWrite *w, gint devid) +{ + w->devid=devid; + return 0; +} + +void ms_oss_write_setup(MSOssWrite *r) +{ + //g_message("starting MSOssWrite.."); + ms_oss_write_start(r); +} + + + +void ms_oss_write_play_dtmf(MSOssWrite *w, char dtmf){ + + w->dtmf_duration=0.1*w->freq; + switch(dtmf){ + case '0': + w->lowfreq=941; + w->highfreq=1336; + break; + case '1': + w->lowfreq=697; + w->highfreq=1209; + break; + case '2': + w->lowfreq=697; + w->highfreq=1336; + break; + case '3': + w->lowfreq=697; + w->highfreq=1477; + break; + case '4': + w->lowfreq=770; + w->highfreq=1209; + break; + case '5': + w->lowfreq=770; + w->highfreq=1336; + break; + case '6': + w->lowfreq=770; + w->highfreq=1477; + break; + case '7': + w->lowfreq=852; + w->highfreq=1209; + break; + case '8': + w->lowfreq=852; + w->highfreq=1336; + break; + case '9': + w->lowfreq=852; + w->highfreq=1477; + break; + case '*': + w->lowfreq=941; + w->highfreq=1209; + break; + case '#': + w->lowfreq=941; + w->highfreq=1477; + break; + case 'A': + w->lowfreq=697; + w->highfreq=1633; + break; + case 'B': + w->lowfreq=770; + w->highfreq=1633; + break; + case 'C': + w->lowfreq=852; + w->highfreq=1633; + break; + case 'D': + w->lowfreq=941; + w->highfreq=1633; + break; + default: + g_warning("Not a dtmf key."); + return; + } + w->lowfreq=w->lowfreq/w->freq; + w->highfreq=w->highfreq/w->freq; + w->dtmf_time=0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msosswrite.h Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,78 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ +#ifndef MSOSSWRITE_H +#define MSOSSWRITE_H + +#include "mssoundwrite.h" +#include "sndcard.h" + +/*this is the class that implements oss writing sink filter*/ + +#define MS_OSS_WRITE_MAX_INPUTS 1 /* max output per filter*/ + +#define MS_OSS_WRITE_DEF_GRAN (512*2) /* the default granularity*/ + +struct _MSOssWrite +{ + /* the MSOssWrite derivates from MSSoundWrite, so the MSSoundWrite object MUST be the first of the MSOssWrite object + in order to the object mechanism to work*/ + MSSoundWrite filter; + MSFifo *f_inputs[MS_OSS_WRITE_MAX_INPUTS]; + gint devid; /* the sound device id it depends on*/ + SndCard *sndcard; + gint bsize; + gint freq; + gint channels; + gdouble lowfreq; + gdouble highfreq; + gint dtmf_time; + gint dtmf_duration; +}; + +typedef struct _MSOssWrite MSOssWrite; + +struct _MSOssWriteClass +{ + /* the MSOssWrite derivates from MSSoundWrite, so the MSSoundWrite class MUST be the first of the MSOssWrite class + in order to the class mechanism to work*/ + MSSoundWriteClass parent_class; +}; + +typedef struct _MSOssWriteClass MSOssWriteClass; + +/* PUBLIC */ +#define MS_OSS_WRITE(filter) ((MSOssWrite*)(filter)) +#define MS_OSS_WRITE_CLASS(klass) ((MSOssWriteClass*)(klass)) +MSFilter * ms_oss_write_new(void); +gint ms_oss_write_set_device(MSOssWrite *w,gint devid); +void ms_oss_write_start(MSOssWrite *w); +void ms_oss_write_stop(MSOssWrite *w); +void ms_oss_write_set_level(MSOssWrite *w, gint level); +void ms_oss_write_play_dtmf(MSOssWrite *w, char dtmf); + +/* FOR INTERNAL USE*/ +void ms_oss_write_init(MSOssWrite *r); +void ms_oss_write_setup(MSOssWrite *r); +void ms_oss_write_class_init(MSOssWriteClass *klass); +void ms_oss_write_destroy( MSOssWrite *obj); +void ms_oss_write_process(MSOssWrite *f); + + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msqdispatcher.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,91 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a dispatcher of the GNU Lesser 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 +*/ + + +#include "msqdispatcher.h" + +static MSQdispatcherClass *ms_qdispatcher_class=NULL; + +MSFilter * ms_qdispatcher_new(void) +{ + MSQdispatcher *obj; + obj=g_malloc(sizeof(MSQdispatcher)); + if (ms_qdispatcher_class==NULL){ + ms_qdispatcher_class=g_malloc0(sizeof(MSQdispatcherClass)); + ms_qdispatcher_class_init(ms_qdispatcher_class); + } + MS_FILTER(obj)->klass=MS_FILTER_CLASS(ms_qdispatcher_class); + ms_qdispatcher_init(obj); + return MS_FILTER(obj); +} + + +void ms_qdispatcher_init(MSQdispatcher *obj) +{ + ms_filter_init(MS_FILTER(obj)); + + MS_FILTER(obj)->inqueues=obj->q_inputs; + MS_FILTER(obj)->outqueues=obj->q_outputs; + memset(obj->q_inputs,0,sizeof(MSQueue*)*MS_QDISPATCHER_MAX_INPUTS); + memset(obj->q_outputs,0,sizeof(MSQueue*)*MS_QDISPATCHER_MAX_OUTPUTS); +} + + + +void ms_qdispatcher_class_init(MSQdispatcherClass *klass) +{ + MSFilterClass *parent_class=MS_FILTER_CLASS(klass); + ms_filter_class_init(parent_class); + ms_filter_class_set_name(parent_class,"qdispatcher"); + parent_class->max_qinputs=MS_QDISPATCHER_MAX_INPUTS; + parent_class->max_qoutputs=MS_QDISPATCHER_MAX_OUTPUTS; + + parent_class->destroy=(MSFilterDestroyFunc)ms_qdispatcher_destroy; + parent_class->process=(MSFilterProcessFunc)ms_qdispatcher_process; +} + + +void ms_qdispatcher_destroy( MSQdispatcher *obj) +{ + g_free(obj); +} + +void ms_qdispatcher_process(MSQdispatcher *obj) +{ + gint i; + MSQueue *inq=obj->q_inputs[0]; + + if (inq!=NULL){ + MSQueue *outq; + MSMessage *m1,*m2; + while ( (m1=ms_queue_get(inq))!=NULL){ + /* dispatch incoming messages to output queues */ + for (i=0;i<MS_QDISPATCHER_MAX_OUTPUTS;i++){ + outq=obj->q_outputs[i]; + if (outq!=NULL){ + m2=ms_message_dup(m1); + ms_queue_put(outq,m2); + } + } + ms_message_destroy(m1); + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msqdispatcher.h Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,60 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a dispatcher of the GNU Lesser 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 +*/ + + +#ifndef MSQDISPATCHER_H +#define MSQDISPATCHER_H + +#include "msfilter.h" + + +/*this is the class that implements a qdispatcher filter*/ + +#define MS_QDISPATCHER_MAX_INPUTS 1 +#define MS_QDISPATCHER_MAX_OUTPUTS 5 + +typedef struct _MSQdispatcher +{ + /* the MSQdispatcher derivates from MSFilter, so the MSFilter object MUST be the first of the MSQdispatcher object + in order to the object mechanism to work*/ + MSFilter filter; + MSQueue *q_inputs[MS_QDISPATCHER_MAX_INPUTS]; + MSQueue *q_outputs[MS_QDISPATCHER_MAX_OUTPUTS]; +} MSQdispatcher; + +typedef struct _MSQdispatcherClass +{ + /* the MSQdispatcher derivates from MSFilter, so the MSFilter class MUST be the first of the MSQdispatcher class + in order to the class mechanism to work*/ + MSFilterClass parent_class; +} MSQdispatcherClass; + +/* PUBLIC */ +#define MS_QDISPATCHER(filter) ((MSQdispatcher*)(filter)) +#define MS_QDISPATCHER_CLASS(klass) ((MSQdispatcherClass*)(klass)) +MSFilter * ms_qdispatcher_new(void); + +/* FOR INTERNAL USE*/ +void ms_qdispatcher_init(MSQdispatcher *r); +void ms_qdispatcher_class_init(MSQdispatcherClass *klass); +void ms_qdispatcher_destroy( MSQdispatcher *obj); +void ms_qdispatcher_process(MSQdispatcher *r); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msqueue.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,56 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + +#include "msqueue.h" +#include <string.h> + +MSQueue * ms_queue_new() +{ + MSQueue *q=g_malloc(sizeof(MSQueue)); + memset(q,0,sizeof(MSQueue)); + return q; +} + +MSMessage *ms_queue_get(MSQueue *q) +{ + MSMessage *b=q->last; + if (b==NULL) return NULL; + q->last=b->prev; + if (b->prev==NULL) q->first=NULL; /* it was the only element of the queue*/ + q->size--; + b->next=b->prev=NULL; + return(b); +} + +void ms_queue_put(MSQueue *q, MSMessage *m) +{ + MSMessage *mtmp=q->first; + g_return_if_fail(m!=NULL); + q->first=m; + m->next=mtmp; + if (mtmp!=NULL) + { + mtmp->prev=m; + } + else q->last=m; /* it was the first element of the q */ + q->size++; +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msqueue.h Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,49 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + +#ifndef MSQUEUE_H +#define MSQUEUE_H + +#include "msbuffer.h" + +/* for the moment these are stupid queues limited to one element*/ + +typedef struct _MSQueue +{ + MSMessage *first; + MSMessage *last; + gint size; + void *prev_data; /*user data, usually the writting filter*/ + void *next_data; /* user data, usually the reading filter*/ +}MSQueue; + + +MSQueue * ms_queue_new(); + +MSMessage *ms_queue_get(MSQueue *q); + +void ms_queue_put(MSQueue *q, MSMessage *m); + +#define ms_queue_can_get(q) ( (q)->size!=0 ) + +#define ms_queue_destroy(q) g_free(q) + + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msread.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,182 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + +#include "msread.h" +#include "mssync.h" +#include <unistd.h> +#include <fcntl.h> +#include <sys/types.h> +#include <string.h> +#include <errno.h> + +static MSReadClass *ms_read_class=NULL; + +MSFilter * ms_read_new(char *name) +{ + MSRead *r; + int fd=-1; + + r=g_new(MSRead,1); + ms_read_init(r); + if (ms_read_class==NULL) + { + ms_read_class=g_new(MSReadClass,1); + ms_read_class_init(ms_read_class); + } + MS_FILTER(r)->klass=MS_FILTER_CLASS(ms_read_class); + r->fd=-1; + if (name!=NULL) ms_read_open(r,name); + return(MS_FILTER(r)); +} + + + +gint ms_read_open(MSRead *r, gchar *name) +{ + gint fd; + fd=open(name,O_RDONLY); + if (fd<0) { + r->fd=-1; + g_warning("ms_read_new: cannot open %s : %s",name,strerror(errno)); + return -1; + } + r->fd=fd; + if (strstr(name,".wav")!=NULL){ + /* skip the header */ + lseek(fd,20,SEEK_SET); +#ifdef WORDS_BIGENDIAN + r->need_swap=1; +#else + r->need_swap=0; +#endif + } + r->state=MS_READ_STATE_STARTED; + return 0; +} + +/* FOR INTERNAL USE*/ +void ms_read_init(MSRead *r) +{ + ms_filter_init(MS_FILTER(r)); + MS_FILTER(r)->outfifos=r->foutputs; + MS_FILTER(r)->outqueues=r->qoutputs; + memset(r->foutputs,0,sizeof(MSFifo*)*MSREAD_MAX_OUTPUTS); + memset(r->qoutputs,0,sizeof(MSQueue*)*MSREAD_MAX_OUTPUTS); + r->fd=-1; + r->gran=320; + r->state=MS_READ_STATE_STOPPED; + r->need_swap=0; + r->rate=8000; +} + +gint ms_read_set_property(MSRead *f,MSFilterProperty prop, void *value) +{ + switch(prop){ + case MS_FILTER_PROPERTY_FREQ: + f->rate=((gint*)value)[0]; + break; + } + return 0; +} + +void ms_read_class_init(MSReadClass *klass) +{ + ms_filter_class_init(MS_FILTER_CLASS(klass)); + ms_filter_class_set_name(MS_FILTER_CLASS(klass),"dskreader"); + ms_filter_class_set_attr(MS_FILTER_CLASS(klass),FILTER_IS_SOURCE); + MS_FILTER_CLASS(klass)->max_foutputs=MSREAD_MAX_OUTPUTS; + MS_FILTER_CLASS(klass)->max_qoutputs=MSREAD_MAX_OUTPUTS; + MS_FILTER_CLASS(klass)->w_maxgran=MSREAD_DEF_GRAN; + MS_FILTER_CLASS(klass)->destroy=(MSFilterDestroyFunc)ms_read_destroy; + MS_FILTER_CLASS(klass)->setup=(MSFilterSetupFunc)ms_read_setup; + MS_FILTER_CLASS(klass)->process=(MSFilterProcessFunc)ms_read_process; + MS_FILTER_CLASS(klass)->set_property=(MSFilterPropertyFunc)ms_read_set_property; +} + +void ms_read_process(MSRead *r) +{ + MSFifo *f; + MSQueue *q; + MSMessage *msg=NULL; + int err; + gint gran=r->gran; + void *p; + + f=r->foutputs[0]; + if ((f!=NULL) && (r->state==MS_READ_STATE_STARTED)) + { + ms_fifo_get_write_ptr(f,gran,&p); + if (p!=NULL) + { + err=read(r->fd,p,gran); + if (err<0) + { + /* temp: */ + g_warning("ms_read_process: failed to read: %s.\n",strerror(errno)); + } + else if (err<gran){ + ms_trace("ms_read_process: end of file."); + ms_filter_notify_event(MS_FILTER(r),MS_READ_EVENT_EOF,NULL); + r->state=MS_READ_STATE_STOPPED; + close(r->fd); + r->fd=-1; + } + if (r->need_swap) swap_buffer(p,gran); + } + } + /* process output queues*/ + q=r->qoutputs[0]; + if ((q!=NULL) && (r->fd>0)) + { + msg=ms_message_new(r->gran); + err=read(r->fd,msg->data,r->gran); + if (err>0){ + msg->size=err; + ms_queue_put(q,msg); + if (r->need_swap) swap_buffer(msg->data,r->gran); + }else{ + ms_filter_notify_event(MS_FILTER(r),MS_READ_EVENT_EOF,NULL); + ms_trace("End of file reached."); + r->state=MS_READ_STATE_STOPPED; + } + } +} + +void ms_read_destroy( MSRead *obj) +{ + if (obj->fd!=0) close(obj->fd); + g_free(obj); +} + +gint ms_read_close(MSRead *obj) +{ + if (obj->fd!=0) { + close(obj->fd); + obj->fd=-1; + obj->state=MS_READ_STATE_STOPPED; + } +} + + +void ms_read_setup(MSRead *r, MSSync *sync) +{ + r->sync=sync; + r->gran=(r->rate*sync->interval/1000)*2; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msread.h Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,80 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + +#ifndef MSREAD_H +#define MSREAD_H + +#include "msfilter.h" +#include "mssync.h" + +/*this is the class that implements file reading source filter*/ + +#define MSREAD_MAX_OUTPUTS 1 /* max output per filter*/ + +#define MSREAD_DEF_GRAN 640 /* the default granularity*/ + +typedef enum{ + MS_READ_STATE_STARTED, + MS_READ_STATE_STOPPED, + MS_READ_STATE_EOF +}MSReadState; + +typedef struct _MSRead +{ + /* the MSRead derivates from MSFilter, so the MSFilter object MUST be the first of the MSRead object + in order to the object mechanism to work*/ + MSFilter filter; + MSFifo *foutputs[MSREAD_MAX_OUTPUTS]; + MSQueue *qoutputs[MSREAD_MAX_OUTPUTS]; + MSSync *sync; + gint rate; + gint fd; /* the file descriptor of the file being read*/ + gint gran; /*granularity*/ /* for use with queues */ + gint need_swap; + gint state; +} MSRead; + +typedef struct _MSReadClass +{ + /* the MSRead derivates from MSFilter, so the MSFilter class MUST be the first of the MSRead class + in order to the class mechanism to work*/ + MSFilterClass parent_class; +} MSReadClass; + +/* PUBLIC */ +#define MS_READ(filter) ((MSRead*)(filter)) +#define MS_READ_CLASS(klass) ((MSReadClass*)(klass)) +MSFilter * ms_read_new(char *name); +/* set the granularity for reading file on disk */ +#define ms_read_set_bufsize(filter,sz) (filter)->gran=(sz) + +/* FOR INTERNAL USE*/ +void ms_read_init(MSRead *r); +void ms_read_class_init(MSReadClass *klass); +void ms_read_destroy( MSRead *obj); +void ms_read_process(MSRead *r); +void ms_read_setup(MSRead *r, MSSync *sync); + +typedef enum{ + MS_READ_EVENT_EOF /* end of file */ +} MSReadEvent; + + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msringplayer.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,246 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + +#include "msringplayer.h" +#include "mssync.h" +#include <unistd.h> +#include <fcntl.h> +#include <sys/types.h> +#include <string.h> +#include <errno.h> + +#include "waveheader.h" + +#define WAVE_HEADER_OFFSET sizeof(wave_header_t) + +enum { PLAY_RING, PLAY_SILENCE}; + +static int supported_freq[6]={8000,11025,16000,22050,32000,44100}; + +gint freq_is_supported(gint freq){ + int i; + for (i=0;i<6;i++){ + if (abs(supported_freq[i]-freq)<50) return supported_freq[i]; + } + return 0; +} + +static MSRingPlayerClass *ms_ring_player_class=NULL; + +/** + * ms_ring_player_new: + * @name: The path to the 16-bit 8khz raw file to be played as a ring. + * @seconds: The number of seconds that separates two rings. + * + * Allocates a new MSRingPlayer object. + * + * + * Returns: a pointer the the object, NULL if name could not be open. + */ +MSFilter * ms_ring_player_new(char *name, gint seconds) +{ + MSRingPlayer *r; + int fd=-1; + + if ((name!=NULL) && (strlen(name)!=0)) + { + fd=open(name,O_RDONLY); + if (fd<0) + { + g_warning("ms_ring_player_new: failed to open %s.\n",name); + return NULL; + } + + }else { + g_warning("ms_ring_player_new: Bad file name"); + return NULL; + } + + r=g_new(MSRingPlayer,1); + ms_ring_player_init(r); + if (ms_ring_player_class==NULL) + { + ms_ring_player_class=g_new(MSRingPlayerClass,1); + ms_ring_player_class_init(ms_ring_player_class); + } + MS_FILTER(r)->klass=MS_FILTER_CLASS(ms_ring_player_class); + + r->fd=fd; + r->silence=seconds; + r->freq=8000; + if (strstr(name,".wav")!=NULL){ + wave_header_t header; + int freq,freq2; + /* read the header */ + read(fd,&header,sizeof(wave_header_t)); + freq=wave_header_get_rate(&header); + if ((freq2=freq_is_supported(freq))>0){ + r->freq=freq2; + }else { + g_warning("Unsupported sampling rate %i",freq); + r->freq=8000; + } + r->channel=wave_header_get_channel(&header); + lseek(fd,WAVE_HEADER_OFFSET,SEEK_SET); +#ifdef WORDS_BIGENDIAN + r->need_swap=1; +#else + r->need_swap=0; +#endif + } + ms_ring_player_set_property(r, MS_FILTER_PROPERTY_FREQ,&r->freq); + r->state=PLAY_RING; + return(MS_FILTER(r)); +} + + +/* FOR INTERNAL USE*/ +void ms_ring_player_init(MSRingPlayer *r) +{ + ms_filter_init(MS_FILTER(r)); + MS_FILTER(r)->outfifos=r->foutputs; + MS_FILTER(r)->outqueues=r->qoutputs; + memset(r->foutputs,0,sizeof(MSFifo*)*MS_RING_PLAYER_MAX_OUTPUTS); + memset(r->qoutputs,0,sizeof(MSQueue*)*MS_RING_PLAYER_MAX_OUTPUTS); + r->fd=-1; + r->current_pos=0; + r->need_swap=0; + r->sync=NULL; +} + +gint ms_ring_player_set_property(MSRingPlayer *f,MSFilterProperty prop, void *value) +{ + switch(prop){ + case MS_FILTER_PROPERTY_FREQ: + f->rate=((gint*)value)[0]*2; + f->silence_bytes=f->silence*f->rate; + if (f->sync!=NULL) + f->gran=(f->rate*f->sync->interval/1000)*2; + break; + } + return 0; +} + +gint ms_ring_player_get_property(MSRingPlayer *f,MSFilterProperty prop, void *value) +{ + switch(prop){ + case MS_FILTER_PROPERTY_FREQ: + ((gint*)value)[0]=f->freq; + + break; + case MS_FILTER_PROPERTY_CHANNELS: + ((gint*)value)[0]=f->channel; + break; + } + return 0; +} + +gint ms_ring_player_get_sample_freq(MSRingPlayer *obj){ + return obj->freq; +} + + +void ms_ring_player_class_init(MSRingPlayerClass *klass) +{ + ms_filter_class_init(MS_FILTER_CLASS(klass)); + ms_filter_class_set_name(MS_FILTER_CLASS(klass),"ringplay"); + ms_filter_class_set_attr(MS_FILTER_CLASS(klass),FILTER_IS_SOURCE); + MS_FILTER_CLASS(klass)->max_foutputs=MS_RING_PLAYER_MAX_OUTPUTS; + MS_FILTER_CLASS(klass)->max_qoutputs=MS_RING_PLAYER_MAX_OUTPUTS; + MS_FILTER_CLASS(klass)->w_maxgran=MS_RING_PLAYER_DEF_GRAN; + MS_FILTER_CLASS(klass)->setup=(MSFilterSetupFunc)ms_ring_player_setup; + MS_FILTER_CLASS(klass)->destroy=(MSFilterDestroyFunc)ms_ring_player_destroy; + MS_FILTER_CLASS(klass)->process=(MSFilterProcessFunc)ms_ring_player_process; + MS_FILTER_CLASS(klass)->set_property=(MSFilterPropertyFunc)ms_ring_player_set_property; + MS_FILTER_CLASS(klass)->get_property=(MSFilterPropertyFunc)ms_ring_player_get_property; +} + +void ms_ring_player_process(MSRingPlayer *r) +{ + MSFifo *f; + gint err; + gint processed=0; + gint gran=r->gran; + char *p; + + g_return_if_fail(gran>0); + /* process output fifos*/ + + f=r->foutputs[0]; + ms_fifo_get_write_ptr(f,gran,(void**)&p); + g_return_if_fail(p!=NULL); + for (processed=0;processed<gran;){ + switch(r->state){ + case PLAY_RING: + err=read(r->fd,&p[processed],gran-processed); + if (err<0) + { + memset(&p[processed],0,gran-processed); + processed=gran; + g_warning("ms_ring_player_process: failed to read: %s.\n",strerror(errno)); + return; + } + else if (err<gran) + {/* end of file */ + + r->current_pos=r->silence_bytes; + lseek(r->fd,WAVE_HEADER_OFFSET,SEEK_SET); + r->state=PLAY_SILENCE; + ms_filter_notify_event(MS_FILTER(r),MS_RING_PLAYER_END_OF_RING_EVENT,NULL); + } + if (r->need_swap) swap_buffer(&p[processed],err); + processed+=err; + break; + case PLAY_SILENCE: + err=gran-processed; + if (r->current_pos>err){ + memset(&p[processed],0,err); + r->current_pos-=gran; + processed=gran; + }else{ + memset(&p[processed],0,r->current_pos); + processed+=r->current_pos; + r->state=PLAY_RING; + } + break; + } + } +} + +/** + * ms_ring_player_destroy: + * @obj: A valid MSRingPlayer object. + * + * Destroy a MSRingPlayer object. + * + * + */ + +void ms_ring_player_destroy( MSRingPlayer *obj) +{ + if (obj->fd!=0) close(obj->fd); + g_free(obj); +} + +void ms_ring_player_setup(MSRingPlayer *r,MSSync *sync) +{ + r->sync=sync; + r->gran=(r->rate*r->sync->interval/1000)*r->channel; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msringplayer.h Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,81 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + +#ifndef MSRINGPLAYER_H +#define MSRINGPLAYER_H + +#include "msfilter.h" +#include "mssync.h" + + +/*this is the class that implements file reading source filter*/ + +#define MS_RING_PLAYER_MAX_OUTPUTS 1 /* max output per filter*/ + +#define MS_RING_PLAYER_DEF_GRAN 8192 /* the default granularity*/ + +#define MS_RING_PLAYER_END_OF_RING_EVENT 1 + +struct _MSRingPlayer +{ + /* the MSRingPlayer derivates from MSFilter, so the MSFilter object MUST be the first of the MSRingPlayer object + in order to the object mechanism to work*/ + MSFilter filter; + MSFifo *foutputs[MS_RING_PLAYER_MAX_OUTPUTS]; + MSQueue *qoutputs[MS_RING_PLAYER_MAX_OUTPUTS];\ + MSSync *sync; + gint gran; + gint freq; + gint rate; + gint channel; /* number of interleaved channels */ + gint silence; /* silence time between each ring, in seconds */ + gint state; + gint fd; /* the file descriptor of the file being read*/ + gint silence_bytes; /*silence in number of bytes between each ring */ + gint current_pos; + gint need_swap; +}; + +typedef struct _MSRingPlayer MSRingPlayer; + +struct _MSRingPlayerClass +{ + /* the MSRingPlayer derivates from MSFilter, so the MSFilter class MUST be the first of the MSRingPlayer class + in order to the class mechanism to work*/ + MSFilterClass parent_class; +}; + +typedef struct _MSRingPlayerClass MSRingPlayerClass; + +/* PUBLIC */ +#define MS_RING_PLAYER(filter) ((MSRingPlayer*)(filter)) +#define MS_RING_PLAYER_CLASS(klass) ((MSRingPlayerClass*)(klass)) +MSFilter * ms_ring_player_new(char *name, gint seconds); +gint ms_ring_player_get_sample_freq(MSRingPlayer *obj); + + +/* FOR INTERNAL USE*/ +void ms_ring_player_init(MSRingPlayer *r); +void ms_ring_player_class_init(MSRingPlayerClass *klass); +void ms_ring_player_destroy( MSRingPlayer *obj); +void ms_ring_player_process(MSRingPlayer *r); +#define ms_ring_player_set_bufsize(filter,sz) (filter)->gran=(sz) +void ms_ring_player_setup(MSRingPlayer *r,MSSync *sync); +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msrtprecv.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,163 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + + +#include "msrtprecv.h" + + +/* some utilities to convert mblk_t to MSMessage and vice-versa */ +MSMessage *msgb_2_ms_message(mblk_t* mp){ + MSMessage *msg; + MSBuffer *msbuf; + if (mp->b_datap->ref_count!=1) return NULL; /* cannot handle properly non-unique buffers*/ + /* create a MSBuffer using the mblk_t buffer */ + msg=ms_message_alloc(); + msbuf=ms_buffer_alloc(0); + msbuf->buffer=mp->b_datap->db_base; + msbuf->size=(char*)mp->b_datap->db_lim-(char*)mp->b_datap->db_base; + ms_message_set_buf(msg,msbuf); + msg->size=mp->b_wptr-mp->b_rptr; + msg->data=mp->b_rptr; + /* free the mblk_t */ + g_free(mp->b_datap); + g_free(mp); + return msg; +} + + +static MSRtpRecvClass *ms_rtp_recv_class=NULL; + +MSFilter * ms_rtp_recv_new(void) +{ + MSRtpRecv *r; + + r=g_new(MSRtpRecv,1); + ms_rtp_recv_init(r); + if (ms_rtp_recv_class==NULL) + { + ms_rtp_recv_class=g_new0(MSRtpRecvClass,1); + ms_rtp_recv_class_init(ms_rtp_recv_class); + } + MS_FILTER(r)->klass=MS_FILTER_CLASS(ms_rtp_recv_class); + return(MS_FILTER(r)); +} + + +/* FOR INTERNAL USE*/ +void ms_rtp_recv_init(MSRtpRecv *r) +{ + ms_filter_init(MS_FILTER(r)); + MS_FILTER(r)->outfifos=r->f_outputs; + MS_FILTER(r)->outqueues=r->q_outputs; + memset(r->f_outputs,0,sizeof(MSFifo*)*MSRTPRECV_MAX_OUTPUTS); + memset(r->q_outputs,0,sizeof(MSFifo*)*MSRTPRECV_MAX_OUTPUTS); + r->rtpsession=NULL; + r->stream_started=0; +} + +void ms_rtp_recv_class_init(MSRtpRecvClass *klass) +{ + ms_filter_class_init(MS_FILTER_CLASS(klass)); + ms_filter_class_set_name(MS_FILTER_CLASS(klass),"RTPRecv"); + MS_FILTER_CLASS(klass)->max_qoutputs=MSRTPRECV_MAX_OUTPUTS; + MS_FILTER_CLASS(klass)->max_foutputs=MSRTPRECV_MAX_OUTPUTS; + MS_FILTER_CLASS(klass)->w_maxgran=MSRTPRECV_DEF_GRAN; + ms_filter_class_set_attr(MS_FILTER_CLASS(klass),FILTER_IS_SOURCE); + MS_FILTER_CLASS(klass)->destroy=(MSFilterDestroyFunc)ms_rtp_recv_destroy; + MS_FILTER_CLASS(klass)->process=(MSFilterProcessFunc)ms_rtp_recv_process; + MS_FILTER_CLASS(klass)->setup=(MSFilterSetupFunc)ms_rtp_recv_setup; +} + +void ms_rtp_recv_process(MSRtpRecv *r) +{ + MSFifo *fo; + MSQueue *qo; + MSSync *sync= r->sync; + void *d; + mblk_t *mp; + gint len; + gint gran=ms_sync_get_samples_per_tick(MS_SYNC(sync)); + + if (r->rtpsession==NULL) return; + /* process output fifo and output queue*/ + fo=r->f_outputs[0]; + if (fo!=NULL) + { + while( (mp=rtp_session_recvm_with_ts(r->rtpsession,r->prev_ts))!=NULL) { + /* try to get rtp packets and paste them to the output fifo */ + r->stream_started=1; + len=mp->b_cont->b_wptr-mp->b_cont->b_rptr; + ms_fifo_get_write_ptr(fo,len,&d); + if (d!=NULL){ + memcpy(d,mp->b_cont->b_rptr,len); + }else ms_warning("ms_rtp_recv_process: no space on output fifo !"); + freemsg(mp); + } + r->prev_ts+=gran; + + } + qo=r->q_outputs[0]; + if (qo!=NULL) + { + guint32 clock; + gint got=0; + /* we are connected with queues (surely for video)*/ + /* use the sync system time to compute a timestamp */ + PayloadType *pt=rtp_profile_get_payload(r->rtpsession->profile,r->rtpsession->payload_type); + if (pt==NULL) { + ms_warning("ms_rtp_recv_process(): NULL RtpPayload- skipping."); + return; + } + clock=(guint32)(((double)sync->time*(double)pt->clock_rate)/1000.0); + /*g_message("Querying packet with timestamp %u",clock);*/ + /* get rtp packet, and send them through the output queue */ + while ( (mp=rtp_session_recvm_with_ts(r->rtpsession,clock))!=NULL ){ + MSMessage *msg; + mblk_t *mdata; + /*g_message("Got packet with timestamp %u",clock);*/ + got++; + r->stream_started=1; + mdata=mp->b_cont; + freeb(mp); + msg=msgb_2_ms_message(mdata); + ms_queue_put(qo,msg); + } + } +} + +void ms_rtp_recv_destroy( MSRtpRecv *obj) +{ + g_free(obj); +} + +RtpSession * ms_rtp_recv_set_session(MSRtpRecv *obj,RtpSession *session) +{ + RtpSession *old=obj->rtpsession; + obj->rtpsession=session; + obj->prev_ts=0; + return old; +} + + +void ms_rtp_recv_setup(MSRtpRecv *r,MSSync *sync) +{ + r->sync=sync; + r->stream_started=0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msrtprecv.h Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,80 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + + +#ifndef MSRTPRECV_H +#define MSRTPRECV_H + +#include "msfilter.h" +#include "mssync.h" + +/* because of a conflict between config.h from oRTP and config.h from linphone:*/ +#undef PACKAGE +#undef VERSION +#include <ortp/ortp.h> + +/*this is the class that implements a copy filter*/ + +#define MSRTPRECV_MAX_OUTPUTS 1 /* max output per filter*/ + +#define MSRTPRECV_DEF_GRAN 4096 /* the default granularity*/ + +struct _MSRtpRecv +{ + /* the MSCopy derivates from MSFilter, so the MSFilter object MUST be the first of the MSCopy object + in order to the object mechanism to work*/ + MSFilter filter; + MSFifo *f_outputs[MSRTPRECV_MAX_OUTPUTS]; + MSQueue *q_outputs[MSRTPRECV_MAX_OUTPUTS]; + MSSync *sync; + RtpSession *rtpsession; + guint32 prev_ts; + gint stream_started; +}; + +typedef struct _MSRtpRecv MSRtpRecv; + +struct _MSRtpRecvClass +{ + /* the MSCopy derivates from MSFilter, so the MSFilter class MUST be the first of the MSCopy class + in order to the class mechanism to work*/ + MSFilterClass parent_class; +}; + +typedef struct _MSRtpRecvClass MSRtpRecvClass; + +/* PUBLIC */ +#define MS_RTP_RECV(filter) ((MSRtpRecv*)(filter)) +#define MS_RTP_RECV_CLASS(klass) ((MSRtpRecvClass*)(klass)) +MSFilter * ms_rtp_recv_new(void); +RtpSession * ms_rtp_recv_set_session(MSRtpRecv *obj,RtpSession *session); +#define ms_rtp_recv_unset_session(obj) (ms_rtp_recv_set_session((obj),NULL)) +#define ms_rtp_recv_get_session(obj) ((obj)->rtpsession) + + + +/* FOR INTERNAL USE*/ +void ms_rtp_recv_init(MSRtpRecv *r); +void ms_rtp_recv_class_init(MSRtpRecvClass *klass); +void ms_rtp_recv_destroy( MSRtpRecv *obj); +void ms_rtp_recv_process(MSRtpRecv *r); +void ms_rtp_recv_setup(MSRtpRecv *r,MSSync *sync); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msrtpsend.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,211 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + +#include "msrtpsend.h" +#include <ortp/telephonyevents.h> +#include "mssync.h" +#include "mscodec.h" + + + +static MSRtpSendClass *ms_rtp_send_class=NULL; + +MSFilter * ms_rtp_send_new(void) +{ + MSRtpSend *r; + + r=g_new(MSRtpSend,1); + + if (ms_rtp_send_class==NULL) + { + ms_rtp_send_class=g_new(MSRtpSendClass,1); + ms_rtp_send_class_init(ms_rtp_send_class); + } + MS_FILTER(r)->klass=MS_FILTER_CLASS(ms_rtp_send_class); + ms_rtp_send_init(r); + return(MS_FILTER(r)); +} + + +void ms_rtp_send_init(MSRtpSend *r) +{ + ms_filter_init(MS_FILTER(r)); + MS_FILTER(r)->infifos=r->f_inputs; + MS_FILTER(r)->inqueues=r->q_inputs; + MS_FILTER(r)->r_mingran=MSRTPSEND_DEF_GRAN; + memset(r->f_inputs,0,sizeof(MSFifo*)*MSRTPSEND_MAX_INPUTS); + memset(r->q_inputs,0,sizeof(MSFifo*)*MSRTPSEND_MAX_INPUTS); + r->rtpsession=NULL; + r->ts=0; + r->ts_inc=0; + r->flags=0; + r->delay=0; +} + +void ms_rtp_send_class_init(MSRtpSendClass *klass) +{ + ms_filter_class_init(MS_FILTER_CLASS(klass)); + ms_filter_class_set_name(MS_FILTER_CLASS(klass),"RTPSend"); + MS_FILTER_CLASS(klass)->max_qinputs=MSRTPSEND_MAX_INPUTS; + MS_FILTER_CLASS(klass)->max_finputs=MSRTPSEND_MAX_INPUTS; + MS_FILTER_CLASS(klass)->r_maxgran=MSRTPSEND_DEF_GRAN; + MS_FILTER_CLASS(klass)->destroy=(MSFilterDestroyFunc)ms_rtp_send_destroy; + MS_FILTER_CLASS(klass)->process=(MSFilterProcessFunc)ms_rtp_send_process; + MS_FILTER_CLASS(klass)->setup=(MSFilterSetupFunc)ms_rtp_send_setup; +} + +void ms_rtp_send_set_timing(MSRtpSend *r, guint32 ts_inc, gint payload_size) +{ + r->ts_inc=ts_inc; + r->packet_size=payload_size; + if (r->ts_inc!=0) r->flags|=RTPSEND_CONFIGURED; + else r->flags&=~RTPSEND_CONFIGURED; + MS_FILTER(r)->r_mingran=payload_size; + /*g_message("ms_rtp_send_set_timing: ts_inc=%i",ts_inc);*/ +} + +guint32 get_new_timestamp(MSRtpSend *r,guint32 synctime) +{ + guint32 clockts; + /* use the sync system time to compute a timestamp */ + PayloadType *pt=rtp_profile_get_payload(r->rtpsession->profile,r->rtpsession->payload_type); + g_return_val_if_fail(pt!=NULL,0); + clockts=(guint32)(((double)synctime * (double)pt->clock_rate)/1000.0); + ms_trace("ms_rtp_send_process: sync->time=%i clock=%i",synctime,clockts); + if (r->flags & RTPSEND_CONFIGURED){ + if (RTP_TIMESTAMP_IS_STRICTLY_NEWER_THAN(clockts,r->ts+(2*r->ts_inc) )){ + r->ts=clockts; + } + else r->ts+=r->ts_inc; + }else{ + r->ts=clockts; + } + return r->ts; +} + + +void ms_rtp_send_process(MSRtpSend *r) +{ + MSFifo *fi; + MSQueue *qi; + MSSync *sync= r->sync; + int gran=ms_sync_get_samples_per_tick(sync); + guint32 ts; + void *s; + guint skip; + guint32 synctime=sync->time; + + g_return_if_fail(gran>0); + if (r->rtpsession==NULL) return; + + ms_filter_lock(MS_FILTER(r)); + skip=r->delay!=0; + if (skip) r->delay--; + /* process output fifo and output queue*/ + fi=r->f_inputs[0]; + if (fi!=NULL) + { + ts=get_new_timestamp(r,synctime); + /* try to read r->packet_size bytes and send them in a rtp packet*/ + ms_fifo_get_read_ptr(fi,r->packet_size,&s); + if (!skip){ + rtp_session_send_with_ts(r->rtpsession,s,r->packet_size,ts); + ms_trace("len=%i, ts=%i ",r->packet_size,ts); + } + } + qi=r->q_inputs[0]; + if (qi!=NULL) + { + MSMessage *msg; + /* read a MSMessage and send it through the network*/ + while ( (msg=ms_queue_get(qi))!=NULL){ + ts=get_new_timestamp(r,synctime); + if (!skip) { + /*g_message("Sending packet with ts=%u",ts);*/ + rtp_session_send_with_ts(r->rtpsession,msg->data,msg->size,ts); + + } + ms_message_destroy(msg); + } + } + ms_filter_unlock(MS_FILTER(r)); +} + +void ms_rtp_send_destroy( MSRtpSend *obj) +{ + g_free(obj); +} + +RtpSession * ms_rtp_send_set_session(MSRtpSend *obj,RtpSession *session) +{ + RtpSession *old=obj->rtpsession; + obj->rtpsession=session; + obj->ts=0; + obj->ts_inc=0; + return old; +} + +void ms_rtp_send_setup(MSRtpSend *r, MSSync *sync) +{ + MSFilter *codec; + MSCodecInfo *info; + r->sync=sync; + codec=ms_filter_search_upstream_by_type(MS_FILTER(r),MS_FILTER_AUDIO_CODEC); + if (codec==NULL) codec=ms_filter_search_upstream_by_type(MS_FILTER(r),MS_FILTER_VIDEO_CODEC); + if (codec==NULL){ + g_warning("ms_rtp_send_setup: could not find upstream codec."); + return; + } + info=MS_CODEC_INFO(codec->klass->info); + if (info->info.type==MS_FILTER_AUDIO_CODEC){ + int ts_inc=info->fr_size/2; + int psize=info->dt_size; + if (ts_inc==0){ + /* dont'use the normal frame size: this is a variable frame size codec */ + /* use the MS_FILTER(codec)->r_mingran */ + ts_inc=MS_FILTER(codec)->r_mingran/2; + psize=0; + } + ms_rtp_send_set_timing(r,ts_inc,psize); + } +} + +gint ms_rtp_send_dtmf(MSRtpSend *r, gchar dtmf) +{ + gint res; + + if (r->rtpsession==NULL) return -1; + if (rtp_session_telephone_events_supported(r->rtpsession)==-1){ + g_warning("ERROR : telephone events not supported.\n"); + return -1; + } + + ms_filter_lock(MS_FILTER(r)); + g_message("Sending DTMF."); + res=rtp_session_send_dtmf(r->rtpsession, dtmf, r->ts); + if (res==0){ + //r->ts+=r->ts_inc; + r->delay+=2; + }else g_warning("Could not send dtmf."); + + ms_filter_unlock(MS_FILTER(r)); + + return res; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msrtpsend.h Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,85 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + + +#ifndef MSRTPSEND_H +#define MSRTPSEND_H + +#include "msfilter.h" +#include "mssync.h" + +#undef PACKAGE +#undef VERSION +#include <ortp/ortp.h> + + +/*this is the class that implements a sending through rtp filter*/ + +#define MSRTPSEND_MAX_INPUTS 1 /* max input per filter*/ + +#define MSRTPSEND_DEF_GRAN 4096/* the default granularity*/ + +struct _MSRtpSend +{ + /* the MSCopy derivates from MSFilter, so the MSFilter object MUST be the first of the MSCopy object + in order to the object mechanism to work*/ + MSFilter filter; + MSFifo *f_inputs[MSRTPSEND_MAX_INPUTS]; + MSQueue *q_inputs[MSRTPSEND_MAX_INPUTS]; + MSSync *sync; + RtpSession *rtpsession; + guint32 ts; + guint32 ts_inc; /* the timestamp increment */ + gint packet_size; + guint flags; + guint delay; /* number of _proccess call which must be skipped */ +#define RTPSEND_CONFIGURED (1) +}; + +typedef struct _MSRtpSend MSRtpSend; + +struct _MSRtpSendClass +{ + /* the MSRtpSend derivates from MSFilter, so the MSFilter class MUST be the first of the MSCopy class + in order to the class mechanism to work*/ + MSFilterClass parent_class; +}; + +typedef struct _MSRtpSendClass MSRtpSendClass; + +/* PUBLIC */ +#define MS_RTP_SEND(filter) ((MSRtpSend*)(filter)) +#define MS_RTP_SEND_CLASS(klass) ((MSRtpSendClass*)(klass)) +MSFilter * ms_rtp_send_new(void); +RtpSession * ms_rtp_send_set_session(MSRtpSend *obj,RtpSession *session); +#define ms_rtp_send_unset_session(obj) (ms_rtp_send_set_session((obj),NULL)) +#define ms_rtp_send_get_session(obj) ((obj)->rtpsession) +void ms_rtp_send_set_timing(MSRtpSend *r, guint32 ts_inc, gint payload_size); +gint ms_rtp_send_dtmf(MSRtpSend *r, gchar dtmf); + + +/* FOR INTERNAL USE*/ +void ms_rtp_send_init(MSRtpSend *r); +void ms_rtp_send_class_init(MSRtpSendClass *klass); +void ms_rtp_send_destroy( MSRtpSend *obj); +void ms_rtp_send_process(MSRtpSend *r); +void ms_rtp_send_setup(MSRtpSend *r, MSSync *sync); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/mssdlout.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,303 @@ +/*************************************************************************** + * mssdlout.c + * + * Mon Jul 11 16:17:59 2005 + * Copyright 2005 Simon Morlat + * Email simon dot morlat at linphone dot org + ****************************************************************************/ + +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + +#include "mssdlout.h" + +MSSdlOutClass *ms_sdl_out_class=NULL; + +void ms_sdl_out_init(MSSdlOut *obj){ + ms_filter_init(MS_FILTER(obj)); + obj->width=VIDEO_SIZE_CIF_W; + obj->height=VIDEO_SIZE_CIF_H; + obj->format="RGB24"; + obj->use_yuv=FALSE; + obj->oldinm1=NULL; + MS_FILTER(obj)->inqueues=obj->input; +} + +void ms_sdl_out_set_format(MSSdlOut *obj, const char *fmt){ + obj->format=fmt; + if (strcmp(fmt,"YUV420P")==0) obj->use_yuv=TRUE; + else obj->use_yuv=FALSE; +} + +void ms_sdl_uninit_sdl(MSSdlOut *obj){ + if (obj->overlay!=NULL){ + SDL_FreeYUVOverlay(obj->overlay); + obj->overlay=NULL; + } + if (obj->screen!=NULL){ + SDL_FreeSurface(obj->screen); + obj->screen=NULL; + } + +} + +void ms_sdl_out_uninit(MSSdlOut *obj){ + ms_sdl_uninit_sdl(obj); +} + +void ms_sdl_out_destroy(MSSdlOut *obj){ + ms_sdl_out_uninit(obj); + if (obj->oldinm1!=NULL) ms_message_destroy(obj->oldinm1); + g_free(obj); +} + +void ms_sdl_init_sdl(MSSdlOut *obj){ + if (strcmp(obj->format,"RGB24")==0){ + }else{ + obj->use_yuv=TRUE; + } + obj->screen = SDL_SetVideoMode(obj->width, obj->height, 0,SDL_HWSURFACE|SDL_ANYFORMAT); + if ( obj->screen == NULL ) { + g_warning("Couldn't set video mode: %s\n", + SDL_GetError()); + return ; + } + if (obj->screen->flags & SDL_HWSURFACE) g_message("SDL surface created in hardware"); + SDL_WM_SetCaption("Linphone Video", NULL); + + if (obj->use_yuv){ + g_message("Using yuv overlay."); + obj->overlay=SDL_CreateYUVOverlay(obj->width,obj->height,SDL_IYUV_OVERLAY,obj->screen); + if (obj->overlay==NULL){ + g_warning("Couldn't create yuv overlay: %s\n", + SDL_GetError()); + }else{ + if (obj->overlay->hw_overlay) g_message("YUV overlay using hardware acceleration."); + } + } + +} + +static void resize_yuv_small(char *pict, int w, int h, int scale){ + int i,j,id,jd; + int nh,nw; + char *smallpict; + int ysize,usize,ydsize,udsize; + int smallpict_sz; + char *dptr,*sptr; + nw=w/scale; + nh=h/scale; + ysize=w*h; + usize=ysize/4; + ydsize=nw*nh; + udsize=ydsize/4; + smallpict_sz=(ydsize*3)/2; + smallpict=(char*)alloca(smallpict_sz); + memset(smallpict,0,smallpict_sz); + + + dptr=smallpict; + sptr=pict; + for (j=0,jd=0;j<nh;j++,jd+=scale){ + for (i=0,id=0;i<nw;i++,id+=scale){ + dptr[(j*nw) + i]=sptr[(jd*w)+id]; + } + } + + nh=nh/2; + nw=nw/2; + w=w/2; + h=h/2; + dptr+=ydsize; + sptr+=ysize; + for (j=0,jd=0;j<nh;j++,jd+=scale){ + for (i=0,id=0;i<nw;i++,id+=scale){ + dptr[(j*nw) + i]=sptr[(jd*w)+id]; + } + } + dptr+=udsize; + sptr+=usize; + for (j=0,jd=0;j<nh;j++,jd+=scale){ + for (i=0,id=0;i<nw;i++,id+=scale){ + dptr[(j*nw) + i]=sptr[(jd*w)+id]; + } + } + + memcpy(pict,smallpict,smallpict_sz); +} + +static void fill_overlay_at_pos(SDL_Overlay *lay, MSMessage *m, int x, int y, int w, int h){ + char *data=(char*)m->data; + int i,j; + int jlim,ilim; + int off; + char *dptr; + + ilim=MIN(x+w,lay->w); + jlim=MIN(y+h,lay->h); + SDL_LockYUVOverlay(lay); + /* set Y */ + dptr=lay->pixels[0]; + for (j=y;j<jlim;j++){ + off=j*lay->w; + for (i=x;i<ilim;i++){ + dptr[off + i]=*data; + data++; + } + } + /*set U and V*/ + ilim=ilim/2; + jlim=jlim/2; + dptr=lay->pixels[1]; + for (j=y/2;j<jlim;j++){ + off=j*(lay->w/2); + for (i=x/2;i<ilim;i++){ + dptr[off + i]=*data; + data++; + } + } + dptr=lay->pixels[2]; + for (j=y/2;j<jlim;j++){ + off=j*(lay->w/2); + for (i=x/2;i<ilim;i++){ + dptr[off + i]=*data; + data++; + } + } + SDL_UnlockYUVOverlay(lay); +} + +static void fill_overlay(SDL_Overlay *lay, MSMessage *m){ + + int w2,h2; + char *data=(char*)m->data; + int ysize=lay->w*lay->h; + int usize; + w2=lay->w/2; + h2=lay->h/2; + usize=w2*h2; + SDL_LockYUVOverlay(lay); + memcpy(lay->pixels[0],data,ysize); + memcpy(lay->pixels[1],data+ysize,usize); + memcpy(lay->pixels[2],data+ysize+usize,usize); + SDL_UnlockYUVOverlay(lay); +} + +#define SCALE_FACTOR 6 + +void ms_sdl_out_process(MSSdlOut *obj){ + MSQueue *q0=obj->input[0]; + MSQueue *q1=obj->input[1]; + MSMessage *inm0=NULL; + MSMessage *inm1=NULL; + int err; + SDL_Rect smallrect; + SDL_Rect rect; + rect.w=obj->width; + rect.h=obj->height; + rect.x=0; + rect.y=0; + smallrect.w=obj->width/SCALE_FACTOR; + smallrect.h=obj->height/SCALE_FACTOR; + smallrect.x=obj->width - smallrect.w ; + smallrect.y=obj->height -smallrect.h; + + if (obj->screen==NULL){ + ms_sdl_init_sdl(obj); + } + + if (q0!=NULL) + inm0=ms_queue_get(q0); + if (q1!=NULL) + inm1=ms_queue_get(q1); + + if (inm0!=NULL){ + SDL_Surface *surf; + if (obj->use_yuv){ + + fill_overlay(obj->overlay,inm0); + + }else { + surf=SDL_CreateRGBSurfaceFrom(inm0->data,obj->width,obj->height,24,obj->width*3,0,0,0,0); + + err=SDL_BlitSurface(surf,NULL,obj->screen,NULL); + if (err<0) g_warning("Fail to blit surface: %s",SDL_GetError()); + SDL_FreeSurface(surf); + } + ms_message_destroy(inm0); + } + if (inm1!=NULL){ + /* this message is blitted on the right,bottom corner of the screen */ + SDL_Surface *surf; + + if (obj->use_yuv){ + resize_yuv_small(inm1->data,rect.w,rect.h,SCALE_FACTOR); + fill_overlay_at_pos(obj->overlay,inm1,smallrect.x, smallrect.y, smallrect.w, smallrect.h); + }else { + surf=SDL_CreateRGBSurfaceFrom(inm1->data,obj->width,obj->height,24,obj->width*3,0,0,0,0); + + err=SDL_BlitSurface(surf,NULL,obj->screen,&smallrect); + if (err<0) g_warning("Fail to blit surface: %s",SDL_GetError()); + SDL_FreeSurface(surf); + } + if (obj->oldinm1!=NULL) { + ms_message_destroy(obj->oldinm1); + } + obj->oldinm1=inm1; + + }else{ + /* this is the case were we have only inm0, we have to redisplay inm1 */ + if (obj->use_yuv){ + if (obj->oldinm1!=NULL){ + fill_overlay_at_pos(obj->overlay,obj->oldinm1,smallrect.x, smallrect.y, smallrect.w, smallrect.h); + } + } + } + + if (obj->use_yuv) SDL_DisplayYUVOverlay(obj->overlay,&rect); + SDL_UpdateRect(obj->screen,0,0,obj->width,obj->height); + +} + +void ms_sdl_out_class_init(MSSdlOutClass *klass){ + MS_FILTER_CLASS(klass)->process=(MSFilterProcessFunc)ms_sdl_out_process; + MS_FILTER_CLASS(klass)->max_qinputs=2; + MS_FILTER_CLASS(klass)->destroy=(MSFilterDestroyFunc)ms_sdl_out_destroy; + MS_FILTER_CLASS(klass)->name="MSSdlOut"; + /* Initialize the SDL library */ + if( SDL_Init(SDL_INIT_VIDEO) < 0 ) { + fprintf(stderr, + "Couldn't initialize SDL: %s\n", SDL_GetError()); + return; + } + /* Clean up on exit */ + atexit(SDL_Quit); +} + +MSFilter * ms_sdl_out_new(void){ + MSSdlOut *obj=g_new0(MSSdlOut,1); + if (ms_sdl_out_class==NULL){ + ms_sdl_out_class=g_new0(MSSdlOutClass,1); + ms_sdl_out_class_init(ms_sdl_out_class); + } + MS_FILTER(obj)->klass=MS_FILTER_CLASS(ms_sdl_out_class); + ms_sdl_out_init(obj); + return MS_FILTER(obj); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/mssdlout.h Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,64 @@ +/*************************************************************************** + * mssdlout.h + * + * Mon Jul 11 16:18:55 2005 + * Copyright 2005 Simon Morlat + * Email simon dot morlat at linphone dot org + ****************************************************************************/ + +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + +#ifndef mssdlout_h +#define mssdlout_h + +#include "msfilter.h" + +#include <SDL/SDL.h> +#include <SDL/SDL_video.h> + +struct _MSSdlOut +{ + MSFilter parent; + MSQueue *input[2]; + gint width,height; + const gchar *format; + SDL_Surface *screen; + SDL_Overlay *overlay; + MSMessage *oldinm1; + gboolean use_yuv; +}; + + +typedef struct _MSSdlOut MSSdlOut; + +struct _MSSdlOutClass +{ + MSFilterClass parent_class; +}; + +typedef struct _MSSdlOutClass MSSdlOutClass; + +MSFilter * ms_sdl_out_new(void); +void ms_sdl_out_set_format(MSSdlOut *obj, const char *fmt); + +#define MS_SDL_OUT(obj) ((MSSdlOut*)obj) + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/mssoundread.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,39 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation + + */ + +#include "mssoundread.h" + + +void ms_sound_read_init(MSSoundRead *w) +{ + ms_filter_init(MS_FILTER(w)); + +} + +void ms_sound_read_class_init(MSSoundReadClass *klass) +{ + int i; + ms_filter_class_init(MS_FILTER_CLASS(klass)); + MS_FILTER_CLASS(klass)->max_foutputs=1; /* one fifo output only */ + + ms_filter_class_set_attr( MS_FILTER_CLASS(klass),FILTER_IS_SOURCE); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/mssoundread.h Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,80 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ +#ifndef MSSOUNDREAD_H +#define MSSOUNDREAD_H + +#include "msfilter.h" +#include "mssync.h" + + + +struct _MSSoundRead +{ + /* the MSOssRead derivates from MSFilter, so the MSFilter object MUST be the first of the MSOssRead object + in order to the object mechanism to work*/ + MSFilter filter; +}; + +typedef struct _MSSoundRead MSSoundRead; + +struct _MSSoundReadClass +{ + /* the MSOssRead derivates from MSFilter, so the MSFilter class MUST be the first of the MSOssRead class + in order to the class mechanism to work*/ + MSFilterClass parent_class; + gint (*set_device)(MSSoundRead *, gint devid); + void (*start)(MSSoundRead *); + void (*stop)(MSSoundRead*); + void (*set_level)(MSSoundRead *, gint a); +}; + +typedef struct _MSSoundReadClass MSSoundReadClass; + +/* PUBLIC */ +#define MS_SOUND_READ(filter) ((MSSoundRead*)(filter)) +#define MS_SOUND_READ_CLASS(klass) ((MSSoundReadClass*)(klass)) + +static inline int ms_sound_read_set_device(MSSoundRead *r,gint devid) +{ + return MS_SOUND_READ_CLASS( MS_FILTER(r)->klass )->set_device(r,devid); +} + +static inline void ms_sound_read_start(MSSoundRead *r) +{ + MS_SOUND_READ_CLASS( MS_FILTER(r)->klass )->start(r); +} + +static inline void ms_sound_read_stop(MSSoundRead *w) +{ + MS_SOUND_READ_CLASS( MS_FILTER(w)->klass )->stop(w); +} + +static inline void ms_sound_read_set_level(MSSoundRead *w,gint a) +{ + MS_SOUND_READ_CLASS( MS_FILTER(w)->klass )->set_level(w,a); +} + +/* FOR INTERNAL USE*/ +void ms_sound_read_init(MSSoundRead *r); +void ms_sound_read_class_init(MSSoundReadClass *klass); + + +#endif +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/mssoundwrite.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,39 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation + + */ + +#include "mssoundwrite.h" + + +void ms_sound_write_init(MSSoundWrite *w) +{ + ms_filter_init(MS_FILTER(w)); + +} + +void ms_sound_write_class_init(MSSoundWriteClass *klass) +{ + int i; + ms_filter_class_init(MS_FILTER_CLASS(klass)); + MS_FILTER_CLASS(klass)->max_finputs=1; /* one fifo output only */ + + ms_filter_class_set_attr( MS_FILTER_CLASS(klass),FILTER_IS_SINK); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/mssoundwrite.h Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,80 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ +#ifndef MSSOUNDWRITE_H +#define MSSOUNDWRITE_H + +#include "msfilter.h" +#include "mssync.h" + + + +struct _MSSoundWrite +{ + /* the MSOssWrite derivates from MSFilter, so the MSFilter object MUST be the first of the MSOssWrite object + in order to the object mechanism to work*/ + MSFilter filter; +}; + +typedef struct _MSSoundWrite MSSoundWrite; + +struct _MSSoundWriteClass +{ + /* the MSOssWrite derivates from MSFilter, so the MSFilter class MUST be the first of the MSOssWrite class + in order to the class mechanism to work*/ + MSFilterClass parent_class; + gint (*set_device)(MSSoundWrite *, gint devid); + void (*start)(MSSoundWrite *); + void (*stop)(MSSoundWrite*); + void (*set_level)(MSSoundWrite *, gint a); +}; + +typedef struct _MSSoundWriteClass MSSoundWriteClass; + +/* PUBLIC */ +#define MS_SOUND_WRITE(filter) ((MSSoundWrite*)(filter)) +#define MS_SOUND_WRITE_CLASS(klass) ((MSSoundWriteClass*)(klass)) + +static inline int ms_sound_write_set_device(MSSoundWrite *r,gint devid) +{ + return MS_SOUND_WRITE_CLASS( MS_FILTER(r)->klass )->set_device(r,devid); +} + +static inline void ms_sound_write_start(MSSoundWrite *r) +{ + MS_SOUND_WRITE_CLASS( MS_FILTER(r)->klass )->start(r); +} + +static inline void ms_sound_write_stop(MSSoundWrite *w) +{ + MS_SOUND_WRITE_CLASS( MS_FILTER(w)->klass )->stop(w); +} + +static inline void ms_sound_write_set_level(MSSoundWrite *w,gint a) +{ + MS_SOUND_WRITE_CLASS( MS_FILTER(w)->klass )->set_level(w,a); +} + +/* FOR INTERNAL USE*/ +void ms_sound_write_init(MSSoundWrite *r); +void ms_sound_write_class_init(MSSoundWriteClass *klass); + + +#endif +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msspeexdec.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,213 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + + +#include "msspeexdec.h" + +#ifdef HAVE_GLIB +#include <gmodule.h> +#endif + +extern MSFilter * ms_speex_enc_new(); + +MSCodecInfo speex_info= +{ + { + "Speex codec", + 0, + MS_FILTER_AUDIO_CODEC, + ms_speex_dec_new, + "A high quality variable bit-rate codec from Jean Marc Valin and David Rowe." + }, + ms_speex_enc_new, + ms_speex_dec_new, + 0, /*frame size */ + 0, + 8000, /*minimal bitrate */ + -1, /* sampling frequency */ + 110, /* payload type */ + "speex", + 1, + 1 +}; + + + +void ms_speex_codec_init() +{ + + ms_filter_register(MS_FILTER_INFO(&speex_info)); + //ms_filter_register(MS_FILTER_INFO(&speex_lbr_info)); +} + +#ifdef HAVE_GLIB +gchar * g_module_check_init(GModule *module) +{ + ms_speex_codec_init(); + + return NULL; +} +#else +gchar * g_module_check_init() +{ + ms_speex_codec_init(); + + return NULL; +} +#endif + +static MSSpeexDecClass * ms_speex_dec_class=NULL; +//static MSSpeexDecClass * ms_speexnb_dec_class=NULL; + +MSFilter * ms_speex_dec_new() +{ + MSSpeexDec *obj=g_new(MSSpeexDec,1); + + if (ms_speex_dec_class==NULL){ + ms_speex_dec_class=g_new(MSSpeexDecClass,1); + ms_speex_dec_class_init(ms_speex_dec_class); + } + MS_FILTER(obj)->klass=MS_FILTER_CLASS(ms_speex_dec_class); + + ms_speex_dec_init(obj); + return MS_FILTER(obj); +} + +void ms_speex_dec_init(MSSpeexDec *obj) +{ + ms_filter_init(MS_FILTER(obj)); + obj->initialized=0; + MS_FILTER(obj)->outfifos=obj->outf; + MS_FILTER(obj)->inqueues=obj->inq; + obj->outf[0]=NULL; + obj->inq[0]=NULL; + obj->frequency=8000; /*default value */ + +} + +void ms_speex_dec_init_core(MSSpeexDec *obj,const SpeexMode *mode) +{ + int pf=1; + + obj->speex_state=speex_decoder_init(mode); + speex_bits_init(&obj->bits); + /* enable the perceptual post filter */ + speex_decoder_ctl(obj->speex_state,SPEEX_SET_PF, &pf); + + speex_mode_query(mode, SPEEX_MODE_FRAME_SIZE, &obj->frame_size); + + obj->initialized=1; +} + +int ms_speex_dec_set_property(MSSpeexDec *obj, MSFilterProperty prop, int *value) +{ + if (obj->initialized){ + /* we are called when speex is running !! forbid that! */ + ms_warning("ms_speex_dec_set_property: cannot call this function when running!"); + return -1; + } + switch(prop){ + case MS_FILTER_PROPERTY_FREQ: + obj->frequency=value[0]; + break; + } + return 0; +} + +void ms_speex_dec_setup(MSSpeexDec *obj) +{ + const SpeexMode *mode; + g_message("Speex decoder setup: freq=%i",obj->frequency); + if ( obj->frequency< 16000) mode=&speex_nb_mode; + else mode=&speex_wb_mode; + ms_speex_dec_init_core(obj,mode); +} + +void ms_speex_dec_unsetup(MSSpeexDec *obj) +{ + ms_speex_dec_uninit_core(obj); +} + +void ms_speex_dec_class_init(MSSpeexDecClass *klass) +{ + gint frame_size=0; + + ms_filter_class_init(MS_FILTER_CLASS(klass)); + /* use the largest frame size to configure fifos */ + speex_mode_query(&speex_wb_mode, SPEEX_MODE_FRAME_SIZE, &frame_size); + MS_FILTER_CLASS(klass)->process=(MSFilterProcessFunc)ms_speex_dec_process; + MS_FILTER_CLASS(klass)->setup=(MSFilterSetupFunc)ms_speex_dec_setup; + MS_FILTER_CLASS(klass)->unsetup=(MSFilterSetupFunc)ms_speex_dec_unsetup; + MS_FILTER_CLASS(klass)->destroy=(MSFilterDestroyFunc)ms_speex_dec_destroy; + MS_FILTER_CLASS(klass)->set_property=(MSFilterPropertyFunc)ms_speex_dec_set_property; + ms_filter_class_set_name(MS_FILTER_CLASS(klass),"SpeexDecoder"); + MS_FILTER_CLASS(klass)->info=(MSFilterInfo*)&speex_info; + MS_FILTER_CLASS(klass)->max_foutputs=1; + MS_FILTER_CLASS(klass)->max_qinputs=1; + MS_FILTER_CLASS(klass)->w_maxgran=frame_size*2; + ms_trace("ms_speex_dec_class_init: w_maxgran is %i.",MS_FILTER_CLASS(klass)->w_maxgran); +} + +void ms_speex_dec_uninit_core(MSSpeexDec *obj) +{ + speex_decoder_destroy(obj->speex_state); + obj->initialized=0; +} + +void ms_speex_dec_uninit(MSSpeexDec *obj) +{ + +} + +void ms_speex_dec_destroy(MSSpeexDec *obj) +{ + ms_speex_dec_uninit(obj); + g_free(obj); +} + +void ms_speex_dec_process(MSSpeexDec *obj) +{ + MSFifo *outf=obj->outf[0]; + MSQueue *inq=obj->inq[0]; + gint16 *output; + gint gran=obj->frame_size*2; + gint i; + MSMessage *m; + + g_return_if_fail(inq!=NULL); + g_return_if_fail(outf!=NULL); + + m=ms_queue_get(inq); + g_return_if_fail(m!=NULL); + speex_bits_reset(&obj->bits); + ms_fifo_get_write_ptr(outf,gran,(void**)&output); + g_return_if_fail(output!=NULL); + if (m->data!=NULL){ + + speex_bits_read_from(&obj->bits,m->data,m->size); + /* decode */ + speex_decode_int(obj->speex_state,&obj->bits,(short*)output); + }else{ + /* we have a missing packet */ + speex_decode_int(obj->speex_state,NULL,(short*)output); + } + ms_message_destroy(m); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msspeexdec.h Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,69 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + + +#ifndef MSSPEEXDEC_H +#define MSSPEEXDEC_H + +#include <mscodec.h> +#include <speex.h> + +struct _MSSpeexDec +{ + MSFilter parent; + MSQueue *inq[1]; /* speex has an input q because it can be variable bit rate */ + MSFifo *outf[1]; + void *speex_state; + SpeexBits bits; + int frequency; + int frame_size; + int initialized; +}; + +typedef struct _MSSpeexDec MSSpeexDec; + + +struct _MSSpeexDecClass +{ + MSFilterClass parent; +}; + +typedef struct _MSSpeexDecClass MSSpeexDecClass; + + +#define MS_SPEEX_DEC(o) ((MSSpeexDec*)(o)) +#define MS_SPEEX_DEC_CLASS(o) ((MSSpeexDecClass*)(o)) + +/* call this before if don't load the plugin dynamically */ +void ms_speex_codec_init(); + +/* mediastreamer compliant constructor */ +MSFilter * ms_speex_dec_new(); + +void ms_speex_dec_init(MSSpeexDec *obj); +void ms_speex_dec_init_core(MSSpeexDec *obj,const SpeexMode *mode); +void ms_speex_dec_class_init(MSSpeexDecClass *klass); +void ms_speex_dec_uninit(MSSpeexDec *obj); +void ms_speex_dec_uninit_core(MSSpeexDec *obj); + +void ms_speex_dec_process(MSSpeexDec *obj); +void ms_speex_dec_destroy(MSSpeexDec *obj); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msspeexenc.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,188 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + + + +#include "msspeexenc.h" +#include "ms.h" +extern MSCodecInfo speex_info; + +static MSSpeexEncClass * ms_speex_enc_class=NULL; + +MSFilter * ms_speex_enc_new() +{ + MSSpeexEnc *obj=g_new(MSSpeexEnc,1); + + if (ms_speex_enc_class==NULL){ + ms_speex_enc_class=g_new(MSSpeexEncClass,1); + ms_speex_enc_class_init(ms_speex_enc_class); + } + MS_FILTER(obj)->klass=MS_FILTER_CLASS(ms_speex_enc_class); + ms_speex_enc_init(MS_SPEEX_ENC(obj)); + return MS_FILTER(obj); +} + +void ms_speex_enc_init(MSSpeexEnc *obj) +{ + ms_filter_init(MS_FILTER(obj)); + MS_FILTER(obj)->infifos=obj->inf; + MS_FILTER(obj)->outqueues=obj->outq; + obj->inf[0]=NULL; + obj->outq[0]=NULL; + obj->frequency=8000; + obj->bitrate=30000; + obj->initialized=0; +} + +void ms_speex_enc_init_core(MSSpeexEnc *obj,const SpeexMode *mode, gint bitrate) +{ + int proc_type, proc_speed; + gchar *proc_vendor; + int tmp; + int frame_size; + + obj->speex_state=speex_encoder_init(mode); + speex_bits_init(&obj->bits); + + if (bitrate>0) { + bitrate++; + speex_encoder_ctl(obj->speex_state, SPEEX_SET_BITRATE, &bitrate); + g_message("Setting speex output bitrate less or equal than %i",bitrate-1); + } + + proc_speed=ms_proc_get_speed(); + proc_vendor=ms_proc_get_param("vendor_id"); + if (proc_speed<0 || proc_vendor==NULL){ + g_warning("Can't guess processor features: setting speex encoder to its lowest complexity."); + tmp=1; + speex_encoder_ctl(obj->speex_state,SPEEX_SET_COMPLEXITY,&tmp); + }else if ((proc_speed!=-1) && (proc_speed<200)){ + g_warning("A cpu speed less than 200 Mhz is not enough: let's reduce the complexity of the speex codec."); + tmp=1; + speex_encoder_ctl(obj->speex_state,SPEEX_SET_COMPLEXITY,&tmp); + }else if (proc_vendor!=NULL) { + if (strncmp(proc_vendor,"GenuineIntel",strlen("GenuineIntel"))==0){ + proc_type=ms_proc_get_type(); + if (proc_type==5){ + g_warning("A pentium I is not enough fast for speex codec in normal mode: let's reduce its complexity."); + tmp=1; + speex_encoder_ctl(obj->speex_state,SPEEX_SET_COMPLEXITY,&tmp); + } + } + g_free(proc_vendor); + } + /* guess the used input frame size */ + speex_mode_query(mode, SPEEX_MODE_FRAME_SIZE, &frame_size); + MS_FILTER(obj)->r_mingran=frame_size*2; + ms_trace("ms_speex_init: using frame size of %i.",MS_FILTER(obj)->r_mingran); + + obj->initialized=1; +} + +/* must be called before the encoder is running*/ +int ms_speex_enc_set_property(MSSpeexEnc *obj,int property,int *value) +{ + if (obj->initialized){ + /* we are called when speex is running !! forbid that! */ + ms_warning("ms_speex_enc_set_property: cannot call this function when running!"); + return -1; + } + switch(property){ + case MS_FILTER_PROPERTY_FREQ: + obj->frequency=value[0]; + break; + case MS_FILTER_PROPERTY_BITRATE: /* to specify max bitrate */ + obj->bitrate=value[0]; + break; + } + return 0; +} + +void ms_speex_enc_setup(MSSpeexEnc *obj) +{ + const SpeexMode *mode; + int quality; + g_message("Speex encoder setup: freq=%i",obj->frequency); + if ( obj->frequency< 16000) mode=&speex_nb_mode; + else mode=&speex_wb_mode; + ms_speex_enc_init_core(obj,mode,obj->bitrate); + +} + +void ms_speex_enc_unsetup(MSSpeexEnc *obj) +{ + ms_speex_enc_uninit_core(obj); +} + +void ms_speex_enc_class_init(MSSpeexEncClass *klass) +{ + gint frame_size=0; + + ms_filter_class_init(MS_FILTER_CLASS(klass)); + /* we take the larger (wb) frame size */ + speex_mode_query(&speex_wb_mode, SPEEX_MODE_FRAME_SIZE, &frame_size); + MS_FILTER_CLASS(klass)->process=(MSFilterProcessFunc)ms_speex_enc_process; + MS_FILTER_CLASS(klass)->destroy=(MSFilterDestroyFunc)ms_speex_enc_destroy; + MS_FILTER_CLASS(klass)->setup=(MSFilterSetupFunc)ms_speex_enc_setup; + MS_FILTER_CLASS(klass)->unsetup=(MSFilterSetupFunc)ms_speex_enc_unsetup; + MS_FILTER_CLASS(klass)->set_property=(MSFilterPropertyFunc)ms_speex_enc_set_property; + ms_filter_class_set_name(MS_FILTER_CLASS(klass),"SpeexEncoder"); + MS_FILTER_CLASS(klass)->info=(MSFilterInfo*)&speex_info; + MS_FILTER_CLASS(klass)->max_finputs=1; + MS_FILTER_CLASS(klass)->max_qoutputs=1; + MS_FILTER_CLASS(klass)->r_maxgran=frame_size*2; + ms_trace("ms_speex_enc_class_init: r_maxgran is %i.",MS_FILTER_CLASS(klass)->r_maxgran); +} + +void ms_speex_enc_uninit_core(MSSpeexEnc *obj) +{ + if (obj->initialized){ + speex_encoder_destroy(obj->speex_state); + obj->initialized=0; + } +} + +void ms_speex_enc_destroy(MSSpeexEnc *obj) +{ + ms_speex_enc_uninit_core(obj); + g_free(obj); +} + +void ms_speex_enc_process(MSSpeexEnc *obj) +{ + MSFifo *inf=obj->inf[0]; + MSQueue *outq=obj->outq[0]; + gint16 *input; + gint gran=MS_FILTER(obj)->r_mingran; + gint i; + MSMessage *m; + + g_return_if_fail(inf!=NULL); + g_return_if_fail(outq!=NULL); + + ms_fifo_get_read_ptr(inf,gran,(void**)&input); + g_return_if_fail(input!=NULL); + /* encode */ + speex_bits_reset(&obj->bits); + speex_encode_int(obj->speex_state,(short*)input,&obj->bits); + m=ms_message_new(speex_bits_nbytes(&obj->bits)); + m->size=speex_bits_write(&obj->bits,m->data,m->size); + ms_queue_put(outq,m); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msspeexenc.h Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,66 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + + +#ifndef MSSPEEXENC_H +#define MSSPEEXENC_H + +#include <mscodec.h> +#include <speex.h> + +struct _MSSpeexEnc +{ + MSFilter parent; + MSFifo *inf[1]; + MSQueue *outq[1]; /* speex has an output q because it can be variable bit rate */ + void *speex_state; + SpeexBits bits; + int frequency; + int bitrate; + int initialized; +}; + +typedef struct _MSSpeexEnc MSSpeexEnc; + + +struct _MSSpeexEncClass +{ + MSFilterClass parent; +}; + +typedef struct _MSSpeexEncClass MSSpeexEncClass; + + +#define MS_SPEEX_ENC(o) ((MSSpeexEnc*)(o)) +#define MS_SPEEX_ENC_CLASS(o) ((MSSpeexEncClass*)(o)) + +/* generic constructor */ +MSFilter * ms_speex_enc_new(); + +void ms_speex_enc_init_core(MSSpeexEnc *obj,const SpeexMode *mode, gint quality); +void ms_speex_enc_uninit_core(MSSpeexEnc *obj); +void ms_speex_enc_init(MSSpeexEnc *obj); +void ms_speex_enc_class_init(MSSpeexEncClass *klass); + + +void ms_speex_enc_process(MSSpeexEnc *obj); +void ms_speex_enc_destroy(MSSpeexEnc *obj); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/mssync.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,193 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + +#include "mssync.h" +#include <errno.h> + +/* TODO: + -define an uninit function that free the mutex +*/ + +/** + * function_name:ms_sync_get_bytes_per_tick + * @sync: A #MSSync object. + * + * Returns the number of bytes per tick. This is a usefull information for sources, so + * that they can know how much data they must deliver each time they are called. + * + */ + +/* private */ +void ms_sync_init(MSSync *sync) +{ + sync->klass=NULL; + sync->lock=g_mutex_new(); + sync->thread_cond=g_cond_new(); + sync->stop_cond=g_cond_new(); + sync->attached_filters=NULL; + sync->execution_list=NULL; + sync->filters=0; + sync->run=0; + sync->flags=0; + sync->samples_per_tick=0; + sync->ticks=0; + sync->time=0; + sync->thread=NULL; +} + +void ms_sync_class_init(MSSyncClass *klass) +{ + klass->max_filters=0; + klass->synchronize=NULL; + klass->attach=ms_sync_attach_generic; + klass->detach=ms_sync_detach_generic; + klass->destroy=NULL; +} + +/* public*/ + + +/** + * ms_sync_attach: + * @sync: A #MSSync object. + * @f: A #MSFilter object. + * + * Attach a chain of filters to a synchronisation source @sync. Filter @f must be the first filter of the processing chain. + * In order to be run, each chain of filter must be attached to a synchronisation source, that will be responsible for scheduling + * the processing. Multiple chains can be attached to a single synchronisation. + * + * Returns: 0 if successfull, a negative value reprensenting the errno.h error. + */ +int ms_sync_attach(MSSync *sync,MSFilter *f) +{ + gint err; + ms_sync_lock(sync); + err=sync->klass->attach(sync,f); + ms_sync_update(sync); + ms_sync_unlock(sync); + return(err); +} + +int ms_sync_attach_generic(MSSync *sync,MSFilter *f) +{ + int i; + //printf("attr: %i\n",f->klass->attributes); + g_return_val_if_fail(f->klass->attributes & FILTER_IS_SOURCE,-EINVAL); + g_return_val_if_fail(sync->attached_filters!=NULL,-EFAULT); + + + /* find a free place to attach*/ + for (i=0;i<sync->klass->max_filters;i++) + { + if (sync->attached_filters[i]==NULL) + { + sync->attached_filters[i]=f; + sync->filters++; + ms_trace("Filter succesfully attached to sync."); + return 0; + } + } + g_warning("No more link on sync !"); + return(-EMLINK); +} + +/** + * ms_sync_detach: + * @sync: A #MSSync object. + * @f: A #MSFilter object. + * + * Dettach a chain of filters to a synchronisation source. Filter @f must be the first filter of the processing chain. + * The processing chain will no more be executed. + * + * Returns: 0 if successfull, a negative value reprensenting the errno.h error. + */ +int ms_sync_detach(MSSync *sync,MSFilter *f) +{ + gint err; + ms_sync_lock(sync); + err=sync->klass->detach(sync,f); + ms_sync_update(sync); + ms_sync_unlock(sync); + return(err); +} + +int ms_sync_detach_generic(MSSync *sync,MSFilter *f) +{ + int i; + g_return_val_if_fail(f->klass->attributes & FILTER_IS_SOURCE,-EINVAL); + g_return_val_if_fail(sync->attached_filters!=NULL,-EFAULT); + for (i=0;i<sync->filters;i++) + { + if (sync->attached_filters[i]==f) + { + sync->attached_filters[i]=NULL; + sync->filters--; + return 0; + } + } + return(-EMLINK); +} + +void ms_sync_set_samples_per_tick(MSSync *sync,gint size) +{ + if (sync->samples_per_tick==0) + { + sync->samples_per_tick=size; + g_cond_signal(sync->thread_cond); + } + else sync->samples_per_tick=size; +} + +/* call the setup func of each filter attached to the graph */ +void ms_sync_setup(MSSync *sync) +{ + GList *elem=sync->execution_list; + MSFilter *f; + while(elem!=NULL){ + f=(MSFilter*)elem->data; + if (f->klass->setup!=NULL){ + f->klass->setup(f,sync); + } + elem=g_list_next(elem); + } +} + +/* call the unsetup func of each filter attached to the graph */ +void ms_sync_unsetup(MSSync *sync) +{ + GList *elem=sync->execution_list; + MSFilter *f; + while(elem!=NULL){ + f=(MSFilter*)elem->data; + if (f->klass->unsetup!=NULL){ + f->klass->unsetup(f,sync); + } + elem=g_list_next(elem); + } +} + + +int ms_sync_uninit(MSSync *sync) +{ + g_mutex_free(sync->lock); + g_cond_free(sync->thread_cond); + g_cond_free(sync->stop_cond); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/mssync.h Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,136 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + +#ifndef MS_SYNC_H +#define MS_SYNC_H + + +#include "msfilter.h" + +struct _MSSync +{ + struct _MSSyncClass *klass; + GMutex *lock; + MSFilter **attached_filters; /* pointer to a table of pointer of filters*/ + GList *execution_list; /* the list of filters to be executed. This is filled with compilation */ + gint filters; /*number of filters attached to the sync */ + gint run; /* flag to indicate whether the sync must be run or not */ + GThread * thread; /* the thread ressource if this sync is run by a thread*/ + GCond *thread_cond; + GCond *stop_cond; + guint32 flags; + gint interval; /* in miliseconds*/ +#define MS_SYNC_NEED_UPDATE (0x0001) /* a modification has occured in the processing chains + attached to this sync; so the execution list has to be updated */ + guint samples_per_tick; /* number of bytes produced by sources of the processing chains*/ + guint32 ticks; + guint32 time; /* a time since the start of the sync expressed in milisec*/ +}; + +typedef struct _MSSync MSSync; + +typedef void (*MSSyncDestroyFunc)(MSSync*); +typedef void (*MSSyncSyncFunc)(MSSync*); +typedef int (*MSSyncAttachFunc)(MSSync*,MSFilter*); +typedef int (*MSSyncDetachFunc)(MSSync*,MSFilter*); + +typedef struct _MSSyncClass +{ + gint max_filters; /* the maximum number of filters that can be attached to this sync*/ + MSSyncSyncFunc synchronize; + MSSyncDestroyFunc destroy; + MSSyncAttachFunc attach; + MSSyncDetachFunc detach; +} MSSyncClass; + +/* private */ +void ms_sync_init(MSSync *sync); +void ms_sync_class_init(MSSyncClass *klass); + +int ms_sync_attach_generic(MSSync *sync,MSFilter *f); +int ms_sync_detach_generic(MSSync *sync,MSFilter *f); + +/* public*/ + +#define MS_SYNC(sync) ((MSSync*)(sync)) +#define MS_SYNC_CLASS(klass) ((MSSyncClass*)(klass)) + +#define ms_sync_synchronize(_sync) \ +do \ +{ \ + MSSync *__sync=_sync; \ + __sync->ticks++; \ + ((__sync)->klass->synchronize((__sync))); \ +}while(0) + +void ms_sync_setup(MSSync *sync); + +void ms_sync_unsetup(MSSync *sync); + +#define ms_sync_update(sync) (sync)->flags|=MS_SYNC_NEED_UPDATE + +#define ms_sync_get_samples_per_tick(sync) ((sync)->samples_per_tick) + +void ms_sync_set_samples_per_tick(MSSync *sync,gint size); + +#define ms_sync_get_tick_count(sync) ((sync)->ticks) + +#define ms_sync_suspend(sync) g_cond_wait((sync)->thread_cond,(sync)->lock) + +#define ms_sync_lock(sync) g_mutex_lock((sync)->lock) + +#define ms_sync_unlock(sync) g_mutex_unlock((sync)->lock) + +#define ms_sync_trylock(sync) g_mutex_trylock((sync)->lock) + +/** + * function_name:ms_sync_attach + * @sync: A #MSSync object. + * @f: A #MSFilter object. + * + * Attach a chain of filters to a synchronisation source. Filter @f must be the first filter of the processing chain. + * + * Returns: 0 if successfull, a negative value reprensenting the errno.h error. + */ +int ms_sync_attach(MSSync *sync,MSFilter *f); + +/** + * ms_sync_detach: + * @sync: A #MSSync object. + * @f: A #MSFilter object. + * + * Dettach a chain of filters to a synchronisation source. Filter @f must be the first filter of the processing chain. + * The processing chain will no more be executed. + * + * Returns: 0 if successfull, a negative value reprensenting the errno.h error. + */ +int ms_sync_detach(MSSync *sync,MSFilter *f); + +int ms_sync_uninit(MSSync *sync); + +#define ms_sync_start(sync) ms_start((sync)) +#define ms_sync_stop(sync) ms_stop((sync)) + + +/*destroy*/ +#define ms_sync_destroy(sync) (sync)->klass->destroy((sync)) + + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/mstimer.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,114 @@ + /* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + + +#include "mstimer.h" +#include <unistd.h> +#include <sys/types.h> +#include <sys/time.h> +#include <signal.h> + +static MSTimerClass *ms_timer_class=NULL; + + +void ms_timer_init(MSTimer *sync) +{ + ms_sync_init(MS_SYNC(sync)); + MS_SYNC(sync)->attached_filters=sync->filters; + memset(sync->filters,0,MSTIMER_MAX_FILTERS*sizeof(MSFilter*)); + MS_SYNC(sync)->samples_per_tick=160; + ms_timer_set_interval(sync,20); + sync->state=MS_TIMER_STOPPED; +} + +void ms_timer_class_init(MSTimerClass *klass) +{ + ms_sync_class_init(MS_SYNC_CLASS(klass)); + MS_SYNC_CLASS(klass)->max_filters=MSTIMER_MAX_FILTERS; + MS_SYNC_CLASS(klass)->synchronize=(MSSyncSyncFunc)ms_timer_synchronize; + MS_SYNC_CLASS(klass)->destroy=(MSSyncDestroyFunc)ms_timer_destroy; + /* no need to overload these function*/ + MS_SYNC_CLASS(klass)->attach=ms_sync_attach_generic; + MS_SYNC_CLASS(klass)->detach=ms_sync_detach_generic; +} + +void ms_timer_destroy(MSTimer *timer) +{ + g_free(timer); +} + + +void ms_timer_synchronize(MSTimer *timer) +{ + //printf("ticks=%i \n",MS_SYNC(timer)->ticks); + if (timer->state==MS_TIMER_STOPPED){ + timer->state=MS_TIMER_RUNNING; + gettimeofday(&timer->orig,NULL); + timer->sync.time=0; + } + else { + gint32 diff,time; + struct timeval tv,cur; + + gettimeofday(&cur,NULL); + time=((cur.tv_usec-timer->orig.tv_usec)/1000 ) + ((cur.tv_sec-timer->orig.tv_sec)*1000 ); + if ( (diff=time-timer->sync.time)>50){ + g_warning("Must catchup %i miliseconds.",diff); + } + while((diff = timer->sync.time-time) > 0) + { + tv.tv_sec = diff/1000; + tv.tv_usec = (diff%1000)*1000; + select(0,NULL,NULL,NULL,&tv); + gettimeofday(&cur,NULL); + time=((cur.tv_usec-timer->orig.tv_usec)/1000 ) + ((cur.tv_sec-timer->orig.tv_sec)*1000 ); + } + } + timer->sync.time+=timer->milisec; + return; +} + + +MSSync *ms_timer_new() +{ + MSTimer *timer; + + timer=g_malloc(sizeof(MSTimer)); + ms_timer_init(timer); + if (ms_timer_class==NULL) + { + ms_timer_class=g_new(MSTimerClass,1); + ms_timer_class_init(ms_timer_class); + } + MS_SYNC(timer)->klass=MS_SYNC_CLASS(ms_timer_class); + return(MS_SYNC(timer)); +} + +void ms_timer_set_interval(MSTimer *timer, int milisec) +{ + + MS_SYNC(timer)->ticks=0; + MS_SYNC(timer)->interval=milisec; + timer->interval.tv_sec=milisec/1000; + timer->interval.tv_usec=(milisec % 1000)*1000; + timer->milisec=milisec; + + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/mstimer.h Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,68 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ +#ifndef MSTIMER_H +#define MSTIMER_H + +#include "mssync.h" +#include <sys/time.h> + +#define MSTIMER_MAX_FILTERS 10 + +/* MSTimer derivates from MSSync base class*/ + +typedef struct _MSTimer +{ + /* the MSSync must be the first field of the object in order to the object mechanism to work*/ + MSSync sync; + MSFilter *filters[MSTIMER_MAX_FILTERS]; + gint milisec; /* the interval */ + struct timeval interval; + struct timeval orig; + gint state; +} MSTimer; + + +typedef struct _MSTimerClass +{ + /* the MSSyncClass must be the first field of the class in order to the class mechanism to work*/ + MSSyncClass parent_class; +} MSTimerClass; + + +/*private*/ +#define MS_TIMER_RUNNING 1 +#define MS_TIMER_STOPPED 0 +void ms_timer_init(MSTimer *sync); +void ms_timer_class_init(MSTimerClass *sync); + +void ms_timer_destroy(MSTimer *timer); +void ms_timer_synchronize(MSTimer *timer); + +/*public*/ +void ms_timer_set_interval(MSTimer *timer, gint milisec); + +/* casts a MSSync object into a MSTimer */ +#define MS_TIMER(sync) ((MSTimer*)(sync)) +/* casts a MSSync class into a MSTimer class */ +#define MS_TIMER_CLASS(klass) ((MSTimerClass*)(klass)) + +MSSync *ms_timer_new(); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/mstruespeechdecoder.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,152 @@ +/* + Copyright 2003 Robert W. Brewer <rbrewer at op.net> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + + +#include "mstruespeechdecoder.h" +#include "mscodec.h" + +MSCodecInfo TrueSpeechinfo = +{ + { + "TrueSpeech codec", + 0, + MS_FILTER_AUDIO_CODEC, + ms_truespeechencoder_new, + "This is a proprietary codec by the DSP Group that is used in some " + "Windows applications. It has a good quality and bitrate. " + "It requires the Windows DLLs tssoft32.acm and " + "tsd32.dll to be available." + }, + ms_truespeechencoder_new, + ms_truespeechdecoder_new, + 480, + 32, + 8536, + 8000, + 116, + "TSP0", + 1, + 1, +}; + + +static MSTrueSpeechDecoderClass *ms_truespeechdecoder_class = 0; + +/* FOR INTERNAL USE*/ +void ms_truespeechdecoder_init(MSTrueSpeechDecoder *r); +void ms_truespeechdecoder_class_init(MSTrueSpeechDecoderClass *klass); +void ms_truespeechdecoder_destroy(MSTrueSpeechDecoder *obj); +void ms_truespeechdecoder_process(MSTrueSpeechDecoder *r); + +MSFilter * ms_truespeechdecoder_new(void) +{ + MSTrueSpeechDecoder *r = 0; + + if (!ms_truespeechdecoder_class) + { + ms_truespeechdecoder_class = g_new(MSTrueSpeechDecoderClass, 1); + ms_truespeechdecoder_class_init(ms_truespeechdecoder_class); + } + + r = g_new(MSTrueSpeechDecoder, 1); + MS_FILTER(r)->klass = MS_FILTER_CLASS(ms_truespeechdecoder_class); + ms_truespeechdecoder_init(r); + return MS_FILTER(r); +} + + +/* FOR INTERNAL USE*/ +void ms_truespeechdecoder_init(MSTrueSpeechDecoder *r) +{ + ms_filter_init(MS_FILTER(r)); + MS_FILTER(r)->infifos = r->f_inputs; + MS_FILTER(r)->outfifos = r->f_outputs; + + WAVEFORMATEX* wf = ms_truespeechencoder_wf_create(); + + r->codec = win32codec_create(wf, 0); + free(wf); + + MS_FILTER(r)->r_mingran = r->codec->min_insize; + + MS_FILTER_CLASS(ms_truespeechdecoder_class)->r_maxgran = + r->codec->min_insize; + MS_FILTER_CLASS(ms_truespeechdecoder_class)->w_maxgran = + r->codec->min_outsize; + + memset(r->f_inputs, 0, sizeof(MSFifo*) * MS_TRUESPEECH_CODEC_MAX_IN_OUT); + memset(r->f_outputs, 0, sizeof(MSFifo*) * MS_TRUESPEECH_CODEC_MAX_IN_OUT); +} + +void ms_truespeechdecoder_class_init(MSTrueSpeechDecoderClass *klass) +{ + ms_filter_class_init(MS_FILTER_CLASS(klass)); + ms_filter_class_set_name(MS_FILTER_CLASS(klass), "TrueSpeechDecoder"); + MS_FILTER_CLASS(klass)->max_finputs = MS_TRUESPEECH_CODEC_MAX_IN_OUT; + MS_FILTER_CLASS(klass)->max_foutputs = MS_TRUESPEECH_CODEC_MAX_IN_OUT; + MS_FILTER_CLASS(klass)->r_maxgran = 0; /* filled in by first instance */ + MS_FILTER_CLASS(klass)->w_maxgran = 0; /* filled in by first instance */ + MS_FILTER_CLASS(klass)->destroy = (MSFilterDestroyFunc)ms_truespeechdecoder_destroy; + MS_FILTER_CLASS(klass)->process = (MSFilterProcessFunc)ms_truespeechdecoder_process; + MS_FILTER_CLASS(klass)->info = MS_FILTER_INFO(&TrueSpeechinfo); + klass->driver = win32codec_create_driver(TRUESPEECH_DLL, + TRUESPEECH_FORMAT_TAG, 0); +} + +void ms_truespeechdecoder_process(MSTrueSpeechDecoder *r) +{ + MSFifo *fi,*fo; + gint err1; + void *s,*d; + + /* process output fifos, but there is only one for this class of filter*/ + + fi = r->f_inputs[0]; + fo = r->f_outputs[0]; + if (fi) + { + err1 = ms_fifo_get_read_ptr(fi, r->codec->min_insize, &s); + if (err1 > 0) + { + err1 = ms_fifo_get_write_ptr(fo, r->codec->min_outsize, &d); + if (d) + { + signed long n; + n = win32codec_convert(r->codec, + s, r->codec->min_insize, + d, r->codec->min_outsize); + } + } + + } +} + + + +void ms_truespeechdecoder_uninit(MSTrueSpeechDecoder *obj) +{ + win32codec_destroy(obj->codec); +} + +void ms_truespeechdecoder_destroy(MSTrueSpeechDecoder *obj) +{ + ms_truespeechdecoder_uninit(obj); + g_free(obj); +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/mstruespeechdecoder.h Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,55 @@ +/* + Copyright (C) 2003 Robert W. Brewer <rbrewer at op.net> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + + +#ifndef MSTRUESPEECHDECODER_H +#define MSTRUESPEECHDECODER_H + +#include "msfilter.h" +#include "mstruespeechencoder.h" + + + +typedef struct _MSTrueSpeechDecoder +{ + /* the MSTrueSpeechDecoder derives from MSFilter, so the MSFilter + object MUST be the first of the MSTrueSpeechDecoder object + in order for the object mechanism to work*/ + MSFilter filter; + MSFifo *f_inputs[MS_TRUESPEECH_CODEC_MAX_IN_OUT]; + MSFifo *f_outputs[MS_TRUESPEECH_CODEC_MAX_IN_OUT]; + Win32Codec* codec; +} MSTrueSpeechDecoder; + +typedef struct _MSTrueSpeechDecoderClass +{ + /* the MSTrueSpeechDecoder derives from MSFilter, + so the MSFilter class MUST be the first of the MSTrueSpechDecoder + class + in order for the class mechanism to work*/ + MSFilterClass parent_class; + Win32CodecDriver* driver; +} MSTrueSpeechDecoderClass; + +/* PUBLIC */ +#define MS_TRUESPEECHDECODER(filter) ((MSTrueSpechMDecoder*)(filter)) +#define MS_TRUESPEECHDECODER_CLASS(klass) ((MSTrueSpeechDecoderClass*)(klass)) +MSFilter * ms_truespeechdecoder_new(void); + + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/mstruespeechencoder.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,161 @@ +/* + Copyright 2003 Robert W. Brewer <rbrewer at op.net> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + + +#include "mstruespeechencoder.h" +#include "mscodec.h" + +#define TRUESPEECH_CBSIZE 32 + +extern MSCodecInfo TrueSpeechinfo; + +static MSTrueSpeechEncoderClass *ms_truespeechencoder_class = 0; + +/* FOR INTERNAL USE*/ +void ms_truespeechencoder_init(MSTrueSpeechEncoder *r); +void ms_truespeechencoder_class_init(MSTrueSpeechEncoderClass *klass); +void ms_truespeechencoder_destroy(MSTrueSpeechEncoder *obj); +void ms_truespeechencoder_process(MSTrueSpeechEncoder *r); + +MSFilter * ms_truespeechencoder_new(void) +{ + MSTrueSpeechEncoder *r = 0; + + if (!ms_truespeechencoder_class) + { + ms_truespeechencoder_class = g_new(MSTrueSpeechEncoderClass, 1); + ms_truespeechencoder_class_init(ms_truespeechencoder_class); + } + + r = g_new(MSTrueSpeechEncoder, 1); + MS_FILTER(r)->klass = MS_FILTER_CLASS(ms_truespeechencoder_class); + ms_truespeechencoder_init(r); + return MS_FILTER(r); +} + + +/* FOR INTERNAL USE*/ +void ms_truespeechencoder_init(MSTrueSpeechEncoder *r) +{ + ms_filter_init(MS_FILTER(r)); + MS_FILTER(r)->infifos = r->f_inputs; + MS_FILTER(r)->outfifos = r->f_outputs; + + WAVEFORMATEX* wf = ms_truespeechencoder_wf_create(); + + r->codec = win32codec_create(wf, 1); + free(wf); + + MS_FILTER(r)->r_mingran = r->codec->min_insize; + + MS_FILTER_CLASS(ms_truespeechencoder_class)->r_maxgran = + r->codec->min_insize; + MS_FILTER_CLASS(ms_truespeechencoder_class)->w_maxgran = + r->codec->min_outsize; + + memset(r->f_inputs, 0, sizeof(MSFifo*) * MS_TRUESPEECH_CODEC_MAX_IN_OUT); + memset(r->f_outputs, 0, sizeof(MSFifo*) * MS_TRUESPEECH_CODEC_MAX_IN_OUT); +} + +void ms_truespeechencoder_class_init(MSTrueSpeechEncoderClass *klass) +{ + ms_filter_class_init(MS_FILTER_CLASS(klass)); + ms_filter_class_set_name(MS_FILTER_CLASS(klass), "TrueSpeechEncoder"); + MS_FILTER_CLASS(klass)->max_finputs = MS_TRUESPEECH_CODEC_MAX_IN_OUT; + MS_FILTER_CLASS(klass)->max_foutputs = MS_TRUESPEECH_CODEC_MAX_IN_OUT; + MS_FILTER_CLASS(klass)->r_maxgran = 0; /* filled in by first instance */ + MS_FILTER_CLASS(klass)->w_maxgran = 0; /* filled in by first instance */ + MS_FILTER_CLASS(klass)->destroy = (MSFilterDestroyFunc)ms_truespeechencoder_destroy; + MS_FILTER_CLASS(klass)->process = (MSFilterProcessFunc)ms_truespeechencoder_process; + MS_FILTER_CLASS(klass)->info = MS_FILTER_INFO(&TrueSpeechinfo); + klass->driver = win32codec_create_driver(TRUESPEECH_DLL, + TRUESPEECH_FORMAT_TAG, 1); +} + +void ms_truespeechencoder_process(MSTrueSpeechEncoder *r) +{ + MSFifo *fi,*fo; + int err1; + void *s,*d; + + /* process output fifos, but there is only one for this class of filter*/ + + fi = r->f_inputs[0]; + fo = r->f_outputs[0]; + if (fi) + { + err1 = ms_fifo_get_read_ptr(fi, r->codec->min_insize, &s); + if (err1 > 0) + { + err1 = ms_fifo_get_write_ptr(fo, r->codec->min_outsize, &d); + if (d) + { + signed long n; + + n = win32codec_convert(r->codec, + s, r->codec->min_insize, + d, r->codec->min_outsize); + } + } + + } +} + + + +void ms_truespeechencoder_uninit(MSTrueSpeechEncoder *obj) +{ + win32codec_destroy(obj->codec); +} + +void ms_truespeechencoder_destroy(MSTrueSpeechEncoder *obj) +{ + ms_truespeechencoder_uninit(obj); + g_free(obj); +} + + +WAVEFORMATEX* ms_truespeechencoder_wf_create() +{ + WAVEFORMATEX* ts_wf = 0; + long* iptr = 0; + + ts_wf = malloc(sizeof(WAVEFORMATEX) + TRUESPEECH_CBSIZE); + if (!ts_wf) + { + return 0; + } + + memset(ts_wf, 0, sizeof(*ts_wf) + TRUESPEECH_CBSIZE); + + ts_wf->wFormatTag = TRUESPEECH_FORMAT_TAG; + ts_wf->nChannels = 1; + ts_wf->nSamplesPerSec = 8000; + ts_wf->wBitsPerSample = 1; + ts_wf->nBlockAlign = 32; + ts_wf->nAvgBytesPerSec = 1067; + ts_wf->cbSize = TRUESPEECH_CBSIZE; + + /* write extra data needed by TrueSpeech codec found + from examining a TrueSpeech .wav file header + */ + iptr = (long*)(ts_wf + 1); + *iptr = 0x00f00001; + + return ts_wf; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/mstruespeechencoder.h Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,62 @@ +/* + Copyright (C) 2003 Robert W. Brewer <rbrewer at op.net> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + + +#ifndef MSTRUESPEECHENCODER_H +#define MSTRUESPEECHENCODER_H + +#include "msfilter.h" +#include <win32codec.h> + + +#define MS_TRUESPEECH_CODEC_MAX_IN_OUT 1 /* max inputs/outputs per filter*/ + +#define TRUESPEECH_FORMAT_TAG 0x22 +#define TRUESPEECH_DLL "tssoft32.acm" + +typedef struct _MSTrueSpeechEncoder +{ + /* the MSTrueSpeechEncoder derives from MSFilter, so the MSFilter + object MUST be the first of the MSTrueSpeechEncoder object + in order for the object mechanism to work*/ + MSFilter filter; + MSFifo *f_inputs[MS_TRUESPEECH_CODEC_MAX_IN_OUT]; + MSFifo *f_outputs[MS_TRUESPEECH_CODEC_MAX_IN_OUT]; + Win32Codec* codec; +} MSTrueSpeechEncoder; + +typedef struct _MSTrueSpeechEncoderClass +{ + /* the MSTrueSpeechEncoder derives from MSFilter, + so the MSFilter class MUST be the first of the MSTrueSpechEncoder + class + in order for the class mechanism to work*/ + MSFilterClass parent_class; + Win32CodecDriver* driver; +} MSTrueSpeechEncoderClass; + +/* PUBLIC */ +#define MS_TRUESPEECHENCODER(filter) ((MSTrueSpechMEncoder*)(filter)) +#define MS_TRUESPEECHENCODER_CLASS(klass) ((MSTrueSpeechEncoderClass*)(klass)) +MSFilter * ms_truespeechencoder_new(void); + +/* for internal use only */ +WAVEFORMATEX* ms_truespeechencoder_wf_create(); + + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msutils.h Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,61 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ +#ifndef MSUTILS_H +#define MSUTILS_H + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifdef HAVE_GLIB +#include <glib.h> +#else +#include <uglib.h> +#endif +#include <errno.h> + +#ifndef ENODATA +/* this is for freeBSD .*/ +#define ENODATA EWOULDBLOCK +#endif + +#ifdef MS_DEBUG + +#define ms_trace g_message + +#else + +#define ms_trace(...) +#endif + +#define ms_warning g_warning +#define ms_error g_error + +#define VIDEO_SIZE_CIF_W 352 +#define VIDEO_SIZE_CIF_H 288 +#define VIDEO_SIZE_QCIF_W 176 +#define VIDEO_SIZE_QCIF_H 144 +#define VIDEO_SIZE_4CIF_W 704 +#define VIDEO_SIZE_4CIF_H 576 +#define VIDEO_SIZE_MAX_W VIDEO_SIZE_4CIF_W +#define VIDEO_SIZE_MAX_H VIDEO_SIZE_4CIF_H + + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msv4l.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,530 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + +#include "msv4l.h" +#include <fcntl.h> +#include <unistd.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/ioctl.h> +#include <errno.h> +#include <string.h> +#include <sys/mman.h> + +char *v4l_palette_string[17]={ + "none", + "GREY", /* Linear greyscale */ + "HI240", /* High 240 cube (BT848) */ + "RGB565", /* 565 16 bit RGB */ + "RGB24", /* 24bit RGB */ + "RGB32", /* 32bit RGB */ + "RGB555", /* 555 15bit RGB */ + "YUV422", /* YUV422 capture */ + "YUYV", + "UYVY", /* The great thing about standards is ... */ + "YUV420", + "YUV411", /* YUV411 capture */ + "RAW", /* RAW capture (BT848) */ + "YUV422P", /* YUV 4:2:2 Planar */ + "YUV411P", /* YUV 4:1:1 Planar */ + "YUV420P", /* YUV 4:2:0 Planar */ + "YUV410P", /* YUV 4:1:0 Planar */ +}; + +#define V4L_PALETTE_TO_STRING(pal) v4l_palette_string[(pal)] + +MSFilterInfo v4l_info= +{ + "Video4Linux", + 0, + MS_FILTER_VIDEO_IO, + ms_v4l_new, + NULL +}; + + +static MSV4lClass *ms_v4l_class=NULL; + +MSFilter * ms_v4l_new() +{ + MSV4l *obj; + obj=g_malloc0(sizeof(MSV4l)); + if (ms_v4l_class==NULL) + { + ms_v4l_class=g_malloc0(sizeof(MSV4lClass)); + ms_v4l_class_init(ms_v4l_class); + } + MS_FILTER(obj)->klass=MS_FILTER_CLASS(ms_v4l_class); + ms_v4l_init(obj); + return MS_FILTER(obj); +} + +void ms_v4l_init(MSV4l *obj) +{ + ms_video_source_init(MS_VIDEO_SOURCE(obj)); + /* initialize the static buffer */ + obj->use_mmap=0; + obj->fd=-1; + obj->device = g_strdup("/dev/video0"); + obj->count=0; + obj->allocdbuf=NULL; + obj->grab_image=FALSE; + obj->image_grabbed=NULL; + obj->cond=g_cond_new(); + obj->stopcond=g_cond_new(); + obj->v4lthread=NULL; + obj->thread_exited=FALSE; + obj->frame=0; + MS_VIDEO_SOURCE(obj)->format="RGB24"; /*default value */ + MS_VIDEO_SOURCE(obj)->width = VIDEO_SIZE_CIF_W; /*default value */ + MS_VIDEO_SOURCE(obj)->height = VIDEO_SIZE_CIF_H; /*default value */ +} + +void ms_v4l_class_init(MSV4lClass *klass) +{ + ms_video_source_class_init(MS_VIDEO_SOURCE_CLASS(klass)); + MS_VIDEO_SOURCE_CLASS(klass)->start=(void (*)(MSVideoSource *))ms_v4l_start; + MS_VIDEO_SOURCE_CLASS(klass)->stop=(void (*)(MSVideoSource *))ms_v4l_stop; + MS_VIDEO_SOURCE_CLASS(klass)->set_device=(int (*)(MSVideoSource*,const gchar*))ms_v4l_set_device; + MS_FILTER_CLASS(klass)->process=(void (*)(MSFilter *))v4l_process; + MS_FILTER_CLASS(klass)->destroy=(MSFilterDestroyFunc)ms_v4l_destroy; + ms_filter_class_set_name(MS_FILTER_CLASS(klass),"msv4l"); + MS_FILTER_CLASS(klass)->info=(MSFilterInfo*)&v4l_info; +} + +void *v4l_thread(MSV4l *obj); + +void ms_v4l_start(MSV4l *obj) +{ + int err; + ms_filter_lock(MS_FILTER(obj)); + obj->fd=open(obj->device,O_RDONLY); + if (obj->fd<0) + { + g_warning("MSV4l: cannot open video device: %s.",strerror(errno)); + }else{ + err=v4l_configure(obj); + if (err<0) + { + g_warning("MSV4l: could not get configuration of video device"); + } + } + obj->thread_exited=FALSE; + obj->v4lthread=g_thread_create((GThreadFunc)v4l_thread,(gpointer)obj,FALSE,NULL); + while(!obj->thread_run) g_cond_wait(obj->cond,MS_FILTER(obj)->lock); + ms_filter_unlock(MS_FILTER(obj)); +} + +void ms_v4l_stop(MSV4l *obj) +{ + ms_filter_lock(MS_FILTER(obj)); + obj->thread_run=FALSE; + obj->grab_image=FALSE; + g_cond_signal(obj->cond); + if (obj->fd>0) + { + close(obj->fd); + obj->fd=-1; + if (!obj->use_mmap){ + if (obj->allocdbuf!=NULL) ms_buffer_destroy(obj->allocdbuf); + else obj->allocdbuf=NULL; + }else + { + munmap(obj->mmapdbuf,obj->vmbuf.size); + obj->mmapdbuf=NULL; + } + obj->image_grabbed=NULL; + } + while(!obj->thread_exited) g_cond_wait(obj->stopcond,MS_FILTER(obj)->lock); + obj->v4lthread=NULL; + ms_filter_unlock(MS_FILTER(obj)); +} + +gint ms_v4l_get_width(MSV4l *v4l) +{ + return v4l->win.width; +} + +gint ms_v4l_get_height(MSV4l *v4l) +{ + return v4l->win.height; +} + +int ms_v4l_set_device(MSV4l *obj, const gchar *device) +{ + if (obj->device!=NULL) g_free(obj->device); + obj->device=g_strdup(device); + return 0; +} + +void ms_v4l_set_size(MSV4l *obj, gint width, gint height) +{ + gint err; + gboolean restart = FALSE; + + if (obj->fd == -1) + { + obj->fd = open(obj->device, O_RDONLY); + if (obj->fd < 0) + { + g_warning("MSV4l: cannot open video device: %s.",strerror(errno)); + return; + } + } else + restart = TRUE; + + ms_filter_lock(MS_FILTER(obj)); + err = ioctl(obj->fd, VIDIOCGCAP, &obj->cap); + if (err != 0) + { + g_warning("MSV4l: cannot get device capabilities: %s.",strerror(errno)); + return; + } + if (width <= obj->cap.maxwidth && width >= obj->cap.minwidth && + height <= obj->cap.maxheight && height >= obj->cap.minheight) + { + MS_VIDEO_SOURCE(obj)->width = width; + MS_VIDEO_SOURCE(obj)->height = height; + } + ms_filter_unlock(MS_FILTER(obj)); + + if (restart) + { + ms_v4l_stop(obj); + ms_v4l_start(obj); + } + +} + +int v4l_configure(MSV4l *f) +{ + gint err; + gint i; + struct video_channel *chan=&f->channel; + struct video_window *win=&f->win; + struct video_picture *pict=&f->pict; + struct video_mmap *vmap=&f->vmap; + struct video_mbuf *vmbuf=&f->vmbuf; + struct video_capture *vcap=&f->vcap; + int found=0; + + err=ioctl(f->fd,VIDIOCGCAP,&f->cap); + if (err!=0) + { + g_warning("MSV4l: cannot get device capabilities: %s.",strerror(errno)); + return -1; + } + MS_VIDEO_SOURCE(f)->dev_name=f->cap.name; + + for (i=0;i<f->cap.channels;i++) + { + chan->channel=i; + err=ioctl(f->fd,VIDIOCGCHAN,chan); + if (err==0) + { + g_message("Getting video channel %s",chan->name); + switch(chan->type){ + case VIDEO_TYPE_TV: + g_message("Channel is a TV."); + break; + case VIDEO_TYPE_CAMERA: + g_message("Channel is a camera"); + break; + default: + g_warning("unknown video channel type."); + } + found=1; + break; /* find the first channel */ + } + } + if (found) g_message("A valid video channel was found."); + /* select this channel */ + ioctl(f->fd,VIDIOCSCHAN,chan); + + /* set/get the resolution */ + err = -1; + /* + if (f->cap.type & VID_TYPE_SUBCAPTURE) { + vcap->x = vcap->y = 0; + vcap->width = MS_VIDEO_SOURCE(f)->width; + vcap->height = MS_VIDEO_SOURCE(f)->height; + err = ioctl(f->fd, VIDIOCSCAPTURE, vcap); + if (err > -1) { + f->width = MS_VIDEO_SOURCE(f)->width; + f->height = MS_VIDEO_SOURCE(f)->height; + } + } + */ + if (err < 0) { + win->x = win->y = 0; + win->width = MS_VIDEO_SOURCE(f)->width; + win->height = MS_VIDEO_SOURCE(f)->height; + win->clipcount = win->flags = 0; + win->clips = NULL; + err=ioctl(f->fd,VIDIOCSWIN,win); + if (err < 0) { + g_warning("Could not set video window properties: %s",strerror(errno)); + + err=ioctl(f->fd,VIDIOCGWIN,win); + if (err < 0) { + g_warning("Could not set video window properties: %s",strerror(errno)); + return -1; + } + f->width = win->width; + f->height = win->height; + } + else { + f->width = MS_VIDEO_SOURCE(f)->width; + f->height = MS_VIDEO_SOURCE(f)->height; + } + } + + /* get picture properties */ + err=ioctl(f->fd,VIDIOCGPICT,pict); + if (err<0){ + g_warning("Could not get picture properties: %s",strerror(errno)); + return -1; + } + g_message("Picture properties: depth=%i, palette=%i.",pict->depth, pict->palette); + f->bsize=(pict->depth/8) * f->height * f->width; + + /* try to get mmap properties */ + err=ioctl(f->fd,VIDIOCGMBUF,vmbuf); + if (err<0){ + g_warning("Could not get mmap properties: %s",strerror(errno)); + f->use_mmap=0; + }else + { + if (vmbuf->size>0){ + f->use_mmap=1; + /* do the mmap */ + f->mmapdbuf=mmap((void*)f,vmbuf->size,PROT_READ,MAP_PRIVATE,f->fd,0); + if (f->mmapdbuf==(void*)-1) { + g_warning("Could not mmap. Using read instead."); + f->use_mmap=0; + f->mmapdbuf=NULL; + }else { + /* initialize the mediastreamer buffers */ + gint i; + g_message("Using %i-frames mmap'd buffer.",vmbuf->frames); + for(i=0;i<vmbuf->frames;i++){ + f->img[i].buffer=f->mmapdbuf+vmbuf->offsets[i]; + f->img[i].size=f->bsize; + f->img[i].ref_count=1; + } + f->frame=0; + } + } else g_warning("This device cannot support mmap."); + } + + /* initialize the video map structure */ + vmap->width=win->width; + vmap->height=win->height; + vmap->format=pict->palette; + vmap->frame=0; + + MS_VIDEO_SOURCE(f)->format=V4L_PALETTE_TO_STRING(pict->palette); + return 0; +} + +#define BPP 3 +static inline +void crop( guchar *src, gint s_width, gint s_height, guchar *dest, gint d_width, gint d_height) +{ + register int i; + register int stride = d_width*BPP; + register guchar *s = src, *d = dest; + s += ((s_height - d_height)/2 * s_width * BPP) + ((s_width - d_width)/2 * BPP); + for (i = 0; i < d_height; i++, d += stride, s += s_width * BPP) + memcpy( d, s, stride); +} + +MSBuffer * v4l_grab_image_mmap(MSV4l *obj){ + struct video_mmap *vmap=&obj->vmap; + struct video_mbuf *vmbuf=&obj->vmbuf; + int err; + int syncframe; + int jitter=vmbuf->frames-1; + obj->query_frame=(obj->frame) % vmbuf->frames; + ms_trace("v4l_mmap_process: query_frame=%i", + obj->query_frame); + vmap->frame=obj->query_frame; + err=ioctl(obj->fd,VIDIOCMCAPTURE,vmap); + if (err<0) { + g_warning("v4l_mmap_process: error in VIDIOCMCAPTURE: %s.",strerror(errno)); + return NULL; + } + syncframe=(obj->frame-jitter); + obj->frame++; + if (syncframe>=0){ + syncframe=syncframe%vmbuf->frames; + err=ioctl(obj->fd,VIDIOCSYNC,&syncframe); + if (err<0) { + g_warning("v4l_mmap_process: error in VIDIOCSYNC: %s.",strerror(errno)); + return NULL; + } + }else { + return NULL; + } + /* not particularly efficient - hope for a capture source that + provides subcapture or setting window */ + + if (obj->width != MS_VIDEO_SOURCE(obj)->width || obj->height != MS_VIDEO_SOURCE(obj)->height){ + guchar tmp[obj->bsize]; + crop((guchar*) obj->img[syncframe].buffer, obj->width, obj->height, tmp, + MS_VIDEO_SOURCE(obj)->width, MS_VIDEO_SOURCE(obj)->height); + memcpy(obj->img[syncframe].buffer, tmp, MS_VIDEO_SOURCE(obj)->width * + MS_VIDEO_SOURCE(obj)->height * obj->pict.depth/8); + } + return &obj->img[syncframe]; +} + +MSBuffer *v4l_grab_image_read(MSV4l *obj){ + int err; + if (obj->allocdbuf==NULL){ + obj->allocdbuf=ms_buffer_new(obj->bsize); + obj->allocdbuf->ref_count++; + } + if (obj->width != MS_VIDEO_SOURCE(obj)->width || obj->height != MS_VIDEO_SOURCE(obj)->height) + { + guchar tmp[obj->bsize]; + err=read(obj->fd,tmp,obj->bsize); + if (err>0) + crop(tmp, obj->width, obj->height, obj->allocdbuf->buffer, MS_VIDEO_SOURCE(obj)->width, MS_VIDEO_SOURCE(obj)->height); + else { + g_warning("MSV4l: Fail to read(): %s",strerror(errno)); + return NULL; + } + } + else + { + err=read(obj->fd,obj->allocdbuf->buffer,obj->bsize); + if (err<0){ + g_warning("MSV4l: Fail to read(): %s",strerror(errno)); + return NULL; + } + } + return obj->allocdbuf; +} + + +MSBuffer * v4l_make_mire(MSV4l *obj){ + gchar *data; + int i,j,line,pos; + int patternw=obj->parent.width/6; + int patternh=obj->parent.height/6; + int red,green=0,blue=0; + if (obj->allocdbuf==NULL){ + obj->allocdbuf=ms_buffer_new(obj->parent.width*obj->parent.height*3); + obj->allocdbuf->ref_count++; + } + data=obj->allocdbuf->buffer; + for (i=0;i<obj->parent.height;++i){ + line=i*obj->parent.width*3; + if ( ((i+obj->count)/patternh) & 0x1) red=255; + else red= 0; + for (j=0;j<obj->parent.width;++j){ + int tmp; + pos=line+(j*3); + + if ( ((j+obj->count)/patternw) & 0x1) blue=255; + else blue= 0; + + data[pos]=red; + data[pos+1]=green; + data[pos+2]=blue; + } + } + obj->count++; + usleep(60000); + return obj->allocdbuf; +} + + +void *v4l_thread(MSV4l *obj){ + GMutex *mutex=MS_FILTER(obj)->lock; + g_mutex_lock(mutex); + obj->thread_run=TRUE; + g_cond_signal(obj->cond); + while(obj->thread_run){ + g_cond_wait(obj->cond,mutex); + if (obj->grab_image){ + MSBuffer *grabbed; + g_mutex_unlock(mutex); + if (obj->fd>0){ + if (obj->use_mmap){ + grabbed=v4l_grab_image_mmap(obj); + }else{ + grabbed=v4l_grab_image_read(obj); + } + }else grabbed=v4l_make_mire(obj); + g_mutex_lock(mutex); + if (grabbed){ + obj->image_grabbed=grabbed; + obj->grab_image=FALSE; + } + } + } + g_cond_signal(obj->stopcond); + obj->thread_exited=TRUE; + g_mutex_unlock(mutex); + return NULL; +} + + + + +void v4l_process(MSV4l * obj) +{ + GMutex *mutex=MS_FILTER(obj)->lock; + g_mutex_lock(mutex); + if (obj->image_grabbed!=NULL){ + MSMessage *m=ms_message_alloc(); + ms_message_set_buf(m,obj->image_grabbed); + ms_queue_put(MS_FILTER(obj)->outqueues[0],m); + obj->image_grabbed=NULL; + }else{ + obj->grab_image=TRUE; + g_cond_signal(obj->cond); + } + g_mutex_unlock(mutex); +} + +void ms_v4l_uninit(MSV4l *obj) +{ + if (obj->device!=NULL) { + g_free(obj->device); + obj->device=NULL; + } + if (obj->v4lthread!=NULL) ms_v4l_stop(obj); + if (obj->allocdbuf!=NULL) { + ms_buffer_destroy(obj->allocdbuf); + obj->allocdbuf=NULL; + } + g_cond_free(obj->cond); + g_cond_free(obj->stopcond); + ms_filter_uninit(MS_FILTER(obj)); +} + +void ms_v4l_destroy(MSV4l *obj) +{ + ms_v4l_uninit(obj); + g_free(obj); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msv4l.h Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,96 @@ + /* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + +#ifndef MSV4L_H +#define MSV4L_H + +#include <msvideosource.h> +#include <sys/types.h> +#include <linux/videodev.h> + +struct _MSV4l +{ + MSVideoSource parent; + int fd; + char *device; + struct video_capability cap; + struct video_channel channel; + struct video_window win; + struct video_picture pict; + struct video_mmap vmap; + struct video_mbuf vmbuf; + struct video_capture vcap; + gint bsize; + gint use_mmap; + gint frame; + guint query_frame; + gchar *mmapdbuf; /* the mmap'd buffer */ + MSBuffer img[VIDEO_MAX_FRAME]; /* the buffer wrappers used for mmaps */ + gint width; /* the capture image size - can be cropped to output size */ + gint height; + MSBuffer *allocdbuf; /* the buffer allocated for read() and mire */ + gint count; + MSBuffer *image_grabbed; + GCond *cond; + GCond *stopcond; + GThread *v4lthread; + gboolean grab_image; + gboolean thread_run; + gboolean thread_exited; +}; + +typedef struct _MSV4l MSV4l; + + +struct _MSV4lClass +{ + MSVideoSourceClass parent_class; + +}; + +typedef struct _MSV4lClass MSV4lClass; + + +/* PUBLIC API */ +#define MS_V4L(v) ((MSV4l*)(v)) +#define MS_V4L_CLASS(k) ((MSV4lClass*)(k)) +MSFilter * ms_v4l_new(); + +void ms_v4l_start(MSV4l *obj); +void ms_v4l_stop(MSV4l *obj); +int ms_v4l_set_device(MSV4l *f, const gchar *device); +gint ms_v4l_get_width(MSV4l *v4l); +gint ms_v4l_get_height(MSV4l *v4l); +void ms_v4l_set_size(MSV4l *v4l, gint w, gint h); + +/* PRIVATE API */ +void ms_v4l_init(MSV4l *obj); +void ms_v4l_class_init(MSV4lClass *klass); +int v4l_configure(MSV4l *f); + +void v4l_process(MSV4l *obj); + +void ms_v4l_uninit(MSV4l *obj); + +void ms_v4l_destroy(MSV4l *obj); + +extern MSFilterInfo v4l_info; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msvideosource.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,94 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + + +#include "msvideosource.h" +#include "mediastream.h" +#include "msv4l.h" +#ifdef HAVE_LIBDC1394 +#include "msdc1394.h" +#endif + +/* register all statically linked codecs */ +void ms_video_source_register_all() +{ + ms_filter_register(&v4l_info); +#ifdef HAVE_LIBDC1394 + ms_filter_register(MS_FILTER_INFO(&dc1394_info)); +#endif +} + +void ms_video_source_class_init(MSVideoSourceClass *klass) +{ + /* init base class first*/ + ms_filter_class_init(MS_FILTER_CLASS(klass)); + /* then init videosource specific things*/ + MS_FILTER_CLASS(klass)->max_qoutputs=MSVIDEOSOURCE_MAX_OUTPUTS; + ms_filter_class_set_attr(MS_FILTER_CLASS(klass),FILTER_IS_SOURCE|FILTER_HAS_QUEUES); +} + +void ms_video_source_init(MSVideoSource *obj) +{ + ms_filter_init(MS_FILTER(obj)); + MS_FILTER(obj)->outqueues=obj->outputs; + obj->width = VIDEO_SIZE_CIF_W; + obj->height = VIDEO_SIZE_CIF_H; +} + +void ms_video_source_start(MSVideoSource *f) +{ + MS_VIDEO_SOURCE_CLASS(MS_FILTER(f)->klass)->start(f); +} + +void ms_video_source_stop(MSVideoSource *f) +{ + MS_VIDEO_SOURCE_CLASS(MS_FILTER(f)->klass)->stop(f); +} + +int ms_video_source_set_device(MSVideoSource *f, const gchar *device) +{ + return MS_VIDEO_SOURCE_CLASS(MS_FILTER(f)->klass)->set_device(f,device); +} + +gchar* ms_video_source_get_device_name(MSVideoSource *f) +{ + return f->dev_name; +} + +void ms_video_source_set_size(MSVideoSource *f, gint width, gint height) +{ + if (MS_VIDEO_SOURCE_CLASS(MS_FILTER(f)->klass)->set_size) + MS_VIDEO_SOURCE_CLASS(MS_FILTER(f)->klass)->set_size(f, width, height); +} + +void ms_video_source_set_frame_rate(MSVideoSource *f, gint frame_rate, gint frame_rate_base) +{ + if (MS_VIDEO_SOURCE_CLASS(MS_FILTER(f)->klass)->set_frame_rate) + MS_VIDEO_SOURCE_CLASS(MS_FILTER(f)->klass)->set_frame_rate(f, frame_rate, frame_rate_base); + else{ + f->frame_rate=frame_rate; + f->frame_rate_base=frame_rate_base; + } +} + +gchar* ms_video_source_get_format(MSVideoSource *f) +{ + return f->format; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/msvideosource.h Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,74 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + +#ifndef MSVIDEOSOURCE_H +#define MSVIDEOSOURCE_H + + +#include "msfilter.h" + +/* this is the video input abstract class */ + +#define MSVIDEOSOURCE_MAX_OUTPUTS 1 /* max output per filter*/ + +typedef struct _MSVideoSource +{ + /* the MSVideoSource derivates from MSFilter, so the MSFilter object MUST be the first of the MSVideoSource object + in order to the object mechanism to work*/ + MSFilter filter; + MSQueue *outputs[MSVIDEOSOURCE_MAX_OUTPUTS]; + gchar *dev_name; + gint width, height; + gchar *format; + gint frame_rate; + gint frame_rate_base; +} MSVideoSource; + +typedef struct _MSVideoSourceClass +{ + /* the MSVideoSource derivates from MSFilter, so the MSFilter class MUST be the first of the MSVideoSource class + in order to the class mechanism to work*/ + MSFilterClass parent_class; + gint (*set_device)(MSVideoSource *s, const gchar *name); + void (*start)(MSVideoSource *s); + void (*stop)(MSVideoSource *s); + void (*set_size)(MSVideoSource *s, gint width, gint height); + void (*set_frame_rate)(MSVideoSource *s, gint frame_rate, gint frame_rate_base); +} MSVideoSourceClass; + +/* PUBLIC */ +void ms_video_source_register_all(); +int ms_video_source_set_device(MSVideoSource *f, const gchar *device); +gchar* ms_video_source_get_device_name(MSVideoSource *f); +void ms_video_source_start(MSVideoSource *f); +void ms_video_source_stop(MSVideoSource *f); +void ms_video_source_set_size(MSVideoSource *f, gint width, gint height); +void ms_video_source_set_frame_rate(MSVideoSource *f, gint frame_rate, gint frame_rate_base); +gchar* ms_video_source_get_format(MSVideoSource *f); + +#define MS_VIDEO_SOURCE(obj) ((MSVideoSource*)(obj)) +#define MS_VIDEO_SOURCE_CLASS(klass) ((MSVideoSourceClass*)(klass)) + + +/* FOR INTERNAL USE*/ +void ms_video_source_init(MSVideoSource *f); +void ms_video_source_class_init(MSVideoSourceClass *klass); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/mswrite.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,121 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + +#include "mswrite.h" +#include <unistd.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <string.h> +#include <errno.h> + +static MSWriteClass *ms_write_class=NULL; + +MSFilter * ms_write_new(char *name) +{ + MSWrite *r; + int fd=-1; + + r=g_new(MSWrite,1); + ms_write_init(r); + if (ms_write_class==NULL) + { + ms_write_class=g_new(MSWriteClass,1); + ms_write_class_init(ms_write_class); + } + MS_FILTER(r)->klass=MS_FILTER_CLASS(ms_write_class); + if ((name!=NULL) && (strlen(name)!=0)) + { + fd=open(name,O_WRONLY | O_CREAT | O_TRUNC,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); + if (fd<0) g_error("ms_write_new: failed to open %s.\n",name); + } + r->fd=fd; + return(MS_FILTER(r)); +} + + +/* FOR INTERNAL USE*/ +void ms_write_init(MSWrite *r) +{ + ms_filter_init(MS_FILTER(r)); + MS_FILTER(r)->infifos=r->f_inputs; + MS_FILTER(r)->inqueues=r->q_inputs; + MS_FILTER(r)->r_mingran=MSWRITE_MIN_GRAN; + memset(r->f_inputs,0,sizeof(MSFifo*)*MSWRITE_MAX_INPUTS); + memset(r->q_inputs,0,sizeof(MSQueue*)*MSWRITE_MAX_INPUTS); + r->fd=-1; +} + +void ms_write_class_init(MSWriteClass *klass) +{ + ms_filter_class_init(MS_FILTER_CLASS(klass)); + ms_filter_class_set_name(MS_FILTER_CLASS(klass),"dskwriter"); + MS_FILTER_CLASS(klass)->max_finputs=MSWRITE_MAX_INPUTS; + MS_FILTER_CLASS(klass)->max_qinputs=MSWRITE_MAX_INPUTS; + MS_FILTER_CLASS(klass)->r_maxgran=MSWRITE_DEF_GRAN; + MS_FILTER_CLASS(klass)->destroy=(MSFilterDestroyFunc)ms_write_destroy; + MS_FILTER_CLASS(klass)->process=(MSFilterProcessFunc)ms_write_process; +} + +void ms_write_process(MSWrite *r) +{ + MSFifo *f; + MSQueue *q; + MSMessage *buf=NULL; + int i,j,err1,err2; + gint gran=ms_filter_get_mingran(MS_FILTER(r)); + void *p; + + /* process output fifos*/ + for (i=0,j=0;(i<MS_FILTER(r)->klass->max_finputs)&&(j<MS_FILTER(r)->finputs);i++) + { + f=r->f_inputs[i]; + if (f!=NULL) + { + if ( (err1=ms_fifo_get_read_ptr(f,gran,&p))>0 ) + { + + err2=write(r->fd,p,gran); + if (err2<0) g_warning("ms_write_process: failed to write: %s.\n",strerror(errno)); + } + j++; + } + } + /* process output queues*/ + for (i=0,j=0;(i<MS_FILTER(r)->klass->max_qinputs)&&(j<MS_FILTER(r)->qinputs);i++) + { + q=r->q_inputs[i]; + if (q!=NULL) + { + while ( (buf=ms_queue_get(q))!=NULL ){ + write(r->fd,buf->data,buf->size); + j++; + ms_message_destroy(buf); + } + } + } +} + +void ms_write_destroy( MSWrite *obj) +{ + if (obj->fd!=0) close(obj->fd); + g_free(obj); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/mswrite.h Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,63 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + +#ifndef MSWRITE_H +#define MSWRITE_H + +#include "msfilter.h" + + +/*this is the class that implements writing reading sink filter*/ + +#define MSWRITE_MAX_INPUTS 1 /* max output per filter*/ + +#define MSWRITE_DEF_GRAN 512 /* the default granularity*/ +#define MSWRITE_MIN_GRAN 64 + +typedef struct _MSWrite +{ + /* the MSWrite derivates from MSFilter, so the MSFilter object MUST be the first of the MSWrite object + in order to the object mechanism to work*/ + MSFilter filter; + MSFifo *f_inputs[MSWRITE_MAX_INPUTS]; + MSQueue *q_inputs[MSWRITE_MAX_INPUTS]; + gint fd; /* the file descriptor of the file being written*/ +} MSWrite; + +typedef struct _MSWriteClass +{ + /* the MSWrite derivates from MSFilter, so the MSFilter class MUST be the first of the MSWrite class + in order to the class mechanism to work*/ + MSFilterClass parent_class; +} MSWriteClass; + +/* PUBLIC */ +#define MS_WRITE(filter) ((MSWrite*)(filter)) +#define MS_WRITE_CLASS(klass) ((MSWriteClass*)(klass)) +MSFilter * ms_write_new(char *name); + +/* FOR INTERNAL USE*/ +void ms_write_init(MSWrite *r); +void ms_write_class_init(MSWriteClass *klass); +void ms_write_destroy( MSWrite *obj); +void ms_write_process(MSWrite *r); + +#endif +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/osscard.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,495 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + +#include "osscard.h" + +#include "msossread.h" +#include "msosswrite.h" + +#ifdef HAVE_SYS_SOUNDCARD_H +#include <sys/soundcard.h> + +#include <errno.h> +#include <fcntl.h> +#include <sys/time.h> + +#if 0 +void * oss_thread(OssCard *obj) +{ + gint i; + gint err; + g_message("oss_thread: starting **********"); + while(1){ + for(i=0;i<OSS_CARD_BUFFERS;i++){ + g_mutex_lock(obj->lock); + if (obj->ref==0){ + g_cond_signal(obj->cond); + g_mutex_unlock(obj->lock); + g_thread_exit(NULL); + } + g_mutex_unlock(obj->lock); + obj->readindex=i; + + err=read(obj->fd,obj->readbuf[i],SND_CARD(obj)->bsize); + if (err<0) g_warning("oss_thread: read() error:%s.",strerror(errno)); + obj->writeindex=i; + write(obj->fd,obj->writebuf[i],SND_CARD(obj)->bsize); + memset(obj->writebuf[i],0,SND_CARD(obj)->bsize); + } + } +} +#endif +int oss_open(OssCard *obj, int bits,int stereo, int rate) +{ + int fd; + int p=0,cond=0; + int i=0; + int min_size=0,blocksize=512; + int err; + + //g_message("opening sound device"); + fd=open(obj->dev_name,O_RDWR|O_NONBLOCK); + if (fd<0) return -EWOULDBLOCK; + /* unset nonblocking mode */ + /* We wanted non blocking open but now put it back to normal ; thanks Xine !*/ + fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)&~O_NONBLOCK); + + /* reset is maybe not needed but takes time*/ + /*ioctl(fd, SNDCTL_DSP_RESET, 0); */ + + +#ifdef WORDS_BIGENDIAN + p=AFMT_U16_BE; +#else + p=AFMT_U16_LE; +#endif + + err=ioctl(fd,SNDCTL_DSP_SETFMT,&p); + if (err<0){ + g_warning("oss_open: can't set sample format:%s.",strerror(errno)); + } + + + p = bits; /* 16 bits */ + err=ioctl(fd, SNDCTL_DSP_SAMPLESIZE, &p); + if (err<0){ + g_warning("oss_open: can't set sample size to %i:%s.",bits,strerror(errno)); + } + + p = rate; /* rate in khz*/ + err=ioctl(fd, SNDCTL_DSP_SPEED, &p); + if (err<0){ + g_warning("oss_open: can't set sample rate to %i:%s.",rate,strerror(errno)); + } + + p = stereo; /* stereo or not */ + err=ioctl(fd, SNDCTL_DSP_STEREO, &p); + if (err<0){ + g_warning("oss_open: can't set mono/stereo mode:%s.",strerror(errno)); + } + + if (rate==16000) blocksize=4096; /* oss emulation is not very good at 16khz */ + else blocksize=blocksize*(rate/8000); + ioctl(fd, SNDCTL_DSP_GETBLKSIZE, &min_size); + + /* try to subdivide BLKSIZE to reach blocksize if necessary */ + if (min_size>blocksize) + { + cond=1; + p=min_size/blocksize; + while(cond) + { + i=ioctl(fd, SNDCTL_DSP_SUBDIVIDE, &p); + //printf("SUB_DIVIDE said error=%i,errno=%i\n",i,errno); + if ((i==0) || (p==1)) cond=0; + else p=p/2; + } + } + ioctl(fd, SNDCTL_DSP_GETBLKSIZE, &min_size); + if (min_size>blocksize) + { + g_warning("dsp block size set to %i.",min_size); + }else{ + /* no need to access the card with less latency than needed*/ + min_size=blocksize; + } + + g_message("dsp blocksize is %i.",min_size); + + /* start recording !!! Alex */ + { + int fl,res; + + fl=PCM_ENABLE_OUTPUT|PCM_ENABLE_INPUT; + res=ioctl(fd, SNDCTL_DSP_SETTRIGGER, &fl); + if (res<0) g_warning("OSS_TRIGGER: %s",strerror(errno)); + } + + obj->fd=fd; + obj->readpos=0; + obj->writepos=0; + SND_CARD(obj)->bits=bits; + SND_CARD(obj)->stereo=stereo; + SND_CARD(obj)->rate=rate; + SND_CARD(obj)->bsize=min_size; + return fd; +} + +int oss_card_probe(OssCard *obj,int bits,int stereo,int rate) +{ + + int fd; + int p=0,cond=0; + int i=0; + int min_size=0,blocksize=512; + + if (obj->fd>0) return SND_CARD(obj)->bsize; + fd=open(obj->dev_name,O_RDWR|O_NONBLOCK); + if (fd<0) { + g_warning("oss_card_probe: can't open %s: %s.",obj->dev_name,strerror(errno)); + return -1; + } + ioctl(fd, SNDCTL_DSP_RESET, 0); + + p = bits; /* 16 bits */ + ioctl(fd, SNDCTL_DSP_SAMPLESIZE, &p); + + p = stereo; /* number of channels */ + ioctl(fd, SNDCTL_DSP_CHANNELS, &p); + + p = rate; /* rate in khz*/ + ioctl(fd, SNDCTL_DSP_SPEED, &p); + + ioctl(fd, SNDCTL_DSP_GETBLKSIZE, &min_size); + + /* try to subdivide BLKSIZE to reach blocksize if necessary */ + if (min_size>blocksize) + { + cond=1; + p=min_size/blocksize; + while(cond) + { + i=ioctl(fd, SNDCTL_DSP_SUBDIVIDE, &p); + //printf("SUB_DIVIDE said error=%i,errno=%i\n",i,errno); + if ((i==0) || (p==1)) cond=0; + else p=p/2; + } + } + ioctl(fd, SNDCTL_DSP_GETBLKSIZE, &min_size); + if (min_size>blocksize) + { + g_warning("dsp block size set to %i.",min_size); + }else{ + /* no need to access the card with less latency than needed*/ + min_size=blocksize; + } + close(fd); + return min_size; +} + + +int oss_card_open(OssCard *obj,int bits,int stereo,int rate) +{ + int fd; + obj->ref++; + if (obj->fd==0){ + fd=oss_open(obj,bits,stereo,rate); + if (fd<0) { + obj->fd=0; + obj->ref--; + return -1; + } + } + + obj->readbuf=g_malloc0(SND_CARD(obj)->bsize); + obj->writebuf=g_malloc0(SND_CARD(obj)->bsize); + + SND_CARD(obj)->flags|=SND_CARD_FLAGS_OPENED; + return 0; +} + +void oss_card_close(OssCard *obj) +{ + int i; + obj->ref--; + if (obj->ref==0) { + close(obj->fd); + obj->fd=0; + SND_CARD(obj)->flags&=~SND_CARD_FLAGS_OPENED; + g_free(obj->readbuf); + obj->readbuf=NULL; + g_free(obj->writebuf); + obj->writebuf=NULL; + + } +} + +void oss_card_destroy(OssCard *obj) +{ + snd_card_uninit(SND_CARD(obj)); + g_free(obj->dev_name); + g_free(obj->mixdev_name); + if (obj->readbuf!=NULL) g_free(obj->readbuf); + if (obj->writebuf!=NULL) g_free(obj->writebuf); +} + +gboolean oss_card_can_read(OssCard *obj) +{ + struct timeval tout={0,0}; + int err; + fd_set fdset; + if (obj->readpos!=0) return TRUE; + FD_ZERO(&fdset); + FD_SET(obj->fd,&fdset); + err=select(obj->fd+1,&fdset,NULL,NULL,&tout); + if (err>0) return TRUE; + else return FALSE; +} + +int oss_card_read(OssCard *obj,char *buf,int size) +{ + int err; + gint bsize=SND_CARD(obj)->bsize; + if (size<bsize){ + gint canread=MIN(bsize-obj->readpos,size); + if (obj->readpos==0){ + err=read(obj->fd,obj->readbuf,bsize); + if (err<0) { + g_warning("oss_card_read: read() failed:%s.",strerror(errno)); + return -1; + } + } + + memcpy(buf,&obj->readbuf[obj->readpos],canread); + obj->readpos+=canread; + if (obj->readpos>=bsize) obj->readpos=0; + return canread; + }else{ + err=read(obj->fd,buf,size); + if (err<0) { + g_warning("oss_card_read: read-2() failed:%s.",strerror(errno)); + } + return err; + } + +} + +int oss_card_write(OssCard *obj,char *buf,int size) +{ + int err; + gint bsize=SND_CARD(obj)->bsize; + + if (size<bsize){ + gint canwrite; + canwrite=MIN(bsize-obj->writepos,size); + memcpy(&obj->writebuf[obj->writepos],buf,canwrite); + obj->writepos+=canwrite; + if (obj->writepos>=bsize){ + err=write(obj->fd,obj->writebuf,bsize); + obj->writepos=0; + } + return canwrite; + }else{ + return write(obj->fd,buf,bsize); + } +} + +void oss_card_set_level(OssCard *obj,gint way,gint a) +{ + int p,mix_fd; + int osscmd; + g_return_if_fail(obj->mixdev_name!=NULL); +#ifdef HAVE_SYS_SOUNDCARD_H + switch(way){ + case SND_CARD_LEVEL_GENERAL: + osscmd=SOUND_MIXER_VOLUME; + break; + case SND_CARD_LEVEL_INPUT: + osscmd=SOUND_MIXER_IGAIN; + break; + case SND_CARD_LEVEL_OUTPUT: + osscmd=SOUND_MIXER_PCM; + break; + default: + g_warning("oss_card_set_level: unsupported command."); + return; + } + p=(((int)a)<<8 | (int)a); + mix_fd = open(obj->mixdev_name, O_WRONLY); + ioctl(mix_fd,MIXER_WRITE(osscmd), &p); + close(mix_fd); +#endif +} + +gint oss_card_get_level(OssCard *obj,gint way) +{ + int p=0,mix_fd; + int osscmd; + g_return_if_fail(obj->mixdev_name!=NULL); +#ifdef HAVE_SYS_SOUNDCARD_H + switch(way){ + case SND_CARD_LEVEL_GENERAL: + osscmd=SOUND_MIXER_VOLUME; + break; + case SND_CARD_LEVEL_INPUT: + osscmd=SOUND_MIXER_IGAIN; + break; + case SND_CARD_LEVEL_OUTPUT: + osscmd=SOUND_MIXER_PCM; + break; + default: + g_warning("oss_card_get_level: unsupported command."); + return -1; + } + mix_fd = open(obj->mixdev_name, O_RDONLY); + ioctl(mix_fd,MIXER_READ(SOUND_MIXER_VOLUME), &p); + close(mix_fd); +#endif + return p>>8; +} + +void oss_card_set_source(OssCard *obj,int source) +{ + gint p=0; + gint mix_fd; + g_return_if_fail(obj->mixdev_name!=NULL); +#ifdef HAVE_SYS_SOUNDCARD_H + if (source == 'c') + p = 1 << SOUND_MIXER_CD; + if (source == 'l') + p = 1 << SOUND_MIXER_LINE; + if (source == 'm') + p = 1 << SOUND_MIXER_MIC; + + + mix_fd = open(obj->mixdev_name, O_WRONLY); + ioctl(mix_fd, SOUND_MIXER_WRITE_RECSRC, &p); + close(mix_fd); +#endif +} + +MSFilter *oss_card_create_read_filter(OssCard *card) +{ + MSFilter *f=ms_oss_read_new(); + ms_oss_read_set_device(MS_OSS_READ(f),SND_CARD(card)->index); + return f; +} + +MSFilter *oss_card_create_write_filter(OssCard *card) +{ + MSFilter *f=ms_oss_write_new(); + ms_oss_write_set_device(MS_OSS_WRITE(f),SND_CARD(card)->index); + return f; +} + + +SndCard * oss_card_new(char *devname, char *mixdev_name) +{ + OssCard * obj= g_new0(OssCard,1); + SndCard *base= SND_CARD(obj); + snd_card_init(base); + obj->dev_name=g_strdup(devname); + obj->mixdev_name=g_strdup( mixdev_name); +#ifdef HAVE_GLIB + base->card_name=g_strdup_printf("%s (Open Sound System)",devname); +#else + base->card_name=malloc(100); + snprintf(base->card_name, 100, "%s (Open Sound System)",devname); +#endif + base->_probe=(SndCardOpenFunc)oss_card_probe; + base->_open_r=(SndCardOpenFunc)oss_card_open; + base->_open_w=(SndCardOpenFunc)oss_card_open; + base->_can_read=(SndCardPollFunc)oss_card_can_read; + base->_read=(SndCardIOFunc)oss_card_read; + base->_write=(SndCardIOFunc)oss_card_write; + base->_close_r=(SndCardCloseFunc)oss_card_close; + base->_close_w=(SndCardCloseFunc)oss_card_close; + base->_set_rec_source=(SndCardMixerSetRecSourceFunc)oss_card_set_source; + base->_set_level=(SndCardMixerSetLevelFunc)oss_card_set_level; + base->_get_level=(SndCardMixerGetLevelFunc)oss_card_get_level; + base->_destroy=(SndCardDestroyFunc)oss_card_destroy; + base->_create_read_filter=(SndCardCreateFilterFunc)oss_card_create_read_filter; + base->_create_write_filter=(SndCardCreateFilterFunc)oss_card_create_write_filter; + return base; +} + +#define DSP_NAME "/dev/dsp" +#define MIXER_NAME "/dev/mixer" + +gint oss_card_manager_init(SndCardManager *manager, gint tabindex) +{ + gchar *devname; + gchar *mixername; + gint devindex=0; + gint found=0; + + /* search for /dev/dsp and /dev/mixer */ +#ifdef HAVE_GLIB + if (g_file_test(DSP_NAME,G_FILE_TEST_EXISTS)){ + tabindex++; + devindex++; + manager->cards[0]=oss_card_new(DSP_NAME,MIXER_NAME); + manager->cards[0]->index=0; + found++; + g_message("Found /dev/dsp."); + } + for (;tabindex<MAX_SND_CARDS && devindex<MAX_SND_CARDS ;devindex++){ + devname=g_strdup_printf("%s%i",DSP_NAME,devindex); + mixername=g_strdup_printf("%s%i",MIXER_NAME,devindex); + if (g_file_test(devname,G_FILE_TEST_EXISTS)){ + manager->cards[tabindex]=oss_card_new(devname,mixername); + manager->cards[tabindex]->index=tabindex; + tabindex++; + found++; + } + g_free(devname); + g_free(mixername); + } +#else + if (access(DSP_NAME,F_OK)==0){ + tabindex++; + devindex++; + manager->cards[0]=oss_card_new(DSP_NAME,MIXER_NAME); + manager->cards[0]->index=0; + found++; + g_message("Found /dev/dsp."); + } + for (;tabindex<MAX_SND_CARDS && devindex<MAX_SND_CARDS ;devindex++){ + devname=malloc(100); + snprintf(devname, 100, "%s%i",DSP_NAME,devindex); + mixername=malloc(100); + snprintf(mixername, 100, "%s%i",MIXER_NAME,devindex); + + if (access(devname,F_OK)==0){ + manager->cards[tabindex]=oss_card_new(devname,mixername); + manager->cards[tabindex]->index=tabindex; + tabindex++; + found++; + } + g_free(devname); + g_free(mixername); + } +#endif + if (tabindex==0) g_warning("No sound cards found !"); + return found; +} + + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/osscard.h Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,47 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ +/* An implementation of SndCard : the OssCard */ + +#ifndef OSS_CARD_H +#define OSS_CARD_H + +#include "sndcard.h" + +#define OSS_CARD_BUFFERS 3 +struct _OssCard +{ + SndCard parent; + gchar *dev_name; /* /dev/dsp0 for example */ + gchar *mixdev_name; /* /dev/mixer0 for example */ + gint fd; /* the file descriptor of the open soundcard, 0 if not open*/ + gint ref; + gchar *readbuf; + gint readpos; + gchar *writebuf; + gint writepos; +}; + +typedef struct _OssCard OssCard; + +SndCard * oss_card_new(char *devname, char *mixdev_name); + +typedef OssCard HpuxSndCard; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/ring_test.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,63 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + +#include "ms.h" + +#include "msringplayer.h" +#include "msosswrite.h" +#include "msossread.h" +#include "mscopy.h" +#include "mstimer.h" +#include <unistd.h> + + +#define READFILE "../share/ring.wav" +#define WRITEFILE "/tmp/mediaout" + +int main() +{ + MSFilter *play,*copy,*rec; + MSSync *timer; + int i=0; + SndCard *card; + ms_init(); + + card=snd_card_manager_get_card(snd_card_manager,1); + play=ms_ring_player_new(READFILE,2); + //play=ms_oss_read_new(0); + rec=snd_card_create_write_filter(card); + copy=ms_copy_new(); + timer=ms_timer_new(); + + ms_filter_add_link(play,copy); + ms_filter_add_link(copy,rec); + ms_sync_attach(timer,play); + + ms_start(timer); + + while(1) + { + ms_sound_write_set_level(MS_SOUND_WRITE(rec),i); + i+=10; + sleep(2); + if (i>100) i=0; + } + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/sndcard.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,204 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + + +#include "sndcard.h" +#include "msfilter.h" + +void snd_card_init(SndCard *obj) +{ + memset(obj,0,sizeof(SndCard)); +} + +void snd_card_uninit(SndCard *obj) +{ + if (obj->card_name!=NULL) g_free(obj->card_name); +} + +const gchar *snd_card_get_identifier(SndCard *obj) +{ + return obj->card_name; +} + +int snd_card_open_r(SndCard *obj, int bits, int stereo, int rate) +{ + g_return_val_if_fail(obj->_open_r!=NULL,-1); + g_message("Opening sound card [%s] in capture mode with stereo=%i,rate=%i,bits=%i",obj->card_name,stereo,rate,bits); + return obj->_open_r(obj,bits,stereo,rate); +} +int snd_card_open_w(SndCard *obj, int bits, int stereo, int rate) +{ + g_return_val_if_fail(obj->_open_w!=NULL,-1); + g_message("Opening sound card [%s] in playback mode with stereo=%i,rate=%i,bits=%i",obj->card_name,stereo,rate,bits); + return obj->_open_w(obj,bits,stereo,rate); +} + +gboolean snd_card_can_read(SndCard *obj){ + g_return_val_if_fail(obj->_can_read!=NULL,-1); + return obj->_can_read(obj); +} + +void snd_card_set_blocking_mode(SndCard *obj,gboolean yesno){ + g_return_if_fail(obj->_set_blocking_mode!=NULL); + obj->_set_blocking_mode(obj,yesno); +} + +int snd_card_read(SndCard *obj,char *buffer,int size) +{ + g_return_val_if_fail(obj->_read!=NULL,-1); + return obj->_read(obj,buffer,size); +} +int snd_card_write(SndCard *obj,char *buffer,int size) +{ + g_return_val_if_fail(obj->_write!=NULL,-1); + return obj->_write(obj,buffer,size); +} + +int snd_card_get_bsize(SndCard *obj) +{ + if (obj->flags & SND_CARD_FLAGS_OPENED){ + return obj->bsize; + } + return -1; +} + +void snd_card_close_r(SndCard *obj) +{ + g_return_if_fail(obj->_close_r!=NULL); + g_message("Closing reading channel of soundcard."); + obj->_close_r(obj); +} + +void snd_card_close_w(SndCard *obj) +{ + g_return_if_fail(obj->_close_w!=NULL); + g_message("Closing writing channel of soundcard."); + obj->_close_w(obj); +} + +gint snd_card_probe(SndCard *obj,int bits, int stereo, int rate) +{ + g_return_val_if_fail(obj->_probe!=NULL,-1); + return obj->_probe(obj,bits,stereo,rate); +} + +void snd_card_set_rec_source(SndCard *obj, int source) +{ + g_return_if_fail(obj->_set_rec_source!=NULL); + obj->_set_rec_source(obj,source); +} + +void snd_card_set_level(SndCard *obj, int way, int level) +{ + g_return_if_fail(obj->_set_level!=NULL); + obj->_set_level(obj,way,level); +} + +gint snd_card_get_level(SndCard *obj,int way) +{ + g_return_val_if_fail(obj->_get_level!=NULL,-1); + return obj->_get_level(obj,way); +} + + +MSFilter * snd_card_create_read_filter(SndCard *obj) +{ + g_return_val_if_fail(obj->_create_read_filter!=NULL,NULL); + return obj->_create_read_filter(obj); +} +MSFilter * snd_card_create_write_filter(SndCard *obj) +{ + g_return_val_if_fail(obj->_create_write_filter!=NULL,NULL); + return obj->_create_write_filter(obj); +} + + +#ifdef HAVE_SYS_AUDIO_H +gint sys_audio_manager_init(SndCardManager *manager, gint index) +{ + /* this is a quick shortcut, as multiple soundcards on HPUX does not happen + very often... */ + manager->cards[index]=hpux_snd_card_new("/dev/audio","/dev/audio"); + return 1; +} + +#endif + +#include "osscard.h" +#include "alsacard.h" +#include "jackcard.h" + +void snd_card_manager_init(SndCardManager *manager) +{ + gint index=0; + gint tmp=0; + memset(manager,0,sizeof(SndCardManager)); + #ifdef HAVE_SYS_SOUNDCARD_H + tmp=oss_card_manager_init(manager,index); + index+=tmp; + if (index>=MAX_SND_CARDS) return; + #endif + #ifdef __ALSA_ENABLED__ + tmp=alsa_card_manager_init(manager,index); + index+=tmp; + if (index>=MAX_SND_CARDS) return; + #endif + #ifdef __JACK_ENABLED__ + tmp=jack_card_manager_init(manager,index); + index+=tmp; + if (index>=MAX_SND_CARDS) return; + #endif + #ifdef HAVE_SYS_AUDIO_H + tmp=sys_audio_manager_init(manager,index); + index+=tmp; + #endif +} + + + + + +SndCard * snd_card_manager_get_card(SndCardManager *manager,int index) +{ + g_return_val_if_fail(index>=0,NULL); + g_return_val_if_fail(index<MAX_SND_CARDS,NULL); + if (index>MAX_SND_CARDS) return NULL; + return manager->cards[index]; +} + +SndCard * snd_card_manager_get_card_with_string(SndCardManager *manager,const char *cardname,int *index) +{ + int i; + for (i=0;i<MAX_SND_CARDS;i++){ + gchar *card_name; + if (manager->cards[i]==NULL) continue; + card_name=manager->cards[i]->card_name; + if (card_name==NULL) continue; + if (strcmp(card_name,cardname)==0){ + *index=i; + return manager->cards[i]; + } + } + g_warning("No card %s found.",cardname); + return NULL; +} + +SndCardManager _snd_card_manager; +SndCardManager *snd_card_manager=&_snd_card_manager;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/sndcard.h Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,143 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + + + +#ifndef SNDCARD_H +#define SNDCARD_H + +#undef PACKAGE +#undef VERSION +#include <config.h> +#undef PACKAGE +#undef VERSION + +#ifdef HAVE_GLIB +#include <glib.h> +#else +#include <uglib.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* the base class for all soundcards: SndCard */ +struct _SndCard; + +typedef int (*SndCardOpenFunc)(struct _SndCard*,int, int, int); +typedef void (*SndCardSetBlockingModeFunc)(struct _SndCard*, gboolean ); +typedef void (*SndCardCloseFunc)(struct _SndCard*); +typedef gint (*SndCardIOFunc)(struct _SndCard*,char *,int); +typedef void (*SndCardDestroyFunc)(struct _SndCard*); +typedef gboolean (*SndCardPollFunc)(struct _SndCard*); +typedef gint (*SndCardMixerGetLevelFunc)(struct _SndCard*,gint); +typedef void (*SndCardMixerSetRecSourceFunc)(struct _SndCard*,gint); +typedef void (*SndCardMixerSetLevelFunc)(struct _SndCard*,gint ,gint); +typedef struct _MSFilter * (*SndCardCreateFilterFunc)(struct _SndCard *); + +struct _SndCard +{ + gchar *card_name; /* SB16 PCI for example */ + gint index; + gint bsize; + gint rate; + gint stereo; + gint bits; + gint flags; +#define SND_CARD_FLAGS_OPENED 1 + SndCardOpenFunc _probe; + SndCardOpenFunc _open_r; + SndCardOpenFunc _open_w; + SndCardSetBlockingModeFunc _set_blocking_mode; + SndCardPollFunc _can_read; + SndCardIOFunc _read; + SndCardIOFunc _write; + SndCardCloseFunc _close_r; + SndCardCloseFunc _close_w; + SndCardMixerGetLevelFunc _get_level; + SndCardMixerSetLevelFunc _set_level; + SndCardMixerSetRecSourceFunc _set_rec_source; + SndCardCreateFilterFunc _create_read_filter; + SndCardCreateFilterFunc _create_write_filter; + SndCardDestroyFunc _destroy; +}; + + +typedef struct _SndCard SndCard; + +void snd_card_init(SndCard *obj); +void snd_card_uninit(SndCard *obj); +gint snd_card_probe(SndCard *obj, int bits, int stereo, int rate); +int snd_card_open_r(SndCard *obj, int bits, int stereo, int rate); +int snd_card_open_w(SndCard *obj, int bits, int stereo, int rate); +int snd_card_get_bsize(SndCard *obj); +gboolean snd_card_can_read(SndCard *obj); +int snd_card_read(SndCard *obj,char *buffer,int size); +int snd_card_write(SndCard *obj,char *buffer,int size); +void snd_card_set_blocking_mode(SndCard *obj,gboolean yesno); +void snd_card_close_r(SndCard *obj); +void snd_card_close_w(SndCard *obj); + +void snd_card_set_rec_source(SndCard *obj, int source); /* source='l' or 'm'*/ +void snd_card_set_level(SndCard *obj, int way, int level); +gint snd_card_get_level(SndCard *obj,int way); + +const gchar *snd_card_get_identifier(SndCard *obj); + +struct _MSFilter * snd_card_create_read_filter(SndCard *sndcard); +struct _MSFilter * snd_card_create_write_filter(SndCard *sndcard); + + +#define SND_CARD_LEVEL_GENERAL 1 +#define SND_CARD_LEVEL_INPUT 2 +#define SND_CARD_LEVEL_OUTPUT 3 + + +int snd_card_destroy(SndCard *obj); + +#define SND_CARD(obj) ((SndCard*)(obj)) + + + + +/* SndCardManager */ + +#define MAX_SND_CARDS 20 + + +struct _SndCardManager +{ + SndCard *cards[MAX_SND_CARDS]; +}; + +typedef struct _SndCardManager SndCardManager; + +void snd_card_manager_init(SndCardManager *manager); +SndCard * snd_card_manager_get_card(SndCardManager *manager,int index); +SndCard * snd_card_manager_get_card_with_string(SndCardManager *manager,const char *cardname,int *index); + +extern SndCardManager *snd_card_manager; + +#ifdef __cplusplus +} +#endif + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/test.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,91 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + +#include "ms.h" + +#include "msringplayer.h" +#include "msosswrite.h" +#include "msossread.h" +#include "mscopy.h" +#include "mstimer.h" +#include <unistd.h> +#include <signal.h> + +#define READFILE "../share/rings/orig.wav" +#define WRITEFILE "/tmp/mediaout" + +static int cond=1; + +void stop_handler(int signum) +{ + cond=0; +} + + +int main(int argc, char *argv[]) +{ + MSFilter *play,*copy,*rec; + MSSync *timer; + int i=0; + int tmp; + char *ring; + + ms_init(); + + if (argc>1){ + ring=argv[1]; + }else ring= READFILE; + + play=ms_ring_player_new(ring,2); + //play=ms_oss_read_new(0); + rec=snd_card_create_write_filter(snd_card_manager_get_card(snd_card_manager,1)); + copy=ms_copy_new(); + + ms_filter_get_property(play,MS_FILTER_PROPERTY_FREQ,&tmp); + g_message("Playing at rate %i.",tmp); + ms_filter_set_property(rec,MS_FILTER_PROPERTY_FREQ,&tmp); + ms_filter_get_property(play,MS_FILTER_PROPERTY_CHANNELS,&tmp); + g_message("Playing with %i channels",tmp); + ms_filter_set_property(rec,MS_FILTER_PROPERTY_CHANNELS,&tmp); + + timer=ms_timer_new(); + ms_sync_start(timer); + + ms_filter_add_link(play,copy); + ms_filter_add_link(copy,rec); + ms_sync_attach(timer,play); + + + while(cond) + { + sleep(1); + } + ms_sync_detach(timer,play); + ms_sync_stop(timer); + ms_sync_destroy(timer); + + ms_filter_remove_links(play,copy); + ms_filter_remove_links(copy,rec); + ms_filter_destroy(play); + ms_filter_destroy(copy); + ms_filter_destroy(rec); + + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/test_alaw.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,90 @@ + /* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + +#include "ms.h" + +#include "msosswrite.h" +#include "msossread.h" +#include "mscopy.h" +#include "mstimer.h" +#include "msAlawdec.h" +#include "msAlawenc.h" + +#include <signal.h> +#include <sys/types.h> +#include <unistd.h> +#include <stdio.h> + +static int cond=1; + +void stop_handler(int signum) +{ + cond=0; +} + +int main() +{ + MSFilter *play,*enc,*dec,*rec; + MSSync *timer; + + ms_init(); + signal(SIGINT,stop_handler); + + play=ms_oss_read_new(); + rec=ms_oss_write_new(); + + ms_sound_read_set_device(MS_SOUND_READ(play),0); + ms_sound_write_set_device(MS_SOUND_WRITE(rec),0); + + enc=ms_ALAWencoder_new(); + dec=ms_ALAWdecoder_new(); + timer=ms_timer_new(); + + ms_filter_add_link(play,enc); + ms_filter_add_link(enc,dec); + ms_filter_add_link(dec,rec); + ms_sync_attach(timer,play); + + ms_start(timer); + + ms_sound_read_start(MS_SOUND_READ(play)); + ms_sound_write_start(MS_SOUND_WRITE(rec)); + while(cond) + { + sleep(1); + } + + ms_sound_read_stop(MS_SOUND_READ(play)); + ms_sound_write_stop(MS_SOUND_WRITE(rec)); + + printf("stoping sync...\n"); + ms_stop(timer); + printf("unlinking filters...\n"); + ms_filter_remove_links(play,enc); + ms_filter_remove_links(enc,dec); + ms_filter_remove_links(dec,rec); + printf("destroying filters...\n"); + ms_filter_destroy(play); + ms_filter_destroy(enc); + ms_filter_destroy(dec); + ms_filter_destroy(rec); + ms_sync_destroy(timer); + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/test_gsm.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,85 @@ + /* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + +#include "ms.h" + +#include "msosswrite.h" +#include "msossread.h" +#include "mscopy.h" +#include "mstimer.h" +#include "msGSMdecoder.h" +#include "msGSMencoder.h" + +#include <signal.h> +#include <sys/types.h> +#include <unistd.h> + +static int cond=1; + +void stop_handler(int signum) +{ + cond=0; +} + +int main() +{ + MSFilter *play,*enc,*dec,*rec; + MSSync *timer; + + ms_init(); + signal(SIGINT,stop_handler); + + play=ms_oss_read_new(); + rec=ms_oss_write_new(); + ms_sound_read_set_device(MS_SOUND_READ(play),0); + ms_sound_write_set_device(MS_SOUND_WRITE(rec),0); + + enc=ms_GSMencoder_new(); + dec=ms_GSMdecoder_new(); + timer=ms_timer_new(); + + ms_filter_add_link(play,enc); + ms_filter_add_link(enc,dec); + ms_filter_add_link(dec,rec); + ms_sync_attach(timer,play); + + ms_start(timer); + ms_sound_read_start(MS_SOUND_READ(play)); + ms_sound_write_start(MS_SOUND_WRITE(rec)); + while(cond) + { + sleep(1); + } + ms_sound_read_stop(MS_SOUND_READ(play)); + ms_sound_write_stop(MS_SOUND_WRITE(rec)); + printf("stoping sync...\n"); + ms_stop(timer); + printf("unlinking filters...\n"); + ms_filter_remove_links(play,enc); + ms_filter_remove_links(enc,dec); + ms_filter_remove_links(dec,rec); + printf("destroying filters...\n"); + ms_filter_destroy(play); + ms_filter_destroy(enc); + ms_filter_destroy(dec); + ms_filter_destroy(rec); + ms_sync_destroy(timer); + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/test_lpc10.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,89 @@ + /* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + +#include "ms.h" + +#include "msosswrite.h" +#include "msossread.h" +#include "mscopy.h" +#include "mstimer.h" +#include "msLPC10decoder.h" +#include "msLPC10encoder.h" + +#include <signal.h> +#include <sys/types.h> +#include <unistd.h> +#include <stdio.h> + +static int cond=1; + +void stop_handler(int signum) +{ + cond=0; +} + +int main() +{ + MSFilter *play,*enc,*dec,*rec; + MSSync *timer; + + ms_init(); + signal(SIGINT,stop_handler); + + play=ms_oss_read_new(); + rec=ms_oss_write_new(); + + ms_sound_read_set_device(MS_SOUND_READ(play),0); + ms_sound_write_set_device(MS_SOUND_WRITE(rec),0); + + enc=ms_LPC10encoder_new(); + dec=ms_LPC10decoder_new(); + timer=ms_timer_new(); + + ms_filter_add_link(play,enc); + ms_filter_add_link(enc,dec); + ms_filter_add_link(dec,rec); + ms_sync_attach(timer,play); + + ms_start(timer); + ms_sound_read_start(MS_SOUND_READ(play)); + ms_sound_write_start(MS_SOUND_WRITE(rec)); + + while(cond) + { + sleep(1); + } + ms_sound_read_stop(MS_SOUND_READ(play)); + ms_sound_write_stop(MS_SOUND_WRITE(rec)); + + printf("stoping sync...\n"); + ms_stop(timer); + printf("unlinking filters...\n"); + ms_filter_remove_links(play,enc); + ms_filter_remove_links(enc,dec); + ms_filter_remove_links(dec,rec); + printf("destroying filters...\n"); + ms_filter_destroy(play); + ms_filter_destroy(enc); + ms_filter_destroy(dec); + ms_filter_destroy(rec); + ms_sync_destroy(timer); + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/test_mulaw.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,87 @@ + /* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + +#include "ms.h" + +#include "msosswrite.h" +#include "msossread.h" +#include "mscopy.h" +#include "msnosync.h" +#include "mstimer.h" +#include "msMUlawdec.h" +#include "msMUlawenc.h" + +#include <signal.h> +#include <sys/types.h> +#include <unistd.h> +#include <stdio.h> + +static int cond=1; + +void stop_handler(int signum) +{ + cond=0; +} + +int main() +{ + MSFilter *play,*enc,*dec,*rec; + MSSync *timer; + + ms_init(); + signal(SIGINT,stop_handler); + + play=ms_oss_read_new(); + rec=ms_oss_write_new(); + ms_sound_read_set_device(MS_SOUND_READ(play),0); + ms_sound_write_set_device(MS_SOUND_WRITE(rec),0); + + enc=ms_MULAWencoder_new(); + dec=ms_MULAWdecoder_new(); + timer=ms_timer_new(); + + ms_filter_add_link(play,enc); + ms_filter_add_link(enc,dec); + ms_filter_add_link(dec,rec); + ms_sync_attach(timer,play); + + ms_start(timer); + ms_sound_read_start(MS_SOUND_READ(play)); + ms_sound_write_start(MS_SOUND_WRITE(rec)); + while(cond) + { + sleep(1); + } + ms_sound_read_stop(MS_SOUND_READ(play)); + ms_sound_write_stop(MS_SOUND_WRITE(rec)); + printf("stoping sync...\n"); + ms_stop(timer); + printf("unlinking filters...\n"); + ms_filter_remove_links(play,enc); + ms_filter_remove_links(enc,dec); + ms_filter_remove_links(dec,rec); + printf("destroying filters...\n"); + ms_filter_destroy(play); + ms_filter_destroy(enc); + ms_filter_destroy(dec); + ms_filter_destroy(rec); + ms_sync_destroy(timer); + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/test_rtprecv.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,100 @@ + /* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + +#include "msrtprecv.h" +#include "ms.h" +#include "mswrite.h" +#include "msosswrite.h" +#include "msMUlawdec.h" +#include "mstimer.h" +#include "msfdispatcher.h" + +#include <signal.h> +#include <sys/types.h> +#include <unistd.h> +#include <stdio.h> + +static int cond=1; + +void stop_handler(int signum) +{ + cond=0; +} + +int main() +{ + MSFilter *play,*dec,*rec,*filerec,*dis; + MSSync *timer; + RtpSession *rtps; + + /*create the rtp session */ + ortp_init(); + ortp_set_debug_file("oRTP",NULL); + rtps=rtp_session_new(RTP_SESSION_RECVONLY); + rtp_session_set_local_addr(rtps,"0.0.0.0",8000); + rtp_session_set_scheduling_mode(rtps,0); + rtp_session_set_blocking_mode(rtps,0); + + ms_init(); + signal(SIGINT,stop_handler); + + play=ms_rtp_recv_new(); + rec=ms_oss_write_new(); + ms_sound_write_set_device(MS_SOUND_WRITE(rec),0); + dec=ms_MULAWdecoder_new(); + filerec=ms_write_new("/tmp/rtpstream"); + dis=ms_fdispatcher_new(); + timer=ms_timer_new(); + + ms_rtp_recv_set_session(MS_RTP_RECV(play),rtps); + + ms_filter_add_link(play,dec); + ms_filter_add_link(dec,dis); + ms_filter_add_link(dis,rec); + ms_filter_add_link(dis,filerec); + ms_sync_attach(timer,play); + printf("gran=%i\n",MS_SYNC(timer)->samples_per_tick); + + ms_start(timer); + ms_sound_write_start(MS_SOUND_WRITE(rec)); + while(cond) + { + sleep(1); + } + + printf("stoping sync...\n"); + ms_stop(timer); + ms_sound_write_stop(MS_SOUND_WRITE(rec)); + printf("unlinking filters...\n"); + ms_filter_remove_links(play,dec); + ms_filter_remove_links(dec,rec); + printf("destroying filters...\n"); + ms_filter_destroy(play); + ms_filter_destroy(dec); + ms_filter_destroy(rec); + ms_filter_destroy(dis); + ms_filter_destroy(filerec); + + rtp_session_destroy(rtps); + ms_sync_destroy(timer); + ortp_global_stats_display(); + + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/test_speex.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,88 @@ + /* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + +#include "ms.h" + +#include "sndcard.h" +#include "mscopy.h" +#include "mstimer.h" +#include "msspeexdec.h" +#include "msspeexenc.h" + +#include <signal.h> +#include <sys/types.h> +#include <unistd.h> + +static int cond=1; + +void stop_handler(int signum) +{ + cond=0; +} + +int main() +{ + MSFilter *play,*enc,*dec,*rec; + MSSync *timer; + SndCard *card; + int rate=16000; + + ms_init(); + signal(SIGINT,stop_handler); + /* get the first card */ + card=snd_card_manager_get_card(snd_card_manager,0); + if (card==NULL) g_error("No sound card detected."); + + play=snd_card_create_read_filter(card); + rec=snd_card_create_write_filter(card); + + enc=ms_speex_enc_new(); + dec=ms_speex_dec_new(); + + ms_filter_set_property(play,MS_FILTER_PROPERTY_FREQ,&rate); + ms_filter_set_property(rec,MS_FILTER_PROPERTY_FREQ,&rate); + ms_filter_set_property(enc,MS_FILTER_PROPERTY_FREQ,&rate); + ms_filter_set_property(dec,MS_FILTER_PROPERTY_FREQ,&rate); + timer=ms_timer_new(); + + ms_filter_add_link(play,enc); + ms_filter_add_link(enc,dec); + ms_filter_add_link(dec,rec); + ms_sync_attach(timer,play); + + ms_start(timer); + while(cond) + { + sleep(1); + } + printf("stoping sync...\n"); + ms_stop(timer); + printf("unlinking filters...\n"); + ms_filter_remove_links(play,enc); + ms_filter_remove_links(enc,dec); + ms_filter_remove_links(dec,rec); + printf("destroying filters...\n"); + ms_filter_destroy(play); + ms_filter_destroy(enc); + ms_filter_destroy(dec); + ms_filter_destroy(rec); + ms_sync_destroy(timer); + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/test_truespeech.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,91 @@ + /* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + +#include "ms.h" + +#include "msosswrite.h" +#include "msossread.h" +#include "mscopy.h" +#include "mstimer.h" +#include "mstruespeechdecoder.h" +#include "mstruespeechencoder.h" + +#include <signal.h> +#include <sys/types.h> +#include <unistd.h> +#include <stdio.h> + +static int cond=1; + +void stop_handler(int signum) +{ + cond=0; +} + + +int main() +{ + MSFilter *play,*enc,*dec,*rec; + MSSync *timer; + + ms_init(); + signal(SIGINT,stop_handler); + + play=ms_oss_read_new(); + rec=ms_oss_write_new(); + + ms_sound_read_set_device(MS_SOUND_READ(play),0); + ms_sound_write_set_device(MS_SOUND_WRITE(rec),0); + + enc=ms_truespeechencoder_new(); + dec=ms_truespeechdecoder_new(); + timer=ms_timer_new(); + + ms_filter_add_link(play,enc); + ms_filter_add_link(enc,dec); + ms_filter_add_link(dec,rec); + ms_sync_attach(timer,play); + + ms_start(timer); + + ms_sound_read_start(MS_SOUND_READ(play)); + ms_sound_write_start(MS_SOUND_WRITE(rec)); + while(cond) + { + sleep(1); + } + + ms_sound_read_stop(MS_SOUND_READ(play)); + ms_sound_write_stop(MS_SOUND_WRITE(rec)); + + printf("stoping sync...\n"); + ms_stop(timer); + printf("unlinking filters...\n"); + ms_filter_remove_links(play,enc); + ms_filter_remove_links(enc,dec); + ms_filter_remove_links(dec,rec); + printf("destroying filters...\n"); + ms_filter_destroy(play); + ms_filter_destroy(dec); + ms_filter_destroy(enc); + ms_filter_destroy(rec); + ms_sync_destroy(timer); + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/test_v4l.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,32 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + +#include "mediastream.h" + + +int main() +{ + VideoStream *v; + ms_init(); + v=video_preview_start("Video4Linux","/dev/video0"); + sleep(5); + video_preview_stop(v); + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/test_videostream.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,44 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + +#include "mediastream.h" +#include <signal.h> + +static gboolean cond=TRUE; + +static void stop_handler(int signum){ + cond=FALSE; +} + +int main() +{ + VideoStream *v; + ortp_init(); + ms_init(); + signal(SIGINT,stop_handler); + v=video_stream_start(&av_profile,6000,"127.0.0.1",6000, 34, 60, TRUE, "Video4Linux","/dev/video0"); + while(cond) { + ortp_global_stats_display(); + sleep(1); + } + video_stream_stop(v); + ortp_exit(); + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/videostream.c Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,258 @@ +/* + The mediastreamer library aims at providing modular media processing and I/O + for linphone, but also for any telephony application. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 +*/ + + +#include "mediastream.h" +#include "msvideosource.h" +#include "msavdecoder.h" +#include "msavencoder.h" +#include "msnosync.h" +#include "mssdlout.h" + +#define USE_SDL + +extern void create_duplex_rtpsession(RtpProfile *profile, int locport,char *remip,int remport, + int payload,int jitt_comp, + RtpSession **recvsend); + +#define MAX_RTP_SIZE 5000 + +/* this code is not part of the library itself, it is part of the mediastream program */ +void +video_stream_free (VideoStream * stream) +{ + RtpSession *recvs, *sends; + if (stream->rtprecv != NULL) + { + recvs = ms_rtp_recv_get_session (MS_RTP_RECV (stream->rtprecv)); + if (recvs != NULL) + { + rtp_session_destroy (recvs); + } + ms_filter_destroy (stream->rtprecv); + } + if (stream->rtpsend != NULL) + { + sends = ms_rtp_send_get_session (MS_RTP_SEND (stream->rtpsend)); + if (sends != NULL && sends!=recvs) + { + rtp_session_destroy (sends); + } + ms_filter_destroy (stream->rtpsend); + } + if (stream->source != NULL) + ms_filter_destroy (stream->source); + if (stream->output != NULL) + ms_filter_destroy (stream->output); + if (stream->decoder != NULL) + ms_filter_destroy (stream->decoder); + if (stream->encoder != NULL) + ms_filter_destroy (stream->encoder); + if (stream->timer != NULL) + ms_sync_destroy (stream->timer); + g_free (stream); +} + + +VideoStream * +video_stream_start (RtpProfile *profile, int locport, char *remip, int remport, + int payload, int jitt_comp, gboolean show_local, + const gchar *source, const gchar *device) +{ + VideoStream *stream = g_new0 (VideoStream, 1); + RtpSession *rtps, *rtpr; + PayloadType *pt; + gchar *format; + gint width = VIDEO_SIZE_CIF_W; + gint height = VIDEO_SIZE_CIF_H; + gfloat fps; + + create_duplex_rtpsession(profile,locport,remip,remport,payload,jitt_comp,&rtpr); + rtp_session_enable_adaptive_jitter_compensation(rtpr,FALSE); + rtps=rtpr; + ms_trace("sending video to %s:%i", remip4, remport); + + /* creates two rtp filters to recv send streams (remote part) */ + rtp_session_max_buf_size_set(rtpr,MAX_RTP_SIZE); + stream->rtpsend = ms_rtp_send_new (); + if (remport>0) ms_rtp_send_set_session (MS_RTP_SEND (stream->rtpsend), rtps); + + + stream->rtprecv = ms_rtp_recv_new (); + ms_rtp_recv_set_session (MS_RTP_RECV (stream->rtprecv), rtpr); + + pt=rtp_profile_get_payload(profile,payload); + if (pt==NULL){ + g_error("videostream.c: undefined payload type."); + return NULL; + } + ms_trace("videostream.c: getting codecs for %s", pt->mime_type); + + /* creates the filters */ + stream->source = ms_filter_new_with_name(source); + if (stream->source == NULL){ + g_error("videostream.c: failed to create video source %s.", source); + return NULL; + } + +#ifdef USE_SDL + stream->output=ms_sdl_out_new(); +#else + stream->output = MS_FILTER(ms_video_output_new ()); +#endif + stream->encoder=ms_encoder_new_with_string_id(pt->mime_type); + g_message("Video encoder created: %x",stream->encoder); + stream->decoder=ms_decoder_new_with_string_id(pt->mime_type); + if ((stream->encoder==NULL) || (stream->decoder==NULL)){ + /* big problem: we have not a registered codec for this payload...*/ + video_stream_free(stream); + g_error("videostream.c: No codecs available for payload %i.",payload); + return NULL; + } + + /* configure the filters */ + ms_video_source_set_device(MS_VIDEO_SOURCE(stream->source), device); + ms_video_source_set_size(MS_VIDEO_SOURCE(stream->source), width, height); + ms_video_source_set_frame_rate(MS_VIDEO_SOURCE(stream->source), 8, 1); + fps = MS_VIDEO_SOURCE(stream->source)->frame_rate / MS_VIDEO_SOURCE(stream->source)->frame_rate_base; + format = ms_video_source_get_format(MS_VIDEO_SOURCE(stream->source)); + + ms_AVencoder_set_format (MS_AVENCODER (stream->encoder), format); + ms_AVencoder_set_width(MS_AVENCODER(stream->encoder), width); + ms_AVencoder_set_height(MS_AVENCODER(stream->encoder), height); + /* bitrate is based upon 30fps? adjust by our possibly lower framerate */ + ms_AVencoder_set_bit_rate(MS_AVENCODER(stream->encoder), pt->normal_bitrate * 30 / fps ); + ms_AVdecoder_set_format (MS_AVDECODER (stream->decoder), "YUV420P"); + ms_AVdecoder_set_width(MS_AVDECODER(stream->decoder), width); + ms_AVdecoder_set_height(MS_AVDECODER(stream->decoder), height); +#ifdef USE_SDL + /* we suppose our decoder and pin1 of encoder always outputs YUV420P */ + ms_sdl_out_set_format(MS_SDL_OUT(stream->output),"YUV420P"); +#else + ms_video_output_set_size (MS_VIDEO_OUTPUT (stream->output), width, height); +#endif + + /* and then connect all */ + ms_filter_add_link (stream->source, stream->encoder); + ms_filter_add_link (stream->encoder, stream->rtpsend); + + ms_filter_add_link (stream->rtprecv, stream->decoder); + ms_filter_add_link (stream->decoder, stream->output); + if (show_local) + ms_filter_add_link(stream->encoder,stream->output); + + /* create the synchronisation source */ + stream->timer = ms_timer_new(); + ms_sync_attach (stream->timer, stream->source); + ms_sync_attach (stream->timer, stream->rtprecv); + + /* and start */ + ms_video_source_start(MS_VIDEO_SOURCE(stream->source)); + ms_start (stream->timer); + stream->show_local=show_local; + return stream; +} + + + +void +video_stream_stop (VideoStream * stream) +{ + + ms_stop (stream->timer); + ms_video_source_stop (MS_VIDEO_SOURCE(stream->source)); + ms_sync_detach (stream->timer, stream->source); + ms_sync_detach (stream->timer, stream->rtprecv); + + ms_filter_remove_links(stream->source,stream->encoder); + ms_filter_remove_links (stream->encoder, + stream->rtpsend); + + ms_filter_remove_links (stream->rtprecv, + stream->decoder); + ms_filter_remove_links (stream->decoder, + stream->output); + if (stream->show_local) { + ms_filter_remove_links (stream->encoder, + stream->output); + } + video_stream_free (stream); +} + + +void video_stream_set_rtcp_information(VideoStream *st, const char *cname){ + if (st->send_session!=NULL){ + rtp_session_set_source_description(st->send_session,cname,NULL,NULL,NULL,NULL,"linphone-" LINPHONE_VERSION, + "This is free software (GPL) !"); + } +} + + + +VideoStream * video_preview_start(const gchar *source, const gchar *device){ + VideoStream *stream = g_new0 (VideoStream, 1); + gchar *format; + gint width = VIDEO_SIZE_CIF_W; + gint height = VIDEO_SIZE_CIF_H; + + /* creates the filters */ + stream->source = ms_filter_new_with_name(source); + if (stream->source == NULL){ + g_error("videostream.c: failed to create video source %s.", source); + return NULL; + } +#ifdef USE_SDL + stream->output=ms_sdl_out_new(); +#else + stream->output = ms_video_output_new (); +#endif + /* configure the filters */ + ms_video_source_set_device(MS_VIDEO_SOURCE(stream->source), device); + ms_video_source_set_size(MS_VIDEO_SOURCE(stream->source), width, height); + ms_video_source_set_frame_rate(MS_VIDEO_SOURCE(stream->source), 8, 1); + format = ms_video_source_get_format(MS_VIDEO_SOURCE(stream->source)); + +#ifdef USE_SDL + ms_sdl_out_set_format(MS_SDL_OUT(stream->output),format); +#else + ms_video_output_set_format(MS_VIDEO_OUTPUT(stream->output),format); + ms_video_output_set_size (MS_VIDEO_OUTPUT (stream->output), width, height); + ms_video_output_set_title(MS_VIDEO_OUTPUT(stream->output),"Linphone Video"); +#endif + /* and then connect all */ + ms_filter_add_link (stream->source, stream->output); + /* create the synchronisation source */ + stream->timer = ms_timer_new(); + ms_sync_attach (stream->timer, stream->source); + + /* and start */ + ms_video_source_start(MS_VIDEO_SOURCE(stream->source)); + ms_start (stream->timer); + + return stream; +} + +void video_preview_stop(VideoStream *stream){ + ms_stop (stream->timer); + ms_video_source_stop (MS_VIDEO_SOURCE(stream->source)); + ms_sync_detach (stream->timer, stream->source); + ms_filter_remove_links(stream->source,stream->output); + video_stream_free(stream); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mediastreamer/waveheader.h Wed Nov 09 08:07:20 2005 +0000 @@ -0,0 +1,111 @@ +/* +linphone +Copyright (C) 2000 Simon MORLAT (simon.morlat@free.fr) + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* the following code was taken from a free software utility that I don't remember the name. */ +/* sorry */ + + + +#include <ms.h> +#ifndef waveheader_h +#define waveheader_h + +typedef struct uint16scheme +{ + unsigned char lo_byte; + unsigned char hi_byte; +} uint16scheme_t; + +typedef struct uint32scheme +{ + guint16 lo_int; + guint16 hi_int; +} uint32scheme_t; + + +/* all integer in wav header must be read in least endian order */ +inline guint16 _readuint16(guint16 a) +{ + guint16 res; + uint16scheme_t *tmp1=(uint16scheme_t*)&a; + + ((uint16scheme_t *)(&res))->lo_byte=tmp1->hi_byte; + ((uint16scheme_t *)(&res))->hi_byte=tmp1->lo_byte; + return res; +} + +inline guint32 _readuint32(guint32 a) +{ + guint32 res; + uint32scheme_t *tmp1=(uint32scheme_t*)&a; + + ((uint32scheme_t *)(&res))->lo_int=_readuint16(tmp1->hi_int); + ((uint32scheme_t *)(&res))->hi_int=_readuint16(tmp1->lo_int); + return res; +} + +#ifdef WORDS_BIGENDIAN +#define le_uint32(a) (_readuint32((a))) +#define le_uint16(a) (_readuint16((a))) +#define le_int16(a) ( (gint16) _readuint16((guint16)((a))) ) +#else +#define le_uint32(a) (a) +#define le_uint16(a) (a) +#define le_int16(a) (a) +#endif + +typedef struct _riff_t { + char riff[4] ; /* "RIFF" (ASCII characters) */ + guint32 len ; /* Length of package (binary, little endian) */ + char wave[4] ; /* "WAVE" (ASCII characters) */ +} riff_t; + +/* The FORMAT chunk */ + +typedef struct _format_t { + char fmt[4] ; /* "fmt_" (ASCII characters) */ + guint32 len ; /* length of FORMAT chunk (always 0x10) */ + guint16 que ; /* Always 0x01 */ + guint16 channel ; /* Channel numbers (0x01 = mono, 0x02 = stereo) */ + guint32 rate ; /* Sample rate (binary, in Hz) */ + guint32 bps ; /* Bytes Per Second */ + guint16 bpsmpl ; /* bytes per sample: 1 = 8 bit Mono, + 2 = 8 bit Stereo/16 bit Mono, + 4 = 16 bit Stereo */ + guint16 bitpspl ; /* bits per sample */ +} format_t; + +/* The DATA chunk */ + +typedef struct _data_t { + char data[4] ; /* "data" (ASCII characters) */ + int len ; /* length of data */ +} data_t; + +typedef struct _wave_header_t +{ + riff_t riff_chunk; + format_t format_chunk; + data_t data_chunk; +} wave_header_t; + +#define wave_header_get_rate(header) le_uint32((header)->format_chunk.rate) +#define wave_header_get_channel(header) le_uint16((header)->format_chunk.channel) + +#endif
--- a/src/prpl.h Wed Nov 09 07:58:36 2005 +0000 +++ b/src/prpl.h Wed Nov 09 08:07:20 2005 +0000 @@ -82,6 +82,7 @@ #include "blist.h" #include "proxy.h" #include "plugin.h" +#include "media.h" #include "roomlist.h" #include "status.h" #include "whiteboard.h" @@ -310,6 +311,7 @@ void (*send_file)(GaimConnection *, const char *who, const char *filename); GaimWhiteboardPrplOps *whiteboard_prpl_ops; + GaimMediaPrplOps *media_prpl_ops; }; #define GAIM_IS_PROTOCOL_PLUGIN(plugin) \
--- a/src/server.c Wed Nov 09 07:58:36 2005 +0000 +++ b/src/server.c Wed Nov 09 08:07:20 2005 +0000 @@ -995,3 +995,14 @@ } } } + +void serv_voice_chat(GaimConnection *gc, const char *who) +{ + GaimPluginProtocolInfo *prpl_info = NULL; + + if (gc != NULL && gc->prpl != NULL) + prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl); + + if (prpl_info && prpl_info->media_prpl_ops && prpl_info->media_prpl_ops->call) + prpl_info->media_prpl_ops->call(gc, who); +}
--- a/src/server.h Wed Nov 09 07:58:36 2005 +0000 +++ b/src/server.h Wed Nov 09 08:07:20 2005 +0000 @@ -66,6 +66,7 @@ void serv_got_chat_in(GaimConnection *g, int id, const char *who, GaimConvChatFlags chatflags, const char *message, time_t mtime); void serv_send_file(GaimConnection *gc, const char *who, const char *file); +void serv_voice_chat(GaimConnection *gc, const char *who); #ifdef __cplusplus }