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