Argus Camera Sample
Argus Camera Sample
 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 {
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.
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,
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 
103  : m_initialized(false)
104  , m_running(false)
105  , m_guiContainerConfig(NULL)
106  , m_guiConfig(NULL)
107 {
108 }
109 
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 
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 
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 
229 {
230  if (!m_running)
231  return true;
232 
233  PROPAGATE_ERROR(m_videoRecord.stop());
234 
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