| /* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are |
| * met: |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above |
| * copyright notice, this list of conditions and the following |
| * disclaimer in the documentation and/or other materials provided |
| * with the distribution. |
| * * Neither the name of The Linux Foundation nor the names of its |
| * contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED |
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT |
| * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS |
| * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
| * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE |
| * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN |
| * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| * |
| */ |
| |
| // System dependencies |
| #include <stdlib.h> |
| #include <pthread.h> |
| #include <errno.h> |
| #include <fcntl.h> |
| #include <media/msm_media_info.h> |
| #define TIME_H <SYSTEM_HEADER_PREFIX/time.h> |
| #include TIME_H |
| #define IOCTL_H <SYSTEM_HEADER_PREFIX/ioctl.h> |
| #include IOCTL_H |
| |
| // Camera dependencies |
| #include "cam_semaphore.h" |
| #include "mm_camera_dbg.h" |
| #include "mm_camera_interface.h" |
| #include "mm_camera.h" |
| |
| /* internal function decalre */ |
| int32_t mm_stream_qbuf(mm_stream_t *my_obj, |
| mm_camera_buf_def_t *buf); |
| int32_t mm_stream_set_ext_mode(mm_stream_t * my_obj); |
| int32_t mm_stream_set_fmt(mm_stream_t * my_obj); |
| int32_t mm_stream_sync_info(mm_stream_t *my_obj); |
| int32_t mm_stream_init_bufs(mm_stream_t * my_obj); |
| int32_t mm_stream_deinit_bufs(mm_stream_t * my_obj); |
| int32_t mm_stream_request_buf(mm_stream_t * my_obj); |
| int32_t mm_stream_unreg_buf(mm_stream_t * my_obj); |
| int32_t mm_stream_release(mm_stream_t *my_obj); |
| int32_t mm_stream_set_parm(mm_stream_t *my_obj, |
| cam_stream_parm_buffer_t *value); |
| int32_t mm_stream_get_parm(mm_stream_t *my_obj, |
| cam_stream_parm_buffer_t *value); |
| int32_t mm_stream_do_action(mm_stream_t *my_obj, |
| void *in_value); |
| int32_t mm_stream_streamon(mm_stream_t *my_obj); |
| int32_t mm_stream_streamoff(mm_stream_t *my_obj); |
| int32_t mm_stream_read_msm_frame(mm_stream_t * my_obj, |
| mm_camera_buf_info_t* buf_info, |
| uint8_t num_planes); |
| int32_t mm_stream_read_user_buf(mm_stream_t * my_obj, |
| mm_camera_buf_info_t* buf_info); |
| int32_t mm_stream_write_user_buf(mm_stream_t * my_obj, |
| mm_camera_buf_def_t *buf); |
| |
| int32_t mm_stream_config(mm_stream_t *my_obj, |
| mm_camera_stream_config_t *config); |
| int32_t mm_stream_reg_buf(mm_stream_t * my_obj); |
| int32_t mm_stream_buf_done(mm_stream_t * my_obj, |
| mm_camera_buf_def_t *frame); |
| int32_t mm_stream_get_queued_buf_count(mm_stream_t * my_obj); |
| |
| int32_t mm_stream_calc_offset(mm_stream_t *my_obj); |
| int32_t mm_stream_calc_offset_preview(cam_stream_info_t *stream_info, |
| cam_dimension_t *dim, |
| cam_padding_info_t *padding, |
| cam_stream_buf_plane_info_t *buf_planes); |
| int32_t mm_stream_calc_offset_post_view(cam_format_t fmt, |
| cam_dimension_t *dim, |
| cam_stream_buf_plane_info_t *buf_planes); |
| |
| int32_t mm_stream_calc_offset_snapshot(cam_format_t fmt, |
| cam_dimension_t *dim, |
| cam_padding_info_t *padding, |
| cam_stream_buf_plane_info_t *buf_planes); |
| int32_t mm_stream_calc_offset_raw(cam_format_t fmt, |
| cam_dimension_t *dim, |
| cam_padding_info_t *padding, |
| cam_stream_buf_plane_info_t *buf_planes); |
| int32_t mm_stream_calc_offset_video(cam_format_t fmt, |
| cam_dimension_t *dim, |
| cam_stream_buf_plane_info_t *buf_planes); |
| int32_t mm_stream_calc_offset_metadata(cam_dimension_t *dim, |
| cam_padding_info_t *padding, |
| cam_stream_buf_plane_info_t *buf_planes); |
| int32_t mm_stream_calc_offset_postproc(cam_stream_info_t *stream_info, |
| cam_padding_info_t *padding, |
| cam_stream_buf_plane_info_t *plns); |
| uint32_t mm_stream_calc_lcm(int32_t num1, int32_t num2); |
| |
| |
| /* state machine function declare */ |
| int32_t mm_stream_fsm_inited(mm_stream_t * my_obj, |
| mm_stream_evt_type_t evt, |
| void * in_val, |
| void * out_val); |
| int32_t mm_stream_fsm_acquired(mm_stream_t * my_obj, |
| mm_stream_evt_type_t evt, |
| void * in_val, |
| void * out_val); |
| int32_t mm_stream_fsm_cfg(mm_stream_t * my_obj, |
| mm_stream_evt_type_t evt, |
| void * in_val, |
| void * out_val); |
| int32_t mm_stream_fsm_buffed(mm_stream_t * my_obj, |
| mm_stream_evt_type_t evt, |
| void * in_val, |
| void * out_val); |
| int32_t mm_stream_fsm_reg(mm_stream_t * my_obj, |
| mm_stream_evt_type_t evt, |
| void * in_val, |
| void * out_val); |
| int32_t mm_stream_fsm_active(mm_stream_t * my_obj, |
| mm_stream_evt_type_t evt, |
| void * in_val, |
| void * out_val); |
| uint32_t mm_stream_get_v4l2_fmt(cam_format_t fmt); |
| |
| |
| /*=========================================================================== |
| * FUNCTION : mm_stream_notify_channel |
| * |
| * DESCRIPTION: function to notify channel object on received buffer |
| * |
| * PARAMETERS : |
| * @ch_obj : channel object |
| * @buf_info: ptr to struct storing buffer information |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * 0> -- failure |
| *==========================================================================*/ |
| int32_t mm_stream_notify_channel(struct mm_channel* ch_obj, |
| mm_camera_buf_info_t *buf_info) |
| { |
| int32_t rc = 0; |
| mm_camera_cmdcb_t* node = NULL; |
| |
| if ((NULL == ch_obj) || (NULL == buf_info)) { |
| LOGD("Invalid channel/buffer"); |
| return -ENODEV; |
| } |
| |
| /* send cam_sem_post to wake up channel cmd thread to enqueue |
| * to super buffer */ |
| node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t)); |
| if (NULL != node) { |
| memset(node, 0, sizeof(mm_camera_cmdcb_t)); |
| node->cmd_type = MM_CAMERA_CMD_TYPE_DATA_CB; |
| node->u.buf = *buf_info; |
| |
| /* enqueue to cmd thread */ |
| cam_queue_enq(&(ch_obj->cmd_thread.cmd_queue), node); |
| |
| /* wake up cmd thread */ |
| cam_sem_post(&(ch_obj->cmd_thread.cmd_sem)); |
| } else { |
| LOGE("No memory for mm_camera_node_t"); |
| rc = -ENOMEM; |
| } |
| |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_stream_handle_rcvd_buf |
| * |
| * DESCRIPTION: function to handle newly received stream buffer |
| * |
| * PARAMETERS : |
| * @cam_obj : stream object |
| * @buf_info: ptr to struct storing buffer information |
| * |
| * RETURN : none |
| *==========================================================================*/ |
| void mm_stream_handle_rcvd_buf(mm_stream_t *my_obj, |
| mm_camera_buf_info_t *buf_info, |
| uint8_t has_cb) |
| { |
| int32_t rc = 0; |
| LOGD("E, my_handle = 0x%x, fd = %d, state = %d", |
| my_obj->my_hdl, my_obj->fd, my_obj->state); |
| |
| /* enqueue to super buf thread */ |
| if (my_obj->is_bundled) { |
| rc = mm_stream_notify_channel(my_obj->ch_obj, buf_info); |
| if (rc < 0) { |
| LOGE("Unable to notify channel"); |
| } |
| } |
| |
| pthread_mutex_lock(&my_obj->buf_lock); |
| if(my_obj->is_linked) { |
| /* need to add into super buf for linking, add ref count */ |
| my_obj->buf_status[buf_info->buf->buf_idx].buf_refcnt++; |
| |
| rc = mm_stream_notify_channel(my_obj->linked_obj, buf_info); |
| if (rc < 0) { |
| LOGE("Unable to notify channel"); |
| } |
| } |
| pthread_mutex_unlock(&my_obj->buf_lock); |
| |
| pthread_mutex_lock(&my_obj->cmd_lock); |
| if(has_cb && my_obj->cmd_thread.is_active) { |
| mm_camera_cmdcb_t* node = NULL; |
| |
| /* send cam_sem_post to wake up cmd thread to dispatch dataCB */ |
| node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t)); |
| if (NULL != node) { |
| memset(node, 0, sizeof(mm_camera_cmdcb_t)); |
| node->cmd_type = MM_CAMERA_CMD_TYPE_DATA_CB; |
| node->u.buf = *buf_info; |
| |
| /* enqueue to cmd thread */ |
| cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node); |
| |
| /* wake up cmd thread */ |
| cam_sem_post(&(my_obj->cmd_thread.cmd_sem)); |
| } else { |
| LOGE("No memory for mm_camera_node_t"); |
| } |
| } |
| pthread_mutex_unlock(&my_obj->cmd_lock); |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_stream_dispatch_sync_data |
| * |
| * DESCRIPTION: dispatch stream buffer to registered users on poll thread |
| * |
| * PARAMETERS : |
| * @cmd_cb : ptr storing stream buffer information |
| * @userdata: user data ptr (stream object) |
| * |
| * RETURN : none |
| *==========================================================================*/ |
| static void mm_stream_dispatch_sync_data(mm_stream_t * my_obj, |
| mm_stream_data_cb_t *buf_cb, mm_camera_buf_info_t *buf_info) |
| { |
| mm_camera_super_buf_t super_buf; |
| |
| if (NULL == my_obj || buf_info == NULL || |
| buf_cb == NULL) { |
| return; |
| } |
| |
| memset(&super_buf, 0, sizeof(mm_camera_super_buf_t)); |
| super_buf.num_bufs = 1; |
| super_buf.bufs[0] = buf_info->buf; |
| super_buf.camera_handle = my_obj->ch_obj->cam_obj->my_hdl; |
| super_buf.ch_id = my_obj->ch_obj->my_hdl; |
| if ((buf_cb != NULL) && (buf_cb->cb_type == MM_CAMERA_STREAM_CB_TYPE_SYNC) |
| && (buf_cb->cb_count != 0)) { |
| /* callback */ |
| buf_cb->cb(&super_buf, buf_cb->user_data); |
| |
| /* if >0, reduce count by 1 every time we called CB until reaches 0 |
| * when count reach 0, reset the buf_cb to have no CB */ |
| if (buf_cb->cb_count > 0) { |
| buf_cb->cb_count--; |
| if (0 == buf_cb->cb_count) { |
| buf_cb->cb = NULL; |
| buf_cb->user_data = NULL; |
| } |
| } |
| } |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_stream_data_notify |
| * |
| * DESCRIPTION: callback to handle data notify from kernel |
| * |
| * PARAMETERS : |
| * @user_data : user data ptr (stream object) |
| * |
| * RETURN : none |
| *==========================================================================*/ |
| static void mm_stream_data_notify(void* user_data) |
| { |
| mm_stream_t *my_obj = (mm_stream_t*)user_data; |
| int32_t i, rc; |
| uint8_t has_cb = 0, length = 0; |
| mm_camera_buf_info_t buf_info; |
| |
| if (NULL == my_obj) { |
| return; |
| } |
| |
| LOGD("E, my_handle = 0x%x, fd = %d, state = %d", |
| my_obj->my_hdl, my_obj->fd, my_obj->state); |
| if (MM_STREAM_STATE_ACTIVE != my_obj->state) { |
| /* this Cb will only received in active_stream_on state |
| * if not so, return here */ |
| LOGE("ERROR!! Wrong state (%d) to receive data notify!", |
| my_obj->state); |
| return; |
| } |
| |
| if (my_obj->stream_info->streaming_mode == CAM_STREAMING_MODE_BATCH) { |
| length = 1; |
| } else { |
| length = my_obj->frame_offset.num_planes; |
| } |
| |
| memset(&buf_info, 0, sizeof(mm_camera_buf_info_t)); |
| rc = mm_stream_read_msm_frame(my_obj, &buf_info, |
| (uint8_t)length); |
| if (rc != 0) { |
| return; |
| } |
| uint32_t idx = buf_info.buf->buf_idx; |
| |
| pthread_mutex_lock(&my_obj->cb_lock); |
| for (i = 0; i < MM_CAMERA_STREAM_BUF_CB_MAX; i++) { |
| if(NULL != my_obj->buf_cb[i].cb) { |
| if (my_obj->buf_cb[i].cb_type == MM_CAMERA_STREAM_CB_TYPE_SYNC) { |
| /*For every SYNC callback, send data*/ |
| mm_stream_dispatch_sync_data(my_obj, |
| &my_obj->buf_cb[i], &buf_info); |
| } else { |
| /* for every ASYNC CB, need ref count */ |
| has_cb = 1; |
| } |
| } |
| } |
| pthread_mutex_unlock(&my_obj->cb_lock); |
| |
| pthread_mutex_lock(&my_obj->buf_lock); |
| /* update buffer location */ |
| my_obj->buf_status[idx].in_kernel = 0; |
| |
| /* update buf ref count */ |
| if (my_obj->is_bundled) { |
| /* need to add into super buf since bundled, add ref count */ |
| my_obj->buf_status[idx].buf_refcnt++; |
| } |
| my_obj->buf_status[idx].buf_refcnt = |
| (uint8_t)(my_obj->buf_status[idx].buf_refcnt + has_cb); |
| pthread_mutex_unlock(&my_obj->buf_lock); |
| |
| mm_stream_handle_rcvd_buf(my_obj, &buf_info, has_cb); |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_stream_dispatch_app_data |
| * |
| * DESCRIPTION: dispatch stream buffer to registered users |
| * |
| * PARAMETERS : |
| * @cmd_cb : ptr storing stream buffer information |
| * @userdata: user data ptr (stream object) |
| * |
| * RETURN : none |
| *==========================================================================*/ |
| static void mm_stream_dispatch_app_data(mm_camera_cmdcb_t *cmd_cb, |
| void* user_data) |
| { |
| int i; |
| mm_stream_t * my_obj = (mm_stream_t *)user_data; |
| mm_camera_buf_info_t* buf_info = NULL; |
| mm_camera_super_buf_t super_buf; |
| |
| if (NULL == my_obj) { |
| return; |
| } |
| LOGD("E, my_handle = 0x%x, fd = %d, state = %d", |
| my_obj->my_hdl, my_obj->fd, my_obj->state); |
| |
| if (MM_CAMERA_CMD_TYPE_DATA_CB != cmd_cb->cmd_type) { |
| LOGE("Wrong cmd_type (%d) for dataCB", |
| cmd_cb->cmd_type); |
| return; |
| } |
| |
| buf_info = &cmd_cb->u.buf; |
| memset(&super_buf, 0, sizeof(mm_camera_super_buf_t)); |
| super_buf.num_bufs = 1; |
| super_buf.bufs[0] = buf_info->buf; |
| super_buf.camera_handle = my_obj->ch_obj->cam_obj->my_hdl; |
| super_buf.ch_id = my_obj->ch_obj->my_hdl; |
| |
| pthread_mutex_lock(&my_obj->cb_lock); |
| for(i = 0; i < MM_CAMERA_STREAM_BUF_CB_MAX; i++) { |
| if(NULL != my_obj->buf_cb[i].cb |
| && (my_obj->buf_cb[i].cb_type != |
| MM_CAMERA_STREAM_CB_TYPE_SYNC)) { |
| if (my_obj->buf_cb[i].cb_count != 0) { |
| /* if <0, means infinite CB |
| * if >0, means CB for certain times |
| * both case we need to call CB */ |
| |
| /* increase buf ref cnt */ |
| pthread_mutex_lock(&my_obj->buf_lock); |
| my_obj->buf_status[buf_info->buf->buf_idx].buf_refcnt++; |
| pthread_mutex_unlock(&my_obj->buf_lock); |
| |
| /* callback */ |
| my_obj->buf_cb[i].cb(&super_buf, |
| my_obj->buf_cb[i].user_data); |
| } |
| |
| /* if >0, reduce count by 1 every time we called CB until reaches 0 |
| * when count reach 0, reset the buf_cb to have no CB */ |
| if (my_obj->buf_cb[i].cb_count > 0) { |
| my_obj->buf_cb[i].cb_count--; |
| if (0 == my_obj->buf_cb[i].cb_count) { |
| my_obj->buf_cb[i].cb = NULL; |
| my_obj->buf_cb[i].user_data = NULL; |
| } |
| } |
| } |
| } |
| pthread_mutex_unlock(&my_obj->cb_lock); |
| |
| /* do buf_done since we increased refcnt by one when has_cb */ |
| mm_stream_buf_done(my_obj, buf_info->buf); |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_stream_fsm_fn |
| * |
| * DESCRIPTION: stream finite state machine entry function. Depends on stream |
| * state, incoming event will be handled differently. |
| * |
| * PARAMETERS : |
| * @my_obj : ptr to a stream object |
| * @evt : stream event to be processed |
| * @in_val : input event payload. Can be NULL if not needed. |
| * @out_val : output payload, Can be NULL if not needed. |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_stream_fsm_fn(mm_stream_t *my_obj, |
| mm_stream_evt_type_t evt, |
| void * in_val, |
| void * out_val) |
| { |
| int32_t rc = -1; |
| |
| LOGD("E, my_handle = 0x%x, fd = %d, state = %d", |
| my_obj->my_hdl, my_obj->fd, my_obj->state); |
| switch (my_obj->state) { |
| case MM_STREAM_STATE_NOTUSED: |
| LOGD("Not handling evt in unused state"); |
| break; |
| case MM_STREAM_STATE_INITED: |
| rc = mm_stream_fsm_inited(my_obj, evt, in_val, out_val); |
| break; |
| case MM_STREAM_STATE_ACQUIRED: |
| rc = mm_stream_fsm_acquired(my_obj, evt, in_val, out_val); |
| break; |
| case MM_STREAM_STATE_CFG: |
| rc = mm_stream_fsm_cfg(my_obj, evt, in_val, out_val); |
| break; |
| case MM_STREAM_STATE_BUFFED: |
| rc = mm_stream_fsm_buffed(my_obj, evt, in_val, out_val); |
| break; |
| case MM_STREAM_STATE_REG: |
| rc = mm_stream_fsm_reg(my_obj, evt, in_val, out_val); |
| break; |
| case MM_STREAM_STATE_ACTIVE: |
| rc = mm_stream_fsm_active(my_obj, evt, in_val, out_val); |
| break; |
| default: |
| LOGD("Not a valid state (%d)", my_obj->state); |
| break; |
| } |
| LOGD("X rc =%d",rc); |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_stream_fsm_inited |
| * |
| * DESCRIPTION: stream finite state machine function to handle event in INITED |
| * state. |
| * |
| * PARAMETERS : |
| * @my_obj : ptr to a stream object |
| * @evt : stream event to be processed |
| * @in_val : input event payload. Can be NULL if not needed. |
| * @out_val : output payload, Can be NULL if not needed. |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_stream_fsm_inited(mm_stream_t *my_obj, |
| mm_stream_evt_type_t evt, |
| void * in_val, |
| void * out_val) |
| { |
| int32_t rc = 0; |
| char dev_name[MM_CAMERA_DEV_NAME_LEN]; |
| const char *dev_name_value = NULL; |
| if (NULL == my_obj) { |
| LOGE("NULL camera object\n"); |
| return -1; |
| } |
| |
| LOGD("E, my_handle = 0x%x, fd = %d, state = %d", |
| my_obj->my_hdl, my_obj->fd, my_obj->state); |
| switch(evt) { |
| case MM_STREAM_EVT_ACQUIRE: |
| if ((NULL == my_obj->ch_obj) || (NULL == my_obj->ch_obj->cam_obj)) { |
| LOGE("NULL channel or camera obj\n"); |
| rc = -1; |
| break; |
| } |
| |
| dev_name_value = mm_camera_util_get_dev_name(my_obj->ch_obj->cam_obj->my_hdl); |
| if (NULL == dev_name_value) { |
| LOGE("NULL device name\n"); |
| rc = -1; |
| break; |
| } |
| |
| snprintf(dev_name, sizeof(dev_name), "/dev/%s", |
| dev_name_value); |
| |
| my_obj->fd = open(dev_name, O_RDWR | O_NONBLOCK); |
| if (my_obj->fd < 0) { |
| LOGE("open dev returned %d\n", my_obj->fd); |
| rc = -1; |
| break; |
| } |
| LOGD("open dev fd = %d\n", my_obj->fd); |
| rc = mm_stream_set_ext_mode(my_obj); |
| if (0 == rc) { |
| my_obj->state = MM_STREAM_STATE_ACQUIRED; |
| } else { |
| /* failed setting ext_mode |
| * close fd */ |
| close(my_obj->fd); |
| my_obj->fd = -1; |
| break; |
| } |
| break; |
| default: |
| LOGE("invalid state (%d) for evt (%d), in(%p), out(%p)", |
| my_obj->state, evt, in_val, out_val); |
| break; |
| } |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_stream_fsm_acquired |
| * |
| * DESCRIPTION: stream finite state machine function to handle event in AQUIRED |
| * state. |
| * |
| * PARAMETERS : |
| * @my_obj : ptr to a stream object |
| * @evt : stream event to be processed |
| * @in_val : input event payload. Can be NULL if not needed. |
| * @out_val : output payload, Can be NULL if not needed. |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_stream_fsm_acquired(mm_stream_t *my_obj, |
| mm_stream_evt_type_t evt, |
| void * in_val, |
| void * out_val) |
| { |
| int32_t rc = 0; |
| |
| LOGD("E, my_handle = 0x%x, fd = %d, state = %d", |
| my_obj->my_hdl, my_obj->fd, my_obj->state); |
| switch(evt) { |
| case MM_STREAM_EVT_SET_FMT: |
| { |
| mm_camera_stream_config_t *config = |
| (mm_camera_stream_config_t *)in_val; |
| |
| rc = mm_stream_config(my_obj, config); |
| |
| /* change state to configed */ |
| my_obj->state = MM_STREAM_STATE_CFG; |
| |
| break; |
| } |
| case MM_STREAM_EVT_RELEASE: |
| rc = mm_stream_release(my_obj); |
| /* change state to not used */ |
| my_obj->state = MM_STREAM_STATE_NOTUSED; |
| break; |
| case MM_STREAM_EVT_SET_PARM: |
| { |
| mm_evt_paylod_set_get_stream_parms_t *payload = |
| (mm_evt_paylod_set_get_stream_parms_t *)in_val; |
| rc = mm_stream_set_parm(my_obj, payload->parms); |
| } |
| break; |
| case MM_STREAM_EVT_GET_PARM: |
| { |
| mm_evt_paylod_set_get_stream_parms_t *payload = |
| (mm_evt_paylod_set_get_stream_parms_t *)in_val; |
| rc = mm_stream_get_parm(my_obj, payload->parms); |
| } |
| break; |
| default: |
| LOGE("invalid state (%d) for evt (%d), in(%p), out(%p)", |
| my_obj->state, evt, in_val, out_val); |
| } |
| LOGD("X rc = %d", rc); |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_stream_fsm_cfg |
| * |
| * DESCRIPTION: stream finite state machine function to handle event in CONFIGURED |
| * state. |
| * |
| * PARAMETERS : |
| * @my_obj : ptr to a stream object |
| * @evt : stream event to be processed |
| * @in_val : input event payload. Can be NULL if not needed. |
| * @out_val : output payload, Can be NULL if not needed. |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_stream_fsm_cfg(mm_stream_t * my_obj, |
| mm_stream_evt_type_t evt, |
| void * in_val, |
| void * out_val) |
| { |
| int32_t rc = 0; |
| LOGD("E, my_handle = 0x%x, fd = %d, state = %d", |
| my_obj->my_hdl, my_obj->fd, my_obj->state); |
| switch(evt) { |
| case MM_STREAM_EVT_SET_FMT: |
| { |
| mm_camera_stream_config_t *config = |
| (mm_camera_stream_config_t *)in_val; |
| |
| rc = mm_stream_config(my_obj, config); |
| |
| /* change state to configed */ |
| my_obj->state = MM_STREAM_STATE_CFG; |
| |
| break; |
| } |
| case MM_STREAM_EVT_RELEASE: |
| rc = mm_stream_release(my_obj); |
| my_obj->state = MM_STREAM_STATE_NOTUSED; |
| break; |
| case MM_STREAM_EVT_SET_PARM: |
| { |
| mm_evt_paylod_set_get_stream_parms_t *payload = |
| (mm_evt_paylod_set_get_stream_parms_t *)in_val; |
| rc = mm_stream_set_parm(my_obj, payload->parms); |
| } |
| break; |
| case MM_STREAM_EVT_GET_PARM: |
| { |
| mm_evt_paylod_set_get_stream_parms_t *payload = |
| (mm_evt_paylod_set_get_stream_parms_t *)in_val; |
| rc = mm_stream_get_parm(my_obj, payload->parms); |
| } |
| break; |
| case MM_STREAM_EVT_GET_BUF: |
| rc = mm_stream_init_bufs(my_obj); |
| /* change state to buff allocated */ |
| if(0 == rc) { |
| my_obj->state = MM_STREAM_STATE_BUFFED; |
| } |
| break; |
| default: |
| LOGE("invalid state (%d) for evt (%d), in(%p), out(%p)", |
| my_obj->state, evt, in_val, out_val); |
| } |
| LOGD("X rc = %d", rc); |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_stream_fsm_buffed |
| * |
| * DESCRIPTION: stream finite state machine function to handle event in BUFFED |
| * state. |
| * |
| * PARAMETERS : |
| * @my_obj : ptr to a stream object |
| * @evt : stream event to be processed |
| * @in_val : input event payload. Can be NULL if not needed. |
| * @out_val : output payload, Can be NULL if not needed. |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_stream_fsm_buffed(mm_stream_t * my_obj, |
| mm_stream_evt_type_t evt, |
| void * in_val, |
| void * out_val) |
| { |
| int32_t rc = 0; |
| LOGD("E, my_handle = 0x%x, fd = %d, state = %d", |
| my_obj->my_hdl, my_obj->fd, my_obj->state); |
| switch(evt) { |
| case MM_STREAM_EVT_PUT_BUF: |
| rc = mm_stream_deinit_bufs(my_obj); |
| /* change state to configed */ |
| my_obj->state = MM_STREAM_STATE_CFG; |
| break; |
| case MM_STREAM_EVT_REG_BUF: |
| rc = mm_stream_reg_buf(my_obj); |
| /* change state to regged */ |
| if(0 == rc) { |
| my_obj->state = MM_STREAM_STATE_REG; |
| } |
| break; |
| case MM_STREAM_EVT_SET_PARM: |
| { |
| mm_evt_paylod_set_get_stream_parms_t *payload = |
| (mm_evt_paylod_set_get_stream_parms_t *)in_val; |
| rc = mm_stream_set_parm(my_obj, payload->parms); |
| } |
| break; |
| case MM_STREAM_EVT_GET_PARM: |
| { |
| mm_evt_paylod_set_get_stream_parms_t *payload = |
| (mm_evt_paylod_set_get_stream_parms_t *)in_val; |
| rc = mm_stream_get_parm(my_obj, payload->parms); |
| } |
| break; |
| default: |
| LOGE("invalid state (%d) for evt (%d), in(%p), out(%p)", |
| my_obj->state, evt, in_val, out_val); |
| } |
| LOGD("X rc = %d", rc); |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_stream_fsm_reg |
| * |
| * DESCRIPTION: stream finite state machine function to handle event in REGGED |
| * state. |
| * |
| * PARAMETERS : |
| * @my_obj : ptr to a stream object |
| * @evt : stream event to be processed |
| * @in_val : input event payload. Can be NULL if not needed. |
| * @out_val : output payload, Can be NULL if not needed. |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_stream_fsm_reg(mm_stream_t * my_obj, |
| mm_stream_evt_type_t evt, |
| void * in_val, |
| void * out_val) |
| { |
| int32_t rc = 0; |
| LOGD("E, my_handle = 0x%x, fd = %d, state = %d", |
| my_obj->my_hdl, my_obj->fd, my_obj->state); |
| |
| switch(evt) { |
| case MM_STREAM_EVT_UNREG_BUF: |
| rc = mm_stream_unreg_buf(my_obj); |
| |
| /* change state to buffed */ |
| my_obj->state = MM_STREAM_STATE_BUFFED; |
| break; |
| case MM_STREAM_EVT_START: |
| { |
| uint8_t has_cb = 0; |
| uint8_t i; |
| /* launch cmd thread if CB is not null */ |
| pthread_mutex_lock(&my_obj->cb_lock); |
| for (i = 0; i < MM_CAMERA_STREAM_BUF_CB_MAX; i++) { |
| if((NULL != my_obj->buf_cb[i].cb) && |
| (my_obj->buf_cb[i].cb_type != MM_CAMERA_STREAM_CB_TYPE_SYNC)) { |
| has_cb = 1; |
| break; |
| } |
| } |
| pthread_mutex_unlock(&my_obj->cb_lock); |
| |
| pthread_mutex_lock(&my_obj->cmd_lock); |
| if (has_cb) { |
| snprintf(my_obj->cmd_thread.threadName, THREAD_NAME_SIZE, "CAM_StrmAppData"); |
| mm_camera_cmd_thread_launch(&my_obj->cmd_thread, |
| mm_stream_dispatch_app_data, |
| (void *)my_obj); |
| } |
| pthread_mutex_unlock(&my_obj->cmd_lock); |
| |
| my_obj->state = MM_STREAM_STATE_ACTIVE; |
| rc = mm_stream_streamon(my_obj); |
| if (0 != rc) { |
| /* failed stream on, need to release cmd thread if it's launched */ |
| pthread_mutex_lock(&my_obj->cmd_lock); |
| if (has_cb) { |
| mm_camera_cmd_thread_release(&my_obj->cmd_thread); |
| } |
| pthread_mutex_unlock(&my_obj->cmd_lock); |
| my_obj->state = MM_STREAM_STATE_REG; |
| break; |
| } |
| } |
| break; |
| case MM_STREAM_EVT_SET_PARM: |
| { |
| mm_evt_paylod_set_get_stream_parms_t *payload = |
| (mm_evt_paylod_set_get_stream_parms_t *)in_val; |
| rc = mm_stream_set_parm(my_obj, payload->parms); |
| } |
| break; |
| case MM_STREAM_EVT_GET_PARM: |
| { |
| mm_evt_paylod_set_get_stream_parms_t *payload = |
| (mm_evt_paylod_set_get_stream_parms_t *)in_val; |
| rc = mm_stream_get_parm(my_obj, payload->parms); |
| } |
| break; |
| default: |
| LOGE("invalid state (%d) for evt (%d), in(%p), out(%p)", |
| my_obj->state, evt, in_val, out_val); |
| } |
| LOGD("X rc = %d", rc); |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_stream_fsm_active |
| * |
| * DESCRIPTION: stream finite state machine function to handle event in ACTIVE |
| * state. |
| * |
| * PARAMETERS : |
| * @my_obj : ptr to a stream object |
| * @evt : stream event to be processed |
| * @in_val : input event payload. Can be NULL if not needed. |
| * @out_val : output payload, Can be NULL if not needed. |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_stream_fsm_active(mm_stream_t * my_obj, |
| mm_stream_evt_type_t evt, |
| void * in_val, |
| void * out_val) |
| { |
| int32_t rc = 0; |
| LOGD("E, my_handle = 0x%x, fd = %d, state = %d", |
| my_obj->my_hdl, my_obj->fd, my_obj->state); |
| switch(evt) { |
| case MM_STREAM_EVT_QBUF: |
| rc = mm_stream_buf_done(my_obj, (mm_camera_buf_def_t *)in_val); |
| break; |
| case MM_STREAM_EVT_GET_QUEUED_BUF_COUNT: |
| rc = mm_stream_get_queued_buf_count(my_obj); |
| break; |
| case MM_STREAM_EVT_STOP: |
| { |
| uint8_t has_cb = 0; |
| uint8_t i; |
| rc = mm_stream_streamoff(my_obj); |
| |
| pthread_mutex_lock(&my_obj->cb_lock); |
| for (i = 0; i < MM_CAMERA_STREAM_BUF_CB_MAX; i++) { |
| if(NULL != my_obj->buf_cb[i].cb |
| && my_obj->buf_cb[i].cb_type != MM_CAMERA_STREAM_CB_TYPE_SYNC) { |
| has_cb = 1; |
| break; |
| } |
| } |
| pthread_mutex_unlock(&my_obj->cb_lock); |
| |
| pthread_mutex_lock(&my_obj->cmd_lock); |
| if (has_cb) { |
| mm_camera_cmd_thread_release(&my_obj->cmd_thread); |
| } |
| pthread_mutex_unlock(&my_obj->cmd_lock); |
| my_obj->state = MM_STREAM_STATE_REG; |
| } |
| break; |
| case MM_STREAM_EVT_SET_PARM: |
| { |
| mm_evt_paylod_set_get_stream_parms_t *payload = |
| (mm_evt_paylod_set_get_stream_parms_t *)in_val; |
| rc = mm_stream_set_parm(my_obj, payload->parms); |
| } |
| break; |
| case MM_STREAM_EVT_GET_PARM: |
| { |
| mm_evt_paylod_set_get_stream_parms_t *payload = |
| (mm_evt_paylod_set_get_stream_parms_t *)in_val; |
| rc = mm_stream_get_parm(my_obj, payload->parms); |
| } |
| break; |
| case MM_STREAM_EVT_DO_ACTION: |
| rc = mm_stream_do_action(my_obj, in_val); |
| break; |
| default: |
| LOGE("invalid state (%d) for evt (%d), in(%p), out(%p)", |
| my_obj->state, evt, in_val, out_val); |
| } |
| LOGD("X rc = %d", rc); |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_stream_map_buf_ops |
| * |
| * DESCRIPTION: ops for mapping stream buffer via domain socket to server. |
| * This function will be passed to upper layer as part of ops table |
| * to be used by upper layer when allocating stream buffers and mapping |
| * buffers to server via domain socket. |
| * |
| * PARAMETERS : |
| * @frame_idx : index of buffer within the stream buffers, only valid if |
| * buf_type is CAM_MAPPING_BUF_TYPE_STREAM_BUF or |
| * CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF |
| * @plane_idx : plane index. If all planes share the same fd, |
| * plane_idx = -1; otherwise, plean_idx is the |
| * index to plane (0..num_of_planes) |
| * @fd : file descriptor of the buffer |
| * @size : size of the buffer |
| * @userdata : user data ptr (stream object) |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| static int32_t mm_stream_map_buf_ops(uint32_t frame_idx, |
| int32_t plane_idx, |
| int fd, |
| size_t size, |
| cam_mapping_buf_type type, |
| void *userdata) |
| { |
| mm_stream_t *my_obj = (mm_stream_t *)userdata; |
| return mm_stream_map_buf(my_obj, |
| type, |
| frame_idx, plane_idx, fd, size); |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_stream_bundled_map_buf_ops |
| * |
| * DESCRIPTION: ops for mapping bundled stream buffers via domain socket to server. |
| * This function will be passed to upper layer as part of ops table |
| * to be used by upper layer when allocating stream buffers and mapping |
| * buffers to server via domain socket. |
| * |
| * PARAMETERS : |
| * @buf_map_list : list of buffer mapping information |
| * @userdata : user data ptr (stream object) |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| static int32_t mm_stream_bundled_map_buf_ops( |
| const cam_buf_map_type_list *buf_map_list, |
| void *userdata) |
| { |
| mm_stream_t *my_obj = (mm_stream_t *)userdata; |
| return mm_stream_map_bufs(my_obj, |
| buf_map_list); |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_stream_unmap_buf_ops |
| * |
| * DESCRIPTION: ops for unmapping stream buffer via domain socket to server. |
| * This function will be passed to upper layer as part of ops table |
| * to be used by upper layer when allocating stream buffers and unmapping |
| * buffers to server via domain socket. |
| * |
| * PARAMETERS : |
| * @frame_idx : index of buffer within the stream buffers, only valid if |
| * buf_type is CAM_MAPPING_BUF_TYPE_STREAM_BUF or |
| * CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF |
| * @plane_idx : plane index. If all planes share the same fd, |
| * plane_idx = -1; otherwise, plean_idx is the |
| * index to plane (0..num_of_planes) |
| * @userdata : user data ptr (stream object) |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| static int32_t mm_stream_unmap_buf_ops(uint32_t frame_idx, |
| int32_t plane_idx, |
| cam_mapping_buf_type type, |
| void *userdata) |
| { |
| mm_stream_t *my_obj = (mm_stream_t *)userdata; |
| return mm_stream_unmap_buf(my_obj, |
| type, |
| frame_idx, |
| plane_idx); |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_stream_config |
| * |
| * DESCRIPTION: configure a stream |
| * |
| * PARAMETERS : |
| * @my_obj : stream object |
| * @config : stream configuration |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_stream_config(mm_stream_t *my_obj, |
| mm_camera_stream_config_t *config) |
| { |
| int32_t rc = 0; |
| int32_t cb_index = 0; |
| |
| LOGD("E, my_handle = 0x%x, fd = %d, state = %d", |
| my_obj->my_hdl, my_obj->fd, my_obj->state); |
| my_obj->stream_info = config->stream_info; |
| my_obj->buf_num = (uint8_t) config->stream_info->num_bufs; |
| my_obj->mem_vtbl = config->mem_vtbl; |
| my_obj->padding_info = config->padding_info; |
| |
| if (config->stream_cb_sync != NULL) { |
| /* SYNC callback is always placed at index 0*/ |
| my_obj->buf_cb[cb_index].cb = config->stream_cb_sync; |
| my_obj->buf_cb[cb_index].user_data = config->userdata; |
| my_obj->buf_cb[cb_index].cb_count = -1; /* infinite by default */ |
| my_obj->buf_cb[cb_index].cb_type = MM_CAMERA_STREAM_CB_TYPE_SYNC; |
| cb_index++; |
| } |
| my_obj->buf_cb[cb_index].cb = config->stream_cb; |
| my_obj->buf_cb[cb_index].user_data = config->userdata; |
| my_obj->buf_cb[cb_index].cb_count = -1; /* infinite by default */ |
| my_obj->buf_cb[cb_index].cb_type = MM_CAMERA_STREAM_CB_TYPE_ASYNC; |
| |
| rc = mm_stream_sync_info(my_obj); |
| if (rc == 0) { |
| rc = mm_stream_set_fmt(my_obj); |
| if (rc < 0) { |
| LOGE("mm_stream_set_fmt failed %d", |
| rc); |
| } |
| } |
| |
| my_obj->map_ops.map_ops = mm_stream_map_buf_ops; |
| my_obj->map_ops.bundled_map_ops = mm_stream_bundled_map_buf_ops; |
| my_obj->map_ops.unmap_ops = mm_stream_unmap_buf_ops; |
| my_obj->map_ops.userdata = my_obj; |
| |
| if(my_obj->mem_vtbl.set_config_ops != NULL) { |
| my_obj->mem_vtbl.set_config_ops(&my_obj->map_ops, |
| my_obj->mem_vtbl.user_data); |
| } |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_stream_release |
| * |
| * DESCRIPTION: release a stream resource |
| * |
| * PARAMETERS : |
| * @my_obj : stream object |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_stream_release(mm_stream_t *my_obj) |
| { |
| LOGD("E, my_handle = 0x%x, fd = %d, state = %d", |
| my_obj->my_hdl, my_obj->fd, my_obj->state); |
| |
| pthread_mutex_lock(&my_obj->buf_lock); |
| memset(my_obj->buf_status, 0, sizeof(my_obj->buf_status)); |
| pthread_mutex_unlock(&my_obj->buf_lock); |
| |
| /* close fd */ |
| if(my_obj->fd >= 0) |
| { |
| close(my_obj->fd); |
| } |
| |
| /* destroy mutex */ |
| pthread_cond_destroy(&my_obj->buf_cond); |
| pthread_mutex_destroy(&my_obj->buf_lock); |
| pthread_mutex_destroy(&my_obj->cb_lock); |
| pthread_mutex_destroy(&my_obj->cmd_lock); |
| |
| /* reset stream obj */ |
| memset(my_obj, 0, sizeof(mm_stream_t)); |
| my_obj->fd = -1; |
| |
| return 0; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_stream_streamon |
| * |
| * DESCRIPTION: stream on a stream. sending v4l2 request to kernel |
| * |
| * PARAMETERS : |
| * @my_obj : stream object |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_stream_streamon(mm_stream_t *my_obj) |
| { |
| int32_t rc = 0; |
| int8_t i; |
| enum v4l2_buf_type buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| |
| LOGD("E, my_handle = 0x%x, fd = %d, state = %d", |
| my_obj->my_hdl, my_obj->fd, my_obj->state); |
| |
| pthread_mutex_lock(&my_obj->buf_lock); |
| for (i = 0; i < my_obj->buf_num; i++) { |
| if ((my_obj->buf_status[i].map_status == 0) && |
| (my_obj->buf_status[i].in_kernel)) { |
| LOGD("waiting for mapping to done: strm fd = %d", |
| my_obj->fd); |
| struct timespec ts; |
| clock_gettime(CLOCK_REALTIME, &ts); |
| ts.tv_sec += WAIT_TIMEOUT; |
| rc = pthread_cond_timedwait(&my_obj->buf_cond, &my_obj->buf_lock, &ts); |
| if (rc == ETIMEDOUT) { |
| LOGE("Timed out. Abort stream-on \n"); |
| rc = -1; |
| } |
| break; |
| } else if (my_obj->buf_status[i].map_status < 0) { |
| LOGD("Buffer mapping failed. Abort Stream On"); |
| rc = -1; |
| break; |
| } |
| } |
| pthread_mutex_unlock(&my_obj->buf_lock); |
| |
| if (rc < 0) { |
| /* remove fd from data poll thread in case of failure */ |
| mm_camera_poll_thread_del_poll_fd(&my_obj->ch_obj->poll_thread[0], |
| my_obj->my_hdl, mm_camera_sync_call); |
| return rc; |
| } |
| |
| rc = ioctl(my_obj->fd, VIDIOC_STREAMON, &buf_type); |
| if (rc < 0) { |
| LOGE("ioctl VIDIOC_STREAMON failed: rc=%d, errno %d", |
| rc, errno); |
| /* remove fd from data poll thread in case of failure */ |
| mm_camera_poll_thread_del_poll_fd(&my_obj->ch_obj->poll_thread[0], my_obj->my_hdl, mm_camera_sync_call); |
| } |
| LOGD("X rc = %d",rc); |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_stream_streamoff |
| * |
| * DESCRIPTION: stream off a stream. sending v4l2 request to kernel |
| * |
| * PARAMETERS : |
| * @my_obj : stream object |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_stream_streamoff(mm_stream_t *my_obj) |
| { |
| int32_t rc = 0; |
| enum v4l2_buf_type buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| LOGD("E, my_handle = 0x%x, fd = %d, state = %d", |
| my_obj->my_hdl, my_obj->fd, my_obj->state); |
| |
| /* step1: remove fd from data poll thread */ |
| rc = mm_camera_poll_thread_del_poll_fd(&my_obj->ch_obj->poll_thread[0], |
| my_obj->my_hdl, mm_camera_sync_call); |
| if (rc < 0) { |
| /* The error might be due to async update. In this case |
| * wait for all updates to complete before proceeding. */ |
| rc = mm_camera_poll_thread_commit_updates(&my_obj->ch_obj->poll_thread[0]); |
| if (rc < 0) { |
| LOGE("Poll sync failed %d", |
| rc); |
| } |
| } |
| |
| /* step2: stream off */ |
| rc = ioctl(my_obj->fd, VIDIOC_STREAMOFF, &buf_type); |
| if (rc < 0) { |
| LOGE("STREAMOFF failed: %s\n", |
| strerror(errno)); |
| } |
| LOGD("X rc = %d",rc); |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_stream_write_user_buf |
| * |
| * DESCRIPTION: dequeue a stream buffer from user buffer queue and fill internal structure |
| * |
| * PARAMETERS : |
| * @my_obj : stream object |
| * @buf : ptr to a struct storing buffer information |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_stream_write_user_buf(mm_stream_t * my_obj, |
| mm_camera_buf_def_t *buf) |
| { |
| int32_t rc = 0, i; |
| int32_t index = -1, count = 0; |
| struct msm_camera_user_buf_cont_t *cont_buf = NULL; |
| |
| if (buf->buf_type == CAM_STREAM_BUF_TYPE_USERPTR) { |
| my_obj->buf_status[buf->buf_idx].buf_refcnt--; |
| if (0 == my_obj->buf_status[buf->buf_idx].buf_refcnt) { |
| cont_buf = (struct msm_camera_user_buf_cont_t *)my_obj->buf[buf->buf_idx].buffer; |
| cont_buf->buf_cnt = my_obj->buf[buf->buf_idx].user_buf.bufs_used; |
| for (i = 0; i < (int32_t)cont_buf->buf_cnt; i++) { |
| cont_buf->buf_idx[i] = my_obj->buf[buf->buf_idx].user_buf.buf_idx[i]; |
| } |
| rc = mm_stream_qbuf(my_obj, buf); |
| if(rc < 0) { |
| LOGE("mm_camera_stream_qbuf(idx=%d) err=%d\n", |
| buf->buf_idx, rc); |
| } else { |
| for (i = 0; i < (int32_t)cont_buf->buf_cnt; i++) { |
| my_obj->buf[buf->buf_idx].user_buf.buf_idx[i] = -1; |
| } |
| my_obj->buf_status[buf->buf_idx].in_kernel = 1; |
| my_obj->buf[buf->buf_idx].user_buf.buf_in_use = 1; |
| } |
| } else { |
| LOGD("<DEBUG> : ref count pending count :%d idx = %d", |
| my_obj->buf_status[buf->buf_idx].buf_refcnt, buf->buf_idx); |
| } |
| return rc; |
| } |
| |
| if ((my_obj->cur_buf_idx < 0) |
| || (my_obj->cur_buf_idx >= my_obj->buf_num)) { |
| for (i = 0; i < my_obj->buf_num; i++) { |
| if ((my_obj->buf_status[i].in_kernel) |
| || (my_obj->buf[i].user_buf.buf_in_use)) { |
| continue; |
| } |
| |
| my_obj->cur_buf_idx = index = i; |
| break; |
| } |
| } else { |
| index = my_obj->cur_buf_idx; |
| } |
| |
| if (index == -1) { |
| LOGE("No Free batch buffer"); |
| rc = -1; |
| return rc; |
| } |
| |
| //Insert Buffer to Batch structure. |
| my_obj->buf[index].user_buf.buf_idx[count] = buf->buf_idx; |
| my_obj->cur_bufs_staged++; |
| |
| LOGD("index = %d filled = %d used = %d", |
| index, |
| my_obj->cur_bufs_staged, |
| my_obj->buf[index].user_buf.bufs_used); |
| |
| if (my_obj->cur_bufs_staged |
| == my_obj->buf[index].user_buf.bufs_used){ |
| my_obj->buf_status[index].buf_refcnt--; |
| if (0 == my_obj->buf_status[index].buf_refcnt) { |
| cont_buf = (struct msm_camera_user_buf_cont_t *)my_obj->buf[index].buffer; |
| cont_buf->buf_cnt = my_obj->buf[index].user_buf.bufs_used; |
| for (i = 0; i < (int32_t)cont_buf->buf_cnt; i++) { |
| cont_buf->buf_idx[i] = my_obj->buf[index].user_buf.buf_idx[i]; |
| } |
| rc = mm_stream_qbuf(my_obj, &my_obj->buf[index]); |
| if(rc < 0) { |
| LOGE("mm_camera_stream_qbuf(idx=%d) err=%d\n", |
| index, rc); |
| } else { |
| for (i = 0; i < (int32_t)cont_buf->buf_cnt; i++) { |
| my_obj->buf[index].user_buf.buf_idx[i] = -1; |
| } |
| my_obj->buf_status[index].in_kernel = 1; |
| my_obj->buf[index].user_buf.buf_in_use = 1; |
| my_obj->cur_bufs_staged = 0; |
| my_obj->cur_buf_idx = -1; |
| } |
| }else{ |
| LOGD("<DEBUG> : ref count pending count :%d idx = %d", |
| my_obj->buf_status[index].buf_refcnt, index); |
| } |
| } |
| |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_stream_read_user_buf |
| * |
| * DESCRIPTION: dequeue a stream buffer from user buffer queue and fill internal structure |
| * |
| * PARAMETERS : |
| * @my_obj : stream object |
| * @buf_info : ptr to a struct storing buffer information |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_stream_read_user_buf(mm_stream_t * my_obj, |
| mm_camera_buf_info_t* buf_info) |
| { |
| int32_t rc = 0, i; |
| mm_camera_buf_def_t *stream_buf = NULL; |
| struct msm_camera_user_buf_cont_t *user_buf = NULL; |
| nsecs_t interval_nsec = 0, frame_ts = 0, timeStamp = 0; |
| int ts_delta = 0; |
| uint32_t frameID = 0; |
| |
| user_buf = (struct msm_camera_user_buf_cont_t *)buf_info->buf->buffer; |
| |
| if(user_buf != my_obj->buf[buf_info->buf->buf_idx].buffer) { |
| LOGD("Buffer modified. ERROR"); |
| rc = -1; |
| return rc; |
| } |
| |
| if (buf_info->buf->frame_idx == 1) { |
| frameID = buf_info->buf->frame_idx; |
| }else { |
| frameID = (buf_info->buf->frame_idx - 1) * user_buf->buf_cnt; |
| } |
| |
| timeStamp = (nsecs_t)(buf_info->buf->ts.tv_sec) * |
| 1000000000LL + buf_info->buf->ts.tv_nsec; |
| |
| if (timeStamp <= my_obj->prev_timestamp) { |
| LOGE("TimeStamp received less than expected"); |
| mm_stream_qbuf(my_obj, buf_info->buf); |
| return rc; |
| } else if (my_obj->prev_timestamp == 0 |
| || (my_obj->prev_frameID != buf_info->buf->frame_idx + 1)) { |
| /* For first frame or incase batch is droped */ |
| interval_nsec = ((my_obj->stream_info->user_buf_info.frameInterval) * 1000000); |
| my_obj->prev_timestamp = (timeStamp - (nsecs_t)(user_buf->buf_cnt * interval_nsec)); |
| } else { |
| ts_delta = timeStamp - my_obj->prev_timestamp; |
| interval_nsec = (nsecs_t)(ts_delta / user_buf->buf_cnt); |
| LOGD("Timestamp delta = %d timestamp = %lld", ts_delta, timeStamp); |
| } |
| |
| for (i = 0; i < (int32_t)user_buf->buf_cnt; i++) { |
| buf_info->buf->user_buf.buf_idx[i] = user_buf->buf_idx[i]; |
| stream_buf = &my_obj->plane_buf[user_buf->buf_idx[i]]; |
| stream_buf->frame_idx = frameID + i; |
| |
| frame_ts = (i * interval_nsec) + my_obj->prev_timestamp; |
| |
| stream_buf->ts.tv_sec = (frame_ts / 1000000000LL); |
| stream_buf->ts.tv_nsec = (frame_ts - (stream_buf->ts.tv_sec * 1000000000LL)); |
| stream_buf->is_uv_subsampled = buf_info->buf->is_uv_subsampled; |
| |
| LOGD("buf_index %d, frame_idx %d, stream type %d, timestamp = %lld", |
| stream_buf->buf_idx, stream_buf->frame_idx, |
| my_obj->stream_info->stream_type, frame_ts); |
| } |
| |
| buf_info->buf->ts.tv_sec = (my_obj->prev_timestamp / 1000000000LL); |
| buf_info->buf->ts.tv_nsec = (my_obj->prev_timestamp - |
| (buf_info->buf->ts.tv_sec * 1000000000LL)); |
| |
| buf_info->buf->user_buf.bufs_used = user_buf->buf_cnt; |
| buf_info->buf->user_buf.buf_in_use = 1; |
| |
| my_obj->prev_timestamp = timeStamp; |
| my_obj->prev_frameID = buf_info->buf->frame_idx; |
| |
| LOGD("X rc = %d",rc); |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_stream_read_msm_frame |
| * |
| * DESCRIPTION: dequeue a stream buffer from kernel queue |
| * |
| * PARAMETERS : |
| * @my_obj : stream object |
| * @buf_info : ptr to a struct storing buffer information |
| * @num_planes : number of planes in the buffer |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_stream_read_msm_frame(mm_stream_t * my_obj, |
| mm_camera_buf_info_t* buf_info, |
| uint8_t num_planes) |
| { |
| int32_t rc = 0; |
| struct v4l2_buffer vb; |
| struct v4l2_plane planes[VIDEO_MAX_PLANES]; |
| LOGD("E, my_handle = 0x%x, fd = %d, state = %d", |
| my_obj->my_hdl, my_obj->fd, my_obj->state); |
| |
| memset(&vb, 0, sizeof(vb)); |
| vb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| vb.memory = V4L2_MEMORY_USERPTR; |
| vb.m.planes = &planes[0]; |
| vb.length = num_planes; |
| |
| rc = ioctl(my_obj->fd, VIDIOC_DQBUF, &vb); |
| if (0 > rc) { |
| LOGE("VIDIOC_DQBUF ioctl call failed on stream type %d (rc=%d): %s", |
| my_obj->stream_info->stream_type, rc, strerror(errno)); |
| } else { |
| pthread_mutex_lock(&my_obj->buf_lock); |
| my_obj->queued_buffer_count--; |
| if (0 == my_obj->queued_buffer_count) { |
| LOGH("Stoping poll on stream %p type: %d", |
| my_obj, my_obj->stream_info->stream_type); |
| mm_camera_poll_thread_del_poll_fd(&my_obj->ch_obj->poll_thread[0], |
| my_obj->my_hdl, mm_camera_async_call); |
| LOGH("Stopped poll on stream %p type: %d", |
| my_obj, my_obj->stream_info->stream_type); |
| } |
| uint32_t idx = vb.index; |
| buf_info->buf = &my_obj->buf[idx]; |
| buf_info->frame_idx = vb.sequence; |
| buf_info->stream_id = my_obj->my_hdl; |
| |
| buf_info->buf->stream_id = my_obj->my_hdl; |
| buf_info->buf->buf_idx = idx; |
| buf_info->buf->frame_idx = vb.sequence; |
| buf_info->buf->ts.tv_sec = vb.timestamp.tv_sec; |
| buf_info->buf->ts.tv_nsec = vb.timestamp.tv_usec * 1000; |
| buf_info->buf->flags = vb.flags; |
| |
| LOGH("VIDIOC_DQBUF buf_index %d, frame_idx %d, stream type %d, rc %d," |
| "queued: %d, buf_type = %d flags = %d", |
| vb.index, buf_info->buf->frame_idx, |
| my_obj->stream_info->stream_type, rc, |
| my_obj->queued_buffer_count, buf_info->buf->buf_type, |
| buf_info->buf->flags); |
| |
| buf_info->buf->is_uv_subsampled = |
| (vb.reserved == V4L2_PIX_FMT_NV14 || vb.reserved == V4L2_PIX_FMT_NV41); |
| |
| if(buf_info->buf->buf_type == CAM_STREAM_BUF_TYPE_USERPTR) { |
| mm_stream_read_user_buf(my_obj, buf_info); |
| } |
| pthread_mutex_unlock(&my_obj->buf_lock); |
| |
| if ( NULL != my_obj->mem_vtbl.clean_invalidate_buf ) { |
| rc = my_obj->mem_vtbl.clean_invalidate_buf(idx, |
| my_obj->mem_vtbl.user_data); |
| if (0 > rc) { |
| LOGE("Clean invalidate cache failed on buffer index: %d", |
| idx); |
| } |
| } else { |
| LOGE("Clean invalidate cache op not supported"); |
| } |
| } |
| |
| LOGD("X rc = %d",rc); |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_stream_set_parms |
| * |
| * DESCRIPTION: set parameters per stream |
| * |
| * PARAMETERS : |
| * @my_obj : stream object |
| * @in_value : ptr to a param struct to be set to server |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| * NOTE : Assume the parms struct buf is already mapped to server via |
| * domain socket. Corresponding fields of parameters to be set |
| * are already filled in by upper layer caller. |
| *==========================================================================*/ |
| int32_t mm_stream_set_parm(mm_stream_t *my_obj, |
| cam_stream_parm_buffer_t *in_value) |
| { |
| int32_t rc = -1; |
| int32_t value = 0; |
| if (in_value != NULL) { |
| rc = mm_camera_util_s_ctrl(my_obj->fd, CAM_PRIV_STREAM_PARM, &value); |
| if (rc < 0) { |
| LOGE("Failed to set stream parameter type = %d", in_value->type); |
| } |
| } |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_stream_get_parms |
| * |
| * DESCRIPTION: get parameters per stream |
| * |
| * PARAMETERS : |
| * @my_obj : stream object |
| * @in_value : ptr to a param struct to be get from server |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| * NOTE : Assume the parms struct buf is already mapped to server via |
| * domain socket. Corresponding fields of parameters to be get |
| * are already filled in by upper layer caller. |
| *==========================================================================*/ |
| int32_t mm_stream_get_parm(mm_stream_t *my_obj, |
| cam_stream_parm_buffer_t *in_value) |
| { |
| int32_t rc = -1; |
| int32_t value = 0; |
| if (in_value != NULL) { |
| rc = mm_camera_util_g_ctrl(my_obj->fd, CAM_PRIV_STREAM_PARM, &value); |
| } |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_stream_do_actions |
| * |
| * DESCRIPTION: request server to perform stream based actions |
| * |
| * PARAMETERS : |
| * @my_obj : stream object |
| * @in_value : ptr to a struct of actions to be performed by the server |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| * NOTE : Assume the action struct buf is already mapped to server via |
| * domain socket. Corresponding fields of actions to be performed |
| * are already filled in by upper layer caller. |
| *==========================================================================*/ |
| int32_t mm_stream_do_action(mm_stream_t *my_obj, |
| void *in_value) |
| { |
| int32_t rc = -1; |
| int32_t value = 0; |
| if (in_value != NULL) { |
| rc = mm_camera_util_s_ctrl(my_obj->fd, CAM_PRIV_STREAM_PARM, &value); |
| } |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_stream_set_ext_mode |
| * |
| * DESCRIPTION: set stream extended mode to server via v4l2 ioctl |
| * |
| * PARAMETERS : |
| * @my_obj : stream object |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| * NOTE : Server will return a server stream id that uniquely identify |
| * this stream on server side. Later on communication to server |
| * per stream should use this server stream id. |
| *==========================================================================*/ |
| int32_t mm_stream_set_ext_mode(mm_stream_t * my_obj) |
| { |
| int32_t rc = 0; |
| struct v4l2_streamparm s_parm; |
| LOGD("E, my_handle = 0x%x, fd = %d, state = %d", |
| my_obj->my_hdl, my_obj->fd, my_obj->state); |
| |
| memset(&s_parm, 0, sizeof(s_parm)); |
| s_parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| |
| rc = ioctl(my_obj->fd, VIDIOC_S_PARM, &s_parm); |
| LOGD("stream fd=%d, rc=%d, extended_mode=%d\n", |
| my_obj->fd, rc, s_parm.parm.capture.extendedmode); |
| if (rc == 0) { |
| /* get server stream id */ |
| my_obj->server_stream_id = s_parm.parm.capture.extendedmode; |
| } else { |
| LOGE("VIDIOC_S_PARM failed %d, errno %d", rc, errno); |
| } |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_stream_qbuf |
| * |
| * DESCRIPTION: enqueue buffer back to kernel queue for furture use |
| * |
| * PARAMETERS : |
| * @my_obj : stream object |
| * @buf : ptr to a struct storing buffer information |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_stream_qbuf(mm_stream_t *my_obj, mm_camera_buf_def_t *buf) |
| { |
| int32_t rc = 0; |
| uint32_t length = 0; |
| struct v4l2_buffer buffer; |
| struct v4l2_plane planes[VIDEO_MAX_PLANES]; |
| LOGD("E, my_handle = 0x%x, fd = %d, state = %d, stream type = %d", |
| my_obj->my_hdl, my_obj->fd, my_obj->state, |
| my_obj->stream_info->stream_type); |
| |
| if (buf->buf_type == CAM_STREAM_BUF_TYPE_USERPTR) { |
| LOGD("USERPTR num_buf = %d, idx = %d", |
| buf->user_buf.bufs_used, buf->buf_idx); |
| memset(&planes, 0, sizeof(planes)); |
| planes[0].length = my_obj->stream_info->user_buf_info.size; |
| planes[0].m.userptr = buf->fd; |
| length = 1; |
| } else { |
| memcpy(planes, buf->planes_buf.planes, sizeof(planes)); |
| length = buf->planes_buf.num_planes; |
| } |
| |
| memset(&buffer, 0, sizeof(buffer)); |
| buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| buffer.memory = V4L2_MEMORY_USERPTR; |
| buffer.index = (__u32)buf->buf_idx; |
| buffer.m.planes = &planes[0]; |
| buffer.length = (__u32)length; |
| |
| if ( NULL != my_obj->mem_vtbl.invalidate_buf ) { |
| rc = my_obj->mem_vtbl.invalidate_buf(buffer.index, |
| my_obj->mem_vtbl.user_data); |
| if ( 0 > rc ) { |
| LOGE("Cache invalidate failed on buffer index: %d", |
| buffer.index); |
| return rc; |
| } |
| } else { |
| LOGE("Cache invalidate op not added"); |
| } |
| |
| my_obj->queued_buffer_count++; |
| if (1 == my_obj->queued_buffer_count) { |
| /* Add fd to data poll thread */ |
| LOGH("Starting poll on stream %p type: %d", |
| my_obj,my_obj->stream_info->stream_type); |
| rc = mm_camera_poll_thread_add_poll_fd(&my_obj->ch_obj->poll_thread[0], |
| my_obj->my_hdl, my_obj->fd, mm_stream_data_notify, (void*)my_obj, |
| mm_camera_async_call); |
| if (0 > rc) { |
| LOGE("Add poll on stream %p type: %d fd error (rc=%d)", |
| my_obj, my_obj->stream_info->stream_type, rc); |
| } else { |
| LOGH("Started poll on stream %p type: %d", |
| my_obj, my_obj->stream_info->stream_type); |
| } |
| } |
| |
| rc = ioctl(my_obj->fd, VIDIOC_QBUF, &buffer); |
| if (0 > rc) { |
| LOGE("VIDIOC_QBUF ioctl call failed on stream type %d (rc=%d): %s", |
| my_obj->stream_info->stream_type, rc, strerror(errno)); |
| my_obj->queued_buffer_count--; |
| if (0 == my_obj->queued_buffer_count) { |
| /* Remove fd from data poll in case of failing |
| * first buffer queuing attempt */ |
| LOGH("Stoping poll on stream %p type: %d", |
| my_obj, my_obj->stream_info->stream_type); |
| mm_camera_poll_thread_del_poll_fd(&my_obj->ch_obj->poll_thread[0], |
| my_obj->my_hdl, mm_camera_async_call); |
| LOGH("Stopped poll on stream %p type: %d", |
| my_obj, my_obj->stream_info->stream_type); |
| } |
| } else { |
| LOGH("VIDIOC_QBUF buf_index %d, frame_idx %d stream type %d, rc %d," |
| " queued: %d, buf_type = %d", |
| buffer.index, buf->frame_idx, my_obj->stream_info->stream_type, rc, |
| my_obj->queued_buffer_count, buf->buf_type); |
| } |
| |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_stream_request_buf |
| * |
| * DESCRIPTION: This function let kernel know the amount of buffers need to |
| * be registered via v4l2 ioctl. |
| * |
| * PARAMETERS : |
| * @my_obj : stream object |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_stream_request_buf(mm_stream_t * my_obj) |
| { |
| int32_t rc = 0; |
| struct v4l2_requestbuffers bufreq; |
| uint8_t buf_num = my_obj->buf_num; |
| LOGD("E, my_handle = 0x%x, fd = %d, state = %d", |
| my_obj->my_hdl, my_obj->fd, my_obj->state); |
| |
| LOGD("buf_num = %d, stream type = %d", |
| buf_num, my_obj->stream_info->stream_type); |
| |
| if(buf_num > MM_CAMERA_MAX_NUM_FRAMES) { |
| LOGE("buf num %d > max limit %d\n", |
| buf_num, MM_CAMERA_MAX_NUM_FRAMES); |
| return -1; |
| } |
| |
| memset(&bufreq, 0, sizeof(bufreq)); |
| bufreq.count = buf_num; |
| bufreq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| bufreq.memory = V4L2_MEMORY_USERPTR; |
| rc = ioctl(my_obj->fd, VIDIOC_REQBUFS, &bufreq); |
| if (rc < 0) { |
| LOGE("fd=%d, ioctl VIDIOC_REQBUFS failed: rc=%d, errno %d", |
| my_obj->fd, rc, errno); |
| } |
| |
| LOGD("X rc = %d",rc); |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_stream_need_wait_for_mapping |
| * |
| * DESCRIPTION: Utility function to determine whether to wait for mapping |
| * |
| * PARAMETERS : |
| * @my_obj : stream object |
| * |
| * RETURN : int8_t whether wait is necessary |
| * 0 -- no wait |
| * 1 -- wait |
| *==========================================================================*/ |
| int8_t mm_stream_need_wait_for_mapping(mm_stream_t * my_obj) |
| { |
| uint32_t i; |
| int8_t ret = 0; |
| |
| for (i = 0; i < my_obj->buf_num; i++) { |
| if ((my_obj->buf_status[i].map_status == 0) |
| && (my_obj->buf_status[i].in_kernel)) { |
| /*do not signal in case if any buffer is not mapped |
| but queued to kernel.*/ |
| ret = 1; |
| } else if (my_obj->buf_status[i].map_status < 0) { |
| return 0; |
| } |
| } |
| |
| return ret; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_stream_map_buf |
| * |
| * DESCRIPTION: mapping stream buffer via domain socket to server |
| * |
| * PARAMETERS : |
| * @my_obj : stream object |
| * @buf_type : type of buffer to be mapped. could be following values: |
| * CAM_MAPPING_BUF_TYPE_STREAM_BUF |
| * CAM_MAPPING_BUF_TYPE_STREAM_INFO |
| * CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF |
| * @frame_idx : index of buffer within the stream buffers, only valid if |
| * buf_type is CAM_MAPPING_BUF_TYPE_STREAM_BUF or |
| * CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF |
| * @plane_idx : plane index. If all planes share the same fd, |
| * plane_idx = -1; otherwise, plean_idx is the |
| * index to plane (0..num_of_planes) |
| * @fd : file descriptor of the buffer |
| * @size : size of the buffer |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_stream_map_buf(mm_stream_t * my_obj, |
| uint8_t buf_type, |
| uint32_t frame_idx, |
| int32_t plane_idx, |
| int32_t fd, |
| size_t size) |
| { |
| int32_t rc = 0; |
| if (NULL == my_obj || NULL == my_obj->ch_obj || NULL == my_obj->ch_obj->cam_obj) { |
| LOGE("NULL obj of stream/channel/camera"); |
| return -1; |
| } |
| |
| cam_sock_packet_t packet; |
| memset(&packet, 0, sizeof(cam_sock_packet_t)); |
| packet.msg_type = CAM_MAPPING_TYPE_FD_MAPPING; |
| packet.payload.buf_map.type = buf_type; |
| packet.payload.buf_map.fd = fd; |
| packet.payload.buf_map.size = size; |
| packet.payload.buf_map.stream_id = my_obj->server_stream_id; |
| packet.payload.buf_map.frame_idx = frame_idx; |
| packet.payload.buf_map.plane_idx = plane_idx; |
| LOGD("mapping buf_type %d, stream_id %d, frame_idx %d, fd %d, size %d", |
| buf_type, my_obj->server_stream_id, frame_idx, fd, size); |
| rc = mm_camera_util_sendmsg(my_obj->ch_obj->cam_obj, |
| &packet, sizeof(cam_sock_packet_t), fd); |
| |
| if ((buf_type == CAM_MAPPING_BUF_TYPE_STREAM_BUF) |
| || ((buf_type |
| == CAM_MAPPING_BUF_TYPE_STREAM_USER_BUF) |
| && (my_obj->stream_info != NULL) |
| && (my_obj->stream_info->streaming_mode |
| == CAM_STREAMING_MODE_BATCH))) { |
| pthread_mutex_lock(&my_obj->buf_lock); |
| if (rc < 0) { |
| my_obj->buf_status[frame_idx].map_status = -1; |
| } else { |
| my_obj->buf_status[frame_idx].map_status = 1; |
| } |
| if (mm_stream_need_wait_for_mapping(my_obj) == 0) { |
| LOGD("Buffer mapping Done: Signal strm fd = %d", |
| my_obj->fd); |
| pthread_cond_signal(&my_obj->buf_cond); |
| } |
| pthread_mutex_unlock(&my_obj->buf_lock); |
| } |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_stream_map_bufs |
| * |
| * DESCRIPTION: mapping stream buffers via domain socket to server |
| * |
| * PARAMETERS : |
| * @my_obj : stream object |
| * @buf_map_list : list of buffer objects to map |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| |
| int32_t mm_stream_map_bufs(mm_stream_t * my_obj, |
| const cam_buf_map_type_list *buf_map_list) |
| { |
| if (NULL == my_obj || NULL == my_obj->ch_obj || NULL == my_obj->ch_obj->cam_obj) { |
| LOGE("NULL obj of stream/channel/camera"); |
| return -1; |
| } |
| |
| cam_sock_packet_t packet; |
| memset(&packet, 0, sizeof(cam_sock_packet_t)); |
| packet.msg_type = CAM_MAPPING_TYPE_FD_BUNDLED_MAPPING; |
| |
| memcpy(&packet.payload.buf_map_list, buf_map_list, |
| sizeof(packet.payload.buf_map_list)); |
| |
| int sendfds[CAM_MAX_NUM_BUFS_PER_STREAM]; |
| uint32_t numbufs = packet.payload.buf_map_list.length; |
| if (numbufs < 1) { |
| LOGD("No buffers, suppressing the mapping command"); |
| return 0; |
| } |
| |
| uint32_t i; |
| for (i = 0; i < numbufs; i++) { |
| packet.payload.buf_map_list.buf_maps[i].stream_id = my_obj->server_stream_id; |
| sendfds[i] = packet.payload.buf_map_list.buf_maps[i].fd; |
| } |
| |
| for (i = numbufs; i < CAM_MAX_NUM_BUFS_PER_STREAM; i++) { |
| packet.payload.buf_map_list.buf_maps[i].fd = -1; |
| sendfds[i] = -1; |
| } |
| |
| int32_t ret = mm_camera_util_bundled_sendmsg(my_obj->ch_obj->cam_obj, |
| &packet, sizeof(cam_sock_packet_t), sendfds, numbufs); |
| if ((numbufs > 0) && ((buf_map_list->buf_maps[0].type |
| == CAM_MAPPING_BUF_TYPE_STREAM_BUF) |
| || ((buf_map_list->buf_maps[0].type == |
| CAM_MAPPING_BUF_TYPE_STREAM_USER_BUF) |
| && (my_obj->stream_info != NULL) |
| && (my_obj->stream_info->streaming_mode |
| == CAM_STREAMING_MODE_BATCH)))) { |
| pthread_mutex_lock(&my_obj->buf_lock); |
| for (i = 0; i < numbufs; i++) { |
| if (ret < 0) { |
| my_obj->buf_status[i].map_status = -1; |
| } else { |
| my_obj->buf_status[i].map_status = 1; |
| } |
| } |
| |
| if (mm_stream_need_wait_for_mapping(my_obj) == 0) { |
| LOGD("Buffer mapping Done: Signal strm fd = %d", |
| my_obj->fd); |
| pthread_cond_signal(&my_obj->buf_cond); |
| } |
| pthread_mutex_unlock(&my_obj->buf_lock); |
| } |
| return ret; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_stream_unmap_buf |
| * |
| * DESCRIPTION: unmapping stream buffer via domain socket to server |
| * |
| * PARAMETERS : |
| * @my_obj : stream object |
| * @buf_type : type of buffer to be unmapped. could be following values: |
| * CAM_MAPPING_BUF_TYPE_STREAM_BUF |
| * CAM_MAPPING_BUF_TYPE_STREAM_INFO |
| * CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF |
| * @frame_idx : index of buffer within the stream buffers, only valid if |
| * buf_type is CAM_MAPPING_BUF_TYPE_STREAM_BUF or |
| * CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF |
| * @plane_idx : plane index. If all planes share the same fd, |
| * plane_idx = -1; otherwise, plean_idx is the |
| * index to plane (0..num_of_planes) |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_stream_unmap_buf(mm_stream_t * my_obj, |
| uint8_t buf_type, |
| uint32_t frame_idx, |
| int32_t plane_idx) |
| { |
| if (NULL == my_obj || NULL == my_obj->ch_obj || NULL == my_obj->ch_obj->cam_obj) { |
| LOGE("NULL obj of stream/channel/camera"); |
| return -1; |
| } |
| cam_sock_packet_t packet; |
| memset(&packet, 0, sizeof(cam_sock_packet_t)); |
| packet.msg_type = CAM_MAPPING_TYPE_FD_UNMAPPING; |
| packet.payload.buf_unmap.type = buf_type; |
| packet.payload.buf_unmap.stream_id = my_obj->server_stream_id; |
| packet.payload.buf_unmap.frame_idx = frame_idx; |
| packet.payload.buf_unmap.plane_idx = plane_idx; |
| int32_t ret = mm_camera_util_sendmsg(my_obj->ch_obj->cam_obj, |
| &packet, |
| sizeof(cam_sock_packet_t), |
| -1); |
| pthread_mutex_lock(&my_obj->buf_lock); |
| my_obj->buf_status[frame_idx].map_status = 0; |
| pthread_mutex_unlock(&my_obj->buf_lock); |
| return ret; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_stream_init_bufs |
| * |
| * DESCRIPTION: initialize stream buffers needed. This function will request |
| * buffers needed from upper layer through the mem ops table passed |
| * during configuration stage. |
| * |
| * PARAMETERS : |
| * @my_obj : stream object |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_stream_init_bufs(mm_stream_t * my_obj) |
| { |
| int32_t i, rc = 0; |
| uint8_t *reg_flags = NULL; |
| LOGD("E, my_handle = 0x%x, fd = %d, state = %d", |
| my_obj->my_hdl, my_obj->fd, my_obj->state); |
| |
| /* deinit buf if it's not NULL*/ |
| if (NULL != my_obj->buf) { |
| mm_stream_deinit_bufs(my_obj); |
| } |
| |
| rc = my_obj->mem_vtbl.get_bufs(&my_obj->frame_offset, |
| &my_obj->buf_num, |
| ®_flags, |
| &my_obj->buf, |
| &my_obj->map_ops, |
| my_obj->mem_vtbl.user_data); |
| |
| if (0 != rc) { |
| LOGE("Error get buf, rc = %d\n", rc); |
| return rc; |
| } |
| |
| for (i = 0; i < my_obj->buf_num; i++) { |
| my_obj->buf_status[i].initial_reg_flag = reg_flags[i]; |
| my_obj->buf[i].stream_id = my_obj->my_hdl; |
| my_obj->buf[i].stream_type = my_obj->stream_info->stream_type; |
| |
| if (my_obj->buf[i].buf_type == CAM_STREAM_BUF_TYPE_USERPTR) { |
| my_obj->buf[i].user_buf.bufs_used = |
| (int8_t)my_obj->stream_info->user_buf_info.frame_buf_cnt; |
| my_obj->buf[i].user_buf.buf_in_use = reg_flags[i]; |
| } |
| } |
| |
| if (my_obj->stream_info->streaming_mode == CAM_STREAMING_MODE_BATCH) { |
| my_obj->plane_buf = my_obj->buf[0].user_buf.plane_buf; |
| if (my_obj->plane_buf != NULL) { |
| my_obj->plane_buf_num = |
| my_obj->buf_num * |
| my_obj->stream_info->user_buf_info.frame_buf_cnt; |
| for (i = 0; i < my_obj->plane_buf_num; i++) { |
| my_obj->plane_buf[i].stream_id = my_obj->my_hdl; |
| my_obj->plane_buf[i].stream_type = my_obj->stream_info->stream_type; |
| } |
| } |
| my_obj->cur_bufs_staged = 0; |
| my_obj->cur_buf_idx = -1; |
| } |
| |
| free(reg_flags); |
| reg_flags = NULL; |
| |
| /* update in stream info about number of stream buffers */ |
| my_obj->stream_info->num_bufs = my_obj->buf_num; |
| |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_stream_deinit_bufs |
| * |
| * DESCRIPTION: return stream buffers to upper layer through the mem ops table |
| * passed during configuration stage. |
| * |
| * PARAMETERS : |
| * @my_obj : stream object |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_stream_deinit_bufs(mm_stream_t * my_obj) |
| { |
| int32_t rc = 0; |
| |
| mm_camera_map_unmap_ops_tbl_t ops_tbl; |
| LOGD("E, my_handle = 0x%x, fd = %d, state = %d", |
| my_obj->my_hdl, my_obj->fd, my_obj->state); |
| |
| if (NULL == my_obj->buf) { |
| LOGD("Buf is NULL, no need to deinit"); |
| return rc; |
| } |
| |
| /* release bufs */ |
| ops_tbl.map_ops = mm_stream_map_buf_ops; |
| ops_tbl.bundled_map_ops = mm_stream_bundled_map_buf_ops; |
| ops_tbl.unmap_ops = mm_stream_unmap_buf_ops; |
| ops_tbl.userdata = my_obj; |
| |
| rc = my_obj->mem_vtbl.put_bufs(&ops_tbl, |
| my_obj->mem_vtbl.user_data); |
| |
| if (my_obj->plane_buf != NULL) { |
| free(my_obj->plane_buf); |
| my_obj->plane_buf = NULL; |
| } |
| |
| free(my_obj->buf); |
| my_obj->buf = NULL; |
| |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_stream_reg_buf |
| * |
| * DESCRIPTION: register buffers with kernel by calling v4l2 ioctl QBUF for |
| * each buffer in the stream |
| * |
| * PARAMETERS : |
| * @my_obj : stream object |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_stream_reg_buf(mm_stream_t * my_obj) |
| { |
| int32_t rc = 0; |
| uint8_t i; |
| LOGD("E, my_handle = 0x%x, fd = %d, state = %d", |
| my_obj->my_hdl, my_obj->fd, my_obj->state); |
| |
| rc = mm_stream_request_buf(my_obj); |
| if (rc != 0) { |
| return rc; |
| } |
| |
| pthread_mutex_lock(&my_obj->buf_lock); |
| my_obj->queued_buffer_count = 0; |
| for(i = 0; i < my_obj->buf_num; i++){ |
| /* check if need to qbuf initially */ |
| if (my_obj->buf_status[i].initial_reg_flag) { |
| rc = mm_stream_qbuf(my_obj, &my_obj->buf[i]); |
| if (rc != 0) { |
| LOGE("VIDIOC_QBUF rc = %d\n", rc); |
| break; |
| } |
| my_obj->buf_status[i].buf_refcnt = 0; |
| my_obj->buf_status[i].in_kernel = 1; |
| } else { |
| /* the buf is held by upper layer, will not queue into kernel. |
| * add buf reference count */ |
| my_obj->buf_status[i].buf_refcnt = 1; |
| my_obj->buf_status[i].in_kernel = 0; |
| } |
| } |
| pthread_mutex_unlock(&my_obj->buf_lock); |
| |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_stream_unreg buf |
| * |
| * DESCRIPTION: unregister all stream buffers from kernel |
| * |
| * PARAMETERS : |
| * @my_obj : stream object |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_stream_unreg_buf(mm_stream_t * my_obj) |
| { |
| struct v4l2_requestbuffers bufreq; |
| int32_t i, rc = 0; |
| LOGD("E, my_handle = 0x%x, fd = %d, state = %d", |
| my_obj->my_hdl, my_obj->fd, my_obj->state); |
| |
| /* unreg buf to kernel */ |
| bufreq.count = 0; |
| bufreq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| bufreq.memory = V4L2_MEMORY_USERPTR; |
| rc = ioctl(my_obj->fd, VIDIOC_REQBUFS, &bufreq); |
| if (rc < 0) { |
| LOGE("fd=%d, VIDIOC_REQBUFS failed, rc=%d, errno %d", |
| my_obj->fd, rc, errno); |
| } |
| |
| /* reset buf reference count */ |
| pthread_mutex_lock(&my_obj->buf_lock); |
| for(i = 0; i < my_obj->buf_num; i++){ |
| my_obj->buf_status[i].buf_refcnt = 0; |
| my_obj->buf_status[i].in_kernel = 0; |
| } |
| pthread_mutex_unlock(&my_obj->buf_lock); |
| |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_stream_get_v4l2_fmt |
| * |
| * DESCRIPTION: translate camera image format into FOURCC code |
| * |
| * PARAMETERS : |
| * @fmt : camera image format |
| * |
| * RETURN : FOURCC code for image format |
| *==========================================================================*/ |
| uint32_t mm_stream_get_v4l2_fmt(cam_format_t fmt) |
| { |
| uint32_t val = 0; |
| switch(fmt) { |
| case CAM_FORMAT_YUV_420_NV12: |
| case CAM_FORMAT_YUV_420_NV12_VENUS: |
| case CAM_FORMAT_YUV_420_NV12_UBWC: |
| val = V4L2_PIX_FMT_NV12; |
| break; |
| case CAM_FORMAT_YUV_420_NV21: |
| case CAM_FORMAT_YUV_420_NV21_VENUS: |
| val = V4L2_PIX_FMT_NV21; |
| break; |
| case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_GBRG: |
| val= V4L2_PIX_FMT_SGBRG10; |
| break; |
| case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_GRBG: |
| val= V4L2_PIX_FMT_SGRBG10; |
| break; |
| case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_RGGB: |
| val= V4L2_PIX_FMT_SRGGB10; |
| break; |
| case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_BGGR: |
| val= V4L2_PIX_FMT_SBGGR10; |
| break; |
| case CAM_FORMAT_BAYER_QCOM_RAW_12BPP_GBRG: |
| val= V4L2_PIX_FMT_SGBRG12; |
| break; |
| case CAM_FORMAT_BAYER_QCOM_RAW_12BPP_GRBG: |
| val= V4L2_PIX_FMT_SGRBG12; |
| break; |
| case CAM_FORMAT_BAYER_QCOM_RAW_12BPP_RGGB: |
| val= V4L2_PIX_FMT_SRGGB12; |
| break; |
| case CAM_FORMAT_BAYER_QCOM_RAW_12BPP_BGGR: |
| val = V4L2_PIX_FMT_SBGGR12; |
| break; |
| case CAM_FORMAT_BAYER_QCOM_RAW_14BPP_GBRG: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_14BPP_GBRG: |
| val= V4L2_PIX_FMT_SGBRG14; |
| break; |
| case CAM_FORMAT_BAYER_QCOM_RAW_14BPP_GRBG: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_14BPP_GRBG: |
| val= V4L2_PIX_FMT_SGRBG14; |
| break; |
| case CAM_FORMAT_BAYER_QCOM_RAW_14BPP_RGGB: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_14BPP_RGGB: |
| val= V4L2_PIX_FMT_SRGGB14; |
| break; |
| case CAM_FORMAT_BAYER_QCOM_RAW_14BPP_BGGR: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_14BPP_BGGR: |
| val = V4L2_PIX_FMT_SBGGR14; |
| break; |
| case CAM_FORMAT_YUV_422_NV61: |
| val= V4L2_PIX_FMT_NV61; |
| break; |
| case CAM_FORMAT_YUV_RAW_8BIT_YUYV: |
| val= V4L2_PIX_FMT_YUYV; |
| break; |
| case CAM_FORMAT_YUV_RAW_8BIT_YVYU: |
| val= V4L2_PIX_FMT_YVYU; |
| break; |
| case CAM_FORMAT_YUV_RAW_8BIT_UYVY: |
| val= V4L2_PIX_FMT_UYVY; |
| break; |
| case CAM_FORMAT_YUV_RAW_8BIT_VYUY: |
| val= V4L2_PIX_FMT_VYUY; |
| break; |
| case CAM_FORMAT_YUV_420_YV12: |
| val= V4L2_PIX_FMT_NV12; |
| break; |
| case CAM_FORMAT_YUV_422_NV16: |
| val= V4L2_PIX_FMT_NV16; |
| break; |
| case CAM_FORMAT_Y_ONLY: |
| val= V4L2_PIX_FMT_GREY; |
| break; |
| case CAM_FORMAT_MAX: |
| /* CAM_STREAM_TYPE_DEFAULT, |
| * CAM_STREAM_TYPE_OFFLINE_PROC, |
| * and CAM_STREAM_TYPE_METADATA |
| * set fmt to CAM_FORMAT_MAX*/ |
| val = 0; |
| break; |
| default: |
| val = 0; |
| LOGE("Unknown fmt=%d", fmt); |
| break; |
| } |
| LOGD("fmt=%d, val =%d", fmt, val); |
| return val; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_stream_calc_offset_preview |
| * |
| * DESCRIPTION: calculate preview frame offset based on format and |
| * padding information |
| * |
| * PARAMETERS : |
| * @fmt : image format |
| * @dim : image dimension |
| * @buf_planes : [out] buffer plane information |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_stream_calc_offset_preview(cam_stream_info_t *stream_info, |
| cam_dimension_t *dim, |
| cam_padding_info_t *padding, |
| cam_stream_buf_plane_info_t *buf_planes) |
| { |
| int32_t rc = 0; |
| int stride = 0, scanline = 0; |
| |
| uint32_t width_padding = 0; |
| uint32_t height_padding = 0; |
| |
| switch (stream_info->fmt) { |
| case CAM_FORMAT_YUV_420_NV12: |
| case CAM_FORMAT_YUV_420_NV21: |
| /* 2 planes: Y + CbCr */ |
| buf_planes->plane_info.num_planes = 2; |
| |
| if (stream_info->stream_type != CAM_STREAM_TYPE_OFFLINE_PROC) { |
| width_padding = padding->width_padding; |
| height_padding = CAM_PAD_TO_2; |
| } else { |
| width_padding = padding->width_padding; |
| height_padding = padding->height_padding; |
| } |
| |
| stride = PAD_TO_SIZE(dim->width, width_padding); |
| scanline = PAD_TO_SIZE(dim->height, height_padding); |
| |
| buf_planes->plane_info.mp[0].offset = 0; |
| buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline); |
| buf_planes->plane_info.mp[0].offset_x = 0; |
| buf_planes->plane_info.mp[0].offset_y = 0; |
| buf_planes->plane_info.mp[0].stride = stride; |
| buf_planes->plane_info.mp[0].scanline = scanline; |
| buf_planes->plane_info.mp[0].width = dim->width; |
| buf_planes->plane_info.mp[0].height = dim->height; |
| |
| stride = PAD_TO_SIZE(dim->width, width_padding); |
| scanline = PAD_TO_SIZE(dim->height / 2, height_padding); |
| buf_planes->plane_info.mp[1].offset = 0; |
| buf_planes->plane_info.mp[1].len = |
| (uint32_t)(stride * scanline); |
| buf_planes->plane_info.mp[1].offset_x = 0; |
| buf_planes->plane_info.mp[1].offset_y = 0; |
| buf_planes->plane_info.mp[1].stride = stride; |
| buf_planes->plane_info.mp[1].scanline = scanline; |
| buf_planes->plane_info.mp[1].width = dim->width; |
| buf_planes->plane_info.mp[1].height = dim->height / 2; |
| |
| buf_planes->plane_info.frame_len = |
| PAD_TO_SIZE(buf_planes->plane_info.mp[0].len + |
| buf_planes->plane_info.mp[1].len, |
| CAM_PAD_TO_4K); |
| break; |
| case CAM_FORMAT_YUV_420_NV21_ADRENO: |
| /* 2 planes: Y + CbCr */ |
| buf_planes->plane_info.num_planes = 2; |
| |
| if (stream_info->stream_type != CAM_STREAM_TYPE_OFFLINE_PROC) { |
| stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_32); |
| scanline = PAD_TO_SIZE(dim->height, CAM_PAD_TO_32); |
| } else { |
| stride = PAD_TO_SIZE(dim->width, padding->width_padding); |
| scanline = PAD_TO_SIZE(dim->height, padding->height_padding); |
| } |
| buf_planes->plane_info.mp[0].offset = 0; |
| buf_planes->plane_info.mp[0].len = |
| PAD_TO_SIZE((uint32_t)(stride * scanline), CAM_PAD_TO_4K); |
| buf_planes->plane_info.mp[0].offset_x = 0; |
| buf_planes->plane_info.mp[0].offset_y = 0; |
| buf_planes->plane_info.mp[0].stride = stride; |
| buf_planes->plane_info.mp[0].scanline = scanline; |
| buf_planes->plane_info.mp[0].width = dim->width; |
| buf_planes->plane_info.mp[0].height = dim->height; |
| |
| stride = PAD_TO_SIZE(dim->width / 2, CAM_PAD_TO_32) * 2; |
| scanline = PAD_TO_SIZE(dim->height / 2, CAM_PAD_TO_32); |
| buf_planes->plane_info.mp[1].offset = 0; |
| buf_planes->plane_info.mp[1].len = |
| PAD_TO_SIZE((uint32_t)(stride * scanline), CAM_PAD_TO_4K); |
| buf_planes->plane_info.mp[1].offset_x = 0; |
| buf_planes->plane_info.mp[1].offset_y = 0; |
| buf_planes->plane_info.mp[1].stride = stride; |
| buf_planes->plane_info.mp[1].scanline = scanline; |
| buf_planes->plane_info.mp[1].width = dim->width; |
| buf_planes->plane_info.mp[1].height = dim->height / 2; |
| |
| buf_planes->plane_info.frame_len = |
| PAD_TO_SIZE(buf_planes->plane_info.mp[0].len + |
| buf_planes->plane_info.mp[1].len, |
| CAM_PAD_TO_4K); |
| break; |
| case CAM_FORMAT_YUV_420_YV12: |
| /* 3 planes: Y + Cr + Cb */ |
| buf_planes->plane_info.num_planes = 3; |
| |
| if (stream_info->stream_type != CAM_STREAM_TYPE_OFFLINE_PROC) { |
| stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16); |
| scanline = PAD_TO_SIZE(dim->height, CAM_PAD_TO_2); |
| } else { |
| stride = PAD_TO_SIZE(dim->width, padding->width_padding); |
| scanline = PAD_TO_SIZE(dim->height, padding->height_padding); |
| } |
| buf_planes->plane_info.mp[0].offset = 0; |
| buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline); |
| buf_planes->plane_info.mp[0].offset_x = 0; |
| buf_planes->plane_info.mp[0].offset_y = 0; |
| buf_planes->plane_info.mp[0].stride = stride; |
| buf_planes->plane_info.mp[0].scanline = scanline; |
| buf_planes->plane_info.mp[0].width = dim->width; |
| buf_planes->plane_info.mp[0].height = dim->height; |
| |
| stride = PAD_TO_SIZE(stride / 2, CAM_PAD_TO_16); |
| scanline = scanline / 2; |
| buf_planes->plane_info.mp[1].offset = 0; |
| buf_planes->plane_info.mp[1].len = |
| (uint32_t)(stride * scanline); |
| buf_planes->plane_info.mp[1].offset_x = 0; |
| buf_planes->plane_info.mp[1].offset_y = 0; |
| buf_planes->plane_info.mp[1].stride = stride; |
| buf_planes->plane_info.mp[1].scanline = scanline; |
| buf_planes->plane_info.mp[1].width = dim->width / 2; |
| buf_planes->plane_info.mp[1].height = dim->height / 2; |
| |
| buf_planes->plane_info.mp[2].offset = 0; |
| buf_planes->plane_info.mp[2].len = |
| (uint32_t)(stride * scanline); |
| buf_planes->plane_info.mp[2].offset_x = 0; |
| buf_planes->plane_info.mp[2].offset_y = 0; |
| buf_planes->plane_info.mp[2].stride = stride; |
| buf_planes->plane_info.mp[2].scanline = scanline; |
| buf_planes->plane_info.mp[2].width = dim->width / 2; |
| buf_planes->plane_info.mp[2].height = dim->height / 2; |
| |
| buf_planes->plane_info.frame_len = |
| PAD_TO_SIZE(buf_planes->plane_info.mp[0].len + |
| buf_planes->plane_info.mp[1].len + |
| buf_planes->plane_info.mp[2].len, |
| CAM_PAD_TO_4K); |
| break; |
| case CAM_FORMAT_YUV_422_NV16: |
| case CAM_FORMAT_YUV_422_NV61: |
| /* 2 planes: Y + CbCr */ |
| buf_planes->plane_info.num_planes = 2; |
| |
| if (stream_info->stream_type != CAM_STREAM_TYPE_OFFLINE_PROC) { |
| stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16); |
| scanline = dim->height; |
| } else { |
| stride = PAD_TO_SIZE(dim->width, padding->width_padding); |
| scanline = PAD_TO_SIZE(dim->height, padding->height_padding); |
| } |
| buf_planes->plane_info.mp[0].offset = 0; |
| buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline); |
| buf_planes->plane_info.mp[0].offset_x = 0; |
| buf_planes->plane_info.mp[0].offset_y = 0; |
| buf_planes->plane_info.mp[0].stride = stride; |
| buf_planes->plane_info.mp[0].scanline = scanline; |
| buf_planes->plane_info.mp[0].width = dim->width; |
| buf_planes->plane_info.mp[0].height = dim->height; |
| |
| buf_planes->plane_info.mp[1].offset = 0; |
| buf_planes->plane_info.mp[1].len = (uint32_t)(stride * scanline); |
| buf_planes->plane_info.mp[1].offset_x = 0; |
| buf_planes->plane_info.mp[1].offset_y = 0; |
| buf_planes->plane_info.mp[1].stride = stride; |
| buf_planes->plane_info.mp[1].scanline = scanline; |
| buf_planes->plane_info.mp[1].width = dim->width; |
| buf_planes->plane_info.mp[1].height = dim->height; |
| |
| buf_planes->plane_info.frame_len = |
| PAD_TO_SIZE(buf_planes->plane_info.mp[0].len + |
| buf_planes->plane_info.mp[1].len, |
| CAM_PAD_TO_4K); |
| break; |
| case CAM_FORMAT_YUV_420_NV12_VENUS: |
| #ifdef VENUS_PRESENT |
| // using Venus |
| if (stream_info->stream_type != CAM_STREAM_TYPE_OFFLINE_PROC) { |
| stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, dim->width); |
| scanline = VENUS_Y_SCANLINES(COLOR_FMT_NV12, dim->height); |
| } else { |
| stride = PAD_TO_SIZE(dim->width, padding->width_padding); |
| scanline = PAD_TO_SIZE(dim->height, padding->height_padding); |
| } |
| buf_planes->plane_info.frame_len = |
| VENUS_BUFFER_SIZE(COLOR_FMT_NV12, stride, scanline); |
| buf_planes->plane_info.num_planes = 2; |
| buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline); |
| buf_planes->plane_info.mp[0].offset = 0; |
| buf_planes->plane_info.mp[0].offset_x =0; |
| buf_planes->plane_info.mp[0].offset_y = 0; |
| buf_planes->plane_info.mp[0].stride = stride; |
| buf_planes->plane_info.mp[0].scanline = scanline; |
| buf_planes->plane_info.mp[0].width = dim->width; |
| buf_planes->plane_info.mp[0].height = dim->height; |
| if (stream_info->stream_type != CAM_STREAM_TYPE_OFFLINE_PROC) { |
| stride = VENUS_UV_STRIDE(COLOR_FMT_NV12, dim->width); |
| scanline = VENUS_UV_SCANLINES(COLOR_FMT_NV12, dim->height); |
| } else { |
| stride = PAD_TO_SIZE(dim->width, padding->width_padding); |
| scanline = PAD_TO_SIZE(dim->height, padding->height_padding); |
| } |
| buf_planes->plane_info.mp[1].len = |
| buf_planes->plane_info.frame_len - buf_planes->plane_info.mp[0].len; |
| buf_planes->plane_info.mp[1].offset = 0; |
| buf_planes->plane_info.mp[1].offset_x =0; |
| buf_planes->plane_info.mp[1].offset_y = 0; |
| buf_planes->plane_info.mp[1].stride = stride; |
| buf_planes->plane_info.mp[1].scanline = scanline; |
| buf_planes->plane_info.mp[1].width = dim->width; |
| buf_planes->plane_info.mp[1].height = dim->height / 2; |
| #else |
| LOGE("Venus hardware not avail, cannot use this format"); |
| rc = -1; |
| #endif |
| break; |
| case CAM_FORMAT_YUV_420_NV21_VENUS: |
| #ifdef VENUS_PRESENT |
| // using Venus |
| if (stream_info->stream_type != CAM_STREAM_TYPE_OFFLINE_PROC) { |
| stride = VENUS_Y_STRIDE(COLOR_FMT_NV21, dim->width); |
| scanline = VENUS_Y_SCANLINES(COLOR_FMT_NV21, dim->height); |
| } else { |
| stride = PAD_TO_SIZE(dim->width, padding->width_padding); |
| scanline = PAD_TO_SIZE(dim->height, padding->height_padding); |
| } |
| buf_planes->plane_info.frame_len = |
| VENUS_BUFFER_SIZE(COLOR_FMT_NV21, stride, scanline); |
| buf_planes->plane_info.num_planes = 2; |
| buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline); |
| buf_planes->plane_info.mp[0].offset = 0; |
| buf_planes->plane_info.mp[0].offset_x =0; |
| buf_planes->plane_info.mp[0].offset_y = 0; |
| buf_planes->plane_info.mp[0].stride = stride; |
| buf_planes->plane_info.mp[0].scanline = scanline; |
| buf_planes->plane_info.mp[0].width = dim->width; |
| buf_planes->plane_info.mp[0].height = dim->height; |
| if (stream_info->stream_type != CAM_STREAM_TYPE_OFFLINE_PROC) { |
| stride = VENUS_UV_STRIDE(COLOR_FMT_NV21, dim->width); |
| scanline = VENUS_UV_SCANLINES(COLOR_FMT_NV21, dim->height); |
| } else { |
| stride = PAD_TO_SIZE(dim->width, padding->width_padding); |
| scanline = PAD_TO_SIZE(dim->height, padding->height_padding); |
| } |
| buf_planes->plane_info.mp[1].len = |
| buf_planes->plane_info.frame_len - buf_planes->plane_info.mp[0].len; |
| buf_planes->plane_info.mp[1].offset = 0; |
| buf_planes->plane_info.mp[1].offset_x =0; |
| buf_planes->plane_info.mp[1].offset_y = 0; |
| buf_planes->plane_info.mp[1].stride = stride; |
| buf_planes->plane_info.mp[1].scanline = scanline; |
| buf_planes->plane_info.mp[1].width = dim->width; |
| buf_planes->plane_info.mp[1].height = dim->height / 2; |
| #else |
| LOGE("Venus hardware not avail, cannot use this format"); |
| rc = -1; |
| #endif |
| break; |
| case CAM_FORMAT_YUV_420_NV12_UBWC: |
| #ifdef UBWC_PRESENT |
| { |
| int meta_stride = 0,meta_scanline = 0; |
| // using UBWC |
| if (stream_info->stream_type != CAM_STREAM_TYPE_OFFLINE_PROC) { |
| stride = VENUS_Y_STRIDE(COLOR_FMT_NV12_UBWC, dim->width); |
| scanline = VENUS_Y_SCANLINES(COLOR_FMT_NV12_UBWC, dim->height); |
| } else { |
| stride = PAD_TO_SIZE(dim->width, padding->width_padding); |
| scanline = PAD_TO_SIZE(dim->height, padding->height_padding); |
| } |
| meta_stride = VENUS_Y_META_STRIDE(COLOR_FMT_NV12_UBWC, dim->width); |
| meta_scanline = VENUS_Y_META_SCANLINES(COLOR_FMT_NV12_UBWC, dim->height); |
| |
| buf_planes->plane_info.frame_len = |
| VENUS_BUFFER_SIZE(COLOR_FMT_NV12_UBWC, stride, scanline); |
| buf_planes->plane_info.num_planes = 2; |
| buf_planes->plane_info.mp[0].offset = 0; |
| buf_planes->plane_info.mp[0].offset_x =0; |
| buf_planes->plane_info.mp[0].offset_y = 0; |
| buf_planes->plane_info.mp[0].stride = stride; |
| buf_planes->plane_info.mp[0].scanline = scanline; |
| buf_planes->plane_info.mp[0].width = dim->width; |
| buf_planes->plane_info.mp[0].height = dim->height; |
| buf_planes->plane_info.mp[0].meta_stride = meta_stride; |
| buf_planes->plane_info.mp[0].meta_scanline = meta_scanline; |
| buf_planes->plane_info.mp[0].meta_len = |
| MSM_MEDIA_ALIGN(meta_stride * meta_scanline, 4096); |
| buf_planes->plane_info.mp[0].len = |
| (uint32_t)(MSM_MEDIA_ALIGN((stride * scanline), 4096) + |
| (buf_planes->plane_info.mp[0].meta_len)); |
| |
| stride = VENUS_UV_STRIDE(COLOR_FMT_NV12_UBWC, dim->width); |
| scanline = VENUS_UV_SCANLINES(COLOR_FMT_NV12_UBWC, dim->height); |
| meta_stride = VENUS_UV_META_STRIDE(COLOR_FMT_NV12_UBWC, dim->width); |
| meta_scanline = VENUS_UV_META_SCANLINES(COLOR_FMT_NV12_UBWC, dim->height); |
| buf_planes->plane_info.mp[1].offset = 0; |
| buf_planes->plane_info.mp[1].offset_x =0; |
| buf_planes->plane_info.mp[1].offset_y = 0; |
| buf_planes->plane_info.mp[1].stride = stride; |
| buf_planes->plane_info.mp[1].scanline = scanline; |
| buf_planes->plane_info.mp[1].width = dim->width; |
| buf_planes->plane_info.mp[1].height = dim->height/2; |
| buf_planes->plane_info.mp[1].meta_stride = meta_stride; |
| buf_planes->plane_info.mp[1].meta_scanline = meta_scanline; |
| buf_planes->plane_info.mp[1].meta_len = |
| MSM_MEDIA_ALIGN(meta_stride * meta_scanline, 4096); |
| buf_planes->plane_info.mp[1].len = |
| buf_planes->plane_info.frame_len - buf_planes->plane_info.mp[0].len; |
| } |
| #else |
| LOGE("UBWC hardware not avail, cannot use this format"); |
| rc = -1; |
| #endif |
| break; |
| |
| default: |
| LOGE("Invalid cam_format for preview %d", |
| stream_info->fmt); |
| rc = -1; |
| break; |
| } |
| |
| return rc; |
| } |
| /*=========================================================================== |
| * FUNCTION : mm_stream_calc_offset_post_view |
| * |
| * DESCRIPTION: calculate postview frame offset based on format and |
| * padding information |
| * |
| * PARAMETERS : |
| * @fmt : image format |
| * @dim : image dimension |
| * @buf_planes : [out] buffer plane information |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_stream_calc_offset_post_view(cam_format_t fmt, |
| cam_dimension_t *dim, |
| cam_stream_buf_plane_info_t *buf_planes) |
| { |
| int32_t rc = 0; |
| int stride = 0, scanline = 0; |
| |
| switch (fmt) { |
| case CAM_FORMAT_YUV_420_NV12: |
| case CAM_FORMAT_YUV_420_NV21: |
| /* 2 planes: Y + CbCr */ |
| buf_planes->plane_info.num_planes = 2; |
| |
| stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_64); |
| scanline = PAD_TO_SIZE(dim->height, CAM_PAD_TO_64); |
| buf_planes->plane_info.mp[0].offset = 0; |
| buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline); |
| buf_planes->plane_info.mp[0].offset_x = 0; |
| buf_planes->plane_info.mp[0].offset_y = 0; |
| buf_planes->plane_info.mp[0].stride = stride; |
| buf_planes->plane_info.mp[0].scanline = scanline; |
| buf_planes->plane_info.mp[0].width = dim->width; |
| buf_planes->plane_info.mp[0].height = dim->height; |
| |
| stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_64); |
| scanline = PAD_TO_SIZE(dim->height / 2, CAM_PAD_TO_64); |
| buf_planes->plane_info.mp[1].offset = 0; |
| buf_planes->plane_info.mp[1].len = |
| (uint32_t)(stride * scanline); |
| buf_planes->plane_info.mp[1].offset_x = 0; |
| buf_planes->plane_info.mp[1].offset_y = 0; |
| buf_planes->plane_info.mp[1].stride = stride; |
| buf_planes->plane_info.mp[1].scanline = scanline; |
| buf_planes->plane_info.mp[1].width = dim->width; |
| buf_planes->plane_info.mp[1].height = dim->height / 2; |
| |
| buf_planes->plane_info.frame_len = |
| PAD_TO_SIZE(buf_planes->plane_info.mp[0].len + |
| buf_planes->plane_info.mp[1].len, |
| CAM_PAD_TO_4K); |
| break; |
| case CAM_FORMAT_YUV_420_NV21_ADRENO: |
| /* 2 planes: Y + CbCr */ |
| buf_planes->plane_info.num_planes = 2; |
| |
| stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_32); |
| scanline = PAD_TO_SIZE(dim->height, CAM_PAD_TO_32); |
| buf_planes->plane_info.mp[0].offset = 0; |
| buf_planes->plane_info.mp[0].len = |
| PAD_TO_SIZE((uint32_t)(stride * scanline), CAM_PAD_TO_4K); |
| buf_planes->plane_info.mp[0].offset_x = 0; |
| buf_planes->plane_info.mp[0].offset_y = 0; |
| buf_planes->plane_info.mp[0].stride = stride; |
| buf_planes->plane_info.mp[0].scanline = scanline; |
| buf_planes->plane_info.mp[0].width = dim->width; |
| buf_planes->plane_info.mp[0].height = dim->height; |
| |
| stride = PAD_TO_SIZE(dim->width / 2, CAM_PAD_TO_32) * 2; |
| scanline = PAD_TO_SIZE(dim->height / 2, CAM_PAD_TO_32); |
| buf_planes->plane_info.mp[1].offset = 0; |
| buf_planes->plane_info.mp[1].len = |
| PAD_TO_SIZE((uint32_t)(stride * scanline), CAM_PAD_TO_4K); |
| buf_planes->plane_info.mp[1].offset_x = 0; |
| buf_planes->plane_info.mp[1].offset_y = 0; |
| buf_planes->plane_info.mp[1].stride = stride; |
| buf_planes->plane_info.mp[1].scanline = scanline; |
| buf_planes->plane_info.mp[1].width = dim->width; |
| buf_planes->plane_info.mp[1].height = dim->height / 2; |
| |
| buf_planes->plane_info.frame_len = |
| PAD_TO_SIZE(buf_planes->plane_info.mp[0].len + |
| buf_planes->plane_info.mp[1].len, |
| CAM_PAD_TO_4K); |
| break; |
| case CAM_FORMAT_YUV_420_YV12: |
| /* 3 planes: Y + Cr + Cb */ |
| buf_planes->plane_info.num_planes = 3; |
| |
| stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16); |
| scanline = PAD_TO_SIZE(dim->height, CAM_PAD_TO_2); |
| buf_planes->plane_info.mp[0].offset = 0; |
| buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline); |
| buf_planes->plane_info.mp[0].offset_x = 0; |
| buf_planes->plane_info.mp[0].offset_y = 0; |
| buf_planes->plane_info.mp[0].stride = stride; |
| buf_planes->plane_info.mp[0].scanline = scanline; |
| buf_planes->plane_info.mp[0].width = dim->width; |
| buf_planes->plane_info.mp[0].height = dim->height; |
| |
| stride = PAD_TO_SIZE(stride / 2, CAM_PAD_TO_16); |
| scanline = scanline / 2; |
| buf_planes->plane_info.mp[1].offset = 0; |
| buf_planes->plane_info.mp[1].len = |
| (uint32_t)(stride * scanline); |
| buf_planes->plane_info.mp[1].offset_x = 0; |
| buf_planes->plane_info.mp[1].offset_y = 0; |
| buf_planes->plane_info.mp[1].stride = stride; |
| buf_planes->plane_info.mp[1].scanline = scanline; |
| buf_planes->plane_info.mp[1].width = dim->width / 2; |
| buf_planes->plane_info.mp[1].height = dim->height / 2; |
| |
| buf_planes->plane_info.mp[2].offset = 0; |
| buf_planes->plane_info.mp[2].len = |
| (uint32_t)(stride * scanline); |
| buf_planes->plane_info.mp[2].offset_x = 0; |
| buf_planes->plane_info.mp[2].offset_y = 0; |
| buf_planes->plane_info.mp[2].stride = stride; |
| buf_planes->plane_info.mp[2].scanline = scanline; |
| buf_planes->plane_info.mp[2].width = dim->width / 2; |
| buf_planes->plane_info.mp[2].height = dim->height / 2; |
| |
| buf_planes->plane_info.frame_len = |
| PAD_TO_SIZE(buf_planes->plane_info.mp[0].len + |
| buf_planes->plane_info.mp[1].len + |
| buf_planes->plane_info.mp[2].len, |
| CAM_PAD_TO_4K); |
| break; |
| case CAM_FORMAT_YUV_422_NV16: |
| case CAM_FORMAT_YUV_422_NV61: |
| /* 2 planes: Y + CbCr */ |
| buf_planes->plane_info.num_planes = 2; |
| |
| stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16); |
| scanline = dim->height; |
| buf_planes->plane_info.mp[0].offset = 0; |
| buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline); |
| buf_planes->plane_info.mp[0].offset_x = 0; |
| buf_planes->plane_info.mp[0].offset_y = 0; |
| buf_planes->plane_info.mp[0].stride = stride; |
| buf_planes->plane_info.mp[0].scanline = scanline; |
| buf_planes->plane_info.mp[0].width = dim->width; |
| buf_planes->plane_info.mp[0].height = dim->height; |
| |
| buf_planes->plane_info.mp[1].offset = 0; |
| buf_planes->plane_info.mp[1].len = (uint32_t)(stride * scanline); |
| buf_planes->plane_info.mp[1].offset_x = 0; |
| buf_planes->plane_info.mp[1].offset_y = 0; |
| buf_planes->plane_info.mp[1].stride = stride; |
| buf_planes->plane_info.mp[1].scanline = scanline; |
| buf_planes->plane_info.mp[1].width = dim->width; |
| buf_planes->plane_info.mp[1].height = dim->height; |
| |
| buf_planes->plane_info.frame_len = |
| PAD_TO_SIZE(buf_planes->plane_info.mp[0].len + |
| buf_planes->plane_info.mp[1].len, |
| CAM_PAD_TO_4K); |
| break; |
| case CAM_FORMAT_YUV_420_NV12_VENUS: |
| #ifdef VENUS_PRESENT |
| // using Venus |
| stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, dim->width); |
| scanline = VENUS_Y_SCANLINES(COLOR_FMT_NV12, dim->height); |
| |
| buf_planes->plane_info.frame_len = |
| VENUS_BUFFER_SIZE(COLOR_FMT_NV12, dim->width, dim->height); |
| buf_planes->plane_info.num_planes = 2; |
| buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline); |
| buf_planes->plane_info.mp[0].offset = 0; |
| buf_planes->plane_info.mp[0].offset_x =0; |
| buf_planes->plane_info.mp[0].offset_y = 0; |
| buf_planes->plane_info.mp[0].stride = stride; |
| buf_planes->plane_info.mp[0].scanline = scanline; |
| buf_planes->plane_info.mp[0].width = dim->width; |
| buf_planes->plane_info.mp[0].height = dim->height; |
| stride = VENUS_UV_STRIDE(COLOR_FMT_NV12, dim->width); |
| scanline = VENUS_UV_SCANLINES(COLOR_FMT_NV12, dim->height); |
| buf_planes->plane_info.mp[1].len = |
| buf_planes->plane_info.frame_len - buf_planes->plane_info.mp[0].len; |
| buf_planes->plane_info.mp[1].offset = 0; |
| buf_planes->plane_info.mp[1].offset_x =0; |
| buf_planes->plane_info.mp[1].offset_y = 0; |
| buf_planes->plane_info.mp[1].stride = stride; |
| buf_planes->plane_info.mp[1].scanline = scanline; |
| buf_planes->plane_info.mp[1].width = dim->width; |
| buf_planes->plane_info.mp[1].height = dim->height / 2; |
| #else |
| LOGE("Venus hardware not avail, cannot use this format"); |
| rc = -1; |
| #endif |
| break; |
| case CAM_FORMAT_YUV_420_NV21_VENUS: |
| #ifdef VENUS_PRESENT |
| // using Venus |
| stride = VENUS_Y_STRIDE(COLOR_FMT_NV21, dim->width); |
| scanline = VENUS_Y_SCANLINES(COLOR_FMT_NV21, dim->height); |
| buf_planes->plane_info.frame_len = |
| VENUS_BUFFER_SIZE(COLOR_FMT_NV21, dim->width, dim->height); |
| buf_planes->plane_info.num_planes = 2; |
| buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline); |
| buf_planes->plane_info.mp[0].offset = 0; |
| buf_planes->plane_info.mp[0].offset_x =0; |
| buf_planes->plane_info.mp[0].offset_y = 0; |
| buf_planes->plane_info.mp[0].stride = stride; |
| buf_planes->plane_info.mp[0].scanline = scanline; |
| buf_planes->plane_info.mp[0].width = dim->width; |
| buf_planes->plane_info.mp[0].height = dim->height; |
| stride = VENUS_UV_STRIDE(COLOR_FMT_NV21, dim->width); |
| scanline = VENUS_UV_SCANLINES(COLOR_FMT_NV21, dim->height); |
| buf_planes->plane_info.mp[1].len = |
| buf_planes->plane_info.frame_len - buf_planes->plane_info.mp[0].len; |
| buf_planes->plane_info.mp[1].offset = 0; |
| buf_planes->plane_info.mp[1].offset_x =0; |
| buf_planes->plane_info.mp[1].offset_y = 0; |
| buf_planes->plane_info.mp[1].stride = stride; |
| buf_planes->plane_info.mp[1].scanline = scanline; |
| buf_planes->plane_info.mp[1].width = dim->width; |
| buf_planes->plane_info.mp[1].height = dim->height / 2; |
| #else |
| LOGE("Venus hardware not avail, cannot use this format"); |
| rc = -1; |
| #endif |
| break; |
| case CAM_FORMAT_YUV_420_NV12_UBWC: |
| #ifdef UBWC_PRESENT |
| { |
| int meta_stride = 0,meta_scanline = 0; |
| // using UBWC |
| stride = VENUS_Y_STRIDE(COLOR_FMT_NV12_UBWC, dim->width); |
| scanline = VENUS_Y_SCANLINES(COLOR_FMT_NV12_UBWC, dim->height); |
| meta_stride = VENUS_Y_META_STRIDE(COLOR_FMT_NV12_UBWC, dim->width); |
| meta_scanline = VENUS_Y_META_SCANLINES(COLOR_FMT_NV12_UBWC, dim->height); |
| |
| buf_planes->plane_info.frame_len = |
| VENUS_BUFFER_SIZE(COLOR_FMT_NV12_UBWC, dim->width, dim->height); |
| buf_planes->plane_info.num_planes = 2; |
| buf_planes->plane_info.mp[0].offset = 0; |
| buf_planes->plane_info.mp[0].offset_x =0; |
| buf_planes->plane_info.mp[0].offset_y = 0; |
| buf_planes->plane_info.mp[0].stride = stride; |
| buf_planes->plane_info.mp[0].scanline = scanline; |
| buf_planes->plane_info.mp[0].width = dim->width; |
| buf_planes->plane_info.mp[0].height = dim->height; |
| buf_planes->plane_info.mp[0].meta_stride = meta_stride; |
| buf_planes->plane_info.mp[0].meta_scanline = meta_scanline; |
| buf_planes->plane_info.mp[0].meta_len = |
| MSM_MEDIA_ALIGN(meta_stride * meta_scanline, 4096); |
| buf_planes->plane_info.mp[0].len = |
| (uint32_t)(MSM_MEDIA_ALIGN((stride * scanline), 4096) + |
| (buf_planes->plane_info.mp[0].meta_len)); |
| |
| stride = VENUS_UV_STRIDE(COLOR_FMT_NV12_UBWC, dim->width); |
| scanline = VENUS_UV_SCANLINES(COLOR_FMT_NV12_UBWC, dim->height); |
| meta_stride = VENUS_UV_META_STRIDE(COLOR_FMT_NV12_UBWC, dim->width); |
| meta_scanline = VENUS_UV_META_SCANLINES(COLOR_FMT_NV12_UBWC, dim->height); |
| buf_planes->plane_info.mp[1].offset = 0; |
| buf_planes->plane_info.mp[1].offset_x =0; |
| buf_planes->plane_info.mp[1].offset_y = 0; |
| buf_planes->plane_info.mp[1].stride = stride; |
| buf_planes->plane_info.mp[1].scanline = scanline; |
| buf_planes->plane_info.mp[1].width = dim->width; |
| buf_planes->plane_info.mp[1].height = dim->height/2; |
| buf_planes->plane_info.mp[1].meta_stride = meta_stride; |
| buf_planes->plane_info.mp[1].meta_scanline = meta_scanline; |
| buf_planes->plane_info.mp[1].meta_len = |
| MSM_MEDIA_ALIGN(meta_stride * meta_scanline, 4096); |
| buf_planes->plane_info.mp[1].len = |
| buf_planes->plane_info.frame_len - buf_planes->plane_info.mp[0].len; |
| } |
| #else |
| LOGE("UBWC hardware not avail, cannot use this format"); |
| rc = -1; |
| #endif |
| break; |
| default: |
| LOGE("Invalid cam_format for preview %d", |
| fmt); |
| rc = -1; |
| break; |
| } |
| |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_stream_calc_offset_snapshot |
| * |
| * DESCRIPTION: calculate snapshot/postproc frame offset based on format and |
| * padding information |
| * |
| * PARAMETERS : |
| * @fmt : image format |
| * @dim : image dimension |
| * @padding : padding information |
| * @buf_planes : [out] buffer plane information |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_stream_calc_offset_snapshot(cam_format_t fmt, |
| cam_dimension_t *dim, |
| cam_padding_info_t *padding, |
| cam_stream_buf_plane_info_t *buf_planes) |
| { |
| int32_t rc = 0; |
| uint8_t isAFamily = mm_camera_util_chip_is_a_family(); |
| int offset_x = 0, offset_y = 0; |
| int stride = 0, scanline = 0; |
| |
| if (isAFamily) { |
| stride = dim->width; |
| scanline = PAD_TO_SIZE(dim->height, CAM_PAD_TO_16); |
| offset_x = 0; |
| offset_y = scanline - dim->height; |
| scanline += offset_y; /* double padding */ |
| } else { |
| offset_x = PAD_TO_SIZE(padding->offset_info.offset_x, |
| padding->plane_padding); |
| offset_y = PAD_TO_SIZE(padding->offset_info.offset_y, |
| padding->plane_padding); |
| stride = PAD_TO_SIZE((dim->width + |
| (2 * offset_x)), padding->width_padding); |
| scanline = PAD_TO_SIZE((dim->height + |
| (2 * offset_y)), padding->height_padding); |
| } |
| |
| switch (fmt) { |
| case CAM_FORMAT_YUV_420_NV12: |
| case CAM_FORMAT_YUV_420_NV21: |
| /* 2 planes: Y + CbCr */ |
| buf_planes->plane_info.num_planes = 2; |
| |
| buf_planes->plane_info.mp[0].len = |
| PAD_TO_SIZE((uint32_t)(stride * scanline), |
| padding->plane_padding); |
| buf_planes->plane_info.mp[0].offset = |
| PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y), |
| padding->plane_padding); |
| buf_planes->plane_info.mp[0].offset_x = offset_x; |
| buf_planes->plane_info.mp[0].offset_y = offset_y; |
| buf_planes->plane_info.mp[0].stride = stride; |
| buf_planes->plane_info.mp[0].scanline = scanline; |
| buf_planes->plane_info.mp[0].width = dim->width; |
| buf_planes->plane_info.mp[0].height = dim->height; |
| |
| scanline = scanline/2; |
| buf_planes->plane_info.mp[1].len = |
| PAD_TO_SIZE((uint32_t)(stride * scanline), |
| padding->plane_padding); |
| buf_planes->plane_info.mp[1].offset = |
| PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y), |
| padding->plane_padding); |
| buf_planes->plane_info.mp[1].offset_x = offset_x; |
| buf_planes->plane_info.mp[1].offset_y = offset_y; |
| buf_planes->plane_info.mp[1].stride = stride; |
| buf_planes->plane_info.mp[1].scanline = scanline; |
| buf_planes->plane_info.mp[1].width = dim->width; |
| buf_planes->plane_info.mp[1].height = dim->height / 2; |
| |
| buf_planes->plane_info.frame_len = |
| PAD_TO_SIZE(buf_planes->plane_info.mp[0].len + |
| buf_planes->plane_info.mp[1].len, |
| CAM_PAD_TO_4K); |
| break; |
| case CAM_FORMAT_YUV_420_YV12: |
| /* 3 planes: Y + Cr + Cb */ |
| buf_planes->plane_info.num_planes = 3; |
| |
| buf_planes->plane_info.mp[0].offset = |
| PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y), |
| padding->plane_padding); |
| buf_planes->plane_info.mp[0].len = |
| PAD_TO_SIZE((uint32_t)(stride * scanline), |
| padding->plane_padding); |
| buf_planes->plane_info.mp[0].offset_x = offset_x; |
| buf_planes->plane_info.mp[0].offset_y = offset_y; |
| buf_planes->plane_info.mp[0].stride = stride; |
| buf_planes->plane_info.mp[0].scanline = scanline; |
| buf_planes->plane_info.mp[0].width = dim->width; |
| buf_planes->plane_info.mp[0].height = dim->height; |
| |
| stride = PAD_TO_SIZE(stride / 2, CAM_PAD_TO_16); |
| scanline = scanline / 2; |
| buf_planes->plane_info.mp[1].offset = |
| PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y), |
| padding->plane_padding); |
| buf_planes->plane_info.mp[1].len = |
| PAD_TO_SIZE((uint32_t)(stride * scanline), |
| padding->plane_padding); |
| buf_planes->plane_info.mp[1].offset_x = offset_x; |
| buf_planes->plane_info.mp[1].offset_y = offset_y; |
| buf_planes->plane_info.mp[1].stride = stride; |
| buf_planes->plane_info.mp[1].scanline = scanline; |
| buf_planes->plane_info.mp[1].width = dim->width / 2; |
| buf_planes->plane_info.mp[1].height = dim->height / 2; |
| |
| buf_planes->plane_info.mp[2].offset = |
| PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y), |
| padding->plane_padding); |
| buf_planes->plane_info.mp[2].len = |
| PAD_TO_SIZE((uint32_t)(stride * scanline), |
| padding->plane_padding); |
| buf_planes->plane_info.mp[2].offset_x = offset_x; |
| buf_planes->plane_info.mp[2].offset_y = offset_y; |
| buf_planes->plane_info.mp[2].stride = stride; |
| buf_planes->plane_info.mp[2].scanline = scanline; |
| buf_planes->plane_info.mp[2].width = dim->width / 2; |
| buf_planes->plane_info.mp[2].height = dim->height / 2; |
| |
| buf_planes->plane_info.frame_len = |
| PAD_TO_SIZE(buf_planes->plane_info.mp[0].len + |
| buf_planes->plane_info.mp[1].len + |
| buf_planes->plane_info.mp[2].len, |
| CAM_PAD_TO_4K); |
| break; |
| case CAM_FORMAT_YUV_422_NV16: |
| case CAM_FORMAT_YUV_422_NV61: |
| /* 2 planes: Y + CbCr */ |
| buf_planes->plane_info.num_planes = 2; |
| buf_planes->plane_info.mp[0].len = |
| PAD_TO_SIZE((uint32_t)(stride * scanline), |
| padding->plane_padding); |
| buf_planes->plane_info.mp[0].offset = |
| PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y), |
| padding->plane_padding); |
| buf_planes->plane_info.mp[0].offset_x = offset_x; |
| buf_planes->plane_info.mp[0].offset_y = offset_y; |
| buf_planes->plane_info.mp[0].stride = stride; |
| buf_planes->plane_info.mp[0].scanline = scanline; |
| buf_planes->plane_info.mp[0].width = dim->width; |
| buf_planes->plane_info.mp[0].height = dim->height; |
| |
| buf_planes->plane_info.mp[1].len = |
| PAD_TO_SIZE((uint32_t)(stride * scanline), |
| padding->plane_padding); |
| buf_planes->plane_info.mp[1].offset = |
| PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y), |
| padding->plane_padding); |
| buf_planes->plane_info.mp[1].offset_x = offset_x; |
| buf_planes->plane_info.mp[1].offset_y = offset_y; |
| buf_planes->plane_info.mp[1].stride = stride; |
| buf_planes->plane_info.mp[1].scanline = scanline; |
| buf_planes->plane_info.mp[1].width = dim->width; |
| buf_planes->plane_info.mp[1].height = dim->height; |
| |
| buf_planes->plane_info.frame_len = PAD_TO_SIZE( |
| buf_planes->plane_info.mp[0].len + buf_planes->plane_info.mp[1].len, |
| CAM_PAD_TO_4K); |
| break; |
| case CAM_FORMAT_YUV_420_NV12_UBWC: |
| #ifdef UBWC_PRESENT |
| { |
| int meta_stride = 0,meta_scanline = 0; |
| // using UBWC |
| stride = VENUS_Y_STRIDE(COLOR_FMT_NV12_UBWC, dim->width); |
| scanline = VENUS_Y_SCANLINES(COLOR_FMT_NV12_UBWC, dim->height); |
| meta_stride = VENUS_Y_META_STRIDE(COLOR_FMT_NV12_UBWC, dim->width); |
| meta_scanline = VENUS_Y_META_SCANLINES(COLOR_FMT_NV12_UBWC, dim->height); |
| |
| buf_planes->plane_info.frame_len = |
| VENUS_BUFFER_SIZE(COLOR_FMT_NV12_UBWC, dim->width, dim->height); |
| buf_planes->plane_info.num_planes = 2; |
| buf_planes->plane_info.mp[0].offset = 0; |
| buf_planes->plane_info.mp[0].offset_x = 0; |
| buf_planes->plane_info.mp[0].offset_y = 0; |
| buf_planes->plane_info.mp[0].stride = stride; |
| buf_planes->plane_info.mp[0].scanline = scanline; |
| buf_planes->plane_info.mp[0].width = dim->width; |
| buf_planes->plane_info.mp[0].height = dim->height; |
| buf_planes->plane_info.mp[0].meta_stride = meta_stride; |
| buf_planes->plane_info.mp[0].meta_scanline = meta_scanline; |
| buf_planes->plane_info.mp[0].meta_len = |
| MSM_MEDIA_ALIGN(meta_stride * meta_scanline, 4096); |
| buf_planes->plane_info.mp[0].len = |
| (uint32_t)(MSM_MEDIA_ALIGN((stride * scanline), 4096) + |
| (buf_planes->plane_info.mp[0].meta_len)); |
| |
| stride = VENUS_UV_STRIDE(COLOR_FMT_NV12_UBWC, dim->width); |
| scanline = VENUS_UV_SCANLINES(COLOR_FMT_NV12_UBWC, dim->height); |
| meta_stride = VENUS_UV_META_STRIDE(COLOR_FMT_NV12_UBWC, dim->width); |
| meta_scanline = VENUS_UV_META_SCANLINES(COLOR_FMT_NV12_UBWC, dim->height); |
| buf_planes->plane_info.mp[1].offset = 0; |
| buf_planes->plane_info.mp[1].offset_x =0; |
| buf_planes->plane_info.mp[1].offset_y = 0; |
| buf_planes->plane_info.mp[1].stride = stride; |
| buf_planes->plane_info.mp[1].scanline = scanline; |
| buf_planes->plane_info.mp[1].width = dim->width; |
| buf_planes->plane_info.mp[1].height = dim->height/2; |
| buf_planes->plane_info.mp[1].meta_stride = meta_stride; |
| buf_planes->plane_info.mp[1].meta_scanline = meta_scanline; |
| buf_planes->plane_info.mp[1].meta_len = |
| MSM_MEDIA_ALIGN(meta_stride * meta_scanline, 4096); |
| buf_planes->plane_info.mp[1].len = |
| buf_planes->plane_info.frame_len - buf_planes->plane_info.mp[0].len; |
| } |
| #else |
| LOGE("UBWC hardware not avail, cannot use this format"); |
| rc = -1; |
| #endif |
| break; |
| case CAM_FORMAT_YUV_420_NV12_VENUS: |
| #ifdef VENUS_PRESENT |
| // using Venus |
| stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, dim->width); |
| scanline = VENUS_Y_SCANLINES(COLOR_FMT_NV12, dim->height); |
| |
| buf_planes->plane_info.frame_len = |
| VENUS_BUFFER_SIZE(COLOR_FMT_NV12, dim->width, dim->height); |
| buf_planes->plane_info.num_planes = 2; |
| buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline); |
| buf_planes->plane_info.mp[0].offset = 0; |
| buf_planes->plane_info.mp[0].offset_x =0; |
| buf_planes->plane_info.mp[0].offset_y = 0; |
| buf_planes->plane_info.mp[0].stride = stride; |
| buf_planes->plane_info.mp[0].scanline = scanline; |
| buf_planes->plane_info.mp[0].width = dim->width; |
| buf_planes->plane_info.mp[0].height = dim->height; |
| stride = VENUS_UV_STRIDE(COLOR_FMT_NV12, dim->width); |
| scanline = VENUS_UV_SCANLINES(COLOR_FMT_NV12, dim->height); |
| buf_planes->plane_info.mp[1].len = |
| buf_planes->plane_info.frame_len - |
| buf_planes->plane_info.mp[0].len; |
| buf_planes->plane_info.mp[1].offset = 0; |
| buf_planes->plane_info.mp[1].offset_x =0; |
| buf_planes->plane_info.mp[1].offset_y = 0; |
| buf_planes->plane_info.mp[1].stride = stride; |
| buf_planes->plane_info.mp[1].scanline = scanline; |
| buf_planes->plane_info.mp[1].width = dim->width; |
| buf_planes->plane_info.mp[1].height = dim->height / 2; |
| #else |
| LOGD("Video format VENUS is not supported = %d", |
| fmt); |
| #endif |
| break; |
| case CAM_FORMAT_YUV_420_NV21_VENUS: |
| #ifdef VENUS_PRESENT |
| // using Venus |
| stride = VENUS_Y_STRIDE(COLOR_FMT_NV21, dim->width); |
| scanline = VENUS_Y_SCANLINES(COLOR_FMT_NV21, dim->height); |
| buf_planes->plane_info.frame_len = |
| VENUS_BUFFER_SIZE(COLOR_FMT_NV21, dim->width, dim->height); |
| buf_planes->plane_info.num_planes = 2; |
| buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline); |
| buf_planes->plane_info.mp[0].offset = 0; |
| buf_planes->plane_info.mp[0].offset_x =0; |
| buf_planes->plane_info.mp[0].offset_y = 0; |
| buf_planes->plane_info.mp[0].stride = stride; |
| buf_planes->plane_info.mp[0].scanline = scanline; |
| buf_planes->plane_info.mp[0].width = dim->width; |
| buf_planes->plane_info.mp[0].height = dim->height; |
| stride = VENUS_UV_STRIDE(COLOR_FMT_NV21, dim->width); |
| scanline = VENUS_UV_SCANLINES(COLOR_FMT_NV21, dim->height); |
| buf_planes->plane_info.mp[1].len = |
| buf_planes->plane_info.frame_len - buf_planes->plane_info.mp[0].len; |
| buf_planes->plane_info.mp[1].offset = 0; |
| buf_planes->plane_info.mp[1].offset_x =0; |
| buf_planes->plane_info.mp[1].offset_y = 0; |
| buf_planes->plane_info.mp[1].stride = stride; |
| buf_planes->plane_info.mp[1].scanline = scanline; |
| buf_planes->plane_info.mp[1].width = dim->width; |
| buf_planes->plane_info.mp[1].height = dim->height / 2; |
| #else |
| LOGE("Venus hardware not avail, cannot use this format"); |
| rc = -1; |
| #endif |
| break; |
| default: |
| LOGE("Invalid cam_format for snapshot %d", |
| fmt); |
| rc = -1; |
| break; |
| } |
| |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_stream_calc_offset_raw |
| * |
| * DESCRIPTION: calculate raw frame offset based on format and padding information |
| * |
| * PARAMETERS : |
| * @fmt : image format |
| * @dim : image dimension |
| * @padding : padding information |
| * @buf_planes : [out] buffer plane information |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_stream_calc_offset_raw(cam_format_t fmt, |
| cam_dimension_t *dim, |
| cam_padding_info_t *padding, |
| cam_stream_buf_plane_info_t *buf_planes) |
| { |
| int32_t rc = 0; |
| |
| if ((NULL == dim) || (NULL == padding) || (NULL == buf_planes)) { |
| return -1; |
| } |
| |
| int32_t stride = PAD_TO_SIZE(dim->width, (int32_t)padding->width_padding); |
| int32_t stride_in_bytes = stride; |
| int32_t scanline = PAD_TO_SIZE(dim->height, (int32_t)padding->height_padding); |
| |
| switch (fmt) { |
| case CAM_FORMAT_YUV_420_NV21: |
| /* 2 planes: Y + CbCr */ |
| buf_planes->plane_info.num_planes = 2; |
| |
| buf_planes->plane_info.mp[0].len = |
| PAD_TO_SIZE((uint32_t)(stride * scanline), |
| padding->plane_padding); |
| buf_planes->plane_info.mp[0].offset = 0; |
| buf_planes->plane_info.mp[0].offset_x = 0; |
| buf_planes->plane_info.mp[0].offset_y = 0; |
| buf_planes->plane_info.mp[0].stride = stride; |
| buf_planes->plane_info.mp[0].stride_in_bytes = stride; |
| buf_planes->plane_info.mp[0].scanline = scanline; |
| buf_planes->plane_info.mp[0].width = dim->width; |
| buf_planes->plane_info.mp[0].height = dim->height; |
| |
| scanline = scanline / 2; |
| buf_planes->plane_info.mp[1].len = |
| PAD_TO_SIZE((uint32_t)(stride * scanline), |
| padding->plane_padding); |
| buf_planes->plane_info.mp[1].offset = 0; |
| buf_planes->plane_info.mp[1].offset_x = 0; |
| buf_planes->plane_info.mp[1].offset_y = 0; |
| buf_planes->plane_info.mp[1].stride = stride; |
| buf_planes->plane_info.mp[1].stride_in_bytes = stride; |
| buf_planes->plane_info.mp[1].scanline = scanline; |
| buf_planes->plane_info.mp[1].width = dim->width; |
| buf_planes->plane_info.mp[1].height = dim->height / 2; |
| |
| buf_planes->plane_info.frame_len = |
| PAD_TO_SIZE(buf_planes->plane_info.mp[0].len + |
| buf_planes->plane_info.mp[1].len, |
| CAM_PAD_TO_4K); |
| break; |
| case CAM_FORMAT_YUV_RAW_8BIT_YUYV: |
| case CAM_FORMAT_YUV_RAW_8BIT_YVYU: |
| case CAM_FORMAT_YUV_RAW_8BIT_UYVY: |
| case CAM_FORMAT_YUV_RAW_8BIT_VYUY: |
| case CAM_FORMAT_JPEG_RAW_8BIT: |
| /* 1 plane */ |
| /* Every 16 pixels occupy 16 bytes */ |
| stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16); |
| stride_in_bytes = stride * 2; |
| buf_planes->plane_info.num_planes = 1; |
| buf_planes->plane_info.mp[0].offset = 0; |
| buf_planes->plane_info.mp[0].len = |
| PAD_TO_SIZE((uint32_t)(stride_in_bytes * scanline), |
| padding->plane_padding); |
| buf_planes->plane_info.frame_len = |
| PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K); |
| buf_planes->plane_info.mp[0].offset_x =0; |
| buf_planes->plane_info.mp[0].offset_y = 0; |
| buf_planes->plane_info.mp[0].stride = stride; |
| buf_planes->plane_info.mp[0].stride_in_bytes = stride_in_bytes; |
| buf_planes->plane_info.mp[0].scanline = scanline; |
| buf_planes->plane_info.mp[0].width = |
| (int32_t)buf_planes->plane_info.mp[0].len; |
| buf_planes->plane_info.mp[0].height = 1; |
| break; |
| case CAM_FORMAT_META_RAW_8BIT: |
| // Every 16 pixels occupy 16 bytes |
| stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16); |
| stride_in_bytes = stride * 2; |
| buf_planes->plane_info.num_planes = 1; |
| buf_planes->plane_info.mp[0].offset = 0; |
| buf_planes->plane_info.mp[0].len = |
| PAD_TO_SIZE((uint32_t)(stride_in_bytes * scanline), |
| padding->plane_padding); |
| buf_planes->plane_info.frame_len = |
| PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K); |
| buf_planes->plane_info.mp[0].offset_x =0; |
| buf_planes->plane_info.mp[0].offset_y = 0; |
| buf_planes->plane_info.mp[0].stride = stride; |
| buf_planes->plane_info.mp[0].stride_in_bytes = stride_in_bytes; |
| buf_planes->plane_info.mp[0].scanline = scanline; |
| break; |
| |
| case CAM_FORMAT_BAYER_QCOM_RAW_8BPP_GBRG: |
| case CAM_FORMAT_BAYER_QCOM_RAW_8BPP_GRBG: |
| case CAM_FORMAT_BAYER_QCOM_RAW_8BPP_RGGB: |
| case CAM_FORMAT_BAYER_QCOM_RAW_8BPP_BGGR: |
| case CAM_FORMAT_BAYER_MIPI_RAW_8BPP_GBRG: |
| case CAM_FORMAT_BAYER_MIPI_RAW_8BPP_GRBG: |
| case CAM_FORMAT_BAYER_MIPI_RAW_8BPP_RGGB: |
| case CAM_FORMAT_BAYER_MIPI_RAW_8BPP_BGGR: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_8BPP_GBRG: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_8BPP_GRBG: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_8BPP_RGGB: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_8BPP_BGGR: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_8BPP_GBRG: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_8BPP_GRBG: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_8BPP_RGGB: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_8BPP_BGGR: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN8_8BPP_GBRG: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN8_8BPP_GRBG: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN8_8BPP_RGGB: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN8_8BPP_BGGR: |
| /* 1 plane */ |
| /* Every 16 pixels occupy 16 bytes */ |
| stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16); |
| stride_in_bytes = stride; |
| buf_planes->plane_info.num_planes = 1; |
| buf_planes->plane_info.mp[0].offset = 0; |
| buf_planes->plane_info.mp[0].len = |
| PAD_TO_SIZE((uint32_t)(stride_in_bytes * scanline), |
| padding->plane_padding); |
| buf_planes->plane_info.frame_len = |
| PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K); |
| buf_planes->plane_info.mp[0].offset_x =0; |
| buf_planes->plane_info.mp[0].offset_y = 0; |
| buf_planes->plane_info.mp[0].stride = stride; |
| buf_planes->plane_info.mp[0].stride_in_bytes = stride_in_bytes; |
| buf_planes->plane_info.mp[0].scanline = scanline; |
| buf_planes->plane_info.mp[0].width = (int32_t)buf_planes->plane_info.mp[0].len; |
| buf_planes->plane_info.mp[0].height = 1; |
| break; |
| case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_GBRG: |
| case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_GRBG: |
| case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_RGGB: |
| case CAM_FORMAT_BAYER_QCOM_RAW_10BPP_BGGR: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_10BPP_GBRG: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_10BPP_GRBG: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_10BPP_RGGB: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_10BPP_BGGR: |
| /* Every 12 pixels occupy 16 bytes */ |
| stride = (dim->width + 11)/12 * 12; |
| stride_in_bytes = stride * 8 / 6; |
| buf_planes->plane_info.num_planes = 1; |
| buf_planes->plane_info.mp[0].offset = 0; |
| buf_planes->plane_info.mp[0].len = |
| PAD_TO_SIZE((uint32_t)(stride_in_bytes * scanline), |
| padding->plane_padding); |
| buf_planes->plane_info.frame_len = |
| PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K); |
| buf_planes->plane_info.mp[0].offset_x =0; |
| buf_planes->plane_info.mp[0].offset_y = 0; |
| buf_planes->plane_info.mp[0].stride = stride; |
| buf_planes->plane_info.mp[0].stride_in_bytes = stride_in_bytes; |
| buf_planes->plane_info.mp[0].scanline = scanline; |
| buf_planes->plane_info.mp[0].width = (int32_t)buf_planes->plane_info.mp[0].len; |
| buf_planes->plane_info.mp[0].height = 1; |
| break; |
| case CAM_FORMAT_BAYER_QCOM_RAW_12BPP_GBRG: |
| case CAM_FORMAT_BAYER_QCOM_RAW_12BPP_GRBG: |
| case CAM_FORMAT_BAYER_QCOM_RAW_12BPP_RGGB: |
| case CAM_FORMAT_BAYER_QCOM_RAW_12BPP_BGGR: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_12BPP_GBRG: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_12BPP_GRBG: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_12BPP_RGGB: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_12BPP_BGGR: |
| /* Every 10 pixels occupy 16 bytes */ |
| stride = (dim->width + 9)/10 * 10; |
| stride_in_bytes = stride * 8 / 5; |
| buf_planes->plane_info.num_planes = 1; |
| buf_planes->plane_info.mp[0].offset = 0; |
| buf_planes->plane_info.mp[0].len = |
| PAD_TO_SIZE((uint32_t)(stride_in_bytes * scanline), |
| padding->plane_padding); |
| buf_planes->plane_info.frame_len = |
| PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K); |
| buf_planes->plane_info.mp[0].offset_x =0; |
| buf_planes->plane_info.mp[0].offset_y = 0; |
| buf_planes->plane_info.mp[0].stride = stride; |
| buf_planes->plane_info.mp[0].stride_in_bytes = stride_in_bytes; |
| buf_planes->plane_info.mp[0].scanline = scanline; |
| buf_planes->plane_info.mp[0].width = (int32_t)buf_planes->plane_info.mp[0].len; |
| buf_planes->plane_info.mp[0].height = 1; |
| break; |
| case CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GBRG: |
| case CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GRBG: |
| case CAM_FORMAT_BAYER_MIPI_RAW_10BPP_RGGB: |
| case CAM_FORMAT_BAYER_MIPI_RAW_10BPP_BGGR: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_10BPP_GBRG: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_10BPP_GRBG: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_10BPP_RGGB: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_10BPP_BGGR: |
| /* Every 64 pixels occupy 80 bytes */ |
| stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_4); |
| stride_in_bytes = PAD_TO_SIZE(stride * 5 / 4, CAM_PAD_TO_8); |
| buf_planes->plane_info.num_planes = 1; |
| buf_planes->plane_info.mp[0].offset = 0; |
| buf_planes->plane_info.mp[0].len = |
| PAD_TO_SIZE((uint32_t)(stride_in_bytes * scanline), |
| padding->plane_padding); |
| buf_planes->plane_info.frame_len = |
| PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K); |
| buf_planes->plane_info.mp[0].offset_x =0; |
| buf_planes->plane_info.mp[0].offset_y = 0; |
| buf_planes->plane_info.mp[0].stride = stride; |
| buf_planes->plane_info.mp[0].stride_in_bytes = stride_in_bytes; |
| buf_planes->plane_info.mp[0].scanline = scanline; |
| buf_planes->plane_info.mp[0].width = (int32_t)buf_planes->plane_info.mp[0].len; |
| buf_planes->plane_info.mp[0].height = 1; |
| break; |
| case CAM_FORMAT_BAYER_MIPI_RAW_12BPP_GBRG: |
| case CAM_FORMAT_BAYER_MIPI_RAW_12BPP_GRBG: |
| case CAM_FORMAT_BAYER_MIPI_RAW_12BPP_RGGB: |
| case CAM_FORMAT_BAYER_MIPI_RAW_12BPP_BGGR: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_12BPP_GBRG: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_12BPP_GRBG: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_12BPP_RGGB: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_12BPP_BGGR: |
| /* Every 32 pixels occupy 48 bytes */ |
| stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_32); |
| stride_in_bytes = stride * 3 / 2; |
| buf_planes->plane_info.num_planes = 1; |
| buf_planes->plane_info.mp[0].offset = 0; |
| buf_planes->plane_info.mp[0].len = |
| PAD_TO_SIZE((uint32_t)(stride_in_bytes * scanline), |
| padding->plane_padding); |
| buf_planes->plane_info.frame_len = |
| PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K); |
| buf_planes->plane_info.mp[0].offset_x =0; |
| buf_planes->plane_info.mp[0].offset_y = 0; |
| buf_planes->plane_info.mp[0].stride = stride; |
| buf_planes->plane_info.mp[0].stride_in_bytes = stride_in_bytes; |
| buf_planes->plane_info.mp[0].scanline = scanline; |
| buf_planes->plane_info.mp[0].width = (int32_t)buf_planes->plane_info.mp[0].len; |
| buf_planes->plane_info.mp[0].height = 1; |
| break; |
| case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_8BPP_GBRG: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_8BPP_GRBG: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_8BPP_RGGB: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_8BPP_BGGR: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_10BPP_GBRG: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_10BPP_GRBG: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_10BPP_RGGB: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_10BPP_BGGR: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_12BPP_GBRG: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_12BPP_GRBG: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_12BPP_RGGB: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_12BPP_BGGR: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_14BPP_GBRG: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_14BPP_GRBG: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_14BPP_RGGB: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_14BPP_BGGR: |
| /* Every 8 pixels occupy 16 bytes */ |
| stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_8); |
| stride_in_bytes = stride * 2; |
| buf_planes->plane_info.num_planes = 1; |
| buf_planes->plane_info.mp[0].offset = 0; |
| buf_planes->plane_info.mp[0].len = |
| PAD_TO_SIZE((uint32_t)(stride_in_bytes * scanline), |
| padding->plane_padding); |
| buf_planes->plane_info.frame_len = |
| PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K); |
| buf_planes->plane_info.mp[0].offset_x =0; |
| buf_planes->plane_info.mp[0].offset_y = 0; |
| buf_planes->plane_info.mp[0].stride = stride; |
| buf_planes->plane_info.mp[0].stride_in_bytes = stride_in_bytes; |
| buf_planes->plane_info.mp[0].scanline = scanline; |
| buf_planes->plane_info.mp[0].width = (int32_t)buf_planes->plane_info.mp[0].len; |
| buf_planes->plane_info.mp[0].height = 1; |
| break; |
| case CAM_FORMAT_BAYER_MIPI_RAW_14BPP_GBRG: |
| case CAM_FORMAT_BAYER_MIPI_RAW_14BPP_GRBG: |
| case CAM_FORMAT_BAYER_MIPI_RAW_14BPP_RGGB: |
| case CAM_FORMAT_BAYER_MIPI_RAW_14BPP_BGGR: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_14BPP_GBRG: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_14BPP_GRBG: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_14BPP_RGGB: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_MIPI_14BPP_BGGR: |
| /* Every 64 pixels occupy 112 bytes */ |
| stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_64); |
| stride_in_bytes = stride * 7 / 4; |
| buf_planes->plane_info.num_planes = 1; |
| buf_planes->plane_info.mp[0].offset = 0; |
| buf_planes->plane_info.mp[0].len = |
| PAD_TO_SIZE((uint32_t)(stride_in_bytes * scanline), |
| padding->plane_padding); |
| buf_planes->plane_info.frame_len = |
| PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K); |
| buf_planes->plane_info.mp[0].offset_x =0; |
| buf_planes->plane_info.mp[0].offset_y = 0; |
| buf_planes->plane_info.mp[0].stride = stride; |
| buf_planes->plane_info.mp[0].stride_in_bytes = stride_in_bytes; |
| buf_planes->plane_info.mp[0].scanline = scanline; |
| buf_planes->plane_info.mp[0].width = (int32_t)buf_planes->plane_info.mp[0].len; |
| buf_planes->plane_info.mp[0].height = 1; |
| break; |
| case CAM_FORMAT_BAYER_QCOM_RAW_14BPP_GBRG: |
| case CAM_FORMAT_BAYER_QCOM_RAW_14BPP_GRBG: |
| case CAM_FORMAT_BAYER_QCOM_RAW_14BPP_RGGB: |
| case CAM_FORMAT_BAYER_QCOM_RAW_14BPP_BGGR: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_14BPP_GBRG: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_14BPP_GRBG: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_14BPP_RGGB: |
| case CAM_FORMAT_BAYER_IDEAL_RAW_QCOM_14BPP_BGGR: |
| /* Every 16 pixels occupy 32 bytes */ |
| stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16); |
| stride_in_bytes = stride * 2; |
| buf_planes->plane_info.num_planes = 1; |
| buf_planes->plane_info.mp[0].offset = 0; |
| buf_planes->plane_info.mp[0].len = |
| PAD_TO_SIZE((uint32_t)(stride_in_bytes * scanline), |
| padding->plane_padding); |
| buf_planes->plane_info.frame_len = |
| PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K); |
| buf_planes->plane_info.mp[0].offset_x =0; |
| buf_planes->plane_info.mp[0].offset_y = 0; |
| buf_planes->plane_info.mp[0].stride = stride; |
| buf_planes->plane_info.mp[0].stride_in_bytes = stride_in_bytes; |
| buf_planes->plane_info.mp[0].scanline = scanline; |
| buf_planes->plane_info.mp[0].width = (int32_t)buf_planes->plane_info.mp[0].len; |
| buf_planes->plane_info.mp[0].height = 1; |
| break; |
| default: |
| LOGE("Invalid cam_format %d for raw stream", |
| fmt); |
| rc = -1; |
| break; |
| } |
| |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_stream_calc_offset_video |
| * |
| * DESCRIPTION: calculate video frame offset based on format and |
| * padding information |
| * |
| * PARAMETERS : |
| * @fmt : image format |
| * @dim : image dimension |
| * @buf_planes : [out] buffer plane information |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_stream_calc_offset_video(cam_format_t fmt, |
| cam_dimension_t *dim, cam_stream_buf_plane_info_t *buf_planes) |
| { |
| int32_t rc = 0; |
| int stride = 0, scanline = 0; |
| int meta_stride = 0,meta_scanline = 0; |
| |
| |
| switch (fmt) { |
| case CAM_FORMAT_YUV_420_NV12: |
| buf_planes->plane_info.num_planes = 2; |
| |
| stride = dim->width; |
| scanline = dim->height; |
| buf_planes->plane_info.mp[0].len = |
| PAD_TO_SIZE((uint32_t)(stride * scanline), |
| CAM_PAD_TO_2K); |
| buf_planes->plane_info.mp[0].offset = 0; |
| buf_planes->plane_info.mp[0].offset_x =0; |
| buf_planes->plane_info.mp[0].offset_y = 0; |
| buf_planes->plane_info.mp[0].stride = stride; |
| buf_planes->plane_info.mp[0].scanline = scanline; |
| buf_planes->plane_info.mp[0].width = dim->width; |
| buf_planes->plane_info.mp[0].height = dim->height; |
| |
| stride = dim->width; |
| scanline = dim->height / 2; |
| buf_planes->plane_info.mp[1].len = |
| PAD_TO_SIZE((uint32_t)(stride * scanline), |
| CAM_PAD_TO_2K); |
| buf_planes->plane_info.mp[1].offset = 0; |
| buf_planes->plane_info.mp[1].offset_x =0; |
| buf_planes->plane_info.mp[1].offset_y = 0; |
| buf_planes->plane_info.mp[1].stride = stride; |
| buf_planes->plane_info.mp[1].scanline = scanline; |
| buf_planes->plane_info.mp[1].width = dim->width; |
| buf_planes->plane_info.mp[1].height = dim->height / 2; |
| |
| buf_planes->plane_info.frame_len = |
| PAD_TO_SIZE(buf_planes->plane_info.mp[0].len + |
| buf_planes->plane_info.mp[1].len, |
| CAM_PAD_TO_4K); |
| break; |
| case CAM_FORMAT_YUV_420_NV12_VENUS: |
| #ifdef VENUS_PRESENT |
| // using Venus |
| stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, dim->width); |
| scanline = VENUS_Y_SCANLINES(COLOR_FMT_NV12, dim->height); |
| |
| buf_planes->plane_info.frame_len = |
| VENUS_BUFFER_SIZE(COLOR_FMT_NV12, dim->width, dim->height); |
| buf_planes->plane_info.num_planes = 2; |
| buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline); |
| buf_planes->plane_info.mp[0].offset = 0; |
| buf_planes->plane_info.mp[0].offset_x =0; |
| buf_planes->plane_info.mp[0].offset_y = 0; |
| buf_planes->plane_info.mp[0].stride = stride; |
| buf_planes->plane_info.mp[0].scanline = scanline; |
| buf_planes->plane_info.mp[0].width = dim->width; |
| buf_planes->plane_info.mp[0].height = dim->height; |
| stride = VENUS_UV_STRIDE(COLOR_FMT_NV12, dim->width); |
| scanline = VENUS_UV_SCANLINES(COLOR_FMT_NV12, dim->height); |
| buf_planes->plane_info.mp[1].len = |
| buf_planes->plane_info.frame_len - |
| buf_planes->plane_info.mp[0].len; |
| buf_planes->plane_info.mp[1].offset = 0; |
| buf_planes->plane_info.mp[1].offset_x =0; |
| buf_planes->plane_info.mp[1].offset_y = 0; |
| buf_planes->plane_info.mp[1].stride = stride; |
| buf_planes->plane_info.mp[1].scanline = scanline; |
| buf_planes->plane_info.mp[1].width = dim->width; |
| buf_planes->plane_info.mp[1].height = dim->height/2; |
| #else |
| LOGD("Video format VENUS is not supported = %d", |
| fmt); |
| #endif |
| break; |
| case CAM_FORMAT_YUV_420_NV21_VENUS: |
| #ifdef VENUS_PRESENT |
| // using Venus |
| stride = VENUS_Y_STRIDE(COLOR_FMT_NV21, dim->width); |
| scanline = VENUS_Y_SCANLINES(COLOR_FMT_NV21, dim->height); |
| |
| buf_planes->plane_info.frame_len = |
| VENUS_BUFFER_SIZE(COLOR_FMT_NV21, dim->width, dim->height); |
| buf_planes->plane_info.num_planes = 2; |
| buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline); |
| buf_planes->plane_info.mp[0].offset = 0; |
| buf_planes->plane_info.mp[0].offset_x =0; |
| buf_planes->plane_info.mp[0].offset_y = 0; |
| buf_planes->plane_info.mp[0].stride = stride; |
| buf_planes->plane_info.mp[0].scanline = scanline; |
| buf_planes->plane_info.mp[0].width = dim->width; |
| buf_planes->plane_info.mp[0].height = dim->height; |
| stride = VENUS_UV_STRIDE(COLOR_FMT_NV21, dim->width); |
| scanline = VENUS_UV_SCANLINES(COLOR_FMT_NV21, dim->height); |
| buf_planes->plane_info.mp[1].len = |
| buf_planes->plane_info.frame_len - |
| buf_planes->plane_info.mp[0].len; |
| buf_planes->plane_info.mp[1].offset = 0; |
| buf_planes->plane_info.mp[1].offset_x =0; |
| buf_planes->plane_info.mp[1].offset_y = 0; |
| buf_planes->plane_info.mp[1].stride = stride; |
| buf_planes->plane_info.mp[1].scanline = scanline; |
| buf_planes->plane_info.mp[1].width = dim->width; |
| buf_planes->plane_info.mp[1].height = dim->height / 2; |
| #else |
| LOGD("Video format VENUS is not supported = %d", |
| fmt); |
| #endif |
| break; |
| case CAM_FORMAT_YUV_420_NV12_UBWC: |
| #ifdef UBWC_PRESENT |
| // using UBWC |
| stride = VENUS_Y_STRIDE(COLOR_FMT_NV12_UBWC, dim->width); |
| scanline = VENUS_Y_SCANLINES(COLOR_FMT_NV12_UBWC, dim->height); |
| meta_stride = VENUS_Y_META_STRIDE(COLOR_FMT_NV12_UBWC, dim->width); |
| meta_scanline = VENUS_Y_META_SCANLINES(COLOR_FMT_NV12_UBWC, dim->height); |
| |
| buf_planes->plane_info.frame_len = |
| VENUS_BUFFER_SIZE(COLOR_FMT_NV12_UBWC, dim->width, dim->height); |
| buf_planes->plane_info.num_planes = 2; |
| buf_planes->plane_info.mp[0].offset = 0; |
| buf_planes->plane_info.mp[0].offset_x =0; |
| buf_planes->plane_info.mp[0].offset_y = 0; |
| buf_planes->plane_info.mp[0].stride = stride; |
| buf_planes->plane_info.mp[0].scanline = scanline; |
| buf_planes->plane_info.mp[0].width = dim->width; |
| buf_planes->plane_info.mp[0].height = dim->height; |
| buf_planes->plane_info.mp[0].meta_stride = meta_stride; |
| buf_planes->plane_info.mp[0].meta_scanline = meta_scanline; |
| buf_planes->plane_info.mp[0].meta_len = |
| MSM_MEDIA_ALIGN(meta_stride * meta_scanline, 4096); |
| buf_planes->plane_info.mp[0].len = |
| (uint32_t)(MSM_MEDIA_ALIGN((stride * scanline), 4096) + |
| (buf_planes->plane_info.mp[0].meta_len)); |
| |
| stride = VENUS_UV_STRIDE(COLOR_FMT_NV12_UBWC, dim->width); |
| scanline = VENUS_UV_SCANLINES(COLOR_FMT_NV12_UBWC, dim->height); |
| meta_stride = VENUS_UV_META_STRIDE(COLOR_FMT_NV12_UBWC, dim->width); |
| meta_scanline = VENUS_UV_META_SCANLINES(COLOR_FMT_NV12_UBWC, dim->height); |
| |
| buf_planes->plane_info.mp[1].offset = 0; |
| buf_planes->plane_info.mp[1].offset_x =0; |
| buf_planes->plane_info.mp[1].offset_y = 0; |
| buf_planes->plane_info.mp[1].stride = stride; |
| buf_planes->plane_info.mp[1].scanline = scanline; |
| buf_planes->plane_info.mp[1].width = dim->width; |
| buf_planes->plane_info.mp[1].height = dim->height/2; |
| buf_planes->plane_info.mp[1].meta_stride = meta_stride; |
| buf_planes->plane_info.mp[1].meta_scanline = meta_scanline; |
| buf_planes->plane_info.mp[1].meta_len = |
| MSM_MEDIA_ALIGN(meta_stride * meta_scanline, 4096); |
| buf_planes->plane_info.mp[1].len = |
| buf_planes->plane_info.frame_len - buf_planes->plane_info.mp[0].len; |
| |
| #else |
| LOGD("Video format UBWC is not supported = %d", |
| fmt); |
| rc = -1; |
| #endif |
| break; |
| default: |
| LOGD("Invalid Video Format = %d", fmt); |
| rc = -1; |
| break; |
| } |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_stream_calc_offset_metadata |
| * |
| * DESCRIPTION: calculate metadata frame offset based on format and |
| * padding information |
| * |
| * PARAMETERS : |
| * @dim : image dimension |
| * @padding : padding information |
| * @buf_planes : [out] buffer plane information |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_stream_calc_offset_metadata(cam_dimension_t *dim, |
| cam_padding_info_t *padding, |
| cam_stream_buf_plane_info_t *buf_planes) |
| { |
| int32_t rc = 0; |
| buf_planes->plane_info.num_planes = 1; |
| buf_planes->plane_info.mp[0].offset = 0; |
| buf_planes->plane_info.mp[0].len = |
| PAD_TO_SIZE((uint32_t)(dim->width * dim->height), |
| padding->plane_padding); |
| buf_planes->plane_info.frame_len = |
| buf_planes->plane_info.mp[0].len; |
| |
| buf_planes->plane_info.mp[0].offset_x =0; |
| buf_planes->plane_info.mp[0].offset_y = 0; |
| buf_planes->plane_info.mp[0].stride = dim->width; |
| buf_planes->plane_info.mp[0].scanline = dim->height; |
| buf_planes->plane_info.mp[0].width = dim->width; |
| buf_planes->plane_info.mp[0].height = dim->height; |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_stream_calc_offset_analysis |
| * |
| * DESCRIPTION: calculate analysis frame offset based on format and |
| * padding information |
| * |
| * PARAMETERS : |
| * @fmt : image format |
| * @dim : image dimension |
| * @padding : padding information |
| * @buf_planes : [out] buffer plane information |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_stream_calc_offset_analysis(cam_format_t fmt, |
| cam_dimension_t *dim, |
| cam_padding_info_t *padding, |
| cam_stream_buf_plane_info_t *buf_planes) |
| { |
| int32_t rc = 0; |
| int32_t offset_x = 0, offset_y = 0; |
| int32_t stride, scanline; |
| |
| /* Clip to minimum supported bytes per line */ |
| if ((uint32_t)dim->width < padding->min_stride) { |
| stride = (int32_t)padding->min_stride; |
| } else { |
| stride = dim->width; |
| } |
| |
| if ((uint32_t)dim->height < padding->min_scanline) { |
| scanline = (int32_t)padding->min_scanline; |
| } else { |
| scanline = dim->height; |
| } |
| |
| stride = PAD_TO_SIZE(stride, padding->width_padding); |
| scanline = PAD_TO_SIZE(scanline, padding->height_padding); |
| |
| switch (fmt) { |
| case CAM_FORMAT_YUV_420_NV12: |
| case CAM_FORMAT_YUV_420_NV21: |
| /* 2 planes: Y + CbCr */ |
| buf_planes->plane_info.num_planes = 2; |
| |
| buf_planes->plane_info.mp[0].len = |
| PAD_TO_SIZE((uint32_t)(stride * scanline), |
| padding->plane_padding); |
| buf_planes->plane_info.mp[0].offset = |
| PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y), |
| padding->plane_padding); |
| buf_planes->plane_info.mp[0].offset_x = offset_x; |
| buf_planes->plane_info.mp[0].offset_y = offset_y; |
| buf_planes->plane_info.mp[0].stride = stride; |
| buf_planes->plane_info.mp[0].scanline = scanline; |
| buf_planes->plane_info.mp[0].width = dim->width; |
| buf_planes->plane_info.mp[0].height = dim->height; |
| |
| scanline = scanline / 2; |
| buf_planes->plane_info.mp[1].len = |
| PAD_TO_SIZE((uint32_t)(stride * scanline), |
| padding->plane_padding); |
| buf_planes->plane_info.mp[1].offset = |
| PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y), |
| padding->plane_padding); |
| buf_planes->plane_info.mp[1].offset_x = offset_x; |
| buf_planes->plane_info.mp[1].offset_y = offset_y; |
| buf_planes->plane_info.mp[1].stride = stride; |
| buf_planes->plane_info.mp[1].scanline = scanline; |
| buf_planes->plane_info.mp[1].width = dim->width; |
| buf_planes->plane_info.mp[1].height = dim->height / 2; |
| |
| buf_planes->plane_info.frame_len = |
| PAD_TO_SIZE(buf_planes->plane_info.mp[0].len + |
| buf_planes->plane_info.mp[1].len, |
| CAM_PAD_TO_4K); |
| break; |
| case CAM_FORMAT_YUV_420_YV12: |
| /* 3 planes: Y + Cr + Cb */ |
| buf_planes->plane_info.num_planes = 3; |
| |
| buf_planes->plane_info.mp[0].offset = |
| PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y), |
| padding->plane_padding); |
| buf_planes->plane_info.mp[0].len = |
| PAD_TO_SIZE((uint32_t)(stride * scanline), |
| padding->plane_padding); |
| buf_planes->plane_info.mp[0].offset_x = offset_x; |
| buf_planes->plane_info.mp[0].offset_y = offset_y; |
| buf_planes->plane_info.mp[0].stride = stride; |
| buf_planes->plane_info.mp[0].scanline = scanline; |
| buf_planes->plane_info.mp[0].width = dim->width; |
| buf_planes->plane_info.mp[0].height = dim->height; |
| |
| stride = PAD_TO_SIZE(stride / 2, CAM_PAD_TO_16); |
| scanline = scanline / 2; |
| buf_planes->plane_info.mp[1].offset = |
| PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y), |
| padding->plane_padding); |
| buf_planes->plane_info.mp[1].len = |
| PAD_TO_SIZE((uint32_t)(stride * scanline), |
| padding->plane_padding); |
| buf_planes->plane_info.mp[1].offset_x = offset_x; |
| buf_planes->plane_info.mp[1].offset_y = offset_y; |
| buf_planes->plane_info.mp[1].stride = stride; |
| buf_planes->plane_info.mp[1].scanline = scanline; |
| buf_planes->plane_info.mp[1].width = dim->width / 2; |
| buf_planes->plane_info.mp[1].height = dim->height / 2; |
| |
| buf_planes->plane_info.mp[2].offset = |
| PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y), |
| padding->plane_padding); |
| buf_planes->plane_info.mp[2].len = |
| PAD_TO_SIZE((uint32_t)(stride * scanline), |
| padding->plane_padding); |
| buf_planes->plane_info.mp[2].offset_x = offset_x; |
| buf_planes->plane_info.mp[2].offset_y = offset_y; |
| buf_planes->plane_info.mp[2].stride = stride; |
| buf_planes->plane_info.mp[2].scanline = scanline; |
| buf_planes->plane_info.mp[2].width = dim->width / 2; |
| buf_planes->plane_info.mp[2].height = dim->height / 2; |
| |
| buf_planes->plane_info.frame_len = |
| PAD_TO_SIZE(buf_planes->plane_info.mp[0].len + |
| buf_planes->plane_info.mp[1].len + |
| buf_planes->plane_info.mp[2].len, |
| CAM_PAD_TO_4K); |
| break; |
| case CAM_FORMAT_YUV_422_NV16: |
| case CAM_FORMAT_YUV_422_NV61: |
| /* 2 planes: Y + CbCr */ |
| buf_planes->plane_info.num_planes = 2; |
| buf_planes->plane_info.mp[0].len = |
| PAD_TO_SIZE((uint32_t)(stride * scanline), |
| padding->plane_padding); |
| buf_planes->plane_info.mp[0].offset = |
| PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y), |
| padding->plane_padding); |
| buf_planes->plane_info.mp[0].offset_x = offset_x; |
| buf_planes->plane_info.mp[0].offset_y = offset_y; |
| buf_planes->plane_info.mp[0].stride = stride; |
| buf_planes->plane_info.mp[0].scanline = scanline; |
| buf_planes->plane_info.mp[0].width = dim->width; |
| buf_planes->plane_info.mp[0].height = dim->height; |
| |
| buf_planes->plane_info.mp[1].len = |
| PAD_TO_SIZE((uint32_t)(stride * scanline), |
| padding->plane_padding); |
| buf_planes->plane_info.mp[1].offset = |
| PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y), |
| padding->plane_padding); |
| buf_planes->plane_info.mp[1].offset_x = offset_x; |
| buf_planes->plane_info.mp[1].offset_y = offset_y; |
| buf_planes->plane_info.mp[1].stride = stride; |
| buf_planes->plane_info.mp[1].scanline = scanline; |
| buf_planes->plane_info.mp[1].width = dim->width; |
| buf_planes->plane_info.mp[1].height = dim->height; |
| |
| buf_planes->plane_info.frame_len = PAD_TO_SIZE( |
| buf_planes->plane_info.mp[0].len + buf_planes->plane_info.mp[1].len, |
| CAM_PAD_TO_4K); |
| break; |
| case CAM_FORMAT_Y_ONLY: |
| buf_planes->plane_info.num_planes = 1; |
| |
| buf_planes->plane_info.mp[0].len = |
| PAD_TO_SIZE((uint32_t)(stride * scanline), |
| padding->plane_padding); |
| buf_planes->plane_info.mp[0].offset = |
| PAD_TO_SIZE((uint32_t)(offset_x + stride * offset_y), |
| padding->plane_padding); |
| buf_planes->plane_info.mp[0].offset_x = offset_x; |
| buf_planes->plane_info.mp[0].offset_y = offset_y; |
| buf_planes->plane_info.mp[0].stride = stride; |
| buf_planes->plane_info.mp[0].scanline = scanline; |
| buf_planes->plane_info.mp[0].width = dim->width; |
| buf_planes->plane_info.mp[0].height = dim->height; |
| buf_planes->plane_info.frame_len = |
| PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K); |
| break; |
| case CAM_FORMAT_YUV_420_NV12_VENUS: |
| #ifdef VENUS_PRESENT |
| // using Venus |
| stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, dim->width); |
| scanline = VENUS_Y_SCANLINES(COLOR_FMT_NV12, dim->height); |
| |
| buf_planes->plane_info.frame_len = |
| VENUS_BUFFER_SIZE(COLOR_FMT_NV12, stride, scanline); |
| buf_planes->plane_info.num_planes = 2; |
| buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline); |
| buf_planes->plane_info.mp[0].offset = 0; |
| buf_planes->plane_info.mp[0].offset_x =0; |
| buf_planes->plane_info.mp[0].offset_y = 0; |
| buf_planes->plane_info.mp[0].stride = stride; |
| buf_planes->plane_info.mp[0].scanline = scanline; |
| buf_planes->plane_info.mp[0].width = dim->width; |
| buf_planes->plane_info.mp[0].height = dim->height; |
| stride = VENUS_UV_STRIDE(COLOR_FMT_NV12, dim->width); |
| scanline = VENUS_UV_SCANLINES(COLOR_FMT_NV12, dim->height); |
| buf_planes->plane_info.mp[1].len = |
| buf_planes->plane_info.frame_len - buf_planes->plane_info.mp[0].len; |
| buf_planes->plane_info.mp[1].offset = 0; |
| buf_planes->plane_info.mp[1].offset_x =0; |
| buf_planes->plane_info.mp[1].offset_y = 0; |
| buf_planes->plane_info.mp[1].stride = stride; |
| buf_planes->plane_info.mp[1].scanline = scanline; |
| buf_planes->plane_info.mp[1].width = dim->width; |
| buf_planes->plane_info.mp[1].height = dim->height / 2; |
| #else |
| LOGE("Venus hardware not avail, cannot use this format"); |
| rc = -1; |
| #endif |
| break; |
| case CAM_FORMAT_YUV_420_NV21_VENUS: |
| #ifdef VENUS_PRESENT |
| // using Venus |
| stride = VENUS_Y_STRIDE(COLOR_FMT_NV21, dim->width); |
| scanline = VENUS_Y_SCANLINES(COLOR_FMT_NV21, dim->height); |
| |
| buf_planes->plane_info.frame_len = |
| VENUS_BUFFER_SIZE(COLOR_FMT_NV21, stride, scanline); |
| buf_planes->plane_info.num_planes = 2; |
| buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline); |
| buf_planes->plane_info.mp[0].offset = 0; |
| buf_planes->plane_info.mp[0].offset_x =0; |
| buf_planes->plane_info.mp[0].offset_y = 0; |
| buf_planes->plane_info.mp[0].stride = stride; |
| buf_planes->plane_info.mp[0].scanline = scanline; |
| buf_planes->plane_info.mp[0].width = dim->width; |
| buf_planes->plane_info.mp[0].height = dim->height; |
| stride = VENUS_UV_STRIDE(COLOR_FMT_NV21, dim->width); |
| scanline = VENUS_UV_SCANLINES(COLOR_FMT_NV21, dim->height); |
| buf_planes->plane_info.mp[1].len = |
| buf_planes->plane_info.frame_len - buf_planes->plane_info.mp[0].len; |
| buf_planes->plane_info.mp[1].offset = 0; |
| buf_planes->plane_info.mp[1].offset_x =0; |
| buf_planes->plane_info.mp[1].offset_y = 0; |
| buf_planes->plane_info.mp[1].stride = stride; |
| buf_planes->plane_info.mp[1].scanline = scanline; |
| buf_planes->plane_info.mp[1].width = dim->width; |
| buf_planes->plane_info.mp[1].height = dim->height / 2; |
| #else |
| LOGE("Venus hardware not avail, cannot use this format"); |
| rc = -1; |
| #endif |
| break; |
| default: |
| LOGE("Invalid cam_format for anlysis %d", |
| fmt); |
| rc = -1; |
| break; |
| } |
| |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_stream_calc_offset_postproc |
| * |
| * DESCRIPTION: calculate postprocess frame offset |
| * |
| * PARAMETERS : |
| * @stream_info: ptr to stream info |
| * @padding : padding information |
| * @plns : [out] buffer plane information |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_stream_calc_offset_postproc(cam_stream_info_t *stream_info, |
| cam_padding_info_t *padding, |
| cam_stream_buf_plane_info_t *plns) |
| { |
| int32_t rc = 0; |
| cam_stream_type_t type = CAM_STREAM_TYPE_DEFAULT; |
| if (stream_info->reprocess_config.pp_type == CAM_OFFLINE_REPROCESS_TYPE) { |
| type = stream_info->reprocess_config.offline.input_type; |
| if (CAM_STREAM_TYPE_DEFAULT == type) { |
| if (plns->plane_info.frame_len == 0) { |
| // take offset from input source |
| *plns = stream_info->reprocess_config.offline.input_buf_planes; |
| return rc; |
| } |
| } else { |
| type = stream_info->reprocess_config.offline.input_type; |
| } |
| } else { |
| type = stream_info->reprocess_config.online.input_stream_type; |
| } |
| |
| switch (type) { |
| case CAM_STREAM_TYPE_PREVIEW: |
| rc = mm_stream_calc_offset_preview(stream_info, |
| &stream_info->dim, |
| padding, |
| plns); |
| break; |
| case CAM_STREAM_TYPE_POSTVIEW: |
| rc = mm_stream_calc_offset_post_view(stream_info->fmt, |
| &stream_info->dim, |
| plns); |
| break; |
| case CAM_STREAM_TYPE_SNAPSHOT: |
| case CAM_STREAM_TYPE_CALLBACK: |
| rc = mm_stream_calc_offset_snapshot(stream_info->fmt, |
| &stream_info->dim, |
| padding, |
| plns); |
| break; |
| case CAM_STREAM_TYPE_VIDEO: |
| rc = mm_stream_calc_offset_video(stream_info->fmt, |
| &stream_info->dim, plns); |
| break; |
| case CAM_STREAM_TYPE_RAW: |
| rc = mm_stream_calc_offset_raw(stream_info->fmt, |
| &stream_info->dim, |
| padding, |
| plns); |
| break; |
| case CAM_STREAM_TYPE_ANALYSIS: |
| rc = mm_stream_calc_offset_analysis(stream_info->fmt, |
| &stream_info->dim, |
| padding, |
| plns); |
| break; |
| case CAM_STREAM_TYPE_METADATA: |
| rc = mm_stream_calc_offset_metadata(&stream_info->dim, |
| padding, |
| plns); |
| break; |
| case CAM_STREAM_TYPE_OFFLINE_PROC: |
| rc = mm_stream_calc_offset_snapshot(stream_info->fmt, |
| &stream_info->dim, padding, plns); |
| break; |
| default: |
| LOGE("not supported for stream type %d", |
| type); |
| rc = -1; |
| break; |
| } |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_stream_calc_lcm |
| * |
| * DESCRIPTION: calculate LCM of two numbers |
| * |
| * PARAMETERS : |
| * @num1 : number 1 |
| * @num2 : number 2 |
| * |
| * RETURN : uint32_t type |
| * |
| *===========================================================================*/ |
| uint32_t mm_stream_calc_lcm(int32_t num1, int32_t num2) |
| { |
| uint32_t lcm = 0; |
| uint32_t temp = 0; |
| |
| if ((num1 < 1) && (num2 < 1)) { |
| return 0; |
| } else if (num1 < 1) { |
| return num2; |
| } else if (num2 < 1) { |
| return num1; |
| } |
| |
| if (num1 > num2) { |
| lcm = num1; |
| } else { |
| lcm = num2; |
| } |
| temp = lcm; |
| |
| while (1) { |
| if (((lcm%num1) == 0) && ((lcm%num2) == 0)) { |
| break; |
| } |
| lcm += temp; |
| } |
| return lcm; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_stream_calc_offset |
| * |
| * DESCRIPTION: calculate frame offset based on format and padding information |
| * |
| * PARAMETERS : |
| * @my_obj : stream object |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_stream_calc_offset(mm_stream_t *my_obj) |
| { |
| int32_t rc = 0; |
| |
| cam_dimension_t dim = my_obj->stream_info->dim; |
| if (my_obj->stream_info->pp_config.feature_mask & CAM_QCOM_FEATURE_ROTATION && |
| my_obj->stream_info->stream_type != CAM_STREAM_TYPE_VIDEO) { |
| if (my_obj->stream_info->pp_config.rotation == ROTATE_90 || |
| my_obj->stream_info->pp_config.rotation == ROTATE_270) { |
| // rotated by 90 or 270, need to switch width and height |
| dim.width = my_obj->stream_info->dim.height; |
| dim.height = my_obj->stream_info->dim.width; |
| } |
| } |
| |
| switch (my_obj->stream_info->stream_type) { |
| case CAM_STREAM_TYPE_PREVIEW: |
| rc = mm_stream_calc_offset_preview(my_obj->stream_info, |
| &dim, |
| &my_obj->padding_info, |
| &my_obj->stream_info->buf_planes); |
| break; |
| case CAM_STREAM_TYPE_POSTVIEW: |
| rc = mm_stream_calc_offset_post_view(my_obj->stream_info->fmt, |
| &dim, |
| &my_obj->stream_info->buf_planes); |
| break; |
| case CAM_STREAM_TYPE_SNAPSHOT: |
| case CAM_STREAM_TYPE_CALLBACK: |
| rc = mm_stream_calc_offset_snapshot(my_obj->stream_info->fmt, |
| &dim, |
| &my_obj->padding_info, |
| &my_obj->stream_info->buf_planes); |
| break; |
| case CAM_STREAM_TYPE_OFFLINE_PROC: |
| rc = mm_stream_calc_offset_postproc(my_obj->stream_info, |
| &my_obj->padding_info, |
| &my_obj->stream_info->buf_planes); |
| break; |
| case CAM_STREAM_TYPE_VIDEO: |
| rc = mm_stream_calc_offset_video(my_obj->stream_info->fmt, |
| &dim, &my_obj->stream_info->buf_planes); |
| break; |
| case CAM_STREAM_TYPE_RAW: |
| rc = mm_stream_calc_offset_raw(my_obj->stream_info->fmt, |
| &dim, |
| &my_obj->padding_info, |
| &my_obj->stream_info->buf_planes); |
| break; |
| case CAM_STREAM_TYPE_ANALYSIS: |
| rc = mm_stream_calc_offset_analysis(my_obj->stream_info->fmt, |
| &dim, |
| &my_obj->padding_info, |
| &my_obj->stream_info->buf_planes); |
| break; |
| case CAM_STREAM_TYPE_METADATA: |
| rc = mm_stream_calc_offset_metadata(&dim, |
| &my_obj->padding_info, |
| &my_obj->stream_info->buf_planes); |
| break; |
| default: |
| LOGE("not supported for stream type %d", |
| my_obj->stream_info->stream_type); |
| rc = -1; |
| break; |
| } |
| |
| my_obj->frame_offset = my_obj->stream_info->buf_planes.plane_info; |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_stream_sync_info |
| * |
| * DESCRIPTION: synchronize stream information with server |
| * |
| * PARAMETERS : |
| * @my_obj : stream object |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| * NOTE : assume stream info buffer is mapped to server and filled in with |
| * stream information by upper layer. This call will let server to |
| * synchornize the stream information with HAL. If server find any |
| * fields that need to be changed accroding to hardware configuration, |
| * server will modify corresponding fields so that HAL could know |
| * about it. |
| *==========================================================================*/ |
| int32_t mm_stream_sync_info(mm_stream_t *my_obj) |
| { |
| int32_t rc = 0; |
| int32_t value = 0; |
| my_obj->stream_info->stream_svr_id = my_obj->server_stream_id; |
| rc = mm_stream_calc_offset(my_obj); |
| |
| if (rc == 0) { |
| rc = mm_camera_util_s_ctrl(my_obj->fd, |
| CAM_PRIV_STREAM_INFO_SYNC, |
| &value); |
| } |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_stream_set_fmt |
| * |
| * DESCRIPTION: set stream format to kernel via v4l2 ioctl |
| * |
| * PARAMETERS : |
| * @my_obj : stream object |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_stream_set_fmt(mm_stream_t *my_obj) |
| { |
| int32_t rc = 0; |
| struct v4l2_format fmt; |
| struct msm_v4l2_format_data msm_fmt; |
| int i; |
| |
| LOGD("E, my_handle = 0x%x, fd = %d, state = %d", |
| my_obj->my_hdl, my_obj->fd, my_obj->state); |
| |
| if (my_obj->stream_info->dim.width == 0 || |
| my_obj->stream_info->dim.height == 0) { |
| LOGE("invalid input[w=%d,h=%d,fmt=%d]\n", |
| my_obj->stream_info->dim.width, |
| my_obj->stream_info->dim.height, |
| my_obj->stream_info->fmt); |
| return -1; |
| } |
| |
| memset(&fmt, 0, sizeof(fmt)); |
| memset(&msm_fmt, 0, sizeof(msm_fmt)); |
| fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| msm_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| |
| |
| msm_fmt.width = (unsigned int)my_obj->stream_info->dim.width; |
| msm_fmt.height = (unsigned int)my_obj->stream_info->dim.height; |
| msm_fmt.pixelformat = mm_stream_get_v4l2_fmt(my_obj->stream_info->fmt); |
| |
| if (my_obj->stream_info->streaming_mode != CAM_STREAMING_MODE_BATCH) { |
| msm_fmt.num_planes = (unsigned char)my_obj->frame_offset.num_planes; |
| for (i = 0; i < msm_fmt.num_planes; i++) { |
| msm_fmt.plane_sizes[i] = my_obj->frame_offset.mp[i].len; |
| } |
| } else { |
| msm_fmt.num_planes = 1; |
| msm_fmt.plane_sizes[0] = my_obj->stream_info->user_buf_info.size; |
| } |
| |
| memcpy(fmt.fmt.raw_data, &msm_fmt, sizeof(msm_fmt)); |
| rc = ioctl(my_obj->fd, VIDIOC_S_FMT, &fmt); |
| if (rc < 0) { |
| LOGE("ioctl failed %d, errno %d", rc, errno); |
| } |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_stream_buf_done |
| * |
| * DESCRIPTION: enqueue buffer back to kernel |
| * |
| * PARAMETERS : |
| * @my_obj : stream object |
| * @frame : frame to be enqueued back to kernel |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_stream_buf_done(mm_stream_t * my_obj, |
| mm_camera_buf_def_t *frame) |
| { |
| int32_t rc = 0; |
| LOGD("E, my_handle = 0x%x, fd = %d, state = %d", |
| my_obj->my_hdl, my_obj->fd, my_obj->state); |
| |
| pthread_mutex_lock(&my_obj->buf_lock); |
| if (my_obj->stream_info->streaming_mode == CAM_STREAMING_MODE_BATCH) { |
| rc = mm_stream_write_user_buf(my_obj, frame); |
| } else if(my_obj->buf_status[frame->buf_idx].buf_refcnt == 0) { |
| LOGD("Error Trying to free second time?(idx=%d) count=%d\n", |
| frame->buf_idx, |
| my_obj->buf_status[frame->buf_idx].buf_refcnt); |
| rc = -1; |
| } else { |
| my_obj->buf_status[frame->buf_idx].buf_refcnt--; |
| if (0 == my_obj->buf_status[frame->buf_idx].buf_refcnt) { |
| LOGD("<DEBUG> : Buf done for buffer:%d, stream:%d", frame->buf_idx, frame->stream_type); |
| rc = mm_stream_qbuf(my_obj, frame); |
| if(rc < 0) { |
| LOGE("mm_camera_stream_qbuf(idx=%d) err=%d\n", |
| frame->buf_idx, rc); |
| } else { |
| my_obj->buf_status[frame->buf_idx].in_kernel = 1; |
| } |
| }else{ |
| LOGD("<DEBUG> : Still ref count pending count :%d", |
| my_obj->buf_status[frame->buf_idx].buf_refcnt); |
| LOGD("<DEBUG> : for buffer:%p:%d", |
| my_obj, frame->buf_idx); |
| } |
| } |
| pthread_mutex_unlock(&my_obj->buf_lock); |
| return rc; |
| } |
| |
| |
| /*=========================================================================== |
| * FUNCTION : mm_stream_get_queued_buf_count |
| * |
| * DESCRIPTION: return queued buffer count |
| * |
| * PARAMETERS : |
| * @my_obj : stream object |
| * |
| * RETURN : queued buffer count |
| *==========================================================================*/ |
| int32_t mm_stream_get_queued_buf_count(mm_stream_t *my_obj) |
| { |
| int32_t rc = 0; |
| LOGD("E, my_handle = 0x%x, fd = %d, state = %d", |
| my_obj->my_hdl, my_obj->fd, my_obj->state); |
| pthread_mutex_lock(&my_obj->buf_lock); |
| rc = my_obj->queued_buffer_count; |
| pthread_mutex_unlock(&my_obj->buf_lock); |
| return rc; |
| } |
| |
| /*=========================================================================== |
| * FUNCTION : mm_stream_reg_buf_cb |
| * |
| * DESCRIPTION: Allow other stream to register dataCB at this stream. |
| * |
| * PARAMETERS : |
| * @my_obj : stream object |
| * @val : callback function to be registered |
| * |
| * RETURN : int32_t type of status |
| * 0 -- success |
| * -1 -- failure |
| *==========================================================================*/ |
| int32_t mm_stream_reg_buf_cb(mm_stream_t *my_obj, |
| mm_stream_data_cb_t val) |
| { |
| int32_t rc = -1; |
| uint8_t i; |
| LOGD("E, my_handle = 0x%x, fd = %d, state = %d", |
| my_obj->my_hdl, my_obj->fd, my_obj->state); |
| |
| pthread_mutex_lock(&my_obj->cb_lock); |
| for (i=0 ;i < MM_CAMERA_STREAM_BUF_CB_MAX; i++) { |
| if(NULL == my_obj->buf_cb[i].cb) { |
| my_obj->buf_cb[i] = val; |
| rc = 0; |
| break; |
| } |
| } |
| pthread_mutex_unlock(&my_obj->cb_lock); |
| |
| return rc; |
| } |