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