1 /* 2 * test-pipe-manager.cpp -test pipe manager 3 * 4 * Copyright (c) 2016 Intel Corporation 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 * 18 * Author: Yinhang Liu <yinhangx.liu (at) intel.com> 19 */ 20 21 #include <pipe_manager.h> 22 #include <smart_analyzer_loader.h> 23 #include <ocl/cl_post_image_processor.h> 24 #if HAVE_LIBDRM 25 #include <drm_display.h> 26 #endif 27 #include <getopt.h> 28 #include <test_common.h> 29 #include <signal.h> 30 #include <stdio.h> 31 32 #define DEFAULT_FPT_BUF_COUNT 32 33 34 using namespace XCam; 35 36 static bool is_stop = false; 37 38 struct FileFP { 39 FILE *fp; 40 FileFP () 41 : fp (NULL) 42 {} 43 ~FileFP () 44 { 45 if (fp) 46 fclose (fp); 47 fp = NULL; 48 } 49 }; 50 51 class MainPipeManager 52 : public PipeManager 53 { 54 public: 55 MainPipeManager () 56 : _image_width (0) 57 , _image_height (0) 58 , _enable_display (false) 59 { 60 #if HAVE_LIBDRM 61 _display = DrmDisplay::instance (); 62 #endif 63 XCAM_OBJ_PROFILING_INIT; 64 } 65 66 void set_image_width (uint32_t image_width) { 67 _image_width = image_width; 68 } 69 70 void set_image_height (uint32_t image_height) { 71 _image_height = image_height; 72 } 73 74 void enable_display (bool value) { 75 _enable_display = value; 76 } 77 78 #if HAVE_LIBDRM 79 void set_display_mode (DrmDisplayMode mode) { 80 _display->set_display_mode (mode); 81 } 82 #endif 83 84 protected: 85 virtual void post_buffer (const SmartPtr<VideoBuffer> &buf); 86 int display_buf (const SmartPtr<VideoBuffer> &buf); 87 88 private: 89 uint32_t _image_width; 90 uint32_t _image_height; 91 bool _enable_display; 92 #if HAVE_LIBDRM 93 SmartPtr<DrmDisplay> _display; 94 #endif 95 XCAM_OBJ_PROFILING_DEFINES; 96 }; 97 98 void 99 MainPipeManager::post_buffer (const SmartPtr<VideoBuffer> &buf) 100 { 101 FPS_CALCULATION (fps_buf, XCAM_OBJ_DUR_FRAME_NUM); 102 103 XCAM_OBJ_PROFILING_START; 104 105 if (_enable_display) 106 display_buf (buf); 107 108 XCAM_OBJ_PROFILING_END("main_pipe_manager_display", XCAM_OBJ_DUR_FRAME_NUM); 109 } 110 111 int 112 MainPipeManager::display_buf (const SmartPtr<VideoBuffer> &data) 113 { 114 #if HAVE_LIBDRM 115 XCamReturn ret = XCAM_RETURN_NO_ERROR; 116 SmartPtr<VideoBuffer> buf = data; 117 const VideoBufferInfo & frame_info = buf->get_video_info (); 118 struct v4l2_rect rect = { 0, 0, frame_info.width, frame_info.height}; 119 120 if (!_display->is_render_inited ()) { 121 ret = _display->render_init (0, 0, this->_image_width, this->_image_height, 122 frame_info.format, &rect); 123 CHECK (ret, "display failed on render_init"); 124 } 125 ret = _display->render_setup_frame_buffer (buf); 126 CHECK (ret, "display failed on framebuf set"); 127 ret = _display->render_buffer (buf); 128 CHECK (ret, "display failed on rendering"); 129 #else 130 XCAM_UNUSED (data); 131 #endif 132 133 return 0; 134 } 135 136 XCamReturn 137 read_buf (SmartPtr<VideoBuffer> &buf, FileFP &file) 138 { 139 const VideoBufferInfo info = buf->get_video_info (); 140 VideoBufferPlanarInfo planar; 141 XCamReturn ret = XCAM_RETURN_NO_ERROR; 142 143 uint8_t *memory = buf->map (); 144 for (uint32_t index = 0; index < info.components; index++) { 145 info.get_planar_info (planar, index); 146 uint32_t line_bytes = planar.width * planar.pixel_bytes; 147 148 for (uint32_t i = 0; i < planar.height; i++) { 149 if (fread (memory + info.offsets [index] + i * info.strides [index], 1, line_bytes, file.fp) != line_bytes) { 150 if (feof (file.fp)) { 151 fseek (file.fp, 0, SEEK_SET); 152 ret = XCAM_RETURN_BYPASS; 153 } else { 154 XCAM_LOG_ERROR ("read file failed, size doesn't match"); 155 ret = XCAM_RETURN_ERROR_FILE; 156 } 157 goto done; 158 } 159 } 160 } 161 done: 162 buf->unmap (); 163 return ret; 164 } 165 166 void pipe_stop_handler(int sig) 167 { 168 XCAM_UNUSED (sig); 169 is_stop = true; 170 } 171 172 void print_help (const char *bin_name) 173 { 174 printf ("Usage: %s [--format=NV12] [--width=1920] ...\n" 175 "\t --format specify output pixel format, default is NV12\n" 176 "\t --width specify input image width, default is 1920\n" 177 "\t --height specify input image height, default is 1080\n" 178 "\t --fake-input specify the path of image as fake source\n" 179 "\t --defog-mode specify defog mode\n" 180 "\t select from [disabled, retinex, dcp], default is [disabled]\n" 181 "\t --wavelet-mode specify wavelet denoise mode, default is disable\n" 182 "\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" 183 "\t --3d-denoise specify 3D Denoise mode\n" 184 "\t select from [disabled, yuv, uv], default is [disabled]\n" 185 "\t --enable-wireframe enable wire frame\n" 186 "\t --enable-warp enable image warp\n" 187 "\t --display-mode display mode\n" 188 "\t select from [primary, overlay], default is [primary]\n" 189 "\t -p enable local display, need root privilege\n" 190 "\t -h help\n" 191 , bin_name); 192 } 193 194 int main (int argc, char *argv[]) 195 { 196 const char *bin_name = argv[0]; 197 198 XCamReturn ret = XCAM_RETURN_NO_ERROR; 199 VideoBufferInfo buf_info; 200 SmartPtr<VideoBuffer> video_buf; 201 SmartPtr<SmartAnalyzer> smart_analyzer; 202 SmartPtr<CLPostImageProcessor> cl_post_processor; 203 SmartPtr<BufferPool> buf_pool; 204 205 uint32_t pixel_format = V4L2_PIX_FMT_NV12; 206 uint32_t image_width = 1920; 207 uint32_t image_height = 1080; 208 bool need_display = false; 209 #if HAVE_LIBDRM 210 DrmDisplayMode display_mode = DRM_DISPLAY_MODE_PRIMARY; 211 #endif 212 const char *input_path = NULL; 213 FileFP input_fp; 214 215 uint32_t defog_mode = 0; 216 CLWaveletBasis wavelet_mode = CL_WAVELET_DISABLED; 217 uint32_t wavelet_channel = CL_IMAGE_CHANNEL_UV; 218 bool wavelet_bayes_shrink = false; 219 uint32_t denoise_3d_mode = 0; 220 uint8_t denoise_3d_ref_count = 3; 221 bool enable_wireframe = false; 222 bool enable_image_warp = false; 223 224 int opt; 225 const char *short_opts = "ph"; 226 const struct option long_opts [] = { 227 {"format", required_argument, NULL, 'F'}, 228 {"width", required_argument, NULL, 'W'}, 229 {"height", required_argument, NULL, 'H'}, 230 {"fake-input", required_argument, NULL, 'A'}, 231 {"defog-mode", required_argument, NULL, 'D'}, 232 {"wavelet-mode", required_argument, NULL, 'V'}, 233 {"3d-denoise", required_argument, NULL, 'N'}, 234 {"enable-wireframe", no_argument, NULL, 'I'}, 235 {"enable-warp", no_argument, NULL, 'S'}, 236 {"display-mode", required_argument, NULL, 'P'}, 237 {NULL, 0, NULL, 0} 238 }; 239 240 while ((opt = getopt_long (argc, argv, short_opts, long_opts, NULL)) != -1) { 241 switch (opt) { 242 case 'F': { 243 XCAM_ASSERT (optarg); 244 CHECK_EXP ((strlen (optarg) == 4), "invalid pixel format\n"); 245 pixel_format = v4l2_fourcc ((unsigned) optarg[0], 246 (unsigned) optarg[1], 247 (unsigned) optarg[2], 248 (unsigned) optarg[3]); 249 break; 250 } 251 case 'W': { 252 XCAM_ASSERT (optarg); 253 image_width = atoi (optarg); 254 break; 255 } 256 case 'H': { 257 XCAM_ASSERT (optarg); 258 image_height = atoi (optarg); 259 break; 260 } 261 case 'A': { 262 XCAM_ASSERT (optarg); 263 XCAM_LOG_INFO ("use image %s as input source", optarg); 264 input_path = optarg; 265 break; 266 } 267 case 'D': { 268 XCAM_ASSERT (optarg); 269 if (!strcmp (optarg, "disabled")) 270 defog_mode = CLPostImageProcessor::DefogDisabled; 271 else if (!strcmp (optarg, "retinex")) 272 defog_mode = CLPostImageProcessor::DefogRetinex; 273 else if (!strcmp (optarg, "dcp")) 274 defog_mode = CLPostImageProcessor::DefogDarkChannelPrior; 275 else { 276 print_help (bin_name); 277 return -1; 278 } 279 break; 280 } 281 case 'V': { 282 XCAM_ASSERT (optarg); 283 if (atoi(optarg) < 0 || atoi(optarg) > 255) { 284 print_help (bin_name); 285 return -1; 286 } 287 if (atoi(optarg) == 1) { 288 wavelet_mode = CL_WAVELET_HAT; 289 wavelet_channel = CL_IMAGE_CHANNEL_Y; 290 } else if (atoi(optarg) == 2) { 291 wavelet_mode = CL_WAVELET_HAT; 292 wavelet_channel = CL_IMAGE_CHANNEL_UV; 293 } else if (atoi(optarg) == 3) { 294 wavelet_mode = CL_WAVELET_HAAR; 295 wavelet_channel = CL_IMAGE_CHANNEL_Y; 296 } else if (atoi(optarg) == 4) { 297 wavelet_mode = CL_WAVELET_HAAR; 298 wavelet_channel = CL_IMAGE_CHANNEL_UV; 299 } else if (atoi(optarg) == 5) { 300 wavelet_mode = CL_WAVELET_HAAR; 301 wavelet_channel = CL_IMAGE_CHANNEL_UV | CL_IMAGE_CHANNEL_Y; 302 } else if (atoi(optarg) == 6) { 303 wavelet_mode = CL_WAVELET_HAAR; 304 wavelet_channel = CL_IMAGE_CHANNEL_UV | CL_IMAGE_CHANNEL_Y; 305 wavelet_bayes_shrink = true; 306 } else { 307 wavelet_mode = CL_WAVELET_DISABLED; 308 } 309 break; 310 } 311 case 'N': { 312 XCAM_ASSERT (optarg); 313 if (!strcmp (optarg, "disabled")) 314 denoise_3d_mode = CLPostImageProcessor::Denoise3DDisabled; 315 else if (!strcmp (optarg, "yuv")) 316 denoise_3d_mode = CLPostImageProcessor::Denoise3DYuv; 317 else if (!strcmp (optarg, "uv")) 318 denoise_3d_mode = CLPostImageProcessor::Denoise3DUV; 319 else { 320 print_help (bin_name); 321 return -1; 322 } 323 break; 324 } 325 case 'I': { 326 enable_wireframe = true; 327 break; 328 } 329 case 'S': { 330 enable_image_warp = true; 331 break; 332 } 333 case 'P': { 334 #if HAVE_LIBDRM 335 XCAM_ASSERT (optarg); 336 if (!strcmp (optarg, "primary")) 337 display_mode = DRM_DISPLAY_MODE_PRIMARY; 338 else if (!strcmp (optarg, "overlay")) 339 display_mode = DRM_DISPLAY_MODE_OVERLAY; 340 else { 341 print_help (bin_name); 342 return -1; 343 } 344 #else 345 XCAM_LOG_WARNING ("preview is not supported"); 346 #endif 347 break; 348 } 349 case 'p': { 350 #if HAVE_LIBDRM 351 need_display = true; 352 #else 353 XCAM_LOG_WARNING ("preview is not supported, disable preview now"); 354 need_display = false; 355 #endif 356 break; 357 } 358 case 'h': 359 print_help (bin_name); 360 return 0; 361 default: 362 print_help (bin_name); 363 return -1; 364 } 365 } 366 367 signal (SIGINT, pipe_stop_handler); 368 369 if (!input_path) { 370 XCAM_LOG_ERROR ("path of image is NULL"); 371 return -1; 372 } 373 input_fp.fp = fopen (input_path, "rb"); 374 if (!input_fp.fp) { 375 XCAM_LOG_ERROR ("failed to open file: %s", XCAM_STR (input_path)); 376 return -1; 377 } 378 379 SmartPtr<MainPipeManager> pipe_manager = new MainPipeManager (); 380 pipe_manager->set_image_width (image_width); 381 pipe_manager->set_image_height (image_height); 382 383 SmartHandlerList smart_handlers = SmartAnalyzerLoader::load_smart_handlers (DEFAULT_SMART_ANALYSIS_LIB_DIR); 384 if (!smart_handlers.empty () ) { 385 smart_analyzer = new SmartAnalyzer (); 386 if (smart_analyzer.ptr ()) { 387 SmartHandlerList::iterator i_handler = smart_handlers.begin (); 388 for (; i_handler != smart_handlers.end (); ++i_handler) { 389 XCAM_ASSERT ((*i_handler).ptr ()); 390 smart_analyzer->add_handler (*i_handler); 391 } 392 } else { 393 XCAM_LOG_INFO ("load smart analyzer(%s) failed", DEFAULT_SMART_ANALYSIS_LIB_DIR); 394 } 395 } 396 if (smart_analyzer.ptr ()) { 397 if (smart_analyzer->prepare_handlers () != XCAM_RETURN_NO_ERROR) { 398 XCAM_LOG_WARNING ("analyzer(%s) prepare handlers failed", smart_analyzer->get_name ()); 399 } 400 pipe_manager->set_smart_analyzer (smart_analyzer); 401 } 402 403 cl_post_processor = new CLPostImageProcessor (); 404 cl_post_processor->set_stats_callback (pipe_manager); 405 cl_post_processor->set_defog_mode ((CLPostImageProcessor::CLDefogMode) defog_mode); 406 cl_post_processor->set_wavelet (wavelet_mode, wavelet_channel, wavelet_bayes_shrink); 407 cl_post_processor->set_3ddenoise_mode ((CLPostImageProcessor::CL3DDenoiseMode) denoise_3d_mode, denoise_3d_ref_count); 408 409 cl_post_processor->set_wireframe (enable_wireframe); 410 cl_post_processor->set_image_warp (enable_image_warp); 411 if (smart_analyzer.ptr () && (enable_wireframe || enable_image_warp)) { 412 cl_post_processor->set_scaler (true); 413 cl_post_processor->set_scaler_factor (640.0 / image_width); 414 } 415 416 pipe_manager->add_image_processor (cl_post_processor); 417 418 buf_info.init (pixel_format, image_width, image_height); 419 buf_pool = new CLVideoBufferPool (); 420 XCAM_ASSERT (buf_pool.ptr ()); 421 if (!buf_pool->set_video_info (buf_info) || !buf_pool->reserve (DEFAULT_FPT_BUF_COUNT)) { 422 XCAM_LOG_ERROR ("init buffer pool failed"); 423 return -1; 424 } 425 426 if (need_display) { 427 need_display = false; 428 XCAM_LOG_WARNING ("CLVideoBuffer doesn't support local preview, disable local preview now"); 429 } 430 431 if (need_display) { 432 #if HAVE_LIBDRM 433 if (DrmDisplay::set_preview (need_display)) { 434 pipe_manager->set_display_mode (display_mode); 435 cl_post_processor->set_output_format (V4L2_PIX_FMT_XBGR32); 436 } else { 437 need_display = false; 438 XCAM_LOG_WARNING ("set preview failed, disable local preview now"); 439 } 440 #else 441 XCAM_LOG_WARNING ("preview is not supported, disable preview now"); 442 need_display = false; 443 #endif 444 } 445 pipe_manager->enable_display (need_display); 446 447 ret = pipe_manager->start (); 448 CHECK (ret, "pipe manager start failed"); 449 450 while (!is_stop) { 451 video_buf = buf_pool->get_buffer (buf_pool); 452 XCAM_ASSERT (video_buf.ptr ()); 453 454 ret = read_buf (video_buf, input_fp); 455 if (ret == XCAM_RETURN_BYPASS) { 456 ret = read_buf (video_buf, input_fp); 457 } 458 459 if (ret == XCAM_RETURN_NO_ERROR) 460 pipe_manager->push_buffer (video_buf); 461 } 462 463 ret = pipe_manager->stop(); 464 CHECK (ret, "pipe manager stop failed"); 465 466 return 0; 467 } 468