1 /*
2 * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
3 *
4 * 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.
9 */
10
11 #include "media/base/media_channel.h"
12
13 #include "media/base/rtp_utils.h"
14
15 namespace webrtc {
16
InvokeSetParametersCallback(SetParametersCallback & callback,RTCError error)17 webrtc::RTCError InvokeSetParametersCallback(SetParametersCallback& callback,
18 RTCError error) {
19 if (callback) {
20 std::move(callback)(error);
21 callback = nullptr;
22 }
23 return error;
24 }
25
26 } // namespace webrtc
27
28 namespace cricket {
29 using webrtc::FrameDecryptorInterface;
30 using webrtc::FrameEncryptorInterface;
31 using webrtc::FrameTransformerInterface;
32 using webrtc::PendingTaskSafetyFlag;
33 using webrtc::SafeTask;
34 using webrtc::TaskQueueBase;
35 using webrtc::VideoTrackInterface;
36
VideoOptions()37 VideoOptions::VideoOptions()
38 : content_hint(VideoTrackInterface::ContentHint::kNone) {}
39 VideoOptions::~VideoOptions() = default;
40
MediaChannel(TaskQueueBase * network_thread,bool enable_dscp)41 MediaChannel::MediaChannel(TaskQueueBase* network_thread, bool enable_dscp)
42 : enable_dscp_(enable_dscp),
43 network_safety_(PendingTaskSafetyFlag::CreateDetachedInactive()),
44 network_thread_(network_thread) {}
45
~MediaChannel()46 MediaChannel::~MediaChannel() {
47 RTC_DCHECK(!network_interface_);
48 }
49
SetInterface(NetworkInterface * iface)50 void MediaChannel::SetInterface(NetworkInterface* iface) {
51 RTC_DCHECK_RUN_ON(network_thread_);
52 iface ? network_safety_->SetAlive() : network_safety_->SetNotAlive();
53 network_interface_ = iface;
54 UpdateDscp();
55 }
56
GetRtpSendTimeExtnId() const57 int MediaChannel::GetRtpSendTimeExtnId() const {
58 return -1;
59 }
60
SetFrameEncryptor(uint32_t ssrc,rtc::scoped_refptr<FrameEncryptorInterface> frame_encryptor)61 void MediaChannel::SetFrameEncryptor(
62 uint32_t ssrc,
63 rtc::scoped_refptr<FrameEncryptorInterface> frame_encryptor) {
64 // Placeholder should be pure virtual once internal supports it.
65 }
66
SetFrameDecryptor(uint32_t ssrc,rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor)67 void MediaChannel::SetFrameDecryptor(
68 uint32_t ssrc,
69 rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor) {
70 // Placeholder should be pure virtual once internal supports it.
71 }
72
SetVideoCodecSwitchingEnabled(bool enabled)73 void MediaChannel::SetVideoCodecSwitchingEnabled(bool enabled) {}
74
SendPacket(rtc::CopyOnWriteBuffer * packet,const rtc::PacketOptions & options)75 bool MediaChannel::SendPacket(rtc::CopyOnWriteBuffer* packet,
76 const rtc::PacketOptions& options) {
77 return DoSendPacket(packet, false, options);
78 }
79
SendRtcp(rtc::CopyOnWriteBuffer * packet,const rtc::PacketOptions & options)80 bool MediaChannel::SendRtcp(rtc::CopyOnWriteBuffer* packet,
81 const rtc::PacketOptions& options) {
82 return DoSendPacket(packet, true, options);
83 }
84
SetOption(NetworkInterface::SocketType type,rtc::Socket::Option opt,int option)85 int MediaChannel::SetOption(NetworkInterface::SocketType type,
86 rtc::Socket::Option opt,
87 int option) {
88 RTC_DCHECK_RUN_ON(network_thread_);
89 return SetOptionLocked(type, opt, option);
90 }
91
92 // Corresponds to the SDP attribute extmap-allow-mixed, see RFC8285.
93 // Set to true if it's allowed to mix one- and two-byte RTP header extensions
94 // in the same stream. The setter and getter must only be called from
95 // worker_thread.
SetExtmapAllowMixed(bool extmap_allow_mixed)96 void MediaChannel::SetExtmapAllowMixed(bool extmap_allow_mixed) {
97 extmap_allow_mixed_ = extmap_allow_mixed;
98 }
99
ExtmapAllowMixed() const100 bool MediaChannel::ExtmapAllowMixed() const {
101 return extmap_allow_mixed_;
102 }
103
HasNetworkInterface() const104 bool MediaChannel::HasNetworkInterface() const {
105 RTC_DCHECK_RUN_ON(network_thread_);
106 return network_interface_ != nullptr;
107 }
108
SetEncoderToPacketizerFrameTransformer(uint32_t ssrc,rtc::scoped_refptr<FrameTransformerInterface> frame_transformer)109 void MediaChannel::SetEncoderToPacketizerFrameTransformer(
110 uint32_t ssrc,
111 rtc::scoped_refptr<FrameTransformerInterface> frame_transformer) {}
112
SetDepacketizerToDecoderFrameTransformer(uint32_t ssrc,rtc::scoped_refptr<FrameTransformerInterface> frame_transformer)113 void MediaChannel::SetDepacketizerToDecoderFrameTransformer(
114 uint32_t ssrc,
115 rtc::scoped_refptr<FrameTransformerInterface> frame_transformer) {}
116
SetOptionLocked(NetworkInterface::SocketType type,rtc::Socket::Option opt,int option)117 int MediaChannel::SetOptionLocked(NetworkInterface::SocketType type,
118 rtc::Socket::Option opt,
119 int option) {
120 if (!network_interface_)
121 return -1;
122 return network_interface_->SetOption(type, opt, option);
123 }
124
DscpEnabled() const125 bool MediaChannel::DscpEnabled() const {
126 return enable_dscp_;
127 }
128
129 // This is the DSCP value used for both RTP and RTCP channels if DSCP is
130 // enabled. It can be changed at any time via `SetPreferredDscp`.
PreferredDscp() const131 rtc::DiffServCodePoint MediaChannel::PreferredDscp() const {
132 RTC_DCHECK_RUN_ON(network_thread_);
133 return preferred_dscp_;
134 }
135
SetPreferredDscp(rtc::DiffServCodePoint new_dscp)136 void MediaChannel::SetPreferredDscp(rtc::DiffServCodePoint new_dscp) {
137 if (!network_thread_->IsCurrent()) {
138 // This is currently the common path as the derived channel classes
139 // get called on the worker thread. There are still some tests though
140 // that call directly on the network thread.
141 network_thread_->PostTask(SafeTask(
142 network_safety_, [this, new_dscp]() { SetPreferredDscp(new_dscp); }));
143 return;
144 }
145
146 RTC_DCHECK_RUN_ON(network_thread_);
147 if (new_dscp == preferred_dscp_)
148 return;
149
150 preferred_dscp_ = new_dscp;
151 UpdateDscp();
152 }
153
network_safety()154 rtc::scoped_refptr<PendingTaskSafetyFlag> MediaChannel::network_safety() {
155 return network_safety_;
156 }
157
UpdateDscp()158 void MediaChannel::UpdateDscp() {
159 rtc::DiffServCodePoint value =
160 enable_dscp_ ? preferred_dscp_ : rtc::DSCP_DEFAULT;
161 int ret =
162 SetOptionLocked(NetworkInterface::ST_RTP, rtc::Socket::OPT_DSCP, value);
163 if (ret == 0)
164 SetOptionLocked(NetworkInterface::ST_RTCP, rtc::Socket::OPT_DSCP, value);
165 }
166
DoSendPacket(rtc::CopyOnWriteBuffer * packet,bool rtcp,const rtc::PacketOptions & options)167 bool MediaChannel::DoSendPacket(rtc::CopyOnWriteBuffer* packet,
168 bool rtcp,
169 const rtc::PacketOptions& options) {
170 RTC_DCHECK_RUN_ON(network_thread_);
171 if (!network_interface_)
172 return false;
173
174 return (!rtcp) ? network_interface_->SendPacket(packet, options)
175 : network_interface_->SendRtcp(packet, options);
176 }
177
SendRtp(const uint8_t * data,size_t len,const webrtc::PacketOptions & options)178 void MediaChannel::SendRtp(const uint8_t* data,
179 size_t len,
180 const webrtc::PacketOptions& options) {
181 auto send =
182 [this, packet_id = options.packet_id,
183 included_in_feedback = options.included_in_feedback,
184 included_in_allocation = options.included_in_allocation,
185 packet = rtc::CopyOnWriteBuffer(data, len, kMaxRtpPacketLen)]() mutable {
186 rtc::PacketOptions rtc_options;
187 rtc_options.packet_id = packet_id;
188 if (DscpEnabled()) {
189 rtc_options.dscp = PreferredDscp();
190 }
191 rtc_options.info_signaled_after_sent.included_in_feedback =
192 included_in_feedback;
193 rtc_options.info_signaled_after_sent.included_in_allocation =
194 included_in_allocation;
195 SendPacket(&packet, rtc_options);
196 };
197
198 // TODO(bugs.webrtc.org/11993): ModuleRtpRtcpImpl2 and related classes (e.g.
199 // RTCPSender) aren't aware of the network thread and may trigger calls to
200 // this function from different threads. Update those classes to keep
201 // network traffic on the network thread.
202 if (network_thread_->IsCurrent()) {
203 send();
204 } else {
205 network_thread_->PostTask(SafeTask(network_safety_, std::move(send)));
206 }
207 }
208
SendRtcp(const uint8_t * data,size_t len)209 void MediaChannel::SendRtcp(const uint8_t* data, size_t len) {
210 auto send = [this, packet = rtc::CopyOnWriteBuffer(
211 data, len, kMaxRtpPacketLen)]() mutable {
212 rtc::PacketOptions rtc_options;
213 if (DscpEnabled()) {
214 rtc_options.dscp = PreferredDscp();
215 }
216 SendRtcp(&packet, rtc_options);
217 };
218
219 if (network_thread_->IsCurrent()) {
220 send();
221 } else {
222 network_thread_->PostTask(SafeTask(network_safety_, std::move(send)));
223 }
224 }
225
226 MediaSenderInfo::MediaSenderInfo() = default;
227 MediaSenderInfo::~MediaSenderInfo() = default;
228
229 MediaReceiverInfo::MediaReceiverInfo() = default;
230 MediaReceiverInfo::~MediaReceiverInfo() = default;
231
232 VoiceSenderInfo::VoiceSenderInfo() = default;
233 VoiceSenderInfo::~VoiceSenderInfo() = default;
234
235 VoiceReceiverInfo::VoiceReceiverInfo() = default;
236 VoiceReceiverInfo::~VoiceReceiverInfo() = default;
237
238 VideoSenderInfo::VideoSenderInfo() = default;
239 VideoSenderInfo::~VideoSenderInfo() = default;
240
241 VideoReceiverInfo::VideoReceiverInfo() = default;
242 VideoReceiverInfo::~VideoReceiverInfo() = default;
243
244 VoiceMediaInfo::VoiceMediaInfo() = default;
245 VoiceMediaInfo::~VoiceMediaInfo() = default;
246
247 VideoMediaInfo::VideoMediaInfo() = default;
248 VideoMediaInfo::~VideoMediaInfo() = default;
249
250 AudioSendParameters::AudioSendParameters() = default;
251 AudioSendParameters::~AudioSendParameters() = default;
252
ToStringMap() const253 std::map<std::string, std::string> AudioSendParameters::ToStringMap() const {
254 auto params = RtpSendParameters<AudioCodec>::ToStringMap();
255 params["options"] = options.ToString();
256 return params;
257 }
258
media_type() const259 cricket::MediaType VoiceMediaChannel::media_type() const {
260 return cricket::MediaType::MEDIA_TYPE_AUDIO;
261 }
262
263 VideoSendParameters::VideoSendParameters() = default;
264 VideoSendParameters::~VideoSendParameters() = default;
265
ToStringMap() const266 std::map<std::string, std::string> VideoSendParameters::ToStringMap() const {
267 auto params = RtpSendParameters<VideoCodec>::ToStringMap();
268 params["conference_mode"] = (conference_mode ? "yes" : "no");
269 return params;
270 }
271
media_type() const272 cricket::MediaType VideoMediaChannel::media_type() const {
273 return cricket::MediaType::MEDIA_TYPE_VIDEO;
274 }
275
276 } // namespace cricket
277