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/IProCameraUser.h> 30 #include <camera/IProCameraCallbacks.h> 31 32 #include <gui/IGraphicBufferProducer.h> 33 34 #include <system/camera_metadata.h> 35 36 namespace android { 37 38 sp<ProCamera> ProCamera::connect(int cameraId) 39 { 40 return CameraBaseT::connect(cameraId, String16(), 41 ICameraService::USE_CALLING_UID); 42 } 43 44 ProCamera::ProCamera(int cameraId) 45 : CameraBase(cameraId) 46 { 47 } 48 49 CameraTraits<ProCamera>::TCamConnectService CameraTraits<ProCamera>::fnConnectService = 50 &ICameraService::connectPro; 51 52 ProCamera::~ProCamera() 53 { 54 55 } 56 57 /* IProCameraUser's implementation */ 58 59 // callback from camera service 60 void ProCamera::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2) 61 { 62 return CameraBaseT::notifyCallback(msgType, ext1, ext2); 63 } 64 65 void ProCamera::onLockStatusChanged( 66 IProCameraCallbacks::LockStatus newLockStatus) 67 { 68 ALOGV("%s: newLockStatus = %d", __FUNCTION__, newLockStatus); 69 70 sp<ProCameraListener> listener; 71 { 72 Mutex::Autolock _l(mLock); 73 listener = mListener; 74 } 75 if (listener != NULL) { 76 switch (newLockStatus) { 77 case IProCameraCallbacks::LOCK_ACQUIRED: 78 listener->onLockAcquired(); 79 break; 80 case IProCameraCallbacks::LOCK_RELEASED: 81 listener->onLockReleased(); 82 break; 83 case IProCameraCallbacks::LOCK_STOLEN: 84 listener->onLockStolen(); 85 break; 86 default: 87 ALOGE("%s: Unknown lock status: %d", 88 __FUNCTION__, newLockStatus); 89 } 90 } 91 } 92 93 void ProCamera::onResultReceived(int32_t requestId, camera_metadata* result) { 94 ALOGV("%s: requestId = %d, result = %p", __FUNCTION__, requestId, result); 95 96 sp<ProCameraListener> listener; 97 { 98 Mutex::Autolock _l(mLock); 99 listener = mListener; 100 } 101 102 CameraMetadata tmp(result); 103 104 // Unblock waitForFrame(id) callers 105 { 106 Mutex::Autolock al(mWaitMutex); 107 mMetadataReady = true; 108 mLatestMetadata = tmp; // make copy 109 mWaitCondition.broadcast(); 110 } 111 112 result = tmp.release(); 113 114 if (listener != NULL) { 115 listener->onResultReceived(requestId, result); 116 } else { 117 free_camera_metadata(result); 118 } 119 120 } 121 122 status_t ProCamera::exclusiveTryLock() 123 { 124 sp <IProCameraUser> c = mCamera; 125 if (c == 0) return NO_INIT; 126 127 return c->exclusiveTryLock(); 128 } 129 status_t ProCamera::exclusiveLock() 130 { 131 sp <IProCameraUser> c = mCamera; 132 if (c == 0) return NO_INIT; 133 134 return c->exclusiveLock(); 135 } 136 status_t ProCamera::exclusiveUnlock() 137 { 138 sp <IProCameraUser> c = mCamera; 139 if (c == 0) return NO_INIT; 140 141 return c->exclusiveUnlock(); 142 } 143 bool ProCamera::hasExclusiveLock() 144 { 145 sp <IProCameraUser> c = mCamera; 146 if (c == 0) return NO_INIT; 147 148 return c->hasExclusiveLock(); 149 } 150 151 // Note that the callee gets a copy of the metadata. 152 int ProCamera::submitRequest(const struct camera_metadata* metadata, 153 bool streaming) 154 { 155 sp <IProCameraUser> c = mCamera; 156 if (c == 0) return NO_INIT; 157 158 return c->submitRequest(const_cast<struct camera_metadata*>(metadata), 159 streaming); 160 } 161 162 status_t ProCamera::cancelRequest(int requestId) 163 { 164 sp <IProCameraUser> c = mCamera; 165 if (c == 0) return NO_INIT; 166 167 return c->cancelRequest(requestId); 168 } 169 170 status_t ProCamera::deleteStream(int streamId) 171 { 172 sp <IProCameraUser> c = mCamera; 173 if (c == 0) return NO_INIT; 174 175 status_t s = c->deleteStream(streamId); 176 177 mStreams.removeItem(streamId); 178 179 return s; 180 } 181 182 status_t ProCamera::createStream(int width, int height, int format, 183 const sp<Surface>& surface, 184 /*out*/ 185 int* streamId) 186 { 187 *streamId = -1; 188 189 ALOGV("%s: createStreamW %dx%d (fmt=0x%x)", __FUNCTION__, width, height, 190 format); 191 192 if (surface == 0) { 193 return BAD_VALUE; 194 } 195 196 return createStream(width, height, format, 197 surface->getIGraphicBufferProducer(), 198 streamId); 199 } 200 201 status_t ProCamera::createStream(int width, int height, int format, 202 const sp<IGraphicBufferProducer>& bufferProducer, 203 /*out*/ 204 int* streamId) { 205 *streamId = -1; 206 207 ALOGV("%s: createStreamT %dx%d (fmt=0x%x)", __FUNCTION__, width, height, 208 format); 209 210 if (bufferProducer == 0) { 211 return BAD_VALUE; 212 } 213 214 sp <IProCameraUser> c = mCamera; 215 status_t stat = c->createStream(width, height, format, bufferProducer, 216 streamId); 217 218 if (stat == OK) { 219 StreamInfo s(*streamId); 220 221 mStreams.add(*streamId, s); 222 } 223 224 return stat; 225 } 226 227 status_t ProCamera::createStreamCpu(int width, int height, int format, 228 int heapCount, 229 /*out*/ 230 sp<CpuConsumer>* cpuConsumer, 231 int* streamId) { 232 return createStreamCpu(width, height, format, heapCount, 233 /*synchronousMode*/true, 234 cpuConsumer, streamId); 235 } 236 237 status_t ProCamera::createStreamCpu(int width, int height, int format, 238 int heapCount, 239 bool synchronousMode, 240 /*out*/ 241 sp<CpuConsumer>* cpuConsumer, 242 int* streamId) 243 { 244 ALOGV("%s: createStreamW %dx%d (fmt=0x%x)", __FUNCTION__, width, height, 245 format); 246 247 *cpuConsumer = NULL; 248 249 sp <IProCameraUser> c = mCamera; 250 if (c == 0) return NO_INIT; 251 252 sp<BufferQueue> bq = new BufferQueue(); 253 sp<CpuConsumer> cc = new CpuConsumer(bq, heapCount/*, synchronousMode*/); 254 cc->setName(String8("ProCamera::mCpuConsumer")); 255 256 sp<Surface> stc = new Surface(bq); 257 258 status_t s = createStream(width, height, format, 259 stc->getIGraphicBufferProducer(), 260 streamId); 261 262 if (s != OK) { 263 ALOGE("%s: Failure to create stream %dx%d (fmt=0x%x)", __FUNCTION__, 264 width, height, format); 265 return s; 266 } 267 268 sp<ProFrameListener> frameAvailableListener = 269 new ProFrameListener(this, *streamId); 270 271 getStreamInfo(*streamId).cpuStream = true; 272 getStreamInfo(*streamId).cpuConsumer = cc; 273 getStreamInfo(*streamId).synchronousMode = synchronousMode; 274 getStreamInfo(*streamId).stc = stc; 275 // for lifetime management 276 getStreamInfo(*streamId).frameAvailableListener = frameAvailableListener; 277 278 cc->setFrameAvailableListener(frameAvailableListener); 279 280 *cpuConsumer = cc; 281 282 return s; 283 } 284 285 camera_metadata* ProCamera::getCameraInfo(int cameraId) { 286 ALOGV("%s: cameraId = %d", __FUNCTION__, cameraId); 287 288 sp <IProCameraUser> c = mCamera; 289 if (c == 0) return NULL; 290 291 camera_metadata* ptr = NULL; 292 status_t status = c->getCameraInfo(cameraId, &ptr); 293 294 if (status != OK) { 295 ALOGE("%s: Failed to get camera info, error = %d", __FUNCTION__, status); 296 } 297 298 return ptr; 299 } 300 301 status_t ProCamera::createDefaultRequest(int templateId, 302 camera_metadata** request) const { 303 ALOGV("%s: templateId = %d", __FUNCTION__, templateId); 304 305 sp <IProCameraUser> c = mCamera; 306 if (c == 0) return NO_INIT; 307 308 return c->createDefaultRequest(templateId, request); 309 } 310 311 void ProCamera::onFrameAvailable(int streamId) { 312 ALOGV("%s: streamId = %d", __FUNCTION__, streamId); 313 314 sp<ProCameraListener> listener = mListener; 315 StreamInfo& stream = getStreamInfo(streamId); 316 317 if (listener.get() != NULL) { 318 listener->onFrameAvailable(streamId, stream.cpuConsumer); 319 } 320 321 // Unblock waitForFrame(id) callers 322 { 323 Mutex::Autolock al(mWaitMutex); 324 getStreamInfo(streamId).frameReady++; 325 mWaitCondition.broadcast(); 326 } 327 } 328 329 int ProCamera::waitForFrameBuffer(int streamId) { 330 status_t stat = BAD_VALUE; 331 Mutex::Autolock al(mWaitMutex); 332 333 StreamInfo& si = getStreamInfo(streamId); 334 335 if (si.frameReady > 0) { 336 int numFrames = si.frameReady; 337 si.frameReady = 0; 338 return numFrames; 339 } else { 340 while (true) { 341 stat = mWaitCondition.waitRelative(mWaitMutex, 342 mWaitTimeout); 343 if (stat != OK) { 344 ALOGE("%s: Error while waiting for frame buffer: %d", 345 __FUNCTION__, stat); 346 return stat; 347 } 348 349 if (si.frameReady > 0) { 350 int numFrames = si.frameReady; 351 si.frameReady = 0; 352 return numFrames; 353 } 354 // else it was some other stream that got unblocked 355 } 356 } 357 358 return stat; 359 } 360 361 int ProCamera::dropFrameBuffer(int streamId, int count) { 362 StreamInfo& si = getStreamInfo(streamId); 363 364 if (!si.cpuStream) { 365 return BAD_VALUE; 366 } else if (count < 0) { 367 return BAD_VALUE; 368 } 369 370 if (!si.synchronousMode) { 371 ALOGW("%s: No need to drop frames on asynchronous streams," 372 " as asynchronous mode only keeps 1 latest frame around.", 373 __FUNCTION__); 374 return BAD_VALUE; 375 } 376 377 int numDropped = 0; 378 for (int i = 0; i < count; ++i) { 379 CpuConsumer::LockedBuffer buffer; 380 if (si.cpuConsumer->lockNextBuffer(&buffer) != OK) { 381 break; 382 } 383 384 si.cpuConsumer->unlockBuffer(buffer); 385 numDropped++; 386 } 387 388 return numDropped; 389 } 390 391 status_t ProCamera::waitForFrameMetadata() { 392 status_t stat = BAD_VALUE; 393 Mutex::Autolock al(mWaitMutex); 394 395 if (mMetadataReady) { 396 return OK; 397 } else { 398 while (true) { 399 stat = mWaitCondition.waitRelative(mWaitMutex, 400 mWaitTimeout); 401 402 if (stat != OK) { 403 ALOGE("%s: Error while waiting for metadata: %d", 404 __FUNCTION__, stat); 405 return stat; 406 } 407 408 if (mMetadataReady) { 409 mMetadataReady = false; 410 return OK; 411 } 412 // else it was some other stream or metadata 413 } 414 } 415 416 return stat; 417 } 418 419 CameraMetadata ProCamera::consumeFrameMetadata() { 420 Mutex::Autolock al(mWaitMutex); 421 422 // Destructive: Subsequent calls return empty metadatas 423 CameraMetadata tmp = mLatestMetadata; 424 mLatestMetadata.clear(); 425 426 return tmp; 427 } 428 429 ProCamera::StreamInfo& ProCamera::getStreamInfo(int streamId) { 430 return mStreams.editValueFor(streamId); 431 } 432 433 }; // namespace android 434