summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkcwu <kcwu@chromium.org>2016-01-11 20:51:34 -0800
committerCommit bot <commit-bot@chromium.org>2016-01-12 04:52:46 +0000
commitdaa96926c4bd58df2790c0e12fc92d858243ed0a (patch)
tree1effd67a74868aa12c3de5ef9ab4b410aa9dc474
parent483df9304bb678dd50b435a41c063a3aed96d10f (diff)
downloadchromium_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}
-rw-r--r--chrome/browser/chromeos/chrome_browser_main_chromeos.cc7
-rw-r--r--components/arc.gypi4
-rw-r--r--components/arc/BUILD.gn4
-rw-r--r--components/arc/arc_bridge_service.cc24
-rw-r--r--components/arc/arc_bridge_service.h11
-rw-r--r--components/arc/arc_service_manager.cc10
-rw-r--r--components/arc/arc_service_manager.h7
-rw-r--r--components/arc/common/arc_bridge.mojom4
-rw-r--r--components/arc/common/video.mojom15
-rw-r--r--components/arc/video/arc_video_bridge.cc52
-rw-r--r--components/arc/video/arc_video_bridge.h41
-rw-r--r--components/arc/video/video_host_delegate.h26
-rw-r--r--content/browser/BUILD.gn4
-rw-r--r--content/browser/DEPS1
-rw-r--r--content/browser/gpu/gpu_arc_video_service_host.cc76
-rw-r--r--content/browser/gpu/gpu_arc_video_service_host.h54
-rw-r--r--content/browser/gpu/gpu_process_host.cc44
-rw-r--r--content/browser/gpu/gpu_process_host.h20
-rw-r--r--content/common/BUILD.gn3
-rw-r--r--content/common/gpu/gpu_channel_manager.cc30
-rw-r--r--content/common/gpu/gpu_channel_manager.h11
-rw-r--r--content/common/gpu/gpu_messages.h23
-rw-r--r--content/common/gpu/gpu_process_launch_causes.h1
-rw-r--r--content/common/gpu/media/gpu_arc_video_service.cc92
-rw-r--r--content/common/gpu/media/gpu_arc_video_service.h68
-rw-r--r--content/content_browser.gypi6
-rw-r--r--content/content_common.gypi2
-rw-r--r--content/public/browser/arc_video_host_delegate.h21
-rw-r--r--tools/metrics/histograms/histograms.xml3
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">