Index: trunk/MagicSoft/Cosy/videodev/Camera.cc
===================================================================
--- trunk/MagicSoft/Cosy/videodev/Camera.cc	(revision 8811)
+++ trunk/MagicSoft/Cosy/videodev/Camera.cc	(revision 8832)
@@ -1,368 +1,173 @@
+/* ======================================================================== *\
+!
+! *
+! * This file is part of MARS, the MAGIC Analysis and Reconstruction
+! * Software. It is distributed to you in the hope that it can be a useful
+! * and timesaving tool in analysing Data of imaging Cerenkov telescopes.
+! * It is distributed WITHOUT ANY WARRANTY.
+! *
+! * Permission to use, copy, modify and distribute this software and its
+! * documentation for any purpose is hereby granted without fee,
+! * provided that the above copyright notice appear in all copies and
+! * that both that copyright notice and this permission notice appear
+! * in supporting documentation. It is provided "as is" without express
+! * or implied warranty.
+! *
+!
+!
+!   Author(s): Thomas Bretz 1/2008 <mailto:tbretz@astro.uni-wuerzburg.de>
+!
+!   Copyright: MAGIC Software Development, 2000-2008
+!
+!
+\* ======================================================================== */
 #include "Camera.h"
 
-#include <iostream>
-#include <errno.h>     // errono
-#include <pthread.h>
-#include <sys/ioctl.h> // ioctl
-#include <sys/mman.h>  // PROT_READ
+#include "MLog.h"
+#include "MLogManip.h"
 
-#include "MStopwatch.h"
+#include "MVideo.h"
+#include "PixClient.h"
 
-#include "videodev.h"
-
-ClassImp(Camera);
+//ClassImp(Camera);
 
 using namespace std;
 
-inline int Camera::Ioctl(int req, void *opt, const char *str)
+Camera::Camera(PixClient &client, Int_t nch) : MyThreadX("Camera"), fClient(client), fVideo(0)
 {
-    if (fd<0)
-    {
-        cout << "Error! Called Ioctl with invalid filedescriptor." << endl;
-        return -1;
-    }
+    fVideo = new MVideo;
+    fVideo->Open(nch);
 
-    while (1)
-    {
-        const int rc = ioctl(fd, req, opt);
-        if (rc>=0)
-            return rc;
-
-        // errno== 4: Interrupted system call
-        // errno==16: Device or resource busy
-        if (errno==4 || errno==16)
-        {
-            cout << "Camera: ioctl returned rc=" << rc << " '";
-            cout << (str?str:strerror(errno)) << "' (errno = " << errno << ")" << endl;
-            usleep(10);
-            continue;
-        }
-
-        cout << "Error! Ioctl " << hex << req << ": errno=" << dec << errno << " - ";
-        cout << (str?str:strerror(errno)) << " (rc=" << rc << ")" << endl;
-        return rc;
-    }
-    return -1;
-}
-
-void Camera::Error(const char *str, int fatal)
-{
-    cout << endl;
-    cout << (fatal?"Fatal ":"") << "Error! " << str << ": " << strerror(errno);
-    cout << endl;
-
-    if (fatal)
-        exit(1);
-}
-void Camera::SigInit()
-{
-    /*
-     struct sigaction act, old;
-
-     memset(&act, 0, sizeof(act));
-
-     act.sa_handler = SigAlarm;
-
-     sigemptyset(&act. sa_mask);
-     sigaction(SIGALRM, &act, &old);
-
-     // signal(SIGINT, ctrlc);
-     */
-}
-
-void Camera::SigAlarm(int signal)
-{
-    cout << "Camera: oops: got sigalarm" << endl;
-    exit(1);
-}
-
-char *Camera::GetImg(unsigned int frame)
-{
-    // wait until grabbing is finished??
-    //
-    // give signal SIGALARM
-    const int SYNC_TIMEOUT = 1;
-
-    alarm(SYNC_TIMEOUT);
-    Ioctl(VIDIOCSYNC, &frame); // sync with mmap grabbing
-    alarm(0);
-
-    return pMapBuffer+iOffsets[frame];
-}
-
-int Camera::StartGrab(unsigned int frame)
-{
-    // We could also get RGB555, RGB565 and RGB32. But we want
-    // RGB24 because we have a 8bit DAC which gives us 8bit per
-    // color ==> RGB24 which is in the following the most simple
-    // to process.
-    static struct video_mmap gb =
-    {
-        0,                  // frame
-        rows, cols,         // height, width
-        VIDEO_PALETTE_RGB24 // palette
-    };
-
-    gb.frame = frame&1;
-
-    //
-    // capture frame
-    //
-    if (Ioctl(VIDIOCMCAPTURE, &gb) != -1)
-        return true;
-
-    if (errno == EAGAIN)
-        cout << "Grabber chip can't sync" << endl;
-
-    return false;
-}
-
-Camera::Camera(PixClient &client, Int_t nch) : fd(-1), iBufferSize(0), fClient(client), fCond(), fMutex(fCond.GetMutex())
-{
-    cout << "Camera: " << this << " /dev/video: opening..." << flush;
-
-    //
-    // ------ Open device /dev/video ------
-    //
-    do
-    {
-        fd = open("/dev/video", O_RDWR);
-        usleep(1);
-    }
-    while (errno==19 && fd==-1);
-
-    if (fd == -1)
-        Error("open /dev/video");
-
-    fcntl(fd, F_SETFD, FD_CLOEXEC);  // Close device on exit
-    SigInit();
-
-    //
-    // get input channel 0 information
-    //
-
-    struct video_channel ch;
-    ch.channel = nch;
-    Ioctl(VIDIOCGCHAN, &ch);
-
-    //
-    // ioctl probe, switch to input 0
-    //
-    Ioctl(VIDIOCSCHAN, &ch, "You need a bttv version > 0.5.13");
-
-    //
-    // map grab buffer, get size and offset
-    //
-    struct video_mbuf buffers;
-    Ioctl(VIDIOCGMBUF, &buffers);
-
-    iBufferSize = buffers.size;
-    iOffsets[0] = buffers.offsets[0];
-    iOffsets[1] = buffers.offsets[1];
-
-    //
-    // map file (device) into memory
-    //
-    pMapBuffer = (char*)mmap(0, iBufferSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
-
-    if ((int)pMapBuffer == -1)
-        Error("mmap");
-
-    cout << "OK." << endl;
-
-    cout << "Buffer Address: " << (void*)pMapBuffer << endl;
-    cout << "Buffer Offset 1: " << (void*)iOffsets[0] << endl;
-    cout << "Buffer Offset 2: " << (void*)iOffsets[1] << endl;
-    cout << "Buffer Size: " << (void*)iBufferSize << endl;
-    cout << "grab: use: 768x576 24 bit TrueColor (LE: bgr) = " << (void*)(768*576*3) << "b" << endl;
-
-//    if (fMutex->UnLock()==13)
-//        cout << "Camera::Camera - tried to unlock mutex locked by other thread." << endl;
-
-    cout << "Starting thread..." << flush;
-    //pthread_cond_init(&fCond, NULL);
-    //pthread_mutex_init(&fMux, NULL);
-    //pthread_mutex_lock(&fMux);
-//    if (fMutex->Lock()==13)
-//        cout << "Camera::Camera - mutex is already locked by this thread" << endl;
-    pthread_create(&fThread, NULL, MapThread, this);
-    cout << "CameraInitialized..." << endl;
-
+    RunThread();
 }
 
 Camera::~Camera()
 {
-    pthread_cancel(fThread);
+    // Shut down the thread
+    CancelThread();
 
-    cout << "/dev/video: closing... " << flush;
-    if (fd != -1)
-    {
-        close(fd);
-        fd = -1;
-    }
-    cout << "done." << endl;
-
-    // unmap device memory
-    if ((int)pMapBuffer != -1)
-        munmap(pMapBuffer, iBufferSize);
-}
-
-void *Camera::MapThread(void *arg)
-{
-    Camera *cam = (Camera*)arg;
-
-    // setpriority(PRIO_PROCESS, 0, 10);
-    pthread_detach(pthread_self());
-
-    cam->Thread();
-
-    return 0;
+    // Now delete (close) the device
+    delete fVideo;
 }
 
 void Camera::ExitLoop()
 {
-    fStop = 1;
-    while (IsRunning())
-        usleep(1);
+    CancelThread();
+
+    // Some information
+    //cout << fNumFrame-1 << "frames processed." << endl;
+    //cout << fNumSkipped << "frames skipped." << endl;
 }
 
-//
-// flag if the execution is running or not
-//
-int Camera::IsRunning() const
+void Camera::ProcessFrame(char *img)
 {
-    const Int_t rc = fMutex->TryLock();
-    if (rc==0)
-        return false;
+    gettimeofday(&fTime, NULL);
 
-    if (rc==13)
-        return false;
+    const Int_t W = fVideo->GetWidth();
+    const Int_t H = fVideo->GetHeight();
 
-    fMutex->UnLock();
-    return true;
+    const Bool_t crop = W!=768 || H!=576;
+
+    // FIXME: This only works for one RGB24
+    if (!crop)
+    {
+        // FIXME: Grey scale assumed!
+        const char *end = img + 768*576*depth;
+        char *beg = fImg;
+        while (img < end)
+        {
+            *beg++ = *img;
+            img += depth;
+        }
+    }
+    else
+    {
+        const Int_t w = TMath::Min(W, 768);
+        const Int_t h = TMath::Min(H, 576);
+
+        memset(fImg, 0, 768*576);
+        for (int y=0; y<h; y++)
+            for (int x=0; x<w; x++)
+                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;
+    }
+
+    fClient.ProcessFrame(fNumFrame-1, (byte*)fImg, &fTime);
 }
 
-void Camera::LoopStep(const unsigned long n)
+Int_t Camera::Thread()
 {
-    char *img = GetImg(n&1);
+    fNumSkipped = 0;
+    fNumFrame   = 1;
 
-    gettimeofday(&fTime, NULL);
+    if (!fVideo->IsOpen())
+    {
+        gLog << "ERROR - Process: Device not open." << endl;
+        return kFALSE;
+    }
 
-    const char *end = img + cols*rows*depth;
-    char *beg = fImg;
+    //Print();
 
-    while (img < end)
-    {
-        *beg++ = *img;
-        img += depth;
-    }
-}
+    for (int f=0; f<fVideo->GetNumBuffers()-1; f++)
+        if (!fVideo->CaptureStart(f))
+            return kFALSE;
 
-void Camera::Thread()
-{
-#define IsOdd(i) (2*(i/2)!=i)
-    cout << "Camera::Thread started..." << endl;
+    Int_t timeouts = 0;
+
     while (1)
     {
-        fCond.Wait();;
-        if (fd==-1)
+        // If cacellation is requested cancel here
+        TThread::CancelPoint();
+
+        // Start to capture into the buffer which has just been processed
+        if (!fVideo->CaptureStart(fNumFrame))
             break;
 
-        MStopwatch t;
-        t.Start();
+        // If cacellation is requested cancel here
+        TThread::CancelPoint();
 
-        unsigned long i=0;
-
-        if (!StartGrab(0))
+        // Check and wait until capture into the next buffer is finshed
+        char *img = 0;
+        switch (fVideo->CaptureWait(++fNumFrame, &img))
+        {
+        case kTRUE: // Process frame
+            ProcessFrame(img);
+            timeouts = 0;
             continue;
 
-        if (!StartGrab(1))
-            continue;
+        case kFALSE: // Waiting failed
+            break;
 
-        while (!(fStop || fNum && i==fNum-2))
-        {
-            LoopStep(i);
-            if (!StartGrab(i&1))
-                break;
+        case kSKIP:  // Skip frame
+            fNumFrame--;
+            fNumSkipped++;
+            if (timeouts++<5)
+                continue;
 
-            fClient.ProcessFrame(i, (byte*)fImg, &fTime);
-            i++;
+            cout << "ERROR - At least five captured images timed out." << endl;
+            break;
         }
 
-        if (!IsOdd(i))
-        {
-            LoopStep(i);
-            fClient.ProcessFrame(i, (byte*)fImg, &fTime);
-            i++;
-        }
-
-        LoopStep(i);
-        fClient.ProcessFrame(i, (byte*)fImg, &fTime);
-        i++;
-
-        //
-        // Wait until processing of frame 1 finished.
-        //
-        t.Stop();
-        t.Print(i);
+        break;
     }
 
-    fMutex->UnLock();
+    // Is this necessary?!?
+    //for (int i=0; i<frames-1; i++)
+    //    video.CaptureWait((f+i+1)%frames);
 
-    cout << "Camera::Thread.. stopped." << endl;
+    cout << fNumFrame-1 << " frames processed." << endl;
+    cout << fNumSkipped << " frames skipped." << endl;
+
+    return kTRUE;
 }
 
 void Camera::Loop(unsigned long nof)
 {
-    if (2*(nof/2) != nof)
-    {
-        cout << "Sorry, only even values are allowed!" << endl;
-        return;
-    }
-
-    ExitLoop();
-
-    fNum  = nof;
-    fStop = 0;
-
-    //
-    // Start execution
-    //
-    fCond.Broadcast();
-
-    // I don't know what the reason for this line is, but it
-    // seems to solve some starnge crashes when switching
-    // between the two cameras and it ensures that cosy works
-    // with root 4.04/02g
-    fMutex->UnLock();
 }
 
-void Camera::SetPicPar(int bright, int hue, int contrast)
+void Camera::SetChannel(int chan)
 {
-    struct video_picture pict;
-
-    Ioctl(VIDIOCGPICT, &pict);  // get
-
-    if (contrast != -1)
-        pict.contrast = contrast;
-
-    if (bright != -1)
-        pict.brightness = bright;
-
-    if (hue != -1)
-	pict.hue = hue;
-
-    Ioctl(VIDIOCSPICT, &pict);  //set
+    CancelThread();
+    fVideo->SetChannel(chan);
+    RunThread();
 }
 
-void Camera::GetPicPar(int *bright, int *hue, int *contrast)
-{
-    struct video_picture pict;
-
-    Ioctl(VIDIOCGPICT, &pict);   // get
-
-    *contrast = pict.contrast;
-    *bright   = pict.brightness;
-    *hue      = pict.hue;
-}
-
Index: trunk/MagicSoft/Cosy/videodev/Camera.h
===================================================================
--- trunk/MagicSoft/Cosy/videodev/Camera.h	(revision 8811)
+++ trunk/MagicSoft/Cosy/videodev/Camera.h	(revision 8832)
@@ -2,23 +2,16 @@
 #define COSY_Camera
 
-#ifndef ROOT_TMutex
-#include <TMutex.h>
-#endif
-#ifndef ROOT_TCondition
-#include <TCondition.h>
+#ifndef MARS_MThread
+#include "MThread.h"
 #endif
 
-#ifdef __CINT__
-typedef unsigned long int pthread_t;
-struct timeval;
-#else
-#include <unistd.h>
-#include <sys/time.h>
+#ifndef COSY_PixGetter
+#include "PixGetter.h"
 #endif
 
-#include "PixGetter.h"
-#include "PixClient.h"
+class MVideo;
+class PixClient;
 
-class Camera : public PixGetter
+class Camera : public PixGetter, public MyThreadX
 {
 private:
@@ -30,21 +23,4 @@
     static const int depth = 3;
 
-    //
-    // Hardware Descriptors
-    //
-    int fd;
-    int iBufferSize;
-    int iOffsets[2];
-
-    char *pMapBuffer;
-
-    //
-    // Thread interface
-    //
-    unsigned long fNum;
-
-    int fStop;
-//    int fRunning;
-
     char fImg[cols*rows];
     struct timeval fTime;
@@ -52,31 +28,11 @@
     PixClient &fClient;
 
-    pthread_t  fThread;
-    TCondition fCond;
-    TMutex    *fMutex;
-    //pthread_mutex_t fMux;
-    //pthread_cond_t  fCond;
+    MVideo *fVideo;
 
-    //
-    // Hardware dependant functions
-    //
-    static void SigAlarm(int signal);
+    UInt_t fNumFrame;
+    UInt_t fNumSkipped;
 
-    int  Ioctl(int req, void *opt, const char *str=NULL);
-
-    void SigInit();
-    void Error(const char *str, int fatal=true);
-
-    int  StartGrab(unsigned int frame);
-
-    char *GetImg(unsigned int frame);
-
-    //
-    // Execution thread which processes the pictures
-    //
-    void Thread();
-    static void *MapThread(void *arg);
-
-    void LoopStep(const unsigned long n);
+    Int_t Thread();
+    void  ProcessFrame(char *img);
 
 public:
@@ -89,19 +45,9 @@
     void Loop(const unsigned long nof=0);
     void ExitLoop();
-    int  IsRunning() const;
+    //int  IsRunning() const;
 
-    //
-    // Execution of one frame - this function may be overloaded!
-    //
-    //virtual void ProcessFrame(const unsigned long n,
-    //                          byte *img, struct timeval *tm);
+    void SetChannel(int);
 
-    //
-    // hardware features
-    //
-    void SetPicPar(int  bright, int  hue, int  contrast);
-    void GetPicPar(int *bright, int *hue, int *contrast);
-
-    ClassDef(Camera, 0)
+    //ClassDef(Camera, 0)
 };
 
Index: trunk/MagicSoft/Cosy/videodev/VideodevLinkDef.h
===================================================================
--- trunk/MagicSoft/Cosy/videodev/VideodevLinkDef.h	(revision 8811)
+++ trunk/MagicSoft/Cosy/videodev/VideodevLinkDef.h	(revision 8832)
@@ -11,5 +11,5 @@
 //#pragma link C++ class CaosFilter+;
 
-#pragma link C++ class Camera+;
+//#pragma link C++ class Camera+;
 #pragma link C++ class PngReader+;
 
