Commit e5654af3 authored by kcwu's avatar kcwu Committed by Commit bot

Implements GpuArcVideoService and its host

In the GPU process, GpuArcVideoService (arc::VideoHost) is registered
via content's gpu client hook. It also manages additional IPC channel
per accelerator and dispatches calls to ArcVideoAccelerator.

In the browser process, GpuArcVideoServiceHost listens events of
ArcBridgeService and pass to GpuArcVideoService.

BUG=b/25057601
TEST=video from arc playbacks

Review URL: https://codereview.chromium.org/1641353003

Cr-Commit-Position: refs/heads/master@{#387799}
parent a5e2d57e
...@@ -497,6 +497,7 @@ group("child_dependencies") { ...@@ -497,6 +497,7 @@ group("child_dependencies") {
public_deps += [ public_deps += [
"//chrome/browser/devtools", "//chrome/browser/devtools",
"//chrome/child", "//chrome/child",
"//chrome/gpu",
"//chrome/renderer", "//chrome/renderer",
"//chrome/utility", "//chrome/utility",
"//content/public/child", "//content/public/child",
...@@ -1014,6 +1015,7 @@ if (is_android) { ...@@ -1014,6 +1015,7 @@ if (is_android) {
"//chrome/browser/ui", "//chrome/browser/ui",
"//chrome/child", "//chrome/child",
"//chrome/common", "//chrome/common",
"//chrome/gpu",
"//chrome/renderer", "//chrome/renderer",
"//chrome/utility", "//chrome/utility",
"//components/safe_browsing_db:safe_browsing_db_mobile", "//components/safe_browsing_db:safe_browsing_db_mobile",
......
...@@ -326,6 +326,7 @@ source_set("test_support") { ...@@ -326,6 +326,7 @@ source_set("test_support") {
"//chrome/browser/policy:path_parser", "//chrome/browser/policy:path_parser",
"//chrome/child", "//chrome/child",
"//chrome/common", "//chrome/common",
"//chrome/gpu",
"//chrome/renderer", "//chrome/renderer",
"//chrome/utility", "//chrome/utility",
"//components/crash/content/app", "//components/crash/content/app",
......
...@@ -6,6 +6,7 @@ include_rules = [ ...@@ -6,6 +6,7 @@ include_rules = [
"+chrome/common/chrome_features.h", "+chrome/common/chrome_features.h",
"+chrome/grit", # For generated headers "+chrome/grit", # For generated headers
"+chrome/installer", "+chrome/installer",
"+chrome/gpu/chrome_content_gpu_client.h",
"+chrome/renderer/chrome_content_renderer_client.h", "+chrome/renderer/chrome_content_renderer_client.h",
"+chrome/utility/chrome_content_utility_client.h", "+chrome/utility/chrome_content_utility_client.h",
"+chrome_elf/chrome_elf_main.h", "+chrome_elf/chrome_elf_main.h",
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#include "chrome/common/switch_utils.h" #include "chrome/common/switch_utils.h"
#include "chrome/common/trace_event_args_whitelist.h" #include "chrome/common/trace_event_args_whitelist.h"
#include "chrome/common/url_constants.h" #include "chrome/common/url_constants.h"
#include "chrome/gpu/chrome_content_gpu_client.h"
#include "chrome/renderer/chrome_content_renderer_client.h" #include "chrome/renderer/chrome_content_renderer_client.h"
#include "chrome/utility/chrome_content_utility_client.h" #include "chrome/utility/chrome_content_utility_client.h"
#include "components/component_updater/component_updater_paths.h" #include "components/component_updater/component_updater_paths.h"
...@@ -141,6 +142,8 @@ ...@@ -141,6 +142,8 @@
#if !defined(CHROME_MULTIPLE_DLL_BROWSER) #if !defined(CHROME_MULTIPLE_DLL_BROWSER)
#include "chrome/child/pdf_child_init.h" #include "chrome/child/pdf_child_init.h"
base::LazyInstance<ChromeContentGpuClient> g_chrome_content_gpu_client =
LAZY_INSTANCE_INITIALIZER;
base::LazyInstance<ChromeContentRendererClient> base::LazyInstance<ChromeContentRendererClient>
g_chrome_content_renderer_client = LAZY_INSTANCE_INITIALIZER; g_chrome_content_renderer_client = LAZY_INSTANCE_INITIALIZER;
base::LazyInstance<ChromeContentUtilityClient> base::LazyInstance<ChromeContentUtilityClient>
...@@ -977,6 +980,14 @@ ChromeMainDelegate::CreateContentBrowserClient() { ...@@ -977,6 +980,14 @@ ChromeMainDelegate::CreateContentBrowserClient() {
#endif #endif
} }
content::ContentGpuClient* ChromeMainDelegate::CreateContentGpuClient() {
#if defined(CHROME_MULTIPLE_DLL_BROWSER)
return nullptr;
#else
return g_chrome_content_gpu_client.Pointer();
#endif
}
content::ContentRendererClient* content::ContentRendererClient*
ChromeMainDelegate::CreateContentRendererClient() { ChromeMainDelegate::CreateContentRendererClient() {
#if defined(CHROME_MULTIPLE_DLL_BROWSER) #if defined(CHROME_MULTIPLE_DLL_BROWSER)
......
...@@ -46,6 +46,7 @@ class ChromeMainDelegate : public content::ContentMainDelegate { ...@@ -46,6 +46,7 @@ class ChromeMainDelegate : public content::ContentMainDelegate {
bool ShouldEnableProfilerRecording() override; bool ShouldEnableProfilerRecording() override;
content::ContentBrowserClient* CreateContentBrowserClient() override; content::ContentBrowserClient* CreateContentBrowserClient() override;
content::ContentGpuClient* CreateContentGpuClient() override;
content::ContentRendererClient* CreateContentRendererClient() override; content::ContentRendererClient* CreateContentRendererClient() override;
content::ContentUtilityClient* CreateContentUtilityClient() override; content::ContentUtilityClient* CreateContentUtilityClient() override;
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "chrome/browser/chromeos/arc/arc_policy_bridge.h" #include "chrome/browser/chromeos/arc/arc_policy_bridge.h"
#include "chrome/browser/chromeos/arc/arc_process_service.h" #include "chrome/browser/chromeos/arc/arc_process_service.h"
#include "chrome/browser/chromeos/arc/arc_settings_service.h" #include "chrome/browser/chromeos/arc/arc_settings_service.h"
#include "chrome/browser/chromeos/arc/gpu_arc_video_service_host.h"
#include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/session_manager_client.h" #include "chromeos/dbus/session_manager_client.h"
#include "components/arc/arc_bridge_service.h" #include "components/arc/arc_bridge_service.h"
...@@ -31,8 +32,10 @@ void ArcServiceLauncher::Initialize() { ...@@ -31,8 +32,10 @@ void ArcServiceLauncher::Initialize() {
new ArcProcessService(arc_service_manager_->arc_bridge_service()))); new ArcProcessService(arc_service_manager_->arc_bridge_service())));
arc_service_manager_->AddService(base::WrapUnique( arc_service_manager_->AddService(base::WrapUnique(
new ArcSettingsService(arc_service_manager_->arc_bridge_service()))); new ArcSettingsService(arc_service_manager_->arc_bridge_service())));
arc_service_manager_->AddService(base::WrapUnique(
new GpuArcVideoServiceHost(arc_service_manager_->arc_bridge_service())));
// Detect availiability. // Detect availability.
chromeos::SessionManagerClient* session_manager_client = chromeos::SessionManagerClient* session_manager_client =
chromeos::DBusThreadManager::Get()->GetSessionManagerClient(); chromeos::DBusThreadManager::Get()->GetSessionManagerClient();
session_manager_client->CheckArcAvailability(base::Bind( session_manager_client->CheckArcAvailability(base::Bind(
......
// 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/chromeos/arc/gpu_arc_video_service_host.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/thread_task_runner_handle.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/gpu_service_registry.h"
#include "content/public/common/service_registry.h"
namespace {
mojo::InterfacePtrInfo<arc::VideoHost> GetServiceOnIOThread() {
arc::VideoHostPtr host_ptr;
content::ServiceRegistry* registry = content::GetGpuServiceRegistry();
registry->ConnectToRemoteService(mojo::GetProxy(&host_ptr));
// Unbind and reply back to UI thread.
return host_ptr.PassInterface();
}
} // namespace
namespace arc {
GpuArcVideoServiceHost::GpuArcVideoServiceHost(
arc::ArcBridgeService* bridge_service)
: ArcService(bridge_service), binding_(this), weak_factory_(this) {
arc_bridge_service()->AddObserver(this);
}
GpuArcVideoServiceHost::~GpuArcVideoServiceHost() {
DCHECK(thread_checker_.CalledOnValidThread());
arc_bridge_service()->RemoveObserver(this);
}
void GpuArcVideoServiceHost::OnVideoInstanceReady() {
DCHECK(thread_checker_.CalledOnValidThread());
auto video_instance = arc_bridge_service()->video_instance();
DCHECK(video_instance);
video_instance->Init(binding_.CreateInterfacePtrAndBind());
}
void GpuArcVideoServiceHost::OnVideoInstanceClosed() {
DCHECK(thread_checker_.CalledOnValidThread());
service_ptr_.reset();
}
void GpuArcVideoServiceHost::OnRequestArcVideoAcceleratorChannel(
const OnRequestArcVideoAcceleratorChannelCallback& callback) {
DCHECK(thread_checker_.CalledOnValidThread());
content::BrowserThread::PostTaskAndReplyWithResult(
content::BrowserThread::IO, FROM_HERE, base::Bind(&GetServiceOnIOThread),
base::Bind(&GpuArcVideoServiceHost::BindServiceAndCreateChannel,
weak_factory_.GetWeakPtr(), callback));
}
void GpuArcVideoServiceHost::BindServiceAndCreateChannel(
const OnRequestArcVideoAcceleratorChannelCallback& callback,
mojo::InterfacePtrInfo<arc::VideoHost> ptr_info) {
DCHECK(thread_checker_.CalledOnValidThread());
service_ptr_.Bind(std::move(ptr_info));
service_ptr_->OnRequestArcVideoAcceleratorChannel(callback);
}
} // namespace arc
// 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 CHROME_BROWSER_CHROMEOS_ARC_GPU_ARC_VIDEO_SERVICE_HOST_H_
#define CHROME_BROWSER_CHROMEOS_ARC_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/arc_bridge_service.h"
#include "components/arc/arc_service.h"
#include "components/arc/common/video.mojom.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/bindings/interface_ptr_info.h"
namespace arc {
// This class takes requests for creating channels of video accelerators from
// arc::VideoInstance and forwards these requests to GpuArcVideoServce. It also
// returns the created channels back to the arc::VideoInstance.
//
// This class is the proxy end of GpuArcVideoService and runs in the browser
// process. The corresponding end "GpuArcVideoService" runs in the GPU process.
class GpuArcVideoServiceHost : public arc::ArcService,
public arc::ArcBridgeService::Observer,
public arc::VideoHost {
public:
explicit GpuArcVideoServiceHost(arc::ArcBridgeService* bridge_service);
~GpuArcVideoServiceHost() override;
// arc::ArcBridgeService::Observer implementation.
void OnVideoInstanceReady() override;
void OnVideoInstanceClosed() override;
// arc::VideoHost implementation.
void OnRequestArcVideoAcceleratorChannel(
const OnRequestArcVideoAcceleratorChannelCallback& callback) override;
private:
void BindServiceAndCreateChannel(
const OnRequestArcVideoAcceleratorChannelCallback& callback,
mojo::InterfacePtrInfo<arc::VideoHost> ptr_info);
base::ThreadChecker thread_checker_;
mojo::Binding<arc::VideoHost> binding_;
arc::VideoHostPtr service_ptr_;
base::WeakPtrFactory<GpuArcVideoServiceHost> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(GpuArcVideoServiceHost);
};
} // namespace arc
#endif // CHROME_BROWSER_CHROMEOS_ARC_GPU_ARC_VIDEO_SERVICE_HOST_H_
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
], ],
'chromium_child_dependencies': [ 'chromium_child_dependencies': [
'child', 'child',
'gpu',
'renderer', 'renderer',
'utility', 'utility',
'../content/content.gyp:content_gpu', '../content/content.gyp:content_gpu',
...@@ -112,6 +113,7 @@ ...@@ -112,6 +113,7 @@
'chrome_debugger.gypi', 'chrome_debugger.gypi',
'chrome_dll.gypi', 'chrome_dll.gypi',
'chrome_exe.gypi', 'chrome_exe.gypi',
'chrome_gpu.gypi',
'chrome_installer.gypi', 'chrome_installer.gypi',
'chrome_renderer.gypi', 'chrome_renderer.gypi',
'chrome_tests.gypi', 'chrome_tests.gypi',
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
'chrome.gyp:browser', 'chrome.gyp:browser',
'chrome.gyp:browser_ui', 'chrome.gyp:browser_ui',
'chrome.gyp:child', 'chrome.gyp:child',
'chrome.gyp:gpu',
'chrome_features.gyp:chrome_common_features', 'chrome_features.gyp:chrome_common_features',
'chrome.gyp:renderer', 'chrome.gyp:renderer',
'chrome.gyp:utility', 'chrome.gyp:utility',
......
...@@ -69,6 +69,8 @@ ...@@ -69,6 +69,8 @@
'browser/chromeos/arc/arc_process_service.h', 'browser/chromeos/arc/arc_process_service.h',
'browser/chromeos/arc/arc_settings_service.cc', 'browser/chromeos/arc/arc_settings_service.cc',
'browser/chromeos/arc/arc_settings_service.h', 'browser/chromeos/arc/arc_settings_service.h',
'browser/chromeos/arc/gpu_arc_video_service_host.cc',
'browser/chromeos/arc/gpu_arc_video_service_host.h',
'browser/chromeos/arc/arc_optin_uma.cc', 'browser/chromeos/arc/arc_optin_uma.cc',
'browser/chromeos/arc/arc_optin_uma.h', 'browser/chromeos/arc/arc_optin_uma.h',
'browser/chromeos/attestation/attestation_ca_client.cc', 'browser/chromeos/attestation/attestation_ca_client.cc',
......
# 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.
{
'targets': [
{
# GN version: //chrome/gpu
'target_name': 'gpu',
'type': 'static_library',
'include_dirs': [
'..',
'<(grit_out_dir)',
],
'sources': [
'gpu/chrome_content_gpu_client.cc',
'gpu/chrome_content_gpu_client.h',
],
'conditions': [
['chromeos==1', {
'dependencies': [
'../components/components.gyp:arc_mojo_bindings',
],
'sources': [
'gpu/arc_video_accelerator.h',
'gpu/gpu_arc_video_service.cc',
'gpu/gpu_arc_video_service.h',
],
}],
],
},
],
}
...@@ -1866,6 +1866,7 @@ ...@@ -1866,6 +1866,7 @@
['OS!="ios"', { ['OS!="ios"', {
'dependencies': [ 'dependencies': [
'child', 'child',
'gpu',
'renderer', 'renderer',
'utility', 'utility',
'../content/content.gyp:content_gpu', '../content/content.gyp:content_gpu',
......
# 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.
static_library("gpu") {
deps = [
"//content/public/gpu",
]
sources = [
"chrome_content_gpu_client.cc",
"chrome_content_gpu_client.h",
]
if (is_chromeos) {
deps += [ "//components/arc:arc_bindings" ]
sources += [
"arc_video_accelerator.h",
"gpu_arc_video_service.cc",
"gpu_arc_video_service.h",
]
}
}
include_rules = [
"+components/arc/common",
"+content/public/gpu",
"+media/video",
"+media/base/video_frame.h",
"+mojo/edk/embedder",
]
piman@chromium.org
posciak@chromium.org
sievers@chromium.org
// 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 CHROME_GPU_ARC_VIDEO_ACCELERATOR_H_
#define CHROME_GPU_ARC_VIDEO_ACCELERATOR_H_
#include "base/files/scoped_file.h"
namespace chromeos {
namespace arc {
enum HalPixelFormatExtension {
// The pixel formats defined in Android but are used here. They are defined
// in "system/core/include/system/graphics.h"
HAL_PIXEL_FORMAT_YCbCr_420_888 = 0x23,
// The following formats are not defined in Android, but used in
// ArcVideoAccelerator to identify the input format.
HAL_PIXEL_FORMAT_H264 = 0x34363248,
HAL_PIXEL_FORMAT_VP8 = 0x00385056,
};
enum PortType {
PORT_INPUT = 0,
PORT_OUTPUT = 1,
PORT_COUNT = 2,
};
enum BufferFlag {
BUFFER_FLAG_EOS = 1 << 0,
};
struct BufferMetadata {
int64_t timestamp = 0; // in microseconds
uint32_t flags = 0; // Flags defined in BufferFlag.
uint32_t bytes_used = 0;
};
struct VideoFormat {
uint32_t pixel_format = 0;
uint32_t buffer_size = 0;
// Minimum number of buffers required to decode/encode the stream.
uint32_t min_num_buffers = 0;
uint32_t coded_width = 0;
uint32_t coded_height = 0;
uint32_t crop_left = 0;
uint32_t crop_width = 0;
uint32_t crop_top = 0;
uint32_t crop_height = 0;
};
// The IPC interface between Android and Chromium for video decoding and
// encoding. Input buffers are sent from Android side and get processed in
// Chromium and the output buffers are returned back to Android side.
class ArcVideoAccelerator {
public:
enum Error {
ILLEGAL_STATE = 1,
INVALID_ARGUMENT = 2,
UNREADABLE_INPUT = 3,
PLATFORM_FAILURE = 4,
};
struct Config {
enum DeviceType {
DEVICE_ENCODER = 0,
DEVICE_DECODER = 1,
};
DeviceType device_type = DEVICE_DECODER;
size_t num_input_buffers = 0;
uint32_t input_pixel_format = 0;
// TODO(owenlin): Add output_pixel_format. For now only the native pixel
// format of each VDA on Chromium is supported.
};
// The callbacks of the ArcVideoAccelerator. The user of this class should
// implement this interface.
class Client {
public:
virtual ~Client() {}
// Called when an asynchronous error happens. The errors in Initialize()
// will not be reported here, but will be indicated by a false return value
// there.
virtual void OnError(Error error) = 0;
// Called when a buffer with the specified |index| and |port| has been
// processed and is no longer used in the accelerator. For input buffers,
// the Client may fill them with new content. For output buffers, indicates
// they are ready to be consumed by the client.
virtual void OnBufferDone(PortType port,
uint32_t index,
const BufferMetadata& metadata) = 0;
// Called when the output format has changed or the output format
// becomes available at beginning of the stream after initial parsing.
virtual void OnOutputFormatChanged(const VideoFormat& format) = 0;
// Called as a completion notification for Reset().
virtual void OnResetDone() = 0;
};
// Initializes the ArcVideoAccelerator with specific configuration. This
// must be called before any other methods. This call is synchronous and
// returns true iff initialization is successful.
virtual bool Initialize(const Config& config, Client* client) = 0;
// Assigns a shared memory to be used for the accelerator at the specified
// port and index. A buffer must be successfully bound before it can be passed
// to the accelerator via UseBuffer(). Already bound buffers may be reused
// multiple times without additional bindings.
virtual void BindSharedMemory(PortType port,
uint32_t index,
base::ScopedFD ashmem_fd,
off_t offset,
size_t length) = 0;
// Assigns a buffer to be used for the accelerator at the specified
// port and index. A buffer must be successfully bound before it can be
// passed to the accelerator via UseBuffer(). Already bound buffers may be
// reused multiple times without additional bindings.
virtual void BindDmabuf(PortType port,
uint32_t index,
base::ScopedFD dmabuf_fd) = 0;
// Passes a buffer to the accelerator. For input buffer, the accelerator
// will process it. For output buffer, the accelerator will output content
// to it.
virtual void UseBuffer(PortType port,
uint32_t index,
const BufferMetadata& metadata) = 0;
// Sets the number of output buffers. When it fails, Client::OnError() will
// be called.
virtual void SetNumberOfOutputBuffers(size_t number) = 0;
// Resets the accelerator. When it is done, Client::OnResetDone() will
// be called. Afterwards, all buffers won't be accessed by the accelerator
// and there won't be more callbacks.
virtual void Reset() = 0;
virtual ~ArcVideoAccelerator() {}
};
} // namespace arc
} // namespace chromeos
#endif // CHROME_GPU_ARC_VIDEO_ACCELERATOR_H_
// 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/gpu/chrome_content_gpu_client.h"
#include "content/public/common/service_registry.h"
#if defined(OS_CHROMEOS)
#include "chrome/gpu/gpu_arc_video_service.h"
#endif
#if defined(OS_CHROMEOS)
namespace {
void CreateGpuArcVideoService(
mojo::InterfaceRequest<::arc::VideoHost> request) {
// GpuArcVideoService is strongly bound to the Mojo message pipe it
// is connected to. When that message pipe is closed, either explicitly on the
// other end (in the browser process), or by a connection error, this object
// will be destroyed.
new chromeos::arc::GpuArcVideoService(std::move(request));
}
} // namespace
#endif
ChromeContentGpuClient::ChromeContentGpuClient() {}
ChromeContentGpuClient::~ChromeContentGpuClient() {}
void ChromeContentGpuClient::RegisterMojoServices(
content::ServiceRegistry* registry) {
#if defined(OS_CHROMEOS)
registry->AddService(base::Bind(&CreateGpuArcVideoService));
#endif
}
// 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 CHROME_GPU_CHROME_CONTENT_GPU_CLIENT_H_
#define CHROME_GPU_CHROME_CONTENT_GPU_CLIENT_H_
#include "base/macros.h"
#include "content/public/gpu/content_gpu_client.h"
class ChromeContentGpuClient : public content::ContentGpuClient {
public:
ChromeContentGpuClient();
~ChromeContentGpuClient() override;
// content::ContentGpuClient implementation.
void RegisterMojoServices(content::ServiceRegistry* registry) override;
private:
DISALLOW_COPY_AND_ASSIGN(ChromeContentGpuClient);
};
#endif // CHROME_GPU_CHROME_CONTENT_GPU_CLIENT_H_
// 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/gpu/gpu_arc_video_service.h"
#include <fcntl.h>
#include <utility>
#include "base/bind.h"
#include "base/logging.h"
#include "base/thread_task_runner_handle.h"
#include "chrome/gpu/arc_video_accelerator.h"
#include "components/arc/common/video_accelerator.mojom.h"
#include "mojo/edk/embedder/embedder.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/bindings/type_converter.h"
namespace mojo {
template <>
struct TypeConverter<arc::BufferMetadataPtr, chromeos::arc::BufferMetadata> {
static arc::BufferMetadataPtr Convert(
const chromeos::arc::BufferMetadata& input) {
arc::BufferMetadataPtr result = arc::BufferMetadata::New();
result->timestamp = input.timestamp;
result->flags = input.flags;
result->bytes_used = input.bytes_used;
return result;
}
};
template <>
struct TypeConverter<chromeos::arc::BufferMetadata, arc::BufferMetadataPtr> {
static chromeos::arc::BufferMetadata Convert(
const arc::BufferMetadataPtr& input) {
chromeos::arc::BufferMetadata result;
result.timestamp = input->timestamp;
result.flags = input->flags;
result.bytes_used = input->bytes_used;
return result;
}
};
template <>
struct TypeConverter<arc::VideoFormatPtr, chromeos::arc::VideoFormat> {
static arc::VideoFormatPtr Convert(const chromeos::arc::VideoFormat& input) {
arc::VideoFormatPtr result = arc::VideoFormat::New();
result->pixel_format = input.pixel_format;
result->buffer_size = input.buffer_size;
result->min_num_buffers = input.min_num_buffers;
result->coded_width = input.coded_width;
result->coded_height = input.coded_height;
result->crop_left = input.crop_left;
result->crop_width = input.crop_width;
result->crop_top = input.crop_top;
result->crop_height = input.crop_height;
return result;
}
};
template <>
struct TypeConverter<chromeos::arc::ArcVideoAccelerator::Config,
arc::ArcVideoAcceleratorConfigPtr> {
static chromeos::arc::ArcVideoAccelerator::Config Convert(
const arc::ArcVideoAcceleratorConfigPtr& input) {
chromeos::arc::ArcVideoAccelerator::Config result;
result.device_type =
static_cast<chromeos::arc::ArcVideoAccelerator::Config::DeviceType>(
input->device_type);
result.num_input_buffers = input->num_input_buffers;
result.input_pixel_format = input->input_pixel_format;
return result;
}
};
} // namespace mojo
namespace chromeos {
namespace arc {
class GpuArcVideoService::AcceleratorStub
: public ::arc::VideoAcceleratorService,
public ArcVideoAccelerator::Client {
public:
// |owner| outlives AcceleratorStub.
explicit AcceleratorStub(GpuArcVideoService* owner)
: owner_(owner), binding_(this) {}
~AcceleratorStub() override { DCHECK(thread_checker_.CalledOnValidThread()); }
bool Connect(const std::string& token) {
DVLOG(2) << "Connect";
mojo::ScopedMessagePipeHandle server_pipe =
mojo::edk::CreateParentMessagePipe(token);
if (!server_pipe.is_valid()) {
LOG(ERROR) << "Invalid pipe";
return false;
}
client_.Bind(mojo::InterfacePtrInfo<::arc::VideoAcceleratorServiceClient>(
std::move(server_pipe), 0u));
// base::Unretained is safe because we own |client_|
client_.set_connection_error_handler(
base::Bind(&GpuArcVideoService::AcceleratorStub::OnConnectionError,
base::Unretained(this)));
// TODO(kcwu): create ArcGpuVideoDecodeAccelerator here.
// accelerator_.reset(new ArcGpuVideoDecodeAccelerator());
::arc::VideoAcceleratorServicePtr service;
binding_.Bind(GetProxy(&service));
// base::Unretained is safe because we own |binding_|
binding_.set_connection_error_handler(
base::Bind(&GpuArcVideoService::AcceleratorStub::OnConnectionError,
base::Unretained(this)));
client_->Init(std::move(service));
return true;
}
void OnConnectionError() {
DVLOG(2) << "OnConnectionError";
owner_->RemoveClient(this);
// |this| is deleted.
}
// ArcVideoAccelerator::Client implementation:
void OnError(ArcVideoAccelerator::Error error) override {
DVLOG(2) << "OnError " << error;
client_->OnError(
static_cast<::arc::VideoAcceleratorServiceClient::Error>(error));
}
void OnBufferDone(PortType port,
uint32_t index,
const BufferMetadata& metadata) override {
DVLOG(2) << "OnBufferDone " << port << "," << index;
client_->OnBufferDone(static_cast<::arc::PortType>(port), index,
::arc::BufferMetadata::From(metadata));
}
void OnResetDone() override {
DVLOG(2) << "OnResetDone";
client_->OnResetDone();
}
void OnOutputFormatChanged(const VideoFormat& format) override {
DVLOG(2) << "OnOutputFormatChanged";
client_->OnOutputFormatChanged(::arc::VideoFormat::From(format));
}
// ::arc::VideoAcceleratorService impementation.
void Initialize(::arc::ArcVideoAcceleratorConfigPtr config,
const InitializeCallback& callback) override {
DVLOG(2) << "Initialize";
bool result = accelerator_->Initialize(
config.To<ArcVideoAccelerator::Config>(), this);
callback.Run(result);
}
void BindSharedMemory(::arc::PortType port,
uint32_t index,
mojo::ScopedHandle ashmem_handle,
uint32_t offset,
uint32_t length) override {
DVLOG(2) << "BindSharedMemoryCallback port=" << port << ", index=" << index
<< ", offset=" << offset << ", length=" << length;
// TODO(kcwu) make sure do we need special care for invalid handle?
mojo::edk::ScopedPlatformHandle scoped_platform_handle;
MojoResult mojo_result = mojo::edk::PassWrappedPlatformHandle(
ashmem_handle.release().value(), &scoped_platform_handle);
DCHECK_EQ(mojo_result, MOJO_RESULT_OK);
auto fd = base::ScopedFD(scoped_platform_handle.release().handle);
accelerator_->BindSharedMemory(static_cast<PortType>(port), index,
std::move(fd), offset, length);
}
void BindDmabuf(::arc::PortType port,
uint32_t index,
mojo::ScopedHandle dmabuf_handle) override {
DVLOG(2) << "BindDmabuf port=" << port << ", index=" << index;
mojo::edk::ScopedPlatformHandle scoped_platform_handle;
MojoResult mojo_result = mojo::edk::PassWrappedPlatformHandle(
dmabuf_handle.release().value(), &scoped_platform_handle);
DCHECK_EQ(mojo_result, MOJO_RESULT_OK);
auto fd = base::ScopedFD(scoped_platform_handle.release().handle);
accelerator_->BindDmabuf(static_cast<PortType>(port), index, std::move(fd));
}
void UseBuffer(::arc::PortType port,
uint32_t index,
::arc::BufferMetadataPtr metadata) override {
DVLOG(2) << "UseBuffer port=" << port << ", index=" << index;
accelerator_->UseBuffer(static_cast<PortType>(port), index,
metadata.To<BufferMetadata>());
}
void SetNumberOfOutputBuffers(uint32_t number) override {
DVLOG(2) << "SetNumberOfOutputBuffers number=" << number;
accelerator_->SetNumberOfOutputBuffers(number);
}
void Reset() override { accelerator_->Reset(); }
private:
base::ThreadChecker thread_checker_;
GpuArcVideoService* const owner_;
std::unique_ptr<ArcVideoAccelerator> accelerator_;
::arc::VideoAcceleratorServiceClientPtr client_;
mojo::Binding<::arc::VideoAcceleratorService> binding_;
};
GpuArcVideoService::GpuArcVideoService(
mojo::InterfaceRequest<::arc::VideoHost> request)
: binding_(this, std::move(request)) {}
GpuArcVideoService::~GpuArcVideoService() {}
void GpuArcVideoService::OnRequestArcVideoAcceleratorChannel(
const OnRequestArcVideoAcceleratorChannelCallback& callback) {
DVLOG(1) << "OnRequestArcVideoAcceleratorChannelCallback";
// Hardcode pid 0 since it is unused in mojo.
const base::ProcessHandle kUnusedChildProcessHandle = 0;
mojo::edk::ScopedPlatformHandle child_handle =
mojo::edk::ChildProcessLaunched(kUnusedChildProcessHandle);
MojoHandle wrapped_handle;
MojoResult wrap_result = mojo::edk::CreatePlatformHandleWrapper(
std::move(child_handle), &wrapped_handle);
if (wrap_result != MOJO_RESULT_OK) {
LOG(WARNING) << "Pipe failed to wrap handles. Closing: " << wrap_result;
callback.Run(mojo::ScopedHandle(), std::string());
return;
}
std::unique_ptr<AcceleratorStub> stub(new AcceleratorStub(this));
std::string token = mojo::edk::GenerateRandomToken();
if (!stub->Connect(token)) {
callback.Run(mojo::ScopedHandle(), std::string());
return;
}
accelerator_stubs_.insert(std::make_pair(stub.get(), std::move(stub)));
callback.Run(mojo::ScopedHandle(mojo::Handle(wrapped_handle)), token);
}
void GpuArcVideoService::RemoveClient(AcceleratorStub* stub) {
accelerator_stubs_.erase(stub);
}
} // namespace arc
} // namespace chromeos
// 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 CHROME_GPU_GPU_ARC_VIDEO_SERVICE_H_
#define CHROME_GPU_GPU_ARC_VIDEO_SERVICE_H_
#include <map>
#include <memory>
#include "base/macros.h"
#include "components/arc/common/video.mojom.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
namespace chromeos {
namespace arc {
// GpuArcVideoService manages life-cycle and IPC message translation for
// ArcVideoAccelerator.
//
// For each creation request from GpuArcVideoServiceHost, GpuArcVideoService
// will create a new IPC channel.
class GpuArcVideoService : public ::arc::VideoHost {
public:
class AcceleratorStub;
// |request| is mojo interface request of arc::VideoHost.
explicit GpuArcVideoService(mojo::InterfaceRequest<::arc::VideoHost> request);
// Upon deletion, all ArcVideoAccelerator will be deleted and the associated
// IPC channels are closed.
~GpuArcVideoService() override;
// Removes the reference of |stub| (and trigger deletion) from this class.
void RemoveClient(AcceleratorStub* stub);
private:
// arc::VideoHost implementation.
void OnRequestArcVideoAcceleratorChannel(
const OnRequestArcVideoAcceleratorChannelCallback& callback) override;
base::ThreadChecker thread_checker_;
// Binding of arc::VideoHost. It also takes ownership of |this|.
mojo::StrongBinding<::arc::VideoHost> binding_;
// Bookkeeping all accelerator stubs.
std::map<AcceleratorStub*, std::unique_ptr<AcceleratorStub>>
accelerator_stubs_;
DISALLOW_COPY_AND_ASSIGN(GpuArcVideoService);
};
} // namespace arc
} // namespace chromeos
#endif // CHROME_GPU_GPU_ARC_VIDEO_SERVICE_H_
...@@ -119,6 +119,7 @@ ...@@ -119,6 +119,7 @@
'arc/common/power.mojom', 'arc/common/power.mojom',
'arc/common/process.mojom', 'arc/common/process.mojom',
'arc/common/video.mojom', 'arc/common/video.mojom',
'arc/common/video_accelerator.mojom',
], ],
}, },
{ {
......
...@@ -96,6 +96,7 @@ mojom("arc_bindings") { ...@@ -96,6 +96,7 @@ mojom("arc_bindings") {
"common/power.mojom", "common/power.mojom",
"common/process.mojom", "common/process.mojom",
"common/video.mojom", "common/video.mojom",
"common/video_accelerator.mojom",
] ]
} }
......
...@@ -34,16 +34,6 @@ namespace arc { ...@@ -34,16 +34,6 @@ namespace arc {
namespace { namespace {
// We do not know the PID of ARC, since Chrome does not create it directly.
// Since Mojo in POSIX does not use the child PID except as an unique
// identifier for the routing table, rather than doing a lot of plumbing in the
// whole system to get the correct PID, just use an arbitrary number that will
// never be used by a legitimate process. Chrome OS assigns unassigned PIDs
// sequentially until it reaches a certain maximum value (Chrome OS uses the
// default value of 32k), at which point it loops around to zero. An arbitrary
// number larger than the maximum should be safe.
const pid_t kArcPid = 0x3DE0EA7C;
const base::FilePath::CharType kArcBridgeSocketPath[] = const base::FilePath::CharType kArcBridgeSocketPath[] =
FILE_PATH_LITERAL("/var/run/chrome/arc_bridge.sock"); FILE_PATH_LITERAL("/var/run/chrome/arc_bridge.sock");
...@@ -260,8 +250,10 @@ base::ScopedFD ArcBridgeBootstrapImpl::AcceptInstanceConnection( ...@@ -260,8 +250,10 @@ base::ScopedFD ArcBridgeBootstrapImpl::AcceptInstanceConnection(
} }
base::ScopedFD scoped_fd(raw_fd); base::ScopedFD scoped_fd(raw_fd);
// Hardcode pid 0 since it is unused in mojo.
const base::ProcessHandle kUnusedChildProcessHandle = 0;
mojo::edk::ScopedPlatformHandle child_handle = mojo::edk::ScopedPlatformHandle child_handle =
mojo::edk::ChildProcessLaunched(kArcPid); mojo::edk::ChildProcessLaunched(kUnusedChildProcessHandle);
mojo::edk::ScopedPlatformHandleVectorPtr handles( mojo::edk::ScopedPlatformHandleVectorPtr handles(
new mojo::edk::PlatformHandleVector{child_handle.release()}); new mojo::edk::PlatformHandleVector{child_handle.release()});
......
...@@ -5,8 +5,12 @@ ...@@ -5,8 +5,12 @@
module arc; module arc;
interface VideoHost { interface VideoHost {
// Notifies Chrome a request for ipc channel of video acceleration. // Requests an ipc channel from Chrome to be used in the video accelerator.
OnRequestArcVideoAcceleratorChannel() => (handle channel_handle); // Replies with |channel_handle| of mojo initial message pipe and |token| for
// creating the client end of VideoAcceleratorService message pipe.
// Replys invalid handle and empty token if any failure.
OnRequestArcVideoAcceleratorChannel() => (handle channel_handle,
string token);
}; };
interface VideoInstance { interface VideoInstance {
......
// 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.
// This file defined the mojo interface between Android and Chromium for video
// decoding and encoding. See comments of ArcVideoAccelerator for more info.
module arc;
[Extensible]
enum HalPixelFormatExtension {
HAL_PIXEL_FORMAT_YCbCr_420_888 = 0x23,
HAL_PIXEL_FORMAT_H264 = 0x34363248,
HAL_PIXEL_FORMAT_VP8 = 0x00385056,
};
enum PortType {
PORT_INPUT = 0,
PORT_OUTPUT = 1,
};
[Extensible]
enum BufferFlag {
BUFFER_FLAG_EOS = 1,
};
struct BufferMetadata {
int64 timestamp; // in microseconds
uint32 flags;
uint32 bytes_used;
};
struct VideoFormat {
uint32 pixel_format;
uint32 buffer_size;
// minimal number of buffers required to process the video.
uint32 min_num_buffers;
uint32 coded_width;
uint32 coded_height;
uint32 crop_left;
uint32 crop_width;
uint32 crop_top;
uint32 crop_height;
};
struct ArcVideoAcceleratorConfig {
enum DeviceType {
DEVICE_ENCODER = 0,
DEVICE_DECODER = 1,
};
DeviceType device_type;
uint32 num_input_buffers;
uint32 input_pixel_format;
};
interface VideoAcceleratorService {
Initialize@0(ArcVideoAcceleratorConfig config) => (bool result);
BindSharedMemory@1(PortType port, uint32 index, handle ashmem_fd,
uint32 offset, uint32 length);
BindDmabuf@2(PortType port, uint32 index, handle dmabuf_fd);
UseBuffer@3(PortType port, uint32 index, BufferMetadata metadata);
SetNumberOfOutputBuffers@4(uint32 number);
Reset@5();
};
interface VideoAcceleratorServiceClient {
enum Error {
NO_ERROR = 0,
ILLEGAL_STATE = 1,
INVALID_ARGUMENT = 2,
UNREADABLE_INPUT = 3,
PLATFORM_FAILURE = 4,
};
Init@0(VideoAcceleratorService service_ptr);
OnError@1(Error error);
OnBufferDone@2(PortType port, uint32 index, BufferMetadata metadata);
OnResetDone@3();
OnOutputFormatChanged@4(VideoFormat format);
};
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment