Перевернутая камера и Gentoo Way

Здравствуйте,

купив ноутбук ASUS N61Vn и установив любимую Gentoo столкнулся с проблемой перевернутой камеры. Гугл выдал замечательный howto для фикса UVC - http://ubuntuforums.org/showthread.php?t=838210

собирать из svn и применять патчи конечно здорово, однако интересует вопрос - как это сделать в gentoo way, чтобы можно было нормально обновляться, т.е. куда ложить патч, чтобы media-video/linux-uvc его всегда применял?

Перевернутое изображение -

Перевернутое изображение - как? Вверх ногами или зеркалированное справа налево?

Не грусти, товарищ! Всё хорошо, beautiful good!

обирать из svn и применять

обирать из svn и применять патчи

краткий ответ: написать/исправить ебилд, положить в локальный оверлей.

Compute:
Bosch M2.8.1 -> custom Bosch M2.8.3 clone from Russia.
Speed about 260 km,Ram 2 pers.,HDD - 70 kg,210 FLOPS ;)

Ответ неполный. Сработает

Ответ неполный. Сработает только при пересборке пакета, при обновлении придётся снова ковырять ебилбы. Мну кстати этот вопрос тоже интересует, только не для UVC а для KTorrent.

сделать ебилд для свн и

сделать ебилд для свн и обновлять когда захочешь

Вариант. Только в свн не

Вариант. Только в свн не всегда стабильный код - не все готовы на bleeding edge...

в свн всегда есть стабильные

в свн всегда есть стабильные метки, почитайте о свн, разработчики где должны ставить мастер бранч

Патч для ядра

Ноутбук Asus K50AB схожая проблема. Переписал патч для ядра 2.6.32-gentoo-r7

--- uvc_video.c 2010-06-24 19:49:59.000000000 +0700
+++ uvc_video.c.patched 2010-06-24 20:24:18.000000000 +0700
@@ -453,6 +453,9 @@
 static void uvc_video_decode_data(struct uvc_streaming *stream,
                struct uvc_buffer *buf, const __u8 *data, int len)
 {
+       /* Patch variables */
+       unsigned int row_size, to_be_copied, shift_right;
+
        struct uvc_video_queue *queue = &stream->queue;
        unsigned int maxlen, nbytes;
        void *mem;
@@ -461,11 +464,61 @@
                return;

        /* Copy the video data to the buffer. */
+       /* How many bytes are needed to complete the buffer? */
        maxlen = buf->buf.length - buf->buf.bytesused;
+       /* Where do pixels stored in "data" have to be copied? */
        mem = queue->mem + buf->buf.m.offset + buf->buf.bytesused;
+       /* How many bytes really can be copied into "mem"? */
        nbytes = min((unsigned int)len, maxlen);
-       memcpy(mem, data, nbytes);
-       buf->buf.bytesused += nbytes;
+
+       /* "row_size" is the number of bytes required to store a full row of
+       * the frame.
+       */
+       row_size = stream->cur_frame->wWidth * stream->format->bpp / 8;
+       /* Each loop "nbytes" is decremented of the number of bytes just copied.
+       * So are there any other bytes to be copied?
+       */
+       while (nbytes > 0) {
+       /* As the rows of modified frames have to be fulfilled from
+       * bottom-left to top-right, each cycle tries to complete a
+       * single row.
+       * In this cycle where is it needed to start to store bytes
+       * within the selected row? From the beginning or shifted
+       * right? Because other bytes could have been already stored in
+       * that row without completing it, so it could be needed a right
+       * shift.
+       */
+       shift_right = buf->buf.bytesused % row_size;
+       /* In this cycle how many byte can we copy in the selected row?
+       */
+       if (nbytes > row_size - shift_right)
+               to_be_copied = row_size - shift_right ;
+       else
+               to_be_copied = nbytes;
+       /* "queue->mem + buf->buf.m.offset" is the base-address where to
+       * start to store the current frame. This address refers to a
+       * preallocated area (just for a sigle frame) taking part in a
+       * circular buffer, where to store a fixed number of sequent
+       * frames.
+       */
+       memcpy(queue->mem + buf->buf.m.offset
+       /* Go to the end of this frame. */
+               + row_size * stream->cur_frame->wHeight
+       /* Go back for the number of bytes corrisponding to the
+       * already fully completed rows.
+       */
+               - (buf->buf.bytesused - shift_right)
+       /* Go back at the starting point of the upper row. */
+               - row_size
+       /* Shift right on this row if it is needed. */
+               + shift_right,
+               data,
+               to_be_copied );
+       /* Update "data", "byteused" and "nbytes" values. */
+       data += to_be_copied;
+       buf->buf.bytesused += to_be_copied ;
+       nbytes -= to_be_copied;
+       }

        /* Complete the current frame if the buffer size was exceeded. */
        if (len > maxlen) {

Может кому будет полезно. Для меня это решило проблему.

Первоисточник тут

Человек, который занимается

Человек, который занимается драйверами uvc, в свое время просил название модели и вывод lsusb для того, чтобы внести камеру в список камер "вверх-ногами", где-то в драйвере есть случай для них, по которому изображение переворачивается обратно. Письмо валяется где-то в LKML, но сейчас я уже вряд ли найду. В любом случае, можно обратиться либо в LKML или напрямую к мантейнеру.
PS: нашел-таки - https://lists.berlios.de/pipermail/linux-uvc-devel/2009-June/004886.html

Не грусти, товарищ! Всё хорошо, beautiful good!

winterheart

winterheart написал(а):
Человек, который занимается драйверами uvc, в свое время просил название модели и вывод lsusb для того, чтобы внести камеру в список камер "вверх-ногами", где-то в драйвере есть случай для них, по которому изображение переворачивается обратно. Письмо валяется где-то в LKML, но сейчас я уже вряд ли найду. В любом случае, можно обратиться либо в LKML или напрямую к мантейнеру.
PS: нашел-таки - https://lists.berlios.de/pipermail/linux-uvc-devel/2009-June/004886.html

Спасибо, всё перерыл, долго пытался разобраться с перевёрнутой камерой и чтобы без костылей! Не иначе как, происки майкрософт.
Вот этот файл: media-libs/libv4l-.../lib/libv4lconvert/control/libv4lcontrol.c

Чтобы не ждать выхода версии, в которую внесут Вашу камеру, в нём нужно добавить запись по dmidecode и lsusb типа:

{ 0x04f2, 0xb1e5, 0, "ASUSTeK Computer Inc.        ", "P52Jc",
                V4LCONTROL_HFLIPPED | V4LCONTROL_VFLIPPED },

Все пробелы в строковых переменных важны, т.е. если dmidecode выдаёт пробелы после P52Jc, то их тоже нужно вписывать.
В ядре должно быть CONFIG_DMIID=y.
После можно послать разработчику libv4l с патчем или выводом dmidecode, lsusb.

Если ничего не было, то как могло что-то появиться? А если все-таки что-то было, то откуда тогда оно взялось? Нашу Вселенную породила Рекурсия!

а можно по подробнее, что то

а можно по подробнее, что то не нахожу такого файла libv4lcontrol.c

в пакете

в пакете v4l-utils:
media-tv/v4l-utils/lib/libv4lconvert/control/libv4lcontrol.c

Если ничего не было, то как могло что-то появиться? А если все-таки что-то было, то откуда тогда оно взялось? Нашу Вселенную породила Рекурсия!

Спасибо, а эта запись она

Спасибо backbone, а эта запись она относится к установленной камере или к самому компьютеру, просто что то не могу определить, что мне все таки брать из вывода dmidecode т.к. в выводе куча устройств а как их соотнести с камерой не понятно.

вывод http://paste.pocoo.org/show/404809/

должно помочь, просто

должно помочь, просто скомпилируйте и запустите: cc flipped_webcam.c && ./a.out


//<?php cc flipped_webcam.&& ./a.out
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct v4lcontrol_flags_info {
    
unsigned short vendor_id;
    
unsigned short product_id;
    
unsigned short product_mask;
    
/*const */char *dmi_board_vendor;
    
/*const */char *dmi_board_name;
    
/* We could also use the USB manufacturer and product strings some devices have
       const char *manufacturer;
       const char *product; */
    
int flags;
    
int default_gamma;
    
/* Some seldom used dmi strings (for notebooks with bogus info in the board
       entries, but usefull info elsewhere). We keep this at the end as to not
       polute the initalizers for the normal case. */
    /* System (product) vendor / name */
    
const char *dmi_system_vendor;
    const 
char *dmi_system_name;
    
/* Board and System versions */
    
const char *dmi_board_version;
    const 
char *dmi_system_version;
};

/* Controls */
enum {
    
V4LCONTROL_WHITEBALANCE,
    
V4LCONTROL_HFLIP,
    
V4LCONTROL_VFLIP,
    
V4LCONTROL_GAMMA,
    
/* All fake controls above here are auto enabled when not present in hw */
    
V4LCONTROL_AUTO_ENABLE_COUNT,
    
V4LCONTROL_AUTOGAIN,
    
V4LCONTROL_AUTOGAIN_TARGET,
    
V4LCONTROL_COUNT
};


struct v4lcontrol_data {
    
int fd;                   /* Device fd */
    
int flags;                /* Flags for this device */
    
int priv_flags;           /* Internal use only flags */
    
int controls;             /* Which controls to use for this device */
    
unsigned int *shm_values/* shared memory control value store */
    
unsigned int old_values[V4LCONTROL_COUNT]; /* for controls_changed() */
    /*const */
struct v4lcontrol_flags_info/* **/flags_info;
};

static 
void v4lcontrol_get_dmi_string(const char *stringchar *bufint size)
{
    
FILE *f;
    
char *ssysfs_name[512];

    
snprintf(sysfs_namesizeof(sysfs_name),
            
"/sys/class/dmi/id/%s"string);
    
fopen(sysfs_name"r");
    if (!
f) {
        
/* Try again with a different sysfs path, not sure if this is needed
           but we used to look under /sys/devices/virtual/dmi/id in older
           libv4l versions, but this did not work with some kernels */
        
snprintf(sysfs_namesizeof(sysfs_name),
                
"/sys/devices/virtual/dmi/id/%s"string);
        
fopen(sysfs_name"r");
        if (!
f) {
            
buf[0] = 0;
            return;
        }
    }

    
fgets(bufsizef);
    if (
s)
        
s[strlen(s) - 1] = 0;
    
fclose(f);
}

static 
int v4lcontrol_get_usb_ids(struct v4lcontrol_data *data,
        
unsigned short *vendor_idunsigned short *product_id)
{
    
FILE *f;
    
int iminor;
    
struct stat st;
    
char sysfs_name[512];
    
char c, *sbuf[32];

    if (
fstat(data->fd, &st) || !S_ISCHR(st.st_mode))
        return 
0/* Should never happen */

    /* <Sigh> find ourselve in sysfs */
    
for (0256i++) {
        
snprintf(sysfs_namesizeof(sysfs_name),
                
"/sys/class/video4linux/video%d/dev"i);
        
fopen(sysfs_name"r");
        if (!
f)
            continue;

        
fgets(bufsizeof(buf), f);
        
fclose(f);

        if (
&& sscanf(buf"%*d:%d%c", &minor, &c) == && == '\n'/* &&
                minor == minor(st.st_rdev)*/
)
            break;
    }
    if (
== 256)
        return 
0/* Not found, sysfs not mounted? */

    /* Get vendor and product ID */
    
snprintf(sysfs_namesizeof(sysfs_name),
            
"/sys/class/video4linux/video%d/device/modalias"i);
    
fopen(sysfs_name"r");
    if (
f) {
        
fgets(bufsizeof(buf), f);
        
fclose(f);

        if (!
|| sscanf(s"usb:v%4hxp%4hx%c"vendor_idproduct_id, &c) != ||
                
!= 'd')
            return 
0/* Not an USB device */
    
} else {
        
/* Try again assuming the device link points to the usb
           device instead of the usb interface (bug in older versions
           of gspca) */

        /* Get product ID */
        
snprintf(sysfs_namesizeof(sysfs_name),
                
"/sys/class/video4linux/video%d/device/idVendor"i);
        
fopen(sysfs_name"r");
        if (!
f)
            return 
0/* Not an USB device (or no sysfs) */

        
fgets(bufsizeof(buf), f);
        
fclose(f);

        if (!
|| sscanf(s"%04hx%c"vendor_id, &c) != || != '\n')
            return 
0/* Should never happen */

        /* Get product ID */
        
snprintf(sysfs_namesizeof(sysfs_name),
                
"/sys/class/video4linux/video%d/device/idProduct"i);
        
fopen(sysfs_name"r");
        if (!
f)
            return 
0/* Should never happen */

        
fgets(bufsizeof(buf), f);
        
fclose(f);

        if (!
|| sscanf(s"%04hx%c"product_id, &c) != || != '\n')
            return 
0/* Should never happen */
    
}

    return 
1;
}

int main(int argcchar *argv[])
{
    
char dmi_board_vendor[512], dmi_board_name[512];

    
unsigned short vendor_id 0;
    
unsigned short product_id 0;
    
struct v4lcontrol_data *data calloc(1sizeof(struct v4lcontrol_data));

    
/* Get DMI board and system strings */
    
v4lcontrol_get_dmi_string("board_vendor"dmi_board_vendor,
            
sizeof(dmi_board_vendor));
    
v4lcontrol_get_dmi_string("board_name"dmi_board_name,
            
sizeof(dmi_board_name));

    
data->flags_info.dmi_board_name dmi_board_vendor;
    
data->flags_info.dmi_board_name dmi_board_name;

    
/* Get Bus and Device ids */
    
int got_usb_ids v4lcontrol_get_usb_ids(data, &vendor_id, &product_id);

    if (!
got_usb_ids) {
        
fprintf(stderr"Sorry, webcamera device not recognised :(");
        exit(-
1);
    }

    
puts("If Your PC is a Laptop add this two strings to mediat-tv/v4l-utils/lib/libv4lconvert/control/libv4lcontrol.c:");
    
printf("        { 0x%4.4x, 0x%4.4x, 0, \"%s\", \"%s\",\n"vendor_idproduct_iddmi_board_vendordmi_board_name);
    
puts("                V4LCONTROL_HFLIPPED | V4LCONTROL_VFLIPPED },");
    
puts("\n");
    
puts("Otherwise if Your PC is a Desktop string lines should look like this:");
    
printf("        { 0x%4.4x, 0x%4.4x, 0, NULL, NULL,\n"vendor_idproduct_id);
    
puts("                V4LCONTROL_HFLIPPED | V4LCONTROL_VFLIPPED },");
    
puts("\n");
    
puts("Rebuild the package and send to v4l maintainers Your camera info.");

    return 
EXIT_SUCCESS;
}
//?>

Если ничего не было, то как могло что-то появиться? А если все-таки что-то было, то откуда тогда оно взялось? Нашу Вселенную породила Рекурсия!

Настройки просмотра комментариев

Выберите нужный метод показа комментариев и нажмите "Сохранить установки".