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