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