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