blob: fc5fb3685feea180e4f0c756ee1f1084e17a1bdf [file] [log] [blame]
Igor Murashkine302ee32012-11-05 11:14:49 -08001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
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
Igor Murashkineab33fc2012-11-06 17:02:54 -080017#ifndef __ANDROID_HAL_CAMERA2_TESTS_STREAM_FIXTURE__
18#define __ANDROID_HAL_CAMERA2_TESTS_STREAM_FIXTURE__
19
Igor Murashkine302ee32012-11-05 11:14:49 -080020#include <gtest/gtest.h>
Igor Murashkineab33fc2012-11-06 17:02:54 -080021#include <iostream>
Eino-Ville Talvala7d831712013-07-01 18:47:09 -070022#include <fstream>
Igor Murashkine302ee32012-11-05 11:14:49 -080023
24#include <gui/CpuConsumer.h>
Mathias Agopiancc501112013-02-14 17:34:35 -080025#include <gui/Surface.h>
Igor Murashkinf1b9ae72012-12-07 15:08:35 -080026#include <utils/Condition.h>
27#include <utils/Mutex.h>
Eino-Ville Talvala4c543a12013-06-25 18:12:19 -070028#include <system/camera_metadata.h>
Igor Murashkine302ee32012-11-05 11:14:49 -080029
30#include "CameraModuleFixture.h"
Igor Murashkineab33fc2012-11-06 17:02:54 -080031#include "TestExtensions.h"
Igor Murashkine302ee32012-11-05 11:14:49 -080032
Eino-Ville Talvala7d831712013-07-01 18:47:09 -070033#define ALIGN(x, mask) ( ((x) + (mask) - 1) & ~((mask) - 1) )
34
Igor Murashkine302ee32012-11-05 11:14:49 -080035namespace android {
36namespace camera2 {
37namespace tests {
38
Eino-Ville Talvala4c543a12013-06-25 18:12:19 -070039// Format specifier for picking the best format for CPU reading the given device
40// version
41#define CAMERA_STREAM_AUTO_CPU_FORMAT (-1)
42
43struct CameraStreamParams;
44
45void PrintTo(const CameraStreamParams& p, ::std::ostream* os);
46
Igor Murashkine302ee32012-11-05 11:14:49 -080047struct CameraStreamParams {
Igor Murashkine302ee32012-11-05 11:14:49 -080048 int mFormat;
49 int mHeapCount;
Eino-Ville Talvala4c543a12013-06-25 18:12:19 -070050
Igor Murashkine302ee32012-11-05 11:14:49 -080051};
52
Eino-Ville Talvala4c543a12013-06-25 18:12:19 -070053inline ::std::ostream& operator<<(::std::ostream& os, const CameraStreamParams &p) {
54 PrintTo(p, &os);
55 return os;
56}
57
Igor Murashkineab33fc2012-11-06 17:02:54 -080058inline void PrintTo(const CameraStreamParams& p, ::std::ostream* os) {
Eino-Ville Talvala4c543a12013-06-25 18:12:19 -070059 char fmt[100];
60 camera_metadata_enum_snprint(
61 ANDROID_SCALER_AVAILABLE_FORMATS, p.mFormat, fmt, sizeof(fmt));
62
Igor Murashkineab33fc2012-11-06 17:02:54 -080063 *os << "{ ";
Igor Murashkin7a7f3572013-02-11 15:52:03 -080064 *os << "Format: 0x" << std::hex << p.mFormat << ", ";
Eino-Ville Talvala4c543a12013-06-25 18:12:19 -070065 *os << "Format name: " << fmt << ", ";
Igor Murashkin7a7f3572013-02-11 15:52:03 -080066 *os << "HeapCount: " << p.mHeapCount;
Igor Murashkineab33fc2012-11-06 17:02:54 -080067 *os << " }";
68}
69
Igor Murashkine302ee32012-11-05 11:14:49 -080070class CameraStreamFixture
71 : public CameraModuleFixture</*InfoQuirk*/true> {
72
73public:
74 CameraStreamFixture(CameraStreamParams p)
Igor Murashkin00b597f2012-12-11 15:19:25 -080075 : CameraModuleFixture(TestSettings::DeviceId()) {
Igor Murashkineab33fc2012-11-06 17:02:54 -080076 TEST_EXTENSION_FORKING_CONSTRUCTOR;
77
Igor Murashkine302ee32012-11-05 11:14:49 -080078 mParam = p;
79
80 SetUp();
81 }
82
83 ~CameraStreamFixture() {
Igor Murashkineab33fc2012-11-06 17:02:54 -080084 TEST_EXTENSION_FORKING_DESTRUCTOR;
85
Igor Murashkine302ee32012-11-05 11:14:49 -080086 TearDown();
87 }
88
89private:
90
91 void SetUp() {
Igor Murashkineab33fc2012-11-06 17:02:54 -080092 TEST_EXTENSION_FORKING_SET_UP;
93
Igor Murashkin7acb21a2012-12-18 13:38:40 -080094 CameraModuleFixture::SetUp();
95
Eino-Ville Talvala4c543a12013-06-25 18:12:19 -070096 sp<CameraDeviceBase> device = mDevice;
Igor Murashkine302ee32012-11-05 11:14:49 -080097
98 /* use an arbitrary w,h */
Yin-Chia Yeh8df990b2014-10-31 15:10:11 -070099 if (getDeviceVersion() < CAMERA_DEVICE_API_VERSION_3_2) {
Igor Murashkine302ee32012-11-05 11:14:49 -0800100 const int tag = ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES;
101
Igor Murashkin7ed10fb2013-02-13 17:33:36 -0800102 const CameraMetadata& staticInfo = device->info();
Igor Murashkine302ee32012-11-05 11:14:49 -0800103 camera_metadata_ro_entry entry = staticInfo.find(tag);
104 ASSERT_NE(0u, entry.count)
105 << "Missing tag android.scaler.availableProcessedSizes";
106
107 ASSERT_LE(2u, entry.count);
108 /* this seems like it would always be the smallest w,h
Yin-Chia Yeh8df990b2014-10-31 15:10:11 -0700109 but we actually make no contract that it's sorted asc */
Igor Murashkine302ee32012-11-05 11:14:49 -0800110 mWidth = entry.data.i32[0];
111 mHeight = entry.data.i32[1];
Yin-Chia Yeh8df990b2014-10-31 15:10:11 -0700112 } else {
113 buildOutputResolutions();
Yin-Chia Yehc2537652015-03-24 10:48:08 -0700114 const int32_t *implDefResolutions = NULL;
Yin-Chia Yeh8df990b2014-10-31 15:10:11 -0700115 size_t implDefResolutionsCount;
116
117 int format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
118
119 getResolutionList(format,
120 &implDefResolutions, &implDefResolutionsCount);
121 ASSERT_NE(0u, implDefResolutionsCount)
122 << "Missing implementation defined sizes";
123 mWidth = implDefResolutions[0];
124 mHeight = implDefResolutions[1];
Igor Murashkine302ee32012-11-05 11:14:49 -0800125 }
126 }
127 void TearDown() {
Igor Murashkineab33fc2012-11-06 17:02:54 -0800128 TEST_EXTENSION_FORKING_TEAR_DOWN;
Igor Murashkin7acb21a2012-12-18 13:38:40 -0800129
130 // important: shut down HAL before releasing streams
131 CameraModuleFixture::TearDown();
132
Yin-Chia Yeh8df990b2014-10-31 15:10:11 -0700133 deleteOutputResolutions();
Eino-Ville Talvalacd6984e2015-06-09 15:23:34 -0700134 mSurface.clear();
Igor Murashkin7acb21a2012-12-18 13:38:40 -0800135 mCpuConsumer.clear();
136 mFrameListener.clear();
Igor Murashkine302ee32012-11-05 11:14:49 -0800137 }
138
139protected:
Yin-Chia Yeh8df990b2014-10-31 15:10:11 -0700140
141 int64_t getMinFrameDurationFor(int32_t format, int32_t width, int32_t height) {
142 int64_t minFrameDuration = -1L;
143 const int tag = ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS;
144 sp<CameraDeviceBase> device = mDevice;
145 const CameraMetadata& staticInfo = device->info();
146 camera_metadata_ro_entry_t availableMinDurations = staticInfo.find(tag);
147 for (uint32_t i = 0; i < availableMinDurations.count; i += 4) {
148 if (format == availableMinDurations.data.i64[i] &&
149 width == availableMinDurations.data.i64[i + 1] &&
150 height == availableMinDurations.data.i64[i + 2]) {
151 minFrameDuration = availableMinDurations.data.i64[i + 3];
152 break;
153 }
154 }
155 return minFrameDuration;
156 }
157
158 void buildOutputResolutions() {
159 if (getDeviceVersion() < CAMERA_DEVICE_API_VERSION_3_2) {
160 return;
161 }
162 if (mOutputResolutions.isEmpty()) {
163 const int tag = ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS;
164 const CameraMetadata& staticInfo = mDevice->info();
165 camera_metadata_ro_entry_t availableStrmConfigs = staticInfo.find(tag);
166 ASSERT_EQ(0u, availableStrmConfigs.count % 4);
167 for (uint32_t i = 0; i < availableStrmConfigs.count; i += 4) {
168 int32_t format = availableStrmConfigs.data.i32[i];
169 int32_t width = availableStrmConfigs.data.i32[i + 1];
170 int32_t height = availableStrmConfigs.data.i32[i + 2];
171 int32_t inOrOut = availableStrmConfigs.data.i32[i + 3];
172 if (inOrOut == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT) {
173 int index = mOutputResolutions.indexOfKey(format);
174 if (index < 0) {
175 index = mOutputResolutions.add(format, new Vector<int32_t>());
176 ASSERT_TRUE(index >= 0);
177 }
178 Vector<int32_t> *resolutions = mOutputResolutions.editValueAt(index);
179 resolutions->add(width);
180 resolutions->add(height);
181 }
182 }
183 }
184 }
185
186 void getResolutionList(int32_t format,
187 const int32_t **list,
188 size_t *count) {
189 status_t res;
190 ALOGV("Getting resolutions for format %x", format);
191 if (getDeviceVersion() < CAMERA_DEVICE_API_VERSION_3_2) {
192 return;
193 }
194 int index = mOutputResolutions.indexOfKey(format);
195 ASSERT_TRUE(index >= 0);
196 Vector<int32_t>* resolutions = mOutputResolutions.valueAt(index);
197 *list = resolutions->array();
198 *count = resolutions->size();
199 }
200
201 void deleteOutputResolutions() {
202 for (uint32_t i = 0; i < mOutputResolutions.size(); i++) {
203 Vector<int32_t>* resolutions = mOutputResolutions.editValueAt(i);
204 delete resolutions;
205 }
206 mOutputResolutions.clear();
207 }
208
Igor Murashkinf1b9ae72012-12-07 15:08:35 -0800209 struct FrameListener : public ConsumerBase::FrameAvailableListener {
210
211 FrameListener() {
212 mPendingFrames = 0;
213 }
214
215 // CpuConsumer::FrameAvailableListener implementation
Dan Stoza32ef0ca2014-11-04 11:39:35 -0800216 virtual void onFrameAvailable(const BufferItem& /* item */) {
Igor Murashkinf1b9ae72012-12-07 15:08:35 -0800217 ALOGV("Frame now available (start)");
218
219 Mutex::Autolock lock(mMutex);
220 mPendingFrames++;
221 mCondition.signal();
222
223 ALOGV("Frame now available (end)");
224 }
225
226 status_t waitForFrame(nsecs_t timeout) {
227 status_t res;
228 Mutex::Autolock lock(mMutex);
229 while (mPendingFrames == 0) {
230 res = mCondition.waitRelative(mMutex, timeout);
231 if (res != OK) return res;
232 }
233 mPendingFrames--;
234 return OK;
235 }
236
237 private:
238 Mutex mMutex;
239 Condition mCondition;
240 int mPendingFrames;
241 };
Igor Murashkine302ee32012-11-05 11:14:49 -0800242
243 void CreateStream() {
Eino-Ville Talvala4c543a12013-06-25 18:12:19 -0700244 sp<CameraDeviceBase> device = mDevice;
Igor Murashkine302ee32012-11-05 11:14:49 -0800245 CameraStreamParams p = mParam;
246
Dan Stoza5dce9e42014-04-07 13:39:37 -0700247 sp<IGraphicBufferProducer> producer;
248 sp<IGraphicBufferConsumer> consumer;
249 BufferQueue::createBufferQueue(&producer, &consumer);
250 mCpuConsumer = new CpuConsumer(consumer, p.mHeapCount);
Igor Murashkine302ee32012-11-05 11:14:49 -0800251 mCpuConsumer->setName(String8("CameraStreamTest::mCpuConsumer"));
252
Eino-Ville Talvalacd6984e2015-06-09 15:23:34 -0700253 mSurface = new Surface(producer);
Igor Murashkine302ee32012-11-05 11:14:49 -0800254
Eino-Ville Talvala4c543a12013-06-25 18:12:19 -0700255 int format = MapAutoFormat(p.mFormat);
256
Igor Murashkine302ee32012-11-05 11:14:49 -0800257 ASSERT_EQ(OK,
Eino-Ville Talvalacd6984e2015-06-09 15:23:34 -0700258 device->createStream(mSurface,
Zhijun He1c3e6572014-08-10 21:24:49 -0700259 mWidth, mHeight, format,
Eino-Ville Talvala898ad172015-03-06 13:23:18 -0800260 HAL_DATASPACE_UNKNOWN,
Yin-Chia Yeh5407ef12015-03-12 15:09:27 -0700261 CAMERA3_STREAM_ROTATION_0,
Igor Murashkine302ee32012-11-05 11:14:49 -0800262 &mStreamId));
263
264 ASSERT_NE(-1, mStreamId);
Igor Murashkinf1b9ae72012-12-07 15:08:35 -0800265
266 // do not make 'this' a FrameListener or the lifetime policy will clash
267 mFrameListener = new FrameListener();
268 mCpuConsumer->setFrameAvailableListener(mFrameListener);
Igor Murashkine302ee32012-11-05 11:14:49 -0800269 }
270
271 void DeleteStream() {
272 ASSERT_EQ(OK, mDevice->deleteStream(mStreamId));
273 }
274
Eino-Ville Talvala4c543a12013-06-25 18:12:19 -0700275 int MapAutoFormat(int format) {
276 if (format == CAMERA_STREAM_AUTO_CPU_FORMAT) {
277 if (getDeviceVersion() >= CAMERA_DEVICE_API_VERSION_3_0) {
278 format = HAL_PIXEL_FORMAT_YCbCr_420_888;
279 } else {
280 format = HAL_PIXEL_FORMAT_YCrCb_420_SP;
281 }
282 }
283 return format;
284 }
285
Eino-Ville Talvala7d831712013-07-01 18:47:09 -0700286 void DumpYuvToFile(const String8 &fileName, const CpuConsumer::LockedBuffer &img) {
287 uint8_t *dataCb, *dataCr;
288 uint32_t stride;
289 uint32_t chromaStride;
290 uint32_t chromaStep;
291
292 switch (img.format) {
293 case HAL_PIXEL_FORMAT_YCbCr_420_888:
294 stride = img.stride;
295 chromaStride = img.chromaStride;
296 chromaStep = img.chromaStep;
297 dataCb = img.dataCb;
298 dataCr = img.dataCr;
299 break;
300 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
301 stride = img.width;
302 chromaStride = img.width;
303 chromaStep = 2;
304 dataCr = img.data + img.width * img.height;
305 dataCb = dataCr + 1;
306 break;
307 case HAL_PIXEL_FORMAT_YV12:
308 stride = img.stride;
309 chromaStride = ALIGN(img.width / 2, 16);
310 chromaStep = 1;
311 dataCr = img.data + img.stride * img.height;
312 dataCb = dataCr + chromaStride * img.height/2;
313 break;
314 default:
315 ALOGE("Unknown format %d, not dumping", img.format);
316 return;
317 }
318
319 // Write Y
320 FILE *yuvFile = fopen(fileName.string(), "w");
321
322 size_t bytes;
323
324 for (size_t y = 0; y < img.height; ++y) {
325 bytes = fwrite(
326 reinterpret_cast<const char*>(img.data + stride * y),
327 1, img.width, yuvFile);
328 if (bytes != img.width) {
329 ALOGE("Unable to write to file %s", fileName.string());
330 fclose(yuvFile);
331 return;
332 }
333 }
334
335 // Write Cb/Cr
336 uint8_t *src = dataCb;
337 for (int c = 0; c < 2; ++c) {
338 for (size_t y = 0; y < img.height / 2; ++y) {
339 uint8_t *px = src + y * chromaStride;
340 if (chromaStep != 1) {
341 for (size_t x = 0; x < img.width / 2; ++x) {
342 fputc(*px, yuvFile);
343 px += chromaStep;
344 }
345 } else {
346 bytes = fwrite(reinterpret_cast<const char*>(px),
347 1, img.width / 2, yuvFile);
348 if (bytes != img.width / 2) {
349 ALOGE("Unable to write to file %s", fileName.string());
350 fclose(yuvFile);
351 return;
352 }
353 }
354 }
355 src = dataCr;
356 }
357 fclose(yuvFile);
358 }
359
Igor Murashkine302ee32012-11-05 11:14:49 -0800360 int mWidth;
361 int mHeight;
362
363 int mStreamId;
Igor Murashkinf1b9ae72012-12-07 15:08:35 -0800364
365 android::sp<FrameListener> mFrameListener;
Igor Murashkine302ee32012-11-05 11:14:49 -0800366 android::sp<CpuConsumer> mCpuConsumer;
Eino-Ville Talvalacd6984e2015-06-09 15:23:34 -0700367 android::sp<Surface> mSurface;
Yin-Chia Yeh8df990b2014-10-31 15:10:11 -0700368 KeyedVector<int32_t, Vector<int32_t>* > mOutputResolutions;
Igor Murashkinf1b9ae72012-12-07 15:08:35 -0800369
Igor Murashkine302ee32012-11-05 11:14:49 -0800370private:
371 CameraStreamParams mParam;
372};
373
374}
375}
376}
377
Igor Murashkineab33fc2012-11-06 17:02:54 -0800378#endif