2 ** Video 4 Linux 2 input
4 ** This file is part of MPlayer, see http://mplayerhq.hu/ for info.
6 ** (c) 2003 Martin Olschewski <olschewski@zpr.uni-koeln.de>
7 ** (c) 2003 Jindrich Makovicka <makovick@gmail.com>
9 ** File licensed under the GPL, see http://www.fsf.org/ for more info.
11 ** Some ideas are based on works from
12 ** Alex Beregszaszi <alex@fsn.hu>
13 ** Gerd Knorr <kraxel@bytesex.org>
15 ** CODE IS UNDER DEVELOPMENT, NO FEATURE REQUESTS PLEASE!
21 - norm setting isn't consistent with tvi_v4l
22 - the same for volume/bass/treble/balance
33 #include <sys/ioctl.h>
36 #include <sys/types.h>
38 #ifdef HAVE_SYS_SYSINFO_H
39 #include <sys/sysinfo.h>
41 #include <linux/types.h>
42 #include <linux/videodev2.h>
44 #include "libmpcodecs/img_format.h"
45 #include "libaf/af_format.h"
49 #define info tvi_info_v4l2
50 static tvi_handle_t
*tvi_init_v4l2(char *video_dev
, char *audio_dev
);
51 /* information about this file */
52 tvi_info_t tvi_info_v4l2
= {
54 "Video 4 Linux 2 input",
56 "Martin Olschewski <olschewski@zpr.uni-koeln.de>",
57 "first try, more to come ;-)"
61 struct v4l2_buffer buf
;
66 #define BUFFER_COUNT 6
74 struct v4l2_capability capability
;
75 struct v4l2_input input
;
76 struct v4l2_format format
;
77 struct v4l2_standard standard
;
78 struct v4l2_tuner tuner
;
82 volatile long long first_frame
;
84 /* audio video interleaving ;-) */
85 volatile int streamon
;
86 pthread_t audio_grabber_thread
;
87 pthread_mutex_t skew_mutex
;
89 /* 2nd level video buffers */
93 int video_buffer_size_max
;
94 volatile int video_buffer_size_current
;
95 unsigned char **video_ringbuffer
;
96 long long *video_timebuffer
;
97 volatile int video_head
;
98 volatile int video_tail
;
99 volatile int video_cnt
;
100 pthread_t video_grabber_thread
;
101 pthread_mutex_t video_buffer_mutex
;
107 long long audio_start_time
;
108 int audio_buffer_size
;
110 unsigned char *audio_ringbuffer
;
111 long long *audio_skew_buffer
;
112 long long *audio_skew_delta_buffer
;
113 volatile int audio_head
;
114 volatile int audio_tail
;
115 volatile int audio_cnt
;
116 volatile long long audio_skew
;
117 volatile double audio_skew_factor
;
118 volatile long long audio_skew_measure_time
;
119 volatile int audio_drop
;
120 volatile int shutdown
;
123 double audio_secs_per_block
;
124 long long audio_usecs_per_block
;
125 long long audio_skew_total
;
126 long long audio_skew_delta_total
;
127 long audio_recv_blocks_total
;
128 long audio_sent_blocks_total
;
129 pthread_mutex_t audio_mutex
;
130 int audio_insert_null_samples
;
131 volatile long audio_null_blocks_inserted
;
132 volatile long long dropped_frames_timeshift
;
133 long long dropped_frames_compensated
;
138 static void *audio_grabber(void *data
);
139 static void *video_grabber(void *data
);
141 /**********************************************************************\
143 Only few of the fourccs are the same in v4l2 and mplayer:
145 IMGFMT_YVU9 == V4L2_PIX_FMT_YVU410
146 IMGFMT_YV12 == V4L2_PIX_FMT_YVU420
147 IMGFMT_NV12 == V4L2_PIX_FMT_NV12
148 IMGFMT_422P == V4L2_PIX_FMT_YUV422P
149 IMGFMT_411P == V4L2_PIX_FMT_YUV411P
150 IMGFMT_UYVY == V4L2_PIX_FMT_UYVY
151 IMGFMT_Y41P == V4L2_PIX_FMT_Y41P
153 This may be an useful translation table for some others:
155 IMGFMT_RGB8 == V4L2_PIX_FMT_RGB332
156 IMGFMT_BGR15 == V4L2_PIX_FMT_RGB555
157 IMGFMT_BGR16 == V4L2_PIX_FMT_RGB565
158 IMGFMT_RGB24 == V4L2_PIX_FMT_RGB24
159 IMGFMT_RGB32 == V4L2_PIX_FMT_RGB32
160 IMGFMT_BGR24 == V4L2_PIX_FMT_BGR24
161 IMGFMT_BGR32 == V4L2_PIX_FMT_BGR32
162 IMGFMT_Y800 == V4L2_PIX_FMT_GREY
163 IMGFMT_IF09 == V4L2_PIX_FMT_YUV410
164 IMGFMT_I420 == V4L2_PIX_FMT_YUV420
165 IMGFMT_YUY2 == V4L2_PIX_FMT_YUYV
167 \**********************************************************************/
170 ** Translate a mplayer fourcc to a video4linux2 pixel format.
172 static int fcc_mp2vl(int fcc
)
175 case IMGFMT_RGB8
: return V4L2_PIX_FMT_RGB332
;
176 case IMGFMT_BGR15
: return V4L2_PIX_FMT_RGB555
;
177 case IMGFMT_BGR16
: return V4L2_PIX_FMT_RGB565
;
178 case IMGFMT_RGB24
: return V4L2_PIX_FMT_RGB24
;
179 case IMGFMT_RGB32
: return V4L2_PIX_FMT_RGB32
;
180 case IMGFMT_BGR24
: return V4L2_PIX_FMT_BGR24
;
181 case IMGFMT_BGR32
: return V4L2_PIX_FMT_BGR32
;
182 case IMGFMT_Y800
: return V4L2_PIX_FMT_GREY
;
183 case IMGFMT_IF09
: return V4L2_PIX_FMT_YUV410
;
184 case IMGFMT_I420
: return V4L2_PIX_FMT_YUV420
;
185 case IMGFMT_YUY2
: return V4L2_PIX_FMT_YUYV
;
186 case IMGFMT_YV12
: return V4L2_PIX_FMT_YVU420
;
187 case IMGFMT_UYVY
: return V4L2_PIX_FMT_UYVY
;
193 ** Translate a video4linux2 fourcc aka pixel format to mplayer.
195 static int fcc_vl2mp(int fcc
)
198 case V4L2_PIX_FMT_RGB332
: return IMGFMT_RGB8
;
199 case V4L2_PIX_FMT_RGB555
: return IMGFMT_BGR15
;
200 case V4L2_PIX_FMT_RGB565
: return IMGFMT_BGR16
;
201 case V4L2_PIX_FMT_RGB24
: return IMGFMT_RGB24
;
202 case V4L2_PIX_FMT_RGB32
: return IMGFMT_RGB32
;
203 case V4L2_PIX_FMT_BGR24
: return IMGFMT_BGR24
;
204 case V4L2_PIX_FMT_BGR32
: return IMGFMT_BGR32
;
205 case V4L2_PIX_FMT_GREY
: return IMGFMT_Y800
;
206 case V4L2_PIX_FMT_YUV410
: return IMGFMT_IF09
;
207 case V4L2_PIX_FMT_YUV420
: return IMGFMT_I420
;
208 case V4L2_PIX_FMT_YVU420
: return IMGFMT_YV12
;
209 case V4L2_PIX_FMT_YUYV
: return IMGFMT_YUY2
;
210 case V4L2_PIX_FMT_UYVY
: return IMGFMT_UYVY
;
216 ** Translate a video4linux2 fourcc aka pixel format
217 ** to a human readable string.
219 static const char *pixfmt2name(int pixfmt
)
221 static char unknown
[24];
224 case V4L2_PIX_FMT_RGB332
: return "RGB332";
225 case V4L2_PIX_FMT_RGB555
: return "RGB555";
226 case V4L2_PIX_FMT_RGB565
: return "RGB565";
227 case V4L2_PIX_FMT_RGB555X
: return "RGB555X";
228 case V4L2_PIX_FMT_RGB565X
: return "RGB565X";
229 case V4L2_PIX_FMT_BGR24
: return "BGR24";
230 case V4L2_PIX_FMT_RGB24
: return "RGB24";
231 case V4L2_PIX_FMT_BGR32
: return "BGR32";
232 case V4L2_PIX_FMT_RGB32
: return "RGB32";
233 case V4L2_PIX_FMT_GREY
: return "GREY";
234 case V4L2_PIX_FMT_YVU410
: return "YVU410";
235 case V4L2_PIX_FMT_YVU420
: return "YVU420";
236 case V4L2_PIX_FMT_YUYV
: return "YUYV";
237 case V4L2_PIX_FMT_UYVY
: return "UYVY";
238 /* case V4L2_PIX_FMT_YVU422P: return "YVU422P"; */
239 /* case V4L2_PIX_FMT_YVU411P: return "YVU411P"; */
240 case V4L2_PIX_FMT_YUV422P
: return "YUV422P";
241 case V4L2_PIX_FMT_YUV411P
: return "YUV411P";
242 case V4L2_PIX_FMT_Y41P
: return "Y41P";
243 case V4L2_PIX_FMT_NV12
: return "NV12";
244 case V4L2_PIX_FMT_NV21
: return "NV21";
245 case V4L2_PIX_FMT_YUV410
: return "YUV410";
246 case V4L2_PIX_FMT_YUV420
: return "YUV420";
247 case V4L2_PIX_FMT_YYUV
: return "YYUV";
248 case V4L2_PIX_FMT_HI240
: return "HI240";
249 case V4L2_PIX_FMT_WNVA
: return "WNVA";
251 sprintf(unknown
, "unknown (0x%x)", pixfmt
);
257 ** Gives the depth of a video4linux2 fourcc aka pixel format in bits.
259 static int pixfmt2depth(int pixfmt
)
262 case V4L2_PIX_FMT_RGB332
:
264 case V4L2_PIX_FMT_RGB555
:
265 case V4L2_PIX_FMT_RGB565
:
266 case V4L2_PIX_FMT_RGB555X
:
267 case V4L2_PIX_FMT_RGB565X
:
269 case V4L2_PIX_FMT_BGR24
:
270 case V4L2_PIX_FMT_RGB24
:
272 case V4L2_PIX_FMT_BGR32
:
273 case V4L2_PIX_FMT_RGB32
:
275 case V4L2_PIX_FMT_GREY
:
277 case V4L2_PIX_FMT_YVU410
:
279 case V4L2_PIX_FMT_YVU420
:
281 case V4L2_PIX_FMT_YUYV
:
282 case V4L2_PIX_FMT_UYVY
:
283 case V4L2_PIX_FMT_YUV422P
:
284 case V4L2_PIX_FMT_YUV411P
:
286 case V4L2_PIX_FMT_Y41P
:
287 case V4L2_PIX_FMT_NV12
:
288 case V4L2_PIX_FMT_NV21
:
290 case V4L2_PIX_FMT_YUV410
:
292 case V4L2_PIX_FMT_YUV420
:
294 case V4L2_PIX_FMT_YYUV
:
296 case V4L2_PIX_FMT_HI240
:
303 static int amode2v4l(int amode
)
307 return V4L2_TUNER_MODE_MONO
;
309 return V4L2_TUNER_MODE_STEREO
;
311 return V4L2_TUNER_MODE_LANG1
;
313 return V4L2_TUNER_MODE_LANG2
;
320 // sets and sanitizes audio buffer/block sizes
321 static void setup_audio_buffer_sizes(priv_t
*priv
)
323 int bytes_per_sample
= priv
->audio_in
.bytes_per_sample
;
324 double fps
= (double)priv
->standard
.frameperiod
.denominator
/
325 priv
->standard
.frameperiod
.numerator
;
326 int seconds
= priv
->video_buffer_size_max
/fps
;
328 if (seconds
< 5) seconds
= 5;
329 if (seconds
> 500) seconds
= 500;
331 // make the audio buffer at least as the video buffer capacity (or 5 seconds) long
332 priv
->audio_buffer_size
= 1 + seconds
*priv
->audio_in
.samplerate
333 *priv
->audio_in
.channels
334 *bytes_per_sample
/priv
->audio_in
.blocksize
;
335 if (priv
->audio_buffer_size
< 256) priv
->audio_buffer_size
= 256;
337 // make the skew buffer at least 1 second long
338 priv
->aud_skew_cnt
= 1 + 1*priv
->audio_in
.samplerate
339 *priv
->audio_in
.channels
340 *bytes_per_sample
/priv
->audio_in
.blocksize
;
341 if (priv
->aud_skew_cnt
< 16) priv
->aud_skew_cnt
= 16;
343 mp_msg(MSGT_TV
, MSGL_V
, "Audio capture - buffer %d blocks of %d bytes, skew average from %d meas.\n",
344 priv
->audio_buffer_size
, priv
->audio_in
.blocksize
, priv
->aud_skew_cnt
);
347 static void init_audio(priv_t
*priv
)
349 if (priv
->audio_inited
) return;
351 if (!tv_param_noaudio
) {
352 #if defined(HAVE_ALSA9) || defined(HAVE_ALSA1X)
354 audio_in_init(&priv
->audio_in
, AUDIO_IN_ALSA
);
356 audio_in_init(&priv
->audio_in
, AUDIO_IN_OSS
);
358 audio_in_init(&priv
->audio_in
, AUDIO_IN_OSS
);
361 if (priv
->audio_dev
) {
362 audio_in_set_device(&priv
->audio_in
, priv
->audio_dev
);
365 audio_in_set_samplerate(&priv
->audio_in
, 44100);
366 if (priv
->capability
.capabilities
& V4L2_CAP_TUNER
) {
367 if (priv
->tuner
.audmode
== V4L2_TUNER_MODE_STEREO
) {
368 audio_in_set_channels(&priv
->audio_in
, 2);
370 audio_in_set_channels(&priv
->audio_in
, 1);
373 if (tv_param_forcechan
>= 0) {
374 audio_in_set_channels(&priv
->audio_in
, tv_param_forcechan
);
376 audio_in_set_channels(&priv
->audio_in
, 2);
380 if (audio_in_setup(&priv
->audio_in
) < 0) return;
382 priv
->audio_inited
= 1;
388 ** the number of milliseconds elapsed between time0 and time1
390 static size_t difftv(struct timeval time1
, struct timeval time0
)
392 return (time1
.tv_sec
- time0
.tv_sec
) * 1000 +
393 (time1
.tv_usec
- time0
.tv_usec
) / 1000;
398 ** Get current video capture format.
400 static int getfmt(priv_t
*priv
)
404 priv
->format
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
405 if ((i
= ioctl(priv
->video_fd
, VIDIOC_G_FMT
, &priv
->format
)) < 0) {
406 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl get format failed: %s\n",
407 info
.short_name
, strerror(errno
));
414 ** Get current video capture standard.
416 static int getstd(priv_t
*priv
)
421 if (ioctl(priv
->video_fd
, VIDIOC_G_STD
, &id
) < 0) {
422 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl get standard failed: %s\n",
423 info
.short_name
, strerror(errno
));
427 priv
->standard
.index
= i
++;
428 if (ioctl(priv
->video_fd
, VIDIOC_ENUMSTD
, &priv
->standard
) < 0) {
431 } while (priv
->standard
.id
!= id
);
435 /***********************************************************************\
438 * Interface to mplayer *
441 \***********************************************************************/
443 static int set_mute(priv_t
*priv
, int value
)
445 struct v4l2_control control
;
446 control
.id
= V4L2_CID_AUDIO_MUTE
;
447 control
.value
= value
;
448 if (ioctl(priv
->video_fd
, VIDIOC_S_CTRL
, &control
) < 0) {
449 mp_msg(MSGT_TV
,MSGL_ERR
,"%s: ioctl set mute failed: %s\n",
450 info
.short_name
, strerror(errno
));
457 ** MPlayer uses values from -100 up to 100 for controls.
458 ** Here they are scaled to what the tv card needs and applied.
460 static int set_control(priv_t
*priv
, struct v4l2_control
*control
, int val_signed
) {
461 struct v4l2_queryctrl qctrl
;
463 qctrl
.id
= control
->id
;
464 if (ioctl(priv
->video_fd
, VIDIOC_QUERYCTRL
, &qctrl
) < 0) {
465 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl query control failed: %s\n",
466 info
.short_name
, strerror(errno
));
467 return TVI_CONTROL_FALSE
;
471 if (control
->value
< 0) {
472 control
->value
= qctrl
.default_value
+ control
->value
*
473 (qctrl
.default_value
- qctrl
.minimum
) / 100;
475 control
->value
= qctrl
.default_value
+ control
->value
*
476 (qctrl
.maximum
- qctrl
.default_value
) / 100;
479 if (control
->value
< 50) {
480 control
->value
= qctrl
.default_value
+ (control
->value
-50) *
481 (qctrl
.default_value
- qctrl
.minimum
) / 50;
483 control
->value
= qctrl
.default_value
+ (control
->value
-50) *
484 (qctrl
.maximum
- qctrl
.default_value
) / 50;
489 if (ioctl(priv
->video_fd
, VIDIOC_S_CTRL
, control
) < 0) {
490 mp_msg(MSGT_TV
, MSGL_ERR
,"%s: ioctl set %s %d failed: %s\n",
491 info
.short_name
, qctrl
.name
, control
->value
, strerror(errno
));
492 return TVI_CONTROL_FALSE
;
494 mp_msg(MSGT_TV
, MSGL_V
, "%s: set %s: %d [%d, %d]\n", info
.short_name
,
495 qctrl
.name
, control
->value
, qctrl
.minimum
, qctrl
.maximum
);
497 return TVI_CONTROL_TRUE
;
502 ** Scale the control values back to what mplayer needs.
504 static int get_control(priv_t
*priv
, struct v4l2_control
*control
, int val_signed
) {
505 struct v4l2_queryctrl qctrl
;
507 qctrl
.id
= control
->id
;
508 if (ioctl(priv
->video_fd
, VIDIOC_QUERYCTRL
, &qctrl
) < 0) {
509 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl query control failed: %s\n",
510 info
.short_name
, strerror(errno
));
511 return TVI_CONTROL_FALSE
;
514 if (ioctl(priv
->video_fd
, VIDIOC_G_CTRL
, control
) < 0) {
515 mp_msg(MSGT_TV
, MSGL_ERR
,"%s: ioctl get %s failed: %s\n",
516 info
.short_name
, qctrl
.name
, strerror(errno
));
517 return TVI_CONTROL_FALSE
;
519 mp_msg(MSGT_TV
, MSGL_V
, "%s: get %s: %d [%d, %d]\n", info
.short_name
,
520 qctrl
.name
, control
->value
, qctrl
.minimum
, qctrl
.maximum
);
523 if (control
->value
< qctrl
.default_value
) {
524 control
->value
= (control
->value
- qctrl
.default_value
) * 100 /
525 (qctrl
.default_value
- qctrl
.minimum
);
527 control
->value
= (control
->value
- qctrl
.default_value
) * 100 /
528 (qctrl
.maximum
- qctrl
.default_value
);
531 if (control
->value
< qctrl
.default_value
) {
532 control
->value
= (control
->value
- qctrl
.default_value
) * 50 /
533 (qctrl
.default_value
- qctrl
.minimum
) + 50;
535 control
->value
= (control
->value
- qctrl
.default_value
) * 50 /
536 (qctrl
.maximum
- qctrl
.default_value
) + 50;
540 return TVI_CONTROL_TRUE
;
543 static int control(priv_t
*priv
, int cmd
, void *arg
)
545 struct v4l2_control control
;
546 struct v4l2_frequency frequency
;
549 case TVI_CONTROL_IS_VIDEO
:
550 return priv
->capability
.capabilities
& V4L2_CAP_VIDEO_CAPTURE
?
551 TVI_CONTROL_TRUE
: TVI_CONTROL_FALSE
;
552 case TVI_CONTROL_IS_AUDIO
:
553 if (tv_param_force_audio
) return TVI_CONTROL_TRUE
;
554 case TVI_CONTROL_IS_TUNER
:
555 return priv
->capability
.capabilities
& V4L2_CAP_TUNER
?
556 TVI_CONTROL_TRUE
: TVI_CONTROL_FALSE
;
557 case TVI_CONTROL_IMMEDIATE
:
558 priv
->immediate_mode
= 1;
559 return TVI_CONTROL_TRUE
;
560 case TVI_CONTROL_VID_GET_FPS
:
561 *(float *)arg
= (float)priv
->standard
.frameperiod
.denominator
/
562 priv
->standard
.frameperiod
.numerator
;
563 mp_msg(MSGT_TV
, MSGL_V
, "%s: get fps: %f\n", info
.short_name
,
565 return TVI_CONTROL_TRUE
;
566 case TVI_CONTROL_VID_GET_BITS
:
567 if (getfmt(priv
) < 0) return TVI_CONTROL_FALSE
;
568 *(int *)arg
= pixfmt2depth(priv
->format
.fmt
.pix
.pixelformat
);
569 mp_msg(MSGT_TV
, MSGL_V
, "%s: get depth: %d\n", info
.short_name
,
571 return TVI_CONTROL_TRUE
;
572 case TVI_CONTROL_VID_GET_FORMAT
:
573 if (getfmt(priv
) < 0) return TVI_CONTROL_FALSE
;
574 *(int *)arg
= fcc_vl2mp(priv
->format
.fmt
.pix
.pixelformat
);
575 mp_msg(MSGT_TV
, MSGL_V
, "%s: get format: %s\n", info
.short_name
,
576 pixfmt2name(priv
->format
.fmt
.pix
.pixelformat
));
577 return TVI_CONTROL_TRUE
;
578 case TVI_CONTROL_VID_SET_FORMAT
:
579 if (getfmt(priv
) < 0) return TVI_CONTROL_FALSE
;
580 priv
->format
.fmt
.pix
.pixelformat
= fcc_mp2vl(*(int *)arg
);
581 priv
->format
.fmt
.pix
.field
= V4L2_FIELD_ANY
;
583 priv
->mp_format
= *(int *)arg
;
584 mp_msg(MSGT_TV
, MSGL_V
, "%s: set format: %s\n", info
.short_name
,
585 pixfmt2name(priv
->format
.fmt
.pix
.pixelformat
));
586 if (ioctl(priv
->video_fd
, VIDIOC_S_FMT
, &priv
->format
) < 0) {
587 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl set format failed: %s\n",
588 info
.short_name
, strerror(errno
));
589 return TVI_CONTROL_FALSE
;
591 /* according to the v4l2 specs VIDIOC_S_FMT should not fail, inflexible drivers
592 might even always return the default parameters -> update the format here*/
593 priv
->mp_format
= fcc_vl2mp(priv
->format
.fmt
.pix
.pixelformat
);
594 return TVI_CONTROL_TRUE
;
595 case TVI_CONTROL_VID_GET_WIDTH
:
596 if (getfmt(priv
) < 0) return TVI_CONTROL_FALSE
;
597 *(int *)arg
= priv
->format
.fmt
.pix
.width
;
598 mp_msg(MSGT_TV
, MSGL_V
, "%s: get width: %d\n", info
.short_name
,
600 return TVI_CONTROL_TRUE
;
601 case TVI_CONTROL_VID_CHK_WIDTH
:
602 return TVI_CONTROL_TRUE
;
603 case TVI_CONTROL_VID_SET_WIDTH
:
604 if (getfmt(priv
) < 0) return TVI_CONTROL_FALSE
;
605 priv
->format
.fmt
.pix
.width
= *(int *)arg
;
606 mp_msg(MSGT_TV
, MSGL_V
, "%s: set width: %d\n", info
.short_name
,
608 if (ioctl(priv
->video_fd
, VIDIOC_S_FMT
, &priv
->format
) < 0) {
609 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl set width failed: %s\n",
610 info
.short_name
, strerror(errno
));
611 return TVI_CONTROL_FALSE
;
613 return TVI_CONTROL_TRUE
;
614 case TVI_CONTROL_VID_GET_HEIGHT
:
615 if (getfmt(priv
) < 0) return TVI_CONTROL_FALSE
;
616 *(int *)arg
= priv
->format
.fmt
.pix
.height
;
617 mp_msg(MSGT_TV
, MSGL_V
, "%s: get height: %d\n", info
.short_name
,
619 return TVI_CONTROL_TRUE
;
620 case TVI_CONTROL_VID_CHK_HEIGHT
:
621 return TVI_CONTROL_TRUE
;
622 case TVI_CONTROL_VID_SET_HEIGHT
:
623 if (getfmt(priv
) < 0) return TVI_CONTROL_FALSE
;
624 priv
->format
.fmt
.pix
.height
= *(int *)arg
;
625 priv
->format
.fmt
.pix
.field
= V4L2_FIELD_ANY
;
626 mp_msg(MSGT_TV
, MSGL_V
, "%s: set height: %d\n", info
.short_name
,
628 if (ioctl(priv
->video_fd
, VIDIOC_S_FMT
, &priv
->format
) < 0) {
629 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl set height failed: %s\n",
630 info
.short_name
, strerror(errno
));
631 return TVI_CONTROL_FALSE
;
633 return TVI_CONTROL_TRUE
;
634 case TVI_CONTROL_VID_GET_BRIGHTNESS
:
635 control
.id
= V4L2_CID_BRIGHTNESS
;
636 if (get_control(priv
, &control
, 1) == TVI_CONTROL_TRUE
) {
637 *(int *)arg
= control
.value
;
638 return TVI_CONTROL_TRUE
;
640 return TVI_CONTROL_FALSE
;
641 case TVI_CONTROL_VID_SET_BRIGHTNESS
:
642 control
.id
= V4L2_CID_BRIGHTNESS
;
643 control
.value
= *(int *)arg
;
644 return set_control(priv
, &control
, 1);
645 case TVI_CONTROL_VID_GET_HUE
:
646 control
.id
= V4L2_CID_HUE
;
647 if (get_control(priv
, &control
, 1) == TVI_CONTROL_TRUE
) {
648 *(int *)arg
= control
.value
;
649 return TVI_CONTROL_TRUE
;
651 return TVI_CONTROL_FALSE
;
652 case TVI_CONTROL_VID_SET_HUE
:
653 control
.id
= V4L2_CID_HUE
;
654 control
.value
= *(int *)arg
;
655 return set_control(priv
, &control
, 1);
656 case TVI_CONTROL_VID_GET_SATURATION
:
657 control
.id
= V4L2_CID_SATURATION
;
658 if (get_control(priv
, &control
, 1) == TVI_CONTROL_TRUE
) {
659 *(int *)arg
= control
.value
;
660 return TVI_CONTROL_TRUE
;
662 return TVI_CONTROL_FALSE
;
663 case TVI_CONTROL_VID_SET_SATURATION
:
664 control
.id
= V4L2_CID_SATURATION
;
665 control
.value
= *(int *)arg
;
666 return set_control(priv
, &control
, 1);
667 case TVI_CONTROL_VID_GET_CONTRAST
:
668 control
.id
= V4L2_CID_CONTRAST
;
669 if (get_control(priv
, &control
, 1) == TVI_CONTROL_TRUE
) {
670 *(int *)arg
= control
.value
;
671 return TVI_CONTROL_TRUE
;
673 return TVI_CONTROL_FALSE
;
674 case TVI_CONTROL_VID_SET_CONTRAST
:
675 control
.id
= V4L2_CID_CONTRAST
;
676 control
.value
= *(int *)arg
;
677 return set_control(priv
, &control
, 1);
678 case TVI_CONTROL_TUN_GET_FREQ
:
680 frequency
.type
= V4L2_TUNER_ANALOG_TV
;
681 if (ioctl(priv
->video_fd
, VIDIOC_G_FREQUENCY
, &frequency
) < 0) {
682 mp_msg(MSGT_TV
,MSGL_ERR
,"%s: ioctl get frequency failed: %s\n",
683 info
.short_name
, strerror(errno
));
684 return TVI_CONTROL_FALSE
;
686 *(int *)arg
= frequency
.frequency
;
687 return TVI_CONTROL_TRUE
;
688 case TVI_CONTROL_TUN_SET_FREQ
:
691 usleep(100000); // wait to suppress noise during switching
694 frequency
.type
= V4L2_TUNER_ANALOG_TV
;
695 frequency
.frequency
= *(int *)arg
;
696 if (ioctl(priv
->video_fd
, VIDIOC_S_FREQUENCY
, &frequency
) < 0) {
697 mp_msg(MSGT_TV
,MSGL_ERR
,"%s: ioctl set frequency failed: %s\n",
698 info
.short_name
, strerror(errno
));
699 return TVI_CONTROL_FALSE
;
702 usleep(100000); // wait to suppress noise during switching
705 return TVI_CONTROL_TRUE
;
706 case TVI_CONTROL_TUN_GET_TUNER
:
707 mp_msg(MSGT_TV
, MSGL_V
, "%s: get tuner\n",info
.short_name
);
708 if (ioctl(priv
->video_fd
, VIDIOC_G_TUNER
, &priv
->tuner
) < 0) {
709 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl get tuner failed: %s\n",
710 info
.short_name
, strerror(errno
));
711 return TVI_CONTROL_FALSE
;
713 return TVI_CONTROL_TRUE
;
714 case TVI_CONTROL_TUN_SET_TUNER
:
715 mp_msg(MSGT_TV
, MSGL_V
, "%s: set tuner\n",info
.short_name
);
716 if (ioctl(priv
->video_fd
, VIDIOC_S_TUNER
, &priv
->tuner
) < 0) {
717 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl set tuner failed: %s\n",
718 info
.short_name
, strerror(errno
));
719 return TVI_CONTROL_FALSE
;
721 return TVI_CONTROL_TRUE
;
722 case TVI_CONTROL_TUN_GET_NORM
:
723 *(int *)arg
= priv
->standard
.index
;
724 return TVI_CONTROL_TRUE
;
725 case TVI_CONTROL_TUN_SET_NORM
:
726 priv
->standard
.index
= *(int *)arg
;
727 if (ioctl(priv
->video_fd
, VIDIOC_ENUMSTD
, &priv
->standard
) < 0) {
728 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl enum norm failed: %s\n",
729 info
.short_name
, strerror(errno
));
730 return TVI_CONTROL_FALSE
;
732 mp_msg(MSGT_TV
, MSGL_V
, "%s: set norm: %s\n", info
.short_name
, priv
->standard
.name
);
733 if (ioctl(priv
->video_fd
, VIDIOC_S_STD
, &priv
->standard
.id
) < 0) {
734 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl set norm failed: %s\n",
735 info
.short_name
, strerror(errno
));
736 return TVI_CONTROL_FALSE
;
738 return TVI_CONTROL_TRUE
;
739 case TVI_CONTROL_SPC_GET_NORMID
:
743 struct v4l2_standard standard
;
744 memset(&standard
, 0, sizeof(standard
));
746 if (-1 == ioctl(priv
->video_fd
, VIDIOC_ENUMSTD
, &standard
))
747 return TVI_CONTROL_FALSE
;
748 if (!strcasecmp(standard
.name
, (char *)arg
)) {
750 return TVI_CONTROL_TRUE
;
753 return TVI_CONTROL_FALSE
;
755 case TVI_CONTROL_SPC_GET_INPUT
:
756 if (ioctl(priv
->video_fd
, VIDIOC_G_INPUT
, (int *)arg
) < 0) {
757 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl get input failed: %s\n",
758 info
.short_name
, strerror(errno
));
759 return TVI_CONTROL_FALSE
;
761 return TVI_CONTROL_TRUE
;
762 case TVI_CONTROL_SPC_SET_INPUT
:
763 mp_msg(MSGT_TV
, MSGL_V
, "%s: set input: %d\n", info
.short_name
, *(int *)arg
);
764 priv
->input
.index
= *(int *)arg
;
765 if (ioctl(priv
->video_fd
, VIDIOC_ENUMINPUT
, &priv
->input
) < 0) {
766 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl enum input failed: %s\n",
767 info
.short_name
, strerror(errno
));
768 return TVI_CONTROL_FALSE
;
770 if (ioctl(priv
->video_fd
, VIDIOC_S_INPUT
, (int *)arg
) < 0) {
771 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl set input failed: %s\n",
772 info
.short_name
, strerror(errno
));
773 return TVI_CONTROL_FALSE
;
775 return TVI_CONTROL_TRUE
;
776 case TVI_CONTROL_AUD_GET_FORMAT
:
778 if (!priv
->audio_inited
) return TVI_CONTROL_FALSE
;
779 *(int *)arg
= AF_FORMAT_S16_LE
;
780 mp_msg(MSGT_TV
, MSGL_V
, "%s: get audio format: %d\n",
781 info
.short_name
, *(int *)arg
);
782 return TVI_CONTROL_TRUE
;
783 case TVI_CONTROL_AUD_GET_SAMPLERATE
:
785 if (!priv
->audio_inited
) return TVI_CONTROL_FALSE
;
786 *(int *)arg
= priv
->audio_in
.samplerate
;
787 mp_msg(MSGT_TV
, MSGL_V
, "%s: get audio samplerate: %d\n",
788 info
.short_name
, *(int *)arg
);
789 return TVI_CONTROL_TRUE
;
790 case TVI_CONTROL_AUD_GET_SAMPLESIZE
:
792 if (!priv
->audio_inited
) return TVI_CONTROL_FALSE
;
793 *(int *)arg
= priv
->audio_in
.bytes_per_sample
;
794 mp_msg(MSGT_TV
, MSGL_V
, "%s: get audio samplesize: %d\n",
795 info
.short_name
, *(int *)arg
);
796 return TVI_CONTROL_TRUE
;
797 case TVI_CONTROL_AUD_GET_CHANNELS
:
799 if (!priv
->audio_inited
) return TVI_CONTROL_FALSE
;
800 *(int *)arg
= priv
->audio_in
.channels
;
801 mp_msg(MSGT_TV
, MSGL_V
, "%s: get audio channels: %d\n",
802 info
.short_name
, *(int *)arg
);
803 return TVI_CONTROL_TRUE
;
804 case TVI_CONTROL_AUD_SET_SAMPLERATE
:
806 mp_msg(MSGT_TV
, MSGL_V
, "%s: set audio samplerate: %d\n",
807 info
.short_name
, *(int *)arg
);
808 if (audio_in_set_samplerate(&priv
->audio_in
, *(int*)arg
) < 0) return TVI_CONTROL_FALSE
;
809 // setup_audio_buffer_sizes(priv);
810 return TVI_CONTROL_TRUE
;
812 mp_msg(MSGT_TV
, MSGL_V
, "%s: unknown control: %d\n", info
.short_name
, cmd
);
813 return(TVI_CONTROL_UNKNOWN
);
817 #define PRIV ((priv_t *) (tvi_handle->priv))
819 /* handler creator - entry point ! */
820 static tvi_handle_t
*tvi_init_v4l2(char *video_dev
, char *audio_dev
)
822 tvi_handle_t
*tvi_handle
;
824 /* new_handle initializes priv with memset 0 */
825 tvi_handle
= new_handle();
831 PRIV
->video_dev
= strdup(video_dev
? video_dev
: "/dev/video0");
832 if (!PRIV
->video_dev
) {
833 free_handle(tvi_handle
);
838 PRIV
->audio_dev
= strdup(audio_dev
);
839 if (!PRIV
->audio_dev
) {
840 free(PRIV
->video_dev
);
841 free_handle(tvi_handle
);
852 static int uninit(priv_t
*priv
)
854 int i
, frames
, dropped
= 0;
857 if(priv
->video_grabber_thread
)
858 pthread_join(priv
->video_grabber_thread
, NULL
);
859 pthread_mutex_destroy(&priv
->video_buffer_mutex
);
861 if (priv
->streamon
) {
862 struct v4l2_buffer buf
;
864 /* get performance */
865 frames
= 1 + (priv
->curr_frame
- priv
->first_frame
+
866 priv
->standard
.frameperiod
.numerator
* 500000 /
867 priv
->standard
.frameperiod
.denominator
) *
868 priv
->standard
.frameperiod
.denominator
/
869 priv
->standard
.frameperiod
.numerator
/ 1000000;
870 dropped
= frames
- priv
->frames
;
872 /* turn off streaming */
873 if (ioctl(priv
->video_fd
, VIDIOC_STREAMOFF
, &(priv
->map
[0].buf
.type
)) < 0) {
874 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl streamoff failed: %s\n",
875 info
.short_name
, strerror(errno
));
879 /* unqueue all remaining buffers */
880 memset(&buf
,0,sizeof(buf
));
881 buf
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
882 buf
.memory
= V4L2_MEMORY_MMAP
;
883 while (!ioctl(priv
->video_fd
, VIDIOC_DQBUF
, &buf
));
886 /* unmap all buffers */
887 for (i
= 0; i
< priv
->mapcount
; i
++) {
888 if (munmap(priv
->map
[i
].addr
, priv
->map
[i
].len
) < 0) {
889 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: munmap capture buffer failed: %s\n",
890 info
.short_name
, strerror(errno
));
894 /* stop audio thread */
895 if (!tv_param_noaudio
&& priv
->audio_grabber_thread
) {
896 pthread_join(priv
->audio_grabber_thread
, NULL
);
897 pthread_mutex_destroy(&priv
->skew_mutex
);
898 pthread_mutex_destroy(&priv
->audio_mutex
);
903 /* free memory and close device */
904 free(priv
->map
); priv
->map
= NULL
;
906 if(priv
->video_fd
!=-1)close(priv
->video_fd
); priv
->video_fd
= -1;
907 free(priv
->video_dev
); priv
->video_dev
= NULL
;
909 if (priv
->video_ringbuffer
) {
911 for (i
= 0; i
< priv
->video_buffer_size_current
; i
++) {
912 free(priv
->video_ringbuffer
[i
]);
914 free(priv
->video_ringbuffer
);
916 if (priv
->video_timebuffer
)
917 free(priv
->video_timebuffer
);
918 if (!tv_param_noaudio
) {
919 if (priv
->audio_ringbuffer
)
920 free(priv
->audio_ringbuffer
);
921 if (priv
->audio_skew_buffer
)
922 free(priv
->audio_skew_buffer
);
923 if (priv
->audio_skew_delta_buffer
)
924 free(priv
->audio_skew_delta_buffer
);
927 /* show some nice statistics ;-) */
928 mp_msg(MSGT_TV
, MSGL_INFO
,
929 "%s: %d frames successfully processed, %d frames dropped.\n",
930 info
.short_name
, priv
->frames
, dropped
);
931 mp_msg(MSGT_TV
, MSGL_V
, "%s: up to %u video frames buffered.\n",
932 info
.short_name
, priv
->video_buffer_size_current
);
938 static int init(priv_t
*priv
)
942 priv
->audio_ringbuffer
= NULL
;
943 priv
->audio_skew_buffer
= NULL
;
944 priv
->audio_skew_delta_buffer
= NULL
;
946 priv
->audio_inited
= 0;
948 /* Open the video device. */
949 priv
->video_fd
= open(priv
->video_dev
, O_RDWR
);
950 if (priv
->video_fd
< 0) {
951 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: unable to open '%s': %s\n",
952 info
.short_name
, priv
->video_dev
, strerror(errno
));
956 mp_msg(MSGT_TV
, MSGL_DBG2
, "%s: video fd: %s: %d\n",
957 info
.short_name
, priv
->video_dev
, priv
->video_fd
);
960 ** Query the video capabilities and current settings
961 ** for further control calls.
963 if (ioctl(priv
->video_fd
, VIDIOC_QUERYCAP
, &priv
->capability
) < 0) {
964 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl query capabilities failed: %s\n",
965 info
.short_name
, strerror(errno
));
970 if (!(priv
->capability
.capabilities
& V4L2_CAP_VIDEO_CAPTURE
))
972 mp_msg(MSGT_TV
, MSGL_ERR
, "Device %s is not a video capture device.\n",
977 if (getfmt(priv
) < 0) {
983 ** if this device has got a tuner query it's settings
984 ** otherwise set some nice defaults
986 if (priv
->capability
.capabilities
& V4L2_CAP_TUNER
) {
987 if (ioctl(priv
->video_fd
, VIDIOC_G_TUNER
, &priv
->tuner
) < 0) {
988 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl get tuner failed: %s\n",
989 info
.short_name
, strerror(errno
));
994 mp_msg(MSGT_TV
, MSGL_INFO
, "Selected device: %s\n", priv
->capability
.card
);
995 if (priv
->capability
.capabilities
& V4L2_CAP_TUNER
) {
996 mp_msg(MSGT_TV
, MSGL_INFO
, " Tuner cap:%s%s%s\n",
997 (priv
->tuner
.capability
& V4L2_TUNER_CAP_STEREO
) ? " STEREO" : "",
998 (priv
->tuner
.capability
& V4L2_TUNER_CAP_LANG1
) ? " LANG1" : "",
999 (priv
->tuner
.capability
& V4L2_TUNER_CAP_LANG2
) ? " LANG2" : "");
1000 mp_msg(MSGT_TV
, MSGL_INFO
, " Tuner rxs:%s%s%s%s\n",
1001 (priv
->tuner
.rxsubchans
& V4L2_TUNER_SUB_MONO
) ? " MONO" : "",
1002 (priv
->tuner
.rxsubchans
& V4L2_TUNER_SUB_STEREO
) ? " STEREO" : "",
1003 (priv
->tuner
.rxsubchans
& V4L2_TUNER_SUB_LANG1
) ? " LANG1" : "",
1004 (priv
->tuner
.rxsubchans
& V4L2_TUNER_SUB_LANG2
) ? " LANG2" : "");
1006 mp_msg(MSGT_TV
, MSGL_INFO
, " Capabilites:%s%s%s%s%s%s%s%s%s%s%s\n",
1007 priv
->capability
.capabilities
& V4L2_CAP_VIDEO_CAPTURE
?
1008 " video capture": "",
1009 priv
->capability
.capabilities
& V4L2_CAP_VIDEO_OUTPUT
?
1010 " video output": "",
1011 priv
->capability
.capabilities
& V4L2_CAP_VIDEO_OVERLAY
?
1012 " video overlay": "",
1013 priv
->capability
.capabilities
& V4L2_CAP_VBI_CAPTURE
?
1014 " VBI capture device": "",
1015 priv
->capability
.capabilities
& V4L2_CAP_VBI_OUTPUT
?
1017 priv
->capability
.capabilities
& V4L2_CAP_RDS_CAPTURE
?
1018 " RDS data capture": "",
1019 priv
->capability
.capabilities
& V4L2_CAP_TUNER
?
1021 priv
->capability
.capabilities
& V4L2_CAP_AUDIO
?
1023 priv
->capability
.capabilities
& V4L2_CAP_READWRITE
?
1025 priv
->capability
.capabilities
& V4L2_CAP_ASYNCIO
?
1027 priv
->capability
.capabilities
& V4L2_CAP_STREAMING
?
1029 mp_msg(MSGT_TV
, MSGL_INFO
, " supported norms:");
1031 struct v4l2_standard standard
;
1032 memset(&standard
, 0, sizeof(standard
));
1034 if (-1 == ioctl(priv
->video_fd
, VIDIOC_ENUMSTD
, &standard
))
1036 mp_msg(MSGT_TV
, MSGL_INFO
, " %d = %s;", i
, standard
.name
);
1038 mp_msg(MSGT_TV
, MSGL_INFO
, "\n inputs:");
1039 for (i
= 0; 1; i
++) {
1040 struct v4l2_input input
;
1043 if (ioctl(priv
->video_fd
, VIDIOC_ENUMINPUT
, &input
) < 0) {
1046 mp_msg(MSGT_TV
, MSGL_INFO
, " %d = %s;", i
, input
.name
);
1048 if (ioctl(priv
->video_fd
, VIDIOC_G_INPUT
, &i
) < 0) {
1049 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl get input failed: %s\n",
1050 info
.short_name
, strerror(errno
));
1052 mp_msg(MSGT_TV
, MSGL_INFO
, "\n Current input: %d\n", i
);
1053 for (i
= 0; ; i
++) {
1054 struct v4l2_fmtdesc fmtdesc
;
1057 fmtdesc
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1058 if (ioctl(priv
->video_fd
, VIDIOC_ENUM_FMT
, &fmtdesc
) < 0) {
1061 mp_msg(MSGT_TV
, MSGL_V
, " Format %-6s (%2d bits, %s): %s\n",
1062 pixfmt2name(fmtdesc
.pixelformat
), pixfmt2depth(fmtdesc
.pixelformat
),
1063 fmtdesc
.description
, vo_format_name(fcc_vl2mp(fmtdesc
.pixelformat
)));
1065 mp_msg(MSGT_TV
, MSGL_INFO
, " Current format: %s\n",
1066 pixfmt2name(priv
->format
.fmt
.pix
.pixelformat
));
1068 /* set some nice defaults */
1069 if (getfmt(priv
) < 0) return 0;
1070 priv
->format
.fmt
.pix
.width
= 640;
1071 priv
->format
.fmt
.pix
.height
= 480;
1072 if (ioctl(priv
->video_fd
, VIDIOC_S_FMT
, &priv
->format
) < 0) {
1073 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl set format failed: %s\n",
1074 info
.short_name
, strerror(errno
));
1079 // if (!(priv->capability.capabilities & V4L2_CAP_AUDIO) && !tv_param_force_audio) tv_param_noaudio = 1;
1081 if (priv
->capability
.capabilities
& V4L2_CAP_TUNER
) {
1082 struct v4l2_control control
;
1083 if (tv_param_amode
>= 0) {
1084 mp_msg(MSGT_TV
, MSGL_V
, "%s: setting audio mode\n", info
.short_name
);
1085 priv
->tuner
.audmode
= amode2v4l(tv_param_amode
);
1086 if (ioctl(priv
->video_fd
, VIDIOC_S_TUNER
, &priv
->tuner
) < 0) {
1087 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl set tuner failed: %s\n",
1088 info
.short_name
, strerror(errno
));
1089 return TVI_CONTROL_FALSE
;
1092 mp_msg(MSGT_TV
, MSGL_INFO
, "%s: current audio mode is :%s%s%s%s\n", info
.short_name
,
1093 (priv
->tuner
.audmode
== V4L2_TUNER_MODE_MONO
) ? " MONO" : "",
1094 (priv
->tuner
.audmode
== V4L2_TUNER_MODE_STEREO
) ? " STEREO" : "",
1095 (priv
->tuner
.audmode
== V4L2_TUNER_MODE_LANG1
) ? " LANG1" : "",
1096 (priv
->tuner
.audmode
== V4L2_TUNER_MODE_LANG2
) ? " LANG2" : "");
1098 if (tv_param_volume
>= 0) {
1099 control
.id
= V4L2_CID_AUDIO_VOLUME
;
1100 control
.value
= tv_param_volume
;
1101 set_control(priv
, &control
, 0);
1103 if (tv_param_bass
>= 0) {
1104 control
.id
= V4L2_CID_AUDIO_BASS
;
1105 control
.value
= tv_param_bass
;
1106 set_control(priv
, &control
, 0);
1108 if (tv_param_treble
>= 0) {
1109 control
.id
= V4L2_CID_AUDIO_TREBLE
;
1110 control
.value
= tv_param_treble
;
1111 set_control(priv
, &control
, 0);
1113 if (tv_param_balance
>= 0) {
1114 control
.id
= V4L2_CID_AUDIO_BALANCE
;
1115 control
.value
= tv_param_balance
;
1116 set_control(priv
, &control
, 0);
1123 static int get_capture_buffer_size(priv_t
*priv
)
1126 int w
= priv
->format
.fmt
.pix
.width
;
1127 int h
= priv
->format
.fmt
.pix
.height
;
1128 int d
= pixfmt2depth(priv
->format
.fmt
.pix
.pixelformat
);
1129 int bytesperline
= w
*d
/8;
1131 if (tv_param_buffer_size
>= 0) {
1132 bufsize
= tv_param_buffer_size
*1024*1024;
1134 #ifdef HAVE_SYS_SYSINFO_H
1138 if (si
.totalram
<2*1024*1024) {
1139 bufsize
= 1024*1024;
1141 bufsize
= si
.totalram
/2;
1144 bufsize
= 16*1024*1024;
1148 cnt
= bufsize
/(h
*bytesperline
);
1149 if (cnt
< 2) cnt
= 2;
1154 /* that's the real start, we'got the format parameters (checked with control) */
1155 static int start(priv_t
*priv
)
1157 struct v4l2_requestbuffers request
;
1160 /* setup audio parameters */
1163 if (!tv_param_noaudio
&& !priv
->audio_inited
) return 0;
1165 /* we need this to size the audio buffer properly */
1166 if (priv
->immediate_mode
) {
1167 priv
->video_buffer_size_max
= 2;
1169 priv
->video_buffer_size_max
= get_capture_buffer_size(priv
);
1172 if (!tv_param_noaudio
) {
1173 setup_audio_buffer_sizes(priv
);
1174 priv
->audio_skew_buffer
= calloc(priv
->aud_skew_cnt
, sizeof(long long));
1175 if (!priv
->audio_skew_buffer
) {
1176 mp_msg(MSGT_TV
, MSGL_ERR
, "cannot allocate skew buffer: %s\n", strerror(errno
));
1179 priv
->audio_skew_delta_buffer
= calloc(priv
->aud_skew_cnt
, sizeof(long long));
1180 if (!priv
->audio_skew_delta_buffer
) {
1181 mp_msg(MSGT_TV
, MSGL_ERR
, "cannot allocate skew buffer: %s\n", strerror(errno
));
1185 priv
->audio_ringbuffer
= calloc(priv
->audio_in
.blocksize
, priv
->audio_buffer_size
);
1186 if (!priv
->audio_ringbuffer
) {
1187 mp_msg(MSGT_TV
, MSGL_ERR
, "cannot allocate audio buffer: %s\n", strerror(errno
));
1191 priv
->audio_secs_per_block
= (double)priv
->audio_in
.blocksize
/(priv
->audio_in
.samplerate
1192 *priv
->audio_in
.channels
1193 *priv
->audio_in
.bytes_per_sample
);
1194 priv
->audio_usecs_per_block
= 1e6
*priv
->audio_secs_per_block
;
1195 priv
->audio_head
= 0;
1196 priv
->audio_tail
= 0;
1197 priv
->audio_cnt
= 0;
1198 priv
->audio_drop
= 0;
1199 priv
->audio_skew
= 0;
1200 priv
->audio_skew_total
= 0;
1201 priv
->audio_skew_delta_total
= 0;
1202 priv
->audio_recv_blocks_total
= 0;
1203 priv
->audio_sent_blocks_total
= 0;
1204 priv
->audio_null_blocks_inserted
= 0;
1205 priv
->audio_insert_null_samples
= 0;
1206 priv
->dropped_frames_timeshift
= 0;
1207 priv
->dropped_frames_compensated
= 0;
1209 pthread_mutex_init(&priv
->skew_mutex
, NULL
);
1210 pthread_mutex_init(&priv
->audio_mutex
, NULL
);
1213 /* setup video parameters */
1214 if (!tv_param_noaudio
) {
1215 if (priv
->video_buffer_size_max
< (3*priv
->standard
.frameperiod
.denominator
) /
1216 priv
->standard
.frameperiod
.numerator
1217 *priv
->audio_secs_per_block
) {
1218 mp_msg(MSGT_TV
, MSGL_ERR
, "Video buffer shorter than 3 times audio frame duration.\n"
1219 "You will probably experience heavy framedrops.\n");
1224 int bytesperline
= priv
->format
.fmt
.pix
.width
*pixfmt2depth(priv
->format
.fmt
.pix
.pixelformat
)/8;
1226 mp_msg(MSGT_TV
, MSGL_V
, "Using a ring buffer for maximum %d frames, %d MB total size.\n",
1227 priv
->video_buffer_size_max
,
1228 priv
->video_buffer_size_max
*priv
->format
.fmt
.pix
.height
*bytesperline
/(1024*1024));
1231 priv
->video_ringbuffer
= calloc(priv
->video_buffer_size_max
, sizeof(unsigned char*));
1232 if (!priv
->video_ringbuffer
) {
1233 mp_msg(MSGT_TV
, MSGL_ERR
, "cannot allocate video buffer: %s\n", strerror(errno
));
1236 for (i
= 0; i
< priv
->video_buffer_size_max
; i
++)
1237 priv
->video_ringbuffer
[i
] = NULL
;
1238 priv
->video_timebuffer
= calloc(priv
->video_buffer_size_max
, sizeof(long long));
1239 if (!priv
->video_timebuffer
) {
1240 mp_msg(MSGT_TV
, MSGL_ERR
, "cannot allocate time buffer: %s\n", strerror(errno
));
1244 pthread_mutex_init(&priv
->video_buffer_mutex
, NULL
);
1246 priv
->video_head
= 0;
1247 priv
->video_tail
= 0;
1248 priv
->video_cnt
= 0;
1250 /* request buffers */
1251 if (priv
->immediate_mode
) {
1254 request
.count
= BUFFER_COUNT
;
1257 request
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1258 request
.memory
= V4L2_MEMORY_MMAP
;
1259 if (ioctl(priv
->video_fd
, VIDIOC_REQBUFS
, &request
) < 0) {
1260 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl request buffers failed: %s\n",
1261 info
.short_name
, strerror(errno
));
1266 if (!(priv
->map
= calloc(request
.count
, sizeof(struct map
)))) {
1267 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: malloc capture buffers failed: %s\n",
1268 info
.short_name
, strerror(errno
));
1272 /* map and queue buffers */
1273 for (i
= 0; i
< request
.count
; i
++) {
1274 memset(&priv
->map
[i
].buf
,0,sizeof(priv
->map
[i
].buf
));
1275 priv
->map
[i
].buf
.index
= i
;
1276 priv
->map
[i
].buf
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1277 priv
->map
[i
].buf
.memory
= V4L2_MEMORY_MMAP
;
1278 if (ioctl(priv
->video_fd
, VIDIOC_QUERYBUF
, &(priv
->map
[i
].buf
)) < 0) {
1279 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl query buffer failed: %s\n",
1280 info
.short_name
, strerror(errno
));
1285 priv
->map
[i
].addr
= mmap (0, priv
->map
[i
].buf
.length
, PROT_READ
|
1286 PROT_WRITE
, MAP_SHARED
, priv
->video_fd
, priv
->map
[i
].buf
.m
.offset
);
1287 if (priv
->map
[i
].addr
== MAP_FAILED
) {
1288 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: mmap capture buffer failed: %s\n",
1289 info
.short_name
, strerror(errno
));
1290 priv
->map
[i
].len
= 0;
1293 priv
->map
[i
].len
= priv
->map
[i
].buf
.length
;
1294 /* count up to make sure this is correct everytime */
1297 if (ioctl(priv
->video_fd
, VIDIOC_QBUF
, &(priv
->map
[i
].buf
)) < 0) {
1298 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl queue buffer failed: %s\n",
1299 info
.short_name
, strerror(errno
));
1304 /* start audio thread */
1306 priv
->audio_skew_measure_time
= 0;
1307 priv
->first_frame
= 0;
1308 priv
->audio_skew
= 0;
1317 #ifdef HAVE_TV_BSDBT848
1318 static double grabimmediate_video_frame(priv_t
*priv
, char *buffer
, int len
)
1320 memset(buffer
, 0xCC, len
);
1323 #endif /* HAVE_TV_BSDBT848 */
1325 // copies a video frame
1326 static inline void copy_frame(priv_t
*priv
, unsigned char *dest
, unsigned char *source
)
1328 int w
= priv
->format
.fmt
.pix
.width
;
1329 int h
= priv
->format
.fmt
.pix
.height
;
1330 int d
= pixfmt2depth(priv
->format
.fmt
.pix
.pixelformat
);
1331 int bytesperline
= w
*d
/8;
1333 memcpy(dest
, source
, bytesperline
* h
);
1336 // maximum skew change, in frames
1337 #define MAX_SKEW_DELTA 0.6
1338 static void *video_grabber(void *data
)
1340 priv_t
*priv
= (priv_t
*)data
;
1341 long long skew
, prev_skew
, xskew
, interval
, prev_interval
, delta
;
1343 int framesize
= priv
->format
.fmt
.pix
.height
*priv
->format
.fmt
.pix
.width
*
1344 pixfmt2depth(priv
->format
.fmt
.pix
.pixelformat
)/8;
1346 struct timeval timeout
;
1347 struct v4l2_buffer buf
;
1355 mp_msg(MSGT_TV
, MSGL_V
, "%s: going to capture\n", info
.short_name
);
1356 if (ioctl(priv
->video_fd
, VIDIOC_STREAMON
, &(priv
->format
.type
)) < 0) {
1357 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl streamon failed: %s\n",
1358 info
.short_name
, strerror(errno
));
1363 if (!tv_param_noaudio
) {
1364 pthread_create(&priv
->audio_grabber_thread
, NULL
, audio_grabber
, priv
);
1367 for (priv
->frames
= 0; !priv
->shutdown
;)
1371 if (priv
->immediate_mode
) {
1372 while (priv
->video_cnt
== priv
->video_buffer_size_max
) {
1374 if (priv
->shutdown
) {
1381 FD_SET (priv
->video_fd
, &rdset
);
1384 timeout
.tv_usec
= 0;
1386 i
= select(priv
->video_fd
+ 1, &rdset
, NULL
, NULL
, &timeout
);
1388 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: select failed: %s\n",
1389 info
.short_name
, strerror(errno
));
1393 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: select timeout\n", info
.short_name
);
1396 else if (!FD_ISSET(priv
->video_fd
, &rdset
)) {
1400 memset(&buf
,0,sizeof(buf
));
1401 buf
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1402 buf
.memory
= V4L2_MEMORY_MMAP
;
1403 ret
= ioctl(priv
->video_fd
, VIDIOC_DQBUF
, &buf
);
1407 if there's no signal, the buffer might me dequeued
1408 so we query all the buffers to see which one we should
1411 observed with saa7134 0.2.8
1412 don't know if is it a bug or (mis)feature
1414 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl dequeue buffer failed: %s, idx = %d\n",
1415 info
.short_name
, strerror(errno
), buf
.index
);
1416 for (i
= 0; i
< priv
->mapcount
; i
++) {
1417 memset(&buf
,0,sizeof(buf
));
1418 buf
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1419 buf
.memory
= V4L2_MEMORY_MMAP
;
1421 ret
= ioctl(priv
->video_fd
, VIDIOC_QUERYBUF
, &buf
);
1423 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl query buffer failed: %s, idx = %d\n",
1424 info
.short_name
, strerror(errno
), buf
.index
);
1427 if ((buf
.flags
& (V4L2_BUF_FLAG_QUEUED
| V4L2_BUF_FLAG_MAPPED
| V4L2_BUF_FLAG_DONE
)) == V4L2_BUF_FLAG_MAPPED
) {
1428 if (ioctl(priv
->video_fd
, VIDIOC_QBUF
, &(priv
->map
[i
].buf
)) < 0) {
1429 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl queue buffer failed: %s\n",
1430 info
.short_name
, strerror(errno
));
1438 /* store the timestamp of the very first frame as reference */
1439 if (!priv
->frames
++) {
1440 if (!tv_param_noaudio
) pthread_mutex_lock(&priv
->skew_mutex
);
1441 priv
->first_frame
= (long long)1e6
*buf
.timestamp
.tv_sec
+ buf
.timestamp
.tv_usec
;
1442 if (!tv_param_noaudio
) pthread_mutex_unlock(&priv
->skew_mutex
);
1444 priv
->curr_frame
= (long long)buf
.timestamp
.tv_sec
*1e6
+buf
.timestamp
.tv_usec
;
1445 // fprintf(stderr, "idx = %d, ts = %lf\n", buf.index, (double)(priv->curr_frame) / 1e6);
1447 interval
= priv
->curr_frame
- priv
->first_frame
;
1448 delta
= interval
- prev_interval
;
1450 if (!priv
->immediate_mode
) {
1451 // interpolate the skew in time
1452 if (!tv_param_noaudio
) pthread_mutex_lock(&priv
->skew_mutex
);
1453 xskew
= priv
->audio_skew
+ (interval
- priv
->audio_skew_measure_time
)*priv
->audio_skew_factor
;
1454 if (!tv_param_noaudio
) pthread_mutex_unlock(&priv
->skew_mutex
);
1455 // correct extreme skew changes to avoid (especially) moving backwards in time
1456 if (xskew
- prev_skew
> delta
*MAX_SKEW_DELTA
) {
1457 skew
= prev_skew
+ delta
*MAX_SKEW_DELTA
;
1458 } else if (xskew
- prev_skew
< -delta
*MAX_SKEW_DELTA
) {
1459 skew
= prev_skew
- delta
*MAX_SKEW_DELTA
;
1465 mp_msg(MSGT_TV
, MSGL_DBG3
, "\nfps = %lf, interval = %lf, a_skew = %f, corr_skew = %f\n",
1466 delta
? (double)1e6
/delta
: -1,
1467 (double)1e-6*interval
, (double)1e-6*xskew
, (double)1e-6*skew
);
1468 mp_msg(MSGT_TV
, MSGL_DBG3
, "vcnt = %d, acnt = %d\n", priv
->video_cnt
, priv
->audio_cnt
);
1471 prev_interval
= interval
;
1473 /* allocate a new buffer, if needed */
1474 pthread_mutex_lock(&priv
->video_buffer_mutex
);
1475 if (priv
->video_buffer_size_current
< priv
->video_buffer_size_max
) {
1476 if (priv
->video_cnt
== priv
->video_buffer_size_current
) {
1477 unsigned char *newbuf
= malloc(framesize
);
1479 memmove(priv
->video_ringbuffer
+priv
->video_tail
+1, priv
->video_ringbuffer
+priv
->video_tail
,
1480 (priv
->video_buffer_size_current
-priv
->video_tail
)*sizeof(unsigned char *));
1481 memmove(priv
->video_timebuffer
+priv
->video_tail
+1, priv
->video_timebuffer
+priv
->video_tail
,
1482 (priv
->video_buffer_size_current
-priv
->video_tail
)*sizeof(long long));
1483 priv
->video_ringbuffer
[priv
->video_tail
] = newbuf
;
1484 if ((priv
->video_head
>= priv
->video_tail
) && (priv
->video_cnt
> 0)) priv
->video_head
++;
1485 priv
->video_buffer_size_current
++;
1489 pthread_mutex_unlock(&priv
->video_buffer_mutex
);
1491 if (priv
->video_cnt
== priv
->video_buffer_size_current
) {
1492 if (!priv
->immediate_mode
) {
1493 mp_msg(MSGT_TV
, MSGL_ERR
, "\nvideo buffer full - dropping frame\n");
1494 if (priv
->audio_insert_null_samples
) {
1495 pthread_mutex_lock(&priv
->audio_mutex
);
1496 priv
->dropped_frames_timeshift
+= delta
;
1497 pthread_mutex_unlock(&priv
->audio_mutex
);
1501 if (priv
->immediate_mode
) {
1502 priv
->video_timebuffer
[priv
->video_tail
] = 0;
1504 // compensate for audio skew
1505 // negative skew => there are more audio samples, increase interval
1506 // positive skew => less samples, shorten the interval
1507 priv
->video_timebuffer
[priv
->video_tail
] = interval
- skew
;
1508 if (priv
->audio_insert_null_samples
&& priv
->video_timebuffer
[priv
->video_tail
] > 0) {
1509 pthread_mutex_lock(&priv
->audio_mutex
);
1510 priv
->video_timebuffer
[priv
->video_tail
] +=
1511 (priv
->audio_null_blocks_inserted
1512 - priv
->dropped_frames_timeshift
/priv
->audio_usecs_per_block
)
1513 *priv
->audio_usecs_per_block
;
1514 pthread_mutex_unlock(&priv
->audio_mutex
);
1518 copy_frame(priv
, priv
->video_ringbuffer
[priv
->video_tail
], priv
->map
[buf
.index
].addr
);
1519 priv
->video_tail
= (priv
->video_tail
+1)%priv
->video_buffer_size_current
;
1522 if (ioctl(priv
->video_fd
, VIDIOC_QBUF
, &buf
) < 0) {
1523 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl queue buffer failed: %s\n",
1524 info
.short_name
, strerror(errno
));
1532 static double grab_video_frame(priv_t
*priv
, char *buffer
, int len
)
1538 pthread_create(&priv
->video_grabber_thread
, NULL
, video_grabber
, priv
);
1542 while (priv
->video_cnt
== 0) {
1544 if (loop_cnt
++ > MAX_LOOP
) return 0;
1547 pthread_mutex_lock(&priv
->video_buffer_mutex
);
1548 interval
= (double)priv
->video_timebuffer
[priv
->video_head
]*1e-6;
1549 memcpy(buffer
, priv
->video_ringbuffer
[priv
->video_head
], len
);
1551 priv
->video_head
= (priv
->video_head
+1)%priv
->video_buffer_size_current
;
1552 pthread_mutex_unlock(&priv
->video_buffer_mutex
);
1557 static int get_video_framesize(priv_t
*priv
)
1559 return priv
->format
.fmt
.pix
.sizeimage
;
1562 //#define DOUBLESPEED
1564 // for testing purposes only
1565 static void read_doublespeed(priv_t
*priv
)
1567 char *bufx
= calloc(priv
->audio_in
.blocksize
, 2);
1572 audio_in_read_chunk(&priv
->audio_in
, bufx
);
1573 audio_in_read_chunk(&priv
->audio_in
, bufx
+priv
->audio_in
.blocksize
);
1576 d
= priv
->audio_ringbuffer
+priv
->audio_tail
*priv
->audio_in
.blocksize
;
1577 for (i
= 0; i
< priv
->audio_in
.blocksize
/2; i
++) {
1585 static void *audio_grabber(void *data
)
1587 priv_t
*priv
= (priv_t
*)data
;
1589 int i
, audio_skew_ptr
= 0;
1590 long long current_time
, prev_skew
= 0, prev_skew_uncorr
= 0;
1591 long long start_time_avg
;
1593 gettimeofday(&tv
, NULL
);
1594 start_time_avg
= priv
->audio_start_time
= (long long)1e6
*tv
.tv_sec
+ tv
.tv_usec
;
1595 audio_in_start_capture(&priv
->audio_in
);
1596 for (i
= 0; i
< priv
->aud_skew_cnt
; i
++)
1597 priv
->audio_skew_buffer
[i
] = 0;
1598 for (i
= 0; i
< priv
->aud_skew_cnt
; i
++)
1599 priv
->audio_skew_delta_buffer
[i
] = 0;
1601 for (; !priv
->shutdown
;)
1604 read_doublespeed(priv
);
1606 if (audio_in_read_chunk(&priv
->audio_in
, priv
->audio_ringbuffer
+priv
->audio_tail
*priv
->audio_in
.blocksize
) < 0)
1609 pthread_mutex_lock(&priv
->skew_mutex
);
1610 if (priv
->first_frame
== 0) {
1611 // there is no first frame yet (unlikely to happen)
1612 gettimeofday(&tv
, NULL
);
1613 start_time_avg
= priv
->audio_start_time
= (long long)1e6
*tv
.tv_sec
+ tv
.tv_usec
;
1614 // fprintf(stderr, "warning - first frame not yet available!\n");
1615 pthread_mutex_unlock(&priv
->skew_mutex
);
1618 pthread_mutex_unlock(&priv
->skew_mutex
);
1620 gettimeofday(&tv
, NULL
);
1622 priv
->audio_recv_blocks_total
++;
1623 current_time
= (long long)1e6
*tv
.tv_sec
+ tv
.tv_usec
- priv
->audio_start_time
;
1625 if (priv
->audio_recv_blocks_total
< priv
->aud_skew_cnt
*2) {
1626 start_time_avg
+= (long long)1e6
*tv
.tv_sec
+ tv
.tv_usec
- priv
->audio_usecs_per_block
*priv
->audio_recv_blocks_total
;
1627 priv
->audio_start_time
= start_time_avg
/(priv
->audio_recv_blocks_total
+1);
1630 // fprintf(stderr, "spb = %lf, bs = %d, skew = %lf\n", priv->audio_secs_per_block, priv->audio_in.blocksize,
1631 // (double)(current_time - 1e6*priv->audio_secs_per_block*priv->audio_recv_blocks_total)/1e6);
1633 // put the current skew into the ring buffer
1634 priv
->audio_skew_total
-= priv
->audio_skew_buffer
[audio_skew_ptr
];
1635 priv
->audio_skew_buffer
[audio_skew_ptr
] = current_time
1636 - priv
->audio_usecs_per_block
*priv
->audio_recv_blocks_total
;
1637 priv
->audio_skew_total
+= priv
->audio_skew_buffer
[audio_skew_ptr
];
1639 pthread_mutex_lock(&priv
->skew_mutex
);
1643 // compute the sliding average of the skews
1644 if (priv
->audio_recv_blocks_total
> priv
->aud_skew_cnt
) {
1645 priv
->audio_skew
= priv
->audio_skew_total
/priv
->aud_skew_cnt
;
1647 priv
->audio_skew
= priv
->audio_skew_total
/priv
->audio_recv_blocks_total
;
1650 // put the current skew change (skew-prev_skew) into the ring buffer
1651 priv
->audio_skew_delta_total
-= priv
->audio_skew_delta_buffer
[audio_skew_ptr
];
1652 priv
->audio_skew_delta_buffer
[audio_skew_ptr
] = priv
->audio_skew
- prev_skew_uncorr
;
1653 priv
->audio_skew_delta_total
+= priv
->audio_skew_delta_buffer
[audio_skew_ptr
];
1654 prev_skew_uncorr
= priv
->audio_skew
; // remember the _uncorrected_ average value
1656 audio_skew_ptr
= (audio_skew_ptr
+1) % priv
->aud_skew_cnt
; // rotate the buffer pointer
1658 // sliding average approximates the value in the middle of the interval
1659 // so interpolate the skew value further to the current time
1660 priv
->audio_skew
+= priv
->audio_skew_delta_total
/2;
1662 // now finally, priv->audio_skew contains fairly good approximation
1663 // of the current value
1665 // current skew factor (assuming linearity)
1666 // used for further interpolation in video_grabber
1667 // probably overkill but seems to be necessary for
1668 // stress testing by dropping half of the audio frames ;)
1669 // especially when using ALSA with large block sizes
1670 // where audio_skew remains a long while behind
1671 if ((priv
->audio_skew_measure_time
!= 0) && (current_time
- priv
->audio_skew_measure_time
!= 0)) {
1672 priv
->audio_skew_factor
= (double)(priv
->audio_skew
-prev_skew
)/(current_time
- priv
->audio_skew_measure_time
);
1674 priv
->audio_skew_factor
= 0.0;
1677 priv
->audio_skew_measure_time
= current_time
;
1678 prev_skew
= priv
->audio_skew
;
1679 priv
->audio_skew
+= priv
->audio_start_time
- priv
->first_frame
;
1680 pthread_mutex_unlock(&priv
->skew_mutex
);
1682 // fprintf(stderr, "audio_skew = %lf, delta = %lf\n", (double)priv->audio_skew/1e6, (double)priv->audio_skew_delta_total/1e6);
1684 pthread_mutex_lock(&priv
->audio_mutex
);
1685 if ((priv
->audio_tail
+1) % priv
->audio_buffer_size
== priv
->audio_head
) {
1686 mp_msg(MSGT_TV
, MSGL_ERR
, "\ntoo bad - dropping audio frame !\n");
1689 priv
->audio_tail
= (priv
->audio_tail
+1) % priv
->audio_buffer_size
;
1692 pthread_mutex_unlock(&priv
->audio_mutex
);
1697 static double grab_audio_frame(priv_t
*priv
, char *buffer
, int len
)
1699 mp_dbg(MSGT_TV
, MSGL_DBG2
, "grab_audio_frame(priv=%p, buffer=%p, len=%d)\n",
1702 // hack: if grab_audio_frame is called first, it means we are used by mplayer
1703 // => switch to the mode which outputs audio immediately, even if
1704 // it should be silence
1705 if (priv
->first
) priv
->audio_insert_null_samples
= 1;
1707 pthread_mutex_lock(&priv
->audio_mutex
);
1708 while (priv
->audio_insert_null_samples
1709 && priv
->dropped_frames_timeshift
- priv
->dropped_frames_compensated
>= priv
->audio_usecs_per_block
) {
1710 // some frames were dropped - drop the corresponding number of audio blocks
1711 if (priv
->audio_drop
) {
1714 if (priv
->audio_head
== priv
->audio_tail
) break;
1715 priv
->audio_head
= (priv
->audio_head
+1) % priv
->audio_buffer_size
;
1717 priv
->dropped_frames_compensated
+= priv
->audio_usecs_per_block
;
1720 // compensate for dropped audio frames
1721 if (priv
->audio_drop
&& (priv
->audio_head
== priv
->audio_tail
)) {
1723 memset(buffer
, 0, len
);
1727 if (priv
->audio_insert_null_samples
&& (priv
->audio_head
== priv
->audio_tail
)) {
1728 // return silence to avoid desync and stuttering
1729 memset(buffer
, 0, len
);
1730 priv
->audio_null_blocks_inserted
++;
1734 pthread_mutex_unlock(&priv
->audio_mutex
);
1735 while (priv
->audio_head
== priv
->audio_tail
) {
1736 // this is mencoder => just wait until some audio is available
1739 pthread_mutex_lock(&priv
->audio_mutex
);
1740 memcpy(buffer
, priv
->audio_ringbuffer
+priv
->audio_head
*priv
->audio_in
.blocksize
, len
);
1741 priv
->audio_head
= (priv
->audio_head
+1) % priv
->audio_buffer_size
;
1744 pthread_mutex_unlock(&priv
->audio_mutex
);
1745 priv
->audio_sent_blocks_total
++;
1746 return (double)priv
->audio_sent_blocks_total
*priv
->audio_secs_per_block
;
1749 static int get_audio_framesize(priv_t
*priv
)
1751 return(priv
->audio_in
.blocksize
);