summaryrefslogtreecommitdiffstats
path: root/exynos4/hal/libhwjpeg/jpeg_hal_unit.c
diff options
context:
space:
mode:
Diffstat (limited to 'exynos4/hal/libhwjpeg/jpeg_hal_unit.c')
-rw-r--r--exynos4/hal/libhwjpeg/jpeg_hal_unit.c572
1 files changed, 572 insertions, 0 deletions
diff --git a/exynos4/hal/libhwjpeg/jpeg_hal_unit.c b/exynos4/hal/libhwjpeg/jpeg_hal_unit.c
new file mode 100644
index 0000000..a0b4224
--- /dev/null
+++ b/exynos4/hal/libhwjpeg/jpeg_hal_unit.c
@@ -0,0 +1,572 @@
+/*
+ * Copyright@ Samsung Electronics Co. LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "libhwjpeg"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <string.h>
+#include <errno.h>
+#include <signal.h>
+#include <math.h>
+#include <sys/poll.h>
+
+#include <cutils/log.h>
+
+#include "jpeg_hal.h"
+
+#ifdef JPEG_PERF_MEAS
+unsigned long measure_time(struct timeval *start, struct timeval *stop)
+{
+ unsigned long sec, usec, time;
+
+ sec = stop->tv_sec - start->tv_sec;
+
+ if (stop->tv_usec >= start->tv_usec) {
+ usec = stop->tv_usec - start->tv_usec;
+ } else {
+ usec = stop->tv_usec + 1000000 - start->tv_usec;
+ sec--;
+ }
+
+ time = (sec * 1000000) + usec;
+
+ return time;
+}
+#endif
+
+static int jpeg_v4l2_querycap(int fd)
+{
+ struct v4l2_capability cap;
+ int ret = 0;
+
+ ret = ioctl(fd, VIDIOC_QUERYCAP, &cap);
+
+ if (!(cap.capabilities & V4L2_CAP_STREAMING))
+ LOGE("[%s]: does not support streaming", __func__);
+
+ if (!(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT))
+ LOGE("[%s]: does not support output", __func__);
+
+ if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE))
+ LOGE("[%s]: does not support capture", __func__);
+
+ return ret;
+}
+
+static int jpeg_v4l2_s_jpegcomp(int fd, int quality)
+{
+ struct v4l2_jpegcompression arg;
+ int ret = 0;
+
+ arg.quality = quality;
+
+ ret = ioctl(fd, VIDIOC_S_JPEGCOMP, &arg);
+
+ return ret;
+}
+
+static int jpeg_v4l2_s_fmt(int fd, enum v4l2_buf_type type, struct jpeg_config *config)
+{
+ struct v4l2_format fmt;
+ int ret = 0;
+
+ fmt.type = type;
+ fmt.fmt.pix_mp.width = config->width;
+ fmt.fmt.pix_mp.height = config->height;
+ fmt.fmt.pix_mp.field = V4L2_FIELD_ANY;
+ fmt.fmt.pix_mp.num_planes = config->num_planes;
+
+ if (config->mode == JPEG_ENCODE)
+ fmt.fmt.pix_mp.colorspace = V4L2_COLORSPACE_JPEG;
+
+ switch (fmt.type) {
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT: /* fall through */
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ break;
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+ if (config->mode == JPEG_ENCODE) {
+ fmt.fmt.pix_mp.pixelformat = config->pix.enc_fmt.in_fmt;
+ } else {
+ fmt.fmt.pix_mp.pixelformat = config->pix.dec_fmt.in_fmt;
+ fmt.fmt.pix_mp.plane_fmt[0].sizeimage = config->sizeJpeg;
+ }
+ break;
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+ if (config->mode == JPEG_ENCODE) {
+ fmt.fmt.pix_mp.pixelformat = config->pix.enc_fmt.out_fmt;
+ } else {
+ fmt.fmt.pix_mp.pixelformat = config->pix.dec_fmt.out_fmt;
+ fmt.fmt.pix_mp.width = config->scaled_width;
+ fmt.fmt.pix_mp.height = config->scaled_height;
+ }
+ break;
+ default:
+ LOGE("[%s]: invalid v4l2 buf type", __func__);
+ return -1;
+ }
+
+ ret = ioctl(fd, VIDIOC_S_FMT, &fmt);
+
+ return ret;
+}
+
+static int jpeg_v4l2_g_fmt(int fd, enum v4l2_buf_type type, struct jpeg_config *config)
+{
+ struct v4l2_format fmt;
+ int ret = 0;
+
+ fmt.type = type;
+ ret = ioctl(fd, VIDIOC_G_FMT, &fmt);
+ if (ret < 0)
+ return -1;
+
+ config->width = fmt.fmt.pix_mp.width;
+ config->height = fmt.fmt.pix_mp.height;
+
+ switch (fmt.type) {
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT: /* fall through */
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ break;
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+ if (config->mode == JPEG_ENCODE)
+ config->pix.enc_fmt.in_fmt = fmt.fmt.pix_mp.pixelformat;
+ else
+ config->pix.dec_fmt.in_fmt = fmt.fmt.pix_mp.pixelformat;
+ break;
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+ if (config->mode == JPEG_ENCODE)
+ config->pix.enc_fmt.out_fmt = fmt.fmt.pix_mp.pixelformat;
+ else
+ config->pix.dec_fmt.out_fmt = fmt.fmt.pix_mp.pixelformat;
+ break;
+ default:
+ LOGE("[%s]: invalid v4l2 buf type", __func__);
+ return -1;
+ }
+
+ return ret;
+}
+
+int jpeghal_getconfig(int fd, struct jpeg_config *config)
+{
+ int ret = 0;
+
+ ret = jpeg_v4l2_g_fmt(fd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, config);
+ if (ret < 0) {
+ LOGE("[%s]: input G_FMT failed", __func__);
+ return -1;
+ }
+
+ ret = jpeg_v4l2_g_fmt(fd, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, config);
+ if (ret < 0)
+ LOGE("[%s]: output G_FMT failed", __func__);
+
+ return ret;
+}
+
+static int jpeg_v4l2_reqbufs(int fd, int buf_cnt, struct jpeg_buf *buf)
+{
+ struct v4l2_requestbuffers req;
+ int ret = 0;
+
+ memset(&req, 0, sizeof(req));
+
+ req.type = buf->buf_type;
+ req.memory = buf->memory;
+
+ req.count = buf_cnt;
+
+ ret = ioctl(fd, VIDIOC_REQBUFS, &req);
+
+ return ret;
+}
+
+static int jpeg_v4l2_querybuf(int fd, struct jpeg_buf *buf)
+{
+ struct v4l2_buffer v4l2_buf;
+ struct v4l2_plane plane[JPEG_MAX_PLANE_CNT];
+ int i;
+ int ret = 0;
+
+ memset(plane, 0, (int)JPEG_MAX_PLANE_CNT * sizeof(struct v4l2_plane));
+
+ v4l2_buf.index = 0;
+ v4l2_buf.type = buf->buf_type;
+ v4l2_buf.memory = buf->memory;
+ v4l2_buf.length = buf->num_planes;
+ v4l2_buf.m.planes = plane;
+
+ ret = ioctl(fd, VIDIOC_QUERYBUF, &v4l2_buf);
+ if (ret < 0) {
+ LOGE("[%s:%d]: VIDIOC_QUERYBUF failed", __func__, ret);
+ return ret;
+ }
+
+ for (i= 0; i < buf->num_planes; i++) {
+ buf->length[i] = v4l2_buf.m.planes[i].length;
+ buf->start[i] = (char *) mmap(0, buf->length[i],
+ PROT_READ | PROT_WRITE, MAP_SHARED, fd,
+ v4l2_buf.m.planes[i].m.mem_offset);
+
+ //LOGI("[%s]: buf.start[%d] = %p, length = %d", __func__, 0, buf->start[0], buf->length[0]);
+ if (buf->start[0] == MAP_FAILED) {
+ LOGE("[%s]: mmap failed", __func__);
+ return -1;
+ }
+ }
+
+ return ret;
+}
+
+static int jpeg_v4l2_qbuf(int fd, struct jpeg_buf *buf)
+{
+ struct v4l2_buffer v4l2_buf;
+ struct v4l2_plane plane[JPEG_MAX_PLANE_CNT];
+ int i;
+ int ret = 0;
+
+ memset(&v4l2_buf, 0, sizeof(struct v4l2_buffer));
+ memset(plane, 0, (int)JPEG_MAX_PLANE_CNT * sizeof(struct v4l2_plane));
+
+ v4l2_buf.index = 0;
+ v4l2_buf.type = buf->buf_type;
+ v4l2_buf.memory = buf->memory;
+ v4l2_buf.length = buf->num_planes;
+ v4l2_buf.m.planes = plane;
+
+ if (buf->memory == V4L2_MEMORY_USERPTR) {
+ for (i = 0; i < buf->num_planes; i++) {
+ v4l2_buf.m.planes[i].m.userptr = (unsigned long)buf->start[i];
+ v4l2_buf.m.planes[i].length = buf->length[i];
+ }
+ }
+
+ ret = ioctl(fd, VIDIOC_QBUF, &v4l2_buf);
+ if (ret < 0) {
+ LOGE("[%s:%d] QBUF failed", __func__, ret);
+ return -1;
+ }
+
+ return ret;
+}
+
+static int jpeg_v4l2_dqbuf(int fd, enum v4l2_buf_type type, enum v4l2_memory memory)
+{
+ struct v4l2_buffer buf;
+ int ret = 0;
+
+ memset(&buf, 0, sizeof(struct v4l2_buffer));
+
+ buf.type = type;
+ buf.memory = memory;
+
+ ret = ioctl(fd, VIDIOC_DQBUF, &buf);
+ if (ret < 0) {
+ LOGE("[%s:%d] DQBUF failed", __func__, ret);
+ return -1;
+ }
+
+ return ret;
+}
+
+static int jpeg_v4l2_streamon(int fd, enum v4l2_buf_type type)
+{
+ int ret = 0;
+
+ ret = ioctl(fd, VIDIOC_STREAMON, &type);
+ if (ret < 0) {
+ LOGE("[%s:%d] STREAMON failed", __func__, ret);
+ return -1;
+ }
+
+ return ret;
+}
+
+static int jpeg_v4l2_streamoff(int fd, enum v4l2_buf_type type)
+{
+ int ret = 0;
+
+ ret = ioctl(fd, VIDIOC_STREAMOFF, &type);
+ if (ret < 0) {
+ LOGE("[%s:%d] STREAMOFF failed", __func__, ret);
+ return -1;
+ }
+
+ return ret;
+}
+
+int jpeghal_dec_init()
+{
+ int fd;
+ int ret = 0;
+
+ fd = open(JPEG_DEC_NODE, O_RDWR, 0);
+
+ if (fd < 0) {
+ LOGE("[%s]: JPEG dec open failed", __func__);
+ return -1;
+ }
+
+ ret = jpeg_v4l2_querycap(fd);
+ if (ret < 0) {
+ LOGE("[%s]: QUERYCAP failed", __func__);
+ return -1;
+ }
+
+ return fd;
+}
+
+int jpeghal_enc_init()
+{
+ int fd;
+ int ret = 0;
+
+ fd = open(JPEG_ENC_NODE, O_RDWR, 0);
+ if (fd < 0) {
+ LOGE("[%s]: JPEG enc open failed", __func__);
+ return -1;
+ }
+
+ ret = jpeg_v4l2_querycap(fd);
+ if (ret < 0) {
+ LOGE("[%s]: QUERYCAP failed", __func__);
+ return -1;
+ }
+
+ return fd;
+}
+
+int jpeghal_dec_setconfig(int fd, struct jpeg_config *config)
+{
+ int ret = 0;
+
+ config->mode = JPEG_DECODE;
+
+ ret = jpeg_v4l2_s_fmt(fd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, config);
+ if (ret < 0) {
+ LOGE("[%s]: decoder input S_FMT failed", __func__);
+ return -1;
+ }
+
+ ret = jpeg_v4l2_s_fmt(fd, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, config);
+ if (ret < 0) {
+ LOGE("[%s]: decoder output S_FMT failed", __func__);
+ return -1;
+ }
+
+ return ret;
+}
+
+int jpeghal_dec_getconfig(int fd, struct jpeg_config *config)
+{
+ int ret = 0;
+
+ jpeghal_getconfig(fd, config);
+
+ return ret;
+}
+
+int jpeghal_enc_setconfig(int fd, struct jpeg_config *config)
+{
+ int ret = 0;
+
+ ret = jpeg_v4l2_s_jpegcomp(fd, config->enc_qual);
+ if (ret < 0) {
+ LOGE("[%s]: S_JPEGCOMP failed", __func__);
+ return -1;
+ }
+
+ config->mode = JPEG_ENCODE;
+
+ ret = jpeg_v4l2_s_fmt(fd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, config);
+ if (ret < 0) {
+ LOGE("[%s]: encoder input S_FMT failed", __func__);
+ return -1;
+ }
+
+ ret = jpeg_v4l2_s_fmt(fd, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, config);
+ if (ret < 0) {
+ LOGE("[%s]: encoder output S_FMT failed", __func__);
+ return -1;
+ }
+
+ return ret;
+}
+
+int jpeghal_enc_getconfig(int fd, struct jpeg_config *config)
+{
+ int ret = 0;
+
+ jpeghal_getconfig(fd, config);
+
+ return ret;
+}
+
+int jpeghal_set_inbuf(int fd, struct jpeg_buf *buf)
+{
+ int ret = 0;
+
+ buf->buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+
+ ret = jpeg_v4l2_reqbufs(fd, 1, buf);
+ if (ret < 0) {
+ LOGE("[%s:%d]: Input REQBUFS failed", __func__, ret);
+ return -1;
+ }
+
+ if (buf->memory == V4L2_MEMORY_MMAP) {
+ ret = jpeg_v4l2_querybuf(fd, buf);
+ if (ret < 0) {
+ LOGE("[%s:%d]: Input QUERYBUF failed", __func__, ret);
+ return -1;
+ }
+ }
+
+ return ret;
+}
+
+int jpeghal_set_outbuf(int fd, struct jpeg_buf *buf)
+{
+ int ret = 0;
+
+ buf->buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+
+ ret = jpeg_v4l2_reqbufs(fd, 1, buf);
+ if (ret < 0) {
+ LOGE("[%s:%d]: Output REQBUFS failed", __func__, ret);
+ return -1;
+ }
+
+ if (buf->memory == V4L2_MEMORY_MMAP) {
+ ret = jpeg_v4l2_querybuf(fd, buf);
+ if (ret < 0) {
+ LOGE("[%s:%d]: Output QUERYBUF failed", __func__, ret);
+ return -1;
+ }
+ }
+
+ return ret;
+}
+
+static int jpeg_exe(int fd, struct jpeg_buf *in_buf, struct jpeg_buf *out_buf)
+{
+ int ret = 0;
+
+ ret = jpeg_v4l2_qbuf(fd, in_buf);
+ if (ret < 0) {
+ LOGE("[%s:%d]: Input QBUF failed", __func__, ret);
+ return -1;
+ }
+
+ ret = jpeg_v4l2_qbuf(fd, out_buf);
+ if (ret < 0) {
+ LOGE("[%s:%d]: Output QBUF failed", __func__, ret);
+ return -1;
+ }
+
+ ret = jpeg_v4l2_streamon(fd, in_buf->buf_type);
+ ret = jpeg_v4l2_streamon(fd, out_buf->buf_type);
+
+ ret = jpeg_v4l2_dqbuf(fd, in_buf->buf_type, in_buf->memory);
+ ret = jpeg_v4l2_dqbuf(fd, out_buf->buf_type, out_buf->memory);
+
+ return ret;
+}
+
+int jpeghal_dec_exe(int fd, struct jpeg_buf *in_buf, struct jpeg_buf *out_buf)
+{
+ int ret = 0;
+
+ ret = jpeg_exe(fd, in_buf, out_buf);
+ if (ret < 0)
+ LOGE("[%s]: JPEG decoding is failed", __func__);
+
+ return ret;
+}
+
+int jpeghal_enc_exe(int fd, struct jpeg_buf *in_buf, struct jpeg_buf *out_buf)
+{
+ int ret = 0;
+
+ ret = jpeg_exe(fd, in_buf, out_buf);
+ if (ret < 0)
+ LOGE("[%s]: JPEG Encoding is failed", __func__);
+
+ return ret;
+}
+
+int jpeghal_deinit(int fd, struct jpeg_buf *in_buf, struct jpeg_buf *out_buf)
+{
+ int ret = 0;
+
+ jpeg_v4l2_streamoff(fd, in_buf->buf_type);
+ jpeg_v4l2_streamoff(fd, out_buf->buf_type);
+
+ if (in_buf->memory == V4L2_MEMORY_MMAP)
+ munmap((char *)(in_buf->start[0]), in_buf->length[0]);
+
+ if (out_buf->memory == V4L2_MEMORY_MMAP)
+ munmap((char *)(out_buf->start[0]), out_buf->length[0]);
+
+ jpeg_v4l2_reqbufs(fd, 0, in_buf);
+
+ jpeg_v4l2_reqbufs(fd, 0, out_buf);
+
+ ret = close(fd);
+
+ return ret;
+}
+
+int jpeghal_s_ctrl(int fd, int cid, int value)
+{
+ struct v4l2_control vc;
+ int ret = 0;
+
+ vc.id = cid;
+ vc.value = value;
+
+ ret = ioctl(fd, VIDIOC_S_CTRL, &vc);
+ if (ret != 0) {
+ LOGE("[%s] ioctl : cid(%d), value(%d)\n", __func__, cid, value);
+ return -1;
+ }
+
+ return ret;
+}
+
+int jpeghal_g_ctrl(int fd, int id)
+{
+ struct v4l2_control ctrl;
+ int ret = 0;
+
+ ctrl.id = id;
+
+ ret = ioctl(fd, VIDIOC_G_CTRL, &ctrl);
+ if (ret < 0) {
+ LOGE("[%s] ioctl : cid(%d)\n", __func__, ctrl.id);
+ return -1;
+ }
+
+ return ctrl.value;
+}