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, 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 
42  : m_initialized(false)
43  , m_running(false)
44 {
45 }
46 
48 {
49  shutdown();
50 }
51 
53  : m_eventThread(NULL)
54 {
55 }
56 
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::Size2D<uint32_t> 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 
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 
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(m_request.reset());
157  }
158 
159  m_perfTracker.onEvent(CLOSE_DONE);
160  // Destroy the session
161  m_session.reset();
162 
163  return true;
164 }
165 
167 {
168  if (m_initialized)
169  return true;
170 
171  m_initialized = true;
172 
173  return true;
174 }
175 
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 
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 
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 
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