ProCamera.cpp revision a140a6efea1db7837984b3578755cfa4eaa8d92d
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#include <gui/Surface.h> 35 36#include <system/camera_metadata.h> 37 38namespace android { 39 40// client singleton for camera service binder interface 41Mutex ProCamera::mLock; 42sp<ICameraService> ProCamera::mCameraService; 43sp<ProCamera::DeathNotifier> ProCamera::mDeathNotifier; 44 45// establish binder interface to camera service 46const sp<ICameraService>& ProCamera::getCameraService() 47{ 48 Mutex::Autolock _l(mLock); 49 if (mCameraService.get() == 0) { 50 sp<IServiceManager> sm = defaultServiceManager(); 51 sp<IBinder> binder; 52 do { 53 binder = sm->getService(String16("media.camera")); 54 if (binder != 0) 55 break; 56 ALOGW("CameraService not published, waiting..."); 57 usleep(500000); // 0.5 s 58 } while(true); 59 if (mDeathNotifier == NULL) { 60 mDeathNotifier = new DeathNotifier(); 61 } 62 binder->linkToDeath(mDeathNotifier); 63 mCameraService = interface_cast<ICameraService>(binder); 64 } 65 ALOGE_IF(mCameraService==0, "no CameraService!?"); 66 return mCameraService; 67} 68 69sp<ProCamera> ProCamera::connect(int cameraId) 70{ 71 ALOGV("connect"); 72 sp<ProCamera> c = new ProCamera(); 73 sp<IProCameraCallbacks> cl = c; 74 const sp<ICameraService>& cs = getCameraService(); 75 if (cs != 0) { 76 c->mCamera = cs->connect(cl, cameraId); 77 } 78 if (c->mCamera != 0) { 79 c->mCamera->asBinder()->linkToDeath(c); 80 c->mStatus = NO_ERROR; 81 } else { 82 c.clear(); 83 } 84 return c; 85} 86 87void ProCamera::disconnect() 88{ 89 ALOGV("%s: disconnect", __FUNCTION__); 90 if (mCamera != 0) { 91 mCamera->disconnect(); 92 mCamera->asBinder()->unlinkToDeath(this); 93 mCamera = 0; 94 } 95 ALOGV("%s: disconnect (done)", __FUNCTION__); 96} 97 98ProCamera::ProCamera() 99{ 100} 101 102ProCamera::~ProCamera() 103{ 104 105} 106 107sp<IProCameraUser> ProCamera::remote() 108{ 109 return mCamera; 110} 111 112void ProCamera::binderDied(const wp<IBinder>& who) { 113 ALOGW("IProCameraUser died"); 114 notifyCallback(CAMERA_MSG_ERROR, CAMERA_ERROR_SERVER_DIED, 0); 115} 116 117void ProCamera::DeathNotifier::binderDied(const wp<IBinder>& who) { 118 ALOGV("binderDied"); 119 Mutex::Autolock _l(ProCamera::mLock); 120 ProCamera::mCameraService.clear(); 121 ALOGW("Camera service died!"); 122} 123 124void ProCamera::setListener(const sp<ProCameraListener>& listener) 125{ 126 Mutex::Autolock _l(mLock); 127 mListener = listener; 128} 129 130 131// callback from camera service 132void ProCamera::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2) 133{ 134 sp<ProCameraListener> listener; 135 { 136 Mutex::Autolock _l(mLock); 137 listener = mListener; 138 } 139 if (listener != NULL) { 140 listener->notify(msgType, ext1, ext2); 141 } 142} 143 144// callback from camera service when frame or image is ready 145void ProCamera::dataCallback(int32_t msgType, const sp<IMemory>& dataPtr, 146 camera_frame_metadata_t *metadata) 147{ 148 sp<ProCameraListener> listener; 149 { 150 Mutex::Autolock _l(mLock); 151 listener = mListener; 152 } 153 if (listener != NULL) { 154 listener->postData(msgType, dataPtr, metadata); 155 } 156} 157 158// callback from camera service when timestamped frame is ready 159void ProCamera::dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, 160 const sp<IMemory>& dataPtr) 161{ 162 sp<ProCameraListener> listener; 163 { 164 Mutex::Autolock _l(mLock); 165 listener = mListener; 166 } 167 if (listener != NULL) { 168 listener->postDataTimestamp(timestamp, msgType, dataPtr); 169 } else { 170 ALOGW("No listener was set. Drop a recording frame."); 171 } 172} 173 174/* IProCameraUser's implementation */ 175 176void ProCamera::onLockStatusChanged( 177 IProCameraCallbacks::LockStatus newLockStatus) 178{ 179 ALOGV("%s: newLockStatus = %d", __FUNCTION__, newLockStatus); 180 181 sp<ProCameraListener> listener; 182 { 183 Mutex::Autolock _l(mLock); 184 listener = mListener; 185 } 186 if (listener != NULL) { 187 switch (newLockStatus) { 188 case IProCameraCallbacks::LOCK_ACQUIRED: 189 listener->onLockAcquired(); 190 break; 191 case IProCameraCallbacks::LOCK_RELEASED: 192 listener->onLockReleased(); 193 break; 194 case IProCameraCallbacks::LOCK_STOLEN: 195 listener->onLockStolen(); 196 break; 197 default: 198 ALOGE("%s: Unknown lock status: %d", 199 __FUNCTION__, newLockStatus); 200 } 201 } 202} 203 204void ProCamera::onResultReceived(int32_t frameId, camera_metadata* result) { 205 ALOGV("%s: frameId = %d, result = %p", __FUNCTION__, frameId, result); 206 207 sp<ProCameraListener> listener; 208 { 209 Mutex::Autolock _l(mLock); 210 listener = mListener; 211 } 212 213 CameraMetadata tmp(result); 214 215 // Unblock waitForFrame(id) callers 216 { 217 Mutex::Autolock al(mWaitMutex); 218 mMetadataReady = true; 219 mLatestMetadata = tmp; 220 mWaitCondition.broadcast(); 221 } 222 223 result = tmp.release(); 224 225 if (listener != NULL) { 226 listener->onResultReceived(frameId, result); 227 } else { 228 free_camera_metadata(result); 229 } 230 231} 232 233status_t ProCamera::exclusiveTryLock() 234{ 235 sp <IProCameraUser> c = mCamera; 236 if (c == 0) return NO_INIT; 237 238 return c->exclusiveTryLock(); 239} 240status_t ProCamera::exclusiveLock() 241{ 242 sp <IProCameraUser> c = mCamera; 243 if (c == 0) return NO_INIT; 244 245 return c->exclusiveLock(); 246} 247status_t ProCamera::exclusiveUnlock() 248{ 249 sp <IProCameraUser> c = mCamera; 250 if (c == 0) return NO_INIT; 251 252 return c->exclusiveUnlock(); 253} 254bool ProCamera::hasExclusiveLock() 255{ 256 sp <IProCameraUser> c = mCamera; 257 if (c == 0) return NO_INIT; 258 259 return c->hasExclusiveLock(); 260} 261 262// Note that the callee gets a copy of the metadata. 263int ProCamera::submitRequest(const struct camera_metadata* metadata, 264 bool streaming) 265{ 266 sp <IProCameraUser> c = mCamera; 267 if (c == 0) return NO_INIT; 268 269 return c->submitRequest(const_cast<struct camera_metadata*>(metadata), 270 streaming); 271} 272 273status_t ProCamera::cancelRequest(int requestId) 274{ 275 sp <IProCameraUser> c = mCamera; 276 if (c == 0) return NO_INIT; 277 278 return c->cancelRequest(requestId); 279} 280 281status_t ProCamera::deleteStream(int streamId) 282{ 283 sp <IProCameraUser> c = mCamera; 284 if (c == 0) return NO_INIT; 285 286 status_t s = c->cancelStream(streamId); 287 288 mStreams.removeItem(streamId); 289 290 return s; 291} 292 293status_t ProCamera::createStream(int width, int height, int format, 294 const sp<Surface>& surface, 295 /*out*/ 296 int* streamId) 297{ 298 *streamId = -1; 299 300 ALOGV("%s: createStreamW %dx%d (fmt=0x%x)", __FUNCTION__, width, height, 301 format); 302 303 if (surface == 0) { 304 return BAD_VALUE; 305 } 306 307 return createStream(width, height, format, surface->getIGraphicBufferProducer(), 308 streamId); 309} 310 311status_t ProCamera::createStream(int width, int height, int format, 312 const sp<IGraphicBufferProducer>& bufferProducer, 313 /*out*/ 314 int* streamId) { 315 *streamId = -1; 316 317 ALOGV("%s: createStreamT %dx%d (fmt=0x%x)", __FUNCTION__, width, height, 318 format); 319 320 if (bufferProducer == 0) { 321 return BAD_VALUE; 322 } 323 324 sp <IProCameraUser> c = mCamera; 325 status_t stat = c->createStream(width, height, format, bufferProducer, 326 streamId); 327 328 if (stat == OK) { 329 StreamInfo s(*streamId); 330 331 mStreams.add(*streamId, s); 332 } 333 334 return stat; 335} 336 337status_t ProCamera::createStreamCpu(int width, int height, int format, 338 int heapCount, 339 /*out*/ 340 sp<CpuConsumer>* cpuConsumer, 341 int* streamId) 342{ 343 ALOGV("%s: createStreamW %dx%d (fmt=0x%x)", __FUNCTION__, width, height, 344 format); 345 346 *cpuConsumer = NULL; 347 348 sp <IProCameraUser> c = mCamera; 349 if (c == 0) return NO_INIT; 350 351 sp<CpuConsumer> cc = new CpuConsumer(heapCount); 352 cc->setName(String8("ProCamera::mCpuConsumer")); 353 354 sp<Surface> stc = new Surface( 355 cc->getProducerInterface()); 356 357 status_t s = createStream(width, height, format, stc->getIGraphicBufferProducer(), 358 streamId); 359 360 if (s != OK) { 361 ALOGE("%s: Failure to create stream %dx%d (fmt=0x%x)", __FUNCTION__, 362 width, height, format); 363 return s; 364 } 365 366 sp<ProFrameListener> frameAvailableListener = 367 new ProFrameListener(this, *streamId); 368 369 getStreamInfo(*streamId).cpuStream = true; 370 getStreamInfo(*streamId).cpuConsumer = cc; 371 getStreamInfo(*streamId).stc = stc; 372 // for lifetime management 373 getStreamInfo(*streamId).frameAvailableListener = frameAvailableListener; 374 375 cc->setFrameAvailableListener(frameAvailableListener); 376 377 *cpuConsumer = cc; 378 379 return s; 380} 381 382int ProCamera::getNumberOfCameras() { 383 const sp<ICameraService> cs = getCameraService(); 384 385 if (!cs.get()) { 386 return DEAD_OBJECT; 387 } 388 return cs->getNumberOfCameras(); 389} 390 391camera_metadata* ProCamera::getCameraInfo(int cameraId) { 392 ALOGV("%s: cameraId = %d", __FUNCTION__, cameraId); 393 394 sp <IProCameraUser> c = mCamera; 395 if (c == 0) return NULL; 396 397 camera_metadata* ptr = NULL; 398 status_t status = c->getCameraInfo(cameraId, &ptr); 399 400 if (status != OK) { 401 ALOGE("%s: Failed to get camera info, error = %d", __FUNCTION__, status); 402 } 403 404 return ptr; 405} 406 407status_t ProCamera::createDefaultRequest(int templateId, 408 camera_metadata** request) const { 409 ALOGV("%s: templateId = %d", __FUNCTION__, templateId); 410 411 sp <IProCameraUser> c = mCamera; 412 if (c == 0) return NO_INIT; 413 414 return c->createDefaultRequest(templateId, request); 415} 416 417void ProCamera::onFrameAvailable(int streamId) { 418 ALOGV("%s: streamId = %d", __FUNCTION__, streamId); 419 420 sp<ProCameraListener> listener = mListener; 421 StreamInfo& stream = getStreamInfo(streamId); 422 423 CpuConsumer::LockedBuffer buf; 424 425 if (listener.get() != NULL) { 426 if (listener->useOnFrameAvailable()) { 427 listener->onFrameAvailable(streamId, stream.cpuConsumer); 428 return; 429 } 430 } 431 432 // Unblock waitForFrame(id) callers 433 { 434 Mutex::Autolock al(mWaitMutex); 435 getStreamInfo(streamId).frameReady = true; 436 mWaitCondition.broadcast(); 437 } 438} 439 440status_t ProCamera::waitForFrameBuffer(int streamId) { 441 status_t stat = BAD_VALUE; 442 Mutex::Autolock al(mWaitMutex); 443 444 StreamInfo& si = getStreamInfo(streamId); 445 446 if (si.frameReady) { 447 si.frameReady = false; 448 return OK; 449 } else { 450 while (true) { 451 stat = mWaitCondition.waitRelative(mWaitMutex, 452 mWaitTimeout); 453 if (stat != OK) { 454 ALOGE("%s: Error while waiting for frame buffer: %d", 455 __FUNCTION__, stat); 456 return stat; 457 } 458 459 if (si.frameReady) { 460 si.frameReady = false; 461 return OK; 462 } 463 // else it was some other stream that got unblocked 464 } 465 } 466 467 return stat; 468} 469 470status_t ProCamera::waitForFrameMetadata() { 471 status_t stat = BAD_VALUE; 472 Mutex::Autolock al(mWaitMutex); 473 474 if (mMetadataReady) { 475 return OK; 476 } else { 477 while (true) { 478 stat = mWaitCondition.waitRelative(mWaitMutex, 479 mWaitTimeout); 480 481 if (stat != OK) { 482 ALOGE("%s: Error while waiting for metadata: %d", 483 __FUNCTION__, stat); 484 return stat; 485 } 486 487 if (mMetadataReady) { 488 mMetadataReady = false; 489 return OK; 490 } 491 // else it was some other stream or metadata 492 } 493 } 494 495 return stat; 496} 497 498CameraMetadata ProCamera::consumeFrameMetadata() { 499 Mutex::Autolock al(mWaitMutex); 500 501 // Destructive: Subsequent calls return empty metadatas 502 CameraMetadata tmp = mLatestMetadata; 503 mLatestMetadata.release(); 504 505 return tmp; 506} 507 508ProCamera::StreamInfo& ProCamera::getStreamInfo(int streamId) { 509 return mStreams.editValueFor(streamId); 510} 511 512}; // namespace android 513