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