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 37 namespace android { 38 39 sp<ProCamera> ProCamera::connect(int cameraId) 40 { 41 return CameraBaseT::connect(cameraId, String16(), 42 ICameraService::USE_CALLING_UID); 43 } 44 45 ProCamera::ProCamera(int cameraId) 46 : CameraBase(cameraId) 47 { 48 } 49 50 ProCamera::~ProCamera() 51 { 52 53 } 54 55 /* IProCameraUser's implementation */ 56 57 // callback from camera service 58 void ProCamera::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2) 59 { 60 return CameraBaseT::notifyCallback(msgType, ext1, ext2); 61 } 62 63 void 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 91 void 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 120 status_t ProCamera::exclusiveTryLock() 121 { 122 sp <IProCameraUser> c = mCamera; 123 if (c == 0) return NO_INIT; 124 125 return c->exclusiveTryLock(); 126 } 127 status_t ProCamera::exclusiveLock() 128 { 129 sp <IProCameraUser> c = mCamera; 130 if (c == 0) return NO_INIT; 131 132 return c->exclusiveLock(); 133 } 134 status_t ProCamera::exclusiveUnlock() 135 { 136 sp <IProCameraUser> c = mCamera; 137 if (c == 0) return NO_INIT; 138 139 return c->exclusiveUnlock(); 140 } 141 bool 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. 150 int 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 160 status_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 168 status_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 180 status_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 199 status_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 225 status_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 235 status_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<CpuConsumer> cc = new CpuConsumer(heapCount, synchronousMode); 251 cc->setName(String8("ProCamera::mCpuConsumer")); 252 253 sp<Surface> stc = new Surface( 254 cc->getProducerInterface()); 255 256 status_t s = createStream(width, height, format, 257 stc->getIGraphicBufferProducer(), 258 streamId); 259 260 if (s != OK) { 261 ALOGE("%s: Failure to create stream %dx%d (fmt=0x%x)", __FUNCTION__, 262 width, height, format); 263 return s; 264 } 265 266 sp<ProFrameListener> frameAvailableListener = 267 new ProFrameListener(this, *streamId); 268 269 getStreamInfo(*streamId).cpuStream = true; 270 getStreamInfo(*streamId).cpuConsumer = cc; 271 getStreamInfo(*streamId).synchronousMode = synchronousMode; 272 getStreamInfo(*streamId).stc = stc; 273 // for lifetime management 274 getStreamInfo(*streamId).frameAvailableListener = frameAvailableListener; 275 276 cc->setFrameAvailableListener(frameAvailableListener); 277 278 *cpuConsumer = cc; 279 280 return s; 281 } 282 283 camera_metadata* ProCamera::getCameraInfo(int cameraId) { 284 ALOGV("%s: cameraId = %d", __FUNCTION__, cameraId); 285 286 sp <IProCameraUser> c = mCamera; 287 if (c == 0) return NULL; 288 289 camera_metadata* ptr = NULL; 290 status_t status = c->getCameraInfo(cameraId, &ptr); 291 292 if (status != OK) { 293 ALOGE("%s: Failed to get camera info, error = %d", __FUNCTION__, status); 294 } 295 296 return ptr; 297 } 298 299 status_t ProCamera::createDefaultRequest(int templateId, 300 camera_metadata** request) const { 301 ALOGV("%s: templateId = %d", __FUNCTION__, templateId); 302 303 sp <IProCameraUser> c = mCamera; 304 if (c == 0) return NO_INIT; 305 306 return c->createDefaultRequest(templateId, request); 307 } 308 309 void ProCamera::onFrameAvailable(int streamId) { 310 ALOGV("%s: streamId = %d", __FUNCTION__, streamId); 311 312 sp<ProCameraListener> listener = mListener; 313 StreamInfo& stream = getStreamInfo(streamId); 314 315 if (listener.get() != NULL) { 316 listener->onFrameAvailable(streamId, stream.cpuConsumer); 317 } 318 319 // Unblock waitForFrame(id) callers 320 { 321 Mutex::Autolock al(mWaitMutex); 322 getStreamInfo(streamId).frameReady++; 323 mWaitCondition.broadcast(); 324 } 325 } 326 327 int ProCamera::waitForFrameBuffer(int streamId) { 328 status_t stat = BAD_VALUE; 329 Mutex::Autolock al(mWaitMutex); 330 331 StreamInfo& si = getStreamInfo(streamId); 332 333 if (si.frameReady > 0) { 334 int numFrames = si.frameReady; 335 si.frameReady = 0; 336 return numFrames; 337 } else { 338 while (true) { 339 stat = mWaitCondition.waitRelative(mWaitMutex, 340 mWaitTimeout); 341 if (stat != OK) { 342 ALOGE("%s: Error while waiting for frame buffer: %d", 343 __FUNCTION__, stat); 344 return stat; 345 } 346 347 if (si.frameReady > 0) { 348 int numFrames = si.frameReady; 349 si.frameReady = 0; 350 return numFrames; 351 } 352 // else it was some other stream that got unblocked 353 } 354 } 355 356 return stat; 357 } 358 359 int ProCamera::dropFrameBuffer(int streamId, int count) { 360 StreamInfo& si = getStreamInfo(streamId); 361 362 if (!si.cpuStream) { 363 return BAD_VALUE; 364 } else if (count < 0) { 365 return BAD_VALUE; 366 } 367 368 if (!si.synchronousMode) { 369 ALOGW("%s: No need to drop frames on asynchronous streams," 370 " as asynchronous mode only keeps 1 latest frame around.", 371 __FUNCTION__); 372 return BAD_VALUE; 373 } 374 375 int numDropped = 0; 376 for (int i = 0; i < count; ++i) { 377 CpuConsumer::LockedBuffer buffer; 378 if (si.cpuConsumer->lockNextBuffer(&buffer) != OK) { 379 break; 380 } 381 382 si.cpuConsumer->unlockBuffer(buffer); 383 numDropped++; 384 } 385 386 return numDropped; 387 } 388 389 status_t ProCamera::waitForFrameMetadata() { 390 status_t stat = BAD_VALUE; 391 Mutex::Autolock al(mWaitMutex); 392 393 if (mMetadataReady) { 394 return OK; 395 } else { 396 while (true) { 397 stat = mWaitCondition.waitRelative(mWaitMutex, 398 mWaitTimeout); 399 400 if (stat != OK) { 401 ALOGE("%s: Error while waiting for metadata: %d", 402 __FUNCTION__, stat); 403 return stat; 404 } 405 406 if (mMetadataReady) { 407 mMetadataReady = false; 408 return OK; 409 } 410 // else it was some other stream or metadata 411 } 412 } 413 414 return stat; 415 } 416 417 CameraMetadata ProCamera::consumeFrameMetadata() { 418 Mutex::Autolock al(mWaitMutex); 419 420 // Destructive: Subsequent calls return empty metadatas 421 CameraMetadata tmp = mLatestMetadata; 422 mLatestMetadata.clear(); 423 424 return tmp; 425 } 426 427 ProCamera::StreamInfo& ProCamera::getStreamInfo(int streamId) { 428 return mStreams.editValueFor(streamId); 429 } 430 431 }; // namespace android 432