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