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