Skip to content

Commit 67c4f17

Browse files
committed
- added libv4l-convert to support more camera formats
- added git version - removed RGB interactions with libjpeg - removed unused YUV conversions
1 parent c7f9446 commit 67c4f17

File tree

4 files changed

+46
-283
lines changed

4 files changed

+46
-283
lines changed

makefile

+8-5
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
# options to compile
2-
OPTIONS = -D_TIME -D_TRAP_FPE -D_GNU_SOURCE
2+
OPTIONS =
33

44
# compiler
55
CC = gcc
66

77
# C flags
8-
CFLAGS = -Wall -march=native -Werror
8+
CFLAGS = -Wall -Werror
99

1010
# libs
11-
LIBS = -ljpeg
11+
LIBS = -ljpeg -lv4lconvert -lv4l2
1212

1313
# executable name
1414
EXENAME = v4l2grab
@@ -18,9 +18,12 @@ SRCS = $(wildcard *.c)
1818
OBJS = $(SRCS:%.c=%.o)
1919
# header files
2020
HDRS = $(wildcard *.h)
21+
# git version
22+
GITVERSION = "$(shell git describe --always --tags --dirty)"
23+
2124

2225
$(EXENAME): $(OBJS)
23-
$(CC) $(OBJS) $(CFLAGS) -o $(EXENAME) $(LIBS)
26+
$(CC) $(OBJS) $(CFLAGS) $(OPTIONS) -o $(EXENAME) $(LIBS)
2427

2528
$(OBJS): $(HDRS) makefile
2629

@@ -30,5 +33,5 @@ clean:
3033
rm -f *.o *~ *.s *.il
3134

3235
%.o : %.c
33-
$(CC) $*.c -c $(CFLAGS)
36+
$(CC) $*.c -c $(CFLAGS) $(OPTIONS) -D__GITVERSION='$(GITVERSION)'
3437

v4l2grab.c

+38-124
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,15 @@
4646
#include <asm/types.h>
4747
#include <linux/videodev2.h>
4848
#include <jpeglib.h>
49+
#include <libv4l2.h>
4950
#include "yuv.h"
5051

5152
#define CLEAR(x) memset (&(x), 0, sizeof (x))
5253

54+
#ifndef __GITVERSION
55+
#define __GITVERSION "unknown"
56+
#endif
57+
5358
#if defined(IO_MMAP) || defined(IO_USERPTR)
5459
// minimum number of buffers to request in VIDIOC_REQBUFS call
5560
#define VIDIOC_REQBUFS_COUNT 2
@@ -76,13 +81,11 @@ static io_method io = IO_METHOD_MMAP;
7681
static int fd = -1;
7782
struct buffer * buffers = NULL;
7883
static unsigned int n_buffers = 0;
79-
unsigned int pixelformat = 0;
8084

8185
// global settings
8286
static unsigned int width = 640;
8387
static unsigned int height = 480;
8488
static unsigned char jpegQuality = 70;
85-
static J_COLOR_SPACE jpegColorSpace = JCS_RGB;
8689
static char* jpegFilename = NULL;
8790
static char* deviceName = "/dev/video0";
8891

@@ -93,7 +96,7 @@ static char* deviceName = "/dev/video0";
9396
*/
9497
static void errno_exit(const char* s)
9598
{
96-
fprintf(stderr, "%s error %d, %s\n", s, errno, strerror (errno));
99+
fprintf(stderr, "%s error %d, %s\n", s, errno, strerror(errno));
97100
exit(EXIT_FAILURE);
98101
}
99102

@@ -109,7 +112,7 @@ static int xioctl(int fd, int request, void* argp)
109112
{
110113
int r;
111114

112-
do r = ioctl(fd, request, argp);
115+
do r = v4l2_ioctl(fd, request, argp);
113116
while (-1 == r && EINTR == errno);
114117

115118
return r;
@@ -142,7 +145,7 @@ static void jpegWrite(unsigned char* img)
142145
cinfo.image_width = width;
143146
cinfo.image_height = height;
144147
cinfo.input_components = 3;
145-
cinfo.in_color_space = jpegColorSpace;
148+
cinfo.in_color_space = JCS_YCbCr;
146149

147150
// set jpeg compression parameters to default
148151
jpeg_set_defaults(&cinfo);
@@ -176,54 +179,7 @@ static void imageProcess(const void* p)
176179
unsigned char* src = (unsigned char*)p;
177180
unsigned char* dst = malloc(width*height*3*sizeof(char));
178181

179-
switch (jpegColorSpace) {
180-
case JCS_GRAYSCALE:
181-
fprintf(stderr, "monochrome color space not supported!\n");
182-
exit(EXIT_FAILURE);
183-
case JCS_RGB:
184-
switch (pixelformat) {
185-
case V4L2_PIX_FMT_YUV420:
186-
// convert from YUV420 to RGB888
187-
YUV420toRGB888(width, height, src, dst);
188-
break;
189-
190-
case V4L2_PIX_FMT_YUYV:
191-
// convert from YUV422 to RGB888
192-
YUV422toRGB888(width, height, src, dst);
193-
break;
194-
195-
default:
196-
fprintf(stderr, "Pixelformat of device not supported with colorspace RGB!\n");
197-
exit(EXIT_FAILURE);
198-
}
199-
break;
200-
case JCS_YCbCr:
201-
switch (pixelformat) {
202-
case V4L2_PIX_FMT_YUV420:
203-
// convert from YUV420 to YUV444
204-
YUV420toYUV444(width, height, src, dst);
205-
break;
206-
case V4L2_PIX_FMT_YUYV:
207-
// convert from YUV422 to YUV444
208-
YUV422toYUV444(width, height, src, dst);
209-
break;
210-
default:
211-
fprintf(stderr, "Pixelformat of device not supported with colorspace YUV!\n");
212-
exit(EXIT_FAILURE);
213-
}
214-
break;
215-
case JCS_CMYK:
216-
fprintf(stderr, "CMYK color space not supported!\n");
217-
exit(EXIT_FAILURE);
218-
case JCS_YCCK:
219-
fprintf(stderr, "YCCK color space not supported!\n");
220-
exit(EXIT_FAILURE);
221-
case JCS_UNKNOWN:
222-
default:
223-
fprintf(stderr, "Color space is unknown and therefore not supported!\n");
224-
exit(EXIT_FAILURE);
225-
break;
226-
}
182+
YUV420toYUV444(width, height, src, dst);
227183

228184
// write jpeg
229185
jpegWrite(dst);
@@ -245,7 +201,7 @@ static int frameRead(void)
245201
switch (io) {
246202
#ifdef IO_READ
247203
case IO_METHOD_READ:
248-
if (-1 == read (fd, buffers[0].start, buffers[0].length)) {
204+
if (-1 == v4l2_read(fd, buffers[0].start, buffers[0].length)) {
249205
switch (errno) {
250206
case EAGAIN:
251207
return 0;
@@ -316,7 +272,7 @@ static int frameRead(void)
316272
}
317273

318274
for (i = 0; i < n_buffers; ++i)
319-
if (buf.m.userptr == (unsigned long) buffers[i].start && buf.length == buffers[i].length)
275+
if (buf.m.userptr == (unsigned long)buffers[i].start && buf.length == buffers[i].length)
320276
break;
321277

322278
assert (i < n_buffers);
@@ -492,15 +448,15 @@ static void deviceUninit(void)
492448
#ifdef IO_MMAP
493449
case IO_METHOD_MMAP:
494450
for (i = 0; i < n_buffers; ++i)
495-
if (-1 == munmap (buffers[i].start, buffers[i].length))
451+
if (-1 == v4l2_munmap(buffers[i].start, buffers[i].length))
496452
errno_exit("munmap");
497453
break;
498454
#endif
499455

500456
#ifdef IO_USERPTR
501457
case IO_METHOD_USERPTR:
502458
for (i = 0; i < n_buffers; ++i)
503-
free (buffers[i].start);
459+
free(buffers[i].start);
504460
break;
505461
#endif
506462
}
@@ -573,7 +529,7 @@ static void mmapInit(void)
573529
errno_exit("VIDIOC_QUERYBUF");
574530

575531
buffers[n_buffers].length = buf.length;
576-
buffers[n_buffers].start = mmap (NULL /* start anywhere */, buf.length, PROT_READ | PROT_WRITE /* required */, MAP_SHARED /* recommended */, fd, buf.m.offset);
532+
buffers[n_buffers].start = v4l2_mmap(NULL /* start anywhere */, buf.length, PROT_READ | PROT_WRITE /* required */, MAP_SHARED /* recommended */, fd, buf.m.offset);
577533

578534
if (MAP_FAILED == buffers[n_buffers].start)
579535
errno_exit("mmap");
@@ -605,7 +561,7 @@ static void userptrInit(unsigned int buffer_size)
605561
}
606562
}
607563

608-
buffers = calloc(4, sizeof (*buffers));
564+
buffers = calloc(4, sizeof(*buffers));
609565

610566
if (!buffers) {
611567
fprintf(stderr, "Out of memory\n");
@@ -614,7 +570,7 @@ static void userptrInit(unsigned int buffer_size)
614570

615571
for (n_buffers = 0; n_buffers < 4; ++n_buffers) {
616572
buffers[n_buffers].length = buffer_size;
617-
buffers[n_buffers].start = memalign (/* boundary */ page_size, buffer_size);
573+
buffers[n_buffers].start = memalign(/* boundary */ page_size, buffer_size);
618574

619575
if (!buffers[n_buffers].start) {
620576
fprintf(stderr, "Out of memory\n");
@@ -699,63 +655,21 @@ static void deviceInit(void)
699655

700656
CLEAR(fmt);
701657

702-
// query device
703-
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
704-
if (-1 == xioctl(fd, VIDIOC_G_FMT, &fmt))
705-
errno_exit("VIDIOC_G_FMT");
706-
707-
pixelformat = fmt.fmt.pix.pixelformat;
708-
709-
switch (pixelformat) {
710-
case V4L2_PIX_FMT_SBGGR8:
711-
fprintf(stderr, "Pixel format 4L2_PIX_FMT_SBGGR8 not supported!\n");
712-
exit(EXIT_FAILURE);
713-
break;
714-
case V4L2_PIX_FMT_SN9C10X:
715-
fprintf(stderr, "Pixel format V4L2_PIX_FMT_SN9C10X not supported!\n");
716-
exit(EXIT_FAILURE);
717-
break;
718-
case V4L2_PIX_FMT_MJPEG:
719-
fprintf(stderr, "Pixel format V4L2_PIX_FMT_MJPEG not supported!\n");
720-
exit(EXIT_FAILURE);
721-
break;
722-
case V4L2_PIX_FMT_JPEG:
723-
fprintf(stderr, "Pixel format V4L2_PIX_FMT_JPEG not supported!\n");
724-
exit(EXIT_FAILURE);
725-
break;
726-
case V4L2_PIX_FMT_RGB24:
727-
fprintf(stderr, "Pixel format V4L2_PIX_FMT_RGB24 not supported!\n");
728-
exit(EXIT_FAILURE);
729-
break;
730-
case V4L2_PIX_FMT_UYVY:
731-
fprintf(stderr, "Pixel format V4L2_PIX_FMT_UYVY not supported!\n");
732-
exit(EXIT_FAILURE);
733-
break;
734-
case V4L2_PIX_FMT_YUV422P:
735-
fprintf(stderr, "Pixel format V4L2_PIX_FMT_YUV422P not supported!\n");
736-
exit(EXIT_FAILURE);
737-
break;
738-
case V4L2_PIX_FMT_YUV420:
739-
printf("Using pixel format V4L2_PIX_FMT_YUV420.\n");
740-
break;
741-
case V4L2_PIX_FMT_YUYV:
742-
printf("Using pixel format V4L2_PIX_FMT_YUYV.\n");
743-
break;
744-
default:
745-
fprintf(stderr, "Unknown pixel format %u!\n", pixelformat);
746-
exit(EXIT_FAILURE);
747-
break;
748-
};
749-
750658
// v4l2_format
751659
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
752660
fmt.fmt.pix.width = width;
753661
fmt.fmt.pix.height = height;
754662
fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
663+
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420;
755664

756665
if (-1 == xioctl(fd, VIDIOC_S_FMT, &fmt))
757666
errno_exit("VIDIOC_S_FMT");
758667

668+
if (fmt.fmt.pix.pixelformat != V4L2_PIX_FMT_YUV420) {
669+
fprintf(stderr,"Libv4l didn't accept YUV420 format. Can't proceed.\n");
670+
exit(EXIT_FAILURE);
671+
}
672+
759673
/* Note VIDIOC_S_FMT may change width and height. */
760674
if (width != fmt.fmt.pix.width) {
761675
width = fmt.fmt.pix.width;
@@ -801,7 +715,7 @@ static void deviceInit(void)
801715
*/
802716
static void deviceClose(void)
803717
{
804-
if (-1 == close (fd))
718+
if (-1 == v4l2_close(fd))
805719
errno_exit("close");
806720

807721
fd = -1;
@@ -816,22 +730,22 @@ static void deviceOpen(void)
816730

817731
// stat file
818732
if (-1 == stat(deviceName, &st)) {
819-
fprintf(stderr, "Cannot identify '%s': %d, %s\n", deviceName, errno, strerror (errno));
733+
fprintf(stderr, "Cannot identify '%s': %d, %s\n", deviceName, errno, strerror(errno));
820734
exit(EXIT_FAILURE);
821735
}
822736

823737
// check if its device
824-
if (!S_ISCHR (st.st_mode)) {
738+
if (!S_ISCHR(st.st_mode)) {
825739
fprintf(stderr, "%s is no device\n", deviceName);
826740
exit(EXIT_FAILURE);
827741
}
828742

829743
// open device
830-
fd = open(deviceName, O_RDWR /* required */ | O_NONBLOCK, 0);
744+
fd = v4l2_open(deviceName, O_RDWR /* required */ | O_NONBLOCK, 0);
831745

832746
// check if opening was successfull
833747
if (-1 == fd) {
834-
fprintf(stderr, "Cannot open '%s': %d, %s\n", deviceName, errno, strerror (errno));
748+
fprintf(stderr, "Cannot open '%s': %d, %s\n", deviceName, errno, strerror(errno));
835749
exit(EXIT_FAILURE);
836750
}
837751
}
@@ -841,37 +755,37 @@ static void deviceOpen(void)
841755
*/
842756
static void usage(FILE* fp, int argc, char** argv)
843757
{
844-
fprintf (fp,
758+
fprintf(fp,
845759
"Usage: %s [options]\n\n"
846760
"Options:\n"
847761
"-d | --device name Video device name [/dev/video0]\n"
848762
"-h | --help Print this message\n"
849763
"-o | --output Set JPEG output filename\n"
850764
"-q | --quality Set JPEG quality (0-100)\n"
851-
"-y | --jpeg-yuv Set JPEG colorspace to YUV\n"
852765
"-m | --mmap Use memory mapped buffers\n"
853766
"-r | --read Use read() calls\n"
854767
"-u | --userptr Use application allocated buffers\n"
855-
"-W | --width width\n"
856-
"-H | --height height\n"
768+
"-W | --width Set image width\n"
769+
"-H | --height Set image height\n"
770+
"-v | --version Print version"
857771
"",
858772
argv[0]);
859773
}
860774

861-
static const char short_options [] = "d:ho:q:ymruW:H:";
775+
static const char short_options [] = "d:ho:q:mruW:H:v";
862776

863777
static const struct option
864778
long_options [] = {
865779
{ "device", required_argument, NULL, 'd' },
866780
{ "help", no_argument, NULL, 'h' },
867781
{ "output", required_argument, NULL, 'o' },
868782
{ "quality", required_argument, NULL, 'q' },
869-
{ "jpeg-yuv", no_argument, NULL, 'y' },
870783
{ "mmap", no_argument, NULL, 'm' },
871784
{ "read", no_argument, NULL, 'r' },
872785
{ "userptr", no_argument, NULL, 'u' },
873786
{ "width", required_argument, NULL, 'W' },
874787
{ "height", required_argument, NULL, 'H' },
788+
{ "version", no_argument, NULL, 'v' },
875789
{ 0, 0, 0, 0 }
876790
};
877791

@@ -909,11 +823,6 @@ int main(int argc, char **argv)
909823
jpegQuality = atoi(optarg);
910824
break;
911825

912-
case 'y':
913-
// set jpeg colorspace to YUV
914-
jpegColorSpace = JCS_YCbCr;
915-
break;
916-
917826
case 'm':
918827
#ifdef IO_MMAP
919828
io = IO_METHOD_MMAP;
@@ -951,6 +860,11 @@ int main(int argc, char **argv)
951860
height = atoi(optarg);
952861
break;
953862

863+
case 'v':
864+
printf("Version: %s\n", __GITVERSION);
865+
exit(EXIT_SUCCESS);
866+
break;
867+
954868
default:
955869
usage(stderr, argc, argv);
956870
exit(EXIT_FAILURE);

0 commit comments

Comments
 (0)