1 /* 2 * Copyright 2009 Google Inc. 3 * Author: lexnikitin (at) google.com (Alexey Nikitin) 4 * 5 * V4LLookup provides basic functionality to work with V2L2 devices in Linux 6 * The functionality is implemented as a class with virtual methods for 7 * the purpose of unit testing. 8 */ 9 #include "talk/media/devices/v4llookup.h" 10 11 #include <errno.h> 12 #include <fcntl.h> 13 #include <linux/types.h> 14 #include <linux/videodev2.h> 15 #include <sys/ioctl.h> 16 #include <sys/types.h> 17 #include <sys/stat.h> 18 #include <unistd.h> 19 20 #include <cstring> 21 22 #include "talk/base/logging.h" 23 24 namespace cricket { 25 26 V4LLookup *V4LLookup::v4l_lookup_ = NULL; 27 28 bool V4LLookup::CheckIsV4L2Device(const std::string& device_path) { 29 // check device major/minor numbers are in the range for video devices. 30 struct stat s; 31 32 if (lstat(device_path.c_str(), &s) != 0 || !S_ISCHR(s.st_mode)) return false; 33 34 int video_fd = -1; 35 bool is_v4l2 = false; 36 37 // check major/minur device numbers are in range for video device 38 if (major(s.st_rdev) == 81) { 39 dev_t num = minor(s.st_rdev); 40 if (num <= 63) { 41 video_fd = ::open(device_path.c_str(), O_RDONLY | O_NONBLOCK); 42 if ((video_fd >= 0) || (errno == EBUSY)) { 43 ::v4l2_capability video_caps; 44 memset(&video_caps, 0, sizeof(video_caps)); 45 46 if ((errno == EBUSY) || 47 (::ioctl(video_fd, VIDIOC_QUERYCAP, &video_caps) >= 0 && 48 (video_caps.capabilities & V4L2_CAP_VIDEO_CAPTURE))) { 49 LOG(LS_INFO) << "Found V4L2 capture device " << device_path; 50 51 is_v4l2 = true; 52 } else { 53 LOG(LS_ERROR) << "VIDIOC_QUERYCAP failed for " << device_path; 54 } 55 } else { 56 LOG(LS_ERROR) << "Failed to open " << device_path; 57 } 58 } 59 } 60 61 if (video_fd >= 0) 62 ::close(video_fd); 63 64 return is_v4l2; 65 } 66 67 }; // namespace cricket 68