Skip to content

Commit 88fa875

Browse files
committed
Address review comments
1 parent 6d73d06 commit 88fa875

File tree

5 files changed

+106
-116
lines changed

5 files changed

+106
-116
lines changed

camera.c

Lines changed: 61 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
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,113 @@ 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

213202
int 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;
233209

234-
fprintf(stderr, "Opening device: %s\n", video_device);
235-
ret = init_device(video_device, &fd, &driver_str);
210+
int width, height = 0;
211+
uint32_t format = 0;
212+
213+
struct v4l2_buffer buf_info = {0};
214+
215+
uint8_t *jpeg = NULL;
216+
217+
ret = camera_init_device(video_device, &fd, &driver_str);
236218
if (ret < 0)
237219
{
238-
cleanup();
239-
return -1;
220+
goto cleanup;
240221
}
241222

242-
int width, height;
243-
uint32_t format;
244-
ret = configure_format(fd, &width, &height, &format);
223+
ret = camera_configure_format(fd, &width, &height, &format);
245224
if (ret < 0)
246225
{
247-
cleanup();
248-
return -1;
226+
goto cleanup;
249227
}
250228

251229
fprintf(stderr, "Driver: %s, Resolution: %dx%d, Format: %c%c%c%c\n", driver_str, width, height,
252230
(char)((format >> 0) & 0xFF), (char)((format >> 8) & 0xFF), (char)((format >> 16) & 0xFF), (char)((format >> 24) & 0xFF));
253231
free(driver_str);
254232

255-
ret = request_buffer(fd);
233+
ret = camera_request_buffer(fd);
256234
if (ret < 0)
257235
{
258-
cleanup();
259-
return -1;
236+
goto cleanup;
260237
}
261238

262-
struct v4l2_buffer buf_info = {0};
263-
264-
ret = query_buffer(fd, &raw_buffer, &buf_info, &raw_size);
239+
ret = camera_query_buffer(fd, &raw_buffer, &buf_info);
265240
if (ret < 0)
266241
{
267-
cleanup();
268-
return -1;
242+
goto cleanup;
269243
}
270244

271-
capture_frame(fd, &buf_info);
245+
camera_capture_frame(fd, &buf_info);
272246

273-
uint8_t *jpeg = NULL;
274247
switch (format)
275248
{
276249
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);
250+
camera_yuyv_to_jpeg(&jpeg, size_ref, raw_buffer, width, height);
284251
break;
285-
}
286252

287253
default:
288254
fprintf(stderr, "Unsupported format\n");
289-
cleanup();
290-
return -1;
255+
ret = -1;
256+
goto cleanup;
291257
}
292258

293259
*buffer_ref = jpeg;
294260

295-
cleanup();
261+
cleanup:
262+
if (fd >= 0)
263+
{
264+
close(fd);
265+
}
266+
if (raw_buffer != NULL)
267+
{
268+
munmap(raw_buffer, buf_info.length);
269+
}
296270

297-
return 0;
271+
return ret;
298272
}

cdba-server.c

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,22 @@ static void capture_image(struct device *device)
118118
return;
119119
}
120120

121-
cdba_send_buf(MSG_CAPTURE_IMAGE, size, jpeg);
121+
const size_t chunk_size = 1024;
122+
size_t remaining_size = size;
123+
const uint8_t *ptr = jpeg;
124+
125+
while (remaining_size > 0) {
126+
size_t send_size = remaining_size > chunk_size ? chunk_size : remaining_size;
127+
128+
cdba_send_buf(MSG_CAPTURE_IMAGE, send_size, ptr);
129+
130+
ptr += send_size;
131+
remaining_size -= send_size;
132+
}
133+
134+
// Empty message to indicate end of image
135+
cdba_send_buf(MSG_CAPTURE_IMAGE, 0, NULL);
136+
122137
free(jpeg);
123138
}
124139

@@ -212,7 +227,7 @@ static int handle_stdin(int fd, void *buf)
212227
capture_image(selected_device);
213228
break;
214229
default:
215-
fprintf(stderr, "unk %d len %u\n", msg->type, msg->len);
230+
fprintf(stderr, "unk %d len %d\n", msg->type, msg->len);
216231
exit(1);
217232
}
218233

cdba.c

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -487,40 +487,41 @@ static void handle_console(const void *data, size_t len)
487487

488488
static void handle_image_capture(void *data, size_t len)
489489
{
490-
int fd;
491-
int ret;
492-
493-
const char *image_dir = "/tmp/cdba-images";
490+
static int fd = -1;
494491
const char *filename = "capture.jpg";
492+
int ret;
495493

496-
char image_path[PATH_MAX];
497-
ret = snprintf(image_path, PATH_MAX, "%s/%s", image_dir, filename);
498-
if (ret < 0)
494+
if (len == 0)
499495
{
500-
err(1, "failed to build image path");
501-
}
496+
// End of image
497+
if (fd >= 0)
498+
{
499+
close(fd);
500+
fd = -1;
502501

503-
ret = mkdir(image_dir, 0700);
504-
if (ret < 0 && errno != EEXIST)
505-
{
506-
err(1, "failed to create directory %s", image_dir);
502+
fprintf(stderr, "Saved captured image to %s\n", filename);
503+
}
504+
return;
507505
}
508506

509-
fd = open(image_path, O_CREAT | O_WRONLY | O_TRUNC, 0600);
510-
if (fd < 0)
511-
{
512-
err(1, "failed to open %s", filename);
507+
if (fd < 0) {
508+
// First chunk of image
509+
fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0666);
510+
if (fd < 0) {
511+
err(1, "Failed to open %s", filename);
512+
}
513513
}
514514

515-
ret = write(fd, data, len);
516-
if (ret != len)
515+
while (len > 0)
517516
{
518-
err(1, "failed to write image to %s", filename);
519-
}
520-
521-
printf("Saved captured image to %s\n", image_path);
517+
ret = write(fd, data, len);
518+
if (ret < 0) {
519+
err(1, "Failed to write to %s", filename);
520+
}
522521

523-
close(fd);
522+
data = (uint8_t *)data + ret;
523+
len -= ret;
524+
}
524525
}
525526

526527
static bool auto_power_on;
@@ -603,7 +604,7 @@ static int handle_message(struct circ_buf *buf)
603604
handle_image_capture(msg->data, msg->len);
604605
break;
605606
default:
606-
fprintf(stderr, "unk %d len %u\n", msg->type, msg->len);
607+
fprintf(stderr, "unk %d len %d\n", msg->type, msg->len);
607608
return -1;
608609
}
609610

cdba.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
struct msg {
1212
uint8_t type;
13-
uint32_t len;
13+
uint16_t len;
1414
uint8_t data[];
1515
} __packed;
1616

circ_buf.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
#define MIN(x, y) ((x) < (y) ? (x) : (y))
1414
#endif
1515

16-
#define CIRC_BUF_SIZE 524288
16+
#define CIRC_BUF_SIZE 16384
1717

1818
struct circ_buf {
1919
char buf[CIRC_BUF_SIZE];

0 commit comments

Comments
 (0)