ProCamera.cpp revision 4bc4a3845e456fd464556d79d20650a107e873e5
1/*
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
36#include <system/camera_metadata.h>
37
38namespace 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{
89    ALOGV("%s: disconnect", __FUNCTION__);
90    if (mCamera != 0) {
91        mCamera->disconnect();
92        mCamera->asBinder()->unlinkToDeath(this);
93        mCamera = 0;
94    }
95    ALOGV("%s: disconnect (done)", __FUNCTION__);
96}
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
124void ProCamera::setListener(const sp<ProCameraListener>& listener)
125{
126    Mutex::Autolock _l(mLock);
127    mListener = listener;
128}
129
130
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
176void 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
204void 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    }
212
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
225    if (listener != NULL) {
226        listener->onResultReceived(frameId, result);
227    } else {
228        free_camera_metadata(result);
229    }
230
231}
232
233status_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
281status_t ProCamera::deleteStream(int streamId)
282{
283    sp <IProCameraUser> c = mCamera;
284    if (c == 0) return NO_INIT;
285
286    status_t s = c->cancelStream(streamId);
287
288    mStreams.removeItem(streamId);
289
290    return s;
291}
292
293status_t ProCamera::createStream(int width, int height, int format,
294                          const sp<Surface>& surface,
295                          /*out*/
296                          int* streamId)
297{
298    *streamId = -1;
299
300    ALOGV("%s: createStreamW %dx%d (fmt=0x%x)", __FUNCTION__, width, height,
301                                                                       format);
302
303    if (surface == 0) {
304        return BAD_VALUE;
305    }
306
307    return createStream(width, height, format, surface->getIGraphicBufferProducer(),
308                        streamId);
309}
310
311status_t ProCamera::createStream(int width, int height, int format,
312                          const sp<IGraphicBufferProducer>& bufferProducer,
313                          /*out*/
314                          int* streamId) {
315    *streamId = -1;
316
317    ALOGV("%s: createStreamT %dx%d (fmt=0x%x)", __FUNCTION__, width, height,
318                                                                       format);
319
320    if (bufferProducer == 0) {
321        return BAD_VALUE;
322    }
323
324    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
334    return stat;
335}
336
337status_t ProCamera::createStreamCpu(int width, int height, int format,
338                          int heapCount,
339                          /*out*/
340                          sp<CpuConsumer>* cpuConsumer,
341                          int* streamId)
342{
343    ALOGV("%s: createStreamW %dx%d (fmt=0x%x)", __FUNCTION__, width, height,
344                                                                        format);
345
346    *cpuConsumer = NULL;
347
348    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
377    *cpuConsumer = cc;
378
379    return s;
380}
381
382int ProCamera::getNumberOfCameras() {
383    const sp<ICameraService> cs = getCameraService();
384
385    if (!cs.get()) {
386        return DEAD_OBJECT;
387    }
388    return cs->getNumberOfCameras();
389}
390
391camera_metadata* ProCamera::getCameraInfo(int cameraId) {
392    ALOGV("%s: cameraId = %d", __FUNCTION__, cameraId);
393
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;
405}
406
407status_t ProCamera::createDefaultRequest(int templateId,
408                                             camera_metadata** request) const {
409    ALOGV("%s: templateId = %d", __FUNCTION__, templateId);
410
411    sp <IProCameraUser> c = mCamera;
412    if (c == 0) return NO_INIT;
413
414    return c->createDefaultRequest(templateId, request);
415}
416
417void ProCamera::onFrameAvailable(int streamId) {
418    ALOGV("%s: streamId = %d", __FUNCTION__, streamId);
419
420    sp<ProCameraListener> listener = mListener;
421    StreamInfo& stream = getStreamInfo(streamId);
422
423    CpuConsumer::LockedBuffer buf;
424
425    if (listener.get() != NULL) {
426        if (listener->useOnFrameAvailable()) {
427            listener->onFrameAvailable(streamId, stream.cpuConsumer);
428            return;
429        }
430    }
431
432    // Unblock waitForFrame(id) callers
433    {
434        Mutex::Autolock al(mWaitMutex);
435        getStreamInfo(streamId).frameReady++;
436        mWaitCondition.broadcast();
437    }
438}
439
440int ProCamera::waitForFrameBuffer(int streamId) {
441    status_t stat = BAD_VALUE;
442    Mutex::Autolock al(mWaitMutex);
443
444    StreamInfo& si = getStreamInfo(streamId);
445
446    if (si.frameReady > 0) {
447        int numFrames = si.frameReady;
448        si.frameReady = 0;
449        return numFrames;
450    } 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
460            if (si.frameReady > 0) {
461                int numFrames = si.frameReady;
462                si.frameReady = 0;
463                return numFrames;
464            }
465            // else it was some other stream that got unblocked
466        }
467    }
468
469    return stat;
470}
471
472int 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
495status_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;
531}
532
533ProCamera::StreamInfo& ProCamera::getStreamInfo(int streamId) {
534    return mStreams.editValueFor(streamId);
535}
536
537}; // namespace android
538