Panda3D
 All Classes Functions Variables Enumerations
webcamVideoV4L.cxx
00001 // Filename: webcamVideoV4L.cxx
00002 // Created by: rdb (11Jun2010)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "webcamVideoV4L.h"
00016 
00017 #ifdef HAVE_VIDEO4LINUX
00018 
00019 #include "webcamVideoCursorV4L.h"
00020 #include "dcast.h"
00021 
00022 #include <fcntl.h>
00023 #include <sys/ioctl.h>
00024 #include <linux/videodev2.h>
00025 
00026 TypeHandle WebcamVideoV4L::_type_handle;
00027 
00028 ////////////////////////////////////////////////////////////////////
00029 //     Function: find_all_webcams_v4l
00030 //       Access: Public, Static
00031 //  Description: Finds all Video4Linux webcams and adds them to
00032 //               the global list _all_webcams.
00033 ////////////////////////////////////////////////////////////////////
00034 void find_all_webcams_v4l() {
00035   struct v4l2_capability cap2;
00036 
00037   vector_string devs;
00038   GlobPattern pattern ("/dev/video*");
00039   pattern.match_files(devs);
00040   for (vector_string::iterator it = devs.begin(); it != devs.end(); ++it) {
00041     int fd = open(it->c_str(), O_RDWR);
00042     if (fd != -1) {
00043       // Check for Video4Linux2 capabilities
00044       if (ioctl(fd, VIDIOC_QUERYCAP, &cap2) != -1) {
00045         if ((cap2.capabilities & V4L2_CAP_VIDEO_CAPTURE) &&
00046             (cap2.capabilities & V4L2_CAP_STREAMING)) {
00047           struct v4l2_fmtdesc fmt;
00048           for (int i = 0;; i++) {
00049             memset(&fmt, 0, sizeof fmt);
00050             fmt.index = i;
00051             fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00052             if (ioctl(fd, VIDIOC_ENUM_FMT, &fmt) == -1) {
00053               break;
00054             }
00055             struct v4l2_frmsizeenum frmsizeenum;
00056             for (int j = 0;; j++) {
00057               memset(&frmsizeenum, 0, sizeof frmsizeenum);
00058               frmsizeenum.index = j;
00059               frmsizeenum.pixel_format = fmt.pixelformat;
00060               if (ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frmsizeenum) == -1) {
00061                 break;
00062               }
00063               if (frmsizeenum.type != V4L2_FRMSIZE_TYPE_DISCRETE) {
00064                 continue;
00065               }
00066               struct v4l2_frmivalenum frmivalenum;
00067               for (int k = 0;; k++) {
00068                 memset(&frmivalenum, 0, sizeof frmivalenum);
00069                 frmivalenum.index = k;
00070                 frmivalenum.pixel_format = fmt.pixelformat;
00071                 frmivalenum.width = frmsizeenum.discrete.width;
00072                 frmivalenum.height = frmsizeenum.discrete.height;
00073                 if (ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &frmivalenum) == -1) {
00074                   break;
00075                 }
00076                 if (frmivalenum.type != V4L2_FRMIVAL_TYPE_DISCRETE) {
00077                   continue;
00078                 }
00079 
00080                 // Create a new webcam video object
00081                 PT(WebcamVideoV4L) wc = new WebcamVideoV4L;
00082                 wc->set_name((const char*) cap2.card);
00083                 wc->_device = *it;
00084                 wc->_size_x = frmsizeenum.discrete.width;
00085                 wc->_size_y = frmsizeenum.discrete.height;
00086                 wc->_fps = ((double) frmivalenum.discrete.denominator) / ((double) frmivalenum.discrete.numerator);
00087                 wc->_pformats.push_back(fmt.pixelformat);
00088 
00089                 // Iterate through the webcams to make sure we don't put any duplicates in there
00090                 pvector<PT(WebcamVideo)>::iterator wvi;
00091                 for (wvi = WebcamVideoV4L::_all_webcams.begin(); wvi != WebcamVideoV4L::_all_webcams.end(); ++wvi) {
00092                   if ((*wvi)->is_of_type(WebcamVideoV4L::get_class_type())) {
00093                     PT(WebcamVideoV4L) wv_v4l = DCAST(WebcamVideoV4L, *wvi);
00094                     if (wv_v4l->_device == wc->_device &&
00095                         wv_v4l->_size_x == wc->_size_x &&
00096                         wv_v4l->_size_y == wc->_size_y &&
00097                         wv_v4l->_fps == wc->_fps) {
00098                       wv_v4l->_pformats.push_back(fmt.pixelformat);
00099                       break;
00100                     }
00101                   }
00102                 }
00103                 // Did the loop finish, meaning that a webcam of these
00104                 // properties does not exist? Add it.
00105                 if (wvi == WebcamVideoV4L::_all_webcams.end()) {
00106                   WebcamVideoV4L::_all_webcams.push_back(DCAST(WebcamVideo, wc));
00107                 }
00108               }
00109             }
00110           }
00111           continue;
00112         }
00113       }
00114     }
00115     close(fd);
00116   }
00117 }
00118 
00119 ////////////////////////////////////////////////////////////////////
00120 //     Function: WebcamVideoV4L::open
00121 //       Access: Published, Virtual
00122 //  Description: Open this video, returning a MovieVideoCursor.
00123 ////////////////////////////////////////////////////////////////////
00124 PT(MovieVideoCursor) WebcamVideoV4L::
00125 open() {
00126   return new WebcamVideoCursorV4L(this);
00127 }
00128 
00129 #endif
 All Classes Functions Variables Enumerations