1- #include "py/obj.h"
2- #include "py/runtime.h"
3- #include "py/mperrno.h"
4-
51#include <stdio.h>
62#include <stdlib.h>
73#include <fcntl.h>
117#include <sys/mman.h>
128#include <string.h>
139#include <errno.h>
10+ #include "py/obj.h"
11+ #include "py/runtime.h"
12+ #include "py/mperrno.h"
1413
1514#define WIDTH 640
1615#define HEIGHT 480
1716#define NUM_BUFFERS 4
1817#define OUTPUT_WIDTH 240
1918#define OUTPUT_HEIGHT 240
2019
21- // Webcam object structure
2220typedef struct _webcam_obj_t {
2321 mp_obj_base_t base ;
2422 int fd ;
@@ -27,7 +25,6 @@ typedef struct _webcam_obj_t {
2725 int frame_count ;
2826} webcam_obj_t ;
2927
30- // Convert YUYV to grayscale and downscale to 240x240
3128static void yuyv_to_grayscale_240x240 (unsigned char * yuyv , unsigned char * gray , int in_width , int in_height ) {
3229 float x_ratio = (float )in_width / OUTPUT_WIDTH ;
3330 float y_ratio = (float )in_height / OUTPUT_HEIGHT ;
@@ -42,7 +39,6 @@ static void yuyv_to_grayscale_240x240(unsigned char *yuyv, unsigned char *gray,
4239 }
4340}
4441
45- // Save grayscale frame as .raw
4642static void save_raw (const char * filename , unsigned char * data , int width , int height ) {
4743 FILE * fp = fopen (filename , "wb" );
4844 if (!fp ) {
@@ -53,7 +49,6 @@ static void save_raw(const char *filename, unsigned char *data, int width, int h
5349 fclose (fp );
5450}
5551
56- // Initialize webcam
5752static int init_webcam (webcam_obj_t * self , const char * device ) {
5853 self -> fd = open (device , O_RDWR );
5954 if (self -> fd < 0 ) {
@@ -123,7 +118,6 @@ static int init_webcam(webcam_obj_t *self, const char *device) {
123118 return 0 ;
124119}
125120
126- // Deinitialize webcam
127121static void deinit_webcam (webcam_obj_t * self ) {
128122 if (self -> fd < 0 ) return ;
129123
@@ -140,40 +134,43 @@ static void deinit_webcam(webcam_obj_t *self) {
140134 self -> fd = -1 ;
141135}
142136
143- // Capture a single frame
144137static mp_obj_t capture_frame (webcam_obj_t * self ) {
145138 struct v4l2_buffer buf = {0 };
146139 buf .type = V4L2_BUF_TYPE_VIDEO_CAPTURE ;
147140 buf .memory = V4L2_MEMORY_MMAP ;
148141 if (ioctl (self -> fd , VIDIOC_DQBUF , & buf ) < 0 ) {
149- mp_raise_msg (& mp_type_OSError , MP_ERROR_TEXT ("Cannot dequeue buffer" ));
142+ mp_raise_OSError (MP_EIO );
143+ }
144+
145+ unsigned char * gray = (unsigned char * )malloc (OUTPUT_WIDTH * OUTPUT_HEIGHT );
146+ if (!gray ) {
147+ mp_raise_OSError (MP_ENOMEM );
150148 }
151149
152- // Convert to grayscale 240x240
153- unsigned char * gray = mp_obj_new_bytearray (OUTPUT_WIDTH * OUTPUT_HEIGHT );
154150 yuyv_to_grayscale_240x240 (self -> buffers [buf .index ], gray , WIDTH , HEIGHT );
155151
156- // Save to file
157152 char filename [32 ];
158153 snprintf (filename , sizeof (filename ), "frame_%03d.raw" , self -> frame_count ++ );
159154 save_raw (filename , gray , OUTPUT_WIDTH , OUTPUT_HEIGHT );
160155
161- // Requeue buffer
156+ mp_obj_t result = mp_obj_new_bytes (gray , OUTPUT_WIDTH * OUTPUT_HEIGHT );
157+
158+ free (gray );
159+
162160 if (ioctl (self -> fd , VIDIOC_QBUF , & buf ) < 0 ) {
163- mp_raise_msg ( & mp_type_OSError , MP_ERROR_TEXT ( "Cannot requeue buffer" ) );
161+ mp_raise_OSError ( MP_EIO );
164162 }
165163
166- return mp_obj_new_bytes ( gray , OUTPUT_WIDTH * OUTPUT_HEIGHT ) ;
164+ return result ;
167165}
168166
169- // MicroPython bindings
170167static mp_obj_t webcam_make_new (const mp_obj_type_t * type , size_t n_args , size_t n_kw , const mp_obj_t * args ) {
171168 webcam_obj_t * self = m_new_obj (webcam_obj_t );
172169 self -> base .type = type ;
173170 self -> fd = -1 ;
174171
175172 if (init_webcam (self , "/dev/video0" ) < 0 ) {
176- mp_raise_msg ( & mp_type_OSError , MP_ERROR_TEXT ( "Webcam initialization failed" ) );
173+ mp_raise_OSError ( MP_EIO );
177174 }
178175
179176 return MP_OBJ_FROM_PTR (self );
@@ -189,7 +186,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(webcam_deinit_obj, webcam_deinit);
189186static mp_obj_t webcam_capture_frame (mp_obj_t self_in ) {
190187 webcam_obj_t * self = MP_OBJ_TO_PTR (self_in );
191188 if (self -> fd < 0 ) {
192- mp_raise_msg ( & mp_type_OSError , MP_ERROR_TEXT ( "Webcam not initialized" ) );
189+ mp_raise_OSError ( MP_EIO );
193190 }
194191 return capture_frame (self );
195192}
0 commit comments