blob: 35bf7527850042d001fd0b9be3b2badc7a148082 [file] [log] [blame]
Jan Sebechlebsky3b478c42023-11-23 13:15:56 +01001/*
Biswarup Pal6152a302023-12-19 12:44:09 +00002 * Copyright 2023 The Android Open Source Project
Jan Sebechlebsky3b478c42023-11-23 13:15:56 +01003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Jan Sebechlebsky8ae23592024-02-02 16:08:18 +010017#include <algorithm>
18#include <iterator>
Jan Sebechlebsky3b478c42023-11-23 13:15:56 +010019#include <memory>
20
21#include "VirtualCameraDevice.h"
22#include "aidl/android/companion/virtualcamera/Format.h"
23#include "aidl/android/companion/virtualcamera/SupportedStreamConfiguration.h"
Biswarup Pal6152a302023-12-19 12:44:09 +000024#include "aidl/android/companion/virtualcamera/VirtualCameraConfiguration.h"
Jan Sebechlebsky3b478c42023-11-23 13:15:56 +010025#include "aidl/android/hardware/camera/device/CameraMetadata.h"
26#include "aidl/android/hardware/camera/device/StreamConfiguration.h"
Jan Sebechlebsky8ae23592024-02-02 16:08:18 +010027#include "aidl/android/hardware/graphics/common/PixelFormat.h"
Jan Sebechlebsky3b478c42023-11-23 13:15:56 +010028#include "android/binder_interface_utils.h"
29#include "gmock/gmock.h"
30#include "gtest/gtest.h"
31#include "log/log_main.h"
32#include "system/camera_metadata.h"
33#include "utils/Errors.h"
34
35namespace android {
36namespace companion {
37namespace virtualcamera {
38namespace {
39
40using ::aidl::android::companion::virtualcamera::Format;
Biswarup Pal112458f2023-12-28 19:50:17 +000041using ::aidl::android::companion::virtualcamera::LensFacing;
Biswarup Pal6152a302023-12-19 12:44:09 +000042using ::aidl::android::companion::virtualcamera::SensorOrientation;
Jan Sebechlebsky3b478c42023-11-23 13:15:56 +010043using ::aidl::android::companion::virtualcamera::SupportedStreamConfiguration;
Biswarup Pal6152a302023-12-19 12:44:09 +000044using ::aidl::android::companion::virtualcamera::VirtualCameraConfiguration;
Jan Sebechlebsky3b478c42023-11-23 13:15:56 +010045using ::aidl::android::hardware::camera::device::CameraMetadata;
46using ::aidl::android::hardware::camera::device::Stream;
47using ::aidl::android::hardware::camera::device::StreamConfiguration;
48using ::aidl::android::hardware::camera::device::StreamType;
49using ::aidl::android::hardware::graphics::common::PixelFormat;
50using ::testing::UnorderedElementsAreArray;
51using metadata_stream_t =
52 camera_metadata_enum_android_scaler_available_stream_configurations_t;
53
54constexpr int kCameraId = 42;
55constexpr int kVgaWidth = 640;
56constexpr int kVgaHeight = 480;
57constexpr int kHdWidth = 1280;
58constexpr int kHdHeight = 720;
Biswarup Pal6152a302023-12-19 12:44:09 +000059constexpr int kMaxFps = 30;
Jan Sebechlebsky3b478c42023-11-23 13:15:56 +010060
Jan Sebechlebsky8ae23592024-02-02 16:08:18 +010061const Stream kVgaYUV420Stream = Stream{
62 .streamType = StreamType::OUTPUT,
63 .width = kVgaWidth,
64 .height = kVgaHeight,
65 .format = PixelFormat::YCBCR_420_888,
66};
67
68const Stream kVgaJpegStream = Stream{
69 .streamType = StreamType::OUTPUT,
70 .width = kVgaWidth,
71 .height = kVgaHeight,
72 .format = PixelFormat::BLOB,
73};
74
Jan Sebechlebsky3b478c42023-11-23 13:15:56 +010075struct AvailableStreamConfiguration {
76 const int width;
77 const int height;
78 const int pixelFormat;
79 const metadata_stream_t streamConfiguration;
80};
81
82bool operator==(const AvailableStreamConfiguration& a,
83 const AvailableStreamConfiguration& b) {
84 return a.width == b.width && a.height == b.height &&
85 a.pixelFormat == b.pixelFormat &&
86 a.streamConfiguration == b.streamConfiguration;
87}
88
89std::ostream& operator<<(std::ostream& os,
90 const AvailableStreamConfiguration& config) {
91 os << config.width << "x" << config.height << " (pixfmt "
92 << config.pixelFormat << ", streamConfiguration "
93 << config.streamConfiguration << ")";
94 return os;
95}
96
97std::vector<AvailableStreamConfiguration> getAvailableStreamConfigurations(
98 const CameraMetadata& metadata) {
99 const camera_metadata_t* const raw =
100 reinterpret_cast<const camera_metadata_t*>(metadata.metadata.data());
101 camera_metadata_ro_entry_t entry;
102 if (find_camera_metadata_ro_entry(
103 raw, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, &entry) !=
104 NO_ERROR) {
105 return {};
106 }
107
108 std::vector<AvailableStreamConfiguration> res;
109 for (int i = 0; i < entry.count; i += 4) {
110 res.push_back(AvailableStreamConfiguration{
111 .width = entry.data.i32[i + 1],
112 .height = entry.data.i32[i + 2],
113 .pixelFormat = entry.data.i32[i],
114 .streamConfiguration =
115 static_cast<metadata_stream_t>(entry.data.i32[i + 3])});
116 }
117 return res;
118}
119
120struct VirtualCameraConfigTestParam {
Biswarup Pal6152a302023-12-19 12:44:09 +0000121 VirtualCameraConfiguration inputConfig;
Jan Sebechlebsky3b478c42023-11-23 13:15:56 +0100122 std::vector<AvailableStreamConfiguration> expectedAvailableStreamConfigs;
123};
124
Jan Sebechlebsky8ae23592024-02-02 16:08:18 +0100125class VirtualCameraDeviceCharacterisicsTest
Jan Sebechlebsky3b478c42023-11-23 13:15:56 +0100126 : public testing::TestWithParam<VirtualCameraConfigTestParam> {};
127
Jan Sebechlebsky8ae23592024-02-02 16:08:18 +0100128TEST_P(VirtualCameraDeviceCharacterisicsTest,
129 cameraCharacteristicsForInputFormat) {
Jan Sebechlebsky3b478c42023-11-23 13:15:56 +0100130 const VirtualCameraConfigTestParam& param = GetParam();
131 std::shared_ptr<VirtualCameraDevice> camera =
Biswarup Pal6152a302023-12-19 12:44:09 +0000132 ndk::SharedRefBase::make<VirtualCameraDevice>(kCameraId,
133 param.inputConfig);
Jan Sebechlebsky3b478c42023-11-23 13:15:56 +0100134
135 CameraMetadata metadata;
136 ASSERT_TRUE(camera->getCameraCharacteristics(&metadata).isOk());
137 EXPECT_THAT(getAvailableStreamConfigurations(metadata),
138 UnorderedElementsAreArray(param.expectedAvailableStreamConfigs));
139
140 // Configuration needs to succeed for every available stream configuration
141 for (const AvailableStreamConfiguration& config :
142 param.expectedAvailableStreamConfigs) {
143 StreamConfiguration configuration{
144 .streams = std::vector<Stream>{Stream{
145 .streamType = StreamType::OUTPUT,
146 .width = config.width,
147 .height = config.height,
148 .format = static_cast<PixelFormat>(config.pixelFormat),
149 }}};
150 bool aidl_ret;
151 ASSERT_TRUE(
152 camera->isStreamCombinationSupported(configuration, &aidl_ret).isOk());
153 EXPECT_TRUE(aidl_ret);
154 }
155}
156
157INSTANTIATE_TEST_SUITE_P(
Jan Sebechlebsky8ae23592024-02-02 16:08:18 +0100158 cameraCharacteristicsForInputFormat, VirtualCameraDeviceCharacterisicsTest,
Jan Sebechlebsky3b478c42023-11-23 13:15:56 +0100159 testing::Values(
160 VirtualCameraConfigTestParam{
Biswarup Pal6152a302023-12-19 12:44:09 +0000161 .inputConfig =
162 VirtualCameraConfiguration{
163 .supportedStreamConfigs = {SupportedStreamConfiguration{
164 .width = kVgaWidth,
165 .height = kVgaHeight,
166 .pixelFormat = Format::YUV_420_888,
167 .maxFps = kMaxFps}},
168 .virtualCameraCallback = nullptr,
Biswarup Pal112458f2023-12-28 19:50:17 +0000169 .sensorOrientation = SensorOrientation::ORIENTATION_0,
170 .lensFacing = LensFacing::FRONT},
Jan Sebechlebsky3b478c42023-11-23 13:15:56 +0100171 .expectedAvailableStreamConfigs =
172 {AvailableStreamConfiguration{
173 .width = kVgaWidth,
174 .height = kVgaHeight,
175 .pixelFormat = ANDROID_SCALER_AVAILABLE_FORMATS_YCbCr_420_888,
176 .streamConfiguration =
177 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT},
178 AvailableStreamConfiguration{
179 .width = kVgaWidth,
180 .height = kVgaHeight,
181 .pixelFormat =
182 ANDROID_SCALER_AVAILABLE_FORMATS_IMPLEMENTATION_DEFINED,
183 .streamConfiguration =
184 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT},
185 AvailableStreamConfiguration{
186 .width = kVgaWidth,
187 .height = kVgaHeight,
188 .pixelFormat = ANDROID_SCALER_AVAILABLE_FORMATS_BLOB,
189 .streamConfiguration =
190 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT}}},
191 VirtualCameraConfigTestParam{
Biswarup Pal6152a302023-12-19 12:44:09 +0000192 .inputConfig =
193 VirtualCameraConfiguration{
194 .supportedStreamConfigs =
195 {SupportedStreamConfiguration{
196 .width = kVgaWidth,
197 .height = kVgaHeight,
198 .pixelFormat = Format::YUV_420_888,
199 .maxFps = kMaxFps},
200 SupportedStreamConfiguration{
201 .width = kHdWidth,
202 .height = kHdHeight,
203 .pixelFormat = Format::YUV_420_888,
204 .maxFps = kMaxFps}},
205 .virtualCameraCallback = nullptr,
Biswarup Pal112458f2023-12-28 19:50:17 +0000206 .sensorOrientation = SensorOrientation::ORIENTATION_0,
207 .lensFacing = LensFacing::BACK},
Jan Sebechlebsky3b478c42023-11-23 13:15:56 +0100208 .expectedAvailableStreamConfigs = {
209 AvailableStreamConfiguration{
210 .width = kVgaWidth,
211 .height = kVgaHeight,
212 .pixelFormat = ANDROID_SCALER_AVAILABLE_FORMATS_YCbCr_420_888,
213 .streamConfiguration =
214 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT},
215 AvailableStreamConfiguration{
216 .width = kVgaWidth,
217 .height = kVgaHeight,
218 .pixelFormat =
219 ANDROID_SCALER_AVAILABLE_FORMATS_IMPLEMENTATION_DEFINED,
220 .streamConfiguration =
221 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT},
222 AvailableStreamConfiguration{
223 .width = kVgaWidth,
224 .height = kVgaHeight,
225 .pixelFormat = ANDROID_SCALER_AVAILABLE_FORMATS_BLOB,
226 .streamConfiguration =
227 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT},
228 AvailableStreamConfiguration{
229 .width = kHdWidth,
230 .height = kHdHeight,
231 .pixelFormat = ANDROID_SCALER_AVAILABLE_FORMATS_YCbCr_420_888,
232 .streamConfiguration =
233 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT},
234 AvailableStreamConfiguration{
235 .width = kHdWidth,
236 .height = kHdHeight,
237 .pixelFormat =
238 ANDROID_SCALER_AVAILABLE_FORMATS_IMPLEMENTATION_DEFINED,
239 .streamConfiguration =
240 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT},
241 AvailableStreamConfiguration{
242 .width = kHdWidth,
243 .height = kHdHeight,
244 .pixelFormat = ANDROID_SCALER_AVAILABLE_FORMATS_BLOB,
245 .streamConfiguration =
246 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT}}}));
247
Jan Sebechlebsky8ae23592024-02-02 16:08:18 +0100248class VirtualCameraDeviceTest : public ::testing::Test {
249 public:
250 void SetUp() override {
251 mCamera = ndk::SharedRefBase::make<VirtualCameraDevice>(
252 kCameraId, VirtualCameraConfiguration{
253 .supportedStreamConfigs = {SupportedStreamConfiguration{
254 .width = kVgaWidth,
255 .height = kVgaHeight,
256 .pixelFormat = Format::YUV_420_888,
257 .maxFps = kMaxFps}},
258 .virtualCameraCallback = nullptr,
259 .sensorOrientation = SensorOrientation::ORIENTATION_0,
260 .lensFacing = LensFacing::FRONT});
261 }
262
263 protected:
264 std::shared_ptr<VirtualCameraDevice> mCamera;
265};
266
267TEST_F(VirtualCameraDeviceTest, configureMaximalNumberOfNonStallStreamsSuceeds) {
268 StreamConfiguration config;
269 std::fill_n(std::back_insert_iterator(config.streams),
270 VirtualCameraDevice::kMaxNumberOfProcessedStreams,
271 kVgaYUV420Stream);
272
273 bool aidl_ret;
274 ASSERT_TRUE(mCamera->isStreamCombinationSupported(config, &aidl_ret).isOk());
275 EXPECT_TRUE(aidl_ret);
276}
277
278TEST_F(VirtualCameraDeviceTest, configureTooManyNonStallStreamsFails) {
279 StreamConfiguration config;
280 std::fill_n(std::back_insert_iterator(config.streams),
281 VirtualCameraDevice::kMaxNumberOfProcessedStreams + 1,
282 kVgaYUV420Stream);
283
284 bool aidl_ret;
285 ASSERT_TRUE(mCamera->isStreamCombinationSupported(config, &aidl_ret).isOk());
286 EXPECT_FALSE(aidl_ret);
287}
288
289TEST_F(VirtualCameraDeviceTest, configureMaximalNumberOfStallStreamsSuceeds) {
290 StreamConfiguration config;
291 std::fill_n(std::back_insert_iterator(config.streams),
292 VirtualCameraDevice::kMaxNumberOfStallStreams, kVgaJpegStream);
293
294 bool aidl_ret;
295 ASSERT_TRUE(mCamera->isStreamCombinationSupported(config, &aidl_ret).isOk());
296 EXPECT_TRUE(aidl_ret);
297}
298
299TEST_F(VirtualCameraDeviceTest, configureTooManyStallStreamsFails) {
300 StreamConfiguration config;
301 std::fill_n(std::back_insert_iterator(config.streams),
302 VirtualCameraDevice::kMaxNumberOfStallStreams + 1, kVgaJpegStream);
303
304 bool aidl_ret;
305 ASSERT_TRUE(mCamera->isStreamCombinationSupported(config, &aidl_ret).isOk());
306 EXPECT_FALSE(aidl_ret);
307}
308
Jan Sebechlebsky3b478c42023-11-23 13:15:56 +0100309} // namespace
310} // namespace virtualcamera
311} // namespace companion
312} // namespace android