Издательский дом ООО "Гейм Лэнд"ЖУРНАЛ ХАКЕР #95, НОЯБРЬ 2006 г.

Eye of the xakep

Fagot (salieff@mail.ru)

Хакер, номер #095, стр. 095-124-4


while(true)

{

if (ioctl(vdev_fd, VIDIOCSYNC, &vmmap.frame)!=0) return false;

memcpy(work_frame_buf, vbuf_ptr+videobuf.offsets[vmmap.frame], vmmap.width*vmmap.height*videopict.depth/8);

vmmap.frame++;

if (vmmap.frame>=(size_t)videobuf.frames) vmmap.frame=0;

if (ioctl(vdev_fd, VIDIOCMCAPTURE, &vmmap)!=0) return false;

ProccessFrame(work_frame_buf);

}

Ну и, конечно же, хочется подстраивать такие параметры изображения, как яркость, контраст и т.д. Делается это с помощью того же ioctl'а и той же структуры, которыми мы выставляли глубину цвета и палитру:

КОД

videopict.brightness=my_br;

videopict.hue=my_hue;

videopict.colour=my_col;

videopict.contrast=my_cnt;

videopict.whiteness=my_wht;

if (ioctl(vdev_fd, VIDIOCSPICT, &videopict)!=0) return false;

Руководствуясь всем упомянутым, я написал класс-обертку QCE_SPCA_Camera для работы со своей камерой (pulbic-интерфейс этого класса можно найти в соответствующей врезке).

Собственный видеоплеер

Чтобы иметь широкие возможности постобработки, вроде цветокоррекции и масштабирования, и при этом не грузить процессор, я решил выводить картинку посредством OpenGL. Так как в качестве интерфейсной библиотеки мы выбрали QT, то и OpenGL я привернул через QGLWidget, который перерисовывался по таймеру. Полезная функциональная нагрузка тут невысока, виджет берет у камеры буфер кадра (немного подкорректированный по размерам под нужды OpenGL) и накладывает его, как текстуру, на прямоугольник, заранее имеющий цвет, призванный произвести цветокоррекцию. Текстурные координаты вычисляются с расчетом софт-зума:

КОД

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 512, 512, 0, GL_BGR, GL_UNSIGNED_BYTE, qce_cam->getGLFrame());

glClear(GL_COLOR_BUFFER_BIT | GL_ACCUM_BUFFER_BIT);

glColor3f(qce_cam->r_koeff, qce_cam->g_koeff, qce_cam->b_koeff);

glBegin(GL_POLYGON);

glTexCoord2f(0+zoom_koeff*x2y_koeff, 0+zoom_koeff);

glVertex2i(-1, 1);

glTexCoord2f(qce_cam->gl_coord_x-zoom_koeff*x2y_koeff, 0+zoom_koeff);

glVertex2i(1, 1);

glTexCoord2f(qce_cam->gl_coord_x-zoom_koeff*x2y_koeff, qce_cam->gl_coord_y-zoom_koeff);

glVertex2i(1, -1);

glTexCoord2f(0+zoom_koeff*x2y_koeff, qce_cam->gl_coord_y-zoom_koeff);

glVertex2i(-1, -1);

glEnd();

Далее, используя буфер аккумуляции, мы корректируем яркость перед окончательной отрисовкой кадра:

КОД

glAccum(GL_ACCUM, 1.0);

glAccum(GL_RETURN, qce_cam->bright_koeff);

Если карточка хоть как-то способна ускорять графику, то решение использовать OpenGL должно дать неслабый выигрыш в производительности по сравнению с софтверной математической обработкой каждого кадра. Также я привернул слева от виджета с кадрами ползунки, позволяющие менять яркость, контраст, разрешение и т.д., и связал их с соответствующими методами интерфейсного класса камеры.

LPT, лирика

Мы будем управлять моторами через DATA-биты LPT-порта. На моей схеме они обозначены синим цветом. Контроллер позволяет нам добиться прямого соответствия: когда мы подаем единички на какой-либо data-бит, на соответствующую обмотку подается 12 вольт. Так как я решил писать в порты ввода-вывода из user-space, моя программа будет работать только под root'ом. Это не есть хорошо, но зато избавляет нас от необходимости написания драйвера kernel-space и расширения этого номера журнала до 500 страниц ;). Data-байт для LPT1 лежит по адресу 0x378. Мы должны получить разрешение туда писать и начать это делать:

Назад на стр. 095-124-3  Содержание  Вперед на стр. 095-124-5