blob: 3cfabf67b7c570d793c37c4bc9b6459c2a8f61e2 [file] [log] [blame]
Igor Murashkin634a5152013-02-20 17:15:11 -08001/*
2**
3** Copyright (C) 2013, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18//#define LOG_NDEBUG 0
19#define LOG_TAG "ProCamera"
20#include <utils/Log.h>
21#include <utils/threads.h>
22#include <utils/Mutex.h>
23
24#include <binder/IPCThreadState.h>
25#include <binder/IServiceManager.h>
26#include <binder/IMemory.h>
27
28#include <camera/ProCamera.h>
29#include <camera/ICameraService.h>
30#include <camera/IProCameraUser.h>
31#include <camera/IProCameraCallbacks.h>
32
33#include <gui/IGraphicBufferProducer.h>
Igor Murashkin634a5152013-02-20 17:15:11 -080034
Igor Murashkina91537e2013-02-21 12:02:29 -080035#include <system/camera_metadata.h>
36
Igor Murashkin634a5152013-02-20 17:15:11 -080037namespace android {
38
Igor Murashkin634a5152013-02-20 17:15:11 -080039sp<ProCamera> ProCamera::connect(int cameraId)
40{
Igor Murashkinc073ba52013-02-26 14:32:34 -080041 return CameraBaseT::connect(cameraId, String16(),
42 ICameraService::USE_CALLING_UID);
Igor Murashkin634a5152013-02-20 17:15:11 -080043}
44
Igor Murashkinc073ba52013-02-26 14:32:34 -080045ProCamera::ProCamera(int cameraId)
46 : CameraBase(cameraId)
Igor Murashkin634a5152013-02-20 17:15:11 -080047{
48}
49
50ProCamera::~ProCamera()
51{
52
53}
54
Igor Murashkinc073ba52013-02-26 14:32:34 -080055/* IProCameraUser's implementation */
Igor Murashkin634a5152013-02-20 17:15:11 -080056
57// callback from camera service
58void ProCamera::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2)
59{
Igor Murashkinc073ba52013-02-26 14:32:34 -080060 return CameraBaseT::notifyCallback(msgType, ext1, ext2);
Igor Murashkin634a5152013-02-20 17:15:11 -080061}
62
63// callback from camera service when frame or image is ready
64void ProCamera::dataCallback(int32_t msgType, const sp<IMemory>& dataPtr,
65 camera_frame_metadata_t *metadata)
66{
Igor Murashkinc073ba52013-02-26 14:32:34 -080067 return CameraBaseT::dataCallback(msgType, dataPtr, metadata);
Igor Murashkin634a5152013-02-20 17:15:11 -080068}
69
70// callback from camera service when timestamped frame is ready
71void ProCamera::dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType,
Igor Murashkinc073ba52013-02-26 14:32:34 -080072 const sp<IMemory>& dataPtr)
Igor Murashkin634a5152013-02-20 17:15:11 -080073{
Igor Murashkinc073ba52013-02-26 14:32:34 -080074 CameraBaseT::dataCallbackTimestamp(timestamp, msgType, dataPtr);
Igor Murashkin634a5152013-02-20 17:15:11 -080075}
76
Igor Murashkin634a5152013-02-20 17:15:11 -080077
Igor Murashkin53765732013-02-20 17:41:57 -080078void ProCamera::onLockStatusChanged(
79 IProCameraCallbacks::LockStatus newLockStatus)
80{
81 ALOGV("%s: newLockStatus = %d", __FUNCTION__, newLockStatus);
82
83 sp<ProCameraListener> listener;
84 {
85 Mutex::Autolock _l(mLock);
86 listener = mListener;
87 }
88 if (listener != NULL) {
89 switch (newLockStatus) {
90 case IProCameraCallbacks::LOCK_ACQUIRED:
91 listener->onLockAcquired();
92 break;
93 case IProCameraCallbacks::LOCK_RELEASED:
94 listener->onLockReleased();
95 break;
96 case IProCameraCallbacks::LOCK_STOLEN:
97 listener->onLockStolen();
98 break;
99 default:
100 ALOGE("%s: Unknown lock status: %d",
101 __FUNCTION__, newLockStatus);
102 }
103 }
104}
105
Igor Murashkina91537e2013-02-21 12:02:29 -0800106void ProCamera::onResultReceived(int32_t frameId, camera_metadata* result) {
107 ALOGV("%s: frameId = %d, result = %p", __FUNCTION__, frameId, result);
108
109 sp<ProCameraListener> listener;
110 {
111 Mutex::Autolock _l(mLock);
112 listener = mListener;
113 }
Igor Murashkina140a6e2013-02-21 14:45:03 -0800114
115 CameraMetadata tmp(result);
116
117 // Unblock waitForFrame(id) callers
118 {
119 Mutex::Autolock al(mWaitMutex);
120 mMetadataReady = true;
121 mLatestMetadata = tmp;
122 mWaitCondition.broadcast();
123 }
124
125 result = tmp.release();
126
Igor Murashkina91537e2013-02-21 12:02:29 -0800127 if (listener != NULL) {
128 listener->onResultReceived(frameId, result);
129 } else {
130 free_camera_metadata(result);
131 }
132
133}
134
Igor Murashkin634a5152013-02-20 17:15:11 -0800135status_t ProCamera::exclusiveTryLock()
136{
137 sp <IProCameraUser> c = mCamera;
138 if (c == 0) return NO_INIT;
139
140 return c->exclusiveTryLock();
141}
142status_t ProCamera::exclusiveLock()
143{
144 sp <IProCameraUser> c = mCamera;
145 if (c == 0) return NO_INIT;
146
147 return c->exclusiveLock();
148}
149status_t ProCamera::exclusiveUnlock()
150{
151 sp <IProCameraUser> c = mCamera;
152 if (c == 0) return NO_INIT;
153
154 return c->exclusiveUnlock();
155}
156bool ProCamera::hasExclusiveLock()
157{
158 sp <IProCameraUser> c = mCamera;
159 if (c == 0) return NO_INIT;
160
161 return c->hasExclusiveLock();
162}
163
164// Note that the callee gets a copy of the metadata.
165int ProCamera::submitRequest(const struct camera_metadata* metadata,
166 bool streaming)
167{
168 sp <IProCameraUser> c = mCamera;
169 if (c == 0) return NO_INIT;
170
171 return c->submitRequest(const_cast<struct camera_metadata*>(metadata),
172 streaming);
173}
174
175status_t ProCamera::cancelRequest(int requestId)
176{
177 sp <IProCameraUser> c = mCamera;
178 if (c == 0) return NO_INIT;
179
180 return c->cancelRequest(requestId);
181}
182
Igor Murashkin5835cc42013-02-20 19:29:53 -0800183status_t ProCamera::deleteStream(int streamId)
Igor Murashkin634a5152013-02-20 17:15:11 -0800184{
185 sp <IProCameraUser> c = mCamera;
186 if (c == 0) return NO_INIT;
187
Igor Murashkin5835cc42013-02-20 19:29:53 -0800188 status_t s = c->cancelStream(streamId);
Igor Murashkin634a5152013-02-20 17:15:11 -0800189
Igor Murashkin5835cc42013-02-20 19:29:53 -0800190 mStreams.removeItem(streamId);
191
192 return s;
Igor Murashkin634a5152013-02-20 17:15:11 -0800193}
194
Igor Murashkin68506fd2013-02-20 17:57:31 -0800195status_t ProCamera::createStream(int width, int height, int format,
Igor Murashkinc073ba52013-02-26 14:32:34 -0800196 const sp<Surface>& surface,
197 /*out*/
198 int* streamId)
Igor Murashkin68506fd2013-02-20 17:57:31 -0800199{
200 *streamId = -1;
201
202 ALOGV("%s: createStreamW %dx%d (fmt=0x%x)", __FUNCTION__, width, height,
203 format);
204
Igor Murashkin985fd302013-02-20 18:24:43 -0800205 if (surface == 0) {
Igor Murashkin68506fd2013-02-20 17:57:31 -0800206 return BAD_VALUE;
207 }
208
Igor Murashkinc073ba52013-02-26 14:32:34 -0800209 return createStream(width, height, format,
210 surface->getIGraphicBufferProducer(),
Igor Murashkin5835cc42013-02-20 19:29:53 -0800211 streamId);
Igor Murashkin68506fd2013-02-20 17:57:31 -0800212}
213
214status_t ProCamera::createStream(int width, int height, int format,
Igor Murashkinc073ba52013-02-26 14:32:34 -0800215 const sp<IGraphicBufferProducer>& bufferProducer,
216 /*out*/
217 int* streamId) {
Igor Murashkin5835cc42013-02-20 19:29:53 -0800218 *streamId = -1;
Igor Murashkin68506fd2013-02-20 17:57:31 -0800219
220 ALOGV("%s: createStreamT %dx%d (fmt=0x%x)", __FUNCTION__, width, height,
221 format);
222
Igor Murashkin5835cc42013-02-20 19:29:53 -0800223 if (bufferProducer == 0) {
Igor Murashkin68506fd2013-02-20 17:57:31 -0800224 return BAD_VALUE;
225 }
226
Igor Murashkin5835cc42013-02-20 19:29:53 -0800227 sp <IProCameraUser> c = mCamera;
228 status_t stat = c->createStream(width, height, format, bufferProducer,
229 streamId);
230
231 if (stat == OK) {
232 StreamInfo s(*streamId);
233
234 mStreams.add(*streamId, s);
235 }
236
Igor Murashkin985fd302013-02-20 18:24:43 -0800237 return stat;
Igor Murashkin68506fd2013-02-20 17:57:31 -0800238}
239
Igor Murashkin5835cc42013-02-20 19:29:53 -0800240status_t ProCamera::createStreamCpu(int width, int height, int format,
Igor Murashkinc073ba52013-02-26 14:32:34 -0800241 int heapCount,
242 /*out*/
243 sp<CpuConsumer>* cpuConsumer,
Igor Murashkinba5ca4e2013-02-28 11:21:00 -0800244 int* streamId) {
245 return createStreamCpu(width, height, format, heapCount,
246 /*synchronousMode*/true,
247 cpuConsumer, streamId);
248}
249
250status_t ProCamera::createStreamCpu(int width, int height, int format,
251 int heapCount,
252 bool synchronousMode,
253 /*out*/
254 sp<CpuConsumer>* cpuConsumer,
Igor Murashkinc073ba52013-02-26 14:32:34 -0800255 int* streamId)
Igor Murashkin5835cc42013-02-20 19:29:53 -0800256{
257 ALOGV("%s: createStreamW %dx%d (fmt=0x%x)", __FUNCTION__, width, height,
258 format);
259
Igor Murashkina140a6e2013-02-21 14:45:03 -0800260 *cpuConsumer = NULL;
261
Igor Murashkin5835cc42013-02-20 19:29:53 -0800262 sp <IProCameraUser> c = mCamera;
263 if (c == 0) return NO_INIT;
264
Igor Murashkinba5ca4e2013-02-28 11:21:00 -0800265 sp<CpuConsumer> cc = new CpuConsumer(heapCount, synchronousMode);
Igor Murashkin5835cc42013-02-20 19:29:53 -0800266 cc->setName(String8("ProCamera::mCpuConsumer"));
267
268 sp<Surface> stc = new Surface(
269 cc->getProducerInterface());
270
Igor Murashkinc073ba52013-02-26 14:32:34 -0800271 status_t s = createStream(width, height, format,
272 stc->getIGraphicBufferProducer(),
273 streamId);
Igor Murashkin5835cc42013-02-20 19:29:53 -0800274
275 if (s != OK) {
276 ALOGE("%s: Failure to create stream %dx%d (fmt=0x%x)", __FUNCTION__,
277 width, height, format);
278 return s;
279 }
280
281 sp<ProFrameListener> frameAvailableListener =
282 new ProFrameListener(this, *streamId);
283
284 getStreamInfo(*streamId).cpuStream = true;
285 getStreamInfo(*streamId).cpuConsumer = cc;
Igor Murashkinba5ca4e2013-02-28 11:21:00 -0800286 getStreamInfo(*streamId).synchronousMode = synchronousMode;
Igor Murashkin5835cc42013-02-20 19:29:53 -0800287 getStreamInfo(*streamId).stc = stc;
288 // for lifetime management
289 getStreamInfo(*streamId).frameAvailableListener = frameAvailableListener;
290
291 cc->setFrameAvailableListener(frameAvailableListener);
292
Igor Murashkina140a6e2013-02-21 14:45:03 -0800293 *cpuConsumer = cc;
294
Igor Murashkin5835cc42013-02-20 19:29:53 -0800295 return s;
296}
297
Igor Murashkin68506fd2013-02-20 17:57:31 -0800298camera_metadata* ProCamera::getCameraInfo(int cameraId) {
Igor Murashkin68506fd2013-02-20 17:57:31 -0800299 ALOGV("%s: cameraId = %d", __FUNCTION__, cameraId);
Igor Murashkin7b33a742013-02-21 13:49:26 -0800300
301 sp <IProCameraUser> c = mCamera;
302 if (c == 0) return NULL;
303
304 camera_metadata* ptr = NULL;
305 status_t status = c->getCameraInfo(cameraId, &ptr);
306
307 if (status != OK) {
308 ALOGE("%s: Failed to get camera info, error = %d", __FUNCTION__, status);
309 }
310
311 return ptr;
Igor Murashkin68506fd2013-02-20 17:57:31 -0800312}
313
314status_t ProCamera::createDefaultRequest(int templateId,
315 camera_metadata** request) const {
Igor Murashkin68506fd2013-02-20 17:57:31 -0800316 ALOGV("%s: templateId = %d", __FUNCTION__, templateId);
317
Igor Murashkin985fd302013-02-20 18:24:43 -0800318 sp <IProCameraUser> c = mCamera;
319 if (c == 0) return NO_INIT;
320
321 return c->createDefaultRequest(templateId, request);
Igor Murashkin68506fd2013-02-20 17:57:31 -0800322}
323
Igor Murashkin5835cc42013-02-20 19:29:53 -0800324void ProCamera::onFrameAvailable(int streamId) {
325 ALOGV("%s: streamId = %d", __FUNCTION__, streamId);
326
327 sp<ProCameraListener> listener = mListener;
Igor Murashkina140a6e2013-02-21 14:45:03 -0800328 StreamInfo& stream = getStreamInfo(streamId);
329
330 CpuConsumer::LockedBuffer buf;
331
Igor Murashkin5835cc42013-02-20 19:29:53 -0800332 if (listener.get() != NULL) {
Igor Murashkina140a6e2013-02-21 14:45:03 -0800333 if (listener->useOnFrameAvailable()) {
334 listener->onFrameAvailable(streamId, stream.cpuConsumer);
Igor Murashkin5835cc42013-02-20 19:29:53 -0800335 return;
336 }
Igor Murashkina140a6e2013-02-21 14:45:03 -0800337 }
Igor Murashkin5835cc42013-02-20 19:29:53 -0800338
Igor Murashkina140a6e2013-02-21 14:45:03 -0800339 // Unblock waitForFrame(id) callers
340 {
341 Mutex::Autolock al(mWaitMutex);
Igor Murashkin4bc4a382013-02-20 13:36:17 -0800342 getStreamInfo(streamId).frameReady++;
Igor Murashkina140a6e2013-02-21 14:45:03 -0800343 mWaitCondition.broadcast();
344 }
345}
Igor Murashkin5835cc42013-02-20 19:29:53 -0800346
Igor Murashkin4bc4a382013-02-20 13:36:17 -0800347int ProCamera::waitForFrameBuffer(int streamId) {
Igor Murashkina140a6e2013-02-21 14:45:03 -0800348 status_t stat = BAD_VALUE;
349 Mutex::Autolock al(mWaitMutex);
350
351 StreamInfo& si = getStreamInfo(streamId);
352
Igor Murashkin4bc4a382013-02-20 13:36:17 -0800353 if (si.frameReady > 0) {
354 int numFrames = si.frameReady;
355 si.frameReady = 0;
356 return numFrames;
Igor Murashkina140a6e2013-02-21 14:45:03 -0800357 } else {
358 while (true) {
359 stat = mWaitCondition.waitRelative(mWaitMutex,
360 mWaitTimeout);
361 if (stat != OK) {
362 ALOGE("%s: Error while waiting for frame buffer: %d",
363 __FUNCTION__, stat);
364 return stat;
365 }
366
Igor Murashkin4bc4a382013-02-20 13:36:17 -0800367 if (si.frameReady > 0) {
368 int numFrames = si.frameReady;
369 si.frameReady = 0;
370 return numFrames;
Igor Murashkina140a6e2013-02-21 14:45:03 -0800371 }
372 // else it was some other stream that got unblocked
Igor Murashkin5835cc42013-02-20 19:29:53 -0800373 }
374 }
Igor Murashkina140a6e2013-02-21 14:45:03 -0800375
376 return stat;
377}
378
Igor Murashkin4bc4a382013-02-20 13:36:17 -0800379int ProCamera::dropFrameBuffer(int streamId, int count) {
380 StreamInfo& si = getStreamInfo(streamId);
381
382 if (!si.cpuStream) {
383 return BAD_VALUE;
384 } else if (count < 0) {
385 return BAD_VALUE;
386 }
387
Igor Murashkinba5ca4e2013-02-28 11:21:00 -0800388 if (!si.synchronousMode) {
389 ALOGW("%s: No need to drop frames on asynchronous streams,"
390 " as asynchronous mode only keeps 1 latest frame around.",
391 __FUNCTION__);
392 return BAD_VALUE;
393 }
394
Igor Murashkin4bc4a382013-02-20 13:36:17 -0800395 int numDropped = 0;
396 for (int i = 0; i < count; ++i) {
397 CpuConsumer::LockedBuffer buffer;
398 if (si.cpuConsumer->lockNextBuffer(&buffer) != OK) {
399 break;
400 }
401
402 si.cpuConsumer->unlockBuffer(buffer);
403 numDropped++;
404 }
405
406 return numDropped;
407}
408
Igor Murashkina140a6e2013-02-21 14:45:03 -0800409status_t ProCamera::waitForFrameMetadata() {
410 status_t stat = BAD_VALUE;
411 Mutex::Autolock al(mWaitMutex);
412
413 if (mMetadataReady) {
414 return OK;
415 } else {
416 while (true) {
417 stat = mWaitCondition.waitRelative(mWaitMutex,
418 mWaitTimeout);
419
420 if (stat != OK) {
421 ALOGE("%s: Error while waiting for metadata: %d",
422 __FUNCTION__, stat);
423 return stat;
424 }
425
426 if (mMetadataReady) {
427 mMetadataReady = false;
428 return OK;
429 }
430 // else it was some other stream or metadata
431 }
432 }
433
434 return stat;
435}
436
437CameraMetadata ProCamera::consumeFrameMetadata() {
438 Mutex::Autolock al(mWaitMutex);
439
440 // Destructive: Subsequent calls return empty metadatas
441 CameraMetadata tmp = mLatestMetadata;
442 mLatestMetadata.release();
443
444 return tmp;
Igor Murashkin5835cc42013-02-20 19:29:53 -0800445}
446
447ProCamera::StreamInfo& ProCamera::getStreamInfo(int streamId) {
448 return mStreams.editValueFor(streamId);
449}
450
Igor Murashkin634a5152013-02-20 17:15:11 -0800451}; // namespace android