1 /*
2 * test-image-blend.cpp - test cl image
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: Wind Yuan <feng.yuan@intel.com>
19 */
20
21 #include "test_common.h"
22 #include "test_inline.h"
23 #include <unistd.h>
24 #include <getopt.h>
25 #include <ocl/cl_device.h>
26 #include <ocl/cl_context.h>
27 #include <ocl/cl_blender.h>
28 #include <image_file_handle.h>
29 #include <ocl/cl_geo_map_handler.h>
30 #if HAVE_LIBDRM
31 #include <drm_display.h>
32 #endif
33 #include <dma_video_buffer.h>
34
35 using namespace XCam;
36
37 #define ENABLE_DMA_TEST 0
38
39 static uint32_t input_format = V4L2_PIX_FMT_NV12;
40 //static uint32_t output_format = V4L2_PIX_FMT_NV12;
41 static uint32_t input_width0 = 1280, input_width1 = 1280;
42 static uint32_t input_height = 960;
43 static uint32_t output_width = 1920;
44 static uint32_t output_height;
45 static bool need_save_output = true;
46 static bool enable_geo = false;
47 static bool enable_seam = false;
48
49 static int loop = 0;
50 static uint32_t map_width = 51, map_height = 43;
51 static const char *map0 = "fisheye0.csv";
52 static const char *map1 = "fisheye1.csv";
53 static char file_in0_name[XCAM_MAX_STR_SIZE], file_in1_name[XCAM_MAX_STR_SIZE], file_out_name[XCAM_MAX_STR_SIZE];
54
55 static int read_map_data (const char* file, GeoPos *map, int width, int height);
56
57 static void
usage(const char * arg0)58 usage(const char* arg0)
59 {
60 printf ("Usage:\n"
61 "%s --input0 file --input1 file --output file"
62 " [--input-w0 width] [--input-w1 width] [--input-h height] [--output-w width] \n"
63 "\t--input0, first image(NV12)\n"
64 "\t--input1, second image(NV12)\n"
65 "\t--output, output image(NV12) PREFIX\n"
66 "\t--input-w0, optional, input width; default:1280\n"
67 "\t--input-w1, optional, input width; default:1280\n"
68 "\t--input-h, optional, input height; default:960\n"
69 "\t--output-w, optional, output width; default:1920, output height is same as input height.\n"
70 "\t--loop, optional, how many loops need to run for performance test, default 0; \n"
71 "\t--save, optional, save file or not, default true; select from [true/false]\n"
72 "\t--enable-geo, optional, enable geo map image frist. default: no\n"
73 "\t--enable-seam, optional, enable seam finder in blending area. default: no\n"
74 "\t--help, usage\n",
75 arg0);
76 }
77
78 static int
geo_correct_image(SmartPtr<CLGeoMapHandler> geo_map_handler,SmartPtr<VideoBuffer> & in_out,GeoPos * geo_map0,uint32_t map_width,uint32_t map_height,char * file_name,bool need_save_output)79 geo_correct_image (
80 SmartPtr<CLGeoMapHandler> geo_map_handler, SmartPtr<VideoBuffer> &in_out,
81 GeoPos *geo_map0, uint32_t map_width, uint32_t map_height,
82 char *file_name, bool need_save_output)
83 {
84 XCamReturn ret = XCAM_RETURN_NO_ERROR;
85 SmartPtr<VideoBuffer> geo_out;
86 geo_map_handler->set_map_data (geo_map0, map_width, map_height);
87 ret = geo_map_handler->execute (in_out, geo_out);
88 CHECK (ret, "geo map handler execute inpu0 failed");
89 XCAM_ASSERT (geo_out.ptr ());
90 in_out = geo_out;
91
92 if (need_save_output) {
93 char gdc_dump_name[1024];
94 snprintf (gdc_dump_name, 1024, "gdc-%s", file_name);
95 ImageFileHandle file_out;
96 file_out.open (gdc_dump_name, "wb");
97 file_out.write_buf (geo_out);
98 file_out.close ();
99 printf ("write gdc output buffer to: %s done\n", gdc_dump_name);
100 }
101 return 0;
102 }
103
104 #if (ENABLE_DMA_TEST) && (HAVE_LIBDRM)
105 static SmartPtr<VideoBuffer>
dma_buf_to_xcam_buf(SmartPtr<DrmDisplay> display,int dma_fd,uint32_t width,uint32_t height,uint32_t size,uint32_t aligned_width=0,uint32_t aligned_height=0)106 dma_buf_to_xcam_buf (
107 SmartPtr<DrmDisplay> display, int dma_fd,
108 uint32_t width, uint32_t height, uint32_t size,
109 uint32_t aligned_width = 0, uint32_t aligned_height = 0)
110 {
111 /*
112 *
113 * XCAM_ASSERT (native_handle_t.numFds == 1);
114 * XCAM_ASSERT (native_handle_t.data[0] > 0);
115 * dma_fd = native_handle_t.data[0] ;
116 */;
117 VideoBufferInfo info;
118 SmartPtr<VideoBuffer> dma_buf;
119 SmartPtr<VideoBuffer> output;
120
121 XCAM_ASSERT (dma_fd > 0);
122
123 if (aligned_width == 0)
124 aligned_width = XCAM_ALIGN_UP(width, 16);
125 if (aligned_height == 0)
126 aligned_height = XCAM_ALIGN_UP(height, 16);
127
128 info.init (V4L2_PIX_FMT_NV12, width, height, aligned_width, aligned_height, size);
129 dma_buf = new DmaVideoBuffer (info, dma_fd);
130 output = display->convert_to_drm_bo_buf (display, dma_buf);
131 if (!output.ptr ()) {
132 XCAM_LOG_ERROR ("dma_buf(%d) convert to xcam_buf failed", dma_fd);
133 }
134
135 return output;
136 }
137
138 static SmartPtr<VideoBuffer>
create_dma_buffer(SmartPtr<DrmDisplay> & display,const VideoBufferInfo & info)139 create_dma_buffer (SmartPtr<DrmDisplay> &display, const VideoBufferInfo &info)
140 {
141 SmartPtr<BufferPool> buf_pool = new DrmBoBufferPool (display);
142 buf_pool->set_video_info (info);
143 buf_pool->reserve (1);
144 return buf_pool->get_buffer (buf_pool);
145 }
146 #endif
147
148 static XCamReturn
blend_images(SmartPtr<VideoBuffer> input0,SmartPtr<VideoBuffer> input1,SmartPtr<VideoBuffer> & output_buf,SmartPtr<CLBlender> blender)149 blend_images (
150 SmartPtr<VideoBuffer> input0, SmartPtr<VideoBuffer> input1,
151 SmartPtr<VideoBuffer> &output_buf,
152 SmartPtr<CLBlender> blender)
153 {
154 blender->set_output_size (output_width, output_height);
155 input0->attach_buffer (input1);
156 return blender->execute (input0, output_buf);
157 }
158
main(int argc,char * argv[])159 int main (int argc, char *argv[])
160 {
161 GeoPos *geo_map0 = NULL, *geo_map1 = NULL;
162 XCamReturn ret = XCAM_RETURN_NO_ERROR;
163 SmartPtr<CLImageHandler> image_handler;
164 SmartPtr<CLGeoMapHandler> geo_map_handler;
165 SmartPtr<CLBlender> blender;
166 VideoBufferInfo input_buf_info0, input_buf_info1, output_buf_info;
167 SmartPtr<CLContext> context;
168 SmartPtr<BufferPool> buf_pool0, buf_pool1;
169 ImageFileHandle file_in0, file_in1, file_out;
170 SmartPtr<VideoBuffer> input0, input1;
171 SmartPtr<VideoBuffer> output_buf;
172 SmartPtr<VideoBuffer> read_buf;
173
174 #define FAILED_GEO_FREE { delete [] geo_map0; delete [] geo_map1; return -1; }
175
176 const struct option long_opts[] = {
177 {"input0", required_argument, NULL, 'i'},
178 {"input1", required_argument, NULL, 'I'},
179 {"output", required_argument, NULL, 'o'},
180 {"input-w0", required_argument, NULL, 'w'},
181 {"input-w1", required_argument, NULL, 'W'},
182 {"input-h", required_argument, NULL, 'H'},
183 {"output-w", required_argument, NULL, 'x'},
184 {"loop", required_argument, NULL, 'l'},
185 {"save", required_argument, NULL, 's'},
186 {"enable-geo", no_argument, NULL, 'g'},
187 {"enable-seam", no_argument, NULL, 'm'},
188 {"help", no_argument, NULL, 'h'},
189 {0, 0, 0, 0},
190 };
191
192 int opt = -1;
193 while ((opt = getopt_long(argc, argv, "", long_opts, NULL)) != -1) {
194 switch (opt) {
195 case 'i':
196 strncpy (file_in0_name, optarg, XCAM_MAX_STR_SIZE);
197 break;
198 case 'I':
199 strncpy (file_in1_name, optarg, XCAM_MAX_STR_SIZE);
200 break;
201 case 'o':
202 strncpy (file_out_name, optarg, XCAM_MAX_STR_SIZE);
203 break;
204 case 'w':
205 input_width0 = atoi(optarg);
206 break;
207 case 'W':
208 input_width1 = atoi(optarg);
209 break;
210 case 'H':
211 input_height = atoi(optarg);
212 break;
213 case 'x':
214 output_width = atoi(optarg);
215 break;
216 case 'l':
217 loop = atoi(optarg);
218 break;
219 case 's':
220 need_save_output = (strcasecmp (optarg, "false") == 0 ? false : true);
221 break;
222 case 'g':
223 enable_geo = true;
224 break;
225 case 'm':
226 enable_seam = true;
227 break;
228 case 'h':
229 usage (argv[0]);
230 return -1;
231 default:
232 printf ("getopt_long return unknown value:%c\n", opt);
233 usage (argv[0]);
234 return -1;
235
236 }
237 }
238
239 if (optind < argc || argc < 2) {
240 printf("unknown option %s\n", argv[optind]);
241 usage (argv[0]);
242 return -1;
243 }
244
245 printf ("Description-----------\n");
246 printf ("input0 file:%s\n", file_in0_name);
247 printf ("input1 file:%s\n", file_in1_name);
248 printf ("output file PREFIX:%s\n", file_out_name);
249 printf ("input0 width:%d\n", input_width0);
250 printf ("input1 width:%d\n", input_width1);
251 printf ("input/output height:%d\n", input_height);
252 printf ("output width:%d\n", output_width);
253 printf ("loop count:%d\n", loop);
254 printf ("need save file:%s\n", need_save_output ? "true" : "false");
255 printf ("enable seam mask:%s\n", (enable_seam ? "true" : "false"));
256 printf ("----------------------\n");
257
258 output_height = input_height;
259 input_buf_info0.init (input_format, input_width0, input_height);
260 input_buf_info1.init (input_format, input_width1, input_height);
261 output_buf_info.init (input_format, output_width, output_height);
262 #if (ENABLE_DMA_TEST) && (HAVE_LIBDRM)
263 SmartPtr<DrmDisplay> display = DrmDisplay::instance ();
264 buf_pool0 = new DrmBoBufferPool (display);
265 buf_pool1 = new DrmBoBufferPool (display);
266 #else
267 buf_pool0 = new CLVideoBufferPool ();
268 buf_pool1 = new CLVideoBufferPool ();
269 #endif
270 XCAM_ASSERT (buf_pool0.ptr () && buf_pool1.ptr ());
271 buf_pool0->set_video_info (input_buf_info0);
272 buf_pool1->set_video_info (input_buf_info1);
273 if (!buf_pool0->reserve (2)) {
274 XCAM_LOG_ERROR ("init buffer pool failed");
275 return -1;
276 }
277 if (!buf_pool1->reserve (2)) {
278 XCAM_LOG_ERROR ("init buffer pool failed");
279 return -1;
280 }
281
282 context = CLDevice::instance ()->get_context ();
283 blender = create_pyramid_blender (context, 2, true, enable_seam).dynamic_cast_ptr<CLBlender> ();
284 XCAM_ASSERT (blender.ptr ());
285
286 #if (ENABLE_DMA_TEST) && (HAVE_LIBDRM)
287 int dma_fd0 = 30, dma_fd1 = 31, dma_fd_out = 32;
288 input_buf_info0.init (
289 input_format, input_width0, input_height, XCAM_ALIGN_UP (input_width0, 16), XCAM_ALIGN_UP(input_height, 16));
290 input_buf_info1.init (
291 input_format, input_width1, input_height, XCAM_ALIGN_UP (input_width1, 16), XCAM_ALIGN_UP(input_height, 16));
292 output_buf_info.init (
293 input_format, output_width, output_height, XCAM_ALIGN_UP (output_width, 16), XCAM_ALIGN_UP(output_height, 16));
294 uint32_t in_size = input_buf_info0.aligned_width * input_buf_info0.aligned_height * 3 / 2;
295 uint32_t out_size = output_buf_info.aligned_width * output_buf_info.aligned_height * 3 / 2;
296 /* create dma fd, for buffer_handle_t just skip this segment, directly goto dma_buf_to_xcam_buf */
297 SmartPtr<VideoBuffer> dma_buf0, dma_buf1, dma_buf_out;
298 dma_buf0 = create_dma_buffer (display, input_buf_info0); //unit test
299 dma_buf1 = create_dma_buffer (display, input_buf_info1); //unit test
300 dma_buf_out = create_dma_buffer (display, output_buf_info); //unit test
301 dma_fd0 = dma_buf0->get_fd (); //unit test
302 dma_fd1 = dma_buf1->get_fd (); //unit test
303 dma_fd_out = dma_buf_out->get_fd (); //unit test
304 /*
305 buffer_handle_t just go to here,
306 dma_fd0 = native_handle_t.data[0];
307 dma_fd1 = native_handle_t.data[0];
308 dma_fd_out = native_handle_t.data[0];
309 */
310 printf ("DMA handles, buf0:%d, buf1:%d, buf_out:%d\n", dma_fd0, dma_fd1, dma_fd_out);
311 input0 = dma_buf_to_xcam_buf (
312 display, dma_fd0, input_width0, input_height, in_size,
313 input_buf_info0.aligned_width, input_buf_info0.aligned_height);
314 input1 = dma_buf_to_xcam_buf (
315 display, dma_fd1, input_width0, input_height, in_size,
316 input_buf_info1.aligned_width, input_buf_info1.aligned_height);
317 output_buf = dma_buf_to_xcam_buf (
318 display, dma_fd_out, output_width, output_height, out_size,
319 output_buf_info.aligned_width, output_buf_info.aligned_height);
320 blender->disable_buf_pool (true);
321 #else
322 input0 = buf_pool0->get_buffer (buf_pool0);
323 input1 = buf_pool1->get_buffer (buf_pool1);
324 XCAM_ASSERT (input0.ptr () && input1.ptr ());
325 #endif
326 //
327 ret = file_in0.open (file_in0_name, "rb");
328 CHECK_STATEMENT (ret, FAILED_GEO_FREE, "open input file(%s) failed", file_in0_name);
329 read_buf = input0;
330 ret = file_in0.read_buf (read_buf);
331 CHECK_STATEMENT (ret, FAILED_GEO_FREE, "read buffer0 from (%s) failed", file_in0_name);
332
333 ret = file_in1.open (file_in1_name, "rb");
334 CHECK_STATEMENT (ret, FAILED_GEO_FREE, "open input file(%s) failed", file_in1_name);
335 read_buf = input1;
336 ret = file_in1.read_buf (read_buf);
337 CHECK_STATEMENT (ret, FAILED_GEO_FREE, "read buffer1 from (%s) failed", file_in1_name);
338
339 if (enable_geo) {
340 geo_map_handler = create_geo_map_handler (context).dynamic_cast_ptr<CLGeoMapHandler> ();
341 XCAM_ASSERT (geo_map_handler.ptr ());
342
343 geo_map0 = new GeoPos[map_width * map_height];
344 geo_map1 = new GeoPos[map_width * map_height];
345 XCAM_ASSERT (geo_map0 && geo_map1);
346 if (read_map_data (map0, geo_map0, map_width, map_height) <= 0 ||
347 read_map_data (map1, geo_map1, map_width, map_height) <= 0) {
348 delete [] geo_map0;
349 delete [] geo_map1;
350 return -1;
351 }
352
353 geo_map_handler->set_map_uint (28.0f, 28.0f);
354 }
355
356 int i = 0;
357 do {
358 input0->clear_attached_buffers ();
359 input1->clear_attached_buffers ();
360
361 if (enable_geo) {
362 geo_correct_image (geo_map_handler, input0, geo_map0, map_width, map_height, file_in0_name, need_save_output);
363 geo_correct_image (geo_map_handler, input1, geo_map1, map_width, map_height, file_in1_name, need_save_output);
364 }
365
366 ret = blend_images (input0, input1, output_buf, blender);
367 CHECK_STATEMENT (ret, FAILED_GEO_FREE, "blend_images execute failed");
368 //printf ("DMA handles, output_buf:%d\n", output_buf->get_fd ());
369
370 if (need_save_output) {
371 char out_name[1024];
372 snprintf (out_name, 1023, "%s.%02d", file_out_name, i);
373
374 ret = file_out.open (out_name, "wb");
375 CHECK_STATEMENT (ret, FAILED_GEO_FREE, "open output file(%s) failed", out_name);
376 ret = file_out.write_buf (output_buf);
377 CHECK_STATEMENT (ret, FAILED_GEO_FREE, "write buffer to (%s) failed", out_name);
378 printf ("write output buffer to: %s done\n", out_name);
379 } else {
380 // check info
381 ensure_gpu_buffer_done (output_buf);
382 }
383
384 FPS_CALCULATION (image_blend, XCAM_OBJ_DUR_FRAME_NUM);
385 ++i;
386 } while (i < loop);
387
388 delete [] geo_map0;
389 delete [] geo_map1;
390
391 return ret;
392 }
393
394 //return count
read_map_data(const char * file,GeoPos * map,int width,int height)395 int read_map_data (const char* file, GeoPos *map, int width, int height)
396 {
397 char *ptr = NULL;
398 FILE *p_f = fopen (file, "rb");
399 CHECK_EXP (p_f, "open geo-map file(%s) failed", file);
400
401 #define FAILED_READ_MAP { if (p_f) fclose(p_f); if (ptr) xcam_free (ptr); return -1; }
402
403 CHECK_DECLARE (ERROR, fseek(p_f, 0L, SEEK_END) == 0, FAILED_READ_MAP, "seek to file(%s) end failed", file);
404 size_t size = ftell (p_f);
405 XCAM_ASSERT ((int)size != -1);
406 fseek (p_f, 0L, SEEK_SET);
407
408 ptr = (char*)xcam_malloc (size + 1);
409 XCAM_ASSERT (ptr);
410 CHECK_DECLARE (ERROR, fread (ptr, 1, size, p_f) == size, FAILED_READ_MAP, "read map file(%s)failed", file);
411 ptr[size] = 0;
412 fclose (p_f);
413 p_f = NULL;
414
415 char *str_num = NULL;
416 char tokens[] = "\t ,\r\n";
417 str_num = strtok (ptr, tokens);
418 int count = 0;
419 int x = 0, y = 0;
420 while (str_num != NULL) {
421 float num = strtof (str_num, NULL);
422 //printf ("%.3f\n", num);
423
424 x = count % width;
425 y = count / (width * 2); // x,y
426 if (y >= height)
427 break;
428
429 if (count % (width * 2) >= width)
430 map[y * width + x].y = num;
431 else
432 map[y * width + x].x = num;
433
434 ++count;
435 str_num = strtok (NULL, tokens);
436 }
437 xcam_free (ptr);
438 ptr = NULL;
439 CHECK_EXP (y < height, "map data(%s) count larger than expected(%dx%dx2)", file, width, height);
440 CHECK_EXP (count >= width * height * 2, "map data(%s) count less than expected(%dx%dx2)", file, width, height);
441
442 printf ("read map(%s) x/y data count:%d\n", file, count);
443 return count;
444 }
445
446