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