blob: b7f3f4eeb34d7191af8f58361a2cb6a23e3b0e28
1 | /* |
2 | * Copyright (c) 2014 Amlogic, Inc. All rights reserved. |
3 | * |
4 | * This source code is subject to the terms and conditions defined in the |
5 | * file 'LICENSE' which is part of this source code package. |
6 | * |
7 | * Description: |
8 | */ |
9 | |
10 | |
11 | #include <stdio.h> |
12 | #include <fcntl.h> |
13 | #include <errno.h> |
14 | #include <sys/mman.h> |
15 | #include <sys/ioctl.h> |
16 | |
17 | #include "ionv4l.h" |
18 | #include "ionvdec_priv.h" |
19 | #define V4LDEVICE_NAME "/dev/video13" |
20 | #define CLEAR(s) memset(&s, 0, sizeof(s)) |
21 | |
22 | static int ionv4l_unmapbufs(ionvideo_dev_t *dev); |
23 | static int ionv4l_mapbufs(ionvideo_dev_t *dev); |
24 | int ionv4l_setfmt(ionvideo_dev_t *dev, struct v4l2_format *fmt); |
25 | int ionv4l_stop(ionvideo_dev_t *dev); |
26 | int ionv4l_init(ionvideo_dev_t *dev, int type, int width, int height, int fmt, int buffernum) |
27 | { |
28 | int ret; |
29 | ionv4l_dev_t *v4l = dev->devpriv; |
30 | struct v4l2_format v4lfmt; |
31 | v4l->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
32 | v4l->width = width; |
33 | v4l->height = height; |
34 | v4l->pixformat = fmt; |
35 | v4l->buffer_num = buffernum; |
36 | v4lfmt.type = v4l->type; |
37 | v4lfmt.fmt.pix.width = v4l->width; |
38 | v4lfmt.fmt.pix.height = v4l->height; |
39 | v4lfmt.fmt.pix.pixelformat = v4l->pixformat; |
40 | ret = ionv4l_setfmt(dev, &v4lfmt); |
41 | if (ret != 0) { |
42 | goto error_out; |
43 | } |
44 | ret = ionv4l_mapbufs(dev); |
45 | error_out: |
46 | return ret; |
47 | } |
48 | |
49 | static int ionv4l_ioctl(ionvideo_dev_t *dev, int request, void *arg) |
50 | { |
51 | int ret; |
52 | ionv4l_dev_t *v4l = dev->devpriv; |
53 | ret = ioctl(v4l->v4l_fd, request, arg); |
54 | if (ret == -1 && errno) { |
55 | ret = -errno; |
56 | } |
57 | return ret; |
58 | } |
59 | |
60 | int ionv4l_release(ionvideo_dev_t *dev) |
61 | { |
62 | int ret = -1; |
63 | ionv4l_dev_t *v4l = dev->devpriv; |
64 | if (v4l->v4l_fd < 0) { |
65 | return 0; |
66 | } |
67 | ionv4l_stop(dev); |
68 | ionv4l_unmapbufs(dev); |
69 | if (v4l->v4l_fd >= 0) { |
70 | ret = close(v4l->v4l_fd); |
71 | } |
72 | v4l->v4l_fd = -1; |
73 | free(dev); |
74 | if (ret == -1 && errno) { |
75 | ret = -errno; |
76 | } |
77 | |
78 | return ret; |
79 | } |
80 | |
81 | int ionv4l_dequeue_buf(ionvideo_dev_t *dev, vframebuf_t *vf) |
82 | { |
83 | struct v4l2_buffer vbuf; |
84 | CLEAR(vbuf); |
85 | int ret; |
86 | ionv4l_dev_t *v4l = dev->devpriv; |
87 | vbuf.type = v4l->type; |
88 | vbuf.memory = v4l->memory_mode; |
89 | vbuf.length = vf->length; |
90 | ret = ionv4l_ioctl(dev, VIDIOC_DQBUF, &vbuf); |
91 | if (!ret && vbuf.index < v4l->buffer_num) { |
92 | vf->pts = vbuf.timestamp.tv_sec & 0xFFFFFFFF; |
93 | vf->pts <<= 32; |
94 | vf->pts += vbuf.timestamp.tv_usec & 0xFFFFFFFF; |
95 | vf->fd = vbuf.m.fd; |
96 | vf->index = vbuf.index; |
97 | } |
98 | |
99 | return ret; |
100 | } |
101 | |
102 | int ionv4l_queue_buf(ionvideo_dev_t *dev, vframebuf_t *vf) |
103 | { |
104 | struct v4l2_buffer vbuf; |
105 | CLEAR(vbuf); |
106 | int ret; |
107 | ionv4l_dev_t *v4l = dev->devpriv; |
108 | vbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
109 | vbuf.memory = V4L2_MEMORY_DMABUF; |
110 | vbuf.index = vf->index; |
111 | vbuf.m.fd = vf->fd; |
112 | vbuf.length = vf->length; |
113 | return ionv4l_ioctl(dev, VIDIOC_QBUF, &vbuf); |
114 | } |
115 | |
116 | int ionv4l_start(ionvideo_dev_t *dev) |
117 | { |
118 | int type; |
119 | ionv4l_dev_t *v4l = dev->devpriv; |
120 | type = v4l->type; |
121 | return ionv4l_ioctl(dev, VIDIOC_STREAMON, &type); |
122 | } |
123 | |
124 | int ionv4l_stop(ionvideo_dev_t *dev) |
125 | { |
126 | int type; |
127 | ionv4l_dev_t *v4l = dev->devpriv; |
128 | type = v4l->type; |
129 | return ionv4l_ioctl(dev, VIDIOC_STREAMOFF, &type); |
130 | } |
131 | |
132 | int ionv4l_setfmt(ionvideo_dev_t *dev, struct v4l2_format *fmt) |
133 | { |
134 | return ionv4l_ioctl(dev, VIDIOC_S_FMT, fmt); |
135 | } |
136 | |
137 | int ionv4l_getfmt(ionvideo_dev_t *dev, struct v4l2_format *fmt) |
138 | { |
139 | return ionv4l_ioctl(dev, VIDIOC_G_FMT, fmt); |
140 | } |
141 | |
142 | static int ionv4l_unmapbufs(ionvideo_dev_t *dev) |
143 | { |
144 | return 0; |
145 | } |
146 | |
147 | static int ionv4l_mapbufs(ionvideo_dev_t *dev) |
148 | { |
149 | int ret; |
150 | struct v4l2_requestbuffers rb; |
151 | CLEAR(rb); |
152 | ionv4l_dev_t *v4l = dev->devpriv; |
153 | rb.count = v4l->buffer_num; |
154 | rb.type = v4l->type; |
155 | rb.memory = v4l->memory_mode; |
156 | return ionv4l_ioctl(dev, VIDIOC_REQBUFS, &rb); |
157 | } |
158 | |
159 | ionvideo_dev_t *new_ionv4l(void) |
160 | { |
161 | ionvideo_dev_t *dev; |
162 | ionv4l_dev_t *v4l; |
163 | dev = malloc(sizeof(ionvideo_dev_t) + sizeof(ionv4l_dev_t)); |
164 | memset(dev, 0, sizeof(ionvideo_dev_t) + sizeof(ionv4l_dev_t)); |
165 | dev->devpriv = (void *)((long)(&dev->devpriv) + 4); |
166 | v4l = dev->devpriv; |
167 | v4l->memory_mode = V4L2_MEMORY_DMABUF; |
168 | dev->ops.init = ionv4l_init; |
169 | dev->ops.release = ionv4l_release; |
170 | dev->ops.dequeuebuf = ionv4l_dequeue_buf; |
171 | dev->ops.queuebuf = ionv4l_queue_buf; |
172 | dev->ops.start = ionv4l_start; |
173 | dev->ops.stop = ionv4l_stop; |
174 | dev->ops.getparameters = ionv4l_getfmt; |
175 | v4l->v4l_fd = open(V4LDEVICE_NAME, O_RDWR | O_NONBLOCK); |
176 | if (v4l->v4l_fd < 0) { |
177 | free(dev); |
178 | LOGE("v4l device opend failed!,%s(%d)\n", strerror(errno), errno); |
179 | return NULL; |
180 | } |
181 | return dev; |
182 | } |
183 | |
184 |