Mercurial > mplayer.hg
comparison stream/tvi_bsdbt848.c @ 19271:64d82a45a05d
introduce new 'stream' directory for all stream layer related components and split them from libmpdemux
author | ben |
---|---|
date | Mon, 31 Jul 2006 17:39:17 +0000 |
parents | libmpdemux/tvi_bsdbt848.c@d2d9d011203f |
children | ac69ba536915 |
comparison
equal
deleted
inserted
replaced
19270:7d39b911f0bd | 19271:64d82a45a05d |
---|---|
1 /* | |
2 (C)2002 Charles R. Henrich (henrich@msu.edu) | |
3 *BSD (hopefully, requires working driver!) BrookTree capture support. | |
4 | |
5 Still in (active) development! | |
6 | |
7 v1.1 Mar 13 2002 Fully functional, need to move ring buffer to | |
8 the kernel driver. | |
9 v1.0 Feb 19 2002 First Release, need to add support for changing | |
10 audio parameters. | |
11 */ | |
12 | |
13 #include "config.h" | |
14 | |
15 #define RINGSIZE 8 | |
16 #define FRAGSIZE 4096 /* (2^12 see SETFRAGSIZE below) */ | |
17 | |
18 #define TRUE (1==1) | |
19 #define FALSE (1==0) | |
20 | |
21 #define PAL_WIDTH 768 | |
22 #define PAL_HEIGHT 576 | |
23 #define PAL_FPS 25 | |
24 | |
25 #define NTSC_WIDTH 640 | |
26 #define NTSC_HEIGHT 480 | |
27 #define NTSC_FPS 29.97 | |
28 | |
29 #include <stdio.h> | |
30 #include <stdlib.h> | |
31 #include <unistd.h> | |
32 #include <fcntl.h> | |
33 #include <sys/types.h> | |
34 #include <sys/mman.h> | |
35 #include <sys/filio.h> | |
36 #include <sys/time.h> | |
37 #include <signal.h> | |
38 #include <string.h> | |
39 | |
40 #include <sys/param.h> | |
41 #ifdef __NetBSD__ | |
42 #include <dev/ic/bt8xx.h> | |
43 #include <sys/audioio.h> | |
44 #elif defined(__DragonFly__) | |
45 #include <dev/video/meteor/ioctl_meteor.h> | |
46 #include <dev/video/bktr/ioctl_bt848.h> | |
47 #elif __FreeBSD_version >= 502100 | |
48 #include <dev/bktr/ioctl_meteor.h> | |
49 #include <dev/bktr/ioctl_bt848.h> | |
50 #else | |
51 #include <machine/ioctl_meteor.h> | |
52 #include <machine/ioctl_bt848.h> | |
53 #endif | |
54 | |
55 #ifdef HAVE_SYS_SOUNDCARD_H | |
56 #include <sys/soundcard.h> | |
57 #else | |
58 #ifdef HAVE_SOUNDCARD_H | |
59 #include <soundcard.h> | |
60 #else | |
61 #include <machine/soundcard.h> | |
62 #endif | |
63 #endif | |
64 | |
65 #include "libaf/af_format.h" | |
66 #include "libvo/img_format.h" | |
67 #include "tv.h" | |
68 | |
69 /* information about this file */ | |
70 static tvi_info_t info = { | |
71 "Brooktree848 Support", | |
72 "bsdbt848", | |
73 "Charles Henrich", | |
74 "in development" | |
75 }; | |
76 | |
77 typedef struct { | |
78 int dirty; | |
79 double timestamp; | |
80 char *buf; | |
81 } RBFRAME; | |
82 | |
83 /* private data's */ | |
84 typedef struct { | |
85 | |
86 /* Audio */ | |
87 char *dspdev; | |
88 int dspready; | |
89 int dspfd; | |
90 int dspsamplesize; | |
91 int dspstereo; | |
92 int dspspeed; | |
93 int dspfmt; | |
94 int dspframesize; | |
95 int dsprate; | |
96 long long dspbytesread; | |
97 | |
98 /* Video */ | |
99 char *btdev; | |
100 int videoready; | |
101 int btfd; | |
102 int source; | |
103 float maxfps; | |
104 float fps; | |
105 int iformat; | |
106 int maxheight; | |
107 int maxwidth; | |
108 struct meteor_geomet geom; | |
109 struct meteor_capframe capframe; | |
110 | |
111 /* Frame Buffer */ | |
112 | |
113 int framebufsize; | |
114 float timestamp; | |
115 int curpaintframe; | |
116 int curbufframe; | |
117 unsigned char *livebuf; | |
118 RBFRAME framebuf[RINGSIZE]; | |
119 | |
120 /* Inputs */ | |
121 | |
122 int input; | |
123 | |
124 /* Tuner */ | |
125 | |
126 char *tunerdev; | |
127 int tunerfd; | |
128 int tunerready; | |
129 u_long tunerfreq; | |
130 struct bktr_chnlset cset; | |
131 | |
132 /* Other */ | |
133 | |
134 int immediatemode; | |
135 double starttime; | |
136 | |
137 } priv_t; | |
138 | |
139 #include "tvi_def.h" | |
140 | |
141 static priv_t *G_private=NULL; | |
142 | |
143 static int getinput(int innumber); | |
144 | |
145 static void processframe(int signal) | |
146 { | |
147 struct timeval curtime; | |
148 | |
149 if(G_private->immediatemode == TRUE) return; | |
150 | |
151 gettimeofday(&curtime, NULL); | |
152 | |
153 if(G_private->framebuf[G_private->curpaintframe].dirty == TRUE) | |
154 { | |
155 memcpy(G_private->framebuf[G_private->curpaintframe].buf, | |
156 G_private->livebuf, G_private->framebufsize); | |
157 | |
158 G_private->framebuf[G_private->curpaintframe].dirty = FALSE; | |
159 | |
160 G_private->framebuf[G_private->curpaintframe].timestamp = | |
161 curtime.tv_sec + curtime.tv_usec*.000001; | |
162 | |
163 G_private->curpaintframe++; | |
164 | |
165 if(G_private->curpaintframe >= RINGSIZE) G_private->curpaintframe = 0; | |
166 } | |
167 | |
168 return; | |
169 } | |
170 | |
171 /* handler creator - entry point ! */ | |
172 tvi_handle_t *tvi_init_bsdbt848(char *device) | |
173 { | |
174 return(new_handle()); | |
175 } | |
176 | |
177 static int control(priv_t *priv, int cmd, void *arg) | |
178 { | |
179 switch(cmd) | |
180 { | |
181 | |
182 /* Tuner Controls */ | |
183 | |
184 case TVI_CONTROL_IS_TUNER: | |
185 if(priv->tunerready == FALSE) return TVI_CONTROL_FALSE; | |
186 return(TVI_CONTROL_TRUE); | |
187 | |
188 case TVI_CONTROL_TUN_GET_FREQ: | |
189 { | |
190 if(ioctl(priv->tunerfd, TVTUNER_GETFREQ, &priv->tunerfreq) < 0) | |
191 { | |
192 perror("GETFREQ:ioctl"); | |
193 return(TVI_CONTROL_FALSE); | |
194 } | |
195 | |
196 (int)*(void **)arg = priv->tunerfreq; | |
197 return(TVI_CONTROL_TRUE); | |
198 } | |
199 | |
200 case TVI_CONTROL_TUN_SET_FREQ: | |
201 { | |
202 priv->tunerfreq = (int)*(void **)arg; | |
203 | |
204 if(ioctl(priv->tunerfd, TVTUNER_SETFREQ, &priv->tunerfreq) < 0) | |
205 { | |
206 perror("SETFREQ:ioctl"); | |
207 return(0); | |
208 } | |
209 | |
210 return(TVI_CONTROL_TRUE); | |
211 } | |
212 | |
213 case TVI_CONTROL_TUN_GET_TUNER: | |
214 case TVI_CONTROL_TUN_SET_TUNER: | |
215 | |
216 /* Inputs */ | |
217 | |
218 case TVI_CONTROL_SPC_GET_INPUT: | |
219 { | |
220 if(ioctl(priv->btfd, METEORGINPUT, &priv->input) < 0) | |
221 { | |
222 perror("GINPUT:ioctl"); | |
223 return(TVI_CONTROL_FALSE); | |
224 } | |
225 | |
226 (int)*(void **)arg = priv->input; | |
227 return(TVI_CONTROL_TRUE); | |
228 } | |
229 | |
230 case TVI_CONTROL_SPC_SET_INPUT: | |
231 { | |
232 priv->input = getinput((int)*(void **)arg); | |
233 | |
234 if(ioctl(priv->btfd, METEORSINPUT, &priv->input) < 0) | |
235 { | |
236 perror("tunerfreq:ioctl"); | |
237 return(0); | |
238 } | |
239 | |
240 return(TVI_CONTROL_TRUE); | |
241 } | |
242 | |
243 /* Audio Controls */ | |
244 | |
245 case TVI_CONTROL_IS_AUDIO: | |
246 if(priv->dspready == FALSE) return TVI_CONTROL_FALSE; | |
247 return(TVI_CONTROL_TRUE); | |
248 | |
249 case TVI_CONTROL_AUD_GET_FORMAT: | |
250 { | |
251 (int)*(void **)arg = AF_FORMAT_S16_LE; | |
252 return(TVI_CONTROL_TRUE); | |
253 } | |
254 case TVI_CONTROL_AUD_GET_CHANNELS: | |
255 { | |
256 (int)*(void **)arg = 2; | |
257 return(TVI_CONTROL_TRUE); | |
258 } | |
259 case TVI_CONTROL_AUD_SET_SAMPLERATE: | |
260 { | |
261 int dspspeed = (int)*(void **)arg; | |
262 | |
263 if(ioctl(priv->dspfd, SNDCTL_DSP_SPEED, &dspspeed) == -1) | |
264 { | |
265 perror("invalidaudiorate"); | |
266 return(TVI_CONTROL_FALSE); | |
267 } | |
268 | |
269 priv->dspspeed = dspspeed; | |
270 | |
271 priv->dspframesize = priv->dspspeed*priv->dspsamplesize/8/ | |
272 priv->fps * (priv->dspstereo+1); | |
273 priv->dsprate = priv->dspspeed * priv->dspsamplesize/8* | |
274 (priv->dspstereo+1); | |
275 | |
276 return(TVI_CONTROL_TRUE); | |
277 } | |
278 case TVI_CONTROL_AUD_GET_SAMPLERATE: | |
279 { | |
280 (int)*(void **)arg = priv->dspspeed; | |
281 return(TVI_CONTROL_TRUE); | |
282 } | |
283 case TVI_CONTROL_AUD_GET_SAMPLESIZE: | |
284 { | |
285 (int)*(void **)arg = priv->dspsamplesize/8; | |
286 return(TVI_CONTROL_TRUE); | |
287 } | |
288 | |
289 /* Video Controls */ | |
290 | |
291 case TVI_CONTROL_IS_VIDEO: | |
292 if(priv->videoready == FALSE) return TVI_CONTROL_FALSE; | |
293 return(TVI_CONTROL_TRUE); | |
294 | |
295 case TVI_CONTROL_TUN_SET_NORM: | |
296 { | |
297 int req_mode = (int)*(void **)arg; | |
298 u_short tmp_fps; | |
299 | |
300 priv->iformat = METEOR_FMT_AUTOMODE; | |
301 | |
302 if(req_mode == TV_NORM_PAL) | |
303 { | |
304 priv->iformat = METEOR_FMT_PAL; | |
305 priv->maxheight = PAL_HEIGHT; | |
306 priv->maxwidth = PAL_WIDTH; | |
307 priv->maxfps = PAL_FPS; | |
308 priv->fps = PAL_FPS; | |
309 | |
310 if(priv->fps > priv->maxfps) priv->fps = priv->maxfps; | |
311 | |
312 if(priv->geom.rows > priv->maxheight) | |
313 { | |
314 priv->geom.rows = priv->maxheight; | |
315 } | |
316 | |
317 if(priv->geom.columns > priv->maxwidth) | |
318 { | |
319 priv->geom.columns = priv->maxwidth; | |
320 } | |
321 } | |
322 | |
323 if(req_mode == TV_NORM_NTSC) | |
324 { | |
325 priv->iformat = METEOR_FMT_NTSC; | |
326 priv->maxheight = NTSC_HEIGHT; | |
327 priv->maxwidth = NTSC_WIDTH; | |
328 priv->maxfps = NTSC_FPS; | |
329 priv->fps = NTSC_FPS; | |
330 | |
331 priv->dspframesize = priv->dspspeed*priv->dspsamplesize/8/ | |
332 priv->fps * (priv->dspstereo+1); | |
333 priv->dsprate = priv->dspspeed * priv->dspsamplesize/8 * | |
334 (priv->dspstereo+1); | |
335 | |
336 if(priv->fps > priv->maxfps) priv->fps = priv->maxfps; | |
337 | |
338 if(priv->geom.rows > priv->maxheight) | |
339 { | |
340 priv->geom.rows = priv->maxheight; | |
341 } | |
342 | |
343 if(priv->geom.columns > priv->maxwidth) | |
344 { | |
345 priv->geom.columns = priv->maxwidth; | |
346 } | |
347 } | |
348 | |
349 if(req_mode == TV_NORM_SECAM) priv->iformat = METEOR_FMT_SECAM; | |
350 | |
351 if(ioctl(priv->btfd, METEORSFMT, &priv->iformat) < 0) | |
352 { | |
353 perror("format:ioctl"); | |
354 return(TVI_CONTROL_FALSE); | |
355 } | |
356 | |
357 if(ioctl(priv->btfd, METEORSETGEO, &priv->geom) < 0) | |
358 { | |
359 perror("geo:ioctl"); | |
360 return(0); | |
361 } | |
362 | |
363 tmp_fps = priv->fps; | |
364 if(ioctl(priv->btfd, METEORSFPS, &tmp_fps) < 0) | |
365 { | |
366 perror("fps:ioctl"); | |
367 return(0); | |
368 } | |
369 | |
370 #ifdef BT848_SAUDIO | |
371 if(priv->tunerready == TRUE && | |
372 ioctl(priv->tunerfd, BT848_SAUDIO, &tv_param_audio_id) < 0) | |
373 { | |
374 perror("audioid:ioctl"); | |
375 } | |
376 #endif | |
377 | |
378 return(TVI_CONTROL_TRUE); | |
379 } | |
380 | |
381 case TVI_CONTROL_VID_GET_FORMAT: | |
382 (int)*(void **)arg = IMGFMT_UYVY; | |
383 return(TVI_CONTROL_TRUE); | |
384 | |
385 case TVI_CONTROL_VID_SET_FORMAT: | |
386 { | |
387 int req_fmt = (int)*(void **)arg; | |
388 | |
389 if(req_fmt != IMGFMT_UYVY) return(TVI_CONTROL_FALSE); | |
390 | |
391 return(TVI_CONTROL_TRUE); | |
392 } | |
393 case TVI_CONTROL_VID_SET_WIDTH: | |
394 priv->geom.columns = (int)*(void **)arg; | |
395 | |
396 if(priv->geom.columns > priv->maxwidth) | |
397 { | |
398 priv->geom.columns = priv->maxwidth; | |
399 } | |
400 | |
401 if(ioctl(priv->btfd, METEORSETGEO, &priv->geom) < 0) | |
402 { | |
403 perror("width:ioctl"); | |
404 return(0); | |
405 } | |
406 | |
407 return(TVI_CONTROL_TRUE); | |
408 | |
409 case TVI_CONTROL_VID_GET_WIDTH: | |
410 (int)*(void **)arg = priv->geom.columns; | |
411 return(TVI_CONTROL_TRUE); | |
412 | |
413 case TVI_CONTROL_VID_SET_HEIGHT: | |
414 priv->geom.rows = (int)*(void **)arg; | |
415 | |
416 if(priv->geom.rows > priv->maxheight) | |
417 { | |
418 priv->geom.rows = priv->maxheight; | |
419 } | |
420 | |
421 if(priv->geom.rows <= priv->maxheight / 2) | |
422 { | |
423 priv->geom.oformat |= METEOR_GEO_EVEN_ONLY; | |
424 } | |
425 | |
426 if(ioctl(priv->btfd, METEORSETGEO, &priv->geom) < 0) | |
427 { | |
428 perror("height:ioctl"); | |
429 return(0); | |
430 } | |
431 | |
432 return(TVI_CONTROL_TRUE); | |
433 | |
434 case TVI_CONTROL_VID_GET_HEIGHT: | |
435 (int)*(void **)arg = priv->geom.rows; | |
436 return(TVI_CONTROL_TRUE); | |
437 | |
438 case TVI_CONTROL_VID_GET_FPS: | |
439 *(float *)arg = priv->fps; | |
440 return(TVI_CONTROL_TRUE); | |
441 | |
442 /* | |
443 case TVI_CONTROL_VID_SET_FPS: | |
444 priv->fps = (int)*(void **)arg; | |
445 | |
446 if(priv->fps > priv->maxfps) priv->fps = priv->maxfps; | |
447 | |
448 if(ioctl(priv->btfd, METEORSFPS, &priv->fps) < 0) | |
449 { | |
450 perror("fps:ioctl"); | |
451 return(0); | |
452 } | |
453 | |
454 return(TVI_CONTROL_TRUE); | |
455 */ | |
456 | |
457 case TVI_CONTROL_VID_CHK_WIDTH: | |
458 case TVI_CONTROL_VID_CHK_HEIGHT: | |
459 return(TVI_CONTROL_TRUE); | |
460 | |
461 case TVI_CONTROL_IMMEDIATE: | |
462 priv->immediatemode = TRUE; | |
463 return(TVI_CONTROL_TRUE); | |
464 } | |
465 | |
466 return(TVI_CONTROL_UNKNOWN); | |
467 } | |
468 | |
469 static int init(priv_t *priv) | |
470 { | |
471 int marg; | |
472 int count; | |
473 u_short tmp_fps; | |
474 | |
475 G_private = priv; /* Oooh, sick */ | |
476 | |
477 /* Video Configuration */ | |
478 | |
479 priv->videoready = TRUE; | |
480 priv->btdev = strdup("/dev/bktr0"); | |
481 priv->immediatemode = FALSE; | |
482 priv->iformat = METEOR_FMT_PAL; | |
483 priv->maxheight = PAL_HEIGHT; | |
484 priv->maxwidth = PAL_WIDTH; | |
485 priv->maxfps = PAL_FPS; | |
486 priv->source = METEOR_INPUT_DEV0; | |
487 priv->fps = priv->maxfps; | |
488 | |
489 priv->starttime=0; | |
490 priv->curpaintframe=0; | |
491 priv->curbufframe=0; | |
492 | |
493 priv->geom.columns = priv->maxwidth; | |
494 priv->geom.rows = priv->maxheight; | |
495 priv->geom.frames = 1; | |
496 priv->geom.oformat = METEOR_GEO_YUV_PACKED; | |
497 | |
498 priv->btfd = open(priv->btdev, O_RDONLY); | |
499 | |
500 if(priv->btfd < 0) | |
501 { | |
502 perror("bktr open"); | |
503 priv->videoready = FALSE; | |
504 } | |
505 | |
506 if(priv->videoready == TRUE && | |
507 ioctl(priv->btfd, METEORSFMT, &priv->iformat) < 0) | |
508 { | |
509 perror("FMT:ioctl"); | |
510 } | |
511 | |
512 if(priv->videoready == TRUE && | |
513 ioctl(priv->btfd, METEORSINPUT, &priv->source) < 0) | |
514 { | |
515 perror("SINPUT:ioctl"); | |
516 } | |
517 | |
518 tmp_fps = priv->fps; | |
519 if(priv->videoready == TRUE && | |
520 ioctl(priv->btfd, METEORSFPS, &tmp_fps) < 0) | |
521 { | |
522 perror("SFPS:ioctl"); | |
523 } | |
524 | |
525 if(priv->videoready == TRUE && | |
526 ioctl(priv->btfd, METEORSETGEO, &priv->geom) < 0) | |
527 { | |
528 perror("SGEO:ioctl"); | |
529 } | |
530 | |
531 if(priv->videoready == TRUE) | |
532 { | |
533 priv->framebufsize = (priv->geom.columns * priv->geom.rows * 2); | |
534 | |
535 priv->livebuf = (u_char *)mmap((caddr_t)0, priv->framebufsize, PROT_READ, | |
536 MAP_SHARED, priv->btfd, (off_t)0); | |
537 | |
538 if(priv->livebuf == (u_char *) MAP_FAILED) | |
539 { | |
540 perror("mmap"); | |
541 priv->videoready = FALSE; | |
542 } | |
543 | |
544 for(count=0;count<RINGSIZE;count++) | |
545 { | |
546 priv->framebuf[count].buf = malloc(priv->framebufsize); | |
547 | |
548 if(priv->framebuf[count].buf == NULL) | |
549 { | |
550 perror("framebufmalloc"); | |
551 priv->videoready = FALSE; | |
552 break; | |
553 } | |
554 | |
555 priv->framebuf[count].dirty = TRUE; | |
556 priv->framebuf[count].timestamp = 0; | |
557 } | |
558 } | |
559 | |
560 /* Tuner Configuration */ | |
561 | |
562 priv->tunerdev = strdup("/dev/tuner0"); | |
563 priv->tunerready = TRUE; | |
564 | |
565 priv->tunerfd = open(priv->tunerdev, O_RDONLY); | |
566 | |
567 if(priv->tunerfd < 0) | |
568 { | |
569 perror("tune open"); | |
570 priv->tunerready = FALSE; | |
571 } | |
572 | |
573 /* Audio Configuration */ | |
574 | |
575 priv->dspready = TRUE; | |
576 #ifdef __NetBSD__ | |
577 priv->dspdev = strdup("/dev/sound"); | |
578 #else | |
579 priv->dspdev = strdup("/dev/dsp"); | |
580 #endif | |
581 priv->dspsamplesize = 16; | |
582 priv->dspstereo = 1; | |
583 priv->dspspeed = 44100; | |
584 priv->dspfmt = AFMT_S16_LE; | |
585 priv->dspbytesread = 0; | |
586 priv->dsprate = priv->dspspeed * priv->dspsamplesize/8*(priv->dspstereo+1); | |
587 priv->dspframesize = priv->dspspeed*priv->dspsamplesize/8/priv->fps * | |
588 (priv->dspstereo+1); | |
589 | |
590 if((priv->dspfd = open (priv->dspdev, O_RDONLY, 0)) < 0) | |
591 { | |
592 perror("dsp open"); | |
593 priv->dspready = FALSE; | |
594 } | |
595 | |
596 marg = (256 << 16) | 12; | |
597 | |
598 if (ioctl(priv->dspfd, SNDCTL_DSP_SETFRAGMENT, &marg ) < 0 ) | |
599 { | |
600 perror("setfrag"); | |
601 priv->dspready = FALSE; | |
602 } | |
603 | |
604 if((priv->dspready == TRUE) && | |
605 ((ioctl(priv->dspfd, SNDCTL_DSP_SAMPLESIZE, &priv->dspsamplesize) == -1) || | |
606 (ioctl(priv->dspfd, SNDCTL_DSP_STEREO, &priv->dspstereo) == -1) || | |
607 (ioctl(priv->dspfd, SNDCTL_DSP_SPEED, &priv->dspspeed) == -1) || | |
608 (ioctl(priv->dspfd, SNDCTL_DSP_SETFMT, &priv->dspfmt) == -1))) | |
609 { | |
610 perror ("configuration of dsp failed"); | |
611 close(priv->dspfd); | |
612 priv->dspready = FALSE; | |
613 } | |
614 | |
615 return(1); | |
616 } | |
617 | |
618 /* that's the real start, we'got the format parameters (checked with control) */ | |
619 static int start(priv_t *priv) | |
620 { | |
621 int tmp; | |
622 struct timeval curtime; | |
623 int marg; | |
624 | |
625 fprintf(stderr,"START\n"); | |
626 if(priv->videoready == FALSE) return(0); | |
627 | |
628 signal(SIGUSR1, processframe); | |
629 signal(SIGALRM, processframe); | |
630 | |
631 marg = SIGUSR1; | |
632 | |
633 if(ioctl(priv->btfd, METEORSSIGNAL, &marg) < 0) | |
634 { | |
635 perror("METEORSSIGNAL failed"); | |
636 return(0); | |
637 } | |
638 | |
639 read(priv->dspfd, &tmp, 2); | |
640 | |
641 gettimeofday(&curtime, NULL); | |
642 | |
643 priv->starttime = curtime.tv_sec + (curtime.tv_usec *.000001); | |
644 | |
645 marg = METEOR_CAP_CONTINOUS; | |
646 | |
647 if(ioctl(priv->btfd, METEORCAPTUR, &marg) < 0) | |
648 { | |
649 perror("METEORCAPTUR failed"); | |
650 return(0); | |
651 } | |
652 | |
653 return(1); | |
654 } | |
655 | |
656 static int uninit(priv_t *priv) | |
657 { | |
658 int marg; | |
659 | |
660 if(priv->videoready == FALSE) return(0); | |
661 | |
662 marg = METEOR_SIG_MODE_MASK; | |
663 | |
664 if(ioctl( priv->btfd, METEORSSIGNAL, &marg) < 0 ) | |
665 { | |
666 perror("METEORSSIGNAL"); | |
667 return(0); | |
668 } | |
669 | |
670 marg = METEOR_CAP_STOP_CONT; | |
671 | |
672 if(ioctl(priv->btfd, METEORCAPTUR, &marg) < 0 ) | |
673 { | |
674 perror("METEORCAPTUR STOP"); | |
675 return(0); | |
676 } | |
677 | |
678 close(priv->btfd); | |
679 close(priv->dspfd); | |
680 | |
681 priv->dspfd = -1; | |
682 priv->btfd = -1; | |
683 | |
684 priv->dspready = priv->videoready = FALSE; | |
685 | |
686 return(1); | |
687 } | |
688 | |
689 | |
690 static double grabimmediate_video_frame(priv_t *priv, char *buffer, int len) | |
691 { | |
692 struct timeval curtime; | |
693 sigset_t sa_mask; | |
694 | |
695 if(priv->videoready == FALSE) return(0); | |
696 | |
697 alarm(1); | |
698 sigfillset(&sa_mask); | |
699 sigdelset(&sa_mask,SIGINT); | |
700 sigdelset(&sa_mask,SIGUSR1); | |
701 sigdelset(&sa_mask,SIGALRM); | |
702 sigsuspend(&sa_mask); | |
703 alarm(0); | |
704 | |
705 memcpy(buffer, priv->livebuf, len); | |
706 | |
707 /* PTS = 0, show the frame NOW, this routine is only used in playback mode | |
708 without audio capture .. */ | |
709 | |
710 return(0); | |
711 } | |
712 | |
713 static double grab_video_frame(priv_t *priv, char *buffer, int len) | |
714 { | |
715 struct timeval curtime; | |
716 double timestamp=0; | |
717 sigset_t sa_mask; | |
718 | |
719 if(priv->videoready == FALSE) return(0); | |
720 | |
721 if(priv->immediatemode == TRUE) | |
722 { | |
723 return grabimmediate_video_frame(priv, buffer, len); | |
724 } | |
725 | |
726 while(priv->framebuf[priv->curbufframe].dirty == TRUE) | |
727 { | |
728 alarm(1); | |
729 sigemptyset(&sa_mask); | |
730 sigsuspend(&sa_mask); | |
731 alarm(0); | |
732 } | |
733 | |
734 memcpy(buffer, priv->framebuf[priv->curbufframe].buf, len); | |
735 timestamp = priv->framebuf[priv->curbufframe].timestamp; | |
736 priv->framebuf[priv->curbufframe].dirty = TRUE; | |
737 | |
738 priv->curbufframe++; | |
739 if(priv->curbufframe >= RINGSIZE) priv->curbufframe = 0; | |
740 | |
741 return(timestamp-priv->starttime); | |
742 } | |
743 | |
744 static int get_video_framesize(priv_t *priv) | |
745 { | |
746 return(priv->geom.columns*priv->geom.rows*16/8); | |
747 } | |
748 | |
749 static double grab_audio_frame(priv_t *priv, char *buffer, int len) | |
750 { | |
751 struct timeval curtime; | |
752 double curpts; | |
753 double timeskew; | |
754 int bytesavail; | |
755 int bytesread; | |
756 int ret; | |
757 | |
758 if(priv->dspready == FALSE) return 0; | |
759 | |
760 gettimeofday(&curtime, NULL); | |
761 | |
762 /* Get exactly one frame of audio, which forces video sync to audio.. */ | |
763 | |
764 bytesread=read(priv->dspfd, buffer, len); | |
765 | |
766 while(bytesread < len) | |
767 { | |
768 ret=read(priv->dspfd, &buffer[bytesread], len-bytesread); | |
769 | |
770 if(ret == -1) | |
771 { | |
772 perror("Audio read failed!"); | |
773 return 0; | |
774 } | |
775 | |
776 bytesread+=ret; | |
777 } | |
778 | |
779 priv->dspbytesread += bytesread; | |
780 | |
781 curpts = curtime.tv_sec + curtime.tv_usec * .000001; | |
782 | |
783 timeskew = priv->dspbytesread * 1.0 / priv->dsprate - (curpts-priv->starttime); | |
784 | |
785 if(timeskew > .125/priv->fps) | |
786 { | |
787 priv->starttime -= timeskew; | |
788 } | |
789 else | |
790 { | |
791 if(timeskew < -.125/priv->fps) | |
792 { | |
793 priv->starttime -= timeskew; | |
794 } | |
795 } | |
796 | |
797 return(priv->dspbytesread * 1.0 / priv->dsprate); | |
798 } | |
799 | |
800 static int get_audio_framesize(priv_t *priv) | |
801 { | |
802 int bytesavail; | |
803 #ifdef __NetBSD__ | |
804 struct audio_info auinf; | |
805 #endif | |
806 | |
807 if(priv->dspready == FALSE) return 0; | |
808 | |
809 #ifdef __NetBSD__ | |
810 if(ioctl(priv->dspfd, AUDIO_GETINFO, &auinf) < 0) | |
811 { | |
812 perror("AUDIO_GETINFO"); | |
813 return(TVI_CONTROL_FALSE); | |
814 } | |
815 else | |
816 bytesavail = auinf.record.seek; /* *priv->dspsamplesize; */ | |
817 #else | |
818 if(ioctl(priv->dspfd, FIONREAD, &bytesavail) < 0) | |
819 { | |
820 perror("FIONREAD"); | |
821 return(TVI_CONTROL_FALSE); | |
822 } | |
823 #endif | |
824 | |
825 /* When mencoder wants audio data, it wants data.. | |
826 it won't go do anything else until it gets it :( */ | |
827 | |
828 if(bytesavail == 0) return FRAGSIZE; | |
829 | |
830 return(bytesavail); | |
831 } | |
832 | |
833 static int getinput(int innumber) | |
834 { | |
835 switch(innumber) | |
836 { | |
837 case 0: return METEOR_INPUT_DEV0; /* RCA */ | |
838 case 1: return METEOR_INPUT_DEV1; /* Tuner */ | |
839 case 2: return METEOR_INPUT_DEV2; /* In 1 */ | |
840 case 3: return METEOR_INPUT_DEV3; /* In 2 */ | |
841 case 4: return METEOR_INPUT_DEV_RGB; /* RGB */ | |
842 case 5: return METEOR_INPUT_DEV_SVIDEO; /* SVid */ | |
843 } | |
844 | |
845 return 0; | |
846 } |