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