3 * Copyright 2004 Google Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
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.
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.
29 #include "talk/media/base/constants.h"
30 #include "talk/media/base/screencastid.h"
31 #include "webrtc/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"
42 const uint32 MSG_CHECKAUTODESTROY = 1;
43 const uint32 MSG_TERMINATECALL = 2;
44 const uint32 MSG_PLAYDTMF = 3;
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;
55 // V is a pointer type.
56 template<class K, class V>
57 V FindOrNull(const std::map<K, V>& map,
59 typename std::map<K, V>::const_iterator it = map.find(key);
60 return (it != map.end()) ? it->second : NULL;
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()) {
78 AudioSourceProxy::AudioSourceProxy(Call* call)
80 call_->SignalAudioMonitor.connect(this, &AudioSourceProxy::OnAudioMonitor);
81 call_->SignalMediaStreamsUpdate.connect(
82 this, &AudioSourceProxy::OnMediaStreamsUpdate);
85 void AudioSourceProxy::OnAudioMonitor(Call* call, const AudioInfo& info) {
86 SignalAudioMonitor(this, info);
89 void AudioSourceProxy::OnMediaStreamsUpdate(Call* call, Session* session,
90 const MediaStreams& added, const MediaStreams& removed) {
91 SignalMediaStreamsUpdate(this, session, added, removed);
94 Call::Call(MediaSessionClient* session_client)
95 : id_(rtc::CreateRandomId()),
96 session_client_(session_client),
101 send_to_voicemail_(true),
102 playing_dtmf_(false) {
103 audio_source_proxy_.reset(new AudioSourceProxy(this));
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);
112 rtc::Thread::Current()->Clear(this);
115 Session* Call::InitiateSession(const buzz::Jid& to,
116 const buzz::Jid& initiator,
117 const CallOptions& options) {
119 std::string initiator_name = initiator.Str();
120 return InternalInitiateSession(id, to, initiator_name, options);
123 Session *Call::InitiateSession(const std::string& id,
125 const CallOptions& options) {
126 std::string initiator_name;
127 return InternalInitiateSession(id, to, initiator_name, options);
130 void Call::IncomingSession(Session* session, const SessionDescription* offer) {
131 AddSession(session, offer);
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);
138 // Missed the first state, the initiate, which is needed by
140 SignalSessionState(this, session, Session::STATE_RECEIVEDINITIATE);
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);
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);
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();
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();
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);
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;
186 MediaStreams* recv_streams = GetMediaStreams(session);
188 found = recv_streams->GetVideoStream(it->selector, &found_stream);
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.";
201 if (!WriteJingleViewRequest(CN_VIDEO, view_request, &elems, &error)) {
202 LOG(LS_ERROR) << "Couldn't write out view request: " << error.text;
206 return session->SendInfoMessage(elems, session->remote_name());
209 void Call::SetVideoRenderer(Session* session, uint32 ssrc,
210 VideoRenderer* renderer) {
211 VideoChannel* video_channel = GetVideoChannel(session);
213 video_channel->SetRenderer(ssrc, renderer);
214 LOG(LS_INFO) << "Set renderer of ssrc " << ssrc
215 << " to " << renderer << ".";
217 LOG(LS_INFO) << "Failed to set renderer of ssrc " << ssrc << ".";
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);
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();
235 // Callee didn't answer - terminate call
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);
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;
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);
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);
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(
289 media_session.voice_channel);
290 // video_channel can be NULL in case of NullVideoEngine.
291 if (media_session.video_channel) {
292 media_session.video_channel->SignalMediaMonitor.connect(
293 this, &Call::OnMediaMonitor);
294 media_session.video_channel->StartMediaMonitor(kMediaMonitorInterval);
300 // If desired, create data channel.
301 if (has_data_ && succeeded) {
302 const DataContentDescription* data = GetFirstDataContentDescription(offer);
306 DataChannelType data_channel_type = DCT_RTP;
307 if ((data->protocol() == kMediaProtocolSctp) ||
308 (data->protocol() == kMediaProtocolDtlsSctp)) {
309 data_channel_type = DCT_SCTP;
313 media_session.data_channel =
314 session_client_->channel_manager()->CreateDataChannel(
315 session, data_offer->name, rtcp, data_channel_type);
316 if (media_session.data_channel) {
317 media_session.data_channel->SignalDataReceived.connect(
318 this, &Call::OnDataReceived);
326 // Add session to list, create channels for this session.
327 media_session.recv_streams = new MediaStreams;
328 media_session_map_[session->id()] = media_session;
329 session->SignalState.connect(this, &Call::OnSessionState);
330 session->SignalError.connect(this, &Call::OnSessionError);
331 session->SignalInfoMessage.connect(
332 this, &Call::OnSessionInfoMessage);
333 session->SignalRemoteDescriptionUpdate.connect(
334 this, &Call::OnRemoteDescriptionUpdate);
335 session->SignalReceivedTerminateReason
336 .connect(this, &Call::OnReceivedTerminateReason);
338 // If this call has the focus, enable this session's channels.
339 if (session_client_->GetFocus() == this) {
340 EnableSessionChannels(session, true);
344 SignalAddSession(this, session);
350 void Call::RemoveSession(Session* session) {
351 MediaSessionMap::iterator it = media_session_map_.find(session->id());
352 if (it == media_session_map_.end())
355 // Remove all the screencasts, if they haven't been already.
356 while (!it->second.started_screencasts.empty()) {
357 uint32 ssrc = it->second.started_screencasts.begin()->first;
358 if (!StopScreencastWithoutSendingUpdate(it->second.session, ssrc)) {
359 LOG(LS_ERROR) << "Unable to stop screencast with ssrc " << ssrc;
364 // Destroy video channel
365 VideoChannel* video_channel = it->second.video_channel;
366 if (video_channel != NULL)
367 session_client_->channel_manager()->DestroyVideoChannel(video_channel);
369 // Destroy voice channel
370 VoiceChannel* voice_channel = it->second.voice_channel;
371 if (voice_channel != NULL)
372 session_client_->channel_manager()->DestroyVoiceChannel(voice_channel);
374 // Destroy data channel
375 DataChannel* data_channel = it->second.data_channel;
376 if (data_channel != NULL)
377 session_client_->channel_manager()->DestroyDataChannel(data_channel);
379 delete it->second.recv_streams;
380 media_session_map_.erase(it);
382 // Destroy speaker monitor
383 StopSpeakerMonitor(session);
386 SignalRemoveSession(this, session);
388 // The call auto destroys when the last session is removed
389 rtc::Thread::Current()->Post(this, MSG_CHECKAUTODESTROY);
392 VoiceChannel* Call::GetVoiceChannel(Session* session) const {
393 MediaSessionMap::const_iterator it = media_session_map_.find(session->id());
394 return (it != media_session_map_.end()) ? it->second.voice_channel : NULL;
397 VideoChannel* Call::GetVideoChannel(Session* session) const {
398 MediaSessionMap::const_iterator it = media_session_map_.find(session->id());
399 return (it != media_session_map_.end()) ? it->second.video_channel : NULL;
402 DataChannel* Call::GetDataChannel(Session* session) const {
403 MediaSessionMap::const_iterator it = media_session_map_.find(session->id());
404 return (it != media_session_map_.end()) ? it->second.data_channel : NULL;
407 MediaStreams* Call::GetMediaStreams(Session* session) const {
408 MediaSessionMap::const_iterator it = media_session_map_.find(session->id());
409 return (it != media_session_map_.end()) ? it->second.recv_streams : NULL;
412 void Call::EnableChannels(bool enable) {
413 MediaSessionMap::iterator it;
414 for (it = media_session_map_.begin(); it != media_session_map_.end(); ++it) {
415 EnableSessionChannels(it->second.session, enable);
419 void Call::EnableSessionChannels(Session* session, bool enable) {
420 MediaSessionMap::iterator it = media_session_map_.find(session->id());
421 if (it == media_session_map_.end())
424 VoiceChannel* voice_channel = it->second.voice_channel;
425 VideoChannel* video_channel = it->second.video_channel;
426 DataChannel* data_channel = it->second.data_channel;
427 if (voice_channel != NULL)
428 voice_channel->Enable(enable);
429 if (video_channel != NULL)
430 video_channel->Enable(enable);
431 if (data_channel != NULL)
432 data_channel->Enable(enable);
435 void Call::Mute(bool mute) {
437 MediaSessionMap::iterator it;
438 for (it = media_session_map_.begin(); it != media_session_map_.end(); ++it) {
439 if (it->second.voice_channel != NULL)
440 it->second.voice_channel->MuteStream(0, mute);
444 void Call::MuteVideo(bool mute) {
446 MediaSessionMap::iterator it;
447 for (it = media_session_map_.begin(); it != media_session_map_.end(); ++it) {
448 if (it->second.video_channel != NULL)
449 it->second.video_channel->MuteStream(0, mute);
453 bool Call::SendData(Session* session,
454 const SendDataParams& params,
455 const rtc::Buffer& payload,
456 SendDataResult* result) {
457 DataChannel* data_channel = GetDataChannel(session);
459 LOG(LS_WARNING) << "Could not send data: no data channel.";
463 return data_channel->SendData(params, payload, result);
466 void Call::PressDTMF(int event) {
467 // Queue up this digit
468 if (queued_dtmf_.size() < kMaxDTMFDigits) {
469 LOG(LS_INFO) << "Call::PressDTMF(" << event << ")";
471 queued_dtmf_.push_back(event);
473 if (!playing_dtmf_) {
479 cricket::VideoFormat ScreencastFormatFromFps(int fps) {
480 // The capturer pretty much ignore this, but just in case we give it
481 // a resolution big enough to cover any expected desktop. In any
482 // case, it can't be 0x0, or the CaptureManager will fail to use it.
483 return cricket::VideoFormat(
485 cricket::VideoFormat::FpsToInterval(fps), cricket::FOURCC_ANY);
488 bool Call::StartScreencast(Session* session,
489 const std::string& streamid, uint32 ssrc,
490 const ScreencastId& screenid, int fps) {
491 MediaSessionMap::iterator it = media_session_map_.find(session->id());
492 if (it == media_session_map_.end()) {
496 VideoChannel *video_channel = GetVideoChannel(session);
497 if (!video_channel) {
498 LOG(LS_WARNING) << "Cannot add screencast"
499 << " because there is no video channel.";
503 VideoCapturer* capturer = session_client_->channel_manager()->
504 CreateScreenCapturer(screenid);
506 LOG(LS_WARNING) << "Could not create screencast capturer.";
510 if (!video_channel->AddScreencast(ssrc, capturer)) {
512 LOG(LS_WARNING) << "Could not add screencast capturer.";
516 VideoFormat format = ScreencastFormatFromFps(fps);
517 if (!session_client_->channel_manager()->StartVideoCapture(
519 LOG(LS_WARNING) << "Could not start video capture.";
520 video_channel->RemoveScreencast(ssrc);
524 if (!video_channel->SetCapturer(ssrc, capturer)) {
525 LOG(LS_WARNING) << "Could not start sending screencast.";
526 session_client_->channel_manager()->StopVideoCapture(
527 capturer, ScreencastFormatFromFps(fps));
528 video_channel->RemoveScreencast(ssrc);
531 // TODO(pthatcher): Once the CaptureManager has a nicer interface
532 // for removing captures (such as having StartCapture return a
533 // handle), remove this StartedCapture stuff.
534 it->second.started_screencasts.insert(
535 std::make_pair(ssrc, StartedCapture(capturer, format)));
537 // TODO(pthatcher): Verify we aren't re-using an existing id or
540 stream.id = streamid;
541 stream.ssrcs.push_back(ssrc);
542 VideoContentDescription* video = CreateVideoStreamUpdate(stream);
544 // TODO(pthatcher): Wait until view request before sending video.
545 video_channel->SetLocalContent(video, CA_UPDATE, NULL);
546 SendVideoStreamUpdate(session, video);
550 bool Call::StopScreencast(Session* session,
551 const std::string& streamid, uint32 ssrc) {
552 if (!StopScreencastWithoutSendingUpdate(session, ssrc)) {
556 VideoChannel *video_channel = GetVideoChannel(session);
557 if (!video_channel) {
558 LOG(LS_WARNING) << "Cannot add screencast"
559 << " because there is no video channel.";
564 stream.id = streamid;
566 VideoContentDescription* video = CreateVideoStreamUpdate(stream);
568 video_channel->SetLocalContent(video, CA_UPDATE, NULL);
569 SendVideoStreamUpdate(session, video);
573 bool Call::StopScreencastWithoutSendingUpdate(
574 Session* session, uint32 ssrc) {
575 MediaSessionMap::iterator it = media_session_map_.find(session->id());
576 if (it == media_session_map_.end()) {
580 VideoChannel *video_channel = GetVideoChannel(session);
581 if (!video_channel) {
582 LOG(LS_WARNING) << "Cannot remove screencast"
583 << " because there is no video channel.";
587 StartedScreencastMap::const_iterator screencast_iter =
588 it->second.started_screencasts.find(ssrc);
589 if (screencast_iter == it->second.started_screencasts.end()) {
590 LOG(LS_WARNING) << "Could not stop screencast " << ssrc
591 << " because there is no capturer.";
595 VideoCapturer* capturer = screencast_iter->second.capturer;
596 VideoFormat format = screencast_iter->second.format;
597 video_channel->SetCapturer(ssrc, NULL);
598 if (!session_client_->channel_manager()->StopVideoCapture(
600 LOG(LS_WARNING) << "Could not stop screencast " << ssrc
601 << " because could not stop capture.";
604 video_channel->RemoveScreencast(ssrc);
605 it->second.started_screencasts.erase(ssrc);
609 VideoContentDescription* Call::CreateVideoStreamUpdate(
610 const StreamParams& stream) {
611 VideoContentDescription* video = new VideoContentDescription();
612 video->set_multistream(true);
613 video->set_partial(true);
614 video->AddStream(stream);
618 void Call::SendVideoStreamUpdate(
619 Session* session, VideoContentDescription* video) {
620 // Takes the ownership of |video|.
621 rtc::scoped_ptr<VideoContentDescription> description(video);
622 const ContentInfo* video_info =
623 GetFirstVideoContent(session->local_description());
624 if (video_info == NULL) {
625 LOG(LS_WARNING) << "Cannot send stream update for video.";
629 std::vector<ContentInfo> contents;
631 ContentInfo(video_info->name, video_info->type, description.get()));
633 session->SendDescriptionInfoMessage(contents);
636 void Call::ContinuePlayDTMF() {
637 playing_dtmf_ = false;
639 // Check to see if we have a queued tone
640 if (queued_dtmf_.size() > 0) {
641 playing_dtmf_ = true;
643 int tone = queued_dtmf_.front();
644 queued_dtmf_.pop_front();
646 LOG(LS_INFO) << "Call::ContinuePlayDTMF(" << tone << ")";
647 for (MediaSessionMap::iterator it = media_session_map_.begin();
648 it != media_session_map_.end(); ++it) {
649 if (it->second.voice_channel != NULL) {
650 it->second.voice_channel->PressDTMF(tone, true);
654 // Post a message to play the next tone or at least clear the playing_dtmf_
656 rtc::Thread::Current()->PostDelayed(kDTMFDelay, this, MSG_PLAYDTMF);
660 void Call::Join(Call* call, bool enable) {
661 for (MediaSessionMap::iterator it = call->media_session_map_.begin();
662 it != call->media_session_map_.end(); ++it) {
663 // Shouldn't already exist.
664 ASSERT(media_session_map_.find(it->first) == media_session_map_.end());
665 media_session_map_[it->first] = it->second;
667 it->second.session->SignalState.connect(this, &Call::OnSessionState);
668 it->second.session->SignalError.connect(this, &Call::OnSessionError);
669 it->second.session->SignalReceivedTerminateReason
670 .connect(this, &Call::OnReceivedTerminateReason);
672 EnableSessionChannels(it->second.session, enable);
675 // Moved all the sessions over, so the other call should no longer have any.
676 call->media_session_map_.clear();
679 void Call::StartConnectionMonitor(Session* session, int cms) {
680 VoiceChannel* voice_channel = GetVoiceChannel(session);
682 voice_channel->SignalConnectionMonitor.connect(this,
683 &Call::OnConnectionMonitor);
684 voice_channel->StartConnectionMonitor(cms);
687 VideoChannel* video_channel = GetVideoChannel(session);
689 video_channel->SignalConnectionMonitor.connect(this,
690 &Call::OnConnectionMonitor);
691 video_channel->StartConnectionMonitor(cms);
695 void Call::StopConnectionMonitor(Session* session) {
696 VoiceChannel* voice_channel = GetVoiceChannel(session);
698 voice_channel->StopConnectionMonitor();
699 voice_channel->SignalConnectionMonitor.disconnect(this);
702 VideoChannel* video_channel = GetVideoChannel(session);
704 video_channel->StopConnectionMonitor();
705 video_channel->SignalConnectionMonitor.disconnect(this);
709 void Call::StartAudioMonitor(Session* session, int cms) {
710 VoiceChannel* voice_channel = GetVoiceChannel(session);
712 voice_channel->SignalAudioMonitor.connect(this, &Call::OnAudioMonitor);
713 voice_channel->StartAudioMonitor(cms);
717 void Call::StopAudioMonitor(Session* session) {
718 VoiceChannel* voice_channel = GetVoiceChannel(session);
720 voice_channel->StopAudioMonitor();
721 voice_channel->SignalAudioMonitor.disconnect(this);
725 bool Call::IsAudioMonitorRunning(Session* session) {
726 VoiceChannel* voice_channel = GetVoiceChannel(session);
728 return voice_channel->IsAudioMonitorRunning();
734 void Call::StartSpeakerMonitor(Session* session) {
735 if (speaker_monitor_map_.find(session->id()) == speaker_monitor_map_.end()) {
736 if (!IsAudioMonitorRunning(session)) {
737 StartAudioMonitor(session, kAudioMonitorPollPeriodMillis);
739 CurrentSpeakerMonitor* speaker_monitor =
740 new cricket::CurrentSpeakerMonitor(
741 audio_source_proxy_.get(), session);
742 speaker_monitor->SignalUpdate.connect(this, &Call::OnSpeakerMonitor);
743 speaker_monitor->Start();
744 speaker_monitor_map_[session->id()] = speaker_monitor;
746 LOG(LS_WARNING) << "Already started speaker monitor for session "
747 << session->id() << ".";
751 void Call::StopSpeakerMonitor(Session* session) {
752 if (speaker_monitor_map_.find(session->id()) == speaker_monitor_map_.end()) {
753 LOG(LS_WARNING) << "Speaker monitor for session "
754 << session->id() << " already stopped.";
756 CurrentSpeakerMonitor* monitor = speaker_monitor_map_[session->id()];
758 speaker_monitor_map_.erase(session->id());
763 void Call::OnConnectionMonitor(VoiceChannel* channel,
764 const std::vector<ConnectionInfo> &infos) {
765 SignalConnectionMonitor(this, infos);
768 void Call::OnMediaMonitor(VoiceChannel* channel, const VoiceMediaInfo& info) {
769 last_voice_media_info_ = info;
770 SignalMediaMonitor(this, info);
773 void Call::OnAudioMonitor(VoiceChannel* channel, const AudioInfo& info) {
774 SignalAudioMonitor(this, info);
777 void Call::OnSpeakerMonitor(CurrentSpeakerMonitor* monitor, uint32 ssrc) {
778 Session* session = static_cast<Session*>(monitor->session());
779 MediaStreams* recv_streams = GetMediaStreams(session);
782 recv_streams->GetAudioStream(StreamSelector(ssrc), &stream);
783 SignalSpeakerMonitor(this, session, stream);
787 void Call::OnConnectionMonitor(VideoChannel* channel,
788 const std::vector<ConnectionInfo> &infos) {
789 SignalVideoConnectionMonitor(this, infos);
792 void Call::OnMediaMonitor(VideoChannel* channel, const VideoMediaInfo& info) {
793 SignalVideoMediaMonitor(this, info);
796 void Call::OnDataReceived(DataChannel* channel,
797 const ReceiveDataParams& params,
798 const rtc::Buffer& payload) {
799 SignalDataReceived(this, params, payload);
806 void Call::OnSessionState(BaseSession* base_session, BaseSession::State state) {
807 Session* session = static_cast<Session*>(base_session);
809 case Session::STATE_RECEIVEDACCEPT:
810 UpdateRemoteMediaStreams(session,
811 session->remote_description()->contents(), false);
812 session_client_->session_manager()->signaling_thread()->Clear(this,
815 case Session::STATE_RECEIVEDREJECT:
816 case Session::STATE_RECEIVEDTERMINATE:
817 session_client_->session_manager()->signaling_thread()->Clear(this,
823 SignalSessionState(this, session, state);
826 void Call::OnSessionError(BaseSession* base_session, Session::Error error) {
827 session_client_->session_manager()->signaling_thread()->Clear(this,
829 SignalSessionError(this, static_cast<Session*>(base_session), error);
832 void Call::OnSessionInfoMessage(Session* session,
833 const buzz::XmlElement* action_elem) {
834 if (!IsJingleViewRequest(action_elem)) {
838 ViewRequest view_request;
840 if (!ParseJingleViewRequest(action_elem, &view_request, &error)) {
841 LOG(LS_WARNING) << "Failed to parse view request: " << error.text;
845 VideoChannel* video_channel = GetVideoChannel(session);
846 if (video_channel == NULL) {
847 LOG(LS_WARNING) << "Ignore view request since we have no video channel.";
851 if (!video_channel->ApplyViewRequest(view_request)) {
852 LOG(LS_WARNING) << "Failed to ApplyViewRequest.";
856 void Call::OnRemoteDescriptionUpdate(BaseSession* base_session,
857 const ContentInfos& updated_contents) {
858 Session* session = static_cast<Session*>(base_session);
860 const ContentInfo* audio_content = GetFirstAudioContent(updated_contents);
862 const AudioContentDescription* audio_update =
863 static_cast<const AudioContentDescription*>(audio_content->description);
864 if (!audio_update->codecs().empty()) {
865 UpdateVoiceChannelRemoteContent(session, audio_update);
869 const ContentInfo* video_content = GetFirstVideoContent(updated_contents);
871 const VideoContentDescription* video_update =
872 static_cast<const VideoContentDescription*>(video_content->description);
873 if (!video_update->codecs().empty()) {
874 UpdateVideoChannelRemoteContent(session, video_update);
878 const ContentInfo* data_content = GetFirstDataContent(updated_contents);
880 const DataContentDescription* data_update =
881 static_cast<const DataContentDescription*>(data_content->description);
882 if (!data_update->codecs().empty()) {
883 UpdateDataChannelRemoteContent(session, data_update);
887 UpdateRemoteMediaStreams(session, updated_contents, true);
890 bool Call::UpdateVoiceChannelRemoteContent(
891 Session* session, const AudioContentDescription* audio) {
892 VoiceChannel* voice_channel = GetVoiceChannel(session);
893 if (!voice_channel->SetRemoteContent(audio, CA_UPDATE, NULL)) {
894 const std::string error_desc =
895 "Failure in audio SetRemoteContent with CA_UPDATE";
896 LOG(LS_ERROR) << error_desc;
897 session->SetError(BaseSession::ERROR_CONTENT, error_desc);
903 bool Call::UpdateVideoChannelRemoteContent(
904 Session* session, const VideoContentDescription* video) {
905 VideoChannel* video_channel = GetVideoChannel(session);
906 if (!video_channel->SetRemoteContent(video, CA_UPDATE, NULL)) {
907 const std::string error_desc =
908 "Failure in video SetRemoteContent with CA_UPDATE";
909 LOG(LS_ERROR) << error_desc;
910 session->SetError(BaseSession::ERROR_CONTENT, error_desc);
916 bool Call::UpdateDataChannelRemoteContent(
917 Session* session, const DataContentDescription* data) {
918 DataChannel* data_channel = GetDataChannel(session);
919 if (!data_channel->SetRemoteContent(data, CA_UPDATE, NULL)) {
920 const std::string error_desc =
921 "Failure in data SetRemoteContent with CA_UPDATE";
922 LOG(LS_ERROR) << error_desc;
923 session->SetError(BaseSession::ERROR_CONTENT, error_desc);
929 void Call::UpdateRemoteMediaStreams(Session* session,
930 const ContentInfos& updated_contents,
931 bool update_channels) {
932 MediaStreams* recv_streams = GetMediaStreams(session);
936 cricket::MediaStreams added_streams;
937 cricket::MediaStreams removed_streams;
939 const ContentInfo* audio_content = GetFirstAudioContent(updated_contents);
941 const AudioContentDescription* audio_update =
942 static_cast<const AudioContentDescription*>(audio_content->description);
943 UpdateRecvStreams(audio_update->streams(),
944 update_channels ? GetVoiceChannel(session) : NULL,
945 recv_streams->mutable_audio(),
946 added_streams.mutable_audio(),
947 removed_streams.mutable_audio());
950 const ContentInfo* video_content = GetFirstVideoContent(updated_contents);
952 const VideoContentDescription* video_update =
953 static_cast<const VideoContentDescription*>(video_content->description);
954 UpdateRecvStreams(video_update->streams(),
955 update_channels ? GetVideoChannel(session) : NULL,
956 recv_streams->mutable_video(),
957 added_streams.mutable_video(),
958 removed_streams.mutable_video());
961 const ContentInfo* data_content = GetFirstDataContent(updated_contents);
963 const DataContentDescription* data_update =
964 static_cast<const DataContentDescription*>(data_content->description);
965 UpdateRecvStreams(data_update->streams(),
966 update_channels ? GetDataChannel(session) : NULL,
967 recv_streams->mutable_data(),
968 added_streams.mutable_data(),
969 removed_streams.mutable_data());
972 if (!added_streams.empty() || !removed_streams.empty()) {
973 SignalMediaStreamsUpdate(this, session, added_streams, removed_streams);
977 void FindStreamChanges(const std::vector<StreamParams>& streams,
978 const std::vector<StreamParams>& updates,
979 std::vector<StreamParams>* added_streams,
980 std::vector<StreamParams>* removed_streams) {
981 for (std::vector<StreamParams>::const_iterator update = updates.begin();
982 update != updates.end(); ++update) {
984 if (GetStreamByIds(streams, update->groupid, update->id, &stream)) {
985 if (!update->has_ssrcs()) {
986 removed_streams->push_back(stream);
989 // There's a bug on reflector that will send <stream>s even
990 // though there is not ssrc (which means there isn't really a
991 // stream). To work around it, we simply ignore new <stream>s
992 // that don't have any ssrcs.
993 if (update->has_ssrcs()) {
994 added_streams->push_back(*update);
1000 void Call::UpdateRecvStreams(const std::vector<StreamParams>& update_streams,
1001 BaseChannel* channel,
1002 std::vector<StreamParams>* recv_streams,
1003 std::vector<StreamParams>* added_streams,
1004 std::vector<StreamParams>* removed_streams) {
1005 FindStreamChanges(*recv_streams,
1006 update_streams, added_streams, removed_streams);
1007 AddRecvStreams(*added_streams,
1008 channel, recv_streams);
1009 RemoveRecvStreams(*removed_streams,
1010 channel, recv_streams);
1013 void Call::AddRecvStreams(const std::vector<StreamParams>& added_streams,
1014 BaseChannel* channel,
1015 std::vector<StreamParams>* recv_streams) {
1016 std::vector<StreamParams>::const_iterator stream;
1017 for (stream = added_streams.begin();
1018 stream != added_streams.end();
1020 AddRecvStream(*stream, channel, recv_streams);
1024 void Call::AddRecvStream(const StreamParams& stream,
1025 BaseChannel* channel,
1026 std::vector<StreamParams>* recv_streams) {
1027 if (channel && stream.has_ssrcs()) {
1028 channel->AddRecvStream(stream);
1030 recv_streams->push_back(stream);
1033 void Call::RemoveRecvStreams(const std::vector<StreamParams>& removed_streams,
1034 BaseChannel* channel,
1035 std::vector<StreamParams>* recv_streams) {
1036 std::vector<StreamParams>::const_iterator stream;
1037 for (stream = removed_streams.begin();
1038 stream != removed_streams.end();
1040 RemoveRecvStream(*stream, channel, recv_streams);
1044 void Call::RemoveRecvStream(const StreamParams& stream,
1045 BaseChannel* channel,
1046 std::vector<StreamParams>* recv_streams) {
1047 if (channel && stream.has_ssrcs()) {
1048 // TODO(pthatcher): Change RemoveRecvStream to take a stream argument.
1049 channel->RemoveRecvStream(stream.first_ssrc());
1051 RemoveStreamByIds(recv_streams, stream.groupid, stream.id);
1054 void Call::OnReceivedTerminateReason(Session* session,
1055 const std::string& reason) {
1056 session_client_->session_manager()->signaling_thread()->Clear(this,
1058 SignalReceivedTerminateReason(this, session, reason);
1061 // TODO(mdodd): Get ride of this method since all Hangouts are using a secure
1063 bool Call::secure() const {
1064 if (session_client_->secure() == SEC_DISABLED) {
1071 MediaSessionMap::const_iterator it;
1072 for (it = media_session_map_.begin(); it != media_session_map_.end(); ++it) {
1073 LOG_F(LS_VERBOSE) << "session[" << i
1074 << "], check local and remote descriptions";
1077 if (!SessionDescriptionContainsCrypto(
1078 it->second.session->local_description()) ||
1079 !SessionDescriptionContainsCrypto(
1080 it->second.session->remote_description())) {
1086 LOG_F(LS_VERBOSE) << "secure=" << ret;
1090 bool Call::SessionDescriptionContainsCrypto(
1091 const SessionDescription* sdesc) const {
1092 if (sdesc == NULL) {
1093 LOG_F(LS_VERBOSE) << "sessionDescription is NULL";
1097 return ContentContainsCrypto(sdesc->GetContentByName(CN_AUDIO)) &&
1098 ContentContainsCrypto(sdesc->GetContentByName(CN_VIDEO));
1101 Session* Call::InternalInitiateSession(const std::string& id,
1102 const buzz::Jid& to,
1103 const std::string& initiator_name,
1104 const CallOptions& options) {
1105 const SessionDescription* offer = session_client_->CreateOffer(options);
1107 Session* session = session_client_->CreateSession(id, this);
1108 // Only override the initiator_name if it was manually supplied. Otherwise,
1109 // session_client_ will supply the local jid as initiator in CreateOffer.
1110 if (!initiator_name.empty()) {
1111 session->set_initiator_name(initiator_name);
1114 AddSession(session, offer);
1115 session->Initiate(to.Str(), offer);
1117 // After this timeout, terminate the call because the callee isn't
1119 session_client_->session_manager()->signaling_thread()->Clear(this,
1121 session_client_->session_manager()->signaling_thread()->PostDelayed(
1122 send_to_voicemail_ ? kSendToVoicemailTimeout : kNoVoicemailTimeout,
1123 this, MSG_TERMINATECALL);
1127 AudioSourceProxy* Call::GetAudioSourceProxy() {
1128 return audio_source_proxy_.get();
1131 } // namespace cricket