Argus Camera Sample
Argus Camera Sample
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
PerfTracker.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 "PerfTracker.h"
30 
31 #include <stdio.h>
32 #define __STDC_FORMAT_MACROS
33 #include <inttypes.h>
34 
35 #include <limits>
36 
37 #include "Dispatcher.h"
38 #include "EventThread.h"
39 #include "InitOnce.h"
40 
41 namespace ArgusSamples
42 {
43 
45  : m_sessionId(0)
46 {
47 }
48 
50 {
51 }
52 
54 {
55  m_sessionId = 0;
56  m_displayCount = 0;
57  return true;
58 }
59 
61 {
62  static InitOnce initOnce;
63  static PerfTracker instance;
64 
65  if (initOnce.begin())
66  {
67  if (instance.initialize())
68  {
69  initOnce.complete();
70  }
71  else
72  {
73  initOnce.failed();
74  REPORT_ERROR("Initalization failed");
75  }
76  }
77 
78  return instance;
79 }
80 
82 {
83  switch (event)
84  {
87  break;
90  break;
92  if (!Dispatcher::getInstance().m_kpi)
93  return true;
94 
96  {
97  // start measurement
99  }
100  else
101  {
102  const TimeValue curTime = getCurrentTime();
103 
104  m_displayCount++;
105 
106  // print every second
107  if (curTime - m_firstDisplayTime > TimeValue::fromSec(1.f))
108  {
109  const float frameRate = static_cast<float>(m_displayCount) *
110  (curTime - m_firstDisplayTime).toCyclesPerSec();
111  printf("PerfTracker: display frame rate %.2f frames per second\n", frameRate);
112 
113  // restart measurement
115  m_displayCount = 0;
116  }
117  }
118  break;
119  default:
120  ORIGINATE_ERROR("Unhandled global event");
121  break;
122  }
123 
124  return true;
125 }
126 
128  : m_id(PerfTracker::getInstance().getNewSessionID())
129  , m_session(NULL)
130  , m_numberframesReceived(0)
131  , m_lastFrameCount(0)
132  , m_totalFrameDrop(0)
133  , m_minLatency(std::numeric_limits<uint64_t>::max())
134  , m_maxLatency(0)
135  , m_sumLatency(0)
136  , m_countLatency(0)
137 {
138 }
139 
141 {
142  PROPAGATE_ERROR_CONTINUE(shutdown());
143 }
144 
146 {
147  if (m_eventThread)
148  {
149  PROPAGATE_ERROR_CONTINUE(m_eventThread->shutdown());
150  m_eventThread.reset();
151  }
152 
153  return true;
154 }
155 
156 bool SessionPerfTracker::setSession(Argus::CaptureSession *session)
157 {
158  m_session = session;
159  return true;
160 }
161 
162 bool SessionPerfTracker::onEvent(SessionEvent event, uint64_t value)
163 {
164  if (!Dispatcher::getInstance().m_kpi)
165  return true;
166 
167  switch (event)
168  {
171  printf("PerfTracker: app initial %" PRIu64 " ms\n",
172  (PerfTracker::getInstance().appInitializedTime() -
173  PerfTracker::getInstance().appStartTime()).toMSec());
174  printf("PerfTracker %d: app intialized to task start %" PRIu64 " ms\n", m_id,
175  (m_taskStartTime - PerfTracker::getInstance().appInitializedTime()).toMSec());
176  break;
178  // captures are about to start, create the event thread which collects information on the
179  // captures received
180  if (!m_eventThread)
181  {
182  m_eventThread.reset(new EventThread(m_session, this));
183  if (!m_eventThread)
184  ORIGINATE_ERROR("Failed to allocate EventThread");
185 
186  PROPAGATE_ERROR(m_eventThread->initialize());
187  PROPAGATE_ERROR(m_eventThread->waitRunning());
188  }
189 
191  printf("PerfTracker %d: task start to issue capture %" PRIu64 " ms\n", m_id,
192  (m_issueCaptureTime - m_taskStartTime).toMSec());
193  break;
196  if (m_numberframesReceived == 0)
197  {
199  printf("PerfTracker %d: first request %" PRIu64 " ms\n", m_id,
201  printf("PerfTracker %d: total launch time %" PRIu64 " ms\n", m_id,
202  (m_firstRequestReceivedTime - PerfTracker::getInstance().appStartTime()).toMSec());
203  }
204 
206  if ((m_numberframesReceived % 30) == 2)
207  {
208  const float frameRate =
209  static_cast<float>(m_numberframesReceived - 1) *
211  printf("PerfTracker %d: frameRate %.2f frames per second at %" PRIu64 " Seconds\n",
212  m_id,
213  frameRate,
215  }
216  break;
218  // can do some stats
219  m_minLatency = (m_minLatency < value) ? m_minLatency : value;
220  m_maxLatency = (m_maxLatency < value) ? value : m_maxLatency;
221  m_sumLatency += value;
222  m_countLatency += 1;
223  if ((m_numberframesReceived % 30) == 6)
224  {
225  const uint64_t latencyAverage = (m_sumLatency + m_countLatency/2) / m_countLatency;
226  printf("PerfTracker %d: latency %" PRIu64 " ms average, min %" PRIu64
227  " max %" PRIu64 "\n",
228  m_id, latencyAverage,
229  m_minLatency,
230  m_maxLatency);
231 
232  m_countLatency = 0;
233  m_sumLatency = 0;
234  m_maxLatency = 0;
235  m_minLatency = std::numeric_limits<uint64_t>::max();
236  }
237  break;
239  {
240  const TimeValue currentTime = getCurrentTime();
241  const uint64_t currentFrameCount = value;
242  int64_t currentFrameDrop = 0;
243  // start frame drop count from 2nd frame
244  if (m_lastFrameCount > 0)
245  {
246  // currentFrameDrop can be negative when metadata comes out of order
247  currentFrameDrop = currentFrameCount - m_lastFrameCount - 1;
248  m_totalFrameDrop += currentFrameDrop;
249  }
250  if (currentFrameDrop != 0)
251  {
252  printf("PerfTracker %d: framedrop current request %" PRId64 ", total %" PRId64
253  ", Drop at %" PRIu64 " Seconds !\n",
254  m_id, currentFrameDrop,
256  (currentTime - m_firstRequestReceivedTime).toSec());
257  }
258  else
259  {
260  if ((m_numberframesReceived % 30) == 4)
261  {
262  printf("PerfTracker %d: framedrop current request %" PRId64 ", total %"
263  PRId64 "\n",
264  m_id, currentFrameDrop,
266  }
267  }
268 
269  m_lastFrameCount = currentFrameCount;
270  break;
271  }
274  // captures are about to be stopped, destroy the event thread.
275  if (m_eventThread)
276  {
277  PROPAGATE_ERROR(m_eventThread->shutdown());
278  m_eventThread.reset();
279  }
280  break;
283  printf("PerfTracker %d: flush takes %" PRIu64 " ms\n", m_id,
285  break;
288  printf("PerfTracker %d: device close takes %" PRIu64 " ms\n", m_id,
289  (m_closeDoneTime - m_flushDoneTime).toMSec());
290  printf("PerfTracker %d: total close takes %" PRIu64 " ms\n", m_id,
292  break;
293  default:
294  ORIGINATE_ERROR("Unhandled session event");
295  break;
296  }
297 
298  return true;
299 }
300 
301 }; // namespace ArgusSamples