From 8b8182da6e16dfd0820ef2418c1bb66d4bcc8079 Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Mon, 2 Jul 2012 10:50:47 +0200 Subject: v4l-mfc-encoder: version 0.1 Signed-off-by: Andrzej Hajda Signed-off-by: Kamil Debski --- v4l2-mfc-encoder/mfc.c | 187 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 187 insertions(+) create mode 100644 v4l2-mfc-encoder/mfc.c (limited to 'v4l2-mfc-encoder/mfc.c') diff --git a/v4l2-mfc-encoder/mfc.c b/v4l2-mfc-encoder/mfc.c new file mode 100644 index 0000000..573ee8a --- /dev/null +++ b/v4l2-mfc-encoder/mfc.c @@ -0,0 +1,187 @@ +/* + * mfc codec encoding example application + * Andrzej Hajda + * + * MFC device. + * + * Copyright 2012 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. + * + */ + +#include +#include +#include + +#include "common.h" +#include "mfc.h" +#include "v4l_dev.h" + +#define MAX_STREAM_SIZE (2*1024*1024) + +int align(int x, int a) +{ + return ((x + a - 1) / a) * a; +} + +/* runs v4l_deq_buf and correct ending conditions + according to MFC driver */ +int mfc_deq_buf(struct io_dev *dev, enum io_dir dir) +{ + int idx; + + idx = v4l_deq_buf(dev, dir); + + if (dir == DIR_IN && dev->io[DIR_IN].state == FS_END + && dev->io[DIR_OUT].limit) + dev->io[DIR_OUT].limit = 0; + + return idx; +} + +struct io_dev_ops mfc_dev_ops = { .req_bufs = v4l_req_bufs, + .enq_buf = v4l_enq_buf, + .deq_buf = mfc_deq_buf, + .deq_event = v4l_deq_event, + .destroy = v4l_destroy + }; + +struct io_dev *mfc_create(char const *name) +{ + struct io_dev *dev; + int ret; + + dev = malloc(sizeof(*dev)); + memzero(*dev); + + dev->ops = &mfc_dev_ops; + + dev->io[DIR_IN].type = IO_MMAP; + dev->io[DIR_OUT].type = IO_MMAP; + + dev->fd = open(name, O_RDWR, 0); + if (dev->fd < 0) { + err("Cannot open MFC device %s", name); + free(dev); + return NULL; + } + + struct v4l2_event_subscription ev_sub; + memzero(ev_sub); + ev_sub.type = V4L2_EVENT_EOS; + ret = ioctl(dev->fd, VIDIOC_SUBSCRIBE_EVENT, &ev_sub); + if (ret != 0) + err("Cannot subscribe EOS event for MFC"); + + dbg("MFC device %s opened with fd=%d", name, dev->fd); + + return dev; +} + +int mfc_set_codec(struct io_dev *dev, enum io_dir dir, int codec) +{ + struct v4l2_format fmt; + int ret; + + memzero(fmt); + fmt.type = io_dir_to_type(dir); + fmt.fmt.pix_mp.pixelformat = codec; + fmt.fmt.pix_mp.plane_fmt[0].sizeimage = MAX_STREAM_SIZE; + + ret = ioctl(dev->fd, VIDIOC_S_FMT, &fmt); + + return ret; +} + +/* set format with proper alignement */ +int mfc_set_fmt(struct io_dev *dev, enum io_dir dir, int width, int height) +{ + struct v4l2_format fmt; + int ret; + + memzero(fmt); + fmt.type = io_dir_to_type(dir); + fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12M; + fmt.fmt.pix_mp.width = width; + fmt.fmt.pix_mp.height = height; + + fmt.fmt.pix_mp.num_planes = 2; + fmt.fmt.pix_mp.plane_fmt[0].bytesperline = align(width, 128); + fmt.fmt.pix_mp.plane_fmt[0].sizeimage = align(width * height, 2048); + fmt.fmt.pix_mp.plane_fmt[1].bytesperline = align(width, 128); + fmt.fmt.pix_mp.plane_fmt[1].sizeimage = align(width * (height / 2), + 2048); + + ret = ioctl(dev->fd, VIDIOC_S_FMT, &fmt); + if (ret != 0) + err("Cannot set format on %d:%d", dev->fd, dir); + + return ret; +} + +int mfc_set_rate(struct io_dev *dev, int rate) +{ + struct v4l2_streamparm fps; + int ret; + + fps.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + fps.parm.output.timeperframe.numerator = 1000; + fps.parm.output.timeperframe.denominator = rate; + + ret = ioctl(dev->fd, VIDIOC_S_PARM, &fps); + if (ret != 0) + err("Cannot set rate on %d", dev->fd); + + return ret; +} + +int mfc_set_mpeg_control(struct io_dev *dev, int id, int value) +{ + struct v4l2_ext_control ctrl; + struct v4l2_ext_controls ctrls; + int ret; + + ctrl.id = id; + ctrl.value = value; + + ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG; + ctrls.count = 1; + ctrls.controls = &ctrl; + + ret = ioctl(dev->fd, VIDIOC_S_EXT_CTRLS, &ctrls); + if (ret < 0) + err("Cannot set control %d to %d on %d", id, value, dev->fd); + + return ret; +} + +int mfc_set_bitrate(struct io_dev *dev, int bitrate) +{ + struct v4l2_ext_control ctrl; + struct v4l2_ext_controls ctrls; + int ret; + + ctrl.id = V4L2_CID_MPEG_VIDEO_BITRATE; + ctrl.value = bitrate; + + ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG; + ctrls.count = 1; + ctrls.controls = &ctrl; + + ret = ioctl(dev->fd, VIDIOC_S_EXT_CTRLS, &ctrls); + if (ret < 0) + err("Cannot set bitrate on %d", dev->fd); + + return ret; +} -- cgit v1.2.3