Changeset 8832


Ignore:
Timestamp:
01/24/08 12:11:47 (17 years ago)
Author:
tbretz
Message:
*** empty log message ***
Location:
trunk/MagicSoft/Cosy
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/MagicSoft/Cosy/Changelog

    r8827 r8832  
    2626     - SetOwner of the fList
    2727
     28   * base/coord.h:
     29     - removed coordinate classes, replaced by new classes from MPointing.h
     30       (they are basically identical by now in libmars.so and derived from TVector2)
     31
     32   * base/msgqueue.[h,cc]:
     33     - simplified the scheme of the message queue using a single thread
     34     - now the default is that new messages override pending ones
     35     - the development is based on debugging with valgrind
     36     - the aim is more stability due to simplification
     37     - uses new threading scheme
     38
    2839   * macros/rootlogon.C:
    2940     - improved
    3041
     42   * Makefile:
     43     - added telesto
     44     - added inlcude directories
     45     - renamed cosy.so to libcosy.so
     46
     47   * base/MThread.[h,cc]:
     48     - implemented new Threading classe(s) -- still to be revised!
     49       (should be made part of Mars finally!)
     50
     51   * candrv/vmodican.[h,cc]:
     52     - adapted to new threading scheme
     53     - replaced lout by gLog
     54     - removed cast from third argument in ioctl (complains from a
     55       64bit debugger)
     56     - removed HandleMessage (now it is one level up -- that's not logical
     57       but just simple)
     58     - the same applies to SendCanFrame and MsgDescr
     59     - thread is not detached anymore
     60
     61   * videodev/Camera.[h,cc]:
     62     - for the moment the Camera class is removed from the root dictionary
     63     - changed to new threading class
     64     - thread doesn't run detached anymore
     65     - the Camera control is now based on the new MVideo-class
     66     - a lot of code has been moved to the new MVideo class
     67     - we also support (as a hack for tests) color cameras with different
     68       field-of-views
     69     - simplified and improved the logic of the loop based on valgrinds output
     70
     71   * videodev/VideodevLinkDef.h:
     72     - removed Camkera from dictionary
    3173
    3274
  • 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\* ======================================================================== */
    124#include "Camera.h"
    225
    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"
    828
    9 #include "MStopwatch.h"
     29#include "MVideo.h"
     30#include "PixClient.h"
    1031
    11 #include "videodev.h"
    12 
    13 ClassImp(Camera);
     32//ClassImp(Camera);
    1433
    1534using namespace std;
    1635
    17 inline int Camera::Ioctl(int req, void *opt, const char *str)
     36Camera::Camera(PixClient &client, Int_t nch) : MyThreadX("Camera"), fClient(client), fVideo(0)
    1837{
    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);
    2440
    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();
    19142}
    19243
    19344Camera::~Camera()
    19445{
    195     pthread_cancel(fThread);
     46    // Shut down the thread
     47    CancelThread();
    19648
    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;
    22051}
    22152
    22253void Camera::ExitLoop()
    22354{
    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;
    22760}
    22861
    229 //
    230 // flag if the execution is running or not
    231 //
    232 int Camera::IsRunning() const
     62void Camera::ProcessFrame(char *img)
    23363{
    234     const Int_t rc = fMutex->TryLock();
    235     if (rc==0)
    236         return false;
     64    gettimeofday(&fTime, NULL);
    23765
    238     if (rc==13)
    239         return false;
     66    const Int_t W = fVideo->GetWidth();
     67    const Int_t H = fVideo->GetHeight();
    24068
    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);
    24395}
    24496
    245 void Camera::LoopStep(const unsigned long n)
     97Int_t Camera::Thread()
    24698{
    247     char *img = GetImg(n&1);
     99    fNumSkipped = 0;
     100    fNumFrame   = 1;
    248101
    249     gettimeofday(&fTime, NULL);
     102    if (!fVideo->IsOpen())
     103    {
     104        gLog << "ERROR - Process: Device not open." << endl;
     105        return kFALSE;
     106    }
    250107
    251     const char *end = img + cols*rows*depth;
    252     char *beg = fImg;
     108    //Print();
    253109
    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;
    260113
    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
    265116    while (1)
    266117    {
    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))
    269123            break;
    270124
    271         MStopwatch t;
    272         t.Start();
     125        // If cacellation is requested cancel here
     126        TThread::CancelPoint();
    273127
    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;
    277135            continue;
    278136
    279         if (!StartGrab(1))
    280             continue;
     137        case kFALSE: // Waiting failed
     138            break;
    281139
    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;
    287145
    288             fClient.ProcessFrame(i, (byte*)fImg, &fTime);
    289             i++;
     146            cout << "ERROR - At least five captured images timed out." << endl;
     147            break;
    290148        }
    291149
    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;
    308151    }
    309152
    310     fMutex->UnLock();
     153    // Is this necessary?!?
     154    //for (int i=0; i<frames-1; i++)
     155    //    video.CaptureWait((f+i+1)%frames);
    311156
    312     cout << "Camera::Thread.. stopped." << endl;
     157    cout << fNumFrame-1 << " frames processed." << endl;
     158    cout << fNumSkipped << " frames skipped." << endl;
     159
     160    return kTRUE;
    313161}
    314162
    315163void Camera::Loop(unsigned long nof)
    316164{
    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 execution
    330     //
    331     fCond.Broadcast();
    332 
    333     // I don't know what the reason for this line is, but it
    334     // seems to solve some starnge crashes when switching
    335     // between the two cameras and it ensures that cosy works
    336     // with root 4.04/02g
    337     fMutex->UnLock();
    338165}
    339166
    340 void Camera::SetPicPar(int bright, int hue, int contrast)
     167void Camera::SetChannel(int chan)
    341168{
    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();
    356172}
    357173
    358 void Camera::GetPicPar(int *bright, int *hue, int *contrast)
    359 {
    360     struct video_picture pict;
    361 
    362     Ioctl(VIDIOCGPICT, &pict);   // get
    363 
    364     *contrast = pict.contrast;
    365     *bright   = pict.brightness;
    366     *hue      = pict.hue;
    367 }
    368 
  • trunk/MagicSoft/Cosy/videodev/Camera.h

    r4105 r8832  
    22#define COSY_Camera
    33
    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"
    96#endif
    107
    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"
    1710#endif
    1811
    19 #include "PixGetter.h"
    20 #include "PixClient.h"
     12class MVideo;
     13class PixClient;
    2114
    22 class Camera : public PixGetter
     15class Camera : public PixGetter, public MyThreadX
    2316{
    2417private:
     
    3023    static const int depth = 3;
    3124
    32     //
    33     // Hardware Descriptors
    34     //
    35     int fd;
    36     int iBufferSize;
    37     int iOffsets[2];
    38 
    39     char *pMapBuffer;
    40 
    41     //
    42     // Thread interface
    43     //
    44     unsigned long fNum;
    45 
    46     int fStop;
    47 //    int fRunning;
    48 
    4925    char fImg[cols*rows];
    5026    struct timeval fTime;
     
    5228    PixClient &fClient;
    5329
    54     pthread_t  fThread;
    55     TCondition fCond;
    56     TMutex    *fMutex;
    57     //pthread_mutex_t fMux;
    58     //pthread_cond_t  fCond;
     30    MVideo *fVideo;
    5931
    60     //
    61     // Hardware dependant functions
    62     //
    63     static void SigAlarm(int signal);
     32    UInt_t fNumFrame;
     33    UInt_t fNumSkipped;
    6434
    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);
    8137
    8238public:
     
    8945    void Loop(const unsigned long nof=0);
    9046    void ExitLoop();
    91     int  IsRunning() const;
     47    //int  IsRunning() const;
    9248
    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);
    9850
    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)
    10652};
    10753
  • trunk/MagicSoft/Cosy/videodev/VideodevLinkDef.h

    r2278 r8832  
    1111//#pragma link C++ class CaosFilter+;
    1212
    13 #pragma link C++ class Camera+;
     13//#pragma link C++ class Camera+;
    1414#pragma link C++ class PngReader+;
    1515
Note: See TracChangeset for help on using the changeset viewer.