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