pmeerw's blog
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