 Chromium Code Reviews
 Chromium Code Reviews Issue 2255463002:
  Change OverUseFrameDetector to use a task queue  (Closed) 
  Base URL: https://chromium.googlesource.com/external/webrtc.git@reland_taskq_in_encoder
    
  
    Issue 2255463002:
  Change OverUseFrameDetector to use a task queue  (Closed) 
  Base URL: https://chromium.googlesource.com/external/webrtc.git@reland_taskq_in_encoder| OLD | NEW | 
|---|---|
| 1 /* | 1 /* | 
| 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 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 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 192 options.low_encode_usage_threshold_percent = 150; | 192 options.low_encode_usage_threshold_percent = 150; | 
| 193 options.high_encode_usage_threshold_percent = 200; | 193 options.high_encode_usage_threshold_percent = 200; | 
| 194 } | 194 } | 
| 195 return options; | 195 return options; | 
| 196 } | 196 } | 
| 197 | 197 | 
| 198 } // namespace | 198 } // namespace | 
| 199 | 199 | 
| 200 class ViEEncoder::EncodeTask : public rtc::QueuedTask { | 200 class ViEEncoder::EncodeTask : public rtc::QueuedTask { | 
| 201 public: | 201 public: | 
| 202 EncodeTask(const VideoFrame& frame, ViEEncoder* vie_encoder) | 202 EncodeTask(const VideoFrame& frame, | 
| 203 : vie_encoder_(vie_encoder) { | 203 ViEEncoder* vie_encoder, | 
| 204 int64_t time_when_posted_in_ms) | |
| 205 : vie_encoder_(vie_encoder), time_when_posted_(time_when_posted_in_ms) { | |
| 204 frame_.ShallowCopy(frame); | 206 frame_.ShallowCopy(frame); | 
| 205 ++vie_encoder_->posted_frames_waiting_for_encode_; | 207 ++vie_encoder_->posted_frames_waiting_for_encode_; | 
| 206 } | 208 } | 
| 207 | 209 | 
| 208 private: | 210 private: | 
| 209 bool Run() override { | 211 bool Run() override { | 
| 210 RTC_DCHECK_GT(vie_encoder_->posted_frames_waiting_for_encode_.Value(), 0); | 212 RTC_DCHECK_GT(vie_encoder_->posted_frames_waiting_for_encode_.Value(), 0); | 
| 211 if (--vie_encoder_->posted_frames_waiting_for_encode_ == 0) { | 213 if (--vie_encoder_->posted_frames_waiting_for_encode_ == 0) { | 
| 212 vie_encoder_->EncodeVideoFrame(frame_); | 214 vie_encoder_->EncodeVideoFrame(frame_, time_when_posted_); | 
| 213 } else { | 215 } else { | 
| 214 // There is a newer frame in flight. Do not encode this frame. | 216 // There is a newer frame in flight. Do not encode this frame. | 
| 215 LOG(LS_VERBOSE) | 217 LOG(LS_VERBOSE) | 
| 216 << "Incoming frame dropped due to that the encoder is blocked."; | 218 << "Incoming frame dropped due to that the encoder is blocked."; | 
| 217 } | 219 } | 
| 218 return true; | 220 return true; | 
| 219 } | 221 } | 
| 220 VideoFrame frame_; | 222 VideoFrame frame_; | 
| 221 ViEEncoder* vie_encoder_; | 223 ViEEncoder* const vie_encoder_; | 
| 224 const int64_t time_when_posted_; | |
| 
åsapersson
2016/08/24 08:59:05
time_when_posted_ms_
 
perkj_webrtc
2016/09/01 10:03:30
Done.
 | |
| 222 }; | 225 }; | 
| 223 | 226 | 
| 224 ViEEncoder::ViEEncoder(uint32_t number_of_cores, | 227 ViEEncoder::ViEEncoder(uint32_t number_of_cores, | 
| 225 SendStatisticsProxy* stats_proxy, | 228 SendStatisticsProxy* stats_proxy, | 
| 226 const VideoSendStream::Config::EncoderSettings& settings, | 229 const VideoSendStream::Config::EncoderSettings& settings, | 
| 227 rtc::VideoSinkInterface<VideoFrame>* pre_encode_callback, | 230 rtc::VideoSinkInterface<VideoFrame>* pre_encode_callback, | 
| 228 LoadObserver* overuse_callback, | 231 LoadObserver* overuse_callback, | 
| 229 EncodedFrameObserver* encoder_timing) | 232 EncodedFrameObserver* encoder_timing) | 
| 230 : shutdown_event_(true /* manual_reset */, false), | 233 : shutdown_event_(true /* manual_reset */, false), | 
| 231 number_of_cores_(number_of_cores), | 234 number_of_cores_(number_of_cores), | 
| (...skipping 17 matching lines...) Expand all Loading... | |
| 249 picture_id_sli_(0), | 252 picture_id_sli_(0), | 
| 250 has_received_rpsi_(false), | 253 has_received_rpsi_(false), | 
| 251 picture_id_rpsi_(0), | 254 picture_id_rpsi_(0), | 
| 252 clock_(Clock::GetRealTimeClock()), | 255 clock_(Clock::GetRealTimeClock()), | 
| 253 last_captured_timestamp_(0), | 256 last_captured_timestamp_(0), | 
| 254 delta_ntp_internal_ms_(clock_->CurrentNtpInMilliseconds() - | 257 delta_ntp_internal_ms_(clock_->CurrentNtpInMilliseconds() - | 
| 255 clock_->TimeInMilliseconds()), | 258 clock_->TimeInMilliseconds()), | 
| 256 encoder_queue_("EncoderQueue") { | 259 encoder_queue_("EncoderQueue") { | 
| 257 vp_->EnableTemporalDecimation(false); | 260 vp_->EnableTemporalDecimation(false); | 
| 258 | 261 | 
| 259 encoder_queue_.PostTask([this] { | 262 encoder_queue_.PostTask([this, encoder_timing] { | 
| 260 RTC_DCHECK_RUN_ON(&encoder_queue_); | 263 RTC_DCHECK_RUN_ON(&encoder_queue_); | 
| 261 video_sender_.RegisterExternalEncoder( | 264 video_sender_.RegisterExternalEncoder( | 
| 262 settings_.encoder, settings_.payload_type, settings_.internal_source); | 265 settings_.encoder, settings_.payload_type, settings_.internal_source); | 
| 266 overuse_detector_.StartCheckForOveruse(); | |
| 263 }); | 267 }); | 
| 264 } | 268 } | 
| 265 | 269 | 
| 266 ViEEncoder::~ViEEncoder() { | 270 ViEEncoder::~ViEEncoder() { | 
| 267 RTC_DCHECK(shutdown_event_.Wait(0)) | 271 RTC_DCHECK(shutdown_event_.Wait(0)) | 
| 268 << "Must call ::Stop() before destruction."; | 272 << "Must call ::Stop() before destruction."; | 
| 269 } | 273 } | 
| 270 | 274 | 
| 271 void ViEEncoder::Stop() { | 275 void ViEEncoder::Stop() { | 
| 272 if (!encoder_queue_.IsCurrent()) { | 276 if (!encoder_queue_.IsCurrent()) { | 
| 273 encoder_queue_.PostTask([this] { Stop(); }); | 277 encoder_queue_.PostTask([this] { Stop(); }); | 
| 274 shutdown_event_.Wait(rtc::Event::kForever); | 278 shutdown_event_.Wait(rtc::Event::kForever); | 
| 275 return; | 279 return; | 
| 276 } | 280 } | 
| 277 RTC_DCHECK_RUN_ON(&encoder_queue_); | 281 RTC_DCHECK_RUN_ON(&encoder_queue_); | 
| 278 video_sender_.RegisterExternalEncoder(nullptr, settings_.payload_type, false); | 282 video_sender_.RegisterExternalEncoder(nullptr, settings_.payload_type, false); | 
| 283 overuse_detector_.StopCheckForOveruse(); | |
| 279 shutdown_event_.Set(); | 284 shutdown_event_.Set(); | 
| 280 } | 285 } | 
| 281 | 286 | 
| 282 void ViEEncoder::RegisterProcessThread(ProcessThread* module_process_thread) { | 287 void ViEEncoder::RegisterProcessThread(ProcessThread* module_process_thread) { | 
| 283 RTC_DCHECK(!module_process_thread_); | 288 RTC_DCHECK(!module_process_thread_); | 
| 284 module_process_thread_ = module_process_thread; | 289 module_process_thread_ = module_process_thread; | 
| 285 module_process_thread_->RegisterModule(&overuse_detector_); | |
| 286 module_process_thread_->RegisterModule(&video_sender_); | 290 module_process_thread_->RegisterModule(&video_sender_); | 
| 287 module_process_thread_checker_.DetachFromThread(); | 291 module_process_thread_checker_.DetachFromThread(); | 
| 288 } | 292 } | 
| 289 | 293 | 
| 290 void ViEEncoder::DeRegisterProcessThread() { | 294 void ViEEncoder::DeRegisterProcessThread() { | 
| 291 module_process_thread_->DeRegisterModule(&overuse_detector_); | |
| 292 module_process_thread_->DeRegisterModule(&video_sender_); | 295 module_process_thread_->DeRegisterModule(&video_sender_); | 
| 293 } | 296 } | 
| 294 | 297 | 
| 295 void ViEEncoder::SetSink(EncodedImageCallback* sink) { | 298 void ViEEncoder::SetSink(EncodedImageCallback* sink) { | 
| 296 encoder_queue_.PostTask([this, sink] { | 299 encoder_queue_.PostTask([this, sink] { | 
| 297 RTC_DCHECK_RUN_ON(&encoder_queue_); | 300 RTC_DCHECK_RUN_ON(&encoder_queue_); | 
| 298 sink_ = sink; | 301 sink_ = sink; | 
| 299 }); | 302 }); | 
| 300 } | 303 } | 
| 301 | 304 | 
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 390 if (incoming_frame.ntp_time_ms() <= last_captured_timestamp_) { | 393 if (incoming_frame.ntp_time_ms() <= last_captured_timestamp_) { | 
| 391 // We don't allow the same capture time for two frames, drop this one. | 394 // We don't allow the same capture time for two frames, drop this one. | 
| 392 LOG(LS_WARNING) << "Same/old NTP timestamp (" | 395 LOG(LS_WARNING) << "Same/old NTP timestamp (" | 
| 393 << incoming_frame.ntp_time_ms() | 396 << incoming_frame.ntp_time_ms() | 
| 394 << " <= " << last_captured_timestamp_ | 397 << " <= " << last_captured_timestamp_ | 
| 395 << ") for incoming frame. Dropping."; | 398 << ") for incoming frame. Dropping."; | 
| 396 return; | 399 return; | 
| 397 } | 400 } | 
| 398 | 401 | 
| 399 last_captured_timestamp_ = incoming_frame.ntp_time_ms(); | 402 last_captured_timestamp_ = incoming_frame.ntp_time_ms(); | 
| 400 overuse_detector_.FrameCaptured(incoming_frame); | 403 encoder_queue_.PostTask(std::unique_ptr<rtc::QueuedTask>( | 
| 401 encoder_queue_.PostTask( | 404 new EncodeTask(incoming_frame, this, clock_->TimeInMilliseconds()))); | 
| 402 std::unique_ptr<rtc::QueuedTask>(new EncodeTask(incoming_frame, this))); | |
| 403 } | 405 } | 
| 404 | 406 | 
| 405 bool ViEEncoder::EncoderPaused() const { | 407 bool ViEEncoder::EncoderPaused() const { | 
| 406 RTC_DCHECK_RUN_ON(&encoder_queue_); | 408 RTC_DCHECK_RUN_ON(&encoder_queue_); | 
| 407 // Pause video if paused by caller or as long as the network is down or the | 409 // Pause video if paused by caller or as long as the network is down or the | 
| 408 // pacer queue has grown too large in buffered mode. | 410 // pacer queue has grown too large in buffered mode. | 
| 409 // If the pacer queue has grown too large or the network is down, | 411 // If the pacer queue has grown too large or the network is down, | 
| 410 // last_observed_bitrate_bps_ will be 0. | 412 // last_observed_bitrate_bps_ will be 0. | 
| 411 return last_observed_bitrate_bps_ == 0; | 413 return last_observed_bitrate_bps_ == 0; | 
| 412 } | 414 } | 
| (...skipping 10 matching lines...) Expand all Loading... | |
| 423 | 425 | 
| 424 void ViEEncoder::TraceFrameDropEnd() { | 426 void ViEEncoder::TraceFrameDropEnd() { | 
| 425 RTC_DCHECK_RUN_ON(&encoder_queue_); | 427 RTC_DCHECK_RUN_ON(&encoder_queue_); | 
| 426 // End trace event on first frame after encoder resumes, if frame was dropped. | 428 // End trace event on first frame after encoder resumes, if frame was dropped. | 
| 427 if (encoder_paused_and_dropped_frame_) { | 429 if (encoder_paused_and_dropped_frame_) { | 
| 428 TRACE_EVENT_ASYNC_END0("webrtc", "EncoderPaused", this); | 430 TRACE_EVENT_ASYNC_END0("webrtc", "EncoderPaused", this); | 
| 429 } | 431 } | 
| 430 encoder_paused_and_dropped_frame_ = false; | 432 encoder_paused_and_dropped_frame_ = false; | 
| 431 } | 433 } | 
| 432 | 434 | 
| 433 void ViEEncoder::EncodeVideoFrame(const VideoFrame& video_frame) { | 435 void ViEEncoder::EncodeVideoFrame(const VideoFrame& video_frame, | 
| 436 int64_t time_when_posted_in_ms) { | |
| 434 RTC_DCHECK_RUN_ON(&encoder_queue_); | 437 RTC_DCHECK_RUN_ON(&encoder_queue_); | 
| 435 if (pre_encode_callback_) | 438 if (pre_encode_callback_) | 
| 436 pre_encode_callback_->OnFrame(video_frame); | 439 pre_encode_callback_->OnFrame(video_frame); | 
| 437 | 440 | 
| 438 if (EncoderPaused()) { | 441 if (EncoderPaused()) { | 
| 439 TraceFrameDropStart(); | 442 TraceFrameDropStart(); | 
| 440 return; | 443 return; | 
| 441 } | 444 } | 
| 442 TraceFrameDropEnd(); | 445 TraceFrameDropEnd(); | 
| 443 | 446 | 
| 444 TRACE_EVENT_ASYNC_STEP0("webrtc", "Video", video_frame.render_time_ms(), | 447 TRACE_EVENT_ASYNC_STEP0("webrtc", "Video", video_frame.render_time_ms(), | 
| 445 "Encode"); | 448 "Encode"); | 
| 446 const VideoFrame* frame_to_send = &video_frame; | 449 const VideoFrame* frame_to_send = &video_frame; | 
| 447 // TODO(wuchengli): support texture frames. | 450 // TODO(wuchengli): support texture frames. | 
| 448 if (!video_frame.video_frame_buffer()->native_handle()) { | 451 if (!video_frame.video_frame_buffer()->native_handle()) { | 
| 449 // Pass frame via preprocessor. | 452 // Pass frame via preprocessor. | 
| 450 frame_to_send = vp_->PreprocessFrame(video_frame); | 453 frame_to_send = vp_->PreprocessFrame(video_frame); | 
| 451 if (!frame_to_send) { | 454 if (!frame_to_send) { | 
| 452 // Drop this frame, or there was an error processing it. | 455 // Drop this frame, or there was an error processing it. | 
| 453 return; | 456 return; | 
| 454 } | 457 } | 
| 455 } | 458 } | 
| 456 | 459 | 
| 460 overuse_detector_.FrameCaptured(video_frame, time_when_posted_in_ms); | |
| 461 | |
| 457 if (encoder_config_.codecType == webrtc::kVideoCodecVP8) { | 462 if (encoder_config_.codecType == webrtc::kVideoCodecVP8) { | 
| 458 webrtc::CodecSpecificInfo codec_specific_info; | 463 webrtc::CodecSpecificInfo codec_specific_info; | 
| 459 codec_specific_info.codecType = webrtc::kVideoCodecVP8; | 464 codec_specific_info.codecType = webrtc::kVideoCodecVP8; | 
| 460 | 465 | 
| 461 codec_specific_info.codecSpecific.VP8.hasReceivedRPSI = | 466 codec_specific_info.codecSpecific.VP8.hasReceivedRPSI = | 
| 462 has_received_rpsi_; | 467 has_received_rpsi_; | 
| 463 codec_specific_info.codecSpecific.VP8.hasReceivedSLI = | 468 codec_specific_info.codecSpecific.VP8.hasReceivedSLI = | 
| 464 has_received_sli_; | 469 has_received_sli_; | 
| 465 codec_specific_info.codecSpecific.VP8.pictureIdRPSI = | 470 codec_specific_info.codecSpecific.VP8.pictureIdRPSI = | 
| 466 picture_id_rpsi_; | 471 picture_id_rpsi_; | 
| (...skipping 24 matching lines...) Expand all Loading... | |
| 491 // Encoded is called on whatever thread the real encoder implementation run | 496 // Encoded is called on whatever thread the real encoder implementation run | 
| 492 // on. In the case of hardware encoders, there might be several encoders | 497 // on. In the case of hardware encoders, there might be several encoders | 
| 493 // running in parallel on different threads. | 498 // running in parallel on different threads. | 
| 494 if (stats_proxy_) { | 499 if (stats_proxy_) { | 
| 495 stats_proxy_->OnSendEncodedImage(encoded_image, codec_specific_info); | 500 stats_proxy_->OnSendEncodedImage(encoded_image, codec_specific_info); | 
| 496 } | 501 } | 
| 497 | 502 | 
| 498 EncodedImageCallback::Result result = | 503 EncodedImageCallback::Result result = | 
| 499 sink_->OnEncodedImage(encoded_image, codec_specific_info, fragmentation); | 504 sink_->OnEncodedImage(encoded_image, codec_specific_info, fragmentation); | 
| 500 | 505 | 
| 501 overuse_detector_.FrameSent(encoded_image._timeStamp); | 506 int64_t time_sent = clock_->TimeInMilliseconds(); | 
| 507 uint32_t timestamp = encoded_image._timeStamp; | |
| 508 encoder_queue_.PostTask([this, timestamp, time_sent] { | |
| 509 RTC_DCHECK_RUN_ON(&encoder_queue_); | |
| 510 overuse_detector_.FrameSent(timestamp, time_sent); | |
| 511 }); | |
| 502 return result; | 512 return result; | 
| 503 } | 513 } | 
| 504 | 514 | 
| 505 void ViEEncoder::SendStatistics(uint32_t bit_rate, | 515 void ViEEncoder::SendStatistics(uint32_t bit_rate, | 
| 506 uint32_t frame_rate, | 516 uint32_t frame_rate, | 
| 507 const std::string& encoder_name) { | 517 const std::string& encoder_name) { | 
| 508 RTC_DCHECK(module_process_thread_checker_.CalledOnValidThread()); | 518 RTC_DCHECK(module_process_thread_checker_.CalledOnValidThread()); | 
| 509 if (stats_proxy_) | 519 if (stats_proxy_) | 
| 510 stats_proxy_->OnEncoderStatsUpdate(frame_rate, bit_rate, encoder_name); | 520 stats_proxy_->OnEncoderStatsUpdate(frame_rate, bit_rate, encoder_name); | 
| 511 } | 521 } | 
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 570 last_observed_bitrate_bps_ = bitrate_bps; | 580 last_observed_bitrate_bps_ = bitrate_bps; | 
| 571 | 581 | 
| 572 if (stats_proxy_ && video_suspension_changed) { | 582 if (stats_proxy_ && video_suspension_changed) { | 
| 573 LOG(LS_INFO) << "Video suspend state changed to: " | 583 LOG(LS_INFO) << "Video suspend state changed to: " | 
| 574 << (video_is_suspended ? "suspended" : "not suspended"); | 584 << (video_is_suspended ? "suspended" : "not suspended"); | 
| 575 stats_proxy_->OnSuspendChange(video_is_suspended); | 585 stats_proxy_->OnSuspendChange(video_is_suspended); | 
| 576 } | 586 } | 
| 577 } | 587 } | 
| 578 | 588 | 
| 579 void ViEEncoder::OveruseDetected() { | 589 void ViEEncoder::OveruseDetected() { | 
| 580 RTC_DCHECK_RUN_ON(&module_process_thread_checker_); | 590 RTC_DCHECK_RUN_ON(&encoder_queue_); | 
| 581 // TODO(perkj): When ViEEncoder inherit rtc::VideoSink instead of | 591 // TODO(perkj): When ViEEncoder inherit rtc::VideoSink instead of | 
| 582 // VideoCaptureInput |load_observer_| should be removed and overuse be | 592 // VideoCaptureInput |load_observer_| should be removed and overuse be | 
| 583 // expressed as rtc::VideoSinkWants instead. | 593 // expressed as rtc::VideoSinkWants instead. | 
| 584 if (load_observer_) | 594 if (load_observer_) | 
| 585 load_observer_->OnLoadUpdate(LoadObserver::kOveruse); | 595 load_observer_->OnLoadUpdate(LoadObserver::kOveruse); | 
| 586 } | 596 } | 
| 587 | 597 | 
| 588 void ViEEncoder::NormalUsage() { | 598 void ViEEncoder::NormalUsage() { | 
| 589 RTC_DCHECK_RUN_ON(&module_process_thread_checker_); | 599 RTC_DCHECK_RUN_ON(&encoder_queue_); | 
| 590 if (load_observer_) | 600 if (load_observer_) | 
| 591 load_observer_->OnLoadUpdate(LoadObserver::kUnderuse); | 601 load_observer_->OnLoadUpdate(LoadObserver::kUnderuse); | 
| 592 } | 602 } | 
| 593 | 603 | 
| 594 } // namespace webrtc | 604 } // namespace webrtc | 
| OLD | NEW |