Argus Camera Sample Argus Camera Sample

- Main Page
- Related Pages
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
AppModuleGeneric.cpp
Go to the documentation of this file.
1 /*
2 * Copyright (c) 2016-2019, NVIDIA CORPORATION. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of NVIDIA CORPORATION nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
24 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <stdlib.h>
30 #include <string.h>
31
32 #include "AppModuleGeneric.h"
33 #include "XMLConfig.h"
34 #include "Dispatcher.h"
35 #include "Error.h"
36 #include "Options.h"
37 #include "Window.h"
38
39 #include <Argus/Ext/DeFog.h>
40
41 namespace ArgusSamples
42 {
43
44 /**
45 * Default configuration file name
46 */
47 #define DEFAULT_CONFIG_FILE "argusAppConfig.xml"
48
49 /* static */ bool AppModuleGeneric::info(void *userPtr, const char *optArg)
50 {
51 std::string info;
52 PROPAGATE_ERROR(Dispatcher::getInstance().getInfo(info));
53 printf("%s\n", info.c_str());
54
55 return true;
56 }
57
58 /* static */ bool AppModuleGeneric::loadConfig(void *userPtr, const char *optArg)
59 {
60 /// @todo ask for file if called from GUI
61
62 const char *configFile = DEFAULT_CONFIG_FILE;
63 if (optArg)
64 configFile = optArg;
65 PROPAGATE_ERROR(ArgusSamples::loadConfig(configFile));
66 return true;
67 }
68
69 /* static */ bool AppModuleGeneric::saveConfig(void *userPtr, const char *optArg)
70 {
71 /// @todo ask for file if called from GUI
72
73 const char *configFile = DEFAULT_CONFIG_FILE;
74 if (optArg)
75 configFile = optArg;
76 PROPAGATE_ERROR(ArgusSamples::saveConfig(configFile));
77 return true;
78 }
79
80 /* static */ bool AppModuleGeneric::quit(void *userPtr, const char *optArg)
81 {
82 PROPAGATE_ERROR(Window::getInstance().requestExit());
83 return true;
84 }
85
86 AppModuleGeneric::AppModuleGeneric()
87 : m_initialized(false)
88 , m_running(false)
89 , m_guiMenuBar(NULL)
90 , m_guiContainerConfig(NULL)
91 , m_guiConfig(NULL)
92 {
93 }
94
95 AppModuleGeneric::~AppModuleGeneric()
96 {
97 shutdown();
98 }
99
100 bool AppModuleGeneric::initialize(Options &options)
101 {
102 if (m_initialized)
103 return true;
104
105 PROPAGATE_ERROR(options.addDescription(
106 "The supported value range of some settings is device or sensor mode dependent.\n"
107 "Use the '--info' option to get a list of the supported values.\n"));
108
109 PROPAGATE_ERROR(options.addOption(
110 Options::Option("info", 'i', "",
111 Options::Option::TYPE_ACTION,"print information on devices.", info)));
112
113 PROPAGATE_ERROR(options.addOption(
114 Options::Option("loadconfig", 0, "FILE",
115 Options::Option::TYPE_ACTION, "load configuration from XML FILE. ",
116 loadConfig, this, DEFAULT_CONFIG_FILE)));
117 PROPAGATE_ERROR(options.addOption(
118 Options::Option("saveconfig", 0, "FILE",
119 Options::Option::TYPE_ACTION, "save configuration to XML FILE. ",
120 saveConfig, this, DEFAULT_CONFIG_FILE)));
121
122 PROPAGATE_ERROR(options.addOption(
123 createValueOption("verbose", 0, "0 or 1", "enable verbose mode.",
124 Dispatcher::getInstance().m_verbose, "1")));
125 PROPAGATE_ERROR(options.addOption(
126 createValueOption("kpi", 0, "0 or 1", "enable kpi mode.",
127 Dispatcher::getInstance().m_kpi, "1")));
128 PROPAGATE_ERROR(options.addOption(
129 createValueOption("device", 'd', "INDEX", "select camera device with INDEX.",
130 Dispatcher::getInstance().m_deviceIndex)));
131
132 // source settings
133 PROPAGATE_ERROR(options.addOption(
134 createValueOption("exposuretimerange", 0, "RANGE",
135 "sets the exposure time range to RANGE, in nanoseconds.",
136 Dispatcher::getInstance().m_exposureTimeRange)));
137 PROPAGATE_ERROR(options.addOption(
138 createValueOption("gainrange", 0, "RANGE", "sets the gain range to RANGE.",
139 Dispatcher::getInstance().m_gainRange)));
140 PROPAGATE_ERROR(options.addOption(
141 createValueOption("sensormode", 0, "INDEX", "set sensor mode to INDEX.",
142 Dispatcher::getInstance().m_sensorModeIndex)));
143 PROPAGATE_ERROR(options.addOption(
144 createValueOption("framerate", 0, "RATE",
145 "an alias to frameRateRange. Sets the sensor frame rate range to (RATE, RATE). If"
146 " RATE is 0 then VFR (variable frame rate) is enabled.",
147 Dispatcher::getInstance().m_frameRate)));
148 PROPAGATE_ERROR(options.addOption(
149 createValueOption("frameraterange", 0, "RANGE",
150 "set the sensor frame rate range to RANGE. If RANGE is 0,0 then VFR (variable frame "
151 "rate) is enabled.", Dispatcher::getInstance().m_frameRateRange)));
152 PROPAGATE_ERROR(options.addOption(
153 createValueOption("focusposition", 0, "POSITION",
154 "sets the focus position to POSITION, in focuser units.",
155 Dispatcher::getInstance().m_focusPosition)));
156 PROPAGATE_ERROR(options.addOption(
157 createValueOption("apertureposition", 0, "POSITION",
158 "sets the aperture position to POSITION, in position units.",
159 Dispatcher::getInstance().m_aperturePosition)));
160 PROPAGATE_ERROR(options.addOption(
161 createValueOption("apertureFnum", 0, "Fnum",
162 "sets the aperture F-num, in F-num units.",
163 Dispatcher::getInstance().m_apertureFnum)));
164 PROPAGATE_ERROR(options.addOption(
165 createValueOption("aperturemotorspeed", 0, "SPEED",
166 "sets the aperture motor speed to SPEED, in steps/second units.",
167 Dispatcher::getInstance().m_apertureMotorSpeed)));
168 PROPAGATE_ERROR(options.addOption(
169 createValueOption("captureyuvformat", 0, "FORMAT",
170 "YUV format for image capture.", Dispatcher::getInstance().m_captureYuvFormat)));
171
172 // output settings
173 PROPAGATE_ERROR(options.addOption(
174 createValueOption("outputsize", 0, "WIDTHxHEIGHT",
175 "set the still and video output size to WIDTHxHEIGHT (e.g. 1920x1080). If WIDTHxHEIGHT "
176 "is '0x0' the output size is the sensor mode size.",
177 Dispatcher::getInstance().m_outputSize)));
178 PROPAGATE_ERROR(options.addOption(
179 createValueOption("outputpath", 0, "PATH",
180 "set the output file path. A file name, an incrementing index and the file extension"
181 " will be appended. E.g. setting 'folder/' will result in 'folder/image0.jpg' or "
182 "'folder/video0.mp4'. '/dev/null' can be used to discard output.",
183 Dispatcher::getInstance().m_outputPath)));
184
185 // stream settings
186 PROPAGATE_ERROR(options.addOption(
187 createValueOption("denoise", 0, "MODE", "set the denoising mode.",
188 Dispatcher::getInstance().m_denoiseMode)));
189 PROPAGATE_ERROR(options.addOption(
190 createValueOption("denoisestrength", 0, "POSITION", "set the denoising strength.",
191 Dispatcher::getInstance().m_denoiseStrength)));
192 PROPAGATE_ERROR(options.addOption(
193 createValueOption("edgeenhance", 0, "MODE", "set the edge enhancement mode.",
194 Dispatcher::getInstance().m_edgeEnhanceMode)));
195 PROPAGATE_ERROR(options.addOption(
196 createValueOption("edgeenhancestrength", 0, "POSITION",
197 "set the edge enhancement strength.",
198 Dispatcher::getInstance().m_edgeEnhanceStrength)));
199
200 // auto control settings
201 PROPAGATE_ERROR(options.addOption(
202 createValueOption("aeantibanding", 0, "MODE", "set the auto exposure antibanding mode.",
203 Dispatcher::getInstance().m_aeAntibandingMode)));
204 PROPAGATE_ERROR(options.addOption(
205 createValueOption("aelock", 0, "LOCK", "set the auto exposure lock.",
206 Dispatcher::getInstance().m_aeLock)));
207 PROPAGATE_ERROR(options.addOption(
208 createValueOption("awblock", 0, "LOCK", "set the auto white balance lock.",
209 Dispatcher::getInstance().m_awbLock)));
210 PROPAGATE_ERROR(options.addOption(
211 createValueOption("awb", 0, "MODE", "set the auto white balance mode.",
212 Dispatcher::getInstance().m_awbMode)));
213 PROPAGATE_ERROR(options.addOption(
214 createValueOption("exposurecompensation", 0, "COMPENSATION",
215 "set the exposure compensation to COMPENSATION.",
216 Dispatcher::getInstance().m_exposureCompensation)));
217 PROPAGATE_ERROR(options.addOption(
218 createValueOption("ispdigitalgainrange", 0, "RANGE",
219 "sets the ISP digital gain range.",
220 Dispatcher::getInstance().m_ispDigitalGainRange)));
221 PROPAGATE_ERROR(options.addOption(
222 createValueOption("acregionhorizontal", 0, "RANGE",
223 "sets the AC auto control region horizontal range.",
224 Dispatcher::getInstance().m_acRegionHorizontal)));
225 PROPAGATE_ERROR(options.addOption(
226 createValueOption("acregionvertical", 0, "RANGE",
227 "sets the AC auto control region vertical range.",
228 Dispatcher::getInstance().m_acRegionVertical)));
229
230 if (Dispatcher::getInstance().supportsExtension(Argus::EXT_DE_FOG))
231 {
232 // DeFog extension settings
233 PROPAGATE_ERROR(options.addOption(
234 createValueOption("defog", 0, "ENABLE",
235 "set the DeFog enable flag to ENABLE.",
236 Dispatcher::getInstance().m_deFogEnable)));
237 PROPAGATE_ERROR(options.addOption(
238 createValueOption("defogamount", 0, "AMOUNT",
239 "sets the amount of fog to be removed to AMOUNT.",
240 Dispatcher::getInstance().m_deFogAmount)));
241 PROPAGATE_ERROR(options.addOption(
242 createValueOption("defogquality", 0, "QUALITY",
243 "sets the quality of the DeFog effect to QUALITY.",
244 Dispatcher::getInstance().m_deFogQuality)));
245 }
246
247 m_initialized = true;
248
249 return true;
250 }
251
252 bool AppModuleGeneric::shutdown()
253 {
254 if (!m_initialized)
255 return true;
256
257 PROPAGATE_ERROR_CONTINUE(stop());
258
259 delete m_guiConfig;
260 m_guiConfig = NULL;
261
262 m_initialized = false;
263
264 return true;
265 }
266
267 bool AppModuleGeneric::start(Window::IGuiMenuBar *iGuiMenuBar,
268 Window::IGuiContainer *iGuiContainerConfig)
269 {
270 if (m_running)
271 return true;
272
273 if (iGuiMenuBar && !m_guiMenuBar)
274 {
275 // initialize the menu
276
277 UniquePointer<Window::IGuiMenu> menu;
278 UniquePointer<Window::IGuiMenuItem> item;
279
280 // create the elements
281 Window::IGuiMenu *fileMenu = iGuiMenuBar->getMenu("File");
282 if (!fileMenu)
283 {
284 PROPAGATE_ERROR(Window::IGuiMenu::create("File", &menu));
285 PROPAGATE_ERROR(iGuiMenuBar->add(menu.get()));
286 fileMenu = menu.get();
287 menu.release();
288 }
289 PROPAGATE_ERROR(Window::IGuiMenuItem::create("Load config", AppModuleGeneric::loadConfig,
290 NULL, &item));
291 PROPAGATE_ERROR(fileMenu->add(item.get()));
292 item.release();
293 PROPAGATE_ERROR(Window::IGuiMenuItem::create("Save Config", AppModuleGeneric::saveConfig,
294 NULL, &item));
295 PROPAGATE_ERROR(fileMenu->add(item.get()));
296 item.release();
297 PROPAGATE_ERROR(Window::IGuiMenuItem::create("Quit", AppModuleGeneric::quit, NULL,
298 &item));
299 PROPAGATE_ERROR(fileMenu->add(item.get()));
300 item.release();
301
302 Window::IGuiMenu *helpMenu = iGuiMenuBar->getMenu("Help");
303 if (!helpMenu)
304 {
305 PROPAGATE_ERROR(Window::IGuiMenu::create("Help", &menu));
306 PROPAGATE_ERROR(iGuiMenuBar->add(menu.get()));
307 helpMenu = menu.get();
308 menu.release();
309 }
310 PROPAGATE_ERROR(Window::IGuiMenuItem::create("Info", AppModuleGeneric::info, NULL,
311 &item));
312 PROPAGATE_ERROR(helpMenu->add(item.get()));
313 item.release();
314
315 m_guiMenuBar = iGuiMenuBar;
316 }
317
318 if (iGuiContainerConfig && !m_guiContainerConfig)
319 {
320 // initialize the GUI
321
322 // create a grid container
323 PROPAGATE_ERROR(Window::IGuiContainerGrid::create(&m_guiConfig));
324
325 // create the elements
326 UniquePointer<Window::IGuiElement> element;
327 Dispatcher &dispatcher = Dispatcher::getInstance();
328
329 Window::IGuiContainerGrid::BuildHelper buildHelper(m_guiConfig);
330
331 #define CREATE_GUI_ELEMENT(_NAME, _VALUE) \
332 PROPAGATE_ERROR(Window::IGuiElement::createValue(&dispatcher._VALUE, &element));\
333 PROPAGATE_ERROR(buildHelper.append(_NAME, element.get())); \
334 element.release();
335
336 #define CREATE_GUI_ELEMENT_COMBO_BOX(_NAME, _VALUE, _FROMTYPE, _TOTYPE) \
337 assert(sizeof(_FROMTYPE) == sizeof(_TOTYPE)); \
338 PROPAGATE_ERROR(Window::IGuiElement::createValue(reinterpret_cast< \
339 Value<_TOTYPE>*>(&dispatcher._VALUE), &element)); \
340 PROPAGATE_ERROR(buildHelper.append(_NAME, element.get())); \
341 element.release();
342
343 #define CREATE_GUI_ELEMENT_PATH_CHOOSER(_NAME, _VALUE) \
344 PROPAGATE_ERROR(Window::IGuiElement::createFileChooser(&dispatcher._VALUE, \
345 true, &element)); \
346 PROPAGATE_ERROR(buildHelper.append(_NAME, element.get())); \
347 element.release();
348
349 CREATE_GUI_ELEMENT("Verbose", m_verbose);
350 CREATE_GUI_ELEMENT("KPI", m_kpi);
351 CREATE_GUI_ELEMENT("Device", m_deviceIndex);
352
353 CREATE_GUI_ELEMENT("Exposure time range (ns)", m_exposureTimeRange);
354 CREATE_GUI_ELEMENT("Gain range", m_gainRange);
355 CREATE_GUI_ELEMENT("ISP digital gain range", m_ispDigitalGainRange);
356 CREATE_GUI_ELEMENT("AC region horizontal", m_acRegionHorizontal);
357 CREATE_GUI_ELEMENT("AC region vertical", m_acRegionVertical);
358
359 CREATE_GUI_ELEMENT_COMBO_BOX("Sensor mode index", m_sensorModeIndex,
360 uint32_t, Window::IGuiElement::ValueTypeEnum);
361 CREATE_GUI_ELEMENT_COMBO_BOX("YUV format", m_captureYuvFormat,
362 Argus::PixelFormat, Argus::NamedUUID);
363 CREATE_GUI_ELEMENT("Frame rate range", m_frameRateRange);
364 CREATE_GUI_ELEMENT("Focus position", m_focusPosition);
365 CREATE_GUI_ELEMENT("Aperture position", m_aperturePosition);
366 CREATE_GUI_ELEMENT_COMBO_BOX("Aperture Fnum", m_apertureFnum,
367 float, Window::IGuiElement::ValueTypeEnum);
368 CREATE_GUI_ELEMENT("Aperture motor speed", m_apertureMotorSpeed);
369 CREATE_GUI_ELEMENT("Output size", m_outputSize);
370
371 CREATE_GUI_ELEMENT_PATH_CHOOSER("Output path", m_outputPath);
372
373 CREATE_GUI_ELEMENT_COMBO_BOX("De-Noise mode", m_denoiseMode,
374 Argus::DenoiseMode, Argus::NamedUUID);
375 CREATE_GUI_ELEMENT("De-Noise strength", m_denoiseStrength);
376 CREATE_GUI_ELEMENT_COMBO_BOX("Edge Enhance mode", m_edgeEnhanceMode,
377 Argus::EdgeEnhanceMode, Argus::NamedUUID);
378 CREATE_GUI_ELEMENT("Edge Enhance strength", m_edgeEnhanceStrength);
379
380 CREATE_GUI_ELEMENT_COMBO_BOX("AE antibanding mode", m_aeAntibandingMode,
381 Argus::AeAntibandingMode, Argus::NamedUUID);
382
383 CREATE_GUI_ELEMENT("AE Lock", m_aeLock);
384 CREATE_GUI_ELEMENT("AWB Lock", m_awbLock);
385 CREATE_GUI_ELEMENT_COMBO_BOX("AWB mode", m_awbMode,
386 Argus::AwbMode, Argus::NamedUUID);
387 CREATE_GUI_ELEMENT("Exposure compensation (ev)", m_exposureCompensation);
388
389 #undef CREATE_GUI_ELEMENT
390 #undef CREATE_GUI_ELEMENT_COMBO_BOX
391 #undef CREATE_GUI_ELEMENT_PATH_CHOOSER
392
393 m_guiContainerConfig = iGuiContainerConfig;
394 }
395
396 if (m_guiContainerConfig)
397 PROPAGATE_ERROR(m_guiContainerConfig->add(m_guiConfig));
398
399 m_running = true;
400
401 return true;
402 }
403
404 bool AppModuleGeneric::stop()
405 {
406 if (!m_running)
407 return true;
408
409 if (m_guiContainerConfig)
410 PROPAGATE_ERROR(m_guiContainerConfig->remove(m_guiConfig));
411
412 m_running = true;
413
414 return true;
415 }
416
417 }; // namespace ArgusSamples