• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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