| 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 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 223 wants.max_pixel_count = std::numeric_limits<int>::max(); | 223 wants.max_pixel_count = std::numeric_limits<int>::max(); |
| 224 wants.target_pixel_count.reset(); | 224 wants.target_pixel_count.reset(); |
| 225 wants.max_framerate_fps = std::numeric_limits<int>::max(); | 225 wants.max_framerate_fps = std::numeric_limits<int>::max(); |
| 226 } | 226 } |
| 227 return wants; | 227 return wants; |
| 228 } | 228 } |
| 229 | 229 |
| 230 bool RequestResolutionLowerThan(int pixel_count) { | 230 bool RequestResolutionLowerThan(int pixel_count) { |
| 231 // Called on the encoder task queue. | 231 // Called on the encoder task queue. |
| 232 rtc::CritScope lock(&crit_); | 232 rtc::CritScope lock(&crit_); |
| 233 if (!IsResolutionScalingEnabledLocked()) { | 233 if (!IsResolutionScalingEnabled(degradation_preference_)) { |
| 234 // This can happen since |degradation_preference_| is set on libjingle's | 234 // This can happen since |degradation_preference_| is set on libjingle's |
| 235 // worker thread but the adaptation is done on the encoder task queue. | 235 // worker thread but the adaptation is done on the encoder task queue. |
| 236 return false; | 236 return false; |
| 237 } | 237 } |
| 238 // The input video frame size will have a resolution with less than or | 238 // The input video frame size will have a resolution with less than or |
| 239 // equal to |max_pixel_count| depending on how the source can scale the | 239 // equal to |max_pixel_count| depending on how the source can scale the |
| 240 // input frame size. | 240 // input frame size. |
| 241 const int pixels_wanted = (pixel_count * 3) / 5; | 241 const int pixels_wanted = (pixel_count * 3) / 5; |
| 242 if (pixels_wanted < kMinPixelsPerFrame) | 242 if (pixels_wanted < kMinPixelsPerFrame) |
| 243 return false; | 243 return false; |
| 244 | 244 |
| 245 sink_wants_.max_pixel_count = pixels_wanted; | 245 sink_wants_.max_pixel_count = pixels_wanted; |
| 246 sink_wants_.target_pixel_count = rtc::Optional<int>(); | 246 sink_wants_.target_pixel_count = rtc::Optional<int>(); |
| 247 if (source_) | 247 if (source_) |
| 248 source_->AddOrUpdateSink(vie_encoder_, GetActiveSinkWants()); | 248 source_->AddOrUpdateSink(vie_encoder_, GetActiveSinkWants()); |
| 249 return true; | 249 return true; |
| 250 } | 250 } |
| 251 | 251 |
| 252 void RequestFramerateLowerThan(int framerate_fps) { | 252 void RequestFramerateLowerThan(int framerate_fps) { |
| 253 // Called on the encoder task queue. | 253 // Called on the encoder task queue. |
| 254 rtc::CritScope lock(&crit_); | 254 rtc::CritScope lock(&crit_); |
| 255 if (!IsFramerateScalingEnabledLocked()) { | 255 if (!IsFramerateScalingEnabled(degradation_preference_)) { |
| 256 // This can happen since |degradation_preference_| is set on libjingle's | 256 // This can happen since |degradation_preference_| is set on libjingle's |
| 257 // worker thread but the adaptation is done on the encoder task queue. | 257 // worker thread but the adaptation is done on the encoder task queue. |
| 258 return; | 258 return; |
| 259 } | 259 } |
| 260 // The input video frame rate will be scaled down to 2/3 of input fps, | 260 // The input video frame rate will be scaled down to 2/3 of input fps, |
| 261 // rounding down. | 261 // rounding down. |
| 262 const int framerate_wanted = | 262 const int framerate_wanted = |
| 263 std::max(kMinFramerateFps, (framerate_fps * 2) / 3); | 263 std::max(kMinFramerateFps, (framerate_fps * 2) / 3); |
| 264 sink_wants_.max_framerate_fps = framerate_wanted; | 264 sink_wants_.max_framerate_fps = framerate_wanted; |
| 265 if (source_) | 265 if (source_) |
| 266 source_->AddOrUpdateSink(vie_encoder_, GetActiveSinkWants()); | 266 source_->AddOrUpdateSink(vie_encoder_, GetActiveSinkWants()); |
| 267 } | 267 } |
| 268 | 268 |
| 269 void RequestHigherResolutionThan(int pixel_count) { | 269 void RequestHigherResolutionThan(int pixel_count) { |
| 270 rtc::CritScope lock(&crit_); | 270 rtc::CritScope lock(&crit_); |
| 271 if (!IsResolutionScalingEnabledLocked()) { | 271 if (!IsResolutionScalingEnabled(degradation_preference_)) { |
| 272 // This can happen since |degradation_preference_| is set on libjingle's | 272 // This can happen since |degradation_preference_| is set on libjingle's |
| 273 // worker thread but the adaptation is done on the encoder task queue. | 273 // worker thread but the adaptation is done on the encoder task queue. |
| 274 return; | 274 return; |
| 275 } | 275 } |
| 276 | 276 |
| 277 if (pixel_count == std::numeric_limits<int>::max()) { | 277 if (pixel_count == std::numeric_limits<int>::max()) { |
| 278 // Remove any constraints. | 278 // Remove any constraints. |
| 279 sink_wants_.target_pixel_count.reset(); | 279 sink_wants_.target_pixel_count.reset(); |
| 280 sink_wants_.max_pixel_count = std::numeric_limits<int>::max(); | 280 sink_wants_.max_pixel_count = std::numeric_limits<int>::max(); |
| 281 } else { | 281 } else { |
| 282 // On step down we request at most 3/5 the pixel count of the previous | 282 // On step down we request at most 3/5 the pixel count of the previous |
| 283 // resolution, so in order to take "one step up" we request a resolution | 283 // resolution, so in order to take "one step up" we request a resolution |
| 284 // as close as possible to 5/3 of the current resolution. The actual pixel | 284 // as close as possible to 5/3 of the current resolution. The actual pixel |
| 285 // count selected depends on the capabilities of the source. In order to | 285 // count selected depends on the capabilities of the source. In order to |
| 286 // not take a too large step up, we cap the requested pixel count to be at | 286 // not take a too large step up, we cap the requested pixel count to be at |
| 287 // most four time the current number of pixels. | 287 // most four time the current number of pixels. |
| 288 sink_wants_.target_pixel_count = | 288 sink_wants_.target_pixel_count = |
| 289 rtc::Optional<int>((pixel_count * 5) / 3); | 289 rtc::Optional<int>((pixel_count * 5) / 3); |
| 290 sink_wants_.max_pixel_count = pixel_count * 4; | 290 sink_wants_.max_pixel_count = pixel_count * 4; |
| 291 } | 291 } |
| 292 if (source_) | 292 if (source_) |
| 293 source_->AddOrUpdateSink(vie_encoder_, GetActiveSinkWants()); | 293 source_->AddOrUpdateSink(vie_encoder_, GetActiveSinkWants()); |
| 294 } | 294 } |
| 295 | 295 |
| 296 void RequestHigherFramerateThan(int framerate_fps) { | 296 void RequestHigherFramerateThan(int framerate_fps) { |
| 297 // Called on the encoder task queue. | 297 // Called on the encoder task queue. |
| 298 rtc::CritScope lock(&crit_); | 298 rtc::CritScope lock(&crit_); |
| 299 if (!IsFramerateScalingEnabledLocked()) { | 299 if (!IsFramerateScalingEnabled(degradation_preference_)) { |
| 300 // This can happen since |degradation_preference_| is set on libjingle's | 300 // This can happen since |degradation_preference_| is set on libjingle's |
| 301 // worker thread but the adaptation is done on the encoder task queue. | 301 // worker thread but the adaptation is done on the encoder task queue. |
| 302 return; | 302 return; |
| 303 } | 303 } |
| 304 if (framerate_fps == std::numeric_limits<int>::max()) { | 304 if (framerate_fps == std::numeric_limits<int>::max()) { |
| 305 // Remove any restrains. | 305 // Remove any restrains. |
| 306 sink_wants_.max_framerate_fps = std::numeric_limits<int>::max(); | 306 sink_wants_.max_framerate_fps = std::numeric_limits<int>::max(); |
| 307 } else { | 307 } else { |
| 308 // The input video frame rate will be scaled up to the last step, with | 308 // The input video frame rate will be scaled up to the last step, with |
| 309 // rounding. | 309 // rounding. |
| 310 const int framerate_wanted = (framerate_fps * 3) / 2; | 310 const int framerate_wanted = (framerate_fps * 3) / 2; |
| 311 sink_wants_.max_framerate_fps = framerate_wanted; | 311 sink_wants_.max_framerate_fps = framerate_wanted; |
| 312 } | 312 } |
| 313 if (source_) | 313 if (source_) |
| 314 source_->AddOrUpdateSink(vie_encoder_, GetActiveSinkWants()); | 314 source_->AddOrUpdateSink(vie_encoder_, GetActiveSinkWants()); |
| 315 } | 315 } |
| 316 | 316 |
| 317 private: | 317 private: |
| 318 bool IsResolutionScalingEnabledLocked() const | |
| 319 EXCLUSIVE_LOCKS_REQUIRED(&crit_) { | |
| 320 return degradation_preference_ == | |
| 321 VideoSendStream::DegradationPreference::kMaintainFramerate || | |
| 322 degradation_preference_ == | |
| 323 VideoSendStream::DegradationPreference::kBalanced; | |
| 324 } | |
| 325 | |
| 326 bool IsFramerateScalingEnabledLocked() const | |
| 327 EXCLUSIVE_LOCKS_REQUIRED(&crit_) { | |
| 328 // TODO(sprang): Also accept kBalanced here? | |
| 329 return degradation_preference_ == | |
| 330 VideoSendStream::DegradationPreference::kMaintainResolution; | |
| 331 } | |
| 332 | |
| 333 rtc::CriticalSection crit_; | 318 rtc::CriticalSection crit_; |
| 334 rtc::SequencedTaskChecker main_checker_; | 319 rtc::SequencedTaskChecker main_checker_; |
| 335 ViEEncoder* const vie_encoder_; | 320 ViEEncoder* const vie_encoder_; |
| 336 rtc::VideoSinkWants sink_wants_ GUARDED_BY(&crit_); | 321 rtc::VideoSinkWants sink_wants_ GUARDED_BY(&crit_); |
| 337 VideoSendStream::DegradationPreference degradation_preference_ | 322 VideoSendStream::DegradationPreference degradation_preference_ |
| 338 GUARDED_BY(&crit_); | 323 GUARDED_BY(&crit_); |
| 339 rtc::VideoSourceInterface<VideoFrame>* source_ GUARDED_BY(&crit_); | 324 rtc::VideoSourceInterface<VideoFrame>* source_ GUARDED_BY(&crit_); |
| 340 | 325 |
| 341 RTC_DISALLOW_COPY_AND_ASSIGN(VideoSourceProxy); | 326 RTC_DISALLOW_COPY_AND_ASSIGN(VideoSourceProxy); |
| 342 }; | 327 }; |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 440 RTC_DCHECK_RUN_ON(&thread_checker_); | 425 RTC_DCHECK_RUN_ON(&thread_checker_); |
| 441 source_proxy_->SetSource(source, degradation_preference); | 426 source_proxy_->SetSource(source, degradation_preference); |
| 442 encoder_queue_.PostTask([this, degradation_preference] { | 427 encoder_queue_.PostTask([this, degradation_preference] { |
| 443 RTC_DCHECK_RUN_ON(&encoder_queue_); | 428 RTC_DCHECK_RUN_ON(&encoder_queue_); |
| 444 if (degradation_preference_ != degradation_preference) { | 429 if (degradation_preference_ != degradation_preference) { |
| 445 // Reset adaptation state, so that we're not tricked into thinking there's | 430 // Reset adaptation state, so that we're not tricked into thinking there's |
| 446 // an already pending request of the same type. | 431 // an already pending request of the same type. |
| 447 last_adaptation_request_.reset(); | 432 last_adaptation_request_.reset(); |
| 448 } | 433 } |
| 449 degradation_preference_ = degradation_preference; | 434 degradation_preference_ = degradation_preference; |
| 450 bool allow_scaling = | 435 bool allow_scaling = IsResolutionScalingEnabled(degradation_preference_); |
| 451 degradation_preference_ == | |
| 452 VideoSendStream::DegradationPreference::kMaintainFramerate || | |
| 453 degradation_preference_ == | |
| 454 VideoSendStream::DegradationPreference::kBalanced; | |
| 455 initial_rampup_ = allow_scaling ? 0 : kMaxInitialFramedrop; | 436 initial_rampup_ = allow_scaling ? 0 : kMaxInitialFramedrop; |
| 456 ConfigureQualityScaler(); | 437 ConfigureQualityScaler(); |
| 457 }); | 438 }); |
| 458 } | 439 } |
| 459 | 440 |
| 460 void ViEEncoder::SetSink(EncoderSink* sink, bool rotation_applied) { | 441 void ViEEncoder::SetSink(EncoderSink* sink, bool rotation_applied) { |
| 461 source_proxy_->SetWantsRotationApplied(rotation_applied); | 442 source_proxy_->SetWantsRotationApplied(rotation_applied); |
| 462 encoder_queue_.PostTask([this, sink] { | 443 encoder_queue_.PostTask([this, sink] { |
| 463 RTC_DCHECK_RUN_ON(&encoder_queue_); | 444 RTC_DCHECK_RUN_ON(&encoder_queue_); |
| 464 sink_ = sink; | 445 sink_ = sink; |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 547 | 528 |
| 548 sink_->OnEncoderConfigurationChanged( | 529 sink_->OnEncoderConfigurationChanged( |
| 549 std::move(streams), encoder_config_.min_transmit_bitrate_bps); | 530 std::move(streams), encoder_config_.min_transmit_bitrate_bps); |
| 550 | 531 |
| 551 ConfigureQualityScaler(); | 532 ConfigureQualityScaler(); |
| 552 } | 533 } |
| 553 | 534 |
| 554 void ViEEncoder::ConfigureQualityScaler() { | 535 void ViEEncoder::ConfigureQualityScaler() { |
| 555 RTC_DCHECK_RUN_ON(&encoder_queue_); | 536 RTC_DCHECK_RUN_ON(&encoder_queue_); |
| 556 const auto scaling_settings = settings_.encoder->GetScalingSettings(); | 537 const auto scaling_settings = settings_.encoder->GetScalingSettings(); |
| 557 const bool degradation_preference_allows_scaling = | |
| 558 degradation_preference_ == | |
| 559 VideoSendStream::DegradationPreference::kMaintainFramerate || | |
| 560 degradation_preference_ == | |
| 561 VideoSendStream::DegradationPreference::kBalanced; | |
| 562 const bool quality_scaling_allowed = | 538 const bool quality_scaling_allowed = |
| 563 degradation_preference_allows_scaling && scaling_settings.enabled; | 539 IsResolutionScalingEnabled(degradation_preference_) && |
| 540 scaling_settings.enabled; |
| 564 | 541 |
| 565 if (quality_scaling_allowed) { | 542 if (quality_scaling_allowed) { |
| 566 if (quality_scaler_.get() == nullptr) { | 543 if (quality_scaler_.get() == nullptr) { |
| 567 // Quality scaler has not already been configured. | 544 // Quality scaler has not already been configured. |
| 568 // Drop frames and scale down until desired quality is achieved. | 545 // Drop frames and scale down until desired quality is achieved. |
| 569 if (scaling_settings.thresholds) { | 546 if (scaling_settings.thresholds) { |
| 570 quality_scaler_.reset( | 547 quality_scaler_.reset( |
| 571 new QualityScaler(this, *(scaling_settings.thresholds))); | 548 new QualityScaler(this, *(scaling_settings.thresholds))); |
| 572 } else { | 549 } else { |
| 573 quality_scaler_.reset(new QualityScaler(this, codec_type_)); | 550 quality_scaler_.reset(new QualityScaler(this, codec_type_)); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 638 return last_observed_bitrate_bps_ == 0; | 615 return last_observed_bitrate_bps_ == 0; |
| 639 } | 616 } |
| 640 | 617 |
| 641 void ViEEncoder::TraceFrameDropStart() { | 618 void ViEEncoder::TraceFrameDropStart() { |
| 642 RTC_DCHECK_RUN_ON(&encoder_queue_); | 619 RTC_DCHECK_RUN_ON(&encoder_queue_); |
| 643 // Start trace event only on the first frame after encoder is paused. | 620 // Start trace event only on the first frame after encoder is paused. |
| 644 if (!encoder_paused_and_dropped_frame_) { | 621 if (!encoder_paused_and_dropped_frame_) { |
| 645 TRACE_EVENT_ASYNC_BEGIN0("webrtc", "EncoderPaused", this); | 622 TRACE_EVENT_ASYNC_BEGIN0("webrtc", "EncoderPaused", this); |
| 646 } | 623 } |
| 647 encoder_paused_and_dropped_frame_ = true; | 624 encoder_paused_and_dropped_frame_ = true; |
| 648 return; | |
| 649 } | 625 } |
| 650 | 626 |
| 651 void ViEEncoder::TraceFrameDropEnd() { | 627 void ViEEncoder::TraceFrameDropEnd() { |
| 652 RTC_DCHECK_RUN_ON(&encoder_queue_); | 628 RTC_DCHECK_RUN_ON(&encoder_queue_); |
| 653 // End trace event on first frame after encoder resumes, if frame was dropped. | 629 // End trace event on first frame after encoder resumes, if frame was dropped. |
| 654 if (encoder_paused_and_dropped_frame_) { | 630 if (encoder_paused_and_dropped_frame_) { |
| 655 TRACE_EVENT_ASYNC_END0("webrtc", "EncoderPaused", this); | 631 TRACE_EVENT_ASYNC_END0("webrtc", "EncoderPaused", this); |
| 656 } | 632 } |
| 657 encoder_paused_and_dropped_frame_ = false; | 633 encoder_paused_and_dropped_frame_ = false; |
| 658 } | 634 } |
| (...skipping 401 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1060 std::string ViEEncoder::AdaptCounter::ToString( | 1036 std::string ViEEncoder::AdaptCounter::ToString( |
| 1061 const std::vector<int>& counters) const { | 1037 const std::vector<int>& counters) const { |
| 1062 std::stringstream ss; | 1038 std::stringstream ss; |
| 1063 for (size_t reason = 0; reason < kScaleReasonSize; ++reason) { | 1039 for (size_t reason = 0; reason < kScaleReasonSize; ++reason) { |
| 1064 ss << (reason ? " cpu" : "quality") << ":" << counters[reason]; | 1040 ss << (reason ? " cpu" : "quality") << ":" << counters[reason]; |
| 1065 } | 1041 } |
| 1066 return ss.str(); | 1042 return ss.str(); |
| 1067 } | 1043 } |
| 1068 | 1044 |
| 1069 } // namespace webrtc | 1045 } // namespace webrtc |
| OLD | NEW |