blob: 25b7a58413453a9eb79581542facd69c0b97c01c [file] [log] [blame]
Eino-Ville Talvala61ab9f92012-05-17 10:30:54 -07001/*
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
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -070017#define LOG_TAG "Camera2-Device"
18#define ATRACE_TAG ATRACE_TAG_CAMERA
Eino-Ville Talvala61ab9f92012-05-17 10:30:54 -070019//#define LOG_NDEBUG 0
Eino-Ville Talvala2c08dc62012-06-15 12:49:21 -070020//#define LOG_NNDEBUG 0 // Per-frame verbose logging
21
22#ifdef LOG_NNDEBUG
23#define ALOGVV(...) ALOGV(__VA_ARGS__)
24#else
25#define ALOGVV(...) ((void)0)
26#endif
Eino-Ville Talvala61ab9f92012-05-17 10:30:54 -070027
28#include <utils/Log.h>
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -070029#include <utils/Trace.h>
Eino-Ville Talvala61ab9f92012-05-17 10:30:54 -070030#include "Camera2Device.h"
31
32namespace android {
33
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -070034Camera2Device::Camera2Device(int id):
35 mId(id),
Eino-Ville Talvala61ab9f92012-05-17 10:30:54 -070036 mDevice(NULL)
37{
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -070038 ATRACE_CALL();
Eino-Ville Talvalac8474b62012-08-24 16:30:44 -070039 ALOGV("%s: Created device for camera %d", __FUNCTION__, id);
Eino-Ville Talvala61ab9f92012-05-17 10:30:54 -070040}
41
42Camera2Device::~Camera2Device()
43{
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -070044 ATRACE_CALL();
Igor Murashkinecf17e82012-10-02 16:05:11 -070045 ALOGV("%s: Tearing down for camera id %d", __FUNCTION__, mId);
Eino-Ville Talvala98bb82d2012-09-20 14:44:20 -070046 disconnect();
Eino-Ville Talvala61ab9f92012-05-17 10:30:54 -070047}
48
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -070049status_t Camera2Device::initialize(camera_module_t *module)
Eino-Ville Talvala61ab9f92012-05-17 10:30:54 -070050{
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -070051 ATRACE_CALL();
Eino-Ville Talvalac8474b62012-08-24 16:30:44 -070052 ALOGV("%s: Initializing device for camera %d", __FUNCTION__, mId);
Eino-Ville Talvala98bb82d2012-09-20 14:44:20 -070053 if (mDevice != NULL) {
54 ALOGE("%s: Already initialized!", __FUNCTION__);
55 return INVALID_OPERATION;
56 }
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -070057
Eino-Ville Talvala61ab9f92012-05-17 10:30:54 -070058 status_t res;
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -070059 char name[10];
60 snprintf(name, sizeof(name), "%d", mId);
61
Eino-Ville Talvala98bb82d2012-09-20 14:44:20 -070062 camera2_device_t *device;
63
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -070064 res = module->common.methods->open(&module->common, name,
Eino-Ville Talvala98bb82d2012-09-20 14:44:20 -070065 reinterpret_cast<hw_device_t**>(&device));
Eino-Ville Talvala61ab9f92012-05-17 10:30:54 -070066
67 if (res != OK) {
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -070068 ALOGE("%s: Could not open camera %d: %s (%d)", __FUNCTION__,
69 mId, strerror(-res), res);
Eino-Ville Talvala61ab9f92012-05-17 10:30:54 -070070 return res;
71 }
72
Eino-Ville Talvala98bb82d2012-09-20 14:44:20 -070073 if (device->common.version != CAMERA_DEVICE_API_VERSION_2_0) {
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -070074 ALOGE("%s: Could not open camera %d: "
75 "Camera device is not version %x, reports %x instead",
76 __FUNCTION__, mId, CAMERA_DEVICE_API_VERSION_2_0,
Eino-Ville Talvala98bb82d2012-09-20 14:44:20 -070077 device->common.version);
78 device->common.close(&device->common);
Eino-Ville Talvala61ab9f92012-05-17 10:30:54 -070079 return BAD_VALUE;
80 }
81
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -070082 camera_info info;
83 res = module->get_camera_info(mId, &info);
84 if (res != OK ) return res;
85
Eino-Ville Talvala98bb82d2012-09-20 14:44:20 -070086 if (info.device_version != device->common.version) {
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -070087 ALOGE("%s: HAL reporting mismatched camera_info version (%x)"
88 " and device version (%x).", __FUNCTION__,
Eino-Ville Talvala98bb82d2012-09-20 14:44:20 -070089 device->common.version, info.device_version);
90 device->common.close(&device->common);
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -070091 return BAD_VALUE;
92 }
93
Eino-Ville Talvala98bb82d2012-09-20 14:44:20 -070094 res = mRequestQueue.setConsumerDevice(device);
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -070095 if (res != OK) {
96 ALOGE("%s: Camera %d: Unable to connect request queue to device: %s (%d)",
97 __FUNCTION__, mId, strerror(-res), res);
Eino-Ville Talvala98bb82d2012-09-20 14:44:20 -070098 device->common.close(&device->common);
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -070099 return res;
100 }
Eino-Ville Talvala98bb82d2012-09-20 14:44:20 -0700101 res = mFrameQueue.setProducerDevice(device);
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700102 if (res != OK) {
103 ALOGE("%s: Camera %d: Unable to connect frame queue to device: %s (%d)",
104 __FUNCTION__, mId, strerror(-res), res);
Eino-Ville Talvala98bb82d2012-09-20 14:44:20 -0700105 device->common.close(&device->common);
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700106 return res;
107 }
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700108
Eino-Ville Talvala98bb82d2012-09-20 14:44:20 -0700109 res = device->ops->get_metadata_vendor_tag_ops(device, &mVendorTagOps);
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700110 if (res != OK ) {
111 ALOGE("%s: Camera %d: Unable to retrieve tag ops from device: %s (%d)",
112 __FUNCTION__, mId, strerror(-res), res);
Eino-Ville Talvala98bb82d2012-09-20 14:44:20 -0700113 device->common.close(&device->common);
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700114 return res;
115 }
Shuzhen Wang092fe442012-08-31 10:24:22 -0700116 res = set_camera_metadata_vendor_tag_ops(mVendorTagOps);
117 if (res != OK) {
118 ALOGE("%s: Camera %d: Unable to set tag ops: %s (%d)",
119 __FUNCTION__, mId, strerror(-res), res);
Eino-Ville Talvala98bb82d2012-09-20 14:44:20 -0700120 device->common.close(&device->common);
Shuzhen Wang092fe442012-08-31 10:24:22 -0700121 return res;
122 }
Eino-Ville Talvala98bb82d2012-09-20 14:44:20 -0700123 res = device->ops->set_notify_callback(device, notificationCallback,
124 NULL);
125 if (res != OK) {
126 ALOGE("%s: Camera %d: Unable to initialize notification callback!",
127 __FUNCTION__, mId);
128 device->common.close(&device->common);
129 return res;
130 }
131
132 mDeviceInfo = info.static_camera_characteristics;
133 mDevice = device;
Eino-Ville Talvala160d4af2012-08-03 09:40:16 -0700134
Eino-Ville Talvala61ab9f92012-05-17 10:30:54 -0700135 return OK;
136}
137
Eino-Ville Talvala98bb82d2012-09-20 14:44:20 -0700138status_t Camera2Device::disconnect() {
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -0700139 ATRACE_CALL();
Eino-Ville Talvala98bb82d2012-09-20 14:44:20 -0700140 status_t res = OK;
141 if (mDevice) {
142 ALOGV("%s: Closing device for camera %d", __FUNCTION__, mId);
143
144 int inProgressCount = mDevice->ops->get_in_progress_count(mDevice);
145 if (inProgressCount > 0) {
146 ALOGW("%s: Closing camera device %d with %d requests in flight!",
147 __FUNCTION__, mId, inProgressCount);
148 }
Eino-Ville Talvalac7d9afd2012-09-24 13:44:07 -0700149 mReprocessStreams.clear();
Eino-Ville Talvala98bb82d2012-09-20 14:44:20 -0700150 mStreams.clear();
151 res = mDevice->common.close(&mDevice->common);
152 if (res != OK) {
153 ALOGE("%s: Could not close camera %d: %s (%d)",
154 __FUNCTION__,
155 mId, strerror(-res), res);
156 }
157 mDevice = NULL;
158 ALOGV("%s: Shutdown complete", __FUNCTION__);
159 }
160 return res;
161}
162
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700163status_t Camera2Device::dump(int fd, const Vector<String16>& args) {
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -0700164 ATRACE_CALL();
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700165 String8 result;
Eino-Ville Talvala97197152012-08-06 14:25:19 -0700166 int detailLevel = 0;
167 int n = args.size();
168 String16 detailOption("-d");
169 for (int i = 0; i + 1 < n; i++) {
170 if (args[i] == detailOption) {
171 String8 levelStr(args[i+1]);
172 detailLevel = atoi(levelStr.string());
173 }
174 }
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700175
Eino-Ville Talvala603b12e2012-08-08 09:25:58 -0700176 result.appendFormat(" Camera2Device[%d] dump (detail level %d):\n",
177 mId, detailLevel);
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700178
Eino-Ville Talvala97197152012-08-06 14:25:19 -0700179 if (detailLevel > 0) {
180 result = " Request queue contents:\n";
181 write(fd, result.string(), result.size());
182 mRequestQueue.dump(fd, args);
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700183
Eino-Ville Talvala97197152012-08-06 14:25:19 -0700184 result = " Frame queue contents:\n";
185 write(fd, result.string(), result.size());
186 mFrameQueue.dump(fd, args);
187 }
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700188
189 result = " Active streams:\n";
190 write(fd, result.string(), result.size());
191 for (StreamList::iterator s = mStreams.begin(); s != mStreams.end(); s++) {
192 (*s)->dump(fd, args);
193 }
194
195 result = " HAL device dump:\n";
196 write(fd, result.string(), result.size());
197
198 status_t res;
199 res = mDevice->ops->dump(mDevice, fd);
200
201 return res;
202}
203
Eino-Ville Talvala2e19c3c2012-08-26 09:29:28 -0700204const camera2::CameraMetadata& Camera2Device::info() const {
Eino-Ville Talvala9e4c3db2012-07-20 11:07:52 -0700205 ALOGVV("%s: E", __FUNCTION__);
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700206
207 return mDeviceInfo;
208}
209
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700210status_t Camera2Device::capture(CameraMetadata &request) {
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -0700211 ATRACE_CALL();
Eino-Ville Talvalad4bcfde2012-06-07 17:12:38 -0700212 ALOGV("%s: E", __FUNCTION__);
213
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700214 mRequestQueue.enqueue(request.release());
Eino-Ville Talvalad4bcfde2012-06-07 17:12:38 -0700215 return OK;
216}
217
218
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700219status_t Camera2Device::setStreamingRequest(const CameraMetadata &request) {
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -0700220 ATRACE_CALL();
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700221 ALOGV("%s: E", __FUNCTION__);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700222 CameraMetadata streamRequest(request);
223 return mRequestQueue.setStreamSlot(streamRequest.release());
224}
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700225
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700226status_t Camera2Device::clearStreamingRequest() {
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -0700227 ATRACE_CALL();
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700228 return mRequestQueue.setStreamSlot(NULL);
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700229}
230
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700231status_t Camera2Device::createStream(sp<ANativeWindow> consumer,
Eino-Ville Talvalad4bcfde2012-06-07 17:12:38 -0700232 uint32_t width, uint32_t height, int format, size_t size, int *id) {
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -0700233 ATRACE_CALL();
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700234 status_t res;
235 ALOGV("%s: E", __FUNCTION__);
236
237 sp<StreamAdapter> stream = new StreamAdapter(mDevice);
238
Eino-Ville Talvalad4bcfde2012-06-07 17:12:38 -0700239 res = stream->connectToDevice(consumer, width, height, format, size);
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700240 if (res != OK) {
241 ALOGE("%s: Camera %d: Unable to create stream (%d x %d, format %x):"
242 "%s (%d)",
243 __FUNCTION__, mId, width, height, format, strerror(-res), res);
244 return res;
245 }
246
247 *id = stream->getId();
248
249 mStreams.push_back(stream);
250 return OK;
251}
252
Eino-Ville Talvalada6665c2012-08-29 17:37:16 -0700253status_t Camera2Device::createReprocessStreamFromStream(int outputId, int *id) {
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -0700254 ATRACE_CALL();
Eino-Ville Talvalada6665c2012-08-29 17:37:16 -0700255 status_t res;
256 ALOGV("%s: E", __FUNCTION__);
257
258 bool found = false;
259 StreamList::iterator streamI;
260 for (streamI = mStreams.begin();
261 streamI != mStreams.end(); streamI++) {
262 if ((*streamI)->getId() == outputId) {
263 found = true;
264 break;
265 }
266 }
267 if (!found) {
268 ALOGE("%s: Camera %d: Output stream %d doesn't exist; can't create "
269 "reprocess stream from it!", __FUNCTION__, mId, outputId);
270 return BAD_VALUE;
271 }
272
273 sp<ReprocessStreamAdapter> stream = new ReprocessStreamAdapter(mDevice);
274
275 res = stream->connectToDevice((*streamI));
276 if (res != OK) {
277 ALOGE("%s: Camera %d: Unable to create reprocessing stream from "\
278 "stream %d: %s (%d)", __FUNCTION__, mId, outputId,
279 strerror(-res), res);
280 return res;
281 }
282
283 *id = stream->getId();
284
285 mReprocessStreams.push_back(stream);
286 return OK;
287}
288
289
Eino-Ville Talvalad4bcfde2012-06-07 17:12:38 -0700290status_t Camera2Device::getStreamInfo(int id,
291 uint32_t *width, uint32_t *height, uint32_t *format) {
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -0700292 ATRACE_CALL();
Eino-Ville Talvalad4bcfde2012-06-07 17:12:38 -0700293 ALOGV("%s: E", __FUNCTION__);
294 bool found = false;
295 StreamList::iterator streamI;
296 for (streamI = mStreams.begin();
297 streamI != mStreams.end(); streamI++) {
298 if ((*streamI)->getId() == id) {
299 found = true;
300 break;
301 }
302 }
303 if (!found) {
304 ALOGE("%s: Camera %d: Stream %d does not exist",
305 __FUNCTION__, mId, id);
306 return BAD_VALUE;
307 }
308
309 if (width) *width = (*streamI)->getWidth();
310 if (height) *height = (*streamI)->getHeight();
311 if (format) *format = (*streamI)->getFormat();
312
313 return OK;
314}
315
Eino-Ville Talvalac94cd192012-06-15 12:47:42 -0700316status_t Camera2Device::setStreamTransform(int id,
317 int transform) {
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -0700318 ATRACE_CALL();
Eino-Ville Talvalac94cd192012-06-15 12:47:42 -0700319 ALOGV("%s: E", __FUNCTION__);
320 bool found = false;
321 StreamList::iterator streamI;
322 for (streamI = mStreams.begin();
323 streamI != mStreams.end(); streamI++) {
324 if ((*streamI)->getId() == id) {
325 found = true;
326 break;
327 }
328 }
329 if (!found) {
330 ALOGE("%s: Camera %d: Stream %d does not exist",
331 __FUNCTION__, mId, id);
332 return BAD_VALUE;
333 }
334
335 return (*streamI)->setTransform(transform);
336}
337
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700338status_t Camera2Device::deleteStream(int id) {
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -0700339 ATRACE_CALL();
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700340 ALOGV("%s: E", __FUNCTION__);
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700341 bool found = false;
342 for (StreamList::iterator streamI = mStreams.begin();
343 streamI != mStreams.end(); streamI++) {
344 if ((*streamI)->getId() == id) {
Eino-Ville Talvala9cca4c62012-06-15 15:41:44 -0700345 status_t res = (*streamI)->release();
Eino-Ville Talvala4ecfec32012-06-12 17:13:48 -0700346 if (res != OK) {
Eino-Ville Talvala9cca4c62012-06-15 15:41:44 -0700347 ALOGE("%s: Unable to release stream %d from HAL device: "
Eino-Ville Talvala4ecfec32012-06-12 17:13:48 -0700348 "%s (%d)", __FUNCTION__, id, strerror(-res), res);
349 return res;
350 }
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700351 mStreams.erase(streamI);
352 found = true;
353 break;
354 }
355 }
356 if (!found) {
357 ALOGE("%s: Camera %d: Unable to find stream %d to delete",
358 __FUNCTION__, mId, id);
359 return BAD_VALUE;
360 }
361 return OK;
362}
363
Eino-Ville Talvalada6665c2012-08-29 17:37:16 -0700364status_t Camera2Device::deleteReprocessStream(int id) {
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -0700365 ATRACE_CALL();
Eino-Ville Talvalada6665c2012-08-29 17:37:16 -0700366 ALOGV("%s: E", __FUNCTION__);
367 bool found = false;
368 for (ReprocessStreamList::iterator streamI = mReprocessStreams.begin();
369 streamI != mReprocessStreams.end(); streamI++) {
370 if ((*streamI)->getId() == id) {
371 status_t res = (*streamI)->release();
372 if (res != OK) {
373 ALOGE("%s: Unable to release reprocess stream %d from "
374 "HAL device: %s (%d)", __FUNCTION__, id,
375 strerror(-res), res);
376 return res;
377 }
378 mReprocessStreams.erase(streamI);
379 found = true;
380 break;
381 }
382 }
383 if (!found) {
384 ALOGE("%s: Camera %d: Unable to find stream %d to delete",
385 __FUNCTION__, mId, id);
386 return BAD_VALUE;
387 }
388 return OK;
389}
390
391
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700392status_t Camera2Device::createDefaultRequest(int templateId,
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700393 CameraMetadata *request) {
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -0700394 ATRACE_CALL();
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700395 status_t err;
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700396 ALOGV("%s: E", __FUNCTION__);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700397 camera_metadata_t *rawRequest;
398 err = mDevice->ops->construct_default_request(
399 mDevice, templateId, &rawRequest);
400 request->acquire(rawRequest);
401 return err;
Eino-Ville Talvalad4bcfde2012-06-07 17:12:38 -0700402}
403
404status_t Camera2Device::waitUntilDrained() {
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -0700405 ATRACE_CALL();
Eino-Ville Talvalad4bcfde2012-06-07 17:12:38 -0700406 static const uint32_t kSleepTime = 50000; // 50 ms
407 static const uint32_t kMaxSleepTime = 10000000; // 10 s
Eino-Ville Talvala98bb82d2012-09-20 14:44:20 -0700408 ALOGV("%s: Camera %d: Starting wait", __FUNCTION__, mId);
Eino-Ville Talvalad4bcfde2012-06-07 17:12:38 -0700409 if (mRequestQueue.getBufferCount() ==
410 CAMERA2_REQUEST_QUEUE_IS_BOTTOMLESS) return INVALID_OPERATION;
411
412 // TODO: Set up notifications from HAL, instead of sleeping here
413 uint32_t totalTime = 0;
414 while (mDevice->ops->get_in_progress_count(mDevice) > 0) {
415 usleep(kSleepTime);
416 totalTime += kSleepTime;
417 if (totalTime > kMaxSleepTime) {
Eino-Ville Talvala98bb82d2012-09-20 14:44:20 -0700418 ALOGE("%s: Waited %d us, %d requests still in flight", __FUNCTION__,
419 mDevice->ops->get_in_progress_count(mDevice), totalTime);
Eino-Ville Talvalad4bcfde2012-06-07 17:12:38 -0700420 return TIMED_OUT;
421 }
422 }
Eino-Ville Talvala98bb82d2012-09-20 14:44:20 -0700423 ALOGV("%s: Camera %d: HAL is idle", __FUNCTION__, mId);
Eino-Ville Talvalad4bcfde2012-06-07 17:12:38 -0700424 return OK;
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700425}
426
Eino-Ville Talvala160d4af2012-08-03 09:40:16 -0700427status_t Camera2Device::setNotifyCallback(NotificationListener *listener) {
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -0700428 ATRACE_CALL();
Eino-Ville Talvala160d4af2012-08-03 09:40:16 -0700429 status_t res;
430 res = mDevice->ops->set_notify_callback(mDevice, notificationCallback,
431 reinterpret_cast<void*>(listener) );
432 if (res != OK) {
433 ALOGE("%s: Unable to set notification callback!", __FUNCTION__);
434 }
435 return res;
436}
437
438void Camera2Device::notificationCallback(int32_t msg_type,
439 int32_t ext1,
440 int32_t ext2,
441 int32_t ext3,
442 void *user) {
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -0700443 ATRACE_CALL();
Eino-Ville Talvala160d4af2012-08-03 09:40:16 -0700444 NotificationListener *listener = reinterpret_cast<NotificationListener*>(user);
445 ALOGV("%s: Notification %d, arguments %d, %d, %d", __FUNCTION__, msg_type,
446 ext1, ext2, ext3);
447 if (listener != NULL) {
448 switch (msg_type) {
449 case CAMERA2_MSG_ERROR:
450 listener->notifyError(ext1, ext2, ext3);
451 break;
452 case CAMERA2_MSG_SHUTTER: {
453 nsecs_t timestamp = (nsecs_t)ext2 | ((nsecs_t)(ext3) << 32 );
454 listener->notifyShutter(ext1, timestamp);
455 break;
456 }
457 case CAMERA2_MSG_AUTOFOCUS:
458 listener->notifyAutoFocus(ext1, ext2);
459 break;
460 case CAMERA2_MSG_AUTOEXPOSURE:
461 listener->notifyAutoExposure(ext1, ext2);
462 break;
463 case CAMERA2_MSG_AUTOWB:
464 listener->notifyAutoWhitebalance(ext1, ext2);
465 break;
466 default:
467 ALOGE("%s: Unknown notification %d (arguments %d, %d, %d)!",
468 __FUNCTION__, msg_type, ext1, ext2, ext3);
469 }
470 }
471}
472
Eino-Ville Talvalac8474b62012-08-24 16:30:44 -0700473status_t Camera2Device::waitForNextFrame(nsecs_t timeout) {
474 return mFrameQueue.waitForBuffer(timeout);
Eino-Ville Talvala8ce89d92012-08-10 08:40:26 -0700475}
476
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700477status_t Camera2Device::getNextFrame(CameraMetadata *frame) {
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -0700478 ATRACE_CALL();
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700479 status_t res;
480 camera_metadata_t *rawFrame;
481 res = mFrameQueue.dequeue(&rawFrame);
482 if (rawFrame == NULL) {
483 return NOT_ENOUGH_DATA;
484 } else if (res == OK) {
485 frame->acquire(rawFrame);
486 }
487 return res;
Eino-Ville Talvala8ce89d92012-08-10 08:40:26 -0700488}
489
Eino-Ville Talvala174181e2012-08-03 13:53:39 -0700490status_t Camera2Device::triggerAutofocus(uint32_t id) {
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -0700491 ATRACE_CALL();
Eino-Ville Talvala174181e2012-08-03 13:53:39 -0700492 status_t res;
493 ALOGV("%s: Triggering autofocus, id %d", __FUNCTION__, id);
494 res = mDevice->ops->trigger_action(mDevice,
495 CAMERA2_TRIGGER_AUTOFOCUS, id, 0);
496 if (res != OK) {
497 ALOGE("%s: Error triggering autofocus (id %d)",
498 __FUNCTION__, id);
499 }
500 return res;
501}
502
503status_t Camera2Device::triggerCancelAutofocus(uint32_t id) {
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -0700504 ATRACE_CALL();
Eino-Ville Talvala174181e2012-08-03 13:53:39 -0700505 status_t res;
506 ALOGV("%s: Canceling autofocus, id %d", __FUNCTION__, id);
507 res = mDevice->ops->trigger_action(mDevice,
508 CAMERA2_TRIGGER_CANCEL_AUTOFOCUS, id, 0);
509 if (res != OK) {
510 ALOGE("%s: Error canceling autofocus (id %d)",
511 __FUNCTION__, id);
512 }
513 return res;
514}
515
516status_t Camera2Device::triggerPrecaptureMetering(uint32_t id) {
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -0700517 ATRACE_CALL();
Eino-Ville Talvala174181e2012-08-03 13:53:39 -0700518 status_t res;
519 ALOGV("%s: Triggering precapture metering, id %d", __FUNCTION__, id);
520 res = mDevice->ops->trigger_action(mDevice,
521 CAMERA2_TRIGGER_PRECAPTURE_METERING, id, 0);
522 if (res != OK) {
523 ALOGE("%s: Error triggering precapture metering (id %d)",
524 __FUNCTION__, id);
525 }
526 return res;
527}
528
Eino-Ville Talvalada6665c2012-08-29 17:37:16 -0700529status_t Camera2Device::pushReprocessBuffer(int reprocessStreamId,
530 buffer_handle_t *buffer, wp<BufferReleasedListener> listener) {
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -0700531 ATRACE_CALL();
Eino-Ville Talvalada6665c2012-08-29 17:37:16 -0700532 ALOGV("%s: E", __FUNCTION__);
533 bool found = false;
534 status_t res = OK;
535 for (ReprocessStreamList::iterator streamI = mReprocessStreams.begin();
536 streamI != mReprocessStreams.end(); streamI++) {
537 if ((*streamI)->getId() == reprocessStreamId) {
538 res = (*streamI)->pushIntoStream(buffer, listener);
539 if (res != OK) {
540 ALOGE("%s: Unable to push buffer to reprocess stream %d: %s (%d)",
541 __FUNCTION__, reprocessStreamId, strerror(-res), res);
542 return res;
543 }
544 found = true;
545 break;
546 }
547 }
548 if (!found) {
549 ALOGE("%s: Camera %d: Unable to find reprocess stream %d",
550 __FUNCTION__, mId, reprocessStreamId);
551 res = BAD_VALUE;
552 }
553 return res;
554}
555
Eino-Ville Talvala160d4af2012-08-03 09:40:16 -0700556/**
557 * Camera2Device::NotificationListener
558 */
559
560Camera2Device::NotificationListener::~NotificationListener() {
561}
562
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700563/**
564 * Camera2Device::MetadataQueue
565 */
566
567Camera2Device::MetadataQueue::MetadataQueue():
568 mDevice(NULL),
569 mFrameCount(0),
570 mCount(0),
571 mStreamSlotCount(0),
Eino-Ville Talvalac8474b62012-08-24 16:30:44 -0700572 mSignalConsumer(true)
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700573{
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -0700574 ATRACE_CALL();
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700575 camera2_request_queue_src_ops::dequeue_request = consumer_dequeue;
576 camera2_request_queue_src_ops::request_count = consumer_buffer_count;
577 camera2_request_queue_src_ops::free_request = consumer_free;
578
579 camera2_frame_queue_dst_ops::dequeue_frame = producer_dequeue;
580 camera2_frame_queue_dst_ops::cancel_frame = producer_cancel;
581 camera2_frame_queue_dst_ops::enqueue_frame = producer_enqueue;
582}
583
584Camera2Device::MetadataQueue::~MetadataQueue() {
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -0700585 ATRACE_CALL();
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700586 Mutex::Autolock l(mMutex);
587 freeBuffers(mEntries.begin(), mEntries.end());
588 freeBuffers(mStreamSlot.begin(), mStreamSlot.end());
589}
590
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700591// Connect to camera2 HAL as consumer (input requests/reprocessing)
592status_t Camera2Device::MetadataQueue::setConsumerDevice(camera2_device_t *d) {
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -0700593 ATRACE_CALL();
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700594 status_t res;
595 res = d->ops->set_request_queue_src_ops(d,
596 this);
597 if (res != OK) return res;
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700598 mDevice = d;
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700599 return OK;
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700600}
601
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700602status_t Camera2Device::MetadataQueue::setProducerDevice(camera2_device_t *d) {
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -0700603 ATRACE_CALL();
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700604 status_t res;
605 res = d->ops->set_frame_queue_dst_ops(d,
606 this);
607 return res;
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700608}
609
610// Real interfaces
611status_t Camera2Device::MetadataQueue::enqueue(camera_metadata_t *buf) {
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -0700612 ATRACE_CALL();
Eino-Ville Talvala2c08dc62012-06-15 12:49:21 -0700613 ALOGVV("%s: E", __FUNCTION__);
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700614 Mutex::Autolock l(mMutex);
615
616 mCount++;
617 mEntries.push_back(buf);
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700618
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700619 return signalConsumerLocked();
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700620}
621
622int Camera2Device::MetadataQueue::getBufferCount() {
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -0700623 ATRACE_CALL();
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700624 Mutex::Autolock l(mMutex);
625 if (mStreamSlotCount > 0) {
626 return CAMERA2_REQUEST_QUEUE_IS_BOTTOMLESS;
627 }
628 return mCount;
629}
630
631status_t Camera2Device::MetadataQueue::dequeue(camera_metadata_t **buf,
632 bool incrementCount)
633{
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -0700634 ATRACE_CALL();
Eino-Ville Talvala2c08dc62012-06-15 12:49:21 -0700635 ALOGVV("%s: E", __FUNCTION__);
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700636 status_t res;
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700637 Mutex::Autolock l(mMutex);
638
639 if (mCount == 0) {
640 if (mStreamSlotCount == 0) {
Eino-Ville Talvala2c08dc62012-06-15 12:49:21 -0700641 ALOGVV("%s: Empty", __FUNCTION__);
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700642 *buf = NULL;
643 mSignalConsumer = true;
644 return OK;
645 }
Eino-Ville Talvala2c08dc62012-06-15 12:49:21 -0700646 ALOGVV("%s: Streaming %d frames to queue", __FUNCTION__,
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700647 mStreamSlotCount);
648
649 for (List<camera_metadata_t*>::iterator slotEntry = mStreamSlot.begin();
650 slotEntry != mStreamSlot.end();
651 slotEntry++ ) {
652 size_t entries = get_camera_metadata_entry_count(*slotEntry);
653 size_t dataBytes = get_camera_metadata_data_count(*slotEntry);
654
655 camera_metadata_t *copy =
656 allocate_camera_metadata(entries, dataBytes);
657 append_camera_metadata(copy, *slotEntry);
658 mEntries.push_back(copy);
659 }
660 mCount = mStreamSlotCount;
661 }
Eino-Ville Talvala2c08dc62012-06-15 12:49:21 -0700662 ALOGVV("MetadataQueue: deque (%d buffers)", mCount);
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700663 camera_metadata_t *b = *(mEntries.begin());
664 mEntries.erase(mEntries.begin());
665
666 if (incrementCount) {
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -0700667 ATRACE_INT("cam2_request", mFrameCount);
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700668 camera_metadata_entry_t frameCount;
669 res = find_camera_metadata_entry(b,
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700670 ANDROID_REQUEST_FRAME_COUNT,
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700671 &frameCount);
672 if (res != OK) {
673 ALOGE("%s: Unable to add frame count: %s (%d)",
674 __FUNCTION__, strerror(-res), res);
675 } else {
676 *frameCount.data.i32 = mFrameCount;
677 }
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700678 mFrameCount++;
679 }
680
681 *buf = b;
682 mCount--;
683
684 return OK;
685}
686
687status_t Camera2Device::MetadataQueue::waitForBuffer(nsecs_t timeout)
688{
689 Mutex::Autolock l(mMutex);
690 status_t res;
691 while (mCount == 0) {
692 res = notEmpty.waitRelative(mMutex,timeout);
693 if (res != OK) return res;
694 }
695 return OK;
696}
697
698status_t Camera2Device::MetadataQueue::setStreamSlot(camera_metadata_t *buf)
699{
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -0700700 ATRACE_CALL();
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700701 ALOGV("%s: E", __FUNCTION__);
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700702 Mutex::Autolock l(mMutex);
703 if (buf == NULL) {
704 freeBuffers(mStreamSlot.begin(), mStreamSlot.end());
705 mStreamSlotCount = 0;
706 return OK;
707 }
Eino-Ville Talvala6ed1ed12012-06-07 10:46:38 -0700708 camera_metadata_t *buf2 = clone_camera_metadata(buf);
709 if (!buf2) {
710 ALOGE("%s: Unable to clone metadata buffer!", __FUNCTION__);
711 return NO_MEMORY;
712 }
713
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700714 if (mStreamSlotCount > 1) {
715 List<camera_metadata_t*>::iterator deleter = ++mStreamSlot.begin();
716 freeBuffers(++mStreamSlot.begin(), mStreamSlot.end());
717 mStreamSlotCount = 1;
718 }
719 if (mStreamSlotCount == 1) {
720 free_camera_metadata( *(mStreamSlot.begin()) );
Eino-Ville Talvala6ed1ed12012-06-07 10:46:38 -0700721 *(mStreamSlot.begin()) = buf2;
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700722 } else {
Eino-Ville Talvala6ed1ed12012-06-07 10:46:38 -0700723 mStreamSlot.push_front(buf2);
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700724 mStreamSlotCount = 1;
725 }
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700726 return signalConsumerLocked();
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700727}
728
729status_t Camera2Device::MetadataQueue::setStreamSlot(
730 const List<camera_metadata_t*> &bufs)
731{
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -0700732 ATRACE_CALL();
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700733 ALOGV("%s: E", __FUNCTION__);
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700734 Mutex::Autolock l(mMutex);
Eino-Ville Talvala6ed1ed12012-06-07 10:46:38 -0700735 status_t res;
736
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700737 if (mStreamSlotCount > 0) {
738 freeBuffers(mStreamSlot.begin(), mStreamSlot.end());
739 }
Eino-Ville Talvala6ed1ed12012-06-07 10:46:38 -0700740 mStreamSlotCount = 0;
741 for (List<camera_metadata_t*>::const_iterator r = bufs.begin();
742 r != bufs.end(); r++) {
743 camera_metadata_t *r2 = clone_camera_metadata(*r);
744 if (!r2) {
745 ALOGE("%s: Unable to clone metadata buffer!", __FUNCTION__);
746 return NO_MEMORY;
747 }
748 mStreamSlot.push_back(r2);
749 mStreamSlotCount++;
750 }
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700751 return signalConsumerLocked();
752}
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700753
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700754status_t Camera2Device::MetadataQueue::dump(int fd,
755 const Vector<String16>& args) {
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -0700756 ATRACE_CALL();
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700757 String8 result;
758 status_t notLocked;
759 notLocked = mMutex.tryLock();
760 if (notLocked) {
761 result.append(" (Unable to lock queue mutex)\n");
762 }
763 result.appendFormat(" Current frame number: %d\n", mFrameCount);
764 if (mStreamSlotCount == 0) {
765 result.append(" Stream slot: Empty\n");
766 write(fd, result.string(), result.size());
767 } else {
768 result.appendFormat(" Stream slot: %d entries\n",
769 mStreamSlot.size());
770 int i = 0;
771 for (List<camera_metadata_t*>::iterator r = mStreamSlot.begin();
772 r != mStreamSlot.end(); r++) {
773 result = String8::format(" Stream slot buffer %d:\n", i);
774 write(fd, result.string(), result.size());
Eino-Ville Talvala428b77a2012-07-30 09:55:30 -0700775 dump_indented_camera_metadata(*r, fd, 2, 10);
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700776 i++;
777 }
778 }
779 if (mEntries.size() == 0) {
780 result = " Main queue is empty\n";
781 write(fd, result.string(), result.size());
782 } else {
783 result = String8::format(" Main queue has %d entries:\n",
784 mEntries.size());
785 int i = 0;
786 for (List<camera_metadata_t*>::iterator r = mEntries.begin();
787 r != mEntries.end(); r++) {
788 result = String8::format(" Queue entry %d:\n", i);
789 write(fd, result.string(), result.size());
Eino-Ville Talvala428b77a2012-07-30 09:55:30 -0700790 dump_indented_camera_metadata(*r, fd, 2, 10);
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700791 i++;
792 }
793 }
794
795 if (notLocked == 0) {
796 mMutex.unlock();
797 }
798
799 return OK;
800}
801
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700802status_t Camera2Device::MetadataQueue::signalConsumerLocked() {
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -0700803 ATRACE_CALL();
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700804 status_t res = OK;
805 notEmpty.signal();
806 if (mSignalConsumer && mDevice != NULL) {
807 mSignalConsumer = false;
808
809 mMutex.unlock();
810 ALOGV("%s: Signaling consumer", __FUNCTION__);
811 res = mDevice->ops->notify_request_queue_not_empty(mDevice);
812 mMutex.lock();
813 }
814 return res;
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700815}
816
817status_t Camera2Device::MetadataQueue::freeBuffers(
818 List<camera_metadata_t*>::iterator start,
819 List<camera_metadata_t*>::iterator end)
820{
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -0700821 ATRACE_CALL();
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700822 while (start != end) {
823 free_camera_metadata(*start);
824 start = mStreamSlot.erase(start);
825 }
826 return OK;
827}
828
829Camera2Device::MetadataQueue* Camera2Device::MetadataQueue::getInstance(
830 const camera2_request_queue_src_ops_t *q)
831{
832 const MetadataQueue* cmq = static_cast<const MetadataQueue*>(q);
833 return const_cast<MetadataQueue*>(cmq);
834}
835
836Camera2Device::MetadataQueue* Camera2Device::MetadataQueue::getInstance(
837 const camera2_frame_queue_dst_ops_t *q)
838{
839 const MetadataQueue* cmq = static_cast<const MetadataQueue*>(q);
840 return const_cast<MetadataQueue*>(cmq);
841}
842
843int Camera2Device::MetadataQueue::consumer_buffer_count(
844 const camera2_request_queue_src_ops_t *q)
845{
846 MetadataQueue *queue = getInstance(q);
847 return queue->getBufferCount();
848}
849
850int Camera2Device::MetadataQueue::consumer_dequeue(
851 const camera2_request_queue_src_ops_t *q,
852 camera_metadata_t **buffer)
853{
854 MetadataQueue *queue = getInstance(q);
855 return queue->dequeue(buffer, true);
856}
857
858int Camera2Device::MetadataQueue::consumer_free(
859 const camera2_request_queue_src_ops_t *q,
860 camera_metadata_t *old_buffer)
861{
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -0700862 ATRACE_CALL();
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700863 MetadataQueue *queue = getInstance(q);
864 free_camera_metadata(old_buffer);
865 return OK;
866}
867
868int Camera2Device::MetadataQueue::producer_dequeue(
869 const camera2_frame_queue_dst_ops_t *q,
870 size_t entries, size_t bytes,
871 camera_metadata_t **buffer)
872{
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -0700873 ATRACE_CALL();
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700874 camera_metadata_t *new_buffer =
875 allocate_camera_metadata(entries, bytes);
876 if (new_buffer == NULL) return NO_MEMORY;
877 *buffer = new_buffer;
878 return OK;
879}
880
881int Camera2Device::MetadataQueue::producer_cancel(
882 const camera2_frame_queue_dst_ops_t *q,
883 camera_metadata_t *old_buffer)
884{
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -0700885 ATRACE_CALL();
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -0700886 free_camera_metadata(old_buffer);
887 return OK;
888}
889
890int Camera2Device::MetadataQueue::producer_enqueue(
891 const camera2_frame_queue_dst_ops_t *q,
892 camera_metadata_t *filled_buffer)
893{
894 MetadataQueue *queue = getInstance(q);
895 return queue->enqueue(filled_buffer);
896}
897
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700898/**
899 * Camera2Device::StreamAdapter
900 */
901
902#ifndef container_of
903#define container_of(ptr, type, member) \
904 (type *)((char*)(ptr) - offsetof(type, member))
905#endif
906
907Camera2Device::StreamAdapter::StreamAdapter(camera2_device_t *d):
Eino-Ville Talvala9cca4c62012-06-15 15:41:44 -0700908 mState(RELEASED),
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700909 mDevice(d),
910 mId(-1),
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -0700911 mWidth(0), mHeight(0), mFormat(0), mSize(0), mUsage(0),
912 mMaxProducerBuffers(0), mMaxConsumerBuffers(0),
913 mTotalBuffers(0),
914 mFormatRequested(0),
915 mActiveBuffers(0),
916 mFrameCount(0),
917 mLastTimestamp(0)
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700918{
919 camera2_stream_ops::dequeue_buffer = dequeue_buffer;
920 camera2_stream_ops::enqueue_buffer = enqueue_buffer;
921 camera2_stream_ops::cancel_buffer = cancel_buffer;
922 camera2_stream_ops::set_crop = set_crop;
923}
924
925Camera2Device::StreamAdapter::~StreamAdapter() {
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -0700926 ATRACE_CALL();
Eino-Ville Talvala9cca4c62012-06-15 15:41:44 -0700927 if (mState != RELEASED) {
928 release();
929 }
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700930}
931
Eino-Ville Talvalad4bcfde2012-06-07 17:12:38 -0700932status_t Camera2Device::StreamAdapter::connectToDevice(
933 sp<ANativeWindow> consumer,
934 uint32_t width, uint32_t height, int format, size_t size) {
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -0700935 ATRACE_CALL();
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700936 status_t res;
Eino-Ville Talvala9e4c3db2012-07-20 11:07:52 -0700937 ALOGV("%s: E", __FUNCTION__);
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700938
Eino-Ville Talvala9cca4c62012-06-15 15:41:44 -0700939 if (mState != RELEASED) return INVALID_OPERATION;
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700940 if (consumer == NULL) {
941 ALOGE("%s: Null consumer passed to stream adapter", __FUNCTION__);
942 return BAD_VALUE;
943 }
944
Eino-Ville Talvala9cca4c62012-06-15 15:41:44 -0700945 ALOGV("%s: New stream parameters %d x %d, format 0x%x, size %d",
946 __FUNCTION__, width, height, format, size);
947
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700948 mConsumerInterface = consumer;
949 mWidth = width;
950 mHeight = height;
Eino-Ville Talvalad4bcfde2012-06-07 17:12:38 -0700951 mSize = (format == HAL_PIXEL_FORMAT_BLOB) ? size : 0;
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700952 mFormatRequested = format;
953
954 // Allocate device-side stream interface
955
956 uint32_t id;
957 uint32_t formatActual;
958 uint32_t usage;
959 uint32_t maxBuffers = 2;
960 res = mDevice->ops->allocate_stream(mDevice,
961 mWidth, mHeight, mFormatRequested, getStreamOps(),
962 &id, &formatActual, &usage, &maxBuffers);
963 if (res != OK) {
964 ALOGE("%s: Device stream allocation failed: %s (%d)",
965 __FUNCTION__, strerror(-res), res);
966 return res;
967 }
968
Eino-Ville Talvala9cca4c62012-06-15 15:41:44 -0700969 ALOGV("%s: Allocated stream id %d, actual format 0x%x, "
970 "usage 0x%x, producer wants %d buffers", __FUNCTION__,
971 id, formatActual, usage, maxBuffers);
972
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -0700973 mId = id;
974 mFormat = formatActual;
975 mUsage = usage;
976 mMaxProducerBuffers = maxBuffers;
977
978 mState = ALLOCATED;
979
980 // Configure consumer-side ANativeWindow interface
981 res = native_window_api_connect(mConsumerInterface.get(),
982 NATIVE_WINDOW_API_CAMERA);
983 if (res != OK) {
984 ALOGE("%s: Unable to connect to native window for stream %d",
985 __FUNCTION__, mId);
986
987 return res;
988 }
989
990 mState = CONNECTED;
991
992 res = native_window_set_usage(mConsumerInterface.get(), mUsage);
993 if (res != OK) {
994 ALOGE("%s: Unable to configure usage %08x for stream %d",
995 __FUNCTION__, mUsage, mId);
996 return res;
997 }
998
Eino-Ville Talvalabd4976a2012-06-07 10:40:25 -0700999 res = native_window_set_scaling_mode(mConsumerInterface.get(),
1000 NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
1001 if (res != OK) {
1002 ALOGE("%s: Unable to configure stream scaling: %s (%d)",
1003 __FUNCTION__, strerror(-res), res);
1004 return res;
1005 }
1006
Eino-Ville Talvalac94cd192012-06-15 12:47:42 -07001007 res = setTransform(0);
Eino-Ville Talvalabd4976a2012-06-07 10:40:25 -07001008 if (res != OK) {
Eino-Ville Talvalabd4976a2012-06-07 10:40:25 -07001009 return res;
1010 }
1011
Eino-Ville Talvalad4bcfde2012-06-07 17:12:38 -07001012 if (mFormat == HAL_PIXEL_FORMAT_BLOB) {
1013 res = native_window_set_buffers_geometry(mConsumerInterface.get(),
1014 mSize, 1, mFormat);
1015 if (res != OK) {
1016 ALOGE("%s: Unable to configure compressed stream buffer geometry"
1017 " %d x %d, size %d for stream %d",
1018 __FUNCTION__, mWidth, mHeight, mSize, mId);
1019 return res;
1020 }
1021 } else {
1022 res = native_window_set_buffers_geometry(mConsumerInterface.get(),
1023 mWidth, mHeight, mFormat);
1024 if (res != OK) {
1025 ALOGE("%s: Unable to configure stream buffer geometry"
1026 " %d x %d, format 0x%x for stream %d",
1027 __FUNCTION__, mWidth, mHeight, mFormat, mId);
1028 return res;
1029 }
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -07001030 }
1031
1032 int maxConsumerBuffers;
1033 res = mConsumerInterface->query(mConsumerInterface.get(),
1034 NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &maxConsumerBuffers);
1035 if (res != OK) {
1036 ALOGE("%s: Unable to query consumer undequeued"
1037 " buffer count for stream %d", __FUNCTION__, mId);
1038 return res;
1039 }
1040 mMaxConsumerBuffers = maxConsumerBuffers;
1041
Eino-Ville Talvala9cca4c62012-06-15 15:41:44 -07001042 ALOGV("%s: Consumer wants %d buffers", __FUNCTION__,
1043 mMaxConsumerBuffers);
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -07001044
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -07001045 mTotalBuffers = mMaxConsumerBuffers + mMaxProducerBuffers;
1046 mActiveBuffers = 0;
1047 mFrameCount = 0;
1048 mLastTimestamp = 0;
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -07001049
1050 res = native_window_set_buffer_count(mConsumerInterface.get(),
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -07001051 mTotalBuffers);
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -07001052 if (res != OK) {
1053 ALOGE("%s: Unable to set buffer count for stream %d",
1054 __FUNCTION__, mId);
1055 return res;
1056 }
1057
1058 // Register allocated buffers with HAL device
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -07001059 buffer_handle_t *buffers = new buffer_handle_t[mTotalBuffers];
1060 ANativeWindowBuffer **anwBuffers = new ANativeWindowBuffer*[mTotalBuffers];
1061 uint32_t bufferIdx = 0;
1062 for (; bufferIdx < mTotalBuffers; bufferIdx++) {
Jamie Gennis1e5b2b32012-06-13 16:29:51 -07001063 res = native_window_dequeue_buffer_and_wait(mConsumerInterface.get(),
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -07001064 &anwBuffers[bufferIdx]);
1065 if (res != OK) {
Eino-Ville Talvala9cca4c62012-06-15 15:41:44 -07001066 ALOGE("%s: Unable to dequeue buffer %d for initial registration for "
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -07001067 "stream %d", __FUNCTION__, bufferIdx, mId);
1068 goto cleanUpBuffers;
1069 }
1070
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -07001071 buffers[bufferIdx] = anwBuffers[bufferIdx]->handle;
Eino-Ville Talvalada6665c2012-08-29 17:37:16 -07001072 ALOGV("%s: Buffer %p allocated", __FUNCTION__, (void*)buffers[bufferIdx]);
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -07001073 }
1074
Eino-Ville Talvala750d74b2012-08-01 09:05:04 -07001075 ALOGV("%s: Registering %d buffers with camera HAL", __FUNCTION__, mTotalBuffers);
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -07001076 res = mDevice->ops->register_stream_buffers(mDevice,
1077 mId,
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -07001078 mTotalBuffers,
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -07001079 buffers);
1080 if (res != OK) {
1081 ALOGE("%s: Unable to register buffers with HAL device for stream %d",
1082 __FUNCTION__, mId);
1083 } else {
1084 mState = ACTIVE;
1085 }
1086
1087cleanUpBuffers:
Eino-Ville Talvala750d74b2012-08-01 09:05:04 -07001088 ALOGV("%s: Cleaning up %d buffers", __FUNCTION__, bufferIdx);
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -07001089 for (uint32_t i = 0; i < bufferIdx; i++) {
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -07001090 res = mConsumerInterface->cancelBuffer(mConsumerInterface.get(),
Jamie Gennis1e5b2b32012-06-13 16:29:51 -07001091 anwBuffers[i], -1);
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -07001092 if (res != OK) {
1093 ALOGE("%s: Unable to cancel buffer %d after registration",
1094 __FUNCTION__, i);
1095 }
1096 }
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -07001097 delete[] anwBuffers;
1098 delete[] buffers;
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -07001099
1100 return res;
1101}
1102
Eino-Ville Talvala9cca4c62012-06-15 15:41:44 -07001103status_t Camera2Device::StreamAdapter::release() {
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -07001104 ATRACE_CALL();
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -07001105 status_t res;
Eino-Ville Talvala9cca4c62012-06-15 15:41:44 -07001106 ALOGV("%s: Releasing stream %d", __FUNCTION__, mId);
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -07001107 if (mState >= ALLOCATED) {
1108 res = mDevice->ops->release_stream(mDevice, mId);
1109 if (res != OK) {
1110 ALOGE("%s: Unable to release stream %d",
1111 __FUNCTION__, mId);
1112 return res;
1113 }
1114 }
1115 if (mState >= CONNECTED) {
1116 res = native_window_api_disconnect(mConsumerInterface.get(),
1117 NATIVE_WINDOW_API_CAMERA);
Igor Murashkinb3e97b32012-10-02 15:21:31 -07001118
1119 /* this is not an error. if client calling process dies,
1120 the window will also die and all calls to it will return
1121 DEAD_OBJECT, thus it's already "disconnected" */
1122 if (res == DEAD_OBJECT) {
1123 ALOGW("%s: While disconnecting stream %d from native window, the"
1124 " native window died from under us", __FUNCTION__, mId);
1125 }
1126 else if (res != OK) {
1127 ALOGE("%s: Unable to disconnect stream %d from native window (error %d %s)",
1128 __FUNCTION__, mId, res, strerror(-res));
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -07001129 return res;
1130 }
1131 }
1132 mId = -1;
Eino-Ville Talvala9cca4c62012-06-15 15:41:44 -07001133 mState = RELEASED;
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -07001134 return OK;
1135}
1136
Eino-Ville Talvalac94cd192012-06-15 12:47:42 -07001137status_t Camera2Device::StreamAdapter::setTransform(int transform) {
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -07001138 ATRACE_CALL();
Eino-Ville Talvalac94cd192012-06-15 12:47:42 -07001139 status_t res;
1140 if (mState < CONNECTED) {
1141 ALOGE("%s: Cannot set transform on unconnected stream", __FUNCTION__);
1142 return INVALID_OPERATION;
1143 }
1144 res = native_window_set_buffers_transform(mConsumerInterface.get(),
1145 transform);
1146 if (res != OK) {
1147 ALOGE("%s: Unable to configure stream transform to %x: %s (%d)",
1148 __FUNCTION__, transform, strerror(-res), res);
1149 }
1150 return res;
1151}
1152
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -07001153status_t Camera2Device::StreamAdapter::dump(int fd,
1154 const Vector<String16>& args) {
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -07001155 ATRACE_CALL();
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -07001156 String8 result = String8::format(" Stream %d: %d x %d, format 0x%x\n",
1157 mId, mWidth, mHeight, mFormat);
1158 result.appendFormat(" size %d, usage 0x%x, requested format 0x%x\n",
1159 mSize, mUsage, mFormatRequested);
1160 result.appendFormat(" total buffers: %d, dequeued buffers: %d\n",
1161 mTotalBuffers, mActiveBuffers);
1162 result.appendFormat(" frame count: %d, last timestamp %lld\n",
1163 mFrameCount, mLastTimestamp);
1164 write(fd, result.string(), result.size());
1165 return OK;
1166}
1167
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -07001168const camera2_stream_ops *Camera2Device::StreamAdapter::getStreamOps() {
1169 return static_cast<camera2_stream_ops *>(this);
1170}
1171
1172ANativeWindow* Camera2Device::StreamAdapter::toANW(
1173 const camera2_stream_ops_t *w) {
1174 return static_cast<const StreamAdapter*>(w)->mConsumerInterface.get();
1175}
1176
1177int Camera2Device::StreamAdapter::dequeue_buffer(const camera2_stream_ops_t *w,
1178 buffer_handle_t** buffer) {
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -07001179 ATRACE_CALL();
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -07001180 int res;
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -07001181 StreamAdapter* stream =
1182 const_cast<StreamAdapter*>(static_cast<const StreamAdapter*>(w));
1183 if (stream->mState != ACTIVE) {
1184 ALOGE("%s: Called when in bad state: %d", __FUNCTION__, stream->mState);
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -07001185 return INVALID_OPERATION;
1186 }
1187
1188 ANativeWindow *a = toANW(w);
1189 ANativeWindowBuffer* anb;
Jamie Gennis1e5b2b32012-06-13 16:29:51 -07001190 res = native_window_dequeue_buffer_and_wait(a, &anb);
Eino-Ville Talvala750d74b2012-08-01 09:05:04 -07001191 if (res != OK) {
1192 ALOGE("Stream %d dequeue: Error from native_window: %s (%d)", stream->mId,
1193 strerror(-res), res);
1194 return res;
1195 }
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -07001196
1197 *buffer = &(anb->handle);
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -07001198 stream->mActiveBuffers++;
1199
Eino-Ville Talvala750d74b2012-08-01 09:05:04 -07001200 ALOGVV("Stream %d dequeue: Buffer %p dequeued", stream->mId, (void*)(**buffer));
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -07001201 return res;
1202}
1203
1204int Camera2Device::StreamAdapter::enqueue_buffer(const camera2_stream_ops_t* w,
1205 int64_t timestamp,
1206 buffer_handle_t* buffer) {
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -07001207 ATRACE_CALL();
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -07001208 StreamAdapter *stream =
1209 const_cast<StreamAdapter*>(static_cast<const StreamAdapter*>(w));
Eino-Ville Talvala228a5382012-08-13 12:16:06 -07001210 stream->mFrameCount++;
1211 ALOGVV("Stream %d enqueue: Frame %d (%p) captured at %lld ns",
James Dong6638f3b2012-09-05 16:46:36 -07001212 stream->mId, stream->mFrameCount, (void*)(*buffer), timestamp);
Eino-Ville Talvalabd4976a2012-06-07 10:40:25 -07001213 int state = stream->mState;
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -07001214 if (state != ACTIVE) {
1215 ALOGE("%s: Called when in bad state: %d", __FUNCTION__, state);
1216 return INVALID_OPERATION;
1217 }
1218 ANativeWindow *a = toANW(w);
1219 status_t err;
Eino-Ville Talvala228a5382012-08-13 12:16:06 -07001220
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -07001221 err = native_window_set_buffers_timestamp(a, timestamp);
Eino-Ville Talvalabd4976a2012-06-07 10:40:25 -07001222 if (err != OK) {
1223 ALOGE("%s: Error setting timestamp on native window: %s (%d)",
1224 __FUNCTION__, strerror(-err), err);
1225 return err;
1226 }
1227 err = a->queueBuffer(a,
Jamie Gennis1e5b2b32012-06-13 16:29:51 -07001228 container_of(buffer, ANativeWindowBuffer, handle), -1);
Eino-Ville Talvalabd4976a2012-06-07 10:40:25 -07001229 if (err != OK) {
1230 ALOGE("%s: Error queueing buffer to native window: %s (%d)",
1231 __FUNCTION__, strerror(-err), err);
James Dong31d377b2012-08-09 17:43:46 -07001232 return err;
Eino-Ville Talvalabd4976a2012-06-07 10:40:25 -07001233 }
James Dong31d377b2012-08-09 17:43:46 -07001234
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -07001235 stream->mActiveBuffers--;
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -07001236 stream->mLastTimestamp = timestamp;
James Dong31d377b2012-08-09 17:43:46 -07001237 return OK;
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -07001238}
1239
1240int Camera2Device::StreamAdapter::cancel_buffer(const camera2_stream_ops_t* w,
1241 buffer_handle_t* buffer) {
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -07001242 ATRACE_CALL();
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -07001243 StreamAdapter *stream =
1244 const_cast<StreamAdapter*>(static_cast<const StreamAdapter*>(w));
Eino-Ville Talvala750d74b2012-08-01 09:05:04 -07001245 ALOGVV("Stream %d cancel: Buffer %p",
1246 stream->mId, (void*)(*buffer));
Eino-Ville Talvala3297daa2012-06-14 10:49:45 -07001247 if (stream->mState != ACTIVE) {
1248 ALOGE("%s: Called when in bad state: %d", __FUNCTION__, stream->mState);
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -07001249 return INVALID_OPERATION;
1250 }
James Dong31d377b2012-08-09 17:43:46 -07001251
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -07001252 ANativeWindow *a = toANW(w);
James Dong31d377b2012-08-09 17:43:46 -07001253 int err = a->cancelBuffer(a,
Jamie Gennis1e5b2b32012-06-13 16:29:51 -07001254 container_of(buffer, ANativeWindowBuffer, handle), -1);
James Dong31d377b2012-08-09 17:43:46 -07001255 if (err != OK) {
1256 ALOGE("%s: Error canceling buffer to native window: %s (%d)",
1257 __FUNCTION__, strerror(-err), err);
1258 return err;
1259 }
1260
1261 stream->mActiveBuffers--;
1262 return OK;
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -07001263}
1264
1265int Camera2Device::StreamAdapter::set_crop(const camera2_stream_ops_t* w,
1266 int left, int top, int right, int bottom) {
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -07001267 ATRACE_CALL();
Eino-Ville Talvala6db981c2012-05-21 18:54:30 -07001268 int state = static_cast<const StreamAdapter*>(w)->mState;
1269 if (state != ACTIVE) {
1270 ALOGE("%s: Called when in bad state: %d", __FUNCTION__, state);
1271 return INVALID_OPERATION;
1272 }
1273 ANativeWindow *a = toANW(w);
1274 android_native_rect_t crop = { left, top, right, bottom };
1275 return native_window_set_crop(a, &crop);
1276}
1277
Eino-Ville Talvalada6665c2012-08-29 17:37:16 -07001278/**
1279 * Camera2Device::ReprocessStreamAdapter
1280 */
1281
1282#ifndef container_of
1283#define container_of(ptr, type, member) \
1284 (type *)((char*)(ptr) - offsetof(type, member))
1285#endif
1286
1287Camera2Device::ReprocessStreamAdapter::ReprocessStreamAdapter(camera2_device_t *d):
1288 mState(RELEASED),
1289 mDevice(d),
1290 mId(-1),
1291 mWidth(0), mHeight(0), mFormat(0),
1292 mActiveBuffers(0),
1293 mFrameCount(0)
1294{
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -07001295 ATRACE_CALL();
Eino-Ville Talvalada6665c2012-08-29 17:37:16 -07001296 camera2_stream_in_ops::acquire_buffer = acquire_buffer;
1297 camera2_stream_in_ops::release_buffer = release_buffer;
1298}
1299
1300Camera2Device::ReprocessStreamAdapter::~ReprocessStreamAdapter() {
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -07001301 ATRACE_CALL();
Eino-Ville Talvalada6665c2012-08-29 17:37:16 -07001302 if (mState != RELEASED) {
1303 release();
1304 }
1305}
1306
1307status_t Camera2Device::ReprocessStreamAdapter::connectToDevice(
1308 const sp<StreamAdapter> &outputStream) {
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -07001309 ATRACE_CALL();
Eino-Ville Talvalada6665c2012-08-29 17:37:16 -07001310 status_t res;
1311 ALOGV("%s: E", __FUNCTION__);
1312
1313 if (mState != RELEASED) return INVALID_OPERATION;
1314 if (outputStream == NULL) {
1315 ALOGE("%s: Null base stream passed to reprocess stream adapter",
1316 __FUNCTION__);
1317 return BAD_VALUE;
1318 }
1319
1320 mBaseStream = outputStream;
1321 mWidth = outputStream->getWidth();
1322 mHeight = outputStream->getHeight();
1323 mFormat = outputStream->getFormat();
1324
1325 ALOGV("%s: New reprocess stream parameters %d x %d, format 0x%x",
1326 __FUNCTION__, mWidth, mHeight, mFormat);
1327
1328 // Allocate device-side stream interface
1329
1330 uint32_t id;
1331 res = mDevice->ops->allocate_reprocess_stream_from_stream(mDevice,
1332 outputStream->getId(), getStreamOps(),
1333 &id);
1334 if (res != OK) {
1335 ALOGE("%s: Device reprocess stream allocation failed: %s (%d)",
1336 __FUNCTION__, strerror(-res), res);
1337 return res;
1338 }
1339
1340 ALOGV("%s: Allocated reprocess stream id %d based on stream %d",
1341 __FUNCTION__, id, outputStream->getId());
1342
1343 mId = id;
1344
1345 mState = ACTIVE;
1346
1347 return OK;
1348}
1349
1350status_t Camera2Device::ReprocessStreamAdapter::release() {
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -07001351 ATRACE_CALL();
Eino-Ville Talvalada6665c2012-08-29 17:37:16 -07001352 status_t res;
1353 ALOGV("%s: Releasing stream %d", __FUNCTION__, mId);
1354 if (mState >= ACTIVE) {
1355 res = mDevice->ops->release_reprocess_stream(mDevice, mId);
1356 if (res != OK) {
1357 ALOGE("%s: Unable to release stream %d",
1358 __FUNCTION__, mId);
1359 return res;
1360 }
1361 }
1362
1363 List<QueueEntry>::iterator s;
1364 for (s = mQueue.begin(); s != mQueue.end(); s++) {
1365 sp<BufferReleasedListener> listener = s->releaseListener.promote();
1366 if (listener != 0) listener->onBufferReleased(s->handle);
1367 }
1368 for (s = mInFlightQueue.begin(); s != mInFlightQueue.end(); s++) {
1369 sp<BufferReleasedListener> listener = s->releaseListener.promote();
1370 if (listener != 0) listener->onBufferReleased(s->handle);
1371 }
1372 mQueue.clear();
1373 mInFlightQueue.clear();
1374
1375 mState = RELEASED;
1376 return OK;
1377}
1378
1379status_t Camera2Device::ReprocessStreamAdapter::pushIntoStream(
1380 buffer_handle_t *handle, const wp<BufferReleasedListener> &releaseListener) {
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -07001381 ATRACE_CALL();
Eino-Ville Talvalada6665c2012-08-29 17:37:16 -07001382 // TODO: Some error checking here would be nice
1383 ALOGV("%s: Pushing buffer %p to stream", __FUNCTION__, (void*)(*handle));
1384
1385 QueueEntry entry;
1386 entry.handle = handle;
1387 entry.releaseListener = releaseListener;
1388 mQueue.push_back(entry);
1389 return OK;
1390}
1391
1392status_t Camera2Device::ReprocessStreamAdapter::dump(int fd,
1393 const Vector<String16>& args) {
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -07001394 ATRACE_CALL();
Eino-Ville Talvalada6665c2012-08-29 17:37:16 -07001395 String8 result =
1396 String8::format(" Reprocess stream %d: %d x %d, fmt 0x%x\n",
1397 mId, mWidth, mHeight, mFormat);
1398 result.appendFormat(" acquired buffers: %d\n",
1399 mActiveBuffers);
1400 result.appendFormat(" frame count: %d\n",
1401 mFrameCount);
1402 write(fd, result.string(), result.size());
1403 return OK;
1404}
1405
1406const camera2_stream_in_ops *Camera2Device::ReprocessStreamAdapter::getStreamOps() {
1407 return static_cast<camera2_stream_in_ops *>(this);
1408}
1409
1410int Camera2Device::ReprocessStreamAdapter::acquire_buffer(
1411 const camera2_stream_in_ops_t *w,
1412 buffer_handle_t** buffer) {
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -07001413 ATRACE_CALL();
Eino-Ville Talvalada6665c2012-08-29 17:37:16 -07001414 int res;
1415 ReprocessStreamAdapter* stream =
1416 const_cast<ReprocessStreamAdapter*>(
1417 static_cast<const ReprocessStreamAdapter*>(w));
1418 if (stream->mState != ACTIVE) {
1419 ALOGE("%s: Called when in bad state: %d", __FUNCTION__, stream->mState);
1420 return INVALID_OPERATION;
1421 }
1422
1423 if (stream->mQueue.empty()) {
1424 *buffer = NULL;
1425 return OK;
1426 }
1427
1428 QueueEntry &entry = *(stream->mQueue.begin());
1429
1430 *buffer = entry.handle;
1431
1432 stream->mInFlightQueue.push_back(entry);
1433 stream->mQueue.erase(stream->mQueue.begin());
1434
1435 stream->mActiveBuffers++;
1436
1437 ALOGV("Stream %d acquire: Buffer %p acquired", stream->mId,
1438 (void*)(**buffer));
1439 return OK;
1440}
1441
1442int Camera2Device::ReprocessStreamAdapter::release_buffer(
1443 const camera2_stream_in_ops_t* w,
1444 buffer_handle_t* buffer) {
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -07001445 ATRACE_CALL();
Eino-Ville Talvalada6665c2012-08-29 17:37:16 -07001446 ReprocessStreamAdapter *stream =
1447 const_cast<ReprocessStreamAdapter*>(
1448 static_cast<const ReprocessStreamAdapter*>(w) );
1449 stream->mFrameCount++;
1450 ALOGV("Reprocess stream %d release: Frame %d (%p)",
1451 stream->mId, stream->mFrameCount, (void*)*buffer);
1452 int state = stream->mState;
1453 if (state != ACTIVE) {
1454 ALOGE("%s: Called when in bad state: %d", __FUNCTION__, state);
1455 return INVALID_OPERATION;
1456 }
1457 stream->mActiveBuffers--;
1458
1459 List<QueueEntry>::iterator s;
1460 for (s = stream->mInFlightQueue.begin(); s != stream->mInFlightQueue.end(); s++) {
1461 if ( s->handle == buffer ) break;
1462 }
1463 if (s == stream->mInFlightQueue.end()) {
1464 ALOGE("%s: Can't find buffer %p in in-flight list!", __FUNCTION__,
1465 buffer);
1466 return INVALID_OPERATION;
1467 }
1468
1469 sp<BufferReleasedListener> listener = s->releaseListener.promote();
1470 if (listener != 0) {
1471 listener->onBufferReleased(s->handle);
1472 } else {
1473 ALOGE("%s: Can't free buffer - missing listener", __FUNCTION__);
1474 }
1475 stream->mInFlightQueue.erase(s);
1476
1477 return OK;
1478}
Eino-Ville Talvala61ab9f92012-05-17 10:30:54 -07001479
1480}; // namespace android