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