Changeset 8832 for trunk/MagicSoft/Cosy/videodev
- Timestamp:
- 01/24/08 12:11:47 (17 years ago)
- Location:
- trunk/MagicSoft/Cosy/videodev
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/MagicSoft/Cosy/videodev/Camera.cc
r7787 r8832 1 /* ======================================================================== *\ 2 ! 3 ! * 4 ! * This file is part of MARS, the MAGIC Analysis and Reconstruction 5 ! * Software. It is distributed to you in the hope that it can be a useful 6 ! * and timesaving tool in analysing Data of imaging Cerenkov telescopes. 7 ! * It is distributed WITHOUT ANY WARRANTY. 8 ! * 9 ! * Permission to use, copy, modify and distribute this software and its 10 ! * documentation for any purpose is hereby granted without fee, 11 ! * provided that the above copyright notice appear in all copies and 12 ! * that both that copyright notice and this permission notice appear 13 ! * in supporting documentation. It is provided "as is" without express 14 ! * or implied warranty. 15 ! * 16 ! 17 ! 18 ! Author(s): Thomas Bretz 1/2008 <mailto:tbretz@astro.uni-wuerzburg.de> 19 ! 20 ! Copyright: MAGIC Software Development, 2000-2008 21 ! 22 ! 23 \* ======================================================================== */ 1 24 #include "Camera.h" 2 25 3 #include <iostream> 4 #include <errno.h> // errono 5 #include <pthread.h> 6 #include <sys/ioctl.h> // ioctl 7 #include <sys/mman.h> // PROT_READ 26 #include "MLog.h" 27 #include "MLogManip.h" 8 28 9 #include "MStopwatch.h" 29 #include "MVideo.h" 30 #include "PixClient.h" 10 31 11 #include "videodev.h" 12 13 ClassImp(Camera); 32 //ClassImp(Camera); 14 33 15 34 using namespace std; 16 35 17 inline int Camera::Ioctl(int req, void *opt, const char *str)36 Camera::Camera(PixClient &client, Int_t nch) : MyThreadX("Camera"), fClient(client), fVideo(0) 18 37 { 19 if (fd<0) 20 { 21 cout << "Error! Called Ioctl with invalid filedescriptor." << endl; 22 return -1; 23 } 38 fVideo = new MVideo; 39 fVideo->Open(nch); 24 40 25 while (1) 26 { 27 const int rc = ioctl(fd, req, opt); 28 if (rc>=0) 29 return rc; 30 31 // errno== 4: Interrupted system call 32 // errno==16: Device or resource busy 33 if (errno==4 || errno==16) 34 { 35 cout << "Camera: ioctl returned rc=" << rc << " '"; 36 cout << (str?str:strerror(errno)) << "' (errno = " << errno << ")" << endl; 37 usleep(10); 38 continue; 39 } 40 41 cout << "Error! Ioctl " << hex << req << ": errno=" << dec << errno << " - "; 42 cout << (str?str:strerror(errno)) << " (rc=" << rc << ")" << endl; 43 return rc; 44 } 45 return -1; 46 } 47 48 void Camera::Error(const char *str, int fatal) 49 { 50 cout << endl; 51 cout << (fatal?"Fatal ":"") << "Error! " << str << ": " << strerror(errno); 52 cout << endl; 53 54 if (fatal) 55 exit(1); 56 } 57 void Camera::SigInit() 58 { 59 /* 60 struct sigaction act, old; 61 62 memset(&act, 0, sizeof(act)); 63 64 act.sa_handler = SigAlarm; 65 66 sigemptyset(&act. sa_mask); 67 sigaction(SIGALRM, &act, &old); 68 69 // signal(SIGINT, ctrlc); 70 */ 71 } 72 73 void Camera::SigAlarm(int signal) 74 { 75 cout << "Camera: oops: got sigalarm" << endl; 76 exit(1); 77 } 78 79 char *Camera::GetImg(unsigned int frame) 80 { 81 // wait until grabbing is finished?? 82 // 83 // give signal SIGALARM 84 const int SYNC_TIMEOUT = 1; 85 86 alarm(SYNC_TIMEOUT); 87 Ioctl(VIDIOCSYNC, &frame); // sync with mmap grabbing 88 alarm(0); 89 90 return pMapBuffer+iOffsets[frame]; 91 } 92 93 int Camera::StartGrab(unsigned int frame) 94 { 95 // We could also get RGB555, RGB565 and RGB32. But we want 96 // RGB24 because we have a 8bit DAC which gives us 8bit per 97 // color ==> RGB24 which is in the following the most simple 98 // to process. 99 static struct video_mmap gb = 100 { 101 0, // frame 102 rows, cols, // height, width 103 VIDEO_PALETTE_RGB24 // palette 104 }; 105 106 gb.frame = frame&1; 107 108 // 109 // capture frame 110 // 111 if (Ioctl(VIDIOCMCAPTURE, &gb) != -1) 112 return true; 113 114 if (errno == EAGAIN) 115 cout << "Grabber chip can't sync" << endl; 116 117 return false; 118 } 119 120 Camera::Camera(PixClient &client, Int_t nch) : fd(-1), iBufferSize(0), fClient(client), fCond(), fMutex(fCond.GetMutex()) 121 { 122 cout << "Camera: " << this << " /dev/video: opening..." << flush; 123 124 // 125 // ------ Open device /dev/video ------ 126 // 127 do 128 { 129 fd = open("/dev/video", O_RDWR); 130 usleep(1); 131 } 132 while (errno==19 && fd==-1); 133 134 if (fd == -1) 135 Error("open /dev/video"); 136 137 fcntl(fd, F_SETFD, FD_CLOEXEC); // Close device on exit 138 SigInit(); 139 140 // 141 // get input channel 0 information 142 // 143 144 struct video_channel ch; 145 ch.channel = nch; 146 Ioctl(VIDIOCGCHAN, &ch); 147 148 // 149 // ioctl probe, switch to input 0 150 // 151 Ioctl(VIDIOCSCHAN, &ch, "You need a bttv version > 0.5.13"); 152 153 // 154 // map grab buffer, get size and offset 155 // 156 struct video_mbuf buffers; 157 Ioctl(VIDIOCGMBUF, &buffers); 158 159 iBufferSize = buffers.size; 160 iOffsets[0] = buffers.offsets[0]; 161 iOffsets[1] = buffers.offsets[1]; 162 163 // 164 // map file (device) into memory 165 // 166 pMapBuffer = (char*)mmap(0, iBufferSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); 167 168 if ((int)pMapBuffer == -1) 169 Error("mmap"); 170 171 cout << "OK." << endl; 172 173 cout << "Buffer Address: " << (void*)pMapBuffer << endl; 174 cout << "Buffer Offset 1: " << (void*)iOffsets[0] << endl; 175 cout << "Buffer Offset 2: " << (void*)iOffsets[1] << endl; 176 cout << "Buffer Size: " << (void*)iBufferSize << endl; 177 cout << "grab: use: 768x576 24 bit TrueColor (LE: bgr) = " << (void*)(768*576*3) << "b" << endl; 178 179 // if (fMutex->UnLock()==13) 180 // cout << "Camera::Camera - tried to unlock mutex locked by other thread." << endl; 181 182 cout << "Starting thread..." << flush; 183 //pthread_cond_init(&fCond, NULL); 184 //pthread_mutex_init(&fMux, NULL); 185 //pthread_mutex_lock(&fMux); 186 // if (fMutex->Lock()==13) 187 // cout << "Camera::Camera - mutex is already locked by this thread" << endl; 188 pthread_create(&fThread, NULL, MapThread, this); 189 cout << "CameraInitialized..." << endl; 190 41 RunThread(); 191 42 } 192 43 193 44 Camera::~Camera() 194 45 { 195 pthread_cancel(fThread); 46 // Shut down the thread 47 CancelThread(); 196 48 197 cout << "/dev/video: closing... " << flush; 198 if (fd != -1) 199 { 200 close(fd); 201 fd = -1; 202 } 203 cout << "done." << endl; 204 205 // unmap device memory 206 if ((int)pMapBuffer != -1) 207 munmap(pMapBuffer, iBufferSize); 208 } 209 210 void *Camera::MapThread(void *arg) 211 { 212 Camera *cam = (Camera*)arg; 213 214 // setpriority(PRIO_PROCESS, 0, 10); 215 pthread_detach(pthread_self()); 216 217 cam->Thread(); 218 219 return 0; 49 // Now delete (close) the device 50 delete fVideo; 220 51 } 221 52 222 53 void Camera::ExitLoop() 223 54 { 224 fStop = 1; 225 while (IsRunning()) 226 usleep(1); 55 CancelThread(); 56 57 // Some information 58 //cout << fNumFrame-1 << "frames processed." << endl; 59 //cout << fNumSkipped << "frames skipped." << endl; 227 60 } 228 61 229 // 230 // flag if the execution is running or not 231 // 232 int Camera::IsRunning() const 62 void Camera::ProcessFrame(char *img) 233 63 { 234 const Int_t rc = fMutex->TryLock(); 235 if (rc==0) 236 return false; 64 gettimeofday(&fTime, NULL); 237 65 238 if (rc==13)239 return false;66 const Int_t W = fVideo->GetWidth(); 67 const Int_t H = fVideo->GetHeight(); 240 68 241 fMutex->UnLock(); 242 return true; 69 const Bool_t crop = W!=768 || H!=576; 70 71 // FIXME: This only works for one RGB24 72 if (!crop) 73 { 74 // FIXME: Grey scale assumed! 75 const char *end = img + 768*576*depth; 76 char *beg = fImg; 77 while (img < end) 78 { 79 *beg++ = *img; 80 img += depth; 81 } 82 } 83 else 84 { 85 const Int_t w = TMath::Min(W, 768); 86 const Int_t h = TMath::Min(H, 576); 87 88 memset(fImg, 0, 768*576); 89 for (int y=0; y<h; y++) 90 for (int x=0; x<w; x++) 91 fImg[x+y*768] = ((UInt_t)(UChar_t)img[(x+y*W)*3]+(UInt_t)(UChar_t)img[(x+y*fVideo->GetWidth())*3+1]+(UInt_t)(UChar_t)img[(x+y*fVideo->GetWidth())*3+2])/3; 92 } 93 94 fClient.ProcessFrame(fNumFrame-1, (byte*)fImg, &fTime); 243 95 } 244 96 245 void Camera::LoopStep(const unsigned long n)97 Int_t Camera::Thread() 246 98 { 247 char *img = GetImg(n&1); 99 fNumSkipped = 0; 100 fNumFrame = 1; 248 101 249 gettimeofday(&fTime, NULL); 102 if (!fVideo->IsOpen()) 103 { 104 gLog << "ERROR - Process: Device not open." << endl; 105 return kFALSE; 106 } 250 107 251 const char *end = img + cols*rows*depth; 252 char *beg = fImg; 108 //Print(); 253 109 254 while (img < end) 255 { 256 *beg++ = *img; 257 img += depth; 258 } 259 } 110 for (int f=0; f<fVideo->GetNumBuffers()-1; f++) 111 if (!fVideo->CaptureStart(f)) 112 return kFALSE; 260 113 261 void Camera::Thread() 262 { 263 #define IsOdd(i) (2*(i/2)!=i) 264 cout << "Camera::Thread started..." << endl; 114 Int_t timeouts = 0; 115 265 116 while (1) 266 117 { 267 fCond.Wait();; 268 if (fd==-1) 118 // If cacellation is requested cancel here 119 TThread::CancelPoint(); 120 121 // Start to capture into the buffer which has just been processed 122 if (!fVideo->CaptureStart(fNumFrame)) 269 123 break; 270 124 271 MStopwatch t;272 t.Start();125 // If cacellation is requested cancel here 126 TThread::CancelPoint(); 273 127 274 unsigned long i=0; 275 276 if (!StartGrab(0)) 128 // Check and wait until capture into the next buffer is finshed 129 char *img = 0; 130 switch (fVideo->CaptureWait(++fNumFrame, &img)) 131 { 132 case kTRUE: // Process frame 133 ProcessFrame(img); 134 timeouts = 0; 277 135 continue; 278 136 279 if (!StartGrab(1))280 continue;137 case kFALSE: // Waiting failed 138 break; 281 139 282 while (!(fStop || fNum && i==fNum-2))283 {284 LoopStep(i);285 if ( !StartGrab(i&1))286 break;140 case kSKIP: // Skip frame 141 fNumFrame--; 142 fNumSkipped++; 143 if (timeouts++<5) 144 continue; 287 145 288 fClient.ProcessFrame(i, (byte*)fImg, &fTime);289 i++;146 cout << "ERROR - At least five captured images timed out." << endl; 147 break; 290 148 } 291 149 292 if (!IsOdd(i)) 293 { 294 LoopStep(i); 295 fClient.ProcessFrame(i, (byte*)fImg, &fTime); 296 i++; 297 } 298 299 LoopStep(i); 300 fClient.ProcessFrame(i, (byte*)fImg, &fTime); 301 i++; 302 303 // 304 // Wait until processing of frame 1 finished. 305 // 306 t.Stop(); 307 t.Print(i); 150 break; 308 151 } 309 152 310 fMutex->UnLock(); 153 // Is this necessary?!? 154 //for (int i=0; i<frames-1; i++) 155 // video.CaptureWait((f+i+1)%frames); 311 156 312 cout << "Camera::Thread.. stopped." << endl; 157 cout << fNumFrame-1 << " frames processed." << endl; 158 cout << fNumSkipped << " frames skipped." << endl; 159 160 return kTRUE; 313 161 } 314 162 315 163 void Camera::Loop(unsigned long nof) 316 164 { 317 if (2*(nof/2) != nof)318 {319 cout << "Sorry, only even values are allowed!" << endl;320 return;321 }322 323 ExitLoop();324 325 fNum = nof;326 fStop = 0;327 328 //329 // Start execution330 //331 fCond.Broadcast();332 333 // I don't know what the reason for this line is, but it334 // seems to solve some starnge crashes when switching335 // between the two cameras and it ensures that cosy works336 // with root 4.04/02g337 fMutex->UnLock();338 165 } 339 166 340 void Camera::Set PicPar(int bright, int hue, int contrast)167 void Camera::SetChannel(int chan) 341 168 { 342 struct video_picture pict; 343 344 Ioctl(VIDIOCGPICT, &pict); // get 345 346 if (contrast != -1) 347 pict.contrast = contrast; 348 349 if (bright != -1) 350 pict.brightness = bright; 351 352 if (hue != -1) 353 pict.hue = hue; 354 355 Ioctl(VIDIOCSPICT, &pict); //set 169 CancelThread(); 170 fVideo->SetChannel(chan); 171 RunThread(); 356 172 } 357 173 358 void Camera::GetPicPar(int *bright, int *hue, int *contrast)359 {360 struct video_picture pict;361 362 Ioctl(VIDIOCGPICT, &pict); // get363 364 *contrast = pict.contrast;365 *bright = pict.brightness;366 *hue = pict.hue;367 }368 -
trunk/MagicSoft/Cosy/videodev/Camera.h
r4105 r8832 2 2 #define COSY_Camera 3 3 4 #ifndef ROOT_TMutex 5 #include <TMutex.h> 6 #endif 7 #ifndef ROOT_TCondition 8 #include <TCondition.h> 4 #ifndef MARS_MThread 5 #include "MThread.h" 9 6 #endif 10 7 11 #ifdef __CINT__ 12 typedef unsigned long int pthread_t; 13 struct timeval; 14 #else 15 #include <unistd.h> 16 #include <sys/time.h> 8 #ifndef COSY_PixGetter 9 #include "PixGetter.h" 17 10 #endif 18 11 19 #include "PixGetter.h" 20 #include "PixClient.h" 12 class MVideo; 13 class PixClient; 21 14 22 class Camera : public PixGetter 15 class Camera : public PixGetter, public MyThreadX 23 16 { 24 17 private: … … 30 23 static const int depth = 3; 31 24 32 //33 // Hardware Descriptors34 //35 int fd;36 int iBufferSize;37 int iOffsets[2];38 39 char *pMapBuffer;40 41 //42 // Thread interface43 //44 unsigned long fNum;45 46 int fStop;47 // int fRunning;48 49 25 char fImg[cols*rows]; 50 26 struct timeval fTime; … … 52 28 PixClient &fClient; 53 29 54 pthread_t fThread; 55 TCondition fCond; 56 TMutex *fMutex; 57 //pthread_mutex_t fMux; 58 //pthread_cond_t fCond; 30 MVideo *fVideo; 59 31 60 // 61 // Hardware dependant functions 62 // 63 static void SigAlarm(int signal); 32 UInt_t fNumFrame; 33 UInt_t fNumSkipped; 64 34 65 int Ioctl(int req, void *opt, const char *str=NULL); 66 67 void SigInit(); 68 void Error(const char *str, int fatal=true); 69 70 int StartGrab(unsigned int frame); 71 72 char *GetImg(unsigned int frame); 73 74 // 75 // Execution thread which processes the pictures 76 // 77 void Thread(); 78 static void *MapThread(void *arg); 79 80 void LoopStep(const unsigned long n); 35 Int_t Thread(); 36 void ProcessFrame(char *img); 81 37 82 38 public: … … 89 45 void Loop(const unsigned long nof=0); 90 46 void ExitLoop(); 91 int IsRunning() const;47 //int IsRunning() const; 92 48 93 // 94 // Execution of one frame - this function may be overloaded! 95 // 96 //virtual void ProcessFrame(const unsigned long n, 97 // byte *img, struct timeval *tm); 49 void SetChannel(int); 98 50 99 // 100 // hardware features 101 // 102 void SetPicPar(int bright, int hue, int contrast); 103 void GetPicPar(int *bright, int *hue, int *contrast); 104 105 ClassDef(Camera, 0) 51 //ClassDef(Camera, 0) 106 52 }; 107 53 -
trunk/MagicSoft/Cosy/videodev/VideodevLinkDef.h
r2278 r8832 11 11 //#pragma link C++ class CaosFilter+; 12 12 13 #pragma link C++ class Camera+;13 //#pragma link C++ class Camera+; 14 14 #pragma link C++ class PngReader+; 15 15
Note:
See TracChangeset
for help on using the changeset viewer.