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_TAG "QCameraHWI_Preview"
     20 #include <utils/Log.h>
     21 #include <utils/threads.h>
     22 #include <fcntl.h>
     23 #include <sys/mman.h>
     24 #include "QCameraHAL.h"
     25 #include "QCameraHWI.h"
     26 #include <genlock.h>
     27 #include <gralloc_priv.h>
     28 
     29 #define UNLIKELY(exp) __builtin_expect(!!(exp), 0)
     30 
     31 /* QCameraHWI_Preview class implementation goes here*/
     32 /* following code implement the preview mode's image capture & display logic of this class*/
     33 
     34 namespace android {
     35 
     36 status_t QCameraStream_preview::setPreviewWindow(const camera2_stream_ops_t* window)
     37 {
     38     status_t retVal = NO_ERROR;
     39     ALOGE(" %s: E ", __FUNCTION__);
     40     if( window == NULL) {
     41         ALOGW(" Setting NULL preview window ");
     42         /* TODO: Current preview window will be invalidated.
     43          * Release all the buffers back */
     44        // relinquishBuffers();
     45     }
     46     Mutex::Autolock lock(mLock);
     47     mPreviewWindow = window;
     48     ALOGV(" %s : X ", __FUNCTION__ );
     49     return retVal;
     50 }
     51 
     52 int QCameraStream_preview::registerStreamBuffers(int num_buffers,
     53         buffer_handle_t *buffers)
     54 {
     55     int err;
     56 
     57     mNumBuffers = num_buffers;
     58     mPreviewMemory.buffer_count = num_buffers;
     59     for (int i = 0; i < num_buffers; i++) {
     60         mPreviewMemory.buffer_handle[i] = buffers[i];
     61         mPreviewMemory.private_buffer_handle[i] = (struct private_handle_t *)buffers[i];
     62         ALOGD("%s:Buffer Size:%d",__func__, mPreviewMemory.private_buffer_handle[i]->size);
     63     }
     64     mDisplayBuf = new mm_camera_buf_def_t[num_buffers];
     65     if (!mDisplayBuf) {
     66         ALOGE("Unable to allocate mDisplayBuf");
     67         return NO_MEMORY;
     68     }
     69 
     70    return OK;
     71 }
     72 
     73 status_t QCameraStream_preview::initBuffers()
     74 {
     75     status_t ret = NO_ERROR;
     76     int width = mWidth;  /* width of channel  */
     77     int height = mHeight; /* height of channel */
     78     uint32_t frame_len = mFrameOffsetInfo.frame_len; /* frame planner length */
     79     int buffer_num = mNumBuffers; /* number of buffers for display */
     80     const char *pmem_region;
     81     uint8_t num_planes = mFrameOffsetInfo.num_planes;
     82     uint32_t planes[VIDEO_MAX_PLANES];
     83     void *vaddr = NULL;
     84     buffer_handle_t *buffer_handle;
     85 
     86     ALOGE("%s:BEGIN",__func__);
     87     memset(mNotifyBuffer, 0, sizeof(mNotifyBuffer));
     88 
     89     this->myMode=myMode; /*Need to assign this in constructor after translating from mask*/
     90     num_planes = mFrameOffsetInfo.num_planes;
     91     for(int i=0; i < num_planes; i++)
     92         planes[i] = mFrameOffsetInfo.mp[i].len;
     93 
     94 
     95     mPreviewMemoryLock.lock();
     96     memset(mDisplayBuf, 0, sizeof(mm_camera_buf_def_t) * mNumBuffers);
     97 
     98     /*allocate memory for the buffers*/
     99     for(int i = 0; i < mNumBuffers; i++){
    100         mDisplayBuf[i].num_planes = num_planes;
    101         mDisplayBuf[i].buf_idx = i;
    102 
    103         /* Plane 0 needs to be set seperately. Set other planes
    104          * in a loop. */
    105         mDisplayBuf[i].planes[0].length = planes[0];
    106         mDisplayBuf[i].planes[0].m.userptr = mPreviewMemory.private_buffer_handle[i]->fd;
    107         mDisplayBuf[i].planes[0].data_offset = mFrameOffsetInfo.mp[0].offset;
    108         mDisplayBuf[i].planes[0].reserved[0] =0;
    109         for (int j = 1; j < num_planes; j++) {
    110             mDisplayBuf[i].planes[j].length = planes[j];
    111             mDisplayBuf[i].planes[j].m.userptr = mPreviewMemory.private_buffer_handle[i]->fd;
    112             mDisplayBuf[i].planes[j].data_offset = mFrameOffsetInfo.mp[j].offset;
    113             mDisplayBuf[i].planes[j].reserved[0] =
    114             mDisplayBuf[i].planes[j-1].reserved[0] +
    115             mDisplayBuf[i].planes[j-1].length;
    116         }
    117 
    118         for (int j = 0; j < num_planes; j++)
    119             ALOGE("Planes: %d length: %d userptr: %lu offset: %d\n", j,
    120                      mDisplayBuf[i].planes[j].length,
    121                      mDisplayBuf[i].planes[j].m.userptr,
    122                      mDisplayBuf[i].planes[j].reserved[0]);
    123 
    124         mDisplayBuf[i].stream_id = mMmStreamId;
    125         mDisplayBuf[i].fd = mPreviewMemory.private_buffer_handle[i]->fd;
    126         ALOGE("DEBUG2:Display buf[%d] fd:%d",i,mDisplayBuf[i].fd);
    127         mDisplayBuf[i].frame_len = mFrameOffsetInfo.frame_len;
    128     }/*end of for loop*/
    129 
    130     /* Dequeue N frames from native window and queue into interface. Only dequeue our requested buffers */
    131     for (int i = 0; i < mNumBuffers; i++)
    132         mPreviewMemory.local_flag[i] = BUFFER_NOT_REGGED;
    133     for (int i = 0; i < OPAQUE_BUFFER_COUNT; i++) {
    134         ALOGE("mPreview Window %p",mPreviewWindow);
    135         int err = mPreviewWindow->dequeue_buffer(mPreviewWindow, &buffer_handle);
    136         if (err == NO_ERROR && buffer_handle) {
    137             int j;
    138             for (j = 0; j < mPreviewMemory.buffer_count; j++) {
    139                 if (mPreviewMemory.buffer_handle[j] == *buffer_handle) {
    140                     mPreviewMemory.local_flag[j] = BUFFER_OWNED;
    141                     ALOGE("%s: [%d]: local_flag = 1", __func__, j);
    142                     break;
    143                 }
    144             }
    145             if (j == mPreviewMemory.buffer_count) {
    146                 ALOGE("Cannot find matching handle in the table.");
    147                 return INVALID_OPERATION;
    148             }
    149         } else {
    150             ALOGE("dequeue_buffer failed.");
    151             return INVALID_OPERATION;
    152         }
    153     }
    154 
    155     /* register the streaming buffers for the channel*/
    156     mPreviewMemoryLock.unlock();
    157     ALOGE("%s:END",__func__);
    158     return NO_ERROR;
    159 
    160 error:
    161     mPreviewMemoryLock.unlock();
    162 
    163     ALOGV("%s: X", __func__);
    164     return ret;
    165 }
    166 
    167 void QCameraStream_preview::deinitBuffers()
    168 {
    169     mPreviewMemoryLock.lock();
    170     for (int i = 0; i < mNumBuffers; i++) {
    171         if (mPreviewMemory.local_flag[i] == BUFFER_OWNED) {
    172             mPreviewWindow->cancel_buffer(mPreviewWindow,
    173                 &mPreviewMemory.buffer_handle[i]);
    174             mPreviewMemory.local_flag[i] = BUFFER_NOT_OWNED;
    175         }
    176     }
    177     mPreviewMemoryLock.unlock();
    178 }
    179 
    180 void QCameraStream_preview::dumpFrameToFile(mm_camera_buf_def_t *newFrame)
    181 {
    182   int32_t enabled = 0;
    183   int frm_num;
    184   uint32_t  skip_mode;
    185   char value[PROPERTY_VALUE_MAX];
    186   char buf[32];
    187   int w, h;
    188   static int count = 0;
    189   int file_fd;
    190   int rc = 0;
    191   int len;
    192   unsigned long addr;
    193   unsigned long * tmp = (unsigned long *)newFrame->buffer;
    194   addr = *tmp;
    195 
    196   len = newFrame->frame_len;
    197   count++;
    198   if(count < 100) {
    199     snprintf(buf, sizeof(buf), "/data/mzhu%d.yuv", count);
    200     file_fd = open(buf, O_RDWR | O_CREAT, 0777);
    201 
    202     rc = write(file_fd, (const void *)addr, len);
    203     ALOGE("%s: file='%s', vaddr_old=0x%x, addr_map = 0x%p, len = %d, rc = %d",
    204           __func__, buf, (uint32_t)newFrame->buffer, (void *)addr, len, rc);
    205     close(file_fd);
    206     ALOGE("%s: dump %s, rc = %d, len = %d", __func__, buf, rc, len);
    207   }
    208 }
    209 
    210 int QCameraStream_preview::prepareStream()
    211 {
    212     mm_camera_img_mode img_mode;
    213     cam_format_t format;
    214     struct private_handle_t *private_handle = mPreviewMemory.private_buffer_handle[0];
    215 
    216     ALOGE("%s: private_handle->format = %d, flags = %d", __func__,
    217         private_handle->format, private_handle->flags);
    218     if (private_handle->flags & private_handle_t::PRIV_FLAGS_VIDEO_ENCODER)
    219         img_mode = MM_CAMERA_VIDEO;
    220     else if (private_handle->flags & private_handle_t::PRIV_FLAGS_CAMERA_WRITE)
    221         img_mode = MM_CAMERA_PREVIEW;
    222     else {
    223         ALOGE("%s: Invalid flags %d\n", __func__, private_handle->flags);
    224         return BAD_VALUE;
    225     }
    226 
    227     switch (private_handle->format) {
    228     case HAL_PIXEL_FORMAT_YCbCr_420_SP:
    229         format = CAMERA_YUV_420_NV12;
    230         break;
    231     case HAL_PIXEL_FORMAT_YCrCb_420_SP:
    232         format = CAMERA_YUV_420_NV21;
    233         break;
    234     default:
    235         ALOGE("%s: Invalid format!!!", __func__);
    236         return BAD_VALUE;
    237     }
    238     if(NO_ERROR!=initStream(img_mode, format)) {
    239         ALOGE("Init stream failed");
    240         return BAD_VALUE;
    241     }
    242     return OK;
    243 }
    244 
    245 status_t QCameraStream_preview::processPreviewFrame (
    246   mm_camera_super_buf_t *frame)
    247 {
    248     ALOGV("%s",__func__);
    249     int err = 0;
    250     int msgType = 0;
    251     int i;
    252     camera_frame_metadata_t *metadata = NULL;
    253 
    254     Mutex::Autolock lock(mLock);
    255     if(!mActive) {
    256         ALOGE("Preview Stopped. Returning callback");
    257         return NO_ERROR;
    258     }
    259 
    260     if(mHalCamCtrl==NULL) {
    261         ALOGE("%s: X: HAL control object not set",__func__);
    262        /*Call buf done*/
    263        return BAD_VALUE;
    264     }
    265     nsecs_t timeStamp = seconds_to_nanoseconds(frame->bufs[0]->ts.tv_sec) ;
    266     timeStamp += frame->bufs[0]->ts.tv_nsec;
    267 
    268     if(mFirstFrameRcvd == false) {
    269         //mm_camera_util_profile("HAL: First preview frame received");
    270         mFirstFrameRcvd = true;
    271     }
    272 
    273     //  dumpFrameToFile(frame->bufs[0]);
    274 
    275     mPreviewMemoryLock.lock();
    276     mNotifyBuffer[frame->bufs[0]->buf_idx] = *frame;
    277     ALOGE("processPreviewFrame: timeStamp = %lld", (int64_t)timeStamp);
    278     err = mPreviewWindow->enqueue_buffer(mPreviewWindow, (int64_t)timeStamp,
    279                   &mPreviewMemory.buffer_handle[frame->bufs[0]->buf_idx]);
    280     if(err != 0) {
    281         ALOGE("%s: enqueue_buffer failed, err = %d", __func__, err);
    282     }
    283     mPreviewMemory.local_flag[frame->bufs[0]->buf_idx] = BUFFER_NOT_OWNED;
    284 
    285     buffer_handle_t *buffer_handle = NULL;
    286     err = mPreviewWindow->dequeue_buffer(mPreviewWindow, &buffer_handle);
    287     if (err == NO_ERROR && buffer_handle != NULL) {
    288         int rc = MM_CAMERA_OK;
    289         ALOGD("%s: dequed buf hdl =%p", __func__, *buffer_handle);
    290         for(i = 0; i < mPreviewMemory.buffer_count; i++) {
    291             if(mPreviewMemory.buffer_handle[i] == *buffer_handle) {
    292                 ALOGE("<DEBUG2>:Found buffer in idx:%d",i);
    293                 break;
    294             }
    295         }
    296         if (mPreviewMemory.local_flag[i] == BUFFER_NOT_REGGED) {
    297             mm_camera_buf_def_t buf = mDisplayBuf[i];
    298             mPreviewMemory.local_flag[i] = BUFFER_OWNED;
    299             rc = p_mm_ops->ops->qbuf(mCameraHandle, mChannelId, &buf);
    300         } else {
    301             mPreviewMemory.local_flag[i] = BUFFER_OWNED;
    302             rc = p_mm_ops->ops->qbuf(mCameraHandle, mChannelId, mNotifyBuffer[i].bufs[0]);
    303         }
    304 
    305         if(rc != MM_CAMERA_OK) {
    306             /* how to handle the error of qbuf? */
    307             ALOGE("BUF DONE FAILED");
    308         }
    309     }
    310     /* Save the last displayed frame. We'll be using it to fill the gap between
    311        when preview stops and postview start during snapshot.*/
    312     mLastQueuedFrame = &(mDisplayBuf[frame->bufs[0]->buf_idx]);
    313     mPreviewMemoryLock.unlock();
    314 
    315     return NO_ERROR;
    316 }
    317 
    318 // ---------------------------------------------------------------------------
    319 // QCameraStream_preview
    320 // ---------------------------------------------------------------------------
    321 
    322 QCameraStream_preview::QCameraStream_preview(uint32_t CameraHandle,
    323                         uint32_t ChannelId,
    324                         uint32_t Width,
    325                         uint32_t Height,
    326                         int requestedFormat,
    327                         mm_camera_vtbl_t *mm_ops,
    328                         camera_mode_t mode) :
    329                  QCameraStream(CameraHandle,
    330                         ChannelId,
    331                         Width,
    332                         Height,
    333                         mm_ops,
    334                         mode),
    335                  mLastQueuedFrame(NULL),
    336                  mDisplayBuf(NULL),
    337                  mNumFDRcvd(0)
    338 {
    339     mHalCamCtrl = NULL;
    340     ALOGE("%s: E", __func__);
    341 
    342     mStreamId = allocateStreamId();
    343 
    344     switch (requestedFormat) {
    345     case CAMERA2_HAL_PIXEL_FORMAT_OPAQUE:
    346         mMaxBuffers = 5;
    347         break;
    348     case HAL_PIXEL_FORMAT_BLOB:
    349         mMaxBuffers = 1;
    350         break;
    351     default:
    352         ALOGE("Unsupported requested format %d", requestedFormat);
    353         mMaxBuffers = 1;
    354         break;
    355     }
    356     /*TODO: There has to be a better way to do this*/
    357     ALOGE("%s: X", __func__);
    358 }
    359 // ---------------------------------------------------------------------------
    360 // QCameraStream_preview
    361 // ---------------------------------------------------------------------------
    362 
    363 QCameraStream_preview::~QCameraStream_preview() {
    364     ALOGV("%s: E", __func__);
    365 	if(mActive) {
    366 		streamOff(0);
    367 	}
    368 	if(mInit) {
    369 		deinitStream();
    370 	}
    371 	mInit = false;
    372 	mActive = false;
    373     if (mDisplayBuf) {
    374         delete[] mDisplayBuf;
    375         mDisplayBuf = NULL;
    376     }
    377     deallocateStreamId(mStreamId);
    378     ALOGV("%s: X", __func__);
    379 
    380 }
    381 // ---------------------------------------------------------------------------
    382 // QCameraStream_preview
    383 // ---------------------------------------------------------------------------
    384 
    385 status_t QCameraStream_preview::init()
    386 {
    387     status_t ret = NO_ERROR;
    388     ALOGV("%s: E", __func__);
    389 
    390 #if 0
    391     if (!(myMode & CAMERA_ZSL_MODE)) {
    392         ALOGE("Setting OP MODE to MM_CAMERA_OP_MODE_VIDEO");
    393         mm_camera_op_mode_type_t op_mode=MM_CAMERA_OP_MODE_VIDEO;
    394         ret = p_mm_ops->ops->set_parm (mCameraHandle, MM_CAMERA_PARM_OP_MODE,
    395                                         &op_mode);
    396         ALOGE("OP Mode Set");
    397 
    398         if(MM_CAMERA_OK != ret) {
    399           ALOGE("%s: X :set mode MM_CAMERA_OP_MODE_VIDEO err=%d\n", __func__, ret);
    400           return BAD_VALUE;
    401         }
    402     }else {
    403         ALOGE("Setting OP MODE to MM_CAMERA_OP_MODE_ZSL");
    404         mm_camera_op_mode_type_t op_mode=MM_CAMERA_OP_MODE_ZSL;
    405         ret =p_mm_ops->ops->set_parm (mCameraHandle, MM_CAMERA_PARM_OP_MODE,
    406                                         &op_mode);
    407         if(MM_CAMERA_OK != ret) {
    408           ALOGE("%s: X :set mode MM_CAMERA_OP_MODE_ZSL err=%d\n", __func__, ret);
    409           return BAD_VALUE;
    410         }
    411      }
    412 
    413     setFormat();
    414     ret = QCameraStream::initStream();
    415     if (NO_ERROR!=ret) {
    416         ALOGE("%s E: can't init native cammera preview ch\n",__func__);
    417         return ret;
    418     }
    419 
    420   mInit = true;
    421 #endif
    422   return ret;
    423 }
    424 // ---------------------------------------------------------------------------
    425 // QCameraStream_preview
    426 // ---------------------------------------------------------------------------
    427 
    428 status_t QCameraStream_preview::start()
    429 {
    430     ALOGV("%s: E", __func__);
    431     status_t ret = NO_ERROR;
    432 
    433     Mutex::Autolock lock(mLock);
    434 
    435     /* call start() in parent class to start the monitor thread*/
    436     //QCameraStream::start ();
    437 
    438 #if 0
    439     ret = cam_config_prepare_buf(mCameraId, &mDisplayBuf);
    440     ALOGE("Debug : %s : cam_config_prepare_buf",__func__);
    441     if(ret != MM_CAMERA_OK) {
    442         ALOGV("%s:reg preview buf err=%d\n", __func__, ret);
    443         ret = BAD_VALUE;
    444         goto error;
    445     }else {
    446         ret = NO_ERROR;
    447     }
    448 #endif
    449     /* For preview, the OP_MODE we set is dependent upon whether we are
    450        starting camera or camcorder. For snapshot, anyway we disable preview.
    451        However, for ZSL we need to set OP_MODE to OP_MODE_ZSL and not
    452        OP_MODE_VIDEO. We'll set that for now in CamCtrl. So in case of
    453        ZSL we skip setting Mode here */
    454 
    455 
    456     /* call mm_camera action start(...)  */
    457     ALOGE("Starting Preview/Video Stream. ");
    458     mFirstFrameRcvd = false;
    459 
    460     ALOGE("Starting Preview/Video Stream. ");
    461     ret = streamOn();
    462     if (MM_CAMERA_OK != ret) {
    463       ALOGE ("%s: preview streaming start err=%d\n", __func__, ret);
    464       ret = BAD_VALUE;
    465       goto end;
    466     }
    467 
    468     ALOGE("Debug : %s : Preview streaming Started",__func__);
    469     ret = NO_ERROR;
    470 
    471     mActive =  true;
    472     goto end;
    473 
    474 end:
    475     ALOGE("%s: X", __func__);
    476     return ret;
    477   }
    478 
    479 
    480 // ---------------------------------------------------------------------------
    481 // QCameraStream_preview
    482 // ---------------------------------------------------------------------------
    483   void QCameraStream_preview::stop() {
    484     ALOGE("%s: E", __func__);
    485     int ret=MM_CAMERA_OK;
    486 
    487     if(!mActive) {
    488       return;
    489     }
    490     Mutex::Autolock lock(mLock);
    491     mActive =  false;
    492     /* unregister the notify fn from the mmmm_camera_t object*/
    493 
    494     ALOGI("%s: Stop the thread \n", __func__);
    495     /* call stop() in parent class to stop the monitor thread*/
    496     //stream_info = mHalCamCtrl->getChannelInterface();
    497 
    498     ret = streamOff(0);
    499     if(MM_CAMERA_OK != ret) {
    500       ALOGE ("%s: camera preview stop err=%d\n", __func__, ret);
    501     }
    502 #if 0
    503     ret = cam_config_unprepare_buf(mCameraId, MM_CAMERA_CH_PREVIEW);
    504     if(ret != MM_CAMERA_OK) {
    505       ALOGE("%s:Unreg preview buf err=%d\n", __func__, ret);
    506       //ret = BAD_VALUE;
    507     }
    508 #endif
    509     /* In case of a clean stop, we need to clean all buffers*/
    510     ALOGE("Debug : %s : Buffer Unprepared",__func__);
    511     /*free camera_memory handles and return buffer back to surface*/
    512     ret= QCameraStream::deinitStream();
    513     ALOGE(": %s : De init Channel",__func__);
    514     if(ret != MM_CAMERA_OK) {
    515       ALOGE("%s:Deinit preview channel failed=%d\n", __func__, ret);
    516       //ret = BAD_VALUE;
    517     }
    518     ALOGE("%s: X", __func__);
    519 
    520   }
    521 // ---------------------------------------------------------------------------
    522 // QCameraStream_preview
    523 // ---------------------------------------------------------------------------
    524   void QCameraStream_preview::release() {
    525 
    526     ALOGE("%s : BEGIN",__func__);
    527     int ret=MM_CAMERA_OK,i;
    528 
    529     if(!mInit)
    530     {
    531       ALOGE("%s : Stream not Initalized",__func__);
    532       return;
    533     }
    534 
    535     if(mActive) {
    536       this->streamOff(0);
    537     }
    538 
    539 
    540     if(mInit) {
    541         deinitStream();
    542     }
    543     mInit = false;
    544     ALOGE("%s: END", __func__);
    545 
    546   }
    547 
    548 QCameraStream*
    549 QCameraStream_preview::createInstance(uint32_t CameraHandle,
    550                         uint32_t ChannelId,
    551                         uint32_t Width,
    552                         uint32_t Height,
    553                         int requestedFormat,
    554                         mm_camera_vtbl_t *mm_ops,
    555                         camera_mode_t mode)
    556 {
    557   QCameraStream* pme = new QCameraStream_preview(CameraHandle,
    558                         ChannelId,
    559                         Width,
    560                         Height,
    561                         requestedFormat,
    562                         mm_ops,
    563                         mode);
    564   return pme;
    565 }
    566 // ---------------------------------------------------------------------------
    567 // QCameraStream_preview
    568 // ---------------------------------------------------------------------------
    569 
    570 void QCameraStream_preview::deleteInstance(QCameraStream *p)
    571 {
    572   if (p){
    573     ALOGV("%s: BEGIN", __func__);
    574     p->release();
    575     delete p;
    576     p = NULL;
    577     ALOGV("%s: END", __func__);
    578   }
    579 }
    580 
    581 
    582 /* Temp helper function */
    583 void *QCameraStream_preview::getLastQueuedFrame(void)
    584 {
    585     return mLastQueuedFrame;
    586 }
    587 
    588 // ---------------------------------------------------------------------------
    589 // No code beyone this line
    590 // ---------------------------------------------------------------------------
    591 }; // namespace android
    592