38 #ifndef WIN32_LEAN_AND_MEAN 39 #define WIN32_LEAN_AND_MEAN 1 46 #include <arpa/inet.h> 70 volatile bool doneG =
false;
72 void usage(
const char* programNameP)
74 std::cerr <<
"USAGE: " << programNameP <<
" [<options>]" << std::endl;
75 std::cerr <<
"Where <options> are:" << std::endl;
76 std::cerr <<
"\t-a <current_address> : CURRENT IPV4 address (default=10.66.171.21)" << std::endl;
77 std::cerr <<
"\t-m <mtu> : CURRENT MTU (default=7200)" << std::endl;
78 std::cerr <<
"\t-s <color_source> : LEFT,RIGHT,AUX (default=aux)" << std::endl;
84 BOOL WINAPI signalHandler(DWORD dwCtrlType)
91 void signalHandler(
int sig)
105 ChannelWrapper(
const std::string& ipAddress) :
106 channelPtr_(
Channel::Create(ipAddress))
124 ChannelWrapper(
const ChannelWrapper&) =
delete;
125 ChannelWrapper operator=(
const ChannelWrapper&) =
delete;
127 Channel* channelPtr_ =
nullptr;
133 class ImageBufferWrapper
139 callbackBuffer_(driver->reserveCallbackBuffer()),
144 ~ImageBufferWrapper()
147 driver_->releaseCallbackBuffer(callbackBuffer_);
158 ImageBufferWrapper(
const ImageBufferWrapper&) =
delete;
159 ImageBufferWrapper operator=(
const ImageBufferWrapper&) =
delete;
162 void* callbackBuffer_;
170 std::shared_ptr<const ImageBufferWrapper> chroma =
nullptr;
171 std::shared_ptr<const ImageBufferWrapper> luma =
nullptr;
174 std::pair<DataSource, DataSource> colorSource;
183 const uint8_t* lumaP =
reinterpret_cast<const uint8_t*
>(luma.
imageDataP);
184 const uint8_t* chromaP =
reinterpret_cast<const uint8_t*
>(chroma.
imageDataP);
186 const size_t luma_offset = (v * luma.
width) + u;
187 const size_t chroma_offset = 2 * (((v / 2) * (luma.
width / 2)) + (u / 2));
189 const float px_y =
static_cast<float>(lumaP[luma_offset]);
190 const float px_cb =
static_cast<float>(chromaP[chroma_offset + 0]) - 128.0f;
191 const float px_cr =
static_cast<float>(chromaP[chroma_offset + 1]) - 128.0f;
193 float px_r = px_y + 1.13983f * px_cr;
194 float px_g = px_y - 0.39465f * px_cb - 0.58060f * px_cr;
195 float px_b = px_y + 2.03211f * px_cb;
197 if (px_r < 0.0f) px_r = 0.0f;
198 else if (px_r > 255.0f) px_r = 255.0f;
199 if (px_g < 0.0f) px_g = 0.0f;
200 else if (px_g > 255.0f) px_g = 255.0f;
201 if (px_b < 0.0f) px_b = 0.0f;
202 else if (px_b > 255.0f) px_b = 255.0f;
204 return { {
static_cast<uint8_t
>(px_r), static_cast<uint8_t>(px_g),
static_cast<uint8_t
>(px_b)} };
213 throw std::runtime_error(
"Only 8-bit luma and 16-bit chroma images are supported by the \ 214 ycbcrToBgr conversion function");
217 const size_t rgb_stride = luma.
width * 3;
219 for (uint32_t y = 0; y < luma.
height; ++y)
221 const size_t row_offset = y * rgb_stride;
223 for (uint32_t x = 0; x < luma.
width; ++x)
225 memcpy(output + row_offset + (3 * x), ycbcrToBgr<uint8_t>(luma, chroma, x, y).data(), 3);
230 bool savePpm(
const std::string& fileName,
235 std::ofstream outputStream(fileName.c_str(), std::ios::out | std::ios::binary);
237 if (
false == outputStream.good()) {
238 std::cerr <<
"Failed to open \"" << fileName <<
"\"" << std::endl;
242 const uint32_t imageSize = height * width * 3;
245 outputStream <<
"P6\n" 246 << width <<
" " << height <<
"\n" 249 outputStream.write(reinterpret_cast<const char*>(dataP), imageSize);
251 outputStream.close();
255 bool saveColor(
const std::string& fileName,
256 std::shared_ptr<const ImageBufferWrapper> leftRect,
257 std::shared_ptr<const ImageBufferWrapper> leftChromaRect)
259 std::vector<uint8_t> output(leftRect->data().width * leftRect->data().height * 3);
260 ycbcrToBgr(leftRect->data(), leftChromaRect->data(), output.data());
262 savePpm(fileName, leftRect->data().width, leftRect->data().height, output.data());
269 UserData* userData =
reinterpret_cast<UserData*
>(userDataP);
272 if (!userData->driver) {
273 std::cerr <<
"Invalid MultiSense channel" << std::endl;
277 if (header.
source == userData->colorSource.first)
279 userData->chroma = std::make_shared<ImageBufferWrapper>(userData->driver, header);
280 if (userData->luma && userData->luma->data().frameId == header.
frameId)
289 if (header.
source == userData->colorSource.second)
291 userData->luma = std::make_shared<ImageBufferWrapper>(userData->driver, header);
292 if (userData->chroma && userData->chroma->data().frameId == header.
frameId)
302 if (userData->luma !=
nullptr && userData->chroma !=
nullptr)
304 saveColor(std::to_string(header.
frameId) +
".ppm", userData->luma,
309 std::pair<DataSource, DataSource> colorSourceFromArg(
const std::string &srcStr)
315 else if (srcStr ==
"left")
319 else if (srcStr ==
"right")
325 throw std::runtime_error(
"Invalid color source given");
334 std::string currentAddress =
"10.66.171.21";
339 SetConsoleCtrlHandler(signalHandler, TRUE);
341 signal(SIGINT, signalHandler);
349 while (-1 != (c =
getopt(argc, argvPP,
"a:m:s:")))
351 case 'a': currentAddress = std::string(
optarg);
break;
352 case 'm': mtu = atoi(
optarg);
break;
353 case 's': userSource = colorSourceFromArg(
optarg);
break;
354 default:
usage(*argvPP);
break;
362 auto channelP = std::make_unique<ChannelWrapper>(currentAddress);
363 if (
nullptr == channelP ||
nullptr == channelP->ptr()) {
364 std::cerr <<
"Failed to establish communications with \"" << currentAddress <<
"\"" << std::endl;
371 status = channelP->ptr()->setMtu(mtu);
381 status = channelP->ptr()->getImageCalibration(calibration);
391 status = channelP->ptr()->getDeviceInfo(deviceInfo);
402 status = channelP->ptr()->getImageConfig(cfg);
413 status = channelP->ptr()->setImageConfig(cfg);
423 UserData userData{ channelP->ptr(),
nullptr,
nullptr, calibration, deviceInfo, userSource };
428 channelP->ptr()->addIsolatedCallback(imageCallback, userSource.first | userSource.second, &userData);
433 status = channelP->ptr()->startStreams(userSource.first | userSource.second);
443 status = channelP->ptr()->stopStreams(
Source_All);
int main(int argc, char **argvPP)
static const char * statusString(Status status)
static CRL_CONSTEXPR DataSource Source_Chroma_Left
static CRL_CONSTEXPR DataSource Source_Luma_Left
void setResolution(uint32_t w, uint32_t h)
int getopt(int argc, char **argv, char *opts)
static CRL_CONSTEXPR DataSource Source_Luma_Rectified_Aux
static CRL_CONSTEXPR DataSource Source_Luma_Right
static CRL_CONSTEXPR Status Status_Ok
void setAutoExposure(bool e)
static CRL_CONSTEXPR DataSource Source_Chroma_Rectified_Aux
static void Destroy(Channel *instanceP)
void setAutoWhiteBalance(bool e)
static CRL_CONSTEXPR DataSource Source_Chroma_Right
static CRL_CONSTEXPR DataSource Source_All