void v4lconvert_destroy(struct v4lconvert_data *data) { v4lprocessing_destroy(data->processing); v4lcontrol_destroy(data->control); if (data->jdec) { unsigned char *comps[3] = { NULL, NULL, NULL }; tinyjpeg_set_components(data->jdec, comps, 3); tinyjpeg_free(data->jdec); } v4lconvert_helper_cleanup(data); free(data->convert1_buf); free(data->convert2_buf); free(data->rotate90_buf); free(data->flip_buf); free(data->convert_pixfmt_buf); free(data); }
void v4lconvert_destroy(struct v4lconvert_data *data) { v4lprocessing_destroy(data->processing); v4lcontrol_destroy(data->control); if (data->tinyjpeg) { unsigned char *comps[3] = { NULL, NULL, NULL }; tinyjpeg_set_components(data->tinyjpeg, comps, 3); tinyjpeg_free(data->tinyjpeg); } if (data->cinfo_initialized) jpeg_destroy_decompress(&data->cinfo); v4lconvert_helper_cleanup(data); free(data->convert1_buf); free(data->convert2_buf); free(data->rotate90_buf); free(data->flip_buf); free(data->convert_pixfmt_buf); free(data->previous_frame); free(data); }
struct v4lconvert_data *v4lconvert_create(int fd) { int i, j; struct v4lconvert_data *data = calloc(1, sizeof(struct v4lconvert_data)); struct v4l2_capability cap; /* This keeps tracks of devices which have only formats for which apps most likely will need conversion and we can thus safely add software processing controls without a performance impact. */ int always_needs_conversion = 1; if (!data) { fprintf(stderr, "libv4lconvert: error: out of memory!\n"); return NULL; } data->fd = fd; data->decompress_pid = -1; data->fps = 30; /* Check supported formats */ for (i = 0; ; i++) { struct v4l2_fmtdesc fmt = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE }; fmt.index = i; if (SYS_IOCTL(data->fd, VIDIOC_ENUM_FMT, &fmt)) break; for (j = 0; j < ARRAY_SIZE(supported_src_pixfmts); j++) if (fmt.pixelformat == supported_src_pixfmts[j].fmt) break; if (j < ARRAY_SIZE(supported_src_pixfmts)) { data->supported_src_formats |= 1 << j; v4lconvert_get_framesizes(data, fmt.pixelformat, j); if (!supported_src_pixfmts[j].needs_conversion) always_needs_conversion = 0; } else always_needs_conversion = 0; } data->no_formats = i; /* Check if this cam has any special flags */ if (SYS_IOCTL(data->fd, VIDIOC_QUERYCAP, &cap) == 0) { if (!strcmp((char *)cap.driver, "uvcvideo")) data->flags |= V4LCONVERT_IS_UVC; if ((cap.capabilities & 0xff) & ~V4L2_CAP_VIDEO_CAPTURE) always_needs_conversion = 0; } data->control = v4lcontrol_create(fd, always_needs_conversion); if (!data->control) { free(data); return NULL; } data->bandwidth = v4lcontrol_get_bandwidth(data->control); data->control_flags = v4lcontrol_get_flags(data->control); if (data->control_flags & V4LCONTROL_FORCE_TINYJPEG) data->flags |= V4LCONVERT_USE_TINYJPEG; data->processing = v4lprocessing_create(fd, data->control); if (!data->processing) { v4lcontrol_destroy(data->control); free(data); return NULL; } return data; }