1 /* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. 2 * 3 * Redistribution and use in source and binary forms, with or without 4 * modification, are permitted provided that the following conditions are 5 * met: 6 * * Redistributions of source code must retain the above copyright 7 * notice, this list of conditions and the following disclaimer. 8 * * Redistributions in binary form must reproduce the above 9 * copyright notice, this list of conditions and the following 10 * disclaimer in the documentation and/or other materials provided 11 * with the distribution. 12 * * Neither the name of The Linux Foundation nor the names of its 13 * contributors may be used to endorse or promote products derived 14 * from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 */ 29 30 #include <pthread.h> 31 #include <errno.h> 32 #include <sys/ioctl.h> 33 #include <sys/types.h> 34 #include <sys/stat.h> 35 #include <fcntl.h> 36 #include <poll.h> 37 #include <time.h> 38 #include <cam_semaphore.h> 39 #ifdef VENUS_PRESENT 40 #include <media/msm_media_info.h> 41 #endif 42 43 #include "mm_camera_dbg.h" 44 #include "mm_camera_interface.h" 45 #include "mm_camera.h" 46 47 /* internal function decalre */ 48 int32_t mm_stream_qbuf(mm_stream_t *my_obj, 49 mm_camera_buf_def_t *buf); 50 int32_t mm_stream_set_ext_mode(mm_stream_t * my_obj); 51 int32_t mm_stream_set_fmt(mm_stream_t * my_obj); 52 int32_t mm_stream_sync_info(mm_stream_t *my_obj); 53 int32_t mm_stream_init_bufs(mm_stream_t * my_obj); 54 int32_t mm_stream_deinit_bufs(mm_stream_t * my_obj); 55 int32_t mm_stream_request_buf(mm_stream_t * my_obj); 56 int32_t mm_stream_unreg_buf(mm_stream_t * my_obj); 57 int32_t mm_stream_release(mm_stream_t *my_obj); 58 int32_t mm_stream_set_parm(mm_stream_t *my_obj, 59 cam_stream_parm_buffer_t *value); 60 int32_t mm_stream_get_parm(mm_stream_t *my_obj, 61 cam_stream_parm_buffer_t *value); 62 int32_t mm_stream_do_action(mm_stream_t *my_obj, 63 void *in_value); 64 int32_t mm_stream_streamon(mm_stream_t *my_obj); 65 int32_t mm_stream_streamoff(mm_stream_t *my_obj); 66 int32_t mm_stream_read_msm_frame(mm_stream_t * my_obj, 67 mm_camera_buf_info_t* buf_info, 68 uint8_t num_planes); 69 int32_t mm_stream_config(mm_stream_t *my_obj, 70 mm_camera_stream_config_t *config); 71 int32_t mm_stream_reg_buf(mm_stream_t * my_obj); 72 int32_t mm_stream_buf_done(mm_stream_t * my_obj, 73 mm_camera_buf_def_t *frame); 74 int32_t mm_stream_calc_offset(mm_stream_t *my_obj); 75 int32_t mm_stream_calc_offset_preview(cam_format_t fmt, 76 cam_dimension_t *dim, 77 cam_stream_buf_plane_info_t *buf_planes); 78 int32_t mm_stream_calc_offset_snapshot(cam_format_t fmt, 79 cam_dimension_t *dim, 80 cam_padding_info_t *padding, 81 cam_stream_buf_plane_info_t *buf_planes); 82 int32_t mm_stream_calc_offset_raw(cam_format_t fmt, 83 cam_dimension_t *dim, 84 cam_padding_info_t *padding, 85 cam_stream_buf_plane_info_t *buf_planes); 86 int32_t mm_stream_calc_offset_video(cam_dimension_t *dim, 87 cam_stream_buf_plane_info_t *buf_planes); 88 int32_t mm_stream_calc_offset_metadata(cam_dimension_t *dim, 89 cam_padding_info_t *padding, 90 cam_stream_buf_plane_info_t *buf_planes); 91 int32_t mm_stream_calc_offset_postproc(cam_stream_info_t *stream_info, 92 cam_padding_info_t *padding, 93 cam_stream_buf_plane_info_t *buf_planes); 94 95 96 /* state machine function declare */ 97 int32_t mm_stream_fsm_inited(mm_stream_t * my_obj, 98 mm_stream_evt_type_t evt, 99 void * in_val, 100 void * out_val); 101 int32_t mm_stream_fsm_acquired(mm_stream_t * my_obj, 102 mm_stream_evt_type_t evt, 103 void * in_val, 104 void * out_val); 105 int32_t mm_stream_fsm_cfg(mm_stream_t * my_obj, 106 mm_stream_evt_type_t evt, 107 void * in_val, 108 void * out_val); 109 int32_t mm_stream_fsm_buffed(mm_stream_t * my_obj, 110 mm_stream_evt_type_t evt, 111 void * in_val, 112 void * out_val); 113 int32_t mm_stream_fsm_reg(mm_stream_t * my_obj, 114 mm_stream_evt_type_t evt, 115 void * in_val, 116 void * out_val); 117 int32_t mm_stream_fsm_active(mm_stream_t * my_obj, 118 mm_stream_evt_type_t evt, 119 void * in_val, 120 void * out_val); 121 uint32_t mm_stream_get_v4l2_fmt(cam_format_t fmt); 122 123 124 /*=========================================================================== 125 * FUNCTION : mm_stream_handle_rcvd_buf 126 * 127 * DESCRIPTION: function to handle newly received stream buffer 128 * 129 * PARAMETERS : 130 * @cam_obj : stream object 131 * @buf_info: ptr to struct storing buffer information 132 * 133 * RETURN : none 134 *==========================================================================*/ 135 void mm_stream_handle_rcvd_buf(mm_stream_t *my_obj, 136 mm_camera_buf_info_t *buf_info, 137 uint8_t has_cb) 138 { 139 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d", 140 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state); 141 142 /* enqueue to super buf thread */ 143 if (my_obj->is_bundled) { 144 mm_camera_cmdcb_t* node = NULL; 145 146 /* send cam_sem_post to wake up channel cmd thread to enqueue to super buffer */ 147 node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t)); 148 if (NULL != node) { 149 memset(node, 0, sizeof(mm_camera_cmdcb_t)); 150 node->cmd_type = MM_CAMERA_CMD_TYPE_DATA_CB; 151 node->u.buf = *buf_info; 152 153 /* enqueue to cmd thread */ 154 cam_queue_enq(&(my_obj->ch_obj->cmd_thread.cmd_queue), node); 155 156 /* wake up cmd thread */ 157 cam_sem_post(&(my_obj->ch_obj->cmd_thread.cmd_sem)); 158 } else { 159 CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__); 160 } 161 } 162 163 if(has_cb) { 164 mm_camera_cmdcb_t* node = NULL; 165 166 /* send cam_sem_post to wake up cmd thread to dispatch dataCB */ 167 node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t)); 168 if (NULL != node) { 169 memset(node, 0, sizeof(mm_camera_cmdcb_t)); 170 node->cmd_type = MM_CAMERA_CMD_TYPE_DATA_CB; 171 node->u.buf = *buf_info; 172 173 /* enqueue to cmd thread */ 174 cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node); 175 176 /* wake up cmd thread */ 177 cam_sem_post(&(my_obj->cmd_thread.cmd_sem)); 178 } else { 179 CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__); 180 } 181 } 182 } 183 184 /*=========================================================================== 185 * FUNCTION : mm_stream_data_notify 186 * 187 * DESCRIPTION: callback to handle data notify from kernel 188 * 189 * PARAMETERS : 190 * @user_data : user data ptr (stream object) 191 * 192 * RETURN : none 193 *==========================================================================*/ 194 static void mm_stream_data_notify(void* user_data) 195 { 196 mm_stream_t *my_obj = (mm_stream_t*)user_data; 197 int32_t idx = -1, i, rc; 198 uint8_t has_cb = 0; 199 mm_camera_buf_info_t buf_info; 200 201 if (NULL == my_obj) { 202 return; 203 } 204 205 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d", 206 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state); 207 if (MM_STREAM_STATE_ACTIVE != my_obj->state) { 208 /* this Cb will only received in active_stream_on state 209 * if not so, return here */ 210 CDBG_ERROR("%s: ERROR!! Wrong state (%d) to receive data notify!", 211 __func__, my_obj->state); 212 return; 213 } 214 215 memset(&buf_info, 0, sizeof(mm_camera_buf_info_t)); 216 rc = mm_stream_read_msm_frame(my_obj, &buf_info, my_obj->frame_offset.num_planes); 217 if (rc != 0) { 218 return; 219 } 220 idx = buf_info.buf->buf_idx; 221 222 pthread_mutex_lock(&my_obj->cb_lock); 223 for (i = 0; i < MM_CAMERA_STREAM_BUF_CB_MAX; i++) { 224 if(NULL != my_obj->buf_cb[i].cb) { 225 /* for every CB, add ref count */ 226 has_cb = 1; 227 break; 228 } 229 } 230 pthread_mutex_unlock(&my_obj->cb_lock); 231 232 pthread_mutex_lock(&my_obj->buf_lock); 233 /* update buffer location */ 234 my_obj->buf_status[idx].in_kernel = 0; 235 236 /* update buf ref count */ 237 if (my_obj->is_bundled) { 238 /* need to add into super buf since bundled, add ref count */ 239 my_obj->buf_status[idx].buf_refcnt++; 240 } 241 my_obj->buf_status[idx].buf_refcnt += has_cb; 242 pthread_mutex_unlock(&my_obj->buf_lock); 243 244 mm_stream_handle_rcvd_buf(my_obj, &buf_info, has_cb); 245 } 246 247 /*=========================================================================== 248 * FUNCTION : mm_stream_dispatch_app_data 249 * 250 * DESCRIPTION: dispatch stream buffer to registered users 251 * 252 * PARAMETERS : 253 * @cmd_cb : ptr storing stream buffer information 254 * @userdata: user data ptr (stream object) 255 * 256 * RETURN : none 257 *==========================================================================*/ 258 static void mm_stream_dispatch_app_data(mm_camera_cmdcb_t *cmd_cb, 259 void* user_data) 260 { 261 int i; 262 mm_stream_t * my_obj = (mm_stream_t *)user_data; 263 mm_camera_buf_info_t* buf_info = NULL; 264 mm_camera_super_buf_t super_buf; 265 266 if (NULL == my_obj) { 267 return; 268 } 269 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d", 270 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state); 271 272 if (MM_CAMERA_CMD_TYPE_DATA_CB != cmd_cb->cmd_type) { 273 CDBG_ERROR("%s: Wrong cmd_type (%d) for dataCB", 274 __func__, cmd_cb->cmd_type); 275 return; 276 } 277 278 buf_info = &cmd_cb->u.buf; 279 memset(&super_buf, 0, sizeof(mm_camera_super_buf_t)); 280 super_buf.num_bufs = 1; 281 super_buf.bufs[0] = buf_info->buf; 282 super_buf.camera_handle = my_obj->ch_obj->cam_obj->my_hdl; 283 super_buf.ch_id = my_obj->ch_obj->my_hdl; 284 285 pthread_mutex_lock(&my_obj->cb_lock); 286 for(i = 0; i < MM_CAMERA_STREAM_BUF_CB_MAX; i++) { 287 if(NULL != my_obj->buf_cb[i].cb) { 288 if (my_obj->buf_cb[i].cb_count != 0) { 289 /* if <0, means infinite CB 290 * if >0, means CB for certain times 291 * both case we need to call CB */ 292 293 /* increase buf ref cnt */ 294 pthread_mutex_lock(&my_obj->buf_lock); 295 my_obj->buf_status[buf_info->buf->buf_idx].buf_refcnt++; 296 pthread_mutex_unlock(&my_obj->buf_lock); 297 298 /* callback */ 299 my_obj->buf_cb[i].cb(&super_buf, 300 my_obj->buf_cb[i].user_data); 301 } 302 303 /* if >0, reduce count by 1 every time we called CB until reaches 0 304 * when count reach 0, reset the buf_cb to have no CB */ 305 if (my_obj->buf_cb[i].cb_count > 0) { 306 my_obj->buf_cb[i].cb_count--; 307 if (0 == my_obj->buf_cb[i].cb_count) { 308 my_obj->buf_cb[i].cb = NULL; 309 my_obj->buf_cb[i].user_data = NULL; 310 } 311 } 312 } 313 } 314 pthread_mutex_unlock(&my_obj->cb_lock); 315 316 /* do buf_done since we increased refcnt by one when has_cb */ 317 mm_stream_buf_done(my_obj, buf_info->buf); 318 } 319 320 /*=========================================================================== 321 * FUNCTION : mm_stream_fsm_fn 322 * 323 * DESCRIPTION: stream finite state machine entry function. Depends on stream 324 * state, incoming event will be handled differently. 325 * 326 * PARAMETERS : 327 * @my_obj : ptr to a stream object 328 * @evt : stream event to be processed 329 * @in_val : input event payload. Can be NULL if not needed. 330 * @out_val : output payload, Can be NULL if not needed. 331 * 332 * RETURN : int32_t type of status 333 * 0 -- success 334 * -1 -- failure 335 *==========================================================================*/ 336 int32_t mm_stream_fsm_fn(mm_stream_t *my_obj, 337 mm_stream_evt_type_t evt, 338 void * in_val, 339 void * out_val) 340 { 341 int32_t rc = -1; 342 343 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d", 344 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state); 345 switch (my_obj->state) { 346 case MM_STREAM_STATE_NOTUSED: 347 CDBG("%s: Not handling evt in unused state", __func__); 348 break; 349 case MM_STREAM_STATE_INITED: 350 rc = mm_stream_fsm_inited(my_obj, evt, in_val, out_val); 351 break; 352 case MM_STREAM_STATE_ACQUIRED: 353 rc = mm_stream_fsm_acquired(my_obj, evt, in_val, out_val); 354 break; 355 case MM_STREAM_STATE_CFG: 356 rc = mm_stream_fsm_cfg(my_obj, evt, in_val, out_val); 357 break; 358 case MM_STREAM_STATE_BUFFED: 359 rc = mm_stream_fsm_buffed(my_obj, evt, in_val, out_val); 360 break; 361 case MM_STREAM_STATE_REG: 362 rc = mm_stream_fsm_reg(my_obj, evt, in_val, out_val); 363 break; 364 case MM_STREAM_STATE_ACTIVE: 365 rc = mm_stream_fsm_active(my_obj, evt, in_val, out_val); 366 break; 367 default: 368 CDBG("%s: Not a valid state (%d)", __func__, my_obj->state); 369 break; 370 } 371 CDBG("%s : X rc =%d",__func__,rc); 372 return rc; 373 } 374 375 /*=========================================================================== 376 * FUNCTION : mm_stream_fsm_inited 377 * 378 * DESCRIPTION: stream finite state machine function to handle event in INITED 379 * state. 380 * 381 * PARAMETERS : 382 * @my_obj : ptr to a stream object 383 * @evt : stream event to be processed 384 * @in_val : input event payload. Can be NULL if not needed. 385 * @out_val : output payload, Can be NULL if not needed. 386 * 387 * RETURN : int32_t type of status 388 * 0 -- success 389 * -1 -- failure 390 *==========================================================================*/ 391 int32_t mm_stream_fsm_inited(mm_stream_t *my_obj, 392 mm_stream_evt_type_t evt, 393 void * in_val, 394 void * out_val) 395 { 396 int32_t rc = 0; 397 char dev_name[MM_CAMERA_DEV_NAME_LEN]; 398 399 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d", 400 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state); 401 switch(evt) { 402 case MM_STREAM_EVT_ACQUIRE: 403 if ((NULL == my_obj->ch_obj) || (NULL == my_obj->ch_obj->cam_obj)) { 404 CDBG_ERROR("%s: NULL channel or camera obj\n", __func__); 405 rc = -1; 406 break; 407 } 408 409 snprintf(dev_name, sizeof(dev_name), "/dev/%s", 410 mm_camera_util_get_dev_name(my_obj->ch_obj->cam_obj->my_hdl)); 411 412 my_obj->fd = open(dev_name, O_RDWR | O_NONBLOCK); 413 if (my_obj->fd <= 0) { 414 CDBG_ERROR("%s: open dev returned %d\n", __func__, my_obj->fd); 415 rc = -1; 416 break; 417 } 418 CDBG("%s: open dev fd = %d\n", __func__, my_obj->fd); 419 rc = mm_stream_set_ext_mode(my_obj); 420 if (0 == rc) { 421 my_obj->state = MM_STREAM_STATE_ACQUIRED; 422 } else { 423 /* failed setting ext_mode 424 * close fd */ 425 close(my_obj->fd); 426 my_obj->fd = 0; 427 break; 428 } 429 break; 430 default: 431 CDBG_ERROR("%s: invalid state (%d) for evt (%d), in(%p), out(%p)", 432 __func__, my_obj->state, evt, in_val, out_val); 433 break; 434 } 435 return rc; 436 } 437 438 /*=========================================================================== 439 * FUNCTION : mm_stream_fsm_acquired 440 * 441 * DESCRIPTION: stream finite state machine function to handle event in AQUIRED 442 * state. 443 * 444 * PARAMETERS : 445 * @my_obj : ptr to a stream object 446 * @evt : stream event to be processed 447 * @in_val : input event payload. Can be NULL if not needed. 448 * @out_val : output payload, Can be NULL if not needed. 449 * 450 * RETURN : int32_t type of status 451 * 0 -- success 452 * -1 -- failure 453 *==========================================================================*/ 454 int32_t mm_stream_fsm_acquired(mm_stream_t *my_obj, 455 mm_stream_evt_type_t evt, 456 void * in_val, 457 void * out_val) 458 { 459 int32_t rc = 0; 460 461 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d", 462 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state); 463 switch(evt) { 464 case MM_STREAM_EVT_SET_FMT: 465 { 466 mm_camera_stream_config_t *config = 467 (mm_camera_stream_config_t *)in_val; 468 469 rc = mm_stream_config(my_obj, config); 470 471 /* change state to configed */ 472 my_obj->state = MM_STREAM_STATE_CFG; 473 474 break; 475 } 476 case MM_STREAM_EVT_RELEASE: 477 rc = mm_stream_release(my_obj); 478 /* change state to not used */ 479 my_obj->state = MM_STREAM_STATE_NOTUSED; 480 break; 481 case MM_STREAM_EVT_SET_PARM: 482 { 483 mm_evt_paylod_set_get_stream_parms_t *payload = 484 (mm_evt_paylod_set_get_stream_parms_t *)in_val; 485 rc = mm_stream_set_parm(my_obj, payload->parms); 486 } 487 break; 488 case MM_STREAM_EVT_GET_PARM: 489 { 490 mm_evt_paylod_set_get_stream_parms_t *payload = 491 (mm_evt_paylod_set_get_stream_parms_t *)in_val; 492 rc = mm_stream_get_parm(my_obj, payload->parms); 493 } 494 break; 495 default: 496 CDBG_ERROR("%s: invalid state (%d) for evt (%d), in(%p), out(%p)", 497 __func__, my_obj->state, evt, in_val, out_val); 498 } 499 CDBG("%s :X rc = %d", __func__, rc); 500 return rc; 501 } 502 503 /*=========================================================================== 504 * FUNCTION : mm_stream_fsm_cfg 505 * 506 * DESCRIPTION: stream finite state machine function to handle event in CONFIGURED 507 * state. 508 * 509 * PARAMETERS : 510 * @my_obj : ptr to a stream object 511 * @evt : stream event to be processed 512 * @in_val : input event payload. Can be NULL if not needed. 513 * @out_val : output payload, Can be NULL if not needed. 514 * 515 * RETURN : int32_t type of status 516 * 0 -- success 517 * -1 -- failure 518 *==========================================================================*/ 519 int32_t mm_stream_fsm_cfg(mm_stream_t * my_obj, 520 mm_stream_evt_type_t evt, 521 void * in_val, 522 void * out_val) 523 { 524 int32_t rc = 0; 525 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d", 526 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state); 527 switch(evt) { 528 case MM_STREAM_EVT_SET_FMT: 529 { 530 mm_camera_stream_config_t *config = 531 (mm_camera_stream_config_t *)in_val; 532 533 rc = mm_stream_config(my_obj, config); 534 535 /* change state to configed */ 536 my_obj->state = MM_STREAM_STATE_CFG; 537 538 break; 539 } 540 case MM_STREAM_EVT_RELEASE: 541 rc = mm_stream_release(my_obj); 542 my_obj->state = MM_STREAM_STATE_NOTUSED; 543 break; 544 case MM_STREAM_EVT_SET_PARM: 545 { 546 mm_evt_paylod_set_get_stream_parms_t *payload = 547 (mm_evt_paylod_set_get_stream_parms_t *)in_val; 548 rc = mm_stream_set_parm(my_obj, payload->parms); 549 } 550 break; 551 case MM_STREAM_EVT_GET_PARM: 552 { 553 mm_evt_paylod_set_get_stream_parms_t *payload = 554 (mm_evt_paylod_set_get_stream_parms_t *)in_val; 555 rc = mm_stream_get_parm(my_obj, payload->parms); 556 } 557 break; 558 case MM_STREAM_EVT_GET_BUF: 559 rc = mm_stream_init_bufs(my_obj); 560 /* change state to buff allocated */ 561 if(0 == rc) { 562 my_obj->state = MM_STREAM_STATE_BUFFED; 563 } 564 break; 565 default: 566 CDBG_ERROR("%s: invalid state (%d) for evt (%d), in(%p), out(%p)", 567 __func__, my_obj->state, evt, in_val, out_val); 568 } 569 CDBG("%s :X rc = %d", __func__, rc); 570 return rc; 571 } 572 573 /*=========================================================================== 574 * FUNCTION : mm_stream_fsm_buffed 575 * 576 * DESCRIPTION: stream finite state machine function to handle event in BUFFED 577 * state. 578 * 579 * PARAMETERS : 580 * @my_obj : ptr to a stream object 581 * @evt : stream event to be processed 582 * @in_val : input event payload. Can be NULL if not needed. 583 * @out_val : output payload, Can be NULL if not needed. 584 * 585 * RETURN : int32_t type of status 586 * 0 -- success 587 * -1 -- failure 588 *==========================================================================*/ 589 int32_t mm_stream_fsm_buffed(mm_stream_t * my_obj, 590 mm_stream_evt_type_t evt, 591 void * in_val, 592 void * out_val) 593 { 594 int32_t rc = 0; 595 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d", 596 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state); 597 switch(evt) { 598 case MM_STREAM_EVT_PUT_BUF: 599 rc = mm_stream_deinit_bufs(my_obj); 600 /* change state to configed */ 601 if(0 == rc) { 602 my_obj->state = MM_STREAM_STATE_CFG; 603 } 604 break; 605 case MM_STREAM_EVT_REG_BUF: 606 rc = mm_stream_reg_buf(my_obj); 607 /* change state to regged */ 608 if(0 == rc) { 609 my_obj->state = MM_STREAM_STATE_REG; 610 } 611 break; 612 case MM_STREAM_EVT_SET_PARM: 613 { 614 mm_evt_paylod_set_get_stream_parms_t *payload = 615 (mm_evt_paylod_set_get_stream_parms_t *)in_val; 616 rc = mm_stream_set_parm(my_obj, payload->parms); 617 } 618 break; 619 case MM_STREAM_EVT_GET_PARM: 620 { 621 mm_evt_paylod_set_get_stream_parms_t *payload = 622 (mm_evt_paylod_set_get_stream_parms_t *)in_val; 623 rc = mm_stream_get_parm(my_obj, payload->parms); 624 } 625 break; 626 default: 627 CDBG_ERROR("%s: invalid state (%d) for evt (%d), in(%p), out(%p)", 628 __func__, my_obj->state, evt, in_val, out_val); 629 } 630 CDBG("%s :X rc = %d", __func__, rc); 631 return rc; 632 } 633 634 /*=========================================================================== 635 * FUNCTION : mm_stream_fsm_reg 636 * 637 * DESCRIPTION: stream finite state machine function to handle event in REGGED 638 * state. 639 * 640 * PARAMETERS : 641 * @my_obj : ptr to a stream object 642 * @evt : stream event to be processed 643 * @in_val : input event payload. Can be NULL if not needed. 644 * @out_val : output payload, Can be NULL if not needed. 645 * 646 * RETURN : int32_t type of status 647 * 0 -- success 648 * -1 -- failure 649 *==========================================================================*/ 650 int32_t mm_stream_fsm_reg(mm_stream_t * my_obj, 651 mm_stream_evt_type_t evt, 652 void * in_val, 653 void * out_val) 654 { 655 int32_t rc = 0; 656 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d", 657 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state); 658 659 switch(evt) { 660 case MM_STREAM_EVT_UNREG_BUF: 661 rc = mm_stream_unreg_buf(my_obj); 662 663 /* change state to buffed */ 664 my_obj->state = MM_STREAM_STATE_BUFFED; 665 break; 666 case MM_STREAM_EVT_START: 667 { 668 uint8_t has_cb = 0; 669 uint8_t i; 670 /* launch cmd thread if CB is not null */ 671 pthread_mutex_lock(&my_obj->cb_lock); 672 for (i = 0; i < MM_CAMERA_STREAM_BUF_CB_MAX; i++) { 673 if(NULL != my_obj->buf_cb[i].cb) { 674 has_cb = 1; 675 break; 676 } 677 } 678 pthread_mutex_unlock(&my_obj->cb_lock); 679 680 if (has_cb) { 681 mm_camera_cmd_thread_launch(&my_obj->cmd_thread, 682 mm_stream_dispatch_app_data, 683 (void *)my_obj); 684 } 685 686 my_obj->state = MM_STREAM_STATE_ACTIVE; 687 rc = mm_stream_streamon(my_obj); 688 if (0 != rc) { 689 /* failed stream on, need to release cmd thread if it's launched */ 690 if (has_cb) { 691 mm_camera_cmd_thread_release(&my_obj->cmd_thread); 692 } 693 my_obj->state = MM_STREAM_STATE_REG; 694 break; 695 } 696 } 697 break; 698 case MM_STREAM_EVT_SET_PARM: 699 { 700 mm_evt_paylod_set_get_stream_parms_t *payload = 701 (mm_evt_paylod_set_get_stream_parms_t *)in_val; 702 rc = mm_stream_set_parm(my_obj, payload->parms); 703 } 704 break; 705 case MM_STREAM_EVT_GET_PARM: 706 { 707 mm_evt_paylod_set_get_stream_parms_t *payload = 708 (mm_evt_paylod_set_get_stream_parms_t *)in_val; 709 rc = mm_stream_get_parm(my_obj, payload->parms); 710 } 711 break; 712 default: 713 CDBG_ERROR("%s: invalid state (%d) for evt (%d), in(%p), out(%p)", 714 __func__, my_obj->state, evt, in_val, out_val); 715 } 716 CDBG("%s :X rc = %d", __func__, rc); 717 return rc; 718 } 719 720 /*=========================================================================== 721 * FUNCTION : mm_stream_fsm_active 722 * 723 * DESCRIPTION: stream finite state machine function to handle event in ACTIVE 724 * state. 725 * 726 * PARAMETERS : 727 * @my_obj : ptr to a stream object 728 * @evt : stream event to be processed 729 * @in_val : input event payload. Can be NULL if not needed. 730 * @out_val : output payload, Can be NULL if not needed. 731 * 732 * RETURN : int32_t type of status 733 * 0 -- success 734 * -1 -- failure 735 *==========================================================================*/ 736 int32_t mm_stream_fsm_active(mm_stream_t * my_obj, 737 mm_stream_evt_type_t evt, 738 void * in_val, 739 void * out_val) 740 { 741 int32_t rc = 0; 742 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d", 743 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state); 744 switch(evt) { 745 case MM_STREAM_EVT_QBUF: 746 rc = mm_stream_buf_done(my_obj, (mm_camera_buf_def_t *)in_val); 747 break; 748 case MM_STREAM_EVT_STOP: 749 { 750 uint8_t has_cb = 0; 751 uint8_t i; 752 rc = mm_stream_streamoff(my_obj); 753 754 pthread_mutex_lock(&my_obj->cb_lock); 755 for (i = 0; i < MM_CAMERA_STREAM_BUF_CB_MAX; i++) { 756 if(NULL != my_obj->buf_cb[i].cb) { 757 has_cb = 1; 758 break; 759 } 760 } 761 pthread_mutex_unlock(&my_obj->cb_lock); 762 763 if (has_cb) { 764 mm_camera_cmd_thread_release(&my_obj->cmd_thread); 765 } 766 my_obj->state = MM_STREAM_STATE_REG; 767 } 768 break; 769 case MM_STREAM_EVT_SET_PARM: 770 { 771 mm_evt_paylod_set_get_stream_parms_t *payload = 772 (mm_evt_paylod_set_get_stream_parms_t *)in_val; 773 rc = mm_stream_set_parm(my_obj, payload->parms); 774 } 775 break; 776 case MM_STREAM_EVT_GET_PARM: 777 { 778 mm_evt_paylod_set_get_stream_parms_t *payload = 779 (mm_evt_paylod_set_get_stream_parms_t *)in_val; 780 rc = mm_stream_get_parm(my_obj, payload->parms); 781 } 782 break; 783 case MM_STREAM_EVT_DO_ACTION: 784 rc = mm_stream_do_action(my_obj, in_val); 785 break; 786 default: 787 CDBG_ERROR("%s: invalid state (%d) for evt (%d), in(%p), out(%p)", 788 __func__, my_obj->state, evt, in_val, out_val); 789 } 790 CDBG("%s :X rc = %d", __func__, rc); 791 return rc; 792 } 793 794 /*=========================================================================== 795 * FUNCTION : mm_stream_config 796 * 797 * DESCRIPTION: configure a stream 798 * 799 * PARAMETERS : 800 * @my_obj : stream object 801 * @config : stream configuration 802 * 803 * RETURN : int32_t type of status 804 * 0 -- success 805 * -1 -- failure 806 *==========================================================================*/ 807 int32_t mm_stream_config(mm_stream_t *my_obj, 808 mm_camera_stream_config_t *config) 809 { 810 int32_t rc = 0; 811 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d", 812 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state); 813 my_obj->stream_info = config->stream_info; 814 my_obj->buf_num = 0; 815 my_obj->mem_vtbl = config->mem_vtbl; 816 my_obj->padding_info = config->padding_info; 817 /* cd through intf always palced at idx 0 of buf_cb */ 818 my_obj->buf_cb[0].cb = config->stream_cb; 819 my_obj->buf_cb[0].user_data = config->userdata; 820 my_obj->buf_cb[0].cb_count = -1; /* infinite by default */ 821 822 rc = mm_stream_sync_info(my_obj); 823 if (rc == 0) { 824 rc = mm_stream_set_fmt(my_obj); 825 } 826 return rc; 827 } 828 829 /*=========================================================================== 830 * FUNCTION : mm_stream_release 831 * 832 * DESCRIPTION: release a stream resource 833 * 834 * PARAMETERS : 835 * @my_obj : stream object 836 * 837 * RETURN : int32_t type of status 838 * 0 -- success 839 * -1 -- failure 840 *==========================================================================*/ 841 int32_t mm_stream_release(mm_stream_t *my_obj) 842 { 843 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d", 844 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state); 845 846 /* close fd */ 847 if(my_obj->fd > 0) 848 { 849 close(my_obj->fd); 850 } 851 852 /* destroy mutex */ 853 pthread_mutex_destroy(&my_obj->buf_lock); 854 pthread_mutex_destroy(&my_obj->cb_lock); 855 856 /* reset stream obj */ 857 memset(my_obj, 0, sizeof(mm_stream_t)); 858 859 return 0; 860 } 861 862 /*=========================================================================== 863 * FUNCTION : mm_stream_streamon 864 * 865 * DESCRIPTION: stream on a stream. sending v4l2 request to kernel 866 * 867 * PARAMETERS : 868 * @my_obj : stream object 869 * 870 * RETURN : int32_t type of status 871 * 0 -- success 872 * -1 -- failure 873 *==========================================================================*/ 874 int32_t mm_stream_streamon(mm_stream_t *my_obj) 875 { 876 int32_t rc; 877 enum v4l2_buf_type buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 878 879 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d", 880 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state); 881 882 rc = ioctl(my_obj->fd, VIDIOC_STREAMON, &buf_type); 883 if (rc < 0) { 884 CDBG_ERROR("%s: ioctl VIDIOC_STREAMON failed: rc=%d\n", 885 __func__, rc); 886 /* remove fd from data poll thread in case of failure */ 887 mm_camera_poll_thread_del_poll_fd(&my_obj->ch_obj->poll_thread[0], my_obj->my_hdl, mm_camera_sync_call); 888 } 889 CDBG("%s :X rc = %d",__func__,rc); 890 return rc; 891 } 892 893 /*=========================================================================== 894 * FUNCTION : mm_stream_streamoff 895 * 896 * DESCRIPTION: stream off a stream. sending v4l2 request to kernel 897 * 898 * PARAMETERS : 899 * @my_obj : stream object 900 * 901 * RETURN : int32_t type of status 902 * 0 -- success 903 * -1 -- failure 904 *==========================================================================*/ 905 int32_t mm_stream_streamoff(mm_stream_t *my_obj) 906 { 907 int32_t rc; 908 enum v4l2_buf_type buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 909 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d", 910 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state); 911 912 /* step1: remove fd from data poll thread */ 913 mm_camera_poll_thread_del_poll_fd(&my_obj->ch_obj->poll_thread[0], my_obj->my_hdl, mm_camera_sync_call); 914 915 /* step2: stream off */ 916 rc = ioctl(my_obj->fd, VIDIOC_STREAMOFF, &buf_type); 917 if (rc < 0) { 918 CDBG_ERROR("%s: STREAMOFF failed: %s\n", 919 __func__, strerror(errno)); 920 } 921 CDBG("%s :X rc = %d",__func__,rc); 922 return rc; 923 } 924 925 /*=========================================================================== 926 * FUNCTION : mm_stream_read_msm_frame 927 * 928 * DESCRIPTION: dequeue a stream buffer from kernel queue 929 * 930 * PARAMETERS : 931 * @my_obj : stream object 932 * @buf_info : ptr to a struct storing buffer information 933 * @num_planes : number of planes in the buffer 934 * 935 * RETURN : int32_t type of status 936 * 0 -- success 937 * -1 -- failure 938 *==========================================================================*/ 939 int32_t mm_stream_read_msm_frame(mm_stream_t * my_obj, 940 mm_camera_buf_info_t* buf_info, 941 uint8_t num_planes) 942 { 943 int32_t rc = 0; 944 struct v4l2_buffer vb; 945 struct v4l2_plane planes[VIDEO_MAX_PLANES]; 946 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d", 947 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state); 948 949 memset(&vb, 0, sizeof(vb)); 950 vb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 951 vb.memory = V4L2_MEMORY_USERPTR; 952 vb.m.planes = &planes[0]; 953 vb.length = num_planes; 954 955 rc = ioctl(my_obj->fd, VIDIOC_DQBUF, &vb); 956 if (rc < 0) { 957 CDBG_ERROR("%s: VIDIOC_DQBUF ioctl call failed (rc=%d)\n", 958 __func__, rc); 959 } else { 960 pthread_mutex_lock(&my_obj->buf_lock); 961 my_obj->queued_buffer_count--; 962 if(my_obj->queued_buffer_count == 0) { 963 CDBG_HIGH("%s: Stoping poll on stream %p type :%d", __func__, my_obj, my_obj->stream_info->stream_type); 964 mm_camera_poll_thread_del_poll_fd(&my_obj->ch_obj->poll_thread[0], my_obj->my_hdl, mm_camera_async_call); 965 CDBG_HIGH("%s: Stopped poll on stream %p type :%d", __func__, my_obj, my_obj->stream_info->stream_type); 966 } 967 pthread_mutex_unlock(&my_obj->buf_lock); 968 int8_t idx = vb.index; 969 buf_info->buf = &my_obj->buf[idx]; 970 buf_info->frame_idx = vb.sequence; 971 buf_info->stream_id = my_obj->my_hdl; 972 973 buf_info->buf->stream_id = my_obj->my_hdl; 974 buf_info->buf->buf_idx = idx; 975 buf_info->buf->frame_idx = vb.sequence; 976 buf_info->buf->ts.tv_sec = vb.timestamp.tv_sec; 977 buf_info->buf->ts.tv_nsec = vb.timestamp.tv_usec * 1000; 978 CDBG("%s: VIDIOC_DQBUF buf_index %d, frame_idx %d, stream type %d\n", 979 __func__, vb.index, buf_info->buf->frame_idx, my_obj->stream_info->stream_type); 980 if ( NULL != my_obj->mem_vtbl.clean_invalidate_buf ) { 981 rc = my_obj->mem_vtbl.clean_invalidate_buf(idx, 982 my_obj->mem_vtbl.user_data); 983 if ( 0 > rc ) { 984 CDBG_ERROR("%s: Clean invalidate cache failed on buffer index: %d", 985 __func__, 986 idx); 987 return rc; 988 } 989 } else { 990 CDBG_ERROR(" %s : Clean invalidate cache op not supported\n", __func__); 991 } 992 } 993 994 CDBG("%s :X rc = %d",__func__,rc); 995 return rc; 996 } 997 998 /*=========================================================================== 999 * FUNCTION : mm_stream_set_parms 1000 * 1001 * DESCRIPTION: set parameters per stream 1002 * 1003 * PARAMETERS : 1004 * @my_obj : stream object 1005 * @in_value : ptr to a param struct to be set to server 1006 * 1007 * RETURN : int32_t type of status 1008 * 0 -- success 1009 * -1 -- failure 1010 * NOTE : Assume the parms struct buf is already mapped to server via 1011 * domain socket. Corresponding fields of parameters to be set 1012 * are already filled in by upper layer caller. 1013 *==========================================================================*/ 1014 int32_t mm_stream_set_parm(mm_stream_t *my_obj, 1015 cam_stream_parm_buffer_t *in_value) 1016 { 1017 int32_t rc = -1; 1018 int32_t value = 0; 1019 if (in_value != NULL) { 1020 rc = mm_camera_util_s_ctrl(my_obj->fd, CAM_PRIV_STREAM_PARM, &value); 1021 } 1022 return rc; 1023 } 1024 1025 /*=========================================================================== 1026 * FUNCTION : mm_stream_get_parms 1027 * 1028 * DESCRIPTION: get parameters per stream 1029 * 1030 * PARAMETERS : 1031 * @my_obj : stream object 1032 * @in_value : ptr to a param struct to be get from server 1033 * 1034 * RETURN : int32_t type of status 1035 * 0 -- success 1036 * -1 -- failure 1037 * NOTE : Assume the parms struct buf is already mapped to server via 1038 * domain socket. Corresponding fields of parameters to be get 1039 * are already filled in by upper layer caller. 1040 *==========================================================================*/ 1041 int32_t mm_stream_get_parm(mm_stream_t *my_obj, 1042 cam_stream_parm_buffer_t *in_value) 1043 { 1044 int32_t rc = -1; 1045 int32_t value = 0; 1046 if (in_value != NULL) { 1047 rc = mm_camera_util_g_ctrl(my_obj->fd, CAM_PRIV_STREAM_PARM, &value); 1048 } 1049 return rc; 1050 } 1051 1052 /*=========================================================================== 1053 * FUNCTION : mm_stream_do_actions 1054 * 1055 * DESCRIPTION: request server to perform stream based actions 1056 * 1057 * PARAMETERS : 1058 * @my_obj : stream object 1059 * @in_value : ptr to a struct of actions to be performed by the server 1060 * 1061 * RETURN : int32_t type of status 1062 * 0 -- success 1063 * -1 -- failure 1064 * NOTE : Assume the action struct buf is already mapped to server via 1065 * domain socket. Corresponding fields of actions to be performed 1066 * are already filled in by upper layer caller. 1067 *==========================================================================*/ 1068 int32_t mm_stream_do_action(mm_stream_t *my_obj, 1069 void *in_value) 1070 { 1071 int32_t rc = -1; 1072 int32_t value = 0; 1073 if (in_value != NULL) { 1074 rc = mm_camera_util_s_ctrl(my_obj->fd, CAM_PRIV_STREAM_PARM, &value); 1075 } 1076 return rc; 1077 } 1078 1079 /*=========================================================================== 1080 * FUNCTION : mm_stream_set_ext_mode 1081 * 1082 * DESCRIPTION: set stream extended mode to server via v4l2 ioctl 1083 * 1084 * PARAMETERS : 1085 * @my_obj : stream object 1086 * 1087 * RETURN : int32_t type of status 1088 * 0 -- success 1089 * -1 -- failure 1090 * NOTE : Server will return a server stream id that uniquely identify 1091 * this stream on server side. Later on communication to server 1092 * per stream should use this server stream id. 1093 *==========================================================================*/ 1094 int32_t mm_stream_set_ext_mode(mm_stream_t * my_obj) 1095 { 1096 int32_t rc = 0; 1097 struct v4l2_streamparm s_parm; 1098 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d", 1099 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state); 1100 1101 memset(&s_parm, 0, sizeof(s_parm)); 1102 s_parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 1103 1104 rc = ioctl(my_obj->fd, VIDIOC_S_PARM, &s_parm); 1105 CDBG("%s:stream fd=%d, rc=%d, extended_mode=%d\n", 1106 __func__, my_obj->fd, rc, s_parm.parm.capture.extendedmode); 1107 if (rc == 0) { 1108 /* get server stream id */ 1109 my_obj->server_stream_id = s_parm.parm.capture.extendedmode; 1110 } 1111 return rc; 1112 } 1113 1114 /*=========================================================================== 1115 * FUNCTION : mm_stream_qbuf 1116 * 1117 * DESCRIPTION: enqueue buffer back to kernel queue for furture use 1118 * 1119 * PARAMETERS : 1120 * @my_obj : stream object 1121 * @buf : ptr to a struct storing buffer information 1122 * 1123 * RETURN : int32_t type of status 1124 * 0 -- success 1125 * -1 -- failure 1126 *==========================================================================*/ 1127 int32_t mm_stream_qbuf(mm_stream_t *my_obj, mm_camera_buf_def_t *buf) 1128 { 1129 int32_t rc = 0; 1130 struct v4l2_buffer buffer; 1131 struct v4l2_plane planes[VIDEO_MAX_PLANES]; 1132 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d", 1133 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state); 1134 1135 memcpy(planes, buf->planes, sizeof(planes)); 1136 memset(&buffer, 0, sizeof(buffer)); 1137 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 1138 buffer.memory = V4L2_MEMORY_USERPTR; 1139 buffer.index = buf->buf_idx; 1140 buffer.m.planes = &planes[0]; 1141 buffer.length = buf->num_planes; 1142 1143 CDBG("%s:plane 0: stream_hdl=%d,fd=%d,frame idx=%d,num_planes = %d, offset = %d, data_offset = %d\n", __func__, 1144 buf->stream_id, buf->fd, buffer.index, buffer.length, buf->planes[0].reserved[0], buf->planes[0].data_offset); 1145 CDBG("%s:plane 1: stream_hdl=%d,fd=%d,frame idx=%d,num_planes = %d, offset = %d, data_offset = %d\n", __func__, 1146 buf->stream_id, buf->fd, buffer.index, buffer.length, buf->planes[1].reserved[0], buf->planes[1].data_offset); 1147 1148 if ( NULL != my_obj->mem_vtbl.invalidate_buf ) { 1149 rc = my_obj->mem_vtbl.invalidate_buf(buffer.index, 1150 my_obj->mem_vtbl.user_data); 1151 if ( 0 > rc ) { 1152 CDBG_ERROR("%s: Cache invalidate failed on buffer index: %d", 1153 __func__, 1154 buffer.index); 1155 return rc; 1156 } 1157 } else { 1158 CDBG_ERROR("%s: Cache invalidate op not added", __func__); 1159 } 1160 1161 my_obj->queued_buffer_count++; 1162 if(my_obj->queued_buffer_count == 1) { 1163 /* Add fd to data poll thread */ 1164 CDBG_HIGH("%s: Starting poll on stream %p type :%d", __func__, my_obj,my_obj->stream_info->stream_type); 1165 rc = mm_camera_poll_thread_add_poll_fd(&my_obj->ch_obj->poll_thread[0], 1166 my_obj->my_hdl, 1167 my_obj->fd, 1168 mm_stream_data_notify, 1169 (void*)my_obj, 1170 mm_camera_async_call); 1171 CDBG_HIGH("%s: Started poll on stream %p type :%d", __func__, my_obj,my_obj->stream_info->stream_type); 1172 if (rc < 0) { 1173 ALOGE("%s: add poll fd error", __func__); 1174 return rc; 1175 } 1176 } 1177 1178 rc = ioctl(my_obj->fd, VIDIOC_QBUF, &buffer); 1179 CDBG("%s: qbuf idx:%d, rc:%d", __func__, buffer.index, rc); 1180 return rc; 1181 } 1182 1183 /*=========================================================================== 1184 * FUNCTION : mm_stream_request_buf 1185 * 1186 * DESCRIPTION: This function let kernel know the amount of buffers need to 1187 * be registered via v4l2 ioctl. 1188 * 1189 * PARAMETERS : 1190 * @my_obj : stream object 1191 * 1192 * RETURN : int32_t type of status 1193 * 0 -- success 1194 * -1 -- failure 1195 *==========================================================================*/ 1196 int32_t mm_stream_request_buf(mm_stream_t * my_obj) 1197 { 1198 int32_t rc = 0; 1199 struct v4l2_requestbuffers bufreq; 1200 uint8_t buf_num = my_obj->buf_num; 1201 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d", 1202 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state); 1203 1204 if(buf_num > MM_CAMERA_MAX_NUM_FRAMES) { 1205 CDBG_ERROR("%s: buf num %d > max limit %d\n", 1206 __func__, buf_num, MM_CAMERA_MAX_NUM_FRAMES); 1207 return -1; 1208 } 1209 1210 memset(&bufreq, 0, sizeof(bufreq)); 1211 bufreq.count = buf_num; 1212 bufreq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 1213 bufreq.memory = V4L2_MEMORY_USERPTR; 1214 rc = ioctl(my_obj->fd, VIDIOC_REQBUFS, &bufreq); 1215 if (rc < 0) { 1216 CDBG_ERROR("%s: fd=%d, ioctl VIDIOC_REQBUFS failed: rc=%d\n", 1217 __func__, my_obj->fd, rc); 1218 } 1219 CDBG("%s :X rc = %d",__func__,rc); 1220 return rc; 1221 } 1222 1223 /*=========================================================================== 1224 * FUNCTION : mm_stream_map_buf 1225 * 1226 * DESCRIPTION: mapping stream buffer via domain socket to server 1227 * 1228 * PARAMETERS : 1229 * @my_obj : stream object 1230 * @buf_type : type of buffer to be mapped. could be following values: 1231 * CAM_MAPPING_BUF_TYPE_STREAM_BUF 1232 * CAM_MAPPING_BUF_TYPE_STREAM_INFO 1233 * CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF 1234 * @frame_idx : index of buffer within the stream buffers, only valid if 1235 * buf_type is CAM_MAPPING_BUF_TYPE_STREAM_BUF or 1236 * CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF 1237 * @plane_idx : plane index. If all planes share the same fd, 1238 * plane_idx = -1; otherwise, plean_idx is the 1239 * index to plane (0..num_of_planes) 1240 * @fd : file descriptor of the buffer 1241 * @size : size of the buffer 1242 * 1243 * RETURN : int32_t type of status 1244 * 0 -- success 1245 * -1 -- failure 1246 *==========================================================================*/ 1247 int32_t mm_stream_map_buf(mm_stream_t * my_obj, 1248 uint8_t buf_type, 1249 uint32_t frame_idx, 1250 int32_t plane_idx, 1251 int fd, 1252 uint32_t size) 1253 { 1254 if (NULL == my_obj || NULL == my_obj->ch_obj || NULL == my_obj->ch_obj->cam_obj) { 1255 CDBG_ERROR("%s: NULL obj of stream/channel/camera", __func__); 1256 return -1; 1257 } 1258 1259 cam_sock_packet_t packet; 1260 memset(&packet, 0, sizeof(cam_sock_packet_t)); 1261 packet.msg_type = CAM_MAPPING_TYPE_FD_MAPPING; 1262 packet.payload.buf_map.type = buf_type; 1263 packet.payload.buf_map.fd = fd; 1264 packet.payload.buf_map.size = size; 1265 packet.payload.buf_map.stream_id = my_obj->server_stream_id; 1266 packet.payload.buf_map.frame_idx = frame_idx; 1267 packet.payload.buf_map.plane_idx = plane_idx; 1268 return mm_camera_util_sendmsg(my_obj->ch_obj->cam_obj, 1269 &packet, 1270 sizeof(cam_sock_packet_t), 1271 fd); 1272 } 1273 1274 /*=========================================================================== 1275 * FUNCTION : mm_stream_unmap_buf 1276 * 1277 * DESCRIPTION: unmapping stream buffer via domain socket to server 1278 * 1279 * PARAMETERS : 1280 * @my_obj : stream object 1281 * @buf_type : type of buffer to be unmapped. could be following values: 1282 * CAM_MAPPING_BUF_TYPE_STREAM_BUF 1283 * CAM_MAPPING_BUF_TYPE_STREAM_INFO 1284 * CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF 1285 * @frame_idx : index of buffer within the stream buffers, only valid if 1286 * buf_type is CAM_MAPPING_BUF_TYPE_STREAM_BUF or 1287 * CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF 1288 * @plane_idx : plane index. If all planes share the same fd, 1289 * plane_idx = -1; otherwise, plean_idx is the 1290 * index to plane (0..num_of_planes) 1291 * 1292 * RETURN : int32_t type of status 1293 * 0 -- success 1294 * -1 -- failure 1295 *==========================================================================*/ 1296 int32_t mm_stream_unmap_buf(mm_stream_t * my_obj, 1297 uint8_t buf_type, 1298 uint32_t frame_idx, 1299 int32_t plane_idx) 1300 { 1301 if (NULL == my_obj || NULL == my_obj->ch_obj || NULL == my_obj->ch_obj->cam_obj) { 1302 CDBG_ERROR("%s: NULL obj of stream/channel/camera", __func__); 1303 return -1; 1304 } 1305 1306 cam_sock_packet_t packet; 1307 memset(&packet, 0, sizeof(cam_sock_packet_t)); 1308 packet.msg_type = CAM_MAPPING_TYPE_FD_UNMAPPING; 1309 packet.payload.buf_unmap.type = buf_type; 1310 packet.payload.buf_unmap.stream_id = my_obj->server_stream_id; 1311 packet.payload.buf_unmap.frame_idx = frame_idx; 1312 packet.payload.buf_unmap.plane_idx = plane_idx; 1313 return mm_camera_util_sendmsg(my_obj->ch_obj->cam_obj, 1314 &packet, 1315 sizeof(cam_sock_packet_t), 1316 0); 1317 } 1318 1319 /*=========================================================================== 1320 * FUNCTION : mm_stream_map_buf_ops 1321 * 1322 * DESCRIPTION: ops for mapping stream buffer via domain socket to server. 1323 * This function will be passed to upper layer as part of ops table 1324 * to be used by upper layer when allocating stream buffers and mapping 1325 * buffers to server via domain socket. 1326 * 1327 * PARAMETERS : 1328 * @frame_idx : index of buffer within the stream buffers, only valid if 1329 * buf_type is CAM_MAPPING_BUF_TYPE_STREAM_BUF or 1330 * CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF 1331 * @plane_idx : plane index. If all planes share the same fd, 1332 * plane_idx = -1; otherwise, plean_idx is the 1333 * index to plane (0..num_of_planes) 1334 * @fd : file descriptor of the buffer 1335 * @size : size of the buffer 1336 * @userdata : user data ptr (stream object) 1337 * 1338 * RETURN : int32_t type of status 1339 * 0 -- success 1340 * -1 -- failure 1341 *==========================================================================*/ 1342 static int32_t mm_stream_map_buf_ops(uint32_t frame_idx, 1343 int32_t plane_idx, 1344 int fd, 1345 uint32_t size, 1346 void *userdata) 1347 { 1348 mm_stream_t *my_obj = (mm_stream_t *)userdata; 1349 return mm_stream_map_buf(my_obj, 1350 CAM_MAPPING_BUF_TYPE_STREAM_BUF, 1351 frame_idx, plane_idx, fd, size); 1352 } 1353 1354 /*=========================================================================== 1355 * FUNCTION : mm_stream_unmap_buf_ops 1356 * 1357 * DESCRIPTION: ops for unmapping stream buffer via domain socket to server. 1358 * This function will be passed to upper layer as part of ops table 1359 * to be used by upper layer when allocating stream buffers and unmapping 1360 * buffers to server via domain socket. 1361 * 1362 * PARAMETERS : 1363 * @frame_idx : index of buffer within the stream buffers, only valid if 1364 * buf_type is CAM_MAPPING_BUF_TYPE_STREAM_BUF or 1365 * CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF 1366 * @plane_idx : plane index. If all planes share the same fd, 1367 * plane_idx = -1; otherwise, plean_idx is the 1368 * index to plane (0..num_of_planes) 1369 * @userdata : user data ptr (stream object) 1370 * 1371 * RETURN : int32_t type of status 1372 * 0 -- success 1373 * -1 -- failure 1374 *==========================================================================*/ 1375 static int32_t mm_stream_unmap_buf_ops(uint32_t frame_idx, 1376 int32_t plane_idx, 1377 void *userdata) 1378 { 1379 mm_stream_t *my_obj = (mm_stream_t *)userdata; 1380 return mm_stream_unmap_buf(my_obj, 1381 CAM_MAPPING_BUF_TYPE_STREAM_BUF, 1382 frame_idx, 1383 plane_idx); 1384 } 1385 1386 /*=========================================================================== 1387 * FUNCTION : mm_stream_init_bufs 1388 * 1389 * DESCRIPTION: initialize stream buffers needed. This function will request 1390 * buffers needed from upper layer through the mem ops table passed 1391 * during configuration stage. 1392 * 1393 * PARAMETERS : 1394 * @my_obj : stream object 1395 * 1396 * RETURN : int32_t type of status 1397 * 0 -- success 1398 * -1 -- failure 1399 *==========================================================================*/ 1400 int32_t mm_stream_init_bufs(mm_stream_t * my_obj) 1401 { 1402 int32_t i, rc = 0; 1403 uint8_t *reg_flags = NULL; 1404 mm_camera_map_unmap_ops_tbl_t ops_tbl; 1405 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d", 1406 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state); 1407 1408 /* deinit buf if it's not NULL*/ 1409 if (NULL != my_obj->buf) { 1410 mm_stream_deinit_bufs(my_obj); 1411 } 1412 1413 ops_tbl.map_ops = mm_stream_map_buf_ops; 1414 ops_tbl.unmap_ops = mm_stream_unmap_buf_ops; 1415 ops_tbl.userdata = my_obj; 1416 1417 rc = my_obj->mem_vtbl.get_bufs(&my_obj->frame_offset, 1418 &my_obj->buf_num, 1419 ®_flags, 1420 &my_obj->buf, 1421 &ops_tbl, 1422 my_obj->mem_vtbl.user_data); 1423 1424 if (0 != rc) { 1425 CDBG_ERROR("%s: Error get buf, rc = %d\n", __func__, rc); 1426 return rc; 1427 } 1428 1429 my_obj->buf_status = 1430 (mm_stream_buf_status_t *)malloc(sizeof(mm_stream_buf_status_t) * my_obj->buf_num); 1431 1432 if (NULL == my_obj->buf_status) { 1433 CDBG_ERROR("%s: No memory for buf_status", __func__); 1434 mm_stream_deinit_bufs(my_obj); 1435 free(reg_flags); 1436 return -1; 1437 } 1438 1439 memset(my_obj->buf_status, 0, sizeof(mm_stream_buf_status_t) * my_obj->buf_num); 1440 for (i = 0; i < my_obj->buf_num; i++) { 1441 my_obj->buf_status[i].initial_reg_flag = reg_flags[i]; 1442 my_obj->buf[i].stream_id = my_obj->my_hdl; 1443 my_obj->buf[i].stream_type = my_obj->stream_info->stream_type; 1444 } 1445 1446 free(reg_flags); 1447 reg_flags = NULL; 1448 1449 return rc; 1450 } 1451 1452 /*=========================================================================== 1453 * FUNCTION : mm_stream_deinit_bufs 1454 * 1455 * DESCRIPTION: return stream buffers to upper layer through the mem ops table 1456 * passed during configuration stage. 1457 * 1458 * PARAMETERS : 1459 * @my_obj : stream object 1460 * 1461 * RETURN : int32_t type of status 1462 * 0 -- success 1463 * -1 -- failure 1464 *==========================================================================*/ 1465 int32_t mm_stream_deinit_bufs(mm_stream_t * my_obj) 1466 { 1467 int32_t rc = 0; 1468 mm_camera_map_unmap_ops_tbl_t ops_tbl; 1469 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d", 1470 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state); 1471 1472 if (NULL == my_obj->buf) { 1473 CDBG("%s: Buf is NULL, no need to deinit", __func__); 1474 return rc; 1475 } 1476 1477 /* release bufs */ 1478 ops_tbl.map_ops = mm_stream_map_buf_ops; 1479 ops_tbl.unmap_ops = mm_stream_unmap_buf_ops; 1480 ops_tbl.userdata = my_obj; 1481 1482 rc = my_obj->mem_vtbl.put_bufs(&ops_tbl, 1483 my_obj->mem_vtbl.user_data); 1484 1485 free(my_obj->buf); 1486 my_obj->buf = NULL; 1487 if (my_obj->buf_status != NULL) { 1488 free(my_obj->buf_status); 1489 my_obj->buf_status = NULL; 1490 } 1491 1492 return rc; 1493 } 1494 1495 /*=========================================================================== 1496 * FUNCTION : mm_stream_reg_buf 1497 * 1498 * DESCRIPTION: register buffers with kernel by calling v4l2 ioctl QBUF for 1499 * each buffer in the stream 1500 * 1501 * PARAMETERS : 1502 * @my_obj : stream object 1503 * 1504 * RETURN : int32_t type of status 1505 * 0 -- success 1506 * -1 -- failure 1507 *==========================================================================*/ 1508 int32_t mm_stream_reg_buf(mm_stream_t * my_obj) 1509 { 1510 int32_t rc = 0; 1511 uint8_t i; 1512 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d", 1513 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state); 1514 1515 rc = mm_stream_request_buf(my_obj); 1516 if (rc != 0) { 1517 return rc; 1518 } 1519 1520 pthread_mutex_lock(&my_obj->buf_lock); 1521 for(i = 0; i < my_obj->buf_num; i++){ 1522 /* check if need to qbuf initially */ 1523 if (my_obj->buf_status[i].initial_reg_flag) { 1524 rc = mm_stream_qbuf(my_obj, &my_obj->buf[i]); 1525 if (rc != 0) { 1526 CDBG_ERROR("%s: VIDIOC_QBUF rc = %d\n", __func__, rc); 1527 break; 1528 } 1529 my_obj->buf_status[i].buf_refcnt = 0; 1530 my_obj->buf_status[i].in_kernel = 1; 1531 } else { 1532 /* the buf is held by upper layer, will not queue into kernel. 1533 * add buf reference count */ 1534 my_obj->buf_status[i].buf_refcnt = 1; 1535 my_obj->buf_status[i].in_kernel = 0; 1536 } 1537 } 1538 pthread_mutex_unlock(&my_obj->buf_lock); 1539 1540 return rc; 1541 } 1542 1543 /*=========================================================================== 1544 * FUNCTION : mm_stream_unreg buf 1545 * 1546 * DESCRIPTION: unregister all stream buffers from kernel 1547 * 1548 * PARAMETERS : 1549 * @my_obj : stream object 1550 * 1551 * RETURN : int32_t type of status 1552 * 0 -- success 1553 * -1 -- failure 1554 *==========================================================================*/ 1555 int32_t mm_stream_unreg_buf(mm_stream_t * my_obj) 1556 { 1557 struct v4l2_requestbuffers bufreq; 1558 int32_t i, rc = 0; 1559 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d", 1560 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state); 1561 1562 /* unreg buf to kernel */ 1563 bufreq.count = 0; 1564 bufreq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 1565 bufreq.memory = V4L2_MEMORY_USERPTR; 1566 rc = ioctl(my_obj->fd, VIDIOC_REQBUFS, &bufreq); 1567 if (rc < 0) { 1568 CDBG_ERROR("%s: fd=%d, VIDIOC_REQBUFS failed, rc=%d\n", 1569 __func__, my_obj->fd, rc); 1570 } 1571 1572 /* reset buf reference count */ 1573 pthread_mutex_lock(&my_obj->buf_lock); 1574 if (NULL != my_obj->buf_status) { 1575 for(i = 0; i < my_obj->buf_num; i++){ 1576 my_obj->buf_status[i].buf_refcnt = 0; 1577 my_obj->buf_status[i].in_kernel = 0; 1578 } 1579 } 1580 pthread_mutex_unlock(&my_obj->buf_lock); 1581 1582 return rc; 1583 } 1584 1585 /*=========================================================================== 1586 * FUNCTION : mm_stream_get_v4l2_fmt 1587 * 1588 * DESCRIPTION: translate camera image format into FOURCC code 1589 * 1590 * PARAMETERS : 1591 * @fmt : camera image format 1592 * 1593 * RETURN : FOURCC code for image format 1594 *==========================================================================*/ 1595 uint32_t mm_stream_get_v4l2_fmt(cam_format_t fmt) 1596 { 1597 uint32_t val; 1598 switch(fmt) { 1599 case CAM_FORMAT_YUV_420_NV12: 1600 val = V4L2_PIX_FMT_NV12; 1601 break; 1602 case CAM_FORMAT_YUV_420_NV21: 1603 val = V4L2_PIX_FMT_NV21; 1604 break; 1605 case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_GBRG: 1606 case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_GRBG: 1607 case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_RGGB: 1608 case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_BGGR: 1609 val= V4L2_PIX_FMT_SBGGR10; 1610 break; 1611 case CAM_FORMAT_YUV_422_NV61: 1612 val= V4L2_PIX_FMT_NV61; 1613 break; 1614 case CAM_FORMAT_YUV_RAW_8BIT_YUYV: 1615 val= V4L2_PIX_FMT_YUYV; 1616 break; 1617 case CAM_FORMAT_YUV_RAW_8BIT_YVYU: 1618 val= V4L2_PIX_FMT_YVYU; 1619 break; 1620 case CAM_FORMAT_YUV_RAW_8BIT_UYVY: 1621 val= V4L2_PIX_FMT_UYVY; 1622 break; 1623 case CAM_FORMAT_YUV_RAW_8BIT_VYUY: 1624 val= V4L2_PIX_FMT_VYUY; 1625 break; 1626 case CAM_FORMAT_YUV_420_YV12: 1627 val= V4L2_PIX_FMT_NV12; 1628 break; 1629 case CAM_FORMAT_YUV_422_NV16: 1630 val= V4L2_PIX_FMT_NV16; 1631 break; 1632 default: 1633 val = 0; 1634 CDBG_ERROR("%s: Unknown fmt=%d", __func__, fmt); 1635 break; 1636 } 1637 CDBG("%s: fmt=%d, val =%d", __func__, fmt, val); 1638 return val; 1639 } 1640 1641 /*=========================================================================== 1642 * FUNCTION : mm_stream_calc_offset_preview 1643 * 1644 * DESCRIPTION: calculate preview/postview frame offset based on format and 1645 * padding information 1646 * 1647 * PARAMETERS : 1648 * @fmt : image format 1649 * @dim : image dimension 1650 * @buf_planes : [out] buffer plane information 1651 * 1652 * RETURN : int32_t type of status 1653 * 0 -- success 1654 * -1 -- failure 1655 *==========================================================================*/ 1656 int32_t mm_stream_calc_offset_preview(cam_format_t fmt, 1657 cam_dimension_t *dim, 1658 cam_stream_buf_plane_info_t *buf_planes) 1659 { 1660 int32_t rc = 0; 1661 int stride = 0, scanline = 0; 1662 1663 switch (fmt) { 1664 case CAM_FORMAT_YUV_420_NV12: 1665 case CAM_FORMAT_YUV_420_NV21: 1666 /* 2 planes: Y + CbCr */ 1667 buf_planes->plane_info.num_planes = 2; 1668 1669 stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16); 1670 scanline = PAD_TO_SIZE(dim->height, CAM_PAD_TO_2); 1671 buf_planes->plane_info.mp[0].offset = 0; 1672 buf_planes->plane_info.mp[0].len = stride * scanline; 1673 buf_planes->plane_info.mp[0].offset_x = 0; 1674 buf_planes->plane_info.mp[0].offset_y = 0; 1675 buf_planes->plane_info.mp[0].stride = stride; 1676 buf_planes->plane_info.mp[0].scanline = scanline; 1677 1678 stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16); 1679 scanline = PAD_TO_SIZE(dim->height / 2, CAM_PAD_TO_2); 1680 buf_planes->plane_info.mp[1].offset = 0; 1681 buf_planes->plane_info.mp[1].len = 1682 stride * scanline; 1683 buf_planes->plane_info.mp[1].offset_x = 0; 1684 buf_planes->plane_info.mp[1].offset_y = 0; 1685 buf_planes->plane_info.mp[1].stride = stride; 1686 buf_planes->plane_info.mp[1].scanline = scanline; 1687 1688 buf_planes->plane_info.frame_len = 1689 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len + 1690 buf_planes->plane_info.mp[1].len, 1691 CAM_PAD_TO_4K); 1692 break; 1693 case CAM_FORMAT_YUV_420_NV21_ADRENO: 1694 /* 2 planes: Y + CbCr */ 1695 buf_planes->plane_info.num_planes = 2; 1696 1697 stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_32); 1698 scanline = PAD_TO_SIZE(dim->height, CAM_PAD_TO_32); 1699 buf_planes->plane_info.mp[0].offset = 0; 1700 buf_planes->plane_info.mp[0].len = 1701 PAD_TO_SIZE(stride * scanline, 1702 CAM_PAD_TO_4K); 1703 buf_planes->plane_info.mp[0].offset_x = 0; 1704 buf_planes->plane_info.mp[0].offset_y = 0; 1705 buf_planes->plane_info.mp[0].stride = stride; 1706 buf_planes->plane_info.mp[0].scanline = scanline; 1707 1708 stride = PAD_TO_SIZE(dim->width / 2, CAM_PAD_TO_32) * 2; 1709 scanline = PAD_TO_SIZE(dim->height / 2, CAM_PAD_TO_32); 1710 buf_planes->plane_info.mp[1].offset = 0; 1711 buf_planes->plane_info.mp[1].len = 1712 PAD_TO_SIZE(stride * scanline, 1713 CAM_PAD_TO_4K); 1714 buf_planes->plane_info.mp[1].offset_x = 0; 1715 buf_planes->plane_info.mp[1].offset_y = 0; 1716 buf_planes->plane_info.mp[1].stride = stride; 1717 buf_planes->plane_info.mp[1].scanline = scanline; 1718 1719 buf_planes->plane_info.frame_len = 1720 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len + 1721 buf_planes->plane_info.mp[1].len, 1722 CAM_PAD_TO_4K); 1723 break; 1724 case CAM_FORMAT_YUV_420_YV12: 1725 /* 3 planes: Y + Cr + Cb */ 1726 buf_planes->plane_info.num_planes = 3; 1727 1728 stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16); 1729 scanline = PAD_TO_SIZE(dim->height, CAM_PAD_TO_2); 1730 buf_planes->plane_info.mp[0].offset = 0; 1731 buf_planes->plane_info.mp[0].len = stride * scanline; 1732 buf_planes->plane_info.mp[0].offset_x = 0; 1733 buf_planes->plane_info.mp[0].offset_y = 0; 1734 buf_planes->plane_info.mp[0].stride = stride; 1735 buf_planes->plane_info.mp[0].scanline = scanline; 1736 1737 stride = PAD_TO_SIZE(stride / 2, CAM_PAD_TO_16); 1738 scanline = scanline / 2; 1739 buf_planes->plane_info.mp[1].offset = 0; 1740 buf_planes->plane_info.mp[1].len = 1741 stride * scanline; 1742 buf_planes->plane_info.mp[1].offset_x = 0; 1743 buf_planes->plane_info.mp[1].offset_y = 0; 1744 buf_planes->plane_info.mp[1].stride = stride; 1745 buf_planes->plane_info.mp[1].scanline = scanline; 1746 1747 buf_planes->plane_info.mp[2].offset = 0; 1748 buf_planes->plane_info.mp[2].len = 1749 stride * scanline; 1750 buf_planes->plane_info.mp[2].offset_x = 0; 1751 buf_planes->plane_info.mp[2].offset_y = 0; 1752 buf_planes->plane_info.mp[2].stride = stride; 1753 buf_planes->plane_info.mp[2].scanline = scanline; 1754 1755 buf_planes->plane_info.frame_len = 1756 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len + 1757 buf_planes->plane_info.mp[1].len + 1758 buf_planes->plane_info.mp[2].len, 1759 CAM_PAD_TO_4K); 1760 break; 1761 case CAM_FORMAT_YUV_422_NV16: 1762 case CAM_FORMAT_YUV_422_NV61: 1763 /* 2 planes: Y + CbCr */ 1764 buf_planes->plane_info.num_planes = 2; 1765 1766 stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16); 1767 scanline = dim->height; 1768 buf_planes->plane_info.mp[0].offset = 0; 1769 buf_planes->plane_info.mp[0].len = stride * scanline; 1770 buf_planes->plane_info.mp[0].offset_x = 0; 1771 buf_planes->plane_info.mp[0].offset_y = 0; 1772 buf_planes->plane_info.mp[0].stride = stride; 1773 buf_planes->plane_info.mp[0].scanline = scanline; 1774 1775 buf_planes->plane_info.mp[1].offset = 0; 1776 buf_planes->plane_info.mp[1].len = stride * scanline; 1777 buf_planes->plane_info.mp[1].offset_x = 0; 1778 buf_planes->plane_info.mp[1].offset_y = 0; 1779 buf_planes->plane_info.mp[1].stride = stride; 1780 buf_planes->plane_info.mp[1].scanline = scanline; 1781 1782 buf_planes->plane_info.frame_len = 1783 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len + 1784 buf_planes->plane_info.mp[1].len, 1785 CAM_PAD_TO_4K); 1786 break; 1787 default: 1788 CDBG_ERROR("%s: Invalid cam_format for preview %d", 1789 __func__, fmt); 1790 rc = -1; 1791 break; 1792 } 1793 1794 return rc; 1795 } 1796 1797 /*=========================================================================== 1798 * FUNCTION : mm_stream_calc_offset_snapshot 1799 * 1800 * DESCRIPTION: calculate snapshot/postproc frame offset based on format and 1801 * padding information 1802 * 1803 * PARAMETERS : 1804 * @fmt : image format 1805 * @dim : image dimension 1806 * @padding : padding information 1807 * @buf_planes : [out] buffer plane information 1808 * 1809 * RETURN : int32_t type of status 1810 * 0 -- success 1811 * -1 -- failure 1812 *==========================================================================*/ 1813 int32_t mm_stream_calc_offset_snapshot(cam_format_t fmt, 1814 cam_dimension_t *dim, 1815 cam_padding_info_t *padding, 1816 cam_stream_buf_plane_info_t *buf_planes) 1817 { 1818 int32_t rc = 0; 1819 uint8_t isAFamily = mm_camera_util_chip_is_a_family(); 1820 int offset_x = 0, offset_y = 0; 1821 int stride = 0, scanline = 0; 1822 1823 if (isAFamily) { 1824 stride = dim->width; 1825 scanline = PAD_TO_SIZE(dim->height, CAM_PAD_TO_16); 1826 offset_x = 0; 1827 offset_y = scanline - dim->height; 1828 scanline += offset_y; /* double padding */ 1829 } else { 1830 stride = PAD_TO_SIZE(dim->width, 1831 padding->width_padding); 1832 scanline = PAD_TO_SIZE(dim->height, 1833 padding->height_padding); 1834 offset_x = 0; 1835 offset_y = 0; 1836 } 1837 1838 switch (fmt) { 1839 case CAM_FORMAT_YUV_420_NV12: 1840 case CAM_FORMAT_YUV_420_NV21: 1841 /* 2 planes: Y + CbCr */ 1842 buf_planes->plane_info.num_planes = 2; 1843 1844 buf_planes->plane_info.mp[0].len = 1845 PAD_TO_SIZE(stride * scanline, 1846 padding->plane_padding); 1847 buf_planes->plane_info.mp[0].offset = 1848 PAD_TO_SIZE(offset_x + stride * offset_y, 1849 padding->plane_padding); 1850 buf_planes->plane_info.mp[0].offset_x = offset_x; 1851 buf_planes->plane_info.mp[0].offset_y = offset_y; 1852 buf_planes->plane_info.mp[0].stride = stride; 1853 buf_planes->plane_info.mp[0].scanline = scanline; 1854 1855 scanline = scanline / 2; 1856 buf_planes->plane_info.mp[1].len = 1857 PAD_TO_SIZE(stride * scanline, 1858 padding->plane_padding); 1859 buf_planes->plane_info.mp[1].offset = 1860 PAD_TO_SIZE(offset_x + stride * offset_y, 1861 padding->plane_padding); 1862 buf_planes->plane_info.mp[1].offset_x = offset_x; 1863 buf_planes->plane_info.mp[1].offset_y = offset_y; 1864 buf_planes->plane_info.mp[1].stride = stride; 1865 buf_planes->plane_info.mp[1].scanline = scanline; 1866 1867 buf_planes->plane_info.frame_len = 1868 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len + 1869 buf_planes->plane_info.mp[1].len, 1870 CAM_PAD_TO_4K); 1871 break; 1872 case CAM_FORMAT_YUV_420_YV12: 1873 /* 3 planes: Y + Cr + Cb */ 1874 buf_planes->plane_info.num_planes = 3; 1875 1876 buf_planes->plane_info.mp[0].offset = 1877 PAD_TO_SIZE(offset_x + stride * offset_y, 1878 padding->plane_padding); 1879 buf_planes->plane_info.mp[0].len = 1880 PAD_TO_SIZE(stride * scanline, padding->plane_padding); 1881 buf_planes->plane_info.mp[0].offset_x = offset_x; 1882 buf_planes->plane_info.mp[0].offset_y = offset_y; 1883 buf_planes->plane_info.mp[0].stride = stride; 1884 buf_planes->plane_info.mp[0].scanline = scanline; 1885 1886 stride = PAD_TO_SIZE(stride / 2, CAM_PAD_TO_16); 1887 scanline = scanline / 2; 1888 buf_planes->plane_info.mp[1].offset = 1889 PAD_TO_SIZE(offset_x + stride * offset_y, 1890 padding->plane_padding); 1891 buf_planes->plane_info.mp[1].len = 1892 PAD_TO_SIZE(stride * scanline, padding->plane_padding); 1893 buf_planes->plane_info.mp[1].offset_x = offset_x; 1894 buf_planes->plane_info.mp[1].offset_y = offset_y; 1895 buf_planes->plane_info.mp[1].stride = stride; 1896 buf_planes->plane_info.mp[1].scanline = scanline; 1897 1898 buf_planes->plane_info.mp[2].offset = 1899 PAD_TO_SIZE(offset_x + stride * offset_y, 1900 padding->plane_padding); 1901 buf_planes->plane_info.mp[2].len = 1902 PAD_TO_SIZE(stride * scanline, padding->plane_padding); 1903 buf_planes->plane_info.mp[2].offset_x = offset_x; 1904 buf_planes->plane_info.mp[2].offset_y = offset_y; 1905 buf_planes->plane_info.mp[2].stride = stride; 1906 buf_planes->plane_info.mp[2].scanline = scanline; 1907 1908 buf_planes->plane_info.frame_len = 1909 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len + 1910 buf_planes->plane_info.mp[1].len + 1911 buf_planes->plane_info.mp[2].len, 1912 CAM_PAD_TO_4K); 1913 break; 1914 case CAM_FORMAT_YUV_422_NV16: 1915 case CAM_FORMAT_YUV_422_NV61: 1916 /* 2 planes: Y + CbCr */ 1917 buf_planes->plane_info.num_planes = 2; 1918 buf_planes->plane_info.mp[0].len = 1919 PAD_TO_SIZE(stride * scanline, padding->plane_padding); 1920 buf_planes->plane_info.mp[0].offset = 1921 PAD_TO_SIZE(offset_x + stride * offset_y, 1922 padding->plane_padding); 1923 buf_planes->plane_info.mp[0].offset_x = offset_x; 1924 buf_planes->plane_info.mp[0].offset_y = offset_y; 1925 buf_planes->plane_info.mp[0].stride = stride; 1926 buf_planes->plane_info.mp[0].scanline = scanline; 1927 1928 buf_planes->plane_info.mp[1].len = 1929 PAD_TO_SIZE(stride * scanline, padding->plane_padding); 1930 buf_planes->plane_info.mp[1].offset = 1931 PAD_TO_SIZE(offset_x + stride * offset_y, 1932 padding->plane_padding); 1933 buf_planes->plane_info.mp[1].offset_x = offset_x; 1934 buf_planes->plane_info.mp[1].offset_y = offset_y; 1935 buf_planes->plane_info.mp[1].stride = stride; 1936 buf_planes->plane_info.mp[1].scanline = scanline; 1937 1938 buf_planes->plane_info.frame_len = PAD_TO_SIZE( 1939 buf_planes->plane_info.mp[0].len + buf_planes->plane_info.mp[1].len, 1940 CAM_PAD_TO_4K); 1941 break; 1942 default: 1943 CDBG_ERROR("%s: Invalid cam_format for snapshot %d", 1944 __func__, fmt); 1945 rc = -1; 1946 break; 1947 } 1948 1949 return rc; 1950 } 1951 1952 /*=========================================================================== 1953 * FUNCTION : mm_stream_calc_offset_raw 1954 * 1955 * DESCRIPTION: calculate raw frame offset based on format and padding information 1956 * 1957 * PARAMETERS : 1958 * @fmt : image format 1959 * @dim : image dimension 1960 * @padding : padding information 1961 * @buf_planes : [out] buffer plane information 1962 * 1963 * RETURN : int32_t type of status 1964 * 0 -- success 1965 * -1 -- failure 1966 *==========================================================================*/ 1967 int32_t mm_stream_calc_offset_raw(cam_format_t fmt, 1968 cam_dimension_t *dim, 1969 cam_padding_info_t *padding, 1970 cam_stream_buf_plane_info_t *buf_planes) 1971 { 1972 int32_t rc = 0; 1973 int stride = 0; 1974 int scanline = dim->height; 1975 1976 switch (fmt) { 1977 case CAM_FORMAT_YUV_RAW_8BIT_YUYV: 1978 case CAM_FORMAT_YUV_RAW_8BIT_YVYU: 1979 case CAM_FORMAT_YUV_RAW_8BIT_UYVY: 1980 case CAM_FORMAT_YUV_RAW_8BIT_VYUY: 1981 case CAM_FORMAT_JPEG_RAW_8BIT: 1982 case CAM_FORMAT_META_RAW_8BIT: 1983 /* 1 plane */ 1984 /* Every 16 pixels occupy 16 bytes */ 1985 stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16); 1986 buf_planes->plane_info.num_planes = 1; 1987 buf_planes->plane_info.mp[0].offset = 0; 1988 buf_planes->plane_info.mp[0].len = 1989 PAD_TO_SIZE(stride * scanline * 2, padding->plane_padding); 1990 buf_planes->plane_info.frame_len = 1991 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K); 1992 buf_planes->plane_info.mp[0].offset_x =0; 1993 buf_planes->plane_info.mp[0].offset_y = 0; 1994 buf_planes->plane_info.mp[0].stride = stride; 1995 buf_planes->plane_info.mp[0].scanline = scanline; 1996 break; 1997 case CAM_FORMAT_BAYER_QCOM_RAW_8BPP_GBRG: 1998 case CAM_FORMAT_BAYER_QCOM_RAW_8BPP_GRBG: 1999 case CAM_FORMAT_BAYER_QCOM_RAW_8BPP_RGGB: 2000 case CAM_FORMAT_BAYER_QCOM_RAW_8BPP_BGGR: 2001 case CAM_FORMAT_BAYER_MIPI_RAW_8BPP_GBRG: 2002 case CAM_FORMAT_BAYER_MIPI_RAW_8BPP_GRBG: 2003 case CAM_FORMAT_BAYER_MIPI_RAW_8BPP_RGGB: 2004 case CAM_FORMAT_BAYER_MIPI_RAW_8BPP_BGGR: 2005 case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_8BPP_GBRG: 2006 case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_8BPP_GRBG: 2007 case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_8BPP_RGGB: 2008 case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_8BPP_BGGR: 2009 case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_8BPP_GBRG: 2010 case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_8BPP_GRBG: 2011 case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_8BPP_RGGB: 2012 case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_8BPP_BGGR: 2013 case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN8_8BPP_GBRG: 2014 case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN8_8BPP_GRBG: 2015 case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN8_8BPP_RGGB: 2016 case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN8_8BPP_BGGR: 2017 /* 1 plane */ 2018 /* Every 16 pixels occupy 16 bytes */ 2019 stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16); 2020 buf_planes->plane_info.num_planes = 1; 2021 buf_planes->plane_info.mp[0].offset = 0; 2022 buf_planes->plane_info.mp[0].len = 2023 PAD_TO_SIZE(stride * scanline, padding->plane_padding); 2024 buf_planes->plane_info.frame_len = 2025 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K); 2026 buf_planes->plane_info.mp[0].offset_x =0; 2027 buf_planes->plane_info.mp[0].offset_y = 0; 2028 buf_planes->plane_info.mp[0].stride = stride; 2029 buf_planes->plane_info.mp[0].scanline = scanline; 2030 break; 2031 case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_GBRG: 2032 case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_GRBG: 2033 case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_RGGB: 2034 case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_BGGR: 2035 case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_10BPP_GBRG: 2036 case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_10BPP_GRBG: 2037 case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_10BPP_RGGB: 2038 case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_10BPP_BGGR: 2039 /* Every 12 pixels occupy 16 bytes */ 2040 stride = (dim->width + 11)/12 * 12; 2041 buf_planes->plane_info.num_planes = 1; 2042 buf_planes->plane_info.mp[0].offset = 0; 2043 buf_planes->plane_info.mp[0].len = 2044 PAD_TO_SIZE(stride * scanline * 8 / 6, padding->plane_padding); 2045 buf_planes->plane_info.frame_len = 2046 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K); 2047 buf_planes->plane_info.mp[0].offset_x =0; 2048 buf_planes->plane_info.mp[0].offset_y = 0; 2049 buf_planes->plane_info.mp[0].stride = stride; 2050 buf_planes->plane_info.mp[0].scanline = scanline; 2051 break; 2052 case CAM_FORMAT_BAYER_QCOM_RAW_12BPP_GBRG: 2053 case CAM_FORMAT_BAYER_QCOM_RAW_12BPP_GRBG: 2054 case CAM_FORMAT_BAYER_QCOM_RAW_12BPP_RGGB: 2055 case CAM_FORMAT_BAYER_QCOM_RAW_12BPP_BGGR: 2056 case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_12BPP_GBRG: 2057 case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_12BPP_GRBG: 2058 case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_12BPP_RGGB: 2059 case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_12BPP_BGGR: 2060 /* Every 10 pixels occupy 16 bytes */ 2061 stride = (dim->width + 9)/10 * 10; 2062 buf_planes->plane_info.num_planes = 1; 2063 buf_planes->plane_info.mp[0].offset = 0; 2064 buf_planes->plane_info.mp[0].len = 2065 PAD_TO_SIZE(stride * scanline * 8 / 5, padding->plane_padding); 2066 buf_planes->plane_info.frame_len = 2067 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K); 2068 buf_planes->plane_info.mp[0].offset_x =0; 2069 buf_planes->plane_info.mp[0].offset_y = 0; 2070 buf_planes->plane_info.mp[0].stride = stride; 2071 buf_planes->plane_info.mp[0].scanline = scanline; 2072 break; 2073 case CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GBRG: 2074 case CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GRBG: 2075 case CAM_FORMAT_BAYER_MIPI_RAW_10BPP_RGGB: 2076 case CAM_FORMAT_BAYER_MIPI_RAW_10BPP_BGGR: 2077 case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_10BPP_GBRG: 2078 case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_10BPP_GRBG: 2079 case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_10BPP_RGGB: 2080 case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_10BPP_BGGR: 2081 /* Every 64 pixels occupy 80 bytes */ 2082 stride = PAD_TO_SIZE(dim->width * 5 / 4, CAM_PAD_TO_8); 2083 buf_planes->plane_info.num_planes = 1; 2084 buf_planes->plane_info.mp[0].offset = 0; 2085 buf_planes->plane_info.mp[0].len = 2086 PAD_TO_SIZE(stride * scanline, padding->plane_padding); 2087 buf_planes->plane_info.frame_len = 2088 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K); 2089 buf_planes->plane_info.mp[0].offset_x =0; 2090 buf_planes->plane_info.mp[0].offset_y = 0; 2091 buf_planes->plane_info.mp[0].stride = stride; 2092 buf_planes->plane_info.mp[0].scanline = scanline; 2093 break; 2094 case CAM_FORMAT_BAYER_MIPI_RAW_12BPP_GBRG: 2095 case CAM_FORMAT_BAYER_MIPI_RAW_12BPP_GRBG: 2096 case CAM_FORMAT_BAYER_MIPI_RAW_12BPP_RGGB: 2097 case CAM_FORMAT_BAYER_MIPI_RAW_12BPP_BGGR: 2098 case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_12BPP_GBRG: 2099 case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_12BPP_GRBG: 2100 case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_12BPP_RGGB: 2101 case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_12BPP_BGGR: 2102 /* Every 32 pixels occupy 48 bytes */ 2103 stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_32); 2104 buf_planes->plane_info.num_planes = 1; 2105 buf_planes->plane_info.mp[0].offset = 0; 2106 buf_planes->plane_info.mp[0].len = 2107 PAD_TO_SIZE(stride * scanline * 3 / 2, padding->plane_padding); 2108 buf_planes->plane_info.frame_len = 2109 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K); 2110 buf_planes->plane_info.mp[0].offset_x =0; 2111 buf_planes->plane_info.mp[0].offset_y = 0; 2112 buf_planes->plane_info.mp[0].stride = stride; 2113 buf_planes->plane_info.mp[0].scanline = scanline; 2114 break; 2115 case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_8BPP_GBRG: 2116 case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_8BPP_GRBG: 2117 case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_8BPP_RGGB: 2118 case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_8BPP_BGGR: 2119 case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_10BPP_GBRG: 2120 case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_10BPP_GRBG: 2121 case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_10BPP_RGGB: 2122 case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_10BPP_BGGR: 2123 case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_12BPP_GBRG: 2124 case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_12BPP_GRBG: 2125 case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_12BPP_RGGB: 2126 case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_12BPP_BGGR: 2127 /* Every 8 pixels occupy 16 bytes */ 2128 stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_8); 2129 buf_planes->plane_info.num_planes = 1; 2130 buf_planes->plane_info.mp[0].offset = 0; 2131 buf_planes->plane_info.mp[0].len = 2132 PAD_TO_SIZE(stride * scanline * 2, padding->plane_padding); 2133 buf_planes->plane_info.frame_len = 2134 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K); 2135 buf_planes->plane_info.mp[0].offset_x =0; 2136 buf_planes->plane_info.mp[0].offset_y = 0; 2137 buf_planes->plane_info.mp[0].stride = stride; 2138 buf_planes->plane_info.mp[0].scanline = scanline; 2139 break; 2140 default: 2141 CDBG_ERROR("%s: Invalid cam_format %d for raw stream", 2142 __func__, fmt); 2143 rc = -1; 2144 break; 2145 } 2146 2147 return rc; 2148 } 2149 2150 /*=========================================================================== 2151 * FUNCTION : mm_stream_calc_offset_video 2152 * 2153 * DESCRIPTION: calculate video frame offset based on format and 2154 * padding information 2155 * 2156 * PARAMETERS : 2157 * @dim : image dimension 2158 * @buf_planes : [out] buffer plane information 2159 * 2160 * RETURN : int32_t type of status 2161 * 0 -- success 2162 * -1 -- failure 2163 *==========================================================================*/ 2164 #ifdef VENUS_PRESENT 2165 int32_t mm_stream_calc_offset_video(cam_dimension_t *dim, 2166 cam_stream_buf_plane_info_t *buf_planes) 2167 { 2168 int stride = 0, scanline = 0; 2169 2170 // using Venus 2171 stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, dim->width); 2172 scanline = VENUS_Y_SCANLINES(COLOR_FMT_NV12, dim->height); 2173 2174 buf_planes->plane_info.frame_len = 2175 VENUS_BUFFER_SIZE(COLOR_FMT_NV12, dim->width, dim->height); 2176 buf_planes->plane_info.num_planes = 2; 2177 buf_planes->plane_info.mp[0].len = stride * scanline; 2178 buf_planes->plane_info.mp[0].offset = 0; 2179 buf_planes->plane_info.mp[0].offset_x =0; 2180 buf_planes->plane_info.mp[0].offset_y = 0; 2181 buf_planes->plane_info.mp[0].stride = stride; 2182 buf_planes->plane_info.mp[0].scanline = scanline; 2183 stride = VENUS_UV_STRIDE(COLOR_FMT_NV12, dim->width); 2184 scanline = VENUS_UV_SCANLINES(COLOR_FMT_NV12, dim->height); 2185 buf_planes->plane_info.mp[1].len = 2186 buf_planes->plane_info.frame_len - buf_planes->plane_info.mp[0].len; 2187 buf_planes->plane_info.mp[1].offset = 0; 2188 buf_planes->plane_info.mp[1].offset_x =0; 2189 buf_planes->plane_info.mp[1].offset_y = 0; 2190 buf_planes->plane_info.mp[1].stride = stride; 2191 buf_planes->plane_info.mp[1].scanline = scanline; 2192 2193 return 0; 2194 } 2195 #else 2196 int32_t mm_stream_calc_offset_video(cam_dimension_t *dim, 2197 cam_stream_buf_plane_info_t *buf_planes) 2198 { 2199 int stride = 0, scanline = 0; 2200 2201 buf_planes->plane_info.num_planes = 2; 2202 2203 stride = dim->width; 2204 scanline = dim->height; 2205 buf_planes->plane_info.mp[0].len = 2206 PAD_TO_SIZE(stride * scanline, CAM_PAD_TO_2K); 2207 buf_planes->plane_info.mp[0].offset = 0; 2208 buf_planes->plane_info.mp[0].offset_x =0; 2209 buf_planes->plane_info.mp[0].offset_y = 0; 2210 buf_planes->plane_info.mp[0].stride = stride; 2211 buf_planes->plane_info.mp[0].scanline = scanline; 2212 2213 stride = dim->width; 2214 scanline = dim->height / 2; 2215 buf_planes->plane_info.mp[1].len = 2216 PAD_TO_SIZE(stride * scanline, CAM_PAD_TO_2K); 2217 buf_planes->plane_info.mp[1].offset = 0; 2218 buf_planes->plane_info.mp[1].offset_x =0; 2219 buf_planes->plane_info.mp[1].offset_y = 0; 2220 buf_planes->plane_info.mp[1].stride = stride; 2221 buf_planes->plane_info.mp[1].scanline = scanline; 2222 2223 buf_planes->plane_info.frame_len = 2224 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len + 2225 buf_planes->plane_info.mp[1].len, 2226 CAM_PAD_TO_4K); 2227 2228 return 0; 2229 } 2230 #endif 2231 2232 /*=========================================================================== 2233 * FUNCTION : mm_stream_calc_offset_metadata 2234 * 2235 * DESCRIPTION: calculate metadata frame offset based on format and 2236 * padding information 2237 * 2238 * PARAMETERS : 2239 * @dim : image dimension 2240 * @padding : padding information 2241 * @buf_planes : [out] buffer plane information 2242 * 2243 * RETURN : int32_t type of status 2244 * 0 -- success 2245 * -1 -- failure 2246 *==========================================================================*/ 2247 int32_t mm_stream_calc_offset_metadata(cam_dimension_t *dim, 2248 cam_padding_info_t *padding, 2249 cam_stream_buf_plane_info_t *buf_planes) 2250 { 2251 int32_t rc = 0; 2252 buf_planes->plane_info.num_planes = 1; 2253 buf_planes->plane_info.mp[0].offset = 0; 2254 buf_planes->plane_info.mp[0].len = 2255 PAD_TO_SIZE(dim->width * dim->height, padding->plane_padding); 2256 buf_planes->plane_info.frame_len = 2257 buf_planes->plane_info.mp[0].len; 2258 2259 buf_planes->plane_info.mp[0].offset_x =0; 2260 buf_planes->plane_info.mp[0].offset_y = 0; 2261 buf_planes->plane_info.mp[0].stride = dim->width; 2262 buf_planes->plane_info.mp[0].scanline = dim->height; 2263 return rc; 2264 } 2265 2266 /*=========================================================================== 2267 * FUNCTION : mm_stream_calc_offset_postproc 2268 * 2269 * DESCRIPTION: calculate postprocess frame offset 2270 * 2271 * PARAMETERS : 2272 * @stream_info: ptr to stream info 2273 * @padding : padding information 2274 * @buf_planes : [out] buffer plane information 2275 * 2276 * RETURN : int32_t type of status 2277 * 0 -- success 2278 * -1 -- failure 2279 *==========================================================================*/ 2280 int32_t mm_stream_calc_offset_postproc(cam_stream_info_t *stream_info, 2281 cam_padding_info_t *padding, 2282 cam_stream_buf_plane_info_t *buf_planes) 2283 { 2284 int32_t rc = 0; 2285 if (stream_info->reprocess_config.pp_type == CAM_OFFLINE_REPROCESS_TYPE) { 2286 if (buf_planes->plane_info.frame_len == 0) { 2287 // take offset from input source 2288 *buf_planes = stream_info->reprocess_config.offline.input_buf_planes; 2289 } 2290 return rc; 2291 } 2292 2293 switch (stream_info->reprocess_config.online.input_stream_type) { 2294 case CAM_STREAM_TYPE_PREVIEW: 2295 case CAM_STREAM_TYPE_CALLBACK: 2296 case CAM_STREAM_TYPE_POSTVIEW: 2297 rc = mm_stream_calc_offset_preview(stream_info->fmt, 2298 &stream_info->dim, 2299 buf_planes); 2300 break; 2301 case CAM_STREAM_TYPE_SNAPSHOT: 2302 case CAM_STREAM_TYPE_NON_ZSL_SNAPSHOT: 2303 rc = mm_stream_calc_offset_snapshot(stream_info->fmt, 2304 &stream_info->dim, 2305 padding, 2306 buf_planes); 2307 break; 2308 case CAM_STREAM_TYPE_VIDEO: 2309 rc = mm_stream_calc_offset_video(&stream_info->dim, 2310 buf_planes); 2311 break; 2312 case CAM_STREAM_TYPE_RAW: 2313 rc = mm_stream_calc_offset_raw(stream_info->fmt, 2314 &stream_info->dim, 2315 padding, 2316 buf_planes); 2317 break; 2318 case CAM_STREAM_TYPE_METADATA: 2319 rc = mm_stream_calc_offset_metadata(&stream_info->dim, 2320 padding, 2321 buf_planes); 2322 break; 2323 default: 2324 CDBG_ERROR("%s: not supported for stream type %d", 2325 __func__, stream_info->reprocess_config.online.input_stream_type); 2326 rc = -1; 2327 break; 2328 } 2329 return rc; 2330 } 2331 2332 /*=========================================================================== 2333 * FUNCTION : mm_stream_calc_offset 2334 * 2335 * DESCRIPTION: calculate frame offset based on format and padding information 2336 * 2337 * PARAMETERS : 2338 * @my_obj : stream object 2339 * 2340 * RETURN : int32_t type of status 2341 * 0 -- success 2342 * -1 -- failure 2343 *==========================================================================*/ 2344 int32_t mm_stream_calc_offset(mm_stream_t *my_obj) 2345 { 2346 int32_t rc = 0; 2347 2348 cam_dimension_t dim = my_obj->stream_info->dim; 2349 if (my_obj->stream_info->pp_config.feature_mask & CAM_QCOM_FEATURE_ROTATION) { 2350 if (my_obj->stream_info->pp_config.rotation == ROTATE_90 || 2351 my_obj->stream_info->pp_config.rotation == ROTATE_270) { 2352 // rotated by 90 or 270, need to switch width and height 2353 dim.width = my_obj->stream_info->dim.height; 2354 dim.height = my_obj->stream_info->dim.width; 2355 } 2356 } 2357 2358 switch (my_obj->stream_info->stream_type) { 2359 case CAM_STREAM_TYPE_PREVIEW: 2360 case CAM_STREAM_TYPE_CALLBACK: 2361 case CAM_STREAM_TYPE_POSTVIEW: 2362 rc = mm_stream_calc_offset_preview(my_obj->stream_info->fmt, 2363 &dim, 2364 &my_obj->stream_info->buf_planes); 2365 break; 2366 case CAM_STREAM_TYPE_SNAPSHOT: 2367 case CAM_STREAM_TYPE_NON_ZSL_SNAPSHOT: 2368 rc = mm_stream_calc_offset_snapshot(my_obj->stream_info->fmt, 2369 &dim, 2370 &my_obj->padding_info, 2371 &my_obj->stream_info->buf_planes); 2372 break; 2373 case CAM_STREAM_TYPE_OFFLINE_PROC: 2374 rc = mm_stream_calc_offset_postproc(my_obj->stream_info, 2375 &my_obj->padding_info, 2376 &my_obj->stream_info->buf_planes); 2377 break; 2378 case CAM_STREAM_TYPE_VIDEO: 2379 rc = mm_stream_calc_offset_video(&dim, 2380 &my_obj->stream_info->buf_planes); 2381 break; 2382 case CAM_STREAM_TYPE_RAW: 2383 rc = mm_stream_calc_offset_raw(my_obj->stream_info->fmt, 2384 &dim, 2385 &my_obj->padding_info, 2386 &my_obj->stream_info->buf_planes); 2387 break; 2388 case CAM_STREAM_TYPE_METADATA: 2389 rc = mm_stream_calc_offset_metadata(&dim, 2390 &my_obj->padding_info, 2391 &my_obj->stream_info->buf_planes); 2392 break; 2393 default: 2394 CDBG_ERROR("%s: not supported for stream type %d", 2395 __func__, my_obj->stream_info->stream_type); 2396 rc = -1; 2397 break; 2398 } 2399 2400 my_obj->frame_offset = my_obj->stream_info->buf_planes.plane_info; 2401 return rc; 2402 } 2403 2404 /*=========================================================================== 2405 * FUNCTION : mm_stream_sync_info 2406 * 2407 * DESCRIPTION: synchronize stream information with server 2408 * 2409 * PARAMETERS : 2410 * @my_obj : stream object 2411 * 2412 * RETURN : int32_t type of status 2413 * 0 -- success 2414 * -1 -- failure 2415 * NOTE : assume stream info buffer is mapped to server and filled in with 2416 * stream information by upper layer. This call will let server to 2417 * synchornize the stream information with HAL. If server find any 2418 * fields that need to be changed accroding to hardware configuration, 2419 * server will modify corresponding fields so that HAL could know 2420 * about it. 2421 *==========================================================================*/ 2422 int32_t mm_stream_sync_info(mm_stream_t *my_obj) 2423 { 2424 int32_t rc = 0; 2425 int32_t value = 0; 2426 my_obj->stream_info->stream_svr_id = my_obj->server_stream_id; 2427 rc = mm_stream_calc_offset(my_obj); 2428 2429 if (rc == 0) { 2430 rc = mm_camera_util_s_ctrl(my_obj->fd, 2431 CAM_PRIV_STREAM_INFO_SYNC, 2432 &value); 2433 } 2434 return rc; 2435 } 2436 2437 /*=========================================================================== 2438 * FUNCTION : mm_stream_set_fmt 2439 * 2440 * DESCRIPTION: set stream format to kernel via v4l2 ioctl 2441 * 2442 * PARAMETERS : 2443 * @my_obj : stream object 2444 * 2445 * RETURN : int32_t type of status 2446 * 0 -- success 2447 * -1 -- failure 2448 *==========================================================================*/ 2449 int32_t mm_stream_set_fmt(mm_stream_t *my_obj) 2450 { 2451 int32_t rc = 0; 2452 struct v4l2_format fmt; 2453 struct msm_v4l2_format_data msm_fmt; 2454 int i; 2455 2456 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d", 2457 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state); 2458 2459 if (my_obj->stream_info->dim.width == 0 || 2460 my_obj->stream_info->dim.height == 0) { 2461 CDBG_ERROR("%s:invalid input[w=%d,h=%d,fmt=%d]\n", 2462 __func__, 2463 my_obj->stream_info->dim.width, 2464 my_obj->stream_info->dim.height, 2465 my_obj->stream_info->fmt); 2466 return -1; 2467 } 2468 2469 memset(&fmt, 0, sizeof(fmt)); 2470 memset(&msm_fmt, 0, sizeof(msm_fmt)); 2471 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 2472 msm_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 2473 msm_fmt.width = my_obj->stream_info->dim.width; 2474 msm_fmt.height = my_obj->stream_info->dim.height; 2475 msm_fmt.pixelformat = mm_stream_get_v4l2_fmt(my_obj->stream_info->fmt); 2476 msm_fmt.num_planes = my_obj->frame_offset.num_planes; 2477 for (i = 0; i < msm_fmt.num_planes; i++) { 2478 msm_fmt.plane_sizes[i] = my_obj->frame_offset.mp[i].len; 2479 } 2480 2481 memcpy(fmt.fmt.raw_data, &msm_fmt, sizeof(msm_fmt)); 2482 rc = ioctl(my_obj->fd, VIDIOC_S_FMT, &fmt); 2483 return rc; 2484 } 2485 2486 /*=========================================================================== 2487 * FUNCTION : mm_stream_buf_done 2488 * 2489 * DESCRIPTION: enqueue buffer back to kernel 2490 * 2491 * PARAMETERS : 2492 * @my_obj : stream object 2493 * @frame : frame to be enqueued back to kernel 2494 * 2495 * RETURN : int32_t type of status 2496 * 0 -- success 2497 * -1 -- failure 2498 *==========================================================================*/ 2499 int32_t mm_stream_buf_done(mm_stream_t * my_obj, 2500 mm_camera_buf_def_t *frame) 2501 { 2502 int32_t rc = 0; 2503 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d", 2504 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state); 2505 2506 pthread_mutex_lock(&my_obj->buf_lock); 2507 if(my_obj->buf_status[frame->buf_idx].buf_refcnt == 0) { 2508 CDBG("%s: Error Trying to free second time?(idx=%d) count=%d\n", 2509 __func__, frame->buf_idx, 2510 my_obj->buf_status[frame->buf_idx].buf_refcnt); 2511 rc = -1; 2512 }else{ 2513 my_obj->buf_status[frame->buf_idx].buf_refcnt--; 2514 if (0 == my_obj->buf_status[frame->buf_idx].buf_refcnt) { 2515 CDBG("<DEBUG> : Buf done for buffer:%d, stream:%d", frame->buf_idx, frame->stream_type); 2516 rc = mm_stream_qbuf(my_obj, frame); 2517 if(rc < 0) { 2518 CDBG_ERROR("%s: mm_camera_stream_qbuf(idx=%d) err=%d\n", 2519 __func__, frame->buf_idx, rc); 2520 } else { 2521 my_obj->buf_status[frame->buf_idx].in_kernel = 1; 2522 } 2523 }else{ 2524 CDBG("<DEBUG> : Still ref count pending count :%d", 2525 my_obj->buf_status[frame->buf_idx].buf_refcnt); 2526 CDBG("<DEBUG> : for buffer:%p:%d", 2527 my_obj, frame->buf_idx); 2528 } 2529 } 2530 pthread_mutex_unlock(&my_obj->buf_lock); 2531 return rc; 2532 } 2533 2534 /*=========================================================================== 2535 * FUNCTION : mm_stream_reg_buf_cb 2536 * 2537 * DESCRIPTION: Allow other stream to register dataCB at this stream. 2538 * 2539 * PARAMETERS : 2540 * @my_obj : stream object 2541 * @val : ptr to info about the callback to be registered 2542 * 2543 * RETURN : int32_t type of status 2544 * 0 -- success 2545 * -1 -- failure 2546 *==========================================================================*/ 2547 int32_t mm_stream_reg_buf_cb(mm_stream_t *my_obj, 2548 mm_stream_data_cb_t *val) 2549 { 2550 int32_t rc = -1; 2551 uint8_t i; 2552 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d", 2553 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state); 2554 2555 pthread_mutex_lock(&my_obj->cb_lock); 2556 for (i=0 ;i < MM_CAMERA_STREAM_BUF_CB_MAX; i++) { 2557 if(NULL == my_obj->buf_cb[i].cb) { 2558 my_obj->buf_cb[i] = *val; 2559 rc = 0; 2560 break; 2561 } 2562 } 2563 pthread_mutex_unlock(&my_obj->cb_lock); 2564 2565 return rc; 2566 } 2567