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 |