FACT++  1.0
MVideo.cc
Go to the documentation of this file.
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:thomas.bretz@epfl.ch>
19 !
20 ! Copyright: MAGIC Software Development, 2000-2011
21 !
22 !
23 \* ======================================================================== */
24 
26 //
27 // MVideo
28 //
29 // Interface to Video4Linux at a simple level
30 //
31 // V4L2 spcifications from http://v4l2spec.bytesex.org/spec/
32 //
34 #include "MVideo.h"
35 
36 // iostream
37 #include <iostream>
38 
39 // open
40 #include <sys/types.h>
41 #include <sys/stat.h>
42 #include <fcntl.h>
43 
44 #include <unistd.h> // usleep
45 #include <errno.h> // errno
46 #include <sys/mman.h> // mmap
47 #include <sys/ioctl.h> // ioctl
48 
49 #include <TEnv.h>
50 #include <TString.h>
51 
52 #include "MLog.h"
53 #include "MLogManip.h"
54 
55 #undef DEBUG
56 
57 using namespace std;
58 
59 //ClassImp(MVideo);
60 
61 MVideoCtrl::MVideoCtrl(const v4l2_queryctrl &ctrl)
62 {
63  fId = ctrl.id;
64  fName = (const char*)ctrl.name;
65  fMinimum = ctrl.minimum;
66  fMaximum = ctrl.maximum;
67  fStep = ctrl.step;
68  fDefault = ctrl.default_value;
69 }
70 
71 // -------------------------------------------------------------
72 //
73 // Constructor. Specify the device (e.g. "/dev/video") to be used
74 //
75 MVideo::MVideo(const char *path) : fPath(path), fFileDesc(-1), fMapBuffer(0)
76 {
77  Reset();
78 
79  fControls.SetOwner();
80 }
81 
82 // -------------------------------------------------------------
83 //
84 // Internal function to reset the descriptors of the device
85 //
87 {
88  fInputs.clear();
89  fStandards.clear();
90 
91  memset(&fCaps, 0, sizeof(fCaps));
92  memset(&fChannel, 0, sizeof(fChannel));
93 // memset(&fBuffer, 0, sizeof(fBuffer));
94  memset(&fAbil, 0, sizeof(fAbil));
95 
96  fFileDesc = -1;
97  fMapBuffer = 0;
98  fChannel.channel = -1;
99  fAbil.tuner = -1;
100 
101  fControls.Delete();
102 }
103 
104 // -------------------------------------------------------------
105 //
106 // Mapper around ioctl for easier access to the device
107 //
108 int MVideo::Ioctl(int req, void *opt, bool allowirq, bool force) const
109 {
110  if (fFileDesc<0)
111  {
112  gLog << err << "ERROR - Ioctl: Device " << fPath << " not open." << endl;
113  return -1;
114  }
115 
116  while (1)
117  {
118  // FIXME: This call is a possible source for a hangup
119  const int rc = ioctl(fFileDesc, req, opt);
120  if (rc==0)
121  return 0;
122 
123  if (errno==EINVAL)
124  return 1;
125 
126  if (!allowirq && errno==EAGAIN)
127  return -4;
128 
129  cout <<"errno="<< errno << endl;
130 
131  // errno== 4: Interrupted system call (e.g. by alarm())
132  // errno==16: Device or resource busy
133  if (errno==4 || errno==16)
134  {
135  if (!allowirq && errno==4)
136  return -4;
137 
138  gLog << err << "ERROR - MVideo::Ioctl 0x" << hex << req << ": errno=" << dec << errno << " - ";
139  gLog << strerror(errno) << " (rc=" << rc << ")" << endl;
140  usleep(10);
141  continue;
142  }
143 
144  if (!force)
145  {
146  gLog << err << "ERROR - MVideo::Ioctl 0x" << hex << req << ": errno=" << dec << errno << " - ";
147  gLog << strerror(errno) << " (rc=" << rc << ")" << endl;
148  }
149  return rc;
150  }
151  return -1;
152 }
153 
154 // -------------------------------------------------------------
155 //
156 // Read the capabilities of the device
157 //
159 {
160  return Ioctl(VIDIOCGCAP, &fCaps)!=-1;
161 }
162 
163 // -------------------------------------------------------------
164 //
165 // Read the properties of the device
166 //
168 {
169  return Ioctl(VIDIOCGPICT, &fProp)!=-1;
170 }
171 
172 // -------------------------------------------------------------
173 //
174 // Read the video standard
175 //
177 {
178  return Ioctl(VIDIOC_G_STD, &fVideoStandard)==-1;
179 }
180 
181 // -------------------------------------------------------------
182 //
183 // Read the abilities of the tuner
184 //
186 {
187  fAbil.tuner = 0; // FIXME?
188  return Ioctl(VIDIOCGTUNER, &fAbil)!=-1;
189 }
190 
191 // -------------------------------------------------------------
192 //
193 // Enumerate (get) all controls from the device and store them
194 // as MVideoCtrl in fControls, starting with the id given as
195 // argument.
196 //
197 Bool_t MVideo::EnumerateControls(UInt_t id)
198 {
199  struct v4l2_queryctrl qctrl;
200  memset(&qctrl, 0, sizeof(qctrl));
201  qctrl.id = id;
202 
203  while (1)
204  {
205  if (Ioctl(VIDIOC_QUERYCTRL, &qctrl, true, true)==-1)
206  break;
207 
208  if (qctrl.maximum<=qctrl.minimum)
209  continue;
210 
211  fControls.Add(new MVideoCtrl(qctrl));
212 
213  qctrl.id++;
214  }
215 
216  return kTRUE;
217 }
218 
219 // -------------------------------------------------------------
220 //
221 // Enumerate (get) all basic and private controls from the
222 // device and store them as MVideoCtrl in fControls.
223 //
225 {
226  if (!EnumerateControls(V4L2_CID_BASE))
227  return kFALSE;
228  if (!EnumerateControls(V4L2_CID_PRIVATE_BASE))
229  return kFALSE;
230 
231  return kTRUE;
232 }
233 
234 // -------------------------------------------------------------
235 //
236 // Reset a given control to it's default value as defined
237 // by the device.
238 //
239 Bool_t MVideo::ResetControl(MVideoCtrl &vctrl) const
240 {
241  return WriteControl(vctrl, vctrl.fDefault);
242 }
243 
244 // -------------------------------------------------------------
245 //
246 // Reset all enumereated device controls to their default.
247 // The default is defined by the device iteself.
248 //
249 Bool_t MVideo::ResetControls() const
250 {
251  Bool_t rc = kTRUE;
252 
253  TIter Next(&fControls);
254  MVideoCtrl *ctrl = 0;
255  while ((ctrl=((MVideoCtrl*)Next())))
256  if (!ResetControl(*ctrl))
257  {
258  gLog << err << "ERROR - Could not reset " << ctrl->fName << "." << endl;
259  rc = kFALSE;
260  }
261 
262  return rc;
263 }
264 
265 // -------------------------------------------------------------
266 //
267 // Read the value of the given control from the device
268 // and store it back into the given MVideoCtrl.
269 //
270 Bool_t MVideo::ReadControl(MVideoCtrl &vctrl) const
271 {
272  struct v4l2_control ctrl = { vctrl.fId, 0 };
273  if (Ioctl(VIDIOC_G_CTRL, &ctrl)==-1)
274  return kFALSE;
275 
276  vctrl.fValue = ctrl.value;
277 
278  return kTRUE;
279 }
280 
281 // -------------------------------------------------------------
282 //
283 // Write the given value into the given control of the device.
284 // On success the value is stored in the given MVideoCtrl.
285 //
286 Bool_t MVideo::WriteControl(MVideoCtrl &vctrl, Int_t val) const
287 {
288  if (val<vctrl.fMinimum)
289  {
290  gLog << err << "ERROR - Value of " << val << " below minimum of " << vctrl.fMinimum << " for " << vctrl.fName << endl;
291  return kFALSE;
292  }
293 
294  if (val>vctrl.fMaximum)
295  {
296  gLog << err << "ERROR - Value of " << val << " above maximum of " << vctrl.fMaximum << " for " << vctrl.fName << endl;
297  return kFALSE;
298  }
299 
300  struct v4l2_control ctrl = { vctrl.fId, val };
301  if (Ioctl(VIDIOC_S_CTRL, &ctrl)==-1)
302  return kFALSE;
303 
304  vctrl.fValue = val;
305 
306  return kTRUE;
307 }
308 
309 // -------------------------------------------------------------
310 //
311 // Set all controls from a TEnv. Note that all whitespaces
312 // and colons in the control names (as defined by the name of
313 // the MVideoCtrls stored in fControls) are replaced by
314 // underscores.
315 //
316 Bool_t MVideo::SetControls(TEnv &env) const
317 {
318  Bool_t rc = kTRUE;
319 
320  TIter Next(&fControls);
321  TObject *o = 0;
322  while ((o=Next()))
323  {
324  if (!env.Defined(o->GetName()))
325  continue;
326 
327  TString str = env.GetValue(o->GetName(), "");
328  str = str.Strip(TString::kBoth);
329  str.ReplaceAll(" ", "_");
330  str.ReplaceAll(":", "_");
331  if (str.IsNull())
332  continue;
333 
334  MVideoCtrl &ctrl = *static_cast<MVideoCtrl*>(o);
335 
336  const Int_t val = str=="default" || str=="def" ?
337  ctrl.fDefault : env.GetValue(o->GetName(), 0);
338 
339  if (!WriteControl(ctrl, val))
340  rc = kFALSE;
341  }
342 
343  return rc;
344 }
345 
346 template<class S>
347 Bool_t MVideo::Enumerate(vector<S> &vec, int request)
348 {
349  for (int i=0; ; i++)
350  {
351  S input;
352  input.index = i;
353 
354  const int rc = Ioctl(request, &input);
355  if (rc<0)
356  return kFALSE;
357  if (rc==1)
358  return kTRUE;
359 
360  vec.push_back(input);
361  }
362 
363  return kFALSE;
364 }
365 
367 {
368  gLog << all;
369  for (vector<v4l2_input>::const_iterator it=fInputs.begin(); it!=fInputs.end(); it++)
370  {
371  gLog << "Input #" << it->index << endl;
372  gLog << " - " << it->name << endl;
373  gLog << " - " << (it->type==V4L2_INPUT_TYPE_CAMERA?"Camera":"Tuner") << endl;
374  gLog << " - TV Standard: " << hex << it->std << dec << endl;
375 
376  gLog << " - Status: 0x" << hex << it->status;
377  if (it->status&V4L2_IN_ST_NO_POWER)
378  gLog << " NoPower";
379  if (it->status&V4L2_IN_ST_NO_SIGNAL)
380  gLog << " NoSignal";
381  if (it->status&V4L2_IN_ST_NO_COLOR)
382  gLog << " NoColor";
383  if (it->status&V4L2_IN_ST_NO_H_LOCK)
384  gLog << " NoHLock";
385  if (it->status&V4L2_IN_ST_COLOR_KILL)
386  gLog << " ColorKill";
387  gLog << endl;
388 
389  /*
390  TV Standard
391  ===========
392  #define V4L2_STD_PAL_B ((v4l2_std_id)0x00000001)
393  #define V4L2_STD_PAL_B1 ((v4l2_std_id)0x00000002)
394  #define V4L2_STD_PAL_G ((v4l2_std_id)0x00000004)
395  #define V4L2_STD_PAL_H ((v4l2_std_id)0x00000008)
396  #define V4L2_STD_PAL_I ((v4l2_std_id)0x00000010)
397  #define V4L2_STD_PAL_D ((v4l2_std_id)0x00000020)
398  #define V4L2_STD_PAL_D1 ((v4l2_std_id)0x00000040)
399  #define V4L2_STD_PAL_K ((v4l2_std_id)0x00000080)
400 
401  #define V4L2_STD_PAL_M ((v4l2_std_id)0x00000100)
402  #define V4L2_STD_PAL_N ((v4l2_std_id)0x00000200)
403  #define V4L2_STD_PAL_Nc ((v4l2_std_id)0x00000400)
404  #define V4L2_STD_PAL_60 ((v4l2_std_id)0x00000800)
405  V4L2_STD_PAL_60 is a hybrid standard with 525 lines, 60 Hz refresh rate, and PAL color modulation with a 4.43 MHz color subcarrier. Some PAL video recorders can play back NTSC tapes in this mode for display on a 50/60 Hz agnostic PAL TV.
406 
407  #define V4L2_STD_NTSC_M ((v4l2_std_id)0x00001000)
408  #define V4L2_STD_NTSC_M_JP ((v4l2_std_id)0x00002000)
409  #define V4L2_STD_NTSC_443 ((v4l2_std_id)0x00004000)
410  V4L2_STD_NTSC_443 is a hybrid standard with 525 lines, 60 Hz refresh rate, and NTSC color modulation with a 4.43 MHz color subcarrier.
411 
412  #define V4L2_STD_NTSC_M_KR ((v4l2_std_id)0x00008000)
413 
414  #define V4L2_STD_SECAM_B ((v4l2_std_id)0x00010000)
415  #define V4L2_STD_SECAM_D ((v4l2_std_id)0x00020000)
416  #define V4L2_STD_SECAM_G ((v4l2_std_id)0x00040000)
417  #define V4L2_STD_SECAM_H ((v4l2_std_id)0x00080000)
418  #define V4L2_STD_SECAM_K ((v4l2_std_id)0x00100000)
419  #define V4L2_STD_SECAM_K1 ((v4l2_std_id)0x00200000)
420  #define V4L2_STD_SECAM_L ((v4l2_std_id)0x00400000)
421  #define V4L2_STD_SECAM_LC ((v4l2_std_id)0x00800000)
422 
423 
424  // ATSC/HDTV
425  #define V4L2_STD_ATSC_8_VSB ((v4l2_std_id)0x01000000)
426  #define V4L2_STD_ATSC_16_VSB ((v4l2_std_id)0x02000000)
427  V4L2_STD_ATSC_8_VSB and V4L2_STD_ATSC_16_VSB are U.S. terrestrial digital TV standards. Presently the V4L2 API does not support digital TV. See also the Linux DVB API at http://linuxtv.org.
428 
429  #define V4L2_STD_PAL_BG (V4L2_STD_PAL_B | V4L2_STD_PAL_B1 | V4L2_STD_PAL_G)
430  #define V4L2_STD_B (V4L2_STD_PAL_B | V4L2_STD_PAL_B1 | V4L2_STD_SECAM_B)
431  #define V4L2_STD_GH (V4L2_STD_PAL_G | V4L2_STD_PAL_H | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H)
432  #define V4L2_STD_PAL_DK (V4L2_STD_PAL_D | V4L2_STD_PAL_D1 | V4L2_STD_PAL_K)
433  #define V4L2_STD_PAL (V4L2_STD_PAL_BG | V4L2_STD_PAL_DK | V4L2_STD_PAL_H | V4L2_STD_PAL_I)
434  #define V4L2_STD_NTSC (V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_JP | V4L2_STD_NTSC_M_KR)
435  #define V4L2_STD_MN (V4L2_STD_PAL_M | V4L2_STD_PAL_N | V4L2_STD_PAL_Nc | V4L2_STD_NTSC)
436  #define V4L2_STD_SECAM_DK (V4L2_STD_SECAM_D | V4L2_STD_SECAM_K | V4L2_STD_SECAM_K1)
437  #define V4L2_STD_DK (V4L2_STD_PAL_DK | V4L2_STD_SECAM_DK)
438  #define V4L2_STD_SECAM (V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H | V4L2_STD_SECAM_DK | V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC)
439  #define V4L2_STD_525_60 (V4L2_STD_PAL_M | V4L2_STD_PAL_60 | V4L2_STD_NTSC | V4L2_STD_NTSC_443)
440  #define V4L2_STD_625_50 (V4L2_STD_PAL | V4L2_STD_PAL_N | V4L2_STD_PAL_Nc | V4L2_STD_SECAM)
441  #define V4L2_STD_UNKNOWN 0
442  #define V4L2_STD_ALL (V4L2_STD_525_60 | V4L2_STD_625_50)
443  */
444 
445  /*
446  Status:
447  =======
448  General
449  V4L2_IN_ST_NO_POWER 0x00000001 Attached device is off.
450  V4L2_IN_ST_NO_SIGNAL 0x00000002
451  V4L2_IN_ST_NO_COLOR 0x00000004 The hardware supports color decoding, but does not detect color modulation in the signal.
452 
453  Analog Video
454  V4L2_IN_ST_NO_H_LOCK 0x00000100 No horizontal sync lock.
455  V4L2_IN_ST_COLOR_KILL 0x00000200 A color killer circuit automatically disables color decoding when it detects no color modulation. When this flag is set the color killer is enabled and has shut off color decoding.
456 
457  Digital Video
458  V4L2_IN_ST_NO_SYNC 0x00010000 No synchronization lock.
459  V4L2_IN_ST_NO_EQU 0x00020000 No equalizer lock.
460  V4L2_IN_ST_NO_CARRIER 0x00040000 Carrier recovery failed.
461 
462  VCR and Set-Top Box
463  V4L2_IN_ST_MACROVISION 0x01000000 Macrovision is an analog copy prevention system mangling the video signal to confuse video recorders. When this flag is set Macrovision has been detected.
464  V4L2_IN_ST_NO_ACCESS 0x02000000 Conditional access denied.
465  V4L2_IN_ST_VTR 0x04000000 VTR time constant. [?]
466  */
467  }
468 }
469 
471 {
472  gLog << all;
473  for (vector<v4l2_standard>::const_iterator it=fStandards.begin(); it!=fStandards.end(); it++)
474  {
475  gLog << "Index #" << it->index << endl;
476  gLog << " - TV Standard: " << it->name << hex << "(" << it->id << ")" << dec << endl;
477  gLog << " - FPS: " << it->frameperiod.numerator << "/" << it->frameperiod.denominator << endl;
478  gLog << " - Lines: " << it->framelines << endl;
479  }
480 }
481 
482 // -------------------------------------------------------------
483 //
484 // Open channel ch of the device
485 //
486 Bool_t MVideo::Open(Int_t ch)
487 {
488  const Bool_t rc = Init(ch);
489  if (!rc)
490  Close();
491  return rc;
492 }
493 
494 // -------------------------------------------------------------
495 //
496 // Open a channel of the device and retriev all necessary
497 // informations from the driver. Initialize the shared
498 // memory. Other access methods are not supported yet.
499 //
500 Bool_t MVideo::Init(Int_t channel)
501 {
502  if (IsOpen())
503  {
504  gLog << warn << "WARNING - Device " << fPath << " already open." << endl;
505  return kTRUE;
506  }
507 
508  gLog << all << "Opening " << fPath << "... " << flush;
509  do
510  {
511  fFileDesc = open(fPath, O_RDWR|O_NONBLOCK, 0);
512  usleep(1);
513  }
514  while (errno==19 && fFileDesc==-1);
515 
516  if (fFileDesc == -1)
517  {
518  gLog << err << "ERROR: " << strerror(errno) << endl;
519  return kFALSE;
520  }
521 
522  gLog << "done (" << fFileDesc << ")." << endl;
523 
524  // Close device on exit
525  if (fcntl(fFileDesc, F_SETFD, FD_CLOEXEC)<0)
526  {
527  gLog << err << "ERROR - Call to fnctl (F_SETFD, FD_CLOEXEC) failed." << endl;
528  return kFALSE;
529  }
530 
531 
532 
533 /*
534  if (!Enumerate(fInputs, VIDIOC_ENUMINPUT))
535  {
536  gLog << err << "ERROR - Could not enumerate inputs." << endl;
537  return kFALSE;
538  }
539  PrintInputs();
540 
541  if (!Enumerate(fStandards, VIDIOC_ENUMSTD))
542  {
543  gLog << err << "ERROR - Could not enumerate inputs." << endl;
544  return kFALSE;
545  }
546  PrintStandards();
547  */
548 
549  int index = 3;
550  if (Ioctl(VIDIOC_S_INPUT, &index)==-1)
551  {
552  gLog << err << "ERROR - Could not set input." << endl;
553  return kFALSE;
554  }
555 
556  //check the input
557  if (Ioctl(VIDIOC_G_INPUT, &index))
558  {
559  gLog << err << "ERROR - Could not get input." << endl;
560  return kFALSE;
561  }
562 
563  v4l2_input input;
564  memset(&input, 0, sizeof (input));
565  input.index = index;
566  if (Ioctl(VIDIOC_ENUMINPUT, &input))
567  {
568  gLog << err << "ERROR - Could enum input." << endl;
569  return kFALSE;
570  }
571  gLog << "*** Input: " << input.name << " (" << input.index << ")" << endl;
572 
573  v4l2_std_id st = 4;//standard.id;
574  if (Ioctl (VIDIOC_S_STD, &st))
575  {
576  gLog << err << "ERROR - Could not set standard." << endl;
577  return kFALSE;
578  }
579 
580  v4l2_capability cap;
581  if (Ioctl(VIDIOC_QUERYCAP, &cap))
582  {
583  gLog << err << "ERROR - Could not get capabilities." << endl;
584  return kFALSE;
585  }
586 
587  if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE))
588  {
589  gLog << err << "ERROR - No capture capabaility." << endl;
590  return kFALSE;
591  }
592 
593  v4l2_cropcap cropcap;
594  cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
595 
596  if (Ioctl(VIDIOC_CROPCAP, &cropcap)==-1)
597  {
598  }
599 
600  v4l2_crop crop;
601  crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
602  crop.c = cropcap.defrect; /* reset to default */
603 
604  if (Ioctl(VIDIOC_S_CROP, &crop))
605  {
606  gLog << err << "Could not reset cropping." << endl;
607  return kFALSE;
608  }
609 
610  v4l2_format fmt;
611  fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
612  fmt.fmt.pix.width = 768;
613  fmt.fmt.pix.height = 576;
614  fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB32;
615 
616  if (Ioctl(VIDIOC_S_FMT, &fmt)==-1)
617  {
618  gLog << err << "ERROR - Could not set format." << endl;
619  return kFALSE;
620  }
621  // The image format must be selected before buffers are allocated,
622  // with the VIDIOC_S_FMT ioctl. When no format is selected the driver
623  // may use the last, possibly by another application requested format.
624 
625  v4l2_requestbuffers reqbuf;
626  memset (&reqbuf, 0, sizeof (reqbuf));
627 
628  reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
629  reqbuf.memory = V4L2_MEMORY_MMAP;
630  reqbuf.count = 4;//125;
631 
632  if (Ioctl(VIDIOC_REQBUFS, &reqbuf)==-1)
633  {
634  gLog << err << "ERROR - Couldn't setup frame buffers." << endl;
635  return kFALSE;
636  }
637 
638  gLog << all << "Allocated " << reqbuf.count << " frame buffers." << endl;
639 
640  for (unsigned int i=0; i<reqbuf.count; i++)
641  {
642  v4l2_buffer buffer;
643  memset (&buffer, 0, sizeof (buffer));
644 
645  buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
646  buffer.memory = V4L2_MEMORY_MMAP;
647  buffer.index = i;
648 
649  if (Ioctl(VIDIOC_QUERYBUF, &buffer))
650  {
651  gLog << err << "ERROR - Request of frame buffer " << i << " failed." << endl;
652  return kFALSE;
653  }
654 
655  void *ptr = mmap(NULL, buffer.length,
656  PROT_READ | PROT_WRITE,
657  MAP_SHARED,
658  fFileDesc, buffer.m.offset);
659 
660  if (MAP_FAILED == ptr)
661  {
662 
663  gLog << err << "ERROR - Could not allocate shared memory." << endl;
664  return kFALSE;
665  // If you do not exit here you should unmap() and free()
666  // the buffers mapped so far.
667  //perror ("mmap");
668  //exit (EXIT_FAILURE);
669  }
670 
671  fBuffers.push_back(make_pair(buffer, ptr));
672  }
673 
674  return kTRUE;
675 }
676 
678 {
679  v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
680  if (Ioctl(VIDIOC_STREAMON, &type)==-1)
681  {
682  gLog << err << "ERROR - Couldn't start capturing." << endl;
683  return kFALSE;
684  }
685 
686  cout << "*** Stream on" << endl;
687 
688  return kTRUE;
689 }
690 
691 // -------------------------------------------------------------
692 //
693 // Close device. Free the shared memory
694 //
696 {
697  // if (!IsOpen())
698  // return kTRUE;
699 /*
700  if (Ioctl(VIDIOC_STREAMON, &fBuffers[0])==-1)
701  {
702  gLog << err << "ERROR - Couldn't start capturing." << endl;
703  return kFALSE;
704  }
705 */
706  Bool_t rc = kTRUE;
707 
708  gLog << all << "Closing " << fPath << " (" << fFileDesc << ")... " << flush;
709  if (fFileDesc != -1)
710  {
711  if (close(fFileDesc)<0)
712  {
713  gLog << err << "ERROR!" << endl;
714  rc = kFALSE;
715  }
716  fFileDesc = -1;
717  }
718  gLog << "done." << endl;
719 
720  // unmap device memory
721  for (vector<pair<v4l2_buffer,void*> >::iterator it=fBuffers.begin(); it!=fBuffers.end(); it++)
722  {
723  munmap(it->second, it->first.length);
724  fBuffers.erase(it);
725  }
726 
727  Reset();
728 
729  return rc;
730 }
731 
732 // -------------------------------------------------------------
733 //
734 // Instruct hardware to start capture into framebuffer frame
735 //
736 Bool_t MVideo::CaptureStart(unsigned int frame) const
737 {
738  frame %= fBuffers.size();
739 
740 // cout << "*** CaptureStart " << frame << endl;
741 
742  if (Ioctl(VIDIOC_QBUF, const_cast<v4l2_buffer*>(&fBuffers[frame].first))==-1)
743  {
744  gLog << err << "ERROR - Couldn't buffer " << frame << "." << endl;
745  return kFALSE;
746  }
747 
748 // cout << "*** " << errno << endl;
749 
750  return kTRUE;
751 
752  /*
753  struct video_mmap gb =
754  {
755  frame, // frame
756  fCaps.maxheight, fCaps.maxwidth, // height, width
757  VIDEO_PALETTE_RGB24 // palette
758  };
759 
760 #ifdef DEBUG
761  gLog << dbg << "CapturStart(" << frame << ")" << endl;
762 #endif
763 
764  //
765  // capture frame
766  //
767  if (Ioctl(VIDIOCMCAPTURE, &gb) != -1)
768  return kTRUE;
769 
770 // if (errno == EAGAIN)
771  gLog << err;
772  gLog << "ERROR - Couldn't start capturing frame " << frame << "." << endl;
773  gLog << " Maybe your card doesn't support VIDEO_PALETTE_RGB24." << endl;
774  return kFALSE;
775  */
776 }
777 
778 // -------------------------------------------------------------
779 //
780 // Wait until hardware has finished capture into framebuffer frame
781 //
782 Int_t MVideo::CaptureWait(unsigned int frame, unsigned char **ptr) const
783 {
784  frame %= fBuffers.size();
785 
786  if (ptr)
787  *ptr = NULL;
788 
789 // const int SYNC_TIMEOUT = 1;
790 
791 //#ifdef DEBUG
792 // cout << "*** CaptureWait " << frame << endl;
793 //#endif
794 
795  //alarm(SYNC_TIMEOUT);
796  const Int_t rc = Ioctl(VIDIOC_DQBUF, const_cast<v4l2_buffer*>(&fBuffers[frame].first), false);
797  if (rc==-4)
798  {
799  //cout << "ERROR - Waiting for frame " << frame << " timed out." << endl;
800  return kSKIP;
801  }
802  //alarm(0);
803 
804  if (rc==-1)
805  {
806  gLog << err << "ERROR - Waiting for " << frame << " frame failed." << endl;
807  return kFALSE;
808  }
809 
810  if (ptr)
811  *ptr = static_cast<unsigned char*>(fBuffers[frame].second);
812 
813  return kTRUE;
814 }
815 
816 // -------------------------------------------------------------
817 //
818 // Change the channel of a priviously opened device
819 //
820 Int_t MVideo::SetChannel(Int_t chan)
821 {
822  return kSKIP;
823 
824  if (fChannel.channel==chan)
825  return kSKIP;
826 
827  if (chan<0 || chan>=fCaps.channels)
828  {
829  gLog << err << "ERROR - Set channel " << chan << " out of range." << endl;
830  return kFALSE;
831  }
832 
833  // Switch to channel
834  struct video_channel ch = { chan, "", 0, 0, 0, 0 };
835  if (Ioctl(VIDIOCSCHAN, &ch)==-1)
836  {
837  gLog << err << "ERROR - Couldn't switch to channel " << chan << "." << endl;
838  gLog << " You might need a bttv version > 0.5.13" << endl;
839  return kFALSE;
840  }
841 
842  // Get information about channel
843  if (Ioctl(VIDIOCGCHAN, &ch)==-1)
844  {
845  gLog << err << "ERROR - Getting information for channel " << chan << " failed." << endl;
846  return kFALSE;
847  }
848 
849  memcpy(&fChannel, &ch, sizeof(fChannel));
850 
851  gLog << all << "Switched to channel " << chan << endl;
852 
853  return kTRUE;
854 }
855 
856 // -------------------------------------------------------------
857 //
858 // Has the device capture capabilities?
859 //
860 Bool_t MVideo::CanCapture() const
861 {
862  return fCaps.type&VID_TYPE_CAPTURE;
863 }
864 
865 // -------------------------------------------------------------
866 //
867 // Has a tuner
868 //
869 Bool_t MVideo::HasTuner() const
870 {
871  return fCaps.type&VID_TYPE_TUNER;
872 }
873 
874 // -------------------------------------------------------------
875 //
876 // Returns the number of frame buffers which can be used
877 //
879 {
880  return fBuffers.size();
881 }
882 
883 // -------------------------------------------------------------
884 //
885 // Maximum width of the frame which can be captured
886 //
887 Int_t MVideo::GetWidth() const
888 {
889  return 768;//fCaps.maxwidth;
890 }
891 
892 // -------------------------------------------------------------
893 //
894 // Maximum height of the frame which can be captured
895 //
896 Int_t MVideo::GetHeight() const
897 {
898  return 576;//fCaps.maxheight;
899 }
900 
901 // -------------------------------------------------------------
902 //
903 // Return the device type as string
904 //
905 TString MVideo::GetDevType(int type) const
906 {
907  TString rc;
908  if (CanCapture())
909  rc += " capture";
910  if (HasTuner())
911  rc += " tuner";
912  if (type&VID_TYPE_TELETEXT)
913  rc += " teletext";
914  if (type&VID_TYPE_OVERLAY)
915  rc += " overlay";
916  if (type&VID_TYPE_CHROMAKEY)
917  rc += " chromakey";
918  if (type&VID_TYPE_CLIPPING)
919  rc += " clipping";
920  if (type&VID_TYPE_FRAMERAM)
921  rc += " frameram";
922  if (type&VID_TYPE_SCALES)
923  rc += " scales";
924  if (type&VID_TYPE_MONOCHROME)
925  rc += " monochrom";
926  if (type&VID_TYPE_SUBCAPTURE)
927  rc += " subcapature";
928  return rc;
929 }
930 
931 TString MVideo::GetTunerFlags(Int_t flags) const
932 {
933  TString rc;
934  if (flags&VIDEO_TUNER_PAL)
935  rc += " PAL";
936  if (flags&VIDEO_TUNER_NTSC)
937  rc += " NTSC";
938  if (flags&VIDEO_TUNER_SECAM)
939  rc += " SECAM";
940  if (flags&VIDEO_TUNER_LOW)
941  rc += " kHz";
942  if (flags&VIDEO_TUNER_NORM)
943  rc += " CanSetNorm";
944  if (flags&VIDEO_TUNER_STEREO_ON)
945  rc += " StereoOn";
946  return rc;
947 }
948 
949 TString MVideo::GetTunerMode(Int_t mode) const
950 {
951  switch (mode)
952  {
953  case VIDEO_MODE_PAL:
954  return "PAL";
955  case VIDEO_MODE_NTSC:
956  return "NTSC";
957  case VIDEO_MODE_SECAM:
958  return "SECAM";
959  case VIDEO_MODE_AUTO:
960  return "AUTO";
961  }
962  return "undefined";
963 }
964 
965 // -------------------------------------------------------------
966 //
967 // Return the channel flags as string
968 //
969 TString MVideo::GetChannelFlags(Int_t flags) const
970 {
971  TString rc = "video";
972  if (flags&VIDEO_VC_TUNER)
973  rc += " tuner";
974  if (flags&VIDEO_VC_AUDIO)
975  rc += " audio";
976 // if (flags&VIDEO_VC_NORM)
977 // rc += " normsetting";
978  return rc;
979 }
980 
981 // -------------------------------------------------------------
982 //
983 // Return the channel type as string
984 //
985 TString MVideo::GetChannelType(Int_t type) const
986 {
987  if (type&VIDEO_TYPE_TV)
988  return "TV";
989  if (type&VIDEO_TYPE_CAMERA)
990  return "Camera";
991  return "unknown";
992 }
993 
994 // -------------------------------------------------------------
995 //
996 // Return the palette pal as string
997 //
998 TString MVideo::GetPalette(Int_t pal) const
999 {
1000  switch (pal)
1001  {
1002  case VIDEO_PALETTE_GREY:
1003  return "VIDEO_PALETTE_GREY: Linear intensity grey scale";
1004  case VIDEO_PALETTE_HI240:
1005  return "VIDEO_PALETTE_HI240: BT848 8-bit color cube";
1006  case VIDEO_PALETTE_RGB565:
1007  return "VIDEO_PALETTE_RGB565: RGB565 packed into 16-bit words";
1008  case VIDEO_PALETTE_RGB555:
1009  return "VIDEO_PALETTE_RGB555: RGB555 packed into 16-bit words, top bit undefined";
1010  case VIDEO_PALETTE_RGB24:
1011  return "VIDEO_PALETTE_RGB24: RGB888 packed into 24-bit words";
1012  case VIDEO_PALETTE_RGB32:
1013  return "VIDEO_PALETTE_RGB32: RGB888 packed into the low three bytes of 32-bit words. Top bits undefined.";
1014  case VIDEO_PALETTE_YUV422:
1015  return "VIDEO_PALETTE_YUV422: Video style YUV422 - 8-bit packed, 4-bit Y, 2-bits U, 2-bits V";
1016  case VIDEO_PALETTE_YUYV:
1017  return "VIDEO_PALETTE_YUYV: YUYV";
1018  case VIDEO_PALETTE_UYVY:
1019  return "VIDEO_PALETTE_UYVY: UYVY";
1020  case VIDEO_PALETTE_YUV420:
1021  return "VIDEO_PALETTE_YUV420: YUV420";
1022  case VIDEO_PALETTE_YUV411:
1023  return "VIDEO_PALETTE_YUV411: YUV411";
1024  case VIDEO_PALETTE_RAW:
1025  return "VIDEO_PALETTE_RAW: Raw capture (Bt848)";
1026  case VIDEO_PALETTE_YUV422P:
1027  return "VIDEO_PALETTE_YUV422P: YUV 4:2:2 planar";
1028  case VIDEO_PALETTE_YUV411P:
1029  return "VIDEO_PALETTE_YUV411P: YUV 4:1:1 planar";
1030  }
1031  return "unknown";
1032 }
1033 
1034 // -------------------------------------------------------------
1035 //
1036 // Print informations about the device, the capabilities, the
1037 // channel and all available information
1038 //
1039 void MVideo::Print() const
1040 {
1041  gLog << all << dec;
1042 
1043  gLog << "Device " << fPath << " " << (fFileDesc>0?"open":"closed") << "." << endl;
1044 
1045  if (fFileDesc<=0)
1046  return;
1047 
1048  gLog << " - Name: " << fCaps.name << endl;
1049  gLog << " - DevType: " << GetDevType(fCaps.type) << endl;
1050  gLog << " - Channels: " << fCaps.channels << endl;
1051  gLog << " - Audios: " << fCaps.audios << endl;
1052  gLog << " - Size: ";
1053  gLog << fCaps.minwidth << "x" << fCaps.minheight << " to ";
1054  gLog << fCaps.maxwidth << "x" << fCaps.maxheight << endl;
1055  gLog << endl;
1056  if (fChannel.channel>=0)
1057  {
1058  gLog << " - Channel: " << fChannel.channel << " (" << fChannel.name << ")" << endl;
1059  gLog << " - IsA: " << GetChannelType(fChannel.type) << " with " << GetChannelFlags(fChannel.flags) << " (" << fChannel.flags << ")" << endl;
1060  //if (fChannel.flags&VIDEO_VC_NORM)
1061  gLog << " - Norm: " << fChannel.norm << endl;
1062  gLog << endl;
1063  }
1064 
1065  if (fAbil.tuner>=0)
1066  {
1067  gLog << " - Tuner: " << fAbil.tuner << endl;
1068  gLog << " - Name: " << fAbil.name << endl;
1069  // gLog << " - Tuner Range: " << fAbil.rangelow << " - " << fAbil.rangehigh << endl;
1070  gLog << " - Tuner flags: " << GetTunerFlags(fAbil.flags) << " (" << fAbil.flags << ")" << endl;
1071  gLog << " - Tuner mode: " << GetTunerMode(fAbil.mode) << " (" << fAbil.mode << ")" <<endl;
1072  gLog << " - Signal Strength: " << fAbil.signal << endl;
1073  }
1074 
1075  gLog << " - Brightness: " << fProp.brightness << endl;
1076  gLog << " - Hue: " << fProp.hue << endl;
1077  gLog << " - Color: " << fProp.colour << endl;
1078  gLog << " - Contrast: " << fProp.contrast << endl;
1079  gLog << " - Whiteness: " << fProp.whiteness << endl;
1080  gLog << " - Depth: " << fProp.depth << endl;
1081  gLog << " - Palette: " << GetPalette(fProp.palette) << " (" << fProp.palette << ")" << endl;
1082  gLog << endl;
1083 
1084 // gLog << " - BufferSize: 0x" << hex << fBuffer.size << " (" << dec << fBuffer.frames << " frames)" << endl;
1085 // gLog << " - Offsets: " << hex;
1086 // for (int i=0; i<fBuffer.frames; i++)
1087 // gLog << " 0x" << fBuffer.offsets[i];
1088 // gLog << dec << endl;
1089 
1090  gLog << inf2 << "Controls:" << endl;
1091  fControls.Print();
1092 }
1093 
1094 /*
1095 void MVideo::SetPicPar(int bright, int hue, int contrast)
1096 {
1097  struct video_picture pict;
1098 
1099  Ioctl(VIDIOCGPICT, &pict); // get
1100 
1101  if (contrast != -1)
1102  pict.contrast = contrast;
1103 
1104  if (bright != -1)
1105  pict.brightness = bright;
1106 
1107  if (hue != -1)
1108  pict.hue = hue;
1109 
1110  Ioctl(VIDIOCSPICT, &pict); //set
1111 }
1112 
1113 void MVideo::GetPicPar(int *bright, int *hue, int *contrast)
1114 {
1115  struct video_picture pict;
1116 
1117  Ioctl(VIDIOCGPICT, &pict); // get
1118 
1119  *contrast = pict.contrast;
1120  *bright = pict.brightness;
1121  *hue = pict.hue;
1122 }
1123 */
char name[32]
Definition: videodev.h:60
#define VIDEO_PALETTE_YUYV
Definition: videodev.h:121
#define VIDEO_PALETTE_UYVY
Definition: videodev.h:122
TString fName
Definition: MVideo.h:32
Int_t GetWidth() const
Definition: MVideo.cc:887
struct video_picture fProp
Definition: MVideo.h:62
#define VID_TYPE_SUBCAPTURE
Definition: videodev.h:56
#define VIDEO_MODE_AUTO
Definition: videodev.h:101
Int_t fMaximum
Definition: MVideo.h:34
void Print() const
Definition: MVideo.cc:1039
__u32 flags
Definition: videodev.h:76
Bool_t ResetControl(MVideoCtrl &vctrl) const
Definition: MVideo.cc:239
#define VIDEO_PALETTE_YUV420
Definition: videodev.h:123
#define VIDEO_VC_AUDIO
Definition: videodev.h:78
void PrintInputs() const
Definition: MVideo.cc:366
__u32 flags
Definition: videodev.h:90
int fFileDesc
Definition: MVideo.h:54
#define VIDEO_PALETTE_RAW
Definition: videodev.h:125
std::vector< v4l2_standard > fStandards
Definition: MVideo.h:68
int mode
#define VID_TYPE_CAPTURE
Definition: videodev.h:47
TString fPath
Definition: MVideo.h:52
#define VIDEO_PALETTE_HI240
Definition: videodev.h:115
int i
Definition: db_dim_client.c:21
void PrintStandards() const
Definition: MVideo.cc:470
#define VIDEO_TUNER_PAL
Definition: videodev.h:91
int Ioctl(int req, void *opt, bool allowirq=true, bool force=false) const
Definition: MVideo.cc:108
#define VIDIOCGCAP
Definition: videodev.h:230
char str[80]
Definition: test_client.c:7
__u16 depth
Definition: videodev.h:112
Bool_t HasTuner() const
Definition: MVideo.cc:869
Int_t GetHeight() const
Definition: MVideo.cc:896
__u16 norm
Definition: videodev.h:82
STL namespace.
Bool_t IsOpen() const
Definition: MVideo.h:105
__u16 palette
Definition: videodev.h:113
#define VID_TYPE_TUNER
Definition: videodev.h:48
char id[4]
Definition: FITS.h:71
#define VID_TYPE_TELETEXT
Definition: videodev.h:49
#define VIDEO_PALETTE_YUV422P
Definition: videodev.h:126
Bool_t Open(Int_t channel=0)
Definition: MVideo.cc:486
int64_t first
Size of this column in the tile.
Definition: zofits.h:26
#define VID_TYPE_SCALES
Definition: videodev.h:54
struct video_capability fCaps
Definition: MVideo.h:59
#define gLog
Definition: fits.h:36
Int_t Close()
Definition: MVideo.cc:695
#define VID_TYPE_FRAMERAM
Definition: videodev.h:53
#define VID_TYPE_CHROMAKEY
Definition: videodev.h:51
Bool_t ResetControls() const
Definition: MVideo.cc:249
TString GetDevType(int type) const
Definition: MVideo.cc:905
__u16 contrast
Definition: videodev.h:110
TString GetPalette(Int_t pal) const
Definition: MVideo.cc:998
Bool_t GetTunerAbilities()
Definition: MVideo.cc:185
__u16 mode
Definition: videodev.h:97
#define VIDEO_TUNER_STEREO_ON
Definition: videodev.h:96
#define VIDEO_VC_TUNER
Definition: videodev.h:77
__u16 brightness
Definition: videodev.h:107
TList fControls
Definition: MVideo.h:71
TString GetTunerMode(Int_t type) const
Definition: MVideo.cc:949
#define VID_TYPE_CLIPPING
Definition: videodev.h:52
Int_t CaptureWait(unsigned int frame, unsigned char **ptr=0) const
Definition: MVideo.cc:782
char name[32]
Definition: videodev.h:74
TString GetChannelFlags(Int_t flags) const
Definition: MVideo.cc:969
Bool_t EnumerateControls()
Definition: MVideo.cc:224
int type
Bool_t GetVideoStandard()
Definition: MVideo.cc:176
__u16 signal
Definition: videodev.h:102
Int_t GetNumBuffers() const
Definition: MVideo.cc:878
#define VID_TYPE_MONOCHROME
Definition: videodev.h:55
Bool_t CanCapture() const
Definition: MVideo.cc:860
TString GetTunerFlags(Int_t type) const
Definition: MVideo.cc:931
ULong64_t fVideoStandard
Definition: MVideo.h:65
struct video_channel fChannel
Definition: MVideo.h:60
Bool_t CaptureStart(unsigned int frame) const
Definition: MVideo.cc:736
struct video_tuner fAbil
Definition: MVideo.h:63
Bool_t Enumerate(std::vector< S > &s, int request)
Definition: MVideo.cc:347
#define VIDEO_MODE_SECAM
Definition: videodev.h:100
#define VIDEO_PALETTE_RGB24
Definition: videodev.h:117
int tuner
Definition: videodev.h:87
#define VIDEO_PALETTE_GREY
Definition: videodev.h:114
#define VIDEO_PALETTE_YUV411P
Definition: videodev.h:127
Int_t SetChannel(Int_t chan)
Definition: MVideo.cc:820
char name[32]
Definition: videodev.h:88
#define VIDIOCGPICT
Definition: videodev.h:235
UInt_t fId
Definition: MVideo.h:30
Bool_t Start()
Definition: MVideo.cc:677
#define VIDEO_TYPE_TV
Definition: videodev.h:80
Bool_t ReadControl(MVideoCtrl &vctrl) const
Definition: MVideo.cc:270
int buffer[BUFFSIZE]
Definition: db_dim_client.c:14
Bool_t WriteControl(MVideoCtrl &vctrl, Int_t val) const
Definition: MVideo.cc:286
uint16_t fId
Definition: HeadersFAD.h:93
__u16 colour
Definition: videodev.h:109
#define VIDEO_TUNER_NORM
Definition: videodev.h:95
#define VIDIOCGTUNER
Definition: videodev.h:233
#define VIDEO_MODE_NTSC
Definition: videodev.h:99
std::vector< std::pair< v4l2_buffer, void * > > fBuffers
Definition: MVideo.h:69
#define VIDEO_PALETTE_RGB32
Definition: videodev.h:118
#define VIDEO_PALETTE_RGB555
Definition: videodev.h:119
#define VIDIOCGCHAN
Definition: videodev.h:231
unsigned char * fMapBuffer
Definition: MVideo.h:56
#define VIDEO_TUNER_NTSC
Definition: videodev.h:92
#define VIDEO_TYPE_CAMERA
Definition: videodev.h:81
UInt_t fValue
Definition: MVideo.h:39
#define VIDEO_TUNER_LOW
Definition: videodev.h:94
#define VIDEO_MODE_PAL
Definition: videodev.h:98
Int_t fDefault
Definition: MVideo.h:36
MVideoCtrl(const v4l2_queryctrl &ctrl)
Definition: MVideo.cc:61
#define VIDEO_PALETTE_YUV422
Definition: videodev.h:120
Bool_t SetControls(TEnv &env) const
Definition: MVideo.cc:316
Bool_t GetCapabilities()
Definition: MVideo.cc:158
#define VIDEO_PALETTE_RGB565
Definition: videodev.h:116
#define VIDEO_TUNER_SECAM
Definition: videodev.h:93
std::vector< v4l2_input > fInputs
Definition: MVideo.h:67
Bool_t GetProperties()
Definition: MVideo.cc:167
TString GetChannelType(Int_t type) const
Definition: MVideo.cc:985
Bool_t Init(Int_t channel)
Definition: MVideo.cc:500
void Reset()
Definition: MVideo.cc:86
__u16 type
Definition: videodev.h:79
#define VIDEO_PALETTE_YUV411
Definition: videodev.h:124
#define VID_TYPE_OVERLAY
Definition: videodev.h:50
Int_t fMinimum
Definition: MVideo.h:33
MVideo(const char *path="/dev/video0")
Definition: MVideo.cc:75
__u16 whiteness
Definition: videodev.h:111
#define VIDIOCSCHAN
Definition: videodev.h:232