ProCamera.cpp revision 8d764bfc74c40641f018a0aa87d6f484aec92eae
102debf605cd904edac8dceb196e5f142ce3d14ebJordan Rose/* 202debf605cd904edac8dceb196e5f142ce3d14ebJordan Rose** 302debf605cd904edac8dceb196e5f142ce3d14ebJordan Rose** Copyright (C) 2013, The Android Open Source Project 402debf605cd904edac8dceb196e5f142ce3d14ebJordan Rose** 502debf605cd904edac8dceb196e5f142ce3d14ebJordan Rose** Licensed under the Apache License, Version 2.0 (the "License"); 602debf605cd904edac8dceb196e5f142ce3d14ebJordan Rose** you may not use this file except in compliance with the License. 702debf605cd904edac8dceb196e5f142ce3d14ebJordan Rose** You may obtain a copy of the License at 802debf605cd904edac8dceb196e5f142ce3d14ebJordan Rose** 902debf605cd904edac8dceb196e5f142ce3d14ebJordan Rose** http://www.apache.org/licenses/LICENSE-2.0 1002debf605cd904edac8dceb196e5f142ce3d14ebJordan Rose** 1102debf605cd904edac8dceb196e5f142ce3d14ebJordan Rose** Unless required by applicable law or agreed to in writing, software 1202debf605cd904edac8dceb196e5f142ce3d14ebJordan Rose** distributed under the License is distributed on an "AS IS" BASIS, 1302debf605cd904edac8dceb196e5f142ce3d14ebJordan Rose** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1402debf605cd904edac8dceb196e5f142ce3d14ebJordan Rose** See the License for the specific language governing permissions and 1502debf605cd904edac8dceb196e5f142ce3d14ebJordan Rose** 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 35#include <system/camera_metadata.h> 36 37namespace android { 38 39sp<ProCamera> ProCamera::connect(int cameraId) 40{ 41 return CameraBaseT::connect(cameraId, String16(), 42 ICameraService::USE_CALLING_UID); 43} 44 45ProCamera::ProCamera(int cameraId) 46 : CameraBase(cameraId) 47{ 48} 49 50ProCamera::~ProCamera() 51{ 52 53} 54 55/* IProCameraUser's implementation */ 56 57// callback from camera service 58void ProCamera::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2) 59{ 60 return CameraBaseT::notifyCallback(msgType, ext1, ext2); 61} 62 63void 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 91void 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 } 99 100 CameraMetadata tmp(result); 101 102 // Unblock waitForFrame(id) callers 103 { 104 Mutex::Autolock al(mWaitMutex); 105 mMetadataReady = true; 106 mLatestMetadata = tmp; // make copy 107 mWaitCondition.broadcast(); 108 } 109 110 result = tmp.release(); 111 112 if (listener != NULL) { 113 listener->onResultReceived(frameId, result); 114 } else { 115 free_camera_metadata(result); 116 } 117 118} 119 120status_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 168status_t ProCamera::deleteStream(int streamId) 169{ 170 sp <IProCameraUser> c = mCamera; 171 if (c == 0) return NO_INIT; 172 173 status_t s = c->deleteStream(streamId); 174 175 mStreams.removeItem(streamId); 176 177 return s; 178} 179 180status_t ProCamera::createStream(int width, int height, int format, 181 const sp<Surface>& surface, 182 /*out*/ 183 int* streamId) 184{ 185 *streamId = -1; 186 187 ALOGV("%s: createStreamW %dx%d (fmt=0x%x)", __FUNCTION__, width, height, 188 format); 189 190 if (surface == 0) { 191 return BAD_VALUE; 192 } 193 194 return createStream(width, height, format, 195 surface->getIGraphicBufferProducer(), 196 streamId); 197} 198 199status_t ProCamera::createStream(int width, int height, int format, 200 const sp<IGraphicBufferProducer>& bufferProducer, 201 /*out*/ 202 int* streamId) { 203 *streamId = -1; 204 205 ALOGV("%s: createStreamT %dx%d (fmt=0x%x)", __FUNCTION__, width, height, 206 format); 207 208 if (bufferProducer == 0) { 209 return BAD_VALUE; 210 } 211 212 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 222 return stat; 223} 224 225status_t ProCamera::createStreamCpu(int width, int height, int format, 226 int heapCount, 227 /*out*/ 228 sp<CpuConsumer>* cpuConsumer, 229 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, 240 int* streamId) 241{ 242 ALOGV("%s: createStreamW %dx%d (fmt=0x%x)", __FUNCTION__, width, height, 243 format); 244 245 *cpuConsumer = NULL; 246 247 sp <IProCameraUser> c = mCamera; 248 if (c == 0) return NO_INIT; 249 250 sp<BufferQueue> bq = new BufferQueue(); 251 sp<CpuConsumer> cc = new CpuConsumer(bq, heapCount, synchronousMode); 252 cc->setName(String8("ProCamera::mCpuConsumer")); 253 254 sp<Surface> stc = new Surface( 255 cc->getProducerInterface()); 256 257 status_t s = createStream(width, height, format, 258 stc->getIGraphicBufferProducer(), 259 streamId); 260 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; 272 getStreamInfo(*streamId).synchronousMode = synchronousMode; 273 getStreamInfo(*streamId).stc = stc; 274 // for lifetime management 275 getStreamInfo(*streamId).frameAvailableListener = frameAvailableListener; 276 277 cc->setFrameAvailableListener(frameAvailableListener); 278 279 *cpuConsumer = cc; 280 281 return s; 282} 283 284camera_metadata* ProCamera::getCameraInfo(int cameraId) { 285 ALOGV("%s: cameraId = %d", __FUNCTION__, cameraId); 286 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; 298} 299 300status_t ProCamera::createDefaultRequest(int templateId, 301 camera_metadata** request) const { 302 ALOGV("%s: templateId = %d", __FUNCTION__, templateId); 303 304 sp <IProCameraUser> c = mCamera; 305 if (c == 0) return NO_INIT; 306 307 return c->createDefaultRequest(templateId, request); 308} 309 310void ProCamera::onFrameAvailable(int streamId) { 311 ALOGV("%s: streamId = %d", __FUNCTION__, streamId); 312 313 sp<ProCameraListener> listener = mListener; 314 StreamInfo& stream = getStreamInfo(streamId); 315 316 if (listener.get() != NULL) { 317 listener->onFrameAvailable(streamId, stream.cpuConsumer); 318 } 319 320 // Unblock waitForFrame(id) callers 321 { 322 Mutex::Autolock al(mWaitMutex); 323 getStreamInfo(streamId).frameReady++; 324 mWaitCondition.broadcast(); 325 } 326} 327 328int ProCamera::waitForFrameBuffer(int streamId) { 329 status_t stat = BAD_VALUE; 330 Mutex::Autolock al(mWaitMutex); 331 332 StreamInfo& si = getStreamInfo(streamId); 333 334 if (si.frameReady > 0) { 335 int numFrames = si.frameReady; 336 si.frameReady = 0; 337 return numFrames; 338 } 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 348 if (si.frameReady > 0) { 349 int numFrames = si.frameReady; 350 si.frameReady = 0; 351 return numFrames; 352 } 353 // else it was some other stream that got unblocked 354 } 355 } 356 357 return stat; 358} 359 360int 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 369 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 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 390status_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.clear(); 424 425 return tmp; 426} 427 428ProCamera::StreamInfo& ProCamera::getStreamInfo(int streamId) { 429 return mStreams.editValueFor(streamId); 430} 431 432}; // namespace android 433