blob: 5ee0e4d05a46b711eca804c951c83e7dabf6716a [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
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
Igor Murashkin53765732013-02-20 17:41:57 -0800121void ProCamera::setListener(const sp<ProCameraListener>& listener)
122{
123 Mutex::Autolock _l(mLock);
124 mListener = listener;
125}
126
Igor Murashkin634a5152013-02-20 17:15:11 -0800127
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
Igor Murashkin53765732013-02-20 17:41:57 -0800173void 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
Igor Murashkin634a5152013-02-20 17:15:11 -0800201status_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
Igor Murashkin5835cc42013-02-20 19:29:53 -0800249status_t ProCamera::deleteStream(int streamId)
Igor Murashkin634a5152013-02-20 17:15:11 -0800250{
251 sp <IProCameraUser> c = mCamera;
252 if (c == 0) return NO_INIT;
253
Igor Murashkin5835cc42013-02-20 19:29:53 -0800254 status_t s = c->cancelStream(streamId);
Igor Murashkin634a5152013-02-20 17:15:11 -0800255
Igor Murashkin5835cc42013-02-20 19:29:53 -0800256 mStreams.removeItem(streamId);
257
258 return s;
Igor Murashkin634a5152013-02-20 17:15:11 -0800259}
260
Igor Murashkin68506fd2013-02-20 17:57:31 -0800261status_t ProCamera::createStream(int width, int height, int format,
Igor Murashkin985fd302013-02-20 18:24:43 -0800262 const sp<Surface>& surface,
Igor Murashkin68506fd2013-02-20 17:57:31 -0800263 /*out*/
264 int* streamId)
265{
266 *streamId = -1;
267
268 ALOGV("%s: createStreamW %dx%d (fmt=0x%x)", __FUNCTION__, width, height,
269 format);
270
Igor Murashkin985fd302013-02-20 18:24:43 -0800271 if (surface == 0) {
Igor Murashkin68506fd2013-02-20 17:57:31 -0800272 return BAD_VALUE;
273 }
274
Igor Murashkin5835cc42013-02-20 19:29:53 -0800275 return createStream(width, height, format, surface->getIGraphicBufferProducer(),
276 streamId);
Igor Murashkin68506fd2013-02-20 17:57:31 -0800277}
278
279status_t ProCamera::createStream(int width, int height, int format,
280 const sp<IGraphicBufferProducer>& bufferProducer,
281 /*out*/
282 int* streamId) {
Igor Murashkin5835cc42013-02-20 19:29:53 -0800283 *streamId = -1;
Igor Murashkin68506fd2013-02-20 17:57:31 -0800284
285 ALOGV("%s: createStreamT %dx%d (fmt=0x%x)", __FUNCTION__, width, height,
286 format);
287
Igor Murashkin5835cc42013-02-20 19:29:53 -0800288 if (bufferProducer == 0) {
Igor Murashkin68506fd2013-02-20 17:57:31 -0800289 return BAD_VALUE;
290 }
291
Igor Murashkin5835cc42013-02-20 19:29:53 -0800292 sp <IProCameraUser> c = mCamera;
293 status_t stat = c->createStream(width, height, format, bufferProducer,
294 streamId);
295
296 if (stat == OK) {
297 StreamInfo s(*streamId);
298
299 mStreams.add(*streamId, s);
300 }
301
Igor Murashkin985fd302013-02-20 18:24:43 -0800302 return stat;
Igor Murashkin68506fd2013-02-20 17:57:31 -0800303}
304
Igor Murashkin5835cc42013-02-20 19:29:53 -0800305status_t ProCamera::createStreamCpu(int width, int height, int format,
306 int heapCount,
307 /*out*/
308 int* streamId)
309{
310 ALOGV("%s: createStreamW %dx%d (fmt=0x%x)", __FUNCTION__, width, height,
311 format);
312
313 sp <IProCameraUser> c = mCamera;
314 if (c == 0) return NO_INIT;
315
316 sp<CpuConsumer> cc = new CpuConsumer(heapCount);
317 cc->setName(String8("ProCamera::mCpuConsumer"));
318
319 sp<Surface> stc = new Surface(
320 cc->getProducerInterface());
321
322 status_t s = createStream(width, height, format, stc->getIGraphicBufferProducer(),
323 streamId);
324
325 if (s != OK) {
326 ALOGE("%s: Failure to create stream %dx%d (fmt=0x%x)", __FUNCTION__,
327 width, height, format);
328 return s;
329 }
330
331 sp<ProFrameListener> frameAvailableListener =
332 new ProFrameListener(this, *streamId);
333
334 getStreamInfo(*streamId).cpuStream = true;
335 getStreamInfo(*streamId).cpuConsumer = cc;
336 getStreamInfo(*streamId).stc = stc;
337 // for lifetime management
338 getStreamInfo(*streamId).frameAvailableListener = frameAvailableListener;
339
340 cc->setFrameAvailableListener(frameAvailableListener);
341
342 return s;
343}
344
Igor Murashkin68506fd2013-02-20 17:57:31 -0800345int ProCamera::getNumberOfCameras() {
346 ALOGE("%s: not implemented yet", __FUNCTION__);
347 return 1;
348}
349
350camera_metadata* ProCamera::getCameraInfo(int cameraId) {
351 ALOGE("%s: not implemented yet", __FUNCTION__);
352
353 ALOGV("%s: cameraId = %d", __FUNCTION__, cameraId);
354 return NULL;
355}
356
357status_t ProCamera::createDefaultRequest(int templateId,
358 camera_metadata** request) const {
Igor Murashkin68506fd2013-02-20 17:57:31 -0800359 ALOGV("%s: templateId = %d", __FUNCTION__, templateId);
360
Igor Murashkin985fd302013-02-20 18:24:43 -0800361 sp <IProCameraUser> c = mCamera;
362 if (c == 0) return NO_INIT;
363
364 return c->createDefaultRequest(templateId, request);
Igor Murashkin68506fd2013-02-20 17:57:31 -0800365}
366
Igor Murashkin5835cc42013-02-20 19:29:53 -0800367void ProCamera::onFrameAvailable(int streamId) {
368 ALOGV("%s: streamId = %d", __FUNCTION__, streamId);
369
370 sp<ProCameraListener> listener = mListener;
371 if (listener.get() != NULL) {
372 StreamInfo& stream = getStreamInfo(streamId);
373
374 CpuConsumer::LockedBuffer buf;
375
376 status_t stat = stream.cpuConsumer->lockNextBuffer(&buf);
377 if (stat != OK) {
378 ALOGE("%s: Failed to lock buffer, error code = %d", __FUNCTION__,
379 stat);
380 return;
381 }
382
383 listener->onBufferReceived(streamId, buf);
384 stat = stream.cpuConsumer->unlockBuffer(buf);
385
386 if (stat != OK) {
387 ALOGE("%s: Failed to unlock buffer, error code = %d", __FUNCTION__,
388 stat);
389 }
390 }
391}
392
393ProCamera::StreamInfo& ProCamera::getStreamInfo(int streamId) {
394 return mStreams.editValueFor(streamId);
395}
396
Igor Murashkin634a5152013-02-20 17:15:11 -0800397}; // namespace android