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 #include <linux/types.h>
53 #include <linux/videodev2.h>
55 #include "libmpcodecs/img_format.h"
56 #include "libmpcodecs/dec_teletext.h"
57 #include "libaf/af_format.h"
61 #define info tvi_info_v4l2
62 static tvi_handle_t
*tvi_init_v4l2(tv_param_t
* tv_param
);
63 /* information about this file */
64 const tvi_info_t tvi_info_v4l2
= {
66 "Video 4 Linux 2 input",
68 "Martin Olschewski <olschewski@zpr.uni-koeln.de>",
69 "first try, more to come ;-)"
73 struct v4l2_buffer buf
;
78 #define BUFFER_COUNT 6
80 /** video ringbuffer entry */
82 unsigned char *data
; ///< frame contents
83 long long timestamp
; ///< frame timestamp
84 int framesize
; ///< actual frame size
96 pthread_t vbi_grabber_thread
;
99 struct v4l2_capability capability
;
100 struct v4l2_input input
;
101 struct v4l2_format format
;
102 struct v4l2_standard standard
;
103 struct v4l2_tuner tuner
;
107 volatile long long first_frame
;
108 long long curr_frame
;
109 /* audio video interleaving ;-) */
110 volatile int streamon
;
111 pthread_t audio_grabber_thread
;
112 pthread_mutex_t skew_mutex
;
114 /* 2nd level video buffers */
118 int video_buffer_size_max
;
119 volatile int video_buffer_size_current
;
120 video_buffer_entry
*video_ringbuffer
;
121 volatile int video_head
;
122 volatile int video_tail
;
123 volatile int video_cnt
;
124 pthread_t video_grabber_thread
;
125 pthread_mutex_t video_buffer_mutex
;
131 long long audio_start_time
;
132 int audio_buffer_size
;
134 unsigned char *audio_ringbuffer
;
135 long long *audio_skew_buffer
;
136 long long *audio_skew_delta_buffer
;
137 volatile int audio_head
;
138 volatile int audio_tail
;
139 volatile int audio_cnt
;
140 volatile long long audio_skew
;
141 volatile double audio_skew_factor
;
142 volatile long long audio_skew_measure_time
;
143 volatile int audio_drop
;
144 volatile int shutdown
;
146 int audio_initialized
;
147 double audio_secs_per_block
;
148 long long audio_usecs_per_block
;
149 long long audio_skew_total
;
150 long long audio_skew_delta_total
;
151 long audio_recv_blocks_total
;
152 long audio_sent_blocks_total
;
153 pthread_mutex_t audio_mutex
;
154 int audio_insert_null_samples
;
155 volatile long audio_null_blocks_inserted
;
156 volatile long long dropped_frames_timeshift
;
157 long long dropped_frames_compensated
;
159 tv_param_t
*tv_param
;
164 static void *audio_grabber(void *data
);
165 static void *video_grabber(void *data
);
167 /**********************************************************************\
169 Only few of the fourccs are the same in v4l2 and mplayer:
171 IMGFMT_YVU9 == V4L2_PIX_FMT_YVU410
172 IMGFMT_YV12 == V4L2_PIX_FMT_YVU420
173 IMGFMT_NV12 == V4L2_PIX_FMT_NV12
174 IMGFMT_422P == V4L2_PIX_FMT_YUV422P
175 IMGFMT_411P == V4L2_PIX_FMT_YUV411P
176 IMGFMT_UYVY == V4L2_PIX_FMT_UYVY
177 IMGFMT_Y41P == V4L2_PIX_FMT_Y41P
179 This may be an useful translation table for some others:
181 IMGFMT_RGB8 == V4L2_PIX_FMT_RGB332
182 IMGFMT_BGR15 == V4L2_PIX_FMT_RGB555
183 IMGFMT_BGR16 == V4L2_PIX_FMT_RGB565
184 IMGFMT_RGB24 == V4L2_PIX_FMT_RGB24
185 IMGFMT_RGB32 == V4L2_PIX_FMT_RGB32
186 IMGFMT_BGR24 == V4L2_PIX_FMT_BGR24
187 IMGFMT_BGR32 == V4L2_PIX_FMT_BGR32
188 IMGFMT_Y800 == V4L2_PIX_FMT_GREY
189 IMGFMT_IF09 == V4L2_PIX_FMT_YUV410
190 IMGFMT_I420 == V4L2_PIX_FMT_YUV420
191 IMGFMT_YUY2 == V4L2_PIX_FMT_YUYV
193 \**********************************************************************/
196 ** Translate a mplayer fourcc to a video4linux2 pixel format.
198 static int fcc_mp2vl(int fcc
)
201 case IMGFMT_RGB8
: return V4L2_PIX_FMT_RGB332
;
202 case IMGFMT_BGR15
: return V4L2_PIX_FMT_RGB555
;
203 case IMGFMT_BGR16
: return V4L2_PIX_FMT_RGB565
;
204 case IMGFMT_RGB24
: return V4L2_PIX_FMT_RGB24
;
205 case IMGFMT_RGB32
: return V4L2_PIX_FMT_RGB32
;
206 case IMGFMT_BGR24
: return V4L2_PIX_FMT_BGR24
;
207 case IMGFMT_BGR32
: return V4L2_PIX_FMT_BGR32
;
208 case IMGFMT_Y800
: return V4L2_PIX_FMT_GREY
;
209 case IMGFMT_IF09
: return V4L2_PIX_FMT_YUV410
;
210 case IMGFMT_I420
: return V4L2_PIX_FMT_YUV420
;
211 case IMGFMT_YUY2
: return V4L2_PIX_FMT_YUYV
;
212 case IMGFMT_YV12
: return V4L2_PIX_FMT_YVU420
;
213 case IMGFMT_UYVY
: return V4L2_PIX_FMT_UYVY
;
214 case IMGFMT_MJPEG
: return V4L2_PIX_FMT_MJPEG
;
220 ** Translate a video4linux2 fourcc aka pixel format to mplayer.
222 static int fcc_vl2mp(int fcc
)
225 case V4L2_PIX_FMT_RGB332
: return IMGFMT_RGB8
;
226 case V4L2_PIX_FMT_RGB555
: return IMGFMT_BGR15
;
227 case V4L2_PIX_FMT_RGB565
: return IMGFMT_BGR16
;
228 case V4L2_PIX_FMT_RGB24
: return IMGFMT_RGB24
;
229 case V4L2_PIX_FMT_RGB32
: return IMGFMT_RGB32
;
230 case V4L2_PIX_FMT_BGR24
: return IMGFMT_BGR24
;
231 case V4L2_PIX_FMT_BGR32
: return IMGFMT_BGR32
;
232 case V4L2_PIX_FMT_GREY
: return IMGFMT_Y800
;
233 case V4L2_PIX_FMT_YUV410
: return IMGFMT_IF09
;
234 case V4L2_PIX_FMT_YUV420
: return IMGFMT_I420
;
235 case V4L2_PIX_FMT_YVU420
: return IMGFMT_YV12
;
236 case V4L2_PIX_FMT_YUYV
: return IMGFMT_YUY2
;
237 case V4L2_PIX_FMT_UYVY
: return IMGFMT_UYVY
;
238 case V4L2_PIX_FMT_MJPEG
: return IMGFMT_MJPEG
;
244 ** Translate a video4linux2 fourcc aka pixel format
245 ** to a human readable string.
247 static const char *pixfmt2name(int pixfmt
)
249 static char unknown
[24];
252 case V4L2_PIX_FMT_RGB332
: return "RGB332";
253 case V4L2_PIX_FMT_RGB555
: return "RGB555";
254 case V4L2_PIX_FMT_RGB565
: return "RGB565";
255 case V4L2_PIX_FMT_RGB555X
: return "RGB555X";
256 case V4L2_PIX_FMT_RGB565X
: return "RGB565X";
257 case V4L2_PIX_FMT_BGR24
: return "BGR24";
258 case V4L2_PIX_FMT_RGB24
: return "RGB24";
259 case V4L2_PIX_FMT_BGR32
: return "BGR32";
260 case V4L2_PIX_FMT_RGB32
: return "RGB32";
261 case V4L2_PIX_FMT_GREY
: return "GREY";
262 case V4L2_PIX_FMT_YVU410
: return "YVU410";
263 case V4L2_PIX_FMT_YVU420
: return "YVU420";
264 case V4L2_PIX_FMT_YUYV
: return "YUYV";
265 case V4L2_PIX_FMT_UYVY
: return "UYVY";
266 /* case V4L2_PIX_FMT_YVU422P: return "YVU422P"; */
267 /* case V4L2_PIX_FMT_YVU411P: return "YVU411P"; */
268 case V4L2_PIX_FMT_YUV422P
: return "YUV422P";
269 case V4L2_PIX_FMT_YUV411P
: return "YUV411P";
270 case V4L2_PIX_FMT_Y41P
: return "Y41P";
271 case V4L2_PIX_FMT_NV12
: return "NV12";
272 case V4L2_PIX_FMT_NV21
: return "NV21";
273 case V4L2_PIX_FMT_YUV410
: return "YUV410";
274 case V4L2_PIX_FMT_YUV420
: return "YUV420";
275 case V4L2_PIX_FMT_YYUV
: return "YYUV";
276 case V4L2_PIX_FMT_HI240
: return "HI240";
277 case V4L2_PIX_FMT_WNVA
: return "WNVA";
278 case V4L2_PIX_FMT_MJPEG
: return "MJPEG";
280 sprintf(unknown
, "unknown (0x%x)", pixfmt
);
286 ** Gives the depth of a video4linux2 fourcc aka pixel format in bits.
288 static int pixfmt2depth(int pixfmt
)
291 case V4L2_PIX_FMT_RGB332
:
293 case V4L2_PIX_FMT_RGB555
:
294 case V4L2_PIX_FMT_RGB565
:
295 case V4L2_PIX_FMT_RGB555X
:
296 case V4L2_PIX_FMT_RGB565X
:
298 case V4L2_PIX_FMT_BGR24
:
299 case V4L2_PIX_FMT_RGB24
:
301 case V4L2_PIX_FMT_BGR32
:
302 case V4L2_PIX_FMT_RGB32
:
304 case V4L2_PIX_FMT_GREY
:
306 case V4L2_PIX_FMT_YVU410
:
308 case V4L2_PIX_FMT_YVU420
:
310 case V4L2_PIX_FMT_YUYV
:
311 case V4L2_PIX_FMT_UYVY
:
312 case V4L2_PIX_FMT_YUV422P
:
313 case V4L2_PIX_FMT_YUV411P
:
315 case V4L2_PIX_FMT_Y41P
:
316 case V4L2_PIX_FMT_NV12
:
317 case V4L2_PIX_FMT_NV21
:
319 case V4L2_PIX_FMT_YUV410
:
321 case V4L2_PIX_FMT_YUV420
:
323 case V4L2_PIX_FMT_YYUV
:
325 case V4L2_PIX_FMT_HI240
:
332 static int amode2v4l(int amode
)
336 return V4L2_TUNER_MODE_MONO
;
338 return V4L2_TUNER_MODE_STEREO
;
340 return V4L2_TUNER_MODE_LANG1
;
342 return V4L2_TUNER_MODE_LANG2
;
352 static double getfps(priv_t
*priv
)
354 if (priv
->tv_param
->fps
> 0)
355 return priv
->tv_param
->fps
;
356 if (priv
->standard
.frameperiod
.denominator
&& priv
->standard
.frameperiod
.numerator
)
357 return (double)priv
->standard
.frameperiod
.denominator
/ priv
->standard
.frameperiod
.numerator
;
361 // sets and sanitizes audio buffer/block sizes
362 static void setup_audio_buffer_sizes(priv_t
*priv
)
364 int bytes_per_sample
= priv
->audio_in
.bytes_per_sample
;
365 int seconds
= priv
->video_buffer_size_max
/getfps(priv
);
367 if (seconds
< 5) seconds
= 5;
368 if (seconds
> 500) seconds
= 500;
370 // make the audio buffer at least as the video buffer capacity (or 5 seconds) long
371 priv
->audio_buffer_size
= 1 + seconds
*priv
->audio_in
.samplerate
372 *priv
->audio_in
.channels
373 *bytes_per_sample
/priv
->audio_in
.blocksize
;
374 if (priv
->audio_buffer_size
< 256) priv
->audio_buffer_size
= 256;
376 // make the skew buffer at least 1 second long
377 priv
->aud_skew_cnt
= 1 + 1*priv
->audio_in
.samplerate
378 *priv
->audio_in
.channels
379 *bytes_per_sample
/priv
->audio_in
.blocksize
;
380 if (priv
->aud_skew_cnt
< 16) priv
->aud_skew_cnt
= 16;
382 mp_msg(MSGT_TV
, MSGL_V
, "Audio capture - buffer %d blocks of %d bytes, skew average from %d meas.\n",
383 priv
->audio_buffer_size
, priv
->audio_in
.blocksize
, priv
->aud_skew_cnt
);
386 static void init_audio(priv_t
*priv
)
388 if (priv
->audio_initialized
) return;
390 if (!priv
->tv_param
->noaudio
) {
392 if (priv
->tv_param
->alsa
)
393 audio_in_init(&priv
->audio_in
, AUDIO_IN_ALSA
);
395 audio_in_init(&priv
->audio_in
, AUDIO_IN_OSS
);
397 audio_in_init(&priv
->audio_in
, AUDIO_IN_OSS
);
400 if (priv
->audio_dev
) {
401 audio_in_set_device(&priv
->audio_in
, priv
->audio_dev
);
404 audio_in_set_samplerate(&priv
->audio_in
, 44100);
405 if (priv
->capability
.capabilities
& V4L2_CAP_TUNER
) {
406 if (priv
->tuner
.audmode
== V4L2_TUNER_MODE_STEREO
) {
407 audio_in_set_channels(&priv
->audio_in
, 2);
409 audio_in_set_channels(&priv
->audio_in
, 1);
412 if (priv
->tv_param
->forcechan
>= 0) {
413 audio_in_set_channels(&priv
->audio_in
, priv
->tv_param
->forcechan
);
415 audio_in_set_channels(&priv
->audio_in
, 2);
419 if (audio_in_setup(&priv
->audio_in
) < 0) return;
421 priv
->audio_initialized
= 1;
427 ** the number of milliseconds elapsed between time0 and time1
429 static size_t difftv(struct timeval time1
, struct timeval time0
)
431 return (time1
.tv_sec
- time0
.tv_sec
) * 1000 +
432 (time1
.tv_usec
- time0
.tv_usec
) / 1000;
437 ** Get current video capture format.
439 static int getfmt(priv_t
*priv
)
443 priv
->format
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
444 if ((i
= ioctl(priv
->video_fd
, VIDIOC_G_FMT
, &priv
->format
)) < 0) {
445 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl get format failed: %s\n",
446 info
.short_name
, strerror(errno
));
453 ** Get current video capture standard.
455 static int getstd(priv_t
*priv
)
460 if (ioctl(priv
->video_fd
, VIDIOC_G_STD
, &id
) < 0) {
461 struct v4l2_streamparm parm
;
463 parm
.type
=V4L2_BUF_TYPE_VIDEO_CAPTURE
;
464 if(ioctl(priv
->video_fd
, VIDIOC_G_PARM
, &parm
) >= 0) {
465 mp_msg(MSGT_TV
, MSGL_WARN
, "%s: your device driver does not support VIDIOC_G_STD ioctl,"
466 " VIDIOC_G_PARM was used instead.\n", info
.short_name
);
467 priv
->standard
.index
=0;
469 priv
->standard
.frameperiod
=parm
.parm
.capture
.timeperframe
;
473 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl get standard failed: %s\n",
474 info
.short_name
, strerror(errno
));
478 priv
->standard
.index
= i
++;
479 if (ioctl(priv
->video_fd
, VIDIOC_ENUMSTD
, &priv
->standard
) < 0) {
482 } while (priv
->standard
.id
!= id
);
486 /***********************************************************************\
489 * Interface to mplayer *
492 \***********************************************************************/
494 static int set_mute(priv_t
*priv
, int value
)
496 struct v4l2_control control
;
497 control
.id
= V4L2_CID_AUDIO_MUTE
;
498 control
.value
= value
;
499 if (ioctl(priv
->video_fd
, VIDIOC_S_CTRL
, &control
) < 0) {
500 mp_msg(MSGT_TV
,MSGL_ERR
,"%s: ioctl set mute failed: %s\n",
501 info
.short_name
, strerror(errno
));
508 ** MPlayer uses values from -100 up to 100 for controls.
509 ** Here they are scaled to what the tv card needs and applied.
511 static int set_control(priv_t
*priv
, struct v4l2_control
*control
, int val_signed
) {
512 struct v4l2_queryctrl qctrl
;
513 qctrl
.id
= control
->id
;
514 if (ioctl(priv
->video_fd
, VIDIOC_QUERYCTRL
, &qctrl
) < 0) {
515 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl query control failed: %s\n",
516 info
.short_name
, strerror(errno
));
517 return TVI_CONTROL_FALSE
;
521 if (control
->value
< 0) {
522 control
->value
= qctrl
.default_value
+ control
->value
*
523 (qctrl
.default_value
- qctrl
.minimum
) / 100;
525 control
->value
= qctrl
.default_value
+ control
->value
*
526 (qctrl
.maximum
- qctrl
.default_value
) / 100;
529 if (control
->value
< 50) {
530 control
->value
= qctrl
.default_value
+ (control
->value
-50) *
531 (qctrl
.default_value
- qctrl
.minimum
) / 50;
533 control
->value
= qctrl
.default_value
+ (control
->value
-50) *
534 (qctrl
.maximum
- qctrl
.default_value
) / 50;
539 if (ioctl(priv
->video_fd
, VIDIOC_S_CTRL
, control
) < 0) {
540 mp_msg(MSGT_TV
, MSGL_ERR
,"%s: ioctl set %s %d failed: %s\n",
541 info
.short_name
, qctrl
.name
, control
->value
, strerror(errno
));
542 return TVI_CONTROL_FALSE
;
544 mp_msg(MSGT_TV
, MSGL_V
, "%s: set %s: %d [%d, %d]\n", info
.short_name
,
545 qctrl
.name
, control
->value
, qctrl
.minimum
, qctrl
.maximum
);
547 return TVI_CONTROL_TRUE
;
552 ** Scale the control values back to what mplayer needs.
554 static int get_control(priv_t
*priv
, struct v4l2_control
*control
, int val_signed
) {
555 struct v4l2_queryctrl qctrl
;
557 qctrl
.id
= control
->id
;
558 if (ioctl(priv
->video_fd
, VIDIOC_QUERYCTRL
, &qctrl
) < 0) {
559 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl query control failed: %s\n",
560 info
.short_name
, strerror(errno
));
561 return TVI_CONTROL_FALSE
;
564 if (ioctl(priv
->video_fd
, VIDIOC_G_CTRL
, control
) < 0) {
565 mp_msg(MSGT_TV
, MSGL_ERR
,"%s: ioctl get %s failed: %s\n",
566 info
.short_name
, qctrl
.name
, strerror(errno
));
567 return TVI_CONTROL_FALSE
;
569 mp_msg(MSGT_TV
, MSGL_V
, "%s: get %s: %d [%d, %d]\n", info
.short_name
,
570 qctrl
.name
, control
->value
, qctrl
.minimum
, qctrl
.maximum
);
573 if (control
->value
< qctrl
.default_value
) {
574 control
->value
= (control
->value
- qctrl
.default_value
) * 100 /
575 (qctrl
.default_value
- qctrl
.minimum
);
577 control
->value
= (control
->value
- qctrl
.default_value
) * 100 /
578 (qctrl
.maximum
- qctrl
.default_value
);
581 if (control
->value
< qctrl
.default_value
) {
582 control
->value
= (control
->value
- qctrl
.default_value
) * 50 /
583 (qctrl
.default_value
- qctrl
.minimum
) + 50;
585 control
->value
= (control
->value
- qctrl
.default_value
) * 50 /
586 (qctrl
.maximum
- qctrl
.default_value
) + 50;
590 return TVI_CONTROL_TRUE
;
593 static int vbi_init(priv_t
* priv
,char* device
)
596 struct v4l2_capability cap
;
597 struct v4l2_format fmt
;
601 return TVI_CONTROL_FALSE
;
603 priv
->vbi_dev
=strdup(device
);
605 vbi_fd
=open(priv
->vbi_dev
,O_RDWR
);
607 mp_msg(MSGT_TV
,MSGL_ERR
,"vbi: could not open device %s\n",priv
->vbi_dev
);
608 return TVI_CONTROL_FALSE
;
611 if(ioctl(vbi_fd
,VIDIOC_QUERYCAP
,&cap
)<0){
612 mp_msg(MSGT_TV
,MSGL_ERR
,"vbi: Query capabilities failed for %s\n",priv
->vbi_dev
);
614 return TVI_CONTROL_FALSE
;
616 if(!(cap
.capabilities
& V4L2_CAP_VBI_CAPTURE
)){
617 mp_msg(MSGT_TV
,MSGL_ERR
,"vbi: %s does not support VBI capture\n",priv
->vbi_dev
);
619 return TVI_CONTROL_FALSE
;
622 memset(&fmt
,0,sizeof(struct v4l2_format
));
623 fmt
.type
=V4L2_BUF_TYPE_VBI_CAPTURE
;
624 if((res
=ioctl(vbi_fd
,VIDIOC_G_FMT
,&fmt
))<0){
625 mp_msg(MSGT_TV
,MSGL_ERR
,"vbi: Query format failed: %x\n",res
);
627 return TVI_CONTROL_FALSE
;
629 if(fmt
.fmt
.vbi
.sample_format
!=V4L2_PIX_FMT_GREY
){
630 mp_msg(MSGT_TV
,MSGL_ERR
,"vbi: format 0x%x is not supported\n",fmt
.fmt
.vbi
.sample_format
);
632 return TVI_CONTROL_FALSE
;
635 mp_msg(MSGT_TV
,MSGL_DBG3
,"vbi: init ok\n");
636 return TVI_CONTROL_TRUE
;
639 static int vbi_get_props(priv_t
* priv
,tt_stream_props
* ptsp
)
641 struct v4l2_format fmt
;
644 return TVI_CONTROL_FALSE
;
646 memset(&fmt
,0,sizeof(struct v4l2_format
));
647 fmt
.type
=V4L2_BUF_TYPE_VBI_CAPTURE
;
648 if((res
=ioctl(priv
->vbi_fd
,VIDIOC_G_FMT
,&fmt
))<0){
649 mp_msg(MSGT_TV
,MSGL_ERR
,"vbi_get_props: Query format failed: %x\n",res
);
650 return TVI_CONTROL_FALSE
;
653 ptsp
->interlaced
=(fmt
.fmt
.vbi
.flags
& V4L2_VBI_INTERLACED
?1:0);
655 ptsp
->offset
=fmt
.fmt
.vbi
.offset
;
656 ptsp
->sampling_rate
=fmt
.fmt
.vbi
.sampling_rate
;
657 ptsp
->samples_per_line
=fmt
.fmt
.vbi
.samples_per_line
,
659 ptsp
->count
[0]=fmt
.fmt
.vbi
.count
[0];
660 ptsp
->count
[1]=fmt
.fmt
.vbi
.count
[1];
661 ptsp
->bufsize
= ptsp
->samples_per_line
* (ptsp
->count
[0] + ptsp
->count
[1]);
663 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",
666 ptsp
->samples_per_line
,
667 ptsp
->interlaced
?"Yes":"No",
671 return TVI_CONTROL_TRUE
;
674 static void *vbi_grabber(void *data
)
676 priv_t
*priv
= (priv_t
*) data
;
677 int bytes
,seq
,prev_seq
;
682 mp_msg(MSGT_TV
,MSGL_WARN
,"vbi: vbi not initialized. stopping thread.\n");
686 if(vbi_get_props(priv
,&tsp
)!=TVI_CONTROL_TRUE
)
689 buf
=malloc(tsp
.bufsize
);
692 mp_msg(MSGT_TV
,MSGL_V
,"vbi: vbi capture thread started.\n");
694 while (!priv
->vbi_shutdown
){
695 bytes
=read(priv
->vbi_fd
,buf
,tsp
.bufsize
);
696 if(bytes
<0 && errno
==EINTR
)
698 if (bytes
!=tsp
.bufsize
){
699 mp_msg(MSGT_TV
,MSGL_WARN
,"vbi: expecting bytes: %d, got: %d\n",tsp
.bufsize
,bytes
);
702 seq
=*(int*)(buf
+bytes
-4);
704 if (prev_seq
&& seq
!=prev_seq
+1){
709 teletext_control(priv
->priv_vbi
,TV_VBI_CONTROL_DECODE_PAGE
,&buf
);
710 mp_msg(MSGT_TV
,MSGL_DBG3
,"grabber: seq:%d\n",seq
);
716 static int control(priv_t
*priv
, int cmd
, void *arg
)
718 struct v4l2_control control
;
719 struct v4l2_frequency frequency
;
722 case TVI_CONTROL_IS_VIDEO
:
723 return priv
->capability
.capabilities
& V4L2_CAP_VIDEO_CAPTURE
?
724 TVI_CONTROL_TRUE
: TVI_CONTROL_FALSE
;
725 case TVI_CONTROL_IS_AUDIO
:
726 if (priv
->tv_param
->force_audio
) return TVI_CONTROL_TRUE
;
727 case TVI_CONTROL_IS_TUNER
:
728 return priv
->capability
.capabilities
& V4L2_CAP_TUNER
?
729 TVI_CONTROL_TRUE
: TVI_CONTROL_FALSE
;
730 case TVI_CONTROL_IMMEDIATE
:
731 priv
->immediate_mode
= 1;
732 return TVI_CONTROL_TRUE
;
733 case TVI_CONTROL_VID_GET_FPS
:
734 *(float *)arg
= getfps(priv
);
735 mp_msg(MSGT_TV
, MSGL_V
, "%s: get fps: %f\n", info
.short_name
,
737 return TVI_CONTROL_TRUE
;
738 case TVI_CONTROL_VID_GET_BITS
:
739 if (getfmt(priv
) < 0) return TVI_CONTROL_FALSE
;
740 *(int *)arg
= pixfmt2depth(priv
->format
.fmt
.pix
.pixelformat
);
741 mp_msg(MSGT_TV
, MSGL_V
, "%s: get depth: %d\n", info
.short_name
,
743 return TVI_CONTROL_TRUE
;
744 case TVI_CONTROL_VID_GET_FORMAT
:
745 if (getfmt(priv
) < 0) return TVI_CONTROL_FALSE
;
746 *(int *)arg
= fcc_vl2mp(priv
->format
.fmt
.pix
.pixelformat
);
747 mp_msg(MSGT_TV
, MSGL_V
, "%s: get format: %s\n", info
.short_name
,
748 pixfmt2name(priv
->format
.fmt
.pix
.pixelformat
));
749 return TVI_CONTROL_TRUE
;
750 case TVI_CONTROL_VID_SET_FORMAT
:
751 if (getfmt(priv
) < 0) return TVI_CONTROL_FALSE
;
752 priv
->format
.fmt
.pix
.pixelformat
= fcc_mp2vl(*(int *)arg
);
753 priv
->format
.fmt
.pix
.field
= V4L2_FIELD_ANY
;
755 priv
->mp_format
= *(int *)arg
;
756 mp_msg(MSGT_TV
, MSGL_V
, "%s: set format: %s\n", info
.short_name
,
757 pixfmt2name(priv
->format
.fmt
.pix
.pixelformat
));
758 if (ioctl(priv
->video_fd
, VIDIOC_S_FMT
, &priv
->format
) < 0) {
759 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl set format failed: %s\n",
760 info
.short_name
, strerror(errno
));
761 return TVI_CONTROL_FALSE
;
763 /* according to the v4l2 specs VIDIOC_S_FMT should not fail, inflexible drivers
764 might even always return the default parameters -> update the format here*/
765 priv
->mp_format
= fcc_vl2mp(priv
->format
.fmt
.pix
.pixelformat
);
766 return TVI_CONTROL_TRUE
;
767 case TVI_CONTROL_VID_GET_WIDTH
:
768 if (getfmt(priv
) < 0) return TVI_CONTROL_FALSE
;
769 *(int *)arg
= priv
->format
.fmt
.pix
.width
;
770 mp_msg(MSGT_TV
, MSGL_V
, "%s: get width: %d\n", info
.short_name
,
772 return TVI_CONTROL_TRUE
;
773 case TVI_CONTROL_VID_CHK_WIDTH
:
774 return TVI_CONTROL_TRUE
;
775 case TVI_CONTROL_VID_SET_WIDTH_HEIGHT
:
776 if (getfmt(priv
) < 0) return TVI_CONTROL_FALSE
;
777 priv
->format
.fmt
.pix
.width
= ((int *)arg
)[0];
778 priv
->format
.fmt
.pix
.height
= ((int *)arg
)[1];
779 priv
->format
.fmt
.pix
.field
= V4L2_FIELD_ANY
;
780 if (ioctl(priv
->video_fd
, VIDIOC_S_FMT
, &priv
->format
) < 0)
781 return TVI_CONTROL_FALSE
;
782 return TVI_CONTROL_TRUE
;
783 case TVI_CONTROL_VID_SET_WIDTH
:
784 if (getfmt(priv
) < 0) return TVI_CONTROL_FALSE
;
785 priv
->format
.fmt
.pix
.width
= *(int *)arg
;
786 mp_msg(MSGT_TV
, MSGL_V
, "%s: set width: %d\n", info
.short_name
,
788 if (ioctl(priv
->video_fd
, VIDIOC_S_FMT
, &priv
->format
) < 0) {
789 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl set width failed: %s\n",
790 info
.short_name
, strerror(errno
));
791 return TVI_CONTROL_FALSE
;
793 return TVI_CONTROL_TRUE
;
794 case TVI_CONTROL_VID_GET_HEIGHT
:
795 if (getfmt(priv
) < 0) return TVI_CONTROL_FALSE
;
796 *(int *)arg
= priv
->format
.fmt
.pix
.height
;
797 mp_msg(MSGT_TV
, MSGL_V
, "%s: get height: %d\n", info
.short_name
,
799 return TVI_CONTROL_TRUE
;
800 case TVI_CONTROL_VID_CHK_HEIGHT
:
801 return TVI_CONTROL_TRUE
;
802 case TVI_CONTROL_VID_SET_HEIGHT
:
803 if (getfmt(priv
) < 0) return TVI_CONTROL_FALSE
;
804 priv
->format
.fmt
.pix
.height
= *(int *)arg
;
805 priv
->format
.fmt
.pix
.field
= V4L2_FIELD_ANY
;
806 mp_msg(MSGT_TV
, MSGL_V
, "%s: set height: %d\n", info
.short_name
,
808 if (ioctl(priv
->video_fd
, VIDIOC_S_FMT
, &priv
->format
) < 0) {
809 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl set height failed: %s\n",
810 info
.short_name
, strerror(errno
));
811 return TVI_CONTROL_FALSE
;
813 return TVI_CONTROL_TRUE
;
814 case TVI_CONTROL_VID_GET_BRIGHTNESS
:
815 control
.id
= V4L2_CID_BRIGHTNESS
;
816 if (get_control(priv
, &control
, 1) == TVI_CONTROL_TRUE
) {
817 *(int *)arg
= control
.value
;
818 return TVI_CONTROL_TRUE
;
820 return TVI_CONTROL_FALSE
;
821 case TVI_CONTROL_VID_SET_BRIGHTNESS
:
822 control
.id
= V4L2_CID_BRIGHTNESS
;
823 control
.value
= *(int *)arg
;
824 return set_control(priv
, &control
, 1);
825 case TVI_CONTROL_VID_GET_HUE
:
826 control
.id
= V4L2_CID_HUE
;
827 if (get_control(priv
, &control
, 1) == TVI_CONTROL_TRUE
) {
828 *(int *)arg
= control
.value
;
829 return TVI_CONTROL_TRUE
;
831 return TVI_CONTROL_FALSE
;
832 case TVI_CONTROL_VID_SET_HUE
:
833 control
.id
= V4L2_CID_HUE
;
834 control
.value
= *(int *)arg
;
835 return set_control(priv
, &control
, 1);
836 case TVI_CONTROL_VID_GET_SATURATION
:
837 control
.id
= V4L2_CID_SATURATION
;
838 if (get_control(priv
, &control
, 1) == TVI_CONTROL_TRUE
) {
839 *(int *)arg
= control
.value
;
840 return TVI_CONTROL_TRUE
;
842 return TVI_CONTROL_FALSE
;
843 case TVI_CONTROL_VID_SET_SATURATION
:
844 control
.id
= V4L2_CID_SATURATION
;
845 control
.value
= *(int *)arg
;
846 return set_control(priv
, &control
, 1);
847 case TVI_CONTROL_VID_GET_GAIN
:
850 control
.id
= V4L2_CID_AUTOGAIN
;
851 if(get_control(priv
,&control
,0)!=TVI_CONTROL_TRUE
)
852 return TVI_CONTROL_FALSE
;
854 if(control
.value
){ //Auto Gain control is enabled
856 return TVI_CONTROL_TRUE
;
859 //Manual Gain control
860 control
.id
= V4L2_CID_GAIN
;
861 if(get_control(priv
,&control
,0)!=TVI_CONTROL_TRUE
)
862 return TVI_CONTROL_FALSE
;
864 *(int*)arg
=control
.value
?control
.value
:1;
866 return TVI_CONTROL_TRUE
;
868 case TVI_CONTROL_VID_SET_GAIN
:
870 //value==0 means automatic gain control
871 int value
=*(int*)arg
;
873 if (value
< 0 || value
>100)
874 return TVI_CONTROL_FALSE
;
876 control
.id
=value
?V4L2_CID_GAIN
:V4L2_CID_AUTOGAIN
;
877 control
.value
=value
?value
:1;
879 return set_control(priv
,&control
,0);
881 case TVI_CONTROL_VID_GET_CONTRAST
:
882 control
.id
= V4L2_CID_CONTRAST
;
883 if (get_control(priv
, &control
, 1) == TVI_CONTROL_TRUE
) {
884 *(int *)arg
= control
.value
;
885 return TVI_CONTROL_TRUE
;
887 return TVI_CONTROL_FALSE
;
888 case TVI_CONTROL_VID_SET_CONTRAST
:
889 control
.id
= V4L2_CID_CONTRAST
;
890 control
.value
= *(int *)arg
;
891 return set_control(priv
, &control
, 1);
892 case TVI_CONTROL_TUN_GET_FREQ
:
894 frequency
.type
= V4L2_TUNER_ANALOG_TV
;
895 if (ioctl(priv
->video_fd
, VIDIOC_G_FREQUENCY
, &frequency
) < 0) {
896 mp_msg(MSGT_TV
,MSGL_ERR
,"%s: ioctl get frequency failed: %s\n",
897 info
.short_name
, strerror(errno
));
898 return TVI_CONTROL_FALSE
;
900 *(int *)arg
= frequency
.frequency
;
901 return TVI_CONTROL_TRUE
;
902 case TVI_CONTROL_TUN_SET_FREQ
:
905 usleep(100000); // wait to suppress noise during switching
908 frequency
.type
= V4L2_TUNER_ANALOG_TV
;
909 frequency
.frequency
= *(int *)arg
;
910 if (ioctl(priv
->video_fd
, VIDIOC_S_FREQUENCY
, &frequency
) < 0) {
911 mp_msg(MSGT_TV
,MSGL_ERR
,"%s: ioctl set frequency failed: %s\n",
912 info
.short_name
, strerror(errno
));
913 return TVI_CONTROL_FALSE
;
916 usleep(100000); // wait to suppress noise during switching
919 return TVI_CONTROL_TRUE
;
920 case TVI_CONTROL_TUN_GET_TUNER
:
921 mp_msg(MSGT_TV
, MSGL_V
, "%s: get tuner\n",info
.short_name
);
922 if (ioctl(priv
->video_fd
, VIDIOC_G_TUNER
, &priv
->tuner
) < 0) {
923 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl get tuner failed: %s\n",
924 info
.short_name
, strerror(errno
));
925 return TVI_CONTROL_FALSE
;
927 return TVI_CONTROL_TRUE
;
928 case TVI_CONTROL_TUN_SET_TUNER
:
929 mp_msg(MSGT_TV
, MSGL_V
, "%s: set tuner\n",info
.short_name
);
930 if (ioctl(priv
->video_fd
, VIDIOC_S_TUNER
, &priv
->tuner
) < 0) {
931 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl set tuner failed: %s\n",
932 info
.short_name
, strerror(errno
));
933 return TVI_CONTROL_FALSE
;
935 return TVI_CONTROL_TRUE
;
936 case TVI_CONTROL_TUN_GET_NORM
:
937 *(int *)arg
= priv
->standard
.index
;
938 return TVI_CONTROL_TRUE
;
939 case TVI_CONTROL_TUN_GET_SIGNAL
:
940 if (ioctl(priv
->video_fd
, VIDIOC_G_TUNER
, &priv
->tuner
) < 0) {
941 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl get tuner failed: %s\n",
942 info
.short_name
, strerror(errno
));
943 return TVI_CONTROL_FALSE
;
945 *(int*)arg
=100*(priv
->tuner
.signal
>>8)/255;
946 return TVI_CONTROL_TRUE
;
947 case TVI_CONTROL_TUN_SET_NORM
:
948 priv
->standard
.index
= *(int *)arg
;
949 if (ioctl(priv
->video_fd
, VIDIOC_ENUMSTD
, &priv
->standard
) < 0) {
950 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl enum norm failed: %s\n",
951 info
.short_name
, strerror(errno
));
952 return TVI_CONTROL_FALSE
;
954 mp_msg(MSGT_TV
, MSGL_V
, "%s: set norm: %s\n", info
.short_name
, priv
->standard
.name
);
955 if (ioctl(priv
->video_fd
, VIDIOC_S_STD
, &priv
->standard
.id
) < 0) {
956 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl set norm failed: %s\n",
957 info
.short_name
, strerror(errno
));
958 return TVI_CONTROL_FALSE
;
960 return TVI_CONTROL_TRUE
;
961 case TVI_CONTROL_SPC_GET_NORMID
:
965 struct v4l2_standard standard
;
966 memset(&standard
, 0, sizeof(standard
));
968 if (-1 == ioctl(priv
->video_fd
, VIDIOC_ENUMSTD
, &standard
))
969 return TVI_CONTROL_FALSE
;
970 if (!strcasecmp(standard
.name
, (char *)arg
)) {
972 return TVI_CONTROL_TRUE
;
975 return TVI_CONTROL_FALSE
;
977 case TVI_CONTROL_SPC_GET_INPUT
:
978 if (ioctl(priv
->video_fd
, VIDIOC_G_INPUT
, (int *)arg
) < 0) {
979 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl get input failed: %s\n",
980 info
.short_name
, strerror(errno
));
981 return TVI_CONTROL_FALSE
;
983 return TVI_CONTROL_TRUE
;
984 case TVI_CONTROL_SPC_SET_INPUT
:
985 mp_msg(MSGT_TV
, MSGL_V
, "%s: set input: %d\n", info
.short_name
, *(int *)arg
);
986 priv
->input
.index
= *(int *)arg
;
987 if (ioctl(priv
->video_fd
, VIDIOC_ENUMINPUT
, &priv
->input
) < 0) {
988 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl enum input failed: %s\n",
989 info
.short_name
, strerror(errno
));
990 return TVI_CONTROL_FALSE
;
992 if (ioctl(priv
->video_fd
, VIDIOC_S_INPUT
, (int *)arg
) < 0) {
993 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl set input failed: %s\n",
994 info
.short_name
, strerror(errno
));
995 return TVI_CONTROL_FALSE
;
997 return TVI_CONTROL_TRUE
;
998 case TVI_CONTROL_AUD_GET_FORMAT
:
1000 if (!priv
->audio_initialized
) return TVI_CONTROL_FALSE
;
1001 *(int *)arg
= AF_FORMAT_S16_LE
;
1002 mp_msg(MSGT_TV
, MSGL_V
, "%s: get audio format: %d\n",
1003 info
.short_name
, *(int *)arg
);
1004 return TVI_CONTROL_TRUE
;
1005 case TVI_CONTROL_AUD_GET_SAMPLERATE
:
1007 if (!priv
->audio_initialized
) return TVI_CONTROL_FALSE
;
1008 *(int *)arg
= priv
->audio_in
.samplerate
;
1009 mp_msg(MSGT_TV
, MSGL_V
, "%s: get audio samplerate: %d\n",
1010 info
.short_name
, *(int *)arg
);
1011 return TVI_CONTROL_TRUE
;
1012 case TVI_CONTROL_AUD_GET_SAMPLESIZE
:
1014 if (!priv
->audio_initialized
) return TVI_CONTROL_FALSE
;
1015 *(int *)arg
= priv
->audio_in
.bytes_per_sample
;
1016 mp_msg(MSGT_TV
, MSGL_V
, "%s: get audio samplesize: %d\n",
1017 info
.short_name
, *(int *)arg
);
1018 return TVI_CONTROL_TRUE
;
1019 case TVI_CONTROL_AUD_GET_CHANNELS
:
1021 if (!priv
->audio_initialized
) return TVI_CONTROL_FALSE
;
1022 *(int *)arg
= priv
->audio_in
.channels
;
1023 mp_msg(MSGT_TV
, MSGL_V
, "%s: get audio channels: %d\n",
1024 info
.short_name
, *(int *)arg
);
1025 return TVI_CONTROL_TRUE
;
1026 case TVI_CONTROL_AUD_SET_SAMPLERATE
:
1028 mp_msg(MSGT_TV
, MSGL_V
, "%s: set audio samplerate: %d\n",
1029 info
.short_name
, *(int *)arg
);
1030 if (audio_in_set_samplerate(&priv
->audio_in
, *(int*)arg
) < 0) return TVI_CONTROL_FALSE
;
1031 // setup_audio_buffer_sizes(priv);
1032 return TVI_CONTROL_TRUE
;
1033 case TVI_CONTROL_VBI_INIT
:
1036 tt_stream_props tsp
;
1038 if (vbi_init(priv
,*(char**)arg
)!=TVI_CONTROL_TRUE
)
1039 return TVI_CONTROL_FALSE
;
1040 if(vbi_get_props(priv
,&tsp
)==TVI_CONTROL_TRUE
)
1043 if(teletext_control(NULL
,TV_VBI_CONTROL_START
,&ptr
)==VBI_CONTROL_TRUE
)
1046 priv
->priv_vbi
=NULL
;
1048 return TVI_CONTROL_TRUE
;
1050 case TVI_CONTROL_GET_VBI_PTR
:
1051 *(void **)arg
=priv
->priv_vbi
;
1052 return TVI_CONTROL_TRUE
;
1054 mp_msg(MSGT_TV
, MSGL_V
, "%s: unknown control: %d\n", info
.short_name
, cmd
);
1055 return TVI_CONTROL_UNKNOWN
;
1059 #define PRIV ((priv_t *) (tvi_handle->priv))
1061 /* handler creator - entry point ! */
1062 static tvi_handle_t
*tvi_init_v4l2(tv_param_t
* tv_param
)
1064 tvi_handle_t
*tvi_handle
;
1066 tvi_handle
= tv_new_handle(sizeof(priv_t
), &functions
);
1070 PRIV
->video_fd
= -1;
1072 PRIV
->video_dev
= strdup(tv_param
->device
? tv_param
->device
: "/dev/video0");
1073 if (!PRIV
->video_dev
) {
1074 tv_free_handle(tvi_handle
);
1078 if (tv_param
->adevice
) {
1079 PRIV
->audio_dev
= strdup(tv_param
->adevice
);
1080 if (!PRIV
->audio_dev
) {
1081 free(PRIV
->video_dev
);
1082 tv_free_handle(tvi_handle
);
1087 PRIV
->tv_param
=tv_param
;
1094 static int uninit(priv_t
*priv
)
1096 int i
, frames
, dropped
= 0;
1098 priv
->vbi_shutdown
=1;
1099 if(priv
->vbi_grabber_thread
)
1100 pthread_join(priv
->vbi_grabber_thread
, NULL
);
1102 teletext_control(priv
->priv_vbi
,TV_VBI_CONTROL_STOP
,(void*)1);
1103 priv
->priv_vbi
=NULL
;
1106 close(priv
->vbi_fd
);
1110 free(priv
->vbi_dev
);
1111 priv
->vbi_dev
= NULL
;
1113 if(priv
->video_grabber_thread
)
1114 pthread_join(priv
->video_grabber_thread
, NULL
);
1115 pthread_mutex_destroy(&priv
->video_buffer_mutex
);
1117 if (priv
->streamon
) {
1118 struct v4l2_buffer buf
;
1120 /* get performance */
1121 frames
= 1 + lrintf((double)(priv
->curr_frame
- priv
->first_frame
) / 1e6
* getfps(priv
));
1122 dropped
= frames
- priv
->frames
;
1124 /* turn off streaming */
1125 if (ioctl(priv
->video_fd
, VIDIOC_STREAMOFF
, &(priv
->map
[0].buf
.type
)) < 0) {
1126 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl streamoff failed: %s\n",
1127 info
.short_name
, strerror(errno
));
1131 /* unqueue all remaining buffers */
1132 memset(&buf
,0,sizeof(buf
));
1133 buf
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1134 buf
.memory
= V4L2_MEMORY_MMAP
;
1135 while (!ioctl(priv
->video_fd
, VIDIOC_DQBUF
, &buf
));
1138 /* unmap all buffers */
1139 for (i
= 0; i
< priv
->mapcount
; i
++) {
1140 if (munmap(priv
->map
[i
].addr
, priv
->map
[i
].len
) < 0) {
1141 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: munmap capture buffer failed: %s\n",
1142 info
.short_name
, strerror(errno
));
1146 /* stop audio thread */
1147 if (!priv
->tv_param
->noaudio
&& priv
->audio_grabber_thread
) {
1148 pthread_join(priv
->audio_grabber_thread
, NULL
);
1149 pthread_mutex_destroy(&priv
->skew_mutex
);
1150 pthread_mutex_destroy(&priv
->audio_mutex
);
1155 /* free memory and close device */
1156 free(priv
->map
); priv
->map
= NULL
;
1158 if(priv
->video_fd
!=-1)close(priv
->video_fd
); priv
->video_fd
= -1;
1159 free(priv
->video_dev
); priv
->video_dev
= NULL
;
1161 if (priv
->video_ringbuffer
) {
1163 for (i
= 0; i
< priv
->video_buffer_size_current
; i
++) {
1164 free(priv
->video_ringbuffer
[i
].data
);
1166 free(priv
->video_ringbuffer
);
1168 if (!priv
->tv_param
->noaudio
) {
1169 free(priv
->audio_ringbuffer
);
1170 free(priv
->audio_skew_buffer
);
1171 free(priv
->audio_skew_delta_buffer
);
1173 audio_in_uninit(&priv
->audio_in
);
1176 /* show some nice statistics ;-) */
1177 mp_msg(MSGT_TV
, MSGL_INFO
,
1178 "%s: %d frames successfully processed, %d frames dropped.\n",
1179 info
.short_name
, priv
->frames
, dropped
);
1180 mp_msg(MSGT_TV
, MSGL_V
, "%s: up to %u video frames buffered.\n",
1181 info
.short_name
, priv
->video_buffer_size_current
);
1186 /* initialisation */
1187 static int init(priv_t
*priv
)
1191 priv
->audio_ringbuffer
= NULL
;
1192 priv
->audio_skew_buffer
= NULL
;
1193 priv
->audio_skew_delta_buffer
= NULL
;
1195 priv
->audio_initialized
= 0;
1197 /* Open the video device. */
1198 priv
->video_fd
= open(priv
->video_dev
, O_RDWR
);
1199 if (priv
->video_fd
< 0) {
1200 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: unable to open '%s': %s\n",
1201 info
.short_name
, priv
->video_dev
, strerror(errno
));
1205 mp_msg(MSGT_TV
, MSGL_DBG2
, "%s: video fd: %s: %d\n",
1206 info
.short_name
, priv
->video_dev
, priv
->video_fd
);
1209 ** Query the video capabilities and current settings
1210 ** for further control calls.
1212 if (ioctl(priv
->video_fd
, VIDIOC_QUERYCAP
, &priv
->capability
) < 0) {
1213 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl query capabilities failed: %s\n",
1214 info
.short_name
, strerror(errno
));
1219 if (!(priv
->capability
.capabilities
& V4L2_CAP_VIDEO_CAPTURE
))
1221 mp_msg(MSGT_TV
, MSGL_ERR
, "Device %s is not a video capture device.\n",
1226 if (getfmt(priv
) < 0) {
1232 ** if this device has got a tuner query it's settings
1233 ** otherwise set some nice defaults
1235 if (priv
->capability
.capabilities
& V4L2_CAP_TUNER
) {
1236 if (ioctl(priv
->video_fd
, VIDIOC_G_TUNER
, &priv
->tuner
) < 0) {
1237 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl get tuner failed: %s\n",
1238 info
.short_name
, strerror(errno
));
1243 mp_msg(MSGT_TV
, MSGL_INFO
, "Selected device: %s\n", priv
->capability
.card
);
1244 if (priv
->capability
.capabilities
& V4L2_CAP_TUNER
) {
1245 mp_msg(MSGT_TV
, MSGL_INFO
, " Tuner cap:%s%s%s\n",
1246 (priv
->tuner
.capability
& V4L2_TUNER_CAP_STEREO
) ? " STEREO" : "",
1247 (priv
->tuner
.capability
& V4L2_TUNER_CAP_LANG1
) ? " LANG1" : "",
1248 (priv
->tuner
.capability
& V4L2_TUNER_CAP_LANG2
) ? " LANG2" : "");
1249 mp_msg(MSGT_TV
, MSGL_INFO
, " Tuner rxs:%s%s%s%s\n",
1250 (priv
->tuner
.rxsubchans
& V4L2_TUNER_SUB_MONO
) ? " MONO" : "",
1251 (priv
->tuner
.rxsubchans
& V4L2_TUNER_SUB_STEREO
) ? " STEREO" : "",
1252 (priv
->tuner
.rxsubchans
& V4L2_TUNER_SUB_LANG1
) ? " LANG1" : "",
1253 (priv
->tuner
.rxsubchans
& V4L2_TUNER_SUB_LANG2
) ? " LANG2" : "");
1255 mp_msg(MSGT_TV
, MSGL_INFO
, " Capabilities:%s%s%s%s%s%s%s%s%s%s%s\n",
1256 priv
->capability
.capabilities
& V4L2_CAP_VIDEO_CAPTURE
?
1257 " video capture": "",
1258 priv
->capability
.capabilities
& V4L2_CAP_VIDEO_OUTPUT
?
1259 " video output": "",
1260 priv
->capability
.capabilities
& V4L2_CAP_VIDEO_OVERLAY
?
1261 " video overlay": "",
1262 priv
->capability
.capabilities
& V4L2_CAP_VBI_CAPTURE
?
1263 " VBI capture device": "",
1264 priv
->capability
.capabilities
& V4L2_CAP_VBI_OUTPUT
?
1266 priv
->capability
.capabilities
& V4L2_CAP_RDS_CAPTURE
?
1267 " RDS data capture": "",
1268 priv
->capability
.capabilities
& V4L2_CAP_TUNER
?
1270 priv
->capability
.capabilities
& V4L2_CAP_AUDIO
?
1272 priv
->capability
.capabilities
& V4L2_CAP_READWRITE
?
1274 priv
->capability
.capabilities
& V4L2_CAP_ASYNCIO
?
1276 priv
->capability
.capabilities
& V4L2_CAP_STREAMING
?
1278 mp_msg(MSGT_TV
, MSGL_INFO
, " supported norms:");
1280 struct v4l2_standard standard
;
1281 memset(&standard
, 0, sizeof(standard
));
1283 if (-1 == ioctl(priv
->video_fd
, VIDIOC_ENUMSTD
, &standard
))
1285 mp_msg(MSGT_TV
, MSGL_INFO
, " %d = %s;", i
, standard
.name
);
1287 mp_msg(MSGT_TV
, MSGL_INFO
, "\n inputs:");
1288 for (i
= 0; 1; i
++) {
1289 struct v4l2_input input
;
1292 if (ioctl(priv
->video_fd
, VIDIOC_ENUMINPUT
, &input
) < 0) {
1295 mp_msg(MSGT_TV
, MSGL_INFO
, " %d = %s;", i
, input
.name
);
1298 if (ioctl(priv
->video_fd
, VIDIOC_G_INPUT
, &i
) < 0) {
1299 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl get input failed: %s\n",
1300 info
.short_name
, strerror(errno
));
1302 mp_msg(MSGT_TV
, MSGL_INFO
, "\n Current input: %d\n", i
);
1303 for (i
= 0; ; i
++) {
1304 struct v4l2_fmtdesc fmtdesc
;
1307 fmtdesc
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1308 if (ioctl(priv
->video_fd
, VIDIOC_ENUM_FMT
, &fmtdesc
) < 0) {
1311 mp_msg(MSGT_TV
, MSGL_V
, " Format %-6s (%2d bits, %s): %s\n",
1312 pixfmt2name(fmtdesc
.pixelformat
), pixfmt2depth(fmtdesc
.pixelformat
),
1313 fmtdesc
.description
, vo_format_name(fcc_vl2mp(fmtdesc
.pixelformat
)));
1315 mp_msg(MSGT_TV
, MSGL_INFO
, " Current format: %s\n",
1316 pixfmt2name(priv
->format
.fmt
.pix
.pixelformat
));
1318 /* set some nice defaults */
1319 if (getfmt(priv
) < 0) return 0;
1320 priv
->format
.fmt
.pix
.width
= 640;
1321 priv
->format
.fmt
.pix
.height
= 480;
1322 if (ioctl(priv
->video_fd
, VIDIOC_S_FMT
, &priv
->format
) < 0) {
1323 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl set format failed: %s\n",
1324 info
.short_name
, strerror(errno
));
1329 // if (!(priv->capability.capabilities & V4L2_CAP_AUDIO) && !priv->tv_param->force_audio) priv->tv_param->noaudio = 1;
1331 if (priv
->capability
.capabilities
& V4L2_CAP_TUNER
) {
1332 struct v4l2_control control
;
1333 if (priv
->tv_param
->amode
>= 0) {
1334 mp_msg(MSGT_TV
, MSGL_V
, "%s: setting audio mode\n", info
.short_name
);
1335 priv
->tuner
.audmode
= amode2v4l(priv
->tv_param
->amode
);
1336 if (ioctl(priv
->video_fd
, VIDIOC_S_TUNER
, &priv
->tuner
) < 0) {
1337 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl set tuner failed: %s\n",
1338 info
.short_name
, strerror(errno
));
1339 return TVI_CONTROL_FALSE
;
1342 mp_msg(MSGT_TV
, MSGL_INFO
, "%s: current audio mode is :%s%s%s%s\n", info
.short_name
,
1343 (priv
->tuner
.audmode
== V4L2_TUNER_MODE_MONO
) ? " MONO" : "",
1344 (priv
->tuner
.audmode
== V4L2_TUNER_MODE_STEREO
) ? " STEREO" : "",
1345 (priv
->tuner
.audmode
== V4L2_TUNER_MODE_LANG1
) ? " LANG1" : "",
1346 (priv
->tuner
.audmode
== V4L2_TUNER_MODE_LANG2
) ? " LANG2" : "");
1348 if (priv
->tv_param
->volume
>= 0) {
1349 control
.id
= V4L2_CID_AUDIO_VOLUME
;
1350 control
.value
= priv
->tv_param
->volume
;
1351 set_control(priv
, &control
, 0);
1353 if (priv
->tv_param
->bass
>= 0) {
1354 control
.id
= V4L2_CID_AUDIO_BASS
;
1355 control
.value
= priv
->tv_param
->bass
;
1356 set_control(priv
, &control
, 0);
1358 if (priv
->tv_param
->treble
>= 0) {
1359 control
.id
= V4L2_CID_AUDIO_TREBLE
;
1360 control
.value
= priv
->tv_param
->treble
;
1361 set_control(priv
, &control
, 0);
1363 if (priv
->tv_param
->balance
>= 0) {
1364 control
.id
= V4L2_CID_AUDIO_BALANCE
;
1365 control
.value
= priv
->tv_param
->balance
;
1366 set_control(priv
, &control
, 0);
1373 static int get_capture_buffer_size(priv_t
*priv
)
1377 if (priv
->tv_param
->buffer_size
>= 0) {
1378 bufsize
= priv
->tv_param
->buffer_size
*1024*1024;
1380 #ifdef HAVE_SYS_SYSINFO_H
1384 if (si
.totalram
<2*1024*1024) {
1385 bufsize
= 1024*1024;
1387 bufsize
= si
.totalram
/2;
1390 bufsize
= 16*1024*1024;
1394 cnt
= bufsize
/priv
->format
.fmt
.pix
.sizeimage
;
1395 if (cnt
< 2) cnt
= 2;
1400 /* that's the real start, we'got the format parameters (checked with control) */
1401 static int start(priv_t
*priv
)
1403 struct v4l2_requestbuffers request
;
1406 /* setup audio parameters */
1409 if (!priv
->tv_param
->noaudio
&& !priv
->audio_initialized
) return 0;
1411 /* we need this to size the audio buffer properly */
1412 if (priv
->immediate_mode
) {
1413 priv
->video_buffer_size_max
= 2;
1415 priv
->video_buffer_size_max
= get_capture_buffer_size(priv
);
1418 if (!priv
->tv_param
->noaudio
) {
1419 setup_audio_buffer_sizes(priv
);
1420 priv
->audio_skew_buffer
= calloc(priv
->aud_skew_cnt
, sizeof(long long));
1421 if (!priv
->audio_skew_buffer
) {
1422 mp_msg(MSGT_TV
, MSGL_ERR
, "cannot allocate skew buffer: %s\n", strerror(errno
));
1425 priv
->audio_skew_delta_buffer
= calloc(priv
->aud_skew_cnt
, sizeof(long long));
1426 if (!priv
->audio_skew_delta_buffer
) {
1427 mp_msg(MSGT_TV
, MSGL_ERR
, "cannot allocate skew buffer: %s\n", strerror(errno
));
1431 priv
->audio_ringbuffer
= calloc(priv
->audio_in
.blocksize
, priv
->audio_buffer_size
);
1432 if (!priv
->audio_ringbuffer
) {
1433 mp_msg(MSGT_TV
, MSGL_ERR
, "cannot allocate audio buffer: %s\n", strerror(errno
));
1437 priv
->audio_secs_per_block
= (double)priv
->audio_in
.blocksize
/(priv
->audio_in
.samplerate
1438 *priv
->audio_in
.channels
1439 *priv
->audio_in
.bytes_per_sample
);
1440 priv
->audio_usecs_per_block
= 1e6
*priv
->audio_secs_per_block
;
1441 priv
->audio_head
= 0;
1442 priv
->audio_tail
= 0;
1443 priv
->audio_cnt
= 0;
1444 priv
->audio_drop
= 0;
1445 priv
->audio_skew
= 0;
1446 priv
->audio_skew_total
= 0;
1447 priv
->audio_skew_delta_total
= 0;
1448 priv
->audio_recv_blocks_total
= 0;
1449 priv
->audio_sent_blocks_total
= 0;
1450 priv
->audio_null_blocks_inserted
= 0;
1451 priv
->audio_insert_null_samples
= 0;
1452 priv
->dropped_frames_timeshift
= 0;
1453 priv
->dropped_frames_compensated
= 0;
1455 pthread_mutex_init(&priv
->skew_mutex
, NULL
);
1456 pthread_mutex_init(&priv
->audio_mutex
, NULL
);
1459 /* setup video parameters */
1460 if (!priv
->tv_param
->noaudio
) {
1461 if (priv
->video_buffer_size_max
< 3*getfps(priv
)*priv
->audio_secs_per_block
) {
1462 mp_msg(MSGT_TV
, MSGL_ERR
, "Video buffer shorter than 3 times audio frame duration.\n"
1463 "You will probably experience heavy framedrops.\n");
1468 int bytesperline
= priv
->format
.fmt
.pix
.width
*pixfmt2depth(priv
->format
.fmt
.pix
.pixelformat
)/8;
1470 mp_msg(MSGT_TV
, MSGL_V
, "Using a ring buffer for maximum %d frames, %d MB total size.\n",
1471 priv
->video_buffer_size_max
,
1472 priv
->video_buffer_size_max
*priv
->format
.fmt
.pix
.height
*bytesperline
/(1024*1024));
1475 priv
->video_ringbuffer
= calloc(priv
->video_buffer_size_max
, sizeof(video_buffer_entry
));
1476 if (!priv
->video_ringbuffer
) {
1477 mp_msg(MSGT_TV
, MSGL_ERR
, "cannot allocate video buffer: %s\n", strerror(errno
));
1480 memset(priv
->video_ringbuffer
,0,priv
->video_buffer_size_max
* sizeof(video_buffer_entry
));
1482 pthread_mutex_init(&priv
->video_buffer_mutex
, NULL
);
1484 priv
->video_head
= 0;
1485 priv
->video_tail
= 0;
1486 priv
->video_cnt
= 0;
1488 /* request buffers */
1489 if (priv
->immediate_mode
) {
1492 request
.count
= BUFFER_COUNT
;
1495 request
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1496 request
.memory
= V4L2_MEMORY_MMAP
;
1497 if (ioctl(priv
->video_fd
, VIDIOC_REQBUFS
, &request
) < 0) {
1498 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl request buffers failed: %s\n",
1499 info
.short_name
, strerror(errno
));
1504 if (!(priv
->map
= calloc(request
.count
, sizeof(struct map
)))) {
1505 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: malloc capture buffers failed: %s\n",
1506 info
.short_name
, strerror(errno
));
1510 /* map and queue buffers */
1511 for (i
= 0; i
< request
.count
; i
++) {
1512 memset(&priv
->map
[i
].buf
,0,sizeof(priv
->map
[i
].buf
));
1513 priv
->map
[i
].buf
.index
= i
;
1514 priv
->map
[i
].buf
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1515 priv
->map
[i
].buf
.memory
= V4L2_MEMORY_MMAP
;
1516 if (ioctl(priv
->video_fd
, VIDIOC_QUERYBUF
, &(priv
->map
[i
].buf
)) < 0) {
1517 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl query buffer failed: %s\n",
1518 info
.short_name
, strerror(errno
));
1523 priv
->map
[i
].addr
= mmap (0, priv
->map
[i
].buf
.length
, PROT_READ
|
1524 PROT_WRITE
, MAP_SHARED
, priv
->video_fd
, priv
->map
[i
].buf
.m
.offset
);
1525 if (priv
->map
[i
].addr
== MAP_FAILED
) {
1526 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: mmap capture buffer failed: %s\n",
1527 info
.short_name
, strerror(errno
));
1528 priv
->map
[i
].len
= 0;
1531 priv
->map
[i
].len
= priv
->map
[i
].buf
.length
;
1532 /* count up to make sure this is correct everytime */
1535 if (ioctl(priv
->video_fd
, VIDIOC_QBUF
, &(priv
->map
[i
].buf
)) < 0) {
1536 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl queue buffer failed: %s\n",
1537 info
.short_name
, strerror(errno
));
1542 /* start vbi thread */
1544 priv
->vbi_shutdown
= 0;
1545 pthread_create(&priv
->vbi_grabber_thread
, NULL
, vbi_grabber
, priv
);
1547 /* start audio thread */
1549 priv
->audio_skew_measure_time
= 0;
1550 priv
->first_frame
= 0;
1551 priv
->audio_skew
= 0;
1559 // copies a video frame
1560 static inline void copy_frame(priv_t
*priv
, video_buffer_entry
*dest
, unsigned char *source
,int len
)
1562 dest
->framesize
=len
;
1563 if(priv
->tv_param
->automute
>0){
1564 if (ioctl(priv
->video_fd
, VIDIOC_G_TUNER
, &priv
->tuner
) >= 0) {
1565 if(priv
->tv_param
->automute
<<8>priv
->tuner
.signal
){
1566 fill_blank_frame(dest
->data
,dest
->framesize
,fcc_vl2mp(priv
->format
.fmt
.pix
.pixelformat
));
1573 memcpy(dest
->data
, source
, len
);
1576 // maximum skew change, in frames
1577 #define MAX_SKEW_DELTA 0.6
1578 static void *video_grabber(void *data
)
1580 priv_t
*priv
= (priv_t
*)data
;
1581 long long skew
, prev_skew
, xskew
, interval
, prev_interval
, delta
;
1583 int framesize
= priv
->format
.fmt
.pix
.sizeimage
;
1585 struct timeval timeout
;
1586 struct v4l2_buffer buf
;
1594 mp_msg(MSGT_TV
, MSGL_V
, "%s: going to capture\n", info
.short_name
);
1595 if (ioctl(priv
->video_fd
, VIDIOC_STREAMON
, &(priv
->format
.type
)) < 0) {
1596 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl streamon failed: %s\n",
1597 info
.short_name
, strerror(errno
));
1602 if (!priv
->tv_param
->noaudio
) {
1603 pthread_create(&priv
->audio_grabber_thread
, NULL
, audio_grabber
, priv
);
1606 for (priv
->frames
= 0; !priv
->shutdown
;)
1610 if (priv
->immediate_mode
) {
1611 while (priv
->video_cnt
== priv
->video_buffer_size_max
) {
1613 if (priv
->shutdown
) {
1620 FD_SET (priv
->video_fd
, &rdset
);
1623 timeout
.tv_usec
= 0;
1625 i
= select(priv
->video_fd
+ 1, &rdset
, NULL
, NULL
, &timeout
);
1627 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: select failed: %s\n",
1628 info
.short_name
, strerror(errno
));
1632 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: select timeout\n", info
.short_name
);
1635 else if (!FD_ISSET(priv
->video_fd
, &rdset
)) {
1639 memset(&buf
,0,sizeof(buf
));
1640 buf
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1641 buf
.memory
= V4L2_MEMORY_MMAP
;
1642 ret
= ioctl(priv
->video_fd
, VIDIOC_DQBUF
, &buf
);
1646 if there's no signal, the buffer might me dequeued
1647 so we query all the buffers to see which one we should
1650 observed with saa7134 0.2.8
1651 don't know if is it a bug or (mis)feature
1653 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl dequeue buffer failed: %s, idx = %d\n",
1654 info
.short_name
, strerror(errno
), buf
.index
);
1655 for (i
= 0; i
< priv
->mapcount
; i
++) {
1656 memset(&buf
,0,sizeof(buf
));
1657 buf
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1658 buf
.memory
= V4L2_MEMORY_MMAP
;
1660 ret
= ioctl(priv
->video_fd
, VIDIOC_QUERYBUF
, &buf
);
1662 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl query buffer failed: %s, idx = %d\n",
1663 info
.short_name
, strerror(errno
), buf
.index
);
1666 if ((buf
.flags
& (V4L2_BUF_FLAG_QUEUED
| V4L2_BUF_FLAG_MAPPED
| V4L2_BUF_FLAG_DONE
)) == V4L2_BUF_FLAG_MAPPED
) {
1667 if (ioctl(priv
->video_fd
, VIDIOC_QBUF
, &(priv
->map
[i
].buf
)) < 0) {
1668 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl queue buffer failed: %s\n",
1669 info
.short_name
, strerror(errno
));
1677 /* store the timestamp of the very first frame as reference */
1678 if (!priv
->frames
++) {
1679 if (!priv
->tv_param
->noaudio
) pthread_mutex_lock(&priv
->skew_mutex
);
1680 priv
->first_frame
= (long long)1e6
*buf
.timestamp
.tv_sec
+ buf
.timestamp
.tv_usec
;
1681 if (!priv
->tv_param
->noaudio
) pthread_mutex_unlock(&priv
->skew_mutex
);
1683 priv
->curr_frame
= (long long)buf
.timestamp
.tv_sec
*1e6
+buf
.timestamp
.tv_usec
;
1684 // fprintf(stderr, "idx = %d, ts = %f\n", buf.index, (double)(priv->curr_frame) / 1e6);
1686 interval
= priv
->curr_frame
- priv
->first_frame
;
1687 delta
= interval
- prev_interval
;
1689 if (!priv
->immediate_mode
) {
1690 // interpolate the skew in time
1691 if (!priv
->tv_param
->noaudio
) pthread_mutex_lock(&priv
->skew_mutex
);
1692 xskew
= priv
->audio_skew
+ (interval
- priv
->audio_skew_measure_time
)*priv
->audio_skew_factor
;
1693 if (!priv
->tv_param
->noaudio
) pthread_mutex_unlock(&priv
->skew_mutex
);
1694 // correct extreme skew changes to avoid (especially) moving backwards in time
1695 if (xskew
- prev_skew
> delta
*MAX_SKEW_DELTA
) {
1696 skew
= prev_skew
+ delta
*MAX_SKEW_DELTA
;
1697 } else if (xskew
- prev_skew
< -delta
*MAX_SKEW_DELTA
) {
1698 skew
= prev_skew
- delta
*MAX_SKEW_DELTA
;
1704 mp_msg(MSGT_TV
, MSGL_DBG3
, "\nfps = %f, interval = %f, a_skew = %f, corr_skew = %f\n",
1705 delta
? (double)1e6
/delta
: -1,
1706 (double)1e-6*interval
, (double)1e-6*xskew
, (double)1e-6*skew
);
1707 mp_msg(MSGT_TV
, MSGL_DBG3
, "vcnt = %d, acnt = %d\n", priv
->video_cnt
, priv
->audio_cnt
);
1710 prev_interval
= interval
;
1712 /* allocate a new buffer, if needed */
1713 pthread_mutex_lock(&priv
->video_buffer_mutex
);
1714 if (priv
->video_buffer_size_current
< priv
->video_buffer_size_max
) {
1715 if (priv
->video_cnt
== priv
->video_buffer_size_current
) {
1716 unsigned char *newbuf
= malloc(framesize
);
1718 memmove(priv
->video_ringbuffer
+priv
->video_tail
+1, priv
->video_ringbuffer
+priv
->video_tail
,
1719 (priv
->video_buffer_size_current
-priv
->video_tail
)*sizeof(video_buffer_entry
));
1720 priv
->video_ringbuffer
[priv
->video_tail
].data
= newbuf
;
1721 if ((priv
->video_head
>= priv
->video_tail
) && (priv
->video_cnt
> 0)) priv
->video_head
++;
1722 priv
->video_buffer_size_current
++;
1726 pthread_mutex_unlock(&priv
->video_buffer_mutex
);
1728 if (priv
->video_cnt
== priv
->video_buffer_size_current
) {
1729 if (!priv
->immediate_mode
) {
1730 mp_msg(MSGT_TV
, MSGL_ERR
, "\nvideo buffer full - dropping frame\n");
1731 if (priv
->audio_insert_null_samples
) {
1732 pthread_mutex_lock(&priv
->audio_mutex
);
1733 priv
->dropped_frames_timeshift
+= delta
;
1734 pthread_mutex_unlock(&priv
->audio_mutex
);
1738 if (priv
->immediate_mode
) {
1739 priv
->video_ringbuffer
[priv
->video_tail
].timestamp
= 0;
1741 // compensate for audio skew
1742 // negative skew => there are more audio samples, increase interval
1743 // positive skew => less samples, shorten the interval
1744 priv
->video_ringbuffer
[priv
->video_tail
].timestamp
= interval
- skew
;
1745 if (priv
->audio_insert_null_samples
&& priv
->video_ringbuffer
[priv
->video_tail
].timestamp
> 0) {
1746 pthread_mutex_lock(&priv
->audio_mutex
);
1747 priv
->video_ringbuffer
[priv
->video_tail
].timestamp
+=
1748 (priv
->audio_null_blocks_inserted
1749 - priv
->dropped_frames_timeshift
/priv
->audio_usecs_per_block
)
1750 *priv
->audio_usecs_per_block
;
1751 pthread_mutex_unlock(&priv
->audio_mutex
);
1754 copy_frame(priv
, priv
->video_ringbuffer
+priv
->video_tail
, priv
->map
[buf
.index
].addr
,buf
.bytesused
);
1755 priv
->video_tail
= (priv
->video_tail
+1)%priv
->video_buffer_size_current
;
1758 if (ioctl(priv
->video_fd
, VIDIOC_QBUF
, &buf
) < 0) {
1759 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl queue buffer failed: %s\n",
1760 info
.short_name
, strerror(errno
));
1768 static double grab_video_frame(priv_t
*priv
, char *buffer
, int len
)
1774 pthread_create(&priv
->video_grabber_thread
, NULL
, video_grabber
, priv
);
1778 while (priv
->video_cnt
== 0) {
1780 if (loop_cnt
++ > MAX_LOOP
) return 0;
1783 pthread_mutex_lock(&priv
->video_buffer_mutex
);
1784 interval
= (double)priv
->video_ringbuffer
[priv
->video_head
].timestamp
*1e-6;
1785 memcpy(buffer
, priv
->video_ringbuffer
[priv
->video_head
].data
, len
);
1787 priv
->video_head
= (priv
->video_head
+1)%priv
->video_buffer_size_current
;
1788 pthread_mutex_unlock(&priv
->video_buffer_mutex
);
1793 static int get_video_framesize(priv_t
*priv
)
1796 this routine will be called before grab_video_frame
1797 thus let's return topmost frame's size
1799 if (priv
->video_cnt
)
1800 return priv
->video_ringbuffer
[priv
->video_head
].framesize
;
1802 no video frames yet available. i don't know what to do in this case,
1803 thus let's return some fallback result (for compressed format this will be
1804 maximum allowed frame size.
1806 return priv
->format
.fmt
.pix
.sizeimage
;
1809 //#define DOUBLESPEED
1811 // for testing purposes only
1812 static void read_doublespeed(priv_t
*priv
)
1814 char *bufx
= calloc(priv
->audio_in
.blocksize
, 2);
1819 audio_in_read_chunk(&priv
->audio_in
, bufx
);
1820 audio_in_read_chunk(&priv
->audio_in
, bufx
+priv
->audio_in
.blocksize
);
1823 d
= priv
->audio_ringbuffer
+priv
->audio_tail
*priv
->audio_in
.blocksize
;
1824 for (i
= 0; i
< priv
->audio_in
.blocksize
/2; i
++) {
1832 static void *audio_grabber(void *data
)
1834 priv_t
*priv
= (priv_t
*)data
;
1836 int i
, audio_skew_ptr
= 0;
1837 long long current_time
, prev_skew
= 0, prev_skew_uncorr
= 0;
1838 long long start_time_avg
;
1840 gettimeofday(&tv
, NULL
);
1841 start_time_avg
= priv
->audio_start_time
= (long long)1e6
*tv
.tv_sec
+ tv
.tv_usec
;
1842 audio_in_start_capture(&priv
->audio_in
);
1843 for (i
= 0; i
< priv
->aud_skew_cnt
; i
++)
1844 priv
->audio_skew_buffer
[i
] = 0;
1845 for (i
= 0; i
< priv
->aud_skew_cnt
; i
++)
1846 priv
->audio_skew_delta_buffer
[i
] = 0;
1848 for (; !priv
->shutdown
;)
1851 read_doublespeed(priv
);
1853 if (audio_in_read_chunk(&priv
->audio_in
, priv
->audio_ringbuffer
+priv
->audio_tail
*priv
->audio_in
.blocksize
) < 0)
1856 pthread_mutex_lock(&priv
->skew_mutex
);
1857 if (priv
->first_frame
== 0) {
1858 // there is no first frame yet (unlikely to happen)
1859 gettimeofday(&tv
, NULL
);
1860 start_time_avg
= priv
->audio_start_time
= (long long)1e6
*tv
.tv_sec
+ tv
.tv_usec
;
1861 // fprintf(stderr, "warning - first frame not yet available!\n");
1862 pthread_mutex_unlock(&priv
->skew_mutex
);
1865 pthread_mutex_unlock(&priv
->skew_mutex
);
1867 gettimeofday(&tv
, NULL
);
1869 priv
->audio_recv_blocks_total
++;
1870 current_time
= (long long)1e6
*tv
.tv_sec
+ tv
.tv_usec
- priv
->audio_start_time
;
1872 if (priv
->audio_recv_blocks_total
< priv
->aud_skew_cnt
*2) {
1873 start_time_avg
+= (long long)1e6
*tv
.tv_sec
+ tv
.tv_usec
- priv
->audio_usecs_per_block
*priv
->audio_recv_blocks_total
;
1874 priv
->audio_start_time
= start_time_avg
/(priv
->audio_recv_blocks_total
+1);
1877 // fprintf(stderr, "spb = %f, bs = %d, skew = %f\n", priv->audio_secs_per_block, priv->audio_in.blocksize,
1878 // (double)(current_time - 1e6*priv->audio_secs_per_block*priv->audio_recv_blocks_total)/1e6);
1880 // put the current skew into the ring buffer
1881 priv
->audio_skew_total
-= priv
->audio_skew_buffer
[audio_skew_ptr
];
1882 priv
->audio_skew_buffer
[audio_skew_ptr
] = current_time
1883 - priv
->audio_usecs_per_block
*priv
->audio_recv_blocks_total
;
1884 priv
->audio_skew_total
+= priv
->audio_skew_buffer
[audio_skew_ptr
];
1886 pthread_mutex_lock(&priv
->skew_mutex
);
1890 // compute the sliding average of the skews
1891 if (priv
->audio_recv_blocks_total
> priv
->aud_skew_cnt
) {
1892 priv
->audio_skew
= priv
->audio_skew_total
/priv
->aud_skew_cnt
;
1894 priv
->audio_skew
= priv
->audio_skew_total
/priv
->audio_recv_blocks_total
;
1897 // put the current skew change (skew-prev_skew) into the ring buffer
1898 priv
->audio_skew_delta_total
-= priv
->audio_skew_delta_buffer
[audio_skew_ptr
];
1899 priv
->audio_skew_delta_buffer
[audio_skew_ptr
] = priv
->audio_skew
- prev_skew_uncorr
;
1900 priv
->audio_skew_delta_total
+= priv
->audio_skew_delta_buffer
[audio_skew_ptr
];
1901 prev_skew_uncorr
= priv
->audio_skew
; // remember the _uncorrected_ average value
1903 audio_skew_ptr
= (audio_skew_ptr
+1) % priv
->aud_skew_cnt
; // rotate the buffer pointer
1905 // sliding average approximates the value in the middle of the interval
1906 // so interpolate the skew value further to the current time
1907 priv
->audio_skew
+= priv
->audio_skew_delta_total
/2;
1909 // now finally, priv->audio_skew contains fairly good approximation
1910 // of the current value
1912 // current skew factor (assuming linearity)
1913 // used for further interpolation in video_grabber
1914 // probably overkill but seems to be necessary for
1915 // stress testing by dropping half of the audio frames ;)
1916 // especially when using ALSA with large block sizes
1917 // where audio_skew remains a long while behind
1918 if ((priv
->audio_skew_measure_time
!= 0) && (current_time
- priv
->audio_skew_measure_time
!= 0)) {
1919 priv
->audio_skew_factor
= (double)(priv
->audio_skew
-prev_skew
)/(current_time
- priv
->audio_skew_measure_time
);
1921 priv
->audio_skew_factor
= 0.0;
1924 priv
->audio_skew_measure_time
= current_time
;
1925 prev_skew
= priv
->audio_skew
;
1926 priv
->audio_skew
+= priv
->audio_start_time
- priv
->first_frame
;
1927 pthread_mutex_unlock(&priv
->skew_mutex
);
1929 // fprintf(stderr, "audio_skew = %f, delta = %f\n", (double)priv->audio_skew/1e6, (double)priv->audio_skew_delta_total/1e6);
1931 pthread_mutex_lock(&priv
->audio_mutex
);
1932 if ((priv
->audio_tail
+1) % priv
->audio_buffer_size
== priv
->audio_head
) {
1933 mp_msg(MSGT_TV
, MSGL_ERR
, "\ntoo bad - dropping audio frame !\n");
1936 priv
->audio_tail
= (priv
->audio_tail
+1) % priv
->audio_buffer_size
;
1939 pthread_mutex_unlock(&priv
->audio_mutex
);
1944 static double grab_audio_frame(priv_t
*priv
, char *buffer
, int len
)
1946 mp_dbg(MSGT_TV
, MSGL_DBG2
, "grab_audio_frame(priv=%p, buffer=%p, len=%d)\n",
1949 // hack: if grab_audio_frame is called first, it means we are used by mplayer
1950 // => switch to the mode which outputs audio immediately, even if
1951 // it should be silence
1952 if (priv
->first
) priv
->audio_insert_null_samples
= 1;
1954 pthread_mutex_lock(&priv
->audio_mutex
);
1955 while (priv
->audio_insert_null_samples
1956 && priv
->dropped_frames_timeshift
- priv
->dropped_frames_compensated
>= priv
->audio_usecs_per_block
) {
1957 // some frames were dropped - drop the corresponding number of audio blocks
1958 if (priv
->audio_drop
) {
1961 if (priv
->audio_head
== priv
->audio_tail
) break;
1962 priv
->audio_head
= (priv
->audio_head
+1) % priv
->audio_buffer_size
;
1964 priv
->dropped_frames_compensated
+= priv
->audio_usecs_per_block
;
1967 // compensate for dropped audio frames
1968 if (priv
->audio_drop
&& (priv
->audio_head
== priv
->audio_tail
)) {
1970 memset(buffer
, 0, len
);
1974 if (priv
->audio_insert_null_samples
&& (priv
->audio_head
== priv
->audio_tail
)) {
1975 // return silence to avoid desync and stuttering
1976 memset(buffer
, 0, len
);
1977 priv
->audio_null_blocks_inserted
++;
1981 pthread_mutex_unlock(&priv
->audio_mutex
);
1982 while (priv
->audio_head
== priv
->audio_tail
) {
1983 // this is mencoder => just wait until some audio is available
1986 pthread_mutex_lock(&priv
->audio_mutex
);
1987 memcpy(buffer
, priv
->audio_ringbuffer
+priv
->audio_head
*priv
->audio_in
.blocksize
, len
);
1988 priv
->audio_head
= (priv
->audio_head
+1) % priv
->audio_buffer_size
;
1991 pthread_mutex_unlock(&priv
->audio_mutex
);
1992 priv
->audio_sent_blocks_total
++;
1993 return (double)priv
->audio_sent_blocks_total
*priv
->audio_secs_per_block
;
1996 static int get_audio_framesize(priv_t
*priv
)
1998 return priv
->audio_in
.blocksize
;