media_channel_impl.cc (9471B)
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_impl.h" 12 13 #include <cstdint> 14 #include <map> 15 #include <string> 16 #include <utility> 17 18 #include "absl/functional/any_invocable.h" 19 #include "api/array_view.h" 20 #include "api/audio_options.h" 21 #include "api/call/transport.h" 22 #include "api/media_stream_interface.h" 23 #include "api/rtc_error.h" 24 #include "api/rtp_sender_interface.h" 25 #include "api/sequence_checker.h" 26 #include "api/task_queue/pending_task_safety_flag.h" 27 #include "api/task_queue/task_queue_base.h" 28 #include "media/base/media_channel.h" 29 #include "media/base/rtp_utils.h" 30 #include "rtc_base/async_packet_socket.h" 31 #include "rtc_base/checks.h" 32 #include "rtc_base/copy_on_write_buffer.h" 33 #include "rtc_base/dscp.h" 34 #include "rtc_base/socket.h" 35 36 namespace webrtc { 37 38 VideoOptions::VideoOptions() 39 : content_hint(VideoTrackInterface::ContentHint::kNone) {} 40 VideoOptions::~VideoOptions() = default; 41 42 MediaChannelUtil::MediaChannelUtil(TaskQueueBase* network_thread, 43 bool enable_dscp) 44 : transport_(network_thread, enable_dscp) {} 45 46 MediaChannelUtil::~MediaChannelUtil() {} 47 48 void MediaChannelUtil::SetInterface(MediaChannelNetworkInterface* iface) { 49 transport_.SetInterface(iface); 50 } 51 52 int MediaChannelUtil::GetRtpSendTimeExtnId() const { 53 return -1; 54 } 55 56 bool MediaChannelUtil::SendPacket(CopyOnWriteBuffer* packet, 57 const AsyncSocketPacketOptions& options) { 58 return transport_.DoSendPacket(packet, false, options); 59 } 60 61 bool MediaChannelUtil::SendRtcp(CopyOnWriteBuffer* packet, 62 const AsyncSocketPacketOptions& options) { 63 return transport_.DoSendPacket(packet, true, options); 64 } 65 66 int MediaChannelUtil::SetOption(MediaChannelNetworkInterface::SocketType type, 67 Socket::Option opt, 68 int option) { 69 return transport_.SetOption(type, opt, option); 70 } 71 72 // Corresponds to the SDP attribute extmap-allow-mixed, see RFC8285. 73 // Set to true if it's allowed to mix one- and two-byte RTP header extensions 74 // in the same stream. The setter and getter must only be called from 75 // worker_thread. 76 void MediaChannelUtil::SetExtmapAllowMixed(bool extmap_allow_mixed) { 77 extmap_allow_mixed_ = extmap_allow_mixed; 78 } 79 80 bool MediaChannelUtil::ExtmapAllowMixed() const { 81 return extmap_allow_mixed_; 82 } 83 84 bool MediaChannelUtil::HasNetworkInterface() const { 85 return transport_.HasNetworkInterface(); 86 } 87 88 bool MediaChannelUtil::DscpEnabled() const { 89 return transport_.DscpEnabled(); 90 } 91 92 void MediaChannelUtil::SetPreferredDscp(DiffServCodePoint new_dscp) { 93 transport_.SetPreferredDscp(new_dscp); 94 } 95 96 MediaSenderInfo::MediaSenderInfo() = default; 97 MediaSenderInfo::~MediaSenderInfo() = default; 98 99 MediaReceiverInfo::MediaReceiverInfo() = default; 100 MediaReceiverInfo::~MediaReceiverInfo() = default; 101 102 VoiceSenderInfo::VoiceSenderInfo() = default; 103 VoiceSenderInfo::~VoiceSenderInfo() = default; 104 105 VoiceReceiverInfo::VoiceReceiverInfo() = default; 106 VoiceReceiverInfo::~VoiceReceiverInfo() = default; 107 108 VideoSenderInfo::VideoSenderInfo() = default; 109 VideoSenderInfo::~VideoSenderInfo() = default; 110 111 VideoReceiverInfo::VideoReceiverInfo() = default; 112 VideoReceiverInfo::~VideoReceiverInfo() = default; 113 114 VoiceMediaInfo::VoiceMediaInfo() = default; 115 VoiceMediaInfo::~VoiceMediaInfo() = default; 116 117 VideoMediaInfo::VideoMediaInfo() = default; 118 VideoMediaInfo::~VideoMediaInfo() = default; 119 120 VideoMediaSendInfo::VideoMediaSendInfo() = default; 121 VideoMediaSendInfo::~VideoMediaSendInfo() = default; 122 123 VoiceMediaSendInfo::VoiceMediaSendInfo() = default; 124 VoiceMediaSendInfo::~VoiceMediaSendInfo() = default; 125 126 VideoMediaReceiveInfo::VideoMediaReceiveInfo() = default; 127 VideoMediaReceiveInfo::~VideoMediaReceiveInfo() = default; 128 129 VoiceMediaReceiveInfo::VoiceMediaReceiveInfo() = default; 130 VoiceMediaReceiveInfo::~VoiceMediaReceiveInfo() = default; 131 132 AudioSenderParameter::AudioSenderParameter() = default; 133 AudioSenderParameter::~AudioSenderParameter() = default; 134 135 std::map<std::string, std::string> AudioSenderParameter::ToStringMap() const { 136 auto params = SenderParameters::ToStringMap(); 137 params["options"] = options.ToString(); 138 return params; 139 } 140 141 VideoSenderParameters::VideoSenderParameters() = default; 142 VideoSenderParameters::~VideoSenderParameters() = default; 143 144 std::map<std::string, std::string> VideoSenderParameters::ToStringMap() const { 145 auto params = SenderParameters::ToStringMap(); 146 params["conference_mode"] = (conference_mode ? "yes" : "no"); 147 return params; 148 } 149 150 // --------------------- MediaChannelUtil::TransportForMediaChannels ----- 151 152 MediaChannelUtil::TransportForMediaChannels::TransportForMediaChannels( 153 TaskQueueBase* network_thread, 154 bool enable_dscp) 155 : network_safety_(PendingTaskSafetyFlag::CreateDetachedInactive()), 156 network_thread_(network_thread), 157 158 enable_dscp_(enable_dscp) {} 159 160 MediaChannelUtil::TransportForMediaChannels::~TransportForMediaChannels() { 161 RTC_DCHECK(!network_interface_); 162 } 163 164 AsyncSocketPacketOptions 165 MediaChannelUtil::TransportForMediaChannels::TranslatePacketOptions( 166 const PacketOptions& options) { 167 AsyncSocketPacketOptions rtc_options; 168 rtc_options.packet_id = options.packet_id; 169 if (DscpEnabled()) { 170 rtc_options.dscp = PreferredDscp(); 171 } 172 rtc_options.info_signaled_after_sent.included_in_feedback = 173 options.included_in_feedback; 174 rtc_options.info_signaled_after_sent.included_in_allocation = 175 options.included_in_allocation; 176 rtc_options.info_signaled_after_sent.is_media = options.is_media; 177 rtc_options.ect_1 = options.send_as_ect1; 178 rtc_options.batchable = options.batchable; 179 rtc_options.last_packet_in_batch = options.last_packet_in_batch; 180 return rtc_options; 181 } 182 183 bool MediaChannelUtil::TransportForMediaChannels::SendRtcp( 184 ArrayView<const uint8_t> packet, 185 const PacketOptions& options) { 186 auto send = [this, packet = CopyOnWriteBuffer(packet, kMaxRtpPacketLen), 187 options]() mutable { 188 DoSendPacket(&packet, true, TranslatePacketOptions(options)); 189 }; 190 191 if (network_thread_->IsCurrent()) { 192 send(); 193 } else { 194 network_thread_->PostTask(SafeTask(network_safety_, std::move(send))); 195 } 196 return true; 197 } 198 199 bool MediaChannelUtil::TransportForMediaChannels::SendRtp( 200 ArrayView<const uint8_t> packet, 201 const PacketOptions& options) { 202 auto send = [this, packet = CopyOnWriteBuffer(packet, kMaxRtpPacketLen), 203 options]() mutable { 204 DoSendPacket(&packet, false, TranslatePacketOptions(options)); 205 }; 206 207 // TODO(bugs.webrtc.org/11993): ModuleRtpRtcpImpl2 and related classes (e.g. 208 // RTCPSender) aren't aware of the network thread and may trigger calls to 209 // this function from different threads. Update those classes to keep 210 // network traffic on the network thread. 211 if (network_thread_->IsCurrent()) { 212 send(); 213 } else { 214 network_thread_->PostTask(SafeTask(network_safety_, std::move(send))); 215 } 216 return true; 217 } 218 219 void MediaChannelUtil::TransportForMediaChannels::SetInterface( 220 MediaChannelNetworkInterface* iface) { 221 RTC_DCHECK_RUN_ON(network_thread_); 222 iface ? network_safety_->SetAlive() : network_safety_->SetNotAlive(); 223 network_interface_ = iface; 224 UpdateDscp(); 225 } 226 227 void MediaChannelUtil::TransportForMediaChannels::UpdateDscp() { 228 DiffServCodePoint value = enable_dscp_ ? preferred_dscp_ : DSCP_DEFAULT; 229 int ret = SetOptionLocked(MediaChannelNetworkInterface::ST_RTP, 230 Socket::OPT_DSCP, value); 231 if (ret == 0) 232 SetOptionLocked(MediaChannelNetworkInterface::ST_RTCP, Socket::OPT_DSCP, 233 value); 234 } 235 236 bool MediaChannelUtil::TransportForMediaChannels::DoSendPacket( 237 CopyOnWriteBuffer* packet, 238 bool rtcp, 239 const AsyncSocketPacketOptions& options) { 240 RTC_DCHECK_RUN_ON(network_thread_); 241 if (!network_interface_) 242 return false; 243 244 return (!rtcp) ? network_interface_->SendPacket(packet, options) 245 : network_interface_->SendRtcp(packet, options); 246 } 247 248 int MediaChannelUtil::TransportForMediaChannels::SetOption( 249 MediaChannelNetworkInterface::SocketType type, 250 Socket::Option opt, 251 int option) { 252 RTC_DCHECK_RUN_ON(network_thread_); 253 return SetOptionLocked(type, opt, option); 254 } 255 256 int MediaChannelUtil::TransportForMediaChannels::SetOptionLocked( 257 MediaChannelNetworkInterface::SocketType type, 258 Socket::Option opt, 259 int option) { 260 if (!network_interface_) 261 return -1; 262 return network_interface_->SetOption(type, opt, option); 263 } 264 265 void MediaChannelUtil::TransportForMediaChannels::SetPreferredDscp( 266 DiffServCodePoint new_dscp) { 267 if (!network_thread_->IsCurrent()) { 268 // This is currently the common path as the derived channel classes 269 // get called on the worker thread. There are still some tests though 270 // that call directly on the network thread. 271 network_thread_->PostTask(SafeTask( 272 network_safety_, [this, new_dscp]() { SetPreferredDscp(new_dscp); })); 273 return; 274 } 275 276 RTC_DCHECK_RUN_ON(network_thread_); 277 if (new_dscp == preferred_dscp_) 278 return; 279 280 preferred_dscp_ = new_dscp; 281 UpdateDscp(); 282 } 283 284 } // namespace webrtc