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@kmlinux.fjfi.cvut.cz>
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 while (!ioctl(priv
->video_fd
, VIDIOC_DQBUF
, &buf
));
882 /* unmap all buffers */
883 for (i
= 0; i
< priv
->mapcount
; i
++) {
884 if (munmap(priv
->map
[i
].addr
, priv
->map
[i
].len
) < 0) {
885 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: munmap capture buffer failed: %s\n",
886 info
.short_name
, strerror(errno
));
890 /* stop audio thread */
891 if (!tv_param_noaudio
&& priv
->audio_grabber_thread
) {
892 pthread_join(priv
->audio_grabber_thread
, NULL
);
893 pthread_mutex_destroy(&priv
->skew_mutex
);
894 pthread_mutex_destroy(&priv
->audio_mutex
);
899 /* free memory and close device */
900 free(priv
->map
); priv
->map
= NULL
;
902 if(priv
->video_fd
!=-1)close(priv
->video_fd
); priv
->video_fd
= -1;
903 free(priv
->video_dev
); priv
->video_dev
= NULL
;
905 if (priv
->video_ringbuffer
) {
907 for (i
= 0; i
< priv
->video_buffer_size_current
; i
++) {
908 free(priv
->video_ringbuffer
[i
]);
910 free(priv
->video_ringbuffer
);
912 if (priv
->video_timebuffer
)
913 free(priv
->video_timebuffer
);
914 if (!tv_param_noaudio
) {
915 if (priv
->audio_ringbuffer
)
916 free(priv
->audio_ringbuffer
);
917 if (priv
->audio_skew_buffer
)
918 free(priv
->audio_skew_buffer
);
919 if (priv
->audio_skew_delta_buffer
)
920 free(priv
->audio_skew_delta_buffer
);
923 /* show some nice statistics ;-) */
924 mp_msg(MSGT_TV
, MSGL_INFO
,
925 "%s: %d frames successfully processed, %d frames dropped.\n",
926 info
.short_name
, priv
->frames
, dropped
);
927 mp_msg(MSGT_TV
, MSGL_V
, "%s: up to %u video frames buffered.\n",
928 info
.short_name
, priv
->video_buffer_size_current
);
934 static int init(priv_t
*priv
)
938 priv
->audio_ringbuffer
= NULL
;
939 priv
->audio_skew_buffer
= NULL
;
940 priv
->audio_skew_delta_buffer
= NULL
;
942 priv
->audio_inited
= 0;
944 /* Open the video device. */
945 priv
->video_fd
= open(priv
->video_dev
, O_RDWR
);
946 if (priv
->video_fd
< 0) {
947 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: unable to open '%s': %s\n",
948 info
.short_name
, priv
->video_dev
, strerror(errno
));
952 mp_msg(MSGT_TV
, MSGL_DBG2
, "%s: video fd: %s: %d\n",
953 info
.short_name
, priv
->video_dev
, priv
->video_fd
);
956 ** Query the video capabilities and current settings
957 ** for further control calls.
959 if (ioctl(priv
->video_fd
, VIDIOC_QUERYCAP
, &priv
->capability
) < 0) {
960 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl query capabilities failed: %s\n",
961 info
.short_name
, strerror(errno
));
966 if (!(priv
->capability
.capabilities
& V4L2_CAP_VIDEO_CAPTURE
))
968 mp_msg(MSGT_TV
, MSGL_ERR
, "Device %s is not a video capture device.\n",
973 if (getfmt(priv
) < 0) {
979 ** if this device has got a tuner query it's settings
980 ** otherwise set some nice defaults
982 if (priv
->capability
.capabilities
& V4L2_CAP_TUNER
) {
983 if (ioctl(priv
->video_fd
, VIDIOC_G_TUNER
, &priv
->tuner
) < 0) {
984 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl get tuner failed: %s\n",
985 info
.short_name
, strerror(errno
));
990 mp_msg(MSGT_TV
, MSGL_INFO
, "Selected device: %s\n", priv
->capability
.card
);
991 if (priv
->capability
.capabilities
& V4L2_CAP_TUNER
) {
992 mp_msg(MSGT_TV
, MSGL_INFO
, " Tuner cap:%s%s%s\n",
993 (priv
->tuner
.capability
& V4L2_TUNER_CAP_STEREO
) ? " STEREO" : "",
994 (priv
->tuner
.capability
& V4L2_TUNER_CAP_LANG1
) ? " LANG1" : "",
995 (priv
->tuner
.capability
& V4L2_TUNER_CAP_LANG2
) ? " LANG2" : "");
996 mp_msg(MSGT_TV
, MSGL_INFO
, " Tuner rxs:%s%s%s%s\n",
997 (priv
->tuner
.rxsubchans
& V4L2_TUNER_SUB_MONO
) ? " MONO" : "",
998 (priv
->tuner
.rxsubchans
& V4L2_TUNER_SUB_STEREO
) ? " STEREO" : "",
999 (priv
->tuner
.rxsubchans
& V4L2_TUNER_SUB_LANG1
) ? " LANG1" : "",
1000 (priv
->tuner
.rxsubchans
& V4L2_TUNER_SUB_LANG2
) ? " LANG2" : "");
1002 mp_msg(MSGT_TV
, MSGL_INFO
, " Capabilites:%s%s%s%s%s%s%s%s%s%s%s\n",
1003 priv
->capability
.capabilities
& V4L2_CAP_VIDEO_CAPTURE
?
1004 " video capture": "",
1005 priv
->capability
.capabilities
& V4L2_CAP_VIDEO_OUTPUT
?
1006 " video output": "",
1007 priv
->capability
.capabilities
& V4L2_CAP_VIDEO_OVERLAY
?
1008 " video overlay": "",
1009 priv
->capability
.capabilities
& V4L2_CAP_VBI_CAPTURE
?
1010 " VBI capture device": "",
1011 priv
->capability
.capabilities
& V4L2_CAP_VBI_OUTPUT
?
1013 priv
->capability
.capabilities
& V4L2_CAP_RDS_CAPTURE
?
1014 " RDS data capture": "",
1015 priv
->capability
.capabilities
& V4L2_CAP_TUNER
?
1017 priv
->capability
.capabilities
& V4L2_CAP_AUDIO
?
1019 priv
->capability
.capabilities
& V4L2_CAP_READWRITE
?
1021 priv
->capability
.capabilities
& V4L2_CAP_ASYNCIO
?
1023 priv
->capability
.capabilities
& V4L2_CAP_STREAMING
?
1025 mp_msg(MSGT_TV
, MSGL_INFO
, " supported norms:");
1027 struct v4l2_standard standard
;
1028 memset(&standard
, 0, sizeof(standard
));
1030 if (-1 == ioctl(priv
->video_fd
, VIDIOC_ENUMSTD
, &standard
))
1032 mp_msg(MSGT_TV
, MSGL_INFO
, " %d = %s;", i
, standard
.name
);
1034 mp_msg(MSGT_TV
, MSGL_INFO
, "\n inputs:");
1035 for (i
= 0; 1; i
++) {
1036 struct v4l2_input input
;
1039 if (ioctl(priv
->video_fd
, VIDIOC_ENUMINPUT
, &input
) < 0) {
1042 mp_msg(MSGT_TV
, MSGL_INFO
, " %d = %s;", i
, input
.name
);
1044 if (ioctl(priv
->video_fd
, VIDIOC_G_INPUT
, &i
) < 0) {
1045 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl get input failed: %s\n",
1046 info
.short_name
, strerror(errno
));
1048 mp_msg(MSGT_TV
, MSGL_INFO
, "\n Current input: %d\n", i
);
1049 for (i
= 0; ; i
++) {
1050 struct v4l2_fmtdesc fmtdesc
;
1053 fmtdesc
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1054 if (ioctl(priv
->video_fd
, VIDIOC_ENUM_FMT
, &fmtdesc
) < 0) {
1057 mp_msg(MSGT_TV
, MSGL_V
, " Format %-6s (%2d bits, %s): %s\n",
1058 pixfmt2name(fmtdesc
.pixelformat
), pixfmt2depth(fmtdesc
.pixelformat
),
1059 fmtdesc
.description
, vo_format_name(fcc_vl2mp(fmtdesc
.pixelformat
)));
1061 mp_msg(MSGT_TV
, MSGL_INFO
, " Current format: %s\n",
1062 pixfmt2name(priv
->format
.fmt
.pix
.pixelformat
));
1064 /* set some nice defaults */
1065 if (getfmt(priv
) < 0) return 0;
1066 priv
->format
.fmt
.pix
.width
= 640;
1067 priv
->format
.fmt
.pix
.height
= 480;
1068 if (ioctl(priv
->video_fd
, VIDIOC_S_FMT
, &priv
->format
) < 0) {
1069 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl set format failed: %s\n",
1070 info
.short_name
, strerror(errno
));
1075 // if (!(priv->capability.capabilities & V4L2_CAP_AUDIO) && !tv_param_force_audio) tv_param_noaudio = 1;
1077 if (priv
->capability
.capabilities
& V4L2_CAP_TUNER
) {
1078 struct v4l2_control control
;
1079 if (tv_param_amode
>= 0) {
1080 mp_msg(MSGT_TV
, MSGL_V
, "%s: setting audio mode\n", info
.short_name
);
1081 priv
->tuner
.audmode
= amode2v4l(tv_param_amode
);
1082 if (ioctl(priv
->video_fd
, VIDIOC_S_TUNER
, &priv
->tuner
) < 0) {
1083 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl set tuner failed: %s\n",
1084 info
.short_name
, strerror(errno
));
1085 return TVI_CONTROL_FALSE
;
1088 mp_msg(MSGT_TV
, MSGL_INFO
, "%s: current audio mode is :%s%s%s%s\n", info
.short_name
,
1089 (priv
->tuner
.audmode
== V4L2_TUNER_MODE_MONO
) ? " MONO" : "",
1090 (priv
->tuner
.audmode
== V4L2_TUNER_MODE_STEREO
) ? " STEREO" : "",
1091 (priv
->tuner
.audmode
== V4L2_TUNER_MODE_LANG1
) ? " LANG1" : "",
1092 (priv
->tuner
.audmode
== V4L2_TUNER_MODE_LANG2
) ? " LANG2" : "");
1094 if (tv_param_volume
>= 0) {
1095 control
.id
= V4L2_CID_AUDIO_VOLUME
;
1096 control
.value
= tv_param_volume
;
1097 set_control(priv
, &control
, 0);
1099 if (tv_param_bass
>= 0) {
1100 control
.id
= V4L2_CID_AUDIO_BASS
;
1101 control
.value
= tv_param_bass
;
1102 set_control(priv
, &control
, 0);
1104 if (tv_param_treble
>= 0) {
1105 control
.id
= V4L2_CID_AUDIO_TREBLE
;
1106 control
.value
= tv_param_treble
;
1107 set_control(priv
, &control
, 0);
1109 if (tv_param_balance
>= 0) {
1110 control
.id
= V4L2_CID_AUDIO_BALANCE
;
1111 control
.value
= tv_param_balance
;
1112 set_control(priv
, &control
, 0);
1119 static int get_capture_buffer_size(priv_t
*priv
)
1122 int w
= priv
->format
.fmt
.pix
.width
;
1123 int h
= priv
->format
.fmt
.pix
.height
;
1124 int d
= pixfmt2depth(priv
->format
.fmt
.pix
.pixelformat
);
1125 int bytesperline
= w
*d
/8;
1127 if (tv_param_buffer_size
>= 0) {
1128 bufsize
= tv_param_buffer_size
*1024*1024;
1130 #ifdef HAVE_SYS_SYSINFO_H
1134 if (si
.totalram
<2*1024*1024) {
1135 bufsize
= 1024*1024;
1137 bufsize
= si
.totalram
/2;
1140 bufsize
= 16*1024*1024;
1144 cnt
= bufsize
/(h
*bytesperline
);
1145 if (cnt
< 2) cnt
= 2;
1150 /* that's the real start, we'got the format parameters (checked with control) */
1151 static int start(priv_t
*priv
)
1153 struct v4l2_requestbuffers request
;
1156 /* setup audio parameters */
1159 if (!tv_param_noaudio
&& !priv
->audio_inited
) return 0;
1161 /* we need this to size the audio buffer properly */
1162 if (priv
->immediate_mode
) {
1163 priv
->video_buffer_size_max
= 2;
1165 priv
->video_buffer_size_max
= get_capture_buffer_size(priv
);
1168 if (!tv_param_noaudio
) {
1169 setup_audio_buffer_sizes(priv
);
1170 priv
->audio_skew_buffer
= calloc(priv
->aud_skew_cnt
, sizeof(long long));
1171 if (!priv
->audio_skew_buffer
) {
1172 mp_msg(MSGT_TV
, MSGL_ERR
, "cannot allocate skew buffer: %s\n", strerror(errno
));
1175 priv
->audio_skew_delta_buffer
= calloc(priv
->aud_skew_cnt
, sizeof(long long));
1176 if (!priv
->audio_skew_delta_buffer
) {
1177 mp_msg(MSGT_TV
, MSGL_ERR
, "cannot allocate skew buffer: %s\n", strerror(errno
));
1181 priv
->audio_ringbuffer
= calloc(priv
->audio_in
.blocksize
, priv
->audio_buffer_size
);
1182 if (!priv
->audio_ringbuffer
) {
1183 mp_msg(MSGT_TV
, MSGL_ERR
, "cannot allocate audio buffer: %s\n", strerror(errno
));
1187 priv
->audio_secs_per_block
= (double)priv
->audio_in
.blocksize
/(priv
->audio_in
.samplerate
1188 *priv
->audio_in
.channels
1189 *priv
->audio_in
.bytes_per_sample
);
1190 priv
->audio_usecs_per_block
= 1e6
*priv
->audio_secs_per_block
;
1191 priv
->audio_head
= 0;
1192 priv
->audio_tail
= 0;
1193 priv
->audio_cnt
= 0;
1194 priv
->audio_drop
= 0;
1195 priv
->audio_skew
= 0;
1196 priv
->audio_skew_total
= 0;
1197 priv
->audio_skew_delta_total
= 0;
1198 priv
->audio_recv_blocks_total
= 0;
1199 priv
->audio_sent_blocks_total
= 0;
1200 priv
->audio_null_blocks_inserted
= 0;
1201 priv
->audio_insert_null_samples
= 0;
1202 priv
->dropped_frames_timeshift
= 0;
1203 priv
->dropped_frames_compensated
= 0;
1205 pthread_mutex_init(&priv
->skew_mutex
, NULL
);
1206 pthread_mutex_init(&priv
->audio_mutex
, NULL
);
1209 /* setup video parameters */
1210 if (!tv_param_noaudio
) {
1211 if (priv
->video_buffer_size_max
< (3*priv
->standard
.frameperiod
.denominator
) /
1212 priv
->standard
.frameperiod
.numerator
1213 *priv
->audio_secs_per_block
) {
1214 mp_msg(MSGT_TV
, MSGL_ERR
, "Video buffer shorter than 3 times audio frame duration.\n"
1215 "You will probably experience heavy framedrops.\n");
1220 int bytesperline
= priv
->format
.fmt
.pix
.width
*pixfmt2depth(priv
->format
.fmt
.pix
.pixelformat
)/8;
1222 mp_msg(MSGT_TV
, MSGL_V
, "Using a ring buffer for maximum %d frames, %d MB total size.\n",
1223 priv
->video_buffer_size_max
,
1224 priv
->video_buffer_size_max
*priv
->format
.fmt
.pix
.height
*bytesperline
/(1024*1024));
1227 priv
->video_ringbuffer
= calloc(priv
->video_buffer_size_max
, sizeof(unsigned char*));
1228 if (!priv
->video_ringbuffer
) {
1229 mp_msg(MSGT_TV
, MSGL_ERR
, "cannot allocate video buffer: %s\n", strerror(errno
));
1232 for (i
= 0; i
< priv
->video_buffer_size_max
; i
++)
1233 priv
->video_ringbuffer
[i
] = NULL
;
1234 priv
->video_timebuffer
= calloc(priv
->video_buffer_size_max
, sizeof(long long));
1235 if (!priv
->video_timebuffer
) {
1236 mp_msg(MSGT_TV
, MSGL_ERR
, "cannot allocate time buffer: %s\n", strerror(errno
));
1240 pthread_mutex_init(&priv
->video_buffer_mutex
, NULL
);
1242 priv
->video_head
= 0;
1243 priv
->video_tail
= 0;
1244 priv
->video_cnt
= 0;
1246 /* request buffers */
1247 if (priv
->immediate_mode
) {
1250 request
.count
= BUFFER_COUNT
;
1253 request
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1254 request
.memory
= V4L2_MEMORY_MMAP
;
1255 if (ioctl(priv
->video_fd
, VIDIOC_REQBUFS
, &request
) < 0) {
1256 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl request buffers failed: %s\n",
1257 info
.short_name
, strerror(errno
));
1262 if (!(priv
->map
= calloc(request
.count
, sizeof(struct map
)))) {
1263 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: malloc capture buffers failed: %s\n",
1264 info
.short_name
, strerror(errno
));
1268 /* map and queue buffers */
1269 for (i
= 0; i
< request
.count
; i
++) {
1270 memset(&priv
->map
[i
].buf
,0,sizeof(priv
->map
[i
].buf
));
1271 priv
->map
[i
].buf
.index
= i
;
1272 priv
->map
[i
].buf
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1273 priv
->map
[i
].buf
.memory
= V4L2_MEMORY_MMAP
;
1274 if (ioctl(priv
->video_fd
, VIDIOC_QUERYBUF
, &(priv
->map
[i
].buf
)) < 0) {
1275 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl query buffer failed: %s\n",
1276 info
.short_name
, strerror(errno
));
1281 priv
->map
[i
].addr
= mmap (0, priv
->map
[i
].buf
.length
, PROT_READ
|
1282 PROT_WRITE
, MAP_SHARED
, priv
->video_fd
, priv
->map
[i
].buf
.m
.offset
);
1283 if (priv
->map
[i
].addr
== MAP_FAILED
) {
1284 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: mmap capture buffer failed: %s\n",
1285 info
.short_name
, strerror(errno
));
1286 priv
->map
[i
].len
= 0;
1289 priv
->map
[i
].len
= priv
->map
[i
].buf
.length
;
1290 /* count up to make sure this is correct everytime */
1293 if (ioctl(priv
->video_fd
, VIDIOC_QBUF
, &(priv
->map
[i
].buf
)) < 0) {
1294 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl queue buffer failed: %s\n",
1295 info
.short_name
, strerror(errno
));
1300 /* start audio thread */
1302 priv
->audio_skew_measure_time
= 0;
1303 priv
->first_frame
= 0;
1304 priv
->audio_skew
= 0;
1313 #ifdef HAVE_TV_BSDBT848
1314 static double grabimmediate_video_frame(priv_t
*priv
, char *buffer
, int len
)
1316 memset(buffer
, 0xCC, len
);
1319 #endif /* HAVE_TV_BSDBT848 */
1321 // copies a video frame
1322 static inline void copy_frame(priv_t
*priv
, unsigned char *dest
, unsigned char *source
)
1324 int w
= priv
->format
.fmt
.pix
.width
;
1325 int h
= priv
->format
.fmt
.pix
.height
;
1326 int d
= pixfmt2depth(priv
->format
.fmt
.pix
.pixelformat
);
1327 int bytesperline
= w
*d
/8;
1329 memcpy(dest
, source
, bytesperline
* h
);
1332 // maximum skew change, in frames
1333 #define MAX_SKEW_DELTA 0.6
1334 static void *video_grabber(void *data
)
1336 priv_t
*priv
= (priv_t
*)data
;
1337 long long skew
, prev_skew
, xskew
, interval
, prev_interval
, delta
;
1339 int framesize
= priv
->format
.fmt
.pix
.height
*priv
->format
.fmt
.pix
.width
*
1340 pixfmt2depth(priv
->format
.fmt
.pix
.pixelformat
)/8;
1342 struct timeval timeout
;
1343 struct v4l2_buffer buf
;
1351 mp_msg(MSGT_TV
, MSGL_V
, "%s: going to capture\n", info
.short_name
);
1352 if (ioctl(priv
->video_fd
, VIDIOC_STREAMON
, &(priv
->format
.type
)) < 0) {
1353 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl streamon failed: %s\n",
1354 info
.short_name
, strerror(errno
));
1359 if (!tv_param_noaudio
) {
1360 pthread_create(&priv
->audio_grabber_thread
, NULL
, audio_grabber
, priv
);
1363 for (priv
->frames
= 0; !priv
->shutdown
;)
1367 if (priv
->immediate_mode
) {
1368 while (priv
->video_cnt
== priv
->video_buffer_size_max
) {
1370 if (priv
->shutdown
) {
1377 FD_SET (priv
->video_fd
, &rdset
);
1380 timeout
.tv_usec
= 0;
1382 i
= select(priv
->video_fd
+ 1, &rdset
, NULL
, NULL
, &timeout
);
1384 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: select failed: %s\n",
1385 info
.short_name
, strerror(errno
));
1389 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: select timeout\n", info
.short_name
);
1392 else if (!FD_ISSET(priv
->video_fd
, &rdset
)) {
1396 memset(&buf
,0,sizeof(buf
));
1397 buf
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1398 ret
= ioctl(priv
->video_fd
, VIDIOC_DQBUF
, &buf
);
1402 if there's no signal, the buffer might me dequeued
1403 so we query all the buffers to see which one we should
1406 observed with saa7134 0.2.8
1407 don't know if is it a bug or (mis)feature
1409 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl dequeue buffer failed: %s, idx = %d\n",
1410 info
.short_name
, strerror(errno
), buf
.index
);
1411 for (i
= 0; i
< priv
->mapcount
; i
++) {
1412 memset(&buf
,0,sizeof(buf
));
1413 buf
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1415 ret
= ioctl(priv
->video_fd
, VIDIOC_QUERYBUF
, &buf
);
1417 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl query buffer failed: %s, idx = %d\n",
1418 info
.short_name
, strerror(errno
), buf
.index
);
1421 if ((buf
.flags
& (V4L2_BUF_FLAG_QUEUED
| V4L2_BUF_FLAG_MAPPED
| V4L2_BUF_FLAG_DONE
)) == V4L2_BUF_FLAG_MAPPED
) {
1422 if (ioctl(priv
->video_fd
, VIDIOC_QBUF
, &(priv
->map
[i
].buf
)) < 0) {
1423 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl queue buffer failed: %s\n",
1424 info
.short_name
, strerror(errno
));
1432 /* store the timestamp of the very first frame as reference */
1433 if (!priv
->frames
++) {
1434 if (!tv_param_noaudio
) pthread_mutex_lock(&priv
->skew_mutex
);
1435 priv
->first_frame
= (long long)1e6
*buf
.timestamp
.tv_sec
+ buf
.timestamp
.tv_usec
;
1436 if (!tv_param_noaudio
) pthread_mutex_unlock(&priv
->skew_mutex
);
1438 priv
->curr_frame
= (long long)buf
.timestamp
.tv_sec
*1e6
+buf
.timestamp
.tv_usec
;
1439 // fprintf(stderr, "idx = %d, ts = %lf\n", buf.index, (double)(priv->curr_frame) / 1e6);
1441 interval
= priv
->curr_frame
- priv
->first_frame
;
1442 delta
= interval
- prev_interval
;
1444 if (!priv
->immediate_mode
) {
1445 // interpolate the skew in time
1446 if (!tv_param_noaudio
) pthread_mutex_lock(&priv
->skew_mutex
);
1447 xskew
= priv
->audio_skew
+ (interval
- priv
->audio_skew_measure_time
)*priv
->audio_skew_factor
;
1448 if (!tv_param_noaudio
) pthread_mutex_unlock(&priv
->skew_mutex
);
1449 // correct extreme skew changes to avoid (especially) moving backwards in time
1450 if (xskew
- prev_skew
> delta
*MAX_SKEW_DELTA
) {
1451 skew
= prev_skew
+ delta
*MAX_SKEW_DELTA
;
1452 } else if (xskew
- prev_skew
< -delta
*MAX_SKEW_DELTA
) {
1453 skew
= prev_skew
- delta
*MAX_SKEW_DELTA
;
1459 mp_msg(MSGT_TV
, MSGL_DBG3
, "\nfps = %lf, interval = %lf, a_skew = %f, corr_skew = %f\n",
1460 delta
? (double)1e6
/delta
: -1,
1461 (double)1e-6*interval
, (double)1e-6*xskew
, (double)1e-6*skew
);
1462 mp_msg(MSGT_TV
, MSGL_DBG3
, "vcnt = %d, acnt = %d\n", priv
->video_cnt
, priv
->audio_cnt
);
1465 prev_interval
= interval
;
1467 /* allocate a new buffer, if needed */
1468 pthread_mutex_lock(&priv
->video_buffer_mutex
);
1469 if (priv
->video_buffer_size_current
< priv
->video_buffer_size_max
) {
1470 if (priv
->video_cnt
== priv
->video_buffer_size_current
) {
1471 unsigned char *newbuf
= malloc(framesize
);
1473 memmove(priv
->video_ringbuffer
+priv
->video_tail
+1, priv
->video_ringbuffer
+priv
->video_tail
,
1474 (priv
->video_buffer_size_current
-priv
->video_tail
)*sizeof(unsigned char *));
1475 memmove(priv
->video_timebuffer
+priv
->video_tail
+1, priv
->video_timebuffer
+priv
->video_tail
,
1476 (priv
->video_buffer_size_current
-priv
->video_tail
)*sizeof(long long));
1477 priv
->video_ringbuffer
[priv
->video_tail
] = newbuf
;
1478 if ((priv
->video_head
>= priv
->video_tail
) && (priv
->video_cnt
> 0)) priv
->video_head
++;
1479 priv
->video_buffer_size_current
++;
1483 pthread_mutex_unlock(&priv
->video_buffer_mutex
);
1485 if (priv
->video_cnt
== priv
->video_buffer_size_current
) {
1486 if (!priv
->immediate_mode
) {
1487 mp_msg(MSGT_TV
, MSGL_ERR
, "\nvideo buffer full - dropping frame\n");
1488 if (priv
->audio_insert_null_samples
) {
1489 pthread_mutex_lock(&priv
->audio_mutex
);
1490 priv
->dropped_frames_timeshift
+= delta
;
1491 pthread_mutex_unlock(&priv
->audio_mutex
);
1495 if (priv
->immediate_mode
) {
1496 priv
->video_timebuffer
[priv
->video_tail
] = 0;
1498 // compensate for audio skew
1499 // negative skew => there are more audio samples, increase interval
1500 // positive skew => less samples, shorten the interval
1501 priv
->video_timebuffer
[priv
->video_tail
] = interval
- skew
;
1502 if (priv
->audio_insert_null_samples
&& priv
->video_timebuffer
[priv
->video_tail
] > 0) {
1503 pthread_mutex_lock(&priv
->audio_mutex
);
1504 priv
->video_timebuffer
[priv
->video_tail
] +=
1505 (priv
->audio_null_blocks_inserted
1506 - priv
->dropped_frames_timeshift
/priv
->audio_usecs_per_block
)
1507 *priv
->audio_usecs_per_block
;
1508 pthread_mutex_unlock(&priv
->audio_mutex
);
1512 copy_frame(priv
, priv
->video_ringbuffer
[priv
->video_tail
], priv
->map
[buf
.index
].addr
);
1513 priv
->video_tail
= (priv
->video_tail
+1)%priv
->video_buffer_size_current
;
1516 if (ioctl(priv
->video_fd
, VIDIOC_QBUF
, &buf
) < 0) {
1517 mp_msg(MSGT_TV
, MSGL_ERR
, "%s: ioctl queue buffer failed: %s\n",
1518 info
.short_name
, strerror(errno
));
1526 static double grab_video_frame(priv_t
*priv
, char *buffer
, int len
)
1532 pthread_create(&priv
->video_grabber_thread
, NULL
, video_grabber
, priv
);
1536 while (priv
->video_cnt
== 0) {
1538 if (loop_cnt
++ > MAX_LOOP
) return 0;
1541 pthread_mutex_lock(&priv
->video_buffer_mutex
);
1542 interval
= (double)priv
->video_timebuffer
[priv
->video_head
]*1e-6;
1543 memcpy(buffer
, priv
->video_ringbuffer
[priv
->video_head
], len
);
1545 priv
->video_head
= (priv
->video_head
+1)%priv
->video_buffer_size_current
;
1546 pthread_mutex_unlock(&priv
->video_buffer_mutex
);
1551 static int get_video_framesize(priv_t
*priv
)
1553 return priv
->format
.fmt
.pix
.sizeimage
;
1556 //#define DOUBLESPEED
1558 // for testing purposes only
1559 static void read_doublespeed(priv_t
*priv
)
1561 char *bufx
= calloc(priv
->audio_in
.blocksize
, 2);
1566 audio_in_read_chunk(&priv
->audio_in
, bufx
);
1567 audio_in_read_chunk(&priv
->audio_in
, bufx
+priv
->audio_in
.blocksize
);
1570 d
= priv
->audio_ringbuffer
+priv
->audio_tail
*priv
->audio_in
.blocksize
;
1571 for (i
= 0; i
< priv
->audio_in
.blocksize
/2; i
++) {
1579 static void *audio_grabber(void *data
)
1581 priv_t
*priv
= (priv_t
*)data
;
1583 int i
, audio_skew_ptr
= 0;
1584 long long current_time
, prev_skew
= 0, prev_skew_uncorr
= 0;
1585 long long start_time_avg
;
1587 gettimeofday(&tv
, NULL
);
1588 start_time_avg
= priv
->audio_start_time
= (long long)1e6
*tv
.tv_sec
+ tv
.tv_usec
;
1589 audio_in_start_capture(&priv
->audio_in
);
1590 for (i
= 0; i
< priv
->aud_skew_cnt
; i
++)
1591 priv
->audio_skew_buffer
[i
] = 0;
1592 for (i
= 0; i
< priv
->aud_skew_cnt
; i
++)
1593 priv
->audio_skew_delta_buffer
[i
] = 0;
1595 for (; !priv
->shutdown
;)
1598 read_doublespeed(priv
);
1600 if (audio_in_read_chunk(&priv
->audio_in
, priv
->audio_ringbuffer
+priv
->audio_tail
*priv
->audio_in
.blocksize
) < 0)
1603 pthread_mutex_lock(&priv
->skew_mutex
);
1604 if (priv
->first_frame
== 0) {
1605 // there is no first frame yet (unlikely to happen)
1606 gettimeofday(&tv
, NULL
);
1607 start_time_avg
= priv
->audio_start_time
= (long long)1e6
*tv
.tv_sec
+ tv
.tv_usec
;
1608 // fprintf(stderr, "warning - first frame not yet available!\n");
1609 pthread_mutex_unlock(&priv
->skew_mutex
);
1612 pthread_mutex_unlock(&priv
->skew_mutex
);
1614 gettimeofday(&tv
, NULL
);
1616 priv
->audio_recv_blocks_total
++;
1617 current_time
= (long long)1e6
*tv
.tv_sec
+ tv
.tv_usec
- priv
->audio_start_time
;
1619 if (priv
->audio_recv_blocks_total
< priv
->aud_skew_cnt
*2) {
1620 start_time_avg
+= (long long)1e6
*tv
.tv_sec
+ tv
.tv_usec
- priv
->audio_usecs_per_block
*priv
->audio_recv_blocks_total
;
1621 priv
->audio_start_time
= start_time_avg
/(priv
->audio_recv_blocks_total
+1);
1624 // fprintf(stderr, "spb = %lf, bs = %d, skew = %lf\n", priv->audio_secs_per_block, priv->audio_in.blocksize,
1625 // (double)(current_time - 1e6*priv->audio_secs_per_block*priv->audio_recv_blocks_total)/1e6);
1627 // put the current skew into the ring buffer
1628 priv
->audio_skew_total
-= priv
->audio_skew_buffer
[audio_skew_ptr
];
1629 priv
->audio_skew_buffer
[audio_skew_ptr
] = current_time
1630 - priv
->audio_usecs_per_block
*priv
->audio_recv_blocks_total
;
1631 priv
->audio_skew_total
+= priv
->audio_skew_buffer
[audio_skew_ptr
];
1633 pthread_mutex_lock(&priv
->skew_mutex
);
1637 // compute the sliding average of the skews
1638 if (priv
->audio_recv_blocks_total
> priv
->aud_skew_cnt
) {
1639 priv
->audio_skew
= priv
->audio_skew_total
/priv
->aud_skew_cnt
;
1641 priv
->audio_skew
= priv
->audio_skew_total
/priv
->audio_recv_blocks_total
;
1644 // put the current skew change (skew-prev_skew) into the ring buffer
1645 priv
->audio_skew_delta_total
-= priv
->audio_skew_delta_buffer
[audio_skew_ptr
];
1646 priv
->audio_skew_delta_buffer
[audio_skew_ptr
] = priv
->audio_skew
- prev_skew_uncorr
;
1647 priv
->audio_skew_delta_total
+= priv
->audio_skew_delta_buffer
[audio_skew_ptr
];
1648 prev_skew_uncorr
= priv
->audio_skew
; // remember the _uncorrected_ average value
1650 audio_skew_ptr
= (audio_skew_ptr
+1) % priv
->aud_skew_cnt
; // rotate the buffer pointer
1652 // sliding average approximates the value in the middle of the interval
1653 // so interpolate the skew value further to the current time
1654 priv
->audio_skew
+= priv
->audio_skew_delta_total
/2;
1656 // now finally, priv->audio_skew contains fairly good approximation
1657 // of the current value
1659 // current skew factor (assuming linearity)
1660 // used for further interpolation in video_grabber
1661 // probably overkill but seems to be necessary for
1662 // stress testing by dropping half of the audio frames ;)
1663 // especially when using ALSA with large block sizes
1664 // where audio_skew remains a long while behind
1665 if ((priv
->audio_skew_measure_time
!= 0) && (current_time
- priv
->audio_skew_measure_time
!= 0)) {
1666 priv
->audio_skew_factor
= (double)(priv
->audio_skew
-prev_skew
)/(current_time
- priv
->audio_skew_measure_time
);
1668 priv
->audio_skew_factor
= 0.0;
1671 priv
->audio_skew_measure_time
= current_time
;
1672 prev_skew
= priv
->audio_skew
;
1673 priv
->audio_skew
+= priv
->audio_start_time
- priv
->first_frame
;
1674 pthread_mutex_unlock(&priv
->skew_mutex
);
1676 // fprintf(stderr, "audio_skew = %lf, delta = %lf\n", (double)priv->audio_skew/1e6, (double)priv->audio_skew_delta_total/1e6);
1678 pthread_mutex_lock(&priv
->audio_mutex
);
1679 if ((priv
->audio_tail
+1) % priv
->audio_buffer_size
== priv
->audio_head
) {
1680 mp_msg(MSGT_TV
, MSGL_ERR
, "\ntoo bad - dropping audio frame !\n");
1683 priv
->audio_tail
= (priv
->audio_tail
+1) % priv
->audio_buffer_size
;
1686 pthread_mutex_unlock(&priv
->audio_mutex
);
1691 static double grab_audio_frame(priv_t
*priv
, char *buffer
, int len
)
1693 mp_dbg(MSGT_TV
, MSGL_DBG2
, "grab_audio_frame(priv=%p, buffer=%p, len=%d)\n",
1696 // hack: if grab_audio_frame is called first, it means we are used by mplayer
1697 // => switch to the mode which outputs audio immediately, even if
1698 // it should be silence
1699 if (priv
->first
) priv
->audio_insert_null_samples
= 1;
1701 pthread_mutex_lock(&priv
->audio_mutex
);
1702 while (priv
->audio_insert_null_samples
1703 && priv
->dropped_frames_timeshift
- priv
->dropped_frames_compensated
>= priv
->audio_usecs_per_block
) {
1704 // some frames were dropped - drop the corresponding number of audio blocks
1705 if (priv
->audio_drop
) {
1708 if (priv
->audio_head
== priv
->audio_tail
) break;
1709 priv
->audio_head
= (priv
->audio_head
+1) % priv
->audio_buffer_size
;
1711 priv
->dropped_frames_compensated
+= priv
->audio_usecs_per_block
;
1714 // compensate for dropped audio frames
1715 if (priv
->audio_drop
&& (priv
->audio_head
== priv
->audio_tail
)) {
1717 memset(buffer
, 0, len
);
1721 if (priv
->audio_insert_null_samples
&& (priv
->audio_head
== priv
->audio_tail
)) {
1722 // return silence to avoid desync and stuttering
1723 memset(buffer
, 0, len
);
1724 priv
->audio_null_blocks_inserted
++;
1728 pthread_mutex_unlock(&priv
->audio_mutex
);
1729 while (priv
->audio_head
== priv
->audio_tail
) {
1730 // this is mencoder => just wait until some audio is available
1733 pthread_mutex_lock(&priv
->audio_mutex
);
1734 memcpy(buffer
, priv
->audio_ringbuffer
+priv
->audio_head
*priv
->audio_in
.blocksize
, len
);
1735 priv
->audio_head
= (priv
->audio_head
+1) % priv
->audio_buffer_size
;
1738 pthread_mutex_unlock(&priv
->audio_mutex
);
1739 priv
->audio_sent_blocks_total
++;
1740 return (double)priv
->audio_sent_blocks_total
*priv
->audio_secs_per_block
;
1743 static int get_audio_framesize(priv_t
*priv
)
1745 return(priv
->audio_in
.blocksize
);