15 #if __GNUC__ == 4 && __GNUC_MINOR__ < 9 18 #include <bits/c++config.h> 19 #undef _GLIBCXX_USE_CLOCK_MONOTONIC 26 #include <condition_variable> 32 #include "visiontransfer/asynctransfer.h" 33 #include "visiontransfer/alignedallocator.h" 40 class AsyncTransfer::Pimpl {
43 const char* localAddress,
const char* localService,
int bufferSize);
47 void sendImagePairAsync(
const ImagePair& imagePair,
bool deleteData);
48 bool collectReceivedImagePair(
ImagePair& imagePair,
double timeout);
55 volatile bool terminate;
59 std::thread sendThread;
61 std::condition_variable sendCond;
62 std::condition_variable sendWaitCond;
64 std::thread receiveThread;
65 std::timed_mutex receiveMutex;
66 std::condition_variable_any receiveCond;
67 std::condition_variable_any receiveWaitCond;
71 std::vector<unsigned char, AlignedAllocator<unsigned char> > receivedData[4];
79 std::exception_ptr receiveException;
80 std::exception_ptr sendException;
82 bool sendThreadCreated;
83 bool receiveThreadCreated;
95 const char* localAddress,
const char* localService,
int bufferSize)
96 : pimpl(new Pimpl(mode, remoteAddress, remoteService, localAddress, localService, bufferSize)) {
99 AsyncTransfer::~AsyncTransfer() {
104 pimpl->sendImagePairAsync(imagePair, deleteData);
108 return pimpl->collectReceivedImagePair(imagePair, timeout);
114 const char* localAddress,
const char* localService,
int bufferSize)
115 : imgTrans(mode, remoteAddress, remoteService, localAddress, localService, bufferSize), terminate(
false),
116 newDataReceived(
false), sendPairValid(
false), deleteSendData(
false), sendThreadCreated(
false),
117 receiveThreadCreated(
false) {
121 while(!imgTrans.tryAccept()) {
122 std::chrono::milliseconds duration(10);
123 std::this_thread::sleep_for(duration);
128 AsyncTransfer::Pimpl::~Pimpl() {
131 sendCond.notify_all();
132 receiveCond.notify_all();
133 sendWaitCond.notify_all();
134 receiveWaitCond.notify_all();
136 if(sendThreadCreated && sendThread.joinable()) {
140 if(receiveThreadCreated && receiveThread.joinable()) {
141 receiveThread.join();
144 if(sendPairValid && deleteSendData) {
145 delete[] sendImagePair.getPixelData(0);
146 delete[] sendImagePair.getPixelData(1);
150 void AsyncTransfer::Pimpl::sendImagePairAsync(
const ImagePair& imagePair,
bool deleteData) {
151 if(!sendThreadCreated) {
153 unique_lock<mutex> lock(sendMutex);
154 sendThread = thread(bind(&AsyncTransfer::Pimpl::sendLoop,
this));
155 sendThreadCreated =
true;
159 unique_lock<mutex> lock(sendMutex);
163 std::rethrow_exception(sendException);
167 sendImagePair = imagePair;
168 sendPairValid =
true;
169 deleteSendData = deleteData;
172 sendCond.notify_one();
177 sendWaitCond.wait(lock);
182 bool AsyncTransfer::Pimpl::collectReceivedImagePair(
ImagePair& imagePair,
double timeout) {
183 if(!receiveThreadCreated) {
185 unique_lock<timed_mutex> lock(receiveMutex);
186 receiveThreadCreated =
true;
187 receiveThread = thread(bind(&AsyncTransfer::Pimpl::receiveLoop,
this));
191 unique_lock<timed_mutex> lock(receiveMutex, std::defer_lock);
195 std::chrono::steady_clock::time_point lockStart =
196 std::chrono::steady_clock::now();
197 if(!lock.try_lock_for(std::chrono::microseconds(static_cast<unsigned int>(timeout*1e6)))) {
203 unsigned int lockDuration =
static_cast<unsigned int>(std::chrono::duration_cast<std::chrono::microseconds>(
204 std::chrono::steady_clock::now() - lockStart).count());
205 timeout = std::max(0.0, timeout - lockDuration*1e-6);
209 if(receiveException) {
210 std::rethrow_exception(receiveException);
213 if(timeout == 0 && !newDataReceived) {
219 if(!newDataReceived) {
221 while(!terminate && !receiveException && !newDataReceived) {
222 receiveCond.wait(lock);
225 receiveCond.wait_for(lock, std::chrono::microseconds(static_cast<unsigned int>(timeout*1e6)));
230 if(receiveException) {
231 std::rethrow_exception(receiveException);
234 if(newDataReceived) {
236 imagePair = receivedPair;
238 newDataReceived =
false;
239 receiveWaitCond.notify_one();
247 void AsyncTransfer::Pimpl::sendLoop() {
250 unique_lock<mutex> lock(sendMutex);
254 bool deletePair =
false;
260 unique_lock<mutex> lock(sendMutex);
262 while(!terminate && !sendPairValid) {
269 pair = sendImagePair;
270 deletePair = deleteSendData;
271 sendPairValid =
false;
273 sendWaitCond.notify_one();
277 imgTrans.setTransferImagePair(pair);
278 imgTrans.transferData(
true);
290 sendException = std::current_exception();
292 sendWaitCond.notify_all();
303 void AsyncTransfer::Pimpl::receiveLoop() {
306 unique_lock<timed_mutex> lock(receiveMutex);
315 if(!imgTrans.receiveImagePair(currentPair)) {
321 for(
int i=0;i<2;i++) {
323 int newStride = currentPair.
getWidth() * bytesPerPixel;
324 int totalSize = currentPair.
getHeight() * newStride;
325 if(static_cast<int>(receivedData[i + bufferIndex].size()) < totalSize) {
326 receivedData[i + bufferIndex].resize(totalSize);
329 memcpy(&receivedData[i + bufferIndex][0], currentPair.
getPixelData(i),
332 for(
int y = 0; y<currentPair.
getHeight(); y++) {
333 memcpy(&receivedData[i + bufferIndex][y*newStride],
339 currentPair.
setPixelData(i, &receivedData[i + bufferIndex][0]);
343 unique_lock<timed_mutex> lock(receiveMutex);
346 while(newDataReceived) {
347 receiveWaitCond.wait_for(lock, std::chrono::milliseconds(100));
354 newDataReceived =
true;
355 receivedPair = currentPair;
356 receiveCond.notify_one();
360 bufferIndex = (bufferIndex + 2) % 4;
364 if(!receiveException) {
365 receiveException = std::current_exception();
367 receiveCond.notify_all();
Using TCP and acting as communication server.
OperationMode
Supported transfer modes.
unsigned char * getPixelData(int imageNumber) const
Returns the pixel data for the given image.
int getWidth() const
Returns the width of each image.
AsyncTransfer(ImageTransfer::OperationMode mode, const char *remoteAddress, const char *remoteService, const char *localAddress, const char *localService, int bufferSize=800000)
Creates a new transfer object.
void setRowStride(int imageNumber, int stride)
Sets a new row stride for the pixel data of one image.
Class for synchronous transfer of image pairs.
void setPixelData(int imageNumber, unsigned char *pixelData)
Sets the pixel data for the given image.
A set of two images, which are usually the left camera image and the disparity map.
ImageFormat getPixelFormat(int imageNumber) const
Returns the pixel format for the given image.
void sendImagePairAsync(const ImagePair &imagePair, bool deleteData)
Starts an asynchronous transmission of the given image pair.
int getHeight() const
Returns the height of each image.
int getRowStride(int imageNumber) const
Returns the row stride for the pixel data of one image.
bool collectReceivedImagePair(ImagePair &imagePair, double timeout=-1)
Collects the asynchronously received image.