3535
3636#include "shared-bindings/camera/Camera.h"
3737
38- #define JPG_COMPRESS_RATIO (9)
39- #define SPRESENSE_CAMIMAGE_MEM_ALIGN (32)
40-
4138typedef struct {
4239 const char * devpath ;
4340 int fd ;
4441} camera_dev_t ;
4542
4643STATIC camera_dev_t camera_dev = {"/dev/video" , -1 };
4744
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;
8175 }
8276}
8377
@@ -118,7 +112,9 @@ static void camera_start_preview() {
118112 camera_start_streaming (V4L2_BUF_TYPE_VIDEO_CAPTURE );
119113}
120114
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 ) {
122118 if (camera_dev .fd < 0 ) {
123119 if (video_initialize (camera_dev .devpath ) < 0 ) {
124120 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) {
129125 }
130126 }
131127
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" ));
149130 }
150131
132+ self -> width = width ;
133+ self -> height = height ;
134+
151135 camera_start_preview ();
152136
153137 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) {
164148
165149 video_uninitialize ();
166150
167- m_free (self -> buffer );
168-
169151 close (camera_dev .fd );
170152 camera_dev .fd = -1 ;
171153}
@@ -174,14 +156,26 @@ bool common_hal_camera_deinited(camera_obj_t *self) {
174156 return camera_dev .fd < 0 ;
175157}
176158
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+
178172 v4l2_buffer_t buf ;
179173
180174 memset (& buf , 0 , sizeof (v4l2_buffer_t ));
181175 buf .type = V4L2_BUF_TYPE_STILL_CAPTURE ;
182176 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 ;
185179 ioctl (camera_dev .fd , VIDIOC_QBUF , (unsigned long )& buf );
186180
187181 ioctl (camera_dev .fd , VIDIOC_TAKEPICT_START , 0 );
@@ -190,35 +184,21 @@ void common_hal_camera_take_picture(camera_obj_t *self) {
190184
191185 ioctl (camera_dev .fd , VIDIOC_TAKEPICT_STOP , false);
192186
193- self -> picture_size = (size_t )buf .bytesused ;
187+ return (size_t )buf .bytesused ;
194188}
195189
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 ;
198192}
199193
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 ;
202196}
203197
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 ;
206200}
207201
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 ;
224204}
0 commit comments