ProCamera.cpp revision fa4cf9d310685b4c25877cba772ff7da84caf517
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 37namespace android { 38 39sp<ProCamera> ProCamera::connect(int cameraId) 40{ 41 return CameraBaseT::connect(cameraId, String16(), 42 ICameraService::USE_CALLING_UID); 43} 44 45ProCamera::ProCamera(int cameraId) 46 : CameraBase(cameraId) 47{ 48} 49 50ProCamera::~ProCamera() 51{ 52 53} 54 55/* IProCameraUser's implementation */ 56 57// callback from camera service 58void ProCamera::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2) 59{ 60 return CameraBaseT::notifyCallback(msgType, ext1, ext2); 61} 62 63void 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 91void 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; 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 120status_t ProCamera::exclusiveTryLock() 121{ 122 sp <IProCameraUser> c = mCamera; 123 if (c == 0) return NO_INIT; 124 125 return c->exclusiveTryLock(); 126} 127status_t ProCamera::exclusiveLock() 128{ 129 sp <IProCameraUser> c = mCamera; 130 if (c == 0) return NO_INIT; 131 132 return c->exclusiveLock(); 133} 134status_t ProCamera::exclusiveUnlock() 135{ 136 sp <IProCameraUser> c = mCamera; 137 if (c == 0) return NO_INIT; 138 139 return c->exclusiveUnlock(); 140} 141bool 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. 150int 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 160status_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 168status_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 180status_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 199status_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 225status_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 235status_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 283camera_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 299status_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 309void ProCamera::onFrameAvailable(int streamId) { 310 ALOGV("%s: streamId = %d", __FUNCTION__, streamId); 311 312 sp<ProCameraListener> listener = mListener; 313 StreamInfo& stream = getStreamInfo(streamId); 314 315 CpuConsumer::LockedBuffer buf; 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 329int 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 361int 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 391status_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 419CameraMetadata ProCamera::consumeFrameMetadata() { 420 Mutex::Autolock al(mWaitMutex); 421 422 // Destructive: Subsequent calls return empty metadatas 423 CameraMetadata tmp = mLatestMetadata; 424 mLatestMetadata.release(); 425 426 return tmp; 427} 428 429ProCamera::StreamInfo& ProCamera::getStreamInfo(int streamId) { 430 return mStreams.editValueFor(streamId); 431} 432 433}; // namespace android 434