1 /*
2 * Copyright 2016 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 "media/base/video_broadcaster.h"
12
13 #include <limits>
14
15 #include "absl/types/optional.h"
16 #include "api/video/i420_buffer.h"
17 #include "api/video/video_frame.h"
18 #include "api/video/video_rotation.h"
19 #include "media/base/fake_video_renderer.h"
20 #include "test/gtest.h"
21
22 using cricket::FakeVideoRenderer;
23 using rtc::VideoBroadcaster;
24 using rtc::VideoSinkWants;
25
TEST(VideoBroadcasterTest,frame_wanted)26 TEST(VideoBroadcasterTest, frame_wanted) {
27 VideoBroadcaster broadcaster;
28 EXPECT_FALSE(broadcaster.frame_wanted());
29
30 FakeVideoRenderer sink;
31 broadcaster.AddOrUpdateSink(&sink, rtc::VideoSinkWants());
32 EXPECT_TRUE(broadcaster.frame_wanted());
33
34 broadcaster.RemoveSink(&sink);
35 EXPECT_FALSE(broadcaster.frame_wanted());
36 }
37
TEST(VideoBroadcasterTest,OnFrame)38 TEST(VideoBroadcasterTest, OnFrame) {
39 VideoBroadcaster broadcaster;
40
41 FakeVideoRenderer sink1;
42 FakeVideoRenderer sink2;
43 broadcaster.AddOrUpdateSink(&sink1, rtc::VideoSinkWants());
44 broadcaster.AddOrUpdateSink(&sink2, rtc::VideoSinkWants());
45 static int kWidth = 100;
46 static int kHeight = 50;
47
48 rtc::scoped_refptr<webrtc::I420Buffer> buffer(
49 webrtc::I420Buffer::Create(kWidth, kHeight));
50 // Initialize, to avoid warnings on use of initialized values.
51 webrtc::I420Buffer::SetBlack(buffer);
52
53 webrtc::VideoFrame frame = webrtc::VideoFrame::Builder()
54 .set_video_frame_buffer(buffer)
55 .set_rotation(webrtc::kVideoRotation_0)
56 .set_timestamp_us(0)
57 .build();
58
59 broadcaster.OnFrame(frame);
60 EXPECT_EQ(1, sink1.num_rendered_frames());
61 EXPECT_EQ(1, sink2.num_rendered_frames());
62
63 broadcaster.RemoveSink(&sink1);
64 broadcaster.OnFrame(frame);
65 EXPECT_EQ(1, sink1.num_rendered_frames());
66 EXPECT_EQ(2, sink2.num_rendered_frames());
67
68 broadcaster.AddOrUpdateSink(&sink1, rtc::VideoSinkWants());
69 broadcaster.OnFrame(frame);
70 EXPECT_EQ(2, sink1.num_rendered_frames());
71 EXPECT_EQ(3, sink2.num_rendered_frames());
72 }
73
TEST(VideoBroadcasterTest,AppliesRotationIfAnySinkWantsRotationApplied)74 TEST(VideoBroadcasterTest, AppliesRotationIfAnySinkWantsRotationApplied) {
75 VideoBroadcaster broadcaster;
76 EXPECT_FALSE(broadcaster.wants().rotation_applied);
77
78 FakeVideoRenderer sink1;
79 VideoSinkWants wants1;
80 wants1.rotation_applied = false;
81
82 broadcaster.AddOrUpdateSink(&sink1, wants1);
83 EXPECT_FALSE(broadcaster.wants().rotation_applied);
84
85 FakeVideoRenderer sink2;
86 VideoSinkWants wants2;
87 wants2.rotation_applied = true;
88
89 broadcaster.AddOrUpdateSink(&sink2, wants2);
90 EXPECT_TRUE(broadcaster.wants().rotation_applied);
91
92 broadcaster.RemoveSink(&sink2);
93 EXPECT_FALSE(broadcaster.wants().rotation_applied);
94 }
95
TEST(VideoBroadcasterTest,AppliesMinOfSinkWantsMaxPixelCount)96 TEST(VideoBroadcasterTest, AppliesMinOfSinkWantsMaxPixelCount) {
97 VideoBroadcaster broadcaster;
98 EXPECT_EQ(std::numeric_limits<int>::max(),
99 broadcaster.wants().max_pixel_count);
100
101 FakeVideoRenderer sink1;
102 VideoSinkWants wants1;
103 wants1.max_pixel_count = 1280 * 720;
104
105 broadcaster.AddOrUpdateSink(&sink1, wants1);
106 EXPECT_EQ(1280 * 720, broadcaster.wants().max_pixel_count);
107
108 FakeVideoRenderer sink2;
109 VideoSinkWants wants2;
110 wants2.max_pixel_count = 640 * 360;
111 broadcaster.AddOrUpdateSink(&sink2, wants2);
112 EXPECT_EQ(640 * 360, broadcaster.wants().max_pixel_count);
113
114 broadcaster.RemoveSink(&sink2);
115 EXPECT_EQ(1280 * 720, broadcaster.wants().max_pixel_count);
116 }
117
TEST(VideoBroadcasterTest,AppliesMinOfSinkWantsMaxAndTargetPixelCount)118 TEST(VideoBroadcasterTest, AppliesMinOfSinkWantsMaxAndTargetPixelCount) {
119 VideoBroadcaster broadcaster;
120 EXPECT_TRUE(!broadcaster.wants().target_pixel_count);
121
122 FakeVideoRenderer sink1;
123 VideoSinkWants wants1;
124 wants1.target_pixel_count = 1280 * 720;
125
126 broadcaster.AddOrUpdateSink(&sink1, wants1);
127 EXPECT_EQ(1280 * 720, *broadcaster.wants().target_pixel_count);
128
129 FakeVideoRenderer sink2;
130 VideoSinkWants wants2;
131 wants2.target_pixel_count = 640 * 360;
132 broadcaster.AddOrUpdateSink(&sink2, wants2);
133 EXPECT_EQ(640 * 360, *broadcaster.wants().target_pixel_count);
134
135 broadcaster.RemoveSink(&sink2);
136 EXPECT_EQ(1280 * 720, *broadcaster.wants().target_pixel_count);
137 }
138
TEST(VideoBroadcasterTest,AppliesMinOfSinkWantsMaxFramerate)139 TEST(VideoBroadcasterTest, AppliesMinOfSinkWantsMaxFramerate) {
140 VideoBroadcaster broadcaster;
141 EXPECT_EQ(std::numeric_limits<int>::max(),
142 broadcaster.wants().max_framerate_fps);
143
144 FakeVideoRenderer sink1;
145 VideoSinkWants wants1;
146 wants1.max_framerate_fps = 30;
147
148 broadcaster.AddOrUpdateSink(&sink1, wants1);
149 EXPECT_EQ(30, broadcaster.wants().max_framerate_fps);
150
151 FakeVideoRenderer sink2;
152 VideoSinkWants wants2;
153 wants2.max_framerate_fps = 15;
154 broadcaster.AddOrUpdateSink(&sink2, wants2);
155 EXPECT_EQ(15, broadcaster.wants().max_framerate_fps);
156
157 broadcaster.RemoveSink(&sink2);
158 EXPECT_EQ(30, broadcaster.wants().max_framerate_fps);
159 }
160
TEST(VideoBroadcasterTest,AppliesLeastCommonMultipleOfSinkWantsResolutionAlignment)161 TEST(VideoBroadcasterTest,
162 AppliesLeastCommonMultipleOfSinkWantsResolutionAlignment) {
163 VideoBroadcaster broadcaster;
164 EXPECT_EQ(broadcaster.wants().resolution_alignment, 1);
165
166 FakeVideoRenderer sink1;
167 VideoSinkWants wants1;
168 wants1.resolution_alignment = 2;
169 broadcaster.AddOrUpdateSink(&sink1, wants1);
170 EXPECT_EQ(broadcaster.wants().resolution_alignment, 2);
171
172 FakeVideoRenderer sink2;
173 VideoSinkWants wants2;
174 wants2.resolution_alignment = 3;
175 broadcaster.AddOrUpdateSink(&sink2, wants2);
176 EXPECT_EQ(broadcaster.wants().resolution_alignment, 6);
177
178 FakeVideoRenderer sink3;
179 VideoSinkWants wants3;
180 wants3.resolution_alignment = 4;
181 broadcaster.AddOrUpdateSink(&sink3, wants3);
182 EXPECT_EQ(broadcaster.wants().resolution_alignment, 12);
183
184 broadcaster.RemoveSink(&sink2);
185 EXPECT_EQ(broadcaster.wants().resolution_alignment, 4);
186 }
187
TEST(VideoBroadcasterTest,SinkWantsBlackFrames)188 TEST(VideoBroadcasterTest, SinkWantsBlackFrames) {
189 VideoBroadcaster broadcaster;
190 EXPECT_TRUE(!broadcaster.wants().black_frames);
191
192 FakeVideoRenderer sink1;
193 VideoSinkWants wants1;
194 wants1.black_frames = true;
195 broadcaster.AddOrUpdateSink(&sink1, wants1);
196
197 FakeVideoRenderer sink2;
198 VideoSinkWants wants2;
199 wants2.black_frames = false;
200 broadcaster.AddOrUpdateSink(&sink2, wants2);
201
202 rtc::scoped_refptr<webrtc::I420Buffer> buffer(
203 webrtc::I420Buffer::Create(100, 200));
204 // Makes it not all black.
205 buffer->InitializeData();
206
207 webrtc::VideoFrame frame1 = webrtc::VideoFrame::Builder()
208 .set_video_frame_buffer(buffer)
209 .set_rotation(webrtc::kVideoRotation_0)
210 .set_timestamp_us(10)
211 .build();
212 broadcaster.OnFrame(frame1);
213 EXPECT_TRUE(sink1.black_frame());
214 EXPECT_EQ(10, sink1.timestamp_us());
215 EXPECT_FALSE(sink2.black_frame());
216 EXPECT_EQ(10, sink2.timestamp_us());
217
218 // Switch the sink wants.
219 wants1.black_frames = false;
220 broadcaster.AddOrUpdateSink(&sink1, wants1);
221 wants2.black_frames = true;
222 broadcaster.AddOrUpdateSink(&sink2, wants2);
223
224 webrtc::VideoFrame frame2 = webrtc::VideoFrame::Builder()
225 .set_video_frame_buffer(buffer)
226 .set_rotation(webrtc::kVideoRotation_0)
227 .set_timestamp_us(30)
228 .build();
229 broadcaster.OnFrame(frame2);
230 EXPECT_FALSE(sink1.black_frame());
231 EXPECT_EQ(30, sink1.timestamp_us());
232 EXPECT_TRUE(sink2.black_frame());
233 EXPECT_EQ(30, sink2.timestamp_us());
234 }
235