OLD | NEW |
| (Empty) |
1 // Copyright 2016 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/remoting_source_impl.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/logging.h" | |
9 #include "media/remoting/rpc/proto_utils.h" | |
10 | |
11 namespace media { | |
12 | |
13 RemotingSourceImpl::RemotingSourceImpl( | |
14 mojom::RemotingSourceRequest source_request, | |
15 mojom::RemoterPtr remoter) | |
16 : rpc_broker_(base::Bind(&RemotingSourceImpl::SendMessageToSink, | |
17 base::Unretained(this))), | |
18 binding_(this, std::move(source_request)), | |
19 remoter_(std::move(remoter)) { | |
20 DCHECK(remoter_); | |
21 } | |
22 | |
23 RemotingSourceImpl::~RemotingSourceImpl() { | |
24 DCHECK(thread_checker_.CalledOnValidThread()); | |
25 | |
26 if (!clients_.empty()) { | |
27 Shutdown(); | |
28 clients_.clear(); | |
29 } | |
30 } | |
31 | |
32 void RemotingSourceImpl::OnSinkAvailable( | |
33 mojom::RemotingSinkCapabilities capabilities) { | |
34 DCHECK(thread_checker_.CalledOnValidThread()); | |
35 | |
36 if (capabilities == mojom::RemotingSinkCapabilities::NONE) { | |
37 OnSinkGone(); | |
38 return; | |
39 } | |
40 sink_capabilities_ = capabilities; | |
41 if (state_ == RemotingSessionState::SESSION_UNAVAILABLE) | |
42 UpdateAndNotifyState(RemotingSessionState::SESSION_CAN_START); | |
43 } | |
44 | |
45 void RemotingSourceImpl::OnSinkGone() { | |
46 DCHECK(thread_checker_.CalledOnValidThread()); | |
47 | |
48 sink_capabilities_ = mojom::RemotingSinkCapabilities::NONE; | |
49 | |
50 if (state_ == RemotingSessionState::SESSION_PERMANENTLY_STOPPED) | |
51 return; | |
52 if (state_ == RemotingSessionState::SESSION_CAN_START) { | |
53 UpdateAndNotifyState(RemotingSessionState::SESSION_UNAVAILABLE); | |
54 return; | |
55 } | |
56 if (state_ == RemotingSessionState::SESSION_STARTED || | |
57 state_ == RemotingSessionState::SESSION_STARTING) { | |
58 VLOG(1) << "Sink is gone in a remoting session."; | |
59 // Remoting is being stopped by Remoter. | |
60 UpdateAndNotifyState(RemotingSessionState::SESSION_STOPPING); | |
61 } | |
62 } | |
63 | |
64 void RemotingSourceImpl::OnStarted() { | |
65 DCHECK(thread_checker_.CalledOnValidThread()); | |
66 | |
67 VLOG(1) << "Remoting started successively."; | |
68 if (clients_.empty() || | |
69 state_ == RemotingSessionState::SESSION_PERMANENTLY_STOPPED || | |
70 state_ == RemotingSessionState::SESSION_STOPPING) { | |
71 for (Client* client : clients_) | |
72 client->OnStarted(false); | |
73 return; | |
74 } | |
75 for (Client* client : clients_) | |
76 client->OnStarted(true); | |
77 state_ = RemotingSessionState::SESSION_STARTED; | |
78 } | |
79 | |
80 void RemotingSourceImpl::OnStartFailed(mojom::RemotingStartFailReason reason) { | |
81 DCHECK(thread_checker_.CalledOnValidThread()); | |
82 | |
83 VLOG(1) << "Failed to start remoting:" << reason; | |
84 for (Client* client : clients_) | |
85 client->OnStarted(false); | |
86 if (state_ == RemotingSessionState::SESSION_PERMANENTLY_STOPPED) | |
87 return; | |
88 state_ = RemotingSessionState::SESSION_UNAVAILABLE; | |
89 } | |
90 | |
91 void RemotingSourceImpl::OnStopped(mojom::RemotingStopReason reason) { | |
92 DCHECK(thread_checker_.CalledOnValidThread()); | |
93 | |
94 VLOG(1) << "Remoting stopped: " << reason; | |
95 if (state_ == RemotingSessionState::SESSION_PERMANENTLY_STOPPED) | |
96 return; | |
97 RemotingSessionState state = RemotingSessionState::SESSION_UNAVAILABLE; | |
98 UpdateAndNotifyState(state); | |
99 } | |
100 | |
101 void RemotingSourceImpl::OnMessageFromSink( | |
102 const std::vector<uint8_t>& message) { | |
103 DCHECK(thread_checker_.CalledOnValidThread()); | |
104 | |
105 std::unique_ptr<remoting::pb::RpcMessage> rpc(new remoting::pb::RpcMessage()); | |
106 if (!rpc->ParseFromArray(message.data(), message.size())) { | |
107 LOG(ERROR) << "corrupted Rpc message"; | |
108 Shutdown(); | |
109 return; | |
110 } | |
111 rpc_broker_.ProcessMessageFromRemote(std::move(rpc)); | |
112 } | |
113 | |
114 void RemotingSourceImpl::UpdateAndNotifyState(RemotingSessionState state) { | |
115 DCHECK(thread_checker_.CalledOnValidThread()); | |
116 | |
117 if (state_ == state) | |
118 return; | |
119 state_ = state; | |
120 for (Client* client : clients_) | |
121 client->OnSessionStateChanged(); | |
122 } | |
123 | |
124 void RemotingSourceImpl::StartRemoting(Client* client) { | |
125 DCHECK(std::find(clients_.begin(), clients_.end(), client) != clients_.end()); | |
126 | |
127 switch (state_) { | |
128 case SESSION_CAN_START: | |
129 remoter_->Start(); | |
130 UpdateAndNotifyState(RemotingSessionState::SESSION_STARTING); | |
131 break; | |
132 case SESSION_STARTING: | |
133 break; | |
134 case SESSION_STARTED: | |
135 client->OnStarted(true); | |
136 break; | |
137 case SESSION_STOPPING: | |
138 case SESSION_UNAVAILABLE: | |
139 case SESSION_PERMANENTLY_STOPPED: | |
140 client->OnStarted(false); | |
141 break; | |
142 } | |
143 } | |
144 | |
145 void RemotingSourceImpl::StopRemoting(Client* client) { | |
146 DCHECK(std::find(clients_.begin(), clients_.end(), client) != clients_.end()); | |
147 | |
148 VLOG(1) << "RemotingSourceImpl::StopRemoting: " << state_; | |
149 | |
150 if (state_ != RemotingSessionState::SESSION_STARTING && | |
151 state_ != RemotingSessionState::SESSION_STARTED) | |
152 return; | |
153 | |
154 remoter_->Stop(mojom::RemotingStopReason::LOCAL_PLAYBACK); | |
155 UpdateAndNotifyState(RemotingSessionState::SESSION_STOPPING); | |
156 } | |
157 | |
158 void RemotingSourceImpl::AddClient(Client* client) { | |
159 DCHECK(thread_checker_.CalledOnValidThread()); | |
160 DCHECK(std::find(clients_.begin(), clients_.end(), client) == clients_.end()); | |
161 | |
162 clients_.push_back(client); | |
163 } | |
164 | |
165 void RemotingSourceImpl::RemoveClient(Client* client) { | |
166 DCHECK(thread_checker_.CalledOnValidThread()); | |
167 | |
168 auto it = std::find(clients_.begin(), clients_.end(), client); | |
169 DCHECK(it != clients_.end()); | |
170 | |
171 clients_.erase(it); | |
172 if (clients_.empty() && (state_ == RemotingSessionState::SESSION_STARTED || | |
173 state_ == RemotingSessionState::SESSION_STARTING)) { | |
174 remoter_->Stop(mojom::RemotingStopReason::SOURCE_GONE); | |
175 state_ = RemotingSessionState::SESSION_STOPPING; | |
176 } | |
177 } | |
178 | |
179 void RemotingSourceImpl::Shutdown() { | |
180 DCHECK(thread_checker_.CalledOnValidThread()); | |
181 | |
182 if (state_ == RemotingSessionState::SESSION_STARTED || | |
183 state_ == RemotingSessionState::SESSION_STARTING) | |
184 remoter_->Stop(mojom::RemotingStopReason::UNEXPECTED_FAILURE); | |
185 UpdateAndNotifyState(RemotingSessionState::SESSION_PERMANENTLY_STOPPED); | |
186 } | |
187 | |
188 void RemotingSourceImpl::StartDataPipe( | |
189 std::unique_ptr<mojo::DataPipe> audio_data_pipe, | |
190 std::unique_ptr<mojo::DataPipe> video_data_pipe, | |
191 const DataPipeStartCallback& done_callback) { | |
192 DCHECK(thread_checker_.CalledOnValidThread()); | |
193 DCHECK(!done_callback.is_null()); | |
194 | |
195 bool audio = audio_data_pipe != nullptr; | |
196 bool video = video_data_pipe != nullptr; | |
197 if (!audio && !video) { | |
198 LOG(ERROR) << "No audio and video to establish data pipe"; | |
199 done_callback.Run(mojom::RemotingDataStreamSenderPtrInfo(), | |
200 mojom::RemotingDataStreamSenderPtrInfo(), | |
201 mojo::ScopedDataPipeProducerHandle(), | |
202 mojo::ScopedDataPipeProducerHandle()); | |
203 return; | |
204 } | |
205 mojom::RemotingDataStreamSenderPtr audio_stream_sender; | |
206 mojom::RemotingDataStreamSenderPtr video_stream_sender; | |
207 remoter_->StartDataStreams( | |
208 audio ? std::move(audio_data_pipe->consumer_handle) | |
209 : mojo::ScopedDataPipeConsumerHandle(), | |
210 video ? std::move(video_data_pipe->consumer_handle) | |
211 : mojo::ScopedDataPipeConsumerHandle(), | |
212 audio ? mojo::MakeRequest(&audio_stream_sender) | |
213 : media::mojom::RemotingDataStreamSenderRequest(), | |
214 video ? mojo::MakeRequest(&video_stream_sender) | |
215 : media::mojom::RemotingDataStreamSenderRequest()); | |
216 done_callback.Run(audio_stream_sender.PassInterface(), | |
217 video_stream_sender.PassInterface(), | |
218 audio ? std::move(audio_data_pipe->producer_handle) | |
219 : mojo::ScopedDataPipeProducerHandle(), | |
220 video ? std::move(video_data_pipe->producer_handle) | |
221 : mojo::ScopedDataPipeProducerHandle()); | |
222 } | |
223 | |
224 remoting::RpcBroker* RemotingSourceImpl::GetRpcBroker() const { | |
225 DCHECK(thread_checker_.CalledOnValidThread()); | |
226 // TODO(xjz): Fix the const-correctness. | |
227 return const_cast<remoting::RpcBroker*>(&rpc_broker_); | |
228 } | |
229 | |
230 void RemotingSourceImpl::SendMessageToSink( | |
231 std::unique_ptr<std::vector<uint8_t>> message) { | |
232 DCHECK(thread_checker_.CalledOnValidThread()); | |
233 remoter_->SendMessageToSink(*message); | |
234 } | |
235 | |
236 } // namespace media | |
OLD | NEW |