blob: 48f8e8eccc436784ab1ac5d71e43aa2329b05ded [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>
Igor Murashkin634a5152013-02-20 17:15:11 -080029#include <camera/IProCameraUser.h>
30#include <camera/IProCameraCallbacks.h>
31
32#include <gui/IGraphicBufferProducer.h>
Igor Murashkin634a5152013-02-20 17:15:11 -080033
Igor Murashkina91537e2013-02-21 12:02:29 -080034#include <system/camera_metadata.h>
35
Igor Murashkin634a5152013-02-20 17:15:11 -080036namespace android {
37
Igor Murashkin634a5152013-02-20 17:15:11 -080038sp<ProCamera> ProCamera::connect(int cameraId)
39{
Igor Murashkinc073ba52013-02-26 14:32:34 -080040 return CameraBaseT::connect(cameraId, String16(),
41 ICameraService::USE_CALLING_UID);
Igor Murashkin634a5152013-02-20 17:15:11 -080042}
43
Igor Murashkinc073ba52013-02-26 14:32:34 -080044ProCamera::ProCamera(int cameraId)
45 : CameraBase(cameraId)
Igor Murashkin634a5152013-02-20 17:15:11 -080046{
47}
48
Ruben Brunk0f61d8f2013-08-08 13:07:18 -070049CameraTraits<ProCamera>::TCamConnectService CameraTraits<ProCamera>::fnConnectService =
50 &ICameraService::connectPro;
51
Igor Murashkin634a5152013-02-20 17:15:11 -080052ProCamera::~ProCamera()
53{
54
55}
56
Igor Murashkinc073ba52013-02-26 14:32:34 -080057/* IProCameraUser's implementation */
Igor Murashkin634a5152013-02-20 17:15:11 -080058
59// callback from camera service
60void ProCamera::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2)
61{
Igor Murashkinc073ba52013-02-26 14:32:34 -080062 return CameraBaseT::notifyCallback(msgType, ext1, ext2);
Igor Murashkin634a5152013-02-20 17:15:11 -080063}
64
Igor Murashkin53765732013-02-20 17:41:57 -080065void ProCamera::onLockStatusChanged(
66 IProCameraCallbacks::LockStatus newLockStatus)
67{
68 ALOGV("%s: newLockStatus = %d", __FUNCTION__, newLockStatus);
69
70 sp<ProCameraListener> listener;
71 {
72 Mutex::Autolock _l(mLock);
73 listener = mListener;
74 }
75 if (listener != NULL) {
76 switch (newLockStatus) {
77 case IProCameraCallbacks::LOCK_ACQUIRED:
78 listener->onLockAcquired();
79 break;
80 case IProCameraCallbacks::LOCK_RELEASED:
81 listener->onLockReleased();
82 break;
83 case IProCameraCallbacks::LOCK_STOLEN:
84 listener->onLockStolen();
85 break;
86 default:
87 ALOGE("%s: Unknown lock status: %d",
88 __FUNCTION__, newLockStatus);
89 }
90 }
91}
92
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -070093void ProCamera::onResultReceived(int32_t requestId, camera_metadata* result) {
94 ALOGV("%s: requestId = %d, result = %p", __FUNCTION__, requestId, result);
Igor Murashkina91537e2013-02-21 12:02:29 -080095
96 sp<ProCameraListener> listener;
97 {
98 Mutex::Autolock _l(mLock);
99 listener = mListener;
100 }
Igor Murashkina140a6e2013-02-21 14:45:03 -0800101
102 CameraMetadata tmp(result);
103
104 // Unblock waitForFrame(id) callers
105 {
106 Mutex::Autolock al(mWaitMutex);
107 mMetadataReady = true;
Igor Murashkin65d79862013-03-27 11:07:06 -0700108 mLatestMetadata = tmp; // make copy
Igor Murashkina140a6e2013-02-21 14:45:03 -0800109 mWaitCondition.broadcast();
110 }
111
112 result = tmp.release();
113
Igor Murashkina91537e2013-02-21 12:02:29 -0800114 if (listener != NULL) {
Eino-Ville Talvalaf1e98d82013-09-06 09:32:43 -0700115 listener->onResultReceived(requestId, result);
Igor Murashkina91537e2013-02-21 12:02:29 -0800116 } else {
117 free_camera_metadata(result);
118 }
119
120}
121
Igor Murashkin634a5152013-02-20 17:15:11 -0800122status_t ProCamera::exclusiveTryLock()
123{
124 sp <IProCameraUser> c = mCamera;
125 if (c == 0) return NO_INIT;
126
127 return c->exclusiveTryLock();
128}
129status_t ProCamera::exclusiveLock()
130{
131 sp <IProCameraUser> c = mCamera;
132 if (c == 0) return NO_INIT;
133
134 return c->exclusiveLock();
135}
136status_t ProCamera::exclusiveUnlock()
137{
138 sp <IProCameraUser> c = mCamera;
139 if (c == 0) return NO_INIT;
140
141 return c->exclusiveUnlock();
142}
143bool ProCamera::hasExclusiveLock()
144{
145 sp <IProCameraUser> c = mCamera;
146 if (c == 0) return NO_INIT;
147
148 return c->hasExclusiveLock();
149}
150
151// Note that the callee gets a copy of the metadata.
152int ProCamera::submitRequest(const struct camera_metadata* metadata,
153 bool streaming)
154{
155 sp <IProCameraUser> c = mCamera;
156 if (c == 0) return NO_INIT;
157
158 return c->submitRequest(const_cast<struct camera_metadata*>(metadata),
159 streaming);
160}
161
162status_t ProCamera::cancelRequest(int requestId)
163{
164 sp <IProCameraUser> c = mCamera;
165 if (c == 0) return NO_INIT;
166
167 return c->cancelRequest(requestId);
168}
169
Igor Murashkin5835cc42013-02-20 19:29:53 -0800170status_t ProCamera::deleteStream(int streamId)
Igor Murashkin634a5152013-02-20 17:15:11 -0800171{
172 sp <IProCameraUser> c = mCamera;
173 if (c == 0) return NO_INIT;
174
Igor Murashkinfa4cf9d2013-03-04 16:14:23 -0800175 status_t s = c->deleteStream(streamId);
Igor Murashkin634a5152013-02-20 17:15:11 -0800176
Igor Murashkin5835cc42013-02-20 19:29:53 -0800177 mStreams.removeItem(streamId);
178
179 return s;
Igor Murashkin634a5152013-02-20 17:15:11 -0800180}
181
Igor Murashkin68506fd2013-02-20 17:57:31 -0800182status_t ProCamera::createStream(int width, int height, int format,
Igor Murashkinc073ba52013-02-26 14:32:34 -0800183 const sp<Surface>& surface,
184 /*out*/
185 int* streamId)
Igor Murashkin68506fd2013-02-20 17:57:31 -0800186{
187 *streamId = -1;
188
189 ALOGV("%s: createStreamW %dx%d (fmt=0x%x)", __FUNCTION__, width, height,
190 format);
191
Igor Murashkin985fd302013-02-20 18:24:43 -0800192 if (surface == 0) {
Igor Murashkin68506fd2013-02-20 17:57:31 -0800193 return BAD_VALUE;
194 }
195
Igor Murashkinc073ba52013-02-26 14:32:34 -0800196 return createStream(width, height, format,
197 surface->getIGraphicBufferProducer(),
Igor Murashkin5835cc42013-02-20 19:29:53 -0800198 streamId);
Igor Murashkin68506fd2013-02-20 17:57:31 -0800199}
200
201status_t ProCamera::createStream(int width, int height, int format,
Igor Murashkinc073ba52013-02-26 14:32:34 -0800202 const sp<IGraphicBufferProducer>& bufferProducer,
203 /*out*/
204 int* streamId) {
Igor Murashkin5835cc42013-02-20 19:29:53 -0800205 *streamId = -1;
Igor Murashkin68506fd2013-02-20 17:57:31 -0800206
207 ALOGV("%s: createStreamT %dx%d (fmt=0x%x)", __FUNCTION__, width, height,
208 format);
209
Igor Murashkin5835cc42013-02-20 19:29:53 -0800210 if (bufferProducer == 0) {
Igor Murashkin68506fd2013-02-20 17:57:31 -0800211 return BAD_VALUE;
212 }
213
Igor Murashkin5835cc42013-02-20 19:29:53 -0800214 sp <IProCameraUser> c = mCamera;
215 status_t stat = c->createStream(width, height, format, bufferProducer,
216 streamId);
217
218 if (stat == OK) {
219 StreamInfo s(*streamId);
220
221 mStreams.add(*streamId, s);
222 }
223
Igor Murashkin985fd302013-02-20 18:24:43 -0800224 return stat;
Igor Murashkin68506fd2013-02-20 17:57:31 -0800225}
226
Igor Murashkin5835cc42013-02-20 19:29:53 -0800227status_t ProCamera::createStreamCpu(int width, int height, int format,
Igor Murashkinc073ba52013-02-26 14:32:34 -0800228 int heapCount,
229 /*out*/
230 sp<CpuConsumer>* cpuConsumer,
Igor Murashkinba5ca4e2013-02-28 11:21:00 -0800231 int* streamId) {
232 return createStreamCpu(width, height, format, heapCount,
233 /*synchronousMode*/true,
234 cpuConsumer, streamId);
235}
236
237status_t ProCamera::createStreamCpu(int width, int height, int format,
238 int heapCount,
239 bool synchronousMode,
240 /*out*/
241 sp<CpuConsumer>* cpuConsumer,
Igor Murashkinc073ba52013-02-26 14:32:34 -0800242 int* streamId)
Igor Murashkin5835cc42013-02-20 19:29:53 -0800243{
244 ALOGV("%s: createStreamW %dx%d (fmt=0x%x)", __FUNCTION__, width, height,
245 format);
246
Igor Murashkina140a6e2013-02-21 14:45:03 -0800247 *cpuConsumer = NULL;
248
Igor Murashkin5835cc42013-02-20 19:29:53 -0800249 sp <IProCameraUser> c = mCamera;
250 if (c == 0) return NO_INIT;
251
Dan Stoza8aa0f062014-03-12 14:31:05 -0700252 sp<IGraphicBufferProducer> producer;
253 sp<IGraphicBufferConsumer> consumer;
254 BufferQueue::createBufferQueue(&producer, &consumer);
255 sp<CpuConsumer> cc = new CpuConsumer(consumer, heapCount
256 /*, synchronousMode*/);
Igor Murashkin5835cc42013-02-20 19:29:53 -0800257 cc->setName(String8("ProCamera::mCpuConsumer"));
258
Dan Stoza8aa0f062014-03-12 14:31:05 -0700259 sp<Surface> stc = new Surface(producer);
Igor Murashkin5835cc42013-02-20 19:29:53 -0800260
Igor Murashkinc073ba52013-02-26 14:32:34 -0800261 status_t s = createStream(width, height, format,
262 stc->getIGraphicBufferProducer(),
263 streamId);
Igor Murashkin5835cc42013-02-20 19:29:53 -0800264
265 if (s != OK) {
266 ALOGE("%s: Failure to create stream %dx%d (fmt=0x%x)", __FUNCTION__,
267 width, height, format);
268 return s;
269 }
270
271 sp<ProFrameListener> frameAvailableListener =
272 new ProFrameListener(this, *streamId);
273
274 getStreamInfo(*streamId).cpuStream = true;
275 getStreamInfo(*streamId).cpuConsumer = cc;
Igor Murashkinba5ca4e2013-02-28 11:21:00 -0800276 getStreamInfo(*streamId).synchronousMode = synchronousMode;
Igor Murashkin5835cc42013-02-20 19:29:53 -0800277 getStreamInfo(*streamId).stc = stc;
278 // for lifetime management
279 getStreamInfo(*streamId).frameAvailableListener = frameAvailableListener;
280
281 cc->setFrameAvailableListener(frameAvailableListener);
282
Igor Murashkina140a6e2013-02-21 14:45:03 -0800283 *cpuConsumer = cc;
284
Igor Murashkin5835cc42013-02-20 19:29:53 -0800285 return s;
286}
287
Igor Murashkin68506fd2013-02-20 17:57:31 -0800288camera_metadata* ProCamera::getCameraInfo(int cameraId) {
Igor Murashkin68506fd2013-02-20 17:57:31 -0800289 ALOGV("%s: cameraId = %d", __FUNCTION__, cameraId);
Igor Murashkin7b33a742013-02-21 13:49:26 -0800290
291 sp <IProCameraUser> c = mCamera;
292 if (c == 0) return NULL;
293
294 camera_metadata* ptr = NULL;
295 status_t status = c->getCameraInfo(cameraId, &ptr);
296
297 if (status != OK) {
298 ALOGE("%s: Failed to get camera info, error = %d", __FUNCTION__, status);
299 }
300
301 return ptr;
Igor Murashkin68506fd2013-02-20 17:57:31 -0800302}
303
304status_t ProCamera::createDefaultRequest(int templateId,
305 camera_metadata** request) const {
Igor Murashkin68506fd2013-02-20 17:57:31 -0800306 ALOGV("%s: templateId = %d", __FUNCTION__, templateId);
307
Igor Murashkin985fd302013-02-20 18:24:43 -0800308 sp <IProCameraUser> c = mCamera;
309 if (c == 0) return NO_INIT;
310
311 return c->createDefaultRequest(templateId, request);
Igor Murashkin68506fd2013-02-20 17:57:31 -0800312}
313
Igor Murashkin5835cc42013-02-20 19:29:53 -0800314void ProCamera::onFrameAvailable(int streamId) {
315 ALOGV("%s: streamId = %d", __FUNCTION__, streamId);
316
317 sp<ProCameraListener> listener = mListener;
Igor Murashkina140a6e2013-02-21 14:45:03 -0800318 StreamInfo& stream = getStreamInfo(streamId);
319
Igor Murashkin5835cc42013-02-20 19:29:53 -0800320 if (listener.get() != NULL) {
Igor Murashkinfa4cf9d2013-03-04 16:14:23 -0800321 listener->onFrameAvailable(streamId, stream.cpuConsumer);
Igor Murashkina140a6e2013-02-21 14:45:03 -0800322 }
Igor Murashkin5835cc42013-02-20 19:29:53 -0800323
Igor Murashkina140a6e2013-02-21 14:45:03 -0800324 // Unblock waitForFrame(id) callers
325 {
326 Mutex::Autolock al(mWaitMutex);
Igor Murashkin4bc4a382013-02-20 13:36:17 -0800327 getStreamInfo(streamId).frameReady++;
Igor Murashkina140a6e2013-02-21 14:45:03 -0800328 mWaitCondition.broadcast();
329 }
330}
Igor Murashkin5835cc42013-02-20 19:29:53 -0800331
Igor Murashkin4bc4a382013-02-20 13:36:17 -0800332int ProCamera::waitForFrameBuffer(int streamId) {
Igor Murashkina140a6e2013-02-21 14:45:03 -0800333 status_t stat = BAD_VALUE;
334 Mutex::Autolock al(mWaitMutex);
335
336 StreamInfo& si = getStreamInfo(streamId);
337
Igor Murashkin4bc4a382013-02-20 13:36:17 -0800338 if (si.frameReady > 0) {
339 int numFrames = si.frameReady;
340 si.frameReady = 0;
341 return numFrames;
Igor Murashkina140a6e2013-02-21 14:45:03 -0800342 } else {
343 while (true) {
344 stat = mWaitCondition.waitRelative(mWaitMutex,
345 mWaitTimeout);
346 if (stat != OK) {
347 ALOGE("%s: Error while waiting for frame buffer: %d",
348 __FUNCTION__, stat);
349 return stat;
350 }
351
Igor Murashkin4bc4a382013-02-20 13:36:17 -0800352 if (si.frameReady > 0) {
353 int numFrames = si.frameReady;
354 si.frameReady = 0;
355 return numFrames;
Igor Murashkina140a6e2013-02-21 14:45:03 -0800356 }
357 // else it was some other stream that got unblocked
Igor Murashkin5835cc42013-02-20 19:29:53 -0800358 }
359 }
Igor Murashkina140a6e2013-02-21 14:45:03 -0800360
361 return stat;
362}
363
Igor Murashkin4bc4a382013-02-20 13:36:17 -0800364int ProCamera::dropFrameBuffer(int streamId, int count) {
365 StreamInfo& si = getStreamInfo(streamId);
366
367 if (!si.cpuStream) {
368 return BAD_VALUE;
369 } else if (count < 0) {
370 return BAD_VALUE;
371 }
372
Igor Murashkinba5ca4e2013-02-28 11:21:00 -0800373 if (!si.synchronousMode) {
374 ALOGW("%s: No need to drop frames on asynchronous streams,"
375 " as asynchronous mode only keeps 1 latest frame around.",
376 __FUNCTION__);
377 return BAD_VALUE;
378 }
379
Igor Murashkin4bc4a382013-02-20 13:36:17 -0800380 int numDropped = 0;
381 for (int i = 0; i < count; ++i) {
382 CpuConsumer::LockedBuffer buffer;
383 if (si.cpuConsumer->lockNextBuffer(&buffer) != OK) {
384 break;
385 }
386
387 si.cpuConsumer->unlockBuffer(buffer);
388 numDropped++;
389 }
390
391 return numDropped;
392}
393
Igor Murashkina140a6e2013-02-21 14:45:03 -0800394status_t ProCamera::waitForFrameMetadata() {
395 status_t stat = BAD_VALUE;
396 Mutex::Autolock al(mWaitMutex);
397
398 if (mMetadataReady) {
399 return OK;
400 } else {
401 while (true) {
402 stat = mWaitCondition.waitRelative(mWaitMutex,
403 mWaitTimeout);
404
405 if (stat != OK) {
406 ALOGE("%s: Error while waiting for metadata: %d",
407 __FUNCTION__, stat);
408 return stat;
409 }
410
411 if (mMetadataReady) {
412 mMetadataReady = false;
413 return OK;
414 }
415 // else it was some other stream or metadata
416 }
417 }
418
419 return stat;
420}
421
422CameraMetadata ProCamera::consumeFrameMetadata() {
423 Mutex::Autolock al(mWaitMutex);
424
425 // Destructive: Subsequent calls return empty metadatas
426 CameraMetadata tmp = mLatestMetadata;
Igor Murashkin65d79862013-03-27 11:07:06 -0700427 mLatestMetadata.clear();
Igor Murashkina140a6e2013-02-21 14:45:03 -0800428
429 return tmp;
Igor Murashkin5835cc42013-02-20 19:29:53 -0800430}
431
432ProCamera::StreamInfo& ProCamera::getStreamInfo(int streamId) {
433 return mStreams.editValueFor(streamId);
434}
435
Igor Murashkin634a5152013-02-20 17:15:11 -0800436}; // namespace android