Home | History | Annotate | Download | only in src
      1 /* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
      2  *
      3  * Redistribution and use in source and binary forms, with or without
      4  * modification, are permitted provided that the following conditions are
      5  * met:
      6  *     * Redistributions of source code must retain the above copyright
      7  *       notice, this list of conditions and the following disclaimer.
      8  *     * Redistributions in binary form must reproduce the above
      9  *       copyright notice, this list of conditions and the following
     10  *       disclaimer in the documentation and/or other materials provided
     11  *       with the distribution.
     12  *     * Neither the name of The Linux Foundation nor the names of its
     13  *       contributors may be used to endorse or promote products derived
     14  *       from this software without specific prior written permission.
     15  *
     16  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
     17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
     19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
     20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
     23  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     24  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     25  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
     26  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27  *
     28  */
     29 
     30 // System dependencies
     31 #include <pthread.h>
     32 #include <fcntl.h>
     33 
     34 // Camera dependencies
     35 #include "cam_semaphore.h"
     36 #include "mm_camera_dbg.h"
     37 #include "mm_camera_interface.h"
     38 #include "mm_camera.h"
     39 #include "mm_camera_muxer.h"
     40 
     41 #include "cam_cond.h"
     42 
     43 extern mm_camera_obj_t* mm_camera_util_get_camera_by_handler(uint32_t cam_handler);
     44 extern mm_channel_t * mm_camera_util_get_channel_by_handler(mm_camera_obj_t * cam_obj,
     45                                                             uint32_t handler);
     46 /* Static frame sync info used between different camera channels*/
     47 static mm_channel_frame_sync_info_t fs = { .num_cam =0, .pos = 0};
     48 /* Frame sync info access lock */
     49 static pthread_mutex_t fs_lock = PTHREAD_MUTEX_INITIALIZER;
     50 
     51 /* internal function declare goes here */
     52 int32_t mm_channel_qbuf(mm_channel_t *my_obj,
     53                         mm_camera_buf_def_t *buf);
     54 int32_t mm_channel_cancel_buf(mm_channel_t *my_obj,
     55                         uint32_t stream_id, uint32_t buf_idx);
     56 int32_t mm_channel_init(mm_channel_t *my_obj,
     57                         mm_camera_channel_attr_t *attr,
     58                         mm_camera_buf_notify_t channel_cb,
     59                         void *userdata);
     60 void mm_channel_release(mm_channel_t *my_obj);
     61 uint32_t mm_channel_add_stream(mm_channel_t *my_obj);
     62 int32_t mm_channel_del_stream(mm_channel_t *my_obj,
     63                                    uint32_t stream_id);
     64 uint32_t mm_channel_link_stream(mm_channel_t *my_obj,
     65         mm_camera_stream_link_t *stream_link);
     66 uint32_t mm_channel_reg_frame_sync(mm_channel_t *my_obj,
     67         mm_evt_paylod_reg_frame_sync *sync);
     68 int32_t mm_channel_trigger_frame_sync(mm_channel_t *my_obj,
     69         mm_evt_paylod_trigger_frame_sync *payload);
     70 int32_t mm_channel_config_stream(mm_channel_t *my_obj,
     71                                  uint32_t stream_id,
     72                                  mm_camera_stream_config_t *config);
     73 int32_t mm_channel_get_bundle_info(mm_channel_t *my_obj,
     74                                    cam_bundle_config_t *bundle_info);
     75 int32_t mm_channel_start(mm_channel_t *my_obj);
     76 int32_t mm_channel_start_sensor_streaming(mm_channel_t *my_obj);
     77 int32_t mm_channel_stop(mm_channel_t *my_obj, bool stop_immediately);
     78 int32_t mm_channel_request_super_buf(mm_channel_t *my_obj,
     79         mm_camera_req_buf_t *buf);
     80 int32_t mm_channel_cancel_super_buf_request(mm_channel_t *my_obj);
     81 int32_t mm_channel_flush_super_buf_queue(mm_channel_t *my_obj,
     82                                          uint32_t frame_idx,
     83                                          cam_stream_type_t stream_type);
     84 int32_t mm_channel_config_notify_mode(mm_channel_t *my_obj,
     85                                       mm_camera_super_buf_notify_mode_t notify_mode);
     86 int32_t mm_channel_start_zsl_snapshot(mm_channel_t *my_obj);
     87 int32_t mm_channel_stop_zsl_snapshot(mm_channel_t *my_obj);
     88 int32_t mm_channel_superbuf_flush(mm_channel_t* my_obj,
     89         mm_channel_queue_t * queue, cam_stream_type_t cam_type);
     90 int32_t mm_channel_set_stream_parm(mm_channel_t *my_obj,
     91                                    mm_evt_paylod_set_get_stream_parms_t *payload);
     92 int32_t mm_channel_get_queued_buf_count(mm_channel_t *my_obj,
     93         uint32_t stream_id);
     94 
     95 int32_t mm_channel_get_stream_parm(mm_channel_t *my_obj,
     96                                    mm_evt_paylod_set_get_stream_parms_t *payload);
     97 int32_t mm_channel_do_stream_action(mm_channel_t *my_obj,
     98                                     mm_evt_paylod_do_stream_action_t *payload);
     99 int32_t mm_channel_map_stream_buf(mm_channel_t *my_obj,
    100                                   cam_buf_map_type *payload);
    101 int32_t mm_channel_map_stream_bufs(mm_channel_t *my_obj,
    102                                    cam_buf_map_type_list *payload);
    103 int32_t mm_channel_unmap_stream_buf(mm_channel_t *my_obj,
    104                                     cam_buf_unmap_type *payload);
    105 
    106 /* state machine function declare */
    107 int32_t mm_channel_fsm_fn_notused(mm_channel_t *my_obj,
    108                           mm_channel_evt_type_t evt,
    109                           void * in_val,
    110                           void * out_val);
    111 int32_t mm_channel_fsm_fn_stopped(mm_channel_t *my_obj,
    112                           mm_channel_evt_type_t evt,
    113                           void * in_val,
    114                           void * out_val);
    115 int32_t mm_channel_fsm_fn_active(mm_channel_t *my_obj,
    116                           mm_channel_evt_type_t evt,
    117                           void * in_val,
    118                           void * out_val);
    119 int32_t mm_channel_fsm_fn_paused(mm_channel_t *my_obj,
    120                           mm_channel_evt_type_t evt,
    121                           void * in_val,
    122                           void * out_val);
    123 
    124 /* channel super queue functions */
    125 int32_t mm_channel_superbuf_queue_init(mm_channel_queue_t * queue);
    126 int32_t mm_channel_superbuf_queue_deinit(mm_channel_queue_t * queue);
    127 int32_t mm_channel_superbuf_comp_and_enqueue(mm_channel_t *ch_obj,
    128                                              mm_channel_queue_t * queue,
    129                                              mm_camera_buf_info_t *buf);
    130 mm_channel_queue_node_t* mm_channel_superbuf_dequeue(
    131         mm_channel_queue_t * queue, mm_channel_t *ch_obj);
    132 int32_t mm_channel_superbuf_bufdone_overflow(mm_channel_t *my_obj,
    133                                              mm_channel_queue_t *queue);
    134 int32_t mm_channel_superbuf_skip(mm_channel_t *my_obj,
    135                                  mm_channel_queue_t *queue);
    136 
    137 static int32_t mm_channel_proc_general_cmd(mm_channel_t *my_obj,
    138                                            mm_camera_generic_cmd_t *p_gen_cmd);
    139 int32_t mm_channel_superbuf_flush_matched(mm_channel_t* my_obj,
    140                                           mm_channel_queue_t * queue);
    141 
    142 /* Start of Frame Sync util methods */
    143 void mm_frame_sync_reset();
    144 int32_t mm_frame_sync_register_channel(mm_channel_t *ch_obj);
    145 int32_t mm_frame_sync_unregister_channel(mm_channel_t *ch_obj);
    146 int32_t mm_frame_sync_add(uint32_t frame_id, mm_channel_t *ch_obj);
    147 int32_t mm_frame_sync_remove(uint32_t frame_id);
    148 uint32_t mm_frame_sync_find_matched(uint8_t oldest);
    149 int8_t mm_frame_sync_find_frame_index(uint32_t frame_id);
    150 void mm_frame_sync_lock_queues();
    151 void mm_frame_sync_unlock_queues();
    152 void mm_channel_node_qbuf(mm_channel_t *ch_obj, mm_channel_queue_node_t *node);
    153 /* End of Frame Sync Util methods */
    154 void mm_channel_send_super_buf(mm_channel_node_info_t *info);
    155 mm_channel_queue_node_t* mm_channel_superbuf_dequeue_frame_internal(
    156         mm_channel_queue_t * queue, uint32_t frame_idx);
    157 
    158 /*===========================================================================
    159  * FUNCTION   : mm_channel_util_get_stream_by_handler
    160  *
    161  * DESCRIPTION: utility function to get a stream object from its handle
    162  *
    163  * PARAMETERS :
    164  *   @cam_obj: ptr to a channel object
    165  *   @handler: stream handle
    166  *
    167  * RETURN     : ptr to a stream object.
    168  *              NULL if failed.
    169  *==========================================================================*/
    170 mm_stream_t * mm_channel_util_get_stream_by_handler(
    171                                     mm_channel_t * ch_obj,
    172                                     uint32_t handler)
    173 {
    174     int i;
    175     mm_stream_t *s_obj = NULL;
    176 
    177     for(i = 0; i < MAX_STREAM_NUM_IN_BUNDLE; i++) {
    178         if ((MM_STREAM_STATE_NOTUSED != ch_obj->streams[i].state) &&
    179             (handler == ch_obj->streams[i].my_hdl)) {
    180             s_obj = &ch_obj->streams[i];
    181             break;
    182         }
    183     }
    184     return s_obj;
    185 }
    186 
    187 /*===========================================================================
    188  * FUNCTION   : mm_channel_dispatch_super_buf
    189  *
    190  * DESCRIPTION: dispatch super buffer of bundle to registered user
    191  *
    192  * PARAMETERS :
    193  *   @cmd_cb  : ptr storing matched super buf information
    194  *   @userdata: user data ptr
    195  *
    196  * RETURN     : none
    197  *==========================================================================*/
    198 static void mm_channel_dispatch_super_buf(mm_camera_cmdcb_t *cmd_cb,
    199                                           void* user_data)
    200 {
    201     mm_channel_t *my_obj = (mm_channel_t *)user_data;
    202     mm_channel_t *m_obj = my_obj;
    203     uint32_t i = 0;
    204 
    205     if (NULL == my_obj) {
    206         return;
    207     }
    208 
    209     if (m_obj->master_ch_obj != NULL) {
    210         //get master object
    211         m_obj = m_obj->master_ch_obj;
    212     }
    213 
    214     pthread_mutex_lock(&m_obj->frame_sync.sync_lock);
    215     if(m_obj->frame_sync.is_active) {
    216         //Frame sync enabled on master
    217         switch(cmd_cb->cmd_type) {
    218             case MM_CAMERA_CMD_TYPE_SUPER_BUF_DATA_CB: {
    219                 mm_camera_muxer_channel_frame_sync(&cmd_cb->u.superbuf, my_obj);
    220             }
    221             break;
    222             case MM_CAMERA_CMD_TYPE_REQ_DATA_CB : {
    223                 mm_camera_muxer_channel_req_data_cb(&cmd_cb->u.req_buf, my_obj);
    224             }
    225             break;
    226             case MM_CAMERA_CMD_TYPE_FLUSH_QUEUE : {
    227                 mm_camera_muxer_channel_frame_sync_flush(my_obj);
    228                 cam_sem_post(&my_obj->cb_thread.sync_sem);
    229             }
    230             break;
    231             default : {
    232                 LOGW("Invalid cmd type %d", cmd_cb->cmd_type);
    233             }
    234             break;
    235         }
    236     } else if (my_obj->bundle.super_buf_notify_cb && my_obj->bundle.is_cb_active) {
    237         //Super buffer channel callback is active
    238         my_obj->bundle.super_buf_notify_cb(&cmd_cb->u.superbuf, my_obj->bundle.user_data);
    239     } else {
    240         //Nothing enabled. Return this buffer
    241         mm_camera_super_buf_t *buffer = &cmd_cb->u.superbuf;
    242         for (i=0; i < buffer->num_bufs; i++) {
    243             if (buffer->bufs[i] != NULL) {
    244                 mm_channel_qbuf(my_obj, buffer->bufs[i]);
    245             }
    246         }
    247     }
    248     pthread_mutex_unlock(&m_obj->frame_sync.sync_lock);
    249 }
    250 
    251 /*===========================================================================
    252  * FUNCTION   : mm_channel_send_frame_sync_req_buf
    253  *
    254  * DESCRIPTION: Request buffer from super buffer sync queue
    255  *
    256  * PARAMETERS :
    257  *   @my_obj  : channel object
    258  *
    259  * RETURN     : int32_t type of status
    260  *              0  -- success
    261  *              -1 -- failure
    262  *==========================================================================*/
    263 int32_t mm_channel_send_frame_sync_req_buf(mm_channel_t* my_obj)
    264 {
    265     int32_t rc = 0;
    266     mm_channel_t *m_obj = my_obj;
    267     mm_camera_req_buf_type_t type = my_obj->req_type;
    268 
    269     if (m_obj->master_ch_obj != NULL) {
    270         m_obj = m_obj->master_ch_obj;
    271     }
    272 
    273     if (!m_obj->frame_sync.is_active) {
    274         return rc;
    275     }
    276 
    277     if (MM_CAMERA_REQ_FRAME_SYNC_BUF != type) {
    278         m_obj = my_obj;
    279     } else if (m_obj != my_obj) {
    280         /*Issue sync request only using master channel*/
    281         return rc;
    282     }
    283 
    284     mm_camera_cmdcb_t* cb_node = NULL;
    285 
    286     /* send cam_sem_post to wake up cb thread to flush sync queue */
    287     cb_node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
    288     if (NULL != cb_node) {
    289         memset(cb_node, 0, sizeof(mm_camera_cmdcb_t));
    290         cb_node->cmd_type = MM_CAMERA_CMD_TYPE_REQ_DATA_CB;
    291 
    292         cb_node->u.req_buf.type = type;
    293         cb_node->u.req_buf.num_buf_requested = 1;
    294         cb_node->u.req_buf.cam_num = m_obj->cam_obj->my_num;
    295 
    296         /* enqueue to cb thread */
    297         cam_queue_enq(&(m_obj->cb_thread.cmd_queue), cb_node);
    298         /* wake up cb thread */
    299         cam_sem_post(&(m_obj->cb_thread.cmd_sem));
    300     } else {
    301         LOGE("No memory for mm_camera_node_t");
    302         rc = -1;
    303     }
    304     return rc;
    305 }
    306 
    307 /*===========================================================================
    308  * FUNCTION   : mm_channel_process_stream_buf
    309  *
    310  * DESCRIPTION: handle incoming buffer from stream in a bundle. In this function,
    311  *              matching logic will be performed on incoming stream frames.
    312  *              Will depends on the bundle attribute, either storing matched frames
    313  *              in the superbuf queue, or sending matched superbuf frames to upper
    314  *              layer through registered callback.
    315  *
    316  * PARAMETERS :
    317  *   @cmd_cb  : ptr storing matched super buf information
    318  *   @userdata: user data ptr
    319  *
    320  * RETURN     : none
    321  *==========================================================================*/
    322 static void mm_channel_process_stream_buf(mm_camera_cmdcb_t * cmd_cb,
    323                                           void *user_data)
    324 {
    325     mm_camera_super_buf_notify_mode_t notify_mode;
    326     mm_channel_queue_node_t *node = NULL;
    327     mm_channel_t *ch_obj = (mm_channel_t *)user_data;
    328     mm_channel_t *m_obj = ch_obj;
    329     uint32_t i = 0;
    330     /* Set expected frame id to a future frame idx, large enough to wait
    331     * for good_frame_idx_range, and small enough to still capture an image */
    332     uint8_t needStartZSL = FALSE;
    333 
    334     if (NULL == ch_obj) {
    335         return;
    336     }
    337 
    338     //get Master object incase of multiple channel
    339     if (m_obj->master_ch_obj != NULL) {
    340         m_obj = m_obj->master_ch_obj;
    341     }
    342 
    343     if (MM_CAMERA_CMD_TYPE_DATA_CB  == cmd_cb->cmd_type) {
    344         /* comp_and_enqueue */
    345         mm_channel_superbuf_comp_and_enqueue(
    346                         ch_obj,
    347                         &ch_obj->bundle.superbuf_queue,
    348                         &cmd_cb->u.buf);
    349     } else if (MM_CAMERA_CMD_TYPE_REQ_DATA_CB  == cmd_cb->cmd_type) {
    350         /* skip frames if needed */
    351         ch_obj->pending_cnt = cmd_cb->u.req_buf.num_buf_requested;
    352         ch_obj->pending_retro_cnt = cmd_cb->u.req_buf.num_retro_buf_requested;
    353         ch_obj->req_type = cmd_cb->u.req_buf.type;
    354         ch_obj->bWaitForPrepSnapshotDone = 0;
    355         if (cmd_cb->u.req_buf.frame_idx) {
    356             ch_obj->requested_frame_id[ch_obj->frame_req_cnt++] =
    357                     cmd_cb->u.req_buf.frame_idx;
    358             LOGH("FrameID Request from Q = %d", cmd_cb->u.req_buf.frame_idx);
    359         }
    360 
    361         LOGH("pending cnt (%d)", ch_obj->pending_cnt);
    362         if (!ch_obj->pending_cnt || (ch_obj->pending_retro_cnt > ch_obj->pending_cnt)) {
    363           ch_obj->pending_retro_cnt = ch_obj->pending_cnt;
    364         }
    365         if (ch_obj->pending_retro_cnt > 0) {
    366           LOGL("Resetting need Led Flash!!!");
    367           ch_obj->needLEDFlash = 0;
    368         }
    369         ch_obj->stopZslSnapshot = 0;
    370         ch_obj->unLockAEC = 0;
    371 
    372         mm_channel_superbuf_skip(ch_obj, &ch_obj->bundle.superbuf_queue);
    373 
    374     } else if (MM_CAMERA_CMD_TYPE_START_ZSL == cmd_cb->cmd_type) {
    375             ch_obj->manualZSLSnapshot = TRUE;
    376             mm_camera_start_zsl_snapshot(ch_obj->cam_obj);
    377     } else if (MM_CAMERA_CMD_TYPE_STOP_ZSL == cmd_cb->cmd_type) {
    378             ch_obj->manualZSLSnapshot = FALSE;
    379             mm_camera_stop_zsl_snapshot(ch_obj->cam_obj);
    380     } else if (MM_CAMERA_CMD_TYPE_CONFIG_NOTIFY == cmd_cb->cmd_type) {
    381            ch_obj->bundle.superbuf_queue.attr.notify_mode = cmd_cb->u.notify_mode;
    382     } else if (MM_CAMERA_CMD_TYPE_FLUSH_QUEUE  == cmd_cb->cmd_type) {
    383         ch_obj->bundle.superbuf_queue.expected_frame_id = cmd_cb->u.flush_cmd.frame_idx;
    384         mm_channel_superbuf_flush(ch_obj,
    385                 &ch_obj->bundle.superbuf_queue, cmd_cb->u.flush_cmd.stream_type);
    386         if (m_obj->frame_sync.is_active) {
    387             cam_sem_wait(&(m_obj->cb_thread.sync_sem));
    388         }
    389         cam_sem_post(&(ch_obj->cmd_thread.sync_sem));
    390         return;
    391     } else if (MM_CAMERA_CMD_TYPE_GENERAL == cmd_cb->cmd_type) {
    392         LOGH("MM_CAMERA_CMD_TYPE_GENERAL");
    393         switch (cmd_cb->u.gen_cmd.type) {
    394             case MM_CAMERA_GENERIC_CMD_TYPE_AE_BRACKETING:
    395             case MM_CAMERA_GENERIC_CMD_TYPE_AF_BRACKETING: {
    396                 uint32_t start = cmd_cb->u.gen_cmd.payload[0];
    397                 LOGI("MM_CAMERA_GENERIC_CMDTYPE_AF_BRACKETING %u",
    398                       start);
    399                 mm_channel_superbuf_flush(ch_obj,
    400                         &ch_obj->bundle.superbuf_queue, CAM_STREAM_TYPE_DEFAULT);
    401 
    402                 if (start) {
    403                     LOGH("need AE bracketing, start zsl snapshot");
    404                     ch_obj->bracketingState = MM_CHANNEL_BRACKETING_STATE_WAIT_GOOD_FRAME_IDX;
    405                 } else {
    406                     ch_obj->bracketingState = MM_CHANNEL_BRACKETING_STATE_OFF;
    407                 }
    408             }
    409                 break;
    410             case MM_CAMERA_GENERIC_CMD_TYPE_FLASH_BRACKETING: {
    411                 uint32_t start = cmd_cb->u.gen_cmd.payload[0];
    412                 LOGI("MM_CAMERA_GENERIC_CMDTYPE_FLASH_BRACKETING %u",
    413                       start);
    414                 mm_channel_superbuf_flush(ch_obj,
    415                         &ch_obj->bundle.superbuf_queue, CAM_STREAM_TYPE_DEFAULT);
    416 
    417                 if (start) {
    418                     LOGH("need flash bracketing");
    419                     ch_obj->isFlashBracketingEnabled = TRUE;
    420                 } else {
    421                     ch_obj->isFlashBracketingEnabled = FALSE;
    422                 }
    423             }
    424                 break;
    425             case MM_CAMERA_GENERIC_CMD_TYPE_ZOOM_1X: {
    426                 uint32_t start = cmd_cb->u.gen_cmd.payload[0];
    427                 LOGI("MM_CAMERA_GENERIC_CMD_TYPE_ZOOM_1X %u",
    428                       start);
    429                 mm_channel_superbuf_flush(ch_obj,
    430                         &ch_obj->bundle.superbuf_queue, CAM_STREAM_TYPE_DEFAULT);
    431 
    432                 if (start) {
    433                     LOGH("need zoom 1x frame");
    434                     ch_obj->isZoom1xFrameRequested = TRUE;
    435                 } else {
    436                     ch_obj->isZoom1xFrameRequested = FALSE;
    437                 }
    438             }
    439                 break;
    440             case MM_CAMERA_GENERIC_CMD_TYPE_CAPTURE_SETTING: {
    441                 uint32_t start = cmd_cb->u.gen_cmd.payload[0];
    442                 LOGI("MM_CAMERA_GENERIC_CMD_TYPE_CAPTURE_SETTING %u num_batch = %d",
    443                       start, cmd_cb->u.gen_cmd.frame_config.num_batch);
    444 
    445                 if (start) {
    446                     memset(&ch_obj->frameConfig, 0, sizeof(cam_capture_frame_config_t));
    447                     for (i = 0; i < cmd_cb->u.gen_cmd.frame_config.num_batch; i++) {
    448                         if (cmd_cb->u.gen_cmd.frame_config.configs[i].type
    449                                 != CAM_CAPTURE_RESET) {
    450                             ch_obj->frameConfig.configs[
    451                                     ch_obj->frameConfig.num_batch] =
    452                                     cmd_cb->u.gen_cmd.frame_config.configs[i];
    453                             ch_obj->frameConfig.num_batch++;
    454                             LOGH("capture setting frame = %d type = %d",
    455                                     i,ch_obj->frameConfig.configs[
    456                                     ch_obj->frameConfig.num_batch].type);
    457                         }
    458                     }
    459                     LOGD("Capture setting Batch Count %d",
    460                               ch_obj->frameConfig.num_batch);
    461                     ch_obj->isConfigCapture = TRUE;
    462                 } else {
    463                     ch_obj->isConfigCapture = FALSE;
    464                     memset(&ch_obj->frameConfig, 0, sizeof(cam_capture_frame_config_t));
    465                 }
    466                 ch_obj->cur_capture_idx = 0;
    467                 memset(ch_obj->capture_frame_id, 0, sizeof(uint8_t) * MAX_CAPTURE_BATCH_NUM);
    468                 break;
    469             }
    470             default:
    471                 LOGE("Error: Invalid command");
    472                 break;
    473         }
    474     }
    475     notify_mode = ch_obj->bundle.superbuf_queue.attr.notify_mode;
    476 
    477     /*Handle use case which does not need start ZSL even in unified case*/
    478     if ((ch_obj->pending_cnt > 0)
    479             && (ch_obj->isConfigCapture)
    480             && (ch_obj->manualZSLSnapshot == FALSE)
    481             && (ch_obj->startZSlSnapshotCalled == FALSE)) {
    482         needStartZSL = TRUE;
    483         for (i = ch_obj->cur_capture_idx;
    484                 i < ch_obj->frameConfig.num_batch;
    485                 i++) {
    486             cam_capture_type type = ch_obj->frameConfig.configs[i].type;
    487             if (((type == CAM_CAPTURE_FLASH) && (!ch_obj->needLEDFlash))
    488                     || ((type == CAM_CAPTURE_LOW_LIGHT) && (!ch_obj->needLowLightZSL))) {
    489                 /*For flash and low light capture, start ZSL is triggered only if needed*/
    490                 needStartZSL = FALSE;
    491                 break;
    492             }
    493         }
    494     }
    495 
    496     if ((ch_obj->isConfigCapture)
    497             && (needStartZSL)) {
    498         for (i = ch_obj->cur_capture_idx;
    499                 i < ch_obj->frameConfig.num_batch;
    500                 i++) {
    501             ch_obj->capture_frame_id[i] =
    502                     ch_obj->bundle.superbuf_queue.expected_frame_id
    503                     + MM_CAMERA_MAX_FUTURE_FRAME_WAIT;
    504         }
    505 
    506         /* Need to Flush the queue and trigger frame config */
    507         mm_channel_superbuf_flush(ch_obj,
    508                 &ch_obj->bundle.superbuf_queue, CAM_STREAM_TYPE_DEFAULT);
    509         LOGI("TRIGGER Start ZSL");
    510         mm_camera_start_zsl_snapshot(ch_obj->cam_obj);
    511         ch_obj->startZSlSnapshotCalled = TRUE;
    512         ch_obj->burstSnapNum = ch_obj->pending_cnt;
    513         ch_obj->bWaitForPrepSnapshotDone = 0;
    514     } else if ((ch_obj->pending_cnt > 0)
    515         && ((ch_obj->needLEDFlash == TRUE) ||
    516         (MM_CHANNEL_BRACKETING_STATE_OFF != ch_obj->bracketingState))
    517         && (ch_obj->manualZSLSnapshot == FALSE)
    518         && ch_obj->startZSlSnapshotCalled == FALSE) {
    519 
    520         LOGI("TRIGGER Start ZSL for Flash");
    521         mm_camera_start_zsl_snapshot(ch_obj->cam_obj);
    522         ch_obj->startZSlSnapshotCalled = TRUE;
    523         ch_obj->burstSnapNum = ch_obj->pending_cnt;
    524         ch_obj->bWaitForPrepSnapshotDone = 0;
    525     } else if (((ch_obj->pending_cnt == 0) || (ch_obj->stopZslSnapshot == 1))
    526             && (ch_obj->manualZSLSnapshot == FALSE)
    527             && (ch_obj->startZSlSnapshotCalled == TRUE)) {
    528         LOGI("TRIGGER Stop ZSL for cancel picture");
    529         mm_camera_stop_zsl_snapshot(ch_obj->cam_obj);
    530         // Unlock AEC
    531         ch_obj->startZSlSnapshotCalled = FALSE;
    532         ch_obj->needLEDFlash = FALSE;
    533         ch_obj->burstSnapNum = 0;
    534         ch_obj->stopZslSnapshot = 0;
    535         ch_obj->bWaitForPrepSnapshotDone = 0;
    536         ch_obj->unLockAEC = 1;
    537         ch_obj->bracketingState = MM_CHANNEL_BRACKETING_STATE_OFF;
    538         ch_obj->isConfigCapture = FALSE;
    539     }
    540     /* bufdone for overflowed bufs */
    541     mm_channel_superbuf_bufdone_overflow(ch_obj, &ch_obj->bundle.superbuf_queue);
    542 
    543     LOGD("Super Buffer received, pending_cnt=%d queue cnt = %d expected = %d",
    544             ch_obj->pending_cnt, ch_obj->bundle.superbuf_queue.match_cnt,
    545             ch_obj->bundle.superbuf_queue.expected_frame_id);
    546 
    547     /* dispatch frame if pending_cnt>0 or is in continuous streaming mode */
    548     while ((((ch_obj->pending_cnt > 0) ||
    549              (MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS == notify_mode)) &&
    550              (!ch_obj->bWaitForPrepSnapshotDone))
    551              || (m_obj->frame_sync.is_active)) {
    552         uint8_t trigger_cb = 0;
    553 
    554         /* dequeue */
    555         mm_channel_node_info_t info;
    556         memset(&info, 0x0, sizeof(info));
    557 
    558         if (ch_obj->req_type == MM_CAMERA_REQ_FRAME_SYNC_BUF
    559                 && !m_obj->frame_sync.is_active) {
    560             // Lock the Queues
    561             mm_frame_sync_lock_queues();
    562             uint32_t match_frame = mm_frame_sync_find_matched(FALSE);
    563             if (match_frame) {
    564                 uint8_t j = 0;
    565                 for (j = 0; j < MAX_NUM_CAMERA_PER_BUNDLE; j++) {
    566                     if (fs.ch_obj[j]) {
    567                         mm_channel_queue_t *ch_queue =
    568                                 &fs.ch_obj[j]->bundle.superbuf_queue;
    569                         if (ch_queue == NULL) {
    570                             LOGW("Channel queue is NULL");
    571                             break;
    572                         }
    573                         node = mm_channel_superbuf_dequeue_frame_internal(
    574                                 ch_queue, match_frame);
    575                         if (node != NULL) {
    576                             info.ch_obj[info.num_nodes] = fs.ch_obj[j];
    577                             info.node[info.num_nodes] = node;
    578                             info.num_nodes++;
    579                             LOGH("Added ch(%p) to node ,num nodes %d",
    580                                      fs.ch_obj[j], info.num_nodes);
    581                         }
    582                     }
    583                 }
    584                 mm_frame_sync_remove(match_frame);
    585                 LOGI("match frame %d", match_frame);
    586                 if (info.num_nodes != fs.num_cam) {
    587                     LOGI("num node %d != num cam (%d) Debug this",
    588                              info.num_nodes, fs.num_cam);
    589                     uint8_t j = 0;
    590                     // free super buffers from various nodes
    591                     for (j = 0; j < info.num_nodes; j++) {
    592                         if (info.node[j]) {
    593                             mm_channel_node_qbuf(info.ch_obj[j], info.node[j]);
    594                             free(info.node[j]);
    595                         }
    596                     }
    597                     // we should not use it as matched dual camera frames
    598                     info.num_nodes = 0;
    599                 }
    600             }
    601             mm_frame_sync_unlock_queues();
    602         } else {
    603            if (ch_obj->frame_req_cnt == 0) {
    604                node = mm_channel_superbuf_dequeue(&ch_obj->bundle.superbuf_queue, ch_obj);
    605            } else {
    606                uint32_t req_frame = ch_obj->requested_frame_id[ch_obj->cur_req_idx];
    607                node = mm_channel_superbuf_dequeue_frame_internal(
    608                        &ch_obj->bundle.superbuf_queue,
    609                        req_frame);
    610            }
    611            if (node != NULL) {
    612                if (ch_obj->isConfigCapture &&
    613                        ((node->frame_idx <
    614                         ch_obj->capture_frame_id[ch_obj->cur_capture_idx]))
    615                         && (ch_obj->frame_req_cnt == 0)) {
    616                    uint8_t i;
    617                    LOGD("Not expected super buffer. frameID = %d expected = %d",
    618                            node->frame_idx, ch_obj->capture_frame_id[ch_obj->cur_capture_idx]);
    619                    for (i = 0; i < node->num_of_bufs; i++) {
    620                        mm_channel_qbuf(ch_obj, node->super_buf[i].buf);
    621                    }
    622                    free(node);
    623                } else {
    624                    info.num_nodes = 1;
    625                    info.ch_obj[0] = ch_obj;
    626                    info.node[0] = node;
    627                }
    628             }
    629         }
    630         if (info.num_nodes > 0) {
    631             if ((m_obj->frame_sync.is_active)
    632                     && (ch_obj->pending_cnt > 0)) {
    633                 trigger_cb = 1;
    634             }
    635             /* decrease pending_cnt */
    636             if (MM_CAMERA_SUPER_BUF_NOTIFY_BURST == notify_mode
    637                     && ch_obj->pending_cnt > 0) {
    638                 ch_obj->pending_cnt--;
    639                 if (ch_obj->pending_retro_cnt > 0) {
    640                   if (ch_obj->pending_retro_cnt == 1) {
    641                     ch_obj->bWaitForPrepSnapshotDone = 1;
    642                   }
    643                   ch_obj->pending_retro_cnt--;
    644                 }
    645 
    646                 if (ch_obj->frame_req_cnt != 0) {
    647                     ch_obj->cur_req_idx++;
    648                 }
    649                 if (((ch_obj->pending_cnt == 0) ||
    650                       (ch_obj->stopZslSnapshot == 1)) &&
    651                       (ch_obj->manualZSLSnapshot == FALSE) &&
    652                        ch_obj->startZSlSnapshotCalled == TRUE) {
    653                     LOGI("TRIGGER Stop ZSL. All frame received");
    654                     mm_camera_stop_zsl_snapshot(ch_obj->cam_obj);
    655                     ch_obj->startZSlSnapshotCalled = FALSE;
    656                     ch_obj->burstSnapNum = 0;
    657                     ch_obj->stopZslSnapshot = 0;
    658                     ch_obj->unLockAEC = 1;
    659                     ch_obj->needLEDFlash = FALSE;
    660                     ch_obj->bracketingState = MM_CHANNEL_BRACKETING_STATE_OFF;
    661                     ch_obj->isConfigCapture = FALSE;
    662                     ch_obj->cur_req_idx = 0;
    663                     ch_obj->frame_req_cnt = 0;
    664                     memset(ch_obj->requested_frame_id, 0,
    665                             sizeof(uint8_t) * MAX_CAPTURE_BATCH_NUM);
    666                 }
    667 
    668                 if (ch_obj->isConfigCapture) {
    669                     if (ch_obj->frameConfig.configs[ch_obj->cur_capture_idx].num_frames != 0) {
    670                         ch_obj->frameConfig.configs[ch_obj->cur_capture_idx].num_frames--;
    671                     } else {
    672                         LOGW("Invalid frame config batch index %d max batch = %d",
    673                                 ch_obj->cur_capture_idx, ch_obj->frameConfig.num_batch);
    674                     }
    675 
    676                     if (ch_obj->frameConfig.configs[ch_obj->cur_capture_idx].num_frames == 0) {
    677                         //Received all frames for current batch
    678                         ch_obj->cur_capture_idx++;
    679                         ch_obj->bundle.superbuf_queue.expected_frame_id =
    680                                 ch_obj->capture_frame_id[ch_obj->cur_capture_idx];
    681                         ch_obj->bundle.superbuf_queue.good_frame_id =
    682                                 ch_obj->capture_frame_id[ch_obj->cur_capture_idx];
    683                     } else {
    684                         LOGH("Need %d frames more for batch %d",
    685                                 ch_obj->frameConfig.configs[ch_obj->cur_capture_idx].num_frames,
    686                                 ch_obj->cur_capture_idx);
    687                     }
    688                 }
    689             }
    690             /* dispatch superbuf */
    691             mm_channel_send_super_buf(&info);
    692 
    693             if (trigger_cb) {
    694                 trigger_cb = 0;
    695                 mm_channel_send_frame_sync_req_buf(ch_obj);
    696             }
    697         } else {
    698             /* no superbuf avail, break the loop */
    699             break;
    700         }
    701     }
    702 }
    703 
    704 /*===========================================================================
    705  * FUNCTION   : mm_channel_send_super_buf
    706  *
    707  * DESCRIPTION: Send super buffers to HAL
    708  *
    709  * PARAMETERS :
    710  *   @info  : Info of super buffers to be sent in callback
    711  *
    712  * RETURN     : None
    713  *==========================================================================*/
    714 void mm_channel_send_super_buf(mm_channel_node_info_t *info)
    715 {
    716     if (!info || !info->num_nodes){
    717         LOGE("X Error!! Info invalid");
    718         return;
    719     }
    720     mm_channel_queue_node_t *node = NULL;
    721 
    722     LOGH("num nodes %d to send", info->num_nodes);
    723     uint32_t idx = 0;
    724     mm_channel_t *ch_obj = NULL;
    725     for (idx = 0; idx < info->num_nodes; idx++) {
    726         node = info->node[idx];
    727         ch_obj = info->ch_obj[idx];
    728         if ((ch_obj) && (NULL != ch_obj->bundle.super_buf_notify_cb) && node) {
    729             mm_camera_cmdcb_t* cb_node = NULL;
    730             LOGD("Send superbuf to HAL, pending_cnt=%d",
    731                      ch_obj->pending_cnt);
    732             /* send cam_sem_post to wake up cb thread to dispatch super buffer */
    733             cb_node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
    734             if (NULL != cb_node) {
    735                 memset(cb_node, 0, sizeof(mm_camera_cmdcb_t));
    736                 cb_node->cmd_type = MM_CAMERA_CMD_TYPE_SUPER_BUF_DATA_CB;
    737                 cb_node->u.superbuf.num_bufs = node->num_of_bufs;
    738                 uint8_t i = 0;
    739                 for (i = 0; i < node->num_of_bufs; i++) {
    740                     cb_node->u.superbuf.bufs[i] = node->super_buf[i].buf;
    741                 }
    742                 cb_node->u.superbuf.camera_handle = ch_obj->cam_obj->my_hdl;
    743                 cb_node->u.superbuf.ch_id = ch_obj->my_hdl;
    744                 cb_node->u.superbuf.bReadyForPrepareSnapshot =
    745                         ch_obj->bWaitForPrepSnapshotDone;
    746                 if (ch_obj->unLockAEC == 1) {
    747                     cb_node->u.superbuf.bUnlockAEC = 1;
    748                     LOGH("Unlocking AEC");
    749                     ch_obj->unLockAEC = 0;
    750                 }
    751                 /* enqueue to cb thread */
    752                 cam_queue_enq(&(ch_obj->cb_thread.cmd_queue), cb_node);
    753                 /* wake up cb thread */
    754                 cam_sem_post(&(ch_obj->cb_thread.cmd_sem));
    755                 LOGH("Sent super buf for node[%d] ", idx);
    756 
    757             } else {
    758                 LOGE("No memory for mm_camera_node_t");
    759                 /* buf done with the unused super buf */
    760                 uint8_t i = 0;
    761                 for (i = 0; i < node->num_of_bufs; i++) {
    762                     mm_channel_qbuf(ch_obj, node->super_buf[i].buf);
    763                 }
    764             }
    765             free(node);
    766         } else if ((ch_obj != NULL) && (node != NULL)) {
    767             /* buf done with the unused super buf */
    768             uint8_t i;
    769             for (i = 0; i < node->num_of_bufs; i++) {
    770                 mm_channel_qbuf(ch_obj, node->super_buf[i].buf);
    771             }
    772             free(node);
    773         } else {
    774             LOGE("node is NULL, debug this");
    775         }
    776     }
    777 }
    778 
    779 /*===========================================================================
    780  * FUNCTION   : mm_channel_reg_stream_buf_cb
    781  *
    782  * DESCRIPTION: Register callback for stream buffer
    783  *
    784  * PARAMETERS :
    785  *   @my_obj     : Channel object
    786  *   @stream_id  : stream that will be linked
    787  *   @buf_cb     : special callback needs to be registered for stream buffer
    788  *
    789  * RETURN     : int32_t type of status
    790  *              0  -- success
    791  *              -1 --  failure
    792  *==========================================================================*/
    793 int32_t mm_channel_reg_stream_buf_cb (mm_channel_t* my_obj,
    794         uint32_t stream_id, mm_stream_data_cb_t buf_cb)
    795 {
    796     int32_t rc = -1;
    797     mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj,
    798             stream_id);
    799 
    800     if (NULL != s_obj) {
    801         if (s_obj->ch_obj != my_obj) {
    802             /* No op. on linked streams */
    803             return 0;
    804         }
    805         rc = mm_stream_reg_buf_cb(s_obj, buf_cb);
    806     }
    807 
    808     return rc;
    809 
    810 }
    811 
    812 /*===========================================================================
    813  * FUNCTION   : mm_channel_fsm_fn
    814  *
    815  * DESCRIPTION: channel finite state machine entry function. Depends on channel
    816  *              state, incoming event will be handled differently.
    817  *
    818  * PARAMETERS :
    819  *   @my_obj   : ptr to a channel object
    820  *   @evt      : channel event to be processed
    821  *   @in_val   : input event payload. Can be NULL if not needed.
    822  *   @out_val  : output payload, Can be NULL if not needed.
    823  *
    824  * RETURN     : int32_t type of status
    825  *              0  -- success
    826  *              -1 -- failure
    827  *==========================================================================*/
    828 int32_t mm_channel_fsm_fn(mm_channel_t *my_obj,
    829                           mm_channel_evt_type_t evt,
    830                           void * in_val,
    831                           void * out_val)
    832 {
    833     int32_t rc = -1;
    834 
    835     LOGD("E state = %d", my_obj->state);
    836     switch (my_obj->state) {
    837     case MM_CHANNEL_STATE_NOTUSED:
    838         rc = mm_channel_fsm_fn_notused(my_obj, evt, in_val, out_val);
    839         break;
    840     case MM_CHANNEL_STATE_STOPPED:
    841         rc = mm_channel_fsm_fn_stopped(my_obj, evt, in_val, out_val);
    842         break;
    843     case MM_CHANNEL_STATE_ACTIVE:
    844         rc = mm_channel_fsm_fn_active(my_obj, evt, in_val, out_val);
    845         break;
    846     case MM_CHANNEL_STATE_PAUSED:
    847         rc = mm_channel_fsm_fn_paused(my_obj, evt, in_val, out_val);
    848         break;
    849     default:
    850         LOGD("Not a valid state (%d)", my_obj->state);
    851         break;
    852     }
    853 
    854     /* unlock ch_lock */
    855     pthread_mutex_unlock(&my_obj->ch_lock);
    856     LOGD("X rc = %d", rc);
    857     return rc;
    858 }
    859 
    860 /*===========================================================================
    861  * FUNCTION   : mm_channel_fsm_fn_notused
    862  *
    863  * DESCRIPTION: channel finite state machine function to handle event
    864  *              in NOT_USED state.
    865  *
    866  * PARAMETERS :
    867  *   @my_obj   : ptr to a channel object
    868  *   @evt      : channel event to be processed
    869  *   @in_val   : input event payload. Can be NULL if not needed.
    870  *   @out_val  : output payload, Can be NULL if not needed.
    871  *
    872  * RETURN     : int32_t type of status
    873  *              0  -- success
    874  *              -1 -- failure
    875  *==========================================================================*/
    876 int32_t mm_channel_fsm_fn_notused(mm_channel_t *my_obj,
    877                                   mm_channel_evt_type_t evt,
    878                                   void * in_val,
    879                                   void * out_val)
    880 {
    881     int32_t rc = -1;
    882 
    883     switch (evt) {
    884     default:
    885         LOGE("invalid state (%d) for evt (%d), in(%p), out(%p)",
    886                     my_obj->state, evt, in_val, out_val);
    887         break;
    888     }
    889 
    890     return rc;
    891 }
    892 
    893 /*===========================================================================
    894  * FUNCTION   : mm_channel_fsm_fn_stopped
    895  *
    896  * DESCRIPTION: channel finite state machine function to handle event
    897  *              in STOPPED state.
    898  *
    899  * PARAMETERS :
    900  *   @my_obj   : ptr to a channel object
    901  *   @evt      : channel event to be processed
    902  *   @in_val   : input event payload. Can be NULL if not needed.
    903  *   @out_val  : output payload, Can be NULL if not needed.
    904  *
    905  * RETURN     : int32_t type of status
    906  *              0  -- success
    907  *              -1 -- failure
    908  *==========================================================================*/
    909 int32_t mm_channel_fsm_fn_stopped(mm_channel_t *my_obj,
    910                                   mm_channel_evt_type_t evt,
    911                                   void * in_val,
    912                                   void * out_val)
    913 {
    914     int32_t rc = 0;
    915     LOGD("E evt = %d", evt);
    916     switch (evt) {
    917     case MM_CHANNEL_EVT_ADD_STREAM:
    918         {
    919             uint32_t s_hdl = 0;
    920             s_hdl = mm_channel_add_stream(my_obj);
    921             *((uint32_t*)out_val) = s_hdl;
    922             rc = 0;
    923         }
    924         break;
    925     case MM_CHANNEL_EVT_LINK_STREAM:
    926         {
    927             mm_camera_stream_link_t *stream_link = NULL;
    928             uint32_t s_hdl = 0;
    929             stream_link = (mm_camera_stream_link_t *) in_val;
    930             s_hdl = mm_channel_link_stream(my_obj, stream_link);
    931             *((uint32_t*)out_val) = s_hdl;
    932             rc = 0;
    933         }
    934         break;
    935     case MM_CHANNEL_EVT_REG_FRAME_SYNC:
    936         {
    937             mm_evt_paylod_reg_frame_sync *frame_sync = NULL;
    938             uint32_t s_hdl = 0;
    939             frame_sync = (mm_evt_paylod_reg_frame_sync *) in_val;
    940             s_hdl = mm_channel_reg_frame_sync(my_obj, frame_sync);
    941             *((uint32_t*)out_val) = s_hdl;
    942             rc = 0;
    943         }
    944         break;
    945     case MM_CHANNEL_EVT_TRIGGER_FRAME_SYNC:
    946         {
    947             rc = mm_channel_trigger_frame_sync(my_obj,
    948                     (mm_evt_paylod_trigger_frame_sync *)in_val);
    949         }
    950         break;
    951     case MM_CHANNEL_EVT_DEL_STREAM:
    952         {
    953             uint32_t s_id = *((uint32_t *)in_val);
    954             rc = mm_channel_del_stream(my_obj, s_id);
    955         }
    956         break;
    957     case MM_CHANNEL_EVT_START:
    958         {
    959             rc = mm_channel_start(my_obj);
    960             /* first stream started in stopped state
    961              * move to active state */
    962             if (0 == rc) {
    963                 my_obj->state = MM_CHANNEL_STATE_ACTIVE;
    964             }
    965         }
    966         break;
    967     case MM_CHANNEL_EVT_CONFIG_STREAM:
    968         {
    969             mm_evt_paylod_config_stream_t *payload =
    970                 (mm_evt_paylod_config_stream_t *)in_val;
    971             rc = mm_channel_config_stream(my_obj,
    972                                           payload->stream_id,
    973                                           payload->config);
    974         }
    975         break;
    976     case MM_CHANNEL_EVT_GET_BUNDLE_INFO:
    977         {
    978             cam_bundle_config_t *payload =
    979                 (cam_bundle_config_t *)in_val;
    980             rc = mm_channel_get_bundle_info(my_obj, payload);
    981         }
    982         break;
    983     case MM_CHANNEL_EVT_DELETE:
    984         {
    985             mm_channel_release(my_obj);
    986             rc = 0;
    987         }
    988         break;
    989     case MM_CHANNEL_EVT_SET_STREAM_PARM:
    990         {
    991             mm_evt_paylod_set_get_stream_parms_t *payload =
    992                 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
    993             rc = mm_channel_set_stream_parm(my_obj, payload);
    994         }
    995         break;
    996     case MM_CHANNEL_EVT_GET_STREAM_QUEUED_BUF_COUNT:
    997         {
    998             uint32_t stream_id = *((uint32_t *)in_val);
    999             rc = mm_channel_get_queued_buf_count(my_obj, stream_id);
   1000         }
   1001         break;
   1002     case MM_CHANNEL_EVT_GET_STREAM_PARM:
   1003         {
   1004             mm_evt_paylod_set_get_stream_parms_t *payload =
   1005                 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
   1006             rc = mm_channel_get_stream_parm(my_obj, payload);
   1007         }
   1008         break;
   1009     case MM_CHANNEL_EVT_DO_ACTION:
   1010         {
   1011             mm_evt_paylod_do_stream_action_t *payload =
   1012                 (mm_evt_paylod_do_stream_action_t *)in_val;
   1013             rc = mm_channel_do_stream_action(my_obj, payload);
   1014         }
   1015         break;
   1016     case MM_CHANNEL_EVT_MAP_STREAM_BUF:
   1017         {
   1018             cam_buf_map_type *payload =
   1019                 (cam_buf_map_type *)in_val;
   1020             rc = mm_channel_map_stream_buf(my_obj, payload);
   1021         }
   1022         break;
   1023     case MM_CHANNEL_EVT_MAP_STREAM_BUFS:
   1024         {
   1025             cam_buf_map_type_list *payload =
   1026                 (cam_buf_map_type_list *)in_val;
   1027             rc = mm_channel_map_stream_bufs(my_obj, payload);
   1028         }
   1029         break;
   1030     case MM_CHANNEL_EVT_UNMAP_STREAM_BUF:
   1031         {
   1032             cam_buf_unmap_type *payload =
   1033                 (cam_buf_unmap_type *)in_val;
   1034             rc = mm_channel_unmap_stream_buf(my_obj, payload);
   1035         }
   1036         break;
   1037     case MM_CHANNEL_EVT_REG_STREAM_BUF_CB:
   1038         {
   1039             mm_evt_paylod_reg_stream_buf_cb *payload =
   1040                 (mm_evt_paylod_reg_stream_buf_cb *)in_val;
   1041             rc = mm_channel_reg_stream_buf_cb (my_obj,
   1042                     payload->stream_id, payload->buf_cb);
   1043         }
   1044         break;
   1045     default:
   1046         LOGW("invalid state (%d) for evt (%d)",
   1047                     my_obj->state, evt);
   1048         break;
   1049     }
   1050     LOGD("E rc = %d", rc);
   1051     return rc;
   1052 }
   1053 
   1054 /*===========================================================================
   1055  * FUNCTION   : mm_channel_fsm_fn_active
   1056  *
   1057  * DESCRIPTION: channel finite state machine function to handle event
   1058  *              in ACTIVE state.
   1059  *
   1060  * PARAMETERS :
   1061  *   @my_obj   : ptr to a channel object
   1062  *   @evt      : channel event to be processed
   1063  *   @in_val   : input event payload. Can be NULL if not needed.
   1064  *   @out_val  : output payload, Can be NULL if not needed.
   1065  *
   1066  * RETURN     : int32_t type of status
   1067  *              0  -- success
   1068  *              -1 -- failure
   1069  *==========================================================================*/
   1070 int32_t mm_channel_fsm_fn_active(mm_channel_t *my_obj,
   1071                           mm_channel_evt_type_t evt,
   1072                           void * in_val,
   1073                           void * out_val)
   1074 {
   1075     int32_t rc = 0;
   1076 
   1077     LOGD("E evt = %d", evt);
   1078     switch (evt) {
   1079     case MM_CHANNEL_EVT_STOP:
   1080         {
   1081             bool stop_immediately = in_val ? *(bool*)in_val : FALSE;
   1082             rc = mm_channel_stop(my_obj, stop_immediately);
   1083             my_obj->state = MM_CHANNEL_STATE_STOPPED;
   1084         }
   1085         break;
   1086     case MM_CHANNEL_EVT_REQUEST_SUPER_BUF:
   1087         {
   1088             mm_camera_req_buf_t *payload =
   1089                     (mm_camera_req_buf_t *)in_val;
   1090             rc = mm_channel_request_super_buf(my_obj, payload);
   1091         }
   1092         break;
   1093     case MM_CHANNEL_EVT_CANCEL_REQUEST_SUPER_BUF:
   1094         {
   1095             rc = mm_channel_cancel_super_buf_request(my_obj);
   1096         }
   1097         break;
   1098     case MM_CHANNEL_EVT_FLUSH_SUPER_BUF_QUEUE:
   1099         {
   1100             uint32_t frame_idx = *((uint32_t *)in_val);
   1101             rc = mm_channel_flush_super_buf_queue(my_obj, frame_idx, CAM_STREAM_TYPE_DEFAULT);
   1102         }
   1103         break;
   1104     case MM_CHANNEL_EVT_START_ZSL_SNAPSHOT:
   1105         {
   1106             rc = mm_channel_start_zsl_snapshot(my_obj);
   1107         }
   1108         break;
   1109     case MM_CHANNEL_EVT_STOP_ZSL_SNAPSHOT:
   1110         {
   1111             rc = mm_channel_stop_zsl_snapshot(my_obj);
   1112         }
   1113         break;
   1114     case MM_CHANNEL_EVT_CONFIG_NOTIFY_MODE:
   1115         {
   1116             mm_camera_super_buf_notify_mode_t notify_mode =
   1117                 *((mm_camera_super_buf_notify_mode_t *)in_val);
   1118             rc = mm_channel_config_notify_mode(my_obj, notify_mode);
   1119         }
   1120         break;
   1121     case MM_CHANNEL_EVT_SET_STREAM_PARM:
   1122         {
   1123             mm_evt_paylod_set_get_stream_parms_t *payload =
   1124                 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
   1125             rc = mm_channel_set_stream_parm(my_obj, payload);
   1126         }
   1127         break;
   1128     case MM_CHANNEL_EVT_GET_STREAM_QUEUED_BUF_COUNT:
   1129         {
   1130             uint32_t stream_id = *((uint32_t *)in_val);
   1131             rc = mm_channel_get_queued_buf_count(my_obj, stream_id);
   1132         }
   1133         break;
   1134     case MM_CHANNEL_EVT_GET_STREAM_PARM:
   1135         {
   1136             mm_evt_paylod_set_get_stream_parms_t *payload =
   1137                 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
   1138             rc = mm_channel_get_stream_parm(my_obj, payload);
   1139         }
   1140         break;
   1141     case MM_CHANNEL_EVT_DO_ACTION:
   1142         {
   1143             mm_evt_paylod_do_stream_action_t *payload =
   1144                 (mm_evt_paylod_do_stream_action_t *)in_val;
   1145             rc = mm_channel_do_stream_action(my_obj, payload);
   1146         }
   1147         break;
   1148     case MM_CHANNEL_EVT_MAP_STREAM_BUF:
   1149         {
   1150             cam_buf_map_type *payload =
   1151                 (cam_buf_map_type *)in_val;
   1152             if (payload != NULL) {
   1153                 uint8_t type = payload->type;
   1154                 if ((type == CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF) ||
   1155                         (type == CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF)) {
   1156                     rc = mm_channel_map_stream_buf(my_obj, payload);
   1157                 }
   1158             } else {
   1159                 LOGE("cannot map regualr stream buf in active state");
   1160             }
   1161         }
   1162         break;
   1163     case MM_CHANNEL_EVT_MAP_STREAM_BUFS:
   1164         {
   1165             cam_buf_map_type_list *payload =
   1166                 (cam_buf_map_type_list *)in_val;
   1167             if ((payload != NULL) && (payload->length > 0)) {
   1168                 uint8_t type = payload->buf_maps[0].type;
   1169                 if ((type == CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF) ||
   1170                         (type == CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF)) {
   1171                     rc = mm_channel_map_stream_bufs(my_obj, payload);
   1172                 }
   1173             } else {
   1174                 LOGE("cannot map regualr stream buf in active state");
   1175             }
   1176         }
   1177         break;
   1178     case MM_CHANNEL_EVT_UNMAP_STREAM_BUF:
   1179         {
   1180             cam_buf_unmap_type *payload =
   1181                 (cam_buf_unmap_type *)in_val;
   1182             if (payload != NULL) {
   1183                 uint8_t type = payload->type;
   1184                 if ((type == CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF) ||
   1185                         (type == CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF)) {
   1186                     rc = mm_channel_unmap_stream_buf(my_obj, payload);
   1187                 }
   1188             } else {
   1189                 LOGE("cannot unmap regualr stream buf in active state");
   1190             }
   1191         }
   1192         break;
   1193     case MM_CHANNEL_EVT_AF_BRACKETING:
   1194         {
   1195             LOGH("MM_CHANNEL_EVT_AF_BRACKETING");
   1196             uint32_t start_flag = *((uint32_t *)in_val);
   1197             mm_camera_generic_cmd_t gen_cmd;
   1198             gen_cmd.type = MM_CAMERA_GENERIC_CMD_TYPE_AF_BRACKETING;
   1199             gen_cmd.payload[0] = start_flag;
   1200             rc = mm_channel_proc_general_cmd(my_obj, &gen_cmd);
   1201         }
   1202         break;
   1203     case MM_CHANNEL_EVT_AE_BRACKETING:
   1204         {
   1205             LOGH("MM_CHANNEL_EVT_AE_BRACKETING");
   1206             uint32_t start_flag = *((uint32_t *)in_val);
   1207             mm_camera_generic_cmd_t gen_cmd;
   1208             gen_cmd.type = MM_CAMERA_GENERIC_CMD_TYPE_AE_BRACKETING;
   1209             gen_cmd.payload[0] = start_flag;
   1210             rc = mm_channel_proc_general_cmd(my_obj, &gen_cmd);
   1211         }
   1212         break;
   1213     case MM_CHANNEL_EVT_FLASH_BRACKETING:
   1214         {
   1215             LOGH("MM_CHANNEL_EVT_FLASH_BRACKETING");
   1216             uint32_t start_flag = *((uint32_t *)in_val);
   1217             mm_camera_generic_cmd_t gen_cmd;
   1218             gen_cmd.type = MM_CAMERA_GENERIC_CMD_TYPE_FLASH_BRACKETING;
   1219             gen_cmd.payload[0] = start_flag;
   1220             rc = mm_channel_proc_general_cmd(my_obj, &gen_cmd);
   1221         }
   1222         break;
   1223     case MM_CHANNEL_EVT_ZOOM_1X:
   1224         {
   1225             LOGH("MM_CHANNEL_EVT_ZOOM_1X");
   1226             uint32_t start_flag = *((uint32_t *)in_val);
   1227             mm_camera_generic_cmd_t gen_cmd;
   1228             gen_cmd.type = MM_CAMERA_GENERIC_CMD_TYPE_ZOOM_1X;
   1229             gen_cmd.payload[0] = start_flag;
   1230             rc = mm_channel_proc_general_cmd(my_obj, &gen_cmd);
   1231         }
   1232         break;
   1233     case MM_CAMERA_EVT_CAPTURE_SETTING:
   1234         {
   1235             mm_camera_generic_cmd_t gen_cmd;
   1236             cam_capture_frame_config_t *input;
   1237             gen_cmd.type = MM_CAMERA_GENERIC_CMD_TYPE_CAPTURE_SETTING;
   1238             LOGH("MM_CAMERA_EVT_CAPTURE_SETTING");
   1239             if (in_val == NULL) {
   1240                 gen_cmd.payload[0] = 0;
   1241                 memset(&gen_cmd.frame_config, 0, sizeof(cam_capture_frame_config_t));
   1242             } else {
   1243                 gen_cmd.payload[0] = 1;
   1244                 input = (cam_capture_frame_config_t *)in_val;
   1245                 gen_cmd.frame_config = *input;
   1246             }
   1247             rc = mm_channel_proc_general_cmd(my_obj, &gen_cmd);
   1248         }
   1249         break;
   1250     case MM_CHANNEL_EVT_REG_STREAM_BUF_CB:
   1251         {
   1252             mm_evt_paylod_reg_stream_buf_cb *payload =
   1253                 (mm_evt_paylod_reg_stream_buf_cb *)in_val;
   1254             rc = mm_channel_reg_stream_buf_cb (my_obj,
   1255                     payload->stream_id, payload->buf_cb);
   1256         }
   1257         break;
   1258     case MM_CHANNEL_EVT_TRIGGER_FRAME_SYNC:
   1259         {
   1260             rc = mm_channel_trigger_frame_sync(my_obj,
   1261                     (mm_evt_paylod_trigger_frame_sync *)in_val);
   1262         }
   1263         break;
   1264 
   1265     case MM_CHANNEL_EVT_START_SENSOR_STREAMING:
   1266         {
   1267             rc = mm_channel_start_sensor_streaming(my_obj);
   1268         }
   1269         break;
   1270 
   1271      default:
   1272         LOGE("invalid state (%d) for evt (%d), in(%p), out(%p)",
   1273                     my_obj->state, evt, in_val, out_val);
   1274         break;
   1275     }
   1276     LOGD("X rc = %d", rc);
   1277     return rc;
   1278 }
   1279 
   1280 /*===========================================================================
   1281  * FUNCTION   : mm_channel_fsm_fn_paused
   1282  *
   1283  * DESCRIPTION: channel finite state machine function to handle event
   1284  *              in PAUSED state.
   1285  *
   1286  * PARAMETERS :
   1287  *   @my_obj   : ptr to a channel object
   1288  *   @evt      : channel event to be processed
   1289  *   @in_val   : input event payload. Can be NULL if not needed.
   1290  *   @out_val  : output payload, Can be NULL if not needed.
   1291  *
   1292  * RETURN     : int32_t type of status
   1293  *              0  -- success
   1294  *              -1 -- failure
   1295  *==========================================================================*/
   1296 int32_t mm_channel_fsm_fn_paused(mm_channel_t *my_obj,
   1297                           mm_channel_evt_type_t evt,
   1298                           void * in_val,
   1299                           void * out_val)
   1300 {
   1301     int32_t rc = 0;
   1302 
   1303     /* currently we are not supporting pause/resume channel */
   1304     LOGE("invalid state (%d) for evt (%d), in(%p), out(%p)",
   1305                 my_obj->state, evt, in_val, out_val);
   1306 
   1307     return rc;
   1308 }
   1309 
   1310 /*===========================================================================
   1311  * FUNCTION   : mm_channel_init
   1312  *
   1313  * DESCRIPTION: initialize a channel
   1314  *
   1315  * PARAMETERS :
   1316  *   @my_obj       : channel object be to initialized
   1317  *   @attr         : bundle attribute of the channel if needed
   1318  *   @channel_cb   : callback function for bundle data notify
   1319  *   @userdata     : user data ptr
   1320  *
   1321  * RETURN     : int32_t type of status
   1322  *              0  -- success
   1323  *              -1 -- failure
   1324  * NOTE       : if no bundle data notify is needed, meaning each stream in the
   1325  *              channel will have its own stream data notify callback, then
   1326  *              attr, channel_cb, and userdata can be NULL. In this case,
   1327  *              no matching logic will be performed in channel for the bundling.
   1328  *==========================================================================*/
   1329 int32_t mm_channel_init(mm_channel_t *my_obj,
   1330                         mm_camera_channel_attr_t *attr,
   1331                         mm_camera_buf_notify_t channel_cb,
   1332                         void *userdata)
   1333 {
   1334     int32_t rc = 0;
   1335 
   1336     my_obj->bundle.super_buf_notify_cb = channel_cb;
   1337     my_obj->bundle.user_data = userdata;
   1338     if (NULL != attr) {
   1339         my_obj->bundle.superbuf_queue.attr = *attr;
   1340     }
   1341 
   1342     my_obj->num_s_cnt = 0;
   1343     memset(&my_obj->frame_sync, 0, sizeof(my_obj->frame_sync));
   1344     pthread_mutex_init(&my_obj->frame_sync.sync_lock, NULL);
   1345     mm_muxer_frame_sync_queue_init(&my_obj->frame_sync.superbuf_queue);
   1346     my_obj->bundle.is_cb_active = 1;
   1347 
   1348     LOGD("Launch data poll thread in channel open");
   1349     snprintf(my_obj->poll_thread[0].threadName, THREAD_NAME_SIZE, "CAM_dataPoll");
   1350     mm_camera_poll_thread_launch(&my_obj->poll_thread[0],
   1351                                  MM_CAMERA_POLL_TYPE_DATA);
   1352 
   1353     /* change state to stopped state */
   1354     my_obj->state = MM_CHANNEL_STATE_STOPPED;
   1355     return rc;
   1356 }
   1357 
   1358 /*===========================================================================
   1359  * FUNCTION   : mm_channel_release
   1360  *
   1361  * DESCRIPTION: release a channel resource. Channel state will move to UNUSED
   1362  *              state after this call.
   1363  *
   1364  * PARAMETERS :
   1365  *   @my_obj       : channel object
   1366  *
   1367  * RETURN     : none
   1368  *==========================================================================*/
   1369 void mm_channel_release(mm_channel_t *my_obj)
   1370 {
   1371     /* stop data poll thread */
   1372     mm_camera_poll_thread_release(&my_obj->poll_thread[0]);
   1373 
   1374     mm_muxer_frame_sync_queue_deinit(&my_obj->frame_sync.superbuf_queue);
   1375     pthread_mutex_destroy(&my_obj->frame_sync.sync_lock);
   1376 
   1377     /* memset bundle info */
   1378     memset(&my_obj->bundle, 0, sizeof(mm_channel_bundle_t));
   1379 
   1380     /* change state to notused state */
   1381     my_obj->state = MM_CHANNEL_STATE_NOTUSED;
   1382 }
   1383 
   1384 /*===========================================================================
   1385  * FUNCTION   : mm_channel_link_stream
   1386  *
   1387  * DESCRIPTION: link a stream from external channel into this channel
   1388  *
   1389  * PARAMETERS :
   1390  *   @my_obj  : channel object
   1391  *   @stream_link  : channel and stream to be linked
   1392  *
   1393  * RETURN     : uint32_t type of stream handle
   1394  *              0  -- invalid stream handle, meaning the op failed
   1395  *              >0 -- successfully added a stream with a valid handle
   1396  *==========================================================================*/
   1397 uint32_t mm_channel_link_stream(mm_channel_t *my_obj,
   1398         mm_camera_stream_link_t *stream_link)
   1399 {
   1400     uint8_t idx = 0;
   1401     uint32_t s_hdl = 0;
   1402     mm_stream_t *stream_obj = NULL;
   1403     mm_stream_t *stream = NULL;
   1404 
   1405     if (NULL == stream_link) {
   1406         LOGE("Invalid stream link");
   1407         return 0;
   1408     }
   1409 
   1410     stream = mm_channel_util_get_stream_by_handler(stream_link->ch,
   1411             stream_link->stream_id);
   1412     if (NULL == stream) {
   1413         return 0;
   1414     }
   1415 
   1416     /* check available stream */
   1417     for (idx = 0; idx < MAX_STREAM_NUM_IN_BUNDLE; idx++) {
   1418         if (MM_STREAM_STATE_NOTUSED == my_obj->streams[idx].state) {
   1419             stream_obj = &my_obj->streams[idx];
   1420             break;
   1421         }
   1422     }
   1423     if (NULL == stream_obj) {
   1424         LOGE("streams reach max, no more stream allowed to add");
   1425         return s_hdl;
   1426     }
   1427 
   1428     /* initialize stream object */
   1429     *stream_obj = *stream;
   1430     stream_obj->linked_stream = stream;
   1431     s_hdl = stream->my_hdl;
   1432 
   1433     LOGD("stream handle = %d", s_hdl);
   1434     return s_hdl;
   1435 }
   1436 
   1437 /*===========================================================================
   1438  * FUNCTION   : mm_channel_reg_frame_sync
   1439  *
   1440  * DESCRIPTION: register/configure frame sync for stream
   1441  *
   1442  * PARAMETERS :
   1443  *   @my_obj    : camera object
   1444  *   @ch_id     : channel handle
   1445  *   @stream_id : stream that will be linked
   1446  *   @sync_attr    : attibutes for sync queue
   1447  *
   1448  * RETURN    : int32_t type of status
   1449  *             0  -- success
   1450  *             1 --  failure
   1451  *==========================================================================*/
   1452 uint32_t mm_channel_reg_frame_sync(mm_channel_t *my_obj,
   1453         mm_evt_paylod_reg_frame_sync *sync)
   1454 {
   1455     uint32_t rc = 0;
   1456     mm_stream_t * stream_obj = NULL;
   1457 
   1458     if (NULL == sync || sync->a_ch_obj == NULL) {
   1459         LOGE("Invalid arguments");
   1460         return -1;
   1461     }
   1462 
   1463     if (sync->stream_id != 0) {
   1464         //Frame sync reg for stream
   1465         stream_obj = mm_channel_util_get_stream_by_handler(
   1466                 my_obj, sync->stream_id);
   1467         if (stream_obj == NULL) {
   1468             LOGE("Invalid Stream ID %d", sync->stream_id);
   1469             return -1;
   1470         }
   1471         sync->a_str_obj = mm_channel_util_get_stream_by_handler(
   1472                 sync->a_ch_obj, sync->sync_attr->a_stream_id);
   1473         return mm_stream_fsm_fn(stream_obj,
   1474                 MM_STREAM_EVT_REG_FRAME_SYNC,
   1475                 sync,
   1476                 NULL);
   1477     }
   1478 
   1479     //Frame sync reg for channel
   1480     mm_frame_sync_t *frame_sync = &my_obj->frame_sync;
   1481     pthread_mutex_lock(&frame_sync->sync_lock);
   1482     mm_frame_sync_queue_t *queue = NULL;
   1483     if (sync->sync_attr->buf_cb == NULL) {
   1484         frame_sync->super_buf_notify_cb =
   1485                 my_obj->bundle.super_buf_notify_cb;
   1486     } else {
   1487         frame_sync->super_buf_notify_cb = sync->sync_attr->buf_cb;
   1488     }
   1489     if (sync->sync_attr->userdata == NULL) {
   1490         frame_sync->user_data =
   1491                 my_obj->bundle.user_data;
   1492     } else {
   1493         frame_sync->user_data = sync->sync_attr->userdata;
   1494     }
   1495     frame_sync->is_active = sync->sync_attr->is_active;
   1496     queue = &frame_sync->superbuf_queue;
   1497     queue->attr = sync->sync_attr->attr;
   1498     queue->num_objs = 0;
   1499     memset(&queue->bundled_objs, 0, sizeof(queue->bundled_objs));
   1500     queue->bundled_objs[queue->num_objs] = my_obj->my_hdl;
   1501     queue->num_objs++;
   1502     queue->bundled_objs[queue->num_objs] = sync->a_ch_obj->my_hdl;
   1503     queue->num_objs++;
   1504 
   1505     my_obj->aux_ch_obj[my_obj->num_s_cnt++] = sync->a_ch_obj;
   1506     sync->a_ch_obj->master_ch_obj = my_obj;
   1507     pthread_mutex_unlock(&frame_sync->sync_lock);
   1508     LOGD("stream handle = %d", rc);
   1509     return rc;
   1510 }
   1511 
   1512 /*===========================================================================
   1513  * FUNCTION   : mm_channel_trigger_frame_sync
   1514  *
   1515  * DESCRIPTION: start/stop frame sync under this channel
   1516  *
   1517  * PARAMETERS :
   1518  *   @my_obj    : camera object
   1519  *   @ch_id     : channel handle
   1520  *   @stream_id : stream that will be linked
   1521  *
   1522  * RETURN    : int32_t type of status
   1523  *             0  -- success
   1524  *             1 --  failure
   1525  *==========================================================================*/
   1526 int32_t mm_channel_trigger_frame_sync(mm_channel_t *my_obj,
   1527         mm_evt_paylod_trigger_frame_sync *payload)
   1528 {
   1529     int32_t rc = 0;
   1530     mm_stream_t * stream_obj = NULL;
   1531     mm_channel_t *m_obj = my_obj;
   1532 
   1533     if (m_obj->master_ch_obj != NULL) {
   1534         m_obj = m_obj->master_ch_obj;
   1535     }
   1536 
   1537     if (payload->stream_id != 0) {
   1538         stream_obj = mm_channel_util_get_stream_by_handler(
   1539                 my_obj, payload->stream_id);
   1540         if (stream_obj == NULL) {
   1541             LOGE("Invalid Stream ID %d", payload->stream_id);
   1542             return -1;
   1543         }
   1544         return mm_stream_fsm_fn(stream_obj,
   1545                 MM_STREAM_EVT_TRIGGER_FRAME_SYNC,
   1546                 &payload->type,
   1547                 NULL);
   1548     }
   1549 
   1550     if (payload->type == MM_CAMERA_CB_REQ_TYPE_FRAME_SYNC) {
   1551         mm_frame_sync_t *frame_sync = &m_obj->frame_sync;
   1552         pthread_mutex_lock(&frame_sync->sync_lock);
   1553         frame_sync->is_active = 1;
   1554         pthread_mutex_unlock(&frame_sync->sync_lock);
   1555     } else {
   1556         LOGE("Not supported for Channel");
   1557         rc = -1;
   1558     }
   1559     return rc;
   1560 }
   1561 
   1562 /*===========================================================================
   1563  * FUNCTION   : mm_channel_add_stream
   1564  *
   1565  * DESCRIPTION: add a stream into the channel
   1566  *
   1567  * PARAMETERS :
   1568  *   @my_obj       : channel object
   1569  *
   1570  * RETURN     : uint32_t type of stream handle
   1571  *              0  -- invalid stream handle, meaning the op failed
   1572  *              >0 -- successfully added a stream with a valid handle
   1573  *==========================================================================*/
   1574 uint32_t mm_channel_add_stream(mm_channel_t *my_obj)
   1575 {
   1576     int32_t rc = 0;
   1577     uint8_t idx = 0;
   1578     uint32_t s_hdl = 0;
   1579     mm_stream_t *stream_obj = NULL;
   1580 
   1581     LOGD("E");
   1582     /* check available stream */
   1583     for (idx = 0; idx < MAX_STREAM_NUM_IN_BUNDLE; idx++) {
   1584         if (MM_STREAM_STATE_NOTUSED == my_obj->streams[idx].state) {
   1585             stream_obj = &my_obj->streams[idx];
   1586             break;
   1587         }
   1588     }
   1589     if (NULL == stream_obj) {
   1590         LOGE("streams reach max, no more stream allowed to add");
   1591         return s_hdl;
   1592     }
   1593 
   1594     /* initialize stream object */
   1595     memset(stream_obj, 0, sizeof(mm_stream_t));
   1596     stream_obj->fd = -1;
   1597     stream_obj->my_hdl = mm_camera_util_generate_handler_by_num (
   1598             my_obj->cam_obj->my_num, idx);
   1599     stream_obj->ch_obj = my_obj;
   1600     stream_obj->state = MM_STREAM_STATE_INITED;
   1601 
   1602     /* acquire stream */
   1603     rc = mm_stream_fsm_fn(stream_obj, MM_STREAM_EVT_ACQUIRE, NULL, NULL);
   1604     if (0 == rc) {
   1605         s_hdl = stream_obj->my_hdl;
   1606     } else {
   1607         /* error during acquire, de-init */
   1608         pthread_cond_destroy(&stream_obj->buf_cond);
   1609         pthread_mutex_destroy(&stream_obj->buf_lock);
   1610         pthread_mutex_destroy(&stream_obj->cb_lock);
   1611         pthread_mutex_destroy(&stream_obj->cmd_lock);
   1612         memset(stream_obj, 0, sizeof(mm_stream_t));
   1613     }
   1614     LOGD("stream handle = %d", s_hdl);
   1615     return s_hdl;
   1616 }
   1617 
   1618 /*===========================================================================
   1619  * FUNCTION   : mm_channel_del_stream
   1620  *
   1621  * DESCRIPTION: delete a stream from the channel bu its handle
   1622  *
   1623  * PARAMETERS :
   1624  *   @my_obj       : channel object
   1625  *   @stream_id    : stream handle
   1626  *
   1627  * RETURN     : int32_t type of status
   1628  *              0  -- success
   1629  *              -1 -- failure
   1630  * NOTE       : assume steam is stooped before it can be deleted
   1631  *==========================================================================*/
   1632 int32_t mm_channel_del_stream(mm_channel_t *my_obj,
   1633                               uint32_t stream_id)
   1634 {
   1635     int rc = -1;
   1636     mm_stream_t * stream_obj = NULL;
   1637     stream_obj = mm_channel_util_get_stream_by_handler(my_obj, stream_id);
   1638 
   1639     if (NULL == stream_obj) {
   1640         LOGE("Invalid Stream Object for stream_id = %d", stream_id);
   1641         return rc;
   1642     }
   1643 
   1644     if (stream_obj->ch_obj != my_obj) {
   1645         /* Only unlink stream */
   1646         pthread_mutex_lock(&stream_obj->linked_stream->buf_lock);
   1647         stream_obj->linked_stream->is_linked = 0;
   1648         stream_obj->linked_stream->linked_obj = NULL;
   1649         pthread_mutex_unlock(&stream_obj->linked_stream->buf_lock);
   1650         memset(stream_obj, 0, sizeof(mm_stream_t));
   1651 
   1652         return 0;
   1653     }
   1654 
   1655     rc = mm_stream_fsm_fn(stream_obj,
   1656                           MM_STREAM_EVT_RELEASE,
   1657                           NULL,
   1658                           NULL);
   1659 
   1660     LOGD("stream handle = %d rc = %d", stream_id, rc);
   1661     return rc;
   1662 }
   1663 
   1664 /*===========================================================================
   1665  * FUNCTION   : mm_channel_config_stream
   1666  *
   1667  * DESCRIPTION: configure a stream
   1668  *
   1669  * PARAMETERS :
   1670  *   @my_obj       : channel object
   1671  *   @stream_id    : stream handle
   1672  *   @config       : stream configuration
   1673  *
   1674  * RETURN     : int32_t type of status
   1675  *              0  -- success
   1676  *              -1 -- failure
   1677  *==========================================================================*/
   1678 int32_t mm_channel_config_stream(mm_channel_t *my_obj,
   1679                                    uint32_t stream_id,
   1680                                    mm_camera_stream_config_t *config)
   1681 {
   1682     int rc = -1;
   1683     mm_stream_t * stream_obj = NULL;
   1684     LOGD("E stream ID = %d", stream_id);
   1685     stream_obj = mm_channel_util_get_stream_by_handler(my_obj, stream_id);
   1686 
   1687     if (NULL == stream_obj) {
   1688         LOGE("Invalid Stream Object for stream_id = %d", stream_id);
   1689         return rc;
   1690     }
   1691 
   1692     if (stream_obj->ch_obj != my_obj) {
   1693         /* No op. on linked streams */
   1694         return 0;
   1695     }
   1696 
   1697     /* set stream fmt */
   1698     rc = mm_stream_fsm_fn(stream_obj,
   1699                           MM_STREAM_EVT_SET_FMT,
   1700                           (void *)config,
   1701                           NULL);
   1702     LOGD("X rc = %d",rc);
   1703     return rc;
   1704 }
   1705 
   1706 /*===========================================================================
   1707  * FUNCTION   : mm_channel_get_bundle_info
   1708  *
   1709  * DESCRIPTION: query bundle info of the channel, which should include all
   1710  *              streams within this channel
   1711  *
   1712  * PARAMETERS :
   1713  *   @my_obj       : channel object
   1714  *   @bundle_info  : bundle info to be filled in
   1715  *
   1716  * RETURN     : int32_t type of status
   1717  *              0  -- success
   1718  *              -1 -- failure
   1719  *==========================================================================*/
   1720 int32_t mm_channel_get_bundle_info(mm_channel_t *my_obj,
   1721                                    cam_bundle_config_t *bundle_info)
   1722 {
   1723     int i;
   1724     mm_stream_t *s_obj = NULL;
   1725     cam_stream_type_t stream_type = CAM_STREAM_TYPE_DEFAULT;
   1726     int32_t rc = 0;
   1727 
   1728     memset(bundle_info, 0, sizeof(cam_bundle_config_t));
   1729     bundle_info->bundle_id = my_obj->my_hdl;
   1730     bundle_info->num_of_streams = 0;
   1731     for (i = 0; i < MAX_STREAM_NUM_IN_BUNDLE; i++) {
   1732         if (my_obj->streams[i].my_hdl > 0) {
   1733             s_obj = mm_channel_util_get_stream_by_handler(my_obj,
   1734                                                           my_obj->streams[i].my_hdl);
   1735             if (NULL != s_obj) {
   1736                 stream_type = s_obj->stream_info->stream_type;
   1737                 if ((CAM_STREAM_TYPE_METADATA != stream_type) &&
   1738                         (s_obj->ch_obj == my_obj)) {
   1739                     bundle_info->stream_ids[bundle_info->num_of_streams++] =
   1740                                                         s_obj->server_stream_id;
   1741                 }
   1742             } else {
   1743                 LOGE("cannot find stream obj (%d) by handler (%d)",
   1744                             i, my_obj->streams[i].my_hdl);
   1745                 rc = -1;
   1746                 break;
   1747             }
   1748         }
   1749     }
   1750     if (rc != 0) {
   1751         /* error, reset to 0 */
   1752         memset(bundle_info, 0, sizeof(cam_bundle_config_t));
   1753     }
   1754     return rc;
   1755 }
   1756 
   1757 /*===========================================================================
   1758  * FUNCTION   : mm_channel_start
   1759  *
   1760  * DESCRIPTION: start a channel, which will start all streams in the channel
   1761  *
   1762  * PARAMETERS :
   1763  *   @my_obj       : channel object
   1764  *
   1765  * RETURN     : int32_t type of status
   1766  *              0  -- success
   1767  *              -1 -- failure
   1768  *==========================================================================*/
   1769 int32_t mm_channel_start(mm_channel_t *my_obj)
   1770 {
   1771     int32_t rc = 0;
   1772     int i = 0, j = 0;
   1773     mm_stream_t *s_objs[MAX_STREAM_NUM_IN_BUNDLE] = {NULL};
   1774     uint8_t num_streams_to_start = 0;
   1775     uint8_t num_streams_in_bundle_queue = 0;
   1776     mm_stream_t *s_obj = NULL;
   1777     int meta_stream_idx = 0;
   1778     cam_stream_type_t stream_type = CAM_STREAM_TYPE_DEFAULT;
   1779 
   1780     for (i = 0; i < MAX_STREAM_NUM_IN_BUNDLE; i++) {
   1781         if (my_obj->streams[i].my_hdl > 0) {
   1782             s_obj = mm_channel_util_get_stream_by_handler(my_obj,
   1783                                                           my_obj->streams[i].my_hdl);
   1784             if (NULL != s_obj) {
   1785                 stream_type = s_obj->stream_info->stream_type;
   1786                 /* remember meta data stream index */
   1787                 if ((stream_type == CAM_STREAM_TYPE_METADATA) &&
   1788                         (s_obj->ch_obj == my_obj)) {
   1789                     meta_stream_idx = num_streams_to_start;
   1790                 }
   1791                 s_objs[num_streams_to_start++] = s_obj;
   1792 
   1793                 if (!s_obj->stream_info->noFrameExpected) {
   1794                     num_streams_in_bundle_queue++;
   1795                 }
   1796             }
   1797         }
   1798     }
   1799 
   1800     if (meta_stream_idx > 0 ) {
   1801         /* always start meta data stream first, so switch the stream object with the first one */
   1802         s_obj = s_objs[0];
   1803         s_objs[0] = s_objs[meta_stream_idx];
   1804         s_objs[meta_stream_idx] = s_obj;
   1805     }
   1806 
   1807     if (NULL != my_obj->bundle.super_buf_notify_cb) {
   1808         /* need to send up cb, therefore launch thread */
   1809         /* init superbuf queue */
   1810         mm_channel_superbuf_queue_init(&my_obj->bundle.superbuf_queue);
   1811         my_obj->bundle.superbuf_queue.num_streams = num_streams_in_bundle_queue;
   1812         my_obj->bundle.superbuf_queue.expected_frame_id =
   1813                 my_obj->bundle.superbuf_queue.attr.user_expected_frame_id;
   1814         my_obj->bundle.superbuf_queue.expected_frame_id_without_led = 0;
   1815         my_obj->bundle.superbuf_queue.led_off_start_frame_id = 0;
   1816         my_obj->bundle.superbuf_queue.led_on_start_frame_id = 0;
   1817         my_obj->bundle.superbuf_queue.led_on_num_frames = 0;
   1818         my_obj->bundle.superbuf_queue.good_frame_id = 0;
   1819 
   1820         for (i = 0; i < num_streams_to_start; i++) {
   1821             /* Only bundle streams that belong to the channel */
   1822             if(!(s_objs[i]->stream_info->noFrameExpected)) {
   1823                 if (s_objs[i]->ch_obj == my_obj) {
   1824                     /* set bundled flag to streams */
   1825                     s_objs[i]->is_bundled = 1;
   1826                 }
   1827                 my_obj->bundle.superbuf_queue.bundled_streams[j++] = s_objs[i]->my_hdl;
   1828             }
   1829         }
   1830 
   1831         /* launch cb thread for dispatching super buf through cb */
   1832         snprintf(my_obj->cb_thread.threadName, THREAD_NAME_SIZE, "CAM_SuperBuf");
   1833         mm_camera_cmd_thread_launch(&my_obj->cb_thread,
   1834                                     mm_channel_dispatch_super_buf,
   1835                                     (void*)my_obj);
   1836 
   1837         /* launch cmd thread for super buf dataCB */
   1838         snprintf(my_obj->cmd_thread.threadName, THREAD_NAME_SIZE, "CAM_SuperBufCB");
   1839         mm_camera_cmd_thread_launch(&my_obj->cmd_thread,
   1840                                     mm_channel_process_stream_buf,
   1841                                     (void*)my_obj);
   1842 
   1843         /* set flag to TRUE */
   1844         my_obj->bundle.is_active = TRUE;
   1845     }
   1846 
   1847     /* link any streams first before starting the rest of the streams */
   1848     for (i = 0; i < num_streams_to_start; i++) {
   1849         if (s_objs[i]->ch_obj != my_obj) {
   1850             pthread_mutex_lock(&s_objs[i]->linked_stream->buf_lock);
   1851             s_objs[i]->linked_stream->linked_obj = my_obj;
   1852             s_objs[i]->linked_stream->is_linked = 1;
   1853             pthread_mutex_unlock(&s_objs[i]->linked_stream->buf_lock);
   1854             continue;
   1855         }
   1856     }
   1857 
   1858     for (i = 0; i < num_streams_to_start; i++) {
   1859         if (s_objs[i]->ch_obj != my_obj) {
   1860             continue;
   1861         }
   1862         /* all streams within a channel should be started at the same time */
   1863         if (s_objs[i]->state == MM_STREAM_STATE_ACTIVE) {
   1864             LOGE("stream already started idx(%d)", i);
   1865             rc = -1;
   1866             break;
   1867         }
   1868 
   1869         /* allocate buf */
   1870         rc = mm_stream_fsm_fn(s_objs[i],
   1871                               MM_STREAM_EVT_GET_BUF,
   1872                               NULL,
   1873                               NULL);
   1874         if (0 != rc) {
   1875             LOGE("get buf failed at idx(%d)", i);
   1876             break;
   1877         }
   1878 
   1879         /* reg buf */
   1880         rc = mm_stream_fsm_fn(s_objs[i],
   1881                               MM_STREAM_EVT_REG_BUF,
   1882                               NULL,
   1883                               NULL);
   1884         if (0 != rc) {
   1885             LOGE("reg buf failed at idx(%d)", i);
   1886             break;
   1887         }
   1888 
   1889         /* start stream */
   1890         rc = mm_stream_fsm_fn(s_objs[i],
   1891                               MM_STREAM_EVT_START,
   1892                               NULL,
   1893                               NULL);
   1894         if (0 != rc) {
   1895             LOGE("start stream failed at idx(%d)", i);
   1896             break;
   1897         }
   1898     }
   1899 
   1900     /* error handling */
   1901     if (0 != rc) {
   1902         /* unlink the streams first */
   1903         for (j = 0; j < num_streams_to_start; j++) {
   1904             if (s_objs[j]->ch_obj != my_obj) {
   1905                 pthread_mutex_lock(&s_objs[j]->linked_stream->buf_lock);
   1906                 s_objs[j]->linked_stream->is_linked = 0;
   1907                 s_objs[j]->linked_stream->linked_obj = NULL;
   1908                 pthread_mutex_unlock(&s_objs[j]->linked_stream->buf_lock);
   1909 
   1910                 if (TRUE == my_obj->bundle.is_active) {
   1911                     mm_channel_flush_super_buf_queue(my_obj, 0,
   1912                             s_objs[i]->stream_info->stream_type);
   1913                 }
   1914                 memset(s_objs[j], 0, sizeof(mm_stream_t));
   1915                 continue;
   1916             }
   1917         }
   1918 
   1919         for (j = 0; j <= i; j++) {
   1920             if ((NULL == s_objs[j]) || (s_objs[j]->ch_obj != my_obj)) {
   1921                 continue;
   1922             }
   1923             /* stop streams*/
   1924             mm_stream_fsm_fn(s_objs[j],
   1925                              MM_STREAM_EVT_STOP,
   1926                              NULL,
   1927                              NULL);
   1928 
   1929             /* unreg buf */
   1930             mm_stream_fsm_fn(s_objs[j],
   1931                              MM_STREAM_EVT_UNREG_BUF,
   1932                              NULL,
   1933                              NULL);
   1934 
   1935             /* put buf back */
   1936             mm_stream_fsm_fn(s_objs[j],
   1937                              MM_STREAM_EVT_PUT_BUF,
   1938                              NULL,
   1939                              NULL);
   1940         }
   1941 
   1942         /* destroy super buf cmd thread */
   1943         if (TRUE == my_obj->bundle.is_active) {
   1944             /* first stop bundle thread */
   1945             mm_camera_cmd_thread_release(&my_obj->cmd_thread);
   1946             mm_camera_cmd_thread_release(&my_obj->cb_thread);
   1947 
   1948             /* deinit superbuf queue */
   1949             mm_channel_superbuf_queue_deinit(&my_obj->bundle.superbuf_queue);
   1950 
   1951             /* memset super buffer queue info */
   1952             my_obj->bundle.is_active = 0;
   1953             memset(&my_obj->bundle.superbuf_queue, 0, sizeof(mm_channel_queue_t));
   1954         }
   1955     }
   1956     my_obj->bWaitForPrepSnapshotDone = 0;
   1957     if (my_obj->bundle.superbuf_queue.attr.enable_frame_sync) {
   1958         LOGH("registering Channel obj %p", my_obj);
   1959         mm_frame_sync_register_channel(my_obj);
   1960     }
   1961     return rc;
   1962 }
   1963 
   1964 int32_t mm_channel_start_sensor_streaming(mm_channel_t *my_obj)
   1965 {
   1966     int32_t rc = 0;
   1967     int i = 0;
   1968     mm_stream_t *s_objs[MAX_STREAM_NUM_IN_BUNDLE] = {NULL};
   1969     uint8_t num_streams_to_start = 0;
   1970     mm_stream_t *s_obj = NULL;
   1971     int meta_stream_idx = 0;
   1972     cam_stream_type_t stream_type = CAM_STREAM_TYPE_DEFAULT;
   1973 
   1974     for (i = 0; i < MAX_STREAM_NUM_IN_BUNDLE; i++) {
   1975         if (my_obj->streams[i].my_hdl > 0) {
   1976             s_obj = mm_channel_util_get_stream_by_handler(my_obj,
   1977                                                           my_obj->streams[i].my_hdl);
   1978             if (NULL != s_obj) {
   1979                 stream_type = s_obj->stream_info->stream_type;
   1980                 /* remember meta data stream index */
   1981                 if ((stream_type == CAM_STREAM_TYPE_METADATA) &&
   1982                         (s_obj->ch_obj == my_obj)) {
   1983                     meta_stream_idx = num_streams_to_start;
   1984                 }
   1985                 s_objs[num_streams_to_start++] = s_obj;
   1986             }
   1987         }
   1988     }
   1989 
   1990     if (meta_stream_idx > 0 ) {
   1991         /* always start meta data stream first, so switch the stream object with the first one */
   1992         s_obj = s_objs[0];
   1993         s_objs[0] = s_objs[meta_stream_idx];
   1994         s_objs[meta_stream_idx] = s_obj;
   1995     }
   1996 
   1997     for (i = 0; i < num_streams_to_start; i++) {
   1998         if (s_objs[i]->ch_obj != my_obj) {
   1999             continue;
   2000         }
   2001 
   2002         /* start sensor streaming */
   2003         rc = mm_stream_fsm_fn(s_objs[i],
   2004                               MM_STREAM_EVT_START_SENSOR_STREAMING,
   2005                               NULL,
   2006                               NULL);
   2007         if (0 != rc) {
   2008             LOGE("start stream failed at idx(%d)", i);
   2009             break;
   2010         }
   2011     }
   2012 
   2013     return rc;
   2014 }
   2015 
   2016 /*===========================================================================
   2017  * FUNCTION   : mm_channel_stop
   2018  *
   2019  * DESCRIPTION: stop a channel, which will stop all streams in the channel
   2020  *
   2021  * PARAMETERS :
   2022  *   @my_obj       : channel object
   2023  *
   2024  * RETURN     : int32_t type of status
   2025  *              0  -- success
   2026  *              -1 -- failure
   2027  *==========================================================================*/
   2028 int32_t mm_channel_stop(mm_channel_t *my_obj, bool stopImmediately)
   2029 {
   2030     int32_t rc = 0;
   2031     int i;
   2032     mm_stream_t *s_objs[MAX_STREAM_NUM_IN_BUNDLE] = {NULL};
   2033     uint8_t num_streams_to_stop = 0;
   2034     mm_stream_t *s_obj = NULL;
   2035     int meta_stream_idx = 0;
   2036     cam_stream_type_t stream_type = CAM_STREAM_TYPE_DEFAULT;
   2037 
   2038     if (my_obj->bundle.superbuf_queue.attr.enable_frame_sync) {
   2039         mm_frame_sync_unregister_channel(my_obj);
   2040     }
   2041 
   2042     for (i = 0; i < MAX_STREAM_NUM_IN_BUNDLE; i++) {
   2043         if (my_obj->streams[i].my_hdl > 0) {
   2044             s_obj = mm_channel_util_get_stream_by_handler(my_obj,
   2045                                                           my_obj->streams[i].my_hdl);
   2046             if (NULL != s_obj) {
   2047                 if (s_obj->ch_obj == my_obj) {
   2048                     stream_type = s_obj->stream_info->stream_type;
   2049                     /* remember meta data stream index */
   2050                     if (stream_type == CAM_STREAM_TYPE_METADATA) {
   2051                         meta_stream_idx = num_streams_to_stop;
   2052                     }
   2053                 }
   2054                 s_objs[num_streams_to_stop++] = s_obj;
   2055             }
   2056         }
   2057     }
   2058 
   2059     if (meta_stream_idx < num_streams_to_stop - 1 ) {
   2060         /* always stop meta data stream last, so switch the stream object with the last one */
   2061         s_obj = s_objs[num_streams_to_stop - 1];
   2062         s_objs[num_streams_to_stop - 1] = s_objs[meta_stream_idx];
   2063         s_objs[meta_stream_idx] = s_obj;
   2064     }
   2065 
   2066     for (i = 0; i < num_streams_to_stop; i++) {
   2067         /* stream that are linked to this channel should not be stopped */
   2068         if (s_objs[i]->ch_obj != my_obj) {
   2069             continue;
   2070         }
   2071 
   2072         /* stream off */
   2073         mm_stream_fsm_fn(s_objs[i],
   2074                          MM_STREAM_EVT_STOP,
   2075                          &stopImmediately,
   2076                          NULL);
   2077 
   2078         /* unreg buf at kernel */
   2079         mm_stream_fsm_fn(s_objs[i],
   2080                          MM_STREAM_EVT_UNREG_BUF,
   2081                          NULL,
   2082                          NULL);
   2083     }
   2084 
   2085     for (i = 0; i < num_streams_to_stop; i++) {
   2086         if (s_objs[i]->ch_obj != my_obj) {
   2087             /* Only unlink stream */
   2088             pthread_mutex_lock(&s_objs[i]->linked_stream->buf_lock);
   2089             s_objs[i]->linked_stream->is_linked = 0;
   2090             s_objs[i]->linked_stream->linked_obj = NULL;
   2091             pthread_mutex_unlock(&s_objs[i]->linked_stream->buf_lock);
   2092         }
   2093     }
   2094 
   2095     /* destroy super buf cmd thread */
   2096     if (TRUE == my_obj->bundle.is_active) {
   2097         mm_channel_flush_super_buf_queue(my_obj, 0, CAM_STREAM_TYPE_DEFAULT);
   2098         /* first stop bundle thread */
   2099         mm_camera_cmd_thread_release(&my_obj->cmd_thread);
   2100         mm_camera_cmd_thread_release(&my_obj->cb_thread);
   2101 
   2102         /* deinit superbuf queue */
   2103         mm_channel_superbuf_queue_deinit(&my_obj->bundle.superbuf_queue);
   2104 
   2105         /* reset few fields in the bundle info */
   2106         my_obj->bundle.is_active = 0;
   2107         my_obj->bundle.superbuf_queue.expected_frame_id = 0;
   2108         my_obj->bundle.superbuf_queue.good_frame_id = 0;
   2109         my_obj->bundle.superbuf_queue.match_cnt = 0;
   2110     }
   2111 
   2112     /* since all streams are stopped, we are safe to
   2113      * release all buffers allocated in stream */
   2114     for (i = 0; i < num_streams_to_stop; i++) {
   2115         if (s_objs[i]->ch_obj != my_obj) {
   2116             continue;
   2117         }
   2118         /* put buf back */
   2119         mm_stream_fsm_fn(s_objs[i],
   2120                          MM_STREAM_EVT_PUT_BUF,
   2121                          NULL,
   2122                          NULL);
   2123     }
   2124 
   2125     for (i = 0; i < num_streams_to_stop; i++) {
   2126         if (s_objs[i]->ch_obj != my_obj) {
   2127             memset(s_objs[i], 0, sizeof(mm_stream_t));
   2128         } else {
   2129             continue;
   2130         }
   2131     }
   2132     return rc;
   2133 }
   2134 
   2135 /*===========================================================================
   2136  * FUNCTION   : mm_channel_request_super_buf
   2137  *
   2138  * DESCRIPTION: for burst mode in bundle, reuqest certain amount of matched
   2139  *              frames from superbuf queue
   2140  *
   2141  * PARAMETERS :
   2142  *   @my_obj       : channel object
   2143  *   @num_buf_requested : number of matched frames needed
   2144  *   @num_retro_buf_requested : number of retro frames needed
   2145  *
   2146  * RETURN     : int32_t type of status
   2147  *              0  -- success
   2148  *              -1 -- failure
   2149  *==========================================================================*/
   2150 int32_t mm_channel_request_super_buf(mm_channel_t *my_obj,
   2151         mm_camera_req_buf_t *buf)
   2152 {
   2153     int32_t rc = 0;
   2154     mm_camera_cmdcb_t* node = NULL;
   2155 
   2156     if(!buf) {
   2157         LOGE("Request info buf is NULL");
   2158         return -1;
   2159     }
   2160 
   2161     /* set pending_cnt
   2162      * will trigger dispatching super frames if pending_cnt > 0 */
   2163     /* send cam_sem_post to wake up cmd thread to dispatch super buffer */
   2164     node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
   2165     if (NULL != node) {
   2166         memset(node, 0, sizeof(mm_camera_cmdcb_t));
   2167         node->cmd_type = MM_CAMERA_CMD_TYPE_REQ_DATA_CB;
   2168         node->u.req_buf = *buf;
   2169 
   2170         /* enqueue to cmd thread */
   2171         cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node);
   2172 
   2173         /* wake up cmd thread */
   2174         cam_sem_post(&(my_obj->cmd_thread.cmd_sem));
   2175     } else {
   2176         LOGE("No memory for mm_camera_node_t");
   2177         rc = -1;
   2178     }
   2179 
   2180     return rc;
   2181 }
   2182 
   2183 /*===========================================================================
   2184  * FUNCTION   : mm_channel_cancel_super_buf_request
   2185  *
   2186  * DESCRIPTION: for burst mode in bundle, cancel the reuqest for certain amount
   2187  *              of matched frames from superbuf queue
   2188  *
   2189  * PARAMETERS :
   2190  *   @my_obj       : channel object
   2191  *
   2192  * RETURN     : int32_t type of status
   2193  *              0  -- success
   2194  *              -1 -- failure
   2195  *==========================================================================*/
   2196 int32_t mm_channel_cancel_super_buf_request(mm_channel_t *my_obj)
   2197 {
   2198     int32_t rc = 0;
   2199     /* reset pending_cnt */
   2200     mm_camera_req_buf_t buf;
   2201     memset(&buf, 0x0, sizeof(buf));
   2202     buf.type = MM_CAMERA_REQ_SUPER_BUF;
   2203     buf.num_buf_requested = 0;
   2204     rc = mm_channel_request_super_buf(my_obj, &buf);
   2205     return rc;
   2206 }
   2207 
   2208 /*===========================================================================
   2209  * FUNCTION   : mm_channel_flush_super_buf_queue
   2210  *
   2211  * DESCRIPTION: flush superbuf queue
   2212  *
   2213  * PARAMETERS :
   2214  *   @my_obj  : channel object
   2215  *   @frame_idx : frame idx until which to flush all superbufs
   2216  *
   2217  * RETURN     : int32_t type of status
   2218  *              0  -- success
   2219  *              -1 -- failure
   2220  *==========================================================================*/
   2221 int32_t mm_channel_flush_super_buf_queue(mm_channel_t *my_obj, uint32_t frame_idx,
   2222                                                      cam_stream_type_t stream_type)
   2223 {
   2224     int32_t rc = 0;
   2225     mm_camera_cmdcb_t* node = NULL;
   2226 
   2227     node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
   2228     if (NULL != node) {
   2229         memset(node, 0, sizeof(mm_camera_cmdcb_t));
   2230         node->cmd_type = MM_CAMERA_CMD_TYPE_FLUSH_QUEUE;
   2231         node->u.flush_cmd.frame_idx = frame_idx;
   2232         node->u.flush_cmd.stream_type = stream_type;
   2233 
   2234         /* enqueue to cmd thread */
   2235         cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node);
   2236 
   2237         /* wake up cmd thread */
   2238         cam_sem_post(&(my_obj->cmd_thread.cmd_sem));
   2239 
   2240         /* wait for ack from cmd thread */
   2241         cam_sem_wait(&(my_obj->cmd_thread.sync_sem));
   2242     } else {
   2243         LOGE("No memory for mm_camera_node_t");
   2244         rc = -1;
   2245     }
   2246 
   2247     return rc;
   2248 }
   2249 
   2250 /*===========================================================================
   2251  * FUNCTION   : mm_channel_config_notify_mode
   2252  *
   2253  * DESCRIPTION: configure notification mode
   2254  *
   2255  * PARAMETERS :
   2256  *   @my_obj  : channel object
   2257  *   @notify_mode : notification mode
   2258  *
   2259  * RETURN     : int32_t type of status
   2260  *              0  -- success
   2261  *              -1 -- failure
   2262  *==========================================================================*/
   2263 int32_t mm_channel_config_notify_mode(mm_channel_t *my_obj,
   2264                                       mm_camera_super_buf_notify_mode_t notify_mode)
   2265 {
   2266     int32_t rc = 0;
   2267     mm_camera_cmdcb_t* node = NULL;
   2268 
   2269     node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
   2270     if (NULL != node) {
   2271         memset(node, 0, sizeof(mm_camera_cmdcb_t));
   2272         node->u.notify_mode = notify_mode;
   2273         node->cmd_type = MM_CAMERA_CMD_TYPE_CONFIG_NOTIFY;
   2274 
   2275         /* enqueue to cmd thread */
   2276         cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node);
   2277 
   2278         /* wake up cmd thread */
   2279         cam_sem_post(&(my_obj->cmd_thread.cmd_sem));
   2280     } else {
   2281         LOGE("No memory for mm_camera_node_t");
   2282         rc = -1;
   2283     }
   2284 
   2285     return rc;
   2286 }
   2287 
   2288 /*===========================================================================
   2289  * FUNCTION   : mm_channel_start_zsl_snapshot
   2290  *
   2291  * DESCRIPTION: start zsl snapshot
   2292  *
   2293  * PARAMETERS :
   2294  *   @my_obj  : channel object
   2295  *
   2296  * RETURN     : int32_t type of status
   2297  *              0  -- success
   2298  *              -1 -- failure
   2299  *==========================================================================*/
   2300 int32_t mm_channel_start_zsl_snapshot(mm_channel_t *my_obj)
   2301 {
   2302     int32_t rc = 0;
   2303     mm_camera_cmdcb_t* node = NULL;
   2304 
   2305     node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
   2306     if (NULL != node) {
   2307         memset(node, 0, sizeof(mm_camera_cmdcb_t));
   2308         node->cmd_type = MM_CAMERA_CMD_TYPE_START_ZSL;
   2309 
   2310         /* enqueue to cmd thread */
   2311         cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node);
   2312 
   2313         /* wake up cmd thread */
   2314         cam_sem_post(&(my_obj->cmd_thread.cmd_sem));
   2315     } else {
   2316         LOGE("No memory for mm_camera_node_t");
   2317         rc = -1;
   2318     }
   2319 
   2320     return rc;
   2321 }
   2322 
   2323 /*===========================================================================
   2324  * FUNCTION   : mm_channel_stop_zsl_snapshot
   2325  *
   2326  * DESCRIPTION: stop zsl snapshot
   2327  *
   2328  * PARAMETERS :
   2329  *   @my_obj  : channel object
   2330  *
   2331  * RETURN     : int32_t type of status
   2332  *              0  -- success
   2333  *              -1 -- failure
   2334  *==========================================================================*/
   2335 int32_t mm_channel_stop_zsl_snapshot(mm_channel_t *my_obj)
   2336 {
   2337     int32_t rc = 0;
   2338     mm_camera_cmdcb_t* node = NULL;
   2339 
   2340     node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
   2341     if (NULL != node) {
   2342         memset(node, 0, sizeof(mm_camera_cmdcb_t));
   2343         node->cmd_type = MM_CAMERA_CMD_TYPE_STOP_ZSL;
   2344 
   2345         /* enqueue to cmd thread */
   2346         cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node);
   2347 
   2348         /* wake up cmd thread */
   2349         cam_sem_post(&(my_obj->cmd_thread.cmd_sem));
   2350     } else {
   2351         LOGE("No memory for mm_camera_node_t");
   2352         rc = -1;
   2353     }
   2354 
   2355     return rc;
   2356 }
   2357 
   2358 /*===========================================================================
   2359  * FUNCTION   : mm_channel_qbuf
   2360  *
   2361  * DESCRIPTION: enqueue buffer back to kernel
   2362  *
   2363  * PARAMETERS :
   2364  *   @my_obj       : channel object
   2365  *   @buf          : buf ptr to be enqueued
   2366  *
   2367  * RETURN     : int32_t type of status
   2368  *              0  -- success
   2369  *              -1 -- failure
   2370  *==========================================================================*/
   2371 int32_t mm_channel_qbuf(mm_channel_t *my_obj,
   2372                         mm_camera_buf_def_t *buf)
   2373 {
   2374     int32_t rc = -1;
   2375     mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj, buf->stream_id);
   2376 
   2377     if (NULL != s_obj) {
   2378         if (s_obj->ch_obj != my_obj) {
   2379             /* Redirect to linked stream */
   2380             rc = mm_stream_fsm_fn(s_obj->linked_stream,
   2381                     MM_STREAM_EVT_QBUF,
   2382                     (void *)buf,
   2383                     NULL);
   2384         } else {
   2385             rc = mm_stream_fsm_fn(s_obj,
   2386                     MM_STREAM_EVT_QBUF,
   2387                     (void *)buf,
   2388                     NULL);
   2389         }
   2390     }
   2391 
   2392     return rc;
   2393 }
   2394 
   2395 /*===========================================================================
   2396  * FUNCTION   : mm_channel_cancel_buf
   2397  *
   2398  * DESCRIPTION: Get back buffer already sent to kernel
   2399  *
   2400  * PARAMETERS :
   2401  *   @my_obj       : channel object
   2402  *   @buf          : buf ptr to be enqueued
   2403  *
   2404  * RETURN     : int32_t type of status
   2405  *              0  -- success
   2406  *              -1 -- failure
   2407  *==========================================================================*/
   2408 int32_t mm_channel_cancel_buf(mm_channel_t *my_obj,
   2409                         uint32_t stream_id, uint32_t buf_idx)
   2410 {
   2411     int32_t rc = -1;
   2412     mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj, stream_id);
   2413 
   2414     if (NULL != s_obj) {
   2415         if (s_obj->ch_obj != my_obj) {
   2416             /* Redirect to linked stream */
   2417             rc = mm_stream_fsm_fn(s_obj->linked_stream,
   2418                     MM_STREAM_EVT_CANCEL_BUF,
   2419                     (void *)&buf_idx,
   2420                     NULL);
   2421         } else {
   2422             rc = mm_stream_fsm_fn(s_obj,
   2423                     MM_STREAM_EVT_CANCEL_BUF,
   2424                     (void *)&buf_idx,
   2425                     NULL);
   2426         }
   2427     }
   2428 
   2429     return rc;
   2430 }
   2431 
   2432 
   2433 /*===========================================================================
   2434  * FUNCTION   : mm_channel_get_queued_buf_count
   2435  *
   2436  * DESCRIPTION: return queued buffer count
   2437  *
   2438  * PARAMETERS :
   2439  *   @my_obj       : channel object
   2440  *   @stream_id    : steam_id
   2441  *
   2442  * RETURN     : queued buffer count
   2443  *==========================================================================*/
   2444 int32_t mm_channel_get_queued_buf_count(mm_channel_t *my_obj, uint32_t stream_id)
   2445 {
   2446     int32_t rc = -1;
   2447     mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj, stream_id);
   2448 
   2449     if (NULL != s_obj) {
   2450         if (s_obj->ch_obj != my_obj) {
   2451             /* Redirect to linked stream */
   2452             rc = mm_stream_fsm_fn(s_obj->linked_stream,
   2453                     MM_STREAM_EVT_GET_QUEUED_BUF_COUNT,
   2454                     NULL,
   2455                     NULL);
   2456         } else {
   2457             rc = mm_stream_fsm_fn(s_obj,
   2458                     MM_STREAM_EVT_GET_QUEUED_BUF_COUNT,
   2459                     NULL,
   2460                     NULL);
   2461         }
   2462     }
   2463 
   2464     return rc;
   2465 }
   2466 
   2467 /*===========================================================================
   2468  * FUNCTION   : mm_channel_set_stream_parms
   2469  *
   2470  * DESCRIPTION: set parameters per stream
   2471  *
   2472  * PARAMETERS :
   2473  *   @my_obj       : channel object
   2474  *   @s_id         : stream handle
   2475  *   @parms        : ptr to a param struct to be set to server
   2476  *
   2477  * RETURN     : int32_t type of status
   2478  *              0  -- success
   2479  *              -1 -- failure
   2480  * NOTE       : Assume the parms struct buf is already mapped to server via
   2481  *              domain socket. Corresponding fields of parameters to be set
   2482  *              are already filled in by upper layer caller.
   2483  *==========================================================================*/
   2484 int32_t mm_channel_set_stream_parm(mm_channel_t *my_obj,
   2485                                    mm_evt_paylod_set_get_stream_parms_t *payload)
   2486 {
   2487     int32_t rc = -1;
   2488     mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj,
   2489                                                                payload->stream_id);
   2490     if (NULL != s_obj) {
   2491         if (s_obj->ch_obj != my_obj) {
   2492             /* No op. on linked streams */
   2493             return 0;
   2494         }
   2495 
   2496         rc = mm_stream_fsm_fn(s_obj,
   2497                               MM_STREAM_EVT_SET_PARM,
   2498                               (void *)payload,
   2499                               NULL);
   2500     }
   2501 
   2502     return rc;
   2503 }
   2504 
   2505 /*===========================================================================
   2506  * FUNCTION   : mm_channel_get_stream_parms
   2507  *
   2508  * DESCRIPTION: get parameters per stream
   2509  *
   2510  * PARAMETERS :
   2511  *   @my_obj       : channel object
   2512  *   @s_id         : stream handle
   2513  *   @parms        : ptr to a param struct to be get from server
   2514  *
   2515  * RETURN     : int32_t type of status
   2516  *              0  -- success
   2517  *              -1 -- failure
   2518  * NOTE       : Assume the parms struct buf is already mapped to server via
   2519  *              domain socket. Parameters to be get from server are already
   2520  *              filled in by upper layer caller. After this call, corresponding
   2521  *              fields of requested parameters will be filled in by server with
   2522  *              detailed information.
   2523  *==========================================================================*/
   2524 int32_t mm_channel_get_stream_parm(mm_channel_t *my_obj,
   2525                                    mm_evt_paylod_set_get_stream_parms_t *payload)
   2526 {
   2527     int32_t rc = -1;
   2528     mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj,
   2529                                                                payload->stream_id);
   2530     if (NULL != s_obj) {
   2531         if (s_obj->ch_obj != my_obj) {
   2532             /* No op. on linked streams */
   2533             return 0;
   2534         }
   2535 
   2536         rc = mm_stream_fsm_fn(s_obj,
   2537                               MM_STREAM_EVT_GET_PARM,
   2538                               (void *)payload,
   2539                               NULL);
   2540     }
   2541 
   2542     return rc;
   2543 }
   2544 
   2545 /*===========================================================================
   2546  * FUNCTION   : mm_channel_do_stream_action
   2547  *
   2548  * DESCRIPTION: request server to perform stream based action. Maybe removed later
   2549  *              if the functionality is included in mm_camera_set_parms
   2550  *
   2551  * PARAMETERS :
   2552  *   @my_obj       : channel object
   2553  *   @s_id         : stream handle
   2554  *   @actions      : ptr to an action struct buf to be performed by server
   2555  *
   2556  * RETURN     : int32_t type of status
   2557  *              0  -- success
   2558  *              -1 -- failure
   2559  * NOTE       : Assume the action struct buf is already mapped to server via
   2560  *              domain socket. Actions to be performed by server are already
   2561  *              filled in by upper layer caller.
   2562  *==========================================================================*/
   2563 int32_t mm_channel_do_stream_action(mm_channel_t *my_obj,
   2564                                    mm_evt_paylod_do_stream_action_t *payload)
   2565 {
   2566     int32_t rc = -1;
   2567     mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj,
   2568                                                                payload->stream_id);
   2569     if (NULL != s_obj) {
   2570         if (s_obj->ch_obj != my_obj) {
   2571             /* No op. on linked streams */
   2572             return 0;
   2573         }
   2574 
   2575         rc = mm_stream_fsm_fn(s_obj,
   2576                               MM_STREAM_EVT_DO_ACTION,
   2577                               (void *)payload,
   2578                               NULL);
   2579     }
   2580 
   2581     return rc;
   2582 }
   2583 
   2584 /*===========================================================================
   2585  * FUNCTION   : mm_channel_map_stream_buf
   2586  *
   2587  * DESCRIPTION: mapping stream buffer via domain socket to server
   2588  *
   2589  * PARAMETERS :
   2590  *   @my_obj       : channel object
   2591  *   @payload      : ptr to payload for mapping
   2592  *
   2593  * RETURN     : int32_t type of status
   2594  *              0  -- success
   2595  *              -1 -- failure
   2596  *==========================================================================*/
   2597 int32_t mm_channel_map_stream_buf(mm_channel_t *my_obj,
   2598                                   cam_buf_map_type *payload)
   2599 {
   2600     int32_t rc = -1;
   2601     mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj,
   2602             payload->stream_id);
   2603     if (NULL != s_obj) {
   2604         if (s_obj->ch_obj != my_obj) {
   2605             /* No op. on linked streams */
   2606             return 0;
   2607         }
   2608         rc = mm_stream_map_buf(s_obj,
   2609                 payload->type, payload->frame_idx,
   2610                 payload->plane_idx, payload->fd,
   2611                 payload->size, payload->buffer);
   2612     }
   2613 
   2614     return rc;
   2615 }
   2616 
   2617 /*===========================================================================
   2618  * FUNCTION   : mm_channel_map_stream_bufs
   2619  *
   2620  * DESCRIPTION: mapping stream buffers via domain socket to server
   2621  *
   2622  * PARAMETERS :
   2623  *   @my_obj       : channel object
   2624  *   @payload      : ptr to payload for mapping
   2625  *
   2626  * RETURN     : int32_t type of status
   2627  *              0  -- success
   2628  *              -1 -- failure
   2629  *==========================================================================*/
   2630 int32_t mm_channel_map_stream_bufs(mm_channel_t *my_obj,
   2631                                    cam_buf_map_type_list *payload)
   2632 {
   2633     int32_t rc = -1;
   2634     if ((payload == NULL) || (payload->length == 0)) {
   2635         return rc;
   2636     }
   2637 
   2638     mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj,
   2639             payload->buf_maps[0].stream_id);
   2640     if (NULL != s_obj) {
   2641         if (s_obj->ch_obj != my_obj) {
   2642             /* No op. on linked streams */
   2643             return 0;
   2644         }
   2645         rc = mm_stream_map_bufs(s_obj, payload);
   2646     }
   2647     return rc;
   2648 }
   2649 
   2650 /*===========================================================================
   2651  * FUNCTION   : mm_channel_unmap_stream_buf
   2652  *
   2653  * DESCRIPTION: unmapping stream buffer via domain socket to server
   2654  *
   2655  * PARAMETERS :
   2656  *   @my_obj       : channel object
   2657  *   @payload      : ptr to unmap payload
   2658  *
   2659  * RETURN     : int32_t type of status
   2660  *              0  -- success
   2661  *              -1 -- failure
   2662  *==========================================================================*/
   2663 int32_t mm_channel_unmap_stream_buf(mm_channel_t *my_obj,
   2664                                     cam_buf_unmap_type *payload)
   2665 {
   2666     int32_t rc = -1;
   2667     mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj,
   2668                                                                payload->stream_id);
   2669     if (NULL != s_obj) {
   2670         if (s_obj->ch_obj != my_obj) {
   2671             /* No op. on linked streams */
   2672             return 0;
   2673         }
   2674 
   2675         rc = mm_stream_unmap_buf(s_obj, payload->type,
   2676                                  payload->frame_idx, payload->plane_idx);
   2677     }
   2678 
   2679     return rc;
   2680 }
   2681 
   2682 /*===========================================================================
   2683  * FUNCTION   : mm_channel_superbuf_queue_init
   2684  *
   2685  * DESCRIPTION: initialize superbuf queue in the channel
   2686  *
   2687  * PARAMETERS :
   2688  *   @queue   : ptr to superbuf queue to be initialized
   2689  *
   2690  * RETURN     : int32_t type of status
   2691  *              0  -- success
   2692  *              -1 -- failure
   2693  *==========================================================================*/
   2694 int32_t mm_channel_superbuf_queue_init(mm_channel_queue_t * queue)
   2695 {
   2696     return cam_queue_init(&queue->que);
   2697 }
   2698 
   2699 /*===========================================================================
   2700  * FUNCTION   : mm_channel_superbuf_queue_deinit
   2701  *
   2702  * DESCRIPTION: deinitialize superbuf queue in the channel
   2703  *
   2704  * PARAMETERS :
   2705  *   @queue   : ptr to superbuf queue to be deinitialized
   2706  *
   2707  * RETURN     : int32_t type of status
   2708  *              0  -- success
   2709  *              -1 -- failure
   2710  *==========================================================================*/
   2711 int32_t mm_channel_superbuf_queue_deinit(mm_channel_queue_t * queue)
   2712 {
   2713     return cam_queue_deinit(&queue->que);
   2714 }
   2715 
   2716 /*===========================================================================
   2717  * FUNCTION   : mm_channel_util_seq_comp_w_rollover
   2718  *
   2719  * DESCRIPTION: utility function to handle sequence number comparison with rollover
   2720  *
   2721  * PARAMETERS :
   2722  *   @v1      : first value to be compared
   2723  *   @v2      : second value to be compared
   2724  *
   2725  * RETURN     : int8_t type of comparison result
   2726  *              >0  -- v1 larger than v2
   2727  *              =0  -- vi equal to v2
   2728  *              <0  -- v1 smaller than v2
   2729  *==========================================================================*/
   2730 int8_t mm_channel_util_seq_comp_w_rollover(uint32_t v1,
   2731                                            uint32_t v2)
   2732 {
   2733     int8_t ret = 0;
   2734 
   2735     /* TODO: need to handle the case if v2 roll over to 0 */
   2736     if (v1 > v2) {
   2737         ret = 1;
   2738     } else if (v1 < v2) {
   2739         ret = -1;
   2740     }
   2741 
   2742     return ret;
   2743 }
   2744 
   2745 /*===========================================================================
   2746  * FUNCTION   : mm_channel_validate_super_buf.
   2747  *
   2748  * DESCRIPTION: Validate incoming buffer with existing super buffer.
   2749  *
   2750  * PARAMETERS :
   2751  *   @ch_obj  : channel object
   2752  *   @queue   : superbuf queue
   2753  *   @buf_info: new buffer from stream
   2754  *
   2755  * RETURN     : int8_t type of validation result
   2756  *              >0  -- Valid frame
   2757  *              =0  -- Cannot validate
   2758  *              <0  -- Invalid frame. Can be freed
   2759  *==========================================================================*/
   2760 int8_t mm_channel_validate_super_buf(mm_channel_t* ch_obj,
   2761         mm_channel_queue_t *queue, mm_camera_buf_info_t *buf_info)
   2762 {
   2763     int8_t ret = 0;
   2764     cam_node_t* node = NULL;
   2765     struct cam_list *head = NULL;
   2766     struct cam_list *pos = NULL;
   2767     mm_channel_queue_node_t* super_buf = NULL;
   2768 
   2769     (void)ch_obj;
   2770 
   2771     /* comp */
   2772     pthread_mutex_lock(&queue->que.lock);
   2773     head = &queue->que.head.list;
   2774     /* get the last one in the queue which is possibly having no matching */
   2775     pos = head->next;
   2776     while (pos != head) {
   2777         node = member_of(pos, cam_node_t, list);
   2778         super_buf = (mm_channel_queue_node_t*)node->data;
   2779         if (NULL != super_buf) {
   2780             if ((super_buf->expected_frame) &&
   2781                     (buf_info->frame_idx == super_buf->frame_idx)) {
   2782                 //This is good frame. Expecting more frames. Keeping this frame.
   2783                 ret = 1;
   2784                 break;
   2785             } else {
   2786                 pos = pos->next;
   2787                 continue;
   2788             }
   2789         }
   2790     }
   2791     pthread_mutex_unlock(&queue->que.lock);
   2792     return ret;
   2793 }
   2794 
   2795 /*===========================================================================
   2796  * FUNCTION   : mm_channel_handle_metadata
   2797  *
   2798  * DESCRIPTION: Handle frame matching logic change due to metadata
   2799  *
   2800  * PARAMETERS :
   2801  *   @ch_obj  : channel object
   2802  *   @queue   : superbuf queue
   2803  *   @buf_info: new buffer from stream
   2804  *
   2805  * RETURN     : int32_t type of status
   2806  *              0  -- success
   2807  *              -1 -- failure
   2808  *==========================================================================*/
   2809 int32_t mm_channel_handle_metadata(
   2810                         mm_channel_t* ch_obj,
   2811                         mm_channel_queue_t * queue,
   2812                         mm_camera_buf_info_t *buf_info)
   2813 {
   2814 
   2815     int rc = 0 ;
   2816     mm_stream_t* stream_obj = NULL;
   2817     stream_obj = mm_channel_util_get_stream_by_handler(ch_obj,
   2818                 buf_info->stream_id);
   2819     uint8_t is_prep_snapshot_done_valid = 0;
   2820     uint8_t is_good_frame_idx_range_valid = 0;
   2821     int32_t prep_snapshot_done_state = 0;
   2822     cam_frame_idx_range_t good_frame_idx_range;
   2823     uint8_t is_crop_1x_found = 0;
   2824     uint32_t snapshot_stream_id = 0;
   2825     uint32_t i;
   2826     /* Set expected frame id to a future frame idx, large enough to wait
   2827     * for good_frame_idx_range, and small enough to still capture an image */
   2828     const uint32_t max_future_frame_offset = MM_CAMERA_MAX_FUTURE_FRAME_WAIT;
   2829 
   2830     memset(&good_frame_idx_range, 0, sizeof(good_frame_idx_range));
   2831 
   2832     if (NULL == stream_obj) {
   2833         LOGE("Invalid Stream Object for stream_id = %d",
   2834                     buf_info->stream_id);
   2835         rc = -1;
   2836         goto end;
   2837     }
   2838     if (NULL == stream_obj->stream_info) {
   2839         LOGE("NULL stream info for stream_id = %d",
   2840                      buf_info->stream_id);
   2841         rc = -1;
   2842         goto end;
   2843     }
   2844 
   2845     if ((CAM_STREAM_TYPE_METADATA == stream_obj->stream_info->stream_type) &&
   2846             ((stream_obj->ch_obj == ch_obj) ||
   2847             ((stream_obj->linked_stream != NULL) &&
   2848             (stream_obj->linked_stream->linked_obj == ch_obj)))) {
   2849         const metadata_buffer_t *metadata;
   2850         metadata = (const metadata_buffer_t *)buf_info->buf->buffer;
   2851 
   2852         if (NULL == metadata) {
   2853             LOGE("NULL metadata buffer for metadata stream");
   2854             rc = -1;
   2855             goto end;
   2856         }
   2857         LOGL("E , expected frame id: %d", queue->expected_frame_id);
   2858 
   2859         IF_META_AVAILABLE(const int32_t, p_prep_snapshot_done_state,
   2860                 CAM_INTF_META_PREP_SNAPSHOT_DONE, metadata) {
   2861             prep_snapshot_done_state = *p_prep_snapshot_done_state;
   2862             is_prep_snapshot_done_valid = 1;
   2863             LOGH("prepare snapshot done valid ");
   2864         }
   2865         IF_META_AVAILABLE(const cam_frame_idx_range_t, p_good_frame_idx_range,
   2866                 CAM_INTF_META_GOOD_FRAME_IDX_RANGE, metadata) {
   2867             good_frame_idx_range = *p_good_frame_idx_range;
   2868             is_good_frame_idx_range_valid = 1;
   2869             LOGH("good_frame_idx_range : min: %d, max: %d , num frames = %d",
   2870                  good_frame_idx_range.min_frame_idx,
   2871                 good_frame_idx_range.max_frame_idx, good_frame_idx_range.num_led_on_frames);
   2872         }
   2873         IF_META_AVAILABLE(const cam_crop_data_t, p_crop_data,
   2874                 CAM_INTF_META_CROP_DATA, metadata) {
   2875             cam_crop_data_t crop_data = *p_crop_data;
   2876 
   2877             for (i = 0; i < ARRAY_SIZE(ch_obj->streams); i++) {
   2878                 if (MM_STREAM_STATE_NOTUSED == ch_obj->streams[i].state) {
   2879                     continue;
   2880                 }
   2881                 if (CAM_STREAM_TYPE_SNAPSHOT ==
   2882                     ch_obj->streams[i].stream_info->stream_type) {
   2883                     snapshot_stream_id = ch_obj->streams[i].server_stream_id;
   2884                     break;
   2885                 }
   2886             }
   2887 
   2888             for (i=0; i<crop_data.num_of_streams; i++) {
   2889                 if (snapshot_stream_id == crop_data.crop_info[i].stream_id) {
   2890                     if (!crop_data.crop_info[i].crop.left &&
   2891                             !crop_data.crop_info[i].crop.top) {
   2892                         is_crop_1x_found = 1;
   2893                         break;
   2894                     }
   2895                 }
   2896             }
   2897         }
   2898 
   2899         IF_META_AVAILABLE(const cam_buf_divert_info_t, p_divert_info,
   2900                 CAM_INTF_BUF_DIVERT_INFO, metadata) {
   2901             cam_buf_divert_info_t divert_info = *p_divert_info;
   2902             if (divert_info.frame_id >= buf_info->frame_idx) {
   2903                 ch_obj->diverted_frame_id = divert_info.frame_id;
   2904             } else {
   2905                 ch_obj->diverted_frame_id = 0;
   2906             }
   2907         }
   2908 
   2909         if (ch_obj->isZoom1xFrameRequested) {
   2910             if (is_crop_1x_found) {
   2911                 ch_obj->isZoom1xFrameRequested = 0;
   2912                 queue->expected_frame_id = buf_info->frame_idx + 1;
   2913             } else {
   2914                 queue->expected_frame_id += max_future_frame_offset;
   2915                 /* Flush unwanted frames */
   2916                 mm_channel_superbuf_flush_matched(ch_obj, queue);
   2917             }
   2918             goto end;
   2919         }
   2920 
   2921         if (ch_obj->startZSlSnapshotCalled && is_good_frame_idx_range_valid) {
   2922             LOGI("frameID = %d, expected = %d good_frame_idx = %d",
   2923                     buf_info->frame_idx, queue->expected_frame_id,
   2924                     good_frame_idx_range.min_frame_idx);
   2925         }
   2926 
   2927         if (is_prep_snapshot_done_valid) {
   2928             ch_obj->bWaitForPrepSnapshotDone = 0;
   2929             if (prep_snapshot_done_state == NEED_FUTURE_FRAME) {
   2930                 queue->expected_frame_id += max_future_frame_offset;
   2931                 LOGI("PreFlash Done. Need Main Flash");
   2932 
   2933                 mm_channel_superbuf_flush(ch_obj,
   2934                         queue, CAM_STREAM_TYPE_DEFAULT);
   2935 
   2936                 ch_obj->needLEDFlash = TRUE;
   2937             } else {
   2938                 ch_obj->needLEDFlash = FALSE;
   2939             }
   2940         }
   2941         if (is_good_frame_idx_range_valid) {
   2942             queue->expected_frame_id =
   2943                 good_frame_idx_range.min_frame_idx;
   2944             queue->good_frame_id = good_frame_idx_range.min_frame_idx;
   2945             if((ch_obj->needLEDFlash == TRUE) && (ch_obj->burstSnapNum > 1)) {
   2946                 queue->led_on_start_frame_id =
   2947                 good_frame_idx_range.min_frame_idx;
   2948                 queue->led_off_start_frame_id =
   2949                 good_frame_idx_range.max_frame_idx;
   2950                 queue->once = 0;
   2951                 queue->led_on_num_frames =
   2952                   good_frame_idx_range.num_led_on_frames;
   2953                 queue->frame_skip_count = good_frame_idx_range.frame_skip_count;
   2954                 LOGD("Need Flash, expected frame id = %d,"
   2955                         " led_on start = %d, led off start = %d, led on frames = %d ",
   2956                            queue->expected_frame_id, queue->led_on_start_frame_id,
   2957                         queue->led_off_start_frame_id, queue->led_on_num_frames);
   2958             } else {
   2959                 LOGD("No flash, expected frame id = %d ",
   2960                          queue->expected_frame_id);
   2961             }
   2962         } else if ((MM_CHANNEL_BRACKETING_STATE_WAIT_GOOD_FRAME_IDX == ch_obj->bracketingState) &&
   2963                 !is_prep_snapshot_done_valid) {
   2964             /* Flush unwanted frames */
   2965             mm_channel_superbuf_flush_matched(ch_obj, queue);
   2966             queue->expected_frame_id += max_future_frame_offset;
   2967         }
   2968         if (ch_obj->isFlashBracketingEnabled &&
   2969             is_good_frame_idx_range_valid) {
   2970             /* Flash bracketing needs two frames, with & without led flash.
   2971             * in valid range min frame is with led flash and max frame is
   2972             * without led flash */
   2973             queue->expected_frame_id =
   2974                     good_frame_idx_range.min_frame_idx;
   2975             /* max frame is without led flash */
   2976             queue->expected_frame_id_without_led =
   2977                     good_frame_idx_range.max_frame_idx;
   2978             queue->good_frame_id =
   2979                     good_frame_idx_range.min_frame_idx;
   2980         } else if (is_good_frame_idx_range_valid) {
   2981             queue->expected_frame_id =
   2982                     good_frame_idx_range.min_frame_idx;
   2983             ch_obj->bracketingState = MM_CHANNEL_BRACKETING_STATE_ACTIVE;
   2984             queue->good_frame_id =
   2985                     good_frame_idx_range.min_frame_idx;
   2986         }
   2987 
   2988         if (ch_obj->isConfigCapture && is_good_frame_idx_range_valid
   2989                 && (good_frame_idx_range.config_batch_idx < ch_obj->frameConfig.num_batch)) {
   2990 
   2991             LOGI("Frame Config: Expcted ID = %d batch index = %d",
   2992                     good_frame_idx_range.min_frame_idx, good_frame_idx_range.config_batch_idx);
   2993             ch_obj->capture_frame_id[good_frame_idx_range.config_batch_idx] =
   2994                     good_frame_idx_range.min_frame_idx;
   2995 
   2996             if (ch_obj->cur_capture_idx == good_frame_idx_range.config_batch_idx) {
   2997                 queue->expected_frame_id =
   2998                         good_frame_idx_range.min_frame_idx;
   2999             } else {
   3000                 queue->expected_frame_id =
   3001                         ch_obj->capture_frame_id[ch_obj->cur_capture_idx];
   3002             }
   3003             queue->good_frame_id = queue->expected_frame_id;
   3004         }
   3005 
   3006         if ((ch_obj->burstSnapNum > 1) && (ch_obj->needLEDFlash == TRUE)
   3007             && !ch_obj->isFlashBracketingEnabled
   3008             && (MM_CHANNEL_BRACKETING_STATE_OFF == ch_obj->bracketingState)
   3009             && !ch_obj->isConfigCapture) {
   3010             if((buf_info->frame_idx >= queue->led_off_start_frame_id)
   3011                     &&  !queue->once) {
   3012                 LOGD("Burst snap num = %d ",
   3013                          ch_obj->burstSnapNum);
   3014                 // Skip frames from LED OFF frame to get a good frame
   3015                 queue->expected_frame_id = queue->led_off_start_frame_id +
   3016                         queue->frame_skip_count;
   3017                 queue->once = 1;
   3018                 ch_obj->stopZslSnapshot = 1;
   3019                 ch_obj->needLEDFlash = FALSE;
   3020                 LOGD("Reached max led on frames = %d , expected id = %d",
   3021                          buf_info->frame_idx, queue->expected_frame_id);
   3022          }
   3023        }
   3024 
   3025         IF_META_AVAILABLE(const cam_low_light_mode_t, low_light_level,
   3026             CAM_INTF_META_LOW_LIGHT, metadata) {
   3027             ch_obj->needLowLightZSL = *low_light_level;
   3028         }
   3029 
   3030         // For the instant capture case, if AEC settles before expected frame ID from user,
   3031         // reset the expected frame ID to current frame index.
   3032         if (queue->attr.user_expected_frame_id > 0) {
   3033             if (queue->attr.user_expected_frame_id > buf_info->frame_idx) {
   3034                 IF_META_AVAILABLE(const cam_3a_params_t, ae_params,
   3035                     CAM_INTF_META_AEC_INFO, metadata) {
   3036                     if (ae_params->settled) {
   3037                         queue->expected_frame_id = buf_info->frame_idx;
   3038                         // Reset the expected frame ID from HAL to 0
   3039                         queue->attr.user_expected_frame_id = 0;
   3040                         LOGD("AEC settled, reset expected frame ID from user");
   3041                     }
   3042                 }
   3043             } else {
   3044                  // Reset the expected frame ID from HAL to 0 after
   3045                  // current frame index is greater than expected id.
   3046                 queue->attr.user_expected_frame_id = 0;
   3047                 LOGD("reset expected frame ID from user as it reached the bound");
   3048             }
   3049         }
   3050     }
   3051 end:
   3052     return rc;
   3053 }
   3054 
   3055 /*===========================================================================
   3056  * FUNCTION   : mm_channel_superbuf_comp_and_enqueue
   3057  *
   3058  * DESCRIPTION: implementation for matching logic for superbuf
   3059  *
   3060  * PARAMETERS :
   3061  *   @ch_obj  : channel object
   3062  *   @queue   : superbuf queue
   3063  *   @buf_info: new buffer from stream
   3064  *
   3065  * RETURN     : int32_t type of status
   3066  *              0  -- success
   3067  *              -1 -- failure
   3068  *==========================================================================*/
   3069 int32_t mm_channel_superbuf_comp_and_enqueue(
   3070                         mm_channel_t* ch_obj,
   3071                         mm_channel_queue_t *queue,
   3072                         mm_camera_buf_info_t *buf_info)
   3073 {
   3074     cam_node_t* node = NULL;
   3075     struct cam_list *head = NULL;
   3076     struct cam_list *pos = NULL;
   3077     mm_channel_queue_node_t* super_buf = NULL;
   3078     uint8_t buf_s_idx, i, found_super_buf, unmatched_bundles;
   3079     struct cam_list *last_buf, *insert_before_buf, *last_buf_ptr;
   3080 
   3081     LOGD("E");
   3082 
   3083     for (buf_s_idx = 0; buf_s_idx < queue->num_streams; buf_s_idx++) {
   3084         if (buf_info->stream_id == queue->bundled_streams[buf_s_idx]) {
   3085             break;
   3086         }
   3087     }
   3088 
   3089     if (buf_s_idx == queue->num_streams) {
   3090         LOGE("buf from stream (%d) not bundled", buf_info->stream_id);
   3091         return -1;
   3092     }
   3093 
   3094     if(buf_info->frame_idx == 0) {
   3095         mm_channel_qbuf(ch_obj, buf_info->buf);
   3096         return 0;
   3097     }
   3098 
   3099     if (mm_channel_handle_metadata(ch_obj, queue, buf_info) < 0) {
   3100         mm_channel_qbuf(ch_obj, buf_info->buf);
   3101         return -1;
   3102     }
   3103 
   3104     if ((mm_channel_util_seq_comp_w_rollover(buf_info->frame_idx,
   3105             queue->expected_frame_id) < 0) &&
   3106             (mm_channel_validate_super_buf(ch_obj, queue, buf_info) <= 0)) {
   3107         LOGH("incoming buf id(%d) is older than expected buf id(%d), will discard it",
   3108                  buf_info->frame_idx, queue->expected_frame_id);
   3109         mm_channel_qbuf(ch_obj, buf_info->buf);
   3110         return 0;
   3111     }
   3112 
   3113     /* comp */
   3114     pthread_mutex_lock(&queue->que.lock);
   3115     head = &queue->que.head.list;
   3116     /* get the last one in the queue which is possibly having no matching */
   3117     pos = head->next;
   3118 
   3119     found_super_buf = 0;
   3120     unmatched_bundles = 0;
   3121     last_buf = NULL;
   3122     insert_before_buf = NULL;
   3123     last_buf_ptr = NULL;
   3124 
   3125     while (pos != head) {
   3126         node = member_of(pos, cam_node_t, list);
   3127         super_buf = (mm_channel_queue_node_t*)node->data;
   3128 
   3129         if (NULL != super_buf) {
   3130             if (super_buf->matched) {
   3131                 /* find a matched super buf, move to next one */
   3132                 pos = pos->next;
   3133                 continue;
   3134             } else if (( buf_info->frame_idx == super_buf->frame_idx )
   3135                     /*Pick metadata greater than available frameID*/
   3136                     || ((queue->attr.priority == MM_CAMERA_SUPER_BUF_PRIORITY_LOW)
   3137                     && (super_buf->super_buf[buf_s_idx].frame_idx == 0)
   3138                     && (buf_info->buf->stream_type == CAM_STREAM_TYPE_METADATA)
   3139                     && (super_buf->frame_idx < buf_info->frame_idx))
   3140                     /*Pick available metadata closest to frameID*/
   3141                     || ((queue->attr.priority == MM_CAMERA_SUPER_BUF_PRIORITY_LOW)
   3142                     && (buf_info->buf->stream_type != CAM_STREAM_TYPE_METADATA)
   3143                     && (super_buf->super_buf[buf_s_idx].frame_idx == 0)
   3144                     && (super_buf->unmatched_meta_idx > buf_info->frame_idx))){
   3145                 /*super buffer frame IDs matching OR In low priority bundling
   3146                 metadata frameID greater than avialbale super buffer frameID  OR
   3147                 metadata frame closest to incoming frameID will be bundled*/
   3148                 found_super_buf = 1;
   3149                 /* If we are filling into a 'meta only' superbuf, make sure to reset
   3150                 the super_buf frame_idx so that missing streams in this superbuf
   3151                 are filled as per matching frame id logic. Note that, in low priority
   3152                 queue, only meta frame id need not match (closest suffices) but
   3153                 the other streams in this superbuf should have same frame id. */
   3154                 if (super_buf->unmatched_meta_idx > 0) {
   3155                     super_buf->unmatched_meta_idx = 0;
   3156                     super_buf->frame_idx = buf_info->frame_idx;
   3157                 }
   3158                 break;
   3159             } else {
   3160                 unmatched_bundles++;
   3161                 if ( NULL == last_buf ) {
   3162                     if ( super_buf->frame_idx < buf_info->frame_idx ) {
   3163                         last_buf = pos;
   3164                     }
   3165                 }
   3166                 if ( NULL == insert_before_buf ) {
   3167                     if ( super_buf->frame_idx > buf_info->frame_idx ) {
   3168                         insert_before_buf = pos;
   3169                     }
   3170                 }
   3171                 pos = pos->next;
   3172             }
   3173         }
   3174     }
   3175 
   3176     if ( found_super_buf ) {
   3177         if(super_buf->super_buf[buf_s_idx].frame_idx != 0) {
   3178             //This can cause frame drop. We are overwriting same memory.
   3179             pthread_mutex_unlock(&queue->que.lock);
   3180             LOGW("Warning: frame is already in camera ZSL queue");
   3181             mm_channel_qbuf(ch_obj, buf_info->buf);
   3182             return 0;
   3183         }
   3184 
   3185         /*Insert incoming buffer to super buffer*/
   3186         super_buf->super_buf[buf_s_idx] = *buf_info;
   3187 
   3188         /* check if superbuf is all matched */
   3189         super_buf->matched = 1;
   3190         for (i=0; i < super_buf->num_of_bufs; i++) {
   3191             if (super_buf->super_buf[i].frame_idx == 0) {
   3192                 super_buf->matched = 0;
   3193                 break;
   3194             }
   3195         }
   3196 
   3197         if (super_buf->matched) {
   3198             if(ch_obj->isFlashBracketingEnabled) {
   3199                queue->expected_frame_id =
   3200                    queue->expected_frame_id_without_led;
   3201                if (buf_info->frame_idx >=
   3202                        queue->expected_frame_id_without_led) {
   3203                    ch_obj->isFlashBracketingEnabled = FALSE;
   3204                }
   3205             } else {
   3206                queue->expected_frame_id = buf_info->frame_idx
   3207                                           + queue->attr.post_frame_skip;
   3208             }
   3209 
   3210             super_buf->expected_frame = FALSE;
   3211 
   3212             LOGD("curr = %d, skip = %d , Expected Frame ID: %d",
   3213                      buf_info->frame_idx,
   3214                     queue->attr.post_frame_skip, queue->expected_frame_id);
   3215 
   3216             queue->match_cnt++;
   3217             if (ch_obj->bundle.superbuf_queue.attr.enable_frame_sync) {
   3218                 pthread_mutex_lock(&fs_lock);
   3219                 mm_frame_sync_add(buf_info->frame_idx, ch_obj);
   3220                 pthread_mutex_unlock(&fs_lock);
   3221             }
   3222             /* Any older unmatched buffer need to be released */
   3223             if ( last_buf ) {
   3224                 while ( last_buf != pos ) {
   3225                     node = member_of(last_buf, cam_node_t, list);
   3226                     super_buf = (mm_channel_queue_node_t*)node->data;
   3227                     if (NULL != super_buf) {
   3228                         for (i=0; i<super_buf->num_of_bufs; i++) {
   3229                             if (super_buf->super_buf[i].frame_idx != 0) {
   3230                                 mm_channel_qbuf(ch_obj, super_buf->super_buf[i].buf);
   3231                             }
   3232                         }
   3233                         queue->que.size--;
   3234                         last_buf = last_buf->next;
   3235                         cam_list_del_node(&node->list);
   3236                         free(node);
   3237                         free(super_buf);
   3238                     } else {
   3239                         LOGE("Invalid superbuf in queue!");
   3240                         break;
   3241                     }
   3242                 }
   3243             }
   3244         }else {
   3245             if (ch_obj->diverted_frame_id == buf_info->frame_idx) {
   3246                 super_buf->expected_frame = TRUE;
   3247                 ch_obj->diverted_frame_id = 0;
   3248             }
   3249         }
   3250     } else {
   3251         if ((queue->attr.max_unmatched_frames < unmatched_bundles)
   3252                 && ( NULL == last_buf )) {
   3253             /* incoming frame is older than the last bundled one */
   3254             mm_channel_qbuf(ch_obj, buf_info->buf);
   3255         } else {
   3256             last_buf_ptr = last_buf;
   3257 
   3258             /* Loop to remove unmatched frames */
   3259             while ((queue->attr.max_unmatched_frames < unmatched_bundles)
   3260                     && (last_buf_ptr != NULL && last_buf_ptr != pos)) {
   3261                 node = member_of(last_buf_ptr, cam_node_t, list);
   3262                 super_buf = (mm_channel_queue_node_t*)node->data;
   3263                 if (NULL != super_buf && super_buf->expected_frame == FALSE
   3264                         && (&node->list != insert_before_buf)) {
   3265                     for (i=0; i<super_buf->num_of_bufs; i++) {
   3266                         if (super_buf->super_buf[i].frame_idx != 0) {
   3267                             mm_channel_qbuf(ch_obj, super_buf->super_buf[i].buf);
   3268                         }
   3269                     }
   3270                     queue->que.size--;
   3271                     cam_list_del_node(&node->list);
   3272                     free(node);
   3273                     free(super_buf);
   3274                     unmatched_bundles--;
   3275                 }
   3276                 last_buf_ptr = last_buf_ptr->next;
   3277             }
   3278 
   3279             if (queue->attr.max_unmatched_frames < unmatched_bundles) {
   3280                 node = member_of(last_buf, cam_node_t, list);
   3281                 super_buf = (mm_channel_queue_node_t*)node->data;
   3282                 for (i=0; i<super_buf->num_of_bufs; i++) {
   3283                     if (super_buf->super_buf[i].frame_idx != 0) {
   3284                         mm_channel_qbuf(ch_obj, super_buf->super_buf[i].buf);
   3285                     }
   3286                 }
   3287                 queue->que.size--;
   3288                 cam_list_del_node(&node->list);
   3289                 free(node);
   3290                 free(super_buf);
   3291             }
   3292 
   3293             /* insert the new frame at the appropriate position. */
   3294 
   3295             mm_channel_queue_node_t *new_buf = NULL;
   3296             cam_node_t* new_node = NULL;
   3297 
   3298             new_buf = (mm_channel_queue_node_t*)malloc(sizeof(mm_channel_queue_node_t));
   3299             new_node = (cam_node_t*)malloc(sizeof(cam_node_t));
   3300             if (NULL != new_buf && NULL != new_node) {
   3301                 memset(new_buf, 0, sizeof(mm_channel_queue_node_t));
   3302                 memset(new_node, 0, sizeof(cam_node_t));
   3303                 new_node->data = (void *)new_buf;
   3304                 new_buf->num_of_bufs = queue->num_streams;
   3305                 new_buf->super_buf[buf_s_idx] = *buf_info;
   3306                 new_buf->frame_idx = buf_info->frame_idx;
   3307 
   3308                 if ((ch_obj->diverted_frame_id == buf_info->frame_idx)
   3309                         || (buf_info->frame_idx == queue->good_frame_id)) {
   3310                     new_buf->expected_frame = TRUE;
   3311                     ch_obj->diverted_frame_id = 0;
   3312                 }
   3313 
   3314                 /* enqueue */
   3315                 if ( insert_before_buf ) {
   3316                     cam_list_insert_before_node(&new_node->list, insert_before_buf);
   3317                 } else {
   3318                     cam_list_add_tail_node(&new_node->list, &queue->que.head.list);
   3319                 }
   3320                 queue->que.size++;
   3321 
   3322                 if(queue->num_streams == 1) {
   3323                     new_buf->matched = 1;
   3324                     new_buf->expected_frame = FALSE;
   3325                     queue->expected_frame_id = buf_info->frame_idx + queue->attr.post_frame_skip;
   3326                     queue->match_cnt++;
   3327                     if (ch_obj->bundle.superbuf_queue.attr.enable_frame_sync) {
   3328                         pthread_mutex_lock(&fs_lock);
   3329                         mm_frame_sync_add(buf_info->frame_idx, ch_obj);
   3330                         pthread_mutex_unlock(&fs_lock);
   3331                     }
   3332                 }
   3333                 /* In low priority queue, this will become a 'meta only' superbuf. Set the
   3334                 unmatched_frame_idx so that the upcoming stream buffers (other than meta)
   3335                 can be filled into this which are nearest to this idx. */
   3336                 if ((queue->attr.priority == MM_CAMERA_SUPER_BUF_PRIORITY_LOW)
   3337                     && (buf_info->buf->stream_type == CAM_STREAM_TYPE_METADATA)) {
   3338                     new_buf->unmatched_meta_idx = buf_info->frame_idx;
   3339                 }
   3340             } else {
   3341                 /* No memory */
   3342                 if (NULL != new_buf) {
   3343                     free(new_buf);
   3344                 }
   3345                 if (NULL != new_node) {
   3346                     free(new_node);
   3347                 }
   3348                 /* qbuf the new buf since we cannot enqueue */
   3349                 mm_channel_qbuf(ch_obj, buf_info->buf);
   3350             }
   3351         }
   3352     }
   3353 
   3354     pthread_mutex_unlock(&queue->que.lock);
   3355     LOGD("X");
   3356     return 0;
   3357 }
   3358 
   3359 /*===========================================================================
   3360  * FUNCTION   : mm_channel_superbuf_dequeue_internal
   3361  *
   3362  * DESCRIPTION: internal implementation for dequeue from the superbuf queue
   3363  *
   3364  * PARAMETERS :
   3365  *   @queue   : superbuf queue
   3366  *   @matched_only : if dequeued buf should be matched
   3367  *   @ch_obj  : channel object
   3368  *
   3369  * RETURN     : ptr to a node from superbuf queue
   3370  *==========================================================================*/
   3371 mm_channel_queue_node_t* mm_channel_superbuf_dequeue_internal(
   3372         mm_channel_queue_t * queue,
   3373         uint8_t matched_only, mm_channel_t *ch_obj)
   3374 {
   3375     cam_node_t* node = NULL;
   3376     struct cam_list *head = NULL;
   3377     struct cam_list *pos = NULL;
   3378     mm_channel_queue_node_t* super_buf = NULL;
   3379 
   3380     head = &queue->que.head.list;
   3381     pos = head->next;
   3382     if (pos != head) {
   3383         /* get the first node */
   3384         node = member_of(pos, cam_node_t, list);
   3385         super_buf = (mm_channel_queue_node_t*)node->data;
   3386         if ( (NULL != super_buf) &&
   3387              (matched_only == TRUE) &&
   3388              (super_buf->matched == FALSE) ) {
   3389             /* require to dequeue matched frame only, but this superbuf is not matched,
   3390                simply set return ptr to NULL */
   3391             super_buf = NULL;
   3392         }
   3393         if (NULL != super_buf) {
   3394             /* remove from the queue */
   3395             cam_list_del_node(&node->list);
   3396             queue->que.size--;
   3397             if (super_buf->matched == TRUE) {
   3398                 queue->match_cnt--;
   3399                 if (ch_obj->bundle.superbuf_queue.attr.enable_frame_sync) {
   3400                     pthread_mutex_lock(&fs_lock);
   3401                     mm_frame_sync_remove(super_buf->frame_idx);
   3402                     pthread_mutex_unlock(&fs_lock);
   3403                 }
   3404             }
   3405             free(node);
   3406         }
   3407     }
   3408 
   3409     return super_buf;
   3410 }
   3411 
   3412 /*===========================================================================
   3413  * FUNCTION   : mm_channel_superbuf_dequeue_frame_internal
   3414  *
   3415  * DESCRIPTION: internal implementation for dequeue based on frame index
   3416  *                     from the superbuf queue
   3417  *
   3418  * PARAMETERS :
   3419  *   @queue       : superbuf queue
   3420  *   @frame_idx  : frame index to be dequeued
   3421  *
   3422  * RETURN     : ptr to a node from superbuf queue with matched frame index
   3423  *                : NULL if not found
   3424  *==========================================================================*/
   3425 mm_channel_queue_node_t* mm_channel_superbuf_dequeue_frame_internal(
   3426         mm_channel_queue_t *queue, uint32_t frame_idx)
   3427 {
   3428     cam_node_t* node = NULL;
   3429     struct cam_list *head = NULL;
   3430     struct cam_list *pos = NULL;
   3431     mm_channel_queue_node_t* super_buf = NULL;
   3432 
   3433     if (!queue) {
   3434         LOGE("queue is NULL");
   3435         return NULL;
   3436     }
   3437 
   3438     head = &queue->que.head.list;
   3439     pos = head->next;
   3440     LOGL("Searching for match frame %d", frame_idx);
   3441     while ((pos != head) && (pos != NULL)) {
   3442         /* get the first node */
   3443         node = member_of(pos, cam_node_t, list);
   3444         super_buf = (mm_channel_queue_node_t*)node->data;
   3445         if (super_buf && super_buf->matched &&
   3446                 (frame_idx <= super_buf->frame_idx)) {
   3447             /* remove from the queue */
   3448             cam_list_del_node(&node->list);
   3449             queue->que.size--;
   3450             queue->match_cnt--;
   3451             LOGH("Found best match frame %d requested = %d",
   3452                     super_buf->frame_idx, frame_idx);
   3453             free(node);
   3454             break;
   3455         } else {
   3456             super_buf = NULL;
   3457         }
   3458         pos = pos->next;
   3459     }
   3460     return super_buf;
   3461 }
   3462 
   3463 
   3464 /*===========================================================================
   3465  * FUNCTION   : mm_channel_superbuf_dequeue
   3466  *
   3467  * DESCRIPTION: dequeue from the superbuf queue
   3468  *
   3469  * PARAMETERS :
   3470  *   @queue   : superbuf queue
   3471  *   @ch_obj  : channel object
   3472  *
   3473  * RETURN     : ptr to a node from superbuf queue
   3474  *==========================================================================*/
   3475 mm_channel_queue_node_t* mm_channel_superbuf_dequeue(
   3476         mm_channel_queue_t * queue, mm_channel_t *ch_obj)
   3477 {
   3478     mm_channel_queue_node_t* super_buf = NULL;
   3479 
   3480     pthread_mutex_lock(&queue->que.lock);
   3481     super_buf = mm_channel_superbuf_dequeue_internal(queue, TRUE, ch_obj);
   3482     pthread_mutex_unlock(&queue->que.lock);
   3483 
   3484     return super_buf;
   3485 }
   3486 
   3487 /*===========================================================================
   3488  * FUNCTION   : mm_channel_superbuf_bufdone_overflow
   3489  *
   3490  * DESCRIPTION: keep superbuf queue no larger than watermark set by upper layer
   3491  *              via channel attribute
   3492  *
   3493  * PARAMETERS :
   3494  *   @my_obj  : channel object
   3495  *   @queue   : superbuf queue
   3496  *
   3497  * RETURN     : int32_t type of status
   3498  *              0  -- success
   3499  *              -1 -- failure
   3500  *==========================================================================*/
   3501 int32_t mm_channel_superbuf_bufdone_overflow(mm_channel_t* my_obj,
   3502                                              mm_channel_queue_t * queue)
   3503 {
   3504     int32_t rc = 0, i;
   3505     mm_channel_queue_node_t* super_buf = NULL;
   3506     if (MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS == queue->attr.notify_mode) {
   3507         /* for continuous streaming mode, no overflow is needed */
   3508         return 0;
   3509     }
   3510 
   3511     LOGD("before match_cnt=%d, water_mark=%d",
   3512           queue->match_cnt, queue->attr.water_mark);
   3513     /* bufdone overflowed bufs */
   3514     pthread_mutex_lock(&queue->que.lock);
   3515     while (queue->match_cnt > queue->attr.water_mark) {
   3516         super_buf = mm_channel_superbuf_dequeue_internal(queue, TRUE, my_obj);
   3517         if (NULL != super_buf) {
   3518             for (i=0; i<super_buf->num_of_bufs; i++) {
   3519                 if (NULL != super_buf->super_buf[i].buf) {
   3520                     mm_channel_qbuf(my_obj, super_buf->super_buf[i].buf);
   3521                 }
   3522             }
   3523             free(super_buf);
   3524         }
   3525     }
   3526     pthread_mutex_unlock(&queue->que.lock);
   3527     LOGD("after match_cnt=%d, water_mark=%d",
   3528           queue->match_cnt, queue->attr.water_mark);
   3529 
   3530     return rc;
   3531 }
   3532 
   3533 /*===========================================================================
   3534  * FUNCTION   : mm_channel_superbuf_skip
   3535  *
   3536  * DESCRIPTION: depends on the lookback configuration of the channel attribute,
   3537  *              unwanted superbufs will be removed from the superbuf queue.
   3538  *
   3539  * PARAMETERS :
   3540  *   @my_obj  : channel object
   3541  *   @queue   : superbuf queue
   3542  *
   3543  * RETURN     : int32_t type of status
   3544  *              0  -- success
   3545  *              -1 -- failure
   3546  *==========================================================================*/
   3547 int32_t mm_channel_superbuf_skip(mm_channel_t* my_obj,
   3548                                  mm_channel_queue_t * queue)
   3549 {
   3550     int32_t rc = 0, i;
   3551     mm_channel_queue_node_t* super_buf = NULL;
   3552     if (MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS == queue->attr.notify_mode) {
   3553         /* for continuous streaming mode, no skip is needed */
   3554         return 0;
   3555     }
   3556 
   3557     /* bufdone overflowed bufs */
   3558     pthread_mutex_lock(&queue->que.lock);
   3559     while (queue->match_cnt > queue->attr.look_back) {
   3560         super_buf = mm_channel_superbuf_dequeue_internal(queue, TRUE, my_obj);
   3561         if (NULL != super_buf) {
   3562             for (i=0; i<super_buf->num_of_bufs; i++) {
   3563                 if (NULL != super_buf->super_buf[i].buf) {
   3564                     mm_channel_qbuf(my_obj, super_buf->super_buf[i].buf);
   3565                 }
   3566             }
   3567             free(super_buf);
   3568         }
   3569     }
   3570     pthread_mutex_unlock(&queue->que.lock);
   3571 
   3572     return rc;
   3573 }
   3574 
   3575 /*===========================================================================
   3576  * FUNCTION   : mm_channel_send_frame_sync_flush
   3577  *
   3578  * DESCRIPTION: flush the superbuf frame sync queue.
   3579  *
   3580  * PARAMETERS :
   3581  *   @my_obj  : channel object
   3582  *
   3583  * RETURN     : int32_t type of status
   3584  *              0  -- success
   3585  *              -1 -- failure
   3586  *==========================================================================*/
   3587 int32_t mm_channel_send_frame_sync_flush(mm_channel_t* my_obj)
   3588 {
   3589     int32_t rc = 0;
   3590     mm_channel_t *m_obj = my_obj;
   3591 
   3592     if (m_obj->master_ch_obj != NULL) {
   3593         m_obj = m_obj->master_ch_obj;
   3594     }
   3595 
   3596     if (m_obj->frame_sync.is_active) {
   3597         mm_camera_cmdcb_t* cb_node = NULL;
   3598 
   3599         /* send cam_sem_post to wake up cb thread to flush sync queue */
   3600         cb_node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
   3601         if (NULL != cb_node) {
   3602             memset(cb_node, 0, sizeof(mm_camera_cmdcb_t));
   3603             cb_node->cmd_type = MM_CAMERA_CMD_TYPE_FLUSH_QUEUE;
   3604             /* enqueue to cb thread */
   3605             cam_queue_enq(&(m_obj->cb_thread.cmd_queue), cb_node);
   3606             /* wake up cb thread */
   3607             cam_sem_post(&(m_obj->cb_thread.cmd_sem));
   3608         } else {
   3609             LOGE("No memory for mm_camera_node_t");
   3610             rc = -1;
   3611         }
   3612     }
   3613     return rc;
   3614 }
   3615 
   3616 /*===========================================================================
   3617  * FUNCTION   : mm_channel_superbuf_flush
   3618  *
   3619  * DESCRIPTION: flush the superbuf queue.
   3620  *
   3621  * PARAMETERS :
   3622  *   @my_obj  : channel object
   3623  *   @queue   : superbuf queue
   3624  *   @cam_type: flush only particular type (default flushes all)
   3625  *
   3626  * RETURN     : int32_t type of status
   3627  *              0  -- success
   3628  *              -1 -- failure
   3629  *==========================================================================*/
   3630 int32_t mm_channel_superbuf_flush(mm_channel_t* my_obj,
   3631         mm_channel_queue_t * queue, cam_stream_type_t cam_type)
   3632 {
   3633     int32_t rc = 0, i;
   3634     mm_channel_queue_node_t* super_buf = NULL;
   3635     cam_stream_type_t stream_type = CAM_STREAM_TYPE_DEFAULT;
   3636 
   3637     /* bufdone bufs */
   3638     pthread_mutex_lock(&queue->que.lock);
   3639     super_buf = mm_channel_superbuf_dequeue_internal(queue, FALSE, my_obj);
   3640     while (super_buf != NULL) {
   3641         for (i=0; i<super_buf->num_of_bufs; i++) {
   3642             if (NULL != super_buf->super_buf[i].buf) {
   3643                 stream_type = super_buf->super_buf[i].buf->stream_type;
   3644                 if ((CAM_STREAM_TYPE_DEFAULT == cam_type) ||
   3645                         (cam_type == stream_type)) {
   3646                     mm_channel_qbuf(my_obj, super_buf->super_buf[i].buf);
   3647                 }
   3648             }
   3649         }
   3650         free(super_buf);
   3651         super_buf = mm_channel_superbuf_dequeue_internal(queue, FALSE, my_obj);
   3652     }
   3653     pthread_mutex_unlock(&queue->que.lock);
   3654 
   3655     /*Flush Super buffer frame sync queue*/
   3656     mm_channel_send_frame_sync_flush(my_obj);
   3657 
   3658     return rc;
   3659 }
   3660 
   3661 /*===========================================================================
   3662  * FUNCTION   : mm_channel_proc_general_cmd
   3663  *
   3664  * DESCRIPTION: process general command
   3665  *
   3666  * PARAMETERS :
   3667  *   @my_obj  : channel object
   3668  *   @notify_mode : notification mode
   3669  *
   3670  * RETURN     : int32_t type of status
   3671  *              0  -- success
   3672  *              -1 -- failure
   3673  *==========================================================================*/
   3674 int32_t mm_channel_proc_general_cmd(mm_channel_t *my_obj,
   3675                                       mm_camera_generic_cmd_t *p_gen_cmd)
   3676 {
   3677     LOGD("E");
   3678     int32_t rc = 0;
   3679     mm_camera_cmdcb_t* node = NULL;
   3680 
   3681     node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
   3682     if (NULL != node) {
   3683         memset(node, 0, sizeof(mm_camera_cmdcb_t));
   3684         node->u.gen_cmd = *p_gen_cmd;
   3685         node->cmd_type = MM_CAMERA_CMD_TYPE_GENERAL;
   3686 
   3687         /* enqueue to cmd thread */
   3688         cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node);
   3689 
   3690         /* wake up cmd thread */
   3691         cam_sem_post(&(my_obj->cmd_thread.cmd_sem));
   3692     } else {
   3693         LOGE("No memory for mm_camera_node_t");
   3694         rc = -1;
   3695     }
   3696     LOGD("X");
   3697 
   3698     return rc;
   3699 }
   3700 
   3701 /*===========================================================================
   3702  * FUNCTION   : mm_channel_superbuf_flush_matched
   3703  *
   3704  * DESCRIPTION: flush matched buffers from the superbuf queue.
   3705  *
   3706  * PARAMETERS :
   3707  *   @my_obj  : channel object
   3708  *   @queue   : superbuf queue
   3709  *
   3710  * RETURN     : int32_t type of status
   3711  *              0  -- success
   3712  *              -1 -- failure
   3713  *==========================================================================*/
   3714 int32_t mm_channel_superbuf_flush_matched(mm_channel_t* my_obj,
   3715                                   mm_channel_queue_t * queue)
   3716 {
   3717     int32_t rc = 0, i;
   3718     mm_channel_queue_node_t* super_buf = NULL;
   3719 
   3720     /* bufdone bufs */
   3721     pthread_mutex_lock(&queue->que.lock);
   3722     super_buf = mm_channel_superbuf_dequeue_internal(queue, TRUE, my_obj);
   3723     while (super_buf != NULL) {
   3724         for (i=0; i<super_buf->num_of_bufs; i++) {
   3725             if (NULL != super_buf->super_buf[i].buf) {
   3726                 mm_channel_qbuf(my_obj, super_buf->super_buf[i].buf);
   3727             }
   3728         }
   3729         free(super_buf);
   3730         super_buf = mm_channel_superbuf_dequeue_internal(queue, TRUE, my_obj);
   3731     }
   3732     pthread_mutex_unlock(&queue->que.lock);
   3733 
   3734     return rc;
   3735 }
   3736 
   3737 
   3738 /*===========================================================================
   3739  * FUNCTION   : mm_frame_sync_reset
   3740  *
   3741  * DESCRIPTION: Reset Frame sync info
   3742  *
   3743  * RETURN     : None
   3744  *==========================================================================*/
   3745 void mm_frame_sync_reset() {
   3746     memset(&fs, 0x0, sizeof(fs));
   3747     LOGD("Reset Done");
   3748 }
   3749 
   3750 /*===========================================================================
   3751  * FUNCTION   : mm_frame_sync_register_channel
   3752  *
   3753  * DESCRIPTION: Register Channel for frame sync
   3754  *
   3755  * PARAMETERS :
   3756  *   @ch_obj  : channel object
   3757  *
   3758  * RETURN     : int32_t type of status
   3759  *              0  -- success
   3760  *              -1 -- failure
   3761  *==========================================================================*/
   3762 int32_t mm_frame_sync_register_channel(mm_channel_t *ch_obj) {
   3763     // Lock frame sync info
   3764     pthread_mutex_lock(&fs_lock);
   3765     if ((fs.num_cam >= MAX_NUM_CAMERA_PER_BUNDLE) || (!ch_obj)) {
   3766         LOGE("Error!! num cam(%d) is out of range ",
   3767                  fs.num_cam);
   3768         pthread_mutex_unlock(&fs_lock);
   3769         return -1;
   3770     }
   3771     if (fs.num_cam == 0) {
   3772         LOGH("First channel registering!!");
   3773         mm_frame_sync_reset();
   3774     }
   3775     uint8_t i = 0;
   3776     for (i = 0; i < MAX_NUM_CAMERA_PER_BUNDLE; i++) {
   3777         if (fs.ch_obj[i] == NULL) {
   3778             fs.ch_obj[i] = ch_obj;
   3779             fs.cb[i] = ch_obj->bundle.super_buf_notify_cb;
   3780             fs.num_cam++;
   3781             LOGD("DBG_FS index %d", i);
   3782             break;
   3783         }
   3784     }
   3785     if (i >= MAX_NUM_CAMERA_PER_BUNDLE) {
   3786         LOGH("X, DBG_FS Cannot register channel!!");
   3787         pthread_mutex_unlock(&fs_lock);
   3788         return -1;
   3789     }
   3790     LOGH("num_cam %d ", fs.num_cam);
   3791     pthread_mutex_unlock(&fs_lock);
   3792     return 0;
   3793 }
   3794 
   3795 /*===========================================================================
   3796  * FUNCTION   : mm_frame_sync_unregister_channel
   3797  *
   3798  * DESCRIPTION: un-register Channel for frame sync
   3799  *
   3800  * PARAMETERS :
   3801  *   @ch_obj  : channel object
   3802  *
   3803  * RETURN     : int32_t type of status
   3804  *              0  -- success
   3805  *              -1 -- failure
   3806  *==========================================================================*/
   3807 int32_t mm_frame_sync_unregister_channel(mm_channel_t *ch_obj) {
   3808     uint8_t i = 0;
   3809     // Lock frame sync info
   3810     pthread_mutex_lock(&fs_lock);
   3811     if (!fs.num_cam || !ch_obj) {
   3812         LOGH("X, DBG_FS: channel not found  !!");
   3813         // Lock frame sync info
   3814         pthread_mutex_unlock(&fs_lock);
   3815         return -1;
   3816     }
   3817     for (i = 0; i < MAX_NUM_CAMERA_PER_BUNDLE; i++) {
   3818         if (fs.ch_obj[i] == ch_obj) {
   3819             LOGD("found ch_obj at i (%d) ", i);
   3820             break;
   3821         }
   3822     }
   3823     if (i < MAX_NUM_CAMERA_PER_BUNDLE) {
   3824         LOGD("remove channel info ");
   3825         fs.ch_obj[i] = NULL;
   3826         fs.cb[i] = NULL;
   3827         fs.num_cam--;
   3828     } else {
   3829         LOGD("DBG_FS Channel not found ");
   3830     }
   3831     if (fs.num_cam == 0) {
   3832         mm_frame_sync_reset();
   3833     }
   3834     LOGH("X, fs.num_cam %d", fs.num_cam);
   3835     pthread_mutex_unlock(&fs_lock);
   3836     return 0;
   3837 }
   3838 
   3839 
   3840 /*===========================================================================
   3841  * FUNCTION   : mm_frame_sync_add
   3842  *
   3843  * DESCRIPTION: Add frame info into frame sync nodes
   3844  *
   3845  * PARAMETERS :
   3846  *   @frame_id  : frame id to be added
   3847  *   @ch_obj  : channel object
   3848  *
   3849  * RETURN     : int32_t type of status
   3850  *              0  -- success
   3851  *              -1 -- failure
   3852  *==========================================================================*/
   3853 int32_t mm_frame_sync_add(uint32_t frame_id, mm_channel_t *ch_obj) {
   3854 
   3855     LOGD("E, frame id %d ch_obj %p", frame_id, ch_obj);
   3856     if (!frame_id || !ch_obj) {
   3857         LOGH("X : Error, cannot add sync frame !!");
   3858         return -1;
   3859     }
   3860 
   3861     int8_t ch_idx = -1;
   3862     uint8_t i = 0;
   3863     for (i = 0; i < MAX_NUM_CAMERA_PER_BUNDLE; i++) {
   3864         if (fs.ch_obj[i] == ch_obj) {
   3865             ch_idx = i;
   3866             LOGD("ch id %d ", ch_idx);
   3867             break;
   3868         }
   3869     }
   3870     if (ch_idx < 0) {
   3871         LOGH("X : DBG_FS ch not found!!");
   3872         return -1;
   3873     }
   3874     int8_t index = mm_frame_sync_find_frame_index(frame_id);
   3875     if ((index >= 0) && (index < MM_CAMERA_FRAME_SYNC_NODES)) {
   3876         fs.node[index].frame_valid[ch_idx] = 1;
   3877     } else if (index < 0) {
   3878         if (fs.pos >= MM_CAMERA_FRAME_SYNC_NODES) {
   3879             fs.pos = 0;
   3880         }
   3881         index = fs.pos;
   3882         memset(&fs.node[index], 0x00, sizeof(mm_channel_sync_node_t));
   3883         fs.pos++;
   3884         fs.node[index].frame_idx = frame_id;
   3885         fs.node[index].frame_valid[ch_idx] = 1;
   3886         if (fs.num_cam == 1) {
   3887             LOGD("Single camera frame %d , matched ", frame_id);
   3888             fs.node[index].matched = 1;
   3889         }
   3890     }
   3891     uint8_t frames_valid = 0;
   3892     if (!fs.node[index].matched) {
   3893         for (i = 0; i < MAX_NUM_CAMERA_PER_BUNDLE; i++) {
   3894             if (fs.node[index].frame_valid[i]) {
   3895                 frames_valid++;
   3896             }
   3897         }
   3898         if (frames_valid == fs.num_cam) {
   3899             fs.node[index].matched = 1;
   3900             LOGD("dual camera frame %d , matched ",
   3901                      frame_id);
   3902         }
   3903     }
   3904     return 0;
   3905 }
   3906 
   3907 /*===========================================================================
   3908  * FUNCTION   : mm_frame_sync_remove
   3909  *
   3910  * DESCRIPTION: Remove frame info from frame sync nodes
   3911  *
   3912  * PARAMETERS :
   3913  *   @frame_id  : frame id to be removed
   3914  *
   3915  * RETURN     : int32_t type of status
   3916  *              0  -- success
   3917  *              -1 -- failure
   3918  *==========================================================================*/
   3919 int32_t mm_frame_sync_remove(uint32_t frame_id) {
   3920     int8_t index = -1;
   3921 
   3922     LOGD("E, frame_id %d", frame_id);
   3923     if (!frame_id) {
   3924         LOGE("X, DBG_FS frame id invalid");
   3925         return -1;
   3926     }
   3927 
   3928     index = mm_frame_sync_find_frame_index(frame_id);
   3929     if ((index >= 0) && (index < MM_CAMERA_FRAME_SYNC_NODES)) {
   3930         LOGD("Removing sync frame %d", frame_id);
   3931         memset(&fs.node[index], 0x00, sizeof(mm_channel_sync_node_t));
   3932     }
   3933     LOGD("X ");
   3934     return 0;
   3935 }
   3936 
   3937 /*===========================================================================
   3938  * FUNCTION   : mm_frame_sync_find_matched
   3939  *
   3940  * DESCRIPTION: Find  a matched sync frame from the node array
   3941  *
   3942  * PARAMETERS :
   3943  *   @oldest  : If enabled, find oldest matched frame.,
   3944  *                  If not enabled, get the first matched frame found
   3945  *
   3946  * RETURN     : unt32_t type of status
   3947  *              0  -- If no matched frames found
   3948  *              frame index: inf matched frame found
   3949  *==========================================================================*/
   3950 uint32_t mm_frame_sync_find_matched(uint8_t oldest) {
   3951     LOGH("E, oldest %d ", oldest);
   3952     uint8_t i = 0;
   3953     uint32_t frame_idx = 0;
   3954     uint32_t curr_frame_idx = 0;
   3955     for (i = 0; i < MM_CAMERA_FRAME_SYNC_NODES; i++) {
   3956         if (fs.node[i].matched) {
   3957             curr_frame_idx = fs.node[i].frame_idx;
   3958             if (!frame_idx) {
   3959                 frame_idx = curr_frame_idx;
   3960             }
   3961             if (!oldest) {
   3962                 break;
   3963             } else if (frame_idx > curr_frame_idx) {
   3964                 frame_idx = curr_frame_idx;
   3965             }
   3966         }
   3967     }
   3968     LOGH("X, oldest %d frame idx %d", oldest, frame_idx);
   3969     return frame_idx;
   3970 }
   3971 
   3972 /*===========================================================================
   3973  * FUNCTION   : mm_frame_sync_find_frame_index
   3974  *
   3975  * DESCRIPTION: Find sync frame index if present
   3976  *
   3977  * PARAMETERS :
   3978  *   @frame_id  : frame id to be searched
   3979  *
   3980  * RETURN     : int8_t type of status
   3981  *              -1  -- If desired frame not found
   3982  *              index: node array index if frame is found
   3983  *==========================================================================*/
   3984 int8_t mm_frame_sync_find_frame_index(uint32_t frame_id) {
   3985 
   3986     LOGD("E, frame_id %d", frame_id);
   3987     int8_t index = -1, i = 0;
   3988     for (i = 0; i < MM_CAMERA_FRAME_SYNC_NODES; i++) {
   3989         if (fs.node[i].frame_idx == frame_id) {
   3990             index = i;
   3991             break;
   3992         }
   3993     }
   3994     LOGD("X index :%d", index);
   3995     return index;
   3996 }
   3997 
   3998 /*===========================================================================
   3999  * FUNCTION   : mm_frame_sync_lock_queues
   4000  *
   4001  * DESCRIPTION: Lock all channel queues present in node info
   4002  *
   4003  * RETURN     : None
   4004  *==========================================================================*/
   4005 void mm_frame_sync_lock_queues() {
   4006     uint8_t j = 0;
   4007     LOGD("E ");
   4008     for (j = 0; j < MAX_NUM_CAMERA_PER_BUNDLE; j++) {
   4009         if (fs.ch_obj[j]) {
   4010             mm_channel_queue_t *ch_queue =
   4011                     &fs.ch_obj[j]->bundle.superbuf_queue;
   4012             if (ch_queue) {
   4013                 pthread_mutex_lock(&ch_queue->que.lock);
   4014                 LOGL("Done locking fs.ch_obj[%d] ", j);
   4015             }
   4016         }
   4017     }
   4018     pthread_mutex_lock(&fs_lock);
   4019     LOGD("X ");
   4020 }
   4021 
   4022 /*===========================================================================
   4023  * FUNCTION   : mm_frame_sync_unlock_queues
   4024  *
   4025  * DESCRIPTION: Unlock all channel queues
   4026  *
   4027  * RETURN     : None
   4028  *==========================================================================*/
   4029 void mm_frame_sync_unlock_queues() {
   4030     // Unlock all queues
   4031     uint8_t j = 0;
   4032     LOGD("E ");
   4033     pthread_mutex_unlock(&fs_lock);
   4034     LOGL("Done unlocking fs ");
   4035     for (j = 0; j < MAX_NUM_CAMERA_PER_BUNDLE; j++) {
   4036         if (fs.ch_obj[j]) {
   4037             mm_channel_queue_t *ch_queue =
   4038                     &fs.ch_obj[j]->bundle.superbuf_queue;
   4039             if (ch_queue) {
   4040                 pthread_mutex_unlock(&ch_queue->que.lock);
   4041                 LOGL("Done unlocking fs.ch_obj[%d] ", j);
   4042             }
   4043         }
   4044     }
   4045     LOGD("X ");
   4046 }
   4047 
   4048 /*===========================================================================
   4049  * FUNCTION   : mm_channel_node_qbuf
   4050  *
   4051  * DESCRIPTION: qbuf all buffers in a node
   4052  *
   4053  * PARAMETERS :
   4054  *   @ch_obj  : Channel info
   4055  *   @node    : node to qbuf
   4056  *
   4057  * RETURN     : None
   4058  *==========================================================================*/
   4059 void mm_channel_node_qbuf(mm_channel_t *ch_obj, mm_channel_queue_node_t *node) {
   4060     uint8_t i;
   4061     if (!ch_obj || !node) {
   4062         return;
   4063     }
   4064     for (i = 0; i < node->num_of_bufs; i++) {
   4065         mm_channel_qbuf(ch_obj, node->super_buf[i].buf);
   4066     }
   4067     return;
   4068 }
   4069