blob: f3585766a04d47d12cd4755b1d0083403baa3565 [file] [log] [blame]
Henrik Boströmce0ea492020-01-13 11:27:18 +01001/*
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/numerics/safe_conversions.h"
18
19namespace webrtc {
20
21VideoSourceSinkController::VideoSourceSinkController(
22 rtc::VideoSinkInterface<VideoFrame>* sink,
23 rtc::VideoSourceInterface<VideoFrame>* source)
24 : sink_(sink),
25 source_(source),
26 degradation_preference_(DegradationPreference::DISABLED) {
27 RTC_DCHECK(sink_);
28}
29
30void VideoSourceSinkController::SetSource(
31 rtc::VideoSourceInterface<VideoFrame>* source,
32 DegradationPreference degradation_preference) {
33 rtc::VideoSourceInterface<VideoFrame>* old_source;
34 rtc::VideoSinkWants wants;
35 {
36 rtc::CritScope lock(&crit_);
37 old_source = source_;
38 source_ = source;
39 degradation_preference_ = degradation_preference;
40 wants = CurrentSettingsToSinkWantsInternal();
41 }
42 if (old_source != source && old_source)
43 old_source->RemoveSink(sink_);
44 if (!source)
45 return;
46 source->AddOrUpdateSink(sink_, wants);
47}
48
49void VideoSourceSinkController::PushSourceSinkSettings() {
50 rtc::CritScope lock(&crit_);
51 if (!source_)
52 return;
53 source_->AddOrUpdateSink(sink_, CurrentSettingsToSinkWantsInternal());
54}
55
56VideoSourceRestrictions VideoSourceSinkController::restrictions() const {
57 rtc::CritScope lock(&crit_);
58 return restrictions_;
59}
60
61absl::optional<size_t> VideoSourceSinkController::pixels_per_frame_upper_limit()
62 const {
63 rtc::CritScope lock(&crit_);
64 return pixels_per_frame_upper_limit_;
65}
66
67absl::optional<double> VideoSourceSinkController::frame_rate_upper_limit()
68 const {
69 rtc::CritScope lock(&crit_);
70 return frame_rate_upper_limit_;
71}
72
73bool VideoSourceSinkController::rotation_applied() const {
74 rtc::CritScope lock(&crit_);
75 return rotation_applied_;
76}
77
78int VideoSourceSinkController::resolution_alignment() const {
79 rtc::CritScope lock(&crit_);
80 return resolution_alignment_;
81}
82
83void VideoSourceSinkController::SetRestrictions(
84 VideoSourceRestrictions restrictions) {
85 rtc::CritScope lock(&crit_);
86 restrictions_ = std::move(restrictions);
87}
88
89void VideoSourceSinkController::SetPixelsPerFrameUpperLimit(
90 absl::optional<size_t> pixels_per_frame_upper_limit) {
91 rtc::CritScope lock(&crit_);
92 pixels_per_frame_upper_limit_ = std::move(pixels_per_frame_upper_limit);
93}
94
95void VideoSourceSinkController::SetFrameRateUpperLimit(
96 absl::optional<double> frame_rate_upper_limit) {
97 rtc::CritScope lock(&crit_);
98 frame_rate_upper_limit_ = std::move(frame_rate_upper_limit);
99}
100
101void VideoSourceSinkController::SetRotationApplied(bool rotation_applied) {
102 rtc::CritScope lock(&crit_);
103 rotation_applied_ = rotation_applied;
104}
105
106void VideoSourceSinkController::SetResolutionAlignment(
107 int resolution_alignment) {
108 rtc::CritScope lock(&crit_);
109 resolution_alignment_ = resolution_alignment;
110}
111
112rtc::VideoSinkWants VideoSourceSinkController::CurrentSettingsToSinkWants()
113 const {
114 rtc::CritScope lock(&crit_);
115 return CurrentSettingsToSinkWantsInternal();
116}
117
118// RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_)
119rtc::VideoSinkWants
120VideoSourceSinkController::CurrentSettingsToSinkWantsInternal() const {
121 rtc::VideoSinkWants wants;
122 wants.rotation_applied = rotation_applied_;
123 // |wants.black_frames| is not used, it always has its default value false.
124 wants.max_pixel_count =
125 rtc::dchecked_cast<int>(restrictions_.max_pixels_per_frame().value_or(
126 std::numeric_limits<int>::max()));
127 wants.target_pixel_count =
128 restrictions_.target_pixels_per_frame().has_value()
129 ? absl::optional<int>(rtc::dchecked_cast<int>(
130 restrictions_.target_pixels_per_frame().value()))
131 : absl::nullopt;
132 wants.max_framerate_fps =
133 restrictions_.max_frame_rate().has_value()
134 ? static_cast<int>(restrictions_.max_frame_rate().value())
135 : std::numeric_limits<int>::max();
136 wants.resolution_alignment = resolution_alignment_;
137 {
138 // Clear any constraints from the current sink wants that don't apply to
139 // the used degradation_preference.
140 switch (degradation_preference_) {
141 case DegradationPreference::BALANCED:
142 break;
143 case DegradationPreference::MAINTAIN_FRAMERATE:
144 wants.max_framerate_fps = std::numeric_limits<int>::max();
145 break;
146 case DegradationPreference::MAINTAIN_RESOLUTION:
147 wants.max_pixel_count = std::numeric_limits<int>::max();
148 wants.target_pixel_count.reset();
149 break;
150 case DegradationPreference::DISABLED:
151 wants.max_pixel_count = std::numeric_limits<int>::max();
152 wants.target_pixel_count.reset();
153 wants.max_framerate_fps = std::numeric_limits<int>::max();
154 }
155 }
156 wants.max_pixel_count =
157 std::min(wants.max_pixel_count,
158 rtc::dchecked_cast<int>(pixels_per_frame_upper_limit_.value_or(
159 std::numeric_limits<int>::max())));
160 wants.max_framerate_fps =
161 std::min(wants.max_framerate_fps,
162 frame_rate_upper_limit_.has_value()
163 ? static_cast<int>(frame_rate_upper_limit_.value())
164 : std::numeric_limits<int>::max());
165 return wants;
166}
167
168} // namespace webrtc