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 1270 CDBG("%s: VIDIOC_DQBUF buf_index %d, frame_idx %d, stream type %d, rc %d," 1271 "queued: %d, buf_type = %d", 1272 __func__, vb.index, buf_info->buf->frame_idx, 1273 my_obj->stream_info->stream_type, rc, 1274 my_obj->queued_buffer_count, buf_info->buf->buf_type); 1275 1276 buf_info->buf->is_uv_subsampled = 1277 (vb.reserved == V4L2_PIX_FMT_NV14 || vb.reserved == V4L2_PIX_FMT_NV41); 1278 1279 if(buf_info->buf->buf_type == CAM_STREAM_BUF_TYPE_USERPTR) { 1280 mm_stream_read_user_buf(my_obj, buf_info); 1281 } 1282 pthread_mutex_unlock(&my_obj->buf_lock); 1283 1284 if ( NULL != my_obj->mem_vtbl.clean_invalidate_buf ) { 1285 rc = my_obj->mem_vtbl.clean_invalidate_buf(idx, 1286 my_obj->mem_vtbl.user_data); 1287 if (0 > rc) { 1288 CDBG_ERROR("%s: Clean invalidate cache failed on buffer index: %d", 1289 __func__, idx); 1290 } 1291 } else { 1292 CDBG_ERROR("%s: Clean invalidate cache op not supported", __func__); 1293 } 1294 } 1295 1296 CDBG("%s :X rc = %d",__func__,rc); 1297 return rc; 1298 } 1299 1300 /*=========================================================================== 1301 * FUNCTION : mm_stream_set_parms 1302 * 1303 * DESCRIPTION: set parameters per stream 1304 * 1305 * PARAMETERS : 1306 * @my_obj : stream object 1307 * @in_value : ptr to a param struct to be set to server 1308 * 1309 * RETURN : int32_t type of status 1310 * 0 -- success 1311 * -1 -- failure 1312 * NOTE : Assume the parms struct buf is already mapped to server via 1313 * domain socket. Corresponding fields of parameters to be set 1314 * are already filled in by upper layer caller. 1315 *==========================================================================*/ 1316 int32_t mm_stream_set_parm(mm_stream_t *my_obj, 1317 cam_stream_parm_buffer_t *in_value) 1318 { 1319 int32_t rc = -1; 1320 int32_t value = 0; 1321 if (in_value != NULL) { 1322 rc = mm_camera_util_s_ctrl(my_obj->fd, CAM_PRIV_STREAM_PARM, &value); 1323 } 1324 return rc; 1325 } 1326 1327 /*=========================================================================== 1328 * FUNCTION : mm_stream_get_parms 1329 * 1330 * DESCRIPTION: get parameters per stream 1331 * 1332 * PARAMETERS : 1333 * @my_obj : stream object 1334 * @in_value : ptr to a param struct to be get from server 1335 * 1336 * RETURN : int32_t type of status 1337 * 0 -- success 1338 * -1 -- failure 1339 * NOTE : Assume the parms struct buf is already mapped to server via 1340 * domain socket. Corresponding fields of parameters to be get 1341 * are already filled in by upper layer caller. 1342 *==========================================================================*/ 1343 int32_t mm_stream_get_parm(mm_stream_t *my_obj, 1344 cam_stream_parm_buffer_t *in_value) 1345 { 1346 int32_t rc = -1; 1347 int32_t value = 0; 1348 if (in_value != NULL) { 1349 rc = mm_camera_util_g_ctrl(my_obj->fd, CAM_PRIV_STREAM_PARM, &value); 1350 } 1351 return rc; 1352 } 1353 1354 /*=========================================================================== 1355 * FUNCTION : mm_stream_do_actions 1356 * 1357 * DESCRIPTION: request server to perform stream based actions 1358 * 1359 * PARAMETERS : 1360 * @my_obj : stream object 1361 * @in_value : ptr to a struct of actions to be performed by the server 1362 * 1363 * RETURN : int32_t type of status 1364 * 0 -- success 1365 * -1 -- failure 1366 * NOTE : Assume the action struct buf is already mapped to server via 1367 * domain socket. Corresponding fields of actions to be performed 1368 * are already filled in by upper layer caller. 1369 *==========================================================================*/ 1370 int32_t mm_stream_do_action(mm_stream_t *my_obj, 1371 void *in_value) 1372 { 1373 int32_t rc = -1; 1374 int32_t value = 0; 1375 if (in_value != NULL) { 1376 rc = mm_camera_util_s_ctrl(my_obj->fd, CAM_PRIV_STREAM_PARM, &value); 1377 } 1378 return rc; 1379 } 1380 1381 /*=========================================================================== 1382 * FUNCTION : mm_stream_set_ext_mode 1383 * 1384 * DESCRIPTION: set stream extended mode to server via v4l2 ioctl 1385 * 1386 * PARAMETERS : 1387 * @my_obj : stream object 1388 * 1389 * RETURN : int32_t type of status 1390 * 0 -- success 1391 * -1 -- failure 1392 * NOTE : Server will return a server stream id that uniquely identify 1393 * this stream on server side. Later on communication to server 1394 * per stream should use this server stream id. 1395 *==========================================================================*/ 1396 int32_t mm_stream_set_ext_mode(mm_stream_t * my_obj) 1397 { 1398 int32_t rc = 0; 1399 struct v4l2_streamparm s_parm; 1400 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d", 1401 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state); 1402 1403 memset(&s_parm, 0, sizeof(s_parm)); 1404 s_parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 1405 1406 rc = ioctl(my_obj->fd, VIDIOC_S_PARM, &s_parm); 1407 CDBG("%s:stream fd=%d, rc=%d, extended_mode=%d\n", 1408 __func__, my_obj->fd, rc, s_parm.parm.capture.extendedmode); 1409 if (rc == 0) { 1410 /* get server stream id */ 1411 my_obj->server_stream_id = s_parm.parm.capture.extendedmode; 1412 } 1413 return rc; 1414 } 1415 1416 /*=========================================================================== 1417 * FUNCTION : mm_stream_qbuf 1418 * 1419 * DESCRIPTION: enqueue buffer back to kernel queue for furture use 1420 * 1421 * PARAMETERS : 1422 * @my_obj : stream object 1423 * @buf : ptr to a struct storing buffer information 1424 * 1425 * RETURN : int32_t type of status 1426 * 0 -- success 1427 * -1 -- failure 1428 *==========================================================================*/ 1429 int32_t mm_stream_qbuf(mm_stream_t *my_obj, mm_camera_buf_def_t *buf) 1430 { 1431 int32_t rc = 0; 1432 uint32_t length = 0; 1433 struct v4l2_buffer buffer; 1434 struct v4l2_plane planes[VIDEO_MAX_PLANES]; 1435 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d, stream type = %d", 1436 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state, 1437 my_obj->stream_info->stream_type); 1438 1439 if (buf->buf_type == CAM_STREAM_BUF_TYPE_USERPTR) { 1440 CDBG("%s: USERPTR num_buf = %d, idx = %d", __func__, 1441 buf->user_buf.bufs_used, buf->buf_idx); 1442 memset(&planes, 0, sizeof(planes)); 1443 planes[0].length = my_obj->stream_info->user_buf_info.size; 1444 planes[0].m.userptr = buf->fd; 1445 length = 1; 1446 } else { 1447 memcpy(planes, buf->planes_buf.planes, sizeof(planes)); 1448 length = buf->planes_buf.num_planes; 1449 1450 CDBG("%s:plane 0: stream_hdl=%u,fd=%d,frame idx=%d,num_planes = %u, " 1451 "offset = %d, data_offset = %d\n", __func__, 1452 buf->stream_id, buf->fd, buffer.index, buffer.length, 1453 buf->planes_buf.planes[0].reserved[0], 1454 buf->planes_buf.planes[0].data_offset); 1455 CDBG("%s:plane 1: stream_hdl=%u,fd=%d,frame idx=%d,num_planes = %u, " 1456 "offset = %d, data_offset = %d\n", __func__, 1457 buf->stream_id, buf->fd, buffer.index, buffer.length, 1458 buf->planes_buf.planes[1].reserved[0], 1459 buf->planes_buf.planes[1].data_offset); 1460 } 1461 1462 memset(&buffer, 0, sizeof(buffer)); 1463 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 1464 buffer.memory = V4L2_MEMORY_USERPTR; 1465 buffer.index = (__u32)buf->buf_idx; 1466 buffer.m.planes = &planes[0]; 1467 buffer.length = (__u32)length; 1468 1469 if ( NULL != my_obj->mem_vtbl.invalidate_buf ) { 1470 rc = my_obj->mem_vtbl.invalidate_buf(buffer.index, 1471 my_obj->mem_vtbl.user_data); 1472 if ( 0 > rc ) { 1473 CDBG_ERROR("%s: Cache invalidate failed on buffer index: %d", 1474 __func__, 1475 buffer.index); 1476 return rc; 1477 } 1478 } else { 1479 CDBG_ERROR("%s: Cache invalidate op not added", __func__); 1480 } 1481 1482 my_obj->queued_buffer_count++; 1483 if (1 == my_obj->queued_buffer_count) { 1484 /* Add fd to data poll thread */ 1485 CDBG_HIGH("%s: Starting poll on stream %p type: %d", __func__, 1486 my_obj,my_obj->stream_info->stream_type); 1487 rc = mm_camera_poll_thread_add_poll_fd(&my_obj->ch_obj->poll_thread[0], 1488 my_obj->my_hdl, my_obj->fd, mm_stream_data_notify, (void*)my_obj, 1489 mm_camera_async_call); 1490 if (0 > rc) { 1491 CDBG_ERROR("%s: Add poll on stream %p type: %d fd error (rc=%d)", 1492 __func__, my_obj, my_obj->stream_info->stream_type, rc); 1493 } else { 1494 CDBG_HIGH("%s: Started poll on stream %p type: %d", __func__, 1495 my_obj, my_obj->stream_info->stream_type); 1496 } 1497 } 1498 1499 rc = ioctl(my_obj->fd, VIDIOC_QBUF, &buffer); 1500 if (0 > rc) { 1501 CDBG_ERROR("%s: VIDIOC_QBUF ioctl call failed on stream type %d (rc=%d): %s", 1502 __func__, my_obj->stream_info->stream_type, rc, strerror(errno)); 1503 my_obj->queued_buffer_count--; 1504 if (0 == my_obj->queued_buffer_count) { 1505 /* Remove fd from data poll in case of failing 1506 * first buffer queuing attempt */ 1507 CDBG_HIGH("%s: Stoping poll on stream %p type: %d", __func__, 1508 my_obj, my_obj->stream_info->stream_type); 1509 mm_camera_poll_thread_del_poll_fd(&my_obj->ch_obj->poll_thread[0], 1510 my_obj->my_hdl, mm_camera_async_call); 1511 CDBG_HIGH("%s: Stopped poll on stream %p type: %d", __func__, 1512 my_obj, my_obj->stream_info->stream_type); 1513 } 1514 } else { 1515 CDBG("%s: VIDIOC_QBUF buf_index %d, stream type %d, rc %d, queued: %d", __func__, 1516 buffer.index, my_obj->stream_info->stream_type, rc, my_obj->queued_buffer_count); 1517 } 1518 1519 return rc; 1520 } 1521 1522 /*=========================================================================== 1523 * FUNCTION : mm_stream_request_buf 1524 * 1525 * DESCRIPTION: This function let kernel know the amount of buffers need to 1526 * be registered via v4l2 ioctl. 1527 * 1528 * PARAMETERS : 1529 * @my_obj : stream object 1530 * 1531 * RETURN : int32_t type of status 1532 * 0 -- success 1533 * -1 -- failure 1534 *==========================================================================*/ 1535 int32_t mm_stream_request_buf(mm_stream_t * my_obj) 1536 { 1537 int32_t rc = 0; 1538 struct v4l2_requestbuffers bufreq; 1539 uint8_t buf_num = my_obj->buf_num; 1540 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d", 1541 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state); 1542 1543 CDBG("%s: buf_num = %d, stream type = %d", 1544 __func__, buf_num, my_obj->stream_info->stream_type); 1545 1546 if(buf_num > MM_CAMERA_MAX_NUM_FRAMES) { 1547 CDBG_ERROR("%s: buf num %d > max limit %d\n", 1548 __func__, buf_num, MM_CAMERA_MAX_NUM_FRAMES); 1549 return -1; 1550 } 1551 1552 memset(&bufreq, 0, sizeof(bufreq)); 1553 bufreq.count = buf_num; 1554 bufreq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 1555 bufreq.memory = V4L2_MEMORY_USERPTR; 1556 rc = ioctl(my_obj->fd, VIDIOC_REQBUFS, &bufreq); 1557 if (rc < 0) { 1558 CDBG_ERROR("%s: fd=%d, ioctl VIDIOC_REQBUFS failed: rc=%d\n", 1559 __func__, my_obj->fd, rc); 1560 } 1561 1562 CDBG("%s :X rc = %d",__func__,rc); 1563 return rc; 1564 } 1565 1566 /*=========================================================================== 1567 * FUNCTION : mm_stream_map_buf 1568 * 1569 * DESCRIPTION: mapping stream buffer via domain socket to server 1570 * 1571 * PARAMETERS : 1572 * @my_obj : stream object 1573 * @buf_type : type of buffer to be mapped. could be following values: 1574 * CAM_MAPPING_BUF_TYPE_STREAM_BUF 1575 * CAM_MAPPING_BUF_TYPE_STREAM_INFO 1576 * CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF 1577 * @frame_idx : index of buffer within the stream buffers, only valid if 1578 * buf_type is CAM_MAPPING_BUF_TYPE_STREAM_BUF or 1579 * CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF 1580 * @plane_idx : plane index. If all planes share the same fd, 1581 * plane_idx = -1; otherwise, plean_idx is the 1582 * index to plane (0..num_of_planes) 1583 * @fd : file descriptor of the buffer 1584 * @size : size of the buffer 1585 * 1586 * RETURN : int32_t type of status 1587 * 0 -- success 1588 * -1 -- failure 1589 *==========================================================================*/ 1590 int32_t mm_stream_map_buf(mm_stream_t * my_obj, 1591 uint8_t buf_type, 1592 uint32_t frame_idx, 1593 int32_t plane_idx, 1594 int32_t fd, 1595 size_t size) 1596 { 1597 if (NULL == my_obj || NULL == my_obj->ch_obj || NULL == my_obj->ch_obj->cam_obj) { 1598 CDBG_ERROR("%s: NULL obj of stream/channel/camera", __func__); 1599 return -1; 1600 } 1601 cam_sock_packet_t packet; 1602 memset(&packet, 0, sizeof(cam_sock_packet_t)); 1603 packet.msg_type = CAM_MAPPING_TYPE_FD_MAPPING; 1604 packet.payload.buf_map.type = buf_type; 1605 packet.payload.buf_map.fd = fd; 1606 packet.payload.buf_map.size = size; 1607 packet.payload.buf_map.stream_id = my_obj->server_stream_id; 1608 packet.payload.buf_map.frame_idx = frame_idx; 1609 packet.payload.buf_map.plane_idx = plane_idx; 1610 return mm_camera_util_sendmsg(my_obj->ch_obj->cam_obj, 1611 &packet, 1612 sizeof(cam_sock_packet_t), 1613 fd); 1614 } 1615 1616 /*=========================================================================== 1617 * FUNCTION : mm_stream_unmap_buf 1618 * 1619 * DESCRIPTION: unmapping stream buffer via domain socket to server 1620 * 1621 * PARAMETERS : 1622 * @my_obj : stream object 1623 * @buf_type : type of buffer to be unmapped. could be following values: 1624 * CAM_MAPPING_BUF_TYPE_STREAM_BUF 1625 * CAM_MAPPING_BUF_TYPE_STREAM_INFO 1626 * CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF 1627 * @frame_idx : index of buffer within the stream buffers, only valid if 1628 * buf_type is CAM_MAPPING_BUF_TYPE_STREAM_BUF or 1629 * CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF 1630 * @plane_idx : plane index. If all planes share the same fd, 1631 * plane_idx = -1; otherwise, plean_idx is the 1632 * index to plane (0..num_of_planes) 1633 * 1634 * RETURN : int32_t type of status 1635 * 0 -- success 1636 * -1 -- failure 1637 *==========================================================================*/ 1638 int32_t mm_stream_unmap_buf(mm_stream_t * my_obj, 1639 uint8_t buf_type, 1640 uint32_t frame_idx, 1641 int32_t plane_idx) 1642 { 1643 if (NULL == my_obj || NULL == my_obj->ch_obj || NULL == my_obj->ch_obj->cam_obj) { 1644 CDBG_ERROR("%s: NULL obj of stream/channel/camera", __func__); 1645 return -1; 1646 } 1647 cam_sock_packet_t packet; 1648 memset(&packet, 0, sizeof(cam_sock_packet_t)); 1649 packet.msg_type = CAM_MAPPING_TYPE_FD_UNMAPPING; 1650 packet.payload.buf_unmap.type = buf_type; 1651 packet.payload.buf_unmap.stream_id = my_obj->server_stream_id; 1652 packet.payload.buf_unmap.frame_idx = frame_idx; 1653 packet.payload.buf_unmap.plane_idx = plane_idx; 1654 return mm_camera_util_sendmsg(my_obj->ch_obj->cam_obj, 1655 &packet, 1656 sizeof(cam_sock_packet_t), 1657 0); 1658 } 1659 1660 /*=========================================================================== 1661 * FUNCTION : mm_stream_map_buf_ops 1662 * 1663 * DESCRIPTION: ops for mapping stream buffer via domain socket to server. 1664 * This function will be passed to upper layer as part of ops table 1665 * to be used by upper layer when allocating stream buffers and mapping 1666 * buffers to server via domain socket. 1667 * 1668 * PARAMETERS : 1669 * @frame_idx : index of buffer within the stream buffers, only valid if 1670 * buf_type is CAM_MAPPING_BUF_TYPE_STREAM_BUF or 1671 * CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF 1672 * @plane_idx : plane index. If all planes share the same fd, 1673 * plane_idx = -1; otherwise, plean_idx is the 1674 * index to plane (0..num_of_planes) 1675 * @fd : file descriptor of the buffer 1676 * @size : size of the buffer 1677 * @userdata : user data ptr (stream object) 1678 * 1679 * RETURN : int32_t type of status 1680 * 0 -- success 1681 * -1 -- failure 1682 *==========================================================================*/ 1683 static int32_t mm_stream_map_buf_ops(uint32_t frame_idx, 1684 int32_t plane_idx, 1685 int fd, 1686 size_t size, 1687 cam_mapping_buf_type type, 1688 void *userdata) 1689 { 1690 mm_stream_t *my_obj = (mm_stream_t *)userdata; 1691 return mm_stream_map_buf(my_obj, 1692 type, 1693 frame_idx, plane_idx, fd, size); 1694 } 1695 1696 /*=========================================================================== 1697 * FUNCTION : mm_stream_unmap_buf_ops 1698 * 1699 * DESCRIPTION: ops for unmapping stream buffer via domain socket to server. 1700 * This function will be passed to upper layer as part of ops table 1701 * to be used by upper layer when allocating stream buffers and unmapping 1702 * buffers to server via domain socket. 1703 * 1704 * PARAMETERS : 1705 * @frame_idx : index of buffer within the stream buffers, only valid if 1706 * buf_type is CAM_MAPPING_BUF_TYPE_STREAM_BUF or 1707 * CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF 1708 * @plane_idx : plane index. If all planes share the same fd, 1709 * plane_idx = -1; otherwise, plean_idx is the 1710 * index to plane (0..num_of_planes) 1711 * @userdata : user data ptr (stream object) 1712 * 1713 * RETURN : int32_t type of status 1714 * 0 -- success 1715 * -1 -- failure 1716 *==========================================================================*/ 1717 static int32_t mm_stream_unmap_buf_ops(uint32_t frame_idx, 1718 int32_t plane_idx, 1719 cam_mapping_buf_type type, 1720 void *userdata) 1721 { 1722 mm_stream_t *my_obj = (mm_stream_t *)userdata; 1723 return mm_stream_unmap_buf(my_obj, 1724 type, 1725 frame_idx, 1726 plane_idx); 1727 } 1728 1729 /*=========================================================================== 1730 * FUNCTION : mm_stream_init_bufs 1731 * 1732 * DESCRIPTION: initialize stream buffers needed. This function will request 1733 * buffers needed from upper layer through the mem ops table passed 1734 * during configuration stage. 1735 * 1736 * PARAMETERS : 1737 * @my_obj : stream object 1738 * 1739 * RETURN : int32_t type of status 1740 * 0 -- success 1741 * -1 -- failure 1742 *==========================================================================*/ 1743 int32_t mm_stream_init_bufs(mm_stream_t * my_obj) 1744 { 1745 int32_t i, rc = 0; 1746 uint8_t *reg_flags = NULL; 1747 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d", 1748 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state); 1749 1750 /* deinit buf if it's not NULL*/ 1751 if (NULL != my_obj->buf) { 1752 mm_stream_deinit_bufs(my_obj); 1753 } 1754 1755 my_obj->map_ops.map_ops = mm_stream_map_buf_ops; 1756 my_obj->map_ops.unmap_ops = mm_stream_unmap_buf_ops; 1757 my_obj->map_ops.userdata = my_obj; 1758 1759 rc = my_obj->mem_vtbl.get_bufs(&my_obj->frame_offset, 1760 &my_obj->buf_num, 1761 ®_flags, 1762 &my_obj->buf, 1763 &my_obj->map_ops, 1764 my_obj->mem_vtbl.user_data); 1765 1766 if (0 != rc) { 1767 CDBG_ERROR("%s: Error get buf, rc = %d\n", __func__, rc); 1768 return rc; 1769 } 1770 1771 my_obj->buf_status = 1772 (mm_stream_buf_status_t *)malloc(sizeof(mm_stream_buf_status_t) * my_obj->buf_num); 1773 1774 if (NULL == my_obj->buf_status) { 1775 CDBG_ERROR("%s: No memory for buf_status", __func__); 1776 mm_stream_deinit_bufs(my_obj); 1777 free(reg_flags); 1778 return -1; 1779 } 1780 1781 memset(my_obj->buf_status, 0, sizeof(mm_stream_buf_status_t) * my_obj->buf_num); 1782 for (i = 0; i < my_obj->buf_num; i++) { 1783 my_obj->buf_status[i].initial_reg_flag = reg_flags[i]; 1784 my_obj->buf[i].stream_id = my_obj->my_hdl; 1785 my_obj->buf[i].stream_type = my_obj->stream_info->stream_type; 1786 1787 if (my_obj->buf[i].buf_type == CAM_STREAM_BUF_TYPE_USERPTR) { 1788 my_obj->buf[i].user_buf.bufs_used = 1789 (int8_t)my_obj->stream_info->user_buf_info.frame_buf_cnt; 1790 my_obj->buf[i].user_buf.buf_in_use = reg_flags[i]; 1791 } 1792 } 1793 1794 if (my_obj->stream_info->streaming_mode == CAM_STREAMING_MODE_BATCH) { 1795 my_obj->plane_buf = my_obj->buf[0].user_buf.plane_buf; 1796 if (my_obj->plane_buf != NULL) { 1797 my_obj->plane_buf_num = 1798 my_obj->buf_num * 1799 my_obj->stream_info->user_buf_info.frame_buf_cnt; 1800 for (i = 0; i < my_obj->plane_buf_num; i++) { 1801 my_obj->plane_buf[i].stream_id = my_obj->my_hdl; 1802 my_obj->plane_buf[i].stream_type = my_obj->stream_info->stream_type; 1803 } 1804 } 1805 my_obj->cur_bufs_staged = 0; 1806 my_obj->cur_buf_idx = -1; 1807 } 1808 1809 free(reg_flags); 1810 reg_flags = NULL; 1811 1812 /* update in stream info about number of stream buffers */ 1813 my_obj->stream_info->num_bufs = my_obj->buf_num; 1814 1815 return rc; 1816 } 1817 1818 /*=========================================================================== 1819 * FUNCTION : mm_stream_deinit_bufs 1820 * 1821 * DESCRIPTION: return stream buffers to upper layer through the mem ops table 1822 * passed during configuration stage. 1823 * 1824 * PARAMETERS : 1825 * @my_obj : stream object 1826 * 1827 * RETURN : int32_t type of status 1828 * 0 -- success 1829 * -1 -- failure 1830 *==========================================================================*/ 1831 int32_t mm_stream_deinit_bufs(mm_stream_t * my_obj) 1832 { 1833 int32_t rc = 0; 1834 1835 mm_camera_map_unmap_ops_tbl_t ops_tbl; 1836 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d", 1837 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state); 1838 1839 if (NULL == my_obj->buf) { 1840 CDBG("%s: Buf is NULL, no need to deinit", __func__); 1841 return rc; 1842 } 1843 1844 /* release bufs */ 1845 ops_tbl.map_ops = mm_stream_map_buf_ops; 1846 ops_tbl.unmap_ops = mm_stream_unmap_buf_ops; 1847 ops_tbl.userdata = my_obj; 1848 1849 rc = my_obj->mem_vtbl.put_bufs(&ops_tbl, 1850 my_obj->mem_vtbl.user_data); 1851 1852 if (my_obj->plane_buf != NULL) { 1853 free(my_obj->plane_buf); 1854 my_obj->plane_buf = NULL; 1855 } 1856 1857 free(my_obj->buf); 1858 my_obj->buf = NULL; 1859 if (my_obj->buf_status != NULL) { 1860 free(my_obj->buf_status); 1861 my_obj->buf_status = NULL; 1862 } 1863 1864 return rc; 1865 } 1866 1867 /*=========================================================================== 1868 * FUNCTION : mm_stream_reg_buf 1869 * 1870 * DESCRIPTION: register buffers with kernel by calling v4l2 ioctl QBUF for 1871 * each buffer in the stream 1872 * 1873 * PARAMETERS : 1874 * @my_obj : stream object 1875 * 1876 * RETURN : int32_t type of status 1877 * 0 -- success 1878 * -1 -- failure 1879 *==========================================================================*/ 1880 int32_t mm_stream_reg_buf(mm_stream_t * my_obj) 1881 { 1882 int32_t rc = 0; 1883 uint8_t i; 1884 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d", 1885 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state); 1886 1887 rc = mm_stream_request_buf(my_obj); 1888 if (rc != 0) { 1889 return rc; 1890 } 1891 1892 pthread_mutex_lock(&my_obj->buf_lock); 1893 my_obj->queued_buffer_count = 0; 1894 for(i = 0; i < my_obj->buf_num; i++){ 1895 /* check if need to qbuf initially */ 1896 if (my_obj->buf_status[i].initial_reg_flag) { 1897 rc = mm_stream_qbuf(my_obj, &my_obj->buf[i]); 1898 if (rc != 0) { 1899 CDBG_ERROR("%s: VIDIOC_QBUF rc = %d\n", __func__, rc); 1900 break; 1901 } 1902 my_obj->buf_status[i].buf_refcnt = 0; 1903 my_obj->buf_status[i].in_kernel = 1; 1904 } else { 1905 /* the buf is held by upper layer, will not queue into kernel. 1906 * add buf reference count */ 1907 my_obj->buf_status[i].buf_refcnt = 1; 1908 my_obj->buf_status[i].in_kernel = 0; 1909 } 1910 } 1911 pthread_mutex_unlock(&my_obj->buf_lock); 1912 1913 return rc; 1914 } 1915 1916 /*=========================================================================== 1917 * FUNCTION : mm_stream_unreg buf 1918 * 1919 * DESCRIPTION: unregister all stream buffers from kernel 1920 * 1921 * PARAMETERS : 1922 * @my_obj : stream object 1923 * 1924 * RETURN : int32_t type of status 1925 * 0 -- success 1926 * -1 -- failure 1927 *==========================================================================*/ 1928 int32_t mm_stream_unreg_buf(mm_stream_t * my_obj) 1929 { 1930 struct v4l2_requestbuffers bufreq; 1931 int32_t i, rc = 0; 1932 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d", 1933 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state); 1934 1935 /* unreg buf to kernel */ 1936 bufreq.count = 0; 1937 bufreq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 1938 bufreq.memory = V4L2_MEMORY_USERPTR; 1939 rc = ioctl(my_obj->fd, VIDIOC_REQBUFS, &bufreq); 1940 if (rc < 0) { 1941 CDBG_ERROR("%s: fd=%d, VIDIOC_REQBUFS failed, rc=%d\n", 1942 __func__, my_obj->fd, rc); 1943 } 1944 1945 /* reset buf reference count */ 1946 pthread_mutex_lock(&my_obj->buf_lock); 1947 if (NULL != my_obj->buf_status) { 1948 for(i = 0; i < my_obj->buf_num; i++){ 1949 my_obj->buf_status[i].buf_refcnt = 0; 1950 my_obj->buf_status[i].in_kernel = 0; 1951 } 1952 } 1953 pthread_mutex_unlock(&my_obj->buf_lock); 1954 1955 return rc; 1956 } 1957 1958 /*=========================================================================== 1959 * FUNCTION : mm_stream_get_v4l2_fmt 1960 * 1961 * DESCRIPTION: translate camera image format into FOURCC code 1962 * 1963 * PARAMETERS : 1964 * @fmt : camera image format 1965 * 1966 * RETURN : FOURCC code for image format 1967 *==========================================================================*/ 1968 uint32_t mm_stream_get_v4l2_fmt(cam_format_t fmt) 1969 { 1970 uint32_t val; 1971 switch(fmt) { 1972 case CAM_FORMAT_YUV_420_NV12: 1973 case CAM_FORMAT_YUV_420_NV12_VENUS: 1974 val = V4L2_PIX_FMT_NV12; 1975 break; 1976 case CAM_FORMAT_YUV_420_NV21: 1977 val = V4L2_PIX_FMT_NV21; 1978 break; 1979 case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_GBRG: 1980 case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_GRBG: 1981 case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_RGGB: 1982 case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_BGGR: 1983 val= V4L2_PIX_FMT_SBGGR10; 1984 break; 1985 case CAM_FORMAT_YUV_422_NV61: 1986 val= V4L2_PIX_FMT_NV61; 1987 break; 1988 case CAM_FORMAT_YUV_RAW_8BIT_YUYV: 1989 val= V4L2_PIX_FMT_YUYV; 1990 break; 1991 case CAM_FORMAT_YUV_RAW_8BIT_YVYU: 1992 val= V4L2_PIX_FMT_YVYU; 1993 break; 1994 case CAM_FORMAT_YUV_RAW_8BIT_UYVY: 1995 val= V4L2_PIX_FMT_UYVY; 1996 break; 1997 case CAM_FORMAT_YUV_RAW_8BIT_VYUY: 1998 val= V4L2_PIX_FMT_VYUY; 1999 break; 2000 case CAM_FORMAT_YUV_420_YV12: 2001 val= V4L2_PIX_FMT_NV12; 2002 break; 2003 case CAM_FORMAT_YUV_422_NV16: 2004 val= V4L2_PIX_FMT_NV16; 2005 break; 2006 default: 2007 val = 0; 2008 CDBG_ERROR("%s: Unknown fmt=%d", __func__, fmt); 2009 break; 2010 } 2011 CDBG("%s: fmt=%d, val =%d", __func__, fmt, val); 2012 return val; 2013 } 2014 2015 /*=========================================================================== 2016 * FUNCTION : mm_stream_calc_offset_preview 2017 * 2018 * DESCRIPTION: calculate preview frame offset based on format and 2019 * padding information 2020 * 2021 * PARAMETERS : 2022 * @fmt : image format 2023 * @dim : image dimension 2024 * @buf_planes : [out] buffer plane information 2025 * 2026 * RETURN : int32_t type of status 2027 * 0 -- success 2028 * -1 -- failure 2029 *==========================================================================*/ 2030 int32_t mm_stream_calc_offset_preview(cam_format_t fmt, 2031 cam_dimension_t *dim, 2032 cam_stream_buf_plane_info_t *buf_planes) 2033 { 2034 int32_t rc = 0; 2035 int stride = 0, scanline = 0; 2036 2037 switch (fmt) { 2038 case CAM_FORMAT_YUV_420_NV12: 2039 case CAM_FORMAT_YUV_420_NV21: 2040 /* 2 planes: Y + CbCr */ 2041 buf_planes->plane_info.num_planes = 2; 2042 2043 stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_32); 2044 scanline = PAD_TO_SIZE(dim->height, CAM_PAD_TO_2); 2045 2046 buf_planes->plane_info.mp[0].offset = 0; 2047 buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline); 2048 buf_planes->plane_info.mp[0].offset_x = 0; 2049 buf_planes->plane_info.mp[0].offset_y = 0; 2050 buf_planes->plane_info.mp[0].stride = stride; 2051 buf_planes->plane_info.mp[0].scanline = scanline; 2052 buf_planes->plane_info.mp[0].width = dim->width; 2053 buf_planes->plane_info.mp[0].height = dim->height; 2054 2055 stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_32); 2056 scanline = PAD_TO_SIZE(dim->height / 2, CAM_PAD_TO_2); 2057 buf_planes->plane_info.mp[1].offset = 0; 2058 buf_planes->plane_info.mp[1].len = 2059 (uint32_t)(stride * scanline); 2060 buf_planes->plane_info.mp[1].offset_x = 0; 2061 buf_planes->plane_info.mp[1].offset_y = 0; 2062 buf_planes->plane_info.mp[1].stride = stride; 2063 buf_planes->plane_info.mp[1].scanline = scanline; 2064 buf_planes->plane_info.mp[1].width = dim->width; 2065 buf_planes->plane_info.mp[1].height = dim->height / 2; 2066 2067 buf_planes->plane_info.frame_len = 2068 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len + 2069 buf_planes->plane_info.mp[1].len, 2070 CAM_PAD_TO_4K); 2071 break; 2072 case CAM_FORMAT_YUV_420_NV21_ADRENO: 2073 /* 2 planes: Y + CbCr */ 2074 buf_planes->plane_info.num_planes = 2; 2075 2076 stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_32); 2077 scanline = PAD_TO_SIZE(dim->height, CAM_PAD_TO_32); 2078 buf_planes->plane_info.mp[0].offset = 0; 2079 buf_planes->plane_info.mp[0].len = 2080 PAD_TO_SIZE((uint32_t)(stride * scanline), CAM_PAD_TO_4K); 2081 buf_planes->plane_info.mp[0].offset_x = 0; 2082 buf_planes->plane_info.mp[0].offset_y = 0; 2083 buf_planes->plane_info.mp[0].stride = stride; 2084 buf_planes->plane_info.mp[0].scanline = scanline; 2085 buf_planes->plane_info.mp[0].width = dim->width; 2086 buf_planes->plane_info.mp[0].height = dim->height; 2087 2088 stride = PAD_TO_SIZE(dim->width / 2, CAM_PAD_TO_32) * 2; 2089 scanline = PAD_TO_SIZE(dim->height / 2, CAM_PAD_TO_32); 2090 buf_planes->plane_info.mp[1].offset = 0; 2091 buf_planes->plane_info.mp[1].len = 2092 PAD_TO_SIZE((uint32_t)(stride * scanline), CAM_PAD_TO_4K); 2093 buf_planes->plane_info.mp[1].offset_x = 0; 2094 buf_planes->plane_info.mp[1].offset_y = 0; 2095 buf_planes->plane_info.mp[1].stride = stride; 2096 buf_planes->plane_info.mp[1].scanline = scanline; 2097 buf_planes->plane_info.mp[1].width = dim->width; 2098 buf_planes->plane_info.mp[1].height = dim->height / 2; 2099 2100 buf_planes->plane_info.frame_len = 2101 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len + 2102 buf_planes->plane_info.mp[1].len, 2103 CAM_PAD_TO_4K); 2104 break; 2105 case CAM_FORMAT_YUV_420_YV12: 2106 /* 3 planes: Y + Cr + Cb */ 2107 buf_planes->plane_info.num_planes = 3; 2108 2109 stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16); 2110 scanline = PAD_TO_SIZE(dim->height, CAM_PAD_TO_2); 2111 buf_planes->plane_info.mp[0].offset = 0; 2112 buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline); 2113 buf_planes->plane_info.mp[0].offset_x = 0; 2114 buf_planes->plane_info.mp[0].offset_y = 0; 2115 buf_planes->plane_info.mp[0].stride = stride; 2116 buf_planes->plane_info.mp[0].scanline = scanline; 2117 buf_planes->plane_info.mp[0].width = dim->width; 2118 buf_planes->plane_info.mp[0].height = dim->height; 2119 2120 stride = PAD_TO_SIZE(stride / 2, CAM_PAD_TO_16); 2121 scanline = scanline / 2; 2122 buf_planes->plane_info.mp[1].offset = 0; 2123 buf_planes->plane_info.mp[1].len = 2124 (uint32_t)(stride * scanline); 2125 buf_planes->plane_info.mp[1].offset_x = 0; 2126 buf_planes->plane_info.mp[1].offset_y = 0; 2127 buf_planes->plane_info.mp[1].stride = stride; 2128 buf_planes->plane_info.mp[1].scanline = scanline; 2129 buf_planes->plane_info.mp[1].width = dim->width / 2; 2130 buf_planes->plane_info.mp[1].height = dim->height / 2; 2131 2132 buf_planes->plane_info.mp[2].offset = 0; 2133 buf_planes->plane_info.mp[2].len = 2134 (uint32_t)(stride * scanline); 2135 buf_planes->plane_info.mp[2].offset_x = 0; 2136 buf_planes->plane_info.mp[2].offset_y = 0; 2137 buf_planes->plane_info.mp[2].stride = stride; 2138 buf_planes->plane_info.mp[2].scanline = scanline; 2139 buf_planes->plane_info.mp[2].width = dim->width / 2; 2140 buf_planes->plane_info.mp[2].height = dim->height / 2; 2141 2142 buf_planes->plane_info.frame_len = 2143 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len + 2144 buf_planes->plane_info.mp[1].len + 2145 buf_planes->plane_info.mp[2].len, 2146 CAM_PAD_TO_4K); 2147 break; 2148 case CAM_FORMAT_YUV_422_NV16: 2149 case CAM_FORMAT_YUV_422_NV61: 2150 /* 2 planes: Y + CbCr */ 2151 buf_planes->plane_info.num_planes = 2; 2152 2153 stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16); 2154 scanline = dim->height; 2155 buf_planes->plane_info.mp[0].offset = 0; 2156 buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline); 2157 buf_planes->plane_info.mp[0].offset_x = 0; 2158 buf_planes->plane_info.mp[0].offset_y = 0; 2159 buf_planes->plane_info.mp[0].stride = stride; 2160 buf_planes->plane_info.mp[0].scanline = scanline; 2161 buf_planes->plane_info.mp[0].width = dim->width; 2162 buf_planes->plane_info.mp[0].height = dim->height; 2163 2164 buf_planes->plane_info.mp[1].offset = 0; 2165 buf_planes->plane_info.mp[1].len = (uint32_t)(stride * scanline); 2166 buf_planes->plane_info.mp[1].offset_x = 0; 2167 buf_planes->plane_info.mp[1].offset_y = 0; 2168 buf_planes->plane_info.mp[1].stride = stride; 2169 buf_planes->plane_info.mp[1].scanline = scanline; 2170 buf_planes->plane_info.mp[1].width = dim->width; 2171 buf_planes->plane_info.mp[1].height = dim->height; 2172 2173 buf_planes->plane_info.frame_len = 2174 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len + 2175 buf_planes->plane_info.mp[1].len, 2176 CAM_PAD_TO_4K); 2177 break; 2178 case CAM_FORMAT_YUV_420_NV12_VENUS: 2179 #ifdef VENUS_PRESENT 2180 // using Venus 2181 stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, dim->width); 2182 scanline = VENUS_Y_SCANLINES(COLOR_FMT_NV12, dim->height); 2183 2184 buf_planes->plane_info.frame_len = 2185 VENUS_BUFFER_SIZE(COLOR_FMT_NV12, dim->width, dim->height); 2186 buf_planes->plane_info.num_planes = 2; 2187 buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline); 2188 buf_planes->plane_info.mp[0].offset = 0; 2189 buf_planes->plane_info.mp[0].offset_x =0; 2190 buf_planes->plane_info.mp[0].offset_y = 0; 2191 buf_planes->plane_info.mp[0].stride = stride; 2192 buf_planes->plane_info.mp[0].scanline = scanline; 2193 buf_planes->plane_info.mp[0].width = dim->width; 2194 buf_planes->plane_info.mp[0].height = dim->height; 2195 stride = VENUS_UV_STRIDE(COLOR_FMT_NV12, dim->width); 2196 scanline = VENUS_UV_SCANLINES(COLOR_FMT_NV12, dim->height); 2197 buf_planes->plane_info.mp[1].len = 2198 buf_planes->plane_info.frame_len - buf_planes->plane_info.mp[0].len; 2199 buf_planes->plane_info.mp[1].offset = 0; 2200 buf_planes->plane_info.mp[1].offset_x =0; 2201 buf_planes->plane_info.mp[1].offset_y = 0; 2202 buf_planes->plane_info.mp[1].stride = stride; 2203 buf_planes->plane_info.mp[1].scanline = scanline; 2204 buf_planes->plane_info.mp[1].width = dim->width; 2205 buf_planes->plane_info.mp[1].height = dim->height / 2; 2206 #else 2207 CDBG_ERROR("%s: Venus hardware not avail, cannot use this format", __func__); 2208 rc = -1; 2209 #endif 2210 break; 2211 default: 2212 CDBG_ERROR("%s: Invalid cam_format for preview %d", 2213 __func__, fmt); 2214 rc = -1; 2215 break; 2216 } 2217 2218 return rc; 2219 } 2220 /*=========================================================================== 2221 * FUNCTION : mm_stream_calc_offset_post_view 2222 * 2223 * DESCRIPTION: calculate postview frame offset based on format and 2224 * padding information 2225 * 2226 * PARAMETERS : 2227 * @fmt : image format 2228 * @dim : image dimension 2229 * @buf_planes : [out] buffer plane information 2230 * 2231 * RETURN : int32_t type of status 2232 * 0 -- success 2233 * -1 -- failure 2234 *==========================================================================*/ 2235 int32_t mm_stream_calc_offset_post_view(cam_format_t fmt, 2236 cam_dimension_t *dim, 2237 cam_stream_buf_plane_info_t *buf_planes) 2238 { 2239 int32_t rc = 0; 2240 int stride = 0, scanline = 0; 2241 2242 switch (fmt) { 2243 case CAM_FORMAT_YUV_420_NV12: 2244 case CAM_FORMAT_YUV_420_NV21: 2245 /* 2 planes: Y + CbCr */ 2246 buf_planes->plane_info.num_planes = 2; 2247 2248 stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_64); 2249 scanline = PAD_TO_SIZE(dim->height, CAM_PAD_TO_64); 2250 buf_planes->plane_info.mp[0].offset = 0; 2251 buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline); 2252 buf_planes->plane_info.mp[0].offset_x = 0; 2253 buf_planes->plane_info.mp[0].offset_y = 0; 2254 buf_planes->plane_info.mp[0].stride = stride; 2255 buf_planes->plane_info.mp[0].scanline = scanline; 2256 buf_planes->plane_info.mp[0].width = dim->width; 2257 buf_planes->plane_info.mp[0].height = dim->height; 2258 2259 stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_64); 2260 scanline = PAD_TO_SIZE(dim->height / 2, CAM_PAD_TO_64); 2261 buf_planes->plane_info.mp[1].offset = 0; 2262 buf_planes->plane_info.mp[1].len = 2263 (uint32_t)(stride * scanline); 2264 buf_planes->plane_info.mp[1].offset_x = 0; 2265 buf_planes->plane_info.mp[1].offset_y = 0; 2266 buf_planes->plane_info.mp[1].stride = stride; 2267 buf_planes->plane_info.mp[1].scanline = scanline; 2268 buf_planes->plane_info.mp[1].width = dim->width; 2269 buf_planes->plane_info.mp[1].height = dim->height / 2; 2270 2271 buf_planes->plane_info.frame_len = 2272 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len + 2273 buf_planes->plane_info.mp[1].len, 2274 CAM_PAD_TO_4K); 2275 break; 2276 case CAM_FORMAT_YUV_420_NV21_ADRENO: 2277 /* 2 planes: Y + CbCr */ 2278 buf_planes->plane_info.num_planes = 2; 2279 2280 stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_32); 2281 scanline = PAD_TO_SIZE(dim->height, CAM_PAD_TO_32); 2282 buf_planes->plane_info.mp[0].offset = 0; 2283 buf_planes->plane_info.mp[0].len = 2284 PAD_TO_SIZE((uint32_t)(stride * scanline), CAM_PAD_TO_4K); 2285 buf_planes->plane_info.mp[0].offset_x = 0; 2286 buf_planes->plane_info.mp[0].offset_y = 0; 2287 buf_planes->plane_info.mp[0].stride = stride; 2288 buf_planes->plane_info.mp[0].scanline = scanline; 2289 buf_planes->plane_info.mp[0].width = dim->width; 2290 buf_planes->plane_info.mp[0].height = dim->height; 2291 2292 stride = PAD_TO_SIZE(dim->width / 2, CAM_PAD_TO_32) * 2; 2293 scanline = PAD_TO_SIZE(dim->height / 2, CAM_PAD_TO_32); 2294 buf_planes->plane_info.mp[1].offset = 0; 2295 buf_planes->plane_info.mp[1].len = 2296 PAD_TO_SIZE((uint32_t)(stride * scanline), CAM_PAD_TO_4K); 2297 buf_planes->plane_info.mp[1].offset_x = 0; 2298 buf_planes->plane_info.mp[1].offset_y = 0; 2299 buf_planes->plane_info.mp[1].stride = stride; 2300 buf_planes->plane_info.mp[1].scanline = scanline; 2301 buf_planes->plane_info.mp[1].width = dim->width; 2302 buf_planes->plane_info.mp[1].height = dim->height / 2; 2303 2304 buf_planes->plane_info.frame_len = 2305 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len + 2306 buf_planes->plane_info.mp[1].len, 2307 CAM_PAD_TO_4K); 2308 break; 2309 case CAM_FORMAT_YUV_420_YV12: 2310 /* 3 planes: Y + Cr + Cb */ 2311 buf_planes->plane_info.num_planes = 3; 2312 2313 stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16); 2314 scanline = PAD_TO_SIZE(dim->height, CAM_PAD_TO_2); 2315 buf_planes->plane_info.mp[0].offset = 0; 2316 buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline); 2317 buf_planes->plane_info.mp[0].offset_x = 0; 2318 buf_planes->plane_info.mp[0].offset_y = 0; 2319 buf_planes->plane_info.mp[0].stride = stride; 2320 buf_planes->plane_info.mp[0].scanline = scanline; 2321 buf_planes->plane_info.mp[0].width = dim->width; 2322 buf_planes->plane_info.mp[0].height = dim->height; 2323 2324 stride = PAD_TO_SIZE(stride / 2, CAM_PAD_TO_16); 2325 scanline = scanline / 2; 2326 buf_planes->plane_info.mp[1].offset = 0; 2327 buf_planes->plane_info.mp[1].len = 2328 (uint32_t)(stride * scanline); 2329 buf_planes->plane_info.mp[1].offset_x = 0; 2330 buf_planes->plane_info.mp[1].offset_y = 0; 2331 buf_planes->plane_info.mp[1].stride = stride; 2332 buf_planes->plane_info.mp[1].scanline = scanline; 2333 buf_planes->plane_info.mp[1].width = dim->width / 2; 2334 buf_planes->plane_info.mp[1].height = dim->height / 2; 2335 2336 buf_planes->plane_info.mp[2].offset = 0; 2337 buf_planes->plane_info.mp[2].len = 2338 (uint32_t)(stride * scanline); 2339 buf_planes->plane_info.mp[2].offset_x = 0; 2340 buf_planes->plane_info.mp[2].offset_y = 0; 2341 buf_planes->plane_info.mp[2].stride = stride; 2342 buf_planes->plane_info.mp[2].scanline = scanline; 2343 buf_planes->plane_info.mp[2].width = dim->width / 2; 2344 buf_planes->plane_info.mp[2].height = dim->height / 2; 2345 2346 buf_planes->plane_info.frame_len = 2347 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len + 2348 buf_planes->plane_info.mp[1].len + 2349 buf_planes->plane_info.mp[2].len, 2350 CAM_PAD_TO_4K); 2351 break; 2352 case CAM_FORMAT_YUV_422_NV16: 2353 case CAM_FORMAT_YUV_422_NV61: 2354 /* 2 planes: Y + CbCr */ 2355 buf_planes->plane_info.num_planes = 2; 2356 2357 stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16); 2358 scanline = dim->height; 2359 buf_planes->plane_info.mp[0].offset = 0; 2360 buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline); 2361 buf_planes->plane_info.mp[0].offset_x = 0; 2362 buf_planes->plane_info.mp[0].offset_y = 0; 2363 buf_planes->plane_info.mp[0].stride = stride; 2364 buf_planes->plane_info.mp[0].scanline = scanline; 2365 buf_planes->plane_info.mp[0].width = dim->width; 2366 buf_planes->plane_info.mp[0].height = dim->height; 2367 2368 buf_planes->plane_info.mp[1].offset = 0; 2369 buf_planes->plane_info.mp[1].len = (uint32_t)(stride * scanline); 2370 buf_planes->plane_info.mp[1].offset_x = 0; 2371 buf_planes->plane_info.mp[1].offset_y = 0; 2372 buf_planes->plane_info.mp[1].stride = stride; 2373 buf_planes->plane_info.mp[1].scanline = scanline; 2374 buf_planes->plane_info.mp[1].width = dim->width; 2375 buf_planes->plane_info.mp[1].height = dim->height; 2376 2377 buf_planes->plane_info.frame_len = 2378 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len + 2379 buf_planes->plane_info.mp[1].len, 2380 CAM_PAD_TO_4K); 2381 break; 2382 case CAM_FORMAT_YUV_420_NV12_VENUS: 2383 #ifdef VENUS_PRESENT 2384 // using Venus 2385 stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, dim->width); 2386 scanline = VENUS_Y_SCANLINES(COLOR_FMT_NV12, dim->height); 2387 2388 buf_planes->plane_info.frame_len = 2389 VENUS_BUFFER_SIZE(COLOR_FMT_NV12, dim->width, dim->height); 2390 buf_planes->plane_info.num_planes = 2; 2391 buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline); 2392 buf_planes->plane_info.mp[0].offset = 0; 2393 buf_planes->plane_info.mp[0].offset_x =0; 2394 buf_planes->plane_info.mp[0].offset_y = 0; 2395 buf_planes->plane_info.mp[0].stride = stride; 2396 buf_planes->plane_info.mp[0].scanline = scanline; 2397 buf_planes->plane_info.mp[0].width = dim->width; 2398 buf_planes->plane_info.mp[0].height = dim->height; 2399 stride = VENUS_UV_STRIDE(COLOR_FMT_NV12, dim->width); 2400 scanline = VENUS_UV_SCANLINES(COLOR_FMT_NV12, dim->height); 2401 buf_planes->plane_info.mp[1].len = 2402 buf_planes->plane_info.frame_len - buf_planes->plane_info.mp[0].len; 2403 buf_planes->plane_info.mp[1].offset = 0; 2404 buf_planes->plane_info.mp[1].offset_x =0; 2405 buf_planes->plane_info.mp[1].offset_y = 0; 2406 buf_planes->plane_info.mp[1].stride = stride; 2407 buf_planes->plane_info.mp[1].scanline = scanline; 2408 buf_planes->plane_info.mp[1].width = dim->width; 2409 buf_planes->plane_info.mp[1].height = dim->height / 2; 2410 #else 2411 CDBG_ERROR("%s: Venus hardware not avail, cannot use this format", __func__); 2412 rc = -1; 2413 #endif 2414 break; 2415 default: 2416 CDBG_ERROR("%s: Invalid cam_format for preview %d", 2417 __func__, fmt); 2418 rc = -1; 2419 break; 2420 } 2421 2422 return rc; 2423 } 2424 2425 /*=========================================================================== 2426 * FUNCTION : mm_stream_calc_offset_snapshot 2427 * 2428 * DESCRIPTION: calculate snapshot/postproc frame offset based on format and 2429 * padding information 2430 * 2431 * PARAMETERS : 2432 * @fmt : image format 2433 * @dim : image dimension 2434 * @padding : padding information 2435 * @buf_planes : [out] buffer plane information 2436 * 2437 * RETURN : int32_t type of status 2438 * 0 -- success 2439 * -1 -- failure 2440 *==========================================================================*/ 2441 int32_t mm_stream_calc_offset_snapshot(cam_format_t fmt, 2442 cam_dimension_t *dim, 2443 cam_padding_info_t *padding, 2444 cam_stream_buf_plane_info_t *buf_planes) 2445 { 2446 int32_t rc = 0; 2447 uint8_t isAFamily = mm_camera_util_chip_is_a_family(); 2448 int offset_x = 0, offset_y = 0; 2449 int stride = 0, scanline = 0; 2450 2451 if (isAFamily) { 2452 stride = dim->width; 2453 scanline = PAD_TO_SIZE(dim->height, CAM_PAD_TO_16); 2454 offset_x = 0; 2455 offset_y = scanline - dim->height; 2456 scanline += offset_y; /* double padding */ 2457 } else { 2458 stride = PAD_TO_SIZE(dim->width, 2459 padding->width_padding); 2460 scanline = PAD_TO_SIZE(dim->height, 2461 padding->height_padding); 2462 offset_x = 0; 2463 offset_y = 0; 2464 } 2465 2466 switch (fmt) { 2467 case CAM_FORMAT_YUV_420_NV12: 2468 case CAM_FORMAT_YUV_420_NV21: 2469 /* 2 planes: Y + CbCr */ 2470 buf_planes->plane_info.num_planes = 2; 2471 2472 buf_planes->plane_info.mp[0].len = 2473 PAD_TO_SIZE((uint32_t)(stride * scanline), 2474 padding->plane_padding); 2475 buf_planes->plane_info.mp[0].offset = 2476 PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y), 2477 padding->plane_padding); 2478 buf_planes->plane_info.mp[0].offset_x = offset_x; 2479 buf_planes->plane_info.mp[0].offset_y = offset_y; 2480 buf_planes->plane_info.mp[0].stride = stride; 2481 buf_planes->plane_info.mp[0].scanline = scanline; 2482 buf_planes->plane_info.mp[0].width = dim->width; 2483 buf_planes->plane_info.mp[0].height = dim->height; 2484 2485 scanline = scanline / 2; 2486 buf_planes->plane_info.mp[1].len = 2487 PAD_TO_SIZE((uint32_t)(stride * scanline), 2488 padding->plane_padding); 2489 buf_planes->plane_info.mp[1].offset = 2490 PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y), 2491 padding->plane_padding); 2492 buf_planes->plane_info.mp[1].offset_x = offset_x; 2493 buf_planes->plane_info.mp[1].offset_y = offset_y; 2494 buf_planes->plane_info.mp[1].stride = stride; 2495 buf_planes->plane_info.mp[1].scanline = scanline; 2496 buf_planes->plane_info.mp[1].width = dim->width; 2497 buf_planes->plane_info.mp[1].height = dim->height / 2; 2498 2499 buf_planes->plane_info.frame_len = 2500 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len + 2501 buf_planes->plane_info.mp[1].len, 2502 CAM_PAD_TO_4K); 2503 break; 2504 case CAM_FORMAT_YUV_420_YV12: 2505 /* 3 planes: Y + Cr + Cb */ 2506 buf_planes->plane_info.num_planes = 3; 2507 2508 buf_planes->plane_info.mp[0].offset = 2509 PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y), 2510 padding->plane_padding); 2511 buf_planes->plane_info.mp[0].len = 2512 PAD_TO_SIZE((uint32_t)(stride * scanline), 2513 padding->plane_padding); 2514 buf_planes->plane_info.mp[0].offset_x = offset_x; 2515 buf_planes->plane_info.mp[0].offset_y = offset_y; 2516 buf_planes->plane_info.mp[0].stride = stride; 2517 buf_planes->plane_info.mp[0].scanline = scanline; 2518 buf_planes->plane_info.mp[0].width = dim->width; 2519 buf_planes->plane_info.mp[0].height = dim->height; 2520 2521 stride = PAD_TO_SIZE(stride / 2, CAM_PAD_TO_16); 2522 scanline = scanline / 2; 2523 buf_planes->plane_info.mp[1].offset = 2524 PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y), 2525 padding->plane_padding); 2526 buf_planes->plane_info.mp[1].len = 2527 PAD_TO_SIZE((uint32_t)(stride * scanline), 2528 padding->plane_padding); 2529 buf_planes->plane_info.mp[1].offset_x = offset_x; 2530 buf_planes->plane_info.mp[1].offset_y = offset_y; 2531 buf_planes->plane_info.mp[1].stride = stride; 2532 buf_planes->plane_info.mp[1].scanline = scanline; 2533 buf_planes->plane_info.mp[1].width = dim->width / 2; 2534 buf_planes->plane_info.mp[1].height = dim->height / 2; 2535 2536 buf_planes->plane_info.mp[2].offset = 2537 PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y), 2538 padding->plane_padding); 2539 buf_planes->plane_info.mp[2].len = 2540 PAD_TO_SIZE((uint32_t)(stride * scanline), 2541 padding->plane_padding); 2542 buf_planes->plane_info.mp[2].offset_x = offset_x; 2543 buf_planes->plane_info.mp[2].offset_y = offset_y; 2544 buf_planes->plane_info.mp[2].stride = stride; 2545 buf_planes->plane_info.mp[2].scanline = scanline; 2546 buf_planes->plane_info.mp[2].width = dim->width / 2; 2547 buf_planes->plane_info.mp[2].height = dim->height / 2; 2548 2549 buf_planes->plane_info.frame_len = 2550 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len + 2551 buf_planes->plane_info.mp[1].len + 2552 buf_planes->plane_info.mp[2].len, 2553 CAM_PAD_TO_4K); 2554 break; 2555 case CAM_FORMAT_YUV_422_NV16: 2556 case CAM_FORMAT_YUV_422_NV61: 2557 /* 2 planes: Y + CbCr */ 2558 buf_planes->plane_info.num_planes = 2; 2559 buf_planes->plane_info.mp[0].len = 2560 PAD_TO_SIZE((uint32_t)(stride * scanline), 2561 padding->plane_padding); 2562 buf_planes->plane_info.mp[0].offset = 2563 PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y), 2564 padding->plane_padding); 2565 buf_planes->plane_info.mp[0].offset_x = offset_x; 2566 buf_planes->plane_info.mp[0].offset_y = offset_y; 2567 buf_planes->plane_info.mp[0].stride = stride; 2568 buf_planes->plane_info.mp[0].scanline = scanline; 2569 buf_planes->plane_info.mp[0].width = dim->width; 2570 buf_planes->plane_info.mp[0].height = dim->height; 2571 2572 buf_planes->plane_info.mp[1].len = 2573 PAD_TO_SIZE((uint32_t)(stride * scanline), 2574 padding->plane_padding); 2575 buf_planes->plane_info.mp[1].offset = 2576 PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y), 2577 padding->plane_padding); 2578 buf_planes->plane_info.mp[1].offset_x = offset_x; 2579 buf_planes->plane_info.mp[1].offset_y = offset_y; 2580 buf_planes->plane_info.mp[1].stride = stride; 2581 buf_planes->plane_info.mp[1].scanline = scanline; 2582 buf_planes->plane_info.mp[1].width = dim->width; 2583 buf_planes->plane_info.mp[1].height = dim->height; 2584 2585 buf_planes->plane_info.frame_len = PAD_TO_SIZE( 2586 buf_planes->plane_info.mp[0].len + buf_planes->plane_info.mp[1].len, 2587 CAM_PAD_TO_4K); 2588 break; 2589 default: 2590 CDBG_ERROR("%s: Invalid cam_format for snapshot %d", 2591 __func__, fmt); 2592 rc = -1; 2593 break; 2594 } 2595 2596 return rc; 2597 } 2598 2599 /*=========================================================================== 2600 * FUNCTION : mm_stream_calc_offset_raw 2601 * 2602 * DESCRIPTION: calculate raw frame offset based on format and padding information 2603 * 2604 * PARAMETERS : 2605 * @fmt : image format 2606 * @dim : image dimension 2607 * @padding : padding information 2608 * @buf_planes : [out] buffer plane information 2609 * 2610 * RETURN : int32_t type of status 2611 * 0 -- success 2612 * -1 -- failure 2613 *==========================================================================*/ 2614 int32_t mm_stream_calc_offset_raw(cam_format_t fmt, 2615 cam_dimension_t *dim, 2616 cam_padding_info_t *padding, 2617 cam_stream_buf_plane_info_t *buf_planes) 2618 { 2619 int32_t rc = 0; 2620 2621 if ((NULL == dim) || (NULL == padding) || (NULL == buf_planes)) { 2622 return -1; 2623 } 2624 2625 int32_t stride = PAD_TO_SIZE(dim->width, (int32_t)padding->width_padding); 2626 int32_t stride_in_bytes = stride; 2627 int32_t scanline = PAD_TO_SIZE(dim->height, (int32_t)padding->height_padding); 2628 2629 switch (fmt) { 2630 case CAM_FORMAT_YUV_420_NV21: 2631 /* 2 planes: Y + CbCr */ 2632 buf_planes->plane_info.num_planes = 2; 2633 2634 buf_planes->plane_info.mp[0].len = 2635 PAD_TO_SIZE((uint32_t)(stride * scanline), 2636 padding->plane_padding); 2637 buf_planes->plane_info.mp[0].offset = 0; 2638 buf_planes->plane_info.mp[0].offset_x = 0; 2639 buf_planes->plane_info.mp[0].offset_y = 0; 2640 buf_planes->plane_info.mp[0].stride = stride; 2641 buf_planes->plane_info.mp[0].stride_in_bytes = stride; 2642 buf_planes->plane_info.mp[0].scanline = scanline; 2643 buf_planes->plane_info.mp[0].width = dim->width; 2644 buf_planes->plane_info.mp[0].height = dim->height; 2645 2646 scanline = scanline / 2; 2647 buf_planes->plane_info.mp[1].len = 2648 PAD_TO_SIZE((uint32_t)(stride * scanline), 2649 padding->plane_padding); 2650 buf_planes->plane_info.mp[1].offset = 0; 2651 buf_planes->plane_info.mp[1].offset_x = 0; 2652 buf_planes->plane_info.mp[1].offset_y = 0; 2653 buf_planes->plane_info.mp[1].stride = stride; 2654 buf_planes->plane_info.mp[1].stride_in_bytes = stride; 2655 buf_planes->plane_info.mp[1].scanline = scanline; 2656 buf_planes->plane_info.mp[1].width = dim->width; 2657 buf_planes->plane_info.mp[1].height = dim->height / 2; 2658 2659 buf_planes->plane_info.frame_len = 2660 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len + 2661 buf_planes->plane_info.mp[1].len, 2662 CAM_PAD_TO_4K); 2663 break; 2664 case CAM_FORMAT_YUV_RAW_8BIT_YUYV: 2665 case CAM_FORMAT_YUV_RAW_8BIT_YVYU: 2666 case CAM_FORMAT_YUV_RAW_8BIT_UYVY: 2667 case CAM_FORMAT_YUV_RAW_8BIT_VYUY: 2668 case CAM_FORMAT_JPEG_RAW_8BIT: 2669 /* 1 plane */ 2670 /* Every 16 pixels occupy 16 bytes */ 2671 stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16); 2672 stride_in_bytes = stride * 2; 2673 buf_planes->plane_info.num_planes = 1; 2674 buf_planes->plane_info.mp[0].offset = 0; 2675 buf_planes->plane_info.mp[0].len = 2676 PAD_TO_SIZE((uint32_t)(stride_in_bytes * scanline), 2677 padding->plane_padding); 2678 buf_planes->plane_info.frame_len = 2679 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K); 2680 buf_planes->plane_info.mp[0].offset_x =0; 2681 buf_planes->plane_info.mp[0].offset_y = 0; 2682 buf_planes->plane_info.mp[0].stride = stride; 2683 buf_planes->plane_info.mp[0].stride_in_bytes = stride_in_bytes; 2684 buf_planes->plane_info.mp[0].scanline = scanline; 2685 buf_planes->plane_info.mp[0].width = 2686 (int32_t)buf_planes->plane_info.mp[0].len; 2687 buf_planes->plane_info.mp[0].height = 1; 2688 break; 2689 case CAM_FORMAT_META_RAW_8BIT: 2690 // Every 16 pixels occupy 16 bytes 2691 stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16); 2692 stride_in_bytes = stride * 2; 2693 buf_planes->plane_info.num_planes = 1; 2694 buf_planes->plane_info.mp[0].offset = 0; 2695 buf_planes->plane_info.mp[0].len = 2696 PAD_TO_SIZE((uint32_t)(stride_in_bytes * scanline), 2697 padding->plane_padding); 2698 buf_planes->plane_info.frame_len = 2699 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K); 2700 buf_planes->plane_info.mp[0].offset_x =0; 2701 buf_planes->plane_info.mp[0].offset_y = 0; 2702 buf_planes->plane_info.mp[0].stride = stride; 2703 buf_planes->plane_info.mp[0].stride_in_bytes = stride_in_bytes; 2704 buf_planes->plane_info.mp[0].scanline = scanline; 2705 break; 2706 2707 case CAM_FORMAT_BAYER_QCOM_RAW_8BPP_GBRG: 2708 case CAM_FORMAT_BAYER_QCOM_RAW_8BPP_GRBG: 2709 case CAM_FORMAT_BAYER_QCOM_RAW_8BPP_RGGB: 2710 case CAM_FORMAT_BAYER_QCOM_RAW_8BPP_BGGR: 2711 case CAM_FORMAT_BAYER_MIPI_RAW_8BPP_GBRG: 2712 case CAM_FORMAT_BAYER_MIPI_RAW_8BPP_GRBG: 2713 case CAM_FORMAT_BAYER_MIPI_RAW_8BPP_RGGB: 2714 case CAM_FORMAT_BAYER_MIPI_RAW_8BPP_BGGR: 2715 case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_8BPP_GBRG: 2716 case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_8BPP_GRBG: 2717 case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_8BPP_RGGB: 2718 case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_8BPP_BGGR: 2719 case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_8BPP_GBRG: 2720 case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_8BPP_GRBG: 2721 case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_8BPP_RGGB: 2722 case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_8BPP_BGGR: 2723 case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN8_8BPP_GBRG: 2724 case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN8_8BPP_GRBG: 2725 case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN8_8BPP_RGGB: 2726 case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN8_8BPP_BGGR: 2727 /* 1 plane */ 2728 /* Every 16 pixels occupy 16 bytes */ 2729 stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16); 2730 stride_in_bytes = stride; 2731 buf_planes->plane_info.num_planes = 1; 2732 buf_planes->plane_info.mp[0].offset = 0; 2733 buf_planes->plane_info.mp[0].len = 2734 PAD_TO_SIZE((uint32_t)(stride_in_bytes * scanline), 2735 padding->plane_padding); 2736 buf_planes->plane_info.frame_len = 2737 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K); 2738 buf_planes->plane_info.mp[0].offset_x =0; 2739 buf_planes->plane_info.mp[0].offset_y = 0; 2740 buf_planes->plane_info.mp[0].stride = stride; 2741 buf_planes->plane_info.mp[0].stride_in_bytes = stride_in_bytes; 2742 buf_planes->plane_info.mp[0].scanline = scanline; 2743 buf_planes->plane_info.mp[0].width = (int32_t)buf_planes->plane_info.mp[0].len; 2744 buf_planes->plane_info.mp[0].height = 1; 2745 break; 2746 case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_GBRG: 2747 case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_GRBG: 2748 case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_RGGB: 2749 case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_BGGR: 2750 case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_10BPP_GBRG: 2751 case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_10BPP_GRBG: 2752 case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_10BPP_RGGB: 2753 case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_10BPP_BGGR: 2754 /* Every 12 pixels occupy 16 bytes */ 2755 stride = (dim->width + 11)/12 * 12; 2756 stride_in_bytes = stride * 8 / 6; 2757 buf_planes->plane_info.num_planes = 1; 2758 buf_planes->plane_info.mp[0].offset = 0; 2759 buf_planes->plane_info.mp[0].len = 2760 PAD_TO_SIZE((uint32_t)(stride_in_bytes * scanline), 2761 padding->plane_padding); 2762 buf_planes->plane_info.frame_len = 2763 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K); 2764 buf_planes->plane_info.mp[0].offset_x =0; 2765 buf_planes->plane_info.mp[0].offset_y = 0; 2766 buf_planes->plane_info.mp[0].stride = stride; 2767 buf_planes->plane_info.mp[0].stride_in_bytes = stride_in_bytes; 2768 buf_planes->plane_info.mp[0].scanline = scanline; 2769 buf_planes->plane_info.mp[0].width = (int32_t)buf_planes->plane_info.mp[0].len; 2770 buf_planes->plane_info.mp[0].height = 1; 2771 break; 2772 case CAM_FORMAT_BAYER_QCOM_RAW_12BPP_GBRG: 2773 case CAM_FORMAT_BAYER_QCOM_RAW_12BPP_GRBG: 2774 case CAM_FORMAT_BAYER_QCOM_RAW_12BPP_RGGB: 2775 case CAM_FORMAT_BAYER_QCOM_RAW_12BPP_BGGR: 2776 case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_12BPP_GBRG: 2777 case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_12BPP_GRBG: 2778 case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_12BPP_RGGB: 2779 case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_12BPP_BGGR: 2780 /* Every 10 pixels occupy 16 bytes */ 2781 stride = (dim->width + 9)/10 * 10; 2782 stride_in_bytes = stride * 8 / 5; 2783 buf_planes->plane_info.num_planes = 1; 2784 buf_planes->plane_info.mp[0].offset = 0; 2785 buf_planes->plane_info.mp[0].len = 2786 PAD_TO_SIZE((uint32_t)(stride_in_bytes * scanline), 2787 padding->plane_padding); 2788 buf_planes->plane_info.frame_len = 2789 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K); 2790 buf_planes->plane_info.mp[0].offset_x =0; 2791 buf_planes->plane_info.mp[0].offset_y = 0; 2792 buf_planes->plane_info.mp[0].stride = stride; 2793 buf_planes->plane_info.mp[0].stride_in_bytes = stride_in_bytes; 2794 buf_planes->plane_info.mp[0].scanline = scanline; 2795 buf_planes->plane_info.mp[0].width = (int32_t)buf_planes->plane_info.mp[0].len; 2796 buf_planes->plane_info.mp[0].height = 1; 2797 break; 2798 case CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GBRG: 2799 case CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GRBG: 2800 case CAM_FORMAT_BAYER_MIPI_RAW_10BPP_RGGB: 2801 case CAM_FORMAT_BAYER_MIPI_RAW_10BPP_BGGR: 2802 case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_10BPP_GBRG: 2803 case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_10BPP_GRBG: 2804 case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_10BPP_RGGB: 2805 case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_10BPP_BGGR: 2806 /* Every 64 pixels occupy 80 bytes */ 2807 stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_4); 2808 stride_in_bytes = PAD_TO_SIZE(stride * 5 / 4, CAM_PAD_TO_8); 2809 buf_planes->plane_info.num_planes = 1; 2810 buf_planes->plane_info.mp[0].offset = 0; 2811 buf_planes->plane_info.mp[0].len = 2812 PAD_TO_SIZE((uint32_t)(stride_in_bytes * scanline), 2813 padding->plane_padding); 2814 buf_planes->plane_info.frame_len = 2815 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K); 2816 buf_planes->plane_info.mp[0].offset_x =0; 2817 buf_planes->plane_info.mp[0].offset_y = 0; 2818 buf_planes->plane_info.mp[0].stride = stride; 2819 buf_planes->plane_info.mp[0].stride_in_bytes = stride_in_bytes; 2820 buf_planes->plane_info.mp[0].scanline = scanline; 2821 buf_planes->plane_info.mp[0].width = (int32_t)buf_planes->plane_info.mp[0].len; 2822 buf_planes->plane_info.mp[0].height = 1; 2823 break; 2824 case CAM_FORMAT_BAYER_MIPI_RAW_12BPP_GBRG: 2825 case CAM_FORMAT_BAYER_MIPI_RAW_12BPP_GRBG: 2826 case CAM_FORMAT_BAYER_MIPI_RAW_12BPP_RGGB: 2827 case CAM_FORMAT_BAYER_MIPI_RAW_12BPP_BGGR: 2828 case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_12BPP_GBRG: 2829 case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_12BPP_GRBG: 2830 case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_12BPP_RGGB: 2831 case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_12BPP_BGGR: 2832 /* Every 32 pixels occupy 48 bytes */ 2833 stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_32); 2834 stride_in_bytes = stride * 3 / 2; 2835 buf_planes->plane_info.num_planes = 1; 2836 buf_planes->plane_info.mp[0].offset = 0; 2837 buf_planes->plane_info.mp[0].len = 2838 PAD_TO_SIZE((uint32_t)(stride_in_bytes * scanline), 2839 padding->plane_padding); 2840 buf_planes->plane_info.frame_len = 2841 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K); 2842 buf_planes->plane_info.mp[0].offset_x =0; 2843 buf_planes->plane_info.mp[0].offset_y = 0; 2844 buf_planes->plane_info.mp[0].stride = stride; 2845 buf_planes->plane_info.mp[0].stride_in_bytes = stride_in_bytes; 2846 buf_planes->plane_info.mp[0].scanline = scanline; 2847 buf_planes->plane_info.mp[0].width = (int32_t)buf_planes->plane_info.mp[0].len; 2848 buf_planes->plane_info.mp[0].height = 1; 2849 break; 2850 case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_8BPP_GBRG: 2851 case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_8BPP_GRBG: 2852 case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_8BPP_RGGB: 2853 case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_8BPP_BGGR: 2854 case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_10BPP_GBRG: 2855 case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_10BPP_GRBG: 2856 case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_10BPP_RGGB: 2857 case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_10BPP_BGGR: 2858 case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_12BPP_GBRG: 2859 case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_12BPP_GRBG: 2860 case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_12BPP_RGGB: 2861 case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_12BPP_BGGR: 2862 /* Every 8 pixels occupy 16 bytes */ 2863 stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_8); 2864 stride_in_bytes = stride * 2; 2865 buf_planes->plane_info.num_planes = 1; 2866 buf_planes->plane_info.mp[0].offset = 0; 2867 buf_planes->plane_info.mp[0].len = 2868 PAD_TO_SIZE((uint32_t)(stride_in_bytes * scanline), 2869 padding->plane_padding); 2870 buf_planes->plane_info.frame_len = 2871 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K); 2872 buf_planes->plane_info.mp[0].offset_x =0; 2873 buf_planes->plane_info.mp[0].offset_y = 0; 2874 buf_planes->plane_info.mp[0].stride = stride; 2875 buf_planes->plane_info.mp[0].stride_in_bytes = stride_in_bytes; 2876 buf_planes->plane_info.mp[0].scanline = scanline; 2877 buf_planes->plane_info.mp[0].width = (int32_t)buf_planes->plane_info.mp[0].len; 2878 buf_planes->plane_info.mp[0].height = 1; 2879 break; 2880 default: 2881 CDBG_ERROR("%s: Invalid cam_format %d for raw stream", 2882 __func__, fmt); 2883 rc = -1; 2884 break; 2885 } 2886 2887 return rc; 2888 } 2889 2890 /*=========================================================================== 2891 * FUNCTION : mm_stream_calc_offset_video 2892 * 2893 * DESCRIPTION: calculate video frame offset based on format and 2894 * padding information 2895 * 2896 * PARAMETERS : 2897 * @dim : image dimension 2898 * @buf_planes : [out] buffer plane information 2899 * 2900 * RETURN : int32_t type of status 2901 * 0 -- success 2902 * -1 -- failure 2903 *==========================================================================*/ 2904 #ifdef VENUS_PRESENT 2905 int32_t mm_stream_calc_offset_video(cam_dimension_t *dim, 2906 cam_stream_buf_plane_info_t *buf_planes) 2907 { 2908 int stride = 0, scanline = 0; 2909 2910 // using Venus 2911 stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, dim->width); 2912 scanline = VENUS_Y_SCANLINES(COLOR_FMT_NV12, dim->height); 2913 2914 buf_planes->plane_info.frame_len = 2915 VENUS_BUFFER_SIZE(COLOR_FMT_NV12, dim->width, dim->height); 2916 buf_planes->plane_info.num_planes = 2; 2917 buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline); 2918 buf_planes->plane_info.mp[0].offset = 0; 2919 buf_planes->plane_info.mp[0].offset_x =0; 2920 buf_planes->plane_info.mp[0].offset_y = 0; 2921 buf_planes->plane_info.mp[0].stride = stride; 2922 buf_planes->plane_info.mp[0].scanline = scanline; 2923 buf_planes->plane_info.mp[0].width = dim->width; 2924 buf_planes->plane_info.mp[0].height = dim->height; 2925 stride = VENUS_UV_STRIDE(COLOR_FMT_NV12, dim->width); 2926 scanline = VENUS_UV_SCANLINES(COLOR_FMT_NV12, dim->height); 2927 buf_planes->plane_info.mp[1].len = 2928 buf_planes->plane_info.frame_len - buf_planes->plane_info.mp[0].len; 2929 buf_planes->plane_info.mp[1].offset = 0; 2930 buf_planes->plane_info.mp[1].offset_x =0; 2931 buf_planes->plane_info.mp[1].offset_y = 0; 2932 buf_planes->plane_info.mp[1].stride = stride; 2933 buf_planes->plane_info.mp[1].scanline = scanline; 2934 buf_planes->plane_info.mp[1].width = dim->width; 2935 buf_planes->plane_info.mp[1].height = dim->height / 2; 2936 2937 return 0; 2938 } 2939 #else 2940 int32_t mm_stream_calc_offset_video(cam_dimension_t *dim, 2941 cam_stream_buf_plane_info_t *buf_planes) 2942 { 2943 int stride = 0, scanline = 0; 2944 2945 buf_planes->plane_info.num_planes = 2; 2946 2947 stride = dim->width; 2948 scanline = dim->height; 2949 buf_planes->plane_info.mp[0].len = 2950 PAD_TO_SIZE((uint32_t)(stride * scanline), CAM_PAD_TO_2K); 2951 buf_planes->plane_info.mp[0].offset = 0; 2952 buf_planes->plane_info.mp[0].offset_x =0; 2953 buf_planes->plane_info.mp[0].offset_y = 0; 2954 buf_planes->plane_info.mp[0].stride = stride; 2955 buf_planes->plane_info.mp[0].scanline = scanline; 2956 buf_planes->plane_info.mp[0].width = dim->width; 2957 buf_planes->plane_info.mp[0].height = dim->height; 2958 2959 stride = dim->width; 2960 scanline = dim->height / 2; 2961 buf_planes->plane_info.mp[1].len = 2962 PAD_TO_SIZE((uint32_t)(stride * scanline), CAM_PAD_TO_2K); 2963 buf_planes->plane_info.mp[1].offset = 0; 2964 buf_planes->plane_info.mp[1].offset_x =0; 2965 buf_planes->plane_info.mp[1].offset_y = 0; 2966 buf_planes->plane_info.mp[1].stride = stride; 2967 buf_planes->plane_info.mp[1].scanline = scanline; 2968 buf_planes->plane_info.mp[1].width = dim->width; 2969 buf_planes->plane_info.mp[1].height = dim->height / 2; 2970 2971 buf_planes->plane_info.frame_len = 2972 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len + 2973 buf_planes->plane_info.mp[1].len, 2974 CAM_PAD_TO_4K); 2975 2976 return 0; 2977 } 2978 #endif 2979 2980 /*=========================================================================== 2981 * FUNCTION : mm_stream_calc_offset_metadata 2982 * 2983 * DESCRIPTION: calculate metadata frame offset based on format and 2984 * padding information 2985 * 2986 * PARAMETERS : 2987 * @dim : image dimension 2988 * @padding : padding information 2989 * @buf_planes : [out] buffer plane information 2990 * 2991 * RETURN : int32_t type of status 2992 * 0 -- success 2993 * -1 -- failure 2994 *==========================================================================*/ 2995 int32_t mm_stream_calc_offset_metadata(cam_dimension_t *dim, 2996 cam_padding_info_t *padding, 2997 cam_stream_buf_plane_info_t *buf_planes) 2998 { 2999 int32_t rc = 0; 3000 buf_planes->plane_info.num_planes = 1; 3001 buf_planes->plane_info.mp[0].offset = 0; 3002 buf_planes->plane_info.mp[0].len = 3003 PAD_TO_SIZE((uint32_t)(dim->width * dim->height), 3004 padding->plane_padding); 3005 buf_planes->plane_info.frame_len = 3006 buf_planes->plane_info.mp[0].len; 3007 3008 buf_planes->plane_info.mp[0].offset_x =0; 3009 buf_planes->plane_info.mp[0].offset_y = 0; 3010 buf_planes->plane_info.mp[0].stride = dim->width; 3011 buf_planes->plane_info.mp[0].scanline = dim->height; 3012 buf_planes->plane_info.mp[0].width = dim->width; 3013 buf_planes->plane_info.mp[0].height = dim->height; 3014 return rc; 3015 } 3016 3017 /*=========================================================================== 3018 * FUNCTION : mm_stream_calc_offset_analysis 3019 * 3020 * DESCRIPTION: calculate analysis frame offset based on format and 3021 * padding information 3022 * 3023 * PARAMETERS : 3024 * @fmt : image format 3025 * @dim : image dimension 3026 * @padding : padding information 3027 * @buf_planes : [out] buffer plane information 3028 * 3029 * RETURN : int32_t type of status 3030 * 0 -- success 3031 * -1 -- failure 3032 *==========================================================================*/ 3033 int32_t mm_stream_calc_offset_analysis(cam_format_t fmt, 3034 cam_dimension_t *dim, 3035 cam_padding_info_t *padding, 3036 cam_stream_buf_plane_info_t *buf_planes) 3037 { 3038 int32_t rc = 0; 3039 int32_t offset_x = 0, offset_y = 0; 3040 int32_t stride, scanline; 3041 3042 /* Clip to minimum supported bytes per line */ 3043 if ((uint32_t)dim->width < padding->min_stride) { 3044 stride = (int32_t)padding->min_stride; 3045 } else { 3046 stride = dim->width; 3047 } 3048 3049 if ((uint32_t)dim->height < padding->min_scanline) { 3050 scanline = (int32_t)padding->min_scanline; 3051 } else { 3052 scanline = dim->height; 3053 } 3054 3055 stride = PAD_TO_SIZE(stride, padding->width_padding); 3056 scanline = PAD_TO_SIZE(scanline, padding->height_padding); 3057 3058 switch (fmt) { 3059 case CAM_FORMAT_YUV_420_NV12: 3060 case CAM_FORMAT_YUV_420_NV21: 3061 /* 2 planes: Y + CbCr */ 3062 buf_planes->plane_info.num_planes = 2; 3063 3064 buf_planes->plane_info.mp[0].len = 3065 PAD_TO_SIZE((uint32_t)(stride * scanline), 3066 padding->plane_padding); 3067 buf_planes->plane_info.mp[0].offset = 3068 PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y), 3069 padding->plane_padding); 3070 buf_planes->plane_info.mp[0].offset_x = offset_x; 3071 buf_planes->plane_info.mp[0].offset_y = offset_y; 3072 buf_planes->plane_info.mp[0].stride = stride; 3073 buf_planes->plane_info.mp[0].scanline = scanline; 3074 buf_planes->plane_info.mp[0].width = dim->width; 3075 buf_planes->plane_info.mp[0].height = dim->height; 3076 3077 scanline = scanline / 2; 3078 buf_planes->plane_info.mp[1].len = 3079 PAD_TO_SIZE((uint32_t)(stride * scanline), 3080 padding->plane_padding); 3081 buf_planes->plane_info.mp[1].offset = 3082 PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y), 3083 padding->plane_padding); 3084 buf_planes->plane_info.mp[1].offset_x = offset_x; 3085 buf_planes->plane_info.mp[1].offset_y = offset_y; 3086 buf_planes->plane_info.mp[1].stride = stride; 3087 buf_planes->plane_info.mp[1].scanline = scanline; 3088 buf_planes->plane_info.mp[1].width = dim->width; 3089 buf_planes->plane_info.mp[1].height = dim->height / 2; 3090 3091 buf_planes->plane_info.frame_len = 3092 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len + 3093 buf_planes->plane_info.mp[1].len, 3094 CAM_PAD_TO_4K); 3095 break; 3096 case CAM_FORMAT_YUV_420_YV12: 3097 /* 3 planes: Y + Cr + Cb */ 3098 buf_planes->plane_info.num_planes = 3; 3099 3100 buf_planes->plane_info.mp[0].offset = 3101 PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y), 3102 padding->plane_padding); 3103 buf_planes->plane_info.mp[0].len = 3104 PAD_TO_SIZE((uint32_t)(stride * scanline), 3105 padding->plane_padding); 3106 buf_planes->plane_info.mp[0].offset_x = offset_x; 3107 buf_planes->plane_info.mp[0].offset_y = offset_y; 3108 buf_planes->plane_info.mp[0].stride = stride; 3109 buf_planes->plane_info.mp[0].scanline = scanline; 3110 buf_planes->plane_info.mp[0].width = dim->width; 3111 buf_planes->plane_info.mp[0].height = dim->height; 3112 3113 stride = PAD_TO_SIZE(stride / 2, CAM_PAD_TO_16); 3114 scanline = scanline / 2; 3115 buf_planes->plane_info.mp[1].offset = 3116 PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y), 3117 padding->plane_padding); 3118 buf_planes->plane_info.mp[1].len = 3119 PAD_TO_SIZE((uint32_t)(stride * scanline), 3120 padding->plane_padding); 3121 buf_planes->plane_info.mp[1].offset_x = offset_x; 3122 buf_planes->plane_info.mp[1].offset_y = offset_y; 3123 buf_planes->plane_info.mp[1].stride = stride; 3124 buf_planes->plane_info.mp[1].scanline = scanline; 3125 buf_planes->plane_info.mp[1].width = dim->width / 2; 3126 buf_planes->plane_info.mp[1].height = dim->height / 2; 3127 3128 buf_planes->plane_info.mp[2].offset = 3129 PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y), 3130 padding->plane_padding); 3131 buf_planes->plane_info.mp[2].len = 3132 PAD_TO_SIZE((uint32_t)(stride * scanline), 3133 padding->plane_padding); 3134 buf_planes->plane_info.mp[2].offset_x = offset_x; 3135 buf_planes->plane_info.mp[2].offset_y = offset_y; 3136 buf_planes->plane_info.mp[2].stride = stride; 3137 buf_planes->plane_info.mp[2].scanline = scanline; 3138 buf_planes->plane_info.mp[2].width = dim->width / 2; 3139 buf_planes->plane_info.mp[2].height = dim->height / 2; 3140 3141 buf_planes->plane_info.frame_len = 3142 PAD_TO_SIZE(buf_planes->plane_info.mp[0].len + 3143 buf_planes->plane_info.mp[1].len + 3144 buf_planes->plane_info.mp[2].len, 3145 CAM_PAD_TO_4K); 3146 break; 3147 case CAM_FORMAT_YUV_422_NV16: 3148 case CAM_FORMAT_YUV_422_NV61: 3149 /* 2 planes: Y + CbCr */ 3150 buf_planes->plane_info.num_planes = 2; 3151 buf_planes->plane_info.mp[0].len = 3152 PAD_TO_SIZE((uint32_t)(stride * scanline), 3153 padding->plane_padding); 3154 buf_planes->plane_info.mp[0].offset = 3155 PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y), 3156 padding->plane_padding); 3157 buf_planes->plane_info.mp[0].offset_x = offset_x; 3158 buf_planes->plane_info.mp[0].offset_y = offset_y; 3159 buf_planes->plane_info.mp[0].stride = stride; 3160 buf_planes->plane_info.mp[0].scanline = scanline; 3161 buf_planes->plane_info.mp[0].width = dim->width; 3162 buf_planes->plane_info.mp[0].height = dim->height; 3163 3164 buf_planes->plane_info.mp[1].len = 3165 PAD_TO_SIZE((uint32_t)(stride * scanline), 3166 padding->plane_padding); 3167 buf_planes->plane_info.mp[1].offset = 3168 PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y), 3169 padding->plane_padding); 3170 buf_planes->plane_info.mp[1].offset_x = offset_x; 3171 buf_planes->plane_info.mp[1].offset_y = offset_y; 3172 buf_planes->plane_info.mp[1].stride = stride; 3173 buf_planes->plane_info.mp[1].scanline = scanline; 3174 buf_planes->plane_info.mp[1].width = dim->width; 3175 buf_planes->plane_info.mp[1].height = dim->height; 3176 3177 buf_planes->plane_info.frame_len = PAD_TO_SIZE( 3178 buf_planes->plane_info.mp[0].len + buf_planes->plane_info.mp[1].len, 3179 CAM_PAD_TO_4K); 3180 break; 3181 default: 3182 CDBG_ERROR("%s: Invalid cam_format for snapshot %d", 3183 __func__, fmt); 3184 rc = -1; 3185 break; 3186 } 3187 3188 return rc; 3189 } 3190 3191 /*=========================================================================== 3192 * FUNCTION : mm_stream_calc_offset_postproc 3193 * 3194 * DESCRIPTION: calculate postprocess frame offset 3195 * 3196 * PARAMETERS : 3197 * @stream_info: ptr to stream info 3198 * @padding : padding information 3199 * @plns : [out] buffer plane information 3200 * 3201 * RETURN : int32_t type of status 3202 * 0 -- success 3203 * -1 -- failure 3204 *==========================================================================*/ 3205 int32_t mm_stream_calc_offset_postproc(cam_stream_info_t *stream_info, 3206 cam_padding_info_t *padding, 3207 cam_stream_buf_plane_info_t *plns) 3208 { 3209 int32_t rc = 0; 3210 cam_stream_type_t type = CAM_STREAM_TYPE_DEFAULT; 3211 if (stream_info->reprocess_config.pp_type == CAM_OFFLINE_REPROCESS_TYPE) { 3212 type = stream_info->reprocess_config.offline.input_type; 3213 if (CAM_STREAM_TYPE_DEFAULT == type) { 3214 if (plns->plane_info.frame_len == 0) { 3215 // take offset from input source 3216 *plns = stream_info->reprocess_config.offline.input_buf_planes; 3217 return rc; 3218 } 3219 } else { 3220 type = stream_info->reprocess_config.offline.input_type; 3221 } 3222 } else { 3223 type = stream_info->reprocess_config.online.input_stream_type; 3224 } 3225 3226 switch (type) { 3227 case CAM_STREAM_TYPE_PREVIEW: 3228 case CAM_STREAM_TYPE_CALLBACK: 3229 rc = mm_stream_calc_offset_preview(stream_info->fmt, 3230 &stream_info->dim, 3231 plns); 3232 break; 3233 case CAM_STREAM_TYPE_POSTVIEW: 3234 rc = mm_stream_calc_offset_post_view(stream_info->fmt, 3235 &stream_info->dim, 3236 plns); 3237 break; 3238 case CAM_STREAM_TYPE_SNAPSHOT: 3239 rc = mm_stream_calc_offset_snapshot(stream_info->fmt, 3240 &stream_info->dim, 3241 padding, 3242 plns); 3243 break; 3244 case CAM_STREAM_TYPE_VIDEO: 3245 rc = mm_stream_calc_offset_video(&stream_info->dim, 3246 plns); 3247 break; 3248 case CAM_STREAM_TYPE_RAW: 3249 rc = mm_stream_calc_offset_raw(stream_info->fmt, 3250 &stream_info->dim, 3251 padding, 3252 plns); 3253 break; 3254 case CAM_STREAM_TYPE_ANALYSIS: 3255 rc = mm_stream_calc_offset_analysis(stream_info->fmt, 3256 &stream_info->dim, 3257 padding, 3258 plns); 3259 break; 3260 case CAM_STREAM_TYPE_METADATA: 3261 rc = mm_stream_calc_offset_metadata(&stream_info->dim, 3262 padding, 3263 plns); 3264 break; 3265 case CAM_STREAM_TYPE_OFFLINE_PROC: 3266 rc = mm_stream_calc_offset_snapshot(stream_info->fmt, 3267 &stream_info->dim, padding, plns); 3268 break; 3269 default: 3270 CDBG_ERROR("%s: not supported for stream type %d", 3271 __func__, type); 3272 rc = -1; 3273 break; 3274 } 3275 return rc; 3276 } 3277 3278 /*=========================================================================== 3279 * FUNCTION : mm_stream_calc_offset 3280 * 3281 * DESCRIPTION: calculate frame offset based on format and padding information 3282 * 3283 * PARAMETERS : 3284 * @my_obj : stream object 3285 * 3286 * RETURN : int32_t type of status 3287 * 0 -- success 3288 * -1 -- failure 3289 *==========================================================================*/ 3290 int32_t mm_stream_calc_offset(mm_stream_t *my_obj) 3291 { 3292 int32_t rc = 0; 3293 3294 cam_dimension_t dim = my_obj->stream_info->dim; 3295 if (my_obj->stream_info->pp_config.feature_mask & CAM_QCOM_FEATURE_ROTATION && 3296 my_obj->stream_info->stream_type != CAM_STREAM_TYPE_VIDEO) { 3297 if (my_obj->stream_info->pp_config.rotation == ROTATE_90 || 3298 my_obj->stream_info->pp_config.rotation == ROTATE_270) { 3299 // rotated by 90 or 270, need to switch width and height 3300 dim.width = my_obj->stream_info->dim.height; 3301 dim.height = my_obj->stream_info->dim.width; 3302 } 3303 } 3304 3305 switch (my_obj->stream_info->stream_type) { 3306 case CAM_STREAM_TYPE_PREVIEW: 3307 case CAM_STREAM_TYPE_CALLBACK: 3308 rc = mm_stream_calc_offset_preview(my_obj->stream_info->fmt, 3309 &dim, 3310 &my_obj->stream_info->buf_planes); 3311 break; 3312 case CAM_STREAM_TYPE_POSTVIEW: 3313 rc = mm_stream_calc_offset_post_view(my_obj->stream_info->fmt, 3314 &dim, 3315 &my_obj->stream_info->buf_planes); 3316 break; 3317 case CAM_STREAM_TYPE_SNAPSHOT: 3318 rc = mm_stream_calc_offset_snapshot(my_obj->stream_info->fmt, 3319 &dim, 3320 &my_obj->padding_info, 3321 &my_obj->stream_info->buf_planes); 3322 break; 3323 case CAM_STREAM_TYPE_OFFLINE_PROC: 3324 rc = mm_stream_calc_offset_postproc(my_obj->stream_info, 3325 &my_obj->padding_info, 3326 &my_obj->stream_info->buf_planes); 3327 break; 3328 case CAM_STREAM_TYPE_VIDEO: 3329 rc = mm_stream_calc_offset_video(&dim, 3330 &my_obj->stream_info->buf_planes); 3331 break; 3332 case CAM_STREAM_TYPE_RAW: 3333 rc = mm_stream_calc_offset_raw(my_obj->stream_info->fmt, 3334 &dim, 3335 &my_obj->padding_info, 3336 &my_obj->stream_info->buf_planes); 3337 break; 3338 case CAM_STREAM_TYPE_ANALYSIS: 3339 rc = mm_stream_calc_offset_analysis(my_obj->stream_info->fmt, 3340 &dim, 3341 &my_obj->padding_info, 3342 &my_obj->stream_info->buf_planes); 3343 break; 3344 case CAM_STREAM_TYPE_METADATA: 3345 rc = mm_stream_calc_offset_metadata(&dim, 3346 &my_obj->padding_info, 3347 &my_obj->stream_info->buf_planes); 3348 break; 3349 default: 3350 CDBG_ERROR("%s: not supported for stream type %d", 3351 __func__, my_obj->stream_info->stream_type); 3352 rc = -1; 3353 break; 3354 } 3355 3356 my_obj->frame_offset = my_obj->stream_info->buf_planes.plane_info; 3357 return rc; 3358 } 3359 3360 /*=========================================================================== 3361 * FUNCTION : mm_stream_sync_info 3362 * 3363 * DESCRIPTION: synchronize stream information with server 3364 * 3365 * PARAMETERS : 3366 * @my_obj : stream object 3367 * 3368 * RETURN : int32_t type of status 3369 * 0 -- success 3370 * -1 -- failure 3371 * NOTE : assume stream info buffer is mapped to server and filled in with 3372 * stream information by upper layer. This call will let server to 3373 * synchornize the stream information with HAL. If server find any 3374 * fields that need to be changed accroding to hardware configuration, 3375 * server will modify corresponding fields so that HAL could know 3376 * about it. 3377 *==========================================================================*/ 3378 int32_t mm_stream_sync_info(mm_stream_t *my_obj) 3379 { 3380 int32_t rc = 0; 3381 int32_t value = 0; 3382 my_obj->stream_info->stream_svr_id = my_obj->server_stream_id; 3383 rc = mm_stream_calc_offset(my_obj); 3384 3385 if (rc == 0) { 3386 rc = mm_camera_util_s_ctrl(my_obj->fd, 3387 CAM_PRIV_STREAM_INFO_SYNC, 3388 &value); 3389 } 3390 return rc; 3391 } 3392 3393 /*=========================================================================== 3394 * FUNCTION : mm_stream_set_fmt 3395 * 3396 * DESCRIPTION: set stream format to kernel via v4l2 ioctl 3397 * 3398 * PARAMETERS : 3399 * @my_obj : stream object 3400 * 3401 * RETURN : int32_t type of status 3402 * 0 -- success 3403 * -1 -- failure 3404 *==========================================================================*/ 3405 int32_t mm_stream_set_fmt(mm_stream_t *my_obj) 3406 { 3407 int32_t rc = 0; 3408 struct v4l2_format fmt; 3409 struct msm_v4l2_format_data msm_fmt; 3410 int i; 3411 3412 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d", 3413 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state); 3414 3415 if (my_obj->stream_info->dim.width == 0 || 3416 my_obj->stream_info->dim.height == 0) { 3417 CDBG_ERROR("%s:invalid input[w=%d,h=%d,fmt=%d]\n", 3418 __func__, 3419 my_obj->stream_info->dim.width, 3420 my_obj->stream_info->dim.height, 3421 my_obj->stream_info->fmt); 3422 return -1; 3423 } 3424 3425 memset(&fmt, 0, sizeof(fmt)); 3426 memset(&msm_fmt, 0, sizeof(msm_fmt)); 3427 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 3428 msm_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 3429 3430 3431 msm_fmt.width = (unsigned int)my_obj->stream_info->dim.width; 3432 msm_fmt.height = (unsigned int)my_obj->stream_info->dim.height; 3433 msm_fmt.pixelformat = mm_stream_get_v4l2_fmt(my_obj->stream_info->fmt); 3434 3435 if (my_obj->stream_info->streaming_mode != CAM_STREAMING_MODE_BATCH) { 3436 msm_fmt.num_planes = (unsigned char)my_obj->frame_offset.num_planes; 3437 for (i = 0; i < msm_fmt.num_planes; i++) { 3438 msm_fmt.plane_sizes[i] = my_obj->frame_offset.mp[i].len; 3439 } 3440 } else { 3441 msm_fmt.num_planes = 1; 3442 msm_fmt.plane_sizes[0] = my_obj->stream_info->user_buf_info.size; 3443 } 3444 3445 memcpy(fmt.fmt.raw_data, &msm_fmt, sizeof(msm_fmt)); 3446 rc = ioctl(my_obj->fd, VIDIOC_S_FMT, &fmt); 3447 return rc; 3448 } 3449 3450 /*=========================================================================== 3451 * FUNCTION : mm_stream_buf_done 3452 * 3453 * DESCRIPTION: enqueue buffer back to kernel 3454 * 3455 * PARAMETERS : 3456 * @my_obj : stream object 3457 * @frame : frame to be enqueued back to kernel 3458 * 3459 * RETURN : int32_t type of status 3460 * 0 -- success 3461 * -1 -- failure 3462 *==========================================================================*/ 3463 int32_t mm_stream_buf_done(mm_stream_t * my_obj, 3464 mm_camera_buf_def_t *frame) 3465 { 3466 int32_t rc = 0; 3467 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d", 3468 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state); 3469 3470 pthread_mutex_lock(&my_obj->buf_lock); 3471 if (my_obj->stream_info->streaming_mode == CAM_STREAMING_MODE_BATCH) { 3472 rc = mm_stream_write_user_buf(my_obj, frame); 3473 } else if(my_obj->buf_status[frame->buf_idx].buf_refcnt == 0) { 3474 CDBG("%s: Error Trying to free second time?(idx=%d) count=%d\n", 3475 __func__, frame->buf_idx, 3476 my_obj->buf_status[frame->buf_idx].buf_refcnt); 3477 rc = -1; 3478 } else { 3479 my_obj->buf_status[frame->buf_idx].buf_refcnt--; 3480 if (0 == my_obj->buf_status[frame->buf_idx].buf_refcnt) { 3481 CDBG("<DEBUG> : Buf done for buffer:%d, stream:%d", frame->buf_idx, frame->stream_type); 3482 rc = mm_stream_qbuf(my_obj, frame); 3483 if(rc < 0) { 3484 CDBG_ERROR("%s: mm_camera_stream_qbuf(idx=%d) err=%d\n", 3485 __func__, frame->buf_idx, rc); 3486 } else { 3487 my_obj->buf_status[frame->buf_idx].in_kernel = 1; 3488 } 3489 }else{ 3490 CDBG("<DEBUG> : Still ref count pending count :%d", 3491 my_obj->buf_status[frame->buf_idx].buf_refcnt); 3492 CDBG("<DEBUG> : for buffer:%p:%d", 3493 my_obj, frame->buf_idx); 3494 } 3495 } 3496 pthread_mutex_unlock(&my_obj->buf_lock); 3497 return rc; 3498 } 3499 3500 3501 /*=========================================================================== 3502 * FUNCTION : mm_stream_get_queued_buf_count 3503 * 3504 * DESCRIPTION: return queued buffer count 3505 * 3506 * PARAMETERS : 3507 * @my_obj : stream object 3508 * 3509 * RETURN : queued buffer count 3510 *==========================================================================*/ 3511 int32_t mm_stream_get_queued_buf_count(mm_stream_t *my_obj) 3512 { 3513 int32_t rc = 0; 3514 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d", 3515 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state); 3516 pthread_mutex_lock(&my_obj->buf_lock); 3517 rc = my_obj->queued_buffer_count; 3518 pthread_mutex_unlock(&my_obj->buf_lock); 3519 return rc; 3520 } 3521 3522 /*=========================================================================== 3523 * FUNCTION : mm_stream_reg_buf_cb 3524 * 3525 * DESCRIPTION: Allow other stream to register dataCB at this stream. 3526 * 3527 * PARAMETERS : 3528 * @my_obj : stream object 3529 * @val : ptr to info about the callback to be registered 3530 * 3531 * RETURN : int32_t type of status 3532 * 0 -- success 3533 * -1 -- failure 3534 *==========================================================================*/ 3535 int32_t mm_stream_reg_buf_cb(mm_stream_t *my_obj, 3536 mm_stream_data_cb_t *val) 3537 { 3538 int32_t rc = -1; 3539 uint8_t i; 3540 CDBG("%s: E, my_handle = 0x%x, fd = %d, state = %d", 3541 __func__, my_obj->my_hdl, my_obj->fd, my_obj->state); 3542 3543 pthread_mutex_lock(&my_obj->cb_lock); 3544 for (i=0 ;i < MM_CAMERA_STREAM_BUF_CB_MAX; i++) { 3545 if(NULL == my_obj->buf_cb[i].cb) { 3546 my_obj->buf_cb[i] = *val; 3547 rc = 0; 3548 break; 3549 } 3550 } 3551 pthread_mutex_unlock(&my_obj->cb_lock); 3552 3553 return rc; 3554 } 3555