26 if(originalFrameRate == 0.) {
27 std::cout <<
"WARNING: original FPS is 0! assuming FPS == 20!" << std::endl;
28 originalFrameRate = 20.;
30 std::chrono::milliseconds sensorDuration((
long long)(((
long long)originalNumberOfFrames * 1000LL) / originalFrameRate));
31 if(sensorDuration < imagePeriod) {
32 imagePeriod = sensorDuration;
34 auto currentPosition = (std::chrono::system_clock::now() - refTime) % imagePeriod;
36 return (std::chrono::duration_cast<std::chrono::microseconds>(currentPosition).count() * originalFrameRate) / 1000000LL;
40 refTime(
std::chrono::system_clock::now()) {};
44 std::chrono::system_clock::time_point refTime;
45 std::chrono::system_clock::duration imagePeriod = std::chrono::system_clock::duration::max();
60 return message.c_str();
67 _DummyGrabberImpl::_DummyGrabberImpl(
const std::string & _deviceName,
68 const std::string & _deviceSource,
69 zmq::context_t & _ctx,
70 const std::string & _brokerEndpoint) :
71 RocServer(_ctx, _brokerEndpoint, _deviceName),
73 deviceName(_deviceName),
74 deviceSource(_deviceSource),
81 rocsHeader(
SSTR(
"ROCS\x01", _deviceName,
".controls")),
82 rocsSocket(_ctx, ZMQ_PUB),
85 dummyFile.openFile(deviceSource);
87 if(deviceName ==
"vnir") {
89 }
else if(deviceName ==
"swir") {
91 }
else if(deviceName ==
"lwir") {
98 _DummyGrabberImpl::~_DummyGrabberImpl() {
102 int _DummyGrabberImpl::getWidth() {
106 int _DummyGrabberImpl::getHeight() {
110 int _DummyGrabberImpl::getBytesPerPixel() {
114 void _DummyGrabberImpl::startServing() {
115 enableAcquisition =
true;
116 acquisitionThread = std::thread(&_DummyGrabberImpl::acquisition,
this);
119 void _DummyGrabberImpl::stopServing() {
120 enableAcquisition =
false;
121 if(acquisitionThread.joinable()) {
122 std::cout <<
"wait for grabber thread to join" << std::endl;
123 acquisitionThread.join();
127 void _DummyGrabberImpl::acquisition() {
128 RocLogger logger(ctx,
"inproc://log",
"camserver",
SSTR(
"grabber.", deviceName));
129 rocsSocket.connect(
"inproc://log");
131 zmq::socket_t pubSocket(ctx, ZMQ_PUB);
132 for(
const auto & ep: endpoints) {
133 pubSocket.bind(ep.c_str());
135 int width = getWidth();
136 int height = getHeight();
137 int bytesPerPixel = getBytesPerPixel();
138 std::cout <<
"width: " << width <<
" height: " << height <<
" bpp: " << bytesPerPixel << std::endl;
139 int bufferCount = 256;
140 char * bufferList[bufferCount];
141 bufferUsers.resize(bufferCount);
145 for(
int i = 0; i < bufferCount; ++i) {
146 bufferList[i] =
new char[width * height * bytesPerPixel];
147 assert(bufferList[i] !=
nullptr);
148 bufferUsers[i] =
new std::atomic<int>(0);
149 assert(bufferUsers[i] !=
nullptr);
152 std::cout <<
"grab initialized" << std::endl;
154 logger.debug(
SSTR(
"grab initialized"));
157 double originalFps = dummyFile.
getFps();
158 auto t1 = std::chrono::high_resolution_clock::now();
159 auto t2 = std::chrono::high_resolution_clock::now();
161 while(enableAcquisition) {
162 statsPublisher.publishBufferLoad(openBuffers, bufferCount);
165 int currentFrame = synchronizer.
getCurrentFrame(originalFps, numFrames);
166 int currentBufferIndex = 0;
168 while(currentBufferIndex < bufferCount && *bufferUsers[currentBufferIndex] > 0) {
169 ++currentBufferIndex;
171 if(currentBufferIndex >= bufferCount) {
174 t2 = std::chrono::high_resolution_clock::now();
175 auto dt = std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1);
177 std::this_thread::sleep_for(std::chrono::microseconds(
int(1e6/fps)) - dt);
179 std::cout <<
"dt: " << dt.count() <<
" ms" << std::endl;
181 auto grabTime = std::chrono::system_clock::now();
182 t1 = std::chrono::high_resolution_clock::now();
184 uint64_t grabHighResTime = std::chrono::duration_cast<std::chrono::microseconds>(t1.time_since_epoch()).count();
185 uint64_t grabWallTime = std::chrono::duration_cast<std::chrono::microseconds>(grabTime.time_since_epoch()).count();
187 acquireBuffer(currentBufferIndex);
189 double dfTint = dummyFile.
getTint();
190 double tintFactor = 1.0;
192 tintFactor = tint / dfTint;
198 switch(bytesPerPixel) {
200 recalculateExposure<uint8_t>((uint8_t*) bufferList[currentBufferIndex],
201 (uint8_t*) dummyFile.getDataByFrame(currentFrame),
210 (uint16_t*) dummyFile.getDataByFrame(currentFrame),
219 (uint32_t*) dummyFile.getDataByFrame(currentFrame),
228 zmq::message_t header(deviceName.length());
229 memcpy(header.data(), deviceName.c_str(), deviceName.length());
230 pubSocket.send(header, ZMQ_SNDMORE);
231 zmq::message_t dimensions(3 * 4 + 2 * 8);
237 pubSocket.send(dimensions, ZMQ_SNDMORE);
238 zmq::message_t data((
char*)(bufferList[currentBufferIndex]),
239 width * height * bytesPerPixel,
241 new
std::function<
void()>(
246 pubSocket.send(data);
248 std::cout << "aquisition stopped" <<
std::endl;
250 while(totalBufferUsers > 0) {
252 std::unique_lock<std::mutex> lock(m);
253 bufferFreeNotifier.wait(lock);
255 for(
int i = 0; i < bufferCount; ++i) {
256 delete[] bufferList[i];
257 delete bufferUsers[i];
260 logger.debug(
SSTR(
"grabber worker is done"));
263 void _DummyGrabberImpl::acquireBuffer(
int bufferId) {
265 if((*bufferUsers[bufferId])++ == 0) {
267 cout << deviceName <<
" acquired buffer " << bufferId << endl;
273 void _DummyGrabberImpl::releaseBuffer(
int bufferId) {
274 if(--(*bufferUsers[bufferId]) == 0) {
276 cout << deviceName <<
" released buffer " << bufferId << endl;
280 bufferFreeNotifier.notify_all();
286 void _DummyGrabberImpl::addEndpoint(
const std::string & _endpoint) {
287 endpoints.push_back(_endpoint);
292 Json::Value _DummyGrabberImpl::call(
const std::string & name,
const Json::Value & arguments) {
293 if(name ==
"openShutter") {
294 shutterClosed =
false;
295 return Json::Value::null;
296 }
else if(name ==
"closeShutter") {
297 shutterClosed =
true;
298 return Json::Value::null;
303 Json::Value _DummyGrabberImpl::getattr(
const std::string & name) {
306 }
else if (name ==
"exposureTime") {
312 void _DummyGrabberImpl::setattr(
const std::string & name,
const Json::Value & value) {
314 fps = value.asFloat();
316 }
else if (name ==
"exposureTime") {
317 tint = value.asFloat();
325 void _DummyGrabberImpl::sendStatus() {
326 zmq::message_t msgHdr(rocsHeader.length());
327 memcpy((
char*)msgHdr.data(), rocsHeader.c_str(), rocsHeader.length());
328 rocsSocket.send(msgHdr, ZMQ_SNDMORE);
330 Json::FastWriter writer;
333 root[
"shutter"] =
"close";
335 root[
"shutter"] =
"open";
337 root[
"exposureTime"] = tint;
339 std::string data = writer.write(root);
340 zmq::message_t msgData(data.length());
341 memcpy((
char *)msgData.data(), data.c_str(), data.length());
342 rocsSocket.send(msgData);
352 int size = width * height;
354 for(
int i = 0; i < size; ++i) {
355 temp = source[i] - dark;
359 temp = (temp * factor) + dark;
void insertNetworkUInt32(void *buffer, uint32_t value)
void insertNetworkUInt64(void *buffer, uint64_t value)
unsigned long long getNumFrames() const
std::string SSTR(Args &&...components)
Creates a temporary string stream for string concatenation.
int getCurrentFrame(double originalFrameRate, int originalNumberOfFrames)
void recalculateExposure(T *target, T *source, int width, int height, double factor, T dark, T max)
DummyException(const std::string &_message)
unsigned long long getHeight() const
static DummyGrabberSynchronizer & getInstance()
unsigned long long getWidth() const
void cbWrapper(void *data, void *hint)
unsigned int getBytesPerPixel() const
virtual const char * what() const