/* * * Copyright 2012 Samsung Electronics S.LSI Co. LTD * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * @file csc.c * * @brief color space convertion abstract source * * @author Pyoungjae Jung(pjet.jung@samsung.com) * * @version 1.0.0 * * @history * 2012.1.11 : Create */ #define LOG_TAG "libcsc" #include <cutils/log.h> #include <stdio.h> #include <stdlib.h> #include <utils/Log.h> #include <system/graphics.h> #include "csc.h" #include "exynos_format.h" #include "swconverter.h" #ifdef EXYNOS_OMX #include "Exynos_OMX_Def.h" #else #include "SEC_OMX_Def.h" #endif #ifdef ENABLE_FIMC #include "hwconverter_wrapper.h" #endif #ifdef ENABLE_GSCALER #include "exynos_gscaler.h" #endif #ifdef ENABLE_G2D #include <fcntl.h> #include <sys/ioctl.h> #include "fimg2d.h" typedef struct { struct fimg2d_image src; struct fimg2d_image dst; int fd; } g2d_data; #endif #define GSCALER_IMG_ALIGN 16 #define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) typedef enum _CSC_PLANE { CSC_Y_PLANE = 0, CSC_RGB_PLANE = 0, CSC_U_PLANE = 1, CSC_UV_PLANE = 1, CSC_V_PLANE = 2 } CSC_PLANE; typedef struct _CSC_FORMAT { unsigned int width; unsigned int height; unsigned int crop_left; unsigned int crop_top; unsigned int crop_width; unsigned int crop_height; unsigned int color_format; unsigned int cacheable; unsigned int mode_drm; } CSC_FORMAT; typedef struct _CSC_BUFFER { void *planes[CSC_MAX_PLANES]; } CSC_BUFFER; typedef struct _CSC_HW_PROPERTY { int fixed_node; int mode_drm; } CSC_HW_PROPERTY; typedef struct _CSC_HANDLE { CSC_FORMAT dst_format; CSC_FORMAT src_format; CSC_BUFFER dst_buffer; CSC_BUFFER src_buffer; CSC_METHOD csc_method; CSC_HW_TYPE csc_hw_type; void *csc_hw_handle; CSC_HW_PROPERTY hw_property; } CSC_HANDLE; /* source is RGB888 */ static CSC_ERRORCODE conv_sw_src_argb888( CSC_HANDLE *handle) { CSC_ERRORCODE ret = CSC_ErrorNone; switch (handle->dst_format.color_format) { case HAL_PIXEL_FORMAT_YCbCr_420_P: csc_ARGB8888_to_YUV420P( (unsigned char *)handle->dst_buffer.planes[CSC_Y_PLANE], (unsigned char *)handle->dst_buffer.planes[CSC_U_PLANE], (unsigned char *)handle->dst_buffer.planes[CSC_V_PLANE], (unsigned char *)handle->src_buffer.planes[CSC_RGB_PLANE], handle->src_format.width, handle->src_format.height); ret = CSC_ErrorNone; break; case HAL_PIXEL_FORMAT_YCbCr_420_SP: csc_ARGB8888_to_YUV420SP_NEON( (unsigned char *)handle->dst_buffer.planes[CSC_Y_PLANE], (unsigned char *)handle->dst_buffer.planes[CSC_UV_PLANE], (unsigned char *)handle->src_buffer.planes[CSC_RGB_PLANE], handle->src_format.width, handle->src_format.height); ret = CSC_ErrorNone; break; default: ret = CSC_ErrorUnsupportFormat; break; } return ret; } /* source is NV12T */ static CSC_ERRORCODE conv_sw_src_nv12t( CSC_HANDLE *handle) { CSC_ERRORCODE ret = CSC_ErrorNone; switch (handle->dst_format.color_format) { case HAL_PIXEL_FORMAT_YCbCr_420_P: csc_tiled_to_linear_y_neon( (unsigned char *)handle->dst_buffer.planes[CSC_Y_PLANE], (unsigned char *)handle->src_buffer.planes[CSC_Y_PLANE], handle->src_format.width, handle->src_format.height); csc_tiled_to_linear_uv_deinterleave_neon( (unsigned char *)handle->dst_buffer.planes[CSC_U_PLANE], (unsigned char *)handle->dst_buffer.planes[CSC_V_PLANE], (unsigned char *)handle->src_buffer.planes[CSC_UV_PLANE], handle->src_format.width, handle->src_format.height / 2); ret = CSC_ErrorNone; break; case HAL_PIXEL_FORMAT_YCbCr_420_SP: csc_tiled_to_linear_y_neon( (unsigned char *)handle->dst_buffer.planes[CSC_Y_PLANE], (unsigned char *)handle->src_buffer.planes[CSC_Y_PLANE], handle->src_format.width, handle->src_format.height); csc_tiled_to_linear_uv_neon( (unsigned char *)handle->dst_buffer.planes[CSC_UV_PLANE], (unsigned char *)handle->src_buffer.planes[CSC_UV_PLANE], handle->src_format.width, handle->src_format.height / 2); ret = CSC_ErrorNone; break; default: ret = CSC_ErrorUnsupportFormat; break; } return ret; } /* source is YUV420P */ static CSC_ERRORCODE conv_sw_src_yuv420p( CSC_HANDLE *handle) { CSC_ERRORCODE ret = CSC_ErrorNone; switch (handle->dst_format.color_format) { case HAL_PIXEL_FORMAT_YCbCr_420_P: /* bypass */ memcpy((unsigned char *)handle->dst_buffer.planes[CSC_Y_PLANE], (unsigned char *)handle->src_buffer.planes[CSC_Y_PLANE], handle->src_format.width * handle->src_format.height); memcpy((unsigned char *)handle->dst_buffer.planes[CSC_U_PLANE], (unsigned char *)handle->src_buffer.planes[CSC_U_PLANE], (handle->src_format.width * handle->src_format.height) >> 2); memcpy((unsigned char *)handle->dst_buffer.planes[CSC_V_PLANE], (unsigned char *)handle->src_buffer.planes[CSC_V_PLANE], (handle->src_format.width * handle->src_format.height) >> 2); ret = CSC_ErrorNone; break; case HAL_PIXEL_FORMAT_YCbCr_420_SP: memcpy((unsigned char *)handle->dst_buffer.planes[CSC_Y_PLANE], (unsigned char *)handle->src_buffer.planes[CSC_Y_PLANE], handle->src_format.width * handle->src_format.height); csc_interleave_memcpy_neon( (unsigned char *)handle->dst_buffer.planes[CSC_UV_PLANE], (unsigned char *)handle->src_buffer.planes[CSC_U_PLANE], (unsigned char *)handle->src_buffer.planes[CSC_V_PLANE], (handle->src_format.width * handle->src_format.height) >> 2); ret = CSC_ErrorNone; break; default: ret = CSC_ErrorUnsupportFormat; break; } return ret; } /* source is YUV420SP */ static CSC_ERRORCODE conv_sw_src_yuv420sp( CSC_HANDLE *handle) { CSC_ERRORCODE ret = CSC_ErrorNone; switch (handle->dst_format.color_format) { case HAL_PIXEL_FORMAT_YCbCr_420_P: memcpy((unsigned char *)handle->dst_buffer.planes[CSC_Y_PLANE], (unsigned char *)handle->src_buffer.planes[CSC_Y_PLANE], handle->src_format.width * handle->src_format.height); csc_deinterleave_memcpy( (unsigned char *)handle->dst_buffer.planes[CSC_U_PLANE], (unsigned char *)handle->dst_buffer.planes[CSC_V_PLANE], (unsigned char *)handle->src_buffer.planes[CSC_UV_PLANE], handle->src_format.width * handle->src_format.height >> 1); ret = CSC_ErrorNone; break; case HAL_PIXEL_FORMAT_YCbCr_420_SP: /* bypass */ memcpy((unsigned char *)handle->dst_buffer.planes[CSC_Y_PLANE], (unsigned char *)handle->src_buffer.planes[CSC_Y_PLANE], handle->src_format.width * handle->src_format.height); memcpy((unsigned char *)handle->dst_buffer.planes[CSC_UV_PLANE], (unsigned char *)handle->src_buffer.planes[CSC_UV_PLANE], handle->src_format.width * handle->src_format.height >> 1); ret = CSC_ErrorNone; break; default: ret = CSC_ErrorUnsupportFormat; break; } return ret; } static CSC_ERRORCODE conv_sw( CSC_HANDLE *handle) { CSC_ERRORCODE ret = CSC_ErrorNone; switch (handle->src_format.color_format) { case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: ret = conv_sw_src_nv12t(handle); break; case HAL_PIXEL_FORMAT_YCbCr_420_P: ret = conv_sw_src_yuv420p(handle); break; case HAL_PIXEL_FORMAT_YCbCr_420_SP: ret = conv_sw_src_yuv420sp(handle); break; case HAL_PIXEL_FORMAT_CUSTOM_ARGB_8888: ret = conv_sw_src_argb888(handle); break; default: ret = CSC_ErrorUnsupportFormat; break; } return ret; } static CSC_ERRORCODE conv_hw( CSC_HANDLE *handle) { CSC_ERRORCODE ret = CSC_ErrorNone; switch (handle->csc_hw_type) { #ifdef ENABLE_FIMC case CSC_HW_TYPE_FIMC: { void *src_addr[3]; void *dst_addr[3]; OMX_COLOR_FORMATTYPE src_omx_format; OMX_COLOR_FORMATTYPE dst_omx_format; src_addr[0] = handle->src_buffer.planes[CSC_Y_PLANE]; src_addr[1] = handle->src_buffer.planes[CSC_UV_PLANE]; dst_addr[0] = handle->dst_buffer.planes[CSC_Y_PLANE]; dst_addr[1] = handle->dst_buffer.planes[CSC_U_PLANE]; dst_addr[2] = handle->dst_buffer.planes[CSC_V_PLANE]; src_omx_format = hal_2_omx_pixel_format(handle->src_format.color_format); dst_omx_format = hal_2_omx_pixel_format(handle->dst_format.color_format); csc_hwconverter_convert_nv12t( handle->csc_hw_handle, dst_addr, src_addr, handle->dst_format.width, handle->dst_format.height, dst_omx_format, src_omx_format); break; } #endif #ifdef ENABLE_GSCALER case CSC_HW_TYPE_GSCALER: if (exynos_gsc_convert(handle->csc_hw_handle) != 0) { ALOGE("%s:: exynos_gsc_convert() fail", __func__); ret = CSC_Error; } break; #endif #ifdef ENABLE_G2D case CSC_HW_TYPE_G2D: { g2d_data *g2d = (g2d_data *)handle->csc_hw_handle; struct fimg2d_blit blit; int err; memset(&blit, 0, sizeof(blit)); blit.op = BLIT_OP_SRC_COPY; blit.param.g_alpha = 0xFF; blit.src = &g2d->src; blit.dst = &g2d->dst; blit.sync = BLIT_SYNC; err = ioctl(g2d->fd, FIMG2D_BITBLT_BLIT, &blit); if (err < 0) { ALOGE("FIMG2D_BITBLT_BLIT ioctl failed: %s", strerror(errno)); ret = CSC_Error; } break; } #endif default: ALOGE("%s:: unsupported csc_hw_type(%d)", __func__, handle->csc_hw_type); ret = CSC_ErrorNotImplemented; break; } return ret; } static CSC_ERRORCODE csc_init_hw( void *handle) { CSC_HANDLE *csc_handle; CSC_ERRORCODE ret = CSC_ErrorNone; csc_handle = (CSC_HANDLE *)handle; if (csc_handle->csc_method == CSC_METHOD_HW) { switch (csc_handle->csc_hw_type) { #ifdef ENABLE_FIMC case CSC_HW_TYPE_FIMC: csc_handle->csc_hw_handle = csc_hwconverter_open(); ALOGV("%s:: CSC_HW_TYPE_FIMC", __func__); break; #endif #ifdef ENABLE_GSCALER case CSC_HW_TYPE_GSCALER: if (csc_handle->hw_property.fixed_node >= 0) csc_handle->csc_hw_handle = exynos_gsc_create_exclusive(csc_handle->hw_property.fixed_node, GSC_M2M_MODE, 0, 0); else csc_handle->csc_hw_handle = exynos_gsc_create(); ALOGV("%s:: CSC_HW_TYPE_GSCALER", __func__); break; #endif #ifdef ENABLE_G2D case CSC_HW_TYPE_G2D: { g2d_data *g2d = calloc(1, sizeof(g2d_data)); if (!g2d) { ALOGE("failed to allocate G2D data"); break; } g2d->fd = open("/dev/fimg2d", O_RDWR); if (g2d->fd < 0) { ALOGE("failed to open G2D: %s", strerror(errno)); free(g2d); } else { csc_handle->csc_hw_handle = g2d; } break; } #endif default: ALOGE("%s:: unsupported csc_hw_type, csc use sw", __func__); csc_handle->csc_hw_handle = NULL; break; } } if (csc_handle->csc_method == CSC_METHOD_HW) { if (csc_handle->csc_hw_handle == NULL) { ALOGE("%s:: CSC_METHOD_HW can't open HW", __func__); ret = CSC_Error; } } ALOGV("%s:: CSC_METHOD=%d", __func__, csc_handle->csc_method); return ret; } static CSC_ERRORCODE csc_set_format( void *handle) { CSC_HANDLE *csc_handle; CSC_ERRORCODE ret = CSC_ErrorNone; if (handle == NULL) return CSC_ErrorNotInit; csc_handle = (CSC_HANDLE *)handle; if (csc_handle->csc_method == CSC_METHOD_HW) { switch (csc_handle->csc_hw_type) { case CSC_HW_TYPE_FIMC: break; #ifdef ENABLE_GSCALER case CSC_HW_TYPE_GSCALER: exynos_gsc_set_src_format( csc_handle->csc_hw_handle, ALIGN(csc_handle->src_format.width, GSCALER_IMG_ALIGN), ALIGN(csc_handle->src_format.height, GSCALER_IMG_ALIGN), csc_handle->src_format.crop_left, csc_handle->src_format.crop_top, csc_handle->src_format.crop_width, csc_handle->src_format.crop_height, HAL_PIXEL_FORMAT_2_V4L2_PIX(csc_handle->src_format.color_format), csc_handle->src_format.cacheable, csc_handle->hw_property.mode_drm); exynos_gsc_set_dst_format( csc_handle->csc_hw_handle, ALIGN(csc_handle->dst_format.width, GSCALER_IMG_ALIGN), ALIGN(csc_handle->dst_format.height, GSCALER_IMG_ALIGN), csc_handle->dst_format.crop_left, csc_handle->dst_format.crop_top, csc_handle->dst_format.crop_width, csc_handle->dst_format.crop_height, HAL_PIXEL_FORMAT_2_V4L2_PIX(csc_handle->dst_format.color_format), csc_handle->dst_format.cacheable, csc_handle->hw_property.mode_drm, 0); break; #endif #ifdef ENABLE_G2D case CSC_HW_TYPE_G2D: { g2d_data *g2d = (g2d_data *)csc_handle->csc_hw_handle; g2d->src.width = ALIGN(csc_handle->src_format.width, GSCALER_IMG_ALIGN); g2d->src.height = csc_handle->src_format.height; g2d->src.stride = g2d->src.width * hal_2_g2d_bpp(csc_handle->src_format.color_format) >> 3; g2d->src.order = hal_2_g2d_pixel_order(csc_handle->src_format.color_format); g2d->src.fmt = hal_2_g2d_color_format(csc_handle->src_format.color_format); g2d->src.rect.x1 = csc_handle->src_format.crop_left; g2d->src.rect.y1 = csc_handle->src_format.crop_top; g2d->src.rect.x2 = csc_handle->src_format.crop_left + csc_handle->src_format.crop_width; g2d->src.rect.y2 = csc_handle->src_format.crop_top + csc_handle->src_format.crop_height; g2d->dst.width = ALIGN(csc_handle->dst_format.width, GSCALER_IMG_ALIGN); g2d->dst.height = csc_handle->dst_format.height; g2d->dst.stride = g2d->dst.width * hal_2_g2d_bpp(csc_handle->dst_format.color_format) >> 3; g2d->dst.order = hal_2_g2d_pixel_order(csc_handle->dst_format.color_format); g2d->dst.fmt = hal_2_g2d_color_format(csc_handle->dst_format.color_format); g2d->dst.rect.x1 = csc_handle->dst_format.crop_left; g2d->dst.rect.y1 = csc_handle->dst_format.crop_top; g2d->dst.rect.x2 = csc_handle->dst_format.crop_left + csc_handle->dst_format.crop_width; g2d->dst.rect.y2 = csc_handle->dst_format.crop_top + csc_handle->dst_format.crop_height; break; } #endif default: ALOGE("%s:: unsupported csc_hw_type", __func__); break; } } return ret; } static CSC_ERRORCODE csc_set_buffer( void *handle) { CSC_HANDLE *csc_handle; CSC_ERRORCODE ret = CSC_ErrorNone; if (handle == NULL) return CSC_ErrorNotInit; csc_handle = (CSC_HANDLE *)handle; if (csc_handle->csc_method == CSC_METHOD_HW) { switch (csc_handle->csc_hw_type) { case CSC_HW_TYPE_FIMC: break; #ifdef ENABLE_GSCALER case CSC_HW_TYPE_GSCALER: exynos_gsc_set_src_addr(csc_handle->csc_hw_handle, csc_handle->src_buffer.planes, -1); exynos_gsc_set_dst_addr(csc_handle->csc_hw_handle, csc_handle->dst_buffer.planes, -1); break; #endif #ifdef ENABLE_G2D case CSC_HW_TYPE_G2D: { g2d_data *g2d = (g2d_data *)csc_handle->csc_hw_handle; g2d->src.addr.type = ADDR_DMA_BUF; g2d->src.addr.fd[0] = (int)csc_handle->src_buffer.planes[0]; g2d->src.addr.fd[1] = (int)csc_handle->src_buffer.planes[1]; g2d->dst.addr.type = ADDR_DMA_BUF; g2d->dst.addr.fd[0] = (int)csc_handle->dst_buffer.planes[0]; g2d->dst.addr.fd[1] = (int)csc_handle->dst_buffer.planes[1]; break; } #endif default: ALOGE("%s:: unsupported csc_hw_type", __func__); break; } } return ret; } void *csc_init( CSC_METHOD method) { CSC_HANDLE *csc_handle; csc_handle = (CSC_HANDLE *)malloc(sizeof(CSC_HANDLE)); if (csc_handle == NULL) return NULL; memset(csc_handle, 0, sizeof(CSC_HANDLE)); csc_handle->hw_property.fixed_node = -1; csc_handle->hw_property.mode_drm = 0; csc_handle->csc_method = method; return (void *)csc_handle; } CSC_ERRORCODE csc_deinit( void *handle) { CSC_ERRORCODE ret = CSC_ErrorNone; CSC_HANDLE *csc_handle; csc_handle = (CSC_HANDLE *)handle; if (csc_handle->csc_hw_handle) { switch (csc_handle->csc_hw_type) { #ifdef ENABLE_FIMC case CSC_HW_TYPE_FIMC: csc_hwconverter_close(csc_handle->csc_hw_handle); break; #endif #ifdef ENABLE_GSCALER case CSC_HW_TYPE_GSCALER: exynos_gsc_destroy(csc_handle->csc_hw_handle); break; #endif #ifdef ENABLE_G2D case CSC_HW_TYPE_G2D: { g2d_data *g2d = (g2d_data *)csc_handle->csc_hw_handle; close(g2d->fd); free(g2d); break; } #endif default: ALOGE("%s:: unsupported csc_hw_type", __func__); break; } } if (csc_handle != NULL) { free(csc_handle); ret = CSC_ErrorNone; } return ret; } CSC_ERRORCODE csc_get_method( void *handle, CSC_METHOD *method) { CSC_HANDLE *csc_handle; CSC_ERRORCODE ret = CSC_ErrorNone; if (handle == NULL) return CSC_ErrorNotInit; csc_handle = (CSC_HANDLE *)handle; *method = csc_handle->csc_method; return ret; } CSC_ERRORCODE csc_set_method( void *handle, CSC_METHOD method) { CSC_HANDLE *csc_handle; CSC_ERRORCODE ret = CSC_ErrorNone; if (handle == NULL) return CSC_ErrorNotInit; csc_handle = (CSC_HANDLE *)handle; csc_handle->csc_method = method; return ret; } CSC_ERRORCODE csc_set_hw_property( void *handle, CSC_HW_PROPERTY_TYPE property, int value) { CSC_HANDLE *csc_handle; CSC_ERRORCODE ret = CSC_ErrorNone; if (handle == NULL) return CSC_ErrorNotInit; csc_handle = (CSC_HANDLE *)handle; if (csc_handle->csc_hw_handle) { ALOGE("%s:: cannot set hw property after hw is already initialized", __func__); return CSC_ErrorUnsupportFormat; } switch (property) { case CSC_HW_PROPERTY_FIXED_NODE: csc_handle->hw_property.fixed_node = value; break; case CSC_HW_PROPERTY_MODE_DRM: csc_handle->hw_property.mode_drm = value; break; case CSC_HW_PROPERTY_HW_TYPE: csc_handle->csc_hw_type = value; break; default: ALOGE("%s:: not supported hw property", __func__); ret = CSC_ErrorUnsupportFormat; } return ret; } CSC_ERRORCODE csc_get_src_format( void *handle, unsigned int *width, unsigned int *height, unsigned int *crop_left, unsigned int *crop_top, unsigned int *crop_width, unsigned int *crop_height, unsigned int *color_format, unsigned int *cacheable) { CSC_HANDLE *csc_handle; CSC_ERRORCODE ret = CSC_ErrorNone; if (handle == NULL) return CSC_ErrorNotInit; csc_handle = (CSC_HANDLE *)handle; *width = csc_handle->src_format.width; *height = csc_handle->src_format.height; *crop_left = csc_handle->src_format.crop_left; *crop_top = csc_handle->src_format.crop_top; *crop_width = csc_handle->src_format.crop_width; *crop_height = csc_handle->src_format.crop_height; *color_format = csc_handle->src_format.color_format; *cacheable = csc_handle->src_format.cacheable; return ret; } CSC_ERRORCODE csc_set_src_format( void *handle, unsigned int width, unsigned int height, unsigned int crop_left, unsigned int crop_top, unsigned int crop_width, unsigned int crop_height, unsigned int color_format, unsigned int cacheable) { CSC_HANDLE *csc_handle; CSC_ERRORCODE ret = CSC_ErrorNone; if (handle == NULL) return CSC_ErrorNotInit; csc_handle = (CSC_HANDLE *)handle; csc_handle->src_format.width = width; csc_handle->src_format.height = height; csc_handle->src_format.crop_left = crop_left; csc_handle->src_format.crop_top = crop_top; csc_handle->src_format.crop_width = crop_width; csc_handle->src_format.crop_height = crop_height; csc_handle->src_format.color_format = color_format; csc_handle->src_format.cacheable = cacheable; return ret; } CSC_ERRORCODE csc_get_dst_format( void *handle, unsigned int *width, unsigned int *height, unsigned int *crop_left, unsigned int *crop_top, unsigned int *crop_width, unsigned int *crop_height, unsigned int *color_format, unsigned int *cacheable) { CSC_HANDLE *csc_handle; CSC_ERRORCODE ret = CSC_ErrorNone; if (handle == NULL) return CSC_ErrorNotInit; csc_handle = (CSC_HANDLE *)handle; *width = csc_handle->dst_format.width; *height = csc_handle->dst_format.height; *crop_left = csc_handle->dst_format.crop_left; *crop_top = csc_handle->dst_format.crop_top; *crop_width = csc_handle->dst_format.crop_width; *crop_height = csc_handle->dst_format.crop_height; *color_format = csc_handle->dst_format.color_format; *cacheable = csc_handle->dst_format.cacheable; return ret; } CSC_ERRORCODE csc_set_dst_format( void *handle, unsigned int width, unsigned int height, unsigned int crop_left, unsigned int crop_top, unsigned int crop_width, unsigned int crop_height, unsigned int color_format, unsigned int cacheable) { CSC_HANDLE *csc_handle; CSC_ERRORCODE ret = CSC_ErrorNone; if (handle == NULL) return CSC_ErrorNotInit; csc_handle = (CSC_HANDLE *)handle; csc_handle->dst_format.width = width; csc_handle->dst_format.height = height; csc_handle->dst_format.crop_left = crop_left; csc_handle->dst_format.crop_top = crop_top; csc_handle->dst_format.crop_width = crop_width; csc_handle->dst_format.crop_height = crop_height; csc_handle->dst_format.color_format = color_format; csc_handle->dst_format.cacheable = cacheable; return ret; } CSC_ERRORCODE csc_set_src_buffer( void *handle, void *addr[3]) { CSC_HANDLE *csc_handle; CSC_ERRORCODE ret = CSC_ErrorNone; if (handle == NULL) return CSC_ErrorNotInit; csc_handle = (CSC_HANDLE *)handle; csc_handle->src_buffer.planes[CSC_Y_PLANE] = addr[0]; csc_handle->src_buffer.planes[CSC_U_PLANE] = addr[1]; csc_handle->src_buffer.planes[CSC_V_PLANE] = addr[2]; return ret; } CSC_ERRORCODE csc_set_dst_buffer( void *handle, void *addr[3]) { CSC_HANDLE *csc_handle; CSC_ERRORCODE ret = CSC_ErrorNone; if (handle == NULL) return CSC_ErrorNotInit; csc_handle = (CSC_HANDLE *)handle; csc_handle->dst_buffer.planes[CSC_Y_PLANE] = addr[0]; csc_handle->dst_buffer.planes[CSC_U_PLANE] = addr[1]; csc_handle->dst_buffer.planes[CSC_V_PLANE] = addr[2]; return ret; } CSC_ERRORCODE csc_convert( void *handle) { CSC_HANDLE *csc_handle = (CSC_HANDLE *)handle; CSC_ERRORCODE ret = CSC_ErrorNone; if (csc_handle == NULL) return CSC_ErrorNotInit; if ((csc_handle->csc_method == CSC_METHOD_HW) && (csc_handle->csc_hw_handle == NULL)) { ret = csc_init_hw(handle); if (ret != CSC_ErrorNone) return ret; } ret = csc_set_format(csc_handle); if (ret != CSC_ErrorNone) return ret; ret = csc_set_buffer(csc_handle); if (ret != CSC_ErrorNone) return ret; if (csc_handle->csc_method == CSC_METHOD_HW) ret = conv_hw(csc_handle); else ret = conv_sw(csc_handle); return ret; }