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