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 /* information about this file */
50 static tvi_info_t info
= {
51 "Video 4 Linux 2 input",
53 "Martin Olschewski <olschewski@zpr.uni-koeln.de>",
54 "first try, more to come ;-)"
58 struct v4l2_buffer buf
;
63 #define BUFFER_COUNT 6
71 struct v4l2_capability capability
;
72 struct v4l2_input input
;
73 struct v4l2_format format
;
74 struct v4l2_standard standard
;
75 struct v4l2_tuner tuner
;
79 volatile long long first_frame
;
81 /* audio video interleaving ;-) */
82 volatile int streamon
;
83 pthread_t audio_grabber_thread
;
84 pthread_mutex_t skew_mutex
;
86 /* 2nd level video buffers */
90 int video_buffer_size_max
;
91 volatile int video_buffer_size_current
;
92 unsigned char **video_ringbuffer
;
93 long long *video_timebuffer
;
94 volatile int video_head
;
95 volatile int video_tail
;
96 volatile int video_cnt
;
97 pthread_t video_grabber_thread
;
98 pthread_mutex_t video_buffer_mutex
;
104 long long audio_start_time
;
105 int audio_buffer_size
;
107 unsigned char *audio_ringbuffer
;
108 long long *audio_skew_buffer
;
109 long long *audio_skew_delta_buffer
;
110 volatile int audio_head
;
111 volatile int audio_tail
;
112 volatile int audio_cnt
;
113 volatile long long audio_skew
;
114 volatile double audio_skew_factor
;
115 volatile long long audio_skew_measure_time
;
116 volatile int audio_drop
;
117 volatile int shutdown
;
120 double audio_secs_per_block
;
121 long long audio_usecs_per_block
;
122 long long audio_skew_total
;
123 long long audio_skew_delta_total
;
124 long audio_recv_blocks_total
;
125 long audio_sent_blocks_total
;
126 pthread_mutex_t audio_mutex
;
127 int audio_insert_null_samples
;
128 volatile long audio_null_blocks_inserted
;
129 volatile long long dropped_frames_timeshift
;
130 long long dropped_frames_compensated
;
135 static void *audio_grabber(void *data
);
136 static void *video_grabber(void *data
);
138 /**********************************************************************\
140 Only few of the fourccs are the same in v4l2 and mplayer:
142 IMGFMT_YVU9 == V4L2_PIX_FMT_YVU410
143 IMGFMT_YV12 == V4L2_PIX_FMT_YVU420
144 IMGFMT_NV12 == V4L2_PIX_FMT_NV12
145 IMGFMT_422P == V4L2_PIX_FMT_YUV422P
146 IMGFMT_411P == V4L2_PIX_FMT_YUV411P
147 IMGFMT_UYVY == V4L2_PIX_FMT_UYVY
148 IMGFMT_Y41P == V4L2_PIX_FMT_Y41P
150 This may be an useful translation table for some others:
152 IMGFMT_RGB8 == V4L2_PIX_FMT_RGB332
153 IMGFMT_BGR15 == V4L2_PIX_FMT_RGB555
154 IMGFMT_BGR16 == V4L2_PIX_FMT_RGB565
155 IMGFMT_RGB24 == V4L2_PIX_FMT_RGB24
156 IMGFMT_RGB32 == V4L2_PIX_FMT_RGB32
157 IMGFMT_BGR24 == V4L2_PIX_FMT_BGR24
158 IMGFMT_BGR32 == V4L2_PIX_FMT_BGR32
159 IMGFMT_Y800 == V4L2_PIX_FMT_GREY
160 IMGFMT_IF09 == V4L2_PIX_FMT_YUV410
161 IMGFMT_I420 == V4L2_PIX_FMT_YUV420
162 IMGFMT_YUY2 == V4L2_PIX_FMT_YUYV
164 \**********************************************************************/
167 ** Translate a mplayer fourcc to a video4linux2 pixel format.
169 static int fcc_mp2vl(int fcc
)
172 case IMGFMT_RGB8
: return V4L2_PIX_FMT_RGB332
;
173 case IMGFMT_BGR15
: return V4L2_PIX_FMT_RGB555
;
174 case IMGFMT_BGR16
: return V4L2_PIX_FMT_RGB565
;
175 case IMGFMT_RGB24
: return V4L2_PIX_FMT_RGB24
;
176 case IMGFMT_RGB32
: return V4L2_PIX_FMT_RGB32
;
177 case IMGFMT_BGR24
: return V4L2_PIX_FMT_BGR24
;
178 case IMGFMT_BGR32
: return V4L2_PIX_FMT_BGR32
;
179 case IMGFMT_Y800
: return V4L2_PIX_FMT_GREY
;
180 case IMGFMT_IF09
: return V4L2_PIX_FMT_YUV410
;
181 case IMGFMT_I420
: return V4L2_PIX_FMT_YUV420
;
182 case IMGFMT_YUY2
: return V4L2_PIX_FMT_YUYV
;
183 case IMGFMT_YV12
: return V4L2_PIX_FMT_YVU420
;
184 case IMGFMT_UYVY
: return V4L2_PIX_FMT_UYVY
;
190 ** Translate a video4linux2 fourcc aka pixel format to mplayer.
192 static int fcc_vl2mp(int fcc
)
195 case V4L2_PIX_FMT_RGB332
: return IMGFMT_RGB8
;
196 case V4L2_PIX_FMT_RGB555
: return IMGFMT_BGR15
;
197 case V4L2_PIX_FMT_RGB565
: return IMGFMT_BGR16
;
198 case V4L2_PIX_FMT_RGB24
: return IMGFMT_RGB24
;
199 case V4L2_PIX_FMT_RGB32
: return IMGFMT_RGB32
;
200 case V4L2_PIX_FMT_BGR24
: return IMGFMT_BGR24
;
201 case V4L2_PIX_FMT_BGR32
: return IMGFMT_BGR32
;
202 case V4L2_PIX_FMT_GREY
: return IMGFMT_Y800
;
203 case V4L2_PIX_FMT_YUV410
: return IMGFMT_IF09
;
204 case V4L2_PIX_FMT_YUV420
: return IMGFMT_I420
;
205 case V4L2_PIX_FMT_YVU420
: return IMGFMT_YV12
;
206 case V4L2_PIX_FMT_YUYV
: return IMGFMT_YUY2
;
207 case V4L2_PIX_FMT_UYVY
: return IMGFMT_UYVY
;
213 ** Translate a video4linux2 fourcc aka pixel format
214 ** to a human readable string.
216 static const char *pixfmt2name(int pixfmt
)
218 static char unknown
[24];
221 case V4L2_PIX_FMT_RGB332
: return "RGB332";
222 case V4L2_PIX_FMT_RGB555
: return "RGB555";
223 case V4L2_PIX_FMT_RGB565
: return "RGB565";
224 case V4L2_PIX_FMT_RGB555X
: return "RGB555X";
225 case V4L2_PIX_FMT_RGB565X
: return "RGB565X";
226 case V4L2_PIX_FMT_BGR24
: return "BGR24";
227 case V4L2_PIX_FMT_RGB24
: return "RGB24";
228 case V4L2_PIX_FMT_BGR32
: return "BGR32";
229 case V4L2_PIX_FMT_RGB32
: return "RGB32";
230 case V4L2_PIX_FMT_GREY
: return "GREY";
231 case V4L2_PIX_FMT_YVU410
: return "YVU410";
232 case V4L2_PIX_FMT_YVU420
: return "YVU420";
233 case V4L2_PIX_FMT_YUYV
: return "YUYV";
234 case V4L2_PIX_FMT_UYVY
: return "UYVY";
235 /* case V4L2_PIX_FMT_YVU422P: return "YVU422P"; */
236 /* case V4L2_PIX_FMT_YVU411P: return "YVU411P"; */
237 case V4L2_PIX_FMT_YUV422P
: return "YUV422P";
238 case V4L2_PIX_FMT_YUV411P
: return "YUV411P";
239 case V4L2_PIX_FMT_Y41P
: return "Y41P";
240 case V4L2_PIX_FMT_NV12
: return "NV12";
241 case V4L2_PIX_FMT_NV21
: return "NV21";
242 case V4L2_PIX_FMT_YUV410
: return "YUV410";
243 case V4L2_PIX_FMT_YUV420
: return "YUV420";
244 case V4L2_PIX_FMT_YYUV
: return "YYUV";
245 case V4L2_PIX_FMT_HI240
: return "HI240";
246 case V4L2_PIX_FMT_WNVA
: return "WNVA";
248 sprintf(unknown
, "unknown (0x%x)", pixfmt
);
254 ** Gives the depth of a video4linux2 fourcc aka pixel format in bits.
256 static int pixfmt2depth(int pixfmt
)
259 case V4L2_PIX_FMT_RGB332
:
261 case V4L2_PIX_FMT_RGB555
:
262 case V4L2_PIX_FMT_RGB565
:
263 case V4L2_PIX_FMT_RGB555X
:
264 case V4L2_PIX_FMT_RGB565X
:
266 case V4L2_PIX_FMT_BGR24
:
267 case V4L2_PIX_FMT_RGB24
:
269 case V4L2_PIX_FMT_BGR32
:
270 case V4L2_PIX_FMT_RGB32
:
272 case V4L2_PIX_FMT_GREY
:
274 case V4L2_PIX_FMT_YVU410
:
276 case V4L2_PIX_FMT_YVU420
:
278 case V4L2_PIX_FMT_YUYV
:
279 case V4L2_PIX_FMT_UYVY
:
280 case V4L2_PIX_FMT_YUV422P
:
281 case V4L2_PIX_FMT_YUV411P
:
283 case V4L2_PIX_FMT_Y41P
:
284 case V4L2_PIX_FMT_NV12
:
285 case V4L2_PIX_FMT_NV21
:
287 case V4L2_PIX_FMT_YUV410
:
289 case V4L2_PIX_FMT_YUV420
:
291 case V4L2_PIX_FMT_YYUV
:
293 case V4L2_PIX_FMT_HI240
:
300 static int amode2v4l(int amode
)
304 return V4L2_TUNER_MODE_MONO
;
306 return V4L2_TUNER_MODE_STEREO
;
308 return V4L2_TUNER_MODE_LANG1
;
310 return V4L2_TUNER_MODE_LANG2
;
317 // sets and sanitizes audio buffer/block sizes
318 static void setup_audio_buffer_sizes(priv_t
*priv
)
320 int bytes_per_sample
= priv
->audio_in
.bytes_per_sample
;
321 double fps
= (double)priv
->standard
.frameperiod
.denominator
/
322 priv
->standard
.frameperiod
.numerator
;
323 int seconds
= priv
->video_buffer_size_max
/fps
;
325 if (seconds
< 5) seconds
= 5;
326 if (seconds
> 500) seconds
= 500;
328 // make the audio buffer at least as the video buffer capacity (or 5 seconds) long
329 priv
->audio_buffer_size
= 1 + seconds
*priv
->audio_in
.samplerate
330 *priv
->audio_in
.channels
331 *bytes_per_sample
/priv
->audio_in
.blocksize
;
332 if (priv
->audio_buffer_size
< 256) priv
->audio_buffer_size
= 256;
334 // make the skew buffer at least 1 second long
335 priv
->aud_skew_cnt
= 1 + 1*priv
->audio_in
.samplerate
336 *priv
->audio_in
.channels
337 *bytes_per_sample
/priv
->audio_in
.blocksize
;
338 if (priv
->aud_skew_cnt
< 16) priv
->aud_skew_cnt
= 16;
340 mp_msg(MSGT_TV
, MSGL_V
, "Audio capture - buffer %d blocks of %d bytes, skew average from %d meas.\n",
341 priv
->audio_buffer_size
, priv
->audio_in
.blocksize
, priv
->aud_skew_cnt
);
344 static void init_audio(priv_t
*priv
)
346 if (priv
->audio_inited
) return;
348 if (!tv_param_noaudio
) {
349 #if defined(HAVE_ALSA9) || defined(HAVE_ALSA1X)
351 audio_in_init(&priv
->audio_in
, AUDIO_IN_ALSA
);
353 audio_in_init(&priv
->audio_in
, AUDIO_IN_OSS
);
355 audio_in_init(&priv
->audio_in
, AUDIO_IN_OSS
);
358 if (priv
->audio_dev
) {
359 audio_in_set_device(&priv
->audio_in
, priv
->audio_dev
);
362 audio_in_set_samplerate(&priv
->audio_in
, 44100);
363 if (priv
->capability
.capabilities
& V4L2_CAP_TUNER
) {
364 if (priv
->tuner
.audmode
== V4L2_TUNER_MODE_STEREO
) {
365 audio_in_set_channels(&priv
->audio_in
, 2);
367 audio_in_set_channels(&priv
->audio_in
, 1);
370 if (tv_param_forcechan
>= 0) {
371 audio_in_set_channels(&priv
->audio_in
, tv_param_forcechan
);
373 audio_in_set_channels(&priv
->audio_in
, 2);
377 if (audio_in_setup(&priv
->audio_in
) < 0) return;
379 priv
->audio_inited
= 1;
385 ** the number of milliseconds elapsed between time0 and time1
387 static size_t difftv(struct timeval time1
, struct timeval time0
)
389 return (time1
.tv_sec
- time0
.tv_sec
) * 1000 +
390 (time1
.tv_usec
- time0
.tv_usec
) / 1000;
395 ** Get current video capture format.
397 static int getfmt(priv_t
*priv
)
401 priv
->format
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
402 if ((i
= ioctl(priv
->video_fd
, VIDIOC_G_FMT
, &priv
->format
)) < 0) {
403 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl get format failed: %s\n",
404 info
.short_name
, strerror(errno
));
411 ** Get current video capture standard.
413 static int getstd(priv_t
*priv
)
418 if (ioctl(priv
->video_fd
, VIDIOC_G_STD
, &id
) < 0) {
419 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl get standard failed: %s\n",
420 info
.short_name
, strerror(errno
));
424 priv
->standard
.index
= i
++;
425 if (ioctl(priv
->video_fd
, VIDIOC_ENUMSTD
, &priv
->standard
) < 0) {
428 } while (priv
->standard
.id
!= id
);
432 /***********************************************************************\
435 * Interface to mplayer *
438 \***********************************************************************/
440 static int set_mute(priv_t
*priv
, int value
)
442 struct v4l2_control control
;
443 control
.id
= V4L2_CID_AUDIO_MUTE
;
444 control
.value
= value
;
445 if (ioctl(priv
->video_fd
, VIDIOC_S_CTRL
, &control
) < 0) {
446 mp_msg(MSGT_TV
,MSGL_ERR
,"%s: ioctl set mute failed: %s\n",
447 info
.short_name
, strerror(errno
));
454 ** MPlayer uses values from -100 up to 100 for controls.
455 ** Here they are scaled to what the tv card needs and applied.
457 static int set_control(priv_t
*priv
, struct v4l2_control
*control
, int val_signed
) {
458 struct v4l2_queryctrl qctrl
;
460 qctrl
.id
= control
->id
;
461 if (ioctl(priv
->video_fd
, VIDIOC_QUERYCTRL
, &qctrl
) < 0) {
462 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl query control failed: %s\n",
463 info
.short_name
, strerror(errno
));
464 return TVI_CONTROL_FALSE
;
468 if (control
->value
< 0) {
469 control
->value
= qctrl
.default_value
+ control
->value
*
470 (qctrl
.default_value
- qctrl
.minimum
) / 100;
472 control
->value
= qctrl
.default_value
+ control
->value
*
473 (qctrl
.maximum
- qctrl
.default_value
) / 100;
476 if (control
->value
< 50) {
477 control
->value
= qctrl
.default_value
+ (control
->value
-50) *
478 (qctrl
.default_value
- qctrl
.minimum
) / 50;
480 control
->value
= qctrl
.default_value
+ (control
->value
-50) *
481 (qctrl
.maximum
- qctrl
.default_value
) / 50;
486 if (ioctl(priv
->video_fd
, VIDIOC_S_CTRL
, control
) < 0) {
487 mp_msg(MSGT_TV
, MSGL_ERR
,"%s: ioctl set %s %d failed: %s\n",
488 info
.short_name
, qctrl
.name
, control
->value
, strerror(errno
));
489 return TVI_CONTROL_FALSE
;
491 mp_msg(MSGT_TV
, MSGL_V
, "%s: set %s: %d [%d, %d]\n", info
.short_name
,
492 qctrl
.name
, control
->value
, qctrl
.minimum
, qctrl
.maximum
);
494 return TVI_CONTROL_TRUE
;
499 ** Scale the control values back to what mplayer needs.
501 static int get_control(priv_t
*priv
, struct v4l2_control
*control
, int val_signed
) {
502 struct v4l2_queryctrl qctrl
;
504 qctrl
.id
= control
->id
;
505 if (ioctl(priv
->video_fd
, VIDIOC_QUERYCTRL
, &qctrl
) < 0) {
506 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl query control failed: %s\n",
507 info
.short_name
, strerror(errno
));
508 return TVI_CONTROL_FALSE
;
511 if (ioctl(priv
->video_fd
, VIDIOC_G_CTRL
, control
) < 0) {
512 mp_msg(MSGT_TV
, MSGL_ERR
,"%s: ioctl get %s failed: %s\n",
513 info
.short_name
, qctrl
.name
, strerror(errno
));
514 return TVI_CONTROL_FALSE
;
516 mp_msg(MSGT_TV
, MSGL_V
, "%s: get %s: %d [%d, %d]\n", info
.short_name
,
517 qctrl
.name
, control
->value
, qctrl
.minimum
, qctrl
.maximum
);
520 if (control
->value
< qctrl
.default_value
) {
521 control
->value
= (control
->value
- qctrl
.default_value
) * 100 /
522 (qctrl
.default_value
- qctrl
.minimum
);
524 control
->value
= (control
->value
- qctrl
.default_value
) * 100 /
525 (qctrl
.maximum
- qctrl
.default_value
);
528 if (control
->value
< qctrl
.default_value
) {
529 control
->value
= (control
->value
- qctrl
.default_value
) * 50 /
530 (qctrl
.default_value
- qctrl
.minimum
) + 50;
532 control
->value
= (control
->value
- qctrl
.default_value
) * 50 /
533 (qctrl
.maximum
- qctrl
.default_value
) + 50;
537 return TVI_CONTROL_TRUE
;
540 static int control(priv_t
*priv
, int cmd
, void *arg
)
542 struct v4l2_control control
;
543 struct v4l2_frequency frequency
;
546 case TVI_CONTROL_IS_VIDEO
:
547 return priv
->capability
.capabilities
& V4L2_CAP_VIDEO_CAPTURE
?
548 TVI_CONTROL_TRUE
: TVI_CONTROL_FALSE
;
549 case TVI_CONTROL_IS_AUDIO
:
550 if (tv_param_force_audio
) return TVI_CONTROL_TRUE
;
551 case TVI_CONTROL_IS_TUNER
:
552 return priv
->capability
.capabilities
& V4L2_CAP_TUNER
?
553 TVI_CONTROL_TRUE
: TVI_CONTROL_FALSE
;
554 case TVI_CONTROL_IMMEDIATE
:
555 priv
->immediate_mode
= 1;
556 return TVI_CONTROL_TRUE
;
557 case TVI_CONTROL_VID_GET_FPS
:
558 *(float *)arg
= (float)priv
->standard
.frameperiod
.denominator
/
559 priv
->standard
.frameperiod
.numerator
;
560 mp_msg(MSGT_TV
, MSGL_V
, "%s: get fps: %f\n", info
.short_name
,
562 return TVI_CONTROL_TRUE
;
563 case TVI_CONTROL_VID_GET_BITS
:
564 if (getfmt(priv
) < 0) return TVI_CONTROL_FALSE
;
565 *(int *)arg
= pixfmt2depth(priv
->format
.fmt
.pix
.pixelformat
);
566 mp_msg(MSGT_TV
, MSGL_V
, "%s: get depth: %d\n", info
.short_name
,
568 return TVI_CONTROL_TRUE
;
569 case TVI_CONTROL_VID_GET_FORMAT
:
570 if (getfmt(priv
) < 0) return TVI_CONTROL_FALSE
;
571 *(int *)arg
= fcc_vl2mp(priv
->format
.fmt
.pix
.pixelformat
);
572 mp_msg(MSGT_TV
, MSGL_V
, "%s: get format: %s\n", info
.short_name
,
573 pixfmt2name(priv
->format
.fmt
.pix
.pixelformat
));
574 return TVI_CONTROL_TRUE
;
575 case TVI_CONTROL_VID_SET_FORMAT
:
576 if (getfmt(priv
) < 0) return TVI_CONTROL_FALSE
;
577 priv
->format
.fmt
.pix
.pixelformat
= fcc_mp2vl(*(int *)arg
);
578 priv
->format
.fmt
.pix
.field
= V4L2_FIELD_ANY
;
580 priv
->mp_format
= *(int *)arg
;
581 mp_msg(MSGT_TV
, MSGL_V
, "%s: set format: %s\n", info
.short_name
,
582 pixfmt2name(priv
->format
.fmt
.pix
.pixelformat
));
583 if (ioctl(priv
->video_fd
, VIDIOC_S_FMT
, &priv
->format
) < 0) {
584 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl set format failed: %s\n",
585 info
.short_name
, strerror(errno
));
586 return TVI_CONTROL_FALSE
;
588 /* according to the v4l2 specs VIDIOC_S_FMT should not fail, inflexible drivers
589 might even always return the default parameters -> update the format here*/
590 priv
->mp_format
= fcc_vl2mp(priv
->format
.fmt
.pix
.pixelformat
);
591 return TVI_CONTROL_TRUE
;
592 case TVI_CONTROL_VID_GET_WIDTH
:
593 if (getfmt(priv
) < 0) return TVI_CONTROL_FALSE
;
594 *(int *)arg
= priv
->format
.fmt
.pix
.width
;
595 mp_msg(MSGT_TV
, MSGL_V
, "%s: get width: %d\n", info
.short_name
,
597 return TVI_CONTROL_TRUE
;
598 case TVI_CONTROL_VID_CHK_WIDTH
:
599 return TVI_CONTROL_TRUE
;
600 case TVI_CONTROL_VID_SET_WIDTH
:
601 if (getfmt(priv
) < 0) return TVI_CONTROL_FALSE
;
602 priv
->format
.fmt
.pix
.width
= *(int *)arg
;
603 mp_msg(MSGT_TV
, MSGL_V
, "%s: set width: %d\n", info
.short_name
,
605 if (ioctl(priv
->video_fd
, VIDIOC_S_FMT
, &priv
->format
) < 0) {
606 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl set width failed: %s\n",
607 info
.short_name
, strerror(errno
));
608 return TVI_CONTROL_FALSE
;
610 return TVI_CONTROL_TRUE
;
611 case TVI_CONTROL_VID_GET_HEIGHT
:
612 if (getfmt(priv
) < 0) return TVI_CONTROL_FALSE
;
613 *(int *)arg
= priv
->format
.fmt
.pix
.height
;
614 mp_msg(MSGT_TV
, MSGL_V
, "%s: get height: %d\n", info
.short_name
,
616 return TVI_CONTROL_TRUE
;
617 case TVI_CONTROL_VID_CHK_HEIGHT
:
618 return TVI_CONTROL_TRUE
;
619 case TVI_CONTROL_VID_SET_HEIGHT
:
620 if (getfmt(priv
) < 0) return TVI_CONTROL_FALSE
;
621 priv
->format
.fmt
.pix
.height
= *(int *)arg
;
622 priv
->format
.fmt
.pix
.field
= V4L2_FIELD_ANY
;
623 mp_msg(MSGT_TV
, MSGL_V
, "%s: set height: %d\n", info
.short_name
,
625 if (ioctl(priv
->video_fd
, VIDIOC_S_FMT
, &priv
->format
) < 0) {
626 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl set height failed: %s\n",
627 info
.short_name
, strerror(errno
));
628 return TVI_CONTROL_FALSE
;
630 return TVI_CONTROL_TRUE
;
631 case TVI_CONTROL_VID_GET_BRIGHTNESS
:
632 control
.id
= V4L2_CID_BRIGHTNESS
;
633 if (get_control(priv
, &control
, 1) == TVI_CONTROL_TRUE
) {
634 *(int *)arg
= control
.value
;
635 return TVI_CONTROL_TRUE
;
637 return TVI_CONTROL_FALSE
;
638 case TVI_CONTROL_VID_SET_BRIGHTNESS
:
639 control
.id
= V4L2_CID_BRIGHTNESS
;
640 control
.value
= *(int *)arg
;
641 return set_control(priv
, &control
, 1);
642 case TVI_CONTROL_VID_GET_HUE
:
643 control
.id
= V4L2_CID_HUE
;
644 if (get_control(priv
, &control
, 1) == TVI_CONTROL_TRUE
) {
645 *(int *)arg
= control
.value
;
646 return TVI_CONTROL_TRUE
;
648 return TVI_CONTROL_FALSE
;
649 case TVI_CONTROL_VID_SET_HUE
:
650 control
.id
= V4L2_CID_HUE
;
651 control
.value
= *(int *)arg
;
652 return set_control(priv
, &control
, 1);
653 case TVI_CONTROL_VID_GET_SATURATION
:
654 control
.id
= V4L2_CID_SATURATION
;
655 if (get_control(priv
, &control
, 1) == TVI_CONTROL_TRUE
) {
656 *(int *)arg
= control
.value
;
657 return TVI_CONTROL_TRUE
;
659 return TVI_CONTROL_FALSE
;
660 case TVI_CONTROL_VID_SET_SATURATION
:
661 control
.id
= V4L2_CID_SATURATION
;
662 control
.value
= *(int *)arg
;
663 return set_control(priv
, &control
, 1);
664 case TVI_CONTROL_VID_GET_CONTRAST
:
665 control
.id
= V4L2_CID_CONTRAST
;
666 if (get_control(priv
, &control
, 1) == TVI_CONTROL_TRUE
) {
667 *(int *)arg
= control
.value
;
668 return TVI_CONTROL_TRUE
;
670 return TVI_CONTROL_FALSE
;
671 case TVI_CONTROL_VID_SET_CONTRAST
:
672 control
.id
= V4L2_CID_CONTRAST
;
673 control
.value
= *(int *)arg
;
674 return set_control(priv
, &control
, 1);
675 case TVI_CONTROL_TUN_GET_FREQ
:
677 frequency
.type
= V4L2_TUNER_ANALOG_TV
;
678 if (ioctl(priv
->video_fd
, VIDIOC_G_FREQUENCY
, &frequency
) < 0) {
679 mp_msg(MSGT_TV
,MSGL_ERR
,"%s: ioctl get frequency failed: %s\n",
680 info
.short_name
, strerror(errno
));
681 return TVI_CONTROL_FALSE
;
683 *(int *)arg
= frequency
.frequency
;
684 return TVI_CONTROL_TRUE
;
685 case TVI_CONTROL_TUN_SET_FREQ
:
688 usleep(100000); // wait to suppress noise during switching
691 frequency
.type
= V4L2_TUNER_ANALOG_TV
;
692 frequency
.frequency
= *(int *)arg
;
693 if (ioctl(priv
->video_fd
, VIDIOC_S_FREQUENCY
, &frequency
) < 0) {
694 mp_msg(MSGT_TV
,MSGL_ERR
,"%s: ioctl set frequency failed: %s\n",
695 info
.short_name
, strerror(errno
));
696 return TVI_CONTROL_FALSE
;
699 usleep(100000); // wait to suppress noise during switching
702 return TVI_CONTROL_TRUE
;
703 case TVI_CONTROL_TUN_GET_TUNER
:
704 mp_msg(MSGT_TV
, MSGL_V
, "%s: get tuner\n",info
.short_name
);
705 if (ioctl(priv
->video_fd
, VIDIOC_G_TUNER
, &priv
->tuner
) < 0) {
706 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl get tuner failed: %s\n",
707 info
.short_name
, strerror(errno
));
708 return TVI_CONTROL_FALSE
;
710 return TVI_CONTROL_TRUE
;
711 case TVI_CONTROL_TUN_SET_TUNER
:
712 mp_msg(MSGT_TV
, MSGL_V
, "%s: set tuner\n",info
.short_name
);
713 if (ioctl(priv
->video_fd
, VIDIOC_S_TUNER
, &priv
->tuner
) < 0) {
714 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl set tuner failed: %s\n",
715 info
.short_name
, strerror(errno
));
716 return TVI_CONTROL_FALSE
;
718 return TVI_CONTROL_TRUE
;
719 case TVI_CONTROL_TUN_GET_NORM
:
720 *(int *)arg
= priv
->standard
.index
;
721 return TVI_CONTROL_TRUE
;
722 case TVI_CONTROL_TUN_SET_NORM
:
723 priv
->standard
.index
= *(int *)arg
;
724 if (ioctl(priv
->video_fd
, VIDIOC_ENUMSTD
, &priv
->standard
) < 0) {
725 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl enum norm failed: %s\n",
726 info
.short_name
, strerror(errno
));
727 return TVI_CONTROL_FALSE
;
729 mp_msg(MSGT_TV
, MSGL_V
, "%s: set norm: %s\n", info
.short_name
, priv
->standard
.name
);
730 if (ioctl(priv
->video_fd
, VIDIOC_S_STD
, &priv
->standard
.id
) < 0) {
731 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl set norm failed: %s\n",
732 info
.short_name
, strerror(errno
));
733 return TVI_CONTROL_FALSE
;
735 return TVI_CONTROL_TRUE
;
736 case TVI_CONTROL_SPC_GET_NORMID
:
740 struct v4l2_standard standard
;
741 memset(&standard
, 0, sizeof(standard
));
743 if (-1 == ioctl(priv
->video_fd
, VIDIOC_ENUMSTD
, &standard
))
744 return TVI_CONTROL_FALSE
;
745 if (!strcasecmp(standard
.name
, (char *)arg
)) {
747 return TVI_CONTROL_TRUE
;
750 return TVI_CONTROL_FALSE
;
752 case TVI_CONTROL_SPC_GET_INPUT
:
753 if (ioctl(priv
->video_fd
, VIDIOC_G_INPUT
, (int *)arg
) < 0) {
754 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl get input failed: %s\n",
755 info
.short_name
, strerror(errno
));
756 return TVI_CONTROL_FALSE
;
758 return TVI_CONTROL_TRUE
;
759 case TVI_CONTROL_SPC_SET_INPUT
:
760 mp_msg(MSGT_TV
, MSGL_V
, "%s: set input: %d\n", info
.short_name
, *(int *)arg
);
761 priv
->input
.index
= *(int *)arg
;
762 if (ioctl(priv
->video_fd
, VIDIOC_ENUMINPUT
, &priv
->input
) < 0) {
763 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl enum input failed: %s\n",
764 info
.short_name
, strerror(errno
));
765 return TVI_CONTROL_FALSE
;
767 if (ioctl(priv
->video_fd
, VIDIOC_S_INPUT
, (int *)arg
) < 0) {
768 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl set input failed: %s\n",
769 info
.short_name
, strerror(errno
));
770 return TVI_CONTROL_FALSE
;
772 return TVI_CONTROL_TRUE
;
773 case TVI_CONTROL_AUD_GET_FORMAT
:
775 if (!priv
->audio_inited
) return TVI_CONTROL_FALSE
;
776 *(int *)arg
= AF_FORMAT_S16_LE
;
777 mp_msg(MSGT_TV
, MSGL_V
, "%s: get audio format: %d\n",
778 info
.short_name
, *(int *)arg
);
779 return TVI_CONTROL_TRUE
;
780 case TVI_CONTROL_AUD_GET_SAMPLERATE
:
782 if (!priv
->audio_inited
) return TVI_CONTROL_FALSE
;
783 *(int *)arg
= priv
->audio_in
.samplerate
;
784 mp_msg(MSGT_TV
, MSGL_V
, "%s: get audio samplerate: %d\n",
785 info
.short_name
, *(int *)arg
);
786 return TVI_CONTROL_TRUE
;
787 case TVI_CONTROL_AUD_GET_SAMPLESIZE
:
789 if (!priv
->audio_inited
) return TVI_CONTROL_FALSE
;
790 *(int *)arg
= priv
->audio_in
.bytes_per_sample
;
791 mp_msg(MSGT_TV
, MSGL_V
, "%s: get audio samplesize: %d\n",
792 info
.short_name
, *(int *)arg
);
793 return TVI_CONTROL_TRUE
;
794 case TVI_CONTROL_AUD_GET_CHANNELS
:
796 if (!priv
->audio_inited
) return TVI_CONTROL_FALSE
;
797 *(int *)arg
= priv
->audio_in
.channels
;
798 mp_msg(MSGT_TV
, MSGL_V
, "%s: get audio channels: %d\n",
799 info
.short_name
, *(int *)arg
);
800 return TVI_CONTROL_TRUE
;
801 case TVI_CONTROL_AUD_SET_SAMPLERATE
:
803 mp_msg(MSGT_TV
, MSGL_V
, "%s: set audio samplerate: %d\n",
804 info
.short_name
, *(int *)arg
);
805 if (audio_in_set_samplerate(&priv
->audio_in
, *(int*)arg
) < 0) return TVI_CONTROL_FALSE
;
806 // setup_audio_buffer_sizes(priv);
807 return TVI_CONTROL_TRUE
;
809 mp_msg(MSGT_TV
, MSGL_V
, "%s: unknown control: %d\n", info
.short_name
, cmd
);
810 return(TVI_CONTROL_UNKNOWN
);
814 #define PRIV ((priv_t *) (tvi_handle->priv))
816 /* handler creator - entry point ! */
817 tvi_handle_t
*tvi_init_v4l2(char *video_dev
, char *audio_dev
)
819 tvi_handle_t
*tvi_handle
;
821 /* new_handle initializes priv with memset 0 */
822 tvi_handle
= new_handle();
828 PRIV
->video_dev
= strdup(video_dev
? video_dev
: "/dev/video0");
829 if (!PRIV
->video_dev
) {
830 free_handle(tvi_handle
);
835 PRIV
->audio_dev
= strdup(audio_dev
);
836 if (!PRIV
->audio_dev
) {
837 free(PRIV
->video_dev
);
838 free_handle(tvi_handle
);
849 static int uninit(priv_t
*priv
)
851 int i
, frames
, dropped
= 0;
854 if(priv
->video_grabber_thread
)
855 pthread_join(priv
->video_grabber_thread
, NULL
);
856 pthread_mutex_destroy(&priv
->video_buffer_mutex
);
858 if (priv
->streamon
) {
859 struct v4l2_buffer buf
;
861 /* get performance */
862 frames
= 1 + (priv
->curr_frame
- priv
->first_frame
+
863 priv
->standard
.frameperiod
.numerator
* 500000 /
864 priv
->standard
.frameperiod
.denominator
) *
865 priv
->standard
.frameperiod
.denominator
/
866 priv
->standard
.frameperiod
.numerator
/ 1000000;
867 dropped
= frames
- priv
->frames
;
869 /* turn off streaming */
870 if (ioctl(priv
->video_fd
, VIDIOC_STREAMOFF
, &(priv
->map
[0].buf
.type
)) < 0) {
871 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl streamoff failed: %s\n",
872 info
.short_name
, strerror(errno
));
876 /* unqueue all remaining buffers */
877 memset(&buf
,0,sizeof(buf
));
878 buf
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
879 buf
.memory
= V4L2_MEMORY_MMAP
;
880 while (!ioctl(priv
->video_fd
, VIDIOC_DQBUF
, &buf
));
883 /* unmap all buffers */
884 for (i
= 0; i
< priv
->mapcount
; i
++) {
885 if (munmap(priv
->map
[i
].addr
, priv
->map
[i
].len
) < 0) {
886 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: munmap capture buffer failed: %s\n",
887 info
.short_name
, strerror(errno
));
891 /* stop audio thread */
892 if (!tv_param_noaudio
&& priv
->audio_grabber_thread
) {
893 pthread_join(priv
->audio_grabber_thread
, NULL
);
894 pthread_mutex_destroy(&priv
->skew_mutex
);
895 pthread_mutex_destroy(&priv
->audio_mutex
);
900 /* free memory and close device */
901 free(priv
->map
); priv
->map
= NULL
;
903 if(priv
->video_fd
!=-1)close(priv
->video_fd
); priv
->video_fd
= -1;
904 free(priv
->video_dev
); priv
->video_dev
= NULL
;
906 if (priv
->video_ringbuffer
) {
908 for (i
= 0; i
< priv
->video_buffer_size_current
; i
++) {
909 free(priv
->video_ringbuffer
[i
]);
911 free(priv
->video_ringbuffer
);
913 if (priv
->video_timebuffer
)
914 free(priv
->video_timebuffer
);
915 if (!tv_param_noaudio
) {
916 if (priv
->audio_ringbuffer
)
917 free(priv
->audio_ringbuffer
);
918 if (priv
->audio_skew_buffer
)
919 free(priv
->audio_skew_buffer
);
920 if (priv
->audio_skew_delta_buffer
)
921 free(priv
->audio_skew_delta_buffer
);
924 /* show some nice statistics ;-) */
925 mp_msg(MSGT_TV
, MSGL_INFO
,
926 "%s: %d frames successfully processed, %d frames dropped.\n",
927 info
.short_name
, priv
->frames
, dropped
);
928 mp_msg(MSGT_TV
, MSGL_V
, "%s: up to %u video frames buffered.\n",
929 info
.short_name
, priv
->video_buffer_size_current
);
935 static int init(priv_t
*priv
)
939 priv
->audio_ringbuffer
= NULL
;
940 priv
->audio_skew_buffer
= NULL
;
941 priv
->audio_skew_delta_buffer
= NULL
;
943 priv
->audio_inited
= 0;
945 /* Open the video device. */
946 priv
->video_fd
= open(priv
->video_dev
, O_RDWR
);
947 if (priv
->video_fd
< 0) {
948 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: unable to open '%s': %s\n",
949 info
.short_name
, priv
->video_dev
, strerror(errno
));
953 mp_msg(MSGT_TV
, MSGL_DBG2
, "%s: video fd: %s: %d\n",
954 info
.short_name
, priv
->video_dev
, priv
->video_fd
);
957 ** Query the video capabilities and current settings
958 ** for further control calls.
960 if (ioctl(priv
->video_fd
, VIDIOC_QUERYCAP
, &priv
->capability
) < 0) {
961 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl query capabilities failed: %s\n",
962 info
.short_name
, strerror(errno
));
967 if (!(priv
->capability
.capabilities
& V4L2_CAP_VIDEO_CAPTURE
))
969 mp_msg(MSGT_TV
, MSGL_ERR
, "Device %s is not a video capture device.\n",
974 if (getfmt(priv
) < 0) {
980 ** if this device has got a tuner query it's settings
981 ** otherwise set some nice defaults
983 if (priv
->capability
.capabilities
& V4L2_CAP_TUNER
) {
984 if (ioctl(priv
->video_fd
, VIDIOC_G_TUNER
, &priv
->tuner
) < 0) {
985 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl get tuner failed: %s\n",
986 info
.short_name
, strerror(errno
));
991 mp_msg(MSGT_TV
, MSGL_INFO
, "Selected device: %s\n", priv
->capability
.card
);
992 if (priv
->capability
.capabilities
& V4L2_CAP_TUNER
) {
993 mp_msg(MSGT_TV
, MSGL_INFO
, " Tuner cap:%s%s%s\n",
994 (priv
->tuner
.capability
& V4L2_TUNER_CAP_STEREO
) ? " STEREO" : "",
995 (priv
->tuner
.capability
& V4L2_TUNER_CAP_LANG1
) ? " LANG1" : "",
996 (priv
->tuner
.capability
& V4L2_TUNER_CAP_LANG2
) ? " LANG2" : "");
997 mp_msg(MSGT_TV
, MSGL_INFO
, " Tuner rxs:%s%s%s%s\n",
998 (priv
->tuner
.rxsubchans
& V4L2_TUNER_SUB_MONO
) ? " MONO" : "",
999 (priv
->tuner
.rxsubchans
& V4L2_TUNER_SUB_STEREO
) ? " STEREO" : "",
1000 (priv
->tuner
.rxsubchans
& V4L2_TUNER_SUB_LANG1
) ? " LANG1" : "",
1001 (priv
->tuner
.rxsubchans
& V4L2_TUNER_SUB_LANG2
) ? " LANG2" : "");
1003 mp_msg(MSGT_TV
, MSGL_INFO
, " Capabilites:%s%s%s%s%s%s%s%s%s%s%s\n",
1004 priv
->capability
.capabilities
& V4L2_CAP_VIDEO_CAPTURE
?
1005 " video capture": "",
1006 priv
->capability
.capabilities
& V4L2_CAP_VIDEO_OUTPUT
?
1007 " video output": "",
1008 priv
->capability
.capabilities
& V4L2_CAP_VIDEO_OVERLAY
?
1009 " video overlay": "",
1010 priv
->capability
.capabilities
& V4L2_CAP_VBI_CAPTURE
?
1011 " VBI capture device": "",
1012 priv
->capability
.capabilities
& V4L2_CAP_VBI_OUTPUT
?
1014 priv
->capability
.capabilities
& V4L2_CAP_RDS_CAPTURE
?
1015 " RDS data capture": "",
1016 priv
->capability
.capabilities
& V4L2_CAP_TUNER
?
1018 priv
->capability
.capabilities
& V4L2_CAP_AUDIO
?
1020 priv
->capability
.capabilities
& V4L2_CAP_READWRITE
?
1022 priv
->capability
.capabilities
& V4L2_CAP_ASYNCIO
?
1024 priv
->capability
.capabilities
& V4L2_CAP_STREAMING
?
1026 mp_msg(MSGT_TV
, MSGL_INFO
, " supported norms:");
1028 struct v4l2_standard standard
;
1029 memset(&standard
, 0, sizeof(standard
));
1031 if (-1 == ioctl(priv
->video_fd
, VIDIOC_ENUMSTD
, &standard
))
1033 mp_msg(MSGT_TV
, MSGL_INFO
, " %d = %s;", i
, standard
.name
);
1035 mp_msg(MSGT_TV
, MSGL_INFO
, "\n inputs:");
1036 for (i
= 0; 1; i
++) {
1037 struct v4l2_input input
;
1040 if (ioctl(priv
->video_fd
, VIDIOC_ENUMINPUT
, &input
) < 0) {
1043 mp_msg(MSGT_TV
, MSGL_INFO
, " %d = %s;", i
, input
.name
);
1045 if (ioctl(priv
->video_fd
, VIDIOC_G_INPUT
, &i
) < 0) {
1046 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl get input failed: %s\n",
1047 info
.short_name
, strerror(errno
));
1049 mp_msg(MSGT_TV
, MSGL_INFO
, "\n Current input: %d\n", i
);
1050 for (i
= 0; ; i
++) {
1051 struct v4l2_fmtdesc fmtdesc
;
1054 fmtdesc
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1055 if (ioctl(priv
->video_fd
, VIDIOC_ENUM_FMT
, &fmtdesc
) < 0) {
1058 mp_msg(MSGT_TV
, MSGL_V
, " Format %-6s (%2d bits, %s): %s\n",
1059 pixfmt2name(fmtdesc
.pixelformat
), pixfmt2depth(fmtdesc
.pixelformat
),
1060 fmtdesc
.description
, vo_format_name(fcc_vl2mp(fmtdesc
.pixelformat
)));
1062 mp_msg(MSGT_TV
, MSGL_INFO
, " Current format: %s\n",
1063 pixfmt2name(priv
->format
.fmt
.pix
.pixelformat
));
1065 /* set some nice defaults */
1066 if (getfmt(priv
) < 0) return 0;
1067 priv
->format
.fmt
.pix
.width
= 640;
1068 priv
->format
.fmt
.pix
.height
= 480;
1069 if (ioctl(priv
->video_fd
, VIDIOC_S_FMT
, &priv
->format
) < 0) {
1070 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl set format failed: %s\n",
1071 info
.short_name
, strerror(errno
));
1076 // if (!(priv->capability.capabilities & V4L2_CAP_AUDIO) && !tv_param_force_audio) tv_param_noaudio = 1;
1078 if (priv
->capability
.capabilities
& V4L2_CAP_TUNER
) {
1079 struct v4l2_control control
;
1080 if (tv_param_amode
>= 0) {
1081 mp_msg(MSGT_TV
, MSGL_V
, "%s: setting audio mode\n", info
.short_name
);
1082 priv
->tuner
.audmode
= amode2v4l(tv_param_amode
);
1083 if (ioctl(priv
->video_fd
, VIDIOC_S_TUNER
, &priv
->tuner
) < 0) {
1084 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl set tuner failed: %s\n",
1085 info
.short_name
, strerror(errno
));
1086 return TVI_CONTROL_FALSE
;
1089 mp_msg(MSGT_TV
, MSGL_INFO
, "%s: current audio mode is :%s%s%s%s\n", info
.short_name
,
1090 (priv
->tuner
.audmode
== V4L2_TUNER_MODE_MONO
) ? " MONO" : "",
1091 (priv
->tuner
.audmode
== V4L2_TUNER_MODE_STEREO
) ? " STEREO" : "",
1092 (priv
->tuner
.audmode
== V4L2_TUNER_MODE_LANG1
) ? " LANG1" : "",
1093 (priv
->tuner
.audmode
== V4L2_TUNER_MODE_LANG2
) ? " LANG2" : "");
1095 if (tv_param_volume
>= 0) {
1096 control
.id
= V4L2_CID_AUDIO_VOLUME
;
1097 control
.value
= tv_param_volume
;
1098 set_control(priv
, &control
, 0);
1100 if (tv_param_bass
>= 0) {
1101 control
.id
= V4L2_CID_AUDIO_BASS
;
1102 control
.value
= tv_param_bass
;
1103 set_control(priv
, &control
, 0);
1105 if (tv_param_treble
>= 0) {
1106 control
.id
= V4L2_CID_AUDIO_TREBLE
;
1107 control
.value
= tv_param_treble
;
1108 set_control(priv
, &control
, 0);
1110 if (tv_param_balance
>= 0) {
1111 control
.id
= V4L2_CID_AUDIO_BALANCE
;
1112 control
.value
= tv_param_balance
;
1113 set_control(priv
, &control
, 0);
1120 static int get_capture_buffer_size(priv_t
*priv
)
1123 int w
= priv
->format
.fmt
.pix
.width
;
1124 int h
= priv
->format
.fmt
.pix
.height
;
1125 int d
= pixfmt2depth(priv
->format
.fmt
.pix
.pixelformat
);
1126 int bytesperline
= w
*d
/8;
1128 if (tv_param_buffer_size
>= 0) {
1129 bufsize
= tv_param_buffer_size
*1024*1024;
1131 #ifdef HAVE_SYS_SYSINFO_H
1135 if (si
.totalram
<2*1024*1024) {
1136 bufsize
= 1024*1024;
1138 bufsize
= si
.totalram
/2;
1141 bufsize
= 16*1024*1024;
1145 cnt
= bufsize
/(h
*bytesperline
);
1146 if (cnt
< 2) cnt
= 2;
1151 /* that's the real start, we'got the format parameters (checked with control) */
1152 static int start(priv_t
*priv
)
1154 struct v4l2_requestbuffers request
;
1157 /* setup audio parameters */
1160 if (!tv_param_noaudio
&& !priv
->audio_inited
) return 0;
1162 /* we need this to size the audio buffer properly */
1163 if (priv
->immediate_mode
) {
1164 priv
->video_buffer_size_max
= 2;
1166 priv
->video_buffer_size_max
= get_capture_buffer_size(priv
);
1169 if (!tv_param_noaudio
) {
1170 setup_audio_buffer_sizes(priv
);
1171 priv
->audio_skew_buffer
= calloc(priv
->aud_skew_cnt
, sizeof(long long));
1172 if (!priv
->audio_skew_buffer
) {
1173 mp_msg(MSGT_TV
, MSGL_ERR
, "cannot allocate skew buffer: %s\n", strerror(errno
));
1176 priv
->audio_skew_delta_buffer
= calloc(priv
->aud_skew_cnt
, sizeof(long long));
1177 if (!priv
->audio_skew_delta_buffer
) {
1178 mp_msg(MSGT_TV
, MSGL_ERR
, "cannot allocate skew buffer: %s\n", strerror(errno
));
1182 priv
->audio_ringbuffer
= calloc(priv
->audio_in
.blocksize
, priv
->audio_buffer_size
);
1183 if (!priv
->audio_ringbuffer
) {
1184 mp_msg(MSGT_TV
, MSGL_ERR
, "cannot allocate audio buffer: %s\n", strerror(errno
));
1188 priv
->audio_secs_per_block
= (double)priv
->audio_in
.blocksize
/(priv
->audio_in
.samplerate
1189 *priv
->audio_in
.channels
1190 *priv
->audio_in
.bytes_per_sample
);
1191 priv
->audio_usecs_per_block
= 1e6
*priv
->audio_secs_per_block
;
1192 priv
->audio_head
= 0;
1193 priv
->audio_tail
= 0;
1194 priv
->audio_cnt
= 0;
1195 priv
->audio_drop
= 0;
1196 priv
->audio_skew
= 0;
1197 priv
->audio_skew_total
= 0;
1198 priv
->audio_skew_delta_total
= 0;
1199 priv
->audio_recv_blocks_total
= 0;
1200 priv
->audio_sent_blocks_total
= 0;
1201 priv
->audio_null_blocks_inserted
= 0;
1202 priv
->audio_insert_null_samples
= 0;
1203 priv
->dropped_frames_timeshift
= 0;
1204 priv
->dropped_frames_compensated
= 0;
1206 pthread_mutex_init(&priv
->skew_mutex
, NULL
);
1207 pthread_mutex_init(&priv
->audio_mutex
, NULL
);
1210 /* setup video parameters */
1211 if (!tv_param_noaudio
) {
1212 if (priv
->video_buffer_size_max
< (3*priv
->standard
.frameperiod
.denominator
) /
1213 priv
->standard
.frameperiod
.numerator
1214 *priv
->audio_secs_per_block
) {
1215 mp_msg(MSGT_TV
, MSGL_ERR
, "Video buffer shorter than 3 times audio frame duration.\n"
1216 "You will probably experience heavy framedrops.\n");
1221 int bytesperline
= priv
->format
.fmt
.pix
.width
*pixfmt2depth(priv
->format
.fmt
.pix
.pixelformat
)/8;
1223 mp_msg(MSGT_TV
, MSGL_V
, "Using a ring buffer for maximum %d frames, %d MB total size.\n",
1224 priv
->video_buffer_size_max
,
1225 priv
->video_buffer_size_max
*priv
->format
.fmt
.pix
.height
*bytesperline
/(1024*1024));
1228 priv
->video_ringbuffer
= calloc(priv
->video_buffer_size_max
, sizeof(unsigned char*));
1229 if (!priv
->video_ringbuffer
) {
1230 mp_msg(MSGT_TV
, MSGL_ERR
, "cannot allocate video buffer: %s\n", strerror(errno
));
1233 for (i
= 0; i
< priv
->video_buffer_size_max
; i
++)
1234 priv
->video_ringbuffer
[i
] = NULL
;
1235 priv
->video_timebuffer
= calloc(priv
->video_buffer_size_max
, sizeof(long long));
1236 if (!priv
->video_timebuffer
) {
1237 mp_msg(MSGT_TV
, MSGL_ERR
, "cannot allocate time buffer: %s\n", strerror(errno
));
1241 pthread_mutex_init(&priv
->video_buffer_mutex
, NULL
);
1243 priv
->video_head
= 0;
1244 priv
->video_tail
= 0;
1245 priv
->video_cnt
= 0;
1247 /* request buffers */
1248 if (priv
->immediate_mode
) {
1251 request
.count
= BUFFER_COUNT
;
1254 request
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1255 request
.memory
= V4L2_MEMORY_MMAP
;
1256 if (ioctl(priv
->video_fd
, VIDIOC_REQBUFS
, &request
) < 0) {
1257 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl request buffers failed: %s\n",
1258 info
.short_name
, strerror(errno
));
1263 if (!(priv
->map
= calloc(request
.count
, sizeof(struct map
)))) {
1264 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: malloc capture buffers failed: %s\n",
1265 info
.short_name
, strerror(errno
));
1269 /* map and queue buffers */
1270 for (i
= 0; i
< request
.count
; i
++) {
1271 memset(&priv
->map
[i
].buf
,0,sizeof(priv
->map
[i
].buf
));
1272 priv
->map
[i
].buf
.index
= i
;
1273 priv
->map
[i
].buf
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1274 priv
->map
[i
].buf
.memory
= V4L2_MEMORY_MMAP
;
1275 if (ioctl(priv
->video_fd
, VIDIOC_QUERYBUF
, &(priv
->map
[i
].buf
)) < 0) {
1276 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl query buffer failed: %s\n",
1277 info
.short_name
, strerror(errno
));
1282 priv
->map
[i
].addr
= mmap (0, priv
->map
[i
].buf
.length
, PROT_READ
|
1283 PROT_WRITE
, MAP_SHARED
, priv
->video_fd
, priv
->map
[i
].buf
.m
.offset
);
1284 if (priv
->map
[i
].addr
== MAP_FAILED
) {
1285 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: mmap capture buffer failed: %s\n",
1286 info
.short_name
, strerror(errno
));
1287 priv
->map
[i
].len
= 0;
1290 priv
->map
[i
].len
= priv
->map
[i
].buf
.length
;
1291 /* count up to make sure this is correct everytime */
1294 if (ioctl(priv
->video_fd
, VIDIOC_QBUF
, &(priv
->map
[i
].buf
)) < 0) {
1295 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl queue buffer failed: %s\n",
1296 info
.short_name
, strerror(errno
));
1301 /* start audio thread */
1303 priv
->audio_skew_measure_time
= 0;
1304 priv
->first_frame
= 0;
1305 priv
->audio_skew
= 0;
1314 #ifdef HAVE_TV_BSDBT848
1315 static double grabimmediate_video_frame(priv_t
*priv
, char *buffer
, int len
)
1317 memset(buffer
, 0xCC, len
);
1320 #endif /* HAVE_TV_BSDBT848 */
1322 // copies a video frame
1323 static inline void copy_frame(priv_t
*priv
, unsigned char *dest
, unsigned char *source
)
1325 int w
= priv
->format
.fmt
.pix
.width
;
1326 int h
= priv
->format
.fmt
.pix
.height
;
1327 int d
= pixfmt2depth(priv
->format
.fmt
.pix
.pixelformat
);
1328 int bytesperline
= w
*d
/8;
1330 memcpy(dest
, source
, bytesperline
* h
);
1333 // maximum skew change, in frames
1334 #define MAX_SKEW_DELTA 0.6
1335 static void *video_grabber(void *data
)
1337 priv_t
*priv
= (priv_t
*)data
;
1338 long long skew
, prev_skew
, xskew
, interval
, prev_interval
, delta
;
1340 int framesize
= priv
->format
.fmt
.pix
.height
*priv
->format
.fmt
.pix
.width
*
1341 pixfmt2depth(priv
->format
.fmt
.pix
.pixelformat
)/8;
1343 struct timeval timeout
;
1344 struct v4l2_buffer buf
;
1352 mp_msg(MSGT_TV
, MSGL_V
, "%s: going to capture\n", info
.short_name
);
1353 if (ioctl(priv
->video_fd
, VIDIOC_STREAMON
, &(priv
->format
.type
)) < 0) {
1354 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl streamon failed: %s\n",
1355 info
.short_name
, strerror(errno
));
1360 if (!tv_param_noaudio
) {
1361 pthread_create(&priv
->audio_grabber_thread
, NULL
, audio_grabber
, priv
);
1364 for (priv
->frames
= 0; !priv
->shutdown
;)
1368 if (priv
->immediate_mode
) {
1369 while (priv
->video_cnt
== priv
->video_buffer_size_max
) {
1371 if (priv
->shutdown
) {
1378 FD_SET (priv
->video_fd
, &rdset
);
1381 timeout
.tv_usec
= 0;
1383 i
= select(priv
->video_fd
+ 1, &rdset
, NULL
, NULL
, &timeout
);
1385 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: select failed: %s\n",
1386 info
.short_name
, strerror(errno
));
1390 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: select timeout\n", info
.short_name
);
1393 else if (!FD_ISSET(priv
->video_fd
, &rdset
)) {
1397 memset(&buf
,0,sizeof(buf
));
1398 buf
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1399 buf
.memory
= V4L2_MEMORY_MMAP
;
1400 ret
= ioctl(priv
->video_fd
, VIDIOC_DQBUF
, &buf
);
1404 if there's no signal, the buffer might me dequeued
1405 so we query all the buffers to see which one we should
1408 observed with saa7134 0.2.8
1409 don't know if is it a bug or (mis)feature
1411 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl dequeue buffer failed: %s, idx = %d\n",
1412 info
.short_name
, strerror(errno
), buf
.index
);
1413 for (i
= 0; i
< priv
->mapcount
; i
++) {
1414 memset(&buf
,0,sizeof(buf
));
1415 buf
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1416 buf
.memory
= V4L2_MEMORY_MMAP
;
1418 ret
= ioctl(priv
->video_fd
, VIDIOC_QUERYBUF
, &buf
);
1420 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl query buffer failed: %s, idx = %d\n",
1421 info
.short_name
, strerror(errno
), buf
.index
);
1424 if ((buf
.flags
& (V4L2_BUF_FLAG_QUEUED
| V4L2_BUF_FLAG_MAPPED
| V4L2_BUF_FLAG_DONE
)) == V4L2_BUF_FLAG_MAPPED
) {
1425 if (ioctl(priv
->video_fd
, VIDIOC_QBUF
, &(priv
->map
[i
].buf
)) < 0) {
1426 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl queue buffer failed: %s\n",
1427 info
.short_name
, strerror(errno
));
1435 /* store the timestamp of the very first frame as reference */
1436 if (!priv
->frames
++) {
1437 if (!tv_param_noaudio
) pthread_mutex_lock(&priv
->skew_mutex
);
1438 priv
->first_frame
= (long long)1e6
*buf
.timestamp
.tv_sec
+ buf
.timestamp
.tv_usec
;
1439 if (!tv_param_noaudio
) pthread_mutex_unlock(&priv
->skew_mutex
);
1441 priv
->curr_frame
= (long long)buf
.timestamp
.tv_sec
*1e6
+buf
.timestamp
.tv_usec
;
1442 // fprintf(stderr, "idx = %d, ts = %lf\n", buf.index, (double)(priv->curr_frame) / 1e6);
1444 interval
= priv
->curr_frame
- priv
->first_frame
;
1445 delta
= interval
- prev_interval
;
1447 if (!priv
->immediate_mode
) {
1448 // interpolate the skew in time
1449 if (!tv_param_noaudio
) pthread_mutex_lock(&priv
->skew_mutex
);
1450 xskew
= priv
->audio_skew
+ (interval
- priv
->audio_skew_measure_time
)*priv
->audio_skew_factor
;
1451 if (!tv_param_noaudio
) pthread_mutex_unlock(&priv
->skew_mutex
);
1452 // correct extreme skew changes to avoid (especially) moving backwards in time
1453 if (xskew
- prev_skew
> delta
*MAX_SKEW_DELTA
) {
1454 skew
= prev_skew
+ delta
*MAX_SKEW_DELTA
;
1455 } else if (xskew
- prev_skew
< -delta
*MAX_SKEW_DELTA
) {
1456 skew
= prev_skew
- delta
*MAX_SKEW_DELTA
;
1462 mp_msg(MSGT_TV
, MSGL_DBG3
, "\nfps = %lf, interval = %lf, a_skew = %f, corr_skew = %f\n",
1463 delta
? (double)1e6
/delta
: -1,
1464 (double)1e-6*interval
, (double)1e-6*xskew
, (double)1e-6*skew
);
1465 mp_msg(MSGT_TV
, MSGL_DBG3
, "vcnt = %d, acnt = %d\n", priv
->video_cnt
, priv
->audio_cnt
);
1468 prev_interval
= interval
;
1470 /* allocate a new buffer, if needed */
1471 pthread_mutex_lock(&priv
->video_buffer_mutex
);
1472 if (priv
->video_buffer_size_current
< priv
->video_buffer_size_max
) {
1473 if (priv
->video_cnt
== priv
->video_buffer_size_current
) {
1474 unsigned char *newbuf
= malloc(framesize
);
1476 memmove(priv
->video_ringbuffer
+priv
->video_tail
+1, priv
->video_ringbuffer
+priv
->video_tail
,
1477 (priv
->video_buffer_size_current
-priv
->video_tail
)*sizeof(unsigned char *));
1478 memmove(priv
->video_timebuffer
+priv
->video_tail
+1, priv
->video_timebuffer
+priv
->video_tail
,
1479 (priv
->video_buffer_size_current
-priv
->video_tail
)*sizeof(long long));
1480 priv
->video_ringbuffer
[priv
->video_tail
] = newbuf
;
1481 if ((priv
->video_head
>= priv
->video_tail
) && (priv
->video_cnt
> 0)) priv
->video_head
++;
1482 priv
->video_buffer_size_current
++;
1486 pthread_mutex_unlock(&priv
->video_buffer_mutex
);
1488 if (priv
->video_cnt
== priv
->video_buffer_size_current
) {
1489 if (!priv
->immediate_mode
) {
1490 mp_msg(MSGT_TV
, MSGL_ERR
, "\nvideo buffer full - dropping frame\n");
1491 if (priv
->audio_insert_null_samples
) {
1492 pthread_mutex_lock(&priv
->audio_mutex
);
1493 priv
->dropped_frames_timeshift
+= delta
;
1494 pthread_mutex_unlock(&priv
->audio_mutex
);
1498 if (priv
->immediate_mode
) {
1499 priv
->video_timebuffer
[priv
->video_tail
] = 0;
1501 // compensate for audio skew
1502 // negative skew => there are more audio samples, increase interval
1503 // positive skew => less samples, shorten the interval
1504 priv
->video_timebuffer
[priv
->video_tail
] = interval
- skew
;
1505 if (priv
->audio_insert_null_samples
&& priv
->video_timebuffer
[priv
->video_tail
] > 0) {
1506 pthread_mutex_lock(&priv
->audio_mutex
);
1507 priv
->video_timebuffer
[priv
->video_tail
] +=
1508 (priv
->audio_null_blocks_inserted
1509 - priv
->dropped_frames_timeshift
/priv
->audio_usecs_per_block
)
1510 *priv
->audio_usecs_per_block
;
1511 pthread_mutex_unlock(&priv
->audio_mutex
);
1515 copy_frame(priv
, priv
->video_ringbuffer
[priv
->video_tail
], priv
->map
[buf
.index
].addr
);
1516 priv
->video_tail
= (priv
->video_tail
+1)%priv
->video_buffer_size_current
;
1519 if (ioctl(priv
->video_fd
, VIDIOC_QBUF
, &buf
) < 0) {
1520 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl queue buffer failed: %s\n",
1521 info
.short_name
, strerror(errno
));
1529 static double grab_video_frame(priv_t
*priv
, char *buffer
, int len
)
1535 pthread_create(&priv
->video_grabber_thread
, NULL
, video_grabber
, priv
);
1539 while (priv
->video_cnt
== 0) {
1541 if (loop_cnt
++ > MAX_LOOP
) return 0;
1544 pthread_mutex_lock(&priv
->video_buffer_mutex
);
1545 interval
= (double)priv
->video_timebuffer
[priv
->video_head
]*1e-6;
1546 memcpy(buffer
, priv
->video_ringbuffer
[priv
->video_head
], len
);
1548 priv
->video_head
= (priv
->video_head
+1)%priv
->video_buffer_size_current
;
1549 pthread_mutex_unlock(&priv
->video_buffer_mutex
);
1554 static int get_video_framesize(priv_t
*priv
)
1556 return priv
->format
.fmt
.pix
.sizeimage
;
1559 //#define DOUBLESPEED
1561 // for testing purposes only
1562 static void read_doublespeed(priv_t
*priv
)
1564 char *bufx
= calloc(priv
->audio_in
.blocksize
, 2);
1569 audio_in_read_chunk(&priv
->audio_in
, bufx
);
1570 audio_in_read_chunk(&priv
->audio_in
, bufx
+priv
->audio_in
.blocksize
);
1573 d
= priv
->audio_ringbuffer
+priv
->audio_tail
*priv
->audio_in
.blocksize
;
1574 for (i
= 0; i
< priv
->audio_in
.blocksize
/2; i
++) {
1582 static void *audio_grabber(void *data
)
1584 priv_t
*priv
= (priv_t
*)data
;
1586 int i
, audio_skew_ptr
= 0;
1587 long long current_time
, prev_skew
= 0, prev_skew_uncorr
= 0;
1588 long long start_time_avg
;
1590 gettimeofday(&tv
, NULL
);
1591 start_time_avg
= priv
->audio_start_time
= (long long)1e6
*tv
.tv_sec
+ tv
.tv_usec
;
1592 audio_in_start_capture(&priv
->audio_in
);
1593 for (i
= 0; i
< priv
->aud_skew_cnt
; i
++)
1594 priv
->audio_skew_buffer
[i
] = 0;
1595 for (i
= 0; i
< priv
->aud_skew_cnt
; i
++)
1596 priv
->audio_skew_delta_buffer
[i
] = 0;
1598 for (; !priv
->shutdown
;)
1601 read_doublespeed(priv
);
1603 if (audio_in_read_chunk(&priv
->audio_in
, priv
->audio_ringbuffer
+priv
->audio_tail
*priv
->audio_in
.blocksize
) < 0)
1606 pthread_mutex_lock(&priv
->skew_mutex
);
1607 if (priv
->first_frame
== 0) {
1608 // there is no first frame yet (unlikely to happen)
1609 gettimeofday(&tv
, NULL
);
1610 start_time_avg
= priv
->audio_start_time
= (long long)1e6
*tv
.tv_sec
+ tv
.tv_usec
;
1611 // fprintf(stderr, "warning - first frame not yet available!\n");
1612 pthread_mutex_unlock(&priv
->skew_mutex
);
1615 pthread_mutex_unlock(&priv
->skew_mutex
);
1617 gettimeofday(&tv
, NULL
);
1619 priv
->audio_recv_blocks_total
++;
1620 current_time
= (long long)1e6
*tv
.tv_sec
+ tv
.tv_usec
- priv
->audio_start_time
;
1622 if (priv
->audio_recv_blocks_total
< priv
->aud_skew_cnt
*2) {
1623 start_time_avg
+= (long long)1e6
*tv
.tv_sec
+ tv
.tv_usec
- priv
->audio_usecs_per_block
*priv
->audio_recv_blocks_total
;
1624 priv
->audio_start_time
= start_time_avg
/(priv
->audio_recv_blocks_total
+1);
1627 // fprintf(stderr, "spb = %lf, bs = %d, skew = %lf\n", priv->audio_secs_per_block, priv->audio_in.blocksize,
1628 // (double)(current_time - 1e6*priv->audio_secs_per_block*priv->audio_recv_blocks_total)/1e6);
1630 // put the current skew into the ring buffer
1631 priv
->audio_skew_total
-= priv
->audio_skew_buffer
[audio_skew_ptr
];
1632 priv
->audio_skew_buffer
[audio_skew_ptr
] = current_time
1633 - priv
->audio_usecs_per_block
*priv
->audio_recv_blocks_total
;
1634 priv
->audio_skew_total
+= priv
->audio_skew_buffer
[audio_skew_ptr
];
1636 pthread_mutex_lock(&priv
->skew_mutex
);
1640 // compute the sliding average of the skews
1641 if (priv
->audio_recv_blocks_total
> priv
->aud_skew_cnt
) {
1642 priv
->audio_skew
= priv
->audio_skew_total
/priv
->aud_skew_cnt
;
1644 priv
->audio_skew
= priv
->audio_skew_total
/priv
->audio_recv_blocks_total
;
1647 // put the current skew change (skew-prev_skew) into the ring buffer
1648 priv
->audio_skew_delta_total
-= priv
->audio_skew_delta_buffer
[audio_skew_ptr
];
1649 priv
->audio_skew_delta_buffer
[audio_skew_ptr
] = priv
->audio_skew
- prev_skew_uncorr
;
1650 priv
->audio_skew_delta_total
+= priv
->audio_skew_delta_buffer
[audio_skew_ptr
];
1651 prev_skew_uncorr
= priv
->audio_skew
; // remember the _uncorrected_ average value
1653 audio_skew_ptr
= (audio_skew_ptr
+1) % priv
->aud_skew_cnt
; // rotate the buffer pointer
1655 // sliding average approximates the value in the middle of the interval
1656 // so interpolate the skew value further to the current time
1657 priv
->audio_skew
+= priv
->audio_skew_delta_total
/2;
1659 // now finally, priv->audio_skew contains fairly good approximation
1660 // of the current value
1662 // current skew factor (assuming linearity)
1663 // used for further interpolation in video_grabber
1664 // probably overkill but seems to be necessary for
1665 // stress testing by dropping half of the audio frames ;)
1666 // especially when using ALSA with large block sizes
1667 // where audio_skew remains a long while behind
1668 if ((priv
->audio_skew_measure_time
!= 0) && (current_time
- priv
->audio_skew_measure_time
!= 0)) {
1669 priv
->audio_skew_factor
= (double)(priv
->audio_skew
-prev_skew
)/(current_time
- priv
->audio_skew_measure_time
);
1671 priv
->audio_skew_factor
= 0.0;
1674 priv
->audio_skew_measure_time
= current_time
;
1675 prev_skew
= priv
->audio_skew
;
1676 priv
->audio_skew
+= priv
->audio_start_time
- priv
->first_frame
;
1677 pthread_mutex_unlock(&priv
->skew_mutex
);
1679 // fprintf(stderr, "audio_skew = %lf, delta = %lf\n", (double)priv->audio_skew/1e6, (double)priv->audio_skew_delta_total/1e6);
1681 pthread_mutex_lock(&priv
->audio_mutex
);
1682 if ((priv
->audio_tail
+1) % priv
->audio_buffer_size
== priv
->audio_head
) {
1683 mp_msg(MSGT_TV
, MSGL_ERR
, "\ntoo bad - dropping audio frame !\n");
1686 priv
->audio_tail
= (priv
->audio_tail
+1) % priv
->audio_buffer_size
;
1689 pthread_mutex_unlock(&priv
->audio_mutex
);
1694 static double grab_audio_frame(priv_t
*priv
, char *buffer
, int len
)
1696 mp_dbg(MSGT_TV
, MSGL_DBG2
, "grab_audio_frame(priv=%p, buffer=%p, len=%d)\n",
1699 // hack: if grab_audio_frame is called first, it means we are used by mplayer
1700 // => switch to the mode which outputs audio immediately, even if
1701 // it should be silence
1702 if (priv
->first
) priv
->audio_insert_null_samples
= 1;
1704 pthread_mutex_lock(&priv
->audio_mutex
);
1705 while (priv
->audio_insert_null_samples
1706 && priv
->dropped_frames_timeshift
- priv
->dropped_frames_compensated
>= priv
->audio_usecs_per_block
) {
1707 // some frames were dropped - drop the corresponding number of audio blocks
1708 if (priv
->audio_drop
) {
1711 if (priv
->audio_head
== priv
->audio_tail
) break;
1712 priv
->audio_head
= (priv
->audio_head
+1) % priv
->audio_buffer_size
;
1714 priv
->dropped_frames_compensated
+= priv
->audio_usecs_per_block
;
1717 // compensate for dropped audio frames
1718 if (priv
->audio_drop
&& (priv
->audio_head
== priv
->audio_tail
)) {
1720 memset(buffer
, 0, len
);
1724 if (priv
->audio_insert_null_samples
&& (priv
->audio_head
== priv
->audio_tail
)) {
1725 // return silence to avoid desync and stuttering
1726 memset(buffer
, 0, len
);
1727 priv
->audio_null_blocks_inserted
++;
1731 pthread_mutex_unlock(&priv
->audio_mutex
);
1732 while (priv
->audio_head
== priv
->audio_tail
) {
1733 // this is mencoder => just wait until some audio is available
1736 pthread_mutex_lock(&priv
->audio_mutex
);
1737 memcpy(buffer
, priv
->audio_ringbuffer
+priv
->audio_head
*priv
->audio_in
.blocksize
, len
);
1738 priv
->audio_head
= (priv
->audio_head
+1) % priv
->audio_buffer_size
;
1741 pthread_mutex_unlock(&priv
->audio_mutex
);
1742 priv
->audio_sent_blocks_total
++;
1743 return (double)priv
->audio_sent_blocks_total
*priv
->audio_secs_per_block
;
1746 static int get_audio_framesize(priv_t
*priv
)
1748 return(priv
->audio_in
.blocksize
);