| 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 26 matching lines...) Expand all Loading... |
| 37 | 37 |
| 38 // Time interval for logging frame counts. | 38 // Time interval for logging frame counts. |
| 39 const int64_t kFrameLogIntervalMs = 60000; | 39 const int64_t kFrameLogIntervalMs = 60000; |
| 40 | 40 |
| 41 // We will never ask for a resolution lower than this. | 41 // We will never ask for a resolution lower than this. |
| 42 // TODO(kthelgason): Lower this limit when better testing | 42 // TODO(kthelgason): Lower this limit when better testing |
| 43 // on MediaCodec and fallback implementations are in place. | 43 // on MediaCodec and fallback implementations are in place. |
| 44 // See https://bugs.chromium.org/p/webrtc/issues/detail?id=7206 | 44 // See https://bugs.chromium.org/p/webrtc/issues/detail?id=7206 |
| 45 const int kMinPixelsPerFrame = 320 * 180; | 45 const int kMinPixelsPerFrame = 320 * 180; |
| 46 const int kMinFramerateFps = 2; | 46 const int kMinFramerateFps = 2; |
| 47 const int kMaxFramerateFps = 120; |
| 47 | 48 |
| 48 // The maximum number of frames to drop at beginning of stream | 49 // The maximum number of frames to drop at beginning of stream |
| 49 // to try and achieve desired bitrate. | 50 // to try and achieve desired bitrate. |
| 50 const int kMaxInitialFramedrop = 4; | 51 const int kMaxInitialFramedrop = 4; |
| 51 | 52 |
| 52 // TODO(pbos): Lower these thresholds (to closer to 100%) when we handle | |
| 53 // pipelining encoders better (multiple input frames before something comes | |
| 54 // out). This should effectively turn off CPU adaptations for systems that | |
| 55 // remotely cope with the load right now. | |
| 56 CpuOveruseOptions GetCpuOveruseOptions(bool full_overuse_time) { | |
| 57 CpuOveruseOptions options; | |
| 58 if (full_overuse_time) { | |
| 59 options.low_encode_usage_threshold_percent = 150; | |
| 60 options.high_encode_usage_threshold_percent = 200; | |
| 61 } | |
| 62 return options; | |
| 63 } | |
| 64 | |
| 65 uint32_t MaximumFrameSizeForBitrate(uint32_t kbps) { | 53 uint32_t MaximumFrameSizeForBitrate(uint32_t kbps) { |
| 66 if (kbps > 0) { | 54 if (kbps > 0) { |
| 67 if (kbps < 300 /* qvga */) { | 55 if (kbps < 300 /* qvga */) { |
| 68 return 320 * 240; | 56 return 320 * 240; |
| 69 } else if (kbps < 500 /* vga */) { | 57 } else if (kbps < 500 /* vga */) { |
| 70 return 640 * 480; | 58 return 640 * 480; |
| 71 } | 59 } |
| 72 } | 60 } |
| 73 return std::numeric_limits<uint32_t>::max(); | 61 return std::numeric_limits<uint32_t>::max(); |
| 74 } | 62 } |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 200 const VideoSendStream::DegradationPreference& degradation_preference) { | 188 const VideoSendStream::DegradationPreference& degradation_preference) { |
| 201 // Called on libjingle's worker thread. | 189 // Called on libjingle's worker thread. |
| 202 RTC_DCHECK_CALLED_SEQUENTIALLY(&main_checker_); | 190 RTC_DCHECK_CALLED_SEQUENTIALLY(&main_checker_); |
| 203 rtc::VideoSourceInterface<VideoFrame>* old_source = nullptr; | 191 rtc::VideoSourceInterface<VideoFrame>* old_source = nullptr; |
| 204 rtc::VideoSinkWants wants; | 192 rtc::VideoSinkWants wants; |
| 205 { | 193 { |
| 206 rtc::CritScope lock(&crit_); | 194 rtc::CritScope lock(&crit_); |
| 207 degradation_preference_ = degradation_preference; | 195 degradation_preference_ = degradation_preference; |
| 208 old_source = source_; | 196 old_source = source_; |
| 209 source_ = source; | 197 source_ = source; |
| 210 wants = GetActiveSinkWants(); | 198 wants = GetActiveSinkWantsInternal(); |
| 211 } | 199 } |
| 212 | 200 |
| 213 if (old_source != source && old_source != nullptr) { | 201 if (old_source != source && old_source != nullptr) { |
| 214 old_source->RemoveSink(vie_encoder_); | 202 old_source->RemoveSink(vie_encoder_); |
| 215 } | 203 } |
| 216 | 204 |
| 217 if (!source) { | 205 if (!source) { |
| 218 return; | 206 return; |
| 219 } | 207 } |
| 220 | 208 |
| 221 source->AddOrUpdateSink(vie_encoder_, wants); | 209 source->AddOrUpdateSink(vie_encoder_, wants); |
| 222 } | 210 } |
| 223 | 211 |
| 224 void SetWantsRotationApplied(bool rotation_applied) { | 212 void SetWantsRotationApplied(bool rotation_applied) { |
| 225 rtc::CritScope lock(&crit_); | 213 rtc::CritScope lock(&crit_); |
| 226 sink_wants_.rotation_applied = rotation_applied; | 214 sink_wants_.rotation_applied = rotation_applied; |
| 227 if (source_) | 215 if (source_) |
| 228 source_->AddOrUpdateSink(vie_encoder_, sink_wants_); | 216 source_->AddOrUpdateSink(vie_encoder_, sink_wants_); |
| 229 } | 217 } |
| 230 | 218 |
| 231 rtc::VideoSinkWants GetActiveSinkWants() EXCLUSIVE_LOCKS_REQUIRED(&crit_) { | 219 rtc::VideoSinkWants GetActiveSinkWants() { |
| 232 rtc::VideoSinkWants wants = sink_wants_; | 220 rtc::CritScope lock(&crit_); |
| 233 // Clear any constraints from the current sink wants that don't apply to | 221 return GetActiveSinkWantsInternal(); |
| 234 // the used degradation_preference. | |
| 235 switch (degradation_preference_) { | |
| 236 case VideoSendStream::DegradationPreference::kBalanced: | |
| 237 break; | |
| 238 case VideoSendStream::DegradationPreference::kMaintainFramerate: | |
| 239 wants.max_framerate_fps = std::numeric_limits<int>::max(); | |
| 240 break; | |
| 241 case VideoSendStream::DegradationPreference::kMaintainResolution: | |
| 242 wants.max_pixel_count = std::numeric_limits<int>::max(); | |
| 243 wants.target_pixel_count.reset(); | |
| 244 break; | |
| 245 case VideoSendStream::DegradationPreference::kDegradationDisabled: | |
| 246 wants.max_pixel_count = std::numeric_limits<int>::max(); | |
| 247 wants.target_pixel_count.reset(); | |
| 248 wants.max_framerate_fps = std::numeric_limits<int>::max(); | |
| 249 } | |
| 250 return wants; | |
| 251 } | 222 } |
| 252 | 223 |
| 253 void ResetPixelFpsCount() { | 224 void ResetPixelFpsCount() { |
| 254 rtc::CritScope lock(&crit_); | 225 rtc::CritScope lock(&crit_); |
| 255 sink_wants_.max_pixel_count = std::numeric_limits<int>::max(); | 226 sink_wants_.max_pixel_count = std::numeric_limits<int>::max(); |
| 256 sink_wants_.target_pixel_count.reset(); | 227 sink_wants_.target_pixel_count.reset(); |
| 257 sink_wants_.max_framerate_fps = std::numeric_limits<int>::max(); | 228 sink_wants_.max_framerate_fps = std::numeric_limits<int>::max(); |
| 258 if (source_) | 229 if (source_) |
| 259 source_->AddOrUpdateSink(vie_encoder_, sink_wants_); | 230 source_->AddOrUpdateSink(vie_encoder_, sink_wants_); |
| 260 } | 231 } |
| 261 | 232 |
| 262 bool RequestResolutionLowerThan(int pixel_count) { | 233 bool RequestResolutionLowerThan(int pixel_count) { |
| 263 // Called on the encoder task queue. | 234 // Called on the encoder task queue. |
| 264 rtc::CritScope lock(&crit_); | 235 rtc::CritScope lock(&crit_); |
| 265 if (!source_ || !IsResolutionScalingEnabled(degradation_preference_)) { | 236 if (!source_ || !IsResolutionScalingEnabled(degradation_preference_)) { |
| 266 // This can happen since |degradation_preference_| is set on libjingle's | 237 // This can happen since |degradation_preference_| is set on libjingle's |
| 267 // worker thread but the adaptation is done on the encoder task queue. | 238 // worker thread but the adaptation is done on the encoder task queue. |
| 268 return false; | 239 return false; |
| 269 } | 240 } |
| 270 // The input video frame size will have a resolution less than or equal to | 241 // The input video frame size will have a resolution less than or equal to |
| 271 // |max_pixel_count| depending on how the source can scale the frame size. | 242 // |max_pixel_count| depending on how the source can scale the frame size. |
| 272 const int pixels_wanted = (pixel_count * 3) / 5; | 243 const int pixels_wanted = (pixel_count * 3) / 5; |
| 273 if (pixels_wanted < kMinPixelsPerFrame || | 244 if (pixels_wanted < kMinPixelsPerFrame || |
| 274 pixels_wanted >= sink_wants_.max_pixel_count) { | 245 pixels_wanted >= sink_wants_.max_pixel_count) { |
| 275 return false; | 246 return false; |
| 276 } | 247 } |
| 277 LOG(LS_INFO) << "Scaling down resolution, max pixels: " << pixels_wanted; | 248 LOG(LS_INFO) << "Scaling down resolution, max pixels: " << pixels_wanted; |
| 278 sink_wants_.max_pixel_count = pixels_wanted; | 249 sink_wants_.max_pixel_count = pixels_wanted; |
| 279 sink_wants_.target_pixel_count = rtc::Optional<int>(); | 250 sink_wants_.target_pixel_count = rtc::Optional<int>(); |
| 280 source_->AddOrUpdateSink(vie_encoder_, GetActiveSinkWants()); | 251 source_->AddOrUpdateSink(vie_encoder_, GetActiveSinkWantsInternal()); |
| 281 return true; | 252 return true; |
| 282 } | 253 } |
| 283 | 254 |
| 284 bool RequestFramerateLowerThan(int fps) { | 255 int RequestFramerateLowerThan(int fps) { |
| 285 // Called on the encoder task queue. | 256 // Called on the encoder task queue. |
| 286 // The input video frame rate will be scaled down to 2/3, rounding down. | 257 // The input video frame rate will be scaled down to 2/3, rounding down. |
| 287 return RestrictFramerate((fps * 2) / 3); | 258 int framerate_wanted = (fps * 2) / 3; |
| 259 return RestrictFramerate(framerate_wanted) ? framerate_wanted : -1; |
| 288 } | 260 } |
| 289 | 261 |
| 290 bool RequestHigherResolutionThan(int pixel_count) { | 262 bool RequestHigherResolutionThan(int pixel_count) { |
| 291 // Called on the encoder task queue. | 263 // Called on the encoder task queue. |
| 292 rtc::CritScope lock(&crit_); | 264 rtc::CritScope lock(&crit_); |
| 293 if (!source_ || !IsResolutionScalingEnabled(degradation_preference_)) { | 265 if (!source_ || !IsResolutionScalingEnabled(degradation_preference_)) { |
| 294 // This can happen since |degradation_preference_| is set on libjingle's | 266 // This can happen since |degradation_preference_| is set on libjingle's |
| 295 // worker thread but the adaptation is done on the encoder task queue. | 267 // worker thread but the adaptation is done on the encoder task queue. |
| 296 return false; | 268 return false; |
| 297 } | 269 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 310 // 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 |
| 311 // 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 |
| 312 // 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 |
| 313 // 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 |
| 314 // 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 |
| 315 // most four time the current number of pixels. | 287 // most four time the current number of pixels. |
| 316 sink_wants_.target_pixel_count = | 288 sink_wants_.target_pixel_count = |
| 317 rtc::Optional<int>((pixel_count * 5) / 3); | 289 rtc::Optional<int>((pixel_count * 5) / 3); |
| 318 } | 290 } |
| 319 LOG(LS_INFO) << "Scaling up resolution, max pixels: " << max_pixels_wanted; | 291 LOG(LS_INFO) << "Scaling up resolution, max pixels: " << max_pixels_wanted; |
| 320 source_->AddOrUpdateSink(vie_encoder_, GetActiveSinkWants()); | 292 source_->AddOrUpdateSink(vie_encoder_, GetActiveSinkWantsInternal()); |
| 321 return true; | 293 return true; |
| 322 } | 294 } |
| 323 | 295 |
| 324 bool RequestHigherFramerateThan(int fps) { | 296 // Request upgrade in framerate. Returns the new requested frame, or -1 if |
| 297 // no change requested. Note that maxint may be returned if limits due to |
| 298 // adaptation requests are removed completely. In that case, consider |
| 299 // |max_framerate_| to be the current limit (assuming the capturer complies). |
| 300 int RequestHigherFramerateThan(int fps) { |
| 325 // Called on the encoder task queue. | 301 // Called on the encoder task queue. |
| 326 // The input frame rate will be scaled up to the last step, with rounding. | 302 // The input frame rate will be scaled up to the last step, with rounding. |
| 327 int framerate_wanted = fps; | 303 int framerate_wanted = fps; |
| 328 if (fps != std::numeric_limits<int>::max()) | 304 if (fps != std::numeric_limits<int>::max()) |
| 329 framerate_wanted = (fps * 3) / 2; | 305 framerate_wanted = (fps * 3) / 2; |
| 330 | 306 |
| 331 return IncreaseFramerate(framerate_wanted); | 307 return IncreaseFramerate(framerate_wanted) ? framerate_wanted : -1; |
| 332 } | 308 } |
| 333 | 309 |
| 334 bool RestrictFramerate(int fps) { | 310 bool RestrictFramerate(int fps) { |
| 335 // Called on the encoder task queue. | 311 // Called on the encoder task queue. |
| 336 rtc::CritScope lock(&crit_); | 312 rtc::CritScope lock(&crit_); |
| 337 if (!source_ || !IsFramerateScalingEnabled(degradation_preference_)) | 313 if (!source_ || !IsFramerateScalingEnabled(degradation_preference_)) |
| 338 return false; | 314 return false; |
| 339 | 315 |
| 340 const int fps_wanted = std::max(kMinFramerateFps, fps); | 316 const int fps_wanted = std::max(kMinFramerateFps, fps); |
| 341 if (fps_wanted >= sink_wants_.max_framerate_fps) | 317 if (fps_wanted >= sink_wants_.max_framerate_fps) |
| 342 return false; | 318 return false; |
| 343 | 319 |
| 344 LOG(LS_INFO) << "Scaling down framerate: " << fps_wanted; | 320 LOG(LS_INFO) << "Scaling down framerate: " << fps_wanted; |
| 345 sink_wants_.max_framerate_fps = fps_wanted; | 321 sink_wants_.max_framerate_fps = fps_wanted; |
| 346 source_->AddOrUpdateSink(vie_encoder_, GetActiveSinkWants()); | 322 source_->AddOrUpdateSink(vie_encoder_, GetActiveSinkWantsInternal()); |
| 347 return true; | 323 return true; |
| 348 } | 324 } |
| 349 | 325 |
| 350 bool IncreaseFramerate(int fps) { | 326 bool IncreaseFramerate(int fps) { |
| 351 // Called on the encoder task queue. | 327 // Called on the encoder task queue. |
| 352 rtc::CritScope lock(&crit_); | 328 rtc::CritScope lock(&crit_); |
| 353 if (!source_ || !IsFramerateScalingEnabled(degradation_preference_)) | 329 if (!source_ || !IsFramerateScalingEnabled(degradation_preference_)) |
| 354 return false; | 330 return false; |
| 355 | 331 |
| 356 const int fps_wanted = std::max(kMinFramerateFps, fps); | 332 const int fps_wanted = std::max(kMinFramerateFps, fps); |
| 357 if (fps_wanted <= sink_wants_.max_framerate_fps) | 333 if (fps_wanted <= sink_wants_.max_framerate_fps) |
| 358 return false; | 334 return false; |
| 359 | 335 |
| 360 LOG(LS_INFO) << "Scaling up framerate: " << fps_wanted; | 336 LOG(LS_INFO) << "Scaling up framerate: " << fps_wanted; |
| 361 sink_wants_.max_framerate_fps = fps_wanted; | 337 sink_wants_.max_framerate_fps = fps_wanted; |
| 362 source_->AddOrUpdateSink(vie_encoder_, GetActiveSinkWants()); | 338 source_->AddOrUpdateSink(vie_encoder_, GetActiveSinkWantsInternal()); |
| 363 return true; | 339 return true; |
| 364 } | 340 } |
| 365 | 341 |
| 366 private: | 342 private: |
| 343 rtc::VideoSinkWants GetActiveSinkWantsInternal() |
| 344 EXCLUSIVE_LOCKS_REQUIRED(&crit_) { |
| 345 rtc::VideoSinkWants wants = sink_wants_; |
| 346 // Clear any constraints from the current sink wants that don't apply to |
| 347 // the used degradation_preference. |
| 348 switch (degradation_preference_) { |
| 349 case VideoSendStream::DegradationPreference::kBalanced: |
| 350 break; |
| 351 case VideoSendStream::DegradationPreference::kMaintainFramerate: |
| 352 wants.max_framerate_fps = std::numeric_limits<int>::max(); |
| 353 break; |
| 354 case VideoSendStream::DegradationPreference::kMaintainResolution: |
| 355 wants.max_pixel_count = std::numeric_limits<int>::max(); |
| 356 wants.target_pixel_count.reset(); |
| 357 break; |
| 358 case VideoSendStream::DegradationPreference::kDegradationDisabled: |
| 359 wants.max_pixel_count = std::numeric_limits<int>::max(); |
| 360 wants.target_pixel_count.reset(); |
| 361 wants.max_framerate_fps = std::numeric_limits<int>::max(); |
| 362 } |
| 363 return wants; |
| 364 } |
| 365 |
| 367 rtc::CriticalSection crit_; | 366 rtc::CriticalSection crit_; |
| 368 rtc::SequencedTaskChecker main_checker_; | 367 rtc::SequencedTaskChecker main_checker_; |
| 369 ViEEncoder* const vie_encoder_; | 368 ViEEncoder* const vie_encoder_; |
| 370 rtc::VideoSinkWants sink_wants_ GUARDED_BY(&crit_); | 369 rtc::VideoSinkWants sink_wants_ GUARDED_BY(&crit_); |
| 371 VideoSendStream::DegradationPreference degradation_preference_ | 370 VideoSendStream::DegradationPreference degradation_preference_ |
| 372 GUARDED_BY(&crit_); | 371 GUARDED_BY(&crit_); |
| 373 rtc::VideoSourceInterface<VideoFrame>* source_ GUARDED_BY(&crit_); | 372 rtc::VideoSourceInterface<VideoFrame>* source_ GUARDED_BY(&crit_); |
| 374 | 373 |
| 375 RTC_DISALLOW_COPY_AND_ASSIGN(VideoSourceProxy); | 374 RTC_DISALLOW_COPY_AND_ASSIGN(VideoSourceProxy); |
| 376 }; | 375 }; |
| 377 | 376 |
| 378 ViEEncoder::ViEEncoder(uint32_t number_of_cores, | 377 ViEEncoder::ViEEncoder(uint32_t number_of_cores, |
| 379 SendStatisticsProxy* stats_proxy, | 378 SendStatisticsProxy* stats_proxy, |
| 380 const VideoSendStream::Config::EncoderSettings& settings, | 379 const VideoSendStream::Config::EncoderSettings& settings, |
| 381 rtc::VideoSinkInterface<VideoFrame>* pre_encode_callback, | 380 rtc::VideoSinkInterface<VideoFrame>* pre_encode_callback, |
| 382 EncodedFrameObserver* encoder_timing) | 381 EncodedFrameObserver* encoder_timing, |
| 382 std::unique_ptr<OveruseFrameDetector> overuse_detector) |
| 383 : shutdown_event_(true /* manual_reset */, false), | 383 : shutdown_event_(true /* manual_reset */, false), |
| 384 number_of_cores_(number_of_cores), | 384 number_of_cores_(number_of_cores), |
| 385 initial_rampup_(0), | 385 initial_rampup_(0), |
| 386 source_proxy_(new VideoSourceProxy(this)), | 386 source_proxy_(new VideoSourceProxy(this)), |
| 387 sink_(nullptr), | 387 sink_(nullptr), |
| 388 settings_(settings), | 388 settings_(settings), |
| 389 codec_type_(PayloadNameToCodecType(settings.payload_name) | 389 codec_type_(PayloadNameToCodecType(settings.payload_name) |
| 390 .value_or(VideoCodecType::kVideoCodecUnknown)), | 390 .value_or(VideoCodecType::kVideoCodecUnknown)), |
| 391 video_sender_(Clock::GetRealTimeClock(), this, this), | 391 video_sender_(Clock::GetRealTimeClock(), this, this), |
| 392 overuse_detector_(GetCpuOveruseOptions(settings.full_overuse_time), | 392 overuse_detector_( |
| 393 this, | 393 overuse_detector.get() |
| 394 encoder_timing, | 394 ? overuse_detector.release() |
| 395 stats_proxy), | 395 : new OveruseFrameDetector( |
| 396 GetCpuOveruseOptions(settings.full_overuse_time), |
| 397 this, |
| 398 encoder_timing, |
| 399 stats_proxy)), |
| 396 stats_proxy_(stats_proxy), | 400 stats_proxy_(stats_proxy), |
| 397 pre_encode_callback_(pre_encode_callback), | 401 pre_encode_callback_(pre_encode_callback), |
| 398 module_process_thread_(nullptr), | 402 module_process_thread_(nullptr), |
| 403 max_framerate_(-1), |
| 399 pending_encoder_reconfiguration_(false), | 404 pending_encoder_reconfiguration_(false), |
| 400 encoder_start_bitrate_bps_(0), | 405 encoder_start_bitrate_bps_(0), |
| 401 max_data_payload_length_(0), | 406 max_data_payload_length_(0), |
| 402 nack_enabled_(false), | 407 nack_enabled_(false), |
| 403 last_observed_bitrate_bps_(0), | 408 last_observed_bitrate_bps_(0), |
| 404 encoder_paused_and_dropped_frame_(false), | 409 encoder_paused_and_dropped_frame_(false), |
| 405 clock_(Clock::GetRealTimeClock()), | 410 clock_(Clock::GetRealTimeClock()), |
| 406 degradation_preference_( | 411 degradation_preference_( |
| 407 VideoSendStream::DegradationPreference::kDegradationDisabled), | 412 VideoSendStream::DegradationPreference::kDegradationDisabled), |
| 408 last_captured_timestamp_(0), | 413 last_captured_timestamp_(0), |
| 409 delta_ntp_internal_ms_(clock_->CurrentNtpInMilliseconds() - | 414 delta_ntp_internal_ms_(clock_->CurrentNtpInMilliseconds() - |
| 410 clock_->TimeInMilliseconds()), | 415 clock_->TimeInMilliseconds()), |
| 411 last_frame_log_ms_(clock_->TimeInMilliseconds()), | 416 last_frame_log_ms_(clock_->TimeInMilliseconds()), |
| 412 captured_frame_count_(0), | 417 captured_frame_count_(0), |
| 413 dropped_frame_count_(0), | 418 dropped_frame_count_(0), |
| 414 bitrate_observer_(nullptr), | 419 bitrate_observer_(nullptr), |
| 415 encoder_queue_("EncoderQueue") { | 420 encoder_queue_("EncoderQueue") { |
| 416 RTC_DCHECK(stats_proxy); | 421 RTC_DCHECK(stats_proxy); |
| 417 encoder_queue_.PostTask([this] { | 422 encoder_queue_.PostTask([this] { |
| 418 RTC_DCHECK_RUN_ON(&encoder_queue_); | 423 RTC_DCHECK_RUN_ON(&encoder_queue_); |
| 419 overuse_detector_.StartCheckForOveruse(); | 424 overuse_detector_->StartCheckForOveruse(); |
| 420 video_sender_.RegisterExternalEncoder( | 425 video_sender_.RegisterExternalEncoder( |
| 421 settings_.encoder, settings_.payload_type, settings_.internal_source); | 426 settings_.encoder, settings_.payload_type, settings_.internal_source); |
| 422 }); | 427 }); |
| 423 } | 428 } |
| 424 | 429 |
| 425 ViEEncoder::~ViEEncoder() { | 430 ViEEncoder::~ViEEncoder() { |
| 426 RTC_DCHECK_RUN_ON(&thread_checker_); | 431 RTC_DCHECK_RUN_ON(&thread_checker_); |
| 427 RTC_DCHECK(shutdown_event_.Wait(0)) | 432 RTC_DCHECK(shutdown_event_.Wait(0)) |
| 428 << "Must call ::Stop() before destruction."; | 433 << "Must call ::Stop() before destruction."; |
| 429 } | 434 } |
| 430 | 435 |
| 436 // TODO(pbos): Lower these thresholds (to closer to 100%) when we handle |
| 437 // pipelining encoders better (multiple input frames before something comes |
| 438 // out). This should effectively turn off CPU adaptations for systems that |
| 439 // remotely cope with the load right now. |
| 440 CpuOveruseOptions ViEEncoder::GetCpuOveruseOptions(bool full_overuse_time) { |
| 441 CpuOveruseOptions options; |
| 442 if (full_overuse_time) { |
| 443 options.low_encode_usage_threshold_percent = 150; |
| 444 options.high_encode_usage_threshold_percent = 200; |
| 445 } |
| 446 return options; |
| 447 } |
| 448 |
| 431 void ViEEncoder::Stop() { | 449 void ViEEncoder::Stop() { |
| 432 RTC_DCHECK_RUN_ON(&thread_checker_); | 450 RTC_DCHECK_RUN_ON(&thread_checker_); |
| 433 source_proxy_->SetSource(nullptr, VideoSendStream::DegradationPreference()); | 451 source_proxy_->SetSource(nullptr, VideoSendStream::DegradationPreference()); |
| 434 encoder_queue_.PostTask([this] { | 452 encoder_queue_.PostTask([this] { |
| 435 RTC_DCHECK_RUN_ON(&encoder_queue_); | 453 RTC_DCHECK_RUN_ON(&encoder_queue_); |
| 436 overuse_detector_.StopCheckForOveruse(); | 454 overuse_detector_->StopCheckForOveruse(); |
| 437 rate_allocator_.reset(); | 455 rate_allocator_.reset(); |
| 438 bitrate_observer_ = nullptr; | 456 bitrate_observer_ = nullptr; |
| 439 video_sender_.RegisterExternalEncoder(nullptr, settings_.payload_type, | 457 video_sender_.RegisterExternalEncoder(nullptr, settings_.payload_type, |
| 440 false); | 458 false); |
| 441 quality_scaler_ = nullptr; | 459 quality_scaler_ = nullptr; |
| 442 shutdown_event_.Set(); | 460 shutdown_event_.Set(); |
| 443 }); | 461 }); |
| 444 | 462 |
| 445 shutdown_event_.Wait(rtc::Event::kForever); | 463 shutdown_event_.Wait(rtc::Event::kForever); |
| 446 } | 464 } |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 486 // TODO(asapersson): Consider removing |adapt_counters_| map and use one | 504 // TODO(asapersson): Consider removing |adapt_counters_| map and use one |
| 487 // AdaptCounter for all modes. | 505 // AdaptCounter for all modes. |
| 488 source_proxy_->ResetPixelFpsCount(); | 506 source_proxy_->ResetPixelFpsCount(); |
| 489 adapt_counters_.clear(); | 507 adapt_counters_.clear(); |
| 490 } | 508 } |
| 491 } | 509 } |
| 492 degradation_preference_ = degradation_preference; | 510 degradation_preference_ = degradation_preference; |
| 493 bool allow_scaling = IsResolutionScalingEnabled(degradation_preference_); | 511 bool allow_scaling = IsResolutionScalingEnabled(degradation_preference_); |
| 494 initial_rampup_ = allow_scaling ? 0 : kMaxInitialFramedrop; | 512 initial_rampup_ = allow_scaling ? 0 : kMaxInitialFramedrop; |
| 495 ConfigureQualityScaler(); | 513 ConfigureQualityScaler(); |
| 514 if (!IsFramerateScalingEnabled(degradation_preference) && |
| 515 max_framerate_ != -1) { |
| 516 // If frame rate scaling is no longer allowed, remove any potential |
| 517 // allowance for longer frame intervals. |
| 518 overuse_detector_->OnTargetFramerateUpdated(max_framerate_); |
| 519 } |
| 496 }); | 520 }); |
| 497 } | 521 } |
| 498 | 522 |
| 499 void ViEEncoder::SetSink(EncoderSink* sink, bool rotation_applied) { | 523 void ViEEncoder::SetSink(EncoderSink* sink, bool rotation_applied) { |
| 500 source_proxy_->SetWantsRotationApplied(rotation_applied); | 524 source_proxy_->SetWantsRotationApplied(rotation_applied); |
| 501 encoder_queue_.PostTask([this, sink] { | 525 encoder_queue_.PostTask([this, sink] { |
| 502 RTC_DCHECK_RUN_ON(&encoder_queue_); | 526 RTC_DCHECK_RUN_ON(&encoder_queue_); |
| 503 sink_ = sink; | 527 sink_ = sink; |
| 504 }); | 528 }); |
| 505 } | 529 } |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 555 if (!VideoCodecInitializer::SetupCodec(encoder_config_, settings_, streams, | 579 if (!VideoCodecInitializer::SetupCodec(encoder_config_, settings_, streams, |
| 556 nack_enabled_, &codec, | 580 nack_enabled_, &codec, |
| 557 &rate_allocator_)) { | 581 &rate_allocator_)) { |
| 558 LOG(LS_ERROR) << "Failed to create encoder configuration."; | 582 LOG(LS_ERROR) << "Failed to create encoder configuration."; |
| 559 } | 583 } |
| 560 | 584 |
| 561 codec.startBitrate = | 585 codec.startBitrate = |
| 562 std::max(encoder_start_bitrate_bps_ / 1000, codec.minBitrate); | 586 std::max(encoder_start_bitrate_bps_ / 1000, codec.minBitrate); |
| 563 codec.startBitrate = std::min(codec.startBitrate, codec.maxBitrate); | 587 codec.startBitrate = std::min(codec.startBitrate, codec.maxBitrate); |
| 564 codec.expect_encode_from_texture = last_frame_info_->is_texture; | 588 codec.expect_encode_from_texture = last_frame_info_->is_texture; |
| 589 max_framerate_ = codec.maxFramerate; |
| 590 RTC_DCHECK_LE(max_framerate_, kMaxFramerateFps); |
| 565 | 591 |
| 566 bool success = video_sender_.RegisterSendCodec( | 592 bool success = video_sender_.RegisterSendCodec( |
| 567 &codec, number_of_cores_, | 593 &codec, number_of_cores_, |
| 568 static_cast<uint32_t>(max_data_payload_length_)) == VCM_OK; | 594 static_cast<uint32_t>(max_data_payload_length_)) == VCM_OK; |
| 569 if (!success) { | 595 if (!success) { |
| 570 LOG(LS_ERROR) << "Failed to configure encoder."; | 596 LOG(LS_ERROR) << "Failed to configure encoder."; |
| 571 rate_allocator_.reset(); | 597 rate_allocator_.reset(); |
| 572 } | 598 } |
| 573 | 599 |
| 574 video_sender_.UpdateChannelParemeters(rate_allocator_.get(), | 600 video_sender_.UpdateChannelParemeters(rate_allocator_.get(), |
| 575 bitrate_observer_); | 601 bitrate_observer_); |
| 576 | 602 |
| 577 int framerate = stats_proxy_->GetSendFrameRate(); | 603 // Get the current actual framerate, as measured by the stats proxy. This is |
| 578 if (framerate == 0) | 604 // used to get the correct bitrate layer allocation. |
| 579 framerate = codec.maxFramerate; | 605 int current_framerate = stats_proxy_->GetSendFrameRate(); |
| 606 if (current_framerate == 0) |
| 607 current_framerate = codec.maxFramerate; |
| 580 stats_proxy_->OnEncoderReconfigured( | 608 stats_proxy_->OnEncoderReconfigured( |
| 581 encoder_config_, rate_allocator_.get() | 609 encoder_config_, |
| 582 ? rate_allocator_->GetPreferredBitrateBps(framerate) | 610 rate_allocator_.get() |
| 583 : codec.maxBitrate); | 611 ? rate_allocator_->GetPreferredBitrateBps(current_framerate) |
| 612 : codec.maxBitrate); |
| 584 | 613 |
| 585 pending_encoder_reconfiguration_ = false; | 614 pending_encoder_reconfiguration_ = false; |
| 586 | 615 |
| 587 sink_->OnEncoderConfigurationChanged( | 616 sink_->OnEncoderConfigurationChanged( |
| 588 std::move(streams), encoder_config_.min_transmit_bitrate_bps); | 617 std::move(streams), encoder_config_.min_transmit_bitrate_bps); |
| 589 | 618 |
| 619 // Get the current target framerate, ie the maximum framerate as specified by |
| 620 // the current codec configuration, or any limit imposed by cpu adaption in |
| 621 // maintain-resolution or balanced mode. This is used to make sure overuse |
| 622 // detection doesn't needlessly trigger in low and/or variable framerate |
| 623 // scenarios. |
| 624 int target_framerate = std::min( |
| 625 max_framerate_, source_proxy_->GetActiveSinkWants().max_framerate_fps); |
| 626 overuse_detector_->OnTargetFramerateUpdated(target_framerate); |
| 627 |
| 590 ConfigureQualityScaler(); | 628 ConfigureQualityScaler(); |
| 591 } | 629 } |
| 592 | 630 |
| 593 void ViEEncoder::ConfigureQualityScaler() { | 631 void ViEEncoder::ConfigureQualityScaler() { |
| 594 RTC_DCHECK_RUN_ON(&encoder_queue_); | 632 RTC_DCHECK_RUN_ON(&encoder_queue_); |
| 595 const auto scaling_settings = settings_.encoder->GetScalingSettings(); | 633 const auto scaling_settings = settings_.encoder->GetScalingSettings(); |
| 596 const bool quality_scaling_allowed = | 634 const bool quality_scaling_allowed = |
| 597 IsResolutionScalingEnabled(degradation_preference_) && | 635 IsResolutionScalingEnabled(degradation_preference_) && |
| 598 scaling_settings.enabled; | 636 scaling_settings.enabled; |
| 599 | 637 |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 728 | 766 |
| 729 if (EncoderPaused()) { | 767 if (EncoderPaused()) { |
| 730 TraceFrameDropStart(); | 768 TraceFrameDropStart(); |
| 731 return; | 769 return; |
| 732 } | 770 } |
| 733 TraceFrameDropEnd(); | 771 TraceFrameDropEnd(); |
| 734 | 772 |
| 735 TRACE_EVENT_ASYNC_STEP0("webrtc", "Video", video_frame.render_time_ms(), | 773 TRACE_EVENT_ASYNC_STEP0("webrtc", "Video", video_frame.render_time_ms(), |
| 736 "Encode"); | 774 "Encode"); |
| 737 | 775 |
| 738 overuse_detector_.FrameCaptured(video_frame, time_when_posted_us); | 776 overuse_detector_->FrameCaptured(video_frame, time_when_posted_us); |
| 739 | 777 |
| 740 video_sender_.AddVideoFrame(video_frame, nullptr); | 778 video_sender_.AddVideoFrame(video_frame, nullptr); |
| 741 } | 779 } |
| 742 | 780 |
| 743 void ViEEncoder::SendKeyFrame() { | 781 void ViEEncoder::SendKeyFrame() { |
| 744 if (!encoder_queue_.IsCurrent()) { | 782 if (!encoder_queue_.IsCurrent()) { |
| 745 encoder_queue_.PostTask([this] { SendKeyFrame(); }); | 783 encoder_queue_.PostTask([this] { SendKeyFrame(); }); |
| 746 return; | 784 return; |
| 747 } | 785 } |
| 748 RTC_DCHECK_RUN_ON(&encoder_queue_); | 786 RTC_DCHECK_RUN_ON(&encoder_queue_); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 759 stats_proxy_->OnSendEncodedImage(encoded_image, codec_specific_info); | 797 stats_proxy_->OnSendEncodedImage(encoded_image, codec_specific_info); |
| 760 | 798 |
| 761 EncodedImageCallback::Result result = | 799 EncodedImageCallback::Result result = |
| 762 sink_->OnEncodedImage(encoded_image, codec_specific_info, fragmentation); | 800 sink_->OnEncodedImage(encoded_image, codec_specific_info, fragmentation); |
| 763 | 801 |
| 764 int64_t time_sent_us = rtc::TimeMicros(); | 802 int64_t time_sent_us = rtc::TimeMicros(); |
| 765 uint32_t timestamp = encoded_image._timeStamp; | 803 uint32_t timestamp = encoded_image._timeStamp; |
| 766 const int qp = encoded_image.qp_; | 804 const int qp = encoded_image.qp_; |
| 767 encoder_queue_.PostTask([this, timestamp, time_sent_us, qp] { | 805 encoder_queue_.PostTask([this, timestamp, time_sent_us, qp] { |
| 768 RTC_DCHECK_RUN_ON(&encoder_queue_); | 806 RTC_DCHECK_RUN_ON(&encoder_queue_); |
| 769 overuse_detector_.FrameSent(timestamp, time_sent_us); | 807 overuse_detector_->FrameSent(timestamp, time_sent_us); |
| 770 if (quality_scaler_ && qp >= 0) | 808 if (quality_scaler_ && qp >= 0) |
| 771 quality_scaler_->ReportQP(qp); | 809 quality_scaler_->ReportQP(qp); |
| 772 }); | 810 }); |
| 773 | 811 |
| 774 return result; | 812 return result; |
| 775 } | 813 } |
| 776 | 814 |
| 777 void ViEEncoder::OnDroppedFrame() { | 815 void ViEEncoder::OnDroppedFrame() { |
| 778 encoder_queue_.PostTask([this] { | 816 encoder_queue_.PostTask([this] { |
| 779 RTC_DCHECK_RUN_ON(&encoder_queue_); | 817 RTC_DCHECK_RUN_ON(&encoder_queue_); |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 894 FALLTHROUGH(); | 932 FALLTHROUGH(); |
| 895 } | 933 } |
| 896 case VideoSendStream::DegradationPreference::kMaintainFramerate: | 934 case VideoSendStream::DegradationPreference::kMaintainFramerate: |
| 897 // Scale down resolution. | 935 // Scale down resolution. |
| 898 if (!source_proxy_->RequestResolutionLowerThan( | 936 if (!source_proxy_->RequestResolutionLowerThan( |
| 899 adaptation_request.input_pixel_count_)) { | 937 adaptation_request.input_pixel_count_)) { |
| 900 return; | 938 return; |
| 901 } | 939 } |
| 902 GetAdaptCounter().IncrementResolution(reason); | 940 GetAdaptCounter().IncrementResolution(reason); |
| 903 break; | 941 break; |
| 904 case VideoSendStream::DegradationPreference::kMaintainResolution: | 942 case VideoSendStream::DegradationPreference::kMaintainResolution: { |
| 905 // Scale down framerate. | 943 // Scale down framerate. |
| 906 if (!source_proxy_->RequestFramerateLowerThan( | 944 const int requested_framerate = source_proxy_->RequestFramerateLowerThan( |
| 907 adaptation_request.framerate_fps_)) { | 945 adaptation_request.framerate_fps_); |
| 946 if (requested_framerate == -1) |
| 908 return; | 947 return; |
| 909 } | 948 RTC_DCHECK_NE(max_framerate_, -1); |
| 949 overuse_detector_->OnTargetFramerateUpdated( |
| 950 std::min(max_framerate_, requested_framerate)); |
| 910 GetAdaptCounter().IncrementFramerate(reason); | 951 GetAdaptCounter().IncrementFramerate(reason); |
| 911 break; | 952 break; |
| 953 } |
| 912 case VideoSendStream::DegradationPreference::kDegradationDisabled: | 954 case VideoSendStream::DegradationPreference::kDegradationDisabled: |
| 913 RTC_NOTREACHED(); | 955 RTC_NOTREACHED(); |
| 914 } | 956 } |
| 915 | 957 |
| 916 last_adaptation_request_.emplace(adaptation_request); | 958 last_adaptation_request_.emplace(adaptation_request); |
| 917 | 959 |
| 918 UpdateAdaptationStats(reason); | 960 UpdateAdaptationStats(reason); |
| 919 | 961 |
| 920 LOG(LS_INFO) << GetConstAdaptCounter().ToString(); | 962 LOG(LS_INFO) << GetConstAdaptCounter().ToString(); |
| 921 } | 963 } |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 978 GetAdaptCounter().DecrementResolution(reason); | 1020 GetAdaptCounter().DecrementResolution(reason); |
| 979 break; | 1021 break; |
| 980 } | 1022 } |
| 981 case VideoSendStream::DegradationPreference::kMaintainResolution: { | 1023 case VideoSendStream::DegradationPreference::kMaintainResolution: { |
| 982 // Scale up framerate. | 1024 // Scale up framerate. |
| 983 int fps = adaptation_request.framerate_fps_; | 1025 int fps = adaptation_request.framerate_fps_; |
| 984 if (adapt_counter.FramerateCount() == 1) { | 1026 if (adapt_counter.FramerateCount() == 1) { |
| 985 LOG(LS_INFO) << "Removing framerate down-scaling setting."; | 1027 LOG(LS_INFO) << "Removing framerate down-scaling setting."; |
| 986 fps = std::numeric_limits<int>::max(); | 1028 fps = std::numeric_limits<int>::max(); |
| 987 } | 1029 } |
| 988 if (!source_proxy_->RequestHigherFramerateThan(fps)) | 1030 |
| 1031 const int requested_framerate = |
| 1032 source_proxy_->RequestHigherFramerateThan(fps); |
| 1033 if (requested_framerate == -1) { |
| 1034 overuse_detector_->OnTargetFramerateUpdated(max_framerate_); |
| 989 return; | 1035 return; |
| 1036 } |
| 1037 overuse_detector_->OnTargetFramerateUpdated( |
| 1038 std::min(max_framerate_, requested_framerate)); |
| 990 GetAdaptCounter().DecrementFramerate(reason); | 1039 GetAdaptCounter().DecrementFramerate(reason); |
| 991 break; | 1040 break; |
| 992 } | 1041 } |
| 993 case VideoSendStream::DegradationPreference::kDegradationDisabled: | 1042 case VideoSendStream::DegradationPreference::kDegradationDisabled: |
| 994 return; | 1043 return; |
| 995 } | 1044 } |
| 996 | 1045 |
| 997 last_adaptation_request_.emplace(adaptation_request); | 1046 last_adaptation_request_.emplace(adaptation_request); |
| 998 | 1047 |
| 999 UpdateAdaptationStats(reason); | 1048 UpdateAdaptationStats(reason); |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1146 std::string ViEEncoder::AdaptCounter::ToString( | 1195 std::string ViEEncoder::AdaptCounter::ToString( |
| 1147 const std::vector<int>& counters) const { | 1196 const std::vector<int>& counters) const { |
| 1148 std::stringstream ss; | 1197 std::stringstream ss; |
| 1149 for (size_t reason = 0; reason < kScaleReasonSize; ++reason) { | 1198 for (size_t reason = 0; reason < kScaleReasonSize; ++reason) { |
| 1150 ss << (reason ? " cpu" : "quality") << ":" << counters[reason]; | 1199 ss << (reason ? " cpu" : "quality") << ":" << counters[reason]; |
| 1151 } | 1200 } |
| 1152 return ss.str(); | 1201 return ss.str(); |
| 1153 } | 1202 } |
| 1154 | 1203 |
| 1155 } // namespace webrtc | 1204 } // namespace webrtc |
| OLD | NEW |