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 LOG_NIDEBUG 0
     20 //#define LOG_NDEBUG 0
     21 
     22 #define LOG_TAG "QCameraHWI"
     23 #include <utils/Log.h>
     24 #include <utils/threads.h>
     25 #include <cutils/properties.h>
     26 #include <fcntl.h>
     27 #include <sys/mman.h>
     28 
     29 #include "QCameraHAL.h"
     30 #include "QCameraHWI.h"
     31 
     32 /* QCameraHardwareInterface class implementation goes here*/
     33 /* following code implement the contol logic of this class*/
     34 
     35 namespace android {
     36 
     37 extern void stream_cb_routine(mm_camera_super_buf_t *bufs,
     38                        void *userdata);
     39 extern void superbuf_cb_routine(mm_camera_super_buf_t *bufs,
     40                        void *userdata);
     41 
     42 
     43 /*Command Thread startup function*/
     44 
     45 void *command_thread(void *obj)
     46 {
     47     QCameraHardwareInterface *pme = (QCameraHardwareInterface *)obj;
     48     ALOGD("%s: E", __func__);
     49     if (pme != NULL) {
     50         pme->runCommandThread(obj);
     51     }
     52     else ALOGW("not starting command thread: the object went away!");
     53     ALOGD("%s: X", __func__);
     54     return NULL;
     55 }
     56 
     57 int QCameraHardwareInterface::tryRestartStreams(
     58     camera_metadata_entry_t& streams)
     59 {
     60     int rc = 0;
     61     bool needRestart = false;
     62     bool needRecordingHint = false;
     63 
     64     for (uint32_t i = 0; i < streams.count; i++) {
     65         int streamId = streams.data.u8[i];
     66         QCameraStream *stream = QCameraStream::getStreamAtId(streamId);
     67         if (!stream->mInit) {
     68             needRestart = true;
     69             if (stream->mFormat == CAMERA_YUV_420_NV12)
     70                 needRecordingHint = true;
     71         }
     72     }
     73 
     74     if (!needRestart)
     75         goto end;
     76 
     77     QCameraStream::streamOffAll();
     78 
     79     if (needRecordingHint) {
     80         uint32_t recordingHint = 1;
     81         rc = mCameraHandle->ops->set_parm(mCameraHandle->camera_handle,
     82             MM_CAMERA_PARM_RECORDING_HINT, &recordingHint);
     83         if (rc < 0) {
     84             ALOGE("set_parm MM_CAMERA_PARM_RECORDING_HINT returns %d", rc);
     85             return rc;
     86         }
     87     }
     88 
     89 end:
     90     for (uint32_t i = 0; i < streams.count; i++) {
     91         int streamId = streams.data.u8[i];
     92         QCameraStream *stream = QCameraStream::getStreamAtId(streamId);
     93         if (!stream->mInit) {
     94             rc = stream->prepareStream();
     95             if (rc < 0) {
     96                 ALOGE("prepareStream for stream %d failed %d", streamId, rc);
     97                 return rc;
     98             }
     99         }
    100     }
    101     for (uint32_t i = 0; i < streams.count; i++) {
    102         int streamId = streams.data.u8[i];
    103         QCameraStream *stream = QCameraStream::getStreamAtId(streamId);
    104 
    105         if (!stream->mActive) {
    106             rc = stream->streamOn();
    107             if (rc < 0) {
    108                 ALOGE("streamOn for stream %d failed %d", streamId, rc);
    109                 return rc;
    110             }
    111         }
    112     }
    113     return rc;
    114 }
    115 
    116 void QCameraHardwareInterface::runCommandThread(void *data)
    117 {
    118 
    119     /**
    120      * This function implements the main service routine for the incoming
    121      * frame requests, this thread routine is started everytime we get a
    122      * notify_request_queue_not_empty trigger, this thread makes the
    123      * assumption that once it receives a NULL on a dequest_request call
    124      * there will be a fresh notify_request_queue_not_empty call that is
    125      * invoked thereby launching a new instance of this thread. Therefore,
    126      * once we get a NULL on a dequeue request we simply let this thread die
    127      */
    128     int res;
    129     camera_metadata_t *request=NULL;
    130     mPendingRequests=0;
    131 
    132     while(mRequestQueueSrc) {
    133         ALOGV("%s:Dequeue request using mRequestQueueSrc:%p",__func__,mRequestQueueSrc);
    134         mRequestQueueSrc->dequeue_request(mRequestQueueSrc,&request);
    135         if(request==NULL) {
    136             ALOGE("%s:No more requests available from src command \
    137                     thread dying",__func__);
    138             return;
    139         }
    140         mPendingRequests++;
    141 
    142         /* Set the metadata values */
    143 
    144         /* Wait for the SOF for the new metadata values to be applied */
    145 
    146         /* Check the streams that need to be active in the stream request */
    147         sort_camera_metadata(request);
    148 
    149         camera_metadata_entry_t streams;
    150         res = find_camera_metadata_entry(request,
    151                 ANDROID_REQUEST_OUTPUT_STREAMS,
    152                 &streams);
    153         if (res != NO_ERROR) {
    154             ALOGE("%s: error reading output stream tag", __FUNCTION__);
    155             return;
    156         }
    157 
    158         res = tryRestartStreams(streams);
    159         if (res != NO_ERROR) {
    160             ALOGE("error tryRestartStreams %d", res);
    161             return;
    162         }
    163 
    164         /* 3rd pass: Turn on all streams requested */
    165         for (uint32_t i = 0; i < streams.count; i++) {
    166             int streamId = streams.data.u8[i];
    167             QCameraStream *stream = QCameraStream::getStreamAtId(streamId);
    168 
    169             /* Increment the frame pending count in each stream class */
    170 
    171             /* Assuming we will have the stream obj in had at this point may be
    172              * may be multiple objs in which case we loop through array of streams */
    173             stream->onNewRequest();
    174         }
    175         ALOGV("%s:Freeing request using mRequestQueueSrc:%p",__func__,mRequestQueueSrc);
    176         /* Free the request buffer */
    177         mRequestQueueSrc->free_request(mRequestQueueSrc,request);
    178         mPendingRequests--;
    179         ALOGV("%s:Completed request",__func__);
    180     }
    181 
    182     QCameraStream::streamOffAll();
    183 }
    184 
    185 /*Mem Hooks*/
    186 int32_t get_buffer_hook(uint32_t camera_handle,
    187                         uint32_t ch_id, uint32_t stream_id,
    188                         void *user_data,
    189                         mm_camera_frame_len_offset *frame_offset_info,
    190                         uint8_t num_bufs,
    191                         uint8_t *initial_reg_flag,
    192                         mm_camera_buf_def_t  *bufs)
    193 {
    194     QCameraHardwareInterface *pme=(QCameraHardwareInterface *)user_data;
    195     return pme->getBuf(camera_handle, ch_id, stream_id,
    196                 user_data, frame_offset_info,
    197                 num_bufs,initial_reg_flag,
    198                 bufs);
    199 
    200 }
    201 
    202 int32_t put_buffer_hook(uint32_t camera_handle,
    203                         uint32_t ch_id, uint32_t stream_id,
    204                         void *user_data, uint8_t num_bufs,
    205                         mm_camera_buf_def_t *bufs)
    206 {
    207     QCameraHardwareInterface *pme=(QCameraHardwareInterface *)user_data;
    208     return pme->putBuf(camera_handle, ch_id, stream_id,
    209                 user_data, num_bufs, bufs);
    210 
    211 }
    212 
    213 int QCameraHardwareInterface::getBuf(uint32_t camera_handle,
    214                         uint32_t ch_id, uint32_t mm_stream_id,
    215                         void *user_data,
    216                         mm_camera_frame_len_offset *frame_offset_info,
    217                         uint8_t num_bufs,
    218                         uint8_t *initial_reg_flag,
    219                         mm_camera_buf_def_t  *bufs)
    220 {
    221     status_t ret=NO_ERROR;
    222     ALOGE("%s: E, stream_id = %d\n", __func__, mm_stream_id);
    223     QCameraStream_preview *stream = (QCameraStream_preview *)
    224                         QCameraStream::getStreamAtMmId(mm_stream_id);
    225 
    226     ALOGE("%s: len:%d, y_off:%d, cbcr:%d num buffers: %d planes:%d streamid:%d",
    227         __func__,
    228         frame_offset_info->frame_len,
    229 	frame_offset_info->mp[0].len,
    230 	frame_offset_info->mp[1].len,
    231         num_bufs,frame_offset_info->num_planes,
    232         mm_stream_id);
    233     /*************Preiew Stream*****************/
    234     ALOGE("Interface requesting Preview Buffers");
    235     stream->mFrameOffsetInfo=*frame_offset_info;
    236     if(NO_ERROR!=stream->initBuffers()){
    237         return BAD_VALUE;
    238     }
    239     ALOGE("Debug : %s : initDisplayBuffers",__func__);
    240     for(int i=0;i<num_bufs;i++) {
    241         bufs[i] = stream->mDisplayBuf[i];
    242         initial_reg_flag[i] =
    243             (stream->mPreviewMemory.local_flag[i] == BUFFER_OWNED);
    244         ALOGE("initial_reg_flag[%d]:%d",i,initial_reg_flag[i]);
    245     }
    246     return 0;
    247 }
    248 
    249 int QCameraHardwareInterface::putBuf(uint32_t camera_handle,
    250                         uint32_t ch_id, uint32_t mm_stream_id,
    251                         void *user_data, uint8_t num_bufs,
    252                         mm_camera_buf_def_t *bufs)
    253 {
    254     ALOGE("%s:E, stream_id = %d",__func__, mm_stream_id);
    255     QCameraStream_preview *stream = (QCameraStream_preview *)
    256                         QCameraStream::getStreamAtMmId(mm_stream_id);
    257     stream->deinitBuffers();
    258     return 0;
    259 }
    260 
    261 
    262 QCameraHardwareInterface::
    263 QCameraHardwareInterface(int cameraId, int mode)
    264                   : mCameraId(cameraId)
    265 {
    266 
    267     cam_ctrl_dimension_t mDimension;
    268 
    269     /* Open camera stack! */
    270     memset(&mMemHooks, 0, sizeof(mm_camear_mem_vtbl_t));
    271     mMemHooks.user_data=this;
    272     mMemHooks.get_buf=get_buffer_hook;
    273     mMemHooks.put_buf=put_buffer_hook;
    274 
    275     mCameraHandle=camera_open(mCameraId, &mMemHooks);
    276     ALOGV("Cam open returned %p",mCameraHandle);
    277     if(mCameraHandle == NULL) {
    278         ALOGE("startCamera: cam_ops_open failed: id = %d", mCameraId);
    279         return;
    280     }
    281     mCameraHandle->ops->sync(mCameraHandle->camera_handle);
    282 
    283     mChannelId=mCameraHandle->ops->ch_acquire(mCameraHandle->camera_handle);
    284     if(mChannelId<=0)
    285     {
    286         ALOGE("%s:Channel aquire failed",__func__);
    287         mCameraHandle->ops->camera_close(mCameraHandle->camera_handle);
    288         return;
    289     }
    290 
    291     /* Initialize # of frame requests the HAL is handling to zero*/
    292     mPendingRequests=0;
    293 }
    294 
    295 QCameraHardwareInterface::~QCameraHardwareInterface()
    296 {
    297     mCameraHandle->ops->camera_close(mCameraHandle->camera_handle);
    298 }
    299 
    300 void QCameraHardwareInterface::release()
    301 {
    302 }
    303 
    304 bool QCameraHardwareInterface::isCameraReady()
    305 {
    306     return true;
    307 }
    308 
    309 int QCameraHardwareInterface::set_request_queue_src_ops(
    310     const camera2_request_queue_src_ops_t *request_src_ops)
    311 {
    312     ALOGE("%s:E mRequestQueueSrc:%p",__func__,request_src_ops);
    313     mRequestQueueSrc = request_src_ops;
    314     ALOGE("%s:X",__func__);
    315     return 0;
    316 }
    317 
    318 int QCameraHardwareInterface::notify_request_queue_not_empty()
    319 {
    320 
    321     pthread_attr_t attr;
    322     if(pthread_attr_init(&attr)!=0) {
    323         ALOGE("%s:pthread_attr_init failed",__func__);
    324         return BAD_VALUE;
    325     }
    326     if(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED)!=0){
    327         ALOGE("%s:pthread_attr_setdetachstate failed",__func__);
    328         return BAD_VALUE;
    329     }
    330     if(pthread_create(&mCommandThread,&attr,
    331                    command_thread, (void *)this)!=0) {
    332         ALOGE("%s:pthread_create failed to launch command_thread",__func__);
    333         return BAD_VALUE;
    334     }
    335 
    336     return NO_ERROR;
    337 }
    338 
    339 int QCameraHardwareInterface::set_frame_queue_dst_ops(
    340     const camera2_frame_queue_dst_ops_t *frame_dst_ops)
    341 {
    342     mFrameQueueDst = frame_dst_ops;
    343     return OK;
    344 }
    345 
    346 int QCameraHardwareInterface::get_in_progress_count()
    347 {
    348     return mPendingRequests;
    349 }
    350 
    351 int QCameraHardwareInterface::construct_default_request(
    352     int request_template, camera_metadata_t **request)
    353 {
    354     status_t ret;
    355     ALOGD("%s:E:request_template:%d ",__func__,request_template);
    356 
    357     if (request == NULL)
    358         return BAD_VALUE;
    359     if (request_template < 0 || request_template >= CAMERA2_TEMPLATE_COUNT)
    360         return BAD_VALUE;
    361 
    362     ret = constructDefaultRequest(request_template, request, true);
    363     if (ret != OK) {
    364         ALOGE("%s: Unable to allocate default request: %s (%d)",
    365             __FUNCTION__, strerror(-ret), ret);
    366         return ret;
    367     }
    368     ret = constructDefaultRequest(request_template, request, false);
    369     if (ret != OK) {
    370         ALOGE("%s: Unable to fill in default request: %s (%d)",
    371             __FUNCTION__, strerror(-ret), ret);
    372         return ret;
    373     }
    374 
    375     ALOGE("Setting OP MODE to MM_CAMERA_OP_MODE_VIDEO");
    376     mm_camera_op_mode_type_t op_mode=MM_CAMERA_OP_MODE_VIDEO;
    377     ret = mCameraHandle->ops->set_parm(
    378                          mCameraHandle->camera_handle,
    379                          MM_CAMERA_PARM_OP_MODE,
    380                          &op_mode);
    381     ALOGE("OP Mode Set");
    382 
    383     return ret;
    384 }
    385 
    386 int QCameraHardwareInterface::allocate_stream(
    387     uint32_t width,
    388     uint32_t height, int format,
    389     const camera2_stream_ops_t *stream_ops,
    390     uint32_t *stream_id,
    391     uint32_t *format_actual,
    392     uint32_t *usage,
    393     uint32_t *max_buffers)
    394 {
    395     int ret = OK;
    396     QCameraStream *stream = NULL;
    397     camera_mode_t myMode = (camera_mode_t)(CAMERA_MODE_2D|CAMERA_NONZSL_MODE);
    398     ALOGE("%s : BEGIN",__func__);
    399 
    400     ALOGE("Mymode Preview = %d",myMode);
    401     stream = QCameraStream_preview::createInstance(
    402                         mCameraHandle->camera_handle,
    403                         mChannelId,
    404                         width,
    405                         height,
    406                         format,
    407                         mCameraHandle,
    408                         myMode);
    409     ALOGE("%s: createInstance done", __func__);
    410     if (!stream) {
    411         ALOGE("%s: error - can't creat preview stream!", __func__);
    412         return BAD_VALUE;
    413     }
    414 
    415     stream->setPreviewWindow(stream_ops);
    416     *stream_id = stream->getStreamId();
    417     *max_buffers= stream->getMaxBuffers();
    418     ALOGE("%s: stream_id = %d\n", __func__, *stream_id);
    419     *usage = GRALLOC_USAGE_HW_CAMERA_WRITE | CAMERA_GRALLOC_HEAP_ID
    420         | CAMERA_GRALLOC_FALLBACK_HEAP_ID;
    421     /* Set to an arbitrary format SUPPORTED by gralloc */
    422     //*format_actual = HAL_PIXEL_FORMAT_YCbCr_422_SP;
    423     *format_actual = HAL_PIXEL_FORMAT_YCrCb_420_SP;
    424     /*TODO: For hardware encoder, add CAMERA_GRALLOC_CACHING_ID */
    425     stream->setHALCameraControl(this);
    426 
    427     ALOGV("%s : END",__func__);
    428     return ret;
    429 }
    430 
    431 int QCameraHardwareInterface::register_stream_buffers(
    432     uint32_t stream_id, int num_buffers,
    433     buffer_handle_t *buffers)
    434 {
    435     struct private_handle_t *private_handle =
    436                         (struct private_handle_t *)buffers[0];
    437     QCameraStream_preview *stream = (QCameraStream_preview *)
    438                         QCameraStream::getStreamAtId(stream_id);
    439 
    440     if(!stream) {
    441         ALOGE("%s: Request for unknown stream",__func__);
    442         return BAD_VALUE;
    443     }
    444 
    445     if(NO_ERROR!=stream->registerStreamBuffers(num_buffers, buffers)) {
    446         ALOGE("%s:registerStreamBuffers failed",__func__);
    447         return BAD_VALUE;
    448     }
    449 
    450     return NO_ERROR;
    451 }
    452 
    453 int QCameraHardwareInterface::release_stream(uint32_t stream_id)
    454 {
    455     QCameraStream *stream = QCameraStream::getStreamAtId(stream_id);
    456 
    457     QCameraStream_preview::deleteInstance(stream);
    458 
    459     return OK;
    460 }
    461 
    462 int QCameraHardwareInterface::allocate_reprocess_stream(
    463     uint32_t width,
    464     uint32_t height,
    465     uint32_t format,
    466     const camera2_stream_in_ops_t *reprocess_stream_ops,
    467     uint32_t *stream_id,
    468     uint32_t *consumer_usage,
    469     uint32_t *max_buffers)
    470 {
    471     return INVALID_OPERATION;
    472 }
    473 
    474 int QCameraHardwareInterface::release_reprocess_stream(uint32_t stream_id)
    475 {
    476     return INVALID_OPERATION;
    477 }
    478 
    479 int QCameraHardwareInterface::get_metadata_vendor_tag_ops(vendor_tag_query_ops_t **ops)
    480 {
    481     *ops = NULL;
    482     return OK;
    483 }
    484 
    485 int QCameraHardwareInterface::set_notify_callback(camera2_notify_callback notify_cb,
    486             void *user)
    487 {
    488     mNotifyCb = notify_cb;
    489     mNotifyUserPtr = user;
    490     return OK;
    491 }
    492 }; // namespace android
    493