Skip to content

Commit

Permalink
Get the name of external cameras from vendor tags.
Browse files Browse the repository at this point in the history
If the information is available in the vendor tags, we will
1. set the display name to the webcam model name instead "External Camera".
2. set the model id to USB "vendor_id:product_id".

Bug: b:131142270, chromium:939996, b:117816888, b:80502887
Test: With CL:1583571 and CL:1583572,
  1. check the model name is shown on
     https://webrtc.github.io/samples/src/content/devices/input-output/
  2. check IPEVO Presenter works with the IPEVO document camera.

  Without that two CLs, check the name is falled back to
  "External Camera" as expected.

  Passes capture_unittests.

Change-Id: I469327b1b224689ebb698278505aee68a2fb88a6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1594388
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
Reviewed-by: Ricky Liang <jcliang@chromium.org>
Reviewed-by: Dan Sanders <sandersd@chromium.org>
Commit-Queue: Shik Chen <shik@chromium.org>
Auto-Submit: Shik Chen <shik@chromium.org>
Cr-Commit-Position: refs/heads/master@{#659423}
  • Loading branch information
Shik Chen authored and Commit Bot committed May 14, 2019
1 parent ec406c2 commit 78ec89e
Show file tree
Hide file tree
Showing 13 changed files with 491 additions and 11 deletions.
4 changes: 4 additions & 0 deletions media/capture/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,8 @@ jumbo_component("capture_lib") {
"video/chromeos/scoped_video_capture_jpeg_decoder.h",
"video/chromeos/stream_buffer_manager.cc",
"video/chromeos/stream_buffer_manager.h",
"video/chromeos/vendor_tag_ops_delegate.cc",
"video/chromeos/vendor_tag_ops_delegate.h",
"video/chromeos/video_capture_device_chromeos_halv3.cc",
"video/chromeos/video_capture_device_chromeos_halv3.h",
"video/chromeos/video_capture_device_factory_chromeos.cc",
Expand Down Expand Up @@ -403,6 +405,8 @@ test("capture_unittests") {
"video/chromeos/local_gpu_memory_buffer_manager.cc",
"video/chromeos/mock_camera_module.cc",
"video/chromeos/mock_camera_module.h",
"video/chromeos/mock_vendor_tag_ops.cc",
"video/chromeos/mock_vendor_tag_ops.h",
"video/chromeos/mock_video_capture_client.cc",
"video/chromeos/mock_video_capture_client.h",
"video/chromeos/request_manager_unittest.cc",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,7 @@ class CameraDeviceDelegateTest : public ::testing::Test {
}

protected:
base::test::ScopedTaskEnvironment scoped_task_environment_;
scoped_refptr<CameraHalDelegate> camera_hal_delegate_;
std::unique_ptr<CameraDeviceDelegate> camera_device_delegate_;

Expand All @@ -445,7 +446,6 @@ class CameraDeviceDelegateTest : public ::testing::Test {
size_t num_streams_;

private:
base::test::ScopedTaskEnvironment scoped_task_environment_;
base::Thread hal_delegate_thread_;
std::unique_ptr<base::RunLoop> run_loop_;
DISALLOW_COPY_AND_ASSIGN(CameraDeviceDelegateTest);
Expand Down
38 changes: 35 additions & 3 deletions media/capture/video/chromeos/camera_hal_delegate.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "base/bind_helpers.h"
#include "base/posix/safe_strerror.h"
#include "base/process/launch.h"
#include "base/strings/strcat.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_split.h"
#include "base/system/system_monitor.h"
Expand Down Expand Up @@ -99,7 +100,8 @@ CameraHalDelegate::CameraHalDelegate(
num_builtin_cameras_(0),
camera_buffer_factory_(new CameraBufferFactory()),
ipc_task_runner_(std::move(ipc_task_runner)),
camera_module_callbacks_(this) {
camera_module_callbacks_(this),
vendor_tag_ops_delegate_(ipc_task_runner_) {
DETACH_FROM_SEQUENCE(sequence_checker_);
}

Expand Down Expand Up @@ -248,12 +250,32 @@ void CameraHalDelegate::GetDeviceDescriptors(
desc.facing = VideoFacingMode::MEDIA_VIDEO_FACING_USER;
desc.set_display_name("Front Camera");
break;
case cros::mojom::CameraFacing::CAMERA_FACING_EXTERNAL:
case cros::mojom::CameraFacing::CAMERA_FACING_EXTERNAL: {
desc.facing = VideoFacingMode::MEDIA_VIDEO_FACING_NONE;
desc.set_display_name("External Camera");

auto get_vendor_string = [&](const std::string& key) -> const char* {
const VendorTagInfo* info =
vendor_tag_ops_delegate_.GetInfoByName(key);
if (info == nullptr) {
return nullptr;
}
auto val = GetMetadataEntryAsSpan<char>(
camera_info->static_camera_characteristics, info->tag);
return val.empty() ? nullptr : val.data();
};

auto* name = get_vendor_string("com.google.usb.modelName");
desc.set_display_name(name != nullptr ? name : "External Camera");

auto* vid = get_vendor_string("com.google.usb.vendorId");
auto* pid = get_vendor_string("com.google.usb.productId");
if (vid != nullptr && pid != nullptr) {
desc.model_id = base::StrCat({vid, ":", pid});
}
break;
// Mojo validates the input parameters for us so we don't need to worry
// about malformed values.
}
}
device_descriptors->push_back(desc);
}
Expand Down Expand Up @@ -309,6 +331,7 @@ void CameraHalDelegate::ResetMojoInterfaceOnIpcThread() {
if (camera_module_callbacks_.is_bound()) {
camera_module_callbacks_.Close();
}
vendor_tag_ops_delegate_.Reset();
builtin_camera_info_updated_.Reset();
camera_module_has_been_set_.Reset();
has_camera_connected_.Reset();
Expand Down Expand Up @@ -365,6 +388,10 @@ void CameraHalDelegate::OnGotNumberOfCamerasOnIpcThread(int32_t num_cameras) {
camera_module_->SetCallbacks(
std::move(camera_module_callbacks_ptr),
base::BindOnce(&CameraHalDelegate::OnSetCallbacksOnIpcThread, this));

camera_module_->GetVendorTagOps(
vendor_tag_ops_delegate_.MakeRequest(),
base::BindOnce(&CameraHalDelegate::OnGotVendorTagOpsOnIpcThread, this));
}

void CameraHalDelegate::OnSetCallbacksOnIpcThread(int32_t result) {
Expand All @@ -390,6 +417,11 @@ void CameraHalDelegate::OnSetCallbacksOnIpcThread(int32_t result) {
}
}

void CameraHalDelegate::OnGotVendorTagOpsOnIpcThread() {
DCHECK(ipc_task_runner_->BelongsToCurrentThread());
vendor_tag_ops_delegate_.Initialize();
}

void CameraHalDelegate::GetCameraInfoOnIpcThread(
int32_t camera_id,
GetCameraInfoCallback callback) {
Expand Down
14 changes: 13 additions & 1 deletion media/capture/video/chromeos/camera_hal_delegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "base/threading/thread.h"
#include "media/capture/video/chromeos/mojo/camera3.mojom.h"
#include "media/capture/video/chromeos/mojo/camera_common.mojom.h"
#include "media/capture/video/chromeos/vendor_tag_ops_delegate.h"
#include "media/capture/video/video_capture_device_factory.h"
#include "media/capture/video_capture_types.h"
#include "mojo/public/cpp/bindings/binding.h"
Expand Down Expand Up @@ -47,7 +48,7 @@ class CAPTURE_EXPORT CameraHalDelegate final

void SetCameraModule(cros::mojom::CameraModulePtrInfo camera_module_ptr_info);

// Resets |camera_module_| and |camera_module_callbacks_|.
// Resets various mojo bindings, WaitableEvents, and cached information.
void Reset();

// Delegation methods for the VideoCaptureDeviceFactory interface. These
Expand Down Expand Up @@ -94,13 +95,20 @@ class CAPTURE_EXPORT CameraHalDelegate final
// GetDeviceDescriptors.
bool UpdateBuiltInCameraInfo();
void UpdateBuiltInCameraInfoOnIpcThread();

// Callback for GetNumberOfCameras Mojo IPC function. GetNumberOfCameras
// returns the number of built-in cameras on the device.
void OnGotNumberOfCamerasOnIpcThread(int32_t num_cameras);

// Callback for SetCallbacks Mojo IPC function. SetCallbacks is called after
// GetNumberOfCameras is called for the first time, and before any other calls
// to |camera_module_|.
void OnSetCallbacksOnIpcThread(int32_t result);

// Callback for GetVendorTagOps Mojo IPC function, which will initialize the
// |vendor_tag_ops_delegate_|.
void OnGotVendorTagOpsOnIpcThread();

void GetCameraInfoOnIpcThread(int32_t camera_id,
GetCameraInfoCallback callback);
void OnGotCameraInfoOnIpcThread(int32_t camera_id,
Expand Down Expand Up @@ -163,6 +171,10 @@ class CAPTURE_EXPORT CameraHalDelegate final
// |ipc_task_runner_|.
mojo::Binding<cros::mojom::CameraModuleCallbacks> camera_module_callbacks_;

// An internal delegate to handle VendorTagOps mojo connection and query
// information of vendor tags. Bound to |ipc_task_runner_|.
VendorTagOpsDelegate vendor_tag_ops_delegate_;

DISALLOW_COPY_AND_ASSIGN(CameraHalDelegate);
};

Expand Down
48 changes: 44 additions & 4 deletions media/capture/video/chromeos/camera_hal_delegate_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@

#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/test/scoped_task_environment.h"
#include "media/capture/video/chromeos/mock_camera_module.h"
#include "media/capture/video/chromeos/mock_vendor_tag_ops.h"
#include "media/capture/video/chromeos/video_capture_device_factory_chromeos.h"
#include "media/capture/video/mock_gpu_memory_buffer_manager.h"
#include "testing/gmock/include/gmock/gmock.h"
Expand All @@ -21,14 +23,13 @@
using testing::_;
using testing::A;
using testing::Invoke;
using testing::Return;

namespace media {

class CameraHalDelegateTest : public ::testing::Test {
public:
CameraHalDelegateTest()
: message_loop_(new base::MessageLoop),
hal_delegate_thread_("HalDelegateThread") {}
CameraHalDelegateTest() : hal_delegate_thread_("HalDelegateThread") {}

void SetUp() override {
VideoCaptureDeviceFactoryChromeOS::SetGpuBufferManager(
Expand All @@ -51,12 +52,13 @@ class CameraHalDelegateTest : public ::testing::Test {
}

protected:
base::test::ScopedTaskEnvironment scoped_task_environment_;
scoped_refptr<CameraHalDelegate> camera_hal_delegate_;
testing::StrictMock<unittest_internal::MockCameraModule> mock_camera_module_;
testing::StrictMock<unittest_internal::MockVendorTagOps> mock_vendor_tag_ops_;
unittest_internal::MockGpuMemoryBufferManager mock_gpu_memory_buffer_manager_;

private:
std::unique_ptr<base::MessageLoop> message_loop_;
base::Thread hal_delegate_thread_;
std::unique_ptr<base::RunLoop> run_loop_;
DISALLOW_COPY_AND_ASSIGN(CameraHalDelegateTest);
Expand Down Expand Up @@ -118,6 +120,12 @@ TEST_F(CameraHalDelegateTest, GetBuiltinCameraInfo) {
std::move(cb).Run(0, std::move(camera_info));
};

auto get_vendor_tag_ops_cb =
[&](cros::mojom::VendorTagOpsRequest& vendor_tag_ops_request,
cros::mojom::CameraModule::GetVendorTagOpsCallback& cb) {
mock_vendor_tag_ops_.Bind(std::move(vendor_tag_ops_request));
};

EXPECT_CALL(mock_camera_module_, DoGetNumberOfCameras(_))
.Times(1)
.WillOnce(Invoke(get_number_of_cameras_cb));
Expand All @@ -126,6 +134,12 @@ TEST_F(CameraHalDelegateTest, GetBuiltinCameraInfo) {
DoSetCallbacks(A<cros::mojom::CameraModuleCallbacksPtr&>(),
A<cros::mojom::CameraModule::SetCallbacksCallback&>()))
.Times(1);
EXPECT_CALL(mock_camera_module_,
DoGetVendorTagOps(
A<cros::mojom::VendorTagOpsRequest&>(),
A<cros::mojom::CameraModule::GetVendorTagOpsCallback&>()))
.Times(1)
.WillOnce(Invoke(get_vendor_tag_ops_cb));
EXPECT_CALL(mock_camera_module_,
DoGetCameraInfo(
0, A<cros::mojom::CameraModule::GetCameraInfoCallback&>()))
Expand All @@ -137,6 +151,29 @@ TEST_F(CameraHalDelegateTest, GetBuiltinCameraInfo) {
.Times(1)
.WillOnce(Invoke(get_camera_info_cb));

EXPECT_CALL(mock_vendor_tag_ops_, DoGetTagCount())
.Times(1)
.WillOnce(Return(1));

const uint32_t kFakeTag = 0x80000000;

EXPECT_CALL(mock_vendor_tag_ops_, DoGetAllTags())
.Times(1)
.WillOnce(Return(std::vector<uint32_t>{kFakeTag}));

EXPECT_CALL(mock_vendor_tag_ops_, DoGetSectionName(kFakeTag))
.Times(1)
.WillOnce(Return("com.google"));

EXPECT_CALL(mock_vendor_tag_ops_, DoGetTagName(kFakeTag))
.Times(1)
.WillOnce(Return("fake.foo.bar"));

EXPECT_CALL(mock_vendor_tag_ops_, DoGetTagType(kFakeTag))
.Times(1)
.WillOnce(
Return(static_cast<int32_t>(cros::mojom::EntryType::TYPE_BYTE)));

VideoCaptureDeviceDescriptors descriptors;
camera_hal_delegate_->GetDeviceDescriptors(&descriptors);

Expand All @@ -148,6 +185,9 @@ TEST_F(CameraHalDelegateTest, GetBuiltinCameraInfo) {
ASSERT_EQ(VideoFacingMode::MEDIA_VIDEO_FACING_ENVIRONMENT,
descriptors[1].facing);

// TODO(shik): Test external camera. Check the fields |display_name| and
// |model_id| are set properly according to the vendor tags.

EXPECT_CALL(mock_gpu_memory_buffer_manager_,
CreateGpuMemoryBuffer(_, gfx::BufferFormat::YUV_420_BIPLANAR,
gfx::BufferUsage::SCANOUT_CAMERA_READ_WRITE,
Expand Down
7 changes: 7 additions & 0 deletions media/capture/video/chromeos/mock_camera_module.cc
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,13 @@ void MockCameraModule::SetTorchMode(int32_t camera_id,
std::move(callback).Run(0);
}

void MockCameraModule::GetVendorTagOps(
cros::mojom::VendorTagOpsRequest vendor_tag_ops_request,
GetVendorTagOpsCallback callback) {
DoGetVendorTagOps(vendor_tag_ops_request, callback);
std::move(callback).Run();
}

cros::mojom::CameraModulePtrInfo MockCameraModule::GetInterfacePtrInfo() {
base::WaitableEvent done(base::WaitableEvent::ResetPolicy::MANUAL,
base::WaitableEvent::InitialState::NOT_SIGNALED);
Expand Down
6 changes: 6 additions & 0 deletions media/capture/video/chromeos/mock_camera_module.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ class MockCameraModule : public cros::mojom::CameraModule {
bool enabled,
SetTorchModeCallback& callback));

void GetVendorTagOps(cros::mojom::VendorTagOpsRequest vendor_tag_ops_request,
GetVendorTagOpsCallback callback) override;
MOCK_METHOD2(DoGetVendorTagOps,
void(cros::mojom::VendorTagOpsRequest& vendor_tag_ops_request,
GetVendorTagOpsCallback& callback));

cros::mojom::CameraModulePtrInfo GetInterfacePtrInfo();

private:
Expand Down
67 changes: 67 additions & 0 deletions media/capture/video/chromeos/mock_vendor_tag_ops.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Copyright 2019 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 "media/capture/video/chromeos/mock_vendor_tag_ops.h"

#include "base/bind.h"
#include "base/logging.h"
#include "base/synchronization/waitable_event.h"

namespace media {
namespace unittest_internal {

MockVendorTagOps::MockVendorTagOps()
: mock_vendor_tag_ops_thread_("MockVendorTagOpsThread"), binding_(this) {
CHECK(mock_vendor_tag_ops_thread_.Start());
}

MockVendorTagOps::~MockVendorTagOps() {
mock_vendor_tag_ops_thread_.task_runner()->PostTask(
FROM_HERE, base::BindOnce(&MockVendorTagOps::CloseBindingOnThread,
base::Unretained(this)));
mock_vendor_tag_ops_thread_.Stop();
}

void MockVendorTagOps::Bind(cros::mojom::VendorTagOpsRequest request) {
base::WaitableEvent done(base::WaitableEvent::ResetPolicy::MANUAL,
base::WaitableEvent::InitialState::NOT_SIGNALED);
cros::mojom::CameraModulePtrInfo ptr_info;
mock_vendor_tag_ops_thread_.task_runner()->PostTask(
FROM_HERE,
base::BindOnce(&MockVendorTagOps::BindOnThread, base::Unretained(this),
base::Unretained(&done), std::move(request)));
done.Wait();
}

void MockVendorTagOps::GetTagCount(GetTagCountCallback callback) {
std::move(callback).Run(DoGetTagCount());
}

void MockVendorTagOps::GetAllTags(GetAllTagsCallback callback) {
std::move(callback).Run(DoGetAllTags());
}

void MockVendorTagOps::GetSectionName(uint32_t tag,
GetSectionNameCallback callback) {
std::move(callback).Run(DoGetSectionName(tag));
}

void MockVendorTagOps::GetTagName(uint32_t tag, GetTagNameCallback callback) {
std::move(callback).Run(DoGetTagName(tag));
}

void MockVendorTagOps::CloseBindingOnThread() {
if (binding_.is_bound()) {
binding_.Close();
}
}

void MockVendorTagOps::BindOnThread(base::WaitableEvent* done,
cros::mojom::VendorTagOpsRequest request) {
binding_.Bind(std::move(request));
done->Signal();
}

} // namespace unittest_internal
} // namespace media
Loading

0 comments on commit 78ec89e

Please sign in to comment.