Skip to content

Commit 549f554

Browse files
add webcam_capture.c for test
1 parent 016028f commit 549f554

File tree

1 file changed

+201
-0
lines changed

1 file changed

+201
-0
lines changed

webcam_test/webcam_capture.c

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
#include <fcntl.h>
4+
#include <unistd.h>
5+
#include <sys/ioctl.h>
6+
#include <linux/videodev2.h>
7+
#include <sys/mman.h>
8+
#include <string.h>
9+
#include <errno.h>
10+
11+
#define WIDTH 640
12+
#define HEIGHT 480
13+
#define NUM_BUFFERS 4
14+
15+
// Global variables
16+
int fd = -1;
17+
struct v4l2_buffer buf;
18+
void *buffers[NUM_BUFFERS];
19+
size_t buffer_length;
20+
21+
// Convert YUYV to RGB for PPM output
22+
void yuyv_to_rgb(unsigned char *yuyv, unsigned char *rgb, int width, int height) {
23+
for (int i = 0; i < width * height; i++) {
24+
int index = i * 2;
25+
int y = yuyv[index];
26+
int u = yuyv[index + 1];
27+
int v = yuyv[index + 3];
28+
29+
int r = y + (1.402 * (v - 128));
30+
int g = y - (0.344 * (u - 128)) - (0.714 * (v - 128));
31+
int b = y + (1.772 * (u - 128));
32+
33+
r = r < 0 ? 0 : (r > 255 ? 255 : r);
34+
g = g < 0 ? 0 : (g > 255 ? 255 : g);
35+
b = b < 0 ? 0 : (b > 255 ? 255 : b);
36+
37+
rgb[i * 3 + 0] = r;
38+
rgb[i * 3 + 1] = g;
39+
rgb[i * 3 + 2] = b;
40+
}
41+
}
42+
43+
// Save frame as PPM
44+
void save_ppm(const char *filename, unsigned char *data, int width, int height) {
45+
FILE *fp = fopen(filename, "wb");
46+
if (!fp) {
47+
perror("Cannot open file");
48+
return;
49+
}
50+
fprintf(fp, "P6\n%d %d\n255\n", width, height);
51+
unsigned char *rgb = malloc(width * height * 3);
52+
yuyv_to_rgb(data, rgb, width, height);
53+
fwrite(rgb, 1, width * height * 3, fp);
54+
fclose(fp);
55+
free(rgb);
56+
}
57+
58+
int init_webcam(const char *device) {
59+
// Open device
60+
fd = open(device, O_RDWR);
61+
if (fd < 0) {
62+
perror("Cannot open device");
63+
return -1;
64+
}
65+
66+
// Set format
67+
struct v4l2_format fmt = {0};
68+
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
69+
fmt.fmt.pix.width = WIDTH;
70+
fmt.fmt.pix.height = HEIGHT;
71+
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
72+
fmt.fmt.pix.field = V4L2_FIELD_ANY;
73+
if (ioctl(fd, VIDIOC_S_FMT, &fmt) < 0) {
74+
perror("Cannot set format");
75+
close(fd);
76+
return -1;
77+
}
78+
79+
// Request buffers
80+
struct v4l2_requestbuffers req = {0};
81+
req.count = NUM_BUFFERS;
82+
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
83+
req.memory = V4L2_MEMORY_MMAP;
84+
if (ioctl(fd, VIDIOC_REQBUFS, &req) < 0) {
85+
perror("Cannot request buffers");
86+
close(fd);
87+
return -1;
88+
}
89+
90+
// Map buffers
91+
for (int i = 0; i < NUM_BUFFERS; i++) {
92+
struct v4l2_buffer buf = {0};
93+
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
94+
buf.memory = V4L2_MEMORY_MMAP;
95+
buf.index = i;
96+
if (ioctl(fd, VIDIOC_QUERYBUF, &buf) < 0) {
97+
perror("Cannot query buffer");
98+
close(fd);
99+
return -1;
100+
}
101+
buffer_length = buf.length;
102+
buffers[i] = mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset);
103+
if (buffers[i] == MAP_FAILED) {
104+
perror("Cannot map buffer");
105+
close(fd);
106+
return -1;
107+
}
108+
}
109+
110+
// Queue buffers
111+
for (int i = 0; i < NUM_BUFFERS; i++) {
112+
struct v4l2_buffer buf = {0};
113+
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
114+
buf.memory = V4L2_MEMORY_MMAP;
115+
buf.index = i;
116+
if (ioctl(fd, VIDIOC_QBUF, &buf) < 0) {
117+
perror("Cannot queue buffer");
118+
return -1;
119+
}
120+
}
121+
122+
// Start streaming
123+
enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
124+
if (ioctl(fd, VIDIOC_STREAMON, &type) < 0) {
125+
perror("Cannot start streaming");
126+
return -1;
127+
}
128+
129+
return 0;
130+
}
131+
132+
void deinit_webcam() {
133+
if (fd < 0) return;
134+
135+
// Stop streaming
136+
enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
137+
ioctl(fd, VIDIOC_STREAMOFF, &type);
138+
139+
// Unmap buffers
140+
for (int i = 0; i < NUM_BUFFERS; i++) {
141+
if (buffers[i] != MAP_FAILED) {
142+
munmap(buffers[i], buffer_length);
143+
}
144+
}
145+
146+
// Close device
147+
close(fd);
148+
fd = -1;
149+
}
150+
151+
int capture_frame(char *filename) {
152+
// Dequeue buffer
153+
struct v4l2_buffer buf = {0};
154+
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
155+
buf.memory = V4L2_MEMORY_MMAP;
156+
if (ioctl(fd, VIDIOC_DQBUF, &buf) < 0) {
157+
perror("Cannot dequeue buffer");
158+
return -1;
159+
}
160+
161+
// Save frame
162+
save_ppm(filename, buffers[buf.index], WIDTH, HEIGHT);
163+
164+
// Requeue buffer
165+
if (ioctl(fd, VIDIOC_QBUF, &buf) < 0) {
166+
perror("Cannot requeue buffer");
167+
return -1;
168+
}
169+
170+
return 0;
171+
}
172+
173+
int capture_frames(int n) {
174+
for (int i = 0; i < n; i++) {
175+
char filename[32];
176+
snprintf(filename, sizeof(filename), "frame_%03d.ppm", i);
177+
if (capture_frame(filename) < 0) {
178+
printf("Failed to capture frame %d\n", i);
179+
return -1;
180+
}
181+
printf("Captured frame %d to %s\n", i, filename);
182+
}
183+
return 0;
184+
}
185+
186+
int main() {
187+
if (init_webcam("/dev/video0") < 0) {
188+
printf("Webcam initialization failed\n");
189+
return -1;
190+
}
191+
192+
if (capture_frames(100) < 0) {
193+
printf("Frame capture failed\n");
194+
deinit_webcam();
195+
return -1;
196+
}
197+
198+
deinit_webcam();
199+
printf("Webcam deinitialized\n");
200+
return 0;
201+
}

0 commit comments

Comments
 (0)