2 * Video 4 Linux 2 input
4 * copyright (c) 2003 Martin Olschewski <olschewski@zpr.uni-koeln.de>
5 * copyright (c) 2003 Jindrich Makovicka <makovick@gmail.com>
7 * Some ideas are based on works from
8 * Alex Beregszaszi <alex@fsn.hu>
9 * Gerd Knorr <kraxel@bytesex.org>
11 * This file is part of MPlayer.
13 * MPlayer is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
18 * MPlayer is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License along
24 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
25 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
31 - norm setting isn't consistent with tvi_v4l
32 - the same for volume/bass/treble/balance
43 #include <sys/ioctl.h>
46 #include <sys/types.h>
49 #ifdef HAVE_SYS_SYSINFO_H
50 #include <sys/sysinfo.h>
52 #ifdef HAVE_SYS_VIDEOIO_H
53 #include <sys/videoio.h>
55 #include <linux/types.h>
56 #include <linux/videodev2.h>
59 #include "libmpcodecs/img_format.h"
60 #include "libmpcodecs/dec_teletext.h"
61 #include "libaf/af_format.h"
65 #define info tvi_info_v4l2
66 static tvi_handle_t
*tvi_init_v4l2(tv_param_t
* tv_param
);
67 /* information about this file */
68 const tvi_info_t tvi_info_v4l2
= {
70 "Video 4 Linux 2 input",
72 "Martin Olschewski <olschewski@zpr.uni-koeln.de>",
73 "first try, more to come ;-)"
77 struct v4l2_buffer buf
;
82 #define BUFFER_COUNT 6
84 /** video ringbuffer entry */
86 unsigned char *data
; ///< frame contents
87 long long timestamp
; ///< frame timestamp
88 int framesize
; ///< actual frame size
100 pthread_t vbi_grabber_thread
;
103 struct v4l2_capability capability
;
104 struct v4l2_input input
;
105 struct v4l2_format format
;
106 struct v4l2_standard standard
;
107 struct v4l2_tuner tuner
;
111 volatile long long first_frame
;
112 long long curr_frame
;
113 /* audio video interleaving ;-) */
114 volatile int streamon
;
115 pthread_t audio_grabber_thread
;
116 pthread_mutex_t skew_mutex
;
118 /* 2nd level video buffers */
122 int video_buffer_size_max
;
123 volatile int video_buffer_size_current
;
124 video_buffer_entry
*video_ringbuffer
;
125 volatile int video_head
;
126 volatile int video_tail
;
127 volatile int video_cnt
;
128 pthread_t video_grabber_thread
;
129 pthread_mutex_t video_buffer_mutex
;
135 long long audio_start_time
;
136 int audio_buffer_size
;
138 unsigned char *audio_ringbuffer
;
139 long long *audio_skew_buffer
;
140 long long *audio_skew_delta_buffer
;
141 volatile int audio_head
;
142 volatile int audio_tail
;
143 volatile int audio_cnt
;
144 volatile long long audio_skew
;
145 volatile double audio_skew_factor
;
146 volatile long long audio_skew_measure_time
;
147 volatile int audio_drop
;
148 volatile int shutdown
;
150 int audio_initialized
;
151 double audio_secs_per_block
;
152 long long audio_usecs_per_block
;
153 long long audio_skew_total
;
154 long long audio_skew_delta_total
;
155 long audio_recv_blocks_total
;
156 long audio_sent_blocks_total
;
157 pthread_mutex_t audio_mutex
;
158 int audio_insert_null_samples
;
159 volatile long audio_null_blocks_inserted
;
160 volatile long long dropped_frames_timeshift
;
161 long long dropped_frames_compensated
;
163 tv_param_t
*tv_param
;
168 static void *audio_grabber(void *data
);
169 static void *video_grabber(void *data
);
171 /**********************************************************************\
173 Only few of the fourccs are the same in v4l2 and mplayer:
175 IMGFMT_YVU9 == V4L2_PIX_FMT_YVU410
176 IMGFMT_YV12 == V4L2_PIX_FMT_YVU420
177 IMGFMT_NV12 == V4L2_PIX_FMT_NV12
178 IMGFMT_422P == V4L2_PIX_FMT_YUV422P
179 IMGFMT_411P == V4L2_PIX_FMT_YUV411P
180 IMGFMT_UYVY == V4L2_PIX_FMT_UYVY
181 IMGFMT_Y41P == V4L2_PIX_FMT_Y41P
183 This may be an useful translation table for some others:
185 IMGFMT_RGB8 == V4L2_PIX_FMT_RGB332
186 IMGFMT_BGR15 == V4L2_PIX_FMT_RGB555
187 IMGFMT_BGR16 == V4L2_PIX_FMT_RGB565
188 IMGFMT_RGB24 == V4L2_PIX_FMT_RGB24
189 IMGFMT_RGB32 == V4L2_PIX_FMT_RGB32
190 IMGFMT_BGR24 == V4L2_PIX_FMT_BGR24
191 IMGFMT_BGR32 == V4L2_PIX_FMT_BGR32
192 IMGFMT_Y800 == V4L2_PIX_FMT_GREY
193 IMGFMT_IF09 == V4L2_PIX_FMT_YUV410
194 IMGFMT_I420 == V4L2_PIX_FMT_YUV420
195 IMGFMT_YUY2 == V4L2_PIX_FMT_YUYV
197 \**********************************************************************/
200 ** Translate a mplayer fourcc to a video4linux2 pixel format.
202 static int fcc_mp2vl(int fcc
)
205 case IMGFMT_RGB8
: return V4L2_PIX_FMT_RGB332
;
206 case IMGFMT_BGR15
: return V4L2_PIX_FMT_RGB555
;
207 case IMGFMT_BGR16
: return V4L2_PIX_FMT_RGB565
;
208 case IMGFMT_RGB24
: return V4L2_PIX_FMT_RGB24
;
209 case IMGFMT_RGB32
: return V4L2_PIX_FMT_RGB32
;
210 case IMGFMT_BGR24
: return V4L2_PIX_FMT_BGR24
;
211 case IMGFMT_BGR32
: return V4L2_PIX_FMT_BGR32
;
212 case IMGFMT_Y800
: return V4L2_PIX_FMT_GREY
;
213 case IMGFMT_IF09
: return V4L2_PIX_FMT_YUV410
;
214 case IMGFMT_I420
: return V4L2_PIX_FMT_YUV420
;
215 case IMGFMT_YUY2
: return V4L2_PIX_FMT_YUYV
;
216 case IMGFMT_YV12
: return V4L2_PIX_FMT_YVU420
;
217 case IMGFMT_UYVY
: return V4L2_PIX_FMT_UYVY
;
218 case IMGFMT_MJPEG
: return V4L2_PIX_FMT_MJPEG
;
224 ** Translate a video4linux2 fourcc aka pixel format to mplayer.
226 static int fcc_vl2mp(int fcc
)
229 case V4L2_PIX_FMT_RGB332
: return IMGFMT_RGB8
;
230 case V4L2_PIX_FMT_RGB555
: return IMGFMT_BGR15
;
231 case V4L2_PIX_FMT_RGB565
: return IMGFMT_BGR16
;
232 case V4L2_PIX_FMT_RGB24
: return IMGFMT_RGB24
;
233 case V4L2_PIX_FMT_RGB32
: return IMGFMT_RGB32
;
234 case V4L2_PIX_FMT_BGR24
: return IMGFMT_BGR24
;
235 case V4L2_PIX_FMT_BGR32
: return IMGFMT_BGR32
;
236 case V4L2_PIX_FMT_GREY
: return IMGFMT_Y800
;
237 case V4L2_PIX_FMT_YUV410
: return IMGFMT_IF09
;
238 case V4L2_PIX_FMT_YUV420
: return IMGFMT_I420
;
239 case V4L2_PIX_FMT_YVU420
: return IMGFMT_YV12
;
240 case V4L2_PIX_FMT_YUYV
: return IMGFMT_YUY2
;
241 case V4L2_PIX_FMT_UYVY
: return IMGFMT_UYVY
;
242 case V4L2_PIX_FMT_MJPEG
: return IMGFMT_MJPEG
;
248 ** Translate a video4linux2 fourcc aka pixel format
249 ** to a human readable string.
251 static const char *pixfmt2name(int pixfmt
)
253 static char unknown
[24];
256 case V4L2_PIX_FMT_RGB332
: return "RGB332";
257 case V4L2_PIX_FMT_RGB555
: return "RGB555";
258 case V4L2_PIX_FMT_RGB565
: return "RGB565";
259 case V4L2_PIX_FMT_RGB555X
: return "RGB555X";
260 case V4L2_PIX_FMT_RGB565X
: return "RGB565X";
261 case V4L2_PIX_FMT_BGR24
: return "BGR24";
262 case V4L2_PIX_FMT_RGB24
: return "RGB24";
263 case V4L2_PIX_FMT_BGR32
: return "BGR32";
264 case V4L2_PIX_FMT_RGB32
: return "RGB32";
265 case V4L2_PIX_FMT_GREY
: return "GREY";
266 case V4L2_PIX_FMT_YVU410
: return "YVU410";
267 case V4L2_PIX_FMT_YVU420
: return "YVU420";
268 case V4L2_PIX_FMT_YUYV
: return "YUYV";
269 case V4L2_PIX_FMT_UYVY
: return "UYVY";
270 /* case V4L2_PIX_FMT_YVU422P: return "YVU422P"; */
271 /* case V4L2_PIX_FMT_YVU411P: return "YVU411P"; */
272 case V4L2_PIX_FMT_YUV422P
: return "YUV422P";
273 case V4L2_PIX_FMT_YUV411P
: return "YUV411P";
274 case V4L2_PIX_FMT_Y41P
: return "Y41P";
275 case V4L2_PIX_FMT_NV12
: return "NV12";
276 case V4L2_PIX_FMT_NV21
: return "NV21";
277 case V4L2_PIX_FMT_YUV410
: return "YUV410";
278 case V4L2_PIX_FMT_YUV420
: return "YUV420";
279 case V4L2_PIX_FMT_YYUV
: return "YYUV";
280 case V4L2_PIX_FMT_HI240
: return "HI240";
281 case V4L2_PIX_FMT_WNVA
: return "WNVA";
282 case V4L2_PIX_FMT_MJPEG
: return "MJPEG";
284 sprintf(unknown
, "unknown (0x%x)", pixfmt
);
290 ** Gives the depth of a video4linux2 fourcc aka pixel format in bits.
292 static int pixfmt2depth(int pixfmt
)
295 case V4L2_PIX_FMT_RGB332
:
297 case V4L2_PIX_FMT_RGB555
:
298 case V4L2_PIX_FMT_RGB565
:
299 case V4L2_PIX_FMT_RGB555X
:
300 case V4L2_PIX_FMT_RGB565X
:
302 case V4L2_PIX_FMT_BGR24
:
303 case V4L2_PIX_FMT_RGB24
:
305 case V4L2_PIX_FMT_BGR32
:
306 case V4L2_PIX_FMT_RGB32
:
308 case V4L2_PIX_FMT_GREY
:
310 case V4L2_PIX_FMT_YVU410
:
312 case V4L2_PIX_FMT_YVU420
:
314 case V4L2_PIX_FMT_YUYV
:
315 case V4L2_PIX_FMT_UYVY
:
316 case V4L2_PIX_FMT_YUV422P
:
317 case V4L2_PIX_FMT_YUV411P
:
319 case V4L2_PIX_FMT_Y41P
:
320 case V4L2_PIX_FMT_NV12
:
321 case V4L2_PIX_FMT_NV21
:
323 case V4L2_PIX_FMT_YUV410
:
325 case V4L2_PIX_FMT_YUV420
:
327 case V4L2_PIX_FMT_YYUV
:
329 case V4L2_PIX_FMT_HI240
:
336 static int amode2v4l(int amode
)
340 return V4L2_TUNER_MODE_MONO
;
342 return V4L2_TUNER_MODE_STEREO
;
344 return V4L2_TUNER_MODE_LANG1
;
346 return V4L2_TUNER_MODE_LANG2
;
356 static double getfps(priv_t
*priv
)
358 if (priv
->tv_param
->fps
> 0)
359 return priv
->tv_param
->fps
;
360 if (priv
->standard
.frameperiod
.denominator
&& priv
->standard
.frameperiod
.numerator
)
361 return (double)priv
->standard
.frameperiod
.denominator
/ priv
->standard
.frameperiod
.numerator
;
365 // sets and sanitizes audio buffer/block sizes
366 static void setup_audio_buffer_sizes(priv_t
*priv
)
368 int bytes_per_sample
= priv
->audio_in
.bytes_per_sample
;
369 int seconds
= priv
->video_buffer_size_max
/getfps(priv
);
371 if (seconds
< 5) seconds
= 5;
372 if (seconds
> 500) seconds
= 500;
374 // make the audio buffer at least as the video buffer capacity (or 5 seconds) long
375 priv
->audio_buffer_size
= 1 + seconds
*priv
->audio_in
.samplerate
376 *priv
->audio_in
.channels
377 *bytes_per_sample
/priv
->audio_in
.blocksize
;
378 if (priv
->audio_buffer_size
< 256) priv
->audio_buffer_size
= 256;
380 // make the skew buffer at least 1 second long
381 priv
->aud_skew_cnt
= 1 + 1*priv
->audio_in
.samplerate
382 *priv
->audio_in
.channels
383 *bytes_per_sample
/priv
->audio_in
.blocksize
;
384 if (priv
->aud_skew_cnt
< 16) priv
->aud_skew_cnt
= 16;
386 mp_msg(MSGT_TV
, MSGL_V
, "Audio capture - buffer %d blocks of %d bytes, skew average from %d meas.\n",
387 priv
->audio_buffer_size
, priv
->audio_in
.blocksize
, priv
->aud_skew_cnt
);
390 static void init_audio(priv_t
*priv
)
392 if (priv
->audio_initialized
) return;
394 if (!priv
->tv_param
->noaudio
) {
396 if (priv
->tv_param
->alsa
)
397 audio_in_init(&priv
->audio_in
, AUDIO_IN_ALSA
);
399 audio_in_init(&priv
->audio_in
, AUDIO_IN_OSS
);
401 audio_in_init(&priv
->audio_in
, AUDIO_IN_OSS
);
404 if (priv
->audio_dev
) {
405 audio_in_set_device(&priv
->audio_in
, priv
->audio_dev
);
408 audio_in_set_samplerate(&priv
->audio_in
, 44100);
409 if (priv
->capability
.capabilities
& V4L2_CAP_TUNER
) {
410 if (priv
->tuner
.audmode
== V4L2_TUNER_MODE_STEREO
) {
411 audio_in_set_channels(&priv
->audio_in
, 2);
413 audio_in_set_channels(&priv
->audio_in
, 1);
416 if (priv
->tv_param
->forcechan
>= 0) {
417 audio_in_set_channels(&priv
->audio_in
, priv
->tv_param
->forcechan
);
419 audio_in_set_channels(&priv
->audio_in
, 2);
423 if (audio_in_setup(&priv
->audio_in
) < 0) return;
425 priv
->audio_initialized
= 1;
431 ** the number of milliseconds elapsed between time0 and time1
433 static size_t difftv(struct timeval time1
, struct timeval time0
)
435 return (time1
.tv_sec
- time0
.tv_sec
) * 1000 +
436 (time1
.tv_usec
- time0
.tv_usec
) / 1000;
441 ** Get current video capture format.
443 static int getfmt(priv_t
*priv
)
447 priv
->format
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
448 if ((i
= ioctl(priv
->video_fd
, VIDIOC_G_FMT
, &priv
->format
)) < 0) {
449 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl get format failed: %s\n",
450 info
.short_name
, strerror(errno
));
457 ** Get current video capture standard.
459 static int getstd(priv_t
*priv
)
464 if (ioctl(priv
->video_fd
, VIDIOC_G_STD
, &id
) < 0) {
465 struct v4l2_streamparm parm
;
467 parm
.type
=V4L2_BUF_TYPE_VIDEO_CAPTURE
;
468 if(ioctl(priv
->video_fd
, VIDIOC_G_PARM
, &parm
) >= 0) {
469 mp_msg(MSGT_TV
, MSGL_WARN
, "%s: your device driver does not support VIDIOC_G_STD ioctl,"
470 " VIDIOC_G_PARM was used instead.\n", info
.short_name
);
471 priv
->standard
.index
=0;
473 priv
->standard
.frameperiod
=parm
.parm
.capture
.timeperframe
;
477 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl get standard failed: %s\n",
478 info
.short_name
, strerror(errno
));
482 priv
->standard
.index
= i
++;
483 if (ioctl(priv
->video_fd
, VIDIOC_ENUMSTD
, &priv
->standard
) < 0) {
486 } while (priv
->standard
.id
!= id
);
490 /***********************************************************************\
493 * Interface to mplayer *
496 \***********************************************************************/
498 static int set_mute(priv_t
*priv
, int value
)
500 struct v4l2_control control
;
501 control
.id
= V4L2_CID_AUDIO_MUTE
;
502 control
.value
= value
;
503 if (ioctl(priv
->video_fd
, VIDIOC_S_CTRL
, &control
) < 0) {
504 mp_msg(MSGT_TV
,MSGL_ERR
,"%s: ioctl set mute failed: %s\n",
505 info
.short_name
, strerror(errno
));
512 ** MPlayer uses values from -100 up to 100 for controls.
513 ** Here they are scaled to what the tv card needs and applied.
515 static int set_control(priv_t
*priv
, struct v4l2_control
*control
, int val_signed
) {
516 struct v4l2_queryctrl qctrl
;
517 qctrl
.id
= control
->id
;
518 if (ioctl(priv
->video_fd
, VIDIOC_QUERYCTRL
, &qctrl
) < 0) {
519 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl query control failed: %s\n",
520 info
.short_name
, strerror(errno
));
521 return TVI_CONTROL_FALSE
;
525 if (control
->value
< 0) {
526 control
->value
= qctrl
.default_value
+ control
->value
*
527 (qctrl
.default_value
- qctrl
.minimum
) / 100;
529 control
->value
= qctrl
.default_value
+ control
->value
*
530 (qctrl
.maximum
- qctrl
.default_value
) / 100;
533 if (control
->value
< 50) {
534 control
->value
= qctrl
.default_value
+ (control
->value
-50) *
535 (qctrl
.default_value
- qctrl
.minimum
) / 50;
537 control
->value
= qctrl
.default_value
+ (control
->value
-50) *
538 (qctrl
.maximum
- qctrl
.default_value
) / 50;
543 if (ioctl(priv
->video_fd
, VIDIOC_S_CTRL
, control
) < 0) {
544 mp_msg(MSGT_TV
, MSGL_ERR
,"%s: ioctl set %s %d failed: %s\n",
545 info
.short_name
, qctrl
.name
, control
->value
, strerror(errno
));
546 return TVI_CONTROL_FALSE
;
548 mp_msg(MSGT_TV
, MSGL_V
, "%s: set %s: %d [%d, %d]\n", info
.short_name
,
549 qctrl
.name
, control
->value
, qctrl
.minimum
, qctrl
.maximum
);
551 return TVI_CONTROL_TRUE
;
556 ** Scale the control values back to what mplayer needs.
558 static int get_control(priv_t
*priv
, struct v4l2_control
*control
, int val_signed
) {
559 struct v4l2_queryctrl qctrl
;
561 qctrl
.id
= control
->id
;
562 if (ioctl(priv
->video_fd
, VIDIOC_QUERYCTRL
, &qctrl
) < 0) {
563 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl query control failed: %s\n",
564 info
.short_name
, strerror(errno
));
565 return TVI_CONTROL_FALSE
;
568 if (ioctl(priv
->video_fd
, VIDIOC_G_CTRL
, control
) < 0) {
569 mp_msg(MSGT_TV
, MSGL_ERR
,"%s: ioctl get %s failed: %s\n",
570 info
.short_name
, qctrl
.name
, strerror(errno
));
571 return TVI_CONTROL_FALSE
;
573 mp_msg(MSGT_TV
, MSGL_V
, "%s: get %s: %d [%d, %d]\n", info
.short_name
,
574 qctrl
.name
, control
->value
, qctrl
.minimum
, qctrl
.maximum
);
577 if (control
->value
< qctrl
.default_value
) {
578 control
->value
= (control
->value
- qctrl
.default_value
) * 100 /
579 (qctrl
.default_value
- qctrl
.minimum
);
581 control
->value
= (control
->value
- qctrl
.default_value
) * 100 /
582 (qctrl
.maximum
- qctrl
.default_value
);
585 if (control
->value
< qctrl
.default_value
) {
586 control
->value
= (control
->value
- qctrl
.default_value
) * 50 /
587 (qctrl
.default_value
- qctrl
.minimum
) + 50;
589 control
->value
= (control
->value
- qctrl
.default_value
) * 50 /
590 (qctrl
.maximum
- qctrl
.default_value
) + 50;
594 return TVI_CONTROL_TRUE
;
597 static int vbi_init(priv_t
* priv
,char* device
)
600 struct v4l2_capability cap
;
601 struct v4l2_format fmt
;
605 return TVI_CONTROL_FALSE
;
607 priv
->vbi_dev
=strdup(device
);
609 vbi_fd
=open(priv
->vbi_dev
,O_RDWR
);
611 mp_msg(MSGT_TV
,MSGL_ERR
,"vbi: could not open device %s\n",priv
->vbi_dev
);
612 return TVI_CONTROL_FALSE
;
615 if(ioctl(vbi_fd
,VIDIOC_QUERYCAP
,&cap
)<0){
616 mp_msg(MSGT_TV
,MSGL_ERR
,"vbi: Query capabilities failed for %s\n",priv
->vbi_dev
);
618 return TVI_CONTROL_FALSE
;
620 if(!(cap
.capabilities
& V4L2_CAP_VBI_CAPTURE
)){
621 mp_msg(MSGT_TV
,MSGL_ERR
,"vbi: %s does not support VBI capture\n",priv
->vbi_dev
);
623 return TVI_CONTROL_FALSE
;
626 memset(&fmt
,0,sizeof(struct v4l2_format
));
627 fmt
.type
=V4L2_BUF_TYPE_VBI_CAPTURE
;
628 if((res
=ioctl(vbi_fd
,VIDIOC_G_FMT
,&fmt
))<0){
629 mp_msg(MSGT_TV
,MSGL_ERR
,"vbi: Query format failed: %x\n",res
);
631 return TVI_CONTROL_FALSE
;
633 if(fmt
.fmt
.vbi
.sample_format
!=V4L2_PIX_FMT_GREY
){
634 mp_msg(MSGT_TV
,MSGL_ERR
,"vbi: format 0x%x is not supported\n",fmt
.fmt
.vbi
.sample_format
);
636 return TVI_CONTROL_FALSE
;
639 mp_msg(MSGT_TV
,MSGL_DBG3
,"vbi: init ok\n");
640 return TVI_CONTROL_TRUE
;
643 static int vbi_get_props(priv_t
* priv
,tt_stream_props
* ptsp
)
645 struct v4l2_format fmt
;
648 return TVI_CONTROL_FALSE
;
650 memset(&fmt
,0,sizeof(struct v4l2_format
));
651 fmt
.type
=V4L2_BUF_TYPE_VBI_CAPTURE
;
652 if((res
=ioctl(priv
->vbi_fd
,VIDIOC_G_FMT
,&fmt
))<0){
653 mp_msg(MSGT_TV
,MSGL_ERR
,"vbi_get_props: Query format failed: %x\n",res
);
654 return TVI_CONTROL_FALSE
;
657 ptsp
->interlaced
=(fmt
.fmt
.vbi
.flags
& V4L2_VBI_INTERLACED
?1:0);
659 ptsp
->offset
=fmt
.fmt
.vbi
.offset
;
660 ptsp
->sampling_rate
=fmt
.fmt
.vbi
.sampling_rate
;
661 ptsp
->samples_per_line
=fmt
.fmt
.vbi
.samples_per_line
,
663 ptsp
->count
[0]=fmt
.fmt
.vbi
.count
[0];
664 ptsp
->count
[1]=fmt
.fmt
.vbi
.count
[1];
665 ptsp
->bufsize
= ptsp
->samples_per_line
* (ptsp
->count
[0] + ptsp
->count
[1]);
667 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",
670 ptsp
->samples_per_line
,
671 ptsp
->interlaced
?"Yes":"No",
675 return TVI_CONTROL_TRUE
;
678 static void *vbi_grabber(void *data
)
680 priv_t
*priv
= (priv_t
*) data
;
681 int bytes
,seq
,prev_seq
;
686 mp_msg(MSGT_TV
,MSGL_WARN
,"vbi: vbi not initialized. stopping thread.\n");
690 if(vbi_get_props(priv
,&tsp
)!=TVI_CONTROL_TRUE
)
693 buf
=malloc(tsp
.bufsize
);
696 mp_msg(MSGT_TV
,MSGL_V
,"vbi: vbi capture thread started.\n");
698 while (!priv
->vbi_shutdown
){
699 bytes
=read(priv
->vbi_fd
,buf
,tsp
.bufsize
);
700 if(bytes
<0 && errno
==EINTR
)
702 if (bytes
!=tsp
.bufsize
){
703 mp_msg(MSGT_TV
,MSGL_WARN
,"vbi: expecting bytes: %d, got: %d\n",tsp
.bufsize
,bytes
);
706 seq
=*(int*)(buf
+bytes
-4);
708 if (prev_seq
&& seq
!=prev_seq
+1){
713 teletext_control(priv
->priv_vbi
,TV_VBI_CONTROL_DECODE_PAGE
,&buf
);
714 mp_msg(MSGT_TV
,MSGL_DBG3
,"grabber: seq:%d\n",seq
);
720 static int control(priv_t
*priv
, int cmd
, void *arg
)
722 struct v4l2_control control
;
723 struct v4l2_frequency frequency
;
726 case TVI_CONTROL_IS_VIDEO
:
727 return priv
->capability
.capabilities
& V4L2_CAP_VIDEO_CAPTURE
?
728 TVI_CONTROL_TRUE
: TVI_CONTROL_FALSE
;
729 case TVI_CONTROL_IS_AUDIO
:
730 if (priv
->tv_param
->force_audio
) return TVI_CONTROL_TRUE
;
731 case TVI_CONTROL_IS_TUNER
:
732 return priv
->capability
.capabilities
& V4L2_CAP_TUNER
?
733 TVI_CONTROL_TRUE
: TVI_CONTROL_FALSE
;
734 case TVI_CONTROL_IMMEDIATE
:
735 priv
->immediate_mode
= 1;
736 return TVI_CONTROL_TRUE
;
737 case TVI_CONTROL_VID_GET_FPS
:
738 *(float *)arg
= getfps(priv
);
739 mp_msg(MSGT_TV
, MSGL_V
, "%s: get fps: %f\n", info
.short_name
,
741 return TVI_CONTROL_TRUE
;
742 case TVI_CONTROL_VID_GET_BITS
:
743 if (getfmt(priv
) < 0) return TVI_CONTROL_FALSE
;
744 *(int *)arg
= pixfmt2depth(priv
->format
.fmt
.pix
.pixelformat
);
745 mp_msg(MSGT_TV
, MSGL_V
, "%s: get depth: %d\n", info
.short_name
,
747 return TVI_CONTROL_TRUE
;
748 case TVI_CONTROL_VID_GET_FORMAT
:
749 if (getfmt(priv
) < 0) return TVI_CONTROL_FALSE
;
750 *(int *)arg
= fcc_vl2mp(priv
->format
.fmt
.pix
.pixelformat
);
751 mp_msg(MSGT_TV
, MSGL_V
, "%s: get format: %s\n", info
.short_name
,
752 pixfmt2name(priv
->format
.fmt
.pix
.pixelformat
));
753 return TVI_CONTROL_TRUE
;
754 case TVI_CONTROL_VID_SET_FORMAT
:
755 if (getfmt(priv
) < 0) return TVI_CONTROL_FALSE
;
756 priv
->format
.fmt
.pix
.pixelformat
= fcc_mp2vl(*(int *)arg
);
757 priv
->format
.fmt
.pix
.field
= V4L2_FIELD_ANY
;
759 priv
->mp_format
= *(int *)arg
;
760 mp_msg(MSGT_TV
, MSGL_V
, "%s: set format: %s\n", info
.short_name
,
761 pixfmt2name(priv
->format
.fmt
.pix
.pixelformat
));
762 if (ioctl(priv
->video_fd
, VIDIOC_S_FMT
, &priv
->format
) < 0) {
763 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl set format failed: %s\n",
764 info
.short_name
, strerror(errno
));
765 return TVI_CONTROL_FALSE
;
767 /* according to the v4l2 specs VIDIOC_S_FMT should not fail, inflexible drivers
768 might even always return the default parameters -> update the format here*/
769 priv
->mp_format
= fcc_vl2mp(priv
->format
.fmt
.pix
.pixelformat
);
770 return TVI_CONTROL_TRUE
;
771 case TVI_CONTROL_VID_GET_WIDTH
:
772 if (getfmt(priv
) < 0) return TVI_CONTROL_FALSE
;
773 *(int *)arg
= priv
->format
.fmt
.pix
.width
;
774 mp_msg(MSGT_TV
, MSGL_V
, "%s: get width: %d\n", info
.short_name
,
776 return TVI_CONTROL_TRUE
;
777 case TVI_CONTROL_VID_CHK_WIDTH
:
778 return TVI_CONTROL_TRUE
;
779 case TVI_CONTROL_VID_SET_WIDTH_HEIGHT
:
780 if (getfmt(priv
) < 0) return TVI_CONTROL_FALSE
;
781 priv
->format
.fmt
.pix
.width
= ((int *)arg
)[0];
782 priv
->format
.fmt
.pix
.height
= ((int *)arg
)[1];
783 priv
->format
.fmt
.pix
.field
= V4L2_FIELD_ANY
;
784 if (ioctl(priv
->video_fd
, VIDIOC_S_FMT
, &priv
->format
) < 0)
785 return TVI_CONTROL_FALSE
;
786 return TVI_CONTROL_TRUE
;
787 case TVI_CONTROL_VID_SET_WIDTH
:
788 if (getfmt(priv
) < 0) return TVI_CONTROL_FALSE
;
789 priv
->format
.fmt
.pix
.width
= *(int *)arg
;
790 mp_msg(MSGT_TV
, MSGL_V
, "%s: set width: %d\n", info
.short_name
,
792 if (ioctl(priv
->video_fd
, VIDIOC_S_FMT
, &priv
->format
) < 0) {
793 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl set width failed: %s\n",
794 info
.short_name
, strerror(errno
));
795 return TVI_CONTROL_FALSE
;
797 return TVI_CONTROL_TRUE
;
798 case TVI_CONTROL_VID_GET_HEIGHT
:
799 if (getfmt(priv
) < 0) return TVI_CONTROL_FALSE
;
800 *(int *)arg
= priv
->format
.fmt
.pix
.height
;
801 mp_msg(MSGT_TV
, MSGL_V
, "%s: get height: %d\n", info
.short_name
,
803 return TVI_CONTROL_TRUE
;
804 case TVI_CONTROL_VID_CHK_HEIGHT
:
805 return TVI_CONTROL_TRUE
;
806 case TVI_CONTROL_VID_SET_HEIGHT
:
807 if (getfmt(priv
) < 0) return TVI_CONTROL_FALSE
;
808 priv
->format
.fmt
.pix
.height
= *(int *)arg
;
809 priv
->format
.fmt
.pix
.field
= V4L2_FIELD_ANY
;
810 mp_msg(MSGT_TV
, MSGL_V
, "%s: set height: %d\n", info
.short_name
,
812 if (ioctl(priv
->video_fd
, VIDIOC_S_FMT
, &priv
->format
) < 0) {
813 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl set height failed: %s\n",
814 info
.short_name
, strerror(errno
));
815 return TVI_CONTROL_FALSE
;
817 return TVI_CONTROL_TRUE
;
818 case TVI_CONTROL_VID_GET_BRIGHTNESS
:
819 control
.id
= V4L2_CID_BRIGHTNESS
;
820 if (get_control(priv
, &control
, 1) == TVI_CONTROL_TRUE
) {
821 *(int *)arg
= control
.value
;
822 return TVI_CONTROL_TRUE
;
824 return TVI_CONTROL_FALSE
;
825 case TVI_CONTROL_VID_SET_BRIGHTNESS
:
826 control
.id
= V4L2_CID_BRIGHTNESS
;
827 control
.value
= *(int *)arg
;
828 return set_control(priv
, &control
, 1);
829 case TVI_CONTROL_VID_GET_HUE
:
830 control
.id
= V4L2_CID_HUE
;
831 if (get_control(priv
, &control
, 1) == TVI_CONTROL_TRUE
) {
832 *(int *)arg
= control
.value
;
833 return TVI_CONTROL_TRUE
;
835 return TVI_CONTROL_FALSE
;
836 case TVI_CONTROL_VID_SET_HUE
:
837 control
.id
= V4L2_CID_HUE
;
838 control
.value
= *(int *)arg
;
839 return set_control(priv
, &control
, 1);
840 case TVI_CONTROL_VID_GET_SATURATION
:
841 control
.id
= V4L2_CID_SATURATION
;
842 if (get_control(priv
, &control
, 1) == TVI_CONTROL_TRUE
) {
843 *(int *)arg
= control
.value
;
844 return TVI_CONTROL_TRUE
;
846 return TVI_CONTROL_FALSE
;
847 case TVI_CONTROL_VID_SET_SATURATION
:
848 control
.id
= V4L2_CID_SATURATION
;
849 control
.value
= *(int *)arg
;
850 return set_control(priv
, &control
, 1);
851 case TVI_CONTROL_VID_GET_GAIN
:
854 control
.id
= V4L2_CID_AUTOGAIN
;
855 if(get_control(priv
,&control
,0)!=TVI_CONTROL_TRUE
)
856 return TVI_CONTROL_FALSE
;
858 if(control
.value
){ //Auto Gain control is enabled
860 return TVI_CONTROL_TRUE
;
863 //Manual Gain control
864 control
.id
= V4L2_CID_GAIN
;
865 if(get_control(priv
,&control
,0)!=TVI_CONTROL_TRUE
)
866 return TVI_CONTROL_FALSE
;
868 *(int*)arg
=control
.value
?control
.value
:1;
870 return TVI_CONTROL_TRUE
;
872 case TVI_CONTROL_VID_SET_GAIN
:
874 //value==0 means automatic gain control
875 int value
=*(int*)arg
;
877 if (value
< 0 || value
>100)
878 return TVI_CONTROL_FALSE
;
880 control
.id
=value
?V4L2_CID_GAIN
:V4L2_CID_AUTOGAIN
;
881 control
.value
=value
?value
:1;
883 return set_control(priv
,&control
,0);
885 case TVI_CONTROL_VID_GET_CONTRAST
:
886 control
.id
= V4L2_CID_CONTRAST
;
887 if (get_control(priv
, &control
, 1) == TVI_CONTROL_TRUE
) {
888 *(int *)arg
= control
.value
;
889 return TVI_CONTROL_TRUE
;
891 return TVI_CONTROL_FALSE
;
892 case TVI_CONTROL_VID_SET_CONTRAST
:
893 control
.id
= V4L2_CID_CONTRAST
;
894 control
.value
= *(int *)arg
;
895 return set_control(priv
, &control
, 1);
896 case TVI_CONTROL_TUN_GET_FREQ
:
898 frequency
.type
= V4L2_TUNER_ANALOG_TV
;
899 if (ioctl(priv
->video_fd
, VIDIOC_G_FREQUENCY
, &frequency
) < 0) {
900 mp_msg(MSGT_TV
,MSGL_ERR
,"%s: ioctl get frequency failed: %s\n",
901 info
.short_name
, strerror(errno
));
902 return TVI_CONTROL_FALSE
;
904 *(int *)arg
= frequency
.frequency
;
905 return TVI_CONTROL_TRUE
;
906 case TVI_CONTROL_TUN_SET_FREQ
:
909 usleep(100000); // wait to suppress noise during switching
912 frequency
.type
= V4L2_TUNER_ANALOG_TV
;
913 frequency
.frequency
= *(int *)arg
;
914 if (ioctl(priv
->video_fd
, VIDIOC_S_FREQUENCY
, &frequency
) < 0) {
915 mp_msg(MSGT_TV
,MSGL_ERR
,"%s: ioctl set frequency failed: %s\n",
916 info
.short_name
, strerror(errno
));
917 return TVI_CONTROL_FALSE
;
920 usleep(100000); // wait to suppress noise during switching
923 return TVI_CONTROL_TRUE
;
924 case TVI_CONTROL_TUN_GET_TUNER
:
925 mp_msg(MSGT_TV
, MSGL_V
, "%s: get tuner\n",info
.short_name
);
926 if (ioctl(priv
->video_fd
, VIDIOC_G_TUNER
, &priv
->tuner
) < 0) {
927 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl get tuner failed: %s\n",
928 info
.short_name
, strerror(errno
));
929 return TVI_CONTROL_FALSE
;
931 return TVI_CONTROL_TRUE
;
932 case TVI_CONTROL_TUN_SET_TUNER
:
933 mp_msg(MSGT_TV
, MSGL_V
, "%s: set tuner\n",info
.short_name
);
934 if (ioctl(priv
->video_fd
, VIDIOC_S_TUNER
, &priv
->tuner
) < 0) {
935 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl set tuner failed: %s\n",
936 info
.short_name
, strerror(errno
));
937 return TVI_CONTROL_FALSE
;
939 return TVI_CONTROL_TRUE
;
940 case TVI_CONTROL_TUN_GET_NORM
:
941 *(int *)arg
= priv
->standard
.index
;
942 return TVI_CONTROL_TRUE
;
943 case TVI_CONTROL_TUN_GET_SIGNAL
:
944 if (ioctl(priv
->video_fd
, VIDIOC_G_TUNER
, &priv
->tuner
) < 0) {
945 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl get tuner failed: %s\n",
946 info
.short_name
, strerror(errno
));
947 return TVI_CONTROL_FALSE
;
949 *(int*)arg
=100*(priv
->tuner
.signal
>>8)/255;
950 return TVI_CONTROL_TRUE
;
951 case TVI_CONTROL_TUN_SET_NORM
:
952 priv
->standard
.index
= *(int *)arg
;
953 if (ioctl(priv
->video_fd
, VIDIOC_ENUMSTD
, &priv
->standard
) < 0) {
954 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl enum norm failed: %s\n",
955 info
.short_name
, strerror(errno
));
956 return TVI_CONTROL_FALSE
;
958 mp_msg(MSGT_TV
, MSGL_V
, "%s: set norm: %s\n", info
.short_name
, priv
->standard
.name
);
959 if (ioctl(priv
->video_fd
, VIDIOC_S_STD
, &priv
->standard
.id
) < 0) {
960 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl set norm failed: %s\n",
961 info
.short_name
, strerror(errno
));
962 return TVI_CONTROL_FALSE
;
964 return TVI_CONTROL_TRUE
;
965 case TVI_CONTROL_SPC_GET_NORMID
:
969 struct v4l2_standard standard
;
970 memset(&standard
, 0, sizeof(standard
));
972 if (-1 == ioctl(priv
->video_fd
, VIDIOC_ENUMSTD
, &standard
))
973 return TVI_CONTROL_FALSE
;
974 if (!strcasecmp(standard
.name
, (char *)arg
)) {
976 return TVI_CONTROL_TRUE
;
979 return TVI_CONTROL_FALSE
;
981 case TVI_CONTROL_SPC_GET_INPUT
:
982 if (ioctl(priv
->video_fd
, VIDIOC_G_INPUT
, (int *)arg
) < 0) {
983 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl get input failed: %s\n",
984 info
.short_name
, strerror(errno
));
985 return TVI_CONTROL_FALSE
;
987 return TVI_CONTROL_TRUE
;
988 case TVI_CONTROL_SPC_SET_INPUT
:
989 mp_msg(MSGT_TV
, MSGL_V
, "%s: set input: %d\n", info
.short_name
, *(int *)arg
);
990 priv
->input
.index
= *(int *)arg
;
991 if (ioctl(priv
->video_fd
, VIDIOC_ENUMINPUT
, &priv
->input
) < 0) {
992 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl enum input failed: %s\n",
993 info
.short_name
, strerror(errno
));
994 return TVI_CONTROL_FALSE
;
996 if (ioctl(priv
->video_fd
, VIDIOC_S_INPUT
, (int *)arg
) < 0) {
997 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl set input failed: %s\n",
998 info
.short_name
, strerror(errno
));
999 return TVI_CONTROL_FALSE
;
1001 return TVI_CONTROL_TRUE
;
1002 case TVI_CONTROL_AUD_GET_FORMAT
:
1004 if (!priv
->audio_initialized
) return TVI_CONTROL_FALSE
;
1005 *(int *)arg
= AF_FORMAT_S16_LE
;
1006 mp_msg(MSGT_TV
, MSGL_V
, "%s: get audio format: %d\n",
1007 info
.short_name
, *(int *)arg
);
1008 return TVI_CONTROL_TRUE
;
1009 case TVI_CONTROL_AUD_GET_SAMPLERATE
:
1011 if (!priv
->audio_initialized
) return TVI_CONTROL_FALSE
;
1012 *(int *)arg
= priv
->audio_in
.samplerate
;
1013 mp_msg(MSGT_TV
, MSGL_V
, "%s: get audio samplerate: %d\n",
1014 info
.short_name
, *(int *)arg
);
1015 return TVI_CONTROL_TRUE
;
1016 case TVI_CONTROL_AUD_GET_SAMPLESIZE
:
1018 if (!priv
->audio_initialized
) return TVI_CONTROL_FALSE
;
1019 *(int *)arg
= priv
->audio_in
.bytes_per_sample
;
1020 mp_msg(MSGT_TV
, MSGL_V
, "%s: get audio samplesize: %d\n",
1021 info
.short_name
, *(int *)arg
);
1022 return TVI_CONTROL_TRUE
;
1023 case TVI_CONTROL_AUD_GET_CHANNELS
:
1025 if (!priv
->audio_initialized
) return TVI_CONTROL_FALSE
;
1026 *(int *)arg
= priv
->audio_in
.channels
;
1027 mp_msg(MSGT_TV
, MSGL_V
, "%s: get audio channels: %d\n",
1028 info
.short_name
, *(int *)arg
);
1029 return TVI_CONTROL_TRUE
;
1030 case TVI_CONTROL_AUD_SET_SAMPLERATE
:
1032 mp_msg(MSGT_TV
, MSGL_V
, "%s: set audio samplerate: %d\n",
1033 info
.short_name
, *(int *)arg
);
1034 if (audio_in_set_samplerate(&priv
->audio_in
, *(int*)arg
) < 0) return TVI_CONTROL_FALSE
;
1035 // setup_audio_buffer_sizes(priv);
1036 return TVI_CONTROL_TRUE
;
1037 case TVI_CONTROL_VBI_INIT
:
1040 tt_stream_props tsp
;
1042 if (vbi_init(priv
,*(char**)arg
)!=TVI_CONTROL_TRUE
)
1043 return TVI_CONTROL_FALSE
;
1044 if(vbi_get_props(priv
,&tsp
)==TVI_CONTROL_TRUE
)
1047 if(teletext_control(NULL
,TV_VBI_CONTROL_START
,&ptr
)==VBI_CONTROL_TRUE
)
1050 priv
->priv_vbi
=NULL
;
1052 return TVI_CONTROL_TRUE
;
1054 case TVI_CONTROL_GET_VBI_PTR
:
1055 *(void **)arg
=priv
->priv_vbi
;
1056 return TVI_CONTROL_TRUE
;
1058 mp_msg(MSGT_TV
, MSGL_V
, "%s: unknown control: %d\n", info
.short_name
, cmd
);
1059 return TVI_CONTROL_UNKNOWN
;
1063 #define PRIV ((priv_t *) (tvi_handle->priv))
1065 /* handler creator - entry point ! */
1066 static tvi_handle_t
*tvi_init_v4l2(tv_param_t
* tv_param
)
1068 tvi_handle_t
*tvi_handle
;
1070 tvi_handle
= tv_new_handle(sizeof(priv_t
), &functions
);
1074 PRIV
->video_fd
= -1;
1076 PRIV
->video_dev
= strdup(tv_param
->device
? tv_param
->device
: "/dev/video0");
1077 if (!PRIV
->video_dev
) {
1078 tv_free_handle(tvi_handle
);
1082 if (tv_param
->adevice
) {
1083 PRIV
->audio_dev
= strdup(tv_param
->adevice
);
1084 if (!PRIV
->audio_dev
) {
1085 free(PRIV
->video_dev
);
1086 tv_free_handle(tvi_handle
);
1091 PRIV
->tv_param
=tv_param
;
1098 static int uninit(priv_t
*priv
)
1100 int i
, frames
, dropped
= 0;
1102 priv
->vbi_shutdown
=1;
1103 if(priv
->vbi_grabber_thread
)
1104 pthread_join(priv
->vbi_grabber_thread
, NULL
);
1106 teletext_control(priv
->priv_vbi
,TV_VBI_CONTROL_STOP
,(void*)1);
1107 priv
->priv_vbi
=NULL
;
1110 close(priv
->vbi_fd
);
1114 free(priv
->vbi_dev
);
1115 priv
->vbi_dev
= NULL
;
1117 if(priv
->video_grabber_thread
)
1118 pthread_join(priv
->video_grabber_thread
, NULL
);
1119 pthread_mutex_destroy(&priv
->video_buffer_mutex
);
1121 if (priv
->streamon
) {
1122 struct v4l2_buffer buf
;
1124 /* get performance */
1125 frames
= 1 + lrintf((double)(priv
->curr_frame
- priv
->first_frame
) / 1e6
* getfps(priv
));
1126 dropped
= frames
- priv
->frames
;
1128 /* turn off streaming */
1129 if (ioctl(priv
->video_fd
, VIDIOC_STREAMOFF
, &(priv
->map
[0].buf
.type
)) < 0) {
1130 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl streamoff failed: %s\n",
1131 info
.short_name
, strerror(errno
));
1135 /* unqueue all remaining buffers */
1136 memset(&buf
,0,sizeof(buf
));
1137 buf
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1138 buf
.memory
= V4L2_MEMORY_MMAP
;
1139 while (!ioctl(priv
->video_fd
, VIDIOC_DQBUF
, &buf
));
1142 /* unmap all buffers */
1143 for (i
= 0; i
< priv
->mapcount
; i
++) {
1144 if (munmap(priv
->map
[i
].addr
, priv
->map
[i
].len
) < 0) {
1145 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: munmap capture buffer failed: %s\n",
1146 info
.short_name
, strerror(errno
));
1150 /* stop audio thread */
1151 if (!priv
->tv_param
->noaudio
&& priv
->audio_grabber_thread
) {
1152 pthread_join(priv
->audio_grabber_thread
, NULL
);
1153 pthread_mutex_destroy(&priv
->skew_mutex
);
1154 pthread_mutex_destroy(&priv
->audio_mutex
);
1159 /* free memory and close device */
1160 free(priv
->map
); priv
->map
= NULL
;
1162 if(priv
->video_fd
!=-1)close(priv
->video_fd
); priv
->video_fd
= -1;
1163 free(priv
->video_dev
); priv
->video_dev
= NULL
;
1165 if (priv
->video_ringbuffer
) {
1167 for (i
= 0; i
< priv
->video_buffer_size_current
; i
++) {
1168 free(priv
->video_ringbuffer
[i
].data
);
1170 free(priv
->video_ringbuffer
);
1172 if (!priv
->tv_param
->noaudio
) {
1173 free(priv
->audio_ringbuffer
);
1174 free(priv
->audio_skew_buffer
);
1175 free(priv
->audio_skew_delta_buffer
);
1177 audio_in_uninit(&priv
->audio_in
);
1180 /* show some nice statistics ;-) */
1181 mp_msg(MSGT_TV
, MSGL_INFO
,
1182 "%s: %d frames successfully processed, %d frames dropped.\n",
1183 info
.short_name
, priv
->frames
, dropped
);
1184 mp_msg(MSGT_TV
, MSGL_V
, "%s: up to %u video frames buffered.\n",
1185 info
.short_name
, priv
->video_buffer_size_current
);
1190 /* initialisation */
1191 static int init(priv_t
*priv
)
1195 priv
->audio_ringbuffer
= NULL
;
1196 priv
->audio_skew_buffer
= NULL
;
1197 priv
->audio_skew_delta_buffer
= NULL
;
1199 priv
->audio_initialized
= 0;
1201 /* Open the video device. */
1202 priv
->video_fd
= open(priv
->video_dev
, O_RDWR
);
1203 if (priv
->video_fd
< 0) {
1204 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: unable to open '%s': %s\n",
1205 info
.short_name
, priv
->video_dev
, strerror(errno
));
1209 mp_msg(MSGT_TV
, MSGL_DBG2
, "%s: video fd: %s: %d\n",
1210 info
.short_name
, priv
->video_dev
, priv
->video_fd
);
1213 ** Query the video capabilities and current settings
1214 ** for further control calls.
1216 if (ioctl(priv
->video_fd
, VIDIOC_QUERYCAP
, &priv
->capability
) < 0) {
1217 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl query capabilities failed: %s\n",
1218 info
.short_name
, strerror(errno
));
1223 if (!(priv
->capability
.capabilities
& V4L2_CAP_VIDEO_CAPTURE
))
1225 mp_msg(MSGT_TV
, MSGL_ERR
, "Device %s is not a video capture device.\n",
1230 if (getfmt(priv
) < 0) {
1236 ** if this device has got a tuner query it's settings
1237 ** otherwise set some nice defaults
1239 if (priv
->capability
.capabilities
& V4L2_CAP_TUNER
) {
1240 if (ioctl(priv
->video_fd
, VIDIOC_G_TUNER
, &priv
->tuner
) < 0) {
1241 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl get tuner failed: %s\n",
1242 info
.short_name
, strerror(errno
));
1247 mp_msg(MSGT_TV
, MSGL_INFO
, "Selected device: %s\n", priv
->capability
.card
);
1248 if (priv
->capability
.capabilities
& V4L2_CAP_TUNER
) {
1249 mp_msg(MSGT_TV
, MSGL_INFO
, " Tuner cap:%s%s%s\n",
1250 (priv
->tuner
.capability
& V4L2_TUNER_CAP_STEREO
) ? " STEREO" : "",
1251 (priv
->tuner
.capability
& V4L2_TUNER_CAP_LANG1
) ? " LANG1" : "",
1252 (priv
->tuner
.capability
& V4L2_TUNER_CAP_LANG2
) ? " LANG2" : "");
1253 mp_msg(MSGT_TV
, MSGL_INFO
, " Tuner rxs:%s%s%s%s\n",
1254 (priv
->tuner
.rxsubchans
& V4L2_TUNER_SUB_MONO
) ? " MONO" : "",
1255 (priv
->tuner
.rxsubchans
& V4L2_TUNER_SUB_STEREO
) ? " STEREO" : "",
1256 (priv
->tuner
.rxsubchans
& V4L2_TUNER_SUB_LANG1
) ? " LANG1" : "",
1257 (priv
->tuner
.rxsubchans
& V4L2_TUNER_SUB_LANG2
) ? " LANG2" : "");
1259 mp_msg(MSGT_TV
, MSGL_INFO
, " Capabilities:%s%s%s%s%s%s%s%s%s%s%s\n",
1260 priv
->capability
.capabilities
& V4L2_CAP_VIDEO_CAPTURE
?
1261 " video capture": "",
1262 priv
->capability
.capabilities
& V4L2_CAP_VIDEO_OUTPUT
?
1263 " video output": "",
1264 priv
->capability
.capabilities
& V4L2_CAP_VIDEO_OVERLAY
?
1265 " video overlay": "",
1266 priv
->capability
.capabilities
& V4L2_CAP_VBI_CAPTURE
?
1267 " VBI capture device": "",
1268 priv
->capability
.capabilities
& V4L2_CAP_VBI_OUTPUT
?
1270 priv
->capability
.capabilities
& V4L2_CAP_RDS_CAPTURE
?
1271 " RDS data capture": "",
1272 priv
->capability
.capabilities
& V4L2_CAP_TUNER
?
1274 priv
->capability
.capabilities
& V4L2_CAP_AUDIO
?
1276 priv
->capability
.capabilities
& V4L2_CAP_READWRITE
?
1278 priv
->capability
.capabilities
& V4L2_CAP_ASYNCIO
?
1280 priv
->capability
.capabilities
& V4L2_CAP_STREAMING
?
1282 mp_msg(MSGT_TV
, MSGL_INFO
, " supported norms:");
1284 struct v4l2_standard standard
;
1285 memset(&standard
, 0, sizeof(standard
));
1287 if (-1 == ioctl(priv
->video_fd
, VIDIOC_ENUMSTD
, &standard
))
1289 mp_msg(MSGT_TV
, MSGL_INFO
, " %d = %s;", i
, standard
.name
);
1291 mp_msg(MSGT_TV
, MSGL_INFO
, "\n inputs:");
1292 for (i
= 0; 1; i
++) {
1293 struct v4l2_input input
;
1296 if (ioctl(priv
->video_fd
, VIDIOC_ENUMINPUT
, &input
) < 0) {
1299 mp_msg(MSGT_TV
, MSGL_INFO
, " %d = %s;", i
, input
.name
);
1302 if (ioctl(priv
->video_fd
, VIDIOC_G_INPUT
, &i
) < 0) {
1303 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl get input failed: %s\n",
1304 info
.short_name
, strerror(errno
));
1306 mp_msg(MSGT_TV
, MSGL_INFO
, "\n Current input: %d\n", i
);
1307 for (i
= 0; ; i
++) {
1308 struct v4l2_fmtdesc fmtdesc
;
1311 fmtdesc
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1312 if (ioctl(priv
->video_fd
, VIDIOC_ENUM_FMT
, &fmtdesc
) < 0) {
1315 mp_msg(MSGT_TV
, MSGL_V
, " Format %-6s (%2d bits, %s): %s\n",
1316 pixfmt2name(fmtdesc
.pixelformat
), pixfmt2depth(fmtdesc
.pixelformat
),
1317 fmtdesc
.description
, vo_format_name(fcc_vl2mp(fmtdesc
.pixelformat
)));
1319 mp_msg(MSGT_TV
, MSGL_INFO
, " Current format: %s\n",
1320 pixfmt2name(priv
->format
.fmt
.pix
.pixelformat
));
1322 /* set some nice defaults */
1323 if (getfmt(priv
) < 0) return 0;
1324 priv
->format
.fmt
.pix
.width
= 640;
1325 priv
->format
.fmt
.pix
.height
= 480;
1326 if (ioctl(priv
->video_fd
, VIDIOC_S_FMT
, &priv
->format
) < 0) {
1327 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl set format failed: %s\n",
1328 info
.short_name
, strerror(errno
));
1333 // if (!(priv->capability.capabilities & V4L2_CAP_AUDIO) && !priv->tv_param->force_audio) priv->tv_param->noaudio = 1;
1335 if (priv
->capability
.capabilities
& V4L2_CAP_TUNER
) {
1336 struct v4l2_control control
;
1337 if (priv
->tv_param
->amode
>= 0) {
1338 mp_msg(MSGT_TV
, MSGL_V
, "%s: setting audio mode\n", info
.short_name
);
1339 priv
->tuner
.audmode
= amode2v4l(priv
->tv_param
->amode
);
1340 if (ioctl(priv
->video_fd
, VIDIOC_S_TUNER
, &priv
->tuner
) < 0) {
1341 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl set tuner failed: %s\n",
1342 info
.short_name
, strerror(errno
));
1343 return TVI_CONTROL_FALSE
;
1346 mp_msg(MSGT_TV
, MSGL_INFO
, "%s: current audio mode is :%s%s%s%s\n", info
.short_name
,
1347 (priv
->tuner
.audmode
== V4L2_TUNER_MODE_MONO
) ? " MONO" : "",
1348 (priv
->tuner
.audmode
== V4L2_TUNER_MODE_STEREO
) ? " STEREO" : "",
1349 (priv
->tuner
.audmode
== V4L2_TUNER_MODE_LANG1
) ? " LANG1" : "",
1350 (priv
->tuner
.audmode
== V4L2_TUNER_MODE_LANG2
) ? " LANG2" : "");
1352 if (priv
->tv_param
->volume
>= 0) {
1353 control
.id
= V4L2_CID_AUDIO_VOLUME
;
1354 control
.value
= priv
->tv_param
->volume
;
1355 set_control(priv
, &control
, 0);
1357 if (priv
->tv_param
->bass
>= 0) {
1358 control
.id
= V4L2_CID_AUDIO_BASS
;
1359 control
.value
= priv
->tv_param
->bass
;
1360 set_control(priv
, &control
, 0);
1362 if (priv
->tv_param
->treble
>= 0) {
1363 control
.id
= V4L2_CID_AUDIO_TREBLE
;
1364 control
.value
= priv
->tv_param
->treble
;
1365 set_control(priv
, &control
, 0);
1367 if (priv
->tv_param
->balance
>= 0) {
1368 control
.id
= V4L2_CID_AUDIO_BALANCE
;
1369 control
.value
= priv
->tv_param
->balance
;
1370 set_control(priv
, &control
, 0);
1377 static int get_capture_buffer_size(priv_t
*priv
)
1382 if (priv
->tv_param
->buffer_size
>= 0) {
1383 bufsize
= priv
->tv_param
->buffer_size
*1024*1024;
1385 #ifdef HAVE_SYS_SYSINFO_H
1389 bufsize
= (si
.freeram
/2)*si
.mem_unit
;
1390 if ( bufsize
< 16*1024*1024)
1392 bufsize
= 16*1024*1024;
1395 cnt
= bufsize
/priv
->format
.fmt
.pix
.sizeimage
;
1396 if (cnt
< 2) cnt
= 2;
1401 /* that's the real start, we'got the format parameters (checked with control) */
1402 static int start(priv_t
*priv
)
1404 struct v4l2_requestbuffers request
;
1407 /* setup audio parameters */
1410 if (!priv
->tv_param
->noaudio
&& !priv
->audio_initialized
) return 0;
1412 /* we need this to size the audio buffer properly */
1413 if (priv
->immediate_mode
) {
1414 priv
->video_buffer_size_max
= 2;
1416 priv
->video_buffer_size_max
= get_capture_buffer_size(priv
);
1419 if (!priv
->tv_param
->noaudio
) {
1420 setup_audio_buffer_sizes(priv
);
1421 priv
->audio_skew_buffer
= calloc(priv
->aud_skew_cnt
, sizeof(long long));
1422 if (!priv
->audio_skew_buffer
) {
1423 mp_msg(MSGT_TV
, MSGL_ERR
, "cannot allocate skew buffer: %s\n", strerror(errno
));
1426 priv
->audio_skew_delta_buffer
= calloc(priv
->aud_skew_cnt
, sizeof(long long));
1427 if (!priv
->audio_skew_delta_buffer
) {
1428 mp_msg(MSGT_TV
, MSGL_ERR
, "cannot allocate skew buffer: %s\n", strerror(errno
));
1432 priv
->audio_ringbuffer
= calloc(priv
->audio_in
.blocksize
, priv
->audio_buffer_size
);
1433 if (!priv
->audio_ringbuffer
) {
1434 mp_msg(MSGT_TV
, MSGL_ERR
, "cannot allocate audio buffer: %s\n", strerror(errno
));
1438 priv
->audio_secs_per_block
= (double)priv
->audio_in
.blocksize
/(priv
->audio_in
.samplerate
1439 *priv
->audio_in
.channels
1440 *priv
->audio_in
.bytes_per_sample
);
1441 priv
->audio_usecs_per_block
= 1e6
*priv
->audio_secs_per_block
;
1442 priv
->audio_head
= 0;
1443 priv
->audio_tail
= 0;
1444 priv
->audio_cnt
= 0;
1445 priv
->audio_drop
= 0;
1446 priv
->audio_skew
= 0;
1447 priv
->audio_skew_total
= 0;
1448 priv
->audio_skew_delta_total
= 0;
1449 priv
->audio_recv_blocks_total
= 0;
1450 priv
->audio_sent_blocks_total
= 0;
1451 priv
->audio_null_blocks_inserted
= 0;
1452 priv
->audio_insert_null_samples
= 0;
1453 priv
->dropped_frames_timeshift
= 0;
1454 priv
->dropped_frames_compensated
= 0;
1456 pthread_mutex_init(&priv
->skew_mutex
, NULL
);
1457 pthread_mutex_init(&priv
->audio_mutex
, NULL
);
1460 /* setup video parameters */
1461 if (!priv
->tv_param
->noaudio
) {
1462 if (priv
->video_buffer_size_max
< 3*getfps(priv
)*priv
->audio_secs_per_block
) {
1463 mp_msg(MSGT_TV
, MSGL_ERR
, "Video buffer shorter than 3 times audio frame duration.\n"
1464 "You will probably experience heavy framedrops.\n");
1469 int bytesperline
= priv
->format
.fmt
.pix
.width
*pixfmt2depth(priv
->format
.fmt
.pix
.pixelformat
)/8;
1471 mp_msg(MSGT_TV
, MSGL_V
, "Using a ring buffer for maximum %d frames, %d MB total size.\n",
1472 priv
->video_buffer_size_max
,
1473 priv
->video_buffer_size_max
*priv
->format
.fmt
.pix
.height
*bytesperline
/(1024*1024));
1476 priv
->video_ringbuffer
= calloc(priv
->video_buffer_size_max
, sizeof(video_buffer_entry
));
1477 if (!priv
->video_ringbuffer
) {
1478 mp_msg(MSGT_TV
, MSGL_ERR
, "cannot allocate video buffer: %s\n", strerror(errno
));
1481 memset(priv
->video_ringbuffer
,0,priv
->video_buffer_size_max
* sizeof(video_buffer_entry
));
1483 pthread_mutex_init(&priv
->video_buffer_mutex
, NULL
);
1485 priv
->video_head
= 0;
1486 priv
->video_tail
= 0;
1487 priv
->video_cnt
= 0;
1489 /* request buffers */
1490 if (priv
->immediate_mode
) {
1493 request
.count
= BUFFER_COUNT
;
1496 request
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1497 request
.memory
= V4L2_MEMORY_MMAP
;
1498 if (ioctl(priv
->video_fd
, VIDIOC_REQBUFS
, &request
) < 0) {
1499 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl request buffers failed: %s\n",
1500 info
.short_name
, strerror(errno
));
1505 if (!(priv
->map
= calloc(request
.count
, sizeof(struct map
)))) {
1506 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: malloc capture buffers failed: %s\n",
1507 info
.short_name
, strerror(errno
));
1511 /* map and queue buffers */
1512 for (i
= 0; i
< request
.count
; i
++) {
1513 memset(&priv
->map
[i
].buf
,0,sizeof(priv
->map
[i
].buf
));
1514 priv
->map
[i
].buf
.index
= i
;
1515 priv
->map
[i
].buf
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1516 priv
->map
[i
].buf
.memory
= V4L2_MEMORY_MMAP
;
1517 if (ioctl(priv
->video_fd
, VIDIOC_QUERYBUF
, &(priv
->map
[i
].buf
)) < 0) {
1518 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl query buffer failed: %s\n",
1519 info
.short_name
, strerror(errno
));
1524 priv
->map
[i
].addr
= mmap (0, priv
->map
[i
].buf
.length
, PROT_READ
|
1525 PROT_WRITE
, MAP_SHARED
, priv
->video_fd
, priv
->map
[i
].buf
.m
.offset
);
1526 if (priv
->map
[i
].addr
== MAP_FAILED
) {
1527 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: mmap capture buffer failed: %s\n",
1528 info
.short_name
, strerror(errno
));
1529 priv
->map
[i
].len
= 0;
1532 priv
->map
[i
].len
= priv
->map
[i
].buf
.length
;
1533 /* count up to make sure this is correct everytime */
1536 if (ioctl(priv
->video_fd
, VIDIOC_QBUF
, &(priv
->map
[i
].buf
)) < 0) {
1537 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl queue buffer failed: %s\n",
1538 info
.short_name
, strerror(errno
));
1543 /* start vbi thread */
1545 priv
->vbi_shutdown
= 0;
1546 pthread_create(&priv
->vbi_grabber_thread
, NULL
, vbi_grabber
, priv
);
1548 /* start audio thread */
1550 priv
->audio_skew_measure_time
= 0;
1551 priv
->first_frame
= 0;
1552 priv
->audio_skew
= 0;
1560 // copies a video frame
1561 static inline void copy_frame(priv_t
*priv
, video_buffer_entry
*dest
, unsigned char *source
,int len
)
1563 dest
->framesize
=len
;
1564 if(priv
->tv_param
->automute
>0){
1565 if (ioctl(priv
->video_fd
, VIDIOC_G_TUNER
, &priv
->tuner
) >= 0) {
1566 if(priv
->tv_param
->automute
<<8>priv
->tuner
.signal
){
1567 fill_blank_frame(dest
->data
,dest
->framesize
,fcc_vl2mp(priv
->format
.fmt
.pix
.pixelformat
));
1574 memcpy(dest
->data
, source
, len
);
1577 // maximum skew change, in frames
1578 #define MAX_SKEW_DELTA 0.6
1579 static void *video_grabber(void *data
)
1581 priv_t
*priv
= (priv_t
*)data
;
1582 long long skew
, prev_skew
, xskew
, interval
, prev_interval
, delta
;
1584 int framesize
= priv
->format
.fmt
.pix
.sizeimage
;
1586 struct timeval timeout
;
1587 struct v4l2_buffer buf
;
1595 mp_msg(MSGT_TV
, MSGL_V
, "%s: going to capture\n", info
.short_name
);
1596 if (ioctl(priv
->video_fd
, VIDIOC_STREAMON
, &(priv
->format
.type
)) < 0) {
1597 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl streamon failed: %s\n",
1598 info
.short_name
, strerror(errno
));
1603 if (!priv
->tv_param
->noaudio
) {
1604 pthread_create(&priv
->audio_grabber_thread
, NULL
, audio_grabber
, priv
);
1607 for (priv
->frames
= 0; !priv
->shutdown
;)
1611 if (priv
->immediate_mode
) {
1612 while (priv
->video_cnt
== priv
->video_buffer_size_max
) {
1614 if (priv
->shutdown
) {
1621 FD_SET (priv
->video_fd
, &rdset
);
1624 timeout
.tv_usec
= 0;
1626 i
= select(priv
->video_fd
+ 1, &rdset
, NULL
, NULL
, &timeout
);
1628 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: select failed: %s\n",
1629 info
.short_name
, strerror(errno
));
1633 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: select timeout\n", info
.short_name
);
1636 else if (!FD_ISSET(priv
->video_fd
, &rdset
)) {
1640 memset(&buf
,0,sizeof(buf
));
1641 buf
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1642 buf
.memory
= V4L2_MEMORY_MMAP
;
1643 ret
= ioctl(priv
->video_fd
, VIDIOC_DQBUF
, &buf
);
1647 if there's no signal, the buffer might me dequeued
1648 so we query all the buffers to see which one we should
1651 observed with saa7134 0.2.8
1652 don't know if is it a bug or (mis)feature
1654 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl dequeue buffer failed: %s, idx = %d\n",
1655 info
.short_name
, strerror(errno
), buf
.index
);
1656 for (i
= 0; i
< priv
->mapcount
; i
++) {
1657 memset(&buf
,0,sizeof(buf
));
1658 buf
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1659 buf
.memory
= V4L2_MEMORY_MMAP
;
1661 ret
= ioctl(priv
->video_fd
, VIDIOC_QUERYBUF
, &buf
);
1663 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl query buffer failed: %s, idx = %d\n",
1664 info
.short_name
, strerror(errno
), buf
.index
);
1667 if ((buf
.flags
& (V4L2_BUF_FLAG_QUEUED
| V4L2_BUF_FLAG_MAPPED
| V4L2_BUF_FLAG_DONE
)) == V4L2_BUF_FLAG_MAPPED
) {
1668 if (ioctl(priv
->video_fd
, VIDIOC_QBUF
, &(priv
->map
[i
].buf
)) < 0) {
1669 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl queue buffer failed: %s\n",
1670 info
.short_name
, strerror(errno
));
1678 /* store the timestamp of the very first frame as reference */
1679 if (!priv
->frames
++) {
1680 if (!priv
->tv_param
->noaudio
) pthread_mutex_lock(&priv
->skew_mutex
);
1681 priv
->first_frame
= (long long)1e6
*buf
.timestamp
.tv_sec
+ buf
.timestamp
.tv_usec
;
1682 if (!priv
->tv_param
->noaudio
) pthread_mutex_unlock(&priv
->skew_mutex
);
1684 priv
->curr_frame
= (long long)buf
.timestamp
.tv_sec
*1e6
+buf
.timestamp
.tv_usec
;
1685 // fprintf(stderr, "idx = %d, ts = %f\n", buf.index, (double)(priv->curr_frame) / 1e6);
1687 interval
= priv
->curr_frame
- priv
->first_frame
;
1688 delta
= interval
- prev_interval
;
1690 if (!priv
->immediate_mode
) {
1691 // interpolate the skew in time
1692 if (!priv
->tv_param
->noaudio
) pthread_mutex_lock(&priv
->skew_mutex
);
1693 xskew
= priv
->audio_skew
+ (interval
- priv
->audio_skew_measure_time
)*priv
->audio_skew_factor
;
1694 if (!priv
->tv_param
->noaudio
) pthread_mutex_unlock(&priv
->skew_mutex
);
1695 // correct extreme skew changes to avoid (especially) moving backwards in time
1696 if (xskew
- prev_skew
> delta
*MAX_SKEW_DELTA
) {
1697 skew
= prev_skew
+ delta
*MAX_SKEW_DELTA
;
1698 } else if (xskew
- prev_skew
< -delta
*MAX_SKEW_DELTA
) {
1699 skew
= prev_skew
- delta
*MAX_SKEW_DELTA
;
1705 mp_msg(MSGT_TV
, MSGL_DBG3
, "\nfps = %f, interval = %f, a_skew = %f, corr_skew = %f\n",
1706 delta
? (double)1e6
/delta
: -1,
1707 (double)1e-6*interval
, (double)1e-6*xskew
, (double)1e-6*skew
);
1708 mp_msg(MSGT_TV
, MSGL_DBG3
, "vcnt = %d, acnt = %d\n", priv
->video_cnt
, priv
->audio_cnt
);
1711 prev_interval
= interval
;
1713 /* allocate a new buffer, if needed */
1714 pthread_mutex_lock(&priv
->video_buffer_mutex
);
1715 if (priv
->video_buffer_size_current
< priv
->video_buffer_size_max
) {
1716 if (priv
->video_cnt
== priv
->video_buffer_size_current
) {
1717 unsigned char *newbuf
= malloc(framesize
);
1719 memmove(priv
->video_ringbuffer
+priv
->video_tail
+1, priv
->video_ringbuffer
+priv
->video_tail
,
1720 (priv
->video_buffer_size_current
-priv
->video_tail
)*sizeof(video_buffer_entry
));
1721 priv
->video_ringbuffer
[priv
->video_tail
].data
= newbuf
;
1722 if ((priv
->video_head
>= priv
->video_tail
) && (priv
->video_cnt
> 0)) priv
->video_head
++;
1723 priv
->video_buffer_size_current
++;
1727 pthread_mutex_unlock(&priv
->video_buffer_mutex
);
1729 if (priv
->video_cnt
== priv
->video_buffer_size_current
) {
1730 if (!priv
->immediate_mode
) {
1731 mp_msg(MSGT_TV
, MSGL_ERR
, "\nvideo buffer full - dropping frame\n");
1732 if (priv
->audio_insert_null_samples
) {
1733 pthread_mutex_lock(&priv
->audio_mutex
);
1734 priv
->dropped_frames_timeshift
+= delta
;
1735 pthread_mutex_unlock(&priv
->audio_mutex
);
1739 if (priv
->immediate_mode
) {
1740 priv
->video_ringbuffer
[priv
->video_tail
].timestamp
= 0;
1742 // compensate for audio skew
1743 // negative skew => there are more audio samples, increase interval
1744 // positive skew => less samples, shorten the interval
1745 priv
->video_ringbuffer
[priv
->video_tail
].timestamp
= interval
- skew
;
1746 if (priv
->audio_insert_null_samples
&& priv
->video_ringbuffer
[priv
->video_tail
].timestamp
> 0) {
1747 pthread_mutex_lock(&priv
->audio_mutex
);
1748 priv
->video_ringbuffer
[priv
->video_tail
].timestamp
+=
1749 (priv
->audio_null_blocks_inserted
1750 - priv
->dropped_frames_timeshift
/priv
->audio_usecs_per_block
)
1751 *priv
->audio_usecs_per_block
;
1752 pthread_mutex_unlock(&priv
->audio_mutex
);
1755 copy_frame(priv
, priv
->video_ringbuffer
+priv
->video_tail
, priv
->map
[buf
.index
].addr
,buf
.bytesused
);
1756 priv
->video_tail
= (priv
->video_tail
+1)%priv
->video_buffer_size_current
;
1759 if (ioctl(priv
->video_fd
, VIDIOC_QBUF
, &buf
) < 0) {
1760 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl queue buffer failed: %s\n",
1761 info
.short_name
, strerror(errno
));
1769 static double grab_video_frame(priv_t
*priv
, char *buffer
, int len
)
1775 pthread_create(&priv
->video_grabber_thread
, NULL
, video_grabber
, priv
);
1779 while (priv
->video_cnt
== 0) {
1781 if (loop_cnt
++ > MAX_LOOP
) return 0;
1784 pthread_mutex_lock(&priv
->video_buffer_mutex
);
1785 interval
= (double)priv
->video_ringbuffer
[priv
->video_head
].timestamp
*1e-6;
1786 memcpy(buffer
, priv
->video_ringbuffer
[priv
->video_head
].data
, len
);
1788 priv
->video_head
= (priv
->video_head
+1)%priv
->video_buffer_size_current
;
1789 pthread_mutex_unlock(&priv
->video_buffer_mutex
);
1794 static int get_video_framesize(priv_t
*priv
)
1797 this routine will be called before grab_video_frame
1798 thus let's return topmost frame's size
1800 if (priv
->video_cnt
)
1801 return priv
->video_ringbuffer
[priv
->video_head
].framesize
;
1803 no video frames yet available. i don't know what to do in this case,
1804 thus let's return some fallback result (for compressed format this will be
1805 maximum allowed frame size.
1807 return priv
->format
.fmt
.pix
.sizeimage
;
1810 //#define DOUBLESPEED
1812 // for testing purposes only
1813 static void read_doublespeed(priv_t
*priv
)
1815 char *bufx
= calloc(priv
->audio_in
.blocksize
, 2);
1820 audio_in_read_chunk(&priv
->audio_in
, bufx
);
1821 audio_in_read_chunk(&priv
->audio_in
, bufx
+priv
->audio_in
.blocksize
);
1824 d
= priv
->audio_ringbuffer
+priv
->audio_tail
*priv
->audio_in
.blocksize
;
1825 for (i
= 0; i
< priv
->audio_in
.blocksize
/2; i
++) {
1833 static void *audio_grabber(void *data
)
1835 priv_t
*priv
= (priv_t
*)data
;
1837 int i
, audio_skew_ptr
= 0;
1838 long long current_time
, prev_skew
= 0, prev_skew_uncorr
= 0;
1839 long long start_time_avg
;
1841 gettimeofday(&tv
, NULL
);
1842 start_time_avg
= priv
->audio_start_time
= (long long)1e6
*tv
.tv_sec
+ tv
.tv_usec
;
1843 audio_in_start_capture(&priv
->audio_in
);
1844 for (i
= 0; i
< priv
->aud_skew_cnt
; i
++)
1845 priv
->audio_skew_buffer
[i
] = 0;
1846 for (i
= 0; i
< priv
->aud_skew_cnt
; i
++)
1847 priv
->audio_skew_delta_buffer
[i
] = 0;
1849 for (; !priv
->shutdown
;)
1852 read_doublespeed(priv
);
1854 if (audio_in_read_chunk(&priv
->audio_in
, priv
->audio_ringbuffer
+priv
->audio_tail
*priv
->audio_in
.blocksize
) < 0)
1857 pthread_mutex_lock(&priv
->skew_mutex
);
1858 if (priv
->first_frame
== 0) {
1859 // there is no first frame yet (unlikely to happen)
1860 gettimeofday(&tv
, NULL
);
1861 start_time_avg
= priv
->audio_start_time
= (long long)1e6
*tv
.tv_sec
+ tv
.tv_usec
;
1862 // fprintf(stderr, "warning - first frame not yet available!\n");
1863 pthread_mutex_unlock(&priv
->skew_mutex
);
1866 pthread_mutex_unlock(&priv
->skew_mutex
);
1868 gettimeofday(&tv
, NULL
);
1870 priv
->audio_recv_blocks_total
++;
1871 current_time
= (long long)1e6
*tv
.tv_sec
+ tv
.tv_usec
- priv
->audio_start_time
;
1873 if (priv
->audio_recv_blocks_total
< priv
->aud_skew_cnt
*2) {
1874 start_time_avg
+= (long long)1e6
*tv
.tv_sec
+ tv
.tv_usec
- priv
->audio_usecs_per_block
*priv
->audio_recv_blocks_total
;
1875 priv
->audio_start_time
= start_time_avg
/(priv
->audio_recv_blocks_total
+1);
1878 // fprintf(stderr, "spb = %f, bs = %d, skew = %f\n", priv->audio_secs_per_block, priv->audio_in.blocksize,
1879 // (double)(current_time - 1e6*priv->audio_secs_per_block*priv->audio_recv_blocks_total)/1e6);
1881 // put the current skew into the ring buffer
1882 priv
->audio_skew_total
-= priv
->audio_skew_buffer
[audio_skew_ptr
];
1883 priv
->audio_skew_buffer
[audio_skew_ptr
] = current_time
1884 - priv
->audio_usecs_per_block
*priv
->audio_recv_blocks_total
;
1885 priv
->audio_skew_total
+= priv
->audio_skew_buffer
[audio_skew_ptr
];
1887 pthread_mutex_lock(&priv
->skew_mutex
);
1891 // compute the sliding average of the skews
1892 if (priv
->audio_recv_blocks_total
> priv
->aud_skew_cnt
) {
1893 priv
->audio_skew
= priv
->audio_skew_total
/priv
->aud_skew_cnt
;
1895 priv
->audio_skew
= priv
->audio_skew_total
/priv
->audio_recv_blocks_total
;
1898 // put the current skew change (skew-prev_skew) into the ring buffer
1899 priv
->audio_skew_delta_total
-= priv
->audio_skew_delta_buffer
[audio_skew_ptr
];
1900 priv
->audio_skew_delta_buffer
[audio_skew_ptr
] = priv
->audio_skew
- prev_skew_uncorr
;
1901 priv
->audio_skew_delta_total
+= priv
->audio_skew_delta_buffer
[audio_skew_ptr
];
1902 prev_skew_uncorr
= priv
->audio_skew
; // remember the _uncorrected_ average value
1904 audio_skew_ptr
= (audio_skew_ptr
+1) % priv
->aud_skew_cnt
; // rotate the buffer pointer
1906 // sliding average approximates the value in the middle of the interval
1907 // so interpolate the skew value further to the current time
1908 priv
->audio_skew
+= priv
->audio_skew_delta_total
/2;
1910 // now finally, priv->audio_skew contains fairly good approximation
1911 // of the current value
1913 // current skew factor (assuming linearity)
1914 // used for further interpolation in video_grabber
1915 // probably overkill but seems to be necessary for
1916 // stress testing by dropping half of the audio frames ;)
1917 // especially when using ALSA with large block sizes
1918 // where audio_skew remains a long while behind
1919 if ((priv
->audio_skew_measure_time
!= 0) && (current_time
- priv
->audio_skew_measure_time
!= 0)) {
1920 priv
->audio_skew_factor
= (double)(priv
->audio_skew
-prev_skew
)/(current_time
- priv
->audio_skew_measure_time
);
1922 priv
->audio_skew_factor
= 0.0;
1925 priv
->audio_skew_measure_time
= current_time
;
1926 prev_skew
= priv
->audio_skew
;
1927 priv
->audio_skew
+= priv
->audio_start_time
- priv
->first_frame
;
1928 pthread_mutex_unlock(&priv
->skew_mutex
);
1930 // fprintf(stderr, "audio_skew = %f, delta = %f\n", (double)priv->audio_skew/1e6, (double)priv->audio_skew_delta_total/1e6);
1932 pthread_mutex_lock(&priv
->audio_mutex
);
1933 if ((priv
->audio_tail
+1) % priv
->audio_buffer_size
== priv
->audio_head
) {
1934 mp_msg(MSGT_TV
, MSGL_ERR
, "\ntoo bad - dropping audio frame !\n");
1937 priv
->audio_tail
= (priv
->audio_tail
+1) % priv
->audio_buffer_size
;
1940 pthread_mutex_unlock(&priv
->audio_mutex
);
1945 static double grab_audio_frame(priv_t
*priv
, char *buffer
, int len
)
1947 mp_dbg(MSGT_TV
, MSGL_DBG2
, "grab_audio_frame(priv=%p, buffer=%p, len=%d)\n",
1950 // hack: if grab_audio_frame is called first, it means we are used by mplayer
1951 // => switch to the mode which outputs audio immediately, even if
1952 // it should be silence
1953 if (priv
->first
) priv
->audio_insert_null_samples
= 1;
1955 pthread_mutex_lock(&priv
->audio_mutex
);
1956 while (priv
->audio_insert_null_samples
1957 && priv
->dropped_frames_timeshift
- priv
->dropped_frames_compensated
>= priv
->audio_usecs_per_block
) {
1958 // some frames were dropped - drop the corresponding number of audio blocks
1959 if (priv
->audio_drop
) {
1962 if (priv
->audio_head
== priv
->audio_tail
) break;
1963 priv
->audio_head
= (priv
->audio_head
+1) % priv
->audio_buffer_size
;
1965 priv
->dropped_frames_compensated
+= priv
->audio_usecs_per_block
;
1968 // compensate for dropped audio frames
1969 if (priv
->audio_drop
&& (priv
->audio_head
== priv
->audio_tail
)) {
1971 memset(buffer
, 0, len
);
1975 if (priv
->audio_insert_null_samples
&& (priv
->audio_head
== priv
->audio_tail
)) {
1976 // return silence to avoid desync and stuttering
1977 memset(buffer
, 0, len
);
1978 priv
->audio_null_blocks_inserted
++;
1982 pthread_mutex_unlock(&priv
->audio_mutex
);
1983 while (priv
->audio_head
== priv
->audio_tail
) {
1984 // this is mencoder => just wait until some audio is available
1987 pthread_mutex_lock(&priv
->audio_mutex
);
1988 memcpy(buffer
, priv
->audio_ringbuffer
+priv
->audio_head
*priv
->audio_in
.blocksize
, len
);
1989 priv
->audio_head
= (priv
->audio_head
+1) % priv
->audio_buffer_size
;
1992 pthread_mutex_unlock(&priv
->audio_mutex
);
1993 priv
->audio_sent_blocks_total
++;
1994 return (double)priv
->audio_sent_blocks_total
*priv
->audio_secs_per_block
;
1997 static int get_audio_framesize(priv_t
*priv
)
1999 return priv
->audio_in
.blocksize
;