blob: be40a7e446670888ae28ea783519c3548fd27f64 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
kjellander65c7f672016-02-12 00:05:01 -08002 * Copyright 2004 The WebRTC project authors. All Rights Reserved.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003 *
kjellander65c7f672016-02-12 00:05:01 -08004 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00009 */
10
Anton Sukhanov4f08faa2019-05-21 11:12:57 -070011#include "pc/channel.h"
12
jbauch5869f502017-06-29 12:31:36 -070013#include <iterator>
kwiberg0eb15ed2015-12-17 03:04:15 -080014#include <utility>
15
Steve Anton64b626b2019-01-28 17:25:26 -080016#include "absl/algorithm/container.h"
Karl Wiberg918f50c2018-07-05 11:40:33 +020017#include "absl/memory/memory.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020018#include "api/call/audio_sink.h"
Anton Sukhanov4f08faa2019-05-21 11:12:57 -070019#include "api/media_transport_config.h"
Steve Anton10542f22019-01-11 09:11:00 -080020#include "media/base/media_constants.h"
21#include "media/base/rtp_utils.h"
Zhi Huang365381f2018-04-13 16:44:34 -070022#include "modules/rtp_rtcp/source/rtp_packet_received.h"
Anton Sukhanov4f08faa2019-05-21 11:12:57 -070023#include "p2p/base/packet_transport_internal.h"
24#include "pc/channel_manager.h"
25#include "pc/rtp_media_utils.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020026#include "rtc_base/bind.h"
Steve Anton10542f22019-01-11 09:11:00 -080027#include "rtc_base/byte_order.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020028#include "rtc_base/checks.h"
Steve Anton10542f22019-01-11 09:11:00 -080029#include "rtc_base/copy_on_write_buffer.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020030#include "rtc_base/dscp.h"
31#include "rtc_base/logging.h"
Steve Anton10542f22019-01-11 09:11:00 -080032#include "rtc_base/network_route.h"
Jonas Olsson366a50c2018-09-06 13:41:30 +020033#include "rtc_base/strings/string_builder.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020034#include "rtc_base/trace_event.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000035
36namespace cricket {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000037using rtc::Bind;
Amit Hilbuchbcd39d42019-01-25 17:13:56 -080038using rtc::UniqueRandomIdGenerator;
Steve Anton3828c062017-12-06 10:34:51 -080039using webrtc::SdpType;
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +000040
deadbeef2d110be2016-01-13 12:00:26 -080041namespace {
Danil Chapovalov33b01f22016-05-11 19:55:27 +020042
43struct SendPacketMessageData : public rtc::MessageData {
44 rtc::CopyOnWriteBuffer packet;
45 rtc::PacketOptions options;
46};
47
Amit Hilbuchbcd39d42019-01-25 17:13:56 -080048// Finds a stream based on target's Primary SSRC or RIDs.
49// This struct is used in BaseChannel::UpdateLocalStreams_w.
50struct StreamFinder {
51 explicit StreamFinder(const StreamParams* target) : target_(target) {
52 RTC_DCHECK(target);
53 }
54
55 bool operator()(const StreamParams& sp) const {
56 if (target_->has_ssrcs() && sp.has_ssrcs()) {
57 return sp.has_ssrc(target_->first_ssrc());
58 }
59
60 if (!target_->has_rids() && !sp.has_rids()) {
61 return false;
62 }
63
64 const std::vector<RidDescription>& target_rids = target_->rids();
65 const std::vector<RidDescription>& source_rids = sp.rids();
66 if (source_rids.size() != target_rids.size()) {
67 return false;
68 }
69
70 // Check that all RIDs match.
71 return std::equal(source_rids.begin(), source_rids.end(),
72 target_rids.begin(),
73 [](const RidDescription& lhs, const RidDescription& rhs) {
74 return lhs.rid == rhs.rid;
75 });
76 }
77
78 const StreamParams* target_;
79};
80
deadbeef2d110be2016-01-13 12:00:26 -080081} // namespace
82
henrike@webrtc.org28e20752013-07-10 00:45:36 +000083enum {
Steve Anton0807d152018-03-05 11:23:09 -080084 MSG_SEND_RTP_PACKET = 1,
Danil Chapovalov33b01f22016-05-11 19:55:27 +020085 MSG_SEND_RTCP_PACKET,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000086 MSG_READYTOSENDDATA,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000087 MSG_DATARECEIVED,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000088 MSG_FIRSTPACKETRECEIVED,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000089};
90
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +000091static void SafeSetError(const std::string& message, std::string* error_desc) {
92 if (error_desc) {
93 *error_desc = message;
94 }
95}
96
Peter Thatcherc2ee2c82015-08-07 16:05:34 -070097template <class Codec>
98void RtpParametersFromMediaDescription(
99 const MediaContentDescriptionImpl<Codec>* desc,
jbauch5869f502017-06-29 12:31:36 -0700100 const RtpHeaderExtensions& extensions,
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700101 RtpParameters<Codec>* params) {
102 // TODO(pthatcher): Remove this once we're sure no one will give us
Zhi Huang801b8682017-11-15 11:36:43 -0800103 // a description without codecs. Currently the ORTC implementation is relying
104 // on this.
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700105 if (desc->has_codecs()) {
106 params->codecs = desc->codecs();
107 }
108 // TODO(pthatcher): See if we really need
109 // rtp_header_extensions_set() and remove it if we don't.
110 if (desc->rtp_header_extensions_set()) {
jbauch5869f502017-06-29 12:31:36 -0700111 params->extensions = extensions;
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700112 }
deadbeef13871492015-12-09 12:37:51 -0800113 params->rtcp.reduced_size = desc->rtcp_reduced_size();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700114}
115
nisse05103312016-03-16 02:22:50 -0700116template <class Codec>
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700117void RtpSendParametersFromMediaDescription(
118 const MediaContentDescriptionImpl<Codec>* desc,
jbauch5869f502017-06-29 12:31:36 -0700119 const RtpHeaderExtensions& extensions,
nisse05103312016-03-16 02:22:50 -0700120 RtpSendParameters<Codec>* send_params) {
jbauch5869f502017-06-29 12:31:36 -0700121 RtpParametersFromMediaDescription(desc, extensions, send_params);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700122 send_params->max_bandwidth_bps = desc->bandwidth();
Johannes Kron9190b822018-10-29 11:22:05 +0100123 send_params->extmap_allow_mixed = desc->extmap_allow_mixed();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700124}
125
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200126BaseChannel::BaseChannel(rtc::Thread* worker_thread,
127 rtc::Thread* network_thread,
zhihuangf5b251b2017-01-12 19:37:48 -0800128 rtc::Thread* signaling_thread,
Steve Anton8699a322017-11-06 15:53:33 -0800129 std::unique_ptr<MediaChannel> media_channel,
deadbeefcbecd352015-09-23 11:50:27 -0700130 const std::string& content_name,
Zhi Huange830e682018-03-30 10:48:35 -0700131 bool srtp_required,
Amit Hilbuchbcd39d42019-01-25 17:13:56 -0800132 webrtc::CryptoOptions crypto_options,
133 UniqueRandomIdGenerator* ssrc_generator)
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200134 : worker_thread_(worker_thread),
135 network_thread_(network_thread),
zhihuangf5b251b2017-01-12 19:37:48 -0800136 signaling_thread_(signaling_thread),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000137 content_name_(content_name),
deadbeef7af91dd2016-12-13 11:29:11 -0800138 srtp_required_(srtp_required),
Zhi Huange830e682018-03-30 10:48:35 -0700139 crypto_options_(crypto_options),
Amit Hilbuchbcd39d42019-01-25 17:13:56 -0800140 media_channel_(std::move(media_channel)),
141 ssrc_generator_(ssrc_generator) {
Steve Anton8699a322017-11-06 15:53:33 -0800142 RTC_DCHECK_RUN_ON(worker_thread_);
Amit Hilbuchbcd39d42019-01-25 17:13:56 -0800143 RTC_DCHECK(ssrc_generator_);
Zhi Huang365381f2018-04-13 16:44:34 -0700144 demuxer_criteria_.mid = content_name;
Mirko Bonadei675513b2017-11-09 11:09:25 +0100145 RTC_LOG(LS_INFO) << "Created channel for " << content_name;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000146}
147
148BaseChannel::~BaseChannel() {
Peter Boströmca8b4042016-03-08 14:24:13 -0800149 TRACE_EVENT0("webrtc", "BaseChannel::~BaseChannel");
Steve Anton8699a322017-11-06 15:53:33 -0800150 RTC_DCHECK_RUN_ON(worker_thread_);
Piotr (Peter) Slatala179a3922018-11-16 09:57:58 -0800151
Anton Sukhanov4f08faa2019-05-21 11:12:57 -0700152 if (media_transport_config_.media_transport) {
153 media_transport_config_.media_transport->RemoveNetworkChangeCallback(this);
Piotr (Peter) Slatala179a3922018-11-16 09:57:58 -0800154 }
155
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200156 // Eats any outstanding messages or packets.
157 worker_thread_->Clear(&invoker_);
158 worker_thread_->Clear(this);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000159 // We must destroy the media channel before the transport channel, otherwise
160 // the media channel may try to send on the dead transport channel. NULLing
161 // is not an effective strategy since the sends will come on another thread.
Steve Anton8699a322017-11-06 15:53:33 -0800162 media_channel_.reset();
Mirko Bonadei675513b2017-11-09 11:09:25 +0100163 RTC_LOG(LS_INFO) << "Destroyed channel: " << content_name_;
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200164}
165
Zhi Huang365381f2018-04-13 16:44:34 -0700166bool BaseChannel::ConnectToRtpTransport() {
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800167 RTC_DCHECK(rtp_transport_);
Zhi Huang365381f2018-04-13 16:44:34 -0700168 if (!RegisterRtpDemuxerSink()) {
169 return false;
170 }
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800171 rtp_transport_->SignalReadyToSend.connect(
172 this, &BaseChannel::OnTransportReadyToSend);
Zhi Huang365381f2018-04-13 16:44:34 -0700173 rtp_transport_->SignalRtcpPacketReceived.connect(
174 this, &BaseChannel::OnRtcpPacketReceived);
Piotr (Peter) Slatala179a3922018-11-16 09:57:58 -0800175
176 // If media transport is used, it's responsible for providing network
177 // route changed callbacks.
Anton Sukhanov4f08faa2019-05-21 11:12:57 -0700178 if (!media_transport_config_.media_transport) {
Piotr (Peter) Slatala179a3922018-11-16 09:57:58 -0800179 rtp_transport_->SignalNetworkRouteChanged.connect(
180 this, &BaseChannel::OnNetworkRouteChanged);
181 }
182 // TODO(bugs.webrtc.org/9719): Media transport should also be used to provide
183 // 'writable' state here.
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800184 rtp_transport_->SignalWritableState.connect(this,
185 &BaseChannel::OnWritableState);
186 rtp_transport_->SignalSentPacket.connect(this,
187 &BaseChannel::SignalSentPacket_n);
Zhi Huang365381f2018-04-13 16:44:34 -0700188 return true;
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800189}
Danil Chapovalovdae07ba2016-05-14 01:43:50 +0200190
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800191void BaseChannel::DisconnectFromRtpTransport() {
192 RTC_DCHECK(rtp_transport_);
Zhi Huang365381f2018-04-13 16:44:34 -0700193 rtp_transport_->UnregisterRtpDemuxerSink(this);
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800194 rtp_transport_->SignalReadyToSend.disconnect(this);
Zhi Huang365381f2018-04-13 16:44:34 -0700195 rtp_transport_->SignalRtcpPacketReceived.disconnect(this);
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800196 rtp_transport_->SignalNetworkRouteChanged.disconnect(this);
197 rtp_transport_->SignalWritableState.disconnect(this);
198 rtp_transport_->SignalSentPacket.disconnect(this);
Danil Chapovalovdae07ba2016-05-14 01:43:50 +0200199}
200
Anton Sukhanov4f08faa2019-05-21 11:12:57 -0700201void BaseChannel::Init_w(
202 webrtc::RtpTransportInternal* rtp_transport,
203 const webrtc::MediaTransportConfig& media_transport_config) {
Zhi Huang2dfc42d2017-12-04 13:38:48 -0800204 RTC_DCHECK_RUN_ON(worker_thread_);
Anton Sukhanov4f08faa2019-05-21 11:12:57 -0700205 media_transport_config_ = media_transport_config;
Piotr (Peter) Slatala179a3922018-11-16 09:57:58 -0800206
Zhi Huang365381f2018-04-13 16:44:34 -0700207 network_thread_->Invoke<void>(
208 RTC_FROM_HERE, [this, rtp_transport] { SetRtpTransport(rtp_transport); });
Zhi Huang2dfc42d2017-12-04 13:38:48 -0800209
210 // Both RTP and RTCP channels should be set, we can call SetInterface on
211 // the media channel and it can set network options.
Anton Sukhanov4f08faa2019-05-21 11:12:57 -0700212 media_channel_->SetInterface(this, media_transport_config);
Piotr (Peter) Slatala179a3922018-11-16 09:57:58 -0800213
Anton Sukhanov4f08faa2019-05-21 11:12:57 -0700214 RTC_LOG(LS_INFO) << "BaseChannel::Init_w, media_transport_config="
215 << media_transport_config.DebugString();
216 if (media_transport_config_.media_transport) {
217 media_transport_config_.media_transport->AddNetworkChangeCallback(this);
Piotr (Peter) Slatala179a3922018-11-16 09:57:58 -0800218 }
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200219}
220
wu@webrtc.org78187522013-10-07 23:32:02 +0000221void BaseChannel::Deinit() {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200222 RTC_DCHECK(worker_thread_->IsCurrent());
Anton Sukhanov98a462c2018-10-17 13:15:42 -0700223 media_channel_->SetInterface(/*iface=*/nullptr,
Anton Sukhanov4f08faa2019-05-21 11:12:57 -0700224 webrtc::MediaTransportConfig());
Danil Chapovalovdae07ba2016-05-14 01:43:50 +0200225 // Packets arrive on the network thread, processing packets calls virtual
226 // functions, so need to stop this process in Deinit that is called in
227 // derived classes destructor.
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800228 network_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
Zhi Huang95e7dbb2018-03-29 00:08:03 +0000229 FlushRtcpMessages_n();
Zhi Huang27f3bf52018-03-26 21:37:23 -0700230
Zhi Huange830e682018-03-30 10:48:35 -0700231 if (rtp_transport_) {
232 DisconnectFromRtpTransport();
Zhi Huang95e7dbb2018-03-29 00:08:03 +0000233 }
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800234 // Clear pending read packets/messages.
235 network_thread_->Clear(&invoker_);
236 network_thread_->Clear(this);
237 });
wu@webrtc.org78187522013-10-07 23:32:02 +0000238}
239
Zhi Huang365381f2018-04-13 16:44:34 -0700240bool BaseChannel::SetRtpTransport(webrtc::RtpTransportInternal* rtp_transport) {
241 if (rtp_transport == rtp_transport_) {
242 return true;
243 }
244
Zhi Huang2dfc42d2017-12-04 13:38:48 -0800245 if (!network_thread_->IsCurrent()) {
Zhi Huang365381f2018-04-13 16:44:34 -0700246 return network_thread_->Invoke<bool>(RTC_FROM_HERE, [this, rtp_transport] {
247 return SetRtpTransport(rtp_transport);
Zhi Huang2dfc42d2017-12-04 13:38:48 -0800248 });
249 }
Zhi Huang95e7dbb2018-03-29 00:08:03 +0000250
Zhi Huang2dfc42d2017-12-04 13:38:48 -0800251 if (rtp_transport_) {
252 DisconnectFromRtpTransport();
253 }
Zhi Huange830e682018-03-30 10:48:35 -0700254
Zhi Huang2dfc42d2017-12-04 13:38:48 -0800255 rtp_transport_ = rtp_transport;
Zhi Huange830e682018-03-30 10:48:35 -0700256 if (rtp_transport_) {
257 RTC_DCHECK(rtp_transport_->rtp_packet_transport());
258 transport_name_ = rtp_transport_->rtp_packet_transport()->transport_name();
Zhi Huang2dfc42d2017-12-04 13:38:48 -0800259
Zhi Huang365381f2018-04-13 16:44:34 -0700260 if (!ConnectToRtpTransport()) {
261 RTC_LOG(LS_ERROR) << "Failed to connect to the new RtpTransport.";
262 return false;
263 }
Zhi Huange830e682018-03-30 10:48:35 -0700264 OnTransportReadyToSend(rtp_transport_->IsReadyToSend());
265 UpdateWritableState_n();
Zhi Huang2dfc42d2017-12-04 13:38:48 -0800266
Zhi Huange830e682018-03-30 10:48:35 -0700267 // Set the cached socket options.
268 for (const auto& pair : socket_options_) {
269 rtp_transport_->rtp_packet_transport()->SetOption(pair.first,
270 pair.second);
271 }
272 if (rtp_transport_->rtcp_packet_transport()) {
273 for (const auto& pair : rtcp_socket_options_) {
274 rtp_transport_->rtp_packet_transport()->SetOption(pair.first,
275 pair.second);
276 }
277 }
guoweis46383312015-12-17 16:45:59 -0800278 }
Zhi Huang365381f2018-04-13 16:44:34 -0700279 return true;
pthatcher@webrtc.org6ad507a2015-03-16 20:19:12 +0000280}
281
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000282bool BaseChannel::Enable(bool enable) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700283 worker_thread_->Invoke<void>(
284 RTC_FROM_HERE,
285 Bind(enable ? &BaseChannel::EnableMedia_w : &BaseChannel::DisableMedia_w,
286 this));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000287 return true;
288}
289
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000290bool BaseChannel::SetLocalContent(const MediaContentDescription* content,
Steve Anton3828c062017-12-06 10:34:51 -0800291 SdpType type,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000292 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +0100293 TRACE_EVENT0("webrtc", "BaseChannel::SetLocalContent");
stefanf79ade12017-06-02 06:44:03 -0700294 return InvokeOnWorker<bool>(
295 RTC_FROM_HERE,
Steve Anton3828c062017-12-06 10:34:51 -0800296 Bind(&BaseChannel::SetLocalContent_w, this, content, type, error_desc));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000297}
298
299bool BaseChannel::SetRemoteContent(const MediaContentDescription* content,
Steve Anton3828c062017-12-06 10:34:51 -0800300 SdpType type,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000301 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +0100302 TRACE_EVENT0("webrtc", "BaseChannel::SetRemoteContent");
stefanf79ade12017-06-02 06:44:03 -0700303 return InvokeOnWorker<bool>(
Steve Anton3828c062017-12-06 10:34:51 -0800304 RTC_FROM_HERE,
305 Bind(&BaseChannel::SetRemoteContent_w, this, content, type, error_desc));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000306}
307
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700308bool BaseChannel::IsReadyToReceiveMedia_w() const {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000309 // Receive data if we are enabled and have local content,
Steve Anton4e70a722017-11-28 14:57:10 -0800310 return enabled() &&
311 webrtc::RtpTransceiverDirectionHasRecv(local_content_direction_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000312}
313
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700314bool BaseChannel::IsReadyToSendMedia_w() const {
315 // Need to access some state updated on the network thread.
316 return network_thread_->Invoke<bool>(
317 RTC_FROM_HERE, Bind(&BaseChannel::IsReadyToSendMedia_n, this));
318}
319
320bool BaseChannel::IsReadyToSendMedia_n() const {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000321 // Send outgoing data if we are enabled, have local and remote content,
322 // and we have had some form of connectivity.
Steve Anton4e70a722017-11-28 14:57:10 -0800323 return enabled() &&
324 webrtc::RtpTransceiverDirectionHasRecv(remote_content_direction_) &&
325 webrtc::RtpTransceiverDirectionHasSend(local_content_direction_) &&
Zhi Huang365381f2018-04-13 16:44:34 -0700326 was_ever_writable();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000327}
328
jbaucheec21bd2016-03-20 06:15:43 -0700329bool BaseChannel::SendPacket(rtc::CopyOnWriteBuffer* packet,
stefanc1aeaf02015-10-15 07:26:07 -0700330 const rtc::PacketOptions& options) {
331 return SendPacket(false, packet, options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000332}
333
jbaucheec21bd2016-03-20 06:15:43 -0700334bool BaseChannel::SendRtcp(rtc::CopyOnWriteBuffer* packet,
stefanc1aeaf02015-10-15 07:26:07 -0700335 const rtc::PacketOptions& options) {
336 return SendPacket(true, packet, options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000337}
338
Yves Gerey665174f2018-06-19 15:03:05 +0200339int BaseChannel::SetOption(SocketType type,
340 rtc::Socket::Option opt,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000341 int value) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200342 return network_thread_->Invoke<int>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700343 RTC_FROM_HERE, Bind(&BaseChannel::SetOption_n, this, type, opt, value));
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200344}
345
346int BaseChannel::SetOption_n(SocketType type,
347 rtc::Socket::Option opt,
348 int value) {
349 RTC_DCHECK(network_thread_->IsCurrent());
Zhi Huange830e682018-03-30 10:48:35 -0700350 RTC_DCHECK(rtp_transport_);
deadbeef5bd5ca32017-02-10 11:31:50 -0800351 rtc::PacketTransportInternal* transport = nullptr;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000352 switch (type) {
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000353 case ST_RTP:
zsteine8ab5432017-07-12 11:48:11 -0700354 transport = rtp_transport_->rtp_packet_transport();
deadbeefcbecd352015-09-23 11:50:27 -0700355 socket_options_.push_back(
356 std::pair<rtc::Socket::Option, int>(opt, value));
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000357 break;
358 case ST_RTCP:
zsteine8ab5432017-07-12 11:48:11 -0700359 transport = rtp_transport_->rtcp_packet_transport();
deadbeefcbecd352015-09-23 11:50:27 -0700360 rtcp_socket_options_.push_back(
361 std::pair<rtc::Socket::Option, int>(opt, value));
wu@webrtc.org9caf2762013-12-11 18:25:07 +0000362 break;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000363 }
deadbeeff5346592017-01-24 21:51:21 -0800364 return transport ? transport->SetOption(opt, value) : -1;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000365}
366
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800367void BaseChannel::OnWritableState(bool writable) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200368 RTC_DCHECK(network_thread_->IsCurrent());
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800369 if (writable) {
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800370 ChannelWritable_n();
371 } else {
372 ChannelNotWritable_n();
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800373 }
374}
375
Zhi Huang942bc2e2017-11-13 13:26:07 -0800376void BaseChannel::OnNetworkRouteChanged(
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200377 absl::optional<rtc::NetworkRoute> network_route) {
Piotr (Peter) Slatala179a3922018-11-16 09:57:58 -0800378 RTC_LOG(LS_INFO) << "Network route was changed.";
379
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200380 RTC_DCHECK(network_thread_->IsCurrent());
Zhi Huang942bc2e2017-11-13 13:26:07 -0800381 rtc::NetworkRoute new_route;
382 if (network_route) {
Zhi Huang942bc2e2017-11-13 13:26:07 -0800383 new_route = *(network_route);
Zhi Huang8c316c12017-11-13 21:13:45 +0000384 }
Zhi Huang942bc2e2017-11-13 13:26:07 -0800385 // Note: When the RTCP-muxing is not enabled, RTCP transport and RTP transport
386 // use the same transport name and MediaChannel::OnNetworkRouteChanged cannot
387 // work correctly. Intentionally leave it broken to simplify the code and
388 // encourage the users to stop using non-muxing RTCP.
Steve Anton8699a322017-11-06 15:53:33 -0800389 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, worker_thread_, [=] {
Zhi Huang942bc2e2017-11-13 13:26:07 -0800390 media_channel_->OnNetworkRouteChanged(transport_name_, new_route);
Steve Anton8699a322017-11-06 15:53:33 -0800391 });
Honghai Zhangcc411c02016-03-29 17:27:21 -0700392}
393
zstein56162b92017-04-24 16:54:35 -0700394void BaseChannel::OnTransportReadyToSend(bool ready) {
Steve Anton8699a322017-11-06 15:53:33 -0800395 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, worker_thread_,
396 [=] { media_channel_->OnReadyToSend(ready); });
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000397}
398
stefanc1aeaf02015-10-15 07:26:07 -0700399bool BaseChannel::SendPacket(bool rtcp,
jbaucheec21bd2016-03-20 06:15:43 -0700400 rtc::CopyOnWriteBuffer* packet,
stefanc1aeaf02015-10-15 07:26:07 -0700401 const rtc::PacketOptions& options) {
Amit Hilbuchedd20542019-03-18 12:33:43 -0700402 // Until all the code is migrated to use RtpPacketType instead of bool.
403 RtpPacketType packet_type = rtcp ? RtpPacketType::kRtcp : RtpPacketType::kRtp;
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200404 // SendPacket gets called from MediaEngine, on a pacer or an encoder thread.
405 // If the thread is not our network thread, we will post to our network
406 // so that the real work happens on our network. This avoids us having to
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000407 // synchronize access to all the pieces of the send path, including
408 // SRTP and the inner workings of the transport channels.
409 // The only downside is that we can't return a proper failure code if
410 // needed. Since UDP is unreliable anyway, this should be a non-issue.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200411 if (!network_thread_->IsCurrent()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000412 // Avoid a copy by transferring the ownership of the packet data.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200413 int message_id = rtcp ? MSG_SEND_RTCP_PACKET : MSG_SEND_RTP_PACKET;
414 SendPacketMessageData* data = new SendPacketMessageData;
kwiberg0eb15ed2015-12-17 03:04:15 -0800415 data->packet = std::move(*packet);
stefanc1aeaf02015-10-15 07:26:07 -0700416 data->options = options;
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700417 network_thread_->Post(RTC_FROM_HERE, this, message_id, data);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000418 return true;
419 }
Zhi Huange830e682018-03-30 10:48:35 -0700420
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200421 TRACE_EVENT0("webrtc", "BaseChannel::SendPacket");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000422
423 // Now that we are on the correct thread, ensure we have a place to send this
424 // packet before doing anything. (We might get RTCP packets that we don't
425 // intend to send.) If we've negotiated RTCP mux, send RTCP over the RTP
426 // transport.
Zhi Huange830e682018-03-30 10:48:35 -0700427 if (!rtp_transport_ || !rtp_transport_->IsWritable(rtcp)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000428 return false;
429 }
430
431 // Protect ourselves against crazy data.
Amit Hilbuchedd20542019-03-18 12:33:43 -0700432 if (!IsValidRtpPacketSize(packet_type, packet->size())) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100433 RTC_LOG(LS_ERROR) << "Dropping outgoing " << content_name_ << " "
Amit Hilbuchedd20542019-03-18 12:33:43 -0700434 << RtpPacketTypeToString(packet_type)
Mirko Bonadei675513b2017-11-09 11:09:25 +0100435 << " packet: wrong size=" << packet->size();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000436 return false;
437 }
438
Zhi Huangcf990f52017-09-22 12:12:30 -0700439 if (!srtp_active()) {
440 if (srtp_required_) {
441 // The audio/video engines may attempt to send RTCP packets as soon as the
442 // streams are created, so don't treat this as an error for RTCP.
443 // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=6809
444 if (rtcp) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000445 return false;
446 }
Zhi Huangcf990f52017-09-22 12:12:30 -0700447 // However, there shouldn't be any RTP packets sent before SRTP is set up
448 // (and SetSend(true) is called).
Mirko Bonadei675513b2017-11-09 11:09:25 +0100449 RTC_LOG(LS_ERROR)
450 << "Can't send outgoing RTP packet when SRTP is inactive"
451 << " and crypto is required";
Zhi Huangcf990f52017-09-22 12:12:30 -0700452 RTC_NOTREACHED();
deadbeef8f425f92016-12-01 12:26:27 -0800453 return false;
454 }
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800455
456 std::string packet_type = rtcp ? "RTCP" : "RTP";
457 RTC_LOG(LS_WARNING) << "Sending an " << packet_type
458 << " packet without encryption.";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000459 }
Zhi Huange830e682018-03-30 10:48:35 -0700460
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000461 // Bon voyage.
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800462 return rtcp ? rtp_transport_->SendRtcpPacket(packet, options, PF_SRTP_BYPASS)
463 : rtp_transport_->SendRtpPacket(packet, options, PF_SRTP_BYPASS);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000464}
465
Zhi Huang365381f2018-04-13 16:44:34 -0700466void BaseChannel::OnRtpPacket(const webrtc::RtpPacketReceived& parsed_packet) {
Niels Möller29e13fd2018-12-17 12:35:30 +0100467 // Take packet time from the |parsed_packet|.
468 // RtpPacketReceived.arrival_time_ms = (timestamp_us + 500) / 1000;
Niels Möllere6933812018-11-05 13:01:41 +0100469 int64_t timestamp_us = -1;
Zhi Huang365381f2018-04-13 16:44:34 -0700470 if (parsed_packet.arrival_time_ms() > 0) {
Niels Möllere6933812018-11-05 13:01:41 +0100471 timestamp_us = parsed_packet.arrival_time_ms() * 1000;
Zhi Huang365381f2018-04-13 16:44:34 -0700472 }
Zhi Huang365381f2018-04-13 16:44:34 -0700473
Niels Möllere6933812018-11-05 13:01:41 +0100474 OnPacketReceived(/*rtcp=*/false, parsed_packet.Buffer(), timestamp_us);
Zhi Huang365381f2018-04-13 16:44:34 -0700475}
476
477void BaseChannel::UpdateRtpHeaderExtensionMap(
478 const RtpHeaderExtensions& header_extensions) {
479 RTC_DCHECK(rtp_transport_);
480 // Update the header extension map on network thread in case there is data
481 // race.
482 // TODO(zhihuang): Add an rtc::ThreadChecker make sure to RtpTransport won't
483 // be accessed from different threads.
484 //
485 // NOTE: This doesn't take the BUNDLE case in account meaning the RTP header
486 // extension maps are not merged when BUNDLE is enabled. This is fine because
487 // the ID for MID should be consistent among all the RTP transports.
488 network_thread_->Invoke<void>(RTC_FROM_HERE, [this, &header_extensions] {
489 rtp_transport_->UpdateRtpHeaderExtensionMap(header_extensions);
490 });
491}
492
493bool BaseChannel::RegisterRtpDemuxerSink() {
494 RTC_DCHECK(rtp_transport_);
495 return network_thread_->Invoke<bool>(RTC_FROM_HERE, [this] {
496 return rtp_transport_->RegisterRtpDemuxerSink(demuxer_criteria_, this);
497 });
498}
499
500void BaseChannel::OnRtcpPacketReceived(rtc::CopyOnWriteBuffer* packet,
Niels Möllere6933812018-11-05 13:01:41 +0100501 int64_t packet_time_us) {
502 OnPacketReceived(/*rtcp=*/true, *packet, packet_time_us);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000503}
504
zstein3dcf0e92017-06-01 13:22:42 -0700505void BaseChannel::OnPacketReceived(bool rtcp,
Zhi Huang365381f2018-04-13 16:44:34 -0700506 const rtc::CopyOnWriteBuffer& packet,
Niels Möllere6933812018-11-05 13:01:41 +0100507 int64_t packet_time_us) {
honghaiz@google.coma67ca1a2015-01-28 19:48:33 +0000508 if (!has_received_packet_ && !rtcp) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000509 has_received_packet_ = true;
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700510 signaling_thread()->Post(RTC_FROM_HERE, this, MSG_FIRSTPACKETRECEIVED);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000511 }
512
Zhi Huangcf990f52017-09-22 12:12:30 -0700513 if (!srtp_active() && srtp_required_) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000514 // Our session description indicates that SRTP is required, but we got a
515 // packet before our SRTP filter is active. This means either that
516 // a) we got SRTP packets before we received the SDES keys, in which case
517 // we can't decrypt it anyway, or
518 // b) we got SRTP packets before DTLS completed on both the RTP and RTCP
zhihuangb2cdd932017-01-19 16:54:25 -0800519 // transports, so we haven't yet extracted keys, even if DTLS did
520 // complete on the transport that the packets are being sent on. It's
521 // really good practice to wait for both RTP and RTCP to be good to go
522 // before sending media, to prevent weird failure modes, so it's fine
523 // for us to just eat packets here. This is all sidestepped if RTCP mux
524 // is used anyway.
Mirko Bonadei675513b2017-11-09 11:09:25 +0100525 RTC_LOG(LS_WARNING)
Amit Hilbuchedd20542019-03-18 12:33:43 -0700526 << "Can't process incoming "
527 << RtpPacketTypeToString(rtcp ? RtpPacketType::kRtcp
528 : RtpPacketType::kRtp)
Mirko Bonadei675513b2017-11-09 11:09:25 +0100529 << " packet when SRTP is inactive and crypto is required";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000530 return;
531 }
532
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200533 invoker_.AsyncInvoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700534 RTC_FROM_HERE, worker_thread_,
Niels Möllere6933812018-11-05 13:01:41 +0100535 Bind(&BaseChannel::ProcessPacket, this, rtcp, packet, packet_time_us));
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200536}
537
zstein3dcf0e92017-06-01 13:22:42 -0700538void BaseChannel::ProcessPacket(bool rtcp,
539 const rtc::CopyOnWriteBuffer& packet,
Niels Möllere6933812018-11-05 13:01:41 +0100540 int64_t packet_time_us) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200541 RTC_DCHECK(worker_thread_->IsCurrent());
zstein3dcf0e92017-06-01 13:22:42 -0700542
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200543 if (rtcp) {
Amit Hilbuche7a5f7b2019-03-12 11:10:27 -0700544 media_channel_->OnRtcpReceived(packet, packet_time_us);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000545 } else {
Amit Hilbuche7a5f7b2019-03-12 11:10:27 -0700546 media_channel_->OnPacketReceived(packet, packet_time_us);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000547 }
548}
549
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000550void BaseChannel::EnableMedia_w() {
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700551 RTC_DCHECK(worker_thread_ == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000552 if (enabled_)
553 return;
554
Mirko Bonadei675513b2017-11-09 11:09:25 +0100555 RTC_LOG(LS_INFO) << "Channel enabled";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000556 enabled_ = true;
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700557 UpdateMediaSendRecvState_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000558}
559
560void BaseChannel::DisableMedia_w() {
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700561 RTC_DCHECK(worker_thread_ == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000562 if (!enabled_)
563 return;
564
Mirko Bonadei675513b2017-11-09 11:09:25 +0100565 RTC_LOG(LS_INFO) << "Channel disabled";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000566 enabled_ = false;
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700567 UpdateMediaSendRecvState_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000568}
569
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200570void BaseChannel::UpdateWritableState_n() {
Zhi Huange830e682018-03-30 10:48:35 -0700571 if (rtp_transport_->IsWritable(/*rtcp=*/true) &&
572 rtp_transport_->IsWritable(/*rtcp=*/false)) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200573 ChannelWritable_n();
deadbeefcbecd352015-09-23 11:50:27 -0700574 } else {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200575 ChannelNotWritable_n();
deadbeefcbecd352015-09-23 11:50:27 -0700576 }
577}
578
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200579void BaseChannel::ChannelWritable_n() {
580 RTC_DCHECK(network_thread_->IsCurrent());
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800581 if (writable_) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000582 return;
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800583 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000584
Mirko Bonadei675513b2017-11-09 11:09:25 +0100585 RTC_LOG(LS_INFO) << "Channel writable (" << content_name_ << ")"
586 << (was_ever_writable_ ? "" : " for the first time");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000587
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000588 was_ever_writable_ = true;
589 writable_ = true;
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700590 UpdateMediaSendRecvState();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000591}
592
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200593void BaseChannel::ChannelNotWritable_n() {
594 RTC_DCHECK(network_thread_->IsCurrent());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000595 if (!writable_)
596 return;
597
Mirko Bonadei675513b2017-11-09 11:09:25 +0100598 RTC_LOG(LS_INFO) << "Channel not writable (" << content_name_ << ")";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000599 writable_ = false;
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700600 UpdateMediaSendRecvState();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000601}
602
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000603bool BaseChannel::AddRecvStream_w(const StreamParams& sp) {
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700604 RTC_DCHECK(worker_thread() == rtc::Thread::Current());
pbos482b12e2015-11-16 10:19:58 -0800605 return media_channel()->AddRecvStream(sp);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000606}
607
Peter Boström0c4e06b2015-10-07 12:23:21 +0200608bool BaseChannel::RemoveRecvStream_w(uint32_t ssrc) {
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700609 RTC_DCHECK(worker_thread() == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000610 return media_channel()->RemoveRecvStream(ssrc);
611}
612
613bool BaseChannel::UpdateLocalStreams_w(const std::vector<StreamParams>& streams,
Steve Anton3828c062017-12-06 10:34:51 -0800614 SdpType type,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000615 std::string* error_desc) {
Amit Hilbuchbcd39d42019-01-25 17:13:56 -0800616 // In the case of RIDs (where SSRCs are not negotiated), this method will
617 // generate an SSRC for each layer in StreamParams. That representation will
618 // be stored internally in |local_streams_|.
619 // In subsequent offers, the same stream can appear in |streams| again
620 // (without the SSRCs), so it should be looked up using RIDs (if available)
621 // and then by primary SSRC.
622 // In both scenarios, it is safe to assume that the media channel will be
623 // created with a StreamParams object with SSRCs. However, it is not safe to
624 // assume that |local_streams_| will always have SSRCs as there are scenarios
625 // in which niether SSRCs or RIDs are negotiated.
626
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000627 // Check for streams that have been removed.
628 bool ret = true;
Steve Anton5f8b5fd2018-12-27 16:58:10 -0800629 for (const StreamParams& old_stream : local_streams_) {
Amit Hilbuchbcd39d42019-01-25 17:13:56 -0800630 if (!old_stream.has_ssrcs() ||
631 GetStream(streams, StreamFinder(&old_stream))) {
632 continue;
633 }
634 if (!media_channel()->RemoveSendStream(old_stream.first_ssrc())) {
635 rtc::StringBuilder desc;
636 desc << "Failed to remove send stream with ssrc "
637 << old_stream.first_ssrc() << ".";
638 SafeSetError(desc.str(), error_desc);
639 ret = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000640 }
641 }
642 // Check for new streams.
Amit Hilbuchbcd39d42019-01-25 17:13:56 -0800643 std::vector<StreamParams> all_streams;
644 for (const StreamParams& stream : streams) {
645 StreamParams* existing = GetStream(local_streams_, StreamFinder(&stream));
646 if (existing) {
647 // Parameters cannot change for an existing stream.
648 all_streams.push_back(*existing);
649 continue;
650 }
651
652 all_streams.push_back(stream);
653 StreamParams& new_stream = all_streams.back();
654
655 if (!new_stream.has_ssrcs() && !new_stream.has_rids()) {
656 continue;
657 }
658
659 RTC_DCHECK(new_stream.has_ssrcs() || new_stream.has_rids());
660 if (new_stream.has_ssrcs() && new_stream.has_rids()) {
661 rtc::StringBuilder desc;
662 desc << "Failed to add send stream: " << new_stream.first_ssrc()
663 << ". Stream has both SSRCs and RIDs.";
664 SafeSetError(desc.str(), error_desc);
665 ret = false;
666 continue;
667 }
668
669 // At this point we use the legacy simulcast group in StreamParams to
670 // indicate that we want multiple layers to the media channel.
671 if (!new_stream.has_ssrcs()) {
672 // TODO(bugs.webrtc.org/10250): Indicate if flex is desired here.
673 new_stream.GenerateSsrcs(new_stream.rids().size(), /* rtx = */ true,
674 /* flex_fec = */ false, ssrc_generator_);
675 }
676
677 if (media_channel()->AddSendStream(new_stream)) {
678 RTC_LOG(LS_INFO) << "Add send stream ssrc: " << new_stream.ssrcs[0];
679 } else {
680 rtc::StringBuilder desc;
681 desc << "Failed to add send stream ssrc: " << new_stream.first_ssrc();
682 SafeSetError(desc.str(), error_desc);
683 ret = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000684 }
685 }
Amit Hilbuchbcd39d42019-01-25 17:13:56 -0800686 local_streams_ = all_streams;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000687 return ret;
688}
689
690bool BaseChannel::UpdateRemoteStreams_w(
691 const std::vector<StreamParams>& streams,
Steve Anton3828c062017-12-06 10:34:51 -0800692 SdpType type,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000693 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000694 // Check for streams that have been removed.
695 bool ret = true;
Steve Anton5f8b5fd2018-12-27 16:58:10 -0800696 for (const StreamParams& old_stream : remote_streams_) {
Seth Hampson5897a6e2018-04-03 11:16:33 -0700697 // If we no longer have an unsignaled stream, we would like to remove
698 // the unsignaled stream params that are cached.
Steve Anton5f8b5fd2018-12-27 16:58:10 -0800699 if ((!old_stream.has_ssrcs() && !HasStreamWithNoSsrcs(streams)) ||
700 !GetStreamBySsrc(streams, old_stream.first_ssrc())) {
701 if (RemoveRecvStream_w(old_stream.first_ssrc())) {
702 RTC_LOG(LS_INFO) << "Remove remote ssrc: " << old_stream.first_ssrc();
Zhi Huang365381f2018-04-13 16:44:34 -0700703 } else {
Jonas Olsson366a50c2018-09-06 13:41:30 +0200704 rtc::StringBuilder desc;
Steve Anton5f8b5fd2018-12-27 16:58:10 -0800705 desc << "Failed to remove remote stream with ssrc "
706 << old_stream.first_ssrc() << ".";
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000707 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000708 ret = false;
709 }
710 }
711 }
Zhi Huang365381f2018-04-13 16:44:34 -0700712 demuxer_criteria_.ssrcs.clear();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000713 // Check for new streams.
Steve Anton5f8b5fd2018-12-27 16:58:10 -0800714 for (const StreamParams& new_stream : streams) {
Seth Hampson5897a6e2018-04-03 11:16:33 -0700715 // We allow a StreamParams with an empty list of SSRCs, in which case the
716 // MediaChannel will cache the parameters and use them for any unsignaled
717 // stream received later.
Steve Anton5f8b5fd2018-12-27 16:58:10 -0800718 if ((!new_stream.has_ssrcs() && !HasStreamWithNoSsrcs(remote_streams_)) ||
719 !GetStreamBySsrc(remote_streams_, new_stream.first_ssrc())) {
720 if (AddRecvStream_w(new_stream)) {
721 RTC_LOG(LS_INFO) << "Add remote ssrc: " << new_stream.first_ssrc();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000722 } else {
Jonas Olsson366a50c2018-09-06 13:41:30 +0200723 rtc::StringBuilder desc;
Steve Anton5f8b5fd2018-12-27 16:58:10 -0800724 desc << "Failed to add remote stream ssrc: " << new_stream.first_ssrc();
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000725 SafeSetError(desc.str(), error_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000726 ret = false;
727 }
728 }
Zhi Huang365381f2018-04-13 16:44:34 -0700729 // Update the receiving SSRCs.
Steve Anton5f8b5fd2018-12-27 16:58:10 -0800730 demuxer_criteria_.ssrcs.insert(new_stream.ssrcs.begin(),
731 new_stream.ssrcs.end());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000732 }
Zhi Huang365381f2018-04-13 16:44:34 -0700733 // Re-register the sink to update the receiving ssrcs.
734 RegisterRtpDemuxerSink();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000735 remote_streams_ = streams;
736 return ret;
737}
738
jbauch5869f502017-06-29 12:31:36 -0700739RtpHeaderExtensions BaseChannel::GetFilteredRtpHeaderExtensions(
740 const RtpHeaderExtensions& extensions) {
Zhi Huange830e682018-03-30 10:48:35 -0700741 RTC_DCHECK(rtp_transport_);
Benjamin Wrighta54daf12018-10-11 15:33:17 -0700742 if (crypto_options_.srtp.enable_encrypted_rtp_header_extensions) {
jbauch5869f502017-06-29 12:31:36 -0700743 RtpHeaderExtensions filtered;
Steve Anton64b626b2019-01-28 17:25:26 -0800744 absl::c_copy_if(extensions, std::back_inserter(filtered),
745 [](const webrtc::RtpExtension& extension) {
746 return !extension.encrypt;
747 });
jbauch5869f502017-06-29 12:31:36 -0700748 return filtered;
749 }
750
751 return webrtc::RtpExtension::FilterDuplicateNonEncrypted(extensions);
752}
753
Yves Gerey665174f2018-06-19 15:03:05 +0200754void BaseChannel::OnMessage(rtc::Message* pmsg) {
Peter Boström6f28cf02015-12-07 23:17:15 +0100755 TRACE_EVENT0("webrtc", "BaseChannel::OnMessage");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000756 switch (pmsg->message_id) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200757 case MSG_SEND_RTP_PACKET:
758 case MSG_SEND_RTCP_PACKET: {
759 RTC_DCHECK(network_thread_->IsCurrent());
760 SendPacketMessageData* data =
761 static_cast<SendPacketMessageData*>(pmsg->pdata);
762 bool rtcp = pmsg->message_id == MSG_SEND_RTCP_PACKET;
763 SendPacket(rtcp, &data->packet, data->options);
764 delete data;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000765 break;
766 }
767 case MSG_FIRSTPACKETRECEIVED: {
Amit Hilbuchdd9390c2018-11-13 16:26:05 -0800768 SignalFirstPacketReceived_(this);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000769 break;
770 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000771 }
772}
773
zstein3dcf0e92017-06-01 13:22:42 -0700774void BaseChannel::AddHandledPayloadType(int payload_type) {
Zhi Huang365381f2018-04-13 16:44:34 -0700775 demuxer_criteria_.payload_types.insert(static_cast<uint8_t>(payload_type));
zstein3dcf0e92017-06-01 13:22:42 -0700776}
777
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200778void BaseChannel::FlushRtcpMessages_n() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000779 // Flush all remaining RTCP messages. This should only be called in
780 // destructor.
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200781 RTC_DCHECK(network_thread_->IsCurrent());
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000782 rtc::MessageList rtcp_messages;
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200783 network_thread_->Clear(this, MSG_SEND_RTCP_PACKET, &rtcp_messages);
784 for (const auto& message : rtcp_messages) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700785 network_thread_->Send(RTC_FROM_HERE, this, MSG_SEND_RTCP_PACKET,
786 message.pdata);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000787 }
788}
789
Zhi Huangcd3fc5d2017-11-29 10:41:57 -0800790void BaseChannel::SignalSentPacket_n(const rtc::SentPacket& sent_packet) {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200791 RTC_DCHECK(network_thread_->IsCurrent());
792 invoker_.AsyncInvoke<void>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700793 RTC_FROM_HERE, worker_thread_,
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200794 rtc::Bind(&BaseChannel::SignalSentPacket_w, this, sent_packet));
795}
796
797void BaseChannel::SignalSentPacket_w(const rtc::SentPacket& sent_packet) {
798 RTC_DCHECK(worker_thread_->IsCurrent());
799 SignalSentPacket(sent_packet);
800}
801
802VoiceChannel::VoiceChannel(rtc::Thread* worker_thread,
803 rtc::Thread* network_thread,
zhihuangf5b251b2017-01-12 19:37:48 -0800804 rtc::Thread* signaling_thread,
Steve Anton8699a322017-11-06 15:53:33 -0800805 std::unique_ptr<VoiceMediaChannel> media_channel,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000806 const std::string& content_name,
Zhi Huange830e682018-03-30 10:48:35 -0700807 bool srtp_required,
Amit Hilbuchbcd39d42019-01-25 17:13:56 -0800808 webrtc::CryptoOptions crypto_options,
809 UniqueRandomIdGenerator* ssrc_generator)
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200810 : BaseChannel(worker_thread,
811 network_thread,
zhihuangf5b251b2017-01-12 19:37:48 -0800812 signaling_thread,
Steve Anton8699a322017-11-06 15:53:33 -0800813 std::move(media_channel),
deadbeefcbecd352015-09-23 11:50:27 -0700814 content_name,
Zhi Huange830e682018-03-30 10:48:35 -0700815 srtp_required,
Amit Hilbuchbcd39d42019-01-25 17:13:56 -0800816 crypto_options,
817 ssrc_generator) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000818
819VoiceChannel::~VoiceChannel() {
Piotr (Peter) Slatala309aafe2019-01-15 14:24:34 -0800820 if (media_transport()) {
821 media_transport()->SetFirstAudioPacketReceivedObserver(nullptr);
822 }
Peter Boströmca8b4042016-03-08 14:24:13 -0800823 TRACE_EVENT0("webrtc", "VoiceChannel::~VoiceChannel");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000824 // this can't be done in the base class, since it calls a virtual
825 DisableMedia_w();
Zhi Huang0ffe03d2018-03-30 13:17:42 -0700826 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000827}
828
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700829void BaseChannel::UpdateMediaSendRecvState() {
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200830 RTC_DCHECK(network_thread_->IsCurrent());
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700831 invoker_.AsyncInvoke<void>(
832 RTC_FROM_HERE, worker_thread_,
833 Bind(&BaseChannel::UpdateMediaSendRecvState_w, this));
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200834}
835
Piotr (Peter) Slatala179a3922018-11-16 09:57:58 -0800836void BaseChannel::OnNetworkRouteChanged(
837 const rtc::NetworkRoute& network_route) {
838 OnNetworkRouteChanged(absl::make_optional(network_route));
839}
840
Anton Sukhanov4f08faa2019-05-21 11:12:57 -0700841void VoiceChannel::Init_w(
842 webrtc::RtpTransportInternal* rtp_transport,
843 const webrtc::MediaTransportConfig& media_transport_config) {
844 BaseChannel::Init_w(rtp_transport, media_transport_config);
845 if (media_transport_config.media_transport) {
846 media_transport_config.media_transport->SetFirstAudioPacketReceivedObserver(
847 this);
Piotr (Peter) Slatala309aafe2019-01-15 14:24:34 -0800848 }
849}
850
851void VoiceChannel::OnFirstAudioPacketReceived(int64_t channel_id) {
852 has_received_packet_ = true;
853 signaling_thread()->Post(RTC_FROM_HERE, this, MSG_FIRSTPACKETRECEIVED);
854}
855
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700856void VoiceChannel::UpdateMediaSendRecvState_w() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000857 // Render incoming data if we're the active call, and we have the local
858 // content. We receive data on the default channel and multiplexed streams.
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700859 bool recv = IsReadyToReceiveMedia_w();
solenberg5b14b422015-10-01 04:10:31 -0700860 media_channel()->SetPlayout(recv);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000861
862 // Send outgoing data if we're the active call, we have the remote content,
863 // and we have had some form of connectivity.
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700864 bool send = IsReadyToSendMedia_w();
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800865 media_channel()->SetSend(send);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000866
Mirko Bonadei675513b2017-11-09 11:09:25 +0100867 RTC_LOG(LS_INFO) << "Changing voice state, recv=" << recv << " send=" << send;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000868}
869
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000870bool VoiceChannel::SetLocalContent_w(const MediaContentDescription* content,
Steve Anton3828c062017-12-06 10:34:51 -0800871 SdpType type,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000872 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +0100873 TRACE_EVENT0("webrtc", "VoiceChannel::SetLocalContent_w");
Steve Antonb1c1de12017-12-21 15:14:30 -0800874 RTC_DCHECK_RUN_ON(worker_thread());
Mirko Bonadei675513b2017-11-09 11:09:25 +0100875 RTC_LOG(LS_INFO) << "Setting local voice description";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000876
Steve Antonb1c1de12017-12-21 15:14:30 -0800877 RTC_DCHECK(content);
878 if (!content) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000879 SafeSetError("Can't find audio content in local description.", error_desc);
880 return false;
881 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000882
Steve Antonb1c1de12017-12-21 15:14:30 -0800883 const AudioContentDescription* audio = content->as_audio();
884
jbauch5869f502017-06-29 12:31:36 -0700885 RtpHeaderExtensions rtp_header_extensions =
886 GetFilteredRtpHeaderExtensions(audio->rtp_header_extensions());
Zhi Huang365381f2018-04-13 16:44:34 -0700887 UpdateRtpHeaderExtensionMap(rtp_header_extensions);
Johannes Kron9190b822018-10-29 11:22:05 +0100888 media_channel()->SetExtmapAllowMixed(audio->extmap_allow_mixed());
jbauch5869f502017-06-29 12:31:36 -0700889
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700890 AudioRecvParameters recv_params = last_recv_params_;
jbauch5869f502017-06-29 12:31:36 -0700891 RtpParametersFromMediaDescription(audio, rtp_header_extensions, &recv_params);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700892 if (!media_channel()->SetRecvParameters(recv_params)) {
Peter Thatcherbfab5cb2015-08-20 17:40:24 -0700893 SafeSetError("Failed to set local audio description recv parameters.",
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700894 error_desc);
895 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000896 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700897 for (const AudioCodec& codec : audio->codecs()) {
zstein3dcf0e92017-06-01 13:22:42 -0700898 AddHandledPayloadType(codec.id);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700899 }
Zhi Huang365381f2018-04-13 16:44:34 -0700900 // Need to re-register the sink to update the handled payload.
901 if (!RegisterRtpDemuxerSink()) {
902 RTC_LOG(LS_ERROR) << "Failed to set up audio demuxing.";
903 return false;
904 }
905
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700906 last_recv_params_ = recv_params;
907
908 // TODO(pthatcher): Move local streams into AudioSendParameters, and
909 // only give it to the media channel once we have a remote
910 // description too (without a remote description, we won't be able
911 // to send them anyway).
Steve Anton3828c062017-12-06 10:34:51 -0800912 if (!UpdateLocalStreams_w(audio->streams(), type, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700913 SafeSetError("Failed to set local audio description streams.", error_desc);
914 return false;
915 }
916
917 set_local_content_direction(content->direction());
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700918 UpdateMediaSendRecvState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700919 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000920}
921
922bool VoiceChannel::SetRemoteContent_w(const MediaContentDescription* content,
Steve Anton3828c062017-12-06 10:34:51 -0800923 SdpType type,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000924 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +0100925 TRACE_EVENT0("webrtc", "VoiceChannel::SetRemoteContent_w");
Steve Antonb1c1de12017-12-21 15:14:30 -0800926 RTC_DCHECK_RUN_ON(worker_thread());
Mirko Bonadei675513b2017-11-09 11:09:25 +0100927 RTC_LOG(LS_INFO) << "Setting remote voice description";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000928
Steve Antonb1c1de12017-12-21 15:14:30 -0800929 RTC_DCHECK(content);
930 if (!content) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000931 SafeSetError("Can't find audio content in remote description.", error_desc);
932 return false;
933 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000934
Steve Antonb1c1de12017-12-21 15:14:30 -0800935 const AudioContentDescription* audio = content->as_audio();
936
jbauch5869f502017-06-29 12:31:36 -0700937 RtpHeaderExtensions rtp_header_extensions =
938 GetFilteredRtpHeaderExtensions(audio->rtp_header_extensions());
939
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700940 AudioSendParameters send_params = last_send_params_;
jbauch5869f502017-06-29 12:31:36 -0700941 RtpSendParametersFromMediaDescription(audio, rtp_header_extensions,
Yves Gerey665174f2018-06-19 15:03:05 +0200942 &send_params);
Steve Antonbb50ce52018-03-26 10:24:32 -0700943 send_params.mid = content_name();
skvladdc1c62c2016-03-16 19:07:43 -0700944
945 bool parameters_applied = media_channel()->SetSendParameters(send_params);
946 if (!parameters_applied) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700947 SafeSetError("Failed to set remote audio description send parameters.",
948 error_desc);
949 return false;
950 }
951 last_send_params_ = send_params;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000952
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700953 // TODO(pthatcher): Move remote streams into AudioRecvParameters,
954 // and only give it to the media channel once we have a local
955 // description too (without a local description, we won't be able to
956 // recv them anyway).
Steve Anton3828c062017-12-06 10:34:51 -0800957 if (!UpdateRemoteStreams_w(audio->streams(), type, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700958 SafeSetError("Failed to set remote audio description streams.", error_desc);
959 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000960 }
961
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700962 set_remote_content_direction(content->direction());
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700963 UpdateMediaSendRecvState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -0700964 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000965}
966
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200967VideoChannel::VideoChannel(rtc::Thread* worker_thread,
968 rtc::Thread* network_thread,
zhihuangf5b251b2017-01-12 19:37:48 -0800969 rtc::Thread* signaling_thread,
Steve Anton8699a322017-11-06 15:53:33 -0800970 std::unique_ptr<VideoMediaChannel> media_channel,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000971 const std::string& content_name,
Zhi Huange830e682018-03-30 10:48:35 -0700972 bool srtp_required,
Amit Hilbuchbcd39d42019-01-25 17:13:56 -0800973 webrtc::CryptoOptions crypto_options,
974 UniqueRandomIdGenerator* ssrc_generator)
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200975 : BaseChannel(worker_thread,
976 network_thread,
zhihuangf5b251b2017-01-12 19:37:48 -0800977 signaling_thread,
Steve Anton8699a322017-11-06 15:53:33 -0800978 std::move(media_channel),
deadbeefcbecd352015-09-23 11:50:27 -0700979 content_name,
Zhi Huange830e682018-03-30 10:48:35 -0700980 srtp_required,
Amit Hilbuchbcd39d42019-01-25 17:13:56 -0800981 crypto_options,
982 ssrc_generator) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000983
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000984VideoChannel::~VideoChannel() {
Peter Boströmca8b4042016-03-08 14:24:13 -0800985 TRACE_EVENT0("webrtc", "VideoChannel::~VideoChannel");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000986 // this can't be done in the base class, since it calls a virtual
987 DisableMedia_w();
Zhi Huang0ffe03d2018-03-30 13:17:42 -0700988 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000989}
990
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700991void VideoChannel::UpdateMediaSendRecvState_w() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000992 // Send outgoing data if we're the active call, we have the remote content,
993 // and we have had some form of connectivity.
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -0700994 bool send = IsReadyToSendMedia_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000995 if (!media_channel()->SetSend(send)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100996 RTC_LOG(LS_ERROR) << "Failed to SetSend on video channel";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000997 // TODO(gangji): Report error back to server.
998 }
999
Mirko Bonadei675513b2017-11-09 11:09:25 +01001000 RTC_LOG(LS_INFO) << "Changing video state, send=" << send;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001001}
1002
stefanf79ade12017-06-02 06:44:03 -07001003void VideoChannel::FillBitrateInfo(BandwidthEstimationInfo* bwe_info) {
1004 InvokeOnWorker<void>(RTC_FROM_HERE, Bind(&VideoMediaChannel::FillBitrateInfo,
1005 media_channel(), bwe_info));
1006}
1007
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001008bool VideoChannel::SetLocalContent_w(const MediaContentDescription* content,
Steve Anton3828c062017-12-06 10:34:51 -08001009 SdpType type,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001010 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01001011 TRACE_EVENT0("webrtc", "VideoChannel::SetLocalContent_w");
Steve Antonb1c1de12017-12-21 15:14:30 -08001012 RTC_DCHECK_RUN_ON(worker_thread());
Mirko Bonadei675513b2017-11-09 11:09:25 +01001013 RTC_LOG(LS_INFO) << "Setting local video description";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001014
Steve Antonb1c1de12017-12-21 15:14:30 -08001015 RTC_DCHECK(content);
1016 if (!content) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001017 SafeSetError("Can't find video content in local description.", error_desc);
1018 return false;
1019 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001020
Steve Antonb1c1de12017-12-21 15:14:30 -08001021 const VideoContentDescription* video = content->as_video();
1022
jbauch5869f502017-06-29 12:31:36 -07001023 RtpHeaderExtensions rtp_header_extensions =
1024 GetFilteredRtpHeaderExtensions(video->rtp_header_extensions());
Zhi Huang365381f2018-04-13 16:44:34 -07001025 UpdateRtpHeaderExtensionMap(rtp_header_extensions);
Johannes Kron9190b822018-10-29 11:22:05 +01001026 media_channel()->SetExtmapAllowMixed(video->extmap_allow_mixed());
jbauch5869f502017-06-29 12:31:36 -07001027
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001028 VideoRecvParameters recv_params = last_recv_params_;
jbauch5869f502017-06-29 12:31:36 -07001029 RtpParametersFromMediaDescription(video, rtp_header_extensions, &recv_params);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001030 if (!media_channel()->SetRecvParameters(recv_params)) {
1031 SafeSetError("Failed to set local video description recv parameters.",
1032 error_desc);
1033 return false;
1034 }
1035 for (const VideoCodec& codec : video->codecs()) {
zstein3dcf0e92017-06-01 13:22:42 -07001036 AddHandledPayloadType(codec.id);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001037 }
Zhi Huang365381f2018-04-13 16:44:34 -07001038 // Need to re-register the sink to update the handled payload.
1039 if (!RegisterRtpDemuxerSink()) {
1040 RTC_LOG(LS_ERROR) << "Failed to set up video demuxing.";
1041 return false;
1042 }
1043
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001044 last_recv_params_ = recv_params;
1045
1046 // TODO(pthatcher): Move local streams into VideoSendParameters, and
1047 // only give it to the media channel once we have a remote
1048 // description too (without a remote description, we won't be able
1049 // to send them anyway).
Steve Anton3828c062017-12-06 10:34:51 -08001050 if (!UpdateLocalStreams_w(video->streams(), type, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001051 SafeSetError("Failed to set local video description streams.", error_desc);
1052 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001053 }
1054
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001055 set_local_content_direction(content->direction());
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001056 UpdateMediaSendRecvState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001057 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001058}
1059
1060bool VideoChannel::SetRemoteContent_w(const MediaContentDescription* content,
Steve Anton3828c062017-12-06 10:34:51 -08001061 SdpType type,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001062 std::string* error_desc) {
Peter Boström9f45a452015-12-08 13:25:57 +01001063 TRACE_EVENT0("webrtc", "VideoChannel::SetRemoteContent_w");
Steve Antonb1c1de12017-12-21 15:14:30 -08001064 RTC_DCHECK_RUN_ON(worker_thread());
Mirko Bonadei675513b2017-11-09 11:09:25 +01001065 RTC_LOG(LS_INFO) << "Setting remote video description";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001066
Steve Antonb1c1de12017-12-21 15:14:30 -08001067 RTC_DCHECK(content);
1068 if (!content) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001069 SafeSetError("Can't find video content in remote description.", error_desc);
1070 return false;
1071 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001072
Steve Antonb1c1de12017-12-21 15:14:30 -08001073 const VideoContentDescription* video = content->as_video();
1074
jbauch5869f502017-06-29 12:31:36 -07001075 RtpHeaderExtensions rtp_header_extensions =
1076 GetFilteredRtpHeaderExtensions(video->rtp_header_extensions());
1077
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001078 VideoSendParameters send_params = last_send_params_;
jbauch5869f502017-06-29 12:31:36 -07001079 RtpSendParametersFromMediaDescription(video, rtp_header_extensions,
Yves Gerey665174f2018-06-19 15:03:05 +02001080 &send_params);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001081 if (video->conference_mode()) {
nisse4b4dc862016-02-17 05:25:36 -08001082 send_params.conference_mode = true;
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001083 }
Steve Antonbb50ce52018-03-26 10:24:32 -07001084 send_params.mid = content_name();
skvladdc1c62c2016-03-16 19:07:43 -07001085
1086 bool parameters_applied = media_channel()->SetSendParameters(send_params);
1087
1088 if (!parameters_applied) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001089 SafeSetError("Failed to set remote video description send parameters.",
1090 error_desc);
1091 return false;
1092 }
1093 last_send_params_ = send_params;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001094
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001095 // TODO(pthatcher): Move remote streams into VideoRecvParameters,
1096 // and only give it to the media channel once we have a local
1097 // description too (without a local description, we won't be able to
1098 // recv them anyway).
Steve Anton3828c062017-12-06 10:34:51 -08001099 if (!UpdateRemoteStreams_w(video->streams(), type, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001100 SafeSetError("Failed to set remote video description streams.", error_desc);
1101 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001102 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001103 set_remote_content_direction(content->direction());
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001104 UpdateMediaSendRecvState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001105 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001106}
1107
deadbeef953c2ce2017-01-09 14:53:41 -08001108RtpDataChannel::RtpDataChannel(rtc::Thread* worker_thread,
1109 rtc::Thread* network_thread,
zhihuangf5b251b2017-01-12 19:37:48 -08001110 rtc::Thread* signaling_thread,
Steve Anton8699a322017-11-06 15:53:33 -08001111 std::unique_ptr<DataMediaChannel> media_channel,
deadbeef953c2ce2017-01-09 14:53:41 -08001112 const std::string& content_name,
Zhi Huange830e682018-03-30 10:48:35 -07001113 bool srtp_required,
Amit Hilbuchbcd39d42019-01-25 17:13:56 -08001114 webrtc::CryptoOptions crypto_options,
1115 UniqueRandomIdGenerator* ssrc_generator)
Danil Chapovalov33b01f22016-05-11 19:55:27 +02001116 : BaseChannel(worker_thread,
1117 network_thread,
zhihuangf5b251b2017-01-12 19:37:48 -08001118 signaling_thread,
Steve Anton8699a322017-11-06 15:53:33 -08001119 std::move(media_channel),
deadbeefcbecd352015-09-23 11:50:27 -07001120 content_name,
Zhi Huange830e682018-03-30 10:48:35 -07001121 srtp_required,
Amit Hilbuchbcd39d42019-01-25 17:13:56 -08001122 crypto_options,
1123 ssrc_generator) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001124
deadbeef953c2ce2017-01-09 14:53:41 -08001125RtpDataChannel::~RtpDataChannel() {
1126 TRACE_EVENT0("webrtc", "RtpDataChannel::~RtpDataChannel");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001127 // this can't be done in the base class, since it calls a virtual
1128 DisableMedia_w();
Zhi Huang0ffe03d2018-03-30 13:17:42 -07001129 Deinit();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001130}
1131
Anton Sukhanov4f08faa2019-05-21 11:12:57 -07001132void RtpDataChannel::Init_w(
1133 webrtc::RtpTransportInternal* rtp_transport,
1134 const webrtc::MediaTransportConfig& media_transport_config) {
1135 BaseChannel::Init_w(rtp_transport, media_transport_config);
Zhi Huang2dfc42d2017-12-04 13:38:48 -08001136 media_channel()->SignalDataReceived.connect(this,
1137 &RtpDataChannel::OnDataReceived);
1138 media_channel()->SignalReadyToSend.connect(
1139 this, &RtpDataChannel::OnDataChannelReadyToSend);
1140}
1141
deadbeef953c2ce2017-01-09 14:53:41 -08001142bool RtpDataChannel::SendData(const SendDataParams& params,
1143 const rtc::CopyOnWriteBuffer& payload,
1144 SendDataResult* result) {
stefanf79ade12017-06-02 06:44:03 -07001145 return InvokeOnWorker<bool>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001146 RTC_FROM_HERE, Bind(&DataMediaChannel::SendData, media_channel(), params,
1147 payload, result));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001148}
1149
deadbeef953c2ce2017-01-09 14:53:41 -08001150bool RtpDataChannel::CheckDataChannelTypeFromContent(
Harald Alvestrand5fc28b12019-05-13 13:36:16 +02001151 const RtpDataContentDescription* content,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001152 std::string* error_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001153 bool is_sctp = ((content->protocol() == kMediaProtocolSctp) ||
1154 (content->protocol() == kMediaProtocolDtlsSctp));
deadbeef953c2ce2017-01-09 14:53:41 -08001155 // It's been set before, but doesn't match. That's bad.
1156 if (is_sctp) {
1157 SafeSetError("Data channel type mismatch. Expected RTP, got SCTP.",
1158 error_desc);
1159 return false;
1160 }
1161 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001162}
1163
deadbeef953c2ce2017-01-09 14:53:41 -08001164bool RtpDataChannel::SetLocalContent_w(const MediaContentDescription* content,
Steve Anton3828c062017-12-06 10:34:51 -08001165 SdpType type,
deadbeef953c2ce2017-01-09 14:53:41 -08001166 std::string* error_desc) {
1167 TRACE_EVENT0("webrtc", "RtpDataChannel::SetLocalContent_w");
Steve Antonb1c1de12017-12-21 15:14:30 -08001168 RTC_DCHECK_RUN_ON(worker_thread());
Mirko Bonadei675513b2017-11-09 11:09:25 +01001169 RTC_LOG(LS_INFO) << "Setting local data description";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001170
Steve Antonb1c1de12017-12-21 15:14:30 -08001171 RTC_DCHECK(content);
1172 if (!content) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001173 SafeSetError("Can't find data content in local description.", error_desc);
1174 return false;
1175 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001176
Harald Alvestrand5fc28b12019-05-13 13:36:16 +02001177 const RtpDataContentDescription* data = content->as_rtp_data();
Steve Antonb1c1de12017-12-21 15:14:30 -08001178
deadbeef953c2ce2017-01-09 14:53:41 -08001179 if (!CheckDataChannelTypeFromContent(data, error_desc)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001180 return false;
1181 }
1182
jbauch5869f502017-06-29 12:31:36 -07001183 RtpHeaderExtensions rtp_header_extensions =
1184 GetFilteredRtpHeaderExtensions(data->rtp_header_extensions());
1185
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001186 DataRecvParameters recv_params = last_recv_params_;
jbauch5869f502017-06-29 12:31:36 -07001187 RtpParametersFromMediaDescription(data, rtp_header_extensions, &recv_params);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001188 if (!media_channel()->SetRecvParameters(recv_params)) {
1189 SafeSetError("Failed to set remote data description recv parameters.",
1190 error_desc);
1191 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001192 }
deadbeef953c2ce2017-01-09 14:53:41 -08001193 for (const DataCodec& codec : data->codecs()) {
zstein3dcf0e92017-06-01 13:22:42 -07001194 AddHandledPayloadType(codec.id);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001195 }
Zhi Huang365381f2018-04-13 16:44:34 -07001196 // Need to re-register the sink to update the handled payload.
1197 if (!RegisterRtpDemuxerSink()) {
1198 RTC_LOG(LS_ERROR) << "Failed to set up data demuxing.";
1199 return false;
1200 }
1201
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001202 last_recv_params_ = recv_params;
1203
1204 // TODO(pthatcher): Move local streams into DataSendParameters, and
1205 // only give it to the media channel once we have a remote
1206 // description too (without a remote description, we won't be able
1207 // to send them anyway).
Steve Anton3828c062017-12-06 10:34:51 -08001208 if (!UpdateLocalStreams_w(data->streams(), type, error_desc)) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001209 SafeSetError("Failed to set local data description streams.", error_desc);
1210 return false;
1211 }
1212
1213 set_local_content_direction(content->direction());
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001214 UpdateMediaSendRecvState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001215 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001216}
1217
deadbeef953c2ce2017-01-09 14:53:41 -08001218bool RtpDataChannel::SetRemoteContent_w(const MediaContentDescription* content,
Steve Anton3828c062017-12-06 10:34:51 -08001219 SdpType type,
deadbeef953c2ce2017-01-09 14:53:41 -08001220 std::string* error_desc) {
1221 TRACE_EVENT0("webrtc", "RtpDataChannel::SetRemoteContent_w");
Steve Antonb1c1de12017-12-21 15:14:30 -08001222 RTC_DCHECK_RUN_ON(worker_thread());
1223 RTC_LOG(LS_INFO) << "Setting remote data description";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001224
Steve Antonb1c1de12017-12-21 15:14:30 -08001225 RTC_DCHECK(content);
1226 if (!content) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001227 SafeSetError("Can't find data content in remote description.", error_desc);
1228 return false;
1229 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001230
Harald Alvestrand5fc28b12019-05-13 13:36:16 +02001231 const RtpDataContentDescription* data = content->as_rtp_data();
1232
1233 if (!data) {
1234 RTC_LOG(LS_INFO) << "Accepting and ignoring non-RTP content description";
1235 return true;
1236 }
Steve Antonb1c1de12017-12-21 15:14:30 -08001237
Zhi Huang801b8682017-11-15 11:36:43 -08001238 // If the remote data doesn't have codecs, it must be empty, so ignore it.
1239 if (!data->has_codecs()) {
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001240 return true;
1241 }
1242
deadbeef953c2ce2017-01-09 14:53:41 -08001243 if (!CheckDataChannelTypeFromContent(data, error_desc)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001244 return false;
1245 }
1246
jbauch5869f502017-06-29 12:31:36 -07001247 RtpHeaderExtensions rtp_header_extensions =
1248 GetFilteredRtpHeaderExtensions(data->rtp_header_extensions());
1249
Mirko Bonadei675513b2017-11-09 11:09:25 +01001250 RTC_LOG(LS_INFO) << "Setting remote data description";
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001251 DataSendParameters send_params = last_send_params_;
jbauch5869f502017-06-29 12:31:36 -07001252 RtpSendParametersFromMediaDescription<DataCodec>(data, rtp_header_extensions,
Yves Gerey665174f2018-06-19 15:03:05 +02001253 &send_params);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001254 if (!media_channel()->SetSendParameters(send_params)) {
1255 SafeSetError("Failed to set remote data description send parameters.",
1256 error_desc);
1257 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001258 }
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001259 last_send_params_ = send_params;
1260
1261 // TODO(pthatcher): Move remote streams into DataRecvParameters,
1262 // and only give it to the media channel once we have a local
1263 // description too (without a local description, we won't be able to
1264 // recv them anyway).
Steve Anton3828c062017-12-06 10:34:51 -08001265 if (!UpdateRemoteStreams_w(data->streams(), type, error_desc)) {
Yves Gerey665174f2018-06-19 15:03:05 +02001266 SafeSetError("Failed to set remote data description streams.", error_desc);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001267 return false;
1268 }
1269
1270 set_remote_content_direction(content->direction());
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001271 UpdateMediaSendRecvState_w();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001272 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001273}
1274
deadbeef953c2ce2017-01-09 14:53:41 -08001275void RtpDataChannel::UpdateMediaSendRecvState_w() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001276 // Render incoming data if we're the active call, and we have the local
1277 // content. We receive data on the default channel and multiplexed streams.
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001278 bool recv = IsReadyToReceiveMedia_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001279 if (!media_channel()->SetReceive(recv)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001280 RTC_LOG(LS_ERROR) << "Failed to SetReceive on data channel";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001281 }
1282
1283 // Send outgoing data if we're the active call, we have the remote content,
1284 // and we have had some form of connectivity.
Taylor Brandstetterbad33bf2016-08-25 13:31:14 -07001285 bool send = IsReadyToSendMedia_w();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001286 if (!media_channel()->SetSend(send)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001287 RTC_LOG(LS_ERROR) << "Failed to SetSend on data channel";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001288 }
1289
sergeyu@chromium.org9cf037b2014-02-07 19:03:26 +00001290 // Trigger SignalReadyToSendData asynchronously.
1291 OnDataChannelReadyToSend(send);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001292
Mirko Bonadei675513b2017-11-09 11:09:25 +01001293 RTC_LOG(LS_INFO) << "Changing data state, recv=" << recv << " send=" << send;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001294}
1295
deadbeef953c2ce2017-01-09 14:53:41 -08001296void RtpDataChannel::OnMessage(rtc::Message* pmsg) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001297 switch (pmsg->message_id) {
1298 case MSG_READYTOSENDDATA: {
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00001299 DataChannelReadyToSendMessageData* data =
1300 static_cast<DataChannelReadyToSendMessageData*>(pmsg->pdata);
wu@webrtc.org07a6fbe2013-11-04 18:41:34 +00001301 ready_to_send_data_ = data->data();
1302 SignalReadyToSendData(ready_to_send_data_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001303 delete data;
1304 break;
1305 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001306 case MSG_DATARECEIVED: {
1307 DataReceivedMessageData* data =
1308 static_cast<DataReceivedMessageData*>(pmsg->pdata);
deadbeef953c2ce2017-01-09 14:53:41 -08001309 SignalDataReceived(data->params, data->payload);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001310 delete data;
1311 break;
1312 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001313 default:
1314 BaseChannel::OnMessage(pmsg);
1315 break;
1316 }
1317}
1318
deadbeef953c2ce2017-01-09 14:53:41 -08001319void RtpDataChannel::OnDataReceived(const ReceiveDataParams& params,
1320 const char* data,
1321 size_t len) {
Yves Gerey665174f2018-06-19 15:03:05 +02001322 DataReceivedMessageData* msg = new DataReceivedMessageData(params, data, len);
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001323 signaling_thread()->Post(RTC_FROM_HERE, this, MSG_DATARECEIVED, msg);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001324}
1325
deadbeef953c2ce2017-01-09 14:53:41 -08001326void RtpDataChannel::OnDataChannelReadyToSend(bool writable) {
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00001327 // This is usded for congestion control to indicate that the stream is ready
1328 // to send by the MediaChannel, as opposed to OnReadyToSend, which indicates
1329 // that the transport channel is ready.
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001330 signaling_thread()->Post(RTC_FROM_HERE, this, MSG_READYTOSENDDATA,
wu@webrtc.orgd64719d2013-08-01 00:00:07 +00001331 new DataChannelReadyToSendMessageData(writable));
1332}
1333
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001334} // namespace cricket