~ubuntu-branches/ubuntu/wily/kopete/wily-proposed

« back to all changes in this revision

Viewing changes to protocols/jabber/libjingle/talk/session/phone/linphonemediaengine.cc

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell, José Manuel Santamaría Lema, Jonathan Riddell
  • Date: 2015-08-18 10:50:51 UTC
  • mfrom: (1.1.30)
  • Revision ID: package-import@ubuntu.com-20150818105051-dlphtsk2m0d8rvjh
Tags: 4:15.07.90-0ubuntu1
[ José Manuel Santamaría Lema ]
* Build depend on libboost-dev instead of libboost1.55-dev. Right now the
  default is libboost1.58-dev so if we don't change this the package may be
  unable to build.

[ Jonathan Riddell ]
* new upstream beta release

Show diffs side-by-side

added added

removed removed

Lines of Context:
69
69
  free(path);
70
70
#endif
71
71
 
72
 
  if (ms_filter_codec_supported("iLBC"))
73
 
    have_ilbc = true;
74
 
  else
75
 
    have_ilbc = false;
76
 
 
77
 
  if (ms_filter_codec_supported("speex"))
78
 
    have_speex = true;
79
 
  else
80
 
    have_speex = false;
81
 
 
82
 
  if (ms_filter_codec_supported("gsm"))
83
 
    have_gsm = true;
84
 
  else
85
 
    have_gsm = false;
 
72
  have_ilbc = ms_filter_codec_supported("iLBC");
 
73
  have_speex = ms_filter_codec_supported("speex");
 
74
  have_gsm = ms_filter_codec_supported("gsm");
86
75
 
87
76
  if (have_speex) {
88
77
    voice_codecs_.push_back(AudioCodec(110, payload_type_speex_wb.mime_type, payload_type_speex_wb.clock_rate, 0, 1, 8));
122
111
bool LinphoneMediaEngine::FindAudioCodec(const AudioCodec &c) {
123
112
  if (c.id == 0)
124
113
    return true;
125
 
  if (c.name == payload_type_telephone_event.mime_type)
126
 
    return true;
127
 
  if (have_speex && c.name == payload_type_speex_wb.mime_type && c.clockrate == payload_type_speex_wb.clock_rate)
128
 
    return true;
129
 
  if (have_speex && c.name == payload_type_speex_nb.mime_type && c.clockrate == payload_type_speex_nb.clock_rate)
130
 
    return true;
131
 
  if (have_ilbc && c.name == payload_type_ilbc.mime_type)
132
 
    return true;
133
 
  if (have_gsm && c.name == payload_type_gsm.mime_type)
 
114
  if (stricmp(c.name.c_str(), payload_type_telephone_event.mime_type) == 0)
 
115
    return true;
 
116
  if (have_speex && stricmp(c.name.c_str(), payload_type_speex_wb.mime_type) == 0 && c.clockrate == payload_type_speex_wb.clock_rate)
 
117
    return true;
 
118
  if (have_speex && stricmp(c.name.c_str(), payload_type_speex_nb.mime_type) == 0 && c.clockrate == payload_type_speex_nb.clock_rate)
 
119
    return true;
 
120
  if (have_ilbc && stricmp(c.name.c_str(), payload_type_ilbc.mime_type) == 0)
 
121
    return true;
 
122
  if (have_gsm && stricmp(c.name.c_str(), payload_type_gsm.mime_type) == 0)
134
123
    return true;
135
124
  return false;
136
125
}
141
130
///////////////////////////////////////////////////////////////////////////
142
131
LinphoneVoiceChannel::LinphoneVoiceChannel(LinphoneMediaEngine*eng)
143
132
    : pt_(-1),
144
 
      audio_stream_(0),
 
133
      profile_(false),
145
134
      engine_(eng),
146
135
      ring_stream_(0)
147
136
{
148
137
 
149
138
  talk_base::Thread *thread = talk_base::ThreadManager::Instance()->CurrentThread();
150
139
  talk_base::SocketServer *ss = thread->socketserver();
 
140
 
151
141
  socket_.reset(ss->CreateAsyncSocket(SOCK_DGRAM));
152
 
 
153
142
  socket_->Bind(talk_base::SocketAddress("localhost", 0)); /* 0 means that OS will choose some free port */
154
 
  port1 = socket_->GetLocalAddress().port(); /* and here we get port choosed by OS */
155
 
  port2 = PORT_UNUSED;
 
143
  captport = socket_->GetLocalAddress().port(); /* and here we get port choosed by OS */
156
144
  socket_->SignalReadEvent.connect(this, &LinphoneVoiceChannel::OnIncomingData);
157
145
 
 
146
  socketRtcp_.reset(ss->CreateAsyncSocket(SOCK_DGRAM));
 
147
  socketRtcp_->Bind(talk_base::SocketAddress("localhost", captport+1));
 
148
  socketRtcp_->SignalReadEvent.connect(this, &LinphoneVoiceChannel::OnIncomingRtcp);
 
149
 
 
150
  playport = PORT_UNUSED;
 
151
  playport2 = PORT_UNUSED;
 
152
 
 
153
#ifdef _DEBUG
 
154
  ortp_set_log_level_mask(ORTP_DEBUG|ORTP_MESSAGE|ORTP_WARNING|ORTP_ERROR|ORTP_FATAL);
 
155
#else
 
156
  ortp_set_log_level_mask(ORTP_FATAL);
 
157
#endif
 
158
 
 
159
#ifdef MEDIASTREAMER_LESS_2_9
 
160
  audio_stream_ = audio_stream_new(-1, 0); /* -1 means that function will choose some free port */
 
161
#else
 
162
  audio_stream_ = audio_stream_new(-1, -1, 0); /* -1 means that function will choose some free port */
 
163
#endif
 
164
 
158
165
}
159
166
 
160
167
LinphoneVoiceChannel::~LinphoneVoiceChannel()
161
168
{
162
169
  fflush(stdout);
163
170
  StopRing();
164
 
 
165
 
  if (audio_stream_)
166
 
    audio_stream_stop(audio_stream_);
 
171
  audio_stream_stop(audio_stream_);
167
172
}
168
173
 
169
174
bool LinphoneVoiceChannel::SetPlayout(bool playout) {
181
186
}
182
187
#endif
183
188
 
 
189
#if defined(MEDIASTREAMER_LESS_2_11) && !defined(MEDIASTREAMER_LESS_2_9)
 
190
static inline int rtp_session_get_local_rtcp_port(const RtpSession *session) {
 
191
  return (session->rtcp.loc_port>0) ? session->rtcp.loc_port : -1;
 
192
}
 
193
#endif
 
194
 
184
195
bool LinphoneVoiceChannel::SetSendCodecs(const std::vector<AudioCodec>& codecs) {
185
196
 
186
 
  bool first = true;
187
 
  std::vector<AudioCodec>::const_iterator i;
188
 
 
189
 
  ortp_set_log_level_mask(ORTP_MESSAGE|ORTP_WARNING|ORTP_ERROR|ORTP_FATAL);
190
 
 
191
 
  for (i = codecs.begin(); i < codecs.end(); i++) {
192
 
 
193
 
    if (!engine_->FindAudioCodec(*i))
194
 
      continue;
195
 
    if (engine_->have_ilbc && i->name == payload_type_ilbc.mime_type) {
 
197
  std::vector<AudioCodec>::const_iterator i;
 
198
 
 
199
  pt_ = -1;
 
200
 
 
201
  for (i = codecs.begin(); i < codecs.end(); i++) {
 
202
 
 
203
    if (!engine_->FindAudioCodec(*i)) {
 
204
      LOG(LS_INFO) << "Codec " << i->name << "/" << i->clockrate << " is not supported";
 
205
      continue;
 
206
    }
 
207
 
 
208
    LOG(LS_INFO) << "Using " << i->name << "/" << i->clockrate;
 
209
    pt_ = i->id;
 
210
    break;
 
211
 
 
212
  }
 
213
 
 
214
  if (pt_ == -1) {
 
215
    // We're being asked to set an empty list of codecs. This will only happen when
 
216
    // working with a buggy client; let's try PCMU.
 
217
    LOG(LS_WARNING) << "Received empty list of codces; using PCMU/8000";
 
218
    pt_ = 0;
 
219
  }
 
220
 
 
221
  if (pt_ != -1 && profile_ && playport == PORT_UNUSED)
 
222
    StartCall();
 
223
 
 
224
  return true;
 
225
 
 
226
}
 
227
 
 
228
bool LinphoneVoiceChannel::SetRecvCodecs(const std::vector<AudioCodec>& codecs) {
 
229
 
 
230
  std::vector<AudioCodec>::const_iterator i;
 
231
 
 
232
  profile_ = false;
 
233
 
 
234
  for (i = codecs.begin(); i < codecs.end(); i++) {
 
235
 
 
236
    if (!engine_->FindAudioCodec(*i)) {
 
237
      LOG(LS_INFO) << "Codec " << i->name << "/" << i->clockrate << " is not supported";
 
238
      continue;
 
239
    }
 
240
 
 
241
    if (engine_->have_ilbc && stricmp(i->name.c_str(), payload_type_ilbc.mime_type) == 0)
196
242
      rtp_profile_set_payload(&av_profile, i->id, &payload_type_ilbc);
197
 
    } else if (engine_->have_speex && i->name == payload_type_speex_wb.mime_type && i->clockrate == payload_type_speex_wb.clock_rate) {
 
243
    else if (engine_->have_speex && stricmp(i->name.c_str(), payload_type_speex_wb.mime_type) == 0 && i->clockrate == payload_type_speex_wb.clock_rate)
198
244
      rtp_profile_set_payload(&av_profile, i->id, &payload_type_speex_wb);
199
 
    } else if (engine_->have_speex && i->name == payload_type_speex_nb.mime_type && i->clockrate == payload_type_speex_nb.clock_rate) {
 
245
    else if (engine_->have_speex && stricmp(i->name.c_str(), payload_type_speex_nb.mime_type) == 0 && i->clockrate == payload_type_speex_nb.clock_rate)
200
246
      rtp_profile_set_payload(&av_profile, i->id, &payload_type_speex_nb);
201
 
    } else if (engine_->have_gsm && i->name == payload_type_gsm.mime_type) {
 
247
    else if (engine_->have_gsm && stricmp(i->name.c_str(), payload_type_gsm.mime_type) == 0)
202
248
      rtp_profile_set_payload(&av_profile, i->id, &payload_type_gsm);
203
 
    } else if (i->name == payload_type_telephone_event.mime_type) {
 
249
    else if (stricmp(i->name.c_str(), payload_type_telephone_event.mime_type) == 0)
204
250
      rtp_profile_set_payload(&av_profile, i->id, &payload_type_telephone_event);
205
 
    } else if (i->id == 0)
 
251
    else if (i->id == 0)
206
252
      rtp_profile_set_payload(&av_profile, 0, &payload_type_pcmu8000);
207
253
 
208
 
    if (first) {
209
 
      StopRing();
210
 
      LOG(LS_INFO) << "Using " << i->name << "/" << i->clockrate;
211
 
      pt_ = i->id;
212
 
      audio_stream_ = audio_stream_start(&av_profile, -1, "localhost", port1, i->id, 250, 0); /* -1 means that function will choose some free port */
213
 
      port2 = rtp_session_get_local_port(audio_stream_get_rtp_session(audio_stream_));
214
 
      first = false;
215
 
    }
 
254
    LOG(LS_INFO) << "Accepting " << i->name << "/" << i->clockrate;
 
255
    profile_ = true;
 
256
 
216
257
  }
217
258
 
218
 
  if (first) {
219
 
    StopRing();
 
259
  if (!profile_) {
220
260
    // We're being asked to set an empty list of codecs. This will only happen when
221
261
    // working with a buggy client; let's try PCMU.
222
 
    LOG(LS_WARNING) << "Received empty list of codces; using PCMU/8000";
223
 
    audio_stream_ = audio_stream_start(&av_profile, -1, "localhost", port1, 0, 250, 0); /* -1 means that function will choose some free port */
224
 
    port2 = rtp_session_get_local_port(audio_stream_get_rtp_session(audio_stream_));
 
262
    LOG(LS_WARNING) << "Received empty list of codces; accepting PCMU/8000";
 
263
    rtp_profile_set_payload(&av_profile, 0, &payload_type_pcmu8000);
 
264
    profile_ = true;
225
265
  }
226
266
 
 
267
  if (pt_ != -1 && profile_ && playport == PORT_UNUSED)
 
268
    StartCall();
 
269
 
 
270
  return true;
 
271
}
 
272
 
 
273
bool LinphoneVoiceChannel::StartCall()
 
274
{
 
275
  StopRing();
 
276
 
 
277
  MSSndCard *playcard = ms_snd_card_manager_get_default_playback_card(ms_snd_card_manager_get());
 
278
  if (!playcard)
 
279
    return false;
 
280
 
 
281
  MSSndCard *captcard = ms_snd_card_manager_get_default_capture_card(ms_snd_card_manager_get());
 
282
  if (!captcard)
 
283
    return false;
 
284
 
 
285
  if (audio_stream_start_now(audio_stream_, &av_profile, "localhost", captport, captport+1, pt_, 250, playcard, captcard, 0))
 
286
    return false;
 
287
 
 
288
  playport = rtp_session_get_local_port(audio_stream_get_rtp_session(audio_stream_));
 
289
 
 
290
#ifdef MEDIASTREAMER_LESS_2_9
 
291
  playport2 = playport+1;
 
292
#else
 
293
  playport2 = rtp_session_get_local_rtcp_port(audio_stream_get_rtp_session(audio_stream_));
 
294
#endif
 
295
 
 
296
  return true;
 
297
}
 
298
 
 
299
bool LinphoneVoiceChannel::AddSendStream(const cricket::StreamParams& st)
 
300
{
 
301
  LOG(LS_INFO) << "linphone:: SET send stream ssrc: " << st.first_ssrc();
 
302
  rtp_session_set_ssrc(audio_stream_get_rtp_session(audio_stream_), st.first_ssrc());
227
303
  return true;
228
304
}
229
305
 
230
306
bool LinphoneVoiceChannel::SetSend(SendFlags flag) {
231
 
  mute_ = !flag;
 
307
  mute_ = (flag == SEND_NOTHING);
 
308
  audio_stream_mute_rtp(audio_stream_, mute_);
 
309
  return true;
 
310
}
 
311
 
 
312
bool LinphoneVoiceChannel::Mute(bool on) {
 
313
  mute_ = on;
 
314
  audio_stream_mute_rtp(audio_stream_, mute_);
232
315
  return true;
233
316
}
234
317
 
235
318
void LinphoneVoiceChannel::OnPacketReceived(talk_base::Buffer* packet) {
236
 
  const void* data = packet->data();
237
 
  int len = packet->length();
238
 
  uint8 buf[2048];
239
 
  memcpy(buf, data, len);
240
 
 
241
 
  if (port2 == PORT_UNUSED)
 
319
  if (playport == PORT_UNUSED)
242
320
    return;
243
321
 
244
322
  /* We may receive packets with payload type 13: comfort noise. Linphone can't
245
323
   * handle them, so let's ignore those packets.
246
324
   */
247
 
  int payloadtype = buf[1] & 0x7f;
 
325
  int payloadtype = ((const uint8*)packet->data())[1] & 0x7f;
248
326
  if (play_ && payloadtype != 13)
249
 
    socket_->SendTo(buf, len, talk_base::SocketAddress("localhost",port2));
 
327
    socket_->SendTo(packet->data(), packet->length(), talk_base::SocketAddress("localhost", playport));
 
328
}
 
329
 
 
330
void LinphoneVoiceChannel::OnRtcpReceived(talk_base::Buffer* packet) {
 
331
  if (playport2 == PORT_UNUSED)
 
332
    return;
 
333
  socketRtcp_->SendTo(packet->data(), packet->length(), talk_base::SocketAddress("localhost", playport2));
250
334
}
251
335
 
252
336
void LinphoneVoiceChannel::StartRing(bool bIncomingCall)
284
368
 
285
369
void LinphoneVoiceChannel::OnIncomingData(talk_base::AsyncSocket *s)
286
370
{
287
 
  char *buf[2048];
288
 
  int len;
289
 
  len = s->Recv(buf, sizeof(buf));
 
371
  char buf[2048];
 
372
  int len = s->Recv(buf, sizeof(buf));
290
373
  talk_base::Buffer packet(buf, len, sizeof(buf));
291
374
  if (network_interface_ && !mute_)
292
375
    network_interface_->SendPacket(&packet);
293
376
}
294
377
 
 
378
void LinphoneVoiceChannel::OnIncomingRtcp(talk_base::AsyncSocket *s)
 
379
{
 
380
  char buf[2048];
 
381
  int len = s->Recv(buf, sizeof(buf));
 
382
  talk_base::Buffer packet(buf, len, sizeof(buf));
 
383
  if (network_interface_)
 
384
    network_interface_->SendRtcp(&packet);
 
385
}
 
386
 
295
387
}
296
388
 
297
389
#endif // HAVE_LINPHONE