ProCamera.cpp revision 68506fd58d26748617babe94d5648503cb3690bb
147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org/*
247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org**
347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org** Copyright (C) 2013, The Android Open Source Project
447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org**
547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org** Licensed under the Apache License, Version 2.0 (the "License");
647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org** you may not use this file except in compliance with the License.
747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org** You may obtain a copy of the License at
847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org**
947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org**     http://www.apache.org/licenses/LICENSE-2.0
1047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org**
1147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org** Unless required by applicable law or agreed to in writing, software
1247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org** distributed under the License is distributed on an "AS IS" BASIS,
1347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org** See the License for the specific language governing permissions and
1547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org** limitations under the License.
1647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org*/
1747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
1847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org//#define LOG_NDEBUG 0
1947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#define LOG_TAG "ProCamera"
2047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <utils/Log.h>
2147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <utils/threads.h>
2247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <utils/Mutex.h>
2347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
2447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <binder/IPCThreadState.h>
2547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <binder/IServiceManager.h>
2647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <binder/IMemory.h>
2747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
2847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <camera/ProCamera.h>
2947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <camera/ICameraService.h>
3047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <camera/IProCameraUser.h>
3147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <camera/IProCameraCallbacks.h>
3247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
3347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <gui/IGraphicBufferProducer.h>
3447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <gui/Surface.h>
3547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
36namespace android {
37
38// client singleton for camera service binder interface
39Mutex ProCamera::mLock;
40sp<ICameraService> ProCamera::mCameraService;
41sp<ProCamera::DeathNotifier> ProCamera::mDeathNotifier;
42
43// establish binder interface to camera service
44const sp<ICameraService>& ProCamera::getCameraService()
45{
46    Mutex::Autolock _l(mLock);
47    if (mCameraService.get() == 0) {
48        sp<IServiceManager> sm = defaultServiceManager();
49        sp<IBinder> binder;
50        do {
51            binder = sm->getService(String16("media.camera"));
52            if (binder != 0)
53                break;
54            ALOGW("CameraService not published, waiting...");
55            usleep(500000); // 0.5 s
56        } while(true);
57        if (mDeathNotifier == NULL) {
58            mDeathNotifier = new DeathNotifier();
59        }
60        binder->linkToDeath(mDeathNotifier);
61        mCameraService = interface_cast<ICameraService>(binder);
62    }
63    ALOGE_IF(mCameraService==0, "no CameraService!?");
64    return mCameraService;
65}
66
67sp<ProCamera> ProCamera::connect(int cameraId)
68{
69    ALOGV("connect");
70    sp<ProCamera> c = new ProCamera();
71    sp<IProCameraCallbacks> cl = c;
72    const sp<ICameraService>& cs = getCameraService();
73    if (cs != 0) {
74        c->mCamera = cs->connect(cl, cameraId);
75    }
76    if (c->mCamera != 0) {
77        c->mCamera->asBinder()->linkToDeath(c);
78        c->mStatus = NO_ERROR;
79    } else {
80        c.clear();
81    }
82    return c;
83}
84
85void ProCamera::disconnect()
86{
87    ALOGV("disconnect");
88    if (mCamera != 0) {
89        mCamera->disconnect();
90        mCamera->asBinder()->unlinkToDeath(this);
91        mCamera = 0;
92    }
93}
94
95ProCamera::ProCamera()
96{
97}
98
99ProCamera::~ProCamera()
100{
101
102}
103
104sp<IProCameraUser> ProCamera::remote()
105{
106    return mCamera;
107}
108
109void ProCamera::binderDied(const wp<IBinder>& who) {
110    ALOGW("IProCameraUser died");
111    notifyCallback(CAMERA_MSG_ERROR, CAMERA_ERROR_SERVER_DIED, 0);
112}
113
114void ProCamera::DeathNotifier::binderDied(const wp<IBinder>& who) {
115    ALOGV("binderDied");
116    Mutex::Autolock _l(ProCamera::mLock);
117    ProCamera::mCameraService.clear();
118    ALOGW("Camera service died!");
119}
120
121void ProCamera::setListener(const sp<ProCameraListener>& listener)
122{
123    Mutex::Autolock _l(mLock);
124    mListener = listener;
125}
126
127
128// callback from camera service
129void ProCamera::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2)
130{
131    sp<ProCameraListener> listener;
132    {
133        Mutex::Autolock _l(mLock);
134        listener = mListener;
135    }
136    if (listener != NULL) {
137        listener->notify(msgType, ext1, ext2);
138    }
139}
140
141// callback from camera service when frame or image is ready
142void ProCamera::dataCallback(int32_t msgType, const sp<IMemory>& dataPtr,
143                          camera_frame_metadata_t *metadata)
144{
145    sp<ProCameraListener> listener;
146    {
147        Mutex::Autolock _l(mLock);
148        listener = mListener;
149    }
150    if (listener != NULL) {
151        listener->postData(msgType, dataPtr, metadata);
152    }
153}
154
155// callback from camera service when timestamped frame is ready
156void ProCamera::dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType,
157                                                    const sp<IMemory>& dataPtr)
158{
159    sp<ProCameraListener> listener;
160    {
161        Mutex::Autolock _l(mLock);
162        listener = mListener;
163    }
164    if (listener != NULL) {
165        listener->postDataTimestamp(timestamp, msgType, dataPtr);
166    } else {
167        ALOGW("No listener was set. Drop a recording frame.");
168    }
169}
170
171/* IProCameraUser's implementation */
172
173void ProCamera::onLockStatusChanged(
174                                 IProCameraCallbacks::LockStatus newLockStatus)
175{
176    ALOGV("%s: newLockStatus = %d", __FUNCTION__, newLockStatus);
177
178    sp<ProCameraListener> listener;
179    {
180        Mutex::Autolock _l(mLock);
181        listener = mListener;
182    }
183    if (listener != NULL) {
184        switch (newLockStatus) {
185            case IProCameraCallbacks::LOCK_ACQUIRED:
186                listener->onLockAcquired();
187                break;
188            case IProCameraCallbacks::LOCK_RELEASED:
189                listener->onLockReleased();
190                break;
191            case IProCameraCallbacks::LOCK_STOLEN:
192                listener->onLockStolen();
193                break;
194            default:
195                ALOGE("%s: Unknown lock status: %d",
196                      __FUNCTION__, newLockStatus);
197        }
198    }
199}
200
201status_t ProCamera::exclusiveTryLock()
202{
203    sp <IProCameraUser> c = mCamera;
204    if (c == 0) return NO_INIT;
205
206    return c->exclusiveTryLock();
207}
208status_t ProCamera::exclusiveLock()
209{
210    sp <IProCameraUser> c = mCamera;
211    if (c == 0) return NO_INIT;
212
213    return c->exclusiveLock();
214}
215status_t ProCamera::exclusiveUnlock()
216{
217    sp <IProCameraUser> c = mCamera;
218    if (c == 0) return NO_INIT;
219
220    return c->exclusiveUnlock();
221}
222bool ProCamera::hasExclusiveLock()
223{
224    sp <IProCameraUser> c = mCamera;
225    if (c == 0) return NO_INIT;
226
227    return c->hasExclusiveLock();
228}
229
230// Note that the callee gets a copy of the metadata.
231int ProCamera::submitRequest(const struct camera_metadata* metadata,
232                             bool streaming)
233{
234    sp <IProCameraUser> c = mCamera;
235    if (c == 0) return NO_INIT;
236
237    return c->submitRequest(const_cast<struct camera_metadata*>(metadata),
238                            streaming);
239}
240
241status_t ProCamera::cancelRequest(int requestId)
242{
243    sp <IProCameraUser> c = mCamera;
244    if (c == 0) return NO_INIT;
245
246    return c->cancelRequest(requestId);
247}
248
249status_t ProCamera::requestStream(int streamId)
250{
251    sp <IProCameraUser> c = mCamera;
252    if (c == 0) return NO_INIT;
253
254    return c->requestStream(streamId);
255}
256status_t ProCamera::cancelStream(int streamId)
257{
258    sp <IProCameraUser> c = mCamera;
259    if (c == 0) return NO_INIT;
260
261    return c->cancelStream(streamId);
262}
263
264status_t ProCamera::createStream(int width, int height, int format,
265                          const sp<ANativeWindow>& window,
266                          /*out*/
267                          int* streamId)
268{
269    *streamId = -1;
270
271    ALOGV("%s: createStreamW %dx%d (fmt=0x%x)", __FUNCTION__, width, height,
272                                                                       format);
273
274    if (window == 0) {
275        return BAD_VALUE;
276    }
277
278    // TODO: actually implement this in IProCamera
279    return INVALID_OPERATION;
280}
281
282status_t ProCamera::createStream(int width, int height, int format,
283                          const sp<IGraphicBufferProducer>& bufferProducer,
284                          /*out*/
285                          int* streamId) {
286
287    ALOGV("%s: createStreamT %dx%d (fmt=0x%x)", __FUNCTION__, width, height,
288                                                                       format);
289
290    sp<IBinder> binder;
291    sp<ANativeWindow> window;
292
293    if (bufferProducer != 0) {
294        binder = bufferProducer->asBinder();
295        window = new Surface(bufferProducer);
296
297        status_t stat = createStream(width, height, format, window, streamId);
298
299        ALOGV("%s: createStreamT END (%d), StreamID = %d", __FUNCTION__, stat,
300                                                                    *streamId);
301    }
302    else {
303        *streamId = -1;
304        return BAD_VALUE;
305    }
306
307    return BAD_VALUE;
308}
309
310int ProCamera::getNumberOfCameras() {
311    ALOGE("%s: not implemented yet", __FUNCTION__);
312    return 1;
313}
314
315camera_metadata* ProCamera::getCameraInfo(int cameraId) {
316    ALOGE("%s: not implemented yet", __FUNCTION__);
317
318    ALOGV("%s: cameraId = %d", __FUNCTION__, cameraId);
319    return NULL;
320}
321
322status_t ProCamera::createDefaultRequest(int templateId,
323                                             camera_metadata** request) const {
324    ALOGE("%s: not implemented yet", __FUNCTION__);
325
326    ALOGV("%s: templateId = %d", __FUNCTION__, templateId);
327
328    *request = NULL;
329    return INVALID_OPERATION;
330}
331
332}; // namespace android
333