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<IGraphicBufferProducer> producer; 253 sp<IGraphicBufferConsumer> consumer; 254 BufferQueue::createBufferQueue(&producer, &consumer); 255 sp<CpuConsumer> cc = new CpuConsumer(consumer, heapCount 256 /*, synchronousMode*/); 257 cc->setName(String8("ProCamera::mCpuConsumer")); 258 259 sp<Surface> stc = new Surface(producer); 260 261 status_t s = createStream(width, height, format, 262 stc->getIGraphicBufferProducer(), 263 streamId); 264 265 if (s != OK) { 266 ALOGE("%s: Failure to create stream %dx%d (fmt=0x%x)", __FUNCTION__, 267 width, height, format); 268 return s; 269 } 270 271 sp<ProFrameListener> frameAvailableListener = 272 new ProFrameListener(this, *streamId); 273 274 getStreamInfo(*streamId).cpuStream = true; 275 getStreamInfo(*streamId).cpuConsumer = cc; 276 getStreamInfo(*streamId).synchronousMode = synchronousMode; 277 getStreamInfo(*streamId).stc = stc; 278 // for lifetime management 279 getStreamInfo(*streamId).frameAvailableListener = frameAvailableListener; 280 281 cc->setFrameAvailableListener(frameAvailableListener); 282 283 *cpuConsumer = cc; 284 285 return s; 286 } 287 288 camera_metadata* ProCamera::getCameraInfo(int cameraId) { 289 ALOGV("%s: cameraId = %d", __FUNCTION__, cameraId); 290 291 sp <IProCameraUser> c = mCamera; 292 if (c == 0) return NULL; 293 294 camera_metadata* ptr = NULL; 295 status_t status = c->getCameraInfo(cameraId, &ptr); 296 297 if (status != OK) { 298 ALOGE("%s: Failed to get camera info, error = %d", __FUNCTION__, status); 299 } 300 301 return ptr; 302 } 303 304 status_t ProCamera::createDefaultRequest(int templateId, 305 camera_metadata** request) const { 306 ALOGV("%s: templateId = %d", __FUNCTION__, templateId); 307 308 sp <IProCameraUser> c = mCamera; 309 if (c == 0) return NO_INIT; 310 311 return c->createDefaultRequest(templateId, request); 312 } 313 314 void ProCamera::onFrameAvailable(int streamId) { 315 ALOGV("%s: streamId = %d", __FUNCTION__, streamId); 316 317 sp<ProCameraListener> listener = mListener; 318 StreamInfo& stream = getStreamInfo(streamId); 319 320 if (listener.get() != NULL) { 321 listener->onFrameAvailable(streamId, stream.cpuConsumer); 322 } 323 324 // Unblock waitForFrame(id) callers 325 { 326 Mutex::Autolock al(mWaitMutex); 327 getStreamInfo(streamId).frameReady++; 328 mWaitCondition.broadcast(); 329 } 330 } 331 332 int ProCamera::waitForFrameBuffer(int streamId) { 333 status_t stat = BAD_VALUE; 334 Mutex::Autolock al(mWaitMutex); 335 336 StreamInfo& si = getStreamInfo(streamId); 337 338 if (si.frameReady > 0) { 339 int numFrames = si.frameReady; 340 si.frameReady = 0; 341 return numFrames; 342 } else { 343 while (true) { 344 stat = mWaitCondition.waitRelative(mWaitMutex, 345 mWaitTimeout); 346 if (stat != OK) { 347 ALOGE("%s: Error while waiting for frame buffer: %d", 348 __FUNCTION__, stat); 349 return stat; 350 } 351 352 if (si.frameReady > 0) { 353 int numFrames = si.frameReady; 354 si.frameReady = 0; 355 return numFrames; 356 } 357 // else it was some other stream that got unblocked 358 } 359 } 360 361 return stat; 362 } 363 364 int ProCamera::dropFrameBuffer(int streamId, int count) { 365 StreamInfo& si = getStreamInfo(streamId); 366 367 if (!si.cpuStream) { 368 return BAD_VALUE; 369 } else if (count < 0) { 370 return BAD_VALUE; 371 } 372 373 if (!si.synchronousMode) { 374 ALOGW("%s: No need to drop frames on asynchronous streams," 375 " as asynchronous mode only keeps 1 latest frame around.", 376 __FUNCTION__); 377 return BAD_VALUE; 378 } 379 380 int numDropped = 0; 381 for (int i = 0; i < count; ++i) { 382 CpuConsumer::LockedBuffer buffer; 383 if (si.cpuConsumer->lockNextBuffer(&buffer) != OK) { 384 break; 385 } 386 387 si.cpuConsumer->unlockBuffer(buffer); 388 numDropped++; 389 } 390 391 return numDropped; 392 } 393 394 status_t ProCamera::waitForFrameMetadata() { 395 status_t stat = BAD_VALUE; 396 Mutex::Autolock al(mWaitMutex); 397 398 if (mMetadataReady) { 399 return OK; 400 } else { 401 while (true) { 402 stat = mWaitCondition.waitRelative(mWaitMutex, 403 mWaitTimeout); 404 405 if (stat != OK) { 406 ALOGE("%s: Error while waiting for metadata: %d", 407 __FUNCTION__, stat); 408 return stat; 409 } 410 411 if (mMetadataReady) { 412 mMetadataReady = false; 413 return OK; 414 } 415 // else it was some other stream or metadata 416 } 417 } 418 419 return stat; 420 } 421 422 CameraMetadata ProCamera::consumeFrameMetadata() { 423 Mutex::Autolock al(mWaitMutex); 424 425 // Destructive: Subsequent calls return empty metadatas 426 CameraMetadata tmp = mLatestMetadata; 427 mLatestMetadata.clear(); 428 429 return tmp; 430 } 431 432 ProCamera::StreamInfo& ProCamera::getStreamInfo(int streamId) { 433 return mStreams.editValueFor(streamId); 434 } 435 436 }; // namespace android 437