| OLD | NEW |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "media/capture/video/chromeos/camera_hal_delegate.h" | 5 #include "media/capture/video/chromeos/camera_hal_delegate.h" |
| 6 | 6 |
| 7 #include <fcntl.h> | 7 #include <fcntl.h> |
| 8 #include <sys/uio.h> | 8 #include <sys/uio.h> |
| 9 | 9 |
| 10 #include <algorithm> | 10 #include <algorithm> |
| 11 #include <utility> | 11 #include <utility> |
| 12 | 12 |
| 13 #include "base/bind.h" | 13 #include "base/bind.h" |
| 14 #include "base/bind_helpers.h" | 14 #include "base/bind_helpers.h" |
| 15 #include "base/strings/string_piece.h" | 15 #include "base/strings/string_piece.h" |
| 16 #include "media/capture/video/chromeos/camera_metadata_utils.h" | 16 #include "media/capture/video/chromeos/camera_metadata_utils.h" |
| 17 #include "media/capture/video/chromeos/pixel_format_utils.h" | 17 #include "media/capture/video/chromeos/pixel_format_utils.h" |
| 18 #include "media/capture/video/chromeos/video_capture_device_arc_chromeos.h" | 18 #include "media/capture/video/chromeos/video_capture_device_arc_chromeos.h" |
| 19 #include "mojo/edk/embedder/embedder.h" | |
| 20 #include "mojo/edk/embedder/incoming_broker_client_invitation.h" | |
| 21 #include "mojo/edk/embedder/named_platform_handle.h" | |
| 22 #include "mojo/edk/embedder/named_platform_handle_utils.h" | |
| 23 #include "mojo/edk/embedder/platform_channel_pair.h" | |
| 24 #include "mojo/edk/embedder/platform_channel_utils_posix.h" | |
| 25 #include "mojo/edk/embedder/platform_handle_vector.h" | |
| 26 | 19 |
| 27 namespace media { | 20 namespace media { |
| 28 | 21 |
| 29 namespace { | 22 namespace { |
| 30 | 23 |
| 31 const base::StringPiece kArcCamera3SocketPath("/var/run/camera/camera3.sock"); | 24 const base::StringPiece kArcCamera3SocketPath("/var/run/camera/camera3.sock"); |
| 32 | 25 |
| 33 const base::TimeDelta kEventWaitTimeoutMs = | 26 const base::TimeDelta kEventWaitTimeoutMs = |
| 34 base::TimeDelta::FromMilliseconds(3000); | 27 base::TimeDelta::FromMilliseconds(3000); |
| 35 | 28 |
| 36 } // namespace | 29 } // namespace |
| 37 | 30 |
| 31 CameraHalDelegate::LocalCameraClient::LocalCameraClient( |
| 32 scoped_refptr<CameraHalDelegate> camera_hal_delegate) |
| 33 : camera_hal_delegate_(camera_hal_delegate) {} |
| 34 |
| 35 void CameraHalDelegate::LocalCameraClient::NotifyCameraHalRegistered( |
| 36 arc::mojom::CameraModulePtr camera_module) { |
| 37 camera_hal_delegate_->SetCameraModule(camera_module.PassInterface()); |
| 38 } |
| 39 |
| 38 CameraHalDelegate::CameraHalDelegate( | 40 CameraHalDelegate::CameraHalDelegate( |
| 39 scoped_refptr<base::SingleThreadTaskRunner> ipc_task_runner) | 41 scoped_refptr<base::SingleThreadTaskRunner> ipc_task_runner) |
| 40 : builtin_camera_info_updated_( | 42 : camera_module_set_(base::WaitableEvent::ResetPolicy::MANUAL, |
| 43 base::WaitableEvent::InitialState::NOT_SIGNALED), |
| 44 builtin_camera_info_updated_( |
| 41 base::WaitableEvent::ResetPolicy::MANUAL, | 45 base::WaitableEvent::ResetPolicy::MANUAL, |
| 42 base::WaitableEvent::InitialState::NOT_SIGNALED), | 46 base::WaitableEvent::InitialState::NOT_SIGNALED), |
| 43 num_builtin_cameras_(0), | 47 num_builtin_cameras_(0), |
| 44 ipc_task_runner_(std::move(ipc_task_runner)), | 48 ipc_task_runner_(std::move(ipc_task_runner)), |
| 45 camera_module_callbacks_(this) { | 49 camera_module_callbacks_(this) { |
| 46 DETACH_FROM_SEQUENCE(sequence_checker_); | 50 DETACH_FROM_SEQUENCE(sequence_checker_); |
| 47 } | 51 } |
| 48 | 52 |
| 49 CameraHalDelegate::~CameraHalDelegate() {} | 53 CameraHalDelegate::~CameraHalDelegate() {} |
| 50 | 54 |
| 51 bool CameraHalDelegate::StartCameraModuleIpc() { | 55 void CameraHalDelegate::RegisterCameraClient() { |
| 52 // Non-blocking socket handle. | 56 auto client_observer = base::MakeUnique<LocalCameraClient>(this); |
| 53 mojo::edk::ScopedPlatformHandle socket_handle = mojo::edk::CreateClientHandle( | 57 ArcCamera3Service::GetInstance()->AddClientObserver( |
| 54 mojo::edk::NamedPlatformHandle(kArcCamera3SocketPath)); | 58 std::move(client_observer)); |
| 59 } |
| 55 | 60 |
| 56 // Set socket to blocking | 61 void CameraHalDelegate::SetCameraModule( |
| 57 int flags = HANDLE_EINTR(fcntl(socket_handle.get().handle, F_GETFL)); | 62 arc::mojom::CameraModulePtrInfo camera_module_ptr_info) { |
| 58 if (flags == -1) { | |
| 59 PLOG(ERROR) << "fcntl(F_GETFL) failed: "; | |
| 60 return false; | |
| 61 } | |
| 62 if (HANDLE_EINTR(fcntl(socket_handle.get().handle, F_SETFL, | |
| 63 flags & ~O_NONBLOCK)) == -1) { | |
| 64 PLOG(ERROR) << "fcntl(F_SETFL) failed: "; | |
| 65 return false; | |
| 66 } | |
| 67 | |
| 68 const size_t kTokenSize = 32; | |
| 69 char token[kTokenSize] = {}; | |
| 70 std::deque<mojo::edk::PlatformHandle> platform_handles; | |
| 71 ssize_t ret = mojo::edk::PlatformChannelRecvmsg( | |
| 72 socket_handle.get(), token, sizeof(token), &platform_handles, true); | |
| 73 if (ret == -1) { | |
| 74 PLOG(ERROR) << "PlatformChannelRecvmsg failed: "; | |
| 75 return false; | |
| 76 } | |
| 77 if (platform_handles.size() != 1) { | |
| 78 LOG(ERROR) << "Unexpected number of handles received, expected 1: " | |
| 79 << platform_handles.size(); | |
| 80 return false; | |
| 81 } | |
| 82 mojo::edk::ScopedPlatformHandle parent_pipe(platform_handles.back()); | |
| 83 platform_handles.pop_back(); | |
| 84 if (!parent_pipe.is_valid()) { | |
| 85 LOG(ERROR) << "Invalid parent pipe"; | |
| 86 return false; | |
| 87 } | |
| 88 std::unique_ptr<mojo::edk::IncomingBrokerClientInvitation> invitation = | |
| 89 mojo::edk::IncomingBrokerClientInvitation::Accept( | |
| 90 mojo::edk::ConnectionParams(mojo::edk::TransportProtocol::kLegacy, | |
| 91 std::move(parent_pipe))); | |
| 92 mojo::ScopedMessagePipeHandle child_pipe = | |
| 93 invitation->ExtractMessagePipe(token); | |
| 94 DCHECK(child_pipe.is_valid()); | |
| 95 | |
| 96 camera_module_ = | 63 camera_module_ = |
| 97 mojo::MakeProxy(mojo::InterfacePtrInfo<arc::mojom::CameraModule>( | 64 mojo::MakeProxy(std::move(camera_module_ptr_info), ipc_task_runner_); |
| 98 std::move(child_pipe), 0u), | 65 camera_module_set_.Signal(); |
| 99 ipc_task_runner_); | 66 ipc_task_runner_->PostTask( |
| 100 | 67 FROM_HERE, |
| 101 VLOG(1) << "Camera module IPC connection established"; | 68 base::Bind(&CameraHalDelegate::SetConnectionErrorHandlerOnModuleThread, |
| 102 | 69 this)); |
| 103 return true; | |
| 104 } | 70 } |
| 105 | 71 |
| 106 void CameraHalDelegate::Reset() { | 72 void CameraHalDelegate::Reset() { |
| 107 ipc_task_runner_->PostTask( | 73 ipc_task_runner_->PostTask( |
| 108 FROM_HERE, | 74 FROM_HERE, |
| 109 base::Bind(&CameraHalDelegate::ResetMojoInterfaceOnModuleThread, this)); | 75 base::Bind(&CameraHalDelegate::ResetMojoInterfaceOnModuleThread, this)); |
| 110 } | 76 } |
| 111 | 77 |
| 112 std::unique_ptr<VideoCaptureDevice> CameraHalDelegate::CreateDevice( | 78 std::unique_ptr<VideoCaptureDevice> CameraHalDelegate::CreateDevice( |
| 113 scoped_refptr<base::SingleThreadTaskRunner> task_runner_for_screen_observer, | 79 scoped_refptr<base::SingleThreadTaskRunner> task_runner_for_screen_observer, |
| 114 const VideoCaptureDeviceDescriptor& device_descriptor) { | 80 const VideoCaptureDeviceDescriptor& device_descriptor) { |
| 115 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); | 81 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| 82 camera_module_set_.Wait(); |
| 116 std::unique_ptr<VideoCaptureDevice> capture_device; | 83 std::unique_ptr<VideoCaptureDevice> capture_device; |
| 117 if (!UpdateBuiltInCameraInfo()) { | 84 if (!UpdateBuiltInCameraInfo()) { |
| 118 return capture_device; | 85 return capture_device; |
| 119 } | 86 } |
| 120 if (camera_info_.find(device_descriptor.device_id) == camera_info_.end()) { | 87 if (camera_info_.find(device_descriptor.device_id) == camera_info_.end()) { |
| 121 LOG(ERROR) << "Invalid camera device: " << device_descriptor.device_id; | 88 LOG(ERROR) << "Invalid camera device: " << device_descriptor.device_id; |
| 122 return capture_device; | 89 return capture_device; |
| 123 } | 90 } |
| 124 capture_device.reset(new VideoCaptureDeviceArcChromeOS( | 91 capture_device.reset(new VideoCaptureDeviceArcChromeOS( |
| 125 std::move(task_runner_for_screen_observer), device_descriptor, this)); | 92 std::move(task_runner_for_screen_observer), device_descriptor, this)); |
| 126 return capture_device; | 93 return capture_device; |
| 127 } | 94 } |
| 128 | 95 |
| 129 void CameraHalDelegate::GetSupportedFormats( | 96 void CameraHalDelegate::GetSupportedFormats( |
| 130 const VideoCaptureDeviceDescriptor& device_descriptor, | 97 const VideoCaptureDeviceDescriptor& device_descriptor, |
| 131 VideoCaptureFormats* supported_formats) { | 98 VideoCaptureFormats* supported_formats) { |
| 132 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); | 99 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| 133 | 100 |
| 101 camera_module_set_.Wait(); |
| 134 if (!UpdateBuiltInCameraInfo()) { | 102 if (!UpdateBuiltInCameraInfo()) { |
| 135 return; | 103 return; |
| 136 } | 104 } |
| 137 std::string camera_id = device_descriptor.device_id; | 105 std::string camera_id = device_descriptor.device_id; |
| 138 if (camera_info_.find(camera_id) == camera_info_.end() || | 106 if (camera_info_.find(camera_id) == camera_info_.end() || |
| 139 camera_info_[camera_id].is_null()) { | 107 camera_info_[camera_id].is_null()) { |
| 140 LOG(ERROR) << "Invalid camera_id: " << camera_id; | 108 LOG(ERROR) << "Invalid camera_id: " << camera_id; |
| 141 return; | 109 return; |
| 142 } | 110 } |
| 143 const arc::mojom::CameraInfoPtr& camera_info = camera_info_[camera_id]; | 111 const arc::mojom::CameraInfoPtr& camera_info = camera_info_[camera_id]; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 180 VLOG(1) << "Supported format: " << width << "x" << height | 148 VLOG(1) << "Supported format: " << width << "x" << height |
| 181 << " fps=" << max_fps << " format=" << cr_format; | 149 << " fps=" << max_fps << " format=" << cr_format; |
| 182 supported_formats->emplace_back(gfx::Size(width, height), max_fps, | 150 supported_formats->emplace_back(gfx::Size(width, height), max_fps, |
| 183 cr_format); | 151 cr_format); |
| 184 } | 152 } |
| 185 } | 153 } |
| 186 | 154 |
| 187 void CameraHalDelegate::GetDeviceDescriptors( | 155 void CameraHalDelegate::GetDeviceDescriptors( |
| 188 VideoCaptureDeviceDescriptors* device_descriptors) { | 156 VideoCaptureDeviceDescriptors* device_descriptors) { |
| 189 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); | 157 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| 158 camera_module_set_.Wait(); |
| 190 | 159 |
| 191 if (!UpdateBuiltInCameraInfo()) { | 160 if (!UpdateBuiltInCameraInfo()) { |
| 192 return; | 161 return; |
| 193 } | 162 } |
| 194 for (size_t id = 0; id < num_builtin_cameras_; ++id) { | 163 for (size_t id = 0; id < num_builtin_cameras_; ++id) { |
| 195 VideoCaptureDeviceDescriptor desc; | 164 VideoCaptureDeviceDescriptor desc; |
| 196 std::string camera_id = std::to_string(id); | 165 std::string camera_id = std::to_string(id); |
| 197 const arc::mojom::CameraInfoPtr& camera_info = camera_info_[camera_id]; | 166 const arc::mojom::CameraInfoPtr& camera_info = camera_info_[camera_id]; |
| 198 if (!camera_info) { | 167 if (!camera_info) { |
| 199 continue; | 168 continue; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 221 } | 190 } |
| 222 // TODO(jcliang): Remove this after JS API supports query camera facing | 191 // TODO(jcliang): Remove this after JS API supports query camera facing |
| 223 // (http://crbug.com/543997). | 192 // (http://crbug.com/543997). |
| 224 std::sort(device_descriptors->begin(), device_descriptors->end()); | 193 std::sort(device_descriptors->begin(), device_descriptors->end()); |
| 225 } | 194 } |
| 226 | 195 |
| 227 void CameraHalDelegate::GetCameraInfo(int32_t camera_id, | 196 void CameraHalDelegate::GetCameraInfo(int32_t camera_id, |
| 228 const GetCameraInfoCallback& callback) { | 197 const GetCameraInfoCallback& callback) { |
| 229 // This method may be called on any thread. Currently this method is used by | 198 // This method may be called on any thread. Currently this method is used by |
| 230 // CameraDeviceDelegate to query camera info. | 199 // CameraDeviceDelegate to query camera info. |
| 200 camera_module_set_.Wait(); |
| 231 ipc_task_runner_->PostTask( | 201 ipc_task_runner_->PostTask( |
| 232 FROM_HERE, base::Bind(&CameraHalDelegate::GetCameraInfoOnModuleThread, | 202 FROM_HERE, base::Bind(&CameraHalDelegate::GetCameraInfoOnModuleThread, |
| 233 this, camera_id, callback)); | 203 this, camera_id, callback)); |
| 234 } | 204 } |
| 235 | 205 |
| 236 void CameraHalDelegate::OpenDevice( | 206 void CameraHalDelegate::OpenDevice( |
| 237 int32_t camera_id, | 207 int32_t camera_id, |
| 238 arc::mojom::Camera3DeviceOpsRequest device_ops_request, | 208 arc::mojom::Camera3DeviceOpsRequest device_ops_request, |
| 239 const OpenDeviceCallback& callback) { | 209 const OpenDeviceCallback& callback) { |
| 240 // This method may be called on any thread. Currently this method is used by | 210 // This method may be called on any thread. Currently this method is used by |
| 241 // CameraDeviceDelegate to open a camera device. | 211 // CameraDeviceDelegate to open a camera device. |
| 212 camera_module_set_.Wait(); |
| 242 ipc_task_runner_->PostTask( | 213 ipc_task_runner_->PostTask( |
| 243 FROM_HERE, | 214 FROM_HERE, |
| 244 base::Bind(&CameraHalDelegate::OpenDeviceOnModuleThread, this, camera_id, | 215 base::Bind(&CameraHalDelegate::OpenDeviceOnModuleThread, this, camera_id, |
| 245 base::Passed(&device_ops_request), callback)); | 216 base::Passed(&device_ops_request), callback)); |
| 246 } | 217 } |
| 247 | 218 |
| 248 void CameraHalDelegate::StartForTesting(arc::mojom::CameraModulePtrInfo info) { | 219 void CameraHalDelegate::SetConnectionErrorHandlerOnModuleThread() { |
| 249 camera_module_.Bind(std::move(info), ipc_task_runner_); | 220 DCHECK(ipc_task_runner_->BelongsToCurrentThread()); |
| 221 DCHECK(camera_module_set_.IsSignaled()); |
| 222 camera_module_.set_connection_error_handler(base::Bind( |
| 223 &CameraHalDelegate::HandleMojoConnectionErrorOnModuleThread, this)); |
| 224 } |
| 225 |
| 226 void CameraHalDelegate::HandleMojoConnectionErrorOnModuleThread() { |
| 227 DCHECK(ipc_task_runner_->BelongsToCurrentThread()); |
| 228 camera_module_.reset(); |
| 229 if (camera_module_callbacks_.is_bound()) { |
| 230 camera_module_callbacks_.Unbind(); |
| 231 } |
| 232 camera_module_set_.Reset(); |
| 250 } | 233 } |
| 251 | 234 |
| 252 void CameraHalDelegate::ResetMojoInterfaceOnModuleThread() { | 235 void CameraHalDelegate::ResetMojoInterfaceOnModuleThread() { |
| 253 DCHECK(ipc_task_runner_->BelongsToCurrentThread()); | 236 DCHECK(ipc_task_runner_->BelongsToCurrentThread()); |
| 254 camera_module_.reset(); | 237 camera_module_.reset(); |
| 255 if (camera_module_callbacks_.is_bound()) { | 238 if (camera_module_callbacks_.is_bound()) { |
| 256 camera_module_callbacks_.Close(); | 239 camera_module_callbacks_.Close(); |
| 257 } | 240 } |
| 258 } | 241 } |
| 259 | 242 |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 356 | 339 |
| 357 // CameraModuleCallbacks implementations. | 340 // CameraModuleCallbacks implementations. |
| 358 void CameraHalDelegate::CameraDeviceStatusChange( | 341 void CameraHalDelegate::CameraDeviceStatusChange( |
| 359 int32_t camera_id, | 342 int32_t camera_id, |
| 360 arc::mojom::CameraDeviceStatus new_status) { | 343 arc::mojom::CameraDeviceStatus new_status) { |
| 361 DCHECK(ipc_task_runner_->BelongsToCurrentThread()); | 344 DCHECK(ipc_task_runner_->BelongsToCurrentThread()); |
| 362 // TODO(jcliang): Handle status change for external cameras. | 345 // TODO(jcliang): Handle status change for external cameras. |
| 363 } | 346 } |
| 364 | 347 |
| 365 } // namespace media | 348 } // namespace media |
| OLD | NEW |