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