1 // Copyright 2020 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "media/remoting/stream_provider.h"
7 #include "base/memory/raw_ptr.h"
8 #include "base/task/single_thread_task_runner.h"
9 #include "base/test/task_environment.h"
10 #include "media/base/audio_decoder_config.h"
11 #include "media/base/demuxer_stream.h"
12 #include "media/base/media_util.h"
13 #include "media/base/test_helpers.h"
14 #include "media/base/video_decoder_config.h"
15 #include "media/cast/openscreen/remoting_proto_enum_utils.h"
16 #include "media/cast/openscreen/remoting_proto_utils.h"
17 #include "media/remoting/mock_receiver_controller.h"
18 #include "testing/gmock/include/gmock/gmock.h"
19 #include "testing/gtest/include/gtest/gtest.h"
21 using openscreen::cast::RpcMessenger;
22 using testing::NiceMock;
25 constexpr int kBufferSize = 10;
31 class StreamProviderTest : public testing::Test {
34 : audio_config_(TestAudioConfig::Normal()),
35 video_config_(TestVideoConfig::Normal()),
36 audio_buffer_(new DecoderBuffer(kBufferSize)),
37 video_buffer_(DecoderBuffer::CreateEOSBuffer()) {}
39 void SetUp() override {
40 mock_controller_ = MockReceiverController::GetInstance();
41 mock_controller_->Initialize(
42 mock_controller_->mock_remotee()->BindNewPipeAndPassRemote());
43 mock_remotee_ = mock_controller_->mock_remotee();
44 stream_provider_ = std::make_unique<StreamProvider>(
45 mock_controller_, base::SingleThreadTaskRunner::GetCurrentDefault());
47 rpc_messenger_ = mock_controller_->rpc_messenger();
48 sender_audio_demuxer_stream_handle_ = rpc_messenger_->GetUniqueHandle();
49 sender_video_demuxer_stream_handle_ = rpc_messenger_->GetUniqueHandle();
50 rpc_messenger_->RegisterMessageReceiverCallback(
51 sender_audio_demuxer_stream_handle_,
52 [this](std::unique_ptr<openscreen::cast::RpcMessage> message) {
53 OnDemuxerStreamReceivedRpc(DemuxerStream::Type::AUDIO,
56 rpc_messenger_->RegisterMessageReceiverCallback(
57 sender_video_demuxer_stream_handle_,
58 [this](std::unique_ptr<openscreen::cast::RpcMessage> message) {
59 OnDemuxerStreamReceivedRpc(DemuxerStream::Type::VIDEO,
64 void TearDown() override {
65 // Drop unowned references before `stream_provider_` destroys them.
66 audio_stream_ = nullptr;
67 video_stream_ = nullptr;
69 stream_provider_.reset();
70 task_environment_.RunUntilIdle();
73 void OnDemuxerStreamReceivedRpc(
74 DemuxerStream::Type type,
75 std::unique_ptr<openscreen::cast::RpcMessage> message) {
77 switch (message->proc()) {
78 case openscreen::cast::RpcMessage::RPC_DS_INITIALIZE:
79 if (type == DemuxerStream::Type::AUDIO) {
80 receiver_audio_demuxer_stream_handle_ = message->integer_value();
81 } else if (type == DemuxerStream::Type::VIDEO) {
82 receiver_video_demuxer_stream_handle_ = message->integer_value();
87 RpcInitializeCallback(type);
90 case openscreen::cast::RpcMessage::RPC_DS_READUNTIL:
95 DVLOG(1) << __func__ << "Unknown supported message.";
99 void RpcInitializeCallback(DemuxerStream::Type type) {
100 // Issues RPC_DS_INITIALIZE_CALLBACK RPC message.
101 auto rpc = std::make_unique<openscreen::cast::RpcMessage>();
102 rpc->set_handle(type == DemuxerStream::Type::AUDIO
103 ? receiver_audio_demuxer_stream_handle_
104 : receiver_video_demuxer_stream_handle_);
105 rpc->set_proc(openscreen::cast::RpcMessage::RPC_DS_INITIALIZE_CALLBACK);
106 auto* init_cb_message = rpc->mutable_demuxerstream_initializecb_rpc();
107 init_cb_message->set_type(type);
110 case DemuxerStream::Type::AUDIO: {
111 openscreen::cast::AudioDecoderConfig* audio_message =
112 init_cb_message->mutable_audio_decoder_config();
113 media::cast::ConvertAudioDecoderConfigToProto(audio_config_,
118 case DemuxerStream::Type::VIDEO: {
119 openscreen::cast::VideoDecoderConfig* video_message =
120 init_cb_message->mutable_video_decoder_config();
121 media::cast::ConvertVideoDecoderConfigToProto(video_config_,
130 rpc_messenger_->SendMessageToRemote(*rpc);
133 void ReadUntil(DemuxerStream::Type type) {
135 case DemuxerStream::Type::AUDIO:
138 case DemuxerStream::Type::VIDEO:
146 void SendRpcAcquireDemuxer() {
147 auto rpc = std::make_unique<openscreen::cast::RpcMessage>();
148 rpc->set_handle(RpcMessenger::kAcquireDemuxerHandle);
149 rpc->set_proc(openscreen::cast::RpcMessage::RPC_ACQUIRE_DEMUXER);
150 openscreen::cast::AcquireDemuxer* message =
151 rpc->mutable_acquire_demuxer_rpc();
152 message->set_audio_demuxer_handle(sender_audio_demuxer_stream_handle_);
153 message->set_video_demuxer_handle(sender_video_demuxer_stream_handle_);
154 rpc_messenger_->SendMessageToRemote(*rpc);
157 void OnStreamProviderInitialized(PipelineStatus status) {
158 EXPECT_EQ(PIPELINE_OK, status);
159 stream_provider_initialized_ = true;
161 stream_provider_->GetFirstStream(DemuxerStream::Type::AUDIO);
163 stream_provider_->GetFirstStream(DemuxerStream::Type::VIDEO);
165 EXPECT_TRUE(audio_stream_);
166 EXPECT_TRUE(video_stream_);
169 void InitializeDemuxer() {
170 DCHECK(stream_provider_);
171 stream_provider_->Initialize(
173 base::BindOnce(&StreamProviderTest::OnStreamProviderInitialized,
174 base::Unretained(this)));
177 void SendAudioFrame() {
178 mock_remotee_->SendAudioFrame(0, audio_buffer_);
179 SendRpcReadUntilCallback(DemuxerStream::Type::AUDIO);
182 void SendVideoFrame() {
183 mock_remotee_->SendVideoFrame(0, video_buffer_);
184 SendRpcReadUntilCallback(DemuxerStream::Type::VIDEO);
187 void SendRpcReadUntilCallback(DemuxerStream::Type type) {
188 // Issues RPC_DS_READUNTIL_CALLBACK RPC message.
189 openscreen::cast::RpcMessage rpc;
190 rpc.set_handle(type == DemuxerStream::Type::AUDIO
191 ? receiver_audio_demuxer_stream_handle_
192 : receiver_video_demuxer_stream_handle_);
193 rpc.set_proc(openscreen::cast::RpcMessage::RPC_DS_READUNTIL_CALLBACK);
194 auto* message = rpc.mutable_demuxerstream_readuntilcb_rpc();
195 message->set_count(0);
197 media::cast::ToProtoDemuxerStreamStatus(DemuxerStream::Status::kOk)
199 rpc_messenger_->SendMessageToRemote(rpc);
202 void FlushUntil(uint32_t flush_audio_count, uint32_t flush_video_count) {
203 mock_remotee_->OnFlushUntil(flush_audio_count, flush_video_count);
206 uint32_t GetAudioCurrentFrameCount() {
207 return stream_provider_->audio_stream_->current_frame_count_;
210 uint32_t GetVideoCurrentFrameCount() {
211 return stream_provider_->video_stream_->current_frame_count_;
214 void OnBufferReadFromDemuxerStream(
215 DemuxerStream::Type type,
216 DemuxerStream::Status status,
217 DemuxerStream::DecoderBufferVector buffers) {
218 EXPECT_EQ(status, DemuxerStream::Status::kOk);
219 EXPECT_EQ(buffers.size(), 1u)
220 << "StreamProviderTest only reads a single-buffer.";
221 scoped_refptr<DecoderBuffer> buffer = std::move(buffers[0]);
223 case DemuxerStream::Type::AUDIO:
224 received_audio_buffer_ = buffer;
226 case DemuxerStream::Type::VIDEO:
227 received_video_buffer_ = buffer;
234 base::test::TaskEnvironment task_environment_;
236 AudioDecoderConfig audio_config_;
237 VideoDecoderConfig video_config_;
239 raw_ptr<DemuxerStream> audio_stream_;
240 raw_ptr<DemuxerStream> video_stream_;
242 scoped_refptr<DecoderBuffer> audio_buffer_;
243 scoped_refptr<DecoderBuffer> video_buffer_;
245 bool stream_provider_initialized_{false};
246 scoped_refptr<DecoderBuffer> received_audio_buffer_;
247 scoped_refptr<DecoderBuffer> received_video_buffer_;
249 int sender_audio_demuxer_stream_handle_ = RpcMessenger::kInvalidHandle;
250 int sender_video_demuxer_stream_handle_ = RpcMessenger::kInvalidHandle;
251 int receiver_audio_demuxer_stream_handle_ = RpcMessenger::kInvalidHandle;
252 int receiver_video_demuxer_stream_handle_ = RpcMessenger::kInvalidHandle;
254 raw_ptr<RpcMessenger> rpc_messenger_;
255 raw_ptr<MockReceiverController> mock_controller_;
256 raw_ptr<MockRemotee> mock_remotee_;
257 std::unique_ptr<StreamProvider> stream_provider_;
260 TEST_F(StreamProviderTest, InitializeBeforeRpcAcquireDemuxer) {
262 EXPECT_FALSE(stream_provider_initialized_);
264 SendRpcAcquireDemuxer();
265 task_environment_.RunUntilIdle();
267 EXPECT_TRUE(mock_remotee_->audio_stream_.is_bound());
268 EXPECT_TRUE(mock_remotee_->video_stream_.is_bound());
269 EXPECT_TRUE(stream_provider_initialized_);
271 // 1 audio stream and 1 video stream
272 EXPECT_EQ(size_t(2), stream_provider_->GetAllStreams().size());
275 TEST_F(StreamProviderTest, InitializeAfterRpcAcquireDemuxer) {
276 SendRpcAcquireDemuxer();
277 EXPECT_FALSE(stream_provider_initialized_);
280 task_environment_.RunUntilIdle();
282 EXPECT_TRUE(mock_remotee_->audio_stream_.is_bound());
283 EXPECT_TRUE(mock_remotee_->video_stream_.is_bound());
284 EXPECT_TRUE(stream_provider_initialized_);
286 // 1 audio stream and 1 video stream
287 EXPECT_EQ(size_t(2), stream_provider_->GetAllStreams().size());
290 TEST_F(StreamProviderTest, ReadBuffer) {
292 SendRpcAcquireDemuxer();
293 task_environment_.RunUntilIdle();
294 EXPECT_TRUE(mock_remotee_->audio_stream_.is_bound());
295 EXPECT_TRUE(mock_remotee_->video_stream_.is_bound());
296 EXPECT_TRUE(stream_provider_initialized_);
299 1, base::BindOnce(&StreamProviderTest::OnBufferReadFromDemuxerStream,
300 base::Unretained(this), DemuxerStream::Type::AUDIO));
301 task_environment_.RunUntilIdle();
302 EXPECT_EQ(audio_buffer_->data_size(), received_audio_buffer_->data_size());
303 EXPECT_EQ(audio_buffer_->end_of_stream(),
304 received_audio_buffer_->end_of_stream());
305 EXPECT_EQ(audio_buffer_->is_key_frame(),
306 received_audio_buffer_->is_key_frame());
309 1, base::BindOnce(&StreamProviderTest::OnBufferReadFromDemuxerStream,
310 base::Unretained(this), DemuxerStream::Type::VIDEO));
311 task_environment_.RunUntilIdle();
312 EXPECT_EQ(video_buffer_->end_of_stream(),
313 received_video_buffer_->end_of_stream());
316 TEST_F(StreamProviderTest, FlushUntil) {
318 SendRpcAcquireDemuxer();
319 task_environment_.RunUntilIdle();
320 EXPECT_TRUE(mock_remotee_->audio_stream_.is_bound());
321 EXPECT_TRUE(mock_remotee_->video_stream_.is_bound());
322 EXPECT_TRUE(stream_provider_initialized_);
324 uint32_t flush_audio_count = 10;
325 uint32_t flush_video_count = 20;
326 FlushUntil(flush_audio_count, flush_video_count);
327 task_environment_.RunUntilIdle();
329 EXPECT_EQ(GetAudioCurrentFrameCount(), flush_audio_count);
330 EXPECT_EQ(GetVideoCurrentFrameCount(), flush_video_count);
333 } // namespace remoting