• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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