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