1 /* Copyright (c) 2012-2014, 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 #include <pthread.h>
31 #include <errno.h>
32 #include <sys/ioctl.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <fcntl.h>
36 #include <poll.h>
37 #include <cam_semaphore.h>
38
39 #include "mm_camera_dbg.h"
40 #include "mm_camera_interface.h"
41 #include "mm_camera.h"
42
43 extern mm_camera_obj_t* mm_camera_util_get_camera_by_handler(uint32_t cam_handler);
44 extern mm_channel_t * mm_camera_util_get_channel_by_handler(mm_camera_obj_t * cam_obj,
45 uint32_t handler);
46
47 /* internal function declare goes here */
48 int32_t mm_channel_qbuf(mm_channel_t *my_obj,
49 mm_camera_buf_def_t *buf);
50 int32_t mm_channel_init(mm_channel_t *my_obj,
51 mm_camera_channel_attr_t *attr,
52 mm_camera_buf_notify_t channel_cb,
53 void *userdata);
54 void mm_channel_release(mm_channel_t *my_obj);
55 uint32_t mm_channel_add_stream(mm_channel_t *my_obj);
56 int32_t mm_channel_del_stream(mm_channel_t *my_obj,
57 uint32_t stream_id);
58 int32_t mm_channel_config_stream(mm_channel_t *my_obj,
59 uint32_t stream_id,
60 mm_camera_stream_config_t *config);
61 int32_t mm_channel_get_bundle_info(mm_channel_t *my_obj,
62 cam_bundle_config_t *bundle_info);
63 int32_t mm_channel_start(mm_channel_t *my_obj);
64 int32_t mm_channel_stop(mm_channel_t *my_obj);
65 int32_t mm_channel_request_super_buf(mm_channel_t *my_obj,
66 uint32_t num_buf_requested, uint32_t num_reto_buf_requested);
67 int32_t mm_channel_cancel_super_buf_request(mm_channel_t *my_obj);
68 int32_t mm_channel_flush_super_buf_queue(mm_channel_t *my_obj,
69 uint32_t frame_idx);
70 int32_t mm_channel_config_notify_mode(mm_channel_t *my_obj,
71 mm_camera_super_buf_notify_mode_t notify_mode);
72 int32_t mm_channel_start_zsl_snapshot(mm_channel_t *my_obj);
73 int32_t mm_channel_stop_zsl_snapshot(mm_channel_t *my_obj);
74 int32_t mm_channel_superbuf_flush(mm_channel_t* my_obj, mm_channel_queue_t * queue);
75 int32_t mm_channel_set_stream_parm(mm_channel_t *my_obj,
76 mm_evt_paylod_set_get_stream_parms_t *payload);
77 int32_t mm_channel_get_stream_parm(mm_channel_t *my_obj,
78 mm_evt_paylod_set_get_stream_parms_t *payload);
79 int32_t mm_channel_do_stream_action(mm_channel_t *my_obj,
80 mm_evt_paylod_do_stream_action_t *payload);
81 int32_t mm_channel_map_stream_buf(mm_channel_t *my_obj,
82 mm_evt_paylod_map_stream_buf_t *payload);
83 int32_t mm_channel_unmap_stream_buf(mm_channel_t *my_obj,
84 mm_evt_paylod_unmap_stream_buf_t *payload);
85
86 /* state machine function declare */
87 int32_t mm_channel_fsm_fn_notused(mm_channel_t *my_obj,
88 mm_channel_evt_type_t evt,
89 void * in_val,
90 void * out_val);
91 int32_t mm_channel_fsm_fn_stopped(mm_channel_t *my_obj,
92 mm_channel_evt_type_t evt,
93 void * in_val,
94 void * out_val);
95 int32_t mm_channel_fsm_fn_active(mm_channel_t *my_obj,
96 mm_channel_evt_type_t evt,
97 void * in_val,
98 void * out_val);
99 int32_t mm_channel_fsm_fn_paused(mm_channel_t *my_obj,
100 mm_channel_evt_type_t evt,
101 void * in_val,
102 void * out_val);
103
104 /* channel super queue functions */
105 int32_t mm_channel_superbuf_queue_init(mm_channel_queue_t * queue);
106 int32_t mm_channel_superbuf_queue_deinit(mm_channel_queue_t * queue);
107 int32_t mm_channel_superbuf_comp_and_enqueue(mm_channel_t *ch_obj,
108 mm_channel_queue_t * queue,
109 mm_camera_buf_info_t *buf);
110 mm_channel_queue_node_t* mm_channel_superbuf_dequeue(mm_channel_queue_t * queue);
111 int32_t mm_channel_superbuf_bufdone_overflow(mm_channel_t *my_obj,
112 mm_channel_queue_t *queue);
113 int32_t mm_channel_superbuf_skip(mm_channel_t *my_obj,
114 mm_channel_queue_t *queue);
115
116 static int32_t mm_channel_proc_general_cmd(mm_channel_t *my_obj,
117 mm_camera_generic_cmd_t *p_gen_cmd);
118 int32_t mm_channel_superbuf_flush_matched(mm_channel_t* my_obj,
119 mm_channel_queue_t * queue);
120 /*===========================================================================
121 * FUNCTION : mm_channel_util_get_stream_by_handler
122 *
123 * DESCRIPTION: utility function to get a stream object from its handle
124 *
125 * PARAMETERS :
126 * @cam_obj: ptr to a channel object
127 * @handler: stream handle
128 *
129 * RETURN : ptr to a stream object.
130 * NULL if failed.
131 *==========================================================================*/
mm_channel_util_get_stream_by_handler(mm_channel_t * ch_obj,uint32_t handler)132 mm_stream_t * mm_channel_util_get_stream_by_handler(
133 mm_channel_t * ch_obj,
134 uint32_t handler)
135 {
136 int i;
137 mm_stream_t *s_obj = NULL;
138 for(i = 0; i < MAX_STREAM_NUM_IN_BUNDLE; i++) {
139 if ((MM_STREAM_STATE_NOTUSED != ch_obj->streams[i].state) &&
140 (handler == ch_obj->streams[i].my_hdl)) {
141 s_obj = &ch_obj->streams[i];
142 break;
143 }
144 }
145 return s_obj;
146 }
147
148 /*===========================================================================
149 * FUNCTION : mm_channel_dispatch_super_buf
150 *
151 * DESCRIPTION: dispatch super buffer of bundle to registered user
152 *
153 * PARAMETERS :
154 * @cmd_cb : ptr storing matched super buf information
155 * @userdata: user data ptr
156 *
157 * RETURN : none
158 *==========================================================================*/
mm_channel_dispatch_super_buf(mm_camera_cmdcb_t * cmd_cb,void * user_data)159 static void mm_channel_dispatch_super_buf(mm_camera_cmdcb_t *cmd_cb,
160 void* user_data)
161 {
162 mm_camera_cmd_thread_name("mm_cam_cb");
163 mm_channel_t * my_obj = (mm_channel_t *)user_data;
164
165 if (NULL == my_obj) {
166 return;
167 }
168
169 if (MM_CAMERA_CMD_TYPE_SUPER_BUF_DATA_CB != cmd_cb->cmd_type) {
170 CDBG_ERROR("%s: Wrong cmd_type (%d) for super buf dataCB",
171 __func__, cmd_cb->cmd_type);
172 return;
173 }
174
175 if (my_obj->bundle.super_buf_notify_cb) {
176 my_obj->bundle.super_buf_notify_cb(&cmd_cb->u.superbuf, my_obj->bundle.user_data);
177 }
178 }
179
180 /*===========================================================================
181 * FUNCTION : mm_channel_process_stream_buf
182 *
183 * DESCRIPTION: handle incoming buffer from stream in a bundle. In this function,
184 * matching logic will be performed on incoming stream frames.
185 * Will depends on the bundle attribute, either storing matched frames
186 * in the superbuf queue, or sending matched superbuf frames to upper
187 * layer through registered callback.
188 *
189 * PARAMETERS :
190 * @cmd_cb : ptr storing matched super buf information
191 * @userdata: user data ptr
192 *
193 * RETURN : none
194 *==========================================================================*/
mm_channel_process_stream_buf(mm_camera_cmdcb_t * cmd_cb,void * user_data)195 static void mm_channel_process_stream_buf(mm_camera_cmdcb_t * cmd_cb,
196 void *user_data)
197 {
198 mm_camera_cmd_thread_name("mm_cam_cmd");
199 mm_camera_super_buf_notify_mode_t notify_mode;
200 mm_channel_queue_node_t *node = NULL;
201 mm_channel_t *ch_obj = (mm_channel_t *)user_data;
202 if (NULL == ch_obj) {
203 return;
204 }
205 if (MM_CAMERA_CMD_TYPE_DATA_CB == cmd_cb->cmd_type) {
206 /* comp_and_enqueue */
207 mm_channel_superbuf_comp_and_enqueue(
208 ch_obj,
209 &ch_obj->bundle.superbuf_queue,
210 &cmd_cb->u.buf);
211 } else if (MM_CAMERA_CMD_TYPE_REQ_DATA_CB == cmd_cb->cmd_type) {
212 /* skip frames if needed */
213 ch_obj->pending_cnt = cmd_cb->u.req_buf.num_buf_requested;
214 ch_obj->pending_retro_cnt = cmd_cb->u.req_buf.num_retro_buf_requested;
215 ch_obj->bWaitForPrepSnapshotDone = 0;
216
217 ALOGV("%s:[ZSL Retro] pending cnt (%d), retro count (%d)",
218 __func__, ch_obj->pending_cnt, ch_obj->pending_retro_cnt);
219 if (!ch_obj->pending_cnt || (ch_obj->pending_retro_cnt > ch_obj->pending_cnt)) {
220 ch_obj->pending_retro_cnt = ch_obj->pending_cnt;
221 }
222 if (ch_obj->pending_retro_cnt > 0) {
223 ALOGV("%s: [ZSL Retro] Resetting need Led Flash!!!",
224 __func__);
225 ch_obj->needLEDFlash = 0;
226 }
227 ch_obj->stopZslSnapshot = 0;
228 ch_obj->unLockAEC = 0;
229
230 mm_channel_superbuf_skip(ch_obj, &ch_obj->bundle.superbuf_queue);
231
232 } else if (MM_CAMERA_CMD_TYPE_START_ZSL == cmd_cb->cmd_type) {
233 ch_obj->manualZSLSnapshot = TRUE;
234 mm_camera_start_zsl_snapshot(ch_obj->cam_obj);
235 } else if (MM_CAMERA_CMD_TYPE_STOP_ZSL == cmd_cb->cmd_type) {
236 ch_obj->manualZSLSnapshot = FALSE;
237 mm_camera_stop_zsl_snapshot(ch_obj->cam_obj);
238 } else if (MM_CAMERA_CMD_TYPE_CONFIG_NOTIFY == cmd_cb->cmd_type) {
239 ch_obj->bundle.superbuf_queue.attr.notify_mode = cmd_cb->u.notify_mode;
240 } else if (MM_CAMERA_CMD_TYPE_FLUSH_QUEUE == cmd_cb->cmd_type) {
241 ch_obj->bundle.superbuf_queue.expected_frame_id = cmd_cb->u.frame_idx;
242 mm_channel_superbuf_flush(ch_obj, &ch_obj->bundle.superbuf_queue);
243 return;
244 } else if (MM_CAMERA_CMD_TYPE_GENERAL == cmd_cb->cmd_type) {
245 CDBG_HIGH("%s:%d] MM_CAMERA_CMD_TYPE_GENERAL", __func__, __LINE__);
246 switch (cmd_cb->u.gen_cmd.type) {
247 case MM_CAMERA_GENERIC_CMD_TYPE_AE_BRACKETING:
248 case MM_CAMERA_GENERIC_CMD_TYPE_AF_BRACKETING: {
249 int8_t start = cmd_cb->u.gen_cmd.payload[0];
250 CDBG_HIGH("%s:%d] MM_CAMERA_GENERIC_CMDTYPE_AF_BRACKETING %d",
251 __func__, __LINE__, start);
252 mm_channel_superbuf_flush(ch_obj,
253 &ch_obj->bundle.superbuf_queue);
254
255 if (start) {
256 CDBG_HIGH("%s:%d] need AE bracketing, start zsl snapshot",
257 __func__, __LINE__);
258 ch_obj->need3ABracketing = TRUE;
259 } else {
260 ch_obj->need3ABracketing = FALSE;
261 }
262 }
263 break;
264 case MM_CAMERA_GENERIC_CMD_TYPE_FLASH_BRACKETING: {
265 int8_t start = cmd_cb->u.gen_cmd.payload[0];
266 CDBG_HIGH("%s:%d] MM_CAMERA_GENERIC_CMDTYPE_FLASH_BRACKETING %d",
267 __func__, __LINE__, start);
268 if (start) {
269 CDBG_HIGH("%s:%d] need flash bracketing",
270 __func__, __LINE__);
271 ch_obj->isFlashBracketingEnabled = TRUE;
272 } else {
273 ch_obj->isFlashBracketingEnabled = FALSE;
274 }
275 }
276 break;
277 case MM_CAMERA_GENERIC_CMD_TYPE_ZOOM_1X: {
278 int8_t start = cmd_cb->u.gen_cmd.payload[0];
279 CDBG_HIGH("%s:%d] MM_CAMERA_GENERIC_CMD_TYPE_ZOOM_1X %d",
280 __func__, __LINE__, start);
281 if (start) {
282 CDBG_HIGH("%s:%d] need zoom 1x frame",
283 __func__, __LINE__);
284 ch_obj->isZoom1xFrameRequested = TRUE;
285 } else {
286 ch_obj->isZoom1xFrameRequested = FALSE;
287 }
288 }
289 break;
290 default:
291 CDBG_ERROR("%s:%d] Error: Invalid command", __func__, __LINE__);
292 break;
293 }
294 }
295 notify_mode = ch_obj->bundle.superbuf_queue.attr.notify_mode;
296
297 if ((ch_obj->pending_cnt > 0)
298 && (ch_obj->needLEDFlash == TRUE || ch_obj->need3ABracketing == TRUE)
299 && (ch_obj->manualZSLSnapshot == FALSE)
300 && ch_obj->startZSlSnapshotCalled == FALSE) {
301
302 CDBG_HIGH("%s: need flash, start zsl snapshot", __func__);
303 mm_camera_start_zsl_snapshot(ch_obj->cam_obj);
304 ch_obj->startZSlSnapshotCalled = TRUE;
305 ch_obj->burstSnapNum = ch_obj->pending_cnt;
306 ch_obj->bWaitForPrepSnapshotDone = 0;
307 ch_obj->needLEDFlash = FALSE;
308 } else if (((ch_obj->pending_cnt == 0) || (ch_obj->stopZslSnapshot == 1))
309 && (ch_obj->manualZSLSnapshot == FALSE)
310 && (ch_obj->startZSlSnapshotCalled == TRUE)) {
311 CDBG_HIGH("%s: Got picture cancelled, stop zsl snapshot", __func__);
312 mm_camera_stop_zsl_snapshot(ch_obj->cam_obj);
313 // Unlock AEC
314 ch_obj->startZSlSnapshotCalled = FALSE;
315 ch_obj->needLEDFlash = FALSE;
316 ch_obj->burstSnapNum = 0;
317 ch_obj->stopZslSnapshot = 0;
318 ch_obj->bWaitForPrepSnapshotDone = 0;
319 ch_obj->unLockAEC = 1;
320 ch_obj->need3ABracketing = FALSE;
321 }
322 /* bufdone for overflowed bufs */
323 mm_channel_superbuf_bufdone_overflow(ch_obj, &ch_obj->bundle.superbuf_queue);
324
325 CDBG("%s: Super Buffer received, pending_cnt=%d",
326 __func__, ch_obj->pending_cnt);
327 /* dispatch frame if pending_cnt>0 or is in continuous streaming mode */
328
329 CDBG("%s: [ZSL Retro] Out loop pending cnt (%d), retro count (%d)",
330 __func__, ch_obj->pending_cnt, ch_obj->pending_retro_cnt);
331 while (((ch_obj->pending_cnt > 0) ||
332 (MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS == notify_mode)) &&
333 (!ch_obj->bWaitForPrepSnapshotDone)) {
334
335 CDBG("%s: [ZSL Retro] In loop pending cnt (%d), retro count (%d)",
336 __func__, ch_obj->pending_cnt, ch_obj->pending_retro_cnt);
337 /* dequeue */
338 node = mm_channel_superbuf_dequeue(&ch_obj->bundle.superbuf_queue);
339 if (NULL != node) {
340 uint32_t bReady = 0;
341 /* decrease pending_cnt */
342 if (MM_CAMERA_SUPER_BUF_NOTIFY_BURST == notify_mode) {
343 ch_obj->pending_cnt--;
344 if (ch_obj->pending_retro_cnt > 0) {
345 if (ch_obj->pending_retro_cnt == 1) {
346 ch_obj->bWaitForPrepSnapshotDone = 1;
347 // Retro Snaps are done..
348 bReady = 1;
349 }
350 ch_obj->pending_retro_cnt--;
351 }
352 CDBG("%s: [ZSL Retro] Super Buffer received, Call client callback,"
353 "pending_cnt=%d", __func__, ch_obj->pending_cnt);
354
355 if (((ch_obj->pending_cnt == 0) ||
356 (ch_obj->stopZslSnapshot == 1)) &&
357 (ch_obj->manualZSLSnapshot == FALSE) &&
358 ch_obj->startZSlSnapshotCalled == TRUE) {
359 CDBG("%s: [ZSL Retro] Received all frames requested, stop zsl snapshot", __func__);
360 mm_camera_stop_zsl_snapshot(ch_obj->cam_obj);
361 ch_obj->startZSlSnapshotCalled = FALSE;
362 ch_obj->burstSnapNum = 0;
363 ch_obj->stopZslSnapshot = 0;
364 ch_obj->unLockAEC = 1;
365
366 }
367 }
368 /* dispatch superbuf */
369 if (NULL != ch_obj->bundle.super_buf_notify_cb) {
370 uint8_t i;
371 mm_camera_cmdcb_t* cb_node = NULL;
372
373 CDBG("%s: Send superbuf to HAL, pending_cnt=%d",
374 __func__, ch_obj->pending_cnt);
375
376 /* send cam_sem_post to wake up cb thread to dispatch super buffer */
377 cb_node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
378 if (NULL != cb_node) {
379 memset(cb_node, 0, sizeof(mm_camera_cmdcb_t));
380 cb_node->cmd_type = MM_CAMERA_CMD_TYPE_SUPER_BUF_DATA_CB;
381 cb_node->u.superbuf.num_bufs = node->num_of_bufs;
382 for (i=0; i<node->num_of_bufs; i++) {
383 cb_node->u.superbuf.bufs[i] = node->super_buf[i].buf;
384 }
385 cb_node->u.superbuf.camera_handle = ch_obj->cam_obj->my_hdl;
386 cb_node->u.superbuf.ch_id = ch_obj->my_hdl;
387 cb_node->u.superbuf.bReadyForPrepareSnapshot = bReady;
388 if (ch_obj->unLockAEC == 1) {
389 cb_node->u.superbuf.bUnlockAEC = 1;
390 ALOGE("%s:[ZSL Retro] Unlocking AEC", __func__);
391 ch_obj->unLockAEC = 0;
392 }
393
394 /* enqueue to cb thread */
395 cam_queue_enq(&(ch_obj->cb_thread.cmd_queue), cb_node);
396 /* wake up cb thread */
397 cam_sem_post(&(ch_obj->cb_thread.cmd_sem));
398 } else {
399 CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__);
400 /* buf done with the nonuse super buf */
401 for (i=0; i<node->num_of_bufs; i++) {
402 mm_channel_qbuf(ch_obj, node->super_buf[i].buf);
403 }
404 }
405 } else {
406 /* buf done with the nonuse super buf */
407 uint8_t i;
408 for (i=0; i<node->num_of_bufs; i++) {
409 mm_channel_qbuf(ch_obj, node->super_buf[i].buf);
410 }
411 }
412 free(node);
413 } else {
414 /* no superbuf avail, break the loop */
415 break;
416 }
417 }
418 }
419
420 /*===========================================================================
421 * FUNCTION : mm_channel_fsm_fn
422 *
423 * DESCRIPTION: channel finite state machine entry function. Depends on channel
424 * state, incoming event will be handled differently.
425 *
426 * PARAMETERS :
427 * @my_obj : ptr to a channel object
428 * @evt : channel event to be processed
429 * @in_val : input event payload. Can be NULL if not needed.
430 * @out_val : output payload, Can be NULL if not needed.
431 *
432 * RETURN : int32_t type of status
433 * 0 -- success
434 * -1 -- failure
435 *==========================================================================*/
mm_channel_fsm_fn(mm_channel_t * my_obj,mm_channel_evt_type_t evt,void * in_val,void * out_val)436 int32_t mm_channel_fsm_fn(mm_channel_t *my_obj,
437 mm_channel_evt_type_t evt,
438 void * in_val,
439 void * out_val)
440 {
441 int32_t rc = -1;
442
443 CDBG("%s : E state = %d", __func__, my_obj->state);
444 switch (my_obj->state) {
445 case MM_CHANNEL_STATE_NOTUSED:
446 rc = mm_channel_fsm_fn_notused(my_obj, evt, in_val, out_val);
447 break;
448 case MM_CHANNEL_STATE_STOPPED:
449 rc = mm_channel_fsm_fn_stopped(my_obj, evt, in_val, out_val);
450 break;
451 case MM_CHANNEL_STATE_ACTIVE:
452 rc = mm_channel_fsm_fn_active(my_obj, evt, in_val, out_val);
453 break;
454 case MM_CHANNEL_STATE_PAUSED:
455 rc = mm_channel_fsm_fn_paused(my_obj, evt, in_val, out_val);
456 break;
457 default:
458 CDBG("%s: Not a valid state (%d)", __func__, my_obj->state);
459 break;
460 }
461
462 /* unlock ch_lock */
463 pthread_mutex_unlock(&my_obj->ch_lock);
464 CDBG("%s : X rc = %d", __func__, rc);
465 return rc;
466 }
467
468 /*===========================================================================
469 * FUNCTION : mm_channel_fsm_fn_notused
470 *
471 * DESCRIPTION: channel finite state machine function to handle event
472 * in NOT_USED state.
473 *
474 * PARAMETERS :
475 * @my_obj : ptr to a channel object
476 * @evt : channel event to be processed
477 * @in_val : input event payload. Can be NULL if not needed.
478 * @out_val : output payload, Can be NULL if not needed.
479 *
480 * RETURN : int32_t type of status
481 * 0 -- success
482 * -1 -- failure
483 *==========================================================================*/
mm_channel_fsm_fn_notused(mm_channel_t * my_obj,mm_channel_evt_type_t evt,void * in_val,void * out_val)484 int32_t mm_channel_fsm_fn_notused(mm_channel_t *my_obj,
485 mm_channel_evt_type_t evt,
486 void * in_val,
487 void * out_val)
488 {
489 int32_t rc = -1;
490
491 switch (evt) {
492 default:
493 CDBG_ERROR("%s: invalid state (%d) for evt (%d), in(%p), out(%p)",
494 __func__, my_obj->state, evt, in_val, out_val);
495 break;
496 }
497
498 return rc;
499 }
500
501 /*===========================================================================
502 * FUNCTION : mm_channel_fsm_fn_stopped
503 *
504 * DESCRIPTION: channel finite state machine function to handle event
505 * in STOPPED state.
506 *
507 * PARAMETERS :
508 * @my_obj : ptr to a channel object
509 * @evt : channel event to be processed
510 * @in_val : input event payload. Can be NULL if not needed.
511 * @out_val : output payload, Can be NULL if not needed.
512 *
513 * RETURN : int32_t type of status
514 * 0 -- success
515 * -1 -- failure
516 *==========================================================================*/
mm_channel_fsm_fn_stopped(mm_channel_t * my_obj,mm_channel_evt_type_t evt,void * in_val,void * out_val)517 int32_t mm_channel_fsm_fn_stopped(mm_channel_t *my_obj,
518 mm_channel_evt_type_t evt,
519 void * in_val,
520 void * out_val)
521 {
522 int32_t rc = 0;
523 CDBG("%s : E evt = %d", __func__, evt);
524 switch (evt) {
525 case MM_CHANNEL_EVT_ADD_STREAM:
526 {
527 uint32_t s_hdl = 0;
528 s_hdl = mm_channel_add_stream(my_obj);
529 *((uint32_t*)out_val) = s_hdl;
530 rc = 0;
531 }
532 break;
533 case MM_CHANNEL_EVT_DEL_STREAM:
534 {
535 uint32_t s_id = (uint32_t)in_val;
536 rc = mm_channel_del_stream(my_obj, s_id);
537 }
538 break;
539 case MM_CHANNEL_EVT_START:
540 {
541 rc = mm_channel_start(my_obj);
542 /* first stream started in stopped state
543 * move to active state */
544 if (0 == rc) {
545 my_obj->state = MM_CHANNEL_STATE_ACTIVE;
546 }
547 }
548 break;
549 case MM_CHANNEL_EVT_CONFIG_STREAM:
550 {
551 mm_evt_paylod_config_stream_t *payload =
552 (mm_evt_paylod_config_stream_t *)in_val;
553 rc = mm_channel_config_stream(my_obj,
554 payload->stream_id,
555 payload->config);
556 }
557 break;
558 case MM_CHANNEL_EVT_GET_BUNDLE_INFO:
559 {
560 cam_bundle_config_t *payload =
561 (cam_bundle_config_t *)in_val;
562 rc = mm_channel_get_bundle_info(my_obj, payload);
563 }
564 break;
565 case MM_CHANNEL_EVT_DELETE:
566 {
567 mm_channel_release(my_obj);
568 rc = 0;
569 }
570 break;
571 case MM_CHANNEL_EVT_SET_STREAM_PARM:
572 {
573 mm_evt_paylod_set_get_stream_parms_t *payload =
574 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
575 rc = mm_channel_set_stream_parm(my_obj, payload);
576 }
577 break;
578 case MM_CHANNEL_EVT_GET_STREAM_PARM:
579 {
580 mm_evt_paylod_set_get_stream_parms_t *payload =
581 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
582 rc = mm_channel_get_stream_parm(my_obj, payload);
583 }
584 break;
585 case MM_CHANNEL_EVT_DO_STREAM_ACTION:
586 {
587 mm_evt_paylod_do_stream_action_t *payload =
588 (mm_evt_paylod_do_stream_action_t *)in_val;
589 rc = mm_channel_do_stream_action(my_obj, payload);
590 }
591 break;
592 case MM_CHANNEL_EVT_MAP_STREAM_BUF:
593 {
594 mm_evt_paylod_map_stream_buf_t *payload =
595 (mm_evt_paylod_map_stream_buf_t *)in_val;
596 rc = mm_channel_map_stream_buf(my_obj, payload);
597 }
598 break;
599 case MM_CHANNEL_EVT_UNMAP_STREAM_BUF:
600 {
601 mm_evt_paylod_unmap_stream_buf_t *payload =
602 (mm_evt_paylod_unmap_stream_buf_t *)in_val;
603 rc = mm_channel_unmap_stream_buf(my_obj, payload);
604 }
605 break;
606 default:
607 CDBG_ERROR("%s: invalid state (%d) for evt (%d)",
608 __func__, my_obj->state, evt);
609 break;
610 }
611 CDBG("%s : E rc = %d", __func__, rc);
612 return rc;
613 }
614
615 /*===========================================================================
616 * FUNCTION : mm_channel_fsm_fn_active
617 *
618 * DESCRIPTION: channel finite state machine function to handle event
619 * in ACTIVE state.
620 *
621 * PARAMETERS :
622 * @my_obj : ptr to a channel object
623 * @evt : channel event to be processed
624 * @in_val : input event payload. Can be NULL if not needed.
625 * @out_val : output payload, Can be NULL if not needed.
626 *
627 * RETURN : int32_t type of status
628 * 0 -- success
629 * -1 -- failure
630 *==========================================================================*/
mm_channel_fsm_fn_active(mm_channel_t * my_obj,mm_channel_evt_type_t evt,void * in_val,void * out_val)631 int32_t mm_channel_fsm_fn_active(mm_channel_t *my_obj,
632 mm_channel_evt_type_t evt,
633 void * in_val,
634 void * out_val)
635 {
636 int32_t rc = 0;
637
638 CDBG("%s : E evt = %d", __func__, evt);
639 switch (evt) {
640 case MM_CHANNEL_EVT_STOP:
641 {
642 rc = mm_channel_stop(my_obj);
643 my_obj->state = MM_CHANNEL_STATE_STOPPED;
644 }
645 break;
646 case MM_CHANNEL_EVT_REQUEST_SUPER_BUF:
647 {
648 uint32_t num_buf_requested = (uint32_t)in_val;
649 uint32_t num_retro_buf_requested = (uint32_t)out_val;
650 rc = mm_channel_request_super_buf(my_obj,
651 num_buf_requested, num_retro_buf_requested);
652 }
653 break;
654 case MM_CHANNEL_EVT_CANCEL_REQUEST_SUPER_BUF:
655 {
656 rc = mm_channel_cancel_super_buf_request(my_obj);
657 }
658 break;
659 case MM_CHANNEL_EVT_FLUSH_SUPER_BUF_QUEUE:
660 {
661 uint32_t frame_idx = (uint32_t)in_val;
662 rc = mm_channel_flush_super_buf_queue(my_obj, frame_idx);
663 }
664 break;
665 case MM_CHANNEL_EVT_START_ZSL_SNAPSHOT:
666 {
667 rc = mm_channel_start_zsl_snapshot(my_obj);
668 }
669 break;
670 case MM_CHANNEL_EVT_STOP_ZSL_SNAPSHOT:
671 {
672 rc = mm_channel_stop_zsl_snapshot(my_obj);
673 }
674 break;
675 case MM_CHANNEL_EVT_CONFIG_NOTIFY_MODE:
676 {
677 mm_camera_super_buf_notify_mode_t notify_mode = ( mm_camera_super_buf_notify_mode_t ) in_val;
678 rc = mm_channel_config_notify_mode(my_obj, notify_mode);
679 }
680 break;
681 case MM_CHANNEL_EVT_SET_STREAM_PARM:
682 {
683 mm_evt_paylod_set_get_stream_parms_t *payload =
684 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
685 rc = mm_channel_set_stream_parm(my_obj, payload);
686 }
687 break;
688 case MM_CHANNEL_EVT_GET_STREAM_PARM:
689 {
690 mm_evt_paylod_set_get_stream_parms_t *payload =
691 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
692 rc = mm_channel_get_stream_parm(my_obj, payload);
693 }
694 break;
695 case MM_CHANNEL_EVT_DO_STREAM_ACTION:
696 {
697 mm_evt_paylod_do_stream_action_t *payload =
698 (mm_evt_paylod_do_stream_action_t *)in_val;
699 rc = mm_channel_do_stream_action(my_obj, payload);
700 }
701 break;
702 case MM_CHANNEL_EVT_MAP_STREAM_BUF:
703 {
704 mm_evt_paylod_map_stream_buf_t *payload =
705 (mm_evt_paylod_map_stream_buf_t *)in_val;
706 if (payload != NULL) {
707 uint8_t type = payload->buf_type;
708 if ((type == CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF) ||
709 (type == CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF)) {
710 rc = mm_channel_map_stream_buf(my_obj, payload);
711 }
712 } else {
713 CDBG_ERROR("%s: cannot map regualr stream buf in active state", __func__);
714 }
715 }
716 break;
717 case MM_CHANNEL_EVT_UNMAP_STREAM_BUF:
718 {
719 mm_evt_paylod_unmap_stream_buf_t *payload =
720 (mm_evt_paylod_unmap_stream_buf_t *)in_val;
721 if (payload != NULL) {
722 uint8_t type = payload->buf_type;
723 if ((type == CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF) ||
724 (type == CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF)) {
725 rc = mm_channel_unmap_stream_buf(my_obj, payload);
726 }
727 } else {
728 CDBG_ERROR("%s: cannot unmap regualr stream buf in active state", __func__);
729 }
730 }
731 break;
732 case MM_CHANNEL_EVT_AF_BRACKETING:
733 {
734 CDBG_HIGH("MM_CHANNEL_EVT_AF_BRACKETING");
735 int32_t start_flag = ( int32_t ) in_val;
736 mm_camera_generic_cmd_t gen_cmd;
737 gen_cmd.type = MM_CAMERA_GENERIC_CMD_TYPE_AF_BRACKETING;
738 gen_cmd.payload[0] = start_flag;
739 rc = mm_channel_proc_general_cmd(my_obj, &gen_cmd);
740 }
741 break;
742 case MM_CHANNEL_EVT_AE_BRACKETING:
743 {
744 CDBG_HIGH("MM_CHANNEL_EVT_AE_BRACKETING");
745 int32_t start_flag = ( int32_t ) in_val;
746 mm_camera_generic_cmd_t gen_cmd;
747 gen_cmd.type = MM_CAMERA_GENERIC_CMD_TYPE_AE_BRACKETING;
748 gen_cmd.payload[0] = start_flag;
749 rc = mm_channel_proc_general_cmd(my_obj, &gen_cmd);
750 }
751 break;
752 case MM_CHANNEL_EVT_FLASH_BRACKETING:
753 {
754 CDBG_HIGH("MM_CHANNEL_EVT_FLASH_BRACKETING");
755 int32_t start_flag = ( int32_t ) in_val;
756 mm_camera_generic_cmd_t gen_cmd;
757 gen_cmd.type = MM_CAMERA_GENERIC_CMD_TYPE_FLASH_BRACKETING;
758 gen_cmd.payload[0] = start_flag;
759 rc = mm_channel_proc_general_cmd(my_obj, &gen_cmd);
760 }
761 break;
762 case MM_CHANNEL_EVT_ZOOM_1X:
763 {
764 CDBG_HIGH("MM_CHANNEL_EVT_ZOOM_1X");
765 int32_t start_flag = ( int32_t ) in_val;
766 mm_camera_generic_cmd_t gen_cmd;
767 gen_cmd.type = MM_CAMERA_GENERIC_CMD_TYPE_ZOOM_1X;
768 gen_cmd.payload[0] = start_flag;
769 rc = mm_channel_proc_general_cmd(my_obj, &gen_cmd);
770 }
771 break;
772 default:
773 CDBG_ERROR("%s: invalid state (%d) for evt (%d), in(%p), out(%p)",
774 __func__, my_obj->state, evt, in_val, out_val);
775 break;
776 }
777 CDBG("%s : X rc = %d", __func__, rc);
778 return rc;
779 }
780
781 /*===========================================================================
782 * FUNCTION : mm_channel_fsm_fn_paused
783 *
784 * DESCRIPTION: channel finite state machine function to handle event
785 * in PAUSED state.
786 *
787 * PARAMETERS :
788 * @my_obj : ptr to a channel object
789 * @evt : channel event to be processed
790 * @in_val : input event payload. Can be NULL if not needed.
791 * @out_val : output payload, Can be NULL if not needed.
792 *
793 * RETURN : int32_t type of status
794 * 0 -- success
795 * -1 -- failure
796 *==========================================================================*/
mm_channel_fsm_fn_paused(mm_channel_t * my_obj,mm_channel_evt_type_t evt,void * in_val,void * out_val)797 int32_t mm_channel_fsm_fn_paused(mm_channel_t *my_obj,
798 mm_channel_evt_type_t evt,
799 void * in_val,
800 void * out_val)
801 {
802 int32_t rc = 0;
803
804 /* currently we are not supporting pause/resume channel */
805 CDBG_ERROR("%s: invalid state (%d) for evt (%d), in(%p), out(%p)",
806 __func__, my_obj->state, evt, in_val, out_val);
807
808 return rc;
809 }
810
811 /*===========================================================================
812 * FUNCTION : mm_channel_init
813 *
814 * DESCRIPTION: initialize a channel
815 *
816 * PARAMETERS :
817 * @my_obj : channel object be to initialized
818 * @attr : bundle attribute of the channel if needed
819 * @channel_cb : callback function for bundle data notify
820 * @userdata : user data ptr
821 *
822 * RETURN : int32_t type of status
823 * 0 -- success
824 * -1 -- failure
825 * NOTE : if no bundle data notify is needed, meaning each stream in the
826 * channel will have its own stream data notify callback, then
827 * attr, channel_cb, and userdata can be NULL. In this case,
828 * no matching logic will be performed in channel for the bundling.
829 *==========================================================================*/
mm_channel_init(mm_channel_t * my_obj,mm_camera_channel_attr_t * attr,mm_camera_buf_notify_t channel_cb,void * userdata)830 int32_t mm_channel_init(mm_channel_t *my_obj,
831 mm_camera_channel_attr_t *attr,
832 mm_camera_buf_notify_t channel_cb,
833 void *userdata)
834 {
835 int32_t rc = 0;
836
837 my_obj->bundle.super_buf_notify_cb = channel_cb;
838 my_obj->bundle.user_data = userdata;
839 if (NULL != attr) {
840 my_obj->bundle.superbuf_queue.attr = *attr;
841 }
842
843 CDBG("%s : Launch data poll thread in channel open", __func__);
844 mm_camera_poll_thread_launch(&my_obj->poll_thread[0],
845 MM_CAMERA_POLL_TYPE_DATA);
846
847 /* change state to stopped state */
848 my_obj->state = MM_CHANNEL_STATE_STOPPED;
849 return rc;
850 }
851
852 /*===========================================================================
853 * FUNCTION : mm_channel_release
854 *
855 * DESCRIPTION: release a channel resource. Channel state will move to UNUSED
856 * state after this call.
857 *
858 * PARAMETERS :
859 * @my_obj : channel object
860 *
861 * RETURN : none
862 *==========================================================================*/
mm_channel_release(mm_channel_t * my_obj)863 void mm_channel_release(mm_channel_t *my_obj)
864 {
865 /* stop data poll thread */
866 mm_camera_poll_thread_release(&my_obj->poll_thread[0]);
867
868 /* change state to notused state */
869 my_obj->state = MM_CHANNEL_STATE_NOTUSED;
870 }
871
872 /*===========================================================================
873 * FUNCTION : mm_channel_add_stream
874 *
875 * DESCRIPTION: add a stream into the channel
876 *
877 * PARAMETERS :
878 * @my_obj : channel object
879 *
880 * RETURN : uint32_t type of stream handle
881 * 0 -- invalid stream handle, meaning the op failed
882 * >0 -- successfully added a stream with a valid handle
883 *==========================================================================*/
mm_channel_add_stream(mm_channel_t * my_obj)884 uint32_t mm_channel_add_stream(mm_channel_t *my_obj)
885 {
886 int32_t rc = 0;
887 uint8_t idx = 0;
888 uint32_t s_hdl = 0;
889 mm_stream_t *stream_obj = NULL;
890
891 CDBG("%s : E", __func__);
892 /* check available stream */
893 for (idx = 0; idx < MAX_STREAM_NUM_IN_BUNDLE; idx++) {
894 if (MM_STREAM_STATE_NOTUSED == my_obj->streams[idx].state) {
895 stream_obj = &my_obj->streams[idx];
896 break;
897 }
898 }
899 if (NULL == stream_obj) {
900 CDBG_ERROR("%s: streams reach max, no more stream allowed to add", __func__);
901 return s_hdl;
902 }
903
904 /* initialize stream object */
905 memset(stream_obj, 0, sizeof(mm_stream_t));
906 stream_obj->fd = -1;
907 stream_obj->my_hdl = mm_camera_util_generate_handler(idx);
908 stream_obj->ch_obj = my_obj;
909 pthread_mutex_init(&stream_obj->buf_lock, NULL);
910 pthread_mutex_init(&stream_obj->cb_lock, NULL);
911 stream_obj->state = MM_STREAM_STATE_INITED;
912
913 /* acquire stream */
914 rc = mm_stream_fsm_fn(stream_obj, MM_STREAM_EVT_ACQUIRE, NULL, NULL);
915 if (0 == rc) {
916 s_hdl = stream_obj->my_hdl;
917 } else {
918 /* error during acquire, de-init */
919 pthread_mutex_destroy(&stream_obj->buf_lock);
920 pthread_mutex_destroy(&stream_obj->cb_lock);
921 memset(stream_obj, 0, sizeof(mm_stream_t));
922 }
923 CDBG("%s : stream handle = %d", __func__, s_hdl);
924 return s_hdl;
925 }
926
927 /*===========================================================================
928 * FUNCTION : mm_channel_del_stream
929 *
930 * DESCRIPTION: delete a stream from the channel bu its handle
931 *
932 * PARAMETERS :
933 * @my_obj : channel object
934 * @stream_id : stream handle
935 *
936 * RETURN : int32_t type of status
937 * 0 -- success
938 * -1 -- failure
939 * NOTE : assume steam is stooped before it can be deleted
940 *==========================================================================*/
mm_channel_del_stream(mm_channel_t * my_obj,uint32_t stream_id)941 int32_t mm_channel_del_stream(mm_channel_t *my_obj,
942 uint32_t stream_id)
943 {
944 int rc = -1;
945 mm_stream_t * stream_obj = NULL;
946 stream_obj = mm_channel_util_get_stream_by_handler(my_obj, stream_id);
947
948 if (NULL == stream_obj) {
949 CDBG_ERROR("%s :Invalid Stream Object for stream_id = %d",
950 __func__, stream_id);
951 return rc;
952 }
953
954 rc = mm_stream_fsm_fn(stream_obj,
955 MM_STREAM_EVT_RELEASE,
956 NULL,
957 NULL);
958
959 return rc;
960 }
961
962 /*===========================================================================
963 * FUNCTION : mm_channel_config_stream
964 *
965 * DESCRIPTION: configure a stream
966 *
967 * PARAMETERS :
968 * @my_obj : channel object
969 * @stream_id : stream handle
970 * @config : stream configuration
971 *
972 * RETURN : int32_t type of status
973 * 0 -- success
974 * -1 -- failure
975 *==========================================================================*/
mm_channel_config_stream(mm_channel_t * my_obj,uint32_t stream_id,mm_camera_stream_config_t * config)976 int32_t mm_channel_config_stream(mm_channel_t *my_obj,
977 uint32_t stream_id,
978 mm_camera_stream_config_t *config)
979 {
980 int rc = -1;
981 mm_stream_t * stream_obj = NULL;
982 CDBG("%s : E stream ID = %d", __func__, stream_id);
983 stream_obj = mm_channel_util_get_stream_by_handler(my_obj, stream_id);
984
985 if (NULL == stream_obj) {
986 CDBG_ERROR("%s :Invalid Stream Object for stream_id = %d", __func__, stream_id);
987 return rc;
988 }
989
990 /* set stream fmt */
991 rc = mm_stream_fsm_fn(stream_obj,
992 MM_STREAM_EVT_SET_FMT,
993 (void *)config,
994 NULL);
995 CDBG("%s : X rc = %d",__func__,rc);
996 return rc;
997 }
998
999 /*===========================================================================
1000 * FUNCTION : mm_channel_get_bundle_info
1001 *
1002 * DESCRIPTION: query bundle info of the channel, which should include all
1003 * streams within this channel
1004 *
1005 * PARAMETERS :
1006 * @my_obj : channel object
1007 * @bundle_info : bundle info to be filled in
1008 *
1009 * RETURN : int32_t type of status
1010 * 0 -- success
1011 * -1 -- failure
1012 *==========================================================================*/
mm_channel_get_bundle_info(mm_channel_t * my_obj,cam_bundle_config_t * bundle_info)1013 int32_t mm_channel_get_bundle_info(mm_channel_t *my_obj,
1014 cam_bundle_config_t *bundle_info)
1015 {
1016 int i;
1017 mm_stream_t *s_obj = NULL;
1018 int32_t rc = 0;
1019
1020 memset(bundle_info, 0, sizeof(cam_bundle_config_t));
1021 bundle_info->bundle_id = my_obj->my_hdl;
1022 bundle_info->num_of_streams = 0;
1023 for (i = 0; i < MAX_STREAM_NUM_IN_BUNDLE; i++) {
1024 if (my_obj->streams[i].my_hdl > 0) {
1025 s_obj = mm_channel_util_get_stream_by_handler(my_obj,
1026 my_obj->streams[i].my_hdl);
1027 if (NULL != s_obj) {
1028 if (CAM_STREAM_TYPE_METADATA != s_obj->stream_info->stream_type) {
1029 bundle_info->stream_ids[bundle_info->num_of_streams++] =
1030 s_obj->server_stream_id;
1031 }
1032 } else {
1033 CDBG_ERROR("%s: cannot find stream obj (%d) by handler (%d)",
1034 __func__, i, my_obj->streams[i].my_hdl);
1035 rc = -1;
1036 break;
1037 }
1038 }
1039 }
1040 if (rc != 0) {
1041 /* error, reset to 0 */
1042 memset(bundle_info, 0, sizeof(cam_bundle_config_t));
1043 }
1044 return rc;
1045 }
1046
1047 /*===========================================================================
1048 * FUNCTION : mm_channel_start
1049 *
1050 * DESCRIPTION: start a channel, which will start all streams in the channel
1051 *
1052 * PARAMETERS :
1053 * @my_obj : channel object
1054 *
1055 * RETURN : int32_t type of status
1056 * 0 -- success
1057 * -1 -- failure
1058 *==========================================================================*/
mm_channel_start(mm_channel_t * my_obj)1059 int32_t mm_channel_start(mm_channel_t *my_obj)
1060 {
1061 int32_t rc = 0;
1062 int i, j;
1063 mm_stream_t *s_objs[MAX_STREAM_NUM_IN_BUNDLE] = {NULL};
1064 uint8_t num_streams_to_start = 0;
1065 mm_stream_t *s_obj = NULL;
1066 int meta_stream_idx = 0;
1067
1068 for (i = 0; i < MAX_STREAM_NUM_IN_BUNDLE; i++) {
1069 if (my_obj->streams[i].my_hdl > 0) {
1070 s_obj = mm_channel_util_get_stream_by_handler(my_obj,
1071 my_obj->streams[i].my_hdl);
1072 if (NULL != s_obj) {
1073 /* remember meta data stream index */
1074 if (s_obj->stream_info->stream_type == CAM_STREAM_TYPE_METADATA) {
1075 meta_stream_idx = num_streams_to_start;
1076 }
1077 s_objs[num_streams_to_start++] = s_obj;
1078 }
1079 }
1080 }
1081
1082 if (meta_stream_idx > 0 ) {
1083 /* always start meta data stream first, so switch the stream object with the first one */
1084 s_obj = s_objs[0];
1085 s_objs[0] = s_objs[meta_stream_idx];
1086 s_objs[meta_stream_idx] = s_obj;
1087 }
1088
1089 if (NULL != my_obj->bundle.super_buf_notify_cb) {
1090 /* need to send up cb, therefore launch thread */
1091 /* init superbuf queue */
1092 mm_channel_superbuf_queue_init(&my_obj->bundle.superbuf_queue);
1093 my_obj->bundle.superbuf_queue.num_streams = num_streams_to_start;
1094 my_obj->bundle.superbuf_queue.expected_frame_id = 0;
1095 my_obj->bundle.superbuf_queue.expected_frame_id_without_led = 0;
1096 my_obj->bundle.superbuf_queue.led_off_start_frame_id = 0;
1097 my_obj->bundle.superbuf_queue.led_on_start_frame_id = 0;
1098 my_obj->bundle.superbuf_queue.led_on_num_frames = 0;
1099
1100 for (i = 0; i < num_streams_to_start; i++) {
1101 /* set bundled flag to streams */
1102 s_objs[i]->is_bundled = 1;
1103 /* init bundled streams to invalid value -1 */
1104 my_obj->bundle.superbuf_queue.bundled_streams[i] = s_objs[i]->my_hdl;
1105 }
1106
1107 /* launch cb thread for dispatching super buf through cb */
1108 mm_camera_cmd_thread_launch(&my_obj->cb_thread,
1109 mm_channel_dispatch_super_buf,
1110 (void*)my_obj);
1111
1112 /* launch cmd thread for super buf dataCB */
1113 mm_camera_cmd_thread_launch(&my_obj->cmd_thread,
1114 mm_channel_process_stream_buf,
1115 (void*)my_obj);
1116
1117 /* set flag to TRUE */
1118 my_obj->bundle.is_active = TRUE;
1119 }
1120
1121 for (i = 0; i < num_streams_to_start; i++) {
1122 /* all streams within a channel should be started at the same time */
1123 if (s_objs[i]->state == MM_STREAM_STATE_ACTIVE) {
1124 CDBG_ERROR("%s: stream already started idx(%d)", __func__, i);
1125 rc = -1;
1126 break;
1127 }
1128
1129 /* allocate buf */
1130 rc = mm_stream_fsm_fn(s_objs[i],
1131 MM_STREAM_EVT_GET_BUF,
1132 NULL,
1133 NULL);
1134 if (0 != rc) {
1135 CDBG_ERROR("%s: get buf failed at idx(%d)", __func__, i);
1136 break;
1137 }
1138
1139 /* reg buf */
1140 rc = mm_stream_fsm_fn(s_objs[i],
1141 MM_STREAM_EVT_REG_BUF,
1142 NULL,
1143 NULL);
1144 if (0 != rc) {
1145 CDBG_ERROR("%s: reg buf failed at idx(%d)", __func__, i);
1146 break;
1147 }
1148
1149 /* start stream */
1150 rc = mm_stream_fsm_fn(s_objs[i],
1151 MM_STREAM_EVT_START,
1152 NULL,
1153 NULL);
1154 if (0 != rc) {
1155 CDBG_ERROR("%s: start stream failed at idx(%d)", __func__, i);
1156 break;
1157 }
1158 }
1159
1160 /* error handling */
1161 if (0 != rc) {
1162 for (j=0; j<=i; j++) {
1163 /* stop streams*/
1164 mm_stream_fsm_fn(s_objs[j],
1165 MM_STREAM_EVT_STOP,
1166 NULL,
1167 NULL);
1168
1169 /* unreg buf */
1170 mm_stream_fsm_fn(s_objs[j],
1171 MM_STREAM_EVT_UNREG_BUF,
1172 NULL,
1173 NULL);
1174
1175 /* put buf back */
1176 mm_stream_fsm_fn(s_objs[j],
1177 MM_STREAM_EVT_PUT_BUF,
1178 NULL,
1179 NULL);
1180 }
1181
1182 /* destroy super buf cmd thread */
1183 if (TRUE == my_obj->bundle.is_active) {
1184 /* first stop bundle thread */
1185 mm_camera_cmd_thread_release(&my_obj->cmd_thread);
1186 mm_camera_cmd_thread_release(&my_obj->cb_thread);
1187
1188 /* deinit superbuf queue */
1189 mm_channel_superbuf_queue_deinit(&my_obj->bundle.superbuf_queue);
1190
1191 /* memset bundle info */
1192 memset(&my_obj->bundle, 0, sizeof(mm_channel_bundle_t));
1193 }
1194 }
1195 my_obj->bWaitForPrepSnapshotDone = 0;
1196
1197 return rc;
1198 }
1199
1200 /*===========================================================================
1201 * FUNCTION : mm_channel_stop
1202 *
1203 * DESCRIPTION: stop a channel, which will stop all streams in the channel
1204 *
1205 * PARAMETERS :
1206 * @my_obj : channel object
1207 *
1208 * RETURN : int32_t type of status
1209 * 0 -- success
1210 * -1 -- failure
1211 *==========================================================================*/
mm_channel_stop(mm_channel_t * my_obj)1212 int32_t mm_channel_stop(mm_channel_t *my_obj)
1213 {
1214 int32_t rc = 0;
1215 int i;
1216 mm_stream_t *s_objs[MAX_STREAM_NUM_IN_BUNDLE] = {NULL};
1217 uint8_t num_streams_to_stop = 0;
1218 mm_stream_t *s_obj = NULL;
1219 int meta_stream_idx = 0;
1220
1221 for (i = 0; i < MAX_STREAM_NUM_IN_BUNDLE; i++) {
1222 if (my_obj->streams[i].my_hdl > 0) {
1223 s_obj = mm_channel_util_get_stream_by_handler(my_obj,
1224 my_obj->streams[i].my_hdl);
1225 if (NULL != s_obj) {
1226 /* remember meta data stream index */
1227 if (s_obj->stream_info->stream_type == CAM_STREAM_TYPE_METADATA) {
1228 meta_stream_idx = num_streams_to_stop;
1229 }
1230 s_objs[num_streams_to_stop++] = s_obj;
1231 }
1232 }
1233 }
1234
1235 if (meta_stream_idx < num_streams_to_stop - 1 ) {
1236 /* always stop meta data stream last, so switch the stream object with the last one */
1237 s_obj = s_objs[num_streams_to_stop - 1];
1238 s_objs[num_streams_to_stop - 1] = s_objs[meta_stream_idx];
1239 s_objs[meta_stream_idx] = s_obj;
1240 }
1241
1242 for (i = 0; i < num_streams_to_stop; i++) {
1243 /* stream off */
1244 mm_stream_fsm_fn(s_objs[i],
1245 MM_STREAM_EVT_STOP,
1246 NULL,
1247 NULL);
1248
1249 /* unreg buf at kernel */
1250 mm_stream_fsm_fn(s_objs[i],
1251 MM_STREAM_EVT_UNREG_BUF,
1252 NULL,
1253 NULL);
1254 }
1255
1256 /* destroy super buf cmd thread */
1257 if (TRUE == my_obj->bundle.is_active) {
1258 /* first stop bundle thread */
1259 mm_camera_cmd_thread_release(&my_obj->cmd_thread);
1260 mm_camera_cmd_thread_release(&my_obj->cb_thread);
1261
1262 /* deinit superbuf queue */
1263 mm_channel_superbuf_queue_deinit(&my_obj->bundle.superbuf_queue);
1264
1265 /* memset bundle info */
1266 memset(&my_obj->bundle, 0, sizeof(mm_channel_bundle_t));
1267 }
1268
1269 /* since all streams are stopped, we are safe to
1270 * release all buffers allocated in stream */
1271 for (i = 0; i < num_streams_to_stop; i++) {
1272 /* put buf back */
1273 mm_stream_fsm_fn(s_objs[i],
1274 MM_STREAM_EVT_PUT_BUF,
1275 NULL,
1276 NULL);
1277 }
1278
1279 return rc;
1280 }
1281
1282 /*===========================================================================
1283 * FUNCTION : mm_channel_request_super_buf
1284 *
1285 * DESCRIPTION: for burst mode in bundle, reuqest certain amount of matched
1286 * frames from superbuf queue
1287 *
1288 * PARAMETERS :
1289 * @my_obj : channel object
1290 * @num_buf_requested : number of matched frames needed
1291 * @num_retro_buf_requested : number of retro frames needed
1292 *
1293 * RETURN : int32_t type of status
1294 * 0 -- success
1295 * -1 -- failure
1296 *==========================================================================*/
mm_channel_request_super_buf(mm_channel_t * my_obj,uint32_t num_buf_requested,uint32_t num_retro_buf_requested)1297 int32_t mm_channel_request_super_buf(mm_channel_t *my_obj,
1298 uint32_t num_buf_requested, uint32_t num_retro_buf_requested)
1299 {
1300 int32_t rc = 0;
1301 mm_camera_cmdcb_t* node = NULL;
1302
1303 /* set pending_cnt
1304 * will trigger dispatching super frames if pending_cnt > 0 */
1305 /* send cam_sem_post to wake up cmd thread to dispatch super buffer */
1306 node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
1307 if (NULL != node) {
1308 memset(node, 0, sizeof(mm_camera_cmdcb_t));
1309 node->cmd_type = MM_CAMERA_CMD_TYPE_REQ_DATA_CB;
1310 node->u.req_buf.num_buf_requested = num_buf_requested;
1311 node->u.req_buf.num_retro_buf_requested = num_retro_buf_requested;
1312
1313 /* enqueue to cmd thread */
1314 cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node);
1315
1316 /* wake up cmd thread */
1317 cam_sem_post(&(my_obj->cmd_thread.cmd_sem));
1318 } else {
1319 CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__);
1320 rc = -1;
1321 }
1322
1323 return rc;
1324 }
1325
1326 /*===========================================================================
1327 * FUNCTION : mm_channel_cancel_super_buf_request
1328 *
1329 * DESCRIPTION: for burst mode in bundle, cancel the reuqest for certain amount
1330 * of matched frames from superbuf queue
1331 *
1332 * PARAMETERS :
1333 * @my_obj : channel object
1334 *
1335 * RETURN : int32_t type of status
1336 * 0 -- success
1337 * -1 -- failure
1338 *==========================================================================*/
mm_channel_cancel_super_buf_request(mm_channel_t * my_obj)1339 int32_t mm_channel_cancel_super_buf_request(mm_channel_t *my_obj)
1340 {
1341 int32_t rc = 0;
1342 /* reset pending_cnt */
1343 rc = mm_channel_request_super_buf(my_obj, 0, 0);
1344 return rc;
1345 }
1346
1347 /*===========================================================================
1348 * FUNCTION : mm_channel_flush_super_buf_queue
1349 *
1350 * DESCRIPTION: flush superbuf queue
1351 *
1352 * PARAMETERS :
1353 * @my_obj : channel object
1354 * @frame_idx : frame idx until which to flush all superbufs
1355 *
1356 * RETURN : int32_t type of status
1357 * 0 -- success
1358 * -1 -- failure
1359 *==========================================================================*/
mm_channel_flush_super_buf_queue(mm_channel_t * my_obj,uint32_t frame_idx)1360 int32_t mm_channel_flush_super_buf_queue(mm_channel_t *my_obj, uint32_t frame_idx)
1361 {
1362 int32_t rc = 0;
1363 mm_camera_cmdcb_t* node = NULL;
1364
1365 node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
1366 if (NULL != node) {
1367 memset(node, 0, sizeof(mm_camera_cmdcb_t));
1368 node->cmd_type = MM_CAMERA_CMD_TYPE_FLUSH_QUEUE;
1369 node->u.frame_idx = frame_idx;
1370
1371 /* enqueue to cmd thread */
1372 cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node);
1373
1374 /* wake up cmd thread */
1375 cam_sem_post(&(my_obj->cmd_thread.cmd_sem));
1376 } else {
1377 CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__);
1378 rc = -1;
1379 }
1380
1381 return rc;
1382 }
1383
1384 /*===========================================================================
1385 * FUNCTION : mm_channel_config_notify_mode
1386 *
1387 * DESCRIPTION: configure notification mode
1388 *
1389 * PARAMETERS :
1390 * @my_obj : channel object
1391 * @notify_mode : notification mode
1392 *
1393 * RETURN : int32_t type of status
1394 * 0 -- success
1395 * -1 -- failure
1396 *==========================================================================*/
mm_channel_config_notify_mode(mm_channel_t * my_obj,mm_camera_super_buf_notify_mode_t notify_mode)1397 int32_t mm_channel_config_notify_mode(mm_channel_t *my_obj,
1398 mm_camera_super_buf_notify_mode_t notify_mode)
1399 {
1400 int32_t rc = 0;
1401 mm_camera_cmdcb_t* node = NULL;
1402
1403 node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
1404 if (NULL != node) {
1405 memset(node, 0, sizeof(mm_camera_cmdcb_t));
1406 node->u.notify_mode = notify_mode;
1407 node->cmd_type = MM_CAMERA_CMD_TYPE_CONFIG_NOTIFY;
1408
1409 /* enqueue to cmd thread */
1410 cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node);
1411
1412 /* wake up cmd thread */
1413 cam_sem_post(&(my_obj->cmd_thread.cmd_sem));
1414 } else {
1415 CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__);
1416 rc = -1;
1417 }
1418
1419 return rc;
1420 }
1421
1422 /*===========================================================================
1423 * FUNCTION : mm_channel_start_zsl_snapshot
1424 *
1425 * DESCRIPTION: start zsl snapshot
1426 *
1427 * PARAMETERS :
1428 * @my_obj : channel object
1429 *
1430 * RETURN : int32_t type of status
1431 * 0 -- success
1432 * -1 -- failure
1433 *==========================================================================*/
mm_channel_start_zsl_snapshot(mm_channel_t * my_obj)1434 int32_t mm_channel_start_zsl_snapshot(mm_channel_t *my_obj)
1435 {
1436 int32_t rc = 0;
1437 mm_camera_cmdcb_t* node = NULL;
1438
1439 node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
1440 if (NULL != node) {
1441 memset(node, 0, sizeof(mm_camera_cmdcb_t));
1442 node->cmd_type = MM_CAMERA_CMD_TYPE_START_ZSL;
1443
1444 /* enqueue to cmd thread */
1445 cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node);
1446
1447 /* wake up cmd thread */
1448 cam_sem_post(&(my_obj->cmd_thread.cmd_sem));
1449 } else {
1450 CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__);
1451 rc = -1;
1452 }
1453
1454 return rc;
1455 }
1456
1457 /*===========================================================================
1458 * FUNCTION : mm_channel_stop_zsl_snapshot
1459 *
1460 * DESCRIPTION: stop zsl snapshot
1461 *
1462 * PARAMETERS :
1463 * @my_obj : channel object
1464 *
1465 * RETURN : int32_t type of status
1466 * 0 -- success
1467 * -1 -- failure
1468 *==========================================================================*/
mm_channel_stop_zsl_snapshot(mm_channel_t * my_obj)1469 int32_t mm_channel_stop_zsl_snapshot(mm_channel_t *my_obj)
1470 {
1471 int32_t rc = 0;
1472 mm_camera_cmdcb_t* node = NULL;
1473
1474 node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
1475 if (NULL != node) {
1476 memset(node, 0, sizeof(mm_camera_cmdcb_t));
1477 node->cmd_type = MM_CAMERA_CMD_TYPE_STOP_ZSL;
1478
1479 /* enqueue to cmd thread */
1480 cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node);
1481
1482 /* wake up cmd thread */
1483 cam_sem_post(&(my_obj->cmd_thread.cmd_sem));
1484 } else {
1485 CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__);
1486 rc = -1;
1487 }
1488
1489 return rc;
1490 }
1491
1492 /*===========================================================================
1493 * FUNCTION : mm_channel_qbuf
1494 *
1495 * DESCRIPTION: enqueue buffer back to kernel
1496 *
1497 * PARAMETERS :
1498 * @my_obj : channel object
1499 * @buf : buf ptr to be enqueued
1500 *
1501 * RETURN : int32_t type of status
1502 * 0 -- success
1503 * -1 -- failure
1504 *==========================================================================*/
mm_channel_qbuf(mm_channel_t * my_obj,mm_camera_buf_def_t * buf)1505 int32_t mm_channel_qbuf(mm_channel_t *my_obj,
1506 mm_camera_buf_def_t *buf)
1507 {
1508 int32_t rc = -1;
1509 mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj, buf->stream_id);
1510
1511 if (NULL != s_obj) {
1512 rc = mm_stream_fsm_fn(s_obj,
1513 MM_STREAM_EVT_QBUF,
1514 (void *)buf,
1515 NULL);
1516 }
1517
1518 return rc;
1519 }
1520
1521 /*===========================================================================
1522 * FUNCTION : mm_channel_set_stream_parms
1523 *
1524 * DESCRIPTION: set parameters per stream
1525 *
1526 * PARAMETERS :
1527 * @my_obj : channel object
1528 * @s_id : stream handle
1529 * @parms : ptr to a param struct to be set to server
1530 *
1531 * RETURN : int32_t type of status
1532 * 0 -- success
1533 * -1 -- failure
1534 * NOTE : Assume the parms struct buf is already mapped to server via
1535 * domain socket. Corresponding fields of parameters to be set
1536 * are already filled in by upper layer caller.
1537 *==========================================================================*/
mm_channel_set_stream_parm(mm_channel_t * my_obj,mm_evt_paylod_set_get_stream_parms_t * payload)1538 int32_t mm_channel_set_stream_parm(mm_channel_t *my_obj,
1539 mm_evt_paylod_set_get_stream_parms_t *payload)
1540 {
1541 int32_t rc = -1;
1542 mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj,
1543 payload->stream_id);
1544 if (NULL != s_obj) {
1545 rc = mm_stream_fsm_fn(s_obj,
1546 MM_STREAM_EVT_SET_PARM,
1547 (void *)payload,
1548 NULL);
1549 }
1550
1551 return rc;
1552 }
1553
1554 /*===========================================================================
1555 * FUNCTION : mm_channel_get_stream_parms
1556 *
1557 * DESCRIPTION: get parameters per stream
1558 *
1559 * PARAMETERS :
1560 * @my_obj : channel object
1561 * @s_id : stream handle
1562 * @parms : ptr to a param struct to be get from server
1563 *
1564 * RETURN : int32_t type of status
1565 * 0 -- success
1566 * -1 -- failure
1567 * NOTE : Assume the parms struct buf is already mapped to server via
1568 * domain socket. Parameters to be get from server are already
1569 * filled in by upper layer caller. After this call, corresponding
1570 * fields of requested parameters will be filled in by server with
1571 * detailed information.
1572 *==========================================================================*/
mm_channel_get_stream_parm(mm_channel_t * my_obj,mm_evt_paylod_set_get_stream_parms_t * payload)1573 int32_t mm_channel_get_stream_parm(mm_channel_t *my_obj,
1574 mm_evt_paylod_set_get_stream_parms_t *payload)
1575 {
1576 int32_t rc = -1;
1577 mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj,
1578 payload->stream_id);
1579 if (NULL != s_obj) {
1580 rc = mm_stream_fsm_fn(s_obj,
1581 MM_STREAM_EVT_GET_PARM,
1582 (void *)payload,
1583 NULL);
1584 }
1585
1586 return rc;
1587 }
1588
1589 /*===========================================================================
1590 * FUNCTION : mm_channel_do_stream_action
1591 *
1592 * DESCRIPTION: request server to perform stream based action. Maybe removed later
1593 * if the functionality is included in mm_camera_set_parms
1594 *
1595 * PARAMETERS :
1596 * @my_obj : channel object
1597 * @s_id : stream handle
1598 * @actions : ptr to an action struct buf to be performed by server
1599 *
1600 * RETURN : int32_t type of status
1601 * 0 -- success
1602 * -1 -- failure
1603 * NOTE : Assume the action struct buf is already mapped to server via
1604 * domain socket. Actions to be performed by server are already
1605 * filled in by upper layer caller.
1606 *==========================================================================*/
mm_channel_do_stream_action(mm_channel_t * my_obj,mm_evt_paylod_do_stream_action_t * payload)1607 int32_t mm_channel_do_stream_action(mm_channel_t *my_obj,
1608 mm_evt_paylod_do_stream_action_t *payload)
1609 {
1610 int32_t rc = -1;
1611 mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj,
1612 payload->stream_id);
1613 if (NULL != s_obj) {
1614 rc = mm_stream_fsm_fn(s_obj,
1615 MM_STREAM_EVT_DO_ACTION,
1616 (void *)payload,
1617 NULL);
1618 }
1619
1620 return rc;
1621 }
1622
1623 /*===========================================================================
1624 * FUNCTION : mm_channel_map_stream_buf
1625 *
1626 * DESCRIPTION: mapping stream buffer via domain socket to server
1627 *
1628 * PARAMETERS :
1629 * @my_obj : channel object
1630 * @payload : ptr to payload for mapping
1631 *
1632 * RETURN : int32_t type of status
1633 * 0 -- success
1634 * -1 -- failure
1635 *==========================================================================*/
mm_channel_map_stream_buf(mm_channel_t * my_obj,mm_evt_paylod_map_stream_buf_t * payload)1636 int32_t mm_channel_map_stream_buf(mm_channel_t *my_obj,
1637 mm_evt_paylod_map_stream_buf_t *payload)
1638 {
1639 int32_t rc = -1;
1640 mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj,
1641 payload->stream_id);
1642 if (NULL != s_obj) {
1643 rc = mm_stream_map_buf(s_obj,
1644 payload->buf_type,
1645 payload->buf_idx,
1646 payload->plane_idx,
1647 payload->fd,
1648 payload->size);
1649 }
1650
1651 return rc;
1652 }
1653
1654 /*===========================================================================
1655 * FUNCTION : mm_channel_unmap_stream_buf
1656 *
1657 * DESCRIPTION: unmapping stream buffer via domain socket to server
1658 *
1659 * PARAMETERS :
1660 * @my_obj : channel object
1661 * @payload : ptr to unmap payload
1662 *
1663 * RETURN : int32_t type of status
1664 * 0 -- success
1665 * -1 -- failure
1666 *==========================================================================*/
mm_channel_unmap_stream_buf(mm_channel_t * my_obj,mm_evt_paylod_unmap_stream_buf_t * payload)1667 int32_t mm_channel_unmap_stream_buf(mm_channel_t *my_obj,
1668 mm_evt_paylod_unmap_stream_buf_t *payload)
1669 {
1670 int32_t rc = -1;
1671 mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj,
1672 payload->stream_id);
1673 if (NULL != s_obj) {
1674 rc = mm_stream_unmap_buf(s_obj, payload->buf_type,
1675 payload->buf_idx, payload->plane_idx);
1676 }
1677
1678 return rc;
1679 }
1680
1681 /*===========================================================================
1682 * FUNCTION : mm_channel_superbuf_queue_init
1683 *
1684 * DESCRIPTION: initialize superbuf queue in the channel
1685 *
1686 * PARAMETERS :
1687 * @queue : ptr to superbuf queue to be initialized
1688 *
1689 * RETURN : int32_t type of status
1690 * 0 -- success
1691 * -1 -- failure
1692 *==========================================================================*/
mm_channel_superbuf_queue_init(mm_channel_queue_t * queue)1693 int32_t mm_channel_superbuf_queue_init(mm_channel_queue_t * queue)
1694 {
1695 return cam_queue_init(&queue->que);
1696 }
1697
1698 /*===========================================================================
1699 * FUNCTION : mm_channel_superbuf_queue_deinit
1700 *
1701 * DESCRIPTION: deinitialize superbuf queue in the channel
1702 *
1703 * PARAMETERS :
1704 * @queue : ptr to superbuf queue to be deinitialized
1705 *
1706 * RETURN : int32_t type of status
1707 * 0 -- success
1708 * -1 -- failure
1709 *==========================================================================*/
mm_channel_superbuf_queue_deinit(mm_channel_queue_t * queue)1710 int32_t mm_channel_superbuf_queue_deinit(mm_channel_queue_t * queue)
1711 {
1712 return cam_queue_deinit(&queue->que);
1713 }
1714
1715 /*===========================================================================
1716 * FUNCTION : mm_channel_util_seq_comp_w_rollover
1717 *
1718 * DESCRIPTION: utility function to handle sequence number comparison with rollover
1719 *
1720 * PARAMETERS :
1721 * @v1 : first value to be compared
1722 * @v2 : second value to be compared
1723 *
1724 * RETURN : int8_t type of comparison result
1725 * >0 -- v1 larger than v2
1726 * =0 -- vi equal to v2
1727 * <0 -- v1 smaller than v2
1728 *==========================================================================*/
mm_channel_util_seq_comp_w_rollover(uint32_t v1,uint32_t v2)1729 int8_t mm_channel_util_seq_comp_w_rollover(uint32_t v1,
1730 uint32_t v2)
1731 {
1732 int8_t ret = 0;
1733
1734 /* TODO: need to handle the case if v2 roll over to 0 */
1735 if (v1 > v2) {
1736 ret = 1;
1737 } else if (v1 < v2) {
1738 ret = -1;
1739 }
1740
1741 return ret;
1742 }
1743
1744 /*===========================================================================
1745 * FUNCTION : mm_channel_handle_metadata
1746 *
1747 * DESCRIPTION: Handle frame matching logic change due to metadata
1748 *
1749 * PARAMETERS :
1750 * @ch_obj : channel object
1751 * @queue : superbuf queue
1752 * @buf_info: new buffer from stream
1753 *
1754 * RETURN : int32_t type of status
1755 * 0 -- success
1756 * -1 -- failure
1757 *==========================================================================*/
mm_channel_handle_metadata(mm_channel_t * ch_obj,mm_channel_queue_t * queue,mm_camera_buf_info_t * buf_info)1758 int32_t mm_channel_handle_metadata(
1759 mm_channel_t* ch_obj,
1760 mm_channel_queue_t * queue,
1761 mm_camera_buf_info_t *buf_info)
1762 {
1763
1764 int rc = 0 ;
1765 mm_stream_t* stream_obj = NULL;
1766 stream_obj = mm_channel_util_get_stream_by_handler(ch_obj,
1767 buf_info->stream_id);
1768 uint8_t is_prep_snapshot_done_valid = 0;
1769 uint8_t is_good_frame_idx_range_valid = 0;
1770 int32_t prep_snapshot_done_state;
1771 cam_frame_idx_range_t good_frame_idx_range;
1772 uint8_t is_crop_1x_found = 0;
1773 uint32_t snapshot_stream_id = 0;
1774 uint32_t i;
1775 /* Set expected frame id to a future frame idx, large enough to wait
1776 * for good_frame_idx_range, and small enough to still capture an image */
1777 const int max_future_frame_offset = 100;
1778
1779 memset(&good_frame_idx_range, 0, sizeof(good_frame_idx_range));
1780
1781 if (NULL == stream_obj) {
1782 CDBG_ERROR("%s: Invalid Stream Object for stream_id = %d",
1783 __func__, buf_info->stream_id);
1784 rc = -1;
1785 goto end;
1786 }
1787 if (NULL == stream_obj->stream_info) {
1788 CDBG_ERROR("%s: NULL stream info for stream_id = %d",
1789 __func__, buf_info->stream_id);
1790 rc = -1;
1791 goto end;
1792 }
1793
1794 if (CAM_STREAM_TYPE_METADATA == stream_obj->stream_info->stream_type) {
1795 const metadata_buffer_t *metadata;
1796 metadata = (const metadata_buffer_t *)buf_info->buf->buffer;
1797
1798 if (NULL == metadata) {
1799 CDBG_ERROR("%s: NULL metadata buffer for metadata stream",
1800 __func__);
1801 rc = -1;
1802 goto end;
1803 }
1804 CDBG("%s: E , expected frame id: %d", __func__, queue->expected_frame_id);
1805
1806 if (IS_META_AVAILABLE(CAM_INTF_META_PREP_SNAPSHOT_DONE, metadata)) {
1807 prep_snapshot_done_state = *((int32_t*)
1808 POINTER_OF_META(CAM_INTF_META_PREP_SNAPSHOT_DONE, metadata));
1809 is_prep_snapshot_done_valid = 1;
1810 CDBG("%s: prepare snapshot done valid ", __func__);
1811 }
1812 if (IS_META_AVAILABLE(CAM_INTF_META_GOOD_FRAME_IDX_RANGE, metadata)){
1813 good_frame_idx_range = *((cam_frame_idx_range_t*)
1814 POINTER_OF_META(CAM_INTF_META_GOOD_FRAME_IDX_RANGE, metadata));
1815 is_good_frame_idx_range_valid = 1;
1816 CDBG("%s: good_frame_idx_range : min: %d, max: %d , num frames = %d",
1817 __func__, good_frame_idx_range.min_frame_idx,
1818 good_frame_idx_range.max_frame_idx, good_frame_idx_range.num_led_on_frames);
1819 }
1820 if (IS_META_AVAILABLE(CAM_INTF_META_CROP_DATA, metadata)) {
1821 cam_crop_data_t crop_data = *((cam_crop_data_t *)
1822 POINTER_OF_META(CAM_INTF_META_CROP_DATA, metadata));
1823
1824 for (i=0; i<ARRAY_SIZE(ch_obj->streams); i++) {
1825 if (CAM_STREAM_TYPE_SNAPSHOT ==
1826 ch_obj->streams[i].stream_info->stream_type) {
1827 snapshot_stream_id = ch_obj->streams[i].server_stream_id;
1828 break;
1829 }
1830 }
1831
1832 for (i=0; i<crop_data.num_of_streams; i++) {
1833 if (snapshot_stream_id == crop_data.crop_info[i].stream_id) {
1834 if (!crop_data.crop_info[i].crop.left &&
1835 !crop_data.crop_info[i].crop.top) {
1836 is_crop_1x_found = 1;
1837 break;
1838 }
1839 }
1840 }
1841 }
1842
1843 if (is_prep_snapshot_done_valid &&
1844 is_good_frame_idx_range_valid) {
1845 CDBG_ERROR("%s: prep_snapshot_done and good_idx_range shouldn't be "
1846 "valid at the same time", __func__);
1847 rc = -1;
1848 goto end;
1849 }
1850
1851 if (ch_obj->isZoom1xFrameRequested) {
1852 if (is_crop_1x_found) {
1853 ch_obj->isZoom1xFrameRequested = 0;
1854 queue->expected_frame_id = buf_info->frame_idx + 1;
1855 } else {
1856 queue->expected_frame_id += max_future_frame_offset;
1857 /* Flush unwanted frames */
1858 mm_channel_superbuf_flush_matched(ch_obj, queue);
1859 }
1860 goto end;
1861 }
1862
1863 if (is_prep_snapshot_done_valid) {
1864 ch_obj->bWaitForPrepSnapshotDone = 0;
1865 if (prep_snapshot_done_state == NEED_FUTURE_FRAME) {
1866 queue->expected_frame_id += max_future_frame_offset;
1867 CDBG("%s: [ZSL Retro] NEED_FUTURE_FRAME, expected frame id = %d ",
1868 __func__, queue->expected_frame_id);
1869
1870 mm_channel_superbuf_flush(ch_obj, queue);
1871 ch_obj->needLEDFlash = TRUE;
1872 } else {
1873 ch_obj->needLEDFlash = FALSE;
1874 }
1875 } else if (is_good_frame_idx_range_valid) {
1876 if (good_frame_idx_range.min_frame_idx >
1877 queue->expected_frame_id) {
1878 CDBG_HIGH("%s: [ZSL Retro] min_frame_idx %d is greater than expected_frame_id %d",
1879 __func__, good_frame_idx_range.min_frame_idx,
1880 queue->expected_frame_id);
1881 }
1882 queue->expected_frame_id =
1883 good_frame_idx_range.min_frame_idx;
1884 if((ch_obj->needLEDFlash == TRUE) && (ch_obj->burstSnapNum > 1)) {
1885 queue->expected_frame_id =
1886 good_frame_idx_range.min_frame_idx;
1887 queue->led_on_start_frame_id =
1888 good_frame_idx_range.min_frame_idx;
1889 queue->led_off_start_frame_id =
1890 good_frame_idx_range.max_frame_idx;
1891 queue->once = 0;
1892 queue->led_on_num_frames =
1893 good_frame_idx_range.num_led_on_frames;
1894 queue->frame_skip_count = good_frame_idx_range.frame_skip_count;
1895 CDBG("%s: [ZSL Retro] Need Flash, expected frame id = %d,"
1896 " led_on start = %d, led off start = %d, led on frames = %d ",
1897 __func__, queue->expected_frame_id, queue->led_on_start_frame_id,
1898 queue->led_off_start_frame_id, queue->led_on_num_frames);
1899 } else {
1900 queue->expected_frame_id =
1901 good_frame_idx_range.min_frame_idx;
1902 CDBG("%s: [ZSL Retro]No flash, expected frame id = %d ",
1903 __func__, queue->expected_frame_id);
1904 }
1905 } else if (ch_obj->need3ABracketing && !is_good_frame_idx_range_valid) {
1906 /* Flush unwanted frames */
1907 mm_channel_superbuf_flush_matched(ch_obj, queue);
1908 queue->expected_frame_id += max_future_frame_offset;
1909 }
1910 if (ch_obj->isFlashBracketingEnabled &&
1911 is_good_frame_idx_range_valid) {
1912 /* Flash bracketing needs two frames, with & without led flash.
1913 * in valid range min frame is with led flash and max frame is
1914 * without led flash */
1915 queue->expected_frame_id =
1916 good_frame_idx_range.min_frame_idx;
1917 /* max frame is without led flash */
1918 queue->expected_frame_id_without_led =
1919 good_frame_idx_range.max_frame_idx;
1920
1921 } else if (is_good_frame_idx_range_valid) {
1922 if (good_frame_idx_range.min_frame_idx >
1923 queue->expected_frame_id) {
1924 CDBG_HIGH("%s: min_frame_idx %d is greater than expected_frame_id %d",
1925 __func__, good_frame_idx_range.min_frame_idx,
1926 queue->expected_frame_id);
1927 }
1928 queue->expected_frame_id =
1929 good_frame_idx_range.min_frame_idx;
1930 ch_obj->need3ABracketing = FALSE;
1931 }
1932
1933 if((ch_obj->burstSnapNum > 1) && (ch_obj->needLEDFlash == TRUE) &&
1934 !ch_obj->isFlashBracketingEnabled) {
1935 if((buf_info->frame_idx >= queue->led_off_start_frame_id)
1936 && !queue->once) {
1937 CDBG("%s: [ZSL Retro]Burst snap num = %d ",
1938 __func__, ch_obj->burstSnapNum);
1939 // Skip frames from LED OFF frame to get a good frame
1940 queue->expected_frame_id = queue->led_off_start_frame_id + queue->frame_skip_count;
1941 queue->once = 1;
1942 ch_obj->stopZslSnapshot = 1;
1943 CDBG("%s:[ZSL Retro]Reached max led on frames = %d , expected id = %d",
1944 __func__, buf_info->frame_idx, queue->expected_frame_id);
1945 }
1946 }
1947 }
1948 end:
1949 return rc;
1950 }
1951
1952 /*===========================================================================
1953 * FUNCTION : mm_channel_superbuf_comp_and_enqueue
1954 *
1955 * DESCRIPTION: implementation for matching logic for superbuf
1956 *
1957 * PARAMETERS :
1958 * @ch_obj : channel object
1959 * @queue : superbuf queue
1960 * @buf_info: new buffer from stream
1961 *
1962 * RETURN : int32_t type of status
1963 * 0 -- success
1964 * -1 -- failure
1965 *==========================================================================*/
mm_channel_superbuf_comp_and_enqueue(mm_channel_t * ch_obj,mm_channel_queue_t * queue,mm_camera_buf_info_t * buf_info)1966 int32_t mm_channel_superbuf_comp_and_enqueue(
1967 mm_channel_t* ch_obj,
1968 mm_channel_queue_t *queue,
1969 mm_camera_buf_info_t *buf_info)
1970 {
1971 cam_node_t* node = NULL;
1972 struct cam_list *head = NULL;
1973 struct cam_list *pos = NULL;
1974 mm_channel_queue_node_t* super_buf = NULL;
1975 uint8_t buf_s_idx, i, found_super_buf, unmatched_bundles;
1976 struct cam_list *last_buf, *insert_before_buf;
1977
1978 CDBG("%s: E", __func__);
1979 for (buf_s_idx = 0; buf_s_idx < queue->num_streams; buf_s_idx++) {
1980 if (buf_info->stream_id == queue->bundled_streams[buf_s_idx]) {
1981 break;
1982 }
1983 }
1984 if (buf_s_idx == queue->num_streams) {
1985 CDBG_ERROR("%s: buf from stream (%d) not bundled", __func__, buf_info->stream_id);
1986 return -1;
1987 }
1988
1989 if (mm_channel_handle_metadata(ch_obj, queue, buf_info) < 0) {
1990 mm_channel_qbuf(ch_obj, buf_info->buf);
1991 return -1;
1992 }
1993 #if 0
1994 mm_stream_t* stream_obj = mm_channel_util_get_stream_by_handler(ch_obj,
1995 buf_info->stream_id);
1996
1997 if (CAM_STREAM_TYPE_METADATA == stream_obj->stream_info->stream_type) {
1998 const metadata_buffer_t *metadata;
1999 metadata = (const metadata_buffer_t *)buf_info->buf->buffer;
2000 int32_t is_meta_valid = *((int32_t*)POINTER_OF(CAM_INTF_META_VALID, metadata));
2001 CDBG("%s: meta_valid: %d\n", __func__, is_meta_valid);
2002 if (!is_meta_valid) {
2003 mm_channel_qbuf(ch_obj, buf_info->buf);
2004 return 0;
2005 }
2006 }
2007 #endif
2008 if (mm_channel_util_seq_comp_w_rollover(buf_info->frame_idx,
2009 queue->expected_frame_id) < 0) {
2010 /* incoming buf is older than expected buf id, will discard it */
2011 mm_channel_qbuf(ch_obj, buf_info->buf);
2012 return 0;
2013 }
2014
2015 if (MM_CAMERA_SUPER_BUF_PRIORITY_NORMAL != queue->attr.priority) {
2016 /* TODO */
2017 /* need to decide if we want to queue the frame based on focus or exposure
2018 * if frame not to be queued, we need to qbuf it back */
2019 }
2020
2021 /* comp */
2022 pthread_mutex_lock(&queue->que.lock);
2023 head = &queue->que.head.list;
2024 /* get the last one in the queue which is possibly having no matching */
2025 pos = head->next;
2026
2027 found_super_buf = 0;
2028 unmatched_bundles = 0;
2029 last_buf = NULL;
2030 insert_before_buf = NULL;
2031 while (pos != head) {
2032 node = member_of(pos, cam_node_t, list);
2033 super_buf = (mm_channel_queue_node_t*)node->data;
2034 if (NULL != super_buf) {
2035 if (super_buf->matched) {
2036 /* find a matched super buf, move to next one */
2037 pos = pos->next;
2038 continue;
2039 } else if ( buf_info->frame_idx == super_buf->frame_idx ) {
2040 /* have an unmatched super buf that matches our frame idx,
2041 * break the loop */
2042 found_super_buf = 1;
2043 break;
2044 } else {
2045 unmatched_bundles++;
2046 if ( NULL == last_buf ) {
2047 if ( super_buf->frame_idx < buf_info->frame_idx ) {
2048 last_buf = pos;
2049 }
2050 }
2051 if ( NULL == insert_before_buf ) {
2052 if ( super_buf->frame_idx > buf_info->frame_idx ) {
2053 insert_before_buf = pos;
2054 }
2055 }
2056 pos = pos->next;
2057 }
2058 }
2059 }
2060 if ( found_super_buf ) {
2061 super_buf->super_buf[buf_s_idx] = *buf_info;
2062
2063 /* check if superbuf is all matched */
2064 super_buf->matched = 1;
2065 for (i=0; i < super_buf->num_of_bufs; i++) {
2066 if (super_buf->super_buf[i].frame_idx == 0) {
2067 super_buf->matched = 0;
2068 break;
2069 }
2070 }
2071
2072 if (super_buf->matched) {
2073 if(ch_obj->isFlashBracketingEnabled) {
2074 queue->expected_frame_id =
2075 queue->expected_frame_id_without_led;
2076 if (buf_info->frame_idx >=
2077 queue->expected_frame_id_without_led) {
2078 ch_obj->isFlashBracketingEnabled = FALSE;
2079 }
2080 } else {
2081 queue->expected_frame_id = buf_info->frame_idx
2082 + queue->attr.post_frame_skip;
2083 }
2084 CDBG("%s: curr = %d, skip = %d , Expected Frame ID: %d",
2085 __func__, buf_info->frame_idx,
2086 queue->attr.post_frame_skip, queue->expected_frame_id);
2087
2088 queue->match_cnt++;
2089 /* Any older unmatched buffer need to be released */
2090 if ( last_buf ) {
2091 while ( last_buf != pos ) {
2092 node = member_of(last_buf, cam_node_t, list);
2093 super_buf = (mm_channel_queue_node_t*)node->data;
2094 if (NULL != super_buf) {
2095 for (i=0; i<super_buf->num_of_bufs; i++) {
2096 if (super_buf->super_buf[i].frame_idx != 0) {
2097 mm_channel_qbuf(ch_obj, super_buf->super_buf[i].buf);
2098 }
2099 }
2100 queue->que.size--;
2101 last_buf = last_buf->next;
2102 cam_list_del_node(&node->list);
2103 free(node);
2104 free(super_buf);
2105 } else {
2106 CDBG_ERROR(" %s : Invalid superbuf in queue!", __func__);
2107 break;
2108 }
2109 }
2110 }
2111 }
2112 } else {
2113 if ( ( queue->attr.max_unmatched_frames < unmatched_bundles ) &&
2114 ( NULL == last_buf ) ) {
2115 /* incoming frame is older than the last bundled one */
2116 mm_channel_qbuf(ch_obj, buf_info->buf);
2117 } else {
2118 if ( queue->attr.max_unmatched_frames < unmatched_bundles ) {
2119 /* release the oldest bundled superbuf */
2120 node = member_of(last_buf, cam_node_t, list);
2121 super_buf = (mm_channel_queue_node_t*)node->data;
2122 for (i=0; i<super_buf->num_of_bufs; i++) {
2123 if (super_buf->super_buf[i].frame_idx != 0) {
2124 mm_channel_qbuf(ch_obj, super_buf->super_buf[i].buf);
2125 }
2126 }
2127 queue->que.size--;
2128 node = member_of(last_buf, cam_node_t, list);
2129 cam_list_del_node(&node->list);
2130 free(node);
2131 free(super_buf);
2132 }
2133 /* insert the new frame at the appropriate position. */
2134
2135 mm_channel_queue_node_t *new_buf = NULL;
2136 cam_node_t* new_node = NULL;
2137
2138 new_buf = (mm_channel_queue_node_t*)malloc(sizeof(mm_channel_queue_node_t));
2139 new_node = (cam_node_t*)malloc(sizeof(cam_node_t));
2140 if (NULL != new_buf && NULL != new_node) {
2141 memset(new_buf, 0, sizeof(mm_channel_queue_node_t));
2142 memset(new_node, 0, sizeof(cam_node_t));
2143 new_node->data = (void *)new_buf;
2144 new_buf->num_of_bufs = queue->num_streams;
2145 new_buf->super_buf[buf_s_idx] = *buf_info;
2146 new_buf->frame_idx = buf_info->frame_idx;
2147 /* enqueue */
2148 if ( insert_before_buf ) {
2149 cam_list_insert_before_node(&new_node->list, insert_before_buf);
2150 } else {
2151 cam_list_add_tail_node(&new_node->list, &queue->que.head.list);
2152 }
2153 queue->que.size++;
2154
2155 if(queue->num_streams == 1) {
2156 new_buf->matched = 1;
2157
2158 queue->expected_frame_id = buf_info->frame_idx + queue->attr.post_frame_skip;
2159 queue->match_cnt++;
2160 }
2161 } else {
2162 /* No memory */
2163 if (NULL != new_buf) {
2164 free(new_buf);
2165 }
2166 if (NULL != new_node) {
2167 free(new_node);
2168 }
2169 /* qbuf the new buf since we cannot enqueue */
2170 mm_channel_qbuf(ch_obj, buf_info->buf);
2171 }
2172 }
2173 }
2174
2175 pthread_mutex_unlock(&queue->que.lock);
2176 CDBG("%s: X", __func__);
2177 return 0;
2178 }
2179
2180 /*===========================================================================
2181 * FUNCTION : mm_channel_superbuf_dequeue_internal
2182 *
2183 * DESCRIPTION: internal implementation for dequeue from the superbuf queue
2184 *
2185 * PARAMETERS :
2186 * @queue : superbuf queue
2187 * @matched_only : if dequeued buf should be matched
2188 *
2189 * RETURN : ptr to a node from superbuf queue
2190 *==========================================================================*/
mm_channel_superbuf_dequeue_internal(mm_channel_queue_t * queue,uint8_t matched_only)2191 mm_channel_queue_node_t* mm_channel_superbuf_dequeue_internal(mm_channel_queue_t * queue,
2192 uint8_t matched_only)
2193 {
2194 cam_node_t* node = NULL;
2195 struct cam_list *head = NULL;
2196 struct cam_list *pos = NULL;
2197 mm_channel_queue_node_t* super_buf = NULL;
2198
2199 head = &queue->que.head.list;
2200 pos = head->next;
2201 if (pos != head) {
2202 /* get the first node */
2203 node = member_of(pos, cam_node_t, list);
2204 super_buf = (mm_channel_queue_node_t*)node->data;
2205 if ( (NULL != super_buf) &&
2206 (matched_only == TRUE) &&
2207 (super_buf->matched == FALSE) ) {
2208 /* require to dequeue matched frame only, but this superbuf is not matched,
2209 simply set return ptr to NULL */
2210 super_buf = NULL;
2211 }
2212 if (NULL != super_buf) {
2213 /* remove from the queue */
2214 cam_list_del_node(&node->list);
2215 queue->que.size--;
2216 if (super_buf->matched == TRUE) {
2217 queue->match_cnt--;
2218 }
2219 free(node);
2220 }
2221 }
2222
2223 return super_buf;
2224 }
2225
2226 /*===========================================================================
2227 * FUNCTION : mm_channel_superbuf_dequeue
2228 *
2229 * DESCRIPTION: dequeue from the superbuf queue
2230 *
2231 * PARAMETERS :
2232 * @queue : superbuf queue
2233 *
2234 * RETURN : ptr to a node from superbuf queue
2235 *==========================================================================*/
mm_channel_superbuf_dequeue(mm_channel_queue_t * queue)2236 mm_channel_queue_node_t* mm_channel_superbuf_dequeue(mm_channel_queue_t * queue)
2237 {
2238 mm_channel_queue_node_t* super_buf = NULL;
2239
2240 pthread_mutex_lock(&queue->que.lock);
2241 super_buf = mm_channel_superbuf_dequeue_internal(queue, TRUE);
2242 pthread_mutex_unlock(&queue->que.lock);
2243
2244 return super_buf;
2245 }
2246
2247 /*===========================================================================
2248 * FUNCTION : mm_channel_superbuf_bufdone_overflow
2249 *
2250 * DESCRIPTION: keep superbuf queue no larger than watermark set by upper layer
2251 * via channel attribute
2252 *
2253 * PARAMETERS :
2254 * @my_obj : channel object
2255 * @queue : superbuf queue
2256 *
2257 * RETURN : int32_t type of status
2258 * 0 -- success
2259 * -1 -- failure
2260 *==========================================================================*/
mm_channel_superbuf_bufdone_overflow(mm_channel_t * my_obj,mm_channel_queue_t * queue)2261 int32_t mm_channel_superbuf_bufdone_overflow(mm_channel_t* my_obj,
2262 mm_channel_queue_t * queue)
2263 {
2264 int32_t rc = 0, i;
2265 mm_channel_queue_node_t* super_buf = NULL;
2266 if (MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS == queue->attr.notify_mode) {
2267 /* for continuous streaming mode, no overflow is needed */
2268 return 0;
2269 }
2270
2271 CDBG("%s: before match_cnt=%d, water_mark=%d",
2272 __func__, queue->match_cnt, queue->attr.water_mark);
2273 /* bufdone overflowed bufs */
2274 pthread_mutex_lock(&queue->que.lock);
2275 while (queue->match_cnt > queue->attr.water_mark) {
2276 super_buf = mm_channel_superbuf_dequeue_internal(queue, TRUE);
2277 if (NULL != super_buf) {
2278 for (i=0; i<super_buf->num_of_bufs; i++) {
2279 if (NULL != super_buf->super_buf[i].buf) {
2280 mm_channel_qbuf(my_obj, super_buf->super_buf[i].buf);
2281 }
2282 }
2283 free(super_buf);
2284 }
2285 }
2286 pthread_mutex_unlock(&queue->que.lock);
2287 CDBG("%s: after match_cnt=%d, water_mark=%d",
2288 __func__, queue->match_cnt, queue->attr.water_mark);
2289
2290 return rc;
2291 }
2292
2293 /*===========================================================================
2294 * FUNCTION : mm_channel_superbuf_skip
2295 *
2296 * DESCRIPTION: depends on the lookback configuration of the channel attribute,
2297 * unwanted superbufs will be removed from the superbuf queue.
2298 *
2299 * PARAMETERS :
2300 * @my_obj : channel object
2301 * @queue : superbuf queue
2302 *
2303 * RETURN : int32_t type of status
2304 * 0 -- success
2305 * -1 -- failure
2306 *==========================================================================*/
mm_channel_superbuf_skip(mm_channel_t * my_obj,mm_channel_queue_t * queue)2307 int32_t mm_channel_superbuf_skip(mm_channel_t* my_obj,
2308 mm_channel_queue_t * queue)
2309 {
2310 int32_t rc = 0, i;
2311 mm_channel_queue_node_t* super_buf = NULL;
2312 if (MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS == queue->attr.notify_mode) {
2313 /* for continuous streaming mode, no skip is needed */
2314 return 0;
2315 }
2316
2317 /* bufdone overflowed bufs */
2318 pthread_mutex_lock(&queue->que.lock);
2319 while (queue->match_cnt > queue->attr.look_back) {
2320 super_buf = mm_channel_superbuf_dequeue_internal(queue, TRUE);
2321 if (NULL != super_buf) {
2322 for (i=0; i<super_buf->num_of_bufs; i++) {
2323 if (NULL != super_buf->super_buf[i].buf) {
2324 mm_channel_qbuf(my_obj, super_buf->super_buf[i].buf);
2325 }
2326 }
2327 free(super_buf);
2328 }
2329 }
2330 pthread_mutex_unlock(&queue->que.lock);
2331
2332 return rc;
2333 }
2334
2335 /*===========================================================================
2336 * FUNCTION : mm_channel_superbuf_flush
2337 *
2338 * DESCRIPTION: flush the superbuf queue.
2339 *
2340 * PARAMETERS :
2341 * @my_obj : channel object
2342 * @queue : superbuf queue
2343 *
2344 * RETURN : int32_t type of status
2345 * 0 -- success
2346 * -1 -- failure
2347 *==========================================================================*/
mm_channel_superbuf_flush(mm_channel_t * my_obj,mm_channel_queue_t * queue)2348 int32_t mm_channel_superbuf_flush(mm_channel_t* my_obj,
2349 mm_channel_queue_t * queue)
2350 {
2351 int32_t rc = 0, i;
2352 mm_channel_queue_node_t* super_buf = NULL;
2353
2354 /* bufdone bufs */
2355 pthread_mutex_lock(&queue->que.lock);
2356 super_buf = mm_channel_superbuf_dequeue_internal(queue, FALSE);
2357 while (super_buf != NULL) {
2358 for (i=0; i<super_buf->num_of_bufs; i++) {
2359 if (NULL != super_buf->super_buf[i].buf) {
2360 mm_channel_qbuf(my_obj, super_buf->super_buf[i].buf);
2361 }
2362 }
2363 free(super_buf);
2364 super_buf = mm_channel_superbuf_dequeue_internal(queue, FALSE);
2365 }
2366 pthread_mutex_unlock(&queue->que.lock);
2367
2368 return rc;
2369 }
2370
2371 /*===========================================================================
2372 * FUNCTION : mm_channel_proc_general_cmd
2373 *
2374 * DESCRIPTION: process general command
2375 *
2376 * PARAMETERS :
2377 * @my_obj : channel object
2378 * @notify_mode : notification mode
2379 *
2380 * RETURN : int32_t type of status
2381 * 0 -- success
2382 * -1 -- failure
2383 *==========================================================================*/
mm_channel_proc_general_cmd(mm_channel_t * my_obj,mm_camera_generic_cmd_t * p_gen_cmd)2384 int32_t mm_channel_proc_general_cmd(mm_channel_t *my_obj,
2385 mm_camera_generic_cmd_t *p_gen_cmd)
2386 {
2387 CDBG("%s: E",__func__);
2388 int32_t rc = 0;
2389 mm_camera_cmdcb_t* node = NULL;
2390
2391 node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
2392 if (NULL != node) {
2393 memset(node, 0, sizeof(mm_camera_cmdcb_t));
2394 node->u.gen_cmd = *p_gen_cmd;
2395 node->cmd_type = MM_CAMERA_CMD_TYPE_GENERAL;
2396
2397 /* enqueue to cmd thread */
2398 cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node);
2399
2400 /* wake up cmd thread */
2401 cam_sem_post(&(my_obj->cmd_thread.cmd_sem));
2402 } else {
2403 CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__);
2404 rc = -1;
2405 }
2406 CDBG("%s: X",__func__);
2407
2408 return rc;
2409 }
2410
2411 /*===========================================================================
2412 * FUNCTION : mm_channel_superbuf_flush_matched
2413 *
2414 * DESCRIPTION: flush matched buffers from the superbuf queue.
2415 *
2416 * PARAMETERS :
2417 * @my_obj : channel object
2418 * @queue : superbuf queue
2419 *
2420 * RETURN : int32_t type of status
2421 * 0 -- success
2422 * -1 -- failure
2423 *==========================================================================*/
mm_channel_superbuf_flush_matched(mm_channel_t * my_obj,mm_channel_queue_t * queue)2424 int32_t mm_channel_superbuf_flush_matched(mm_channel_t* my_obj,
2425 mm_channel_queue_t * queue)
2426 {
2427 int32_t rc = 0, i;
2428 mm_channel_queue_node_t* super_buf = NULL;
2429
2430 /* bufdone bufs */
2431 pthread_mutex_lock(&queue->que.lock);
2432 super_buf = mm_channel_superbuf_dequeue_internal(queue, TRUE);
2433 while (super_buf != NULL) {
2434 for (i=0; i<super_buf->num_of_bufs; i++) {
2435 if (NULL != super_buf->super_buf[i].buf) {
2436 mm_channel_qbuf(my_obj, super_buf->super_buf[i].buf);
2437 }
2438 }
2439 free(super_buf);
2440 super_buf = mm_channel_superbuf_dequeue_internal(queue, TRUE);
2441 }
2442 pthread_mutex_unlock(&queue->que.lock);
2443
2444 return rc;
2445 }
2446