You've already forked MicroPythonOS
mirror of
https://github.com/m5stack/MicroPythonOS.git
synced 2026-05-20 11:51:27 -07:00
webcam: going right direction (EAGAIN)
This commit is contained in:
+36
-28
@@ -6,7 +6,6 @@
|
||||
#include <linux/videodev2.h>
|
||||
#include <sys/mman.h>
|
||||
#include <string.h>
|
||||
#include <poll.h>
|
||||
|
||||
#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
|
||||
|
||||
Reference in New Issue
Block a user