123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188 |
- // Copyright 2018 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "components/mirroring/service/rtp_stream.h"
- #include "base/callback_helpers.h"
- #include "base/memory/raw_ptr.h"
- #include "base/run_loop.h"
- #include "base/test/mock_callback.h"
- #include "base/test/simple_test_tick_clock.h"
- #include "base/test/task_environment.h"
- #include "base/time/time.h"
- #include "media/base/video_frame.h"
- #include "media/cast/cast_config.h"
- #include "media/cast/cast_environment.h"
- #include "media/cast/sender/audio_sender.h"
- #include "media/cast/sender/video_sender.h"
- #include "media/cast/test/mock_cast_transport.h"
- #include "media/cast/test/utility/audio_utility.h"
- #include "media/cast/test/utility/default_config.h"
- #include "media/cast/test/utility/video_utility.h"
- #include "testing/gmock/include/gmock/gmock.h"
- #include "testing/gtest/include/gtest/gtest.h"
- using ::testing::InvokeWithoutArgs;
- using ::testing::_;
- using media::cast::TestAudioBusFactory;
- namespace mirroring {
- namespace {
- class StreamClient final : public RtpStreamClient {
- public:
- explicit StreamClient(base::SimpleTestTickClock* clock) : clock_(clock) {}
- StreamClient(const StreamClient&) = delete;
- StreamClient& operator=(const StreamClient&) = delete;
- ~StreamClient() override = default;
- void SetVideoRtpStream(VideoRtpStream* stream) { video_stream_ = stream; }
- // RtpStreamClient implementation.
- void OnError(const std::string& message) override {}
- void RequestRefreshFrame() override {
- if (video_stream_) {
- video_stream_->InsertVideoFrame(CreateVideoFrame());
- }
- }
- void CreateVideoEncodeAccelerator(
- media::cast::ReceiveVideoEncodeAcceleratorCallback callback) override {}
- scoped_refptr<media::VideoFrame> CreateVideoFrame() {
- constexpr gfx::Size kFrameSize(640, 480);
- base::TimeDelta frame_timestamp;
- if (first_frame_time_.is_null()) {
- first_frame_time_ = clock_->NowTicks();
- frame_timestamp = base::TimeDelta();
- } else {
- clock_->Advance(base::Milliseconds(10));
- frame_timestamp = clock_->NowTicks() - first_frame_time_;
- }
- auto frame = media::VideoFrame::CreateFrame(
- media::PIXEL_FORMAT_I420, kFrameSize, gfx::Rect(kFrameSize), kFrameSize,
- frame_timestamp);
- media::cast::PopulateVideoFrame(frame.get(), 1);
- frame->metadata().reference_time = clock_->NowTicks();
- return frame;
- }
- base::WeakPtr<RtpStreamClient> GetWeakPtr() {
- return weak_factory_.GetWeakPtr();
- }
- private:
- raw_ptr<VideoRtpStream> video_stream_;
- base::TimeTicks first_frame_time_;
- const raw_ptr<base::SimpleTestTickClock> clock_;
- base::WeakPtrFactory<StreamClient> weak_factory_{this};
- };
- } // namespace
- class RtpStreamTest : public ::testing::Test {
- public:
- RtpStreamTest()
- : cast_environment_(new media::cast::CastEnvironment(
- &testing_clock_,
- task_environment_.GetMainThreadTaskRunner(),
- task_environment_.GetMainThreadTaskRunner(),
- task_environment_.GetMainThreadTaskRunner())),
- client_(&testing_clock_) {
- testing_clock_.Advance(base::TimeTicks::Now() - base::TimeTicks());
- }
- RtpStreamTest(const RtpStreamTest&) = delete;
- RtpStreamTest& operator=(const RtpStreamTest&) = delete;
- ~RtpStreamTest() override { task_environment_.RunUntilIdle(); }
- protected:
- base::test::TaskEnvironment task_environment_;
- base::SimpleTestTickClock testing_clock_;
- const scoped_refptr<media::cast::CastEnvironment> cast_environment_;
- StreamClient client_;
- // We currently don't care about sender reports, so we use a nice mock here.
- testing::NiceMock<media::cast::MockCastTransport> transport_;
- };
- // Test the video streaming pipeline.
- TEST_F(RtpStreamTest, VideoStreaming) {
- auto video_sender = std::make_unique<media::cast::VideoSender>(
- cast_environment_, media::cast::GetDefaultVideoSenderConfig(),
- base::DoNothing(), base::DoNothing(), &transport_, base::DoNothing(),
- base::DoNothing());
- VideoRtpStream video_stream(std::move(video_sender), client_.GetWeakPtr());
- {
- base::RunLoop run_loop;
- // Expect the video frame is sent to video sender for encoding, and the
- // encoded frame is sent to the transport.
- EXPECT_CALL(transport_, InsertFrame(_, _))
- .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
- video_stream.InsertVideoFrame(client_.CreateVideoFrame());
- run_loop.Run();
- }
- task_environment_.RunUntilIdle();
- }
- TEST_F(RtpStreamTest, VideoStreamEmitsFramesWhenNoUpdates) {
- auto video_sender = std::make_unique<media::cast::VideoSender>(
- cast_environment_, media::cast::GetDefaultVideoSenderConfig(),
- base::DoNothing(), base::DoNothing(), &transport_, base::DoNothing(),
- base::DoNothing());
- VideoRtpStream video_stream(std::move(video_sender), client_.GetWeakPtr());
- client_.SetVideoRtpStream(&video_stream);
- {
- base::RunLoop run_loop;
- int loop_count = 0;
- // Expect the video frame is sent to video sender for encoding, and the
- // encoded frame is sent to the transport.
- EXPECT_CALL(transport_, InsertFrame(_, _))
- .WillRepeatedly(InvokeWithoutArgs([&run_loop, &loop_count] {
- if (loop_count++ == 5) {
- run_loop.Quit();
- }
- }));
- // We start with one valid frame, then the rest should be update requests.
- video_stream.InsertVideoFrame(client_.CreateVideoFrame());
- run_loop.Run();
- }
- task_environment_.RunUntilIdle();
- }
- // Test the audio streaming pipeline.
- TEST_F(RtpStreamTest, AudioStreaming) {
- // Create audio data.
- const base::TimeDelta kDuration = base::Milliseconds(10);
- media::cast::FrameSenderConfig audio_config =
- media::cast::GetDefaultAudioSenderConfig();
- std::unique_ptr<media::AudioBus> audio_bus =
- TestAudioBusFactory(audio_config.channels, audio_config.rtp_timebase,
- TestAudioBusFactory::kMiddleANoteFreq, 0.5f)
- .NextAudioBus(kDuration);
- auto audio_sender = std::make_unique<media::cast::AudioSender>(
- cast_environment_, audio_config, base::DoNothing(), &transport_);
- AudioRtpStream audio_stream(std::move(audio_sender), client_.GetWeakPtr());
- {
- base::RunLoop run_loop;
- // Expect the audio data is sent to audio sender for encoding, and the
- // encoded frame is sent to the transport.
- EXPECT_CALL(transport_, InsertFrame(_, _))
- .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
- audio_stream.InsertAudio(std::move(audio_bus), testing_clock_.NowTicks());
- run_loop.Run();
- }
- task_environment_.RunUntilIdle();
- }
- } // namespace mirroring
|