1 /* Copyright (c) 2012-2013, 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);
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_superbuf_flush(mm_channel_t* my_obj, mm_channel_queue_t * queue);
73 int32_t mm_channel_set_stream_parm(mm_channel_t *my_obj,
74 mm_evt_paylod_set_get_stream_parms_t *payload);
75 int32_t mm_channel_get_stream_parm(mm_channel_t *my_obj,
76 mm_evt_paylod_set_get_stream_parms_t *payload);
77 int32_t mm_channel_do_stream_action(mm_channel_t *my_obj,
78 mm_evt_paylod_do_stream_action_t *payload);
79 int32_t mm_channel_map_stream_buf(mm_channel_t *my_obj,
80 mm_evt_paylod_map_stream_buf_t *payload);
81 int32_t mm_channel_unmap_stream_buf(mm_channel_t *my_obj,
82 mm_evt_paylod_unmap_stream_buf_t *payload);
83
84 /* state machine function declare */
85 int32_t mm_channel_fsm_fn_notused(mm_channel_t *my_obj,
86 mm_channel_evt_type_t evt,
87 void * in_val,
88 void * out_val);
89 int32_t mm_channel_fsm_fn_stopped(mm_channel_t *my_obj,
90 mm_channel_evt_type_t evt,
91 void * in_val,
92 void * out_val);
93 int32_t mm_channel_fsm_fn_active(mm_channel_t *my_obj,
94 mm_channel_evt_type_t evt,
95 void * in_val,
96 void * out_val);
97 int32_t mm_channel_fsm_fn_paused(mm_channel_t *my_obj,
98 mm_channel_evt_type_t evt,
99 void * in_val,
100 void * out_val);
101
102 /* channel super queue functions */
103 int32_t mm_channel_superbuf_queue_init(mm_channel_queue_t * queue);
104 int32_t mm_channel_superbuf_queue_deinit(mm_channel_queue_t * queue);
105 int32_t mm_channel_superbuf_comp_and_enqueue(mm_channel_t *ch_obj,
106 mm_channel_queue_t * queue,
107 mm_camera_buf_info_t *buf);
108 mm_channel_queue_node_t* mm_channel_superbuf_dequeue(mm_channel_queue_t * queue);
109 int32_t mm_channel_superbuf_bufdone_overflow(mm_channel_t *my_obj,
110 mm_channel_queue_t *queue);
111 int32_t mm_channel_superbuf_skip(mm_channel_t *my_obj,
112 mm_channel_queue_t *queue);
113
114 /*===========================================================================
115 * FUNCTION : mm_channel_util_get_stream_by_handler
116 *
117 * DESCRIPTION: utility function to get a stream object from its handle
118 *
119 * PARAMETERS :
120 * @cam_obj: ptr to a channel object
121 * @handler: stream handle
122 *
123 * RETURN : ptr to a stream object.
124 * NULL if failed.
125 *==========================================================================*/
mm_channel_util_get_stream_by_handler(mm_channel_t * ch_obj,uint32_t handler)126 mm_stream_t * mm_channel_util_get_stream_by_handler(
127 mm_channel_t * ch_obj,
128 uint32_t handler)
129 {
130 int i;
131 mm_stream_t *s_obj = NULL;
132 for(i = 0; i < MAX_STREAM_NUM_IN_BUNDLE; i++) {
133 if ((MM_STREAM_STATE_NOTUSED != ch_obj->streams[i].state) &&
134 (handler == ch_obj->streams[i].my_hdl)) {
135 s_obj = &ch_obj->streams[i];
136 break;
137 }
138 }
139 return s_obj;
140 }
141
142 /*===========================================================================
143 * FUNCTION : mm_channel_dispatch_super_buf
144 *
145 * DESCRIPTION: dispatch super buffer of bundle to registered user
146 *
147 * PARAMETERS :
148 * @cmd_cb : ptr storing matched super buf information
149 * @userdata: user data ptr
150 *
151 * RETURN : none
152 *==========================================================================*/
mm_channel_dispatch_super_buf(mm_camera_cmdcb_t * cmd_cb,void * user_data)153 static void mm_channel_dispatch_super_buf(mm_camera_cmdcb_t *cmd_cb,
154 void* user_data)
155 {
156 mm_channel_t * my_obj = (mm_channel_t *)user_data;
157
158 if (NULL == my_obj) {
159 return;
160 }
161
162 if (MM_CAMERA_CMD_TYPE_SUPER_BUF_DATA_CB != cmd_cb->cmd_type) {
163 CDBG_ERROR("%s: Wrong cmd_type (%d) for super buf dataCB",
164 __func__, cmd_cb->cmd_type);
165 return;
166 }
167
168 if (my_obj->bundle.super_buf_notify_cb) {
169 my_obj->bundle.super_buf_notify_cb(&cmd_cb->u.superbuf, my_obj->bundle.user_data);
170 }
171 }
172
173 /*===========================================================================
174 * FUNCTION : mm_channel_process_stream_buf
175 *
176 * DESCRIPTION: handle incoming buffer from stream in a bundle. In this function,
177 * matching logic will be performed on incoming stream frames.
178 * Will depends on the bundle attribute, either storing matched frames
179 * in the superbuf queue, or sending matched superbuf frames to upper
180 * layer through registered callback.
181 *
182 * PARAMETERS :
183 * @cmd_cb : ptr storing matched super buf information
184 * @userdata: user data ptr
185 *
186 * RETURN : none
187 *==========================================================================*/
mm_channel_process_stream_buf(mm_camera_cmdcb_t * cmd_cb,void * user_data)188 static void mm_channel_process_stream_buf(mm_camera_cmdcb_t * cmd_cb,
189 void *user_data)
190 {
191 mm_camera_super_buf_notify_mode_t notify_mode;
192 mm_channel_queue_node_t *node = NULL;
193 mm_channel_t *ch_obj = (mm_channel_t *)user_data;
194 if (NULL == ch_obj) {
195 return;
196 }
197
198 if (MM_CAMERA_CMD_TYPE_DATA_CB == cmd_cb->cmd_type) {
199 /* comp_and_enqueue */
200 mm_channel_superbuf_comp_and_enqueue(
201 ch_obj,
202 &ch_obj->bundle.superbuf_queue,
203 &cmd_cb->u.buf);
204 } else if (MM_CAMERA_CMD_TYPE_REQ_DATA_CB == cmd_cb->cmd_type) {
205 /* skip frames if needed */
206 ch_obj->pending_cnt = cmd_cb->u.req_buf.num_buf_requested;
207 mm_channel_superbuf_skip(ch_obj, &ch_obj->bundle.superbuf_queue);
208 } else if (MM_CAMERA_CMD_TYPE_CONFIG_NOTIFY == cmd_cb->cmd_type) {
209 ch_obj->bundle.superbuf_queue.attr.notify_mode = cmd_cb->u.notify_mode;
210 } else if (MM_CAMERA_CMD_TYPE_FLUSH_QUEUE == cmd_cb->cmd_type) {
211 ch_obj->bundle.superbuf_queue.expected_frame_id = cmd_cb->u.frame_idx;
212 mm_channel_superbuf_flush(ch_obj, &ch_obj->bundle.superbuf_queue);
213 return;
214 }
215 notify_mode = ch_obj->bundle.superbuf_queue.attr.notify_mode;
216
217 /* bufdone for overflowed bufs */
218 mm_channel_superbuf_bufdone_overflow(ch_obj, &ch_obj->bundle.superbuf_queue);
219
220 /* dispatch frame if pending_cnt>0 or is in continuous streaming mode */
221 while ( (ch_obj->pending_cnt > 0) ||
222 (MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS == notify_mode) ) {
223
224 /* dequeue */
225 node = mm_channel_superbuf_dequeue(&ch_obj->bundle.superbuf_queue);
226 if (NULL != node) {
227 /* decrease pending_cnt */
228 CDBG("%s: Super Buffer received, Call client callback, pending_cnt=%d",
229 __func__, ch_obj->pending_cnt);
230 if (MM_CAMERA_SUPER_BUF_NOTIFY_BURST == notify_mode) {
231 ch_obj->pending_cnt--;
232 }
233
234 /* dispatch superbuf */
235 if (NULL != ch_obj->bundle.super_buf_notify_cb) {
236 uint8_t i;
237 mm_camera_cmdcb_t* cb_node = NULL;
238
239 CDBG("%s: Send superbuf to HAL, pending_cnt=%d",
240 __func__, ch_obj->pending_cnt);
241
242 /* send cam_sem_post to wake up cb thread to dispatch super buffer */
243 cb_node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
244 if (NULL != cb_node) {
245 memset(cb_node, 0, sizeof(mm_camera_cmdcb_t));
246 cb_node->cmd_type = MM_CAMERA_CMD_TYPE_SUPER_BUF_DATA_CB;
247 cb_node->u.superbuf.num_bufs = node->num_of_bufs;
248 for (i=0; i<node->num_of_bufs; i++) {
249 cb_node->u.superbuf.bufs[i] = node->super_buf[i].buf;
250 }
251 cb_node->u.superbuf.camera_handle = ch_obj->cam_obj->my_hdl;
252 cb_node->u.superbuf.ch_id = ch_obj->my_hdl;
253
254 /* enqueue to cb thread */
255 cam_queue_enq(&(ch_obj->cb_thread.cmd_queue), cb_node);
256
257 /* wake up cb thread */
258 cam_sem_post(&(ch_obj->cb_thread.cmd_sem));
259 } else {
260 CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__);
261 /* buf done with the nonuse super buf */
262 for (i=0; i<node->num_of_bufs; i++) {
263 mm_channel_qbuf(ch_obj, node->super_buf[i].buf);
264 }
265 }
266 } else {
267 /* buf done with the nonuse super buf */
268 uint8_t i;
269 for (i=0; i<node->num_of_bufs; i++) {
270 mm_channel_qbuf(ch_obj, node->super_buf[i].buf);
271 }
272 }
273 free(node);
274 } else {
275 /* no superbuf avail, break the loop */
276 break;
277 }
278 }
279 }
280
281 /*===========================================================================
282 * FUNCTION : mm_channel_fsm_fn
283 *
284 * DESCRIPTION: channel finite state machine entry function. Depends on channel
285 * state, incoming event will be handled differently.
286 *
287 * PARAMETERS :
288 * @my_obj : ptr to a channel object
289 * @evt : channel event to be processed
290 * @in_val : input event payload. Can be NULL if not needed.
291 * @out_val : output payload, Can be NULL if not needed.
292 *
293 * RETURN : int32_t type of status
294 * 0 -- success
295 * -1 -- failure
296 *==========================================================================*/
mm_channel_fsm_fn(mm_channel_t * my_obj,mm_channel_evt_type_t evt,void * in_val,void * out_val)297 int32_t mm_channel_fsm_fn(mm_channel_t *my_obj,
298 mm_channel_evt_type_t evt,
299 void * in_val,
300 void * out_val)
301 {
302 int32_t rc = -1;
303
304 CDBG("%s : E state = %d", __func__, my_obj->state);
305 switch (my_obj->state) {
306 case MM_CHANNEL_STATE_NOTUSED:
307 rc = mm_channel_fsm_fn_notused(my_obj, evt, in_val, out_val);
308 break;
309 case MM_CHANNEL_STATE_STOPPED:
310 rc = mm_channel_fsm_fn_stopped(my_obj, evt, in_val, out_val);
311 break;
312 case MM_CHANNEL_STATE_ACTIVE:
313 rc = mm_channel_fsm_fn_active(my_obj, evt, in_val, out_val);
314 break;
315 case MM_CHANNEL_STATE_PAUSED:
316 rc = mm_channel_fsm_fn_paused(my_obj, evt, in_val, out_val);
317 break;
318 default:
319 CDBG("%s: Not a valid state (%d)", __func__, my_obj->state);
320 break;
321 }
322
323 /* unlock ch_lock */
324 pthread_mutex_unlock(&my_obj->ch_lock);
325 CDBG("%s : X rc = %d", __func__, rc);
326 return rc;
327 }
328
329 /*===========================================================================
330 * FUNCTION : mm_channel_fsm_fn_notused
331 *
332 * DESCRIPTION: channel finite state machine function to handle event
333 * in NOT_USED state.
334 *
335 * PARAMETERS :
336 * @my_obj : ptr to a channel object
337 * @evt : channel event to be processed
338 * @in_val : input event payload. Can be NULL if not needed.
339 * @out_val : output payload, Can be NULL if not needed.
340 *
341 * RETURN : int32_t type of status
342 * 0 -- success
343 * -1 -- failure
344 *==========================================================================*/
mm_channel_fsm_fn_notused(mm_channel_t * my_obj,mm_channel_evt_type_t evt,void * in_val,void * out_val)345 int32_t mm_channel_fsm_fn_notused(mm_channel_t *my_obj,
346 mm_channel_evt_type_t evt,
347 void * in_val,
348 void * out_val)
349 {
350 int32_t rc = -1;
351
352 switch (evt) {
353 default:
354 CDBG_ERROR("%s: invalid state (%d) for evt (%d), in(%p), out(%p)",
355 __func__, my_obj->state, evt, in_val, out_val);
356 break;
357 }
358
359 return rc;
360 }
361
362 /*===========================================================================
363 * FUNCTION : mm_channel_fsm_fn_stopped
364 *
365 * DESCRIPTION: channel finite state machine function to handle event
366 * in STOPPED state.
367 *
368 * PARAMETERS :
369 * @my_obj : ptr to a channel object
370 * @evt : channel event to be processed
371 * @in_val : input event payload. Can be NULL if not needed.
372 * @out_val : output payload, Can be NULL if not needed.
373 *
374 * RETURN : int32_t type of status
375 * 0 -- success
376 * -1 -- failure
377 *==========================================================================*/
mm_channel_fsm_fn_stopped(mm_channel_t * my_obj,mm_channel_evt_type_t evt,void * in_val,void * out_val)378 int32_t mm_channel_fsm_fn_stopped(mm_channel_t *my_obj,
379 mm_channel_evt_type_t evt,
380 void * in_val,
381 void * out_val)
382 {
383 int32_t rc = 0;
384 CDBG("%s : E evt = %d", __func__, evt);
385 switch (evt) {
386 case MM_CHANNEL_EVT_ADD_STREAM:
387 {
388 uint32_t s_hdl = 0;
389 s_hdl = mm_channel_add_stream(my_obj);
390 *((uint32_t*)out_val) = s_hdl;
391 rc = 0;
392 }
393 break;
394 case MM_CHANNEL_EVT_DEL_STREAM:
395 {
396 uint32_t s_id = (uint32_t)in_val;
397 rc = mm_channel_del_stream(my_obj, s_id);
398 }
399 break;
400 case MM_CHANNEL_EVT_START:
401 {
402 rc = mm_channel_start(my_obj);
403 /* first stream started in stopped state
404 * move to active state */
405 if (0 == rc) {
406 my_obj->state = MM_CHANNEL_STATE_ACTIVE;
407 }
408 }
409 break;
410 case MM_CHANNEL_EVT_CONFIG_STREAM:
411 {
412 mm_evt_paylod_config_stream_t *payload =
413 (mm_evt_paylod_config_stream_t *)in_val;
414 rc = mm_channel_config_stream(my_obj,
415 payload->stream_id,
416 payload->config);
417 }
418 break;
419 case MM_CHANNEL_EVT_GET_BUNDLE_INFO:
420 {
421 cam_bundle_config_t *payload =
422 (cam_bundle_config_t *)in_val;
423 rc = mm_channel_get_bundle_info(my_obj, payload);
424 }
425 break;
426 case MM_CHANNEL_EVT_DELETE:
427 {
428 mm_channel_release(my_obj);
429 rc = 0;
430 }
431 break;
432 case MM_CHANNEL_EVT_SET_STREAM_PARM:
433 {
434 mm_evt_paylod_set_get_stream_parms_t *payload =
435 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
436 rc = mm_channel_set_stream_parm(my_obj, payload);
437 }
438 break;
439 case MM_CHANNEL_EVT_GET_STREAM_PARM:
440 {
441 mm_evt_paylod_set_get_stream_parms_t *payload =
442 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
443 rc = mm_channel_get_stream_parm(my_obj, payload);
444 }
445 break;
446 case MM_CHANNEL_EVT_DO_STREAM_ACTION:
447 {
448 mm_evt_paylod_do_stream_action_t *payload =
449 (mm_evt_paylod_do_stream_action_t *)in_val;
450 rc = mm_channel_do_stream_action(my_obj, payload);
451 }
452 break;
453 case MM_CHANNEL_EVT_MAP_STREAM_BUF:
454 {
455 mm_evt_paylod_map_stream_buf_t *payload =
456 (mm_evt_paylod_map_stream_buf_t *)in_val;
457 rc = mm_channel_map_stream_buf(my_obj, payload);
458 }
459 break;
460 case MM_CHANNEL_EVT_UNMAP_STREAM_BUF:
461 {
462 mm_evt_paylod_unmap_stream_buf_t *payload =
463 (mm_evt_paylod_unmap_stream_buf_t *)in_val;
464 rc = mm_channel_unmap_stream_buf(my_obj, payload);
465 }
466 break;
467 default:
468 CDBG_ERROR("%s: invalid state (%d) for evt (%d)",
469 __func__, my_obj->state, evt);
470 break;
471 }
472 CDBG("%s : E rc = %d", __func__, rc);
473 return rc;
474 }
475
476 /*===========================================================================
477 * FUNCTION : mm_channel_fsm_fn_active
478 *
479 * DESCRIPTION: channel finite state machine function to handle event
480 * in ACTIVE state.
481 *
482 * PARAMETERS :
483 * @my_obj : ptr to a channel object
484 * @evt : channel event to be processed
485 * @in_val : input event payload. Can be NULL if not needed.
486 * @out_val : output payload, Can be NULL if not needed.
487 *
488 * RETURN : int32_t type of status
489 * 0 -- success
490 * -1 -- failure
491 *==========================================================================*/
mm_channel_fsm_fn_active(mm_channel_t * my_obj,mm_channel_evt_type_t evt,void * in_val,void * out_val)492 int32_t mm_channel_fsm_fn_active(mm_channel_t *my_obj,
493 mm_channel_evt_type_t evt,
494 void * in_val,
495 void * out_val)
496 {
497 int32_t rc = 0;
498
499 CDBG("%s : E evt = %d", __func__, evt);
500 switch (evt) {
501 case MM_CHANNEL_EVT_STOP:
502 {
503 rc = mm_channel_stop(my_obj);
504 my_obj->state = MM_CHANNEL_STATE_STOPPED;
505 }
506 break;
507 case MM_CHANNEL_EVT_REQUEST_SUPER_BUF:
508 {
509 uint32_t num_buf_requested = (uint32_t)in_val;
510 rc = mm_channel_request_super_buf(my_obj, num_buf_requested);
511 }
512 break;
513 case MM_CHANNEL_EVT_CANCEL_REQUEST_SUPER_BUF:
514 {
515 rc = mm_channel_cancel_super_buf_request(my_obj);
516 }
517 break;
518 case MM_CHANNEL_EVT_FLUSH_SUPER_BUF_QUEUE:
519 {
520 uint32_t frame_idx = (uint32_t)in_val;
521 rc = mm_channel_flush_super_buf_queue(my_obj, frame_idx);
522 }
523 break;
524 case MM_CHANNEL_EVT_CONFIG_NOTIFY_MODE:
525 {
526 mm_camera_super_buf_notify_mode_t notify_mode = ( mm_camera_super_buf_notify_mode_t ) in_val;
527 rc = mm_channel_config_notify_mode(my_obj, notify_mode);
528 }
529 break;
530 case MM_CHANNEL_EVT_SET_STREAM_PARM:
531 {
532 mm_evt_paylod_set_get_stream_parms_t *payload =
533 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
534 rc = mm_channel_set_stream_parm(my_obj, payload);
535 }
536 break;
537 case MM_CHANNEL_EVT_GET_STREAM_PARM:
538 {
539 mm_evt_paylod_set_get_stream_parms_t *payload =
540 (mm_evt_paylod_set_get_stream_parms_t *)in_val;
541 rc = mm_channel_get_stream_parm(my_obj, payload);
542 }
543 break;
544 case MM_CHANNEL_EVT_DO_STREAM_ACTION:
545 {
546 mm_evt_paylod_do_stream_action_t *payload =
547 (mm_evt_paylod_do_stream_action_t *)in_val;
548 rc = mm_channel_do_stream_action(my_obj, payload);
549 }
550 break;
551 case MM_CHANNEL_EVT_MAP_STREAM_BUF:
552 {
553 mm_evt_paylod_map_stream_buf_t *payload =
554 (mm_evt_paylod_map_stream_buf_t *)in_val;
555 if (payload != NULL &&
556 payload->buf_type == CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF) {
557 rc = mm_channel_map_stream_buf(my_obj, payload);
558 } else {
559 CDBG_ERROR("%s: cannot map regualr stream buf in active state", __func__);
560 }
561 }
562 break;
563 case MM_CHANNEL_EVT_UNMAP_STREAM_BUF:
564 {
565 mm_evt_paylod_unmap_stream_buf_t *payload =
566 (mm_evt_paylod_unmap_stream_buf_t *)in_val;
567 if (payload != NULL &&
568 payload->buf_type == CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF) {
569 rc = mm_channel_unmap_stream_buf(my_obj, payload);
570 } else {
571 CDBG_ERROR("%s: cannot unmap regualr stream buf in active state", __func__);
572 }
573 }
574 break;
575 default:
576 CDBG_ERROR("%s: invalid state (%d) for evt (%d), in(%p), out(%p)",
577 __func__, my_obj->state, evt, in_val, out_val);
578 break;
579 }
580 CDBG("%s : X rc = %d", __func__, rc);
581 return rc;
582 }
583
584 /*===========================================================================
585 * FUNCTION : mm_channel_fsm_fn_paused
586 *
587 * DESCRIPTION: channel finite state machine function to handle event
588 * in PAUSED state.
589 *
590 * PARAMETERS :
591 * @my_obj : ptr to a channel object
592 * @evt : channel event to be processed
593 * @in_val : input event payload. Can be NULL if not needed.
594 * @out_val : output payload, Can be NULL if not needed.
595 *
596 * RETURN : int32_t type of status
597 * 0 -- success
598 * -1 -- failure
599 *==========================================================================*/
mm_channel_fsm_fn_paused(mm_channel_t * my_obj,mm_channel_evt_type_t evt,void * in_val,void * out_val)600 int32_t mm_channel_fsm_fn_paused(mm_channel_t *my_obj,
601 mm_channel_evt_type_t evt,
602 void * in_val,
603 void * out_val)
604 {
605 int32_t rc = 0;
606
607 /* currently we are not supporting pause/resume channel */
608 CDBG_ERROR("%s: invalid state (%d) for evt (%d), in(%p), out(%p)",
609 __func__, my_obj->state, evt, in_val, out_val);
610
611 return rc;
612 }
613
614 /*===========================================================================
615 * FUNCTION : mm_channel_init
616 *
617 * DESCRIPTION: initialize a channel
618 *
619 * PARAMETERS :
620 * @my_obj : channel object be to initialized
621 * @attr : bundle attribute of the channel if needed
622 * @channel_cb : callback function for bundle data notify
623 * @userdata : user data ptr
624 *
625 * RETURN : int32_t type of status
626 * 0 -- success
627 * -1 -- failure
628 * NOTE : if no bundle data notify is needed, meaning each stream in the
629 * channel will have its own stream data notify callback, then
630 * attr, channel_cb, and userdata can be NULL. In this case,
631 * no matching logic will be performed in channel for the bundling.
632 *==========================================================================*/
mm_channel_init(mm_channel_t * my_obj,mm_camera_channel_attr_t * attr,mm_camera_buf_notify_t channel_cb,void * userdata)633 int32_t mm_channel_init(mm_channel_t *my_obj,
634 mm_camera_channel_attr_t *attr,
635 mm_camera_buf_notify_t channel_cb,
636 void *userdata)
637 {
638 int32_t rc = 0;
639
640 my_obj->bundle.super_buf_notify_cb = channel_cb;
641 my_obj->bundle.user_data = userdata;
642 if (NULL != attr) {
643 my_obj->bundle.superbuf_queue.attr = *attr;
644 }
645
646 CDBG("%s : Launch data poll thread in channel open", __func__);
647 mm_camera_poll_thread_launch(&my_obj->poll_thread[0],
648 MM_CAMERA_POLL_TYPE_DATA);
649
650 /* change state to stopped state */
651 my_obj->state = MM_CHANNEL_STATE_STOPPED;
652 return rc;
653 }
654
655 /*===========================================================================
656 * FUNCTION : mm_channel_release
657 *
658 * DESCRIPTION: release a channel resource. Channel state will move to UNUSED
659 * state after this call.
660 *
661 * PARAMETERS :
662 * @my_obj : channel object
663 *
664 * RETURN : none
665 *==========================================================================*/
mm_channel_release(mm_channel_t * my_obj)666 void mm_channel_release(mm_channel_t *my_obj)
667 {
668 /* stop data poll thread */
669 mm_camera_poll_thread_release(&my_obj->poll_thread[0]);
670
671 /* change state to notused state */
672 my_obj->state = MM_CHANNEL_STATE_NOTUSED;
673 }
674
675 /*===========================================================================
676 * FUNCTION : mm_channel_add_stream
677 *
678 * DESCRIPTION: add a stream into the channel
679 *
680 * PARAMETERS :
681 * @my_obj : channel object
682 *
683 * RETURN : uint32_t type of stream handle
684 * 0 -- invalid stream handle, meaning the op failed
685 * >0 -- successfully added a stream with a valid handle
686 *==========================================================================*/
mm_channel_add_stream(mm_channel_t * my_obj)687 uint32_t mm_channel_add_stream(mm_channel_t *my_obj)
688 {
689 int32_t rc = 0;
690 uint8_t idx = 0;
691 uint32_t s_hdl = 0;
692 mm_stream_t *stream_obj = NULL;
693
694 CDBG("%s : E", __func__);
695 /* check available stream */
696 for (idx = 0; idx < MAX_STREAM_NUM_IN_BUNDLE; idx++) {
697 if (MM_STREAM_STATE_NOTUSED == my_obj->streams[idx].state) {
698 stream_obj = &my_obj->streams[idx];
699 break;
700 }
701 }
702 if (NULL == stream_obj) {
703 CDBG_ERROR("%s: streams reach max, no more stream allowed to add", __func__);
704 return s_hdl;
705 }
706
707 /* initialize stream object */
708 memset(stream_obj, 0, sizeof(mm_stream_t));
709 stream_obj->my_hdl = mm_camera_util_generate_handler(idx);
710 stream_obj->ch_obj = my_obj;
711 pthread_mutex_init(&stream_obj->buf_lock, NULL);
712 pthread_mutex_init(&stream_obj->cb_lock, NULL);
713 stream_obj->state = MM_STREAM_STATE_INITED;
714
715 /* acquire stream */
716 rc = mm_stream_fsm_fn(stream_obj, MM_STREAM_EVT_ACQUIRE, NULL, NULL);
717 if (0 == rc) {
718 s_hdl = stream_obj->my_hdl;
719 } else {
720 /* error during acquire, de-init */
721 pthread_mutex_destroy(&stream_obj->buf_lock);
722 pthread_mutex_destroy(&stream_obj->cb_lock);
723 memset(stream_obj, 0, sizeof(mm_stream_t));
724 }
725 CDBG("%s : stream handle = %d", __func__, s_hdl);
726 return s_hdl;
727 }
728
729 /*===========================================================================
730 * FUNCTION : mm_channel_del_stream
731 *
732 * DESCRIPTION: delete a stream from the channel bu its handle
733 *
734 * PARAMETERS :
735 * @my_obj : channel object
736 * @stream_id : stream handle
737 *
738 * RETURN : int32_t type of status
739 * 0 -- success
740 * -1 -- failure
741 * NOTE : assume steam is stooped before it can be deleted
742 *==========================================================================*/
mm_channel_del_stream(mm_channel_t * my_obj,uint32_t stream_id)743 int32_t mm_channel_del_stream(mm_channel_t *my_obj,
744 uint32_t stream_id)
745 {
746 int rc = -1;
747 mm_stream_t * stream_obj = NULL;
748 stream_obj = mm_channel_util_get_stream_by_handler(my_obj, stream_id);
749
750 if (NULL == stream_obj) {
751 CDBG_ERROR("%s :Invalid Stream Object for stream_id = %d",
752 __func__, stream_id);
753 return rc;
754 }
755
756 rc = mm_stream_fsm_fn(stream_obj,
757 MM_STREAM_EVT_RELEASE,
758 NULL,
759 NULL);
760
761 return rc;
762 }
763
764 /*===========================================================================
765 * FUNCTION : mm_channel_config_stream
766 *
767 * DESCRIPTION: configure a stream
768 *
769 * PARAMETERS :
770 * @my_obj : channel object
771 * @stream_id : stream handle
772 * @config : stream configuration
773 *
774 * RETURN : int32_t type of status
775 * 0 -- success
776 * -1 -- failure
777 *==========================================================================*/
mm_channel_config_stream(mm_channel_t * my_obj,uint32_t stream_id,mm_camera_stream_config_t * config)778 int32_t mm_channel_config_stream(mm_channel_t *my_obj,
779 uint32_t stream_id,
780 mm_camera_stream_config_t *config)
781 {
782 int rc = -1;
783 mm_stream_t * stream_obj = NULL;
784 CDBG("%s : E stream ID = %d", __func__, stream_id);
785 stream_obj = mm_channel_util_get_stream_by_handler(my_obj, stream_id);
786
787 if (NULL == stream_obj) {
788 CDBG_ERROR("%s :Invalid Stream Object for stream_id = %d", __func__, stream_id);
789 return rc;
790 }
791
792 /* set stream fmt */
793 rc = mm_stream_fsm_fn(stream_obj,
794 MM_STREAM_EVT_SET_FMT,
795 (void *)config,
796 NULL);
797 CDBG("%s : X rc = %d",__func__,rc);
798 return rc;
799 }
800
801 /*===========================================================================
802 * FUNCTION : mm_channel_get_bundle_info
803 *
804 * DESCRIPTION: query bundle info of the channel, which should include all
805 * streams within this channel
806 *
807 * PARAMETERS :
808 * @my_obj : channel object
809 * @bundle_info : bundle info to be filled in
810 *
811 * RETURN : int32_t type of status
812 * 0 -- success
813 * -1 -- failure
814 *==========================================================================*/
mm_channel_get_bundle_info(mm_channel_t * my_obj,cam_bundle_config_t * bundle_info)815 int32_t mm_channel_get_bundle_info(mm_channel_t *my_obj,
816 cam_bundle_config_t *bundle_info)
817 {
818 int i;
819 mm_stream_t *s_obj = NULL;
820 int32_t rc = 0;
821
822 memset(bundle_info, 0, sizeof(cam_bundle_config_t));
823 bundle_info->bundle_id = my_obj->my_hdl;
824 bundle_info->num_of_streams = 0;
825 for (i = 0; i < MAX_STREAM_NUM_IN_BUNDLE; i++) {
826 if (my_obj->streams[i].my_hdl > 0) {
827 s_obj = mm_channel_util_get_stream_by_handler(my_obj,
828 my_obj->streams[i].my_hdl);
829 if (NULL != s_obj) {
830 if (CAM_STREAM_TYPE_METADATA != s_obj->stream_info->stream_type) {
831 bundle_info->stream_ids[bundle_info->num_of_streams++] =
832 s_obj->server_stream_id;
833 }
834 } else {
835 CDBG_ERROR("%s: cannot find stream obj (%d) by handler (%d)",
836 __func__, i, my_obj->streams[i].my_hdl);
837 rc = -1;
838 break;
839 }
840 }
841 }
842 if (rc != 0) {
843 /* error, reset to 0 */
844 memset(bundle_info, 0, sizeof(cam_bundle_config_t));
845 }
846 return rc;
847 }
848
849 /*===========================================================================
850 * FUNCTION : mm_channel_start
851 *
852 * DESCRIPTION: start a channel, which will start all streams in the channel
853 *
854 * PARAMETERS :
855 * @my_obj : channel object
856 *
857 * RETURN : int32_t type of status
858 * 0 -- success
859 * -1 -- failure
860 *==========================================================================*/
mm_channel_start(mm_channel_t * my_obj)861 int32_t mm_channel_start(mm_channel_t *my_obj)
862 {
863 int32_t rc = 0;
864 int i, j;
865 mm_stream_t *s_objs[MAX_STREAM_NUM_IN_BUNDLE] = {NULL};
866 uint8_t num_streams_to_start = 0;
867 mm_stream_t *s_obj = NULL;
868 int meta_stream_idx = 0;
869
870 for (i = 0; i < MAX_STREAM_NUM_IN_BUNDLE; i++) {
871 if (my_obj->streams[i].my_hdl > 0) {
872 s_obj = mm_channel_util_get_stream_by_handler(my_obj,
873 my_obj->streams[i].my_hdl);
874 if (NULL != s_obj) {
875 /* remember meta data stream index */
876 if (s_obj->stream_info->stream_type == CAM_STREAM_TYPE_METADATA) {
877 meta_stream_idx = num_streams_to_start;
878 }
879 s_objs[num_streams_to_start++] = s_obj;
880 }
881 }
882 }
883
884 if (meta_stream_idx > 0 ) {
885 /* always start meta data stream first, so switch the stream object with the first one */
886 s_obj = s_objs[0];
887 s_objs[0] = s_objs[meta_stream_idx];
888 s_objs[meta_stream_idx] = s_obj;
889 }
890
891 if (NULL != my_obj->bundle.super_buf_notify_cb) {
892 /* need to send up cb, therefore launch thread */
893 /* init superbuf queue */
894 mm_channel_superbuf_queue_init(&my_obj->bundle.superbuf_queue);
895 my_obj->bundle.superbuf_queue.num_streams = num_streams_to_start;
896 my_obj->bundle.superbuf_queue.expected_frame_id = 0;
897
898 for (i = 0; i < num_streams_to_start; i++) {
899 /* set bundled flag to streams */
900 s_objs[i]->is_bundled = 1;
901 /* init bundled streams to invalid value -1 */
902 my_obj->bundle.superbuf_queue.bundled_streams[i] = s_objs[i]->my_hdl;
903 }
904
905 /* launch cb thread for dispatching super buf through cb */
906 mm_camera_cmd_thread_launch(&my_obj->cb_thread,
907 mm_channel_dispatch_super_buf,
908 (void*)my_obj);
909
910 /* launch cmd thread for super buf dataCB */
911 mm_camera_cmd_thread_launch(&my_obj->cmd_thread,
912 mm_channel_process_stream_buf,
913 (void*)my_obj);
914
915 /* set flag to TRUE */
916 my_obj->bundle.is_active = TRUE;
917 }
918
919 for (i = 0; i < num_streams_to_start; i++) {
920 /* all streams within a channel should be started at the same time */
921 if (s_objs[i]->state == MM_STREAM_STATE_ACTIVE) {
922 CDBG_ERROR("%s: stream already started idx(%d)", __func__, i);
923 rc = -1;
924 break;
925 }
926
927 /* allocate buf */
928 rc = mm_stream_fsm_fn(s_objs[i],
929 MM_STREAM_EVT_GET_BUF,
930 NULL,
931 NULL);
932 if (0 != rc) {
933 CDBG_ERROR("%s: get buf failed at idx(%d)", __func__, i);
934 break;
935 }
936
937 /* reg buf */
938 rc = mm_stream_fsm_fn(s_objs[i],
939 MM_STREAM_EVT_REG_BUF,
940 NULL,
941 NULL);
942 if (0 != rc) {
943 CDBG_ERROR("%s: reg buf failed at idx(%d)", __func__, i);
944 break;
945 }
946
947 /* start stream */
948 rc = mm_stream_fsm_fn(s_objs[i],
949 MM_STREAM_EVT_START,
950 NULL,
951 NULL);
952 if (0 != rc) {
953 CDBG_ERROR("%s: start stream failed at idx(%d)", __func__, i);
954 break;
955 }
956 }
957
958 /* error handling */
959 if (0 != rc) {
960 for (j=0; j<=i; j++) {
961 /* stop streams*/
962 mm_stream_fsm_fn(s_objs[j],
963 MM_STREAM_EVT_STOP,
964 NULL,
965 NULL);
966
967 /* unreg buf */
968 mm_stream_fsm_fn(s_objs[j],
969 MM_STREAM_EVT_UNREG_BUF,
970 NULL,
971 NULL);
972
973 /* put buf back */
974 mm_stream_fsm_fn(s_objs[j],
975 MM_STREAM_EVT_PUT_BUF,
976 NULL,
977 NULL);
978 }
979 }
980
981 return rc;
982 }
983
984 /*===========================================================================
985 * FUNCTION : mm_channel_stop
986 *
987 * DESCRIPTION: stop a channel, which will stop all streams in the channel
988 *
989 * PARAMETERS :
990 * @my_obj : channel object
991 *
992 * RETURN : int32_t type of status
993 * 0 -- success
994 * -1 -- failure
995 *==========================================================================*/
mm_channel_stop(mm_channel_t * my_obj)996 int32_t mm_channel_stop(mm_channel_t *my_obj)
997 {
998 int32_t rc = 0;
999 int i;
1000 mm_stream_t *s_objs[MAX_STREAM_NUM_IN_BUNDLE] = {NULL};
1001 uint8_t num_streams_to_stop = 0;
1002 mm_stream_t *s_obj = NULL;
1003 int meta_stream_idx = 0;
1004
1005 for (i = 0; i < MAX_STREAM_NUM_IN_BUNDLE; i++) {
1006 if (my_obj->streams[i].my_hdl > 0) {
1007 s_obj = mm_channel_util_get_stream_by_handler(my_obj,
1008 my_obj->streams[i].my_hdl);
1009 if (NULL != s_obj) {
1010 /* remember meta data stream index */
1011 if (s_obj->stream_info->stream_type == CAM_STREAM_TYPE_METADATA) {
1012 meta_stream_idx = num_streams_to_stop;
1013 }
1014 s_objs[num_streams_to_stop++] = s_obj;
1015 }
1016 }
1017 }
1018
1019 if (meta_stream_idx < num_streams_to_stop - 1 ) {
1020 /* always stop meta data stream last, so switch the stream object with the last one */
1021 s_obj = s_objs[num_streams_to_stop - 1];
1022 s_objs[num_streams_to_stop - 1] = s_objs[meta_stream_idx];
1023 s_objs[meta_stream_idx] = s_obj;
1024 }
1025
1026 for (i = 0; i < num_streams_to_stop; i++) {
1027 /* stream off */
1028 mm_stream_fsm_fn(s_objs[i],
1029 MM_STREAM_EVT_STOP,
1030 NULL,
1031 NULL);
1032
1033 /* unreg buf at kernel */
1034 mm_stream_fsm_fn(s_objs[i],
1035 MM_STREAM_EVT_UNREG_BUF,
1036 NULL,
1037 NULL);
1038 }
1039
1040 /* destroy super buf cmd thread */
1041 if (TRUE == my_obj->bundle.is_active) {
1042 /* first stop bundle thread */
1043 mm_camera_cmd_thread_release(&my_obj->cmd_thread);
1044 mm_camera_cmd_thread_release(&my_obj->cb_thread);
1045
1046 /* deinit superbuf queue */
1047 mm_channel_superbuf_queue_deinit(&my_obj->bundle.superbuf_queue);
1048
1049 /* memset bundle info */
1050 memset(&my_obj->bundle, 0, sizeof(mm_channel_bundle_t));
1051 }
1052
1053 /* since all streams are stopped, we are safe to
1054 * release all buffers allocated in stream */
1055 for (i = 0; i < num_streams_to_stop; i++) {
1056 /* put buf back */
1057 mm_stream_fsm_fn(s_objs[i],
1058 MM_STREAM_EVT_PUT_BUF,
1059 NULL,
1060 NULL);
1061 }
1062
1063 return rc;
1064 }
1065
1066 /*===========================================================================
1067 * FUNCTION : mm_channel_request_super_buf
1068 *
1069 * DESCRIPTION: for burst mode in bundle, reuqest certain amount of matched
1070 * frames from superbuf queue
1071 *
1072 * PARAMETERS :
1073 * @my_obj : channel object
1074 * @num_buf_requested : number of matched frames needed
1075 *
1076 * RETURN : int32_t type of status
1077 * 0 -- success
1078 * -1 -- failure
1079 *==========================================================================*/
mm_channel_request_super_buf(mm_channel_t * my_obj,uint32_t num_buf_requested)1080 int32_t mm_channel_request_super_buf(mm_channel_t *my_obj, uint32_t num_buf_requested)
1081 {
1082 int32_t rc = 0;
1083 mm_camera_cmdcb_t* node = NULL;
1084
1085 /* set pending_cnt
1086 * will trigger dispatching super frames if pending_cnt > 0 */
1087 /* send cam_sem_post to wake up cmd thread to dispatch super buffer */
1088 node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
1089 if (NULL != node) {
1090 memset(node, 0, sizeof(mm_camera_cmdcb_t));
1091 node->cmd_type = MM_CAMERA_CMD_TYPE_REQ_DATA_CB;
1092 node->u.req_buf.num_buf_requested = num_buf_requested;
1093
1094 /* enqueue to cmd thread */
1095 cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node);
1096
1097 /* wake up cmd thread */
1098 cam_sem_post(&(my_obj->cmd_thread.cmd_sem));
1099 } else {
1100 CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__);
1101 rc = -1;
1102 }
1103
1104 return rc;
1105 }
1106
1107 /*===========================================================================
1108 * FUNCTION : mm_channel_cancel_super_buf_request
1109 *
1110 * DESCRIPTION: for burst mode in bundle, cancel the reuqest for certain amount
1111 * of matched frames from superbuf queue
1112 *
1113 * PARAMETERS :
1114 * @my_obj : channel object
1115 *
1116 * RETURN : int32_t type of status
1117 * 0 -- success
1118 * -1 -- failure
1119 *==========================================================================*/
mm_channel_cancel_super_buf_request(mm_channel_t * my_obj)1120 int32_t mm_channel_cancel_super_buf_request(mm_channel_t *my_obj)
1121 {
1122 int32_t rc = 0;
1123 /* reset pending_cnt */
1124 rc = mm_channel_request_super_buf(my_obj, 0);
1125 return rc;
1126 }
1127
1128 /*===========================================================================
1129 * FUNCTION : mm_channel_flush_super_buf_queue
1130 *
1131 * DESCRIPTION: flush superbuf queue
1132 *
1133 * PARAMETERS :
1134 * @my_obj : channel object
1135 * @frame_idx : frame idx until which to flush all superbufs
1136 *
1137 * RETURN : int32_t type of status
1138 * 0 -- success
1139 * -1 -- failure
1140 *==========================================================================*/
mm_channel_flush_super_buf_queue(mm_channel_t * my_obj,uint32_t frame_idx)1141 int32_t mm_channel_flush_super_buf_queue(mm_channel_t *my_obj, uint32_t frame_idx)
1142 {
1143 int32_t rc = 0;
1144 mm_camera_cmdcb_t* node = NULL;
1145
1146 node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
1147 if (NULL != node) {
1148 memset(node, 0, sizeof(mm_camera_cmdcb_t));
1149 node->cmd_type = MM_CAMERA_CMD_TYPE_FLUSH_QUEUE;
1150 node->u.frame_idx = frame_idx;
1151
1152 /* enqueue to cmd thread */
1153 cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node);
1154
1155 /* wake up cmd thread */
1156 cam_sem_post(&(my_obj->cmd_thread.cmd_sem));
1157 } else {
1158 CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__);
1159 rc = -1;
1160 }
1161
1162 return rc;
1163 }
1164
1165 /*===========================================================================
1166 * FUNCTION : mm_channel_config_notify_mode
1167 *
1168 * DESCRIPTION: configure notification mode
1169 *
1170 * PARAMETERS :
1171 * @my_obj : channel object
1172 * @notify_mode : notification mode
1173 *
1174 * RETURN : int32_t type of status
1175 * 0 -- success
1176 * -1 -- failure
1177 *==========================================================================*/
mm_channel_config_notify_mode(mm_channel_t * my_obj,mm_camera_super_buf_notify_mode_t notify_mode)1178 int32_t mm_channel_config_notify_mode(mm_channel_t *my_obj,
1179 mm_camera_super_buf_notify_mode_t notify_mode)
1180 {
1181 int32_t rc = 0;
1182 mm_camera_cmdcb_t* node = NULL;
1183
1184 node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
1185 if (NULL != node) {
1186 memset(node, 0, sizeof(mm_camera_cmdcb_t));
1187 node->u.notify_mode = notify_mode;
1188 node->cmd_type = MM_CAMERA_CMD_TYPE_CONFIG_NOTIFY;
1189
1190 /* enqueue to cmd thread */
1191 cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node);
1192
1193 /* wake up cmd thread */
1194 cam_sem_post(&(my_obj->cmd_thread.cmd_sem));
1195 } else {
1196 CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__);
1197 rc = -1;
1198 }
1199
1200 return rc;
1201 }
1202
1203 /*===========================================================================
1204 * FUNCTION : mm_channel_qbuf
1205 *
1206 * DESCRIPTION: enqueue buffer back to kernel
1207 *
1208 * PARAMETERS :
1209 * @my_obj : channel object
1210 * @buf : buf ptr to be enqueued
1211 *
1212 * RETURN : int32_t type of status
1213 * 0 -- success
1214 * -1 -- failure
1215 *==========================================================================*/
mm_channel_qbuf(mm_channel_t * my_obj,mm_camera_buf_def_t * buf)1216 int32_t mm_channel_qbuf(mm_channel_t *my_obj,
1217 mm_camera_buf_def_t *buf)
1218 {
1219 int32_t rc = -1;
1220 mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj, buf->stream_id);
1221
1222 if (NULL != s_obj) {
1223 rc = mm_stream_fsm_fn(s_obj,
1224 MM_STREAM_EVT_QBUF,
1225 (void *)buf,
1226 NULL);
1227 }
1228
1229 return rc;
1230 }
1231
1232 /*===========================================================================
1233 * FUNCTION : mm_channel_set_stream_parms
1234 *
1235 * DESCRIPTION: set parameters per stream
1236 *
1237 * PARAMETERS :
1238 * @my_obj : channel object
1239 * @s_id : stream handle
1240 * @parms : ptr to a param struct to be set to server
1241 *
1242 * RETURN : int32_t type of status
1243 * 0 -- success
1244 * -1 -- failure
1245 * NOTE : Assume the parms struct buf is already mapped to server via
1246 * domain socket. Corresponding fields of parameters to be set
1247 * are already filled in by upper layer caller.
1248 *==========================================================================*/
mm_channel_set_stream_parm(mm_channel_t * my_obj,mm_evt_paylod_set_get_stream_parms_t * payload)1249 int32_t mm_channel_set_stream_parm(mm_channel_t *my_obj,
1250 mm_evt_paylod_set_get_stream_parms_t *payload)
1251 {
1252 int32_t rc = -1;
1253 mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj,
1254 payload->stream_id);
1255 if (NULL != s_obj) {
1256 rc = mm_stream_fsm_fn(s_obj,
1257 MM_STREAM_EVT_SET_PARM,
1258 (void *)payload,
1259 NULL);
1260 }
1261
1262 return rc;
1263 }
1264
1265 /*===========================================================================
1266 * FUNCTION : mm_channel_get_stream_parms
1267 *
1268 * DESCRIPTION: get parameters per stream
1269 *
1270 * PARAMETERS :
1271 * @my_obj : channel object
1272 * @s_id : stream handle
1273 * @parms : ptr to a param struct to be get from server
1274 *
1275 * RETURN : int32_t type of status
1276 * 0 -- success
1277 * -1 -- failure
1278 * NOTE : Assume the parms struct buf is already mapped to server via
1279 * domain socket. Parameters to be get from server are already
1280 * filled in by upper layer caller. After this call, corresponding
1281 * fields of requested parameters will be filled in by server with
1282 * detailed information.
1283 *==========================================================================*/
mm_channel_get_stream_parm(mm_channel_t * my_obj,mm_evt_paylod_set_get_stream_parms_t * payload)1284 int32_t mm_channel_get_stream_parm(mm_channel_t *my_obj,
1285 mm_evt_paylod_set_get_stream_parms_t *payload)
1286 {
1287 int32_t rc = -1;
1288 mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj,
1289 payload->stream_id);
1290 if (NULL != s_obj) {
1291 rc = mm_stream_fsm_fn(s_obj,
1292 MM_STREAM_EVT_GET_PARM,
1293 (void *)payload,
1294 NULL);
1295 }
1296
1297 return rc;
1298 }
1299
1300 /*===========================================================================
1301 * FUNCTION : mm_channel_do_stream_action
1302 *
1303 * DESCRIPTION: request server to perform stream based action. Maybe removed later
1304 * if the functionality is included in mm_camera_set_parms
1305 *
1306 * PARAMETERS :
1307 * @my_obj : channel object
1308 * @s_id : stream handle
1309 * @actions : ptr to an action struct buf to be performed by server
1310 *
1311 * RETURN : int32_t type of status
1312 * 0 -- success
1313 * -1 -- failure
1314 * NOTE : Assume the action struct buf is already mapped to server via
1315 * domain socket. Actions to be performed by server are already
1316 * filled in by upper layer caller.
1317 *==========================================================================*/
mm_channel_do_stream_action(mm_channel_t * my_obj,mm_evt_paylod_do_stream_action_t * payload)1318 int32_t mm_channel_do_stream_action(mm_channel_t *my_obj,
1319 mm_evt_paylod_do_stream_action_t *payload)
1320 {
1321 int32_t rc = -1;
1322 mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj,
1323 payload->stream_id);
1324 if (NULL != s_obj) {
1325 rc = mm_stream_fsm_fn(s_obj,
1326 MM_STREAM_EVT_DO_ACTION,
1327 (void *)payload,
1328 NULL);
1329 }
1330
1331 return rc;
1332 }
1333
1334 /*===========================================================================
1335 * FUNCTION : mm_channel_map_stream_buf
1336 *
1337 * DESCRIPTION: mapping stream buffer via domain socket to server
1338 *
1339 * PARAMETERS :
1340 * @my_obj : channel object
1341 * @payload : ptr to payload for mapping
1342 *
1343 * RETURN : int32_t type of status
1344 * 0 -- success
1345 * -1 -- failure
1346 *==========================================================================*/
mm_channel_map_stream_buf(mm_channel_t * my_obj,mm_evt_paylod_map_stream_buf_t * payload)1347 int32_t mm_channel_map_stream_buf(mm_channel_t *my_obj,
1348 mm_evt_paylod_map_stream_buf_t *payload)
1349 {
1350 int32_t rc = -1;
1351 mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj,
1352 payload->stream_id);
1353 if (NULL != s_obj) {
1354 rc = mm_stream_map_buf(s_obj,
1355 payload->buf_type,
1356 payload->buf_idx,
1357 payload->plane_idx,
1358 payload->fd,
1359 payload->size);
1360 }
1361
1362 return rc;
1363 }
1364
1365 /*===========================================================================
1366 * FUNCTION : mm_channel_unmap_stream_buf
1367 *
1368 * DESCRIPTION: unmapping stream buffer via domain socket to server
1369 *
1370 * PARAMETERS :
1371 * @my_obj : channel object
1372 * @payload : ptr to unmap payload
1373 *
1374 * RETURN : int32_t type of status
1375 * 0 -- success
1376 * -1 -- failure
1377 *==========================================================================*/
mm_channel_unmap_stream_buf(mm_channel_t * my_obj,mm_evt_paylod_unmap_stream_buf_t * payload)1378 int32_t mm_channel_unmap_stream_buf(mm_channel_t *my_obj,
1379 mm_evt_paylod_unmap_stream_buf_t *payload)
1380 {
1381 int32_t rc = -1;
1382 mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj,
1383 payload->stream_id);
1384 if (NULL != s_obj) {
1385 rc = mm_stream_unmap_buf(s_obj, payload->buf_type,
1386 payload->buf_idx, payload->plane_idx);
1387 }
1388
1389 return rc;
1390 }
1391
1392 /*===========================================================================
1393 * FUNCTION : mm_channel_superbuf_queue_init
1394 *
1395 * DESCRIPTION: initialize superbuf queue in the channel
1396 *
1397 * PARAMETERS :
1398 * @queue : ptr to superbuf queue to be initialized
1399 *
1400 * RETURN : int32_t type of status
1401 * 0 -- success
1402 * -1 -- failure
1403 *==========================================================================*/
mm_channel_superbuf_queue_init(mm_channel_queue_t * queue)1404 int32_t mm_channel_superbuf_queue_init(mm_channel_queue_t * queue)
1405 {
1406 return cam_queue_init(&queue->que);
1407 }
1408
1409 /*===========================================================================
1410 * FUNCTION : mm_channel_superbuf_queue_deinit
1411 *
1412 * DESCRIPTION: deinitialize superbuf queue in the channel
1413 *
1414 * PARAMETERS :
1415 * @queue : ptr to superbuf queue to be deinitialized
1416 *
1417 * RETURN : int32_t type of status
1418 * 0 -- success
1419 * -1 -- failure
1420 *==========================================================================*/
mm_channel_superbuf_queue_deinit(mm_channel_queue_t * queue)1421 int32_t mm_channel_superbuf_queue_deinit(mm_channel_queue_t * queue)
1422 {
1423 return cam_queue_deinit(&queue->que);
1424 }
1425
1426 /*===========================================================================
1427 * FUNCTION : mm_channel_util_seq_comp_w_rollover
1428 *
1429 * DESCRIPTION: utility function to handle sequence number comparison with rollover
1430 *
1431 * PARAMETERS :
1432 * @v1 : first value to be compared
1433 * @v2 : second value to be compared
1434 *
1435 * RETURN : int8_t type of comparison result
1436 * >0 -- v1 larger than v2
1437 * =0 -- vi equal to v2
1438 * <0 -- v1 smaller than v2
1439 *==========================================================================*/
mm_channel_util_seq_comp_w_rollover(uint32_t v1,uint32_t v2)1440 int8_t mm_channel_util_seq_comp_w_rollover(uint32_t v1,
1441 uint32_t v2)
1442 {
1443 int8_t ret = 0;
1444
1445 /* TODO: need to handle the case if v2 roll over to 0 */
1446 if (v1 > v2) {
1447 ret = 1;
1448 } else if (v1 < v2) {
1449 ret = -1;
1450 }
1451
1452 return ret;
1453 }
1454
1455 /*===========================================================================
1456 * FUNCTION : mm_channel_handle_metadata
1457 *
1458 * DESCRIPTION: Handle frame matching logic change due to metadata
1459 *
1460 * PARAMETERS :
1461 * @ch_obj : channel object
1462 * @queue : superbuf queue
1463 * @buf_info: new buffer from stream
1464 *
1465 * RETURN : int32_t type of status
1466 * 0 -- success
1467 * -1 -- failure
1468 *==========================================================================*/
mm_channel_handle_metadata(mm_channel_t * ch_obj,mm_channel_queue_t * queue,mm_camera_buf_info_t * buf_info)1469 int32_t mm_channel_handle_metadata(
1470 mm_channel_t* ch_obj,
1471 mm_channel_queue_t * queue,
1472 mm_camera_buf_info_t *buf_info)
1473 {
1474 int rc = 0 ;
1475 mm_stream_t* stream_obj = NULL;
1476 stream_obj = mm_channel_util_get_stream_by_handler(ch_obj,
1477 buf_info->stream_id);
1478
1479 if (NULL == stream_obj) {
1480 CDBG_ERROR("%s: Invalid Stream Object for stream_id = %d",
1481 __func__, buf_info->stream_id);
1482 rc = -1;
1483 goto end;
1484 }
1485 if (NULL == stream_obj->stream_info) {
1486 CDBG_ERROR("%s: NULL stream info for stream_id = %d",
1487 __func__, buf_info->stream_id);
1488 rc = -1;
1489 goto end;
1490 }
1491
1492 if (CAM_STREAM_TYPE_METADATA == stream_obj->stream_info->stream_type) {
1493 const cam_metadata_info_t *metadata;
1494 metadata = (const cam_metadata_info_t *)buf_info->buf->buffer;
1495
1496 if (NULL == metadata) {
1497 CDBG_ERROR("%s: NULL metadata buffer for metadata stream",
1498 __func__);
1499 rc = -1;
1500 goto end;
1501 }
1502
1503 if (metadata->is_prep_snapshot_done_valid &&
1504 metadata->is_good_frame_idx_range_valid) {
1505 CDBG_ERROR("%s: prep_snapshot_done and good_idx_range shouldn't be valid at the same time", __func__);
1506 rc = -1;
1507 goto end;
1508 }
1509
1510 if (metadata->is_prep_snapshot_done_valid &&
1511 metadata->prep_snapshot_done_state == NEED_FUTURE_FRAME) {
1512
1513 /* Set expected frame id to a future frame idx, large enough to wait
1514 * for good_frame_idx_range, and small enough to still capture an image */
1515 const int max_future_frame_offset = 100;
1516 queue->expected_frame_id += max_future_frame_offset;
1517
1518 mm_channel_superbuf_flush(ch_obj, queue);
1519 } else if (metadata->is_good_frame_idx_range_valid) {
1520 if (metadata->good_frame_idx_range.min_frame_idx >
1521 queue->expected_frame_id) {
1522 CDBG_HIGH("%s: min_frame_idx %d is greater than expected_frame_id %d",
1523 __func__, metadata->good_frame_idx_range.min_frame_idx,
1524 queue->expected_frame_id);
1525 }
1526 queue->expected_frame_id =
1527 metadata->good_frame_idx_range.min_frame_idx;
1528 }
1529 }
1530 end:
1531 return rc;
1532 }
1533
1534 /*===========================================================================
1535 * FUNCTION : mm_channel_superbuf_comp_and_enqueue
1536 *
1537 * DESCRIPTION: implementation for matching logic for superbuf
1538 *
1539 * PARAMETERS :
1540 * @ch_obj : channel object
1541 * @queue : superbuf queue
1542 * @buf_info: new buffer from stream
1543 *
1544 * RETURN : int32_t type of status
1545 * 0 -- success
1546 * -1 -- failure
1547 *==========================================================================*/
mm_channel_superbuf_comp_and_enqueue(mm_channel_t * ch_obj,mm_channel_queue_t * queue,mm_camera_buf_info_t * buf_info)1548 int32_t mm_channel_superbuf_comp_and_enqueue(
1549 mm_channel_t* ch_obj,
1550 mm_channel_queue_t *queue,
1551 mm_camera_buf_info_t *buf_info)
1552 {
1553 cam_node_t* node = NULL;
1554 struct cam_list *head = NULL;
1555 struct cam_list *pos = NULL;
1556 mm_channel_queue_node_t* super_buf = NULL;
1557 uint8_t buf_s_idx, i, found_super_buf, unmatched_bundles;
1558 struct cam_list *last_buf, *insert_before_buf;
1559
1560 CDBG("%s: E", __func__);
1561 for (buf_s_idx = 0; buf_s_idx < queue->num_streams; buf_s_idx++) {
1562 if (buf_info->stream_id == queue->bundled_streams[buf_s_idx]) {
1563 break;
1564 }
1565 }
1566 if (buf_s_idx == queue->num_streams) {
1567 CDBG_ERROR("%s: buf from stream (%d) not bundled", __func__, buf_info->stream_id);
1568 return -1;
1569 }
1570
1571 if (mm_channel_handle_metadata(ch_obj, queue, buf_info) < 0) {
1572 return -1;
1573 }
1574
1575 if (mm_channel_util_seq_comp_w_rollover(buf_info->frame_idx,
1576 queue->expected_frame_id) < 0) {
1577 /* incoming buf is older than expected buf id, will discard it */
1578 mm_channel_qbuf(ch_obj, buf_info->buf);
1579 return 0;
1580 }
1581
1582 if (MM_CAMERA_SUPER_BUF_PRIORITY_NORMAL != queue->attr.priority) {
1583 /* TODO */
1584 /* need to decide if we want to queue the frame based on focus or exposure
1585 * if frame not to be queued, we need to qbuf it back */
1586 }
1587
1588 /* comp */
1589 pthread_mutex_lock(&queue->que.lock);
1590 head = &queue->que.head.list;
1591 /* get the last one in the queue which is possibly having no matching */
1592 pos = head->next;
1593
1594 found_super_buf = 0;
1595 unmatched_bundles = 0;
1596 last_buf = NULL;
1597 insert_before_buf = NULL;
1598 while (pos != head) {
1599 node = member_of(pos, cam_node_t, list);
1600 super_buf = (mm_channel_queue_node_t*)node->data;
1601 if (NULL != super_buf) {
1602 if (super_buf->matched) {
1603 /* find a matched super buf, move to next one */
1604 pos = pos->next;
1605 continue;
1606 } else if ( buf_info->frame_idx == super_buf->frame_idx ) {
1607 /* have an unmatched super buf that matches our frame idx,
1608 * break the loop */
1609 found_super_buf = 1;
1610 break;
1611 } else {
1612 unmatched_bundles++;
1613 if ( NULL == last_buf ) {
1614 if ( super_buf->frame_idx < buf_info->frame_idx ) {
1615 last_buf = pos;
1616 }
1617 }
1618 if ( NULL == insert_before_buf ) {
1619 if ( super_buf->frame_idx > buf_info->frame_idx ) {
1620 insert_before_buf = pos;
1621 }
1622 }
1623 pos = pos->next;
1624 }
1625 }
1626 }
1627
1628 if ( found_super_buf ) {
1629 super_buf->super_buf[buf_s_idx] = *buf_info;
1630
1631 /* check if superbuf is all matched */
1632 super_buf->matched = 1;
1633 for (i=0; i < super_buf->num_of_bufs; i++) {
1634 if (super_buf->super_buf[i].frame_idx == 0) {
1635 super_buf->matched = 0;
1636 break;
1637 }
1638 }
1639
1640 if (super_buf->matched) {
1641 queue->expected_frame_id = buf_info->frame_idx + queue->attr.post_frame_skip;
1642 queue->match_cnt++;
1643 /* Any older unmatched buffer need to be released */
1644 if ( last_buf ) {
1645 while ( last_buf != pos ) {
1646 node = member_of(last_buf, cam_node_t, list);
1647 super_buf = (mm_channel_queue_node_t*)node->data;
1648 if (NULL != super_buf) {
1649 for (i=0; i<super_buf->num_of_bufs; i++) {
1650 if (super_buf->super_buf[i].frame_idx != 0) {
1651 mm_channel_qbuf(ch_obj, super_buf->super_buf[i].buf);
1652 }
1653 }
1654 queue->que.size--;
1655 last_buf = last_buf->next;
1656 cam_list_del_node(&node->list);
1657 free(node);
1658 free(super_buf);
1659 } else {
1660 CDBG_ERROR(" %s : Invalid superbuf in queue!", __func__);
1661 break;
1662 }
1663 }
1664 }
1665 }
1666 } else {
1667 if ( ( queue->attr.max_unmatched_frames < unmatched_bundles ) &&
1668 ( NULL == last_buf ) ) {
1669 /* incoming frame is older than the last bundled one */
1670 mm_channel_qbuf(ch_obj, buf_info->buf);
1671 } else {
1672 if ( queue->attr.max_unmatched_frames < unmatched_bundles ) {
1673 /* release the oldest bundled superbuf */
1674 node = member_of(last_buf, cam_node_t, list);
1675 super_buf = (mm_channel_queue_node_t*)node->data;
1676 for (i=0; i<super_buf->num_of_bufs; i++) {
1677 if (super_buf->super_buf[i].frame_idx != 0) {
1678 mm_channel_qbuf(ch_obj, super_buf->super_buf[i].buf);
1679 }
1680 }
1681 queue->que.size--;
1682 node = member_of(last_buf, cam_node_t, list);
1683 cam_list_del_node(&node->list);
1684 free(node);
1685 free(super_buf);
1686 }
1687 /* insert the new frame at the appropriate position. */
1688
1689 mm_channel_queue_node_t *new_buf = NULL;
1690 cam_node_t* new_node = NULL;
1691
1692 new_buf = (mm_channel_queue_node_t*)malloc(sizeof(mm_channel_queue_node_t));
1693 new_node = (cam_node_t*)malloc(sizeof(cam_node_t));
1694 if (NULL != new_buf && NULL != new_node) {
1695 memset(new_buf, 0, sizeof(mm_channel_queue_node_t));
1696 memset(new_node, 0, sizeof(cam_node_t));
1697 new_node->data = (void *)new_buf;
1698 new_buf->num_of_bufs = queue->num_streams;
1699 new_buf->super_buf[buf_s_idx] = *buf_info;
1700 new_buf->frame_idx = buf_info->frame_idx;
1701
1702 /* enqueue */
1703 if ( insert_before_buf ) {
1704 cam_list_insert_before_node(&new_node->list, insert_before_buf);
1705 } else {
1706 cam_list_add_tail_node(&new_node->list, &queue->que.head.list);
1707 }
1708 queue->que.size++;
1709
1710 if(queue->num_streams == 1) {
1711 new_buf->matched = 1;
1712
1713 queue->expected_frame_id = buf_info->frame_idx + queue->attr.post_frame_skip;
1714 queue->match_cnt++;
1715 }
1716 } else {
1717 /* No memory */
1718 if (NULL != new_buf) {
1719 free(new_buf);
1720 }
1721 if (NULL != new_node) {
1722 free(new_node);
1723 }
1724 /* qbuf the new buf since we cannot enqueue */
1725 mm_channel_qbuf(ch_obj, buf_info->buf);
1726 }
1727 }
1728 }
1729
1730 pthread_mutex_unlock(&queue->que.lock);
1731
1732 CDBG("%s: X", __func__);
1733 return 0;
1734 }
1735
1736 /*===========================================================================
1737 * FUNCTION : mm_channel_superbuf_dequeue_internal
1738 *
1739 * DESCRIPTION: internal implementation for dequeue from the superbuf queue
1740 *
1741 * PARAMETERS :
1742 * @queue : superbuf queue
1743 * @matched_only : if dequeued buf should be matched
1744 *
1745 * RETURN : ptr to a node from superbuf queue
1746 *==========================================================================*/
mm_channel_superbuf_dequeue_internal(mm_channel_queue_t * queue,uint8_t matched_only)1747 mm_channel_queue_node_t* mm_channel_superbuf_dequeue_internal(mm_channel_queue_t * queue,
1748 uint8_t matched_only)
1749 {
1750 cam_node_t* node = NULL;
1751 struct cam_list *head = NULL;
1752 struct cam_list *pos = NULL;
1753 mm_channel_queue_node_t* super_buf = NULL;
1754
1755 head = &queue->que.head.list;
1756 pos = head->next;
1757 if (pos != head) {
1758 /* get the first node */
1759 node = member_of(pos, cam_node_t, list);
1760 super_buf = (mm_channel_queue_node_t*)node->data;
1761 if ( (NULL != super_buf) &&
1762 (matched_only == TRUE) &&
1763 (super_buf->matched == FALSE) ) {
1764 /* require to dequeue matched frame only, but this superbuf is not matched,
1765 simply set return ptr to NULL */
1766 super_buf = NULL;
1767 }
1768 if (NULL != super_buf) {
1769 /* remove from the queue */
1770 cam_list_del_node(&node->list);
1771 queue->que.size--;
1772 if (super_buf->matched == TRUE) {
1773 queue->match_cnt--;
1774 }
1775 free(node);
1776 }
1777 }
1778
1779 return super_buf;
1780 }
1781
1782 /*===========================================================================
1783 * FUNCTION : mm_channel_superbuf_dequeue
1784 *
1785 * DESCRIPTION: dequeue from the superbuf queue
1786 *
1787 * PARAMETERS :
1788 * @queue : superbuf queue
1789 *
1790 * RETURN : ptr to a node from superbuf queue
1791 *==========================================================================*/
mm_channel_superbuf_dequeue(mm_channel_queue_t * queue)1792 mm_channel_queue_node_t* mm_channel_superbuf_dequeue(mm_channel_queue_t * queue)
1793 {
1794 mm_channel_queue_node_t* super_buf = NULL;
1795
1796 pthread_mutex_lock(&queue->que.lock);
1797 super_buf = mm_channel_superbuf_dequeue_internal(queue, TRUE);
1798 pthread_mutex_unlock(&queue->que.lock);
1799
1800 return super_buf;
1801 }
1802
1803 /*===========================================================================
1804 * FUNCTION : mm_channel_superbuf_bufdone_overflow
1805 *
1806 * DESCRIPTION: keep superbuf queue no larger than watermark set by upper layer
1807 * via channel attribute
1808 *
1809 * PARAMETERS :
1810 * @my_obj : channel object
1811 * @queue : superbuf queue
1812 *
1813 * RETURN : int32_t type of status
1814 * 0 -- success
1815 * -1 -- failure
1816 *==========================================================================*/
mm_channel_superbuf_bufdone_overflow(mm_channel_t * my_obj,mm_channel_queue_t * queue)1817 int32_t mm_channel_superbuf_bufdone_overflow(mm_channel_t* my_obj,
1818 mm_channel_queue_t * queue)
1819 {
1820 int32_t rc = 0, i;
1821 mm_channel_queue_node_t* super_buf = NULL;
1822 if (MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS == queue->attr.notify_mode) {
1823 /* for continuous streaming mode, no overflow is needed */
1824 return 0;
1825 }
1826
1827 CDBG("%s: before match_cnt=%d, water_mark=%d",
1828 __func__, queue->match_cnt, queue->attr.water_mark);
1829 /* bufdone overflowed bufs */
1830 pthread_mutex_lock(&queue->que.lock);
1831 while (queue->match_cnt > queue->attr.water_mark) {
1832 super_buf = mm_channel_superbuf_dequeue_internal(queue, TRUE);
1833 if (NULL != super_buf) {
1834 for (i=0; i<super_buf->num_of_bufs; i++) {
1835 if (NULL != super_buf->super_buf[i].buf) {
1836 mm_channel_qbuf(my_obj, super_buf->super_buf[i].buf);
1837 }
1838 }
1839 free(super_buf);
1840 }
1841 }
1842 pthread_mutex_unlock(&queue->que.lock);
1843 CDBG("%s: after match_cnt=%d, water_mark=%d",
1844 __func__, queue->match_cnt, queue->attr.water_mark);
1845
1846 return rc;
1847 }
1848
1849 /*===========================================================================
1850 * FUNCTION : mm_channel_superbuf_skip
1851 *
1852 * DESCRIPTION: depends on the lookback configuration of the channel attribute,
1853 * unwanted superbufs will be removed from the superbuf queue.
1854 *
1855 * PARAMETERS :
1856 * @my_obj : channel object
1857 * @queue : superbuf queue
1858 *
1859 * RETURN : int32_t type of status
1860 * 0 -- success
1861 * -1 -- failure
1862 *==========================================================================*/
mm_channel_superbuf_skip(mm_channel_t * my_obj,mm_channel_queue_t * queue)1863 int32_t mm_channel_superbuf_skip(mm_channel_t* my_obj,
1864 mm_channel_queue_t * queue)
1865 {
1866 int32_t rc = 0, i;
1867 mm_channel_queue_node_t* super_buf = NULL;
1868 if (MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS == queue->attr.notify_mode) {
1869 /* for continuous streaming mode, no skip is needed */
1870 return 0;
1871 }
1872
1873 /* bufdone overflowed bufs */
1874 pthread_mutex_lock(&queue->que.lock);
1875 while (queue->match_cnt > queue->attr.look_back) {
1876 super_buf = mm_channel_superbuf_dequeue_internal(queue, TRUE);
1877 if (NULL != super_buf) {
1878 for (i=0; i<super_buf->num_of_bufs; i++) {
1879 if (NULL != super_buf->super_buf[i].buf) {
1880 mm_channel_qbuf(my_obj, super_buf->super_buf[i].buf);
1881 }
1882 }
1883 free(super_buf);
1884 }
1885 }
1886 pthread_mutex_unlock(&queue->que.lock);
1887
1888 return rc;
1889 }
1890
1891 /*===========================================================================
1892 * FUNCTION : mm_channel_superbuf_flush
1893 *
1894 * DESCRIPTION: flush the superbuf queue.
1895 *
1896 * PARAMETERS :
1897 * @my_obj : channel object
1898 * @queue : superbuf queue
1899 *
1900 * RETURN : int32_t type of status
1901 * 0 -- success
1902 * -1 -- failure
1903 *==========================================================================*/
mm_channel_superbuf_flush(mm_channel_t * my_obj,mm_channel_queue_t * queue)1904 int32_t mm_channel_superbuf_flush(mm_channel_t* my_obj,
1905 mm_channel_queue_t * queue)
1906 {
1907 int32_t rc = 0, i;
1908 mm_channel_queue_node_t* super_buf = NULL;
1909
1910 /* bufdone bufs */
1911 pthread_mutex_lock(&queue->que.lock);
1912 super_buf = mm_channel_superbuf_dequeue_internal(queue, FALSE);
1913 while (super_buf != NULL) {
1914 for (i=0; i<super_buf->num_of_bufs; i++) {
1915 if (NULL != super_buf->super_buf[i].buf) {
1916 mm_channel_qbuf(my_obj, super_buf->super_buf[i].buf);
1917 }
1918 }
1919 free(super_buf);
1920 super_buf = mm_channel_superbuf_dequeue_internal(queue, FALSE);
1921 }
1922 pthread_mutex_unlock(&queue->que.lock);
1923
1924 return rc;
1925 }
1926