4 * Copyright (C) 2001 Alex Beregszaszi
6 * Some ideas are based on xawtv/libng's grab-v4l.c written by
7 * Gerd Knorr <kraxel@bytesex.org>
9 * Multithreading, a/v sync and native ALSA support by
10 * Jindrich Makovicka <makovick@gmail.com>
12 * MJPEG hardware encoding support by
13 * Ivan Szanto <szivan@freemail.hu>
15 * CODE IS UNDER DEVELOPMENT, NO FEATURE REQUESTS PLEASE!
17 * This file is part of MPlayer.
19 * MPlayer is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation; either version 2 of the License, or
22 * (at your option) any later version.
24 * MPlayer is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
29 * You should have received a copy of the GNU General Public License along
30 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
31 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
39 #include <sys/ioctl.h>
40 #include <sys/types.h>
43 /* Necessary to prevent collisions between <linux/time.h> and <sys/time.h> when V4L2 is installed. */
46 #include <linux/videodev.h>
52 #ifdef HAVE_SYS_SYSINFO_H
53 #include <sys/sysinfo.h>
57 #include "libaf/af_format.h"
58 #include "libmpcodecs/img_format.h"
59 #include "libmpcodecs/dec_teletext.h"
60 #include "libvo/fastmemcpy.h"
61 #include "libvo/videodev_mjpeg.h"
67 static tvi_handle_t
*tvi_init_v4l(tv_param_t
* tv_param
);
69 const tvi_info_t tvi_info_v4l
= {
71 "Video 4 Linux input",
78 #define PAL_HEIGHT 576
81 #define NTSC_WIDTH 640
82 #define NTSC_HEIGHT 480
83 #define NTSC_FPS (30000.0/1001.0)
85 #define MAX_AUDIO_CHANNELS 10
87 #define VID_BUF_SIZE_IMMEDIATE 2
88 #define VIDEO_AVG_BUFFER_SIZE 600
94 struct video_capability capability
;
95 struct video_channel
*channels
;
97 struct video_tuner tuner
;
100 struct video_picture picture
;
101 int format
; /* output format */
107 struct video_mbuf mbuf
;
109 struct video_mmap
*buf
;
117 struct video_audio audio
[MAX_AUDIO_CHANNELS
];
118 int audio_channels
[MAX_AUDIO_CHANNELS
];
120 /* buffering stuff */
123 int audio_buffer_size
;
125 unsigned char *audio_ringbuffer
;
126 long long *audio_skew_buffer
;
127 volatile int audio_head
;
128 volatile int audio_tail
;
129 volatile int audio_cnt
;
130 volatile long long audio_skew
;
131 volatile double audio_skew_factor
;
132 volatile long long audio_skew_measure_time
;
133 volatile int audio_drop
;
136 int video_buffer_size_max
;
137 volatile int video_buffer_size_current
;
138 unsigned char **video_ringbuffer
;
139 long long *video_timebuffer
;
140 long long *video_avg_buffer
;
142 int video_interval_sum
;
143 volatile int video_head
;
144 volatile int video_tail
;
145 volatile int video_cnt
;
147 volatile int shutdown
;
149 pthread_t audio_grabber_thread
;
150 pthread_t video_grabber_thread
;
151 pthread_mutex_t audio_starter
;
152 pthread_mutex_t skew_mutex
;
153 pthread_mutex_t video_buffer_mutex
;
156 double audio_secs_per_block
;
157 long long audio_skew_total
;
158 long audio_recv_blocks_total
;
159 long audio_sent_blocks_total
;
165 pthread_t vbi_grabber_thread
;
168 tv_param_t
*tv_param
;
173 static const char *device_cap2name
[] = {
174 "capture", "tuner", "teletext", "overlay", "chromakey", "clipping",
175 "frameram", "scales", "monochrome", "subcapture", "mpeg-decoder",
176 "mpeg-encoder", "mjpeg-decoder", "mjpeg-encoder", NULL
179 static const char *device_palette2name
[] = {
180 "-", "grey", "hi240", "rgb16", "rgb24", "rgb32", "rgb15", "yuv422",
181 "yuyv", "uyvy", "yuv420", "yuv411", "raw", "yuv422p", "yuv411p",
184 #define PALETTE(x) ((x < sizeof(device_palette2name)/sizeof(char*)) ? device_palette2name[x] : "UNKNOWN")
186 static const struct {
193 } supported_norms
[]={
194 {"pal", TV_NORM_PAL
, VIDEO_TUNER_PAL
, VIDEO_MODE_PAL
, VIDEO_MODE_PAL
, PAL_FPS
},
195 {"ntsc", TV_NORM_NTSC
, VIDEO_TUNER_NTSC
, VIDEO_MODE_NTSC
, VIDEO_MODE_NTSC
, NTSC_FPS
},
196 {"secam", TV_NORM_SECAM
, VIDEO_TUNER_SECAM
, VIDEO_MODE_SECAM
,VIDEO_MODE_SECAM
,PAL_FPS
},
197 {"palnc", TV_NORM_PALNC
, VIDEO_TUNER_PAL
, VIDEO_MODE_PAL
, 3, PAL_FPS
},
198 {"palm", TV_NORM_PALM
, VIDEO_TUNER_NTSC
, VIDEO_MODE_NTSC
, 4, NTSC_FPS
},
199 {"paln", TV_NORM_PALN
, VIDEO_TUNER_PAL
, VIDEO_MODE_PAL
, 5, PAL_FPS
},
200 {"ntscjp",TV_NORM_NTSCJP
, VIDEO_TUNER_NTSC
, VIDEO_MODE_NTSC
, 6, NTSC_FPS
},
201 {"auto", -1, -1, -1, VIDEO_MODE_AUTO
, -1 },
202 {NULL
, -1, -1, -1, -1 }
205 static const char *norm2name(int mode
)
208 for(i
=0;supported_norms
[i
].name
; i
++)
209 if(supported_norms
[i
].input_norm
==mode
)
210 return supported_norms
[i
].name
;
214 static const char *audio_mode2name(int mode
)
217 case VIDEO_SOUND_MONO
:
219 case VIDEO_SOUND_STEREO
:
221 case VIDEO_SOUND_LANG1
:
223 case VIDEO_SOUND_LANG2
:
230 static void *audio_grabber(void *data
);
231 static void *video_grabber(void *data
);
233 static int palette2depth(int palette
)
238 case VIDEO_PALETTE_RGB555
:
240 case VIDEO_PALETTE_RGB565
:
242 case VIDEO_PALETTE_RGB24
:
244 case VIDEO_PALETTE_RGB32
:
247 case VIDEO_PALETTE_YUV411P
:
248 case VIDEO_PALETTE_YUV420P
:
249 case VIDEO_PALETTE_YUV410P
:
252 case VIDEO_PALETTE_YUV422P
:
253 case VIDEO_PALETTE_YUV422
:
254 case VIDEO_PALETTE_YUYV
:
255 case VIDEO_PALETTE_UYVY
:
256 case VIDEO_PALETTE_YUV420
:
257 case VIDEO_PALETTE_YUV411
:
263 static int format2palette(int format
)
268 return VIDEO_PALETTE_RGB555
;
270 return VIDEO_PALETTE_RGB565
;
272 return VIDEO_PALETTE_RGB24
;
274 return VIDEO_PALETTE_RGB32
;
277 return VIDEO_PALETTE_YUV420P
;
279 return VIDEO_PALETTE_YUV422
;
281 return VIDEO_PALETTE_UYVY
;
286 // sets and sanitizes audio buffer/block sizes
287 static void setup_audio_buffer_sizes(priv_t
*priv
)
289 int bytes_per_sample
= priv
->audio_in
.bytes_per_sample
;
291 // make the audio buffer at least 5 seconds long
292 priv
->audio_buffer_size
= 1 + 5*priv
->audio_in
.samplerate
293 *priv
->audio_in
.channels
294 *bytes_per_sample
/priv
->audio_in
.blocksize
;
295 if (priv
->audio_buffer_size
< 256) priv
->audio_buffer_size
= 256;
297 // make the skew buffer at least 1 second long
298 priv
->aud_skew_cnt
= 1 + 1*priv
->audio_in
.samplerate
299 *priv
->audio_in
.channels
300 *bytes_per_sample
/priv
->audio_in
.blocksize
;
301 if (priv
->aud_skew_cnt
< 16) priv
->aud_skew_cnt
= 16;
303 mp_msg(MSGT_TV
, MSGL_V
, "Audio capture - buffer %d blocks of %d bytes, skew average from %d meas.\n",
304 priv
->audio_buffer_size
, priv
->audio_in
.blocksize
, priv
->aud_skew_cnt
);
307 static tvi_handle_t
*tvi_init_v4l(tv_param_t
* tv_param
)
318 /* set video device name */
319 if (!tv_param
->device
)
320 priv
->video_device
= strdup("/dev/video0");
322 priv
->video_device
= strdup(tv_param
->device
);
324 /* set video device name */
325 if (!tv_param
->adevice
)
326 priv
->audio_device
= NULL
;
328 priv
->audio_device
= strdup(tv_param
->adevice
);
331 /* allocation failed */
332 if (!priv
->video_device
) {
337 priv
->tv_param
=tv_param
;
341 /* retrieves info about audio channels from the BTTV */
342 static void init_v4l_audio(priv_t
*priv
)
347 if (!priv
->capability
.audios
) return;
351 mp_msg(MSGT_TV
, MSGL_V
, " Audio devices: %d\n", priv
->capability
.audios
);
353 mp_msg(MSGT_TV
, MSGL_V
, "Video capture card reports the audio setup as follows:\n");
354 for (i
= 0; i
< priv
->capability
.audios
; i
++)
356 if (i
>= MAX_AUDIO_CHANNELS
)
358 mp_msg(MSGT_TV
, MSGL_ERR
, "no space for more audio channels (increase in source!) (%d > %d)\n",
359 i
, MAX_AUDIO_CHANNELS
);
360 i
= priv
->capability
.audios
;
364 priv
->audio
[i
].audio
= i
;
365 if (ioctl(priv
->video_fd
, VIDIOCGAUDIO
, &priv
->audio
[i
]) == -1)
367 mp_msg(MSGT_TV
, MSGL_ERR
, "ioctl get audio failed: %s\n", strerror(errno
));
371 /* mute all channels */
372 priv
->audio
[i
].flags
|= VIDEO_AUDIO_MUTE
;
374 if (priv
->tv_param
->amode
>= 0) {
375 switch (priv
->tv_param
->amode
) {
377 reqmode
= VIDEO_SOUND_MONO
;
380 reqmode
= VIDEO_SOUND_STEREO
;
383 reqmode
= VIDEO_SOUND_LANG1
;
386 reqmode
= VIDEO_SOUND_LANG2
;
389 mp_msg(MSGT_TV
, MSGL_ERR
, "Unknown audio mode requested.\n");
392 if (reqmode
>= 0) priv
->audio
[i
].mode
= reqmode
;
394 ioctl(priv
->video_fd
, VIDIOCSAUDIO
, &priv
->audio
[i
]);
396 // get the parameters back
397 if (ioctl(priv
->video_fd
, VIDIOCGAUDIO
, &priv
->audio
[i
]) == -1)
399 mp_msg(MSGT_TV
, MSGL_ERR
, "ioctl get audio failed: %s\n", strerror(errno
));
403 switch(priv
->audio
[i
].mode
)
405 case VIDEO_SOUND_MONO
:
406 case VIDEO_SOUND_LANG1
:
407 case VIDEO_SOUND_LANG2
:
408 priv
->audio_channels
[i
] = 1;
410 case VIDEO_SOUND_STEREO
:
411 priv
->audio_channels
[i
] = 2;
414 mp_msg(MSGT_TV
, MSGL_ERR
, "Card reports an unknown audio mode !\n");
415 mp_msg(MSGT_TV
, MSGL_ERR
, "Trying two channel audio. Use forcechan to override.\n");
416 priv
->audio_channels
[i
] = 2;
420 if (reqmode
>= 0 && priv
->audio
[i
].mode
!= reqmode
) {
421 mp_msg(MSGT_TV
, MSGL_ERR
, "Audio mode setup warning!\n");
422 mp_msg(MSGT_TV
, MSGL_ERR
, "Requested mode was %s, but v4l still reports %s.\n",
423 audio_mode2name(reqmode
), audio_mode2name(priv
->audio
[i
].mode
));
424 mp_msg(MSGT_TV
, MSGL_ERR
, "You may need \"forcechan\" option to force stereo/mono audio recording.\n");
428 mp_msg(MSGT_TV
, MSGL_V
, " %d: %s: ", priv
->audio
[i
].audio
,
429 priv
->audio
[i
].name
);
430 if (priv
->audio
[i
].flags
& VIDEO_AUDIO_MUTABLE
) {
431 mp_msg(MSGT_TV
, MSGL_V
, "muted=%s ",
432 (priv
->audio
[i
].flags
& VIDEO_AUDIO_MUTE
) ? "yes" : "no");
434 mp_msg(MSGT_TV
, MSGL_V
, "vol=%d bass=%d treble=%d balance=%d mode=%s",
435 priv
->audio
[i
].volume
, priv
->audio
[i
].bass
, priv
->audio
[i
].treble
,
436 priv
->audio
[i
].balance
, audio_mode2name(priv
->audio
[i
].mode
));
437 mp_msg(MSGT_TV
, MSGL_V
, " chan=%d\n", priv
->audio_channels
[i
]);
439 if (priv
->tv_param
->forcechan
>= 0)
440 priv
->audio_channels
[i
] = priv
->tv_param
->forcechan
;
442 // we'll call VIDIOCSAUDIO again when starting capture
443 // let's set audio mode to requested mode again for the case
444 // when VIDIOCGAUDIO just cannot report the mode correctly
445 if (reqmode
>= 0) priv
->audio
[i
].mode
= reqmode
;
449 #if !defined(__LINUX_VIDEODEV2_H) && !defined(VIDIOC_QUERYCAP)
450 struct v4l2_capability
452 __u8 driver
[16]; /* i.e. "bttv" */
453 __u8 card
[32]; /* i.e. "Hauppauge WinTV" */
454 __u8 bus_info
[32]; /* "PCI:" + pci_dev->slot_name */
455 __u32 version
; /* should use KERNEL_VERSION() */
456 __u32 capabilities
; /* Device capabilities */
460 #define VIDIOC_QUERYCAP _IOR ('V', 0, struct v4l2_capability)
463 static int init(priv_t
*priv
)
467 if (priv
->tv_param
->immediate
== 1)
468 priv
->tv_param
->noaudio
= 1;
470 priv
->video_ringbuffer
= NULL
;
471 priv
->video_timebuffer
= NULL
;
472 priv
->video_avg_buffer
= NULL
;
473 priv
->audio_ringbuffer
= NULL
;
474 priv
->audio_skew_buffer
= NULL
;
476 priv
->video_fd
= open(priv
->video_device
, O_RDWR
);
477 mp_msg(MSGT_TV
, MSGL_DBG2
, "Video fd: %d, %p\n", priv
->video_fd
,
479 if (priv
->video_fd
== -1)
481 mp_msg(MSGT_TV
, MSGL_ERR
, "unable to open '%s': %s\n",
482 priv
->video_device
, strerror(errno
));
487 if (ioctl(priv
->video_fd
, VIDIOC_QUERYCAP
, &priv
->capability
) == 0) {
488 mp_msg(MSGT_TV
, MSGL_ERR
, "=================================================================\n");
489 mp_msg(MSGT_TV
, MSGL_ERR
, " WARNING: YOU ARE USING V4L DEMUXER WITH V4L2 DRIVERS!!!\n");
490 mp_msg(MSGT_TV
, MSGL_ERR
, " As the V4L1 compatibility layer is broken, this may not work.\n");
491 mp_msg(MSGT_TV
, MSGL_ERR
, " If you encounter any problems, use driver=v4l2 instead.\n");
492 mp_msg(MSGT_TV
, MSGL_ERR
, " Bugreports on driver=v4l with v4l2 drivers will be ignored.\n");
493 mp_msg(MSGT_TV
, MSGL_ERR
, "=================================================================\n");
496 /* get capabilities (priv->capability is needed!) */
497 if (ioctl(priv
->video_fd
, VIDIOCGCAP
, &priv
->capability
) == -1)
499 mp_msg(MSGT_TV
, MSGL_ERR
, "ioctl get capabilites failed: %s\n", strerror(errno
));
503 fcntl(priv
->video_fd
, F_SETFD
, FD_CLOEXEC
);
505 mp_msg(MSGT_TV
, MSGL_INFO
, "Selected device: %s\n", priv
->capability
.name
);
506 mp_msg(MSGT_TV
, MSGL_INFO
, " Capabilites: ");
507 for (i
= 0; device_cap2name
[i
] != NULL
; i
++)
508 if (priv
->capability
.type
& (1 << i
))
509 mp_msg(MSGT_TV
, MSGL_INFO
, "%s ", device_cap2name
[i
]);
510 mp_msg(MSGT_TV
, MSGL_INFO
, "\n");
511 mp_msg(MSGT_TV
, MSGL_INFO
, " Device type: %d\n", priv
->capability
.type
);
512 mp_msg(MSGT_TV
, MSGL_INFO
, " Supported sizes: %dx%d => %dx%d\n",
513 priv
->capability
.minwidth
, priv
->capability
.minheight
,
514 priv
->capability
.maxwidth
, priv
->capability
.maxheight
);
515 priv
->width
= priv
->capability
.minwidth
;
516 priv
->height
= priv
->capability
.minheight
;
518 /* somewhere here could disable priv->tv_param->mjpeg, if it is not a capability */
520 /* initialize if necessary */
521 if ( priv
->tv_param
->mjpeg
)
523 struct mjpeg_params bparm
;
524 struct mjpeg_requestbuffers breq
; /* buffer requests */
526 if (ioctl(priv
->video_fd
, MJPIOC_G_PARAMS
, &bparm
) < 0)
528 mp_msg(MSGT_TV
, MSGL_ERR
,
529 " MJP: Error getting video parameters: %s\n", strerror(errno
));
533 mp_msg(MSGT_TV
, MSGL_INFO
,
534 " MJP: previous params: x: %d, y: %d, w: %d, h: %d, decim: %d, fields: %d,\n",
535 bparm
.img_x
, bparm
.img_y
, bparm
.img_width
, bparm
.img_height
,
536 bparm
.decimation
, bparm
.field_per_buff
);
538 mp_msg(MSGT_TV
, MSGL_INFO
,
539 " MJP: HorDcm: %d, VerDcm: %d, TmpDcm: %d\n",
540 bparm
.HorDcm
, bparm
.VerDcm
, bparm
.TmpDcm
);
542 bparm
.input
= priv
->tv_param
->input
; /* tv */
543 if (!strcasecmp(priv
->tv_param
->norm
, "pal"))
544 bparm
.norm
= 0; /* PAL */
545 else if (!strcasecmp(priv
->tv_param
->norm
, "ntsc"))
546 bparm
.norm
= 1; /* NTSC */
547 else if (!strcasecmp(priv
->tv_param
->norm
, "secam"))
548 bparm
.norm
= 2; /* SECAM */
549 bparm
.quality
= priv
->tv_param
->quality
;
550 bparm
.decimation
= priv
->tv_param
->decimation
;
552 mp_msg(MSGT_TV
, MSGL_INFO
, " MJP: setting params to decimation: %d, quality: %d\n",
553 bparm
.decimation
, bparm
.quality
);
555 if (ioctl(priv
->video_fd
, MJPIOC_S_PARAMS
, &bparm
) < 0)
557 mp_msg(MSGT_TV
, MSGL_ERR
,
558 " MJP: Error setting video parameters: %s\n", strerror(errno
));
562 if (ioctl(priv
->video_fd
, MJPIOC_G_PARAMS
, &bparm
) < 0)
564 mp_msg(MSGT_TV
, MSGL_ERR
,
565 " MJP: Error getting video parameters: %s\n", strerror(errno
));
569 mp_msg(MSGT_TV
, MSGL_INFO
,
570 " MJP: current params: x: %d, y: %d, w: %d, h: %d, decim: %d, fields: %d,\n",
571 bparm
.img_x
, bparm
.img_y
, bparm
.img_width
, bparm
.img_height
,
572 bparm
.decimation
, bparm
.field_per_buff
);
574 mp_msg(MSGT_TV
, MSGL_INFO
,
575 " MJP: HorDcm: %d, VerDcm: %d, TmpDcm: %d\n",
576 bparm
.HorDcm
, bparm
.VerDcm
, bparm
.TmpDcm
);
580 priv
-> nbuf
= breq
.count
;
581 priv
->mbuf
.frames
= priv
-> nbuf
;
582 priv
->mjpeg_bufsize
= 256*1024;
583 if (priv
->tv_param
->buffer_size
>= 0)
584 priv
->mjpeg_bufsize
= priv
->tv_param
->buffer_size
*1024;
585 breq
.size
= priv
-> mjpeg_bufsize
;
586 if (ioctl(priv
->video_fd
, MJPIOC_REQBUFS
,&(breq
)) < 0)
588 mp_msg (MSGT_TV
, MSGL_ERR
,
589 " MJP: Error requesting video buffers: %s\n", strerror(errno
));
592 mp_msg(MSGT_TV
, MSGL_INFO
,
593 " MJP: Got %ld buffers of size %ld KB\n",
594 breq
.count
, breq
.size
/1024);
596 priv
-> mmap
= mmap(0, breq
.count
* breq
.size
,
597 PROT_READ
|PROT_WRITE
, MAP_SHARED
, priv
->video_fd
, 0);
598 if (priv
-> mmap
== MAP_FAILED
)
600 mp_msg(MSGT_TV
, MSGL_INFO
,
601 " MJP: Error mapping video buffers: %s\n", strerror(errno
));
606 mp_msg(MSGT_TV
, MSGL_INFO
, " Inputs: %d\n", priv
->capability
.channels
);
607 priv
->channels
= calloc(priv
->capability
.channels
, sizeof(struct video_channel
));
610 memset(priv
->channels
, 0, sizeof(struct video_channel
)*priv
->capability
.channels
);
611 for (i
= 0; i
< priv
->capability
.channels
; i
++)
613 priv
->channels
[i
].channel
= i
;
614 if (ioctl(priv
->video_fd
, VIDIOCGCHAN
, &priv
->channels
[i
]) == -1)
616 mp_msg(MSGT_TV
, MSGL_ERR
, "ioctl get channel failed: %s\n", strerror(errno
));
619 mp_msg(MSGT_TV
, MSGL_INFO
, " %d: %s: %s%s%s%s (tuner:%d, norm:%s)\n", i
,
620 priv
->channels
[i
].name
,
621 (priv
->channels
[i
].flags
& VIDEO_VC_TUNER
) ? "tuner " : "",
622 (priv
->channels
[i
].flags
& VIDEO_VC_AUDIO
) ? "audio " : "",
623 (priv
->channels
[i
].flags
& VIDEO_TYPE_TV
) ? "tv " : "",
624 (priv
->channels
[i
].flags
& VIDEO_TYPE_CAMERA
) ? "camera " : "",
625 priv
->channels
[i
].tuners
,
626 norm2name(priv
->channels
[i
].norm
));
628 priv
->act_channel
= 0;
630 if (!(priv
->capability
.type
& VID_TYPE_CAPTURE
))
632 mp_msg(MSGT_TV
, MSGL_ERR
, "Only grabbing supported (for overlay use another program)\n");
637 /* init v4l audio even when we don't capture */
638 init_v4l_audio(priv
);
640 if (!priv
->capability
.audios
&& !priv
->tv_param
->force_audio
) priv
->tv_param
->noaudio
= 1;
643 if (!priv
->tv_param
->noaudio
) {
646 if (priv
->tv_param
->alsa
)
647 audio_in_init(&priv
->audio_in
, AUDIO_IN_ALSA
);
649 audio_in_init(&priv
->audio_in
, AUDIO_IN_OSS
);
651 audio_in_init(&priv
->audio_in
, AUDIO_IN_OSS
);
654 if (priv
->audio_device
) {
655 audio_in_set_device(&priv
->audio_in
, priv
->audio_device
);
658 if (priv
->tv_param
->audio_id
< priv
->capability
.audios
)
659 priv
->audio_id
= priv
->tv_param
->audio_id
;
662 audio_in_set_samplerate(&priv
->audio_in
, 44100);
663 if (priv
->capability
.audios
) {
664 audio_in_set_channels(&priv
->audio_in
, priv
->audio_channels
[priv
->audio_id
]);
666 if (priv
->tv_param
->forcechan
>= 0) {
667 audio_in_set_channels(&priv
->audio_in
, priv
->tv_param
->forcechan
);
669 audio_in_set_channels(&priv
->audio_in
, 2);
672 if (audio_in_setup(&priv
->audio_in
) < 0) return 0;
673 setup_audio_buffer_sizes(priv
);
680 free(priv
->channels
);
684 if (priv
->video_fd
!= -1)
685 close(priv
->video_fd
);
689 static int uninit(priv_t
*priv
)
693 priv
->vbi_shutdown
=1;
694 if(priv
->vbi_grabber_thread
)
695 pthread_join(priv
->vbi_grabber_thread
, NULL
);
697 teletext_control(priv
->priv_vbi
,TV_VBI_CONTROL_STOP
,(void*)1);
712 mp_msg(MSGT_TV
, MSGL_V
, "Waiting for threads to finish... ");
713 if (!priv
->tv_param
->noaudio
) {
714 pthread_join(priv
->audio_grabber_thread
, NULL
);
715 pthread_mutex_destroy(&priv
->audio_starter
);
716 pthread_mutex_destroy(&priv
->skew_mutex
);
718 pthread_mutex_destroy(&priv
->video_buffer_mutex
);
719 if(priv
->video_grabber_thread
)
720 pthread_join(priv
->video_grabber_thread
, NULL
);
722 mp_msg(MSGT_TV
, MSGL_V
, "done\n");
724 if (priv
->capability
.audios
) {
725 priv
->audio
[priv
->audio_id
].flags
|= VIDEO_AUDIO_MUTE
;
726 ioctl(priv
->video_fd
, VIDIOCSAUDIO
, &priv
->audio
[priv
->audio_id
]);
729 if ( priv
->tv_param
->mjpeg
)
732 if (ioctl(priv
->video_fd
, MJPIOC_QBUF_CAPT
, &num
) < 0)
733 mp_msg(MSGT_TV
, MSGL_ERR
, "\n MJP: ioctl MJPIOC_QBUF_CAPT failed: %s\n", strerror(errno
));
737 // We need to munmap as close don't close mem mappings
738 if(munmap(priv
->mmap
,priv
->mbuf
.size
))
739 mp_msg(MSGT_TV
, MSGL_ERR
, "Munmap failed: %s\n",strerror(errno
));
742 if(close(priv
->video_fd
))
743 mp_msg(MSGT_TV
, MSGL_ERR
, "Close tv failed: %s\n",strerror(errno
));
745 audio_in_uninit(&priv
->audio_in
);
747 if (priv
->video_ringbuffer
) {
749 for (i
= 0; i
< priv
->video_buffer_size_current
; i
++) {
750 free(priv
->video_ringbuffer
[i
]);
752 free(priv
->video_ringbuffer
);
755 if (priv
->video_timebuffer
)
756 free(priv
->video_timebuffer
);
757 if (priv
->video_avg_buffer
)
758 free(priv
->video_avg_buffer
);
759 if (!priv
->tv_param
->noaudio
) {
760 if (priv
->audio_ringbuffer
)
761 free(priv
->audio_ringbuffer
);
762 if (priv
->audio_skew_buffer
)
763 free(priv
->audio_skew_buffer
);
769 static int get_capture_buffer_size(priv_t
*priv
)
773 if (priv
->tv_param
->buffer_size
>= 0) {
774 bufsize
= priv
->tv_param
->buffer_size
*1024*1024;
776 #ifdef HAVE_SYS_SYSINFO_H
780 if (si
.totalram
<2*1024*1024) {
783 bufsize
= si
.totalram
/2;
786 bufsize
= 16*1024*1024;
790 cnt
= bufsize
/(priv
->height
*priv
->bytesperline
);
791 if (cnt
< 2) cnt
= 2;
796 static int vbi_init(priv_t
* priv
,char* device
)
799 struct video_capability cap
;
802 return TVI_CONTROL_FALSE
;
804 priv
->vbi_dev
=strdup(device
);
806 vbi_fd
=open(priv
->vbi_dev
,O_RDWR
);
808 mp_msg(MSGT_TV
,MSGL_ERR
,"vbi: could not open device %s\n",priv
->vbi_dev
);
809 return TVI_CONTROL_FALSE
;
812 if(ioctl(vbi_fd
,VIDIOCGCAP
,&cap
)<0){
813 mp_msg(MSGT_TV
,MSGL_ERR
,"vbi: Query capatibilities failed for %s\n",priv
->vbi_dev
);
815 return TVI_CONTROL_FALSE
;
817 if(!cap
.type
& VID_TYPE_CAPTURE
){
818 mp_msg(MSGT_TV
,MSGL_ERR
,"vbi: %s is not capture device\n",priv
->vbi_dev
);
820 return TVI_CONTROL_FALSE
;
824 mp_msg(MSGT_TV
,MSGL_DBG3
,"vbi: init ok\n");
825 return TVI_CONTROL_TRUE
;
828 static int vbi_get_props(priv_t
* priv
,tt_stream_props
* ptsp
)
830 struct vbi_format fmt
;
833 return TVI_CONTROL_FALSE
;
835 memset(&fmt
,0,sizeof(struct vbi_format
));
836 if((res
=ioctl(priv
->vbi_fd
,VIDIOCGVBIFMT
,&fmt
))<0){
837 mp_msg(MSGT_TV
,MSGL_ERR
,"vbi_get_props: Query format failed: %x\n",res
);
838 return TVI_CONTROL_FALSE
;
841 ptsp
->interlaced
=(fmt
.flags
& VBI_INTERLACED
?1:0);
842 if(fmt
.start
[1]>0 && fmt
.count
[1]){
843 if(fmt
.start
[1]>=286)
845 ptsp
->offset
=10.2e-6*fmt
.sampling_rate
;
848 ptsp
->offset
=9.2e-6*fmt
.sampling_rate
;
850 ptsp
->offset
=9.7e-6*fmt
.sampling_rate
;
852 ptsp
->sampling_rate
=fmt
.sampling_rate
;
853 ptsp
->samples_per_line
=fmt
.samples_per_line
,
855 ptsp
->count
[0]=fmt
.count
[0];
856 ptsp
->count
[1]=fmt
.count
[1];
857 ptsp
->bufsize
= ptsp
->samples_per_line
* (ptsp
->count
[0] + ptsp
->count
[1]);
859 mp_msg(MSGT_TV
,MSGL_V
,"vbi_get_props: sampling_rate=%d,offset:%d,samples_per_line: %d\n interlaced:%s, count=[%d,%d]\n",
862 ptsp
->samples_per_line
,
863 ptsp
->interlaced
?"Yes":"No",
867 return TVI_CONTROL_TRUE
;
870 static void *vbi_grabber(void *data
)
872 priv_t
*priv
= (priv_t
*) data
;
873 int bytes
,seq
,prev_seq
;
878 mp_msg(MSGT_TV
,MSGL_WARN
,"vbi: vbi not initialized. stopping thread.\n");
882 if(vbi_get_props(priv
,&tsp
)!=TVI_CONTROL_TRUE
)
885 buf
=malloc(tsp
.bufsize
);
888 mp_msg(MSGT_TV
,MSGL_V
,"vbi: vbi capture thread started.\n");
890 while (!priv
->vbi_shutdown
){
891 bytes
=read(priv
->vbi_fd
,buf
,tsp
.bufsize
);
892 if(bytes
<0 && errno
==EINTR
)
894 if (bytes
!=tsp
.bufsize
){
895 mp_msg(MSGT_TV
,MSGL_WARN
,"vbi: expecting bytes: %d, got: %d",tsp
.bufsize
,bytes
);
898 seq
=*(int*)(buf
+bytes
-4);
900 if (prev_seq
&& seq
!=prev_seq
+1){
905 teletext_control(priv
->priv_vbi
,TV_VBI_CONTROL_DECODE_PAGE
,&buf
);
906 mp_msg(MSGT_TV
,MSGL_DBG3
,"grabber: seq:%d\n",seq
);
912 static int start(priv_t
*priv
)
915 int bytes_per_sample
;
916 struct video_window win
;
918 if (ioctl(priv
->video_fd
, VIDIOCGPICT
, &priv
->picture
) == -1)
920 mp_msg(MSGT_TV
, MSGL_ERR
, "ioctl get picture failed: %s\n", strerror(errno
));
924 priv
->picture
.palette
= format2palette(priv
->format
);
925 priv
->picture
.depth
= palette2depth(priv
->picture
.palette
);
927 if (priv
->format
!= IMGFMT_BGR15
) {
928 priv
->bytesperline
= priv
->width
* priv
->picture
.depth
/ 8;
930 priv
->bytesperline
= priv
->width
* 2;
933 mp_msg(MSGT_TV
, MSGL_V
, "Picture values:\n");
934 mp_msg(MSGT_TV
, MSGL_V
, " Depth: %d, Palette: %s (Format: %s)\n", priv
->picture
.depth
,
935 PALETTE(priv
->picture
.palette
), vo_format_name(priv
->format
));
936 mp_msg(MSGT_TV
, MSGL_V
, " Brightness: %d, Hue: %d, Colour: %d, Contrast: %d\n",
937 priv
->picture
.brightness
, priv
->picture
.hue
,
938 priv
->picture
.colour
, priv
->picture
.contrast
);
940 if (ioctl(priv
->video_fd
, VIDIOCSPICT
, &priv
->picture
) == -1)
942 mp_msg(MSGT_TV
, MSGL_ERR
, "ioctl set picture failed: %s\n", strerror(errno
));
943 mp_msg(MSGT_TV
, MSGL_ERR
, "The 'outfmt' of '%s' is likely not supported by your card\n",
944 vo_format_name(priv
->format
));
948 /* Set capture size */
951 win
.width
= priv
->width
;
952 win
.height
= priv
->height
;
956 if (ioctl(priv
->video_fd
, VIDIOCSWIN
, &win
) == -1)
957 mp_msg(MSGT_TV
, MSGL_ERR
, "ioctl set window failed: %s\n", strerror(errno
));
959 if ( !priv
->tv_param
->mjpeg
)
961 /* map grab buffer */
962 if (ioctl(priv
->video_fd
, VIDIOCGMBUF
, &priv
->mbuf
) == -1)
964 mp_msg(MSGT_TV
, MSGL_ERR
, "ioctl get mbuf failed: %s\n", strerror(errno
));
968 mp_msg(MSGT_TV
, MSGL_V
, "mbuf: size=%d, frames=%d\n",
969 priv
->mbuf
.size
, priv
->mbuf
.frames
);
970 priv
->mmap
= mmap(0, priv
->mbuf
.size
, PROT_READ
|PROT_WRITE
,
971 MAP_SHARED
, priv
->video_fd
, 0);
972 if (priv
->mmap
== (unsigned char *)-1)
974 mp_msg(MSGT_TV
, MSGL_ERR
, "Unable to map memory for buffers: %s\n", strerror(errno
));
977 mp_msg(MSGT_TV
, MSGL_DBG2
, "our buffer: %p\n", priv
->mmap
);
980 priv
->nbuf
= priv
->mbuf
.frames
;
983 priv
->buf
= calloc(priv
->nbuf
, sizeof(struct video_mmap
));
986 memset(priv
->buf
, 0, priv
->nbuf
* sizeof(struct video_mmap
));
989 if ( !priv
->tv_param
->mjpeg
)
991 priv
->nbuf
= priv
->mbuf
.frames
;
992 for (i
=0; i
< priv
->nbuf
; i
++)
994 priv
->buf
[i
].format
= priv
->picture
.palette
;
995 priv
->buf
[i
].frame
= i
;
996 priv
->buf
[i
].width
= priv
->width
;
997 priv
->buf
[i
].height
= priv
->height
;
998 mp_msg(MSGT_TV
, MSGL_DBG2
, "buffer: %d => %p\n", i
, &priv
->buf
[i
]);
1004 struct video_play_mode pmode
;
1006 pmode
.mode
= VID_PLAY_NORMAL
;
1009 if (ioctl(priv
->video_fd
, VIDIOCSPLAYMODE
, &pmode
) == -1)
1011 mp_msg(MSGT_TV
, MSGL_ERR
, "ioctl set play mode failed: %s\n", strerror(errno
));
1018 // initialize video capture
1019 if (ioctl(priv
->video_fd
, VIDIOCCAPTURE
, &one
) == -1)
1021 mp_msg(MSGT_TV
, MSGL_ERR
, "FATAL: ioctl ccapture failed: %s\n", strerror(errno
));
1026 /* setup audio parameters */
1027 if (!priv
->tv_param
->noaudio
) {
1028 setup_audio_buffer_sizes(priv
);
1029 bytes_per_sample
= priv
->audio_in
.bytes_per_sample
;
1030 priv
->audio_skew_buffer
= calloc(priv
->aud_skew_cnt
, sizeof(long long));
1031 if (!priv
->audio_skew_buffer
) {
1032 mp_msg(MSGT_TV
, MSGL_ERR
, "cannot allocate skew buffer: %s\n", strerror(errno
));
1036 priv
->audio_ringbuffer
= calloc(priv
->audio_in
.blocksize
, priv
->audio_buffer_size
);
1037 if (!priv
->audio_ringbuffer
) {
1038 mp_msg(MSGT_TV
, MSGL_ERR
, "cannot allocate audio buffer: %s\n", strerror(errno
));
1042 priv
->audio_secs_per_block
= (double)priv
->audio_in
.blocksize
/(priv
->audio_in
.samplerate
1043 *priv
->audio_in
.channels
1045 priv
->audio_head
= 0;
1046 priv
->audio_tail
= 0;
1047 priv
->audio_cnt
= 0;
1048 priv
->audio_drop
= 0;
1049 priv
->audio_skew
= 0;
1050 priv
->audio_skew_total
= 0;
1051 priv
->audio_recv_blocks_total
= 0;
1052 priv
->audio_sent_blocks_total
= 0;
1055 /* setup video parameters */
1056 if (priv
->immediate_mode
) {
1057 priv
->video_buffer_size_max
= VID_BUF_SIZE_IMMEDIATE
;
1059 priv
->video_buffer_size_max
= get_capture_buffer_size(priv
);
1061 priv
->video_buffer_size_current
= 0;
1063 if (!priv
->tv_param
->noaudio
) {
1064 if (priv
->video_buffer_size_max
< 3.0*priv
->fps
*priv
->audio_secs_per_block
) {
1065 mp_msg(MSGT_TV
, MSGL_ERR
, "Video buffer shorter than 3 times audio frame duration.\n"
1066 "You will probably experience heavy framedrops.\n");
1070 mp_msg(MSGT_TV
, MSGL_V
, "Using a ring buffer for maximum %d frames, %d MB total size.\n",
1071 priv
->video_buffer_size_max
,
1072 priv
->video_buffer_size_max
*priv
->height
*priv
->bytesperline
/(1024*1024));
1074 priv
->video_ringbuffer
= calloc(priv
->video_buffer_size_max
, sizeof(unsigned char*));
1075 if (!priv
->video_ringbuffer
) {
1076 mp_msg(MSGT_TV
, MSGL_ERR
, "cannot allocate video buffer: %s\n", strerror(errno
));
1079 for (i
= 0; i
< priv
->video_buffer_size_max
; i
++)
1080 priv
->video_ringbuffer
[i
] = NULL
;
1082 priv
->video_timebuffer
= calloc(priv
->video_buffer_size_max
, sizeof(long long));
1083 if (!priv
->video_timebuffer
) {
1084 mp_msg(MSGT_TV
, MSGL_ERR
, "cannot allocate time buffer: %s\n", strerror(errno
));
1087 priv
->video_avg_buffer
= malloc(sizeof(long long) * VIDEO_AVG_BUFFER_SIZE
);
1088 if (!priv
->video_avg_buffer
) {
1089 mp_msg(MSGT_TV
, MSGL_ERR
, "cannot allocate period buffer: %s\n", strerror(errno
));
1092 priv
->video_interval_sum
= (1e6
/priv
->fps
)*VIDEO_AVG_BUFFER_SIZE
;
1093 for (i
= 0; i
< VIDEO_AVG_BUFFER_SIZE
; i
++) {
1094 priv
->video_avg_buffer
[i
] = 1e6
/priv
->fps
;
1097 priv
->video_avg_ptr
= 0;
1099 priv
->video_head
= 0;
1100 priv
->video_tail
= 0;
1101 priv
->video_cnt
= 0;
1104 if (priv
->capability
.audios
) {
1106 if (priv
->tv_param
->volume
>= 0)
1107 priv
->audio
[priv
->audio_id
].volume
= priv
->tv_param
->volume
;
1108 if (priv
->tv_param
->bass
>= 0)
1109 priv
->audio
[priv
->audio_id
].bass
= priv
->tv_param
->bass
;
1110 if (priv
->tv_param
->treble
>= 0)
1111 priv
->audio
[priv
->audio_id
].treble
= priv
->tv_param
->treble
;
1112 if (priv
->tv_param
->balance
>= 0)
1113 priv
->audio
[priv
->audio_id
].balance
= priv
->tv_param
->balance
;
1114 priv
->audio
[priv
->audio_id
].flags
&= ~VIDEO_AUDIO_MUTE
;
1115 mp_msg(MSGT_TV
, MSGL_V
, "Enabling tv audio. Requested setup is:\n");
1116 mp_msg(MSGT_TV
, MSGL_V
, "id=%d vol=%d bass=%d treble=%d balance=%d mode=%s",
1118 priv
->audio
[priv
->audio_id
].volume
, priv
->audio
[priv
->audio_id
].bass
, priv
->audio
[priv
->audio_id
].treble
,
1119 priv
->audio
[priv
->audio_id
].balance
, audio_mode2name(priv
->audio
[priv
->audio_id
].mode
));
1120 mp_msg(MSGT_TV
, MSGL_V
, " chan=%d\n", priv
->audio_channels
[priv
->audio_id
]);
1121 ioctl(priv
->video_fd
, VIDIOCSAUDIO
, &priv
->audio
[priv
->audio_id
]);
1124 /* start vbi thread */
1126 priv
->vbi_shutdown
= 0;
1127 pthread_create(&priv
->vbi_grabber_thread
, NULL
, vbi_grabber
, priv
);
1130 /* launch capture threads */
1132 if (!priv
->tv_param
->noaudio
) {
1133 pthread_mutex_init(&priv
->audio_starter
, NULL
);
1134 pthread_mutex_init(&priv
->skew_mutex
, NULL
);
1135 pthread_mutex_lock(&priv
->audio_starter
);
1136 pthread_create(&priv
->audio_grabber_thread
, NULL
, audio_grabber
, priv
);
1138 pthread_mutex_init(&priv
->video_buffer_mutex
, NULL
);
1139 /* we'll launch the video capture later, when a first request for a frame arrives */
1145 static int control(priv_t
*priv
, int cmd
, void *arg
)
1147 mp_msg(MSGT_TV
, MSGL_DBG2
, "\ndebug: control(priv=%p, cmd=%d, arg=%p)\n",
1151 /* ========== GENERIC controls =========== */
1152 case TVI_CONTROL_IS_VIDEO
:
1154 if (priv
->capability
.type
& VID_TYPE_CAPTURE
)
1155 return TVI_CONTROL_TRUE
;
1156 return TVI_CONTROL_FALSE
;
1158 case TVI_CONTROL_IS_AUDIO
:
1159 if (priv
->tv_param
->force_audio
) return TVI_CONTROL_TRUE
;
1160 if (priv
->channels
[priv
->act_channel
].flags
& VIDEO_VC_AUDIO
)
1162 return TVI_CONTROL_TRUE
;
1164 return TVI_CONTROL_FALSE
;
1165 case TVI_CONTROL_IS_TUNER
:
1167 // if (priv->capability.type & VID_TYPE_TUNER)
1168 if (priv
->channels
[priv
->act_channel
].flags
& VIDEO_VC_TUNER
)
1169 return TVI_CONTROL_TRUE
;
1170 return TVI_CONTROL_FALSE
;
1173 /* ========== VIDEO controls =========== */
1174 case TVI_CONTROL_VID_GET_FORMAT
:
1176 int output_fmt
= -1;
1178 output_fmt
= priv
->format
;
1179 if ( priv
->tv_param
->mjpeg
)
1181 mp_msg(MSGT_TV
, MSGL_INFO
, " MJP: setting sh_video->format to mjpg\n");
1182 output_fmt
= 0x47504a4d;
1183 output_fmt
= 0x67706a6d;
1184 *(int *)arg
= output_fmt
;
1185 mp_msg(MSGT_TV
, MSGL_V
, "Output format: %s\n", "mjpg");
1189 *(int *)arg
= output_fmt
;
1190 mp_msg(MSGT_TV
, MSGL_V
, "Output format: %s\n", vo_format_name(output_fmt
));
1192 return TVI_CONTROL_TRUE
;
1194 case TVI_CONTROL_VID_SET_FORMAT
:
1195 priv
->format
= *(int *)arg
;
1196 // !HACK! v4l uses BGR format instead of RGB
1197 // and we have to correct this. Fortunately,
1198 // tv.c reads later the format back so we
1199 // can persuade it to use what we want.
1200 if (IMGFMT_IS_RGB(priv
->format
)) {
1201 priv
->format
&= ~IMGFMT_RGB_MASK
;
1202 priv
->format
|= IMGFMT_BGR
;
1204 return TVI_CONTROL_TRUE
;
1205 case TVI_CONTROL_VID_GET_PLANES
:
1206 *(int *)arg
= 1; /* FIXME, also not needed at this time */
1207 return TVI_CONTROL_TRUE
;
1208 case TVI_CONTROL_VID_GET_BITS
:
1209 *(int *)arg
= palette2depth(format2palette(priv
->format
));
1210 return TVI_CONTROL_TRUE
;
1211 case TVI_CONTROL_VID_GET_WIDTH
:
1212 *(int *)arg
= priv
->width
;
1213 return TVI_CONTROL_TRUE
;
1214 case TVI_CONTROL_VID_CHK_WIDTH
:
1216 int req_width
= *(int *)arg
;
1218 mp_msg(MSGT_TV
, MSGL_V
, "Requested width: %d\n", req_width
);
1219 if ((req_width
>= priv
->capability
.minwidth
) &&
1220 (req_width
<= priv
->capability
.maxwidth
))
1221 return TVI_CONTROL_TRUE
;
1222 return TVI_CONTROL_FALSE
;
1224 case TVI_CONTROL_VID_SET_WIDTH
:
1225 priv
->width
= *(int *)arg
;
1226 return TVI_CONTROL_TRUE
;
1227 case TVI_CONTROL_VID_GET_HEIGHT
:
1228 *(int *)arg
= priv
->height
;
1229 return TVI_CONTROL_TRUE
;
1230 case TVI_CONTROL_VID_CHK_HEIGHT
:
1232 int req_height
= *(int *)arg
;
1234 mp_msg(MSGT_TV
, MSGL_V
, "Requested height: %d\n", req_height
);
1235 if ((req_height
>= priv
->capability
.minheight
) &&
1236 (req_height
<= priv
->capability
.maxheight
))
1237 return TVI_CONTROL_TRUE
;
1238 return TVI_CONTROL_FALSE
;
1240 case TVI_CONTROL_VID_SET_HEIGHT
:
1241 priv
->height
= *(int *)arg
;
1242 return TVI_CONTROL_TRUE
;
1243 case TVI_CONTROL_VID_GET_PICTURE
:
1244 if (ioctl(priv
->video_fd
, VIDIOCGPICT
, &priv
->picture
) == -1)
1246 mp_msg(MSGT_TV
, MSGL_ERR
, "ioctl get picture failed: %s\n", strerror(errno
));
1247 return TVI_CONTROL_FALSE
;
1249 return TVI_CONTROL_TRUE
;
1250 case TVI_CONTROL_VID_SET_PICTURE
:
1251 if (ioctl(priv
->video_fd
, VIDIOCSPICT
, &priv
->picture
) == -1)
1253 mp_msg(MSGT_TV
, MSGL_ERR
, "ioctl set picture failed: %s\n", strerror(errno
));
1254 return TVI_CONTROL_FALSE
;
1256 return TVI_CONTROL_TRUE
;
1257 case TVI_CONTROL_VID_SET_BRIGHTNESS
:
1258 priv
->picture
.brightness
= (327*(*(int *)arg
+100)) + 68;
1259 return control(priv
, TVI_CONTROL_VID_SET_PICTURE
, 0);
1260 case TVI_CONTROL_VID_SET_HUE
:
1261 priv
->picture
.hue
= (327*(*(int *)arg
+100)) + 68;
1262 return control(priv
, TVI_CONTROL_VID_SET_PICTURE
, 0);
1263 case TVI_CONTROL_VID_SET_SATURATION
:
1264 priv
->picture
.colour
= (327*(*(int *)arg
+100)) + 68;
1265 return control(priv
, TVI_CONTROL_VID_SET_PICTURE
, 0);
1266 case TVI_CONTROL_VID_SET_CONTRAST
:
1267 priv
->picture
.contrast
= (327*(*(int *)arg
+100)) + 68;
1268 return control(priv
, TVI_CONTROL_VID_SET_PICTURE
, 0);
1269 case TVI_CONTROL_VID_GET_BRIGHTNESS
:
1270 if(!control(priv
, TVI_CONTROL_VID_GET_PICTURE
, 0)) return 0;
1271 *(int*)arg
= ((int)priv
->picture
.brightness
-68)/327-100;
1273 case TVI_CONTROL_VID_GET_HUE
:
1274 if(!control(priv
, TVI_CONTROL_VID_GET_PICTURE
, 0)) return 0;
1275 *(int*)arg
= ((int)priv
->picture
.hue
-68)/327-100;
1277 case TVI_CONTROL_VID_GET_SATURATION
:
1278 if(!control(priv
, TVI_CONTROL_VID_GET_PICTURE
, 0)) return 0;
1279 *(int*)arg
= ((int)priv
->picture
.colour
-68)/327-100;
1281 case TVI_CONTROL_VID_GET_CONTRAST
:
1282 if(!control(priv
, TVI_CONTROL_VID_GET_PICTURE
, 0)) return 0;
1283 *(int*)arg
= ((int)priv
->picture
.contrast
-68)/327-100;
1285 case TVI_CONTROL_VID_GET_FPS
:
1286 *(float *)arg
=priv
->fps
;
1287 return TVI_CONTROL_TRUE
;
1289 /* ========== TUNER controls =========== */
1290 case TVI_CONTROL_TUN_GET_FREQ
:
1294 if (ioctl(priv
->video_fd
, VIDIOCGFREQ
, &freq
) == -1)
1296 mp_msg(MSGT_TV
, MSGL_ERR
, "ioctl get freq failed: %s\n", strerror(errno
));
1297 return TVI_CONTROL_FALSE
;
1300 /* tuner uses khz not mhz ! */
1301 // if (priv->tuner.flags & VIDEO_TUNER_LOW)
1303 *(unsigned long *)arg
= freq
;
1304 return TVI_CONTROL_TRUE
;
1306 case TVI_CONTROL_TUN_SET_FREQ
:
1308 /* argument is in MHz ! */
1309 unsigned long freq
= *(unsigned long *)arg
;
1311 if (priv
->capability
.audios
) {
1312 priv
->audio
[priv
->audio_id
].flags
|= VIDEO_AUDIO_MUTE
;
1313 ioctl(priv
->video_fd
, VIDIOCSAUDIO
, &priv
->audio
[priv
->audio_id
]);
1316 mp_msg(MSGT_TV
, MSGL_V
, "requested frequency: %.3f\n", (float)freq
/16);
1318 /* tuner uses khz not mhz ! */
1319 // if (priv->tuner.flags & VIDEO_TUNER_LOW)
1321 // mp_msg(MSGT_TV, MSGL_V, " requesting from driver: freq=%.3f\n", (float)freq/16);
1322 if (ioctl(priv
->video_fd
, VIDIOCSFREQ
, &freq
) == -1)
1324 mp_msg(MSGT_TV
, MSGL_ERR
, "ioctl set freq failed: %s\n", strerror(errno
));
1325 return TVI_CONTROL_FALSE
;
1327 usleep(100000); // wait to suppress noise during switching
1329 if (priv
->capability
.audios
) {
1330 priv
->audio
[priv
->audio_id
].flags
&= ~VIDEO_AUDIO_MUTE
;
1331 ioctl(priv
->video_fd
, VIDIOCSAUDIO
, &priv
->audio
[priv
->audio_id
]);
1334 return TVI_CONTROL_TRUE
;
1336 case TVI_CONTROL_TUN_GET_TUNER
:
1338 if (ioctl(priv
->video_fd
, VIDIOCGTUNER
, &priv
->tuner
) == -1)
1340 mp_msg(MSGT_TV
, MSGL_ERR
, "ioctl get tuner failed: %s\n", strerror(errno
));
1341 return TVI_CONTROL_FALSE
;
1344 mp_msg(MSGT_TV
, MSGL_V
, "Tuner (%s) range: %lu -> %lu\n", priv
->tuner
.name
,
1345 priv
->tuner
.rangelow
, priv
->tuner
.rangehigh
);
1346 return TVI_CONTROL_TRUE
;
1348 case TVI_CONTROL_TUN_SET_TUNER
:
1350 if (ioctl(priv
->video_fd
, VIDIOCSTUNER
, &priv
->tuner
) == -1)
1352 mp_msg(MSGT_TV
, MSGL_ERR
, "ioctl set tuner failed: %s\n", strerror(errno
));
1353 return TVI_CONTROL_FALSE
;
1355 return TVI_CONTROL_TRUE
;
1357 case TVI_CONTROL_TUN_SET_NORM
:
1359 int req_mode
= *(int *)arg
;
1361 for(norm_index
=0;supported_norms
[norm_index
].name
; norm_index
++)
1362 if(req_mode
==supported_norms
[norm_index
].normid
)
1365 if(!supported_norms
[norm_index
].name
) {
1366 mp_msg(MSGT_TV
, MSGL_ERR
, "Unknown norm!\n");
1367 return TVI_CONTROL_FALSE
;
1370 if (priv
->channels
[priv
->act_channel
].flags
& VIDEO_VC_TUNER
) {
1373 control(priv
, TVI_CONTROL_TUN_GET_TUNER
, 0);
1374 if(!(priv
->tuner
.flags
& supported_norms
[norm_index
].tuner_flags
))
1376 mp_msg(MSGT_TV
, MSGL_ERR
, "Tuner isn't capable to set norm!\n");
1377 return TVI_CONTROL_FALSE
;
1380 prev_mode
= priv
->tuner
.mode
;
1382 priv
->tuner
.mode
= supported_norms
[norm_index
].tuner_mode
;
1384 if (control(priv
, TVI_CONTROL_TUN_SET_TUNER
, &priv
->tuner
) != TVI_CONTROL_TRUE
) {
1385 // norm setting failed, but maybe it's only because it's fixed
1386 if (priv
->tuner
.mode
!= prev_mode
) return TVI_CONTROL_FALSE
; // no it really failed
1391 priv
->channels
[priv
->act_channel
].norm
= supported_norms
[norm_index
].input_norm
;
1393 if (ioctl(priv
->video_fd
, VIDIOCSCHAN
, &priv
->channels
[priv
->act_channel
]) == -1)
1395 mp_msg(MSGT_TV
, MSGL_ERR
, "ioctl set chan failed: %s\n", strerror(errno
));
1396 return TVI_CONTROL_FALSE
;
1399 if (ioctl(priv
->video_fd
, VIDIOCGCAP
, &priv
->capability
) == -1) {
1400 mp_msg(MSGT_TV
, MSGL_ERR
, "ioctl get capabilites failed: %s\n", strerror(errno
));
1401 return TVI_CONTROL_FALSE
;
1404 priv
->fps
= supported_norms
[norm_index
].fps
;
1406 if(priv
->height
> priv
->capability
.maxheight
) {
1407 priv
->height
= priv
->capability
.maxheight
;
1410 if(priv
->width
> priv
->capability
.maxwidth
) {
1411 priv
->width
= priv
->capability
.maxwidth
;
1414 return TVI_CONTROL_TRUE
;
1416 case TVI_CONTROL_TUN_GET_NORM
:
1418 *(int *)arg
= priv
->tuner
.mode
;
1420 return TVI_CONTROL_TRUE
;
1422 case TVI_CONTROL_TUN_GET_SIGNAL
:
1424 if (ioctl(priv
->video_fd
, VIDIOCGTUNER
, &priv
->tuner
) == -1)
1426 mp_msg(MSGT_TV
, MSGL_ERR
, "ioctl get tuner failed: %s\n", strerror(errno
));
1427 return TVI_CONTROL_FALSE
;
1429 *(int*)arg
=100*(priv
->tuner
.signal
>>8)/255;
1430 return TVI_CONTROL_TRUE
;
1433 /* ========== AUDIO controls =========== */
1434 case TVI_CONTROL_AUD_GET_FORMAT
:
1436 *(int *)arg
= AF_FORMAT_S16_LE
;
1437 return TVI_CONTROL_TRUE
;
1439 case TVI_CONTROL_AUD_GET_CHANNELS
:
1441 *(int *)arg
= priv
->audio_in
.channels
;
1442 return TVI_CONTROL_TRUE
;
1444 case TVI_CONTROL_AUD_GET_SAMPLERATE
:
1446 *(int *)arg
= priv
->audio_in
.samplerate
;
1447 return TVI_CONTROL_TRUE
;
1449 case TVI_CONTROL_AUD_GET_SAMPLESIZE
:
1451 *(int *)arg
= priv
->audio_in
.bytes_per_sample
;
1452 return TVI_CONTROL_TRUE
;
1454 case TVI_CONTROL_AUD_SET_SAMPLERATE
:
1456 if (audio_in_set_samplerate(&priv
->audio_in
, *(int *)arg
) < 0) return TVI_CONTROL_FALSE
;
1457 setup_audio_buffer_sizes(priv
);
1458 return TVI_CONTROL_TRUE
;
1460 /* ========== SPECIFIC controls =========== */
1461 case TVI_CONTROL_SPC_GET_INPUT
:
1463 int req_chan
= *(int *)arg
;
1466 for (i
= 0; i
< priv
->capability
.channels
; i
++)
1468 if (priv
->channels
[i
].channel
== req_chan
)
1472 priv
->act_channel
= i
;
1474 if (ioctl(priv
->video_fd
, VIDIOCGCHAN
, &priv
->channels
[i
]) == -1)
1476 mp_msg(MSGT_TV
, MSGL_ERR
, "ioctl get channel failed: %s\n", strerror(errno
));
1477 return TVI_CONTROL_FALSE
;
1479 return TVI_CONTROL_TRUE
;
1482 case TVI_CONTROL_SPC_SET_INPUT
:
1484 struct video_channel chan
;
1485 int req_chan
= *(int *)arg
;
1488 if (req_chan
>= priv
->capability
.channels
)
1490 mp_msg(MSGT_TV
, MSGL_ERR
, "Invalid input requested: %d, valid: 0-%d\n",
1491 req_chan
, priv
->capability
.channels
- 1);
1492 return TVI_CONTROL_FALSE
;
1495 for (i
= 0; i
< priv
->capability
.channels
; i
++)
1497 if (priv
->channels
[i
].channel
== req_chan
)
1498 chan
= priv
->channels
[i
];
1501 if (ioctl(priv
->video_fd
, VIDIOCSCHAN
, &chan
) == -1)
1503 mp_msg(MSGT_TV
, MSGL_ERR
, "ioctl set chan failed: %s\n", strerror(errno
));
1504 return TVI_CONTROL_FALSE
;
1506 mp_msg(MSGT_TV
, MSGL_INFO
, "Using input '%s'\n", chan
.name
);
1508 priv
->act_channel
= i
;
1510 /* update tuner state */
1511 // if (priv->capability.type & VID_TYPE_TUNER)
1512 if (priv
->channels
[priv
->act_channel
].flags
& VIDEO_VC_TUNER
)
1513 control(priv
, TVI_CONTROL_TUN_GET_TUNER
, 0);
1515 /* update local channel list */
1516 control(priv
, TVI_CONTROL_SPC_GET_INPUT
, &req_chan
);
1517 return TVI_CONTROL_TRUE
;
1518 case TVI_CONTROL_IMMEDIATE
:
1519 priv
->immediate_mode
= 1;
1520 return TVI_CONTROL_TRUE
;
1522 case TVI_CONTROL_VBI_INIT
:
1525 tt_stream_props tsp
;
1527 if (vbi_init(priv
,*(char**)arg
)!=TVI_CONTROL_TRUE
)
1528 return TVI_CONTROL_FALSE
;
1529 if(vbi_get_props(priv
,&tsp
)==TVI_CONTROL_TRUE
)
1532 if(teletext_control(NULL
,TV_VBI_CONTROL_START
,&ptr
)==VBI_CONTROL_TRUE
)
1535 priv
->priv_vbi
=NULL
;
1537 return TVI_CONTROL_TRUE
;
1539 case TVI_CONTROL_GET_VBI_PTR
:
1540 *(void **)arg
=priv
->priv_vbi
;
1541 return TVI_CONTROL_TRUE
;
1544 return TVI_CONTROL_UNKNOWN
;
1547 static int set_mute(priv_t
* priv
,int value
)
1549 if (!priv
->capability
.audios
) {
1553 priv
->audio
[priv
->audio_id
].flags
|=VIDEO_AUDIO_MUTE
;
1555 priv
->audio
[priv
->audio_id
].flags
&= ~VIDEO_AUDIO_MUTE
;
1557 if(ioctl(priv
->video_fd
, VIDIOCSAUDIO
, &priv
->audio
[priv
->audio_id
])<0)
1562 // copies a video frame
1563 // for YV12 swaps the 2nd and 3rd plane
1564 static inline void copy_frame(priv_t
*priv
, unsigned char *dest
, unsigned char *source
)
1566 if(priv
->tv_param
->automute
>0){
1567 if (ioctl(priv
->video_fd
, VIDIOCGTUNER
, &priv
->tuner
) >= 0) {
1568 if(priv
->tv_param
->automute
<<8>priv
->tuner
.signal
){
1569 fill_blank_frame(dest
,priv
->bytesperline
* priv
->height
,priv
->format
);
1576 // YV12 uses VIDEO_PALETTE_YUV420P, but the planes are swapped
1577 if (priv
->format
== IMGFMT_YV12
) {
1578 fast_memcpy(dest
, source
, priv
->width
* priv
->height
);
1579 fast_memcpy(dest
+priv
->width
* priv
->height
*5/4, source
+priv
->width
* priv
->height
, priv
->width
* priv
->height
/4);
1580 fast_memcpy(dest
+priv
->width
* priv
->height
, source
+priv
->width
* priv
->height
*5/4, priv
->width
* priv
->height
/4);
1584 fast_memcpy(dest
, source
, priv
->bytesperline
* priv
->height
);
1587 // maximum skew change, in frames
1588 #define MAX_SKEW_DELTA 0.6
1589 static void *video_grabber(void *data
)
1591 #define MAXTOL (priv->nbuf)
1592 priv_t
*priv
= (priv_t
*)data
;
1593 struct timeval curtime
;
1594 long long skew
, prev_skew
, xskew
, interval
, prev_interval
;
1601 /* start the capture process */
1603 if ( priv
->tv_param
->mjpeg
)
1605 mp_msg(MSGT_TV
, MSGL_INFO
, " MJP: gonna capture ! \n");
1606 for (i
=0; i
< priv
->nbuf
; i
++) {
1608 if (ioctl(priv
->video_fd
, MJPIOC_QBUF_CAPT
, &num
) < 0)
1609 mp_msg(MSGT_TV
, MSGL_ERR
,
1610 "\n MJP: ioctl MJPIOC_QBUF_CAPT b failed: %s\n", strerror(errno
));
1615 for (i
=0; i
< priv
->nbuf
; i
++) {
1616 if (ioctl(priv
->video_fd
, VIDIOCMCAPTURE
, &priv
->buf
[i
]) == -1)
1617 mp_msg(MSGT_TV
, MSGL_ERR
, "\nioctl mcapture failed: %s\n", strerror(errno
));
1621 gettimeofday(&curtime
, NULL
);
1622 priv
->starttime
= (long long)1e6
*curtime
.tv_sec
+ curtime
.tv_usec
;
1623 priv
->audio_skew_measure_time
= 0;
1624 pthread_mutex_unlock(&priv
->audio_starter
);
1634 for (framecount
= 0; !priv
->shutdown
;)
1636 for (i
= 0; i
< priv
->nbuf
&& !priv
->shutdown
; i
++, framecount
++) {
1638 if (priv
->immediate_mode
) {
1639 while (priv
->video_cnt
== priv
->video_buffer_size_max
) {
1641 if (priv
->shutdown
) {
1649 if ( priv
->tv_param
->mjpeg
)
1651 while (ioctl(priv
->video_fd
, MJPIOC_SYNC
, &priv
->buf
[frame
].frame
) < 0 &&
1652 (errno
== EAGAIN
|| errno
== EINTR
));
1656 while (ioctl(priv
->video_fd
, VIDIOCSYNC
, &priv
->buf
[frame
].frame
) < 0 &&
1657 (errno
== EAGAIN
|| errno
== EINTR
));
1659 mp_dbg(MSGT_TV
, MSGL_DBG3
, "\npicture sync failed\n");
1661 gettimeofday(&curtime
, NULL
);
1662 if (!priv
->immediate_mode
) {
1663 interval
= (long long)1e6
*curtime
.tv_sec
+ curtime
.tv_usec
- priv
->starttime
;
1665 interval
= (long long)1e6
*framecount
/priv
->fps
;
1668 if (!priv
->immediate_mode
) {
1669 long long period
, orig_interval
;
1671 if (tolerance
== 0) {
1672 if (interval
- prev_interval
== 0) {
1673 mp_msg(MSGT_TV
, MSGL_V
, "\nvideo capture thread: frame delta = 0\n");
1674 } else if ((interval
- prev_interval
< (long long)0.85e6
/priv
->fps
)
1675 || (interval
- prev_interval
> (long long)1.15e6
/priv
->fps
) ) {
1676 mp_msg(MSGT_TV
, MSGL_V
, "\nvideo capture thread: frame delta ~ %.1f fps\n",
1677 (double)1e6
/(interval
- prev_interval
));
1681 // correct the rate fluctuations on a small scale
1682 orig_interval
= interval
;
1683 period
= priv
->video_interval_sum
/VIDEO_AVG_BUFFER_SIZE
;
1684 if (interval
- prev_interval
> 105*period
/100) {
1685 if (tolerance
> 0) {
1686 mp_msg(MSGT_TV
, MSGL_DBG3
, "correcting timestamp\n");
1687 interval
= prev_interval
+ priv
->video_interval_sum
/VIDEO_AVG_BUFFER_SIZE
;
1690 mp_msg(MSGT_TV
, MSGL_DBG3
, "bad - frames were dropped\n");
1694 if (tolerance
< MAXTOL
) {
1695 mp_msg(MSGT_TV
, MSGL_DBG3
, "fluctuation overcome\n");
1700 priv
->video_interval_sum
-= priv
->video_avg_buffer
[priv
->video_avg_ptr
];
1701 priv
->video_avg_buffer
[priv
->video_avg_ptr
++] = orig_interval
-prev_interval
;
1702 priv
->video_interval_sum
+= orig_interval
-prev_interval
;
1703 if (priv
->video_avg_ptr
>= VIDEO_AVG_BUFFER_SIZE
) priv
->video_avg_ptr
= 0;
1705 // fprintf(stderr, "fps: %lf\n", (double)1e6*VIDEO_AVG_BUFFER_SIZE/priv->video_interval_sum);
1707 // interpolate the skew in time
1708 pthread_mutex_lock(&priv
->skew_mutex
);
1709 xskew
= priv
->audio_skew
+ (interval
- priv
->audio_skew_measure_time
)*priv
->audio_skew_factor
;
1710 pthread_mutex_unlock(&priv
->skew_mutex
);
1711 // correct extreme skew changes to avoid (especially) moving backwards in time
1712 if (xskew
- prev_skew
> (interval
- prev_interval
)*MAX_SKEW_DELTA
) {
1713 skew
= prev_skew
+ (interval
- prev_interval
)*MAX_SKEW_DELTA
;
1714 } else if (xskew
- prev_skew
< -(interval
- prev_interval
)*MAX_SKEW_DELTA
) {
1715 skew
= prev_skew
- (interval
- prev_interval
)*MAX_SKEW_DELTA
;
1721 mp_msg(MSGT_TV
, MSGL_DBG3
, "\nfps = %f, interval = %f, a_skew = %f, corr_skew = %f\n",
1722 (interval
!= prev_interval
) ? (double)1e6
/(interval
- prev_interval
) : -1,
1723 (double)1e-6*interval
, (double)1e-6*xskew
, (double)1e-6*skew
);
1724 mp_msg(MSGT_TV
, MSGL_DBG3
, "vcnt = %d, acnt = %d\n", priv
->video_cnt
, priv
->audio_cnt
);
1727 prev_interval
= interval
;
1729 /* allocate a new buffer, if needed */
1730 pthread_mutex_lock(&priv
->video_buffer_mutex
);
1731 if (priv
->video_buffer_size_current
< priv
->video_buffer_size_max
) {
1732 if (priv
->video_cnt
== priv
->video_buffer_size_current
) {
1733 unsigned char *newbuf
= calloc(priv
->bytesperline
, priv
->height
);
1735 memmove(priv
->video_ringbuffer
+priv
->video_tail
+1, priv
->video_ringbuffer
+priv
->video_tail
,
1736 (priv
->video_buffer_size_current
-priv
->video_tail
)*sizeof(unsigned char *));
1737 memmove(priv
->video_timebuffer
+priv
->video_tail
+1, priv
->video_timebuffer
+priv
->video_tail
,
1738 (priv
->video_buffer_size_current
-priv
->video_tail
)*sizeof(long long));
1739 priv
->video_ringbuffer
[priv
->video_tail
] = newbuf
;
1740 if ((priv
->video_head
>= priv
->video_tail
) && (priv
->video_cnt
> 0)) priv
->video_head
++;
1741 priv
->video_buffer_size_current
++;
1745 pthread_mutex_unlock(&priv
->video_buffer_mutex
);
1747 if (priv
->video_cnt
== priv
->video_buffer_size_current
) {
1748 if (!priv
->immediate_mode
) {
1749 mp_msg(MSGT_TV
, MSGL_ERR
, "\nvideo buffer full - dropping frame\n");
1752 if (priv
->immediate_mode
) {
1753 priv
->video_timebuffer
[priv
->video_tail
] = interval
;
1755 // compensate for audio skew
1756 // negative skew => there are more audio samples, increase interval
1757 // positive skew => less samples, shorten the interval
1758 priv
->video_timebuffer
[priv
->video_tail
] = interval
- skew
;
1761 if ( priv
->tv_param
->mjpeg
)
1762 copy_frame(priv
, priv
->video_ringbuffer
[priv
->video_tail
],
1763 priv
->mmap
+(priv
->mjpeg_bufsize
)*i
);
1765 copy_frame(priv
, priv
->video_ringbuffer
[priv
->video_tail
],
1766 priv
->mmap
+priv
->mbuf
.offsets
[frame
]);
1767 priv
->video_tail
= (priv
->video_tail
+1)%priv
->video_buffer_size_current
;
1771 if ( priv
->tv_param
->mjpeg
)
1774 if (ioctl(priv
->video_fd
, MJPIOC_QBUF_CAPT
, &num
) < 0)
1776 mp_msg(MSGT_TV
, MSGL_ERR
, "\n MJP: ioctl MJPIOC_QBUF_CAPT end failed: %s\n",
1783 if (ioctl(priv
->video_fd
, VIDIOCMCAPTURE
, &priv
->buf
[frame
]) == -1)
1785 mp_msg(MSGT_TV
, MSGL_ERR
, "\nioctl mcapture failed: %s\n", strerror(errno
));
1791 mp_msg(MSGT_TV
, MSGL_INFO
, " MJP: returning! \n");
1795 static double grab_video_frame(priv_t
*priv
, char *buffer
, int len
)
1800 pthread_create(&priv
->video_grabber_thread
, NULL
, video_grabber
, priv
);
1804 while (priv
->video_cnt
== 0) {
1808 pthread_mutex_lock(&priv
->video_buffer_mutex
);
1809 interval
= (double)priv
->video_timebuffer
[priv
->video_head
]*1e-6;
1810 fast_memcpy(buffer
, priv
->video_ringbuffer
[priv
->video_head
], len
);
1812 priv
->video_head
= (priv
->video_head
+1)%priv
->video_buffer_size_current
;
1813 pthread_mutex_unlock(&priv
->video_buffer_mutex
);
1818 static int get_video_framesize(priv_t
*priv
)
1820 return priv
->bytesperline
* priv
->height
;
1823 static void *audio_grabber(void *data
)
1825 priv_t
*priv
= (priv_t
*)data
;
1827 int i
, audio_skew_ptr
= 0;
1828 long long current_time
, prev_skew
= 0;
1830 pthread_mutex_lock(&priv
->audio_starter
);
1832 audio_in_start_capture(&priv
->audio_in
);
1833 for (i
= 0; i
< priv
->aud_skew_cnt
; i
++)
1834 priv
->audio_skew_buffer
[i
] = 0;
1836 for (; !priv
->shutdown
;)
1838 if (audio_in_read_chunk(&priv
->audio_in
, priv
->audio_ringbuffer
+priv
->audio_tail
*priv
->audio_in
.blocksize
) < 0)
1841 gettimeofday(&tv
, NULL
);
1843 priv
->audio_recv_blocks_total
++;
1844 current_time
= (long long)1e6
*tv
.tv_sec
+ tv
.tv_usec
- priv
->starttime
;
1846 priv
->audio_skew_total
-= priv
->audio_skew_buffer
[audio_skew_ptr
];
1847 priv
->audio_skew_buffer
[audio_skew_ptr
] = current_time
1848 - 1e6
*priv
->audio_secs_per_block
*priv
->audio_recv_blocks_total
;
1849 priv
->audio_skew_total
+= priv
->audio_skew_buffer
[audio_skew_ptr
];
1850 audio_skew_ptr
= (audio_skew_ptr
+1) % priv
->aud_skew_cnt
;
1852 pthread_mutex_lock(&priv
->skew_mutex
);
1853 // linear interpolation - here we interpolate current skew value
1854 // from the moving average, which we expect to be in the middle
1856 if (priv
->audio_recv_blocks_total
> priv
->aud_skew_cnt
) {
1857 priv
->audio_skew
= priv
->audio_skew_total
/priv
->aud_skew_cnt
;
1858 priv
->audio_skew
+= (priv
->audio_skew
*priv
->aud_skew_cnt
)/(2*priv
->audio_recv_blocks_total
-priv
->aud_skew_cnt
);
1860 // this smoothes the evolution of audio_skew at startup a bit
1861 priv
->audio_skew
= ((priv
->aud_skew_cnt
+priv
->audio_recv_blocks_total
)*priv
->audio_skew_total
)/(priv
->aud_skew_cnt
*priv
->audio_recv_blocks_total
);
1863 // current skew factor (assuming linearity)
1864 // used for further interpolation in video_grabber
1865 // probably overkill but seems to be necessary for
1866 // stress testing by dropping half of the audio frames ;)
1867 // especially when using ALSA with large block sizes
1868 // where audio_skew remains a long while behind
1869 if ((priv
->audio_skew_measure_time
!= 0) && (current_time
- priv
->audio_skew_measure_time
!= 0)) {
1870 priv
->audio_skew_factor
= (double)(priv
->audio_skew
-prev_skew
)/(current_time
- priv
->audio_skew_measure_time
);
1872 priv
->audio_skew_factor
= 0.0;
1875 priv
->audio_skew_measure_time
= current_time
;
1876 prev_skew
= priv
->audio_skew
;
1877 pthread_mutex_unlock(&priv
->skew_mutex
);
1879 if ((priv
->audio_tail
+1) % priv
->audio_buffer_size
== priv
->audio_head
) {
1880 mp_msg(MSGT_TV
, MSGL_ERR
, "\ntoo bad - dropping audio frame !\n");
1883 priv
->audio_tail
= (priv
->audio_tail
+1) % priv
->audio_buffer_size
;
1890 static double grab_audio_frame(priv_t
*priv
, char *buffer
, int len
)
1892 mp_dbg(MSGT_TV
, MSGL_DBG2
, "grab_audio_frame(priv=%p, buffer=%p, len=%d)\n",
1896 pthread_create(&priv
->video_grabber_thread
, NULL
, video_grabber
, priv
);
1900 // compensate for dropped audio frames
1901 if (priv
->audio_drop
&& (priv
->audio_head
== priv
->audio_tail
)) {
1903 priv
->audio_sent_blocks_total
++;
1904 memset(buffer
, 0, len
);
1905 return (double)priv
->audio_sent_blocks_total
*priv
->audio_secs_per_block
;
1908 while (priv
->audio_head
== priv
->audio_tail
) {
1911 fast_memcpy(buffer
, priv
->audio_ringbuffer
+priv
->audio_head
*priv
->audio_in
.blocksize
, len
);
1912 priv
->audio_head
= (priv
->audio_head
+1) % priv
->audio_buffer_size
;
1914 priv
->audio_sent_blocks_total
++;
1915 return (double)priv
->audio_sent_blocks_total
*priv
->audio_secs_per_block
;
1918 static int get_audio_framesize(priv_t
*priv
)
1920 return priv
->audio_in
.blocksize
;