diff options
author | kcwu <kcwu@chromium.org> | 2016-01-11 20:51:34 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-01-12 04:52:46 +0000 |
commit | daa96926c4bd58df2790c0e12fc92d858243ed0a (patch) | |
tree | 1effd67a74868aa12c3de5ef9ab4b410aa9dc474 | |
parent | 483df9304bb678dd50b435a41c063a3aed96d10f (diff) | |
download | chromium_src-daa96926c4bd58df2790c0e12fc92d858243ed0a.zip chromium_src-daa96926c4bd58df2790c0e12fc92d858243ed0a.tar.gz chromium_src-daa96926c4bd58df2790c0e12fc92d858243ed0a.tar.bz2 |
Implement GpuArcVideoService for arc video accelerator
GpuArcVideoService creates new channel and dispatch IPC to
ArcVideoAccelerator.
BUG=b/25057601
Review URL: https://codereview.chromium.org/1451353002
Cr-Commit-Position: refs/heads/master@{#368797}
29 files changed, 659 insertions, 5 deletions
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc index 0b5154a..aa3df36 100644 --- a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc +++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc @@ -117,6 +117,8 @@ #include "components/arc/arc_bridge_service.h" #include "components/arc/arc_service_manager.h" #include "components/arc/settings/arc_settings_bridge.h" +#include "components/arc/video/arc_video_bridge.h" +#include "components/arc/video/video_host_delegate.h" #include "components/browser_sync/common/browser_sync_switches.h" #include "components/device_event_log/device_event_log.h" #include "components/metrics/metrics_service.h" @@ -126,6 +128,7 @@ #include "components/user_manager/user.h" #include "components/user_manager/user_manager.h" #include "components/wallpaper/wallpaper_manager_base.h" +#include "content/public/browser/arc_video_host_delegate.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/notification_service.h" #include "content/public/common/content_switches.h" @@ -397,7 +400,9 @@ void ChromeBrowserMainPartsChromeos::PreMainMessageLoopRun() { arc_service_manager_.reset(new arc::ArcServiceManager( make_scoped_ptr(new arc::ArcAuthServiceImpl()), - make_scoped_ptr(new arc::ArcSettingsBridgeImpl()))); + make_scoped_ptr(new arc::ArcSettingsBridgeImpl()), + make_scoped_ptr( + new arc::ArcVideoBridge(content::CreateArcVideoHostDelegate())))); arc_service_manager_->arc_bridge_service()->DetectAvailability(); chromeos::ResourceReporter::GetInstance()->StartMonitoring(); diff --git a/components/arc.gypi b/components/arc.gypi index 1e7a8fa..daeef02 100644 --- a/components/arc.gypi +++ b/components/arc.gypi @@ -40,6 +40,9 @@ 'arc/settings/arc_settings_bridge.h', 'arc/power/arc_power_bridge.cc', 'arc/power/arc_power_bridge.h', + 'arc/video/arc_video_bridge.cc', + 'arc/video/arc_video_bridge.h', + 'arc/video/video_host_delegate.h', ], }, { @@ -80,6 +83,7 @@ 'arc/common/power.mojom', 'arc/common/process.mojom', 'arc/common/settings.mojom', + 'arc/common/video.mojom', ], }, ], diff --git a/components/arc/BUILD.gn b/components/arc/BUILD.gn index 693e8f3..113a392 100644 --- a/components/arc/BUILD.gn +++ b/components/arc/BUILD.gn @@ -24,6 +24,9 @@ static_library("arc") { "power/arc_power_bridge.h", "settings/arc_settings_bridge.cc", "settings/arc_settings_bridge.h", + "video/arc_video_bridge.cc", + "video/arc_video_bridge.h", + "video/video_host_delegate.h", ] deps = [ @@ -56,6 +59,7 @@ mojom("arc_bindings") { "common/power.mojom", "common/process.mojom", "common/settings.mojom", + "common/video.mojom", ] } diff --git a/components/arc/arc_bridge_service.cc b/components/arc/arc_bridge_service.cc index 41f5fd3..60acbfe 100644 --- a/components/arc/arc_bridge_service.cc +++ b/components/arc/arc_bridge_service.cc @@ -252,6 +252,29 @@ void ArcBridgeService::CloseSettingsChannel() { FOR_EACH_OBSERVER(Observer, observer_list(), OnSettingsInstanceClosed()); } +void ArcBridgeService::OnVideoInstanceReady(VideoInstancePtr video_ptr) { + DCHECK(CalledOnValidThread()); + temporary_video_ptr_ = std::move(video_ptr); + temporary_video_ptr_.QueryVersion(base::Bind( + &ArcBridgeService::OnVideoVersionReady, weak_factory_.GetWeakPtr())); +} + +void ArcBridgeService::OnVideoVersionReady(int32_t version) { + video_ptr_ = std::move(temporary_video_ptr_); + FOR_EACH_OBSERVER(Observer, observer_list(), OnVideoInstanceReady()); + video_ptr_.set_connection_error_handler(base::Bind( + &ArcBridgeService::CloseVideoChannel, weak_factory_.GetWeakPtr())); +} + +void ArcBridgeService::CloseVideoChannel() { + DCHECK(CalledOnValidThread()); + if (!video_ptr_) + return; + + video_ptr_.reset(); + FOR_EACH_OBSERVER(Observer, observer_list(), OnVideoInstanceClosed()); +} + void ArcBridgeService::SetState(State state) { DCHECK(CalledOnValidThread()); // DCHECK on enum classes not supported. @@ -282,6 +305,7 @@ void ArcBridgeService::CloseAllChannels() { ClosePowerChannel(); CloseProcessChannel(); CloseSettingsChannel(); + CloseVideoChannel(); } } // namespace arc diff --git a/components/arc/arc_bridge_service.h b/components/arc/arc_bridge_service.h index 438e330a..509c79c 100644 --- a/components/arc/arc_bridge_service.h +++ b/components/arc/arc_bridge_service.h @@ -105,6 +105,10 @@ class ArcBridgeService : public ArcBridgeHost { virtual void OnSettingsInstanceReady() {} virtual void OnSettingsInstanceClosed() {} + // Called whenever the ARC video interface state changes. + virtual void OnVideoInstanceReady() {} + virtual void OnVideoInstanceClosed() {} + protected: virtual ~Observer() {} }; @@ -152,6 +156,7 @@ class ArcBridgeService : public ArcBridgeHost { PowerInstance* power_instance() { return power_ptr_.get(); } ProcessInstance* process_instance() { return process_ptr_.get(); } SettingsInstance* settings_instance() { return settings_ptr_.get(); } + VideoInstance* video_instance() { return video_ptr_.get(); } int32_t app_version() const { return app_ptr_.version(); } int32_t auth_version() const { return auth_ptr_.version(); } @@ -161,6 +166,7 @@ class ArcBridgeService : public ArcBridgeHost { int32_t power_version() const { return power_ptr_.version(); } int32_t process_version() const { return process_ptr_.version(); } int32_t settings_version() const { return settings_ptr_.version(); } + int32_t video_version() const { return video_ptr_.version(); } // ArcHost: void OnAppInstanceReady(AppInstancePtr app_ptr) override; @@ -172,6 +178,7 @@ class ArcBridgeService : public ArcBridgeHost { void OnPowerInstanceReady(PowerInstancePtr power_ptr) override; void OnProcessInstanceReady(ProcessInstancePtr process_ptr) override; void OnSettingsInstanceReady(SettingsInstancePtr process_ptr) override; + void OnVideoInstanceReady(VideoInstancePtr video_ptr) override; // Gets the current state of the bridge service. State state() const { return state_; } @@ -211,6 +218,7 @@ class ArcBridgeService : public ArcBridgeHost { void ClosePowerChannel(); void CloseProcessChannel(); void CloseSettingsChannel(); + void CloseVideoChannel(); // Callbacks for QueryVersion. void OnAppVersionReady(int32_t version); @@ -221,6 +229,7 @@ class ArcBridgeService : public ArcBridgeHost { void OnPowerVersionReady(int32_t version); void OnProcessVersionReady(int32_t version); void OnSettingsVersionReady(int32_t version); + void OnVideoVersionReady(int32_t version); // Mojo interfaces. AppInstancePtr app_ptr_; @@ -231,6 +240,7 @@ class ArcBridgeService : public ArcBridgeHost { PowerInstancePtr power_ptr_; ProcessInstancePtr process_ptr_; SettingsInstancePtr settings_ptr_; + VideoInstancePtr video_ptr_; // Temporary Mojo interfaces. After a Mojo interface pointer has been // received from the other endpoint, we still need to asynchronously query @@ -246,6 +256,7 @@ class ArcBridgeService : public ArcBridgeHost { PowerInstancePtr temporary_power_ptr_; ProcessInstancePtr temporary_process_ptr_; SettingsInstancePtr temporary_settings_ptr_; + VideoInstancePtr temporary_video_ptr_; base::ObserverList<Observer> observer_list_; diff --git a/components/arc/arc_service_manager.cc b/components/arc/arc_service_manager.cc index 9b8bd81..3f56538 100644 --- a/components/arc/arc_service_manager.cc +++ b/components/arc/arc_service_manager.cc @@ -4,6 +4,8 @@ #include "components/arc/arc_service_manager.h" +#include <utility> + #include "base/sequenced_task_runner.h" #include "base/thread_task_runner_handle.h" #include "components/arc/arc_bridge_bootstrap.h" @@ -13,6 +15,7 @@ #include "components/arc/input/arc_input_bridge.h" #include "components/arc/power/arc_power_bridge.h" #include "components/arc/settings/arc_settings_bridge.h" +#include "components/arc/video/arc_video_bridge.h" namespace arc { @@ -25,19 +28,22 @@ ArcServiceManager* g_arc_service_manager = nullptr; ArcServiceManager::ArcServiceManager( scoped_ptr<ArcAuthService> auth_service, - scoped_ptr<ArcSettingsBridge> settings_bridge) + scoped_ptr<ArcSettingsBridge> settings_bridge, + scoped_ptr<ArcVideoBridge> video_bridge) : arc_bridge_service_( new ArcBridgeServiceImpl(ArcBridgeBootstrap::Create())), arc_auth_service_(std::move(auth_service)), arc_clipboard_bridge_(new ArcClipboardBridge(arc_bridge_service_.get())), arc_input_bridge_(ArcInputBridge::Create(arc_bridge_service_.get())), arc_settings_bridge_(std::move(settings_bridge)), - arc_power_bridge_(new ArcPowerBridge(arc_bridge_service_.get())) { + arc_power_bridge_(new ArcPowerBridge(arc_bridge_service_.get())), + arc_video_bridge_(std::move(video_bridge)) { DCHECK(!g_arc_service_manager); g_arc_service_manager = this; arc_settings_bridge_->StartObservingBridgeServiceChanges(); arc_auth_service_->StartObservingBridgeServiceChanges(); + arc_video_bridge_->StartObservingBridgeServiceChanges(); } ArcServiceManager::~ArcServiceManager() { diff --git a/components/arc/arc_service_manager.h b/components/arc/arc_service_manager.h index 75686d0..278b1e1 100644 --- a/components/arc/arc_service_manager.h +++ b/components/arc/arc_service_manager.h @@ -15,15 +15,17 @@ class ArcAuthService; class ArcBridgeService; class ArcClipboardBridge; class ArcInputBridge; -class ArcSettingsBridge; class ArcPowerBridge; +class ArcSettingsBridge; +class ArcVideoBridge; // Manages creation and destruction of services that communicate with the ARC // instance via the ArcBridgeService. class ArcServiceManager { public: ArcServiceManager(scoped_ptr<ArcAuthService> auth_service, - scoped_ptr<ArcSettingsBridge> settings_bridge); + scoped_ptr<ArcSettingsBridge> settings_bridge, + scoped_ptr<ArcVideoBridge> video_bridge); virtual ~ArcServiceManager(); // |arc_bridge_service| can only be accessed on the thread that this @@ -44,6 +46,7 @@ class ArcServiceManager { scoped_ptr<ArcInputBridge> arc_input_bridge_; scoped_ptr<ArcSettingsBridge> arc_settings_bridge_; scoped_ptr<ArcPowerBridge> arc_power_bridge_; + scoped_ptr<ArcVideoBridge> arc_video_bridge_; DISALLOW_COPY_AND_ASSIGN(ArcServiceManager); }; diff --git a/components/arc/common/arc_bridge.mojom b/components/arc/common/arc_bridge.mojom index ae180b9..3844592 100644 --- a/components/arc/common/arc_bridge.mojom +++ b/components/arc/common/arc_bridge.mojom @@ -12,6 +12,7 @@ import "notifications.mojom"; import "power.mojom"; import "process.mojom"; import "settings.mojom"; +import "video.mojom"; interface ArcBridgeHost { // Keep the entries alphabetical. In order to do so without breaking @@ -41,6 +42,9 @@ interface ArcBridgeHost { // Notifies Chrome that the SettingsInstance interface is ready. OnSettingsInstanceReady@105(SettingsInstance instance_ptr); + + // Notifies Chrome that the VideoInstance interface is ready. + [MinVersion=2] OnVideoInstanceReady@107(VideoInstance instance_ptr); }; interface ArcBridgeInstance { diff --git a/components/arc/common/video.mojom b/components/arc/common/video.mojom new file mode 100644 index 0000000..b21a1db --- /dev/null +++ b/components/arc/common/video.mojom @@ -0,0 +1,15 @@ +// 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. + +module arc; + +interface VideoHost { + // Notifies Chrome a request for ipc channel of video acceleration. + OnRequestArcVideoAcceleratorChannel() => (handle channel_handle); +}; + +interface VideoInstance { + // Establishes full-duplex communication with the host. + Init(VideoHost host_ptr); +}; diff --git a/components/arc/video/arc_video_bridge.cc b/components/arc/video/arc_video_bridge.cc new file mode 100644 index 0000000..dddbb39 --- /dev/null +++ b/components/arc/video/arc_video_bridge.cc @@ -0,0 +1,52 @@ +// 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 "components/arc/video/arc_video_bridge.h" + +#include <utility> + +namespace arc { + +ArcVideoBridge::ArcVideoBridge( + scoped_ptr<VideoHostDelegate> video_host_delegate) + : video_host_delegate_(std::move(video_host_delegate)), + binding_(video_host_delegate_.get()) {} + +ArcVideoBridge::~ArcVideoBridge() { + arc::ArcBridgeService* bridge_service = arc::ArcBridgeService::Get(); + DCHECK(bridge_service); + bridge_service->RemoveObserver(this); +} + +void ArcVideoBridge::StartObservingBridgeServiceChanges() { + arc::ArcBridgeService* bridge_service = arc::ArcBridgeService::Get(); + DCHECK(bridge_service); + bridge_service->AddObserver(this); + + // If VideoInstance was ready before we AddObserver(), we won't get + // OnVideoInstanceReady events. For such case, we have to call it explicitly. + if (bridge_service->video_instance()) + OnVideoInstanceReady(); +} + +void ArcVideoBridge::OnStateChanged(arc::ArcBridgeService::State state) { + switch (state) { + case arc::ArcBridgeService::State::STOPPING: + video_host_delegate_->OnStopping(); + break; + default: + break; + } +} + +void ArcVideoBridge::OnVideoInstanceReady() { + arc::ArcBridgeService* bridge_service = arc::ArcBridgeService::Get(); + DCHECK(bridge_service); + + arc::VideoHostPtr host; + binding_.Bind(mojo::GetProxy(&host)); + bridge_service->video_instance()->Init(std::move(host)); +} + +} // namespace arc diff --git a/components/arc/video/arc_video_bridge.h b/components/arc/video/arc_video_bridge.h new file mode 100644 index 0000000..f781a5e --- /dev/null +++ b/components/arc/video/arc_video_bridge.h @@ -0,0 +1,41 @@ +// 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. + +#ifndef COMPONENTS_ARC_VIDEO_ARC_VIDEO_BRIDGE_H +#define COMPONENTS_ARC_VIDEO_ARC_VIDEO_BRIDGE_H + +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "components/arc/arc_bridge_service.h" +#include "components/arc/video/video_host_delegate.h" +#include "mojo/public/cpp/bindings/binding.h" + +namespace arc { + +class VideoHostDelegate; + +// ArcVideoBridge bridges ArcBridgeService and VideoHostDelegate. It observes +// ArcBridgeService events and pass VideoHost proxy to VideoInstance. +class ArcVideoBridge : public ArcBridgeService::Observer { + public: + explicit ArcVideoBridge(scoped_ptr<VideoHostDelegate> video_host_delegate); + ~ArcVideoBridge() override; + + // Starts listening to state changes of the ArcBridgeService. + void StartObservingBridgeServiceChanges(); + + // arc::ArcBridgeService::Observer implementation. + void OnStateChanged(arc::ArcBridgeService::State state) override; + void OnVideoInstanceReady() override; + + private: + scoped_ptr<VideoHostDelegate> video_host_delegate_; + mojo::Binding<arc::VideoHost> binding_; + + DISALLOW_COPY_AND_ASSIGN(ArcVideoBridge); +}; + +} // namespace arc + +#endif // COMPONENTS_ARC_VIDEO_ARC_VIDEO_BRIDGE_H diff --git a/components/arc/video/video_host_delegate.h b/components/arc/video/video_host_delegate.h new file mode 100644 index 0000000..3edc792 --- /dev/null +++ b/components/arc/video/video_host_delegate.h @@ -0,0 +1,26 @@ +// 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. + +#ifndef COMPONENTS_ARC_VIDEO_VIDEO_HOST_DELEGATE_H +#define COMPONENTS_ARC_VIDEO_VIDEO_HOST_DELEGATE_H + +#include "components/arc/common/video.mojom.h" + +namespace arc { + +// VideoHostDelegate is an abstract class providing video decoding/encoding +// acceleration service. +// +// The purpose of this interface is to create a channel into the GPU process +// only, which then handles video decoding/encoding, without going through +// VideoHostDelegate anymore. +class VideoHostDelegate : public VideoHost { + public: + // Called when the video service is stopping. + virtual void OnStopping() = 0; +}; + +} // namespace arc + +#endif // COMPONENTS_ARC_VIDEO_VIDEO_HOST_DELEGATE_H diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index cc4419c..4d66f86 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn @@ -417,6 +417,10 @@ source_set("browser") { if (is_chromeos) { sources -= [ "device_sensors/data_fetcher_shared_memory_default.cc" ] + sources += [ + "gpu/gpu_arc_video_service_host.cc", + "gpu/gpu_arc_video_service_host.h", + ] deps += [ "//chromeos", "//chromeos:power_manager_proto", diff --git a/content/browser/DEPS b/content/browser/DEPS index 93be705..5e33c93 100644 --- a/content/browser/DEPS +++ b/content/browser/DEPS @@ -1,6 +1,7 @@ include_rules = [ # Allow inclusion of specific components that we depend on. We may only # depend on components which we share with the mojo html_viewer. + "+components/arc", "+components/mime_util", "+components/mus/public/interfaces", "+components/mus/public", diff --git a/content/browser/gpu/gpu_arc_video_service_host.cc b/content/browser/gpu/gpu_arc_video_service_host.cc new file mode 100644 index 0000000..7ba572d --- /dev/null +++ b/content/browser/gpu/gpu_arc_video_service_host.cc @@ -0,0 +1,76 @@ +// 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 "content/browser/gpu/gpu_arc_video_service_host.h" + +#include "base/location.h" +#include "base/logging.h" +#include "base/message_loop/message_loop.h" +#include "content/browser/gpu/gpu_process_host.h" +#include "content/common/gpu/gpu_messages.h" +#include "content/public/browser/arc_video_host_delegate.h" +#include "content/public/browser/browser_thread.h" +#include "ipc/ipc_channel_handle.h" +#include "ipc/ipc_message_macros.h" +#include "ipc/ipc_message_utils.h" +#include "third_party/mojo/src/mojo/edk/embedder/embedder.h" + +namespace content { + +namespace { + +void CreateChannelOnIOThread( + const GpuProcessHost::CreateArcVideoAcceleratorChannelCallback& callback) { + GpuProcessHost* gpu_process_host = + GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, + CAUSE_FOR_GPU_LAUNCH_ARCVIDEOACCELERATOR); + gpu_process_host->CreateArcVideoAcceleratorChannel(callback); +} + +void HandleChannelCreatedReply( + const arc::VideoHost::OnRequestArcVideoAcceleratorChannelCallback& callback, + const IPC::ChannelHandle& handle) { + MojoHandle wrapped_handle; + MojoResult wrap_result = mojo::embedder::CreatePlatformHandleWrapper( + mojo::embedder::ScopedPlatformHandle( + mojo::embedder::PlatformHandle(handle.socket.fd)), + &wrapped_handle); + if (wrap_result != MOJO_RESULT_OK) { + LOG(WARNING) << "Pipe failed to wrap handles. Closing: " << wrap_result; + callback.Run(mojo::ScopedHandle()); + return; + } + callback.Run(mojo::ScopedHandle(mojo::Handle(wrapped_handle))); +} + +} // namespace + +scoped_ptr<arc::VideoHostDelegate> CreateArcVideoHostDelegate() { + return make_scoped_ptr(new GpuArcVideoServiceHost()); +} + +GpuArcVideoServiceHost::GpuArcVideoServiceHost() + : io_task_runner_(content::BrowserThread::GetMessageLoopProxyForThread( + content::BrowserThread::IO)) {} + +GpuArcVideoServiceHost::~GpuArcVideoServiceHost() { + DCHECK(thread_checker_.CalledOnValidThread()); +} + +void GpuArcVideoServiceHost::OnRequestArcVideoAcceleratorChannel( + const OnRequestArcVideoAcceleratorChannelCallback& callback) { + DCHECK(thread_checker_.CalledOnValidThread()); + + io_task_runner_->PostTask( + FROM_HERE, base::Bind(&CreateChannelOnIOThread, + base::Bind(&HandleChannelCreatedReply, callback))); +} + +void GpuArcVideoServiceHost::OnStopping() { + GpuProcessHost::SendOnIO(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, + CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH, + new GpuMsg_ShutdownArcVideoService()); +} + +} // namespace content diff --git a/content/browser/gpu/gpu_arc_video_service_host.h b/content/browser/gpu/gpu_arc_video_service_host.h new file mode 100644 index 0000000..3a5ca2a --- /dev/null +++ b/content/browser/gpu/gpu_arc_video_service_host.h @@ -0,0 +1,54 @@ +// 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. + +#ifndef CONTENT_BROWSER_GPU_GPU_ARC_VIDEO_SERVICE_HOST_H_ +#define CONTENT_BROWSER_GPU_GPU_ARC_VIDEO_SERVICE_HOST_H_ + +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/threading/thread_checker.h" +#include "components/arc/video/video_host_delegate.h" + +namespace base { +class SingleThreadTaskRunner; +} + +namespace IPC { +struct ChannelHandle; +} + +namespace content { + +// This class passes requests from arc::VideoInstance to GpuArcVideoService to +// create a video accelerator channel in GPU process and reply the created +// channel. +// +// Don't be confused two senses of "host" of this class. This class, which +// implements arc::VideoHost, handles requests from arc::VideoInstance. At the +// same time, as its name says, this class is the host of corresponding class, +// GpuArcVideoService, in the GPU process. +class GpuArcVideoServiceHost : public arc::VideoHostDelegate { + public: + GpuArcVideoServiceHost(); + ~GpuArcVideoServiceHost() override; + + // arc::VideoHostDelegate implementation. + void OnStopping() override; + + // arc::VideoHost implementation. + void OnRequestArcVideoAcceleratorChannel( + const OnRequestArcVideoAcceleratorChannelCallback& callback) override; + + private: + base::ThreadChecker thread_checker_; + + // IO task runner, where GpuProcessHost tasks run. + scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; + + DISALLOW_COPY_AND_ASSIGN(GpuArcVideoServiceHost); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_GPU_GPU_ARC_VIDEO_SERVICE_HOST_H_ diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc index b970578..45eaf1a 100644 --- a/content/browser/gpu/gpu_process_host.cc +++ b/content/browser/gpu/gpu_process_host.cc @@ -604,6 +604,10 @@ bool GpuProcessHost::OnMessageReceived(const IPC::Message& message) { OnGpuMemoryBufferCreated) IPC_MESSAGE_HANDLER(GpuHostMsg_DidCreateOffscreenContext, OnDidCreateOffscreenContext) +#if defined(OS_CHROMEOS) + IPC_MESSAGE_HANDLER(GpuHostMsg_ArcVideoAcceleratorChannelCreated, + OnArcVideoAcceleratorChannelCreated) +#endif IPC_MESSAGE_HANDLER(GpuHostMsg_DidLoseContext, OnDidLoseContext) IPC_MESSAGE_HANDLER(GpuHostMsg_DidDestroyOffscreenContext, OnDidDestroyOffscreenContext) @@ -787,6 +791,19 @@ void GpuProcessHost::DestroyGpuMemoryBuffer(gfx::GpuMemoryBufferId id, Send(new GpuMsg_DestroyGpuMemoryBuffer(id, client_id, sync_token)); } +#if defined(OS_CHROMEOS) +void GpuProcessHost::CreateArcVideoAcceleratorChannel( + const CreateArcVideoAcceleratorChannelCallback& callback) { + DCHECK(CalledOnValidThread()); + + if (Send(new GpuMsg_CreateArcVideoAcceleratorChannel())) { + create_arc_video_accelerator_channel_requests_.push(callback); + } else { + callback.Run(IPC::ChannelHandle()); + } +} +#endif + void GpuProcessHost::OnInitialized(bool result, const gpu::GPUInfo& gpu_info) { UMA_HISTOGRAM_BOOLEAN("GPU.GPUProcessInitialized", result); initialized_ = result; @@ -854,6 +871,24 @@ void GpuProcessHost::OnGpuMemoryBufferCreated( callback.Run(handle); } +#if defined(OS_CHROMEOS) +void GpuProcessHost::OnArcVideoAcceleratorChannelCreated( + const IPC::ChannelHandle& handle) { + if (create_arc_video_accelerator_channel_requests_.empty()) { + RouteOnUIThread( + GpuHostMsg_OnLogMessage(logging::LOG_WARNING, "WARNING", + "Received a ArcVideoAcceleratorChannelCreated " + "message but no requests in queue.")); + return; + } + + CreateArcVideoAcceleratorChannelCallback callback = + create_arc_video_accelerator_channel_requests_.front(); + create_arc_video_accelerator_channel_requests_.pop(); + callback.Run(handle); +} +#endif + void GpuProcessHost::OnDidCreateOffscreenContext(const GURL& url) { urls_with_live_offscreen_contexts_.insert(url); } @@ -1059,6 +1094,15 @@ void GpuProcessHost::SendOutstandingReplies() { create_gpu_memory_buffer_requests_.pop(); callback.Run(gfx::GpuMemoryBufferHandle()); } + +#if defined(OS_CHROMEOS) + while (!create_arc_video_accelerator_channel_requests_.empty()) { + CreateArcVideoAcceleratorChannelCallback callback = + create_arc_video_accelerator_channel_requests_.front(); + create_arc_video_accelerator_channel_requests_.pop(); + callback.Run(IPC::ChannelHandle()); + } +#endif } void GpuProcessHost::BlockLiveOffscreenContexts() { diff --git a/content/browser/gpu/gpu_process_host.h b/content/browser/gpu/gpu_process_host.h index 3df8067..ec94b98 100644 --- a/content/browser/gpu/gpu_process_host.h +++ b/content/browser/gpu/gpu_process_host.h @@ -74,6 +74,11 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate, typedef base::Callback<void(const gfx::GpuMemoryBufferHandle& handle)> CreateGpuMemoryBufferCallback; +#if defined(OS_CHROMEOS) + typedef base::Callback<void(const IPC::ChannelHandle&)> + CreateArcVideoAcceleratorChannelCallback; +#endif + static bool gpu_enabled() { return gpu_enabled_; } static int gpu_crash_count() { return gpu_crash_count_; } @@ -154,6 +159,13 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate, int client_id, const gpu::SyncToken& sync_token); +#if defined(OS_CHROMEOS) + // Tells the GPU process to create a new ipc channel for + // ArcVideoAccelerator. + void CreateArcVideoAcceleratorChannel( + const CreateArcVideoAcceleratorChannelCallback& callback); +#endif + // What kind of GPU process, e.g. sandboxed or unsandboxed. GpuProcessKind kind(); @@ -196,6 +208,7 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate, void OnChannelEstablished(const IPC::ChannelHandle& channel_handle); void OnCommandBufferCreated(CreateCommandBufferResult result); void OnGpuMemoryBufferCreated(const gfx::GpuMemoryBufferHandle& handle); + void OnArcVideoAcceleratorChannelCreated(const IPC::ChannelHandle& handle); void OnDidCreateOffscreenContext(const GURL& url); void OnDidLoseContext(bool offscreen, gpu::error::ContextLostReason reason, @@ -242,6 +255,13 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate, // The pending create gpu memory buffer requests we need to reply to. std::queue<CreateGpuMemoryBufferCallback> create_gpu_memory_buffer_requests_; +#if defined(OS_CHROMEOS) + // The pending create arc video accelerator channel requests we need to reply + // to. + std::queue<CreateArcVideoAcceleratorChannelCallback> + create_arc_video_accelerator_channel_requests_; +#endif + // Qeueud messages to send when the process launches. std::queue<IPC::Message*> queued_messages_; diff --git a/content/common/BUILD.gn b/content/common/BUILD.gn index d2ef67d..e60bfee 100644 --- a/content/common/BUILD.gn +++ b/content/common/BUILD.gn @@ -379,6 +379,8 @@ source_set("common") { if (is_chromeos) { sources += [ "gpu/media/accelerated_video_decoder.h", + "gpu/media/gpu_arc_video_service.cc", + "gpu/media/gpu_arc_video_service.h", "gpu/media/h264_decoder.cc", "gpu/media/h264_decoder.h", "gpu/media/h264_dpb.cc", @@ -392,6 +394,7 @@ source_set("common") { "gpu/media/vp9_picture.cc", "gpu/media/vp9_picture.h", ] + deps += [ "//components/arc" ] if (use_v4lplugin) { defines += [ "USE_LIBV4L2" ] sources += get_target_outputs(":libv4l2_generate_stubs") diff --git a/content/common/gpu/gpu_channel_manager.cc b/content/common/gpu/gpu_channel_manager.cc index 4f14ed8..8f59e90 100644 --- a/content/common/gpu/gpu_channel_manager.cc +++ b/content/common/gpu/gpu_channel_manager.cc @@ -30,6 +30,10 @@ #include "ui/gl/gl_bindings.h" #include "ui/gl/gl_share_group.h" +#if defined(OS_CHROMEOS) +#include "content/common/gpu/media/gpu_arc_video_service.h" +#endif + namespace content { namespace { @@ -138,6 +142,10 @@ bool GpuChannelManager::OnControlMessageReceived(const IPC::Message& msg) { IPC_MESSAGE_HANDLER(GpuMsg_CreateViewCommandBuffer, OnCreateViewCommandBuffer) IPC_MESSAGE_HANDLER(GpuMsg_DestroyGpuMemoryBuffer, OnDestroyGpuMemoryBuffer) +#if defined(OS_CHROMEOS) + IPC_MESSAGE_HANDLER(GpuMsg_CreateArcVideoAcceleratorChannel, + OnCreateArcVideoAcceleratorChannel) +#endif IPC_MESSAGE_HANDLER(GpuMsg_LoadedShader, OnLoadedShader) IPC_MESSAGE_HANDLER(GpuMsg_UpdateValueState, OnUpdateValueState) #if defined(OS_ANDROID) @@ -247,6 +255,28 @@ void GpuChannelManager::OnDestroyGpuMemoryBuffer( DestroyGpuMemoryBuffer(id, client_id); } +#if defined(OS_CHROMEOS) +void GpuChannelManager::OnCreateArcVideoAcceleratorChannel() { + if (!gpu_arc_video_service_) { + gpu_arc_video_service_.reset( + new GpuArcVideoService(shutdown_event_, io_task_runner_)); + } + + gpu_arc_video_service_->CreateChannel( + base::Bind(&GpuChannelManager::ArcVideoAcceleratorChannelCreated, + weak_factory_.GetWeakPtr())); +} + +void GpuChannelManager::ArcVideoAcceleratorChannelCreated( + const IPC::ChannelHandle& handle) { + Send(new GpuHostMsg_ArcVideoAcceleratorChannelCreated(handle)); +} + +void GpuChannelManager::OnShutdownArcVideoService() { + gpu_arc_video_service_.reset(); +} +#endif + void GpuChannelManager::OnUpdateValueState( int client_id, unsigned int target, const gpu::ValueState& state) { // Only pass updated state to the channel corresponding to the diff --git a/content/common/gpu/gpu_channel_manager.h b/content/common/gpu/gpu_channel_manager.h index ab76a65..f195a55 100644 --- a/content/common/gpu/gpu_channel_manager.h +++ b/content/common/gpu/gpu_channel_manager.h @@ -58,6 +58,9 @@ struct GPUCreateCommandBufferConfig; struct GpuMsg_EstablishChannel_Params; namespace content { +#if defined(OS_CHROMEOS) +class GpuArcVideoService; +#endif class GpuChannel; class GpuMemoryBufferFactory; class GpuWatchdog; @@ -164,6 +167,11 @@ class CONTENT_EXPORT GpuChannelManager : public IPC::Listener, void OnDestroyGpuMemoryBuffer(gfx::GpuMemoryBufferId id, int client_id, const gpu::SyncToken& sync_token); +#if defined(OS_CHROMEOS) + void OnCreateArcVideoAcceleratorChannel(); + void ArcVideoAcceleratorChannelCreated(const IPC::ChannelHandle& handle); + void OnShutdownArcVideoService(); +#endif void OnUpdateValueState(int client_id, unsigned int target, @@ -195,6 +203,9 @@ class CONTENT_EXPORT GpuChannelManager : public IPC::Listener, scoped_refptr<gpu::gles2::FramebufferCompletenessCache> framebuffer_completeness_cache_; scoped_refptr<gfx::GLSurface> default_offscreen_surface_; +#if defined(OS_CHROMEOS) + scoped_ptr<GpuArcVideoService> gpu_arc_video_service_; +#endif GpuMemoryBufferFactory* const gpu_memory_buffer_factory_; #if defined(OS_ANDROID) // Last time we know the GPU was powered on. Global for tracking across all diff --git a/content/common/gpu/gpu_messages.h b/content/common/gpu/gpu_messages.h index 24664df..cfe01a3 100644 --- a/content/common/gpu/gpu_messages.h +++ b/content/common/gpu/gpu_messages.h @@ -853,3 +853,26 @@ IPC_MESSAGE_ROUTED0(AcceleratedJpegDecoderMsg_Destroy) IPC_MESSAGE_ROUTED2(AcceleratedJpegDecoderHostMsg_DecodeAck, int32_t, /* bitstream_buffer_id */ media::JpegDecodeAccelerator::Error /* error */) + +#if defined(OS_CHROMEOS) +//------------------------------------------------------------------------------ +// Arc Video Accelerator Messages +// These messages are sent from the Browser process to GPU process. + +// Tells the GPU process to create a new channel for communication with +// ArcVideoAccelerator. The channel is returned using +// GpuHostMsg_ArcVideoAcceleratorChannelCreated message. +IPC_MESSAGE_CONTROL0(GpuMsg_CreateArcVideoAcceleratorChannel) + +// Tells the GPU process to shutdown arc video service and terminate all +// instances of ArcVideoAccelerator. +IPC_MESSAGE_CONTROL0(GpuMsg_ShutdownArcVideoService) + +//------------------------------------------------------------------------------ +// Arc Video Accelerator Host Messages +// These messages are sent from the GPU process to Browser process. + +// Response from GPU to a GpuMsg_CreateArcVideoAcceleratorChannel message. +IPC_MESSAGE_CONTROL1(GpuHostMsg_ArcVideoAcceleratorChannelCreated, + IPC::ChannelHandle /* handle to channel */) +#endif diff --git a/content/common/gpu/gpu_process_launch_causes.h b/content/common/gpu/gpu_process_launch_causes.h index 533a594..1c28076 100644 --- a/content/common/gpu/gpu_process_launch_causes.h +++ b/content/common/gpu/gpu_process_launch_causes.h @@ -23,6 +23,7 @@ enum CauseForGpuLaunch { CAUSE_FOR_GPU_LAUNCH_GPU_MEMORY_BUFFER_ALLOCATE, CAUSE_FOR_GPU_LAUNCH_JPEGDECODEACCELERATOR_INITIALIZE, CAUSE_FOR_GPU_LAUNCH_MOJO_SETUP, + CAUSE_FOR_GPU_LAUNCH_ARCVIDEOACCELERATOR, // All new values should be inserted above this point so that // existing values continue to match up with those in histograms.xml. diff --git a/content/common/gpu/media/gpu_arc_video_service.cc b/content/common/gpu/media/gpu_arc_video_service.cc new file mode 100644 index 0000000..91d3698 --- /dev/null +++ b/content/common/gpu/media/gpu_arc_video_service.cc @@ -0,0 +1,92 @@ +// 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 "content/common/gpu/media/gpu_arc_video_service.h" + +#include "base/logging.h" +#include "content/common/gpu/gpu_messages.h" +#include "ipc/ipc_listener.h" +#include "ipc/ipc_message_macros.h" +#include "ipc/ipc_sync_channel.h" + +namespace content { + +// TODO(kcwu) implement ArcVideoAccelerator::Client. +class GpuArcVideoService::AcceleratorStub : public IPC::Listener, + public IPC::Sender { + public: + // |owner| outlives AcceleratorStub. + explicit AcceleratorStub(GpuArcVideoService* owner) : owner_(owner) {} + + ~AcceleratorStub() override { + DCHECK(thread_checker_.CalledOnValidThread()); + channel_->Close(); + } + + IPC::ChannelHandle CreateChannel( + base::WaitableEvent* shutdown_event, + const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner) { + IPC::ChannelHandle handle = + IPC::Channel::GenerateVerifiedChannelID("arc-video"); + channel_ = IPC::SyncChannel::Create(handle, IPC::Channel::MODE_SERVER, this, + io_task_runner, false, shutdown_event); + base::ScopedFD client_fd = channel_->TakeClientFileDescriptor(); + DCHECK(client_fd.is_valid()); + handle.socket = base::FileDescriptor(std::move(client_fd)); + return handle; + } + + // IPC::Sender implementation: + bool Send(IPC::Message* msg) override { + DCHECK(msg); + return channel_->Send(msg); + } + + // IPC::Listener implementation: + void OnChannelError() override { + DCHECK(thread_checker_.CalledOnValidThread()); + // RemoveClient will delete |this|. + owner_->RemoveClient(this); + } + + // IPC::Listener implementation: + bool OnMessageReceived(const IPC::Message& msg) override { + DCHECK(thread_checker_.CalledOnValidThread()); + + // TODO(kcwu) Add handlers here. + return false; + } + + private: + base::ThreadChecker thread_checker_; + GpuArcVideoService* const owner_; + scoped_ptr<IPC::SyncChannel> channel_; +}; + +GpuArcVideoService::GpuArcVideoService( + base::WaitableEvent* shutdown_event, + const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner) + : shutdown_event_(shutdown_event), io_task_runner_(io_task_runner) {} + +GpuArcVideoService::~GpuArcVideoService() {} + +void GpuArcVideoService::CreateChannel(const CreateChannelCallback& callback) { + DCHECK(thread_checker_.CalledOnValidThread()); + + scoped_ptr<AcceleratorStub> stub(new AcceleratorStub(this)); + + IPC::ChannelHandle handle = + stub->CreateChannel(shutdown_event_, io_task_runner_); + accelerator_stubs_[stub.get()] = std::move(stub); + + callback.Run(handle); +} + +void GpuArcVideoService::RemoveClient(AcceleratorStub* stub) { + DCHECK(thread_checker_.CalledOnValidThread()); + + accelerator_stubs_.erase(stub); +} + +} // namespace content diff --git a/content/common/gpu/media/gpu_arc_video_service.h b/content/common/gpu/media/gpu_arc_video_service.h new file mode 100644 index 0000000..131150c --- /dev/null +++ b/content/common/gpu/media/gpu_arc_video_service.h @@ -0,0 +1,68 @@ +// 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. + +#ifndef CONTENT_COMMON_GPU_MEDIA_GPU_ARC_VIDEO_SERVICE_H_ +#define CONTENT_COMMON_GPU_MEDIA_GPU_ARC_VIDEO_SERVICE_H_ + +#include <map> + +#include "base/callback.h" +#include "base/threading/thread_checker.h" + +namespace base { +class SingleThreadTaskRunner; +class WaitableEvent; +} + +namespace IPC { +struct ChannelHandle; +} + +namespace content { + +// GpuArcVideoService manages life-cycle and IPC message translation for +// ArcVideoAccelerator. +// +// For each creation request from GpuChannelManager, GpuArcVideoService will +// create a new IPC channel. +class GpuArcVideoService { + public: + class AcceleratorStub; + using CreateChannelCallback = base::Callback<void(const IPC::ChannelHandle&)>; + + // |shutdown_event| should signal an event when this process is about to be + // shut down in order to notify our new IPC channel to terminate. + GpuArcVideoService( + base::WaitableEvent* shutdown_event, + const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner); + + // Upon deletion, all ArcVideoAccelerator will be deleted and the associated + // IPC channels are closed. + ~GpuArcVideoService(); + + // Creates a new accelerator stub. The creation result will be sent back via + // |callback|. + void CreateChannel(const CreateChannelCallback& callback); + + // Removes the reference of |stub| (and trigger deletion) from this class. + void RemoveClient(AcceleratorStub* stub); + + private: + base::ThreadChecker thread_checker_; + + // Shutdown event of GPU process. + base::WaitableEvent* shutdown_event_; + + // GPU io thread task runner. + scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; + + // Bookkeeping all accelerator stubs. + std::map<AcceleratorStub*, scoped_ptr<AcceleratorStub>> accelerator_stubs_; + + DISALLOW_COPY_AND_ASSIGN(GpuArcVideoService); +}; + +} // namespace content + +#endif // CONTENT_COMMON_GPU_MEDIA_GPU_ARC_VIDEO_SERVICE_H_ diff --git a/content/content_browser.gypi b/content/content_browser.gypi index 2e88e6f..a88623f 100644 --- a/content/content_browser.gypi +++ b/content/content_browser.gypi @@ -114,6 +114,7 @@ 'public/browser/browser_thread.h', 'public/browser/browser_thread_delegate.h', 'public/browser/browser_url_handler.h', + 'public/browser/arc_video_host_delegate.h', 'public/browser/cache_storage_context.h', 'public/browser/cache_storage_usage_info.h', 'public/browser/cert_store.h', @@ -2117,6 +2118,11 @@ '../build/linux/system.gyp:dbus', '../chromeos/chromeos.gyp:chromeos', '../chromeos/chromeos.gyp:power_manager_proto', + '../components/components.gyp:arc', + ], + 'sources': [ + 'browser/gpu/gpu_arc_video_service_host.cc', + 'browser/gpu/gpu_arc_video_service_host.h', ], 'sources!': [ 'browser/device_sensors/data_fetcher_shared_memory_default.cc', diff --git a/content/content_common.gypi b/content/content_common.gypi index 929e235..d73f628 100644 --- a/content/content_common.gypi +++ b/content/content_common.gypi @@ -876,6 +876,8 @@ ['chromeos==1', { 'sources': [ 'common/gpu/media/accelerated_video_decoder.h', + 'common/gpu/media/gpu_arc_video_service.cc', + 'common/gpu/media/gpu_arc_video_service.h', 'common/gpu/media/h264_decoder.cc', 'common/gpu/media/h264_decoder.h', 'common/gpu/media/h264_dpb.cc', diff --git a/content/public/browser/arc_video_host_delegate.h b/content/public/browser/arc_video_host_delegate.h new file mode 100644 index 0000000..08f54f8 --- /dev/null +++ b/content/public/browser/arc_video_host_delegate.h @@ -0,0 +1,21 @@ +// 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. + +#ifndef CONTENT_PUBLIC_BROWSER_ARC_VIDEO_HOST_DELEGATE_H_ +#define CONTENT_PUBLIC_BROWSER_ARC_VIDEO_HOST_DELEGATE_H_ + +#include "base/memory/scoped_ptr.h" +#include "content/common/content_export.h" + +namespace arc { +class VideoHostDelegate; +} + +namespace content { + +CONTENT_EXPORT scoped_ptr<arc::VideoHostDelegate> CreateArcVideoHostDelegate(); + +} // namespace content + +#endif // CONTENT_PUBLIC_BROWSER_ARC_VIDEO_HOST_DELEGATE_H_ diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 93280b8..6becf03a 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml @@ -66612,6 +66612,9 @@ http://cs/file:chrome/histograms.xml - but prefer this file for new entries. CAUSE_FOR_GPU_LAUNCH_JPEGDECODEACCELERATOR_INITIALIZE </int> <int value="13" label="Mojo Setup">CAUSE_FOR_GPU_LAUNCH_MOJO_SETUP</int> + <int value="14" label="Create arc video accelerator"> + CAUSE_FOR_GPU_LAUNCH_ARCVIDEOACCELERATOR + </int> </enum> <enum name="GzipEncodingFixupResult" type="int"> |