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