1 /* Copyright (c) 2012-2016, 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 // System dependencies 31 #include <pthread.h> 32 #include <fcntl.h> 33 34 // Camera dependencies 35 #include "cam_semaphore.h" 36 #include "mm_camera_dbg.h" 37 #include "mm_camera_interface.h" 38 #include "mm_camera.h" 39 40 extern mm_camera_obj_t* mm_camera_util_get_camera_by_handler(uint32_t cam_handler); 41 extern mm_channel_t * mm_camera_util_get_channel_by_handler(mm_camera_obj_t * cam_obj, 42 uint32_t handler); 43 /* Static frame sync info used between different camera channels*/ 44 static mm_channel_frame_sync_info_t fs = { .num_cam =0, .pos = 0}; 45 /* Frame sync info access lock */ 46 static pthread_mutex_t fs_lock = PTHREAD_MUTEX_INITIALIZER; 47 48 /* internal function declare goes here */ 49 int32_t mm_channel_qbuf(mm_channel_t *my_obj, 50 mm_camera_buf_def_t *buf); 51 int32_t mm_channel_cancel_buf(mm_channel_t *my_obj, 52 uint32_t stream_id, uint32_t buf_idx); 53 int32_t mm_channel_init(mm_channel_t *my_obj, 54 mm_camera_channel_attr_t *attr, 55 mm_camera_buf_notify_t channel_cb, 56 void *userdata); 57 void mm_channel_release(mm_channel_t *my_obj); 58 uint32_t mm_channel_add_stream(mm_channel_t *my_obj); 59 int32_t mm_channel_del_stream(mm_channel_t *my_obj, 60 uint32_t stream_id); 61 uint32_t mm_channel_link_stream(mm_channel_t *my_obj, 62 mm_camera_stream_link_t *stream_link); 63 int32_t mm_channel_config_stream(mm_channel_t *my_obj, 64 uint32_t stream_id, 65 mm_camera_stream_config_t *config); 66 int32_t mm_channel_get_bundle_info(mm_channel_t *my_obj, 67 cam_bundle_config_t *bundle_info); 68 int32_t mm_channel_start(mm_channel_t *my_obj); 69 int32_t mm_channel_stop(mm_channel_t *my_obj); 70 int32_t mm_channel_request_super_buf(mm_channel_t *my_obj, 71 mm_camera_req_buf_t *buf); 72 int32_t mm_channel_cancel_super_buf_request(mm_channel_t *my_obj); 73 int32_t mm_channel_flush_super_buf_queue(mm_channel_t *my_obj, 74 uint32_t frame_idx, 75 cam_stream_type_t stream_type); 76 int32_t mm_channel_config_notify_mode(mm_channel_t *my_obj, 77 mm_camera_super_buf_notify_mode_t notify_mode); 78 int32_t mm_channel_start_zsl_snapshot(mm_channel_t *my_obj); 79 int32_t mm_channel_stop_zsl_snapshot(mm_channel_t *my_obj); 80 int32_t mm_channel_superbuf_flush(mm_channel_t* my_obj, 81 mm_channel_queue_t * queue, cam_stream_type_t cam_type); 82 int32_t mm_channel_set_stream_parm(mm_channel_t *my_obj, 83 mm_evt_paylod_set_get_stream_parms_t *payload); 84 int32_t mm_channel_get_queued_buf_count(mm_channel_t *my_obj, 85 uint32_t stream_id); 86 87 int32_t mm_channel_get_stream_parm(mm_channel_t *my_obj, 88 mm_evt_paylod_set_get_stream_parms_t *payload); 89 int32_t mm_channel_do_stream_action(mm_channel_t *my_obj, 90 mm_evt_paylod_do_stream_action_t *payload); 91 int32_t mm_channel_map_stream_buf(mm_channel_t *my_obj, 92 cam_buf_map_type *payload); 93 int32_t mm_channel_map_stream_bufs(mm_channel_t *my_obj, 94 cam_buf_map_type_list *payload); 95 int32_t mm_channel_unmap_stream_buf(mm_channel_t *my_obj, 96 cam_buf_unmap_type *payload); 97 98 /* state machine function declare */ 99 int32_t mm_channel_fsm_fn_notused(mm_channel_t *my_obj, 100 mm_channel_evt_type_t evt, 101 void * in_val, 102 void * out_val); 103 int32_t mm_channel_fsm_fn_stopped(mm_channel_t *my_obj, 104 mm_channel_evt_type_t evt, 105 void * in_val, 106 void * out_val); 107 int32_t mm_channel_fsm_fn_active(mm_channel_t *my_obj, 108 mm_channel_evt_type_t evt, 109 void * in_val, 110 void * out_val); 111 int32_t mm_channel_fsm_fn_paused(mm_channel_t *my_obj, 112 mm_channel_evt_type_t evt, 113 void * in_val, 114 void * out_val); 115 116 /* channel super queue functions */ 117 int32_t mm_channel_superbuf_queue_init(mm_channel_queue_t * queue); 118 int32_t mm_channel_superbuf_queue_deinit(mm_channel_queue_t * queue); 119 int32_t mm_channel_superbuf_comp_and_enqueue(mm_channel_t *ch_obj, 120 mm_channel_queue_t * queue, 121 mm_camera_buf_info_t *buf); 122 mm_channel_queue_node_t* mm_channel_superbuf_dequeue( 123 mm_channel_queue_t * queue, mm_channel_t *ch_obj); 124 int32_t mm_channel_superbuf_bufdone_overflow(mm_channel_t *my_obj, 125 mm_channel_queue_t *queue); 126 int32_t mm_channel_superbuf_skip(mm_channel_t *my_obj, 127 mm_channel_queue_t *queue); 128 129 static int32_t mm_channel_proc_general_cmd(mm_channel_t *my_obj, 130 mm_camera_generic_cmd_t *p_gen_cmd); 131 int32_t mm_channel_superbuf_flush_matched(mm_channel_t* my_obj, 132 mm_channel_queue_t * queue); 133 134 /* Start of Frame Sync util methods */ 135 void mm_frame_sync_reset(); 136 int32_t mm_frame_sync_register_channel(mm_channel_t *ch_obj); 137 int32_t mm_frame_sync_unregister_channel(mm_channel_t *ch_obj); 138 int32_t mm_frame_sync_add(uint32_t frame_id, mm_channel_t *ch_obj); 139 int32_t mm_frame_sync_remove(uint32_t frame_id); 140 uint32_t mm_frame_sync_find_matched(uint8_t oldest); 141 int8_t mm_frame_sync_find_frame_index(uint32_t frame_id); 142 void mm_frame_sync_lock_queues(); 143 void mm_frame_sync_unlock_queues(); 144 void mm_channel_node_qbuf(mm_channel_t *ch_obj, mm_channel_queue_node_t *node); 145 /* End of Frame Sync Util methods */ 146 void mm_channel_send_super_buf(mm_channel_node_info_t *info); 147 mm_channel_queue_node_t* mm_channel_superbuf_dequeue_frame_internal( 148 mm_channel_queue_t * queue, uint32_t frame_idx); 149 150 /*=========================================================================== 151 * FUNCTION : mm_channel_util_get_stream_by_handler 152 * 153 * DESCRIPTION: utility function to get a stream object from its handle 154 * 155 * PARAMETERS : 156 * @cam_obj: ptr to a channel object 157 * @handler: stream handle 158 * 159 * RETURN : ptr to a stream object. 160 * NULL if failed. 161 *==========================================================================*/ 162 mm_stream_t * mm_channel_util_get_stream_by_handler( 163 mm_channel_t * ch_obj, 164 uint32_t handler) 165 { 166 int i; 167 mm_stream_t *s_obj = NULL; 168 for(i = 0; i < MAX_STREAM_NUM_IN_BUNDLE; i++) { 169 if ((MM_STREAM_STATE_NOTUSED != ch_obj->streams[i].state) && 170 (handler == ch_obj->streams[i].my_hdl)) { 171 s_obj = &ch_obj->streams[i]; 172 break; 173 } 174 } 175 return s_obj; 176 } 177 178 /*=========================================================================== 179 * FUNCTION : mm_channel_dispatch_super_buf 180 * 181 * DESCRIPTION: dispatch super buffer of bundle to registered user 182 * 183 * PARAMETERS : 184 * @cmd_cb : ptr storing matched super buf information 185 * @userdata: user data ptr 186 * 187 * RETURN : none 188 *==========================================================================*/ 189 static void mm_channel_dispatch_super_buf(mm_camera_cmdcb_t *cmd_cb, 190 void* user_data) 191 { 192 mm_channel_t * my_obj = (mm_channel_t *)user_data; 193 194 if (NULL == my_obj) { 195 return; 196 } 197 198 if (MM_CAMERA_CMD_TYPE_SUPER_BUF_DATA_CB != cmd_cb->cmd_type) { 199 LOGE("Wrong cmd_type (%d) for super buf dataCB", 200 cmd_cb->cmd_type); 201 return; 202 } 203 204 if (my_obj->bundle.super_buf_notify_cb) { 205 my_obj->bundle.super_buf_notify_cb(&cmd_cb->u.superbuf, my_obj->bundle.user_data); 206 } 207 } 208 209 /*=========================================================================== 210 * FUNCTION : mm_channel_process_stream_buf 211 * 212 * DESCRIPTION: handle incoming buffer from stream in a bundle. In this function, 213 * matching logic will be performed on incoming stream frames. 214 * Will depends on the bundle attribute, either storing matched frames 215 * in the superbuf queue, or sending matched superbuf frames to upper 216 * layer through registered callback. 217 * 218 * PARAMETERS : 219 * @cmd_cb : ptr storing matched super buf information 220 * @userdata: user data ptr 221 * 222 * RETURN : none 223 *==========================================================================*/ 224 static void mm_channel_process_stream_buf(mm_camera_cmdcb_t * cmd_cb, 225 void *user_data) 226 { 227 mm_camera_super_buf_notify_mode_t notify_mode; 228 mm_channel_queue_node_t *node = NULL; 229 mm_channel_t *ch_obj = (mm_channel_t *)user_data; 230 uint32_t i = 0; 231 /* Set expected frame id to a future frame idx, large enough to wait 232 * for good_frame_idx_range, and small enough to still capture an image */ 233 uint8_t needStartZSL = FALSE; 234 235 if (NULL == ch_obj) { 236 return; 237 } 238 if (MM_CAMERA_CMD_TYPE_DATA_CB == cmd_cb->cmd_type) { 239 /* comp_and_enqueue */ 240 mm_channel_superbuf_comp_and_enqueue( 241 ch_obj, 242 &ch_obj->bundle.superbuf_queue, 243 &cmd_cb->u.buf); 244 } else if (MM_CAMERA_CMD_TYPE_REQ_DATA_CB == cmd_cb->cmd_type) { 245 /* skip frames if needed */ 246 ch_obj->pending_cnt = cmd_cb->u.req_buf.num_buf_requested; 247 ch_obj->pending_retro_cnt = cmd_cb->u.req_buf.num_retro_buf_requested; 248 ch_obj->req_type = cmd_cb->u.req_buf.type; 249 ch_obj->bWaitForPrepSnapshotDone = 0; 250 251 LOGH("pending cnt (%d), retro count (%d)" 252 "req_type (%d) is_primary (%d)", 253 ch_obj->pending_cnt, ch_obj->pending_retro_cnt, 254 ch_obj->req_type, cmd_cb->u.req_buf.primary_only); 255 if (!ch_obj->pending_cnt || (ch_obj->pending_retro_cnt > ch_obj->pending_cnt)) { 256 ch_obj->pending_retro_cnt = ch_obj->pending_cnt; 257 } 258 if (ch_obj->pending_retro_cnt > 0) { 259 LOGL("Resetting need Led Flash!!!"); 260 ch_obj->needLEDFlash = 0; 261 } 262 ch_obj->stopZslSnapshot = 0; 263 ch_obj->unLockAEC = 0; 264 265 mm_channel_superbuf_skip(ch_obj, &ch_obj->bundle.superbuf_queue); 266 267 } else if (MM_CAMERA_CMD_TYPE_START_ZSL == cmd_cb->cmd_type) { 268 ch_obj->manualZSLSnapshot = TRUE; 269 mm_camera_start_zsl_snapshot(ch_obj->cam_obj); 270 } else if (MM_CAMERA_CMD_TYPE_STOP_ZSL == cmd_cb->cmd_type) { 271 ch_obj->manualZSLSnapshot = FALSE; 272 mm_camera_stop_zsl_snapshot(ch_obj->cam_obj); 273 } else if (MM_CAMERA_CMD_TYPE_CONFIG_NOTIFY == cmd_cb->cmd_type) { 274 ch_obj->bundle.superbuf_queue.attr.notify_mode = cmd_cb->u.notify_mode; 275 } else if (MM_CAMERA_CMD_TYPE_FLUSH_QUEUE == cmd_cb->cmd_type) { 276 ch_obj->bundle.superbuf_queue.expected_frame_id = cmd_cb->u.flush_cmd.frame_idx; 277 mm_channel_superbuf_flush(ch_obj, 278 &ch_obj->bundle.superbuf_queue, cmd_cb->u.flush_cmd.stream_type); 279 cam_sem_post(&(ch_obj->cmd_thread.sync_sem)); 280 return; 281 } else if (MM_CAMERA_CMD_TYPE_GENERAL == cmd_cb->cmd_type) { 282 LOGH("MM_CAMERA_CMD_TYPE_GENERAL"); 283 switch (cmd_cb->u.gen_cmd.type) { 284 case MM_CAMERA_GENERIC_CMD_TYPE_AE_BRACKETING: 285 case MM_CAMERA_GENERIC_CMD_TYPE_AF_BRACKETING: { 286 uint32_t start = cmd_cb->u.gen_cmd.payload[0]; 287 LOGI("MM_CAMERA_GENERIC_CMDTYPE_AF_BRACKETING %u", 288 start); 289 mm_channel_superbuf_flush(ch_obj, 290 &ch_obj->bundle.superbuf_queue, CAM_STREAM_TYPE_DEFAULT); 291 292 if (start) { 293 LOGH("need AE bracketing, start zsl snapshot"); 294 ch_obj->bracketingState = MM_CHANNEL_BRACKETING_STATE_WAIT_GOOD_FRAME_IDX; 295 } else { 296 ch_obj->bracketingState = MM_CHANNEL_BRACKETING_STATE_OFF; 297 } 298 } 299 break; 300 case MM_CAMERA_GENERIC_CMD_TYPE_FLASH_BRACKETING: { 301 uint32_t start = cmd_cb->u.gen_cmd.payload[0]; 302 LOGI("MM_CAMERA_GENERIC_CMDTYPE_FLASH_BRACKETING %u", 303 start); 304 mm_channel_superbuf_flush(ch_obj, 305 &ch_obj->bundle.superbuf_queue, CAM_STREAM_TYPE_DEFAULT); 306 307 if (start) { 308 LOGH("need flash bracketing"); 309 ch_obj->isFlashBracketingEnabled = TRUE; 310 } else { 311 ch_obj->isFlashBracketingEnabled = FALSE; 312 } 313 } 314 break; 315 case MM_CAMERA_GENERIC_CMD_TYPE_ZOOM_1X: { 316 uint32_t start = cmd_cb->u.gen_cmd.payload[0]; 317 LOGI("MM_CAMERA_GENERIC_CMD_TYPE_ZOOM_1X %u", 318 start); 319 mm_channel_superbuf_flush(ch_obj, 320 &ch_obj->bundle.superbuf_queue, CAM_STREAM_TYPE_DEFAULT); 321 322 if (start) { 323 LOGH("need zoom 1x frame"); 324 ch_obj->isZoom1xFrameRequested = TRUE; 325 } else { 326 ch_obj->isZoom1xFrameRequested = FALSE; 327 } 328 } 329 break; 330 case MM_CAMERA_GENERIC_CMD_TYPE_CAPTURE_SETTING: { 331 uint32_t start = cmd_cb->u.gen_cmd.payload[0]; 332 LOGI("MM_CAMERA_GENERIC_CMD_TYPE_CAPTURE_SETTING %u num_batch = %d", 333 start, cmd_cb->u.gen_cmd.frame_config.num_batch); 334 335 if (start) { 336 memset(&ch_obj->frameConfig, 0, sizeof(cam_capture_frame_config_t)); 337 for (i = 0; i < cmd_cb->u.gen_cmd.frame_config.num_batch; i++) { 338 if (cmd_cb->u.gen_cmd.frame_config.configs[i].type 339 != CAM_CAPTURE_RESET) { 340 ch_obj->frameConfig.configs[ 341 ch_obj->frameConfig.num_batch] = 342 cmd_cb->u.gen_cmd.frame_config.configs[i]; 343 ch_obj->frameConfig.num_batch++; 344 LOGH("capture setting frame = %d type = %d", 345 i,ch_obj->frameConfig.configs[ 346 ch_obj->frameConfig.num_batch].type); 347 } 348 } 349 LOGD("Capture setting Batch Count %d", 350 ch_obj->frameConfig.num_batch); 351 ch_obj->isConfigCapture = TRUE; 352 } else { 353 ch_obj->isConfigCapture = FALSE; 354 memset(&ch_obj->frameConfig, 0, sizeof(cam_capture_frame_config_t)); 355 } 356 ch_obj->cur_capture_idx = 0; 357 memset(ch_obj->capture_frame_id, 0, sizeof(uint8_t) * MAX_CAPTURE_BATCH_NUM); 358 break; 359 } 360 default: 361 LOGE("Error: Invalid command"); 362 break; 363 } 364 } 365 notify_mode = ch_obj->bundle.superbuf_queue.attr.notify_mode; 366 367 /*Handle use case which does not need start ZSL even in unified case*/ 368 if ((ch_obj->pending_cnt > 0) 369 && (ch_obj->isConfigCapture) 370 && (ch_obj->manualZSLSnapshot == FALSE) 371 && (ch_obj->startZSlSnapshotCalled == FALSE)) { 372 needStartZSL = TRUE; 373 for (i = ch_obj->cur_capture_idx; 374 i < ch_obj->frameConfig.num_batch; 375 i++) { 376 cam_capture_type type = ch_obj->frameConfig.configs[i].type; 377 if (((type == CAM_CAPTURE_FLASH) && (!ch_obj->needLEDFlash)) 378 || ((type == CAM_CAPTURE_LOW_LIGHT) && (!ch_obj->needLowLightZSL))) { 379 /*For flash and low light capture, start ZSL is triggered only if needed*/ 380 needStartZSL = FALSE; 381 break; 382 } 383 } 384 } 385 386 if ((ch_obj->isConfigCapture) 387 && (needStartZSL)) { 388 for (i = ch_obj->cur_capture_idx; 389 i < ch_obj->frameConfig.num_batch; 390 i++) { 391 ch_obj->capture_frame_id[i] = 392 ch_obj->bundle.superbuf_queue.expected_frame_id 393 + MM_CAMERA_MAX_FUTURE_FRAME_WAIT; 394 } 395 396 /* Need to Flush the queue and trigger frame config */ 397 mm_channel_superbuf_flush(ch_obj, 398 &ch_obj->bundle.superbuf_queue, CAM_STREAM_TYPE_DEFAULT); 399 LOGI("TRIGGER Start ZSL"); 400 mm_camera_start_zsl_snapshot(ch_obj->cam_obj); 401 ch_obj->startZSlSnapshotCalled = TRUE; 402 ch_obj->burstSnapNum = ch_obj->pending_cnt; 403 ch_obj->bWaitForPrepSnapshotDone = 0; 404 } else if ((ch_obj->pending_cnt > 0) 405 && ((ch_obj->needLEDFlash == TRUE) || 406 (MM_CHANNEL_BRACKETING_STATE_OFF != ch_obj->bracketingState)) 407 && (ch_obj->manualZSLSnapshot == FALSE) 408 && ch_obj->startZSlSnapshotCalled == FALSE) { 409 410 LOGI("TRIGGER Start ZSL for Flash"); 411 mm_camera_start_zsl_snapshot(ch_obj->cam_obj); 412 ch_obj->startZSlSnapshotCalled = TRUE; 413 ch_obj->burstSnapNum = ch_obj->pending_cnt; 414 ch_obj->bWaitForPrepSnapshotDone = 0; 415 } else if (((ch_obj->pending_cnt == 0) || (ch_obj->stopZslSnapshot == 1)) 416 && (ch_obj->manualZSLSnapshot == FALSE) 417 && (ch_obj->startZSlSnapshotCalled == TRUE)) { 418 LOGI("TRIGGER Stop ZSL for cancel picture"); 419 mm_camera_stop_zsl_snapshot(ch_obj->cam_obj); 420 // Unlock AEC 421 ch_obj->startZSlSnapshotCalled = FALSE; 422 ch_obj->needLEDFlash = FALSE; 423 ch_obj->burstSnapNum = 0; 424 ch_obj->stopZslSnapshot = 0; 425 ch_obj->bWaitForPrepSnapshotDone = 0; 426 ch_obj->unLockAEC = 1; 427 ch_obj->bracketingState = MM_CHANNEL_BRACKETING_STATE_OFF; 428 ch_obj->isConfigCapture = FALSE; 429 } 430 /* bufdone for overflowed bufs */ 431 mm_channel_superbuf_bufdone_overflow(ch_obj, &ch_obj->bundle.superbuf_queue); 432 433 LOGD("Super Buffer received, pending_cnt=%d queue cnt = %d expected = %d", 434 ch_obj->pending_cnt, ch_obj->bundle.superbuf_queue.match_cnt, 435 ch_obj->bundle.superbuf_queue.expected_frame_id); 436 437 /* dispatch frame if pending_cnt>0 or is in continuous streaming mode */ 438 while (((ch_obj->pending_cnt > 0) || 439 (MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS == notify_mode)) && 440 (!ch_obj->bWaitForPrepSnapshotDone)) { 441 442 /* dequeue */ 443 mm_channel_node_info_t info; 444 memset(&info, 0x0, sizeof(info)); 445 446 if (ch_obj->req_type == MM_CAMERA_REQ_FRAME_SYNC_BUF) { 447 // Lock the Queues 448 mm_frame_sync_lock_queues(); 449 uint32_t match_frame = mm_frame_sync_find_matched(FALSE); 450 if (match_frame) { 451 uint8_t j = 0; 452 for (j = 0; j < MAX_NUM_CAMERA_PER_BUNDLE; j++) { 453 if (fs.ch_obj[j]) { 454 mm_channel_queue_t *ch_queue = 455 &fs.ch_obj[j]->bundle.superbuf_queue; 456 if (ch_queue == NULL) { 457 LOGW("Channel queue is NULL"); 458 break; 459 } 460 node = mm_channel_superbuf_dequeue_frame_internal( 461 ch_queue, match_frame); 462 if (node != NULL) { 463 info.ch_obj[info.num_nodes] = fs.ch_obj[j]; 464 info.node[info.num_nodes] = node; 465 info.num_nodes++; 466 LOGH("Added ch(%p) to node ,num nodes %d", 467 fs.ch_obj[j], info.num_nodes); 468 } 469 } 470 } 471 mm_frame_sync_remove(match_frame); 472 LOGI("match frame %d", match_frame); 473 if (info.num_nodes != fs.num_cam) { 474 LOGI("num node %d != num cam (%d) Debug this", 475 info.num_nodes, fs.num_cam); 476 uint8_t j = 0; 477 // free super buffers from various nodes 478 for (j = 0; j < info.num_nodes; j++) { 479 if (info.node[j]) { 480 mm_channel_node_qbuf(info.ch_obj[j], info.node[j]); 481 free(info.node[j]); 482 } 483 } 484 // we should not use it as matched dual camera frames 485 info.num_nodes = 0; 486 } 487 } 488 mm_frame_sync_unlock_queues(); 489 } else { 490 node = mm_channel_superbuf_dequeue(&ch_obj->bundle.superbuf_queue, ch_obj); 491 if (node != NULL) { 492 if (ch_obj->isConfigCapture && 493 ((node->frame_idx < 494 ch_obj->capture_frame_id[ch_obj->cur_capture_idx]))) { 495 uint8_t i; 496 LOGD("Not expected super buffer. frameID = %d expected = %d", 497 node->frame_idx, ch_obj->capture_frame_id[ch_obj->cur_capture_idx]); 498 for (i = 0; i < node->num_of_bufs; i++) { 499 mm_channel_qbuf(ch_obj, node->super_buf[i].buf); 500 } 501 free(node); 502 } else { 503 info.num_nodes = 1; 504 info.ch_obj[0] = ch_obj; 505 info.node[0] = node; 506 } 507 } 508 } 509 if (info.num_nodes > 0) { 510 /* decrease pending_cnt */ 511 if (MM_CAMERA_SUPER_BUF_NOTIFY_BURST == notify_mode) { 512 ch_obj->pending_cnt--; 513 if (ch_obj->pending_retro_cnt > 0) { 514 if (ch_obj->pending_retro_cnt == 1) { 515 ch_obj->bWaitForPrepSnapshotDone = 1; 516 } 517 ch_obj->pending_retro_cnt--; 518 } 519 520 if (((ch_obj->pending_cnt == 0) || 521 (ch_obj->stopZslSnapshot == 1)) && 522 (ch_obj->manualZSLSnapshot == FALSE) && 523 ch_obj->startZSlSnapshotCalled == TRUE) { 524 LOGI("TRIGGER Stop ZSL. All frame received"); 525 mm_camera_stop_zsl_snapshot(ch_obj->cam_obj); 526 ch_obj->startZSlSnapshotCalled = FALSE; 527 ch_obj->burstSnapNum = 0; 528 ch_obj->stopZslSnapshot = 0; 529 ch_obj->unLockAEC = 1; 530 ch_obj->needLEDFlash = FALSE; 531 ch_obj->bracketingState = MM_CHANNEL_BRACKETING_STATE_OFF; 532 ch_obj->isConfigCapture = FALSE; 533 } 534 535 if (ch_obj->isConfigCapture) { 536 if (ch_obj->frameConfig.configs[ch_obj->cur_capture_idx].num_frames != 0) { 537 ch_obj->frameConfig.configs[ch_obj->cur_capture_idx].num_frames--; 538 } else { 539 LOGW("Invalid frame config batch index %d max batch = %d", 540 ch_obj->cur_capture_idx, ch_obj->frameConfig.num_batch); 541 } 542 543 if (ch_obj->frameConfig.configs[ch_obj->cur_capture_idx].num_frames == 0) { 544 //Received all frames for current batch 545 ch_obj->cur_capture_idx++; 546 ch_obj->bundle.superbuf_queue.expected_frame_id = 547 ch_obj->capture_frame_id[ch_obj->cur_capture_idx]; 548 ch_obj->bundle.superbuf_queue.good_frame_id = 549 ch_obj->capture_frame_id[ch_obj->cur_capture_idx]; 550 } else { 551 LOGH("Need %d frames more for batch %d", 552 ch_obj->frameConfig.configs[ch_obj->cur_capture_idx].num_frames, 553 ch_obj->cur_capture_idx); 554 } 555 } 556 } 557 /* dispatch superbuf */ 558 mm_channel_send_super_buf(&info); 559 } else { 560 /* no superbuf avail, break the loop */ 561 break; 562 } 563 } 564 } 565 566 /*=========================================================================== 567 * FUNCTION : mm_channel_send_super_buf 568 * 569 * DESCRIPTION: Send super buffers to HAL 570 * 571 * PARAMETERS : 572 * @info : Info of super buffers to be sent in callback 573 * 574 * RETURN : None 575 *==========================================================================*/ 576 void mm_channel_send_super_buf(mm_channel_node_info_t *info) 577 { 578 if (!info || !info->num_nodes){ 579 LOGE("X Error!! Info invalid"); 580 return; 581 } 582 mm_channel_queue_node_t *node = NULL; 583 584 LOGH("num nodes %d to send", info->num_nodes); 585 uint32_t idx = 0; 586 mm_channel_t *ch_obj = NULL; 587 for (idx = 0; idx < info->num_nodes; idx++) { 588 node = info->node[idx]; 589 ch_obj = info->ch_obj[idx]; 590 if ((ch_obj) && (NULL != ch_obj->bundle.super_buf_notify_cb) && node) { 591 mm_camera_cmdcb_t* cb_node = NULL; 592 LOGD("Send superbuf to HAL, pending_cnt=%d", 593 ch_obj->pending_cnt); 594 /* send cam_sem_post to wake up cb thread to dispatch super buffer */ 595 cb_node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t)); 596 if (NULL != cb_node) { 597 memset(cb_node, 0, sizeof(mm_camera_cmdcb_t)); 598 cb_node->cmd_type = MM_CAMERA_CMD_TYPE_SUPER_BUF_DATA_CB; 599 cb_node->u.superbuf.num_bufs = node->num_of_bufs; 600 uint8_t i = 0; 601 for (i = 0; i < node->num_of_bufs; i++) { 602 cb_node->u.superbuf.bufs[i] = node->super_buf[i].buf; 603 } 604 cb_node->u.superbuf.camera_handle = ch_obj->cam_obj->my_hdl; 605 cb_node->u.superbuf.ch_id = ch_obj->my_hdl; 606 cb_node->u.superbuf.bReadyForPrepareSnapshot = 607 ch_obj->bWaitForPrepSnapshotDone; 608 if (ch_obj->unLockAEC == 1) { 609 cb_node->u.superbuf.bUnlockAEC = 1; 610 LOGH("Unlocking AEC"); 611 ch_obj->unLockAEC = 0; 612 } 613 /* enqueue to cb thread */ 614 cam_queue_enq(&(ch_obj->cb_thread.cmd_queue), cb_node); 615 /* wake up cb thread */ 616 cam_sem_post(&(ch_obj->cb_thread.cmd_sem)); 617 LOGH("Sent super buf for node[%d] ", idx); 618 619 } else { 620 LOGE("No memory for mm_camera_node_t"); 621 /* buf done with the unused super buf */ 622 uint8_t i = 0; 623 for (i = 0; i < node->num_of_bufs; i++) { 624 mm_channel_qbuf(ch_obj, node->super_buf[i].buf); 625 } 626 } 627 free(node); 628 } else if ((ch_obj != NULL) && (node != NULL)) { 629 /* buf done with the unused super buf */ 630 uint8_t i; 631 for (i = 0; i < node->num_of_bufs; i++) { 632 mm_channel_qbuf(ch_obj, node->super_buf[i].buf); 633 } 634 free(node); 635 } else { 636 LOGE("node is NULL, debug this"); 637 } 638 } 639 } 640 641 /*=========================================================================== 642 * FUNCTION : mm_channel_reg_stream_buf_cb 643 * 644 * DESCRIPTION: Register callback for stream buffer 645 * 646 * PARAMETERS : 647 * @my_obj : Channel object 648 * @stream_id : stream that will be linked 649 * @buf_cb : special callback needs to be registered for stream buffer 650 * 651 * RETURN : int32_t type of status 652 * 0 -- success 653 * -1 -- failure 654 *==========================================================================*/ 655 int32_t mm_channel_reg_stream_buf_cb (mm_channel_t* my_obj, 656 uint32_t stream_id, mm_stream_data_cb_t buf_cb) 657 { 658 int32_t rc = -1; 659 mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj, 660 stream_id); 661 662 if (NULL != s_obj) { 663 if (s_obj->ch_obj != my_obj) { 664 /* No op. on linked streams */ 665 return 0; 666 } 667 rc = mm_stream_reg_buf_cb(s_obj, buf_cb); 668 } 669 670 return rc; 671 672 } 673 674 /*=========================================================================== 675 * FUNCTION : mm_channel_fsm_fn 676 * 677 * DESCRIPTION: channel finite state machine entry function. Depends on channel 678 * state, incoming event will be handled differently. 679 * 680 * PARAMETERS : 681 * @my_obj : ptr to a channel object 682 * @evt : channel event to be processed 683 * @in_val : input event payload. Can be NULL if not needed. 684 * @out_val : output payload, Can be NULL if not needed. 685 * 686 * RETURN : int32_t type of status 687 * 0 -- success 688 * -1 -- failure 689 *==========================================================================*/ 690 int32_t mm_channel_fsm_fn(mm_channel_t *my_obj, 691 mm_channel_evt_type_t evt, 692 void * in_val, 693 void * out_val) 694 { 695 int32_t rc = -1; 696 697 LOGD("E state = %d", my_obj->state); 698 switch (my_obj->state) { 699 case MM_CHANNEL_STATE_NOTUSED: 700 rc = mm_channel_fsm_fn_notused(my_obj, evt, in_val, out_val); 701 break; 702 case MM_CHANNEL_STATE_STOPPED: 703 rc = mm_channel_fsm_fn_stopped(my_obj, evt, in_val, out_val); 704 break; 705 case MM_CHANNEL_STATE_ACTIVE: 706 rc = mm_channel_fsm_fn_active(my_obj, evt, in_val, out_val); 707 break; 708 case MM_CHANNEL_STATE_PAUSED: 709 rc = mm_channel_fsm_fn_paused(my_obj, evt, in_val, out_val); 710 break; 711 default: 712 LOGD("Not a valid state (%d)", my_obj->state); 713 break; 714 } 715 716 /* unlock ch_lock */ 717 pthread_mutex_unlock(&my_obj->ch_lock); 718 LOGD("X rc = %d", rc); 719 return rc; 720 } 721 722 /*=========================================================================== 723 * FUNCTION : mm_channel_fsm_fn_notused 724 * 725 * DESCRIPTION: channel finite state machine function to handle event 726 * in NOT_USED state. 727 * 728 * PARAMETERS : 729 * @my_obj : ptr to a channel object 730 * @evt : channel event to be processed 731 * @in_val : input event payload. Can be NULL if not needed. 732 * @out_val : output payload, Can be NULL if not needed. 733 * 734 * RETURN : int32_t type of status 735 * 0 -- success 736 * -1 -- failure 737 *==========================================================================*/ 738 int32_t mm_channel_fsm_fn_notused(mm_channel_t *my_obj, 739 mm_channel_evt_type_t evt, 740 void * in_val, 741 void * out_val) 742 { 743 int32_t rc = -1; 744 745 switch (evt) { 746 default: 747 LOGE("invalid state (%d) for evt (%d), in(%p), out(%p)", 748 my_obj->state, evt, in_val, out_val); 749 break; 750 } 751 752 return rc; 753 } 754 755 /*=========================================================================== 756 * FUNCTION : mm_channel_fsm_fn_stopped 757 * 758 * DESCRIPTION: channel finite state machine function to handle event 759 * in STOPPED state. 760 * 761 * PARAMETERS : 762 * @my_obj : ptr to a channel object 763 * @evt : channel event to be processed 764 * @in_val : input event payload. Can be NULL if not needed. 765 * @out_val : output payload, Can be NULL if not needed. 766 * 767 * RETURN : int32_t type of status 768 * 0 -- success 769 * -1 -- failure 770 *==========================================================================*/ 771 int32_t mm_channel_fsm_fn_stopped(mm_channel_t *my_obj, 772 mm_channel_evt_type_t evt, 773 void * in_val, 774 void * out_val) 775 { 776 int32_t rc = 0; 777 LOGD("E evt = %d", evt); 778 switch (evt) { 779 case MM_CHANNEL_EVT_ADD_STREAM: 780 { 781 uint32_t s_hdl = 0; 782 s_hdl = mm_channel_add_stream(my_obj); 783 *((uint32_t*)out_val) = s_hdl; 784 rc = 0; 785 } 786 break; 787 case MM_CHANNEL_EVT_LINK_STREAM: 788 { 789 mm_camera_stream_link_t *stream_link = NULL; 790 uint32_t s_hdl = 0; 791 stream_link = (mm_camera_stream_link_t *) in_val; 792 s_hdl = mm_channel_link_stream(my_obj, stream_link); 793 *((uint32_t*)out_val) = s_hdl; 794 rc = 0; 795 } 796 break; 797 case MM_CHANNEL_EVT_DEL_STREAM: 798 { 799 uint32_t s_id = *((uint32_t *)in_val); 800 rc = mm_channel_del_stream(my_obj, s_id); 801 } 802 break; 803 case MM_CHANNEL_EVT_START: 804 { 805 rc = mm_channel_start(my_obj); 806 /* first stream started in stopped state 807 * move to active state */ 808 if (0 == rc) { 809 my_obj->state = MM_CHANNEL_STATE_ACTIVE; 810 } 811 } 812 break; 813 case MM_CHANNEL_EVT_CONFIG_STREAM: 814 { 815 mm_evt_paylod_config_stream_t *payload = 816 (mm_evt_paylod_config_stream_t *)in_val; 817 rc = mm_channel_config_stream(my_obj, 818 payload->stream_id, 819 payload->config); 820 } 821 break; 822 case MM_CHANNEL_EVT_GET_BUNDLE_INFO: 823 { 824 cam_bundle_config_t *payload = 825 (cam_bundle_config_t *)in_val; 826 rc = mm_channel_get_bundle_info(my_obj, payload); 827 } 828 break; 829 case MM_CHANNEL_EVT_DELETE: 830 { 831 mm_channel_release(my_obj); 832 rc = 0; 833 } 834 break; 835 case MM_CHANNEL_EVT_SET_STREAM_PARM: 836 { 837 mm_evt_paylod_set_get_stream_parms_t *payload = 838 (mm_evt_paylod_set_get_stream_parms_t *)in_val; 839 rc = mm_channel_set_stream_parm(my_obj, payload); 840 } 841 break; 842 case MM_CHANNEL_EVT_GET_STREAM_QUEUED_BUF_COUNT: 843 { 844 uint32_t stream_id = *((uint32_t *)in_val); 845 rc = mm_channel_get_queued_buf_count(my_obj, stream_id); 846 } 847 break; 848 case MM_CHANNEL_EVT_GET_STREAM_PARM: 849 { 850 mm_evt_paylod_set_get_stream_parms_t *payload = 851 (mm_evt_paylod_set_get_stream_parms_t *)in_val; 852 rc = mm_channel_get_stream_parm(my_obj, payload); 853 } 854 break; 855 case MM_CHANNEL_EVT_DO_STREAM_ACTION: 856 { 857 mm_evt_paylod_do_stream_action_t *payload = 858 (mm_evt_paylod_do_stream_action_t *)in_val; 859 rc = mm_channel_do_stream_action(my_obj, payload); 860 } 861 break; 862 case MM_CHANNEL_EVT_MAP_STREAM_BUF: 863 { 864 cam_buf_map_type *payload = 865 (cam_buf_map_type *)in_val; 866 rc = mm_channel_map_stream_buf(my_obj, payload); 867 } 868 break; 869 case MM_CHANNEL_EVT_MAP_STREAM_BUFS: 870 { 871 cam_buf_map_type_list *payload = 872 (cam_buf_map_type_list *)in_val; 873 rc = mm_channel_map_stream_bufs(my_obj, payload); 874 } 875 break; 876 case MM_CHANNEL_EVT_UNMAP_STREAM_BUF: 877 { 878 cam_buf_unmap_type *payload = 879 (cam_buf_unmap_type *)in_val; 880 rc = mm_channel_unmap_stream_buf(my_obj, payload); 881 } 882 break; 883 case MM_CHANNEL_EVT_REG_STREAM_BUF_CB: 884 { 885 mm_evt_paylod_reg_stream_buf_cb *payload = 886 (mm_evt_paylod_reg_stream_buf_cb *)in_val; 887 rc = mm_channel_reg_stream_buf_cb (my_obj, 888 payload->stream_id, payload->buf_cb); 889 } 890 break; 891 default: 892 LOGE("invalid state (%d) for evt (%d)", 893 my_obj->state, evt); 894 break; 895 } 896 LOGD("E rc = %d", rc); 897 return rc; 898 } 899 900 /*=========================================================================== 901 * FUNCTION : mm_channel_fsm_fn_active 902 * 903 * DESCRIPTION: channel finite state machine function to handle event 904 * in ACTIVE state. 905 * 906 * PARAMETERS : 907 * @my_obj : ptr to a channel object 908 * @evt : channel event to be processed 909 * @in_val : input event payload. Can be NULL if not needed. 910 * @out_val : output payload, Can be NULL if not needed. 911 * 912 * RETURN : int32_t type of status 913 * 0 -- success 914 * -1 -- failure 915 *==========================================================================*/ 916 int32_t mm_channel_fsm_fn_active(mm_channel_t *my_obj, 917 mm_channel_evt_type_t evt, 918 void * in_val, 919 void * out_val) 920 { 921 int32_t rc = 0; 922 923 LOGD("E evt = %d", evt); 924 switch (evt) { 925 case MM_CHANNEL_EVT_STOP: 926 { 927 rc = mm_channel_stop(my_obj); 928 my_obj->state = MM_CHANNEL_STATE_STOPPED; 929 } 930 break; 931 case MM_CHANNEL_EVT_REQUEST_SUPER_BUF: 932 { 933 mm_camera_req_buf_t *payload = 934 (mm_camera_req_buf_t *)in_val; 935 rc = mm_channel_request_super_buf(my_obj, payload); 936 } 937 break; 938 case MM_CHANNEL_EVT_CANCEL_REQUEST_SUPER_BUF: 939 { 940 rc = mm_channel_cancel_super_buf_request(my_obj); 941 } 942 break; 943 case MM_CHANNEL_EVT_FLUSH_SUPER_BUF_QUEUE: 944 { 945 uint32_t frame_idx = *((uint32_t *)in_val); 946 rc = mm_channel_flush_super_buf_queue(my_obj, frame_idx, CAM_STREAM_TYPE_DEFAULT); 947 } 948 break; 949 case MM_CHANNEL_EVT_START_ZSL_SNAPSHOT: 950 { 951 rc = mm_channel_start_zsl_snapshot(my_obj); 952 } 953 break; 954 case MM_CHANNEL_EVT_STOP_ZSL_SNAPSHOT: 955 { 956 rc = mm_channel_stop_zsl_snapshot(my_obj); 957 } 958 break; 959 case MM_CHANNEL_EVT_CONFIG_NOTIFY_MODE: 960 { 961 mm_camera_super_buf_notify_mode_t notify_mode = 962 *((mm_camera_super_buf_notify_mode_t *)in_val); 963 rc = mm_channel_config_notify_mode(my_obj, notify_mode); 964 } 965 break; 966 case MM_CHANNEL_EVT_SET_STREAM_PARM: 967 { 968 mm_evt_paylod_set_get_stream_parms_t *payload = 969 (mm_evt_paylod_set_get_stream_parms_t *)in_val; 970 rc = mm_channel_set_stream_parm(my_obj, payload); 971 } 972 break; 973 case MM_CHANNEL_EVT_GET_STREAM_QUEUED_BUF_COUNT: 974 { 975 uint32_t stream_id = *((uint32_t *)in_val); 976 rc = mm_channel_get_queued_buf_count(my_obj, stream_id); 977 } 978 break; 979 case MM_CHANNEL_EVT_GET_STREAM_PARM: 980 { 981 mm_evt_paylod_set_get_stream_parms_t *payload = 982 (mm_evt_paylod_set_get_stream_parms_t *)in_val; 983 rc = mm_channel_get_stream_parm(my_obj, payload); 984 } 985 break; 986 case MM_CHANNEL_EVT_DO_STREAM_ACTION: 987 { 988 mm_evt_paylod_do_stream_action_t *payload = 989 (mm_evt_paylod_do_stream_action_t *)in_val; 990 rc = mm_channel_do_stream_action(my_obj, payload); 991 } 992 break; 993 case MM_CHANNEL_EVT_MAP_STREAM_BUF: 994 { 995 cam_buf_map_type *payload = 996 (cam_buf_map_type *)in_val; 997 if (payload != NULL) { 998 uint8_t type = payload->type; 999 if ((type == CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF) || 1000 (type == CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF)) { 1001 rc = mm_channel_map_stream_buf(my_obj, payload); 1002 } 1003 } else { 1004 LOGE("cannot map regualr stream buf in active state"); 1005 } 1006 } 1007 break; 1008 case MM_CHANNEL_EVT_MAP_STREAM_BUFS: 1009 { 1010 cam_buf_map_type_list *payload = 1011 (cam_buf_map_type_list *)in_val; 1012 if ((payload != NULL) && (payload->length > 0)) { 1013 uint8_t type = payload->buf_maps[0].type; 1014 if ((type == CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF) || 1015 (type == CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF)) { 1016 rc = mm_channel_map_stream_bufs(my_obj, payload); 1017 } 1018 } else { 1019 LOGE("cannot map regualr stream buf in active state"); 1020 } 1021 } 1022 break; 1023 case MM_CHANNEL_EVT_UNMAP_STREAM_BUF: 1024 { 1025 cam_buf_unmap_type *payload = 1026 (cam_buf_unmap_type *)in_val; 1027 if (payload != NULL) { 1028 uint8_t type = payload->type; 1029 if ((type == CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF) || 1030 (type == CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF)) { 1031 rc = mm_channel_unmap_stream_buf(my_obj, payload); 1032 } 1033 } else { 1034 LOGE("cannot unmap regualr stream buf in active state"); 1035 } 1036 } 1037 break; 1038 case MM_CHANNEL_EVT_AF_BRACKETING: 1039 { 1040 LOGH("MM_CHANNEL_EVT_AF_BRACKETING"); 1041 uint32_t start_flag = *((uint32_t *)in_val); 1042 mm_camera_generic_cmd_t gen_cmd; 1043 gen_cmd.type = MM_CAMERA_GENERIC_CMD_TYPE_AF_BRACKETING; 1044 gen_cmd.payload[0] = start_flag; 1045 rc = mm_channel_proc_general_cmd(my_obj, &gen_cmd); 1046 } 1047 break; 1048 case MM_CHANNEL_EVT_AE_BRACKETING: 1049 { 1050 LOGH("MM_CHANNEL_EVT_AE_BRACKETING"); 1051 uint32_t start_flag = *((uint32_t *)in_val); 1052 mm_camera_generic_cmd_t gen_cmd; 1053 gen_cmd.type = MM_CAMERA_GENERIC_CMD_TYPE_AE_BRACKETING; 1054 gen_cmd.payload[0] = start_flag; 1055 rc = mm_channel_proc_general_cmd(my_obj, &gen_cmd); 1056 } 1057 break; 1058 case MM_CHANNEL_EVT_FLASH_BRACKETING: 1059 { 1060 LOGH("MM_CHANNEL_EVT_FLASH_BRACKETING"); 1061 uint32_t start_flag = *((uint32_t *)in_val); 1062 mm_camera_generic_cmd_t gen_cmd; 1063 gen_cmd.type = MM_CAMERA_GENERIC_CMD_TYPE_FLASH_BRACKETING; 1064 gen_cmd.payload[0] = start_flag; 1065 rc = mm_channel_proc_general_cmd(my_obj, &gen_cmd); 1066 } 1067 break; 1068 case MM_CHANNEL_EVT_ZOOM_1X: 1069 { 1070 LOGH("MM_CHANNEL_EVT_ZOOM_1X"); 1071 uint32_t start_flag = *((uint32_t *)in_val); 1072 mm_camera_generic_cmd_t gen_cmd; 1073 gen_cmd.type = MM_CAMERA_GENERIC_CMD_TYPE_ZOOM_1X; 1074 gen_cmd.payload[0] = start_flag; 1075 rc = mm_channel_proc_general_cmd(my_obj, &gen_cmd); 1076 } 1077 break; 1078 case MM_CAMERA_EVT_CAPTURE_SETTING: 1079 { 1080 mm_camera_generic_cmd_t gen_cmd; 1081 cam_capture_frame_config_t *input; 1082 gen_cmd.type = MM_CAMERA_GENERIC_CMD_TYPE_CAPTURE_SETTING; 1083 LOGH("MM_CAMERA_EVT_CAPTURE_SETTING"); 1084 if (in_val == NULL) { 1085 gen_cmd.payload[0] = 0; 1086 memset(&gen_cmd.frame_config, 0, sizeof(cam_capture_frame_config_t)); 1087 } else { 1088 gen_cmd.payload[0] = 1; 1089 input = (cam_capture_frame_config_t *)in_val; 1090 gen_cmd.frame_config = *input; 1091 } 1092 rc = mm_channel_proc_general_cmd(my_obj, &gen_cmd); 1093 } 1094 break; 1095 case MM_CHANNEL_EVT_REG_STREAM_BUF_CB: 1096 { 1097 mm_evt_paylod_reg_stream_buf_cb *payload = 1098 (mm_evt_paylod_reg_stream_buf_cb *)in_val; 1099 rc = mm_channel_reg_stream_buf_cb (my_obj, 1100 payload->stream_id, payload->buf_cb); 1101 } 1102 break; 1103 default: 1104 LOGE("invalid state (%d) for evt (%d), in(%p), out(%p)", 1105 my_obj->state, evt, in_val, out_val); 1106 break; 1107 } 1108 LOGD("X rc = %d", rc); 1109 return rc; 1110 } 1111 1112 /*=========================================================================== 1113 * FUNCTION : mm_channel_fsm_fn_paused 1114 * 1115 * DESCRIPTION: channel finite state machine function to handle event 1116 * in PAUSED state. 1117 * 1118 * PARAMETERS : 1119 * @my_obj : ptr to a channel object 1120 * @evt : channel event to be processed 1121 * @in_val : input event payload. Can be NULL if not needed. 1122 * @out_val : output payload, Can be NULL if not needed. 1123 * 1124 * RETURN : int32_t type of status 1125 * 0 -- success 1126 * -1 -- failure 1127 *==========================================================================*/ 1128 int32_t mm_channel_fsm_fn_paused(mm_channel_t *my_obj, 1129 mm_channel_evt_type_t evt, 1130 void * in_val, 1131 void * out_val) 1132 { 1133 int32_t rc = 0; 1134 1135 /* currently we are not supporting pause/resume channel */ 1136 LOGE("invalid state (%d) for evt (%d), in(%p), out(%p)", 1137 my_obj->state, evt, in_val, out_val); 1138 1139 return rc; 1140 } 1141 1142 /*=========================================================================== 1143 * FUNCTION : mm_channel_init 1144 * 1145 * DESCRIPTION: initialize a channel 1146 * 1147 * PARAMETERS : 1148 * @my_obj : channel object be to initialized 1149 * @attr : bundle attribute of the channel if needed 1150 * @channel_cb : callback function for bundle data notify 1151 * @userdata : user data ptr 1152 * 1153 * RETURN : int32_t type of status 1154 * 0 -- success 1155 * -1 -- failure 1156 * NOTE : if no bundle data notify is needed, meaning each stream in the 1157 * channel will have its own stream data notify callback, then 1158 * attr, channel_cb, and userdata can be NULL. In this case, 1159 * no matching logic will be performed in channel for the bundling. 1160 *==========================================================================*/ 1161 int32_t mm_channel_init(mm_channel_t *my_obj, 1162 mm_camera_channel_attr_t *attr, 1163 mm_camera_buf_notify_t channel_cb, 1164 void *userdata) 1165 { 1166 int32_t rc = 0; 1167 1168 my_obj->bundle.super_buf_notify_cb = channel_cb; 1169 my_obj->bundle.user_data = userdata; 1170 if (NULL != attr) { 1171 my_obj->bundle.superbuf_queue.attr = *attr; 1172 } 1173 1174 LOGD("Launch data poll thread in channel open"); 1175 snprintf(my_obj->poll_thread[0].threadName, THREAD_NAME_SIZE, "CAM_dataPoll"); 1176 mm_camera_poll_thread_launch(&my_obj->poll_thread[0], 1177 MM_CAMERA_POLL_TYPE_DATA); 1178 1179 /* change state to stopped state */ 1180 my_obj->state = MM_CHANNEL_STATE_STOPPED; 1181 return rc; 1182 } 1183 1184 /*=========================================================================== 1185 * FUNCTION : mm_channel_release 1186 * 1187 * DESCRIPTION: release a channel resource. Channel state will move to UNUSED 1188 * state after this call. 1189 * 1190 * PARAMETERS : 1191 * @my_obj : channel object 1192 * 1193 * RETURN : none 1194 *==========================================================================*/ 1195 void mm_channel_release(mm_channel_t *my_obj) 1196 { 1197 /* stop data poll thread */ 1198 mm_camera_poll_thread_release(&my_obj->poll_thread[0]); 1199 1200 /* memset bundle info */ 1201 memset(&my_obj->bundle, 0, sizeof(mm_channel_bundle_t)); 1202 1203 /* change state to notused state */ 1204 my_obj->state = MM_CHANNEL_STATE_NOTUSED; 1205 } 1206 1207 /*=========================================================================== 1208 * FUNCTION : mm_channel_link_stream 1209 * 1210 * DESCRIPTION: link a stream from external channel into this channel 1211 * 1212 * PARAMETERS : 1213 * @my_obj : channel object 1214 * @stream_link : channel and stream to be linked 1215 * 1216 * RETURN : uint32_t type of stream handle 1217 * 0 -- invalid stream handle, meaning the op failed 1218 * >0 -- successfully added a stream with a valid handle 1219 *==========================================================================*/ 1220 uint32_t mm_channel_link_stream(mm_channel_t *my_obj, 1221 mm_camera_stream_link_t *stream_link) 1222 { 1223 uint8_t idx = 0; 1224 uint32_t s_hdl = 0; 1225 mm_stream_t *stream_obj = NULL; 1226 mm_stream_t *stream = NULL; 1227 1228 if (NULL == stream_link) { 1229 LOGE("Invalid stream link"); 1230 return 0; 1231 } 1232 1233 stream = mm_channel_util_get_stream_by_handler(stream_link->ch, 1234 stream_link->stream_id); 1235 if (NULL == stream) { 1236 return 0; 1237 } 1238 1239 /* check available stream */ 1240 for (idx = 0; idx < MAX_STREAM_NUM_IN_BUNDLE; idx++) { 1241 if (MM_STREAM_STATE_NOTUSED == my_obj->streams[idx].state) { 1242 stream_obj = &my_obj->streams[idx]; 1243 break; 1244 } 1245 } 1246 if (NULL == stream_obj) { 1247 LOGE("streams reach max, no more stream allowed to add"); 1248 return s_hdl; 1249 } 1250 1251 /* initialize stream object */ 1252 *stream_obj = *stream; 1253 stream_obj->linked_stream = stream; 1254 s_hdl = stream->my_hdl; 1255 1256 LOGD("stream handle = %d", s_hdl); 1257 return s_hdl; 1258 } 1259 1260 /*=========================================================================== 1261 * FUNCTION : mm_channel_add_stream 1262 * 1263 * DESCRIPTION: add a stream into the channel 1264 * 1265 * PARAMETERS : 1266 * @my_obj : channel object 1267 * 1268 * RETURN : uint32_t type of stream handle 1269 * 0 -- invalid stream handle, meaning the op failed 1270 * >0 -- successfully added a stream with a valid handle 1271 *==========================================================================*/ 1272 uint32_t mm_channel_add_stream(mm_channel_t *my_obj) 1273 { 1274 int32_t rc = 0; 1275 uint8_t idx = 0; 1276 uint32_t s_hdl = 0; 1277 mm_stream_t *stream_obj = NULL; 1278 1279 LOGD("E"); 1280 /* check available stream */ 1281 for (idx = 0; idx < MAX_STREAM_NUM_IN_BUNDLE; idx++) { 1282 if (MM_STREAM_STATE_NOTUSED == my_obj->streams[idx].state) { 1283 stream_obj = &my_obj->streams[idx]; 1284 break; 1285 } 1286 } 1287 if (NULL == stream_obj) { 1288 LOGE("streams reach max, no more stream allowed to add"); 1289 return s_hdl; 1290 } 1291 1292 /* initialize stream object */ 1293 memset(stream_obj, 0, sizeof(mm_stream_t)); 1294 stream_obj->fd = -1; 1295 stream_obj->my_hdl = mm_camera_util_generate_handler(idx); 1296 stream_obj->ch_obj = my_obj; 1297 pthread_mutex_init(&stream_obj->buf_lock, NULL); 1298 pthread_mutex_init(&stream_obj->cb_lock, NULL); 1299 pthread_mutex_init(&stream_obj->cmd_lock, NULL); 1300 pthread_cond_init(&stream_obj->buf_cond, NULL); 1301 memset(stream_obj->buf_status, 0, 1302 sizeof(stream_obj->buf_status)); 1303 stream_obj->state = MM_STREAM_STATE_INITED; 1304 1305 /* acquire stream */ 1306 rc = mm_stream_fsm_fn(stream_obj, MM_STREAM_EVT_ACQUIRE, NULL, NULL); 1307 if (0 == rc) { 1308 s_hdl = stream_obj->my_hdl; 1309 } else { 1310 /* error during acquire, de-init */ 1311 pthread_cond_destroy(&stream_obj->buf_cond); 1312 pthread_mutex_destroy(&stream_obj->buf_lock); 1313 pthread_mutex_destroy(&stream_obj->cb_lock); 1314 pthread_mutex_destroy(&stream_obj->cmd_lock); 1315 memset(stream_obj, 0, sizeof(mm_stream_t)); 1316 } 1317 LOGD("stream handle = %d", s_hdl); 1318 return s_hdl; 1319 } 1320 1321 /*=========================================================================== 1322 * FUNCTION : mm_channel_del_stream 1323 * 1324 * DESCRIPTION: delete a stream from the channel bu its handle 1325 * 1326 * PARAMETERS : 1327 * @my_obj : channel object 1328 * @stream_id : stream handle 1329 * 1330 * RETURN : int32_t type of status 1331 * 0 -- success 1332 * -1 -- failure 1333 * NOTE : assume steam is stooped before it can be deleted 1334 *==========================================================================*/ 1335 int32_t mm_channel_del_stream(mm_channel_t *my_obj, 1336 uint32_t stream_id) 1337 { 1338 int rc = -1; 1339 mm_stream_t * stream_obj = NULL; 1340 stream_obj = mm_channel_util_get_stream_by_handler(my_obj, stream_id); 1341 1342 if (NULL == stream_obj) { 1343 LOGE("Invalid Stream Object for stream_id = %d", stream_id); 1344 return rc; 1345 } 1346 1347 if (stream_obj->ch_obj != my_obj) { 1348 /* Only unlink stream */ 1349 pthread_mutex_lock(&stream_obj->linked_stream->buf_lock); 1350 stream_obj->linked_stream->is_linked = 0; 1351 stream_obj->linked_stream->linked_obj = NULL; 1352 pthread_mutex_unlock(&stream_obj->linked_stream->buf_lock); 1353 memset(stream_obj, 0, sizeof(mm_stream_t)); 1354 1355 return 0; 1356 } 1357 1358 rc = mm_stream_fsm_fn(stream_obj, 1359 MM_STREAM_EVT_RELEASE, 1360 NULL, 1361 NULL); 1362 1363 return rc; 1364 } 1365 1366 /*=========================================================================== 1367 * FUNCTION : mm_channel_config_stream 1368 * 1369 * DESCRIPTION: configure a stream 1370 * 1371 * PARAMETERS : 1372 * @my_obj : channel object 1373 * @stream_id : stream handle 1374 * @config : stream configuration 1375 * 1376 * RETURN : int32_t type of status 1377 * 0 -- success 1378 * -1 -- failure 1379 *==========================================================================*/ 1380 int32_t mm_channel_config_stream(mm_channel_t *my_obj, 1381 uint32_t stream_id, 1382 mm_camera_stream_config_t *config) 1383 { 1384 int rc = -1; 1385 mm_stream_t * stream_obj = NULL; 1386 LOGD("E stream ID = %d", stream_id); 1387 stream_obj = mm_channel_util_get_stream_by_handler(my_obj, stream_id); 1388 1389 if (NULL == stream_obj) { 1390 LOGE("Invalid Stream Object for stream_id = %d", stream_id); 1391 return rc; 1392 } 1393 1394 if (stream_obj->ch_obj != my_obj) { 1395 /* No op. on linked streams */ 1396 return 0; 1397 } 1398 1399 /* set stream fmt */ 1400 rc = mm_stream_fsm_fn(stream_obj, 1401 MM_STREAM_EVT_SET_FMT, 1402 (void *)config, 1403 NULL); 1404 LOGD("X rc = %d",rc); 1405 return rc; 1406 } 1407 1408 /*=========================================================================== 1409 * FUNCTION : mm_channel_get_bundle_info 1410 * 1411 * DESCRIPTION: query bundle info of the channel, which should include all 1412 * streams within this channel 1413 * 1414 * PARAMETERS : 1415 * @my_obj : channel object 1416 * @bundle_info : bundle info to be filled in 1417 * 1418 * RETURN : int32_t type of status 1419 * 0 -- success 1420 * -1 -- failure 1421 *==========================================================================*/ 1422 int32_t mm_channel_get_bundle_info(mm_channel_t *my_obj, 1423 cam_bundle_config_t *bundle_info) 1424 { 1425 int i; 1426 mm_stream_t *s_obj = NULL; 1427 cam_stream_type_t stream_type = CAM_STREAM_TYPE_DEFAULT; 1428 int32_t rc = 0; 1429 1430 memset(bundle_info, 0, sizeof(cam_bundle_config_t)); 1431 bundle_info->bundle_id = my_obj->my_hdl; 1432 bundle_info->num_of_streams = 0; 1433 for (i = 0; i < MAX_STREAM_NUM_IN_BUNDLE; i++) { 1434 if (my_obj->streams[i].my_hdl > 0) { 1435 s_obj = mm_channel_util_get_stream_by_handler(my_obj, 1436 my_obj->streams[i].my_hdl); 1437 if (NULL != s_obj) { 1438 stream_type = s_obj->stream_info->stream_type; 1439 if ((CAM_STREAM_TYPE_METADATA != stream_type) && 1440 (s_obj->ch_obj == my_obj)) { 1441 bundle_info->stream_ids[bundle_info->num_of_streams++] = 1442 s_obj->server_stream_id; 1443 } 1444 } else { 1445 LOGE("cannot find stream obj (%d) by handler (%d)", 1446 i, my_obj->streams[i].my_hdl); 1447 rc = -1; 1448 break; 1449 } 1450 } 1451 } 1452 if (rc != 0) { 1453 /* error, reset to 0 */ 1454 memset(bundle_info, 0, sizeof(cam_bundle_config_t)); 1455 } 1456 return rc; 1457 } 1458 1459 /*=========================================================================== 1460 * FUNCTION : mm_channel_start 1461 * 1462 * DESCRIPTION: start a channel, which will start all streams in the channel 1463 * 1464 * PARAMETERS : 1465 * @my_obj : channel object 1466 * 1467 * RETURN : int32_t type of status 1468 * 0 -- success 1469 * -1 -- failure 1470 *==========================================================================*/ 1471 int32_t mm_channel_start(mm_channel_t *my_obj) 1472 { 1473 int32_t rc = 0; 1474 int i = 0, j = 0; 1475 mm_stream_t *s_objs[MAX_STREAM_NUM_IN_BUNDLE] = {NULL}; 1476 uint8_t num_streams_to_start = 0; 1477 uint8_t num_streams_in_bundle_queue = 0; 1478 mm_stream_t *s_obj = NULL; 1479 int meta_stream_idx = 0; 1480 cam_stream_type_t stream_type = CAM_STREAM_TYPE_DEFAULT; 1481 1482 for (i = 0; i < MAX_STREAM_NUM_IN_BUNDLE; i++) { 1483 if (my_obj->streams[i].my_hdl > 0) { 1484 s_obj = mm_channel_util_get_stream_by_handler(my_obj, 1485 my_obj->streams[i].my_hdl); 1486 if (NULL != s_obj) { 1487 stream_type = s_obj->stream_info->stream_type; 1488 /* remember meta data stream index */ 1489 if ((stream_type == CAM_STREAM_TYPE_METADATA) && 1490 (s_obj->ch_obj == my_obj)) { 1491 meta_stream_idx = num_streams_to_start; 1492 } 1493 s_objs[num_streams_to_start++] = s_obj; 1494 1495 if (!s_obj->stream_info->noFrameExpected) { 1496 num_streams_in_bundle_queue++; 1497 } 1498 } 1499 } 1500 } 1501 1502 if (meta_stream_idx > 0 ) { 1503 /* always start meta data stream first, so switch the stream object with the first one */ 1504 s_obj = s_objs[0]; 1505 s_objs[0] = s_objs[meta_stream_idx]; 1506 s_objs[meta_stream_idx] = s_obj; 1507 } 1508 1509 if (NULL != my_obj->bundle.super_buf_notify_cb) { 1510 /* need to send up cb, therefore launch thread */ 1511 /* init superbuf queue */ 1512 mm_channel_superbuf_queue_init(&my_obj->bundle.superbuf_queue); 1513 my_obj->bundle.superbuf_queue.num_streams = num_streams_in_bundle_queue; 1514 my_obj->bundle.superbuf_queue.expected_frame_id = 1515 my_obj->bundle.superbuf_queue.attr.user_expected_frame_id; 1516 my_obj->bundle.superbuf_queue.expected_frame_id_without_led = 0; 1517 my_obj->bundle.superbuf_queue.led_off_start_frame_id = 0; 1518 my_obj->bundle.superbuf_queue.led_on_start_frame_id = 0; 1519 my_obj->bundle.superbuf_queue.led_on_num_frames = 0; 1520 my_obj->bundle.superbuf_queue.good_frame_id = 0; 1521 1522 for (i = 0; i < num_streams_to_start; i++) { 1523 /* Only bundle streams that belong to the channel */ 1524 if(!(s_objs[i]->stream_info->noFrameExpected)) { 1525 if (s_objs[i]->ch_obj == my_obj) { 1526 /* set bundled flag to streams */ 1527 s_objs[i]->is_bundled = 1; 1528 } 1529 my_obj->bundle.superbuf_queue.bundled_streams[j++] = s_objs[i]->my_hdl; 1530 } 1531 } 1532 1533 /* launch cb thread for dispatching super buf through cb */ 1534 snprintf(my_obj->cb_thread.threadName, THREAD_NAME_SIZE, "CAM_SuperBuf"); 1535 mm_camera_cmd_thread_launch(&my_obj->cb_thread, 1536 mm_channel_dispatch_super_buf, 1537 (void*)my_obj); 1538 1539 /* launch cmd thread for super buf dataCB */ 1540 snprintf(my_obj->cmd_thread.threadName, THREAD_NAME_SIZE, "CAM_SuperBufCB"); 1541 mm_camera_cmd_thread_launch(&my_obj->cmd_thread, 1542 mm_channel_process_stream_buf, 1543 (void*)my_obj); 1544 1545 /* set flag to TRUE */ 1546 my_obj->bundle.is_active = TRUE; 1547 } 1548 1549 /* link any streams first before starting the rest of the streams */ 1550 for (i = 0; i < num_streams_to_start; i++) { 1551 if (s_objs[i]->ch_obj != my_obj) { 1552 pthread_mutex_lock(&s_objs[i]->linked_stream->buf_lock); 1553 s_objs[i]->linked_stream->linked_obj = my_obj; 1554 s_objs[i]->linked_stream->is_linked = 1; 1555 pthread_mutex_unlock(&s_objs[i]->linked_stream->buf_lock); 1556 continue; 1557 } 1558 } 1559 1560 for (i = 0; i < num_streams_to_start; i++) { 1561 if (s_objs[i]->ch_obj != my_obj) { 1562 continue; 1563 } 1564 /* all streams within a channel should be started at the same time */ 1565 if (s_objs[i]->state == MM_STREAM_STATE_ACTIVE) { 1566 LOGE("stream already started idx(%d)", i); 1567 rc = -1; 1568 break; 1569 } 1570 1571 /* allocate buf */ 1572 rc = mm_stream_fsm_fn(s_objs[i], 1573 MM_STREAM_EVT_GET_BUF, 1574 NULL, 1575 NULL); 1576 if (0 != rc) { 1577 LOGE("get buf failed at idx(%d)", i); 1578 break; 1579 } 1580 1581 /* reg buf */ 1582 rc = mm_stream_fsm_fn(s_objs[i], 1583 MM_STREAM_EVT_REG_BUF, 1584 NULL, 1585 NULL); 1586 if (0 != rc) { 1587 LOGE("reg buf failed at idx(%d)", i); 1588 break; 1589 } 1590 1591 /* start stream */ 1592 rc = mm_stream_fsm_fn(s_objs[i], 1593 MM_STREAM_EVT_START, 1594 NULL, 1595 NULL); 1596 if (0 != rc) { 1597 LOGE("start stream failed at idx(%d)", i); 1598 break; 1599 } 1600 } 1601 1602 /* error handling */ 1603 if (0 != rc) { 1604 /* unlink the streams first */ 1605 for (j = 0; j < num_streams_to_start; j++) { 1606 if (s_objs[j]->ch_obj != my_obj) { 1607 pthread_mutex_lock(&s_objs[j]->linked_stream->buf_lock); 1608 s_objs[j]->linked_stream->is_linked = 0; 1609 s_objs[j]->linked_stream->linked_obj = NULL; 1610 pthread_mutex_unlock(&s_objs[j]->linked_stream->buf_lock); 1611 1612 if (TRUE == my_obj->bundle.is_active) { 1613 mm_channel_flush_super_buf_queue(my_obj, 0, 1614 s_objs[i]->stream_info->stream_type); 1615 } 1616 memset(s_objs[j], 0, sizeof(mm_stream_t)); 1617 continue; 1618 } 1619 } 1620 1621 for (j = 0; j <= i; j++) { 1622 if ((NULL == s_objs[j]) || (s_objs[j]->ch_obj != my_obj)) { 1623 continue; 1624 } 1625 /* stop streams*/ 1626 mm_stream_fsm_fn(s_objs[j], 1627 MM_STREAM_EVT_STOP, 1628 NULL, 1629 NULL); 1630 1631 /* unreg buf */ 1632 mm_stream_fsm_fn(s_objs[j], 1633 MM_STREAM_EVT_UNREG_BUF, 1634 NULL, 1635 NULL); 1636 1637 /* put buf back */ 1638 mm_stream_fsm_fn(s_objs[j], 1639 MM_STREAM_EVT_PUT_BUF, 1640 NULL, 1641 NULL); 1642 } 1643 1644 /* destroy super buf cmd thread */ 1645 if (TRUE == my_obj->bundle.is_active) { 1646 /* first stop bundle thread */ 1647 mm_camera_cmd_thread_release(&my_obj->cmd_thread); 1648 mm_camera_cmd_thread_release(&my_obj->cb_thread); 1649 1650 /* deinit superbuf queue */ 1651 mm_channel_superbuf_queue_deinit(&my_obj->bundle.superbuf_queue); 1652 1653 /* memset super buffer queue info */ 1654 my_obj->bundle.is_active = 0; 1655 memset(&my_obj->bundle.superbuf_queue, 0, sizeof(mm_channel_queue_t)); 1656 } 1657 } 1658 my_obj->bWaitForPrepSnapshotDone = 0; 1659 if (my_obj->bundle.superbuf_queue.attr.enable_frame_sync) { 1660 LOGH("registering Channel obj %p", my_obj); 1661 mm_frame_sync_register_channel(my_obj); 1662 } 1663 return rc; 1664 } 1665 1666 /*=========================================================================== 1667 * FUNCTION : mm_channel_stop 1668 * 1669 * DESCRIPTION: stop a channel, which will stop all streams in the channel 1670 * 1671 * PARAMETERS : 1672 * @my_obj : channel object 1673 * 1674 * RETURN : int32_t type of status 1675 * 0 -- success 1676 * -1 -- failure 1677 *==========================================================================*/ 1678 int32_t mm_channel_stop(mm_channel_t *my_obj) 1679 { 1680 int32_t rc = 0; 1681 int i; 1682 mm_stream_t *s_objs[MAX_STREAM_NUM_IN_BUNDLE] = {NULL}; 1683 uint8_t num_streams_to_stop = 0; 1684 mm_stream_t *s_obj = NULL; 1685 int meta_stream_idx = 0; 1686 cam_stream_type_t stream_type = CAM_STREAM_TYPE_DEFAULT; 1687 1688 if (my_obj->bundle.superbuf_queue.attr.enable_frame_sync) { 1689 mm_frame_sync_unregister_channel(my_obj); 1690 } 1691 1692 for (i = 0; i < MAX_STREAM_NUM_IN_BUNDLE; i++) { 1693 if (my_obj->streams[i].my_hdl > 0) { 1694 s_obj = mm_channel_util_get_stream_by_handler(my_obj, 1695 my_obj->streams[i].my_hdl); 1696 if (NULL != s_obj) { 1697 if (s_obj->ch_obj == my_obj) { 1698 stream_type = s_obj->stream_info->stream_type; 1699 /* remember meta data stream index */ 1700 if (stream_type == CAM_STREAM_TYPE_METADATA) { 1701 meta_stream_idx = num_streams_to_stop; 1702 } 1703 } 1704 s_objs[num_streams_to_stop++] = s_obj; 1705 } 1706 } 1707 } 1708 1709 if (meta_stream_idx < num_streams_to_stop - 1 ) { 1710 /* always stop meta data stream last, so switch the stream object with the last one */ 1711 s_obj = s_objs[num_streams_to_stop - 1]; 1712 s_objs[num_streams_to_stop - 1] = s_objs[meta_stream_idx]; 1713 s_objs[meta_stream_idx] = s_obj; 1714 } 1715 1716 for (i = 0; i < num_streams_to_stop; i++) { 1717 /* stream that are linked to this channel should not be stopped */ 1718 if (s_objs[i]->ch_obj != my_obj) { 1719 continue; 1720 } 1721 1722 /* stream off */ 1723 mm_stream_fsm_fn(s_objs[i], 1724 MM_STREAM_EVT_STOP, 1725 NULL, 1726 NULL); 1727 1728 /* unreg buf at kernel */ 1729 mm_stream_fsm_fn(s_objs[i], 1730 MM_STREAM_EVT_UNREG_BUF, 1731 NULL, 1732 NULL); 1733 } 1734 1735 for (i = 0; i < num_streams_to_stop; i++) { 1736 if (s_objs[i]->ch_obj != my_obj) { 1737 /* Only unlink stream */ 1738 pthread_mutex_lock(&s_objs[i]->linked_stream->buf_lock); 1739 s_objs[i]->linked_stream->is_linked = 0; 1740 s_objs[i]->linked_stream->linked_obj = NULL; 1741 pthread_mutex_unlock(&s_objs[i]->linked_stream->buf_lock); 1742 } 1743 } 1744 1745 /* destroy super buf cmd thread */ 1746 if (TRUE == my_obj->bundle.is_active) { 1747 mm_channel_flush_super_buf_queue(my_obj, 0, CAM_STREAM_TYPE_DEFAULT); 1748 /* first stop bundle thread */ 1749 mm_camera_cmd_thread_release(&my_obj->cmd_thread); 1750 mm_camera_cmd_thread_release(&my_obj->cb_thread); 1751 1752 /* deinit superbuf queue */ 1753 mm_channel_superbuf_queue_deinit(&my_obj->bundle.superbuf_queue); 1754 1755 /* reset few fields in the bundle info */ 1756 my_obj->bundle.is_active = 0; 1757 my_obj->bundle.superbuf_queue.expected_frame_id = 0; 1758 my_obj->bundle.superbuf_queue.good_frame_id = 0; 1759 my_obj->bundle.superbuf_queue.match_cnt = 0; 1760 } 1761 1762 /* since all streams are stopped, we are safe to 1763 * release all buffers allocated in stream */ 1764 for (i = 0; i < num_streams_to_stop; i++) { 1765 if (s_objs[i]->ch_obj != my_obj) { 1766 continue; 1767 } 1768 /* put buf back */ 1769 mm_stream_fsm_fn(s_objs[i], 1770 MM_STREAM_EVT_PUT_BUF, 1771 NULL, 1772 NULL); 1773 } 1774 1775 for (i = 0; i < num_streams_to_stop; i++) { 1776 if (s_objs[i]->ch_obj != my_obj) { 1777 memset(s_objs[i], 0, sizeof(mm_stream_t)); 1778 } else { 1779 continue; 1780 } 1781 } 1782 1783 return rc; 1784 } 1785 1786 /*=========================================================================== 1787 * FUNCTION : mm_channel_request_super_buf 1788 * 1789 * DESCRIPTION: for burst mode in bundle, reuqest certain amount of matched 1790 * frames from superbuf queue 1791 * 1792 * PARAMETERS : 1793 * @my_obj : channel object 1794 * @num_buf_requested : number of matched frames needed 1795 * @num_retro_buf_requested : number of retro frames needed 1796 * 1797 * RETURN : int32_t type of status 1798 * 0 -- success 1799 * -1 -- failure 1800 *==========================================================================*/ 1801 int32_t mm_channel_request_super_buf(mm_channel_t *my_obj, 1802 mm_camera_req_buf_t *buf) 1803 { 1804 int32_t rc = 0; 1805 mm_camera_cmdcb_t* node = NULL; 1806 1807 if(!buf) { 1808 LOGE("Request info buf is NULL"); 1809 return -1; 1810 } 1811 1812 /* set pending_cnt 1813 * will trigger dispatching super frames if pending_cnt > 0 */ 1814 /* send cam_sem_post to wake up cmd thread to dispatch super buffer */ 1815 node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t)); 1816 if (NULL != node) { 1817 memset(node, 0, sizeof(mm_camera_cmdcb_t)); 1818 node->cmd_type = MM_CAMERA_CMD_TYPE_REQ_DATA_CB; 1819 node->u.req_buf = *buf; 1820 1821 /* enqueue to cmd thread */ 1822 cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node); 1823 1824 /* wake up cmd thread */ 1825 cam_sem_post(&(my_obj->cmd_thread.cmd_sem)); 1826 } else { 1827 LOGE("No memory for mm_camera_node_t"); 1828 rc = -1; 1829 } 1830 1831 return rc; 1832 } 1833 1834 /*=========================================================================== 1835 * FUNCTION : mm_channel_cancel_super_buf_request 1836 * 1837 * DESCRIPTION: for burst mode in bundle, cancel the reuqest for certain amount 1838 * of matched frames from superbuf queue 1839 * 1840 * PARAMETERS : 1841 * @my_obj : channel object 1842 * 1843 * RETURN : int32_t type of status 1844 * 0 -- success 1845 * -1 -- failure 1846 *==========================================================================*/ 1847 int32_t mm_channel_cancel_super_buf_request(mm_channel_t *my_obj) 1848 { 1849 int32_t rc = 0; 1850 /* reset pending_cnt */ 1851 mm_camera_req_buf_t buf; 1852 memset(&buf, 0x0, sizeof(buf)); 1853 buf.type = MM_CAMERA_REQ_SUPER_BUF; 1854 buf.num_buf_requested = 0; 1855 rc = mm_channel_request_super_buf(my_obj, &buf); 1856 return rc; 1857 } 1858 1859 /*=========================================================================== 1860 * FUNCTION : mm_channel_flush_super_buf_queue 1861 * 1862 * DESCRIPTION: flush superbuf queue 1863 * 1864 * PARAMETERS : 1865 * @my_obj : channel object 1866 * @frame_idx : frame idx until which to flush all superbufs 1867 * 1868 * RETURN : int32_t type of status 1869 * 0 -- success 1870 * -1 -- failure 1871 *==========================================================================*/ 1872 int32_t mm_channel_flush_super_buf_queue(mm_channel_t *my_obj, uint32_t frame_idx, 1873 cam_stream_type_t stream_type) 1874 { 1875 int32_t rc = 0; 1876 mm_camera_cmdcb_t* node = NULL; 1877 1878 node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t)); 1879 if (NULL != node) { 1880 memset(node, 0, sizeof(mm_camera_cmdcb_t)); 1881 node->cmd_type = MM_CAMERA_CMD_TYPE_FLUSH_QUEUE; 1882 node->u.flush_cmd.frame_idx = frame_idx; 1883 node->u.flush_cmd.stream_type = stream_type; 1884 1885 /* enqueue to cmd thread */ 1886 cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node); 1887 1888 /* wake up cmd thread */ 1889 cam_sem_post(&(my_obj->cmd_thread.cmd_sem)); 1890 1891 /* wait for ack from cmd thread */ 1892 cam_sem_wait(&(my_obj->cmd_thread.sync_sem)); 1893 } else { 1894 LOGE("No memory for mm_camera_node_t"); 1895 rc = -1; 1896 } 1897 1898 return rc; 1899 } 1900 1901 /*=========================================================================== 1902 * FUNCTION : mm_channel_config_notify_mode 1903 * 1904 * DESCRIPTION: configure notification mode 1905 * 1906 * PARAMETERS : 1907 * @my_obj : channel object 1908 * @notify_mode : notification mode 1909 * 1910 * RETURN : int32_t type of status 1911 * 0 -- success 1912 * -1 -- failure 1913 *==========================================================================*/ 1914 int32_t mm_channel_config_notify_mode(mm_channel_t *my_obj, 1915 mm_camera_super_buf_notify_mode_t notify_mode) 1916 { 1917 int32_t rc = 0; 1918 mm_camera_cmdcb_t* node = NULL; 1919 1920 node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t)); 1921 if (NULL != node) { 1922 memset(node, 0, sizeof(mm_camera_cmdcb_t)); 1923 node->u.notify_mode = notify_mode; 1924 node->cmd_type = MM_CAMERA_CMD_TYPE_CONFIG_NOTIFY; 1925 1926 /* enqueue to cmd thread */ 1927 cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node); 1928 1929 /* wake up cmd thread */ 1930 cam_sem_post(&(my_obj->cmd_thread.cmd_sem)); 1931 } else { 1932 LOGE("No memory for mm_camera_node_t"); 1933 rc = -1; 1934 } 1935 1936 return rc; 1937 } 1938 1939 /*=========================================================================== 1940 * FUNCTION : mm_channel_start_zsl_snapshot 1941 * 1942 * DESCRIPTION: start zsl snapshot 1943 * 1944 * PARAMETERS : 1945 * @my_obj : channel object 1946 * 1947 * RETURN : int32_t type of status 1948 * 0 -- success 1949 * -1 -- failure 1950 *==========================================================================*/ 1951 int32_t mm_channel_start_zsl_snapshot(mm_channel_t *my_obj) 1952 { 1953 int32_t rc = 0; 1954 mm_camera_cmdcb_t* node = NULL; 1955 1956 node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t)); 1957 if (NULL != node) { 1958 memset(node, 0, sizeof(mm_camera_cmdcb_t)); 1959 node->cmd_type = MM_CAMERA_CMD_TYPE_START_ZSL; 1960 1961 /* enqueue to cmd thread */ 1962 cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node); 1963 1964 /* wake up cmd thread */ 1965 cam_sem_post(&(my_obj->cmd_thread.cmd_sem)); 1966 } else { 1967 LOGE("No memory for mm_camera_node_t"); 1968 rc = -1; 1969 } 1970 1971 return rc; 1972 } 1973 1974 /*=========================================================================== 1975 * FUNCTION : mm_channel_stop_zsl_snapshot 1976 * 1977 * DESCRIPTION: stop zsl snapshot 1978 * 1979 * PARAMETERS : 1980 * @my_obj : channel object 1981 * 1982 * RETURN : int32_t type of status 1983 * 0 -- success 1984 * -1 -- failure 1985 *==========================================================================*/ 1986 int32_t mm_channel_stop_zsl_snapshot(mm_channel_t *my_obj) 1987 { 1988 int32_t rc = 0; 1989 mm_camera_cmdcb_t* node = NULL; 1990 1991 node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t)); 1992 if (NULL != node) { 1993 memset(node, 0, sizeof(mm_camera_cmdcb_t)); 1994 node->cmd_type = MM_CAMERA_CMD_TYPE_STOP_ZSL; 1995 1996 /* enqueue to cmd thread */ 1997 cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node); 1998 1999 /* wake up cmd thread */ 2000 cam_sem_post(&(my_obj->cmd_thread.cmd_sem)); 2001 } else { 2002 LOGE("No memory for mm_camera_node_t"); 2003 rc = -1; 2004 } 2005 2006 return rc; 2007 } 2008 2009 /*=========================================================================== 2010 * FUNCTION : mm_channel_qbuf 2011 * 2012 * DESCRIPTION: enqueue buffer back to kernel 2013 * 2014 * PARAMETERS : 2015 * @my_obj : channel object 2016 * @buf : buf ptr to be enqueued 2017 * 2018 * RETURN : int32_t type of status 2019 * 0 -- success 2020 * -1 -- failure 2021 *==========================================================================*/ 2022 int32_t mm_channel_qbuf(mm_channel_t *my_obj, 2023 mm_camera_buf_def_t *buf) 2024 { 2025 int32_t rc = -1; 2026 mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj, buf->stream_id); 2027 2028 if (NULL != s_obj) { 2029 if (s_obj->ch_obj != my_obj) { 2030 /* Redirect to linked stream */ 2031 rc = mm_stream_fsm_fn(s_obj->linked_stream, 2032 MM_STREAM_EVT_QBUF, 2033 (void *)buf, 2034 NULL); 2035 } else { 2036 rc = mm_stream_fsm_fn(s_obj, 2037 MM_STREAM_EVT_QBUF, 2038 (void *)buf, 2039 NULL); 2040 } 2041 } 2042 2043 return rc; 2044 } 2045 2046 /*=========================================================================== 2047 * FUNCTION : mm_channel_cancel_buf 2048 * 2049 * DESCRIPTION: Get back buffer already sent to kernel 2050 * 2051 * PARAMETERS : 2052 * @my_obj : channel object 2053 * @buf : buf ptr to be enqueued 2054 * 2055 * RETURN : int32_t type of status 2056 * 0 -- success 2057 * -1 -- failure 2058 *==========================================================================*/ 2059 int32_t mm_channel_cancel_buf(mm_channel_t *my_obj, 2060 uint32_t stream_id, uint32_t buf_idx) 2061 { 2062 int32_t rc = -1; 2063 mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj, stream_id); 2064 2065 if (NULL != s_obj) { 2066 if (s_obj->ch_obj != my_obj) { 2067 /* Redirect to linked stream */ 2068 rc = mm_stream_fsm_fn(s_obj->linked_stream, 2069 MM_STREAM_EVT_CANCEL_BUF, 2070 (void *)&buf_idx, 2071 NULL); 2072 } else { 2073 rc = mm_stream_fsm_fn(s_obj, 2074 MM_STREAM_EVT_CANCEL_BUF, 2075 (void *)&buf_idx, 2076 NULL); 2077 } 2078 } 2079 2080 return rc; 2081 } 2082 2083 2084 /*=========================================================================== 2085 * FUNCTION : mm_channel_get_queued_buf_count 2086 * 2087 * DESCRIPTION: return queued buffer count 2088 * 2089 * PARAMETERS : 2090 * @my_obj : channel object 2091 * @stream_id : steam_id 2092 * 2093 * RETURN : queued buffer count 2094 *==========================================================================*/ 2095 int32_t mm_channel_get_queued_buf_count(mm_channel_t *my_obj, uint32_t stream_id) 2096 { 2097 int32_t rc = -1; 2098 mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj, stream_id); 2099 2100 if (NULL != s_obj) { 2101 if (s_obj->ch_obj != my_obj) { 2102 /* Redirect to linked stream */ 2103 rc = mm_stream_fsm_fn(s_obj->linked_stream, 2104 MM_STREAM_EVT_GET_QUEUED_BUF_COUNT, 2105 NULL, 2106 NULL); 2107 } else { 2108 rc = mm_stream_fsm_fn(s_obj, 2109 MM_STREAM_EVT_GET_QUEUED_BUF_COUNT, 2110 NULL, 2111 NULL); 2112 } 2113 } 2114 2115 return rc; 2116 } 2117 2118 /*=========================================================================== 2119 * FUNCTION : mm_channel_set_stream_parms 2120 * 2121 * DESCRIPTION: set parameters per stream 2122 * 2123 * PARAMETERS : 2124 * @my_obj : channel object 2125 * @s_id : stream handle 2126 * @parms : ptr to a param struct to be set to server 2127 * 2128 * RETURN : int32_t type of status 2129 * 0 -- success 2130 * -1 -- failure 2131 * NOTE : Assume the parms struct buf is already mapped to server via 2132 * domain socket. Corresponding fields of parameters to be set 2133 * are already filled in by upper layer caller. 2134 *==========================================================================*/ 2135 int32_t mm_channel_set_stream_parm(mm_channel_t *my_obj, 2136 mm_evt_paylod_set_get_stream_parms_t *payload) 2137 { 2138 int32_t rc = -1; 2139 mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj, 2140 payload->stream_id); 2141 if (NULL != s_obj) { 2142 if (s_obj->ch_obj != my_obj) { 2143 /* No op. on linked streams */ 2144 return 0; 2145 } 2146 2147 rc = mm_stream_fsm_fn(s_obj, 2148 MM_STREAM_EVT_SET_PARM, 2149 (void *)payload, 2150 NULL); 2151 } 2152 2153 return rc; 2154 } 2155 2156 /*=========================================================================== 2157 * FUNCTION : mm_channel_get_stream_parms 2158 * 2159 * DESCRIPTION: get parameters per stream 2160 * 2161 * PARAMETERS : 2162 * @my_obj : channel object 2163 * @s_id : stream handle 2164 * @parms : ptr to a param struct to be get from server 2165 * 2166 * RETURN : int32_t type of status 2167 * 0 -- success 2168 * -1 -- failure 2169 * NOTE : Assume the parms struct buf is already mapped to server via 2170 * domain socket. Parameters to be get from server are already 2171 * filled in by upper layer caller. After this call, corresponding 2172 * fields of requested parameters will be filled in by server with 2173 * detailed information. 2174 *==========================================================================*/ 2175 int32_t mm_channel_get_stream_parm(mm_channel_t *my_obj, 2176 mm_evt_paylod_set_get_stream_parms_t *payload) 2177 { 2178 int32_t rc = -1; 2179 mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj, 2180 payload->stream_id); 2181 if (NULL != s_obj) { 2182 if (s_obj->ch_obj != my_obj) { 2183 /* No op. on linked streams */ 2184 return 0; 2185 } 2186 2187 rc = mm_stream_fsm_fn(s_obj, 2188 MM_STREAM_EVT_GET_PARM, 2189 (void *)payload, 2190 NULL); 2191 } 2192 2193 return rc; 2194 } 2195 2196 /*=========================================================================== 2197 * FUNCTION : mm_channel_do_stream_action 2198 * 2199 * DESCRIPTION: request server to perform stream based action. Maybe removed later 2200 * if the functionality is included in mm_camera_set_parms 2201 * 2202 * PARAMETERS : 2203 * @my_obj : channel object 2204 * @s_id : stream handle 2205 * @actions : ptr to an action struct buf to be performed by server 2206 * 2207 * RETURN : int32_t type of status 2208 * 0 -- success 2209 * -1 -- failure 2210 * NOTE : Assume the action struct buf is already mapped to server via 2211 * domain socket. Actions to be performed by server are already 2212 * filled in by upper layer caller. 2213 *==========================================================================*/ 2214 int32_t mm_channel_do_stream_action(mm_channel_t *my_obj, 2215 mm_evt_paylod_do_stream_action_t *payload) 2216 { 2217 int32_t rc = -1; 2218 mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj, 2219 payload->stream_id); 2220 if (NULL != s_obj) { 2221 if (s_obj->ch_obj != my_obj) { 2222 /* No op. on linked streams */ 2223 return 0; 2224 } 2225 2226 rc = mm_stream_fsm_fn(s_obj, 2227 MM_STREAM_EVT_DO_ACTION, 2228 (void *)payload, 2229 NULL); 2230 } 2231 2232 return rc; 2233 } 2234 2235 /*=========================================================================== 2236 * FUNCTION : mm_channel_map_stream_buf 2237 * 2238 * DESCRIPTION: mapping stream buffer via domain socket to server 2239 * 2240 * PARAMETERS : 2241 * @my_obj : channel object 2242 * @payload : ptr to payload for mapping 2243 * 2244 * RETURN : int32_t type of status 2245 * 0 -- success 2246 * -1 -- failure 2247 *==========================================================================*/ 2248 int32_t mm_channel_map_stream_buf(mm_channel_t *my_obj, 2249 cam_buf_map_type *payload) 2250 { 2251 int32_t rc = -1; 2252 mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj, 2253 payload->stream_id); 2254 if (NULL != s_obj) { 2255 if (s_obj->ch_obj != my_obj) { 2256 /* No op. on linked streams */ 2257 return 0; 2258 } 2259 rc = mm_stream_map_buf(s_obj, 2260 payload->type, payload->frame_idx, 2261 payload->plane_idx, payload->fd, 2262 payload->size, payload->buffer); 2263 } 2264 2265 return rc; 2266 } 2267 2268 /*=========================================================================== 2269 * FUNCTION : mm_channel_map_stream_bufs 2270 * 2271 * DESCRIPTION: mapping stream buffers via domain socket to server 2272 * 2273 * PARAMETERS : 2274 * @my_obj : channel object 2275 * @payload : ptr to payload for mapping 2276 * 2277 * RETURN : int32_t type of status 2278 * 0 -- success 2279 * -1 -- failure 2280 *==========================================================================*/ 2281 int32_t mm_channel_map_stream_bufs(mm_channel_t *my_obj, 2282 cam_buf_map_type_list *payload) 2283 { 2284 int32_t rc = -1; 2285 if ((payload == NULL) || (payload->length == 0)) { 2286 return rc; 2287 } 2288 2289 mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj, 2290 payload->buf_maps[0].stream_id); 2291 if (NULL != s_obj) { 2292 if (s_obj->ch_obj != my_obj) { 2293 /* No op. on linked streams */ 2294 return 0; 2295 } 2296 2297 rc = mm_stream_map_bufs(s_obj, payload); 2298 } 2299 2300 return rc; 2301 } 2302 2303 /*=========================================================================== 2304 * FUNCTION : mm_channel_unmap_stream_buf 2305 * 2306 * DESCRIPTION: unmapping stream buffer via domain socket to server 2307 * 2308 * PARAMETERS : 2309 * @my_obj : channel object 2310 * @payload : ptr to unmap payload 2311 * 2312 * RETURN : int32_t type of status 2313 * 0 -- success 2314 * -1 -- failure 2315 *==========================================================================*/ 2316 int32_t mm_channel_unmap_stream_buf(mm_channel_t *my_obj, 2317 cam_buf_unmap_type *payload) 2318 { 2319 int32_t rc = -1; 2320 mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj, 2321 payload->stream_id); 2322 if (NULL != s_obj) { 2323 if (s_obj->ch_obj != my_obj) { 2324 /* No op. on linked streams */ 2325 return 0; 2326 } 2327 2328 rc = mm_stream_unmap_buf(s_obj, payload->type, 2329 payload->frame_idx, payload->plane_idx); 2330 } 2331 2332 return rc; 2333 } 2334 2335 /*=========================================================================== 2336 * FUNCTION : mm_channel_superbuf_queue_init 2337 * 2338 * DESCRIPTION: initialize superbuf queue in the channel 2339 * 2340 * PARAMETERS : 2341 * @queue : ptr to superbuf queue to be initialized 2342 * 2343 * RETURN : int32_t type of status 2344 * 0 -- success 2345 * -1 -- failure 2346 *==========================================================================*/ 2347 int32_t mm_channel_superbuf_queue_init(mm_channel_queue_t * queue) 2348 { 2349 return cam_queue_init(&queue->que); 2350 } 2351 2352 /*=========================================================================== 2353 * FUNCTION : mm_channel_superbuf_queue_deinit 2354 * 2355 * DESCRIPTION: deinitialize superbuf queue in the channel 2356 * 2357 * PARAMETERS : 2358 * @queue : ptr to superbuf queue to be deinitialized 2359 * 2360 * RETURN : int32_t type of status 2361 * 0 -- success 2362 * -1 -- failure 2363 *==========================================================================*/ 2364 int32_t mm_channel_superbuf_queue_deinit(mm_channel_queue_t * queue) 2365 { 2366 return cam_queue_deinit(&queue->que); 2367 } 2368 2369 /*=========================================================================== 2370 * FUNCTION : mm_channel_util_seq_comp_w_rollover 2371 * 2372 * DESCRIPTION: utility function to handle sequence number comparison with rollover 2373 * 2374 * PARAMETERS : 2375 * @v1 : first value to be compared 2376 * @v2 : second value to be compared 2377 * 2378 * RETURN : int8_t type of comparison result 2379 * >0 -- v1 larger than v2 2380 * =0 -- vi equal to v2 2381 * <0 -- v1 smaller than v2 2382 *==========================================================================*/ 2383 int8_t mm_channel_util_seq_comp_w_rollover(uint32_t v1, 2384 uint32_t v2) 2385 { 2386 int8_t ret = 0; 2387 2388 /* TODO: need to handle the case if v2 roll over to 0 */ 2389 if (v1 > v2) { 2390 ret = 1; 2391 } else if (v1 < v2) { 2392 ret = -1; 2393 } 2394 2395 return ret; 2396 } 2397 2398 /*=========================================================================== 2399 * FUNCTION : mm_channel_validate_super_buf. 2400 * 2401 * DESCRIPTION: Validate incoming buffer with existing super buffer. 2402 * 2403 * PARAMETERS : 2404 * @ch_obj : channel object 2405 * @queue : superbuf queue 2406 * @buf_info: new buffer from stream 2407 * 2408 * RETURN : int8_t type of validation result 2409 * >0 -- Valid frame 2410 * =0 -- Cannot validate 2411 * <0 -- Invalid frame. Can be freed 2412 *==========================================================================*/ 2413 int8_t mm_channel_validate_super_buf(__unused mm_channel_t* ch_obj, 2414 mm_channel_queue_t *queue, mm_camera_buf_info_t *buf_info) 2415 { 2416 int8_t ret = 0; 2417 cam_node_t* node = NULL; 2418 struct cam_list *head = NULL; 2419 struct cam_list *pos = NULL; 2420 mm_channel_queue_node_t* super_buf = NULL; 2421 2422 (void)ch_obj; 2423 2424 /* comp */ 2425 pthread_mutex_lock(&queue->que.lock); 2426 head = &queue->que.head.list; 2427 /* get the last one in the queue which is possibly having no matching */ 2428 pos = head->next; 2429 while (pos != head) { 2430 node = member_of(pos, cam_node_t, list); 2431 super_buf = (mm_channel_queue_node_t*)node->data; 2432 if (NULL != super_buf) { 2433 if ((super_buf->expected_frame) && 2434 (buf_info->frame_idx == super_buf->frame_idx)) { 2435 //This is good frame. Expecting more frames. Keeping this frame. 2436 ret = 1; 2437 break; 2438 } else { 2439 pos = pos->next; 2440 continue; 2441 } 2442 } 2443 } 2444 pthread_mutex_unlock(&queue->que.lock); 2445 return ret; 2446 } 2447 2448 /*=========================================================================== 2449 * FUNCTION : mm_channel_handle_metadata 2450 * 2451 * DESCRIPTION: Handle frame matching logic change due to metadata 2452 * 2453 * PARAMETERS : 2454 * @ch_obj : channel object 2455 * @queue : superbuf queue 2456 * @buf_info: new buffer from stream 2457 * 2458 * RETURN : int32_t type of status 2459 * 0 -- success 2460 * -1 -- failure 2461 *==========================================================================*/ 2462 int32_t mm_channel_handle_metadata( 2463 mm_channel_t* ch_obj, 2464 mm_channel_queue_t * queue, 2465 mm_camera_buf_info_t *buf_info) 2466 { 2467 2468 int rc = 0 ; 2469 mm_stream_t* stream_obj = NULL; 2470 stream_obj = mm_channel_util_get_stream_by_handler(ch_obj, 2471 buf_info->stream_id); 2472 uint8_t is_prep_snapshot_done_valid = 0; 2473 uint8_t is_good_frame_idx_range_valid = 0; 2474 int32_t prep_snapshot_done_state = 0; 2475 cam_frame_idx_range_t good_frame_idx_range; 2476 uint8_t is_crop_1x_found = 0; 2477 uint32_t snapshot_stream_id = 0; 2478 uint32_t i; 2479 /* Set expected frame id to a future frame idx, large enough to wait 2480 * for good_frame_idx_range, and small enough to still capture an image */ 2481 const uint32_t max_future_frame_offset = MM_CAMERA_MAX_FUTURE_FRAME_WAIT; 2482 2483 memset(&good_frame_idx_range, 0, sizeof(good_frame_idx_range)); 2484 2485 if (NULL == stream_obj) { 2486 LOGE("Invalid Stream Object for stream_id = %d", 2487 buf_info->stream_id); 2488 rc = -1; 2489 goto end; 2490 } 2491 if (NULL == stream_obj->stream_info) { 2492 LOGE("NULL stream info for stream_id = %d", 2493 buf_info->stream_id); 2494 rc = -1; 2495 goto end; 2496 } 2497 2498 if ((CAM_STREAM_TYPE_METADATA == stream_obj->stream_info->stream_type) && 2499 ((stream_obj->ch_obj == ch_obj) || 2500 ((stream_obj->linked_stream != NULL) && 2501 (stream_obj->linked_stream->linked_obj == ch_obj)))) { 2502 const metadata_buffer_t *metadata; 2503 metadata = (const metadata_buffer_t *)buf_info->buf->buffer; 2504 2505 if (NULL == metadata) { 2506 LOGE("NULL metadata buffer for metadata stream"); 2507 rc = -1; 2508 goto end; 2509 } 2510 LOGL("E , expected frame id: %d", queue->expected_frame_id); 2511 2512 IF_META_AVAILABLE(const int32_t, p_prep_snapshot_done_state, 2513 CAM_INTF_META_PREP_SNAPSHOT_DONE, metadata) { 2514 prep_snapshot_done_state = *p_prep_snapshot_done_state; 2515 is_prep_snapshot_done_valid = 1; 2516 LOGH("prepare snapshot done valid "); 2517 } 2518 IF_META_AVAILABLE(const cam_frame_idx_range_t, p_good_frame_idx_range, 2519 CAM_INTF_META_GOOD_FRAME_IDX_RANGE, metadata) { 2520 good_frame_idx_range = *p_good_frame_idx_range; 2521 is_good_frame_idx_range_valid = 1; 2522 LOGH("good_frame_idx_range : min: %d, max: %d , num frames = %d", 2523 good_frame_idx_range.min_frame_idx, 2524 good_frame_idx_range.max_frame_idx, good_frame_idx_range.num_led_on_frames); 2525 } 2526 IF_META_AVAILABLE(const cam_crop_data_t, p_crop_data, 2527 CAM_INTF_META_CROP_DATA, metadata) { 2528 cam_crop_data_t crop_data = *p_crop_data; 2529 2530 for (i = 0; i < ARRAY_SIZE(ch_obj->streams); i++) { 2531 if (MM_STREAM_STATE_NOTUSED == ch_obj->streams[i].state) { 2532 continue; 2533 } 2534 if (CAM_STREAM_TYPE_SNAPSHOT == 2535 ch_obj->streams[i].stream_info->stream_type) { 2536 snapshot_stream_id = ch_obj->streams[i].server_stream_id; 2537 break; 2538 } 2539 } 2540 2541 for (i=0; i<crop_data.num_of_streams; i++) { 2542 if (snapshot_stream_id == crop_data.crop_info[i].stream_id) { 2543 if (!crop_data.crop_info[i].crop.left && 2544 !crop_data.crop_info[i].crop.top) { 2545 is_crop_1x_found = 1; 2546 break; 2547 } 2548 } 2549 } 2550 } 2551 2552 IF_META_AVAILABLE(const cam_buf_divert_info_t, p_divert_info, 2553 CAM_INTF_BUF_DIVERT_INFO, metadata) { 2554 cam_buf_divert_info_t divert_info = *p_divert_info; 2555 if (divert_info.frame_id >= buf_info->frame_idx) { 2556 ch_obj->diverted_frame_id = divert_info.frame_id; 2557 } else { 2558 ch_obj->diverted_frame_id = 0; 2559 } 2560 } 2561 2562 if (ch_obj->isZoom1xFrameRequested) { 2563 if (is_crop_1x_found) { 2564 ch_obj->isZoom1xFrameRequested = 0; 2565 queue->expected_frame_id = buf_info->frame_idx + 1; 2566 } else { 2567 queue->expected_frame_id += max_future_frame_offset; 2568 /* Flush unwanted frames */ 2569 mm_channel_superbuf_flush_matched(ch_obj, queue); 2570 } 2571 goto end; 2572 } 2573 2574 if (ch_obj->startZSlSnapshotCalled && is_good_frame_idx_range_valid) { 2575 LOGI("frameID = %d, expected = %d good_frame_idx = %d", 2576 buf_info->frame_idx, queue->expected_frame_id, 2577 good_frame_idx_range.min_frame_idx); 2578 } 2579 2580 if (is_prep_snapshot_done_valid) { 2581 ch_obj->bWaitForPrepSnapshotDone = 0; 2582 if (prep_snapshot_done_state == NEED_FUTURE_FRAME) { 2583 queue->expected_frame_id += max_future_frame_offset; 2584 LOGI("PreFlash Done. Need Main Flash"); 2585 2586 mm_channel_superbuf_flush(ch_obj, 2587 queue, CAM_STREAM_TYPE_DEFAULT); 2588 2589 ch_obj->needLEDFlash = TRUE; 2590 } else { 2591 ch_obj->needLEDFlash = FALSE; 2592 } 2593 } 2594 if (is_good_frame_idx_range_valid) { 2595 queue->expected_frame_id = 2596 good_frame_idx_range.min_frame_idx; 2597 queue->good_frame_id = good_frame_idx_range.min_frame_idx; 2598 if((ch_obj->needLEDFlash == TRUE) && (ch_obj->burstSnapNum > 1)) { 2599 queue->led_on_start_frame_id = 2600 good_frame_idx_range.min_frame_idx; 2601 queue->led_off_start_frame_id = 2602 good_frame_idx_range.max_frame_idx; 2603 queue->once = 0; 2604 queue->led_on_num_frames = 2605 good_frame_idx_range.num_led_on_frames; 2606 queue->frame_skip_count = good_frame_idx_range.frame_skip_count; 2607 LOGD("Need Flash, expected frame id = %d," 2608 " led_on start = %d, led off start = %d, led on frames = %d ", 2609 queue->expected_frame_id, queue->led_on_start_frame_id, 2610 queue->led_off_start_frame_id, queue->led_on_num_frames); 2611 } else { 2612 LOGD("No flash, expected frame id = %d ", 2613 queue->expected_frame_id); 2614 } 2615 } else if ((MM_CHANNEL_BRACKETING_STATE_WAIT_GOOD_FRAME_IDX == ch_obj->bracketingState) && 2616 !is_prep_snapshot_done_valid) { 2617 /* Flush unwanted frames */ 2618 mm_channel_superbuf_flush_matched(ch_obj, queue); 2619 queue->expected_frame_id += max_future_frame_offset; 2620 } 2621 if (ch_obj->isFlashBracketingEnabled && 2622 is_good_frame_idx_range_valid) { 2623 /* Flash bracketing needs two frames, with & without led flash. 2624 * in valid range min frame is with led flash and max frame is 2625 * without led flash */ 2626 queue->expected_frame_id = 2627 good_frame_idx_range.min_frame_idx; 2628 /* max frame is without led flash */ 2629 queue->expected_frame_id_without_led = 2630 good_frame_idx_range.max_frame_idx; 2631 queue->good_frame_id = 2632 good_frame_idx_range.min_frame_idx; 2633 } else if (is_good_frame_idx_range_valid) { 2634 queue->expected_frame_id = 2635 good_frame_idx_range.min_frame_idx; 2636 ch_obj->bracketingState = MM_CHANNEL_BRACKETING_STATE_ACTIVE; 2637 queue->good_frame_id = 2638 good_frame_idx_range.min_frame_idx; 2639 } 2640 2641 if (ch_obj->isConfigCapture && is_good_frame_idx_range_valid 2642 && (good_frame_idx_range.config_batch_idx < ch_obj->frameConfig.num_batch)) { 2643 2644 LOGI("Frame Config: Expcted ID = %d batch index = %d", 2645 good_frame_idx_range.min_frame_idx, good_frame_idx_range.config_batch_idx); 2646 ch_obj->capture_frame_id[good_frame_idx_range.config_batch_idx] = 2647 good_frame_idx_range.min_frame_idx; 2648 2649 if (ch_obj->cur_capture_idx == good_frame_idx_range.config_batch_idx) { 2650 queue->expected_frame_id = 2651 good_frame_idx_range.min_frame_idx; 2652 } else { 2653 queue->expected_frame_id = 2654 ch_obj->capture_frame_id[ch_obj->cur_capture_idx]; 2655 } 2656 queue->good_frame_id = queue->expected_frame_id; 2657 } 2658 2659 if ((ch_obj->burstSnapNum > 1) && (ch_obj->needLEDFlash == TRUE) 2660 && !ch_obj->isFlashBracketingEnabled 2661 && (MM_CHANNEL_BRACKETING_STATE_OFF == ch_obj->bracketingState) 2662 && !ch_obj->isConfigCapture) { 2663 if((buf_info->frame_idx >= queue->led_off_start_frame_id) 2664 && !queue->once) { 2665 LOGD("Burst snap num = %d ", 2666 ch_obj->burstSnapNum); 2667 // Skip frames from LED OFF frame to get a good frame 2668 queue->expected_frame_id = queue->led_off_start_frame_id + 2669 queue->frame_skip_count; 2670 queue->once = 1; 2671 ch_obj->stopZslSnapshot = 1; 2672 ch_obj->needLEDFlash = FALSE; 2673 LOGD("Reached max led on frames = %d , expected id = %d", 2674 buf_info->frame_idx, queue->expected_frame_id); 2675 } 2676 } 2677 2678 IF_META_AVAILABLE(const cam_low_light_mode_t, low_light_level, 2679 CAM_INTF_META_LOW_LIGHT, metadata) { 2680 ch_obj->needLowLightZSL = *low_light_level; 2681 } 2682 2683 // For the instant capture case, if AEC settles before expected frame ID from user, 2684 // reset the expected frame ID to current frame index. 2685 if (queue->attr.user_expected_frame_id > 0) { 2686 if (queue->attr.user_expected_frame_id > buf_info->frame_idx) { 2687 IF_META_AVAILABLE(const cam_3a_params_t, ae_params, 2688 CAM_INTF_META_AEC_INFO, metadata) { 2689 if (ae_params->settled) { 2690 queue->expected_frame_id = buf_info->frame_idx; 2691 // Reset the expected frame ID from HAL to 0 2692 queue->attr.user_expected_frame_id = 0; 2693 LOGD("AEC settled, reset expected frame ID from user"); 2694 } 2695 } 2696 } else { 2697 // Reset the expected frame ID from HAL to 0 after 2698 // current frame index is greater than expected id. 2699 queue->attr.user_expected_frame_id = 0; 2700 LOGD("reset expected frame ID from user as it reached the bound"); 2701 } 2702 } 2703 } 2704 end: 2705 return rc; 2706 } 2707 2708 /*=========================================================================== 2709 * FUNCTION : mm_channel_superbuf_comp_and_enqueue 2710 * 2711 * DESCRIPTION: implementation for matching logic for superbuf 2712 * 2713 * PARAMETERS : 2714 * @ch_obj : channel object 2715 * @queue : superbuf queue 2716 * @buf_info: new buffer from stream 2717 * 2718 * RETURN : int32_t type of status 2719 * 0 -- success 2720 * -1 -- failure 2721 *==========================================================================*/ 2722 int32_t mm_channel_superbuf_comp_and_enqueue( 2723 mm_channel_t* ch_obj, 2724 mm_channel_queue_t *queue, 2725 mm_camera_buf_info_t *buf_info) 2726 { 2727 cam_node_t* node = NULL; 2728 struct cam_list *head = NULL; 2729 struct cam_list *pos = NULL; 2730 mm_channel_queue_node_t* super_buf = NULL; 2731 uint8_t buf_s_idx, i, found_super_buf, unmatched_bundles; 2732 struct cam_list *last_buf, *insert_before_buf, *last_buf_ptr; 2733 2734 LOGD("E"); 2735 2736 for (buf_s_idx = 0; buf_s_idx < queue->num_streams; buf_s_idx++) { 2737 if (buf_info->stream_id == queue->bundled_streams[buf_s_idx]) { 2738 break; 2739 } 2740 } 2741 2742 if (buf_s_idx == queue->num_streams) { 2743 LOGE("buf from stream (%d) not bundled", buf_info->stream_id); 2744 return -1; 2745 } 2746 2747 if(buf_info->frame_idx == 0) { 2748 mm_channel_qbuf(ch_obj, buf_info->buf); 2749 return 0; 2750 } 2751 2752 if (mm_channel_handle_metadata(ch_obj, queue, buf_info) < 0) { 2753 mm_channel_qbuf(ch_obj, buf_info->buf); 2754 return -1; 2755 } 2756 2757 if ((mm_channel_util_seq_comp_w_rollover(buf_info->frame_idx, 2758 queue->expected_frame_id) < 0) && 2759 (mm_channel_validate_super_buf(ch_obj, queue, buf_info) <= 0)) { 2760 LOGH("incoming buf id(%d) is older than expected buf id(%d), will discard it", 2761 buf_info->frame_idx, queue->expected_frame_id); 2762 mm_channel_qbuf(ch_obj, buf_info->buf); 2763 return 0; 2764 } 2765 2766 /* comp */ 2767 pthread_mutex_lock(&queue->que.lock); 2768 head = &queue->que.head.list; 2769 /* get the last one in the queue which is possibly having no matching */ 2770 pos = head->next; 2771 2772 found_super_buf = 0; 2773 unmatched_bundles = 0; 2774 last_buf = NULL; 2775 insert_before_buf = NULL; 2776 last_buf_ptr = NULL; 2777 2778 while (pos != head) { 2779 node = member_of(pos, cam_node_t, list); 2780 super_buf = (mm_channel_queue_node_t*)node->data; 2781 2782 if (NULL != super_buf) { 2783 if (super_buf->matched) { 2784 /* find a matched super buf, move to next one */ 2785 pos = pos->next; 2786 continue; 2787 } else if (( buf_info->frame_idx == super_buf->frame_idx ) 2788 /*Pick metadata greater than available frameID*/ 2789 || ((queue->attr.priority == MM_CAMERA_SUPER_BUF_PRIORITY_LOW) 2790 && (super_buf->super_buf[buf_s_idx].frame_idx == 0) 2791 && (buf_info->buf->stream_type == CAM_STREAM_TYPE_METADATA) 2792 && (super_buf->frame_idx < buf_info->frame_idx)) 2793 /*Pick available metadata closest to frameID*/ 2794 || ((queue->attr.priority == MM_CAMERA_SUPER_BUF_PRIORITY_LOW) 2795 && (buf_info->buf->stream_type != CAM_STREAM_TYPE_METADATA) 2796 && (super_buf->super_buf[buf_s_idx].frame_idx == 0) 2797 && (super_buf->unmatched_meta_idx > buf_info->frame_idx))){ 2798 /*super buffer frame IDs matching OR In low priority bundling 2799 metadata frameID greater than avialbale super buffer frameID OR 2800 metadata frame closest to incoming frameID will be bundled*/ 2801 found_super_buf = 1; 2802 /* If we are filling into a 'meta only' superbuf, make sure to reset 2803 the super_buf frame_idx so that missing streams in this superbuf 2804 are filled as per matching frame id logic. Note that, in low priority 2805 queue, only meta frame id need not match (closest suffices) but 2806 the other streams in this superbuf should have same frame id. */ 2807 if (super_buf->unmatched_meta_idx > 0) { 2808 super_buf->unmatched_meta_idx = 0; 2809 super_buf->frame_idx = buf_info->frame_idx; 2810 } 2811 break; 2812 } else { 2813 unmatched_bundles++; 2814 if ( NULL == last_buf ) { 2815 if ( super_buf->frame_idx < buf_info->frame_idx ) { 2816 last_buf = pos; 2817 } 2818 } 2819 if ( NULL == insert_before_buf ) { 2820 if ( super_buf->frame_idx > buf_info->frame_idx ) { 2821 insert_before_buf = pos; 2822 } 2823 } 2824 pos = pos->next; 2825 } 2826 } 2827 } 2828 2829 if ( found_super_buf ) { 2830 if(super_buf->super_buf[buf_s_idx].frame_idx != 0) { 2831 //This can cause frame drop. We are overwriting same memory. 2832 pthread_mutex_unlock(&queue->que.lock); 2833 LOGW("Warning: frame is already in camera ZSL queue"); 2834 mm_channel_qbuf(ch_obj, buf_info->buf); 2835 return 0; 2836 } 2837 2838 /*Insert incoming buffer to super buffer*/ 2839 super_buf->super_buf[buf_s_idx] = *buf_info; 2840 2841 /* check if superbuf is all matched */ 2842 super_buf->matched = 1; 2843 for (i=0; i < super_buf->num_of_bufs; i++) { 2844 if (super_buf->super_buf[i].frame_idx == 0) { 2845 super_buf->matched = 0; 2846 break; 2847 } 2848 } 2849 2850 if (super_buf->matched) { 2851 if(ch_obj->isFlashBracketingEnabled) { 2852 queue->expected_frame_id = 2853 queue->expected_frame_id_without_led; 2854 if (buf_info->frame_idx >= 2855 queue->expected_frame_id_without_led) { 2856 ch_obj->isFlashBracketingEnabled = FALSE; 2857 } 2858 } else { 2859 queue->expected_frame_id = buf_info->frame_idx 2860 + queue->attr.post_frame_skip; 2861 } 2862 2863 super_buf->expected_frame = FALSE; 2864 2865 LOGD("curr = %d, skip = %d , Expected Frame ID: %d", 2866 buf_info->frame_idx, 2867 queue->attr.post_frame_skip, queue->expected_frame_id); 2868 2869 queue->match_cnt++; 2870 if (ch_obj->bundle.superbuf_queue.attr.enable_frame_sync) { 2871 pthread_mutex_lock(&fs_lock); 2872 mm_frame_sync_add(buf_info->frame_idx, ch_obj); 2873 pthread_mutex_unlock(&fs_lock); 2874 } 2875 /* Any older unmatched buffer need to be released */ 2876 if ( last_buf ) { 2877 while ( last_buf != pos ) { 2878 node = member_of(last_buf, cam_node_t, list); 2879 super_buf = (mm_channel_queue_node_t*)node->data; 2880 if (NULL != super_buf) { 2881 for (i=0; i<super_buf->num_of_bufs; i++) { 2882 if (super_buf->super_buf[i].frame_idx != 0) { 2883 mm_channel_qbuf(ch_obj, super_buf->super_buf[i].buf); 2884 } 2885 } 2886 queue->que.size--; 2887 last_buf = last_buf->next; 2888 cam_list_del_node(&node->list); 2889 free(node); 2890 free(super_buf); 2891 } else { 2892 LOGE("Invalid superbuf in queue!"); 2893 break; 2894 } 2895 } 2896 } 2897 }else { 2898 if (ch_obj->diverted_frame_id == buf_info->frame_idx) { 2899 super_buf->expected_frame = TRUE; 2900 ch_obj->diverted_frame_id = 0; 2901 } 2902 } 2903 } else { 2904 if ((queue->attr.max_unmatched_frames < unmatched_bundles) 2905 && ( NULL == last_buf )) { 2906 /* incoming frame is older than the last bundled one */ 2907 mm_channel_qbuf(ch_obj, buf_info->buf); 2908 } else { 2909 last_buf_ptr = last_buf; 2910 2911 /* Loop to remove unmatched frames */ 2912 while ((queue->attr.max_unmatched_frames < unmatched_bundles) 2913 && (last_buf_ptr != NULL && last_buf_ptr != pos)) { 2914 node = member_of(last_buf_ptr, cam_node_t, list); 2915 super_buf = (mm_channel_queue_node_t*)node->data; 2916 if (NULL != super_buf && super_buf->expected_frame == FALSE 2917 && (&node->list != insert_before_buf)) { 2918 for (i=0; i<super_buf->num_of_bufs; i++) { 2919 if (super_buf->super_buf[i].frame_idx != 0) { 2920 mm_channel_qbuf(ch_obj, super_buf->super_buf[i].buf); 2921 } 2922 } 2923 queue->que.size--; 2924 cam_list_del_node(&node->list); 2925 free(node); 2926 free(super_buf); 2927 unmatched_bundles--; 2928 } 2929 last_buf_ptr = last_buf_ptr->next; 2930 } 2931 2932 if (queue->attr.max_unmatched_frames < unmatched_bundles) { 2933 node = member_of(last_buf, cam_node_t, list); 2934 super_buf = (mm_channel_queue_node_t*)node->data; 2935 for (i=0; i<super_buf->num_of_bufs; i++) { 2936 if (super_buf->super_buf[i].frame_idx != 0) { 2937 mm_channel_qbuf(ch_obj, super_buf->super_buf[i].buf); 2938 } 2939 } 2940 queue->que.size--; 2941 cam_list_del_node(&node->list); 2942 free(node); 2943 free(super_buf); 2944 } 2945 2946 /* insert the new frame at the appropriate position. */ 2947 2948 mm_channel_queue_node_t *new_buf = NULL; 2949 cam_node_t* new_node = NULL; 2950 2951 new_buf = (mm_channel_queue_node_t*)malloc(sizeof(mm_channel_queue_node_t)); 2952 new_node = (cam_node_t*)malloc(sizeof(cam_node_t)); 2953 if (NULL != new_buf && NULL != new_node) { 2954 memset(new_buf, 0, sizeof(mm_channel_queue_node_t)); 2955 memset(new_node, 0, sizeof(cam_node_t)); 2956 new_node->data = (void *)new_buf; 2957 new_buf->num_of_bufs = queue->num_streams; 2958 new_buf->super_buf[buf_s_idx] = *buf_info; 2959 new_buf->frame_idx = buf_info->frame_idx; 2960 2961 if ((ch_obj->diverted_frame_id == buf_info->frame_idx) 2962 || (buf_info->frame_idx == queue->good_frame_id)) { 2963 new_buf->expected_frame = TRUE; 2964 ch_obj->diverted_frame_id = 0; 2965 } 2966 2967 /* enqueue */ 2968 if ( insert_before_buf ) { 2969 cam_list_insert_before_node(&new_node->list, insert_before_buf); 2970 } else { 2971 cam_list_add_tail_node(&new_node->list, &queue->que.head.list); 2972 } 2973 queue->que.size++; 2974 2975 if(queue->num_streams == 1) { 2976 new_buf->matched = 1; 2977 new_buf->expected_frame = FALSE; 2978 queue->expected_frame_id = buf_info->frame_idx + queue->attr.post_frame_skip; 2979 queue->match_cnt++; 2980 if (ch_obj->bundle.superbuf_queue.attr.enable_frame_sync) { 2981 pthread_mutex_lock(&fs_lock); 2982 mm_frame_sync_add(buf_info->frame_idx, ch_obj); 2983 pthread_mutex_unlock(&fs_lock); 2984 } 2985 } 2986 /* In low priority queue, this will become a 'meta only' superbuf. Set the 2987 unmatched_frame_idx so that the upcoming stream buffers (other than meta) 2988 can be filled into this which are nearest to this idx. */ 2989 if ((queue->attr.priority == MM_CAMERA_SUPER_BUF_PRIORITY_LOW) 2990 && (buf_info->buf->stream_type == CAM_STREAM_TYPE_METADATA)) { 2991 new_buf->unmatched_meta_idx = buf_info->frame_idx; 2992 } 2993 } else { 2994 /* No memory */ 2995 if (NULL != new_buf) { 2996 free(new_buf); 2997 } 2998 if (NULL != new_node) { 2999 free(new_node); 3000 } 3001 /* qbuf the new buf since we cannot enqueue */ 3002 mm_channel_qbuf(ch_obj, buf_info->buf); 3003 } 3004 } 3005 } 3006 3007 pthread_mutex_unlock(&queue->que.lock); 3008 LOGD("X"); 3009 return 0; 3010 } 3011 3012 /*=========================================================================== 3013 * FUNCTION : mm_channel_superbuf_dequeue_internal 3014 * 3015 * DESCRIPTION: internal implementation for dequeue from the superbuf queue 3016 * 3017 * PARAMETERS : 3018 * @queue : superbuf queue 3019 * @matched_only : if dequeued buf should be matched 3020 * @ch_obj : channel object 3021 * 3022 * RETURN : ptr to a node from superbuf queue 3023 *==========================================================================*/ 3024 mm_channel_queue_node_t* mm_channel_superbuf_dequeue_internal( 3025 mm_channel_queue_t * queue, 3026 uint8_t matched_only, mm_channel_t *ch_obj) 3027 { 3028 cam_node_t* node = NULL; 3029 struct cam_list *head = NULL; 3030 struct cam_list *pos = NULL; 3031 mm_channel_queue_node_t* super_buf = NULL; 3032 3033 head = &queue->que.head.list; 3034 pos = head->next; 3035 if (pos != head) { 3036 /* get the first node */ 3037 node = member_of(pos, cam_node_t, list); 3038 super_buf = (mm_channel_queue_node_t*)node->data; 3039 if ( (NULL != super_buf) && 3040 (matched_only == TRUE) && 3041 (super_buf->matched == FALSE) ) { 3042 /* require to dequeue matched frame only, but this superbuf is not matched, 3043 simply set return ptr to NULL */ 3044 super_buf = NULL; 3045 } 3046 if (NULL != super_buf) { 3047 /* remove from the queue */ 3048 cam_list_del_node(&node->list); 3049 queue->que.size--; 3050 if (super_buf->matched == TRUE) { 3051 queue->match_cnt--; 3052 if (ch_obj->bundle.superbuf_queue.attr.enable_frame_sync) { 3053 pthread_mutex_lock(&fs_lock); 3054 mm_frame_sync_remove(super_buf->frame_idx); 3055 pthread_mutex_unlock(&fs_lock); 3056 } 3057 } 3058 free(node); 3059 } 3060 } 3061 3062 return super_buf; 3063 } 3064 3065 /*=========================================================================== 3066 * FUNCTION : mm_channel_superbuf_dequeue_frame_internal 3067 * 3068 * DESCRIPTION: internal implementation for dequeue based on frame index 3069 * from the superbuf queue 3070 * 3071 * PARAMETERS : 3072 * @queue : superbuf queue 3073 * @frame_idx : frame index to be dequeued 3074 * 3075 * RETURN : ptr to a node from superbuf queue with matched frame index 3076 * : NULL if not found 3077 *==========================================================================*/ 3078 mm_channel_queue_node_t* mm_channel_superbuf_dequeue_frame_internal( 3079 mm_channel_queue_t * queue, uint32_t frame_idx) 3080 { 3081 cam_node_t* node = NULL; 3082 struct cam_list *head = NULL; 3083 struct cam_list *pos = NULL; 3084 mm_channel_queue_node_t* super_buf = NULL; 3085 3086 if (!queue) { 3087 LOGE("queue is NULL"); 3088 return NULL; 3089 } 3090 3091 head = &queue->que.head.list; 3092 pos = head->next; 3093 LOGL("Searching for match frame %d", frame_idx); 3094 while ((pos != head) && (pos != NULL)) { 3095 /* get the first node */ 3096 node = member_of(pos, cam_node_t, list); 3097 super_buf = (mm_channel_queue_node_t*)node->data; 3098 if (super_buf && super_buf->matched && 3099 (super_buf->frame_idx == frame_idx)) { 3100 /* remove from the queue */ 3101 cam_list_del_node(&node->list); 3102 queue->que.size--; 3103 queue->match_cnt--; 3104 LOGH("Found match frame %d", frame_idx); 3105 free(node); 3106 break; 3107 } 3108 else { 3109 LOGH("match frame not found %d", frame_idx); 3110 super_buf = NULL; 3111 } 3112 pos = pos->next; 3113 } 3114 return super_buf; 3115 } 3116 3117 3118 /*=========================================================================== 3119 * FUNCTION : mm_channel_superbuf_dequeue 3120 * 3121 * DESCRIPTION: dequeue from the superbuf queue 3122 * 3123 * PARAMETERS : 3124 * @queue : superbuf queue 3125 * @ch_obj : channel object 3126 * 3127 * RETURN : ptr to a node from superbuf queue 3128 *==========================================================================*/ 3129 mm_channel_queue_node_t* mm_channel_superbuf_dequeue( 3130 mm_channel_queue_t * queue, mm_channel_t *ch_obj) 3131 { 3132 mm_channel_queue_node_t* super_buf = NULL; 3133 3134 pthread_mutex_lock(&queue->que.lock); 3135 super_buf = mm_channel_superbuf_dequeue_internal(queue, TRUE, ch_obj); 3136 pthread_mutex_unlock(&queue->que.lock); 3137 3138 return super_buf; 3139 } 3140 3141 /*=========================================================================== 3142 * FUNCTION : mm_channel_superbuf_bufdone_overflow 3143 * 3144 * DESCRIPTION: keep superbuf queue no larger than watermark set by upper layer 3145 * via channel attribute 3146 * 3147 * PARAMETERS : 3148 * @my_obj : channel object 3149 * @queue : superbuf queue 3150 * 3151 * RETURN : int32_t type of status 3152 * 0 -- success 3153 * -1 -- failure 3154 *==========================================================================*/ 3155 int32_t mm_channel_superbuf_bufdone_overflow(mm_channel_t* my_obj, 3156 mm_channel_queue_t * queue) 3157 { 3158 int32_t rc = 0, i; 3159 mm_channel_queue_node_t* super_buf = NULL; 3160 if (MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS == queue->attr.notify_mode) { 3161 /* for continuous streaming mode, no overflow is needed */ 3162 return 0; 3163 } 3164 3165 LOGD("before match_cnt=%d, water_mark=%d", 3166 queue->match_cnt, queue->attr.water_mark); 3167 /* bufdone overflowed bufs */ 3168 pthread_mutex_lock(&queue->que.lock); 3169 while (queue->match_cnt > queue->attr.water_mark) { 3170 super_buf = mm_channel_superbuf_dequeue_internal(queue, TRUE, my_obj); 3171 if (NULL != super_buf) { 3172 for (i=0; i<super_buf->num_of_bufs; i++) { 3173 if (NULL != super_buf->super_buf[i].buf) { 3174 mm_channel_qbuf(my_obj, super_buf->super_buf[i].buf); 3175 } 3176 } 3177 free(super_buf); 3178 } 3179 } 3180 pthread_mutex_unlock(&queue->que.lock); 3181 LOGD("after match_cnt=%d, water_mark=%d", 3182 queue->match_cnt, queue->attr.water_mark); 3183 3184 return rc; 3185 } 3186 3187 /*=========================================================================== 3188 * FUNCTION : mm_channel_superbuf_skip 3189 * 3190 * DESCRIPTION: depends on the lookback configuration of the channel attribute, 3191 * unwanted superbufs will be removed from the superbuf queue. 3192 * 3193 * PARAMETERS : 3194 * @my_obj : channel object 3195 * @queue : superbuf queue 3196 * 3197 * RETURN : int32_t type of status 3198 * 0 -- success 3199 * -1 -- failure 3200 *==========================================================================*/ 3201 int32_t mm_channel_superbuf_skip(mm_channel_t* my_obj, 3202 mm_channel_queue_t * queue) 3203 { 3204 int32_t rc = 0, i; 3205 mm_channel_queue_node_t* super_buf = NULL; 3206 if (MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS == queue->attr.notify_mode) { 3207 /* for continuous streaming mode, no skip is needed */ 3208 return 0; 3209 } 3210 3211 /* bufdone overflowed bufs */ 3212 pthread_mutex_lock(&queue->que.lock); 3213 while (queue->match_cnt > queue->attr.look_back) { 3214 super_buf = mm_channel_superbuf_dequeue_internal(queue, TRUE, my_obj); 3215 if (NULL != super_buf) { 3216 for (i=0; i<super_buf->num_of_bufs; i++) { 3217 if (NULL != super_buf->super_buf[i].buf) { 3218 mm_channel_qbuf(my_obj, super_buf->super_buf[i].buf); 3219 } 3220 } 3221 free(super_buf); 3222 } 3223 } 3224 pthread_mutex_unlock(&queue->que.lock); 3225 3226 return rc; 3227 } 3228 3229 /*=========================================================================== 3230 * FUNCTION : mm_channel_superbuf_flush 3231 * 3232 * DESCRIPTION: flush the superbuf queue. 3233 * 3234 * PARAMETERS : 3235 * @my_obj : channel object 3236 * @queue : superbuf queue 3237 * @cam_type: flush only particular type (default flushes all) 3238 * 3239 * RETURN : int32_t type of status 3240 * 0 -- success 3241 * -1 -- failure 3242 *==========================================================================*/ 3243 int32_t mm_channel_superbuf_flush(mm_channel_t* my_obj, 3244 mm_channel_queue_t * queue, cam_stream_type_t cam_type) 3245 { 3246 int32_t rc = 0, i; 3247 mm_channel_queue_node_t* super_buf = NULL; 3248 cam_stream_type_t stream_type = CAM_STREAM_TYPE_DEFAULT; 3249 3250 /* bufdone bufs */ 3251 pthread_mutex_lock(&queue->que.lock); 3252 super_buf = mm_channel_superbuf_dequeue_internal(queue, FALSE, my_obj); 3253 while (super_buf != NULL) { 3254 for (i=0; i<super_buf->num_of_bufs; i++) { 3255 if (NULL != super_buf->super_buf[i].buf) { 3256 stream_type = super_buf->super_buf[i].buf->stream_type; 3257 if ((CAM_STREAM_TYPE_DEFAULT == cam_type) || 3258 (cam_type == stream_type)) { 3259 mm_channel_qbuf(my_obj, super_buf->super_buf[i].buf); 3260 } 3261 } 3262 } 3263 free(super_buf); 3264 super_buf = mm_channel_superbuf_dequeue_internal(queue, FALSE, my_obj); 3265 } 3266 pthread_mutex_unlock(&queue->que.lock); 3267 3268 return rc; 3269 } 3270 3271 /*=========================================================================== 3272 * FUNCTION : mm_channel_proc_general_cmd 3273 * 3274 * DESCRIPTION: process general command 3275 * 3276 * PARAMETERS : 3277 * @my_obj : channel object 3278 * @notify_mode : notification mode 3279 * 3280 * RETURN : int32_t type of status 3281 * 0 -- success 3282 * -1 -- failure 3283 *==========================================================================*/ 3284 int32_t mm_channel_proc_general_cmd(mm_channel_t *my_obj, 3285 mm_camera_generic_cmd_t *p_gen_cmd) 3286 { 3287 LOGD("E"); 3288 int32_t rc = 0; 3289 mm_camera_cmdcb_t* node = NULL; 3290 3291 node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t)); 3292 if (NULL != node) { 3293 memset(node, 0, sizeof(mm_camera_cmdcb_t)); 3294 node->u.gen_cmd = *p_gen_cmd; 3295 node->cmd_type = MM_CAMERA_CMD_TYPE_GENERAL; 3296 3297 /* enqueue to cmd thread */ 3298 cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node); 3299 3300 /* wake up cmd thread */ 3301 cam_sem_post(&(my_obj->cmd_thread.cmd_sem)); 3302 } else { 3303 LOGE("No memory for mm_camera_node_t"); 3304 rc = -1; 3305 } 3306 LOGD("X"); 3307 3308 return rc; 3309 } 3310 3311 /*=========================================================================== 3312 * FUNCTION : mm_channel_superbuf_flush_matched 3313 * 3314 * DESCRIPTION: flush matched buffers from the superbuf queue. 3315 * 3316 * PARAMETERS : 3317 * @my_obj : channel object 3318 * @queue : superbuf queue 3319 * 3320 * RETURN : int32_t type of status 3321 * 0 -- success 3322 * -1 -- failure 3323 *==========================================================================*/ 3324 int32_t mm_channel_superbuf_flush_matched(mm_channel_t* my_obj, 3325 mm_channel_queue_t * queue) 3326 { 3327 int32_t rc = 0, i; 3328 mm_channel_queue_node_t* super_buf = NULL; 3329 3330 /* bufdone bufs */ 3331 pthread_mutex_lock(&queue->que.lock); 3332 super_buf = mm_channel_superbuf_dequeue_internal(queue, TRUE, my_obj); 3333 while (super_buf != NULL) { 3334 for (i=0; i<super_buf->num_of_bufs; i++) { 3335 if (NULL != super_buf->super_buf[i].buf) { 3336 mm_channel_qbuf(my_obj, super_buf->super_buf[i].buf); 3337 } 3338 } 3339 free(super_buf); 3340 super_buf = mm_channel_superbuf_dequeue_internal(queue, TRUE, my_obj); 3341 } 3342 pthread_mutex_unlock(&queue->que.lock); 3343 3344 return rc; 3345 } 3346 3347 3348 /*=========================================================================== 3349 * FUNCTION : mm_frame_sync_reset 3350 * 3351 * DESCRIPTION: Reset Frame sync info 3352 * 3353 * RETURN : None 3354 *==========================================================================*/ 3355 void mm_frame_sync_reset() { 3356 memset(&fs, 0x0, sizeof(fs)); 3357 LOGD("Reset Done"); 3358 } 3359 3360 /*=========================================================================== 3361 * FUNCTION : mm_frame_sync_register_channel 3362 * 3363 * DESCRIPTION: Register Channel for frame sync 3364 * 3365 * PARAMETERS : 3366 * @ch_obj : channel object 3367 * 3368 * RETURN : int32_t type of status 3369 * 0 -- success 3370 * -1 -- failure 3371 *==========================================================================*/ 3372 int32_t mm_frame_sync_register_channel(mm_channel_t *ch_obj) { 3373 // Lock frame sync info 3374 pthread_mutex_lock(&fs_lock); 3375 if ((fs.num_cam >= MAX_NUM_CAMERA_PER_BUNDLE) || (!ch_obj)) { 3376 LOGE("Error!! num cam(%d) is out of range ", 3377 fs.num_cam); 3378 pthread_mutex_unlock(&fs_lock); 3379 return -1; 3380 } 3381 if (fs.num_cam == 0) { 3382 LOGH("First channel registering!!"); 3383 mm_frame_sync_reset(); 3384 } 3385 uint8_t i = 0; 3386 for (i = 0; i < MAX_NUM_CAMERA_PER_BUNDLE; i++) { 3387 if (fs.ch_obj[i] == NULL) { 3388 fs.ch_obj[i] = ch_obj; 3389 fs.cb[i] = ch_obj->bundle.super_buf_notify_cb; 3390 fs.num_cam++; 3391 LOGD("DBG_FS index %d", i); 3392 break; 3393 } 3394 } 3395 if (i >= MAX_NUM_CAMERA_PER_BUNDLE) { 3396 LOGH("X, DBG_FS Cannot register channel!!"); 3397 pthread_mutex_unlock(&fs_lock); 3398 return -1; 3399 } 3400 LOGH("num_cam %d ", fs.num_cam); 3401 pthread_mutex_unlock(&fs_lock); 3402 return 0; 3403 } 3404 3405 /*=========================================================================== 3406 * FUNCTION : mm_frame_sync_unregister_channel 3407 * 3408 * DESCRIPTION: un-register Channel for frame sync 3409 * 3410 * PARAMETERS : 3411 * @ch_obj : channel object 3412 * 3413 * RETURN : int32_t type of status 3414 * 0 -- success 3415 * -1 -- failure 3416 *==========================================================================*/ 3417 int32_t mm_frame_sync_unregister_channel(mm_channel_t *ch_obj) { 3418 uint8_t i = 0; 3419 // Lock frame sync info 3420 pthread_mutex_lock(&fs_lock); 3421 if (!fs.num_cam || !ch_obj) { 3422 LOGH("X, DBG_FS: channel not found !!"); 3423 // Lock frame sync info 3424 pthread_mutex_unlock(&fs_lock); 3425 return -1; 3426 } 3427 for (i = 0; i < MAX_NUM_CAMERA_PER_BUNDLE; i++) { 3428 if (fs.ch_obj[i] == ch_obj) { 3429 LOGD("found ch_obj at i (%d) ", i); 3430 break; 3431 } 3432 } 3433 if (i < MAX_NUM_CAMERA_PER_BUNDLE) { 3434 LOGD("remove channel info "); 3435 fs.ch_obj[i] = NULL; 3436 fs.cb[i] = NULL; 3437 fs.num_cam--; 3438 } else { 3439 LOGD("DBG_FS Channel not found "); 3440 } 3441 if (fs.num_cam == 0) { 3442 mm_frame_sync_reset(); 3443 } 3444 LOGH("X, fs.num_cam %d", fs.num_cam); 3445 pthread_mutex_unlock(&fs_lock); 3446 return 0; 3447 } 3448 3449 3450 /*=========================================================================== 3451 * FUNCTION : mm_frame_sync_add 3452 * 3453 * DESCRIPTION: Add frame info into frame sync nodes 3454 * 3455 * PARAMETERS : 3456 * @frame_id : frame id to be added 3457 * @ch_obj : channel object 3458 * 3459 * RETURN : int32_t type of status 3460 * 0 -- success 3461 * -1 -- failure 3462 *==========================================================================*/ 3463 int32_t mm_frame_sync_add(uint32_t frame_id, mm_channel_t *ch_obj) { 3464 3465 LOGD("E, frame id %d ch_obj %p", frame_id, ch_obj); 3466 if (!frame_id || !ch_obj) { 3467 LOGH("X : Error, cannot add sync frame !!"); 3468 return -1; 3469 } 3470 3471 int8_t ch_idx = -1; 3472 uint8_t i = 0; 3473 for (i = 0; i < MAX_NUM_CAMERA_PER_BUNDLE; i++) { 3474 if (fs.ch_obj[i] == ch_obj) { 3475 ch_idx = i; 3476 LOGD("ch id %d ", ch_idx); 3477 break; 3478 } 3479 } 3480 if (ch_idx < 0) { 3481 LOGH("X : DBG_FS ch not found!!"); 3482 return -1; 3483 } 3484 int8_t index = mm_frame_sync_find_frame_index(frame_id); 3485 if ((index >= 0) && (index < MM_CAMERA_FRAME_SYNC_NODES)) { 3486 fs.node[index].frame_valid[ch_idx] = 1; 3487 } else if (index < 0) { 3488 if (fs.pos >= MM_CAMERA_FRAME_SYNC_NODES) { 3489 fs.pos = 0; 3490 } 3491 index = fs.pos; 3492 memset(&fs.node[index], 0x00, sizeof(mm_channel_sync_node_t)); 3493 fs.pos++; 3494 fs.node[index].frame_idx = frame_id; 3495 fs.node[index].frame_valid[ch_idx] = 1; 3496 if (fs.num_cam == 1) { 3497 LOGD("Single camera frame %d , matched ", frame_id); 3498 fs.node[index].matched = 1; 3499 } 3500 } 3501 uint8_t frames_valid = 0; 3502 if (!fs.node[index].matched) { 3503 for (i = 0; i < MAX_NUM_CAMERA_PER_BUNDLE; i++) { 3504 if (fs.node[index].frame_valid[i]) { 3505 frames_valid++; 3506 } 3507 } 3508 if (frames_valid == fs.num_cam) { 3509 fs.node[index].matched = 1; 3510 LOGD("dual camera frame %d , matched ", 3511 frame_id); 3512 } 3513 } 3514 return 0; 3515 } 3516 3517 /*=========================================================================== 3518 * FUNCTION : mm_frame_sync_remove 3519 * 3520 * DESCRIPTION: Remove frame info from frame sync nodes 3521 * 3522 * PARAMETERS : 3523 * @frame_id : frame id to be removed 3524 * 3525 * RETURN : int32_t type of status 3526 * 0 -- success 3527 * -1 -- failure 3528 *==========================================================================*/ 3529 int32_t mm_frame_sync_remove(uint32_t frame_id) { 3530 int8_t index = -1; 3531 3532 LOGD("E, frame_id %d", frame_id); 3533 if (!frame_id) { 3534 LOGE("X, DBG_FS frame id invalid"); 3535 return -1; 3536 } 3537 3538 index = mm_frame_sync_find_frame_index(frame_id); 3539 if ((index >= 0) && (index < MM_CAMERA_FRAME_SYNC_NODES)) { 3540 LOGD("Removing sync frame %d", frame_id); 3541 memset(&fs.node[index], 0x00, sizeof(mm_channel_sync_node_t)); 3542 } 3543 LOGD("X "); 3544 return 0; 3545 } 3546 3547 /*=========================================================================== 3548 * FUNCTION : mm_frame_sync_find_matched 3549 * 3550 * DESCRIPTION: Find a matched sync frame from the node array 3551 * 3552 * PARAMETERS : 3553 * @oldest : If enabled, find oldest matched frame., 3554 * If not enabled, get the first matched frame found 3555 * 3556 * RETURN : unt32_t type of status 3557 * 0 -- If no matched frames found 3558 * frame index: inf matched frame found 3559 *==========================================================================*/ 3560 uint32_t mm_frame_sync_find_matched(uint8_t oldest) { 3561 LOGH("E, oldest %d ", oldest); 3562 uint8_t i = 0; 3563 uint32_t frame_idx = 0; 3564 uint32_t curr_frame_idx = 0; 3565 for (i = 0; i < MM_CAMERA_FRAME_SYNC_NODES; i++) { 3566 if (fs.node[i].matched) { 3567 curr_frame_idx = fs.node[i].frame_idx; 3568 if (!frame_idx) { 3569 frame_idx = curr_frame_idx; 3570 } 3571 if (!oldest) { 3572 break; 3573 } else if (frame_idx > curr_frame_idx) { 3574 frame_idx = curr_frame_idx; 3575 } 3576 } 3577 } 3578 LOGH("X, oldest %d frame idx %d", oldest, frame_idx); 3579 return frame_idx; 3580 } 3581 3582 /*=========================================================================== 3583 * FUNCTION : mm_frame_sync_find_frame_index 3584 * 3585 * DESCRIPTION: Find sync frame index if present 3586 * 3587 * PARAMETERS : 3588 * @frame_id : frame id to be searched 3589 * 3590 * RETURN : int8_t type of status 3591 * -1 -- If desired frame not found 3592 * index: node array index if frame is found 3593 *==========================================================================*/ 3594 int8_t mm_frame_sync_find_frame_index(uint32_t frame_id) { 3595 3596 LOGD("E, frame_id %d", frame_id); 3597 int8_t index = -1, i = 0; 3598 for (i = 0; i < MM_CAMERA_FRAME_SYNC_NODES; i++) { 3599 if (fs.node[i].frame_idx == frame_id) { 3600 index = i; 3601 break; 3602 } 3603 } 3604 LOGD("X index :%d", index); 3605 return index; 3606 } 3607 3608 /*=========================================================================== 3609 * FUNCTION : mm_frame_sync_lock_queues 3610 * 3611 * DESCRIPTION: Lock all channel queues present in node info 3612 * 3613 * RETURN : None 3614 *==========================================================================*/ 3615 void mm_frame_sync_lock_queues() { 3616 uint8_t j = 0; 3617 LOGD("E "); 3618 for (j = 0; j < MAX_NUM_CAMERA_PER_BUNDLE; j++) { 3619 if (fs.ch_obj[j]) { 3620 mm_channel_queue_t *ch_queue = 3621 &fs.ch_obj[j]->bundle.superbuf_queue; 3622 if (ch_queue) { 3623 pthread_mutex_lock(&ch_queue->que.lock); 3624 LOGL("Done locking fs.ch_obj[%d] ", j); 3625 } 3626 } 3627 } 3628 pthread_mutex_lock(&fs_lock); 3629 LOGD("X "); 3630 } 3631 3632 /*=========================================================================== 3633 * FUNCTION : mm_frame_sync_unlock_queues 3634 * 3635 * DESCRIPTION: Unlock all channel queues 3636 * 3637 * RETURN : None 3638 *==========================================================================*/ 3639 void mm_frame_sync_unlock_queues() { 3640 // Unlock all queues 3641 uint8_t j = 0; 3642 LOGD("E "); 3643 pthread_mutex_unlock(&fs_lock); 3644 LOGL("Done unlocking fs "); 3645 for (j = 0; j < MAX_NUM_CAMERA_PER_BUNDLE; j++) { 3646 if (fs.ch_obj[j]) { 3647 mm_channel_queue_t *ch_queue = 3648 &fs.ch_obj[j]->bundle.superbuf_queue; 3649 if (ch_queue) { 3650 pthread_mutex_unlock(&ch_queue->que.lock); 3651 LOGL("Done unlocking fs.ch_obj[%d] ", j); 3652 } 3653 } 3654 } 3655 LOGD("X "); 3656 } 3657 3658 /*=========================================================================== 3659 * FUNCTION : mm_channel_node_qbuf 3660 * 3661 * DESCRIPTION: qbuf all buffers in a node 3662 * 3663 * PARAMETERS : 3664 * @ch_obj : Channel info 3665 * @node : node to qbuf 3666 * 3667 * RETURN : None 3668 *==========================================================================*/ 3669 void mm_channel_node_qbuf(mm_channel_t *ch_obj, mm_channel_queue_node_t *node) { 3670 uint8_t i; 3671 if (!ch_obj || !node) { 3672 return; 3673 } 3674 for (i = 0; i < node->num_of_bufs; i++) { 3675 mm_channel_qbuf(ch_obj, node->super_buf[i].buf); 3676 } 3677 return; 3678 } 3679