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->my_hdl = mm_camera_util_generate_handler(idx); 712 stream_obj->ch_obj = my_obj; 713 pthread_mutex_init(&stream_obj->buf_lock, NULL); 714 pthread_mutex_init(&stream_obj->cb_lock, NULL); 715 stream_obj->state = MM_STREAM_STATE_INITED; 716 717 /* acquire stream */ 718 rc = mm_stream_fsm_fn(stream_obj, MM_STREAM_EVT_ACQUIRE, NULL, NULL); 719 if (0 == rc) { 720 s_hdl = stream_obj->my_hdl; 721 } else { 722 /* error during acquire, de-init */ 723 pthread_mutex_destroy(&stream_obj->buf_lock); 724 pthread_mutex_destroy(&stream_obj->cb_lock); 725 memset(stream_obj, 0, sizeof(mm_stream_t)); 726 } 727 CDBG("%s : stream handle = %d", __func__, s_hdl); 728 return s_hdl; 729 } 730 731 /*=========================================================================== 732 * FUNCTION : mm_channel_del_stream 733 * 734 * DESCRIPTION: delete a stream from the channel bu its handle 735 * 736 * PARAMETERS : 737 * @my_obj : channel object 738 * @stream_id : stream handle 739 * 740 * RETURN : int32_t type of status 741 * 0 -- success 742 * -1 -- failure 743 * NOTE : assume steam is stooped before it can be deleted 744 *==========================================================================*/ 745 int32_t mm_channel_del_stream(mm_channel_t *my_obj, 746 uint32_t stream_id) 747 { 748 int rc = -1; 749 mm_stream_t * stream_obj = NULL; 750 stream_obj = mm_channel_util_get_stream_by_handler(my_obj, stream_id); 751 752 if (NULL == stream_obj) { 753 CDBG_ERROR("%s :Invalid Stream Object for stream_id = %d", 754 __func__, stream_id); 755 return rc; 756 } 757 758 rc = mm_stream_fsm_fn(stream_obj, 759 MM_STREAM_EVT_RELEASE, 760 NULL, 761 NULL); 762 763 return rc; 764 } 765 766 /*=========================================================================== 767 * FUNCTION : mm_channel_config_stream 768 * 769 * DESCRIPTION: configure a stream 770 * 771 * PARAMETERS : 772 * @my_obj : channel object 773 * @stream_id : stream handle 774 * @config : stream configuration 775 * 776 * RETURN : int32_t type of status 777 * 0 -- success 778 * -1 -- failure 779 *==========================================================================*/ 780 int32_t mm_channel_config_stream(mm_channel_t *my_obj, 781 uint32_t stream_id, 782 mm_camera_stream_config_t *config) 783 { 784 int rc = -1; 785 mm_stream_t * stream_obj = NULL; 786 CDBG("%s : E stream ID = %d", __func__, stream_id); 787 stream_obj = mm_channel_util_get_stream_by_handler(my_obj, stream_id); 788 789 if (NULL == stream_obj) { 790 CDBG_ERROR("%s :Invalid Stream Object for stream_id = %d", __func__, stream_id); 791 return rc; 792 } 793 794 /* set stream fmt */ 795 rc = mm_stream_fsm_fn(stream_obj, 796 MM_STREAM_EVT_SET_FMT, 797 (void *)config, 798 NULL); 799 CDBG("%s : X rc = %d",__func__,rc); 800 return rc; 801 } 802 803 /*=========================================================================== 804 * FUNCTION : mm_channel_get_bundle_info 805 * 806 * DESCRIPTION: query bundle info of the channel, which should include all 807 * streams within this channel 808 * 809 * PARAMETERS : 810 * @my_obj : channel object 811 * @bundle_info : bundle info to be filled in 812 * 813 * RETURN : int32_t type of status 814 * 0 -- success 815 * -1 -- failure 816 *==========================================================================*/ 817 int32_t mm_channel_get_bundle_info(mm_channel_t *my_obj, 818 cam_bundle_config_t *bundle_info) 819 { 820 int i; 821 mm_stream_t *s_obj = NULL; 822 int32_t rc = 0; 823 824 memset(bundle_info, 0, sizeof(cam_bundle_config_t)); 825 bundle_info->bundle_id = my_obj->my_hdl; 826 bundle_info->num_of_streams = 0; 827 for (i = 0; i < MAX_STREAM_NUM_IN_BUNDLE; i++) { 828 if (my_obj->streams[i].my_hdl > 0) { 829 s_obj = mm_channel_util_get_stream_by_handler(my_obj, 830 my_obj->streams[i].my_hdl); 831 if (NULL != s_obj) { 832 if (CAM_STREAM_TYPE_METADATA != s_obj->stream_info->stream_type) { 833 bundle_info->stream_ids[bundle_info->num_of_streams++] = 834 s_obj->server_stream_id; 835 } 836 } else { 837 CDBG_ERROR("%s: cannot find stream obj (%d) by handler (%d)", 838 __func__, i, my_obj->streams[i].my_hdl); 839 rc = -1; 840 break; 841 } 842 } 843 } 844 if (rc != 0) { 845 /* error, reset to 0 */ 846 memset(bundle_info, 0, sizeof(cam_bundle_config_t)); 847 } 848 return rc; 849 } 850 851 /*=========================================================================== 852 * FUNCTION : mm_channel_start 853 * 854 * DESCRIPTION: start a channel, which will start all streams in the channel 855 * 856 * PARAMETERS : 857 * @my_obj : channel object 858 * 859 * RETURN : int32_t type of status 860 * 0 -- success 861 * -1 -- failure 862 *==========================================================================*/ 863 int32_t mm_channel_start(mm_channel_t *my_obj) 864 { 865 int32_t rc = 0; 866 int i, j; 867 mm_stream_t *s_objs[MAX_STREAM_NUM_IN_BUNDLE] = {NULL}; 868 uint8_t num_streams_to_start = 0; 869 mm_stream_t *s_obj = NULL; 870 int meta_stream_idx = 0; 871 872 for (i = 0; i < MAX_STREAM_NUM_IN_BUNDLE; i++) { 873 if (my_obj->streams[i].my_hdl > 0) { 874 s_obj = mm_channel_util_get_stream_by_handler(my_obj, 875 my_obj->streams[i].my_hdl); 876 if (NULL != s_obj) { 877 /* remember meta data stream index */ 878 if (s_obj->stream_info->stream_type == CAM_STREAM_TYPE_METADATA) { 879 meta_stream_idx = num_streams_to_start; 880 } 881 s_objs[num_streams_to_start++] = s_obj; 882 } 883 } 884 } 885 886 if (meta_stream_idx > 0 ) { 887 /* always start meta data stream first, so switch the stream object with the first one */ 888 s_obj = s_objs[0]; 889 s_objs[0] = s_objs[meta_stream_idx]; 890 s_objs[meta_stream_idx] = s_obj; 891 } 892 893 if (NULL != my_obj->bundle.super_buf_notify_cb) { 894 /* need to send up cb, therefore launch thread */ 895 /* init superbuf queue */ 896 mm_channel_superbuf_queue_init(&my_obj->bundle.superbuf_queue); 897 my_obj->bundle.superbuf_queue.num_streams = num_streams_to_start; 898 my_obj->bundle.superbuf_queue.expected_frame_id = 0; 899 900 for (i = 0; i < num_streams_to_start; i++) { 901 /* set bundled flag to streams */ 902 s_objs[i]->is_bundled = 1; 903 /* init bundled streams to invalid value -1 */ 904 my_obj->bundle.superbuf_queue.bundled_streams[i] = s_objs[i]->my_hdl; 905 } 906 907 /* launch cb thread for dispatching super buf through cb */ 908 mm_camera_cmd_thread_launch(&my_obj->cb_thread, 909 mm_channel_dispatch_super_buf, 910 (void*)my_obj); 911 912 /* launch cmd thread for super buf dataCB */ 913 mm_camera_cmd_thread_launch(&my_obj->cmd_thread, 914 mm_channel_process_stream_buf, 915 (void*)my_obj); 916 917 /* set flag to TRUE */ 918 my_obj->bundle.is_active = TRUE; 919 } 920 921 for (i = 0; i < num_streams_to_start; i++) { 922 /* all streams within a channel should be started at the same time */ 923 if (s_objs[i]->state == MM_STREAM_STATE_ACTIVE) { 924 CDBG_ERROR("%s: stream already started idx(%d)", __func__, i); 925 rc = -1; 926 break; 927 } 928 929 /* allocate buf */ 930 rc = mm_stream_fsm_fn(s_objs[i], 931 MM_STREAM_EVT_GET_BUF, 932 NULL, 933 NULL); 934 if (0 != rc) { 935 CDBG_ERROR("%s: get buf failed at idx(%d)", __func__, i); 936 break; 937 } 938 939 /* reg buf */ 940 rc = mm_stream_fsm_fn(s_objs[i], 941 MM_STREAM_EVT_REG_BUF, 942 NULL, 943 NULL); 944 if (0 != rc) { 945 CDBG_ERROR("%s: reg buf failed at idx(%d)", __func__, i); 946 break; 947 } 948 949 /* start stream */ 950 rc = mm_stream_fsm_fn(s_objs[i], 951 MM_STREAM_EVT_START, 952 NULL, 953 NULL); 954 if (0 != rc) { 955 CDBG_ERROR("%s: start stream failed at idx(%d)", __func__, i); 956 break; 957 } 958 } 959 960 /* error handling */ 961 if (0 != rc) { 962 for (j=0; j<=i; j++) { 963 /* stop streams*/ 964 mm_stream_fsm_fn(s_objs[j], 965 MM_STREAM_EVT_STOP, 966 NULL, 967 NULL); 968 969 /* unreg buf */ 970 mm_stream_fsm_fn(s_objs[j], 971 MM_STREAM_EVT_UNREG_BUF, 972 NULL, 973 NULL); 974 975 /* put buf back */ 976 mm_stream_fsm_fn(s_objs[j], 977 MM_STREAM_EVT_PUT_BUF, 978 NULL, 979 NULL); 980 } 981 } 982 983 return rc; 984 } 985 986 /*=========================================================================== 987 * FUNCTION : mm_channel_stop 988 * 989 * DESCRIPTION: stop a channel, which will stop all streams in the channel 990 * 991 * PARAMETERS : 992 * @my_obj : channel object 993 * 994 * RETURN : int32_t type of status 995 * 0 -- success 996 * -1 -- failure 997 *==========================================================================*/ 998 int32_t mm_channel_stop(mm_channel_t *my_obj) 999 { 1000 int32_t rc = 0; 1001 int i; 1002 mm_stream_t *s_objs[MAX_STREAM_NUM_IN_BUNDLE] = {NULL}; 1003 uint8_t num_streams_to_stop = 0; 1004 mm_stream_t *s_obj = NULL; 1005 int meta_stream_idx = 0; 1006 1007 for (i = 0; i < MAX_STREAM_NUM_IN_BUNDLE; i++) { 1008 if (my_obj->streams[i].my_hdl > 0) { 1009 s_obj = mm_channel_util_get_stream_by_handler(my_obj, 1010 my_obj->streams[i].my_hdl); 1011 if (NULL != s_obj) { 1012 /* remember meta data stream index */ 1013 if (s_obj->stream_info->stream_type == CAM_STREAM_TYPE_METADATA) { 1014 meta_stream_idx = num_streams_to_stop; 1015 } 1016 s_objs[num_streams_to_stop++] = s_obj; 1017 } 1018 } 1019 } 1020 1021 if (meta_stream_idx < num_streams_to_stop - 1 ) { 1022 /* always stop meta data stream last, so switch the stream object with the last one */ 1023 s_obj = s_objs[num_streams_to_stop - 1]; 1024 s_objs[num_streams_to_stop - 1] = s_objs[meta_stream_idx]; 1025 s_objs[meta_stream_idx] = s_obj; 1026 } 1027 1028 for (i = 0; i < num_streams_to_stop; i++) { 1029 /* stream off */ 1030 mm_stream_fsm_fn(s_objs[i], 1031 MM_STREAM_EVT_STOP, 1032 NULL, 1033 NULL); 1034 1035 /* unreg buf at kernel */ 1036 mm_stream_fsm_fn(s_objs[i], 1037 MM_STREAM_EVT_UNREG_BUF, 1038 NULL, 1039 NULL); 1040 } 1041 1042 /* destroy super buf cmd thread */ 1043 if (TRUE == my_obj->bundle.is_active) { 1044 /* first stop bundle thread */ 1045 mm_camera_cmd_thread_release(&my_obj->cmd_thread); 1046 mm_camera_cmd_thread_release(&my_obj->cb_thread); 1047 1048 /* deinit superbuf queue */ 1049 mm_channel_superbuf_queue_deinit(&my_obj->bundle.superbuf_queue); 1050 1051 /* memset bundle info */ 1052 memset(&my_obj->bundle, 0, sizeof(mm_channel_bundle_t)); 1053 } 1054 1055 /* since all streams are stopped, we are safe to 1056 * release all buffers allocated in stream */ 1057 for (i = 0; i < num_streams_to_stop; i++) { 1058 /* put buf back */ 1059 mm_stream_fsm_fn(s_objs[i], 1060 MM_STREAM_EVT_PUT_BUF, 1061 NULL, 1062 NULL); 1063 } 1064 1065 return rc; 1066 } 1067 1068 /*=========================================================================== 1069 * FUNCTION : mm_channel_request_super_buf 1070 * 1071 * DESCRIPTION: for burst mode in bundle, reuqest certain amount of matched 1072 * frames from superbuf queue 1073 * 1074 * PARAMETERS : 1075 * @my_obj : channel object 1076 * @num_buf_requested : number of matched frames needed 1077 * 1078 * RETURN : int32_t type of status 1079 * 0 -- success 1080 * -1 -- failure 1081 *==========================================================================*/ 1082 int32_t mm_channel_request_super_buf(mm_channel_t *my_obj, uint32_t num_buf_requested) 1083 { 1084 int32_t rc = 0; 1085 mm_camera_cmdcb_t* node = NULL; 1086 1087 /* set pending_cnt 1088 * will trigger dispatching super frames if pending_cnt > 0 */ 1089 /* send cam_sem_post to wake up cmd thread to dispatch super buffer */ 1090 node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t)); 1091 if (NULL != node) { 1092 memset(node, 0, sizeof(mm_camera_cmdcb_t)); 1093 node->cmd_type = MM_CAMERA_CMD_TYPE_REQ_DATA_CB; 1094 node->u.req_buf.num_buf_requested = num_buf_requested; 1095 1096 /* enqueue to cmd thread */ 1097 cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node); 1098 1099 /* wake up cmd thread */ 1100 cam_sem_post(&(my_obj->cmd_thread.cmd_sem)); 1101 } else { 1102 CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__); 1103 rc = -1; 1104 } 1105 1106 return rc; 1107 } 1108 1109 /*=========================================================================== 1110 * FUNCTION : mm_channel_cancel_super_buf_request 1111 * 1112 * DESCRIPTION: for burst mode in bundle, cancel the reuqest for certain amount 1113 * of matched frames from superbuf queue 1114 * 1115 * PARAMETERS : 1116 * @my_obj : channel object 1117 * 1118 * RETURN : int32_t type of status 1119 * 0 -- success 1120 * -1 -- failure 1121 *==========================================================================*/ 1122 int32_t mm_channel_cancel_super_buf_request(mm_channel_t *my_obj) 1123 { 1124 int32_t rc = 0; 1125 /* reset pending_cnt */ 1126 rc = mm_channel_request_super_buf(my_obj, 0); 1127 return rc; 1128 } 1129 1130 /*=========================================================================== 1131 * FUNCTION : mm_channel_flush_super_buf_queue 1132 * 1133 * DESCRIPTION: flush superbuf queue 1134 * 1135 * PARAMETERS : 1136 * @my_obj : channel object 1137 * @frame_idx : frame idx until which to flush all superbufs 1138 * 1139 * RETURN : int32_t type of status 1140 * 0 -- success 1141 * -1 -- failure 1142 *==========================================================================*/ 1143 int32_t mm_channel_flush_super_buf_queue(mm_channel_t *my_obj, uint32_t frame_idx) 1144 { 1145 int32_t rc = 0; 1146 mm_camera_cmdcb_t* node = NULL; 1147 1148 node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t)); 1149 if (NULL != node) { 1150 memset(node, 0, sizeof(mm_camera_cmdcb_t)); 1151 node->cmd_type = MM_CAMERA_CMD_TYPE_FLUSH_QUEUE; 1152 node->u.frame_idx = frame_idx; 1153 1154 /* enqueue to cmd thread */ 1155 cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node); 1156 1157 /* wake up cmd thread */ 1158 cam_sem_post(&(my_obj->cmd_thread.cmd_sem)); 1159 } else { 1160 CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__); 1161 rc = -1; 1162 } 1163 1164 return rc; 1165 } 1166 1167 /*=========================================================================== 1168 * FUNCTION : mm_channel_config_notify_mode 1169 * 1170 * DESCRIPTION: configure notification mode 1171 * 1172 * PARAMETERS : 1173 * @my_obj : channel object 1174 * @notify_mode : notification mode 1175 * 1176 * RETURN : int32_t type of status 1177 * 0 -- success 1178 * -1 -- failure 1179 *==========================================================================*/ 1180 int32_t mm_channel_config_notify_mode(mm_channel_t *my_obj, 1181 mm_camera_super_buf_notify_mode_t notify_mode) 1182 { 1183 int32_t rc = 0; 1184 mm_camera_cmdcb_t* node = NULL; 1185 1186 node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t)); 1187 if (NULL != node) { 1188 memset(node, 0, sizeof(mm_camera_cmdcb_t)); 1189 node->u.notify_mode = notify_mode; 1190 node->cmd_type = MM_CAMERA_CMD_TYPE_CONFIG_NOTIFY; 1191 1192 /* enqueue to cmd thread */ 1193 cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node); 1194 1195 /* wake up cmd thread */ 1196 cam_sem_post(&(my_obj->cmd_thread.cmd_sem)); 1197 } else { 1198 CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__); 1199 rc = -1; 1200 } 1201 1202 return rc; 1203 } 1204 1205 /*=========================================================================== 1206 * FUNCTION : mm_channel_qbuf 1207 * 1208 * DESCRIPTION: enqueue buffer back to kernel 1209 * 1210 * PARAMETERS : 1211 * @my_obj : channel object 1212 * @buf : buf ptr to be enqueued 1213 * 1214 * RETURN : int32_t type of status 1215 * 0 -- success 1216 * -1 -- failure 1217 *==========================================================================*/ 1218 int32_t mm_channel_qbuf(mm_channel_t *my_obj, 1219 mm_camera_buf_def_t *buf) 1220 { 1221 int32_t rc = -1; 1222 mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj, buf->stream_id); 1223 1224 if (NULL != s_obj) { 1225 rc = mm_stream_fsm_fn(s_obj, 1226 MM_STREAM_EVT_QBUF, 1227 (void *)buf, 1228 NULL); 1229 } 1230 1231 return rc; 1232 } 1233 1234 /*=========================================================================== 1235 * FUNCTION : mm_channel_set_stream_parms 1236 * 1237 * DESCRIPTION: set parameters per stream 1238 * 1239 * PARAMETERS : 1240 * @my_obj : channel object 1241 * @s_id : stream handle 1242 * @parms : ptr to a param struct to be set to server 1243 * 1244 * RETURN : int32_t type of status 1245 * 0 -- success 1246 * -1 -- failure 1247 * NOTE : Assume the parms struct buf is already mapped to server via 1248 * domain socket. Corresponding fields of parameters to be set 1249 * are already filled in by upper layer caller. 1250 *==========================================================================*/ 1251 int32_t mm_channel_set_stream_parm(mm_channel_t *my_obj, 1252 mm_evt_paylod_set_get_stream_parms_t *payload) 1253 { 1254 int32_t rc = -1; 1255 mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj, 1256 payload->stream_id); 1257 if (NULL != s_obj) { 1258 rc = mm_stream_fsm_fn(s_obj, 1259 MM_STREAM_EVT_SET_PARM, 1260 (void *)payload, 1261 NULL); 1262 } 1263 1264 return rc; 1265 } 1266 1267 /*=========================================================================== 1268 * FUNCTION : mm_channel_get_stream_parms 1269 * 1270 * DESCRIPTION: get parameters per stream 1271 * 1272 * PARAMETERS : 1273 * @my_obj : channel object 1274 * @s_id : stream handle 1275 * @parms : ptr to a param struct to be get from server 1276 * 1277 * RETURN : int32_t type of status 1278 * 0 -- success 1279 * -1 -- failure 1280 * NOTE : Assume the parms struct buf is already mapped to server via 1281 * domain socket. Parameters to be get from server are already 1282 * filled in by upper layer caller. After this call, corresponding 1283 * fields of requested parameters will be filled in by server with 1284 * detailed information. 1285 *==========================================================================*/ 1286 int32_t mm_channel_get_stream_parm(mm_channel_t *my_obj, 1287 mm_evt_paylod_set_get_stream_parms_t *payload) 1288 { 1289 int32_t rc = -1; 1290 mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj, 1291 payload->stream_id); 1292 if (NULL != s_obj) { 1293 rc = mm_stream_fsm_fn(s_obj, 1294 MM_STREAM_EVT_GET_PARM, 1295 (void *)payload, 1296 NULL); 1297 } 1298 1299 return rc; 1300 } 1301 1302 /*=========================================================================== 1303 * FUNCTION : mm_channel_do_stream_action 1304 * 1305 * DESCRIPTION: request server to perform stream based action. Maybe removed later 1306 * if the functionality is included in mm_camera_set_parms 1307 * 1308 * PARAMETERS : 1309 * @my_obj : channel object 1310 * @s_id : stream handle 1311 * @actions : ptr to an action struct buf to be performed by server 1312 * 1313 * RETURN : int32_t type of status 1314 * 0 -- success 1315 * -1 -- failure 1316 * NOTE : Assume the action struct buf is already mapped to server via 1317 * domain socket. Actions to be performed by server are already 1318 * filled in by upper layer caller. 1319 *==========================================================================*/ 1320 int32_t mm_channel_do_stream_action(mm_channel_t *my_obj, 1321 mm_evt_paylod_do_stream_action_t *payload) 1322 { 1323 int32_t rc = -1; 1324 mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj, 1325 payload->stream_id); 1326 if (NULL != s_obj) { 1327 rc = mm_stream_fsm_fn(s_obj, 1328 MM_STREAM_EVT_DO_ACTION, 1329 (void *)payload, 1330 NULL); 1331 } 1332 1333 return rc; 1334 } 1335 1336 /*=========================================================================== 1337 * FUNCTION : mm_channel_map_stream_buf 1338 * 1339 * DESCRIPTION: mapping stream buffer via domain socket to server 1340 * 1341 * PARAMETERS : 1342 * @my_obj : channel object 1343 * @payload : ptr to payload for mapping 1344 * 1345 * RETURN : int32_t type of status 1346 * 0 -- success 1347 * -1 -- failure 1348 *==========================================================================*/ 1349 int32_t mm_channel_map_stream_buf(mm_channel_t *my_obj, 1350 mm_evt_paylod_map_stream_buf_t *payload) 1351 { 1352 int32_t rc = -1; 1353 mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj, 1354 payload->stream_id); 1355 if (NULL != s_obj) { 1356 rc = mm_stream_map_buf(s_obj, 1357 payload->buf_type, 1358 payload->buf_idx, 1359 payload->plane_idx, 1360 payload->fd, 1361 payload->size); 1362 } 1363 1364 return rc; 1365 } 1366 1367 /*=========================================================================== 1368 * FUNCTION : mm_channel_unmap_stream_buf 1369 * 1370 * DESCRIPTION: unmapping stream buffer via domain socket to server 1371 * 1372 * PARAMETERS : 1373 * @my_obj : channel object 1374 * @payload : ptr to unmap payload 1375 * 1376 * RETURN : int32_t type of status 1377 * 0 -- success 1378 * -1 -- failure 1379 *==========================================================================*/ 1380 int32_t mm_channel_unmap_stream_buf(mm_channel_t *my_obj, 1381 mm_evt_paylod_unmap_stream_buf_t *payload) 1382 { 1383 int32_t rc = -1; 1384 mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj, 1385 payload->stream_id); 1386 if (NULL != s_obj) { 1387 rc = mm_stream_unmap_buf(s_obj, payload->buf_type, 1388 payload->buf_idx, payload->plane_idx); 1389 } 1390 1391 return rc; 1392 } 1393 1394 /*=========================================================================== 1395 * FUNCTION : mm_channel_superbuf_queue_init 1396 * 1397 * DESCRIPTION: initialize superbuf queue in the channel 1398 * 1399 * PARAMETERS : 1400 * @queue : ptr to superbuf queue to be initialized 1401 * 1402 * RETURN : int32_t type of status 1403 * 0 -- success 1404 * -1 -- failure 1405 *==========================================================================*/ 1406 int32_t mm_channel_superbuf_queue_init(mm_channel_queue_t * queue) 1407 { 1408 return cam_queue_init(&queue->que); 1409 } 1410 1411 /*=========================================================================== 1412 * FUNCTION : mm_channel_superbuf_queue_deinit 1413 * 1414 * DESCRIPTION: deinitialize superbuf queue in the channel 1415 * 1416 * PARAMETERS : 1417 * @queue : ptr to superbuf queue to be deinitialized 1418 * 1419 * RETURN : int32_t type of status 1420 * 0 -- success 1421 * -1 -- failure 1422 *==========================================================================*/ 1423 int32_t mm_channel_superbuf_queue_deinit(mm_channel_queue_t * queue) 1424 { 1425 return cam_queue_deinit(&queue->que); 1426 } 1427 1428 /*=========================================================================== 1429 * FUNCTION : mm_channel_util_seq_comp_w_rollover 1430 * 1431 * DESCRIPTION: utility function to handle sequence number comparison with rollover 1432 * 1433 * PARAMETERS : 1434 * @v1 : first value to be compared 1435 * @v2 : second value to be compared 1436 * 1437 * RETURN : int8_t type of comparison result 1438 * >0 -- v1 larger than v2 1439 * =0 -- vi equal to v2 1440 * <0 -- v1 smaller than v2 1441 *==========================================================================*/ 1442 int8_t mm_channel_util_seq_comp_w_rollover(uint32_t v1, 1443 uint32_t v2) 1444 { 1445 int8_t ret = 0; 1446 1447 /* TODO: need to handle the case if v2 roll over to 0 */ 1448 if (v1 > v2) { 1449 ret = 1; 1450 } else if (v1 < v2) { 1451 ret = -1; 1452 } 1453 1454 return ret; 1455 } 1456 1457 /*=========================================================================== 1458 * FUNCTION : mm_channel_handle_metadata 1459 * 1460 * DESCRIPTION: Handle frame matching logic change due to metadata 1461 * 1462 * PARAMETERS : 1463 * @ch_obj : channel object 1464 * @queue : superbuf queue 1465 * @buf_info: new buffer from stream 1466 * 1467 * RETURN : int32_t type of status 1468 * 0 -- success 1469 * -1 -- failure 1470 *==========================================================================*/ 1471 int32_t mm_channel_handle_metadata( 1472 mm_channel_t* ch_obj, 1473 mm_channel_queue_t * queue, 1474 mm_camera_buf_info_t *buf_info) 1475 { 1476 int rc = 0 ; 1477 mm_stream_t* stream_obj = NULL; 1478 stream_obj = mm_channel_util_get_stream_by_handler(ch_obj, 1479 buf_info->stream_id); 1480 1481 if (NULL == stream_obj) { 1482 CDBG_ERROR("%s: Invalid Stream Object for stream_id = %d", 1483 __func__, buf_info->stream_id); 1484 rc = -1; 1485 goto end; 1486 } 1487 if (NULL == stream_obj->stream_info) { 1488 CDBG_ERROR("%s: NULL stream info for stream_id = %d", 1489 __func__, buf_info->stream_id); 1490 rc = -1; 1491 goto end; 1492 } 1493 1494 if (CAM_STREAM_TYPE_METADATA == stream_obj->stream_info->stream_type) { 1495 const cam_metadata_info_t *metadata; 1496 metadata = (const cam_metadata_info_t *)buf_info->buf->buffer; 1497 1498 if (NULL == metadata) { 1499 CDBG_ERROR("%s: NULL metadata buffer for metadata stream", 1500 __func__); 1501 rc = -1; 1502 goto end; 1503 } 1504 1505 if (metadata->is_prep_snapshot_done_valid && 1506 metadata->is_good_frame_idx_range_valid) { 1507 CDBG_ERROR("%s: prep_snapshot_done and good_idx_range shouldn't be valid at the same time", __func__); 1508 rc = -1; 1509 goto end; 1510 } 1511 1512 if (metadata->is_prep_snapshot_done_valid && 1513 metadata->prep_snapshot_done_state == NEED_FUTURE_FRAME) { 1514 1515 /* Set expected frame id to a future frame idx, large enough to wait 1516 * for good_frame_idx_range, and small enough to still capture an image */ 1517 const int max_future_frame_offset = 100; 1518 queue->expected_frame_id += max_future_frame_offset; 1519 1520 mm_channel_superbuf_flush(ch_obj, queue); 1521 } else if (metadata->is_good_frame_idx_range_valid) { 1522 if (metadata->good_frame_idx_range.min_frame_idx > 1523 queue->expected_frame_id) { 1524 CDBG_HIGH("%s: min_frame_idx %d is greater than expected_frame_id %d", 1525 __func__, metadata->good_frame_idx_range.min_frame_idx, 1526 queue->expected_frame_id); 1527 } 1528 queue->expected_frame_id = 1529 metadata->good_frame_idx_range.min_frame_idx; 1530 } 1531 } 1532 end: 1533 return rc; 1534 } 1535 1536 /*=========================================================================== 1537 * FUNCTION : mm_channel_superbuf_comp_and_enqueue 1538 * 1539 * DESCRIPTION: implementation for matching logic for superbuf 1540 * 1541 * PARAMETERS : 1542 * @ch_obj : channel object 1543 * @queue : superbuf queue 1544 * @buf_info: new buffer from stream 1545 * 1546 * RETURN : int32_t type of status 1547 * 0 -- success 1548 * -1 -- failure 1549 *==========================================================================*/ 1550 int32_t mm_channel_superbuf_comp_and_enqueue( 1551 mm_channel_t* ch_obj, 1552 mm_channel_queue_t *queue, 1553 mm_camera_buf_info_t *buf_info) 1554 { 1555 cam_node_t* node = NULL; 1556 struct cam_list *head = NULL; 1557 struct cam_list *pos = NULL; 1558 mm_channel_queue_node_t* super_buf = NULL; 1559 uint8_t buf_s_idx, i, found_super_buf, unmatched_bundles; 1560 struct cam_list *last_buf, *insert_before_buf; 1561 1562 CDBG("%s: E", __func__); 1563 for (buf_s_idx = 0; buf_s_idx < queue->num_streams; buf_s_idx++) { 1564 if (buf_info->stream_id == queue->bundled_streams[buf_s_idx]) { 1565 break; 1566 } 1567 } 1568 if (buf_s_idx == queue->num_streams) { 1569 CDBG_ERROR("%s: buf from stream (%d) not bundled", __func__, buf_info->stream_id); 1570 return -1; 1571 } 1572 1573 if (mm_channel_handle_metadata(ch_obj, queue, buf_info) < 0) { 1574 return -1; 1575 } 1576 1577 if (mm_channel_util_seq_comp_w_rollover(buf_info->frame_idx, 1578 queue->expected_frame_id) < 0) { 1579 /* incoming buf is older than expected buf id, will discard it */ 1580 mm_channel_qbuf(ch_obj, buf_info->buf); 1581 return 0; 1582 } 1583 1584 if (MM_CAMERA_SUPER_BUF_PRIORITY_NORMAL != queue->attr.priority) { 1585 /* TODO */ 1586 /* need to decide if we want to queue the frame based on focus or exposure 1587 * if frame not to be queued, we need to qbuf it back */ 1588 } 1589 1590 /* comp */ 1591 pthread_mutex_lock(&queue->que.lock); 1592 head = &queue->que.head.list; 1593 /* get the last one in the queue which is possibly having no matching */ 1594 pos = head->next; 1595 1596 found_super_buf = 0; 1597 unmatched_bundles = 0; 1598 last_buf = NULL; 1599 insert_before_buf = NULL; 1600 while (pos != head) { 1601 node = member_of(pos, cam_node_t, list); 1602 super_buf = (mm_channel_queue_node_t*)node->data; 1603 if (NULL != super_buf) { 1604 if (super_buf->matched) { 1605 /* find a matched super buf, move to next one */ 1606 pos = pos->next; 1607 continue; 1608 } else if ( buf_info->frame_idx == super_buf->frame_idx ) { 1609 /* have an unmatched super buf that matches our frame idx, 1610 * break the loop */ 1611 found_super_buf = 1; 1612 break; 1613 } else { 1614 unmatched_bundles++; 1615 if ( NULL == last_buf ) { 1616 if ( super_buf->frame_idx < buf_info->frame_idx ) { 1617 last_buf = pos; 1618 } 1619 } 1620 if ( NULL == insert_before_buf ) { 1621 if ( super_buf->frame_idx > buf_info->frame_idx ) { 1622 insert_before_buf = pos; 1623 } 1624 } 1625 pos = pos->next; 1626 } 1627 } 1628 } 1629 1630 if ( found_super_buf ) { 1631 super_buf->super_buf[buf_s_idx] = *buf_info; 1632 1633 /* check if superbuf is all matched */ 1634 super_buf->matched = 1; 1635 for (i=0; i < super_buf->num_of_bufs; i++) { 1636 if (super_buf->super_buf[i].frame_idx == 0) { 1637 super_buf->matched = 0; 1638 break; 1639 } 1640 } 1641 1642 if (super_buf->matched) { 1643 queue->expected_frame_id = buf_info->frame_idx + queue->attr.post_frame_skip; 1644 queue->match_cnt++; 1645 /* Any older unmatched buffer need to be released */ 1646 if ( last_buf ) { 1647 while ( last_buf != pos ) { 1648 node = member_of(last_buf, cam_node_t, list); 1649 super_buf = (mm_channel_queue_node_t*)node->data; 1650 if (NULL != super_buf) { 1651 for (i=0; i<super_buf->num_of_bufs; i++) { 1652 if (super_buf->super_buf[i].frame_idx != 0) { 1653 mm_channel_qbuf(ch_obj, super_buf->super_buf[i].buf); 1654 } 1655 } 1656 queue->que.size--; 1657 last_buf = last_buf->next; 1658 cam_list_del_node(&node->list); 1659 free(node); 1660 free(super_buf); 1661 } else { 1662 CDBG_ERROR(" %s : Invalid superbuf in queue!", __func__); 1663 break; 1664 } 1665 } 1666 } 1667 } 1668 } else { 1669 if ( ( queue->attr.max_unmatched_frames < unmatched_bundles ) && 1670 ( NULL == last_buf ) ) { 1671 /* incoming frame is older than the last bundled one */ 1672 mm_channel_qbuf(ch_obj, buf_info->buf); 1673 } else { 1674 if ( queue->attr.max_unmatched_frames < unmatched_bundles ) { 1675 /* release the oldest bundled superbuf */ 1676 node = member_of(last_buf, cam_node_t, list); 1677 super_buf = (mm_channel_queue_node_t*)node->data; 1678 for (i=0; i<super_buf->num_of_bufs; i++) { 1679 if (super_buf->super_buf[i].frame_idx != 0) { 1680 mm_channel_qbuf(ch_obj, super_buf->super_buf[i].buf); 1681 } 1682 } 1683 queue->que.size--; 1684 node = member_of(last_buf, cam_node_t, list); 1685 cam_list_del_node(&node->list); 1686 free(node); 1687 free(super_buf); 1688 } 1689 /* insert the new frame at the appropriate position. */ 1690 1691 mm_channel_queue_node_t *new_buf = NULL; 1692 cam_node_t* new_node = NULL; 1693 1694 new_buf = (mm_channel_queue_node_t*)malloc(sizeof(mm_channel_queue_node_t)); 1695 new_node = (cam_node_t*)malloc(sizeof(cam_node_t)); 1696 if (NULL != new_buf && NULL != new_node) { 1697 memset(new_buf, 0, sizeof(mm_channel_queue_node_t)); 1698 memset(new_node, 0, sizeof(cam_node_t)); 1699 new_node->data = (void *)new_buf; 1700 new_buf->num_of_bufs = queue->num_streams; 1701 new_buf->super_buf[buf_s_idx] = *buf_info; 1702 new_buf->frame_idx = buf_info->frame_idx; 1703 1704 /* enqueue */ 1705 if ( insert_before_buf ) { 1706 cam_list_insert_before_node(&new_node->list, insert_before_buf); 1707 } else { 1708 cam_list_add_tail_node(&new_node->list, &queue->que.head.list); 1709 } 1710 queue->que.size++; 1711 1712 if(queue->num_streams == 1) { 1713 new_buf->matched = 1; 1714 1715 queue->expected_frame_id = buf_info->frame_idx + queue->attr.post_frame_skip; 1716 queue->match_cnt++; 1717 } 1718 } else { 1719 /* No memory */ 1720 if (NULL != new_buf) { 1721 free(new_buf); 1722 } 1723 if (NULL != new_node) { 1724 free(new_node); 1725 } 1726 /* qbuf the new buf since we cannot enqueue */ 1727 mm_channel_qbuf(ch_obj, buf_info->buf); 1728 } 1729 } 1730 } 1731 1732 pthread_mutex_unlock(&queue->que.lock); 1733 1734 CDBG("%s: X", __func__); 1735 return 0; 1736 } 1737 1738 /*=========================================================================== 1739 * FUNCTION : mm_channel_superbuf_dequeue_internal 1740 * 1741 * DESCRIPTION: internal implementation for dequeue from the superbuf queue 1742 * 1743 * PARAMETERS : 1744 * @queue : superbuf queue 1745 * @matched_only : if dequeued buf should be matched 1746 * 1747 * RETURN : ptr to a node from superbuf queue 1748 *==========================================================================*/ 1749 mm_channel_queue_node_t* mm_channel_superbuf_dequeue_internal(mm_channel_queue_t * queue, 1750 uint8_t matched_only) 1751 { 1752 cam_node_t* node = NULL; 1753 struct cam_list *head = NULL; 1754 struct cam_list *pos = NULL; 1755 mm_channel_queue_node_t* super_buf = NULL; 1756 1757 head = &queue->que.head.list; 1758 pos = head->next; 1759 if (pos != head) { 1760 /* get the first node */ 1761 node = member_of(pos, cam_node_t, list); 1762 super_buf = (mm_channel_queue_node_t*)node->data; 1763 if ( (NULL != super_buf) && 1764 (matched_only == TRUE) && 1765 (super_buf->matched == FALSE) ) { 1766 /* require to dequeue matched frame only, but this superbuf is not matched, 1767 simply set return ptr to NULL */ 1768 super_buf = NULL; 1769 } 1770 if (NULL != super_buf) { 1771 /* remove from the queue */ 1772 cam_list_del_node(&node->list); 1773 queue->que.size--; 1774 if (super_buf->matched == TRUE) { 1775 queue->match_cnt--; 1776 } 1777 free(node); 1778 } 1779 } 1780 1781 return super_buf; 1782 } 1783 1784 /*=========================================================================== 1785 * FUNCTION : mm_channel_superbuf_dequeue 1786 * 1787 * DESCRIPTION: dequeue from the superbuf queue 1788 * 1789 * PARAMETERS : 1790 * @queue : superbuf queue 1791 * 1792 * RETURN : ptr to a node from superbuf queue 1793 *==========================================================================*/ 1794 mm_channel_queue_node_t* mm_channel_superbuf_dequeue(mm_channel_queue_t * queue) 1795 { 1796 mm_channel_queue_node_t* super_buf = NULL; 1797 1798 pthread_mutex_lock(&queue->que.lock); 1799 super_buf = mm_channel_superbuf_dequeue_internal(queue, TRUE); 1800 pthread_mutex_unlock(&queue->que.lock); 1801 1802 return super_buf; 1803 } 1804 1805 /*=========================================================================== 1806 * FUNCTION : mm_channel_superbuf_bufdone_overflow 1807 * 1808 * DESCRIPTION: keep superbuf queue no larger than watermark set by upper layer 1809 * via channel attribute 1810 * 1811 * PARAMETERS : 1812 * @my_obj : channel object 1813 * @queue : superbuf queue 1814 * 1815 * RETURN : int32_t type of status 1816 * 0 -- success 1817 * -1 -- failure 1818 *==========================================================================*/ 1819 int32_t mm_channel_superbuf_bufdone_overflow(mm_channel_t* my_obj, 1820 mm_channel_queue_t * queue) 1821 { 1822 int32_t rc = 0, i; 1823 mm_channel_queue_node_t* super_buf = NULL; 1824 if (MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS == queue->attr.notify_mode) { 1825 /* for continuous streaming mode, no overflow is needed */ 1826 return 0; 1827 } 1828 1829 CDBG("%s: before match_cnt=%d, water_mark=%d", 1830 __func__, queue->match_cnt, queue->attr.water_mark); 1831 /* bufdone overflowed bufs */ 1832 pthread_mutex_lock(&queue->que.lock); 1833 while (queue->match_cnt > queue->attr.water_mark) { 1834 super_buf = mm_channel_superbuf_dequeue_internal(queue, TRUE); 1835 if (NULL != super_buf) { 1836 for (i=0; i<super_buf->num_of_bufs; i++) { 1837 if (NULL != super_buf->super_buf[i].buf) { 1838 mm_channel_qbuf(my_obj, super_buf->super_buf[i].buf); 1839 } 1840 } 1841 free(super_buf); 1842 } 1843 } 1844 pthread_mutex_unlock(&queue->que.lock); 1845 CDBG("%s: after match_cnt=%d, water_mark=%d", 1846 __func__, queue->match_cnt, queue->attr.water_mark); 1847 1848 return rc; 1849 } 1850 1851 /*=========================================================================== 1852 * FUNCTION : mm_channel_superbuf_skip 1853 * 1854 * DESCRIPTION: depends on the lookback configuration of the channel attribute, 1855 * unwanted superbufs will be removed from the superbuf queue. 1856 * 1857 * PARAMETERS : 1858 * @my_obj : channel object 1859 * @queue : superbuf queue 1860 * 1861 * RETURN : int32_t type of status 1862 * 0 -- success 1863 * -1 -- failure 1864 *==========================================================================*/ 1865 int32_t mm_channel_superbuf_skip(mm_channel_t* my_obj, 1866 mm_channel_queue_t * queue) 1867 { 1868 int32_t rc = 0, i; 1869 mm_channel_queue_node_t* super_buf = NULL; 1870 if (MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS == queue->attr.notify_mode) { 1871 /* for continuous streaming mode, no skip is needed */ 1872 return 0; 1873 } 1874 1875 /* bufdone overflowed bufs */ 1876 pthread_mutex_lock(&queue->que.lock); 1877 while (queue->match_cnt > queue->attr.look_back) { 1878 super_buf = mm_channel_superbuf_dequeue_internal(queue, TRUE); 1879 if (NULL != super_buf) { 1880 for (i=0; i<super_buf->num_of_bufs; i++) { 1881 if (NULL != super_buf->super_buf[i].buf) { 1882 mm_channel_qbuf(my_obj, super_buf->super_buf[i].buf); 1883 } 1884 } 1885 free(super_buf); 1886 } 1887 } 1888 pthread_mutex_unlock(&queue->que.lock); 1889 1890 return rc; 1891 } 1892 1893 /*=========================================================================== 1894 * FUNCTION : mm_channel_superbuf_flush 1895 * 1896 * DESCRIPTION: flush the superbuf queue. 1897 * 1898 * PARAMETERS : 1899 * @my_obj : channel object 1900 * @queue : superbuf queue 1901 * 1902 * RETURN : int32_t type of status 1903 * 0 -- success 1904 * -1 -- failure 1905 *==========================================================================*/ 1906 int32_t mm_channel_superbuf_flush(mm_channel_t* my_obj, 1907 mm_channel_queue_t * queue) 1908 { 1909 int32_t rc = 0, i; 1910 mm_channel_queue_node_t* super_buf = NULL; 1911 1912 /* bufdone bufs */ 1913 pthread_mutex_lock(&queue->que.lock); 1914 super_buf = mm_channel_superbuf_dequeue_internal(queue, FALSE); 1915 while (super_buf != NULL) { 1916 for (i=0; i<super_buf->num_of_bufs; i++) { 1917 if (NULL != super_buf->super_buf[i].buf) { 1918 mm_channel_qbuf(my_obj, super_buf->super_buf[i].buf); 1919 } 1920 } 1921 free(super_buf); 1922 super_buf = mm_channel_superbuf_dequeue_internal(queue, FALSE); 1923 } 1924 pthread_mutex_unlock(&queue->que.lock); 1925 1926 return rc; 1927 } 1928