OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "media/remoting/end2end_test_renderer.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/bind_helpers.h" | |
9 #include "base/callback.h" | |
10 #include "base/threading/thread_task_runner_handle.h" | |
11 #include "media/mojo/interfaces/remoting.mojom.h" | |
12 #include "media/remoting/courier_renderer.h" | |
13 #include "media/remoting/proto_utils.h" | |
14 #include "media/remoting/remote_receiver.h" | |
15 #include "media/remoting/renderer_controller.h" | |
16 #include "mojo/public/cpp/bindings/strong_binding.h" | |
17 | |
18 namespace media { | |
19 namespace remoting { | |
20 | |
21 namespace { | |
22 | |
23 class TestStreamSender final : public mojom::RemotingDataStreamSender { | |
24 public: | |
25 using SendFrameToSinkCallback = | |
26 base::Callback<void(const std::vector<uint8_t>& data, | |
27 DemuxerStream::Type type)>; | |
28 TestStreamSender(mojom::RemotingDataStreamSenderRequest request, | |
29 mojo::ScopedDataPipeConsumerHandle handle, | |
30 DemuxerStream::Type type, | |
31 const SendFrameToSinkCallback& callback) | |
32 : binding_(this, std::move(request)), | |
33 consumer_handle_(std::move(handle)), | |
34 type_(type), | |
35 send_frame_to_sink_cb_(callback) {} | |
36 | |
37 ~TestStreamSender() override {} | |
38 | |
39 // mojom::RemotingDataStreamSender implementation. | |
40 | |
41 void ConsumeDataChunk(uint32_t offset, | |
42 uint32_t size, | |
43 uint32_t total_payload_size) override { | |
44 next_frame_data_.resize(total_payload_size); | |
45 MojoResult result = mojo::ReadDataRaw( | |
46 consumer_handle_.get(), next_frame_data_.data() + offset, &size, | |
47 MOJO_READ_DATA_FLAG_ALL_OR_NONE); | |
48 CHECK(result == MOJO_RESULT_OK); | |
49 } | |
50 | |
51 void SendFrame() override { | |
52 if (!send_frame_to_sink_cb_.is_null()) | |
53 send_frame_to_sink_cb_.Run(next_frame_data_, type_); | |
54 next_frame_data_.resize(0); | |
55 } | |
56 | |
57 void CancelInFlightData() override { next_frame_data_.resize(0); } | |
58 | |
59 private: | |
60 mojo::Binding<RemotingDataStreamSender> binding_; | |
61 mojo::ScopedDataPipeConsumerHandle consumer_handle_; | |
62 const DemuxerStream::Type type_; | |
63 const SendFrameToSinkCallback& send_frame_to_sink_cb_; | |
miu
2017/03/29 01:39:13
typo: Need to remove ampersand here.
xjz
2017/03/30 23:21:30
Done.
| |
64 std::vector<uint8_t> next_frame_data_; | |
65 | |
66 DISALLOW_COPY_AND_ASSIGN(TestStreamSender); | |
67 }; | |
68 | |
69 class TestRemoter final : public mojom::Remoter { | |
70 public: | |
71 using SendMessageToSinkCallback = | |
72 base::Callback<void(const std::vector<uint8_t>& message)>; | |
73 TestRemoter( | |
74 mojom::RemotingSourcePtr source, | |
75 const SendMessageToSinkCallback& send_message_to_sink_cb, | |
76 const TestStreamSender::SendFrameToSinkCallback& send_frame_to_sink_cb) | |
77 : source_(std::move(source)), | |
78 send_message_to_sink_cb_(send_message_to_sink_cb), | |
79 send_frame_to_sink_cb_(send_frame_to_sink_cb) {} | |
80 | |
81 ~TestRemoter() override {} | |
82 | |
83 // mojom::Remoter implementation. | |
84 | |
85 void Start() override { source_->OnStarted(); } | |
86 | |
87 void StartDataStreams( | |
88 mojo::ScopedDataPipeConsumerHandle audio_pipe, | |
89 mojo::ScopedDataPipeConsumerHandle video_pipe, | |
90 mojom::RemotingDataStreamSenderRequest audio_sender_request, | |
91 mojom::RemotingDataStreamSenderRequest video_sender_request) override { | |
92 if (audio_pipe.is_valid()) { | |
93 audio_stream_sender_.reset(new TestStreamSender( | |
94 std::move(audio_sender_request), std::move(audio_pipe), | |
95 DemuxerStream::AUDIO, send_frame_to_sink_cb_)); | |
96 } | |
97 if (video_pipe.is_valid()) { | |
98 video_stream_sender_.reset(new TestStreamSender( | |
99 std::move(video_sender_request), std::move(video_pipe), | |
100 DemuxerStream::VIDEO, send_frame_to_sink_cb_)); | |
101 } | |
102 } | |
103 | |
104 void Stop(mojom::RemotingStopReason reason) override { | |
105 source_->OnStopped(reason); | |
106 } | |
107 | |
108 void SendMessageToSink(const std::vector<uint8_t>& message) override { | |
109 if (!send_message_to_sink_cb_.is_null()) | |
110 send_message_to_sink_cb_.Run(message); | |
111 } | |
112 | |
113 // Called when receives RPC messages from receiver. | |
114 void OnMessageFromSink(const std::vector<uint8_t>& message) { | |
115 source_->OnMessageFromSink(message); | |
116 } | |
117 | |
118 private: | |
119 mojom::RemotingSourcePtr source_; | |
120 const SendMessageToSinkCallback send_message_to_sink_cb_; | |
121 const TestStreamSender::SendFrameToSinkCallback send_frame_to_sink_cb_; | |
122 std::unique_ptr<TestStreamSender> audio_stream_sender_; | |
123 std::unique_ptr<TestStreamSender> video_stream_sender_; | |
124 | |
125 DISALLOW_COPY_AND_ASSIGN(TestRemoter); | |
126 }; | |
127 | |
128 scoped_refptr<SharedSession> CreateSharedSession( | |
129 const TestRemoter::SendMessageToSinkCallback& send_message_to_sink_cb, | |
130 const TestStreamSender::SendFrameToSinkCallback& send_frame_to_sink_cb) { | |
131 mojom::RemotingSourcePtr remoting_source; | |
132 mojom::RemotingSourceRequest remoting_source_request(&remoting_source); | |
133 mojom::RemoterPtr remoter; | |
134 std::unique_ptr<TestRemoter> test_remoter = base::MakeUnique<TestRemoter>( | |
135 std::move(remoting_source), send_message_to_sink_cb, | |
136 send_frame_to_sink_cb); | |
137 mojo::MakeStrongBinding(std::move(test_remoter), mojo::MakeRequest(&remoter)); | |
138 return new SharedSession(std::move(remoting_source_request), | |
139 std::move(remoter)); | |
140 } | |
141 | |
142 } // namespace | |
143 | |
144 End2EndTestRenderer::End2EndTestRenderer(std::unique_ptr<Renderer> renderer) | |
145 : receiver_rpc_broker_(base::Bind(&End2EndTestRenderer::OnMessageFromSink, | |
146 base::Unretained(this))), | |
147 receiver_(new RemoteReceiver(std::move(renderer), &receiver_rpc_broker_)), | |
148 weak_factory_(this) { | |
149 shared_session_ = | |
150 CreateSharedSession(base::Bind(&End2EndTestRenderer::SendMessageToSink, | |
151 weak_factory_.GetWeakPtr()), | |
152 base::Bind(&End2EndTestRenderer::SendFrameToSink, | |
153 weak_factory_.GetWeakPtr())); | |
154 controller_.reset(new RendererController(shared_session_)); | |
155 courier_renderer_.reset(new CourierRenderer( | |
156 base::ThreadTaskRunnerHandle::Get(), controller_->GetWeakPtr(), nullptr)); | |
157 } | |
158 | |
159 End2EndTestRenderer::~End2EndTestRenderer() {} | |
160 | |
161 void End2EndTestRenderer::Initialize(MediaResource* media_resource, | |
162 RendererClient* client, | |
163 const PipelineStatusCB& init_cb) { | |
164 courier_renderer_->Initialize(media_resource, client, init_cb); | |
165 } | |
166 | |
167 void End2EndTestRenderer::SetCdm(CdmContext* cdm_context, | |
168 const CdmAttachedCB& cdc_attached_cb) { | |
169 // TODO(xjz): Add the implementation when media remoting starts supporting | |
170 // encrypted contents. | |
171 LOG(ERROR) << __func__ << ": Media Remoting doesn't support EME for now."; | |
miu
2017/03/29 01:39:13
Instead:
NOTIMPLEMENTED();
xjz
2017/03/30 23:21:30
Done.
| |
172 } | |
173 | |
174 void End2EndTestRenderer::Flush(const base::Closure& flush_cb) { | |
175 courier_renderer_->Flush(flush_cb); | |
176 } | |
177 | |
178 void End2EndTestRenderer::StartPlayingFrom(base::TimeDelta time) { | |
179 courier_renderer_->StartPlayingFrom(time); | |
180 } | |
181 | |
182 void End2EndTestRenderer::SetPlaybackRate(double playback_rate) { | |
183 courier_renderer_->SetPlaybackRate(playback_rate); | |
184 } | |
185 | |
186 void End2EndTestRenderer::SetVolume(float volume) { | |
187 courier_renderer_->SetVolume(volume); | |
188 } | |
189 | |
190 base::TimeDelta End2EndTestRenderer::GetMediaTime() { | |
191 return courier_renderer_->GetMediaTime(); | |
192 } | |
193 | |
194 void End2EndTestRenderer::SendMessageToSink( | |
195 const std::vector<uint8_t>& message) { | |
196 std::unique_ptr<pb::RpcMessage> rpc(new pb::RpcMessage()); | |
197 if (!rpc->ParseFromArray(message.data(), message.size())) { | |
198 VLOG(1) << __func__ << ": Received corrupted Rpc message."; | |
199 return; | |
200 } | |
201 receiver_rpc_broker_.ProcessMessageFromRemote(std::move(rpc)); | |
202 } | |
203 | |
204 void End2EndTestRenderer::SendFrameToSink(const std::vector<uint8_t>& frame, | |
205 DemuxerStream::Type type) { | |
206 if (frame.empty()) | |
miu
2017/03/29 01:39:13
Why do we check if the frame is empty? Feels like
xjz
2017/03/30 23:21:30
Done. Removed the check.
| |
207 return; | |
208 scoped_refptr<DecoderBuffer> decoder_buffer = | |
209 ByteArrayToDecoderBuffer(frame.data(), frame.size()); | |
210 receiver_->OnReceivedBuffer(type, decoder_buffer); | |
211 } | |
212 | |
213 void End2EndTestRenderer::OnMessageFromSink( | |
214 std::unique_ptr<std::vector<uint8_t>> message) { | |
215 shared_session_->OnMessageFromSink(*message); | |
216 } | |
217 | |
218 } // namespace remoting | |
219 } // namespace media | |
OLD | NEW |