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