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/remote_stream_provider.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/callback.h" | |
9 #include "base/callback_helpers.h" | |
10 #include "media/base/decoder_buffer.h" | |
11 #include "media/base/video_rotation.h" | |
12 #include "media/remoting/proto_enum_utils.h" | |
13 #include "media/remoting/proto_utils.h" | |
14 | |
15 namespace media { | |
16 namespace remoting { | |
17 | |
18 namespace { | |
19 // The number of frames requested in each ReadUntil RPC message. | |
20 constexpr int kNumFramesInEachReadUntil = 10; | |
21 } | |
22 | |
23 RemoteMediaStream::RemoteMediaStream(RpcBroker* rpc_broker, | |
24 Type type, | |
25 int remote_handle) | |
26 : rpc_broker_(rpc_broker), | |
27 type_(type), | |
28 remote_handle_(remote_handle), | |
29 rpc_handle_(rpc_broker_->GetUniqueHandle()), | |
30 weak_factory_(this) { | |
31 DCHECK(remote_handle_ != RpcBroker::kInvalidHandle); | |
32 rpc_broker_->RegisterMessageReceiverCallback( | |
33 rpc_handle_, base::Bind(&RemoteMediaStream::OnReceivedRpc, | |
34 weak_factory_.GetWeakPtr())); | |
35 } | |
36 | |
37 RemoteMediaStream::~RemoteMediaStream() { | |
38 rpc_broker_->UnregisterMessageReceiverCallback(rpc_handle_); | |
39 } | |
40 | |
41 void RemoteMediaStream::Initialize(const base::Closure& init_done_cb) { | |
42 DCHECK(init_done_callback_.is_null()); | |
43 DCHECK(!init_done_cb.is_null()); | |
44 init_done_callback_ = init_done_cb; | |
45 | |
46 DVLOG(3) << __func__ << "Issues RpcMessage::RPC_DS_INITIALIZE with " | |
47 << "remote_handle=" << remote_handle_ | |
48 << " rpc_handle=" << rpc_handle_; | |
49 std::unique_ptr<pb::RpcMessage> rpc(new pb::RpcMessage()); | |
50 rpc->set_handle(remote_handle_); | |
51 rpc->set_proc(pb::RpcMessage::RPC_DS_INITIALIZE); | |
52 rpc->set_integer_value(rpc_handle_); | |
53 rpc_broker_->SendMessageToRemote(std::move(rpc)); | |
54 } | |
55 | |
56 void RemoteMediaStream::OnReceivedRpc(std::unique_ptr<pb::RpcMessage> message) { | |
57 DCHECK(message->handle() == rpc_handle_); | |
58 | |
59 switch (message->proc()) { | |
60 case pb::RpcMessage::RPC_DS_INITIALIZE_CALLBACK: | |
61 OnInitializeCallback(std::move(message)); | |
62 break; | |
63 case pb::RpcMessage::RPC_DS_READUNTIL_CALLBACK: | |
64 OnReadUntilCallback(std::move(message)); | |
65 break; | |
66 default: | |
67 VLOG(3) << __func__ << "Unknow RPC message."; | |
68 } | |
69 } | |
70 | |
71 void RemoteMediaStream::OnInitializeCallback( | |
72 std::unique_ptr<pb::RpcMessage> message) { | |
73 DVLOG(3) << __func__ << "Receives RPC_DS_INITIALIZE_CALLBACK message."; | |
74 const pb::DemuxerStreamInitializeCallback callback_message = | |
75 message->demuxerstream_initializecb_rpc(); | |
76 DCHECK(callback_message.type() == type_); | |
miu
2017/03/29 01:39:14
These four DCHECKs() should be if-statements inste
xjz
2017/03/30 23:21:31
Done.
| |
77 DCHECK(audio_decoder_config_.empty()); | |
78 DCHECK(video_decoder_config_.empty()); | |
79 DCHECK(!init_done_callback_.is_null()); | |
80 | |
81 if (type_ == DemuxerStream::AUDIO && | |
82 callback_message.has_audio_decoder_config()) { | |
83 const pb::AudioDecoderConfig audio_message = | |
84 callback_message.audio_decoder_config(); | |
85 UpdateConfig(&audio_message, nullptr); | |
86 } else if (type_ == DemuxerStream::VIDEO && | |
87 callback_message.has_video_decoder_config()) { | |
88 const pb::VideoDecoderConfig video_message = | |
89 callback_message.video_decoder_config(); | |
90 UpdateConfig(nullptr, &video_message); | |
91 } else { | |
92 NOTREACHED(); | |
miu
2017/03/29 01:39:14
Replace with something like:
SendInitializeRpcF
xjz
2017/03/30 23:21:31
Done.
| |
93 } | |
94 base::ResetAndReturn(&init_done_callback_).Run(); | |
95 } | |
96 | |
97 void RemoteMediaStream::OnReadUntilCallback( | |
98 std::unique_ptr<pb::RpcMessage> message) { | |
99 DVLOG(3) << __func__ << ": Receives RPC_DS_READUNTIL_CALLBACK message."; | |
100 DCHECK(read_until_sent_); | |
miu
2017/03/29 01:39:14
DCHECK() --> if ()
...and rather than me point al
xjz
2017/03/30 23:21:31
Done.
| |
101 read_until_sent_ = false; | |
102 const pb::DemuxerStreamReadUntilCallback callback_message = | |
103 message->demuxerstream_readuntilcb_rpc(); | |
104 last_read_until_count_ = callback_message.count(); | |
105 if (ToDemuxerStreamStatus(callback_message.status()) == kConfigChanged) { | |
106 if (callback_message.has_audio_decoder_config()) { | |
107 const pb::AudioDecoderConfig audio_message = | |
108 callback_message.audio_decoder_config(); | |
109 UpdateConfig(&audio_message, nullptr); | |
110 } | |
111 if (callback_message.has_video_decoder_config()) { | |
112 const pb::VideoDecoderConfig video_message = | |
113 callback_message.video_decoder_config(); | |
114 UpdateConfig(nullptr, &video_message); | |
115 } | |
116 config_changed_ = true; | |
117 if (buffers_.empty() && !read_complete_callback_.is_null()) | |
118 CompleteRead(DemuxerStream::kConfigChanged); | |
119 return; | |
120 } | |
121 if (buffers_.empty() && !read_complete_callback_.is_null()) | |
122 SendReadUntil(); | |
123 } | |
124 | |
125 void RemoteMediaStream::UpdateConfig( | |
126 const pb::AudioDecoderConfig* audio_message, | |
127 const pb::VideoDecoderConfig* video_message) { | |
128 if (type_ == AUDIO) { | |
129 DCHECK(audio_message && !video_message); | |
130 AudioDecoderConfig audio_config; | |
131 ConvertProtoToAudioDecoderConfig(*audio_message, &audio_config); | |
132 DCHECK(audio_config.IsValidConfig()); | |
133 audio_decoder_config_.push_back(audio_config); | |
134 } else if (type_ == VIDEO) { | |
135 DCHECK(video_message && !audio_message); | |
136 VideoDecoderConfig video_config; | |
137 ConvertProtoToVideoDecoderConfig(*video_message, &video_config); | |
138 DCHECK(video_config.IsValidConfig()); | |
139 video_decoder_config_.push_back(video_config); | |
140 } else { | |
141 VLOG(1) << __func__ << ": Only supports video or audio stream."; | |
142 } | |
143 } | |
144 | |
145 void RemoteMediaStream::SendReadUntil() { | |
146 if (read_until_sent_) | |
147 return; | |
148 DVLOG(3) << "Issues RPC_DS_READUNTIL RPC message to remote_handle_=" | |
149 << remote_handle_ << " with callback handle=" << rpc_handle_ | |
150 << " count=" << last_read_until_count_; | |
151 | |
152 std::unique_ptr<pb::RpcMessage> rpc(new pb::RpcMessage()); | |
153 rpc->set_handle(remote_handle_); | |
154 rpc->set_proc(pb::RpcMessage::RPC_DS_READUNTIL); | |
155 auto* message = rpc->mutable_demuxerstream_readuntil_rpc(); | |
156 last_read_until_count_ += kNumFramesInEachReadUntil; | |
157 message->set_count(last_read_until_count_); | |
158 message->set_callback_handle(rpc_handle_); | |
159 rpc_broker_->SendMessageToRemote(std::move(rpc)); | |
160 read_until_sent_ = true; | |
161 } | |
162 | |
163 void RemoteMediaStream::FlushUntil(int count) { | |
164 while (!buffers_.empty()) { | |
165 buffers_.pop_front(); | |
166 } | |
167 | |
168 last_read_until_count_ = count; | |
169 if (!read_complete_callback_.is_null()) | |
170 CompleteRead(DemuxerStream::kAborted); | |
171 read_until_sent_ = false; | |
172 } | |
173 | |
174 void RemoteMediaStream::Read(const ReadCB& read_cb) { | |
175 DVLOG(3) << __func__; | |
176 DCHECK(read_complete_callback_.is_null()); | |
177 read_complete_callback_ = read_cb; | |
178 if (buffers_.empty() && config_changed_) { | |
179 CompleteRead(DemuxerStream::kConfigChanged); | |
180 return; | |
181 } | |
182 | |
183 // Wait for more data. | |
184 if (buffers_.empty()) { | |
185 SendReadUntil(); | |
186 return; | |
187 } | |
188 | |
189 CompleteRead(DemuxerStream::kOk); | |
190 } | |
191 | |
192 void RemoteMediaStream::CompleteRead(DemuxerStream::Status status) { | |
193 DVLOG(3) << __func__ << ": " << status; | |
194 switch (status) { | |
195 case DemuxerStream::kConfigChanged: | |
196 if (type_ == AUDIO) { | |
197 DCHECK(audio_decoder_config_.size() == 2); | |
miu
2017/03/29 01:39:14
This is weird. Looks like we create a whole deque
xjz
2017/03/30 23:21:31
Done.
| |
198 audio_decoder_config_.pop_front(); | |
199 } else { | |
200 DCHECK(video_decoder_config_.size() == 2); | |
201 video_decoder_config_.pop_front(); | |
202 } | |
203 config_changed_ = false; | |
204 base::ResetAndReturn(&read_complete_callback_).Run(status, nullptr); | |
205 return; | |
206 case DemuxerStream::kAborted: | |
207 base::ResetAndReturn(&read_complete_callback_).Run(status, nullptr); | |
208 return; | |
209 case DemuxerStream::kOk: | |
210 DCHECK(!buffers_.empty()); | |
211 scoped_refptr<DecoderBuffer> frame_data = buffers_.front(); | |
212 buffers_.pop_front(); | |
213 base::ResetAndReturn(&read_complete_callback_).Run(status, frame_data); | |
214 return; | |
215 } | |
216 } | |
217 | |
218 AudioDecoderConfig RemoteMediaStream::audio_decoder_config() { | |
219 DVLOG(3) << __func__; | |
220 DCHECK(type_ == DemuxerStream::AUDIO); | |
221 DCHECK(!audio_decoder_config_.empty()); | |
222 return audio_decoder_config_.front(); | |
223 } | |
224 | |
225 VideoDecoderConfig RemoteMediaStream::video_decoder_config() { | |
226 DVLOG(3) << __func__; | |
227 DCHECK(type_ == DemuxerStream::VIDEO); | |
228 DCHECK(!video_decoder_config_.empty()); | |
229 return video_decoder_config_.front(); | |
230 } | |
231 | |
232 DemuxerStream::Type RemoteMediaStream::type() const { | |
233 return type_; | |
234 } | |
235 | |
236 bool RemoteMediaStream::SupportsConfigChanges() { | |
237 return true; | |
238 } | |
239 | |
240 VideoRotation RemoteMediaStream::video_rotation() { | |
241 return VideoRotation::VIDEO_ROTATION_0; | |
242 } | |
243 | |
244 bool RemoteMediaStream::enabled() const { | |
245 return true; | |
246 } | |
247 | |
248 void RemoteMediaStream::AppendBuffer(scoped_refptr<DecoderBuffer> buffer) { | |
249 DVLOG(3) << __func__; | |
250 buffers_.push_back(buffer); | |
251 if (!read_complete_callback_.is_null()) | |
252 CompleteRead(DemuxerStream::kOk); | |
253 } | |
254 | |
255 RemoteStreamProvider::RemoteStreamProvider(RpcBroker* rpc_broker) | |
256 : rpc_broker_(rpc_broker), weak_factory_(this) {} | |
257 | |
258 RemoteStreamProvider::~RemoteStreamProvider() {} | |
259 | |
260 void RemoteStreamProvider::Initialize(int remote_audio_handle, | |
261 int remote_video_handle, | |
262 const base::Closure& callback) { | |
263 DVLOG(3) << __func__ << ": remote_audio_handle=" << remote_audio_handle | |
264 << " remote_video_handle=" << remote_video_handle; | |
265 DCHECK(init_done_callback_.is_null()); | |
266 DCHECK(remote_audio_handle != RpcBroker::kInvalidHandle || | |
267 remote_video_handle != RpcBroker::kInvalidHandle); | |
268 | |
269 init_done_callback_ = callback; | |
270 if (remote_audio_handle != RpcBroker::kInvalidHandle) { | |
271 audio_stream_.reset(new RemoteMediaStream(rpc_broker_, DemuxerStream::AUDIO, | |
272 remote_audio_handle)); | |
273 audio_stream_->Initialize( | |
274 base::Bind(&RemoteStreamProvider::AudioStreamInitialized, | |
275 weak_factory_.GetWeakPtr())); | |
276 } | |
277 if (remote_video_handle != RpcBroker::kInvalidHandle) { | |
278 video_stream_.reset(new RemoteMediaStream(rpc_broker_, DemuxerStream::VIDEO, | |
279 remote_video_handle)); | |
280 video_stream_->Initialize( | |
281 base::Bind(&RemoteStreamProvider::VideoStreamInitialized, | |
282 weak_factory_.GetWeakPtr())); | |
283 } | |
284 } | |
285 | |
286 void RemoteStreamProvider::AudioStreamInitialized() { | |
287 DCHECK(!init_done_callback_.is_null()); | |
288 audio_stream_initialized_ = true; | |
289 if (video_stream_initialized_ || !video_stream_) | |
290 base::ResetAndReturn(&init_done_callback_).Run(); | |
291 } | |
292 | |
293 void RemoteStreamProvider::VideoStreamInitialized() { | |
294 DCHECK(!init_done_callback_.is_null()); | |
295 video_stream_initialized_ = true; | |
296 if (audio_stream_initialized_ || !audio_stream_) | |
297 base::ResetAndReturn(&init_done_callback_).Run(); | |
298 } | |
299 | |
300 DemuxerStream* RemoteStreamProvider::GetStream(DemuxerStream::Type type) { | |
301 if (type == DemuxerStream::AUDIO) | |
302 return audio_stream_.get(); | |
303 else if (type == DemuxerStream::VIDEO) | |
304 return video_stream_.get(); | |
305 else | |
306 VLOG(1) << __func__ << ": Only supports video or audio stream."; | |
307 return nullptr; | |
308 } | |
309 | |
310 void RemoteStreamProvider::AppendBuffer(DemuxerStream::Type type, | |
311 scoped_refptr<DecoderBuffer> buffer) { | |
312 if (type == DemuxerStream::AUDIO) | |
313 audio_stream_->AppendBuffer(buffer); | |
314 else if (type == DemuxerStream::VIDEO) | |
315 video_stream_->AppendBuffer(buffer); | |
316 else | |
317 VLOG(1) << __func__ << ": Only supports video or audio stream."; | |
318 } | |
319 | |
320 void RemoteStreamProvider::FlushUntil(DemuxerStream::Type type, int count) { | |
321 DVLOG(3) << __func__ << ": type=" << type << " count=" << count; | |
322 if (type == DemuxerStream::AUDIO) | |
323 audio_stream_->FlushUntil(count); | |
324 else if (type == DemuxerStream::VIDEO) | |
325 video_stream_->FlushUntil(count); | |
326 else | |
327 VLOG(1) << __func__ << ": Only supports video or audio stream."; | |
328 } | |
329 | |
330 } // namespace remoting | |
331 } // namespace media | |
OLD | NEW |