Argus Camera Sample
Argus Camera Sample
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
MultiSession.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 <sstream>
30 
31 #include "MultiSession.h"
32 #include "Composer.h"
33 #include "Dispatcher.h"
34 #include "Error.h"
35 #include "UniquePointer.h"
36 #include "PerfTracker.h"
37 
38 namespace ArgusSamples
39 {
40 
42  : m_initialized(false)
43  , m_running(false)
44  , m_prevRunning(false)
45 {
46 }
47 
49 {
50  shutdown();
51 }
52 
54 {
55 }
56 
58 {
59  shutdown();
60 }
61 
62 bool TaskMultiSession::Session::initialize(uint32_t deviceIndex)
63 {
64  // create the perf tracker
65  m_perfTracker.reset(new SessionPerfTracker());
66  if (!m_perfTracker)
67  ORIGINATE_ERROR("Out of memory");
68 
69  PROPAGATE_ERROR(m_perfTracker->onEvent(SESSION_EVENT_TASK_START));
70 
71  Composer &composer = Composer::getInstance();
72  Dispatcher &dispatcher = Dispatcher::getInstance();
73 
74  // create the session using the current device index
75  PROPAGATE_ERROR(dispatcher.createSession(m_session, deviceIndex));
76  PROPAGATE_ERROR(m_perfTracker->setSession(m_session.get()));
77 
78  // create the request
79  PROPAGATE_ERROR(dispatcher.createRequest(m_request, Argus::CAPTURE_INTENT_STILL_CAPTURE,
80  m_session.get()));
81 
82  // Create the preview stream
83  PROPAGATE_ERROR(dispatcher.createOutputStream(m_request.get(), false, m_outputStream,
84  m_session.get()));
85 
86  // bind the preview stream to the composer
87  Argus::IStream *iStream = Argus::interface_cast<Argus::IStream>(m_outputStream.get());
88  if (!iStream)
89  ORIGINATE_ERROR("Failed to get IStream interface");
90 
91  // Bind the stream to the composer
92  PROPAGATE_ERROR(composer.bindStream(iStream->getEGLStream()));
93 
94  const Argus::Size2D<uint32_t> streamSize = iStream->getResolution();
95  PROPAGATE_ERROR(composer.setStreamAspectRatio(iStream->getEGLStream(),
96  (float)streamSize.width() / (float)streamSize.height()));
97 
98  // Enable the output stream
99  PROPAGATE_ERROR(dispatcher.enableOutputStream(m_request.get(), m_outputStream.get()));
100 
101  return true;
102 }
103 
105 {
106  Composer &composer = Composer::getInstance();
107 
108  // activate the streams and populate the burst request array
109  PROPAGATE_ERROR(composer.setStreamActive(
110  Argus::interface_cast<Argus::IStream>(m_outputStream)->getEGLStream(), true));
111 
112  // start the repeating burst request for the preview
113  PROPAGATE_ERROR(m_perfTracker->onEvent(SESSION_EVENT_ISSUE_CAPTURE));
114  PROPAGATE_ERROR(Dispatcher::getInstance().startRepeat(m_request.get(), m_session.get()));
115 
116  return true;
117 }
118 
120 {
121  PROPAGATE_ERROR(m_perfTracker->onEvent(SESSION_EVENT_CLOSE_REQUESTED));
122 
123  Dispatcher &dispatcher = Dispatcher::getInstance();
124  Composer &composer = Composer::getInstance();
125 
126  PROPAGATE_ERROR(dispatcher.stopRepeat(m_session.get()));
127  PROPAGATE_ERROR(composer.setStreamActive(
128  Argus::interface_cast<Argus::IStream>(m_outputStream)->getEGLStream(), false));
129  PROPAGATE_ERROR(dispatcher.waitForIdle(m_session.get()));
130  PROPAGATE_ERROR(m_perfTracker->onEvent(SESSION_EVENT_FLUSH_DONE));
131 
132  return true;
133 }
134 
136 {
137  if (m_request)
138  {
139  Dispatcher &dispatcher = Dispatcher::getInstance();
140  Composer &composer = Composer::getInstance();
141 
142  if (m_outputStream)
143  {
144  // destroy the producer
145  PROPAGATE_ERROR_CONTINUE(dispatcher.disableOutputStream(m_request.get(),
146  m_outputStream.get()));
147 
148  Argus::IStream *iStream = Argus::interface_cast<Argus::IStream>(m_outputStream);
149  if (!iStream)
150  REPORT_ERROR("Failed to get IStream interface");
151 
152  // disconnect the EGL stream
153  iStream->disconnect();
154 
155  // unbind the EGL stream from the composer
156  PROPAGATE_ERROR_CONTINUE(composer.unbindStream(iStream->getEGLStream()));
157 
158  m_outputStream.reset();
159  }
160 
161  // destroy the request
162  PROPAGATE_ERROR_CONTINUE(m_request.reset());
163  }
164 
165  PROPAGATE_ERROR(m_perfTracker->onEvent(SESSION_EVENT_CLOSE_DONE));
166 
167  // Destroy the session
168  m_session.reset();
169 
170  return true;
171 }
172 
174 {
175  if (m_initialized)
176  return true;
177 
178  PROPAGATE_ERROR_CONTINUE(Dispatcher::getInstance().m_sensorModeValid.registerObserver(this,
179  static_cast<IObserver::CallbackFunction>(&TaskMultiSession::onSensorModeValidChanged)));
180  PROPAGATE_ERROR_CONTINUE(Dispatcher::getInstance().m_outputSize.registerObserver(this,
181  static_cast<IObserver::CallbackFunction>(&TaskMultiSession::restartStreams)));
182 
183  m_initialized = true;
184 
185  return true;
186 }
187 
189 {
190  if (!m_initialized)
191  return true;
192 
193  // stop the preview
194  PROPAGATE_ERROR(stop());
195 
196  PROPAGATE_ERROR_CONTINUE(Dispatcher::getInstance().m_outputSize.unregisterObserver(this,
197  static_cast<IObserver::CallbackFunction>(&TaskMultiSession::restartStreams)));
198  PROPAGATE_ERROR_CONTINUE(Dispatcher::getInstance().m_sensorModeValid.unregisterObserver(this,
199  static_cast<IObserver::CallbackFunction>(&TaskMultiSession::onSensorModeValidChanged)));
200 
201  m_initialized = false;
202 
203  return true;
204 }
205 
207 {
208  if (!m_sessions.empty())
209  {
210  // shutdown the sessions
211  for (std::list<Session*>::iterator it = m_sessions.begin(); it != m_sessions.end(); ++it)
212  {
213  Session *session = *it;
214  PROPAGATE_ERROR_CONTINUE(session->shutdown());
215  delete session;
216  }
217  m_sessions.clear();
218  }
219 
220  return true;
221 }
222 
224 {
225  if (m_running)
226  return true;
227 
228  Dispatcher &dispatcher = Dispatcher::getInstance();
229 
230  if (m_sessions.empty())
231  {
232  const uint32_t deviceCount = dispatcher.getDeviceCount();
233 
234  if (deviceCount == 0)
235  ORIGINATE_ERROR("No camera devices found");
236 
237  // create a request and streams for each session
238  for (uint32_t deviceIndex = 0; deviceIndex < deviceCount; ++deviceIndex)
239  {
240  UniquePointer<Session> session(new Session);
241 
242  if (!session)
243  ORIGINATE_ERROR("Out of memory");
244 
245  PROPAGATE_ERROR(session->initialize(deviceIndex));
246 
247  m_sessions.push_back(session.release());
248  }
249  }
250 
251  // start the sessions
252  for (std::list<Session*>::iterator it = m_sessions.begin(); it != m_sessions.end(); ++it)
253  {
254  Session *session = *it;
255  PROPAGATE_ERROR(session->start());
256  }
257 
258  m_running = true;
259 
260  return true;
261 }
262 
264 {
265  if (!m_running)
266  return true;
267 
268  for (std::list<Session*>::iterator it = m_sessions.begin(); it != m_sessions.end(); ++it)
269  {
270  Session *session = *it;
271  PROPAGATE_ERROR(session->stop());
272  }
273 
274  PROPAGATE_ERROR(shutdownSessions());
275 
276  m_running = false;
277 
278  return true;
279 }
280 
281 bool TaskMultiSession::onSensorModeValidChanged(const Observed &source)
282 {
283  const bool isTrue = static_cast<const Value<bool>&>(source).get();
284 
285  if (!isTrue)
286  {
288  if (m_running)
289  {
290  PROPAGATE_ERROR(stop());
291  }
292  }
293  else if (m_prevRunning)
294  {
295  m_prevRunning = false;
296  PROPAGATE_ERROR(start());
297  }
298 
299  return true;
300 }
301 
302 bool TaskMultiSession::restartStreams(__attribute__((unused)) const Observed &source)
303 {
304  if (m_running)
305  {
306  PROPAGATE_ERROR(stop());
307  PROPAGATE_ERROR(start());
308  }
309  return true;
310 }
311 
312 }; // namespace ArgusSamples