Newsgroup: it.comp.os.linux.development
Titolo: Problema con gli headers....

Sto provando a fare un programma che legge i dati da una webcam.
A parte il fatto che la documentazione di video4linux mi sembra un po'
carente (se avete link con tutorial fatemelo sapere per piacere), ho più o
meno fatto qualche routine, solo che quando cerco di compilare mi ritrovo
con questo problema:
bott@dirac:~/video > make
gcc -c visione.c -o visione.o
In file included from visione.c:5:
visione.h:6: ioctl.h: No such file or directory
In file included from /usr/include/sys/types.h:215,
                 from visione.h:7,
                 from visione.c:5:
/usr/include/sys/select.h:58: warning: `__NFDBITS' redefined
/usr/include/linux/posix_types.h:22: warning: this is the location of the previous definition
/usr/include/sys/select.h:60: warning: `__FDMASK' redefined
/usr/include/linux/posix_types.h:34: warning: this is the location of the previous definition
make: *** [all] Error 1
bott@dirac:~/video >
In pratica si incavola come una iena perché si trova a mescolare gli
header della libreria C con gli hedare del kernel (che poi non sono
nemmeno quelli a dire il vero). Ho letto che per le applicazioni in
userspace si dovrebbero usare gli header di libreria e non quelli del
kernel, però non riesco ad andarne fuori. Vi posto il codice, sperando
che abbiate un qualche suggerimento da darmi.
Secondo voi può essere legato all'ordine degli include?
*** visione.h ***
#include <linux/videodev.h>
 
#include <sys/ioctl.h>
#include <sys/types.h> /*open */
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h> /* mmap */
#include <sys/mman.h>
 
 
typedef struct _Camera Camera;
 
struct _Camera {
        /** Struttura dati con i parametri delle telecamera. */
        struct video_capability capability;
        /** Struttura necessaria per impostare il formato. */
        struct video_picture picture;
        /** buffer per l'mmap */
        struct video_mbuf buffer;
        /** */
        struct video_mmap map;
        /** Il dispositivo da cui stiamo leggendo. */
        char device[32];
        /** Il filedescriptor associato alla telecamera da cui stiamo
         * leggendo. */
        int fd;
        /** Il numero totale di pixel per quadro */
        int pixel;
};
/**
 * Inizializza la telecamera. Impostiamo uan risoluzione a 32 bit perché
 * pur non essendo  il massimo in efficienza (aumentiamo del  33% i dati
 * da  trasferire  dalla camera  al  pc)  guadagnamo tempo  dopo  quando
 * dobbiamo fare le  elaborazioni delle immagini. Se usassimo  3 bit non
 * avremmo  i dati  sempre allineati  e potrebbero  spesso servirci  due
 * letture al posto di una.
 */
void initCamera (Camera *camera, const char* device);
 
void getImage (Camera *camera);
*** fine visione.h ***
*** visione.c ***
#include <string.h>
#include <stdio.h>
#include <error.h>
 
#include "visione.h"
void initCamera (Camera *camera, const char* device) {
        int fd, i;
 
        strcpy (camera->device, device);
 
        fd = open ("/dev/video", O_RDWR);
 
        if (fd<0) perror ("Errore nell'inizializzazione: open.");
 
        i = ioctl (fd, VIDIOCGCAP, camera->capability);
        if (i<0) perror ("Errore nell'inizializzazione: VIDIOCGCAP");
        i = ioctl (fd, VIDIOCGPICT, camera->picture);
        if (i<0) perror ("Errore nell'inizializzazione: VIDIOCGPICT");
        if (camera->picture.palette != VIDEO_PALETTE_RGB32) {
                camera->picture.palette = VIDEO_PALETTE_RGB32;
                i = ioctl (fd, VIDIOCSPICT, camera->picture);
                if (i<0) perror ("Errore nell'inizializzazione: VIDIOCSPICT");
                /* e adesso siamo a 32 bit */
        }
        camera->pixel = camera->capability.maxwidth * camera->capability.maxwidth;
}
void getImage (Camera *camera) {
        int frmbuf,frames = 0;
        void *grabarea;
 
        if (ioctl (camera->fd, VIDIOCGMBUF, camera->buffer) == -1) {
                perror ("Errore nella lettura: VIDIOCGMBUF");
                return;
        }
 
        grabarea = mmap(NULL, camera->buffer.size, PROT_READ,MAP_SHARED,
                        camera->fd, 0);
 
        if (grabarea == MAP_FAILED) {
                perror ("Errore nella lettura: MAP_FAILED");
                return;
        }
 
        camera->map.frame = 0;
        camera->map.width = camera->capability.maxwidth;
        camera->map.height = camera->capability.maxheight;
        camera->map.format = VIDEO_PALETTE_RGB32;
 
        // MCAPTURE(0)
        if (ioctl (camera->fd, VIDIOCMCAPTURE, camera->map) == -1) {
                perror ("Errore nella lettura: VIDIOCMCAPTURE");
                return;
        }
        // MCAPTURE(1)
        camera->map.frame = 1;
        if (ioctl (camera->fd, VIDIOCMCAPTURE, camera->map) == -1) {
                perror ("Errore nella lettura: VIDIOCMCAPTURE");
                return;
        }
 
        do {
                // SYNC(0)
                frmbuf = 0;
                if (ioctl (camera->fd, VIDIOCSYNC, &frmbuf) == -1) {
                        perror ("Errore nella lettura: VIDIOCSYNC");
                        break;
                }
 
                // elabora frame 0
 
                // MCAPTURE(0)
                camera->map.frame = 0;
                if (ioctl (camera->fd, VIDIOCMCAPTURE, camera->map) == -1) {
                        perror ("Errore nella lettura: VIDIOCMCAPTURE");
                        break;
                }
 
                // SYNC(0)
                frmbuf = 1;
                if( ioctl(camera->fd, VIDIOCSYNC, &frmbuf) == -1 ) {
                        perror ("Errore nella lettura: VIDIOCSYNC");
                        break;
                }
 
                // elabora frame 1;
 
                // MCAPTURE(1)
                camera->map.frame = 1;
                if (ioctl (camera->fd, VIDIOCMCAPTURE, camera->map) == -1) {
                        perror ("Errore nella lettura: VIDIOCMCAPTURE");
                        break;
                }
        } while (TRUE);
 
        munmap (grabarea, camera->buffer.size);
 
        return;
}


Infatti in /usr/include/sys/select.h c'e':
/* Some versions of <linux/posix_types.h> define these macros.*/
#undef  __NFDBITS
#undef  __FDELT
#undef  __FDMASK
/* It's easier to assume 8-bit bytes than to get CHAR_BIT.*/
#define __NFDBITS       (8 * sizeof (__fd_mask))
#define __FDELT(d)      ((d) / __NFDBITS)
#define __FDMASK(d)     ((__fd_mask) 1 << ((d) % __NFDBITS))
Ma videodev.h (che include linux/types.h -> linux/posix_types.h) e' prima di
sys/types (che include select.h).
Sorvolando su questo:
visione.h:6: ioctl.h: No such file or directory 
non e' che magari in preda alla stanchezza ti sei dimenticato di dare un
make clean per ricompilare anche gli headers ?
Ad ogni modo ho provato anch'io il tuo programma:
gcc visione.c
In file included from visione.h:1,
                 from visione.c:4:
/usr/include/linux/videodev.h:55: parse error before "ulong"
/usr/include/linux/videodev.h:71: parse error before '}' token
Ho trovato qui
 
http://www.alfonsomartone.itb.it/hdlvkd.html
questa sequenza di headers per visione.h:
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <linux/ioctl.h>
#include <linux/videodev.h>
gcc visione.c -o visione
/usr/lib/gcc-lib/i386-redhat-linux/3.2/../../../crt1.o: In function
`_start':
/usr/lib/gcc-lib/i386-redhat-linux/3.2/../../../crt1.o(.text+0x18):
undefined reference to `main'
collect2: ld returned 1 exit status
A questo punto il problema e' sparito ma ora c'e' quello del linker.
Nicola.
-- 
chi va pian va san e va lontan

                 /* e adesso siamo a 32 bit */
Per cominciare, a quelle ioctl devi passare il puntatore alle strutture 
dati, non direttamente le strutture (quindi "&camera->capability" etc.).
Poi tieni conto che non tutte le telecamere supportano la 
VIDEO_PALETTE_RGB32, perciò se la tua applicazione lavora in quel 
colorspace ti toccherà provvedere alle conversioni necessarie (ad 
esempio da YUV).
Ciao
  David
-- 
<d.santinoli presso mi. flashnet. it>

 Nicola.
porca miseria, ho provato a chiamare la funzioni initCamera, guarda cosa
nmi viene fuori:
bott@dirac:~/video > gdb ./visione
GNU gdb 2002-04-01-cvs
Copyright 2002 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i386-linux"...
(gdb) run
Starting program: /home/bott/video/visione
 
Program received signal SIGSEGV, Segmentation fault.
0x4000956f in fixup () from /lib/ld-linux.so.2
(gdb) where
#0  0x4000956f in fixup () from /lib/ld-linux.so.2
#1  0x400097c0 in _dl_runtime_resolve () from /lib/ld-linux.so.2
(gdb)
Ma non dovrebbe essere stata codificata dentro l'eseguibile? Io compilo
cosě:
bott@dirac:~/video > make
gcc -c visione.c -g
gcc -c main.c -g
gcc visione.o main.o -o visione -g
bott@dirac:~/video >
e il main č banale:
#include "visione.h"
 
int main (int argc, char *argv[]) {
        Camera camera;
 
        initCamera (&camera, "/dev/video");
 
        return 0;
}
mah.... 

 bott@dirac:~/video >
Uhm, il programma che ho io esce correttamente: 
Errore nell'inizializzazione: open.: Is a directory
Errore nell'inizializzazione: VIDIOCGCAP: Bad file descriptor
Errore nell'inizializzazione: VIDIOCGPICT: Bad file descriptor
Errore nell'inizializzazione: VIDIOCSPICT: Bad file descriptor
Ma io non ho una telecamera su /dev/video, prova a vedere dove trovi il
problema usando il comando where di gdb.
