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