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