blob: 75cc52bdaf180a5f2c17dbecc117ef642814a91e [file] [log] [blame]
Henrik Boströmce0ea492020-01-13 10:27:181/*
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 <limits>
14
15#include "api/video/video_frame.h"
16#include "api/video/video_source_interface.h"
17#include "call/adaptation/video_source_restrictions.h"
18#include "test/gmock.h"
19#include "test/gtest.h"
20
21using testing::_;
22
23namespace webrtc {
24
25namespace {
26
Jonas Oreland0deda152022-09-23 10:08:5727using FrameSize = rtc::VideoSinkWants::FrameSize;
Henrik Boströmce0ea492020-01-13 10:27:1828constexpr int kIntUnconstrained = std::numeric_limits<int>::max();
29
30class MockVideoSinkWithVideoFrame : public rtc::VideoSinkInterface<VideoFrame> {
31 public:
32 ~MockVideoSinkWithVideoFrame() override {}
33
Danil Chapovalov91fdc602020-05-14 17:17:5134 MOCK_METHOD(void, OnFrame, (const VideoFrame& frame), (override));
35 MOCK_METHOD(void, OnDiscardedFrame, (), (override));
Henrik Boströmce0ea492020-01-13 10:27:1836};
37
38class MockVideoSourceWithVideoFrame
39 : public rtc::VideoSourceInterface<VideoFrame> {
40 public:
41 ~MockVideoSourceWithVideoFrame() override {}
42
Danil Chapovalov91fdc602020-05-14 17:17:5143 MOCK_METHOD(void,
44 AddOrUpdateSink,
45 (rtc::VideoSinkInterface<VideoFrame>*,
46 const rtc::VideoSinkWants&),
47 (override));
48 MOCK_METHOD(void,
49 RemoveSink,
50 (rtc::VideoSinkInterface<VideoFrame>*),
51 (override));
Markus Handell2e0f4f02021-12-21 18:14:5852 MOCK_METHOD(void, RequestRefreshFrame, (), (override));
Henrik Boströmce0ea492020-01-13 10:27:1853};
54
55} // namespace
56
57TEST(VideoSourceSinkControllerTest, UnconstrainedByDefault) {
58 MockVideoSinkWithVideoFrame sink;
59 MockVideoSourceWithVideoFrame source;
60 VideoSourceSinkController controller(&sink, &source);
61 EXPECT_EQ(controller.restrictions(), VideoSourceRestrictions());
62 EXPECT_FALSE(controller.pixels_per_frame_upper_limit().has_value());
63 EXPECT_FALSE(controller.frame_rate_upper_limit().has_value());
64 EXPECT_FALSE(controller.rotation_applied());
Jonas Oreland0deda152022-09-23 10:08:5765 EXPECT_FALSE(controller.requested_resolution().has_value());
Henrik Boströmce0ea492020-01-13 10:27:1866 EXPECT_EQ(controller.resolution_alignment(), 1);
67
68 EXPECT_CALL(source, AddOrUpdateSink(_, _))
69 .WillOnce([](rtc::VideoSinkInterface<VideoFrame>* sink,
70 const rtc::VideoSinkWants& wants) {
71 EXPECT_FALSE(wants.rotation_applied);
72 EXPECT_EQ(wants.max_pixel_count, kIntUnconstrained);
73 EXPECT_EQ(wants.target_pixel_count, absl::nullopt);
74 EXPECT_EQ(wants.max_framerate_fps, kIntUnconstrained);
75 EXPECT_EQ(wants.resolution_alignment, 1);
Jonas Oreland0deda152022-09-23 10:08:5776 EXPECT_FALSE(wants.requested_resolution.has_value());
Henrik Boströmce0ea492020-01-13 10:27:1877 });
78 controller.PushSourceSinkSettings();
79}
80
81TEST(VideoSourceSinkControllerTest, VideoRestrictionsToSinkWants) {
82 MockVideoSinkWithVideoFrame sink;
83 MockVideoSourceWithVideoFrame source;
84 VideoSourceSinkController controller(&sink, &source);
85
Henrik Boströmce0ea492020-01-13 10:27:1886 VideoSourceRestrictions restrictions = controller.restrictions();
Artem Titovab30d722021-07-27 14:22:1187 // max_pixels_per_frame() maps to `max_pixel_count`.
Henrik Boströmce0ea492020-01-13 10:27:1888 restrictions.set_max_pixels_per_frame(42u);
Artem Titovab30d722021-07-27 14:22:1189 // target_pixels_per_frame() maps to `target_pixel_count`.
Henrik Boströmce0ea492020-01-13 10:27:1890 restrictions.set_target_pixels_per_frame(200u);
Artem Titovab30d722021-07-27 14:22:1191 // max_frame_rate() maps to `max_framerate_fps`.
Henrik Boströmce0ea492020-01-13 10:27:1892 restrictions.set_max_frame_rate(30.0);
93 controller.SetRestrictions(restrictions);
94 EXPECT_CALL(source, AddOrUpdateSink(_, _))
95 .WillOnce([](rtc::VideoSinkInterface<VideoFrame>* sink,
96 const rtc::VideoSinkWants& wants) {
97 EXPECT_EQ(wants.max_pixel_count, 42);
98 EXPECT_EQ(wants.target_pixel_count, 200);
99 EXPECT_EQ(wants.max_framerate_fps, 30);
100 });
101 controller.PushSourceSinkSettings();
102
Artem Titovab30d722021-07-27 14:22:11103 // pixels_per_frame_upper_limit() caps `max_pixel_count`.
Henrik Boströmce0ea492020-01-13 10:27:18104 controller.SetPixelsPerFrameUpperLimit(24);
Artem Titovab30d722021-07-27 14:22:11105 // frame_rate_upper_limit() caps `max_framerate_fps`.
Henrik Boströmce0ea492020-01-13 10:27:18106 controller.SetFrameRateUpperLimit(10.0);
107
108 EXPECT_CALL(source, AddOrUpdateSink(_, _))
109 .WillOnce([](rtc::VideoSinkInterface<VideoFrame>* sink,
110 const rtc::VideoSinkWants& wants) {
111 EXPECT_EQ(wants.max_pixel_count, 24);
112 EXPECT_EQ(wants.max_framerate_fps, 10);
113 });
114 controller.PushSourceSinkSettings();
115}
116
117TEST(VideoSourceSinkControllerTest, RotationApplied) {
118 MockVideoSinkWithVideoFrame sink;
119 MockVideoSourceWithVideoFrame source;
120 VideoSourceSinkController controller(&sink, &source);
121 controller.SetRotationApplied(true);
122 EXPECT_TRUE(controller.rotation_applied());
123
124 EXPECT_CALL(source, AddOrUpdateSink(_, _))
125 .WillOnce([](rtc::VideoSinkInterface<VideoFrame>* sink,
126 const rtc::VideoSinkWants& wants) {
127 EXPECT_TRUE(wants.rotation_applied);
128 });
129 controller.PushSourceSinkSettings();
130}
131
132TEST(VideoSourceSinkControllerTest, ResolutionAlignment) {
133 MockVideoSinkWithVideoFrame sink;
134 MockVideoSourceWithVideoFrame source;
135 VideoSourceSinkController controller(&sink, &source);
136 controller.SetResolutionAlignment(13);
137 EXPECT_EQ(controller.resolution_alignment(), 13);
138
139 EXPECT_CALL(source, AddOrUpdateSink(_, _))
140 .WillOnce([](rtc::VideoSinkInterface<VideoFrame>* sink,
141 const rtc::VideoSinkWants& wants) {
142 EXPECT_EQ(wants.resolution_alignment, 13);
143 });
144 controller.PushSourceSinkSettings();
145}
146
147TEST(VideoSourceSinkControllerTest,
148 PushSourceSinkSettingsWithoutSourceDoesNotCrash) {
149 MockVideoSinkWithVideoFrame sink;
150 VideoSourceSinkController controller(&sink, nullptr);
151 controller.PushSourceSinkSettings();
152}
153
Markus Handell2e0f4f02021-12-21 18:14:58154TEST(VideoSourceSinkControllerTest, RequestsRefreshFrameWithSource) {
155 MockVideoSinkWithVideoFrame sink;
156 MockVideoSourceWithVideoFrame source;
157 VideoSourceSinkController controller(&sink, &source);
158 EXPECT_CALL(source, RequestRefreshFrame);
159 controller.RequestRefreshFrame();
160}
161
162TEST(VideoSourceSinkControllerTest,
163 RequestsRefreshFrameWithoutSourceDoesNotCrash) {
164 MockVideoSinkWithVideoFrame sink;
165 VideoSourceSinkController controller(&sink, nullptr);
166 controller.RequestRefreshFrame();
167}
Jonas Oreland0deda152022-09-23 10:08:57168
169TEST(VideoSourceSinkControllerTest, RequestedResolutionPropagatesToWants) {
170 MockVideoSinkWithVideoFrame sink;
171 MockVideoSourceWithVideoFrame source;
172 VideoSourceSinkController controller(&sink, &source);
173 controller.SetRequestedResolution(FrameSize(640, 360));
174 EXPECT_TRUE(controller.requested_resolution().has_value());
175
176 EXPECT_CALL(source, AddOrUpdateSink(_, _))
177 .WillOnce([](rtc::VideoSinkInterface<VideoFrame>* sink,
178 const rtc::VideoSinkWants& wants) {
179 EXPECT_EQ(*wants.requested_resolution, FrameSize(640, 360));
180 });
181 controller.PushSourceSinkSettings();
182}
183
184TEST(VideoSourceSinkControllerTest, ActivePropagatesToWants) {
185 MockVideoSinkWithVideoFrame sink;
186 MockVideoSourceWithVideoFrame source;
187 VideoSourceSinkController controller(&sink, &source);
188 controller.SetActive(true);
189 EXPECT_TRUE(controller.active());
190
191 EXPECT_CALL(source, AddOrUpdateSink(_, _))
192 .WillOnce([](rtc::VideoSinkInterface<VideoFrame>* sink,
193 const rtc::VideoSinkWants& wants) {
194 EXPECT_TRUE(wants.is_active);
195 });
196 controller.PushSourceSinkSettings();
197}
198
Henrik Boströmce0ea492020-01-13 10:27:18199} // namespace webrtc