/* * 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 <yinhangx.liu@intel.com> */ #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; }