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