Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
M
mediastreamer2
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
3
Issues
3
List
Board
Labels
Milestones
Merge Requests
8
Merge Requests
8
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
External Wiki
External Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
BC
public
mediastreamer2
Commits
fd8f21d7
Commit
fd8f21d7
authored
Feb 06, 2013
by
Simon Morlat
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'dev_callrecording'
parents
1f0374f4
0285f393
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
291 additions
and
94 deletions
+291
-94
Makefile.am
include/mediastreamer2/Makefile.am
+0
-1
mediastream.h
include/mediastreamer2/mediastream.h
+23
-8
msinterfaces.h
include/mediastreamer2/msinterfaces.h
+34
-2
Makefile.am
src/Makefile.am
+2
-1
msfileplayer.c
src/audiofilters/msfileplayer.c
+57
-41
msfilerec.c
src/audiofilters/msfilerec.c
+66
-24
waveheader.h
src/audiofilters/waveheader.h
+4
-1
audioconference.c
src/voip/audioconference.c
+1
-1
audiostream.c
src/voip/audiostream.c
+103
-14
Makefile.am
tests/Makefile.am
+1
-1
No files found.
include/mediastreamer2/Makefile.am
View file @
fd8f21d7
...
...
@@ -18,7 +18,6 @@ mediastreamer2_include_HEADERS= ice.h \
mediastream.h
\
msv4l.h
\
msvideo.h
\
waveheader.h
\
msvideoout.h
\
msvolume.h
\
mstee.h
\
...
...
include/mediastreamer2/mediastream.h
View file @
fd8f21d7
...
...
@@ -132,6 +132,11 @@ struct _AudioStream
MSFilter
*
write_resampler
;
MSFilter
*
equalizer
;
MSFilter
*
dummy
;
MSFilter
*
send_tee
;
MSFilter
*
recv_tee
;
MSFilter
*
recorder_mixer
;
MSFilter
*
recorder
;
char
*
recorder_file
;
uint64_t
last_packet_count
;
time_t
last_packet_time
;
EchoLimiterType
el_type
;
/*use echo limiter: two MSVolume, measured input level controlling local output level*/
...
...
@@ -209,13 +214,15 @@ MS2_PUBLIC void audio_stream_play_received_dtmfs(AudioStream *st, bool_t yesno);
**/
MS2_PUBLIC
AudioStream
*
audio_stream_new
(
int
loc_rtp_port
,
int
loc_rtcp_port
,
bool_t
ipv6
);
#define AUDIO_STREAM_FEATURE_PLC (1 << 0)
#define AUDIO_STREAM_FEATURE_EC (1 << 1)
#define AUDIO_STREAM_FEATURE_EQUALIZER (1 << 2)
#define AUDIO_STREAM_FEATURE_VOL_SND (1 << 3)
#define AUDIO_STREAM_FEATURE_VOL_RCV (1 << 4)
#define AUDIO_STREAM_FEATURE_DTMF (1 << 5)
#define AUDIO_STREAM_FEATURE_DTMF_ECHO (1 << 6)
#define AUDIO_STREAM_FEATURE_PLC (1 << 0)
#define AUDIO_STREAM_FEATURE_EC (1 << 1)
#define AUDIO_STREAM_FEATURE_EQUALIZER (1 << 2)
#define AUDIO_STREAM_FEATURE_VOL_SND (1 << 3)
#define AUDIO_STREAM_FEATURE_VOL_RCV (1 << 4)
#define AUDIO_STREAM_FEATURE_DTMF (1 << 5)
#define AUDIO_STREAM_FEATURE_DTMF_ECHO (1 << 6)
#define AUDIO_STREAM_FEATURE_MIXED_RECORDING (1 << 7)
#define AUDIO_STREAM_FEATURE_ALL (\
AUDIO_STREAM_FEATURE_PLC | \
AUDIO_STREAM_FEATURE_EC | \
...
...
@@ -223,9 +230,11 @@ MS2_PUBLIC AudioStream *audio_stream_new(int loc_rtp_port, int loc_rtcp_port, bo
AUDIO_STREAM_FEATURE_VOL_SND | \
AUDIO_STREAM_FEATURE_VOL_RCV | \
AUDIO_STREAM_FEATURE_DTMF | \
AUDIO_STREAM_FEATURE_DTMF_ECHO \
AUDIO_STREAM_FEATURE_DTMF_ECHO |\
AUDIO_STREAM_FEATURE_MIXED_RECORDING \
)
MS2_PUBLIC
uint32_t
audio_stream_get_features
(
AudioStream
*
st
);
MS2_PUBLIC
void
audio_stream_set_features
(
AudioStream
*
st
,
uint32_t
features
);
...
...
@@ -301,6 +310,12 @@ MS2_PUBLIC void audio_stream_stop (AudioStream * stream);
/* send a dtmf */
MS2_PUBLIC
int
audio_stream_send_dtmf
(
AudioStream
*
stream
,
char
dtmf
);
MS2_PUBLIC
int
audio_stream_mixed_record_open
(
AudioStream
*
st
,
const
char
*
filename
);
MS2_PUBLIC
int
audio_stream_mixed_record_start
(
AudioStream
*
st
);
MS2_PUBLIC
int
audio_stream_mixed_record_stop
(
AudioStream
*
st
);
MS2_PUBLIC
void
audio_stream_set_default_card
(
int
cardindex
);
/* retrieve RTP statistics*/
...
...
include/mediastreamer2/msinterfaces.h
View file @
fd8f21d7
...
...
@@ -79,7 +79,7 @@ typedef enum _MSPlayerState MSPlayerState;
/**open a media file*/
#define MS_PLAYER_OPEN \
MS_FILTER_METHOD(MSFilterPlayerInterface,0,const char
*
)
MS_FILTER_METHOD(MSFilterPlayerInterface,0,const char )
#define MS_PLAYER_START \
MS_FILTER_METHOD_NO_ARG(MSFilterPlayerInterface,1)
...
...
@@ -94,7 +94,39 @@ typedef enum _MSPlayerState MSPlayerState;
MS_FILTER_METHOD(MSFilterPlayerInterface,4,int)
#define MS_PLAYER_GET_STATE \
MS_FILTER_METHOD(MSFilterPlayerInterface,5,int)
MS_FILTER_METHOD(MSFilterPlayerInterface,5,MSPlayerState)
/**
* Interface definitions for recorders
**/
enum
_MSRecorderState
{
MSRecorderClosed
,
MSRecorderPaused
,
MSRecorderRunning
};
typedef
enum
_MSRecorderState
MSRecorderState
;
/**open a media file for recording*/
#define MS_RECORDER_OPEN \
MS_FILTER_METHOD(MSFilterRecorderInterface,0,const char )
#define MS_RECORDER_START \
MS_FILTER_METHOD_NO_ARG(MSFilterRecorderInterface,1)
#define MS_RECORDER_PAUSE \
MS_FILTER_METHOD_NO_ARG(MSFilterRecorderInterface,2)
#define MS_RECORDER_CLOSE \
MS_FILTER_METHOD_NO_ARG(MSFilterRecorderInterface,3)
#define MS_RECORDER_GET_STATE \
MS_FILTER_METHOD(MSFilterRecorderInterface,5,MSRecorderState)
/** Interface definitions for echo cancellers */
...
...
src/Makefile.am
View file @
fd8f21d7
...
...
@@ -119,7 +119,8 @@ libmediastreamer_voip_la_SOURCES+= audiofilters/winsnd3.c \
audiofilters/msfilerec_win.c
else
libmediastreamer_voip_la_SOURCES
+=
audiofilters/msfileplayer.c
\
audiofilters/msfilerec.c
audiofilters/msfilerec.c
\
audiofilters/waveheader.h
endif
if
BUILD_RESAMPLE
...
...
src/audiofilters/msfileplayer.c
View file @
fd8f21d7
...
...
@@ -22,7 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#endif
#include "mediastreamer2/msfileplayer.h"
#include "
mediastreamer2/
waveheader.h"
#include "waveheader.h"
#include "mediastreamer2/msticker.h"
#ifdef HAVE_PCAP
...
...
@@ -44,6 +44,7 @@ struct _PlayerData{
int
samplesize
;
uint32_t
ts
;
bool_t
swap
;
bool_t
is_raw
;
#ifdef HAVE_PCAP
pcap_t
*
pcap
;
struct
pcap_pkthdr
*
pcap_hdr
;
...
...
@@ -58,7 +59,7 @@ struct _PlayerData{
typedef
struct
_PlayerData
PlayerData
;
static
void
player_init
(
MSFilter
*
f
){
PlayerData
*
d
=
ms_new
(
PlayerData
,
1
);
PlayerData
*
d
=
ms_new
0
(
PlayerData
,
1
);
d
->
fd
=-
1
;
d
->
state
=
MSPlayerClosed
;
d
->
swap
=
FALSE
;
...
...
@@ -70,6 +71,7 @@ static void player_init(MSFilter *f){
d
->
pause_time
=
0
;
d
->
count
=
0
;
d
->
ts
=
0
;
d
->
is_raw
=
TRUE
;
#ifdef HAVE_PCAP
d
->
pcap
=
NULL
;
d
->
pcap_hdr
=
NULL
;
...
...
@@ -81,74 +83,87 @@ static void player_init(MSFilter *f){
f
->
data
=
d
;
}
static
int
read_wav_header
(
PlayerData
*
d
){
char
header1
[
sizeof
(
riff_t
)];
char
header2
[
sizeof
(
format_t
)];
char
header3
[
sizeof
(
data_t
)];
int
ms_read_wav_header_from_fd
(
wave_header_t
*
header
,
int
fd
){
int
count
;
riff_t
*
riff_chunk
=
(
riff_t
*
)
header1
;
format_t
*
format_chunk
=
(
format_t
*
)
header2
;
data_t
*
data_chunk
=
(
data_t
*
)
header3
;
int
skip
;
int
hsize
=
0
;
riff_t
*
riff_chunk
=&
header
->
riff_chunk
;
format_t
*
format_chunk
=&
header
->
format_chunk
;
data_t
*
data_chunk
=&
header
->
data_chunk
;
unsigned
long
len
=
0
;
len
=
read
(
d
->
fd
,
header1
,
sizeof
(
header1
))
;
if
(
len
!=
sizeof
(
header1
)){
len
=
read
(
fd
,
(
char
*
)
riff_chunk
,
sizeof
(
riff_t
))
;
if
(
len
!=
sizeof
(
riff_t
)){
goto
not_a_wav
;
}
if
(
0
!=
strncmp
(
riff_chunk
->
riff
,
"RIFF"
,
4
)
||
0
!=
strncmp
(
riff_chunk
->
wave
,
"WAVE"
,
4
)){
if
(
0
!=
strncmp
(
riff_chunk
->
riff
,
"RIFF"
,
4
)
||
0
!=
strncmp
(
riff_chunk
->
wave
,
"WAVE"
,
4
)){
goto
not_a_wav
;
}
len
=
read
(
d
->
fd
,
header2
,
sizeof
(
header2
))
;
if
(
len
!=
sizeof
(
header2
)){
len
=
read
(
fd
,
(
char
*
)
format_chunk
,
sizeof
(
format_t
))
;
if
(
len
!=
sizeof
(
format_t
)){
ms_warning
(
"Wrong wav header: cannot read file"
);
goto
not_a_wav
;
}
d
->
rate
=
le_uint32
(
format_chunk
->
rate
);
d
->
nchannels
=
le_uint16
(
format_chunk
->
channel
);
if
(
d
->
nchannels
==
0
)
goto
not_a_wav
;
d
->
samplesize
=
le_uint16
(
format_chunk
->
blockalign
)
/
d
->
nchannels
;
if
(
format_chunk
->
len
-
0x10
>
0
)
if
((
skip
=
le_uint32
(
format_chunk
->
len
)
-
0x10
)
>
0
)
{
lseek
(
d
->
fd
,(
format_chunk
->
len
-
0x10
)
,
SEEK_CUR
);
lseek
(
fd
,
skip
,
SEEK_CUR
);
}
hsize
=
sizeof
(
wave_header_t
)
-
0x10
+
le_uint32
(
format_chunk
->
len
);
d
->
hsize
=
sizeof
(
wave_header_t
)
-
0x10
+
format_chunk
->
len
;
len
=
read
(
d
->
fd
,
header3
,
sizeof
(
header3
))
;
if
(
len
!=
sizeof
(
header3
)){
ms_warning
(
"Wrong wav header: cannot read file"
);
goto
not_a_wav
;
}
count
=
0
;
while
(
strncmp
(
data_chunk
->
data
,
"data"
,
4
)
!=
0
&&
count
<
30
)
{
ms_warning
(
"skipping chunk=%s len=%i"
,
data_chunk
->
data
,
data_chunk
->
len
);
lseek
(
d
->
fd
,
data_chunk
->
len
,
SEEK_CUR
);
count
++
;
d
->
hsize
=
d
->
hsize
+
len
+
data_chunk
->
len
;
len
=
read
(
d
->
fd
,
header3
,
sizeof
(
header3
))
;
if
(
len
!=
sizeof
(
header3
)){
do
{
len
=
read
(
fd
,
data_chunk
,
sizeof
(
data_t
))
;
if
(
len
!=
sizeof
(
data_t
)){
ms_warning
(
"Wrong wav header: cannot read file"
);
goto
not_a_wav
;
}
}
if
(
strncmp
(
data_chunk
->
data
,
"data"
,
4
)
!=
0
){
ms_warning
(
"skipping chunk=%s len=%i"
,
data_chunk
->
data
,
data_chunk
->
len
);
lseek
(
fd
,
le_uint32
(
data_chunk
->
len
),
SEEK_CUR
);
count
++
;
hsize
+=
len
+
le_uint32
(
data_chunk
->
len
);
}
else
{
hsize
+=
len
;
break
;
}
}
while
(
count
<
30
);
return
hsize
;
not_a_wav
:
/*rewind*/
lseek
(
fd
,
0
,
SEEK_SET
);
return
-
1
;
}
static
int
read_wav_header
(
PlayerData
*
d
){
wave_header_t
header
;
format_t
*
format_chunk
=&
header
.
format_chunk
;
int
ret
=
ms_read_wav_header_from_fd
(
&
header
,
d
->
fd
);
if
(
ret
==-
1
)
goto
not_a_wav
;
d
->
rate
=
le_uint32
(
format_chunk
->
rate
);
d
->
nchannels
=
le_uint16
(
format_chunk
->
channel
);
if
(
d
->
nchannels
==
0
)
goto
not_a_wav
;
d
->
samplesize
=
le_uint16
(
format_chunk
->
blockalign
)
/
d
->
nchannels
;
d
->
hsize
=
ret
;
#ifdef WORDS_BIGENDIAN
if
(
le_uint16
(
format_chunk
->
blockalign
)
==
le_uint16
(
format_chunk
->
channel
)
*
2
)
d
->
swap
=
TRUE
;
#endif
d
->
is_raw
=
FALSE
;
return
0
;
not_a_wav
:
/*rewind*/
lseek
(
d
->
fd
,
0
,
SEEK_SET
);
d
->
hsize
=
0
;
d
->
is_raw
=
TRUE
;
return
-
1
;
}
...
...
@@ -374,9 +389,10 @@ static int player_get_sr(MSFilter *f, void*arg){
}
static
int
player_set_sr
(
MSFilter
*
f
,
void
*
arg
)
{
/* This function should be used only when playing a PCAP file */
/* This function should be used only when playing a PCAP
or raw
file */
PlayerData
*
d
=
(
PlayerData
*
)
f
->
data
;
d
->
rate
=
*
((
int
*
)
arg
);
if
(
d
->
is_raw
)
d
->
rate
=
*
((
int
*
)
arg
);
else
return
-
1
;
return
0
;
}
...
...
src/audiofilters/msfilerec.c
View file @
fd8f21d7
...
...
@@ -22,26 +22,21 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#endif
#include "mediastreamer2/msfilerec.h"
#include "
mediastreamer2/
waveheader.h"
#include "waveheader.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
static
int
rec_close
(
MSFilter
*
f
,
void
*
arg
);
typedef
enum
{
Closed
,
Stopped
,
Started
}
State
;
static
int
rec_close
(
MSFilter
*
f
,
void
*
arg
);
typedef
struct
RecState
{
int
fd
;
int
rate
;
int
nchannels
;
int
size
;
State
state
;
MSRecorder
State
state
;
}
RecState
;
static
void
rec_init
(
MSFilter
*
f
){
...
...
@@ -50,7 +45,7 @@ static void rec_init(MSFilter *f){
s
->
rate
=
8000
;
s
->
nchannels
=
1
;
s
->
size
=
0
;
s
->
state
=
Closed
;
s
->
state
=
MSRecorder
Closed
;
f
->
data
=
s
;
}
...
...
@@ -61,7 +56,7 @@ static void rec_process(MSFilter *f){
while
((
m
=
ms_queue_get
(
f
->
inputs
[
0
]))
!=
NULL
){
mblk_t
*
it
=
m
;
ms_mutex_lock
(
&
f
->
lock
);
if
(
s
->
state
==
Started
){
if
(
s
->
state
==
MSRecorderRunning
){
while
(
it
!=
NULL
){
int
len
=
it
->
b_wptr
-
it
->
b_rptr
;
if
((
err
=
write
(
s
->
fd
,
it
->
b_rptr
,
len
))
!=
len
){
...
...
@@ -77,26 +72,62 @@ static void rec_process(MSFilter *f){
}
}
static
int
rec_get_length
(
const
char
*
file
,
int
*
length
){
wave_header_t
header
;
int
fd
=
open
(
file
,
O_RDONLY
);
int
ret
=
ms_read_wav_header_from_fd
(
&
header
,
fd
);
close
(
fd
);
if
(
ret
>
0
){
*
length
=
le_uint32
(
header
.
data_chunk
.
len
);
}
else
{
*
length
=
0
;
}
return
ret
;
}
static
int
rec_open
(
MSFilter
*
f
,
void
*
arg
){
RecState
*
s
=
(
RecState
*
)
f
->
data
;
const
char
*
filename
=
(
const
char
*
)
arg
;
if
(
s
->
fd
>=
0
)
rec_close
(
f
,
NULL
);
ms_mutex_lock
(
&
f
->
lock
);
s
->
fd
=
open
(
filename
,
O_WRONLY
|
O_CREAT
|
O_TRUNC
,
S_IRUSR
|
S_IWUSR
);
if
(
s
->
fd
<
0
){
int
flags
;
if
(
s
->
fd
!=-
1
)
rec_close
(
f
,
NULL
);
if
(
access
(
filename
,
R_OK
|
W_OK
)
==
0
){
flags
=
O_WRONLY
;
if
(
rec_get_length
(
filename
,
&
s
->
size
)
>
0
){
ms_message
(
"Opening wav file in append mode, current data size is %i"
,
s
->
size
);
}
}
else
{
flags
=
O_WRONLY
|
O_CREAT
|
O_TRUNC
;
s
->
size
=
0
;
}
s
->
fd
=
open
(
filename
,
flags
,
S_IRUSR
|
S_IWUSR
);
if
(
s
->
fd
==-
1
){
ms_warning
(
"Cannot open %s: %s"
,
filename
,
strerror
(
errno
));
ms_mutex_unlock
(
&
f
->
lock
);
return
-
1
;
}
s
->
state
=
Stopped
;
if
(
s
->
size
>
0
){
struct
stat
statbuf
;
if
(
fstat
(
s
->
fd
,
&
statbuf
)
==
0
){
if
(
lseek
(
s
->
fd
,
statbuf
.
st_size
,
SEEK_SET
)
!=
0
){
ms_error
(
"Could not lseek to end of file: %s"
,
strerror
(
errno
));
}
}
else
ms_error
(
"fstat() failed: %s"
,
strerror
(
errno
));
}
ms_mutex_lock
(
&
f
->
lock
);
s
->
state
=
MSRecorderPaused
;
ms_mutex_unlock
(
&
f
->
lock
);
return
0
;
}
static
int
rec_start
(
MSFilter
*
f
,
void
*
arg
){
RecState
*
s
=
(
RecState
*
)
f
->
data
;
if
(
s
->
state
!=
MSRecorderPaused
){
ms_error
(
"MSFileRec: cannot start, state=%i"
,
s
->
state
);
return
-
1
;
}
ms_mutex_lock
(
&
f
->
lock
);
s
->
state
=
Started
;
s
->
state
=
MSRecorderRunning
;
ms_mutex_unlock
(
&
f
->
lock
);
return
0
;
}
...
...
@@ -104,7 +135,7 @@ static int rec_start(MSFilter *f, void *arg){
static
int
rec_stop
(
MSFilter
*
f
,
void
*
arg
){
RecState
*
s
=
(
RecState
*
)
f
->
data
;
ms_mutex_lock
(
&
f
->
lock
);
s
->
state
=
Stopp
ed
;
s
->
state
=
MSRecorderPaus
ed
;
ms_mutex_unlock
(
&
f
->
lock
);
return
0
;
}
...
...
@@ -135,8 +166,8 @@ static void write_wav_header(int fd, int rate, int nchannels, int size){
static
int
rec_close
(
MSFilter
*
f
,
void
*
arg
){
RecState
*
s
=
(
RecState
*
)
f
->
data
;
ms_mutex_lock
(
&
f
->
lock
);
s
->
state
=
Closed
;
if
(
s
->
fd
>=
0
)
{
s
->
state
=
MSRecorder
Closed
;
if
(
s
->
fd
!=-
1
)
{
write_wav_header
(
s
->
fd
,
s
->
rate
,
s
->
nchannels
,
s
->
size
);
close
(
s
->
fd
);
s
->
fd
=-
1
;
...
...
@@ -145,6 +176,12 @@ static int rec_close(MSFilter *f, void *arg){
return
0
;
}
static
int
rec_get_state
(
MSFilter
*
f
,
void
*
arg
){
RecState
*
s
=
(
RecState
*
)
f
->
data
;
*
(
MSRecorderState
*
)
arg
=
s
->
state
;
return
0
;
}
static
int
rec_set_sr
(
MSFilter
*
f
,
void
*
arg
){
RecState
*
s
=
(
RecState
*
)
f
->
data
;
ms_mutex_lock
(
&
f
->
lock
);
...
...
@@ -161,7 +198,7 @@ static int rec_set_nchannels(MSFilter *f, void *arg) {
static
void
rec_uninit
(
MSFilter
*
f
){
RecState
*
s
=
(
RecState
*
)
f
->
data
;
if
(
s
->
fd
>=
0
)
rec_close
(
f
,
NULL
);
if
(
s
->
fd
!=-
1
)
rec_close
(
f
,
NULL
);
ms_free
(
s
);
}
...
...
@@ -172,6 +209,11 @@ static MSFilterMethod rec_methods[]={
{
MS_FILE_REC_START
,
rec_start
},
{
MS_FILE_REC_STOP
,
rec_stop
},
{
MS_FILE_REC_CLOSE
,
rec_close
},
{
MS_RECORDER_OPEN
,
rec_open
},
{
MS_RECORDER_START
,
rec_start
},
{
MS_RECORDER_PAUSE
,
rec_stop
},
{
MS_RECORDER_CLOSE
,
rec_close
},
{
MS_RECORDER_GET_STATE
,
rec_get_state
},
{
0
,
NULL
}
};
...
...
@@ -183,13 +225,13 @@ MSFilterDesc ms_file_rec_desc={
N_
(
"Wav file recorder"
),
MS_FILTER_OTHER
,
NULL
,
1
,
1
,
0
,
rec_init
,
NULL
,
rec_process
,
rec_process
,
NULL
,
rec_uninit
,
rec_uninit
,
rec_methods
};
...
...
include/mediastreamer2
/waveheader.h
→
src/audiofilters
/waveheader.h
View file @
fd8f21d7
...
...
@@ -74,7 +74,7 @@ typedef struct _format_t {
typedef
struct
_data_t
{
char
data
[
4
]
;
/* "data" (ASCII characters) */
in
t
len
;
/* length of data */
uint32_
t
len
;
/* length of data */
}
data_t
;
typedef
struct
_wave_header_t
...
...
@@ -89,4 +89,7 @@ typedef struct _wave_header_t
#define wave_header_get_channel(header) le_uint16((header)->format_chunk.channel)
#define wave_header_get_bpsmpl(header) \
le_uint16((header)->format_chunk.blockalign)
int
ms_read_wav_header_from_fd
(
wave_header_t
*
header
,
int
fd
);
#endif
src/voip/audioconference.c
View file @
fd8f21d7
...
...
@@ -93,7 +93,7 @@ static void cut_audio_stream_graph(MSAudioEndpoint *ep, bool_t is_remote){
/*we would like to keep the volrecv (MSVolume filter) in the graph to measure the output level*/
ep
->
in_cut_point_prev
.
filter
=
st
->
volrecv
;
}
else
{
ep
->
in_cut_point_prev
.
filter
=
st
->
ms
.
decoder
;
ep
->
in_cut_point_prev
.
filter
=
st
->
plc
?
st
->
plc
:
st
->
ms
.
decoder
;
}
ep
->
in_cut_point
=
just_after
(
ep
->
in_cut_point_prev
.
filter
);
ms_filter_unlink
(
ep
->
in_cut_point_prev
.
filter
,
ep
->
in_cut_point_prev
.
pin
,
ep
->
in_cut_point
.
filter
,
ep
->
in_cut_point
.
pin
);
...
...
src/voip/audiostream.c
View file @
fd8f21d7
...
...
@@ -31,6 +31,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "mediastreamer2/msfilerec.h"
#include "mediastreamer2/msvolume.h"
#include "mediastreamer2/msequalizer.h"
#include "mediastreamer2/mstee.h"
#include "mediastreamer2/msaudiomixer.h"
#include "mediastreamer2/mscodecutils.h"
#include "private.h"
...
...
@@ -42,8 +44,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#endif
#endif
void
audio_stream_free
(
AudioStream
*
stream
)
{
static
void
audio_stream_free
(
AudioStream
*
stream
)
{
media_stream_free
(
&
stream
->
ms
);
if
(
stream
->
soundread
!=
NULL
)
ms_filter_destroy
(
stream
->
soundread
);
if
(
stream
->
soundwrite
!=
NULL
)
ms_filter_destroy
(
stream
->
soundwrite
);
...
...
@@ -57,6 +58,11 @@ void audio_stream_free(AudioStream *stream) {
if
(
stream
->
write_resampler
!=
NULL
)
ms_filter_destroy
(
stream
->
write_resampler
);
if
(
stream
->
dtmfgen_rtp
!=
NULL
)
ms_filter_destroy
(
stream
->
dtmfgen_rtp
);
if
(
stream
->
dummy
)
ms_filter_destroy
(
stream
->
dummy
);
if
(
stream
->
recv_tee
)
ms_filter_destroy
(
stream
->
recv_tee
);
if
(
stream
->
send_tee
)
ms_filter_destroy
(
stream
->
send_tee
);
if
(
stream
->
recorder
)
ms_filter_destroy
(
stream
->
recorder
);
if
(
stream
->
recorder_mixer
)
ms_filter_destroy
(
stream
->
recorder_mixer
);
if
(
stream
->
recorder_file
)
ms_free
(
stream
->
recorder_file
);
if
(
stream
->
qi
)
ms_quality_indicator_destroy
(
stream
->
qi
);
ms_free
(
stream
);
}
...
...
@@ -356,30 +362,48 @@ int audio_stream_start_full(AudioStream *stream, RtpProfile *profile, const char
if
(
stream
->
ec
){
ms_filter_call_method
(
stream
->
ec
,
MS_FILTER_SET_SAMPLE_RATE
,
&
sample_rate
);
}
if
(
stream
->
features
&
AUDIO_STREAM_FEATURE_MIXED_RECORDING
){
int
val
=
0
;
int
pin
=
1
;
stream
->
recorder
=
ms_filter_new
(
MS_FILE_REC_ID
);
stream
->
recorder_mixer
=
ms_filter_new
(
MS_AUDIO_MIXER_ID
);
stream
->
recv_tee
=
ms_filter_new
(
MS_TEE_ID
);
stream
->
send_tee
=
ms_filter_new
(
MS_TEE_ID
);
ms_filter_call_method
(
stream
->
recorder_mixer
,
MS_AUDIO_MIXER_ENABLE_CONFERENCE_MODE
,
&
val
);
ms_filter_call_method
(
stream
->
recorder_mixer
,
MS_FILTER_SET_SAMPLE_RATE
,
&
sample_rate
);
ms_filter_call_method
(
stream
->
recorder_mixer
,
MS_FILTER_SET_NCHANNELS
,
&
pt
->
channels
);
ms_filter_call_method
(
stream
->
recv_tee
,
MS_TEE_MUTE
,
&
pin
);
ms_filter_call_method
(
stream
->
send_tee
,
MS_TEE_MUTE
,
&
pin
);
ms_filter_call_method
(
stream
->
recorder
,
MS_FILTER_SET_SAMPLE_RATE
,
&
sample_rate
);
ms_filter_call_method
(
stream
->
recorder
,
MS_FILTER_SET_NCHANNELS
,
&
pt
->
channels
);
}
/* give the encoder/decoder some parameters*/
ms_filter_call_method
(
stream
->
ms
.
encoder
,
MS_FILTER_SET_SAMPLE_RATE
,
&
pt
->
clock
_rate
);
ms_filter_call_method
(
stream
->
ms
.
encoder
,
MS_FILTER_SET_SAMPLE_RATE
,
&
sample
_rate
);
ms_message
(
"Payload's bitrate is %i"
,
pt
->
normal_bitrate
);
if
(
pt
->
normal_bitrate
>
0
){
ms_message
(
"Setting audio encoder network bitrate to %i"
,
pt
->
normal_bitrate
);
ms_filter_call_method
(
stream
->
ms
.
encoder
,
MS_FILTER_SET_BITRATE
,
&
pt
->
normal_bitrate
);
}
ms_filter_call_method
(
stream
->
ms
.
encoder
,
MS_FILTER_SET_NCHANNELS
,
&
pt
->
channels
);
ms_filter_call_method
(
stream
->
ms
.
decoder
,
MS_FILTER_SET_SAMPLE_RATE
,
&
pt
->
clock
_rate
);
ms_filter_call_method
(
stream
->
ms
.
decoder
,
MS_FILTER_SET_SAMPLE_RATE
,
&
sample
_rate
);
ms_filter_call_method
(
stream
->
ms
.
decoder
,
MS_FILTER_SET_NCHANNELS
,
&
pt
->
channels
);
if
(
pt
->
send_fmtp
!=
NULL
)
ms_filter_call_method
(
stream
->
ms
.
encoder
,
MS_FILTER_ADD_FMTP
,
(
void
*
)
pt
->
send_fmtp
);
if
(
pt
->
recv_fmtp
!=
NULL
)
ms_filter_call_method
(
stream
->
ms
.
decoder
,
MS_FILTER_ADD_FMTP
,(
void
*
)
pt
->
recv_fmtp
);
/*create the equalizer*/
if
((
stream
->
features
&
AUDIO_STREAM_FEATURE_EQUALIZER
)
!=
0
)
if
((
stream
->
features
&
AUDIO_STREAM_FEATURE_EQUALIZER
)
!=
0
)
{
stream
->
equalizer
=
ms_filter_new
(
MS_EQUALIZER_ID
);
else
if
(
stream
->
equalizer
)
{
tmp
=
stream
->
eq_active
;
ms_filter_call_method
(
stream
->
equalizer
,
MS_EQUALIZER_SET_ACTIVE
,
&
tmp
);
}
}
else
stream
->
equalizer
=
NULL
;
if
(
stream
->
equalizer
)
{
tmp
=
stream
->
eq_active
;
ms_filter_call_method
(
stream
->
equalizer
,
MS_EQUALIZER_SET_ACTIVE
,
&
tmp
);
}
/*configure resampler if needed*/
ms_filter_call_method
(
stream
->
ms
.
rtpsend
,
MS_FILTER_SET_NCHANNELS
,
&
pt
->
channels
);
...
...
@@ -440,6 +464,8 @@ int audio_stream_start_full(AudioStream *stream, RtpProfile *profile, const char
ms_connection_helper_link
(
&
h
,
stream
->
volsend
,
0
,
0
);
if
(
stream
->
dtmfgen_rtp
)
ms_connection_helper_link
(
&
h
,
stream
->
dtmfgen_rtp
,
0
,
0
);
if
(
stream
->
send_tee
)
ms_connection_helper_link
(
&
h
,
stream
->
send_tee
,
0
,
0
);
ms_connection_helper_link
(
&
h
,
stream
->
ms
.
encoder
,
0
,
0
);
ms_connection_helper_link
(
&
h
,
stream
->
ms
.
rtpsend
,
0
,
-
1
);
...
...
@@ -447,12 +473,14 @@ int audio_stream_start_full(AudioStream *stream, RtpProfile *profile, const char
ms_connection_helper_start
(
&
h
);
ms_connection_helper_link
(
&
h
,
stream
->
ms
.
rtprecv
,
-
1
,
0
);
ms_connection_helper_link
(
&
h
,
stream
->
ms
.
decoder
,
0
,
0
);
if
(
stream
->
plc
)
if
(
stream
->
plc
)
ms_connection_helper_link
(
&
h
,
stream
->
plc
,
0
,
0
);
if
(
stream
->
dtmfgen
)
ms_connection_helper_link
(
&
h
,
stream
->
dtmfgen
,
0
,
0
);
if
(
stream
->
volrecv
)
ms_connection_helper_link
(
&
h
,
stream
->
volrecv
,
0
,
0
);
if
(
stream
->
recv_tee
)
ms_connection_helper_link
(
&
h
,
stream
->
recv_tee
,
0
,
0
);
if
(
stream
->
equalizer
)
ms_connection_helper_link
(
&
h
,
stream
->
equalizer
,
0
,
0
);
if
(
stream
->
ec
)
...
...
@@ -461,6 +489,13 @@ int audio_stream_start_full(AudioStream *stream, RtpProfile *profile, const char
ms_connection_helper_link
(
&
h
,
stream
->
write_resampler
,
0
,
0
);
ms_connection_helper_link
(
&
h
,
stream
->
soundwrite
,
0
,
-
1
);
/*call recording part, attached to both outgoing and incoming graphs*/
if
(
stream
->
recorder
){
ms_filter_link
(
stream
->
send_tee
,
1
,
stream
->
recorder_mixer
,
0
);
ms_filter_link
(
stream
->
recv_tee
,
1
,
stream
->
recorder_mixer
,
1
);
ms_filter_link
(
stream
->
recorder_mixer
,
0
,
stream
->
recorder
,
0
);
}
/*to make sure all preprocess are done before befre processing audio*/
ms_ticker_attach_multiple
(
stream
->
ms
.
ticker
,
stream
->
soundread
...
...
@@ -543,6 +578,51 @@ void audio_stream_record(AudioStream *st, const char *name){
}
}
int
audio_stream_mixed_record_open
(
AudioStream
*
st
,
const
char
*
filename
){
if
(
!
(
st
->
features
&
AUDIO_STREAM_FEATURE_MIXED_RECORDING
)){
if
(
audio_stream_started
(
st
)){
ms_error
(
"Too late - you cannot request a mixed recording when the stream is running because it did not have AUDIO_STREAM_FEATURE_MIXED_RECORDING feature."
);
return
-
1
;
}
else
{
st
->
features
|=
AUDIO_STREAM_FEATURE_MIXED_RECORDING
;
}
}
if
(
st
->
recorder_file
){
audio_stream_mixed_record_stop
(
st
);
}
st
->
recorder_file
=
filename
?
ms_strdup
(
filename
)
:
NULL
;
return
0
;
}
int
audio_stream_mixed_record_start
(
AudioStream
*
st
){
if
(
st
->
recorder
&&
st
->
recorder_file
){
int
pin
=
1
;
MSRecorderState
state
;
ms_filter_call_method
(
st
->
recorder
,
MS_RECORDER_GET_STATE
,
&
state
);
if
(
state
==
MSRecorderClosed
){
if
(
ms_filter_call_method
(
st
->
recorder
,
MS_RECORDER_OPEN
,
st
->
recorder_file
)
==-
1
)
return
-
1
;
}
ms_filter_call_method_noarg
(
st
->
recorder
,
MS_RECORDER_START
);
ms_filter_call_method
(
st
->
recv_tee
,
MS_TEE_UNMUTE
,
&
pin
);
ms_filter_call_method
(
st
->
send_tee
,
MS_TEE_UNMUTE
,
&
pin
);
return
0
;
}
return
-
1
;
}
int
audio_stream_mixed_record_stop
(
AudioStream
*
st
){
if
(
st
->
recorder
&&
st
->
recorder_file
){
int
pin
=
1
;
ms_filter_call_method_noarg
(
st
->
recorder
,
MS_RECORDER_PAUSE
);
ms_filter_call_method
(
st
->
recv_tee
,
MS_TEE_MUTE
,
&
pin
);
ms_filter_call_method
(
st
->
send_tee
,
MS_TEE_MUTE
,
&
pin
);
ms_filter_call_method_noarg
(
st
->
recorder
,
MS_RECORDER_CLOSE
);
}
return
0
;
}
uint32_t
audio_stream_get_features
(
AudioStream
*
st
){
return
st
->
features
;
}
...
...
@@ -632,8 +712,6 @@ void audio_stream_enable_noise_gate(AudioStream *stream, bool_t val){
}
else
{
ms_warning
(
"cannot set noise gate mode to [%i] because no volume send"
,
val
);
}
}
void
audio_stream_set_mic_gain
(
AudioStream
*
stream
,
float
gain
){
...
...
@@ -691,6 +769,8 @@ void audio_stream_stop(AudioStream * stream)
ms_connection_helper_unlink
(
&
h
,
stream
->
volsend
,
0
,
0
);
if
(
stream
->
dtmfgen_rtp
)
ms_connection_helper_unlink
(
&
h
,
stream
->
dtmfgen_rtp
,
0
,
0
);
if
(
stream
->
send_tee
)
ms_connection_helper_unlink
(
&
h
,
stream
->
send_tee
,
0
,
0
);
ms_connection_helper_unlink
(
&
h
,
stream
->
ms
.
encoder
,
0
,
0
);
ms_connection_helper_unlink
(
&
h
,
stream
->
ms
.
rtpsend
,
0
,
-
1
);
...
...
@@ -704,6 +784,8 @@ void audio_stream_stop(AudioStream * stream)
ms_connection_helper_unlink
(
&
h
,
stream
->
dtmfgen
,
0
,
0
);
if
(
stream
->
volrecv
!=
NULL
)
ms_connection_helper_unlink
(
&
h
,
stream
->
volrecv
,
0
,
0
);
if
(
stream
->
recv_tee
)
ms_connection_helper_unlink
(
&
h
,
stream
->
recv_tee
,
0
,
0
);
if
(
stream
->
equalizer
!=
NULL
)
ms_connection_helper_unlink
(
&
h
,
stream
->
equalizer
,
0
,
0
);
if
(
stream
->
ec
!=
NULL
)
...
...
@@ -711,6 +793,13 @@ void audio_stream_stop(AudioStream * stream)
if
(
stream
->
write_resampler
!=
NULL
)
ms_connection_helper_unlink
(
&
h
,
stream
->
write_resampler
,
0
,
0
);
ms_connection_helper_unlink
(
&
h
,
stream
->
soundwrite
,
0
,
-
1
);
/*dismantle the call recording */
if
(
stream
->
recorder
){
ms_filter_unlink
(
stream
->
send_tee
,
1
,
stream
->
recorder_mixer
,
0
);
ms_filter_unlink
(
stream
->
recv_tee
,
1
,
stream
->
recorder_mixer
,
1
);
ms_filter_unlink
(
stream
->
recorder_mixer
,
0
,
stream
->
recorder
,
0
);
}
}
}