aboutsummaryrefslogtreecommitdiff
path: root/video.c
diff options
context:
space:
mode:
Diffstat (limited to 'video.c')
-rw-r--r--video.c132
1 files changed, 117 insertions, 15 deletions
diff --git a/video.c b/video.c
index a5e1a95..3284800 100644
--- a/video.c
+++ b/video.c
@@ -21,6 +21,7 @@
*/
#include <linux/videodev2.h>
+#include <linux/media.h>
#include <linux/v4l2-controls.h>
#include <fcntl.h>
#include <string.h>
@@ -38,6 +39,7 @@
static char *dbg_type[2] = {"OUTPUT", "CAPTURE"};
static char *dbg_status[2] = {"ON", "OFF"};
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
/* check is it a decoder video device */
static int is_video_encoder(int fd, const char *name)
@@ -124,34 +126,41 @@ static int is_video_encoder(int fd, const char *name)
int video_open(struct instance *i, const char *name)
{
char video_name[64];
- unsigned idx = 0, v = 0;
- int ret, fd = -1;
+ char media_name[64];
+ unsigned idxM = 0, idxV = 0, v = 0;
+ int ret, fd = -1, media_fd = -1;
- while (v++ < 32) {
- ret = sprintf(video_name, "/dev/video%d", idx);
+ ret = sprintf(media_name, "/dev/media%d", idxM);
if (ret < 0)
return ret;
- idx++;
+ err("open media device: %s", media_name);
- dbg("open video device: %s", video_name);
+ media_fd = open(media_name, O_RDWR, 0);
+ if (media_fd < 0) {
+ err("Failed to open media device: %s", media_name);
+ return -1;
+ }
+
+ ret = sprintf(video_name, "/dev/video%d", idxV);
+ if (ret < 0)
+ return ret;
+
+ err("open video device: %s", video_name);
fd = open(video_name, O_RDWR, 0);
if (fd < 0) {
err("Failed to open video device: %s", video_name);
- continue;
+ return -1;
}
ret = is_video_encoder(fd, video_name);
if (ret < 0) {
close(fd);
- continue;
+ close(media_fd);
+ return -1;
}
- if (!ret)
- break;
- }
-
if (!ret)
info("found encoder video device %s", video_name);
@@ -164,13 +173,15 @@ int video_open(struct instance *i, const char *name)
}
i->video.fd = fd;
+ i->video.media_fd = media_fd;
- return 0;
+ return 0;
}
void video_close(struct instance *i)
{
close(i->video.fd);
+ close(i->video.media_fd);
}
int video_set_control(struct instance *i)
@@ -305,6 +316,71 @@ int video_set_control(struct instance *i)
return 0;
}
+int set_extra_control(int video_fd, int request_fd, unsigned int id,
+ void *data, unsigned int size)
+{
+ struct v4l2_ext_control control;
+ struct v4l2_ext_controls controls;
+ int rc;
+ err("set_extra_control");
+ memset(&control, 0, sizeof(control));
+ memset(&controls, 0, sizeof(controls));
+
+ control.id = id;
+ control.ptr = data;
+ control.size = size;
+
+ controls.controls = &control;
+ controls.count = 1;
+
+ if (request_fd >= 0) {
+ controls.which = V4L2_CTRL_WHICH_REQUEST_VAL;
+ controls.request_fd = request_fd;
+ }
+
+ rc = ioctl(video_fd, VIDIOC_S_EXT_CTRLS, &controls);
+ if (rc < 0) {
+ err("Unable to set control: %d %s\n", errno,strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+int video_setup_extra_control_out(struct instance *inst, unsigned int index)
+{
+ struct video *vid = &inst->video;
+ int rc;
+ unsigned int i;
+ err("video_setup_extra_control_out index %d",index);
+ struct v4l2_ctrl_venus_metadata {
+ unsigned int index;
+ //__u8 hdr10plus[16];
+ } hdr10plusInfo[] = {{1},{2},{3},{4},{5},{6},{7},{8},{9}};
+
+ if (index >= vid->out_buf_cnt) {
+ err("Tried to queue a non exisiting buffer");
+ return -1;
+ }
+ struct {
+ char *description;
+ unsigned int id;
+ void *data;
+ unsigned int size;
+ } controls[] = {{"HDR10", V4L2_CID_MPEG_VIDEO_VENUS_METADATA , &hdr10plusInfo[index+vid->cap_buf_cnt], sizeof(hdr10plusInfo)}};
+ for (i = 0; i < ARRAY_SIZE(controls); i++) {
+ struct v4l2_ctrl_venus_metadata *meta = controls[i].data;
+ err("set_extra_control : vid->fd %d vid->request_fd_out[%d] %d meta index %d",vid->fd,index,vid->request_fd_out[index],meta->index);
+ rc = set_extra_control(vid->fd, vid->request_fd_out[index], controls[i].id, controls[i].data,
+ controls[i].size);
+ if (rc < 0) {
+ err("Unable to set %s control\n", controls[i].description);
+ fprintf(stderr, "Unable to set %s control\n",strerror(errno));
+ return -1;
+ }
+ }
+ return rc;
+}
int video_export_buf(struct instance *i, unsigned int index)
{
struct video *vid = &i->video;
@@ -342,6 +418,7 @@ static int video_queue_buf(struct instance *i, unsigned int index,
struct v4l2_plane planes[2];
struct timeval tv;
int ret;
+ int request_fd = -1;
memzero(buf);
memset(planes, 0, sizeof(planes));
@@ -357,6 +434,14 @@ static int video_queue_buf(struct instance *i, unsigned int index,
buf.m.planes[0].data_offset = 0;
buf.m.planes[1].data_offset = 0;
+ if(type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+ request_fd = vid->request_fd_out[index];
+ if (request_fd >= 0) {
+ err("request_fd %d", request_fd);
+ buf.flags = V4L2_BUF_FLAG_REQUEST_FD;
+ buf.request_fd = request_fd;
+ }
+
if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
buf.m.planes[0].length = vid->cap_buf_size[0];
} else {
@@ -375,9 +460,10 @@ static int video_queue_buf(struct instance *i, unsigned int index,
ret = ioctl(vid->fd, VIDIOC_QBUF, &buf);
if (ret) {
- err("Failed to queue buffer (index=%d) on %s (%s)",
+ err("Failed to queue buffer (index=%d) on %s %u (%s)",
buf.index,
dbg_type[type==V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE],
+ errno,
strerror(errno));
return -1;
}
@@ -440,6 +526,7 @@ int video_dequeue_output(struct instance *i, unsigned int *n)
struct v4l2_buffer buf;
struct v4l2_plane planes[OUT_PLANES];
int ret;
+ int request_fd = -1;
memzero(buf);
buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
@@ -452,7 +539,13 @@ int video_dequeue_output(struct instance *i, unsigned int *n)
return ret;
*n = buf.index;
-
+ request_fd = i->video.request_fd_out[*n];
+ ret = ioctl(request_fd, MEDIA_REQUEST_IOC_REINIT, NULL);
+ if (ret < 0) {
+ fprintf(stderr, "Unable to reinit media request for fd %d: %s\n",
+ request_fd,strerror(errno));
+ //return -1;
+ }
return 0;
}
@@ -623,6 +716,7 @@ int video_setup_output(struct instance *i, unsigned long codec,
struct v4l2_plane planes[OUT_PLANES];
int ret;
int n;
+ int request_fd = -1;
memzero(try_fmt);
try_fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
@@ -727,6 +821,14 @@ int video_setup_output(struct instance *i, unsigned long codec,
}
vid->out_buf_flag[n] = 0;
+
+ ret = ioctl(vid->media_fd, MEDIA_IOC_REQUEST_ALLOC, &request_fd);
+ if (ret) {
+ err("Unable to allocate media request %u (%s)", errno,strerror(errno));
+ return -1;
+ }
+ vid->request_fd_out[n] = request_fd;
+ err("request_fd %d vid->request_fd_out[%d] %d", request_fd,n,vid->request_fd_out[n]);
}
info("OUTPUT: Succesfully mmapped %u buffers", n);