Bonjour.
J'ai une webcam Logitech quickam pro 4000 v4l. Elle fonctionne sans
problème avec les applications usuelles (xawtv, camorama etc).
J'essaye de développer un programme (en c ou c++) qui va me permettre
d'effectuer une capture et un traitement sur l'image. A ce que j'ai
compris, il faut utilise l'api de v4l2. J'ai donc un bout de code qui
capture une image et l'écrit dans un fichier. Le problème est que je
n'arrive pas à changer la palette ni le "depth" de la capture. Il n'y a
pas de message d'erreur particulier mais lorsque je relis les
paramètres, ils sont inchangés.
j'essaye de changer les valeurs ainsi:
imageProperties.depth =24
imageProperties.palette = VIDEO_PALETTE_RGB24;
if (ioctl (deviceHandle, VIDIOCSPICT, &imageProperties) == -1)
{ // failed to set the image properties
printf ("Erreur de palette.\n");
}
La palette n'est effectivement pas changée. Y a t'il une autre méthode?
Je suis preneur de toute autre solution. Si vous connaissez autre chose
(une abstraction de v4l par exemple) je serai aussi interessé. Merci.
ci joint voici un bout de code effectuant la capture.
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <linux/videodev.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
char* deviceName = "/dev/video0";
int deviceHandle = 0;
int i; // temporary counter
struct video_capability capability;
struct video_channel queryChannel;
struct video_channel selectedChannel;
struct video_window captureWindow;
struct video_picture imageProperties;
struct video_mbuf memoryBuffer;
struct video_mmap* mmaps;
char* memoryMap;
int channelNumber = 0;
int width = 320;
int height = 240;
int depth;
int palette;
int bufferIndex;
char* NextFrame()
{
// send a request to begin capturing to the currently indexed buffer
if (ioctl (deviceHandle, VIDIOCMCAPTURE, &mmaps[bufferIndex]) == -1)
{ // capture request failed
}
// move bufferIndex to the next frame
++ bufferIndex;
if (bufferIndex == memoryBuffer.frames)
{ // bufferIndex is indexing beyond the last buffer
// set it to index the first buffer
bufferIndex = 0;
}
// wait for the currently indexed frame to complete capture
if (ioctl (deviceHandle, VIDIOCSYNC, &mmaps[bufferIndex]) == -1)
{ // sync request failed
}
// return the address of the frame data for the current buffer index
return (memoryMap + memoryBuffer.offsets[bufferIndex]);
}
void Capabilities(video_capability cap){
printf("type : %x\n",cap.type);
}
int main()
{
// open the device
deviceName = "/dev/video0";
deviceHandle = open (deviceName, O_RDWR);
if (deviceHandle == -1)
{ // could not open device
printf ("Could not open device %s - %s\n", deviceName, sys_errlist[errno]);
return -1;
}
// get device capabilities
if (ioctl (deviceHandle, VIDIOCGCAP, &capability) == -1)
{ // query failed
printf ("could not obtain device capabilities\n");
return -1;
}
Capabilities(capability);
if ((capability.type & VID_TYPE_CAPTURE) == 0)
{ // this device cannot capture video to memory, exit
printf ("this device cannot capture video to memory\n");
return -1;
}
// enumerate and print out the channels
printf ("Select a channel:\n");
i = 0;
while (i < capability.channels)
{
queryChannel.channel = i;
if (ioctl (deviceHandle, VIDIOCGCHAN, &queryChannel) != -1)
{ // ioctl success, queryChannel contains
// information about this channel
printf ("%d. %s\n", queryChannel.channel, queryChannel.name);
}
++ i;
}
// have the user select a channel
printf (": ");
fflush (stdout);
scanf ("%d", &channelNumber);
// set the selected channel
selectedChannel.channel = channelNumber;
selectedChannel.norm = VIDEO_MODE_AUTO;
if (ioctl (deviceHandle, VIDIOCSCHAN, &selectedChannel) == -1)
{ // could not set the selected channel
printf ("Could not set channel #%d\nNot a fatal error.", channelNumber);
}
// set the desired width and height
if ((capability.type & VID_TYPE_SCALES) == -1)
{ // supports the ability to scale captured images
// have the user enter a desired width
printf ("Enter the desired width (e.g. 320): ");
fflush (stdout);
scanf ("%d", &width);
printf ("Enter the desired height (e.g. 240): ");
fflush (stdout);
scanf ("%d", &height);
captureWindow.x = 0;
captureWindow.y = 0;
captureWindow.width = width;
captureWindow.height = height;
captureWindow.chromakey = 0;
captureWindow.flags = 0;
captureWindow.clips = 0;
captureWindow.clipcount = 0;
if (ioctl (deviceHandle, VIDIOCSWIN, &captureWindow) == -1)
{ // could not set window values for capture
printf ("Could not set desired dimensions\nNot a fatal error.\n");
}
}
// retrieve the actual width and height of the capturing images
if (ioctl (deviceHandle, VIDIOCGWIN, &captureWindow) == -1)
{ // could not obtain specifics of capture window
printf ("Could not obtain capture window dimensions.\n");
}
width = captureWindow.width;
height = captureWindow.height;
printf ("Capturing dimensions are : %d, %d\n", width, height);
// request that we capture to 24bit RGB
// get image properties
if (ioctl (deviceHandle, VIDIOCGPICT, &imageProperties) != -1)
{ // successfully retrieved the default image properties
printf("ok, on regle les propriétées\n");
printf("depth: %d\n", imageProperties.depth);
printf("palette: %d\n", imageProperties.palette);
printf("palette: %d\n", VIDEO_PALETTE_RGB24);
// the following values are for requesting 24bit RGB
imageProperties.depth =24 ;
if (ioctl (deviceHandle, VIDIOCSPICT, &imageProperties) == -1)
{ // failed to set the image properties
printf ("Erreur depth\n");
}
imageProperties.palette = VIDEO_PALETTE_RGB24;
if (ioctl (deviceHandle, VIDIOCSPICT, &imageProperties) == -1)
{ // failed to set the image properties
printf ("Erreur de palette.\n");
}
}
// verify that the requested capture pixel depth and palette succeeded
if (ioctl (deviceHandle, VIDIOCGPICT, &imageProperties) == -1)
{ // failed to retrieve default image properties
printf ("Failed to retrieve the video depth and palette.\n");
return -1;
}
depth = imageProperties.depth;
palette = imageProperties.palette;
if ((depth != 24) || (palette != VIDEO_PALETTE_RGB24))
{ // not a format our program supports
printf("depth %d\n", depth);
printf("palette %d\n", palette);
printf ("Format is not 24bit RGB.\n");
return -1;
}
// obtain memory about capture space
if (ioctl (deviceHandle, VIDIOCGMBUF, &memoryBuffer) == -1)
{ // failed to retrieve information about capture memory space
printf ("Failed to retrieve information about MMIO space.\n");
return -1;
}
// obtain memory mapped area
memoryMap = (char*)mmap (0, memoryBuffer.size, PROT_READ | PROT_WRITE, MAP_SHARED, deviceHandle, 0);
if ((int)memoryMap == -1)
{ // failed to retrieve pointer to memory mapped area
printf ("Failed to obtain MMIO space.\n");
return -1;
}
// allocate structures
mmaps = (struct video_mmap*)(malloc (memoryBuffer.frames * sizeof (struct video_mmap)));
// fill out the fields
i = 0;
while (i < memoryBuffer.frames)
{
mmaps[i].frame = i;
mmaps[i].width = width;
mmaps[i].height = height;
mmaps[i].format = palette;
++ i;
}
// request capture to each buffer except the last one
i = 0;
while (i < (memoryBuffer.frames-1))
{
if (ioctl (deviceHandle, VIDIOCMCAPTURE, &mmaps[i]) == -1)
{ // capture request failed
}
++ i;
}
// set our index to the last buffer
bufferIndex = memoryBuffer.frames-1;
// capture and write out ten frames
printf ("Capture is ready; capturing 10 images.\n");
int i = 0;
while (i < 10)
{
char* frame = NextFrame();
// write out PPM file
char fname[80];
sprintf (fname, "output%02d.ppm", i);
printf ("Writing out PPM file %s\n", fname);
FILE* fp;
if ((fp = fopen (fname, "w")) == NULL)
{
printf ("Could not open file %s for writing.\n", fname);
return -1;
}
fprintf (fp, "P6\n%d %d\n255\n", width, height);
int n = width * height;
for (int index = 0; index < n; ++ index)
{
putc (frame[index*3+2], fp);
putc (frame[index*3+1], fp);
putc (frame[index*3+0], fp);
}
fflush (fp);
fclose (fp);
++ i;
}
printf ("Use 'xv output*' to view output.\n");
// free the video_mmap structures
free (mmaps);
// unmap the capture memory
munmap (memoryMap, memoryBuffer.size);
// close the device
close (deviceHandle);
return 0;
}
_______________________________________________
gull mailing list
[email protected]
http://lists.alphanet.ch/mailman/listinfo/gull