/* * Copyright (c) Hisilicon Technologies Co., Ltd. 2020-2020. All rights reserved. * Description: convert iapi layer struct to drv layer * Author: sdk * Create: 2020-04-03 */ #include "venc_convert.h" #include "td_type.h" #include "securec.h" #include "soc_errno.h" #include "drv_ioctl_venc.h" #include "uapi_venc.h" #include "mpi_venc.h" #define VENC_INVALID_HANDLE (-1ll) typedef struct { ext_drv_pixel_format drv_pix_frm; uapi_video_pixel_format iapi_pix_frm; } venc_pix_frm_map; static ext_venc_h264e_nalu_type g_data_tpye_map_h264[UAPI_VENC_H264_NALU_MAX] = { EXT_VENC_H264E_NALU_SPS, EXT_VENC_H264E_NALU_PPS, EXT_VENC_H264E_NALU_SEI, EXT_VENC_H264E_NALU_ISLICE, EXT_VENC_H264E_NALU_PSLICE, EXT_VENC_H264E_NALU_MAX }; static ext_venc_h265e_nalu_type g_data_tpye_map_h265[UAPI_VENC_H265_NALU_MAX] = { EXT_VENC_H265E_NALU_VPS, EXT_VENC_H265E_NALU_SPS, EXT_VENC_H265E_NALU_PPS, EXT_VENC_H265E_NALU_SEI, EXT_VENC_H265E_NALU_PSLICE, EXT_VENC_H265E_NALU_ISLICE, EXT_VENC_H265E_NALU_MAX }; static const venc_pix_frm_map g_pix_frm_map_tab[] = { {EXT_DRV_PIXEL_FMT_NV61_2X1, UAPI_FORMAT_YUV_SEMIPLANAR_422_VU}, {EXT_DRV_PIXEL_FMT_NV12, UAPI_FORMAT_YUV_SEMIPLANAR_420_UV}, {EXT_DRV_PIXEL_FMT_NV21, UAPI_FORMAT_YUV_SEMIPLANAR_420_VU}, {EXT_DRV_PIXEL_FMT_NV80, UAPI_FORMAT_YUV_SEMIPLANAR_400}, {EXT_DRV_PIXEL_FMT_NV12_411, UAPI_FORMAT_YUV_SEMIPLANAR_411_UV}, {EXT_DRV_PIXEL_FMT_NV61, UAPI_FORMAT_YUV_SEMIPLANAR_422_VU}, {EXT_DRV_PIXEL_FMT_NV42, UAPI_FORMAT_YUV_SEMIPLANAR_444_VU}, {EXT_DRV_PIXEL_FMT_UYVY, UAPI_FORMAT_YUV_PACKAGE_UYVY}, {EXT_DRV_PIXEL_FMT_YUYV, UAPI_FORMAT_YUV_PACKAGE_YUYV}, {EXT_DRV_PIXEL_FMT_YVYU, UAPI_FORMAT_YUV_PACKAGE_YVYU}, {EXT_DRV_PIXEL_FMT_YUV400, UAPI_FORMAT_YUV_PLANAR_400}, {EXT_DRV_PIXEL_FMT_YUV411, UAPI_FORMAT_YUV_PLANAR_411_UV}, {EXT_DRV_PIXEL_FMT_YUV420P, UAPI_FORMAT_YUV_PLANAR_420_UV}, {EXT_DRV_PIXEL_FMT_YUV422_1X2, UAPI_FORMAT_YUV_PLANAR_422_UV}, /* EXT_DRV_PIXEL_FMT_YUV422_2X1 --> UAPI_FORMAT_YUV_PLANAR_422_2X1 */ {EXT_DRV_PIXEL_FMT_YUV_444, UAPI_FORMAT_YUV_PLANAR_444_UV}, {EXT_DRV_PIXEL_FMT_YUV410P, UAPI_FORMAT_YUV_PLANAR_410_UV}, {EXT_DRV_PIXEL_FMT_ARGB8888, UAPI_FORMAT_ARGB8888}, {EXT_DRV_PIXEL_MAX, UAPI_FORMAT_MAX} }; static uapi_video_scan_type get_iapi_scan_type_from_drv(ext_drv_sample_type drv_scan_type) { uapi_video_scan_type iapi_scan_type; switch (drv_scan_type) { case EXT_DRV_SAMPLE_TYPE_UNKNOWN: iapi_scan_type = UAPI_VIDEO_SCAN_TYPE_UNKNOWN; break; case EXT_DRV_SAMPLE_TYPE_PROGRESSIVE: iapi_scan_type = UAPI_VIDEO_SCAN_TYPE_PROGRESSIVE; break; case EXT_DRV_SAMPLE_TYPE_INTERLACE: iapi_scan_type = UAPI_VIDEO_SCAN_TYPE_INTERLACE; break; default: iapi_scan_type = UAPI_VIDEO_SCAN_TYPE_MAX; break; } return iapi_scan_type; } static td_void set_video_format_nv(ext_drv_pixel_format pix_format, uapi_video_pixel_format *video_format) { td_u32 i; for (i = 0; g_pix_frm_map_tab[i].drv_pix_frm != EXT_DRV_PIXEL_MAX; i++) { if (pix_format == g_pix_frm_map_tab[i].drv_pix_frm) { *video_format = g_pix_frm_map_tab[i].iapi_pix_frm; break; } } if (g_pix_frm_map_tab[i].drv_pix_frm == EXT_DRV_PIXEL_MAX) { *video_format = UAPI_FORMAT_MAX; } } static ext_drv_sample_type get_drv_scan_type_from_unf(uapi_video_scan_type iapi_scan_type) { ext_drv_sample_type drv_scan_type; switch (iapi_scan_type) { case UAPI_VIDEO_SCAN_TYPE_UNKNOWN: drv_scan_type = EXT_DRV_SAMPLE_TYPE_UNKNOWN; break; case UAPI_VIDEO_SCAN_TYPE_PROGRESSIVE: drv_scan_type = EXT_DRV_SAMPLE_TYPE_PROGRESSIVE; break; case UAPI_VIDEO_SCAN_TYPE_INTERLACE: drv_scan_type = EXT_DRV_SAMPLE_TYPE_INTERLACE; break; default: drv_scan_type = EXT_DRV_SAMPLE_TYPE_MAX; break; } return drv_scan_type; } static td_void convert_hdr_frame_info_user_to_drv(ext_drv_video_frame *drv_image, const uapi_video_frame_info *user_image) { switch (user_image->hdr_type) { case UAPI_HDR_TYPE_SDR: drv_image->hdr_type = EXT_DRV_HDR_TYPE_SDR; break; case UAPI_HDR_TYPE_HDR10: drv_image->hdr_type = EXT_DRV_HDR_TYPE_HDR10; venc_check_neq_void_ret(memcpy_s(&drv_image->hdr_info.hdr10_info, sizeof(ext_drv_hdr_static_metadata), &user_image->hdr_metadata.hdr10_metadata, sizeof(uapi_hdr_static_metadata)), EOK); break; case UAPI_HDR_TYPE_HLG: drv_image->hdr_type = EXT_DRV_HDR_TYPE_HLG; venc_check_neq_void_ret(memcpy_s(&drv_image->hdr_info.hlg_info, sizeof(ext_drv_hdr_hlg_metadata), &user_image->hdr_metadata.hlg_metadata, sizeof(uapi_hdr_hlg_metadata)), EOK); break; case UAPI_HDR_TYPE_CUVA: drv_image->hdr_type = EXT_DRV_HDR_TYPE_CUVA; venc_check_neq_void_ret(memcpy_s(&drv_image->hdr_info.cuva_info, sizeof(ext_drv_hdr_cuva_metadata), &user_image->hdr_metadata.cuva_metadata, sizeof(uapi_hdr_cuva_metadata)), EOK); break; case UAPI_HDR_TYPE_JTP_SL_HDR: drv_image->hdr_type = EXT_DRV_HDR_TYPE_JTP_SL_HDR; venc_check_neq_void_ret(memcpy_s(&drv_image->hdr_info.sl_hdr_info, sizeof(ext_drv_hdr_sl_metadata), &user_image->hdr_metadata.sl_hdr_metadata, sizeof(uapi_hdr_sl_metadata)), EOK); break; case UAPI_HDR_TYPE_DOLBYVISION: drv_image->hdr_type = EXT_DRV_HDR_TYPE_DOLBYVISION; venc_check_neq_void_ret(memcpy_s(&drv_image->hdr_info.dolby_info, sizeof(ext_drv_hdr_dolby_metadata), &user_image->hdr_metadata.dolby_metadata, sizeof(uapi_hdr_dolby_metadata)), EOK); break; default: drv_image->hdr_type = EXT_DRV_HDR_TYPE_MAX; break; } return; } static td_void convert_hdr_static_metadata_drv_to_unf(uapi_hdr_static_metadata *iapi_metadata, const ext_drv_hdr_static_metadata *drv_metadata) { iapi_metadata->content_available = drv_metadata->content_available; iapi_metadata->mastering_available = drv_metadata->mastering_available; iapi_metadata->content_info.max_content_light_level = drv_metadata->content_info.max_content_light_level; iapi_metadata->content_info.max_frame_average_light_level = drv_metadata->content_info.max_pic_average_light_level; iapi_metadata->mastering_info.max_display_mastering_luminance = drv_metadata->mastering_info.max_display_mastering_luminance; iapi_metadata->mastering_info.min_display_mastering_luminance = drv_metadata->mastering_info.min_display_mastering_luminance; iapi_metadata->mastering_info.white_point_x = drv_metadata->mastering_info.white_point_x; iapi_metadata->mastering_info.white_point_y = drv_metadata->mastering_info.white_point_y; venc_check_neq_void_ret(memcpy_s(iapi_metadata->mastering_info.display_primaries_x, sizeof(iapi_metadata->mastering_info.display_primaries_x), drv_metadata->mastering_info.display_primaries_x, sizeof(drv_metadata->mastering_info.display_primaries_x)), EOK); venc_check_neq_void_ret(memcpy_s(iapi_metadata->mastering_info.display_primaries_y, sizeof(iapi_metadata->mastering_info.display_primaries_y), drv_metadata->mastering_info.display_primaries_y, sizeof(drv_metadata->mastering_info.display_primaries_y)), EOK); } static td_void convert_cuva_metadata_drv_to_user(uapi_video_frame_info *user_image, const ext_drv_video_frame *drv_image) { uapi_hdr_cuva_metadata *user_metadata = &user_image->hdr_metadata.cuva_metadata; const ext_drv_hdr_cuva_metadata *drv_metadata = &drv_image->hdr_info.cuva_info; user_image->hdr_type = UAPI_HDR_TYPE_CUVA; user_metadata->static_metadata_available = drv_metadata->static_metadata_available; user_metadata->dynamic_metadata_available = drv_metadata->dynamic_metadata_available; user_metadata->dynamic_metadata.mem_addr = drv_metadata->dynamic_metadata.mem_addr; user_metadata->dynamic_metadata.data_length = drv_metadata->dynamic_metadata.data_length; convert_hdr_static_metadata_drv_to_unf(&user_metadata->static_metadata, &drv_metadata->static_metadata); } static td_void convert_sl_metadata_drv_to_user(uapi_video_frame_info *user_image, const ext_drv_video_frame *drv_image) { uapi_hdr_sl_metadata *user_metadata = &user_image->hdr_metadata.sl_hdr_metadata; const ext_drv_hdr_sl_metadata *drv_metadata = &drv_image->hdr_info.sl_hdr_info; user_image->hdr_type = UAPI_HDR_TYPE_JTP_SL_HDR; user_metadata->static_metadata_available = drv_metadata->static_metadata_available; user_metadata->dynamic_metadata_available = drv_metadata->dynamic_metadata_available; user_metadata->dynamic_metadata.mem_addr = drv_metadata->dynamic_metadata.mem_addr; user_metadata->dynamic_metadata.data_length = drv_metadata->dynamic_metadata.data_length; convert_hdr_static_metadata_drv_to_unf(&user_metadata->static_metadata, &drv_metadata->static_metadata); } static td_void convert_hdr_frame_info_drv_to_user(uapi_video_frame_info *user_image, const ext_drv_video_frame *drv_image) { switch (drv_image->hdr_type) { case EXT_DRV_HDR_TYPE_SDR: user_image->hdr_type = UAPI_HDR_TYPE_SDR; break; case EXT_DRV_HDR_TYPE_HDR10: user_image->hdr_type = UAPI_HDR_TYPE_HDR10; convert_hdr_static_metadata_drv_to_unf(&user_image->hdr_metadata.hdr10_metadata, &drv_image->hdr_info.hdr10_info); break; case EXT_DRV_HDR_TYPE_HLG: user_image->hdr_type = UAPI_HDR_TYPE_HLG; venc_check_neq_void_ret(memcpy_s(&user_image->hdr_metadata.hlg_metadata, sizeof(uapi_hdr_hlg_metadata), &drv_image->hdr_info.hlg_info, sizeof(ext_drv_hdr_hlg_metadata)), EOK); break; case EXT_DRV_HDR_TYPE_CUVA: convert_cuva_metadata_drv_to_user(user_image, drv_image); break; case EXT_DRV_HDR_TYPE_JTP_SL_HDR: convert_sl_metadata_drv_to_user(user_image, drv_image); break; case EXT_DRV_HDR_TYPE_DOLBYVISION: { uapi_hdr_dolby_metadata *user_metadata = &user_image->hdr_metadata.dolby_metadata; const ext_drv_hdr_dolby_metadata *drv_metadata = &drv_image->hdr_info.dolby_info; user_image->hdr_type = UAPI_HDR_TYPE_DOLBYVISION; user_metadata->metadata_valid = drv_metadata->metadata_valid; user_metadata->compatible = drv_metadata->compatible; user_metadata->metadata.mem_addr = drv_metadata->metadata.mem_addr; user_metadata->metadata.data_length = drv_metadata->metadata.data_length; } break; default: user_image->hdr_type = UAPI_HDR_TYPE_MAX; break; } return; } static td_void get_frame_type(uapi_video_frame_packing_type frame_packing_type, ext_drv_3d_type *frm_type) { switch (frame_packing_type) { case UAPI_FRAME_PACKING_TYPE_2D: *frm_type = EXT_DRV_3D_NONE; break; case UAPI_FRAME_PACKING_TYPE_SIDE_BY_SIDE: *frm_type = EXT_DRV_3D_SBS_HALF; break; case UAPI_FRAME_PACKING_TYPE_TOP_AND_BOTTOM: *frm_type = EXT_DRV_3D_TAB; break; case UAPI_FRAME_PACKING_TYPE_TIME_INTERLACED: *frm_type = EXT_DRV_3D_NONE; break; case UAPI_FRAME_PACKING_TYPE_FRAME_PACKING: *frm_type = EXT_DRV_3D_FPK; break; default: *frm_type = EXT_DRV_3D_MAX; break; } } static td_void get_video_format_nv(uapi_video_pixel_format video_format, ext_drv_pixel_format *pix_format) { td_u32 i; for (i = 0; g_pix_frm_map_tab[i].iapi_pix_frm != UAPI_FORMAT_MAX; i++) { if (video_format == g_pix_frm_map_tab[i].iapi_pix_frm) { *pix_format = g_pix_frm_map_tab[i].drv_pix_frm; break; } } if (g_pix_frm_map_tab[i].iapi_pix_frm == UAPI_FORMAT_MAX) { *pix_format = EXT_DRV_PIXEL_MAX; } } static td_void venc_iapi_profile_to_venc_profile(const uapi_venc_attr *user_attr, ext_venc_chan_info *drv_attr) { switch (user_attr->profile.h264_profile) { case UAPI_H264_PROFILE_BASELINE: drv_attr->profile = EXT_VENC_H264_PROFILE_BASELINE; break; case UAPI_H264_PROFILE_MAIN: drv_attr->profile = EXT_VENC_H264_PROFILE_MAIN; break; case UAPI_H264_PROFILE_EXTENDED: drv_attr->profile = EXT_VENC_H264_PROFILE_EXTENDED; break; case UAPI_H264_PROFILE_HIGH: drv_attr->profile = EXT_VENC_H264_PROFILE_HIGH; break; case UAPI_H264_PROFILE_MAX: drv_attr->profile = EXT_VENC_H264_PROFILE_MAX; break; default: break; } } static td_void venc_iapi_split_mode_to_venc_mode(const uapi_venc_attr *user_attr, ext_venc_chan_info *drv_attr) { switch (user_attr->slice_split.mode) { case UAPI_VENC_SPLIT_BY_BYTE: drv_attr->config.slice_split.mode = EXT_VENC_SPLIT_BY_BYTE; break; case UAPI_VENC_SPLIT_BY_LINE: drv_attr->config.slice_split.mode = EXT_VENC_SPLIT_BY_LINE; break; case UAPI_VENC_SPLIT_MAX: drv_attr->config.slice_split.mode = EXT_VENC_SPLIT_MAX; break; default: break; } } static td_void venc_iapi_gop_mode_to_venc_mode(const uapi_venc_attr *user_attr, ext_venc_chan_info *drv_attr) { switch (user_attr->gop_mode) { case UAPI_VENC_GOP_MODE_NORMALP: drv_attr->gop_mode = EXT_VENC_GOP_MODE_NORMALP; break; case UAPI_VENC_GOP_MODE_DUALP: drv_attr->gop_mode = EXT_VENC_GOP_MODE_DUALP; break; case UAPI_VENC_GOP_MODE_SMARTP: drv_attr->gop_mode = EXT_VENC_GOP_MODE_SMARTP; break; case UAPI_VENC_GOP_MODE_MAX: drv_attr->gop_mode = EXT_VENC_GOP_MODE_MAX; break; default: break; } } td_void venc_convert_attr_user_to_drv(ext_venc_chan_info *drv_attr, const uapi_venc_attr *user_attr) { check_venc_ptr_ret_void(drv_attr); check_venc_ptr_ret_void(user_attr); if (user_attr->venc_type == UAPI_VCODEC_TYPE_H264) { drv_attr->standard = EXT_VENC_STD_H264; } else if (user_attr->venc_type == UAPI_VCODEC_TYPE_H265) { drv_attr->standard = EXT_VENC_STD_H265; } else if (user_attr->venc_type == UAPI_VCODEC_TYPE_MJPEG) { drv_attr->standard = EXT_VENC_STD_JPEG; } else { drv_attr->standard = EXT_VENC_STD_MAX; } /* FixMe: Need to distinguish between h264 and h265 */ venc_iapi_profile_to_venc_profile(user_attr, drv_attr); drv_attr->max_width = user_attr->max_width; drv_attr->max_height = user_attr->max_height; drv_attr->strm_buf_size = user_attr->stream_buf_size; drv_attr->config.slice_split.enable = user_attr->slice_split.enable; venc_iapi_split_mode_to_venc_mode(user_attr, drv_attr); drv_attr->config.slice_split.size = user_attr->slice_split.size; drv_attr->secure = user_attr->secure; venc_iapi_gop_mode_to_venc_mode(user_attr, drv_attr); venc_convert_config_user_to_drv(&drv_attr->config, &user_attr->config); } td_s32 venc_convert_stream_drv_to_user(uapi_venc_stream *user_stream, const venc_ioctl_acquire_stream *drv_stream) { td_u32 i; const ext_venc_stream *stream = TD_NULL; check_venc_ptr_ret(user_stream); check_venc_ptr_ret(drv_stream); stream = &drv_stream->stream; user_stream->pts_us = stream->pts; user_stream->frame_end = stream->frame_end; user_stream->buf.size = stream->slc_len; user_stream->buf.data = u64_ptr(stream->virt_addr); user_stream->buf.buf_handle.mem_handle = drv_stream->buf_handle.mem_handle; user_stream->buf.buf_handle.addr_offset = drv_stream->buf_handle.addr_offset; if (drv_stream->protocol == VEDU_H264) { for (i = 0; i < UAPI_VENC_H264_NALU_MAX; i++) { if (g_data_tpye_map_h264[i] == stream->data_type.h264e_type) { user_stream->data_type.h264_type = i; break; } } if (i == UAPI_VENC_H264_NALU_MAX) { ext_err_venc("error h264 nalu type: %d\n", stream->data_type.h264e_type); return TD_FAILURE; } } else if (drv_stream->protocol == VEDU_H265) { for (i = 0; i < UAPI_VENC_H265_NALU_MAX; i++) { if (g_data_tpye_map_h265[i] == stream->data_type.h265e_type) { user_stream->data_type.h265_type = i; break; } } if (i == UAPI_VENC_H265_NALU_MAX) { ext_err_venc("error h265 nalu type: %d\n", stream->data_type.h265e_type); return TD_FAILURE; } } return TD_SUCCESS; } td_s32 venc_convert_stream_user_to_drv(venc_ioctl_acquire_stream *acquire_stream, const uapi_venc_stream *user_stream) { ext_venc_stream *drv_stream = TD_NULL; check_venc_ptr_ret(acquire_stream); check_venc_ptr_ret(user_stream); drv_stream = &acquire_stream->stream; drv_stream->pts = user_stream->pts_us; drv_stream->frame_end = user_stream->frame_end; drv_stream->virt_addr = ptr_u64(user_stream->buf.data); drv_stream->slc_len = user_stream->buf.size; acquire_stream->buf_handle.mem_handle = user_stream->buf.buf_handle.mem_handle; acquire_stream->buf_handle.addr_offset = user_stream->buf.buf_handle.addr_offset; if (acquire_stream->protocol == VEDU_H264) { /* If all values of an enum are greater than 0, the compiler considers the enum to be unsigned */ if (user_stream->data_type.h264_type >= UAPI_VENC_H264_NALU_MAX) { ext_err_venc("invalid h264 nalu type: %u\n", user_stream->data_type.h264_type); return TD_FAILURE; } drv_stream->data_type.h264e_type = g_data_tpye_map_h264[user_stream->data_type.h264_type]; } else if (acquire_stream->protocol == VEDU_H265) { if (user_stream->data_type.h265_type >= UAPI_VENC_H265_NALU_MAX) { ext_err_venc("invalid h265 nalu type: %u\n", user_stream->data_type.h265_type); return TD_FAILURE; } drv_stream->data_type.h265e_type = g_data_tpye_map_h265[user_stream->data_type.h265_type]; } return TD_SUCCESS; } td_void venc_convert_config_user_to_drv(ext_venc_chan_config *drv_config, const uapi_venc_config *user_config) { check_venc_ptr_ret_void(drv_config); check_venc_ptr_ret_void(user_config); drv_config->width = user_config->width; drv_config->height = user_config->height; drv_config->target_bitrate = user_config->target_bitrate; drv_config->target_frame_rate = user_config->target_frame_rate / 1000; /* 1000: frame rate convert ot driver */ drv_config->input_frame_rate = user_config->input_frame_rate / 1000; /* 1000: frame rate convert ot driver */ drv_config->gop = user_config->gop; drv_config->quick_encode = user_config->quick_encode; drv_config->priority = user_config->priority; drv_config->qfactor = user_config->qfactor; drv_config->sp_interval = user_config->sp_interval; drv_config->frm_rate_type = (ext_venc_frm_rate_type)user_config->input_frame_rate_type; } td_void venc_convert_config_drv_to_user(uapi_venc_config *user_config, const ext_venc_chan_config *drv_config) { check_venc_ptr_ret_void(drv_config); check_venc_ptr_ret_void(user_config); user_config->width = drv_config->width; user_config->height = drv_config->height; user_config->target_bitrate = drv_config->target_bitrate; user_config->target_frame_rate = drv_config->target_frame_rate * 1000; /* 1000: frame rate convert ot uapi */ user_config->input_frame_rate = drv_config->input_frame_rate * 1000; /* 1000: frame rate convert ot uapi */ user_config->gop = drv_config->gop; user_config->quick_encode = drv_config->quick_encode; user_config->priority = drv_config->priority; user_config->qfactor = drv_config->qfactor; user_config->sp_interval = drv_config->sp_interval; user_config->input_frame_rate_type = (uapi_venc_frame_rate_type)drv_config->frm_rate_type; } td_void venc_get_drv_chn_create_attr(venc_ioctl_create *venc_chn_create, const uapi_venc_attr *attr) { ext_venc_omx_private *omx_attr = TD_NULL; ext_venc_frame_drop_strategy *frm_drop_attr = TD_NULL; ext_venc_rc_param *rc_attr = TD_NULL; ext_venc_ref_param *ref_param = TD_NULL; check_venc_ptr_ret_void(venc_chn_create); check_venc_ptr_ret_void(attr); omx_attr = &venc_chn_create->attr.omx_private; frm_drop_attr = &venc_chn_create->attr.frm_drop_strategy; rc_attr = &venc_chn_create->attr.rc_param; ref_param = &venc_chn_create->attr.ref_param; venc_convert_attr_user_to_drv(&(venc_chn_create->attr), attr); venc_chn_create->omx_chan = TD_FALSE; omx_attr->auto_request_i_frame = TD_FALSE; omx_attr->prepend_sps_pps = TD_TRUE; omx_attr->omx_chan = TD_FALSE; omx_attr->control_rate_type = EXT_VENC_CONTROL_RATE_CONSTANT; frm_drop_attr->bit_rate_threshold = -1; frm_drop_attr->drop_gap = 0; frm_drop_attr->enable = TD_FALSE; frm_drop_attr->mode = EXT_VENC_FRAME_DROP_NORMAL; rc_attr->max_qp = 48; /* 48: default max QP */ rc_attr->min_qp = 16; /* 16: default min QP */ rc_attr->i_max_qp = 48; /* 48: default max QP */ rc_attr->i_min_qp = 16; /* 16: default min QP */ rc_attr->type = EXT_VENC_RC_TYPE_CBR; ref_param->base = 1; ref_param->enhance = 0; ref_param->pred_en = TD_TRUE; } static td_void get_drv_frame_para(ext_drv_video_frame *drv_image, const uapi_video_frame_info *user_image) { drv_image->frame_index = user_image->frame_index; drv_image->secure = user_image->secure_frame; drv_image->buf_addr[0].start_addr = user_image->frame_addr[0].start_addr; drv_image->buf_addr[0].y_offset = user_image->frame_addr[0].y_offset; drv_image->buf_addr[0].stride_y = user_image->frame_addr[0].stride_y; drv_image->buf_addr[0].c_offset = user_image->frame_addr[0].c_offset; drv_image->buf_addr[0].stride_c = user_image->frame_addr[0].stride_c; drv_image->buf_addr[0].cr_offset = user_image->frame_addr[0].cr_offset; drv_image->buf_addr[0].stride_cr = user_image->frame_addr[0].stride_cr; drv_image->buf_addr[1].start_addr = user_image->frame_addr[1].start_addr; drv_image->buf_addr[1].y_offset = user_image->frame_addr[1].y_offset; drv_image->buf_addr[1].stride_y = user_image->frame_addr[1].stride_y; drv_image->buf_addr[1].c_offset = user_image->frame_addr[1].c_offset; drv_image->buf_addr[1].stride_c = user_image->frame_addr[1].stride_c; drv_image->buf_addr[1].cr_offset = user_image->frame_addr[1].cr_offset; drv_image->buf_addr[1].stride_cr = user_image->frame_addr[1].stride_cr; drv_image->width = user_image->decode_width; drv_image->height = user_image->decode_height; drv_image->src_pts = user_image->src_pts; drv_image->pts = user_image->pts; drv_image->aspect_width = user_image->aspect_width; drv_image->aspect_height = user_image->aspect_height; drv_image->frame_rate = user_image->frame_rate; get_video_format_nv(user_image->video_format, &drv_image->pixel_format); drv_image->sample_type = get_drv_scan_type_from_unf(user_image->scan_type); } static ext_drv_pixel_bitwidth get_drv_bit_width(uapi_pixel_bit_depth iapi_bit_depth) { ext_drv_pixel_bitwidth drv_bit_width; switch (iapi_bit_depth) { case UAPI_PIXEL_BIT_DEPTH_DEFAULT: case UAPI_PIXEL_BIT_DEPTH_8BIT: drv_bit_width = EXT_DRV_PIXEL_BITWIDTH_8BIT; break; case UAPI_PIXEL_BIT_DEPTH_10BIT: drv_bit_width = EXT_DRV_PIXEL_BITWIDTH_10BIT; break; case UAPI_PIXEL_BIT_DEPTH_12BIT: case UAPI_PIXEL_BIT_DEPTH_16BIT: default: drv_bit_width = EXT_DRV_PIXEL_BITWIDTH_MAX; break; } return drv_bit_width; } static td_void convert_private_info_to_drv(ext_drv_video_frame *drv_image, const uapi_video_frame_info *uapi_image) { ext_vid_frm_private_info *private_info = TD_NULL; if (sizeof(uapi_image->priv_info.priv_data) < sizeof(ext_vid_frm_private_info)) { ext_err_venc("unf private size=%d smaller than private struct size=%d\n", sizeof(uapi_image->priv_info.priv_data), sizeof(ext_vid_frm_private_info)); return; } private_info = (ext_vid_frm_private_info *)uapi_image->priv_info.priv_data; drv_image->tunnel_buffer.fd_handle = private_info->tunnel_buffer.mem_handle; drv_image->tunnel_buffer.dma_handle = 0; drv_image->tunnel_buffer.offset = (td_u32)private_info->tunnel_buffer.addr_offset; drv_image->secure_info.phy_addr = private_info->secure_info.phy_addr; drv_image->secure_info.session_id = private_info->secure_info.session_id; venc_check_neq_void_ret(memcpy_s(drv_image->secure_info.hdcp_info, sizeof(drv_image->secure_info.hdcp_info), private_info->secure_info.hdcp_info, sizeof(private_info->secure_info.hdcp_info)), EOK); switch (private_info->buf_valid_mode) { case EXT_FIELD_ALL: drv_image->buf_valid_mode = EXT_DRV_FIELD_ALL; break; case EXT_FIELD_TOP: drv_image->buf_valid_mode = EXT_DRV_FIELD_TOP; break; case EXT_FIELD_BOTTOM: drv_image->buf_valid_mode = EXT_DRV_FIELD_BOTTOM; break; default: drv_image->buf_valid_mode = EXT_DRV_FIELD_MAX; break; } } td_s32 venc_convert_frame_user_to_drv(ext_drv_video_frame *drv_image, const uapi_video_frame_info *user_image) { check_venc_ptr_ret(drv_image); check_venc_ptr_ret(user_image); venc_check_neq_ret(memset_s(drv_image, sizeof(ext_drv_video_frame), 0, sizeof(ext_drv_video_frame)), TD_SUCCESS, TD_FAILURE); get_drv_frame_para(drv_image, user_image); switch (user_image->field_mode) { case UAPI_VIDEO_FIELD_ALL: drv_image->field_mode = EXT_DRV_FIELD_ALL; break; case UAPI_VIDEO_FIELD_TOP: drv_image->field_mode = EXT_DRV_FIELD_TOP; break; case UAPI_VIDEO_FIELD_BOTTOM: drv_image->field_mode = EXT_DRV_FIELD_BOTTOM; break; default: drv_image->field_mode = EXT_DRV_FIELD_MAX; break; } drv_image->top_field_first = user_image->top_field_first; drv_image->disp_rect.rect_h = (td_s32)user_image->display_height; drv_image->disp_rect.rect_w = (td_s32)user_image->display_width; drv_image->disp_rect.rect_x = (td_s32)user_image->display_center_x; drv_image->disp_rect.rect_y = (td_s32)user_image->display_center_y; get_frame_type(user_image->frame_packing_type, &drv_image->video_3d_type); drv_image->bit_width = get_drv_bit_width(user_image->bit_depth); if (drv_image->bit_width == EXT_DRV_PIXEL_BITWIDTH_MAX) { ext_err_venc("unsupport source bit depth: %d\n", user_image->bit_depth); return SOC_ERR_VENC_NOT_SUPPORT; } drv_image->flip_h = user_image->horizontal_mirror; drv_image->flip_v = user_image->vertical_mirror; drv_image->error_level = user_image->error_level; convert_private_info_to_drv(drv_image, user_image); convert_hdr_frame_info_user_to_drv(drv_image, user_image); return TD_SUCCESS; } static void get_user_frame_para(uapi_video_frame_info *iapi_image, const ext_drv_video_frame *drv_image) { venc_check_neq_void_ret(memset_s(iapi_image, sizeof(uapi_video_frame_info), 0, sizeof(uapi_video_frame_info)), TD_SUCCESS); iapi_image->frame_index = drv_image->frame_index; iapi_image->secure_frame = drv_image->secure; iapi_image->frame_addr[0].start_addr = drv_image->buf_addr[0].start_addr; iapi_image->frame_addr[0].y_offset = drv_image->buf_addr[0].y_offset; iapi_image->frame_addr[0].stride_y = drv_image->buf_addr[0].stride_y; iapi_image->frame_addr[0].c_offset = drv_image->buf_addr[0].c_offset; iapi_image->frame_addr[0].stride_c = drv_image->buf_addr[0].stride_c; iapi_image->frame_addr[0].cr_offset = drv_image->buf_addr[0].cr_offset; iapi_image->frame_addr[0].stride_cr = drv_image->buf_addr[0].stride_cr; iapi_image->frame_addr[1].start_addr = drv_image->buf_addr[1].start_addr; iapi_image->frame_addr[1].y_offset = drv_image->buf_addr[1].y_offset; iapi_image->frame_addr[1].stride_y = drv_image->buf_addr[1].stride_y; iapi_image->frame_addr[1].c_offset = drv_image->buf_addr[1].c_offset; iapi_image->frame_addr[1].stride_c = drv_image->buf_addr[1].stride_c; iapi_image->frame_addr[1].cr_offset = drv_image->buf_addr[1].cr_offset; iapi_image->frame_addr[1].stride_cr = drv_image->buf_addr[1].stride_cr; iapi_image->display_width = drv_image->width; iapi_image->display_height = drv_image->height; iapi_image->decode_width = drv_image->width; iapi_image->decode_height = drv_image->height; iapi_image->src_pts = drv_image->src_pts; iapi_image->pts = drv_image->pts; iapi_image->aspect_width = drv_image->aspect_width; iapi_image->aspect_height = drv_image->aspect_height; iapi_image->frame_rate = drv_image->frame_rate; set_video_format_nv(drv_image->pixel_format, &iapi_image->video_format); iapi_image->scan_type = get_iapi_scan_type_from_drv(drv_image->sample_type); switch (drv_image->field_mode) { case EXT_DRV_FIELD_ALL: iapi_image->field_mode = UAPI_VIDEO_FIELD_ALL; break; case EXT_DRV_FIELD_TOP: iapi_image->field_mode = UAPI_VIDEO_FIELD_TOP; break; case EXT_DRV_FIELD_BOTTOM: iapi_image->field_mode = UAPI_VIDEO_FIELD_BOTTOM; break; default: iapi_image->field_mode = UAPI_VIDEO_FIELD_MAX; break; } iapi_image->top_field_first = drv_image->top_field_first; iapi_image->display_height = (td_u32)drv_image->disp_rect.rect_h; iapi_image->display_width = (td_u32)drv_image->disp_rect.rect_w; iapi_image->display_center_x = (td_u32)drv_image->disp_rect.rect_x; iapi_image->display_center_y = (td_u32)drv_image->disp_rect.rect_y; } static uapi_pixel_bit_depth get_iapi_bit_depth(ext_drv_pixel_bitwidth drv_bit_width) { uapi_pixel_bit_depth iapi_bit_depth; switch (drv_bit_width) { case EXT_DRV_PIXEL_BITWIDTH_DEFAULT: iapi_bit_depth = UAPI_PIXEL_BIT_DEPTH_DEFAULT; break; case EXT_DRV_PIXEL_BITWIDTH_8BIT: iapi_bit_depth = UAPI_PIXEL_BIT_DEPTH_8BIT; break; case EXT_DRV_PIXEL_BITWIDTH_10BIT: iapi_bit_depth = UAPI_PIXEL_BIT_DEPTH_10BIT; break; case EXT_DRV_PIXEL_BITWIDTH_12BIT: iapi_bit_depth = UAPI_PIXEL_BIT_DEPTH_12BIT; break; case EXT_DRV_PIXEL_BITWIDTH_16BIT: iapi_bit_depth = UAPI_PIXEL_BIT_DEPTH_16BIT; break; case EXT_DRV_PIXEL_BITWIDTH_MAX: default: iapi_bit_depth = UAPI_PIXEL_BIT_DEPTH_MAX; break; } return iapi_bit_depth; } static td_void convert_private_info_to_uapi(uapi_video_frame_info *uapi_image, const ext_drv_video_frame *drv_image) { ext_vid_frm_private_info *private_info = TD_NULL; if (sizeof(uapi_image->priv_info.priv_data) < sizeof(ext_vid_frm_private_info)) { ext_err_venc("unf private size=%d smaller than private struct size=%d\n", sizeof(uapi_image->priv_info.priv_data), sizeof(ext_vid_frm_private_info)); return; } private_info = (ext_vid_frm_private_info *)uapi_image->priv_info.priv_data; private_info->content_available = TD_TRUE; private_info->content_mode_id = SOC_ID_VENC; private_info->tunnel_buffer.mem_handle = drv_image->tunnel_buffer.fd_handle; private_info->tunnel_buffer.addr_offset = drv_image->tunnel_buffer.offset; private_info->secure_info.session_id = drv_image->secure_info.session_id; private_info->secure_info.phy_addr = drv_image->secure_info.phy_addr; venc_check_neq_void_ret(memcpy_s(private_info->secure_info.hdcp_info, sizeof(private_info->secure_info.hdcp_info), drv_image->secure_info.hdcp_info, sizeof(drv_image->secure_info.hdcp_info)), EOK); switch (drv_image->buf_valid_mode) { case EXT_DRV_FIELD_ALL: private_info->buf_valid_mode = EXT_FIELD_ALL; break; case EXT_DRV_FIELD_TOP: private_info->buf_valid_mode = EXT_FIELD_TOP; break; case EXT_DRV_FIELD_BOTTOM: private_info->buf_valid_mode = EXT_FIELD_BOTTOM; break; default: private_info->buf_valid_mode = EXT_FIELD_MAX; break; } } td_s32 venc_convert_frame_drv_to_user(uapi_video_frame_info *iapi_image, const ext_drv_video_frame *drv_image) { check_venc_ptr_ret(iapi_image); check_venc_ptr_ret(drv_image); get_user_frame_para(iapi_image, drv_image); switch (drv_image->video_3d_type) { case EXT_DRV_3D_NONE: iapi_image->frame_packing_type = UAPI_FRAME_PACKING_TYPE_2D; break; case EXT_DRV_3D_SBS_HALF: iapi_image->frame_packing_type = UAPI_FRAME_PACKING_TYPE_SIDE_BY_SIDE; break; case EXT_DRV_3D_TAB: iapi_image->frame_packing_type = UAPI_FRAME_PACKING_TYPE_TOP_AND_BOTTOM; break; case EXT_DRV_3D_FS: iapi_image->frame_packing_type = UAPI_FRAME_PACKING_TYPE_TIME_INTERLACED; break; case EXT_DRV_3D_FPK: iapi_image->frame_packing_type = UAPI_FRAME_PACKING_TYPE_FRAME_PACKING; break; default: iapi_image->frame_packing_type = UAPI_FRAME_PACKING_TYPE_MAX; break; } iapi_image->bit_depth = get_iapi_bit_depth(drv_image->bit_width); iapi_image->horizontal_mirror = drv_image->flip_h; iapi_image->vertical_mirror = drv_image->flip_v; iapi_image->error_level = drv_image->error_level; convert_private_info_to_uapi(iapi_image, drv_image); convert_hdr_frame_info_drv_to_user(iapi_image, drv_image); return TD_SUCCESS; } td_void venc_convert_strategy_user_to_drv(venc_ioctl_drop_frame_strategy *venc_frm_drop_strategy, const uapi_venc_frame_drop_strategy *frm_drop_param) { ext_venc_frame_drop_mode mode; check_venc_ptr_ret_void(venc_frm_drop_strategy); check_venc_ptr_ret_void(frm_drop_param); switch (frm_drop_param->mode) { case UAPI_VENC_FRAME_DROP_NORMAL: mode = EXT_VENC_FRAME_DROP_NORMAL; break; case UAPI_VENC_FRAME_DROP_SKIP_FRM: mode = EXT_VENC_FRAME_DROP_SKIP_FRM; break; default: mode = EXT_VENC_FRAME_DROP_MAX; break; } venc_frm_drop_strategy->drop_frame_strategy.enable = frm_drop_param->enable; venc_frm_drop_strategy->drop_frame_strategy.bit_rate_threshold = frm_drop_param->bit_rate_threshold; venc_frm_drop_strategy->drop_frame_strategy.drop_gap = frm_drop_param->drop_gap; venc_frm_drop_strategy->drop_frame_strategy.mode = mode; } td_void venc_convert_strategy_drv_to_user(uapi_venc_frame_drop_strategy *frm_drop_param, const venc_ioctl_drop_frame_strategy *venc_frm_drop_strategy) { uapi_venc_frame_drop_mode mode; check_venc_ptr_ret_void(venc_frm_drop_strategy); check_venc_ptr_ret_void(frm_drop_param); switch (venc_frm_drop_strategy->drop_frame_strategy.mode) { case EXT_VENC_FRAME_DROP_NORMAL: mode = UAPI_VENC_FRAME_DROP_NORMAL; break; case EXT_VENC_FRAME_DROP_SKIP_FRM: mode = UAPI_VENC_FRAME_DROP_SKIP_FRM; break; default: mode = UAPI_VENC_FRAME_DROP_MAX; break; } frm_drop_param->enable = venc_frm_drop_strategy->drop_frame_strategy.enable; frm_drop_param->bit_rate_threshold = venc_frm_drop_strategy->drop_frame_strategy.bit_rate_threshold; frm_drop_param->drop_gap = venc_frm_drop_strategy->drop_frame_strategy.drop_gap; frm_drop_param->mode = mode; } td_void venc_convert_status_drv_to_user(uapi_venc_chan_status *user_status, const venc_ioctl_status *drv_status) { check_venc_ptr_ret_void(user_status); check_venc_ptr_ret_void(drv_status); user_status->is_start = drv_status->chan_status.is_start; user_status->left_pics = drv_status->chan_status.left_pics; user_status->left_stream_bytes = drv_status->chan_status.left_stream_bytes; user_status->drop_frame_num = drv_status->chan_status.drop_frame_num; } static td_void venc_profile_to_iapi_profile(const ext_venc_chan_info *drv_attr, uapi_venc_attr *user_attr) { switch (drv_attr->profile) { case EXT_VENC_H264_PROFILE_BASELINE: user_attr->profile.h264_profile = UAPI_H264_PROFILE_BASELINE; break; case EXT_VENC_H264_PROFILE_MAIN: user_attr->profile.h264_profile = UAPI_H264_PROFILE_MAIN; break; case EXT_VENC_H264_PROFILE_EXTENDED: user_attr->profile.h264_profile = UAPI_H264_PROFILE_EXTENDED; break; case EXT_VENC_H264_PROFILE_HIGH: user_attr->profile.h264_profile = UAPI_H264_PROFILE_HIGH; break; case EXT_VENC_H264_PROFILE_MAX: user_attr->profile.h264_profile = UAPI_H264_PROFILE_MAX; break; default: break; } } static td_void venc_split_mode_to_iapi_mode(const ext_venc_chan_info *drv_attr, uapi_venc_attr *user_attr) { switch (drv_attr->config.slice_split.mode) { case EXT_VENC_SPLIT_BY_BYTE: user_attr->slice_split.mode = UAPI_VENC_SPLIT_BY_BYTE; break; case EXT_VENC_SPLIT_BY_LINE: user_attr->slice_split.mode = UAPI_VENC_SPLIT_BY_LINE; break; case EXT_VENC_SPLIT_MAX: user_attr->slice_split.mode = UAPI_VENC_SPLIT_MAX; break; default: break; } } static td_void venc_gop_mode_to_iapi_mode(const ext_venc_chan_info *drv_attr, uapi_venc_attr *user_attr) { switch (drv_attr->gop_mode) { case EXT_VENC_GOP_MODE_NORMALP: user_attr->gop_mode = UAPI_VENC_GOP_MODE_NORMALP; break; case EXT_VENC_GOP_MODE_DUALP: user_attr->gop_mode = UAPI_VENC_GOP_MODE_DUALP; break; case EXT_VENC_GOP_MODE_SMARTP: user_attr->gop_mode = UAPI_VENC_GOP_MODE_SMARTP; break; case EXT_VENC_GOP_MODE_MAX: user_attr->gop_mode = UAPI_VENC_GOP_MODE_MAX; break; default: break; } } td_void venc_convert_attr_drv_to_user(uapi_venc_attr *user_attr, const ext_venc_chan_info *drv_attr) { check_venc_ptr_ret_void(user_attr); check_venc_ptr_ret_void(drv_attr); if (drv_attr->standard == EXT_VENC_STD_H264) { user_attr->venc_type = UAPI_VCODEC_TYPE_H264; } else if (drv_attr->standard == EXT_VENC_STD_H265) { user_attr->venc_type = UAPI_VCODEC_TYPE_H265; } else if (drv_attr->standard == EXT_VENC_STD_JPEG) { user_attr->venc_type = UAPI_VCODEC_TYPE_MJPEG; } else { user_attr->venc_type = UAPI_VCODEC_TYPE_MAX; } /* FixMe: Need to distinguish between h264 and h265 */ venc_profile_to_iapi_profile(drv_attr, user_attr); user_attr->max_width = drv_attr->max_width; user_attr->max_height = drv_attr->max_height; user_attr->stream_buf_size = drv_attr->strm_buf_size; user_attr->slice_split.enable = drv_attr->config.slice_split.enable; venc_split_mode_to_iapi_mode(drv_attr, user_attr); user_attr->slice_split.size = drv_attr->config.slice_split.size; user_attr->secure = drv_attr->secure; venc_gop_mode_to_iapi_mode(drv_attr, user_attr); venc_convert_config_drv_to_user(&user_attr->config, &drv_attr->config); } td_void venc_convert_cap_drv_to_user(uapi_venc_cap *iapi_cap, const venc_ioctl_cap *drv_cap) { td_u32 i; check_venc_ptr_ret_void(iapi_cap); check_venc_ptr_ret_void(drv_cap); venc_check_neq_void_ret(memcpy_s(iapi_cap->cap_info, sizeof(uapi_venc_cap_info) * UAPI_VENC_TYPE_NUM, drv_cap->cap_info, sizeof(ext_venc_cap_info) * EXT_VENC_TYPE_NUM), TD_SUCCESS); iapi_cap->support_type_num = drv_cap->support_type_num; for (i = 0; i < drv_cap->support_type_num; i++) { switch (drv_cap->cap_info[i].standard) { case EXT_VENC_STD_H264: iapi_cap->cap_info[i].code_type = UAPI_VCODEC_TYPE_H264; break; case EXT_VENC_STD_H265: iapi_cap->cap_info[i].code_type = UAPI_VCODEC_TYPE_H265; break; case EXT_VENC_STD_JPEG: iapi_cap->cap_info[i].code_type = UAPI_VCODEC_TYPE_MJPEG; break; default: iapi_cap->cap_info[i].code_type = UAPI_VCODEC_TYPE_MAX; } } } td_void venc_convert_rc_param_iapi_to_drv(ext_venc_rc_param *drv_rc_param, const uapi_venc_rc_param *iapi_rc_param) { check_venc_ptr_ret_void(drv_rc_param); check_venc_ptr_ret_void(iapi_rc_param); drv_rc_param->max_qp = iapi_rc_param->max_qp; drv_rc_param->min_qp = iapi_rc_param->min_qp; switch (iapi_rc_param->type) { case UAPI_VENC_RC_TYPE_CBR: drv_rc_param->type = EXT_VENC_RC_TYPE_CBR; break; case UAPI_VENC_RC_TYPE_AVBR: drv_rc_param->type = EXT_VENC_RC_TYPE_AVBR; break; default: drv_rc_param->type = EXT_VENC_RC_TYPE_MAX; break; } } static td_void venc_rc_type_to_iapi_type(const ext_venc_rc_param *drv_rc_param, uapi_venc_rc_param *iapi_rc_param) { switch (drv_rc_param->type) { case EXT_VENC_RC_TYPE_CBR: iapi_rc_param->type = UAPI_VENC_RC_TYPE_CBR; break; case EXT_VENC_RC_TYPE_AVBR: iapi_rc_param->type = UAPI_VENC_RC_TYPE_AVBR; break; case EXT_VENC_RC_TYPE_MAX: iapi_rc_param->type = UAPI_VENC_RC_TYPE_MAX; break; default: break; } } td_void venc_convert_rc_param_drv_to_unf(uapi_venc_rc_param *iapi_rc_param, const ext_venc_rc_param *drv_rc_param) { check_venc_ptr_ret_void(iapi_rc_param); check_venc_ptr_ret_void(drv_rc_param); iapi_rc_param->max_qp = drv_rc_param->max_qp; iapi_rc_param->min_qp = drv_rc_param->min_qp; venc_rc_type_to_iapi_type(drv_rc_param, iapi_rc_param); }