1 ////////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
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.
8 //
9 //
10 //                        Intel License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
15 //
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
18 //
19 //   * Redistribution's of source code must retain the above copyright notice,
20 //     this list of conditions and the following disclaimer.
21 //
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.
25 //
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.
28 //
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.
39 //
40 //
41 
42 //
43 // The code has been contributed by Justin G. Eskesen on 2010 Jan
44 //
45 
46 #include "precomp.hpp"
47 
48 #ifdef HAVE_PVAPI
49 #if !defined WIN32 && !defined _WIN32 && !defined _LINUX
50 #define _LINUX
51 #endif
52 
53 #if defined(_x64) || defined (__x86_64) || defined (_M_X64)
54 #define _x64 1
55 #elif defined(_x86) || defined(__i386) || defined (_M_IX86)
56 #define _x86 1
57 #endif
58 
59 #include <PvApi.h>
60 #ifdef WIN32
61 #  include <io.h>
62 #else
63 #  include <time.h>
64 #  include <unistd.h>
65 #endif
66 
67 //#include <arpa/inet.h>
68 
69 #define MAX_CAMERAS 10
70 
71 /********************* Capturing video from camera via PvAPI *********************/
72 
73 class CvCaptureCAM_PvAPI : public CvCapture
74 {
75 public:
76     CvCaptureCAM_PvAPI();
~CvCaptureCAM_PvAPI()77     virtual ~CvCaptureCAM_PvAPI()
78     {
79         close();
80     }
81 
82     virtual bool open( int index );
83     virtual void close();
84     virtual double getProperty(int) const;
85     virtual bool setProperty(int, double);
86     virtual bool grabFrame();
87     virtual IplImage* retrieveFrame(int);
getCaptureDomain()88     virtual int getCaptureDomain()
89     {
90         return CV_CAP_PVAPI;
91     }
92 
93 protected:
94 #ifndef WIN32
95     virtual void Sleep(unsigned int time);
96 #endif
97 
98     void stopCapture();
99     bool startCapture();
100     bool resizeCaptureFrame (int frameWidth, int frameHeight);
101 
102     typedef struct
103     {
104         unsigned long   UID;
105         tPvHandle       Handle;
106         tPvFrame        Frame;
107     } tCamera;
108 
109     IplImage *frame;
110     tCamera  Camera;
111     tPvErr   Errcode;
112 };
113 
114 
CvCaptureCAM_PvAPI()115 CvCaptureCAM_PvAPI::CvCaptureCAM_PvAPI()
116 {
117     frame = NULL;
118     memset(&this->Camera, 0, sizeof(this->Camera));
119 }
120 
121 #ifndef WIN32
Sleep(unsigned int time)122 void CvCaptureCAM_PvAPI::Sleep(unsigned int time)
123 {
124     struct timespec t,r;
125 
126     t.tv_sec    = time / 1000;
127     t.tv_nsec   = (time % 1000) * 1000000;
128 
129     while(nanosleep(&t,&r)==-1)
130         t = r;
131 }
132 #endif
133 
close()134 void CvCaptureCAM_PvAPI::close()
135 {
136     // Stop the acquisition & free the camera
137     stopCapture();
138     PvCameraClose(Camera.Handle);
139     PvUnInitialize();
140 }
141 
142 // Initialize camera input
open(int index)143 bool CvCaptureCAM_PvAPI::open( int index )
144 {
145     tPvCameraInfo cameraList[MAX_CAMERAS];
146 
147     tPvCameraInfo  camInfo;
148     tPvIpSettings ipSettings;
149 
150 
151     if (PvInitialize()) {
152     }
153     //return false;
154 
155     Sleep(1000);
156 
157     //close();
158 
159     int numCameras=PvCameraList(cameraList, MAX_CAMERAS, NULL);
160 
161     if (numCameras <= 0 || index >= numCameras)
162         return false;
163 
164     Camera.UID = cameraList[index].UniqueId;
165 
166     if (!PvCameraInfo(Camera.UID,&camInfo) && !PvCameraIpSettingsGet(Camera.UID,&ipSettings))
167     {
168         /*
169         struct in_addr addr;
170         addr.s_addr = ipSettings.CurrentIpAddress;
171         printf("Current address:\t%s\n",inet_ntoa(addr));
172         addr.s_addr = ipSettings.CurrentIpSubnet;
173         printf("Current subnet:\t\t%s\n",inet_ntoa(addr));
174         addr.s_addr = ipSettings.CurrentIpGateway;
175         printf("Current gateway:\t%s\n",inet_ntoa(addr));
176         */
177     }
178     else
179     {
180         fprintf(stderr,"ERROR: could not retrieve camera IP settings.\n");
181         return false;
182     }
183 
184 
185     if (PvCameraOpen(Camera.UID, ePvAccessMaster, &(Camera.Handle))==ePvErrSuccess)
186     {
187         tPvUint32 frameWidth, frameHeight;
188         unsigned long maxSize;
189 
190         PvAttrUint32Get(Camera.Handle, "Width", &frameWidth);
191         PvAttrUint32Get(Camera.Handle, "Height", &frameHeight);
192 
193         // Determine the maximum packet size supported by the system (ethernet adapter)
194         // and then configure the camera to use this value.  If the system's NIC only supports
195         // an MTU of 1500 or lower, this will automatically configure an MTU of 1500.
196         // 8228 is the optimal size described by the API in order to enable jumbo frames
197 
198         maxSize = 8228;
199         //PvAttrUint32Get(Camera.Handle,"PacketSize",&maxSize);
200         if (PvCaptureAdjustPacketSize(Camera.Handle,maxSize)!=ePvErrSuccess)
201             return false;
202 
203         resizeCaptureFrame(frameWidth, frameHeight);
204 
205         return startCapture();
206 
207     }
208     fprintf(stderr,"Error cannot open camera\n");
209     return false;
210 
211 }
212 
grabFrame()213 bool CvCaptureCAM_PvAPI::grabFrame()
214 {
215     //if(Camera.Frame.Status != ePvErrUnplugged && Camera.Frame.Status != ePvErrCancelled)
216     return PvCaptureQueueFrame(Camera.Handle, &(Camera.Frame), NULL) == ePvErrSuccess;
217 }
218 
219 
retrieveFrame(int)220 IplImage* CvCaptureCAM_PvAPI::retrieveFrame(int)
221 {
222     if (PvCaptureWaitForFrameDone(Camera.Handle, &(Camera.Frame), 1000) == ePvErrSuccess)
223     {
224         return frame;
225     }
226     else return NULL;
227 }
228 
getProperty(int property_id) const229 double CvCaptureCAM_PvAPI::getProperty( int property_id ) const
230 {
231     tPvUint32 nTemp;
232 
233     switch ( property_id )
234     {
235     case CV_CAP_PROP_FRAME_WIDTH:
236         PvAttrUint32Get(Camera.Handle, "Width", &nTemp);
237         return (double)nTemp;
238     case CV_CAP_PROP_FRAME_HEIGHT:
239         PvAttrUint32Get(Camera.Handle, "Height", &nTemp);
240         return (double)nTemp;
241     case CV_CAP_PROP_EXPOSURE:
242         PvAttrUint32Get(Camera.Handle,"ExposureValue",&nTemp);
243         return (double)nTemp;
244     case CV_CAP_PROP_FPS:
245         tPvFloat32 nfTemp;
246         PvAttrFloat32Get(Camera.Handle, "StatFrameRate", &nfTemp);
247         return (double)nfTemp;
248     case CV_CAP_PROP_PVAPI_MULTICASTIP:
249         char mEnable[2];
250         char mIp[11];
251         PvAttrEnumGet(Camera.Handle,"MulticastEnable",mEnable,sizeof(mEnable),NULL);
252         if (strcmp(mEnable, "Off") == 0)
253         {
254             return -1;
255         }
256         else
257         {
258             long int ip;
259             int a,b,c,d;
260             PvAttrStringGet(Camera.Handle, "MulticastIPAddress",mIp,sizeof(mIp),NULL);
261             sscanf(mIp, "%d.%d.%d.%d", &a, &b, &c, &d); ip = ((a*256 + b)*256 + c)*256 + d;
262             return (double)ip;
263         }
264     case CV_CAP_PROP_GAIN:
265         PvAttrUint32Get(Camera.Handle, "GainValue", &nTemp);
266         return (double)nTemp;
267     case CV_CAP_PROP_PVAPI_FRAMESTARTTRIGGERMODE:
268         char triggerMode[256];
269         PvAttrEnumGet(Camera.Handle, "FrameStartTriggerMode", triggerMode, 256, NULL);
270         if (strcmp(triggerMode, "Freerun")==0)
271             return 0.0;
272         else if (strcmp(triggerMode, "SyncIn1")==0)
273             return 1.0;
274         else if (strcmp(triggerMode, "SyncIn2")==0)
275             return 2.0;
276         else if (strcmp(triggerMode, "FixedRate")==0)
277             return 3.0;
278         else if (strcmp(triggerMode, "Software")==0)
279             return 4.0;
280         else
281             return -1.0;
282     case CV_CAP_PROP_PVAPI_DECIMATIONHORIZONTAL:
283         PvAttrUint32Get(Camera.Handle, "DecimationHorizontal", &nTemp);
284         return (double)nTemp;
285     case CV_CAP_PROP_PVAPI_DECIMATIONVERTICAL:
286         PvAttrUint32Get(Camera.Handle, "DecimationVertical", &nTemp);
287         return (double)nTemp;
288     case CV_CAP_PROP_PVAPI_BINNINGX:
289         PvAttrUint32Get(Camera.Handle,"BinningX",&nTemp);
290         return (double)nTemp;
291     case CV_CAP_PROP_PVAPI_BINNINGY:
292         PvAttrUint32Get(Camera.Handle,"BinningY",&nTemp);
293         return (double)nTemp;
294     case CV_CAP_PROP_PVAPI_PIXELFORMAT:
295         char pixelFormat[256];
296         PvAttrEnumGet(Camera.Handle, "PixelFormat", pixelFormat,256,NULL);
297         if (strcmp(pixelFormat, "Mono8")==0)
298             return 1.0;
299         else if (strcmp(pixelFormat, "Mono16")==0)
300             return 2.0;
301         else if (strcmp(pixelFormat, "Bayer8")==0)
302             return 3.0;
303         else if (strcmp(pixelFormat, "Bayer16")==0)
304             return 4.0;
305         else if (strcmp(pixelFormat, "Rgb24")==0)
306             return 5.0;
307         else if (strcmp(pixelFormat, "Bgr24")==0)
308             return 6.0;
309         else if (strcmp(pixelFormat, "Rgba32")==0)
310             return 7.0;
311         else if (strcmp(pixelFormat, "Bgra32")==0)
312             return 8.0;
313     }
314     return -1.0;
315 }
316 
setProperty(int property_id,double value)317 bool CvCaptureCAM_PvAPI::setProperty( int property_id, double value )
318 {
319     tPvErr error;
320 
321     switch ( property_id )
322     {
323     case CV_CAP_PROP_FRAME_WIDTH:
324     {
325         tPvUint32 currHeight;
326 
327         PvAttrUint32Get(Camera.Handle, "Height", &currHeight);
328 
329         stopCapture();
330         // Reallocate Frames
331         if (!resizeCaptureFrame(value, currHeight))
332         {
333             startCapture();
334             return false;
335         }
336 
337         startCapture();
338 
339         break;
340     }
341     case CV_CAP_PROP_FRAME_HEIGHT:
342     {
343         tPvUint32 currWidth;
344 
345         PvAttrUint32Get(Camera.Handle, "Width", &currWidth);
346 
347         stopCapture();
348 
349         // Reallocate Frames
350         if (!resizeCaptureFrame(currWidth, value))
351         {
352             startCapture();
353             return false;
354         }
355 
356         startCapture();
357 
358         break;
359     }
360     case CV_CAP_PROP_EXPOSURE:
361         if ((PvAttrUint32Set(Camera.Handle,"ExposureValue",(tPvUint32)value)==ePvErrSuccess))
362             break;
363         else
364             return false;
365     case CV_CAP_PROP_PVAPI_MULTICASTIP:
366         if (value==-1)
367         {
368             if ((PvAttrEnumSet(Camera.Handle,"MulticastEnable", "Off")==ePvErrSuccess))
369                 break;
370             else
371                 return false;
372         }
373         else
374         {
375             cv::String ip=cv::format("%d.%d.%d.%d", ((unsigned int)value>>24)&255, ((unsigned int)value>>16)&255, ((unsigned int)value>>8)&255, (unsigned int)value&255);
376             if ((PvAttrEnumSet(Camera.Handle,"MulticastEnable", "On")==ePvErrSuccess) &&
377                 (PvAttrStringSet(Camera.Handle, "MulticastIPAddress", ip.c_str())==ePvErrSuccess))
378                 break;
379             else
380                 return false;
381         }
382     case CV_CAP_PROP_GAIN:
383         if (PvAttrUint32Set(Camera.Handle,"GainValue",(tPvUint32)value)!=ePvErrSuccess)
384         {
385             return false;
386         }
387         break;
388     case CV_CAP_PROP_PVAPI_FRAMESTARTTRIGGERMODE:
389         if (value==0)
390             error = PvAttrEnumSet(Camera.Handle, "FrameStartTriggerMode", "Freerun");
391         else if (value==1)
392             error = PvAttrEnumSet(Camera.Handle, "FrameStartTriggerMode", "SyncIn1");
393         else if (value==2)
394             error = PvAttrEnumSet(Camera.Handle, "FrameStartTriggerMode", "SyncIn2");
395         else if (value==3)
396             error = PvAttrEnumSet(Camera.Handle, "FrameStartTriggerMode", "FixedRate");
397         else if (value==4)
398             error = PvAttrEnumSet(Camera.Handle, "FrameStartTriggerMode", "Software");
399         else
400             error = ePvErrOutOfRange;
401         if(error==ePvErrSuccess)
402             break;
403         else
404             return false;
405     case CV_CAP_PROP_PVAPI_DECIMATIONHORIZONTAL:
406         if (value >= 1 && value <= 8)
407             error = PvAttrUint32Set(Camera.Handle, "DecimationHorizontal", value);
408         else
409             error = ePvErrOutOfRange;
410         if(error==ePvErrSuccess)
411             break;
412         else
413             return false;
414     case CV_CAP_PROP_PVAPI_DECIMATIONVERTICAL:
415         if (value >= 1 && value <= 8)
416             error = PvAttrUint32Set(Camera.Handle, "DecimationVertical", value);
417         else
418             error = ePvErrOutOfRange;
419         if(error==ePvErrSuccess)
420             break;
421         else
422             return false;
423     case CV_CAP_PROP_PVAPI_BINNINGX:
424         error = PvAttrUint32Set(Camera.Handle, "BinningX", value);
425         if(error==ePvErrSuccess)
426             break;
427         else
428             return false;
429     case CV_CAP_PROP_PVAPI_BINNINGY:
430         error = PvAttrUint32Set(Camera.Handle, "BinningY", value);
431         if(error==ePvErrSuccess)
432             break;
433         else
434             return false;
435     case CV_CAP_PROP_PVAPI_PIXELFORMAT:
436         {
437             cv::String pixelFormat;
438 
439             if (value==1)
440                 pixelFormat = "Mono8";
441             else if (value==2)
442                 pixelFormat = "Mono16";
443             else if (value==3)
444                 pixelFormat = "Bayer8";
445             else if (value==4)
446                 pixelFormat = "Bayer16";
447             else if (value==5)
448                 pixelFormat = "Rgb24";
449             else if (value==6)
450                 pixelFormat = "Bgr24";
451             else if (value==7)
452                 pixelFormat = "Rgba32";
453             else if (value==8)
454                 pixelFormat = "Bgra32";
455             else
456                 return false;
457 
458             if ((PvAttrEnumSet(Camera.Handle,"PixelFormat", pixelFormat.c_str())==ePvErrSuccess))
459             {
460                 tPvUint32 currWidth;
461                 tPvUint32 currHeight;
462 
463                 PvAttrUint32Get(Camera.Handle, "Width", &currWidth);
464                 PvAttrUint32Get(Camera.Handle, "Height", &currHeight);
465 
466                 stopCapture();
467                 // Reallocate Frames
468                 if (!resizeCaptureFrame(currWidth, currHeight))
469                 {
470                     startCapture();
471                     return false;
472                 }
473 
474                 startCapture();
475                 return true;
476             }
477             else
478                 return false;
479         }
480     default:
481         return false;
482     }
483     return true;
484 }
485 
stopCapture()486 void CvCaptureCAM_PvAPI::stopCapture()
487 {
488     PvCommandRun(Camera.Handle, "AcquisitionStop");
489     PvCaptureEnd(Camera.Handle);
490 }
491 
startCapture()492 bool CvCaptureCAM_PvAPI::startCapture()
493 {
494     // Start the camera
495     PvCaptureStart(Camera.Handle);
496 
497     // Set the camera to capture continuously
498     if(PvAttrEnumSet(Camera.Handle, "AcquisitionMode", "Continuous")!= ePvErrSuccess)
499     {
500         fprintf(stderr,"Could not set PvAPI Acquisition Mode\n");
501         return false;
502     }
503 
504     if(PvCommandRun(Camera.Handle, "AcquisitionStart")!= ePvErrSuccess)
505     {
506         fprintf(stderr,"Could not start PvAPI acquisition\n");
507         return false;
508     }
509 
510     if(PvAttrEnumSet(Camera.Handle, "FrameStartTriggerMode", "Freerun")!= ePvErrSuccess)
511     {
512         fprintf(stderr,"Error setting PvAPI trigger to \"Freerun\"");
513         return false;
514     }
515 
516     return true;
517 }
518 
resizeCaptureFrame(int frameWidth,int frameHeight)519 bool CvCaptureCAM_PvAPI::resizeCaptureFrame (int frameWidth, int frameHeight)
520 {
521     char pixelFormat[256];
522     tPvUint32 frameSize;
523     tPvUint32 sensorHeight;
524     tPvUint32 sensorWidth;
525 
526     if (frame)
527     {
528         cvReleaseImage(&frame);
529         frame = NULL;
530     }
531 
532     if (PvAttrUint32Get(Camera.Handle, "SensorWidth", &sensorWidth) != ePvErrSuccess)
533     {
534         return false;
535     }
536 
537     if (PvAttrUint32Get(Camera.Handle, "SensorHeight", &sensorHeight) != ePvErrSuccess)
538     {
539         return false;
540     }
541 
542     // Cap out of bounds widths to the max supported by the sensor
543     if ((frameWidth < 0) || ((tPvUint32)frameWidth > sensorWidth))
544     {
545         frameWidth = sensorWidth;
546     }
547 
548     if ((frameHeight < 0) || ((tPvUint32)frameHeight > sensorHeight))
549     {
550         frameHeight = sensorHeight;
551     }
552 
553 
554     if (PvAttrUint32Set(Camera.Handle, "Height", frameHeight) != ePvErrSuccess)
555     {
556         return false;
557     }
558 
559     if (PvAttrUint32Set(Camera.Handle, "Width", frameWidth) != ePvErrSuccess)
560     {
561         return false;
562     }
563 
564     PvAttrEnumGet(Camera.Handle, "PixelFormat", pixelFormat,256,NULL);
565     PvAttrUint32Get(Camera.Handle, "TotalBytesPerFrame", &frameSize);
566 
567 
568     if ( (strcmp(pixelFormat, "Mono8")==0) || (strcmp(pixelFormat, "Bayer8")==0) )
569     {
570         frame = cvCreateImage(cvSize((int)frameWidth, (int)frameHeight), IPL_DEPTH_8U, 1);
571         frame->widthStep = (int)frameWidth;
572         Camera.Frame.ImageBufferSize = frameSize;
573         Camera.Frame.ImageBuffer = frame->imageData;
574     }
575     else if ( (strcmp(pixelFormat, "Mono16")==0) || (strcmp(pixelFormat, "Bayer16")==0) )
576     {
577         frame = cvCreateImage(cvSize((int)frameWidth, (int)frameHeight), IPL_DEPTH_16U, 1);
578         frame->widthStep = (int)frameWidth*2;
579         Camera.Frame.ImageBufferSize = frameSize;
580         Camera.Frame.ImageBuffer = frame->imageData;
581     }
582     else if ( (strcmp(pixelFormat, "Rgb24")==0) || (strcmp(pixelFormat, "Bgr24")==0) )
583     {
584         frame = cvCreateImage(cvSize((int)frameWidth, (int)frameHeight), IPL_DEPTH_8U, 3);
585         frame->widthStep = (int)frameWidth*3;
586         Camera.Frame.ImageBufferSize = frameSize;
587         Camera.Frame.ImageBuffer = frame->imageData;
588     }
589     else if ( (strcmp(pixelFormat, "Rgba32")==0) || (strcmp(pixelFormat, "Bgra32")==0) )
590     {
591         frame = cvCreateImage(cvSize((int)frameWidth, (int)frameHeight), IPL_DEPTH_8U, 4);
592         frame->widthStep = (int)frameWidth*4;
593         Camera.Frame.ImageBufferSize = frameSize;
594         Camera.Frame.ImageBuffer = frame->imageData;
595     }
596     else
597         return false;
598 
599     return true;
600 }
601 
cvCreateCameraCapture_PvAPI(int index)602 CvCapture* cvCreateCameraCapture_PvAPI( int index )
603 {
604     CvCaptureCAM_PvAPI* capture = new CvCaptureCAM_PvAPI;
605 
606     if ( capture->open( index ))
607         return capture;
608 
609     delete capture;
610     return NULL;
611 }
612 #endif
613