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<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