3 ** Copyright (C) 2013, The Android Open Source Project
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
9 ** http://www.apache.org/licenses/LICENSE-2.0
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.
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>
24 #include <binder/IPCThreadState.h>
25 #include <binder/IServiceManager.h>
26 #include <binder/IMemory.h>
28 #include <camera/ProCamera.h>
29 #include <camera/IProCameraUser.h>
30 #include <camera/IProCameraCallbacks.h>
32 #include <gui/IGraphicBufferProducer.h>
34 #include <system/camera_metadata.h>
38 sp<ProCamera> ProCamera::connect(int cameraId)
40 return CameraBaseT::connect(cameraId, String16(),
41 ICameraService::USE_CALLING_UID);
44 ProCamera::ProCamera(int cameraId)
45 : CameraBase(cameraId)
49 CameraTraits<ProCamera>::TCamConnectService CameraTraits<ProCamera>::fnConnectService =
50 &ICameraService::connectPro;
52 ProCamera::~ProCamera()
57 /* IProCameraUser's implementation */
59 // callback from camera service
60 void ProCamera::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2)
62 return CameraBaseT::notifyCallback(msgType, ext1, ext2);
65 void ProCamera::onLockStatusChanged(
66 IProCameraCallbacks::LockStatus newLockStatus)
68 ALOGV("%s: newLockStatus = %d", __FUNCTION__, newLockStatus);
70 sp<ProCameraListener> listener;
72 Mutex::Autolock _l(mLock);
75 if (listener != NULL) {
76 switch (newLockStatus) {
77 case IProCameraCallbacks::LOCK_ACQUIRED:
78 listener->onLockAcquired();
80 case IProCameraCallbacks::LOCK_RELEASED:
81 listener->onLockReleased();
83 case IProCameraCallbacks::LOCK_STOLEN:
84 listener->onLockStolen();
87 ALOGE("%s: Unknown lock status: %d",
88 __FUNCTION__, newLockStatus);
93 void ProCamera::onResultReceived(int32_t requestId, camera_metadata* result) {
94 ALOGV("%s: requestId = %d, result = %p", __FUNCTION__, requestId, result);
96 sp<ProCameraListener> listener;
98 Mutex::Autolock _l(mLock);
102 CameraMetadata tmp(result);
104 // Unblock waitForFrame(id) callers
106 Mutex::Autolock al(mWaitMutex);
107 mMetadataReady = true;
108 mLatestMetadata = tmp; // make copy
109 mWaitCondition.broadcast();
112 result = tmp.release();
114 if (listener != NULL) {
115 listener->onResultReceived(requestId, result);
117 free_camera_metadata(result);
122 status_t ProCamera::exclusiveTryLock()
124 sp <IProCameraUser> c = mCamera;
125 if (c == 0) return NO_INIT;
127 return c->exclusiveTryLock();
129 status_t ProCamera::exclusiveLock()
131 sp <IProCameraUser> c = mCamera;
132 if (c == 0) return NO_INIT;
134 return c->exclusiveLock();
136 status_t ProCamera::exclusiveUnlock()
138 sp <IProCameraUser> c = mCamera;
139 if (c == 0) return NO_INIT;
141 return c->exclusiveUnlock();
143 bool ProCamera::hasExclusiveLock()
145 sp <IProCameraUser> c = mCamera;
146 if (c == 0) return NO_INIT;
148 return c->hasExclusiveLock();
151 // Note that the callee gets a copy of the metadata.
152 int ProCamera::submitRequest(const struct camera_metadata* metadata,
155 sp <IProCameraUser> c = mCamera;
156 if (c == 0) return NO_INIT;
158 return c->submitRequest(const_cast<struct camera_metadata*>(metadata),
162 status_t ProCamera::cancelRequest(int requestId)
164 sp <IProCameraUser> c = mCamera;
165 if (c == 0) return NO_INIT;
167 return c->cancelRequest(requestId);
170 status_t ProCamera::deleteStream(int streamId)
172 sp <IProCameraUser> c = mCamera;
173 if (c == 0) return NO_INIT;
175 status_t s = c->deleteStream(streamId);
177 mStreams.removeItem(streamId);
182 status_t ProCamera::createStream(int width, int height, int format,
183 const sp<Surface>& surface,
189 ALOGV("%s: createStreamW %dx%d (fmt=0x%x)", __FUNCTION__, width, height,
196 return createStream(width, height, format,
197 surface->getIGraphicBufferProducer(),
201 status_t ProCamera::createStream(int width, int height, int format,
202 const sp<IGraphicBufferProducer>& bufferProducer,
207 ALOGV("%s: createStreamT %dx%d (fmt=0x%x)", __FUNCTION__, width, height,
210 if (bufferProducer == 0) {
214 sp <IProCameraUser> c = mCamera;
215 status_t stat = c->createStream(width, height, format, bufferProducer,
219 StreamInfo s(*streamId);
221 mStreams.add(*streamId, s);
227 status_t ProCamera::createStreamCpu(int width, int height, int format,
230 sp<CpuConsumer>* cpuConsumer,
232 return createStreamCpu(width, height, format, heapCount,
233 /*synchronousMode*/true,
234 cpuConsumer, streamId);
237 status_t ProCamera::createStreamCpu(int width, int height, int format,
239 bool synchronousMode,
241 sp<CpuConsumer>* cpuConsumer,
244 ALOGV("%s: createStreamW %dx%d (fmt=0x%x)", __FUNCTION__, width, height,
249 sp <IProCameraUser> c = mCamera;
250 if (c == 0) return NO_INIT;
252 sp<IGraphicBufferProducer> producer;
253 sp<IGraphicBufferConsumer> consumer;
254 BufferQueue::createBufferQueue(&producer, &consumer);
255 sp<CpuConsumer> cc = new CpuConsumer(consumer, heapCount
256 /*, synchronousMode*/);
257 cc->setName(String8("ProCamera::mCpuConsumer"));
259 sp<Surface> stc = new Surface(producer);
261 status_t s = createStream(width, height, format,
262 stc->getIGraphicBufferProducer(),
266 ALOGE("%s: Failure to create stream %dx%d (fmt=0x%x)", __FUNCTION__,
267 width, height, format);
271 sp<ProFrameListener> frameAvailableListener =
272 new ProFrameListener(this, *streamId);
274 getStreamInfo(*streamId).cpuStream = true;
275 getStreamInfo(*streamId).cpuConsumer = cc;
276 getStreamInfo(*streamId).synchronousMode = synchronousMode;
277 getStreamInfo(*streamId).stc = stc;
278 // for lifetime management
279 getStreamInfo(*streamId).frameAvailableListener = frameAvailableListener;
281 cc->setFrameAvailableListener(frameAvailableListener);
288 camera_metadata* ProCamera::getCameraInfo(int cameraId) {
289 ALOGV("%s: cameraId = %d", __FUNCTION__, cameraId);
291 sp <IProCameraUser> c = mCamera;
292 if (c == 0) return NULL;
294 camera_metadata* ptr = NULL;
295 status_t status = c->getCameraInfo(cameraId, &ptr);
298 ALOGE("%s: Failed to get camera info, error = %d", __FUNCTION__, status);
304 status_t ProCamera::createDefaultRequest(int templateId,
305 camera_metadata** request) const {
306 ALOGV("%s: templateId = %d", __FUNCTION__, templateId);
308 sp <IProCameraUser> c = mCamera;
309 if (c == 0) return NO_INIT;
311 return c->createDefaultRequest(templateId, request);
314 void ProCamera::onFrameAvailable(int streamId) {
315 ALOGV("%s: streamId = %d", __FUNCTION__, streamId);
317 sp<ProCameraListener> listener = mListener;
318 StreamInfo& stream = getStreamInfo(streamId);
320 if (listener.get() != NULL) {
321 listener->onFrameAvailable(streamId, stream.cpuConsumer);
324 // Unblock waitForFrame(id) callers
326 Mutex::Autolock al(mWaitMutex);
327 getStreamInfo(streamId).frameReady++;
328 mWaitCondition.broadcast();
332 int ProCamera::waitForFrameBuffer(int streamId) {
333 status_t stat = BAD_VALUE;
334 Mutex::Autolock al(mWaitMutex);
336 StreamInfo& si = getStreamInfo(streamId);
338 if (si.frameReady > 0) {
339 int numFrames = si.frameReady;
344 stat = mWaitCondition.waitRelative(mWaitMutex,
347 ALOGE("%s: Error while waiting for frame buffer: %d",
352 if (si.frameReady > 0) {
353 int numFrames = si.frameReady;
357 // else it was some other stream that got unblocked
364 int ProCamera::dropFrameBuffer(int streamId, int count) {
365 StreamInfo& si = getStreamInfo(streamId);
369 } else if (count < 0) {
373 if (!si.synchronousMode) {
374 ALOGW("%s: No need to drop frames on asynchronous streams,"
375 " as asynchronous mode only keeps 1 latest frame around.",
381 for (int i = 0; i < count; ++i) {
382 CpuConsumer::LockedBuffer buffer;
383 if (si.cpuConsumer->lockNextBuffer(&buffer) != OK) {
387 si.cpuConsumer->unlockBuffer(buffer);
394 status_t ProCamera::waitForFrameMetadata() {
395 status_t stat = BAD_VALUE;
396 Mutex::Autolock al(mWaitMutex);
398 if (mMetadataReady) {
402 stat = mWaitCondition.waitRelative(mWaitMutex,
406 ALOGE("%s: Error while waiting for metadata: %d",
411 if (mMetadataReady) {
412 mMetadataReady = false;
415 // else it was some other stream or metadata
422 CameraMetadata ProCamera::consumeFrameMetadata() {
423 Mutex::Autolock al(mWaitMutex);
425 // Destructive: Subsequent calls return empty metadatas
426 CameraMetadata tmp = mLatestMetadata;
427 mLatestMetadata.clear();
432 ProCamera::StreamInfo& ProCamera::getStreamInfo(int streamId) {
433 return mStreams.editValueFor(streamId);
436 }; // namespace android