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