| 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 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 156 | 156 |
| 157 void SetSource(rtc::VideoSourceInterface<VideoFrame>* source, | 157 void SetSource(rtc::VideoSourceInterface<VideoFrame>* source, |
| 158 const DegradationPreference& degradation_preference) { | 158 const DegradationPreference& degradation_preference) { |
| 159 // Called on libjingle's worker thread. | 159 // Called on libjingle's worker thread. |
| 160 RTC_DCHECK_CALLED_SEQUENTIALLY(&main_checker_); | 160 RTC_DCHECK_CALLED_SEQUENTIALLY(&main_checker_); |
| 161 rtc::VideoSourceInterface<VideoFrame>* old_source = nullptr; | 161 rtc::VideoSourceInterface<VideoFrame>* old_source = nullptr; |
| 162 rtc::VideoSinkWants wants; | 162 rtc::VideoSinkWants wants; |
| 163 { | 163 { |
| 164 rtc::CritScope lock(&crit_); | 164 rtc::CritScope lock(&crit_); |
| 165 old_source = source_; | 165 old_source = source_; |
| 166 wants = sink_wants_; |
| 167 // If changing degradation preference, clear any constraints from the |
| 168 // current sink wants that will no longer apply. |
| 169 if (degradation_preference_ != degradation_preference) { |
| 170 switch (degradation_preference) { |
| 171 case DegradationPreference::kBalanced: |
| 172 wants.framerate_fps_.reset(); |
| 173 break; |
| 174 case DegradationPreference::kMaintainResolution: |
| 175 wants.pixel_count.reset(); |
| 176 break; |
| 177 } |
| 178 } |
| 179 degradation_preference_ = degradation_preference; |
| 166 source_ = source; | 180 source_ = source; |
| 167 degradation_preference_ = degradation_preference; | |
| 168 wants = current_wants(); | |
| 169 } | 181 } |
| 170 | 182 |
| 171 if (old_source != source && old_source != nullptr) { | 183 if (old_source != source && old_source != nullptr) { |
| 172 old_source->RemoveSink(vie_encoder_); | 184 old_source->RemoveSink(vie_encoder_); |
| 173 } | 185 } |
| 174 | 186 |
| 175 if (!source) { | 187 if (!source) { |
| 176 return; | 188 return; |
| 177 } | 189 } |
| 178 | 190 |
| 179 source->AddOrUpdateSink(vie_encoder_, wants); | 191 source->AddOrUpdateSink(vie_encoder_, wants); |
| 180 } | 192 } |
| 181 | 193 |
| 182 void SetWantsRotationApplied(bool rotation_applied) { | 194 void SetWantsRotationApplied(bool rotation_applied) { |
| 183 rtc::CritScope lock(&crit_); | 195 rtc::CritScope lock(&crit_); |
| 184 sink_wants_.rotation_applied = rotation_applied; | 196 sink_wants_.rotation_applied = rotation_applied; |
| 185 disabled_scaling_sink_wants_.rotation_applied = rotation_applied; | |
| 186 if (source_) { | 197 if (source_) { |
| 187 source_->AddOrUpdateSink(vie_encoder_, current_wants()); | 198 source_->AddOrUpdateSink(vie_encoder_, sink_wants_); |
| 188 } | 199 } |
| 189 } | 200 } |
| 190 | 201 |
| 191 void RequestResolutionLowerThan(int pixel_count) { | 202 void RequestResolutionLowerThan(int pixel_count) { |
| 192 // Called on the encoder task queue. | 203 // Called on the encoder task queue. |
| 193 rtc::CritScope lock(&crit_); | 204 rtc::CritScope lock(&crit_); |
| 194 if (!IsResolutionScalingEnabledLocked()) { | 205 if (!IsResolutionScalingEnabledLocked()) { |
| 195 // This can happen since |degradation_preference_| is set on | 206 // This can happen since |degradation_preference_| is set on |
| 196 // libjingle's worker thread but the adaptation is done on the encoder | 207 // libjingle's worker thread but the adaptation is done on the encoder |
| 197 // task queue. | 208 // task queue. |
| 198 return; | 209 return; |
| 199 } | 210 } |
| 200 // The input video frame size will have a resolution with less than or | 211 // The input video frame size will have a resolution with less than or |
| 201 // equal to |max_pixel_count| depending on how the source can scale the | 212 // equal to |max_pixel_count| depending on how the source can scale the |
| 202 // input frame size. | 213 // input frame size. |
| 203 const int pixels_wanted = (pixel_count * 3) / 5; | 214 const int pixels_wanted = (pixel_count * 3) / 5; |
| 204 if (pixels_wanted < kMinPixelsPerFrame) | 215 if (pixels_wanted < kMinPixelsPerFrame) |
| 205 return; | 216 return; |
| 206 sink_wants_.max_pixel_count = rtc::Optional<int>(pixels_wanted); | 217 sink_wants_.pixel_count.emplace(rtc::VideoSinkWants::Range( |
| 207 sink_wants_.target_pixel_count = rtc::Optional<int>(); | 218 kMinPixelsPerFrame, pixels_wanted, pixel_count - 1)); |
| 208 if (source_) | 219 if (source_) |
| 209 source_->AddOrUpdateSink(vie_encoder_, sink_wants_); | 220 source_->AddOrUpdateSink(vie_encoder_, sink_wants_); |
| 210 } | 221 } |
| 211 | 222 |
| 223 void RequestFramerateLowerThan(int framerate_fps) { |
| 224 // TODO(sprang): Update SinkWants. |
| 225 } |
| 226 |
| 212 void RequestHigherResolutionThan(int pixel_count) { | 227 void RequestHigherResolutionThan(int pixel_count) { |
| 213 rtc::CritScope lock(&crit_); | 228 rtc::CritScope lock(&crit_); |
| 214 if (!IsResolutionScalingEnabledLocked()) { | 229 if (!IsResolutionScalingEnabledLocked()) { |
| 215 // This can happen since |degradation_preference_| is set on | 230 // This can happen since |degradation_preference_| is set on |
| 216 // libjingle's worker thread but the adaptation is done on the encoder | 231 // libjingle's worker thread but the adaptation is done on the encoder |
| 217 // task queue. | 232 // task queue. |
| 218 return; | 233 return; |
| 219 } | 234 } |
| 220 // On step down we request at most 3/5 the pixel count of the previous | 235 |
| 221 // resolution, so in order to take "one step up" we request a resolution as | 236 // The input video frame size will have a resolution with "one step up" |
| 222 // close as possible to 5/3 of the current resolution. The actual pixel | 237 // pixels than |max_pixel_count_step_up| where "one step up" depends on |
| 223 // count selected depends on the capabilities of the source. In order to not | 238 // how the source can scale the input frame size. We still cap the step up |
| 224 // take a too large step up, we cap the requested pixel count to be at most | 239 // to be at most twice the number of pixels. |
| 225 // four time the current number of pixels. | 240 sink_wants_.pixel_count.emplace(rtc::VideoSinkWants::Range( |
| 226 sink_wants_.target_pixel_count = rtc::Optional<int>((pixel_count * 5) / 3); | 241 pixel_count + 1, (pixel_count * 5) / 3, pixel_count * 4)); |
| 227 sink_wants_.max_pixel_count = rtc::Optional<int>(pixel_count * 4); | |
| 228 if (source_) | 242 if (source_) |
| 229 source_->AddOrUpdateSink(vie_encoder_, sink_wants_); | 243 source_->AddOrUpdateSink(vie_encoder_, sink_wants_); |
| 230 } | 244 } |
| 231 | 245 |
| 246 void RequestHigherFramerateThan(int framerate_fps) { |
| 247 // TODO(sprang): Update SinkWants. |
| 248 } |
| 249 |
| 232 private: | 250 private: |
| 233 bool IsResolutionScalingEnabledLocked() const | 251 bool IsResolutionScalingEnabledLocked() const |
| 234 EXCLUSIVE_LOCKS_REQUIRED(&crit_) { | 252 EXCLUSIVE_LOCKS_REQUIRED(&crit_) { |
| 235 return degradation_preference_ != | 253 return degradation_preference_ != |
| 236 DegradationPreference::kMaintainResolution; | 254 DegradationPreference::kMaintainResolution; |
| 237 } | 255 } |
| 238 | 256 |
| 239 const rtc::VideoSinkWants& current_wants() const | 257 bool IsFramerateScalingEnabledLocked() const |
| 240 EXCLUSIVE_LOCKS_REQUIRED(&crit_) { | 258 EXCLUSIVE_LOCKS_REQUIRED(&crit_) { |
| 241 return IsResolutionScalingEnabledLocked() ? sink_wants_ | 259 return degradation_preference_ == |
| 242 : disabled_scaling_sink_wants_; | 260 DegradationPreference::kMaintainResolution; |
| 243 } | 261 } |
| 244 | 262 |
| 245 rtc::CriticalSection crit_; | 263 rtc::CriticalSection crit_; |
| 246 rtc::SequencedTaskChecker main_checker_; | 264 rtc::SequencedTaskChecker main_checker_; |
| 247 ViEEncoder* const vie_encoder_; | 265 ViEEncoder* const vie_encoder_; |
| 248 rtc::VideoSinkWants sink_wants_ GUARDED_BY(&crit_); | 266 rtc::VideoSinkWants sink_wants_ GUARDED_BY(&crit_); |
| 249 rtc::VideoSinkWants disabled_scaling_sink_wants_ GUARDED_BY(&crit_); | |
| 250 DegradationPreference degradation_preference_ GUARDED_BY(&crit_); | 267 DegradationPreference degradation_preference_ GUARDED_BY(&crit_); |
| 251 rtc::VideoSourceInterface<VideoFrame>* source_ GUARDED_BY(&crit_); | 268 rtc::VideoSourceInterface<VideoFrame>* source_ GUARDED_BY(&crit_); |
| 252 | 269 |
| 253 RTC_DISALLOW_COPY_AND_ASSIGN(VideoSourceProxy); | 270 RTC_DISALLOW_COPY_AND_ASSIGN(VideoSourceProxy); |
| 254 }; | 271 }; |
| 255 | 272 |
| 256 ViEEncoder::ViEEncoder(uint32_t number_of_cores, | 273 ViEEncoder::ViEEncoder(uint32_t number_of_cores, |
| 257 SendStatisticsProxy* stats_proxy, | 274 SendStatisticsProxy* stats_proxy, |
| 258 const VideoSendStream::Config::EncoderSettings& settings, | 275 const VideoSendStream::Config::EncoderSettings& settings, |
| 259 rtc::VideoSinkInterface<VideoFrame>* pre_encode_callback, | 276 rtc::VideoSinkInterface<VideoFrame>* pre_encode_callback, |
| (...skipping 474 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 734 | 751 |
| 735 if (video_suspension_changed) { | 752 if (video_suspension_changed) { |
| 736 LOG(LS_INFO) << "Video suspend state changed to: " | 753 LOG(LS_INFO) << "Video suspend state changed to: " |
| 737 << (video_is_suspended ? "suspended" : "not suspended"); | 754 << (video_is_suspended ? "suspended" : "not suspended"); |
| 738 stats_proxy_->OnSuspendChange(video_is_suspended); | 755 stats_proxy_->OnSuspendChange(video_is_suspended); |
| 739 } | 756 } |
| 740 } | 757 } |
| 741 | 758 |
| 742 void ViEEncoder::AdaptDown(AdaptReason reason) { | 759 void ViEEncoder::AdaptDown(AdaptReason reason) { |
| 743 RTC_DCHECK_RUN_ON(&encoder_queue_); | 760 RTC_DCHECK_RUN_ON(&encoder_queue_); |
| 744 if (degradation_preference_ != DegradationPreference::kBalanced) | 761 AdaptationRequest adaptation_request = { |
| 745 return; | 762 last_frame_info_->pixel_count(), |
| 746 RTC_DCHECK(static_cast<bool>(last_frame_info_)); | 763 stats_proxy_->GetStats().input_frame_rate, |
| 747 int current_pixel_count = last_frame_info_->pixel_count(); | 764 AdaptationRequest::Mode::kAdaptDown}; |
| 765 |
| 748 if (last_adaptation_request_ && | 766 if (last_adaptation_request_ && |
| 749 last_adaptation_request_->mode_ == AdaptationRequest::Mode::kAdaptDown && | 767 last_adaptation_request_->mode_ == AdaptationRequest::Mode::kAdaptDown) { |
| 750 current_pixel_count >= last_adaptation_request_->input_pixel_count_) { | 768 switch (degradation_preference_) { |
| 751 // Don't request lower resolution if the current resolution is not lower | 769 case DegradationPreference::kBalanced: |
| 752 // than the last time we asked for the resolution to be lowered. | 770 if (adaptation_request.input_pixel_count_ >= |
| 753 return; | 771 last_adaptation_request_->input_pixel_count_) { |
| 772 // Don't request lower resolution if the current resolution is not |
| 773 // lower |
| 774 // than the last time we asked for the resolution to be lowered. |
| 775 return; |
| 776 } |
| 777 break; |
| 778 case DegradationPreference::kMaintainResolution: |
| 779 if (adaptation_request.framerate_fps_ <= 1) { |
| 780 // Don't request lower framerate if we don't have a valid frame rate. |
| 781 // Since framerate, unlike resolution, is a measure we have to |
| 782 // estimate, and can fluctuate naturally over time, don't make the |
| 783 // same kind of limitations as for resolution, but trust the overuse |
| 784 // detector to not trigger too often. |
| 785 return; |
| 786 } |
| 787 break; |
| 788 } |
| 754 } | 789 } |
| 755 last_adaptation_request_.emplace(AdaptationRequest{ | 790 |
| 756 current_pixel_count, AdaptationRequest::Mode::kAdaptDown}); | 791 last_adaptation_request_.emplace(adaptation_request); |
| 757 | 792 |
| 758 switch (reason) { | 793 switch (reason) { |
| 759 case kQuality: | 794 case kQuality: |
| 760 stats_proxy_->OnQualityRestrictedResolutionChanged( | 795 stats_proxy_->OnQualityRestrictedResolutionChanged( |
| 761 scale_counter_[reason] + 1); | 796 scale_counter_[reason] + 1); |
| 762 break; | 797 break; |
| 763 case kCpu: | 798 case kCpu: |
| 764 if (scale_counter_[reason] >= kMaxCpuDowngrades) | 799 if (scale_counter_[reason] >= kMaxCpuDowngrades) |
| 765 return; | 800 return; |
| 766 // Update stats accordingly. | 801 // Update stats accordingly. |
| 767 stats_proxy_->OnCpuRestrictedResolutionChanged(true); | 802 stats_proxy_->OnCpuRestrictedResolutionChanged(true); |
| 768 break; | 803 break; |
| 769 } | 804 } |
| 770 ++scale_counter_[reason]; | 805 ++scale_counter_[reason]; |
| 771 source_proxy_->RequestResolutionLowerThan(current_pixel_count); | 806 |
| 772 LOG(LS_INFO) << "Scaling down resolution."; | 807 switch (degradation_preference_) { |
| 808 case DegradationPreference::kBalanced: |
| 809 source_proxy_->RequestResolutionLowerThan( |
| 810 adaptation_request.input_pixel_count_); |
| 811 LOG(LS_INFO) << "Scaling down resolution."; |
| 812 break; |
| 813 case DegradationPreference::kMaintainResolution: |
| 814 source_proxy_->RequestFramerateLowerThan( |
| 815 adaptation_request.framerate_fps_); |
| 816 LOG(LS_INFO) << "Scaling down framerate."; |
| 817 break; |
| 818 } |
| 819 |
| 773 for (size_t i = 0; i < kScaleReasonSize; ++i) { | 820 for (size_t i = 0; i < kScaleReasonSize; ++i) { |
| 774 LOG(LS_INFO) << "Scaled " << scale_counter_[i] | 821 LOG(LS_INFO) << "Scaled " << scale_counter_[i] |
| 775 << " times for reason: " << (i ? "cpu" : "quality"); | 822 << " times for reason: " << (i ? "cpu" : "quality"); |
| 776 } | 823 } |
| 777 } | 824 } |
| 778 | 825 |
| 779 void ViEEncoder::AdaptUp(AdaptReason reason) { | 826 void ViEEncoder::AdaptUp(AdaptReason reason) { |
| 780 RTC_DCHECK_RUN_ON(&encoder_queue_); | 827 RTC_DCHECK_RUN_ON(&encoder_queue_); |
| 781 if (scale_counter_[reason] == 0 || | 828 if (scale_counter_[reason] == 0 || |
| 782 degradation_preference_ != DegradationPreference::kBalanced) { | 829 degradation_preference_ != DegradationPreference::kBalanced) { |
| 783 return; | 830 return; |
| 784 } | 831 } |
| 785 // Only scale if resolution is higher than last time we requested higher | 832 |
| 786 // resolution. | 833 AdaptationRequest adaptation_request = { |
| 787 RTC_DCHECK(static_cast<bool>(last_frame_info_)); | 834 last_frame_info_->pixel_count(), |
| 788 int current_pixel_count = last_frame_info_->pixel_count(); | 835 stats_proxy_->GetStats().input_frame_rate, |
| 836 AdaptationRequest::Mode::kAdaptUp}; |
| 837 |
| 789 if (last_adaptation_request_ && | 838 if (last_adaptation_request_ && |
| 790 last_adaptation_request_->mode_ == AdaptationRequest::Mode::kAdaptUp && | 839 last_adaptation_request_->mode_ == AdaptationRequest::Mode::kAdaptUp) { |
| 791 current_pixel_count <= last_adaptation_request_->input_pixel_count_) { | 840 switch (degradation_preference_) { |
| 792 // Don't request higher resolution if the current resolution is not higher | 841 case DegradationPreference::kBalanced: |
| 793 // than the last time we asked for the resolution to be higher. | 842 if (adaptation_request.input_pixel_count_ <= |
| 794 return; | 843 last_adaptation_request_->input_pixel_count_) { |
| 844 // Don't request higher resolution if the current resolution is not |
| 845 // higher than the last time we asked for the resolution to be higher. |
| 846 return; |
| 847 } |
| 848 break; |
| 849 case DegradationPreference::kMaintainResolution: |
| 850 // TODO(sprang): Don't request higher framerate if we are already at |
| 851 // max requested fps? |
| 852 break; |
| 853 } |
| 795 } | 854 } |
| 796 last_adaptation_request_.emplace(AdaptationRequest{ | 855 |
| 797 current_pixel_count, AdaptationRequest::Mode::kAdaptUp}); | 856 last_adaptation_request_.emplace(adaptation_request); |
| 798 | 857 |
| 799 switch (reason) { | 858 switch (reason) { |
| 800 case kQuality: | 859 case kQuality: |
| 801 stats_proxy_->OnQualityRestrictedResolutionChanged( | 860 stats_proxy_->OnQualityRestrictedResolutionChanged( |
| 802 scale_counter_[reason] - 1); | 861 scale_counter_[reason] - 1); |
| 803 break; | 862 break; |
| 804 case kCpu: | 863 case kCpu: |
| 805 // Update stats accordingly. | 864 // Update stats accordingly. |
| 806 stats_proxy_->OnCpuRestrictedResolutionChanged(scale_counter_[reason] > | 865 stats_proxy_->OnCpuRestrictedResolutionChanged(scale_counter_[reason] > |
| 807 1); | 866 1); |
| 808 break; | 867 break; |
| 809 } | 868 } |
| 810 --scale_counter_[reason]; | 869 --scale_counter_[reason]; |
| 811 source_proxy_->RequestHigherResolutionThan(current_pixel_count); | 870 |
| 812 LOG(LS_INFO) << "Scaling up resolution."; | 871 switch (degradation_preference_) { |
| 872 case DegradationPreference::kBalanced: |
| 873 source_proxy_->RequestHigherResolutionThan( |
| 874 adaptation_request.input_pixel_count_); |
| 875 LOG(LS_INFO) << "Scaling up resolution."; |
| 876 break; |
| 877 case DegradationPreference::kMaintainResolution: |
| 878 source_proxy_->RequestHigherFramerateThan( |
| 879 adaptation_request.framerate_fps_); |
| 880 LOG(LS_INFO) << "Scaling up framerate."; |
| 881 break; |
| 882 } |
| 883 |
| 813 for (size_t i = 0; i < kScaleReasonSize; ++i) { | 884 for (size_t i = 0; i < kScaleReasonSize; ++i) { |
| 814 LOG(LS_INFO) << "Scaled " << scale_counter_[i] | 885 LOG(LS_INFO) << "Scaled " << scale_counter_[i] |
| 815 << " times for reason: " << (i ? "cpu" : "quality"); | 886 << " times for reason: " << (i ? "cpu" : "quality"); |
| 816 } | 887 } |
| 817 } | 888 } |
| 818 | 889 |
| 819 } // namespace webrtc | 890 } // namespace webrtc |
| OLD | NEW |