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