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 VideoSourceSinkController(rtc::VideoSinkInterface<VideoFrame> * sink,rtc::VideoSourceInterface<VideoFrame> * source)23VideoSourceSinkController::VideoSourceSinkController( 24 rtc::VideoSinkInterface<VideoFrame>* sink, 25 rtc::VideoSourceInterface<VideoFrame>* source) 26 : sink_(sink), source_(source) { 27 RTC_DCHECK(sink_); 28 } 29 ~VideoSourceSinkController()30VideoSourceSinkController::~VideoSourceSinkController() { 31 RTC_DCHECK_RUN_ON(&sequence_checker_); 32 } 33 SetSource(rtc::VideoSourceInterface<VideoFrame> * source)34void VideoSourceSinkController::SetSource( 35 rtc::VideoSourceInterface<VideoFrame>* source) { 36 RTC_DCHECK_RUN_ON(&sequence_checker_); 37 38 rtc::VideoSourceInterface<VideoFrame>* old_source = source_; 39 source_ = source; 40 41 if (old_source != source && old_source) 42 old_source->RemoveSink(sink_); 43 44 if (!source) 45 return; 46 47 source->AddOrUpdateSink(sink_, CurrentSettingsToSinkWants()); 48 } 49 HasSource() const50bool VideoSourceSinkController::HasSource() const { 51 RTC_DCHECK_RUN_ON(&sequence_checker_); 52 return source_ != nullptr; 53 } 54 RequestRefreshFrame()55void VideoSourceSinkController::RequestRefreshFrame() { 56 RTC_DCHECK_RUN_ON(&sequence_checker_); 57 if (source_) 58 source_->RequestRefreshFrame(); 59 } 60 PushSourceSinkSettings()61void VideoSourceSinkController::PushSourceSinkSettings() { 62 RTC_DCHECK_RUN_ON(&sequence_checker_); 63 if (!source_) 64 return; 65 rtc::VideoSinkWants wants = CurrentSettingsToSinkWants(); 66 source_->AddOrUpdateSink(sink_, wants); 67 } 68 restrictions() const69VideoSourceRestrictions VideoSourceSinkController::restrictions() const { 70 RTC_DCHECK_RUN_ON(&sequence_checker_); 71 return restrictions_; 72 } 73 pixels_per_frame_upper_limit() const74absl::optional<size_t> VideoSourceSinkController::pixels_per_frame_upper_limit() 75 const { 76 RTC_DCHECK_RUN_ON(&sequence_checker_); 77 return pixels_per_frame_upper_limit_; 78 } 79 frame_rate_upper_limit() const80absl::optional<double> VideoSourceSinkController::frame_rate_upper_limit() 81 const { 82 RTC_DCHECK_RUN_ON(&sequence_checker_); 83 return frame_rate_upper_limit_; 84 } 85 rotation_applied() const86bool VideoSourceSinkController::rotation_applied() const { 87 RTC_DCHECK_RUN_ON(&sequence_checker_); 88 return rotation_applied_; 89 } 90 resolution_alignment() const91int VideoSourceSinkController::resolution_alignment() const { 92 RTC_DCHECK_RUN_ON(&sequence_checker_); 93 return resolution_alignment_; 94 } 95 96 const std::vector<rtc::VideoSinkWants::FrameSize>& resolutions() const97VideoSourceSinkController::resolutions() const { 98 RTC_DCHECK_RUN_ON(&sequence_checker_); 99 return resolutions_; 100 } 101 active() const102bool VideoSourceSinkController::active() const { 103 RTC_DCHECK_RUN_ON(&sequence_checker_); 104 return active_; 105 } 106 107 absl::optional<rtc::VideoSinkWants::FrameSize> requested_resolution() const108VideoSourceSinkController::requested_resolution() const { 109 RTC_DCHECK_RUN_ON(&sequence_checker_); 110 return requested_resolution_; 111 } 112 SetRestrictions(VideoSourceRestrictions restrictions)113void VideoSourceSinkController::SetRestrictions( 114 VideoSourceRestrictions restrictions) { 115 RTC_DCHECK_RUN_ON(&sequence_checker_); 116 restrictions_ = std::move(restrictions); 117 } 118 SetPixelsPerFrameUpperLimit(absl::optional<size_t> pixels_per_frame_upper_limit)119void VideoSourceSinkController::SetPixelsPerFrameUpperLimit( 120 absl::optional<size_t> pixels_per_frame_upper_limit) { 121 RTC_DCHECK_RUN_ON(&sequence_checker_); 122 pixels_per_frame_upper_limit_ = std::move(pixels_per_frame_upper_limit); 123 } 124 SetFrameRateUpperLimit(absl::optional<double> frame_rate_upper_limit)125void VideoSourceSinkController::SetFrameRateUpperLimit( 126 absl::optional<double> frame_rate_upper_limit) { 127 RTC_DCHECK_RUN_ON(&sequence_checker_); 128 frame_rate_upper_limit_ = std::move(frame_rate_upper_limit); 129 } 130 SetRotationApplied(bool rotation_applied)131void VideoSourceSinkController::SetRotationApplied(bool rotation_applied) { 132 RTC_DCHECK_RUN_ON(&sequence_checker_); 133 rotation_applied_ = rotation_applied; 134 } 135 SetResolutionAlignment(int resolution_alignment)136void VideoSourceSinkController::SetResolutionAlignment( 137 int resolution_alignment) { 138 RTC_DCHECK_RUN_ON(&sequence_checker_); 139 resolution_alignment_ = resolution_alignment; 140 } 141 SetResolutions(std::vector<rtc::VideoSinkWants::FrameSize> resolutions)142void VideoSourceSinkController::SetResolutions( 143 std::vector<rtc::VideoSinkWants::FrameSize> resolutions) { 144 RTC_DCHECK_RUN_ON(&sequence_checker_); 145 resolutions_ = std::move(resolutions); 146 } 147 SetActive(bool active)148void VideoSourceSinkController::SetActive(bool active) { 149 RTC_DCHECK_RUN_ON(&sequence_checker_); 150 active_ = active; 151 } 152 SetRequestedResolution(absl::optional<rtc::VideoSinkWants::FrameSize> requested_resolution)153void VideoSourceSinkController::SetRequestedResolution( 154 absl::optional<rtc::VideoSinkWants::FrameSize> requested_resolution) { 155 RTC_DCHECK_RUN_ON(&sequence_checker_); 156 requested_resolution_ = std::move(requested_resolution); 157 } 158 159 // RTC_EXCLUSIVE_LOCKS_REQUIRED(sequence_checker_) CurrentSettingsToSinkWants() const160rtc::VideoSinkWants VideoSourceSinkController::CurrentSettingsToSinkWants() 161 const { 162 rtc::VideoSinkWants wants; 163 wants.rotation_applied = rotation_applied_; 164 // `wants.black_frames` is not used, it always has its default value false. 165 wants.max_pixel_count = 166 rtc::dchecked_cast<int>(restrictions_.max_pixels_per_frame().value_or( 167 std::numeric_limits<int>::max())); 168 wants.target_pixel_count = 169 restrictions_.target_pixels_per_frame().has_value() 170 ? absl::optional<int>(rtc::dchecked_cast<int>( 171 restrictions_.target_pixels_per_frame().value())) 172 : absl::nullopt; 173 wants.max_framerate_fps = 174 restrictions_.max_frame_rate().has_value() 175 ? static_cast<int>(restrictions_.max_frame_rate().value()) 176 : std::numeric_limits<int>::max(); 177 wants.resolution_alignment = resolution_alignment_; 178 wants.max_pixel_count = 179 std::min(wants.max_pixel_count, 180 rtc::dchecked_cast<int>(pixels_per_frame_upper_limit_.value_or( 181 std::numeric_limits<int>::max()))); 182 wants.max_framerate_fps = 183 std::min(wants.max_framerate_fps, 184 frame_rate_upper_limit_.has_value() 185 ? static_cast<int>(frame_rate_upper_limit_.value()) 186 : std::numeric_limits<int>::max()); 187 wants.resolutions = resolutions_; 188 wants.is_active = active_; 189 wants.requested_resolution = requested_resolution_; 190 return wants; 191 } 192 193 } // namespace webrtc 194