ProCamera.cpp revision d127c2c8a8b68dae2f8743c310c2547e8f46d967
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("disconnect"); 90 if (mCamera != 0) { 91 mCamera->disconnect(); 92 mCamera->asBinder()->unlinkToDeath(this); 93 mCamera = 0; 94 } 95} 96 97ProCamera::ProCamera() 98{ 99} 100 101ProCamera::~ProCamera() 102{ 103 104} 105 106sp<IProCameraUser> ProCamera::remote() 107{ 108 return mCamera; 109} 110 111void ProCamera::binderDied(const wp<IBinder>& who) { 112 ALOGW("IProCameraUser died"); 113 notifyCallback(CAMERA_MSG_ERROR, CAMERA_ERROR_SERVER_DIED, 0); 114} 115 116void ProCamera::DeathNotifier::binderDied(const wp<IBinder>& who) { 117 ALOGV("binderDied"); 118 Mutex::Autolock _l(ProCamera::mLock); 119 ProCamera::mCameraService.clear(); 120 ALOGW("Camera service died!"); 121} 122 123void ProCamera::setListener(const sp<ProCameraListener>& listener) 124{ 125 Mutex::Autolock _l(mLock); 126 mListener = listener; 127} 128 129 130// callback from camera service 131void ProCamera::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2) 132{ 133 sp<ProCameraListener> listener; 134 { 135 Mutex::Autolock _l(mLock); 136 listener = mListener; 137 } 138 if (listener != NULL) { 139 listener->notify(msgType, ext1, ext2); 140 } 141} 142 143// callback from camera service when frame or image is ready 144void ProCamera::dataCallback(int32_t msgType, const sp<IMemory>& dataPtr, 145 camera_frame_metadata_t *metadata) 146{ 147 sp<ProCameraListener> listener; 148 { 149 Mutex::Autolock _l(mLock); 150 listener = mListener; 151 } 152 if (listener != NULL) { 153 listener->postData(msgType, dataPtr, metadata); 154 } 155} 156 157// callback from camera service when timestamped frame is ready 158void ProCamera::dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, 159 const sp<IMemory>& dataPtr) 160{ 161 sp<ProCameraListener> listener; 162 { 163 Mutex::Autolock _l(mLock); 164 listener = mListener; 165 } 166 if (listener != NULL) { 167 listener->postDataTimestamp(timestamp, msgType, dataPtr); 168 } else { 169 ALOGW("No listener was set. Drop a recording frame."); 170 } 171} 172 173/* IProCameraUser's implementation */ 174 175void ProCamera::onLockStatusChanged( 176 IProCameraCallbacks::LockStatus newLockStatus) 177{ 178 ALOGV("%s: newLockStatus = %d", __FUNCTION__, newLockStatus); 179 180 sp<ProCameraListener> listener; 181 { 182 Mutex::Autolock _l(mLock); 183 listener = mListener; 184 } 185 if (listener != NULL) { 186 switch (newLockStatus) { 187 case IProCameraCallbacks::LOCK_ACQUIRED: 188 listener->onLockAcquired(); 189 break; 190 case IProCameraCallbacks::LOCK_RELEASED: 191 listener->onLockReleased(); 192 break; 193 case IProCameraCallbacks::LOCK_STOLEN: 194 listener->onLockStolen(); 195 break; 196 default: 197 ALOGE("%s: Unknown lock status: %d", 198 __FUNCTION__, newLockStatus); 199 } 200 } 201} 202 203void ProCamera::onResultReceived(int32_t frameId, camera_metadata* result) { 204 ALOGV("%s: frameId = %d, result = %p", __FUNCTION__, frameId, result); 205 206 sp<ProCameraListener> listener; 207 { 208 Mutex::Autolock _l(mLock); 209 listener = mListener; 210 } 211 if (listener != NULL) { 212 listener->onResultReceived(frameId, result); 213 } else { 214 free_camera_metadata(result); 215 } 216 217} 218 219status_t ProCamera::exclusiveTryLock() 220{ 221 sp <IProCameraUser> c = mCamera; 222 if (c == 0) return NO_INIT; 223 224 return c->exclusiveTryLock(); 225} 226status_t ProCamera::exclusiveLock() 227{ 228 sp <IProCameraUser> c = mCamera; 229 if (c == 0) return NO_INIT; 230 231 return c->exclusiveLock(); 232} 233status_t ProCamera::exclusiveUnlock() 234{ 235 sp <IProCameraUser> c = mCamera; 236 if (c == 0) return NO_INIT; 237 238 return c->exclusiveUnlock(); 239} 240bool ProCamera::hasExclusiveLock() 241{ 242 sp <IProCameraUser> c = mCamera; 243 if (c == 0) return NO_INIT; 244 245 return c->hasExclusiveLock(); 246} 247 248// Note that the callee gets a copy of the metadata. 249int ProCamera::submitRequest(const struct camera_metadata* metadata, 250 bool streaming) 251{ 252 sp <IProCameraUser> c = mCamera; 253 if (c == 0) return NO_INIT; 254 255 return c->submitRequest(const_cast<struct camera_metadata*>(metadata), 256 streaming); 257} 258 259status_t ProCamera::cancelRequest(int requestId) 260{ 261 sp <IProCameraUser> c = mCamera; 262 if (c == 0) return NO_INIT; 263 264 return c->cancelRequest(requestId); 265} 266 267status_t ProCamera::deleteStream(int streamId) 268{ 269 sp <IProCameraUser> c = mCamera; 270 if (c == 0) return NO_INIT; 271 272 status_t s = c->cancelStream(streamId); 273 274 mStreams.removeItem(streamId); 275 276 return s; 277} 278 279status_t ProCamera::createStream(int width, int height, int format, 280 const sp<Surface>& surface, 281 /*out*/ 282 int* streamId) 283{ 284 *streamId = -1; 285 286 ALOGV("%s: createStreamW %dx%d (fmt=0x%x)", __FUNCTION__, width, height, 287 format); 288 289 if (surface == 0) { 290 return BAD_VALUE; 291 } 292 293 return createStream(width, height, format, surface->getIGraphicBufferProducer(), 294 streamId); 295} 296 297status_t ProCamera::createStream(int width, int height, int format, 298 const sp<IGraphicBufferProducer>& bufferProducer, 299 /*out*/ 300 int* streamId) { 301 *streamId = -1; 302 303 ALOGV("%s: createStreamT %dx%d (fmt=0x%x)", __FUNCTION__, width, height, 304 format); 305 306 if (bufferProducer == 0) { 307 return BAD_VALUE; 308 } 309 310 sp <IProCameraUser> c = mCamera; 311 status_t stat = c->createStream(width, height, format, bufferProducer, 312 streamId); 313 314 if (stat == OK) { 315 StreamInfo s(*streamId); 316 317 mStreams.add(*streamId, s); 318 } 319 320 return stat; 321} 322 323status_t ProCamera::createStreamCpu(int width, int height, int format, 324 int heapCount, 325 /*out*/ 326 int* streamId) 327{ 328 ALOGV("%s: createStreamW %dx%d (fmt=0x%x)", __FUNCTION__, width, height, 329 format); 330 331 sp <IProCameraUser> c = mCamera; 332 if (c == 0) return NO_INIT; 333 334 sp<CpuConsumer> cc = new CpuConsumer(heapCount); 335 cc->setName(String8("ProCamera::mCpuConsumer")); 336 337 sp<Surface> stc = new Surface( 338 cc->getProducerInterface()); 339 340 status_t s = createStream(width, height, format, stc->getIGraphicBufferProducer(), 341 streamId); 342 343 if (s != OK) { 344 ALOGE("%s: Failure to create stream %dx%d (fmt=0x%x)", __FUNCTION__, 345 width, height, format); 346 return s; 347 } 348 349 sp<ProFrameListener> frameAvailableListener = 350 new ProFrameListener(this, *streamId); 351 352 getStreamInfo(*streamId).cpuStream = true; 353 getStreamInfo(*streamId).cpuConsumer = cc; 354 getStreamInfo(*streamId).stc = stc; 355 // for lifetime management 356 getStreamInfo(*streamId).frameAvailableListener = frameAvailableListener; 357 358 cc->setFrameAvailableListener(frameAvailableListener); 359 360 return s; 361} 362 363int ProCamera::getNumberOfCameras() { 364 const sp<ICameraService> cs = getCameraService(); 365 366 if (!cs.get()) { 367 return DEAD_OBJECT; 368 } 369 return cs->getNumberOfCameras(); 370} 371 372camera_metadata* ProCamera::getCameraInfo(int cameraId) { 373 ALOGV("%s: cameraId = %d", __FUNCTION__, cameraId); 374 375 sp <IProCameraUser> c = mCamera; 376 if (c == 0) return NULL; 377 378 camera_metadata* ptr = NULL; 379 status_t status = c->getCameraInfo(cameraId, &ptr); 380 381 if (status != OK) { 382 ALOGE("%s: Failed to get camera info, error = %d", __FUNCTION__, status); 383 } 384 385 return ptr; 386} 387 388status_t ProCamera::createDefaultRequest(int templateId, 389 camera_metadata** request) const { 390 ALOGV("%s: templateId = %d", __FUNCTION__, templateId); 391 392 sp <IProCameraUser> c = mCamera; 393 if (c == 0) return NO_INIT; 394 395 return c->createDefaultRequest(templateId, request); 396} 397 398void ProCamera::onFrameAvailable(int streamId) { 399 ALOGV("%s: streamId = %d", __FUNCTION__, streamId); 400 401 sp<ProCameraListener> listener = mListener; 402 if (listener.get() != NULL) { 403 StreamInfo& stream = getStreamInfo(streamId); 404 405 CpuConsumer::LockedBuffer buf; 406 407 status_t stat = stream.cpuConsumer->lockNextBuffer(&buf); 408 if (stat != OK) { 409 ALOGE("%s: Failed to lock buffer, error code = %d", __FUNCTION__, 410 stat); 411 return; 412 } 413 414 listener->onBufferReceived(streamId, buf); 415 stat = stream.cpuConsumer->unlockBuffer(buf); 416 417 if (stat != OK) { 418 ALOGE("%s: Failed to unlock buffer, error code = %d", __FUNCTION__, 419 stat); 420 } 421 } 422} 423 424ProCamera::StreamInfo& ProCamera::getStreamInfo(int streamId) { 425 return mStreams.editValueFor(streamId); 426} 427 428}; // namespace android 429