| /* |
| * test-pipe-manager.cpp -test pipe manager |
| * |
| * Copyright (c) 2016 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: Yinhang Liu <[email protected]> |
| */ |
| |
| #include <pipe_manager.h> |
| #include <smart_analyzer_loader.h> |
| #include <ocl/cl_post_image_processor.h> |
| #if HAVE_LIBDRM |
| #include <drm_display.h> |
| #endif |
| #include <getopt.h> |
| #include <test_common.h> |
| #include <signal.h> |
| #include <stdio.h> |
| |
| #define DEFAULT_FPT_BUF_COUNT 32 |
| |
| using namespace XCam; |
| |
| static bool is_stop = false; |
| |
| struct FileFP { |
| FILE *fp; |
| FileFP () |
| : fp (NULL) |
| {} |
| ~FileFP () |
| { |
| if (fp) |
| fclose (fp); |
| fp = NULL; |
| } |
| }; |
| |
| class MainPipeManager |
| : public PipeManager |
| { |
| public: |
| MainPipeManager () |
| : _image_width (0) |
| , _image_height (0) |
| , _enable_display (false) |
| { |
| #if HAVE_LIBDRM |
| _display = DrmDisplay::instance (); |
| #endif |
| XCAM_OBJ_PROFILING_INIT; |
| } |
| |
| void set_image_width (uint32_t image_width) { |
| _image_width = image_width; |
| } |
| |
| void set_image_height (uint32_t image_height) { |
| _image_height = image_height; |
| } |
| |
| void enable_display (bool value) { |
| _enable_display = value; |
| } |
| |
| #if HAVE_LIBDRM |
| void set_display_mode (DrmDisplayMode mode) { |
| _display->set_display_mode (mode); |
| } |
| #endif |
| |
| protected: |
| virtual void post_buffer (const SmartPtr<VideoBuffer> &buf); |
| int display_buf (const SmartPtr<VideoBuffer> &buf); |
| |
| private: |
| uint32_t _image_width; |
| uint32_t _image_height; |
| bool _enable_display; |
| #if HAVE_LIBDRM |
| SmartPtr<DrmDisplay> _display; |
| #endif |
| XCAM_OBJ_PROFILING_DEFINES; |
| }; |
| |
| void |
| MainPipeManager::post_buffer (const SmartPtr<VideoBuffer> &buf) |
| { |
| FPS_CALCULATION (fps_buf, XCAM_OBJ_DUR_FRAME_NUM); |
| |
| XCAM_OBJ_PROFILING_START; |
| |
| if (_enable_display) |
| display_buf (buf); |
| |
| XCAM_OBJ_PROFILING_END("main_pipe_manager_display", XCAM_OBJ_DUR_FRAME_NUM); |
| } |
| |
| int |
| MainPipeManager::display_buf (const SmartPtr<VideoBuffer> &data) |
| { |
| #if HAVE_LIBDRM |
| XCamReturn ret = XCAM_RETURN_NO_ERROR; |
| SmartPtr<VideoBuffer> buf = data; |
| const VideoBufferInfo & frame_info = buf->get_video_info (); |
| struct v4l2_rect rect = { 0, 0, frame_info.width, frame_info.height}; |
| |
| if (!_display->is_render_inited ()) { |
| ret = _display->render_init (0, 0, this->_image_width, this->_image_height, |
| frame_info.format, &rect); |
| CHECK (ret, "display failed on render_init"); |
| } |
| ret = _display->render_setup_frame_buffer (buf); |
| CHECK (ret, "display failed on framebuf set"); |
| ret = _display->render_buffer (buf); |
| CHECK (ret, "display failed on rendering"); |
| #else |
| XCAM_UNUSED (data); |
| #endif |
| |
| return 0; |
| } |
| |
| XCamReturn |
| read_buf (SmartPtr<VideoBuffer> &buf, FileFP &file) |
| { |
| const VideoBufferInfo info = buf->get_video_info (); |
| VideoBufferPlanarInfo planar; |
| XCamReturn ret = XCAM_RETURN_NO_ERROR; |
| |
| uint8_t *memory = buf->map (); |
| for (uint32_t index = 0; index < info.components; index++) { |
| info.get_planar_info (planar, index); |
| uint32_t line_bytes = planar.width * planar.pixel_bytes; |
| |
| for (uint32_t i = 0; i < planar.height; i++) { |
| if (fread (memory + info.offsets [index] + i * info.strides [index], 1, line_bytes, file.fp) != line_bytes) { |
| if (feof (file.fp)) { |
| fseek (file.fp, 0, SEEK_SET); |
| ret = XCAM_RETURN_BYPASS; |
| } else { |
| XCAM_LOG_ERROR ("read file failed, size doesn't match"); |
| ret = XCAM_RETURN_ERROR_FILE; |
| } |
| goto done; |
| } |
| } |
| } |
| done: |
| buf->unmap (); |
| return ret; |
| } |
| |
| void pipe_stop_handler(int sig) |
| { |
| XCAM_UNUSED (sig); |
| is_stop = true; |
| } |
| |
| void print_help (const char *bin_name) |
| { |
| printf ("Usage: %s [--format=NV12] [--width=1920] ...\n" |
| "\t --format specify output pixel format, default is NV12\n" |
| "\t --width specify input image width, default is 1920\n" |
| "\t --height specify input image height, default is 1080\n" |
| "\t --fake-input specify the path of image as fake source\n" |
| "\t --defog-mode specify defog mode\n" |
| "\t select from [disabled, retinex, dcp], default is [disabled]\n" |
| "\t --wavelet-mode specify wavelet denoise mode, default is disable\n" |
| "\t select from [0:disable, 1:Hat Y, 2:Hat UV, 3:Haar Y, 4:Haar UV, 5:Haar YUV, 6:Haar Bayes Shrink]\n" |
| "\t --3d-denoise specify 3D Denoise mode\n" |
| "\t select from [disabled, yuv, uv], default is [disabled]\n" |
| "\t --enable-wireframe enable wire frame\n" |
| "\t --enable-warp enable image warp\n" |
| "\t --display-mode display mode\n" |
| "\t select from [primary, overlay], default is [primary]\n" |
| "\t -p enable local display, need root privilege\n" |
| "\t -h help\n" |
| , bin_name); |
| } |
| |
| int main (int argc, char *argv[]) |
| { |
| const char *bin_name = argv[0]; |
| |
| XCamReturn ret = XCAM_RETURN_NO_ERROR; |
| VideoBufferInfo buf_info; |
| SmartPtr<VideoBuffer> video_buf; |
| SmartPtr<SmartAnalyzer> smart_analyzer; |
| SmartPtr<CLPostImageProcessor> cl_post_processor; |
| SmartPtr<BufferPool> buf_pool; |
| |
| uint32_t pixel_format = V4L2_PIX_FMT_NV12; |
| uint32_t image_width = 1920; |
| uint32_t image_height = 1080; |
| bool need_display = false; |
| #if HAVE_LIBDRM |
| DrmDisplayMode display_mode = DRM_DISPLAY_MODE_PRIMARY; |
| #endif |
| const char *input_path = NULL; |
| FileFP input_fp; |
| |
| uint32_t defog_mode = 0; |
| CLWaveletBasis wavelet_mode = CL_WAVELET_DISABLED; |
| uint32_t wavelet_channel = CL_IMAGE_CHANNEL_UV; |
| bool wavelet_bayes_shrink = false; |
| uint32_t denoise_3d_mode = 0; |
| uint8_t denoise_3d_ref_count = 3; |
| bool enable_wireframe = false; |
| bool enable_image_warp = false; |
| |
| int opt; |
| const char *short_opts = "ph"; |
| const struct option long_opts [] = { |
| {"format", required_argument, NULL, 'F'}, |
| {"width", required_argument, NULL, 'W'}, |
| {"height", required_argument, NULL, 'H'}, |
| {"fake-input", required_argument, NULL, 'A'}, |
| {"defog-mode", required_argument, NULL, 'D'}, |
| {"wavelet-mode", required_argument, NULL, 'V'}, |
| {"3d-denoise", required_argument, NULL, 'N'}, |
| {"enable-wireframe", no_argument, NULL, 'I'}, |
| {"enable-warp", no_argument, NULL, 'S'}, |
| {"display-mode", required_argument, NULL, 'P'}, |
| {NULL, 0, NULL, 0} |
| }; |
| |
| while ((opt = getopt_long (argc, argv, short_opts, long_opts, NULL)) != -1) { |
| switch (opt) { |
| case 'F': { |
| XCAM_ASSERT (optarg); |
| CHECK_EXP ((strlen (optarg) == 4), "invalid pixel format\n"); |
| pixel_format = v4l2_fourcc ((unsigned) optarg[0], |
| (unsigned) optarg[1], |
| (unsigned) optarg[2], |
| (unsigned) optarg[3]); |
| break; |
| } |
| case 'W': { |
| XCAM_ASSERT (optarg); |
| image_width = atoi (optarg); |
| break; |
| } |
| case 'H': { |
| XCAM_ASSERT (optarg); |
| image_height = atoi (optarg); |
| break; |
| } |
| case 'A': { |
| XCAM_ASSERT (optarg); |
| XCAM_LOG_INFO ("use image %s as input source", optarg); |
| input_path = optarg; |
| break; |
| } |
| case 'D': { |
| XCAM_ASSERT (optarg); |
| if (!strcmp (optarg, "disabled")) |
| defog_mode = CLPostImageProcessor::DefogDisabled; |
| else if (!strcmp (optarg, "retinex")) |
| defog_mode = CLPostImageProcessor::DefogRetinex; |
| else if (!strcmp (optarg, "dcp")) |
| defog_mode = CLPostImageProcessor::DefogDarkChannelPrior; |
| else { |
| print_help (bin_name); |
| return -1; |
| } |
| break; |
| } |
| case 'V': { |
| XCAM_ASSERT (optarg); |
| if (atoi(optarg) < 0 || atoi(optarg) > 255) { |
| print_help (bin_name); |
| return -1; |
| } |
| if (atoi(optarg) == 1) { |
| wavelet_mode = CL_WAVELET_HAT; |
| wavelet_channel = CL_IMAGE_CHANNEL_Y; |
| } else if (atoi(optarg) == 2) { |
| wavelet_mode = CL_WAVELET_HAT; |
| wavelet_channel = CL_IMAGE_CHANNEL_UV; |
| } else if (atoi(optarg) == 3) { |
| wavelet_mode = CL_WAVELET_HAAR; |
| wavelet_channel = CL_IMAGE_CHANNEL_Y; |
| } else if (atoi(optarg) == 4) { |
| wavelet_mode = CL_WAVELET_HAAR; |
| wavelet_channel = CL_IMAGE_CHANNEL_UV; |
| } else if (atoi(optarg) == 5) { |
| wavelet_mode = CL_WAVELET_HAAR; |
| wavelet_channel = CL_IMAGE_CHANNEL_UV | CL_IMAGE_CHANNEL_Y; |
| } else if (atoi(optarg) == 6) { |
| wavelet_mode = CL_WAVELET_HAAR; |
| wavelet_channel = CL_IMAGE_CHANNEL_UV | CL_IMAGE_CHANNEL_Y; |
| wavelet_bayes_shrink = true; |
| } else { |
| wavelet_mode = CL_WAVELET_DISABLED; |
| } |
| break; |
| } |
| case 'N': { |
| XCAM_ASSERT (optarg); |
| if (!strcmp (optarg, "disabled")) |
| denoise_3d_mode = CLPostImageProcessor::Denoise3DDisabled; |
| else if (!strcmp (optarg, "yuv")) |
| denoise_3d_mode = CLPostImageProcessor::Denoise3DYuv; |
| else if (!strcmp (optarg, "uv")) |
| denoise_3d_mode = CLPostImageProcessor::Denoise3DUV; |
| else { |
| print_help (bin_name); |
| return -1; |
| } |
| break; |
| } |
| case 'I': { |
| enable_wireframe = true; |
| break; |
| } |
| case 'S': { |
| enable_image_warp = true; |
| break; |
| } |
| case 'P': { |
| #if HAVE_LIBDRM |
| XCAM_ASSERT (optarg); |
| if (!strcmp (optarg, "primary")) |
| display_mode = DRM_DISPLAY_MODE_PRIMARY; |
| else if (!strcmp (optarg, "overlay")) |
| display_mode = DRM_DISPLAY_MODE_OVERLAY; |
| else { |
| print_help (bin_name); |
| return -1; |
| } |
| #else |
| XCAM_LOG_WARNING ("preview is not supported"); |
| #endif |
| break; |
| } |
| case 'p': { |
| #if HAVE_LIBDRM |
| need_display = true; |
| #else |
| XCAM_LOG_WARNING ("preview is not supported, disable preview now"); |
| need_display = false; |
| #endif |
| break; |
| } |
| case 'h': |
| print_help (bin_name); |
| return 0; |
| default: |
| print_help (bin_name); |
| return -1; |
| } |
| } |
| |
| signal (SIGINT, pipe_stop_handler); |
| |
| if (!input_path) { |
| XCAM_LOG_ERROR ("path of image is NULL"); |
| return -1; |
| } |
| input_fp.fp = fopen (input_path, "rb"); |
| if (!input_fp.fp) { |
| XCAM_LOG_ERROR ("failed to open file: %s", XCAM_STR (input_path)); |
| return -1; |
| } |
| |
| SmartPtr<MainPipeManager> pipe_manager = new MainPipeManager (); |
| pipe_manager->set_image_width (image_width); |
| pipe_manager->set_image_height (image_height); |
| |
| SmartHandlerList smart_handlers = SmartAnalyzerLoader::load_smart_handlers (DEFAULT_SMART_ANALYSIS_LIB_DIR); |
| if (!smart_handlers.empty () ) { |
| smart_analyzer = new SmartAnalyzer (); |
| if (smart_analyzer.ptr ()) { |
| SmartHandlerList::iterator i_handler = smart_handlers.begin (); |
| for (; i_handler != smart_handlers.end (); ++i_handler) { |
| XCAM_ASSERT ((*i_handler).ptr ()); |
| smart_analyzer->add_handler (*i_handler); |
| } |
| } else { |
| XCAM_LOG_INFO ("load smart analyzer(%s) failed", DEFAULT_SMART_ANALYSIS_LIB_DIR); |
| } |
| } |
| if (smart_analyzer.ptr ()) { |
| if (smart_analyzer->prepare_handlers () != XCAM_RETURN_NO_ERROR) { |
| XCAM_LOG_WARNING ("analyzer(%s) prepare handlers failed", smart_analyzer->get_name ()); |
| } |
| pipe_manager->set_smart_analyzer (smart_analyzer); |
| } |
| |
| cl_post_processor = new CLPostImageProcessor (); |
| cl_post_processor->set_stats_callback (pipe_manager); |
| cl_post_processor->set_defog_mode ((CLPostImageProcessor::CLDefogMode) defog_mode); |
| cl_post_processor->set_wavelet (wavelet_mode, wavelet_channel, wavelet_bayes_shrink); |
| cl_post_processor->set_3ddenoise_mode ((CLPostImageProcessor::CL3DDenoiseMode) denoise_3d_mode, denoise_3d_ref_count); |
| |
| cl_post_processor->set_wireframe (enable_wireframe); |
| cl_post_processor->set_image_warp (enable_image_warp); |
| if (smart_analyzer.ptr () && (enable_wireframe || enable_image_warp)) { |
| cl_post_processor->set_scaler (true); |
| cl_post_processor->set_scaler_factor (640.0 / image_width); |
| } |
| |
| pipe_manager->add_image_processor (cl_post_processor); |
| |
| buf_info.init (pixel_format, image_width, image_height); |
| buf_pool = new CLVideoBufferPool (); |
| XCAM_ASSERT (buf_pool.ptr ()); |
| if (!buf_pool->set_video_info (buf_info) || !buf_pool->reserve (DEFAULT_FPT_BUF_COUNT)) { |
| XCAM_LOG_ERROR ("init buffer pool failed"); |
| return -1; |
| } |
| |
| if (need_display) { |
| need_display = false; |
| XCAM_LOG_WARNING ("CLVideoBuffer doesn't support local preview, disable local preview now"); |
| } |
| |
| if (need_display) { |
| #if HAVE_LIBDRM |
| if (DrmDisplay::set_preview (need_display)) { |
| pipe_manager->set_display_mode (display_mode); |
| cl_post_processor->set_output_format (V4L2_PIX_FMT_XBGR32); |
| } else { |
| need_display = false; |
| XCAM_LOG_WARNING ("set preview failed, disable local preview now"); |
| } |
| #else |
| XCAM_LOG_WARNING ("preview is not supported, disable preview now"); |
| need_display = false; |
| #endif |
| } |
| pipe_manager->enable_display (need_display); |
| |
| ret = pipe_manager->start (); |
| CHECK (ret, "pipe manager start failed"); |
| |
| while (!is_stop) { |
| video_buf = buf_pool->get_buffer (buf_pool); |
| XCAM_ASSERT (video_buf.ptr ()); |
| |
| ret = read_buf (video_buf, input_fp); |
| if (ret == XCAM_RETURN_BYPASS) { |
| ret = read_buf (video_buf, input_fp); |
| } |
| |
| if (ret == XCAM_RETURN_NO_ERROR) |
| pipe_manager->push_buffer (video_buf); |
| } |
| |
| ret = pipe_manager->stop(); |
| CHECK (ret, "pipe manager stop failed"); |
| |
| return 0; |
| } |