1313
1414#define WIDTH 640
1515#define HEIGHT 480
16- #define NUM_BUFFERS 4
16+ #define NUM_BUFFERS 1 # more buffers doesnt seem to help so one is enough
1717#define OUTPUT_WIDTH 240
1818#define OUTPUT_HEIGHT 240
1919
20- // Forward declaration of the webcam type
20+ #define WEBCAM_DEBUG_PRINT (...) mp_printf(&mp_plat_print, __VA_ARGS__)
21+
2122static const mp_obj_type_t webcam_type ;
2223
2324typedef struct _webcam_obj_t {
@@ -26,27 +27,34 @@ typedef struct _webcam_obj_t {
2627 void * buffers [NUM_BUFFERS ];
2728 size_t buffer_length ;
2829 int frame_count ;
29- unsigned char * gray_buffer ; // Persistent buffer for memoryview
30+ unsigned char * gray_buffer ;
3031} webcam_obj_t ;
3132
3233static void yuyv_to_grayscale_240x240 (unsigned char * yuyv , unsigned char * gray , int in_width , int in_height ) {
33- float x_ratio = (float )in_width / OUTPUT_WIDTH ;
34- float y_ratio = (float )in_height / OUTPUT_HEIGHT ;
34+ // Crop to 480x480 centered region
35+ int crop_size = 480 ;
36+ int crop_x_offset = (in_width - crop_size ) / 2 ; // Center the crop: (640 - 480) / 2 = 80
37+ int crop_y_offset = (in_height - crop_size ) / 2 ; // Center the crop: (480 - 480) / 2 = 0
38+
39+ // Downscale ratios from 480x480 to 240x240
40+ float x_ratio = (float )crop_size / OUTPUT_WIDTH ; // 480 / 240 = 2.0
41+ float y_ratio = (float )crop_size / OUTPUT_HEIGHT ; // 480 / 240 = 2.0
3542
3643 for (int y = 0 ; y < OUTPUT_HEIGHT ; y ++ ) {
3744 for (int x = 0 ; x < OUTPUT_WIDTH ; x ++ ) {
38- int src_x = (int )(x * x_ratio );
39- int src_y = (int )(y * y_ratio );
40- int src_index = (src_y * in_width + src_x ) * 2 ;
41- gray [y * OUTPUT_WIDTH + x ] = yuyv [src_index ];
45+ // Map output pixel to cropped region
46+ int src_x = (int )(x * x_ratio ) + crop_x_offset ; // Adjust for crop offset
47+ int src_y = (int )(y * y_ratio ) + crop_y_offset ; // Adjust for crop offset
48+ int src_index = (src_y * in_width + src_x ) * 2 ; // YUYV uses 2 bytes per pixel
49+ gray [y * OUTPUT_WIDTH + x ] = yuyv [src_index ]; // Extract Y channel
4250 }
4351 }
4452}
4553
4654static void save_raw (const char * filename , unsigned char * data , int width , int height ) {
4755 FILE * fp = fopen (filename , "wb" );
4856 if (!fp ) {
49- fprintf ( stderr , "Cannot open file %s: %s\n" , filename , strerror (errno ));
57+ WEBCAM_DEBUG_PRINT ( "Cannot open file %s: %s\n" , filename , strerror (errno ));
5058 return ;
5159 }
5260 fwrite (data , 1 , width * height , fp );
@@ -56,7 +64,7 @@ static void save_raw(const char *filename, unsigned char *data, int width, int h
5664static int init_webcam (webcam_obj_t * self , const char * device ) {
5765 self -> fd = open (device , O_RDWR );
5866 if (self -> fd < 0 ) {
59- fprintf ( stderr , "Cannot open device: %s\n" , strerror (errno ));
67+ WEBCAM_DEBUG_PRINT ( "Cannot open device: %s\n" , strerror (errno ));
6068 return -1 ;
6169 }
6270
@@ -67,7 +75,7 @@ static int init_webcam(webcam_obj_t *self, const char *device) {
6775 fmt .fmt .pix .pixelformat = V4L2_PIX_FMT_YUYV ;
6876 fmt .fmt .pix .field = V4L2_FIELD_ANY ;
6977 if (ioctl (self -> fd , VIDIOC_S_FMT , & fmt ) < 0 ) {
70- fprintf ( stderr , "Cannot set format: %s\n" , strerror (errno ));
78+ WEBCAM_DEBUG_PRINT ( "Cannot set format: %s\n" , strerror (errno ));
7179 close (self -> fd );
7280 return -1 ;
7381 }
@@ -77,7 +85,7 @@ static int init_webcam(webcam_obj_t *self, const char *device) {
7785 req .type = V4L2_BUF_TYPE_VIDEO_CAPTURE ;
7886 req .memory = V4L2_MEMORY_MMAP ;
7987 if (ioctl (self -> fd , VIDIOC_REQBUFS , & req ) < 0 ) {
80- fprintf ( stderr , "Cannot request buffers: %s\n" , strerror (errno ));
88+ WEBCAM_DEBUG_PRINT ( "Cannot request buffers: %s\n" , strerror (errno ));
8189 close (self -> fd );
8290 return -1 ;
8391 }
@@ -88,14 +96,14 @@ static int init_webcam(webcam_obj_t *self, const char *device) {
8896 buf .memory = V4L2_MEMORY_MMAP ;
8997 buf .index = i ;
9098 if (ioctl (self -> fd , VIDIOC_QUERYBUF , & buf ) < 0 ) {
91- fprintf ( stderr , "Cannot query buffer: %s\n" , strerror (errno ));
99+ WEBCAM_DEBUG_PRINT ( "Cannot query buffer: %s\n" , strerror (errno ));
92100 close (self -> fd );
93101 return -1 ;
94102 }
95103 self -> buffer_length = buf .length ;
96104 self -> buffers [i ] = mmap (NULL , buf .length , PROT_READ | PROT_WRITE , MAP_SHARED , self -> fd , buf .m .offset );
97105 if (self -> buffers [i ] == MAP_FAILED ) {
98- fprintf ( stderr , "Cannot map buffer: %s\n" , strerror (errno ));
106+ WEBCAM_DEBUG_PRINT ( "Cannot map buffer: %s\n" , strerror (errno ));
99107 close (self -> fd );
100108 return -1 ;
101109 }
@@ -107,21 +115,21 @@ static int init_webcam(webcam_obj_t *self, const char *device) {
107115 buf .memory = V4L2_MEMORY_MMAP ;
108116 buf .index = i ;
109117 if (ioctl (self -> fd , VIDIOC_QBUF , & buf ) < 0 ) {
110- fprintf ( stderr , "Cannot queue buffer: %s\n" , strerror (errno ));
118+ WEBCAM_DEBUG_PRINT ( "Cannot queue buffer: %s\n" , strerror (errno ));
111119 return -1 ;
112120 }
113121 }
114122
115123 enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE ;
116124 if (ioctl (self -> fd , VIDIOC_STREAMON , & type ) < 0 ) {
117- fprintf ( stderr , "Cannot start streaming: %s\n" , strerror (errno ));
125+ WEBCAM_DEBUG_PRINT ( "Cannot start streaming: %s\n" , strerror (errno ));
118126 return -1 ;
119127 }
120128
121129 self -> frame_count = 0 ;
122130 self -> gray_buffer = (unsigned char * )malloc (OUTPUT_WIDTH * OUTPUT_HEIGHT );
123131 if (!self -> gray_buffer ) {
124- fprintf ( stderr , "Cannot allocate gray buffer: %s\n" , strerror (errno ));
132+ WEBCAM_DEBUG_PRINT ( "Cannot allocate gray buffer: %s\n" , strerror (errno ));
125133 close (self -> fd );
126134 return -1 ;
127135 }
@@ -178,7 +186,7 @@ static mp_obj_t capture_frame(webcam_obj_t *self) {
178186// snprintf(filename, sizeof(filename), "frame_%03d.raw", self->frame_count++);
179187// save_raw(filename, self->gray_buffer, OUTPUT_WIDTH, OUTPUT_HEIGHT);
180188
181- mp_obj_t result = mp_obj_new_bytes ( self -> gray_buffer , OUTPUT_WIDTH * OUTPUT_HEIGHT );
189+ mp_obj_t result = mp_obj_new_memoryview ( 'b' , OUTPUT_WIDTH * OUTPUT_HEIGHT , self -> gray_buffer );
182190
183191 if (ioctl (self -> fd , VIDIOC_QBUF , & buf ) < 0 ) {
184192 mp_raise_OSError (MP_EIO );
@@ -189,7 +197,7 @@ static mp_obj_t capture_frame(webcam_obj_t *self) {
189197
190198static mp_obj_t webcam_init (size_t n_args , const mp_obj_t * args ) {
191199 mp_arg_check_num (n_args , 0 , 0 , 1 , false);
192- const char * device = "/dev/video0" ; // Default device
200+ const char * device = "/dev/video0" ;
193201 if (n_args == 1 ) {
194202 device = mp_obj_str_get_str (args [0 ]);
195203 }
0 commit comments