blob: 13ba07c653ca4ba1997d9f00350898202f846e75 [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
63// callback from camera service when frame or image is ready
64void ProCamera::dataCallback(int32_t msgType, const sp<IMemory>& dataPtr,
65 camera_frame_metadata_t *metadata)
66{
Igor Murashkinc073ba52013-02-26 14:32:34 -080067 return CameraBaseT::dataCallback(msgType, dataPtr, metadata);
Igor Murashkin634a5152013-02-20 17:15:11 -080068}
69
70// callback from camera service when timestamped frame is ready
71void ProCamera::dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType,
Igor Murashkinc073ba52013-02-26 14:32:34 -080072 const sp<IMemory>& dataPtr)
Igor Murashkin634a5152013-02-20 17:15:11 -080073{
Igor Murashkinc073ba52013-02-26 14:32:34 -080074 CameraBaseT::dataCallbackTimestamp(timestamp, msgType, dataPtr);
Igor Murashkin634a5152013-02-20 17:15:11 -080075}
76
Igor Murashkin634a5152013-02-20 17:15:11 -080077
Igor Murashkin53765732013-02-20 17:41:57 -080078void ProCamera::onLockStatusChanged(
79 IProCameraCallbacks::LockStatus newLockStatus)
80{
81 ALOGV("%s: newLockStatus = %d", __FUNCTION__, newLockStatus);
82
83 sp<ProCameraListener> listener;
84 {
85 Mutex::Autolock _l(mLock);
86 listener = mListener;
87 }
88 if (listener != NULL) {
89 switch (newLockStatus) {
90 case IProCameraCallbacks::LOCK_ACQUIRED:
91 listener->onLockAcquired();
92 break;
93 case IProCameraCallbacks::LOCK_RELEASED:
94 listener->onLockReleased();
95 break;
96 case IProCameraCallbacks::LOCK_STOLEN:
97 listener->onLockStolen();
98 break;
99 default:
100 ALOGE("%s: Unknown lock status: %d",
101 __FUNCTION__, newLockStatus);
102 }
103 }
104}
105
Igor Murashkina91537e2013-02-21 12:02:29 -0800106void ProCamera::onResultReceived(int32_t frameId, camera_metadata* result) {
107 ALOGV("%s: frameId = %d, result = %p", __FUNCTION__, frameId, result);
108
109 sp<ProCameraListener> listener;
110 {
111 Mutex::Autolock _l(mLock);
112 listener = mListener;
113 }
Igor Murashkina140a6e2013-02-21 14:45:03 -0800114
115 CameraMetadata tmp(result);
116
117 // Unblock waitForFrame(id) callers
118 {
119 Mutex::Autolock al(mWaitMutex);
120 mMetadataReady = true;
121 mLatestMetadata = tmp;
122 mWaitCondition.broadcast();
123 }
124
125 result = tmp.release();
126
Igor Murashkina91537e2013-02-21 12:02:29 -0800127 if (listener != NULL) {
128 listener->onResultReceived(frameId, result);
129 } else {
130 free_camera_metadata(result);
131 }
132
133}
134
Igor Murashkin634a5152013-02-20 17:15:11 -0800135status_t ProCamera::exclusiveTryLock()
136{
137 sp <IProCameraUser> c = mCamera;
138 if (c == 0) return NO_INIT;
139
140 return c->exclusiveTryLock();
141}
142status_t ProCamera::exclusiveLock()
143{
144 sp <IProCameraUser> c = mCamera;
145 if (c == 0) return NO_INIT;
146
147 return c->exclusiveLock();
148}
149status_t ProCamera::exclusiveUnlock()
150{
151 sp <IProCameraUser> c = mCamera;
152 if (c == 0) return NO_INIT;
153
154 return c->exclusiveUnlock();
155}
156bool ProCamera::hasExclusiveLock()
157{
158 sp <IProCameraUser> c = mCamera;
159 if (c == 0) return NO_INIT;
160
161 return c->hasExclusiveLock();
162}
163
164// Note that the callee gets a copy of the metadata.
165int ProCamera::submitRequest(const struct camera_metadata* metadata,
166 bool streaming)
167{
168 sp <IProCameraUser> c = mCamera;
169 if (c == 0) return NO_INIT;
170
171 return c->submitRequest(const_cast<struct camera_metadata*>(metadata),
172 streaming);
173}
174
175status_t ProCamera::cancelRequest(int requestId)
176{
177 sp <IProCameraUser> c = mCamera;
178 if (c == 0) return NO_INIT;
179
180 return c->cancelRequest(requestId);
181}
182
Igor Murashkin5835cc42013-02-20 19:29:53 -0800183status_t ProCamera::deleteStream(int streamId)
Igor Murashkin634a5152013-02-20 17:15:11 -0800184{
185 sp <IProCameraUser> c = mCamera;
186 if (c == 0) return NO_INIT;
187
Igor Murashkin5835cc42013-02-20 19:29:53 -0800188 status_t s = c->cancelStream(streamId);
Igor Murashkin634a5152013-02-20 17:15:11 -0800189
Igor Murashkin5835cc42013-02-20 19:29:53 -0800190 mStreams.removeItem(streamId);
191
192 return s;
Igor Murashkin634a5152013-02-20 17:15:11 -0800193}
194
Igor Murashkin68506fd2013-02-20 17:57:31 -0800195status_t ProCamera::createStream(int width, int height, int format,
Igor Murashkinc073ba52013-02-26 14:32:34 -0800196 const sp<Surface>& surface,
197 /*out*/
198 int* streamId)
Igor Murashkin68506fd2013-02-20 17:57:31 -0800199{
200 *streamId = -1;
201
202 ALOGV("%s: createStreamW %dx%d (fmt=0x%x)", __FUNCTION__, width, height,
203 format);
204
Igor Murashkin985fd302013-02-20 18:24:43 -0800205 if (surface == 0) {
Igor Murashkin68506fd2013-02-20 17:57:31 -0800206 return BAD_VALUE;
207 }
208
Igor Murashkinc073ba52013-02-26 14:32:34 -0800209 return createStream(width, height, format,
210 surface->getIGraphicBufferProducer(),
Igor Murashkin5835cc42013-02-20 19:29:53 -0800211 streamId);
Igor Murashkin68506fd2013-02-20 17:57:31 -0800212}
213
214status_t ProCamera::createStream(int width, int height, int format,
Igor Murashkinc073ba52013-02-26 14:32:34 -0800215 const sp<IGraphicBufferProducer>& bufferProducer,
216 /*out*/
217 int* streamId) {
Igor Murashkin5835cc42013-02-20 19:29:53 -0800218 *streamId = -1;
Igor Murashkin68506fd2013-02-20 17:57:31 -0800219
220 ALOGV("%s: createStreamT %dx%d (fmt=0x%x)", __FUNCTION__, width, height,
221 format);
222
Igor Murashkin5835cc42013-02-20 19:29:53 -0800223 if (bufferProducer == 0) {
Igor Murashkin68506fd2013-02-20 17:57:31 -0800224 return BAD_VALUE;
225 }
226
Igor Murashkin5835cc42013-02-20 19:29:53 -0800227 sp <IProCameraUser> c = mCamera;
228 status_t stat = c->createStream(width, height, format, bufferProducer,
229 streamId);
230
231 if (stat == OK) {
232 StreamInfo s(*streamId);
233
234 mStreams.add(*streamId, s);
235 }
236
Igor Murashkin985fd302013-02-20 18:24:43 -0800237 return stat;
Igor Murashkin68506fd2013-02-20 17:57:31 -0800238}
239
Igor Murashkin5835cc42013-02-20 19:29:53 -0800240status_t ProCamera::createStreamCpu(int width, int height, int format,
Igor Murashkinc073ba52013-02-26 14:32:34 -0800241 int heapCount,
242 /*out*/
243 sp<CpuConsumer>* cpuConsumer,
244 int* streamId)
Igor Murashkin5835cc42013-02-20 19:29:53 -0800245{
246 ALOGV("%s: createStreamW %dx%d (fmt=0x%x)", __FUNCTION__, width, height,
247 format);
248
Igor Murashkina140a6e2013-02-21 14:45:03 -0800249 *cpuConsumer = NULL;
250
Igor Murashkin5835cc42013-02-20 19:29:53 -0800251 sp <IProCameraUser> c = mCamera;
252 if (c == 0) return NO_INIT;
253
254 sp<CpuConsumer> cc = new CpuConsumer(heapCount);
255 cc->setName(String8("ProCamera::mCpuConsumer"));
256
257 sp<Surface> stc = new Surface(
258 cc->getProducerInterface());
259
Igor Murashkinc073ba52013-02-26 14:32:34 -0800260 status_t s = createStream(width, height, format,
261 stc->getIGraphicBufferProducer(),
262 streamId);
Igor Murashkin5835cc42013-02-20 19:29:53 -0800263
264 if (s != OK) {
265 ALOGE("%s: Failure to create stream %dx%d (fmt=0x%x)", __FUNCTION__,
266 width, height, format);
267 return s;
268 }
269
270 sp<ProFrameListener> frameAvailableListener =
271 new ProFrameListener(this, *streamId);
272
273 getStreamInfo(*streamId).cpuStream = true;
274 getStreamInfo(*streamId).cpuConsumer = cc;
275 getStreamInfo(*streamId).stc = stc;
276 // for lifetime management
277 getStreamInfo(*streamId).frameAvailableListener = frameAvailableListener;
278
279 cc->setFrameAvailableListener(frameAvailableListener);
280
Igor Murashkina140a6e2013-02-21 14:45:03 -0800281 *cpuConsumer = cc;
282
Igor Murashkin5835cc42013-02-20 19:29:53 -0800283 return s;
284}
285
Igor Murashkin68506fd2013-02-20 17:57:31 -0800286camera_metadata* ProCamera::getCameraInfo(int cameraId) {
Igor Murashkin68506fd2013-02-20 17:57:31 -0800287 ALOGV("%s: cameraId = %d", __FUNCTION__, cameraId);
Igor Murashkin7b33a742013-02-21 13:49:26 -0800288
289 sp <IProCameraUser> c = mCamera;
290 if (c == 0) return NULL;
291
292 camera_metadata* ptr = NULL;
293 status_t status = c->getCameraInfo(cameraId, &ptr);
294
295 if (status != OK) {
296 ALOGE("%s: Failed to get camera info, error = %d", __FUNCTION__, status);
297 }
298
299 return ptr;
Igor Murashkin68506fd2013-02-20 17:57:31 -0800300}
301
302status_t ProCamera::createDefaultRequest(int templateId,
303 camera_metadata** request) const {
Igor Murashkin68506fd2013-02-20 17:57:31 -0800304 ALOGV("%s: templateId = %d", __FUNCTION__, templateId);
305
Igor Murashkin985fd302013-02-20 18:24:43 -0800306 sp <IProCameraUser> c = mCamera;
307 if (c == 0) return NO_INIT;
308
309 return c->createDefaultRequest(templateId, request);
Igor Murashkin68506fd2013-02-20 17:57:31 -0800310}
311
Igor Murashkin5835cc42013-02-20 19:29:53 -0800312void ProCamera::onFrameAvailable(int streamId) {
313 ALOGV("%s: streamId = %d", __FUNCTION__, streamId);
314
315 sp<ProCameraListener> listener = mListener;
Igor Murashkina140a6e2013-02-21 14:45:03 -0800316 StreamInfo& stream = getStreamInfo(streamId);
317
318 CpuConsumer::LockedBuffer buf;
319
Igor Murashkin5835cc42013-02-20 19:29:53 -0800320 if (listener.get() != NULL) {
Igor Murashkina140a6e2013-02-21 14:45:03 -0800321 if (listener->useOnFrameAvailable()) {
322 listener->onFrameAvailable(streamId, stream.cpuConsumer);
Igor Murashkin5835cc42013-02-20 19:29:53 -0800323 return;
324 }
Igor Murashkina140a6e2013-02-21 14:45:03 -0800325 }
Igor Murashkin5835cc42013-02-20 19:29:53 -0800326
Igor Murashkina140a6e2013-02-21 14:45:03 -0800327 // Unblock waitForFrame(id) callers
328 {
329 Mutex::Autolock al(mWaitMutex);
Igor Murashkin4bc4a382013-02-20 13:36:17 -0800330 getStreamInfo(streamId).frameReady++;
Igor Murashkina140a6e2013-02-21 14:45:03 -0800331 mWaitCondition.broadcast();
332 }
333}
Igor Murashkin5835cc42013-02-20 19:29:53 -0800334
Igor Murashkin4bc4a382013-02-20 13:36:17 -0800335int ProCamera::waitForFrameBuffer(int streamId) {
Igor Murashkina140a6e2013-02-21 14:45:03 -0800336 status_t stat = BAD_VALUE;
337 Mutex::Autolock al(mWaitMutex);
338
339 StreamInfo& si = getStreamInfo(streamId);
340
Igor Murashkin4bc4a382013-02-20 13:36:17 -0800341 if (si.frameReady > 0) {
342 int numFrames = si.frameReady;
343 si.frameReady = 0;
344 return numFrames;
Igor Murashkina140a6e2013-02-21 14:45:03 -0800345 } else {
346 while (true) {
347 stat = mWaitCondition.waitRelative(mWaitMutex,
348 mWaitTimeout);
349 if (stat != OK) {
350 ALOGE("%s: Error while waiting for frame buffer: %d",
351 __FUNCTION__, stat);
352 return stat;
353 }
354
Igor Murashkin4bc4a382013-02-20 13:36:17 -0800355 if (si.frameReady > 0) {
356 int numFrames = si.frameReady;
357 si.frameReady = 0;
358 return numFrames;
Igor Murashkina140a6e2013-02-21 14:45:03 -0800359 }
360 // else it was some other stream that got unblocked
Igor Murashkin5835cc42013-02-20 19:29:53 -0800361 }
362 }
Igor Murashkina140a6e2013-02-21 14:45:03 -0800363
364 return stat;
365}
366
Igor Murashkin4bc4a382013-02-20 13:36:17 -0800367int ProCamera::dropFrameBuffer(int streamId, int count) {
368 StreamInfo& si = getStreamInfo(streamId);
369
370 if (!si.cpuStream) {
371 return BAD_VALUE;
372 } else if (count < 0) {
373 return BAD_VALUE;
374 }
375
376 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;
423 mLatestMetadata.release();
424
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