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/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 
     37 namespace android {
     38 
     39 sp<ProCamera> ProCamera::connect(int cameraId)
     40 {
     41     return CameraBaseT::connect(cameraId, String16(),
     42                                  ICameraService::USE_CALLING_UID);
     43 }
     44 
     45 ProCamera::ProCamera(int cameraId)
     46     : CameraBase(cameraId)
     47 {
     48 }
     49 
     50 ProCamera::~ProCamera()
     51 {
     52 
     53 }
     54 
     55 /* IProCameraUser's implementation */
     56 
     57 // callback from camera service
     58 void ProCamera::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2)
     59 {
     60     return CameraBaseT::notifyCallback(msgType, ext1, ext2);
     61 }
     62 
     63 void 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 
     91 void 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; // make copy
    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 
    120 status_t ProCamera::exclusiveTryLock()
    121 {
    122     sp <IProCameraUser> c = mCamera;
    123     if (c == 0) return NO_INIT;
    124 
    125     return c->exclusiveTryLock();
    126 }
    127 status_t ProCamera::exclusiveLock()
    128 {
    129     sp <IProCameraUser> c = mCamera;
    130     if (c == 0) return NO_INIT;
    131 
    132     return c->exclusiveLock();
    133 }
    134 status_t ProCamera::exclusiveUnlock()
    135 {
    136     sp <IProCameraUser> c = mCamera;
    137     if (c == 0) return NO_INIT;
    138 
    139     return c->exclusiveUnlock();
    140 }
    141 bool 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.
    150 int 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 
    160 status_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 
    168 status_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 
    180 status_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 
    199 status_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 
    225 status_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 
    235 status_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 
    283 camera_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 
    299 status_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 
    309 void ProCamera::onFrameAvailable(int streamId) {
    310     ALOGV("%s: streamId = %d", __FUNCTION__, streamId);
    311 
    312     sp<ProCameraListener> listener = mListener;
    313     StreamInfo& stream = getStreamInfo(streamId);
    314 
    315     if (listener.get() != NULL) {
    316         listener->onFrameAvailable(streamId, stream.cpuConsumer);
    317     }
    318 
    319     // Unblock waitForFrame(id) callers
    320     {
    321         Mutex::Autolock al(mWaitMutex);
    322         getStreamInfo(streamId).frameReady++;
    323         mWaitCondition.broadcast();
    324     }
    325 }
    326 
    327 int ProCamera::waitForFrameBuffer(int streamId) {
    328     status_t stat = BAD_VALUE;
    329     Mutex::Autolock al(mWaitMutex);
    330 
    331     StreamInfo& si = getStreamInfo(streamId);
    332 
    333     if (si.frameReady > 0) {
    334         int numFrames = si.frameReady;
    335         si.frameReady = 0;
    336         return numFrames;
    337     } else {
    338         while (true) {
    339             stat = mWaitCondition.waitRelative(mWaitMutex,
    340                                                 mWaitTimeout);
    341             if (stat != OK) {
    342                 ALOGE("%s: Error while waiting for frame buffer: %d",
    343                     __FUNCTION__, stat);
    344                 return stat;
    345             }
    346 
    347             if (si.frameReady > 0) {
    348                 int numFrames = si.frameReady;
    349                 si.frameReady = 0;
    350                 return numFrames;
    351             }
    352             // else it was some other stream that got unblocked
    353         }
    354     }
    355 
    356     return stat;
    357 }
    358 
    359 int ProCamera::dropFrameBuffer(int streamId, int count) {
    360     StreamInfo& si = getStreamInfo(streamId);
    361 
    362     if (!si.cpuStream) {
    363         return BAD_VALUE;
    364     } else if (count < 0) {
    365         return BAD_VALUE;
    366     }
    367 
    368     if (!si.synchronousMode) {
    369         ALOGW("%s: No need to drop frames on asynchronous streams,"
    370               " as asynchronous mode only keeps 1 latest frame around.",
    371               __FUNCTION__);
    372         return BAD_VALUE;
    373     }
    374 
    375     int numDropped = 0;
    376     for (int i = 0; i < count; ++i) {
    377         CpuConsumer::LockedBuffer buffer;
    378         if (si.cpuConsumer->lockNextBuffer(&buffer) != OK) {
    379             break;
    380         }
    381 
    382         si.cpuConsumer->unlockBuffer(buffer);
    383         numDropped++;
    384     }
    385 
    386     return numDropped;
    387 }
    388 
    389 status_t ProCamera::waitForFrameMetadata() {
    390     status_t stat = BAD_VALUE;
    391     Mutex::Autolock al(mWaitMutex);
    392 
    393     if (mMetadataReady) {
    394         return OK;
    395     } else {
    396         while (true) {
    397             stat = mWaitCondition.waitRelative(mWaitMutex,
    398                                                mWaitTimeout);
    399 
    400             if (stat != OK) {
    401                 ALOGE("%s: Error while waiting for metadata: %d",
    402                         __FUNCTION__, stat);
    403                 return stat;
    404             }
    405 
    406             if (mMetadataReady) {
    407                 mMetadataReady = false;
    408                 return OK;
    409             }
    410             // else it was some other stream or metadata
    411         }
    412     }
    413 
    414     return stat;
    415 }
    416 
    417 CameraMetadata ProCamera::consumeFrameMetadata() {
    418     Mutex::Autolock al(mWaitMutex);
    419 
    420     // Destructive: Subsequent calls return empty metadatas
    421     CameraMetadata tmp = mLatestMetadata;
    422     mLatestMetadata.clear();
    423 
    424     return tmp;
    425 }
    426 
    427 ProCamera::StreamInfo& ProCamera::getStreamInfo(int streamId) {
    428     return mStreams.editValueFor(streamId);
    429 }
    430 
    431 }; // namespace android
    432