ProCamera.cpp revision 8aa0f0619ea867e8fb240cf27913d4f8ae767385
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 36namespace android { 37 38sp<ProCamera> ProCamera::connect(int cameraId) 39{ 40 return CameraBaseT::connect(cameraId, String16(), 41 ICameraService::USE_CALLING_UID); 42} 43 44ProCamera::ProCamera(int cameraId) 45 : CameraBase(cameraId) 46{ 47} 48 49CameraTraits<ProCamera>::TCamConnectService CameraTraits<ProCamera>::fnConnectService = 50 &ICameraService::connectPro; 51 52ProCamera::~ProCamera() 53{ 54 55} 56 57/* IProCameraUser's implementation */ 58 59// callback from camera service 60void ProCamera::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2) 61{ 62 return CameraBaseT::notifyCallback(msgType, ext1, ext2); 63} 64 65void 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 93void 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 122status_t ProCamera::exclusiveTryLock() 123{ 124 sp <IProCameraUser> c = mCamera; 125 if (c == 0) return NO_INIT; 126 127 return c->exclusiveTryLock(); 128} 129status_t ProCamera::exclusiveLock() 130{ 131 sp <IProCameraUser> c = mCamera; 132 if (c == 0) return NO_INIT; 133 134 return c->exclusiveLock(); 135} 136status_t ProCamera::exclusiveUnlock() 137{ 138 sp <IProCameraUser> c = mCamera; 139 if (c == 0) return NO_INIT; 140 141 return c->exclusiveUnlock(); 142} 143bool 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. 152int 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 162status_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 170status_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 182status_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 201status_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 227status_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 237status_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 288camera_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 304status_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 314void 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 332int 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 364int 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 394status_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 422CameraMetadata 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 432ProCamera::StreamInfo& ProCamera::getStreamInfo(int streamId) { 433 return mStreams.editValueFor(streamId); 434} 435 436}; // namespace android 437