blob: 3d614dbfdad5102b3394c80d095eb71f53d3b569 [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
Igor Murashkine302ee32012-11-05 11:14:49 -080096 CameraStreamParams p = mParam;
Eino-Ville Talvala4c543a12013-06-25 18:12:19 -070097 sp<CameraDeviceBase> device = mDevice;
Igor Murashkine302ee32012-11-05 11:14:49 -080098
99 /* use an arbitrary w,h */
100 {
101 const int tag = ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES;
102
Igor Murashkin7ed10fb2013-02-13 17:33:36 -0800103 const CameraMetadata& staticInfo = device->info();
Igor Murashkine302ee32012-11-05 11:14:49 -0800104 camera_metadata_ro_entry entry = staticInfo.find(tag);
105 ASSERT_NE(0u, entry.count)
106 << "Missing tag android.scaler.availableProcessedSizes";
107
108 ASSERT_LE(2u, entry.count);
109 /* this seems like it would always be the smallest w,h
110 but we actually make no contract that it's sorted asc */;
111 mWidth = entry.data.i32[0];
112 mHeight = entry.data.i32[1];
113 }
114 }
115 void TearDown() {
Igor Murashkineab33fc2012-11-06 17:02:54 -0800116 TEST_EXTENSION_FORKING_TEAR_DOWN;
Igor Murashkin7acb21a2012-12-18 13:38:40 -0800117
118 // important: shut down HAL before releasing streams
119 CameraModuleFixture::TearDown();
120
121 mNativeWindow.clear();
122 mCpuConsumer.clear();
123 mFrameListener.clear();
Igor Murashkine302ee32012-11-05 11:14:49 -0800124 }
125
126protected:
Igor Murashkinf1b9ae72012-12-07 15:08:35 -0800127 struct FrameListener : public ConsumerBase::FrameAvailableListener {
128
129 FrameListener() {
130 mPendingFrames = 0;
131 }
132
133 // CpuConsumer::FrameAvailableListener implementation
134 virtual void onFrameAvailable() {
135 ALOGV("Frame now available (start)");
136
137 Mutex::Autolock lock(mMutex);
138 mPendingFrames++;
139 mCondition.signal();
140
141 ALOGV("Frame now available (end)");
142 }
143
144 status_t waitForFrame(nsecs_t timeout) {
145 status_t res;
146 Mutex::Autolock lock(mMutex);
147 while (mPendingFrames == 0) {
148 res = mCondition.waitRelative(mMutex, timeout);
149 if (res != OK) return res;
150 }
151 mPendingFrames--;
152 return OK;
153 }
154
155 private:
156 Mutex mMutex;
157 Condition mCondition;
158 int mPendingFrames;
159 };
Igor Murashkine302ee32012-11-05 11:14:49 -0800160
161 void CreateStream() {
Eino-Ville Talvala4c543a12013-06-25 18:12:19 -0700162 sp<CameraDeviceBase> device = mDevice;
Igor Murashkine302ee32012-11-05 11:14:49 -0800163 CameraStreamParams p = mParam;
164
165 mCpuConsumer = new CpuConsumer(p.mHeapCount);
166 mCpuConsumer->setName(String8("CameraStreamTest::mCpuConsumer"));
167
Mathias Agopiancc501112013-02-14 17:34:35 -0800168 mNativeWindow = new Surface(
Igor Murashkine302ee32012-11-05 11:14:49 -0800169 mCpuConsumer->getProducerInterface());
170
Eino-Ville Talvala4c543a12013-06-25 18:12:19 -0700171 int format = MapAutoFormat(p.mFormat);
172
Igor Murashkine302ee32012-11-05 11:14:49 -0800173 ASSERT_EQ(OK,
174 device->createStream(mNativeWindow,
Eino-Ville Talvala4c543a12013-06-25 18:12:19 -0700175 mWidth, mHeight, format, /*size (for jpegs)*/0,
Igor Murashkine302ee32012-11-05 11:14:49 -0800176 &mStreamId));
177
178 ASSERT_NE(-1, mStreamId);
Igor Murashkinf1b9ae72012-12-07 15:08:35 -0800179
180 // do not make 'this' a FrameListener or the lifetime policy will clash
181 mFrameListener = new FrameListener();
182 mCpuConsumer->setFrameAvailableListener(mFrameListener);
Igor Murashkine302ee32012-11-05 11:14:49 -0800183 }
184
185 void DeleteStream() {
186 ASSERT_EQ(OK, mDevice->deleteStream(mStreamId));
187 }
188
Eino-Ville Talvala4c543a12013-06-25 18:12:19 -0700189 int MapAutoFormat(int format) {
190 if (format == CAMERA_STREAM_AUTO_CPU_FORMAT) {
191 if (getDeviceVersion() >= CAMERA_DEVICE_API_VERSION_3_0) {
192 format = HAL_PIXEL_FORMAT_YCbCr_420_888;
193 } else {
194 format = HAL_PIXEL_FORMAT_YCrCb_420_SP;
195 }
196 }
197 return format;
198 }
199
Eino-Ville Talvala7d831712013-07-01 18:47:09 -0700200 void DumpYuvToFile(const String8 &fileName, const CpuConsumer::LockedBuffer &img) {
201 uint8_t *dataCb, *dataCr;
202 uint32_t stride;
203 uint32_t chromaStride;
204 uint32_t chromaStep;
205
206 switch (img.format) {
207 case HAL_PIXEL_FORMAT_YCbCr_420_888:
208 stride = img.stride;
209 chromaStride = img.chromaStride;
210 chromaStep = img.chromaStep;
211 dataCb = img.dataCb;
212 dataCr = img.dataCr;
213 break;
214 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
215 stride = img.width;
216 chromaStride = img.width;
217 chromaStep = 2;
218 dataCr = img.data + img.width * img.height;
219 dataCb = dataCr + 1;
220 break;
221 case HAL_PIXEL_FORMAT_YV12:
222 stride = img.stride;
223 chromaStride = ALIGN(img.width / 2, 16);
224 chromaStep = 1;
225 dataCr = img.data + img.stride * img.height;
226 dataCb = dataCr + chromaStride * img.height/2;
227 break;
228 default:
229 ALOGE("Unknown format %d, not dumping", img.format);
230 return;
231 }
232
233 // Write Y
234 FILE *yuvFile = fopen(fileName.string(), "w");
235
236 size_t bytes;
237
238 for (size_t y = 0; y < img.height; ++y) {
239 bytes = fwrite(
240 reinterpret_cast<const char*>(img.data + stride * y),
241 1, img.width, yuvFile);
242 if (bytes != img.width) {
243 ALOGE("Unable to write to file %s", fileName.string());
244 fclose(yuvFile);
245 return;
246 }
247 }
248
249 // Write Cb/Cr
250 uint8_t *src = dataCb;
251 for (int c = 0; c < 2; ++c) {
252 for (size_t y = 0; y < img.height / 2; ++y) {
253 uint8_t *px = src + y * chromaStride;
254 if (chromaStep != 1) {
255 for (size_t x = 0; x < img.width / 2; ++x) {
256 fputc(*px, yuvFile);
257 px += chromaStep;
258 }
259 } else {
260 bytes = fwrite(reinterpret_cast<const char*>(px),
261 1, img.width / 2, yuvFile);
262 if (bytes != img.width / 2) {
263 ALOGE("Unable to write to file %s", fileName.string());
264 fclose(yuvFile);
265 return;
266 }
267 }
268 }
269 src = dataCr;
270 }
271 fclose(yuvFile);
272 }
273
Igor Murashkine302ee32012-11-05 11:14:49 -0800274 int mWidth;
275 int mHeight;
276
277 int mStreamId;
Igor Murashkinf1b9ae72012-12-07 15:08:35 -0800278
279 android::sp<FrameListener> mFrameListener;
Igor Murashkine302ee32012-11-05 11:14:49 -0800280 android::sp<CpuConsumer> mCpuConsumer;
281 android::sp<ANativeWindow> mNativeWindow;
282
Igor Murashkinf1b9ae72012-12-07 15:08:35 -0800283
Igor Murashkine302ee32012-11-05 11:14:49 -0800284private:
285 CameraStreamParams mParam;
286};
287
288}
289}
290}
291
Igor Murashkineab33fc2012-11-06 17:02:54 -0800292#endif