| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright (c) 2013 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 <string.h> | |
| 12 | |
| 13 #include <map> | |
| 14 #include <vector> | |
| 15 | |
| 16 #include "webrtc/base/checks.h" | |
| 17 #include "webrtc/base/scoped_ptr.h" | |
| 18 #include "webrtc/base/thread_annotations.h" | |
| 19 #include "webrtc/call.h" | |
| 20 #include "webrtc/common.h" | |
| 21 #include "webrtc/config.h" | |
| 22 #include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h" | |
| 23 #include "webrtc/modules/rtp_rtcp/source/byte_io.h" | |
| 24 #include "webrtc/modules/utility/interface/process_thread.h" | |
| 25 #include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h" | |
| 26 #include "webrtc/modules/video_coding/codecs/vp9/include/vp9.h" | |
| 27 #include "webrtc/modules/video_render/include/video_render.h" | |
| 28 #include "webrtc/system_wrappers/interface/cpu_info.h" | |
| 29 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" | |
| 30 #include "webrtc/system_wrappers/interface/logging.h" | |
| 31 #include "webrtc/system_wrappers/interface/rw_lock_wrapper.h" | |
| 32 #include "webrtc/system_wrappers/interface/trace.h" | |
| 33 #include "webrtc/system_wrappers/interface/trace_event.h" | |
| 34 #include "webrtc/video/audio_receive_stream.h" | |
| 35 #include "webrtc/video/rtc_event_log.h" | |
| 36 #include "webrtc/video/video_receive_stream.h" | |
| 37 #include "webrtc/video/video_send_stream.h" | |
| 38 #include "webrtc/voice_engine/include/voe_codec.h" | |
| 39 | |
| 40 namespace webrtc { | |
| 41 | |
| 42 const int Call::Config::kDefaultStartBitrateBps = 300000; | |
| 43 | |
| 44 namespace internal { | |
| 45 | |
| 46 class Call : public webrtc::Call, public PacketReceiver { | |
| 47 public: | |
| 48 explicit Call(const Call::Config& config); | |
| 49 virtual ~Call(); | |
| 50 | |
| 51 PacketReceiver* Receiver() override; | |
| 52 | |
| 53 webrtc::AudioSendStream* CreateAudioSendStream( | |
| 54 const webrtc::AudioSendStream::Config& config) override; | |
| 55 void DestroyAudioSendStream(webrtc::AudioSendStream* send_stream) override; | |
| 56 | |
| 57 webrtc::AudioReceiveStream* CreateAudioReceiveStream( | |
| 58 const webrtc::AudioReceiveStream::Config& config) override; | |
| 59 void DestroyAudioReceiveStream( | |
| 60 webrtc::AudioReceiveStream* receive_stream) override; | |
| 61 | |
| 62 webrtc::VideoSendStream* CreateVideoSendStream( | |
| 63 const webrtc::VideoSendStream::Config& config, | |
| 64 const VideoEncoderConfig& encoder_config) override; | |
| 65 void DestroyVideoSendStream(webrtc::VideoSendStream* send_stream) override; | |
| 66 | |
| 67 webrtc::VideoReceiveStream* CreateVideoReceiveStream( | |
| 68 const webrtc::VideoReceiveStream::Config& config) override; | |
| 69 void DestroyVideoReceiveStream( | |
| 70 webrtc::VideoReceiveStream* receive_stream) override; | |
| 71 | |
| 72 Stats GetStats() const override; | |
| 73 | |
| 74 DeliveryStatus DeliverPacket(MediaType media_type, | |
| 75 const uint8_t* packet, | |
| 76 size_t length, | |
| 77 const PacketTime& packet_time) override; | |
| 78 | |
| 79 void SetBitrateConfig( | |
| 80 const webrtc::Call::Config::BitrateConfig& bitrate_config) override; | |
| 81 void SignalNetworkState(NetworkState state) override; | |
| 82 | |
| 83 private: | |
| 84 DeliveryStatus DeliverRtcp(MediaType media_type, const uint8_t* packet, | |
| 85 size_t length); | |
| 86 DeliveryStatus DeliverRtp(MediaType media_type, | |
| 87 const uint8_t* packet, | |
| 88 size_t length, | |
| 89 const PacketTime& packet_time); | |
| 90 | |
| 91 void SetBitrateControllerConfig( | |
| 92 const webrtc::Call::Config::BitrateConfig& bitrate_config); | |
| 93 | |
| 94 void ConfigureSync(const std::string& sync_group) | |
| 95 EXCLUSIVE_LOCKS_REQUIRED(receive_crit_); | |
| 96 | |
| 97 const int num_cpu_cores_; | |
| 98 const rtc::scoped_ptr<ProcessThread> module_process_thread_; | |
| 99 const rtc::scoped_ptr<ChannelGroup> channel_group_; | |
| 100 volatile int next_channel_id_; | |
| 101 Call::Config config_; | |
| 102 | |
| 103 // Needs to be held while write-locking |receive_crit_| or |send_crit_|. This | |
| 104 // ensures that we have a consistent network state signalled to all senders | |
| 105 // and receivers. | |
| 106 rtc::CriticalSection network_enabled_crit_; | |
| 107 bool network_enabled_ GUARDED_BY(network_enabled_crit_); | |
| 108 | |
| 109 rtc::scoped_ptr<RWLockWrapper> receive_crit_; | |
| 110 std::map<uint32_t, AudioReceiveStream*> audio_receive_ssrcs_ | |
| 111 GUARDED_BY(receive_crit_); | |
| 112 std::map<uint32_t, VideoReceiveStream*> video_receive_ssrcs_ | |
| 113 GUARDED_BY(receive_crit_); | |
| 114 std::set<VideoReceiveStream*> video_receive_streams_ | |
| 115 GUARDED_BY(receive_crit_); | |
| 116 std::map<std::string, AudioReceiveStream*> sync_stream_mapping_ | |
| 117 GUARDED_BY(receive_crit_); | |
| 118 | |
| 119 rtc::scoped_ptr<RWLockWrapper> send_crit_; | |
| 120 std::map<uint32_t, VideoSendStream*> video_send_ssrcs_ GUARDED_BY(send_crit_); | |
| 121 std::set<VideoSendStream*> video_send_streams_ GUARDED_BY(send_crit_); | |
| 122 | |
| 123 VideoSendStream::RtpStateMap suspended_video_send_ssrcs_; | |
| 124 | |
| 125 RtcEventLog* event_log_; | |
| 126 | |
| 127 RTC_DISALLOW_COPY_AND_ASSIGN(Call); | |
| 128 }; | |
| 129 } // namespace internal | |
| 130 | |
| 131 Call* Call::Create(const Call::Config& config) { | |
| 132 return new internal::Call(config); | |
| 133 } | |
| 134 | |
| 135 namespace internal { | |
| 136 | |
| 137 Call::Call(const Call::Config& config) | |
| 138 : num_cpu_cores_(CpuInfo::DetectNumberOfCores()), | |
| 139 module_process_thread_(ProcessThread::Create("ModuleProcessThread")), | |
| 140 channel_group_(new ChannelGroup(module_process_thread_.get())), | |
| 141 next_channel_id_(0), | |
| 142 config_(config), | |
| 143 network_enabled_(true), | |
| 144 receive_crit_(RWLockWrapper::CreateRWLock()), | |
| 145 send_crit_(RWLockWrapper::CreateRWLock()), | |
| 146 event_log_(nullptr) { | |
| 147 RTC_DCHECK_GE(config.bitrate_config.min_bitrate_bps, 0); | |
| 148 RTC_DCHECK_GE(config.bitrate_config.start_bitrate_bps, | |
| 149 config.bitrate_config.min_bitrate_bps); | |
| 150 if (config.bitrate_config.max_bitrate_bps != -1) { | |
| 151 RTC_DCHECK_GE(config.bitrate_config.max_bitrate_bps, | |
| 152 config.bitrate_config.start_bitrate_bps); | |
| 153 } | |
| 154 if (config.voice_engine) { | |
| 155 VoECodec* voe_codec = VoECodec::GetInterface(config.voice_engine); | |
| 156 if (voe_codec) { | |
| 157 event_log_ = voe_codec->GetEventLog(); | |
| 158 voe_codec->Release(); | |
| 159 } | |
| 160 } | |
| 161 | |
| 162 Trace::CreateTrace(); | |
| 163 module_process_thread_->Start(); | |
| 164 | |
| 165 SetBitrateControllerConfig(config_.bitrate_config); | |
| 166 } | |
| 167 | |
| 168 Call::~Call() { | |
| 169 RTC_CHECK_EQ(0u, video_send_ssrcs_.size()); | |
| 170 RTC_CHECK_EQ(0u, video_send_streams_.size()); | |
| 171 RTC_CHECK_EQ(0u, audio_receive_ssrcs_.size()); | |
| 172 RTC_CHECK_EQ(0u, video_receive_ssrcs_.size()); | |
| 173 RTC_CHECK_EQ(0u, video_receive_streams_.size()); | |
| 174 | |
| 175 module_process_thread_->Stop(); | |
| 176 Trace::ReturnTrace(); | |
| 177 } | |
| 178 | |
| 179 PacketReceiver* Call::Receiver() { return this; } | |
| 180 | |
| 181 webrtc::AudioSendStream* Call::CreateAudioSendStream( | |
| 182 const webrtc::AudioSendStream::Config& config) { | |
| 183 return nullptr; | |
| 184 } | |
| 185 | |
| 186 void Call::DestroyAudioSendStream(webrtc::AudioSendStream* send_stream) { | |
| 187 } | |
| 188 | |
| 189 webrtc::AudioReceiveStream* Call::CreateAudioReceiveStream( | |
| 190 const webrtc::AudioReceiveStream::Config& config) { | |
| 191 TRACE_EVENT0("webrtc", "Call::CreateAudioReceiveStream"); | |
| 192 LOG(LS_INFO) << "CreateAudioReceiveStream: " << config.ToString(); | |
| 193 AudioReceiveStream* receive_stream = new AudioReceiveStream( | |
| 194 channel_group_->GetRemoteBitrateEstimator(), config); | |
| 195 { | |
| 196 WriteLockScoped write_lock(*receive_crit_); | |
| 197 RTC_DCHECK(audio_receive_ssrcs_.find(config.rtp.remote_ssrc) == | |
| 198 audio_receive_ssrcs_.end()); | |
| 199 audio_receive_ssrcs_[config.rtp.remote_ssrc] = receive_stream; | |
| 200 ConfigureSync(config.sync_group); | |
| 201 } | |
| 202 return receive_stream; | |
| 203 } | |
| 204 | |
| 205 void Call::DestroyAudioReceiveStream( | |
| 206 webrtc::AudioReceiveStream* receive_stream) { | |
| 207 TRACE_EVENT0("webrtc", "Call::DestroyAudioReceiveStream"); | |
| 208 RTC_DCHECK(receive_stream != nullptr); | |
| 209 AudioReceiveStream* audio_receive_stream = | |
| 210 static_cast<AudioReceiveStream*>(receive_stream); | |
| 211 { | |
| 212 WriteLockScoped write_lock(*receive_crit_); | |
| 213 size_t num_deleted = audio_receive_ssrcs_.erase( | |
| 214 audio_receive_stream->config().rtp.remote_ssrc); | |
| 215 RTC_DCHECK(num_deleted == 1); | |
| 216 const std::string& sync_group = audio_receive_stream->config().sync_group; | |
| 217 const auto it = sync_stream_mapping_.find(sync_group); | |
| 218 if (it != sync_stream_mapping_.end() && | |
| 219 it->second == audio_receive_stream) { | |
| 220 sync_stream_mapping_.erase(it); | |
| 221 ConfigureSync(sync_group); | |
| 222 } | |
| 223 } | |
| 224 delete audio_receive_stream; | |
| 225 } | |
| 226 | |
| 227 webrtc::VideoSendStream* Call::CreateVideoSendStream( | |
| 228 const webrtc::VideoSendStream::Config& config, | |
| 229 const VideoEncoderConfig& encoder_config) { | |
| 230 TRACE_EVENT0("webrtc", "Call::CreateVideoSendStream"); | |
| 231 LOG(LS_INFO) << "CreateVideoSendStream: " << config.ToString(); | |
| 232 RTC_DCHECK(!config.rtp.ssrcs.empty()); | |
| 233 | |
| 234 // TODO(mflodman): Base the start bitrate on a current bandwidth estimate, if | |
| 235 // the call has already started. | |
| 236 VideoSendStream* send_stream = new VideoSendStream(num_cpu_cores_, | |
| 237 module_process_thread_.get(), channel_group_.get(), | |
| 238 rtc::AtomicOps::Increment(&next_channel_id_), config, encoder_config, | |
| 239 suspended_video_send_ssrcs_); | |
| 240 | |
| 241 // This needs to be taken before send_crit_ as both locks need to be held | |
| 242 // while changing network state. | |
| 243 rtc::CritScope lock(&network_enabled_crit_); | |
| 244 WriteLockScoped write_lock(*send_crit_); | |
| 245 for (uint32_t ssrc : config.rtp.ssrcs) { | |
| 246 RTC_DCHECK(video_send_ssrcs_.find(ssrc) == video_send_ssrcs_.end()); | |
| 247 video_send_ssrcs_[ssrc] = send_stream; | |
| 248 } | |
| 249 video_send_streams_.insert(send_stream); | |
| 250 | |
| 251 if (event_log_) | |
| 252 event_log_->LogVideoSendStreamConfig(config); | |
| 253 | |
| 254 if (!network_enabled_) | |
| 255 send_stream->SignalNetworkState(kNetworkDown); | |
| 256 return send_stream; | |
| 257 } | |
| 258 | |
| 259 void Call::DestroyVideoSendStream(webrtc::VideoSendStream* send_stream) { | |
| 260 TRACE_EVENT0("webrtc", "Call::DestroyVideoSendStream"); | |
| 261 RTC_DCHECK(send_stream != nullptr); | |
| 262 | |
| 263 send_stream->Stop(); | |
| 264 | |
| 265 VideoSendStream* send_stream_impl = nullptr; | |
| 266 { | |
| 267 WriteLockScoped write_lock(*send_crit_); | |
| 268 auto it = video_send_ssrcs_.begin(); | |
| 269 while (it != video_send_ssrcs_.end()) { | |
| 270 if (it->second == static_cast<VideoSendStream*>(send_stream)) { | |
| 271 send_stream_impl = it->second; | |
| 272 video_send_ssrcs_.erase(it++); | |
| 273 } else { | |
| 274 ++it; | |
| 275 } | |
| 276 } | |
| 277 video_send_streams_.erase(send_stream_impl); | |
| 278 } | |
| 279 RTC_CHECK(send_stream_impl != nullptr); | |
| 280 | |
| 281 VideoSendStream::RtpStateMap rtp_state = send_stream_impl->GetRtpStates(); | |
| 282 | |
| 283 for (VideoSendStream::RtpStateMap::iterator it = rtp_state.begin(); | |
| 284 it != rtp_state.end(); | |
| 285 ++it) { | |
| 286 suspended_video_send_ssrcs_[it->first] = it->second; | |
| 287 } | |
| 288 | |
| 289 delete send_stream_impl; | |
| 290 } | |
| 291 | |
| 292 webrtc::VideoReceiveStream* Call::CreateVideoReceiveStream( | |
| 293 const webrtc::VideoReceiveStream::Config& config) { | |
| 294 TRACE_EVENT0("webrtc", "Call::CreateVideoReceiveStream"); | |
| 295 LOG(LS_INFO) << "CreateVideoReceiveStream: " << config.ToString(); | |
| 296 VideoReceiveStream* receive_stream = new VideoReceiveStream( | |
| 297 num_cpu_cores_, channel_group_.get(), | |
| 298 rtc::AtomicOps::Increment(&next_channel_id_), config, | |
| 299 config_.voice_engine); | |
| 300 | |
| 301 // This needs to be taken before receive_crit_ as both locks need to be held | |
| 302 // while changing network state. | |
| 303 rtc::CritScope lock(&network_enabled_crit_); | |
| 304 WriteLockScoped write_lock(*receive_crit_); | |
| 305 RTC_DCHECK(video_receive_ssrcs_.find(config.rtp.remote_ssrc) == | |
| 306 video_receive_ssrcs_.end()); | |
| 307 video_receive_ssrcs_[config.rtp.remote_ssrc] = receive_stream; | |
| 308 // TODO(pbos): Configure different RTX payloads per receive payload. | |
| 309 VideoReceiveStream::Config::Rtp::RtxMap::const_iterator it = | |
| 310 config.rtp.rtx.begin(); | |
| 311 if (it != config.rtp.rtx.end()) | |
| 312 video_receive_ssrcs_[it->second.ssrc] = receive_stream; | |
| 313 video_receive_streams_.insert(receive_stream); | |
| 314 | |
| 315 ConfigureSync(config.sync_group); | |
| 316 | |
| 317 if (!network_enabled_) | |
| 318 receive_stream->SignalNetworkState(kNetworkDown); | |
| 319 | |
| 320 if (event_log_) | |
| 321 event_log_->LogVideoReceiveStreamConfig(config); | |
| 322 | |
| 323 return receive_stream; | |
| 324 } | |
| 325 | |
| 326 void Call::DestroyVideoReceiveStream( | |
| 327 webrtc::VideoReceiveStream* receive_stream) { | |
| 328 TRACE_EVENT0("webrtc", "Call::DestroyVideoReceiveStream"); | |
| 329 RTC_DCHECK(receive_stream != nullptr); | |
| 330 VideoReceiveStream* receive_stream_impl = nullptr; | |
| 331 { | |
| 332 WriteLockScoped write_lock(*receive_crit_); | |
| 333 // Remove all ssrcs pointing to a receive stream. As RTX retransmits on a | |
| 334 // separate SSRC there can be either one or two. | |
| 335 auto it = video_receive_ssrcs_.begin(); | |
| 336 while (it != video_receive_ssrcs_.end()) { | |
| 337 if (it->second == static_cast<VideoReceiveStream*>(receive_stream)) { | |
| 338 if (receive_stream_impl != nullptr) | |
| 339 RTC_DCHECK(receive_stream_impl == it->second); | |
| 340 receive_stream_impl = it->second; | |
| 341 video_receive_ssrcs_.erase(it++); | |
| 342 } else { | |
| 343 ++it; | |
| 344 } | |
| 345 } | |
| 346 video_receive_streams_.erase(receive_stream_impl); | |
| 347 RTC_CHECK(receive_stream_impl != nullptr); | |
| 348 ConfigureSync(receive_stream_impl->config().sync_group); | |
| 349 } | |
| 350 delete receive_stream_impl; | |
| 351 } | |
| 352 | |
| 353 Call::Stats Call::GetStats() const { | |
| 354 Stats stats; | |
| 355 // Fetch available send/receive bitrates. | |
| 356 uint32_t send_bandwidth = 0; | |
| 357 channel_group_->GetBitrateController()->AvailableBandwidth(&send_bandwidth); | |
| 358 std::vector<unsigned int> ssrcs; | |
| 359 uint32_t recv_bandwidth = 0; | |
| 360 channel_group_->GetRemoteBitrateEstimator()->LatestEstimate(&ssrcs, | |
| 361 &recv_bandwidth); | |
| 362 stats.send_bandwidth_bps = send_bandwidth; | |
| 363 stats.recv_bandwidth_bps = recv_bandwidth; | |
| 364 stats.pacer_delay_ms = channel_group_->GetPacerQueuingDelayMs(); | |
| 365 { | |
| 366 ReadLockScoped read_lock(*send_crit_); | |
| 367 for (const auto& kv : video_send_ssrcs_) { | |
| 368 int rtt_ms = kv.second->GetRtt(); | |
| 369 if (rtt_ms > 0) | |
| 370 stats.rtt_ms = rtt_ms; | |
| 371 } | |
| 372 } | |
| 373 return stats; | |
| 374 } | |
| 375 | |
| 376 void Call::SetBitrateConfig( | |
| 377 const webrtc::Call::Config::BitrateConfig& bitrate_config) { | |
| 378 TRACE_EVENT0("webrtc", "Call::SetBitrateConfig"); | |
| 379 RTC_DCHECK_GE(bitrate_config.min_bitrate_bps, 0); | |
| 380 if (bitrate_config.max_bitrate_bps != -1) | |
| 381 RTC_DCHECK_GT(bitrate_config.max_bitrate_bps, 0); | |
| 382 if (config_.bitrate_config.min_bitrate_bps == | |
| 383 bitrate_config.min_bitrate_bps && | |
| 384 (bitrate_config.start_bitrate_bps <= 0 || | |
| 385 config_.bitrate_config.start_bitrate_bps == | |
| 386 bitrate_config.start_bitrate_bps) && | |
| 387 config_.bitrate_config.max_bitrate_bps == | |
| 388 bitrate_config.max_bitrate_bps) { | |
| 389 // Nothing new to set, early abort to avoid encoder reconfigurations. | |
| 390 return; | |
| 391 } | |
| 392 config_.bitrate_config = bitrate_config; | |
| 393 SetBitrateControllerConfig(bitrate_config); | |
| 394 } | |
| 395 | |
| 396 void Call::SetBitrateControllerConfig( | |
| 397 const webrtc::Call::Config::BitrateConfig& bitrate_config) { | |
| 398 BitrateController* bitrate_controller = | |
| 399 channel_group_->GetBitrateController(); | |
| 400 if (bitrate_config.start_bitrate_bps > 0) | |
| 401 bitrate_controller->SetStartBitrate(bitrate_config.start_bitrate_bps); | |
| 402 bitrate_controller->SetMinMaxBitrate(bitrate_config.min_bitrate_bps, | |
| 403 bitrate_config.max_bitrate_bps); | |
| 404 } | |
| 405 | |
| 406 void Call::SignalNetworkState(NetworkState state) { | |
| 407 // Take crit for entire function, it needs to be held while updating streams | |
| 408 // to guarantee a consistent state across streams. | |
| 409 rtc::CritScope lock(&network_enabled_crit_); | |
| 410 network_enabled_ = state == kNetworkUp; | |
| 411 { | |
| 412 ReadLockScoped write_lock(*send_crit_); | |
| 413 for (auto& kv : video_send_ssrcs_) { | |
| 414 kv.second->SignalNetworkState(state); | |
| 415 } | |
| 416 } | |
| 417 { | |
| 418 ReadLockScoped write_lock(*receive_crit_); | |
| 419 for (auto& kv : video_receive_ssrcs_) { | |
| 420 kv.second->SignalNetworkState(state); | |
| 421 } | |
| 422 } | |
| 423 } | |
| 424 | |
| 425 void Call::ConfigureSync(const std::string& sync_group) { | |
| 426 // Set sync only if there was no previous one. | |
| 427 if (config_.voice_engine == nullptr || sync_group.empty()) | |
| 428 return; | |
| 429 | |
| 430 AudioReceiveStream* sync_audio_stream = nullptr; | |
| 431 // Find existing audio stream. | |
| 432 const auto it = sync_stream_mapping_.find(sync_group); | |
| 433 if (it != sync_stream_mapping_.end()) { | |
| 434 sync_audio_stream = it->second; | |
| 435 } else { | |
| 436 // No configured audio stream, see if we can find one. | |
| 437 for (const auto& kv : audio_receive_ssrcs_) { | |
| 438 if (kv.second->config().sync_group == sync_group) { | |
| 439 if (sync_audio_stream != nullptr) { | |
| 440 LOG(LS_WARNING) << "Attempting to sync more than one audio stream " | |
| 441 "within the same sync group. This is not " | |
| 442 "supported in the current implementation."; | |
| 443 break; | |
| 444 } | |
| 445 sync_audio_stream = kv.second; | |
| 446 } | |
| 447 } | |
| 448 } | |
| 449 if (sync_audio_stream) | |
| 450 sync_stream_mapping_[sync_group] = sync_audio_stream; | |
| 451 size_t num_synced_streams = 0; | |
| 452 for (VideoReceiveStream* video_stream : video_receive_streams_) { | |
| 453 if (video_stream->config().sync_group != sync_group) | |
| 454 continue; | |
| 455 ++num_synced_streams; | |
| 456 if (num_synced_streams > 1) { | |
| 457 // TODO(pbos): Support synchronizing more than one A/V pair. | |
| 458 // https://code.google.com/p/webrtc/issues/detail?id=4762 | |
| 459 LOG(LS_WARNING) << "Attempting to sync more than one audio/video pair " | |
| 460 "within the same sync group. This is not supported in " | |
| 461 "the current implementation."; | |
| 462 } | |
| 463 // Only sync the first A/V pair within this sync group. | |
| 464 if (sync_audio_stream != nullptr && num_synced_streams == 1) { | |
| 465 video_stream->SetSyncChannel(config_.voice_engine, | |
| 466 sync_audio_stream->config().voe_channel_id); | |
| 467 } else { | |
| 468 video_stream->SetSyncChannel(config_.voice_engine, -1); | |
| 469 } | |
| 470 } | |
| 471 } | |
| 472 | |
| 473 PacketReceiver::DeliveryStatus Call::DeliverRtcp(MediaType media_type, | |
| 474 const uint8_t* packet, | |
| 475 size_t length) { | |
| 476 // TODO(pbos): Figure out what channel needs it actually. | |
| 477 // Do NOT broadcast! Also make sure it's a valid packet. | |
| 478 // Return DELIVERY_UNKNOWN_SSRC if it can be determined that | |
| 479 // there's no receiver of the packet. | |
| 480 bool rtcp_delivered = false; | |
| 481 if (media_type == MediaType::ANY || media_type == MediaType::VIDEO) { | |
| 482 ReadLockScoped read_lock(*receive_crit_); | |
| 483 for (VideoReceiveStream* stream : video_receive_streams_) { | |
| 484 if (stream->DeliverRtcp(packet, length)) { | |
| 485 rtcp_delivered = true; | |
| 486 if (event_log_) | |
| 487 event_log_->LogRtcpPacket(true, media_type, packet, length); | |
| 488 } | |
| 489 } | |
| 490 } | |
| 491 if (media_type == MediaType::ANY || media_type == MediaType::VIDEO) { | |
| 492 ReadLockScoped read_lock(*send_crit_); | |
| 493 for (VideoSendStream* stream : video_send_streams_) { | |
| 494 if (stream->DeliverRtcp(packet, length)) { | |
| 495 rtcp_delivered = true; | |
| 496 if (event_log_) | |
| 497 event_log_->LogRtcpPacket(false, media_type, packet, length); | |
| 498 } | |
| 499 } | |
| 500 } | |
| 501 return rtcp_delivered ? DELIVERY_OK : DELIVERY_PACKET_ERROR; | |
| 502 } | |
| 503 | |
| 504 PacketReceiver::DeliveryStatus Call::DeliverRtp(MediaType media_type, | |
| 505 const uint8_t* packet, | |
| 506 size_t length, | |
| 507 const PacketTime& packet_time) { | |
| 508 // Minimum RTP header size. | |
| 509 if (length < 12) | |
| 510 return DELIVERY_PACKET_ERROR; | |
| 511 | |
| 512 uint32_t ssrc = ByteReader<uint32_t>::ReadBigEndian(&packet[8]); | |
| 513 | |
| 514 ReadLockScoped read_lock(*receive_crit_); | |
| 515 if (media_type == MediaType::ANY || media_type == MediaType::AUDIO) { | |
| 516 auto it = audio_receive_ssrcs_.find(ssrc); | |
| 517 if (it != audio_receive_ssrcs_.end()) { | |
| 518 auto status = it->second->DeliverRtp(packet, length, packet_time) | |
| 519 ? DELIVERY_OK | |
| 520 : DELIVERY_PACKET_ERROR; | |
| 521 if (status == DELIVERY_OK && event_log_) | |
| 522 event_log_->LogRtpHeader(true, media_type, packet, length); | |
| 523 return status; | |
| 524 } | |
| 525 } | |
| 526 if (media_type == MediaType::ANY || media_type == MediaType::VIDEO) { | |
| 527 auto it = video_receive_ssrcs_.find(ssrc); | |
| 528 if (it != video_receive_ssrcs_.end()) { | |
| 529 auto status = it->second->DeliverRtp(packet, length, packet_time) | |
| 530 ? DELIVERY_OK | |
| 531 : DELIVERY_PACKET_ERROR; | |
| 532 if (status == DELIVERY_OK && event_log_) | |
| 533 event_log_->LogRtpHeader(true, media_type, packet, length); | |
| 534 return status; | |
| 535 } | |
| 536 } | |
| 537 return DELIVERY_UNKNOWN_SSRC; | |
| 538 } | |
| 539 | |
| 540 PacketReceiver::DeliveryStatus Call::DeliverPacket( | |
| 541 MediaType media_type, | |
| 542 const uint8_t* packet, | |
| 543 size_t length, | |
| 544 const PacketTime& packet_time) { | |
| 545 if (RtpHeaderParser::IsRtcp(packet, length)) | |
| 546 return DeliverRtcp(media_type, packet, length); | |
| 547 | |
| 548 return DeliverRtp(media_type, packet, length, packet_time); | |
| 549 } | |
| 550 | |
| 551 } // namespace internal | |
| 552 } // namespace webrtc | |
| OLD | NEW |