Chromium Code Reviews| 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 |