1 /* 2 Copyright (c) 2011-2012, The Linux Foundation. All rights reserved. 3 4 Redistribution and use in source and binary forms, with or without 5 modification, are permitted provided that the following conditions are 6 met: 7 * Redistributions of source code must retain the above copyright 8 notice, this list of conditions and the following disclaimer. 9 * Redistributions in binary form must reproduce the above 10 copyright notice, this list of conditions and the following 11 disclaimer in the documentation and/or other materials provided 12 with the distribution. 13 * Neither the name of The Linux Foundation nor the names of its 14 contributors may be used to endorse or promote products derived 15 from this software without specific prior written permission. 16 17 THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 18 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 20 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 21 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 24 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 26 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #include <pthread.h> 31 #include <errno.h> 32 #include <sys/ioctl.h> 33 #include <sys/types.h> 34 #include <sys/stat.h> 35 #include <fcntl.h> 36 #include <poll.h> 37 #include <semaphore.h> 38 39 #include "mm_camera_dbg.h" 40 #include "mm_camera_interface.h" 41 #include "mm_camera.h" 42 43 extern mm_camera_obj_t* mm_camera_util_get_camera_by_handler(uint32_t cam_handler); 44 extern mm_channel_t * mm_camera_util_get_channel_by_handler( 45 mm_camera_obj_t * cam_obj, 46 uint32_t handler); 47 extern int32_t mm_camera_send_native_ctrl_cmd(mm_camera_obj_t * my_obj, 48 cam_ctrl_type type, 49 uint32_t length, 50 void *value); 51 extern int32_t mm_camera_send_native_ctrl_timeout_cmd(mm_camera_obj_t * my_obj, 52 cam_ctrl_type type, 53 uint32_t length, 54 void *value, 55 int timeout); 56 57 /* internal function declare goes here */ 58 int32_t mm_channel_qbuf(mm_channel_t *my_obj, 59 mm_camera_buf_def_t *buf); 60 int32_t mm_channel_init(mm_channel_t *my_obj); 61 void mm_channel_release(mm_channel_t *my_obj); 62 uint32_t mm_channel_add_stream(mm_channel_t *my_obj, 63 mm_camera_buf_notify_t buf_cb, void *user_data, 64 uint32_t ext_image_mode, uint32_t sensor_idx); 65 int32_t mm_channel_del_stream(mm_channel_t *my_obj, 66 uint32_t stream_id); 67 int32_t mm_channel_config_stream(mm_channel_t *my_obj, 68 uint32_t stream_id, 69 mm_camera_stream_config_t *config); 70 int32_t mm_channel_bundle_stream(mm_channel_t *my_obj, 71 mm_camera_buf_notify_t super_frame_notify_cb, 72 void *user_data, 73 mm_camera_bundle_attr_t *attr, 74 uint8_t num_streams, 75 uint32_t *stream_ids); 76 int32_t mm_channel_destroy_bundle(mm_channel_t *my_obj); 77 int32_t mm_channel_start_streams(mm_channel_t *my_obj, 78 uint8_t num_streams, 79 uint32_t *stream_ids); 80 int32_t mm_channel_stop_streams(mm_channel_t *my_obj, 81 uint8_t num_streams, 82 uint32_t *stream_ids, 83 uint8_t tear_down_flag); 84 int32_t mm_channel_request_super_buf(mm_channel_t *my_obj, uint32_t num_buf_requested); 85 int32_t mm_channel_cancel_super_buf_request(mm_channel_t *my_obj); 86 int32_t mm_channel_start_focus(mm_channel_t *my_obj, 87 uint32_t sensor_idx, 88 uint32_t focus_mode); 89 int32_t mm_channel_abort_focus(mm_channel_t *my_obj, 90 uint32_t sensor_idx); 91 int32_t mm_channel_prepare_snapshot(mm_channel_t *my_obj, 92 uint32_t sensor_idx); 93 int32_t mm_channel_set_stream_parm(mm_channel_t *my_obj, 94 uint32_t s_id, 95 void *value); 96 int32_t mm_channel_get_stream_parm(mm_channel_t *my_obj, 97 uint32_t s_id, 98 void *value); 99 int32_t mm_channel_do_post_processing(mm_channel_t *my_obj, 100 mm_channel_queue_node_t *super_buf); 101 int32_t mm_channel_superbuf_bufdone_overflow(mm_channel_t *my_obj, 102 mm_channel_queue_t *queue); 103 int32_t mm_channel_superbuf_skip(mm_channel_t *my_obj, 104 mm_channel_queue_t *queue); 105 uint32_t mm_channel_open_repro_isp(mm_channel_t *my_obj, 106 mm_camera_repro_isp_type_t isp_type); 107 int32_t mm_channel_close_repro_isp(mm_channel_t *my_obj, 108 uint32_t repro_handle); 109 int32_t mm_channel_config_repro_isp(mm_channel_t *my_obj, 110 uint32_t repro_handle, 111 mm_camera_repro_isp_config_t *config); 112 int32_t mm_channel_repro_isp_dest_stream_ops(mm_channel_t *my_obj, 113 uint32_t repro_handle, 114 uint32_t stream_handle, 115 uint8_t attach_flag); 116 int32_t mm_channel_repro_isp_ops(mm_channel_t *my_obj, 117 uint32_t repro_handle, 118 uint32_t stream_id, 119 uint8_t start_flag); 120 int32_t mm_channel_reprocess(mm_channel_t *my_obj, 121 uint32_t repro_handle, 122 mm_camera_repro_data_t *repro_data); 123 124 /* state machine function declare */ 125 int32_t mm_channel_fsm_fn_notused(mm_channel_t *my_obj, 126 mm_channel_evt_type_t evt, 127 void * in_val, 128 void * out_val); 129 int32_t mm_channel_fsm_fn_stopped(mm_channel_t *my_obj, 130 mm_channel_evt_type_t evt, 131 void * in_val, 132 void * out_val); 133 int32_t mm_channel_fsm_fn_active(mm_channel_t *my_obj, 134 mm_channel_evt_type_t evt, 135 void * in_val, 136 void * out_val); 137 int32_t mm_channel_fsm_fn_paused(mm_channel_t *my_obj, 138 mm_channel_evt_type_t evt, 139 void * in_val, 140 void * out_val); 141 142 /* channel super queue functions */ 143 int32_t mm_channel_superbuf_queue_init(mm_channel_queue_t * queue); 144 int32_t mm_channel_superbuf_queue_deinit(mm_channel_t *my_obj, 145 mm_channel_queue_t * queue); 146 int32_t mm_channel_superbuf_comp_and_enqueue(mm_channel_t *ch_obj, 147 mm_channel_queue_t * queue, 148 mm_camera_buf_info_t *buf); 149 mm_channel_queue_node_t* mm_channel_superbuf_dequeue(mm_channel_queue_t * queue); 150 151 /* channel utility function */ 152 mm_stream_t * mm_channel_util_get_stream_by_handler( 153 mm_channel_t * ch_obj, 154 uint32_t handler) 155 { 156 int i; 157 mm_stream_t *s_obj = NULL; 158 uint8_t ch_idx = mm_camera_util_get_index_by_handler(handler); 159 160 for(i = 0; i < MM_CAMEAR_STRAEM_NUM_MAX; i++) { 161 if (handler == ch_obj->streams[i].my_hdl) { 162 s_obj = &ch_obj->streams[i]; 163 break; 164 } 165 } 166 return s_obj; 167 } 168 169 static void mm_channel_dispatch_super_buf(mm_camera_cmdcb_t *cmd_cb, 170 void* user_data) 171 { 172 int i; 173 mm_channel_t * my_obj = (mm_channel_t *)user_data; 174 175 if (NULL == my_obj) { 176 return; 177 } 178 179 if (MM_CAMERA_CMD_TYPE_SUPER_BUF_DATA_CB != cmd_cb->cmd_type) { 180 CDBG_ERROR("%s: Wrong cmd_type (%d) for super buf dataCB", 181 __func__, cmd_cb->cmd_type); 182 return; 183 } 184 185 if (my_obj->bundle.super_buf_notify_cb) { 186 my_obj->bundle.super_buf_notify_cb(&cmd_cb->u.superbuf, my_obj->bundle.user_data); 187 } 188 } 189 190 /* CB for processing stream buffer */ 191 static void mm_channel_process_stream_buf(mm_camera_cmdcb_t * cmd_cb, 192 void *user_data) 193 { 194 mm_camera_super_buf_notify_mode_t notify_mode; 195 mm_channel_queue_node_t *node = NULL; 196 mm_channel_t *ch_obj = (mm_channel_t *)user_data; 197 if (NULL == ch_obj) { 198 return; 199 } 200 201 if (MM_CAMERA_CMD_TYPE_DATA_CB == cmd_cb->cmd_type) { 202 /* comp_and_enqueue */ 203 mm_channel_superbuf_comp_and_enqueue( 204 ch_obj, 205 &ch_obj->bundle.superbuf_queue, 206 &cmd_cb->u.buf); 207 } else if (MM_CAMERA_CMD_TYPE_REQ_DATA_CB == cmd_cb->cmd_type) { 208 /* skip frames if needed */ 209 ch_obj->pending_cnt = cmd_cb->u.req_buf.num_buf_requested; 210 mm_channel_superbuf_skip(ch_obj, &ch_obj->bundle.superbuf_queue); 211 } 212 213 notify_mode = ch_obj->bundle.superbuf_queue.attr.notify_mode; 214 215 /* bufdone for overflowed bufs */ 216 mm_channel_superbuf_bufdone_overflow(ch_obj, &ch_obj->bundle.superbuf_queue); 217 218 /* dispatch frame if pending_cnt>0 or is in continuous streaming mode */ 219 while ( (ch_obj->pending_cnt > 0) || 220 (MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS == notify_mode) ) { 221 222 /* dequeue */ 223 node = mm_channel_superbuf_dequeue(&ch_obj->bundle.superbuf_queue); 224 if (NULL != node) { 225 /* decrease pending_cnt */ 226 CDBG("%s: Super Buffer received, Call client callback, pending_cnt=%d", 227 __func__, ch_obj->pending_cnt); 228 if (MM_CAMERA_SUPER_BUF_NOTIFY_BURST == notify_mode) { 229 ch_obj->pending_cnt--; 230 } 231 232 /* do post processing if needed */ 233 /* this is a blocking call */ 234 mm_channel_do_post_processing(ch_obj, node); 235 236 /* dispatch superbuf */ 237 if (NULL != ch_obj->bundle.super_buf_notify_cb) { 238 uint8_t i; 239 mm_camera_cmdcb_t* cb_node = NULL; 240 241 CDBG("%s: Send superbuf to HAL, pending_cnt=%d", 242 __func__, ch_obj->pending_cnt); 243 244 /* send sem_post to wake up cb thread to dispatch super buffer */ 245 cb_node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t)); 246 if (NULL != cb_node) { 247 memset(cb_node, 0, sizeof(mm_camera_cmdcb_t)); 248 cb_node->cmd_type = MM_CAMERA_CMD_TYPE_SUPER_BUF_DATA_CB; 249 cb_node->u.superbuf.num_bufs = node->num_of_bufs; 250 for (i=0; i<node->num_of_bufs; i++) { 251 cb_node->u.superbuf.bufs[i] = node->super_buf[i].buf; 252 } 253 cb_node->u.superbuf.camera_handle = ch_obj->cam_obj->my_hdl; 254 cb_node->u.superbuf.ch_id = ch_obj->my_hdl; 255 256 /* enqueue to cb thread */ 257 mm_camera_queue_enq(&(ch_obj->cb_thread.cmd_queue), cb_node); 258 259 /* wake up cb thread */ 260 sem_post(&(ch_obj->cb_thread.cmd_sem)); 261 } else { 262 CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__); 263 /* buf done with the nonuse super buf */ 264 for (i=0; i<node->num_of_bufs; i++) { 265 mm_channel_qbuf(ch_obj, node->super_buf[i].buf); 266 } 267 } 268 } else { 269 /* buf done with the nonuse super buf */ 270 uint8_t i; 271 for (i=0; i<node->num_of_bufs; i++) { 272 mm_channel_qbuf(ch_obj, node->super_buf[i].buf); 273 } 274 } 275 free(node); 276 } else { 277 /* no superbuf avail, break the loop */ 278 break; 279 } 280 } 281 } 282 283 /* state machine entry */ 284 int32_t mm_channel_fsm_fn(mm_channel_t *my_obj, 285 mm_channel_evt_type_t evt, 286 void * in_val, 287 void * out_val) 288 { 289 int32_t rc = -1; 290 291 CDBG("%s : E state = %d",__func__,my_obj->state); 292 switch (my_obj->state) { 293 case MM_CHANNEL_STATE_NOTUSED: 294 rc = mm_channel_fsm_fn_notused(my_obj, evt, in_val, out_val); 295 break; 296 case MM_CHANNEL_STATE_STOPPED: 297 rc = mm_channel_fsm_fn_stopped(my_obj, evt, in_val, out_val); 298 break; 299 case MM_CHANNEL_STATE_ACTIVE: 300 rc = mm_channel_fsm_fn_active(my_obj, evt, in_val, out_val); 301 break; 302 case MM_CHANNEL_STATE_PAUSED: 303 rc = mm_channel_fsm_fn_paused(my_obj, evt, in_val, out_val); 304 break; 305 default: 306 CDBG("%s: Not a valid state (%d)", __func__, my_obj->state); 307 break; 308 } 309 310 /* unlock ch_lock */ 311 pthread_mutex_unlock(&my_obj->ch_lock); 312 CDBG("%s : X rc = %d",__func__,rc); 313 return rc; 314 } 315 316 int32_t mm_channel_fsm_fn_notused(mm_channel_t *my_obj, 317 mm_channel_evt_type_t evt, 318 void * in_val, 319 void * out_val) 320 { 321 int32_t rc = -1; 322 323 switch (evt) { 324 default: 325 CDBG_ERROR("%s: invalid state (%d) for evt (%d)", 326 __func__, my_obj->state, evt); 327 break; 328 } 329 330 return rc; 331 } 332 333 int32_t mm_channel_fsm_fn_stopped(mm_channel_t *my_obj, 334 mm_channel_evt_type_t evt, 335 void * in_val, 336 void * out_val) 337 { 338 int32_t rc = 0; 339 CDBG("%s : E evt = %d",__func__,evt); 340 switch (evt) { 341 case MM_CHANNEL_EVT_ADD_STREAM: 342 { 343 uint32_t s_hdl = 0; 344 mm_evt_paylod_add_stream_t *payload = 345 (mm_evt_paylod_add_stream_t *)in_val; 346 s_hdl = mm_channel_add_stream(my_obj, 347 payload->buf_cb, 348 payload->user_data, 349 payload->ext_image_mode, 350 payload->sensor_idx); 351 *((uint32_t*)out_val) = s_hdl; 352 rc = 0; 353 } 354 break; 355 case MM_CHANNEL_EVT_DEL_STREAM: 356 { 357 uint32_t s_id = *((uint32_t *)in_val); 358 rc = mm_channel_del_stream(my_obj, s_id); 359 } 360 break; 361 case MM_CHANNEL_EVT_START_STREAM: 362 { 363 mm_evt_payload_start_stream_t *payload = 364 (mm_evt_payload_start_stream_t *)in_val; 365 rc = mm_channel_start_streams(my_obj, 366 payload->num_streams, 367 payload->stream_ids); 368 /* first stream started in stopped state 369 * move to active state */ 370 if (0 == rc) { 371 my_obj->state = MM_CHANNEL_STATE_ACTIVE; 372 } 373 } 374 break; 375 case MM_CHANNEL_EVT_CONFIG_STREAM: 376 { 377 mm_evt_paylod_config_stream_t *payload = 378 (mm_evt_paylod_config_stream_t *)in_val; 379 rc = mm_channel_config_stream(my_obj, 380 payload->stream_id, 381 payload->config); 382 } 383 break; 384 case MM_CHANNEL_EVT_INIT_BUNDLE: 385 { 386 mm_evt_payload_bundle_stream_t *payload = 387 (mm_evt_payload_bundle_stream_t *)in_val; 388 rc = mm_channel_bundle_stream(my_obj, 389 payload->super_frame_notify_cb, 390 payload->user_data, 391 payload->attr, 392 payload->num_streams, 393 payload->stream_ids); 394 } 395 break; 396 case MM_CHANNEL_EVT_DESTROY_BUNDLE: 397 rc = mm_channel_destroy_bundle(my_obj); 398 break; 399 case MM_CHANNEL_EVT_PREPARE_SNAPSHOT: 400 { 401 uint32_t sensor_idx = (uint32_t)in_val; 402 rc = mm_channel_prepare_snapshot(my_obj, sensor_idx); 403 } 404 break; 405 case MM_CHANNEL_EVT_DELETE: 406 mm_channel_release(my_obj); 407 rc = 0; 408 break; 409 case MM_CHANNEL_EVT_SET_STREAM_PARM: 410 { 411 uint32_t s_id = (uint32_t)in_val; 412 rc = mm_channel_set_stream_parm(my_obj, s_id, out_val); 413 } 414 break; 415 case MM_CHANNEL_EVT_GET_STREAM_PARM: 416 { 417 uint32_t s_id = (uint32_t)in_val; 418 rc = mm_channel_get_stream_parm(my_obj, s_id, out_val); 419 } 420 break; 421 case MM_CHANNEL_EVT_OPEN_REPRO_ISP: 422 { 423 uint32_t repro_hdl = 0; 424 mm_camera_repro_isp_type_t isp_type = 425 (mm_camera_repro_isp_type_t)in_val; 426 repro_hdl = mm_channel_open_repro_isp(my_obj, isp_type); 427 *((uint32_t*)out_val) = repro_hdl; 428 rc = 0; 429 } 430 break; 431 case MM_CHANNEL_EVT_CONFIG_REPRO_ISP: 432 { 433 mm_evt_paylod_config_repro_isp_t *payload = 434 (mm_evt_paylod_config_repro_isp_t *)in_val; 435 rc = mm_channel_config_repro_isp(my_obj, 436 payload->repro_isp_handle, 437 payload->config); 438 } 439 break; 440 case MM_CHANNEL_EVT_ATTACH_STREAM_TO_REPRO_ISP: 441 { 442 mm_evt_paylod_stream_to_repro_isp_t *payload = 443 (mm_evt_paylod_stream_to_repro_isp_t *)in_val; 444 rc = mm_channel_repro_isp_dest_stream_ops(my_obj, 445 payload->repro_isp_handle, 446 payload->stream_id, 447 TRUE); 448 } 449 break; 450 case MM_CHANNEL_EVT_START_REPRO_ISP: 451 { 452 mm_evt_paylod_repro_start_stop_t *payload = 453 (mm_evt_paylod_repro_start_stop_t*)in_val; 454 rc = mm_channel_repro_isp_ops(my_obj, 455 payload->repro_isp_handle, 456 payload->stream_id, 457 TRUE); 458 } 459 break; 460 case MM_CHANNEL_EVT_REPROCESS: 461 { 462 mm_evt_paylod_reprocess_t *payload = 463 (mm_evt_paylod_reprocess_t *)in_val; 464 rc = mm_channel_reprocess(my_obj, 465 payload->repro_isp_handle, 466 payload->repro_data); 467 } 468 break; 469 case MM_CHANNEL_EVT_STOP_REPRO_ISP: 470 { 471 mm_evt_paylod_repro_start_stop_t *payload = 472 (mm_evt_paylod_repro_start_stop_t*)in_val; 473 rc = mm_channel_repro_isp_ops(my_obj, 474 payload->repro_isp_handle, 475 payload->stream_id, 476 FALSE); 477 } 478 break; 479 case MM_CHANNEL_EVT_DETACH_STREAM_FROM_REPRO_ISP: 480 { 481 mm_evt_paylod_stream_to_repro_isp_t *payload = 482 (mm_evt_paylod_stream_to_repro_isp_t *)in_val; 483 rc = mm_channel_repro_isp_dest_stream_ops(my_obj, 484 payload->repro_isp_handle, 485 payload->stream_id, 486 FALSE); 487 } 488 break; 489 case MM_CHANNEL_EVT_CLOSE_REPRO_ISP: 490 { 491 uint32_t repro_handle = (uint32_t)in_val; 492 rc = mm_channel_close_repro_isp(my_obj, repro_handle); 493 } 494 break; 495 default: 496 CDBG_ERROR("%s: invalid state (%d) for evt (%d)", 497 __func__, my_obj->state, evt); 498 break; 499 } 500 CDBG("%s : E rc = %d",__func__,rc); 501 return rc; 502 } 503 504 int32_t mm_channel_fsm_fn_active(mm_channel_t *my_obj, 505 mm_channel_evt_type_t evt, 506 void * in_val, 507 void * out_val) 508 { 509 int32_t rc = 0; 510 511 CDBG("%s : E evt = %d",__func__,evt); 512 switch (evt) { 513 case MM_CHANNEL_EVT_CONFIG_STREAM: 514 { 515 mm_evt_paylod_config_stream_t *payload = 516 (mm_evt_paylod_config_stream_t *)in_val; 517 rc = mm_channel_config_stream(my_obj, 518 payload->stream_id, 519 payload->config); 520 } 521 break; 522 case MM_CHANNEL_EVT_START_STREAM: 523 { 524 mm_evt_payload_start_stream_t *payload = 525 (mm_evt_payload_start_stream_t *)in_val; 526 rc = mm_channel_start_streams(my_obj, 527 payload->num_streams, 528 payload->stream_ids); 529 } 530 break; 531 case MM_CHANNEL_EVT_STOP_STREAM: 532 case MM_CHANNEL_EVT_TEARDOWN_STREAM: 533 { 534 int i; 535 uint8_t tear_down_flag = (MM_CHANNEL_EVT_TEARDOWN_STREAM == evt)? 1:0; 536 uint8_t all_stopped = 1; 537 mm_evt_payload_stop_stream_t *payload = 538 (mm_evt_payload_stop_stream_t *)in_val; 539 540 rc = mm_channel_stop_streams(my_obj, 541 payload->num_streams, 542 payload->stream_ids, 543 tear_down_flag); 544 545 /* check if all streams are stopped 546 * then we move to stopped state */ 547 548 for (i=0; i<MM_CAMEAR_STRAEM_NUM_MAX; i++) { 549 if (MM_STREAM_STATE_ACTIVE_STREAM_ON == my_obj->streams[i].state || 550 MM_STREAM_STATE_ACTIVE_STREAM_OFF == my_obj->streams[i].state) { 551 all_stopped = 0; 552 break; 553 } 554 } 555 if (all_stopped) { 556 my_obj->state = MM_CHANNEL_STATE_STOPPED; 557 } 558 559 } 560 break; 561 case MM_CHANNEL_EVT_INIT_BUNDLE: 562 { 563 mm_evt_payload_bundle_stream_t *payload = 564 (mm_evt_payload_bundle_stream_t *)in_val; 565 rc = mm_channel_bundle_stream(my_obj, 566 payload->super_frame_notify_cb, 567 payload->user_data, 568 payload->attr, 569 payload->num_streams, 570 payload->stream_ids); 571 } 572 break; 573 case MM_CHANNEL_EVT_DESTROY_BUNDLE: 574 rc = mm_channel_destroy_bundle(my_obj); 575 break; 576 case MM_CHANNEL_EVT_REQUEST_SUPER_BUF: 577 { 578 uint32_t num_buf_requested = (uint32_t)in_val; 579 rc = mm_channel_request_super_buf(my_obj, num_buf_requested); 580 } 581 break; 582 case MM_CHANNEL_EVT_CANCEL_REQUEST_SUPER_BUF: 583 rc = mm_channel_cancel_super_buf_request(my_obj); 584 break; 585 case MM_CHANNEL_EVT_START_FOCUS: 586 { 587 mm_evt_payload_start_focus_t* payload = 588 (mm_evt_payload_start_focus_t *)in_val; 589 rc = mm_channel_start_focus(my_obj, 590 payload->sensor_idx, 591 payload->focus_mode); 592 } 593 break; 594 case MM_CHANNEL_EVT_ABORT_FOCUS: 595 { 596 uint32_t sensor_idx = (uint32_t)in_val; 597 rc = mm_channel_abort_focus(my_obj, sensor_idx); 598 } 599 break; 600 case MM_CHANNEL_EVT_PREPARE_SNAPSHOT: 601 { 602 uint32_t sensor_idx = (uint32_t)in_val; 603 rc = mm_channel_prepare_snapshot(my_obj, sensor_idx); 604 } 605 break; 606 case MM_CHANNEL_EVT_SET_STREAM_PARM: 607 { 608 uint32_t s_id = (uint32_t)in_val; 609 rc = mm_channel_set_stream_parm(my_obj, s_id, out_val); 610 } 611 break; 612 case MM_CHANNEL_EVT_GET_STREAM_PARM: 613 { 614 uint32_t s_id = (uint32_t)in_val; 615 rc = mm_channel_get_stream_parm(my_obj, s_id, out_val); 616 } 617 break; 618 619 case MM_CHANNEL_EVT_DEL_STREAM: 620 { 621 uint32_t s_id = *((uint32_t *)in_val); 622 rc = mm_channel_del_stream(my_obj, s_id); 623 } 624 break; 625 case MM_CHANNEL_EVT_ATTACH_STREAM_TO_REPRO_ISP: 626 { 627 mm_evt_paylod_stream_to_repro_isp_t *payload = 628 (mm_evt_paylod_stream_to_repro_isp_t *)in_val; 629 rc = mm_channel_repro_isp_dest_stream_ops(my_obj, 630 payload->repro_isp_handle, 631 payload->stream_id, 632 TRUE); 633 } 634 break; 635 case MM_CHANNEL_EVT_START_REPRO_ISP: 636 { 637 mm_evt_paylod_repro_start_stop_t *payload = 638 (mm_evt_paylod_repro_start_stop_t*)in_val; 639 rc = mm_channel_repro_isp_ops(my_obj, 640 payload->repro_isp_handle, 641 payload->stream_id, 642 TRUE); 643 } 644 break; 645 case MM_CHANNEL_EVT_REPROCESS: 646 { 647 mm_evt_paylod_reprocess_t *payload = 648 (mm_evt_paylod_reprocess_t *)in_val; 649 rc = mm_channel_reprocess(my_obj, 650 payload->repro_isp_handle, 651 payload->repro_data); 652 } 653 break; 654 case MM_CHANNEL_EVT_STOP_REPRO_ISP: 655 { 656 mm_evt_paylod_repro_start_stop_t *payload = 657 (mm_evt_paylod_repro_start_stop_t*)in_val; 658 rc = mm_channel_repro_isp_ops(my_obj, 659 payload->repro_isp_handle, 660 payload->stream_id, 661 FALSE); 662 } 663 break; 664 case MM_CHANNEL_EVT_DETACH_STREAM_FROM_REPRO_ISP: 665 { 666 mm_evt_paylod_stream_to_repro_isp_t *payload = 667 (mm_evt_paylod_stream_to_repro_isp_t *)in_val; 668 rc = mm_channel_repro_isp_dest_stream_ops(my_obj, 669 payload->repro_isp_handle, 670 payload->stream_id, 671 FALSE); 672 } 673 break; 674 default: 675 CDBG_ERROR("%s: invalid state (%d) for evt (%d)", 676 __func__, my_obj->state, evt); 677 break; 678 } 679 CDBG("%s : X rc = %d",__func__,rc); 680 return rc; 681 } 682 683 int32_t mm_channel_fsm_fn_paused(mm_channel_t *my_obj, 684 mm_channel_evt_type_t evt, 685 void * in_val, 686 void * out_val) 687 { 688 int32_t rc = 0; 689 690 /* currently we are not supporting pause/resume channel */ 691 CDBG_ERROR("%s: evt (%d) not supported in state (%d)", 692 __func__, evt, my_obj->state); 693 694 return rc; 695 } 696 697 int32_t mm_channel_init(mm_channel_t *my_obj) 698 { 699 int32_t rc = 0; 700 CDBG("%s : Launch data poll thread in channel open",__func__); 701 mm_camera_poll_thread_launch(&my_obj->poll_thread[0], 702 MM_CAMERA_POLL_TYPE_CH); 703 704 /* change state to stopped state */ 705 my_obj->state = MM_CHANNEL_STATE_STOPPED; 706 return rc; 707 } 708 709 void mm_channel_release(mm_channel_t *my_obj) 710 { 711 /* stop data poll thread */ 712 mm_camera_poll_thread_release(&my_obj->poll_thread[0]); 713 714 /* change state to notused state */ 715 my_obj->state = MM_CHANNEL_STATE_NOTUSED; 716 } 717 718 uint32_t mm_channel_get_ext_mode_from_img_mode(uint32_t img_mode) 719 { 720 switch (img_mode) { 721 case MM_CAMERA_PREVIEW: 722 return MSM_V4L2_EXT_CAPTURE_MODE_PREVIEW; 723 case MM_CAMERA_VIDEO: 724 return MSM_V4L2_EXT_CAPTURE_MODE_VIDEO; 725 case MM_CAMERA_SNAPSHOT_MAIN: 726 return MSM_V4L2_EXT_CAPTURE_MODE_MAIN; 727 case MM_CAMERA_SNAPSHOT_THUMBNAIL: 728 return MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL; 729 case MM_CAMERA_SNAPSHOT_RAW: 730 return MSM_V4L2_EXT_CAPTURE_MODE_RAW; 731 case MM_CAMERA_RDI: 732 return MSM_V4L2_EXT_CAPTURE_MODE_RDI; 733 case MM_CAMERA_RDI1: 734 return MSM_V4L2_EXT_CAPTURE_MODE_RDI1; 735 case MM_CAMERA_RDI2: 736 return MSM_V4L2_EXT_CAPTURE_MODE_RDI2; 737 case MM_CAMERA_SAEC: 738 return MSM_V4L2_EXT_CAPTURE_MODE_AEC; 739 case MM_CAMERA_SAWB: 740 return MSM_V4L2_EXT_CAPTURE_MODE_AWB; 741 case MM_CAMERA_SAFC: 742 return MSM_V4L2_EXT_CAPTURE_MODE_AF; 743 case MM_CAMERA_IHST: 744 return MSM_V4L2_EXT_CAPTURE_MODE_IHIST; 745 case MM_CAMERA_CS: 746 return MSM_V4L2_EXT_CAPTURE_MODE_CS; 747 case MM_CAMERA_RS: 748 return MSM_V4L2_EXT_CAPTURE_MODE_RS; 749 case MM_CAMERA_CSTA: 750 return MSM_V4L2_EXT_CAPTURE_MODE_CSTA; 751 case MM_CAMERA_ISP_PIX_OUTPUT1: 752 return MSM_V4L2_EXT_CAPTURE_MODE_ISP_PIX_OUTPUT1; 753 case MM_CAMERA_ISP_PIX_OUTPUT2: 754 return MSM_V4L2_EXT_CAPTURE_MODE_ISP_PIX_OUTPUT2; 755 default: 756 return MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT; 757 } 758 } 759 760 uint32_t mm_channel_add_stream(mm_channel_t *my_obj, 761 mm_camera_buf_notify_t buf_cb, void *user_data, 762 uint32_t ext_image_mode, uint32_t sensor_idx) 763 { 764 int32_t rc = 0; 765 uint8_t idx = 0; 766 uint32_t s_hdl = 0; 767 mm_stream_t *stream_obj = NULL; 768 769 CDBG("%s : image mode = %d",__func__,ext_image_mode); 770 /* check available stream */ 771 for (idx = 0; idx < MM_CAMEAR_STRAEM_NUM_MAX; idx++) { 772 if (MM_STREAM_STATE_NOTUSED == my_obj->streams[idx].state) { 773 stream_obj = &my_obj->streams[idx]; 774 break; 775 } 776 } 777 if (NULL == stream_obj) { 778 CDBG_ERROR("%s: streams reach max, no more stream allowed to add", __func__); 779 return s_hdl; 780 } 781 782 /* initialize stream object */ 783 memset(stream_obj, 0, sizeof(mm_stream_t)); 784 stream_obj->my_hdl = mm_camera_util_generate_handler(idx); 785 stream_obj->ch_obj = my_obj; 786 /* cd through intf always palced at idx 0 of buf_cb */ 787 stream_obj->buf_cb[0].cb = buf_cb; 788 stream_obj->buf_cb[0].user_data = user_data; 789 stream_obj->buf_cb[0].cb_count = -1; /* infinite by default */ 790 stream_obj->ext_image_mode = 791 mm_channel_get_ext_mode_from_img_mode(ext_image_mode); 792 stream_obj->sensor_idx = sensor_idx; 793 stream_obj->fd = -1; 794 pthread_mutex_init(&stream_obj->buf_lock, NULL); 795 pthread_mutex_init(&stream_obj->cb_lock, NULL); 796 stream_obj->state = MM_STREAM_STATE_INITED; 797 798 /* acquire stream */ 799 rc = mm_stream_fsm_fn(stream_obj, MM_STREAM_EVT_ACQUIRE, NULL, NULL); 800 if (0 == rc) { 801 s_hdl = stream_obj->my_hdl; 802 } else { 803 /* error during acquire, de-init */ 804 pthread_mutex_destroy(&stream_obj->buf_lock); 805 pthread_mutex_destroy(&stream_obj->cb_lock); 806 memset(stream_obj, 0, sizeof(mm_stream_t)); 807 } 808 CDBG("%s : stream handle = %d",__func__,s_hdl); 809 return s_hdl; 810 } 811 812 int32_t mm_channel_del_stream(mm_channel_t *my_obj, 813 uint32_t stream_id) 814 { 815 int rc = -1; 816 mm_stream_t * stream_obj = NULL; 817 stream_obj = mm_channel_util_get_stream_by_handler(my_obj, stream_id); 818 819 if (NULL == stream_obj) { 820 CDBG_ERROR("%s :Invalid Stream Object for stream_id = %d",__func__, stream_id); 821 return rc; 822 } 823 824 rc = mm_stream_fsm_fn(stream_obj, 825 MM_STREAM_EVT_RELEASE, 826 NULL, 827 NULL); 828 829 return rc; 830 } 831 832 int32_t mm_channel_config_stream(mm_channel_t *my_obj, 833 uint32_t stream_id, 834 mm_camera_stream_config_t *config) 835 { 836 int rc = -1; 837 mm_stream_t * stream_obj = NULL; 838 CDBG("%s : E stream ID = %d",__func__,stream_id); 839 stream_obj = mm_channel_util_get_stream_by_handler(my_obj, stream_id); 840 841 if (NULL == stream_obj) { 842 CDBG_ERROR("%s :Invalid Stream Object for stream_id = %d",__func__, stream_id); 843 return rc; 844 } 845 846 /* set stream fmt */ 847 rc = mm_stream_fsm_fn(stream_obj, 848 MM_STREAM_EVT_SET_FMT, 849 (void *)config, 850 NULL); 851 CDBG("%s : X rc = %d",__func__,rc); 852 return rc; 853 } 854 855 int32_t mm_channel_bundle_stream(mm_channel_t *my_obj, 856 mm_camera_buf_notify_t super_frame_notify_cb, 857 void *user_data, 858 mm_camera_bundle_attr_t *attr, 859 uint8_t num_streams, 860 uint32_t *stream_ids) 861 { 862 int32_t rc = 0; 863 int i; 864 cam_stream_bundle_t bundle; 865 mm_stream_t* s_objs[MM_CAMEAR_MAX_STRAEM_BUNDLE] = {NULL}; 866 867 /* first check if all streams to be bundled are valid */ 868 for (i=0; i < num_streams; i++) { 869 s_objs[i] = mm_channel_util_get_stream_by_handler(my_obj, stream_ids[i]); 870 if (NULL == s_objs[i]) { 871 CDBG_ERROR("%s: invalid stream handler %d (idx=%d) to be bundled", 872 __func__, stream_ids[i], i); 873 return -1; 874 } 875 } 876 877 /* init superbuf queue */ 878 mm_channel_superbuf_queue_init(&my_obj->bundle.superbuf_queue); 879 880 memset(&bundle, 0, sizeof(bundle)); 881 /* save bundle config */ 882 memcpy(&my_obj->bundle.superbuf_queue.attr, attr, sizeof(mm_camera_bundle_attr_t)); 883 my_obj->bundle.super_buf_notify_cb = super_frame_notify_cb; 884 my_obj->bundle.user_data = user_data; 885 my_obj->bundle.superbuf_queue.num_streams = num_streams; 886 my_obj->bundle.superbuf_queue.expected_frame_id = 0; 887 888 for (i=0; i < num_streams; i++) { 889 /* set bundled flag to streams */ 890 s_objs[i]->is_bundled = 1; 891 /* init bundled streams to invalid value -1 */ 892 my_obj->bundle.superbuf_queue.bundled_streams[i] = stream_ids[i]; 893 bundle.stream_handles[bundle.num++] = 894 s_objs[i]->inst_hdl; 895 } 896 /* in the case of 1 bundle , current implementation is nop */ 897 if (bundle.num > 1) { 898 rc = mm_camera_send_native_ctrl_cmd(my_obj->cam_obj, 899 CAMERA_SET_BUNDLE, 900 sizeof(bundle), 901 (void *)&bundle); 902 if (0 != rc) { 903 CDBG_ERROR("%s: set_bundle failed (rc=%d)", __func__, rc); 904 return -1; 905 } 906 } 907 908 /* launch cb thread for dispatching super buf through cb */ 909 mm_camera_cmd_thread_launch(&my_obj->cb_thread, 910 mm_channel_dispatch_super_buf, 911 (void*)my_obj); 912 913 /* launch cmd thread for super buf dataCB */ 914 mm_camera_cmd_thread_launch(&my_obj->cmd_thread, 915 mm_channel_process_stream_buf, 916 (void*)my_obj); 917 918 /* set flag to TRUE */ 919 my_obj->bundle.is_active = TRUE; 920 921 return rc; 922 } 923 924 /* bundled streams must all be stopped before bundle can be destroyed */ 925 int32_t mm_channel_destroy_bundle(mm_channel_t *my_obj) 926 { 927 mm_stream_t* s_obj = NULL; 928 uint8_t i; 929 930 if (FALSE == my_obj->bundle.is_active) { 931 CDBG("%s: bundle not active, no need to destroy", __func__); 932 return 0; 933 } 934 935 /* first check all bundled streams should be stopped already */ 936 for (i=0; i < my_obj->bundle.superbuf_queue.num_streams; i++) { 937 s_obj = mm_channel_util_get_stream_by_handler(my_obj, 938 my_obj->bundle.superbuf_queue.bundled_streams[i]); 939 if (NULL != s_obj) { 940 if (MM_STREAM_STATE_ACTIVE_STREAM_ON == s_obj->state || 941 MM_STREAM_STATE_ACTIVE_STREAM_OFF == s_obj->state) { 942 CDBG_ERROR("%s: at least one of the bundled streams (%d) is still active", 943 __func__, my_obj->bundle.superbuf_queue.bundled_streams[i]); 944 return -1; 945 } 946 } 947 } 948 949 /* deinit superbuf queue */ 950 mm_channel_superbuf_queue_deinit(my_obj, &my_obj->bundle.superbuf_queue); 951 952 /* memset bundle info */ 953 memset(&my_obj->bundle, 0, sizeof(mm_channel_bundle_t)); 954 my_obj->bundle.is_active = FALSE; 955 return 0; 956 } 957 958 int32_t mm_channel_start_streams(mm_channel_t *my_obj, 959 uint8_t num_streams, 960 uint32_t *stream_ids) 961 { 962 int32_t rc = 0; 963 int i, j; 964 mm_stream_t* s_objs[MM_CAMEAR_MAX_STRAEM_BUNDLE] = {NULL}; 965 uint8_t num_streams_to_start = num_streams; 966 uint32_t streams_to_start[MM_CAMEAR_MAX_STRAEM_BUNDLE]; 967 uint8_t bundle_to_start = 0; 968 969 /* check if any bundled stream to be start, 970 * then all bundled stream should be started */ 971 memcpy(streams_to_start, stream_ids, sizeof(uint32_t) * num_streams); 972 for (i=0; i < num_streams; i++) { 973 for (j=0; j < my_obj->bundle.superbuf_queue.num_streams; j++) { 974 if (stream_ids[i] == my_obj->bundle.superbuf_queue.bundled_streams[j]) { 975 bundle_to_start = 1; 976 break; 977 } 978 } 979 } 980 981 if (bundle_to_start) { 982 uint8_t need_add; 983 /* add bundled streams into the start list if not already added*/ 984 for (i=0; i<my_obj->bundle.superbuf_queue.num_streams; i++) { 985 need_add = 1; 986 for (j=0; j<num_streams; j++) { 987 if (stream_ids[j] == my_obj->bundle.superbuf_queue.bundled_streams[i]) { 988 need_add = 0; 989 break; 990 } 991 } 992 if (need_add) { 993 streams_to_start[num_streams_to_start++] = 994 my_obj->bundle.superbuf_queue.bundled_streams[i]; 995 } 996 } 997 } 998 999 /* check if all streams to be started are valid */ 1000 for (i=0; i<num_streams_to_start; i++) { 1001 s_objs[i] = mm_channel_util_get_stream_by_handler(my_obj, streams_to_start[i]); 1002 1003 if (NULL == s_objs[i]) { 1004 CDBG_ERROR("%s: invalid stream handler %d (idx=%d) to be started", 1005 __func__, streams_to_start[i], i); 1006 return -1; 1007 } 1008 } 1009 1010 for (i=0; i<num_streams_to_start; i++) { 1011 /* if stream is already started, there is no need to start it */ 1012 if (s_objs[i]->state == MM_STREAM_STATE_ACTIVE_STREAM_ON || 1013 s_objs[i]->state == MM_STREAM_STATE_ACTIVE_STREAM_OFF) { 1014 continue; 1015 } 1016 1017 /* allocate buf */ 1018 rc = mm_stream_fsm_fn(s_objs[i], 1019 MM_STREAM_EVT_GET_BUF, 1020 NULL, 1021 NULL); 1022 if (0 != rc) { 1023 CDBG_ERROR("%s: get buf failed at idx(%d)", __func__, i); 1024 break; 1025 } 1026 1027 /* reg buf */ 1028 rc = mm_stream_fsm_fn(s_objs[i], 1029 MM_STREAM_EVT_REG_BUF, 1030 NULL, 1031 NULL); 1032 if (0 != rc) { 1033 CDBG_ERROR("%s: reg buf failed at idx(%d)", __func__, i); 1034 break; 1035 } 1036 1037 /* start stream */ 1038 rc = mm_stream_fsm_fn(s_objs[i], 1039 MM_STREAM_EVT_START, 1040 NULL, 1041 NULL); 1042 if (0 != rc) { 1043 CDBG_ERROR("%s: start stream failed at idx(%d)", __func__, i); 1044 break; 1045 } 1046 } 1047 1048 /* error handling */ 1049 if (0 != rc) { 1050 for (j=0; j<=i; j++) { 1051 /* stop streams*/ 1052 mm_stream_fsm_fn(s_objs[i], 1053 MM_STREAM_EVT_STOP, 1054 NULL, 1055 NULL); 1056 1057 /* unreg buf */ 1058 mm_stream_fsm_fn(s_objs[i], 1059 MM_STREAM_EVT_UNREG_BUF, 1060 NULL, 1061 NULL); 1062 1063 /* put buf back */ 1064 mm_stream_fsm_fn(s_objs[i], 1065 MM_STREAM_EVT_PUT_BUF, 1066 NULL, 1067 NULL); 1068 } 1069 } 1070 1071 return rc; 1072 } 1073 1074 /* Required: bundled streams need to be stopped together */ 1075 int32_t mm_channel_stop_streams(mm_channel_t *my_obj, 1076 uint8_t num_streams, 1077 uint32_t *stream_ids, 1078 uint8_t tear_down_flag) 1079 { 1080 int32_t rc = 0; 1081 int i, j; 1082 mm_stream_t* s_objs[MM_CAMEAR_MAX_STRAEM_BUNDLE] = {NULL}; 1083 uint8_t num_streams_to_stop = num_streams; 1084 uint32_t streams_to_stop[MM_CAMEAR_MAX_STRAEM_BUNDLE]; 1085 uint8_t bundle_to_stop = 0; 1086 1087 /* make sure bundled streams are stopped together */ 1088 memcpy(streams_to_stop, stream_ids, sizeof(uint32_t) * num_streams); 1089 for (i=0; i<num_streams; i++) { 1090 for (j=0; j<my_obj->bundle.superbuf_queue.num_streams; j++) { 1091 if (stream_ids[i] == my_obj->bundle.superbuf_queue.bundled_streams[j]) { 1092 bundle_to_stop = 1; 1093 break; 1094 } 1095 } 1096 } 1097 if (bundle_to_stop) { 1098 /* first stop bundle thread */ 1099 mm_camera_cmd_thread_stop(&my_obj->cmd_thread); 1100 mm_camera_cmd_thread_stop(&my_obj->cb_thread); 1101 1102 uint8_t need_add; 1103 /* add bundled streams into the start list if not already added*/ 1104 for (i=0; i<my_obj->bundle.superbuf_queue.num_streams; i++) { 1105 need_add = 1; 1106 for (j=0; j<num_streams; j++) { 1107 if (stream_ids[j] == my_obj->bundle.superbuf_queue.bundled_streams[i]) { 1108 need_add = 0; 1109 break; 1110 } 1111 } 1112 if (need_add) { 1113 streams_to_stop[num_streams_to_stop++] = 1114 my_obj->bundle.superbuf_queue.bundled_streams[i]; 1115 } 1116 } 1117 } 1118 1119 for (i=0; i<num_streams_to_stop; i++) { 1120 s_objs[i] = mm_channel_util_get_stream_by_handler(my_obj, streams_to_stop[i]); 1121 1122 if (NULL != s_objs[i]) { 1123 /* stream off */ 1124 mm_stream_fsm_fn(s_objs[i], 1125 MM_STREAM_EVT_STOP, 1126 NULL, 1127 NULL); 1128 1129 /* unreg buf at kernel */ 1130 mm_stream_fsm_fn(s_objs[i], 1131 MM_STREAM_EVT_UNREG_BUF, 1132 NULL, 1133 NULL); 1134 } 1135 } 1136 1137 /* destroy super buf cmd thread */ 1138 if (bundle_to_stop) { 1139 /* first stop bundle thread */ 1140 mm_camera_cmd_thread_destroy(&my_obj->cmd_thread); 1141 mm_camera_cmd_thread_destroy(&my_obj->cb_thread); 1142 } 1143 1144 /* since all streams are stopped, we are safe to 1145 * release all buffers allocated in stream */ 1146 for (i=0; i<num_streams_to_stop; i++) { 1147 if (NULL != s_objs[i]) { 1148 /* put buf back */ 1149 mm_stream_fsm_fn(s_objs[i], 1150 MM_STREAM_EVT_PUT_BUF, 1151 NULL, 1152 NULL); 1153 1154 if (tear_down_flag) { 1155 /* to tear down stream totally, stream needs to be released */ 1156 mm_stream_fsm_fn(s_objs[i], 1157 MM_STREAM_EVT_RELEASE, 1158 NULL, 1159 NULL); 1160 } 1161 } 1162 } 1163 1164 return rc; 1165 } 1166 1167 int32_t mm_channel_request_super_buf(mm_channel_t *my_obj, uint32_t num_buf_requested) 1168 { 1169 int32_t rc = 0; 1170 mm_camera_cmdcb_t* node = NULL; 1171 1172 /* set pending_cnt 1173 * will trigger dispatching super frames if pending_cnt > 0 */ 1174 /* send sem_post to wake up cmd thread to dispatch super buffer */ 1175 node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t)); 1176 if (NULL != node) { 1177 memset(node, 0, sizeof(mm_camera_cmdcb_t)); 1178 node->cmd_type = MM_CAMERA_CMD_TYPE_REQ_DATA_CB; 1179 node->u.req_buf.num_buf_requested = num_buf_requested; 1180 1181 /* enqueue to cmd thread */ 1182 mm_camera_queue_enq(&(my_obj->cmd_thread.cmd_queue), node); 1183 1184 /* wake up cmd thread */ 1185 sem_post(&(my_obj->cmd_thread.cmd_sem)); 1186 } else { 1187 CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__); 1188 rc = -1; 1189 } 1190 1191 return rc; 1192 } 1193 1194 int32_t mm_channel_cancel_super_buf_request(mm_channel_t *my_obj) 1195 { 1196 int32_t rc = 0; 1197 /* reset pending_cnt */ 1198 my_obj->pending_cnt = 0; 1199 1200 return rc; 1201 } 1202 1203 int32_t mm_channel_qbuf(mm_channel_t *my_obj, 1204 mm_camera_buf_def_t *buf) 1205 { 1206 int32_t rc = -1; 1207 mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj, buf->stream_id); 1208 1209 if (NULL != s_obj) { 1210 rc = mm_stream_fsm_fn(s_obj, 1211 MM_STREAM_EVT_QBUF, 1212 (void *)buf, 1213 NULL); 1214 } 1215 1216 return rc; 1217 } 1218 1219 int32_t mm_channel_start_focus(mm_channel_t *my_obj, 1220 uint32_t sensor_idx, 1221 uint32_t focus_mode) 1222 { 1223 return mm_camera_send_native_ctrl_cmd(my_obj->cam_obj, 1224 CAMERA_SET_PARM_AUTO_FOCUS, 1225 sizeof(uint32_t), (void*)focus_mode); 1226 } 1227 1228 int32_t mm_channel_abort_focus(mm_channel_t *my_obj, uint32_t sensor_idx) 1229 { 1230 return mm_camera_send_native_ctrl_cmd(my_obj->cam_obj, 1231 CAMERA_AUTO_FOCUS_CANCEL, 1232 0, NULL); 1233 } 1234 1235 int32_t mm_channel_prepare_snapshot(mm_channel_t *my_obj, uint32_t sensor_idx) 1236 { 1237 return mm_camera_send_native_ctrl_timeout_cmd(my_obj->cam_obj, 1238 CAMERA_PREPARE_SNAPSHOT, 1239 0, NULL, 2000); 1240 } 1241 1242 int32_t mm_channel_set_stream_parm(mm_channel_t *my_obj, 1243 uint32_t s_id, 1244 void *value) 1245 { 1246 int32_t rc = -1; 1247 mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj, s_id); 1248 if (NULL != s_obj) { 1249 rc = mm_stream_fsm_fn(s_obj, 1250 MM_STREAM_EVT_SET_PARM, 1251 value, 1252 NULL); 1253 } 1254 1255 return rc; 1256 } 1257 1258 int32_t mm_channel_get_stream_parm(mm_channel_t *my_obj, 1259 uint32_t s_id, 1260 void *value) 1261 { 1262 int32_t rc = -1; 1263 mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj, s_id); 1264 if (NULL != s_obj) { 1265 rc = mm_stream_fsm_fn(s_obj, 1266 MM_STREAM_EVT_GET_PARM, 1267 NULL, 1268 value); 1269 } 1270 1271 return rc; 1272 } 1273 1274 int32_t mm_channel_do_post_processing(mm_channel_t *my_obj, 1275 mm_channel_queue_node_t *super_buf) 1276 { 1277 int32_t rc = 0; 1278 uint8_t pp_mask = 0; 1279 1280 pp_mask = mm_camera_util_get_pp_mask(my_obj->cam_obj); 1281 1282 if (pp_mask & CAMERA_PP_MASK_TYPE_WNR) { 1283 mm_camera_wnr_info_t wnr_info; 1284 uint8_t i, j = 0; 1285 mm_stream_t* s_obj = NULL; 1286 1287 memset(&wnr_info, 0, sizeof(mm_camera_wnr_info_t)); 1288 for (i = 0; i < super_buf->num_of_bufs; i++) { 1289 s_obj = mm_channel_util_get_stream_by_handler(my_obj, super_buf->super_buf[i].stream_id); 1290 if (NULL != s_obj) { 1291 wnr_info.frames[j].instance_hdl = s_obj->inst_hdl; 1292 wnr_info.frames[j].frame_idx = super_buf->super_buf[i].buf->buf_idx; 1293 wnr_info.frames[j].frame_width = s_obj->fmt.width; 1294 wnr_info.frames[j].frame_height = s_obj->fmt.height; 1295 memcpy(&wnr_info.frames[j].frame_offset, 1296 &s_obj->frame_offset, 1297 sizeof(cam_frame_len_offset_t)); 1298 j++; 1299 } 1300 } 1301 wnr_info.num_frames = j; 1302 1303 rc = mm_camera_send_native_ctrl_cmd(my_obj->cam_obj, 1304 CAMERA_DO_PP_WNR, 1305 sizeof(mm_camera_wnr_info_t), 1306 (void *)&wnr_info); 1307 if (0 != rc) { 1308 CDBG_ERROR("%s: do_pp_wnr failed (rc=%d)", __func__, rc); 1309 } 1310 } 1311 1312 return rc; 1313 } 1314 1315 int32_t mm_channel_reg_stream_cb(mm_channel_t *my_obj, 1316 mm_stream_data_cb_t *cb, 1317 uint32_t ext_image_mode, 1318 uint32_t sensor_idx) 1319 { 1320 uint8_t idx; 1321 mm_stream_t *dest_stream = NULL; 1322 int32_t rc = -1; 1323 1324 /* browse all streams in channel to find the destination */ 1325 for (idx=0; idx < MM_CAMEAR_STRAEM_NUM_MAX; idx++) { 1326 if (my_obj->streams[idx].state != MM_STREAM_STATE_NOTUSED && 1327 my_obj->streams[idx].ext_image_mode == ext_image_mode && 1328 my_obj->streams[idx].sensor_idx == sensor_idx) { 1329 /* find matching stream as the destination */ 1330 dest_stream = &my_obj->streams[idx]; 1331 break; 1332 } 1333 } 1334 1335 if (NULL != dest_stream) { 1336 rc = mm_stream_reg_buf_cb(dest_stream, cb); 1337 } 1338 1339 return rc; 1340 } 1341 1342 int32_t mm_channel_superbuf_queue_init(mm_channel_queue_t * queue) 1343 { 1344 return mm_camera_queue_init(&queue->que); 1345 } 1346 1347 int32_t mm_channel_superbuf_queue_deinit(mm_channel_t *my_obj, 1348 mm_channel_queue_t * queue) 1349 { 1350 return mm_camera_queue_deinit(&queue->que); 1351 } 1352 1353 int8_t mm_channel_util_seq_comp_w_rollover(uint32_t v1, 1354 uint32_t v2) 1355 { 1356 int8_t ret = 0; 1357 1358 /* TODO: need to handle the case if v2 roll over to 0 */ 1359 if (v1 > v2) { 1360 ret = 1; 1361 } else if (v1 < v2) { 1362 ret = -1; 1363 } 1364 1365 return ret; 1366 } 1367 1368 int32_t mm_channel_superbuf_comp_and_enqueue( 1369 mm_channel_t* ch_obj, 1370 mm_channel_queue_t * queue, 1371 mm_camera_buf_info_t *buf_info) 1372 { 1373 mm_camera_q_node_t* node = NULL; 1374 struct cam_list *head = NULL; 1375 struct cam_list *pos = NULL; 1376 mm_channel_queue_node_t* super_buf = NULL; 1377 uint8_t buf_s_idx, i; 1378 1379 CDBG("%s: E", __func__); 1380 for (buf_s_idx=0; buf_s_idx < queue->num_streams; buf_s_idx++) { 1381 if (buf_info->stream_id == queue->bundled_streams[buf_s_idx]) { 1382 break; 1383 } 1384 } 1385 if (buf_s_idx == queue->num_streams) { 1386 CDBG_ERROR("%s: buf from stream (%d) not bundled", __func__, buf_info->stream_id); 1387 return -1; 1388 } 1389 1390 if (mm_channel_util_seq_comp_w_rollover(buf_info->frame_idx, 1391 queue->expected_frame_id) < 0) { 1392 /* incoming buf is older than expected buf id, will discard it */ 1393 mm_channel_qbuf(ch_obj, buf_info->buf); 1394 return 0; 1395 } 1396 1397 if (MM_CAMERA_SUPER_BUF_PRIORITY_NORMAL != queue->attr.priority) { 1398 /* TODO */ 1399 /* need to decide if we want to queue the frame based on focus or exposure 1400 * if frame not to be queued, we need to qbuf it back */ 1401 } 1402 1403 /* comp */ 1404 pthread_mutex_lock(&queue->que.lock); 1405 head = &queue->que.head.list; 1406 /* get the last one in the queue which is possibly having no matching */ 1407 pos = head->next; 1408 while (pos != head) { 1409 node = member_of(pos, mm_camera_q_node_t, list); 1410 super_buf = (mm_channel_queue_node_t*)node->data; 1411 if (NULL != super_buf) { 1412 if (super_buf->matched) { 1413 /* find a matched super buf, move to next one */ 1414 pos = pos->next; 1415 continue; 1416 } else { 1417 /* have an unmatched super buf, break the loop */ 1418 break; 1419 } 1420 } 1421 } 1422 1423 if (pos == head) { 1424 CDBG("%s: all nodes in queue are mtached, or no node in queue, create a new node", __func__); 1425 /* all nodes in queue are mtached, or no node in queue 1426 * create a new node */ 1427 mm_channel_queue_node_t *new_buf = NULL; 1428 mm_camera_q_node_t* new_node = NULL; 1429 1430 new_buf = (mm_channel_queue_node_t*)malloc(sizeof(mm_channel_queue_node_t)); 1431 new_node = (mm_camera_q_node_t*)malloc(sizeof(mm_camera_q_node_t)); 1432 if (NULL != new_buf && NULL != new_node) { 1433 memset(new_buf, 0, sizeof(mm_channel_queue_node_t)); 1434 memset(new_node, 0, sizeof(mm_camera_q_node_t)); 1435 new_node->data = (void *)new_buf; 1436 new_buf->num_of_bufs = queue->num_streams; 1437 memcpy(&new_buf->super_buf[buf_s_idx], buf_info, sizeof(mm_camera_buf_info_t)); 1438 1439 /* enqueue */ 1440 //cam_list_add_tail_node(&node->list, &queue->que.head.list); 1441 cam_list_add_tail_node(&new_node->list, &queue->que.head.list); 1442 queue->que.size++; 1443 1444 if(queue->num_streams == 1) { 1445 //TODO : Check. Live snapshot will have one stream in bundle? 1446 new_buf->matched = 1; 1447 1448 if (new_buf->matched) { 1449 queue->expected_frame_id = buf_info->frame_idx + queue->attr.post_frame_skip; 1450 queue->match_cnt++; 1451 } 1452 } 1453 } else { 1454 /* No memory */ 1455 if (NULL != new_buf) { 1456 free(new_buf); 1457 } 1458 if (NULL != new_node) { 1459 free(new_node); 1460 } 1461 /* qbuf the new buf since we cannot enqueue */ 1462 mm_channel_qbuf(ch_obj, buf_info->buf); 1463 } 1464 } else { 1465 CDBG("%s: find an unmatched super buf", __func__); 1466 /* find an unmatched super buf */ 1467 if (super_buf->super_buf[buf_s_idx].frame_idx == 0) { 1468 /* new frame from the stream_id */ 1469 uint8_t is_new = 1; 1470 uint32_t frame_idx; 1471 1472 for (i=0; i < super_buf->num_of_bufs; i++) { 1473 //for (i=0; i < buf_s_idx; i++) { 1474 if(super_buf->super_buf[i].buf == NULL) { 1475 continue; 1476 } 1477 frame_idx = super_buf->super_buf[i].buf->frame_idx; 1478 if (frame_idx == 0) { 1479 continue; 1480 } 1481 if (frame_idx < buf_info->frame_idx) { 1482 /* existing frame is older than the new frame, qbuf it */ 1483 mm_channel_qbuf(ch_obj, super_buf->super_buf[i].buf); 1484 memset(&super_buf->super_buf[i], 0, sizeof(mm_camera_buf_info_t)); 1485 } else if (frame_idx > buf_info->frame_idx) { 1486 /* new frame is older */ 1487 is_new = 0; 1488 break; 1489 }else{ 1490 //TODO: reveiw again 1491 break; 1492 } 1493 } 1494 if (is_new) { 1495 CDBG("%s: add stream = %d frame id = %d ", 1496 __func__, buf_info->stream_id, buf_info->frame_idx); 1497 memcpy(&super_buf->super_buf[buf_s_idx], buf_info, sizeof(mm_camera_buf_info_t)); 1498 1499 /* check if superbuf is all matched */ 1500 super_buf->matched = 1; 1501 for (i=0; i < super_buf->num_of_bufs; i++) { 1502 if (super_buf->super_buf[i].frame_idx == 0) { 1503 super_buf->matched = 0; 1504 break; 1505 } 1506 } 1507 1508 if (super_buf->matched) { 1509 queue->expected_frame_id = buf_info->frame_idx + queue->attr.post_frame_skip; 1510 queue->match_cnt++; 1511 CDBG("%s, match_cnt = %d", __func__, queue->match_cnt); 1512 } 1513 } else { 1514 mm_channel_qbuf(ch_obj, buf_info->buf); 1515 } 1516 } else { 1517 if (super_buf->super_buf[buf_s_idx].frame_idx < buf_info->frame_idx) { 1518 CDBG("%s: new frame is newer, add into superbuf", __func__); 1519 /* current frames in superbuf are older than the new frame 1520 * qbuf all current frames */ 1521 for (i=0; i<super_buf->num_of_bufs; i++) { 1522 if (super_buf->super_buf[i].frame_idx != 0) { 1523 mm_channel_qbuf(ch_obj, super_buf->super_buf[i].buf); 1524 memset(&super_buf->super_buf[i], 0, sizeof(mm_camera_buf_info_t)); 1525 } 1526 } 1527 /* add the new frame into the superbuf */ 1528 memcpy(&super_buf->super_buf[buf_s_idx], buf_info, sizeof(mm_camera_buf_info_t)); 1529 } else { 1530 /* the new frame is older, just ignor */ 1531 mm_channel_qbuf(ch_obj, buf_info->buf); 1532 } 1533 } 1534 } 1535 pthread_mutex_unlock(&queue->que.lock); 1536 1537 CDBG("%s: X", __func__); 1538 return 0; 1539 } 1540 1541 mm_channel_queue_node_t* mm_channel_superbuf_dequeue_internal(mm_channel_queue_t * queue) 1542 { 1543 mm_camera_q_node_t* node = NULL; 1544 struct cam_list *head = NULL; 1545 struct cam_list *pos = NULL; 1546 mm_channel_queue_node_t* super_buf = NULL; 1547 1548 head = &queue->que.head.list; 1549 pos = head->next; 1550 if (pos != head) { 1551 /* get the first node */ 1552 node = member_of(pos, mm_camera_q_node_t, list); 1553 super_buf = (mm_channel_queue_node_t*)node->data; 1554 if (NULL != super_buf) { 1555 if (super_buf->matched) { 1556 /* we found a mtaching super buf, dequeue it */ 1557 cam_list_del_node(&node->list); 1558 queue->que.size--; 1559 queue->match_cnt--; 1560 free(node); 1561 } else { 1562 super_buf = NULL; 1563 } 1564 } 1565 } 1566 1567 return super_buf; 1568 } 1569 1570 mm_channel_queue_node_t* mm_channel_superbuf_dequeue(mm_channel_queue_t * queue) 1571 { 1572 mm_camera_q_node_t* node = NULL; 1573 struct cam_list *head = NULL; 1574 struct cam_list *pos = NULL; 1575 mm_channel_queue_node_t* super_buf = NULL; 1576 1577 pthread_mutex_lock(&queue->que.lock); 1578 super_buf = mm_channel_superbuf_dequeue_internal(queue); 1579 pthread_mutex_unlock(&queue->que.lock); 1580 1581 return super_buf; 1582 } 1583 1584 int32_t mm_channel_superbuf_bufdone_overflow(mm_channel_t* my_obj, 1585 mm_channel_queue_t * queue) 1586 { 1587 int32_t rc = 0, i; 1588 mm_channel_queue_node_t* super_buf = NULL; 1589 if (MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS == queue->attr.notify_mode) { 1590 /* for continuous streaming mode, no overflow is needed */ 1591 return 0; 1592 } 1593 1594 CDBG("%s: before match_cnt=%d, water_mark=%d", 1595 __func__, queue->match_cnt, queue->attr.water_mark); 1596 /* bufdone overflowed bufs */ 1597 pthread_mutex_lock(&queue->que.lock); 1598 while (queue->match_cnt > queue->attr.water_mark) { 1599 super_buf = mm_channel_superbuf_dequeue_internal(queue); 1600 if (NULL != super_buf) { 1601 for (i=0; i<super_buf->num_of_bufs; i++) { 1602 if (NULL != super_buf->super_buf[i].buf) { 1603 mm_channel_qbuf(my_obj, super_buf->super_buf[i].buf); 1604 } 1605 } 1606 free(super_buf); 1607 } 1608 } 1609 pthread_mutex_unlock(&queue->que.lock); 1610 CDBG("%s: after match_cnt=%d, water_mark=%d", 1611 __func__, queue->match_cnt, queue->attr.water_mark); 1612 1613 return rc; 1614 } 1615 1616 int32_t mm_channel_superbuf_skip(mm_channel_t* my_obj, 1617 mm_channel_queue_t * queue) 1618 { 1619 int32_t rc = 0, i, count; 1620 mm_channel_queue_node_t* super_buf = NULL; 1621 if (MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS == queue->attr.notify_mode) { 1622 /* for continuous streaming mode, no skip is needed */ 1623 return 0; 1624 } 1625 1626 /* bufdone overflowed bufs */ 1627 pthread_mutex_lock(&queue->que.lock); 1628 while (queue->match_cnt > queue->attr.look_back) { 1629 super_buf = mm_channel_superbuf_dequeue_internal(queue); 1630 if (NULL != super_buf) { 1631 for (i=0; i<super_buf->num_of_bufs; i++) { 1632 if (NULL != super_buf->super_buf[i].buf) { 1633 mm_channel_qbuf(my_obj, super_buf->super_buf[i].buf); 1634 } 1635 } 1636 free(super_buf); 1637 } 1638 } 1639 pthread_mutex_unlock(&queue->que.lock); 1640 1641 return rc; 1642 } 1643 1644 uint32_t mm_channel_open_repro_isp(mm_channel_t *my_obj, 1645 mm_camera_repro_isp_type_t isp_type) 1646 { 1647 int32_t rc = -1; 1648 mm_camera_repro_cmd_t repro_cmd; 1649 1650 memset(&repro_cmd, 0, sizeof(mm_camera_repro_cmd_t)); 1651 repro_cmd.cmd = MM_CAMERA_REPRO_CMD_OPEN; 1652 repro_cmd.payload.open.isp_type = isp_type; 1653 rc = mm_camera_send_native_ctrl_cmd(my_obj->cam_obj, 1654 CAMERA_SEND_PP_PIPELINE_CMD, 1655 sizeof(mm_camera_repro_cmd_t), 1656 (void *)&repro_cmd); 1657 if (0 != rc) { 1658 CDBG_ERROR("%s: open repo isp failed (rc=%d)", __func__, rc); 1659 } 1660 return repro_cmd.payload.open.repro_handle; 1661 } 1662 1663 int32_t mm_channel_close_repro_isp(mm_channel_t *my_obj, 1664 uint32_t repro_handle) 1665 { 1666 int32_t rc = -1; 1667 mm_camera_repro_cmd_t repro_cmd; 1668 1669 memset(&repro_cmd, 0, sizeof(mm_camera_repro_cmd_t)); 1670 repro_cmd.cmd = MM_CAMERA_REPRO_CMD_CLOSE; 1671 repro_cmd.payload.repro_handle = repro_handle; 1672 rc = mm_camera_send_native_ctrl_cmd(my_obj->cam_obj, 1673 CAMERA_SEND_PP_PIPELINE_CMD, 1674 sizeof(mm_camera_repro_cmd_t), 1675 (void *)&repro_cmd); 1676 if (0 != rc) { 1677 CDBG_ERROR("%s: close repo isp failed (rc=%d)", __func__, rc); 1678 } 1679 return rc; 1680 } 1681 1682 int32_t mm_channel_config_repro_isp(mm_channel_t *my_obj, 1683 uint32_t repro_handle, 1684 mm_camera_repro_isp_config_t *config) 1685 { 1686 int32_t rc = -1; 1687 mm_camera_repro_cmd_t repro_cmd; 1688 mm_stream_t *src_stream = NULL; 1689 mm_stream_t *dest_streams[MM_CAMERA_MAX_NUM_REPROCESS_DEST]; 1690 uint8_t i; 1691 1692 /* first check if src and dest streams are valid */ 1693 src_stream = mm_channel_util_get_stream_by_handler(my_obj, config->src.inst_handle); 1694 if (NULL == src_stream) { 1695 CDBG_ERROR("%s: src stream obj not found %d", __func__, config->src.inst_handle); 1696 return -1; 1697 } 1698 for (i = 0; i < config->num_dest; i++) { 1699 dest_streams[i] = 1700 mm_channel_util_get_stream_by_handler(my_obj, config->dest[i].inst_handle); 1701 if (NULL == dest_streams[i]) { 1702 CDBG_ERROR("%s: dest stream obj not found %d", __func__, config->dest[i].inst_handle); 1703 return -1; 1704 } 1705 } 1706 1707 /* fill in config */ 1708 memset(&repro_cmd, 0, sizeof(mm_camera_repro_cmd_t)); 1709 repro_cmd.cmd = MM_CAMERA_REPRO_CMD_CONFIG; 1710 repro_cmd.payload.config.repro_handle = repro_handle; 1711 /* using instant handler which can be understandable by mctl */ 1712 repro_cmd.payload.config.src.inst_handle = src_stream->inst_hdl; 1713 /* translate to V4L2 ext image mode */ 1714 repro_cmd.payload.config.src.image_mode = 1715 mm_channel_get_ext_mode_from_img_mode(config->src.image_mode); 1716 repro_cmd.payload.config.src.format = config->src.format; 1717 repro_cmd.payload.config.src.width = config->src.width; 1718 repro_cmd.payload.config.src.height = config->src.height; 1719 CDBG("%s: src: inst_hdl=0x%x, image_mode=%d, format=%d, width x height=%dx%d", 1720 __func__, 1721 repro_cmd.payload.config.src.inst_handle, 1722 repro_cmd.payload.config.src.image_mode, 1723 repro_cmd.payload.config.src.format, 1724 repro_cmd.payload.config.src.width, 1725 repro_cmd.payload.config.src.height); 1726 repro_cmd.payload.config.num_dest = config->num_dest; 1727 for (i = 0; i < repro_cmd.payload.config.num_dest; i++) { 1728 /* using instant handler which can be understandable by mctl */ 1729 repro_cmd.payload.config.dest[i].inst_handle = dest_streams[i]->inst_hdl; 1730 /* translate into V4L2 ext image mode */ 1731 repro_cmd.payload.config.dest[i].image_mode = 1732 mm_channel_get_ext_mode_from_img_mode(config->dest[i].image_mode); 1733 repro_cmd.payload.config.dest[i].format = config->dest[i].format; 1734 repro_cmd.payload.config.dest[i].width = config->dest[i].width; 1735 repro_cmd.payload.config.dest[i].height = config->dest[i].height; 1736 CDBG("%s: dest %d: inst_hdl=0x%x, image_mode=%d, format=%d, width x height=%dx%d", 1737 __func__, i, 1738 repro_cmd.payload.config.dest[i].inst_handle, 1739 repro_cmd.payload.config.dest[i].image_mode, 1740 repro_cmd.payload.config.dest[i].format, 1741 repro_cmd.payload.config.dest[i].width, 1742 repro_cmd.payload.config.dest[i].height); 1743 } 1744 rc = mm_camera_send_native_ctrl_cmd(my_obj->cam_obj, 1745 CAMERA_SEND_PP_PIPELINE_CMD, 1746 sizeof(mm_camera_repro_cmd_t), 1747 (void *)&repro_cmd); 1748 if (0 != rc) { 1749 CDBG_ERROR("%s: config repo isp failed (rc=%d)", __func__, rc); 1750 } 1751 return rc; 1752 } 1753 1754 int32_t mm_channel_repro_isp_dest_stream_ops(mm_channel_t *my_obj, 1755 uint32_t repro_handle, 1756 uint32_t stream_handle, 1757 uint8_t attach_flag) 1758 { 1759 int32_t rc = -1; 1760 mm_stream_t *stream_obj = NULL; 1761 mm_camera_repro_cmd_t repro_cmd; 1762 1763 /* first check if streams are valid */ 1764 stream_obj = mm_channel_util_get_stream_by_handler(my_obj, stream_handle); 1765 if (NULL == stream_obj) { 1766 CDBG_ERROR("%s: stream obj not found %d", __func__, stream_handle); 1767 return -1; 1768 } 1769 1770 memset(&repro_cmd, 0, sizeof(mm_camera_repro_cmd_t)); 1771 repro_cmd.cmd = MM_CAMERA_REPRO_CMD_ATTACH_DETACH; 1772 repro_cmd.payload.attach_detach.repro_handle = repro_handle; 1773 repro_cmd.payload.attach_detach.attach_flag = attach_flag; 1774 repro_cmd.payload.attach_detach.inst_handle = stream_obj->inst_hdl; 1775 rc = mm_camera_send_native_ctrl_cmd(my_obj->cam_obj, 1776 CAMERA_SEND_PP_PIPELINE_CMD, 1777 sizeof(mm_camera_repro_cmd_t), 1778 (void *)&repro_cmd); 1779 if (0 != rc) { 1780 CDBG_ERROR("%s: repo isp stream operation failed (flag=%d, rc=%d)", 1781 __func__, attach_flag, rc); 1782 } 1783 return rc; 1784 } 1785 1786 int32_t mm_channel_repro_isp_ops(mm_channel_t *my_obj, 1787 uint32_t repro_handle, 1788 uint32_t stream_id, 1789 uint8_t start_flag) 1790 { 1791 int32_t rc = -1; 1792 mm_camera_repro_cmd_t repro_cmd; 1793 mm_stream_t *stream_obj = NULL; 1794 1795 /* first check if streams are valid */ 1796 stream_obj = mm_channel_util_get_stream_by_handler(my_obj, stream_id); 1797 if (NULL == stream_obj) { 1798 CDBG_ERROR("%s: stream obj not found %d", __func__, stream_id); 1799 return -1; 1800 } 1801 1802 memset(&repro_cmd, 0, sizeof(mm_camera_repro_cmd_t)); 1803 repro_cmd.cmd = MM_CAMERA_REPRO_CMD_START_STOP; 1804 repro_cmd.payload.start_stop.repro_handle = repro_handle; 1805 repro_cmd.payload.start_stop.dest_handle = stream_obj->inst_hdl; 1806 repro_cmd.payload.start_stop.start_flag = start_flag; 1807 rc = mm_camera_send_native_ctrl_cmd(my_obj->cam_obj, 1808 CAMERA_SEND_PP_PIPELINE_CMD, 1809 sizeof(mm_camera_repro_cmd_t), 1810 (void *)&repro_cmd); 1811 if (0 != rc) { 1812 CDBG_ERROR("%s: repo isp stream operation failed (flag=%d, rc=%d)", 1813 __func__, start_flag, rc); 1814 } 1815 return rc; 1816 } 1817 1818 int32_t mm_channel_reprocess(mm_channel_t *my_obj, 1819 uint32_t repro_handle, 1820 mm_camera_repro_data_t *repro_data) 1821 { 1822 int32_t rc = -1; 1823 mm_camera_repro_cmd_t repro_cmd; 1824 mm_stream_t *stream_obj = NULL; 1825 uint8_t i; 1826 1827 /* check if input param is valid */ 1828 if (NULL == repro_data || NULL == repro_data->src_frame) { 1829 CDBG_ERROR("%s: invalid input param", __func__); 1830 return -1; 1831 } 1832 1833 /* check if streams are valid */ 1834 stream_obj = mm_channel_util_get_stream_by_handler(my_obj, 1835 repro_data->src_frame->stream_id); 1836 if (NULL == stream_obj) { 1837 CDBG_ERROR("%s: stream obj not found %d", 1838 __func__, repro_data->src_frame->stream_id); 1839 return -1; 1840 } 1841 1842 memset(&repro_cmd, 0, sizeof(mm_camera_repro_cmd_t)); 1843 repro_cmd.cmd = MM_CAMERA_REPRO_CMD_START_STOP; 1844 repro_cmd.payload.reprocess.repro_handle = repro_handle; 1845 repro_cmd.payload.reprocess.inst_handle = stream_obj->inst_hdl; 1846 repro_cmd.payload.reprocess.buf_idx = repro_data->src_frame->buf_idx; 1847 repro_cmd.payload.reprocess.frame_id = repro_data->src_frame->frame_idx; 1848 repro_cmd.payload.reprocess.frame_len = repro_data->src_frame->frame_len; 1849 repro_cmd.payload.reprocess.timestamp.tv_sec = 1850 repro_data->src_frame->ts.tv_sec; 1851 repro_cmd.payload.reprocess.timestamp.tv_usec = 1852 repro_data->src_frame->ts.tv_nsec/1000; 1853 repro_cmd.payload.reprocess.num_planes = repro_data->src_frame->num_planes; 1854 for (i = 0; i < repro_cmd.payload.reprocess.num_planes; i++) { 1855 repro_cmd.payload.reprocess.planes[i].addr_offset = 1856 repro_data->src_frame->planes[i].reserved[0]; 1857 repro_cmd.payload.reprocess.planes[i].data_offset = 1858 repro_data->src_frame->planes[i].data_offset; 1859 repro_cmd.payload.reprocess.planes[i].length = 1860 repro_data->src_frame->planes[i].length; 1861 } 1862 rc = mm_camera_send_native_ctrl_cmd(my_obj->cam_obj, 1863 CAMERA_SEND_PP_PIPELINE_CMD, 1864 sizeof(mm_camera_repro_cmd_t), 1865 (void *)&repro_cmd); 1866 if (0 != rc) { 1867 CDBG_ERROR("%s: do reprocess failed (rc=%d)", __func__, rc); 1868 } 1869 return rc; 1870 } 1871 1872