blob: 190402e95caf0c19d02fbcec6fe71b40fcf7c3e5 [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>
Igor Murashkin634a5152013-02-20 17:15:11 -080034
Igor Murashkina91537e2013-02-21 12:02:29 -080035#include <system/camera_metadata.h>
36
Igor Murashkin634a5152013-02-20 17:15:11 -080037namespace android {
38
Igor Murashkin634a5152013-02-20 17:15:11 -080039sp<ProCamera> ProCamera::connect(int cameraId)
40{
Igor Murashkinc073ba52013-02-26 14:32:34 -080041 return CameraBaseT::connect(cameraId, String16(),
42 ICameraService::USE_CALLING_UID);
Igor Murashkin634a5152013-02-20 17:15:11 -080043}
44
Igor Murashkinc073ba52013-02-26 14:32:34 -080045ProCamera::ProCamera(int cameraId)
46 : CameraBase(cameraId)
Igor Murashkin634a5152013-02-20 17:15:11 -080047{
48}
49
50ProCamera::~ProCamera()
51{
52
53}
54
Igor Murashkinc073ba52013-02-26 14:32:34 -080055/* IProCameraUser's implementation */
Igor Murashkin634a5152013-02-20 17:15:11 -080056
57// callback from camera service
58void ProCamera::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2)
59{
Igor Murashkinc073ba52013-02-26 14:32:34 -080060 return CameraBaseT::notifyCallback(msgType, ext1, ext2);
Igor Murashkin634a5152013-02-20 17:15:11 -080061}
62
Igor Murashkin53765732013-02-20 17:41:57 -080063void ProCamera::onLockStatusChanged(
64 IProCameraCallbacks::LockStatus newLockStatus)
65{
66 ALOGV("%s: newLockStatus = %d", __FUNCTION__, newLockStatus);
67
68 sp<ProCameraListener> listener;
69 {
70 Mutex::Autolock _l(mLock);
71 listener = mListener;
72 }
73 if (listener != NULL) {
74 switch (newLockStatus) {
75 case IProCameraCallbacks::LOCK_ACQUIRED:
76 listener->onLockAcquired();
77 break;
78 case IProCameraCallbacks::LOCK_RELEASED:
79 listener->onLockReleased();
80 break;
81 case IProCameraCallbacks::LOCK_STOLEN:
82 listener->onLockStolen();
83 break;
84 default:
85 ALOGE("%s: Unknown lock status: %d",
86 __FUNCTION__, newLockStatus);
87 }
88 }
89}
90
Igor Murashkina91537e2013-02-21 12:02:29 -080091void ProCamera::onResultReceived(int32_t frameId, camera_metadata* result) {
92 ALOGV("%s: frameId = %d, result = %p", __FUNCTION__, frameId, result);
93
94 sp<ProCameraListener> listener;
95 {
96 Mutex::Autolock _l(mLock);
97 listener = mListener;
98 }
Igor Murashkina140a6e2013-02-21 14:45:03 -080099
100 CameraMetadata tmp(result);
101
102 // Unblock waitForFrame(id) callers
103 {
104 Mutex::Autolock al(mWaitMutex);
105 mMetadataReady = true;
Igor Murashkin65d79862013-03-27 11:07:06 -0700106 mLatestMetadata = tmp; // make copy
Igor Murashkina140a6e2013-02-21 14:45:03 -0800107 mWaitCondition.broadcast();
108 }
109
110 result = tmp.release();
111
Igor Murashkina91537e2013-02-21 12:02:29 -0800112 if (listener != NULL) {
113 listener->onResultReceived(frameId, result);
114 } else {
115 free_camera_metadata(result);
116 }
117
118}
119
Igor Murashkin634a5152013-02-20 17:15:11 -0800120status_t ProCamera::exclusiveTryLock()
121{
122 sp <IProCameraUser> c = mCamera;
123 if (c == 0) return NO_INIT;
124
125 return c->exclusiveTryLock();
126}
127status_t ProCamera::exclusiveLock()
128{
129 sp <IProCameraUser> c = mCamera;
130 if (c == 0) return NO_INIT;
131
132 return c->exclusiveLock();
133}
134status_t ProCamera::exclusiveUnlock()
135{
136 sp <IProCameraUser> c = mCamera;
137 if (c == 0) return NO_INIT;
138
139 return c->exclusiveUnlock();
140}
141bool ProCamera::hasExclusiveLock()
142{
143 sp <IProCameraUser> c = mCamera;
144 if (c == 0) return NO_INIT;
145
146 return c->hasExclusiveLock();
147}
148
149// Note that the callee gets a copy of the metadata.
150int ProCamera::submitRequest(const struct camera_metadata* metadata,
151 bool streaming)
152{
153 sp <IProCameraUser> c = mCamera;
154 if (c == 0) return NO_INIT;
155
156 return c->submitRequest(const_cast<struct camera_metadata*>(metadata),
157 streaming);
158}
159
160status_t ProCamera::cancelRequest(int requestId)
161{
162 sp <IProCameraUser> c = mCamera;
163 if (c == 0) return NO_INIT;
164
165 return c->cancelRequest(requestId);
166}
167
Igor Murashkin5835cc42013-02-20 19:29:53 -0800168status_t ProCamera::deleteStream(int streamId)
Igor Murashkin634a5152013-02-20 17:15:11 -0800169{
170 sp <IProCameraUser> c = mCamera;
171 if (c == 0) return NO_INIT;
172
Igor Murashkinfa4cf9d2013-03-04 16:14:23 -0800173 status_t s = c->deleteStream(streamId);
Igor Murashkin634a5152013-02-20 17:15:11 -0800174
Igor Murashkin5835cc42013-02-20 19:29:53 -0800175 mStreams.removeItem(streamId);
176
177 return s;
Igor Murashkin634a5152013-02-20 17:15:11 -0800178}
179
Igor Murashkin68506fd2013-02-20 17:57:31 -0800180status_t ProCamera::createStream(int width, int height, int format,
Igor Murashkinc073ba52013-02-26 14:32:34 -0800181 const sp<Surface>& surface,
182 /*out*/
183 int* streamId)
Igor Murashkin68506fd2013-02-20 17:57:31 -0800184{
185 *streamId = -1;
186
187 ALOGV("%s: createStreamW %dx%d (fmt=0x%x)", __FUNCTION__, width, height,
188 format);
189
Igor Murashkin985fd302013-02-20 18:24:43 -0800190 if (surface == 0) {
Igor Murashkin68506fd2013-02-20 17:57:31 -0800191 return BAD_VALUE;
192 }
193
Igor Murashkinc073ba52013-02-26 14:32:34 -0800194 return createStream(width, height, format,
195 surface->getIGraphicBufferProducer(),
Igor Murashkin5835cc42013-02-20 19:29:53 -0800196 streamId);
Igor Murashkin68506fd2013-02-20 17:57:31 -0800197}
198
199status_t ProCamera::createStream(int width, int height, int format,
Igor Murashkinc073ba52013-02-26 14:32:34 -0800200 const sp<IGraphicBufferProducer>& bufferProducer,
201 /*out*/
202 int* streamId) {
Igor Murashkin5835cc42013-02-20 19:29:53 -0800203 *streamId = -1;
Igor Murashkin68506fd2013-02-20 17:57:31 -0800204
205 ALOGV("%s: createStreamT %dx%d (fmt=0x%x)", __FUNCTION__, width, height,
206 format);
207
Igor Murashkin5835cc42013-02-20 19:29:53 -0800208 if (bufferProducer == 0) {
Igor Murashkin68506fd2013-02-20 17:57:31 -0800209 return BAD_VALUE;
210 }
211
Igor Murashkin5835cc42013-02-20 19:29:53 -0800212 sp <IProCameraUser> c = mCamera;
213 status_t stat = c->createStream(width, height, format, bufferProducer,
214 streamId);
215
216 if (stat == OK) {
217 StreamInfo s(*streamId);
218
219 mStreams.add(*streamId, s);
220 }
221
Igor Murashkin985fd302013-02-20 18:24:43 -0800222 return stat;
Igor Murashkin68506fd2013-02-20 17:57:31 -0800223}
224
Igor Murashkin5835cc42013-02-20 19:29:53 -0800225status_t ProCamera::createStreamCpu(int width, int height, int format,
Igor Murashkinc073ba52013-02-26 14:32:34 -0800226 int heapCount,
227 /*out*/
228 sp<CpuConsumer>* cpuConsumer,
Igor Murashkinba5ca4e2013-02-28 11:21:00 -0800229 int* streamId) {
230 return createStreamCpu(width, height, format, heapCount,
231 /*synchronousMode*/true,
232 cpuConsumer, streamId);
233}
234
235status_t ProCamera::createStreamCpu(int width, int height, int format,
236 int heapCount,
237 bool synchronousMode,
238 /*out*/
239 sp<CpuConsumer>* cpuConsumer,
Igor Murashkinc073ba52013-02-26 14:32:34 -0800240 int* streamId)
Igor Murashkin5835cc42013-02-20 19:29:53 -0800241{
242 ALOGV("%s: createStreamW %dx%d (fmt=0x%x)", __FUNCTION__, width, height,
243 format);
244
Igor Murashkina140a6e2013-02-21 14:45:03 -0800245 *cpuConsumer = NULL;
246
Igor Murashkin5835cc42013-02-20 19:29:53 -0800247 sp <IProCameraUser> c = mCamera;
248 if (c == 0) return NO_INIT;
249
Mathias Agopian8d764bf2013-07-12 22:06:20 -0700250 sp<BufferQueue> bq = new BufferQueue();
251 sp<CpuConsumer> cc = new CpuConsumer(bq, heapCount, synchronousMode);
Igor Murashkin5835cc42013-02-20 19:29:53 -0800252 cc->setName(String8("ProCamera::mCpuConsumer"));
253
254 sp<Surface> stc = new Surface(
255 cc->getProducerInterface());
256
Igor Murashkinc073ba52013-02-26 14:32:34 -0800257 status_t s = createStream(width, height, format,
258 stc->getIGraphicBufferProducer(),
259 streamId);
Igor Murashkin5835cc42013-02-20 19:29:53 -0800260
261 if (s != OK) {
262 ALOGE("%s: Failure to create stream %dx%d (fmt=0x%x)", __FUNCTION__,
263 width, height, format);
264 return s;
265 }
266
267 sp<ProFrameListener> frameAvailableListener =
268 new ProFrameListener(this, *streamId);
269
270 getStreamInfo(*streamId).cpuStream = true;
271 getStreamInfo(*streamId).cpuConsumer = cc;
Igor Murashkinba5ca4e2013-02-28 11:21:00 -0800272 getStreamInfo(*streamId).synchronousMode = synchronousMode;
Igor Murashkin5835cc42013-02-20 19:29:53 -0800273 getStreamInfo(*streamId).stc = stc;
274 // for lifetime management
275 getStreamInfo(*streamId).frameAvailableListener = frameAvailableListener;
276
277 cc->setFrameAvailableListener(frameAvailableListener);
278
Igor Murashkina140a6e2013-02-21 14:45:03 -0800279 *cpuConsumer = cc;
280
Igor Murashkin5835cc42013-02-20 19:29:53 -0800281 return s;
282}
283
Igor Murashkin68506fd2013-02-20 17:57:31 -0800284camera_metadata* ProCamera::getCameraInfo(int cameraId) {
Igor Murashkin68506fd2013-02-20 17:57:31 -0800285 ALOGV("%s: cameraId = %d", __FUNCTION__, cameraId);
Igor Murashkin7b33a742013-02-21 13:49:26 -0800286
287 sp <IProCameraUser> c = mCamera;
288 if (c == 0) return NULL;
289
290 camera_metadata* ptr = NULL;
291 status_t status = c->getCameraInfo(cameraId, &ptr);
292
293 if (status != OK) {
294 ALOGE("%s: Failed to get camera info, error = %d", __FUNCTION__, status);
295 }
296
297 return ptr;
Igor Murashkin68506fd2013-02-20 17:57:31 -0800298}
299
300status_t ProCamera::createDefaultRequest(int templateId,
301 camera_metadata** request) const {
Igor Murashkin68506fd2013-02-20 17:57:31 -0800302 ALOGV("%s: templateId = %d", __FUNCTION__, templateId);
303
Igor Murashkin985fd302013-02-20 18:24:43 -0800304 sp <IProCameraUser> c = mCamera;
305 if (c == 0) return NO_INIT;
306
307 return c->createDefaultRequest(templateId, request);
Igor Murashkin68506fd2013-02-20 17:57:31 -0800308}
309
Igor Murashkin5835cc42013-02-20 19:29:53 -0800310void ProCamera::onFrameAvailable(int streamId) {
311 ALOGV("%s: streamId = %d", __FUNCTION__, streamId);
312
313 sp<ProCameraListener> listener = mListener;
Igor Murashkina140a6e2013-02-21 14:45:03 -0800314 StreamInfo& stream = getStreamInfo(streamId);
315
Igor Murashkin5835cc42013-02-20 19:29:53 -0800316 if (listener.get() != NULL) {
Igor Murashkinfa4cf9d2013-03-04 16:14:23 -0800317 listener->onFrameAvailable(streamId, stream.cpuConsumer);
Igor Murashkina140a6e2013-02-21 14:45:03 -0800318 }
Igor Murashkin5835cc42013-02-20 19:29:53 -0800319
Igor Murashkina140a6e2013-02-21 14:45:03 -0800320 // Unblock waitForFrame(id) callers
321 {
322 Mutex::Autolock al(mWaitMutex);
Igor Murashkin4bc4a382013-02-20 13:36:17 -0800323 getStreamInfo(streamId).frameReady++;
Igor Murashkina140a6e2013-02-21 14:45:03 -0800324 mWaitCondition.broadcast();
325 }
326}
Igor Murashkin5835cc42013-02-20 19:29:53 -0800327
Igor Murashkin4bc4a382013-02-20 13:36:17 -0800328int ProCamera::waitForFrameBuffer(int streamId) {
Igor Murashkina140a6e2013-02-21 14:45:03 -0800329 status_t stat = BAD_VALUE;
330 Mutex::Autolock al(mWaitMutex);
331
332 StreamInfo& si = getStreamInfo(streamId);
333
Igor Murashkin4bc4a382013-02-20 13:36:17 -0800334 if (si.frameReady > 0) {
335 int numFrames = si.frameReady;
336 si.frameReady = 0;
337 return numFrames;
Igor Murashkina140a6e2013-02-21 14:45:03 -0800338 } else {
339 while (true) {
340 stat = mWaitCondition.waitRelative(mWaitMutex,
341 mWaitTimeout);
342 if (stat != OK) {
343 ALOGE("%s: Error while waiting for frame buffer: %d",
344 __FUNCTION__, stat);
345 return stat;
346 }
347
Igor Murashkin4bc4a382013-02-20 13:36:17 -0800348 if (si.frameReady > 0) {
349 int numFrames = si.frameReady;
350 si.frameReady = 0;
351 return numFrames;
Igor Murashkina140a6e2013-02-21 14:45:03 -0800352 }
353 // else it was some other stream that got unblocked
Igor Murashkin5835cc42013-02-20 19:29:53 -0800354 }
355 }
Igor Murashkina140a6e2013-02-21 14:45:03 -0800356
357 return stat;
358}
359
Igor Murashkin4bc4a382013-02-20 13:36:17 -0800360int ProCamera::dropFrameBuffer(int streamId, int count) {
361 StreamInfo& si = getStreamInfo(streamId);
362
363 if (!si.cpuStream) {
364 return BAD_VALUE;
365 } else if (count < 0) {
366 return BAD_VALUE;
367 }
368
Igor Murashkinba5ca4e2013-02-28 11:21:00 -0800369 if (!si.synchronousMode) {
370 ALOGW("%s: No need to drop frames on asynchronous streams,"
371 " as asynchronous mode only keeps 1 latest frame around.",
372 __FUNCTION__);
373 return BAD_VALUE;
374 }
375
Igor Murashkin4bc4a382013-02-20 13:36:17 -0800376 int numDropped = 0;
377 for (int i = 0; i < count; ++i) {
378 CpuConsumer::LockedBuffer buffer;
379 if (si.cpuConsumer->lockNextBuffer(&buffer) != OK) {
380 break;
381 }
382
383 si.cpuConsumer->unlockBuffer(buffer);
384 numDropped++;
385 }
386
387 return numDropped;
388}
389
Igor Murashkina140a6e2013-02-21 14:45:03 -0800390status_t ProCamera::waitForFrameMetadata() {
391 status_t stat = BAD_VALUE;
392 Mutex::Autolock al(mWaitMutex);
393
394 if (mMetadataReady) {
395 return OK;
396 } else {
397 while (true) {
398 stat = mWaitCondition.waitRelative(mWaitMutex,
399 mWaitTimeout);
400
401 if (stat != OK) {
402 ALOGE("%s: Error while waiting for metadata: %d",
403 __FUNCTION__, stat);
404 return stat;
405 }
406
407 if (mMetadataReady) {
408 mMetadataReady = false;
409 return OK;
410 }
411 // else it was some other stream or metadata
412 }
413 }
414
415 return stat;
416}
417
418CameraMetadata ProCamera::consumeFrameMetadata() {
419 Mutex::Autolock al(mWaitMutex);
420
421 // Destructive: Subsequent calls return empty metadatas
422 CameraMetadata tmp = mLatestMetadata;
Igor Murashkin65d79862013-03-27 11:07:06 -0700423 mLatestMetadata.clear();
Igor Murashkina140a6e2013-02-21 14:45:03 -0800424
425 return tmp;
Igor Murashkin5835cc42013-02-20 19:29:53 -0800426}
427
428ProCamera::StreamInfo& ProCamera::getStreamInfo(int streamId) {
429 return mStreams.editValueFor(streamId);
430}
431
Igor Murashkin634a5152013-02-20 17:15:11 -0800432}; // namespace android