1f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch/*
2f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * libjingle
3f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * Copyright 2004--2007, Google Inc.
4f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *
5f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * Redistribution and use in source and binary forms, with or without
6f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * modification, are permitted provided that the following conditions are met:
7f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *
8f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *  1. Redistributions of source code must retain the above copyright notice,
9f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *     this list of conditions and the following disclaimer.
10f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *  2. Redistributions in binary form must reproduce the above copyright notice,
11f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *     this list of conditions and the following disclaimer in the documentation
12f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *     and/or other materials provided with the distribution.
13f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *  3. The name of the author may not be used to endorse or promote products
14f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *     derived from this software without specific prior written permission.
15f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *
16f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch */
27f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
28f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/session/phone/channel.h"
29dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
30dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "talk/base/buffer.h"
31f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/byteorder.h"
32f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/common.h"
33f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/logging.h"
34f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/p2p/base/transportchannel.h"
35f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/session/phone/channelmanager.h"
36f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/session/phone/mediasessionclient.h"
374a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "talk/session/phone/mediasink.h"
38dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "talk/session/phone/rtcpmuxfilter.h"
39f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
40f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochnamespace cricket {
41f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
42dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenstruct PacketMessageData : public talk_base::MessageData {
43dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  talk_base::Buffer packet;
44dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen};
45dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
46dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenstruct VoiceChannelErrorMessageData : public talk_base::MessageData {
47dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  VoiceChannelErrorMessageData(uint32 in_ssrc,
48dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                               VoiceMediaChannel::Error in_error)
49dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      : ssrc(in_ssrc),
50dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        error(in_error) {}
51dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  uint32 ssrc;
52dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  VoiceMediaChannel::Error error;
53dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen};
54dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
55dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenstruct VideoChannelErrorMessageData : public talk_base::MessageData {
56dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  VideoChannelErrorMessageData(uint32 in_ssrc,
57dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                               VideoMediaChannel::Error in_error)
58dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      : ssrc(in_ssrc),
59dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        error(in_error) {}
60dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  uint32 ssrc;
61dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  VideoMediaChannel::Error error;
62dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen};
63f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
64f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstatic const char* PacketType(bool rtcp) {
65f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return (!rtcp) ? "RTP" : "RTCP";
66f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
67f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
68dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenstatic bool ValidPacket(bool rtcp, const talk_base::Buffer* packet) {
69dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Check the packet size. We could check the header too if needed.
70dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return (packet &&
71dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      packet->length() >= (!rtcp ? kMinRtpPacketLen : kMinRtcpPacketLen) &&
72dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      packet->length() <= kMaxRtpPacketLen);
73dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
74dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
75dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenstatic uint16 GetRtpSeqNum(const talk_base::Buffer* packet) {
76dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return (packet->length() >= kMinRtpPacketLen) ?
77dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen       talk_base::GetBE16(packet->data() + 2) : 0;
78dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
79dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
80dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenstatic uint32 GetRtpSsrc(const talk_base::Buffer* packet) {
81dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return (packet->length() >= kMinRtpPacketLen) ?
82dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen       talk_base::GetBE32(packet->data() + 8) : 0;
83dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
84dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
85dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenstatic int GetRtcpType(const talk_base::Buffer* packet) {
86dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return (packet->length() >= kMinRtcpPacketLen) ?
87dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen       static_cast<int>(packet->data()[1]) : 0;
88dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
89dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
90f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochBaseChannel::BaseChannel(talk_base::Thread* thread, MediaEngine* media_engine,
91f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                         MediaChannel* media_channel, BaseSession* session,
92731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                         const std::string& content_name,
93f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                         TransportChannel* transport_channel)
944a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    : worker_thread_(thread),
954a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      media_engine_(media_engine),
964a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      session_(session),
974a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      media_channel_(media_channel),
984a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      received_media_sink_(NULL),
994a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      sent_media_sink_(NULL),
100731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      content_name_(content_name),
1014a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      transport_channel_(transport_channel),
1024a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      rtcp_transport_channel_(NULL),
1034a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      enabled_(false),
1044a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      writable_(false),
1054a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      has_codec_(false),
1064a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      muted_(false) {
107f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ASSERT(worker_thread_ == talk_base::Thread::Current());
108f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  media_channel_->SetInterface(this);
109f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  transport_channel_->SignalWritableState.connect(
110f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      this, &BaseChannel::OnWritableState);
111f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  transport_channel_->SignalReadPacket.connect(
112f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      this, &BaseChannel::OnChannelRead);
113f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
114f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  LOG(LS_INFO) << "Created channel";
115f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
116f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  session->SignalState.connect(this, &BaseChannel::OnSessionState);
117f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
118f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
119f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochBaseChannel::~BaseChannel() {
120f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ASSERT(worker_thread_ == talk_base::Thread::Current());
121f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  StopConnectionMonitor();
122dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  FlushRtcpMessages();  // Send any outstanding RTCP packets.
123dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  Clear();  // eats any outstanding messages or packets
124f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // We must destroy the media channel before the transport channel, otherwise
125f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // the media channel may try to send on the dead transport channel. NULLing
126f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // is not an effective strategy since the sends will come on another thread.
127f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  delete media_channel_;
128f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  set_rtcp_transport_channel(NULL);
129f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (transport_channel_ != NULL)
130731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    session_->DestroyChannel(content_name_, transport_channel_->name());
131f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  LOG(LS_INFO) << "Destroyed channel";
132f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
133f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
134f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool BaseChannel::Enable(bool enable) {
135f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // Can be called from thread other than worker thread
136f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  Send(enable ? MSG_ENABLE : MSG_DISABLE);
137f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return true;
138f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
139f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
140f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool BaseChannel::Mute(bool mute) {
141f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // Can be called from thread other than worker thread
142f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  Send(mute ? MSG_MUTE : MSG_UNMUTE);
143f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return true;
144f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
145f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
146f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool BaseChannel::RemoveStream(uint32 ssrc) {
147f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  StreamMessageData data(ssrc, 0);
148f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  Send(MSG_REMOVESTREAM, &data);
149f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return true;
150f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
151f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool BaseChannel::SetRtcpCName(const std::string& cname) {
1533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  SetRtcpCNameData data(cname);
1543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  Send(MSG_SETRTCPCNAME, &data);
155f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return data.result;
156f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
157f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool BaseChannel::SetLocalContent(const MediaContentDescription* content,
1593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                  ContentAction action) {
1603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  SetContentData data(content, action);
1613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  Send(MSG_SETLOCALCONTENT, &data);
1623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return data.result;
1633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
1643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool BaseChannel::SetRemoteContent(const MediaContentDescription* content,
1663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   ContentAction action) {
1673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  SetContentData data(content, action);
1683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  Send(MSG_SETREMOTECONTENT, &data);
169f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return data.result;
170f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
171f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
172f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool BaseChannel::SetMaxSendBandwidth(int max_bandwidth) {
173f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  SetBandwidthData data(max_bandwidth);
174f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  Send(MSG_SETMAXSENDBANDWIDTH, &data);
175f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return data.result;
176f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
177f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
178f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid BaseChannel::StartConnectionMonitor(int cms) {
179f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  socket_monitor_.reset(new SocketMonitor(transport_channel_,
180f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                          worker_thread(),
181f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                          talk_base::Thread::Current()));
182f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  socket_monitor_->SignalUpdate.connect(
183f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      this, &BaseChannel::OnConnectionMonitorUpdate);
184f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  socket_monitor_->Start(cms);
185f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
186f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
187f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid BaseChannel::StopConnectionMonitor() {
188f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (socket_monitor_.get()) {
189f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    socket_monitor_->Stop();
190f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    socket_monitor_.reset();
191f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
192f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
193f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
194f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid BaseChannel::set_rtcp_transport_channel(TransportChannel* channel) {
195f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (rtcp_transport_channel_ != channel) {
196f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (rtcp_transport_channel_) {
197731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      session_->DestroyChannel(content_name_, rtcp_transport_channel_->name());
198f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
199f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    rtcp_transport_channel_ = channel;
200f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (rtcp_transport_channel_) {
201f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      rtcp_transport_channel_->SignalWritableState.connect(
202f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          this, &BaseChannel::OnWritableState);
203f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      rtcp_transport_channel_->SignalReadPacket.connect(
204f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          this, &BaseChannel::OnChannelRead);
205f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
206f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
207f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
208f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
209dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenbool BaseChannel::SendPacket(talk_base::Buffer* packet) {
210dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return SendPacket(false, packet);
211f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
212f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
213dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenbool BaseChannel::SendRtcp(talk_base::Buffer* packet) {
214dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return SendPacket(true, packet);
215f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
216f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
217f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochint BaseChannel::SetOption(SocketType type, talk_base::Socket::Option opt,
218f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                           int value) {
219f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  switch (type) {
220f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case ST_RTP: return transport_channel_->SetOption(opt, value);
221f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case ST_RTCP: return rtcp_transport_channel_->SetOption(opt, value);
222f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    default: return -1;
223f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
224f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
225f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
226f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid BaseChannel::OnWritableState(TransportChannel* channel) {
227f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ASSERT(channel == transport_channel_ || channel == rtcp_transport_channel_);
228f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (transport_channel_->writable()
229f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      && (!rtcp_transport_channel_ || rtcp_transport_channel_->writable())) {
230f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ChannelWritable_w();
231f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  } else {
232f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ChannelNotWritable_w();
233f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
234f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
235f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
236f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid BaseChannel::OnChannelRead(TransportChannel* channel,
237f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                const char* data, size_t len) {
238f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // OnChannelRead gets called from P2PSocket; now pass data to MediaEngine
239f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ASSERT(worker_thread_ == talk_base::Thread::Current());
240f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
241dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  talk_base::Buffer packet(data, len);
242f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // When using RTCP multiplexing we might get RTCP packets on the RTP
243f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // transport. We feed RTP traffic into the demuxer to determine if it is RTCP.
244f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bool rtcp = (channel == rtcp_transport_channel_ ||
245dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen               rtcp_mux_filter_.DemuxRtcp(packet.data(), packet.length()));
246dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  HandlePacket(rtcp, &packet);
247dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
248dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
249dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenbool BaseChannel::SendPacket(bool rtcp, talk_base::Buffer* packet) {
250dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // SendPacket gets called from MediaEngine, typically on an encoder thread.
251dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // If the thread is not our worker thread, we will post to our worker
252dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // so that the real work happens on our worker. This avoids us having to
253dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // synchronize access to all the pieces of the send path, including
254dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // SRTP and the inner workings of the transport channels.
255dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // The only downside is that we can't return a proper failure code if
256dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // needed. Since UDP is unreliable anyway, this should be a non-issue.
257dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (talk_base::Thread::Current() != worker_thread_) {
258dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // Avoid a copy by transferring the ownership of the packet data.
259dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    int message_id = (!rtcp) ? MSG_RTPPACKET : MSG_RTCPPACKET;
260dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    PacketMessageData* data = new PacketMessageData;
261dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    packet->TransferTo(&data->packet);
262dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    worker_thread_->Post(this, message_id, data);
263dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return true;
264f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
265f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
266f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // Make sure we have a place to send this packet before doing anything.
267f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // (We might get RTCP packets that we don't intend to send.)
268f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // If we've negotiated RTCP mux, send RTCP over the RTP transport.
269f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  TransportChannel* channel = (!rtcp || rtcp_mux_filter_.IsActive()) ?
270f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      transport_channel_ : rtcp_transport_channel_;
271f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!channel) {
272dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return false;
273f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
274f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
275dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Protect ourselves against crazy data.
276dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!ValidPacket(rtcp, packet)) {
277dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    LOG(LS_ERROR) << "Dropping outgoing " << content_name_ << " "
278dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                  << PacketType(rtcp) << " packet: wrong size="
279dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                  << packet->length();
280dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return false;
281f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
282f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
283dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Push the packet down to the media sink.
284dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Need to do this before protecting the packet.
2854a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  {
2864a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    talk_base::CritScope cs(&sink_critical_section_);
2874a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    if (sent_media_sink_) {
2884a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      if (!rtcp) {
289dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        sent_media_sink_->OnRtpPacket(packet->data(), packet->length());
2904a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      } else {
291dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        sent_media_sink_->OnRtcpPacket(packet->data(), packet->length());
2924a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      }
2934a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    }
2944a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  }
2954a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
296dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Protect if needed.
297dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (srtp_filter_.IsActive()) {
298dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    bool res;
299dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    char* data = packet->data();
300dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    int len = packet->length();
301dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (!rtcp) {
302dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      res = srtp_filter_.ProtectRtp(data, len, packet->capacity(), &len);
303dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      if (!res) {
304dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        LOG(LS_ERROR) << "Failed to protect " << content_name_
305dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                      << " RTP packet: size=" << len
306dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                      << ", seqnum=" << GetRtpSeqNum(packet)
307dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                      << ", SSRC=" << GetRtpSsrc(packet);
308dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        return false;
309dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      }
310dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    } else {
311dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      res = srtp_filter_.ProtectRtcp(data, len, packet->capacity(), &len);
312dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      if (!res) {
313dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        LOG(LS_ERROR) << "Failed to protect " << content_name_
314dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                     << " RTCP packet: size=" << len
315dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                      << ", type=" << GetRtcpType(packet);
316dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        return false;
317dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      }
318dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
319dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
320dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // Update the length of the packet now that we've added the auth tag.
321dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    packet->SetLength(len);
322dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
323dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
324dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Bon voyage.
325dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return (channel->SendPacket(packet->data(), packet->length())
326dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      == static_cast<int>(packet->length()));
327f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
328f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
329dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid BaseChannel::HandlePacket(bool rtcp, talk_base::Buffer* packet) {
330f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // Protect ourselvs against crazy data.
331dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!ValidPacket(rtcp, packet)) {
332dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    LOG(LS_ERROR) << "Dropping incoming " << content_name_ << " "
333dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                  << PacketType(rtcp) << " packet: wrong size="
334dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                  << packet->length();
335f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return;
336f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
337f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
338f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // Unprotect the packet, if needed.
339f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (srtp_filter_.IsActive()) {
340dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    char* data = packet->data();
341dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    int len = packet->length();
342f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    bool res;
343f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (!rtcp) {
344dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      res = srtp_filter_.UnprotectRtp(data, len, &len);
345dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      if (!res) {
346dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        LOG(LS_ERROR) << "Failed to unprotect " << content_name_
347dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                      << " RTP packet: size=" << len
348dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                      << ", seqnum=" << GetRtpSeqNum(packet)
349dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                      << ", SSRC=" << GetRtpSsrc(packet);
350dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        return;
351dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      }
352f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    } else {
353dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      res = srtp_filter_.UnprotectRtcp(data, len, &len);
354dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      if (!res) {
355dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        LOG(LS_ERROR) << "Failed to unprotect " << content_name_
356dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                      << " RTCP packet: size=" << len
357dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                      << ", type=" << GetRtcpType(packet);
358dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        return;
359dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      }
360f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
361dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
362dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    packet->SetLength(len);
363f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
364f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
365f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // Push it down to the media channel.
366f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!rtcp) {
367dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    media_channel_->OnPacketReceived(packet);
368f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  } else {
369dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    media_channel_->OnRtcpReceived(packet);
370f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
3714a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
372dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Push it down to the media sink.
3734a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  {
3744a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    talk_base::CritScope cs(&sink_critical_section_);
3754a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    if (received_media_sink_) {
3764a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      if (!rtcp) {
377dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        received_media_sink_->OnRtpPacket(packet->data(), packet->length());
3784a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      } else {
379dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        received_media_sink_->OnRtcpPacket(packet->data(), packet->length());
3804a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      }
3814a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    }
3824a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  }
383f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
384f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
385f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid BaseChannel::OnSessionState(BaseSession* session,
386f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                 BaseSession::State state) {
3873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const MediaContentDescription* content = NULL;
388f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  switch (state) {
389f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case Session::STATE_SENTINITIATE:
3903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      content = GetFirstContent(session->local_description());
391dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      if (content && !SetLocalContent(content, CA_OFFER)) {
392dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        LOG(LS_ERROR) << "Failure in SetLocalContent with CA_OFFER";
393dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        session->SetError(BaseSession::ERROR_CONTENT);
3943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      }
3953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      break;
396f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case Session::STATE_SENTACCEPT:
3973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      content = GetFirstContent(session->local_description());
398dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      if (content && !SetLocalContent(content, CA_ANSWER)) {
399dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        LOG(LS_ERROR) << "Failure in SetLocalContent with CA_ANSWER";
400dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        session->SetError(BaseSession::ERROR_CONTENT);
401f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      }
402f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      break;
403f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case Session::STATE_RECEIVEDINITIATE:
4043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      content = GetFirstContent(session->remote_description());
405dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      if (content && !SetRemoteContent(content, CA_OFFER)) {
406dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        LOG(LS_ERROR) << "Failure in SetRemoteContent with CA_OFFER";
407dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        session->SetError(BaseSession::ERROR_CONTENT);
4083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      }
4093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      break;
410f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case Session::STATE_RECEIVEDACCEPT:
4113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      content = GetFirstContent(session->remote_description());
412dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      if (content && !SetRemoteContent(content, CA_ANSWER)) {
413dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        LOG(LS_ERROR) << "Failure in SetRemoteContent with CA_ANSWER";
414dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        session->SetError(BaseSession::ERROR_CONTENT);
415f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      }
416f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      break;
417f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    default:
418f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      break;
419f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
420f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
421f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
422f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid BaseChannel::EnableMedia_w() {
423f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ASSERT(worker_thread_ == talk_base::Thread::Current());
424f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (enabled_)
425f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return;
426f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
427f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  LOG(LS_INFO) << "Channel enabled";
428f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  enabled_ = true;
429f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ChangeState();
430f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
431f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
432f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid BaseChannel::DisableMedia_w() {
433f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ASSERT(worker_thread_ == talk_base::Thread::Current());
434f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!enabled_)
435f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return;
436f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
437f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  LOG(LS_INFO) << "Channel disabled";
438f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  enabled_ = false;
439f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ChangeState();
440f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
441f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
442f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid BaseChannel::MuteMedia_w() {
443f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ASSERT(worker_thread_ == talk_base::Thread::Current());
444f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (muted_)
445f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return;
446f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
447f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (media_channel()->Mute(true)) {
448f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LS_INFO) << "Channel muted";
449f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    muted_ = true;
450f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
451f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
452f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
453f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid BaseChannel::UnmuteMedia_w() {
454f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ASSERT(worker_thread_ == talk_base::Thread::Current());
455f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!muted_)
456f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return;
457f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
458f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (media_channel()->Mute(false)) {
459f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LS_INFO) << "Channel unmuted";
460f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    muted_ = false;
461f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
462f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
463f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
464f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid BaseChannel::ChannelWritable_w() {
465f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ASSERT(worker_thread_ == talk_base::Thread::Current());
466f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (writable_)
467f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return;
468f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  LOG(LS_INFO) << "Channel socket writable ("
469f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch               << transport_channel_->name().c_str() << ")";
470f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  writable_ = true;
471f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ChangeState();
472f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
473f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
474f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid BaseChannel::ChannelNotWritable_w() {
475f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ASSERT(worker_thread_ == talk_base::Thread::Current());
476f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!writable_)
477f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return;
478f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
479f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  LOG(LS_INFO) << "Channel socket not writable ("
480f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch               << transport_channel_->name().c_str() << ")";
481f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  writable_ = false;
482f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ChangeState();
483f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
484f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
4854a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// Sets the maximum video bandwidth for automatic bandwidth adjustment.
486f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool BaseChannel::SetMaxSendBandwidth_w(int max_bandwidth) {
4874a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  return media_channel()->SetSendBandwidth(true, max_bandwidth);
488f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
489f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
4903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool BaseChannel::SetRtcpCName_w(const std::string& cname) {
4913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return media_channel()->SetRtcpCName(cname);
4923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
4933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
494f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool BaseChannel::SetSrtp_w(const std::vector<CryptoParams>& cryptos,
4953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                            ContentAction action, ContentSource src) {
496f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bool ret;
4973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (action == CA_OFFER) {
498f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ret = srtp_filter_.SetOffer(cryptos, src);
4993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  } else if (action == CA_ANSWER) {
500f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ret = srtp_filter_.SetAnswer(cryptos, src);
501f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  } else {
5023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // CA_UPDATE, no crypto params.
503f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ret = true;
504f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
505f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return ret;
506f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
507f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
5083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool BaseChannel::SetRtcpMux_w(bool enable, ContentAction action,
5093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                               ContentSource src) {
510f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bool ret;
5113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (action == CA_OFFER) {
512f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ret = rtcp_mux_filter_.SetOffer(enable, src);
5133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  } else if (action == CA_ANSWER) {
514f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ret = rtcp_mux_filter_.SetAnswer(enable, src);
515f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (ret && rtcp_mux_filter_.IsActive()) {
516f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      // We activated RTCP mux, close down the RTCP transport.
517f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      set_rtcp_transport_channel(NULL);
518f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      // If the RTP transport is already writable, then so are we.
519f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      if (transport_channel_->writable()) {
520f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        ChannelWritable_w();
521f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      }
522f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
523f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  } else {
5243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // CA_UPDATE, no RTCP mux info.
525f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ret = true;
526f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
527f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return ret;
528f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
529f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
530f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid BaseChannel::OnMessage(talk_base::Message *pmsg) {
531f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  switch (pmsg->message_id) {
532f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case MSG_ENABLE:
533f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      EnableMedia_w();
534f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      break;
535f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case MSG_DISABLE:
536f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      DisableMedia_w();
537f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      break;
538f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
539f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case MSG_MUTE:
540f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      MuteMedia_w();
541f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      break;
542f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case MSG_UNMUTE:
543f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      UnmuteMedia_w();
544f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      break;
545f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
5463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    case MSG_SETRTCPCNAME: {
5473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      SetRtcpCNameData* data = static_cast<SetRtcpCNameData*>(pmsg->pdata);
5483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      data->result = SetRtcpCName_w(data->cname);
5493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      break;
5503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
5513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
5523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    case MSG_SETLOCALCONTENT: {
5533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      SetContentData* data = static_cast<SetContentData*>(pmsg->pdata);
5543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      data->result = SetLocalContent_w(data->content, data->action);
555f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      break;
556f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
5573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    case MSG_SETREMOTECONTENT: {
5583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      SetContentData* data = static_cast<SetContentData*>(pmsg->pdata);
5593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      data->result = SetRemoteContent_w(data->content, data->action);
560f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      break;
561f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
562f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
563f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case MSG_REMOVESTREAM: {
564f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      StreamMessageData* data = static_cast<StreamMessageData*>(pmsg->pdata);
565f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      RemoveStream_w(data->ssrc1);
566f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      break;
567f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
568f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
569f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case MSG_SETMAXSENDBANDWIDTH: {
570f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      SetBandwidthData* data = static_cast<SetBandwidthData*>(pmsg->pdata);
571f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      data->result = SetMaxSendBandwidth_w(data->value);
572f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      break;
573f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
574dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
575dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    case MSG_RTPPACKET:
576dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    case MSG_RTCPPACKET: {
577dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      PacketMessageData* data = static_cast<PacketMessageData*>(pmsg->pdata);
578dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      SendPacket(pmsg->message_id == MSG_RTCPPACKET, &data->packet);
579dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      delete data;  // because it is Posted
580dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      break;
581dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
582f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
583f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
584f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
585f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid BaseChannel::Send(uint32 id, talk_base::MessageData *pdata) {
586f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  worker_thread_->Send(this, id, pdata);
587f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
588f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
589f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid BaseChannel::Post(uint32 id, talk_base::MessageData *pdata) {
590f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  worker_thread_->Post(this, id, pdata);
591f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
592f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
593f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid BaseChannel::PostDelayed(int cmsDelay, uint32 id,
594f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                              talk_base::MessageData *pdata) {
595f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  worker_thread_->PostDelayed(cmsDelay, this, id, pdata);
596f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
597f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
598f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid BaseChannel::Clear(uint32 id, talk_base::MessageList* removed) {
599f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  worker_thread_->Clear(this, id, removed);
600f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
601f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
602dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid BaseChannel::FlushRtcpMessages() {
603dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Flush all remaining RTCP messages. This should only be called in
604dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // destructor.
605dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ASSERT(talk_base::Thread::Current() == worker_thread_);
606dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  talk_base::MessageList rtcp_messages;
607dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  Clear(MSG_RTCPPACKET, &rtcp_messages);
608dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  for (talk_base::MessageList::iterator it = rtcp_messages.begin();
609dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen       it != rtcp_messages.end(); ++it) {
610dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    Send(MSG_RTCPPACKET, it->pdata);
611dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
612dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
613dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
614f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochVoiceChannel::VoiceChannel(talk_base::Thread* thread,
615f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                           MediaEngine* media_engine,
616f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                           VoiceMediaChannel* media_channel,
617f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                           BaseSession* session,
618731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                           const std::string& content_name,
619f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                           bool rtcp)
620731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    : BaseChannel(thread, media_engine, media_channel, session, content_name,
621731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                  session->CreateChannel(content_name, "rtp")),
622f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      received_media_(false) {
623f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (rtcp) {
624731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    set_rtcp_transport_channel(session->CreateChannel(content_name, "rtcp"));
625f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
626731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // Can't go in BaseChannel because certain session states will
627731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // trigger pure virtual functions, such as GetFirstContent().
628731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  OnSessionState(session, session->state());
629dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
630dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  media_channel->SignalMediaError.connect(
631dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      this, &VoiceChannel::OnVoiceChannelError);
632f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
633f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
634f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochVoiceChannel::~VoiceChannel() {
635f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  StopAudioMonitor();
636f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  StopMediaMonitor();
637f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // this can't be done in the base class, since it calls a virtual
638f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  DisableMedia_w();
639f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
640f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
641f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool VoiceChannel::AddStream(uint32 ssrc) {
642f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  StreamMessageData data(ssrc, 0);
643f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  Send(MSG_ADDSTREAM, &data);
644f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return true;
645f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
646f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
647f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool VoiceChannel::SetRingbackTone(const void* buf, int len) {
648f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  SetRingbackToneMessageData data(buf, len);
649f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  Send(MSG_SETRINGBACKTONE, &data);
650f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return true;
651f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
652f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
653731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// TODO: Handle early media the right way. We should get an explicit
654f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// ringing message telling us to start playing local ringback, which we cancel
655f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// if any early media actually arrives. For now, we do the opposite, which is
656f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// to wait 1 second for early media, and start playing local ringback if none
657f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// arrives.
658f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid VoiceChannel::SetEarlyMedia(bool enable) {
659f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (enable) {
660f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // Start the early media timeout
661f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    PostDelayed(kEarlyMediaTimeout, MSG_EARLYMEDIATIMEOUT);
662f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  } else {
663f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // Stop the timeout if currently going.
664f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    Clear(MSG_EARLYMEDIATIMEOUT);
665f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
666f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
667f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
668f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool VoiceChannel::PlayRingbackTone(bool play, bool loop) {
669f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  PlayRingbackToneMessageData data(play, loop);
670f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  Send(MSG_PLAYRINGBACKTONE, &data);
671f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return data.result;
672f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
673f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
674f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool VoiceChannel::PressDTMF(int digit, bool playout) {
675f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  DtmfMessageData data(digit, playout);
676f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  Send(MSG_PRESSDTMF, &data);
677f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return data.result;
678f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
679f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
680f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid VoiceChannel::StartMediaMonitor(int cms) {
681f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  media_monitor_.reset(new VoiceMediaMonitor(media_channel(), worker_thread(),
682f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      talk_base::Thread::Current()));
683f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  media_monitor_->SignalUpdate.connect(
684f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      this, &VoiceChannel::OnMediaMonitorUpdate);
685f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  media_monitor_->Start(cms);
686f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
687f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
688f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid VoiceChannel::StopMediaMonitor() {
689f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (media_monitor_.get()) {
690f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    media_monitor_->Stop();
691f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    media_monitor_->SignalUpdate.disconnect(this);
692f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    media_monitor_.reset();
693f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
694f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
695f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
696f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid VoiceChannel::StartAudioMonitor(int cms) {
697f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  audio_monitor_.reset(new AudioMonitor(this, talk_base::Thread::Current()));
698f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  audio_monitor_
699f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ->SignalUpdate.connect(this, &VoiceChannel::OnAudioMonitorUpdate);
700f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  audio_monitor_->Start(cms);
701f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
702f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
703f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid VoiceChannel::StopAudioMonitor() {
704f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (audio_monitor_.get()) {
705f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    audio_monitor_->Stop();
706f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    audio_monitor_.reset();
707f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
708f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
709f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
710f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochint VoiceChannel::GetInputLevel_w() {
711f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return media_engine()->GetInputLevel();
712f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
713f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
714f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochint VoiceChannel::GetOutputLevel_w() {
715f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return media_channel()->GetOutputLevel();
716f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
717f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
718f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid VoiceChannel::GetActiveStreams_w(AudioInfo::StreamList* actives) {
719f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  media_channel()->GetActiveStreams(actives);
720f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
721f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
722f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid VoiceChannel::OnChannelRead(TransportChannel* channel,
723f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                 const char* data, size_t len) {
724f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  BaseChannel::OnChannelRead(channel, data, len);
725f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
726f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // Set a flag when we've received an RTP packet. If we're waiting for early
727f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // media, this will disable the timeout.
728f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // If we were playing out our local ringback, make sure it is stopped to
729f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // prevent it from interfering with the incoming media.
730f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!received_media_) {
731dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (!PlayRingbackTone_w(false, false)) {
732dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      LOG(LS_ERROR) << "Failed to stop ringback tone.";
733dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      SendLastMediaError();
734dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
735f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
736f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
737f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
738f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid VoiceChannel::ChangeState() {
739f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // render incoming data if we are the active call
740f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // we receive data on the default channel and multiplexed streams
741f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bool recv = enabled();
742dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!media_channel()->SetPlayout(recv)) {
743dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    SendLastMediaError();
744dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
745f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
746f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // send outgoing data if we are the active call, have the
747f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // remote party's codec, and have a writable transport
748f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // we only send data on the default channel
749f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bool send = enabled() && has_codec() && writable();
750dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  SendFlags send_flag = send ? SEND_MICROPHONE : SEND_NOTHING;
751dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!media_channel()->SetSend(send_flag)) {
752dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    LOG(LS_ERROR) << "Failed to SetSend " << send_flag << " on voice channel";
753dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    SendLastMediaError();
754dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
755f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
756f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  LOG(LS_INFO) << "Changing voice state, recv=" << recv << " send=" << send;
757f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
758f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
7593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst MediaContentDescription* VoiceChannel::GetFirstContent(
7603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const SessionDescription* sdesc) {
7613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const ContentInfo* cinfo = GetFirstAudioContent(sdesc);
7623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (cinfo == NULL)
7633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return NULL;
7643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
7653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return static_cast<const MediaContentDescription*>(cinfo->description);
7663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
7673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
7683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool VoiceChannel::SetLocalContent_w(const MediaContentDescription* content,
7693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     ContentAction action) {
770f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ASSERT(worker_thread() == talk_base::Thread::Current());
771f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  LOG(LS_INFO) << "Setting local voice description";
772f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
7733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const AudioContentDescription* audio =
7743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      static_cast<const AudioContentDescription*>(content);
7753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT(audio != NULL);
7763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
777f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bool ret;
778f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // set SRTP
7793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ret = SetSrtp_w(audio->cryptos(), action, CS_LOCAL);
780f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // set RTCP mux
781f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (ret) {
7823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    ret = SetRtcpMux_w(audio->rtcp_mux(), action, CS_LOCAL);
783f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
784f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // set payload type and config for voice codecs
785f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (ret) {
7863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    ret = media_channel()->SetRecvCodecs(audio->codecs());
787f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
788f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return ret;
789f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
790f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
7913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool VoiceChannel::SetRemoteContent_w(const MediaContentDescription* content,
7923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                      ContentAction action) {
793f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ASSERT(worker_thread() == talk_base::Thread::Current());
794f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  LOG(LS_INFO) << "Setting remote voice description";
795f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
7963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const AudioContentDescription* audio =
7973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      static_cast<const AudioContentDescription*>(content);
7983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT(audio != NULL);
7993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
800f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bool ret;
801f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // set the sending SSRC, if the remote side gave us one
8023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (audio->ssrc_set()) {
8033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    media_channel()->SetSendSsrc(audio->ssrc());
804f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
805f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // set SRTP
8063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ret = SetSrtp_w(audio->cryptos(), action, CS_REMOTE);
807f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // set RTCP mux
808f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (ret) {
8093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    ret = SetRtcpMux_w(audio->rtcp_mux(), action, CS_REMOTE);
810f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
811f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // set codecs and payload types
812f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (ret) {
8133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    ret = media_channel()->SetSendCodecs(audio->codecs());
814f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
815731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
816dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  int audio_options = 0;
817dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (audio->conference_mode()) {
818dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    audio_options |= OPT_CONFERENCE;
819dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
8204a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  if (!media_channel()->SetOptions(audio_options)) {
8214a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    // Log an error on failure, but don't abort the call.
8224a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    LOG(LS_ERROR) << "Failed to set voice channel options";
8234a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  }
824731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
825f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // update state
826f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (ret) {
827f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    set_has_codec(true);
828f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ChangeState();
829f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
830f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return ret;
831f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
832f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
833f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid VoiceChannel::AddStream_w(uint32 ssrc) {
834f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ASSERT(worker_thread() == talk_base::Thread::Current());
835f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  media_channel()->AddStream(ssrc);
836f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
837f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
838f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid VoiceChannel::RemoveStream_w(uint32 ssrc) {
839f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  media_channel()->RemoveStream(ssrc);
840f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
841f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
842f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid VoiceChannel::SetRingbackTone_w(const void* buf, int len) {
843f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ASSERT(worker_thread() == talk_base::Thread::Current());
844f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  media_channel()->SetRingbackTone(static_cast<const char*>(buf), len);
845f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
846f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
847f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool VoiceChannel::PlayRingbackTone_w(bool play, bool loop) {
848f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ASSERT(worker_thread() == talk_base::Thread::Current());
849f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (play) {
850f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LS_INFO) << "Playing ringback tone, loop=" << loop;
851f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  } else {
852f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LS_INFO) << "Stopping ringback tone";
853f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
854f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return media_channel()->PlayRingbackTone(play, loop);
855f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
856f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
857f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid VoiceChannel::HandleEarlyMediaTimeout() {
858f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // This occurs on the main thread, not the worker thread.
859f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!received_media_) {
860f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LS_INFO) << "No early media received before timeout";
861f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    SignalEarlyMediaTimeout(this);
862f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
863f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
864f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
865f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool VoiceChannel::PressDTMF_w(int digit, bool playout) {
866f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!enabled() || !writable()) {
867f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
868f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
869f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
870f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return media_channel()->PressDTMF(digit, playout);
871f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
872f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
873f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid VoiceChannel::OnMessage(talk_base::Message *pmsg) {
874f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  switch (pmsg->message_id) {
875f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case MSG_ADDSTREAM: {
876f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      StreamMessageData* data = static_cast<StreamMessageData*>(pmsg->pdata);
877f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      AddStream_w(data->ssrc1);
878f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      break;
879f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
880f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case MSG_SETRINGBACKTONE: {
881f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      SetRingbackToneMessageData* data =
882f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          static_cast<SetRingbackToneMessageData*>(pmsg->pdata);
883f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      SetRingbackTone_w(data->buf, data->len);
884f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      break;
885f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
886f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case MSG_PLAYRINGBACKTONE: {
887f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      PlayRingbackToneMessageData* data =
888f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          static_cast<PlayRingbackToneMessageData*>(pmsg->pdata);
889f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      data->result = PlayRingbackTone_w(data->play, data->loop);
890f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      break;
891f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
892f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case MSG_EARLYMEDIATIMEOUT:
893f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      HandleEarlyMediaTimeout();
894f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      break;
895f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case MSG_PRESSDTMF: {
896f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      DtmfMessageData* data = static_cast<DtmfMessageData*>(pmsg->pdata);
897f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      data->result = PressDTMF_w(data->digit, data->playout);
898f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      break;
899f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
900dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    case MSG_CHANNEL_ERROR: {
901dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      VoiceChannelErrorMessageData* data =
902dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          static_cast<VoiceChannelErrorMessageData*>(pmsg->pdata);
903dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      SignalMediaError(this, data->ssrc, data->error);
904dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      delete data;
905dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      break;
906dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
907f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
908f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    default:
909f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      BaseChannel::OnMessage(pmsg);
910f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      break;
911f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
912f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
913f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
914f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid VoiceChannel::OnConnectionMonitorUpdate(
915f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    SocketMonitor* monitor, const std::vector<ConnectionInfo>& infos) {
916f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  SignalConnectionMonitor(this, infos);
917f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
918f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
919f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid VoiceChannel::OnMediaMonitorUpdate(
920f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    VoiceMediaChannel* media_channel, const VoiceMediaInfo& info) {
921f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ASSERT(media_channel == this->media_channel());
922f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  SignalMediaMonitor(this, info);
923f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
924f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
925f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid VoiceChannel::OnAudioMonitorUpdate(AudioMonitor* monitor,
926f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                        const AudioInfo& info) {
927f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  SignalAudioMonitor(this, info);
928f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
929f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
930dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid VoiceChannel::OnVoiceChannelError(
931dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    uint32 ssrc, VoiceMediaChannel::Error error) {
932dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  VoiceChannelErrorMessageData *data = new VoiceChannelErrorMessageData(
933dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      ssrc, error);
934dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  signaling_thread()->Post(this, MSG_CHANNEL_ERROR, data);
935dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
936dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
937f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochVideoChannel::VideoChannel(talk_base::Thread* thread,
938f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                           MediaEngine* media_engine,
939f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                           VideoMediaChannel* media_channel,
940731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                           BaseSession* session,
941731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                           const std::string& content_name,
942731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                           bool rtcp,
943f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                           VoiceChannel* voice_channel)
944731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    : BaseChannel(thread, media_engine, media_channel, session, content_name,
945731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                  session->CreateChannel(content_name, "video_rtp")),
946f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      voice_channel_(voice_channel), renderer_(NULL) {
947f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (rtcp) {
948731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    set_rtcp_transport_channel(
949731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        session->CreateChannel(content_name, "video_rtcp"));
950f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
951731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // Can't go in BaseChannel because certain session states will
952731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // trigger pure virtual functions, such as GetFirstContent()
953731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  OnSessionState(session, session->state());
9544a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
955dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  media_channel->SignalMediaError.connect(
956dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      this, &VideoChannel::OnVideoChannelError);
957dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
958dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
959dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid VoiceChannel::SendLastMediaError() {
960dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  uint32 ssrc;
961dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  VoiceMediaChannel::Error error;
962dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  media_channel()->GetLastMediaError(&ssrc, &error);
963dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  SignalMediaError(this, ssrc, error);
964f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
965f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
966f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochVideoChannel::~VideoChannel() {
967f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  StopMediaMonitor();
968f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // this can't be done in the base class, since it calls a virtual
969f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  DisableMedia_w();
970f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
971f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
972f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool VideoChannel::AddStream(uint32 ssrc, uint32 voice_ssrc) {
973f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  StreamMessageData data(ssrc, voice_ssrc);
974f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  Send(MSG_ADDSTREAM, &data);
975f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return true;
976f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
977f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
978f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool VideoChannel::SetRenderer(uint32 ssrc, VideoRenderer* renderer) {
979f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  RenderMessageData data(ssrc, renderer);
980f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  Send(MSG_SETRENDERER, &data);
981f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return true;
982f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
983f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
984f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
9854a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
9864a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochbool VideoChannel::SendIntraFrame() {
9874a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  Send(MSG_SENDINTRAFRAME);
9884a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  return true;
9894a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch}
9904a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochbool VideoChannel::RequestIntraFrame() {
9914a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  Send(MSG_REQUESTINTRAFRAME);
9924a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  return true;
9934a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch}
9944a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
995f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid VideoChannel::ChangeState() {
996f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // render incoming data if we are the active call
997f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // we receive data on the default channel and multiplexed streams
998f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bool recv = enabled();
999dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!media_channel()->SetRender(recv)) {
1000dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    LOG(LS_ERROR) << "Failed to SetRender on video channel";
1001dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // TODO: Report error back to server.
1002dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
1003f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1004f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // send outgoing data if we are the active call, have the
1005f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // remote party's codec, and have a writable transport
1006f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // we only send data on the default channel
1007f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bool send = enabled() && has_codec() && writable();
1008dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!media_channel()->SetSend(send)) {
1009dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    LOG(LS_ERROR) << "Failed to SetSend on video channel";
1010dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // TODO: Report error back to server.
1011dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
1012f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1013f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  LOG(LS_INFO) << "Changing video state, recv=" << recv << " send=" << send;
1014f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
1015f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1016f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid VideoChannel::StartMediaMonitor(int cms) {
1017f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  media_monitor_.reset(new VideoMediaMonitor(media_channel(), worker_thread(),
1018f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      talk_base::Thread::Current()));
1019f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  media_monitor_->SignalUpdate.connect(
1020f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      this, &VideoChannel::OnMediaMonitorUpdate);
1021f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  media_monitor_->Start(cms);
1022f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
1023f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1024f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid VideoChannel::StopMediaMonitor() {
1025f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (media_monitor_.get()) {
1026f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    media_monitor_->Stop();
1027f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    media_monitor_.reset();
1028f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
1029f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
1030f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
10313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst MediaContentDescription* VideoChannel::GetFirstContent(
10323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const SessionDescription* sdesc) {
10333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const ContentInfo* cinfo = GetFirstVideoContent(sdesc);
10343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (cinfo == NULL)
10353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return NULL;
10363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
10373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return static_cast<const MediaContentDescription*>(cinfo->description);
10383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
10393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
10403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool VideoChannel::SetLocalContent_w(const MediaContentDescription* content,
10413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     ContentAction action) {
1042f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ASSERT(worker_thread() == talk_base::Thread::Current());
1043f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  LOG(LS_INFO) << "Setting local video description";
1044f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
10453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const VideoContentDescription* video =
10463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      static_cast<const VideoContentDescription*>(content);
10473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT(video != NULL);
10483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1049f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bool ret;
1050f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // set SRTP
10513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ret = SetSrtp_w(video->cryptos(), action, CS_LOCAL);
1052f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // set RTCP mux
1053f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (ret) {
10543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    ret = SetRtcpMux_w(video->rtcp_mux(), action, CS_LOCAL);
1055f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
1056f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // set payload types and config for receiving video
1057f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (ret) {
10583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    ret = media_channel()->SetRecvCodecs(video->codecs());
1059f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
1060f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return ret;
1061f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
1062f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
10633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool VideoChannel::SetRemoteContent_w(const MediaContentDescription* content,
10643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                      ContentAction action) {
1065f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ASSERT(worker_thread() == talk_base::Thread::Current());
1066f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  LOG(LS_INFO) << "Setting remote video description";
1067f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
10683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const VideoContentDescription* video =
10693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      static_cast<const VideoContentDescription*>(content);
10703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT(video != NULL);
10713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1072f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bool ret;
1073f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // set the sending SSRC, if the remote side gave us one
1074731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // TODO: remove this, since it's not needed.
10753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (video->ssrc_set()) {
10763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    media_channel()->SetSendSsrc(video->ssrc());
1077f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
1078f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // set SRTP
10793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ret = SetSrtp_w(video->cryptos(), action, CS_REMOTE);
1080f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // set RTCP mux
1081f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (ret) {
10823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    ret = SetRtcpMux_w(video->rtcp_mux(), action, CS_REMOTE);
1083f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
10844a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // Set video bandwidth parameters.
10854a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  if (ret) {
10864a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    int bandwidth_bps = video->bandwidth();
10874a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    bool auto_bandwidth = (bandwidth_bps == kAutoBandwidth);
10884a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    ret = media_channel()->SetSendBandwidth(auto_bandwidth, bandwidth_bps);
10894a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  }
1090f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (ret) {
10913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    ret = media_channel()->SetSendCodecs(video->codecs());
1092f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
10933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  media_channel()->SetRtpExtensionHeaders(!video->rtp_headers_disabled());
1094f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (ret) {
1095f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    set_has_codec(true);
1096f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ChangeState();
1097f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
1098f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return ret;
1099f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
1100f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1101f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid VideoChannel::AddStream_w(uint32 ssrc, uint32 voice_ssrc) {
1102f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  media_channel()->AddStream(ssrc, voice_ssrc);
1103f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
1104f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1105f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid VideoChannel::RemoveStream_w(uint32 ssrc) {
1106f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  media_channel()->RemoveStream(ssrc);
1107f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
1108f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1109f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid VideoChannel::SetRenderer_w(uint32 ssrc, VideoRenderer* renderer) {
1110f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  media_channel()->SetRenderer(ssrc, renderer);
1111f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
1112f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1113f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1114f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid VideoChannel::OnMessage(talk_base::Message *pmsg) {
1115f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  switch (pmsg->message_id) {
1116f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case MSG_ADDSTREAM: {
1117f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      StreamMessageData* data = static_cast<StreamMessageData*>(pmsg->pdata);
1118f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      AddStream_w(data->ssrc1, data->ssrc2);
1119f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      break;
1120f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
1121f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    case MSG_SETRENDERER: {
1122f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      RenderMessageData* data = static_cast<RenderMessageData*>(pmsg->pdata);
1123f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      SetRenderer_w(data->ssrc, data->renderer);
1124f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      break;
1125f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
11264a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    case MSG_SENDINTRAFRAME:
11274a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      SendIntraFrame_w();
11284a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      break;
11294a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    case MSG_REQUESTINTRAFRAME:
11304a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      RequestIntraFrame_w();
11314a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      break;
1132dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    case MSG_CHANNEL_ERROR: {
1133dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      const VideoChannelErrorMessageData* data =
1134dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          static_cast<VideoChannelErrorMessageData*>(pmsg->pdata);
1135dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      SignalMediaError(this, data->ssrc, data->error);
1136dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      delete data;
1137dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      break;
1138dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
1139dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    default:
1140dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      BaseChannel::OnMessage(pmsg);
1141dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      break;
1142f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
1143f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
1144f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1145f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid VideoChannel::OnConnectionMonitorUpdate(
1146f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    SocketMonitor *monitor, const std::vector<ConnectionInfo> &infos) {
1147f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  SignalConnectionMonitor(this, infos);
1148f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
1149f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1150f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid VideoChannel::OnMediaMonitorUpdate(
1151f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    VideoMediaChannel* media_channel, const VideoMediaInfo &info) {
1152f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ASSERT(media_channel == this->media_channel());
1153f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  SignalMediaMonitor(this, info);
1154f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
1155f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
11564a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1157dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid VideoChannel::OnVideoChannelError(uint32 ssrc,
1158dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                       VideoMediaChannel::Error error) {
1159dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  VideoChannelErrorMessageData* data = new VideoChannelErrorMessageData(
1160dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      ssrc, error);
1161dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  signaling_thread()->Post(this, MSG_CHANNEL_ERROR, data);
1162f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
1163f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1164f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}  // namespace cricket
1165