1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "media/capture/video/chromeos/camera_hal_delegate.h"
6
7 #include <stddef.h>
8 #include <stdint.h>
9
10 #include <memory>
11 #include <utility>
12
13 #include "base/run_loop.h"
14 #include "base/test/task_environment.h"
15 #include "media/capture/video/chromeos/mock_camera_module.h"
16 #include "media/capture/video/chromeos/mock_vendor_tag_ops.h"
17 #include "media/capture/video/chromeos/video_capture_device_factory_chromeos.h"
18 #include "media/capture/video/mock_gpu_memory_buffer_manager.h"
19 #include "mojo/public/cpp/bindings/pending_receiver.h"
20 #include "mojo/public/cpp/bindings/pending_remote.h"
21 #include "testing/gmock/include/gmock/gmock.h"
22 #include "testing/gtest/include/gtest/gtest.h"
23
24 using testing::_;
25 using testing::A;
26 using testing::Invoke;
27 using testing::Return;
28
29 namespace {
30
31 constexpr uint32_t kDevicePathTag = 0x80000000;
32 constexpr char kFakeDevicePath[] = "/dev/video5566";
33
34 } // namespace
35
36 namespace media {
37
38 class CameraHalDelegateTest : public ::testing::Test {
39 public:
CameraHalDelegateTest()40 CameraHalDelegateTest() : hal_delegate_thread_("HalDelegateThread") {}
41
SetUp()42 void SetUp() override {
43 VideoCaptureDeviceFactoryChromeOS::SetGpuBufferManager(
44 &mock_gpu_memory_buffer_manager_);
45 hal_delegate_thread_.Start();
46 camera_hal_delegate_ =
47 new CameraHalDelegate(hal_delegate_thread_.task_runner());
48 camera_hal_delegate_->SetCameraModule(
49 mock_camera_module_.GetPendingRemote());
50 }
51
TearDown()52 void TearDown() override {
53 camera_hal_delegate_->Reset();
54 hal_delegate_thread_.Stop();
55 }
56
Wait()57 void Wait() {
58 run_loop_.reset(new base::RunLoop());
59 run_loop_->Run();
60 }
61
62 protected:
63 base::test::TaskEnvironment task_environment_;
64 scoped_refptr<CameraHalDelegate> camera_hal_delegate_;
65 testing::StrictMock<unittest_internal::MockCameraModule> mock_camera_module_;
66 testing::StrictMock<unittest_internal::MockVendorTagOps> mock_vendor_tag_ops_;
67 unittest_internal::MockGpuMemoryBufferManager mock_gpu_memory_buffer_manager_;
68
69 private:
70 base::Thread hal_delegate_thread_;
71 std::unique_ptr<base::RunLoop> run_loop_;
72 DISALLOW_COPY_AND_ASSIGN(CameraHalDelegateTest);
73 };
74
TEST_F(CameraHalDelegateTest,GetBuiltinCameraInfo)75 TEST_F(CameraHalDelegateTest, GetBuiltinCameraInfo) {
76 auto get_number_of_cameras_cb =
77 [](cros::mojom::CameraModule::GetNumberOfCamerasCallback& cb) {
78 std::move(cb).Run(2);
79 };
80
81 auto get_camera_info_cb = [](uint32_t camera_id,
82 cros::mojom::CameraModule::GetCameraInfoCallback&
83 cb) {
84 cros::mojom::CameraInfoPtr camera_info = cros::mojom::CameraInfo::New();
85 cros::mojom::CameraMetadataPtr static_metadata =
86 cros::mojom::CameraMetadata::New();
87 static_metadata->entry_count = 2;
88 static_metadata->entry_capacity = 2;
89 static_metadata->entries =
90 std::vector<cros::mojom::CameraMetadataEntryPtr>();
91
92 cros::mojom::CameraMetadataEntryPtr entry =
93 cros::mojom::CameraMetadataEntry::New();
94 entry->index = 0;
95 entry->tag = cros::mojom::CameraMetadataTag::
96 ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS;
97 entry->type = cros::mojom::EntryType::TYPE_INT64;
98 entry->count = 8;
99 std::vector<int64_t> min_frame_durations(8);
100 min_frame_durations[0] = static_cast<int64_t>(
101 cros::mojom::HalPixelFormat::HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED);
102 min_frame_durations[1] = 1280;
103 min_frame_durations[2] = 720;
104 min_frame_durations[3] = 33333333;
105 min_frame_durations[4] = static_cast<int64_t>(
106 cros::mojom::HalPixelFormat::HAL_PIXEL_FORMAT_YCbCr_420_888);
107 min_frame_durations[5] = 1280;
108 min_frame_durations[6] = 720;
109 min_frame_durations[7] = 16666666;
110 uint8_t* as_int8 = reinterpret_cast<uint8_t*>(min_frame_durations.data());
111 entry->data.assign(as_int8, as_int8 + entry->count * sizeof(int64_t));
112 static_metadata->entries->push_back(std::move(entry));
113
114 entry = cros::mojom::CameraMetadataEntry::New();
115 entry->index = 1;
116 entry->tag = cros::mojom::CameraMetadataTag::
117 ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES;
118 entry->type = cros::mojom::EntryType::TYPE_INT32;
119 entry->count = 4;
120 std::vector<int32_t> default_fps_range{30, 30, 60, 60};
121 as_int8 = reinterpret_cast<uint8_t*>(default_fps_range.data());
122 entry->data.assign(as_int8, as_int8 + entry->count * sizeof(int32_t));
123 static_metadata->entries->push_back(std::move(entry));
124
125 switch (camera_id) {
126 case 0:
127 camera_info->facing = cros::mojom::CameraFacing::CAMERA_FACING_BACK;
128 camera_info->orientation = 0;
129 camera_info->static_camera_characteristics = std::move(static_metadata);
130 break;
131 case 1:
132 camera_info->facing = cros::mojom::CameraFacing::CAMERA_FACING_FRONT;
133 camera_info->orientation = 0;
134 camera_info->static_camera_characteristics = std::move(static_metadata);
135 break;
136 case 2:
137 entry = cros::mojom::CameraMetadataEntry::New();
138 entry->index = static_metadata->entry_count;
139 entry->tag =
140 static_cast<cros::mojom::CameraMetadataTag>(kDevicePathTag);
141 entry->type = cros::mojom::EntryType::TYPE_BYTE;
142 entry->count = sizeof(kFakeDevicePath);
143 entry->data.assign(std::begin(kFakeDevicePath),
144 std::end(kFakeDevicePath));
145
146 static_metadata->entry_count++;
147 static_metadata->entry_capacity++;
148 static_metadata->entries->push_back(std::move(entry));
149
150 camera_info->facing = cros::mojom::CameraFacing::CAMERA_FACING_EXTERNAL;
151 camera_info->orientation = 0;
152 camera_info->static_camera_characteristics = std::move(static_metadata);
153 break;
154 default:
155 FAIL() << "Invalid camera id";
156 }
157
158 std::move(cb).Run(0, std::move(camera_info));
159 };
160
161 auto get_vendor_tag_ops_cb =
162 [&](mojo::PendingReceiver<cros::mojom::VendorTagOps>
163 vendor_tag_ops_receiver,
164 cros::mojom::CameraModule::GetVendorTagOpsCallback&) {
165 mock_vendor_tag_ops_.Bind(std::move(vendor_tag_ops_receiver));
166 };
167
168 auto set_callbacks_cb =
169 [&](mojo::PendingRemote<cros::mojom::CameraModuleCallbacks>& callbacks,
170 cros::mojom::CameraModule::SetCallbacksCallback&) {
171 mock_camera_module_.NotifyCameraDeviceChange(
172 2, cros::mojom::CameraDeviceStatus::CAMERA_DEVICE_STATUS_PRESENT);
173 };
174
175 EXPECT_CALL(mock_camera_module_, DoGetNumberOfCameras(_))
176 .Times(1)
177 .WillOnce(Invoke(get_number_of_cameras_cb));
178 EXPECT_CALL(mock_camera_module_,
179 DoSetCallbacks(
180 A<mojo::PendingRemote<cros::mojom::CameraModuleCallbacks>&>(),
181 A<cros::mojom::CameraModule::SetCallbacksCallback&>()))
182 .Times(1)
183 .WillOnce(Invoke(set_callbacks_cb));
184 EXPECT_CALL(mock_camera_module_,
185 DoGetVendorTagOps(
186 A<mojo::PendingReceiver<cros::mojom::VendorTagOps>>(),
187 A<cros::mojom::CameraModule::GetVendorTagOpsCallback&>()))
188 .Times(1)
189 .WillOnce(Invoke(get_vendor_tag_ops_cb));
190 EXPECT_CALL(mock_camera_module_,
191 DoGetCameraInfo(
192 0, A<cros::mojom::CameraModule::GetCameraInfoCallback&>()))
193 .Times(1)
194 .WillOnce(Invoke(get_camera_info_cb));
195 EXPECT_CALL(mock_camera_module_,
196 DoGetCameraInfo(
197 1, A<cros::mojom::CameraModule::GetCameraInfoCallback&>()))
198 .Times(1)
199 .WillOnce(Invoke(get_camera_info_cb));
200 EXPECT_CALL(mock_camera_module_,
201 DoGetCameraInfo(
202 2, A<cros::mojom::CameraModule::GetCameraInfoCallback&>()))
203 .Times(1)
204 .WillOnce(Invoke(get_camera_info_cb));
205
206 EXPECT_CALL(mock_vendor_tag_ops_, DoGetTagCount())
207 .Times(1)
208 .WillOnce(Return(1));
209
210 EXPECT_CALL(mock_vendor_tag_ops_, DoGetAllTags())
211 .Times(1)
212 .WillOnce(Return(std::vector<uint32_t>{kDevicePathTag}));
213
214 EXPECT_CALL(mock_vendor_tag_ops_, DoGetSectionName(kDevicePathTag))
215 .Times(1)
216 .WillOnce(Return("com.google"));
217
218 EXPECT_CALL(mock_vendor_tag_ops_, DoGetTagName(kDevicePathTag))
219 .Times(1)
220 .WillOnce(Return("usb.devicePath"));
221
222 EXPECT_CALL(mock_vendor_tag_ops_, DoGetTagType(kDevicePathTag))
223 .Times(1)
224 .WillOnce(
225 Return(static_cast<int32_t>(cros::mojom::EntryType::TYPE_BYTE)));
226
227 VideoCaptureDeviceDescriptors descriptors;
228 camera_hal_delegate_->GetDeviceDescriptors(&descriptors);
229
230 ASSERT_EQ(3u, descriptors.size());
231 // We have workaround to always put front camera at first.
232 ASSERT_EQ("1", descriptors[0].device_id);
233 ASSERT_EQ(VideoFacingMode::MEDIA_VIDEO_FACING_USER, descriptors[0].facing);
234 ASSERT_EQ("0", descriptors[1].device_id);
235 ASSERT_EQ(VideoFacingMode::MEDIA_VIDEO_FACING_ENVIRONMENT,
236 descriptors[1].facing);
237 ASSERT_EQ(kFakeDevicePath, descriptors[2].device_id);
238 ASSERT_EQ(VideoFacingMode::MEDIA_VIDEO_FACING_NONE, descriptors[2].facing);
239
240 // TODO(shik): Test external camera. Check the fields |display_name| and
241 // |model_id| are set properly according to the vendor tags.
242
243 EXPECT_CALL(mock_gpu_memory_buffer_manager_,
244 CreateGpuMemoryBuffer(_, gfx::BufferFormat::YUV_420_BIPLANAR,
245 gfx::BufferUsage::SCANOUT_CAMERA_READ_WRITE,
246 gpu::kNullSurfaceHandle))
247 .Times(1)
248 .WillOnce(Invoke(&unittest_internal::MockGpuMemoryBufferManager::
249 CreateFakeGpuMemoryBuffer));
250
251 VideoCaptureFormats supported_formats;
252 camera_hal_delegate_->GetSupportedFormats(descriptors[0], &supported_formats);
253
254 // IMPLEMENTATION_DEFINED format should be filtered; currently YCbCr_420_888
255 // format corresponds to NV12 in Chrome.
256 ASSERT_GE(supported_formats.size(), 1U);
257 for (auto& format : supported_formats) {
258 ASSERT_EQ(gfx::Size(1280, 720), format.frame_size);
259 ASSERT_TRUE(format.frame_rate == 60.0 || format.frame_rate == 30.0);
260 ASSERT_EQ(PIXEL_FORMAT_NV12, format.pixel_format);
261 }
262 }
263
264 } // namespace media
265