Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(131)

Side by Side Diff: webrtc/libjingle/session/media/call.cc

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

Powered by Google App Engine
This is Rietveld 408576698