Boa tarde a todos, fiz alguns testes com esse código sem sucesso, o tamanho do arquivo continua em 0 bytes, provavelmente alguma configuração mal feita nas structs... pois o arquivo compilado roda normal, e na compilação o gcc não retorna nenhuma mensagem de warning (?)
Comando utilizado para compilação.
gcc -o <nome-do-programa> -Wall -g -O2 <nome-arquivo.c>
Sei que a maioria do pessoal conhece bem o gcc, mas pra quem ainda não observou o man, aqui algumas dicas)
Observações para linha de comando:
"-Wall" todas as mensagens de erro e warming do compilador gcc.
"-g" gera símbolos para depuração com gdb.
"-O2" nível 2 de otimização do código na compilação.
segue abaixo código testado:
#include <errno.h>
#include <fcntl.h>
#include <linux/videodev2.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <unistd.h>
uint8_t *buffer;
static int xioctl(int fd, int request, void *arg)
{
int r;
do r = ioctl (fd, request, arg);
while (-1 == r && EINTR == errno);
return r;
}
int print_caps(int fd)
{
struct v4l2_capability caps = {};
if (-1 == xioctl(fd, VIDIOC_QUERYCAP, &caps))
{
perror("Querying Capabilities");
return 1;
}
printf( "Driver Caps:\n"
" Driver: \"%s\"\n"
" Card: \"%s\"\n"
" Bus: \"%s\"\n"
" Version: %d.%d\n"
" Capabilities: %08x\n",
caps.driver,
caps.card,
caps.bus_info,
(caps.version>>16)&&0xff,
(caps.version>>24)&&0xff,
caps.capabilities);
struct v4l2_cropcap cropcap = {0};
cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (-1 == xioctl (fd, VIDIOC_CROPCAP, &cropcap))
{
perror("Querying Cropping Capabilities");
return 1;
}
printf( "\nCamera Cropping:\n"
" Bounds: %dx%d+%d+%d\n"
" Default: %dx%d+%d+%d\n"
" Aspect: %d/%d\n",
cropcap.bounds.width, cropcap.bounds.height, cropcap.bounds.left, cropcap.bounds.top,
cropcap.defrect.width, cropcap.defrect.height, cropcap.defrect.left, cropcap.defrect.top,
cropcap.pixelaspect.numerator, cropcap.pixelaspect.denominator);
int support_grbg10 = 0;
struct v4l2_fmtdesc fmtdesc = {0};
fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
char fourcc[5] = {0};
char c, e;
printf("\n FMT : CE Desc\n--------------------\n");
while (0 == xioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc))
{
strncpy(fourcc, (char *)&fmtdesc.pixelformat, 4);
if (fmtdesc.pixelformat == V4L2_PIX_FMT_SGRBG10)
support_grbg10 = 1;
c = fmtdesc.flags & 1? 'C' : ' ';
e = fmtdesc.flags & 2? 'E' : ' ';
printf(" %s: %c%c %s\n", fourcc, c, e, fmtdesc.description);
fmtdesc.index++;
}
/*
if (!support_grbg10)
{
printf("Doesn't support GRBG10.\n");
return 1;
}
*/
struct v4l2_format fmt = {0};
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
/*
fmt.fmt.pix.width = 752;
fmt.fmt.pix.height = 480;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SGRBG10;
fmt.fmt.pix.field = V4L2_FIELD_NONE;
*/
fmt.fmt.pix.width = 640;
fmt.fmt.pix.height = 480;
//fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_BGR24;
//fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_GREY;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
fmt.fmt.pix.field = V4L2_FIELD_NONE;
if (-1 == xioctl(fd, VIDIOC_S_FMT, &fmt))
{
perror("Setting Pixel Format");
return 1;
}
strncpy(fourcc, (char *)&fmt.fmt.pix.pixelformat, 4);
printf( "Selected Camera Mode:\n"
" Width: %d\n"
" Height: %d\n"
" PixFmt: %s\n"
" Field: %d\n",
fmt.fmt.pix.width,
fmt.fmt.pix.height,
fourcc,
fmt.fmt.pix.field);
return 0;
}
int init_mmap(int fd)
{
struct v4l2_requestbuffers req = {0};
req.count = 1;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
if (-1 == xioctl(fd, VIDIOC_REQBUFS, &req))
{
perror("Requesting Buffer");
return 1;
}
struct v4l2_buffer buf = {0};
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = 0;
if(-1 == xioctl(fd, VIDIOC_QUERYBUF, &buf))
{
perror("Querying Buffer");
return 1;
}
buffer = mmap (NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset);
printf("Length: %d\nAddress: %p\n", buf.length, buffer);
printf("Image Length: %d\n", buf.bytesused);
return 0;
}
int capture_image(int fd)
{
struct v4l2_buffer buf = {0};
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = 0;
if(-1 == xioctl(fd, VIDIOC_QBUF, &buf))
{
perror("Query Buffer");
return 1;
}
if(-1 == xioctl(fd, VIDIOC_STREAMON, &buf.type))
{
perror("Start Capture");
return 1;
}
fd_set fds;
FD_ZERO(&fds);
FD_SET(fd, &fds);
struct timeval tv = {0};
tv.tv_sec = 2;
int r = select(fd+1, &fds, NULL, NULL, &tv);
if(-1 == r)
{
perror("Waiting for Frame");
return 1;
}
if(-1 == xioctl(fd, VIDIOC_DQBUF, &buf))
{
perror("Retrieving Frame");
return 1;
}
//int outfd = open("out.img", O_RDWR);
int outfd = open("out.jpeg", O_RDWR);
write(outfd, buffer, buf.bytesused);
close(outfd);
if(-1 == xioctl(fd, VIDIOC_STREAMOFF, &buf.type))
{
perror("OFF Capture");
return 1;
}
return 0;
}
int main()
{
int fd;
fd = open("/dev/video0", O_RDWR);
if (fd == -1) {
perror("Opening video device");
return 1;
}
if(print_caps(fd))
return 1;
if(init_mmap(fd))
return 1;
if(capture_image(fd))
return 1;
close(fd);
return 0;
}
Desde já agradeço, aguardando perguntas e respostas dos leitores.
Abraço.