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 |