D'après ce qu'on trouve sur le net, il semble que la taille des données soient trop grosses pour être utilisées via un appel à read, et qu'il faille utiliser mmap...
Version imprimable
D'après ce qu'on trouve sur le net, il semble que la taille des données soient trop grosses pour être utilisées via un appel à read, et qu'il faille utiliser mmap...
Je pensais aussi, peut-être libérer l'espace mémoire après chaque capture avec un
Code:
1
2 free(mapbuf);
Je réitère donc mon conseil :
1) utilise le double-buffering
(je n'ai jamais utilisé comme je le disais la vidéo sur Linux, mais a) c'est une technique classique du traitement d'image, et 2) puisqu'ils le mentionnent expréssément dans la doc de la fonction c'est que ça doit être asez important :P )
2) Que fait la fonction ptrfonction ??
c'est ptete là dedans que ça se passe aussi... Là aussi un test rapide en la mettant (ou la partie qui éventuellement fait des calculs) en commentaire peut s'avérer utile...
et finalement, tu vois, ce que j'avais donné en première réponse (mettre des printf pour mesurer) aurait évité 3 jours de recherche à tenter d'optimiser la fonction qui n'était pas le goulot 8O ....
Bonjour a tous, ;)
Je me pose une question existancielle !
Que viens faire du double buffering pour enregistrer des images ?
Pour les voir en animations OUI complètement OUI,
mais pour les enregistrer :? ?
Là, je suis perplexe !
Soit vous n'avez pas compris son utilisation,
soit il faut que vous m'expliquiez car c'est moi qui suis à la traîne :mouarf: !
Merci ...
Visiblement d'après la doc pointée plus haut c'est que la fonction de capture peut être appelée de manière non synchrone... Et donc pendant qu'elle capture on peut jouer sur un buffer alternatif qui aurait stocké la précédente image...
Je ne sais pas vraiment puisque je n'ai pas utilsé, mas la doc paraît assez claire...
Bien, voici là ou j'en suis.... D'après ce que j'ai trouvé sur le net, le double buffering permet d'atteindre 30 frames/s.... en théorie, pas mal...
J'ai essayé en utilisant ce que souviron34 m'a suggéré:
et là surprise, VIDEOCMCAPTURE n'est pas une fonction = pas de compilation possible....Code:
1
2
3
4
5
6
7
8
9 VIDIOCMCAPTURE(0) while (whatever) { VIDIOCMCAPTURE(1) VIDIOCSYNC(0) /* process frame 0 while the hardware captures frame 1 */ VIDIOCMCAPTURE(0) VIDIOCSYNC(1) /* process frame 1 while the hardware captures frame 0 */
Alors j'ai cherché d'autre manière de procédé, et j'ai obtenu ceci:
Et normalement, ca devrait faire effet... mais je reste bloqué à 10 images seconde.....Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65 void captureImage(void (*ptrfonction) (unsigned char*, int, int, int), int rep) { if(ioctl(descrpFichier, VIDIOCGMBUF, &mbuf)<0) { perror("VIDIOCGMBUF"); exit(-1); } ptr = (unsigned char*)mmap(0, mbuf.size, PROT_READ|PROT_WRITE, MAP_SHARED,descrpFichier,0); if(ptr==(unsigned char*) -1){ perror("mmap"); exit(1); } /*Les demandes de captures sont mises dans la file d'attente du buffer*/ mapbuf.height = HEIGHT ; mapbuf.width = WIDTH; mapbuf.format = PALETTE; printf ("buffers: %d - size: %d\n", mbuf.frames,mbuf.size); printf("Début de traitement\n"); for(frame=0; frame<mbuf.frames; frame++) { mapbuf.frame = frame; if(ioctl(descrpFichier, VIDIOCMCAPTURE, &mapbuf)<0) { perror("VIDIOCMCAPTURE"); exit(-1); } } frame = 0; nbcapture = 0; while(nbcapture<750) { i=-1; while(i < 0) { i = ioctl(descrpFichier, VIDIOCSYNC, &frame); if(i < 0 && errno == EINTR) { fprintf(stderr,"-"); continue; } if(i < 0) { perror("VIDIOCSYNC"); exit (-1); } break; } /* refer the frame to save */ posImg = ptr + mbuf.offsets[frame]; /*permet d'appeler extraxpix */ ptrfonction(posImg,HEIGHT, WIDTH, nbcapture); /* remet le buffer à disposition de l'acquisition*/ mapbuf.frame = frame; if(ioctl(descrpFichier, VIDIOCMCAPTURE, &mapbuf)<0) { perror("VIDIOCMCAPTURE"); exit(-1); } /* image suivante */ frame++; /* reset to the 1st frame */ if (frame>=mbuf.frames) frame = 0; nbcapture++; }
D'après ce que j'ai compris du lien que j'avais mentionné, c'était du PSEUDO code !!!!Citation:
J'ai essayé en utilisant ce que souviron34 m'a suggéré:
Code :
VIDIOCMCAPTURE(0)
while (whatever) {
VIDIOCMCAPTURE(1)
VIDIOCSYNC(0)
/* process frame 0 while the hardware captures frame 1 */
VIDIOCMCAPTURE(0)
VIDIOCSYNC(1)
/* process frame 1 while the hardware captures frame 0 */
et là surprise, VIDEOCMCAPTURE n'est pas une fonction = pas de compilation possible....
(au dessus, au début , il y a les ioctl avec ce genre de flags). Il semble que VIDIOCMCAPTURE et les autres comme ça soient des flags... Qu'il faillent appeler via les ioctl.... Comme c'est indiqué...
Ce qu'ils veulent dire est :
tu appelles les ioctl sur buffer1/image1, synchronise sur 0, puis l'inverse, puis l'inverse etc....
Oui, là je me suis un brin précipité vraiment SANS réfléchir, mea culpa:oops: ....
Je vais essayer tel que s'est mentionné.... (ca doit vraiment commencer à m'énerver, vu que je fais plus attention à rien.....:cry: :cry: :cry: )
bien, je pense avoir fait quelquechose qui ressemble au double buffering, mais le problème,c 'est que la cadence est toujours aussi lente....:cry:
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63 ptr = (unsigned char*)mmap(0, mbuf.size, PROT_READ|PROT_WRITE, MAP_SHARED,descrpFichier,0); if(ptr==(unsigned char*) -1){ perror("mmap"); exit(1); } mmaps = (struct video_mmap*)(malloc (mbuf.frames * sizeof (struct video_mmap))); /*Les demandes de captures sont mises dans la file d'attente du buffer*/ i = 0; while (i < mbuf.frames) { mmaps[i].frame = i; mmaps[i].width = WIDTH; mmaps[i].height = HEIGHT; mmaps[i].format = PALETTE; i++; } if (ioctl (descrpFichier, VIDIOCMCAPTURE, &mmaps[0]) == -1) { perror ("VIDIOCMCAPTURE"); exit (1); } // Permet de vérifier que deux buffer sont bien disponibles printf ("buffers: %d - size: %d\n", mbuf.frames,mbuf.size); while(nbcapture<1500){ if (ioctl (descrpFichier, VIDIOCMCAPTURE, &mmaps[1]) == -1) { perror ("VIDIOCMCAPTURE"); exit (1); } if (ioctl (descrpFichier, VIDIOCSYNC, &mmaps[0]) == -1) { perror ("VIDIOCSYNC,"); exit (1); } if (ioctl (descrpFichier, VIDIOCMCAPTURE, &mmaps[0]) == -1) { perror ("VIDIOCMCAPTURE"); exit (1); } if (ioctl (descrpFichier, VIDIOCSYNC, &mmaps[1]) == -1) { perror ("VIDIOCSYNC,"); exit (1); } // et on "imprime" les deux images indexées posImg= ptr+ mbuf.offsets[0]; //ptrfonction(posImg,HEIGHT, WIDTH, nbcapture); nbcapture++; posImg= ptr+ mbuf.offsets[1]; //ptrfonction(posImg,HEIGHT, WIDTH, nbcapture); nbcapture++; }
Quelqu'un est il familier du double buffering, ou a déjà utilisé V4L?? Parce que là j'ai l'impression d'avoir fait le tour....
tu n'avais pas une fonction ptrfonction quelque part ??
Si elle y est toujours, ré-essaye le coup de la mettre en commentaire pour voir la vitesse.
Si c'est elle qui ralentit, poste le code..
Si c'est pas elle, désolé , comme je disais plus haut je n'ai jamais utilisé ces fonctions....
la routine captureimage prend en paramètre une fonction ptrfonction qui n'est ni plus ni moins que la fonction extraxpix.....
Je ne sais pas. Là je ne vois rien, surtout que tu as mis extactPix en commentaires. Par contre, le premier est mal placé (d'après l'algo donné), il devrait être :
Mais si tu les mets en commentaires, c'est sûr que c'est ABSOLUMENT EQUIVALENT au fait de ne PAS avoir de double-buffering, puisqu'il n'y a rien pour ralentir l'éxécution.. Donc les requêtes se suivent comme avant, dans ce cas-là.. ça ne sert QUE si tu as du traitement entre les 2..Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 if (ioctl (descrpFichier, VIDIOCSYNC, &mmaps[0]) == -1) { perror ("VIDIOCSYNC,"); exit (1); } posImg= ptr+ mbuf.offsets[0]; //ptrfonction(posImg,HEIGHT, WIDTH, nbcapture); nbcapture++; if (ioctl (descrpFichier, VIDIOCMCAPTURE, &mmaps[0]) == -1) { perror ("VIDIOCMCAPTURE"); exit (1); }
Donc si sans rien tu arrives à cette cadence, cela me semble (mais c'est pas une certitude parce que jamais utilisé) être la limite sur ton système...
Mais d'après le nom de la varaible tu lis un fichier, c'est ça ? Tu pourrais pas essayer de le lire (d'un coup ou par morceaux) et de travailler en mémoire ?
OOOpppss désolé je suis pas encore très bien réveillé et j'avais pas vu que c'était avec ioctl...
Oui, ils sont en commentaires pour vérifier la cadence avec le double buffering, sans traitement...ce qui est la même chose avec les fonctions ptrfonction (==extrapix).
J'arrive pas à savoir si c'est la demande d'acquisition (= VIDIOCMCAPTURE) ou le rapatriement de l'image issue de la mémoire (= VIDIOCSYNC) qui est le plus long... Dans la mesure où on ne peut pas les utiliser séparément (j'ai essayé pour savoir qui prend le plus de temps, mais ce fut infructeux), je comprends pas tout.
Sur ce que j'ai vu sur le net, je me demande si on peut pas faire plusieurs appels à VIDIOCMCAPTURE et un seul appel à VIDIOCSYNC pour rapatrier le tout.. Puis on se décale avec mbuf.offsets[frame] pour lire les images ainsi récupérées...
Quant aux limites de mon système, ce serait la loose... Mais je vois pas pourquoi apparemment on peut atteindre 30 frames/seconde, et pas moi!!!:cry:
Sauf si c'est une mauvaise utilisation des fonctions. Mais j'ai beau cherché, je tombe sur des solutions équivalentes, et qui n'ont pas de grandes cadences.
(toujours aux alentours de 10 frame/s)
eurfff !!! Tu sais 1) ça dépend certainement de la taille des images, et 2) ce ne serait pas la première fois que on te dis ce qui PEUT se passer dans le MEILLEUR des cas !! (voir les banques, les assurances, et en info. tout ce qui se dit...) :(Citation:
Quant aux limites de mon système, ce serait la loose... Mais je vois pas pourquoi apparemment on peut atteindre 30 frames/seconde, et pas moi!!!
Quant à :
ça doit dépendre de pas mal de choses : le matériel utilsé entre autres... les transferts de mémoire peuvent être longs si les vitesses de bus ne correspondent pas, si les architectures physiques sont différentes, si... Mais la capture peut aussi être longue...Citation:
J'arrive pas à savoir si c'est la demande d'acquisition (= VIDIOCMCAPTURE) ou le rapatriement de l'image issue de la mémoire (= VIDIOCSYNC) qui est le plus long... Dans la mesure où on ne peut pas les utiliser séparément (j'ai essayé pour savoir qui prend le plus de temps, mais ce fut infructeux), je comprends pas tout.
Là je ne peux plus rien faire pour toi, désolé... Ce n'a plus l'air d'être dans mes cordes... :(
Bien, merci en tout cas de la patience accordée... Mais ce topic n'est pas fermé pour autant!! Help me!!
Bien, j'ai des choses à rajouter, je ne sais pas si ca aidera quelqu'un à toruver une issue à mon problème, mais ca pourra peut-être aider quelqu'un un jour (histoire de laisser une trace)
J'ai fait des tests avec deux webcam logitech, qui ont pour point commun d'utiliser le même driver pwc:
Resultats avec une quickcam communicate STX:
Resultats avec une quickam sphere (en 640*480, 15 fr/s, en 320*240, 30 fr/s):Code:
1
2
3
4
5 pour 1500 images, - en 640*480: plus de 5 min - en 320*240: 2'10 - en 176*144 (résolution min): 2'8
J'ai par ailleurs trouvé sur le net que vraisemblablement les drivers pwc seraient plus "lent"... Ce qui impliquerait de tester mon code avec une camera avec un driver PCiA (de mémoire c'est le nom...), histoire de voir s'il y a une différence.Code:
1
2
3
4
5 pour 1500 images, - en 640*480: plus de 4 min - en 320*240: 2'30 - en 176*144 (résolution min): 2'30
Mais j'ai aussi remarqué des ralentissements de l'ordinateur lors de l'acquisition, donc il y a peut-être moyen d'optimiser la gestion de la mémoire dans le code de "camera.c".
Peut-être tout ceci aiguillera une bonne âme désireuse de m'aider??