| 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 |