Категории раздела |
|
Автомобильные гаджеты, ремонт...
[143]
|
Безопасность IT
[404]
|
Блоки питания, Power Banks, зарядки...
[508]
|
Видеорегистраторы
[186]
|
Гаджеты для спорта и здоровья...
[190]
|
Гаджеты, аксессуары...
[627]
|
Измерительная техника, инструменты
[437]
|
Накопители данных
[232]
|
Нетбуки, Ноутбуки, Ультрабуки
[689]
|
Мультиварки, блендеры и не только...
[162]
|
Планшеты
[764]
|
Радар-детекторы
[26]
|
Роботы-пылесосы
[37]
|
Своими руками
[360]
|
Сети, сетевые технологии, оборудование...
[273]
|
Смартфоны
[4959]
|
Фотокамеры, объективы, искусство фотографии..
[541]
|
Умный дом
[50]
|
Электронные книги
[101]
|
CB, LPD, PMR- связь...
[170]
|
DECT, IP-телефоны
[18]
|
Drones, boats, cars...
[108]
|
electric cars
[35]
|
GPS-навигаторы, трекеры...
[51]
|
Linux и не только
[3981]
|
mini computers и не только...
[409]
|
News IT, Это интересно, ликбез...
[1120]
|
Smart TV, UltraHD, приставки, проекторы...
[415]
|
Smart Watch
[268]
|
Sound: наушники, плееры, усилители...
[618]
|
Windows 10...
[301]
|
Windows 11
[37]
|
| |
|
|
| | |
| Главная » 2014 » Февраль » 14 » Работа с usb видеокамерой в Linux. Часть 2
21:14 Работа с usb видеокамерой в Linux. Часть 2 |
Работа с usb видеокамерой в Linux. Часть 2
Привествую, Хабр!
Продолжаем цикл статей про программирование видеокамеры в Linux. В первой части [1],
мы рассмотрели механизм открытия и считывания первичных параметров
видеоустройства. Была написана простенькая утилита catvd. Сегодня
расширим функционал нашей маленькой программы, но сначала надо написать обертку для функции ioctl.
Код метода xioctlint videodevice::xioctl(int fd, int request, void *arg)
{
int r;
r = ioctl (fd, request, arg);
if(r == -1)
{
if (errno == EAGAIN)
return EAGAIN;
stringstream ss;
ss << "ioctl code " << request << " ";
errno_exit(ss.str());
}
return r;
}
Эта обертка позволяет прервать программу если была ошибка и показать сообщение.
Попробуем считать картинку с камеры и сохранить в файл.
Код метода getFramevoid videodevice::getFrame(string file_name)
{
initMMAP()
startCapturing()
long int i = 0
for (
{
if(readFrame(file_name))
break
i++
}
cout << "iter == " << i << endl
stopCapturing()
freeMMAP()
}
метод readFrame — отвечает за чтение и обработку полученого изображения.
методы initMMAP(), freeMMAP() — создание/очистка буфера памяти устройства.
методы startCapturing(), stopCapturing() — включение/выключение режима
streaming у видеоустройства. Наличие этих функций, у камеры, можно
проверить флагом V4L2_CAP_STREAMING [*].
Разберем метод initMMAP
Код метода initMMAPvoid videodevice::initMMAP()
{
struct v4l2_requestbuffers req
req.count = 1
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE
req.memory = V4L2_MEMORY_MMAP
xioctl(fd, VIDIOC_REQBUFS, &req)
devbuffer = (buffer*) calloc(req.count, sizeof(*devbuffer))
struct v4l2_buffer buf
memset(&buf, 0, sizeof(buf))
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE
buf.memory = V4L2_MEMORY_MMAP
buf.index = 0
xioctl(fd, VIDIOC_QUERYBUF, &buf)
devbuffer->length = buf.length
devbuffer->start =
mmap(NULL,
buf.length,
PROT_READ | PROT_WRITE,
MAP_SHARED,
fd,
buf.m.offset)
if (devbuffer->start == MAP_FAILED)
errno_exit("mmap")
}
функция VIDIOC_REQBUFS [↓] позволяет проинициализировать буфер памяти внутри устройства. Структура v4l2_requestbuffers задает параметры инициализации
struct v4l2_requestbuffers {
__u32 count;
__u32 type;
__u32 memory;
__u32 reserved[2];
};
После того, как буфер был проинициализирован, его надо отобразить на область памяти (mapping).
Функция VIDIOC_QUERYBUF [↓]
позволяет считать параметры буфера, которые будут использоваться для
создания memory-mapping области. Структура v4l2_buffer большая, опишу
необходимые поля:
struct v4l2_buffer {
//до выполнения VIDIOC_QUERYBUF устанавливаем следующие поля
__u32 index; // ноль или номер буфера (если v4l2_requestbuffers.cout > 1)
__u32 type; // тип (совпадает со значением v4l2_requestbuffers.type)
//после выполнения VIDIOC_QUERYBUF используем эти поля в качестве параметров для memory-mapping
union {
__u32 offset; // смещение буфера относительно начала памяти устройства
} m;
__u32 length; // размер буфера
};
системная функция mmap() [3] позволяет отображать файл или область памяти устройств в оперативную память. Для использования mmap() необходимо подключить
<sys/mman.h>
Далее необходимо переключить камеру в режим захвата.
Код метода startCapturingvoid videodevice::startCapturing()
{
struct v4l2_buffer buf
memset(&buf, 0, sizeof(buf))
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE
buf.memory = V4L2_MEMORY_MMAP
buf.index = 0
xioctl(fd, VIDIOC_QBUF, &buf)
enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE
xioctl(fd, VIDIOC_STREAMON, &type)
}
Функция VIDIOC_QBUF [↓]
ставит буфер в очередь обработки драйвером устройства. Поля
используются такие же, как и для VIDIOC_REQBUFS или VIDIOC_QUERYBUF.
Функция VIDIOC_STREAMON[↓] включает камеру в режим захвата.
Теперь камера включена и захватывает изображения. Но картинку еще надо получить.
Код метода readFrameint videodevice::readFrame(string file_name)
{
struct v4l2_buffer buf
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE
buf.memory = V4L2_MEMORY_MMAP
if (xioctl(fd, VIDIOC_DQBUF, &buf) == EAGAIN)
return 0
buffer *temp = devbuffer
FILE *out_file = fopen(file_name.c_str(),"w")
fwrite(temp->start,temp->length,1,out_file)
fclose(out_file)
return 1
}
Функция VIDIOC_DQBUF[↓]
освобождает буфер из очереди обработки драйвера. В результате можем
получить ошибку EAGAIN. Ничего опасного в этом нет, надо еще раз вызвать
VIDIOC_DQBUF. Это происходит потому, что драйвер еще обрабатывает
запрос и не может освободить буфер из очереди. При успешном выполнении
этой функции, мы получаем в «руки» нашу картинку. В самом начале статьи,
в коде был добавлен итератор. Итератор позволяет проследить сколько
итераций вхолостую проходит цикл до успешного выполнения VIDIOC_DQBUF.
Компиляция
$ cmake .
$ make
Вывод программы следующий
$./getimage
Open device /dev/video0
Init mmap
Start capturing
read frame from buffer and write to file
iter == 831013
stop Capturing
free mmap
Close device /dev/video0
Из «iter == 831013» видно — картинка скидывается в буфер довольно долго.
Для ускорения можно использовать несколько буферов и вытаскивать
картинку с первого свободного и т.д.
Сегодня была рассмотрена инициализация буфера памяти и чтения из него
картинки. Изображение сохраняется в raw формате. Можно открыть
программой Shotwell. В следующей статье будет рассмотрен вывод
изображению в текстуру (через SDL2), затронуты некоторые форматы
изображения и настройки камеры.
Ресурсы используемые в статье:
- Работа с usb видеокамерой в Linux. Часть 1
- video for Linux API
- подробнее про mmap()
Ссылки на используемые функции:
Исходный код
http://habrahabr.ru/post/212531/
|
Категория: Linux и не только |
Просмотров: 714 |
Добавил: laptop
| Рейтинг: 0.0/0 |
Добавлять комментарии могут только зарегистрированные пользователи. [ Регистрация | Вход ]
| |
| | |
|
Волк слабее льва и тигра, но в цирке волк не выступает!
Волк - единственный из зверей, который может пойти в бой на более сильного противника.
Если же он проиграл бой, то до последнего вздоха смотрит в глаза противника. После этого умирает...
Внимание! |
|
Администратор сайта laptop.ucoz.ru не несет ответственности за содержание рекламных объявлений. Все используемые на сайте зарегистрированные товарные знаки принадлежат своим законным владельцам! Используемая со сторонних источников информация публикуется с обязательными ссылками на эти источники.
| |
|
|