Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 27 #include "webrtc/video/call_stats.h" | 27 #include "webrtc/video/call_stats.h" |
| 28 #include "webrtc/video/video_capture_input.h" | 28 #include "webrtc/video/video_capture_input.h" |
| 29 #include "webrtc/video/vie_remb.h" | 29 #include "webrtc/video/vie_remb.h" |
| 30 #include "webrtc/video_send_stream.h" | 30 #include "webrtc/video_send_stream.h" |
| 31 | 31 |
| 32 namespace webrtc { | 32 namespace webrtc { |
| 33 | 33 |
| 34 class RtcpIntraFrameObserver; | 34 class RtcpIntraFrameObserver; |
| 35 class TransportFeedbackObserver; | 35 class TransportFeedbackObserver; |
| 36 | 36 |
| 37 static const int kMinSendSidePacketHistorySize = 600; | |
| 38 | |
| 39 namespace { | |
| 40 | |
| 41 std::vector<RtpRtcp*> CreateRtpRtcpModules( | |
| 42 Transport* outgoing_transport, | |
| 43 RtcpIntraFrameObserver* intra_frame_callback, | |
| 44 RtcpBandwidthObserver* bandwidth_callback, | |
| 45 TransportFeedbackObserver* transport_feedback_callback, | |
| 46 RtcpRttStats* rtt_stats, | |
| 47 RtpPacketSender* paced_sender, | |
| 48 TransportSequenceNumberAllocator* transport_sequence_number_allocator, | |
| 49 SendStatisticsProxy* stats_proxy, | |
| 50 size_t num_modules) { | |
| 51 RTC_DCHECK_GT(num_modules, 0u); | |
| 52 RtpRtcp::Configuration configuration; | |
| 53 ReceiveStatistics* null_receive_statistics = configuration.receive_statistics; | |
| 54 configuration.audio = false; | |
| 55 configuration.receiver_only = false; | |
| 56 configuration.receive_statistics = null_receive_statistics; | |
| 57 configuration.outgoing_transport = outgoing_transport; | |
| 58 configuration.intra_frame_callback = intra_frame_callback; | |
| 59 configuration.rtt_stats = rtt_stats; | |
| 60 configuration.rtcp_packet_type_counter_observer = stats_proxy; | |
| 61 configuration.paced_sender = paced_sender; | |
| 62 configuration.transport_sequence_number_allocator = | |
| 63 transport_sequence_number_allocator; | |
| 64 configuration.send_bitrate_observer = stats_proxy; | |
| 65 configuration.send_frame_count_observer = stats_proxy; | |
| 66 configuration.send_side_delay_observer = stats_proxy; | |
| 67 configuration.bandwidth_callback = bandwidth_callback; | |
| 68 configuration.transport_feedback_callback = transport_feedback_callback; | |
| 69 | |
| 70 std::vector<RtpRtcp*> modules; | |
| 71 for (size_t i = 0; i < num_modules; ++i) { | |
| 72 RtpRtcp* rtp_rtcp = RtpRtcp::CreateRtpRtcp(configuration); | |
| 73 rtp_rtcp->SetSendingStatus(false); | |
| 74 rtp_rtcp->SetSendingMediaStatus(false); | |
| 75 rtp_rtcp->SetRTCPStatus(RtcpMode::kCompound); | |
| 76 modules.push_back(rtp_rtcp); | |
| 77 } | |
| 78 return modules; | |
| 79 } | |
| 80 | |
| 81 } // namespace | |
| 82 | |
| 37 std::string | 83 std::string |
| 38 VideoSendStream::Config::EncoderSettings::ToString() const { | 84 VideoSendStream::Config::EncoderSettings::ToString() const { |
| 39 std::stringstream ss; | 85 std::stringstream ss; |
| 40 ss << "{payload_name: " << payload_name; | 86 ss << "{payload_name: " << payload_name; |
| 41 ss << ", payload_type: " << payload_type; | 87 ss << ", payload_type: " << payload_type; |
| 42 ss << ", encoder: " << (encoder ? "(VideoEncoder)" : "nullptr"); | 88 ss << ", encoder: " << (encoder ? "(VideoEncoder)" : "nullptr"); |
| 43 ss << '}'; | 89 ss << '}'; |
| 44 return ss.str(); | 90 return ss.str(); |
| 45 } | 91 } |
| 46 | 92 |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 176 remb_(remb), | 222 remb_(remb), |
| 177 encoder_thread_(EncoderThreadFunction, this, "EncoderThread"), | 223 encoder_thread_(EncoderThreadFunction, this, "EncoderThread"), |
| 178 encoder_wakeup_event_(false, false), | 224 encoder_wakeup_event_(false, false), |
| 179 stop_encoder_thread_(0), | 225 stop_encoder_thread_(0), |
| 180 overuse_detector_( | 226 overuse_detector_( |
| 181 Clock::GetRealTimeClock(), | 227 Clock::GetRealTimeClock(), |
| 182 GetCpuOveruseOptions(config.encoder_settings.full_overuse_time), | 228 GetCpuOveruseOptions(config.encoder_settings.full_overuse_time), |
| 183 this, | 229 this, |
| 184 config.post_encode_callback, | 230 config.post_encode_callback, |
| 185 &stats_proxy_), | 231 &stats_proxy_), |
| 186 vie_channel_(config.send_transport, | |
| 187 module_process_thread_, | |
| 188 &payload_router_, | |
| 189 nullptr, | |
| 190 &encoder_feedback_, | |
| 191 congestion_controller_->GetBitrateController() | |
| 192 ->CreateRtcpBandwidthObserver(), | |
| 193 congestion_controller_->GetTransportFeedbackObserver(), | |
| 194 nullptr, | |
| 195 call_stats_->rtcp_rtt_stats(), | |
| 196 congestion_controller_->pacer(), | |
| 197 congestion_controller_->packet_router(), | |
| 198 config_.rtp.ssrcs.size(), | |
| 199 true), | |
| 200 vie_receiver_(vie_channel_.vie_receiver()), | |
| 201 vie_encoder_(num_cpu_cores, | 232 vie_encoder_(num_cpu_cores, |
| 202 config_.rtp.ssrcs, | 233 config_.rtp.ssrcs, |
| 203 module_process_thread_, | 234 module_process_thread_, |
| 204 &stats_proxy_, | 235 &stats_proxy_, |
| 205 config.pre_encode_callback, | 236 config.pre_encode_callback, |
| 206 &overuse_detector_, | 237 &overuse_detector_, |
| 207 congestion_controller_->pacer(), | 238 congestion_controller_->pacer(), |
| 208 &payload_router_), | 239 &payload_router_), |
| 209 vcm_(vie_encoder_.vcm()), | 240 vcm_(vie_encoder_.vcm()), |
| 210 rtp_rtcp_modules_(vie_channel_.rtp_rtcp()), | 241 bandwidth_observer_(congestion_controller_->GetBitrateController() |
| 242 ->CreateRtcpBandwidthObserver()), | |
| 243 rtp_rtcp_modules_(CreateRtpRtcpModules( | |
| 244 config.send_transport, | |
| 245 &encoder_feedback_, | |
| 246 bandwidth_observer_.get(), | |
| 247 congestion_controller_->GetTransportFeedbackObserver(), | |
| 248 call_stats_->rtcp_rtt_stats(), | |
| 249 congestion_controller_->pacer(), | |
| 250 congestion_controller_->packet_router(), | |
| 251 &stats_proxy_, | |
| 252 config_.rtp.ssrcs.size())), | |
| 253 payload_router_(rtp_rtcp_modules_), | |
| 211 input_(&encoder_wakeup_event_, | 254 input_(&encoder_wakeup_event_, |
| 212 config_.local_renderer, | 255 config_.local_renderer, |
| 213 &stats_proxy_, | 256 &stats_proxy_, |
| 214 &overuse_detector_) { | 257 &overuse_detector_) { |
| 215 LOG(LS_INFO) << "VideoSendStream: " << config_.ToString(); | 258 LOG(LS_INFO) << "VideoSendStream: " << config_.ToString(); |
| 216 | 259 |
| 217 RTC_DCHECK(!config_.rtp.ssrcs.empty()); | 260 RTC_DCHECK(!config_.rtp.ssrcs.empty()); |
| 218 RTC_DCHECK(module_process_thread_); | 261 RTC_DCHECK(module_process_thread_); |
| 219 RTC_DCHECK(call_stats_); | 262 RTC_DCHECK(call_stats_); |
| 220 RTC_DCHECK(congestion_controller_); | 263 RTC_DCHECK(congestion_controller_); |
| 221 RTC_DCHECK(remb_); | 264 RTC_DCHECK(remb_); |
| 222 | 265 |
| 223 payload_router_.Init(rtp_rtcp_modules_); | |
| 224 RTC_CHECK(vie_encoder_.Init()); | 266 RTC_CHECK(vie_encoder_.Init()); |
| 225 encoder_feedback_.Init(config_.rtp.ssrcs, &vie_encoder_); | 267 encoder_feedback_.Init(config_.rtp.ssrcs, &vie_encoder_); |
| 226 RTC_CHECK(vie_channel_.Init() == 0); | |
| 227 | 268 |
| 228 vcm_->RegisterProtectionCallback(vie_channel_.vcm_protection_callback()); | 269 // RTP/RTCP initialization. |
| 270 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) { | |
| 271 module_process_thread_->RegisterModule(rtp_rtcp); | |
| 272 congestion_controller_->packet_router()->AddRtpModule(rtp_rtcp); | |
| 273 } | |
| 229 | 274 |
| 230 call_stats_->RegisterStatsObserver(vie_channel_.GetStatsObserver()); | 275 vcm_->RegisterProtectionCallback(this); |
| 276 | |
| 277 // NOW! This only seems to be used receive side from looking at the code?? | |
|
stefan-webrtc
2016/04/12 07:59:10
AFAICT you are right.
perkj_webrtc
2016/04/13 11:43:49
Done.
| |
| 278 // call_stats_->RegisterStatsObserver(vie_channel_.GetStatsObserver()); | |
| 231 | 279 |
| 232 for (size_t i = 0; i < config_.rtp.extensions.size(); ++i) { | 280 for (size_t i = 0; i < config_.rtp.extensions.size(); ++i) { |
| 233 const std::string& extension = config_.rtp.extensions[i].name; | 281 const std::string& extension = config_.rtp.extensions[i].name; |
| 234 int id = config_.rtp.extensions[i].id; | 282 int id = config_.rtp.extensions[i].id; |
| 235 // One-byte-extension local identifiers are in the range 1-14 inclusive. | 283 // One-byte-extension local identifiers are in the range 1-14 inclusive. |
| 236 RTC_DCHECK_GE(id, 1); | 284 RTC_DCHECK_GE(id, 1); |
| 237 RTC_DCHECK_LE(id, 14); | 285 RTC_DCHECK_LE(id, 14); |
| 238 RTC_DCHECK(RtpExtension::IsSupportedForVideo(extension)); | 286 RTC_DCHECK(RtpExtension::IsSupportedForVideo(extension)); |
| 239 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) { | 287 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) { |
| 240 RTC_CHECK_EQ(0, rtp_rtcp->RegisterSendRtpHeaderExtension( | 288 RTC_CHECK_EQ(0, rtp_rtcp->RegisterSendRtpHeaderExtension( |
| 241 StringToRtpExtensionType(extension), id)); | 289 StringToRtpExtensionType(extension), id)); |
| 242 } | 290 } |
| 243 } | 291 } |
| 244 | 292 |
| 245 remb_->AddRembSender(rtp_rtcp_modules_[0]); | 293 remb_->AddRembSender(rtp_rtcp_modules_[0]); |
| 246 rtp_rtcp_modules_[0]->SetREMBStatus(true); | 294 rtp_rtcp_modules_[0]->SetREMBStatus(true); |
| 247 | 295 |
| 248 // Enable NACK, FEC or both. | 296 ConfigureProtection(); |
| 249 const bool enable_protection_nack = config_.rtp.nack.rtp_history_ms > 0; | |
| 250 bool enable_protection_fec = config_.rtp.fec.red_payload_type != -1; | |
| 251 // Payload types without picture ID cannot determine that a stream is complete | |
| 252 // without retransmitting FEC, so using FEC + NACK for H.264 (for instance) is | |
| 253 // a waste of bandwidth since FEC packets still have to be transmitted. Note | |
| 254 // that this is not the case with FLEXFEC. | |
| 255 if (enable_protection_nack && | |
| 256 !PayloadTypeSupportsSkippingFecPackets( | |
| 257 config_.encoder_settings.payload_name)) { | |
| 258 LOG(LS_WARNING) << "Transmitting payload type without picture ID using" | |
| 259 "NACK+FEC is a waste of bandwidth since FEC packets " | |
| 260 "also have to be retransmitted. Disabling FEC."; | |
| 261 enable_protection_fec = false; | |
| 262 } | |
| 263 // TODO(changbin): Should set RTX for RED mapping in RTP sender in future. | |
| 264 vie_channel_.SetProtectionMode(enable_protection_nack, enable_protection_fec, | |
| 265 config_.rtp.fec.red_payload_type, | |
| 266 config_.rtp.fec.ulpfec_payload_type); | |
| 267 vie_encoder_.SetProtectionMethod(enable_protection_nack, | |
| 268 enable_protection_fec); | |
| 269 | |
| 270 ConfigureSsrcs(); | 297 ConfigureSsrcs(); |
| 271 | 298 |
| 272 // TODO(pbos): Should we set CNAME on all RTP modules? | 299 // TODO(pbos): Should we set CNAME on all RTP modules? |
| 273 rtp_rtcp_modules_.front()->SetCNAME(config_.rtp.c_name.c_str()); | 300 rtp_rtcp_modules_.front()->SetCNAME(config_.rtp.c_name.c_str()); |
| 274 // 28 to match packet overhead in ModuleRtpRtcpImpl. | 301 // 28 to match packet overhead in ModuleRtpRtcpImpl. |
| 275 static const size_t kRtpPacketSizeOverhead = 28; | 302 static const size_t kRtpPacketSizeOverhead = 28; |
| 276 RTC_DCHECK_LE(config_.rtp.max_packet_size, 0xFFFFu + kRtpPacketSizeOverhead); | 303 RTC_DCHECK_LE(config_.rtp.max_packet_size, 0xFFFFu + kRtpPacketSizeOverhead); |
| 277 const uint16_t mtu = static_cast<uint16_t>(config_.rtp.max_packet_size + | 304 const uint16_t mtu = static_cast<uint16_t>(config_.rtp.max_packet_size + |
| 278 kRtpPacketSizeOverhead); | 305 kRtpPacketSizeOverhead); |
| 279 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) { | 306 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) { |
| 280 rtp_rtcp->RegisterRtcpStatisticsCallback(&stats_proxy_); | 307 rtp_rtcp->RegisterRtcpStatisticsCallback(&stats_proxy_); |
| 281 rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(&stats_proxy_); | 308 rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(&stats_proxy_); |
| 282 rtp_rtcp->SetMaxTransferUnit(mtu); | 309 rtp_rtcp->SetMaxTransferUnit(mtu); |
| 283 rtp_rtcp->RegisterVideoSendPayload( | 310 rtp_rtcp->RegisterVideoSendPayload( |
| 284 config_.encoder_settings.payload_type, | 311 config_.encoder_settings.payload_type, |
| 285 config_.encoder_settings.payload_name.c_str()); | 312 config_.encoder_settings.payload_name.c_str()); |
| 286 } | 313 } |
| 287 | 314 |
| 288 RTC_DCHECK(config.encoder_settings.encoder); | 315 RTC_DCHECK(config.encoder_settings.encoder); |
| 289 RTC_DCHECK_GE(config.encoder_settings.payload_type, 0); | 316 RTC_DCHECK_GE(config.encoder_settings.payload_type, 0); |
| 290 RTC_DCHECK_LE(config.encoder_settings.payload_type, 127); | 317 RTC_DCHECK_LE(config.encoder_settings.payload_type, 127); |
| 291 RTC_CHECK_EQ(0, vie_encoder_.RegisterExternalEncoder( | 318 RTC_CHECK_EQ(0, vie_encoder_.RegisterExternalEncoder( |
| 292 config.encoder_settings.encoder, | 319 config.encoder_settings.encoder, |
| 293 config.encoder_settings.payload_type, | 320 config.encoder_settings.payload_type, |
| 294 config.encoder_settings.internal_source)); | 321 config.encoder_settings.internal_source)); |
| 295 | 322 |
| 296 ReconfigureVideoEncoder(encoder_config); | 323 ReconfigureVideoEncoder(encoder_config); |
| 297 | 324 |
| 298 vie_channel_.RegisterSendSideDelayObserver(&stats_proxy_); | |
| 299 | |
| 300 if (config_.post_encode_callback) | 325 if (config_.post_encode_callback) |
| 301 vie_encoder_.RegisterPostEncodeImageCallback(&encoded_frame_proxy_); | 326 vie_encoder_.RegisterPostEncodeImageCallback(&encoded_frame_proxy_); |
| 302 | 327 |
| 303 if (config_.suspend_below_min_bitrate) { | 328 if (config_.suspend_below_min_bitrate) { |
| 304 vcm_->SuspendBelowMinBitrate(); | 329 vcm_->SuspendBelowMinBitrate(); |
| 305 bitrate_allocator_->EnforceMinBitrate(false); | 330 bitrate_allocator_->EnforceMinBitrate(false); |
| 306 } | 331 } |
| 307 | 332 |
| 308 vie_channel_.RegisterRtcpPacketTypeCounterObserver(&stats_proxy_); | |
| 309 vie_channel_.RegisterSendBitrateObserver(&stats_proxy_); | |
| 310 vie_channel_.RegisterSendFrameCountObserver(&stats_proxy_); | |
| 311 | |
| 312 module_process_thread_->RegisterModule(&overuse_detector_); | 333 module_process_thread_->RegisterModule(&overuse_detector_); |
| 313 | 334 |
| 314 encoder_thread_.Start(); | 335 encoder_thread_.Start(); |
| 315 encoder_thread_.SetPriority(rtc::kHighPriority); | 336 encoder_thread_.SetPriority(rtc::kHighPriority); |
| 316 } | 337 } |
| 317 | 338 |
| 318 VideoSendStream::~VideoSendStream() { | 339 VideoSendStream::~VideoSendStream() { |
| 319 LOG(LS_INFO) << "~VideoSendStream: " << config_.ToString(); | 340 LOG(LS_INFO) << "~VideoSendStream: " << config_.ToString(); |
| 320 | 341 |
| 321 Stop(); | 342 Stop(); |
| 322 | 343 |
| 323 // Stop the encoder thread permanently. | 344 // Stop the encoder thread permanently. |
| 324 rtc::AtomicOps::ReleaseStore(&stop_encoder_thread_, 1); | 345 rtc::AtomicOps::ReleaseStore(&stop_encoder_thread_, 1); |
| 325 encoder_wakeup_event_.Set(); | 346 encoder_wakeup_event_.Set(); |
| 326 encoder_thread_.Stop(); | 347 encoder_thread_.Stop(); |
| 327 | 348 |
| 328 // This needs to happen after stopping the encoder thread, | 349 // This needs to happen after stopping the encoder thread, |
| 329 // since the encoder thread calls AddObserver. | 350 // since the encoder thread calls AddObserver. |
| 330 bitrate_allocator_->RemoveObserver(this); | 351 bitrate_allocator_->RemoveObserver(this); |
| 331 | 352 |
| 332 module_process_thread_->DeRegisterModule(&overuse_detector_); | 353 module_process_thread_->DeRegisterModule(&overuse_detector_); |
| 333 vie_channel_.RegisterSendFrameCountObserver(nullptr); | |
| 334 vie_channel_.RegisterSendBitrateObserver(nullptr); | |
| 335 vie_channel_.RegisterRtcpPacketTypeCounterObserver(nullptr); | |
| 336 | 354 |
| 337 vie_encoder_.DeRegisterExternalEncoder(config_.encoder_settings.payload_type); | 355 vie_encoder_.DeRegisterExternalEncoder(config_.encoder_settings.payload_type); |
| 338 | 356 |
| 339 call_stats_->DeregisterStatsObserver(vie_channel_.GetStatsObserver()); | 357 // call_stats_->DeregisterStatsObserver(vie_channel_.GetStatsObserver()); |
| 340 rtp_rtcp_modules_[0]->SetREMBStatus(false); | 358 rtp_rtcp_modules_[0]->SetREMBStatus(false); |
| 341 remb_->RemoveRembSender(rtp_rtcp_modules_[0]); | 359 remb_->RemoveRembSender(rtp_rtcp_modules_[0]); |
| 342 | 360 |
| 343 // ViEChannel outlives ViEEncoder so remove encoder from feedback before | 361 // What is this??????? |
|
stefan-webrtc
2016/04/12 07:59:10
Looks incorrect to me, and should be removed since
perkj_webrtc
2016/04/13 11:43:49
Done.
| |
| 344 // destruction. | 362 // congestion_controller_->GetRemoteBitrateEstimator(false)->RemoveStream( |
| 345 encoder_feedback_.TearDown(); | 363 // vie_receiver_->GetRemoteSsrc()); |
| 346 | 364 |
| 347 congestion_controller_->GetRemoteBitrateEstimator(false)->RemoveStream( | 365 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) { |
| 348 vie_receiver_->GetRemoteSsrc()); | 366 congestion_controller_->packet_router()->RemoveRtpModule(rtp_rtcp); |
| 367 module_process_thread_->DeRegisterModule(rtp_rtcp); | |
| 368 delete rtp_rtcp; | |
| 369 } | |
| 349 } | 370 } |
| 350 | 371 |
| 351 VideoCaptureInput* VideoSendStream::Input() { | 372 VideoCaptureInput* VideoSendStream::Input() { |
| 352 return &input_; | 373 return &input_; |
| 353 } | 374 } |
| 354 | 375 |
| 355 void VideoSendStream::Start() { | 376 void VideoSendStream::Start() { |
| 356 if (payload_router_.active()) | 377 if (payload_router_.active()) |
| 357 return; | 378 return; |
| 358 vie_encoder_.Pause(); | 379 vie_encoder_.Pause(); |
| 359 payload_router_.set_active(true); | 380 payload_router_.set_active(true); |
| 360 // Was not already started, trigger a keyframe. | 381 // Was not already started, trigger a keyframe. |
| 361 vie_encoder_.SendKeyFrame(); | 382 vie_encoder_.SendKeyFrame(); |
| 362 vie_encoder_.Restart(); | 383 vie_encoder_.Restart(); |
| 363 vie_receiver_->StartReceive(); | |
| 364 } | 384 } |
| 365 | 385 |
| 366 void VideoSendStream::Stop() { | 386 void VideoSendStream::Stop() { |
| 367 if (!payload_router_.active()) | 387 if (!payload_router_.active()) |
| 368 return; | 388 return; |
| 369 // TODO(pbos): Make sure the encoder stops here. | 389 // TODO(pbos): Make sure the encoder stops here. |
| 370 payload_router_.set_active(false); | 390 payload_router_.set_active(false); |
| 371 vie_receiver_->StopReceive(); | |
| 372 } | 391 } |
| 373 | 392 |
| 374 bool VideoSendStream::EncoderThreadFunction(void* obj) { | 393 bool VideoSendStream::EncoderThreadFunction(void* obj) { |
| 375 static_cast<VideoSendStream*>(obj)->EncoderProcess(); | 394 static_cast<VideoSendStream*>(obj)->EncoderProcess(); |
| 376 // We're done, return false to abort. | 395 // We're done, return false to abort. |
| 377 return false; | 396 return false; |
| 378 } | 397 } |
| 379 | 398 |
| 380 void VideoSendStream::EncoderProcess() { | 399 void VideoSendStream::EncoderProcess() { |
| 381 while (true) { | 400 while (true) { |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 526 video_codec.maxFramerate = streams[0].max_framerate; | 545 video_codec.maxFramerate = streams[0].max_framerate; |
| 527 | 546 |
| 528 video_codec.startBitrate = | 547 video_codec.startBitrate = |
| 529 bitrate_allocator_->AddObserver(this, | 548 bitrate_allocator_->AddObserver(this, |
| 530 video_codec.minBitrate * 1000, | 549 video_codec.minBitrate * 1000, |
| 531 video_codec.maxBitrate * 1000) / 1000; | 550 video_codec.maxBitrate * 1000) / 1000; |
| 532 vie_encoder_.SetEncoder(video_codec, config.min_transmit_bitrate_bps); | 551 vie_encoder_.SetEncoder(video_codec, config.min_transmit_bitrate_bps); |
| 533 } | 552 } |
| 534 | 553 |
| 535 bool VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) { | 554 bool VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) { |
| 536 return vie_receiver_->DeliverRtcp(packet, length); | 555 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) |
| 556 rtp_rtcp->IncomingRtcpPacket(packet, length); | |
| 557 return true; | |
| 537 } | 558 } |
| 538 | 559 |
| 539 VideoSendStream::Stats VideoSendStream::GetStats() { | 560 VideoSendStream::Stats VideoSendStream::GetStats() { |
| 540 return stats_proxy_.GetStats(); | 561 return stats_proxy_.GetStats(); |
| 541 } | 562 } |
| 542 | 563 |
| 543 void VideoSendStream::OveruseDetected() { | 564 void VideoSendStream::OveruseDetected() { |
| 544 if (config_.overuse_callback) | 565 if (config_.overuse_callback) |
| 545 config_.overuse_callback->OnLoadUpdate(LoadObserver::kOveruse); | 566 config_.overuse_callback->OnLoadUpdate(LoadObserver::kOveruse); |
| 546 } | 567 } |
| 547 | 568 |
| 548 void VideoSendStream::NormalUsage() { | 569 void VideoSendStream::NormalUsage() { |
| 549 if (config_.overuse_callback) | 570 if (config_.overuse_callback) |
| 550 config_.overuse_callback->OnLoadUpdate(LoadObserver::kUnderuse); | 571 config_.overuse_callback->OnLoadUpdate(LoadObserver::kUnderuse); |
| 551 } | 572 } |
| 552 | 573 |
| 574 void VideoSendStream::ConfigureProtection() { | |
| 575 // Enable NACK, FEC or both. | |
| 576 const bool enable_protection_nack = config_.rtp.nack.rtp_history_ms > 0; | |
| 577 bool enable_protection_fec = config_.rtp.fec.red_payload_type != -1; | |
| 578 // Payload types without picture ID cannot determine that a stream is complete | |
| 579 // without retransmitting FEC, so using FEC + NACK for H.264 (for instance) is | |
| 580 // a waste of bandwidth since FEC packets still have to be transmitted. Note | |
| 581 // that this is not the case with FLEXFEC. | |
| 582 if (enable_protection_nack && | |
| 583 !PayloadTypeSupportsSkippingFecPackets( | |
| 584 config_.encoder_settings.payload_name)) { | |
| 585 LOG(LS_WARNING) << "Transmitting payload type without picture ID using" | |
| 586 "NACK+FEC is a waste of bandwidth since FEC packets " | |
| 587 "also have to be retransmitted. Disabling FEC."; | |
| 588 enable_protection_fec = false; | |
| 589 } | |
| 590 | |
| 591 // Set to valid uint8_ts to be castable later without signed overflows. | |
| 592 uint8_t payload_type_red = 0; | |
| 593 uint8_t payload_type_fec = 0; | |
| 594 // TODO(changbin): Should set RTX for RED mapping in RTP sender in future. | |
| 595 // Validate payload types. If either RED or FEC payload types are set then | |
| 596 // both should be. If FEC is enabled then they both have to be set. | |
| 597 if (enable_protection_fec || config_.rtp.fec.red_payload_type != -1 || | |
| 598 config_.rtp.fec.ulpfec_payload_type != -1) { | |
| 599 RTC_DCHECK_GE(config_.rtp.fec.red_payload_type, 0); | |
| 600 RTC_DCHECK_GE(config_.rtp.fec.ulpfec_payload_type, 0); | |
| 601 RTC_DCHECK_LE(config_.rtp.fec.red_payload_type, 127); | |
| 602 RTC_DCHECK_LE(config_.rtp.fec.ulpfec_payload_type, 127); | |
| 603 payload_type_red = static_cast<uint8_t>(config_.rtp.fec.red_payload_type); | |
| 604 payload_type_fec = | |
| 605 static_cast<uint8_t>(config_.rtp.fec.ulpfec_payload_type); | |
| 606 } else { | |
| 607 // Payload types unset. | |
| 608 RTC_DCHECK_EQ(config_.rtp.fec.red_payload_type, -1); | |
| 609 RTC_DCHECK_EQ(config_.rtp.fec.ulpfec_payload_type, -1); | |
| 610 } | |
| 611 | |
| 612 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) { | |
| 613 // Set NACK. | |
| 614 rtp_rtcp->SetStorePacketsStatus( | |
| 615 enable_protection_nack || congestion_controller_->pacer(), | |
| 616 kMinSendSidePacketHistorySize); | |
| 617 // Set FEC. | |
| 618 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) { | |
| 619 rtp_rtcp->SetGenericFECStatus(enable_protection_fec, payload_type_red, | |
| 620 payload_type_fec); | |
| 621 } | |
| 622 } | |
| 623 | |
| 624 vie_encoder_.SetProtectionMethod(enable_protection_nack, | |
| 625 enable_protection_fec); | |
| 626 } | |
| 627 | |
| 553 void VideoSendStream::ConfigureSsrcs() { | 628 void VideoSendStream::ConfigureSsrcs() { |
| 554 // Configure regular SSRCs. | 629 // Configure regular SSRCs. |
| 555 for (size_t i = 0; i < config_.rtp.ssrcs.size(); ++i) { | 630 for (size_t i = 0; i < config_.rtp.ssrcs.size(); ++i) { |
| 556 uint32_t ssrc = config_.rtp.ssrcs[i]; | 631 uint32_t ssrc = config_.rtp.ssrcs[i]; |
| 557 RtpRtcp* const rtp_rtcp = rtp_rtcp_modules_[i]; | 632 RtpRtcp* const rtp_rtcp = rtp_rtcp_modules_[i]; |
| 558 rtp_rtcp->SetSSRC(ssrc); | 633 rtp_rtcp->SetSSRC(ssrc); |
| 559 | 634 |
| 560 // Restore RTP state if previous existed. | 635 // Restore RTP state if previous existed. |
| 561 RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc); | 636 RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc); |
| 562 if (it != suspended_ssrcs_.end()) | 637 if (it != suspended_ssrcs_.end()) |
| 563 rtp_rtcp->SetRtpStateForSsrc(ssrc, it->second); | 638 rtp_rtcp->SetRtpState(it->second); |
| 564 } | 639 } |
| 565 | 640 |
| 566 // Set up RTX if available. | 641 // Set up RTX if available. |
| 567 if (config_.rtp.rtx.ssrcs.empty()) | 642 if (config_.rtp.rtx.ssrcs.empty()) |
| 568 return; | 643 return; |
| 569 | 644 |
| 570 // Configure RTX SSRCs. | 645 // Configure RTX SSRCs. |
| 571 RTC_DCHECK_EQ(config_.rtp.rtx.ssrcs.size(), config_.rtp.ssrcs.size()); | 646 RTC_DCHECK_EQ(config_.rtp.rtx.ssrcs.size(), config_.rtp.ssrcs.size()); |
| 572 for (size_t i = 0; i < config_.rtp.rtx.ssrcs.size(); ++i) { | 647 for (size_t i = 0; i < config_.rtp.rtx.ssrcs.size(); ++i) { |
| 573 uint32_t ssrc = config_.rtp.rtx.ssrcs[i]; | 648 uint32_t ssrc = config_.rtp.rtx.ssrcs[i]; |
| 574 RtpRtcp* const rtp_rtcp = rtp_rtcp_modules_[i]; | 649 RtpRtcp* const rtp_rtcp = rtp_rtcp_modules_[i]; |
| 575 rtp_rtcp->SetRtxSsrc(ssrc); | 650 rtp_rtcp->SetRtxSsrc(ssrc); |
| 576 RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc); | 651 RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc); |
| 577 if (it != suspended_ssrcs_.end()) | 652 if (it != suspended_ssrcs_.end()) |
| 578 rtp_rtcp->SetRtpStateForSsrc(ssrc, it->second); | 653 rtp_rtcp->SetRtxState(it->second); |
| 579 } | 654 } |
| 580 | 655 |
| 581 // Configure RTX payload types. | 656 // Configure RTX payload types. |
| 582 RTC_DCHECK_GE(config_.rtp.rtx.payload_type, 0); | 657 RTC_DCHECK_GE(config_.rtp.rtx.payload_type, 0); |
| 583 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) { | 658 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) { |
| 584 rtp_rtcp->SetRtxSendPayloadType(config_.rtp.rtx.payload_type, | 659 rtp_rtcp->SetRtxSendPayloadType(config_.rtp.rtx.payload_type, |
| 585 config_.encoder_settings.payload_type); | 660 config_.encoder_settings.payload_type); |
| 586 rtp_rtcp->SetRtxSendStatus(kRtxRetransmitted | kRtxRedundantPayloads); | 661 rtp_rtcp->SetRtxSendStatus(kRtxRetransmitted | kRtxRedundantPayloads); |
| 587 } | 662 } |
| 588 if (config_.rtp.fec.red_payload_type != -1 && | 663 if (config_.rtp.fec.red_payload_type != -1 && |
| 589 config_.rtp.fec.red_rtx_payload_type != -1) { | 664 config_.rtp.fec.red_rtx_payload_type != -1) { |
| 590 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) { | 665 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) { |
| 591 rtp_rtcp->SetRtxSendPayloadType(config_.rtp.fec.red_rtx_payload_type, | 666 rtp_rtcp->SetRtxSendPayloadType(config_.rtp.fec.red_rtx_payload_type, |
| 592 config_.rtp.fec.red_payload_type); | 667 config_.rtp.fec.red_payload_type); |
| 593 } | 668 } |
| 594 } | 669 } |
| 595 } | 670 } |
| 596 | 671 |
| 597 std::map<uint32_t, RtpState> VideoSendStream::GetRtpStates() const { | 672 std::map<uint32_t, RtpState> VideoSendStream::GetRtpStates() const { |
| 598 std::map<uint32_t, RtpState> rtp_states; | 673 std::map<uint32_t, RtpState> rtp_states; |
| 599 for (size_t i = 0; i < config_.rtp.ssrcs.size(); ++i) { | 674 for (size_t i = 0; i < config_.rtp.ssrcs.size(); ++i) { |
| 600 uint32_t ssrc = config_.rtp.ssrcs[i]; | 675 uint32_t ssrc = config_.rtp.ssrcs[i]; |
| 601 rtp_states[ssrc] = vie_channel_.GetRtpStateForSsrc(ssrc); | 676 RTC_DCHECK_EQ(ssrc, rtp_rtcp_modules_[i]->SSRC()); |
| 677 rtp_states[ssrc] = rtp_rtcp_modules_[i]->GetRtpState(); | |
| 602 } | 678 } |
| 603 | 679 |
| 604 for (size_t i = 0; i < config_.rtp.rtx.ssrcs.size(); ++i) { | 680 for (size_t i = 0; i < config_.rtp.rtx.ssrcs.size(); ++i) { |
| 605 uint32_t ssrc = config_.rtp.rtx.ssrcs[i]; | 681 uint32_t ssrc = config_.rtp.rtx.ssrcs[i]; |
| 606 rtp_states[ssrc] = vie_channel_.GetRtpStateForSsrc(ssrc); | 682 rtp_states[ssrc] = rtp_rtcp_modules_[i]->GetRtxState(); |
| 607 } | 683 } |
| 608 | 684 |
| 609 return rtp_states; | 685 return rtp_states; |
| 610 } | 686 } |
| 611 | 687 |
| 612 void VideoSendStream::SignalNetworkState(NetworkState state) { | 688 void VideoSendStream::SignalNetworkState(NetworkState state) { |
| 613 // When network goes up, enable RTCP status before setting transmission state. | 689 // When network goes up, enable RTCP status before setting transmission state. |
| 614 // When it goes down, disable RTCP afterwards. This ensures that any packets | 690 // When it goes down, disable RTCP afterwards. This ensures that any packets |
| 615 // sent due to the network state changed will not be dropped. | 691 // sent due to the network state changed will not be dropped. |
| 616 if (state == kNetworkUp) { | 692 if (state == kNetworkUp) { |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 627 int VideoSendStream::GetPaddingNeededBps() const { | 703 int VideoSendStream::GetPaddingNeededBps() const { |
| 628 return vie_encoder_.GetPaddingNeededBps(); | 704 return vie_encoder_.GetPaddingNeededBps(); |
| 629 } | 705 } |
| 630 | 706 |
| 631 void VideoSendStream::OnBitrateUpdated(uint32_t bitrate_bps, | 707 void VideoSendStream::OnBitrateUpdated(uint32_t bitrate_bps, |
| 632 uint8_t fraction_loss, | 708 uint8_t fraction_loss, |
| 633 int64_t rtt) { | 709 int64_t rtt) { |
| 634 vie_encoder_.OnBitrateUpdated(bitrate_bps, fraction_loss, rtt); | 710 vie_encoder_.OnBitrateUpdated(bitrate_bps, fraction_loss, rtt); |
| 635 } | 711 } |
| 636 | 712 |
| 713 int VideoSendStream::ProtectionRequest(const FecProtectionParams* delta_params, | |
| 714 const FecProtectionParams* key_params, | |
| 715 uint32_t* sent_video_rate_bps, | |
| 716 uint32_t* sent_nack_rate_bps, | |
| 717 uint32_t* sent_fec_rate_bps) { | |
| 718 *sent_video_rate_bps = 0; | |
| 719 *sent_nack_rate_bps = 0; | |
| 720 *sent_fec_rate_bps = 0; | |
| 721 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) { | |
| 722 uint32_t not_used = 0; | |
| 723 uint32_t module_video_rate = 0; | |
| 724 uint32_t module_fec_rate = 0; | |
| 725 uint32_t module_nack_rate = 0; | |
| 726 rtp_rtcp->SetFecParameters(delta_params, key_params); | |
| 727 rtp_rtcp->BitrateSent(¬_used, &module_video_rate, &module_fec_rate, | |
| 728 &module_nack_rate); | |
| 729 *sent_video_rate_bps += module_video_rate; | |
| 730 *sent_nack_rate_bps += module_nack_rate; | |
| 731 *sent_fec_rate_bps += module_fec_rate; | |
| 732 } | |
| 733 return 0; | |
| 734 } | |
| 735 | |
| 637 } // namespace internal | 736 } // namespace internal |
| 638 } // namespace webrtc | 737 } // namespace webrtc |
| OLD | NEW |