/* * test_cl_image.cpp - test cl image * * Copyright (c) 2014-2015 Intel Corporation * * 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. * * Author: Wind Yuan <feng.yuan@intel.com> * Author: Yinhang Liu <yinhangx.liu@intel.com> * Author: Wei Zong <wei.zong@intel.com> */ #include "test_common.h" #include "test_inline.h" #include "image_file_handle.h" #include "ocl/cl_device.h" #include "ocl/cl_context.h" #include "ocl/cl_demo_handler.h" #include "ocl/cl_csc_handler.h" #include "ocl/cl_bayer_pipe_handler.h" #include "ocl/cl_yuv_pipe_handler.h" #include "ocl/cl_tonemapping_handler.h" #include "ocl/cl_retinex_handler.h" #include "ocl/cl_gauss_handler.h" #include "ocl/cl_wavelet_denoise_handler.h" #include "ocl/cl_newwavelet_denoise_handler.h" #include "ocl/cl_defog_dcp_handler.h" #include "ocl/cl_3d_denoise_handler.h" #include "ocl/cl_image_warp_handler.h" #include "ocl/cl_fisheye_handler.h" #include "ocl/cl_utils.h" using namespace XCam; enum TestHandlerType { TestHandlerUnknown = 0, TestHandlerDemo, TestHandlerColorConversion, TestHandlerBayerPipe, TestHandlerYuvPipe, TestHandlerTonemapping, TestHandlerRetinex, TestHandlerGauss, TestHandlerHatWavelet, TestHandlerHaarWavelet, TestHandlerDefogDcp, TestHandler3DDenoise, TestHandlerImageWarp, TestHandlerFisheye, }; enum PsnrType { PSNRY = 0, PSNRR, PSNRG, PSNRB, }; static XCamReturn calculate_psnr (SmartPtr<VideoBuffer> &psnr_cur, SmartPtr<VideoBuffer> &psnr_ref, PsnrType psnr_type, float &psnr) { const VideoBufferInfo info = psnr_cur->get_video_info (); VideoBufferPlanarInfo planar; uint8_t *cur_mem = NULL, *ref_mem = NULL; XCamReturn ret = XCAM_RETURN_NO_ERROR; int8_t interval = 1, index = 0; if (PSNRY == psnr_type) { interval = 1; index = 0; } else if (PSNRR == psnr_type) { interval = 4; index = 0; } else if (PSNRG == psnr_type) { interval = 4; index = 1; } else if (PSNRB == psnr_type) { interval = 4; index = 2; } cur_mem = psnr_cur->map (); ref_mem = psnr_ref->map (); if (!cur_mem || !ref_mem) { XCAM_LOG_ERROR ("calculate_psnr map buffer failed"); return XCAM_RETURN_ERROR_MEM; } uint32_t sum = 0, pos = 0; info.get_planar_info (planar, 0); for (uint32_t i = 0; i < planar.height; i++) { for (uint32_t j = 0; j < planar.width / interval; j++) { pos = i * planar.width + j * interval + index; sum += (cur_mem [pos] - ref_mem [pos]) * (cur_mem [pos] - ref_mem [pos]); } } float mse = (float) sum / (planar.height * planar.width / interval) + 0.000001f; psnr = 10 * log10 (255 * 255 / mse); psnr_cur->unmap (); psnr_ref->unmap (); return ret; } static XCamReturn kernel_loop(SmartPtr<CLImageHandler> &image_handler, SmartPtr<VideoBuffer> &input_buf, SmartPtr<VideoBuffer> &output_buf, uint32_t kernel_loop_count) { XCamReturn ret = XCAM_RETURN_NO_ERROR; for (uint32_t i = 0; i < kernel_loop_count; i++) { PROFILING_START(cl_kernel); ret = image_handler->execute (input_buf, output_buf); PROFILING_END(cl_kernel, kernel_loop_count) } return ret; } static void print_help (const char *bin_name) { printf ("Usage: %s [-f format] -i input -o output\n" "\t -t type specify image handler type\n" "\t select from [demo, blacklevel, defect, demosaic, tonemapping, csc, hdr, wb, denoise," " gamma, snr, bnr, macc, ee, bayerpipe, yuvpipe, retinex, gauss, wavelet-hat, wavelet-haar, dcp, fisheye]\n" "\t -f input_format specify a input format\n" "\t -W image_width specify input image width\n" "\t -H image_height specify input image height\n" "\t -g output_format specify a output format\n" "\t select from [NV12, BA10, RGBA, RGBA64]\n" "\t -i input specify input file path\n" "\t -o output specify output file path\n" "\t -r refer specify reference file path\n" "\t -k binary_kernel specify binary kernel path\n" "\t -p count specify cl kernel loop count\n" "\t -c csc_type specify csc type, default:rgba2nv12\n" "\t select from [rgbatonv12, rgbatolab, rgba64torgba, yuyvtorgba, nv12torgba]\n" "\t -b enable bayer-nr, default: disable\n" "\t -P enable psnr calculation, default: disable\n" "\t -h help\n" , bin_name); printf ("Note:\n" "Usage of binary kernel:\n" "1. generate binary kernel:\n" " $ test-binary-kernel --src-kernel kernel_demo.cl --bin-kernel kernel_demo.cl.bin" " --kernel-name kernel_demo\n" "2. execute binary kernel:\n" " $ test-cl-image -t demo -f BA10 -i input.raw -o output.raw -k kernel_demo.cl.bin\n"); } int main (int argc, char *argv[]) { uint32_t input_format = 0; uint32_t output_format = V4L2_PIX_FMT_RGBA32; uint32_t width = 1920; uint32_t height = 1080; uint32_t buf_count = 0; int32_t kernel_loop_count = 0; const char *input_file = NULL, *output_file = NULL, *refer_file = NULL; const char *bin_kernel_path = NULL; ImageFileHandle input_fp, output_fp, refer_fp; const char *bin_name = argv[0]; TestHandlerType handler_type = TestHandlerUnknown; XCamReturn ret = XCAM_RETURN_NO_ERROR; SmartPtr<CLImageHandler> image_handler; VideoBufferInfo input_buf_info; SmartPtr<CLContext> context; SmartPtr<BufferPool> buf_pool; int opt = 0; CLCscType csc_type = CL_CSC_TYPE_RGBATONV12; bool enable_bnr = false; bool enable_psnr = false; while ((opt = getopt(argc, argv, "f:W:H:i:o:r:t:k:p:c:g:bPh")) != -1) { switch (opt) { case 'i': input_file = optarg; break; case 'o': output_file = optarg; break; case 'r': refer_file = optarg; break; case 'f': { if (!strcasecmp (optarg, "nv12")) input_format = V4L2_PIX_FMT_NV12; else if (!strcasecmp (optarg, "ba10")) input_format = V4L2_PIX_FMT_SGRBG10; else if (! strcasecmp (optarg, "rgba")) input_format = V4L2_PIX_FMT_RGBA32; else if (! strcasecmp (optarg, "rgba64")) input_format = XCAM_PIX_FMT_RGBA64; else if (!strcasecmp (optarg, "ba12")) input_format = V4L2_PIX_FMT_SGRBG12; else print_help (bin_name); break; } case 'W': { width = atoi (optarg); break; } case 'H': { height = atoi (optarg); break; } case 'g': { if (!strcasecmp (optarg, "nv12")) output_format = V4L2_PIX_FMT_NV12; else if (!strcasecmp (optarg, "ba10")) output_format = V4L2_PIX_FMT_SGRBG10; else if (! strcasecmp (optarg, "rgba")) output_format = V4L2_PIX_FMT_RGBA32; else if (! strcasecmp (optarg, "rgba64")) output_format = XCAM_PIX_FMT_RGBA64; else print_help (bin_name); break; } case 't': { if (!strcasecmp (optarg, "demo")) handler_type = TestHandlerDemo; else if (!strcasecmp (optarg, "csc")) handler_type = TestHandlerColorConversion; else if (!strcasecmp (optarg, "bayerpipe")) handler_type = TestHandlerBayerPipe; else if (!strcasecmp (optarg, "yuvpipe")) handler_type = TestHandlerYuvPipe; else if (!strcasecmp (optarg, "tonemapping")) handler_type = TestHandlerTonemapping; else if (!strcasecmp (optarg, "retinex")) handler_type = TestHandlerRetinex; else if (!strcasecmp (optarg, "gauss")) handler_type = TestHandlerGauss; else if (!strcasecmp (optarg, "wavelet-hat")) handler_type = TestHandlerHatWavelet; else if (!strcasecmp (optarg, "wavelet-haar")) handler_type = TestHandlerHaarWavelet; else if (!strcasecmp (optarg, "dcp")) handler_type = TestHandlerDefogDcp; else if (!strcasecmp (optarg, "3d-denoise")) handler_type = TestHandler3DDenoise; else if (!strcasecmp (optarg, "warp")) handler_type = TestHandlerImageWarp; else if (!strcasecmp (optarg, "fisheye")) handler_type = TestHandlerFisheye; else print_help (bin_name); break; } case 'k': bin_kernel_path = optarg; break; case 'p': kernel_loop_count = atoi (optarg); XCAM_ASSERT (kernel_loop_count >= 0 && kernel_loop_count < INT32_MAX); break; case 'c': if (!strcasecmp (optarg, "rgbatonv12")) csc_type = CL_CSC_TYPE_RGBATONV12; else if (!strcasecmp (optarg, "rgbatolab")) csc_type = CL_CSC_TYPE_RGBATOLAB; else if (!strcasecmp (optarg, "rgba64torgba")) csc_type = CL_CSC_TYPE_RGBA64TORGBA; else if (!strcasecmp (optarg, "yuyvtorgba")) csc_type = CL_CSC_TYPE_YUYVTORGBA; else if (!strcasecmp (optarg, "nv12torgba")) csc_type = CL_CSC_TYPE_NV12TORGBA; else print_help (bin_name); break; case 'b': enable_bnr = true; break; case 'P': enable_psnr = true; break; case 'h': print_help (bin_name); return 0; default: print_help (bin_name); return -1; } } if (!input_format || !input_file || !output_file || (enable_psnr && !refer_file) || handler_type == TestHandlerUnknown) { print_help (bin_name); return -1; } ret = input_fp.open (input_file, "rb"); CHECK (ret, "open input file(%s) failed", XCAM_STR (input_file)); ret = output_fp.open (output_file, "wb"); CHECK (ret, "open output file(%s) failed", XCAM_STR (output_file)); if (enable_psnr) { refer_fp.open (refer_file, "rb"); CHECK (ret, "open reference file(%s) failed", XCAM_STR (refer_file)); } context = CLDevice::instance ()->get_context (); switch (handler_type) { case TestHandlerDemo: if (!bin_kernel_path) image_handler = create_cl_demo_image_handler (context); else { FileHandle file; if (file.open (bin_kernel_path, "r") != XCAM_RETURN_NO_ERROR) { XCAM_LOG_ERROR ("open binary kernel failed"); return -1; } size_t size; if (file.get_file_size (size) != XCAM_RETURN_NO_ERROR) { XCAM_LOG_ERROR ("get binary kernel size failed"); return -1; } uint8_t *binary = (uint8_t *) xcam_malloc0 (sizeof (uint8_t) * (size)); XCAM_ASSERT (binary); if (file.read_file (binary, size) != XCAM_RETURN_NO_ERROR) { XCAM_LOG_ERROR ("read binary kernel failed"); xcam_free (binary); return -1; } image_handler = create_cl_binary_demo_image_handler (context, binary, size); xcam_free (binary); } break; case TestHandlerColorConversion: { SmartPtr<CLCscImageHandler> csc_handler; XCam3aResultColorMatrix color_matrix; xcam_mem_clear (color_matrix); double matrix_table[XCAM_COLOR_MATRIX_SIZE] = {0.299, 0.587, 0.114, -0.14713, -0.28886, 0.436, 0.615, -0.51499, -0.10001}; memcpy (color_matrix.matrix, matrix_table, sizeof(double)*XCAM_COLOR_MATRIX_SIZE); image_handler = create_cl_csc_image_handler (context, csc_type); csc_handler = image_handler.dynamic_cast_ptr<CLCscImageHandler> (); XCAM_ASSERT (csc_handler.ptr ()); csc_handler->set_matrix(color_matrix); break; } case TestHandlerBayerPipe: { image_handler = create_cl_bayer_pipe_image_handler (context); SmartPtr<CLBayerPipeImageHandler> bayer_pipe = image_handler.dynamic_cast_ptr<CLBayerPipeImageHandler> (); XCAM_ASSERT (bayer_pipe.ptr ()); bayer_pipe->set_output_format (output_format); bayer_pipe->enable_denoise (enable_bnr); break; } case TestHandlerYuvPipe: { image_handler = create_cl_yuv_pipe_image_handler (context); SmartPtr<CLYuvPipeImageHandler> yuv_pipe = image_handler.dynamic_cast_ptr<CLYuvPipeImageHandler> (); XCAM_ASSERT (yuv_pipe.ptr ()); break; } case TestHandlerTonemapping: { image_handler = create_cl_tonemapping_image_handler (context); SmartPtr<CLTonemappingImageHandler> tonemapping_pipe = image_handler.dynamic_cast_ptr<CLTonemappingImageHandler> (); XCAM_ASSERT (tonemapping_pipe.ptr ()); break; } case TestHandlerRetinex: { image_handler = create_cl_retinex_image_handler (context); SmartPtr<CLRetinexImageHandler> retinex = image_handler.dynamic_cast_ptr<CLRetinexImageHandler> (); XCAM_ASSERT (retinex.ptr ()); break; } case TestHandlerGauss: { image_handler = create_cl_gauss_image_handler (context); SmartPtr<CLGaussImageHandler> gauss = image_handler.dynamic_cast_ptr<CLGaussImageHandler> (); XCAM_ASSERT (gauss.ptr ()); break; } case TestHandlerHatWavelet: { image_handler = create_cl_wavelet_denoise_image_handler (context, CL_IMAGE_CHANNEL_UV); SmartPtr<CLWaveletDenoiseImageHandler> wavelet = image_handler.dynamic_cast_ptr<CLWaveletDenoiseImageHandler> (); XCAM_ASSERT (wavelet.ptr ()); XCam3aResultWaveletNoiseReduction wavelet_config; xcam_mem_clear (wavelet_config); wavelet_config.threshold[0] = 0.2; wavelet_config.threshold[1] = 0.5; wavelet_config.decomposition_levels = 4; wavelet_config.analog_gain = 0.001; wavelet->set_denoise_config (wavelet_config); break; } case TestHandlerHaarWavelet: { image_handler = create_cl_newwavelet_denoise_image_handler (context, CL_IMAGE_CHANNEL_UV | CL_IMAGE_CHANNEL_Y, false); SmartPtr<CLNewWaveletDenoiseImageHandler> wavelet = image_handler.dynamic_cast_ptr<CLNewWaveletDenoiseImageHandler> (); XCAM_ASSERT (wavelet.ptr ()); XCam3aResultWaveletNoiseReduction wavelet_config; wavelet_config.threshold[0] = 0.2; wavelet_config.threshold[1] = 0.5; wavelet_config.decomposition_levels = 4; wavelet_config.analog_gain = 0.001; wavelet->set_denoise_config (wavelet_config); break; } case TestHandlerDefogDcp: { image_handler = create_cl_defog_dcp_image_handler (context); XCAM_ASSERT (image_handler.ptr ()); break; } case TestHandler3DDenoise: { uint8_t ref_count = 2; image_handler = create_cl_3d_denoise_image_handler (context, CL_IMAGE_CHANNEL_Y | CL_IMAGE_CHANNEL_UV, ref_count); SmartPtr<CL3DDenoiseImageHandler> denoise = image_handler.dynamic_cast_ptr<CL3DDenoiseImageHandler> (); XCAM_ASSERT (denoise.ptr ()); XCam3aResultTemporalNoiseReduction denoise_config; xcam_mem_clear (denoise_config); denoise_config.threshold[0] = 0.05; denoise_config.threshold[1] = 0.05; denoise_config.gain = 0.6; denoise->set_denoise_config (denoise_config); break; } case TestHandlerImageWarp: { image_handler = create_cl_image_warp_handler (context); SmartPtr<CLImageWarpHandler> warp = image_handler.dynamic_cast_ptr<CLImageWarpHandler> (); XCAM_ASSERT (warp.ptr ()); XCamDVSResult warp_config; xcam_mem_clear (warp_config); warp_config.frame_id = 1; warp_config.frame_width = width; warp_config.frame_height = height; float theta = -10.0f; float phi = 10.0f; float shift_x = -0.2f * width; float shift_y = 0.2f * height; float scale_x = 2.0f; float scale_y = 0.5f; float shear_x = tan(theta * 3.1415926 / 180.0f); float shear_y = tan(phi * 3.1415926 / 180.0f); float project_x = 2.0f / width; float project_y = -1.0f / height; warp_config.proj_mat[0] = scale_x; warp_config.proj_mat[1] = shear_x; warp_config.proj_mat[2] = shift_x; warp_config.proj_mat[3] = shear_y; warp_config.proj_mat[4] = scale_y; warp_config.proj_mat[5] = shift_y; warp_config.proj_mat[6] = project_x; warp_config.proj_mat[7] = project_y; warp_config.proj_mat[8] = 1.0f; warp->set_warp_config (warp_config); break; } case TestHandlerFisheye: { image_handler = create_fisheye_handler (context); SmartPtr<CLFisheyeHandler> fisheye = image_handler.dynamic_cast_ptr<CLFisheyeHandler> (); XCAM_ASSERT (fisheye.ptr ()); FisheyeInfo fisheye_info; //fisheye0 {480.0f, 480.0f, 190.0f, 480.0f, -90.0f}, //fisheye1 {1440.0f, 480.0f, 190.0f, 480.0f, 90.0f} fisheye_info.center_x = 480.0f; fisheye_info.center_y = 480.0f; fisheye_info.wide_angle = 190.0f; fisheye_info.radius = 480.0f; fisheye_info.rotate_angle = -90.0f; fisheye->set_fisheye_info (fisheye_info); fisheye->set_dst_range (210.0f, 180.0f); fisheye->set_output_size (1120, 960); break; } default: XCAM_LOG_ERROR ("unsupported image handler type:%d", handler_type); return -1; } if (!image_handler.ptr ()) { XCAM_LOG_ERROR ("create image_handler failed"); return -1; } input_buf_info.init (input_format, width, height); buf_pool = new CLVideoBufferPool (); image_handler->set_pool_type (CLImageHandler::CLVideoPoolType); buf_pool->set_video_info (input_buf_info); if (!buf_pool->reserve (6)) { XCAM_LOG_ERROR ("init buffer pool failed"); return -1; } SmartPtr<VideoBuffer> input_buf, output_buf, psnr_cur, psnr_ref; while (true) { input_buf = buf_pool->get_buffer (buf_pool); XCAM_ASSERT (input_buf.ptr ()); ret = input_fp.read_buf (input_buf); if (ret == XCAM_RETURN_BYPASS) break; if (ret == XCAM_RETURN_ERROR_FILE) { XCAM_LOG_ERROR ("read buffer from %s failed", XCAM_STR (input_file)); return -1; } if (kernel_loop_count != 0) { kernel_loop (image_handler, input_buf, output_buf, kernel_loop_count); CHECK (ret, "execute kernels failed"); return 0; } ret = image_handler->execute (input_buf, output_buf); CHECK_EXP ((ret == XCAM_RETURN_NO_ERROR || ret == XCAM_RETURN_BYPASS), "execute kernels failed"); if (ret == XCAM_RETURN_BYPASS) continue; context->finish (); XCAM_ASSERT (output_buf.ptr ()); ret = output_fp.write_buf (output_buf); CHECK (ret, "write buffer to %s failed", XCAM_STR (output_file)); psnr_cur = output_buf; ++buf_count; } XCAM_LOG_INFO ("processed %d buffers successfully", buf_count); if (enable_psnr) { buf_pool = new CLVideoBufferPool (); XCAM_ASSERT (buf_pool.ptr ()); buf_pool->set_video_info (input_buf_info); if (!buf_pool->reserve (6)) { XCAM_LOG_ERROR ("init buffer pool failed"); return -1; } psnr_ref = buf_pool->get_buffer (buf_pool); XCAM_ASSERT (psnr_ref.ptr ()); ret = refer_fp.read_buf (psnr_ref); CHECK (ret, "read buffer from %s failed", refer_file); float psnr = 0.0f; ret = calculate_psnr (psnr_cur, psnr_ref, PSNRY, psnr); CHECK (ret, "calculate PSNR_Y failed"); XCAM_LOG_INFO ("PSNR_Y: %.2f", psnr); image_handler = create_cl_csc_image_handler (context, CL_CSC_TYPE_NV12TORGBA); XCAM_ASSERT (image_handler.ptr ()); SmartPtr<VideoBuffer> psnr_cur_output, psnr_ref_output; ret = image_handler->execute (psnr_cur, psnr_cur_output); CHECK (ret, "execute kernels failed"); XCAM_ASSERT (psnr_cur_output.ptr ()); ret = image_handler->execute (psnr_ref, psnr_ref_output); CHECK (ret, "execute kernels failed"); XCAM_ASSERT (psnr_ref_output.ptr ()); ret = calculate_psnr (psnr_cur_output, psnr_ref_output, PSNRR, psnr); CHECK (ret, "calculate PSNR_R failed"); XCAM_LOG_INFO ("PSNR_R: %.2f", psnr); ret = calculate_psnr (psnr_cur_output, psnr_ref_output, PSNRG, psnr); CHECK (ret, "calculate PSNR_G failed"); XCAM_LOG_INFO ("PSNR_G: %.2f", psnr); ret = calculate_psnr (psnr_cur_output, psnr_ref_output, PSNRB, psnr); CHECK (ret, "calculate PSNR_B failed"); XCAM_LOG_INFO ("PSNR_B: %.2f", psnr); } return 0; }