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