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