annotate libmpdemux/tvi_v4l2.c @ 18001:a2683ee7cb5a

fix descrambling of asf file, where signed buffer could cause erroneous values to be filled in descrable variables, add misssing check for one of these variables and restore sign of these variables as insurance that these checks will work even in such case.
author iive
date Thu, 30 Mar 2006 23:06:18 +0000
parents 7bf483eaa99a
children 8ceb31f028ee
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1 /*
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
2 ** Video 4 Linux 2 input
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
3 **
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
4 ** This file is part of MPlayer, see http://mplayerhq.hu/ for info.
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
5 **
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
6 ** (c) 2003 Martin Olschewski <olschewski@zpr.uni-koeln.de>
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
7 ** (c) 2003 Jindrich Makovicka <makovick@kmlinux.fjfi.cvut.cz>
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
8 **
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
9 ** File licensed under the GPL, see http://www.fsf.org/ for more info.
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
10 **
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
11 ** Some ideas are based on works from
16536
c515865e4f99 fix my email address
alex
parents: 16442
diff changeset
12 ** Alex Beregszaszi <alex@fsn.hu>
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
13 ** Gerd Knorr <kraxel@bytesex.org>
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
14 **
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
15 ** CODE IS UNDER DEVELOPMENT, NO FEATURE REQUESTS PLEASE!
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
16 */
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
17
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
18 /*
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
19
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
20 known issues:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
21 - norm setting isn't consistent with tvi_v4l
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
22 - the same for volume/bass/treble/balance
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
23
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
24 */
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
25
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
26 #include "config.h"
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
27
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
28 #if defined(USE_TV) && defined(HAVE_TV_V4L2)
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
29
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
30 #include <errno.h>
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
31 #include <fcntl.h>
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
32 #include <pthread.h>
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
33 #include <stdio.h>
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
34 #include <string.h>
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
35 #include <sys/ioctl.h>
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
36 #include <sys/mman.h>
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
37 #include <sys/time.h>
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
38 #include <sys/types.h>
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
39 #include <unistd.h>
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
40 #ifdef HAVE_SYS_SYSINFO_H
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
41 #include <sys/sysinfo.h>
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
42 #endif
16442
11331109ecad - remove useless /dev/video* checks
henry
parents: 16289
diff changeset
43 #include <linux/types.h>
11331109ecad - remove useless /dev/video* checks
henry
parents: 16289
diff changeset
44 #include <linux/videodev2.h>
17012
6ff3379a0862 Unify include path handling, -I.. is in CFLAGS.
diego
parents: 16962
diff changeset
45 #include "mp_msg.h"
6ff3379a0862 Unify include path handling, -I.. is in CFLAGS.
diego
parents: 16962
diff changeset
46 #include "libvo/img_format.h"
6ff3379a0862 Unify include path handling, -I.. is in CFLAGS.
diego
parents: 16962
diff changeset
47 #include "libaf/af_format.h"
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
48 #include "tv.h"
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
49 #include "audio_in.h"
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
50
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
51 /* information about this file */
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
52 static tvi_info_t info = {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
53 "Video 4 Linux 2 input",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
54 "v4l2",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
55 "Martin Olschewski <olschewski@zpr.uni-koeln.de>",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
56 "first try, more to come ;-)"
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
57 };
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
58
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
59 struct map {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
60 struct v4l2_buffer buf;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
61 void *addr;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
62 size_t len;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
63 };
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
64
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
65 #define BUFFER_COUNT 6
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
66
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
67 /* private data */
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
68 typedef struct {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
69 /* video */
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
70 char *video_dev;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
71 int video_fd;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
72 int mp_format;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
73 struct v4l2_capability capability;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
74 struct v4l2_input input;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
75 struct v4l2_format format;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
76 struct v4l2_standard standard;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
77 struct v4l2_tuner tuner;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
78 struct map *map;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
79 int mapcount;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
80 int frames;
10851
41bad7ce4cc9 yet another sync fix
henry
parents: 10810
diff changeset
81 volatile long long first_frame;
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
82 long long curr_frame;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
83 /* audio video interleaving ;-) */
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
84 volatile int streamon;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
85 pthread_t audio_grabber_thread;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
86 pthread_mutex_t skew_mutex;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
87
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
88 /* 2nd level video buffers */
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
89 int first;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
90 int immediate_mode;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
91
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
92 int video_buffer_size_max;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
93 volatile int video_buffer_size_current;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
94 unsigned char **video_ringbuffer;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
95 long long *video_timebuffer;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
96 volatile int video_head;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
97 volatile int video_tail;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
98 volatile int video_cnt;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
99 pthread_t video_grabber_thread;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
100 pthread_mutex_t video_buffer_mutex;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
101
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
102 /* audio */
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
103 char *audio_dev;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
104 audio_in_t audio_in;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
105
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
106 long long audio_start_time;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
107 int audio_buffer_size;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
108 int aud_skew_cnt;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
109 unsigned char *audio_ringbuffer;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
110 long long *audio_skew_buffer;
10653
d9dfbe5e1011 a/v sync improvements
henry
parents: 10538
diff changeset
111 long long *audio_skew_delta_buffer;
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
112 volatile int audio_head;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
113 volatile int audio_tail;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
114 volatile int audio_cnt;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
115 volatile long long audio_skew;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
116 volatile double audio_skew_factor;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
117 volatile long long audio_skew_measure_time;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
118 volatile int audio_drop;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
119 volatile int shutdown;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
120
15464
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
121 int audio_inited;
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
122 double audio_secs_per_block;
15449
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
123 long long audio_usecs_per_block;
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
124 long long audio_skew_total;
10653
d9dfbe5e1011 a/v sync improvements
henry
parents: 10538
diff changeset
125 long long audio_skew_delta_total;
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
126 long audio_recv_blocks_total;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
127 long audio_sent_blocks_total;
15449
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
128 pthread_mutex_t audio_mutex;
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
129 int audio_insert_null_samples;
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
130 volatile long audio_null_blocks_inserted;
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
131 volatile long long dropped_frames_timeshift;
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
132 long long dropped_frames_compensated;
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
133 } priv_t;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
134
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
135 #include "tvi_def.h"
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
136
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
137 static void *audio_grabber(void *data);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
138 static void *video_grabber(void *data);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
139
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
140 /**********************************************************************\
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
141
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
142 Only few of the fourccs are the same in v4l2 and mplayer:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
143
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
144 IMGFMT_YVU9 == V4L2_PIX_FMT_YVU410
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
145 IMGFMT_YV12 == V4L2_PIX_FMT_YVU420
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
146 IMGFMT_NV12 == V4L2_PIX_FMT_NV12
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
147 IMGFMT_422P == V4L2_PIX_FMT_YUV422P
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
148 IMGFMT_411P == V4L2_PIX_FMT_YUV411P
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
149 IMGFMT_UYVY == V4L2_PIX_FMT_UYVY
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
150 IMGFMT_Y41P == V4L2_PIX_FMT_Y41P
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
151
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
152 This may be an useful translation table for some others:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
153
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
154 IMGFMT_RGB8 == V4L2_PIX_FMT_RGB332
15449
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
155 IMGFMT_BGR15 == V4L2_PIX_FMT_RGB555
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
156 IMGFMT_BGR16 == V4L2_PIX_FMT_RGB565
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
157 IMGFMT_RGB24 == V4L2_PIX_FMT_RGB24
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
158 IMGFMT_RGB32 == V4L2_PIX_FMT_RGB32
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
159 IMGFMT_BGR24 == V4L2_PIX_FMT_BGR24
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
160 IMGFMT_BGR32 == V4L2_PIX_FMT_BGR32
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
161 IMGFMT_Y800 == V4L2_PIX_FMT_GREY
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
162 IMGFMT_IF09 == V4L2_PIX_FMT_YUV410
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
163 IMGFMT_I420 == V4L2_PIX_FMT_YUV420
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
164 IMGFMT_YUY2 == V4L2_PIX_FMT_YUYV
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
165
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
166 \**********************************************************************/
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
167
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
168 /*
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
169 ** Translate a mplayer fourcc to a video4linux2 pixel format.
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
170 */
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
171 static int fcc_mp2vl(int fcc)
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
172 {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
173 switch (fcc) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
174 case IMGFMT_RGB8: return V4L2_PIX_FMT_RGB332;
15418
c2bbb228011c v4l2 RGB15/16 is actually BGR
henry
parents: 15246
diff changeset
175 case IMGFMT_BGR15: return V4L2_PIX_FMT_RGB555;
c2bbb228011c v4l2 RGB15/16 is actually BGR
henry
parents: 15246
diff changeset
176 case IMGFMT_BGR16: return V4L2_PIX_FMT_RGB565;
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
177 case IMGFMT_RGB24: return V4L2_PIX_FMT_RGB24;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
178 case IMGFMT_RGB32: return V4L2_PIX_FMT_RGB32;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
179 case IMGFMT_BGR24: return V4L2_PIX_FMT_BGR24;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
180 case IMGFMT_BGR32: return V4L2_PIX_FMT_BGR32;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
181 case IMGFMT_Y800: return V4L2_PIX_FMT_GREY;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
182 case IMGFMT_IF09: return V4L2_PIX_FMT_YUV410;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
183 case IMGFMT_I420: return V4L2_PIX_FMT_YUV420;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
184 case IMGFMT_YUY2: return V4L2_PIX_FMT_YUYV;
17199
9164ef9a1834 remove now useless YV12 plane swap hack, patch by Luc Gallant lucgallant at gmail com
henry
parents: 17012
diff changeset
185 case IMGFMT_YV12: return V4L2_PIX_FMT_YVU420;
11657
36879e2df6cd UYVY support (port from v4l1)
henry
parents: 10852
diff changeset
186 case IMGFMT_UYVY: return V4L2_PIX_FMT_UYVY;
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
187 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
188 return fcc;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
189 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
190
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
191 /*
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
192 ** Translate a video4linux2 fourcc aka pixel format to mplayer.
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
193 */
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
194 static int fcc_vl2mp(int fcc)
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
195 {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
196 switch (fcc) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
197 case V4L2_PIX_FMT_RGB332: return IMGFMT_RGB8;
15418
c2bbb228011c v4l2 RGB15/16 is actually BGR
henry
parents: 15246
diff changeset
198 case V4L2_PIX_FMT_RGB555: return IMGFMT_BGR15;
c2bbb228011c v4l2 RGB15/16 is actually BGR
henry
parents: 15246
diff changeset
199 case V4L2_PIX_FMT_RGB565: return IMGFMT_BGR16;
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
200 case V4L2_PIX_FMT_RGB24: return IMGFMT_RGB24;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
201 case V4L2_PIX_FMT_RGB32: return IMGFMT_RGB32;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
202 case V4L2_PIX_FMT_BGR24: return IMGFMT_BGR24;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
203 case V4L2_PIX_FMT_BGR32: return IMGFMT_BGR32;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
204 case V4L2_PIX_FMT_GREY: return IMGFMT_Y800;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
205 case V4L2_PIX_FMT_YUV410: return IMGFMT_IF09;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
206 case V4L2_PIX_FMT_YUV420: return IMGFMT_I420;
17199
9164ef9a1834 remove now useless YV12 plane swap hack, patch by Luc Gallant lucgallant at gmail com
henry
parents: 17012
diff changeset
207 case V4L2_PIX_FMT_YVU420: return IMGFMT_YV12;
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
208 case V4L2_PIX_FMT_YUYV: return IMGFMT_YUY2;
11657
36879e2df6cd UYVY support (port from v4l1)
henry
parents: 10852
diff changeset
209 case V4L2_PIX_FMT_UYVY: return IMGFMT_UYVY;
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
210 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
211 return fcc;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
212 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
213
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
214 /*
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
215 ** Translate a video4linux2 fourcc aka pixel format
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
216 ** to a human readable string.
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
217 */
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
218 static char *pixfmt2name(int pixfmt)
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
219 {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
220 static char unknown[24];
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
221
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
222 switch (pixfmt) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
223 case V4L2_PIX_FMT_RGB332: return "RGB332";
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
224 case V4L2_PIX_FMT_RGB555: return "RGB555";
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
225 case V4L2_PIX_FMT_RGB565: return "RGB565";
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
226 case V4L2_PIX_FMT_RGB555X: return "RGB555X";
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
227 case V4L2_PIX_FMT_RGB565X: return "RGB565X";
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
228 case V4L2_PIX_FMT_BGR24: return "BGR24";
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
229 case V4L2_PIX_FMT_RGB24: return "RGB24";
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
230 case V4L2_PIX_FMT_BGR32: return "BGR32";
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
231 case V4L2_PIX_FMT_RGB32: return "RGB32";
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
232 case V4L2_PIX_FMT_GREY: return "GREY";
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
233 case V4L2_PIX_FMT_YVU410: return "YVU410";
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
234 case V4L2_PIX_FMT_YVU420: return "YVU420";
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
235 case V4L2_PIX_FMT_YUYV: return "YUYV";
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
236 case V4L2_PIX_FMT_UYVY: return "UYVY";
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
237 /* case V4L2_PIX_FMT_YVU422P: return "YVU422P"; */
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
238 /* case V4L2_PIX_FMT_YVU411P: return "YVU411P"; */
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
239 case V4L2_PIX_FMT_YUV422P: return "YUV422P";
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
240 case V4L2_PIX_FMT_YUV411P: return "YUV411P";
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
241 case V4L2_PIX_FMT_Y41P: return "Y41P";
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
242 case V4L2_PIX_FMT_NV12: return "NV12";
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
243 case V4L2_PIX_FMT_NV21: return "NV21";
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
244 case V4L2_PIX_FMT_YUV410: return "YUV410";
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
245 case V4L2_PIX_FMT_YUV420: return "YUV420";
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
246 case V4L2_PIX_FMT_YYUV: return "YYUV";
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
247 case V4L2_PIX_FMT_HI240: return "HI240";
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
248 case V4L2_PIX_FMT_WNVA: return "WNVA";
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
249 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
250 sprintf(unknown, "unknown (0x%x)", pixfmt);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
251 return unknown;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
252 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
253
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
254
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
255 /*
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
256 ** Gives the depth of a video4linux2 fourcc aka pixel format in bits.
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
257 */
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
258 static int pixfmt2depth(int pixfmt)
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
259 {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
260 switch (pixfmt) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
261 case V4L2_PIX_FMT_RGB332:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
262 return 8;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
263 case V4L2_PIX_FMT_RGB555:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
264 case V4L2_PIX_FMT_RGB565:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
265 case V4L2_PIX_FMT_RGB555X:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
266 case V4L2_PIX_FMT_RGB565X:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
267 return 16;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
268 case V4L2_PIX_FMT_BGR24:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
269 case V4L2_PIX_FMT_RGB24:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
270 return 24;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
271 case V4L2_PIX_FMT_BGR32:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
272 case V4L2_PIX_FMT_RGB32:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
273 return 32;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
274 case V4L2_PIX_FMT_GREY:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
275 return 8;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
276 case V4L2_PIX_FMT_YVU410:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
277 return 9;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
278 case V4L2_PIX_FMT_YVU420:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
279 return 12;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
280 case V4L2_PIX_FMT_YUYV:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
281 case V4L2_PIX_FMT_UYVY:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
282 case V4L2_PIX_FMT_YUV422P:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
283 case V4L2_PIX_FMT_YUV411P:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
284 return 16;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
285 case V4L2_PIX_FMT_Y41P:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
286 case V4L2_PIX_FMT_NV12:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
287 case V4L2_PIX_FMT_NV21:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
288 return 12;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
289 case V4L2_PIX_FMT_YUV410:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
290 return 9;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
291 case V4L2_PIX_FMT_YUV420:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
292 return 12;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
293 case V4L2_PIX_FMT_YYUV:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
294 return 16;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
295 case V4L2_PIX_FMT_HI240:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
296 return 8;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
297
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
298 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
299 return 0;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
300 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
301
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
302 static int amode2v4l(int amode)
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
303 {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
304 switch (amode) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
305 case 0:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
306 return V4L2_TUNER_MODE_MONO;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
307 case 1:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
308 return V4L2_TUNER_MODE_STEREO;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
309 case 2:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
310 return V4L2_TUNER_MODE_LANG1;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
311 case 3:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
312 return V4L2_TUNER_MODE_LANG2;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
313 default:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
314 return -1;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
315 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
316 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
317
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
318
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
319 // sets and sanitizes audio buffer/block sizes
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
320 static void setup_audio_buffer_sizes(priv_t *priv)
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
321 {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
322 int bytes_per_sample = priv->audio_in.bytes_per_sample;
16274
67a685497d21 1000000000000000l
rfelker
parents: 16186
diff changeset
323 double fps = (double)priv->standard.frameperiod.denominator /
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
324 priv->standard.frameperiod.numerator;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
325 int seconds = priv->video_buffer_size_max/fps;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
326
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
327 if (seconds < 5) seconds = 5;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
328 if (seconds > 500) seconds = 500;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
329
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
330 // make the audio buffer at least as the video buffer capacity (or 5 seconds) long
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
331 priv->audio_buffer_size = 1 + seconds*priv->audio_in.samplerate
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
332 *priv->audio_in.channels
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
333 *bytes_per_sample/priv->audio_in.blocksize;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
334 if (priv->audio_buffer_size < 256) priv->audio_buffer_size = 256;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
335
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
336 // make the skew buffer at least 1 second long
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
337 priv->aud_skew_cnt = 1 + 1*priv->audio_in.samplerate
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
338 *priv->audio_in.channels
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
339 *bytes_per_sample/priv->audio_in.blocksize;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
340 if (priv->aud_skew_cnt < 16) priv->aud_skew_cnt = 16;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
341
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
342 mp_msg(MSGT_TV, MSGL_V, "Audio capture - buffer %d blocks of %d bytes, skew average from %d meas.\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
343 priv->audio_buffer_size, priv->audio_in.blocksize, priv->aud_skew_cnt);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
344 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
345
15464
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
346 static void init_audio(priv_t *priv)
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
347 {
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
348 if (priv->audio_inited) return;
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
349
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
350 if (!tv_param_noaudio) {
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
351 #if defined(HAVE_ALSA9) || defined(HAVE_ALSA1X)
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
352 if (tv_param_alsa)
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
353 audio_in_init(&priv->audio_in, AUDIO_IN_ALSA);
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
354 else
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
355 audio_in_init(&priv->audio_in, AUDIO_IN_OSS);
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
356 #else
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
357 audio_in_init(&priv->audio_in, AUDIO_IN_OSS);
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
358 #endif
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
359
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
360 if (priv->audio_dev) {
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
361 audio_in_set_device(&priv->audio_in, priv->audio_dev);
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
362 }
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
363
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
364 audio_in_set_samplerate(&priv->audio_in, 44100);
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
365 if (priv->capability.capabilities & V4L2_CAP_TUNER) {
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
366 if (priv->tuner.audmode == V4L2_TUNER_MODE_STEREO) {
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
367 audio_in_set_channels(&priv->audio_in, 2);
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
368 } else {
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
369 audio_in_set_channels(&priv->audio_in, 1);
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
370 }
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
371 } else {
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
372 if (tv_param_forcechan >= 0) {
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
373 audio_in_set_channels(&priv->audio_in, tv_param_forcechan);
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
374 } else {
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
375 audio_in_set_channels(&priv->audio_in, 2);
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
376 }
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
377 }
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
378
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
379 if (audio_in_setup(&priv->audio_in) < 0) return;
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
380
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
381 priv->audio_inited = 1;
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
382 }
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
383 }
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
384
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
385 #if 0
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
386 /*
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
387 ** the number of milliseconds elapsed between time0 and time1
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
388 */
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
389 static size_t difftv(struct timeval time1, struct timeval time0)
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
390 {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
391 return (time1.tv_sec - time0.tv_sec) * 1000 +
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
392 (time1.tv_usec - time0.tv_usec) / 1000;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
393 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
394 #endif
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
395
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
396 /*
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
397 ** Get current video capture format.
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
398 */
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
399 static int getfmt(priv_t *priv)
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
400 {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
401 int i;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
402
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
403 priv->format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
404 if ((i = ioctl(priv->video_fd, VIDIOC_G_FMT, &priv->format)) < 0) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
405 mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl get format failed: %s\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
406 info.short_name, strerror(errno));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
407 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
408 return i;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
409 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
410
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
411
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
412 /*
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
413 ** Get current video capture standard.
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
414 */
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
415 static int getstd(priv_t *priv)
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
416 {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
417 v4l2_std_id id;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
418 int i=0;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
419
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
420 if (ioctl(priv->video_fd, VIDIOC_G_STD, &id) < 0) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
421 mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl get standard failed: %s\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
422 info.short_name, strerror(errno));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
423 return -1;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
424 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
425 do {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
426 priv->standard.index = i++;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
427 if (ioctl(priv->video_fd, VIDIOC_ENUMSTD, &priv->standard) < 0) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
428 return -1;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
429 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
430 } while (priv->standard.id != id);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
431 return 0;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
432 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
433
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
434 /***********************************************************************\
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
435 * *
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
436 * *
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
437 * Interface to mplayer *
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
438 * *
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
439 * *
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
440 \***********************************************************************/
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
441
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
442 static int set_mute(priv_t *priv, int value)
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
443 {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
444 struct v4l2_control control;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
445 control.id = V4L2_CID_AUDIO_MUTE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
446 control.value = value;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
447 if (ioctl(priv->video_fd, VIDIOC_S_CTRL, &control) < 0) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
448 mp_msg(MSGT_TV,MSGL_ERR,"%s: ioctl set mute failed: %s\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
449 info.short_name, strerror(errno));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
450 return 0;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
451 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
452 return 1;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
453 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
454
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
455 /*
12860
03d3ab9f6400 embarassing typo
diego
parents: 12380
diff changeset
456 ** MPlayer uses values from -100 up to 100 for controls.
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
457 ** Here they are scaled to what the tv card needs and applied.
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
458 */
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
459 static int set_control(priv_t *priv, struct v4l2_control *control, int val_signed) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
460 struct v4l2_queryctrl qctrl;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
461
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
462 qctrl.id = control->id;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
463 if (ioctl(priv->video_fd, VIDIOC_QUERYCTRL, &qctrl) < 0) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
464 mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl query control failed: %s\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
465 info.short_name, strerror(errno));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
466 return TVI_CONTROL_FALSE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
467 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
468
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
469 if (val_signed) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
470 if (control->value < 0) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
471 control->value = qctrl.default_value + control->value *
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
472 (qctrl.default_value - qctrl.minimum) / 100;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
473 } else {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
474 control->value = qctrl.default_value + control->value *
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
475 (qctrl.maximum - qctrl.default_value) / 100;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
476 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
477 } else {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
478 if (control->value < 50) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
479 control->value = qctrl.default_value + (control->value-50) *
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
480 (qctrl.default_value - qctrl.minimum) / 50;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
481 } else {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
482 control->value = qctrl.default_value + (control->value-50) *
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
483 (qctrl.maximum - qctrl.default_value) / 50;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
484 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
485 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
486
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
487
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
488 if (ioctl(priv->video_fd, VIDIOC_S_CTRL, control) < 0) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
489 mp_msg(MSGT_TV, MSGL_ERR,"%s: ioctl set %s %d failed: %s\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
490 info.short_name, qctrl.name, control->value, strerror(errno));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
491 return TVI_CONTROL_FALSE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
492 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
493 mp_msg(MSGT_TV, MSGL_V, "%s: set %s: %d [%d, %d]\n", info.short_name,
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
494 qctrl.name, control->value, qctrl.minimum, qctrl.maximum);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
495
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
496 return TVI_CONTROL_TRUE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
497 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
498
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
499
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
500 /*
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
501 ** Scale the control values back to what mplayer needs.
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
502 */
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
503 static int get_control(priv_t *priv, struct v4l2_control *control, int val_signed) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
504 struct v4l2_queryctrl qctrl;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
505
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
506 qctrl.id = control->id;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
507 if (ioctl(priv->video_fd, VIDIOC_QUERYCTRL, &qctrl) < 0) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
508 mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl query control failed: %s\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
509 info.short_name, strerror(errno));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
510 return TVI_CONTROL_FALSE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
511 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
512
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
513 if (ioctl(priv->video_fd, VIDIOC_G_CTRL, control) < 0) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
514 mp_msg(MSGT_TV, MSGL_ERR,"%s: ioctl get %s failed: %s\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
515 info.short_name, qctrl.name, strerror(errno));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
516 return TVI_CONTROL_FALSE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
517 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
518 mp_msg(MSGT_TV, MSGL_V, "%s: get %s: %d [%d, %d]\n", info.short_name,
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
519 qctrl.name, control->value, qctrl.minimum, qctrl.maximum);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
520
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
521 if (val_signed) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
522 if (control->value < qctrl.default_value) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
523 control->value = (control->value - qctrl.default_value) * 100 /
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
524 (qctrl.default_value - qctrl.minimum);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
525 } else {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
526 control->value = (control->value - qctrl.default_value) * 100 /
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
527 (qctrl.maximum - qctrl.default_value);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
528 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
529 } else {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
530 if (control->value < qctrl.default_value) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
531 control->value = (control->value - qctrl.default_value) * 50 /
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
532 (qctrl.default_value - qctrl.minimum) + 50;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
533 } else {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
534 control->value = (control->value - qctrl.default_value) * 50 /
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
535 (qctrl.maximum - qctrl.default_value) + 50;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
536 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
537 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
538
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
539 return TVI_CONTROL_TRUE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
540 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
541
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
542 static int control(priv_t *priv, int cmd, void *arg)
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
543 {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
544 struct v4l2_control control;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
545 struct v4l2_frequency frequency;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
546
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
547 switch(cmd) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
548 case TVI_CONTROL_IS_VIDEO:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
549 return priv->capability.capabilities & V4L2_CAP_VIDEO_CAPTURE?
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
550 TVI_CONTROL_TRUE: TVI_CONTROL_FALSE;
17765
7bf483eaa99a If we have a tuner, use that as a reason we have audio support, and do
aurel
parents: 17626
diff changeset
551 case TVI_CONTROL_IS_AUDIO:
7bf483eaa99a If we have a tuner, use that as a reason we have audio support, and do
aurel
parents: 17626
diff changeset
552 if (tv_param_force_audio) return TVI_CONTROL_TRUE;
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
553 case TVI_CONTROL_IS_TUNER:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
554 return priv->capability.capabilities & V4L2_CAP_TUNER?
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
555 TVI_CONTROL_TRUE: TVI_CONTROL_FALSE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
556 case TVI_CONTROL_IMMEDIATE:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
557 priv->immediate_mode = 1;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
558 return TVI_CONTROL_TRUE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
559 case TVI_CONTROL_VID_GET_FPS:
16289
cafa391ff89c mode fps int vs. float woes
henry
parents: 16274
diff changeset
560 *(float *)arg = (float)priv->standard.frameperiod.denominator /
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
561 priv->standard.frameperiod.numerator;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
562 mp_msg(MSGT_TV, MSGL_V, "%s: get fps: %f\n", info.short_name,
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
563 *(float *)arg);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
564 return TVI_CONTROL_TRUE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
565 case TVI_CONTROL_VID_GET_BITS:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
566 if (getfmt(priv) < 0) return TVI_CONTROL_FALSE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
567 *(int *)arg = pixfmt2depth(priv->format.fmt.pix.pixelformat);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
568 mp_msg(MSGT_TV, MSGL_V, "%s: get depth: %d\n", info.short_name,
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
569 *(int *)arg);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
570 return TVI_CONTROL_TRUE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
571 case TVI_CONTROL_VID_GET_FORMAT:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
572 if (getfmt(priv) < 0) return TVI_CONTROL_FALSE;
17199
9164ef9a1834 remove now useless YV12 plane swap hack, patch by Luc Gallant lucgallant at gmail com
henry
parents: 17012
diff changeset
573 *(int *)arg = fcc_vl2mp(priv->format.fmt.pix.pixelformat);
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
574 mp_msg(MSGT_TV, MSGL_V, "%s: get format: %s\n", info.short_name,
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
575 pixfmt2name(priv->format.fmt.pix.pixelformat));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
576 return TVI_CONTROL_TRUE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
577 case TVI_CONTROL_VID_SET_FORMAT:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
578 if (getfmt(priv) < 0) return TVI_CONTROL_FALSE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
579 priv->format.fmt.pix.pixelformat = fcc_mp2vl(*(int *)arg);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
580 priv->format.fmt.pix.field = V4L2_FIELD_ANY;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
581
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
582 priv->mp_format = *(int *)arg;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
583 mp_msg(MSGT_TV, MSGL_V, "%s: set format: %s\n", info.short_name,
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
584 pixfmt2name(priv->format.fmt.pix.pixelformat));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
585 if (ioctl(priv->video_fd, VIDIOC_S_FMT, &priv->format) < 0) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
586 mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl set format failed: %s\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
587 info.short_name, strerror(errno));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
588 return TVI_CONTROL_FALSE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
589 }
16186
e861f9b7a70e take into account that VIDIOC_S_FMT might return updated parameters
faust3
parents: 16185
diff changeset
590 /* according to the v4l2 specs VIDIOC_S_FMT should not fail, inflexible drivers
e861f9b7a70e take into account that VIDIOC_S_FMT might return updated parameters
faust3
parents: 16185
diff changeset
591 might even always return the default parameters -> update the format here*/
e861f9b7a70e take into account that VIDIOC_S_FMT might return updated parameters
faust3
parents: 16185
diff changeset
592 priv->mp_format = fcc_vl2mp(priv->format.fmt.pix.pixelformat);
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
593 return TVI_CONTROL_TRUE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
594 case TVI_CONTROL_VID_GET_WIDTH:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
595 if (getfmt(priv) < 0) return TVI_CONTROL_FALSE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
596 *(int *)arg = priv->format.fmt.pix.width;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
597 mp_msg(MSGT_TV, MSGL_V, "%s: get width: %d\n", info.short_name,
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
598 *(int *)arg);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
599 return TVI_CONTROL_TRUE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
600 case TVI_CONTROL_VID_CHK_WIDTH:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
601 return TVI_CONTROL_TRUE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
602 case TVI_CONTROL_VID_SET_WIDTH:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
603 if (getfmt(priv) < 0) return TVI_CONTROL_FALSE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
604 priv->format.fmt.pix.width = *(int *)arg;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
605 mp_msg(MSGT_TV, MSGL_V, "%s: set width: %d\n", info.short_name,
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
606 *(int *)arg);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
607 if (ioctl(priv->video_fd, VIDIOC_S_FMT, &priv->format) < 0) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
608 mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl set width failed: %s\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
609 info.short_name, strerror(errno));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
610 return TVI_CONTROL_FALSE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
611 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
612 return TVI_CONTROL_TRUE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
613 case TVI_CONTROL_VID_GET_HEIGHT:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
614 if (getfmt(priv) < 0) return TVI_CONTROL_FALSE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
615 *(int *)arg = priv->format.fmt.pix.height;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
616 mp_msg(MSGT_TV, MSGL_V, "%s: get height: %d\n", info.short_name,
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
617 *(int *)arg);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
618 return TVI_CONTROL_TRUE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
619 case TVI_CONTROL_VID_CHK_HEIGHT:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
620 return TVI_CONTROL_TRUE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
621 case TVI_CONTROL_VID_SET_HEIGHT:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
622 if (getfmt(priv) < 0) return TVI_CONTROL_FALSE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
623 priv->format.fmt.pix.height = *(int *)arg;
12210
c941a2362911 specify field mode when setting image height
henry
parents: 11997
diff changeset
624 priv->format.fmt.pix.field = V4L2_FIELD_ANY;
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
625 mp_msg(MSGT_TV, MSGL_V, "%s: set height: %d\n", info.short_name,
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
626 *(int *)arg);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
627 if (ioctl(priv->video_fd, VIDIOC_S_FMT, &priv->format) < 0) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
628 mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl set height failed: %s\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
629 info.short_name, strerror(errno));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
630 return TVI_CONTROL_FALSE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
631 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
632 return TVI_CONTROL_TRUE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
633 case TVI_CONTROL_VID_GET_BRIGHTNESS:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
634 control.id = V4L2_CID_BRIGHTNESS;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
635 if (get_control(priv, &control, 1) == TVI_CONTROL_TRUE) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
636 *(int *)arg = control.value;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
637 return TVI_CONTROL_TRUE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
638 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
639 return TVI_CONTROL_FALSE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
640 case TVI_CONTROL_VID_SET_BRIGHTNESS:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
641 control.id = V4L2_CID_BRIGHTNESS;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
642 control.value = *(int *)arg;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
643 return set_control(priv, &control, 1);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
644 case TVI_CONTROL_VID_GET_HUE:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
645 control.id = V4L2_CID_HUE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
646 if (get_control(priv, &control, 1) == TVI_CONTROL_TRUE) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
647 *(int *)arg = control.value;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
648 return TVI_CONTROL_TRUE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
649 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
650 return TVI_CONTROL_FALSE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
651 case TVI_CONTROL_VID_SET_HUE:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
652 control.id = V4L2_CID_HUE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
653 control.value = *(int *)arg;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
654 return set_control(priv, &control, 1);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
655 case TVI_CONTROL_VID_GET_SATURATION:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
656 control.id = V4L2_CID_SATURATION;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
657 if (get_control(priv, &control, 1) == TVI_CONTROL_TRUE) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
658 *(int *)arg = control.value;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
659 return TVI_CONTROL_TRUE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
660 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
661 return TVI_CONTROL_FALSE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
662 case TVI_CONTROL_VID_SET_SATURATION:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
663 control.id = V4L2_CID_SATURATION;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
664 control.value = *(int *)arg;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
665 return set_control(priv, &control, 1);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
666 case TVI_CONTROL_VID_GET_CONTRAST:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
667 control.id = V4L2_CID_CONTRAST;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
668 if (get_control(priv, &control, 1) == TVI_CONTROL_TRUE) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
669 *(int *)arg = control.value;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
670 return TVI_CONTROL_TRUE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
671 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
672 return TVI_CONTROL_FALSE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
673 case TVI_CONTROL_VID_SET_CONTRAST:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
674 control.id = V4L2_CID_CONTRAST;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
675 control.value = *(int *)arg;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
676 return set_control(priv, &control, 1);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
677 case TVI_CONTROL_TUN_GET_FREQ:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
678 frequency.tuner = 0;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
679 frequency.type = V4L2_TUNER_ANALOG_TV;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
680 if (ioctl(priv->video_fd, VIDIOC_G_FREQUENCY, &frequency) < 0) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
681 mp_msg(MSGT_TV,MSGL_ERR,"%s: ioctl get frequency failed: %s\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
682 info.short_name, strerror(errno));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
683 return TVI_CONTROL_FALSE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
684 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
685 *(int *)arg = frequency.frequency;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
686 return TVI_CONTROL_TRUE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
687 case TVI_CONTROL_TUN_SET_FREQ:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
688 #if 0
17626
5627625b0cdb Don't test the v4l2_input audioset field for audio capabilities but still try changing the mute setting (patch by Jesse Allen < the3dfxdude _at_ gmail.com >)
aurel
parents: 17199
diff changeset
689 set_mute(priv, 1);
5627625b0cdb Don't test the v4l2_input audioset field for audio capabilities but still try changing the mute setting (patch by Jesse Allen < the3dfxdude _at_ gmail.com >)
aurel
parents: 17199
diff changeset
690 usleep(100000); // wait to supress noise during switching
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
691 #endif
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
692 frequency.tuner = 0;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
693 frequency.type = V4L2_TUNER_ANALOG_TV;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
694 frequency.frequency = *(int *)arg;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
695 if (ioctl(priv->video_fd, VIDIOC_S_FREQUENCY, &frequency) < 0) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
696 mp_msg(MSGT_TV,MSGL_ERR,"%s: ioctl set frequency failed: %s\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
697 info.short_name, strerror(errno));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
698 return TVI_CONTROL_FALSE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
699 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
700 #if 0
17626
5627625b0cdb Don't test the v4l2_input audioset field for audio capabilities but still try changing the mute setting (patch by Jesse Allen < the3dfxdude _at_ gmail.com >)
aurel
parents: 17199
diff changeset
701 usleep(100000); // wait to supress noise during switching
5627625b0cdb Don't test the v4l2_input audioset field for audio capabilities but still try changing the mute setting (patch by Jesse Allen < the3dfxdude _at_ gmail.com >)
aurel
parents: 17199
diff changeset
702 set_mute(priv, 0);
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
703 #endif
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
704 return TVI_CONTROL_TRUE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
705 case TVI_CONTROL_TUN_GET_TUNER:
10735
8a10d5d0ce86 serious bugs - 1l absinth (changed to absinth against cola inflation)
alex
parents: 10704
diff changeset
706 mp_msg(MSGT_TV, MSGL_V, "%s: get tuner\n",info.short_name);
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
707 if (ioctl(priv->video_fd, VIDIOC_G_TUNER, &priv->tuner) < 0) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
708 mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl get tuner failed: %s\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
709 info.short_name, strerror(errno));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
710 return TVI_CONTROL_FALSE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
711 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
712 return TVI_CONTROL_TRUE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
713 case TVI_CONTROL_TUN_SET_TUNER:
10735
8a10d5d0ce86 serious bugs - 1l absinth (changed to absinth against cola inflation)
alex
parents: 10704
diff changeset
714 mp_msg(MSGT_TV, MSGL_V, "%s: set tuner\n",info.short_name);
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
715 if (ioctl(priv->video_fd, VIDIOC_S_TUNER, &priv->tuner) < 0) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
716 mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl set tuner failed: %s\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
717 info.short_name, strerror(errno));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
718 return TVI_CONTROL_FALSE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
719 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
720 return TVI_CONTROL_TRUE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
721 case TVI_CONTROL_TUN_GET_NORM:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
722 *(int *)arg = priv->standard.index;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
723 return TVI_CONTROL_TRUE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
724 case TVI_CONTROL_TUN_SET_NORM:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
725 priv->standard.index = *(int *)arg;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
726 if (ioctl(priv->video_fd, VIDIOC_ENUMSTD, &priv->standard) < 0) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
727 mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl enum norm failed: %s\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
728 info.short_name, strerror(errno));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
729 return TVI_CONTROL_FALSE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
730 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
731 mp_msg(MSGT_TV, MSGL_V, "%s: set norm: %s\n", info.short_name, priv->standard.name);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
732 if (ioctl(priv->video_fd, VIDIOC_S_STD, &priv->standard.id) < 0) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
733 mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl set norm failed: %s\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
734 info.short_name, strerror(errno));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
735 return TVI_CONTROL_FALSE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
736 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
737 return TVI_CONTROL_TRUE;
13978
2a9afbfc79d7 setting the norm using text ID instead of numeric
henry
parents: 12860
diff changeset
738 case TVI_CONTROL_SPC_GET_NORMID:
2a9afbfc79d7 setting the norm using text ID instead of numeric
henry
parents: 12860
diff changeset
739 {
2a9afbfc79d7 setting the norm using text ID instead of numeric
henry
parents: 12860
diff changeset
740 int i;
2a9afbfc79d7 setting the norm using text ID instead of numeric
henry
parents: 12860
diff changeset
741 for (i = 0;; i++) {
2a9afbfc79d7 setting the norm using text ID instead of numeric
henry
parents: 12860
diff changeset
742 struct v4l2_standard standard;
2a9afbfc79d7 setting the norm using text ID instead of numeric
henry
parents: 12860
diff changeset
743 memset(&standard, 0, sizeof(standard));
2a9afbfc79d7 setting the norm using text ID instead of numeric
henry
parents: 12860
diff changeset
744 standard.index = i;
2a9afbfc79d7 setting the norm using text ID instead of numeric
henry
parents: 12860
diff changeset
745 if (-1 == ioctl(priv->video_fd, VIDIOC_ENUMSTD, &standard))
2a9afbfc79d7 setting the norm using text ID instead of numeric
henry
parents: 12860
diff changeset
746 return TVI_CONTROL_FALSE;
2a9afbfc79d7 setting the norm using text ID instead of numeric
henry
parents: 12860
diff changeset
747 if (!strcasecmp(standard.name, (char *)arg)) {
2a9afbfc79d7 setting the norm using text ID instead of numeric
henry
parents: 12860
diff changeset
748 *(int *)arg = i;
2a9afbfc79d7 setting the norm using text ID instead of numeric
henry
parents: 12860
diff changeset
749 return TVI_CONTROL_TRUE;
2a9afbfc79d7 setting the norm using text ID instead of numeric
henry
parents: 12860
diff changeset
750 }
2a9afbfc79d7 setting the norm using text ID instead of numeric
henry
parents: 12860
diff changeset
751 }
2a9afbfc79d7 setting the norm using text ID instead of numeric
henry
parents: 12860
diff changeset
752 return TVI_CONTROL_FALSE;
2a9afbfc79d7 setting the norm using text ID instead of numeric
henry
parents: 12860
diff changeset
753 }
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
754 case TVI_CONTROL_SPC_GET_INPUT:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
755 if (ioctl(priv->video_fd, VIDIOC_G_INPUT, (int *)arg) < 0) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
756 mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl get input failed: %s\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
757 info.short_name, strerror(errno));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
758 return TVI_CONTROL_FALSE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
759 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
760 return TVI_CONTROL_TRUE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
761 case TVI_CONTROL_SPC_SET_INPUT:
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
762 mp_msg(MSGT_TV, MSGL_V, "%s: set input: %d\n", info.short_name, *(int *)arg);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
763 priv->input.index = *(int *)arg;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
764 if (ioctl(priv->video_fd, VIDIOC_ENUMINPUT, &priv->input) < 0) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
765 mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl enum input failed: %s\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
766 info.short_name, strerror(errno));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
767 return TVI_CONTROL_FALSE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
768 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
769 if (ioctl(priv->video_fd, VIDIOC_S_INPUT, (int *)arg) < 0) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
770 mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl set input failed: %s\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
771 info.short_name, strerror(errno));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
772 return TVI_CONTROL_FALSE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
773 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
774 return TVI_CONTROL_TRUE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
775 case TVI_CONTROL_AUD_GET_FORMAT:
15464
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
776 init_audio(priv);
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
777 if (!priv->audio_inited) return TVI_CONTROL_FALSE;
14245
815f03b7cee5 removing AFMT_ dependancy
alex
parents: 14214
diff changeset
778 *(int *)arg = AF_FORMAT_S16_LE;
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
779 mp_msg(MSGT_TV, MSGL_V, "%s: get audio format: %d\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
780 info.short_name, *(int *)arg);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
781 return TVI_CONTROL_TRUE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
782 case TVI_CONTROL_AUD_GET_SAMPLERATE:
15464
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
783 init_audio(priv);
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
784 if (!priv->audio_inited) return TVI_CONTROL_FALSE;
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
785 *(int *)arg = priv->audio_in.samplerate;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
786 mp_msg(MSGT_TV, MSGL_V, "%s: get audio samplerate: %d\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
787 info.short_name, *(int *)arg);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
788 return TVI_CONTROL_TRUE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
789 case TVI_CONTROL_AUD_GET_SAMPLESIZE:
15464
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
790 init_audio(priv);
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
791 if (!priv->audio_inited) return TVI_CONTROL_FALSE;
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
792 *(int *)arg = priv->audio_in.bytes_per_sample;
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
793 mp_msg(MSGT_TV, MSGL_V, "%s: get audio samplesize: %d\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
794 info.short_name, *(int *)arg);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
795 return TVI_CONTROL_TRUE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
796 case TVI_CONTROL_AUD_GET_CHANNELS:
15464
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
797 init_audio(priv);
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
798 if (!priv->audio_inited) return TVI_CONTROL_FALSE;
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
799 *(int *)arg = priv->audio_in.channels;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
800 mp_msg(MSGT_TV, MSGL_V, "%s: get audio channels: %d\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
801 info.short_name, *(int *)arg);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
802 return TVI_CONTROL_TRUE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
803 case TVI_CONTROL_AUD_SET_SAMPLERATE:
15464
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
804 init_audio(priv);
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
805 mp_msg(MSGT_TV, MSGL_V, "%s: set audio samplerate: %d\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
806 info.short_name, *(int *)arg);
12380
ae2f3126d7df 10000000000l twisted typecasting
henry
parents: 12210
diff changeset
807 if (audio_in_set_samplerate(&priv->audio_in, *(int*)arg) < 0) return TVI_CONTROL_FALSE;
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
808 // setup_audio_buffer_sizes(priv);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
809 return TVI_CONTROL_TRUE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
810 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
811 mp_msg(MSGT_TV, MSGL_V, "%s: unknown control: %d\n", info.short_name, cmd);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
812 return(TVI_CONTROL_UNKNOWN);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
813 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
814
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
815
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
816 #define PRIV ((priv_t *) (tvi_handle->priv))
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
817
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
818 /* handler creator - entry point ! */
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
819 tvi_handle_t *tvi_init_v4l2(char *video_dev, char *audio_dev)
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
820 {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
821 tvi_handle_t *tvi_handle;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
822
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
823 /* new_handle initializes priv with memset 0 */
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
824 tvi_handle = new_handle();
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
825 if (!tvi_handle) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
826 return NULL;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
827 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
828 PRIV->video_fd = -1;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
829
15246
849a6f39964f use the documented default video device /dev/video0 instead of /dev/video that is missing on most systems
iive
parents: 14245
diff changeset
830 PRIV->video_dev = strdup(video_dev? video_dev: "/dev/video0");
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
831 if (!PRIV->video_dev) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
832 free_handle(tvi_handle);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
833 return NULL;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
834 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
835
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
836 if (audio_dev) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
837 PRIV->audio_dev = strdup(audio_dev);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
838 if (!PRIV->audio_dev) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
839 free(PRIV->video_dev);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
840 free_handle(tvi_handle);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
841 return NULL;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
842 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
843 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
844
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
845 return tvi_handle;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
846 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
847
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
848 #undef PRIV
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
849
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
850
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
851 static int uninit(priv_t *priv)
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
852 {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
853 int i, frames, dropped = 0;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
854
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
855 priv->shutdown = 1;
16185
973b82bf1187 do not crash when /dev/video0 is not present
faust3
parents: 15987
diff changeset
856 if(priv->video_grabber_thread)
973b82bf1187 do not crash when /dev/video0 is not present
faust3
parents: 15987
diff changeset
857 pthread_join(priv->video_grabber_thread, NULL);
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
858 pthread_mutex_destroy(&priv->video_buffer_mutex);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
859
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
860 if (priv->streamon) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
861 struct v4l2_buffer buf;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
862
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
863 /* get performance */
11997
48b5bfb25dc0 missing video thread shutdown, frame count rounding fix
henry
parents: 11876
diff changeset
864 frames = 1 + (priv->curr_frame - priv->first_frame +
48b5bfb25dc0 missing video thread shutdown, frame count rounding fix
henry
parents: 11876
diff changeset
865 priv->standard.frameperiod.numerator * 500000 /
48b5bfb25dc0 missing video thread shutdown, frame count rounding fix
henry
parents: 11876
diff changeset
866 priv->standard.frameperiod.denominator) *
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
867 priv->standard.frameperiod.denominator /
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
868 priv->standard.frameperiod.numerator / 1000000;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
869 dropped = frames - priv->frames;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
870
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
871 /* turn off streaming */
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
872 if (ioctl(priv->video_fd, VIDIOC_STREAMOFF, &(priv->map[0].buf.type)) < 0) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
873 mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl streamoff failed: %s\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
874 info.short_name, strerror(errno));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
875 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
876 priv->streamon = 0;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
877
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
878 /* unqueue all remaining buffers */
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
879 memset(&buf,0,sizeof(buf));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
880 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
881 while (!ioctl(priv->video_fd, VIDIOC_DQBUF, &buf));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
882 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
883
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
884 /* unmap all buffers */
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
885 for (i = 0; i < priv->mapcount; i++) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
886 if (munmap(priv->map[i].addr, priv->map[i].len) < 0) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
887 mp_msg(MSGT_TV, MSGL_ERR, "%s: munmap capture buffer failed: %s\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
888 info.short_name, strerror(errno));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
889 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
890 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
891
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
892 /* stop audio thread */
15987
51aafa55f44c fix a crash at v4l2 uninit
aurel
parents: 15464
diff changeset
893 if (!tv_param_noaudio && priv->audio_grabber_thread) {
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
894 pthread_join(priv->audio_grabber_thread, NULL);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
895 pthread_mutex_destroy(&priv->skew_mutex);
15449
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
896 pthread_mutex_destroy(&priv->audio_mutex);
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
897 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
898
17626
5627625b0cdb Don't test the v4l2_input audioset field for audio capabilities but still try changing the mute setting (patch by Jesse Allen < the3dfxdude _at_ gmail.com >)
aurel
parents: 17199
diff changeset
899 set_mute(priv, 1);
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
900
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
901 /* free memory and close device */
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
902 free(priv->map); priv->map = NULL;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
903 priv->mapcount = 0;
16185
973b82bf1187 do not crash when /dev/video0 is not present
faust3
parents: 15987
diff changeset
904 if(priv->video_fd!=-1)close(priv->video_fd); priv->video_fd = -1;
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
905 free(priv->video_dev); priv->video_dev = NULL;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
906
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
907 if (priv->video_ringbuffer) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
908 int i;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
909 for (i = 0; i < priv->video_buffer_size_current; i++) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
910 free(priv->video_ringbuffer[i]);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
911 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
912 free(priv->video_ringbuffer);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
913 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
914 if (priv->video_timebuffer)
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
915 free(priv->video_timebuffer);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
916 if (!tv_param_noaudio) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
917 if (priv->audio_ringbuffer)
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
918 free(priv->audio_ringbuffer);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
919 if (priv->audio_skew_buffer)
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
920 free(priv->audio_skew_buffer);
10653
d9dfbe5e1011 a/v sync improvements
henry
parents: 10538
diff changeset
921 if (priv->audio_skew_delta_buffer)
d9dfbe5e1011 a/v sync improvements
henry
parents: 10538
diff changeset
922 free(priv->audio_skew_delta_buffer);
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
923 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
924
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
925 /* show some nice statistics ;-) */
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
926 mp_msg(MSGT_TV, MSGL_INFO,
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
927 "%s: %d frames successfully processed, %d frames dropped.\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
928 info.short_name, priv->frames, dropped);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
929 mp_msg(MSGT_TV, MSGL_V, "%s: up to %u video frames buffered.\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
930 info.short_name, priv->video_buffer_size_current);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
931 return 1;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
932 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
933
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
934
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
935 /* initialisation */
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
936 static int init(priv_t *priv)
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
937 {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
938 int i;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
939
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
940 priv->audio_ringbuffer = NULL;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
941 priv->audio_skew_buffer = NULL;
10653
d9dfbe5e1011 a/v sync improvements
henry
parents: 10538
diff changeset
942 priv->audio_skew_delta_buffer = NULL;
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
943
15464
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
944 priv->audio_inited = 0;
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
945
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
946 /* Open the video device. */
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
947 priv->video_fd = open(priv->video_dev, O_RDWR);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
948 if (priv->video_fd < 0) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
949 mp_msg(MSGT_TV, MSGL_ERR, "%s: unable to open '%s': %s\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
950 info.short_name, priv->video_dev, strerror(errno));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
951 uninit(priv);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
952 return 0;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
953 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
954 mp_msg(MSGT_TV, MSGL_DBG2, "%s: video fd: %s: %d\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
955 info.short_name, priv->video_dev, priv->video_fd);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
956
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
957 /*
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
958 ** Query the video capabilities and current settings
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
959 ** for further control calls.
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
960 */
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
961 if (ioctl(priv->video_fd, VIDIOC_QUERYCAP, &priv->capability) < 0) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
962 mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl query capabilities failed: %s\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
963 info.short_name, strerror(errno));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
964 uninit(priv);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
965 return 0;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
966 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
967
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
968 if (!(priv->capability.capabilities & V4L2_CAP_VIDEO_CAPTURE))
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
969 {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
970 mp_msg(MSGT_TV, MSGL_ERR, "Device %s is not a video capture device.\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
971 priv->video_dev);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
972 return 0;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
973 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
974
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
975 if (getfmt(priv) < 0 || getstd(priv) < 0) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
976 uninit(priv);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
977 return 0;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
978 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
979 /*
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
980 ** if this device has got a tuner query it's settings
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
981 ** otherwise set some nice defaults
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
982 */
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
983 if (priv->capability.capabilities & V4L2_CAP_TUNER) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
984 if (ioctl(priv->video_fd, VIDIOC_G_TUNER, &priv->tuner) < 0) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
985 mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl get tuner failed: %s\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
986 info.short_name, strerror(errno));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
987 uninit(priv);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
988 return 0;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
989 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
990 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
991 mp_msg(MSGT_TV, MSGL_INFO, "Selected device: %s\n", priv->capability.card);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
992 if (priv->capability.capabilities & V4L2_CAP_TUNER) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
993 mp_msg(MSGT_TV, MSGL_INFO, " Tuner cap:%s%s%s\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
994 (priv->tuner.capability & V4L2_TUNER_CAP_STEREO) ? " STEREO" : "",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
995 (priv->tuner.capability & V4L2_TUNER_CAP_LANG1) ? " LANG1" : "",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
996 (priv->tuner.capability & V4L2_TUNER_CAP_LANG2) ? " LANG2" : "");
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
997 mp_msg(MSGT_TV, MSGL_INFO, " Tuner rxs:%s%s%s%s\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
998 (priv->tuner.rxsubchans & V4L2_TUNER_SUB_MONO) ? " MONO" : "",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
999 (priv->tuner.rxsubchans & V4L2_TUNER_SUB_STEREO) ? " STEREO" : "",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1000 (priv->tuner.rxsubchans & V4L2_TUNER_SUB_LANG1) ? " LANG1" : "",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1001 (priv->tuner.rxsubchans & V4L2_TUNER_SUB_LANG2) ? " LANG2" : "");
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1002 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1003 mp_msg(MSGT_TV, MSGL_INFO, " Capabilites:%s%s%s%s%s%s%s%s%s%s%s\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1004 priv->capability.capabilities & V4L2_CAP_VIDEO_CAPTURE?
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1005 " video capture": "",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1006 priv->capability.capabilities & V4L2_CAP_VIDEO_OUTPUT?
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1007 " video output": "",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1008 priv->capability.capabilities & V4L2_CAP_VIDEO_OVERLAY?
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1009 " video overlay": "",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1010 priv->capability.capabilities & V4L2_CAP_VBI_CAPTURE?
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1011 " VBI capture device": "",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1012 priv->capability.capabilities & V4L2_CAP_VBI_OUTPUT?
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1013 " VBI output": "",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1014 priv->capability.capabilities & V4L2_CAP_RDS_CAPTURE?
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1015 " RDS data capture": "",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1016 priv->capability.capabilities & V4L2_CAP_TUNER?
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1017 " tuner": "",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1018 priv->capability.capabilities & V4L2_CAP_AUDIO?
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1019 " audio": "",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1020 priv->capability.capabilities & V4L2_CAP_READWRITE?
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1021 " read/write": "",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1022 priv->capability.capabilities & V4L2_CAP_ASYNCIO?
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1023 " async i/o": "",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1024 priv->capability.capabilities & V4L2_CAP_STREAMING?
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1025 " streaming": "");
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1026 mp_msg(MSGT_TV, MSGL_INFO, " supported norms:");
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1027 for (i = 0;; i++) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1028 struct v4l2_standard standard;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1029 memset(&standard, 0, sizeof(standard));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1030 standard.index = i;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1031 if (-1 == ioctl(priv->video_fd, VIDIOC_ENUMSTD, &standard))
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1032 break;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1033 printf(" %d = %s;", i, standard.name);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1034 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1035 mp_msg(MSGT_TV, MSGL_INFO, "\n inputs:");
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1036 for (i = 0; 1; i++) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1037 struct v4l2_input input;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1038
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1039 input.index = i;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1040 if (ioctl(priv->video_fd, VIDIOC_ENUMINPUT, &input) < 0) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1041 break;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1042 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1043 mp_msg(MSGT_TV, MSGL_INFO, " %d = %s;", i, input.name);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1044 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1045 if (ioctl(priv->video_fd, VIDIOC_G_INPUT, &i) < 0) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1046 mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl get input failed: %s\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1047 info.short_name, strerror(errno));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1048 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1049 mp_msg(MSGT_TV, MSGL_INFO, "\n Current input: %d\n", i);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1050 for (i = 0; ; i++) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1051 struct v4l2_fmtdesc fmtdesc;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1052
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1053 fmtdesc.index = i;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1054 fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1055 if (ioctl(priv->video_fd, VIDIOC_ENUM_FMT, &fmtdesc) < 0) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1056 break;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1057 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1058 mp_msg(MSGT_TV, MSGL_V, " Format %-6s (%2d bits, %s): %s\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1059 pixfmt2name(fmtdesc.pixelformat), pixfmt2depth(fmtdesc.pixelformat),
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1060 fmtdesc.description, vo_format_name(fcc_vl2mp(fmtdesc.pixelformat)));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1061 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1062 mp_msg(MSGT_TV, MSGL_INFO, " Current format: %s\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1063 pixfmt2name(priv->format.fmt.pix.pixelformat));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1064
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1065 /* set some nice defaults */
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1066 if (getfmt(priv) < 0) return 0;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1067 priv->format.fmt.pix.width = 640;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1068 priv->format.fmt.pix.height = 480;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1069 if (ioctl(priv->video_fd, VIDIOC_S_FMT, &priv->format) < 0) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1070 mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl set format failed: %s\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1071 info.short_name, strerror(errno));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1072 uninit(priv);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1073 return 0;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1074 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1075
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1076 // if (!(priv->capability.capabilities & V4L2_CAP_AUDIO) && !tv_param_force_audio) tv_param_noaudio = 1;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1077
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1078 if (priv->capability.capabilities & V4L2_CAP_TUNER) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1079 struct v4l2_control control;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1080 if (tv_param_amode >= 0) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1081 mp_msg(MSGT_TV, MSGL_V, "%s: setting audio mode\n", info.short_name);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1082 priv->tuner.audmode = amode2v4l(tv_param_amode);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1083 if (ioctl(priv->video_fd, VIDIOC_S_TUNER, &priv->tuner) < 0) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1084 mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl set tuner failed: %s\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1085 info.short_name, strerror(errno));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1086 return TVI_CONTROL_FALSE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1087 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1088 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1089 mp_msg(MSGT_TV, MSGL_INFO, "%s: current audio mode is :%s%s%s%s\n", info.short_name,
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1090 (priv->tuner.audmode == V4L2_TUNER_MODE_MONO) ? " MONO" : "",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1091 (priv->tuner.audmode == V4L2_TUNER_MODE_STEREO) ? " STEREO" : "",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1092 (priv->tuner.audmode == V4L2_TUNER_MODE_LANG1) ? " LANG1" : "",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1093 (priv->tuner.audmode == V4L2_TUNER_MODE_LANG2) ? " LANG2" : "");
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1094
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1095 if (tv_param_volume >= 0) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1096 control.id = V4L2_CID_AUDIO_VOLUME;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1097 control.value = tv_param_volume;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1098 set_control(priv, &control, 0);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1099 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1100 if (tv_param_bass >= 0) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1101 control.id = V4L2_CID_AUDIO_BASS;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1102 control.value = tv_param_bass;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1103 set_control(priv, &control, 0);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1104 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1105 if (tv_param_treble >= 0) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1106 control.id = V4L2_CID_AUDIO_TREBLE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1107 control.value = tv_param_treble;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1108 set_control(priv, &control, 0);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1109 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1110 if (tv_param_balance >= 0) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1111 control.id = V4L2_CID_AUDIO_BALANCE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1112 control.value = tv_param_balance;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1113 set_control(priv, &control, 0);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1114 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1115 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1116
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1117 return 1;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1118 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1119
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1120 static int get_capture_buffer_size(priv_t *priv)
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1121 {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1122 int bufsize, cnt;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1123 int w = priv->format.fmt.pix.width;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1124 int h = priv->format.fmt.pix.height;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1125 int d = pixfmt2depth(priv->format.fmt.pix.pixelformat);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1126 int bytesperline = w*d/8;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1127
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1128 if (tv_param_buffer_size >= 0) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1129 bufsize = tv_param_buffer_size*1024*1024;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1130 } else {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1131 #ifdef HAVE_SYS_SYSINFO_H
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1132 struct sysinfo si;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1133
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1134 sysinfo(&si);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1135 if (si.totalram<2*1024*1024) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1136 bufsize = 1024*1024;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1137 } else {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1138 bufsize = si.totalram/2;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1139 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1140 #else
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1141 bufsize = 16*1024*1024;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1142 #endif
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1143 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1144
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1145 cnt = bufsize/(h*bytesperline);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1146 if (cnt < 2) cnt = 2;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1147
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1148 return cnt;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1149 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1150
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1151 /* that's the real start, we'got the format parameters (checked with control) */
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1152 static int start(priv_t *priv)
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1153 {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1154 struct v4l2_requestbuffers request;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1155 int i;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1156
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1157 /* setup audio parameters */
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1158
15464
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
1159 init_audio(priv);
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
1160 if (!tv_param_noaudio && !priv->audio_inited) return 0;
a57ec42d7df1 do not modify tv_param_noaudio
henry
parents: 15462
diff changeset
1161
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1162 /* we need this to size the audio buffer properly */
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1163 if (priv->immediate_mode) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1164 priv->video_buffer_size_max = 2;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1165 } else {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1166 priv->video_buffer_size_max = get_capture_buffer_size(priv);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1167 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1168
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1169 if (!tv_param_noaudio) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1170 setup_audio_buffer_sizes(priv);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1171 priv->audio_skew_buffer = (long long*)malloc(sizeof(long long)*priv->aud_skew_cnt);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1172 if (!priv->audio_skew_buffer) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1173 mp_msg(MSGT_TV, MSGL_ERR, "cannot allocate skew buffer: %s\n", strerror(errno));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1174 return 0;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1175 }
10653
d9dfbe5e1011 a/v sync improvements
henry
parents: 10538
diff changeset
1176 priv->audio_skew_delta_buffer = (long long*)malloc(sizeof(long long)*priv->aud_skew_cnt);
d9dfbe5e1011 a/v sync improvements
henry
parents: 10538
diff changeset
1177 if (!priv->audio_skew_delta_buffer) {
d9dfbe5e1011 a/v sync improvements
henry
parents: 10538
diff changeset
1178 mp_msg(MSGT_TV, MSGL_ERR, "cannot allocate skew buffer: %s\n", strerror(errno));
d9dfbe5e1011 a/v sync improvements
henry
parents: 10538
diff changeset
1179 return 0;
d9dfbe5e1011 a/v sync improvements
henry
parents: 10538
diff changeset
1180 }
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1181
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1182 priv->audio_ringbuffer = (unsigned char*)malloc(priv->audio_in.blocksize*priv->audio_buffer_size);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1183 if (!priv->audio_ringbuffer) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1184 mp_msg(MSGT_TV, MSGL_ERR, "cannot allocate audio buffer: %s\n", strerror(errno));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1185 return 0;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1186 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1187
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1188 priv->audio_secs_per_block = (double)priv->audio_in.blocksize/(priv->audio_in.samplerate
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1189 *priv->audio_in.channels
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1190 *priv->audio_in.bytes_per_sample);
15449
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1191 priv->audio_usecs_per_block = 1e6*priv->audio_secs_per_block;
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1192 priv->audio_head = 0;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1193 priv->audio_tail = 0;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1194 priv->audio_cnt = 0;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1195 priv->audio_drop = 0;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1196 priv->audio_skew = 0;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1197 priv->audio_skew_total = 0;
10653
d9dfbe5e1011 a/v sync improvements
henry
parents: 10538
diff changeset
1198 priv->audio_skew_delta_total = 0;
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1199 priv->audio_recv_blocks_total = 0;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1200 priv->audio_sent_blocks_total = 0;
15449
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1201 priv->audio_null_blocks_inserted = 0;
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1202 priv->audio_insert_null_samples = 0;
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1203 priv->dropped_frames_timeshift = 0;
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1204 priv->dropped_frames_compensated = 0;
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1205
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1206 pthread_mutex_init(&priv->skew_mutex, NULL);
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1207 pthread_mutex_init(&priv->audio_mutex, NULL);
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1208 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1209
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1210 /* setup video parameters */
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1211 if (!tv_param_noaudio) {
16289
cafa391ff89c mode fps int vs. float woes
henry
parents: 16274
diff changeset
1212 if (priv->video_buffer_size_max < (3*priv->standard.frameperiod.denominator) /
cafa391ff89c mode fps int vs. float woes
henry
parents: 16274
diff changeset
1213 priv->standard.frameperiod.numerator
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1214 *priv->audio_secs_per_block) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1215 mp_msg(MSGT_TV, MSGL_ERR, "Video buffer shorter than 3 times audio frame duration.\n"
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1216 "You will probably experience heavy framedrops.\n");
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1217 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1218 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1219
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1220 {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1221 int bytesperline = priv->format.fmt.pix.width*pixfmt2depth(priv->format.fmt.pix.pixelformat)/8;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1222
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1223 mp_msg(MSGT_TV, MSGL_V, "Using a ring buffer for maximum %d frames, %d MB total size.\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1224 priv->video_buffer_size_max,
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1225 priv->video_buffer_size_max*priv->format.fmt.pix.height*bytesperline/(1024*1024));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1226 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1227
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1228 priv->video_ringbuffer = (unsigned char**)malloc(priv->video_buffer_size_max*sizeof(unsigned char*));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1229 if (!priv->video_ringbuffer) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1230 mp_msg(MSGT_TV, MSGL_ERR, "cannot allocate video buffer: %s\n", strerror(errno));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1231 return 0;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1232 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1233 for (i = 0; i < priv->video_buffer_size_max; i++)
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1234 priv->video_ringbuffer[i] = NULL;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1235 priv->video_timebuffer = (long long*)malloc(sizeof(long long) * priv->video_buffer_size_max);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1236 if (!priv->video_timebuffer) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1237 mp_msg(MSGT_TV, MSGL_ERR, "cannot allocate time buffer: %s\n", strerror(errno));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1238 return 0;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1239 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1240
15449
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1241 pthread_mutex_init(&priv->video_buffer_mutex, NULL);
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1242
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1243 priv->video_head = 0;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1244 priv->video_tail = 0;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1245 priv->video_cnt = 0;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1246
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1247 /* request buffers */
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1248 if (priv->immediate_mode) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1249 request.count = 2;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1250 } else {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1251 request.count = BUFFER_COUNT;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1252 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1253
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1254 request.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1255 request.memory = V4L2_MEMORY_MMAP;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1256 if (ioctl(priv->video_fd, VIDIOC_REQBUFS, &request) < 0) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1257 mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl request buffers failed: %s\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1258 info.short_name, strerror(errno));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1259 return 0;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1260 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1261
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1262 /* query buffers */
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1263 if (!(priv->map = malloc(sizeof(struct map) * request.count))) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1264 mp_msg(MSGT_TV, MSGL_ERR, "%s: malloc capture buffers failed: %s\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1265 info.short_name, strerror(errno));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1266 return 0;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1267 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1268
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1269 /* map and queue buffers */
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1270 for (i = 0; i < request.count; i++) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1271 memset(&priv->map[i].buf,0,sizeof(priv->map[i].buf));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1272 priv->map[i].buf.index = i;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1273 priv->map[i].buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1274 priv->map[i].buf.memory = V4L2_MEMORY_MMAP;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1275 if (ioctl(priv->video_fd, VIDIOC_QUERYBUF, &(priv->map[i].buf)) < 0) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1276 mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl query buffer failed: %s\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1277 info.short_name, strerror(errno));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1278 free(priv->map);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1279 priv->map = NULL;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1280 return 0;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1281 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1282 priv->map[i].addr = mmap (0, priv->map[i].buf.length, PROT_READ |
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1283 PROT_WRITE, MAP_SHARED, priv->video_fd, priv->map[i].buf.m.offset);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1284 if (priv->map[i].addr == MAP_FAILED) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1285 mp_msg(MSGT_TV, MSGL_ERR, "%s: mmap capture buffer failed: %s\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1286 info.short_name, strerror(errno));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1287 priv->map[i].len = 0;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1288 return 0;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1289 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1290 priv->map[i].len = priv->map[i].buf.length;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1291 /* count up to make sure this is correct everytime */
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1292 priv->mapcount++;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1293
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1294 if (ioctl(priv->video_fd, VIDIOC_QBUF, &(priv->map[i].buf)) < 0) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1295 mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl queue buffer failed: %s\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1296 info.short_name, strerror(errno));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1297 return 0;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1298 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1299 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1300
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1301 /* start audio thread */
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1302 priv->shutdown = 0;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1303 priv->audio_skew_measure_time = 0;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1304 priv->first_frame = 0;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1305 priv->audio_skew = 0;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1306 priv->first = 1;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1307
17626
5627625b0cdb Don't test the v4l2_input audioset field for audio capabilities but still try changing the mute setting (patch by Jesse Allen < the3dfxdude _at_ gmail.com >)
aurel
parents: 17199
diff changeset
1308 set_mute(priv, 0);
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1309
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1310 return 1;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1311 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1312
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1313
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1314 #ifdef HAVE_TV_BSDBT848
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1315 static double grabimmediate_video_frame(priv_t *priv, char *buffer, int len)
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1316 {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1317 memset(buffer, 0xCC, len);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1318 return(1);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1319 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1320 #endif /* HAVE_TV_BSDBT848 */
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1321
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1322 // copies a video frame
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1323 static inline void copy_frame(priv_t *priv, unsigned char *dest, unsigned char *source)
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1324 {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1325 int w = priv->format.fmt.pix.width;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1326 int h = priv->format.fmt.pix.height;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1327 int d = pixfmt2depth(priv->format.fmt.pix.pixelformat);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1328 int bytesperline = w*d/8;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1329
17199
9164ef9a1834 remove now useless YV12 plane swap hack, patch by Luc Gallant lucgallant at gmail com
henry
parents: 17012
diff changeset
1330 memcpy(dest, source, bytesperline * h);
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1331 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1332
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1333 // maximum skew change, in frames
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1334 #define MAX_SKEW_DELTA 0.6
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1335 static void *video_grabber(void *data)
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1336 {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1337 priv_t *priv = (priv_t*)data;
15449
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1338 long long skew, prev_skew, xskew, interval, prev_interval, delta;
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1339 int i;
16962
bdc218b5a49a Do not hang forever when the card delivers no new data.
reimar
parents: 16536
diff changeset
1340 int err_count = 0;
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1341 int framesize = priv->format.fmt.pix.height*priv->format.fmt.pix.width*
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1342 pixfmt2depth(priv->format.fmt.pix.pixelformat)/8;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1343 fd_set rdset;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1344 struct timeval timeout;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1345 struct v4l2_buffer buf;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1346
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1347 xskew = 0;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1348 skew = 0;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1349 interval = 0;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1350 prev_interval = 0;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1351 prev_skew = 0;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1352
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1353 mp_msg(MSGT_TV, MSGL_V, "%s: going to capture\n", info.short_name);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1354 if (ioctl(priv->video_fd, VIDIOC_STREAMON, &(priv->format.type)) < 0) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1355 mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl streamon failed: %s\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1356 info.short_name, strerror(errno));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1357 return 0;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1358 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1359 priv->streamon = 1;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1360
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1361 if (!tv_param_noaudio) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1362 pthread_create(&priv->audio_grabber_thread, NULL, audio_grabber, priv);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1363 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1364
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1365 for (priv->frames = 0; !priv->shutdown;)
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1366 {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1367 int ret;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1368
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1369 if (priv->immediate_mode) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1370 while (priv->video_cnt == priv->video_buffer_size_max) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1371 usleep(10000);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1372 if (priv->shutdown) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1373 return NULL;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1374 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1375 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1376 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1377
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1378 FD_ZERO (&rdset);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1379 FD_SET (priv->video_fd, &rdset);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1380
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1381 timeout.tv_sec = 1;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1382 timeout.tv_usec = 0;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1383
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1384 i = select(priv->video_fd + 1, &rdset, NULL, NULL, &timeout);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1385 if (i < 0) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1386 mp_msg(MSGT_TV, MSGL_ERR, "%s: select failed: %s\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1387 info.short_name, strerror(errno));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1388 continue;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1389 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1390 else if (i == 0) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1391 mp_msg(MSGT_TV, MSGL_ERR, "%s: select timeout\n", info.short_name);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1392 continue;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1393 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1394 else if (!FD_ISSET(priv->video_fd, &rdset)) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1395 continue;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1396 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1397
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1398 memset(&buf,0,sizeof(buf));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1399 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1400 ret = ioctl(priv->video_fd, VIDIOC_DQBUF, &buf);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1401
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1402 if (ret < 0) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1403 /*
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1404 if there's no signal, the buffer might me dequeued
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1405 so we query all the buffers to see which one we should
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1406 put back to queue
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1407
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1408 observed with saa7134 0.2.8
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1409 don't know if is it a bug or (mis)feature
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1410 */
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1411 mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl dequeue buffer failed: %s, idx = %d\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1412 info.short_name, strerror(errno), buf.index);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1413 for (i = 0; i < priv->mapcount; i++) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1414 memset(&buf,0,sizeof(buf));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1415 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1416 buf.index = i;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1417 ret = ioctl(priv->video_fd, VIDIOC_QUERYBUF, &buf);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1418 if (ret < 0) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1419 mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl query buffer failed: %s, idx = %d\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1420 info.short_name, strerror(errno), buf.index);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1421 return 0;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1422 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1423 if ((buf.flags & (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_DONE)) == V4L2_BUF_FLAG_MAPPED) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1424 if (ioctl(priv->video_fd, VIDIOC_QBUF, &(priv->map[i].buf)) < 0) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1425 mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl queue buffer failed: %s\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1426 info.short_name, strerror(errno));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1427 return 0;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1428 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1429 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1430 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1431 continue;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1432 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1433
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1434 /* store the timestamp of the very first frame as reference */
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1435 if (!priv->frames++) {
15462
74813a319929 cleanups of the mutex usage
henry
parents: 15451
diff changeset
1436 if (!tv_param_noaudio) pthread_mutex_lock(&priv->skew_mutex);
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1437 priv->first_frame = (long long)1e6*buf.timestamp.tv_sec + buf.timestamp.tv_usec;
15462
74813a319929 cleanups of the mutex usage
henry
parents: 15451
diff changeset
1438 if (!tv_param_noaudio) pthread_mutex_unlock(&priv->skew_mutex);
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1439 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1440 priv->curr_frame = (long long)buf.timestamp.tv_sec*1e6+buf.timestamp.tv_usec;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1441 // fprintf(stderr, "idx = %d, ts = %lf\n", buf.index, (double)(priv->curr_frame) / 1e6);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1442
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1443 interval = priv->curr_frame - priv->first_frame;
15449
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1444 delta = interval - prev_interval;
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1445
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1446 if (!priv->immediate_mode) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1447 // interpolate the skew in time
15462
74813a319929 cleanups of the mutex usage
henry
parents: 15451
diff changeset
1448 if (!tv_param_noaudio) pthread_mutex_lock(&priv->skew_mutex);
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1449 xskew = priv->audio_skew + (interval - priv->audio_skew_measure_time)*priv->audio_skew_factor;
15462
74813a319929 cleanups of the mutex usage
henry
parents: 15451
diff changeset
1450 if (!tv_param_noaudio) pthread_mutex_unlock(&priv->skew_mutex);
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1451 // correct extreme skew changes to avoid (especially) moving backwards in time
15449
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1452 if (xskew - prev_skew > delta*MAX_SKEW_DELTA) {
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1453 skew = prev_skew + delta*MAX_SKEW_DELTA;
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1454 } else if (xskew - prev_skew < -delta*MAX_SKEW_DELTA) {
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1455 skew = prev_skew - delta*MAX_SKEW_DELTA;
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1456 } else {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1457 skew = xskew;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1458 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1459 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1460
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1461 mp_msg(MSGT_TV, MSGL_DBG3, "\nfps = %lf, interval = %lf, a_skew = %f, corr_skew = %f\n",
15449
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1462 delta ? (double)1e6/delta : -1,
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1463 (double)1e-6*interval, (double)1e-6*xskew, (double)1e-6*skew);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1464 mp_msg(MSGT_TV, MSGL_DBG3, "vcnt = %d, acnt = %d\n", priv->video_cnt, priv->audio_cnt);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1465
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1466 prev_skew = skew;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1467 prev_interval = interval;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1468
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1469 /* allocate a new buffer, if needed */
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1470 pthread_mutex_lock(&priv->video_buffer_mutex);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1471 if (priv->video_buffer_size_current < priv->video_buffer_size_max) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1472 if (priv->video_cnt == priv->video_buffer_size_current) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1473 unsigned char *newbuf = (unsigned char*)malloc(framesize);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1474 if (newbuf) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1475 memmove(priv->video_ringbuffer+priv->video_tail+1, priv->video_ringbuffer+priv->video_tail,
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1476 (priv->video_buffer_size_current-priv->video_tail)*sizeof(unsigned char *));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1477 memmove(priv->video_timebuffer+priv->video_tail+1, priv->video_timebuffer+priv->video_tail,
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1478 (priv->video_buffer_size_current-priv->video_tail)*sizeof(long long));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1479 priv->video_ringbuffer[priv->video_tail] = newbuf;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1480 if ((priv->video_head >= priv->video_tail) && (priv->video_cnt > 0)) priv->video_head++;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1481 priv->video_buffer_size_current++;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1482 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1483 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1484 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1485 pthread_mutex_unlock(&priv->video_buffer_mutex);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1486
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1487 if (priv->video_cnt == priv->video_buffer_size_current) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1488 if (!priv->immediate_mode) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1489 mp_msg(MSGT_TV, MSGL_ERR, "\nvideo buffer full - dropping frame\n");
15449
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1490 if (priv->audio_insert_null_samples) {
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1491 pthread_mutex_lock(&priv->audio_mutex);
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1492 priv->dropped_frames_timeshift += delta;
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1493 pthread_mutex_unlock(&priv->audio_mutex);
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1494 }
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1495 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1496 } else {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1497 if (priv->immediate_mode) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1498 priv->video_timebuffer[priv->video_tail] = 0;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1499 } else {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1500 // compensate for audio skew
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1501 // negative skew => there are more audio samples, increase interval
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1502 // positive skew => less samples, shorten the interval
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1503 priv->video_timebuffer[priv->video_tail] = interval - skew;
15449
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1504 if (priv->audio_insert_null_samples && priv->video_timebuffer[priv->video_tail] > 0) {
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1505 pthread_mutex_lock(&priv->audio_mutex);
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1506 priv->video_timebuffer[priv->video_tail] +=
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1507 (priv->audio_null_blocks_inserted
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1508 - priv->dropped_frames_timeshift/priv->audio_usecs_per_block)
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1509 *priv->audio_usecs_per_block;
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1510 pthread_mutex_unlock(&priv->audio_mutex);
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1511 }
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1512 }
15449
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1513
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1514 copy_frame(priv, priv->video_ringbuffer[priv->video_tail], priv->map[buf.index].addr);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1515 priv->video_tail = (priv->video_tail+1)%priv->video_buffer_size_current;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1516 priv->video_cnt++;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1517 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1518 if (ioctl(priv->video_fd, VIDIOC_QBUF, &buf) < 0) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1519 mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl queue buffer failed: %s\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1520 info.short_name, strerror(errno));
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1521 return 0;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1522 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1523 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1524 return NULL;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1525 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1526
16962
bdc218b5a49a Do not hang forever when the card delivers no new data.
reimar
parents: 16536
diff changeset
1527 #define MAX_LOOP 50
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1528 static double grab_video_frame(priv_t *priv, char *buffer, int len)
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1529 {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1530 double interval;
16962
bdc218b5a49a Do not hang forever when the card delivers no new data.
reimar
parents: 16536
diff changeset
1531 int loop_cnt = 0;
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1532
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1533 if (priv->first) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1534 pthread_create(&priv->video_grabber_thread, NULL, video_grabber, priv);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1535 priv->first = 0;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1536 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1537
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1538 while (priv->video_cnt == 0) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1539 usleep(10000);
16962
bdc218b5a49a Do not hang forever when the card delivers no new data.
reimar
parents: 16536
diff changeset
1540 if (loop_cnt++ > MAX_LOOP) return 0;
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1541 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1542
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1543 pthread_mutex_lock(&priv->video_buffer_mutex);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1544 interval = (double)priv->video_timebuffer[priv->video_head]*1e-6;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1545 memcpy(buffer, priv->video_ringbuffer[priv->video_head], len);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1546 priv->video_cnt--;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1547 priv->video_head = (priv->video_head+1)%priv->video_buffer_size_current;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1548 pthread_mutex_unlock(&priv->video_buffer_mutex);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1549
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1550 return interval;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1551 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1552
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1553 static int get_video_framesize(priv_t *priv)
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1554 {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1555 return priv->format.fmt.pix.sizeimage;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1556 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1557
10704
1d991eb5cf02 a/v sync cleanups
henry
parents: 10653
diff changeset
1558 //#define DOUBLESPEED
1d991eb5cf02 a/v sync cleanups
henry
parents: 10653
diff changeset
1559 #ifdef DOUBLESPEED
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1560 // for testing purposes only
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1561 static void read_doublespeed(priv_t *priv)
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1562 {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1563 char *bufx = (char*)malloc(priv->audio_in.blocksize*2);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1564 short *s;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1565 short *d;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1566 int i;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1567
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1568 audio_in_read_chunk(&priv->audio_in, bufx);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1569 audio_in_read_chunk(&priv->audio_in, bufx+priv->audio_in.blocksize);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1570
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1571 s = bufx;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1572 d = priv->audio_ringbuffer+priv->audio_tail*priv->audio_in.blocksize;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1573 for (i = 0; i < priv->audio_in.blocksize/2; i++) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1574 *d++ = *s++;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1575 *s++;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1576 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1577
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1578 }
10704
1d991eb5cf02 a/v sync cleanups
henry
parents: 10653
diff changeset
1579 #endif
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1580
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1581 static void *audio_grabber(void *data)
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1582 {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1583 priv_t *priv = (priv_t*)data;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1584 struct timeval tv;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1585 int i, audio_skew_ptr = 0;
10653
d9dfbe5e1011 a/v sync improvements
henry
parents: 10538
diff changeset
1586 long long current_time, prev_skew = 0, prev_skew_uncorr = 0;
10852
henry
parents: 10851
diff changeset
1587 long long start_time_avg;
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1588
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1589 gettimeofday(&tv, NULL);
10852
henry
parents: 10851
diff changeset
1590 start_time_avg = priv->audio_start_time = (long long)1e6*tv.tv_sec + tv.tv_usec;
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1591 audio_in_start_capture(&priv->audio_in);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1592 for (i = 0; i < priv->aud_skew_cnt; i++)
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1593 priv->audio_skew_buffer[i] = 0;
10653
d9dfbe5e1011 a/v sync improvements
henry
parents: 10538
diff changeset
1594 for (i = 0; i < priv->aud_skew_cnt; i++)
d9dfbe5e1011 a/v sync improvements
henry
parents: 10538
diff changeset
1595 priv->audio_skew_delta_buffer[i] = 0;
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1596
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1597 for (; !priv->shutdown;)
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1598 {
10704
1d991eb5cf02 a/v sync cleanups
henry
parents: 10653
diff changeset
1599 #ifdef DOUBLESPEED
1d991eb5cf02 a/v sync cleanups
henry
parents: 10653
diff changeset
1600 read_doublespeed(priv);
1d991eb5cf02 a/v sync cleanups
henry
parents: 10653
diff changeset
1601 #else
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1602 if (audio_in_read_chunk(&priv->audio_in, priv->audio_ringbuffer+priv->audio_tail*priv->audio_in.blocksize) < 0)
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1603 continue;
10704
1d991eb5cf02 a/v sync cleanups
henry
parents: 10653
diff changeset
1604 #endif
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1605 pthread_mutex_lock(&priv->skew_mutex);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1606 if (priv->first_frame == 0) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1607 // there is no first frame yet (unlikely to happen)
10810
d0aaa6bf3def 10l - forgotten gettimeofday
henry
parents: 10776
diff changeset
1608 gettimeofday(&tv, NULL);
10852
henry
parents: 10851
diff changeset
1609 start_time_avg = priv->audio_start_time = (long long)1e6*tv.tv_sec + tv.tv_usec;
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1610 // fprintf(stderr, "warning - first frame not yet available!\n");
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1611 pthread_mutex_unlock(&priv->skew_mutex);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1612 continue;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1613 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1614 pthread_mutex_unlock(&priv->skew_mutex);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1615
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1616 gettimeofday(&tv, NULL);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1617
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1618 priv->audio_recv_blocks_total++;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1619 current_time = (long long)1e6*tv.tv_sec + tv.tv_usec - priv->audio_start_time;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1620
10852
henry
parents: 10851
diff changeset
1621 if (priv->audio_recv_blocks_total < priv->aud_skew_cnt*2) {
15449
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1622 start_time_avg += (long long)1e6*tv.tv_sec + tv.tv_usec - priv->audio_usecs_per_block*priv->audio_recv_blocks_total;
10852
henry
parents: 10851
diff changeset
1623 priv->audio_start_time = start_time_avg/(priv->audio_recv_blocks_total+1);
henry
parents: 10851
diff changeset
1624 }
henry
parents: 10851
diff changeset
1625
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1626 // fprintf(stderr, "spb = %lf, bs = %d, skew = %lf\n", priv->audio_secs_per_block, priv->audio_in.blocksize,
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1627 // (double)(current_time - 1e6*priv->audio_secs_per_block*priv->audio_recv_blocks_total)/1e6);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1628
10704
1d991eb5cf02 a/v sync cleanups
henry
parents: 10653
diff changeset
1629 // put the current skew into the ring buffer
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1630 priv->audio_skew_total -= priv->audio_skew_buffer[audio_skew_ptr];
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1631 priv->audio_skew_buffer[audio_skew_ptr] = current_time
15449
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1632 - priv->audio_usecs_per_block*priv->audio_recv_blocks_total;
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1633 priv->audio_skew_total += priv->audio_skew_buffer[audio_skew_ptr];
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1634
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1635 pthread_mutex_lock(&priv->skew_mutex);
10704
1d991eb5cf02 a/v sync cleanups
henry
parents: 10653
diff changeset
1636
1d991eb5cf02 a/v sync cleanups
henry
parents: 10653
diff changeset
1637 // skew calculation
1d991eb5cf02 a/v sync cleanups
henry
parents: 10653
diff changeset
1638
1d991eb5cf02 a/v sync cleanups
henry
parents: 10653
diff changeset
1639 // compute the sliding average of the skews
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1640 if (priv->audio_recv_blocks_total > priv->aud_skew_cnt) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1641 priv->audio_skew = priv->audio_skew_total/priv->aud_skew_cnt;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1642 } else {
10704
1d991eb5cf02 a/v sync cleanups
henry
parents: 10653
diff changeset
1643 priv->audio_skew = priv->audio_skew_total/priv->audio_recv_blocks_total;
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1644 }
10653
d9dfbe5e1011 a/v sync improvements
henry
parents: 10538
diff changeset
1645
10704
1d991eb5cf02 a/v sync cleanups
henry
parents: 10653
diff changeset
1646 // put the current skew change (skew-prev_skew) into the ring buffer
10653
d9dfbe5e1011 a/v sync improvements
henry
parents: 10538
diff changeset
1647 priv->audio_skew_delta_total -= priv->audio_skew_delta_buffer[audio_skew_ptr];
d9dfbe5e1011 a/v sync improvements
henry
parents: 10538
diff changeset
1648 priv->audio_skew_delta_buffer[audio_skew_ptr] = priv->audio_skew - prev_skew_uncorr;
d9dfbe5e1011 a/v sync improvements
henry
parents: 10538
diff changeset
1649 priv->audio_skew_delta_total += priv->audio_skew_delta_buffer[audio_skew_ptr];
10704
1d991eb5cf02 a/v sync cleanups
henry
parents: 10653
diff changeset
1650 prev_skew_uncorr = priv->audio_skew; // remember the _uncorrected_ average value
1d991eb5cf02 a/v sync cleanups
henry
parents: 10653
diff changeset
1651
1d991eb5cf02 a/v sync cleanups
henry
parents: 10653
diff changeset
1652 audio_skew_ptr = (audio_skew_ptr+1) % priv->aud_skew_cnt; // rotate the buffer pointer
10653
d9dfbe5e1011 a/v sync improvements
henry
parents: 10538
diff changeset
1653
10704
1d991eb5cf02 a/v sync cleanups
henry
parents: 10653
diff changeset
1654 // sliding average approximates the value in the middle of the interval
1d991eb5cf02 a/v sync cleanups
henry
parents: 10653
diff changeset
1655 // so interpolate the skew value further to the current time
1d991eb5cf02 a/v sync cleanups
henry
parents: 10653
diff changeset
1656 priv->audio_skew += priv->audio_skew_delta_total/2;
10653
d9dfbe5e1011 a/v sync improvements
henry
parents: 10538
diff changeset
1657
10704
1d991eb5cf02 a/v sync cleanups
henry
parents: 10653
diff changeset
1658 // now finally, priv->audio_skew contains fairly good approximation
1d991eb5cf02 a/v sync cleanups
henry
parents: 10653
diff changeset
1659 // of the current value
10653
d9dfbe5e1011 a/v sync improvements
henry
parents: 10538
diff changeset
1660
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1661 // current skew factor (assuming linearity)
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1662 // used for further interpolation in video_grabber
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1663 // probably overkill but seems to be necessary for
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1664 // stress testing by dropping half of the audio frames ;)
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1665 // especially when using ALSA with large block sizes
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1666 // where audio_skew remains a long while behind
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1667 if ((priv->audio_skew_measure_time != 0) && (current_time - priv->audio_skew_measure_time != 0)) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1668 priv->audio_skew_factor = (double)(priv->audio_skew-prev_skew)/(current_time - priv->audio_skew_measure_time);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1669 } else {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1670 priv->audio_skew_factor = 0.0;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1671 }
10852
henry
parents: 10851
diff changeset
1672
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1673 priv->audio_skew_measure_time = current_time;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1674 prev_skew = priv->audio_skew;
10852
henry
parents: 10851
diff changeset
1675 priv->audio_skew += priv->audio_start_time - priv->first_frame;
henry
parents: 10851
diff changeset
1676 pthread_mutex_unlock(&priv->skew_mutex);
henry
parents: 10851
diff changeset
1677
henry
parents: 10851
diff changeset
1678 // fprintf(stderr, "audio_skew = %lf, delta = %lf\n", (double)priv->audio_skew/1e6, (double)priv->audio_skew_delta_total/1e6);
10851
41bad7ce4cc9 yet another sync fix
henry
parents: 10810
diff changeset
1679
15449
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1680 pthread_mutex_lock(&priv->audio_mutex);
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1681 if ((priv->audio_tail+1) % priv->audio_buffer_size == priv->audio_head) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1682 mp_msg(MSGT_TV, MSGL_ERR, "\ntoo bad - dropping audio frame !\n");
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1683 priv->audio_drop++;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1684 } else {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1685 priv->audio_tail = (priv->audio_tail+1) % priv->audio_buffer_size;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1686 priv->audio_cnt++;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1687 }
15449
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1688 pthread_mutex_unlock(&priv->audio_mutex);
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1689 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1690 return NULL;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1691 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1692
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1693 static double grab_audio_frame(priv_t *priv, char *buffer, int len)
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1694 {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1695 mp_dbg(MSGT_TV, MSGL_DBG2, "grab_audio_frame(priv=%p, buffer=%p, len=%d)\n",
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1696 priv, buffer, len);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1697
15449
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1698 // hack: if grab_audio_frame is called first, it means we are used by mplayer
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1699 // => switch to the mode which outputs audio immediately, even if
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1700 // it should be silence
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1701 if (priv->first) priv->audio_insert_null_samples = 1;
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1702
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1703 pthread_mutex_lock(&priv->audio_mutex);
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1704 while (priv->audio_insert_null_samples
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1705 && priv->dropped_frames_timeshift - priv->dropped_frames_compensated >= priv->audio_usecs_per_block) {
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1706 // some frames were dropped - drop the corresponding number of audio blocks
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1707 if (priv->audio_drop) {
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1708 priv->audio_drop--;
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1709 } else {
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1710 if (priv->audio_head == priv->audio_tail) break;
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1711 priv->audio_head = (priv->audio_head+1) % priv->audio_buffer_size;
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1712 }
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1713 priv->dropped_frames_compensated += priv->audio_usecs_per_block;
10776
80402283a017 Fix immediatemode with mplayer (ie playing both sound and video)
albeu
parents: 10735
diff changeset
1714 }
80402283a017 Fix immediatemode with mplayer (ie playing both sound and video)
albeu
parents: 10735
diff changeset
1715
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1716 // compensate for dropped audio frames
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1717 if (priv->audio_drop && (priv->audio_head == priv->audio_tail)) {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1718 priv->audio_drop--;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1719 memset(buffer, 0, len);
15449
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1720 goto out;
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1721 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1722
15449
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1723 if (priv->audio_insert_null_samples && (priv->audio_head == priv->audio_tail)) {
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1724 // return silence to avoid desync and stuttering
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1725 memset(buffer, 0, len);
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1726 priv->audio_null_blocks_inserted++;
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1727 goto out;
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1728 }
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1729
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1730 pthread_mutex_unlock(&priv->audio_mutex);
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1731 while (priv->audio_head == priv->audio_tail) {
15449
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1732 // this is mencoder => just wait until some audio is available
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1733 usleep(10000);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1734 }
15451
bad4378c5456 10l forgotten comment
henry
parents: 15449
diff changeset
1735 pthread_mutex_lock(&priv->audio_mutex);
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1736 memcpy(buffer, priv->audio_ringbuffer+priv->audio_head*priv->audio_in.blocksize, len);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1737 priv->audio_head = (priv->audio_head+1) % priv->audio_buffer_size;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1738 priv->audio_cnt--;
15449
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1739 out:
a7966365a197 improve playback with mplayer -tv immediatemode=0
henry
parents: 15418
diff changeset
1740 pthread_mutex_unlock(&priv->audio_mutex);
10536
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1741 priv->audio_sent_blocks_total++;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1742 return (double)priv->audio_sent_blocks_total*priv->audio_secs_per_block;
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1743 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1744
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1745 static int get_audio_framesize(priv_t *priv)
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1746 {
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1747 return(priv->audio_in.blocksize);
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1748 }
527e978cb0f8 v4l2 support
henry
parents:
diff changeset
1749
10538
dd2572331142 10l - some forgotten ifdefs
henry
parents: 10536
diff changeset
1750 #endif /* USE_TV && HAVE_TV_V4L2 */