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
AppModuleVideo.cpp
Go to the documentation of this file.
1 /*
2 * Copyright (c) 2016-2018, 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 "AppModuleVideo.h"
30
31 #include <stdlib.h>
32 #include <string.h>
33 #include <unistd.h>
34
35 #include "Dispatcher.h"
36 #include "Util.h"
37 #include "Error.h"
38 #include "Options.h"
39 #include "ScopedGuard.h"
40 #include "VideoPipeline.h"
41
42 namespace ArgusSamples
43 {
44
45 /* static */ bool AppModuleVideo::video(void *userPtr, const char *optArg)
46 {
47 if (!VideoPipeline::isSupported())
48 {
49 fprintf(stderr, "------------------------------------------------------\n");
50 fprintf(stderr, "Error: Video recording is not supported on Android due\n");
51 fprintf(stderr, "to the lack of the required gstreamer functionality\n");
52 fprintf(stderr, "------------------------------------------------------\n");
53 ORIGINATE_ERROR("Unsupported function on Android");
54 }
55
56 AppModuleVideo *module = reinterpret_cast< AppModuleVideo*>(userPtr);
57
58 const float seconds = atof(optArg);
59 if (seconds <= 0.0f)
60 ORIGINATE_ERROR("'SECONDS' is invalid, must not be less than or equal to zero");
61
62 // start the video module
63 PROPAGATE_ERROR(module->start());
64 // the scoped guard is used to call the stop function if following calls fail so that
65 // the function is exited with module stopped.
66 ScopedGuard<AppModuleVideo> runningGuard(module, &AppModuleVideo::stop);
67
68 const TimeValue endTime = getCurrentTime() + TimeValue::fromSec(seconds);
69
70 // start the recording
71 PROPAGATE_ERROR(module->m_videoRecord.startRecording());
72 ScopedGuard<TaskVideoRecord> recordingGuard(&module->m_videoRecord,
73 &TaskVideoRecord::stopRecording);
74
75 // wait until the time has elapsed
76 while (getCurrentTime() < endTime)
77 {
78 PROPAGATE_ERROR(Window::getInstance().pollEvents());
79 usleep(1000);
80 }
81
82 // stop recording
83 recordingGuard.cancel();
84 PROPAGATE_ERROR(module->m_videoRecord.stopRecording());
85
86 // stop the module
87 runningGuard.cancel();
88 PROPAGATE_ERROR(module->stop());
89
90 return true;
91 }
92
93 /* static */ bool AppModuleVideo::toggleRecording(void *userPtr, const char *optArg)
94 {
95 AppModuleVideo *module = reinterpret_cast< AppModuleVideo*>(userPtr);
96
97 PROPAGATE_ERROR(module->m_videoRecord.toggleRecording());
98
99 return true;
100 }
101
102 AppModuleVideo::AppModuleVideo()
103 : m_initialized(false)
104 , m_running(false)
105 , m_guiContainerConfig(NULL)
106 , m_guiConfig(NULL)
107 {
108 }
109
110 AppModuleVideo::~AppModuleVideo()
111 {
112 shutdown();
113 }
114
115 bool AppModuleVideo::initialize(Options &options)
116 {
117 if (m_initialized)
118 return true;
119
120 PROPAGATE_ERROR(m_videoRecord.initialize());
121
122 PROPAGATE_ERROR(options.addOption(
123 Options::Option("video", 'v', "DURATION", Options::Option::TYPE_ACTION,
124 "record video for DURATION seconds and save to a file.", video, this)));
125
126 PROPAGATE_ERROR(options.addOption(
127 createValueOption("videobitrate", 0, "RATE",
128 "set the video bit rate mode to RATE. If RATE is zero a reasonable default "
129 "is selected.", Dispatcher::getInstance().m_videoBitRate)));
130 PROPAGATE_ERROR(options.addOption(
131 createValueOption("videoformat", 0, "FORMAT",
132 "set the video format. Jetson-tx1 doesn't support vp9, use other "
133 "available formats.", Dispatcher::getInstance().m_videoFormat)));
134 PROPAGATE_ERROR(options.addOption(
135 createValueOption("videofiletype", 0, "TYPE",
136 "set the video file type. For video format 'h265/vp9' set the file type as 'mkv' "
137 "since 'h265 & vp9' are only supported by the 'mkv' container.",
138 Dispatcher::getInstance().m_videoFileType)));
139
140 m_initialized = true;
141
142 return true;
143 }
144
145 bool AppModuleVideo::shutdown()
146 {
147 if (!m_initialized)
148 return true;
149
150 PROPAGATE_ERROR_CONTINUE(stop());
151
152 PROPAGATE_ERROR_CONTINUE(m_videoRecord.shutdown());
153
154 delete m_guiConfig;
155 m_guiConfig = NULL;
156
157 m_guiContainerConfig = NULL;
158
159 m_initialized = false;
160
161 return true;
162 }
163
164 bool AppModuleVideo::start(Window::IGuiMenuBar *iGuiMenuBar,
165 Window::IGuiContainer *iGuiContainerConfig)
166 {
167 if (m_running)
168 return true;
169
170 // register key observer
171 PROPAGATE_ERROR(Window::getInstance().registerObserver(this));
172
173 // initialize the GUI
174 if (iGuiContainerConfig && !m_guiConfig)
175 {
176 // initialize the GUI
177
178 // create a grid container
179 PROPAGATE_ERROR(Window::IGuiContainerGrid::create(&m_guiConfig));
180
181 // create the elements
182 UniquePointer<Window::IGuiElement> element;
183 Dispatcher &dispatcher = Dispatcher::getInstance();
184
185 Window::IGuiContainerGrid::BuildHelper buildHelper(m_guiConfig);
186
187 #define CREATE_GUI_ELEMENT(_NAME, _VALUE) \
188 PROPAGATE_ERROR(Window::IGuiElement::createValue(&dispatcher._VALUE, &element));\
189 PROPAGATE_ERROR(buildHelper.append(_NAME, element.get())); \
190 element.release();
191
192 #define CREATE_GUI_ELEMENT_COMBO_BOX(_NAME, _VALUE, _FROMTYPE, _TOTYPE) \
193 assert(sizeof(_FROMTYPE) == sizeof(_TOTYPE)); \
194 PROPAGATE_ERROR(Window::IGuiElement::createValue(reinterpret_cast< \
195 Value<_TOTYPE>*>(&dispatcher._VALUE), &element)); \
196 PROPAGATE_ERROR(buildHelper.append(_NAME, element.get())); \
197 element.release();
198
199 CREATE_GUI_ELEMENT_COMBO_BOX("Video Format", m_videoFormat,
200 VideoPipeline::VideoFormat, Window::IGuiElement::ValueTypeEnum);
201 CREATE_GUI_ELEMENT_COMBO_BOX("Video File Type", m_videoFileType,
202 VideoPipeline::VideoFileType, Window::IGuiElement::ValueTypeEnum);
203
204 CREATE_GUI_ELEMENT("Video Bit Rate", m_videoBitRate);
205
206 #undef CREATE_GUI_ELEMENT
207 #undef CREATE_GUI_ELEMENT_COMBO_BOX
208
209 PROPAGATE_ERROR(Window::IGuiElement::createAction("Toggle Recording",
210 AppModuleVideo::toggleRecording, this, Window::IGuiElement::FLAG_BUTTON_TOGGLE,
211 Window::IGuiElement::ICON_MEDIA_RECORD, &element));
212 PROPAGATE_ERROR(buildHelper.append(element.get(), 2));
213 element.release();
214
215 m_guiContainerConfig = iGuiContainerConfig;
216 }
217
218 if (m_guiContainerConfig)
219 PROPAGATE_ERROR(m_guiContainerConfig->add(m_guiConfig));
220
221 PROPAGATE_ERROR(m_videoRecord.start());
222
223 m_running = true;
224
225 return true;
226 }
227
228 bool AppModuleVideo::stop()
229 {
230 if (!m_running)
231 return true;
232
233 PROPAGATE_ERROR(m_videoRecord.stop());
234
235 if (m_guiContainerConfig)
236 PROPAGATE_ERROR(m_guiContainerConfig->remove(m_guiConfig));
237
238 // unregister key observer
239 PROPAGATE_ERROR(Window::getInstance().unregisterObserver(this));
240
241 m_running = false;
242
243 return true;
244 }
245
246 bool AppModuleVideo::onKey(const Key &key)
247 {
248 if (key == Key("space"))
249 {
250 PROPAGATE_ERROR(m_videoRecord.toggleRecording());
251 }
252
253 return true;
254 }
255
256 }; // namespace ArgusSamples