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