1 /*
2 * libjingle
3 * Copyright 2004 Google Inc.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #include <string>
29 #include "talk/media/base/constants.h"
30 #include "talk/media/base/screencastid.h"
31 #include "talk/p2p/base/parsing.h"
32 #include "talk/session/media/call.h"
33 #include "talk/session/media/currentspeakermonitor.h"
34 #include "talk/session/media/mediasessionclient.h"
35 #include "webrtc/base/helpers.h"
36 #include "webrtc/base/logging.h"
37 #include "webrtc/base/thread.h"
38 #include "webrtc/base/window.h"
39
40 namespace cricket {
41
42 const uint32 MSG_CHECKAUTODESTROY = 1;
43 const uint32 MSG_TERMINATECALL = 2;
44 const uint32 MSG_PLAYDTMF = 3;
45
46 namespace {
47 const int kDTMFDelay = 300; // msec
48 const size_t kMaxDTMFDigits = 30;
49 const int kSendToVoicemailTimeout = 1000*20;
50 const int kNoVoicemailTimeout = 1000*180;
51 const int kMediaMonitorInterval = 1000*15;
52 // In order to be the same as the server-side switching, this must be 100.
53 const int kAudioMonitorPollPeriodMillis = 100;
54
55 // V is a pointer type.
56 template<class K, class V>
FindOrNull(const std::map<K,V> & map,const K & key)57 V FindOrNull(const std::map<K, V>& map,
58 const K& key) {
59 typename std::map<K, V>::const_iterator it = map.find(key);
60 return (it != map.end()) ? it->second : NULL;
61 }
62
63
ContentContainsCrypto(const cricket::ContentInfo * content)64 bool ContentContainsCrypto(const cricket::ContentInfo* content) {
65 if (content != NULL) {
66 const cricket::MediaContentDescription* desc =
67 static_cast<const cricket::MediaContentDescription*>(
68 content->description);
69 if (!desc || desc->cryptos().empty()) {
70 return false;
71 }
72 }
73 return true;
74 }
75
76 }
77
AudioSourceProxy(Call * call)78 AudioSourceProxy::AudioSourceProxy(Call* call)
79 : call_(call) {
80 call_->SignalAudioMonitor.connect(this, &AudioSourceProxy::OnAudioMonitor);
81 call_->SignalMediaStreamsUpdate.connect(
82 this, &AudioSourceProxy::OnMediaStreamsUpdate);
83 }
84
OnAudioMonitor(Call * call,const AudioInfo & info)85 void AudioSourceProxy::OnAudioMonitor(Call* call, const AudioInfo& info) {
86 SignalAudioMonitor(this, info);
87 }
88
OnMediaStreamsUpdate(Call * call,Session * session,const MediaStreams & added,const MediaStreams & removed)89 void AudioSourceProxy::OnMediaStreamsUpdate(Call* call, Session* session,
90 const MediaStreams& added, const MediaStreams& removed) {
91 SignalMediaStreamsUpdate(this, session, added, removed);
92 }
93
Call(MediaSessionClient * session_client)94 Call::Call(MediaSessionClient* session_client)
95 : id_(rtc::CreateRandomId()),
96 session_client_(session_client),
97 has_video_(false),
98 has_data_(false),
99 muted_(false),
100 video_muted_(false),
101 send_to_voicemail_(true),
102 playing_dtmf_(false) {
103 audio_source_proxy_.reset(new AudioSourceProxy(this));
104 }
105
~Call()106 Call::~Call() {
107 while (media_session_map_.begin() != media_session_map_.end()) {
108 Session* session = media_session_map_.begin()->second.session;
109 RemoveSession(session);
110 session_client_->session_manager()->DestroySession(session);
111 }
112 rtc::Thread::Current()->Clear(this);
113 }
114
InitiateSession(const buzz::Jid & to,const buzz::Jid & initiator,const CallOptions & options)115 Session* Call::InitiateSession(const buzz::Jid& to,
116 const buzz::Jid& initiator,
117 const CallOptions& options) {
118 std::string id;
119 std::string initiator_name = initiator.Str();
120 return InternalInitiateSession(id, to, initiator_name, options);
121 }
122
InitiateSession(const std::string & id,const buzz::Jid & to,const CallOptions & options)123 Session *Call::InitiateSession(const std::string& id,
124 const buzz::Jid& to,
125 const CallOptions& options) {
126 std::string initiator_name;
127 return InternalInitiateSession(id, to, initiator_name, options);
128 }
129
IncomingSession(Session * session,const SessionDescription * offer)130 void Call::IncomingSession(Session* session, const SessionDescription* offer) {
131 AddSession(session, offer);
132
133 // Make sure the session knows about the incoming ssrcs. This needs to be done
134 // prior to the SignalSessionState call, because that may trigger handling of
135 // these new SSRCs, so they need to be registered before then.
136 UpdateRemoteMediaStreams(session, offer->contents(), false);
137
138 // Missed the first state, the initiate, which is needed by
139 // call_client.
140 SignalSessionState(this, session, Session::STATE_RECEIVEDINITIATE);
141 }
142
AcceptSession(Session * session,const cricket::CallOptions & options)143 void Call::AcceptSession(Session* session,
144 const cricket::CallOptions& options) {
145 MediaSessionMap::iterator it = media_session_map_.find(session->id());
146 if (it != media_session_map_.end()) {
147 const SessionDescription* answer = session_client_->CreateAnswer(
148 session->remote_description(), options);
149 it->second.session->Accept(answer);
150 }
151 }
152
RejectSession(Session * session)153 void Call::RejectSession(Session* session) {
154 // Assume polite decline.
155 MediaSessionMap::iterator it = media_session_map_.find(session->id());
156 if (it != media_session_map_.end())
157 it->second.session->Reject(STR_TERMINATE_DECLINE);
158 }
159
TerminateSession(Session * session)160 void Call::TerminateSession(Session* session) {
161 MediaSessionMap::iterator it = media_session_map_.find(session->id());
162 if (it != media_session_map_.end()) {
163 // Assume polite terminations.
164 it->second.session->Terminate();
165 }
166 }
167
Terminate()168 void Call::Terminate() {
169 // Copy the list so that we can iterate over it in a stable way
170 std::vector<Session*> sessions = this->sessions();
171
172 // There may be more than one session to terminate
173 std::vector<Session*>::iterator it;
174 for (it = sessions.begin(); it != sessions.end(); ++it) {
175 TerminateSession(*it);
176 }
177 }
178
SendViewRequest(Session * session,const ViewRequest & view_request)179 bool Call::SendViewRequest(Session* session,
180 const ViewRequest& view_request) {
181 StaticVideoViews::const_iterator it;
182 for (it = view_request.static_video_views.begin();
183 it != view_request.static_video_views.end(); ++it) {
184 StreamParams found_stream;
185 bool found = false;
186 MediaStreams* recv_streams = GetMediaStreams(session);
187 if (recv_streams)
188 found = recv_streams->GetVideoStream(it->selector, &found_stream);
189 if (!found) {
190 LOG(LS_WARNING) << "Trying to send view request for ("
191 << it->selector.ssrc << ", '"
192 << it->selector.groupid << "', '"
193 << it->selector.streamid << "'"
194 << ") is not in the local streams.";
195 return false;
196 }
197 }
198
199 XmlElements elems;
200 WriteError error;
201 if (!WriteJingleViewRequest(CN_VIDEO, view_request, &elems, &error)) {
202 LOG(LS_ERROR) << "Couldn't write out view request: " << error.text;
203 return false;
204 }
205
206 return session->SendInfoMessage(elems, session->remote_name());
207 }
208
SetVideoRenderer(Session * session,uint32 ssrc,VideoRenderer * renderer)209 void Call::SetVideoRenderer(Session* session, uint32 ssrc,
210 VideoRenderer* renderer) {
211 VideoChannel* video_channel = GetVideoChannel(session);
212 if (video_channel) {
213 video_channel->SetRenderer(ssrc, renderer);
214 LOG(LS_INFO) << "Set renderer of ssrc " << ssrc
215 << " to " << renderer << ".";
216 } else {
217 LOG(LS_INFO) << "Failed to set renderer of ssrc " << ssrc << ".";
218 }
219 }
220
OnMessage(rtc::Message * message)221 void Call::OnMessage(rtc::Message* message) {
222 switch (message->message_id) {
223 case MSG_CHECKAUTODESTROY:
224 // If no more sessions for this call, delete it
225 if (media_session_map_.empty())
226 session_client_->DestroyCall(this);
227 break;
228 case MSG_TERMINATECALL:
229 // Signal to the user that a timeout has happened and the call should
230 // be sent to voicemail.
231 if (send_to_voicemail_) {
232 SignalSetupToCallVoicemail();
233 }
234
235 // Callee didn't answer - terminate call
236 Terminate();
237 break;
238 case MSG_PLAYDTMF:
239 ContinuePlayDTMF();
240 }
241 }
242
sessions()243 std::vector<Session*> Call::sessions() {
244 std::vector<Session*> sessions;
245 MediaSessionMap::iterator it;
246 for (it = media_session_map_.begin(); it != media_session_map_.end(); ++it)
247 sessions.push_back(it->second.session);
248
249 return sessions;
250 }
251
AddSession(Session * session,const SessionDescription * offer)252 bool Call::AddSession(Session* session, const SessionDescription* offer) {
253 bool succeeded = true;
254 MediaSession media_session;
255 media_session.session = session;
256 media_session.voice_channel = NULL;
257 media_session.video_channel = NULL;
258 media_session.data_channel = NULL;
259 media_session.recv_streams = NULL;
260
261 const ContentInfo* audio_offer = GetFirstAudioContent(offer);
262 const ContentInfo* video_offer = GetFirstVideoContent(offer);
263 const ContentInfo* data_offer = GetFirstDataContent(offer);
264 has_video_ = (video_offer != NULL);
265 has_data_ = (data_offer != NULL);
266
267 ASSERT(audio_offer != NULL);
268 // Create voice channel and start a media monitor.
269 media_session.voice_channel =
270 session_client_->channel_manager()->CreateVoiceChannel(
271 session, audio_offer->name, has_video_);
272 // voice_channel can be NULL in case of NullVoiceEngine.
273 if (media_session.voice_channel) {
274 media_session.voice_channel->SignalMediaMonitor.connect(
275 this, &Call::OnMediaMonitor);
276 media_session.voice_channel->StartMediaMonitor(kMediaMonitorInterval);
277 } else {
278 succeeded = false;
279 }
280
281 // If desired, create video channel and start a media monitor.
282 if (has_video_ && succeeded) {
283 media_session.video_channel =
284 session_client_->channel_manager()->CreateVideoChannel(
285 session, video_offer->name, true, media_session.voice_channel);
286 // video_channel can be NULL in case of NullVideoEngine.
287 if (media_session.video_channel) {
288 media_session.video_channel->SignalMediaMonitor.connect(
289 this, &Call::OnMediaMonitor);
290 media_session.video_channel->StartMediaMonitor(kMediaMonitorInterval);
291 } else {
292 succeeded = false;
293 }
294 }
295
296 // If desired, create data channel.
297 if (has_data_ && succeeded) {
298 const DataContentDescription* data = GetFirstDataContentDescription(offer);
299 if (data == NULL) {
300 succeeded = false;
301 } else {
302 DataChannelType data_channel_type = DCT_RTP;
303 if ((data->protocol() == kMediaProtocolSctp) ||
304 (data->protocol() == kMediaProtocolDtlsSctp)) {
305 data_channel_type = DCT_SCTP;
306 }
307
308 bool rtcp = false;
309 media_session.data_channel =
310 session_client_->channel_manager()->CreateDataChannel(
311 session, data_offer->name, rtcp, data_channel_type);
312 if (media_session.data_channel) {
313 media_session.data_channel->SignalDataReceived.connect(
314 this, &Call::OnDataReceived);
315 } else {
316 succeeded = false;
317 }
318 }
319 }
320
321 if (succeeded) {
322 // Add session to list, create channels for this session.
323 media_session.recv_streams = new MediaStreams;
324 media_session_map_[session->id()] = media_session;
325 session->SignalState.connect(this, &Call::OnSessionState);
326 session->SignalError.connect(this, &Call::OnSessionError);
327 session->SignalInfoMessage.connect(
328 this, &Call::OnSessionInfoMessage);
329 session->SignalRemoteDescriptionUpdate.connect(
330 this, &Call::OnRemoteDescriptionUpdate);
331 session->SignalReceivedTerminateReason
332 .connect(this, &Call::OnReceivedTerminateReason);
333
334 // If this call has the focus, enable this session's channels.
335 if (session_client_->GetFocus() == this) {
336 EnableSessionChannels(session, true);
337 }
338
339 // Signal client.
340 SignalAddSession(this, session);
341 }
342
343 return succeeded;
344 }
345
RemoveSession(Session * session)346 void Call::RemoveSession(Session* session) {
347 MediaSessionMap::iterator it = media_session_map_.find(session->id());
348 if (it == media_session_map_.end())
349 return;
350
351 // Remove all the screencasts, if they haven't been already.
352 while (!it->second.started_screencasts.empty()) {
353 uint32 ssrc = it->second.started_screencasts.begin()->first;
354 if (!StopScreencastWithoutSendingUpdate(it->second.session, ssrc)) {
355 LOG(LS_ERROR) << "Unable to stop screencast with ssrc " << ssrc;
356 ASSERT(false);
357 }
358 }
359
360 // Destroy video channel
361 VideoChannel* video_channel = it->second.video_channel;
362 if (video_channel != NULL)
363 session_client_->channel_manager()->DestroyVideoChannel(video_channel);
364
365 // Destroy voice channel
366 VoiceChannel* voice_channel = it->second.voice_channel;
367 if (voice_channel != NULL)
368 session_client_->channel_manager()->DestroyVoiceChannel(voice_channel);
369
370 // Destroy data channel
371 DataChannel* data_channel = it->second.data_channel;
372 if (data_channel != NULL)
373 session_client_->channel_manager()->DestroyDataChannel(data_channel);
374
375 delete it->second.recv_streams;
376 media_session_map_.erase(it);
377
378 // Destroy speaker monitor
379 StopSpeakerMonitor(session);
380
381 // Signal client
382 SignalRemoveSession(this, session);
383
384 // The call auto destroys when the last session is removed
385 rtc::Thread::Current()->Post(this, MSG_CHECKAUTODESTROY);
386 }
387
GetVoiceChannel(Session * session) const388 VoiceChannel* Call::GetVoiceChannel(Session* session) const {
389 MediaSessionMap::const_iterator it = media_session_map_.find(session->id());
390 return (it != media_session_map_.end()) ? it->second.voice_channel : NULL;
391 }
392
GetVideoChannel(Session * session) const393 VideoChannel* Call::GetVideoChannel(Session* session) const {
394 MediaSessionMap::const_iterator it = media_session_map_.find(session->id());
395 return (it != media_session_map_.end()) ? it->second.video_channel : NULL;
396 }
397
GetDataChannel(Session * session) const398 DataChannel* Call::GetDataChannel(Session* session) const {
399 MediaSessionMap::const_iterator it = media_session_map_.find(session->id());
400 return (it != media_session_map_.end()) ? it->second.data_channel : NULL;
401 }
402
GetMediaStreams(Session * session) const403 MediaStreams* Call::GetMediaStreams(Session* session) const {
404 MediaSessionMap::const_iterator it = media_session_map_.find(session->id());
405 return (it != media_session_map_.end()) ? it->second.recv_streams : NULL;
406 }
407
EnableChannels(bool enable)408 void Call::EnableChannels(bool enable) {
409 MediaSessionMap::iterator it;
410 for (it = media_session_map_.begin(); it != media_session_map_.end(); ++it) {
411 EnableSessionChannels(it->second.session, enable);
412 }
413 }
414
EnableSessionChannels(Session * session,bool enable)415 void Call::EnableSessionChannels(Session* session, bool enable) {
416 MediaSessionMap::iterator it = media_session_map_.find(session->id());
417 if (it == media_session_map_.end())
418 return;
419
420 VoiceChannel* voice_channel = it->second.voice_channel;
421 VideoChannel* video_channel = it->second.video_channel;
422 DataChannel* data_channel = it->second.data_channel;
423 if (voice_channel != NULL)
424 voice_channel->Enable(enable);
425 if (video_channel != NULL)
426 video_channel->Enable(enable);
427 if (data_channel != NULL)
428 data_channel->Enable(enable);
429 }
430
Mute(bool mute)431 void Call::Mute(bool mute) {
432 muted_ = mute;
433 MediaSessionMap::iterator it;
434 for (it = media_session_map_.begin(); it != media_session_map_.end(); ++it) {
435 if (it->second.voice_channel != NULL)
436 it->second.voice_channel->MuteStream(0, mute);
437 }
438 }
439
MuteVideo(bool mute)440 void Call::MuteVideo(bool mute) {
441 video_muted_ = mute;
442 MediaSessionMap::iterator it;
443 for (it = media_session_map_.begin(); it != media_session_map_.end(); ++it) {
444 if (it->second.video_channel != NULL)
445 it->second.video_channel->MuteStream(0, mute);
446 }
447 }
448
SendData(Session * session,const SendDataParams & params,const rtc::Buffer & payload,SendDataResult * result)449 bool Call::SendData(Session* session,
450 const SendDataParams& params,
451 const rtc::Buffer& payload,
452 SendDataResult* result) {
453 DataChannel* data_channel = GetDataChannel(session);
454 if (!data_channel) {
455 LOG(LS_WARNING) << "Could not send data: no data channel.";
456 return false;
457 }
458
459 return data_channel->SendData(params, payload, result);
460 }
461
PressDTMF(int event)462 void Call::PressDTMF(int event) {
463 // Queue up this digit
464 if (queued_dtmf_.size() < kMaxDTMFDigits) {
465 LOG(LS_INFO) << "Call::PressDTMF(" << event << ")";
466
467 queued_dtmf_.push_back(event);
468
469 if (!playing_dtmf_) {
470 ContinuePlayDTMF();
471 }
472 }
473 }
474
ScreencastFormatFromFps(int fps)475 cricket::VideoFormat ScreencastFormatFromFps(int fps) {
476 // The capturer pretty much ignore this, but just in case we give it
477 // a resolution big enough to cover any expected desktop. In any
478 // case, it can't be 0x0, or the CaptureManager will fail to use it.
479 return cricket::VideoFormat(
480 1, 1,
481 cricket::VideoFormat::FpsToInterval(fps), cricket::FOURCC_ANY);
482 }
483
StartScreencast(Session * session,const std::string & streamid,uint32 ssrc,const ScreencastId & screenid,int fps)484 bool Call::StartScreencast(Session* session,
485 const std::string& streamid, uint32 ssrc,
486 const ScreencastId& screenid, int fps) {
487 MediaSessionMap::iterator it = media_session_map_.find(session->id());
488 if (it == media_session_map_.end()) {
489 return false;
490 }
491
492 VideoChannel *video_channel = GetVideoChannel(session);
493 if (!video_channel) {
494 LOG(LS_WARNING) << "Cannot add screencast"
495 << " because there is no video channel.";
496 return false;
497 }
498
499 VideoCapturer* capturer = session_client_->channel_manager()->
500 CreateScreenCapturer(screenid);
501 if (!capturer) {
502 LOG(LS_WARNING) << "Could not create screencast capturer.";
503 return false;
504 }
505
506 if (!video_channel->AddScreencast(ssrc, capturer)) {
507 delete capturer;
508 LOG(LS_WARNING) << "Could not add screencast capturer.";
509 return false;
510 }
511
512 VideoFormat format = ScreencastFormatFromFps(fps);
513 if (!session_client_->channel_manager()->StartVideoCapture(
514 capturer, format)) {
515 LOG(LS_WARNING) << "Could not start video capture.";
516 video_channel->RemoveScreencast(ssrc);
517 return false;
518 }
519
520 if (!video_channel->SetCapturer(ssrc, capturer)) {
521 LOG(LS_WARNING) << "Could not start sending screencast.";
522 session_client_->channel_manager()->StopVideoCapture(
523 capturer, ScreencastFormatFromFps(fps));
524 video_channel->RemoveScreencast(ssrc);
525 }
526
527 // TODO(pthatcher): Once the CaptureManager has a nicer interface
528 // for removing captures (such as having StartCapture return a
529 // handle), remove this StartedCapture stuff.
530 it->second.started_screencasts.insert(
531 std::make_pair(ssrc, StartedCapture(capturer, format)));
532
533 // TODO(pthatcher): Verify we aren't re-using an existing id or
534 // ssrc.
535 StreamParams stream;
536 stream.id = streamid;
537 stream.ssrcs.push_back(ssrc);
538 VideoContentDescription* video = CreateVideoStreamUpdate(stream);
539
540 // TODO(pthatcher): Wait until view request before sending video.
541 video_channel->SetLocalContent(video, CA_UPDATE, NULL);
542 SendVideoStreamUpdate(session, video);
543 return true;
544 }
545
StopScreencast(Session * session,const std::string & streamid,uint32 ssrc)546 bool Call::StopScreencast(Session* session,
547 const std::string& streamid, uint32 ssrc) {
548 if (!StopScreencastWithoutSendingUpdate(session, ssrc)) {
549 return false;
550 }
551
552 VideoChannel *video_channel = GetVideoChannel(session);
553 if (!video_channel) {
554 LOG(LS_WARNING) << "Cannot add screencast"
555 << " because there is no video channel.";
556 return false;
557 }
558
559 StreamParams stream;
560 stream.id = streamid;
561 // No ssrcs
562 VideoContentDescription* video = CreateVideoStreamUpdate(stream);
563
564 video_channel->SetLocalContent(video, CA_UPDATE, NULL);
565 SendVideoStreamUpdate(session, video);
566 return true;
567 }
568
StopScreencastWithoutSendingUpdate(Session * session,uint32 ssrc)569 bool Call::StopScreencastWithoutSendingUpdate(
570 Session* session, uint32 ssrc) {
571 MediaSessionMap::iterator it = media_session_map_.find(session->id());
572 if (it == media_session_map_.end()) {
573 return false;
574 }
575
576 VideoChannel *video_channel = GetVideoChannel(session);
577 if (!video_channel) {
578 LOG(LS_WARNING) << "Cannot remove screencast"
579 << " because there is no video channel.";
580 return false;
581 }
582
583 StartedScreencastMap::const_iterator screencast_iter =
584 it->second.started_screencasts.find(ssrc);
585 if (screencast_iter == it->second.started_screencasts.end()) {
586 LOG(LS_WARNING) << "Could not stop screencast " << ssrc
587 << " because there is no capturer.";
588 return false;
589 }
590
591 VideoCapturer* capturer = screencast_iter->second.capturer;
592 VideoFormat format = screencast_iter->second.format;
593 video_channel->SetCapturer(ssrc, NULL);
594 if (!session_client_->channel_manager()->StopVideoCapture(
595 capturer, format)) {
596 LOG(LS_WARNING) << "Could not stop screencast " << ssrc
597 << " because could not stop capture.";
598 return false;
599 }
600 video_channel->RemoveScreencast(ssrc);
601 it->second.started_screencasts.erase(ssrc);
602 return true;
603 }
604
CreateVideoStreamUpdate(const StreamParams & stream)605 VideoContentDescription* Call::CreateVideoStreamUpdate(
606 const StreamParams& stream) {
607 VideoContentDescription* video = new VideoContentDescription();
608 video->set_multistream(true);
609 video->set_partial(true);
610 video->AddStream(stream);
611 return video;
612 }
613
SendVideoStreamUpdate(Session * session,VideoContentDescription * video)614 void Call::SendVideoStreamUpdate(
615 Session* session, VideoContentDescription* video) {
616 // Takes the ownership of |video|.
617 rtc::scoped_ptr<VideoContentDescription> description(video);
618 const ContentInfo* video_info =
619 GetFirstVideoContent(session->local_description());
620 if (video_info == NULL) {
621 LOG(LS_WARNING) << "Cannot send stream update for video.";
622 return;
623 }
624
625 std::vector<ContentInfo> contents;
626 contents.push_back(
627 ContentInfo(video_info->name, video_info->type, description.get()));
628
629 session->SendDescriptionInfoMessage(contents);
630 }
631
ContinuePlayDTMF()632 void Call::ContinuePlayDTMF() {
633 playing_dtmf_ = false;
634
635 // Check to see if we have a queued tone
636 if (queued_dtmf_.size() > 0) {
637 playing_dtmf_ = true;
638
639 int tone = queued_dtmf_.front();
640 queued_dtmf_.pop_front();
641
642 LOG(LS_INFO) << "Call::ContinuePlayDTMF(" << tone << ")";
643 for (MediaSessionMap::iterator it = media_session_map_.begin();
644 it != media_session_map_.end(); ++it) {
645 if (it->second.voice_channel != NULL) {
646 it->second.voice_channel->PressDTMF(tone, true);
647 }
648 }
649
650 // Post a message to play the next tone or at least clear the playing_dtmf_
651 // bit.
652 rtc::Thread::Current()->PostDelayed(kDTMFDelay, this, MSG_PLAYDTMF);
653 }
654 }
655
Join(Call * call,bool enable)656 void Call::Join(Call* call, bool enable) {
657 for (MediaSessionMap::iterator it = call->media_session_map_.begin();
658 it != call->media_session_map_.end(); ++it) {
659 // Shouldn't already exist.
660 ASSERT(media_session_map_.find(it->first) == media_session_map_.end());
661 media_session_map_[it->first] = it->second;
662
663 it->second.session->SignalState.connect(this, &Call::OnSessionState);
664 it->second.session->SignalError.connect(this, &Call::OnSessionError);
665 it->second.session->SignalReceivedTerminateReason
666 .connect(this, &Call::OnReceivedTerminateReason);
667
668 EnableSessionChannels(it->second.session, enable);
669 }
670
671 // Moved all the sessions over, so the other call should no longer have any.
672 call->media_session_map_.clear();
673 }
674
StartConnectionMonitor(Session * session,int cms)675 void Call::StartConnectionMonitor(Session* session, int cms) {
676 VoiceChannel* voice_channel = GetVoiceChannel(session);
677 if (voice_channel) {
678 voice_channel->SignalConnectionMonitor.connect(this,
679 &Call::OnConnectionMonitor);
680 voice_channel->StartConnectionMonitor(cms);
681 }
682
683 VideoChannel* video_channel = GetVideoChannel(session);
684 if (video_channel) {
685 video_channel->SignalConnectionMonitor.connect(this,
686 &Call::OnConnectionMonitor);
687 video_channel->StartConnectionMonitor(cms);
688 }
689 }
690
StopConnectionMonitor(Session * session)691 void Call::StopConnectionMonitor(Session* session) {
692 VoiceChannel* voice_channel = GetVoiceChannel(session);
693 if (voice_channel) {
694 voice_channel->StopConnectionMonitor();
695 voice_channel->SignalConnectionMonitor.disconnect(this);
696 }
697
698 VideoChannel* video_channel = GetVideoChannel(session);
699 if (video_channel) {
700 video_channel->StopConnectionMonitor();
701 video_channel->SignalConnectionMonitor.disconnect(this);
702 }
703 }
704
StartAudioMonitor(Session * session,int cms)705 void Call::StartAudioMonitor(Session* session, int cms) {
706 VoiceChannel* voice_channel = GetVoiceChannel(session);
707 if (voice_channel) {
708 voice_channel->SignalAudioMonitor.connect(this, &Call::OnAudioMonitor);
709 voice_channel->StartAudioMonitor(cms);
710 }
711 }
712
StopAudioMonitor(Session * session)713 void Call::StopAudioMonitor(Session* session) {
714 VoiceChannel* voice_channel = GetVoiceChannel(session);
715 if (voice_channel) {
716 voice_channel->StopAudioMonitor();
717 voice_channel->SignalAudioMonitor.disconnect(this);
718 }
719 }
720
IsAudioMonitorRunning(Session * session)721 bool Call::IsAudioMonitorRunning(Session* session) {
722 VoiceChannel* voice_channel = GetVoiceChannel(session);
723 if (voice_channel) {
724 return voice_channel->IsAudioMonitorRunning();
725 } else {
726 return false;
727 }
728 }
729
StartSpeakerMonitor(Session * session)730 void Call::StartSpeakerMonitor(Session* session) {
731 if (speaker_monitor_map_.find(session->id()) == speaker_monitor_map_.end()) {
732 if (!IsAudioMonitorRunning(session)) {
733 StartAudioMonitor(session, kAudioMonitorPollPeriodMillis);
734 }
735 CurrentSpeakerMonitor* speaker_monitor =
736 new cricket::CurrentSpeakerMonitor(
737 audio_source_proxy_.get(), session);
738 speaker_monitor->SignalUpdate.connect(this, &Call::OnSpeakerMonitor);
739 speaker_monitor->Start();
740 speaker_monitor_map_[session->id()] = speaker_monitor;
741 } else {
742 LOG(LS_WARNING) << "Already started speaker monitor for session "
743 << session->id() << ".";
744 }
745 }
746
StopSpeakerMonitor(Session * session)747 void Call::StopSpeakerMonitor(Session* session) {
748 if (speaker_monitor_map_.find(session->id()) == speaker_monitor_map_.end()) {
749 LOG(LS_WARNING) << "Speaker monitor for session "
750 << session->id() << " already stopped.";
751 } else {
752 CurrentSpeakerMonitor* monitor = speaker_monitor_map_[session->id()];
753 monitor->Stop();
754 speaker_monitor_map_.erase(session->id());
755 delete monitor;
756 }
757 }
758
OnConnectionMonitor(VoiceChannel * channel,const std::vector<ConnectionInfo> & infos)759 void Call::OnConnectionMonitor(VoiceChannel* channel,
760 const std::vector<ConnectionInfo> &infos) {
761 SignalConnectionMonitor(this, infos);
762 }
763
OnMediaMonitor(VoiceChannel * channel,const VoiceMediaInfo & info)764 void Call::OnMediaMonitor(VoiceChannel* channel, const VoiceMediaInfo& info) {
765 last_voice_media_info_ = info;
766 SignalMediaMonitor(this, info);
767 }
768
OnAudioMonitor(VoiceChannel * channel,const AudioInfo & info)769 void Call::OnAudioMonitor(VoiceChannel* channel, const AudioInfo& info) {
770 SignalAudioMonitor(this, info);
771 }
772
OnSpeakerMonitor(CurrentSpeakerMonitor * monitor,uint32 ssrc)773 void Call::OnSpeakerMonitor(CurrentSpeakerMonitor* monitor, uint32 ssrc) {
774 Session* session = static_cast<Session*>(monitor->session());
775 MediaStreams* recv_streams = GetMediaStreams(session);
776 if (recv_streams) {
777 StreamParams stream;
778 recv_streams->GetAudioStream(StreamSelector(ssrc), &stream);
779 SignalSpeakerMonitor(this, session, stream);
780 }
781 }
782
OnConnectionMonitor(VideoChannel * channel,const std::vector<ConnectionInfo> & infos)783 void Call::OnConnectionMonitor(VideoChannel* channel,
784 const std::vector<ConnectionInfo> &infos) {
785 SignalVideoConnectionMonitor(this, infos);
786 }
787
OnMediaMonitor(VideoChannel * channel,const VideoMediaInfo & info)788 void Call::OnMediaMonitor(VideoChannel* channel, const VideoMediaInfo& info) {
789 SignalVideoMediaMonitor(this, info);
790 }
791
OnDataReceived(DataChannel * channel,const ReceiveDataParams & params,const rtc::Buffer & payload)792 void Call::OnDataReceived(DataChannel* channel,
793 const ReceiveDataParams& params,
794 const rtc::Buffer& payload) {
795 SignalDataReceived(this, params, payload);
796 }
797
id()798 uint32 Call::id() {
799 return id_;
800 }
801
OnSessionState(BaseSession * base_session,BaseSession::State state)802 void Call::OnSessionState(BaseSession* base_session, BaseSession::State state) {
803 Session* session = static_cast<Session*>(base_session);
804 switch (state) {
805 case Session::STATE_RECEIVEDACCEPT:
806 UpdateRemoteMediaStreams(session,
807 session->remote_description()->contents(), false);
808 session_client_->session_manager()->signaling_thread()->Clear(this,
809 MSG_TERMINATECALL);
810 break;
811 case Session::STATE_RECEIVEDREJECT:
812 case Session::STATE_RECEIVEDTERMINATE:
813 session_client_->session_manager()->signaling_thread()->Clear(this,
814 MSG_TERMINATECALL);
815 break;
816 default:
817 break;
818 }
819 SignalSessionState(this, session, state);
820 }
821
OnSessionError(BaseSession * base_session,Session::Error error)822 void Call::OnSessionError(BaseSession* base_session, Session::Error error) {
823 session_client_->session_manager()->signaling_thread()->Clear(this,
824 MSG_TERMINATECALL);
825 SignalSessionError(this, static_cast<Session*>(base_session), error);
826 }
827
OnSessionInfoMessage(Session * session,const buzz::XmlElement * action_elem)828 void Call::OnSessionInfoMessage(Session* session,
829 const buzz::XmlElement* action_elem) {
830 if (!IsJingleViewRequest(action_elem)) {
831 return;
832 }
833
834 ViewRequest view_request;
835 ParseError error;
836 if (!ParseJingleViewRequest(action_elem, &view_request, &error)) {
837 LOG(LS_WARNING) << "Failed to parse view request: " << error.text;
838 return;
839 }
840
841 VideoChannel* video_channel = GetVideoChannel(session);
842 if (video_channel == NULL) {
843 LOG(LS_WARNING) << "Ignore view request since we have no video channel.";
844 return;
845 }
846
847 if (!video_channel->ApplyViewRequest(view_request)) {
848 LOG(LS_WARNING) << "Failed to ApplyViewRequest.";
849 }
850 }
851
OnRemoteDescriptionUpdate(BaseSession * base_session,const ContentInfos & updated_contents)852 void Call::OnRemoteDescriptionUpdate(BaseSession* base_session,
853 const ContentInfos& updated_contents) {
854 Session* session = static_cast<Session*>(base_session);
855
856 const ContentInfo* audio_content = GetFirstAudioContent(updated_contents);
857 if (audio_content) {
858 const AudioContentDescription* audio_update =
859 static_cast<const AudioContentDescription*>(audio_content->description);
860 if (!audio_update->codecs().empty()) {
861 UpdateVoiceChannelRemoteContent(session, audio_update);
862 }
863 }
864
865 const ContentInfo* video_content = GetFirstVideoContent(updated_contents);
866 if (video_content) {
867 const VideoContentDescription* video_update =
868 static_cast<const VideoContentDescription*>(video_content->description);
869 if (!video_update->codecs().empty()) {
870 UpdateVideoChannelRemoteContent(session, video_update);
871 }
872 }
873
874 const ContentInfo* data_content = GetFirstDataContent(updated_contents);
875 if (data_content) {
876 const DataContentDescription* data_update =
877 static_cast<const DataContentDescription*>(data_content->description);
878 if (!data_update->codecs().empty()) {
879 UpdateDataChannelRemoteContent(session, data_update);
880 }
881 }
882
883 UpdateRemoteMediaStreams(session, updated_contents, true);
884 }
885
UpdateVoiceChannelRemoteContent(Session * session,const AudioContentDescription * audio)886 bool Call::UpdateVoiceChannelRemoteContent(
887 Session* session, const AudioContentDescription* audio) {
888 VoiceChannel* voice_channel = GetVoiceChannel(session);
889 if (!voice_channel->SetRemoteContent(audio, CA_UPDATE, NULL)) {
890 const std::string error_desc =
891 "Failure in audio SetRemoteContent with CA_UPDATE";
892 LOG(LS_ERROR) << error_desc;
893 session->SetError(BaseSession::ERROR_CONTENT, error_desc);
894 return false;
895 }
896 return true;
897 }
898
UpdateVideoChannelRemoteContent(Session * session,const VideoContentDescription * video)899 bool Call::UpdateVideoChannelRemoteContent(
900 Session* session, const VideoContentDescription* video) {
901 VideoChannel* video_channel = GetVideoChannel(session);
902 if (!video_channel->SetRemoteContent(video, CA_UPDATE, NULL)) {
903 const std::string error_desc =
904 "Failure in video SetRemoteContent with CA_UPDATE";
905 LOG(LS_ERROR) << error_desc;
906 session->SetError(BaseSession::ERROR_CONTENT, error_desc);
907 return false;
908 }
909 return true;
910 }
911
UpdateDataChannelRemoteContent(Session * session,const DataContentDescription * data)912 bool Call::UpdateDataChannelRemoteContent(
913 Session* session, const DataContentDescription* data) {
914 DataChannel* data_channel = GetDataChannel(session);
915 if (!data_channel->SetRemoteContent(data, CA_UPDATE, NULL)) {
916 const std::string error_desc =
917 "Failure in data SetRemoteContent with CA_UPDATE";
918 LOG(LS_ERROR) << error_desc;
919 session->SetError(BaseSession::ERROR_CONTENT, error_desc);
920 return false;
921 }
922 return true;
923 }
924
UpdateRemoteMediaStreams(Session * session,const ContentInfos & updated_contents,bool update_channels)925 void Call::UpdateRemoteMediaStreams(Session* session,
926 const ContentInfos& updated_contents,
927 bool update_channels) {
928 MediaStreams* recv_streams = GetMediaStreams(session);
929 if (!recv_streams)
930 return;
931
932 cricket::MediaStreams added_streams;
933 cricket::MediaStreams removed_streams;
934
935 const ContentInfo* audio_content = GetFirstAudioContent(updated_contents);
936 if (audio_content) {
937 const AudioContentDescription* audio_update =
938 static_cast<const AudioContentDescription*>(audio_content->description);
939 UpdateRecvStreams(audio_update->streams(),
940 update_channels ? GetVoiceChannel(session) : NULL,
941 recv_streams->mutable_audio(),
942 added_streams.mutable_audio(),
943 removed_streams.mutable_audio());
944 }
945
946 const ContentInfo* video_content = GetFirstVideoContent(updated_contents);
947 if (video_content) {
948 const VideoContentDescription* video_update =
949 static_cast<const VideoContentDescription*>(video_content->description);
950 UpdateRecvStreams(video_update->streams(),
951 update_channels ? GetVideoChannel(session) : NULL,
952 recv_streams->mutable_video(),
953 added_streams.mutable_video(),
954 removed_streams.mutable_video());
955 }
956
957 const ContentInfo* data_content = GetFirstDataContent(updated_contents);
958 if (data_content) {
959 const DataContentDescription* data_update =
960 static_cast<const DataContentDescription*>(data_content->description);
961 UpdateRecvStreams(data_update->streams(),
962 update_channels ? GetDataChannel(session) : NULL,
963 recv_streams->mutable_data(),
964 added_streams.mutable_data(),
965 removed_streams.mutable_data());
966 }
967
968 if (!added_streams.empty() || !removed_streams.empty()) {
969 SignalMediaStreamsUpdate(this, session, added_streams, removed_streams);
970 }
971 }
972
FindStreamChanges(const std::vector<StreamParams> & streams,const std::vector<StreamParams> & updates,std::vector<StreamParams> * added_streams,std::vector<StreamParams> * removed_streams)973 void FindStreamChanges(const std::vector<StreamParams>& streams,
974 const std::vector<StreamParams>& updates,
975 std::vector<StreamParams>* added_streams,
976 std::vector<StreamParams>* removed_streams) {
977 for (std::vector<StreamParams>::const_iterator update = updates.begin();
978 update != updates.end(); ++update) {
979 StreamParams stream;
980 if (GetStreamByIds(streams, update->groupid, update->id, &stream)) {
981 if (!update->has_ssrcs()) {
982 removed_streams->push_back(stream);
983 }
984 } else {
985 // There's a bug on reflector that will send <stream>s even
986 // though there is not ssrc (which means there isn't really a
987 // stream). To work around it, we simply ignore new <stream>s
988 // that don't have any ssrcs.
989 if (update->has_ssrcs()) {
990 added_streams->push_back(*update);
991 }
992 }
993 }
994 }
995
UpdateRecvStreams(const std::vector<StreamParams> & update_streams,BaseChannel * channel,std::vector<StreamParams> * recv_streams,std::vector<StreamParams> * added_streams,std::vector<StreamParams> * removed_streams)996 void Call::UpdateRecvStreams(const std::vector<StreamParams>& update_streams,
997 BaseChannel* channel,
998 std::vector<StreamParams>* recv_streams,
999 std::vector<StreamParams>* added_streams,
1000 std::vector<StreamParams>* removed_streams) {
1001 FindStreamChanges(*recv_streams,
1002 update_streams, added_streams, removed_streams);
1003 AddRecvStreams(*added_streams,
1004 channel, recv_streams);
1005 RemoveRecvStreams(*removed_streams,
1006 channel, recv_streams);
1007 }
1008
AddRecvStreams(const std::vector<StreamParams> & added_streams,BaseChannel * channel,std::vector<StreamParams> * recv_streams)1009 void Call::AddRecvStreams(const std::vector<StreamParams>& added_streams,
1010 BaseChannel* channel,
1011 std::vector<StreamParams>* recv_streams) {
1012 std::vector<StreamParams>::const_iterator stream;
1013 for (stream = added_streams.begin();
1014 stream != added_streams.end();
1015 ++stream) {
1016 AddRecvStream(*stream, channel, recv_streams);
1017 }
1018 }
1019
AddRecvStream(const StreamParams & stream,BaseChannel * channel,std::vector<StreamParams> * recv_streams)1020 void Call::AddRecvStream(const StreamParams& stream,
1021 BaseChannel* channel,
1022 std::vector<StreamParams>* recv_streams) {
1023 if (channel && stream.has_ssrcs()) {
1024 channel->AddRecvStream(stream);
1025 }
1026 recv_streams->push_back(stream);
1027 }
1028
RemoveRecvStreams(const std::vector<StreamParams> & removed_streams,BaseChannel * channel,std::vector<StreamParams> * recv_streams)1029 void Call::RemoveRecvStreams(const std::vector<StreamParams>& removed_streams,
1030 BaseChannel* channel,
1031 std::vector<StreamParams>* recv_streams) {
1032 std::vector<StreamParams>::const_iterator stream;
1033 for (stream = removed_streams.begin();
1034 stream != removed_streams.end();
1035 ++stream) {
1036 RemoveRecvStream(*stream, channel, recv_streams);
1037 }
1038 }
1039
RemoveRecvStream(const StreamParams & stream,BaseChannel * channel,std::vector<StreamParams> * recv_streams)1040 void Call::RemoveRecvStream(const StreamParams& stream,
1041 BaseChannel* channel,
1042 std::vector<StreamParams>* recv_streams) {
1043 if (channel && stream.has_ssrcs()) {
1044 // TODO(pthatcher): Change RemoveRecvStream to take a stream argument.
1045 channel->RemoveRecvStream(stream.first_ssrc());
1046 }
1047 RemoveStreamByIds(recv_streams, stream.groupid, stream.id);
1048 }
1049
OnReceivedTerminateReason(Session * session,const std::string & reason)1050 void Call::OnReceivedTerminateReason(Session* session,
1051 const std::string& reason) {
1052 session_client_->session_manager()->signaling_thread()->Clear(this,
1053 MSG_TERMINATECALL);
1054 SignalReceivedTerminateReason(this, session, reason);
1055 }
1056
1057 // TODO(mdodd): Get ride of this method since all Hangouts are using a secure
1058 // connection.
secure() const1059 bool Call::secure() const {
1060 if (session_client_->secure() == SEC_DISABLED) {
1061 return false;
1062 }
1063
1064 bool ret = true;
1065 int i = 0;
1066
1067 MediaSessionMap::const_iterator it;
1068 for (it = media_session_map_.begin(); it != media_session_map_.end(); ++it) {
1069 LOG_F(LS_VERBOSE) << "session[" << i
1070 << "], check local and remote descriptions";
1071 i++;
1072
1073 if (!SessionDescriptionContainsCrypto(
1074 it->second.session->local_description()) ||
1075 !SessionDescriptionContainsCrypto(
1076 it->second.session->remote_description())) {
1077 ret = false;
1078 break;
1079 }
1080 }
1081
1082 LOG_F(LS_VERBOSE) << "secure=" << ret;
1083 return ret;
1084 }
1085
SessionDescriptionContainsCrypto(const SessionDescription * sdesc) const1086 bool Call::SessionDescriptionContainsCrypto(
1087 const SessionDescription* sdesc) const {
1088 if (sdesc == NULL) {
1089 LOG_F(LS_VERBOSE) << "sessionDescription is NULL";
1090 return false;
1091 }
1092
1093 return ContentContainsCrypto(sdesc->GetContentByName(CN_AUDIO)) &&
1094 ContentContainsCrypto(sdesc->GetContentByName(CN_VIDEO));
1095 }
1096
InternalInitiateSession(const std::string & id,const buzz::Jid & to,const std::string & initiator_name,const CallOptions & options)1097 Session* Call::InternalInitiateSession(const std::string& id,
1098 const buzz::Jid& to,
1099 const std::string& initiator_name,
1100 const CallOptions& options) {
1101 const SessionDescription* offer = session_client_->CreateOffer(options);
1102
1103 Session* session = session_client_->CreateSession(id, this);
1104 // Only override the initiator_name if it was manually supplied. Otherwise,
1105 // session_client_ will supply the local jid as initiator in CreateOffer.
1106 if (!initiator_name.empty()) {
1107 session->set_initiator_name(initiator_name);
1108 }
1109
1110 AddSession(session, offer);
1111 session->Initiate(to.Str(), offer);
1112
1113 // After this timeout, terminate the call because the callee isn't
1114 // answering
1115 session_client_->session_manager()->signaling_thread()->Clear(this,
1116 MSG_TERMINATECALL);
1117 session_client_->session_manager()->signaling_thread()->PostDelayed(
1118 send_to_voicemail_ ? kSendToVoicemailTimeout : kNoVoicemailTimeout,
1119 this, MSG_TERMINATECALL);
1120 return session;
1121 }
1122
GetAudioSourceProxy()1123 AudioSourceProxy* Call::GetAudioSourceProxy() {
1124 return audio_source_proxy_.get();
1125 }
1126
1127 } // namespace cricket
1128