ProCamera.cpp revision c073ba525404f3416c2824c435d3d926a9892f1b
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{ 246 ALOGV("%s: createStreamW %dx%d (fmt=0x%x)", __FUNCTION__, width, height, 247 format); 248 249 *cpuConsumer = NULL; 250 251 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 260 status_t s = createStream(width, height, format, 261 stc->getIGraphicBufferProducer(), 262 streamId); 263 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 281 *cpuConsumer = cc; 282 283 return s; 284} 285 286camera_metadata* ProCamera::getCameraInfo(int cameraId) { 287 ALOGV("%s: cameraId = %d", __FUNCTION__, cameraId); 288 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; 300} 301 302status_t ProCamera::createDefaultRequest(int templateId, 303 camera_metadata** request) const { 304 ALOGV("%s: templateId = %d", __FUNCTION__, templateId); 305 306 sp <IProCameraUser> c = mCamera; 307 if (c == 0) return NO_INIT; 308 309 return c->createDefaultRequest(templateId, request); 310} 311 312void ProCamera::onFrameAvailable(int streamId) { 313 ALOGV("%s: streamId = %d", __FUNCTION__, streamId); 314 315 sp<ProCameraListener> listener = mListener; 316 StreamInfo& stream = getStreamInfo(streamId); 317 318 CpuConsumer::LockedBuffer buf; 319 320 if (listener.get() != NULL) { 321 if (listener->useOnFrameAvailable()) { 322 listener->onFrameAvailable(streamId, stream.cpuConsumer); 323 return; 324 } 325 } 326 327 // Unblock waitForFrame(id) callers 328 { 329 Mutex::Autolock al(mWaitMutex); 330 getStreamInfo(streamId).frameReady++; 331 mWaitCondition.broadcast(); 332 } 333} 334 335int ProCamera::waitForFrameBuffer(int streamId) { 336 status_t stat = BAD_VALUE; 337 Mutex::Autolock al(mWaitMutex); 338 339 StreamInfo& si = getStreamInfo(streamId); 340 341 if (si.frameReady > 0) { 342 int numFrames = si.frameReady; 343 si.frameReady = 0; 344 return numFrames; 345 } 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 355 if (si.frameReady > 0) { 356 int numFrames = si.frameReady; 357 si.frameReady = 0; 358 return numFrames; 359 } 360 // else it was some other stream that got unblocked 361 } 362 } 363 364 return stat; 365} 366 367int 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 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.release(); 424 425 return tmp; 426} 427 428ProCamera::StreamInfo& ProCamera::getStreamInfo(int streamId) { 429 return mStreams.editValueFor(streamId); 430} 431 432}; // namespace android 433