blob: 66d49b68e888fc61d3d309b3e97b5ce0d1ccce0e [file] [log] [blame]
Wind Yuan75564b12015-01-15 06:51:15 -05001/*
2 * main.cpp - test
3 *
4 * Copyright (c) 2014 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 "device_manager.h"
22#include "atomisp_device.h"
23#include "isp_controller.h"
24#include "isp_image_processor.h"
25#include "x3a_analyzer_simple.h"
26#if HAVE_IA_AIQ
27#include "x3a_analyzer_aiq.h"
28#endif
Wind Yuand4427312015-02-11 16:09:00 +080029#if HAVE_LIBCL
Wind Yuane4ba0c92015-03-26 16:59:06 +080030#include "cl_3a_image_processor.h"
31#endif
32#if HAVE_LIBDRM
33#include "drm_display.h"
Wind Yuand4427312015-02-11 16:09:00 +080034#endif
35
Wind Yuan75564b12015-01-15 06:51:15 -050036#include <unistd.h>
37#include <signal.h>
38#include <stdlib.h>
ShincyTue521cf92015-03-27 15:13:51 +080039#include <string>
John Yeae9da732015-01-22 13:36:36 +080040#include "test_common.h"
41
Wind Yuan75564b12015-01-15 06:51:15 -050042using namespace XCam;
43
ShincyTue521cf92015-03-27 15:13:51 +080044static Mutex g_mutex;
45static Cond g_cond;
46static bool g_stop = false;
47
Wind Yuan75564b12015-01-15 06:51:15 -050048class MainDeviceManager
49 : public DeviceManager
50{
51public:
52 MainDeviceManager ()
53 : _file (NULL)
54 , _save_file (false)
55 , _interval (1)
56 , _frame_count (0)
ShincyTue521cf92015-03-27 15:13:51 +080057 , _frame_save (0)
Wind Yuan683f8662015-03-27 18:52:38 +080058 , _enable_display (false)
Wind Yuane4ba0c92015-03-26 16:59:06 +080059 {
60#if HAVE_LIBDRM
61 _display = DrmDisplay::instance();
62#endif
63 }
Wind Yuan75564b12015-01-15 06:51:15 -050064
65 ~MainDeviceManager () {
66 close_file ();
67 }
68
69 void enable_save_file (bool enable) {
70 _save_file = enable;
71 }
72 void set_interval (uint32_t inteval) {
73 _interval = inteval;
74 }
ShincyTue521cf92015-03-27 15:13:51 +080075 void set_frame_save (uint32_t frame_save) {
76 _frame_save = frame_save;
77 }
Wind Yuan75564b12015-01-15 06:51:15 -050078
Wind Yuan683f8662015-03-27 18:52:38 +080079 void enable_display(bool value) {
80 _enable_display = value;
81 }
82
Wind Yuan75564b12015-01-15 06:51:15 -050083protected:
84 virtual void handle_message (SmartPtr<XCamMessage> &msg);
85 virtual void handle_buffer (SmartPtr<VideoBuffer> &buf);
86
Wind Yuane4ba0c92015-03-26 16:59:06 +080087 int display_buf (SmartPtr<VideoBuffer> &buf);
88
Wind Yuan75564b12015-01-15 06:51:15 -050089private:
90 void open_file ();
91 void close_file ();
92
93 FILE *_file;
94 bool _save_file;
95 uint32_t _interval;
96 uint32_t _frame_count;
ShincyTue521cf92015-03-27 15:13:51 +080097 uint32_t _frame_save;
Wind Yuane4ba0c92015-03-26 16:59:06 +080098 SmartPtr<DrmDisplay> _display;
Wind Yuan683f8662015-03-27 18:52:38 +080099 bool _enable_display;
Wind Yuan75564b12015-01-15 06:51:15 -0500100};
101
102void
103MainDeviceManager::handle_message (SmartPtr<XCamMessage> &msg)
104{
105 XCAM_UNUSED (msg);
106}
107
108void
109MainDeviceManager::handle_buffer (SmartPtr<VideoBuffer> &buf)
110{
Wind Yuan683f8662015-03-27 18:52:38 +0800111 FPS_CALCULATION (fps_buf, 30);
112
113 if (_enable_display)
114 display_buf (buf);
Wind Yuane4ba0c92015-03-26 16:59:06 +0800115
Wind Yuan75564b12015-01-15 06:51:15 -0500116 if (!_save_file)
117 return ;
118
119 if ((_frame_count++ % _interval) != 0)
120 return;
121
ShincyTue521cf92015-03-27 15:13:51 +0800122 if ((_frame_save != 0) && (_frame_count > _frame_save)) {
123 SmartLock locker (g_mutex);
124 g_stop = true;
125 g_cond.broadcast ();
126 return;
127 }
128
Wind Yuan75564b12015-01-15 06:51:15 -0500129 const VideoBufferInfo & frame_info = buf->get_video_info ();
130 uint8_t *frame = buf->map ();
ShincyTu2808b592015-03-13 17:17:25 +0800131
Wind Yuan75564b12015-01-15 06:51:15 -0500132 if (frame == NULL)
133 return;
ShincyTu2808b592015-03-13 17:17:25 +0800134
135 uint32_t size = 0;
136
137 switch(frame_info.format) {
138 case V4L2_PIX_FMT_NV12: // 420
139 case V4L2_PIX_FMT_NV21:
140 size = XCAM_ALIGN_UP(frame_info.width, 2) * XCAM_ALIGN_UP(frame_info.height, 2) * 3 / 2;
141 break;
142 case V4L2_PIX_FMT_YUV422P: // 422 Planar
143 case V4L2_PIX_FMT_YUYV: // 422
144 case V4L2_PIX_FMT_SBGGR10:
145 case V4L2_PIX_FMT_SGBRG10:
146 case V4L2_PIX_FMT_SGRBG10:
147 case V4L2_PIX_FMT_SRGGB10:
148 size = XCAM_ALIGN_UP(frame_info.width, 2) * XCAM_ALIGN_UP(frame_info.height, 2) * 2;
149 break;
150 default:
151 XCAM_LOG_ERROR (
152 "unknown v4l2 format(%s) in buffer handle",
153 xcam_fourcc_to_string (frame_info.format));
154 return;
155 }
156
Wind Yuan75564b12015-01-15 06:51:15 -0500157 open_file ();
158 if (fwrite (frame, size, 1, _file) <= 0) {
159 XCAM_LOG_WARNING ("write frame failed.");
160 }
161}
162
Wind Yuane4ba0c92015-03-26 16:59:06 +0800163int
164MainDeviceManager::display_buf (SmartPtr<VideoBuffer> &buf)
165{
166#if HAVE_LIBDRM
167 XCamReturn ret = XCAM_RETURN_NO_ERROR;
168 const VideoBufferInfo & frame_info = buf->get_video_info ();
169 struct v4l2_rect rect = { 0, 0, (int)frame_info.width, (int)frame_info.height };
170
171 if (!_display->is_render_inited ()) {
Wind Yuan024e1f32015-03-30 16:27:41 +0800172 ret = _display->render_init (12, 3, 1920, 1080, frame_info.format, &rect);
Wind Yuane4ba0c92015-03-26 16:59:06 +0800173 CHECK (ret, "display failed on render_init");
174 }
175 ret = _display->render_setup_frame_buffer (buf);
176 CHECK (ret, "display failed on framebuf set");
177 ret = _display->render_buffer (buf);
178 CHECK (ret, "display failed on rendering");
179#endif
180 return 0;
181}
182
183
Wind Yuan75564b12015-01-15 06:51:15 -0500184void
185MainDeviceManager::open_file ()
186{
ShincyTue521cf92015-03-27 15:13:51 +0800187 if ((_file) && (_frame_save == 0))
Wind Yuan75564b12015-01-15 06:51:15 -0500188 return;
ShincyTue521cf92015-03-27 15:13:51 +0800189
190 std::string file_name = DEFAULT_SAVE_FILE_NAME;
191
192 if (_frame_save != 0) {
193 file_name += std::to_string(_frame_count);
194 }
195 file_name += ".raw";
196
197 _file = fopen(file_name.c_str(), "wb");
Wind Yuan75564b12015-01-15 06:51:15 -0500198}
199
200void
201MainDeviceManager::close_file ()
202{
203 if (_file)
204 fclose (_file);
205 _file = NULL;
206}
207
208#define V4L2_CAPTURE_MODE_STILL 0x2000
209#define V4L2_CAPTURE_MODE_VIDEO 0x4000
210#define V4L2_CAPTURE_MODE_PREVIEW 0x8000
211
Wind Yuan26e9e212015-04-16 15:55:45 +0800212typedef enum {
213 AnalyzerTypeSimple = 0,
214 AnalyzerTypeAiq,
215} AnalyzerType;
216
Wind Yuan75564b12015-01-15 06:51:15 -0500217void dev_stop_handler(int sig)
218{
219 XCAM_UNUSED (sig);
220
221 SmartLock locker (g_mutex);
222 g_stop = true;
223 g_cond.broadcast ();
224
225 //exit(0);
226}
227
228void print_help (const char *bin_name)
229{
230 printf ("Usage: %s [-a analyzer]\n"
ShincyTue521cf92015-03-27 15:13:51 +0800231 "\t -a analyzer specify a analyzer\n"
232 "\t select from [simple, aiq], default is [simple]\n"
233 "\t -m mem_type specify video memory type\n"
234 "\t mem_type select from [dma, mmap], default is [mmap]\n"
235 "\t -s save file to %s\n"
236 "\t -n interval save file on every [interval] frame\n"
237 "\t -c process image with cl kernel\n"
238 "\t -f pixel_fmt specify output pixel format\n"
239 "\t pixel_fmt select from [NV12, YUYV, BA10], default is [NV12]\n"
240 "\t -d cap_mode specify capture mode\n"
241 "\t cap_mode select from [video, still], default is [video]\n"
242 "\t -i frame_save specify the frame count to save, default is 0 which means endless\n"
Wind Yuane4ba0c92015-03-26 16:59:06 +0800243 "\t -p preview on local display\n"
ShincyTue521cf92015-03-27 15:13:51 +0800244 "\t -h help\n"
Wind Yuan75564b12015-01-15 06:51:15 -0500245 , bin_name
246 , DEFAULT_SAVE_FILE_NAME);
247}
248
249int main (int argc, char *argv[])
250{
251 XCamReturn ret = XCAM_RETURN_NO_ERROR;
252 SmartPtr<MainDeviceManager> device_manager = new MainDeviceManager;
253 SmartPtr<V4l2Device> device;
254 SmartPtr<V4l2SubDevice> event_device;
255 SmartPtr<IspController> isp_controller;
256 SmartPtr<X3aAnalyzer> analyzer;
Wind Yuane4ba0c92015-03-26 16:59:06 +0800257 SmartPtr<ImageProcessor> isp_processor;
Wind Yuan26e9e212015-04-16 15:55:45 +0800258 AnalyzerType analyzer_type = AnalyzerTypeSimple;
Wind Yuane4ba0c92015-03-26 16:59:06 +0800259#if HAVE_LIBDRM
260 SmartPtr<DrmDisplay> drm_disp = DrmDisplay::instance();
261#endif
262
Wind Yuand4427312015-02-11 16:09:00 +0800263#if HAVE_LIBCL
Wind Yuane4ba0c92015-03-26 16:59:06 +0800264 SmartPtr<CL3aImageProcessor> cl_processor;
Wind Yuand4427312015-02-11 16:09:00 +0800265#endif
266 bool have_cl_processor = false;
Wind Yuane4ba0c92015-03-26 16:59:06 +0800267 bool need_display = false;
Wind Yuand4427312015-02-11 16:09:00 +0800268 enum v4l2_memory v4l2_mem_type = V4L2_MEMORY_MMAP;
Wind Yuan75564b12015-01-15 06:51:15 -0500269 const char *bin_name = argv[0];
270 int opt;
ShincyTu2808b592015-03-13 17:17:25 +0800271 uint32_t capture_mode = V4L2_CAPTURE_MODE_VIDEO;
272 uint32_t pixel_format = V4L2_PIX_FMT_NV12;
Wind Yuan75564b12015-01-15 06:51:15 -0500273
ShincyTue521cf92015-03-27 15:13:51 +0800274 while ((opt = getopt(argc, argv, "sca:n:m:f:d:pi:h")) != -1) {
Wind Yuan75564b12015-01-15 06:51:15 -0500275 switch (opt) {
276 case 'a': {
277 if (!strcmp (optarg, "simple"))
Wind Yuan26e9e212015-04-16 15:55:45 +0800278 analyzer_type = AnalyzerTypeSimple;
Wind Yuan75564b12015-01-15 06:51:15 -0500279#if HAVE_IA_AIQ
280 else if (!strcmp (optarg, "aiq"))
Wind Yuan26e9e212015-04-16 15:55:45 +0800281 analyzer_type = AnalyzerTypeAiq;
Wind Yuan75564b12015-01-15 06:51:15 -0500282#endif
283 else {
284 print_help (bin_name);
285 return -1;
286 }
287 break;
288 }
289
Wind Yuand4427312015-02-11 16:09:00 +0800290 case 'm': {
291 if (!strcmp (optarg, "dma"))
292 v4l2_mem_type = V4L2_MEMORY_DMABUF;
293 else if (!strcmp (optarg, "mmap"))
294 v4l2_mem_type = V4L2_MEMORY_MMAP;
295 else
296 print_help (bin_name);
297 break;
298 }
299
Wind Yuan75564b12015-01-15 06:51:15 -0500300 case 's':
301 device_manager->enable_save_file (true);
302 break;
303 case 'n':
304 device_manager->set_interval (atoi(optarg));
305 break;
Wind Yuand4427312015-02-11 16:09:00 +0800306 case 'c':
307 have_cl_processor = true;
308 break;
ShincyTu2808b592015-03-13 17:17:25 +0800309 case 'f':
ShincyTuc8466402015-03-31 11:03:39 +0800310 CHECK_EXP ((strlen(optarg) == 4), "invalid pixel format\n");
311 pixel_format = v4l2_fourcc ((unsigned)optarg[0],
312 (unsigned)optarg[1],
313 (unsigned)optarg[2],
314 (unsigned)optarg[3]);
ShincyTu2808b592015-03-13 17:17:25 +0800315 break;
316 case 'd':
317 if (!strcmp (optarg, "still"))
318 capture_mode = V4L2_CAPTURE_MODE_STILL;
319 else if (!strcmp (optarg, "video"))
320 capture_mode = V4L2_CAPTURE_MODE_VIDEO;
321 else {
322 print_help (bin_name);
323 return -1;
324 }
325 break;
Wind Yuane4ba0c92015-03-26 16:59:06 +0800326 case 'p':
327 need_display = true;
328 break;
ShincyTue521cf92015-03-27 15:13:51 +0800329 case 'i':
330 device_manager->set_frame_save(atoi(optarg));
331 break;
Wind Yuan75564b12015-01-15 06:51:15 -0500332 case 'h':
333 print_help (bin_name);
334 return 0;
335
336 default:
337 print_help (bin_name);
338 return -1;
339 }
340 }
341
Wind Yuan683f8662015-03-27 18:52:38 +0800342 if (need_display)
343 device_manager->enable_display (true);
344
ShincyTu2808b592015-03-13 17:17:25 +0800345 if (!device.ptr ()) {
346 if (capture_mode == V4L2_CAPTURE_MODE_STILL)
347 device = new AtomispDevice (CAPTURE_DEVICE_STILL);
348 else if (capture_mode == V4L2_CAPTURE_MODE_VIDEO)
349 device = new AtomispDevice (CAPTURE_DEVICE_VIDEO);
350 else
351 device = new AtomispDevice (DEFAULT_CAPTURE_DEVICE);
352 }
Wind Yuan75564b12015-01-15 06:51:15 -0500353 if (!event_device.ptr ())
354 event_device = new V4l2SubDevice (DEFAULT_EVENT_DEVICE);
355 if (!isp_controller.ptr ())
356 isp_controller = new IspController (device);
Wind Yuane4ba0c92015-03-26 16:59:06 +0800357 if (!isp_processor.ptr ())
358 isp_processor = new IspImageProcessor (isp_controller);
Wind Yuan26e9e212015-04-16 15:55:45 +0800359
360 switch (analyzer_type) {
361 case AnalyzerTypeSimple:
362 analyzer = new X3aAnalyzerSimple ();
363 break;
364#if HAVE_IA_AIQ
365 case AnalyzerTypeAiq:
366 analyzer = new X3aAnalyzerAiq (isp_controller, DEFAULT_CPF_FILE);
367 break;
368#endif
369 default:
370 print_help (bin_name);
371 return -1;
372 }
Wind Yuan75564b12015-01-15 06:51:15 -0500373
374 signal(SIGINT, dev_stop_handler);
375
376 device->set_sensor_id (0);
ShincyTu2808b592015-03-13 17:17:25 +0800377 device->set_capture_mode (capture_mode);
Wind Yuan75564b12015-01-15 06:51:15 -0500378 //device->set_mem_type (V4L2_MEMORY_DMABUF);
Wind Yuand4427312015-02-11 16:09:00 +0800379 device->set_mem_type (v4l2_mem_type);
Wind Yuan75564b12015-01-15 06:51:15 -0500380 device->set_buffer_count (8);
381 device->set_framerate (25, 1);
382 ret = device->open ();
383 CHECK (ret, "device(%s) open failed", device->get_device_name());
ShincyTu2808b592015-03-13 17:17:25 +0800384 ret = device->set_format (1920, 1080, pixel_format, V4L2_FIELD_NONE, 1920 * 2);
Wind Yuan75564b12015-01-15 06:51:15 -0500385 CHECK (ret, "device(%s) set format failed", device->get_device_name());
386
387 ret = event_device->open ();
388 CHECK (ret, "event device(%s) open failed", event_device->get_device_name());
389 int event = V4L2_EVENT_ATOMISP_3A_STATS_READY;
390 ret = event_device->subscribe_event (event);
391 CHECK_CONTINUE (
392 ret,
393 "device(%s) subscribe event(%d) failed",
394 event_device->get_device_name(), event);
395 event = V4L2_EVENT_FRAME_SYNC;
396 ret = event_device->subscribe_event (event);
397 CHECK_CONTINUE (
398 ret,
399 "device(%s) subscribe event(%d) failed",
400 event_device->get_device_name(), event);
401
402 device_manager->set_capture_device (device);
403 device_manager->set_event_device (event_device);
404 device_manager->set_isp_controller (isp_controller);
405 if (analyzer.ptr())
406 device_manager->set_analyzer (analyzer);
Wind Yuane4ba0c92015-03-26 16:59:06 +0800407 device_manager->add_image_processor (isp_processor);
Wind Yuand4427312015-02-11 16:09:00 +0800408#if HAVE_LIBCL
409 if (have_cl_processor) {
Wind Yuane4ba0c92015-03-26 16:59:06 +0800410 cl_processor = new CL3aImageProcessor ();
Wind Yuan7ddf2602015-04-14 18:49:45 +0800411 cl_processor->set_stats_callback(device_manager);
Wind Yuane4ba0c92015-03-26 16:59:06 +0800412 cl_processor->set_hdr (true);
Juan Zhaoab5e6fe2015-04-08 14:12:46 +0800413 cl_processor->set_denoise (false);
Wind Yuane4ba0c92015-03-26 16:59:06 +0800414 if (need_display) {
415 cl_processor->set_output_format (V4L2_PIX_FMT_XBGR32);
416 }
Wind Yuand4427312015-02-11 16:09:00 +0800417 device_manager->add_image_processor (cl_processor);
418 }
419#endif
Wind Yuane4ba0c92015-03-26 16:59:06 +0800420
Wind Yuan75564b12015-01-15 06:51:15 -0500421 ret = device_manager->start ();
422 CHECK (ret, "device manager start failed");
423
424 // wait for interruption
425 {
426 SmartLock locker (g_mutex);
427 while (!g_stop)
428 g_cond.wait (g_mutex);
429 }
430
431 ret = device_manager->stop();
432 CHECK_CONTINUE (ret, "device manager stop failed");
433 device->close ();
434 event_device->close ();
435
436 return 0;
437}