Argus Camera Sample
Argus Camera Sample
 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, 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 /* static */ bool AppModuleGeneric::verbose(void *userPtr, const char *optArg)
87 {
88  PROPAGATE_ERROR(Dispatcher::getInstance().m_verbose.set(true));
89  return true;
90 }
91 
92 /* static */ bool AppModuleGeneric::kpi(void *userPtr, const char *optArg)
93 {
94  PROPAGATE_ERROR(Dispatcher::getInstance().m_kpi.set(true));
95  return true;
96 }
97 
98 /* static */ bool AppModuleGeneric::device(void *userPtr, const char *optArg)
99 {
100  PROPAGATE_ERROR(Dispatcher::getInstance().m_deviceIndex.setFromString(optArg));
101  return true;
102 }
103 
104 /* static */ bool AppModuleGeneric::exposureTimeRange(void *userPtr, const char *optArg)
105 {
106  PROPAGATE_ERROR(Dispatcher::getInstance().m_exposureTimeRange.setFromString(optArg));
107  return true;
108 }
109 
110 /* static */ bool AppModuleGeneric::focusPosition(void *userPtr, const char *optArg)
111 {
112  PROPAGATE_ERROR(Dispatcher::getInstance().m_focusPosition.setFromString(optArg));
113  return true;
114 }
115 
116 /* static */ bool AppModuleGeneric::gainRange(void *userPtr, const char *optArg)
117 {
118  PROPAGATE_ERROR(Dispatcher::getInstance().m_gainRange.setFromString(optArg));
119  return true;
120 }
121 
122 /* static */ bool AppModuleGeneric::sensorMode(void *userPtr, const char *optArg)
123 {
124  PROPAGATE_ERROR(Dispatcher::getInstance().m_sensorModeIndex.setFromString(optArg));
125  return true;
126 }
127 
128 /* static */ bool AppModuleGeneric::frameRate(void *userPtr, const char *optArg)
129 {
130  PROPAGATE_ERROR(Dispatcher::getInstance().m_frameRate.setFromString(optArg));
131 
132  return true;
133 }
134 
135 /* static */ bool AppModuleGeneric::outputSize(void *userPtr, const char *optArg)
136 {
137  PROPAGATE_ERROR(Dispatcher::getInstance().m_outputSize.setFromString(optArg));
138  return true;
139 }
140 
141 /* static */ bool AppModuleGeneric::outputPath(void *userPtr, const char *optArg)
142 {
143  PROPAGATE_ERROR(Dispatcher::getInstance().m_outputPath.set(optArg));
144  return true;
145 }
146 
147 /* static */ bool AppModuleGeneric::vstab(void *userPtr, const char *optArg)
148 {
149  PROPAGATE_ERROR(Dispatcher::getInstance().m_vstabMode.setFromString(optArg));
150  return true;
151 }
152 
153 /* static */ bool AppModuleGeneric::deNoise(void *userPtr, const char *optArg)
154 {
155  PROPAGATE_ERROR(Dispatcher::getInstance().m_denoiseMode.setFromString(optArg));
156  return true;
157 }
158 
159 /* static */ bool AppModuleGeneric::aeAntibanding(void *userPtr, const char *optArg)
160 {
161  PROPAGATE_ERROR(Dispatcher::getInstance().m_aeAntibandingMode.setFromString(optArg));
162  return true;
163 }
164 
165 /* static */ bool AppModuleGeneric::aeLock(void *userPtr, const char *optArg)
166 {
167  PROPAGATE_ERROR(Dispatcher::getInstance().m_aeLock.setFromString(optArg));
168  return true;
169 }
170 
171 /* static */ bool AppModuleGeneric::awbLock(void *userPtr, const char *optArg)
172 {
173  PROPAGATE_ERROR(Dispatcher::getInstance().m_awbLock.setFromString(optArg));
174  return true;
175 }
176 
177 /* static */ bool AppModuleGeneric::awb(void *userPtr, const char *optArg)
178 {
179  PROPAGATE_ERROR(Dispatcher::getInstance().m_awbMode.setFromString(optArg));
180  return true;
181 }
182 
183 /* static */ bool AppModuleGeneric::exposureCompensation(void *userPtr, const char *optArg)
184 {
185  PROPAGATE_ERROR(Dispatcher::getInstance().m_exposureCompensation.setFromString(optArg));
186  return true;
187 }
188 
189 /* static */ bool AppModuleGeneric::ispDigitalGainRange(void *userPtr, const char *optArg)
190 {
191  PROPAGATE_ERROR(Dispatcher::getInstance().m_ispDigitalGainRange.setFromString(optArg));
192  return true;
193 }
194 
195 /* static */ bool AppModuleGeneric::deFogEnable(void *userPtr, const char *optArg)
196 {
197  PROPAGATE_ERROR(Dispatcher::getInstance().m_deFogEnable.setFromString(optArg));
198  return true;
199 }
200 
201 /* static */ bool AppModuleGeneric::deFogAmount(void *userPtr, const char *optArg)
202 {
203  PROPAGATE_ERROR(Dispatcher::getInstance().m_deFogAmount.setFromString(optArg));
204  return true;
205 }
206 
207 /* static */ bool AppModuleGeneric::deFogQuality(void *userPtr, const char *optArg)
208 {
209  PROPAGATE_ERROR(Dispatcher::getInstance().m_deFogQuality.setFromString(optArg));
210  return true;
211 }
212 
214  : m_initialized(false)
215  , m_running(false)
216  , m_guiMenuBar(NULL)
217  , m_guiContainerConfig(NULL)
218  , m_guiConfig(NULL)
219 {
220 }
221 
223 {
224  shutdown();
225 }
226 
227 bool AppModuleGeneric::initialize(Options &options)
228 {
229  if (m_initialized)
230  return true;
231 
232  PROPAGATE_ERROR(options.addDescription(
233  "The supported value range of some settings is device or sensor mode dependent.\n"
234  "Use the '--info' option to get a list of the supported values.\n"));
235 
236  PROPAGATE_ERROR(options.addOption(
237  Options::Option("info", 'i', "",
238  Options::Option::TYPE_ACTION, Options::Option::FLAG_NO_ARGUMENT,
239  "print information on devices.", info)));
240 
241  PROPAGATE_ERROR(options.addOption(
242  Options::Option("loadconfig", 0, "FILE",
243  Options::Option::TYPE_ACTION, Options::Option::FLAG_OPTIONAL_ARGUMENT,
244  "load configuration from XML FILE. Default for file is '" DEFAULT_CONFIG_FILE "'.",
245  loadConfig)));
246  PROPAGATE_ERROR(options.addOption(
247  Options::Option("saveconfig", 0, "FILE",
248  Options::Option::TYPE_ACTION, Options::Option::FLAG_OPTIONAL_ARGUMENT,
249  "save configuration to XML FILE. Default for file is '" DEFAULT_CONFIG_FILE "'.",
250  saveConfig)));
251 
252  PROPAGATE_ERROR(options.addOption(
253  Options::Option("verbose", 0, "", Dispatcher::getInstance().m_verbose,
254  "enable verbose mode.", verbose)));
255  PROPAGATE_ERROR(options.addOption(
256  Options::Option("kpi", 0, "", Dispatcher::getInstance().m_kpi,
257  "enable kpi mode.", kpi)));
258  PROPAGATE_ERROR(options.addOption(
259  Options::Option("device", 'd', "INDEX", Dispatcher::getInstance().m_deviceIndex,
260  "select camera device with INDEX.", device)));
261 
262  // source settings
263  PROPAGATE_ERROR(options.addOption(
264  Options::Option("exposuretimerange", 0, "RANGE",
266  "sets the exposure time range to RANGE, in nanoseconds.",
268  PROPAGATE_ERROR(options.addOption(
269  Options::Option("gainrange", 0, "RANGE", Dispatcher::getInstance().m_gainRange,
270  "sets the gain range to RANGE.", gainRange)));
271  PROPAGATE_ERROR(options.addOption(
272  Options::Option("sensormode", 0, "INDEX", Dispatcher::getInstance().m_sensorModeIndex,
273  "set sensor mode to INDEX.", sensorMode)));
274  PROPAGATE_ERROR(options.addOption(
275  Options::Option("framerate", 0, "RATE", Dispatcher::getInstance().m_frameRate,
276  "set the sensor frame rate to RATE. If RATE is 0 then VFR (variable frame rate) is "
277  "enabled.", frameRate)));
278  PROPAGATE_ERROR(options.addOption(
279  Options::Option("focusposition", 0, "POSITION", Dispatcher::getInstance().m_focusPosition,
280  "sets the focus position to POSITION, in focuser units.",
281  focusPosition)));
282 
283  // output settings
284  PROPAGATE_ERROR(options.addOption(
285  Options::Option("outputsize", 0, "WIDTHxHEIGHT", Dispatcher::getInstance().m_outputSize,
286  "set the still and video output size to WIDTHxHEIGHT (e.g. 1920x1080). If WIDTHxHEIGHT "
287  "is '0x0' the output size is the sensor mode size.", outputSize)));
288  PROPAGATE_ERROR(options.addOption(
289  Options::Option("outputpath", 0, "PATH", Dispatcher::getInstance().m_outputPath,
290  "set the output file path. A file name, an incrementing index and the file extension will "
291  "be appended. E.g. setting 'folder/' will result in 'folder/image0.jpg' or "
292  "'folder/video0.mp4'. '/dev/null' can be used to discard output.",
293  outputPath)));
294 
295  // stream settings
296  PROPAGATE_ERROR(options.addOption(
297  Options::Option("vstab", 0, "MODE", Dispatcher::getInstance().m_vstabMode,
298  "set the video stabilization mode.", vstab)));
299  PROPAGATE_ERROR(options.addOption(
300  Options::Option("denoise", 0, "MODE", Dispatcher::getInstance().m_denoiseMode,
301  "set the denoising mode.", deNoise)));
302 
303  // auto control settings
304  PROPAGATE_ERROR(options.addOption(
305  Options::Option("aeantibanding", 0, "MODE", Dispatcher::getInstance().m_aeAntibandingMode,
306  "set the auto exposure antibanding mode.", aeAntibanding)));
307  PROPAGATE_ERROR(options.addOption(
308  Options::Option("aelock", 0, "LOCK", Dispatcher::getInstance().m_aeLock,
309  "set the auto exposure lock.", aeLock)));
310  PROPAGATE_ERROR(options.addOption(
311  Options::Option("awblock", 0, "LOCK", Dispatcher::getInstance().m_awbLock,
312  "set the auto white balance lock.", awbLock)));
313  PROPAGATE_ERROR(options.addOption(
314  Options::Option("awb", 0, "MODE", Dispatcher::getInstance().m_awbMode,
315  "set the auto white balance mode.", awb)));
316  PROPAGATE_ERROR(options.addOption(
317  Options::Option("exposurecompensation", 0, "COMPENSATION",
319  "set the exposure compensation to COMPENSATION.",
321  PROPAGATE_ERROR(options.addOption(
322  Options::Option("ispdigitalgainrange", 0, "RANGE",
324  "sets the ISP digital gain range.",
326 
327  if (Dispatcher::getInstance().supportsExtension(Argus::EXT_DE_FOG))
328  {
329  // DeFog extension settings
330  PROPAGATE_ERROR(options.addOption(
331  Options::Option("defog", 0, "ENABLE", Dispatcher::getInstance().m_deFogEnable,
332  "set the DeFog enable flag to ENABLE.", deFogEnable)));
333  PROPAGATE_ERROR(options.addOption(
334  Options::Option("defogamount", 0, "AMOUNT", Dispatcher::getInstance().m_deFogAmount,
335  "sets the amount of fog to be removed to AMOUNT.", deFogAmount)));
336  PROPAGATE_ERROR(options.addOption(
337  Options::Option("defogquality", 0, "QUALITY", Dispatcher::getInstance().m_deFogQuality,
338  "sets the quality of the DeFog effect to QUALITY.",
339  deFogQuality)));
340  }
341 
342  m_initialized = true;
343 
344  return true;
345 }
346 
348 {
349  if (!m_initialized)
350  return true;
351 
352  PROPAGATE_ERROR_CONTINUE(stop());
353 
354  delete m_guiConfig;
355  m_guiConfig = NULL;
356 
357  m_initialized = false;
358 
359  return true;
360 }
361 
362 bool AppModuleGeneric::start(Window::IGuiMenuBar *iGuiMenuBar,
363  Window::IGuiContainer *iGuiContainerConfig)
364 {
365  if (m_running)
366  return true;
367 
368  if (iGuiMenuBar && !m_guiMenuBar)
369  {
370  // initialize the menu
371 
372  UniquePointer<Window::IGuiMenu> menu;
373  UniquePointer<Window::IGuiMenuItem> item;
374 
375  // create the elements
376  Window::IGuiMenu *fileMenu = iGuiMenuBar->getMenu("File");
377  if (!fileMenu)
378  {
379  PROPAGATE_ERROR(Window::IGuiMenu::create("File", &menu));
380  PROPAGATE_ERROR(iGuiMenuBar->add(menu.get()));
381  fileMenu = menu.get();
382  menu.release();
383  }
384  PROPAGATE_ERROR(Window::IGuiMenuItem::create("Load config", AppModuleGeneric::loadConfig,
385  NULL, &item));
386  PROPAGATE_ERROR(fileMenu->add(item.get()));
387  item.release();
388  PROPAGATE_ERROR(Window::IGuiMenuItem::create("Save Config", AppModuleGeneric::saveConfig,
389  NULL, &item));
390  PROPAGATE_ERROR(fileMenu->add(item.get()));
391  item.release();
392  PROPAGATE_ERROR(Window::IGuiMenuItem::create("Quit", AppModuleGeneric::quit, NULL,
393  &item));
394  PROPAGATE_ERROR(fileMenu->add(item.get()));
395  item.release();
396 
397  Window::IGuiMenu *helpMenu = iGuiMenuBar->getMenu("Help");
398  if (!helpMenu)
399  {
400  PROPAGATE_ERROR(Window::IGuiMenu::create("Help", &menu));
401  PROPAGATE_ERROR(iGuiMenuBar->add(menu.get()));
402  helpMenu = menu.get();
403  menu.release();
404  }
405  PROPAGATE_ERROR(Window::IGuiMenuItem::create("Info", AppModuleGeneric::info, NULL,
406  &item));
407  PROPAGATE_ERROR(helpMenu->add(item.get()));
408  item.release();
409 
410  m_guiMenuBar = iGuiMenuBar;
411  }
412 
413  if (iGuiContainerConfig && !m_guiContainerConfig)
414  {
415  // initialize the GUI
416 
417  // create a grid container
418  PROPAGATE_ERROR(Window::IGuiContainerGrid::create(&m_guiConfig));
419 
420  // create the elements
421  UniquePointer<Window::IGuiElement> element;
422  Dispatcher &dispatcher = Dispatcher::getInstance();
423 
424  Window::IGuiContainerGrid::BuildHelper buildHelper(m_guiConfig);
425 
426 #define CREATE_GUI_ELEMENT(_NAME, _VALUE) \
427  PROPAGATE_ERROR(Window::IGuiElement::createValue(&dispatcher._VALUE, &element));\
428  PROPAGATE_ERROR(buildHelper.append(_NAME, element.get())); \
429  element.release();
430 
431 #define CREATE_GUI_ELEMENT_COMBO_BOX(_NAME, _VALUE, _FROMTYPE, _TOTYPE) \
432  assert(sizeof(_FROMTYPE) == sizeof(_TOTYPE)); \
433  PROPAGATE_ERROR(Window::IGuiElement::createValue(reinterpret_cast< \
434  Value<_TOTYPE>*>(&dispatcher._VALUE), &element)); \
435  PROPAGATE_ERROR(buildHelper.append(_NAME, element.get())); \
436  element.release();
437 
438 #define CREATE_GUI_ELEMENT_PATH_CHOOSER(_NAME, _VALUE) \
439  PROPAGATE_ERROR(Window::IGuiElement::createFileChooser(&dispatcher._VALUE, \
440  true, &element)); \
441  PROPAGATE_ERROR(buildHelper.append(_NAME, element.get())); \
442  element.release();
443 
444  CREATE_GUI_ELEMENT("Verbose", m_verbose);
445  CREATE_GUI_ELEMENT("KPI", m_kpi);
446  CREATE_GUI_ELEMENT("Device", m_deviceIndex);
447 
448  CREATE_GUI_ELEMENT("Exposure time range (ns)", m_exposureTimeRange);
449  CREATE_GUI_ELEMENT("Gain range", m_gainRange);
450  CREATE_GUI_ELEMENT("ISP digital gain range", m_ispDigitalGainRange);
451 
452  CREATE_GUI_ELEMENT_COMBO_BOX("Sensor mode index", m_sensorModeIndex,
453  uint32_t, Window::IGuiElement::ValueTypeEnum);
454  CREATE_GUI_ELEMENT("Frame rate", m_frameRate);
455  CREATE_GUI_ELEMENT("Focus position", m_focusPosition);
456  CREATE_GUI_ELEMENT("Output size", m_outputSize);
457 
458  CREATE_GUI_ELEMENT_PATH_CHOOSER("Output path", m_outputPath);
459 
460  CREATE_GUI_ELEMENT_COMBO_BOX("Video stabilization mode", m_vstabMode,
461  Argus::VideoStabilizationMode, Argus::NamedUUID);
462  CREATE_GUI_ELEMENT_COMBO_BOX("De-Noise mode", m_denoiseMode,
463  Argus::DenoiseMode, Argus::NamedUUID);
464 
465  CREATE_GUI_ELEMENT_COMBO_BOX("AE antibanding mode", m_aeAntibandingMode,
466  Argus::AeAntibandingMode, Window::IGuiElement::ValueTypeEnum);
467 
468  CREATE_GUI_ELEMENT("AE Lock", m_aeLock);
469  CREATE_GUI_ELEMENT("AWB Lock", m_awbLock);
470  CREATE_GUI_ELEMENT_COMBO_BOX("AWB mode", m_awbMode,
471  Argus::AwbMode, Argus::NamedUUID);
472  CREATE_GUI_ELEMENT("Exposure compensation (ev)", m_exposureCompensation);
473 
474 #undef CREATE_GUI_ELEMENT
475 #undef CREATE_GUI_ELEMENT_COMBO_BOX
476 #undef CREATE_GUI_ELEMENT_PATH_CHOOSER
477 
478  m_guiContainerConfig = iGuiContainerConfig;
479  }
480 
482  PROPAGATE_ERROR(m_guiContainerConfig->add(m_guiConfig));
483 
484  m_running = true;
485 
486  return true;
487 }
488 
490 {
491  if (!m_running)
492  return true;
493 
495  PROPAGATE_ERROR(m_guiContainerConfig->remove(m_guiConfig));
496 
497  m_running = true;
498 
499  return true;
500 }
501 
502 }; // namespace ArgusSamples