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 SetSource(rtc::VideoSourceInterface<VideoFrame> * source)46void VideoSourceSinkController::SetSource( 47 rtc::VideoSourceInterface<VideoFrame>* source) { 48 rtc::VideoSourceInterface<VideoFrame>* old_source; 49 rtc::VideoSinkWants wants; 50 { 51 MutexLock lock(&mutex_); 52 old_source = source_; 53 source_ = source; 54 wants = CurrentSettingsToSinkWants(); 55 } 56 if (old_source != source && old_source) 57 old_source->RemoveSink(sink_); 58 if (!source) 59 return; 60 source->AddOrUpdateSink(sink_, wants); 61 } 62 PushSourceSinkSettings()63void VideoSourceSinkController::PushSourceSinkSettings() { 64 MutexLock lock(&mutex_); 65 if (!source_) 66 return; 67 rtc::VideoSinkWants wants = CurrentSettingsToSinkWants(); 68 RTC_LOG(INFO) << "Pushing SourceSink restrictions: " << WantsToString(wants); 69 source_->AddOrUpdateSink(sink_, wants); 70 } 71 restrictions() const72VideoSourceRestrictions VideoSourceSinkController::restrictions() const { 73 MutexLock lock(&mutex_); 74 return restrictions_; 75 } 76 pixels_per_frame_upper_limit() const77absl::optional<size_t> VideoSourceSinkController::pixels_per_frame_upper_limit() 78 const { 79 MutexLock lock(&mutex_); 80 return pixels_per_frame_upper_limit_; 81 } 82 frame_rate_upper_limit() const83absl::optional<double> VideoSourceSinkController::frame_rate_upper_limit() 84 const { 85 MutexLock lock(&mutex_); 86 return frame_rate_upper_limit_; 87 } 88 rotation_applied() const89bool VideoSourceSinkController::rotation_applied() const { 90 MutexLock lock(&mutex_); 91 return rotation_applied_; 92 } 93 resolution_alignment() const94int VideoSourceSinkController::resolution_alignment() const { 95 MutexLock lock(&mutex_); 96 return resolution_alignment_; 97 } 98 SetRestrictions(VideoSourceRestrictions restrictions)99void VideoSourceSinkController::SetRestrictions( 100 VideoSourceRestrictions restrictions) { 101 MutexLock lock(&mutex_); 102 restrictions_ = std::move(restrictions); 103 } 104 SetPixelsPerFrameUpperLimit(absl::optional<size_t> pixels_per_frame_upper_limit)105void VideoSourceSinkController::SetPixelsPerFrameUpperLimit( 106 absl::optional<size_t> pixels_per_frame_upper_limit) { 107 MutexLock lock(&mutex_); 108 pixels_per_frame_upper_limit_ = std::move(pixels_per_frame_upper_limit); 109 } 110 SetFrameRateUpperLimit(absl::optional<double> frame_rate_upper_limit)111void VideoSourceSinkController::SetFrameRateUpperLimit( 112 absl::optional<double> frame_rate_upper_limit) { 113 MutexLock lock(&mutex_); 114 frame_rate_upper_limit_ = std::move(frame_rate_upper_limit); 115 } 116 SetRotationApplied(bool rotation_applied)117void VideoSourceSinkController::SetRotationApplied(bool rotation_applied) { 118 MutexLock lock(&mutex_); 119 rotation_applied_ = rotation_applied; 120 } 121 SetResolutionAlignment(int resolution_alignment)122void VideoSourceSinkController::SetResolutionAlignment( 123 int resolution_alignment) { 124 MutexLock lock(&mutex_); 125 resolution_alignment_ = resolution_alignment; 126 } 127 128 // RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_) CurrentSettingsToSinkWants() const129rtc::VideoSinkWants VideoSourceSinkController::CurrentSettingsToSinkWants() 130 const { 131 rtc::VideoSinkWants wants; 132 wants.rotation_applied = rotation_applied_; 133 // |wants.black_frames| is not used, it always has its default value false. 134 wants.max_pixel_count = 135 rtc::dchecked_cast<int>(restrictions_.max_pixels_per_frame().value_or( 136 std::numeric_limits<int>::max())); 137 wants.target_pixel_count = 138 restrictions_.target_pixels_per_frame().has_value() 139 ? absl::optional<int>(rtc::dchecked_cast<int>( 140 restrictions_.target_pixels_per_frame().value())) 141 : absl::nullopt; 142 wants.max_framerate_fps = 143 restrictions_.max_frame_rate().has_value() 144 ? static_cast<int>(restrictions_.max_frame_rate().value()) 145 : std::numeric_limits<int>::max(); 146 wants.resolution_alignment = resolution_alignment_; 147 wants.max_pixel_count = 148 std::min(wants.max_pixel_count, 149 rtc::dchecked_cast<int>(pixels_per_frame_upper_limit_.value_or( 150 std::numeric_limits<int>::max()))); 151 wants.max_framerate_fps = 152 std::min(wants.max_framerate_fps, 153 frame_rate_upper_limit_.has_value() 154 ? static_cast<int>(frame_rate_upper_limit_.value()) 155 : std::numeric_limits<int>::max()); 156 return wants; 157 } 158 159 } // namespace webrtc 160