Eye of the xakep Fagot (salieff@mail.ru) Хакер, номер #095, стр. 095-124-3 Начинаем с того, что открываем файл камеры и получаем ее свойства: КОД int vdev_fd; struct video_capability videocap; if ((vdev_fd=open("/dev/video0", O_RDWR))<0) return false; if (ioctl(vdev_fd, VIDIOCGCAP, &videocap)!=0) return false; if (!(videocap.type&VID_TYPE_CAPTURE)) return false; Так как у меня веб-камера, а не тюнер с кучей каналов (не эфирных, а аппаратных - аудио, видео, телетекста и прочих), то я не буду заморачиваться с выбором нужного канала посредством VIDIOCGCHAN/VIDIOCSCHAN, а сразу перейду к настройке параметров картинки, запрошу текущие параметры, поправлю необходимые мне и установлю обратно: КОД struct video_picture videopict; if (ioctl(vdev_fd, VIDIOCGPICT, &videopict)!=0) return false; videopict.depth=24; videopict.palette=VIDEO_PALETTE_RGB24; if (ioctl(vdev_fd, VIDIOCSPICT, &videopict)!=0) return false; Затем установим разрешение видеозахвата. Я ставлю максимальное из ранее полученных от камеры свойств: КОД struct video_window videowin; if (ioctl(vdev_fd, VIDIOCGWIN, &videowin)!=0) return false; videowin.width=videocap.maxwidth; videowin.height=videocap.maxheight; if (ioctl(vdev_fd, VIDIOCSWIN, &videowin)!=0) return false; Теперь все готово к тому, чтобы читать кадры из дескриптора vdev_fd, например вот так: КОД char frame_buf[videowin.width*videowin.height*videopict.depth/8]={0}; if (read(vdev_fd, frame_buf, sizeof(frame_buf))!=sizeof(frame_buf)) return false; Но... это неспортивно ;). Сейчас объясню почему. Каждый вызов read блокируется на время формирования кадра, а между вызовами камера простаивает. Учитывая невысокий FPS дешевых веб-камер, это недопустимо. Нужно сделать так, чтобы во время обработки текущего кадра камера уже формировала следующий, то есть организовать doublebuffering. Делается это с помощью mmap. Суть такова – можно сказать камере, чтобы она начала формирование кадра, а самому не блокироваться, а заниматься своими делами. Для использования mmap нужно получить параметры мэпинга и заmmap'ить сам файл камеры: КОД struct video_mbuf videobuf; unsigned char * vbuf_ptr; if (ioctl(vdev_fd, VIDIOCGMBUF, &videobuf)!=0) return false; if ((vbuf_ptr=(unsigned char *)mmap(0, videobuf.size, PROT_READ | PROT_WRITE, MAP_SHARED, vdev_fd, 0))==MAP_FAILED) return false; Теперь можно приступить к захвату в режиме doublebufering. Синхронизируемся с формированием кадра, копируем кадр из mmap-указателя в рабочий буфер, запускаем на формирование следующий кадр, отправляем рабочий буфер на обработку. Таким образом, пока идет обработка, камера не теряет времени даром, формируя нам следующий кадр: КОД struct video_mmap vmmap; vmmap.height = videowin.height; vmmap.width = videowin.width; vmmap.format = videopict.palette; vmmap.frame = 0; if (ioctl(vdev_fd, VIDIOCMCAPTURE, &vmmap)!=0) return false; |