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, 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 "Renderer.h"
33 #include "Dispatcher.h"
34 #include "Error.h"
35 #include "UniquePointer.h"
36 #include "EventThread.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 : m_eventThread(NULL)
54 {
55 }
56
57 TaskMultiSession::Session::~Session()
58 {
59 shutdown();
60 }
61
62 bool TaskMultiSession::Session::initialize(uint32_t deviceIndex)
63 {
64 m_perfTracker.onEvent(TASK_START);
65 Renderer &renderer = Renderer::getInstance();
66
67 Dispatcher &dispatcher = Dispatcher::getInstance();
68
69 // create the session using the current device index
70 PROPAGATE_ERROR(dispatcher.createSession(m_session, deviceIndex));
71
72 // create the request
73 PROPAGATE_ERROR(dispatcher.createRequest(m_request, Argus::CAPTURE_INTENT_STILL_CAPTURE,
74 m_session.get()));
75
76 // Create the preview stream
77 PROPAGATE_ERROR(dispatcher.createOutputStream(m_request.get(), m_outputStream,
78 m_session.get()));
79
80 // bind the preview stream to the renderer
81 Argus::IStream *iStream = Argus::interface_cast<Argus::IStream>(m_outputStream.get());
82 if (!iStream)
83 ORIGINATE_ERROR("Failed to get IStream interface");
84
85 // Bind the stream to the renderer
86 PROPAGATE_ERROR(renderer.bindStream(iStream->getEGLStream()));
87
88 const Argus::Size streamSize = iStream->getResolution();
89 PROPAGATE_ERROR(renderer.setStreamAspectRatio(iStream->getEGLStream(),
90 (float)streamSize.width / (float)streamSize.height));
91
92 // Enable the output stream
93 PROPAGATE_ERROR(dispatcher.enableOutputStream(m_request.get(), m_outputStream.get()));
94
95 std::vector<Argus::EventType> eventTypes;
96 eventTypes.push_back(Argus::EVENT_TYPE_CAPTURE_COMPLETE);
97
98 Argus::UniqueObj<Argus::EventQueue> eventQueue;
99 PROPAGATE_ERROR(dispatcher.createEventQueue(eventTypes, eventQueue, m_session.get()));
100
101 // pass ownership of eventQueue to EventThread
102 m_eventThread.reset(new EventThread(m_session.get(), eventQueue.release(), &m_perfTracker));
103 if (!m_eventThread)
104 {
105 ORIGINATE_ERROR("Failed to allocate EventThread");
106 }
107
108 PROPAGATE_ERROR(m_eventThread->initialize());
109 PROPAGATE_ERROR(m_eventThread->waitRunning());
110
111 return true;
112 }
113
114 bool TaskMultiSession::Session::stop()
115 {
116 m_perfTracker.onEvent(CLOSE_REQUESTED);
117
118 // stop eventThread first to avoid the thread keep waiting for long time to stop
119 PROPAGATE_ERROR(m_eventThread->shutdown());
120 m_eventThread.reset();
121
122 Dispatcher &dispatcher = Dispatcher::getInstance();
123 Renderer &renderer = Renderer::getInstance();
124
125 PROPAGATE_ERROR(dispatcher.stopRepeat(m_session.get()));
126 PROPAGATE_ERROR(renderer.setStreamActive(
127 Argus::interface_cast<Argus::IStream>(m_outputStream)->getEGLStream(), false));
128 PROPAGATE_ERROR(dispatcher.waitForIdle(m_session.get()));
129 m_perfTracker.onEvent(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
140 if (m_outputStream)
141 {
142 // destroy the producer
143 PROPAGATE_ERROR_CONTINUE(dispatcher.disableOutputStream(m_request.get(),
144 m_outputStream.get()));
145
146 const EGLStreamKHR eglStream =
147 Argus::interface_cast<Argus::IStream>(m_outputStream)->getEGLStream();
148
149 m_outputStream.reset();
150
151 // unbind the EGL stream from the renderer
152 PROPAGATE_ERROR_CONTINUE(Renderer::getInstance().unbindStream(eglStream));
153 }
154
155 // destroy the request
156 PROPAGATE_ERROR_CONTINUE(dispatcher.destroyRequest(m_request));
157 }
158
159 m_perfTracker.onEvent(CLOSE_DONE);
160 // Destroy the session
161 m_session.reset();
162
163 return true;
164 }
165
166 bool TaskMultiSession::initialize()
167 {
168 if (m_initialized)
169 return true;
170
171 m_initialized = true;
172
173 return true;
174 }
175
176 bool TaskMultiSession::shutdown()
177 {
178 if (!m_initialized)
179 return true;
180
181 // stop the preview
182 PROPAGATE_ERROR(stop());
183
184 m_initialized = false;
185
186 return true;
187 }
188
189 bool TaskMultiSession::shutdownSessions()
190 {
191 if (!m_sessions.empty())
192 {
193 // shutdown the sessions
194 for (std::list<Session*>::iterator it = m_sessions.begin(); it != m_sessions.end(); ++it)
195 {
196 Session *session = *it;
197 PROPAGATE_ERROR_CONTINUE(session->shutdown());
198 delete session;
199 }
200 m_sessions.clear();
201 }
202
203 return true;
204 }
205
206 bool TaskMultiSession::start()
207 {
208 if (m_running)
209 return true;
210
211 Dispatcher &dispatcher = Dispatcher::getInstance();
212
213 if (m_sessions.empty())
214 {
215 const uint32_t deviceCount = dispatcher.getDeviceCount();
216
217 if (deviceCount == 0)
218 ORIGINATE_ERROR("No camera devices found");
219
220 // create a request and streams for each session
221 for (uint32_t deviceIndex = 0; deviceIndex < deviceCount; ++deviceIndex)
222 {
223 UniquePointer<Session> session(new Session);
224
225 if (!session)
226 ORIGINATE_ERROR("Out of memory");
227
228 PROPAGATE_ERROR(session->initialize(deviceIndex));
229
230 m_sessions.push_back(session.release());
231 }
232 }
233
234 // activate the streams and populate the burst request array
235 Renderer &renderer = Renderer::getInstance();
236 for (std::list<Session*>::iterator it = m_sessions.begin(); it != m_sessions.end(); ++it)
237 {
238 Session *session = *it;
239 PROPAGATE_ERROR(renderer.setStreamActive(
240 Argus::interface_cast<Argus::IStream>(session->m_outputStream)->getEGLStream(), true));
241
242 PerfTracker &perf = session->m_perfTracker;
243 perf.onEvent(ISSUE_CAPTURE);
244 // start the repeating burst request for the preview
245 PROPAGATE_ERROR(dispatcher.startRepeat(session->m_request.get(), session->m_session.get()));
246 }
247
248 m_running = true;
249
250 return true;
251 }
252
253 bool TaskMultiSession::stop()
254 {
255 if (!m_running)
256 return true;
257
258 for (std::list<Session*>::iterator it = m_sessions.begin(); it != m_sessions.end(); ++it)
259 {
260 Session *session = *it;
261 PROPAGATE_ERROR(session->stop());
262 }
263
264 PROPAGATE_ERROR(shutdownSessions());
265
266 m_running = false;
267
268 return true;
269 }
270
271 }; // namespace ArgusSamples