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