Home | History | Annotate | Download | only in mm-camera-interface
      1 /*
      2 Copyright (c) 2011-2012,2015, The Linux Foundation. All rights reserved.
      3 
      4 Redistribution and use in source and binary forms, with or without
      5 modification, are permitted provided that the following conditions are
      6 met:
      7     * Redistributions of source code must retain the above copyright
      8       notice, this list of conditions and the following disclaimer.
      9     * Redistributions in binary form must reproduce the above
     10       copyright notice, this list of conditions and the following
     11       disclaimer in the documentation and/or other materials provided
     12       with the distribution.
     13     * Neither the name of The Linux Foundation nor the names of its
     14       contributors may be used to endorse or promote products derived
     15       from this software without specific prior written permission.
     16 
     17 THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
     18 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
     20 ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
     21 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
     24 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     25 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     26 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
     27 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28 */
     29 
     30 #include <pthread.h>
     31 #include "mm_camera_dbg.h"
     32 #include <errno.h>
     33 #include <linux/msm_ion.h>
     34 #include <sys/ioctl.h>
     35 #include <sys/types.h>
     36 #include <sys/stat.h>
     37 #include <fcntl.h>
     38 #include <poll.h>
     39 #include "mm_camera_interface2.h"
     40 #include "mm_camera.h"
     41 
     42 #if 0
     43 #undef CDBG
     44 #define CDBG ALOGV
     45 #endif
     46 /* static functions prototype declarations */
     47 static int mm_camera_channel_skip_frames(mm_camera_obj_t *my_obj,
     48                                           mm_camera_frame_queue_t *mq,
     49                                           mm_camera_frame_queue_t *sq,
     50                                           mm_camera_stream_t *mstream,
     51                                           mm_camera_stream_t *sstream,
     52                                           mm_camera_channel_attr_buffering_frame_t *frame_attr);
     53 static int mm_camera_channel_get_starting_frame(mm_camera_obj_t *my_obj,
     54                                                 mm_camera_ch_t *ch,
     55                                                 mm_camera_stream_t *mstream,
     56                                                 mm_camera_stream_t *sstream,
     57                                                 mm_camera_frame_queue_t *mq,
     58                                                 mm_camera_frame_queue_t *sq,
     59                                                 mm_camera_frame_t **mframe,
     60                                                 mm_camera_frame_t **sframe);
     61 static int mm_camera_ch_search_frame_based_on_time(mm_camera_obj_t *my_obj,
     62                                                    mm_camera_ch_t *ch,
     63                                                    mm_camera_stream_t *mstream,
     64                                                    mm_camera_stream_t *sstream,
     65                                                    mm_camera_frame_queue_t *mq,
     66                                                    mm_camera_frame_queue_t *sq,
     67                                                    mm_camera_frame_t **mframe,
     68                                                    mm_camera_frame_t **sframe);
     69 
     70 
     71 
     72 int mm_camera_ch_util_get_num_stream(mm_camera_obj_t * my_obj,mm_camera_channel_type_t ch_type)
     73 {
     74     int num = 0;
     75     switch(ch_type) {
     76     case MM_CAMERA_CH_RAW:
     77         num =  1;
     78         break;
     79     case MM_CAMERA_CH_PREVIEW:
     80         num =  1;
     81         break;
     82     case MM_CAMERA_CH_VIDEO:
     83         num =  1;
     84         if(my_obj->ch[ch_type].video.has_main) {
     85             num +=  1;
     86         }
     87         break;
     88     case MM_CAMERA_CH_SNAPSHOT:
     89         num =  2;
     90         break;
     91     default:
     92         break;
     93     }
     94     return num;
     95 }
     96 
     97 void mm_camera_ch_util_get_stream_objs(mm_camera_obj_t * my_obj,
     98                                        mm_camera_channel_type_t ch_type,
     99                                        mm_camera_stream_t **stream1,
    100                                        mm_camera_stream_t **stream2)
    101 {
    102     *stream1 = NULL;
    103     *stream2 = NULL;
    104 
    105     switch(ch_type) {
    106     case MM_CAMERA_CH_RAW:
    107         *stream1 = &my_obj->ch[ch_type].raw.stream;
    108         break;
    109     case MM_CAMERA_CH_PREVIEW:
    110         *stream1 = &my_obj->ch[ch_type].preview.stream;
    111         break;
    112     case MM_CAMERA_CH_VIDEO:
    113         *stream1 = &my_obj->ch[ch_type].video.video;
    114         if(my_obj->ch[ch_type].video.has_main) {
    115             *stream2 = &my_obj->ch[ch_type].video.main;
    116         }
    117         break;
    118     case MM_CAMERA_CH_SNAPSHOT:
    119         *stream1 = &my_obj->ch[ch_type].snapshot.main;
    120         if (!my_obj->full_liveshot)
    121             *stream2 = &my_obj->ch[ch_type].snapshot.thumbnail;
    122         break;
    123     default:
    124         break;
    125     }
    126 }
    127 
    128 static int32_t mm_camera_ch_util_set_fmt(mm_camera_obj_t * my_obj,
    129                                          mm_camera_channel_type_t ch_type,
    130                                          mm_camera_ch_image_fmt_parm_t *fmt)
    131 {
    132     int32_t rc = MM_CAMERA_OK;
    133     mm_camera_stream_t *stream1 = NULL;
    134     mm_camera_stream_t *stream2 = NULL;
    135     mm_camera_image_fmt_t *fmt1 = NULL;
    136     mm_camera_image_fmt_t *fmt2 = NULL;
    137 
    138     switch(ch_type) {
    139     case MM_CAMERA_CH_RAW:
    140         stream1 = &my_obj->ch[ch_type].raw.stream;
    141         fmt1 = &fmt->def;
    142         break;
    143     case MM_CAMERA_CH_PREVIEW:
    144         stream1 = &my_obj->ch[ch_type].preview.stream;
    145         fmt1 = &fmt->def;
    146         break;
    147     case MM_CAMERA_CH_VIDEO:
    148         stream1 = &my_obj->ch[ch_type].video.video;
    149         fmt1 = &fmt->video.video;
    150         if(my_obj->ch[ch_type].video.has_main) {
    151             CDBG("%s:video channel has main image stream\n", __func__);
    152             stream2 = &my_obj->ch[ch_type].video.main;
    153             fmt2 = &fmt->video.main;
    154         }
    155         break;
    156     case MM_CAMERA_CH_SNAPSHOT:
    157         stream1 = &my_obj->ch[ch_type].snapshot.main;
    158         fmt1 = &fmt->snapshot.main;
    159         if (!my_obj->full_liveshot) {
    160             stream2 = &my_obj->ch[ch_type].snapshot.thumbnail;
    161             fmt2 = &fmt->snapshot.thumbnail;
    162         }
    163         break;
    164     default:
    165         rc = -1;
    166         break;
    167     }
    168     CDBG("%s:ch=%d, streams[0x%x,0x%x]\n", __func__, ch_type,
    169              (uint32_t)stream1, (uint32_t)stream2);
    170     if(stream1)
    171         rc = mm_camera_stream_fsm_fn_vtbl(my_obj, stream1,
    172                          MM_CAMERA_STATE_EVT_SET_FMT, fmt1);
    173     if(stream2 && !rc)
    174         rc = mm_camera_stream_fsm_fn_vtbl(my_obj, stream2,
    175                          MM_CAMERA_STATE_EVT_SET_FMT, fmt2);
    176     return rc;
    177 }
    178 
    179 static int32_t mm_camera_ch_util_acquire(mm_camera_obj_t * my_obj,
    180                                          mm_camera_channel_type_t ch_type)
    181 {
    182     int32_t rc = MM_CAMERA_OK;
    183     mm_camera_stream_t *stream1 = NULL;
    184     mm_camera_stream_t *stream2 = NULL;
    185     mm_camera_stream_type_t type1;
    186     mm_camera_stream_type_t type2;
    187 
    188     if(my_obj->ch[ch_type].acquired) {
    189         rc = MM_CAMERA_OK;
    190         goto end;
    191     }
    192     pthread_mutex_init(&my_obj->ch[ch_type].mutex, NULL);
    193     switch(ch_type) {
    194     case MM_CAMERA_CH_RAW:
    195         stream1 = &my_obj->ch[ch_type].raw.stream;
    196         type1 = MM_CAMERA_STREAM_RAW;
    197         break;
    198     case MM_CAMERA_CH_PREVIEW:
    199         stream1 = &my_obj->ch[ch_type].preview.stream;
    200         type1 = MM_CAMERA_STREAM_PREVIEW;
    201         break;
    202     case MM_CAMERA_CH_VIDEO:
    203         stream1 = &my_obj->ch[ch_type].video.video;
    204         type1 = MM_CAMERA_STREAM_VIDEO;
    205         /* no full image live shot by default */
    206         my_obj->ch[ch_type].video.has_main = FALSE;
    207         break;
    208     case MM_CAMERA_CH_SNAPSHOT:
    209         stream1 = &my_obj->ch[ch_type].snapshot.main;
    210         type1 = MM_CAMERA_STREAM_SNAPSHOT;
    211         if (!my_obj->full_liveshot) {
    212             stream2 = &my_obj->ch[ch_type].snapshot.thumbnail;
    213             type2 = MM_CAMERA_STREAM_THUMBNAIL;
    214         }
    215         break;
    216     default:
    217         return -1;
    218         break;
    219     }
    220     if(stream1) rc = mm_camera_stream_fsm_fn_vtbl(my_obj, stream1,
    221                                             MM_CAMERA_STATE_EVT_ACQUIRE, &type1);
    222     if(stream2 && !rc) rc = mm_camera_stream_fsm_fn_vtbl(my_obj, stream2,
    223                                             MM_CAMERA_STATE_EVT_ACQUIRE, &type2);
    224     if(rc == MM_CAMERA_OK) {
    225         if(!my_obj->ch[ch_type].acquired)    my_obj->ch[ch_type].acquired = TRUE;
    226     }
    227 
    228 end:
    229     return rc;
    230 }
    231 
    232 static int32_t mm_camera_ch_util_release(mm_camera_obj_t * my_obj,
    233                                          mm_camera_channel_type_t ch_type,
    234                                          mm_camera_state_evt_type_t evt)
    235 {
    236     mm_camera_stream_t *stream1, *stream2;
    237 
    238     if(!my_obj->ch[ch_type].acquired) return MM_CAMERA_OK;
    239 
    240     mm_camera_ch_util_get_stream_objs(my_obj,ch_type, &stream1, &stream2);
    241     if(stream1)
    242         mm_camera_stream_fsm_fn_vtbl(my_obj, stream1, evt, NULL);
    243     if(stream2)
    244         mm_camera_stream_fsm_fn_vtbl(my_obj, stream2, evt, NULL);
    245     pthread_mutex_destroy(&my_obj->ch[ch_type].mutex);
    246     memset(&my_obj->ch[ch_type],0,sizeof(my_obj->ch[ch_type]));
    247     return 0;
    248 }
    249 
    250 static int32_t mm_camera_ch_util_stream_null_val(mm_camera_obj_t * my_obj,
    251                                                  mm_camera_channel_type_t ch_type,
    252                                                             mm_camera_state_evt_type_t evt, void *val)
    253 {
    254         int32_t rc = 0;
    255         switch(ch_type) {
    256         case MM_CAMERA_CH_RAW:
    257             rc = mm_camera_stream_fsm_fn_vtbl(my_obj, &my_obj->ch[ch_type].raw.stream,
    258                                               evt, NULL);
    259             break;
    260         case MM_CAMERA_CH_PREVIEW:
    261             rc = mm_camera_stream_fsm_fn_vtbl(my_obj, &my_obj->ch[ch_type].preview.stream,
    262                                               evt, NULL);
    263             break;
    264         case MM_CAMERA_CH_VIDEO:
    265             rc = mm_camera_stream_fsm_fn_vtbl(my_obj,
    266                             &my_obj->ch[ch_type].video.video, evt,
    267                             NULL);
    268             if(!rc && my_obj->ch[ch_type].video.main.fd)
    269                 rc = mm_camera_stream_fsm_fn_vtbl(my_obj,
    270                                 &my_obj->ch[ch_type].video.main, evt,
    271                                 NULL);
    272             break;
    273         case MM_CAMERA_CH_SNAPSHOT:
    274             my_obj->ch[ch_type].snapshot.expected_matching_id = 0;
    275             rc = mm_camera_stream_fsm_fn_vtbl(my_obj,
    276                             &my_obj->ch[ch_type].snapshot.main, evt,
    277                             NULL);
    278             if(!rc && !my_obj->full_liveshot)
    279                 rc = mm_camera_stream_fsm_fn_vtbl(my_obj,
    280                                 &my_obj->ch[ch_type].snapshot.thumbnail, evt,
    281                                 NULL);
    282             break;
    283         default:
    284             CDBG_ERROR("%s: Invalid ch_type=%d", __func__, ch_type);
    285             rc = -1;
    286             break;
    287         }
    288         return rc;
    289 }
    290 
    291 static int32_t mm_camera_ch_util_reg_buf(mm_camera_obj_t * my_obj,
    292                                          mm_camera_channel_type_t ch_type,
    293                                          mm_camera_state_evt_type_t evt, void *val)
    294 {
    295         int32_t rc = 0;
    296         switch(ch_type) {
    297         case MM_CAMERA_CH_RAW:
    298             rc = mm_camera_stream_fsm_fn_vtbl(my_obj,
    299                                              &my_obj->ch[ch_type].raw.stream, evt,
    300                                              (mm_camera_buf_def_t *)val);
    301             break;
    302         case MM_CAMERA_CH_PREVIEW:
    303             rc = mm_camera_stream_fsm_fn_vtbl(my_obj,
    304                                              &my_obj->ch[ch_type].preview.stream, evt,
    305                                              (mm_camera_buf_def_t *)val);
    306             break;
    307         case MM_CAMERA_CH_VIDEO:
    308             {
    309                 mm_camera_buf_video_t * buf = (mm_camera_buf_video_t *)val;
    310                 rc = mm_camera_stream_fsm_fn_vtbl(my_obj,
    311                                 &my_obj->ch[ch_type].video.video, evt,
    312                                 &buf->video);
    313                 if(!rc && my_obj->ch[ch_type].video.has_main) {
    314                     rc = mm_camera_stream_fsm_fn_vtbl(my_obj,
    315                                     &my_obj->ch[ch_type].video.main, evt,
    316                                     &buf->main);
    317                 }
    318             }
    319             break;
    320         case MM_CAMERA_CH_SNAPSHOT:
    321             {
    322                 mm_camera_buf_snapshot_t * buf = (mm_camera_buf_snapshot_t *)val;
    323                 rc = mm_camera_stream_fsm_fn_vtbl(my_obj,
    324                                 &my_obj->ch[ch_type].snapshot.main, evt,
    325                                 &buf->main);
    326                 if(!rc && !my_obj->full_liveshot) {
    327                     rc = mm_camera_stream_fsm_fn_vtbl(my_obj,
    328                                     &my_obj->ch[ch_type].snapshot.thumbnail, evt,
    329                                     & buf->thumbnail);
    330                 }
    331             }
    332             break;
    333         default:
    334             return -1;
    335             break;
    336         }
    337         return rc;
    338 }
    339 
    340 static int32_t mm_camera_ch_util_attr(mm_camera_obj_t *my_obj,
    341                                       mm_camera_channel_type_t ch_type,
    342                                       mm_camera_channel_attr_t *val)
    343 {
    344     int rc = -MM_CAMERA_E_NOT_SUPPORTED;
    345     /*if(ch_type != MM_CAMERA_CH_RAW) {
    346         CDBG("%s: attr type %d not support for ch %d\n", __func__, val->type, ch_type);
    347         return rc;
    348     }*/
    349     if(my_obj->ch[ch_type].acquired== 0) {
    350       CDBG_ERROR("%s Channel %d not yet acquired ", __func__, ch_type);
    351       return -MM_CAMERA_E_INVALID_OPERATION;
    352     }
    353     switch(val->type) {
    354     case MM_CAMERA_CH_ATTR_RAW_STREAMING_TYPE:
    355         if(val->raw_streaming_mode == MM_CAMERA_RAW_STREAMING_CAPTURE_SINGLE) {
    356             my_obj->ch[ch_type].raw.mode = val->raw_streaming_mode;
    357             rc = MM_CAMERA_OK;
    358         }
    359         break;
    360     case MM_CAMERA_CH_ATTR_BUFFERING_FRAME:
    361       /* it's good to check the stream state. TBD later  */
    362       memcpy(&my_obj->ch[ch_type].buffering_frame, &val->buffering_frame, sizeof(val->buffering_frame));
    363       break;
    364     default:
    365         break;
    366     }
    367     return MM_CAMERA_OK;
    368 }
    369 
    370 static int32_t mm_camera_ch_util_reg_buf_cb(mm_camera_obj_t *my_obj,
    371                                             mm_camera_channel_type_t ch_type,
    372                                             mm_camera_buf_cb_t *val)
    373 {
    374     /* TODOhere: Need to return failure in case of MAX Cb registered
    375      * but in order to return fail case need to set up rc.
    376      * but the rc value needs to be thread safe
    377      */
    378     int i;
    379     ALOGV("%s: Trying to register",__func__);
    380 //    pthread_mutex_lock(&my_obj->ch[ch_type].mutex);
    381     for( i=0 ;i < MM_CAMERA_BUF_CB_MAX; i++ ) {
    382         if(my_obj->ch[ch_type].buf_cb[i].cb==NULL) {
    383             memcpy(&my_obj->ch[ch_type].buf_cb[i],val,sizeof(mm_camera_buf_cb_t));
    384             break;
    385         }
    386     }
    387 //    pthread_mutex_unlock(&my_obj->ch[ch_type].mutex);
    388     ALOGV("%s: Done register",__func__);
    389     return MM_CAMERA_OK;
    390 }
    391 
    392 static int32_t mm_camera_ch_util_qbuf(mm_camera_obj_t *my_obj,
    393                                     mm_camera_channel_type_t ch_type,
    394                                     mm_camera_state_evt_type_t evt,
    395                                     mm_camera_ch_data_buf_t *val)
    396 {
    397     int32_t rc = -1;
    398     mm_camera_stream_t *stream;
    399     struct ion_flush_data cache_inv_data;
    400     struct ion_custom_data custom_data;
    401     int ion_fd;
    402     struct msm_frame *cache_frame;
    403     struct msm_frame *cache_frame1 = NULL;
    404 
    405     CDBG("<DEBUG>: %s:ch_type:%d",__func__,ch_type);
    406     switch(ch_type) {
    407     case MM_CAMERA_CH_RAW:
    408         rc = mm_camera_stream_fsm_fn_vtbl(my_obj,
    409                                           &my_obj->ch[ch_type].raw.stream, evt,
    410                                                                      &val->def);
    411         cache_frame = val->def.frame;
    412         break;
    413     case MM_CAMERA_CH_PREVIEW:
    414         rc = mm_camera_stream_fsm_fn_vtbl(my_obj,
    415                                          &my_obj->ch[ch_type].preview.stream, evt,
    416                                          &val->def);
    417         cache_frame = val->def.frame;
    418         CDBG("buffer fd = %d, length = %d, vaddr = %p\n",
    419          val->def.frame->fd, val->def.frame->ion_alloc.len, val->def.frame->buffer);
    420         break;
    421     case MM_CAMERA_CH_VIDEO:
    422         {
    423             rc = mm_camera_stream_fsm_fn_vtbl(my_obj,
    424                             &my_obj->ch[ch_type].video.video, evt,
    425                             &val->video.video);
    426             cache_frame = val->video.video.frame;
    427             CDBG("buffer fd = %d, length = %d, vaddr = %p\n",
    428                  val->video.video.frame->fd, val->video.video.frame->ion_alloc.len, val->video.video.frame->buffer);
    429 
    430             if(!rc && val->video.main.frame) {
    431                 rc = mm_camera_stream_fsm_fn_vtbl(my_obj,
    432                                 &my_obj->ch[ch_type].video.main, evt,
    433                                 &val->video.main);
    434                 cache_frame1 = val->video.main.frame;
    435             }
    436         }
    437         break;
    438     case MM_CAMERA_CH_SNAPSHOT:
    439         {
    440             rc = mm_camera_stream_fsm_fn_vtbl(my_obj,
    441                             &my_obj->ch[ch_type].snapshot.main, evt,
    442                             &val->snapshot.main);
    443             cache_frame = val->snapshot.main.frame;
    444             CDBG("buffer fd = %d, length = %d, vaddr = %p\n",
    445                  val->snapshot.main.frame->fd, val->snapshot.main.frame->ion_alloc.len, val->snapshot.main.frame->buffer);
    446             if(!rc && (!my_obj->full_liveshot)) {
    447                 if (my_obj->op_mode == MM_CAMERA_OP_MODE_ZSL)
    448                   stream = &my_obj->ch[MM_CAMERA_CH_PREVIEW].preview.stream;
    449                 else
    450                   stream = &my_obj->ch[ch_type].snapshot.thumbnail;
    451                 rc = mm_camera_stream_fsm_fn_vtbl(my_obj,
    452                                 stream, evt,
    453                                 &val->snapshot.thumbnail);
    454                 cache_frame1 = val->snapshot.thumbnail.frame;
    455                 CDBG("buffer fd = %d, length = %d, vaddr = %p\n",
    456                  val->snapshot.thumbnail.frame->fd, val->snapshot.thumbnail.frame->ion_alloc.len, val->snapshot.thumbnail.frame->buffer);
    457             }
    458         }
    459         break;
    460     default:
    461         return -1;
    462         break;
    463     }
    464 #ifdef USE_ION
    465     cache_inv_data.vaddr = cache_frame->buffer;
    466     cache_inv_data.fd = cache_frame->fd;
    467     cache_inv_data.handle = cache_frame->fd_data.handle;
    468     cache_inv_data.length = cache_frame->ion_alloc.len;
    469     custom_data.cmd = ION_IOC_INV_CACHES;
    470     custom_data.arg = &cache_inv_data;
    471     ion_fd = cache_frame->ion_dev_fd;
    472     if(ion_fd > 0) {
    473         if(ioctl(ion_fd, ION_IOC_CUSTOM, &custom_data) < 0)
    474             CDBG_ERROR("%s: Cache Invalidate failed\n", __func__);
    475         else {
    476             CDBG("%s: Successful cache invalidate\n", __func__);
    477             if(cache_frame1) {
    478               ion_fd = cache_frame1->ion_dev_fd;
    479               cache_inv_data.vaddr = cache_frame1->buffer;
    480               cache_inv_data.fd = cache_frame1->fd;
    481               cache_inv_data.handle = cache_frame1->fd_data.handle;
    482               cache_inv_data.length = cache_frame1->ion_alloc.len;
    483               custom_data.cmd = ION_IOC_INV_CACHES;
    484               custom_data.arg = &cache_inv_data;
    485               if(ioctl(ion_fd, ION_IOC_CUSTOM, &custom_data) < 0)
    486                 CDBG_ERROR("%s: Cache Invalidate failed\n", __func__);
    487               else
    488                 CDBG("%s: Successful cache invalidate\n", __func__);
    489             }
    490         }
    491     }
    492 #endif
    493 
    494     return rc;
    495 }
    496 
    497 static int mm_camera_ch_util_get_crop(mm_camera_obj_t *my_obj,
    498                                 mm_camera_channel_type_t ch_type,
    499                                 mm_camera_state_evt_type_t evt,
    500                                 mm_camera_ch_crop_t *crop)
    501 {
    502     int rc = MM_CAMERA_OK;
    503     switch(ch_type) {
    504     case MM_CAMERA_CH_RAW:
    505         rc = mm_camera_stream_fsm_fn_vtbl(my_obj,
    506                                        &my_obj->ch[ch_type].raw.stream, evt,
    507                                        &crop->crop);
    508         break;
    509     case MM_CAMERA_CH_PREVIEW:
    510         rc = mm_camera_stream_fsm_fn_vtbl(my_obj,
    511                                     &my_obj->ch[ch_type].preview.stream, evt,
    512                                     &crop->crop);
    513         break;
    514     case MM_CAMERA_CH_VIDEO:
    515         rc = mm_camera_stream_fsm_fn_vtbl(my_obj,
    516                           &my_obj->ch[ch_type].video.video, evt,
    517                           &crop->crop);
    518         break;
    519     case MM_CAMERA_CH_SNAPSHOT:
    520         {
    521             rc = mm_camera_stream_fsm_fn_vtbl(my_obj,
    522                           &my_obj->ch[ch_type].snapshot.main, evt,
    523                           &crop->snapshot.main_crop);
    524             if(!rc && !my_obj->full_liveshot) {
    525               ALOGV("%s: should not come here for Live Shot", __func__);
    526               rc = mm_camera_stream_fsm_fn_vtbl(my_obj,
    527                               &my_obj->ch[ch_type].snapshot.thumbnail, evt,
    528                               &crop->snapshot.thumbnail_crop);
    529             }
    530         }
    531         break;
    532     default:
    533         return -1;
    534         break;
    535     }
    536     return rc;
    537 }
    538 
    539 static int mm_camera_ch_util_dispatch_buffered_frame(mm_camera_obj_t *my_obj,
    540                 mm_camera_channel_type_t ch_type)
    541 {
    542     return mm_camera_poll_dispatch_buffered_frames(my_obj, ch_type);
    543 }
    544 
    545 int mm_camera_channel_get_time_diff(struct timespec *cur_ts, int usec_target, struct timespec *frame_ts)
    546 {
    547     int dtusec = (cur_ts->tv_nsec - frame_ts->tv_nsec)/1000;
    548     dtusec += (cur_ts->tv_sec - frame_ts->tv_sec)*1000000 - usec_target;
    549     return dtusec;
    550 }
    551 
    552 static int mm_camera_channel_skip_frames(mm_camera_obj_t *my_obj,
    553                                           mm_camera_frame_queue_t *mq,
    554                                           mm_camera_frame_queue_t *sq,
    555                                           mm_camera_stream_t *mstream,
    556                                           mm_camera_stream_t *sstream,
    557                                           mm_camera_channel_attr_buffering_frame_t *frame_attr)
    558 {
    559     int count = 0;
    560     int i = 0;
    561     mm_camera_frame_t *mframe = NULL, *sframe = NULL;
    562     mm_camera_notify_frame_t notify_frame;
    563 
    564     count = mm_camera_stream_frame_get_q_cnt(mq);
    565     if(count < mm_camera_stream_frame_get_q_cnt(sq))
    566         count = mm_camera_stream_frame_get_q_cnt(sq);
    567     CDBG("%s: Q-size=%d, look_back =%d, M_match=%d, T_match=%d", __func__,
    568          count, frame_attr->look_back, mq->match_cnt, sq->match_cnt);
    569 
    570     count -= frame_attr->look_back;
    571     CDBG("count=%d, frame_attr->look_back=%d,mq->match_cnt=%d, sq->match_cnt=%d",
    572                count, frame_attr->look_back, mq->match_cnt,sq->match_cnt);
    573     for(i=0; i < count; i++) {
    574         mframe = mm_camera_stream_frame_deq(mq);
    575         sframe = mm_camera_stream_frame_deq(sq);
    576         if(mframe && sframe && mframe->frame.frame_id ==
    577            sframe->frame.frame_id) {
    578           mq->match_cnt--;
    579           sq->match_cnt--;
    580         }
    581         if(mframe) {
    582             notify_frame.frame = &mframe->frame;
    583             notify_frame.idx = mframe->idx;
    584             mm_camera_stream_util_buf_done(my_obj, mstream, &notify_frame);
    585         }
    586         if(sframe) {
    587             notify_frame.frame = &sframe->frame;
    588             notify_frame.idx = sframe->idx;
    589             mm_camera_stream_util_buf_done(my_obj, sstream, &notify_frame);
    590         }
    591     }
    592 
    593     CDBG("Post %s: Q-size=%d, look_back =%d, M_match=%d, T_match=%d", __func__,
    594          count, frame_attr->look_back, mq->match_cnt, sq->match_cnt);
    595     return MM_CAMERA_OK;
    596 }
    597 
    598 /*for ZSL mode to send the image pair to client*/
    599 void mm_camera_dispatch_buffered_frames(mm_camera_obj_t *my_obj,
    600                                         mm_camera_channel_type_t ch_type)
    601 {
    602     int mcnt, i, rc = MM_CAMERA_E_GENERAL, scnt;
    603     int num_of_req_frame = 0;
    604     int j;
    605     mm_camera_ch_data_buf_t data;
    606     mm_camera_frame_t *mframe = NULL, *sframe = NULL;
    607     mm_camera_frame_t *qmframe = NULL, *qsframe = NULL;
    608     mm_camera_ch_t *ch = &my_obj->ch[ch_type];
    609     mm_camera_frame_queue_t *mq = NULL;
    610     mm_camera_frame_queue_t *sq = NULL;
    611     mm_camera_stream_t *stream1 = NULL;
    612     mm_camera_stream_t *stream2 = NULL;
    613     ALOGV("%s: E", __func__);
    614     mm_camera_ch_util_get_stream_objs(my_obj, ch_type, &stream1, &stream2);
    615     stream2 = &my_obj->ch[MM_CAMERA_CH_PREVIEW].preview.stream;
    616     if(stream1) {
    617       mq = &stream1->frame.readyq;
    618     }
    619     if(stream2) {
    620       sq = &stream2->frame.readyq;
    621     }
    622     CDBG("mq=%p, sq=%p, stream1=%p, stream2=%p", mq, sq, stream1, stream2);
    623     pthread_mutex_lock(&my_obj->ch[MM_CAMERA_CH_PREVIEW].mutex);
    624     pthread_mutex_lock(&my_obj->ch[MM_CAMERA_CH_SNAPSHOT].mutex);
    625     if (mq && sq && stream1 && stream2) {
    626         rc = mm_camera_channel_skip_frames(my_obj, mq, sq, stream1, stream2, &ch->buffering_frame);
    627         if(rc != MM_CAMERA_OK) {
    628             CDBG_ERROR("%s: Error getting right frame!", __func__);
    629             goto end;
    630         }
    631         num_of_req_frame = my_obj->snap_burst_num_by_user;
    632         ch->snapshot.pending_cnt = num_of_req_frame;
    633 
    634         CDBG("num_of_req_frame =%d", num_of_req_frame);
    635         for(i = 0; i < num_of_req_frame; i++) {
    636             mframe = mm_camera_stream_frame_deq(mq);
    637             sframe = mm_camera_stream_frame_deq(sq);
    638             if(mframe && sframe) {
    639                 CDBG("%s: frame_id = 0x%x|0x%x, main idx = %d, thumbnail idx = %d", __func__,
    640                      mframe->frame.frame_id, sframe->frame.frame_id, mframe->idx, sframe->idx);
    641                 if(mframe->frame.frame_id != sframe->frame.frame_id) {
    642                     CDBG_ERROR("%s: ZSL algorithm error, main and thumbnail "
    643                         "frame_ids not same. Need bug fix", __func__);
    644                 }
    645                 memset(&data, 0, sizeof(data));
    646                 data.type = ch_type;
    647                 data.snapshot.main.frame = &mframe->frame;
    648                 data.snapshot.main.idx = mframe->idx;
    649                 data.snapshot.thumbnail.frame = &sframe->frame;
    650                 data.snapshot.thumbnail.idx = sframe->idx;
    651                 ch->snapshot.pending_cnt--;
    652                 mq->match_cnt--;
    653                 sq->match_cnt--;
    654                 for(j=0;j<MM_CAMERA_BUF_CB_MAX;j++) {
    655                     if( ch->buf_cb[j].cb!=NULL )
    656                         ch->buf_cb[j].cb(&data, ch->buf_cb[j].user_data);
    657                 }
    658             } else {
    659                CDBG_ERROR("%s: mframe %p, sframe = %p", __func__, mframe, sframe);
    660                 qmframe = mframe;
    661                 qsframe = sframe;
    662                 rc = -1;
    663                 break;
    664             }
    665         }
    666         if(qmframe) {
    667             mm_camera_stream_frame_enq(mq, &stream1->frame.frame[qmframe->idx]);
    668             qmframe = NULL;
    669         }
    670         if(qsframe) {
    671             mm_camera_stream_frame_enq(sq, &stream2->frame.frame[qsframe->idx]);
    672             qsframe = NULL;
    673         }
    674     } else {
    675       CDBG_ERROR(" mq =%p sq =%p stream1 =%p stream2 =%p", mq, sq , stream1 , stream2);
    676 
    677     }
    678     CDBG("%s: burst number: %d, pending_count: %d", __func__,
    679         my_obj->snap_burst_num_by_user, ch->snapshot.pending_cnt);
    680 end:
    681     pthread_mutex_unlock(&my_obj->ch[MM_CAMERA_CH_SNAPSHOT].mutex);
    682     pthread_mutex_unlock(&my_obj->ch[MM_CAMERA_CH_PREVIEW].mutex);
    683     /* If we are done sending callbacks for all the requested number of snapshots
    684        send data delivery done event*/
    685     if((rc == MM_CAMERA_OK) && (!ch->snapshot.pending_cnt)) {
    686         mm_camera_event_t data;
    687         data.event_type = MM_CAMERA_EVT_TYPE_CH;
    688         data.e.ch.evt = MM_CAMERA_CH_EVT_DATA_DELIVERY_DONE;
    689         data.e.ch.ch = ch_type;
    690         mm_camera_poll_send_ch_event(my_obj, &data);
    691     }
    692 }
    693 
    694 int32_t mm_camera_ch_fn(mm_camera_obj_t * my_obj,
    695         mm_camera_channel_type_t ch_type,
    696         mm_camera_state_evt_type_t evt, void *val)
    697 {
    698     int32_t rc = MM_CAMERA_OK;
    699 
    700     CDBG("%s:ch = %d, evt=%d\n", __func__, ch_type, evt);
    701     switch(evt) {
    702     case MM_CAMERA_STATE_EVT_ACQUIRE:
    703         rc = mm_camera_ch_util_acquire(my_obj, ch_type);
    704         break;
    705     case MM_CAMERA_STATE_EVT_RELEASE:
    706       /* safe code in case no stream off before release. */
    707         //mm_camera_poll_thread_release(my_obj, ch_type);
    708         rc = mm_camera_ch_util_release(my_obj, ch_type, evt);
    709         break;
    710     case MM_CAMERA_STATE_EVT_ATTR:
    711         rc = mm_camera_ch_util_attr(my_obj, ch_type,
    712                                     (mm_camera_channel_attr_t *)val);
    713         break;
    714     case MM_CAMERA_STATE_EVT_REG_BUF_CB:
    715         rc = mm_camera_ch_util_reg_buf_cb(my_obj, ch_type,
    716                                           (mm_camera_buf_cb_t *)val);
    717         break;
    718     case MM_CAMERA_STATE_EVT_SET_FMT:
    719         rc = mm_camera_ch_util_set_fmt(my_obj, ch_type,
    720                                        (mm_camera_ch_image_fmt_parm_t *)val);
    721         break;
    722     case MM_CAMERA_STATE_EVT_REG_BUF:
    723     case MM_CAMERA_STATE_EVT_REQUEST_BUF:
    724         rc = mm_camera_ch_util_reg_buf(my_obj, ch_type, evt, val);
    725         break;
    726     case MM_CAMERA_STATE_EVT_UNREG_BUF:
    727         rc = mm_camera_ch_util_stream_null_val(my_obj, ch_type, evt, NULL);
    728         break;
    729     case MM_CAMERA_STATE_EVT_STREAM_ON: {
    730         if(ch_type == MM_CAMERA_CH_RAW &&
    731              my_obj->ch[ch_type].raw.mode == MM_CAMERA_RAW_STREAMING_CAPTURE_SINGLE) {
    732             if( MM_CAMERA_OK != (rc = mm_camera_util_s_ctrl(my_obj->ctrl_fd,
    733                 MSM_V4L2_PID_CAM_MODE, MSM_V4L2_CAM_OP_RAW))) {
    734                 CDBG("%s:set MM_CAMERA_RAW_STREAMING_CAPTURE_SINGLE err=%d\n", __func__, rc);
    735                 break;
    736             }
    737         }
    738         mm_camera_poll_thread_add_ch(my_obj, ch_type);
    739         rc = mm_camera_ch_util_stream_null_val(my_obj, ch_type, evt, NULL);
    740         if(rc < 0) {
    741           CDBG_ERROR("%s: Failed in STREAM ON", __func__);
    742           mm_camera_poll_thread_release(my_obj, ch_type);
    743         }
    744         break;
    745     }
    746     case MM_CAMERA_STATE_EVT_STREAM_OFF: {
    747         mm_camera_poll_thread_del_ch(my_obj, ch_type);
    748         rc = mm_camera_ch_util_stream_null_val(my_obj, ch_type, evt, NULL);
    749         break;
    750     }
    751     case MM_CAMERA_STATE_EVT_QBUF:
    752         rc = mm_camera_ch_util_qbuf(my_obj, ch_type, evt,
    753                                     (mm_camera_ch_data_buf_t *)val);
    754         break;
    755     case MM_CAMERA_STATE_EVT_GET_CROP:
    756       rc = mm_camera_ch_util_get_crop(my_obj, ch_type, evt,
    757                                   (mm_camera_ch_crop_t *)val);
    758       break;
    759     case MM_CAMERA_STATE_EVT_DISPATCH_BUFFERED_FRAME:
    760       rc = mm_camera_ch_util_dispatch_buffered_frame(my_obj, ch_type);
    761       break;
    762     default:
    763         break;
    764     }
    765     return rc;
    766 }
    767