| 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 "chrome/browser/media/router/mojo/media_remoting_session_impl.h" |
| 6 |
| 7 #include "base/callback_helpers.h" |
| 8 #include "chrome/browser/media/router/media_remoting_connector.h" |
| 9 |
| 10 namespace media_router { |
| 11 |
| 12 MediaRemotingSessionImpl::MediaRemotingSessionImpl( |
| 13 MediaRemotingConnector* connector, |
| 14 interfaces::MediaRemotingProviderPtr provider, |
| 15 mojo::InterfaceRequest<interfaces::MediaRemotingSession> request, |
| 16 const base::Closure& did_terminate_callback) |
| 17 : connector_(connector), |
| 18 remoting_provider_(std::move(provider)), |
| 19 binding_(this, std::move(request)), |
| 20 did_terminate_callback_(did_terminate_callback), |
| 21 remote_capabilities_(nullptr), |
| 22 transport_session_id_(nullptr), |
| 23 can_remote_media_(false) { |
| 24 remoting_provider_.set_connection_error_handler(base::Bind( |
| 25 &MediaRemotingSessionImpl::OnConnectionError, base::Unretained(this))); |
| 26 binding_.set_connection_error_handler(base::Bind( |
| 27 &MediaRemotingSessionImpl::OnConnectionError, base::Unretained(this))); |
| 28 } |
| 29 |
| 30 MediaRemotingSessionImpl::~MediaRemotingSessionImpl() { |
| 31 DCHECK(!connector_); // Terminate() must be called before destruction. |
| 32 } |
| 33 |
| 34 void MediaRemotingSessionImpl::OnRemoteServicesAvailable( |
| 35 media::mojom::RemoteCapabilitiesPtr capabilities) { |
| 36 remote_capabilities_ = std::move(capabilities); |
| 37 UpdateAvailability(); |
| 38 } |
| 39 |
| 40 void MediaRemotingSessionImpl::OnRemoteServicesGone() { |
| 41 remote_capabilities_.reset(); |
| 42 UpdateAvailability(); |
| 43 } |
| 44 |
| 45 void MediaRemotingSessionImpl::OnBitstreamTransportAvailable( |
| 46 const mojo::String& transport_session_id) { |
| 47 // TODO(miu): Validate that the Cast Streaming transport can be found using |
| 48 // the above identifier. |
| 49 NOTIMPLEMENTED(); |
| 50 transport_session_id_ = transport_session_id; // This is a stub. |
| 51 UpdateAvailability(); |
| 52 } |
| 53 |
| 54 void MediaRemotingSessionImpl::OnBitstreamTransportGone() { |
| 55 transport_session_id_ = mojo::String(nullptr); |
| 56 UpdateAvailability(); |
| 57 } |
| 58 |
| 59 void MediaRemotingSessionImpl::OnMessageFromRemote( |
| 60 mojo::Array<uint8_t> message) { |
| 61 if (message_callback_.is_null()) |
| 62 return; |
| 63 message_callback_.Run(std::move(message)); |
| 64 } |
| 65 |
| 66 void MediaRemotingSessionImpl::Terminate(const mojo::String& error_reason) { |
| 67 if (can_remote_media_) { |
| 68 connector_->SetProvider(nullptr); |
| 69 // Note: By notifying the MediaRemotingConnector that this |
| 70 // MediaRemotingSessionImpl is no longer available, it will have called |
| 71 // this->StopMediaServices() to shutdown any active media remoting. |
| 72 DCHECK(message_callback_.is_null()); |
| 73 can_remote_media_ = false; |
| 74 } |
| 75 |
| 76 // Now, reset/unbind all remaining mojo bindings. |
| 77 if (remoting_provider_.is_bound()) { |
| 78 remoting_provider_->OnSessionTerminated(error_reason); |
| 79 remoting_provider_.reset(); |
| 80 } |
| 81 binding_.Close(); |
| 82 |
| 83 connector_ = nullptr; |
| 84 |
| 85 // Finally, run the callback to notify of termination. |
| 86 if (!did_terminate_callback_.is_null()) { |
| 87 base::ResetAndReturn(&did_terminate_callback_).Run(); |
| 88 // Note: Running the callback may have deleted |this|! |
| 89 } |
| 90 } |
| 91 |
| 92 const media::mojom::RemoteCapabilities* |
| 93 MediaRemotingSessionImpl::GetRemoteCapabilities() const { |
| 94 return remote_capabilities_.get(); |
| 95 } |
| 96 |
| 97 bool MediaRemotingSessionImpl::StartMediaServices( |
| 98 mojo::ScopedDataPipeConsumerHandle audio_pipe, |
| 99 mojo::ScopedDataPipeConsumerHandle video_pipe, |
| 100 const RemoteMessageCallback& message_callback) { |
| 101 if (!can_remote_media_ || !message_callback_.is_null()) |
| 102 return false; |
| 103 |
| 104 // Either or both data pipes must be provided. |
| 105 if (!audio_pipe.is_valid() && !video_pipe.is_valid()) |
| 106 return false; |
| 107 |
| 108 DCHECK(!message_callback.is_null()); |
| 109 message_callback_ = message_callback; |
| 110 |
| 111 // TODO(miu): Connect data pipes to Cast streaming for remoting frames. |
| 112 NOTIMPLEMENTED(); |
| 113 |
| 114 remoting_provider_->StartMediaServices(); |
| 115 return true; |
| 116 } |
| 117 |
| 118 void MediaRemotingSessionImpl::StopMediaServices( |
| 119 const mojo::String& error_reason) { |
| 120 if (message_callback_.is_null()) |
| 121 return; |
| 122 |
| 123 message_callback_.Reset(); |
| 124 |
| 125 // TODO(miu): Disconnect data pipes from Cast streaming for remoting frames. |
| 126 NOTIMPLEMENTED(); |
| 127 |
| 128 remoting_provider_->StopMediaServices(error_reason); |
| 129 } |
| 130 |
| 131 void MediaRemotingSessionImpl::SendMessageToRemote(mojo::Array<uint8_t> message)
{ |
| 132 remoting_provider_->SendMessageToRemote(std::move(message)); |
| 133 } |
| 134 |
| 135 void MediaRemotingSessionImpl::SendBufferToRemote( |
| 136 uint32_t pipe_id, media::mojom::DecoderBufferPtr buffer) { |
| 137 // TODO(miu): Read from pipe and queue frame for sending via Cast streaming. |
| 138 NOTIMPLEMENTED(); |
| 139 } |
| 140 |
| 141 void MediaRemotingSessionImpl::UpdateAvailability() { |
| 142 const bool could_remote_media = can_remote_media_; |
| 143 can_remote_media_ = (connector_ && |
| 144 binding_.is_bound() && |
| 145 remoting_provider_.is_bound() && |
| 146 !remote_capabilities_.is_null() && |
| 147 !transport_session_id_.is_null()); |
| 148 if (can_remote_media_ == could_remote_media) |
| 149 return; |
| 150 DCHECK(connector_); |
| 151 connector_->SetProvider(can_remote_media_ ? this : nullptr); |
| 152 } |
| 153 |
| 154 void MediaRemotingSessionImpl::OnConnectionError() { |
| 155 Terminate("internal connection error"); |
| 156 } |
| 157 |
| 158 AutoTerminatingRemotingSession::AutoTerminatingRemotingSession( |
| 159 content::WebContents* source_contents, |
| 160 interfaces::MediaRemotingProviderPtr provider, |
| 161 mojo::InterfaceRequest<interfaces::MediaRemotingSession> request, |
| 162 const base::Closure& did_terminate_callback) |
| 163 : MediaRemotingSessionImpl(MediaRemotingConnector::Get(source_contents), |
| 164 std::move(provider), std::move(request), |
| 165 did_terminate_callback), |
| 166 content::WebContentsObserver(source_contents) {} |
| 167 |
| 168 AutoTerminatingRemotingSession::~AutoTerminatingRemotingSession() {} |
| 169 |
| 170 void AutoTerminatingRemotingSession::WebContentsDestroyed() { |
| 171 MediaRemotingSessionImpl::Terminate("source of content is gone"); |
| 172 // Note: At this point, the super class cleared its reference to the |
| 173 // MediaRemotingConnector owned by the WebContents, so there should be no |
| 174 // dangling references at this point. |
| 175 } |
| 176 |
| 177 } // namespace media_router |
| OLD | NEW |