diff --git a/c_mpos/src/webcam.c b/c_mpos/src/webcam.c index 59d65b63..ba89480f 100644 --- a/c_mpos/src/webcam.c +++ b/c_mpos/src/webcam.c @@ -6,7 +6,6 @@ #include #include #include -#include #include "py/obj.h" #include "py/runtime.h" @@ -24,7 +23,7 @@ #define CAPTURE_HEIGHT 480 #define OUTPUT_WIDTH 240 // Resize to 240x240 #define OUTPUT_HEIGHT 240 -#define NUM_BUFFERS 4 // Use 4 buffers for continuous streaming +#define NUM_BUFFERS 2 // Use 2 buffers, as it worked for two captures // Webcam object type typedef struct _webcam_obj_t { @@ -73,16 +72,42 @@ static void resize_640x480_to_240x240(uint8_t *src, uint8_t *dst) { static mp_obj_t webcam_capture_grayscale(mp_obj_t self_in) { webcam_obj_t *self = MP_OBJ_TO_PTR(self_in); - // Poll for available buffer - struct pollfd pfd = { .fd = self->fd, .events = POLLIN }; - WEBCAM_DEBUG_PRINT("webcam: Polling for available buffer\n"); - if (poll(&pfd, 1, 1000) <= 0) { // 1-second timeout - WEBCAM_DEBUG_PRINT("webcam: Poll timeout or error (errno=%d)\n", errno); - mp_raise_OSError(ETIMEDOUT); + // Try to queue a buffer + struct v4l2_buffer buf = {0}; + bool queued = false; + for (size_t i = 0; i < self->num_buffers; i++) { + memset(&buf, 0, sizeof(buf)); + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + buf.index = i; + + WEBCAM_DEBUG_PRINT("webcam: Attempting to queue buffer (index=%zu)\n", i); + if (ioctl(self->fd, VIDIOC_QBUF, &buf) == 0) { + WEBCAM_DEBUG_PRINT("webcam: Successfully queued buffer (index=%zu)\n", i); + queued = true; + break; + } + WEBCAM_DEBUG_PRINT("webcam: Failed to queue buffer (index=%zu, errno=%d)\n", i, errno); + } + + if (!queued) { + WEBCAM_DEBUG_PRINT("webcam: No buffers available for queuing\n"); + mp_raise_OSError(EAGAIN); // Try again later + } + + // Start streaming if not already started + if (!self->streaming) { + enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + WEBCAM_DEBUG_PRINT("webcam: Starting video streaming\n"); + if (ioctl(self->fd, VIDIOC_STREAMON, &type) < 0) { + WEBCAM_DEBUG_PRINT("webcam: Failed to start video streaming (errno=%d)\n", errno); + mp_raise_OSError(errno); + } + self->streaming = true; } // Dequeue a buffer (capture frame) - struct v4l2_buffer buf = {0}; + memset(&buf, 0, sizeof(buf)); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; WEBCAM_DEBUG_PRINT("webcam: Dequeuing buffer\n"); @@ -184,7 +209,7 @@ static mp_obj_t webcam_init(void) { // Open the webcam device WEBCAM_DEBUG_PRINT("webcam: Opening device %s\n", VIDEO_DEVICE); - self->fd = open(VIDEO_DEVICE, O_RDWR | O_NONBLOCK); // Non-blocking for polling + self->fd = open(VIDEO_DEVICE, O_RDWR); if (self->fd < 0) { WEBCAM_DEBUG_PRINT("webcam: Failed to open device %s (errno=%d)\n", VIDEO_DEVICE, errno); mp_raise_OSError(errno); @@ -216,7 +241,7 @@ static mp_obj_t webcam_init(void) { mp_raise_OSError(errno); } self->num_buffers = req.count; - if (self->num_buffers < 2) { + if (self->num_buffers < NUM_BUFFERS) { WEBCAM_DEBUG_PRINT("webcam: Insufficient buffers allocated (%zu)\n", self->num_buffers); close(self->fd); mp_raise_OSError(ENOMEM); @@ -253,23 +278,6 @@ static mp_obj_t webcam_init(void) { close(self->fd); mp_raise_OSError(errno); } - - // Queue the buffer upfront - memset(&buf, 0, sizeof(buf)); - buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf.memory = V4L2_MEMORY_MMAP; - buf.index = i; - WEBCAM_DEBUG_PRINT("webcam: Initial queuing of buffer %zu\n", i); - if (ioctl(self->fd, VIDIOC_QBUF, &buf) < 0) { - WEBCAM_DEBUG_PRINT("webcam: Failed to queue buffer %zu initially (errno=%d)\n", i, errno); - for (size_t j = 0; j <= i; j++) { - if (self->buffers[j].start != NULL) { - munmap(self->buffers[j].start, self->buffers[j].length); - } - } - close(self->fd); - mp_raise_OSError(errno); - } } // Create a tuple to hold the webcam object and method references