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)25 std::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)39 VideoSourceSinkController::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)46 void 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()63 void 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() const72 VideoSourceRestrictions VideoSourceSinkController::restrictions() const {
73   MutexLock lock(&mutex_);
74   return restrictions_;
75 }
76 
pixels_per_frame_upper_limit() const77 absl::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() const83 absl::optional<double> VideoSourceSinkController::frame_rate_upper_limit()
84     const {
85   MutexLock lock(&mutex_);
86   return frame_rate_upper_limit_;
87 }
88 
rotation_applied() const89 bool VideoSourceSinkController::rotation_applied() const {
90   MutexLock lock(&mutex_);
91   return rotation_applied_;
92 }
93 
resolution_alignment() const94 int VideoSourceSinkController::resolution_alignment() const {
95   MutexLock lock(&mutex_);
96   return resolution_alignment_;
97 }
98 
SetRestrictions(VideoSourceRestrictions restrictions)99 void 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)105 void 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)111 void 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)117 void VideoSourceSinkController::SetRotationApplied(bool rotation_applied) {
118   MutexLock lock(&mutex_);
119   rotation_applied_ = rotation_applied;
120 }
121 
SetResolutionAlignment(int resolution_alignment)122 void VideoSourceSinkController::SetResolutionAlignment(
123     int resolution_alignment) {
124   MutexLock lock(&mutex_);
125   resolution_alignment_ = resolution_alignment;
126 }
127 
128 // RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_)
CurrentSettingsToSinkWants() const129 rtc::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