15976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org/*
25976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * libjingle
35976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * Copyright 2004 Google Inc.
45976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *
55976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * Redistribution and use in source and binary forms, with or without
65976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * modification, are permitted provided that the following conditions are met:
75976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *
85976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *  1. Redistributions of source code must retain the above copyright notice,
95976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *     this list of conditions and the following disclaimer.
105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *  2. Redistributions in binary form must reproduce the above copyright notice,
115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *     this list of conditions and the following disclaimer in the documentation
125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *     and/or other materials provided with the distribution.
135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *  3. The name of the author may not be used to endorse or promote products
145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *     derived from this software without specific prior written permission.
155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *
165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org */
275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include <string>
295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/helpers.h"
305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/logging.h"
315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/thread.h"
325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/window.h"
335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/media/base/constants.h"
345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/media/base/screencastid.h"
355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/p2p/base/parsing.h"
365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/session/media/call.h"
375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/session/media/mediasessionclient.h"
385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgnamespace cricket {
405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst uint32 MSG_CHECKAUTODESTROY = 1;
425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst uint32 MSG_TERMINATECALL = 2;
435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst uint32 MSG_PLAYDTMF = 3;
445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgnamespace {
465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst int kDTMFDelay = 300;  // msec
475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst size_t kMaxDTMFDigits = 30;
485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst int kSendToVoicemailTimeout = 1000*20;
495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst int kNoVoicemailTimeout = 1000*180;
505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst int kMediaMonitorInterval = 1000*15;
515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// In order to be the same as the server-side switching, this must be 100.
525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst int kAudioMonitorPollPeriodMillis = 100;
535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// V is a pointer type.
555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgtemplate<class K, class V>
565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgV FindOrNull(const std::map<K, V>& map,
575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org             const K& key) {
585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  typename std::map<K, V>::const_iterator it = map.find(key);
595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return (it != map.end()) ? it->second : NULL;
605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
62c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org
63c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.orgbool ContentContainsCrypto(const cricket::ContentInfo* content) {
64c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org  if (content != NULL) {
65c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org    const cricket::MediaContentDescription* desc =
66c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org        static_cast<const cricket::MediaContentDescription*>(
67c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org            content->description);
68c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org    if (!desc || desc->cryptos().empty()) {
69c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org      return false;
70c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org    }
71c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org  }
72c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org  return true;
73c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org}
74c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org
755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgCall::Call(MediaSessionClient* session_client)
785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    : id_(talk_base::CreateRandomId()),
795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      session_client_(session_client),
805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      local_renderer_(NULL),
815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      has_video_(false),
825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      has_data_(false),
835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      muted_(false),
845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      video_muted_(false),
855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      send_to_voicemail_(true),
865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      playing_dtmf_(false) {
875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgCall::~Call() {
905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  while (media_session_map_.begin() != media_session_map_.end()) {
915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    Session* session = media_session_map_.begin()->second.session;
925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    RemoveSession(session);
935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    session_client_->session_manager()->DestroySession(session);
945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  talk_base::Thread::Current()->Clear(this);
965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgSession* Call::InitiateSession(const buzz::Jid& to,
995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                               const buzz::Jid& initiator,
1005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                               const CallOptions& options) {
101c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org  std::string id;
102c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org  std::string initiator_name = initiator.Str();
103c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org  return InternalInitiateSession(id, to, initiator_name, options);
104c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org}
1055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
106c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.orgSession *Call::InitiateSession(const std::string& id,
107c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org                               const buzz::Jid& to,
108c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org                               const CallOptions& options) {
109c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org  std::string initiator_name;
110c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org  return InternalInitiateSession(id, to, initiator_name, options);
1115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Call::IncomingSession(Session* session, const SessionDescription* offer) {
1145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  AddSession(session, offer);
1155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Make sure the session knows about the incoming ssrcs. This needs to be done
1175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // prior to the SignalSessionState call, because that may trigger handling of
1185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // these new SSRCs, so they need to be registered before then.
1195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  UpdateRemoteMediaStreams(session, offer->contents(), false);
1205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Missed the first state, the initiate, which is needed by
1225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // call_client.
1235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  SignalSessionState(this, session, Session::STATE_RECEIVEDINITIATE);
1245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Call::AcceptSession(Session* session,
1275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                         const cricket::CallOptions& options) {
1285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  MediaSessionMap::iterator it = media_session_map_.find(session->id());
1295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (it != media_session_map_.end()) {
1305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const SessionDescription* answer = session_client_->CreateAnswer(
1315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        session->remote_description(), options);
1325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    it->second.session->Accept(answer);
1335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
1345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Call::RejectSession(Session* session) {
1375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Assume polite decline.
1385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  MediaSessionMap::iterator it = media_session_map_.find(session->id());
1395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (it != media_session_map_.end())
1405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    it->second.session->Reject(STR_TERMINATE_DECLINE);
1415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Call::TerminateSession(Session* session) {
1445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  MediaSessionMap::iterator it = media_session_map_.find(session->id());
1455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (it != media_session_map_.end()) {
1465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // Assume polite terminations.
1475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    it->second.session->Terminate();
1485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
1495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Call::Terminate() {
1525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Copy the list so that we can iterate over it in a stable way
1535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  std::vector<Session*> sessions = this->sessions();
1545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // There may be more than one session to terminate
1565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  std::vector<Session*>::iterator it;
1575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  for (it = sessions.begin(); it != sessions.end(); ++it) {
1585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    TerminateSession(*it);
1595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
1605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool Call::SendViewRequest(Session* session,
1635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                           const ViewRequest& view_request) {
1645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  StaticVideoViews::const_iterator it;
1655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  for (it = view_request.static_video_views.begin();
1665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org       it != view_request.static_video_views.end(); ++it) {
1675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    StreamParams found_stream;
1685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    bool found = false;
1695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    MediaStreams* recv_streams = GetMediaStreams(session);
1705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (recv_streams)
1715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      found = recv_streams->GetVideoStream(it->selector, &found_stream);
1725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (!found) {
1735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      LOG(LS_WARNING) << "Trying to send view request for ("
1745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                      << it->selector.ssrc << ", '"
1755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                      << it->selector.groupid << "', '"
1765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                      << it->selector.streamid << "'"
1775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                      << ") is not in the local streams.";
1785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      return false;
1795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
1805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
1815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  XmlElements elems;
1835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  WriteError error;
1845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!WriteJingleViewRequest(CN_VIDEO, view_request, &elems, &error)) {
1855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_ERROR) << "Couldn't write out view request: " << error.text;
1865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
1875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
1885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1890687a8153d275005a575afd929cc5e6392693347mflodman@webrtc.org  return session->SendInfoMessage(elems, session->remote_name());
1905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Call::SetLocalRenderer(VideoRenderer* renderer) {
1935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  local_renderer_ = renderer;
1945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (session_client_->GetFocus() == this) {
1955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    session_client_->channel_manager()->SetLocalRenderer(renderer);
1965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
1975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Call::SetVideoRenderer(Session* session, uint32 ssrc,
2005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                            VideoRenderer* renderer) {
2015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  VideoChannel* video_channel = GetVideoChannel(session);
2025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (video_channel) {
2035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    video_channel->SetRenderer(ssrc, renderer);
2045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_INFO) << "Set renderer of ssrc " << ssrc
2055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                 << " to " << renderer << ".";
2065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  } else {
2075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_INFO) << "Failed to set renderer of ssrc " << ssrc << ".";
2085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
2095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
2105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Call::OnMessage(talk_base::Message* message) {
2125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  switch (message->message_id) {
2135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  case MSG_CHECKAUTODESTROY:
2145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // If no more sessions for this call, delete it
2155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (media_session_map_.empty())
2165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      session_client_->DestroyCall(this);
2175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    break;
2185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  case MSG_TERMINATECALL:
2195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // Signal to the user that a timeout has happened and the call should
2205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // be sent to voicemail.
2215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (send_to_voicemail_) {
2225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      SignalSetupToCallVoicemail();
2235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
2245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // Callee didn't answer - terminate call
2265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    Terminate();
2275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    break;
2285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  case MSG_PLAYDTMF:
2295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    ContinuePlayDTMF();
2305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
2315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
2325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstd::vector<Session*> Call::sessions() {
2345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  std::vector<Session*> sessions;
2355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  MediaSessionMap::iterator it;
2365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  for (it = media_session_map_.begin(); it != media_session_map_.end(); ++it)
2375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    sessions.push_back(it->second.session);
2385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return sessions;
2405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
2415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool Call::AddSession(Session* session, const SessionDescription* offer) {
2435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  bool succeeded = true;
2445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  MediaSession media_session;
2455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  media_session.session = session;
2465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  media_session.voice_channel = NULL;
2475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  media_session.video_channel = NULL;
2485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  media_session.data_channel = NULL;
2495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  media_session.recv_streams = NULL;
2505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  const ContentInfo* audio_offer = GetFirstAudioContent(offer);
2525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  const ContentInfo* video_offer = GetFirstVideoContent(offer);
2535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  const ContentInfo* data_offer = GetFirstDataContent(offer);
2545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  has_video_ = (video_offer != NULL);
2555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  has_data_ = (data_offer != NULL);
2565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ASSERT(audio_offer != NULL);
2585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Create voice channel and start a media monitor.
2595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  media_session.voice_channel =
2605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      session_client_->channel_manager()->CreateVoiceChannel(
2615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          session, audio_offer->name, has_video_);
2625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // voice_channel can be NULL in case of NullVoiceEngine.
2635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (media_session.voice_channel) {
2645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    media_session.voice_channel->SignalMediaMonitor.connect(
2655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        this, &Call::OnMediaMonitor);
2665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    media_session.voice_channel->StartMediaMonitor(kMediaMonitorInterval);
2675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  } else {
2685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    succeeded = false;
2695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
2705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // If desired, create video channel and start a media monitor.
2725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (has_video_ && succeeded) {
2735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    media_session.video_channel =
2745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        session_client_->channel_manager()->CreateVideoChannel(
2755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org            session, video_offer->name, true, media_session.voice_channel);
2765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // video_channel can be NULL in case of NullVideoEngine.
2775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (media_session.video_channel) {
2785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      media_session.video_channel->SignalMediaMonitor.connect(
2795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          this, &Call::OnMediaMonitor);
2805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      media_session.video_channel->StartMediaMonitor(kMediaMonitorInterval);
2815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    } else {
2825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      succeeded = false;
2835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
2845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
2855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // If desired, create data channel.
2875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (has_data_ && succeeded) {
2885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const DataContentDescription* data = GetFirstDataContentDescription(offer);
2895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (data == NULL) {
2905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      succeeded = false;
2915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    } else {
2925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      DataChannelType data_channel_type = DCT_RTP;
2935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      if ((data->protocol() == kMediaProtocolSctp) ||
2945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          (data->protocol() == kMediaProtocolDtlsSctp)) {
2955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        data_channel_type = DCT_SCTP;
2965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      }
2975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      bool rtcp = false;
2995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      media_session.data_channel =
3005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          session_client_->channel_manager()->CreateDataChannel(
3015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org              session, data_offer->name, rtcp, data_channel_type);
3025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      if (media_session.data_channel) {
3035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        media_session.data_channel->SignalDataReceived.connect(
3045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org            this, &Call::OnDataReceived);
3055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      } else {
3065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        succeeded = false;
3075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      }
3085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
3095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
3105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (succeeded) {
3125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // Add session to list, create channels for this session.
3135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    media_session.recv_streams = new MediaStreams;
3145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    media_session_map_[session->id()] = media_session;
3155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    session->SignalState.connect(this, &Call::OnSessionState);
3165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    session->SignalError.connect(this, &Call::OnSessionError);
3175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    session->SignalInfoMessage.connect(
3185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        this, &Call::OnSessionInfoMessage);
3195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    session->SignalRemoteDescriptionUpdate.connect(
3205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        this, &Call::OnRemoteDescriptionUpdate);
3215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    session->SignalReceivedTerminateReason
3225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      .connect(this, &Call::OnReceivedTerminateReason);
3235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // If this call has the focus, enable this session's channels.
3255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (session_client_->GetFocus() == this) {
3265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      EnableSessionChannels(session, true);
3275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
3285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // Signal client.
3305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    SignalAddSession(this, session);
3315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
3325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return succeeded;
3345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
3355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Call::RemoveSession(Session* session) {
3375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  MediaSessionMap::iterator it = media_session_map_.find(session->id());
3385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (it == media_session_map_.end())
3395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return;
3405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Remove all the screencasts, if they haven't been already.
3425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  while (!it->second.started_screencasts.empty()) {
3435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    uint32 ssrc = it->second.started_screencasts.begin()->first;
3445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (!StopScreencastWithoutSendingUpdate(it->second.session, ssrc)) {
3455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      LOG(LS_ERROR) << "Unable to stop screencast with ssrc " << ssrc;
3465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      ASSERT(false);
3475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
3485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
3495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Destroy video channel
3515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  VideoChannel* video_channel = it->second.video_channel;
3525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (video_channel != NULL)
3535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    session_client_->channel_manager()->DestroyVideoChannel(video_channel);
3545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Destroy voice channel
3565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  VoiceChannel* voice_channel = it->second.voice_channel;
3575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (voice_channel != NULL)
3585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    session_client_->channel_manager()->DestroyVoiceChannel(voice_channel);
3595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Destroy data channel
3615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  DataChannel* data_channel = it->second.data_channel;
3625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (data_channel != NULL)
3635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    session_client_->channel_manager()->DestroyDataChannel(data_channel);
3645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  delete it->second.recv_streams;
3665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  media_session_map_.erase(it);
3675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Destroy speaker monitor
3695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  StopSpeakerMonitor(session);
3705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Signal client
3725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  SignalRemoveSession(this, session);
3735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // The call auto destroys when the last session is removed
3755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  talk_base::Thread::Current()->Post(this, MSG_CHECKAUTODESTROY);
3765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
3775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgVoiceChannel* Call::GetVoiceChannel(Session* session) const {
3795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  MediaSessionMap::const_iterator it = media_session_map_.find(session->id());
3805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return (it != media_session_map_.end()) ? it->second.voice_channel : NULL;
3815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
3825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgVideoChannel* Call::GetVideoChannel(Session* session) const {
3845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  MediaSessionMap::const_iterator it = media_session_map_.find(session->id());
3855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return (it != media_session_map_.end()) ? it->second.video_channel : NULL;
3865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
3875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgDataChannel* Call::GetDataChannel(Session* session) const {
3895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  MediaSessionMap::const_iterator it = media_session_map_.find(session->id());
3905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return (it != media_session_map_.end()) ? it->second.data_channel : NULL;
3915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
3925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgMediaStreams* Call::GetMediaStreams(Session* session) const {
3945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  MediaSessionMap::const_iterator it = media_session_map_.find(session->id());
3955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return (it != media_session_map_.end()) ? it->second.recv_streams : NULL;
3965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
3975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Call::EnableChannels(bool enable) {
3995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  MediaSessionMap::iterator it;
4005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  for (it = media_session_map_.begin(); it != media_session_map_.end(); ++it) {
4015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    EnableSessionChannels(it->second.session, enable);
4025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
4035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  session_client_->channel_manager()->SetLocalRenderer(
4045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      (enable) ? local_renderer_ : NULL);
4055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
4065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Call::EnableSessionChannels(Session* session, bool enable) {
4085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  MediaSessionMap::iterator it = media_session_map_.find(session->id());
4095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (it == media_session_map_.end())
4105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return;
4115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  VoiceChannel* voice_channel = it->second.voice_channel;
4135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  VideoChannel* video_channel = it->second.video_channel;
4145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  DataChannel* data_channel = it->second.data_channel;
4155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (voice_channel != NULL)
4165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    voice_channel->Enable(enable);
4175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (video_channel != NULL)
4185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    video_channel->Enable(enable);
4195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (data_channel != NULL)
4205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    data_channel->Enable(enable);
4215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
4225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Call::Mute(bool mute) {
4245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  muted_ = mute;
4255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  MediaSessionMap::iterator it;
4265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  for (it = media_session_map_.begin(); it != media_session_map_.end(); ++it) {
4275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (it->second.voice_channel != NULL)
4285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      it->second.voice_channel->MuteStream(0, mute);
4295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
4305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
4315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Call::MuteVideo(bool mute) {
4335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  video_muted_ = mute;
4345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  MediaSessionMap::iterator it;
4355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  for (it = media_session_map_.begin(); it != media_session_map_.end(); ++it) {
4365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (it->second.video_channel != NULL)
4375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      it->second.video_channel->MuteStream(0, mute);
4385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
4395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
4405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool Call::SendData(Session* session,
4425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                    const SendDataParams& params,
4435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                    const talk_base::Buffer& payload,
4445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                    SendDataResult* result) {
4455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  DataChannel* data_channel = GetDataChannel(session);
4465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!data_channel) {
4475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_WARNING) << "Could not send data: no data channel.";
4485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
4495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
4505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return data_channel->SendData(params, payload, result);
4525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
4535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Call::PressDTMF(int event) {
4555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Queue up this digit
4565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (queued_dtmf_.size() < kMaxDTMFDigits) {
4575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_INFO) << "Call::PressDTMF(" << event << ")";
4585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    queued_dtmf_.push_back(event);
4605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (!playing_dtmf_) {
4625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      ContinuePlayDTMF();
4635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
4645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
4655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
4665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgcricket::VideoFormat ScreencastFormatFromFps(int fps) {
4685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // The capturer pretty much ignore this, but just in case we give it
4695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // a resolution big enough to cover any expected desktop.  In any
4705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // case, it can't be 0x0, or the CaptureManager will fail to use it.
4715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return cricket::VideoFormat(
4725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      1, 1,
4735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      cricket::VideoFormat::FpsToInterval(fps), cricket::FOURCC_ANY);
4745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
4755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool Call::StartScreencast(Session* session,
4775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                           const std::string& streamid, uint32 ssrc,
4785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                           const ScreencastId& screencastid, int fps) {
4795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  MediaSessionMap::iterator it = media_session_map_.find(session->id());
4805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (it == media_session_map_.end()) {
4815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
4825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
4835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  VideoChannel *video_channel = GetVideoChannel(session);
4855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!video_channel) {
4865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_WARNING) << "Cannot add screencast"
4875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                    << " because there is no video channel.";
4885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
4895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
4905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  VideoCapturer *capturer = video_channel->AddScreencast(ssrc, screencastid);
4925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (capturer == NULL) {
4935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_WARNING) << "Could not create screencast capturer.";
4945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
4955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
4965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  VideoFormat format = ScreencastFormatFromFps(fps);
4985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!session_client_->channel_manager()->StartVideoCapture(
4995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          capturer, format)) {
5005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_WARNING) << "Could not start video capture.";
5015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    video_channel->RemoveScreencast(ssrc);
5025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
5035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
5045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!video_channel->SetCapturer(ssrc, capturer)) {
5065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_WARNING) << "Could not start sending screencast.";
5075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    session_client_->channel_manager()->StopVideoCapture(
5085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        capturer, ScreencastFormatFromFps(fps));
5095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    video_channel->RemoveScreencast(ssrc);
5105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
5115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // TODO(pthatcher): Once the CaptureManager has a nicer interface
5135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // for removing captures (such as having StartCapture return a
5145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // handle), remove this StartedCapture stuff.
5155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  it->second.started_screencasts.insert(
5165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      std::make_pair(ssrc, StartedCapture(capturer, format)));
5175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // TODO(pthatcher): Verify we aren't re-using an existing id or
5195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // ssrc.
5205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  StreamParams stream;
5215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  stream.id = streamid;
5225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  stream.ssrcs.push_back(ssrc);
5235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  VideoContentDescription* video = CreateVideoStreamUpdate(stream);
5245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // TODO(pthatcher): Wait until view request before sending video.
5265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  video_channel->SetLocalContent(video, CA_UPDATE);
5275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  SendVideoStreamUpdate(session, video);
5285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return true;
5295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
5305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool Call::StopScreencast(Session* session,
5325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                          const std::string& streamid, uint32 ssrc) {
5335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!StopScreencastWithoutSendingUpdate(session, ssrc)) {
5345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
5355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
5365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  VideoChannel *video_channel = GetVideoChannel(session);
5385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!video_channel) {
5395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_WARNING) << "Cannot add screencast"
5405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                    << " because there is no video channel.";
5415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
5425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
5435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  StreamParams stream;
5455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  stream.id = streamid;
5465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // No ssrcs
5475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  VideoContentDescription* video = CreateVideoStreamUpdate(stream);
5485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  video_channel->SetLocalContent(video, CA_UPDATE);
5505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  SendVideoStreamUpdate(session, video);
5515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return true;
5525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
5535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool Call::StopScreencastWithoutSendingUpdate(
5555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    Session* session, uint32 ssrc) {
5565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  MediaSessionMap::iterator it = media_session_map_.find(session->id());
5575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (it == media_session_map_.end()) {
5585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
5595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
5605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  VideoChannel *video_channel = GetVideoChannel(session);
5625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!video_channel) {
5635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_WARNING) << "Cannot remove screencast"
5645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                    << " because there is no video channel.";
5655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
5665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
5675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  StartedScreencastMap::const_iterator screencast_iter =
5695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      it->second.started_screencasts.find(ssrc);
5705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (screencast_iter == it->second.started_screencasts.end()) {
5715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_WARNING) << "Could not stop screencast " << ssrc
5725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                    << " because there is no capturer.";
5735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
5745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
5755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  VideoCapturer* capturer = screencast_iter->second.capturer;
5775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  VideoFormat format = screencast_iter->second.format;
5785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  video_channel->SetCapturer(ssrc, NULL);
5795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!session_client_->channel_manager()->StopVideoCapture(
5805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          capturer, format)) {
5815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_WARNING) << "Could not stop screencast " << ssrc
5825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                    << " because could not stop capture.";
5835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
5845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
5855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  video_channel->RemoveScreencast(ssrc);
5865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  it->second.started_screencasts.erase(ssrc);
5875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return true;
5885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
5895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgVideoContentDescription* Call::CreateVideoStreamUpdate(
5915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const StreamParams& stream) {
5925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  VideoContentDescription* video = new VideoContentDescription();
5935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  video->set_multistream(true);
5945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  video->set_partial(true);
5955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  video->AddStream(stream);
5965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return video;
5975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
5985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Call::SendVideoStreamUpdate(
6005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    Session* session, VideoContentDescription* video) {
601c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org  // Takes the ownership of |video|.
602c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org  talk_base::scoped_ptr<VideoContentDescription> description(video);
6035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  const ContentInfo* video_info =
6045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      GetFirstVideoContent(session->local_description());
6055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (video_info == NULL) {
6065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_WARNING) << "Cannot send stream update for video.";
6075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return;
6085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
6095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  std::vector<ContentInfo> contents;
6115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  contents.push_back(
612c1c67e5a722135af4ca83ee4c7d2dbe3f26bae70henrike@webrtc.org      ContentInfo(video_info->name, video_info->type, description.get()));
6135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  session->SendDescriptionInfoMessage(contents);
6155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
6165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Call::ContinuePlayDTMF() {
6185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  playing_dtmf_ = false;
6195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Check to see if we have a queued tone
6215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (queued_dtmf_.size() > 0) {
6225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    playing_dtmf_ = true;
6235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    int tone = queued_dtmf_.front();
6255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    queued_dtmf_.pop_front();
6265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_INFO) << "Call::ContinuePlayDTMF(" << tone << ")";
6285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    for (MediaSessionMap::iterator it = media_session_map_.begin();
6295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org         it != media_session_map_.end(); ++it) {
6305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      if (it->second.voice_channel != NULL) {
6315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        it->second.voice_channel->PressDTMF(tone, true);
6325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      }
6335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
6345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // Post a message to play the next tone or at least clear the playing_dtmf_
6365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // bit.
6375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    talk_base::Thread::Current()->PostDelayed(kDTMFDelay, this, MSG_PLAYDTMF);
6385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
6395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
6405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Call::Join(Call* call, bool enable) {
6425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  for (MediaSessionMap::iterator it = call->media_session_map_.begin();
6435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org       it != call->media_session_map_.end(); ++it) {
6445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // Shouldn't already exist.
6455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    ASSERT(media_session_map_.find(it->first) == media_session_map_.end());
6465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    media_session_map_[it->first] = it->second;
6475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    it->second.session->SignalState.connect(this, &Call::OnSessionState);
6495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    it->second.session->SignalError.connect(this, &Call::OnSessionError);
6505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    it->second.session->SignalReceivedTerminateReason
6515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      .connect(this, &Call::OnReceivedTerminateReason);
6525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    EnableSessionChannels(it->second.session, enable);
6545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
6555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Moved all the sessions over, so the other call should no longer have any.
6575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  call->media_session_map_.clear();
6585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
6595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Call::StartConnectionMonitor(Session* session, int cms) {
6615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  VoiceChannel* voice_channel = GetVoiceChannel(session);
6625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (voice_channel) {
6635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    voice_channel->SignalConnectionMonitor.connect(this,
6645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        &Call::OnConnectionMonitor);
6655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    voice_channel->StartConnectionMonitor(cms);
6665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
6675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  VideoChannel* video_channel = GetVideoChannel(session);
6695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (video_channel) {
6705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    video_channel->SignalConnectionMonitor.connect(this,
6715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        &Call::OnConnectionMonitor);
6725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    video_channel->StartConnectionMonitor(cms);
6735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
6745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
6755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Call::StopConnectionMonitor(Session* session) {
6775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  VoiceChannel* voice_channel = GetVoiceChannel(session);
6785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (voice_channel) {
6795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    voice_channel->StopConnectionMonitor();
6805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    voice_channel->SignalConnectionMonitor.disconnect(this);
6815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
6825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  VideoChannel* video_channel = GetVideoChannel(session);
6845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (video_channel) {
6855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    video_channel->StopConnectionMonitor();
6865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    video_channel->SignalConnectionMonitor.disconnect(this);
6875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
6885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
6895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Call::StartAudioMonitor(Session* session, int cms) {
6915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  VoiceChannel* voice_channel = GetVoiceChannel(session);
6925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (voice_channel) {
6935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    voice_channel->SignalAudioMonitor.connect(this, &Call::OnAudioMonitor);
6945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    voice_channel->StartAudioMonitor(cms);
6955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
6965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
6975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Call::StopAudioMonitor(Session* session) {
6995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  VoiceChannel* voice_channel = GetVoiceChannel(session);
7005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (voice_channel) {
7015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    voice_channel->StopAudioMonitor();
7025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    voice_channel->SignalAudioMonitor.disconnect(this);
7035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
7045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
7055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool Call::IsAudioMonitorRunning(Session* session) {
7075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  VoiceChannel* voice_channel = GetVoiceChannel(session);
7085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (voice_channel) {
7095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return voice_channel->IsAudioMonitorRunning();
7105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  } else {
7115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
7125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
7135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
7145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Call::StartSpeakerMonitor(Session* session) {
7165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (speaker_monitor_map_.find(session->id()) == speaker_monitor_map_.end()) {
7175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (!IsAudioMonitorRunning(session)) {
7185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      StartAudioMonitor(session, kAudioMonitorPollPeriodMillis);
7195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
7205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    CurrentSpeakerMonitor* speaker_monitor =
7215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        new cricket::CurrentSpeakerMonitor(this, session);
7225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    speaker_monitor->SignalUpdate.connect(this, &Call::OnSpeakerMonitor);
7235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    speaker_monitor->Start();
7245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    speaker_monitor_map_[session->id()] = speaker_monitor;
7255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  } else {
7265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_WARNING) << "Already started speaker monitor for session "
7275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                    << session->id() << ".";
7285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
7295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
7305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Call::StopSpeakerMonitor(Session* session) {
7325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (speaker_monitor_map_.find(session->id()) == speaker_monitor_map_.end()) {
7335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_WARNING) << "Speaker monitor for session "
7345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                    << session->id() << " already stopped.";
7355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  } else {
7365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    CurrentSpeakerMonitor* monitor = speaker_monitor_map_[session->id()];
7375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    monitor->Stop();
7385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    speaker_monitor_map_.erase(session->id());
7395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    delete monitor;
7405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
7415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
7425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Call::OnConnectionMonitor(VoiceChannel* channel,
7445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                               const std::vector<ConnectionInfo> &infos) {
7455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  SignalConnectionMonitor(this, infos);
7465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
7475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Call::OnMediaMonitor(VoiceChannel* channel, const VoiceMediaInfo& info) {
7495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  last_voice_media_info_ = info;
7505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  SignalMediaMonitor(this, info);
7515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
7525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Call::OnAudioMonitor(VoiceChannel* channel, const AudioInfo& info) {
7545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  SignalAudioMonitor(this, info);
7555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
7565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Call::OnSpeakerMonitor(CurrentSpeakerMonitor* monitor, uint32 ssrc) {
7585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  Session* session = static_cast<Session*>(monitor->session());
7595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  MediaStreams* recv_streams = GetMediaStreams(session);
7605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (recv_streams) {
7615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    StreamParams stream;
7625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    recv_streams->GetAudioStream(StreamSelector(ssrc), &stream);
7635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    SignalSpeakerMonitor(this, session, stream);
7645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
7655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
7665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Call::OnConnectionMonitor(VideoChannel* channel,
7685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                               const std::vector<ConnectionInfo> &infos) {
7695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  SignalVideoConnectionMonitor(this, infos);
7705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
7715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Call::OnMediaMonitor(VideoChannel* channel, const VideoMediaInfo& info) {
7735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  SignalVideoMediaMonitor(this, info);
7745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
7755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Call::OnDataReceived(DataChannel* channel,
7775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                          const ReceiveDataParams& params,
7785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                          const talk_base::Buffer& payload) {
7795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  SignalDataReceived(this, params, payload);
7805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
7815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orguint32 Call::id() {
7835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return id_;
7845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
7855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Call::OnSessionState(BaseSession* base_session, BaseSession::State state) {
7875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  Session* session = static_cast<Session*>(base_session);
7885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  switch (state) {
7895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case Session::STATE_RECEIVEDACCEPT:
7905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      UpdateRemoteMediaStreams(session,
7915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          session->remote_description()->contents(), false);
7925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      session_client_->session_manager()->signaling_thread()->Clear(this,
7935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          MSG_TERMINATECALL);
7945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
7955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case Session::STATE_RECEIVEDREJECT:
7965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case Session::STATE_RECEIVEDTERMINATE:
7975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      session_client_->session_manager()->signaling_thread()->Clear(this,
7985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          MSG_TERMINATECALL);
7995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
8005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    default:
8015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
8025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
8035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  SignalSessionState(this, session, state);
8045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
8055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
8065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Call::OnSessionError(BaseSession* base_session, Session::Error error) {
8075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  session_client_->session_manager()->signaling_thread()->Clear(this,
8085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      MSG_TERMINATECALL);
8095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  SignalSessionError(this, static_cast<Session*>(base_session), error);
8105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
8115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
8125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Call::OnSessionInfoMessage(Session* session,
8135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                const buzz::XmlElement* action_elem) {
8145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!IsJingleViewRequest(action_elem)) {
8155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return;
8165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
8175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
8185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ViewRequest view_request;
8195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ParseError error;
8205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!ParseJingleViewRequest(action_elem, &view_request, &error)) {
8215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_WARNING) << "Failed to parse view request: " << error.text;
8225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return;
8235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
8245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
8255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  VideoChannel* video_channel = GetVideoChannel(session);
8265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (video_channel == NULL) {
8275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_WARNING) << "Ignore view request since we have no video channel.";
8285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return;
8295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
8305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
8315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!video_channel->ApplyViewRequest(view_request)) {
8325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_WARNING) << "Failed to ApplyViewRequest.";
8335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
8345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
8355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
8365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Call::OnRemoteDescriptionUpdate(BaseSession* base_session,
8375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                     const ContentInfos& updated_contents) {
8385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  Session* session = static_cast<Session*>(base_session);
8395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
8405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  const ContentInfo* audio_content = GetFirstAudioContent(updated_contents);
8415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (audio_content) {
8425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const AudioContentDescription* audio_update =
8435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        static_cast<const AudioContentDescription*>(audio_content->description);
8445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (!audio_update->codecs().empty()) {
8455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      UpdateVoiceChannelRemoteContent(session, audio_update);
8465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
8475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
8485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
8495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  const ContentInfo* video_content = GetFirstVideoContent(updated_contents);
8505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (video_content) {
8515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const VideoContentDescription* video_update =
8525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        static_cast<const VideoContentDescription*>(video_content->description);
8535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (!video_update->codecs().empty()) {
8545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      UpdateVideoChannelRemoteContent(session, video_update);
8555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
8565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
8575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
8585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  const ContentInfo* data_content = GetFirstDataContent(updated_contents);
8595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (data_content) {
8605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const DataContentDescription* data_update =
8615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        static_cast<const DataContentDescription*>(data_content->description);
8625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (!data_update->codecs().empty()) {
8635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      UpdateDataChannelRemoteContent(session, data_update);
8645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
8655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
8665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
8675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  UpdateRemoteMediaStreams(session, updated_contents, true);
8685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
8695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
8705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool Call::UpdateVoiceChannelRemoteContent(
8715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    Session* session, const AudioContentDescription* audio) {
8725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  VoiceChannel* voice_channel = GetVoiceChannel(session);
8735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!voice_channel->SetRemoteContent(audio, CA_UPDATE)) {
8745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_ERROR) << "Failure in audio SetRemoteContent with CA_UPDATE";
8755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    session->SetError(BaseSession::ERROR_CONTENT);
8765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
8775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
8785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return true;
8795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
8805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
8815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool Call::UpdateVideoChannelRemoteContent(
8825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    Session* session, const VideoContentDescription* video) {
8835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  VideoChannel* video_channel = GetVideoChannel(session);
8845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!video_channel->SetRemoteContent(video, CA_UPDATE)) {
8855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_ERROR) << "Failure in video SetRemoteContent with CA_UPDATE";
8865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    session->SetError(BaseSession::ERROR_CONTENT);
8875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
8885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
8895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return true;
8905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
8915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
8925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool Call::UpdateDataChannelRemoteContent(
8935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    Session* session, const DataContentDescription* data) {
8945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  DataChannel* data_channel = GetDataChannel(session);
8955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!data_channel->SetRemoteContent(data, CA_UPDATE)) {
8965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_ERROR) << "Failure in data SetRemoteContent with CA_UPDATE";
8975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    session->SetError(BaseSession::ERROR_CONTENT);
8985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
8995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
9005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return true;
9015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
9025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
9035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Call::UpdateRemoteMediaStreams(Session* session,
9045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                    const ContentInfos& updated_contents,
9055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                    bool update_channels) {
9065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  MediaStreams* recv_streams = GetMediaStreams(session);
9075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!recv_streams)
9085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return;
9095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
9105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  cricket::MediaStreams added_streams;
9115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  cricket::MediaStreams removed_streams;
9125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
9135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  const ContentInfo* audio_content = GetFirstAudioContent(updated_contents);
9145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (audio_content) {
9155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const AudioContentDescription* audio_update =
9165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        static_cast<const AudioContentDescription*>(audio_content->description);
9175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    UpdateRecvStreams(audio_update->streams(),
9185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                      update_channels ? GetVoiceChannel(session) : NULL,
9195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                      recv_streams->mutable_audio(),
9205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                      added_streams.mutable_audio(),
9215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                      removed_streams.mutable_audio());
9225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
9235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
9245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  const ContentInfo* video_content = GetFirstVideoContent(updated_contents);
9255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (video_content) {
9265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const VideoContentDescription* video_update =
9275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        static_cast<const VideoContentDescription*>(video_content->description);
9285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    UpdateRecvStreams(video_update->streams(),
9295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                      update_channels ? GetVideoChannel(session) : NULL,
9305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                      recv_streams->mutable_video(),
9315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                      added_streams.mutable_video(),
9325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                      removed_streams.mutable_video());
9335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
9345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
9355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  const ContentInfo* data_content = GetFirstDataContent(updated_contents);
9365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (data_content) {
9375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const DataContentDescription* data_update =
9385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        static_cast<const DataContentDescription*>(data_content->description);
9395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    UpdateRecvStreams(data_update->streams(),
9405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                      update_channels ? GetDataChannel(session) : NULL,
9415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                      recv_streams->mutable_data(),
9425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                      added_streams.mutable_data(),
9435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                      removed_streams.mutable_data());
9445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
9455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
9465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!added_streams.empty() || !removed_streams.empty()) {
9475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    SignalMediaStreamsUpdate(this, session, added_streams, removed_streams);
9485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
9495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
9505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
9515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid FindStreamChanges(const std::vector<StreamParams>& streams,
9525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                       const std::vector<StreamParams>& updates,
9535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                       std::vector<StreamParams>* added_streams,
9545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                       std::vector<StreamParams>* removed_streams) {
9555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  for (std::vector<StreamParams>::const_iterator update = updates.begin();
9565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org       update != updates.end(); ++update) {
9575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    StreamParams stream;
9585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (GetStreamByIds(streams, update->groupid, update->id, &stream)) {
9595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      if (!update->has_ssrcs()) {
9605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        removed_streams->push_back(stream);
9615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      }
9625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    } else {
9635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      // There's a bug on reflector that will send <stream>s even
9645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      // though there is not ssrc (which means there isn't really a
9655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      // stream).  To work around it, we simply ignore new <stream>s
9665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      // that don't have any ssrcs.
9675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      if (update->has_ssrcs()) {
9685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        added_streams->push_back(*update);
9695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      }
9705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
9715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
9725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
9735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
9745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Call::UpdateRecvStreams(const std::vector<StreamParams>& update_streams,
9755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                             BaseChannel* channel,
9765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                             std::vector<StreamParams>* recv_streams,
9775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                             std::vector<StreamParams>* added_streams,
9785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                             std::vector<StreamParams>* removed_streams) {
9795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  FindStreamChanges(*recv_streams,
9805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                    update_streams, added_streams, removed_streams);
9815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  AddRecvStreams(*added_streams,
9825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                 channel, recv_streams);
9835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  RemoveRecvStreams(*removed_streams,
9845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                    channel, recv_streams);
9855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
9865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
9875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Call::AddRecvStreams(const std::vector<StreamParams>& added_streams,
9885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                          BaseChannel* channel,
9895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                          std::vector<StreamParams>* recv_streams) {
9905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  std::vector<StreamParams>::const_iterator stream;
9915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  for (stream = added_streams.begin();
9925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org       stream != added_streams.end();
9935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org       ++stream) {
9945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    AddRecvStream(*stream, channel, recv_streams);
9955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
9965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
9975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
9985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Call::AddRecvStream(const StreamParams& stream,
9995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                         BaseChannel* channel,
10005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                         std::vector<StreamParams>* recv_streams) {
10015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (channel && stream.has_ssrcs()) {
10025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    channel->AddRecvStream(stream);
10035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
10045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  recv_streams->push_back(stream);
10055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
10065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
10075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Call::RemoveRecvStreams(const std::vector<StreamParams>& removed_streams,
10085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                             BaseChannel* channel,
10095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                             std::vector<StreamParams>* recv_streams) {
10105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  std::vector<StreamParams>::const_iterator stream;
10115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  for (stream = removed_streams.begin();
10125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org       stream != removed_streams.end();
10135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org       ++stream) {
10145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    RemoveRecvStream(*stream, channel, recv_streams);
10155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
10165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
10175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
10185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Call::RemoveRecvStream(const StreamParams& stream,
10195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                            BaseChannel* channel,
10205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                            std::vector<StreamParams>* recv_streams) {
10215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (channel && stream.has_ssrcs()) {
10225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // TODO(pthatcher): Change RemoveRecvStream to take a stream argument.
10235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    channel->RemoveRecvStream(stream.first_ssrc());
10245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
10255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  RemoveStreamByIds(recv_streams, stream.groupid, stream.id);
10265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
10275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
10285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid Call::OnReceivedTerminateReason(Session* session,
10295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                     const std::string& reason) {
10305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  session_client_->session_manager()->signaling_thread()->Clear(this,
10315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    MSG_TERMINATECALL);
10325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  SignalReceivedTerminateReason(this, session, reason);
10335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
10345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1035c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org// TODO(mdodd): Get ride of this method since all Hangouts are using a secure
1036c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org// connection.
1037c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.orgbool Call::secure() const {
1038c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org  if (session_client_->secure() == SEC_DISABLED) {
1039c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org    return false;
1040c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org  }
1041c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org
1042c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org  bool ret = true;
1043c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org  int i = 0;
1044c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org
1045c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org  MediaSessionMap::const_iterator it;
1046c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org  for (it = media_session_map_.begin(); it != media_session_map_.end(); ++it) {
1047c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org    LOG_F(LS_VERBOSE) << "session[" << i
1048c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org                      << "], check local and remote descriptions";
1049c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org    i++;
1050c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org
1051c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org    if (!SessionDescriptionContainsCrypto(
1052c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org            it->second.session->local_description()) ||
1053c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org        !SessionDescriptionContainsCrypto(
1054c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org            it->second.session->remote_description())) {
1055c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org      ret = false;
1056c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org      break;
1057c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org    }
1058c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org  }
1059c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org
1060c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org  LOG_F(LS_VERBOSE) << "secure=" << ret;
1061c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org  return ret;
1062c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org}
1063c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org
1064c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.orgbool Call::SessionDescriptionContainsCrypto(
1065c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org    const SessionDescription* sdesc) const {
1066c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org  if (sdesc == NULL) {
1067c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org    LOG_F(LS_VERBOSE) << "sessionDescription is NULL";
1068c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org    return false;
1069c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org  }
1070c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org
1071c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org  return ContentContainsCrypto(sdesc->GetContentByName(CN_AUDIO)) &&
1072c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org         ContentContainsCrypto(sdesc->GetContentByName(CN_VIDEO));
1073c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org}
1074c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org
1075c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.orgSession* Call::InternalInitiateSession(const std::string& id,
1076c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org                                       const buzz::Jid& to,
1077c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org                                       const std::string& initiator_name,
1078c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org                                       const CallOptions& options) {
1079c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org  const SessionDescription* offer = session_client_->CreateOffer(options);
1080c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org
1081c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org  Session* session = session_client_->CreateSession(id, this);
1082e73fa366a56d0c3c46860c534db19fffe110f167mallinath@webrtc.org  // Only override the initiator_name if it was manually supplied. Otherwise,
1083e73fa366a56d0c3c46860c534db19fffe110f167mallinath@webrtc.org  // session_client_ will supply the local jid as initiator in CreateOffer.
1084e73fa366a56d0c3c46860c534db19fffe110f167mallinath@webrtc.org  if (!initiator_name.empty()) {
1085e73fa366a56d0c3c46860c534db19fffe110f167mallinath@webrtc.org    session->set_initiator_name(initiator_name);
1086e73fa366a56d0c3c46860c534db19fffe110f167mallinath@webrtc.org  }
1087c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org
1088c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org  AddSession(session, offer);
1089c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org  session->Initiate(to.Str(), offer);
1090c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org
1091c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org  // After this timeout, terminate the call because the callee isn't
1092c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org  // answering
1093c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org  session_client_->session_manager()->signaling_thread()->Clear(this,
1094c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org      MSG_TERMINATECALL);
1095c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org  session_client_->session_manager()->signaling_thread()->PostDelayed(
1096c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org    send_to_voicemail_ ? kSendToVoicemailTimeout : kNoVoicemailTimeout,
1097c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org    this, MSG_TERMINATECALL);
1098c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org  return session;
1099c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org}
1100c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org
11015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}  // namespace cricket
1102