| Index: chrome/browser/media/router/mojo/media_remoting_session_impl.cc
|
| diff --git a/chrome/browser/media/router/mojo/media_remoting_session_impl.cc b/chrome/browser/media/router/mojo/media_remoting_session_impl.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..89f56ecb3dc26612434f2eac070f40790d0b8a13
|
| --- /dev/null
|
| +++ b/chrome/browser/media/router/mojo/media_remoting_session_impl.cc
|
| @@ -0,0 +1,177 @@
|
| +// Copyright 2016 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "chrome/browser/media/router/mojo/media_remoting_session_impl.h"
|
| +
|
| +#include "base/callback_helpers.h"
|
| +#include "chrome/browser/media/router/media_remoting_connector.h"
|
| +
|
| +namespace media_router {
|
| +
|
| +MediaRemotingSessionImpl::MediaRemotingSessionImpl(
|
| + MediaRemotingConnector* connector,
|
| + interfaces::MediaRemotingProviderPtr provider,
|
| + mojo::InterfaceRequest<interfaces::MediaRemotingSession> request,
|
| + const base::Closure& did_terminate_callback)
|
| + : connector_(connector),
|
| + remoting_provider_(std::move(provider)),
|
| + binding_(this, std::move(request)),
|
| + did_terminate_callback_(did_terminate_callback),
|
| + remote_capabilities_(nullptr),
|
| + transport_session_id_(nullptr),
|
| + can_remote_media_(false) {
|
| + remoting_provider_.set_connection_error_handler(base::Bind(
|
| + &MediaRemotingSessionImpl::OnConnectionError, base::Unretained(this)));
|
| + binding_.set_connection_error_handler(base::Bind(
|
| + &MediaRemotingSessionImpl::OnConnectionError, base::Unretained(this)));
|
| +}
|
| +
|
| +MediaRemotingSessionImpl::~MediaRemotingSessionImpl() {
|
| + DCHECK(!connector_); // Terminate() must be called before destruction.
|
| +}
|
| +
|
| +void MediaRemotingSessionImpl::OnRemoteServicesAvailable(
|
| + media::mojom::RemoteCapabilitiesPtr capabilities) {
|
| + remote_capabilities_ = std::move(capabilities);
|
| + UpdateAvailability();
|
| +}
|
| +
|
| +void MediaRemotingSessionImpl::OnRemoteServicesGone() {
|
| + remote_capabilities_.reset();
|
| + UpdateAvailability();
|
| +}
|
| +
|
| +void MediaRemotingSessionImpl::OnBitstreamTransportAvailable(
|
| + const mojo::String& transport_session_id) {
|
| + // TODO(miu): Validate that the Cast Streaming transport can be found using
|
| + // the above identifier.
|
| + NOTIMPLEMENTED();
|
| + transport_session_id_ = transport_session_id; // This is a stub.
|
| + UpdateAvailability();
|
| +}
|
| +
|
| +void MediaRemotingSessionImpl::OnBitstreamTransportGone() {
|
| + transport_session_id_ = mojo::String(nullptr);
|
| + UpdateAvailability();
|
| +}
|
| +
|
| +void MediaRemotingSessionImpl::OnMessageFromRemote(
|
| + mojo::Array<uint8_t> message) {
|
| + if (message_callback_.is_null())
|
| + return;
|
| + message_callback_.Run(std::move(message));
|
| +}
|
| +
|
| +void MediaRemotingSessionImpl::Terminate(const mojo::String& error_reason) {
|
| + if (can_remote_media_) {
|
| + connector_->SetProvider(nullptr);
|
| + // Note: By notifying the MediaRemotingConnector that this
|
| + // MediaRemotingSessionImpl is no longer available, it will have called
|
| + // this->StopMediaServices() to shutdown any active media remoting.
|
| + DCHECK(message_callback_.is_null());
|
| + can_remote_media_ = false;
|
| + }
|
| +
|
| + // Now, reset/unbind all remaining mojo bindings.
|
| + if (remoting_provider_.is_bound()) {
|
| + remoting_provider_->OnSessionTerminated(error_reason);
|
| + remoting_provider_.reset();
|
| + }
|
| + binding_.Close();
|
| +
|
| + connector_ = nullptr;
|
| +
|
| + // Finally, run the callback to notify of termination.
|
| + if (!did_terminate_callback_.is_null()) {
|
| + base::ResetAndReturn(&did_terminate_callback_).Run();
|
| + // Note: Running the callback may have deleted |this|!
|
| + }
|
| +}
|
| +
|
| +const media::mojom::RemoteCapabilities*
|
| +MediaRemotingSessionImpl::GetRemoteCapabilities() const {
|
| + return remote_capabilities_.get();
|
| +}
|
| +
|
| +bool MediaRemotingSessionImpl::StartMediaServices(
|
| + mojo::ScopedDataPipeConsumerHandle audio_pipe,
|
| + mojo::ScopedDataPipeConsumerHandle video_pipe,
|
| + const RemoteMessageCallback& message_callback) {
|
| + if (!can_remote_media_ || !message_callback_.is_null())
|
| + return false;
|
| +
|
| + // Either or both data pipes must be provided.
|
| + if (!audio_pipe.is_valid() && !video_pipe.is_valid())
|
| + return false;
|
| +
|
| + DCHECK(!message_callback.is_null());
|
| + message_callback_ = message_callback;
|
| +
|
| + // TODO(miu): Connect data pipes to Cast streaming for remoting frames.
|
| + NOTIMPLEMENTED();
|
| +
|
| + remoting_provider_->StartMediaServices();
|
| + return true;
|
| +}
|
| +
|
| +void MediaRemotingSessionImpl::StopMediaServices(
|
| + const mojo::String& error_reason) {
|
| + if (message_callback_.is_null())
|
| + return;
|
| +
|
| + message_callback_.Reset();
|
| +
|
| + // TODO(miu): Disconnect data pipes from Cast streaming for remoting frames.
|
| + NOTIMPLEMENTED();
|
| +
|
| + remoting_provider_->StopMediaServices(error_reason);
|
| +}
|
| +
|
| +void MediaRemotingSessionImpl::SendMessageToRemote(mojo::Array<uint8_t> message) {
|
| + remoting_provider_->SendMessageToRemote(std::move(message));
|
| +}
|
| +
|
| +void MediaRemotingSessionImpl::SendBufferToRemote(
|
| + uint32_t pipe_id, media::mojom::DecoderBufferPtr buffer) {
|
| + // TODO(miu): Read from pipe and queue frame for sending via Cast streaming.
|
| + NOTIMPLEMENTED();
|
| +}
|
| +
|
| +void MediaRemotingSessionImpl::UpdateAvailability() {
|
| + const bool could_remote_media = can_remote_media_;
|
| + can_remote_media_ = (connector_ &&
|
| + binding_.is_bound() &&
|
| + remoting_provider_.is_bound() &&
|
| + !remote_capabilities_.is_null() &&
|
| + !transport_session_id_.is_null());
|
| + if (can_remote_media_ == could_remote_media)
|
| + return;
|
| + DCHECK(connector_);
|
| + connector_->SetProvider(can_remote_media_ ? this : nullptr);
|
| +}
|
| +
|
| +void MediaRemotingSessionImpl::OnConnectionError() {
|
| + Terminate("internal connection error");
|
| +}
|
| +
|
| +AutoTerminatingRemotingSession::AutoTerminatingRemotingSession(
|
| + content::WebContents* source_contents,
|
| + interfaces::MediaRemotingProviderPtr provider,
|
| + mojo::InterfaceRequest<interfaces::MediaRemotingSession> request,
|
| + const base::Closure& did_terminate_callback)
|
| + : MediaRemotingSessionImpl(MediaRemotingConnector::Get(source_contents),
|
| + std::move(provider), std::move(request),
|
| + did_terminate_callback),
|
| + content::WebContentsObserver(source_contents) {}
|
| +
|
| +AutoTerminatingRemotingSession::~AutoTerminatingRemotingSession() {}
|
| +
|
| +void AutoTerminatingRemotingSession::WebContentsDestroyed() {
|
| + MediaRemotingSessionImpl::Terminate("source of content is gone");
|
| + // Note: At this point, the super class cleared its reference to the
|
| + // MediaRemotingConnector owned by the WebContents, so there should be no
|
| + // dangling references at this point.
|
| +}
|
| +
|
| +} // namespace media_router
|
|
|