Home | History | Annotate | Download | only in camera
      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