blob: 7c66d621eafb2a758aedeb4b22d749fa2d2b2a74 [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>
34#include <gui/Surface.h>
35
Igor Murashkina91537e2013-02-21 12:02:29 -080036#include <system/camera_metadata.h>
37
Igor Murashkin634a5152013-02-20 17:15:11 -080038namespace android {
39
40// client singleton for camera service binder interface
41Mutex ProCamera::mLock;
42sp<ICameraService> ProCamera::mCameraService;
43sp<ProCamera::DeathNotifier> ProCamera::mDeathNotifier;
44
45// establish binder interface to camera service
46const sp<ICameraService>& ProCamera::getCameraService()
47{
48 Mutex::Autolock _l(mLock);
49 if (mCameraService.get() == 0) {
50 sp<IServiceManager> sm = defaultServiceManager();
51 sp<IBinder> binder;
52 do {
53 binder = sm->getService(String16("media.camera"));
54 if (binder != 0)
55 break;
56 ALOGW("CameraService not published, waiting...");
57 usleep(500000); // 0.5 s
58 } while(true);
59 if (mDeathNotifier == NULL) {
60 mDeathNotifier = new DeathNotifier();
61 }
62 binder->linkToDeath(mDeathNotifier);
63 mCameraService = interface_cast<ICameraService>(binder);
64 }
65 ALOGE_IF(mCameraService==0, "no CameraService!?");
66 return mCameraService;
67}
68
69sp<ProCamera> ProCamera::connect(int cameraId)
70{
71 ALOGV("connect");
72 sp<ProCamera> c = new ProCamera();
73 sp<IProCameraCallbacks> cl = c;
74 const sp<ICameraService>& cs = getCameraService();
75 if (cs != 0) {
76 c->mCamera = cs->connect(cl, cameraId);
77 }
78 if (c->mCamera != 0) {
79 c->mCamera->asBinder()->linkToDeath(c);
80 c->mStatus = NO_ERROR;
81 } else {
82 c.clear();
83 }
84 return c;
85}
86
87void ProCamera::disconnect()
88{
Igor Murashkina140a6e2013-02-21 14:45:03 -080089 ALOGV("%s: disconnect", __FUNCTION__);
Igor Murashkin634a5152013-02-20 17:15:11 -080090 if (mCamera != 0) {
91 mCamera->disconnect();
92 mCamera->asBinder()->unlinkToDeath(this);
93 mCamera = 0;
94 }
Igor Murashkina140a6e2013-02-21 14:45:03 -080095 ALOGV("%s: disconnect (done)", __FUNCTION__);
Igor Murashkin634a5152013-02-20 17:15:11 -080096}
97
98ProCamera::ProCamera()
99{
100}
101
102ProCamera::~ProCamera()
103{
104
105}
106
107sp<IProCameraUser> ProCamera::remote()
108{
109 return mCamera;
110}
111
112void ProCamera::binderDied(const wp<IBinder>& who) {
113 ALOGW("IProCameraUser died");
114 notifyCallback(CAMERA_MSG_ERROR, CAMERA_ERROR_SERVER_DIED, 0);
115}
116
117void ProCamera::DeathNotifier::binderDied(const wp<IBinder>& who) {
118 ALOGV("binderDied");
119 Mutex::Autolock _l(ProCamera::mLock);
120 ProCamera::mCameraService.clear();
121 ALOGW("Camera service died!");
122}
123
Igor Murashkin53765732013-02-20 17:41:57 -0800124void ProCamera::setListener(const sp<ProCameraListener>& listener)
125{
126 Mutex::Autolock _l(mLock);
127 mListener = listener;
128}
129
Igor Murashkin634a5152013-02-20 17:15:11 -0800130
131// callback from camera service
132void ProCamera::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2)
133{
134 sp<ProCameraListener> listener;
135 {
136 Mutex::Autolock _l(mLock);
137 listener = mListener;
138 }
139 if (listener != NULL) {
140 listener->notify(msgType, ext1, ext2);
141 }
142}
143
144// callback from camera service when frame or image is ready
145void ProCamera::dataCallback(int32_t msgType, const sp<IMemory>& dataPtr,
146 camera_frame_metadata_t *metadata)
147{
148 sp<ProCameraListener> listener;
149 {
150 Mutex::Autolock _l(mLock);
151 listener = mListener;
152 }
153 if (listener != NULL) {
154 listener->postData(msgType, dataPtr, metadata);
155 }
156}
157
158// callback from camera service when timestamped frame is ready
159void ProCamera::dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType,
160 const sp<IMemory>& dataPtr)
161{
162 sp<ProCameraListener> listener;
163 {
164 Mutex::Autolock _l(mLock);
165 listener = mListener;
166 }
167 if (listener != NULL) {
168 listener->postDataTimestamp(timestamp, msgType, dataPtr);
169 } else {
170 ALOGW("No listener was set. Drop a recording frame.");
171 }
172}
173
174/* IProCameraUser's implementation */
175
Igor Murashkin53765732013-02-20 17:41:57 -0800176void ProCamera::onLockStatusChanged(
177 IProCameraCallbacks::LockStatus newLockStatus)
178{
179 ALOGV("%s: newLockStatus = %d", __FUNCTION__, newLockStatus);
180
181 sp<ProCameraListener> listener;
182 {
183 Mutex::Autolock _l(mLock);
184 listener = mListener;
185 }
186 if (listener != NULL) {
187 switch (newLockStatus) {
188 case IProCameraCallbacks::LOCK_ACQUIRED:
189 listener->onLockAcquired();
190 break;
191 case IProCameraCallbacks::LOCK_RELEASED:
192 listener->onLockReleased();
193 break;
194 case IProCameraCallbacks::LOCK_STOLEN:
195 listener->onLockStolen();
196 break;
197 default:
198 ALOGE("%s: Unknown lock status: %d",
199 __FUNCTION__, newLockStatus);
200 }
201 }
202}
203
Igor Murashkina91537e2013-02-21 12:02:29 -0800204void ProCamera::onResultReceived(int32_t frameId, camera_metadata* result) {
205 ALOGV("%s: frameId = %d, result = %p", __FUNCTION__, frameId, result);
206
207 sp<ProCameraListener> listener;
208 {
209 Mutex::Autolock _l(mLock);
210 listener = mListener;
211 }
Igor Murashkina140a6e2013-02-21 14:45:03 -0800212
213 CameraMetadata tmp(result);
214
215 // Unblock waitForFrame(id) callers
216 {
217 Mutex::Autolock al(mWaitMutex);
218 mMetadataReady = true;
219 mLatestMetadata = tmp;
220 mWaitCondition.broadcast();
221 }
222
223 result = tmp.release();
224
Igor Murashkina91537e2013-02-21 12:02:29 -0800225 if (listener != NULL) {
226 listener->onResultReceived(frameId, result);
227 } else {
228 free_camera_metadata(result);
229 }
230
231}
232
Igor Murashkin634a5152013-02-20 17:15:11 -0800233status_t ProCamera::exclusiveTryLock()
234{
235 sp <IProCameraUser> c = mCamera;
236 if (c == 0) return NO_INIT;
237
238 return c->exclusiveTryLock();
239}
240status_t ProCamera::exclusiveLock()
241{
242 sp <IProCameraUser> c = mCamera;
243 if (c == 0) return NO_INIT;
244
245 return c->exclusiveLock();
246}
247status_t ProCamera::exclusiveUnlock()
248{
249 sp <IProCameraUser> c = mCamera;
250 if (c == 0) return NO_INIT;
251
252 return c->exclusiveUnlock();
253}
254bool ProCamera::hasExclusiveLock()
255{
256 sp <IProCameraUser> c = mCamera;
257 if (c == 0) return NO_INIT;
258
259 return c->hasExclusiveLock();
260}
261
262// Note that the callee gets a copy of the metadata.
263int ProCamera::submitRequest(const struct camera_metadata* metadata,
264 bool streaming)
265{
266 sp <IProCameraUser> c = mCamera;
267 if (c == 0) return NO_INIT;
268
269 return c->submitRequest(const_cast<struct camera_metadata*>(metadata),
270 streaming);
271}
272
273status_t ProCamera::cancelRequest(int requestId)
274{
275 sp <IProCameraUser> c = mCamera;
276 if (c == 0) return NO_INIT;
277
278 return c->cancelRequest(requestId);
279}
280
Igor Murashkin5835cc42013-02-20 19:29:53 -0800281status_t ProCamera::deleteStream(int streamId)
Igor Murashkin634a5152013-02-20 17:15:11 -0800282{
283 sp <IProCameraUser> c = mCamera;
284 if (c == 0) return NO_INIT;
285
Igor Murashkin5835cc42013-02-20 19:29:53 -0800286 status_t s = c->cancelStream(streamId);
Igor Murashkin634a5152013-02-20 17:15:11 -0800287
Igor Murashkin5835cc42013-02-20 19:29:53 -0800288 mStreams.removeItem(streamId);
289
290 return s;
Igor Murashkin634a5152013-02-20 17:15:11 -0800291}
292
Igor Murashkin68506fd2013-02-20 17:57:31 -0800293status_t ProCamera::createStream(int width, int height, int format,
Igor Murashkin985fd302013-02-20 18:24:43 -0800294 const sp<Surface>& surface,
Igor Murashkin68506fd2013-02-20 17:57:31 -0800295 /*out*/
296 int* streamId)
297{
298 *streamId = -1;
299
300 ALOGV("%s: createStreamW %dx%d (fmt=0x%x)", __FUNCTION__, width, height,
301 format);
302
Igor Murashkin985fd302013-02-20 18:24:43 -0800303 if (surface == 0) {
Igor Murashkin68506fd2013-02-20 17:57:31 -0800304 return BAD_VALUE;
305 }
306
Igor Murashkin5835cc42013-02-20 19:29:53 -0800307 return createStream(width, height, format, surface->getIGraphicBufferProducer(),
308 streamId);
Igor Murashkin68506fd2013-02-20 17:57:31 -0800309}
310
311status_t ProCamera::createStream(int width, int height, int format,
312 const sp<IGraphicBufferProducer>& bufferProducer,
313 /*out*/
314 int* streamId) {
Igor Murashkin5835cc42013-02-20 19:29:53 -0800315 *streamId = -1;
Igor Murashkin68506fd2013-02-20 17:57:31 -0800316
317 ALOGV("%s: createStreamT %dx%d (fmt=0x%x)", __FUNCTION__, width, height,
318 format);
319
Igor Murashkin5835cc42013-02-20 19:29:53 -0800320 if (bufferProducer == 0) {
Igor Murashkin68506fd2013-02-20 17:57:31 -0800321 return BAD_VALUE;
322 }
323
Igor Murashkin5835cc42013-02-20 19:29:53 -0800324 sp <IProCameraUser> c = mCamera;
325 status_t stat = c->createStream(width, height, format, bufferProducer,
326 streamId);
327
328 if (stat == OK) {
329 StreamInfo s(*streamId);
330
331 mStreams.add(*streamId, s);
332 }
333
Igor Murashkin985fd302013-02-20 18:24:43 -0800334 return stat;
Igor Murashkin68506fd2013-02-20 17:57:31 -0800335}
336
Igor Murashkin5835cc42013-02-20 19:29:53 -0800337status_t ProCamera::createStreamCpu(int width, int height, int format,
338 int heapCount,
339 /*out*/
Igor Murashkina140a6e2013-02-21 14:45:03 -0800340 sp<CpuConsumer>* cpuConsumer,
Igor Murashkin5835cc42013-02-20 19:29:53 -0800341 int* streamId)
342{
343 ALOGV("%s: createStreamW %dx%d (fmt=0x%x)", __FUNCTION__, width, height,
344 format);
345
Igor Murashkina140a6e2013-02-21 14:45:03 -0800346 *cpuConsumer = NULL;
347
Igor Murashkin5835cc42013-02-20 19:29:53 -0800348 sp <IProCameraUser> c = mCamera;
349 if (c == 0) return NO_INIT;
350
351 sp<CpuConsumer> cc = new CpuConsumer(heapCount);
352 cc->setName(String8("ProCamera::mCpuConsumer"));
353
354 sp<Surface> stc = new Surface(
355 cc->getProducerInterface());
356
357 status_t s = createStream(width, height, format, stc->getIGraphicBufferProducer(),
358 streamId);
359
360 if (s != OK) {
361 ALOGE("%s: Failure to create stream %dx%d (fmt=0x%x)", __FUNCTION__,
362 width, height, format);
363 return s;
364 }
365
366 sp<ProFrameListener> frameAvailableListener =
367 new ProFrameListener(this, *streamId);
368
369 getStreamInfo(*streamId).cpuStream = true;
370 getStreamInfo(*streamId).cpuConsumer = cc;
371 getStreamInfo(*streamId).stc = stc;
372 // for lifetime management
373 getStreamInfo(*streamId).frameAvailableListener = frameAvailableListener;
374
375 cc->setFrameAvailableListener(frameAvailableListener);
376
Igor Murashkina140a6e2013-02-21 14:45:03 -0800377 *cpuConsumer = cc;
378
Igor Murashkin5835cc42013-02-20 19:29:53 -0800379 return s;
380}
381
Igor Murashkin68506fd2013-02-20 17:57:31 -0800382int ProCamera::getNumberOfCameras() {
Igor Murashkin7b33a742013-02-21 13:49:26 -0800383 const sp<ICameraService> cs = getCameraService();
384
385 if (!cs.get()) {
386 return DEAD_OBJECT;
387 }
388 return cs->getNumberOfCameras();
Igor Murashkin68506fd2013-02-20 17:57:31 -0800389}
390
391camera_metadata* ProCamera::getCameraInfo(int cameraId) {
Igor Murashkin68506fd2013-02-20 17:57:31 -0800392 ALOGV("%s: cameraId = %d", __FUNCTION__, cameraId);
Igor Murashkin7b33a742013-02-21 13:49:26 -0800393
394 sp <IProCameraUser> c = mCamera;
395 if (c == 0) return NULL;
396
397 camera_metadata* ptr = NULL;
398 status_t status = c->getCameraInfo(cameraId, &ptr);
399
400 if (status != OK) {
401 ALOGE("%s: Failed to get camera info, error = %d", __FUNCTION__, status);
402 }
403
404 return ptr;
Igor Murashkin68506fd2013-02-20 17:57:31 -0800405}
406
407status_t ProCamera::createDefaultRequest(int templateId,
408 camera_metadata** request) const {
Igor Murashkin68506fd2013-02-20 17:57:31 -0800409 ALOGV("%s: templateId = %d", __FUNCTION__, templateId);
410
Igor Murashkin985fd302013-02-20 18:24:43 -0800411 sp <IProCameraUser> c = mCamera;
412 if (c == 0) return NO_INIT;
413
414 return c->createDefaultRequest(templateId, request);
Igor Murashkin68506fd2013-02-20 17:57:31 -0800415}
416
Igor Murashkin5835cc42013-02-20 19:29:53 -0800417void ProCamera::onFrameAvailable(int streamId) {
418 ALOGV("%s: streamId = %d", __FUNCTION__, streamId);
419
420 sp<ProCameraListener> listener = mListener;
Igor Murashkina140a6e2013-02-21 14:45:03 -0800421 StreamInfo& stream = getStreamInfo(streamId);
422
423 CpuConsumer::LockedBuffer buf;
424
Igor Murashkin5835cc42013-02-20 19:29:53 -0800425 if (listener.get() != NULL) {
Igor Murashkina140a6e2013-02-21 14:45:03 -0800426 if (listener->useOnFrameAvailable()) {
427 listener->onFrameAvailable(streamId, stream.cpuConsumer);
Igor Murashkin5835cc42013-02-20 19:29:53 -0800428 return;
429 }
Igor Murashkina140a6e2013-02-21 14:45:03 -0800430 }
Igor Murashkin5835cc42013-02-20 19:29:53 -0800431
Igor Murashkina140a6e2013-02-21 14:45:03 -0800432 // Unblock waitForFrame(id) callers
433 {
434 Mutex::Autolock al(mWaitMutex);
Igor Murashkin4bc4a382013-02-20 13:36:17 -0800435 getStreamInfo(streamId).frameReady++;
Igor Murashkina140a6e2013-02-21 14:45:03 -0800436 mWaitCondition.broadcast();
437 }
438}
Igor Murashkin5835cc42013-02-20 19:29:53 -0800439
Igor Murashkin4bc4a382013-02-20 13:36:17 -0800440int ProCamera::waitForFrameBuffer(int streamId) {
Igor Murashkina140a6e2013-02-21 14:45:03 -0800441 status_t stat = BAD_VALUE;
442 Mutex::Autolock al(mWaitMutex);
443
444 StreamInfo& si = getStreamInfo(streamId);
445
Igor Murashkin4bc4a382013-02-20 13:36:17 -0800446 if (si.frameReady > 0) {
447 int numFrames = si.frameReady;
448 si.frameReady = 0;
449 return numFrames;
Igor Murashkina140a6e2013-02-21 14:45:03 -0800450 } else {
451 while (true) {
452 stat = mWaitCondition.waitRelative(mWaitMutex,
453 mWaitTimeout);
454 if (stat != OK) {
455 ALOGE("%s: Error while waiting for frame buffer: %d",
456 __FUNCTION__, stat);
457 return stat;
458 }
459
Igor Murashkin4bc4a382013-02-20 13:36:17 -0800460 if (si.frameReady > 0) {
461 int numFrames = si.frameReady;
462 si.frameReady = 0;
463 return numFrames;
Igor Murashkina140a6e2013-02-21 14:45:03 -0800464 }
465 // else it was some other stream that got unblocked
Igor Murashkin5835cc42013-02-20 19:29:53 -0800466 }
467 }
Igor Murashkina140a6e2013-02-21 14:45:03 -0800468
469 return stat;
470}
471
Igor Murashkin4bc4a382013-02-20 13:36:17 -0800472int ProCamera::dropFrameBuffer(int streamId, int count) {
473 StreamInfo& si = getStreamInfo(streamId);
474
475 if (!si.cpuStream) {
476 return BAD_VALUE;
477 } else if (count < 0) {
478 return BAD_VALUE;
479 }
480
481 int numDropped = 0;
482 for (int i = 0; i < count; ++i) {
483 CpuConsumer::LockedBuffer buffer;
484 if (si.cpuConsumer->lockNextBuffer(&buffer) != OK) {
485 break;
486 }
487
488 si.cpuConsumer->unlockBuffer(buffer);
489 numDropped++;
490 }
491
492 return numDropped;
493}
494
Igor Murashkina140a6e2013-02-21 14:45:03 -0800495status_t ProCamera::waitForFrameMetadata() {
496 status_t stat = BAD_VALUE;
497 Mutex::Autolock al(mWaitMutex);
498
499 if (mMetadataReady) {
500 return OK;
501 } else {
502 while (true) {
503 stat = mWaitCondition.waitRelative(mWaitMutex,
504 mWaitTimeout);
505
506 if (stat != OK) {
507 ALOGE("%s: Error while waiting for metadata: %d",
508 __FUNCTION__, stat);
509 return stat;
510 }
511
512 if (mMetadataReady) {
513 mMetadataReady = false;
514 return OK;
515 }
516 // else it was some other stream or metadata
517 }
518 }
519
520 return stat;
521}
522
523CameraMetadata ProCamera::consumeFrameMetadata() {
524 Mutex::Autolock al(mWaitMutex);
525
526 // Destructive: Subsequent calls return empty metadatas
527 CameraMetadata tmp = mLatestMetadata;
528 mLatestMetadata.release();
529
530 return tmp;
Igor Murashkin5835cc42013-02-20 19:29:53 -0800531}
532
533ProCamera::StreamInfo& ProCamera::getStreamInfo(int streamId) {
534 return mStreams.editValueFor(streamId);
535}
536
Igor Murashkin634a5152013-02-20 17:15:11 -0800537}; // namespace android