blob: 142c03bcc392fd8802568ff82476d5d044d6b0d0 [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{
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
Igor Murashkin53765732013-02-20 17:41:57 -0800123void ProCamera::setListener(const sp<ProCameraListener>& listener)
124{
125 Mutex::Autolock _l(mLock);
126 mListener = listener;
127}
128
Igor Murashkin634a5152013-02-20 17:15:11 -0800129
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
Igor Murashkin53765732013-02-20 17:41:57 -0800175void 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
Igor Murashkina91537e2013-02-21 12:02:29 -0800203void 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
Igor Murashkin634a5152013-02-20 17:15:11 -0800219status_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
Igor Murashkin5835cc42013-02-20 19:29:53 -0800267status_t ProCamera::deleteStream(int streamId)
Igor Murashkin634a5152013-02-20 17:15:11 -0800268{
269 sp <IProCameraUser> c = mCamera;
270 if (c == 0) return NO_INIT;
271
Igor Murashkin5835cc42013-02-20 19:29:53 -0800272 status_t s = c->cancelStream(streamId);
Igor Murashkin634a5152013-02-20 17:15:11 -0800273
Igor Murashkin5835cc42013-02-20 19:29:53 -0800274 mStreams.removeItem(streamId);
275
276 return s;
Igor Murashkin634a5152013-02-20 17:15:11 -0800277}
278
Igor Murashkin68506fd2013-02-20 17:57:31 -0800279status_t ProCamera::createStream(int width, int height, int format,
Igor Murashkin985fd302013-02-20 18:24:43 -0800280 const sp<Surface>& surface,
Igor Murashkin68506fd2013-02-20 17:57:31 -0800281 /*out*/
282 int* streamId)
283{
284 *streamId = -1;
285
286 ALOGV("%s: createStreamW %dx%d (fmt=0x%x)", __FUNCTION__, width, height,
287 format);
288
Igor Murashkin985fd302013-02-20 18:24:43 -0800289 if (surface == 0) {
Igor Murashkin68506fd2013-02-20 17:57:31 -0800290 return BAD_VALUE;
291 }
292
Igor Murashkin5835cc42013-02-20 19:29:53 -0800293 return createStream(width, height, format, surface->getIGraphicBufferProducer(),
294 streamId);
Igor Murashkin68506fd2013-02-20 17:57:31 -0800295}
296
297status_t ProCamera::createStream(int width, int height, int format,
298 const sp<IGraphicBufferProducer>& bufferProducer,
299 /*out*/
300 int* streamId) {
Igor Murashkin5835cc42013-02-20 19:29:53 -0800301 *streamId = -1;
Igor Murashkin68506fd2013-02-20 17:57:31 -0800302
303 ALOGV("%s: createStreamT %dx%d (fmt=0x%x)", __FUNCTION__, width, height,
304 format);
305
Igor Murashkin5835cc42013-02-20 19:29:53 -0800306 if (bufferProducer == 0) {
Igor Murashkin68506fd2013-02-20 17:57:31 -0800307 return BAD_VALUE;
308 }
309
Igor Murashkin5835cc42013-02-20 19:29:53 -0800310 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
Igor Murashkin985fd302013-02-20 18:24:43 -0800320 return stat;
Igor Murashkin68506fd2013-02-20 17:57:31 -0800321}
322
Igor Murashkin5835cc42013-02-20 19:29:53 -0800323status_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
Igor Murashkin68506fd2013-02-20 17:57:31 -0800363int ProCamera::getNumberOfCameras() {
364 ALOGE("%s: not implemented yet", __FUNCTION__);
365 return 1;
366}
367
368camera_metadata* ProCamera::getCameraInfo(int cameraId) {
369 ALOGE("%s: not implemented yet", __FUNCTION__);
370
371 ALOGV("%s: cameraId = %d", __FUNCTION__, cameraId);
372 return NULL;
373}
374
375status_t ProCamera::createDefaultRequest(int templateId,
376 camera_metadata** request) const {
Igor Murashkin68506fd2013-02-20 17:57:31 -0800377 ALOGV("%s: templateId = %d", __FUNCTION__, templateId);
378
Igor Murashkin985fd302013-02-20 18:24:43 -0800379 sp <IProCameraUser> c = mCamera;
380 if (c == 0) return NO_INIT;
381
382 return c->createDefaultRequest(templateId, request);
Igor Murashkin68506fd2013-02-20 17:57:31 -0800383}
384
Igor Murashkin5835cc42013-02-20 19:29:53 -0800385void ProCamera::onFrameAvailable(int streamId) {
386 ALOGV("%s: streamId = %d", __FUNCTION__, streamId);
387
388 sp<ProCameraListener> listener = mListener;
389 if (listener.get() != NULL) {
390 StreamInfo& stream = getStreamInfo(streamId);
391
392 CpuConsumer::LockedBuffer buf;
393
394 status_t stat = stream.cpuConsumer->lockNextBuffer(&buf);
395 if (stat != OK) {
396 ALOGE("%s: Failed to lock buffer, error code = %d", __FUNCTION__,
397 stat);
398 return;
399 }
400
401 listener->onBufferReceived(streamId, buf);
402 stat = stream.cpuConsumer->unlockBuffer(buf);
403
404 if (stat != OK) {
405 ALOGE("%s: Failed to unlock buffer, error code = %d", __FUNCTION__,
406 stat);
407 }
408 }
409}
410
411ProCamera::StreamInfo& ProCamera::getStreamInfo(int streamId) {
412 return mStreams.editValueFor(streamId);
413}
414
Igor Murashkin634a5152013-02-20 17:15:11 -0800415}; // namespace android