Skip to content

Commit d57aa55

Browse files
webcam: going right direction (EAGAIN)
1 parent d20843c commit d57aa55

File tree

1 file changed

+36
-28
lines changed

1 file changed

+36
-28
lines changed

c_mpos/src/webcam.c

Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
#include <linux/videodev2.h>
77
#include <sys/mman.h>
88
#include <string.h>
9-
#include <poll.h>
109

1110
#include "py/obj.h"
1211
#include "py/runtime.h"
@@ -24,7 +23,7 @@
2423
#define CAPTURE_HEIGHT 480
2524
#define OUTPUT_WIDTH 240 // Resize to 240x240
2625
#define OUTPUT_HEIGHT 240
27-
#define NUM_BUFFERS 4 // Use 4 buffers for continuous streaming
26+
#define NUM_BUFFERS 2 // Use 2 buffers, as it worked for two captures
2827

2928
// Webcam object type
3029
typedef struct _webcam_obj_t {
@@ -73,16 +72,42 @@ static void resize_640x480_to_240x240(uint8_t *src, uint8_t *dst) {
7372
static mp_obj_t webcam_capture_grayscale(mp_obj_t self_in) {
7473
webcam_obj_t *self = MP_OBJ_TO_PTR(self_in);
7574

76-
// Poll for available buffer
77-
struct pollfd pfd = { .fd = self->fd, .events = POLLIN };
78-
WEBCAM_DEBUG_PRINT("webcam: Polling for available buffer\n");
79-
if (poll(&pfd, 1, 1000) <= 0) { // 1-second timeout
80-
WEBCAM_DEBUG_PRINT("webcam: Poll timeout or error (errno=%d)\n", errno);
81-
mp_raise_OSError(ETIMEDOUT);
75+
// Try to queue a buffer
76+
struct v4l2_buffer buf = {0};
77+
bool queued = false;
78+
for (size_t i = 0; i < self->num_buffers; i++) {
79+
memset(&buf, 0, sizeof(buf));
80+
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
81+
buf.memory = V4L2_MEMORY_MMAP;
82+
buf.index = i;
83+
84+
WEBCAM_DEBUG_PRINT("webcam: Attempting to queue buffer (index=%zu)\n", i);
85+
if (ioctl(self->fd, VIDIOC_QBUF, &buf) == 0) {
86+
WEBCAM_DEBUG_PRINT("webcam: Successfully queued buffer (index=%zu)\n", i);
87+
queued = true;
88+
break;
89+
}
90+
WEBCAM_DEBUG_PRINT("webcam: Failed to queue buffer (index=%zu, errno=%d)\n", i, errno);
91+
}
92+
93+
if (!queued) {
94+
WEBCAM_DEBUG_PRINT("webcam: No buffers available for queuing\n");
95+
mp_raise_OSError(EAGAIN); // Try again later
96+
}
97+
98+
// Start streaming if not already started
99+
if (!self->streaming) {
100+
enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
101+
WEBCAM_DEBUG_PRINT("webcam: Starting video streaming\n");
102+
if (ioctl(self->fd, VIDIOC_STREAMON, &type) < 0) {
103+
WEBCAM_DEBUG_PRINT("webcam: Failed to start video streaming (errno=%d)\n", errno);
104+
mp_raise_OSError(errno);
105+
}
106+
self->streaming = true;
82107
}
83108

84109
// Dequeue a buffer (capture frame)
85-
struct v4l2_buffer buf = {0};
110+
memset(&buf, 0, sizeof(buf));
86111
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
87112
buf.memory = V4L2_MEMORY_MMAP;
88113
WEBCAM_DEBUG_PRINT("webcam: Dequeuing buffer\n");
@@ -184,7 +209,7 @@ static mp_obj_t webcam_init(void) {
184209

185210
// Open the webcam device
186211
WEBCAM_DEBUG_PRINT("webcam: Opening device %s\n", VIDEO_DEVICE);
187-
self->fd = open(VIDEO_DEVICE, O_RDWR | O_NONBLOCK); // Non-blocking for polling
212+
self->fd = open(VIDEO_DEVICE, O_RDWR);
188213
if (self->fd < 0) {
189214
WEBCAM_DEBUG_PRINT("webcam: Failed to open device %s (errno=%d)\n", VIDEO_DEVICE, errno);
190215
mp_raise_OSError(errno);
@@ -216,7 +241,7 @@ static mp_obj_t webcam_init(void) {
216241
mp_raise_OSError(errno);
217242
}
218243
self->num_buffers = req.count;
219-
if (self->num_buffers < 2) {
244+
if (self->num_buffers < NUM_BUFFERS) {
220245
WEBCAM_DEBUG_PRINT("webcam: Insufficient buffers allocated (%zu)\n", self->num_buffers);
221246
close(self->fd);
222247
mp_raise_OSError(ENOMEM);
@@ -253,23 +278,6 @@ static mp_obj_t webcam_init(void) {
253278
close(self->fd);
254279
mp_raise_OSError(errno);
255280
}
256-
257-
// Queue the buffer upfront
258-
memset(&buf, 0, sizeof(buf));
259-
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
260-
buf.memory = V4L2_MEMORY_MMAP;
261-
buf.index = i;
262-
WEBCAM_DEBUG_PRINT("webcam: Initial queuing of buffer %zu\n", i);
263-
if (ioctl(self->fd, VIDIOC_QBUF, &buf) < 0) {
264-
WEBCAM_DEBUG_PRINT("webcam: Failed to queue buffer %zu initially (errno=%d)\n", i, errno);
265-
for (size_t j = 0; j <= i; j++) {
266-
if (self->buffers[j].start != NULL) {
267-
munmap(self->buffers[j].start, self->buffers[j].length);
268-
}
269-
}
270-
close(self->fd);
271-
mp_raise_OSError(errno);
272-
}
273281
}
274282

275283
// Create a tuple to hold the webcam object and method references

0 commit comments

Comments
 (0)