1 /* 2 * Copyright 2020 The WebRTC Project Authors. All rights reserved. 3 * 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 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "video/video_source_sink_controller.h" 12 13 #include <algorithm> 14 #include <limits> 15 #include <utility> 16 17 #include "rtc_base/logging.h" 18 #include "rtc_base/numerics/safe_conversions.h" 19 #include "rtc_base/strings/string_builder.h" 20 21 namespace webrtc { 22 23 namespace { 24 WantsToString(const rtc::VideoSinkWants & wants)25std::string WantsToString(const rtc::VideoSinkWants& wants) { 26 rtc::StringBuilder ss; 27 28 ss << "max_fps=" << wants.max_framerate_fps 29 << " max_pixel_count=" << wants.max_pixel_count << " target_pixel_count=" 30 << (wants.target_pixel_count.has_value() 31 ? std::to_string(wants.target_pixel_count.value()) 32 : "null"); 33 34 return ss.Release(); 35 } 36 37 } // namespace 38 VideoSourceSinkController(rtc::VideoSinkInterface<VideoFrame> * sink,rtc::VideoSourceInterface<VideoFrame> * source)39VideoSourceSinkController::VideoSourceSinkController( 40 rtc::VideoSinkInterface<VideoFrame>* sink, 41 rtc::VideoSourceInterface<VideoFrame>* source) 42 : sink_(sink), source_(source) { 43 RTC_DCHECK(sink_); 44 } 45 ~VideoSourceSinkController()46VideoSourceSinkController::~VideoSourceSinkController() { 47 RTC_DCHECK_RUN_ON(&sequence_checker_); 48 } 49 SetSource(rtc::VideoSourceInterface<VideoFrame> * source)50void VideoSourceSinkController::SetSource( 51 rtc::VideoSourceInterface<VideoFrame>* source) { 52 RTC_DCHECK_RUN_ON(&sequence_checker_); 53 54 rtc::VideoSourceInterface<VideoFrame>* old_source = source_; 55 source_ = source; 56 57 if (old_source != source && old_source) 58 old_source->RemoveSink(sink_); 59 60 if (!source) 61 return; 62 63 source->AddOrUpdateSink(sink_, CurrentSettingsToSinkWants()); 64 } 65 HasSource() const66bool VideoSourceSinkController::HasSource() const { 67 RTC_DCHECK_RUN_ON(&sequence_checker_); 68 return source_ != nullptr; 69 } 70 PushSourceSinkSettings()71void VideoSourceSinkController::PushSourceSinkSettings() { 72 RTC_DCHECK_RUN_ON(&sequence_checker_); 73 if (!source_) 74 return; 75 rtc::VideoSinkWants wants = CurrentSettingsToSinkWants(); 76 RTC_LOG(INFO) << "Pushing SourceSink restrictions: " << WantsToString(wants); 77 source_->AddOrUpdateSink(sink_, wants); 78 } 79 restrictions() const80VideoSourceRestrictions VideoSourceSinkController::restrictions() const { 81 RTC_DCHECK_RUN_ON(&sequence_checker_); 82 return restrictions_; 83 } 84 pixels_per_frame_upper_limit() const85absl::optional<size_t> VideoSourceSinkController::pixels_per_frame_upper_limit() 86 const { 87 RTC_DCHECK_RUN_ON(&sequence_checker_); 88 return pixels_per_frame_upper_limit_; 89 } 90 frame_rate_upper_limit() const91absl::optional<double> VideoSourceSinkController::frame_rate_upper_limit() 92 const { 93 RTC_DCHECK_RUN_ON(&sequence_checker_); 94 return frame_rate_upper_limit_; 95 } 96 rotation_applied() const97bool VideoSourceSinkController::rotation_applied() const { 98 RTC_DCHECK_RUN_ON(&sequence_checker_); 99 return rotation_applied_; 100 } 101 resolution_alignment() const102int VideoSourceSinkController::resolution_alignment() const { 103 RTC_DCHECK_RUN_ON(&sequence_checker_); 104 return resolution_alignment_; 105 } 106 SetRestrictions(VideoSourceRestrictions restrictions)107void VideoSourceSinkController::SetRestrictions( 108 VideoSourceRestrictions restrictions) { 109 RTC_DCHECK_RUN_ON(&sequence_checker_); 110 restrictions_ = std::move(restrictions); 111 } 112 SetPixelsPerFrameUpperLimit(absl::optional<size_t> pixels_per_frame_upper_limit)113void VideoSourceSinkController::SetPixelsPerFrameUpperLimit( 114 absl::optional<size_t> pixels_per_frame_upper_limit) { 115 RTC_DCHECK_RUN_ON(&sequence_checker_); 116 pixels_per_frame_upper_limit_ = std::move(pixels_per_frame_upper_limit); 117 } 118 SetFrameRateUpperLimit(absl::optional<double> frame_rate_upper_limit)119void VideoSourceSinkController::SetFrameRateUpperLimit( 120 absl::optional<double> frame_rate_upper_limit) { 121 RTC_DCHECK_RUN_ON(&sequence_checker_); 122 frame_rate_upper_limit_ = std::move(frame_rate_upper_limit); 123 } 124 SetRotationApplied(bool rotation_applied)125void VideoSourceSinkController::SetRotationApplied(bool rotation_applied) { 126 RTC_DCHECK_RUN_ON(&sequence_checker_); 127 rotation_applied_ = rotation_applied; 128 } 129 SetResolutionAlignment(int resolution_alignment)130void VideoSourceSinkController::SetResolutionAlignment( 131 int resolution_alignment) { 132 RTC_DCHECK_RUN_ON(&sequence_checker_); 133 resolution_alignment_ = resolution_alignment; 134 } 135 136 // RTC_EXCLUSIVE_LOCKS_REQUIRED(sequence_checker_) CurrentSettingsToSinkWants() const137rtc::VideoSinkWants VideoSourceSinkController::CurrentSettingsToSinkWants() 138 const { 139 rtc::VideoSinkWants wants; 140 wants.rotation_applied = rotation_applied_; 141 // |wants.black_frames| is not used, it always has its default value false. 142 wants.max_pixel_count = 143 rtc::dchecked_cast<int>(restrictions_.max_pixels_per_frame().value_or( 144 std::numeric_limits<int>::max())); 145 wants.target_pixel_count = 146 restrictions_.target_pixels_per_frame().has_value() 147 ? absl::optional<int>(rtc::dchecked_cast<int>( 148 restrictions_.target_pixels_per_frame().value())) 149 : absl::nullopt; 150 wants.max_framerate_fps = 151 restrictions_.max_frame_rate().has_value() 152 ? static_cast<int>(restrictions_.max_frame_rate().value()) 153 : std::numeric_limits<int>::max(); 154 wants.resolution_alignment = resolution_alignment_; 155 wants.max_pixel_count = 156 std::min(wants.max_pixel_count, 157 rtc::dchecked_cast<int>(pixels_per_frame_upper_limit_.value_or( 158 std::numeric_limits<int>::max()))); 159 wants.max_framerate_fps = 160 std::min(wants.max_framerate_fps, 161 frame_rate_upper_limit_.has_value() 162 ? static_cast<int>(frame_rate_upper_limit_.value()) 163 : std::numeric_limits<int>::max()); 164 return wants; 165 } 166 167 } // namespace webrtc 168