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-2023, 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 
87  : m_initialized(false)
88  , m_running(false)
89  , m_guiMenuBar(NULL)
90  , m_guiContainerConfig(NULL)
91  , m_guiConfig(NULL)
92 {
93 }
94 
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. ",
117  PROPAGATE_ERROR(options.addOption(
118  Options::Option("saveconfig", 0, "FILE",
119  Options::Option::TYPE_ACTION, "save configuration to XML 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",
191  "set the denoising strength. Negative values are for auto-control"
192  " and positive values for manual settings.",
193  Dispatcher::getInstance().m_denoiseStrength)));
194  PROPAGATE_ERROR(options.addOption(
195  createValueOption("edgeenhance", 0, "MODE", "set the edge enhancement mode.",
196  Dispatcher::getInstance().m_edgeEnhanceMode)));
197  PROPAGATE_ERROR(options.addOption(
198  createValueOption("edgeenhancestrength", 0, "POSITION",
199  "set the edge enhancement strength. Negative values are for auto-control"
200  " and positive values for manual settings.",
201  Dispatcher::getInstance().m_edgeEnhanceStrength)));
202 
203  // auto control settings
204  PROPAGATE_ERROR(options.addOption(
205  createValueOption("aeantibanding", 0, "MODE", "set the auto exposure antibanding mode.",
206  Dispatcher::getInstance().m_aeAntibandingMode)));
207  PROPAGATE_ERROR(options.addOption(
208  createValueOption("aelock", 0, "LOCK", "set the auto exposure lock.",
209  Dispatcher::getInstance().m_aeLock)));
210  PROPAGATE_ERROR(options.addOption(
211  createValueOption("awblock", 0, "LOCK", "set the auto white balance lock.",
212  Dispatcher::getInstance().m_awbLock)));
213  PROPAGATE_ERROR(options.addOption(
214  createValueOption("awb", 0, "MODE", "set the auto white balance mode.",
215  Dispatcher::getInstance().m_awbMode)));
216  PROPAGATE_ERROR(options.addOption(
217  createValueOption("exposurecompensation", 0, "COMPENSATION",
218  "set the exposure compensation to COMPENSATION.",
219  Dispatcher::getInstance().m_exposureCompensation)));
220  PROPAGATE_ERROR(options.addOption(
221  createValueOption("ispdigitalgainrange", 0, "RANGE",
222  "sets the ISP digital gain range.",
223  Dispatcher::getInstance().m_ispDigitalGainRange)));
224  PROPAGATE_ERROR(options.addOption(
225  createValueOption("acregionhorizontal", 0, "RANGE",
226  "sets the AC auto control region horizontal range.",
227  Dispatcher::getInstance().m_acRegionHorizontal)));
228  PROPAGATE_ERROR(options.addOption(
229  createValueOption("acregionvertical", 0, "RANGE",
230  "sets the AC auto control region vertical range.",
231  Dispatcher::getInstance().m_acRegionVertical)));
232 
233  if (Dispatcher::getInstance().supportsExtension(Argus::EXT_DE_FOG))
234  {
235  // DeFog extension settings
236  PROPAGATE_ERROR(options.addOption(
237  createValueOption("defog", 0, "ENABLE",
238  "set the DeFog enable flag to ENABLE.",
239  Dispatcher::getInstance().m_deFogEnable)));
240  PROPAGATE_ERROR(options.addOption(
241  createValueOption("defogamount", 0, "AMOUNT",
242  "sets the amount of fog to be removed to AMOUNT.",
243  Dispatcher::getInstance().m_deFogAmount)));
244  PROPAGATE_ERROR(options.addOption(
245  createValueOption("defogquality", 0, "QUALITY",
246  "sets the quality of the DeFog effect to QUALITY.",
247  Dispatcher::getInstance().m_deFogQuality)));
248  }
249 
250  m_initialized = true;
251 
252  return true;
253 }
254 
256 {
257  if (!m_initialized)
258  return true;
259 
260  PROPAGATE_ERROR_CONTINUE(stop());
261 
262  delete m_guiConfig;
263  m_guiConfig = NULL;
264 
265  m_initialized = false;
266 
267  return true;
268 }
269 
270 bool AppModuleGeneric::start(Window::IGuiMenuBar *iGuiMenuBar,
271  Window::IGuiContainer *iGuiContainerConfig)
272 {
273  if (m_running)
274  return true;
275 
276  if (iGuiMenuBar && !m_guiMenuBar)
277  {
278  // initialize the menu
279 
280  UniquePointer<Window::IGuiMenu> menu;
281  UniquePointer<Window::IGuiMenuItem> item;
282 
283  // create the elements
284  Window::IGuiMenu *fileMenu = iGuiMenuBar->getMenu("File");
285  if (!fileMenu)
286  {
287  PROPAGATE_ERROR(Window::IGuiMenu::create("File", &menu));
288  PROPAGATE_ERROR(iGuiMenuBar->add(menu.get()));
289  fileMenu = menu.get();
290  menu.release();
291  }
292  PROPAGATE_ERROR(Window::IGuiMenuItem::create("Load config", AppModuleGeneric::loadConfig,
293  NULL, &item));
294  PROPAGATE_ERROR(fileMenu->add(item.get()));
295  item.release();
296  PROPAGATE_ERROR(Window::IGuiMenuItem::create("Save Config", AppModuleGeneric::saveConfig,
297  NULL, &item));
298  PROPAGATE_ERROR(fileMenu->add(item.get()));
299  item.release();
300  PROPAGATE_ERROR(Window::IGuiMenuItem::create("Quit", AppModuleGeneric::quit, NULL,
301  &item));
302  PROPAGATE_ERROR(fileMenu->add(item.get()));
303  item.release();
304 
305  Window::IGuiMenu *helpMenu = iGuiMenuBar->getMenu("Help");
306  if (!helpMenu)
307  {
308  PROPAGATE_ERROR(Window::IGuiMenu::create("Help", &menu));
309  PROPAGATE_ERROR(iGuiMenuBar->add(menu.get()));
310  helpMenu = menu.get();
311  menu.release();
312  }
313  PROPAGATE_ERROR(Window::IGuiMenuItem::create("Info", AppModuleGeneric::info, NULL,
314  &item));
315  PROPAGATE_ERROR(helpMenu->add(item.get()));
316  item.release();
317 
318  m_guiMenuBar = iGuiMenuBar;
319  }
320 
321  if (iGuiContainerConfig && !m_guiContainerConfig)
322  {
323  // initialize the GUI
324 
325  // create a grid container
326  PROPAGATE_ERROR(Window::IGuiContainerGrid::create(&m_guiConfig));
327 
328  // create the elements
329  UniquePointer<Window::IGuiElement> element;
330  Dispatcher &dispatcher = Dispatcher::getInstance();
331 
332  Window::IGuiContainerGrid::BuildHelper buildHelper(m_guiConfig);
333 
334 #define CREATE_GUI_ELEMENT(_NAME, _VALUE) \
335  PROPAGATE_ERROR(Window::IGuiElement::createValue(&dispatcher._VALUE, &element));\
336  PROPAGATE_ERROR(buildHelper.append(_NAME, element.get())); \
337  element.release();
338 
339 #define CREATE_GUI_ELEMENT_COMBO_BOX(_NAME, _VALUE, _FROMTYPE, _TOTYPE) \
340  assert(sizeof(_FROMTYPE) == sizeof(_TOTYPE)); \
341  PROPAGATE_ERROR(Window::IGuiElement::createValue(reinterpret_cast< \
342  Value<_TOTYPE>*>(&dispatcher._VALUE), &element)); \
343  PROPAGATE_ERROR(buildHelper.append(_NAME, element.get())); \
344  element.release();
345 
346 #define CREATE_GUI_ELEMENT_PATH_CHOOSER(_NAME, _VALUE) \
347  PROPAGATE_ERROR(Window::IGuiElement::createFileChooser(&dispatcher._VALUE, \
348  true, &element)); \
349  PROPAGATE_ERROR(buildHelper.append(_NAME, element.get())); \
350  element.release();
351 
352  CREATE_GUI_ELEMENT("Verbose", m_verbose);
353  CREATE_GUI_ELEMENT("KPI", m_kpi);
354  CREATE_GUI_ELEMENT("Device", m_deviceIndex);
355 
356  CREATE_GUI_ELEMENT("Exposure time range (ns)", m_exposureTimeRange);
357  CREATE_GUI_ELEMENT("Gain range", m_gainRange);
358  CREATE_GUI_ELEMENT("ISP digital gain range", m_ispDigitalGainRange);
359  CREATE_GUI_ELEMENT("AC region horizontal", m_acRegionHorizontal);
360  CREATE_GUI_ELEMENT("AC region vertical", m_acRegionVertical);
361 
362  CREATE_GUI_ELEMENT_COMBO_BOX("Sensor mode index", m_sensorModeIndex,
363  uint32_t, Window::IGuiElement::ValueTypeEnum);
364  CREATE_GUI_ELEMENT_COMBO_BOX("YUV format", m_captureYuvFormat,
365  Argus::PixelFormat, Argus::NamedUUID);
366  CREATE_GUI_ELEMENT("Frame rate range", m_frameRateRange);
367  CREATE_GUI_ELEMENT("Focus position", m_focusPosition);
368  CREATE_GUI_ELEMENT("Aperture position", m_aperturePosition);
369  CREATE_GUI_ELEMENT_COMBO_BOX("Aperture Fnum", m_apertureFnum,
370  float, Window::IGuiElement::ValueTypeEnum);
371  CREATE_GUI_ELEMENT("Aperture motor speed", m_apertureMotorSpeed);
372  CREATE_GUI_ELEMENT("Output size", m_outputSize);
373 
374  CREATE_GUI_ELEMENT_PATH_CHOOSER("Output path", m_outputPath);
375 
376  CREATE_GUI_ELEMENT_COMBO_BOX("De-Noise mode", m_denoiseMode,
377  Argus::DenoiseMode, Argus::NamedUUID);
378  CREATE_GUI_ELEMENT("De-Noise strength", m_denoiseStrength);
379  CREATE_GUI_ELEMENT_COMBO_BOX("Edge Enhance mode", m_edgeEnhanceMode,
380  Argus::EdgeEnhanceMode, Argus::NamedUUID);
381  CREATE_GUI_ELEMENT("Edge Enhance strength", m_edgeEnhanceStrength);
382 
383  CREATE_GUI_ELEMENT_COMBO_BOX("AE antibanding mode", m_aeAntibandingMode,
384  Argus::AeAntibandingMode, Argus::NamedUUID);
385 
386  CREATE_GUI_ELEMENT("AE Lock", m_aeLock);
387  CREATE_GUI_ELEMENT("AWB Lock", m_awbLock);
388  CREATE_GUI_ELEMENT_COMBO_BOX("AWB mode", m_awbMode,
389  Argus::AwbMode, Argus::NamedUUID);
390  CREATE_GUI_ELEMENT("Exposure compensation (ev)", m_exposureCompensation);
391 
392 #undef CREATE_GUI_ELEMENT
393 #undef CREATE_GUI_ELEMENT_COMBO_BOX
394 #undef CREATE_GUI_ELEMENT_PATH_CHOOSER
395 
396  m_guiContainerConfig = iGuiContainerConfig;
397  }
398 
400  PROPAGATE_ERROR(m_guiContainerConfig->add(m_guiConfig));
401 
402  m_running = true;
403 
404  return true;
405 }
406 
408 {
409  if (!m_running)
410  return true;
411 
413  PROPAGATE_ERROR(m_guiContainerConfig->remove(m_guiConfig));
414 
415  m_running = true;
416 
417  return true;
418 }
419 
420 }; // namespace ArgusSamples