Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
BC
public
mediastreamer2
Commits
332d7920
Commit
332d7920
authored
Aug 26, 2010
by
Simon Morlat
Browse files
send inband dtmfs when no telephone event are possible and pcmX is used
implement dtmfs playing within RingStream
parent
030250c1
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
120 additions
and
27 deletions
+120
-27
include/mediastreamer2/dtmfgen.h
include/mediastreamer2/dtmfgen.h
+6
-0
include/mediastreamer2/mediastream.h
include/mediastreamer2/mediastream.h
+2
-0
src/audiostream.c
src/audiostream.c
+36
-10
src/dtmfgen.c
src/dtmfgen.c
+76
-17
No files found.
include/mediastreamer2/dtmfgen.h
View file @
332d7920
...
...
@@ -24,6 +24,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define MS_DTMF_GEN_PUT MS_FILTER_METHOD(MS_DTMF_GEN_ID,0,const char)
#define MS_DTMF_GEN_PLAY MS_FILTER_METHOD(MS_DTMF_GEN_ID,0,const char)
/*alias to put*/
/**Start playing a dtmf */
#define MS_DTMF_GEN_START MS_FILTER_METHOD(MS_DTMF_GEN_ID,1,const char)
/**Stop currently played dtmf*/
#define MS_DTMF_GEN_STOP MS_FILTER_METHOD_NO_ARG(MS_DTMF_GEN_ID,2)
extern
MSFilterDesc
ms_dtmf_gen_desc
;
#endif
include/mediastreamer2/mediastream.h
View file @
332d7920
...
...
@@ -53,6 +53,7 @@ struct _AudioStream
MSFilter
*
rtprecv
;
MSFilter
*
rtpsend
;
MSFilter
*
dtmfgen
;
MSFilter
*
dtmfgen_rtp
;
MSFilter
*
ec
;
/*echo canceler*/
MSFilter
*
volsend
,
*
volrecv
;
/*MSVolumes*/
MSFilter
*
read_resampler
;
...
...
@@ -82,6 +83,7 @@ struct _RingStream
{
MSTicker
*
ticker
;
MSFilter
*
source
;
MSFilter
*
gendtmf
;
MSFilter
*
sndwrite
;
};
...
...
src/audiostream.c
View file @
332d7920
...
...
@@ -66,6 +66,7 @@ void audio_stream_free(AudioStream *stream)
if
(
stream
->
ticker
!=
NULL
)
ms_ticker_destroy
(
stream
->
ticker
);
if
(
stream
->
read_resampler
!=
NULL
)
ms_filter_destroy
(
stream
->
read_resampler
);
if
(
stream
->
write_resampler
!=
NULL
)
ms_filter_destroy
(
stream
->
write_resampler
);
if
(
stream
->
dtmfgen_rtp
!=
NULL
)
ms_filter_destroy
(
stream
->
dtmfgen_rtp
);
ms_free
(
stream
);
}
...
...
@@ -250,6 +251,13 @@ int audio_stream_start_full(AudioStream *stream, RtpProfile *profile, const char
ms_error
(
"audiostream.c: undefined payload type."
);
return
-
1
;
}
if
(
rtp_profile_get_payload_from_mime
(
profile
,
"telephone-event"
)
==
NULL
&&
(
strcasecmp
(
pt
->
mime_type
,
"pcmu"
)
==
0
||
strcasecmp
(
pt
->
mime_type
,
"pcma"
)
==
0
)){
/*if no telephone-event payload is usable and pcma or pcmu is used, we will generate
inband dtmf*/
stream
->
dtmfgen_rtp
=
ms_filter_new
(
MS_DTMF_GEN_ID
);
}
if
(
ms_filter_call_method
(
stream
->
rtpsend
,
MS_FILTER_GET_SAMPLE_RATE
,
&
sample_rate
)
!=
0
){
ms_error
(
"Sample rate is unknown for RTP side !"
);
return
-
1
;
...
...
@@ -357,6 +365,8 @@ int audio_stream_start_full(AudioStream *stream, RtpProfile *profile, const char
ms_connection_helper_link
(
&
h
,
stream
->
ec
,
1
,
1
);
if
(
stream
->
volsend
)
ms_connection_helper_link
(
&
h
,
stream
->
volsend
,
0
,
0
);
if
(
stream
->
dtmfgen_rtp
)
ms_connection_helper_link
(
&
h
,
stream
->
dtmfgen_rtp
,
0
,
0
);
ms_connection_helper_link
(
&
h
,
stream
->
encoder
,
0
,
0
);
ms_connection_helper_link
(
&
h
,
stream
->
rtpsend
,
0
,
-
1
);
...
...
@@ -578,32 +588,48 @@ RingStream * ring_start_with_cb(const char *file,int interval,MSSndCard *sndcard
int
tmp
;
stream
=
(
RingStream
*
)
ms_new0
(
RingStream
,
1
);
stream
->
source
=
ms_filter_new
(
MS_FILE_PLAYER_ID
);
if
(
ms_filter_call_method
(
stream
->
source
,
MS_FILE_PLAYER_OPEN
,(
void
*
)
file
)
<
0
){
ms_filter_destroy
(
stream
->
source
);
ms_free
(
stream
);
return
NULL
;
}
if
(
file
)
ms_filter_call_method
(
stream
->
source
,
MS_FILE_PLAYER_OPEN
,(
void
*
)
file
);
ms_filter_call_method
(
stream
->
source
,
MS_FILE_PLAYER_LOOP
,
&
interval
);
ms_filter_call_method_noarg
(
stream
->
source
,
MS_FILE_PLAYER_START
);
if
(
func
!=
NULL
)
ms_filter_set_notify_callback
(
stream
->
source
,
func
,
user_data
);
stream
->
gendtmf
=
ms_filter_new
(
MS_DTMF_GEN_ID
);
stream
->
sndwrite
=
ms_snd_card_create_writer
(
sndcard
);
ms_filter_call_method
(
stream
->
source
,
MS_FILTER_GET_SAMPLE_RATE
,
&
tmp
);
ms_filter_call_method
(
stream
->
gendtmf
,
MS_FILTER_SET_SAMPLE_RATE
,
&
tmp
);
ms_filter_call_method
(
stream
->
sndwrite
,
MS_FILTER_SET_SAMPLE_RATE
,
&
tmp
);
ms_filter_call_method
(
stream
->
source
,
MS_FILTER_GET_NCHANNELS
,
&
tmp
);
ms_filter_call_method
(
stream
->
gendtmf
,
MS_FILTER_SET_NCHANNELS
,
&
tmp
);
ms_filter_call_method
(
stream
->
sndwrite
,
MS_FILTER_SET_NCHANNELS
,
&
tmp
);
stream
->
ticker
=
ms_ticker_new
();
ms_ticker_set_name
(
stream
->
ticker
,
"Audio (ring) MSTicker"
);
ms_filter_link
(
stream
->
source
,
0
,
stream
->
sndwrite
,
0
);
ms_filter_link
(
stream
->
source
,
0
,
stream
->
gendtmf
,
0
);
ms_filter_link
(
stream
->
gendtmf
,
0
,
stream
->
sndwrite
,
0
);
ms_ticker_attach
(
stream
->
ticker
,
stream
->
source
);
return
stream
;
}
void
ring_play_dtmf
(
RingStream
*
stream
,
char
dtmf
,
int
duration_ms
){
if
(
duration_ms
>
0
)
ms_filter_call_method
(
stream
->
gendtmf
,
MS_DTMF_GEN_PLAY
,
&
dtmf
);
else
ms_filter_call_method
(
stream
->
gendtmf
,
MS_DTMF_GEN_START
,
&
dtmf
);
}
void
ring_stop_dtmf
(
RingStream
*
stream
){
ms_filter_call_method_noarg
(
stream
->
gendtmf
,
MS_DTMF_GEN_STOP
);
}
void
ring_stop
(
RingStream
*
stream
){
ms_ticker_detach
(
stream
->
ticker
,
stream
->
source
);
ms_filter_unlink
(
stream
->
source
,
0
,
stream
->
sndwrite
,
0
);
ms_filter_unlink
(
stream
->
source
,
0
,
stream
->
gendtmf
,
0
);
ms_filter_unlink
(
stream
->
gendtmf
,
0
,
stream
->
sndwrite
,
0
);
ms_ticker_destroy
(
stream
->
ticker
);
ms_filter_destroy
(
stream
->
source
);
ms_filter_destroy
(
stream
->
gendtmf
);
ms_filter_destroy
(
stream
->
sndwrite
);
ms_free
(
stream
);
#ifdef _WIN32_WCE
...
...
@@ -615,10 +641,10 @@ void ring_stop(RingStream *stream){
int
audio_stream_send_dtmf
(
AudioStream
*
stream
,
char
dtmf
)
{
if
(
stream
->
rtpsend
)
if
(
stream
->
dtmfgen_rtp
)
ms_filter_call_method
(
stream
->
dtmfgen_rtp
,
MS_DTMF_GEN_PLAY
,
&
dtmf
);
else
if
(
stream
->
rtpsend
)
ms_filter_call_method
(
stream
->
rtpsend
,
MS_RTP_SEND_SEND_DTMF
,
&
dtmf
);
if
(
stream
->
dtmfgen
)
ms_filter_call_method
(
stream
->
dtmfgen
,
MS_DTMF_GEN_PUT
,
&
dtmf
);
return
0
;
}
...
...
src/dtmfgen.c
View file @
332d7920
...
...
@@ -18,6 +18,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "mediastreamer2/dtmfgen.h"
#include "mediastreamer2/msticker.h"
#include <math.h>
...
...
@@ -26,12 +27,17 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define M_PI 3.14159265358979323846
#endif
#define NO_SAMPLES_THRESHOLD 100
/*ms*/
#define TRAILLING_SILENCE 500
/*ms*/
struct
DtmfGenState
{
int
rate
;
int
dur
;
int
pos
;
float
highfreq
;
float
lowfreq
;
int
nosamples_time
;
int
silence
;
char
dtmf
;
};
...
...
@@ -43,6 +49,8 @@ static void dtmfgen_init(MSFilter *f){
s
->
dur
=
s
->
rate
/
10
;
s
->
pos
=
0
;
s
->
dtmf
=
0
;
s
->
nosamples_time
=
0
;
s
->
silence
=
0
;
f
->
data
=
s
;
}
...
...
@@ -123,45 +131,94 @@ static int dtmfgen_put(MSFilter *f, void *arg){
ms_warning
(
"Not a dtmf key."
);
return
-
1
;
}
ms_filter_lock
(
f
);
s
->
lowfreq
=
s
->
lowfreq
/
s
->
rate
;
s
->
highfreq
=
s
->
highfreq
/
s
->
rate
;
s
->
dur
=
s
->
rate
/
10
;
/*100 ms duration */
s
->
silence
=
0
;
s
->
dtmf
=
dtmf
[
0
];
ms_filter_unlock
(
f
);
return
0
;
}
static
int
dtmfgen_start
(
MSFilter
*
f
,
void
*
arg
){
if
(
dtmfgen_put
(
f
,
arg
)
==
0
){
DtmfGenState
*
s
=
(
DtmfGenState
*
)
f
->
data
;
s
->
dur
=
5
*
s
->
rate
;
return
0
;
}
return
-
1
;
}
static
int
dtmfgen_stop
(
MSFilter
*
f
,
void
*
arg
){
DtmfGenState
*
s
=
(
DtmfGenState
*
)
f
->
data
;
s
->
dtmf
=
0
;
return
0
;
}
static
int
dtmfgen_set_rate
(
MSFilter
*
f
,
void
*
arg
){
DtmfGenState
*
s
=
(
DtmfGenState
*
)
f
->
data
;
s
->
rate
=*
((
int
*
)
arg
);
s
->
dur
=
s
->
rate
/
10
;
return
0
;
}
static
void
write_dtmf
(
DtmfGenState
*
s
,
int16_t
*
sample
,
int
nsamples
){
int
i
;
for
(
i
=
0
;
i
<
nsamples
&&
s
->
pos
<
s
->
dur
;
i
++
,
s
->
pos
++
){
sample
[
i
]
=
(
int16_t
)(
10000
.
0
*
sin
(
2
*
M_PI
*
(
float
)
s
->
pos
*
s
->
lowfreq
));
sample
[
i
]
+=
(
int16_t
)(
10000
.
0
*
sin
(
2
*
M_PI
*
(
float
)
s
->
pos
*
s
->
highfreq
));
}
if
(
s
->
pos
==
s
->
dur
){
s
->
pos
=
0
;
s
->
dtmf
=
0
;
s
->
silence
=
TRAILLING_SILENCE
;
}
}
static
void
dtmfgen_process
(
MSFilter
*
f
){
mblk_t
*
m
;
DtmfGenState
*
s
=
(
DtmfGenState
*
)
f
->
data
;
int
nsamples
;
while
((
m
=
ms_queue_get
(
f
->
inputs
[
0
]))
!=
NULL
){
if
(
s
->
dtmf
!=
0
){
int
nsamples
=
(
m
->
b_wptr
-
m
->
b_rptr
)
/
2
;
int
i
;
int16_t
*
sample
=
(
int16_t
*
)
m
->
b_rptr
;
for
(
i
=
0
;
i
<
nsamples
&&
s
->
pos
<
s
->
dur
;
i
++
,
s
->
pos
++
){
sample
[
i
]
=
(
int16_t
)(
10000
.
0
*
sin
(
2
*
M_PI
*
(
float
)
s
->
pos
*
s
->
lowfreq
));
sample
[
i
]
+=
(
int16_t
)(
10000
.
0
*
sin
(
2
*
M_PI
*
(
float
)
s
->
pos
*
s
->
highfreq
));
ms_filter_lock
(
f
);
if
(
ms_queue_empty
(
f
->
inputs
[
0
])){
s
->
nosamples_time
+=
f
->
ticker
->
interval
;
if
((
s
->
dtmf
!=
0
||
s
->
silence
!=
0
)
&&
s
->
nosamples_time
>
NO_SAMPLES_THRESHOLD
){
/*after 100 ms without stream we decide to generate our own sample
instead of writing into incoming stream samples*/
nsamples
=
(
f
->
ticker
->
interval
*
s
->
rate
)
/
1000
;
m
=
allocb
(
nsamples
*
2
,
0
);
if
(
s
->
silence
==
0
){
write_dtmf
(
s
,(
int16_t
*
)
m
->
b_wptr
,
nsamples
);
}
else
{
memset
(
m
->
b_wptr
,
0
,
nsamples
*
2
);
s
->
silence
-=
f
->
ticker
->
interval
;
if
(
s
->
silence
<
0
)
s
->
silence
=
0
;
}
if
(
s
->
pos
==
s
->
dur
){
s
->
pos
=
0
;
s
->
dtmf
=
0
;
m
->
b_wptr
+=
nsamples
*
2
;
ms_queue_put
(
f
->
outputs
[
0
],
m
);
}
}
else
{
s
->
nosamples_time
=
0
;
s
->
silence
=
0
;
while
((
m
=
ms_queue_get
(
f
->
inputs
[
0
]))
!=
NULL
){
if
(
s
->
dtmf
!=
0
){
nsamples
=
(
m
->
b_wptr
-
m
->
b_rptr
)
/
2
;
write_dtmf
(
s
,
(
int16_t
*
)
m
->
b_rptr
,
nsamples
);
}
ms_queue_put
(
f
->
outputs
[
0
],
m
);
}
ms_queue_put
(
f
->
outputs
[
0
],
m
);
}
ms_filter_unlock
(
f
);
}
MSFilterMethod
dtmfgen_methods
[]
=
{
{
MS_FILTER_SET_SAMPLE_RATE
,
dtmfgen_set_rate
},
{
MS_DTMF_GEN_PUT
,
dtmfgen_put
},
{
MS_DTMF_GEN_PLAY
,
dtmfgen_put
},
{
MS_DTMF_GEN_START
,
dtmfgen_start
},
{
MS_DTMF_GEN_STOP
,
dtmfgen_stop
},
{
0
,
NULL
}
};
...
...
@@ -180,7 +237,8 @@ MSFilterDesc ms_dtmf_gen_desc={
dtmfgen_process
,
NULL
,
dtmfgen_uninit
,
dtmfgen_methods
dtmfgen_methods
,
MS_FILTER_IS_PUMP
};
#else
...
...
@@ -195,7 +253,8 @@ MSFilterDesc ms_dtmf_gen_desc={
.
init
=
dtmfgen_init
,
.
process
=
dtmfgen_process
,
.
uninit
=
dtmfgen_uninit
,
.
methods
=
dtmfgen_methods
.
methods
=
dtmfgen_methods
,
.
flags
=
MS_FILTER_IS_PUMP
};
#endif
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment