2121#include "camera.h"
2222#include "device.h"
2323
24- int init_device (const char * dev_name , int * fd_ref , char * * driver_ref )
24+ static int camera_init_device (const char * dev_name , int * fd_ref , char * * driver_ref )
2525{
2626 * fd_ref = open (dev_name , O_RDWR );
2727 if (* fd_ref < 0 )
@@ -43,7 +43,7 @@ int init_device(const char *dev_name, int *fd_ref, char **driver_ref)
4343 return 0 ;
4444}
4545
46- int configure_format (const int fd , int * width_ref , int * height_ref , uint32_t * format_ref )
46+ static int camera_configure_format (const int fd , int * width_ref , int * height_ref , uint32_t * format_ref )
4747{
4848 struct v4l2_format fmt = {0 };
4949 fmt .type = V4L2_BUF_TYPE_VIDEO_CAPTURE ;
@@ -80,7 +80,7 @@ int configure_format(const int fd, int *width_ref, int *height_ref, uint32_t *fo
8080 return 0 ;
8181}
8282
83- int request_buffer (const int fd )
83+ static int camera_request_buffer (const int fd )
8484{
8585 struct v4l2_requestbuffers reqbuf = {0 };
8686 reqbuf .count = 1 ;
@@ -96,7 +96,7 @@ int request_buffer(const int fd)
9696 return 0 ;
9797}
9898
99- int query_buffer (const int fd , uint8_t * * buf_ref , struct v4l2_buffer * buf_info_ref , int * size_ref )
99+ static int camera_query_buffer (const int fd , uint8_t * * buf_ref , struct v4l2_buffer * buf_info_ref )
100100{
101101 buf_info_ref -> type = V4L2_BUF_TYPE_VIDEO_CAPTURE ;
102102 buf_info_ref -> memory = V4L2_MEMORY_MMAP ;
@@ -115,12 +115,10 @@ int query_buffer(const int fd, uint8_t **buf_ref, struct v4l2_buffer *buf_info_r
115115 return -1 ;
116116 }
117117
118- * size_ref = buf_info_ref -> length ;
119-
120118 return 0 ;
121119}
122120
123- int capture_frame (const int fd , struct v4l2_buffer * buf_info )
121+ static int camera_capture_frame (const int fd , struct v4l2_buffer * buf_info )
124122{
125123 if (ioctl (fd , VIDIOC_QBUF , buf_info ))
126124 {
@@ -147,41 +145,12 @@ int capture_frame(const int fd, struct v4l2_buffer *buf_info)
147145 return 0 ;
148146}
149147
150- void yuyv_to_rgb (uint8_t * rgb_ref , const uint8_t * yuyv , const int width , const int height )
151- {
152- int frame_size = width * height * 2 ;
153-
154- for (int i = 0 , j = 0 ; i < frame_size ; i += 4 , j += 6 )
155- {
156- int Y0 = yuyv [i ];
157- int U = yuyv [i + 1 ] - 128 ;
158- int Y1 = yuyv [i + 2 ];
159- int V = yuyv [i + 3 ] - 128 ;
160-
161- int R1 = Y0 + 1.140 * V ;
162- int G1 = Y0 - 0.395 * U - 0.581 * V ;
163- int B1 = Y0 + 2.032 * U ;
164-
165- int R2 = Y1 + 1.140 * V ;
166- int G2 = Y1 - 0.395 * U - 0.581 * V ;
167- int B2 = Y1 + 2.032 * U ;
168-
169- rgb_ref [j + 0 ] = (uint8_t )(R1 < 0 ? 0 : (R1 > 255 ? 255 : R1 ));
170- rgb_ref [j + 1 ] = (uint8_t )(G1 < 0 ? 0 : (G1 > 255 ? 255 : G1 ));
171- rgb_ref [j + 2 ] = (uint8_t )(B1 < 0 ? 0 : (B1 > 255 ? 255 : B1 ));
172- rgb_ref [j + 3 ] = (uint8_t )(R2 < 0 ? 0 : (R2 > 255 ? 255 : R2 ));
173- rgb_ref [j + 4 ] = (uint8_t )(G2 < 0 ? 0 : (G2 > 255 ? 255 : G2 ));
174- rgb_ref [j + 5 ] = (uint8_t )(B2 < 0 ? 0 : (B2 > 255 ? 255 : B2 ));
175- }
176- }
177-
178- void rgb_to_jpeg (uint8_t * * jpeg_ref , unsigned long * size_ref , const uint8_t * rgb , const int width , const int height )
148+ static int camera_yuyv_to_jpeg (uint8_t * * jpeg_ref , unsigned long * size_ref , const uint8_t * yuyv , const int width , const int height )
179149{
180150 struct jpeg_compress_struct cinfo ;
181151 struct jpeg_error_mgr jerr ;
182152
183153 JSAMPROW row_pointer [1 ];
184- int row_stride ;
185154
186155 cinfo .err = jpeg_std_error (& jerr );
187156 jpeg_create_compress (& cinfo );
@@ -191,108 +160,116 @@ void rgb_to_jpeg(uint8_t **jpeg_ref, unsigned long *size_ref, const uint8_t *rgb
191160 cinfo .image_width = width ;
192161 cinfo .image_height = height ;
193162 cinfo .input_components = 3 ;
194- cinfo .in_color_space = JCS_RGB ;
163+ cinfo .in_color_space = JCS_YCbCr ;
195164
196165 jpeg_set_defaults (& cinfo );
197- jpeg_set_quality (& cinfo , 75 , TRUE);
166+ jpeg_set_quality (& cinfo , 100 , TRUE);
198167
199168 jpeg_start_compress (& cinfo , TRUE);
200169
201- row_stride = width * 3 ;
170+ uint8_t * row_buffer = (uint8_t * )malloc (width * 3 * sizeof (uint8_t ));
171+ if (!row_buffer )
172+ {
173+ fprintf (stderr , "Memory allocation failed\n" );
174+ jpeg_destroy_compress (& cinfo );
175+ return -1 ;
176+ }
202177
203- while (cinfo .next_scanline < cinfo . image_height )
178+ while (cinfo .next_scanline < height )
204179 {
205- row_pointer [0 ] = (JSAMPROW )& rgb [cinfo .next_scanline * row_stride ];
180+ const uint32_t offset = cinfo .next_scanline * width * 2 ;
181+ for (uint32_t i = 0 , j = 0 ; i < width * 2 ; i += 4 , j += 6 )
182+ {
183+ row_buffer [j + 0 ] = yuyv [offset + i + 0 ];
184+ row_buffer [j + 1 ] = yuyv [offset + i + 1 ];
185+ row_buffer [j + 2 ] = yuyv [offset + i + 3 ];
186+ row_buffer [j + 3 ] = yuyv [offset + i + 2 ];
187+ row_buffer [j + 4 ] = yuyv [offset + i + 1 ];
188+ row_buffer [j + 5 ] = yuyv [offset + i + 3 ];
189+ }
190+ row_pointer [0 ] = row_buffer ;
206191 jpeg_write_scanlines (& cinfo , row_pointer , 1 );
207192 }
208193
209194 jpeg_finish_compress (& cinfo );
210195 jpeg_destroy_compress (& cinfo );
196+
197+ free (row_buffer );
198+
199+ return 0 ;
211200}
212201
213202int camera_capture_jpeg (uint8_t * * buffer_ref , unsigned long * size_ref , const char * video_device )
214203{
215204 int fd = -1 ;
216205 uint8_t * raw_buffer = NULL ;
217- int raw_size = 0 ;
218-
219- void cleanup ()
220- {
221- if (fd >= 0 )
222- {
223- close (fd );
224- }
225- if (raw_buffer != NULL )
226- {
227- munmap (raw_buffer , raw_size );
228- }
229- }
230206
231207 int ret = 0 ;
232- char * driver_str ;
208+ char * driver_str = NULL ;
209+
210+ int width , height = 0 ;
211+ uint32_t format = 0 ;
233212
234- fprintf (stderr , "Opening device: %s\n" , video_device );
235- ret = init_device (video_device , & fd , & driver_str );
213+ struct v4l2_buffer buf_info = {0 };
214+
215+ uint8_t * jpeg = NULL ;
216+
217+
218+ ret = camera_init_device (video_device , & fd , & driver_str );
236219 if (ret < 0 )
237220 {
238- cleanup ();
239- return -1 ;
221+ goto cleanup ;
240222 }
241223
242- int width , height ;
243- uint32_t format ;
244- ret = configure_format (fd , & width , & height , & format );
224+
225+ ret = camera_configure_format (fd , & width , & height , & format );
245226 if (ret < 0 )
246227 {
247- cleanup ();
248- return -1 ;
228+ goto cleanup ;
249229 }
250230
251231 fprintf (stderr , "Driver: %s, Resolution: %dx%d, Format: %c%c%c%c\n" , driver_str , width , height ,
252232 (char )((format >> 0 ) & 0xFF ), (char )((format >> 8 ) & 0xFF ), (char )((format >> 16 ) & 0xFF ), (char )((format >> 24 ) & 0xFF ));
253233 free (driver_str );
254234
255- ret = request_buffer (fd );
235+ ret = camera_request_buffer (fd );
256236 if (ret < 0 )
257237 {
258- cleanup ();
259- return -1 ;
238+ goto cleanup ;
260239 }
261240
262- struct v4l2_buffer buf_info = {0 };
263-
264- ret = query_buffer (fd , & raw_buffer , & buf_info , & raw_size );
241+ ret = camera_query_buffer (fd , & raw_buffer , & buf_info );
265242 if (ret < 0 )
266243 {
267- cleanup ();
268- return -1 ;
244+ goto cleanup ;
269245 }
270246
271- capture_frame (fd , & buf_info );
247+ camera_capture_frame (fd , & buf_info );
248+
272249
273- uint8_t * jpeg = NULL ;
274250 switch (format )
275251 {
276252 case V4L2_PIX_FMT_YUYV :
277- {
278- uint8_t * rgb = (uint8_t * )malloc (width * height * 3 );
279-
280- yuyv_to_rgb (rgb , raw_buffer , width , height );
281- rgb_to_jpeg (& jpeg , size_ref , rgb , width , height );
282-
283- free (rgb );
253+ camera_yuyv_to_jpeg (& jpeg , size_ref , raw_buffer , width , height );
284254 break ;
285- }
286255
287256 default :
288257 fprintf (stderr , "Unsupported format\n" );
289- cleanup () ;
290- return -1 ;
258+ ret = -1 ;
259+ goto cleanup ;
291260 }
292261
293262 * buffer_ref = jpeg ;
294263
295- cleanup ();
264+ cleanup :
265+ if (fd >= 0 )
266+ {
267+ close (fd );
268+ }
269+ if (raw_buffer != NULL )
270+ {
271+ munmap (raw_buffer , buf_info .length );
272+ }
296273
297- return 0 ;
274+ return ret ;
298275}
0 commit comments