Home | History | Annotate | Download | only in src
      1 /*
      2 ** Copyright (c) 2011-2012 The Linux Foundation. All rights reserved.
      3 **
      4 ** Licensed under the Apache License, Version 2.0 (the "License");
      5 ** you may not use this file except in compliance with the License.
      6 ** You may obtain a copy of the License at
      7 **
      8 **     http://www.apache.org/licenses/LICENSE-2.0
      9 **
     10 ** Unless required by applicable law or agreed to in writing, software
     11 ** distributed under the License is distributed on an "AS IS" BASIS,
     12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 ** See the License for the specific language governing permissions and
     14 ** limitations under the License.
     15 */
     16 
     17 /*#error uncomment this for compiler test!*/
     18 
     19 #define ALOG_NDEBUG 0
     20 #define ALOG_NIDEBUG 0
     21 #define LOG_TAG __FILE__
     22 #include <utils/Log.h>
     23 #include <utils/threads.h>
     24 
     25 #include "QCameraHWI.h"
     26 #include "QCameraStream.h"
     27 
     28 /* QCameraStream class implementation goes here*/
     29 /* following code implement the control logic of this class*/
     30 
     31 namespace android {
     32 
     33 StreamQueue::StreamQueue(){
     34     mInitialized = false;
     35 }
     36 
     37 StreamQueue::~StreamQueue(){
     38     flush();
     39 }
     40 
     41 void StreamQueue::init(){
     42     Mutex::Autolock l(&mQueueLock);
     43     mInitialized = true;
     44     mQueueWait.signal();
     45 }
     46 
     47 void StreamQueue::deinit(){
     48     Mutex::Autolock l(&mQueueLock);
     49     mInitialized = false;
     50     mQueueWait.signal();
     51 }
     52 
     53 bool StreamQueue::isInitialized(){
     54    Mutex::Autolock l(&mQueueLock);
     55    return mInitialized;
     56 }
     57 
     58 bool StreamQueue::enqueue(
     59                  void * element){
     60     Mutex::Autolock l(&mQueueLock);
     61     if(mInitialized == false)
     62         return false;
     63 
     64     mContainer.add(element);
     65     mQueueWait.signal();
     66     return true;
     67 }
     68 
     69 bool StreamQueue::isEmpty(){
     70     return (mInitialized && mContainer.isEmpty());
     71 }
     72 void* StreamQueue::dequeue(){
     73 
     74     void *frame;
     75     mQueueLock.lock();
     76     while(mInitialized && mContainer.isEmpty()){
     77         mQueueWait.wait(mQueueLock);
     78     }
     79 
     80     if(!mInitialized){
     81         mQueueLock.unlock();
     82         return NULL;
     83     }
     84 
     85     frame = mContainer.itemAt(0);
     86     mContainer.removeAt(0);
     87     mQueueLock.unlock();
     88     return frame;
     89 }
     90 
     91 void StreamQueue::flush(){
     92     Mutex::Autolock l(&mQueueLock);
     93     mContainer.clear();
     94 }
     95 
     96 
     97 // ---------------------------------------------------------------------------
     98 // QCameraStream
     99 // ---------------------------------------------------------------------------
    100 
    101 void superbuf_cb_routine(mm_camera_super_buf_t *bufs,
    102                        void *userdata)
    103 {
    104     QCameraHardwareInterface *p_obj=(QCameraHardwareInterface*) userdata;
    105     ALOGE("%s: E",__func__);
    106 
    107     //Implement call to JPEG routine in Snapshot here
    108      if(bufs->bufs[0]->stream_id == p_obj->mStreamSnapMain->mMmStreamId){
    109          ALOGE("%s : jpeg callback for MM_CAMERA_SNAPSHOT_MAIN", __func__);
    110          p_obj->mStreamSnapMain->receiveRawPicture(bufs);
    111      }
    112 
    113 
    114     for(int i=0;i<bufs->num_bufs;i++) {
    115 
    116         p_obj->mCameraHandle->ops->qbuf(p_obj->mCameraHandle->camera_handle,
    117                                        p_obj->mChannelId,
    118                                        bufs->bufs[i]);
    119 
    120     }
    121 
    122 
    123 }
    124 
    125 void stream_cb_routine(mm_camera_super_buf_t *bufs,
    126                        void *userdata)
    127 {
    128     ALOGE("%s E ", __func__);
    129     QCameraStream *p_obj=(QCameraStream*) userdata;
    130     ALOGE("DEBUG4:ExtMode:%d,streamid:%d",p_obj->mExtImgMode,bufs->bufs[0]->stream_id);
    131     switch(p_obj->mExtImgMode) {
    132     case MM_CAMERA_PREVIEW:
    133         ALOGE("%s : callback for MM_CAMERA_PREVIEW", __func__);
    134         ((QCameraStream_preview *)p_obj)->dataCallback(bufs);
    135         break;
    136     case MM_CAMERA_VIDEO:
    137         ALOGE("%s : callback for MM_CAMERA_VIDEO", __func__);
    138         ((QCameraStream_preview *)p_obj)->dataCallback(bufs);
    139         break;
    140     case MM_CAMERA_SNAPSHOT_MAIN:
    141 #if 0
    142                 if(p_obj->mHalCamCtrl->getHDRMode()) {
    143                     ALOGE("%s: Skipping Q Buf for HDR mode",__func__);
    144                     break;
    145                 }
    146 #endif
    147 
    148                 ALOGE("%s : callback for MM_CAMERA_SNAPSHOT_MAIN", __func__);
    149                 p_obj->p_mm_ops->ops->qbuf(p_obj->mCameraHandle,
    150                                            p_obj->mChannelId,
    151                                            bufs->bufs[0]);
    152                 break;
    153          case MM_CAMERA_SNAPSHOT_THUMBNAIL:
    154                 break;
    155          default:
    156                 break;
    157 
    158     }
    159     ALOGE("%s X ", __func__);
    160 }
    161 
    162 QCameraStream *QCameraStream::mStreamTable[STREAM_TABLE_SIZE];
    163 
    164 void QCameraStream::dataCallback(mm_camera_super_buf_t *bufs)
    165 {
    166     if(mPendingCount!=0) {
    167         ALOGD("Got frame request");
    168         pthread_mutex_lock(&mFrameDeliveredMutex);
    169         mPendingCount--;
    170         ALOGD("Completed frame request");
    171         pthread_cond_signal(&mFrameDeliveredCond);
    172         pthread_mutex_unlock(&mFrameDeliveredMutex);
    173         processPreviewFrame(bufs);
    174     } else {
    175         p_mm_ops->ops->qbuf(mCameraHandle,
    176                 mChannelId, bufs->bufs[0]);
    177     }
    178 }
    179 
    180 void QCameraStream::onNewRequest()
    181 {
    182     ALOGI("%s:E",__func__);
    183     pthread_mutex_lock(&mFrameDeliveredMutex);
    184     ALOGI("Sending Frame request");
    185     mPendingCount++;
    186     pthread_cond_wait(&mFrameDeliveredCond,&mFrameDeliveredMutex);
    187     ALOGV("Got frame");
    188     pthread_mutex_unlock(&mFrameDeliveredMutex);
    189     ALOGV("%s:X",__func__);
    190 }
    191 
    192 int32_t QCameraStream::streamOn()
    193 {
    194    status_t rc=NO_ERROR;
    195    mm_camera_stream_config_t stream_config;
    196    ALOGE("%s:streamid:%d",__func__,mMmStreamId);
    197    Mutex::Autolock lock(mLock);
    198    if(mActive){
    199        ALOGE("%s: Stream:%d is already active",
    200             __func__,mMmStreamId);
    201        return rc;
    202    }
    203 
    204    if (mInit == true) {
    205        /* this is the restart case */
    206        memset(&stream_config, 0, sizeof(mm_camera_stream_config_t));
    207        stream_config.fmt.fmt=(cam_format_t)mFormat;
    208        stream_config.fmt.meta_header=MM_CAMEAR_META_DATA_TYPE_DEF;
    209        stream_config.fmt.width=mWidth;
    210        stream_config.fmt.height=mHeight;
    211        stream_config.fmt.rotation = 0;
    212        ALOGE("<DEBUG>::%s: Width :%d Height:%d Format:%d",__func__,mWidth,mHeight,mFormat);
    213        stream_config.num_of_bufs=mNumBuffers;
    214        stream_config.need_stream_on=true;
    215        rc=p_mm_ops->ops->config_stream(mCameraHandle,
    216                                  mChannelId,
    217                                  mMmStreamId,
    218                                  &stream_config);
    219        ALOGE("%s: config_stream, rc = %d", __func__, rc);
    220    }
    221 
    222    rc = p_mm_ops->ops->start_streams(mCameraHandle,
    223                               mChannelId,
    224                               1,
    225                               &mMmStreamId);
    226    if(rc==NO_ERROR)
    227        mActive = true;
    228    return rc;
    229 }
    230 
    231 int32_t QCameraStream::streamOff(bool isAsyncCmd)
    232 {
    233     status_t rc=NO_ERROR;
    234     Mutex::Autolock lock(mLock);
    235     if(!mActive) {
    236         ALOGE("%s: Stream:%d is not active",
    237               __func__,mMmStreamId);
    238         return rc;
    239     }
    240 
    241     rc = p_mm_ops->ops->stop_streams(mCameraHandle,
    242                               mChannelId,
    243                               1,
    244                               &mMmStreamId);
    245 
    246     mActive=false;
    247     return rc;
    248 
    249 }
    250 
    251 /* initialize a streaming channel*/
    252 status_t QCameraStream::initStream(mm_camera_img_mode imgmode,
    253     cam_format_t format)
    254 {
    255     int rc = MM_CAMERA_OK;
    256     status_t ret = NO_ERROR;
    257     mm_camera_op_mode_type_t op_mode=MM_CAMERA_OP_MODE_VIDEO;
    258     cam_ctrl_dimension_t dim;
    259     int i;
    260     mm_camera_stream_config_t stream_config;
    261 
    262     ALOGE("QCameraStream::initStream : E");
    263 
    264     mFormat = format;
    265     /*TODO: Convert between TEMPLATE to img_mode */
    266     mExtImgMode = imgmode;
    267     /***********Allocate Stream**************/
    268 
    269     rc=p_mm_ops->ops->add_stream(mCameraHandle,
    270                         mChannelId,
    271                         stream_cb_routine,
    272                         (void *)this,
    273                         mExtImgMode,
    274                         0/*sensor_idx*/);
    275 
    276     if (rc < 0)
    277        goto error1;
    278 
    279     mMmStreamId=rc;
    280     ALOGE("%s: mMmStreamId = %d\n", __func__, mMmStreamId);
    281 
    282     memset(&stream_config, 0, sizeof(mm_camera_stream_config_t));
    283     stream_config.fmt.fmt=format;
    284     stream_config.fmt.meta_header=MM_CAMEAR_META_DATA_TYPE_DEF;
    285     stream_config.fmt.width=mWidth;
    286     stream_config.fmt.height=mHeight;
    287     ALOGE("<DEBUG>::%s: Width :%d Height:%d Format:%d",__func__,mWidth,mHeight,format);
    288     stream_config.num_of_bufs=mNumBuffers;
    289     stream_config.need_stream_on=true;
    290     rc=p_mm_ops->ops->config_stream(mCameraHandle,
    291                               mChannelId,
    292                               mMmStreamId,
    293                               &stream_config);
    294     if(MM_CAMERA_OK != rc)
    295         goto error2;
    296 
    297     goto end;
    298 
    299 
    300 error2:
    301     ALOGE("%s: Error configuring stream",__func__);
    302     p_mm_ops->ops->del_stream(mCameraHandle,mChannelId,
    303                               mMmStreamId);
    304 
    305 error1:
    306     return BAD_VALUE;
    307 end:
    308     ALOGE("Setting mInit to true");
    309     mInit=true;
    310     return NO_ERROR;
    311 
    312 }
    313 
    314 status_t QCameraStream::deinitStream()
    315 {
    316 
    317     int rc = MM_CAMERA_OK;
    318 
    319     ALOGI("%s: E, Stream = %d\n", __func__, mMmStreamId);
    320 
    321     rc= p_mm_ops->ops->del_stream(mCameraHandle,mChannelId,
    322                               mMmStreamId);
    323 
    324     ALOGI("%s: X, Stream = %d\n", __func__, mMmStreamId);
    325     mInit=false;
    326     return NO_ERROR;
    327 }
    328 
    329 status_t QCameraStream::setMode(int enable) {
    330   ALOGE("%s :myMode %x ", __func__, myMode);
    331   if (enable) {
    332       myMode = (camera_mode_t)(myMode | CAMERA_ZSL_MODE);
    333   } else {
    334       myMode = (camera_mode_t)(myMode & ~CAMERA_ZSL_MODE);
    335   }
    336   return NO_ERROR;
    337 }
    338 
    339 status_t QCameraStream::setFormat()
    340 {
    341     ALOGE("%s: E",__func__);
    342 
    343     char mDeviceName[PROPERTY_VALUE_MAX];
    344     property_get("ro.product.device",mDeviceName," ");
    345 
    346     ALOGE("%s: X",__func__);
    347     return NO_ERROR;
    348 }
    349 
    350 QCameraStream::QCameraStream (){
    351     mInit = false;
    352     mActive = false;
    353     /* memset*/
    354     memset(&mCrop, 0, sizeof(mm_camera_rect_t));
    355 }
    356 
    357 QCameraStream::QCameraStream(uint32_t CameraHandle,
    358                        uint32_t ChannelId,
    359                         uint32_t Width,
    360                         uint32_t Height,
    361                         mm_camera_vtbl_t *mm_ops,
    362                         camera_mode_t mode)
    363               :myMode(mode)
    364 {
    365     mInit = false;
    366     mActive = false;
    367 
    368     mCameraHandle=CameraHandle;
    369     mChannelId=ChannelId;
    370     mWidth=Width;
    371     mHeight=Height;
    372     p_mm_ops=mm_ops;
    373 
    374     /* memset*/
    375     memset(&mCrop, 0, sizeof(mm_camera_rect_t));
    376 
    377     mPendingCount=0;
    378     pthread_mutex_init(&mFrameDeliveredMutex, NULL);
    379     pthread_cond_init(&mFrameDeliveredCond, NULL);
    380 }
    381 
    382 QCameraStream::~QCameraStream () {;}
    383 
    384 int QCameraStream::allocateStreamId() {
    385     int i = 0;
    386     for (i = 0; i < STREAM_TABLE_SIZE; i++)
    387         if (mStreamTable[i] == NULL) {
    388             mStreamTable[i] = this;
    389             break;
    390         }
    391     if (i == STREAM_TABLE_SIZE)
    392         return INVALID_OPERATION;
    393     ALOGE("%s: mStreamTable[%d] = %p\n", __func__, i, mStreamTable[i]);
    394     return i;
    395 }
    396 
    397 int QCameraStream::deallocateStreamId(int id) {
    398     if (id < 0 || id >= STREAM_TABLE_SIZE)
    399         return BAD_VALUE;
    400     mStreamTable[id] = NULL;
    401     return OK;
    402 }
    403 
    404 QCameraStream *QCameraStream::getStreamAtId(int id) {
    405     if (id < 0 || id >= STREAM_TABLE_SIZE)
    406         return NULL;
    407     else
    408         return mStreamTable[id];
    409 }
    410 
    411 QCameraStream *QCameraStream::getStreamAtMmId(uint32_t mm_id) {
    412     /*TODO: More efficient to do direct lookup. But it requires
    413      *mm-camera-interface to expose a macro for handle-index mapping*/
    414     for (int i = 0; i < STREAM_TABLE_SIZE; i++) {
    415         ALOGE("%s: %d: ", __func__, i);
    416         if (mStreamTable[i])
    417             ALOGE("%s: mMmStreamId = %d", __func__, mStreamTable[i]->mMmStreamId);
    418         if (mStreamTable[i] && (mStreamTable[i]->mMmStreamId == mm_id))
    419             return mStreamTable[i];
    420     }
    421     ALOGE("%s: Cannot find stream with interface id %d", __func__, mm_id);
    422     return NULL;
    423 }
    424 
    425 void QCameraStream::streamOffAll()
    426 {
    427     for (int i = 0; i < STREAM_TABLE_SIZE; i++) {
    428         if (mStreamTable[i]) {
    429             if (mStreamTable[i]->mActive) {
    430                 ALOGI("%s: stream off stream[%d]", __func__, i);
    431                 mStreamTable[i]->streamOff(0);
    432                 ALOGI("%s: stream off stream[%d] done", __func__, i);
    433             }
    434             if (mStreamTable[i]->mInit) {
    435                 ALOGI("%s: deinit stream[%d]", __func__, i);
    436                 mStreamTable[i]->deinitStream();
    437                 ALOGI("%s: deinit stream[%d] done", __func__, i);
    438             }
    439         }
    440     }
    441 }
    442 
    443 status_t QCameraStream::init() {
    444     return NO_ERROR;
    445 }
    446 
    447 status_t QCameraStream::start() {
    448     return NO_ERROR;
    449 }
    450 
    451 void QCameraStream::stop() {
    452     return;
    453 }
    454 
    455 void QCameraStream::release() {
    456     return;
    457 }
    458 
    459 void QCameraStream::setHALCameraControl(QCameraHardwareInterface* ctrl) {
    460 
    461     /* provide a frame data user,
    462     for the  queue monitor thread to call the busy queue is not empty*/
    463     mHalCamCtrl = ctrl;
    464 }
    465 
    466 }; // namespace android
    467