libvisiontransfer  6.1.0
imageprotocol.cpp
1 /*******************************************************************************
2  * Copyright (c) 2018 Nerian Vision GmbH
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to deal
6  * in the Software without restriction, including without limitation the rights
7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *******************************************************************************/
14 
15 #include <cstring>
16 #include <iostream>
17 #include <limits>
18 #include <vector>
19 #include <memory>
20 #include <algorithm>
21 #include "visiontransfer/imageprotocol.h"
22 #include "visiontransfer/alignedallocator.h"
23 #include "visiontransfer/datablockprotocol.h"
24 #include "visiontransfer/exceptions.h"
25 #include "visiontransfer/bitconversions.h"
26 #include "visiontransfer/internalinformation.h"
27 
28 // Network headers
29 #ifdef _WIN32
30  #ifndef NOMINMAX
31  #define NOMINMAX
32  #endif
33  #include <winsock2.h>
34 #else
35  #include <arpa/inet.h>
36 #endif
37 
38 using namespace std;
39 
40 /*************** Pimpl class containing all private members ***********/
41 
42 class ImageProtocol::Pimpl {
43 public:
44  Pimpl(bool server, ProtocolType protType, int maxUdpPacketSize);
45 
46  // Redeclaration of public members
47  void setTransferImagePair(const ImagePair& imagePair);
48  void setRawTransferData(const ImagePair& metaData, unsigned char* rawData,
49  int firstTileWidth = 0, int secondTileWidth = 0, int validBytes = 0x7FFFFFFF);
50  void setRawValidBytes(int validBytes);
51  const unsigned char* getTransferMessage(int& length);
52  bool transferComplete();
53  void resetTransfer();
54  bool getReceivedImagePair(ImagePair& imagePair);
55  bool getPartiallyReceivedImagePair(ImagePair& imagePair,
56  int& validRows, bool& complete);
57  bool imagesReceived() const;
58 
59  unsigned char* getNextReceiveBuffer(int& maxLength);
60 
61  void processReceivedMessage(int length);
62  int getProspectiveMessageSize();
63  int getNumDroppedFrames() const;
64  void resetReception();
65  bool isConnected() const;
66  const unsigned char* getNextControlMessage(int& length);
67  bool newClientConnected();
68 
69 private:
70  unsigned short MAGIC_SEQUECE = 0x3D15;
71 
72  // Header data transferred in the first packet
73 #pragma pack(push,1)
74  struct HeaderData{
75  unsigned short magic;
76 
77  unsigned char protocolVersion;
78  unsigned char isRawImagePair;
79 
80  unsigned short width;
81  unsigned short height;
82 
83  unsigned short firstTileWidth;
84  unsigned short secondTileWidth;
85 
86  unsigned char format0;
87  unsigned char format1;
88  unsigned char minDisparity;
89  unsigned char maxDisparity;
90 
91  unsigned int seqNum;
92  int timeSec;
93  int timeMicrosec;
94 
95  float q[16];
96  };
97 #pragma pack(pop)
98 
99  // Underlying protocol for data transfers
100  DataBlockProtocol dataProt;
101  ProtocolType protType;
102 
103  // Transfer related variables
104  std::vector<unsigned char> headerBuffer;
105  std::vector<unsigned char> rawBuffer;
106  unsigned char* rawData;
107 
108  // Reception related variables
109  std::vector<unsigned char, AlignedAllocator<unsigned char> >decodeBuffer[2];
110  bool receiveHeaderParsed;
111  HeaderData receiveHeader;
112  int lastReceivedPayloadBytes[2];
113  bool receptionDone;
114 
115  // Copies the transmission header to the given buffer
116  void copyHeaderToBuffer(const ImagePair& imagePair, int firstTileWidth,
117  int secondTileWidth, unsigned char* buffer);
118 
119  // Decodes header information from the received data
120  void tryDecodeHeader(const unsigned char* receivedData, int receivedBytes);
121 
122  // Decodes a received image from an interleaved buffer
123  unsigned char* decodeInterleaved(int imageNumber, int receivedBytes,
124  unsigned char* data, int& validRows, int& rowStride);
125 
126  int getFrameSize(int width, int height, int firstTileWidth, int secondTileWidth,
128 
129  int getFormatBits(ImagePair::ImageFormat format, bool afterDecode);
130 
131  void decodeTiledImage(int imageNumber, int lastReceivedPayloadBytes, int receivedPayloadBytes,
132  const unsigned char* data, int firstTileStride, int secondTileStride, int& validRows,
133  ImagePair::ImageFormat format);
134 
135  void decodeRowsFromTile(int startRow, int stopRow, unsigned const char* src,
136  unsigned char* dst, int srcStride, int dstStride, int tileWidth);
137 
138  void allocateDecodeBuffer(int imageNumber);
139 };
140 
141 
142 /******************** Stubs for all public members ********************/
143 
144 ImageProtocol::ImageProtocol(bool server, ProtocolType protType, int maxUdpPacketSize)
145  : pimpl(new Pimpl(server, protType, maxUdpPacketSize)) {
146  // All initializations are done by the Pimpl class
147 }
148 
149 ImageProtocol::~ImageProtocol() {
150  delete pimpl;
151 }
152 
154  pimpl->setTransferImagePair(imagePair);
155 }
156 
158  unsigned char* imageData, int firstTileWidth, int secondTileWidth, int validBytes) {
159  pimpl->setRawTransferData(metaData, imageData, firstTileWidth, secondTileWidth, validBytes);
160 }
161 
162 void ImageProtocol::setRawValidBytes(int validBytes) {
163  pimpl->setRawValidBytes(validBytes);
164 }
165 
166 const unsigned char* ImageProtocol::getTransferMessage(int& length) {
167  return pimpl->getTransferMessage(length);
168 }
169 
171  return pimpl->transferComplete();
172 }
173 
175  pimpl->resetTransfer();
176 }
177 
179  return pimpl->getReceivedImagePair(imagePair);
180 }
181 
183  ImagePair& imagePair, int& validRows, bool& complete) {
184  return pimpl->getPartiallyReceivedImagePair(imagePair, validRows, complete);
185 }
186 
188  return pimpl->imagesReceived();
189 }
190 
191 unsigned char* ImageProtocol::getNextReceiveBuffer(int& maxLength) {
192  return pimpl->getNextReceiveBuffer(maxLength);
193 }
194 
196  pimpl->processReceivedMessage(length);
197 }
198 
200  return pimpl->getNumDroppedFrames();
201 }
202 
204  pimpl->resetReception();
205 }
206 
208  return pimpl->isConnected();
209 }
210 
211 const unsigned char* ImageProtocol::getNextControlMessage(int& length) {
212  return pimpl->getNextControlMessage(length);
213 }
214 
216  return pimpl->newClientConnected();
217 }
218 
219 /******************** Implementation in pimpl class *******************/
220 
221 ImageProtocol::Pimpl::Pimpl(bool server, ProtocolType protType, int maxUdpPacketSize)
222  :dataProt(server, (DataBlockProtocol::ProtocolType)protType,
223  maxUdpPacketSize), protType(protType), rawData(nullptr),
224  receiveHeaderParsed(false), lastReceivedPayloadBytes{0, 0},
225  receptionDone(false) {
226  headerBuffer.resize(sizeof(HeaderData) + 32);
227  memset(&headerBuffer[0], 0, sizeof(headerBuffer.size()));
228  memset(&receiveHeader, 0, sizeof(receiveHeader));
229 }
230 
231 void ImageProtocol::Pimpl::setTransferImagePair(const ImagePair& imagePair) {
232  if(imagePair.getPixelData(0) == nullptr || imagePair.getPixelData(1) == nullptr) {
233  throw ProtocolException("Image data is null pointer!");
234  }
235 
236  // Determine the size of a frame
237  int rawDataLength = getFrameSize(imagePair.getWidth(), imagePair.getHeight(), 0, 0,
238  imagePair.getPixelFormat(0), imagePair.getPixelFormat(1));
239 
240  // Set header as first piece of data
241  copyHeaderToBuffer(imagePair, 0, 0, &headerBuffer[16]);
242  dataProt.resetTransfer();
243  dataProt.setTransferHeader(&headerBuffer[16], sizeof(HeaderData), rawDataLength);
244 
245  // Perform 12 bit packed encoding if necessary
246  int bits[2] = {0, 0};
247  int rowSize[2] = {0, 0};
248  int rowStride[2] = {0, 0};
249  const unsigned char* pixelData[2] = {nullptr, nullptr};
250  std::vector<unsigned char> encodingBuffer[2];
251 
252  for(int i = 0; i<2; i++) {
253  bits[i] = getFormatBits(imagePair.getPixelFormat(i), false);
254  rowSize[i] = imagePair.getWidth()*bits[i]/8;
255 
256  if(imagePair.getPixelFormat(i) != ImagePair::FORMAT_12_BIT_MONO) {
257  pixelData[i] = imagePair.getPixelData(i);
258  rowStride[i] = imagePair.getRowStride(i);
259  } else {
260  encodingBuffer[i].resize(rowSize[i] * imagePair.getHeight());
261  BitConversions::encode12BitPacked(0, imagePair.getHeight(), imagePair.getPixelData(i),
262  &encodingBuffer[i][0], imagePair.getRowStride(i), rowSize[i], imagePair.getWidth());
263  pixelData[i] = &encodingBuffer[i][0];
264  rowStride[i] = rowSize[i];
265  }
266  }
267 
268  // Make a interleaved copy
269  rawBuffer.resize(imagePair.getWidth()*imagePair.getHeight()*(bits[0] + bits[1])/8 + sizeof(int));
270  int bufferOffset = 0;
271 
272  for(int y = 0; y<imagePair.getHeight(); y++) {
273  memcpy(&rawBuffer[bufferOffset], &pixelData[0][y*rowStride[0]], rowSize[0]);
274  bufferOffset += rowSize[0];
275 
276  memcpy(&rawBuffer[bufferOffset], &pixelData[1][y*rowStride[1]], rowSize[1]);
277  bufferOffset += rowSize[1];
278  }
279 
280  rawData = &rawBuffer[0];
281  int rawValidBytes = static_cast<int>(rawBuffer.size() - sizeof(int));
282 
283  dataProt.setTransferData(rawData, rawValidBytes);
284 }
285 
286 void ImageProtocol::Pimpl::setRawTransferData(const ImagePair& metaData, unsigned char* rawData,
287  int firstTileWidth, int secondTileWidth, int validBytes) {
288  if(rawData == nullptr) {
289  throw ProtocolException("Image data is null pointer!");
290  }
291 
292  // Determine the size of a frame
293  int rawDataLength = getFrameSize(metaData.getWidth(), metaData.getHeight(),
294  firstTileWidth, secondTileWidth, metaData.getPixelFormat(0),
295  metaData.getPixelFormat(1));
296 
297  // Set header as first piece of data
298  copyHeaderToBuffer(metaData, firstTileWidth, secondTileWidth, &headerBuffer[16]);
299  dataProt.resetTransfer();
300  dataProt.setTransferHeader(&headerBuffer[16], sizeof(HeaderData), rawDataLength);
301 
302  this->rawData = rawData;
303 
304  dataProt.setTransferData(rawData, validBytes);
305 }
306 
307 void ImageProtocol::Pimpl::setRawValidBytes(int validBytes) {
308  dataProt.setTransferValidBytes(validBytes);
309 }
310 
311 const unsigned char* ImageProtocol::Pimpl::getTransferMessage(int& length) {
312  const unsigned char* msg = dataProt.getTransferMessage(length);
313 
314  if(msg == nullptr) {
315  msg = dataProt.getTransferMessage(length);
316  }
317 
318  return msg;
319 }
320 
321 bool ImageProtocol::Pimpl::transferComplete() {
322  return dataProt.transferComplete();
323 }
324 
325 int ImageProtocol::Pimpl::getFrameSize(int width, int height, int firstTileWidth,
326  int secondTileWidth, ImagePair::ImageFormat format0,
327  ImagePair::ImageFormat format1) {
328 
329  int bits0 = getFormatBits(format0, false);
330  int bits1 = getFormatBits(format1, false);
331 
332  int effectiveWidth = firstTileWidth > 0 ? firstTileWidth + secondTileWidth : width;
333 
334  return (effectiveWidth * height * (bits0 + bits1)) /8;
335 }
336 
337 int ImageProtocol::Pimpl::getFormatBits(ImagePair::ImageFormat format, bool afterDecode) {
338  if(afterDecode) {
339  return ImagePair::getBytesPerPixel(format)*8;
340  } else {
341  switch(format) {
342  case ImagePair::FORMAT_8_BIT_MONO: return 8;
343  case ImagePair::FORMAT_12_BIT_MONO: return 12;
344  case ImagePair::FORMAT_8_BIT_RGB: return 24;
345  default: throw ProtocolException("Illegal pixel format!");
346  }
347  }
348 }
349 
350 void ImageProtocol::Pimpl::copyHeaderToBuffer(const ImagePair& imagePair,
351  int firstTileWidth, int secondTileWidth, unsigned char* buffer) {
352  HeaderData* transferHeader = reinterpret_cast<HeaderData*>(buffer);
353  memset(transferHeader, 0, sizeof(*transferHeader));
354  transferHeader->magic = htons(MAGIC_SEQUECE);
355  transferHeader->protocolVersion = InternalInformation::CURRENT_PROTOCOL_VERSION;
356  transferHeader->isRawImagePair = imagePair.isImageDisparityPair() ? 0 : 1;
357  transferHeader->width = htons(imagePair.getWidth());
358  transferHeader->height = htons(imagePair.getHeight());
359  transferHeader->firstTileWidth = htons(firstTileWidth);
360  transferHeader->secondTileWidth = htons(secondTileWidth);
361  transferHeader->format0 = static_cast<unsigned char>(imagePair.getPixelFormat(0));
362  transferHeader->format1 = static_cast<unsigned char>(imagePair.getPixelFormat(1));
363  transferHeader->seqNum = static_cast<unsigned int>(htonl(imagePair.getSequenceNumber()));
364 
365  int minDisp = 0, maxDisp = 0;
366  imagePair.getDisparityRange(minDisp, maxDisp);
367  transferHeader->minDisparity = minDisp;
368  transferHeader->maxDisparity = maxDisp;
369 
370  int timeSec = 0, timeMicrosec = 0;
371  imagePair.getTimestamp(timeSec, timeMicrosec);
372  transferHeader->timeSec = static_cast<int>(htonl(static_cast<unsigned int>(timeSec)));
373  transferHeader->timeMicrosec = static_cast<int>(htonl(static_cast<unsigned int>(timeMicrosec)));
374 
375  if(imagePair.getQMatrix() != nullptr) {
376  memcpy(transferHeader->q, imagePair.getQMatrix(), sizeof(float)*16);
377  }
378 }
379 
380 void ImageProtocol::Pimpl::resetTransfer() {
381  dataProt.resetTransfer();
382 }
383 
384 unsigned char* ImageProtocol::Pimpl::getNextReceiveBuffer(int& maxLength) {
385  maxLength = dataProt.getMaxReceptionSize();
386  return dataProt.getNextReceiveBuffer(maxLength);
387 }
388 
389 void ImageProtocol::Pimpl::processReceivedMessage(int length) {
390  receptionDone = false;
391 
392  // Add the received message
393  dataProt.processReceivedMessage(length, receptionDone);
394 
395  int receivedBytes = 0;
396  dataProt.getReceivedData(receivedBytes);
397 
398  // Immediately try to decode the header
399  if(!receiveHeaderParsed) {
400  int headerLen = 0;
401  unsigned char* headerData = dataProt.getReceivedHeader(headerLen);
402  if(headerData != nullptr) {
403  tryDecodeHeader(headerData, headerLen);
404  }
405  }
406 }
407 
408 void ImageProtocol::Pimpl::tryDecodeHeader(const
409 unsigned char* receivedData, int receivedBytes) {
410  if(receivedBytes >= static_cast<int>(sizeof(HeaderData))) {
411  receiveHeader = *reinterpret_cast<const HeaderData*>(receivedData);
412  if(receiveHeader.magic != htons(MAGIC_SEQUECE)) {
413  // Let's not call this an error. Perhaps it's just not a header
414  // packet
415  return;
416  }
417 
418  if(receiveHeader.protocolVersion > InternalInformation::CURRENT_PROTOCOL_VERSION ||
419  receiveHeader.protocolVersion < 4) {
420  throw ProtocolException("Protocol version mismatch!");
421  }
422 
423  // Convert byte order
424  receiveHeader.width = ntohs(receiveHeader.width);
425  receiveHeader.height = ntohs(receiveHeader.height);
426  receiveHeader.firstTileWidth = ntohs(receiveHeader.firstTileWidth);
427  receiveHeader.secondTileWidth = ntohs(receiveHeader.secondTileWidth);
428  receiveHeader.timeSec = static_cast<int>(
429  htonl(static_cast<unsigned int>(receiveHeader.timeSec)));
430  receiveHeader.timeMicrosec = static_cast<int>(
431  htonl(static_cast<unsigned int>(receiveHeader.timeMicrosec)));
432  receiveHeader.seqNum = htonl(receiveHeader.seqNum);
433 
434  receiveHeaderParsed = true;
435  }
436 }
437 
438 bool ImageProtocol::Pimpl::imagesReceived() const {
439  return receptionDone && receiveHeaderParsed;
440 }
441 
442 bool ImageProtocol::Pimpl::getReceivedImagePair(ImagePair& imagePair) {
443  bool complete = false;
444  int validRows;
445  bool ok = getPartiallyReceivedImagePair(imagePair, validRows, complete);
446 
447  return (ok && complete);
448 }
449 
450 bool ImageProtocol::Pimpl::getPartiallyReceivedImagePair(ImagePair& imagePair, int& validRows, bool& complete) {
451  imagePair.setWidth(0);
452  imagePair.setHeight(0);
453 
454  complete = false;
455 
456  if(!receiveHeaderParsed) {
457  // We haven't even received the image header yet
458  return false;
459  } else {
460  // We received at least some pixel data
461  int receivedBytes = 0;
462  unsigned char* data = dataProt.getReceivedData(receivedBytes);
463  imagePair.setImageDisparityPair(receiveHeader.isRawImagePair == 0);
464 
465  validRows = 0;
466  imagePair.setWidth(receiveHeader.width);
467  imagePair.setHeight(receiveHeader.height);
468  imagePair.setPixelFormat(0, static_cast<ImagePair::ImageFormat>(receiveHeader.format0));
469  imagePair.setPixelFormat(1, static_cast<ImagePair::ImageFormat>(receiveHeader.format1));
470 
471  int rowStride0 = 0, rowStride1 = 0;
472  int validRows0 = 0, validRows1 = 0;
473  unsigned char* pixel0 = decodeInterleaved(0, receivedBytes, data, validRows0, rowStride0);
474  unsigned char* pixel1 = decodeInterleaved(1, receivedBytes, data, validRows1, rowStride1);
475 
476  imagePair.setRowStride(0, rowStride0);
477  imagePair.setRowStride(1, rowStride1);
478  imagePair.setPixelData(0, pixel0);
479  imagePair.setPixelData(1, pixel1);
480  imagePair.setQMatrix(receiveHeader.q);
481 
482  imagePair.setSequenceNumber(receiveHeader.seqNum);
483  imagePair.setTimestamp(receiveHeader.timeSec, receiveHeader.timeMicrosec);
484  imagePair.setDisparityRange(receiveHeader.minDisparity, receiveHeader.maxDisparity);
485 
486  validRows = min(validRows0, validRows1);
487 
488  if(validRows == receiveHeader.height || receptionDone) {
489  complete = true;
490  resetReception();
491  }
492 
493  return true;
494  }
495 }
496 
497 unsigned char* ImageProtocol::Pimpl::decodeInterleaved(int imageNumber, int receivedBytes,
498  unsigned char* data, int& validRows, int& rowStride) {
499  ImagePair::ImageFormat format = static_cast<ImagePair::ImageFormat>(
500  imageNumber == 0 ? receiveHeader.format0 : receiveHeader.format1);
501  int bits0 = getFormatBits(static_cast<ImagePair::ImageFormat>(receiveHeader.format0), false);
502  int bits1 = getFormatBits(static_cast<ImagePair::ImageFormat>(receiveHeader.format1), false);
503 
504  unsigned char* ret = nullptr;
505 
506  if(receiveHeader.secondTileWidth == 0) {
507  int bufferOffset = imageNumber*receiveHeader.width * bits0/8;
508  int bufferRowStride = receiveHeader.width*(bits0 + bits1) / 8;
509 
510  if(format == ImagePair::FORMAT_8_BIT_MONO || format == ImagePair::FORMAT_8_BIT_RGB) {
511  // No decoding is necessary. We can just pass through the
512  // data pointer
513  ret = &data[bufferOffset];
514  rowStride = bufferRowStride;
515  validRows = receivedBytes / bufferRowStride;
516  } else {
517  // Perform 12-bit => 16 bit decoding
518  allocateDecodeBuffer(imageNumber);
519  validRows = receivedBytes / bufferRowStride;
520  rowStride = 2*receiveHeader.width;
521  int lastRow = lastReceivedPayloadBytes[imageNumber] / bufferRowStride;
522 
523  BitConversions::decode12BitPacked(lastRow, validRows, &data[bufferOffset],
524  &decodeBuffer[imageNumber][0], bufferRowStride, rowStride, receiveHeader.width);
525 
526  ret = &decodeBuffer[imageNumber][0];
527  }
528  } else {
529  // Decode the tiled transfer
530  decodeTiledImage(imageNumber,
531  lastReceivedPayloadBytes[imageNumber], receivedBytes,
532  data, receiveHeader.firstTileWidth * (bits0 + bits1) / 8,
533  receiveHeader.secondTileWidth * (bits0 + bits1) / 8,
534  validRows, format);
535  ret = &decodeBuffer[imageNumber][0];
536  rowStride = receiveHeader.width*getFormatBits(
537  static_cast<ImagePair::ImageFormat>(format), true)/8;
538  }
539 
540  lastReceivedPayloadBytes[imageNumber] = receivedBytes;
541  return ret;
542 }
543 
544 void ImageProtocol::Pimpl::allocateDecodeBuffer(int imageNumber) {
545  ImagePair::ImageFormat format = static_cast<ImagePair::ImageFormat>(
546  imageNumber == 0 ? receiveHeader.format0 : receiveHeader.format1);
547  int bytesPerPixel = getFormatBits(format, true);
548  int bufferSize = receiveHeader.width * receiveHeader.height * bytesPerPixel;
549 
550  if(decodeBuffer[imageNumber].size() != static_cast<unsigned int>(bufferSize)) {
551  decodeBuffer[imageNumber].resize(bufferSize);
552  }
553 }
554 
555 void ImageProtocol::Pimpl::decodeTiledImage(int imageNumber, int lastReceivedPayloadBytes, int receivedPayloadBytes,
556  const unsigned char* data, int firstTileStride, int secondTileStride, int& validRows,
557  ImagePair::ImageFormat format) {
558 
559  // Allocate a decoding buffer
560  allocateDecodeBuffer(imageNumber);
561 
562  // Get beginning and end of first tile
563  int startFirstTile = lastReceivedPayloadBytes / firstTileStride;
564  int stopFirstTile = std::min(receivedPayloadBytes / firstTileStride,
565  static_cast<int>(receiveHeader.height));
566 
567  // Get beginning and end of second tile
568  int secondTileBytes = receivedPayloadBytes - (receiveHeader.height*firstTileStride);
569  int lastSecondTileBytes = lastReceivedPayloadBytes - (receiveHeader.height*firstTileStride);
570  int startSecondTile = std::max(0, lastSecondTileBytes / secondTileStride);
571  int stopSecondTile = std::max(0, secondTileBytes / secondTileStride);
572  int firstTileOffset = imageNumber * getFormatBits(
573  static_cast<ImagePair::ImageFormat>(receiveHeader.format0), false) * receiveHeader.firstTileWidth / 8;
574 
575  // Decode first tile
576  if(format == ImagePair::FORMAT_12_BIT_MONO) {
577  BitConversions::decode12BitPacked(startFirstTile, stopFirstTile, &data[firstTileOffset], &decodeBuffer[imageNumber][0],
578  firstTileStride, 2*receiveHeader.width, receiveHeader.firstTileWidth);
579  } else {
580  decodeRowsFromTile(startFirstTile, stopFirstTile, &data[firstTileOffset],
581  &decodeBuffer[imageNumber][0], firstTileStride, receiveHeader.width,
582  receiveHeader.firstTileWidth);
583  }
584 
585  // Decode second tile
586  int secondTileOffset = receiveHeader.height*firstTileStride +
587  imageNumber * getFormatBits(static_cast<ImagePair::ImageFormat>(receiveHeader.format0), false) * receiveHeader.secondTileWidth / 8;
588 
589  if(format == ImagePair::FORMAT_12_BIT_MONO) {
590  BitConversions::decode12BitPacked(startSecondTile, stopSecondTile,
591  &data[secondTileOffset], &decodeBuffer[imageNumber][2*receiveHeader.firstTileWidth],
592  secondTileStride, 2*receiveHeader.width, receiveHeader.secondTileWidth);
593  } else {
594  decodeRowsFromTile(startSecondTile, stopSecondTile, &data[secondTileOffset],
595  &decodeBuffer[imageNumber][receiveHeader.firstTileWidth],
596  secondTileStride, receiveHeader.width, receiveHeader.secondTileWidth);
597  }
598 
599  validRows = stopSecondTile;
600 }
601 
602 void ImageProtocol::Pimpl::decodeRowsFromTile(int startRow, int stopRow, unsigned const char* src,
603  unsigned char* dst, int srcStride, int dstStride, int tileWidth) {
604  for(int y = startRow; y < stopRow; y++) {
605  memcpy(&dst[y*dstStride], &src[y*srcStride], tileWidth);
606  }
607 }
608 
609 void ImageProtocol::Pimpl::resetReception() {
610  receiveHeaderParsed = false;
611  lastReceivedPayloadBytes[0] = 0;
612  lastReceivedPayloadBytes[1] = 0;
613  dataProt.resetReception(false);
614  receptionDone = false;
615 }
616 
617 bool ImageProtocol::Pimpl::isConnected() const {
618  return dataProt.isConnected();
619 }
620 
621 const unsigned char* ImageProtocol::Pimpl::getNextControlMessage(int& length) {
622  return dataProt.getNextControlMessage(length);
623 }
624 
625 bool ImageProtocol::Pimpl::newClientConnected() {
626  return dataProt.newClientConnected();
627 }
628 
629 int ImageProtocol::Pimpl::getNumDroppedFrames() const {
630  return dataProt.getDroppedReceptions();
631 }
void setTimestamp(int seconds, int microsec)
Sets the time at which this image pair has been captured.
Definition: imagepair.h:145
void setHeight(int h)
Sets a new width for both images.
Definition: imagepair.h:77
Exception class that is used for all protocol exceptions.
Definition: exceptions.h:23
8-bit greyscale format
Definition: imagepair.h:38
unsigned char * getNextReceiveBuffer(int &maxLength)
Returns the buffer for receiving the next network message.
void setSequenceNumber(unsigned int num)
Sets the sequence number for this image pair.
Definition: imagepair.h:134
int getHeight() const
Returns the height of each image.
Definition: imagepair.h:178
int getNumDroppedFrames() const
Returns the number of frames that have been dropped since connecting to the current remote host...
void setPixelFormat(int imageNumber, ImageFormat format)
Sets the pixel format for the given image.
Definition: imagepair.h:98
bool getReceivedImagePair(ImagePair &imagePair)
Returns a received image when complete.
void resetTransfer()
Aborts the transmission of the current transfer and performs a reset of the internal state...
int getRowStride(int imageNumber) const
Returns the row stride for the pixel data of one image.
Definition: imagepair.h:186
ImageFormat getPixelFormat(int imageNumber) const
Returns the pixel format for the given image.
Definition: imagepair.h:197
bool transferComplete()
Returns true if the current transfer has been completed.
ImageProtocol(bool server, ProtocolType protType, int maxUdpPacketSize=1472)
Creates a new instance for decoding / encoding network messages for the given network protocol...
unsigned char * getPixelData(int imageNumber) const
Returns the pixel data for the given image.
Definition: imagepair.h:208
A protocol for transmitting large blocks of data over a network.
bool newClientConnected()
Returns true if the last message has established a new connection from a client.
void setDisparityRange(int minimum, int maximum)
Sets the value range for the disparity map contained in this image pair.
Definition: imagepair.h:157
void setWidth(int w)
Sets a new width for both images.
Definition: imagepair.h:72
void setQMatrix(const float *q)
Sets the pointer to the disparity-to-depth mapping matrix q.
Definition: imagepair.h:127
void setRowStride(int imageNumber, int stride)
Sets a new row stride for the pixel data of one image.
Definition: imagepair.h:86
unsigned int getSequenceNumber() const
Returns the sequence number for this image pair.
Definition: imagepair.h:223
8-bit RGB format
Definition: imagepair.h:41
void setTransferImagePair(const ImagePair &imagePair)
Sets a new image that will be transfer.
void setRawValidBytes(int validBytes)
Updates the number of valid bytes in a partial raw transfer.
void setPixelData(int imageNumber, unsigned char *pixelData)
Sets the pixel data for the given image.
Definition: imagepair.h:116
void getDisparityRange(int &minimum, int &maximum) const
Gets the value range for the disparity map contained in this image pair. If the image pair does not c...
Definition: imagepair.h:245
ProtocolType
Supported network protocols.
Definition: imageprotocol.h:39
const unsigned char * getNextControlMessage(int &length)
If a control message is pending to be transmitted then the message data will be returned by this meth...
void processReceivedMessage(int length)
Handles a received network message.
void resetReception()
Aborts the reception of the current image transfer and resets the internal state. ...
bool isConnected() const
Returns true if a remote connection is established.
int getWidth() const
Returns the width of each image.
Definition: imagepair.h:173
A set of two images, which are usually the left camera image and the disparity map.
Definition: imagepair.h:31
void getTimestamp(int &seconds, int &microsec) const
Returns the time at which this image pair has been captured.
Definition: imagepair.h:232
const unsigned char * getTransferMessage(int &length)
Gets the next network message for the current transfer.
void setRawTransferData(const ImagePair &metaData, unsigned char *rawData, int firstTileWidth=0, int secondTileWidth=0, int validBytes=0x7FFFFFFF)
Sets the already pre-formatted image data for the next transfer.
const float * getQMatrix() const
Returns a pointer to the disparity-to-depth mapping matrix q.
Definition: imagepair.h:216
bool isImageDisparityPair() const
Returns true if this is a left camera image and disparity map pair.
Definition: imagepair.h:262
void setImageDisparityPair(bool dispPair)
Sets whether this is a left camera image and disparity map pair, or two raw camera images...
Definition: imagepair.h:166
bool imagesReceived() const
Returns true if the images of the current transfer have been received.
ImageFormat
Image formats that can be transferred.
Definition: imagepair.h:36
bool getPartiallyReceivedImagePair(ImagePair &imagePair, int &validRows, bool &complete)
Returns a partially received image.
int getBytesPerPixel(int imageNumber) const
Returns the number of bytes that are required to store one image pixel.
Definition: imagepair.h:277
Nerian Vision Technologies