1 /*M///////////////////////////////////////////////////////////////////////////////////////
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
5 // By downloading, copying, installing or using the software you agree to this license.
6 // If you do not agree to this license, do not download, install,
7 // copy or use the software.
10 // Intel License Agreement
11 // For Open Source Computer Vision Library
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
19 // * Redistribution's of source code must retain the above copyright notice,
20 // this list of conditions and the following disclaimer.
22 // * Redistribution's in binary form must reproduce the above copyright notice,
23 // this list of conditions and the following disclaimer in the documentation
24 // and/or other materials provided with the distribution.
26 // * The name of Intel Corporation may not be used to endorse or promote products
27 // derived from this software without specific prior written permission.
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
44 #include <sys/types.h>
48 #include <sys/ioctl.h>
59 #include "cvvidtypes.h"
64 //#define DEBUG_CVCAM 1
65 //#define DEBUG_THREADS 1
68 #define pthread_mutex_lock(x) printf("locking mutex "#x" from thread %p\n",pthread_self()),pthread_mutex_lock(x)
69 #define pthread_mutex_unlock(x) printf("unlocking mutex "#x" from thread %p\n",pthread_self()),pthread_mutex_unlock(x)
70 #define pthread_rwlock_rdlock(x) printf("rdlocking rwlock "#x" from thread %p\n",pthread_self()),pthread_rwlock_rdlock(x)
71 #define pthread_rwlock_wrlock(x) printf("wrlocking rwlock "#x" from thread %p\n",pthread_self()),pthread_rwlock_wrlock(x)
72 #define pthread_rwlock_unlock(x) printf("unlocking rwlock "#x" from thread %p\n",pthread_self()),pthread_rwlock_unlock(x)
73 #define pthread_create(a,b,c,d) printf("starting new thread from thread %p\n",pthread_self()),pthread_create(a,b,c,d)
76 const int FRAMES_FORMAT=0;
77 const int TIME_FORMAT = 1;
79 CvVideoCamera* cameras = NULL;
80 static int ncameras = 0;
82 static void icvVideoPicture2ImageBuffer(int camera);
83 static IplImage * icvVideoGetImage(int cameraid);
85 /* Returns the actual number of currently available cameras */
86 int cvcamGetCamerasCount()
93 struct video_capability VidCap;
94 struct video_channel Channel;
97 printf("cvcamGetCamerasCount(), ncameras=%d\n",ncameras);
102 if(glob("/dev/video*",GLOB_MARK,NULL, &pglob))
104 fprintf(stderr, "cvcamGetCamerasCount:no video devices /dev/video(n)"
109 descriptors = (int*)malloc(pglob.gl_pathc*sizeof(int));
111 for(count = 0; count < pglob.gl_pathc; count++)
113 descriptors[count] = open(pglob.gl_pathv[count],O_RDWR);
114 if (descriptors[count] != -1 )
116 if(ioctl(descriptors[count], VIDIOCGCAP, &VidCap)==-1)
118 close(descriptors[count]);
122 for(count1=0; count1<VidCap.channels; count1++)
125 Channel.channel = count1;
127 if((ioctl(descriptors[count], VIDIOCGCHAN, &Channel) != -1))
131 Channel.channel = count1;
133 if((ioctl(descriptors[count],VIDIOCSCHAN, &Channel) != -1)&&
134 (ioctl(descriptors[count], VIDIOCGCAP, &VidCap) != -1))
136 if(Channel.type&VIDEO_TYPE_CAMERA)
140 (CvVideoCamera*)realloc(cameras,
141 (CamerasCount+1)*sizeof(CvVideoCamera));
142 if(!icvVideoSetDefaultValues(CamerasCount,
146 printf("icvVideoSetDefaultValues failed for camera %d, channel %d\n",count,count1);
150 strcpy(cameras[CamerasCount].description.device,
151 pglob.gl_pathv[count]);
153 strcpy(cameras[CamerasCount].description.DeviceDescription,
156 strcpy(cameras[CamerasCount].description.ChannelDescription,
162 }//if(Channel.type&VIDEO_TYPE_CAMERA)
163 }//if((ioctl(descriptors[count],VIDIOCSCHAN, &Channel) != -1)&&
164 //(ioctl(descriptors[count], VIDIOCGCAP, &VidCap)!=-1))
165 }//if(ioctl(fd, VIDIOCSCHAN, &Channel) != -1)
166 }//for(count1=0; count1<VidCap.channels; count1++)
167 if(count1 == VidCap.channels) // no valid channel found
169 printf("closing descriptors[%d]=%d\n",count,descriptors[count]);
170 close(descriptors[count]);
172 }//if (descriptors[count] = open(pglob.gl_pathv[count],O_RDWR) != -1 )
173 }//for (count = 0; count < pglob.gl_pathc; count++)
176 ncameras = CamerasCount;
179 printf("cvcamGetCamerasCount() found %d cameras\n",ncameras);
183 ///////////////////////////////////////////////////////////////////////////////
184 /* get/set the property of the camera. returns 0 if the property is not supported */
185 int cvcamGetProperty(int cameraid, const char* property, void* value)
187 CvVideoCamera *const camera = &(cameras[cameraid]);
190 printf("cvcamGetProperty(camera=%d,property=%s)\n",cameraid, property);
192 if(!cameras||cameraid>ncameras-1||cameraid<0)
194 fprintf(stderr,"cvcamGetProperty:no such camera\n");
196 }//if(!cameras||camera>ncameras-1||camera<0)
198 IF_GETTING_PROPERTY("description")
200 strcpy(((CameraDescription*)value)->DeviceDescription,camera->description.DeviceDescription);
201 strcpy(((CameraDescription*)value)->device, camera->description.device);
202 strcpy(((CameraDescription*)value)->ChannelDescription,camera->description.ChannelDescription);
204 ((CameraDescription*)value)->channel = camera->description.channel;
206 ((CameraDescription*)value)->maxwidth = camera->description.maxwidth;
207 ((CameraDescription*)value)->maxheight = camera->description.maxheight;
208 ((CameraDescription*)value)->minwidth = camera->description.minwidth;
209 ((CameraDescription*)value)->minheight = camera->description.minheight;
212 }//IF_GETTING_PROPERTY("description")
214 IF_GETTING_PROPERTY("enable")
216 *(int*)value = camera->enabled;
218 }//IF_GETTING_PROPERTY("enable")
220 IF_GETTING_PROPERTY("render")
222 *(int*)value = camera->rendered;
223 //TODO: real call to rendering ioctl(if after initialisation)
226 }//IF_GETTING_PROPERTY("render")
228 IF_GETTING_PROPERTY("window")
230 *(Window*)value = camera->window;
232 }//IF_GETTING_PROPERTY("window")
234 IF_GETTING_PROPERTY("callback")
236 fprintf(stdout,"The property \"callback\" is set-only\n");
238 }//IF_GETTING_PROPERTY("callback")
240 IF_GETTING_PROPERTY("camera_pp")
242 icvVideoCameraPPDialog(cameraid);
244 }//IF_GETTING_PROPERTY("camera_pp")
246 IF_GETTING_PROPERTY("set_video_format")
249 if(!camera->initialised)
251 fprintf(stderr, "cvcamGetProperty, property = video_pp, camera\
256 ((VideoFormat*)value)->width = camera->videopp.width;
257 ((VideoFormat*)value)->height = camera->videopp.height;
259 ((VideoFormat*)value)->picture.brightness =
260 camera->videopp.picture.brightness;
262 ((VideoFormat*)value)->picture.hue =
263 camera->videopp.picture.hue;
265 ((VideoFormat*)value)->picture.colour =
266 camera->videopp.picture.colour;
268 ((VideoFormat*)value)->picture.contrast =
269 camera->videopp.picture.contrast;
271 ((VideoFormat*)value)->picture.whiteness =
272 camera->videopp.picture.whiteness;
274 ((VideoFormat*)value)->picture.depth =
275 camera->videopp.picture.depth;
277 ((VideoFormat*)value)->picture.palette =
278 camera->videopp.picture.palette;
281 }//IF_GETTING_PROPERTY("set_video_format")
283 IF_GETTING_PROPERTY("rectify_parameters")
285 fprintf(stdout,"TODO get prop rectify_parameters\n");
287 }//IF_GETTING_PROPERTY("rectify_parameters")
289 IF_GETTING_PROPERTY("stereo_parameters")
291 fprintf(stdout,"TODO get prop stereo_parameters\n");
293 }//IF_GETTING_PROPERTY("stereo_parameters")
295 IF_GETTING_PROPERTY("raw_image")
297 *((IplImage**)value) = icvVideoGetImage(cameraid);
298 if(*((IplImage**)value) != NULL)
302 }//IF_GETTING_PROPERTY("raw_image")
304 IF_GETTING_PROPERTY("disparity")
306 fprintf(stdout,"TODO get prop disparity\n");
308 }//IF_GETTING_PROPERTY("disparity")
310 IF_GETTING_PROPERTY("stereo_image")
312 fprintf(stdout,"TODO get prop stereo_image\n");
314 }//IF_GETTING_PROPERTY("stereo_image")
316 IF_GETTING_PROPERTY("video_pp")
318 icvVideoVideoPPDialog(cameraid);
320 }//IF_GETTING_PROPERTY("video_pp")
322 IF_GETTING_PROPERTY(CVCAM_RNDWIDTH)
324 *(int*)value = camera->renderwidth;
326 }//IF_GETTING_PROPERTY (CVCAM_RNDWIDTH)
328 IF_GETTING_PROPERTY(CVCAM_RNDHEIGHT)
330 *(int*)value = camera->renderheight;
332 }//IF_GETTING_PROPERTY("CVCAM_RNDHEIGHT")
337 //////////////////////////////////////////////////////////////////////////////////////////////////////////
340 /* gets all property names. the actual number of properties is returned. */
341 int cvcamGetPropertiesList(int camera, const char** properties, int count)
344 printf("cvcamGetPropertiesList()\n");
348 properties[0] = "description" ;
349 properties[1] = "enable";
350 properties[2] = "render";
351 properties[3] = "window";
352 properties[4] = "callback";
353 properties[5] = "camera_pp";
354 properties[6] = "video_pp" ;
355 properties[7] = "raw_image";
356 properties[8] = "set_video_format" ;
360 ///////////////////////////////////////////////////////////////////////////////////////////////////////////
363 int cvcamSetProperty(int cameraid, const char* property, void* value)
366 CvVideoCamera *const camera = &(cameras[cameraid]);
369 printf("cvcamSetProperty(camera=%d,property=%s)\n",cameraid, property);
371 if(!cameras||cameraid>ncameras-1||cameraid<0)
373 fprintf(stderr,"cvcamSetProperty: no such camera\n");
375 }//if(!cameras||camera>ncameras-1)
377 IF_SETTING_PROPERTY("description")
379 fprintf(stdout, "cvcamSetProperty: The property \"description\" cannot be "
382 }//IF_SETTING_PROPERTY("description")
384 IF_SETTING_PROPERTY("enable")
386 camera->enabled = (int)value;
388 }//IF_SETTING_PROPERTY("enable")
390 IF_SETTING_PROPERTY("render")
392 camera->rendered = (int)value;
394 }//IF_SETTING_PROPERTY("render")
396 IF_SETTING_PROPERTY("window")
398 camera->window = *(Window*)value;
400 //fprintf(stdout,"TODO get prop window\n");
402 }//IF_SETTING_PROPERTY("window")
404 IF_SETTING_PROPERTY("callback")
406 camera->callback = ( void (*)(IplImage*) )value;
408 }//IF_SETTING_PROPERTY("callback")
410 IF_SETTING_PROPERTY("camera_pp")
412 fprintf(stdout,"TODO get prop camera_pp\n");
414 }//IF_SETTING_PROPERTY("camera_pp")
416 IF_SETTING_PROPERTY("description")
418 fprintf(stdout,"TODO get prop camera_pp\n");
420 }//IF_SETTING_PROPERTY("camera_pp")
422 IF_SETTING_PROPERTY("set_video_format")
424 k = icvVideoStop(cameraid);
426 (((VideoFormat*)value)->picture.brightness>0xffff)||
427 (((VideoFormat*)value)->picture.hue>0xffff)||
428 (((VideoFormat*)value)->picture.colour>0xffff)||
429 (((VideoFormat*)value)->picture.contrast>0xffff)||
430 (((VideoFormat*)value)->picture.whiteness>0xffff)||
431 (((VideoFormat*)value)->width > camera->description.maxwidth)||
432 (((VideoFormat*)value)->height > camera->description.maxheight)||
433 (((VideoFormat*)value)->width < camera->description.minwidth)||
434 (((VideoFormat*)value)->height < camera->description.minheight)
438 printf("cvcamSetProperty(camera=%d,property=%s): values out of bounds\n",cameraid, property);
441 icvVideoStart(cameraid);
446 ((((VideoFormat*)value)->width == camera->description.maxwidth)&&
447 (((VideoFormat*)value)->height == camera->description.maxheight))||
448 ((((VideoFormat*)value)->width == camera->description.minwidth)&&
449 (((VideoFormat*)value)->height == camera->description.minheight))||
450 ((((VideoFormat*)value)->width == 320)&&
451 (((VideoFormat*)value)->height == 240))
454 camera->videopp.width = ((VideoFormat*)value)->width;
455 camera->videopp.height= ((VideoFormat*)value)->height;
460 ((((VideoFormat*)value)->width > 320)&&
461 ((VideoFormat*)value)->height > 240)
464 camera->videopp.width = 320;
465 camera->videopp.height= 240;
468 camera->videopp.width=
469 camera->description.minwidth;
471 camera->videopp.height=
472 camera->description.minheight;
476 camera->videopp.picture.brightness=
477 ((VideoFormat*)value)->picture.brightness;
479 camera->videopp.picture.hue=
480 ((VideoFormat*)value)->picture.hue;
482 camera->videopp.picture.colour=
483 ((VideoFormat*)value)->picture.colour;
485 camera->videopp.picture.contrast=
486 ((VideoFormat*)value)->picture.contrast ;
488 camera->videopp.picture.whiteness=
489 ((VideoFormat*)value)->picture.whiteness;
491 camera->videopp.picture.palette=
492 ((VideoFormat*)value)->picture.palette;
493 if(camera->videopp.picture.palette == VIDEO_PALETTE_YUV420P)
494 camera->imagepalette = VIDEO_PALETTE_RGB24;
496 camera->videopp.picture.depth = icvVideoFormat2Depth(camera->imagepalette);
498 if(!camera->videopp.picture.depth)
505 icvVideoStart(cameraid);
506 //fprintf(stdout,"TODO get prop video_pp\n");
508 }//IF_SETTING_PROPERTY("set_video_format")
510 IF_SETTING_PROPERTY("rectify_parameters")
512 fprintf(stdout,"TODO get prop rectify_parameters\n");
514 }//IF_SETTING_PROPERTY("rectify_parameters")
516 IF_SETTING_PROPERTY("stereo_parameters")
518 fprintf(stdout,"TODO get prop stereo_parameters\n");
520 }//IF_SETTING_PROPERTY("stereo_parameters")
522 IF_SETTING_PROPERTY("raw_image")
524 fprintf(stdout,"TODO get prop raw_image\n");
526 }//IF_SETTING_PROPERTY("raw_image")
528 IF_SETTING_PROPERTY("disparity")
530 fprintf(stdout,"TODO get prop disparity\n");
532 }//IF_SETTING_PROPERTY("disparity")
534 IF_SETTING_PROPERTY("stereo_image")
536 fprintf(stdout,"TODO get prop stereo_image\n");
538 }//IF_SETTING_PROPERTY("stereo_image")
540 IF_SETTING_PROPERTY("video_pp")
542 fprintf(stdout,"TODO get prop set_video_format\n");
544 }//IF_SETTING_PROPERTY( "video_pp" )
547 IF_SETTING_PROPERTY(CVCAM_RNDWIDTH)
549 k=icvVideoStop(cameraid);
550 camera->renderwidth = *(int*)value;
552 icvVideoStart(cameraid);
555 }//IF_SETTING_PROPERTY(CVCAM_RNDWIDTH)
557 IF_SETTING_PROPERTY(CVCAM_RNDHEIGHT)
559 k=icvVideoStop(cameraid);
560 camera->renderheight = *(int*)value;
562 icvVideoStart(cameraid);
565 }//IF_SETTING_PROPERTY(CVCAM_RNDHEIGHT)
569 ///////////////////////////////////////////////////////////////////////////////
571 /* Prepares the currently enabled cameras for work */
576 printf("cvcamInit()\n");
578 for(camera=0; camera<ncameras; camera++)
580 icvVideoInit(camera);
581 }//for(camera=0; camera<ncameras; camera++)
586 ///////////////////////////////////////////////////////////////////////////////
587 /* Start the video */
593 printf("cvcamStart()\n");
595 for(cameraid=0; cameraid<ncameras; cameraid++)
597 if(cameras[cameraid].enabled)
599 if(!icvVideoStart(cameraid))
604 }//for(cameraid=0; cameraid<ncameras; cameraid++)
609 int icvVideoStart(int cameraid)
611 CvVideoCamera *const camera = &(cameras[cameraid]);
614 pthread_mutex_lock(&(camera->capturestatemutex));
615 if(camera->capturestate != READY)
617 fprintf(stderr,"icvVideoStart: camera %d not ready\n",camera);
618 pthread_mutex_unlock(&(camera->capturestatemutex));
621 camera->capturestate = STARTING;
622 pthread_cond_signal(&(camera->capturestatecond));
623 pthread_mutex_unlock(&(camera->capturestatemutex));
625 pthread_mutex_lock(&(camera->ioctlmutex));
626 if(ioctl(camera->device, VIDIOCGMBUF,
627 &(camera->mbuf)) == -1)
629 pthread_mutex_unlock(&(camera->ioctlmutex));
632 pthread_mutex_unlock(&(camera->ioctlmutex));
634 printf("mbuf: size=%d, frames=%d, offsets=",camera->mbuf.size,
635 camera->mbuf.frames);
637 camera->memorymap = (char*)mmap(0,
639 PROT_READ|PROT_WRITE, MAP_SHARED,
643 if((int)camera->memorymap == -1)
645 fprintf(stderr, "icvVideoStart: mmap failed");
649 // acquire first frame
650 camera->vid_mmap.frame = 0;
651 camera->vid_mmap.width = camera->videopp.width;
652 camera->vid_mmap.height = camera->videopp.height;
653 camera->vid_mmap.format = camera->videopp.picture.palette;
654 camera->lastframe = 0;
656 pthread_mutex_lock(&(camera->ioctlmutex));
658 if(ioctl(camera->device, VIDIOCMCAPTURE, &(camera->vid_mmap)) < 0)
660 fprintf(stderr, "icvVideoInit: ioctl VIDIOCMCAPTURE failed \n");
663 if(ioctl(camera->device, VIDIOCSYNC, &(camera->vid_mmap.frame) ) < 0)
665 fprintf(stderr, "icvVideoInit: ioctl VIDIOCSYNC failed \n");
667 }//if ioctl(..., VIDIOCSYNK, ...)
668 pthread_mutex_unlock(&(camera->ioctlmutex));
670 assert(camera->videopp.picture.palette);
671 assert(icvVideoFormat2Depth(camera->imagepalette));
673 pthread_mutex_lock(&(camera->capturestatemutex));
674 camera->capturestate = CAPTURING;
675 pthread_cond_signal(&(camera->capturestatecond));
676 pthread_mutex_unlock(&(camera->capturestatemutex));
678 // initialize frame locks.
679 pthread_mutex_init(&(camera->lastframemutex), NULL);
680 camera->framelock = (pthread_rwlock_t *)malloc(camera->mbuf.frames *
681 sizeof(pthread_rwlock_t));
682 for(frame = 0; frame < camera->mbuf.frames; frame++)
684 pthread_rwlock_init(&(camera->framelock[frame]),NULL);
689 // start capture thread
690 if(pthread_create((&(camera->thread)),NULL,
691 icvVideoCaptureProc, (void*)cameraid))
693 fprintf(stderr, "icvVideoStart: couldn't start thread for "
694 "camera %d\n", camera);
696 }//if pthread_create ...
698 printf("started icvVideoCaptureProc thread %p from thread %p\n",
699 camera->thread, pthread_self());
705 printf("icvVideoStart: start rendering\n");
707 icvVideoRenderStart(cameraid);
713 ////////////////////////////////////////////////////////////////////////////////
714 void* icvVideoCaptureProc(void* arg)
716 int cameraid = (int) arg;
717 CvVideoCamera* const camera = &(cameras[cameraid]);
719 assert(cameras != NULL);
720 assert(cameraid>=0 && cameraid <ncameras);
721 assert(camera->mbuf.frames>0);
722 pthread_mutex_lock(&(camera->capturestatemutex));
723 while(camera->capturestate == CAPTURING)
725 pthread_mutex_unlock(&(camera->capturestatemutex));
730 // I don't need to rdlock lastframe, since I'm the one who writes it
731 //pthread_mutex_lock(&(camera->lastframemutex));
732 camera->vid_mmap.frame = (camera->lastframe + 1)%camera->mbuf.frames;
733 //pthread_mutex_unlock(&(camera->lastframemutex));
735 pthread_rwlock_wrlock(&(camera->framelock[camera->vid_mmap.frame]));
736 pthread_mutex_lock(&(camera->ioctlmutex));
737 if(ioctl(camera->device, VIDIOCMCAPTURE, &(camera->vid_mmap)) < 0)
739 fprintf(stderr, "icvVideoCaptureProc: ioctl VIDIOCMCAPTURE failed \n");
740 pthread_mutex_lock(&(camera->capturestatemutex));
741 camera->capturestate = FINISHED;
742 pthread_cond_signal(&(camera->capturestatecond));
743 pthread_mutex_unlock(&(camera->capturestatemutex));
745 if(ioctl(camera->device, VIDIOCSYNC, &(camera->vid_mmap.frame) ) < 0)
747 fprintf(stderr, "icvVideoCaptureProc: ioctl VIDIOCSYNC failed \n");
748 pthread_mutex_lock(&(camera->capturestatemutex));
749 camera->capturestate = FINISHED;
750 pthread_cond_signal(&(camera->capturestatecond));
751 pthread_mutex_unlock(&(camera->capturestatemutex));
752 }//if ioctl(..., VIDIOCSYNK, ...)
753 pthread_mutex_unlock(&(camera->ioctlmutex));
754 pthread_rwlock_unlock(&(camera->framelock[camera->vid_mmap.frame]));
755 pthread_mutex_lock(&(camera->lastframemutex));
756 camera->lastframe = camera->vid_mmap.frame;
757 pthread_mutex_unlock(&(camera->lastframemutex));
758 // if the camera is not rendered, call the callback myself
759 if (!camera->rendered && (camera->callback != NULL))
761 IplImage *image = icvVideoGetImage(cameraid);
763 camera->callback(image);
764 cvReleaseImage(&image);
766 fprintf(stderr, "icvVideoCaptureProc: icvVideoGetImage() returned NULL\n");
769 // signal that the rendering should be updated, since the image changed
770 if (camera->rendered)
772 pthread_mutex_lock(&(camera->updatedmutex));
773 if(camera->updated == 0)
775 pthread_cond_signal(&(camera->updatedcond));
778 pthread_mutex_unlock(&(camera->updatedmutex));
780 // stop here if we're paused
781 pthread_mutex_lock(&(camera->pausemutex));
782 pthread_mutex_unlock(&(camera->pausemutex));
783 pthread_mutex_lock(&(camera->capturestatemutex));
785 pthread_mutex_unlock(&(camera->capturestatemutex));
786 pthread_mutex_lock(&(camera->capturestatemutex));
787 camera->capturestate = FINISHED;
788 pthread_cond_signal(&(camera->capturestatecond));
789 pthread_mutex_unlock(&(camera->capturestatemutex));
792 ////////////////////////////////////////////////////////////////////////////////
794 /* Frees all resources */
800 printf("cvcamExit(), ncameras = %d\n",ncameras);
803 for(cameraid=0; cameraid<ncameras; cameraid++) {
804 CvVideoCamera *const camera = &(cameras[cameraid]);
805 close(camera->device);
806 pthread_mutex_destroy(&(camera->ioctlmutex));
807 pthread_mutex_destroy(&(camera->pausemutex));
808 pthread_mutex_destroy(&(camera->capturestatemutex));
809 pthread_cond_destroy(&(camera->capturestatecond));
810 for(frame=0; frame< camera->mbuf.frames; frame++)
812 pthread_rwlock_destroy(&(camera->framelock[frame]));
814 free(camera->framelock);
815 pthread_mutex_destroy(&(camera->lastframemutex));
816 pthread_cond_destroy(&(camera->updatedcond));
817 pthread_mutex_destroy(&(camera->updatedmutex));
818 camera->initialised = 0;
826 ////////////////////////////////////////////////////////////////////////////////
828 int icvVideoPauseCamera(int cameraid)
830 CvVideoCamera *const camera = &(cameras[cameraid]);
832 pthread_mutex_lock(&(camera->capturestatemutex));
833 if(!(camera->capturestate==CAPTURING))
835 pthread_mutex_unlock(&(camera->capturestatemutex));
838 pthread_mutex_unlock(&(camera->capturestatemutex));
839 // taking this lock will stop grabbing
840 if(!camera->paused) {
841 pthread_mutex_lock(&(camera->pausemutex));
846 ////////////////////////////////////////////////////////////////////////////////
848 int icvVideoResumeCamera(int cameraid)
850 CvVideoCamera *const camera = &(cameras[cameraid]);
852 pthread_mutex_lock(&(camera->capturestatemutex));
853 if(!(camera->capturestate==CAPTURING))
855 pthread_mutex_unlock(&(camera->capturestatemutex));
858 pthread_mutex_unlock(&(camera->capturestatemutex));
861 pthread_mutex_unlock(&(camera->pausemutex));
865 ////////////////////////////////////////////////////////////////////////////////
867 /* Pause the video; should be used for preventing data changes during frame reading
868 using "frame" and other properties */
874 printf("cvcamPause()\n");
876 for(i=0; i<ncameras; i++)
878 icvVideoPauseCamera(i);
885 ////////////////////////////////////////////////////////////////////////////////
887 /* Resume the video */
893 printf("cvcamResume()\n");
895 for(i=0; i<ncameras; i++)
897 icvVideoResumeCamera(i);
903 ////////////////////////////////////////////////////////////////////////////////
905 int icvVideoInit(int cameraid)
907 struct video_channel Channel;
908 struct video_capability VidCap;
909 CvVideoCamera *const camera = &(cameras[cameraid]);
912 printf("icvVideoInit(%d)\n",cameraid);
916 if(camera->initialised)
919 fprintf(stderr, "icvVideoInit:camera %d is already "
920 "initialized\n",camera);*/
926 pthread_mutex_lock(&(camera->ioctlmutex));
927 if(ioctl(camera->device,VIDIOCSPICT,
928 &(camera->videopp.picture) )==-1)
930 pthread_mutex_unlock(&(camera->ioctlmutex));
931 fprintf(stdout, "icvVideoInit: ioctl VIDIOCSPICT failed\n");
932 fprintf(stdout,"camera=%d,brightness=%d,hue=%d,colour=%d,contrast=%d,whiteness=%d,depth=%d,palette=%d\n",
934 camera->videopp.picture.brightness,
935 camera->videopp.picture.hue,
936 camera->videopp.picture.colour,
937 camera->videopp.picture.contrast,camera->videopp.picture.whiteness,camera->videopp.picture.depth,camera->videopp.picture.palette);
940 pthread_mutex_unlock(&(camera->ioctlmutex));
943 Channel.channel = camera->channel;
944 pthread_mutex_lock(&(camera->ioctlmutex));
945 if((ioctl(camera->device,VIDIOCSCHAN, &Channel) == -1)||
946 (ioctl(camera->device, VIDIOCGCAP, &VidCap)==-1))
949 "icvVideoInit: ioctl VIDIOCSCHAN or VIDIOCGCAP failed\n");
950 pthread_mutex_unlock(&(camera->ioctlmutex));
953 pthread_mutex_unlock(&(camera->ioctlmutex));
955 pthread_mutex_lock(&(camera->ioctlmutex));
956 if(ioctl(camera->device, VIDIOCGMBUF,
957 &(camera->mbuf)) == -1)
959 pthread_mutex_unlock(&(camera->ioctlmutex));
960 fprintf(stdout, "icvVideoInit: ioctl VIDIOCGMBUF failed\n");
963 pthread_mutex_unlock(&(camera->ioctlmutex));
965 pthread_mutex_lock(&(camera->ioctlmutex));
966 if(ioctl(camera->device,
967 VIDIOCSCHAN, &Channel)==-1)
969 fprintf(stderr, "icvVideoInit: couldn't set channel %d",
971 pthread_mutex_unlock(&(camera->ioctlmutex));
974 pthread_mutex_unlock(&(camera->ioctlmutex));
976 camera->initialised = 1;
977 pthread_mutex_lock(&(camera->capturestatemutex));
978 camera->capturestate = READY;
979 pthread_cond_signal(&(camera->capturestatecond));
980 pthread_mutex_unlock(&(camera->capturestatemutex));
982 }//if(camera->IsEnabled)
985 ////////////////////////////////////////////////////////////
987 int icvVideoStop(int cameraid)
990 CvVideoCamera *const camera = &(cameras[cameraid]);
993 printf("icvVideoStop(%d)\n",cameraid);
995 pthread_mutex_lock(&(camera->capturestatemutex));
996 if(camera->capturestate != CAPTURING)
999 printf("icvVideoStop: not capturing (state=%d), returning 0\n",camera->capturestate);
1001 pthread_mutex_unlock(&(camera->capturestatemutex));
1004 camera->capturestate = STOPPING;
1005 pthread_cond_signal(&(camera->capturestatecond));
1006 pthread_mutex_unlock(&(camera->capturestatemutex));
1008 icvVideoResumeCamera(cameraid);
1010 pthread_mutex_lock(&(camera->capturestatemutex));
1011 // wait for the end of capture proc
1012 while (camera->capturestate != FINISHED )
1014 pthread_cond_wait(&(camera->capturestatecond),&(camera->capturestatemutex));
1016 // wait for the end of rendering
1017 while (camera->renderstate)
1019 // the rendering loop may be waiting for an update
1020 pthread_mutex_lock(&(camera->updatedmutex));
1021 camera->updated = 1;
1022 pthread_cond_signal(&(camera->updatedcond));
1023 pthread_mutex_unlock(&(camera->updatedmutex));
1024 pthread_cond_wait(&(camera->capturestatecond),&(camera->capturestatemutex));
1026 pthread_mutex_unlock(&(camera->capturestatemutex));
1028 munmap(camera->memorymap,
1031 pthread_mutex_lock(&(camera->capturestatemutex));
1032 camera->capturestate = READY;
1033 pthread_cond_signal(&(camera->capturestatecond));
1034 pthread_mutex_unlock(&(camera->capturestatemutex));
1036 printf("icvVideoStop: returning 1\n",camera->capturestate);
1040 //////////////////////////////////////////////////////////////////
1042 /* Stop the video */
1047 printf("cvcamStop()\n");
1049 for(camera=0; camera<ncameras; camera++)
1051 icvVideoStop(camera);
1052 }//for(camera=0; camera<ncameras; camera++)
1055 ////////////////////////////////////////////////////////////////////////////////
1057 ////////////////////////////////////////////////////////////////////////////////
1058 int icvVideoFormat2Depth(int format)
1062 case VIDEO_PALETTE_RGB24:
1065 case VIDEO_PALETTE_RGB32:
1068 case VIDEO_PALETTE_RGB565:
1071 case VIDEO_PALETTE_RGB555:
1078 ////////////////////////////////////////////////////////////////////////////////
1079 ////////////////////////////////////////////////////////////////////////////////
1080 int icvVideoSetDefaultValues(int cameraid, int device, int channel,
1081 struct video_capability VidCap)
1083 CvVideoCamera *const camera = &(cameras[cameraid]);
1085 camera->device = device;
1086 camera->channel = channel;
1087 camera->description.channel = channel;
1088 pthread_mutex_init(&(camera->ioctlmutex), NULL);
1089 camera->enabled = 0;
1090 camera->rendered = 0;
1091 camera->initialised = 0;
1093 pthread_mutex_init(&(camera->pausemutex), NULL);
1094 pthread_mutex_init(&(camera->capturestatemutex), NULL);
1095 pthread_cond_init(&(camera->capturestatecond), NULL);
1096 camera->capturestate = FINISHED;
1097 camera->memorymap = NULL;
1098 camera->renderstate = 0;
1099 pthread_mutex_init(&(camera->updatedmutex), NULL);
1100 pthread_cond_init(&(camera->updatedcond), NULL);
1101 camera->updated = 0;
1102 camera->videopp.picture.palette = VIDEO_PALETTE_RGB24;
1103 camera->imagepalette = VIDEO_PALETTE_RGB24;
1105 camera->description.maxwidth = VidCap.maxwidth;
1107 camera->description.maxheight = VidCap.maxheight;
1109 camera->description.minwidth = VidCap.minwidth;
1111 if(camera->description.minwidth<160)
1112 camera->description.minwidth = 160;
1114 camera->description.minheight = VidCap.minheight;
1116 if(camera->description.minheight<120)
1117 camera->description.minheight = 120;
1119 if(ioctl(device,VIDIOCGPICT,
1120 &(camera->videopp.picture) )==-1)
1123 camera->videopp.picture.palette = VIDEO_PALETTE_RGB24;
1124 camera->imagepalette = VIDEO_PALETTE_RGB24;
1125 camera->videopp.width = camera->description.maxwidth;
1127 camera->videopp.height = camera->description.maxheight;
1128 camera->videopp.picture.depth = 24;
1129 camera->videopp.picture.brightness = 30000;
1130 camera->videopp.picture.hue = 30000;
1131 camera->videopp.picture.colour = 30000;
1132 camera->videopp.picture.contrast = 30000;
1133 camera->videopp.picture.whiteness = 30000;
1134 camera->callback = NULL;
1136 camera->renderwidth = 0;
1137 camera->renderheight = 0;
1139 if(ioctl(device,VIDIOCSPICT,
1140 &(camera->videopp.picture) )==-1)
1143 fprintf(stdout, "icvSetDefaultValues: ioctl VIDIOCSPICT failed, trying YUV420P format\n");
1145 camera->videopp.picture.palette = VIDEO_PALETTE_YUV420P;
1146 if(ioctl(device,VIDIOCSPICT,
1147 &(camera->videopp.picture) )==-1)
1149 fprintf(stdout, "icvSetDefaultValues: ioctl VIDIOCSPICT failed even in YUV420P format\n");
1151 fprintf(stdout,"camera=%d,brightness=%d,hue=%d,colour=%d,contrast=%d,whiteness=%d,depth=%d,palette=%d\n",
1153 camera->videopp.picture.brightness,
1154 camera->videopp.picture.hue,
1155 camera->videopp.picture.colour,
1156 camera->videopp.picture.contrast,
1157 camera->videopp.picture.whiteness,
1158 camera->videopp.picture.depth,
1159 camera->videopp.picture.palette);
1165 fprintf(stdout,"OK! camera=%d,brightness=%d,hue=%d,colour=%d,contrast=%d,whiteness=%d,depth=%d,palette=%d\n",
1167 camera->videopp.picture.brightness,
1168 camera->videopp.picture.hue,
1169 camera->videopp.picture.colour,
1170 camera->videopp.picture.contrast,camera->videopp.picture.whiteness,camera->videopp.picture.depth,camera->videopp.picture.palette);
1175 /**********************************************************************
1177 * Color correction functions
1179 **********************************************************************/
1182 * Turn a YUV4:2:0 block into an RGB block
1184 * Video4Linux seems to use the blue, green, red channel
1185 * order convention-- rgb[0] is blue, rgb[1] is green, rgb[2] is red.
1187 * Color space conversion coefficients taken from the excellent
1188 * http://www.inforamp.net/~poynton/ColorFAQ.html
1189 * In his terminology, this is a CCIR 601.1 YCbCr -> RGB.
1190 * Y values are given for all 4 pixels, but the U (Pb)
1191 * and V (Pr) are assumed constant over the 2x2 block.
1193 * To avoid floating point arithmetic, the color conversion
1194 * coefficients are scaled into 16.16 fixed-point integers.
1195 * They were determined as follows:
1197 * double brightness = 1.0; (0->black; 1->full scale)
1198 * double saturation = 1.0; (0->greyscale; 1->full color)
1199 * double fixScale = brightness * 256 * 256;
1200 * int rvScale = (int)(1.402 * saturation * fixScale);
1201 * int guScale = (int)(-0.344136 * saturation * fixScale);
1202 * int gvScale = (int)(-0.714136 * saturation * fixScale);
1203 * int buScale = (int)(1.772 * saturation * fixScale);
1204 * int yScale = (int)(fixScale);
1207 /* LIMIT: convert a 16.16 fixed-point value to a byte, with clipping. */
1208 #define LIMIT(x) ((x)>0xffffff?0xff: ((x)<=0xffff?0:((x)>>16)))
1211 move_420_block(int yTL, int yTR, int yBL, int yBR, int u, int v,
1212 int rowPixels, unsigned char * rgb, int bits)
1214 const int rvScale = 91881;
1215 const int guScale = -22553;
1216 const int gvScale = -46801;
1217 const int buScale = 116129;
1218 const int yScale = 65536;
1221 g = guScale * u + gvScale * v;
1230 yTL *= yScale; yTR *= yScale;
1231 yBL *= yScale; yBR *= yScale;
1234 /* Write out top two pixels */
1235 rgb[0] = LIMIT(b+yTL); rgb[1] = LIMIT(g+yTL);
1236 rgb[2] = LIMIT(r+yTL);
1238 rgb[3] = LIMIT(b+yTR); rgb[4] = LIMIT(g+yTR);
1239 rgb[5] = LIMIT(r+yTR);
1241 /* Skip down to next line to write out bottom two pixels */
1242 rgb += 3 * rowPixels;
1243 rgb[0] = LIMIT(b+yBL); rgb[1] = LIMIT(g+yBL);
1244 rgb[2] = LIMIT(r+yBL);
1246 rgb[3] = LIMIT(b+yBR); rgb[4] = LIMIT(g+yBR);
1247 rgb[5] = LIMIT(r+yBR);
1248 } else if (bits == 16) {
1249 /* Write out top two pixels */
1250 rgb[0] = ((LIMIT(b+yTL) >> 3) & 0x1F)
1251 | ((LIMIT(g+yTL) << 3) & 0xE0);
1252 rgb[1] = ((LIMIT(g+yTL) >> 5) & 0x07)
1253 | (LIMIT(r+yTL) & 0xF8);
1255 rgb[2] = ((LIMIT(b+yTR) >> 3) & 0x1F)
1256 | ((LIMIT(g+yTR) << 3) & 0xE0);
1257 rgb[3] = ((LIMIT(g+yTR) >> 5) & 0x07)
1258 | (LIMIT(r+yTR) & 0xF8);
1260 /* Skip down to next line to write out bottom two pixels */
1261 rgb += 2 * rowPixels;
1263 rgb[0] = ((LIMIT(b+yBL) >> 3) & 0x1F)
1264 | ((LIMIT(g+yBL) << 3) & 0xE0);
1265 rgb[1] = ((LIMIT(g+yBL) >> 5) & 0x07)
1266 | (LIMIT(r+yBL) & 0xF8);
1268 rgb[2] = ((LIMIT(b+yBR) >> 3) & 0x1F)
1269 | ((LIMIT(g+yBR) << 3) & 0xE0);
1270 rgb[3] = ((LIMIT(g+yBR) >> 5) & 0x07)
1271 | (LIMIT(r+yBR) & 0xF8);
1275 /* Converts from planar YUV420 to RGB24. */
1277 yuv420p_to_rgb(int width, int height,
1278 unsigned char *pIn0, unsigned char *pOut0, int bits)
1280 const int numpix = width * height;
1281 const int bytes = bits >> 3;
1282 int i, j, y00, y01, y10, y11, u, v;
1283 unsigned char *pY = pIn0;
1284 unsigned char *pU = pY + numpix;
1285 unsigned char *pV = pU + numpix / 4;
1286 unsigned char *pOut = pOut0;
1288 for (j = 0; j <= height - 2; j += 2) {
1289 for (i = 0; i <= width - 2; i += 2) {
1292 y10 = *(pY + width);
1293 y11 = *(pY + width + 1);
1297 move_420_block(y00, y01, y10, y11, u, v,
1305 pOut += width * bytes;
1310 // allocates a nes iplimage containing the last grabbed image.
1311 // Can be called from the main thread or the render thread, via
1312 // GetProperty("raw_image"), or from the capturing thread, via
1315 icvVideoGetImage(int cameraid)
1318 CvVideoCamera *const camera = &(cameras[cameraid]);
1322 int depth = icvVideoFormat2Depth(camera->imagepalette);
1324 pthread_mutex_lock(&(camera->capturestatemutex));
1325 if(!(camera->capturestate==CAPTURING))
1327 pthread_mutex_unlock(&(camera->capturestatemutex));
1330 pthread_mutex_unlock(&(camera->capturestatemutex));
1331 size.width = camera->videopp.width;
1332 size.height = camera->videopp.height;
1334 assert(camera->videopp.picture.palette);
1335 assert(icvVideoFormat2Depth(camera->imagepalette));
1337 image = cvCreateImageHeader(size,IPL_DEPTH_8U,depth/8);
1338 pthread_mutex_lock(&(camera->lastframemutex));
1339 lastframe = camera->lastframe;
1340 pthread_mutex_unlock(&(camera->lastframemutex));
1341 pthread_rwlock_rdlock(&(camera->framelock[lastframe]));
1342 if (camera->imagepalette == camera->videopp.picture.palette)
1344 IplImage *buffer = cvCreateImageHeader(size,IPL_DEPTH_8U,depth/8);
1345 cvSetImageData(buffer,
1346 (void*)(camera->memorymap+
1347 camera->mbuf.offsets[camera->lastframe]),
1348 size.width*(depth/8));
1349 cvCreateImageData(image);
1350 cvCopyImage(buffer, image);
1351 pthread_rwlock_unlock(&(camera->framelock[lastframe]));
1352 cvReleaseImageHeader(&buffer);
1355 // only one conversion is implemented, for now
1356 assert(camera->videopp.picture.palette == VIDEO_PALETTE_YUV420P);
1357 assert((camera->imagepalette == VIDEO_PALETTE_RGB24) ||
1358 (camera->imagepalette == VIDEO_PALETTE_RGB565));
1360 data = (void*)cvAlloc(size.width*size.height*(depth/8));
1361 cvSetImageData(image, data, size.width*(depth/8));
1362 yuv420p_to_rgb(camera->videopp.width,
1363 camera->videopp.height,
1364 (unsigned char*)(camera->memorymap+
1365 camera->mbuf.offsets[camera->lastframe]),
1366 (unsigned char*)(data),
1368 pthread_rwlock_unlock(&(camera->framelock[lastframe]));
1372 //Stubs for avi files
1374 /*Plays a specified avi file into a specified window
1375 if file is NULL, file browser is opened. if window is 0,
1376 it is created. width and height mean output size's 0 means
1377 those of avi file are used. __cdecl (*callback)(IplImage*) would be
1378 called on every frame. NULL means no callback*/
1379 CVCAM_API int cvcamPlayAVI(const char* file,
1390 /*Advanced API for dealing with AVI files*/
1395 /*Opens a given file or pops up a dialog if file is NULL
1396 returns a handle to the file opened for success or -1 for failure*/
1397 CVCAM_API cvcamAVIFILE cvcamAVIOpenFile(char* file)
1399 return (cvcamAVIFILE)-1;
1402 /*The next functions just do what they say and return 0
1403 for success, anything other for failure*/
1405 CVCAM_API int cvcamAVICloseFile(cvcamAVIFILE file)
1410 CVCAM_API int cvcamAVISetWindow(cvcamAVIFILE file, void* window)
1415 CVCAM_API int cvcamAVISetCallback(cvcamAVIFILE file, void* callback)
1420 CVCAM_API int cvcamAVISetSize(cvcamAVIFILE file, int width, int height)
1425 CVCAM_API int cvcamAVIRun(cvcamAVIFILE file)
1430 CVCAM_API int cvcamAVIStop(cvcamAVIFILE file)
1435 CVCAM_API int cvcamAVIPause(cvcamAVIFILE file)
1440 CVCAM_API int cvcamAVIResume(cvcamAVIFILE file)
1445 CVCAM_API int cvcamAVIWaitCompletion(cvcamAVIFILE file)
1450 CVCAM_API int cvcamAVIIsRunning(cvcamAVIFILE file)