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
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
41 TaskMultiSession::TaskMultiSession()
42 : m_initialized(false)
43 , m_running(false)
44 {
45 }
46
47 TaskMultiSession::~TaskMultiSession()
48 {
49 shutdown();
50 }
51
52 TaskMultiSession::Session::Session()
53 {
54 }
55
56 TaskMultiSession::Session::~Session()
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
103 bool TaskMultiSession::Session::start()
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
118 bool TaskMultiSession::Session::stop()
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
134 bool TaskMultiSession::Session::shutdown()
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
172 bool TaskMultiSession::initialize()
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
187 bool TaskMultiSession::shutdown()
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
205 bool TaskMultiSession::shutdownSessions()
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
222 bool TaskMultiSession::start()
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
262 bool TaskMultiSession::stop()
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