Home | History | Annotate | Download | only in mm-camera-interface
      1 /*
      2 Copyright (c) 2011-2012, 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 <sys/ioctl.h>
     34 #include <sys/types.h>
     35 #include <sys/stat.h>
     36 #include <fcntl.h>
     37 #include <poll.h>
     38 #include <linux/msm_ion.h>
     39 #include "mm_camera_interface2.h"
     40 #include "mm_camera.h"
     41 
     42 #if 0
     43 #undef CDBG
     44 #undef LOG_TAG
     45 #define CDBG ALOGV
     46 #define LOG_TAG "NotifyLogs"
     47 #endif
     48 
     49 static void mm_camera_read_raw_frame(mm_camera_obj_t * my_obj)
     50 {
     51     int rc = 0;
     52     int idx;
     53     int i;
     54     int cnt = 0;
     55     mm_camera_stream_t *stream;
     56     mm_camera_buf_cb_t buf_cb[MM_CAMERA_BUF_CB_MAX];
     57     mm_camera_ch_data_buf_t data[MM_CAMERA_BUF_CB_MAX];
     58 
     59     stream = &my_obj->ch[MM_CAMERA_CH_RAW].raw.stream;
     60     idx =  mm_camera_read_msm_frame(my_obj, stream);
     61     if (idx < 0) {
     62         return;
     63     }
     64     pthread_mutex_lock(&my_obj->ch[MM_CAMERA_CH_RAW].mutex);
     65     for( i=0;i<MM_CAMERA_BUF_CB_MAX;i++) {
     66         if((my_obj->ch[MM_CAMERA_CH_RAW].buf_cb[i].cb) &&
     67                 (my_obj->poll_threads[MM_CAMERA_CH_RAW].data.used == 1)){
     68             data[cnt].type = MM_CAMERA_CH_RAW;
     69             data[cnt].def.idx = idx;
     70             data[cnt].def.frame = &my_obj->ch[MM_CAMERA_CH_RAW].raw.stream.frame.frame[idx].frame;
     71             my_obj->ch[MM_CAMERA_CH_RAW].raw.stream.frame.ref_count[idx]++;
     72             CDBG("%s:calling data notify cb 0x%x, 0x%x\n", __func__,
     73                      (uint32_t)my_obj->ch[MM_CAMERA_CH_RAW].buf_cb[i].cb,
     74                      (uint32_t)my_obj->ch[MM_CAMERA_CH_RAW].buf_cb[i].user_data);
     75             memcpy(&buf_cb[cnt], &my_obj->ch[MM_CAMERA_CH_RAW].buf_cb[i], sizeof(mm_camera_buf_cb_t));
     76             cnt++;
     77         }
     78     }
     79     pthread_mutex_unlock(&my_obj->ch[MM_CAMERA_CH_RAW].mutex);
     80 
     81     for( i=0;i<cnt;i++) {
     82         if(buf_cb[i].cb != NULL && my_obj->poll_threads[MM_CAMERA_CH_RAW].data.used == 1){
     83             buf_cb[i].cb(&data[i],buf_cb[i].user_data);
     84         }
     85     }
     86 }
     87 
     88 int mm_camera_zsl_frame_cmp_and_enq(mm_camera_obj_t * my_obj,
     89                                mm_camera_frame_t *node,
     90                                mm_camera_stream_t *mystream)
     91 {
     92     int watermark, interval;
     93     mm_camera_frame_queue_t *myq;
     94     mm_camera_frame_queue_t *peerq;
     95     mm_camera_stream_t *peerstream;
     96     int rc = 0;
     97     int deliver_done = 0;
     98     mm_camera_frame_t *peer_frame;
     99     mm_camera_frame_t *peer_frame_prev;
    100     mm_camera_frame_t *peer_frame_tmp;
    101     mm_camera_notify_frame_t notify_frame;
    102     uint32_t expected_id;
    103     mm_camera_ch_data_buf_t data;
    104     mm_camera_frame_t *my_frame = NULL;
    105     int i;
    106     mm_camera_buf_cb_t buf_cb[MM_CAMERA_BUF_CB_MAX];
    107 
    108     pthread_mutex_lock(&my_obj->ch[MM_CAMERA_CH_PREVIEW].mutex);
    109     pthread_mutex_lock(&my_obj->ch[MM_CAMERA_CH_SNAPSHOT].mutex);
    110 
    111     if(mystream->stream_type == MM_CAMERA_STREAM_PREVIEW) {
    112         peerstream = &my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.main;
    113     } else
    114         peerstream = &my_obj->ch[MM_CAMERA_CH_PREVIEW].preview.stream;
    115     myq = &mystream->frame.readyq;
    116     peerq = &peerstream->frame.readyq;
    117     watermark = my_obj->ch[MM_CAMERA_CH_SNAPSHOT].buffering_frame.water_mark;
    118     interval = my_obj->ch[MM_CAMERA_CH_SNAPSHOT].buffering_frame.interval;
    119     expected_id = my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.expected_matching_id;
    120     peer_frame = peerq->tail;
    121     /* for 30-120 fps streaming no need to consider the wrapping back of frame_id
    122        expected_matching_id is used when requires skipping bwtween frames */
    123     if(!peer_frame || (node->frame.frame_id > peer_frame->frame.frame_id &&
    124         node->frame.frame_id >= expected_id)) {
    125         /* new frame is newer than all stored peer frames. simply keep the node */
    126         /* in case the frame_id wraps back, the peer frame's frame_id will be
    127            larger than the new frame's frame id */
    128         CDBG("%s New frame. Just enqueue it into the queue ", __func__);
    129         mm_camera_stream_frame_enq_no_lock(myq, node);
    130         node->valid_entry = 1;
    131     }
    132     CDBG("%s Need to find match for the frame id %d ,exped_id =%d, strm type =%d",
    133          __func__, node->frame.frame_id, expected_id, mystream->stream_type);
    134     /* the node is older than the peer, we will either find a match or drop it */
    135     peer_frame = peerq->head;
    136     peer_frame_prev = NULL;
    137     peer_frame_tmp = NULL;
    138     while(peer_frame) {
    139         CDBG("%s peer frame_id = %d node frame_id = %d, expected_id =%d, interval=%d", __func__,
    140              peer_frame->frame.frame_id, node->frame.frame_id,
    141              expected_id, interval);
    142         if(peer_frame->match) {
    143             CDBG("%s Peer frame already matched, keep looking in the list ",
    144                  __func__);
    145             /* matched frame., skip */
    146             peer_frame_prev = peer_frame;
    147             peer_frame = peer_frame->next;
    148             continue;
    149         }
    150         if(peer_frame->frame.frame_id == node->frame.frame_id &&
    151            node->frame.frame_id >= my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.expected_matching_id) {
    152             /* find a match keep the frame */
    153             node->match = 1;
    154             peer_frame->match = 1;
    155             CDBG("%s Found match, add to myq, frame_id=%d ", __func__, node->frame.frame_id);
    156             mm_camera_stream_frame_enq_no_lock(myq, node);
    157             myq->match_cnt++;
    158             peerq->match_cnt++;
    159             /*set next min matching id*/
    160             my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.expected_matching_id =
    161               node->frame.frame_id + interval;
    162             goto water_mark;
    163         } else {
    164             /* no match */
    165             if(node->frame.frame_id > peer_frame->frame.frame_id) {
    166                 /* the incoming frame is newer than the peer's unmatched frame.
    167                    drop the peer frame */
    168                 CDBG("%s node frame is newer, release old peer frame ",
    169                      __func__);
    170                 if(!peer_frame_prev) {
    171                     /* this is the head */
    172                     peer_frame_tmp = mm_camera_stream_frame_deq_no_lock(peerq);
    173                     notify_frame.frame = &peer_frame_tmp->frame;
    174                     notify_frame.idx = peer_frame_tmp->idx;
    175                     mm_camera_stream_util_buf_done(my_obj, peerstream,
    176                                                    &notify_frame);
    177                     peer_frame = peerq->head;
    178                     peer_frame_prev = NULL;
    179                     continue;
    180                 } else {
    181                     /* this is not the head. */
    182                     peer_frame_tmp = peer_frame;
    183                     peer_frame_prev->next = peer_frame->next;
    184                     if(peer_frame == peerq->tail) {
    185                         /* peer_frame is the tail */
    186                         peerq->tail = peer_frame_prev;
    187                     }
    188                     notify_frame.frame = &peer_frame_tmp->frame;
    189                     notify_frame.idx = peer_frame_tmp->idx;
    190                     mm_camera_stream_util_buf_done(my_obj, peerstream,
    191                                                    &notify_frame);
    192                     peer_frame = peer_frame_prev->next;
    193                     peerq->cnt--;
    194                     continue;
    195                 }
    196             } else {
    197                 /* Current frame is older than peer's unmatched frame, dont add
    198                  * it into the queue. just drop it */
    199                 CDBG("%s node frame is older than peer's unmatched frame. "
    200                      "Drop the current frame.", __func__);
    201                 notify_frame.frame = &node->frame;
    202                 notify_frame.idx = node->idx;
    203                 mm_camera_stream_util_buf_done(my_obj, mystream, &notify_frame);
    204                 goto end;
    205             }
    206         }
    207     }
    208     if(!node->match && !node->valid_entry) {
    209         /* if no match and not a valid entry.
    210          * the node is not added into the queue. it's dirty node */
    211         CDBG_ERROR("%s: stream type = %d and fd = %d, frame 0x%x is dirty"
    212                    " and queue back kernel", __func__, mystream->stream_type,
    213                     mystream->fd, node->frame.frame_id);
    214         notify_frame.frame = &node->frame;
    215         notify_frame.idx = node->idx;
    216         mm_camera_stream_util_buf_done(my_obj, mystream, &notify_frame);
    217     }
    218 water_mark:
    219     while((myq->match_cnt > watermark) && (peerq->match_cnt > watermark)) {
    220         peer_frame_tmp = mm_camera_stream_frame_deq_no_lock(peerq);
    221         if (NULL == peer_frame_tmp) {
    222             break;
    223         }
    224         notify_frame.frame = &peer_frame_tmp->frame;
    225         notify_frame.idx = peer_frame_tmp->idx;
    226         CDBG("%s match_cnt %d > watermark %d, buf_done on "
    227                    "peer frame idx %d id = %d", __func__,
    228                    myq->match_cnt, watermark, notify_frame.idx,
    229                    notify_frame.frame->frame_id);
    230         mm_camera_stream_util_buf_done(my_obj, peerstream, &notify_frame);
    231         peerq->match_cnt--;
    232         peer_frame_tmp = mm_camera_stream_frame_deq_no_lock(myq);
    233         notify_frame.frame = &peer_frame_tmp->frame;
    234         notify_frame.idx = peer_frame_tmp->idx;
    235         mm_camera_stream_util_buf_done(my_obj, mystream, &notify_frame);
    236         myq->match_cnt--;
    237     }
    238 end:
    239     CDBG("%s myQ->cnt = %d myQ->match_cnt = %d ", __func__,
    240          myq->cnt, myq->match_cnt);
    241     if(myq->cnt > myq->match_cnt + 1) {
    242         /* drop the first unmatched frame */
    243         mm_camera_frame_t *peer_frame = myq->head;;
    244         mm_camera_frame_t *peer_frame_prev = NULL;
    245         while(peer_frame) {
    246             CDBG("%s myQ->cnt = %d myQ->match_cnt = %d ", __func__,
    247                    myq->cnt, myq->match_cnt);
    248             if(peer_frame->match == 0) {
    249                 /* first unmatched frame */
    250                 if(!peer_frame_prev) {
    251                     /* this is the head */
    252                     peer_frame_tmp = mm_camera_stream_frame_deq_no_lock(myq);
    253                     notify_frame.frame = &peer_frame_tmp->frame;
    254                     notify_frame.idx = peer_frame_tmp->idx;
    255                     CDBG("%s Head Issuing buf_done on my frame idx %d id %d",
    256                          __func__, notify_frame.idx,
    257                          notify_frame.frame->frame_id);
    258                     mm_camera_stream_util_buf_done(my_obj, mystream,
    259                                                    &notify_frame);
    260                 } else {
    261                     /* this is not the head. */
    262                     peer_frame_tmp = peer_frame;
    263                     peer_frame_prev->next = peer_frame->next;
    264                     if(peer_frame == peerq->tail) {
    265                         /* peer_frame is the tail */
    266                         myq->tail = peer_frame_prev;
    267                     }
    268                     notify_frame.frame = &peer_frame_tmp->frame;
    269                     notify_frame.idx = peer_frame_tmp->idx;
    270                     CDBG("%s Issuing buf_done on my frame idx %d id = %d",
    271                          __func__, notify_frame.idx,
    272                          notify_frame.frame->frame_id);
    273                     mm_camera_stream_util_buf_done(my_obj, mystream,
    274                                                    &notify_frame);
    275                     myq->cnt--;
    276                 }
    277                 break;
    278             } else {
    279                 peer_frame_prev= peer_frame;
    280                 peer_frame = peer_frame_prev->next;
    281             }
    282         }
    283     }
    284     CDBG("%s peerQ->cnt = %d peerQ->match_cnt = %d ", __func__,
    285          peerq->cnt, peerq->match_cnt);
    286     if(peerq->cnt > peerq->match_cnt + 1) {
    287         /* drop the first unmatched frame */
    288         mm_camera_frame_t *peer_frame = peerq->head;
    289         mm_camera_frame_t *peer_frame_prev = NULL;
    290         while(peer_frame) {
    291             CDBG("%s Traverse peerq list frame idx %d frame_id = %d match %d ",
    292                   __func__, peer_frame->idx, peer_frame->frame.frame_id,
    293                   peer_frame->match);
    294             if(peer_frame->match == 0) {
    295                 /* first unmatched frame */
    296                 if(!peer_frame_prev) {
    297                     /* this is the head */
    298                     peer_frame_tmp = mm_camera_stream_frame_deq_no_lock(peerq);
    299                     notify_frame.frame = &peer_frame_tmp->frame;
    300                     notify_frame.idx = peer_frame_tmp->idx;
    301                     CDBG("%s Head Issuing buf_done on peer frame idx %d "
    302                          "id = %d", __func__, notify_frame.idx,
    303                          notify_frame.frame->frame_id);
    304                     mm_camera_stream_util_buf_done(my_obj, peerstream,
    305                                                    &notify_frame);
    306                 } else {
    307                     /* this is not the head. */
    308                     peer_frame_tmp = peer_frame;
    309                     peer_frame_prev->next = peer_frame->next;
    310                     if(peer_frame == peerq->tail) {
    311                         /* peer_frame is the tail */
    312                         peerq->tail = peer_frame_prev;
    313                     }
    314                     notify_frame.frame = &peer_frame_tmp->frame;
    315                     notify_frame.idx = peer_frame_tmp->idx;
    316                     CDBG("%s Issuing buf_done on peer frame idx %d id = %d",
    317                          __func__, notify_frame.idx,
    318                          notify_frame.frame->frame_id);
    319                     mm_camera_stream_util_buf_done(my_obj, peerstream,
    320                                                    &notify_frame);
    321                     peerq->cnt--;
    322                 }
    323                 break;
    324             } else {
    325                 peer_frame_prev= peer_frame;
    326                 peer_frame = peer_frame_prev->next;
    327             }
    328         }
    329     }
    330 
    331     CDBG("%s Dispatching ZSL frame ", __func__);
    332     if(my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.pending_cnt > 0) {
    333         if(!myq->match_cnt || !peerq->match_cnt) {
    334             pthread_mutex_unlock(&my_obj->ch[MM_CAMERA_CH_SNAPSHOT].mutex);
    335             pthread_mutex_unlock(&my_obj->ch[MM_CAMERA_CH_PREVIEW].mutex);
    336             return 0;
    337         }
    338         /* dequeue one by one and then pass to HAL */
    339         my_frame = mm_camera_stream_frame_deq_no_lock(&my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.main.frame.readyq);
    340         peer_frame = mm_camera_stream_frame_deq_no_lock(&my_obj->ch[MM_CAMERA_CH_PREVIEW].preview.stream.frame.readyq);
    341         if (!my_frame || !peer_frame) {
    342             pthread_mutex_unlock(&my_obj->ch[MM_CAMERA_CH_SNAPSHOT].mutex);
    343             pthread_mutex_unlock(&my_obj->ch[MM_CAMERA_CH_PREVIEW].mutex);
    344             return 0;
    345         }
    346         myq->match_cnt--;
    347         peerq->match_cnt--;
    348         CDBG("%s: Dequeued frame: main frame idx: %d thumbnail "
    349              "frame idx: %d", __func__, my_frame->idx, peer_frame->idx);
    350         /* dispatch this pair of frames */
    351         memset(&data, 0, sizeof(data));
    352         data.type = MM_CAMERA_CH_SNAPSHOT;
    353         data.snapshot.main.frame = &my_frame->frame;
    354         data.snapshot.main.idx = my_frame->idx;
    355         data.snapshot.thumbnail.frame = &peer_frame->frame;
    356         data.snapshot.thumbnail.idx = peer_frame->idx;
    357         my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.pending_cnt--;
    358         memcpy(&buf_cb[0], &my_obj->ch[MM_CAMERA_CH_SNAPSHOT].buf_cb[0],
    359                sizeof(mm_camera_buf_cb_t)* MM_CAMERA_BUF_CB_MAX);
    360         if(my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.pending_cnt == 0)
    361             deliver_done = 1;
    362         pthread_mutex_unlock(&my_obj->ch[MM_CAMERA_CH_SNAPSHOT].mutex);
    363         pthread_mutex_unlock(&my_obj->ch[MM_CAMERA_CH_PREVIEW].mutex);
    364 
    365         goto send_to_hal;
    366     }
    367 
    368     pthread_mutex_unlock(&my_obj->ch[MM_CAMERA_CH_SNAPSHOT].mutex);
    369     pthread_mutex_unlock(&my_obj->ch[MM_CAMERA_CH_PREVIEW].mutex);
    370     return rc;
    371 
    372 send_to_hal:
    373     for( i=0;i < MM_CAMERA_BUF_CB_MAX;i++) {
    374         if (buf_cb[i].cb && my_obj->poll_threads[MM_CAMERA_CH_SNAPSHOT].data.used == 1)
    375             buf_cb[i].cb(&data,buf_cb[i].user_data);
    376     }
    377     if(deliver_done > 0) {
    378         mm_camera_event_t data_evt;
    379         CDBG("%s: ZSL delivered", __func__);
    380         data_evt.event_type = MM_CAMERA_EVT_TYPE_CH;
    381         data_evt.e.ch.evt = MM_CAMERA_CH_EVT_DATA_DELIVERY_DONE;
    382         data_evt.e.ch.ch = MM_CAMERA_CH_SNAPSHOT;
    383         mm_camera_poll_send_ch_event(my_obj, &data_evt);
    384     }
    385     return rc;
    386 }
    387 
    388 static void mm_camera_read_preview_frame(mm_camera_obj_t * my_obj)
    389 {
    390     int rc = 0;
    391     int idx;
    392     int i;
    393     int cnt = 0;
    394     mm_camera_stream_t *stream;
    395     mm_camera_buf_cb_t buf_cb[MM_CAMERA_BUF_CB_MAX];
    396     mm_camera_ch_data_buf_t data[MM_CAMERA_BUF_CB_MAX];
    397 
    398     if (!my_obj->ch[MM_CAMERA_CH_PREVIEW].acquired) {
    399         ALOGV("Preview channel is not in acquired state \n");
    400         return;
    401     }
    402     stream = &my_obj->ch[MM_CAMERA_CH_PREVIEW].preview.stream;
    403     idx =  mm_camera_read_msm_frame(my_obj, stream);
    404     if (idx < 0) {
    405         return;
    406     }
    407     CDBG("%s Read Preview frame %d ", __func__, idx);
    408     pthread_mutex_lock(&my_obj->ch[MM_CAMERA_CH_PREVIEW].mutex);
    409     for( i=0;i<MM_CAMERA_BUF_CB_MAX;i++) {
    410         if((my_obj->ch[MM_CAMERA_CH_PREVIEW].buf_cb[i].cb) &&
    411                 (my_obj->poll_threads[MM_CAMERA_CH_PREVIEW].data.used == 1)) {
    412             data[cnt].type = MM_CAMERA_CH_PREVIEW;
    413             data[cnt].def.idx = idx;
    414             data[cnt].def.frame = &my_obj->ch[MM_CAMERA_CH_PREVIEW].preview.stream.frame.frame[idx].frame;
    415             /* Since the frame is originating here, reset the ref count to either
    416              * 2(ZSL case) or 1(non-ZSL case). */
    417             if(my_obj->op_mode == MM_CAMERA_OP_MODE_ZSL)
    418                 my_obj->ch[MM_CAMERA_CH_PREVIEW].preview.stream.frame.ref_count[idx] = 2;
    419             else
    420                 my_obj->ch[MM_CAMERA_CH_PREVIEW].preview.stream.frame.ref_count[idx] = 1;
    421             CDBG("%s:calling data notify cb 0x%x, 0x%x\n", __func__,
    422                      (uint32_t)my_obj->ch[MM_CAMERA_CH_PREVIEW].buf_cb[i].cb,
    423                      (uint32_t)my_obj->ch[MM_CAMERA_CH_PREVIEW].buf_cb[i].user_data);
    424             /*my_obj->ch[MM_CAMERA_CH_PREVIEW].buf_cb[i].cb(&data,
    425                                         my_obj->ch[MM_CAMERA_CH_PREVIEW].buf_cb[i].user_data);*/
    426             memcpy(&buf_cb[cnt], &my_obj->ch[MM_CAMERA_CH_PREVIEW].buf_cb[i],
    427                    sizeof(mm_camera_buf_cb_t));
    428             cnt++;
    429         }
    430     }
    431     pthread_mutex_unlock(&my_obj->ch[MM_CAMERA_CH_PREVIEW].mutex);
    432 
    433     if(my_obj->op_mode == MM_CAMERA_OP_MODE_ZSL) {
    434         /* Reset match to 0. */
    435         stream->frame.frame[idx].match = 0;
    436         stream->frame.frame[idx].valid_entry = 0;
    437         mm_camera_zsl_frame_cmp_and_enq(my_obj,
    438           &my_obj->ch[MM_CAMERA_CH_PREVIEW].preview.stream.frame.frame[idx],
    439           stream);
    440     }
    441 
    442     for( i=0;i<cnt;i++) {
    443         if(buf_cb[i].cb != NULL && my_obj->poll_threads[MM_CAMERA_CH_PREVIEW].data.used == 1) {
    444             buf_cb[i].cb(&data[i],buf_cb[i].user_data);
    445         }
    446     }
    447 }
    448 
    449 static void mm_camera_snapshot_send_liveshot_notify(mm_camera_obj_t * my_obj)
    450 {
    451     int delivered = 0;
    452     mm_camera_frame_queue_t *s_q;
    453     int i;
    454     int cnt = 0;
    455 //    mm_camera_frame_queue_t *s_q, *t_q;
    456     mm_camera_buf_cb_t buf_cb[MM_CAMERA_BUF_CB_MAX];
    457     mm_camera_ch_data_buf_t data[MM_CAMERA_BUF_CB_MAX];
    458 
    459     mm_camera_frame_t *frame;
    460     s_q =   &my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.main.frame.readyq;
    461     pthread_mutex_lock(&my_obj->ch[MM_CAMERA_CH_SNAPSHOT].mutex);
    462 
    463     for( i=0;i<MM_CAMERA_BUF_CB_MAX;i++) {
    464         if(s_q->cnt && my_obj->ch[MM_CAMERA_CH_SNAPSHOT].buf_cb[i].cb) {
    465             data[cnt].type = MM_CAMERA_CH_SNAPSHOT;
    466             frame = mm_camera_stream_frame_deq(s_q);
    467             data[cnt].snapshot.main.frame = &frame->frame;
    468             data[cnt].snapshot.main.idx = frame->idx;
    469             data[cnt].snapshot.thumbnail.frame = NULL;
    470             my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.main.frame.ref_count[data[cnt].snapshot.main.idx]++;
    471             /*my_obj->ch[MM_CAMERA_CH_SNAPSHOT].buf_cb[i].cb(&data,
    472                                     my_obj->ch[MM_CAMERA_CH_SNAPSHOT].buf_cb[i].user_data);*/
    473             memcpy(&buf_cb[cnt], &my_obj->ch[MM_CAMERA_CH_SNAPSHOT].buf_cb[i],
    474                    sizeof(mm_camera_buf_cb_t));
    475             cnt++;
    476 
    477             my_obj->snap_burst_num_by_user -= 1;
    478             CDBG("%s: burst number =%d", __func__, my_obj->snap_burst_num_by_user);
    479             delivered = 1;
    480         }
    481     }
    482     pthread_mutex_unlock(&my_obj->ch[MM_CAMERA_CH_SNAPSHOT].mutex);
    483 
    484     for( i=0;i<cnt;i++) {
    485         if(buf_cb[i].cb != NULL && my_obj->poll_threads[MM_CAMERA_CH_SNAPSHOT].data.used == 1) {
    486             buf_cb[i].cb(&data[i],buf_cb[i].user_data);
    487         }
    488     }
    489 
    490     if(delivered) {
    491       mm_camera_event_t data;
    492       data.event_type = MM_CAMERA_EVT_TYPE_CH;
    493       data.e.ch.evt = MM_CAMERA_CH_EVT_DATA_DELIVERY_DONE;
    494       data.e.ch.ch = MM_CAMERA_CH_SNAPSHOT;
    495       mm_camera_poll_send_ch_event(my_obj, &data);
    496     }
    497 }
    498 
    499 static void mm_camera_snapshot_send_snapshot_notify(mm_camera_obj_t * my_obj)
    500 {
    501     int delivered = 0;
    502     int i;
    503     int cnt = 0;
    504     mm_camera_frame_queue_t *s_q, *t_q;
    505     mm_camera_frame_t *frame;
    506     //mm_camera_buf_cb_t buf_cb;
    507 
    508     mm_camera_buf_cb_t buf_cb[MM_CAMERA_BUF_CB_MAX];
    509     mm_camera_ch_data_buf_t data[MM_CAMERA_BUF_CB_MAX];
    510 
    511     memset(&buf_cb, 0, sizeof(buf_cb));
    512     s_q =   &my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.main.frame.readyq;
    513     t_q =   &my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.thumbnail.frame.readyq;
    514     pthread_mutex_lock(&my_obj->ch[MM_CAMERA_CH_SNAPSHOT].mutex);
    515 
    516     for( i=0;i<MM_CAMERA_BUF_CB_MAX;i++) {
    517         CDBG("%s Got notify: s_q->cnt = %d, t_q->cnt = %d, buf_cb = %x, "
    518              "data.used = %d ", __func__, s_q->cnt, t_q->cnt,
    519              (uint32_t)my_obj->ch[MM_CAMERA_CH_SNAPSHOT].buf_cb[i].cb,
    520              my_obj->poll_threads[MM_CAMERA_CH_SNAPSHOT].data.used);
    521         if((s_q->cnt && t_q->cnt && my_obj->ch[MM_CAMERA_CH_SNAPSHOT].buf_cb[i].cb) &&
    522                 (my_obj->poll_threads[MM_CAMERA_CH_SNAPSHOT].data.used == 1)) {
    523             data[cnt].type = MM_CAMERA_CH_SNAPSHOT;
    524             frame = mm_camera_stream_frame_deq(s_q);
    525             data[cnt].snapshot.main.frame = &frame->frame;
    526             data[cnt].snapshot.main.idx = frame->idx;
    527             frame = mm_camera_stream_frame_deq(t_q);
    528             data[cnt].snapshot.thumbnail.frame = &frame->frame;
    529             data[cnt].snapshot.thumbnail.idx = frame->idx;
    530             my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.main.frame.ref_count[data[i].snapshot.main.idx]++;
    531             my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.thumbnail.frame.ref_count[data[i].snapshot.thumbnail.idx]++;
    532 
    533             //bu = my_obj->ch[MM_CAMERA_CH_SNAPSHOT].buf_cb[i];
    534             memcpy(&buf_cb[cnt], &my_obj->ch[MM_CAMERA_CH_SNAPSHOT].buf_cb[i],
    535                sizeof(mm_camera_buf_cb_t));
    536             cnt++;
    537 
    538             //buf_cb.cb(&data,buf_cb.user_data);
    539             my_obj->snap_burst_num_by_user -= 1;
    540             CDBG("%s: burst number =%d", __func__, my_obj->snap_burst_num_by_user);
    541             delivered = 1;
    542         }
    543     }
    544     pthread_mutex_unlock(&my_obj->ch[MM_CAMERA_CH_SNAPSHOT].mutex);
    545 
    546     for( i=0;i<cnt;i++) {
    547         if(buf_cb[i].cb != NULL && my_obj->poll_threads[MM_CAMERA_CH_SNAPSHOT].data.used == 1) {
    548             buf_cb[i].cb(&data[i],buf_cb[i].user_data);
    549         }
    550     }
    551 
    552     CDBG("%s Delivered = %d ", __func__, delivered );
    553     if(delivered) {
    554         mm_camera_event_t edata;
    555         /*for( i=0;i<MM_CAMERA_BUF_CB_MAX;i++){
    556             buf_cb = &my_obj->ch[MM_CAMERA_CH_SNAPSHOT].buf_cb[i];
    557             if((buf_cb) && (my_obj->poll_threads[MM_CAMERA_CH_SNAPSHOT].data.used == 1)) {
    558                 buf_cb->cb(&data,buf_cb->user_data);
    559             }
    560         }*/
    561         edata.event_type = MM_CAMERA_EVT_TYPE_CH;
    562         edata.e.ch.evt = MM_CAMERA_CH_EVT_DATA_DELIVERY_DONE;
    563         edata.e.ch.ch = MM_CAMERA_CH_SNAPSHOT;
    564         mm_camera_poll_send_ch_event(my_obj, &edata);
    565     }
    566 }
    567 
    568 static void mm_camera_read_snapshot_main_frame(mm_camera_obj_t * my_obj)
    569 {
    570     int rc = 0;
    571     int idx;
    572     mm_camera_stream_t *stream;
    573     mm_camera_frame_queue_t *q;
    574     if (!my_obj->ch[MM_CAMERA_CH_SNAPSHOT].acquired) {
    575         ALOGV("Snapshot channel is not in acquired state \n");
    576         return;
    577     }
    578     q = &my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.main.frame.readyq;
    579     stream = &my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.main;
    580     idx =  mm_camera_read_msm_frame(my_obj,stream);
    581     if (idx < 0)
    582         return;
    583 
    584     CDBG("%s Read Snapshot frame %d ", __func__, idx);
    585     if(my_obj->op_mode == MM_CAMERA_OP_MODE_ZSL) {
    586         my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.main.frame.ref_count[idx]++;
    587         /* Reset match to 0. */
    588         stream->frame.frame[idx].match = 0;
    589         stream->frame.frame[idx].valid_entry = 0;
    590         mm_camera_zsl_frame_cmp_and_enq(my_obj,
    591           &my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.main.frame.frame[idx], stream);
    592     } else {
    593         /* send to HAL */
    594         mm_camera_stream_frame_enq(q, &stream->frame.frame[idx]);
    595         if (!my_obj->full_liveshot)
    596           mm_camera_snapshot_send_snapshot_notify(my_obj);
    597         else
    598           mm_camera_snapshot_send_liveshot_notify(my_obj);
    599     }
    600 }
    601 static void mm_camera_read_snapshot_thumbnail_frame(mm_camera_obj_t * my_obj)
    602 {
    603     int idx, rc = 0;
    604     mm_camera_stream_t *stream;
    605     mm_camera_frame_queue_t *q;
    606 
    607     if (!my_obj->ch[MM_CAMERA_CH_SNAPSHOT].acquired) {
    608         ALOGV("Snapshot channel is not in acquired state \n");
    609         return;
    610     }
    611     q = &my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.thumbnail.frame.readyq;
    612     stream = &my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.thumbnail;
    613     idx =  mm_camera_read_msm_frame(my_obj,stream);
    614     if (idx < 0)
    615         return;
    616     if(my_obj->op_mode != MM_CAMERA_OP_MODE_ZSL) {
    617         mm_camera_stream_frame_enq(q, &stream->frame.frame[idx]);
    618         mm_camera_snapshot_send_snapshot_notify(my_obj);
    619     } else {
    620 //        CDBG("%s: ZSL does not use thumbnail stream",  __func__);
    621         rc = mm_camera_stream_qbuf(my_obj, stream, idx);
    622 //        CDBG("%s Q back thumbnail buffer rc = %d ", __func__, rc);
    623     }
    624 }
    625 
    626 static void mm_camera_read_video_frame(mm_camera_obj_t * my_obj)
    627 {
    628     int idx, rc = 0;
    629     mm_camera_stream_t *stream;
    630     mm_camera_frame_queue_t *q;
    631     int i;
    632     int cnt = 0;
    633     mm_camera_buf_cb_t buf_cb[MM_CAMERA_BUF_CB_MAX];
    634     mm_camera_ch_data_buf_t data[MM_CAMERA_BUF_CB_MAX];
    635 
    636     if (!my_obj->ch[MM_CAMERA_CH_VIDEO].acquired) {
    637         ALOGV("Snapshot channel is not in acquired state \n");
    638         return;
    639     }
    640     stream = &my_obj->ch[MM_CAMERA_CH_VIDEO].video.video;
    641     idx =  mm_camera_read_msm_frame(my_obj,stream);
    642     if (idx < 0)
    643         return;
    644 
    645     ALOGV("Video thread locked");
    646     pthread_mutex_lock(&my_obj->ch[MM_CAMERA_CH_VIDEO].mutex);
    647     for( i=0;i<MM_CAMERA_BUF_CB_MAX;i++) {
    648         if((my_obj->ch[MM_CAMERA_CH_VIDEO].buf_cb[i].cb) &&
    649                 (my_obj->poll_threads[MM_CAMERA_CH_VIDEO].data.used == 1)){
    650             data[cnt].type = MM_CAMERA_CH_VIDEO;
    651             data[cnt].video.main.frame = NULL;
    652             data[cnt].video.main.idx = -1;
    653             data[cnt].video.video.idx = idx;
    654             data[cnt].video.video.frame = &my_obj->ch[MM_CAMERA_CH_VIDEO].video.video.
    655                 frame.frame[idx].frame;
    656             my_obj->ch[MM_CAMERA_CH_VIDEO].video.video.frame.ref_count[idx]++;
    657             ALOGV("Video thread callback issued");
    658             //my_obj->ch[MM_CAMERA_CH_VIDEO].buf_cb[i].cb(&data,
    659             //                        my_obj->ch[MM_CAMERA_CH_VIDEO].buf_cb[i].user_data);
    660             memcpy(&buf_cb[cnt], &my_obj->ch[MM_CAMERA_CH_VIDEO].buf_cb[i],
    661                    sizeof(mm_camera_buf_cb_t));
    662             cnt++;
    663 
    664             ALOGV("Video thread callback returned");
    665             if( my_obj->ch[MM_CAMERA_CH_VIDEO].buf_cb[i].cb_type==MM_CAMERA_BUF_CB_COUNT ) {
    666                 ALOGV("<DEBUG>:%s: Additional cb called for buffer %p:%d",__func__,stream,idx);
    667                 if(--(my_obj->ch[MM_CAMERA_CH_VIDEO].buf_cb[i].cb_count) == 0 )
    668                     my_obj->ch[MM_CAMERA_CH_VIDEO].buf_cb[i].cb=NULL;
    669             }
    670         }
    671     }
    672     pthread_mutex_unlock(&my_obj->ch[MM_CAMERA_CH_VIDEO].mutex);
    673 
    674      for( i=0;i<cnt;i++) {
    675         if(buf_cb[i].cb != NULL && my_obj->poll_threads[MM_CAMERA_CH_VIDEO].data.used == 1) {
    676             buf_cb[i].cb(&data[i],buf_cb[i].user_data);
    677         }
    678         /*if( buf_cb[i].cb_type==MM_CAMERA_BUF_CB_COUNT ) {
    679                 ALOGV("<DEBUG>:%s: Additional cb called for buffer %p:%d",__func__,stream,idx);
    680                 if(--(buf_cb[i].cb_count) == 0 )
    681                     buf_cb[i].cb=NULL;
    682         }*/
    683     }
    684 
    685     ALOGV("Video thread unlocked");
    686 }
    687 
    688 static void mm_camera_read_video_main_frame(mm_camera_obj_t * my_obj)
    689 {
    690     int rc = 0;
    691     return;rc;
    692 }
    693 
    694 static void mm_camera_read_zsl_main_frame(mm_camera_obj_t * my_obj)
    695 {
    696     int idx, rc = 0;
    697     mm_camera_stream_t *stream;
    698     mm_camera_frame_queue_t *q;
    699     mm_camera_frame_t *frame;
    700     int cnt, watermark;
    701 
    702     q =   &my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.main.frame.readyq;
    703     stream = &my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.main;
    704     idx =  mm_camera_read_msm_frame(my_obj,stream);
    705     if (idx < 0)
    706         return;
    707 
    708     CDBG("%s: Enqueuing frame id: %d", __func__, idx);
    709     mm_camera_stream_frame_enq(q, &stream->frame.frame[idx]);
    710     cnt = mm_camera_stream_frame_get_q_cnt(q);
    711     watermark = my_obj->ch[MM_CAMERA_CH_SNAPSHOT].buffering_frame.water_mark;
    712 
    713     CDBG("%s: Watermark: %d Queue in a frame: %d", __func__, watermark, cnt);
    714     if(watermark < cnt) {
    715         /* water overflow, queue head back to kernel */
    716         frame = mm_camera_stream_frame_deq(q);
    717         if(frame) {
    718             rc = mm_camera_stream_qbuf(my_obj, stream, frame->idx);
    719             if(rc < 0) {
    720                 CDBG("%s: mm_camera_stream_qbuf(idx=%d) err=%d\n",
    721                      __func__, frame->idx, rc);
    722                 return;
    723             }
    724         }
    725     }
    726     mm_camera_check_pending_zsl_frames(my_obj, MM_CAMERA_CH_SNAPSHOT);
    727 }
    728 
    729 static void mm_camera_read_zsl_postview_frame(mm_camera_obj_t * my_obj)
    730 {
    731     int idx, rc = 0;
    732     mm_camera_stream_t *stream;
    733     mm_camera_frame_queue_t *q;
    734     mm_camera_frame_t *frame;
    735     int cnt, watermark;
    736     q = &my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.thumbnail.frame.readyq;
    737     stream = &my_obj->ch[MM_CAMERA_CH_SNAPSHOT].snapshot.thumbnail;
    738     idx =  mm_camera_read_msm_frame(my_obj,stream);
    739     if (idx < 0)
    740         return;
    741     mm_camera_stream_frame_enq(q, &stream->frame.frame[idx]);
    742     watermark = my_obj->ch[MM_CAMERA_CH_SNAPSHOT].buffering_frame.water_mark;
    743     cnt = mm_camera_stream_frame_get_q_cnt(q);
    744     if(watermark < cnt) {
    745         /* water overflow, queue head back to kernel */
    746         frame = mm_camera_stream_frame_deq(q);
    747         if(frame) {
    748             rc = mm_camera_stream_qbuf(my_obj, stream, frame->idx);
    749             if(rc < 0) {
    750                 CDBG("%s: mm_camera_stream_qbuf(idx=%d) err=%d\n",
    751                      __func__, frame->idx, rc);
    752                 return;
    753             }
    754         }
    755     }
    756     mm_camera_check_pending_zsl_frames(my_obj, MM_CAMERA_CH_SNAPSHOT);
    757 }
    758 
    759 void mm_camera_msm_data_notify(mm_camera_obj_t * my_obj, int fd,
    760                                mm_camera_stream_type_t stream_type)
    761 {
    762     switch(stream_type) {
    763     case MM_CAMERA_STREAM_RAW:
    764         mm_camera_read_raw_frame(my_obj);
    765         break;
    766     case MM_CAMERA_STREAM_PREVIEW:
    767         mm_camera_read_preview_frame(my_obj);
    768         break;
    769     case MM_CAMERA_STREAM_SNAPSHOT:
    770         mm_camera_read_snapshot_main_frame(my_obj);
    771         break;
    772     case MM_CAMERA_STREAM_THUMBNAIL:
    773         mm_camera_read_snapshot_thumbnail_frame(my_obj);
    774         break;
    775     case MM_CAMERA_STREAM_VIDEO:
    776         mm_camera_read_video_frame(my_obj);
    777         break;
    778     case MM_CAMERA_STREAM_VIDEO_MAIN:
    779         mm_camera_read_video_main_frame(my_obj);
    780         break;
    781     default:
    782         break;
    783     }
    784 }
    785 
    786 static mm_camera_channel_type_t mm_camera_image_mode_to_ch(int image_mode)
    787 {
    788     switch(image_mode) {
    789     case MSM_V4L2_EXT_CAPTURE_MODE_PREVIEW:
    790         return MM_CAMERA_CH_PREVIEW;
    791     case MSM_V4L2_EXT_CAPTURE_MODE_MAIN:
    792     case MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL:
    793         return MM_CAMERA_CH_SNAPSHOT;
    794     case MSM_V4L2_EXT_CAPTURE_MODE_VIDEO:
    795         return MM_CAMERA_CH_VIDEO;
    796     case MSM_V4L2_EXT_CAPTURE_MODE_RAW:
    797         return MM_CAMERA_CH_RAW;
    798     default:
    799         return MM_CAMERA_CH_MAX;
    800     }
    801 }
    802 
    803 void mm_camera_dispatch_app_event(mm_camera_obj_t *my_obj, mm_camera_event_t *event)
    804 {
    805     int i;
    806     mm_camera_evt_obj_t evtcb;
    807 
    808     if(event->event_type <  MM_CAMERA_EVT_TYPE_MAX) {
    809       pthread_mutex_lock(&my_obj->mutex);
    810       memcpy(&evtcb,
    811        &my_obj->evt[event->event_type],
    812        sizeof(mm_camera_evt_obj_t));
    813       pthread_mutex_unlock(&my_obj->mutex);
    814       for(i = 0; i < MM_CAMERA_EVT_ENTRY_MAX; i++) {
    815         if(evtcb.evt[i].evt_cb) {
    816           evtcb.evt[i].evt_cb(event, evtcb.evt[i].user_data);
    817         }
    818       }
    819     }
    820 }
    821 
    822 void mm_camera_msm_evt_notify(mm_camera_obj_t * my_obj, int fd)
    823 {
    824     struct v4l2_event ev;
    825     int rc;
    826     mm_camera_event_t *evt = NULL;
    827 
    828     memset(&ev, 0, sizeof(ev));
    829     rc = ioctl(fd, VIDIOC_DQEVENT, &ev);
    830     evt = (mm_camera_event_t *)ev.u.data;
    831 
    832     if (rc >= 0) {
    833         if(ev.type == V4L2_EVENT_PRIVATE_START+MSM_CAM_APP_NOTIFY_ERROR_EVENT) {
    834             evt->event_type = MM_CAMERA_EVT_TYPE_CTRL;
    835             evt->e.ctrl.evt = MM_CAMERA_CTRL_EVT_ERROR;
    836         }
    837         switch(evt->event_type) {
    838         case MM_CAMERA_EVT_TYPE_INFO:
    839            break;
    840         case MM_CAMERA_EVT_TYPE_STATS:
    841            break;
    842         case MM_CAMERA_EVT_TYPE_CTRL:
    843            break;
    844         default:
    845             break;
    846         }
    847         mm_camera_dispatch_app_event(my_obj, evt);
    848     }
    849 }
    850