1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25#include <array>
26#include <cmath>
27#include <cstdint>
28#include <cstring>
29
30
31#include <boost/accumulators/accumulators.hpp>
32#include <boost/accumulators/statistics/count.hpp>
33#include <boost/accumulators/statistics/extended_p_square.hpp>
34#include <boost/accumulators/statistics/max.hpp>
35#include <boost/accumulators/statistics/mean.hpp>
36#include <boost/accumulators/statistics/min.hpp>
37#include <boost/accumulators/statistics/stats.hpp>
38#include <boost/accumulators/statistics/sum.hpp>
39#include <boost/accumulators/statistics/variance.hpp>
40
41
49
50
51
52
53
60
61
62
63
64struct Stats
65{
66
67 static constexpr std::array<double, 4> PROB = {{ 0.5, 0.68, 0.95, 0.997 }};
68 using Accumulator = boost::accumulators::accumulator_set<double, boost::accumulators::stats<
69 boost::accumulators::tag::count,
70 boost::accumulators::tag::mean,
71 boost::accumulators::tag::min,
72 boost::accumulators::tag::max,
73 boost::accumulators::tag::sum,
74 boost::accumulators::tag::variance,
75 boost::accumulators::tag::extended_p_square>>;
76 Accumulator lat { boost::accumulators::extended_p_square_probabilities = PROB };
77 Accumulator size { boost::accumulators::extended_p_square_probabilities = PROB };
78 Accumulator exp { boost::accumulators::extended_p_square_probabilities = PROB };
79 Accumulator dec { boost::accumulators::extended_p_square_probabilities = PROB };
80
81};
82
83
84
85int main(int argc, char** argv)
86{
87#ifndef NDEBUG
89#endif
90
91
92
93
94
95
96
97
98 if (argc != 5) {
99 ERROR(
"Missing arguments!");
101 "Usage: camera_streaming <sensor> <cam> <type> <rate>\n"
102 "Where: <sensor> is the sensor's hostname or IP address, <cam> is CAM1 or CAM2, <type> is\n"
103 "HIRES_VID, LORES_VID, HIRES_IMG or LORES_IMG, and <rate> is the throttling rate (must be\n"
104 "1 for encoded video)\n"
105 "Examples:\n"
106 " camera_streaming 10.0.2.1 CAM1 HIRES_VID 1\n"
107 " camera_streaming 10.0.2.1 CAM1 HIRES_IMG 10\n"
108 " timeout -s SIGINT 60 camera_streaming ...");
109 return EXIT_FAILURE;
110 }
111
112#if 0
114#else
116#endif
117
118 const std::string sensor = argv[1];
121 int rate = 0;
123
125
126
128 if (!stream) {
129 return EXIT_FAILURE;
130 }
131
132
133 if (!stream->Connect()) {
134 return EXIT_FAILURE;
135 }
136
137
139
140
141 Stats stats;
142
143
146 std::size_t n_frames = 0;
147 char info[1000];
148 bool ok = true;
150 while (ok && !sigint.
ShouldAbort() && stream->NextFrame(data)) {
151
152
153
154
155
159 n_frames++;
160
161
162 std::size_t len =
163 std::snprintf(info, sizeof(info), "Frame %6" PRIuMAX ": %-7s %-5s %-10s %-9s %-7s %6" PRIuMAX " %s %4.1f",
167
168
169 stats.size((
double)data.
data_.size() / 1024.0);
170 stats.exp((double)t_expo.GetSec() * 1e3);
171
172
174 const double lat = (t_recv - t_data).GetSec() * 1e3;
175 len += std::snprintf(&info[len], sizeof(info) - len, " -- latency: %+5.1f", lat);
176 stats.lat(lat);
177 }
178
179
181
184 }
185 if (decoder) {
187 const auto img = decoder->DecodeFrame(data.
data_);
188 if (!img) {
189 ok = false;
190 break;
191 }
192
193
194
195
196
197
198 const auto lat = tt.
Toc().
GetSec() * 1e3;
199 len += std::snprintf(&info[len], sizeof(info) - len, " -- decode: %+5.1f", lat);
200 stats.dec(lat);
201 }
202 }
203
205 }
207 const auto t_str = (t_end - t_start).GetSec();
208
209 stream->Disconnect();
210
211
212 NOTICE(
"Streamed %s %s %s %d for %.0fs (%" PRIuMAX
" frames)", sensor.c_str(),
CamIdToStr(cam_id),
213 CamDataTypeToStr(type), rate, t_str, boost::accumulators::count(stats.size));
214 if (boost::accumulators::count(stats.lat) > 10) {
215 INFO(
"Latency receiving data [ms]: mean %4.1f (std %4.1f) min/0.5/0.68/0.95/0.997/max %4.1f %4.1f %4.1f %4.1f %4.1f %4.1f",
216 boost::accumulators::mean(stats.lat), std::sqrt(boost::accumulators::variance(stats.lat)),
217 boost::accumulators::min(stats.lat), boost::accumulators::extended_p_square(stats.lat)[0],
218 boost::accumulators::extended_p_square(stats.lat)[1], boost::accumulators::extended_p_square(stats.lat)[2],
219 boost::accumulators::extended_p_square(stats.lat)[3], boost::accumulators::max(stats.lat));
220 }
221 if (boost::accumulators::count(stats.dec) > 10) {
222 INFO(
"Latency decoding video [ms]: mean %4.1f (std %4.1f) min/0.5/0.68/0.95/0.997/max %4.1f %4.1f %4.1f %4.1f %4.1f %4.1f",
223 boost::accumulators::mean(stats.dec), std::sqrt(boost::accumulators::variance(stats.dec)),
224 boost::accumulators::min(stats.dec), boost::accumulators::extended_p_square(stats.dec)[0],
225 boost::accumulators::extended_p_square(stats.dec)[1], boost::accumulators::extended_p_square(stats.dec)[2],
226 boost::accumulators::extended_p_square(stats.dec)[3], boost::accumulators::max(stats.dec));
227 }
228 if (boost::accumulators::count(stats.exp) > 10) {
229 INFO(
"Exposure duration [ms]: mean %4.1f (std %4.1f) min/0.5/0.68/0.95/0.997/max %4.1f %4.1f %4.1f %4.1f %4.1f %4.1f",
230 boost::accumulators::mean(stats.exp), std::sqrt(boost::accumulators::variance(stats.exp)),
231 boost::accumulators::min(stats.exp), boost::accumulators::extended_p_square(stats.exp)[0],
232 boost::accumulators::extended_p_square(stats.exp)[1], boost::accumulators::extended_p_square(stats.exp)[2],
233 boost::accumulators::extended_p_square(stats.exp)[3], boost::accumulators::max(stats.exp));
234 }
235 if ((boost::accumulators::count(stats.size) > 10) && (t_str > 1.0)) {
236 INFO(
"Data size per frame [KiB]: mean %4.0f (std %4.0f) min/0.5/0.68/0.95/0.997/max %4.0f %4.0f %4.0f %4.0f %4.0f %4.0f",
237 boost::accumulators::mean(stats.size), std::sqrt(boost::accumulators::variance(stats.size)),
238 boost::accumulators::min(stats.size), boost::accumulators::extended_p_square(stats.size)[0],
239 boost::accumulators::extended_p_square(stats.size)[1],
240 boost::accumulators::extended_p_square(stats.size)[2],
241 boost::accumulators::extended_p_square(stats.size)[3], boost::accumulators::max(stats.size));
242 const double avg = boost::accumulators::sum(stats.size) / t_str;
243
244 INFO(
"Average data rate [KiB/s]: %.0f (~%.1f%%GigE)", avg, avg / 120500.0 * 1e2);
245 }
246
247 return ok ? EXIT_SUCCESS : EXIT_FAILURE;
248}
249
250
Fixposition SDK: Utilities for apps.
Fixposition SDK: Camera types and utilities.
Helper to catch SIGINT (CTRL-c).
bool ShouldAbort()
Check if signal was raised and we should abort.
Helper to print a strack trace on SIGSEGV and SIGABRT.
static Duration FromNSec(const int64_t nsec)
Make Duration from nanoseconds.
double GetSec(const int prec=9) const
Get duration as seconds.
Helper to measure wallclock time.
Duration Toc(const bool reset=false)
Get elapsed wallclock time.
static Time FromPosixNs(const uint64_t posix_ns)
From POSIX nanoseconds (POSIX).
static Time FromClockRealtime()
From system clock current (now) system time (CLOCK_REALTIME).
Fixposition SDK: Logging.
#define ERROR(...)
Print a error message.
#define NOTICE(...)
Print a notice message.
#define INFO(...)
Print a info message.
Camera types and utilities.
const char * CamIdToStr(const CamId camid)
Stringify camera ID enum.
const char * CamDataFmtToStr(const CamDataFmt fmt)
Stringify camera data format enum.
CamId CamIdFromStrOr(const char *str, const CamId def)
Convert camera ID string to enum.
@ UNSPECIFIED
Unspecified.
const char * CamDataTypeToStr(const CamDataType type)
Stringify camera data type enum.
CamDataType
Camera data type (type of data).
@ UNSPECIFIED
Unspecified.
const char * CamDataFrmToStr(const CamDataFrm frm)
Stringify camera data frame type enum.
@ H265_NAL
H.265 NAL (HEVC) (video/hevc).
@ I_FRAME
I-frame (= Horizon camsys MC_H26[45]_NALU_TYPE_I).
CamStreamPtr CreateCamStream(const CamStreamParams ¶ms)
Create a camera stream instance.
CamDataType CamDataTypeFromStrOr(const char *str, const CamDataType def)
Convert camera data type string to enum.
LoggingParams LoggingSetParams(const LoggingParams ¶ms)
Configure logging.
@ RELATIVE
Relative timestamps (since first logging message, sssss.sss format).
@ TRACE
[7/debug] Extra debugging, only compiled-in in non-Release builds
@ INFO
[6/info] Interesting stuff, the default level (for apps)
@ AUTO
Automatic (default), use colours if stderr is an interactive terminal.
bool StrToValue(const std::string &str, int8_t &value)
Convert string to value (int8_t).
@ RGB24
Packed RGB 8:8:8, 24bpp, RGBRGB... (= FFmpeg AV_PIX_FMT_RGB24).
@ H265
H.265 High Efficiency Video Coding (HEVC).
std::unique_ptr< VideoFrameDecoder > VideoFrameDecoderPtr
Pointer to a VideoFrameDecoder instance, see CreateVideoFrameDecoder().
VideoFrameDecoderPtr CreateVideoFrameDecoder(const VideoDecoderParams ¶ms)
Create a video frame decoder.
Fixposition SDK: String utilities.
Camera data from CamStream (or from FPL, see fpl::CamData).
uint64_t ts_
Camera image time (middle of exposure) [CLOCK_REALTIME ns] (0 = invalid).
CamId cam_id_
= meta_.cam_id_ as enum (if value in range)
uint32_t dt_
Exposure time (duration) [ns] (0 = not available).
CamDataFmt fmt_
= meta_.fmt_ as enum (if value in range)
CamDataType type_
= meta_.type_ as enum (if value in range)
bool valid_
Data valid, successfully extracted from message.
std::vector< uint8_t > data_
Image/frame data, contents depends on fmt_ etc.
CamDataFrm frm_
= meta_.frm_ as enum (if value in range)
Fixposition SDK: Time utilities.
Fixposition SDK: Common types and type helpers.
Fixposition SDK: Video frame decoding.