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
XMLConfig.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 <string>
30 #include <fstream>
31 #include <stdio.h>
32
33 #include <expat.h>
34
35 #include "XMLConfig.h"
36 #include "Dispatcher.h"
37 #include "UniquePointer.h"
38
39 namespace ArgusSamples
40 {
41
42 // XML version
43 static const char *VERSION = "1.0";
44
45 // element names
46 static const char *ELEMENT_DEVICE_INDEX = "deviceIndex";
47 static const char *ELEMENT_VERBOSE = "verbose";
48 static const char *ELEMENT_KPI = "kpi";
49 static const char *ELEMENT_EXPOSURE_TIME_RANGE = "exposureTimeRange";
50 static const char *ELEMENT_GAIN_RANGE = "gainRange";
51 static const char *ELEMENT_SENSOR_MODE_INDEX = "sensorModeIndex";
52 static const char *ELEMENT_FRAME_RATE = "frameRate";
53 static const char *ELEMENT_FRAME_RATE_RANGE = "frameRateRange";
54 static const char *ELEMENT_FOCUS_POSITION = "focusPosition";
55 static const char *ELEMENT_APERTURE_POSITION = "aperturePosition";
56 static const char *ELEMENT_APERTURE_MOTOR_SPEED = "apertureMotorSpeed";
57 static const char *ELEMENT_CAPTURE_YUV_FORMAT = "captureYuvFormat";
58 static const char *ELEMENT_AE_ANTIBANDING_MODE = "aeAntibandingMode";
59 static const char *ELEMENT_AE_LOCK = "aeLock";
60 static const char *ELEMENT_AWB_LOCK = "awbLock";
61 static const char *ELEMENT_AWB_MODE = "awbMode";
62 static const char *ELEMENT_EXPOSURE_COMPENSATION = "exposureCompensation";
63 static const char *ELEMENT_ISP_DIGITAL_GAIN_RANGE = "ispDigitalGainRange";
64 static const char *ELEMENT_DENOISE_MODE = "denoiseMode";
65 static const char *ELEMENT_STILL_FILE_TYPE = "stillFileType";
66 static const char *ELEMENT_VIDEO_FORMAT = "videoFormat";
67 static const char *ELEMENT_VIDEO_FILE_TYPE = "videoFileType";
68 static const char *ELEMENT_VIDEO_BIT_RATE = "videoBitRate";
69 static const char *ELEMENT_OUTPUT_SIZE = "outputSize";
70 static const char *ELEMENT_OUTPUT_PATH = "outputPath";
71 static const char *ELEMENT_DE_FOG_ENABLE = "deFogEnable";
72 static const char *ELEMENT_DE_FOG_AMOUNT = "deFogAmount";
73 static const char *ELEMENT_DE_FOG_QUALITY = "deFogQaulity";
74
75 static void XMLCALL xmlHandleData(void *parser, const char *s, int len)
76 {
77 XML_Parser p = (XML_Parser)parser;
78 std::string *data = reinterpret_cast<std::string*>(XML_GetUserData(p));
79
80 data->append(s, len);
81 }
82
83 static void XMLCALL xmlStartElement(void *parser, const char *name, const char **atts)
84 {
85 XML_Parser p = (XML_Parser)parser;
86
87 if (strcmp(name, "argusconfig") == 0)
88 {
89 const char **curAtt = atts;
90
91 while (*curAtt != NULL)
92 {
93 const char *attribute = curAtt[0];
94 const char *value = curAtt[1];
95
96 if (strcmp(attribute, "version") == 0)
97 {
98 if (strcmp(value, VERSION) != 0)
99 {
100 ORIGINATE_ERROR_FAIL("Unsupported version '%s' expected version '%s'",
101 value, VERSION);
102 }
103 }
104 else
105 ORIGINATE_ERROR_FAIL("Found unexpected attribute '%s'", attribute);
106 curAtt += 2;
107 }
108 }
109
110 XML_SetCharacterDataHandler(p, xmlHandleData);
111
112 return;
113
114 fail:
115 XML_StopParser(p, XML_FALSE);
116 }
117
118 /**
119 * Check if an element matches the value name, if this is the case set the value to 'dataStr'
120 * @param [in] elementName current element
121 * @param [in] dataStr data for that element
122 * @param [in] valueName value name
123 * @param [in] value value to update with dataStr if there is a match
124 * @param [out] match set if there was a match
125 */
126 template<typename T> static bool checkValue(const char *elementName, const char *dataStr,
127 const char *valueName, Value<T> &value, bool *match)
128 {
129 if (strcmp(elementName, valueName) == 0)
130 {
131 PROPAGATE_ERROR(value.setFromString(dataStr));
132 *match = true;
133 }
134
135 return true;
136 }
137
138 static void XMLCALL xmlEndElement(void *parser, const char *name)
139 {
140 Dispatcher &dispatcher = Dispatcher::getInstance();
141 XML_Parser p = (XML_Parser)parser;
142 std::string *data = reinterpret_cast<std::string*>(XML_GetUserData(p));
143
144 if (strcmp(name, ELEMENT_DEVICE_INDEX) == 0)
145 {
146 PROPAGATE_ERROR_FAIL(dispatcher.m_deviceIndex.setFromString(data->c_str()));
147 }
148 else if (strcmp(name, ELEMENT_VERBOSE) == 0)
149 {
150 PROPAGATE_ERROR_FAIL(dispatcher.m_verbose.setFromString(data->c_str()));
151 }
152 else if (strcmp(name, ELEMENT_KPI) == 0)
153 {
154 PROPAGATE_ERROR_FAIL(dispatcher.m_kpi.setFromString(data->c_str()));
155 }
156 else if (strcmp(name, ELEMENT_EXPOSURE_TIME_RANGE) == 0)
157 {
158 PROPAGATE_ERROR_FAIL(dispatcher.m_exposureTimeRange.setFromString(data->c_str()));
159 }
160 else if (strcmp(name, ELEMENT_GAIN_RANGE) == 0)
161 {
162 PROPAGATE_ERROR_FAIL(dispatcher.m_gainRange.setFromString(data->c_str()));
163 }
164 else if (strcmp(name, ELEMENT_SENSOR_MODE_INDEX) == 0)
165 {
166 PROPAGATE_ERROR_FAIL(dispatcher.m_sensorModeIndex.setFromString(data->c_str()));
167 }
168 else if (strcmp(name, ELEMENT_FRAME_RATE) == 0)
169 {
170 PROPAGATE_ERROR_FAIL(dispatcher.m_frameRate.setFromString(data->c_str()));
171 }
172 else if (strcmp(name, ELEMENT_FRAME_RATE_RANGE) == 0)
173 {
174 PROPAGATE_ERROR_FAIL(dispatcher.m_frameRateRange.setFromString(data->c_str()));
175 }
176 else if (strcmp(name, ELEMENT_FOCUS_POSITION) == 0)
177 {
178 PROPAGATE_ERROR_FAIL(dispatcher.m_focusPosition.setFromString(data->c_str()));
179 }
180 else if (strcmp(name, ELEMENT_APERTURE_POSITION) == 0)
181 {
182 PROPAGATE_ERROR_FAIL(dispatcher.m_aperturePosition.setFromString(data->c_str()));
183 }
184 else if (strcmp(name, ELEMENT_APERTURE_MOTOR_SPEED) == 0)
185 {
186 PROPAGATE_ERROR_FAIL(dispatcher.m_apertureMotorSpeed.setFromString(data->c_str()));
187 }
188 else if (strcmp(name, ELEMENT_CAPTURE_YUV_FORMAT) == 0)
189 {
190 PROPAGATE_ERROR_FAIL(dispatcher.m_captureYuvFormat.setFromString(data->c_str()));
191 }
192 else if (strcmp(name, ELEMENT_DENOISE_MODE) == 0)
193 {
194 PROPAGATE_ERROR_FAIL(dispatcher.m_denoiseMode.setFromString(data->c_str()));
195 }
196 else if (strcmp(name, ELEMENT_AE_ANTIBANDING_MODE) == 0)
197 {
198 PROPAGATE_ERROR_FAIL(dispatcher.m_aeAntibandingMode.setFromString(data->c_str()));
199 }
200 else if (strcmp(name, ELEMENT_AE_LOCK) == 0)
201 {
202 PROPAGATE_ERROR_FAIL(dispatcher.m_aeLock.setFromString(data->c_str()));
203 }
204 else if (strcmp(name, ELEMENT_AWB_LOCK) == 0)
205 {
206 PROPAGATE_ERROR_FAIL(dispatcher.m_awbLock.setFromString(data->c_str()));
207 }
208 else if (strcmp(name, ELEMENT_AWB_MODE) == 0)
209 {
210 PROPAGATE_ERROR_FAIL(dispatcher.m_awbMode.setFromString(data->c_str()));
211 }
212 else if (strcmp(name, ELEMENT_EXPOSURE_COMPENSATION) == 0)
213 {
214 PROPAGATE_ERROR_FAIL(dispatcher.m_exposureCompensation.setFromString(data->c_str()));
215 }
216 else if (strcmp(name, ELEMENT_ISP_DIGITAL_GAIN_RANGE) == 0)
217 {
218 PROPAGATE_ERROR_FAIL(dispatcher.m_ispDigitalGainRange.setFromString(data->c_str()));
219 }
220 else if (strcmp(name, ELEMENT_STILL_FILE_TYPE) == 0)
221 {
222 PROPAGATE_ERROR_FAIL(dispatcher.m_stillFileType.setFromString(data->c_str()));
223 }
224 else if (strcmp(name, ELEMENT_VIDEO_FORMAT) == 0)
225 {
226 PROPAGATE_ERROR_FAIL(dispatcher.m_videoFormat.setFromString(data->c_str()));
227 }
228 else if (strcmp(name, ELEMENT_VIDEO_FILE_TYPE) == 0)
229 {
230 PROPAGATE_ERROR_FAIL(dispatcher.m_videoFileType.setFromString(data->c_str()));
231 }
232 else if (strcmp(name, ELEMENT_VIDEO_BIT_RATE) == 0)
233 {
234 PROPAGATE_ERROR_FAIL(dispatcher.m_videoBitRate.setFromString(data->c_str()));
235 }
236 else if (strcmp(name, ELEMENT_OUTPUT_SIZE) == 0)
237 {
238 PROPAGATE_ERROR_FAIL(dispatcher.m_outputSize.setFromString(data->c_str()));
239 }
240 else if (strcmp(name, ELEMENT_OUTPUT_PATH) == 0)
241 {
242 PROPAGATE_ERROR_FAIL(dispatcher.m_outputPath.set(*data));
243 }
244 else if (strcmp(name, ELEMENT_DE_FOG_ENABLE) == 0)
245 {
246 PROPAGATE_ERROR_FAIL(dispatcher.m_deFogEnable.setFromString(data->c_str()));
247 }
248 else if (strcmp(name, ELEMENT_DE_FOG_AMOUNT) == 0)
249 {
250 PROPAGATE_ERROR_FAIL(dispatcher.m_deFogAmount.setFromString(data->c_str()));
251 }
252 else if (strcmp(name, ELEMENT_DE_FOG_QUALITY) == 0)
253 {
254 PROPAGATE_ERROR_FAIL(dispatcher.m_deFogQuality.setFromString(data->c_str()));
255 }
256 else if (strcmp(name, "argusconfig") == 0)
257 {
258 }
259 else
260 {
261 ORIGINATE_ERROR_FAIL("Unhandled element '%s'.", name);
262 }
263
264 XML_SetCharacterDataHandler(p, NULL);
265 data->clear();
266
267 return;
268
269 fail:
270 XML_StopParser(p, XML_FALSE);
271 }
272
273 bool loadConfig(const char *configFile)
274 {
275 if (configFile == NULL)
276 ORIGINATE_ERROR("'configFile' is NULL");
277
278 FILE *xmlFile;
279 bool success = true;
280 long ftellResult;
281 size_t fileSize;
282 UniquePointer<char> fileData;
283 XML_Parser parser = NULL;
284 std::string data;
285
286 // open the file
287 xmlFile = fopen(configFile, "rb");
288 if (xmlFile == NULL)
289 ORIGINATE_ERROR_FAIL("Failed to open file %s", configFile);
290
291 // get file size
292 if (fseek(xmlFile, 0, SEEK_END) != 0)
293 ORIGINATE_ERROR_FAIL("Failed to read buffer file %s", configFile);
294
295 ftellResult = ftell(xmlFile);
296 if (ftellResult == -1)
297 ORIGINATE_ERROR_FAIL("Failed to read buffer file %s", configFile);
298 if (ftellResult == 0)
299 ORIGINATE_ERROR_FAIL("Empty file %s", configFile);
300
301 fileSize = ftellResult;
302
303 if (fseek(xmlFile, 0, SEEK_SET) != 0)
304 ORIGINATE_ERROR_FAIL("Failed to read buffer file %s", configFile);
305
306 // allocate buffer
307 fileData.reset(new char[fileSize + 1]);
308 if (!fileData)
309 ORIGINATE_ERROR_FAIL("Out of memory");
310
311 // read from file to buffer
312 if (fread(fileData.get(), fileSize, 1, xmlFile) != 1)
313 ORIGINATE_ERROR_FAIL("Failed to read buffer file %s", configFile);
314 // terminate string
315 fileData.get()[fileSize] = 0;
316
317 // create XML parser
318 parser = XML_ParserCreate(NULL);
319 if (parser == NULL)
320 ORIGINATE_ERROR_FAIL("Failed to create parser");
321
322 XML_UseParserAsHandlerArg(parser);
323 // the user data is a string, the XML data handler appens to this, the end element handler
324 // then uses it to set the values
325 XML_SetUserData(parser, &data);
326 XML_SetElementHandler(parser, xmlStartElement, xmlEndElement);
327
328 // start parsing
329 if (XML_Parse(parser, fileData.get(), (int)fileSize, 1) == XML_STATUS_ERROR)
330 {
331 // on failure print the line and column number and the line in which the error occured
332 const XML_Size lineNumber = XML_GetCurrentLineNumber(parser);
333 const XML_Size columnNumber = XML_GetCurrentColumnNumber(parser);
334 const XML_Index byteIndex = XML_GetCurrentByteIndex(parser);
335
336 std::string line;
337
338 if ((byteIndex >= 0) && (static_cast<size_t>(byteIndex) < fileSize))
339 {
340 // find line start
341 size_t lineStart = static_cast<size_t>(byteIndex);
342 while ((lineStart > 0) && (fileData.get()[lineStart] != '\n'))
343 --lineStart;
344 // point after new line
345 if (fileData.get()[lineStart] == '\n')
346 ++lineStart;
347
348 // find line end
349 size_t lineEnd = static_cast<size_t>(lineStart);
350 while ((lineEnd < fileSize) && (fileData.get()[lineEnd] != '\n'))
351 ++lineEnd;
352
353 line.append(&fileData.get()[lineStart], lineEnd - lineStart);
354 }
355 else
356 {
357 line += "-";
358 }
359
360 ORIGINATE_ERROR_FAIL("%s at line %lu:%lu:\n%s",
361 XML_ErrorString(XML_GetErrorCode(parser)),
362 lineNumber, columnNumber, line.c_str());
363 }
364
365 goto succeeded;
366
367 fail:
368 success = false;
369
370 succeeded:
371 if (parser != 0)
372 XML_ParserFree(parser);
373 if (xmlFile != NULL)
374 fclose(xmlFile);
375
376 return success;
377 }
378
379 // write an string to XML
380 static void writeValue(std::ofstream &stream, const char *name, const std::string& string)
381 {
382 stream << " <" << name << ">" << string << "</" << name << ">" << std::endl;
383 }
384
385 // write an value to XML
386 template<typename T> static void writeValue(std::ofstream &stream, const char *name,
387 const Value<T> &value)
388 {
389 writeValue(stream, name, value.toString());
390 }
391
392 bool saveConfig(const char *configFile)
393 {
394 if (configFile == NULL)
395 ORIGINATE_ERROR("'configFile' is NULL");
396
397 Dispatcher &dispatcher = Dispatcher::getInstance();
398
399 // open the stream
400 std::ofstream stream(configFile, std::ofstream::out);
401 if (!stream.is_open())
402 ORIGINATE_ERROR("Failed to open file '%s' for saving.", configFile);
403
404 // header
405 stream << "<?xml version='1.0' encoding='utf-8'?>" << std::endl;
406 stream << "<argusconfig version='" << VERSION << "'>" << std::endl;
407
408 // write the value
409 writeValue(stream, ELEMENT_DEVICE_INDEX, dispatcher.m_deviceIndex);
410 writeValue(stream, ELEMENT_VERBOSE, dispatcher.m_verbose);
411 writeValue(stream, ELEMENT_KPI, dispatcher.m_kpi);
412 writeValue(stream, ELEMENT_EXPOSURE_TIME_RANGE, dispatcher.m_exposureTimeRange);
413 writeValue(stream, ELEMENT_GAIN_RANGE, dispatcher.m_gainRange);
414 writeValue(stream, ELEMENT_SENSOR_MODE_INDEX, dispatcher.m_sensorModeIndex);
415 writeValue(stream, ELEMENT_FRAME_RATE, dispatcher.m_frameRate);
416 writeValue(stream, ELEMENT_FRAME_RATE_RANGE, dispatcher.m_frameRateRange);
417 writeValue(stream, ELEMENT_FOCUS_POSITION, dispatcher.m_focusPosition);
418 writeValue(stream, ELEMENT_APERTURE_POSITION, dispatcher.m_aperturePosition);
419 writeValue(stream, ELEMENT_APERTURE_MOTOR_SPEED, dispatcher.m_apertureMotorSpeed);
420 writeValue(stream, ELEMENT_CAPTURE_YUV_FORMAT, dispatcher.m_captureYuvFormat);
421 writeValue(stream, ELEMENT_DENOISE_MODE, dispatcher.m_denoiseMode);
422 writeValue(stream, ELEMENT_AE_ANTIBANDING_MODE, dispatcher.m_aeAntibandingMode);
423 writeValue(stream, ELEMENT_AE_LOCK, dispatcher.m_aeLock);
424 writeValue(stream, ELEMENT_AWB_LOCK, dispatcher.m_awbLock);
425 writeValue(stream, ELEMENT_AWB_MODE, dispatcher.m_awbMode);
426 writeValue(stream, ELEMENT_EXPOSURE_COMPENSATION, dispatcher.m_exposureCompensation);
427 writeValue(stream, ELEMENT_ISP_DIGITAL_GAIN_RANGE, dispatcher.m_ispDigitalGainRange);
428 writeValue(stream, ELEMENT_STILL_FILE_TYPE, dispatcher.m_stillFileType);
429 writeValue(stream, ELEMENT_VIDEO_FORMAT, dispatcher.m_videoFormat);
430 writeValue(stream, ELEMENT_VIDEO_FILE_TYPE, dispatcher.m_videoFileType);
431 writeValue(stream, ELEMENT_VIDEO_BIT_RATE, dispatcher.m_videoBitRate);
432 writeValue(stream, ELEMENT_OUTPUT_SIZE, dispatcher.m_outputSize);
433 writeValue(stream, ELEMENT_OUTPUT_PATH, dispatcher.m_outputPath.get());
434 writeValue(stream, ELEMENT_DE_FOG_ENABLE, dispatcher.m_deFogEnable);
435 writeValue(stream, ELEMENT_DE_FOG_AMOUNT, dispatcher.m_deFogAmount);
436 writeValue(stream, ELEMENT_DE_FOG_QUALITY, dispatcher.m_deFogQuality);
437
438 // footer
439 stream << "</argusconfig>" << std::endl;
440
441 stream.close();
442
443 return true;
444 }
445
446 }; // namespace ArgusSamples