1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
|
/*
Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com>
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, see <https://www.gnu.org/licenses/>.
*/
#ifndef _AUDIO_TX_H
#define _AUDIO_TX_H
// Receive RTP and send audio to soundcard
#include <map>
#include <string>
#include "audio_codecs.h"
#include "audio_decoder.h"
#include "audio_rx.h"
#include "media_buffer.h"
#include "rtp_telephone_event.h"
#include "user.h"
#include "threads/mutex.h"
#include "audio_device.h"
#include "twinkle_rtp_session.h"
#include "twinkle_config.h"
#ifdef HAVE_GSM
#include <gsm/gsm.h>
#else
#include "gsm/inc/gsm.h"
#endif
using namespace std;
using namespace ost;
// Forward declarations
class t_audio_session;
class t_line;
class t_audio_tx {
private:
// audio_session owning this audio transmitter
t_audio_session *audio_session;
// User profile of user using the line
// This is a pointer to the user_config owned by a phone user.
// So this pointer should never be deleted.
t_user *user_config;
// file descriptor audio capture device
t_audio_io *playback_device;
t_twinkle_rtp_session *rtp_session;
// Indicates if this transmitter is part of a 3-way conference
bool is_3way;
// Indicates if this transmitter is the mixer in a 3-way conference.
// The mixer will mix this audio stream with the audio from the other
// party and send it to the soundcard.
// If the transmitter is part of a 3-way conference, but not the
// mixer, then it simply has to send its audio payload to the mixer.
bool is_3way_mixer;
// Media buffer for media from the other far-end. This buffer is
// used by the mixer.
t_media_buffer *media_3way_peer_tx;
// The peer audio transmitter in a 3-way conference
t_audio_tx *peer_tx_3way;
// The audio receiver that needs input from this transmitter in
// a 3-way conference.
t_audio_rx *peer_rx_3way;
// Buffer for mixing purposes in 3-way conference.
unsigned char *mix_buf_3way;
// Mutex to protect 3-way resources
t_mutex mtx_3way;
// Codec information
t_audio_codec codec;
map<unsigned short, t_audio_codec> payload2codec;
unsigned short ptime; // in milliseconds
// Sample rate of sound card.
// The sample rate of the sound card is set to the sample rate
// used for the initial codec. The far end may dynamically switch
// to a codec with another sample rate. This will not change the
// sample rate of the sound card! (capture and playback cannot
// be done at different sampling rates).
unsigned short sc_sample_rate;
// Mapping from codecs to decoders
map<t_audio_codec, t_audio_decoder *> map_audio_decoder;
// Buffer to store PCM samples of a received RTP packet
unsigned char *sample_buf;
// Jitter buffer (PCM).
// jitter_buf_len indicates the number of bytes in the jitter buffer.
// At the start of playing the samples are stored in the jitter buffer.
// Once the buffer is full, all samples are copied to the memory of
// the soundcard. From that point the soundcard itself is the jitter
// buffer.
unsigned char *jitter_buf;
unsigned short jitter_buf_len;
bool load_jitter_buf;
// Buffer to keep last played packets for concealment.
unsigned char *conceal_buf[MAX_CONCEALMENT];
unsigned short conceal_buflen[MAX_CONCEALMENT]; // length of packet
short conceal_pos; // points to the oldest packet.
short conceal_num; // number of retained packets.
unsigned short soundcard_buf_size;
// Payload type for telephone-event payload.
// Some endpoints ignore the payload type that was sent in an
// outgoing INVITE and simply sends it with the payload type,
// they indicated in the 200 OK. Accept both payloads for
// interoperability.
int pt_telephone_event;
int pt_telephone_event_alt;
// Timestamp of previous DTMF tone
unsigned long dtmf_previous_timestamp;
// Inidicates if the playing thread is running
volatile bool is_running;
// The thread exits when this indicator is set to true
volatile bool stop_running;
// Retain a packet (PCM encoded) for possible concealment.
void retain_for_concealment(unsigned char *buf, unsigned short len);
// Play last num packets again.
void conceal(short num);
// Erase concealment buffers.
void clear_conceal_buf(void);
// Play PCM encoded samples
// - only_3rd_party indicates if there is only 3rd_party audio available,
// i.e. due to jitter, packet loss or silence suppression
void play_pcm(unsigned char *buf, unsigned short len, bool only_3rd_party = false);
public:
// Create the audio transmitter
// _fd file descriptor of capture device
// _rtp_session RTP socket tp send the RTP stream
// _codec audio codec to use
// _ptime length of the audio packets in ms
// _ptime = 0 means use default ptime value for the codec
t_audio_tx(t_audio_session *_audio_session, t_audio_io *_playback_device,
t_twinkle_rtp_session *_rtp_session,
t_audio_codec _codec,
const map<unsigned short, t_audio_codec> &_payload2codec,
unsigned short _ptime = 0);
~t_audio_tx();
// Set the is running flag
void set_running(bool running);
void run(void);
// Set the dynamic payload type for telephone events
void set_pt_telephone_event(int pt, int pt_alt);
// Get phone line belonging to this audio transmitter
t_line *get_line(void) const;
// Join this transmitter in a 3way conference.
// mixer indicates if this transmitter must be the mixer.
// - peer_tx is the peer transmitter in a 3-way
// - audio_rx is the audio receiver needing the output from this
// transmitter for mixing.
void join_3way(bool mixer, t_audio_tx *peer_tx, t_audio_rx *peer_rx);
// Change the peer rx/tx (NULL to erase)
void set_peer_tx_3way(t_audio_tx *peer_tx);
void set_peer_rx_3way(t_audio_rx *peer_rx);
// Change the mixer role
void set_mixer_3way(bool mixer);
// Stop the 3-way conference and make it a 1-on-1 call again.
void stop_3way(void);
// Post media from the peer transmitter for a 3-way mixer.
void post_media_peer_tx_3way(unsigned char *media, int len,
unsigned short peer_sample_rate);
// Returns if this transmitter is the mixer in a 3-way
bool get_is_3way_mixer(void) const;
};
#endif
|