tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

video_broadcaster_unittest.cc (14709B)


      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 #include <optional>
     15 
     16 #include "api/scoped_refptr.h"
     17 #include "api/video/i420_buffer.h"
     18 #include "api/video/video_frame.h"
     19 #include "api/video/video_rotation.h"
     20 #include "api/video/video_sink_interface.h"
     21 #include "api/video/video_source_interface.h"
     22 #include "api/video_track_source_constraints.h"
     23 #include "media/base/fake_video_renderer.h"
     24 #include "test/gmock.h"
     25 #include "test/gtest.h"
     26 
     27 using ::webrtc::FakeVideoRenderer;
     28 using ::webrtc::VideoBroadcaster;
     29 using ::webrtc::VideoSinkWants;
     30 using FrameSize = webrtc::VideoSinkWants::FrameSize;
     31 
     32 using ::testing::AllOf;
     33 using ::testing::Eq;
     34 using ::testing::Field;
     35 using ::testing::Mock;
     36 using ::testing::Optional;
     37 
     38 class MockSink : public webrtc::VideoSinkInterface<webrtc::VideoFrame> {
     39 public:
     40  void OnFrame(const webrtc::VideoFrame&) override {}
     41 
     42  MOCK_METHOD(void,
     43              OnConstraintsChanged,
     44              (const webrtc::VideoTrackSourceConstraints& constraints),
     45              (override));
     46 };
     47 
     48 TEST(VideoBroadcasterTest, frame_wanted) {
     49  VideoBroadcaster broadcaster;
     50  EXPECT_FALSE(broadcaster.frame_wanted());
     51 
     52  FakeVideoRenderer sink;
     53  broadcaster.AddOrUpdateSink(&sink, webrtc::VideoSinkWants());
     54  EXPECT_TRUE(broadcaster.frame_wanted());
     55 
     56  broadcaster.RemoveSink(&sink);
     57  EXPECT_FALSE(broadcaster.frame_wanted());
     58 }
     59 
     60 TEST(VideoBroadcasterTest, OnFrame) {
     61  VideoBroadcaster broadcaster;
     62 
     63  FakeVideoRenderer sink1;
     64  FakeVideoRenderer sink2;
     65  broadcaster.AddOrUpdateSink(&sink1, webrtc::VideoSinkWants());
     66  broadcaster.AddOrUpdateSink(&sink2, webrtc::VideoSinkWants());
     67  static int kWidth = 100;
     68  static int kHeight = 50;
     69 
     70  webrtc::scoped_refptr<webrtc::I420Buffer> buffer(
     71      webrtc::I420Buffer::Create(kWidth, kHeight));
     72  // Initialize, to avoid warnings on use of initialized values.
     73  webrtc::I420Buffer::SetBlack(buffer.get());
     74 
     75  webrtc::VideoFrame frame = webrtc::VideoFrame::Builder()
     76                                 .set_video_frame_buffer(buffer)
     77                                 .set_rotation(webrtc::kVideoRotation_0)
     78                                 .set_timestamp_us(0)
     79                                 .build();
     80 
     81  broadcaster.OnFrame(frame);
     82  EXPECT_EQ(1, sink1.num_rendered_frames());
     83  EXPECT_EQ(1, sink2.num_rendered_frames());
     84 
     85  broadcaster.RemoveSink(&sink1);
     86  broadcaster.OnFrame(frame);
     87  EXPECT_EQ(1, sink1.num_rendered_frames());
     88  EXPECT_EQ(2, sink2.num_rendered_frames());
     89 
     90  broadcaster.AddOrUpdateSink(&sink1, webrtc::VideoSinkWants());
     91  broadcaster.OnFrame(frame);
     92  EXPECT_EQ(2, sink1.num_rendered_frames());
     93  EXPECT_EQ(3, sink2.num_rendered_frames());
     94 }
     95 
     96 TEST(VideoBroadcasterTest, AppliesRotationIfAnySinkWantsRotationApplied) {
     97  VideoBroadcaster broadcaster;
     98  EXPECT_FALSE(broadcaster.wants().rotation_applied);
     99 
    100  FakeVideoRenderer sink1;
    101  VideoSinkWants wants1;
    102  wants1.rotation_applied = false;
    103 
    104  broadcaster.AddOrUpdateSink(&sink1, wants1);
    105  EXPECT_FALSE(broadcaster.wants().rotation_applied);
    106 
    107  FakeVideoRenderer sink2;
    108  VideoSinkWants wants2;
    109  wants2.rotation_applied = true;
    110 
    111  broadcaster.AddOrUpdateSink(&sink2, wants2);
    112  EXPECT_TRUE(broadcaster.wants().rotation_applied);
    113 
    114  broadcaster.RemoveSink(&sink2);
    115  EXPECT_FALSE(broadcaster.wants().rotation_applied);
    116 }
    117 
    118 TEST(VideoBroadcasterTest, AppliesMinOfSinkWantsMaxPixelCount) {
    119  VideoBroadcaster broadcaster;
    120  EXPECT_EQ(std::numeric_limits<int>::max(),
    121            broadcaster.wants().max_pixel_count);
    122 
    123  FakeVideoRenderer sink1;
    124  VideoSinkWants wants1;
    125  wants1.max_pixel_count = 1280 * 720;
    126 
    127  broadcaster.AddOrUpdateSink(&sink1, wants1);
    128  EXPECT_EQ(1280 * 720, broadcaster.wants().max_pixel_count);
    129 
    130  FakeVideoRenderer sink2;
    131  VideoSinkWants wants2;
    132  wants2.max_pixel_count = 640 * 360;
    133  broadcaster.AddOrUpdateSink(&sink2, wants2);
    134  EXPECT_EQ(640 * 360, broadcaster.wants().max_pixel_count);
    135 
    136  broadcaster.RemoveSink(&sink2);
    137  EXPECT_EQ(1280 * 720, broadcaster.wants().max_pixel_count);
    138 }
    139 
    140 TEST(VideoBroadcasterTest, AppliesMinOfSinkWantsMaxAndTargetPixelCount) {
    141  VideoBroadcaster broadcaster;
    142  EXPECT_TRUE(!broadcaster.wants().target_pixel_count);
    143 
    144  FakeVideoRenderer sink1;
    145  VideoSinkWants wants1;
    146  wants1.target_pixel_count = 1280 * 720;
    147 
    148  broadcaster.AddOrUpdateSink(&sink1, wants1);
    149  EXPECT_EQ(1280 * 720, *broadcaster.wants().target_pixel_count);
    150 
    151  FakeVideoRenderer sink2;
    152  VideoSinkWants wants2;
    153  wants2.target_pixel_count = 640 * 360;
    154  broadcaster.AddOrUpdateSink(&sink2, wants2);
    155  EXPECT_EQ(640 * 360, *broadcaster.wants().target_pixel_count);
    156 
    157  broadcaster.RemoveSink(&sink2);
    158  EXPECT_EQ(1280 * 720, *broadcaster.wants().target_pixel_count);
    159 }
    160 
    161 TEST(VideoBroadcasterTest, AppliesMinOfSinkWantsMaxFramerate) {
    162  VideoBroadcaster broadcaster;
    163  EXPECT_EQ(std::numeric_limits<int>::max(),
    164            broadcaster.wants().max_framerate_fps);
    165 
    166  FakeVideoRenderer sink1;
    167  VideoSinkWants wants1;
    168  wants1.max_framerate_fps = 30;
    169 
    170  broadcaster.AddOrUpdateSink(&sink1, wants1);
    171  EXPECT_EQ(30, broadcaster.wants().max_framerate_fps);
    172 
    173  FakeVideoRenderer sink2;
    174  VideoSinkWants wants2;
    175  wants2.max_framerate_fps = 15;
    176  broadcaster.AddOrUpdateSink(&sink2, wants2);
    177  EXPECT_EQ(15, broadcaster.wants().max_framerate_fps);
    178 
    179  broadcaster.RemoveSink(&sink2);
    180  EXPECT_EQ(30, broadcaster.wants().max_framerate_fps);
    181 }
    182 
    183 TEST(VideoBroadcasterTest,
    184     AppliesLeastCommonMultipleOfSinkWantsResolutionAlignment) {
    185  VideoBroadcaster broadcaster;
    186  EXPECT_EQ(broadcaster.wants().resolution_alignment, 1);
    187 
    188  FakeVideoRenderer sink1;
    189  VideoSinkWants wants1;
    190  wants1.resolution_alignment = 2;
    191  broadcaster.AddOrUpdateSink(&sink1, wants1);
    192  EXPECT_EQ(broadcaster.wants().resolution_alignment, 2);
    193 
    194  FakeVideoRenderer sink2;
    195  VideoSinkWants wants2;
    196  wants2.resolution_alignment = 3;
    197  broadcaster.AddOrUpdateSink(&sink2, wants2);
    198  EXPECT_EQ(broadcaster.wants().resolution_alignment, 6);
    199 
    200  FakeVideoRenderer sink3;
    201  VideoSinkWants wants3;
    202  wants3.resolution_alignment = 4;
    203  broadcaster.AddOrUpdateSink(&sink3, wants3);
    204  EXPECT_EQ(broadcaster.wants().resolution_alignment, 12);
    205 
    206  broadcaster.RemoveSink(&sink2);
    207  EXPECT_EQ(broadcaster.wants().resolution_alignment, 4);
    208 }
    209 
    210 TEST(VideoBroadcasterTest, SinkWantsBlackFrames) {
    211  VideoBroadcaster broadcaster;
    212  EXPECT_TRUE(!broadcaster.wants().black_frames);
    213 
    214  FakeVideoRenderer sink1;
    215  VideoSinkWants wants1;
    216  wants1.black_frames = true;
    217  broadcaster.AddOrUpdateSink(&sink1, wants1);
    218 
    219  FakeVideoRenderer sink2;
    220  VideoSinkWants wants2;
    221  wants2.black_frames = false;
    222  broadcaster.AddOrUpdateSink(&sink2, wants2);
    223 
    224  webrtc::scoped_refptr<webrtc::I420Buffer> buffer(
    225      webrtc::I420Buffer::Create(100, 200));
    226  // Makes it not all black.
    227  buffer->InitializeData();
    228 
    229  webrtc::VideoFrame frame1 = webrtc::VideoFrame::Builder()
    230                                  .set_video_frame_buffer(buffer)
    231                                  .set_rotation(webrtc::kVideoRotation_0)
    232                                  .set_timestamp_us(10)
    233                                  .build();
    234  broadcaster.OnFrame(frame1);
    235  EXPECT_TRUE(sink1.black_frame());
    236  EXPECT_EQ(10, sink1.timestamp_us());
    237  EXPECT_FALSE(sink2.black_frame());
    238  EXPECT_EQ(10, sink2.timestamp_us());
    239 
    240  // Switch the sink wants.
    241  wants1.black_frames = false;
    242  broadcaster.AddOrUpdateSink(&sink1, wants1);
    243  wants2.black_frames = true;
    244  broadcaster.AddOrUpdateSink(&sink2, wants2);
    245 
    246  webrtc::VideoFrame frame2 = webrtc::VideoFrame::Builder()
    247                                  .set_video_frame_buffer(buffer)
    248                                  .set_rotation(webrtc::kVideoRotation_0)
    249                                  .set_timestamp_us(30)
    250                                  .build();
    251  broadcaster.OnFrame(frame2);
    252  EXPECT_FALSE(sink1.black_frame());
    253  EXPECT_EQ(30, sink1.timestamp_us());
    254  EXPECT_TRUE(sink2.black_frame());
    255  EXPECT_EQ(30, sink2.timestamp_us());
    256 }
    257 
    258 TEST(VideoBroadcasterTest, ConstraintsChangedNotCalledOnSinkAddition) {
    259  MockSink sink;
    260  VideoBroadcaster broadcaster;
    261  EXPECT_CALL(sink, OnConstraintsChanged).Times(0);
    262  broadcaster.AddOrUpdateSink(&sink, VideoSinkWants());
    263 }
    264 
    265 TEST(VideoBroadcasterTest, ForwardsLastConstraintsOnAdd) {
    266  MockSink sink;
    267  VideoBroadcaster broadcaster;
    268  broadcaster.ProcessConstraints({.min_fps = 2, .max_fps = 3});
    269  broadcaster.ProcessConstraints({.min_fps = 1, .max_fps = 4});
    270  EXPECT_CALL(
    271      sink,
    272      OnConstraintsChanged(AllOf(
    273          Field(&webrtc::VideoTrackSourceConstraints::min_fps, Optional(1)),
    274          Field(&webrtc::VideoTrackSourceConstraints::max_fps, Optional(4)))));
    275  broadcaster.AddOrUpdateSink(&sink, VideoSinkWants());
    276 }
    277 
    278 TEST(VideoBroadcasterTest, UpdatesOnlyNewSinksWithConstraints) {
    279  MockSink sink1;
    280  VideoBroadcaster broadcaster;
    281  broadcaster.AddOrUpdateSink(&sink1, VideoSinkWants());
    282  broadcaster.ProcessConstraints({.min_fps = 1, .max_fps = 4});
    283  Mock::VerifyAndClearExpectations(&sink1);
    284  EXPECT_CALL(sink1, OnConstraintsChanged).Times(0);
    285  MockSink sink2;
    286  EXPECT_CALL(
    287      sink2,
    288      OnConstraintsChanged(AllOf(
    289          Field(&webrtc::VideoTrackSourceConstraints::min_fps, Optional(1)),
    290          Field(&webrtc::VideoTrackSourceConstraints::max_fps, Optional(4)))));
    291  broadcaster.AddOrUpdateSink(&sink2, VideoSinkWants());
    292 }
    293 
    294 TEST(VideoBroadcasterTest, ForwardsConstraintsToSink) {
    295  MockSink sink;
    296  VideoBroadcaster broadcaster;
    297  EXPECT_CALL(sink, OnConstraintsChanged).Times(0);
    298  broadcaster.AddOrUpdateSink(&sink, VideoSinkWants());
    299  Mock::VerifyAndClearExpectations(&sink);
    300 
    301  EXPECT_CALL(sink, OnConstraintsChanged(AllOf(
    302                        Field(&webrtc::VideoTrackSourceConstraints::min_fps,
    303                              Eq(std::nullopt)),
    304                        Field(&webrtc::VideoTrackSourceConstraints::max_fps,
    305                              Eq(std::nullopt)))));
    306  broadcaster.ProcessConstraints(
    307      {.min_fps = std::nullopt, .max_fps = std::nullopt});
    308  Mock::VerifyAndClearExpectations(&sink);
    309 
    310  EXPECT_CALL(
    311      sink,
    312      OnConstraintsChanged(AllOf(
    313          Field(&webrtc::VideoTrackSourceConstraints::min_fps,
    314                Eq(std::nullopt)),
    315          Field(&webrtc::VideoTrackSourceConstraints::max_fps, Optional(3)))));
    316  broadcaster.ProcessConstraints({.min_fps = std::nullopt, .max_fps = 3});
    317  Mock::VerifyAndClearExpectations(&sink);
    318 
    319  EXPECT_CALL(
    320      sink,
    321      OnConstraintsChanged(AllOf(
    322          Field(&webrtc::VideoTrackSourceConstraints::min_fps, Optional(2)),
    323          Field(&webrtc::VideoTrackSourceConstraints::max_fps,
    324                Eq(std::nullopt)))));
    325  broadcaster.ProcessConstraints({.min_fps = 2, .max_fps = std::nullopt});
    326  Mock::VerifyAndClearExpectations(&sink);
    327 
    328  EXPECT_CALL(
    329      sink,
    330      OnConstraintsChanged(AllOf(
    331          Field(&webrtc::VideoTrackSourceConstraints::min_fps, Optional(2)),
    332          Field(&webrtc::VideoTrackSourceConstraints::max_fps, Optional(3)))));
    333  broadcaster.ProcessConstraints({.min_fps = 2, .max_fps = 3});
    334 }
    335 
    336 TEST(VideoBroadcasterTest, AppliesMaxOfSinkWantsScaleResolutionDownTo) {
    337  VideoBroadcaster broadcaster;
    338 
    339  FakeVideoRenderer sink1;
    340  VideoSinkWants wants1;
    341  wants1.is_active = true;
    342  wants1.requested_resolution = FrameSize(640, 360);
    343 
    344  broadcaster.AddOrUpdateSink(&sink1, wants1);
    345  EXPECT_EQ(FrameSize(640, 360), *broadcaster.wants().requested_resolution);
    346 
    347  FakeVideoRenderer sink2;
    348  VideoSinkWants wants2;
    349  wants2.is_active = true;
    350  wants2.requested_resolution = FrameSize(650, 350);
    351  broadcaster.AddOrUpdateSink(&sink2, wants2);
    352  EXPECT_EQ(FrameSize(650, 360), *broadcaster.wants().requested_resolution);
    353 
    354  broadcaster.RemoveSink(&sink2);
    355  EXPECT_EQ(FrameSize(640, 360), *broadcaster.wants().requested_resolution);
    356 }
    357 
    358 TEST(VideoBroadcasterTest, AnyActive) {
    359  VideoBroadcaster broadcaster;
    360 
    361  FakeVideoRenderer sink1;
    362  VideoSinkWants wants1;
    363  wants1.is_active = false;
    364 
    365  broadcaster.AddOrUpdateSink(&sink1, wants1);
    366  EXPECT_EQ(false, broadcaster.wants().is_active);
    367 
    368  FakeVideoRenderer sink2;
    369  VideoSinkWants wants2;
    370  wants2.is_active = true;
    371  broadcaster.AddOrUpdateSink(&sink2, wants2);
    372  EXPECT_EQ(true, broadcaster.wants().is_active);
    373 
    374  broadcaster.RemoveSink(&sink2);
    375  EXPECT_EQ(false, broadcaster.wants().is_active);
    376 }
    377 
    378 TEST(VideoBroadcasterTest, AnyActiveWithoutScaleResolutionDownTo) {
    379  VideoBroadcaster broadcaster;
    380 
    381  FakeVideoRenderer sink1;
    382  VideoSinkWants wants1;
    383  wants1.is_active = true;
    384  wants1.requested_resolution = FrameSize(640, 360);
    385 
    386  broadcaster.AddOrUpdateSink(&sink1, wants1);
    387  EXPECT_EQ(
    388      false,
    389      broadcaster.wants().aggregates->any_active_without_requested_resolution);
    390 
    391  FakeVideoRenderer sink2;
    392  VideoSinkWants wants2;
    393  wants2.is_active = true;
    394  broadcaster.AddOrUpdateSink(&sink2, wants2);
    395  EXPECT_EQ(
    396      true,
    397      broadcaster.wants().aggregates->any_active_without_requested_resolution);
    398 
    399  broadcaster.RemoveSink(&sink2);
    400  EXPECT_EQ(
    401      false,
    402      broadcaster.wants().aggregates->any_active_without_requested_resolution);
    403 }
    404 
    405 // This verifies that the VideoSinkWants from a Sink that is_active = false
    406 // is ignored IF there is an active sink using requested_resolution (controlled
    407 // via new API scale_resolution_down_to). The uses resolution_alignment for
    408 // verification.
    409 TEST(VideoBroadcasterTest, IgnoreInactiveSinkIfNewApiUsed) {
    410  VideoBroadcaster broadcaster;
    411 
    412  FakeVideoRenderer sink1;
    413  VideoSinkWants wants1;
    414  wants1.is_active = true;
    415  wants1.requested_resolution = FrameSize(640, 360);
    416  wants1.resolution_alignment = 2;
    417  broadcaster.AddOrUpdateSink(&sink1, wants1);
    418  EXPECT_EQ(broadcaster.wants().resolution_alignment, 2);
    419 
    420  FakeVideoRenderer sink2;
    421  VideoSinkWants wants2;
    422  wants2.is_active = true;
    423  wants2.resolution_alignment = 8;
    424  broadcaster.AddOrUpdateSink(&sink2, wants2);
    425  EXPECT_EQ(broadcaster.wants().resolution_alignment, 8);
    426 
    427  // Now wants2 will be ignored.
    428  wants2.is_active = false;
    429  broadcaster.AddOrUpdateSink(&sink2, wants2);
    430  EXPECT_EQ(broadcaster.wants().resolution_alignment, 2);
    431 
    432  // But when wants1 is inactive, wants2 matters again.
    433  wants1.is_active = false;
    434  broadcaster.AddOrUpdateSink(&sink1, wants1);
    435  EXPECT_EQ(broadcaster.wants().resolution_alignment, 8);
    436 
    437  // inactive wants1 (new api) is always ignored.
    438  broadcaster.RemoveSink(&sink2);
    439  EXPECT_EQ(broadcaster.wants().resolution_alignment, 1);
    440 }