26 Jan 2014
Linux has a relatively new (2.6.13, June 2005), easy-to-use interface to watch and monitor file operation: inotify. See the Linux Journal article also.
I plan to use it to see when new devices show up under /dev
:
#includestatic const char *progname = "ino"; static const char *inotify_mask_str(unsigned mask) { switch (mask) { case IN_CREATE: return "create"; case IN_DELETE: return "delete"; default: return "???"; } } int main() { int fd = inotify_init1(0); if (fd < 0) { fprintf(stderr, "%s: init failed\n", progname); exit(EXIT_FAILURE); } int wd = inotify_add_watch(fd, "/dev", IN_CREATE | IN_DELETE); if (wd < 0) { fprintf(stderr, "%s: add watch failed\n", progname); exit(EXIT_FAILURE); } while (true) { uint8_t buf[sizeof(struct inotify_event) + FILENAME_MAX + 1]; ssize_t ret = read(fd, &buf, sizeof(buf)); if (ret < 0) { if (errno == EINTR) continue; fprintf(stderr, "%s: read failed\n", progname); exit(EXIT_FAILURE); } size_t processed = 0; while (processed < ret - sizeof(struct inotify_event)) { struct inotify_event *iev = (struct inotify_event *) &buf[processed]; printf("%4zd:%08x %s %s\n", ret, iev->mask, inotify_mask_str(iev->mask), iev->name); processed += sizeof(struct inotify_event) + iev->len; } } close(wd); close(fd); return EXIT_SUCCESS; }
posted at: 15:31 | path: /programming | permanent link
Encoding image data to JPEG is straightforward: use libjpeg. However, if you care about runtime performance, things get a bit more complicated... Here are some observations on the task on a ARM Cortex-A8 CPU.
dct_method = JDCT_IFAST
.
# time ./cjpeg -dct int -q 70 test.ppm > /tmp/test.jpg real 0m 1.70s # time ./cjpeg -dct fast -q 70 test.ppm > /tmp/test.jpg real 0m 1.04s
in_color_space = JCS_YCbCr
to avoid extra effort.
raw_data_in = TRUE
is used. The raw interface requires rearranging input data, however.
-O2
).
struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); cinfo.image_width = w; cinfo.image_height = h; cinfo.input_components = 3; cinfo.in_color_space = JCS_YCbCr; // input color space jpeg_mem_dest(&cinfo, &outbuf, outbuf_size); jpeg_set_defaults(&cinfo); cinfo.dct_method = JDCT_IFAST; // DCT method // set up subsampling cinfo.raw_data_in = TRUE; cinfo.comp_info[0].h_samp_factor = 2; cinfo.comp_info[0].v_samp_factor = 2; cinfo.comp_info[1].h_samp_factor = 1; cinfo.comp_info[1].v_samp_factor = 1; cinfo.comp_info[2].h_samp_factor = 1; cinfo.comp_info[2].v_samp_factor = 1; jpeg_set_quality(&cinfo, 70, TRUE); jpeg_start_compress(&cinfo, TRUE); // allocate input data buffer JSAMPIMAGE data = malloc(sizeof(JSAMPARRAY) * cinfo.input_components); data[0] = malloc(sizeof(JSAMPROW) * (16 + 8 + 8)); data[1] = data[0] + 16; data[2] = data[0] + 16 + 8; // Y component data[0][0] = malloc(sizeof(JSAMPLE) * cinfo.image_width * 16); for (unsigned i = 1; i < 16; i++) data[0][i] = data[0][i-1] + cinfo.image_width; // U component data[1][0] = malloc(sizeof(JSAMPLE) * cinfo.image_width * 8 / 2); for (unsigned i = 1; i < 8; i++) data[1][i] = data[1][i-1] + cinfo.image_width / 2; // V component data[2][0] = malloc(sizeof(JSAMPLE) * cinfo.image_width * 8 / 2); for (unsigned i = 1; i < 8; i++) data[2][i] = data[2][i-1] + cinfo.image_width / 2; JSAMPLE *in = inbuf; for (unsigned i = 0; i < cinfo.image_height; i += 16) { JSAMPLE *yp = data[0][0], *up = data[1][0], *vp = data[2][0]; for (unsigned j = 0; j < 16; j += 2) { for (unsigned k = 0; k < cinfo.image_width * 2; k += 4) { *up++ = *in++; // assume UYVY *yp++ = *in++; *vp++ = *in++; *yp++ = *in++; } for (unsigned k = 0; k < cinfo.image_width * 2; k += 4) { in++; // subsample by dropping chroma data on odd lines *yp++ = *in++; in++; *yp++ = *in++; } } jpeg_write_raw_data(&cinfo, data, 16); } free(data[0][0]); free(data[1][0]); free(data[2][0]); free(data[0]); free(data); jpeg_finish_compress(&cinfo); jpeg_destroy_compress(&cinfo);
posted at: 15:19 | path: /programming | permanent link