35
35
36
36
#include "shared-bindings/camera/Camera.h"
37
37
38
- #define JPG_COMPRESS_RATIO (9)
39
- #define SPRESENSE_CAMIMAGE_MEM_ALIGN (32)
40
-
41
38
typedef struct {
42
39
const char * devpath ;
43
40
int fd ;
44
41
} camera_dev_t ;
45
42
46
43
STATIC camera_dev_t camera_dev = {"/dev/video" , -1 };
47
44
48
- static void camera_size_to_width_and_height (camera_imagesize_t size , uint16_t * width , uint16_t * height ) {
49
- switch (size ) {
50
- case IMAGESIZE_320x240 :
51
- * height = VIDEO_VSIZE_QVGA ;
52
- * width = VIDEO_HSIZE_QVGA ;
53
- break ;
54
- case IMAGESIZE_640x320 :
55
- * height = VIDEO_VSIZE_VGA ;
56
- * width = VIDEO_HSIZE_VGA ;
57
- break ;
58
- case IMAGESIZE_1280x720 :
59
- * height = VIDEO_VSIZE_HD ;
60
- * width = VIDEO_HSIZE_HD ;
61
- break ;
62
- case IMAGESIZE_1280x960 :
63
- * height = VIDEO_VSIZE_QUADVGA ;
64
- * width = VIDEO_HSIZE_QUADVGA ;
65
- break ;
66
- case IMAGESIZE_1920x1080 :
67
- * height = VIDEO_VSIZE_FULLHD ;
68
- * width = VIDEO_HSIZE_FULLHD ;
69
- break ;
70
- case IMAGESIZE_2048x1536 :
71
- * height = VIDEO_VSIZE_3M ;
72
- * width = VIDEO_HSIZE_3M ;
73
- break ;
74
- case IMAGESIZE_2560x1920 :
75
- * height = VIDEO_VSIZE_5M ;
76
- * width = VIDEO_HSIZE_5M ;
77
- break ;
78
- default :
79
- mp_raise_ValueError (translate ("Size not supported" ));
80
- break ;
45
+ static bool camera_check_width_and_height (uint16_t width , uint16_t height ) {
46
+ if ((width == VIDEO_HSIZE_QVGA && height == VIDEO_VSIZE_QVGA ) ||
47
+ (width == VIDEO_HSIZE_VGA && height == VIDEO_VSIZE_VGA ) ||
48
+ (width == VIDEO_HSIZE_HD && height == VIDEO_VSIZE_HD ) ||
49
+ (width == VIDEO_HSIZE_QUADVGA && height == VIDEO_VSIZE_QUADVGA ) ||
50
+ (width == VIDEO_HSIZE_FULLHD && height == VIDEO_VSIZE_FULLHD ) ||
51
+ (width == VIDEO_HSIZE_3M && height == VIDEO_VSIZE_3M ) ||
52
+ (width == VIDEO_HSIZE_5M && height == VIDEO_VSIZE_5M )) {
53
+ return true;
54
+ } else {
55
+ return false;
56
+ }
57
+ }
58
+
59
+ static bool camera_check_buffer_length (uint16_t width , uint16_t height , camera_imageformat_t format , size_t length ) {
60
+ if (format == IMAGEFORMAT_JPG ) {
61
+ // In SPRESENSE SDK, JPEG compression quality=80 by default.
62
+ // In such setting, the maximum actual measured size of JPEG image
63
+ // is about width * height * 2 / 9.
64
+ return length >= (size_t )(width * height * 2 / 9 ) ? true : false;
65
+ } else {
66
+ return false;
67
+ }
68
+ }
69
+
70
+ static bool camera_check_format (camera_imageformat_t format ) {
71
+ if (format == IMAGEFORMAT_JPG ) {
72
+ return true;
73
+ } else {
74
+ return false;
81
75
}
82
76
}
83
77
@@ -118,7 +112,9 @@ static void camera_start_preview() {
118
112
camera_start_streaming (V4L2_BUF_TYPE_VIDEO_CAPTURE );
119
113
}
120
114
121
- void common_hal_camera_construct (camera_obj_t * self , camera_imagesize_t size ) {
115
+ extern uint32_t _ebss ;
116
+ extern uint32_t _stext ;
117
+ void common_hal_camera_construct (camera_obj_t * self , uint16_t width , uint16_t height ) {
122
118
if (camera_dev .fd < 0 ) {
123
119
if (video_initialize (camera_dev .devpath ) < 0 ) {
124
120
mp_raise_ValueError (translate ("Could not initialize Camera" ));
@@ -129,25 +125,13 @@ void common_hal_camera_construct(camera_obj_t *self, camera_imagesize_t size) {
129
125
}
130
126
}
131
127
132
- uint16_t width , height ;
133
-
134
- camera_size_to_width_and_height (size , & width , & height );
135
-
136
- self -> size = size ;
137
-
138
- // In SPRESENSE SDK, JPEG compression quality=80 by default.
139
- // In such setting, the maximum actual measured size of JPEG image
140
- // is about width * height * 2 / 9.
141
- self -> buffer_size = (size_t )(width * height * 2 / JPG_COMPRESS_RATIO );;
142
- self -> buffer = m_malloc (self -> buffer_size , true);
143
- if (self -> buffer == NULL ) {
144
- mp_raise_msg (& mp_type_MemoryError , translate ("Couldn't allocate picture buffer" ));
145
- }
146
- self -> picture_buffer = self -> buffer ;
147
- while ((uint32_t )self -> picture_buffer % SPRESENSE_CAMIMAGE_MEM_ALIGN != 0 ) {
148
- self -> picture_buffer ++ ;
128
+ if (!camera_check_width_and_height (width , height )) {
129
+ mp_raise_ValueError (translate ("Size not supported" ));
149
130
}
150
131
132
+ self -> width = width ;
133
+ self -> height = height ;
134
+
151
135
camera_start_preview ();
152
136
153
137
camera_set_format (V4L2_BUF_TYPE_STILL_CAPTURE , V4L2_PIX_FMT_JPEG , width , height );
@@ -164,8 +148,6 @@ void common_hal_camera_deinit(camera_obj_t *self) {
164
148
165
149
video_uninitialize ();
166
150
167
- m_free (self -> buffer );
168
-
169
151
close (camera_dev .fd );
170
152
camera_dev .fd = -1 ;
171
153
}
@@ -174,14 +156,26 @@ bool common_hal_camera_deinited(camera_obj_t *self) {
174
156
return camera_dev .fd < 0 ;
175
157
}
176
158
177
- void common_hal_camera_take_picture (camera_obj_t * self ) {
159
+ size_t common_hal_camera_take_picture (camera_obj_t * self , uint8_t * buffer , size_t len , camera_imageformat_t format ) {
160
+ if (!camera_check_width_and_height (self -> width , self -> height )) {
161
+ mp_raise_ValueError (translate ("Size not supported" ));
162
+ }
163
+ if (!camera_check_buffer_length (self -> width , self -> height , format , len )) {
164
+ mp_raise_ValueError (translate ("Buffer is too small" ));
165
+ }
166
+ if (!camera_check_format (format )) {
167
+ mp_raise_ValueError (translate ("Format not supported" ));
168
+ }
169
+
170
+ camera_set_format (V4L2_BUF_TYPE_STILL_CAPTURE , V4L2_PIX_FMT_JPEG , self -> width , self -> height );
171
+
178
172
v4l2_buffer_t buf ;
179
173
180
174
memset (& buf , 0 , sizeof (v4l2_buffer_t ));
181
175
buf .type = V4L2_BUF_TYPE_STILL_CAPTURE ;
182
176
buf .memory = V4L2_MEMORY_USERPTR ;
183
- buf .m .userptr = (unsigned long )self -> picture_buffer ;
184
- buf .length = self -> buffer_size - SPRESENSE_CAMIMAGE_MEM_ALIGN ;
177
+ buf .m .userptr = (unsigned long )buffer ;
178
+ buf .length = len ;
185
179
ioctl (camera_dev .fd , VIDIOC_QBUF , (unsigned long )& buf );
186
180
187
181
ioctl (camera_dev .fd , VIDIOC_TAKEPICT_START , 0 );
@@ -190,35 +184,21 @@ void common_hal_camera_take_picture(camera_obj_t *self) {
190
184
191
185
ioctl (camera_dev .fd , VIDIOC_TAKEPICT_STOP , false);
192
186
193
- self -> picture_size = (size_t )buf .bytesused ;
187
+ return (size_t )buf .bytesused ;
194
188
}
195
189
196
- uint8_t * common_hal_camera_get_picture_buffer (camera_obj_t * self ) {
197
- return self -> picture_buffer ;
190
+ uint16_t common_hal_camera_get_width (camera_obj_t * self ) {
191
+ return self -> width ;
198
192
}
199
193
200
- size_t common_hal_camera_get_picture_size (camera_obj_t * self ) {
201
- return self -> picture_size ;
194
+ void common_hal_camera_set_width (camera_obj_t * self , uint16_t width ) {
195
+ self -> width = width ;
202
196
}
203
197
204
- camera_imagesize_t common_hal_camera_get_size (camera_obj_t * self ) {
205
- return self -> size ;
198
+ uint16_t common_hal_camera_get_height (camera_obj_t * self ) {
199
+ return self -> height ;
206
200
}
207
201
208
- void common_hal_camera_set_size (camera_obj_t * self , camera_imagesize_t size ) {
209
- uint16_t width , height ;
210
-
211
- camera_size_to_width_and_height (size , & width , & height );
212
-
213
- self -> buffer_size = (size_t )(width * height * 2 / JPG_COMPRESS_RATIO );;
214
- self -> buffer = m_realloc (self -> buffer , self -> buffer_size );
215
- if (self -> buffer == NULL ) {
216
- mp_raise_msg (& mp_type_MemoryError , translate ("Couldn't allocate picture buffer" ));
217
- }
218
- self -> picture_buffer = self -> buffer ;
219
- while ((uint32_t )self -> picture_buffer % SPRESENSE_CAMIMAGE_MEM_ALIGN != 0 ) {
220
- self -> picture_buffer ++ ;
221
- }
222
-
223
- camera_set_format (V4L2_BUF_TYPE_STILL_CAPTURE , V4L2_PIX_FMT_JPEG , width , height );
202
+ void common_hal_camera_set_height (camera_obj_t * self , uint16_t height ) {
203
+ self -> height = height ;
224
204
}
0 commit comments