Home | History | Annotate | Download | only in tests
      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