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