net.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <cams/net.h>
00025 #include <cams/cam_exceptions.h>
00026
00027 #include <core/exception.h>
00028 #include <core/exceptions/software.h>
00029
00030 #include <fvutils/net/fuse_client.h>
00031 #include <fvutils/net/fuse_message.h>
00032 #include <fvutils/net/fuse_image_content.h>
00033 #include <fvutils/net/fuse_imagelist_content.h>
00034 #include <fvutils/system/camargp.h>
00035 #include <fvutils/compression/jpeg_decompressor.h>
00036
00037 #include <netinet/in.h>
00038 #include <cstdlib>
00039 #include <cstring>
00040
00041 using namespace fawkes;
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058 NetworkCamera::NetworkCamera(const char *host, unsigned short port, bool jpeg)
00059 {
00060 if ( host == NULL ) {
00061 throw NullPointerException("NetworkCamera: host must not be NULL");
00062 }
00063 __image_id = 0;
00064 __host = strdup(host);
00065 __port = port;
00066 __get_jpeg = jpeg;
00067
00068 __connected = false;
00069 __opened = false;
00070 __local_version = 0;
00071 __remote_version = 0;
00072 __decompressor = NULL;
00073 __decompressed_buffer = NULL;
00074 __last_width = 0;
00075 __last_height = 0;
00076 __fuse_image = NULL;
00077 __fuse_message = NULL;
00078 __fuse_imageinfo = NULL;
00079
00080 __fusec = new FuseClient(__host, __port, this);
00081 if ( __get_jpeg ) {
00082 __decompressor = new JpegImageDecompressor();
00083 }
00084 }
00085
00086
00087
00088
00089
00090
00091
00092
00093 NetworkCamera::NetworkCamera(const char *host, unsigned short port, const char *image_id,
00094 bool jpeg)
00095 {
00096 if ( image_id == NULL ) {
00097 throw NullPointerException("NetworkCamera: image_id must not be NULL");
00098 }
00099 if ( host == NULL ) {
00100 throw NullPointerException("NetworkCamera: host must not be NULL");
00101 }
00102 __image_id = strdup(image_id);
00103 __host = strdup(host);
00104 __port = port;
00105 __get_jpeg = jpeg;
00106
00107 __connected = false;
00108 __opened = false;
00109 __local_version = 0;
00110 __remote_version = 0;
00111 __decompressor = NULL;
00112 __decompressed_buffer = NULL;
00113 __last_width = 0;
00114 __last_height = 0;
00115 __fuse_image = NULL;
00116 __fuse_message = NULL;
00117 __fuse_imageinfo = NULL;
00118
00119 __fusec = new FuseClient(__host, __port, this);
00120 if ( __get_jpeg ) {
00121 __decompressor = new JpegImageDecompressor();
00122 }
00123 }
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135 NetworkCamera::NetworkCamera(const CameraArgumentParser *cap)
00136 {
00137 if ( cap->has("image") ) {
00138 __image_id = strdup(cap->get("image").c_str());
00139 } else {
00140 throw NullPointerException("image parameter must be set");
00141 }
00142 if ( cap->has("host") ) {
00143 __host = strdup(cap->get("host").c_str());
00144 } else {
00145 __host = strdup("localhost");
00146 }
00147 if ( cap->has("port") ) {
00148 int i = atoi(cap->get("port").c_str());
00149 if ( (i < 0) || (i >= 0xFFFF) ) {
00150 throw IllegalArgumentException("Port must be in the range 0-65535");
00151 }
00152 __port = (unsigned int)i;
00153 } else {
00154 __port = 2208;
00155 }
00156
00157 __get_jpeg = ( cap->has("jpeg") && (cap->get("jpeg") == "true"));
00158
00159 __connected = false;
00160 __opened = false;
00161 __local_version = 0;
00162 __remote_version = 0;
00163 __decompressor = NULL;
00164 __decompressed_buffer = NULL;
00165 __last_width = 0;
00166 __last_height = 0;
00167 __fuse_image = NULL;
00168 __fuse_message = NULL;
00169 __fuse_imageinfo = NULL;
00170
00171 __fusec = new FuseClient(__host, __port, this);
00172 if ( __get_jpeg ) {
00173 __decompressor = new JpegImageDecompressor();
00174 }
00175 }
00176
00177
00178
00179 NetworkCamera::~NetworkCamera()
00180 {
00181 close();
00182 delete __fusec;
00183 free(__host);
00184 free(__image_id);
00185 if ( __decompressed_buffer != NULL) free(__decompressed_buffer);
00186 delete __decompressor;
00187 }
00188
00189
00190 void
00191 NetworkCamera::open()
00192 {
00193 if ( __opened ) return;
00194
00195 __fusec->connect();
00196 __fusec->start();
00197 __fusec->wait_greeting();
00198
00199 if ( __image_id) {
00200 FUSE_imagedesc_message_t *imagedesc = (FUSE_imagedesc_message_t *)calloc(1, sizeof(FUSE_imagedesc_message_t));
00201 strncpy(imagedesc->image_id, __image_id, IMAGE_ID_MAX_LENGTH);
00202 __fusec->enqueue_and_wait(FUSE_MT_GET_IMAGE_INFO, imagedesc, sizeof(FUSE_imagedesc_message_t));
00203
00204 if ( ! __fuse_imageinfo ) {
00205 throw Exception("Could not received image info. Image not available?");
00206 }
00207 }
00208
00209 __opened = true;
00210 }
00211
00212
00213 void
00214 NetworkCamera::start()
00215 {
00216 __started = true;
00217 }
00218
00219 void
00220 NetworkCamera::stop()
00221 {
00222 __started = false;
00223 }
00224
00225
00226 void
00227 NetworkCamera::print_info()
00228 {
00229 }
00230
00231
00232 void
00233 NetworkCamera::capture()
00234 {
00235 if (! __connected) {
00236 throw CaptureException("Capture failed, not connected");
00237 }
00238 if ( __fuse_image ) {
00239 throw CaptureException("You must dispose the buffer before fetching a new image");
00240 }
00241 if ( !__image_id ) {
00242 throw CaptureException("You must specify an image id");
00243 }
00244
00245 FUSE_imagereq_message_t *irm = (FUSE_imagereq_message_t *)malloc(sizeof(FUSE_imagereq_message_t));
00246 memset(irm, 0, sizeof(FUSE_imagereq_message_t));
00247 strncpy(irm->image_id, __image_id, IMAGE_ID_MAX_LENGTH);
00248 irm->format = (__get_jpeg ? FUSE_IF_JPEG : FUSE_IF_RAW);
00249 __fusec->enqueue_and_wait(FUSE_MT_GET_IMAGE, irm, sizeof(FUSE_imagereq_message_t));
00250
00251 if (! __connected) {
00252 throw CaptureException("Capture failed, connection died while waiting for image");
00253 }
00254 if ( ! __fuse_image ) {
00255 throw CaptureException("Fetching the image failed, no image received");
00256 }
00257
00258 if ( __get_jpeg ) {
00259 if ( (__fuse_image->pixel_width() != __last_width) ||
00260 (__fuse_image->pixel_height() != __last_height) ) {
00261 if (__decompressed_buffer != NULL ) {
00262 free(__decompressed_buffer);
00263 }
00264 size_t buffer_size = colorspace_buffer_size(YUV422_PLANAR, __fuse_image->pixel_width(),
00265 __fuse_image->pixel_height());
00266 __decompressed_buffer = (unsigned char *)malloc(buffer_size);
00267 __decompressor->set_decompressed_buffer(__decompressed_buffer, buffer_size);
00268 }
00269 __decompressor->set_compressed_buffer(__fuse_image->buffer(), __fuse_image->buffer_size());
00270 __decompressor->decompress();
00271 }
00272 }
00273
00274
00275 unsigned char *
00276 NetworkCamera::buffer()
00277 {
00278 if (__get_jpeg) {
00279 return __decompressed_buffer;
00280 } else {
00281 if ( __fuse_image ) {
00282 return __fuse_image->buffer();
00283 } else {
00284 return NULL;
00285 }
00286 }
00287 }
00288
00289 unsigned int
00290 NetworkCamera::buffer_size()
00291 {
00292 if ( __get_jpeg ) {
00293 return colorspace_buffer_size(YUV422_PLANAR, pixel_width(), pixel_height());
00294 } else {
00295 if (! __fuse_image) {
00296 return 0;
00297 } else {
00298 return colorspace_buffer_size((colorspace_t)__fuse_image->colorspace(),
00299 __fuse_image->pixel_width(),
00300 __fuse_image->pixel_height());
00301 }
00302 }
00303 }
00304
00305 void
00306 NetworkCamera::close()
00307 {
00308 dispose_buffer();
00309 if ( __started ) {
00310 stop();
00311 }
00312 if ( __fuse_imageinfo ) {
00313 free(__fuse_imageinfo);
00314 __fuse_imageinfo = NULL;
00315 }
00316 if ( __opened ) {
00317 __fusec->disconnect();
00318 __fusec->cancel();
00319 __fusec->join();
00320 __opened = false;
00321 }
00322 }
00323
00324 void
00325 NetworkCamera::dispose_buffer()
00326 {
00327 delete __fuse_image;
00328 __fuse_image = NULL;
00329 if ( __fuse_message ) {
00330 __fuse_message->unref();
00331 __fuse_message = NULL;
00332 }
00333 }
00334
00335 unsigned int
00336 NetworkCamera::pixel_width()
00337 {
00338 if ( __fuse_imageinfo ) {
00339 return ntohl(__fuse_imageinfo->width);
00340 } else {
00341 throw NullPointerException("No valid image info received");
00342 }
00343 }
00344
00345 unsigned int
00346 NetworkCamera::pixel_height()
00347 {
00348 if ( __fuse_imageinfo ) {
00349 return ntohl(__fuse_imageinfo->height);
00350 } else {
00351 throw NullPointerException("No valid image info received");
00352 }
00353 }
00354
00355 fawkes::Time *
00356 NetworkCamera::capture_time()
00357 {
00358 if ( __fuse_image ) {
00359 return __fuse_image->capture_time();
00360 } else {
00361 throw NullPointerException("No valid image exists");
00362 }
00363 }
00364
00365 void
00366 NetworkCamera::flush()
00367 {
00368 if (! __connected) return;
00369 dispose_buffer();
00370 }
00371
00372
00373 bool
00374 NetworkCamera::ready()
00375 {
00376 return __connected;
00377 }
00378
00379
00380
00381
00382
00383 void
00384 NetworkCamera::set_image_id(const char *image_id)
00385 {
00386 __image_id = strdup(image_id);
00387
00388 FUSE_imagedesc_message_t *imagedesc = (FUSE_imagedesc_message_t *)calloc(1, sizeof(FUSE_imagedesc_message_t));
00389 strncpy(imagedesc->image_id, __image_id, IMAGE_ID_MAX_LENGTH);
00390 __fusec->enqueue_and_wait(FUSE_MT_GET_IMAGE_INFO, imagedesc, sizeof(FUSE_imagedesc_message_t));
00391
00392 if ( ! __fuse_imageinfo ) {
00393 throw Exception("Could not received image info. Image not available?");
00394 }
00395 }
00396
00397
00398 void
00399 NetworkCamera::set_image_number(unsigned int n)
00400 {
00401
00402 }
00403
00404
00405 colorspace_t
00406 NetworkCamera::colorspace()
00407 {
00408 if ( __get_jpeg ) {
00409 return YUV422_PLANAR;
00410 } else {
00411 if ( __fuse_imageinfo ) {
00412 return (colorspace_t)ntohs(__fuse_imageinfo->colorspace);
00413 } else {
00414 return CS_UNKNOWN;
00415 }
00416 }
00417 }
00418
00419
00420
00421
00422
00423 std::vector<FUSE_imageinfo_t>&
00424 NetworkCamera::image_list()
00425 {
00426 __image_list.clear();
00427
00428 if (! __connected) {
00429 throw CaptureException("Capture failed, not connected");
00430 }
00431
00432 __fusec->enqueue_and_wait(FUSE_MT_GET_IMAGE_LIST);
00433
00434 return __image_list;
00435 }
00436
00437
00438 void
00439 NetworkCamera::fuse_invalid_server_version(uint32_t local_version,
00440 uint32_t remote_version) throw()
00441 {
00442 __local_version = local_version;
00443 __remote_version = remote_version;
00444 }
00445
00446
00447 void
00448 NetworkCamera::fuse_connection_established() throw()
00449 {
00450 __connected = true;
00451 }
00452
00453
00454 void
00455 NetworkCamera::fuse_connection_died() throw()
00456 {
00457 __connected = false;
00458 }
00459
00460
00461 void
00462 NetworkCamera::fuse_inbound_received(FuseNetworkMessage *m) throw()
00463 {
00464 switch(m->type()) {
00465
00466 case FUSE_MT_IMAGE:
00467 try {
00468 __fuse_image = m->msgc<FuseImageContent>();
00469 if ( __fuse_image ) {
00470 __fuse_message = m;
00471 __fuse_message->ref();
00472 }
00473 } catch (Exception &e) {
00474 __fuse_image = NULL;
00475 __fuse_message = NULL;
00476 }
00477 break;
00478
00479
00480 case FUSE_MT_IMAGE_INFO:
00481 try {
00482 __fuse_imageinfo = m->msg_copy<FUSE_imageinfo_t>();
00483 } catch (Exception &e) {
00484 __fuse_imageinfo = NULL;
00485 }
00486 break;
00487
00488 case FUSE_MT_IMAGE_INFO_FAILED:
00489 __fuse_imageinfo = NULL;
00490 break;
00491
00492 case FUSE_MT_GET_IMAGE_FAILED:
00493 if ( __fuse_message ) {
00494 __fuse_message->unref();
00495 }
00496 __fuse_message = NULL;
00497 __fuse_image = NULL;
00498 break;
00499
00500 case FUSE_MT_IMAGE_LIST:
00501 try {
00502 FuseImageListContent* fuse_image_list = m->msgc<FuseImageListContent>();
00503 if (fuse_image_list ) {
00504 while ( fuse_image_list->has_next() ) {
00505 FUSE_imageinfo_t *iip = fuse_image_list->next();
00506 FUSE_imageinfo_t ii;
00507 strncpy(ii.image_id, iip->image_id, IMAGE_ID_MAX_LENGTH);
00508 ii.colorspace = ntohs(iip->colorspace);
00509 ii.width = ntohl(iip->width);
00510 ii.height = ntohl(iip->height);
00511 ii.buffer_size = ntohl(iip->buffer_size);
00512 __image_list.push_back(ii);
00513 }
00514 }
00515 }
00516 catch (Exception &e) {
00517 }
00518 break;
00519
00520 default:
00521 break;
00522 }
00523 }
00524