ProCamera.cpp revision ba5ca4ee770fa0fe9e14990fd13b23f1010f5c98
1/* 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> 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 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{ 67 return CameraBaseT::dataCallback(msgType, dataPtr, metadata); 68} 69 70// callback from camera service when timestamped frame is ready 71void ProCamera::dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, 72 const sp<IMemory>& dataPtr) 73{ 74 CameraBaseT::dataCallbackTimestamp(timestamp, msgType, dataPtr); 75} 76 77 78void 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 106void 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 } 114 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 127 if (listener != NULL) { 128 listener->onResultReceived(frameId, result); 129 } else { 130 free_camera_metadata(result); 131 } 132 133} 134 135status_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 183status_t ProCamera::deleteStream(int streamId) 184{ 185 sp <IProCameraUser> c = mCamera; 186 if (c == 0) return NO_INIT; 187 188 status_t s = c->cancelStream(streamId); 189 190 mStreams.removeItem(streamId); 191 192 return s; 193} 194 195status_t ProCamera::createStream(int width, int height, int format, 196 const sp<Surface>& surface, 197 /*out*/ 198 int* streamId) 199{ 200 *streamId = -1; 201 202 ALOGV("%s: createStreamW %dx%d (fmt=0x%x)", __FUNCTION__, width, height, 203 format); 204 205 if (surface == 0) { 206 return BAD_VALUE; 207 } 208 209 return createStream(width, height, format, 210 surface->getIGraphicBufferProducer(), 211 streamId); 212} 213 214status_t ProCamera::createStream(int width, int height, int format, 215 const sp<IGraphicBufferProducer>& bufferProducer, 216 /*out*/ 217 int* streamId) { 218 *streamId = -1; 219 220 ALOGV("%s: createStreamT %dx%d (fmt=0x%x)", __FUNCTION__, width, height, 221 format); 222 223 if (bufferProducer == 0) { 224 return BAD_VALUE; 225 } 226 227 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 237 return stat; 238} 239 240status_t ProCamera::createStreamCpu(int width, int height, int format, 241 int heapCount, 242 /*out*/ 243 sp<CpuConsumer>* cpuConsumer, 244 int* streamId) { 245 return createStreamCpu(width, height, format, heapCount, 246 /*synchronousMode*/true, 247 cpuConsumer, streamId); 248} 249 250status_t ProCamera::createStreamCpu(int width, int height, int format, 251 int heapCount, 252 bool synchronousMode, 253 /*out*/ 254 sp<CpuConsumer>* cpuConsumer, 255 int* streamId) 256{ 257 ALOGV("%s: createStreamW %dx%d (fmt=0x%x)", __FUNCTION__, width, height, 258 format); 259 260 *cpuConsumer = NULL; 261 262 sp <IProCameraUser> c = mCamera; 263 if (c == 0) return NO_INIT; 264 265 sp<CpuConsumer> cc = new CpuConsumer(heapCount, synchronousMode); 266 cc->setName(String8("ProCamera::mCpuConsumer")); 267 268 sp<Surface> stc = new Surface( 269 cc->getProducerInterface()); 270 271 status_t s = createStream(width, height, format, 272 stc->getIGraphicBufferProducer(), 273 streamId); 274 275 if (s != OK) { 276 ALOGE("%s: Failure to create stream %dx%d (fmt=0x%x)", __FUNCTION__, 277 width, height, format); 278 return s; 279 } 280 281 sp<ProFrameListener> frameAvailableListener = 282 new ProFrameListener(this, *streamId); 283 284 getStreamInfo(*streamId).cpuStream = true; 285 getStreamInfo(*streamId).cpuConsumer = cc; 286 getStreamInfo(*streamId).synchronousMode = synchronousMode; 287 getStreamInfo(*streamId).stc = stc; 288 // for lifetime management 289 getStreamInfo(*streamId).frameAvailableListener = frameAvailableListener; 290 291 cc->setFrameAvailableListener(frameAvailableListener); 292 293 *cpuConsumer = cc; 294 295 return s; 296} 297 298camera_metadata* ProCamera::getCameraInfo(int cameraId) { 299 ALOGV("%s: cameraId = %d", __FUNCTION__, cameraId); 300 301 sp <IProCameraUser> c = mCamera; 302 if (c == 0) return NULL; 303 304 camera_metadata* ptr = NULL; 305 status_t status = c->getCameraInfo(cameraId, &ptr); 306 307 if (status != OK) { 308 ALOGE("%s: Failed to get camera info, error = %d", __FUNCTION__, status); 309 } 310 311 return ptr; 312} 313 314status_t ProCamera::createDefaultRequest(int templateId, 315 camera_metadata** request) const { 316 ALOGV("%s: templateId = %d", __FUNCTION__, templateId); 317 318 sp <IProCameraUser> c = mCamera; 319 if (c == 0) return NO_INIT; 320 321 return c->createDefaultRequest(templateId, request); 322} 323 324void ProCamera::onFrameAvailable(int streamId) { 325 ALOGV("%s: streamId = %d", __FUNCTION__, streamId); 326 327 sp<ProCameraListener> listener = mListener; 328 StreamInfo& stream = getStreamInfo(streamId); 329 330 CpuConsumer::LockedBuffer buf; 331 332 if (listener.get() != NULL) { 333 if (listener->useOnFrameAvailable()) { 334 listener->onFrameAvailable(streamId, stream.cpuConsumer); 335 return; 336 } 337 } 338 339 // Unblock waitForFrame(id) callers 340 { 341 Mutex::Autolock al(mWaitMutex); 342 getStreamInfo(streamId).frameReady++; 343 mWaitCondition.broadcast(); 344 } 345} 346 347int ProCamera::waitForFrameBuffer(int streamId) { 348 status_t stat = BAD_VALUE; 349 Mutex::Autolock al(mWaitMutex); 350 351 StreamInfo& si = getStreamInfo(streamId); 352 353 if (si.frameReady > 0) { 354 int numFrames = si.frameReady; 355 si.frameReady = 0; 356 return numFrames; 357 } else { 358 while (true) { 359 stat = mWaitCondition.waitRelative(mWaitMutex, 360 mWaitTimeout); 361 if (stat != OK) { 362 ALOGE("%s: Error while waiting for frame buffer: %d", 363 __FUNCTION__, stat); 364 return stat; 365 } 366 367 if (si.frameReady > 0) { 368 int numFrames = si.frameReady; 369 si.frameReady = 0; 370 return numFrames; 371 } 372 // else it was some other stream that got unblocked 373 } 374 } 375 376 return stat; 377} 378 379int ProCamera::dropFrameBuffer(int streamId, int count) { 380 StreamInfo& si = getStreamInfo(streamId); 381 382 if (!si.cpuStream) { 383 return BAD_VALUE; 384 } else if (count < 0) { 385 return BAD_VALUE; 386 } 387 388 if (!si.synchronousMode) { 389 ALOGW("%s: No need to drop frames on asynchronous streams," 390 " as asynchronous mode only keeps 1 latest frame around.", 391 __FUNCTION__); 392 return BAD_VALUE; 393 } 394 395 int numDropped = 0; 396 for (int i = 0; i < count; ++i) { 397 CpuConsumer::LockedBuffer buffer; 398 if (si.cpuConsumer->lockNextBuffer(&buffer) != OK) { 399 break; 400 } 401 402 si.cpuConsumer->unlockBuffer(buffer); 403 numDropped++; 404 } 405 406 return numDropped; 407} 408 409status_t ProCamera::waitForFrameMetadata() { 410 status_t stat = BAD_VALUE; 411 Mutex::Autolock al(mWaitMutex); 412 413 if (mMetadataReady) { 414 return OK; 415 } else { 416 while (true) { 417 stat = mWaitCondition.waitRelative(mWaitMutex, 418 mWaitTimeout); 419 420 if (stat != OK) { 421 ALOGE("%s: Error while waiting for metadata: %d", 422 __FUNCTION__, stat); 423 return stat; 424 } 425 426 if (mMetadataReady) { 427 mMetadataReady = false; 428 return OK; 429 } 430 // else it was some other stream or metadata 431 } 432 } 433 434 return stat; 435} 436 437CameraMetadata ProCamera::consumeFrameMetadata() { 438 Mutex::Autolock al(mWaitMutex); 439 440 // Destructive: Subsequent calls return empty metadatas 441 CameraMetadata tmp = mLatestMetadata; 442 mLatestMetadata.release(); 443 444 return tmp; 445} 446 447ProCamera::StreamInfo& ProCamera::getStreamInfo(int streamId) { 448 return mStreams.editValueFor(streamId); 449} 450 451}; // namespace android 452