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); |
231 | 276 |
232 for (size_t i = 0; i < config_.rtp.extensions.size(); ++i) { | 277 for (size_t i = 0; i < config_.rtp.extensions.size(); ++i) { |
233 const std::string& extension = config_.rtp.extensions[i].name; | 278 const std::string& extension = config_.rtp.extensions[i].name; |
234 int id = config_.rtp.extensions[i].id; | 279 int id = config_.rtp.extensions[i].id; |
235 // One-byte-extension local identifiers are in the range 1-14 inclusive. | 280 // One-byte-extension local identifiers are in the range 1-14 inclusive. |
236 RTC_DCHECK_GE(id, 1); | 281 RTC_DCHECK_GE(id, 1); |
237 RTC_DCHECK_LE(id, 14); | 282 RTC_DCHECK_LE(id, 14); |
238 RTC_DCHECK(RtpExtension::IsSupportedForVideo(extension)); | 283 RTC_DCHECK(RtpExtension::IsSupportedForVideo(extension)); |
239 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) { | 284 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) { |
240 RTC_CHECK_EQ(0, rtp_rtcp->RegisterSendRtpHeaderExtension( | 285 RTC_CHECK_EQ(0, rtp_rtcp->RegisterSendRtpHeaderExtension( |
241 StringToRtpExtensionType(extension), id)); | 286 StringToRtpExtensionType(extension), id)); |
242 } | 287 } |
243 } | 288 } |
244 | 289 |
245 remb_->AddRembSender(rtp_rtcp_modules_[0]); | 290 remb_->AddRembSender(rtp_rtcp_modules_[0]); |
246 rtp_rtcp_modules_[0]->SetREMBStatus(true); | 291 rtp_rtcp_modules_[0]->SetREMBStatus(true); |
247 | 292 |
248 // Enable NACK, FEC or both. | 293 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(); | 294 ConfigureSsrcs(); |
271 | 295 |
272 // TODO(pbos): Should we set CNAME on all RTP modules? | 296 // TODO(pbos): Should we set CNAME on all RTP modules? |
273 rtp_rtcp_modules_.front()->SetCNAME(config_.rtp.c_name.c_str()); | 297 rtp_rtcp_modules_.front()->SetCNAME(config_.rtp.c_name.c_str()); |
274 // 28 to match packet overhead in ModuleRtpRtcpImpl. | 298 // 28 to match packet overhead in ModuleRtpRtcpImpl. |
275 static const size_t kRtpPacketSizeOverhead = 28; | 299 static const size_t kRtpPacketSizeOverhead = 28; |
276 RTC_DCHECK_LE(config_.rtp.max_packet_size, 0xFFFFu + kRtpPacketSizeOverhead); | 300 RTC_DCHECK_LE(config_.rtp.max_packet_size, 0xFFFFu + kRtpPacketSizeOverhead); |
277 const uint16_t mtu = static_cast<uint16_t>(config_.rtp.max_packet_size + | 301 const uint16_t mtu = static_cast<uint16_t>(config_.rtp.max_packet_size + |
278 kRtpPacketSizeOverhead); | 302 kRtpPacketSizeOverhead); |
279 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) { | 303 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) { |
280 rtp_rtcp->RegisterRtcpStatisticsCallback(&stats_proxy_); | 304 rtp_rtcp->RegisterRtcpStatisticsCallback(&stats_proxy_); |
281 rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(&stats_proxy_); | 305 rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(&stats_proxy_); |
282 rtp_rtcp->SetMaxTransferUnit(mtu); | 306 rtp_rtcp->SetMaxTransferUnit(mtu); |
283 rtp_rtcp->RegisterVideoSendPayload( | 307 rtp_rtcp->RegisterVideoSendPayload( |
284 config_.encoder_settings.payload_type, | 308 config_.encoder_settings.payload_type, |
285 config_.encoder_settings.payload_name.c_str()); | 309 config_.encoder_settings.payload_name.c_str()); |
286 } | 310 } |
287 | 311 |
288 RTC_DCHECK(config.encoder_settings.encoder); | 312 RTC_DCHECK(config.encoder_settings.encoder); |
289 RTC_DCHECK_GE(config.encoder_settings.payload_type, 0); | 313 RTC_DCHECK_GE(config.encoder_settings.payload_type, 0); |
290 RTC_DCHECK_LE(config.encoder_settings.payload_type, 127); | 314 RTC_DCHECK_LE(config.encoder_settings.payload_type, 127); |
291 RTC_CHECK_EQ(0, vie_encoder_.RegisterExternalEncoder( | 315 RTC_CHECK_EQ(0, vie_encoder_.RegisterExternalEncoder( |
292 config.encoder_settings.encoder, | 316 config.encoder_settings.encoder, |
293 config.encoder_settings.payload_type, | 317 config.encoder_settings.payload_type, |
294 config.encoder_settings.internal_source)); | 318 config.encoder_settings.internal_source)); |
295 | 319 |
296 ReconfigureVideoEncoder(encoder_config); | 320 ReconfigureVideoEncoder(encoder_config); |
297 | 321 |
298 vie_channel_.RegisterSendSideDelayObserver(&stats_proxy_); | |
299 | |
300 if (config_.post_encode_callback) | 322 if (config_.post_encode_callback) |
301 vie_encoder_.RegisterPostEncodeImageCallback(&encoded_frame_proxy_); | 323 vie_encoder_.RegisterPostEncodeImageCallback(&encoded_frame_proxy_); |
302 | 324 |
303 if (config_.suspend_below_min_bitrate) { | 325 if (config_.suspend_below_min_bitrate) { |
304 vcm_->SuspendBelowMinBitrate(); | 326 vcm_->SuspendBelowMinBitrate(); |
305 bitrate_allocator_->EnforceMinBitrate(false); | 327 bitrate_allocator_->EnforceMinBitrate(false); |
306 } | 328 } |
307 | 329 |
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_); | 330 module_process_thread_->RegisterModule(&overuse_detector_); |
313 | 331 |
314 encoder_thread_.Start(); | 332 encoder_thread_.Start(); |
315 encoder_thread_.SetPriority(rtc::kHighPriority); | 333 encoder_thread_.SetPriority(rtc::kHighPriority); |
316 } | 334 } |
317 | 335 |
318 VideoSendStream::~VideoSendStream() { | 336 VideoSendStream::~VideoSendStream() { |
319 LOG(LS_INFO) << "~VideoSendStream: " << config_.ToString(); | 337 LOG(LS_INFO) << "~VideoSendStream: " << config_.ToString(); |
320 | 338 |
321 Stop(); | 339 Stop(); |
322 | 340 |
323 // Stop the encoder thread permanently. | 341 // Stop the encoder thread permanently. |
324 rtc::AtomicOps::ReleaseStore(&stop_encoder_thread_, 1); | 342 rtc::AtomicOps::ReleaseStore(&stop_encoder_thread_, 1); |
325 encoder_wakeup_event_.Set(); | 343 encoder_wakeup_event_.Set(); |
326 encoder_thread_.Stop(); | 344 encoder_thread_.Stop(); |
327 | 345 |
328 // This needs to happen after stopping the encoder thread, | 346 // This needs to happen after stopping the encoder thread, |
329 // since the encoder thread calls AddObserver. | 347 // since the encoder thread calls AddObserver. |
330 bitrate_allocator_->RemoveObserver(this); | 348 bitrate_allocator_->RemoveObserver(this); |
331 | 349 |
332 module_process_thread_->DeRegisterModule(&overuse_detector_); | 350 module_process_thread_->DeRegisterModule(&overuse_detector_); |
333 vie_channel_.RegisterSendFrameCountObserver(nullptr); | |
334 vie_channel_.RegisterSendBitrateObserver(nullptr); | |
335 vie_channel_.RegisterRtcpPacketTypeCounterObserver(nullptr); | |
336 | 351 |
337 vie_encoder_.DeRegisterExternalEncoder(config_.encoder_settings.payload_type); | 352 vie_encoder_.DeRegisterExternalEncoder(config_.encoder_settings.payload_type); |
338 | 353 |
339 call_stats_->DeregisterStatsObserver(vie_channel_.GetStatsObserver()); | |
340 rtp_rtcp_modules_[0]->SetREMBStatus(false); | 354 rtp_rtcp_modules_[0]->SetREMBStatus(false); |
341 remb_->RemoveRembSender(rtp_rtcp_modules_[0]); | 355 remb_->RemoveRembSender(rtp_rtcp_modules_[0]); |
342 | 356 |
343 // ViEChannel outlives ViEEncoder so remove encoder from feedback before | 357 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) { |
344 // destruction. | 358 congestion_controller_->packet_router()->RemoveRtpModule(rtp_rtcp); |
345 encoder_feedback_.TearDown(); | 359 module_process_thread_->DeRegisterModule(rtp_rtcp); |
346 | 360 delete rtp_rtcp; |
347 congestion_controller_->GetRemoteBitrateEstimator(false)->RemoveStream( | 361 } |
348 vie_receiver_->GetRemoteSsrc()); | |
349 } | 362 } |
350 | 363 |
351 VideoCaptureInput* VideoSendStream::Input() { | 364 VideoCaptureInput* VideoSendStream::Input() { |
352 return &input_; | 365 return &input_; |
353 } | 366 } |
354 | 367 |
355 void VideoSendStream::Start() { | 368 void VideoSendStream::Start() { |
356 if (payload_router_.active()) | 369 if (payload_router_.active()) |
357 return; | 370 return; |
358 TRACE_EVENT_INSTANT0("webrtc", "VideoSendStream::Start"); | 371 TRACE_EVENT_INSTANT0("webrtc", "VideoSendStream::Start"); |
359 vie_encoder_.Pause(); | 372 vie_encoder_.Pause(); |
360 payload_router_.set_active(true); | 373 payload_router_.set_active(true); |
361 // Was not already started, trigger a keyframe. | 374 // Was not already started, trigger a keyframe. |
362 vie_encoder_.SendKeyFrame(); | 375 vie_encoder_.SendKeyFrame(); |
363 vie_encoder_.Restart(); | 376 vie_encoder_.Restart(); |
364 vie_receiver_->StartReceive(); | |
365 } | 377 } |
366 | 378 |
367 void VideoSendStream::Stop() { | 379 void VideoSendStream::Stop() { |
368 if (!payload_router_.active()) | 380 if (!payload_router_.active()) |
369 return; | 381 return; |
370 TRACE_EVENT_INSTANT0("webrtc", "VideoSendStream::Stop"); | 382 TRACE_EVENT_INSTANT0("webrtc", "VideoSendStream::Stop"); |
371 // TODO(pbos): Make sure the encoder stops here. | 383 // TODO(pbos): Make sure the encoder stops here. |
372 payload_router_.set_active(false); | 384 payload_router_.set_active(false); |
373 vie_receiver_->StopReceive(); | |
374 } | 385 } |
375 | 386 |
376 bool VideoSendStream::EncoderThreadFunction(void* obj) { | 387 bool VideoSendStream::EncoderThreadFunction(void* obj) { |
377 static_cast<VideoSendStream*>(obj)->EncoderProcess(); | 388 static_cast<VideoSendStream*>(obj)->EncoderProcess(); |
378 // We're done, return false to abort. | 389 // We're done, return false to abort. |
379 return false; | 390 return false; |
380 } | 391 } |
381 | 392 |
382 void VideoSendStream::EncoderProcess() { | 393 void VideoSendStream::EncoderProcess() { |
383 while (true) { | 394 while (true) { |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
528 video_codec.maxFramerate = streams[0].max_framerate; | 539 video_codec.maxFramerate = streams[0].max_framerate; |
529 | 540 |
530 video_codec.startBitrate = | 541 video_codec.startBitrate = |
531 bitrate_allocator_->AddObserver(this, | 542 bitrate_allocator_->AddObserver(this, |
532 video_codec.minBitrate * 1000, | 543 video_codec.minBitrate * 1000, |
533 video_codec.maxBitrate * 1000) / 1000; | 544 video_codec.maxBitrate * 1000) / 1000; |
534 vie_encoder_.SetEncoder(video_codec, config.min_transmit_bitrate_bps); | 545 vie_encoder_.SetEncoder(video_codec, config.min_transmit_bitrate_bps); |
535 } | 546 } |
536 | 547 |
537 bool VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) { | 548 bool VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) { |
538 return vie_receiver_->DeliverRtcp(packet, length); | 549 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) |
| 550 rtp_rtcp->IncomingRtcpPacket(packet, length); |
| 551 return true; |
539 } | 552 } |
540 | 553 |
541 VideoSendStream::Stats VideoSendStream::GetStats() { | 554 VideoSendStream::Stats VideoSendStream::GetStats() { |
542 return stats_proxy_.GetStats(); | 555 return stats_proxy_.GetStats(); |
543 } | 556 } |
544 | 557 |
545 void VideoSendStream::OveruseDetected() { | 558 void VideoSendStream::OveruseDetected() { |
546 if (config_.overuse_callback) | 559 if (config_.overuse_callback) |
547 config_.overuse_callback->OnLoadUpdate(LoadObserver::kOveruse); | 560 config_.overuse_callback->OnLoadUpdate(LoadObserver::kOveruse); |
548 } | 561 } |
549 | 562 |
550 void VideoSendStream::NormalUsage() { | 563 void VideoSendStream::NormalUsage() { |
551 if (config_.overuse_callback) | 564 if (config_.overuse_callback) |
552 config_.overuse_callback->OnLoadUpdate(LoadObserver::kUnderuse); | 565 config_.overuse_callback->OnLoadUpdate(LoadObserver::kUnderuse); |
553 } | 566 } |
554 | 567 |
| 568 void VideoSendStream::ConfigureProtection() { |
| 569 // Enable NACK, FEC or both. |
| 570 const bool enable_protection_nack = config_.rtp.nack.rtp_history_ms > 0; |
| 571 bool enable_protection_fec = config_.rtp.fec.red_payload_type != -1; |
| 572 // Payload types without picture ID cannot determine that a stream is complete |
| 573 // without retransmitting FEC, so using FEC + NACK for H.264 (for instance) is |
| 574 // a waste of bandwidth since FEC packets still have to be transmitted. Note |
| 575 // that this is not the case with FLEXFEC. |
| 576 if (enable_protection_nack && |
| 577 !PayloadTypeSupportsSkippingFecPackets( |
| 578 config_.encoder_settings.payload_name)) { |
| 579 LOG(LS_WARNING) << "Transmitting payload type without picture ID using" |
| 580 "NACK+FEC is a waste of bandwidth since FEC packets " |
| 581 "also have to be retransmitted. Disabling FEC."; |
| 582 enable_protection_fec = false; |
| 583 } |
| 584 |
| 585 // Set to valid uint8_ts to be castable later without signed overflows. |
| 586 uint8_t payload_type_red = 0; |
| 587 uint8_t payload_type_fec = 0; |
| 588 // TODO(changbin): Should set RTX for RED mapping in RTP sender in future. |
| 589 // Validate payload types. If either RED or FEC payload types are set then |
| 590 // both should be. If FEC is enabled then they both have to be set. |
| 591 if (enable_protection_fec || config_.rtp.fec.red_payload_type != -1 || |
| 592 config_.rtp.fec.ulpfec_payload_type != -1) { |
| 593 RTC_DCHECK_GE(config_.rtp.fec.red_payload_type, 0); |
| 594 RTC_DCHECK_GE(config_.rtp.fec.ulpfec_payload_type, 0); |
| 595 RTC_DCHECK_LE(config_.rtp.fec.red_payload_type, 127); |
| 596 RTC_DCHECK_LE(config_.rtp.fec.ulpfec_payload_type, 127); |
| 597 payload_type_red = static_cast<uint8_t>(config_.rtp.fec.red_payload_type); |
| 598 payload_type_fec = |
| 599 static_cast<uint8_t>(config_.rtp.fec.ulpfec_payload_type); |
| 600 } else { |
| 601 // Payload types unset. |
| 602 RTC_DCHECK_EQ(config_.rtp.fec.red_payload_type, -1); |
| 603 RTC_DCHECK_EQ(config_.rtp.fec.ulpfec_payload_type, -1); |
| 604 } |
| 605 |
| 606 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) { |
| 607 // Set NACK. |
| 608 rtp_rtcp->SetStorePacketsStatus( |
| 609 enable_protection_nack || congestion_controller_->pacer(), |
| 610 kMinSendSidePacketHistorySize); |
| 611 // Set FEC. |
| 612 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) { |
| 613 rtp_rtcp->SetGenericFECStatus(enable_protection_fec, payload_type_red, |
| 614 payload_type_fec); |
| 615 } |
| 616 } |
| 617 |
| 618 vie_encoder_.SetProtectionMethod(enable_protection_nack, |
| 619 enable_protection_fec); |
| 620 } |
| 621 |
555 void VideoSendStream::ConfigureSsrcs() { | 622 void VideoSendStream::ConfigureSsrcs() { |
556 // Configure regular SSRCs. | 623 // Configure regular SSRCs. |
557 for (size_t i = 0; i < config_.rtp.ssrcs.size(); ++i) { | 624 for (size_t i = 0; i < config_.rtp.ssrcs.size(); ++i) { |
558 uint32_t ssrc = config_.rtp.ssrcs[i]; | 625 uint32_t ssrc = config_.rtp.ssrcs[i]; |
559 RtpRtcp* const rtp_rtcp = rtp_rtcp_modules_[i]; | 626 RtpRtcp* const rtp_rtcp = rtp_rtcp_modules_[i]; |
560 rtp_rtcp->SetSSRC(ssrc); | 627 rtp_rtcp->SetSSRC(ssrc); |
561 | 628 |
562 // Restore RTP state if previous existed. | 629 // Restore RTP state if previous existed. |
563 RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc); | 630 RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc); |
564 if (it != suspended_ssrcs_.end()) | 631 if (it != suspended_ssrcs_.end()) |
565 rtp_rtcp->SetRtpStateForSsrc(ssrc, it->second); | 632 rtp_rtcp->SetRtpState(it->second); |
566 } | 633 } |
567 | 634 |
568 // Set up RTX if available. | 635 // Set up RTX if available. |
569 if (config_.rtp.rtx.ssrcs.empty()) | 636 if (config_.rtp.rtx.ssrcs.empty()) |
570 return; | 637 return; |
571 | 638 |
572 // Configure RTX SSRCs. | 639 // Configure RTX SSRCs. |
573 RTC_DCHECK_EQ(config_.rtp.rtx.ssrcs.size(), config_.rtp.ssrcs.size()); | 640 RTC_DCHECK_EQ(config_.rtp.rtx.ssrcs.size(), config_.rtp.ssrcs.size()); |
574 for (size_t i = 0; i < config_.rtp.rtx.ssrcs.size(); ++i) { | 641 for (size_t i = 0; i < config_.rtp.rtx.ssrcs.size(); ++i) { |
575 uint32_t ssrc = config_.rtp.rtx.ssrcs[i]; | 642 uint32_t ssrc = config_.rtp.rtx.ssrcs[i]; |
576 RtpRtcp* const rtp_rtcp = rtp_rtcp_modules_[i]; | 643 RtpRtcp* const rtp_rtcp = rtp_rtcp_modules_[i]; |
577 rtp_rtcp->SetRtxSsrc(ssrc); | 644 rtp_rtcp->SetRtxSsrc(ssrc); |
578 RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc); | 645 RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc); |
579 if (it != suspended_ssrcs_.end()) | 646 if (it != suspended_ssrcs_.end()) |
580 rtp_rtcp->SetRtpStateForSsrc(ssrc, it->second); | 647 rtp_rtcp->SetRtxState(it->second); |
581 } | 648 } |
582 | 649 |
583 // Configure RTX payload types. | 650 // Configure RTX payload types. |
584 RTC_DCHECK_GE(config_.rtp.rtx.payload_type, 0); | 651 RTC_DCHECK_GE(config_.rtp.rtx.payload_type, 0); |
585 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) { | 652 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) { |
586 rtp_rtcp->SetRtxSendPayloadType(config_.rtp.rtx.payload_type, | 653 rtp_rtcp->SetRtxSendPayloadType(config_.rtp.rtx.payload_type, |
587 config_.encoder_settings.payload_type); | 654 config_.encoder_settings.payload_type); |
588 rtp_rtcp->SetRtxSendStatus(kRtxRetransmitted | kRtxRedundantPayloads); | 655 rtp_rtcp->SetRtxSendStatus(kRtxRetransmitted | kRtxRedundantPayloads); |
589 } | 656 } |
590 if (config_.rtp.fec.red_payload_type != -1 && | 657 if (config_.rtp.fec.red_payload_type != -1 && |
591 config_.rtp.fec.red_rtx_payload_type != -1) { | 658 config_.rtp.fec.red_rtx_payload_type != -1) { |
592 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) { | 659 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) { |
593 rtp_rtcp->SetRtxSendPayloadType(config_.rtp.fec.red_rtx_payload_type, | 660 rtp_rtcp->SetRtxSendPayloadType(config_.rtp.fec.red_rtx_payload_type, |
594 config_.rtp.fec.red_payload_type); | 661 config_.rtp.fec.red_payload_type); |
595 } | 662 } |
596 } | 663 } |
597 } | 664 } |
598 | 665 |
599 std::map<uint32_t, RtpState> VideoSendStream::GetRtpStates() const { | 666 std::map<uint32_t, RtpState> VideoSendStream::GetRtpStates() const { |
600 std::map<uint32_t, RtpState> rtp_states; | 667 std::map<uint32_t, RtpState> rtp_states; |
601 for (size_t i = 0; i < config_.rtp.ssrcs.size(); ++i) { | 668 for (size_t i = 0; i < config_.rtp.ssrcs.size(); ++i) { |
602 uint32_t ssrc = config_.rtp.ssrcs[i]; | 669 uint32_t ssrc = config_.rtp.ssrcs[i]; |
603 rtp_states[ssrc] = vie_channel_.GetRtpStateForSsrc(ssrc); | 670 RTC_DCHECK_EQ(ssrc, rtp_rtcp_modules_[i]->SSRC()); |
| 671 rtp_states[ssrc] = rtp_rtcp_modules_[i]->GetRtpState(); |
604 } | 672 } |
605 | 673 |
606 for (size_t i = 0; i < config_.rtp.rtx.ssrcs.size(); ++i) { | 674 for (size_t i = 0; i < config_.rtp.rtx.ssrcs.size(); ++i) { |
607 uint32_t ssrc = config_.rtp.rtx.ssrcs[i]; | 675 uint32_t ssrc = config_.rtp.rtx.ssrcs[i]; |
608 rtp_states[ssrc] = vie_channel_.GetRtpStateForSsrc(ssrc); | 676 rtp_states[ssrc] = rtp_rtcp_modules_[i]->GetRtxState(); |
609 } | 677 } |
610 | 678 |
611 return rtp_states; | 679 return rtp_states; |
612 } | 680 } |
613 | 681 |
614 void VideoSendStream::SignalNetworkState(NetworkState state) { | 682 void VideoSendStream::SignalNetworkState(NetworkState state) { |
615 // When network goes up, enable RTCP status before setting transmission state. | 683 // When network goes up, enable RTCP status before setting transmission state. |
616 // When it goes down, disable RTCP afterwards. This ensures that any packets | 684 // When it goes down, disable RTCP afterwards. This ensures that any packets |
617 // sent due to the network state changed will not be dropped. | 685 // sent due to the network state changed will not be dropped. |
618 if (state == kNetworkUp) { | 686 if (state == kNetworkUp) { |
(...skipping 10 matching lines...) Expand all Loading... |
629 int VideoSendStream::GetPaddingNeededBps() const { | 697 int VideoSendStream::GetPaddingNeededBps() const { |
630 return vie_encoder_.GetPaddingNeededBps(); | 698 return vie_encoder_.GetPaddingNeededBps(); |
631 } | 699 } |
632 | 700 |
633 void VideoSendStream::OnBitrateUpdated(uint32_t bitrate_bps, | 701 void VideoSendStream::OnBitrateUpdated(uint32_t bitrate_bps, |
634 uint8_t fraction_loss, | 702 uint8_t fraction_loss, |
635 int64_t rtt) { | 703 int64_t rtt) { |
636 vie_encoder_.OnBitrateUpdated(bitrate_bps, fraction_loss, rtt); | 704 vie_encoder_.OnBitrateUpdated(bitrate_bps, fraction_loss, rtt); |
637 } | 705 } |
638 | 706 |
| 707 int VideoSendStream::ProtectionRequest(const FecProtectionParams* delta_params, |
| 708 const FecProtectionParams* key_params, |
| 709 uint32_t* sent_video_rate_bps, |
| 710 uint32_t* sent_nack_rate_bps, |
| 711 uint32_t* sent_fec_rate_bps) { |
| 712 *sent_video_rate_bps = 0; |
| 713 *sent_nack_rate_bps = 0; |
| 714 *sent_fec_rate_bps = 0; |
| 715 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) { |
| 716 uint32_t not_used = 0; |
| 717 uint32_t module_video_rate = 0; |
| 718 uint32_t module_fec_rate = 0; |
| 719 uint32_t module_nack_rate = 0; |
| 720 rtp_rtcp->SetFecParameters(delta_params, key_params); |
| 721 rtp_rtcp->BitrateSent(¬_used, &module_video_rate, &module_fec_rate, |
| 722 &module_nack_rate); |
| 723 *sent_video_rate_bps += module_video_rate; |
| 724 *sent_nack_rate_bps += module_nack_rate; |
| 725 *sent_fec_rate_bps += module_fec_rate; |
| 726 } |
| 727 return 0; |
| 728 } |
| 729 |
639 } // namespace internal | 730 } // namespace internal |
640 } // namespace webrtc | 731 } // namespace webrtc |
OLD | NEW |