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