SenShaMart/demo/camera_client/dependencies/libvisiontransfer/visiontransfer/imageprotocol.h
2023-07-13 11:32:02 +10:00

259 lines
9.5 KiB
C++

/*******************************************************************************
* Copyright (c) 2021 Nerian Vision GmbH
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*******************************************************************************/
#ifndef VISIONTRANSFER_IMAGEPROTOCOL_H
#define VISIONTRANSFER_IMAGEPROTOCOL_H
#include "visiontransfer/common.h"
#include "visiontransfer/imageset.h"
#include <vector>
namespace visiontransfer {
/**
* \brief A lightweight protocol for transferring image sets.
*
* Two images are transferred together as a set. These are usually the left
* and right image of a stereo camera, or the left image and a disparity map.
*
* The images are 8- or 12-bit monochrome, or 8-bit RGB color. For simplicity,
* 12-bit images are inflated to 16-bit by introducing additional padding
* bits. Both images must always have the same image size.
*
* When receiving, the class takes in an image set and chops it down to several
* network messages. When sending, the class takes a set of messages and
* assembles them into an image set. We have to differentiate between TCP and
* UDP in both cases.
*/
class VT_EXPORT ImageProtocol {
public:
/// Supported network protocols
enum ProtocolType {
/// The connection oriented TCP transport protocol
PROTOCOL_TCP,
/// The connection-less UDP transport protocol
PROTOCOL_UDP
};
/**
* \brief Creates a new instance for decoding / encoding network messages
* for the given network protocol.
*
* \param server If set to true, this object will be a communication server.
* \param maxUdpPacketSize Maximum allowed size of a UDP packet when sending data.
*/
ImageProtocol(bool server, ProtocolType protType, int maxUdpPacketSize = 1472);
~ImageProtocol();
/**
* \brief Sets a new image that will be transfer.
*
* \param imageSet The image set that shall be transmitted.
*
* After setting the transfer image, subsequent calls to
* getTransferMessage() can be made for obtaining the encoded
* network messages.
*/
void setTransferImageSet(const ImageSet& imageSet);
/**
* \brief Sets the already pre-formatted image data for the next transfer.
*
* \param metaData ImageSet object containing all the meta data but no
* pixel data.
* \param rawData Pre-formatted data for this transfer.
* \param firstTileWidth If not 0, specifies the width of the first tile in
* a tiled transfer.
* \param middleTilesWidth If not 0, specifies the width of the tiles between
the first and the last tile in a tiled transfer.
* \param lastTileWidth If not 0, specifies the width of the last tile in
* a tiled transfer.
* \param validBytes The number of bytes that are valid in \c rawData.
*
* This method is a more efficient alternative to setTransferImage(). In this case
* the image data already has to be pre-formatted in the format of
* the image protocol, which means row-wise interleaving both images.
* For 12-bit images, the pixel data must be packed in LSB order.
*
* The pixel data contained in \c metaData is ignored, while all
* other data is transmitted. The actual pixel data must be encoded in
* \c rawData.
*
* Parts of \c rawData will be overwritten. There must be at least 4 additional
* allocated bytes after the pixel data in \c rawData.
*
* If \c validBytes is set to a value smaller than the total transfer
* size, only a partial transfer is performed. Subsequent calls to
* setRawValidBytes() are then necessary.
*/
void setRawTransferData(const ImageSet& metaData, const std::vector<unsigned char*>& imageData,
int firstTileWidth = 0, int middleTilesWidth = 0, int lastTileWidth = 0, int validBytes = 0x7FFFFFFF);
/**
* \brief Updates the number of valid bytes in a partial raw transfer.
*
* \param validBytes The number of already valid bytes in the previously
* set raw data pointer.
*
* This method has to be called whenever new data is available in a raw
* transfer. \see setRawTransferData()
*/
void setRawValidBytes(const std::vector<int>& validBytes);
/**
* \brief Gets the next network message for the current transfer.
*
* \param length The length of the network message.
* \return Pointer to the network message data.
*
* If the transfer has already been completed, a null pointer is returned.
*/
const unsigned char* getTransferMessage(int& length);
/**
* \brief Returns true if the current transfer has been completed.
*/
bool transferComplete();
/**
* \brief Aborts the transmission of the current transfer and performs a
* reset of the internal state.
*/
void resetTransfer();
/**
* \brief Returns a received image when complete.
*
* \param imageSet Will be set to the received image set.
* \return Returns true if a new image set has been received. Otherwise
* false.
*
* After obtaining a received image set, reception is reset and
* subsequent calls to getReceivedImageSet() or imagesReceived()
* will return false.
*
* Please note that the received image data is only valid until processing
* the first network message of the next image transfer.
*/
bool getReceivedImageSet(ImageSet& imageSet);
/**
* \brief Returns a partially received image.
*
* \param imageSet Will be set to the partially received image set.
* \param validRows The number of valid image rows in the partially received
image set.
* \param complete True if the image set has been fully received.
* \return Returns true if a full or partial image have been received.
* Otherwise false.
*
* If a partial image has been received, the meta data returned in
* \c imageSet will be complete. The pixel data contained in
* \c imageSet, however, will only be valid for the first
* \c validRows rows.
*
* After obtaining a complete image set, reception is reset and
* subsequent calls to getPartiallyReceivedImageSet() or imagesReceived()
* will return false.
*
* Please note that the received image data is only valid until processing
* the first network message of the next image transfer.
*/
bool getPartiallyReceivedImageSet(ImageSet& imageSet, int& validRows, bool& complete);
/**
* \brief Returns true if the images of the current transfer have been received.
*/
bool imagesReceived() const;
/**
* \brief Returns the buffer for receiving the next network message.
*
* \param maxLength Maximum allowed length for the next network message
* \return Pointer to the buffer memory.
**/
unsigned char* getNextReceiveBuffer(int& maxLength);
/**
* \brief Handles a received network message
*
* \param length Length of the received network message.
*
* This method has to be called for every network message that has been
* received. The message data must be located in the most recent buffer
* that has been obtained with getNextReceiveBuffer().
*
* After calling this method, please check if a new image has been received
* by calling getReceivedImageSet() or getPartiallyReceivedImageSet().
*
* In order to handle connection timeouts this method should be called
* frequently. If no new data is available, a length of 0 can be passed.
*/
void processReceivedMessage(int length);
/**
* \brief Returns the number of frames that have been dropped since
* connecting to the current remote host.
*
* Dropped frames are caused by dropped packets due to a poor network
* connection
*/
int getNumDroppedFrames() const;
/**
* \brief Aborts the reception of the current image transfer and resets
* the internal state.
*/
void resetReception();
/**
* \brief Returns true if the last message has established a new connection
* from a client
*/
bool newClientConnected();
/**
* \brief Returns true if a remote connection is established
*/
bool isConnected() const;
/**
* \brief If a control message is pending to be transmitted then
* the message data will be returned by this method.
*
* \param length Will be set to the length of the message
* \return Pointer to the message data or NULL if no message is pending
*
* Control messages are only needed when using the UDP network protocol.
*/
const unsigned char* getNextControlMessage(int& length);
std::string statusReport();
private:
// We follow the pimpl idiom
class Pimpl;
Pimpl* pimpl;
// This class cannot be copied
ImageProtocol(const ImageProtocol& other);
ImageProtocol& operator=(const ImageProtocol&);
};
} // namespace
#endif