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

Répondre à