mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-05-06 20:53:04 +00:00
add new entry and button to trigger buddylookup
Improve buddylookup dialog git-svn-id: svn+ssh://svn.savannah.nongnu.org/linphone/trunk@633 3f6dc0c8-ddfe-455d-9043-3cd528dc4637
This commit is contained in:
parent
c9b82c9984
commit
35519331bd
199 changed files with 152 additions and 53431 deletions
|
|
@ -40,7 +40,15 @@ void linphone_gtk_buddy_lookup_window_destroyed(GtkWidget *w){
|
|||
}
|
||||
}
|
||||
|
||||
void linphone_gtk_show_buddy_lookup_window(SipSetupContext *ctx){
|
||||
static void enable_add_buddy_button(GtkWidget *w){
|
||||
gtk_widget_set_sensitive(linphone_gtk_get_widget(w,"add_buddy"),TRUE);
|
||||
}
|
||||
|
||||
static void disable_add_buddy_button(GtkWidget *w){
|
||||
gtk_widget_set_sensitive(linphone_gtk_get_widget(w,"add_buddy"),FALSE);
|
||||
}
|
||||
|
||||
GtkWidget * linphone_gtk_show_buddy_lookup_window(SipSetupContext *ctx){
|
||||
GtkListStore *store;
|
||||
GtkCellRenderer *renderer;
|
||||
GtkTreeViewColumn *column;
|
||||
|
|
@ -71,6 +79,7 @@ void linphone_gtk_show_buddy_lookup_window(SipSetupContext *ctx){
|
|||
|
||||
select = gtk_tree_view_get_selection (GTK_TREE_VIEW (results));
|
||||
gtk_tree_selection_set_mode (select, GTK_SELECTION_SINGLE);
|
||||
g_signal_connect_swapped(G_OBJECT(select),"changed",(GCallback)enable_add_buddy_button,w);
|
||||
#if GTK_CHECK_VERSION(2,12,0)
|
||||
gtk_tree_view_set_tooltip_column(GTK_TREE_VIEW(results),LOOKUP_RESULT_ADDRESS);
|
||||
#endif
|
||||
|
|
@ -81,11 +90,14 @@ void linphone_gtk_show_buddy_lookup_window(SipSetupContext *ctx){
|
|||
gtk_progress_bar_set_text(pb,NULL);
|
||||
gtk_dialog_add_button(GTK_DIALOG(w),GTK_STOCK_CLOSE,GTK_RESPONSE_CLOSE);
|
||||
g_object_set_data(G_OBJECT(w),"last_state",GINT_TO_POINTER(-1));
|
||||
|
||||
gtk_widget_show(w);
|
||||
return w;
|
||||
}
|
||||
|
||||
static void enable_add_buddy_button(GtkWidget *w, gboolean val){
|
||||
gtk_widget_set_sensitive(linphone_gtk_get_widget(w,"add_buddy"),val);
|
||||
|
||||
void linphone_gtk_buddy_lookup_set_keyword(GtkWidget *w, const char *kw){
|
||||
gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(w,"keyword")),kw);
|
||||
}
|
||||
|
||||
static gboolean linphone_gtk_process_buddy_lookup(GtkWidget *w){
|
||||
|
|
@ -134,7 +146,6 @@ static gboolean linphone_gtk_process_buddy_lookup(GtkWidget *w){
|
|||
if (results) sip_setup_context_free_results(results);
|
||||
break;
|
||||
}
|
||||
enable_add_buddy_button(w,bls==BuddyLookupDone);
|
||||
g_object_set_data(G_OBJECT(w),"last_state",GINT_TO_POINTER(bls));
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -176,6 +187,7 @@ static void linphone_gtk_display_lookup_results(GtkWidget *w, const MSList *resu
|
|||
const MSList *elem;
|
||||
store=GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(w)));
|
||||
gtk_list_store_clear(store);
|
||||
disable_add_buddy_button(gtk_widget_get_toplevel(w));
|
||||
for(elem=results;elem!=NULL;elem=elem->next){
|
||||
BuddyInfo *bi=(BuddyInfo*)elem->data;
|
||||
gtk_list_store_append(store,&iter);
|
||||
|
|
@ -204,11 +216,16 @@ void linphone_gtk_add_buddy_from_database(GtkWidget *button){
|
|||
gtk_tree_model_get (model, &iter,LOOKUP_RESULT_SIP_URI , &uri,LOOKUP_RESULT_NAME, &name, -1);
|
||||
addr=g_strdup_printf("%s <%s>",name,uri);
|
||||
lf=linphone_friend_new_with_addr(addr);
|
||||
linphone_core_add_friend(linphone_gtk_get_core(),lf);
|
||||
linphone_gtk_show_friends();
|
||||
g_free(addr);
|
||||
g_free(uri);
|
||||
g_free(name);
|
||||
linphone_gtk_show_contact(lf);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*called when double clicking on a contact */
|
||||
void linphone_gtk_buddy_lookup_contact_activated(GtkWidget *treeview){
|
||||
linphone_gtk_add_buddy_from_database(treeview);
|
||||
gtk_widget_destroy(gtk_widget_get_toplevel(treeview));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
|
||||
<!--Generated with glade3 3.4.5 on Mon Mar 9 15:48:11 2009 -->
|
||||
<?xml version="1.0"?>
|
||||
<glade-interface>
|
||||
<!-- interface-requires gtk+ 2.16 -->
|
||||
<!-- interface-naming-policy toplevel-contextual -->
|
||||
<widget class="GtkDialog" id="buddylookup">
|
||||
<property name="border_width">5</property>
|
||||
<property name="title" translatable="yes">Search contacts in directory</property>
|
||||
<property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property>
|
||||
<property name="window_position">center-on-parent</property>
|
||||
<property name="icon">linphone2.png</property>
|
||||
<property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
|
||||
<property name="type_hint">dialog</property>
|
||||
<property name="has_separator">False</property>
|
||||
<signal name="response" handler="gtk_widget_destroy"/>
|
||||
<child internal-child="vbox">
|
||||
|
|
@ -35,21 +35,23 @@
|
|||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkScrolledWindow" id="scrolledwindow1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
|
||||
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
|
||||
<property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
|
||||
<property name="hscrollbar_policy">automatic</property>
|
||||
<property name="vscrollbar_policy">automatic</property>
|
||||
<property name="shadow_type">etched-in</property>
|
||||
<child>
|
||||
<widget class="GtkTreeView" id="search_results">
|
||||
<property name="width_request">512</property>
|
||||
<property name="height_request">140</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<signal name="row_activated" handler="linphone_gtk_buddy_lookup_contact_activated"/>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
|
|
@ -63,7 +65,6 @@
|
|||
<property name="visible">True</property>
|
||||
<property name="activity_mode">True</property>
|
||||
<property name="show_text">True</property>
|
||||
<property name="text" translatable="yes"></property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
|
|
@ -79,7 +80,6 @@
|
|||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="response_id">0</property>
|
||||
<signal name="clicked" handler="linphone_gtk_add_buddy_from_database"/>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox1">
|
||||
|
|
@ -92,6 +92,7 @@
|
|||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
|
|
@ -110,6 +111,7 @@
|
|||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="padding">5</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
|
|
@ -139,7 +141,7 @@
|
|||
<child internal-child="action_area">
|
||||
<widget class="GtkHButtonBox" id="dialog-action_area1">
|
||||
<property name="visible">True</property>
|
||||
<property name="layout_style">GTK_BUTTONBOX_END</property>
|
||||
<property name="layout_style">end</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
|
|
@ -149,7 +151,8 @@
|
|||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="pack_type">GTK_PACK_END</property>
|
||||
<property name="pack_type">end</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
|
|
|
|||
|
|
@ -226,6 +226,58 @@ static void linphone_gtk_friend_list_init(GtkWidget *friendlist)
|
|||
gtk_widget_get_toplevel(friendlist),"show_category")),0);
|
||||
}
|
||||
|
||||
void linphone_gtk_show_directory_search(void){
|
||||
LinphoneProxyConfig *cfg=NULL;
|
||||
SipSetupContext * ssc=NULL;
|
||||
GtkWidget *mw=linphone_gtk_get_main_window();
|
||||
GtkWidget *search_box=linphone_gtk_get_widget(mw,"directory_search_box");
|
||||
|
||||
linphone_core_get_default_proxy(linphone_gtk_get_core(),&cfg);
|
||||
if (cfg){
|
||||
ssc=linphone_proxy_config_get_sip_setup_context(cfg);
|
||||
if (ssc!=NULL && sip_setup_context_get_capabilities(ssc) & SIP_SETUP_CAP_BUDDY_LOOKUP){
|
||||
GtkWidget *entry=linphone_gtk_get_widget(mw,"directory_search_entry");
|
||||
gchar *tooltip;
|
||||
GdkColor grey={0,40000,40000,40000};
|
||||
gtk_widget_show(search_box);
|
||||
tooltip=g_strdup_printf(_("Search in %s directory"),linphone_proxy_config_get_domain(cfg));
|
||||
gtk_widget_modify_text(entry,GTK_STATE_NORMAL,&grey);
|
||||
gtk_entry_set_text(GTK_ENTRY(entry),tooltip);
|
||||
g_object_set_data(G_OBJECT(entry),"active",GINT_TO_POINTER(0));
|
||||
g_free(tooltip);
|
||||
return;
|
||||
}
|
||||
}
|
||||
gtk_widget_hide(search_box);
|
||||
}
|
||||
|
||||
gboolean linphone_gtk_directory_search_focus_out(GtkWidget *entry){
|
||||
if (gtk_entry_get_text_length(GTK_ENTRY(entry))==0)
|
||||
linphone_gtk_show_directory_search();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean linphone_gtk_directory_search_focus_in(GtkWidget *entry){
|
||||
if (GPOINTER_TO_INT(g_object_get_data(G_OBJECT(entry),"active"))==0){
|
||||
gtk_entry_set_text(GTK_ENTRY(entry),"");
|
||||
gtk_widget_modify_text(entry,GTK_STATE_NORMAL,NULL);
|
||||
g_object_set_data(G_OBJECT(entry),"active",GINT_TO_POINTER(1));
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void linphone_gtk_directory_search_activate(GtkWidget *entry){
|
||||
LinphoneProxyConfig *cfg;
|
||||
linphone_core_get_default_proxy(linphone_gtk_get_core(),&cfg);
|
||||
GtkWidget *w=linphone_gtk_show_buddy_lookup_window(linphone_proxy_config_get_sip_setup_context(cfg));
|
||||
linphone_gtk_buddy_lookup_set_keyword(w,gtk_entry_get_text(GTK_ENTRY(entry)));
|
||||
}
|
||||
|
||||
void linphone_gtk_directory_search_button_clicked(GtkWidget *button){
|
||||
linphone_gtk_directory_search_activate(
|
||||
linphone_gtk_get_widget(gtk_widget_get_toplevel(button),"directory_search_entry"));
|
||||
}
|
||||
|
||||
void linphone_gtk_show_friends(void){
|
||||
GtkWidget *mw=linphone_gtk_get_main_window();
|
||||
GtkWidget *friendlist=linphone_gtk_get_widget(mw,"contact_list");
|
||||
|
|
@ -237,6 +289,8 @@ void linphone_gtk_show_friends(void){
|
|||
LinphoneCore *core=linphone_gtk_get_core();
|
||||
const gchar *search=NULL;
|
||||
gboolean online_only=FALSE,lookup=FALSE;
|
||||
|
||||
linphone_gtk_show_directory_search();
|
||||
|
||||
if (gtk_tree_view_get_model(GTK_TREE_VIEW(friendlist))==NULL){
|
||||
linphone_gtk_friend_list_init(friendlist);
|
||||
|
|
|
|||
|
|
@ -69,10 +69,13 @@ void linphone_gtk_check_for_new_version(void);
|
|||
const char *linphone_gtk_get_lang(const char *config_file);
|
||||
void linphone_gtk_set_lang(const char *code);
|
||||
SipSetupContext* linphone_gtk_get_default_sip_setup_context(void);
|
||||
void linphone_gtk_show_buddy_lookup_window(SipSetupContext *ctx);
|
||||
GtkWidget * linphone_gtk_show_buddy_lookup_window(SipSetupContext *ctx);
|
||||
void linphone_gtk_buddy_lookup_set_keyword(GtkWidget *w, const char *kw);
|
||||
void * linphone_gtk_wait(LinphoneCore *lc, void *ctx, LinphoneWaitingState ws, const char *purpose, float progress);
|
||||
gchar *linphone_gtk_get_display_name(const char *sip_uri);
|
||||
|
||||
void linphone_gtk_show_directory_search(void);
|
||||
|
||||
/*functions controlling the in-call view*/
|
||||
void linphone_gtk_show_in_call_view(void);
|
||||
void linphone_gtk_show_idle_view(void);
|
||||
|
|
|
|||
|
|
@ -366,6 +366,7 @@ static void update_video_title(){
|
|||
}
|
||||
|
||||
static gboolean linphone_gtk_iterate(LinphoneCore *lc){
|
||||
static gboolean first_time=TRUE;
|
||||
unsigned long id;
|
||||
static unsigned long previd=0;
|
||||
static gboolean in_iterate=FALSE;
|
||||
|
|
@ -374,6 +375,12 @@ static gboolean linphone_gtk_iterate(LinphoneCore *lc){
|
|||
if (in_iterate) return TRUE;
|
||||
in_iterate=TRUE;
|
||||
linphone_core_iterate(lc);
|
||||
if (first_time){
|
||||
/*after the first call to iterate, SipSetupContexts should be ready, so take actions:*/
|
||||
linphone_gtk_show_directory_search();
|
||||
first_time=FALSE;
|
||||
}
|
||||
|
||||
id=linphone_core_get_native_video_window_id(lc);
|
||||
if (id!=previd || video_needs_update){
|
||||
GdkWindow *w;
|
||||
|
|
@ -578,8 +585,10 @@ void linphone_gtk_enable_self_view(GtkWidget *w){
|
|||
void linphone_gtk_used_identity_changed(GtkWidget *w){
|
||||
int active=gtk_combo_box_get_active(GTK_COMBO_BOX(w));
|
||||
char *sel=gtk_combo_box_get_active_text(GTK_COMBO_BOX(w));
|
||||
if (sel && strlen(sel)>0) //avoid a dummy "changed" at gui startup
|
||||
if (sel && strlen(sel)>0){ //avoid a dummy "changed" at gui startup
|
||||
linphone_core_set_default_proxy_index(linphone_gtk_get_core(),(active==0) ? -1 : (active-1));
|
||||
linphone_gtk_show_directory_search();
|
||||
}
|
||||
}
|
||||
|
||||
static void linphone_gtk_show_main_window(){
|
||||
|
|
|
|||
|
|
@ -440,6 +440,46 @@ Online users</property>
|
|||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="directory_search_box">
|
||||
<child>
|
||||
<widget class="GtkEntry" id="directory_search_entry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="invisible_char">●</property>
|
||||
<property name="secondary_icon_stock">gtk-find</property>
|
||||
<property name="secondary_icon_activatable">True</property>
|
||||
<property name="secondary_icon_sensitive">True</property>
|
||||
<signal name="focus_in_event" handler="linphone_gtk_directory_search_focus_in"/>
|
||||
<signal name="activate" handler="linphone_gtk_directory_search_activate"/>
|
||||
<signal name="icon_press" handler="linphone_gtk_directory_search_activate"/>
|
||||
<signal name="focus_out_event" handler="linphone_gtk_directory_search_focus_out"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkButton" id="directory_search_button">
|
||||
<property name="label" translatable="yes">gtk-find</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
<signal name="clicked" handler="linphone_gtk_directory_search_button_clicked"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
16
linphone/mediastreamer/.gitignore
vendored
16
linphone/mediastreamer/.gitignore
vendored
|
|
@ -1,16 +0,0 @@
|
|||
*.lo
|
||||
.deps
|
||||
.libs
|
||||
Makefile
|
||||
Makefile.in
|
||||
libmediastreamer.la
|
||||
libmsspeex.la
|
||||
mediastream
|
||||
mstest
|
||||
ring_test
|
||||
test_alaw
|
||||
test_gsm
|
||||
test_lpc10
|
||||
test_mulaw
|
||||
test_rtprecv
|
||||
test_speex
|
||||
|
|
@ -1,174 +0,0 @@
|
|||
EXTRA_DIST=Makefile.ms
|
||||
|
||||
|
||||
if BUILD_UGLIB
|
||||
SUPPORTLIB=$(top_builddir)/support/libuglib.la
|
||||
endif
|
||||
|
||||
|
||||
#gdk video output
|
||||
if BUILD_VIDEO
|
||||
VIDEO_TESTPROGS=test_v4l test_videostream
|
||||
#videoserver videoclient
|
||||
endif
|
||||
|
||||
if BUILD_TRUESPEECH
|
||||
TRUESPEECH_SOURCES = mstruespeechencoder.c mstruespeechencoder.h \
|
||||
mstruespeechdecoder.c mstruespeechdecoder.h
|
||||
TRUESPEECH_LIBADD = ../win32acm/libwin32acm.a
|
||||
TRUESPEECH_TEST = test_truespeech
|
||||
TRUESPEECH_INCLUDES = -I$(top_srcdir)/win32acm
|
||||
endif
|
||||
|
||||
if BUILD_MEDIASTREAMER
|
||||
|
||||
noinst_LTLIBRARIES = libmediastreamer.la
|
||||
endif
|
||||
|
||||
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 \
|
||||
msGSMencoder.c msGSMencoder.h \
|
||||
msGSMdecoder.c msGSMdecoder.h \
|
||||
msLPC10encoder.c msLPC10encoder.h \
|
||||
msLPC10decoder.c msLPC10decoder.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 \
|
||||
$(TRUESPEECH_SOURCES)\
|
||||
msspeexenc.c msspeexenc.h msspeexdec.c msspeexdec.h \
|
||||
$(VIDEO_SOURCES)
|
||||
|
||||
if BUILD_VIDEO
|
||||
libmediastreamer_la_SOURCES+=msv4l.c msv4l.h affine.c affine.h \
|
||||
msavencoder.c msavencoder.h\
|
||||
msavdecoder.c msavdecoder.h \
|
||||
videostream.c \
|
||||
msvideosource.c msvideosource.h \
|
||||
mssdlout.c mssdlout.h \
|
||||
rfc2429.h
|
||||
endif
|
||||
|
||||
libmediastreamer_la_LIBADD= $(GLIB_LIBS) \
|
||||
../gsmlib/libgsm.la \
|
||||
../lpc10-1.5/liblpc10.la \
|
||||
../oRTP/src/libortp.la \
|
||||
$(JACK_LIBS)\
|
||||
$(SAMPLERATE_LIBS)\
|
||||
$(SUPPORTLIB) \
|
||||
$(ALSA_LIBS) \
|
||||
$(TRUESPEECH_LIBADD) \
|
||||
$(SPEEX_LIBS) \
|
||||
$(VIDEO_LIBS)
|
||||
|
||||
|
||||
|
||||
if BUILD_MEDIASTREAMER
|
||||
noinst_PROGRAMS=mstest ring_test test_gsm test_lpc10 test_alaw test_mulaw \
|
||||
test_speex \
|
||||
test_rtprecv \
|
||||
$(VIDEO_TESTPROGS) $(TRUESPEECH_TEST)
|
||||
|
||||
libexec_PROGRAMS=mediastream
|
||||
endif
|
||||
|
||||
|
||||
# test program to test TrueSpeech encoder and decoder objects
|
||||
test_truespeech_SOURCES=test_truespeech.c
|
||||
test_truespeech_LDADD=libmediastreamer.la
|
||||
|
||||
mstest_SOURCES=test.c
|
||||
mstest_LDADD=libmediastreamer.la
|
||||
|
||||
#test program to test MSRingPlayer object
|
||||
ring_test_SOURCES=ring_test.c
|
||||
ring_test_LDADD=libmediastreamer.la
|
||||
|
||||
#test program to test GSM dec and enc objects
|
||||
test_gsm_SOURCES=test_gsm.c
|
||||
test_gsm_LDADD=libmediastreamer.la
|
||||
|
||||
#test program to test speex dec and enc objects
|
||||
test_speex_SOURCES=test_speex.c
|
||||
test_speex_LDADD=libmediastreamer.la
|
||||
|
||||
#test program to test LPC10-1.5 dec and enc objects
|
||||
test_lpc10_SOURCES=test_lpc10.c
|
||||
test_lpc10_LDADD=libmediastreamer.la
|
||||
|
||||
#test program to test ALAW dec and enc objects
|
||||
test_alaw_SOURCES=test_alaw.c
|
||||
test_alaw_LDADD=libmediastreamer.la
|
||||
|
||||
#test program to test MULAW dec and enc objects
|
||||
test_mulaw_SOURCES=test_mulaw.c
|
||||
test_mulaw_LDADD=libmediastreamer.la
|
||||
|
||||
|
||||
#test program to test rtprecv object
|
||||
test_rtprecv_SOURCES=test_rtprecv.c
|
||||
test_rtprecv_LDADD=libmediastreamer.la
|
||||
|
||||
#test program to test full video stream
|
||||
test_videostream_SOURCES=test_videostream.c
|
||||
test_videostream_LDADD=libmediastreamer.la
|
||||
|
||||
#test program to test video4linux input plugin
|
||||
test_v4l_SOURCES=test_v4l.c
|
||||
test_v4l_LDADD=libmediastreamer.la
|
||||
|
||||
#videoserver_SOURCES=videoserver.c
|
||||
#videoserver_LDADD=libmediastreamer.la
|
||||
|
||||
#videoclient_SOURCES=videoclient.c
|
||||
#videoclient_LDADD=libmediastreamer.la
|
||||
|
||||
|
||||
#the mediastream program that runs a processing that will be used in linphone
|
||||
mediastream_SOURCES=mediastream.c
|
||||
mediastream_LDADD=libmediastreamer.la
|
||||
|
||||
|
||||
ORTP_CFLAGS=`cat $(top_builddir)/oRTP/ortp.defs`
|
||||
|
||||
AM_CFLAGS=$(GLIB_CFLAGS) -DG_LOG_DOMAIN=\"MediaStreamer\" $(TRUESPEECH_CFLAGS) $(IPV6_CFLAGS) $(ORTP_CFLAGS) \
|
||||
$(VIDEO_CFLAGS)
|
||||
|
||||
INCLUDES= -I$(top_srcdir) \
|
||||
-I$(top_srcdir)/mediastreamer \
|
||||
-I$(top_srcdir)/oRTP/include \
|
||||
-I$(top_srcdir)/gsmlib \
|
||||
-I$(top_srcdir)/lpc10-1.5 \
|
||||
$(SPEEX_CFLAGS) \
|
||||
$(TRUESPEECH_INCLUDES)
|
||||
|
||||
linphone_includedir=$(includedir)/linphone
|
||||
|
||||
linphone_include_HEADERS=sndcard.h
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
|
||||
OBJEXT=o
|
||||
AR = ar
|
||||
RANLIB = ranlib
|
||||
DEFS= -DG_LOG_DOMAIN=\"MediaStreamer\"
|
||||
INCLUDES=-I/usr/local/include/glib-2.0 -I/usr/local/lib/glib-2.0/include/ \
|
||||
-I../gsmlib/ -I../lpc10-1.5 -I../oRTP
|
||||
COMPILE= gcc $(DEFS) $(INCLUDES)
|
||||
LIBTOOL=libtool
|
||||
LDFLAGS=-L/usr/local/lib/ -lglib-1.3 -lgthread-1.3 -lpthread
|
||||
LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
|
||||
|
||||
libmediastreamer_a_OBJECTS = msfilter.$(OBJEXT) msbuffer.$(OBJEXT) \
|
||||
msqueue.$(OBJEXT) msfifo.$(OBJEXT) ms.$(OBJEXT) mssync.$(OBJEXT) \
|
||||
msnosync.$(OBJEXT) msread.$(OBJEXT) mswrite.$(OBJEXT) mscopy.$(OBJEXT) \
|
||||
msv4lsource.$(OBJEXT) msoss.$(OBJEXT) msosswrite.$(OBJEXT) \
|
||||
msossread.$(OBJEXT) msringplayer.$(OBJEXT) msGSMencoder.$(OBJEXT) \
|
||||
msGSMdecoder.$(OBJEXT) msLPC10encoder.$(OBJEXT) \
|
||||
msLPC10decoder.$(OBJEXT)
|
||||
|
||||
all: libmediastreamer.a mstest
|
||||
|
||||
|
||||
.c.o:
|
||||
$(COMPILE) -c $<
|
||||
|
||||
libmediastreamer.a: $(libmediastreamer_a_OBJECTS)
|
||||
-rm -f libmediastreamer.a
|
||||
$(AR) cru libmediastreamer.a $(libmediastreamer_a_OBJECTS)
|
||||
$(RANLIB) libmediastreamer.a
|
||||
|
||||
|
||||
mstest: test.o libmediastreamer.a
|
||||
gcc -o mstest test.o libmediastreamer.a $(LDFLAGS) -Wl,-rpath /usr/local/lib
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
Mediastreamer is the library that handle all media operations: rtp streaming
|
||||
from file, from soundcard, with codec transcoding, and vice-versa;-).
|
||||
And also video streaming in the future.
|
||||
|
|
@ -1,144 +0,0 @@
|
|||
/*
|
||||
* 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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
/*
|
||||
* 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
|
||||
|
||||
|
|
@ -1,653 +0,0 @@
|
|||
/*
|
||||
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;
|
||||
guint exact_uvalue;
|
||||
gulong exact_ulvalue;
|
||||
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_uvalue=rate;
|
||||
dir=0;
|
||||
if ((err=snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &exact_uvalue, &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_uvalue);
|
||||
}
|
||||
/* 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_ulvalue=periodsize;
|
||||
dir=0;
|
||||
if (snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &exact_ulvalue, &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, (int)exact_ulvalue);
|
||||
}
|
||||
periodsize=exact_ulvalue;
|
||||
/* Set number of periods. Periods used to be called fragments. */
|
||||
exact_uvalue=periods;
|
||||
dir=0;
|
||||
if (snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &exact_uvalue, &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_uvalue);
|
||||
}
|
||||
/* 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;
|
||||
int 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 || obj->writepos!=0)
|
||||
{
|
||||
gint canwrite;
|
||||
gint totalwrite=0;
|
||||
|
||||
while(1){
|
||||
canwrite=MIN(bsize-obj->writepos,size);
|
||||
if (canwrite==0)
|
||||
break;
|
||||
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;
|
||||
}
|
||||
size-=canwrite;
|
||||
buf+=canwrite;
|
||||
totalwrite+=canwrite;
|
||||
}
|
||||
return totalwrite;
|
||||
|
||||
}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;
|
||||
case PLAYBACK_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;
|
||||
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 = -1;
|
||||
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 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
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
/*
|
||||
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
|
||||
|
|
@ -1,340 +0,0 @@
|
|||
/*
|
||||
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
|
||||
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_set_recv_buf_size(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;
|
||||
/* creates two rtp filters to recv send streams (remote part)*/
|
||||
|
||||
rtps=rtp_session_new(RTP_SESSION_SENDONLY);
|
||||
rtp_session_set_recv_buf_size(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_set_recv_buf_size(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_send_payload_type(rtpr,payload);
|
||||
rtp_session_set_recv_payload_type(rtpr,payload);
|
||||
rtp_session_set_jitter_compensation(rtpr,jitt_comp);
|
||||
rtp_session_signal_connect(rtpr,"timestamp_jump",(RtpCallback)on_timestamp_jump,(unsigned long)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,(unsigned long)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->send_fmtp);
|
||||
ms_filter_set_property(stream->decoder,MS_FILTER_PROPERTY_FMTP,(void*)pt->recv_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-" LINPHONE_VERSION,
|
||||
"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);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,171 +0,0 @@
|
|||
/*
|
||||
* 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));
|
||||
}
|
||||
|
|
@ -1,301 +0,0 @@
|
|||
/*
|
||||
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
|
||||
|
|
@ -1,574 +0,0 @@
|
|||
/*
|
||||
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
|
||||
|
|
@ -1,81 +0,0 @@
|
|||
/*
|
||||
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
|
||||
|
|
@ -1,144 +0,0 @@
|
|||
/*
|
||||
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 number>\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();
|
||||
rtp_profile_set_payload(&av_profile,115,&payload_type_lpc1015);
|
||||
rtp_profile_set_payload(&av_profile,110,&payload_type_speex_nb);
|
||||
rtp_profile_set_payload(&av_profile,98,&payload_type_h263_1998);
|
||||
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=NULL;
|
||||
#ifdef VIDEO_ENABLED
|
||||
VideoStream *video=NULL;
|
||||
#endif
|
||||
PayloadType *pt=rtp_profile_get_payload(&av_profile,payload);
|
||||
|
||||
if (pt==NULL) {
|
||||
printf("Error: No payload type defined for %i !\n",payload);
|
||||
exit (-1);
|
||||
}
|
||||
ms_init();
|
||||
ms_speex_codec_init();
|
||||
signal(SIGINT,stop_handler);
|
||||
|
||||
if (pt->type!=PAYLOAD_VIDEO){
|
||||
printf("Starting audio stream.\n");
|
||||
audio=audio_stream_start(&av_profile,localport,remote_ip,remoteport,payload,50);
|
||||
}else{
|
||||
#ifdef VIDEO_ENABLED
|
||||
printf("Starting video stream.\n");
|
||||
video=video_stream_start(&av_profile,
|
||||
localport,
|
||||
remote_ip,
|
||||
remoteport,
|
||||
payload,
|
||||
50,
|
||||
TRUE,
|
||||
"Video4Linux",
|
||||
"/dev/video0");
|
||||
#else
|
||||
printf("Error: video support not compiled.\n");
|
||||
#endif
|
||||
}
|
||||
while(cond)
|
||||
{
|
||||
/* sleep until we receive SIGINT */
|
||||
sleep(1);
|
||||
ortp_global_stats_display();
|
||||
}
|
||||
|
||||
printf("stoping all...\n");
|
||||
|
||||
if (audio) audio_stream_stop(audio);
|
||||
#ifdef VIDEO_ENABLED
|
||||
if (video) video_stream_stop(video);
|
||||
#endif
|
||||
}
|
||||
|
|
@ -1,133 +0,0 @@
|
|||
/*
|
||||
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);
|
||||
|
||||
VideoStream * video_stream_send_only_start(RtpProfile *profile, int locport, char *remip, int remport,
|
||||
int payload, const gchar *source, const gchar *device);
|
||||
|
||||
void video_stream_send_only_stop(VideoStream *stream);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -1,394 +0,0 @@
|
|||
/*
|
||||
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>
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#ifdef HAVE_DLOPEN
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GLIB
|
||||
#include "gmodule.h" /* g_module_open() */
|
||||
#endif
|
||||
|
||||
#define MS_PLUGINS_DIR PACKAGE_PLUGINS_DIR "/mediastreamer"
|
||||
|
||||
|
||||
#ifdef VIDEO_ENABLED
|
||||
extern void ms_video_source_register_all();
|
||||
#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);
|
||||
|
||||
/* 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
|
||||
ms_load_plugins(MS_PLUGINS_DIR);
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#define PLUGINS_EXT ".so"
|
||||
|
||||
typedef void (*init_func_t)(void);
|
||||
|
||||
void ms_load_plugins(const char *dir){
|
||||
#ifdef HAVE_DLOPEN
|
||||
DIR *ds;
|
||||
struct dirent *de;
|
||||
char *fullpath;
|
||||
ds=opendir(dir);
|
||||
if (ds==NULL){
|
||||
g_warning("Cannot open directory %s: %s",dir,strerror(errno));
|
||||
return;
|
||||
}
|
||||
while( (de=readdir(ds))!=NULL){
|
||||
if (de->d_type==DT_REG && strstr(de->d_name,PLUGINS_EXT)!=NULL){
|
||||
void *handle;
|
||||
fullpath=g_strdup_printf("%s/%s",dir,de->d_name);
|
||||
g_message("Loading plugin %s...",fullpath);
|
||||
|
||||
if ( (handle=dlopen(fullpath,RTLD_NOW))==NULL){
|
||||
g_warning("Fail to load plugin %s : %s",fullpath,dlerror());
|
||||
}else {
|
||||
char *initroutine_name=g_malloc0(strlen(de->d_name)+10);
|
||||
char *p;
|
||||
void *initroutine;
|
||||
strcpy(initroutine_name,de->d_name);
|
||||
p=strstr(initroutine_name,PLUGINS_EXT);
|
||||
strcpy(p,"_init");
|
||||
initroutine=dlsym(handle,initroutine_name);
|
||||
if (initroutine!=NULL){
|
||||
init_func_t func=(init_func_t)initroutine;
|
||||
func();
|
||||
g_message("Plugin loaded.");
|
||||
}else{
|
||||
g_warning("Could not locate init routine of plugin %s",de->d_name);
|
||||
}
|
||||
g_free(initroutine_name);
|
||||
}
|
||||
g_free(fullpath);
|
||||
}
|
||||
}
|
||||
closedir(ds);
|
||||
#else
|
||||
g_warning("no loadable plugin support: plugins cannot be loaded.");
|
||||
#endif
|
||||
}
|
||||
|
|
@ -1,81 +0,0 @@
|
|||
/*
|
||||
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();
|
||||
|
||||
void ms_load_plugins(const char *dir);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,132 +0,0 @@
|
|||
/*
|
||||
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);
|
||||
}
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
/*
|
||||
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
|
||||
|
|
@ -1,124 +0,0 @@
|
|||
/*
|
||||
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);
|
||||
}
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
/*
|
||||
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
|
||||
|
|
@ -1,116 +0,0 @@
|
|||
/*
|
||||
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)->inqueues=r->q_inputs;
|
||||
MS_FILTER(r)->outfifos=r->f_outputs;
|
||||
MS_FILTER(r)->r_mingran=33;
|
||||
memset(r->q_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_qinputs=MSGSMDECODER_MAX_INPUTS;
|
||||
MS_FILTER_CLASS(klass)->max_foutputs=MSGSMDECODER_MAX_INPUTS;
|
||||
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 *fo;
|
||||
MSQueue *qi;
|
||||
void *d;
|
||||
MSMessage *inm;
|
||||
|
||||
/* process output fifos, but there is only one for this class of filter*/
|
||||
|
||||
qi=r->q_inputs[0];
|
||||
fo=r->f_outputs[0];
|
||||
inm=ms_queue_get(qi);
|
||||
ms_fifo_get_write_ptr(fo,160*2,&d);
|
||||
if (d!=NULL)
|
||||
gsm_decode(r->gsm_handle,(guchar*)inm->data,(gsm_signal*)d);
|
||||
ms_message_destroy(inm);
|
||||
}
|
||||
|
||||
void ms_GSMdecoder_uninit(MSGSMDecoder *obj)
|
||||
{
|
||||
gsm_destroy(obj->gsm_handle);
|
||||
}
|
||||
|
||||
void ms_GSMdecoder_destroy( MSGSMDecoder *obj)
|
||||
{
|
||||
ms_GSMdecoder_uninit(obj);
|
||||
g_free(obj);
|
||||
}
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
/*
|
||||
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;
|
||||
MSQueue *q_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
|
||||
|
|
@ -1,98 +0,0 @@
|
|||
/*
|
||||
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)->outqueues=r->q_outputs;
|
||||
MS_FILTER(r)->r_mingran=2*160;
|
||||
memset(r->f_inputs,0,sizeof(MSFifo*)*MSGSMENCODER_MAX_INPUTS);
|
||||
memset(r->q_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_qoutputs=MSGSMENCODER_MAX_INPUTS;
|
||||
MS_FILTER_CLASS(klass)->r_maxgran=2*160;
|
||||
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;
|
||||
MSQueue *qo;
|
||||
int err1;
|
||||
void *s;
|
||||
|
||||
/* process output fifos, but there is only one for this class of filter*/
|
||||
|
||||
fi=r->f_inputs[0];
|
||||
qo=r->q_outputs[0];
|
||||
err1=ms_fifo_get_read_ptr(fi,160*2,&s);
|
||||
if (err1>0){
|
||||
MSMessage *m=ms_message_new(33);
|
||||
gsm_encode(r->gsm_handle,(gsm_signal*)s,(gsm_byte*)m->data);
|
||||
ms_queue_put(qo,m);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ms_GSMencoder_uninit(MSGSMEncoder *obj)
|
||||
{
|
||||
gsm_destroy(obj->gsm_handle);
|
||||
}
|
||||
|
||||
void ms_GSMencoder_destroy( MSGSMEncoder *obj)
|
||||
{
|
||||
ms_GSMencoder_uninit(obj);
|
||||
g_free(obj);
|
||||
}
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
/*
|
||||
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];
|
||||
MSQueue *q_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
|
||||
|
|
@ -1,129 +0,0 @@
|
|||
/*
|
||||
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);
|
||||
}
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
/*
|
||||
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
|
||||
|
|
@ -1,251 +0,0 @@
|
|||
/*
|
||||
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);
|
||||
}
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
/*
|
||||
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
|
||||
|
|
@ -1,130 +0,0 @@
|
|||
/*
|
||||
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);
|
||||
}
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
/*
|
||||
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
|
||||
|
|
@ -1,99 +0,0 @@
|
|||
/*
|
||||
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);
|
||||
}
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
/*
|
||||
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
|
||||
|
|
@ -1,294 +0,0 @@
|
|||
/*
|
||||
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 <stdio.h>
|
||||
|
||||
#include "msavdecoder.h"
|
||||
#include "mscodec.h"
|
||||
#include "rfc2429.h"
|
||||
|
||||
extern MSFilter *ms_mpeg_encoder_new();
|
||||
extern MSFilter *ms_mpeg4_encoder_new();
|
||||
extern MSFilter *ms_h263p_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 h263pinfo={
|
||||
{
|
||||
"H263 codec",
|
||||
0,
|
||||
MS_FILTER_VIDEO_CODEC,
|
||||
ms_h263p_encoder_new,
|
||||
"This is a H263 codec taken from the ffmpeg project."
|
||||
},
|
||||
ms_h263p_encoder_new,
|
||||
ms_h263p_decoder_new,
|
||||
0,
|
||||
0,
|
||||
0, /*bitrate */
|
||||
0, /*sample freq */
|
||||
0,
|
||||
"H263-1998",
|
||||
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*)&h263pinfo);
|
||||
//ms_filter_register((MSFilterInfo*)&MPEG4info);
|
||||
}
|
||||
|
||||
|
||||
static MSAVDecoderClass *ms_avdecoder_class=NULL;
|
||||
|
||||
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_h263p_decoder_new(){
|
||||
/* H263P decoder doesn't exist in libavcodec...*/
|
||||
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);
|
||||
ms_AVdecoder_set_width(dec,VIDEO_SIZE_CIF_W);
|
||||
ms_AVdecoder_set_height(dec,VIDEO_SIZE_CIF_H);
|
||||
dec->av_codec=codec;
|
||||
dec->av_opened=0;
|
||||
dec->skip_gob=1;
|
||||
dec->obufwrap=NULL;
|
||||
dec->buf_size=0;
|
||||
}
|
||||
|
||||
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 >= 2)
|
||||
{
|
||||
guint32 *p = (guint32*)inm->data;
|
||||
char *ph=inm->data;
|
||||
int PLEN;
|
||||
gboolean P;
|
||||
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;
|
||||
}
|
||||
P=rfc2429_get_P(ph);
|
||||
PLEN=rfc2429_get_PLEN(ph);
|
||||
/*printf("receiving new packet; P=%i; V=%i; PLEN=%i; PEBIT=%i\n",P,rfc2429_get_V(ph),PLEN,rfc2429_get_PEBIT(ph));
|
||||
*/
|
||||
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 */
|
||||
if (PLEN>0){
|
||||
/* we ignore the redundant picture header and
|
||||
directly go to the bitstream */
|
||||
inm->data+=PLEN;
|
||||
inm->size-=PLEN;
|
||||
}
|
||||
if (P){
|
||||
inm->data[0]=inm->data[1]=0;
|
||||
}else{
|
||||
/* no PSC omitted */
|
||||
inm->data+=2;
|
||||
inm->size-=2;
|
||||
}
|
||||
|
||||
/* accumulate the video packet until we have the rtp markbit*/
|
||||
memcpy(r->buf_compressed + r->buf_size, inm->data, inm->size);
|
||||
r->buf_size += inm->size;
|
||||
|
||||
if (inm->markbit)
|
||||
{
|
||||
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 );
|
||||
if (len<0) {
|
||||
ms_warning("ms_AVdecoder_process: error %i.",len);
|
||||
break;
|
||||
}
|
||||
if (got_picture) {
|
||||
/*g_message("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,r->width,r->height));
|
||||
r->obufwrap->ref_count++;
|
||||
}
|
||||
ms_message_set_buf(outm,r->obufwrap);
|
||||
avpicture_fill(&transformed,(unsigned char *)outm->data,r->output_pix_fmt,r->width,r->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;
|
||||
}
|
||||
r->buf_size=0;
|
||||
}
|
||||
}
|
||||
ms_message_destroy(inm);
|
||||
}
|
||||
|
||||
|
||||
void ms_AVdecoder_set_width(MSAVDecoder *av,gint w)
|
||||
{
|
||||
/*av->av_context.width=av->width=w;*/
|
||||
av->width=w;
|
||||
}
|
||||
|
||||
void ms_AVdecoder_set_height(MSAVDecoder *av,gint h)
|
||||
{
|
||||
/*av->av_context.height=av->height=h;*/
|
||||
av->height=h;
|
||||
}
|
||||
|
|
@ -1,87 +0,0 @@
|
|||
/*
|
||||
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_h263p_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
|
||||
|
|
@ -1,258 +0,0 @@
|
|||
/*
|
||||
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"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <ws2tcpip.h>
|
||||
#else
|
||||
#include <netinet/in.h> /* ntohl(3) */
|
||||
#endif
|
||||
|
||||
extern MSCodecInfo MPEG4info;
|
||||
extern MSCodecInfo MPEGinfo;
|
||||
extern MSCodecInfo h263pinfo;
|
||||
|
||||
static MSAVEncoderClass *ms_avencoder_class=NULL;
|
||||
static void ms_AVencoder_rtp_callback (AVCodecContext *ctx,void *data, int size, int packet_number);
|
||||
|
||||
MSFilter *ms_h263p_encoder_new()
|
||||
{
|
||||
/* temporily prefer CODEC_ID_H263 to CODEC_ID_H263P since
|
||||
ffmpeg does not comply to H233P at profile=0.
|
||||
*/
|
||||
return ms_AVencoder_new_with_codec(CODEC_ID_H263P,&h263pinfo);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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 = 50000;
|
||||
/* resolution must be a multiple of two */
|
||||
c->width = VIDEO_SIZE_CIF_W;
|
||||
c->height = VIDEO_SIZE_CIF_H;
|
||||
ms_AVencoder_set_frame_rate(enc,15,1);
|
||||
c->gop_size = 10; /* emit one intra frame every x frames */
|
||||
c->rtp_mode = 1;
|
||||
c->rtp_payload_size = 1000;
|
||||
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");
|
||||
enc->outm=NULL;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
if (enc->outm!=NULL) ms_message_destroy(enc->outm);
|
||||
|
||||
}
|
||||
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.time_base.num = frame_rate;
|
||||
obj->av_context.time_base.den = 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;
|
||||
MSMessage *prev_outm=r->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) ie H263-1998 */
|
||||
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);
|
||||
r->outm=outm;
|
||||
|
||||
/*g_message("output video packet of size %i",size);*/
|
||||
if (prev_outm) {
|
||||
if (gob_num==0) prev_outm->markbit=TRUE;
|
||||
ms_queue_put(outq, prev_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");
|
||||
/* set the mark bit on the last packet, which contains the end of the frame */
|
||||
/*
|
||||
MSMessage *last=ms_queue_peek_last(r->q_outputs[0]);
|
||||
if (last!=NULL) last->markbit=TRUE;
|
||||
else g_warning("No last packet ?");
|
||||
*/
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
|
@ -1,92 +0,0 @@
|
|||
/*
|
||||
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;
|
||||
MSMessage *outm;
|
||||
};
|
||||
|
||||
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_h263p_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
|
||||
|
|
@ -1,91 +0,0 @@
|
|||
/*
|
||||
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->freefn=NULL;
|
||||
buf->freearg=NULL;
|
||||
return(buf);
|
||||
}
|
||||
|
||||
MSBuffer *ms_buffer_new_with_buf(char *extbuf, int size,void (*freefn)(void *), void *freearg)
|
||||
{
|
||||
MSBuffer *buf;
|
||||
buf=(MSBuffer*)g_malloc(sizeof(MSBuffer));
|
||||
buf->ref_count=0;
|
||||
buf->size=size;
|
||||
buf->buffer=extbuf;
|
||||
buf->freefn=freefn;
|
||||
buf->freearg=freearg;
|
||||
return(buf);
|
||||
}
|
||||
|
||||
|
||||
void ms_buffer_destroy(MSBuffer *buf)
|
||||
{
|
||||
if (buf->freefn!=NULL) buf->freefn(buf->freearg);
|
||||
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;
|
||||
}
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
/*
|
||||
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
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GLIB
|
||||
#include <glib.h>
|
||||
#else
|
||||
#include <uglib.h>
|
||||
#endif
|
||||
|
||||
|
||||
#define MS_BUFFER_LARGE 4092
|
||||
|
||||
|
||||
typedef struct _MSBuffer
|
||||
{
|
||||
gchar *buffer;
|
||||
guint32 size;
|
||||
gint ref_count;
|
||||
void (*freefn)(void *);
|
||||
void *freearg;
|
||||
}MSBuffer;
|
||||
|
||||
MSBuffer * ms_buffer_new(guint32 size);
|
||||
MSBuffer *ms_buffer_new_with_buf(char *extbuf, int size,void (*freefn)(void *), void *freearg);
|
||||
void ms_buffer_destroy(MSBuffer *buf);
|
||||
|
||||
struct _MSMessage
|
||||
{
|
||||
MSBuffer *buffer; /* points to a MSBuffer */
|
||||
char *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 */
|
||||
gboolean markbit;
|
||||
};
|
||||
|
||||
typedef struct _MSMessage MSMessage;
|
||||
|
||||
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
|
||||
|
|
@ -1,259 +0,0 @@
|
|||
/*
|
||||
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"
|
||||
|
||||
#ifndef _WIN32
|
||||
# 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()
|
||||
{
|
||||
#ifndef _WIN32
|
||||
ms_filter_register(MS_FILTER_INFO(&GSMinfo));
|
||||
ms_filter_register(MS_FILTER_INFO(&LPC10info));
|
||||
#endif
|
||||
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);
|
||||
}
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
/*
|
||||
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
|
||||
|
|
@ -1,96 +0,0 @@
|
|||
/*
|
||||
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);
|
||||
}
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
/*
|
||||
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
|
||||
|
|
@ -1,94 +0,0 @@
|
|||
/*
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
/*
|
||||
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
|
||||
|
|
@ -1,167 +0,0 @@
|
|||
/*
|
||||
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;
|
||||
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 -1;
|
||||
}
|
||||
|
||||
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=fifo->prev_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 -1;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
|
@ -1,73 +0,0 @@
|
|||
/*
|
||||
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);
|
||||
|
|
@ -1,537 +0,0 @@
|
|||
/*
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,202 +0,0 @@
|
|||
/*
|
||||
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
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GLIB
|
||||
#include <glib.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
|
||||
|
|
@ -1,82 +0,0 @@
|
|||
/*
|
||||
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));
|
||||
}
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
/*
|
||||
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();
|
||||
|
|
@ -1,150 +0,0 @@
|
|||
/*
|
||||
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;
|
||||
default:
|
||||
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;
|
||||
}
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
/*
|
||||
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
|
||||
|
|
@ -1,249 +0,0 @@
|
|||
/*
|
||||
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;
|
||||
default:
|
||||
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;
|
||||
}
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
/*
|
||||
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
|
||||
|
|
@ -1,91 +0,0 @@
|
|||
/*
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
/*
|
||||
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
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
/*
|
||||
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++;
|
||||
}
|
||||
|
||||
MSMessage *ms_queue_peek_last(MSQueue *q){
|
||||
return q->last;
|
||||
}
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
/*
|
||||
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);
|
||||
|
||||
MSMessage *ms_queue_peek_last(MSQueue *q);
|
||||
|
||||
#define ms_queue_can_get(q) ( (q)->size!=0 )
|
||||
|
||||
#define ms_queue_destroy(q) g_free(q)
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -1,186 +0,0 @@
|
|||
/*
|
||||
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;
|
||||
|
||||
gint ms_read_open(MSRead *r, gchar *name);
|
||||
|
||||
MSFilter * ms_read_new(char *name)
|
||||
{
|
||||
MSRead *r;
|
||||
|
||||
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;
|
||||
default:
|
||||
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;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void ms_read_setup(MSRead *r, MSSync *sync)
|
||||
{
|
||||
r->sync=sync;
|
||||
r->gran=(r->rate*sync->interval/1000)*2;
|
||||
}
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
/*
|
||||
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
|
||||
|
|
@ -1,255 +0,0 @@
|
|||
/*
|
||||
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 <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.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 ms_ring_player_set_property(MSRingPlayer *f,MSFilterProperty prop, void *value);
|
||||
|
||||
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 */
|
||||
size_t ret = read(fd,&header,sizeof(wave_header_t));
|
||||
assert( ret == 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;
|
||||
default:
|
||||
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;
|
||||
default:
|
||||
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;
|
||||
}
|
||||
|
|
@ -1,81 +0,0 @@
|
|||
/*
|
||||
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
|
||||
|
|
@ -1,182 +0,0 @@
|
|||
/*
|
||||
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_new_with_buf(mp->b_datap->db_base,mp->b_datap->db_lim-mp->b_datap->db_base,
|
||||
freemsg,mp);
|
||||
ms_message_set_buf(msg,msbuf);
|
||||
msg->size=mp->b_wptr-mp->b_rptr;
|
||||
msg->data=mp->b_rptr;
|
||||
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;
|
||||
r->ignore=FALSE;
|
||||
r->payload_expected=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->send_pt);
|
||||
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;
|
||||
if (!r->ignore){
|
||||
gboolean markbit=((rtp_header_t*)mp->b_rptr)->markbit;
|
||||
mdata=mp->b_cont;
|
||||
freeb(mp);
|
||||
msg=msgb_2_ms_message(mdata);
|
||||
msg->markbit=markbit;
|
||||
ms_queue_put(qo,msg);
|
||||
|
||||
}else{
|
||||
freemsg(mp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ms_rtp_recv_destroy( MSRtpRecv *obj)
|
||||
{
|
||||
g_free(obj);
|
||||
}
|
||||
|
||||
static void __payload_type_changed(RtpSession *session,MSRtpRecv *obj){
|
||||
int pt_num=rtp_session_get_recv_payload_type(session);
|
||||
PayloadType *pt=rtp_profile_get_payload(rtp_session_get_profile(session),pt_num);
|
||||
if (pt==NULL){
|
||||
/* sip phone should ignore payload types they don't understand */
|
||||
g_warning("Ignoring payload type %i",pt_num);
|
||||
obj->ignore=TRUE;
|
||||
}else{
|
||||
if (obj->ignore) g_warning("payload type is coming back to something known");
|
||||
obj->ignore=FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
RtpSession * ms_rtp_recv_set_session(MSRtpRecv *obj,RtpSession *session)
|
||||
{
|
||||
RtpSession *old=obj->rtpsession;
|
||||
obj->rtpsession=session;
|
||||
rtp_session_signal_connect(session,"payload_type_changed",(RtpCallback)__payload_type_changed,(unsigned long)obj);
|
||||
obj->prev_ts=0;
|
||||
return old;
|
||||
}
|
||||
|
||||
|
||||
void ms_rtp_recv_setup(MSRtpRecv *r,MSSync *sync)
|
||||
{
|
||||
r->sync=sync;
|
||||
r->stream_started=0;
|
||||
}
|
||||
|
|
@ -1,82 +0,0 @@
|
|||
/*
|
||||
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 320 /* 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;
|
||||
gint payload_expected;
|
||||
gboolean ignore;
|
||||
};
|
||||
|
||||
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
|
||||
|
|
@ -1,213 +0,0 @@
|
|||
/*
|
||||
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->send_pt);
|
||||
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);*/
|
||||
mblk_t *packet=rtp_session_create_packet_with_data(r->rtpsession,msg->data,msg->size,NULL);
|
||||
rtp_set_markbit(packet,msg->markbit);
|
||||
rtp_session_sendm_with_ts(r->rtpsession,packet,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;
|
||||
}
|
||||
|
|
@ -1,85 +0,0 @@
|
|||
/*
|
||||
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 160/* 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
|
||||
|
|
@ -1,303 +0,0 @@
|
|||
/***************************************************************************
|
||||
* 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);
|
||||
}
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
/***************************************************************************
|
||||
* 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
|
||||
|
|
@ -1,181 +0,0 @@
|
|||
/*
|
||||
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 "mssmpeg.h"
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
|
||||
static MSSmpegClass *ms_smpeg_class=NULL;
|
||||
|
||||
|
||||
int seek_mpeg_data(struct SDL_RWops *context, int offset, int whence)
|
||||
{
|
||||
MSSmpeg *obj=context->hidden.unknown.data1;
|
||||
g_message("Entering seek function offset=%i whence=%i",offset,whence);
|
||||
switch (whence)
|
||||
{
|
||||
case SEEK_SET:
|
||||
obj->pos=offset;
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
return obj->pos;
|
||||
break;
|
||||
case SEEK_END:
|
||||
return obj->end_pos;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int read_mpeg_data(struct SDL_RWops *context, void *ptr, int size, int maxnum)
|
||||
{
|
||||
MSSmpeg *obj=context->hidden.unknown.data1;
|
||||
gint bytes;
|
||||
g_message("Entering read function: size=%i maxnum=%i",size,maxnum);
|
||||
if (obj->pos>=obj->end_pos)
|
||||
{
|
||||
g_message("End of file");
|
||||
return 0;
|
||||
}
|
||||
if (obj->current==NULL)
|
||||
{
|
||||
g_message("Nothing to read.");
|
||||
return 0;
|
||||
}
|
||||
bytes=MIN(maxnum,obj->current->size);
|
||||
memcpy(ptr,obj->current->data,bytes);
|
||||
obj->pos+=bytes;
|
||||
//obj->current;
|
||||
return bytes;
|
||||
}
|
||||
|
||||
void ms_smpeg_init(MSSmpeg *obj)
|
||||
{
|
||||
gint error;
|
||||
ms_filter_init(MS_FILTER(obj));
|
||||
MS_FILTER(obj)->inqueues=obj->input;
|
||||
obj->surface = SDL_SetVideoMode ( 400, 400,0 , SDL_HWSURFACE );
|
||||
if (obj->surface==NULL)
|
||||
{
|
||||
g_error("Could not create a SDL surface");
|
||||
}
|
||||
/*
|
||||
error=pipe(obj->fd);
|
||||
if (error<0)
|
||||
{
|
||||
g_error("Could not create pipe !");
|
||||
}
|
||||
fcntl(obj->fd[1],F_SETFL,O_NONBLOCK);
|
||||
*/
|
||||
obj->rwops=SDL_AllocRW();
|
||||
obj->rwops->read=read_mpeg_data;
|
||||
obj->rwops->seek=seek_mpeg_data;
|
||||
obj->rwops->hidden.unknown.data1=(void*)obj;
|
||||
obj->pos=0;
|
||||
obj->end_pos=0;
|
||||
}
|
||||
|
||||
void ms_smpeg_class_init(MSSmpegClass *klass)
|
||||
{
|
||||
int error;
|
||||
ms_filter_class_init(MS_FILTER_CLASS(klass));
|
||||
MS_FILTER_CLASS(klass)->max_qinputs=1;
|
||||
MS_FILTER_CLASS(klass)->destroy=(MSFilterDestroyFunc)ms_smpeg_destroy;
|
||||
MS_FILTER_CLASS(klass)->process=(MSFilterProcessFunc)ms_smpeg_process;
|
||||
ms_filter_class_set_name(MS_FILTER_CLASS(klass),"MSSmpeg");
|
||||
error=SDL_Init(SDL_INIT_VIDEO);
|
||||
if (error<0){
|
||||
g_error("Could not initialize SDL !");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ms_smpeg_uninit(MSSmpeg *obj)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
MSFilter * ms_smpeg_new()
|
||||
{
|
||||
MSSmpeg *obj=g_malloc(sizeof(MSSmpeg));
|
||||
|
||||
if (ms_smpeg_class==NULL)
|
||||
{
|
||||
ms_smpeg_class=g_malloc(sizeof(MSSmpegClass));
|
||||
ms_smpeg_class_init(ms_smpeg_class);
|
||||
}
|
||||
MS_FILTER(obj)->klass=MS_FILTER_CLASS(ms_smpeg_class);
|
||||
ms_smpeg_init(obj);
|
||||
return MS_FILTER(obj);
|
||||
}
|
||||
|
||||
void ms_smpeg_start(MSSmpeg *obj)
|
||||
{
|
||||
//SMPEG_play(obj->handle);
|
||||
obj->first_time=1;
|
||||
obj->run_cond=1;
|
||||
}
|
||||
|
||||
void ms_smpeg_stop(MSSmpeg *obj)
|
||||
{
|
||||
SMPEG_stop(obj->handle);
|
||||
obj->run_cond=0;
|
||||
}
|
||||
|
||||
void ms_smpeg_process(MSSmpeg *obj)
|
||||
{
|
||||
MSQueue *q=obj->input[0];
|
||||
MSMessage *m;
|
||||
SMPEG_Info info;
|
||||
|
||||
while((m=ms_queue_get(q))!=NULL)
|
||||
{
|
||||
g_message("Getting new buffer");
|
||||
if (obj->run_cond)
|
||||
{
|
||||
obj->current=m;
|
||||
obj->end_pos+=m->size;
|
||||
if (obj->first_time)
|
||||
{
|
||||
obj->handle=SMPEG_new_rwops(obj->rwops,NULL,0);
|
||||
if (obj->handle==NULL){
|
||||
g_error("Could not create smpeg object.");
|
||||
}
|
||||
SMPEG_setdisplay(obj->handle,obj->surface,NULL,NULL);
|
||||
obj->first_time=0;
|
||||
//SMPEG_play(obj->handle);
|
||||
}
|
||||
SMPEG_getinfo(obj->handle, &info );
|
||||
g_message("Current frame is %i",info.current_frame);
|
||||
SMPEG_renderFrame(obj->handle, info.current_frame+1);
|
||||
}
|
||||
ms_message_destroy(m);
|
||||
obj->current=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void ms_smpeg_destroy(MSSmpeg *obj)
|
||||
{
|
||||
ms_smpeg_uninit(obj);
|
||||
g_free(obj);
|
||||
}
|
||||
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
/*
|
||||
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 MSSMPEG_H
|
||||
#define MSSMPEG_H
|
||||
|
||||
|
||||
#include "ms.h"
|
||||
#include "msfilter.h"
|
||||
|
||||
#include <smpeg/smpeg.h>
|
||||
#include <SDL/SDL.h>
|
||||
|
||||
struct _MSSmpeg
|
||||
{
|
||||
MSFilter parent;
|
||||
MSQueue *input[1];
|
||||
SMPEG *handle;
|
||||
SDL_Surface *surface;
|
||||
SDL_RWops *rwops;
|
||||
int run_cond;
|
||||
int first_time;
|
||||
MSMessage *current;
|
||||
int pos;
|
||||
int end_pos;
|
||||
};
|
||||
|
||||
|
||||
typedef struct _MSSmpeg MSSmpeg;
|
||||
|
||||
struct _MSSmpegClass
|
||||
{
|
||||
MSFilterClass parent_class;
|
||||
};
|
||||
|
||||
typedef struct _MSSmpegClass MSSmpegClass;
|
||||
|
||||
|
||||
#define MS_SMPEG(obj) ((MSSmpeg*)(obj))
|
||||
#define MS_SMPEG_CLASS(klass) ((MSSmpegClass*)(klass))
|
||||
|
||||
void ms_smpeg_init(MSSmpeg *obj);
|
||||
void ms_smpeg_class_init(MSSmpegClass *klass);
|
||||
void ms_smpeg_uninit(MSSmpeg *obj);
|
||||
|
||||
MSFilter * ms_smpeg_new();
|
||||
void ms_smpeg_start(MSSmpeg *obj);
|
||||
void ms_smpeg_stop(MSSmpeg *obj);
|
||||
|
||||
|
||||
void ms_smpeg_destroy(MSSmpeg *obj);
|
||||
void ms_smpeg_process(MSSmpeg *obj);
|
||||
#endif
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
/*
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
/*
|
||||
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
|
||||
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
/*
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
/*
|
||||
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
|
||||
|
||||
|
|
@ -1,215 +0,0 @@
|
|||
/*
|
||||
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((SpeexMode*)mode);
|
||||
speex_bits_init(&obj->bits);
|
||||
/* enable the perceptual post filter */
|
||||
speex_decoder_ctl(obj->speex_state,SPEEX_SET_PF, &pf);
|
||||
|
||||
speex_mode_query((SpeexMode*)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;
|
||||
default:
|
||||
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);
|
||||
speex_bits_destroy(&obj->bits);
|
||||
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;
|
||||
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);
|
||||
|
||||
}
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
/*
|
||||
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/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
|
||||
|
|
@ -1,187 +0,0 @@
|
|||
/*
|
||||
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((SpeexMode*)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((SpeexMode*)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;
|
||||
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);
|
||||
speex_bits_destroy(&obj->bits);
|
||||
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;
|
||||
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);
|
||||
}
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
/*
|
||||
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/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
|
||||
|
|
@ -1,194 +0,0 @@
|
|||
/*
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1,136 +0,0 @@
|
|||
/*
|
||||
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
|
||||
|
|
@ -1,137 +0,0 @@
|
|||
/*
|
||||
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 "mstcpclient.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
|
||||
void ms_tcp_client_process(MSTcpClient *r);
|
||||
void ms_tcp_client_init(MSTcpClient *r);
|
||||
void ms_tcp_client_destroy(MSTcpClient *r);
|
||||
void ms_tcp_client_class_init(MSTcpClientClass *klass);
|
||||
|
||||
static MSTcpClientClass *ms_tcp_client_class=NULL;
|
||||
|
||||
MSFilter * ms_tcp_client_new(void)
|
||||
{
|
||||
MSTcpClient *r;
|
||||
|
||||
r=g_new(MSTcpClient,1);
|
||||
|
||||
if (ms_tcp_client_class==NULL)
|
||||
{
|
||||
ms_tcp_client_class=g_new(MSTcpClientClass,1);
|
||||
ms_tcp_client_class_init(ms_tcp_client_class);
|
||||
}
|
||||
MS_FILTER(r)->klass=MS_FILTER_CLASS(ms_tcp_client_class);
|
||||
ms_tcp_client_init(r);
|
||||
return(MS_FILTER(r));
|
||||
}
|
||||
|
||||
|
||||
void ms_tcp_client_init(MSTcpClient *r)
|
||||
{
|
||||
ms_filter_init(MS_FILTER(r));
|
||||
MS_FILTER(r)->outqueues=r->q_outputs;
|
||||
memset(r->q_outputs,0,sizeof(MSQueue*));
|
||||
r->sock=-1;
|
||||
r->msg=NULL;
|
||||
}
|
||||
|
||||
|
||||
int ms_tcp_client_connect(MSTcpClient *obj, const char *addr, int port){
|
||||
struct addrinfo hints;
|
||||
struct addrinfo *res;
|
||||
char service[40];
|
||||
int err;
|
||||
sprintf(service,"%i",port);
|
||||
memset(&hints,0,sizeof(hints));
|
||||
hints.ai_family=PF_UNSPEC;
|
||||
hints.ai_socktype=SOCK_STREAM;
|
||||
err=getaddrinfo(addr,service,&hints,&res);
|
||||
if (err!=0){
|
||||
g_warning("getaddrinfo error: %s",gai_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
obj->sock=socket(res->ai_family,res->ai_socktype,0);
|
||||
if (obj->sock<0){
|
||||
g_warning("fail to create socket: %s",strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
err=connect(obj->sock,res->ai_addr,res->ai_addrlen);
|
||||
if (err<0){
|
||||
g_warning("Could not connect to %s:%i : %s",addr,port,strerror(errno));
|
||||
close(obj->sock);
|
||||
obj->sock=-1;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ms_tcp_client_class_init(MSTcpClientClass *klass)
|
||||
{
|
||||
ms_filter_class_init(MS_FILTER_CLASS(klass));
|
||||
ms_filter_class_set_name(MS_FILTER_CLASS(klass),"TcpClient");
|
||||
MS_FILTER_CLASS(klass)->max_qoutputs=1;
|
||||
MS_FILTER_CLASS(klass)->destroy=(MSFilterDestroyFunc)ms_tcp_client_destroy;
|
||||
MS_FILTER_CLASS(klass)->process=(MSFilterProcessFunc)ms_tcp_client_process;
|
||||
ms_filter_class_set_attr(MS_FILTER_CLASS(klass),FILTER_IS_SOURCE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ms_tcp_client_process(MSTcpClient *r)
|
||||
{
|
||||
static const int rcvsz=5000;
|
||||
int err;
|
||||
if (r->sock>0){
|
||||
if (r->msg==NULL){
|
||||
r->msg=ms_message_new(rcvsz);
|
||||
memset(r->msg->data,0,rcvsz);
|
||||
}
|
||||
err=recv(r->sock,r->msg->data,rcvsz,MSG_DONTWAIT);
|
||||
if (err<0 && errno!=EWOULDBLOCK && errno!=EAGAIN){
|
||||
g_warning("recv error: %s",strerror(errno));
|
||||
}else if (err>0){
|
||||
r->msg->size=err;
|
||||
ms_queue_put(r->q_outputs[0],r->msg);
|
||||
printf("output new message %p,%i\n",r->msg->data,r->msg->size);
|
||||
r->msg=NULL;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ms_tcp_client_uninit( MSTcpClient *obj){
|
||||
if (obj->sock>0) close(obj->sock);
|
||||
if (obj->msg!=NULL) ms_message_destroy(obj->msg);
|
||||
}
|
||||
|
||||
void ms_tcp_client_destroy( MSTcpClient *obj)
|
||||
{
|
||||
ms_tcp_client_uninit(obj);
|
||||
g_free(obj);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
/*
|
||||
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 mstcpclient_h
|
||||
#define mstcpclient_h
|
||||
|
||||
#include "msfilter.h"
|
||||
|
||||
/* According to earlier standards */
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
struct _MSTcpClient{
|
||||
MSFilter parent;
|
||||
MSQueue *q_outputs[1];
|
||||
int sock;
|
||||
MSMessage *msg;
|
||||
};
|
||||
|
||||
typedef struct _MSTcpClient MSTcpClient;
|
||||
|
||||
struct _MSTcpClientClass{
|
||||
MSFilterClass parent;
|
||||
};
|
||||
|
||||
typedef struct _MSTcpClientClass MSTcpClientClass;
|
||||
|
||||
MSFilter *ms_tcp_client_new();
|
||||
int ms_tcp_client_connect(MSTcpClient *obj, const char *addr, int port);
|
||||
#define MS_TCP_CLIENT(o) ((MSTcpClient*)(o))
|
||||
#endif
|
||||
|
|
@ -1,174 +0,0 @@
|
|||
/*
|
||||
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 "mstcpserv.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
|
||||
void ms_tcp_serv_process(MSTcpServ *r);
|
||||
void ms_tcp_serv_init(MSTcpServ *r, int port);
|
||||
void ms_tcp_serv_destroy(MSTcpServ *r);
|
||||
void ms_tcp_serv_class_init(MSTcpServClass *klass);
|
||||
|
||||
static MSTcpServClass *ms_tcp_serv_class=NULL;
|
||||
|
||||
MSFilter * ms_tcp_serv_new(void)
|
||||
{
|
||||
MSTcpServ *r;
|
||||
|
||||
r=g_new(MSTcpServ,1);
|
||||
|
||||
if (ms_tcp_serv_class==NULL)
|
||||
{
|
||||
ms_tcp_serv_class=g_new(MSTcpServClass,1);
|
||||
ms_tcp_serv_class_init(ms_tcp_serv_class);
|
||||
}
|
||||
MS_FILTER(r)->klass=MS_FILTER_CLASS(ms_tcp_serv_class);
|
||||
ms_tcp_serv_init(r,5800);
|
||||
return(MS_FILTER(r));
|
||||
}
|
||||
|
||||
|
||||
void ms_tcp_serv_init(MSTcpServ *r, int port)
|
||||
{
|
||||
struct addrinfo *res;
|
||||
struct addrinfo hints;
|
||||
char service[20];
|
||||
int err;
|
||||
int val=1;
|
||||
|
||||
ms_filter_init(MS_FILTER(r));
|
||||
MS_FILTER(r)->inqueues=r->q_inputs;
|
||||
memset(r->q_inputs,0,sizeof(MSQueue*));
|
||||
memset(&r->set,0,sizeof(fd_set));
|
||||
r->maxfd=0;
|
||||
r->asock=socket(PF_INET,SOCK_STREAM,0);
|
||||
if (r->asock<0){
|
||||
g_warning("Could not create socket: %s",strerror(errno));
|
||||
return;
|
||||
}
|
||||
err=fcntl(r->asock,F_SETFL,O_NONBLOCK);
|
||||
if (err<0){
|
||||
g_warning("Could not non blocking flag on socket: %s",strerror(errno));
|
||||
return;
|
||||
}
|
||||
err=setsockopt(r->asock,SOL_SOCKET,SO_REUSEADDR,&val,sizeof(int));
|
||||
if (err<0){
|
||||
g_warning("Could not set socket reusable: %s",strerror(errno));
|
||||
return;
|
||||
}
|
||||
sprintf(service,"%i",port);
|
||||
memset(&hints,0,sizeof(hints));
|
||||
hints.ai_family=PF_UNSPEC;
|
||||
hints.ai_socktype=SOCK_STREAM;
|
||||
if (err=getaddrinfo("0.0.0.0",service,&hints,&res)!=0){
|
||||
g_warning("Could not getaddrinfo: %s",gai_strerror(err));
|
||||
return;
|
||||
}
|
||||
err=bind(r->asock,(struct sockaddr *)res->ai_addr,res->ai_addrlen);
|
||||
freeaddrinfo(res);
|
||||
if (err<0){
|
||||
g_warning("Could not bind socket: %s",strerror(errno));
|
||||
return;
|
||||
}
|
||||
err=listen(r->asock,10);
|
||||
if (err<0){
|
||||
g_warning("Could not listen: %s",strerror(errno));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void ms_tcp_serv_class_init(MSTcpServClass *klass)
|
||||
{
|
||||
ms_filter_class_init(MS_FILTER_CLASS(klass));
|
||||
ms_filter_class_set_name(MS_FILTER_CLASS(klass),"TcpServ");
|
||||
MS_FILTER_CLASS(klass)->max_qinputs=1;
|
||||
MS_FILTER_CLASS(klass)->max_finputs=0;
|
||||
MS_FILTER_CLASS(klass)->destroy=(MSFilterDestroyFunc)ms_tcp_serv_destroy;
|
||||
MS_FILTER_CLASS(klass)->process=(MSFilterProcessFunc)ms_tcp_serv_process;
|
||||
}
|
||||
|
||||
static void accept_new_clients(MSTcpServ *r){
|
||||
int sock;
|
||||
struct sockaddr_storage ss;
|
||||
socklen_t len=sizeof(ss);
|
||||
int val=1;
|
||||
int err;
|
||||
|
||||
sock=accept(r->asock,(struct sockaddr*)&ss,&len);
|
||||
if (sock<0){
|
||||
if (errno!=EWOULDBLOCK && errno!=EAGAIN) g_warning("Could not accept connection: %s",strerror(errno));
|
||||
return;
|
||||
}
|
||||
FD_SET(sock,&r->set);
|
||||
err=setsockopt(sock,SOL_TCP,TCP_NODELAY,&val,sizeof(int));
|
||||
if (err<0){
|
||||
g_warning("Could not set tcp nodelay option: %s",strerror(errno));
|
||||
}
|
||||
if (r->maxfd<sock) r->maxfd=sock;
|
||||
printf("New client accepted.\n");
|
||||
}
|
||||
|
||||
|
||||
void ms_tcp_serv_process(MSTcpServ *r)
|
||||
{
|
||||
MSMessage *msg;
|
||||
int err;
|
||||
g_return_if_fail(r->asock>0);
|
||||
/*printf("ms_tcp_serv_process\n");*/
|
||||
/* first accept incoming connections */
|
||||
accept_new_clients(r);
|
||||
/* send data to all clients */
|
||||
msg=ms_queue_get(r->q_inputs[0]);
|
||||
if (msg!=NULL){
|
||||
int i;
|
||||
for (i=0;i<r->maxfd+1;i++){
|
||||
if (FD_ISSET(i,&r->set)){
|
||||
err=send(i,msg->data,msg->size,0);
|
||||
if (err<0){
|
||||
FD_CLR(i,&r->set);
|
||||
close(i);
|
||||
g_message("Client disconnected.");
|
||||
}
|
||||
}
|
||||
}
|
||||
ms_message_destroy(msg);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ms_tcp_serv_uninit( MSTcpServ *obj){
|
||||
if (obj->asock>0) close(obj->asock);
|
||||
}
|
||||
|
||||
void ms_tcp_serv_destroy( MSTcpServ *obj)
|
||||
{
|
||||
ms_tcp_serv_uninit(obj);
|
||||
g_free(obj);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
#ifndef mstcpserver_h
|
||||
#define mstcpserver_h
|
||||
|
||||
#include "msfilter.h"
|
||||
|
||||
/* According to earlier standards */
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
struct _MSTcpServ{
|
||||
MSFilter parent;
|
||||
MSQueue *q_inputs[1];
|
||||
fd_set set;
|
||||
int maxfd;
|
||||
int asock;
|
||||
};
|
||||
|
||||
typedef struct _MSTcpServ MSTcpServ;
|
||||
|
||||
struct _MSTcpServClass{
|
||||
MSFilterClass parent;
|
||||
};
|
||||
|
||||
typedef struct _MSTcpServClass MSTcpServClass;
|
||||
|
||||
MSFilter *ms_tcp_serv_new();
|
||||
#define MS_TCP_SERV(o) ((MSTcpServ*)(o))
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -1,114 +0,0 @@
|
|||
/*
|
||||
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=80;
|
||||
ms_timer_set_interval(sync,10);
|
||||
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;
|
||||
|
||||
timer->sync.time+=timer->milisec;
|
||||
|
||||
gettimeofday(&cur,NULL);
|
||||
time=((cur.tv_usec-timer->orig.tv_usec)/1000 ) + ((cur.tv_sec-timer->orig.tv_sec)*1000 );
|
||||
while((diff = timer->sync.time-time) > 0)
|
||||
{
|
||||
tv.tv_sec = timer->milisec/1000;
|
||||
tv.tv_usec = (timer->milisec%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 );
|
||||
}
|
||||
if (diff<-50) g_warning("Must catchup %i miliseconds.",-diff);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
/*
|
||||
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
|
||||
|
|
@ -1,152 +0,0 @@
|
|||
/*
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
/*
|
||||
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
|
||||
|
|
@ -1,161 +0,0 @@
|
|||
/*
|
||||
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;
|
||||
}
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
/*
|
||||
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
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
/*
|
||||
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
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue