3 * Copyright 2012 Samsung Electronics S.LSI Co. LTD
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
21 * @brief color space convertion abstract source
23 * @author Pyoungjae Jung(pjet.jung@samsung.com)
30 #define LOG_TAG "libcsc"
31 #include <cutils/log.h>
35 #include <utils/Log.h>
36 #include <system/graphics.h>
39 #include "exynos_format.h"
40 #include "swconverter.h"
43 #include "Exynos_OMX_Def.h"
45 #include "SEC_OMX_Def.h"
49 #include "hwconverter_wrapper.h"
53 #include "exynos_gscaler.h"
56 #define GSCALER_IMG_ALIGN 16
57 #define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
59 typedef enum _CSC_PLANE
{
67 typedef enum _CSC_HW_TYPE
{
72 typedef struct _CSC_FORMAT
{
75 unsigned int crop_left
;
76 unsigned int crop_top
;
77 unsigned int crop_width
;
78 unsigned int crop_height
;
79 unsigned int color_format
;
80 unsigned int cacheable
;
81 unsigned int mode_drm
;
84 typedef struct _CSC_BUFFER
{
85 void *planes
[CSC_MAX_PLANES
];
88 typedef struct _CSC_HW_PROPERTY
{
93 typedef struct _CSC_HANDLE
{
94 CSC_FORMAT dst_format
;
95 CSC_FORMAT src_format
;
96 CSC_BUFFER dst_buffer
;
97 CSC_BUFFER src_buffer
;
98 CSC_METHOD csc_method
;
99 CSC_HW_TYPE csc_hw_type
;
101 CSC_HW_PROPERTY hw_property
;
104 /* source is RGB888 */
105 static CSC_ERRORCODE
conv_sw_src_argb888(
108 CSC_ERRORCODE ret
= CSC_ErrorNone
;
110 switch (handle
->dst_format
.color_format
) {
111 case HAL_PIXEL_FORMAT_YCbCr_420_P
:
112 csc_ARGB8888_to_YUV420P(
113 (unsigned char *)handle
->dst_buffer
.planes
[CSC_Y_PLANE
],
114 (unsigned char *)handle
->dst_buffer
.planes
[CSC_U_PLANE
],
115 (unsigned char *)handle
->dst_buffer
.planes
[CSC_V_PLANE
],
116 (unsigned char *)handle
->src_buffer
.planes
[CSC_RGB_PLANE
],
117 handle
->src_format
.width
,
118 handle
->src_format
.height
);
121 case HAL_PIXEL_FORMAT_YCbCr_420_SP
:
122 csc_ARGB8888_to_YUV420SP_NEON(
123 (unsigned char *)handle
->dst_buffer
.planes
[CSC_Y_PLANE
],
124 (unsigned char *)handle
->dst_buffer
.planes
[CSC_UV_PLANE
],
125 (unsigned char *)handle
->src_buffer
.planes
[CSC_RGB_PLANE
],
126 handle
->src_format
.width
,
127 handle
->src_format
.height
);
131 ret
= CSC_ErrorUnsupportFormat
;
138 /* source is NV12T */
139 static CSC_ERRORCODE
conv_sw_src_nv12t(
142 CSC_ERRORCODE ret
= CSC_ErrorNone
;
144 switch (handle
->dst_format
.color_format
) {
145 case HAL_PIXEL_FORMAT_YCbCr_420_P
:
146 csc_tiled_to_linear_y_neon(
147 (unsigned char *)handle
->dst_buffer
.planes
[CSC_Y_PLANE
],
148 (unsigned char *)handle
->src_buffer
.planes
[CSC_Y_PLANE
],
149 handle
->src_format
.width
,
150 handle
->src_format
.height
);
151 csc_tiled_to_linear_uv_deinterleave_neon(
152 (unsigned char *)handle
->dst_buffer
.planes
[CSC_U_PLANE
],
153 (unsigned char *)handle
->dst_buffer
.planes
[CSC_V_PLANE
],
154 (unsigned char *)handle
->src_buffer
.planes
[CSC_UV_PLANE
],
155 handle
->src_format
.width
,
156 handle
->src_format
.height
/ 2);
159 case HAL_PIXEL_FORMAT_YCbCr_420_SP
:
160 csc_tiled_to_linear_y_neon(
161 (unsigned char *)handle
->dst_buffer
.planes
[CSC_Y_PLANE
],
162 (unsigned char *)handle
->src_buffer
.planes
[CSC_Y_PLANE
],
163 handle
->src_format
.width
,
164 handle
->src_format
.height
);
165 csc_tiled_to_linear_uv_neon(
166 (unsigned char *)handle
->dst_buffer
.planes
[CSC_UV_PLANE
],
167 (unsigned char *)handle
->src_buffer
.planes
[CSC_UV_PLANE
],
168 handle
->src_format
.width
,
169 handle
->src_format
.height
/ 2);
173 ret
= CSC_ErrorUnsupportFormat
;
180 /* source is YUV420P */
181 static CSC_ERRORCODE
conv_sw_src_yuv420p(
184 CSC_ERRORCODE ret
= CSC_ErrorNone
;
186 switch (handle
->dst_format
.color_format
) {
187 case HAL_PIXEL_FORMAT_YCbCr_420_P
: /* bypass */
188 memcpy((unsigned char *)handle
->dst_buffer
.planes
[CSC_Y_PLANE
],
189 (unsigned char *)handle
->src_buffer
.planes
[CSC_Y_PLANE
],
190 handle
->src_format
.width
* handle
->src_format
.height
);
191 memcpy((unsigned char *)handle
->dst_buffer
.planes
[CSC_U_PLANE
],
192 (unsigned char *)handle
->src_buffer
.planes
[CSC_U_PLANE
],
193 (handle
->src_format
.width
* handle
->src_format
.height
) >> 2);
194 memcpy((unsigned char *)handle
->dst_buffer
.planes
[CSC_V_PLANE
],
195 (unsigned char *)handle
->src_buffer
.planes
[CSC_V_PLANE
],
196 (handle
->src_format
.width
* handle
->src_format
.height
) >> 2);
199 case HAL_PIXEL_FORMAT_YCbCr_420_SP
:
200 memcpy((unsigned char *)handle
->dst_buffer
.planes
[CSC_Y_PLANE
],
201 (unsigned char *)handle
->src_buffer
.planes
[CSC_Y_PLANE
],
202 handle
->src_format
.width
* handle
->src_format
.height
);
203 csc_interleave_memcpy_neon(
204 (unsigned char *)handle
->dst_buffer
.planes
[CSC_UV_PLANE
],
205 (unsigned char *)handle
->src_buffer
.planes
[CSC_U_PLANE
],
206 (unsigned char *)handle
->src_buffer
.planes
[CSC_V_PLANE
],
207 (handle
->src_format
.width
* handle
->src_format
.height
) >> 2);
211 ret
= CSC_ErrorUnsupportFormat
;
218 /* source is YUV420SP */
219 static CSC_ERRORCODE
conv_sw_src_yuv420sp(
222 CSC_ERRORCODE ret
= CSC_ErrorNone
;
224 switch (handle
->dst_format
.color_format
) {
225 case HAL_PIXEL_FORMAT_YCbCr_420_P
:
226 memcpy((unsigned char *)handle
->dst_buffer
.planes
[CSC_Y_PLANE
],
227 (unsigned char *)handle
->src_buffer
.planes
[CSC_Y_PLANE
],
228 handle
->src_format
.width
* handle
->src_format
.height
);
229 csc_deinterleave_memcpy(
230 (unsigned char *)handle
->dst_buffer
.planes
[CSC_U_PLANE
],
231 (unsigned char *)handle
->dst_buffer
.planes
[CSC_V_PLANE
],
232 (unsigned char *)handle
->src_buffer
.planes
[CSC_UV_PLANE
],
233 handle
->src_format
.width
* handle
->src_format
.height
>> 1);
236 case HAL_PIXEL_FORMAT_YCbCr_420_SP
: /* bypass */
237 memcpy((unsigned char *)handle
->dst_buffer
.planes
[CSC_Y_PLANE
],
238 (unsigned char *)handle
->src_buffer
.planes
[CSC_Y_PLANE
],
239 handle
->src_format
.width
* handle
->src_format
.height
);
240 memcpy((unsigned char *)handle
->dst_buffer
.planes
[CSC_UV_PLANE
],
241 (unsigned char *)handle
->src_buffer
.planes
[CSC_UV_PLANE
],
242 handle
->src_format
.width
* handle
->src_format
.height
>> 1);
246 ret
= CSC_ErrorUnsupportFormat
;
253 static CSC_ERRORCODE
conv_sw(
256 CSC_ERRORCODE ret
= CSC_ErrorNone
;
258 switch (handle
->src_format
.color_format
) {
259 case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED
:
260 ret
= conv_sw_src_nv12t(handle
);
262 case HAL_PIXEL_FORMAT_YCbCr_420_P
:
263 ret
= conv_sw_src_yuv420p(handle
);
265 case HAL_PIXEL_FORMAT_YCbCr_420_SP
:
266 ret
= conv_sw_src_yuv420sp(handle
);
268 case HAL_PIXEL_FORMAT_ARGB888
:
269 ret
= conv_sw_src_argb888(handle
);
272 ret
= CSC_ErrorUnsupportFormat
;
279 static CSC_ERRORCODE
conv_hw(
282 CSC_ERRORCODE ret
= CSC_ErrorNone
;
283 switch (handle
->csc_hw_type
) {
285 case CSC_HW_TYPE_FIMC
:
289 OMX_COLOR_FORMATTYPE src_omx_format
;
290 OMX_COLOR_FORMATTYPE dst_omx_format
;
291 src_addr
[0] = handle
->src_buffer
.planes
[CSC_Y_PLANE
];
292 src_addr
[1] = handle
->src_buffer
.planes
[CSC_UV_PLANE
];
293 dst_addr
[0] = handle
->dst_buffer
.planes
[CSC_Y_PLANE
];
294 dst_addr
[1] = handle
->dst_buffer
.planes
[CSC_U_PLANE
];
295 dst_addr
[2] = handle
->dst_buffer
.planes
[CSC_V_PLANE
];
296 src_omx_format
= hal_2_omx_pixel_format(handle
->src_format
.color_format
);
297 dst_omx_format
= hal_2_omx_pixel_format(handle
->dst_format
.color_format
);
298 csc_hwconverter_convert_nv12t(
299 handle
->csc_hw_handle
,
302 handle
->dst_format
.width
,
303 handle
->dst_format
.height
,
309 #ifdef ENABLE_GSCALER
310 case CSC_HW_TYPE_GSCALER
:
311 if (exynos_gsc_convert(handle
->csc_hw_handle
) != 0) {
312 ALOGE("%s:: exynos_gsc_convert() fail", __func__
);
318 ALOGE("%s:: unsupported csc_hw_type(%d)", __func__
, handle
->csc_hw_type
);
319 ret
= CSC_ErrorNotImplemented
;
326 static CSC_ERRORCODE
csc_init_hw(
329 CSC_HANDLE
*csc_handle
;
330 CSC_ERRORCODE ret
= CSC_ErrorNone
;
332 csc_handle
= (CSC_HANDLE
*)handle
;
333 if (csc_handle
->csc_method
== CSC_METHOD_HW
) {
335 csc_handle
->csc_hw_type
= CSC_HW_TYPE_FIMC
;
337 #ifdef ENABLE_GSCALER
338 csc_handle
->csc_hw_type
= CSC_HW_TYPE_GSCALER
;
340 switch (csc_handle
->csc_hw_type
) {
342 case CSC_HW_TYPE_FIMC
:
343 csc_handle
->csc_hw_handle
= csc_hwconverter_open();
344 ALOGV("%s:: CSC_HW_TYPE_FIMC", __func__
);
347 #ifdef ENABLE_GSCALER
348 case CSC_HW_TYPE_GSCALER
:
349 if (csc_handle
->hw_property
.fixed_node
>= 0)
350 csc_handle
->csc_hw_handle
= exynos_gsc_create_exclusive(csc_handle
->hw_property
.fixed_node
, GSC_M2M_MODE
, 0, 0);
352 csc_handle
->csc_hw_handle
= exynos_gsc_create();
353 ALOGV("%s:: CSC_HW_TYPE_GSCALER", __func__
);
357 ALOGE("%s:: unsupported csc_hw_type, csc use sw", __func__
);
358 csc_handle
->csc_hw_handle
== NULL
;
363 if (csc_handle
->csc_method
== CSC_METHOD_HW
) {
364 if (csc_handle
->csc_hw_handle
== NULL
) {
365 ALOGE("%s:: CSC_METHOD_HW can't open HW", __func__
);
371 ALOGV("%s:: CSC_METHOD=%d", __func__
, csc_handle
->csc_method
);
376 static CSC_ERRORCODE
csc_set_format(
379 CSC_HANDLE
*csc_handle
;
380 CSC_ERRORCODE ret
= CSC_ErrorNone
;
383 return CSC_ErrorNotInit
;
385 csc_handle
= (CSC_HANDLE
*)handle
;
386 if (csc_handle
->csc_method
== CSC_METHOD_HW
) {
387 switch (csc_handle
->csc_hw_type
) {
388 case CSC_HW_TYPE_FIMC
:
390 #ifdef ENABLE_GSCALER
391 case CSC_HW_TYPE_GSCALER
:
392 exynos_gsc_set_src_format(
393 csc_handle
->csc_hw_handle
,
394 ALIGN(csc_handle
->src_format
.width
, GSCALER_IMG_ALIGN
),
395 ALIGN(csc_handle
->src_format
.height
, GSCALER_IMG_ALIGN
),
396 csc_handle
->src_format
.crop_left
,
397 csc_handle
->src_format
.crop_top
,
398 csc_handle
->src_format
.crop_width
,
399 csc_handle
->src_format
.crop_height
,
400 HAL_PIXEL_FORMAT_2_V4L2_PIX(csc_handle
->src_format
.color_format
),
401 csc_handle
->src_format
.cacheable
,
402 csc_handle
->hw_property
.mode_drm
);
404 exynos_gsc_set_dst_format(
405 csc_handle
->csc_hw_handle
,
406 ALIGN(csc_handle
->dst_format
.width
, GSCALER_IMG_ALIGN
),
407 ALIGN(csc_handle
->dst_format
.height
, GSCALER_IMG_ALIGN
),
408 csc_handle
->dst_format
.crop_left
,
409 csc_handle
->dst_format
.crop_top
,
410 csc_handle
->dst_format
.crop_width
,
411 csc_handle
->dst_format
.crop_height
,
412 HAL_PIXEL_FORMAT_2_V4L2_PIX(csc_handle
->dst_format
.color_format
),
413 csc_handle
->dst_format
.cacheable
,
414 csc_handle
->hw_property
.mode_drm
,
419 ALOGE("%s:: unsupported csc_hw_type", __func__
);
427 static CSC_ERRORCODE
csc_set_buffer(
430 CSC_HANDLE
*csc_handle
;
431 CSC_ERRORCODE ret
= CSC_ErrorNone
;
434 return CSC_ErrorNotInit
;
436 csc_handle
= (CSC_HANDLE
*)handle
;
437 if (csc_handle
->csc_method
== CSC_METHOD_HW
) {
438 switch (csc_handle
->csc_hw_type
) {
439 case CSC_HW_TYPE_FIMC
:
441 #ifdef ENABLE_GSCALER
442 case CSC_HW_TYPE_GSCALER
:
443 exynos_gsc_set_src_addr(csc_handle
->csc_hw_handle
, csc_handle
->src_buffer
.planes
, -1);
444 exynos_gsc_set_dst_addr(csc_handle
->csc_hw_handle
, csc_handle
->dst_buffer
.planes
, -1);
448 ALOGE("%s:: unsupported csc_hw_type", __func__
);
459 CSC_HANDLE
*csc_handle
;
460 csc_handle
= (CSC_HANDLE
*)malloc(sizeof(CSC_HANDLE
));
461 if (csc_handle
== NULL
)
464 memset(csc_handle
, 0, sizeof(CSC_HANDLE
));
465 csc_handle
->hw_property
.fixed_node
= -1;
466 csc_handle
->hw_property
.mode_drm
= 0;
467 csc_handle
->csc_method
= method
;
469 return (void *)csc_handle
;
472 CSC_ERRORCODE
csc_deinit(
475 CSC_ERRORCODE ret
= CSC_ErrorNone
;
476 CSC_HANDLE
*csc_handle
;
478 csc_handle
= (CSC_HANDLE
*)handle
;
479 if (csc_handle
->csc_method
== CSC_METHOD_HW
) {
480 switch (csc_handle
->csc_hw_type
) {
482 case CSC_HW_TYPE_FIMC
:
483 csc_hwconverter_close(csc_handle
->csc_hw_handle
);
486 #ifdef ENABLE_GSCALER
487 case CSC_HW_TYPE_GSCALER
:
488 exynos_gsc_destroy(csc_handle
->csc_hw_handle
);
492 ALOGE("%s:: unsupported csc_hw_type", __func__
);
497 if (csc_handle
!= NULL
) {
505 CSC_ERRORCODE
csc_get_method(
509 CSC_HANDLE
*csc_handle
;
510 CSC_ERRORCODE ret
= CSC_ErrorNone
;
513 return CSC_ErrorNotInit
;
515 csc_handle
= (CSC_HANDLE
*)handle
;
516 *method
= csc_handle
->csc_method
;
521 CSC_ERRORCODE
csc_set_hw_property(
523 CSC_HW_PROPERTY_TYPE property
,
526 CSC_HANDLE
*csc_handle
;
527 CSC_ERRORCODE ret
= CSC_ErrorNone
;
530 return CSC_ErrorNotInit
;
532 csc_handle
= (CSC_HANDLE
*)handle
;
534 case CSC_HW_PROPERTY_FIXED_NODE
:
535 csc_handle
->hw_property
.fixed_node
= value
;
537 case CSC_HW_PROPERTY_MODE_DRM
:
538 csc_handle
->hw_property
.mode_drm
= value
;
541 ALOGE("%s:: not supported hw property", __func__
);
542 ret
= CSC_ErrorUnsupportFormat
;
548 CSC_ERRORCODE
csc_get_src_format(
551 unsigned int *height
,
552 unsigned int *crop_left
,
553 unsigned int *crop_top
,
554 unsigned int *crop_width
,
555 unsigned int *crop_height
,
556 unsigned int *color_format
,
557 unsigned int *cacheable
)
559 CSC_HANDLE
*csc_handle
;
560 CSC_ERRORCODE ret
= CSC_ErrorNone
;
563 return CSC_ErrorNotInit
;
565 csc_handle
= (CSC_HANDLE
*)handle
;
566 *width
= csc_handle
->src_format
.width
;
567 *height
= csc_handle
->src_format
.height
;
568 *crop_left
= csc_handle
->src_format
.crop_left
;
569 *crop_top
= csc_handle
->src_format
.crop_top
;
570 *crop_width
= csc_handle
->src_format
.crop_width
;
571 *crop_height
= csc_handle
->src_format
.crop_height
;
572 *color_format
= csc_handle
->src_format
.color_format
;
573 *cacheable
= csc_handle
->src_format
.cacheable
;
578 CSC_ERRORCODE
csc_set_src_format(
582 unsigned int crop_left
,
583 unsigned int crop_top
,
584 unsigned int crop_width
,
585 unsigned int crop_height
,
586 unsigned int color_format
,
587 unsigned int cacheable
)
589 CSC_HANDLE
*csc_handle
;
590 CSC_ERRORCODE ret
= CSC_ErrorNone
;
593 return CSC_ErrorNotInit
;
595 csc_handle
= (CSC_HANDLE
*)handle
;
596 csc_handle
->src_format
.width
= width
;
597 csc_handle
->src_format
.height
= height
;
598 csc_handle
->src_format
.crop_left
= crop_left
;
599 csc_handle
->src_format
.crop_top
= crop_top
;
600 csc_handle
->src_format
.crop_width
= crop_width
;
601 csc_handle
->src_format
.crop_height
= crop_height
;
602 csc_handle
->src_format
.color_format
= color_format
;
603 csc_handle
->src_format
.cacheable
= cacheable
;
608 CSC_ERRORCODE
csc_get_dst_format(
611 unsigned int *height
,
612 unsigned int *crop_left
,
613 unsigned int *crop_top
,
614 unsigned int *crop_width
,
615 unsigned int *crop_height
,
616 unsigned int *color_format
,
617 unsigned int *cacheable
)
619 CSC_HANDLE
*csc_handle
;
620 CSC_ERRORCODE ret
= CSC_ErrorNone
;
623 return CSC_ErrorNotInit
;
625 csc_handle
= (CSC_HANDLE
*)handle
;
626 *width
= csc_handle
->dst_format
.width
;
627 *height
= csc_handle
->dst_format
.height
;
628 *crop_left
= csc_handle
->dst_format
.crop_left
;
629 *crop_top
= csc_handle
->dst_format
.crop_top
;
630 *crop_width
= csc_handle
->dst_format
.crop_width
;
631 *crop_height
= csc_handle
->dst_format
.crop_height
;
632 *color_format
= csc_handle
->dst_format
.color_format
;
633 *cacheable
= csc_handle
->dst_format
.cacheable
;
638 CSC_ERRORCODE
csc_set_dst_format(
642 unsigned int crop_left
,
643 unsigned int crop_top
,
644 unsigned int crop_width
,
645 unsigned int crop_height
,
646 unsigned int color_format
,
647 unsigned int cacheable
)
649 CSC_HANDLE
*csc_handle
;
650 CSC_ERRORCODE ret
= CSC_ErrorNone
;
653 return CSC_ErrorNotInit
;
655 csc_handle
= (CSC_HANDLE
*)handle
;
656 csc_handle
->dst_format
.width
= width
;
657 csc_handle
->dst_format
.height
= height
;
658 csc_handle
->dst_format
.crop_left
= crop_left
;
659 csc_handle
->dst_format
.crop_top
= crop_top
;
660 csc_handle
->dst_format
.crop_width
= crop_width
;
661 csc_handle
->dst_format
.crop_height
= crop_height
;
662 csc_handle
->dst_format
.color_format
= color_format
;
663 csc_handle
->dst_format
.cacheable
= cacheable
;
668 CSC_ERRORCODE
csc_set_src_buffer(
672 CSC_HANDLE
*csc_handle
;
673 CSC_ERRORCODE ret
= CSC_ErrorNone
;
676 return CSC_ErrorNotInit
;
678 csc_handle
= (CSC_HANDLE
*)handle
;
679 csc_handle
->src_buffer
.planes
[CSC_Y_PLANE
] = addr
[0];
680 csc_handle
->src_buffer
.planes
[CSC_U_PLANE
] = addr
[1];
681 csc_handle
->src_buffer
.planes
[CSC_V_PLANE
] = addr
[2];
686 CSC_ERRORCODE
csc_set_dst_buffer(
690 CSC_HANDLE
*csc_handle
;
691 CSC_ERRORCODE ret
= CSC_ErrorNone
;
694 return CSC_ErrorNotInit
;
696 csc_handle
= (CSC_HANDLE
*)handle
;
697 csc_handle
->dst_buffer
.planes
[CSC_Y_PLANE
] = addr
[0];
698 csc_handle
->dst_buffer
.planes
[CSC_U_PLANE
] = addr
[1];
699 csc_handle
->dst_buffer
.planes
[CSC_V_PLANE
] = addr
[2];
704 CSC_ERRORCODE
csc_convert(
707 CSC_HANDLE
*csc_handle
= (CSC_HANDLE
*)handle
;
708 CSC_ERRORCODE ret
= CSC_ErrorNone
;
710 if (csc_handle
== NULL
)
711 return CSC_ErrorNotInit
;
713 if ((csc_handle
->csc_method
== CSC_METHOD_HW
) &&
714 (csc_handle
->csc_hw_handle
== NULL
))
717 csc_set_format(csc_handle
);
718 csc_set_buffer(csc_handle
);
720 if (csc_handle
->csc_method
== CSC_METHOD_HW
)
721 ret
= conv_hw(csc_handle
);
723 ret
= conv_sw(csc_handle
);