Mercurial > mplayer.hg
comparison libvo/vo_ivtv.c @ 19137:d9656bb2ae0e
new vo driver for ivtv cards tv-out through internal h/w mpeg decoder
author | ben |
---|---|
date | Wed, 19 Jul 2006 22:02:09 +0000 |
parents | |
children | 4c22e1d84ac9 |
comparison
equal
deleted
inserted
replaced
19136:87f9eebbf712 | 19137:d9656bb2ae0e |
---|---|
1 /* | |
2 * Copyright (C) 2006 Benjamin Zores | |
3 * Video output for WinTV PVR-150/250/350 (a.k.a IVTV) cards. | |
4 * TV-Out through hardware MPEG decoder. | |
5 * Based on some old code from ivtv driver authors. | |
6 * See http://ivtvdriver.org/index.php/Main_Page for more details on the | |
7 * cards supported by the ivtv driver. | |
8 * | |
9 * This program is free software; you can redistribute it and/or modify | |
10 * it under the terms of the GNU General Public License as published by | |
11 * the Free Software Foundation; either version 2 of the License, or | |
12 * (at your option) any later version. | |
13 * | |
14 * This program is distributed in the hope that it will be useful, | |
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 * GNU General Public License for more details. | |
18 * | |
19 * You should have received a copy of the GNU General Public License | |
20 * along with this program; if not, write to the Free Software Foundation, | |
21 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
22 */ | |
23 | |
24 #include "config.h" | |
25 | |
26 #include <stdio.h> | |
27 #include <stdlib.h> | |
28 #include <string.h> | |
29 #include <errno.h> | |
30 #include <sys/types.h> | |
31 #include <sys/stat.h> | |
32 #include <sys/ioctl.h> | |
33 #include <fcntl.h> | |
34 #include <unistd.h> | |
35 #include <stdlib.h> | |
36 #include <inttypes.h> | |
37 #include <linux/types.h> | |
38 #include <linux/videodev2.h> | |
39 #include <linux/ivtv.h> | |
40 #include <linux/ioctl.h> | |
41 | |
42 #include "mp_msg.h" | |
43 #include "subopt-helper.h" | |
44 #include "video_out.h" | |
45 #include "video_out_internal.h" | |
46 #include "libmpcodecs/mpeg_packetizer.h" | |
47 | |
48 #define DEFAULT_MPEG_DECODER "/dev/video16" | |
49 #define IVTV_VO_HDR "VO: [ivtv]" | |
50 | |
51 /* ivtv private */ | |
52 int ivtv_fd = -1; | |
53 static vo_mpegpes_t *pes; | |
54 | |
55 /* suboptions */ | |
56 static int output = -1; | |
57 static char *device = NULL; | |
58 | |
59 static opt_t subopts[] = { | |
60 {"output", OPT_ARG_INT, &output, (opt_test_f)int_non_neg}, | |
61 {"device", OPT_ARG_MSTRZ, &device, NULL}, | |
62 {NULL} | |
63 }; | |
64 | |
65 static vo_info_t info = | |
66 { | |
67 "IVTV MPEG Video Decoder TV-Out", | |
68 "ivtv", | |
69 "Benjamin Zores", | |
70 "" | |
71 }; | |
72 LIBVO_EXTERN (ivtv) | |
73 | |
74 /* ivtv internals */ | |
75 | |
76 static uint32_t | |
77 ivtv_reset (int blank_screen) | |
78 { | |
79 struct ivtv_cfg_stop_decode sd; | |
80 struct ivtv_cfg_start_decode sd1; | |
81 | |
82 sd.hide_last = blank_screen; | |
83 sd.pts_stop = 0; | |
84 | |
85 if (ioctl (ivtv_fd, IVTV_IOC_S_STOP_DECODE, &sd) < 0) | |
86 { | |
87 mp_msg (MSGT_VO, MSGL_ERR, | |
88 "IVTV_IOC_STOP_DECODE: %s\n", strerror (errno)); | |
89 return 1; | |
90 } | |
91 | |
92 sd1.gop_offset = 0; | |
93 sd1.muted_audio_frames = 0; | |
94 | |
95 if (ioctl (ivtv_fd, IVTV_IOC_S_START_DECODE, &sd1) < 0) | |
96 { | |
97 mp_msg (MSGT_VO, MSGL_ERR, | |
98 "IVTV_IOC_START_DECODE: %s\n", strerror (errno)); | |
99 return 1; | |
100 } | |
101 | |
102 return 0; | |
103 } | |
104 | |
105 int | |
106 ivtv_write (unsigned char *data, int len) | |
107 { | |
108 if (ivtv_fd < 0) | |
109 return 0; | |
110 | |
111 return write (ivtv_fd, data, len); | |
112 } | |
113 | |
114 /* video out functions */ | |
115 | |
116 static int | |
117 config (uint32_t width, uint32_t height, | |
118 uint32_t d_width, uint32_t d_height, | |
119 uint32_t fullscreen, char *title, uint32_t format) | |
120 { | |
121 return 0; | |
122 } | |
123 | |
124 static int | |
125 preinit (const char *arg) | |
126 { | |
127 struct v4l2_output vout; | |
128 int err; | |
129 | |
130 if (subopt_parse (arg, subopts) != 0) | |
131 { | |
132 mp_msg (MSGT_VO, MSGL_FATAL, | |
133 "\n-vo ivtv command line help:\n" | |
134 "Example: mplayer -vo ivtv:device=/dev/video16:output=2\n" | |
135 "\nOptions:\n" | |
136 " device=/dev/videoX\n" | |
137 " Name of the MPEG decoder device file.\n" | |
138 " output=<0-...>\n" | |
139 " V4L2 id of the TV output.\n" | |
140 "\n" ); | |
141 return -1; | |
142 } | |
143 | |
144 if (!device) | |
145 device = strdup (DEFAULT_MPEG_DECODER); | |
146 | |
147 ivtv_fd = open (device, O_RDWR); | |
148 if (ivtv_fd < 0) | |
149 { | |
150 free (device); | |
151 mp_msg (MSGT_VO, MSGL_FATAL, "%s %s\n", IVTV_VO_HDR, strerror (errno)); | |
152 return -1; | |
153 } | |
154 | |
155 /* list available outputs */ | |
156 vout.index = 0; | |
157 err = 1; | |
158 mp_msg (MSGT_VO, MSGL_INFO, "%s Available video outputs: ", IVTV_VO_HDR); | |
159 while (ioctl (ivtv_fd, VIDIOC_ENUMOUTPUT, &vout) >= 0) | |
160 { | |
161 err = 0; | |
162 mp_msg (MSGT_VO, MSGL_INFO, "'#%d, %s' ", vout.index, vout.name); | |
163 vout.index++; | |
164 } | |
165 if (err) | |
166 { | |
167 mp_msg (MSGT_VO, MSGL_INFO, "none\n"); | |
168 free (device); | |
169 return -1; | |
170 } | |
171 else | |
172 mp_msg (MSGT_VO, MSGL_INFO, "\n"); | |
173 | |
174 /* set user specified output */ | |
175 if (output != -1) | |
176 { | |
177 if (ioctl (ivtv_fd, VIDIOC_S_OUTPUT, &output) < 0) | |
178 { | |
179 mp_msg (MSGT_VO, MSGL_ERR, | |
180 "%s can't set output (%s)\n", IVTV_VO_HDR, strerror (errno)); | |
181 free (device); | |
182 return -1; | |
183 } | |
184 } | |
185 | |
186 /* display device name */ | |
187 mp_msg (MSGT_VO, MSGL_INFO, "%s using %s\n", IVTV_VO_HDR, device); | |
188 free (device); | |
189 | |
190 /* display current video output */ | |
191 if (ioctl (ivtv_fd, VIDIOC_G_OUTPUT, &output) == 0) | |
192 { | |
193 vout.index = output; | |
194 if (ioctl (ivtv_fd, VIDIOC_ENUMOUTPUT, &vout) < 0) | |
195 { | |
196 mp_msg (MSGT_VO, MSGL_ERR, | |
197 "%s can't get output (%s).\n", IVTV_VO_HDR, strerror (errno)); | |
198 return -1; | |
199 } | |
200 else | |
201 mp_msg (MSGT_VO, MSGL_INFO, | |
202 "%s video output: %s\n", IVTV_VO_HDR, vout.name); | |
203 } | |
204 else | |
205 { | |
206 mp_msg (MSGT_VO, MSGL_ERR, | |
207 "%s can't get output (%s).\n", IVTV_VO_HDR, strerror (errno)); | |
208 return -1; | |
209 } | |
210 | |
211 /* clear output */ | |
212 ivtv_reset (1); | |
213 | |
214 return 0; | |
215 } | |
216 | |
217 static void | |
218 draw_osd (void) | |
219 { | |
220 /* do nothing */ | |
221 } | |
222 | |
223 static int | |
224 draw_frame (uint8_t * src[]) | |
225 { | |
226 pes = (vo_mpegpes_t *) src[0]; | |
227 return 0; | |
228 } | |
229 | |
230 static void | |
231 flip_page (void) | |
232 { | |
233 if (ivtv_fd < 0) | |
234 return; | |
235 | |
236 if (!pes) | |
237 return; | |
238 | |
239 send_mpeg2_pes_packet (pes->data, pes->size, pes->id, | |
240 pes->timestamp ? pes->timestamp : vo_pts, | |
241 ivtv_write); | |
242 | |
243 /* ensure flip_page() won't be called twice */ | |
244 pes = NULL; | |
245 } | |
246 | |
247 static int | |
248 draw_slice (uint8_t *image[], int stride[], int w, int h, int x, int y) | |
249 { | |
250 return 0; | |
251 } | |
252 | |
253 static void | |
254 uninit (void) | |
255 { | |
256 if (ivtv_fd < 0) | |
257 return; | |
258 | |
259 /* clear output */ | |
260 ivtv_reset (1); | |
261 | |
262 /* close device */ | |
263 close (ivtv_fd); | |
264 ivtv_fd = -1; | |
265 } | |
266 | |
267 static void | |
268 check_events (void) | |
269 { | |
270 /* do nothing */ | |
271 } | |
272 | |
273 static int | |
274 query_format (uint32_t format) | |
275 { | |
276 if (format != IMGFMT_MPEGPES) | |
277 return 0; | |
278 | |
279 return VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_TIMER; | |
280 } | |
281 | |
282 static int | |
283 control (uint32_t request, void *data, ...) | |
284 { | |
285 switch (request) | |
286 { | |
287 case VOCTRL_PAUSE: | |
288 case VOCTRL_RESUME: | |
289 return ivtv_reset (0); | |
290 | |
291 case VOCTRL_RESET: | |
292 return ivtv_reset (1); | |
293 | |
294 case VOCTRL_QUERY_FORMAT: | |
295 return query_format (*((uint32_t*) data)); | |
296 } | |
297 | |
298 return VO_NOTIMPL; | |
299 } |