diff options
author | Sebastian Jansson <srte@webrtc.org> | 2018-04-19 17:09:15 +0200 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2018-04-20 13:12:13 +0000 |
commit | 652dc915bc88d15c5ffd520218f274234d5c8ea4 (patch) | |
tree | 2cfd715116a4c301d335d0c82dcdc25ef86981da /video | |
parent | 33444dc835b0d2b64d1d2b3dd406ace1d1264230 (diff) | |
download | webrtc-652dc915bc88d15c5ffd520218f274234d5c8ea4.tar.gz |
Adds unit tests for VideoSendStreamImpl.
Bug: None
Change-Id: Ifadad47af4769d8aca42c98832cea49a6c7977cd
Reviewed-on: https://webrtc-review.googlesource.com/71040
Reviewed-by: Niels Moller <nisse@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Commit-Queue: Sebastian Jansson <srte@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#22959}
Diffstat (limited to 'video')
-rw-r--r-- | video/BUILD.gn | 14 | ||||
-rw-r--r-- | video/encoder_rtcp_feedback.cc | 2 | ||||
-rw-r--r-- | video/encoder_rtcp_feedback.h | 8 | ||||
-rw-r--r-- | video/encoder_rtcp_feedback_unittest.cc | 24 | ||||
-rw-r--r-- | video/test/mock_video_stream_encoder.h | 44 | ||||
-rw-r--r-- | video/video_send_stream_impl.cc | 4 | ||||
-rw-r--r-- | video/video_send_stream_impl.h | 8 | ||||
-rw-r--r-- | video/video_send_stream_impl_unittest.cc | 183 | ||||
-rw-r--r-- | video/video_stream_encoder.h | 64 |
9 files changed, 298 insertions, 53 deletions
diff --git a/video/BUILD.gn b/video/BUILD.gn index 732b83a7ef..56ff9e66cb 100644 --- a/video/BUILD.gn +++ b/video/BUILD.gn @@ -127,6 +127,16 @@ rtc_source_set("video_stream_decoder_impl") { } if (rtc_include_tests) { + rtc_source_set("video_mocks") { + testonly = true + sources = [ + "test/mock_video_stream_encoder.h", + ] + deps = [ + ":video", + "../test:test_support", + ] + } rtc_source_set("video_quality_test") { testonly = true visibility = [ ":*" ] # Only targets in this file can depend on this. @@ -336,16 +346,19 @@ if (rtc_include_tests) { "stats_counter_unittest.cc", "stream_synchronization_unittest.cc", "video_receive_stream_unittest.cc", + "video_send_stream_impl_unittest.cc", "video_send_stream_tests.cc", "video_stream_encoder_unittest.cc", ] deps = [ ":video", + ":video_mocks", "../api:optional", "../api:video_frame_api", "../api:video_frame_api_i420", "../api/video_codecs:video_codecs_api", "../call:call_interfaces", + "../call:mock_bitrate_allocator", "../call:mock_rtp_interfaces", "../call:rtp_receiver", "../call:rtp_sender", @@ -377,6 +390,7 @@ if (rtc_include_tests) { "../rtc_base:rtc_base_tests_utils", "../rtc_base:rtc_numerics", "../rtc_base:rtc_task_queue", + "../rtc_base:rtc_task_queue_for_test", "../rtc_base/experiments:alr_experiment", "../system_wrappers", "../system_wrappers:field_trial_default", diff --git a/video/encoder_rtcp_feedback.cc b/video/encoder_rtcp_feedback.cc index 9e0227403d..f88bca94dd 100644 --- a/video/encoder_rtcp_feedback.cc +++ b/video/encoder_rtcp_feedback.cc @@ -19,7 +19,7 @@ namespace webrtc { EncoderRtcpFeedback::EncoderRtcpFeedback(Clock* clock, const std::vector<uint32_t>& ssrcs, - VideoStreamEncoder* encoder) + VideoStreamEncoderInterface* encoder) : clock_(clock), ssrcs_(ssrcs), video_stream_encoder_(encoder), diff --git a/video/encoder_rtcp_feedback.h b/video/encoder_rtcp_feedback.h index fd57558fc6..d66a78e121 100644 --- a/video/encoder_rtcp_feedback.h +++ b/video/encoder_rtcp_feedback.h @@ -19,13 +19,13 @@ namespace webrtc { -class VideoStreamEncoder; +class VideoStreamEncoderInterface; class EncoderRtcpFeedback : public RtcpIntraFrameObserver { public: EncoderRtcpFeedback(Clock* clock, - const std::vector<uint32_t>& ssrcs, - VideoStreamEncoder* encoder); + const std::vector<uint32_t>& ssrcs, + VideoStreamEncoderInterface* encoder); void OnReceivedIntraFrameRequest(uint32_t ssrc) override; private: @@ -34,7 +34,7 @@ class EncoderRtcpFeedback : public RtcpIntraFrameObserver { Clock* const clock_; const std::vector<uint32_t> ssrcs_; - VideoStreamEncoder* const video_stream_encoder_; + VideoStreamEncoderInterface* const video_stream_encoder_; rtc::CriticalSection crit_; std::vector<int64_t> time_last_intra_request_ms_ RTC_GUARDED_BY(crit_); diff --git a/video/encoder_rtcp_feedback_unittest.cc b/video/encoder_rtcp_feedback_unittest.cc index ec5a1ce011..1ce387b991 100644 --- a/video/encoder_rtcp_feedback_unittest.cc +++ b/video/encoder_rtcp_feedback_unittest.cc @@ -14,34 +14,17 @@ #include "test/gmock.h" #include "test/gtest.h" -#include "video/send_statistics_proxy.h" -#include "video/video_stream_encoder.h" +#include "video/test/mock_video_stream_encoder.h" using ::testing::NiceMock; namespace webrtc { -class MockVideoStreamEncoder : public VideoStreamEncoder { - public: - explicit MockVideoStreamEncoder(SendStatisticsProxy* send_stats_proxy) - : VideoStreamEncoder(1, - send_stats_proxy, - VideoSendStream::Config::EncoderSettings(), - nullptr, - rtc::MakeUnique<OveruseFrameDetector>(nullptr)) {} - ~MockVideoStreamEncoder() { Stop(); } - - MOCK_METHOD0(SendKeyFrame, void()); -}; - class VieKeyRequestTest : public ::testing::Test { public: VieKeyRequestTest() : simulated_clock_(123456789), - send_stats_proxy_(&simulated_clock_, - VideoSendStream::Config(nullptr), - VideoEncoderConfig::ContentType::kRealtimeVideo), - encoder_(&send_stats_proxy_), + encoder_(), encoder_rtcp_feedback_( &simulated_clock_, std::vector<uint32_t>(1, VieKeyRequestTest::kSsrc), @@ -51,8 +34,7 @@ class VieKeyRequestTest : public ::testing::Test { const uint32_t kSsrc = 1234; SimulatedClock simulated_clock_; - SendStatisticsProxy send_stats_proxy_; - MockVideoStreamEncoder encoder_; + testing::StrictMock<MockVideoStreamEncoder> encoder_; EncoderRtcpFeedback encoder_rtcp_feedback_; }; diff --git a/video/test/mock_video_stream_encoder.h b/video/test/mock_video_stream_encoder.h new file mode 100644 index 0000000000..55f6063f23 --- /dev/null +++ b/video/test/mock_video_stream_encoder.h @@ -0,0 +1,44 @@ +/* + * Copyright 2018 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. + */ +#ifndef VIDEO_TEST_MOCK_VIDEO_STREAM_ENCODER_H_ +#define VIDEO_TEST_MOCK_VIDEO_STREAM_ENCODER_H_ + +#include "test/gmock.h" +#include "video/video_stream_encoder.h" + +namespace webrtc { + +class MockVideoStreamEncoder : public VideoStreamEncoderInterface { + public: + MOCK_METHOD2(SetSource, + void(rtc::VideoSourceInterface<VideoFrame>*, + const VideoSendStream::DegradationPreference&)); + MOCK_METHOD2(SetSink, void(EncoderSink*, bool)); + MOCK_METHOD1(SetStartBitrate, void(int)); + MOCK_METHOD0(SendKeyFrame, void()); + MOCK_METHOD3(OnBitrateUpdated, void(uint32_t, uint8_t, int64_t)); + MOCK_METHOD1(OnFrame, void(const VideoFrame&)); + MOCK_METHOD1(SetBitrateObserver, void(VideoBitrateAllocationObserver*)); + MOCK_METHOD0(Stop, void()); + + MOCK_METHOD3(MockedConfigureEncoder, + void(const VideoEncoderConfig&, size_t, bool)); + // gtest generates implicit copy which is not allowed on VideoEncoderConfig, + // so we can't mock ConfigureEncoder directly. + void ConfigureEncoder(VideoEncoderConfig config, + size_t max_data_payload_length, + bool nack_enabled) { + MockedConfigureEncoder(config, max_data_payload_length, nack_enabled); + } +}; + +} // namespace webrtc + +#endif // VIDEO_TEST_MOCK_VIDEO_STREAM_ENCODER_H_ diff --git a/video/video_send_stream_impl.cc b/video/video_send_stream_impl.cc index 8d9b480026..5e032fc565 100644 --- a/video/video_send_stream_impl.cc +++ b/video/video_send_stream_impl.cc @@ -283,9 +283,9 @@ VideoSendStreamImpl::VideoSendStreamImpl( rtc::TaskQueue* worker_queue, CallStats* call_stats, RtpTransportControllerSendInterface* transport, - BitrateAllocator* bitrate_allocator, + BitrateAllocatorInterface* bitrate_allocator, SendDelayStats* send_delay_stats, - VideoStreamEncoder* video_stream_encoder, + VideoStreamEncoderInterface* video_stream_encoder, RtcEventLog* event_log, const VideoSendStream::Config* config, int initial_encoder_max_bitrate, diff --git a/video/video_send_stream_impl.h b/video/video_send_stream_impl.h index 8a52141bb5..d237dfdacb 100644 --- a/video/video_send_stream_impl.h +++ b/video/video_send_stream_impl.h @@ -52,9 +52,9 @@ class VideoSendStreamImpl : public webrtc::BitrateAllocatorObserver, rtc::TaskQueue* worker_queue, CallStats* call_stats, RtpTransportControllerSendInterface* transport, - BitrateAllocator* bitrate_allocator, + BitrateAllocatorInterface* bitrate_allocator, SendDelayStats* send_delay_stats, - VideoStreamEncoder* video_stream_encoder, + VideoStreamEncoderInterface* video_stream_encoder, RtcEventLog* event_log, const VideoSendStream::Config* config, int initial_encoder_max_bitrate, @@ -156,7 +156,7 @@ class VideoSendStreamImpl : public webrtc::BitrateAllocatorObserver, CallStats* const call_stats_; RtpTransportControllerSendInterface* const transport_; - BitrateAllocator* const bitrate_allocator_; + BitrateAllocatorInterface* const bitrate_allocator_; // TODO(brandtr): Move ownership to PayloadRouter. std::unique_ptr<FlexfecSender> flexfec_sender_; @@ -172,7 +172,7 @@ class VideoSendStreamImpl : public webrtc::BitrateAllocatorObserver, double encoder_bitrate_priority_; bool has_packet_feedback_; - VideoStreamEncoder* const video_stream_encoder_; + VideoStreamEncoderInterface* const video_stream_encoder_; EncoderRtcpFeedback encoder_feedback_; RtcpBandwidthObserver* const bandwidth_observer_; diff --git a/video/video_send_stream_impl_unittest.cc b/video/video_send_stream_impl_unittest.cc new file mode 100644 index 0000000000..b8f6d958b1 --- /dev/null +++ b/video/video_send_stream_impl_unittest.cc @@ -0,0 +1,183 @@ +/* + * Copyright 2018 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 <string> + +#include "call/test/mock_bitrate_allocator.h" +#include "call/test/mock_rtp_transport_controller_send.h" +#include "logging/rtc_event_log/rtc_event_log.h" +#include "modules/video_coding/fec_controller_default.h" +#include "rtc_base/experiments/alr_experiment.h" +#include "rtc_base/task_queue_for_test.h" +#include "test/field_trial.h" +#include "test/gmock.h" +#include "test/gtest.h" +#include "test/mock_transport.h" +#include "video/test/mock_video_stream_encoder.h" +#include "video/video_send_stream_impl.h" + +namespace webrtc { +namespace internal { +namespace { +using testing::NiceMock; +using testing::StrictMock; +using testing::ReturnRef; +using testing::Return; +using testing::Invoke; +using testing::_; + +constexpr int64_t kDefaultInitialBitrateBps = 333000; +const double kDefaultBitratePriority = 0.5; + +const float kAlrProbingExperimentPaceMultiplier = 1.0f; +std::string GetAlrProbingExperimentString() { + return std::string( + AlrExperimentSettings::kScreenshareProbingBweExperimentName) + + "/1.0,2875,80,40,-60,3/"; +} + +} // namespace + +class VideoSendStreamImplTest : public ::testing::Test { + protected: + VideoSendStreamImplTest() + : clock_(1000 * 1000 * 1000), + config_(&transport_), + send_delay_stats_(&clock_), + retransmission_limiter_(&clock_, 1000), + test_queue_("test_queue"), + process_thread_(ProcessThread::Create("test_thread")), + call_stats_(&clock_, process_thread_.get()), + stats_proxy_(&clock_, + config_, + VideoEncoderConfig::ContentType::kRealtimeVideo) { + config_.rtp.ssrcs.push_back(8080); + config_.rtp.payload_type = 1; + + EXPECT_CALL(transport_controller_, keepalive_config()) + .WillRepeatedly(ReturnRef(keepalive_config_)); + EXPECT_CALL(transport_controller_, packet_router()) + .WillRepeatedly(Return(&packet_router_)); + } + ~VideoSendStreamImplTest() {} + + std::unique_ptr<VideoSendStreamImpl> CreateVideoSendStreamImpl( + int initial_encoder_max_bitrate, + double initial_encoder_bitrate_priority, + VideoEncoderConfig::ContentType content_type) { + EXPECT_CALL(bitrate_allocator_, GetStartBitrate(_)) + .WillOnce(Return(123000)); + std::map<uint32_t, RtpState> suspended_ssrcs; + std::map<uint32_t, RtpPayloadState> suspended_payload_states; + return rtc::MakeUnique<VideoSendStreamImpl>( + &stats_proxy_, &test_queue_, &call_stats_, &transport_controller_, + &bitrate_allocator_, &send_delay_stats_, &video_stream_encoder_, + &event_log_, &config_, initial_encoder_max_bitrate, + initial_encoder_bitrate_priority, suspended_ssrcs, + suspended_payload_states, content_type, + rtc::MakeUnique<FecControllerDefault>(&clock_), + &retransmission_limiter_); + } + + protected: + NiceMock<MockTransport> transport_; + NiceMock<MockRtpTransportControllerSend> transport_controller_; + NiceMock<MockBitrateAllocator> bitrate_allocator_; + NiceMock<MockVideoStreamEncoder> video_stream_encoder_; + + SimulatedClock clock_; + RtcEventLogNullImpl event_log_; + VideoSendStream::Config config_; + SendDelayStats send_delay_stats_; + RateLimiter retransmission_limiter_; + rtc::test::TaskQueueForTest test_queue_; + std::unique_ptr<ProcessThread> process_thread_; + CallStats call_stats_; + SendStatisticsProxy stats_proxy_; + PacketRouter packet_router_; + RtpKeepAliveConfig keepalive_config_; +}; + +TEST_F(VideoSendStreamImplTest, RegistersAsBitrateObserverOnStart) { + test_queue_.SendTask([this] { + config_.track_id = "test"; + const bool kSuspend = false; + config_.suspend_below_min_bitrate = kSuspend; + auto vss_impl = CreateVideoSendStreamImpl( + kDefaultInitialBitrateBps, kDefaultBitratePriority, + VideoEncoderConfig::ContentType::kRealtimeVideo); + EXPECT_CALL(bitrate_allocator_, AddObserver(vss_impl.get(), _)) + .WillOnce(Invoke( + [&](BitrateAllocatorObserver*, MediaStreamAllocationConfig config) { + EXPECT_EQ(config.min_bitrate_bps, 0u); + EXPECT_EQ(config.max_bitrate_bps, kDefaultInitialBitrateBps); + EXPECT_EQ(config.pad_up_bitrate_bps, 0u); + EXPECT_EQ(config.enforce_min_bitrate, !kSuspend); + EXPECT_EQ(config.track_id, "test"); + EXPECT_EQ(config.bitrate_priority, kDefaultBitratePriority); + EXPECT_EQ(config.has_packet_feedback, false); + })); + vss_impl->Start(); + EXPECT_CALL(bitrate_allocator_, RemoveObserver(vss_impl.get())).Times(1); + vss_impl->Stop(); + }); +} + +TEST_F(VideoSendStreamImplTest, ReportFeedbackAvailability) { + test_queue_.SendTask([this] { + config_.rtp.extensions.emplace_back( + RtpExtension::kTransportSequenceNumberUri, + RtpExtension::kTransportSequenceNumberDefaultId); + + auto vss_impl = CreateVideoSendStreamImpl( + kDefaultInitialBitrateBps, kDefaultBitratePriority, + VideoEncoderConfig::ContentType::kRealtimeVideo); + EXPECT_CALL(bitrate_allocator_, AddObserver(vss_impl.get(), _)) + .WillOnce(Invoke( + [&](BitrateAllocatorObserver*, MediaStreamAllocationConfig config) { + EXPECT_EQ(config.has_packet_feedback, true); + })); + vss_impl->Start(); + EXPECT_CALL(bitrate_allocator_, RemoveObserver(vss_impl.get())).Times(1); + vss_impl->Stop(); + }); +} + +TEST_F(VideoSendStreamImplTest, SetsScreensharePacingFactorWithFeedback) { + test::ScopedFieldTrials alr_experiment(GetAlrProbingExperimentString()); + + test_queue_.SendTask([this] { + config_.rtp.extensions.emplace_back( + RtpExtension::kTransportSequenceNumberUri, + RtpExtension::kTransportSequenceNumberDefaultId); + EXPECT_CALL(transport_controller_, + SetPacingFactor(kAlrProbingExperimentPaceMultiplier)) + .Times(1); + auto vss_impl = CreateVideoSendStreamImpl( + kDefaultInitialBitrateBps, kDefaultBitratePriority, + VideoEncoderConfig::ContentType::kScreen); + vss_impl->Start(); + vss_impl->Stop(); + }); +} + +TEST_F(VideoSendStreamImplTest, DoesNotSetPacingFactorWithoutFeedback) { + test::ScopedFieldTrials alr_experiment(GetAlrProbingExperimentString()); + test_queue_.SendTask([this] { + EXPECT_CALL(transport_controller_, SetPacingFactor(_)).Times(0); + auto vss_impl = CreateVideoSendStreamImpl( + kDefaultInitialBitrateBps, kDefaultBitratePriority, + VideoEncoderConfig::ContentType::kScreen); + vss_impl->Start(); + vss_impl->Stop(); + }); +} +} // namespace internal +} // namespace webrtc diff --git a/video/video_stream_encoder.h b/video/video_stream_encoder.h index ac4f2549ff..59974dc4de 100644 --- a/video/video_stream_encoder.h +++ b/video/video_stream_encoder.h @@ -39,6 +39,37 @@ namespace webrtc { class SendStatisticsProxy; class VideoBitrateAllocationObserver; +class VideoStreamEncoderInterface : public rtc::VideoSinkInterface<VideoFrame> { + public: + // Interface for receiving encoded video frames and notifications about + // configuration changes. + class EncoderSink : public EncodedImageCallback { + public: + virtual void OnEncoderConfigurationChanged( + std::vector<VideoStream> streams, + int min_transmit_bitrate_bps) = 0; + }; + virtual void SetSource( + rtc::VideoSourceInterface<VideoFrame>* source, + const VideoSendStream::DegradationPreference& degradation_preference) = 0; + virtual void SetSink(EncoderSink* sink, bool rotation_applied) = 0; + + virtual void SetStartBitrate(int start_bitrate_bps) = 0; + virtual void SendKeyFrame() = 0; + virtual void OnBitrateUpdated(uint32_t bitrate_bps, + uint8_t fraction_lost, + int64_t round_trip_time_ms) = 0; + + virtual void SetBitrateObserver( + VideoBitrateAllocationObserver* bitrate_observer) = 0; + virtual void ConfigureEncoder(VideoEncoderConfig config, + size_t max_data_payload_length, + bool nack_enabled) = 0; + virtual void Stop() = 0; + + protected: + ~VideoStreamEncoderInterface() = default; +}; // VideoStreamEncoder represent a video encoder that accepts raw video frames as // input and produces an encoded bit stream. // Usage: @@ -47,20 +78,11 @@ class VideoBitrateAllocationObserver; // Call SetSource. // Call ConfigureEncoder with the codec settings. // Call Stop() when done. -class VideoStreamEncoder : public rtc::VideoSinkInterface<VideoFrame>, +class VideoStreamEncoder : public VideoStreamEncoderInterface, private EncodedImageCallback, // Protected only to provide access to tests. protected AdaptationObserverInterface { public: - // Interface for receiving encoded video frames and notifications about - // configuration changes. - class EncoderSink : public EncodedImageCallback { - public: - virtual void OnEncoderConfigurationChanged( - std::vector<VideoStream> streams, - int min_transmit_bitrate_bps) = 0; - }; - // Number of resolution and framerate reductions (-1: disabled). struct AdaptCounts { int resolution = 0; @@ -77,34 +99,34 @@ class VideoStreamEncoder : public rtc::VideoSinkInterface<VideoFrame>, // Sets the source that will provide I420 video frames. // |degradation_preference| control whether or not resolution or frame rate // may be reduced. - void SetSource( - rtc::VideoSourceInterface<VideoFrame>* source, - const VideoSendStream::DegradationPreference& degradation_preference); + void SetSource(rtc::VideoSourceInterface<VideoFrame>* source, + const VideoSendStream::DegradationPreference& + degradation_preference) override; // Sets the |sink| that gets the encoded frames. |rotation_applied| means // that the source must support rotation. Only set |rotation_applied| if the // remote side does not support the rotation extension. - void SetSink(EncoderSink* sink, bool rotation_applied); + void SetSink(EncoderSink* sink, bool rotation_applied) override; // TODO(perkj): Can we remove VideoCodec.startBitrate ? - void SetStartBitrate(int start_bitrate_bps); + void SetStartBitrate(int start_bitrate_bps) override; - void SetBitrateObserver(VideoBitrateAllocationObserver* bitrate_observer); + void SetBitrateObserver( + VideoBitrateAllocationObserver* bitrate_observer) override; void ConfigureEncoder(VideoEncoderConfig config, size_t max_data_payload_length, - bool nack_enabled); + bool nack_enabled) override; // Permanently stop encoding. After this method has returned, it is // guaranteed that no encoded frames will be delivered to the sink. - void Stop(); + void Stop() override; - // virtual to test EncoderRtcpFeedback with mocks. - virtual void SendKeyFrame(); + void SendKeyFrame() override; void OnBitrateUpdated(uint32_t bitrate_bps, uint8_t fraction_lost, - int64_t round_trip_time_ms); + int64_t round_trip_time_ms) override; protected: // Used for testing. For example the |ScalingObserverInterface| methods must |