diff options
Diffstat (limited to 'third_party/libwebrtc/video/video_source_sink_controller_unittest.cc')
-rw-r--r-- | third_party/libwebrtc/video/video_source_sink_controller_unittest.cc | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/third_party/libwebrtc/video/video_source_sink_controller_unittest.cc b/third_party/libwebrtc/video/video_source_sink_controller_unittest.cc new file mode 100644 index 0000000000..75cc52bdaf --- /dev/null +++ b/third_party/libwebrtc/video/video_source_sink_controller_unittest.cc @@ -0,0 +1,199 @@ +/* + * Copyright 2020 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "video/video_source_sink_controller.h" + +#include <limits> + +#include "api/video/video_frame.h" +#include "api/video/video_source_interface.h" +#include "call/adaptation/video_source_restrictions.h" +#include "test/gmock.h" +#include "test/gtest.h" + +using testing::_; + +namespace webrtc { + +namespace { + +using FrameSize = rtc::VideoSinkWants::FrameSize; +constexpr int kIntUnconstrained = std::numeric_limits<int>::max(); + +class MockVideoSinkWithVideoFrame : public rtc::VideoSinkInterface<VideoFrame> { + public: + ~MockVideoSinkWithVideoFrame() override {} + + MOCK_METHOD(void, OnFrame, (const VideoFrame& frame), (override)); + MOCK_METHOD(void, OnDiscardedFrame, (), (override)); +}; + +class MockVideoSourceWithVideoFrame + : public rtc::VideoSourceInterface<VideoFrame> { + public: + ~MockVideoSourceWithVideoFrame() override {} + + MOCK_METHOD(void, + AddOrUpdateSink, + (rtc::VideoSinkInterface<VideoFrame>*, + const rtc::VideoSinkWants&), + (override)); + MOCK_METHOD(void, + RemoveSink, + (rtc::VideoSinkInterface<VideoFrame>*), + (override)); + MOCK_METHOD(void, RequestRefreshFrame, (), (override)); +}; + +} // namespace + +TEST(VideoSourceSinkControllerTest, UnconstrainedByDefault) { + MockVideoSinkWithVideoFrame sink; + MockVideoSourceWithVideoFrame source; + VideoSourceSinkController controller(&sink, &source); + EXPECT_EQ(controller.restrictions(), VideoSourceRestrictions()); + EXPECT_FALSE(controller.pixels_per_frame_upper_limit().has_value()); + EXPECT_FALSE(controller.frame_rate_upper_limit().has_value()); + EXPECT_FALSE(controller.rotation_applied()); + EXPECT_FALSE(controller.requested_resolution().has_value()); + EXPECT_EQ(controller.resolution_alignment(), 1); + + EXPECT_CALL(source, AddOrUpdateSink(_, _)) + .WillOnce([](rtc::VideoSinkInterface<VideoFrame>* sink, + const rtc::VideoSinkWants& wants) { + EXPECT_FALSE(wants.rotation_applied); + EXPECT_EQ(wants.max_pixel_count, kIntUnconstrained); + EXPECT_EQ(wants.target_pixel_count, absl::nullopt); + EXPECT_EQ(wants.max_framerate_fps, kIntUnconstrained); + EXPECT_EQ(wants.resolution_alignment, 1); + EXPECT_FALSE(wants.requested_resolution.has_value()); + }); + controller.PushSourceSinkSettings(); +} + +TEST(VideoSourceSinkControllerTest, VideoRestrictionsToSinkWants) { + MockVideoSinkWithVideoFrame sink; + MockVideoSourceWithVideoFrame source; + VideoSourceSinkController controller(&sink, &source); + + VideoSourceRestrictions restrictions = controller.restrictions(); + // max_pixels_per_frame() maps to `max_pixel_count`. + restrictions.set_max_pixels_per_frame(42u); + // target_pixels_per_frame() maps to `target_pixel_count`. + restrictions.set_target_pixels_per_frame(200u); + // max_frame_rate() maps to `max_framerate_fps`. + restrictions.set_max_frame_rate(30.0); + controller.SetRestrictions(restrictions); + EXPECT_CALL(source, AddOrUpdateSink(_, _)) + .WillOnce([](rtc::VideoSinkInterface<VideoFrame>* sink, + const rtc::VideoSinkWants& wants) { + EXPECT_EQ(wants.max_pixel_count, 42); + EXPECT_EQ(wants.target_pixel_count, 200); + EXPECT_EQ(wants.max_framerate_fps, 30); + }); + controller.PushSourceSinkSettings(); + + // pixels_per_frame_upper_limit() caps `max_pixel_count`. + controller.SetPixelsPerFrameUpperLimit(24); + // frame_rate_upper_limit() caps `max_framerate_fps`. + controller.SetFrameRateUpperLimit(10.0); + + EXPECT_CALL(source, AddOrUpdateSink(_, _)) + .WillOnce([](rtc::VideoSinkInterface<VideoFrame>* sink, + const rtc::VideoSinkWants& wants) { + EXPECT_EQ(wants.max_pixel_count, 24); + EXPECT_EQ(wants.max_framerate_fps, 10); + }); + controller.PushSourceSinkSettings(); +} + +TEST(VideoSourceSinkControllerTest, RotationApplied) { + MockVideoSinkWithVideoFrame sink; + MockVideoSourceWithVideoFrame source; + VideoSourceSinkController controller(&sink, &source); + controller.SetRotationApplied(true); + EXPECT_TRUE(controller.rotation_applied()); + + EXPECT_CALL(source, AddOrUpdateSink(_, _)) + .WillOnce([](rtc::VideoSinkInterface<VideoFrame>* sink, + const rtc::VideoSinkWants& wants) { + EXPECT_TRUE(wants.rotation_applied); + }); + controller.PushSourceSinkSettings(); +} + +TEST(VideoSourceSinkControllerTest, ResolutionAlignment) { + MockVideoSinkWithVideoFrame sink; + MockVideoSourceWithVideoFrame source; + VideoSourceSinkController controller(&sink, &source); + controller.SetResolutionAlignment(13); + EXPECT_EQ(controller.resolution_alignment(), 13); + + EXPECT_CALL(source, AddOrUpdateSink(_, _)) + .WillOnce([](rtc::VideoSinkInterface<VideoFrame>* sink, + const rtc::VideoSinkWants& wants) { + EXPECT_EQ(wants.resolution_alignment, 13); + }); + controller.PushSourceSinkSettings(); +} + +TEST(VideoSourceSinkControllerTest, + PushSourceSinkSettingsWithoutSourceDoesNotCrash) { + MockVideoSinkWithVideoFrame sink; + VideoSourceSinkController controller(&sink, nullptr); + controller.PushSourceSinkSettings(); +} + +TEST(VideoSourceSinkControllerTest, RequestsRefreshFrameWithSource) { + MockVideoSinkWithVideoFrame sink; + MockVideoSourceWithVideoFrame source; + VideoSourceSinkController controller(&sink, &source); + EXPECT_CALL(source, RequestRefreshFrame); + controller.RequestRefreshFrame(); +} + +TEST(VideoSourceSinkControllerTest, + RequestsRefreshFrameWithoutSourceDoesNotCrash) { + MockVideoSinkWithVideoFrame sink; + VideoSourceSinkController controller(&sink, nullptr); + controller.RequestRefreshFrame(); +} + +TEST(VideoSourceSinkControllerTest, RequestedResolutionPropagatesToWants) { + MockVideoSinkWithVideoFrame sink; + MockVideoSourceWithVideoFrame source; + VideoSourceSinkController controller(&sink, &source); + controller.SetRequestedResolution(FrameSize(640, 360)); + EXPECT_TRUE(controller.requested_resolution().has_value()); + + EXPECT_CALL(source, AddOrUpdateSink(_, _)) + .WillOnce([](rtc::VideoSinkInterface<VideoFrame>* sink, + const rtc::VideoSinkWants& wants) { + EXPECT_EQ(*wants.requested_resolution, FrameSize(640, 360)); + }); + controller.PushSourceSinkSettings(); +} + +TEST(VideoSourceSinkControllerTest, ActivePropagatesToWants) { + MockVideoSinkWithVideoFrame sink; + MockVideoSourceWithVideoFrame source; + VideoSourceSinkController controller(&sink, &source); + controller.SetActive(true); + EXPECT_TRUE(controller.active()); + + EXPECT_CALL(source, AddOrUpdateSink(_, _)) + .WillOnce([](rtc::VideoSinkInterface<VideoFrame>* sink, + const rtc::VideoSinkWants& wants) { + EXPECT_TRUE(wants.is_active); + }); + controller.PushSourceSinkSettings(); +} + +} // namespace webrtc |