• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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@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;
FileFPFileFP40     FileFP ()
41         : fp (NULL)
42     {}
~FileFPFileFP43     ~FileFP ()
44     {
45         if (fp)
46             fclose (fp);
47         fp = NULL;
48     }
49 };
50 
51 class MainPipeManager
52     : public PipeManager
53 {
54 public:
MainPipeManager()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 
set_image_width(uint32_t image_width)66     void set_image_width (uint32_t image_width) {
67         _image_width = image_width;
68     }
69 
set_image_height(uint32_t image_height)70     void set_image_height (uint32_t image_height) {
71         _image_height = image_height;
72     }
73 
enable_display(bool value)74     void enable_display (bool value) {
75         _enable_display = value;
76     }
77 
78 #if HAVE_LIBDRM
set_display_mode(DrmDisplayMode mode)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
post_buffer(const SmartPtr<VideoBuffer> & buf)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
display_buf(const SmartPtr<VideoBuffer> & data)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
read_buf(SmartPtr<VideoBuffer> & buf,FileFP & file)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 
pipe_stop_handler(int sig)166 void pipe_stop_handler(int sig)
167 {
168     XCAM_UNUSED (sig);
169     is_stop = true;
170 }
171 
print_help(const char * bin_name)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 
main(int argc,char * argv[])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