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