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-2017, 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 
99  : m_initialized(false)
100  , m_running(false)
101  , m_guiMenuBar(NULL)
102  , m_guiContainerConfig(NULL)
103  , m_guiConfig(NULL)
104 {
105 }
106 
108 {
109  shutdown();
110 }
111 
112 bool AppModuleGeneric::initialize(Options &options)
113 {
114  if (m_initialized)
115  return true;
116 
117  PROPAGATE_ERROR(options.addDescription(
118  "The supported value range of some settings is device or sensor mode dependent.\n"
119  "Use the '--info' option to get a list of the supported values.\n"));
120 
121  PROPAGATE_ERROR(options.addOption(
122  Options::Option("info", 'i', "",
123  Options::Option::TYPE_ACTION, Options::Option::FLAG_NO_ARGUMENT,
124  "print information on devices.", info)));
125 
126  PROPAGATE_ERROR(options.addOption(
127  Options::Option("loadconfig", 0, "FILE",
128  Options::Option::TYPE_ACTION, Options::Option::FLAG_OPTIONAL_ARGUMENT,
129  "load configuration from XML FILE. Default for file is '" DEFAULT_CONFIG_FILE "'.",
130  loadConfig)));
131  PROPAGATE_ERROR(options.addOption(
132  Options::Option("saveconfig", 0, "FILE",
133  Options::Option::TYPE_ACTION, Options::Option::FLAG_OPTIONAL_ARGUMENT,
134  "save configuration to XML FILE. Default for file is '" DEFAULT_CONFIG_FILE "'.",
135  saveConfig)));
136 
137  PROPAGATE_ERROR(options.addOption(
138  Options::Option("verbose", 0, "", Dispatcher::getInstance().m_verbose,
139  "enable verbose mode.", verbose)));
140  PROPAGATE_ERROR(options.addOption(
141  Options::Option("kpi", 0, "", Dispatcher::getInstance().m_kpi,
142  "enable kpi mode.", kpi)));
143  PROPAGATE_ERROR(options.addOption(
144  createValueOption("device", 'd', "INDEX", "select camera device with INDEX.",
145  Dispatcher::getInstance().m_deviceIndex)));
146 
147  // source settings
148  PROPAGATE_ERROR(options.addOption(
149  createValueOption("exposuretimerange", 0, "RANGE",
150  "sets the exposure time range to RANGE, in nanoseconds.",
151  Dispatcher::getInstance().m_exposureTimeRange)));
152  PROPAGATE_ERROR(options.addOption(
153  createValueOption("gainrange", 0, "RANGE", "sets the gain range to RANGE.",
154  Dispatcher::getInstance().m_gainRange)));
155  PROPAGATE_ERROR(options.addOption(
156  createValueOption("sensormode", 0, "INDEX", "set sensor mode to INDEX.",
157  Dispatcher::getInstance().m_sensorModeIndex)));
158  PROPAGATE_ERROR(options.addOption(
159  createValueOption("framerate", 0, "RATE",
160  "set the sensor frame rate to RATE. If RATE is 0 then VFR (variable frame rate) is "
161  "enabled.", Dispatcher::getInstance().m_frameRate)));
162  PROPAGATE_ERROR(options.addOption(
163  createValueOption("focusposition", 0, "POSITION",
164  "sets the focus position to POSITION, in focuser units.",
165  Dispatcher::getInstance().m_focusPosition)));
166 
167  // output settings
168  PROPAGATE_ERROR(options.addOption(
169  createValueOption("outputsize", 0, "WIDTHxHEIGHT",
170  "set the still and video output size to WIDTHxHEIGHT (e.g. 1920x1080). If WIDTHxHEIGHT "
171  "is '0x0' the output size is the sensor mode size.",
172  Dispatcher::getInstance().m_outputSize)));
173  PROPAGATE_ERROR(options.addOption(
174  createValueOption("outputpath", 0, "PATH",
175  "set the output file path. A file name, an incrementing index and the file extension will "
176  "be appended. E.g. setting 'folder/' will result in 'folder/image0.jpg' or "
177  "'folder/video0.mp4'. '/dev/null' can be used to discard output.",
178  Dispatcher::getInstance().m_outputPath)));
179 
180  // stream settings
181  PROPAGATE_ERROR(options.addOption(
182  createValueOption("vstab", 0, "MODE", "set the video stabilization mode.",
183  Dispatcher::getInstance().m_vstabMode)));
184  PROPAGATE_ERROR(options.addOption(
185  createValueOption("denoise", 0, "MODE", "set the denoising mode.",
186  Dispatcher::getInstance().m_denoiseMode)));
187  PROPAGATE_ERROR(options.addOption(
188  createValueOption("denoisestrength", 0, "POSITION", "set the denoising strength.",
189  Dispatcher::getInstance().m_denoiseStrength)));
190  PROPAGATE_ERROR(options.addOption(
191  createValueOption("edgeenhance", 0, "MODE", "set the edge enhancement mode.",
192  Dispatcher::getInstance().m_edgeEnhanceMode)));
193  PROPAGATE_ERROR(options.addOption(
194  createValueOption("edgeenhancestrength", 0, "POSITION",
195  "set the edge enhancement strength.",
196  Dispatcher::getInstance().m_edgeEnhanceStrength)));
197 
198  // auto control settings
199  PROPAGATE_ERROR(options.addOption(
200  createValueOption("aeantibanding", 0, "MODE", "set the auto exposure antibanding mode.",
201  Dispatcher::getInstance().m_aeAntibandingMode)));
202  PROPAGATE_ERROR(options.addOption(
203  createValueOption("aelock", 0, "LOCK", "set the auto exposure lock.",
204  Dispatcher::getInstance().m_aeLock)));
205  PROPAGATE_ERROR(options.addOption(
206  createValueOption("awblock", 0, "LOCK", "set the auto white balance lock.",
207  Dispatcher::getInstance().m_awbLock)));
208  PROPAGATE_ERROR(options.addOption(
209  createValueOption("awb", 0, "MODE", "set the auto white balance mode.",
210  Dispatcher::getInstance().m_awbMode)));
211  PROPAGATE_ERROR(options.addOption(
212  createValueOption("exposurecompensation", 0, "COMPENSATION",
213  "set the exposure compensation to COMPENSATION.",
214  Dispatcher::getInstance().m_exposureCompensation)));
215  PROPAGATE_ERROR(options.addOption(
216  createValueOption("ispdigitalgainrange", 0, "RANGE",
217  "sets the ISP digital gain range.",
218  Dispatcher::getInstance().m_ispDigitalGainRange)));
219 
220  if (Dispatcher::getInstance().supportsExtension(Argus::EXT_DE_FOG))
221  {
222  // DeFog extension settings
223  PROPAGATE_ERROR(options.addOption(
224  createValueOption("defog", 0, "ENABLE",
225  "set the DeFog enable flag to ENABLE.",
226  Dispatcher::getInstance().m_deFogEnable)));
227  PROPAGATE_ERROR(options.addOption(
228  createValueOption("defogamount", 0, "AMOUNT",
229  "sets the amount of fog to be removed to AMOUNT.",
230  Dispatcher::getInstance().m_deFogAmount)));
231  PROPAGATE_ERROR(options.addOption(
232  createValueOption("defogquality", 0, "QUALITY",
233  "sets the quality of the DeFog effect to QUALITY.",
234  Dispatcher::getInstance().m_deFogQuality)));
235  }
236 
237  m_initialized = true;
238 
239  return true;
240 }
241 
243 {
244  if (!m_initialized)
245  return true;
246 
247  PROPAGATE_ERROR_CONTINUE(stop());
248 
249  delete m_guiConfig;
250  m_guiConfig = NULL;
251 
252  m_initialized = false;
253 
254  return true;
255 }
256 
257 bool AppModuleGeneric::start(Window::IGuiMenuBar *iGuiMenuBar,
258  Window::IGuiContainer *iGuiContainerConfig)
259 {
260  if (m_running)
261  return true;
262 
263  if (iGuiMenuBar && !m_guiMenuBar)
264  {
265  // initialize the menu
266 
267  UniquePointer<Window::IGuiMenu> menu;
268  UniquePointer<Window::IGuiMenuItem> item;
269 
270  // create the elements
271  Window::IGuiMenu *fileMenu = iGuiMenuBar->getMenu("File");
272  if (!fileMenu)
273  {
274  PROPAGATE_ERROR(Window::IGuiMenu::create("File", &menu));
275  PROPAGATE_ERROR(iGuiMenuBar->add(menu.get()));
276  fileMenu = menu.get();
277  menu.release();
278  }
279  PROPAGATE_ERROR(Window::IGuiMenuItem::create("Load config", AppModuleGeneric::loadConfig,
280  NULL, &item));
281  PROPAGATE_ERROR(fileMenu->add(item.get()));
282  item.release();
283  PROPAGATE_ERROR(Window::IGuiMenuItem::create("Save Config", AppModuleGeneric::saveConfig,
284  NULL, &item));
285  PROPAGATE_ERROR(fileMenu->add(item.get()));
286  item.release();
287  PROPAGATE_ERROR(Window::IGuiMenuItem::create("Quit", AppModuleGeneric::quit, NULL,
288  &item));
289  PROPAGATE_ERROR(fileMenu->add(item.get()));
290  item.release();
291 
292  Window::IGuiMenu *helpMenu = iGuiMenuBar->getMenu("Help");
293  if (!helpMenu)
294  {
295  PROPAGATE_ERROR(Window::IGuiMenu::create("Help", &menu));
296  PROPAGATE_ERROR(iGuiMenuBar->add(menu.get()));
297  helpMenu = menu.get();
298  menu.release();
299  }
300  PROPAGATE_ERROR(Window::IGuiMenuItem::create("Info", AppModuleGeneric::info, NULL,
301  &item));
302  PROPAGATE_ERROR(helpMenu->add(item.get()));
303  item.release();
304 
305  m_guiMenuBar = iGuiMenuBar;
306  }
307 
308  if (iGuiContainerConfig && !m_guiContainerConfig)
309  {
310  // initialize the GUI
311 
312  // create a grid container
313  PROPAGATE_ERROR(Window::IGuiContainerGrid::create(&m_guiConfig));
314 
315  // create the elements
316  UniquePointer<Window::IGuiElement> element;
317  Dispatcher &dispatcher = Dispatcher::getInstance();
318 
319  Window::IGuiContainerGrid::BuildHelper buildHelper(m_guiConfig);
320 
321 #define CREATE_GUI_ELEMENT(_NAME, _VALUE) \
322  PROPAGATE_ERROR(Window::IGuiElement::createValue(&dispatcher._VALUE, &element));\
323  PROPAGATE_ERROR(buildHelper.append(_NAME, element.get())); \
324  element.release();
325 
326 #define CREATE_GUI_ELEMENT_COMBO_BOX(_NAME, _VALUE, _FROMTYPE, _TOTYPE) \
327  assert(sizeof(_FROMTYPE) == sizeof(_TOTYPE)); \
328  PROPAGATE_ERROR(Window::IGuiElement::createValue(reinterpret_cast< \
329  Value<_TOTYPE>*>(&dispatcher._VALUE), &element)); \
330  PROPAGATE_ERROR(buildHelper.append(_NAME, element.get())); \
331  element.release();
332 
333 #define CREATE_GUI_ELEMENT_PATH_CHOOSER(_NAME, _VALUE) \
334  PROPAGATE_ERROR(Window::IGuiElement::createFileChooser(&dispatcher._VALUE, \
335  true, &element)); \
336  PROPAGATE_ERROR(buildHelper.append(_NAME, element.get())); \
337  element.release();
338 
339  CREATE_GUI_ELEMENT("Verbose", m_verbose);
340  CREATE_GUI_ELEMENT("KPI", m_kpi);
341  CREATE_GUI_ELEMENT("Device", m_deviceIndex);
342 
343  CREATE_GUI_ELEMENT("Exposure time range (ns)", m_exposureTimeRange);
344  CREATE_GUI_ELEMENT("Gain range", m_gainRange);
345  CREATE_GUI_ELEMENT("ISP digital gain range", m_ispDigitalGainRange);
346 
347  CREATE_GUI_ELEMENT_COMBO_BOX("Sensor mode index", m_sensorModeIndex,
348  uint32_t, Window::IGuiElement::ValueTypeEnum);
349  CREATE_GUI_ELEMENT("Frame rate", m_frameRate);
350  CREATE_GUI_ELEMENT("Focus position", m_focusPosition);
351  CREATE_GUI_ELEMENT("Output size", m_outputSize);
352 
353  CREATE_GUI_ELEMENT_PATH_CHOOSER("Output path", m_outputPath);
354 
355  CREATE_GUI_ELEMENT_COMBO_BOX("Video stabilization mode", m_vstabMode,
356  Argus::VideoStabilizationMode, Argus::NamedUUID);
357  CREATE_GUI_ELEMENT_COMBO_BOX("De-Noise mode", m_denoiseMode,
358  Argus::DenoiseMode, Argus::NamedUUID);
359  CREATE_GUI_ELEMENT("De-Noise strength", m_denoiseStrength);
360  CREATE_GUI_ELEMENT_COMBO_BOX("Edge Enhance mode", m_edgeEnhanceMode,
361  Argus::EdgeEnhanceMode, Argus::NamedUUID);
362  CREATE_GUI_ELEMENT("Edge Enhance strength", m_edgeEnhanceStrength);
363 
364  CREATE_GUI_ELEMENT_COMBO_BOX("AE antibanding mode", m_aeAntibandingMode,
365  Argus::AeAntibandingMode, Window::IGuiElement::ValueTypeEnum);
366 
367  CREATE_GUI_ELEMENT("AE Lock", m_aeLock);
368  CREATE_GUI_ELEMENT("AWB Lock", m_awbLock);
369  CREATE_GUI_ELEMENT_COMBO_BOX("AWB mode", m_awbMode,
370  Argus::AwbMode, Argus::NamedUUID);
371  CREATE_GUI_ELEMENT("Exposure compensation (ev)", m_exposureCompensation);
372 
373 #undef CREATE_GUI_ELEMENT
374 #undef CREATE_GUI_ELEMENT_COMBO_BOX
375 #undef CREATE_GUI_ELEMENT_PATH_CHOOSER
376 
377  m_guiContainerConfig = iGuiContainerConfig;
378  }
379 
381  PROPAGATE_ERROR(m_guiContainerConfig->add(m_guiConfig));
382 
383  m_running = true;
384 
385  return true;
386 }
387 
389 {
390  if (!m_running)
391  return true;
392 
394  PROPAGATE_ERROR(m_guiContainerConfig->remove(m_guiConfig));
395 
396  m_running = true;
397 
398  return true;
399 }
400 
401 }; // namespace ArgusSamples