ProCamera.cpp revision d127c2c8a8b68dae2f8743c310c2547e8f46d967
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("disconnect");
90    if (mCamera != 0) {
91        mCamera->disconnect();
92        mCamera->asBinder()->unlinkToDeath(this);
93        mCamera = 0;
94    }
95}
96
97ProCamera::ProCamera()
98{
99}
100
101ProCamera::~ProCamera()
102{
103
104}
105
106sp<IProCameraUser> ProCamera::remote()
107{
108    return mCamera;
109}
110
111void ProCamera::binderDied(const wp<IBinder>& who) {
112    ALOGW("IProCameraUser died");
113    notifyCallback(CAMERA_MSG_ERROR, CAMERA_ERROR_SERVER_DIED, 0);
114}
115
116void ProCamera::DeathNotifier::binderDied(const wp<IBinder>& who) {
117    ALOGV("binderDied");
118    Mutex::Autolock _l(ProCamera::mLock);
119    ProCamera::mCameraService.clear();
120    ALOGW("Camera service died!");
121}
122
123void ProCamera::setListener(const sp<ProCameraListener>& listener)
124{
125    Mutex::Autolock _l(mLock);
126    mListener = listener;
127}
128
129
130// callback from camera service
131void ProCamera::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2)
132{
133    sp<ProCameraListener> listener;
134    {
135        Mutex::Autolock _l(mLock);
136        listener = mListener;
137    }
138    if (listener != NULL) {
139        listener->notify(msgType, ext1, ext2);
140    }
141}
142
143// callback from camera service when frame or image is ready
144void ProCamera::dataCallback(int32_t msgType, const sp<IMemory>& dataPtr,
145                          camera_frame_metadata_t *metadata)
146{
147    sp<ProCameraListener> listener;
148    {
149        Mutex::Autolock _l(mLock);
150        listener = mListener;
151    }
152    if (listener != NULL) {
153        listener->postData(msgType, dataPtr, metadata);
154    }
155}
156
157// callback from camera service when timestamped frame is ready
158void ProCamera::dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType,
159                                                    const sp<IMemory>& dataPtr)
160{
161    sp<ProCameraListener> listener;
162    {
163        Mutex::Autolock _l(mLock);
164        listener = mListener;
165    }
166    if (listener != NULL) {
167        listener->postDataTimestamp(timestamp, msgType, dataPtr);
168    } else {
169        ALOGW("No listener was set. Drop a recording frame.");
170    }
171}
172
173/* IProCameraUser's implementation */
174
175void ProCamera::onLockStatusChanged(
176                                 IProCameraCallbacks::LockStatus newLockStatus)
177{
178    ALOGV("%s: newLockStatus = %d", __FUNCTION__, newLockStatus);
179
180    sp<ProCameraListener> listener;
181    {
182        Mutex::Autolock _l(mLock);
183        listener = mListener;
184    }
185    if (listener != NULL) {
186        switch (newLockStatus) {
187            case IProCameraCallbacks::LOCK_ACQUIRED:
188                listener->onLockAcquired();
189                break;
190            case IProCameraCallbacks::LOCK_RELEASED:
191                listener->onLockReleased();
192                break;
193            case IProCameraCallbacks::LOCK_STOLEN:
194                listener->onLockStolen();
195                break;
196            default:
197                ALOGE("%s: Unknown lock status: %d",
198                      __FUNCTION__, newLockStatus);
199        }
200    }
201}
202
203void ProCamera::onResultReceived(int32_t frameId, camera_metadata* result) {
204    ALOGV("%s: frameId = %d, result = %p", __FUNCTION__, frameId, result);
205
206    sp<ProCameraListener> listener;
207    {
208        Mutex::Autolock _l(mLock);
209        listener = mListener;
210    }
211    if (listener != NULL) {
212        listener->onResultReceived(frameId, result);
213    } else {
214        free_camera_metadata(result);
215    }
216
217}
218
219status_t ProCamera::exclusiveTryLock()
220{
221    sp <IProCameraUser> c = mCamera;
222    if (c == 0) return NO_INIT;
223
224    return c->exclusiveTryLock();
225}
226status_t ProCamera::exclusiveLock()
227{
228    sp <IProCameraUser> c = mCamera;
229    if (c == 0) return NO_INIT;
230
231    return c->exclusiveLock();
232}
233status_t ProCamera::exclusiveUnlock()
234{
235    sp <IProCameraUser> c = mCamera;
236    if (c == 0) return NO_INIT;
237
238    return c->exclusiveUnlock();
239}
240bool ProCamera::hasExclusiveLock()
241{
242    sp <IProCameraUser> c = mCamera;
243    if (c == 0) return NO_INIT;
244
245    return c->hasExclusiveLock();
246}
247
248// Note that the callee gets a copy of the metadata.
249int ProCamera::submitRequest(const struct camera_metadata* metadata,
250                             bool streaming)
251{
252    sp <IProCameraUser> c = mCamera;
253    if (c == 0) return NO_INIT;
254
255    return c->submitRequest(const_cast<struct camera_metadata*>(metadata),
256                            streaming);
257}
258
259status_t ProCamera::cancelRequest(int requestId)
260{
261    sp <IProCameraUser> c = mCamera;
262    if (c == 0) return NO_INIT;
263
264    return c->cancelRequest(requestId);
265}
266
267status_t ProCamera::deleteStream(int streamId)
268{
269    sp <IProCameraUser> c = mCamera;
270    if (c == 0) return NO_INIT;
271
272    status_t s = c->cancelStream(streamId);
273
274    mStreams.removeItem(streamId);
275
276    return s;
277}
278
279status_t ProCamera::createStream(int width, int height, int format,
280                          const sp<Surface>& surface,
281                          /*out*/
282                          int* streamId)
283{
284    *streamId = -1;
285
286    ALOGV("%s: createStreamW %dx%d (fmt=0x%x)", __FUNCTION__, width, height,
287                                                                       format);
288
289    if (surface == 0) {
290        return BAD_VALUE;
291    }
292
293    return createStream(width, height, format, surface->getIGraphicBufferProducer(),
294                        streamId);
295}
296
297status_t ProCamera::createStream(int width, int height, int format,
298                          const sp<IGraphicBufferProducer>& bufferProducer,
299                          /*out*/
300                          int* streamId) {
301    *streamId = -1;
302
303    ALOGV("%s: createStreamT %dx%d (fmt=0x%x)", __FUNCTION__, width, height,
304                                                                       format);
305
306    if (bufferProducer == 0) {
307        return BAD_VALUE;
308    }
309
310    sp <IProCameraUser> c = mCamera;
311    status_t stat = c->createStream(width, height, format, bufferProducer,
312                                    streamId);
313
314    if (stat == OK) {
315        StreamInfo s(*streamId);
316
317        mStreams.add(*streamId, s);
318    }
319
320    return stat;
321}
322
323status_t ProCamera::createStreamCpu(int width, int height, int format,
324                          int heapCount,
325                          /*out*/
326                          int* streamId)
327{
328    ALOGV("%s: createStreamW %dx%d (fmt=0x%x)", __FUNCTION__, width, height,
329                                                                        format);
330
331    sp <IProCameraUser> c = mCamera;
332    if (c == 0) return NO_INIT;
333
334    sp<CpuConsumer> cc = new CpuConsumer(heapCount);
335    cc->setName(String8("ProCamera::mCpuConsumer"));
336
337    sp<Surface> stc = new Surface(
338        cc->getProducerInterface());
339
340    status_t s = createStream(width, height, format, stc->getIGraphicBufferProducer(),
341                        streamId);
342
343    if (s != OK) {
344        ALOGE("%s: Failure to create stream %dx%d (fmt=0x%x)", __FUNCTION__,
345                    width, height, format);
346        return s;
347    }
348
349    sp<ProFrameListener> frameAvailableListener =
350        new ProFrameListener(this, *streamId);
351
352    getStreamInfo(*streamId).cpuStream = true;
353    getStreamInfo(*streamId).cpuConsumer = cc;
354    getStreamInfo(*streamId).stc = stc;
355    // for lifetime management
356    getStreamInfo(*streamId).frameAvailableListener = frameAvailableListener;
357
358    cc->setFrameAvailableListener(frameAvailableListener);
359
360    return s;
361}
362
363int ProCamera::getNumberOfCameras() {
364    const sp<ICameraService> cs = getCameraService();
365
366    if (!cs.get()) {
367        return DEAD_OBJECT;
368    }
369    return cs->getNumberOfCameras();
370}
371
372camera_metadata* ProCamera::getCameraInfo(int cameraId) {
373    ALOGV("%s: cameraId = %d", __FUNCTION__, cameraId);
374
375    sp <IProCameraUser> c = mCamera;
376    if (c == 0) return NULL;
377
378    camera_metadata* ptr = NULL;
379    status_t status = c->getCameraInfo(cameraId, &ptr);
380
381    if (status != OK) {
382        ALOGE("%s: Failed to get camera info, error = %d", __FUNCTION__, status);
383    }
384
385    return ptr;
386}
387
388status_t ProCamera::createDefaultRequest(int templateId,
389                                             camera_metadata** request) const {
390    ALOGV("%s: templateId = %d", __FUNCTION__, templateId);
391
392    sp <IProCameraUser> c = mCamera;
393    if (c == 0) return NO_INIT;
394
395    return c->createDefaultRequest(templateId, request);
396}
397
398void ProCamera::onFrameAvailable(int streamId) {
399    ALOGV("%s: streamId = %d", __FUNCTION__, streamId);
400
401    sp<ProCameraListener> listener = mListener;
402    if (listener.get() != NULL) {
403        StreamInfo& stream = getStreamInfo(streamId);
404
405        CpuConsumer::LockedBuffer buf;
406
407        status_t stat = stream.cpuConsumer->lockNextBuffer(&buf);
408        if (stat != OK) {
409            ALOGE("%s: Failed to lock buffer, error code = %d", __FUNCTION__,
410                   stat);
411            return;
412        }
413
414        listener->onBufferReceived(streamId, buf);
415        stat = stream.cpuConsumer->unlockBuffer(buf);
416
417        if (stat != OK) {
418            ALOGE("%s: Failed to unlock buffer, error code = %d", __FUNCTION__,
419                   stat);
420        }
421    }
422}
423
424ProCamera::StreamInfo& ProCamera::getStreamInfo(int streamId) {
425    return mStreams.editValueFor(streamId);
426}
427
428}; // namespace android
429