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