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