00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <stdio.h>
00022 #include <stdlib.h>
00023 #include <unistd.h>
00024 #include <string.h>
00025 #include <errno.h>
00026 #include <linux/types.h>
00027 #include <linux/videodev.h>
00028 #include <sys/mman.h>
00029 #include <sys/ioctl.h>
00030 #include <sys/file.h>
00031 #include <sys/types.h>
00032 #include <sys/stat.h>
00033 #include <fcntl.h>
00034 #include "flgrRtCapture.h"
00035
00036 #include <flgrCoreDispatch.h>
00037
00048
00049
00053
00054 unsigned short flgr2d_rtcapture_palette_from_string(char *palette) {
00055
00056
00057 if(strcmp(palette,"GREY")==0) {
00058 return VIDEO_PALETTE_GREY;
00059
00060 }else if(strcmp(palette,"HI240")==0) {
00061 return VIDEO_PALETTE_HI240;
00062
00063 }else if(strcmp(palette,"RGB565")==0) {
00064 return VIDEO_PALETTE_RGB565;
00065
00066 }else if(strcmp(palette,"RGB555")==0) {
00067 return VIDEO_PALETTE_RGB555;
00068
00069 }else if(strcmp(palette,"RGB24")==0) {
00070 return VIDEO_PALETTE_RGB24;
00071
00072 }else if(strcmp(palette,"RGB32")==0) {
00073 return VIDEO_PALETTE_RGB32;
00074
00075 }else if(strcmp(palette,"YUV422")==0) {
00076 return VIDEO_PALETTE_YUV422;
00077
00078 }else if(strcmp(palette,"YUYV")==0) {
00079 return VIDEO_PALETTE_YUYV;
00080
00081 }else if(strcmp(palette,"UYVY")==0) {
00082 return VIDEO_PALETTE_UYVY;
00083
00084 }else if(strcmp(palette,"YUV420")==0) {
00085 return VIDEO_PALETTE_YUV420;
00086
00087 }else if(strcmp(palette,"YUV411")==0) {
00088 return VIDEO_PALETTE_YUV411;
00089
00090 }else if(strcmp(palette,"RAW")==0) {
00091 return VIDEO_PALETTE_RAW;
00092
00093 }else if(strcmp(palette,"YUV422P")==0) {
00094 return VIDEO_PALETTE_YUV422P;
00095
00096 }else if(strcmp(palette,"YUV411P")==0) {
00097 return VIDEO_PALETTE_YUV411P;
00098
00099 }else if(strcmp(palette,"YUV420P")==0) {
00100 return VIDEO_PALETTE_YUV420P;
00101
00102 }else if(strcmp(palette,"YUV410P")==0) {
00103 return VIDEO_PALETTE_YUV410P;
00104 }
00105
00106 POST_WARNING("Unknown palette type\n");
00107 return 0;
00108 }
00109
00111
00116
00117 FLGR_Ret flgr2d_rtcapture_set_palette(FLGR_RtCapture2D *viddev, char *palette) {
00118 unsigned short plte = flgr2d_rtcapture_palette_from_string(palette);
00119
00120
00121
00122 if(viddev==NULL) {
00123 POST_ERROR("Null objects!\n");
00124 return FLGR_RET_NULL_OBJECT;
00125 }
00126
00127 if(plte==0) return FLGR_RET_UNDEFINED_ERROR;
00128
00129 viddev->vpic.palette = plte;
00130
00131 if( ioctl (viddev->fd, VIDIOCSPICT, &(viddev->vpic)) < 0 ) {
00132 POST_ERROR("");
00133 perror("VIDIOCSPICT");
00134 return FLGR_RET_UNDEFINED_ERROR;
00135 }
00136
00137 return FLGR_RET_OK;
00138 }
00139
00140
00141
00142 #define ALLOC_CPY_STRING(var,string) \
00143 var = (char *) malloc(strlen(string)+1); \
00144 strcpy(var,string)
00145
00147
00151
00152 char *flgr2d_rtcapture_get_palette(FLGR_RtCapture2D *viddev) {
00153 char *str;
00154
00155
00156
00157 if(viddev==NULL) {
00158 POST_ERROR("Null objects!\n");
00159 return NULL;
00160 }
00161
00162 switch(viddev->vpic.palette) {
00163 case VIDEO_PALETTE_GREY:
00164 ALLOC_CPY_STRING(str,"GREY");break;
00165
00166 case VIDEO_PALETTE_HI240:
00167 ALLOC_CPY_STRING(str,"HI240");break;
00168
00169 case VIDEO_PALETTE_RGB565:
00170 ALLOC_CPY_STRING(str,"RGB565");break;
00171
00172 case VIDEO_PALETTE_RGB24:
00173 ALLOC_CPY_STRING(str,"RGB24");break;
00174
00175 case VIDEO_PALETTE_RGB32:
00176 ALLOC_CPY_STRING(str,"RGB32");break;
00177
00178 case VIDEO_PALETTE_RGB555:
00179 ALLOC_CPY_STRING(str,"RGB555");break;
00180
00181 case VIDEO_PALETTE_YUV422:
00182 ALLOC_CPY_STRING(str,"YUV422");break;
00183
00184 case VIDEO_PALETTE_YUYV:
00185 ALLOC_CPY_STRING(str,"YUYV");break;
00186
00187 case VIDEO_PALETTE_UYVY:
00188 ALLOC_CPY_STRING(str,"UYVY");break;
00189
00190 case VIDEO_PALETTE_YUV420:
00191 ALLOC_CPY_STRING(str,"YUV420");break;
00192
00193 case VIDEO_PALETTE_YUV411:
00194 ALLOC_CPY_STRING(str,"YUV411");break;
00195
00196 case VIDEO_PALETTE_RAW:
00197 ALLOC_CPY_STRING(str,"RAW");break;
00198
00199 case VIDEO_PALETTE_YUV422P:
00200 ALLOC_CPY_STRING(str,"YUV422P");break;
00201
00202 case VIDEO_PALETTE_YUV411P:
00203 ALLOC_CPY_STRING(str,"YUV411P");break;
00204
00205 case VIDEO_PALETTE_YUV420P:
00206 ALLOC_CPY_STRING(str,"YUV420P");break;
00207
00208 case VIDEO_PALETTE_YUV410P:
00209 ALLOC_CPY_STRING(str,"YUV410P");break;
00210
00211 default:
00212 ALLOC_CPY_STRING(str,"UNKNOWN FORMAT");break;
00213 }
00214
00215 return str;
00216 }
00217
00218
00219
00220
00221
00223
00227
00228 FLGR_RtCapture2D *flgr2d_rtcapture_create(char *device) {
00229 int i;
00230 char *str;
00231 FLGR_RtCapture2D *viddev = malloc(sizeof(FLGR_RtCapture2D));
00232
00233
00234
00235 viddev->fd = open(device, O_RDWR);
00236 if(viddev->fd<0) {
00237 POST_ERROR("Could not open %s! ",device);
00238 perror("open");
00239 free(viddev);
00240 return NULL;
00241 }
00242
00243 if( ioctl(viddev->fd, VIDIOCGCAP, &(viddev->vcap) ) < 0 ) {
00244 POST_ERROR("%s is not a v4l device ??? ",device);
00245 perror("VIDIOGCAP");
00246 close(viddev->fd);
00247 free(viddev);
00248 return NULL;
00249 }
00250
00251 if( ioctl(viddev->fd, VIDIOCGWIN, &(viddev->vwin)) < 0 ) {
00252 POST_ERROR("");
00253 perror("VIDIOCGWIN");
00254 close(viddev->fd);
00255 free(viddev);
00256 return NULL;
00257 }
00258
00259 POST_INFO("Capture Device found : %s\n",viddev->vcap.name);
00260 POST_INFO("Capture Device Size : max size_x:%d max size_y:%d\n",viddev->vcap.maxwidth, viddev->vcap.maxheight);
00261
00262 if( ioctl(viddev->fd, VIDIOCGPICT, &(viddev->vpic)) < 0 ) {
00263 POST_ERROR("");
00264 perror("VIDIOCGPICT");
00265 close(viddev->fd);
00266 free(viddev);
00267 return NULL;
00268 }
00269
00270
00271 if( ioctl(viddev->fd, VIDIOCGCHAN, &(viddev->vchan)) < 0 ) {
00272 POST_WARNING("Capture device does not support Get Video Channel IOCTL\n");
00273 } else {
00274 POST_INFO("Video Channel found: %s \n", viddev->vchan.name);
00275 }
00276
00277
00278 POST_INFO("Current palette : %s\n",flgr2d_rtcapture_get_palette(viddev));
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288 POST_INFO("MMAP Frame Buffer\n");
00289 memset (&(viddev->vmbuf), 0, sizeof (viddev->vmbuf));
00290
00291 if( ioctl(viddev->fd, VIDIOCGMBUF, &(viddev->vmbuf)) < 0 ) {
00292 POST_ERROR("");
00293 perror (" init VIDIOCGMBUF FAILED\n");
00294 }
00295
00296 POST_INFO("Video MBUF Size %d ; Frames %d ; Offsets[0]=%d ; Offsets[1]=%d\n",
00297 viddev->vmbuf.size, viddev->vmbuf.frames,
00298 viddev->vmbuf.offsets[0], viddev->vmbuf.offsets[1]);
00299
00300 viddev->framebuffer = (unsigned char *) mmap (0, viddev->vmbuf.size, PROT_READ | PROT_WRITE, MAP_SHARED, viddev->fd, 0);
00301
00302 viddev->vmmap.width = viddev->vwin.width;
00303 viddev->vmmap.height = viddev->vwin.height;
00304 viddev->vmmap.format = viddev->vpic.palette;
00305
00306 POST_INFO("Capture bps: %d ; palette: %d\n",viddev->vpic.depth, viddev->vpic.palette);
00307 POST_INFO("Pixel Format : %s\n",str=flgr2d_rtcapture_get_palette(viddev));
00308 free(str);
00309
00310 for(i=0 ; i<viddev->vmbuf.frames ; i++) {
00311 viddev->vmmap.frame = i;
00312 if( ioctl (viddev->fd, VIDIOCMCAPTURE, &(viddev->vmmap)) ) {
00313 POST_WARNING("");
00314 perror("CMCAPTURE");
00315 }
00316 }
00317 viddev->vmmap.frame = 0;
00318
00319 return viddev;
00320 }
00321
00323
00327
00328 void flgr2d_rtcapture_destroy(FLGR_RtCapture2D *viddev) {
00329
00330
00331 if(viddev==NULL) {
00332 POST_ERROR("Null objects!\n");
00333 return;
00334 }
00335
00336 munmap (viddev->framebuffer, viddev->vmbuf.size);
00337 close(viddev->fd);
00338 free(viddev);
00339 }
00340
00342
00348
00349 FLGR_Ret flgr2d_rtcapture_set_window_size(FLGR_RtCapture2D *viddev, int size_x, int size_y) {
00350
00351
00352 if(viddev==NULL) {
00353 POST_ERROR("Null objects!\n");
00354 return FLGR_RET_NULL_OBJECT;
00355 }
00356
00357 if(size_x>viddev->vcap.maxwidth) {
00358 POST_ERROR("size_x too large\n");
00359 return FLGR_RET_UNDEFINED_ERROR;
00360 }
00361
00362 if(size_y>viddev->vcap.maxheight) {
00363 POST_ERROR("size_x too large\n");
00364 return FLGR_RET_UNDEFINED_ERROR;
00365 }
00366
00367 viddev->vwin.width = size_x;
00368 viddev->vwin.height = size_y;
00369 viddev->vmmap.width = size_x;
00370 viddev->vmmap.height = size_y;
00371
00372 if( ioctl (viddev->fd, VIDIOCSWIN, &(viddev->vwin)) < 0 ) {
00373 POST_ERROR("Could not change capture resolution to %d x %d \n",
00374 size_x, size_y);
00375 return FLGR_RET_UNDEFINED_ERROR;
00376 }
00377
00378 if( viddev->vwin.width != size_x) {
00379 POST_ERROR("Width capture resolution change failed!\n");
00380 return FLGR_RET_UNDEFINED_ERROR;
00381 }
00382
00383 if( viddev->vwin.height != size_y) {
00384 POST_ERROR("Height capture resolution change failed!\n");
00385 return FLGR_RET_UNDEFINED_ERROR;
00386 }
00387
00388
00389
00390 return FLGR_RET_OK;
00391 }
00392
00394
00400
00401 FLGR_Ret flgr2d_rtcapture_get_window_size(FLGR_RtCapture2D *viddev, int *size_x, int *size_y) {
00402
00403
00404 if(viddev==NULL) {
00405 POST_ERROR("Null objects!\n");
00406 return FLGR_RET_NULL_OBJECT;
00407 }
00408
00409 if( ioctl (viddev->fd, VIDIOCGWIN, &(viddev->vwin)) < 0 ) {
00410 POST_ERROR("Could not get capture resolution\n");
00411 return FLGR_RET_UNDEFINED_ERROR;
00412 }
00413
00414 *size_x = viddev->vwin.width;
00415 *size_y = viddev->vwin.height;
00416
00417 return FLGR_RET_OK;
00418 }
00419
00421
00426
00427 FLGR_Ret flgr2d_rtcapture_gray_image(FLGR_Data2D *img, FLGR_RtCapture2D *viddev) {
00428 int framec;
00429 unsigned char *ptr;
00430 fgUINT8 *rowptr;
00431 int tmp;
00432 int i,j,k;
00433
00434
00435
00436 if(viddev==NULL) {
00437 POST_ERROR("Null objects!\n");
00438 return FLGR_RET_NULL_OBJECT;
00439 }
00440
00441 if((viddev->vwin.width != img->size_x) || (viddev->vwin.height != img->size_y)){
00442 POST_ERROR("Capture Window sizes and Images sizes different\n");
00443 return FLGR_RET_SIZE_ERROR;
00444 }
00445
00446 if(img->type != FLGR_UINT8) {
00447 POST_ERROR("type is not allowed for gray capture\n");
00448 return FLGR_RET_TYPE_UNKNOWN;
00449 }
00450
00451 if( (viddev->vpic.palette != VIDEO_PALETTE_YUV420P ) &&
00452 (viddev->vpic.palette != VIDEO_PALETTE_RGB32 ) &&
00453 (viddev->vpic.palette != VIDEO_PALETTE_RGB24 ) ){
00454 POST_ERROR("Capture device could not work with Gray images\n");
00455 return FLGR_RET_UNDEFINED_ERROR;
00456 }
00457
00458
00459 framec = viddev->vmmap.frame;
00460 if( ioctl (viddev->fd, VIDIOCSYNC, &framec) < 0 ) {
00461 POST_ERROR("");
00462 perror ("Capture sync error");
00463 return FLGR_RET_UNDEFINED_ERROR;
00464 }
00465
00466 viddev->vmmap.frame = framec;
00467 ptr = viddev->framebuffer + viddev->vmbuf.offsets[viddev->vmmap.frame];
00468
00469
00470 if( viddev->vpic.palette == VIDEO_PALETTE_YUV420P ) {
00471 for(i=0 ; i<img->size_y ; i++) {
00472 memcpy(img->array[i], ptr, img->size_x);
00473 ptr += img->size_x;
00474 }
00475 }else if( viddev->vpic.palette == VIDEO_PALETTE_RGB32 ) {
00476 for(i=0 ; i<img->size_y ; i++) {
00477 rowptr = img->array[i];
00478 k=0;
00479 for(j=0 ; j<img->size_x ; j++) {
00480 tmp = ptr[k++];
00481 tmp += ptr[k++];
00482 tmp += ptr[k++];
00483 rowptr[j]=tmp/3;
00484 }
00485 ptr += img->size_x*4;
00486 }
00487 }else {
00488 for(i=0 ; i<img->size_y ; i++) {
00489 rowptr = img->array[i];
00490 k=0;
00491 for(j=0 ; j<img->size_x ; j++) {
00492 tmp = ptr[k++];
00493 tmp += ptr[k++];
00494 tmp += ptr[k++];
00495 rowptr[j]=tmp/3;
00496 }
00497 ptr += img->size_x*3;
00498 }
00499 }
00500
00501 if((ioctl (viddev->fd, VIDIOCMCAPTURE, &(viddev->vmmap))) < 0 ) {
00502 POST_ERROR("");
00503 perror ("cmcapture");
00504 return FLGR_RET_UNDEFINED_ERROR;
00505 }
00506 viddev->vmmap.frame = (viddev->vmmap.frame + 1) % viddev->vmbuf.frames;
00507
00508 return FLGR_RET_OK;
00509
00510 }
00511
00513
00520
00521 FLGR_Ret flgr2d_rtcapture_RGB24_image(FLGR_Data2D *imgR, FLGR_Data2D *imgG, FLGR_Data2D *imgB, FLGR_RtCapture2D *viddev) {
00522 int i,j,k;
00523 int framec;
00524 unsigned char *ptr;
00525 FLGR_Ret ret;
00526 fgUINT8 *ptrR,*ptrG,*ptrB;
00527
00528
00529
00530 if(viddev==NULL) {
00531 POST_ERROR("Null objects!\n");
00532 return FLGR_RET_NULL_OBJECT;
00533 }
00534
00535 if(imgR->type != FLGR_UINT8) {
00536 POST_ERROR("ype is not allowed for gray capture\n");
00537 return FLGR_RET_TYPE_UNKNOWN;
00538 }
00539 if(imgG->type != FLGR_UINT8) {
00540 POST_ERROR("type is not allowed for gray capture\n");
00541 return FLGR_RET_TYPE_UNKNOWN;
00542 }
00543 if(imgB->type != FLGR_UINT8) {
00544 POST_ERROR("type is not allowed for gray capture\n");
00545 return FLGR_RET_TYPE_UNKNOWN;
00546 }
00547
00548 if( (ret = flgr2d_is_data_same_size(imgR,imgG)) != FLGR_RET_OK ) {
00549 POST_ERROR("Images have different sizes!\n");
00550 return FLGR_RET_SIZE_ERROR;
00551 }
00552
00553 if( (ret = flgr2d_is_data_same_size(imgR,imgB)) != FLGR_RET_OK ) {
00554 POST_ERROR("Images have different sizes!\n");
00555 return FLGR_RET_SIZE_ERROR;
00556 }
00557
00558
00559
00560 if( viddev->vpic.palette == VIDEO_PALETTE_RGB24 ) {
00561 framec = viddev->vmmap.frame;
00562 if( ioctl (viddev->fd, VIDIOCSYNC, &framec) < 0 ) {
00563 POST_ERROR("");
00564 perror ("Capture sync error");
00565 return FLGR_RET_UNDEFINED_ERROR;
00566 }
00567
00568 viddev->vmmap.frame = framec;
00569
00570 ptr = viddev->framebuffer + viddev->vmbuf.offsets[viddev->vmmap.frame];
00571 for(i=0 ; i<imgR->size_y ; i++) {
00572 ptrR = imgR->array[i];
00573 ptrG = imgG->array[i];
00574 ptrB = imgB->array[i];
00575 k=0;
00576 for(j=0 ; j<imgR->size_x ; j++) {
00577 ptrR[j] = (fgUINT8) ptr[k++];
00578 ptrG[j] = (fgUINT8) ptr[k++];
00579 ptrB[j] = (fgUINT8) ptr[k++];
00580 }
00581 ptr += (imgR->size_x*3);
00582 }
00583
00584 if((ioctl (viddev->fd, VIDIOCMCAPTURE, &(viddev->vmmap))) < 0 ) {
00585 POST_ERROR("");
00586 perror ("cmcapture");
00587 return FLGR_RET_UNDEFINED_ERROR;
00588 }
00589 viddev->vmmap.frame = (viddev->vmmap.frame + 1) % viddev->vmbuf.frames;
00590
00591 return FLGR_RET_OK;
00592
00593 }else {
00594 POST_ERROR("Capture device could not work with Gray images\n");
00595 return FLGR_RET_UNDEFINED_ERROR;
00596
00597 }
00598 }
00599
00600