1 /*****************************************************************************
2 * v4l2.c : Video4Linux2 input module for vlc
3 *****************************************************************************
4 * Copyright (C) 2002-2009 the VideoLAN team
7 * Authors: Benjamin Pracht <bigben at videolan dot org>
8 * Richard Hosking <richard at hovis dot net>
9 * Antoine Cellerier <dionoea at videolan d.t org>
10 * Dennis Lou <dlou99 at yahoo dot com>
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
25 *****************************************************************************/
28 * Sections based on the reference V4L2 capture example at
29 * http://v4l2spec.bytesex.org/spec/capture-example.html
32 /*****************************************************************************
34 *****************************************************************************/
40 #include <vlc_common.h>
41 #include <vlc_plugin.h>
42 #include <vlc_access.h>
43 #include <vlc_charset.h>
45 #include <vlc_demux.h>
46 #include <vlc_input.h>
51 #include <sys/ioctl.h>
54 #if defined(HAVE_LINUX_VIDEODEV2_H)
55 # include <linux/videodev2.h>
56 #elif defined(HAVE_SYS_VIDEOIO_H)
57 # include <sys/videoio.h>
59 # error "No Video4Linux2 headers found."
68 /*****************************************************************************
70 *****************************************************************************/
72 static int DemuxOpen ( vlc_object_t
* );
73 static void DemuxClose( vlc_object_t
* );
74 static int AccessOpen ( vlc_object_t
* );
75 static void AccessClose( vlc_object_t
* );
77 #define STANDARD_TEXT N_( "Standard" )
78 #define STANDARD_LONGTEXT N_( \
79 "Video standard (Default, SECAM, PAL, or NTSC)." )
80 #define CHROMA_TEXT N_("Video input chroma format")
81 #define CHROMA_LONGTEXT N_( \
82 "Force the Video4Linux2 video device to use a specific chroma format " \
83 "(eg. I420 or I422 for raw images, MJPG for M-JPEG compressed input) " \
84 "(Complete list: GREY, I240, RV16, RV15, RV24, RV32, YUY2, YUYV, UYVY, " \
85 "I41N, I422, I420, I411, I410, MJPG)")
86 #define INPUT_TEXT N_( "Input" )
87 #define INPUT_LONGTEXT N_( \
88 "Input of the card to use (see debug)." )
89 #define AUDIO_INPUT_TEXT N_( "Audio input" )
90 #define AUDIO_INPUT_LONGTEXT N_( \
91 "Audio input of the card to use (see debug)." )
92 #define IOMETHOD_TEXT N_( "IO Method" )
93 #define IOMETHOD_LONGTEXT N_( \
94 "IO Method (READ, MMAP, USERPTR)." )
95 #define WIDTH_TEXT N_( "Width" )
96 #define WIDTH_LONGTEXT N_( \
97 "Force width (-1 for autodetect, 0 for driver default)." )
98 #define HEIGHT_TEXT N_( "Height" )
99 #define HEIGHT_LONGTEXT N_( \
100 "Force height (-1 for autodetect, 0 for driver default)." )
101 #define FPS_TEXT N_( "Framerate" )
102 #define FPS_LONGTEXT N_( "Framerate to capture, if applicable " \
103 "(0 for autodetect)." )
106 #define LIBV4L2_TEXT N_( "Use libv4l2" )
107 #define LIBV4L2_LONGTEXT N_( \
108 "Force usage of the libv4l2 wrapper." )
111 #define CTRL_RESET_TEXT N_( "Reset v4l2 controls" )
112 #define CTRL_RESET_LONGTEXT N_( \
113 "Reset controls to defaults provided by the v4l2 driver." )
114 #define BRIGHTNESS_TEXT N_( "Brightness" )
115 #define BRIGHTNESS_LONGTEXT N_( \
116 "Brightness of the video input (if supported by the v4l2 driver)." )
117 #define CONTRAST_TEXT N_( "Contrast" )
118 #define CONTRAST_LONGTEXT N_( \
119 "Contrast of the video input (if supported by the v4l2 driver)." )
120 #define SATURATION_TEXT N_( "Saturation" )
121 #define SATURATION_LONGTEXT N_( \
122 "Saturation of the video input (if supported by the v4l2 driver)." )
123 #define HUE_TEXT N_( "Hue" )
124 #define HUE_LONGTEXT N_( \
125 "Hue of the video input (if supported by the v4l2 driver)." )
126 #define BLACKLEVEL_TEXT N_( "Black level" )
127 #define BLACKLEVEL_LONGTEXT N_( \
128 "Black level of the video input (if supported by the v4l2 driver)." )
129 #define AUTOWHITEBALANCE_TEXT N_( "Auto white balance" )
130 #define AUTOWHITEBALANCE_LONGTEXT N_( \
131 "Automatically set the white balance of the video input " \
132 "(if supported by the v4l2 driver)." )
133 #define DOWHITEBALANCE_TEXT N_( "Do white balance" )
134 #define DOWHITEBALANCE_LONGTEXT N_( \
135 "Trigger a white balancing action, useless if auto white balance is " \
136 "activated (if supported by the v4l2 driver)." )
137 #define REDBALANCE_TEXT N_( "Red balance" )
138 #define REDBALANCE_LONGTEXT N_( \
139 "Red balance of the video input (if supported by the v4l2 driver)." )
140 #define BLUEBALANCE_TEXT N_( "Blue balance" )
141 #define BLUEBALANCE_LONGTEXT N_( \
142 "Blue balance of the video input (if supported by the v4l2 driver)." )
143 #define GAMMA_TEXT N_( "Gamma" )
144 #define GAMMA_LONGTEXT N_( \
145 "Gamma of the video input (if supported by the v4l2 driver)." )
146 #define EXPOSURE_TEXT N_( "Exposure" )
147 #define EXPOSURE_LONGTEXT N_( \
148 "Exposure of the video input (if supported by the v4L2 driver)." )
149 #define AUTOGAIN_TEXT N_( "Auto gain" )
150 #define AUTOGAIN_LONGTEXT N_( \
151 "Automatically set the video input's gain (if supported by the " \
153 #define GAIN_TEXT N_( "Gain" )
154 #define GAIN_LONGTEXT N_( \
155 "Video input's gain (if supported by the v4l2 driver)." )
156 #define HFLIP_TEXT N_( "Horizontal flip" )
157 #define HFLIP_LONGTEXT N_( \
158 "Flip the video horizontally (if supported by the v4l2 driver)." )
159 #define VFLIP_TEXT N_( "Vertical flip" )
160 #define VFLIP_LONGTEXT N_( \
161 "Flip the video vertically (if supported by the v4l2 driver)." )
162 #define HCENTER_TEXT N_( "Horizontal centering" )
163 #define HCENTER_LONGTEXT N_( \
164 "Set the camera's horizontal centering (if supported by the v4l2 driver)." )
165 #define VCENTER_TEXT N_( "Vertical centering" )
166 #define VCENTER_LONGTEXT N_( \
167 "Set the camera's vertical centering (if supported by the v4l2 driver)." )
169 #define AUDIO_VOLUME_TEXT N_( "Volume" )
170 #define AUDIO_VOLUME_LONGTEXT N_( \
171 "Volume of the audio input (if supported by the v4l2 driver)." )
172 #define AUDIO_BALANCE_TEXT N_( "Balance" )
173 #define AUDIO_BALANCE_LONGTEXT N_( \
174 "Balance of the audio input (if supported by the v4l2 driver)." )
175 #define AUDIO_MUTE_TEXT N_( "Mute" )
176 #define AUDIO_MUTE_LONGTEXT N_( \
177 "Mute audio input (if supported by the v4l2 driver)." )
178 #define AUDIO_BASS_TEXT N_( "Bass" )
179 #define AUDIO_BASS_LONGTEXT N_( \
180 "Bass level of the audio input (if supported by the v4l2 driver)." )
181 #define AUDIO_TREBLE_TEXT N_( "Treble" )
182 #define AUDIO_TREBLE_LONGTEXT N_( \
183 "Treble level of the audio input (if supported by the v4l2 driver)." )
184 #define AUDIO_LOUDNESS_TEXT N_( "Loudness" )
185 #define AUDIO_LOUDNESS_LONGTEXT N_( \
186 "Loudness of the audio input (if supported by the v4l2 driver)." )
188 #define CACHING_TEXT N_("Caching value in ms")
189 #define CACHING_LONGTEXT N_( \
190 "Caching value for V4L2 captures. This " \
191 "value should be set in milliseconds." )
192 #define S_CTRLS_TEXT N_("v4l2 driver controls")
193 #define S_CTRLS_LONGTEXT N_( \
194 "Set the v4l2 driver controls to the values specified using a comma " \
195 "separated list optionally encapsulated by curly braces " \
196 "(e.g.: {video_bitrate=6000000,audio_crc=0,stream_type=3} ). " \
197 "To list available controls, increase verbosity (-vvv) " \
198 "or use the v4l2-ctl application." )
200 #define TUNER_TEXT N_("Tuner id")
201 #define TUNER_LONGTEXT N_( \
202 "Tuner id (see debug output)." )
203 #define FREQUENCY_TEXT N_("Frequency")
204 #define FREQUENCY_LONGTEXT N_( \
205 "Tuner frequency in Hz or kHz (see debug output)" )
206 #define TUNER_AUDIO_MODE_TEXT N_("Audio mode")
207 #define TUNER_AUDIO_MODE_LONGTEXT N_( \
208 "Tuner audio mono/stereo and track selection." )
210 #define AUDIO_DEPRECATED_ERROR N_( \
211 "Alsa or OSS audio capture in the v4l2 access is deprecated. " \
212 "please use 'v4l2:/""/ :input-slave=alsa:/""/' or " \
213 "'v4l2:/""/ :input-slave=oss:/""/' instead." )
215 #define ASPECT_TEXT N_("Picture aspect-ratio n:m")
216 #define ASPECT_LONGTEXT N_("Define input picture aspect-ratio to use. Default is 4:3" )
225 static const int i_standards_list
[] =
226 { V4L2_STD_UNKNOWN
, V4L2_STD_SECAM
, V4L2_STD_PAL
, V4L2_STD_NTSC
,
227 V4L2_STD_PAL_B
, V4L2_STD_PAL_B1
, V4L2_STD_PAL_G
, V4L2_STD_PAL_H
,
228 V4L2_STD_PAL_I
, V4L2_STD_PAL_D
, V4L2_STD_PAL_D1
, V4L2_STD_PAL_K
,
229 V4L2_STD_PAL_M
, V4L2_STD_PAL_N
, V4L2_STD_PAL_Nc
, V4L2_STD_PAL_60
,
230 V4L2_STD_NTSC_M
, V4L2_STD_NTSC_M_JP
, V4L2_STD_NTSC_443
,
232 V4L2_STD_SECAM_B
, V4L2_STD_SECAM_D
, V4L2_STD_SECAM_G
,
233 V4L2_STD_SECAM_H
, V4L2_STD_SECAM_K
, V4L2_STD_SECAM_K1
,
234 V4L2_STD_SECAM_L
, V4L2_STD_SECAM_LC
,
235 V4L2_STD_ATSC_8_VSB
, V4L2_STD_ATSC_16_VSB
,
237 static const char *const psz_standards_list_text
[] =
238 { N_("Default"), "SECAM", "PAL", "NTSC",
239 "PAL_B", "PAL_B1", "PAL_G", "PAL_H", "PAL_I", "PAL_D",
240 "PAL_D1", "PAL_K", "PAL_M", "PAL_N", "PAL_Nc", "PAL_60",
241 "NTSC_M", "NTSC_M_JP", "NTSC_443", "NTSC_M_KR",
242 "SECAM_B", "SECAM_D", "SECAM_G", "SECAM_H", "SECAM_K",
243 "SECAM_K1", "SECAM_L", "SECAM_LC",
244 "ATSC_8_VSB", "ATSC_16_VSB"
247 static const int i_iomethod_list
[] =
248 { IO_METHOD_AUTO
, IO_METHOD_READ
, IO_METHOD_MMAP
, IO_METHOD_USERPTR
};
249 static const char *const psz_iomethod_list_text
[] =
250 { N_("AUTO"), N_("READ"), N_("MMAP"), N_("USERPTR") };
252 static const int i_tuner_audio_modes_list
[] =
253 { V4L2_TUNER_MODE_MONO
, V4L2_TUNER_MODE_STEREO
,
254 V4L2_TUNER_MODE_LANG1
, V4L2_TUNER_MODE_LANG2
,
255 V4L2_TUNER_MODE_SAP
, V4L2_TUNER_MODE_LANG1_LANG2
};
256 static const char *const psz_tuner_audio_modes_list_text
[] =
259 N_( "Primary language (Analog TV tuners only)" ),
260 N_( "Secondary language (Analog TV tuners only)" ),
261 N_( "Second audio program (Analog TV tuners only)" ),
262 N_( "Primary language left, Secondary language right" ) };
264 #define V4L2_DEFAULT "/dev/video0"
265 #define CFG_PREFIX "v4l2-"
268 # define DEFAULT_WIDTH 640
269 # define DEFAULT_HEIGHT 492
272 #ifndef DEFAULT_WIDTH
273 # define DEFAULT_WIDTH (-1)
274 # define DEFAULT_HEIGHT (-1)
278 set_shortname( N_("Video4Linux2") )
279 set_description( N_("Video4Linux2 input") )
280 set_category( CAT_INPUT
)
281 set_subcategory( SUBCAT_INPUT_ACCESS
)
283 set_section( N_( "Video input" ), NULL
)
284 add_integer( CFG_PREFIX
"standard", 0, STANDARD_TEXT
,
285 STANDARD_LONGTEXT
, false )
286 change_integer_list( i_standards_list
, psz_standards_list_text
)
287 add_string( CFG_PREFIX
"chroma", NULL
, CHROMA_TEXT
, CHROMA_LONGTEXT
,
289 add_integer( CFG_PREFIX
"input", 0, INPUT_TEXT
, INPUT_LONGTEXT
,
291 add_integer( CFG_PREFIX
"audio-input", 0, AUDIO_INPUT_TEXT
,
292 AUDIO_INPUT_LONGTEXT
, true )
293 add_integer( CFG_PREFIX
"io", IO_METHOD_AUTO
, IOMETHOD_TEXT
,
294 IOMETHOD_LONGTEXT
, true )
295 change_integer_list( i_iomethod_list
, psz_iomethod_list_text
)
296 add_integer( CFG_PREFIX
"width", DEFAULT_WIDTH
, WIDTH_TEXT
,
297 WIDTH_LONGTEXT
, true )
298 add_integer( CFG_PREFIX
"height", DEFAULT_HEIGHT
, HEIGHT_TEXT
,
299 HEIGHT_LONGTEXT
, true )
300 add_string( CFG_PREFIX
"aspect-ratio", "4:3", ASPECT_TEXT
,
301 ASPECT_LONGTEXT
, true )
302 add_float( CFG_PREFIX
"fps", 0, FPS_TEXT
, FPS_LONGTEXT
, true )
303 add_integer( CFG_PREFIX
"caching", 50 /* ms */,
304 CACHING_TEXT
, CACHING_LONGTEXT
, true )
306 add_bool( CFG_PREFIX
"use-libv4l2", false, LIBV4L2_TEXT
, LIBV4L2_LONGTEXT
, true );
309 set_section( N_( "Tuner" ), NULL
)
310 add_integer( CFG_PREFIX
"tuner", 0, TUNER_TEXT
, TUNER_LONGTEXT
,
312 add_integer( CFG_PREFIX
"tuner-frequency", -1, FREQUENCY_TEXT
,
313 FREQUENCY_LONGTEXT
, true )
314 add_integer( CFG_PREFIX
"tuner-audio-mode", -1, TUNER_AUDIO_MODE_TEXT
,
315 TUNER_AUDIO_MODE_LONGTEXT
, true )
316 change_integer_list( i_tuner_audio_modes_list
,
317 psz_tuner_audio_modes_list_text
)
319 set_section( N_( "Controls" ),
320 N_( "v4l2 driver controls, if supported by your v4l2 driver." ) )
321 add_bool( CFG_PREFIX
"controls-reset", false, CTRL_RESET_TEXT
,
322 CTRL_RESET_LONGTEXT
, true )
323 add_integer( CFG_PREFIX
"brightness", -1, BRIGHTNESS_TEXT
,
324 BRIGHTNESS_LONGTEXT
, true )
325 add_integer( CFG_PREFIX
"contrast", -1, CONTRAST_TEXT
,
326 CONTRAST_LONGTEXT
, true )
327 add_integer( CFG_PREFIX
"saturation", -1, SATURATION_TEXT
,
328 SATURATION_LONGTEXT
, true )
329 add_integer( CFG_PREFIX
"hue", -1, HUE_TEXT
,
331 add_integer( CFG_PREFIX
"black-level", -1, BLACKLEVEL_TEXT
,
332 BLACKLEVEL_LONGTEXT
, true )
333 add_integer( CFG_PREFIX
"auto-white-balance", -1,
334 AUTOWHITEBALANCE_TEXT
, AUTOWHITEBALANCE_LONGTEXT
, true )
335 add_integer( CFG_PREFIX
"do-white-balance", -1, DOWHITEBALANCE_TEXT
,
336 DOWHITEBALANCE_LONGTEXT
, true )
337 add_integer( CFG_PREFIX
"red-balance", -1, REDBALANCE_TEXT
,
338 REDBALANCE_LONGTEXT
, true )
339 add_integer( CFG_PREFIX
"blue-balance", -1, BLUEBALANCE_TEXT
,
340 BLUEBALANCE_LONGTEXT
, true )
341 add_integer( CFG_PREFIX
"gamma", -1, GAMMA_TEXT
,
342 GAMMA_LONGTEXT
, true )
343 add_integer( CFG_PREFIX
"exposure", -1, EXPOSURE_TEXT
,
344 EXPOSURE_LONGTEXT
, true )
345 add_integer( CFG_PREFIX
"autogain", -1, AUTOGAIN_TEXT
,
346 AUTOGAIN_LONGTEXT
, true )
347 add_integer( CFG_PREFIX
"gain", -1, GAIN_TEXT
,
348 GAIN_LONGTEXT
, true )
349 add_integer( CFG_PREFIX
"hflip", -1, HFLIP_TEXT
,
350 HFLIP_LONGTEXT
, true )
351 add_integer( CFG_PREFIX
"vflip", -1, VFLIP_TEXT
,
352 VFLIP_LONGTEXT
, true )
353 add_integer( CFG_PREFIX
"hcenter", -1, HCENTER_TEXT
,
354 HCENTER_LONGTEXT
, true )
355 add_integer( CFG_PREFIX
"vcenter", -1, VCENTER_TEXT
,
356 VCENTER_LONGTEXT
, true )
357 add_integer( CFG_PREFIX
"audio-volume", -1, AUDIO_VOLUME_TEXT
,
358 AUDIO_VOLUME_LONGTEXT
, true )
359 add_integer( CFG_PREFIX
"audio-balance", -1, AUDIO_BALANCE_TEXT
,
360 AUDIO_BALANCE_LONGTEXT
, true )
361 add_bool( CFG_PREFIX
"audio-mute", false, AUDIO_MUTE_TEXT
,
362 AUDIO_MUTE_LONGTEXT
, true )
363 add_integer( CFG_PREFIX
"audio-bass", -1, AUDIO_BASS_TEXT
,
364 AUDIO_BASS_LONGTEXT
, true )
365 add_integer( CFG_PREFIX
"audio-treble", -1, AUDIO_TREBLE_TEXT
,
366 AUDIO_TREBLE_LONGTEXT
, true )
367 add_integer( CFG_PREFIX
"audio-loudness", -1, AUDIO_LOUDNESS_TEXT
,
368 AUDIO_LOUDNESS_LONGTEXT
, true )
369 add_string( CFG_PREFIX
"set-ctrls", NULL
, S_CTRLS_TEXT
,
370 S_CTRLS_LONGTEXT
, true )
372 add_obsolete_string( CFG_PREFIX
"dev" )
374 add_obsolete_string( CFG_PREFIX
"adev" )
375 add_obsolete_integer( CFG_PREFIX
"audio-method" )
376 add_obsolete_bool( CFG_PREFIX
"stereo" )
377 add_obsolete_integer( CFG_PREFIX
"samplerate" )
379 add_shortcut( "v4l2" )
380 set_capability( "access_demux", 10 )
381 set_callbacks( DemuxOpen
, DemuxClose
)
384 add_shortcut( "v4l2", "v4l2c" )
385 set_description( N_("Video4Linux2 Compressed A/V") )
386 set_capability( "access", 0 )
387 /* use these when open as access_demux fails; VLC will use another demux */
388 set_callbacks( AccessOpen
, AccessClose
)
392 /*****************************************************************************
393 * Access: local prototypes
394 *****************************************************************************/
396 static void CommonClose( vlc_object_t
*, demux_sys_t
* );
397 static void ParseMRL( demux_sys_t
*, char *, vlc_object_t
* );
398 static void GetV4L2Params( demux_sys_t
*, vlc_object_t
* );
399 static void SetAvailControlsByString( vlc_object_t
*, demux_sys_t
*, int );
401 static int DemuxControl( demux_t
*, int, va_list );
402 static int AccessControl( access_t
*, int, va_list );
404 static int Demux( demux_t
* );
405 static block_t
*AccessRead( access_t
* );
406 static ssize_t
AccessReadStream( access_t
* p_access
, uint8_t * p_buffer
, size_t i_len
);
408 static block_t
* GrabVideo( vlc_object_t
*p_demux
, demux_sys_t
*p_sys
);
409 static block_t
* ProcessVideoFrame( vlc_object_t
*p_demux
, uint8_t *p_frame
, size_t );
411 static bool IsPixelFormatSupported( demux_t
*p_demux
,
412 unsigned int i_pixelformat
);
414 static int OpenVideoDev( vlc_object_t
*, demux_sys_t
*, bool );
415 static bool ProbeVideoDev( vlc_object_t
*, demux_sys_t
*,
416 const char *psz_device
);
418 static int ControlList( vlc_object_t
*, demux_sys_t
*, int , bool, bool );
419 static int Control( vlc_object_t
*, demux_sys_t
*, int i_fd
,
420 const char *psz_name
, int i_cid
, int i_value
);
422 static int DemuxControlCallback( vlc_object_t
*p_this
, const char *psz_var
,
423 vlc_value_t oldval
, vlc_value_t newval
,
425 static int DemuxControlResetCallback( vlc_object_t
*p_this
, const char *psz_var
,
426 vlc_value_t oldval
, vlc_value_t newval
,
428 static int AccessControlCallback( vlc_object_t
*p_this
, const char *psz_var
,
429 vlc_value_t oldval
, vlc_value_t newval
,
431 static int AccessControlResetCallback( vlc_object_t
*p_this
,
432 const char *psz_var
, vlc_value_t oldval
,
433 vlc_value_t newval
, void *p_data
);
438 vlc_fourcc_t i_fourcc
;
442 } v4l2chroma_to_fourcc
[] =
445 { V4L2_PIX_FMT_GREY
, VLC_CODEC_GREY
, 0, 0, 0 },
446 { V4L2_PIX_FMT_HI240
, VLC_FOURCC('I','2','4','0'), 0, 0, 0 },
447 { V4L2_PIX_FMT_RGB555
, VLC_CODEC_RGB15
, 0x001f,0x03e0,0x7c00 },
448 { V4L2_PIX_FMT_RGB565
, VLC_CODEC_RGB16
, 0x001f,0x07e0,0xf800 },
449 /* Won't work since we don't know how to handle such gmask values
451 { V4L2_PIX_FMT_RGB555X, VLC_CODEC_RGB15, 0x007c,0xe003,0x1f00 },
452 { V4L2_PIX_FMT_RGB565X, VLC_CODEC_RGB16, 0x00f8,0xe007,0x1f00 },
454 { V4L2_PIX_FMT_BGR24
, VLC_CODEC_RGB24
, 0xff0000,0xff00,0xff },
455 { V4L2_PIX_FMT_RGB24
, VLC_CODEC_RGB24
, 0xff,0xff00,0xff0000 },
456 { V4L2_PIX_FMT_BGR32
, VLC_CODEC_RGB32
, 0xff0000,0xff00,0xff },
457 { V4L2_PIX_FMT_RGB32
, VLC_CODEC_RGB32
, 0xff,0xff00,0xff0000 },
458 { V4L2_PIX_FMT_YUYV
, VLC_CODEC_YUYV
, 0, 0, 0 },
459 { V4L2_PIX_FMT_UYVY
, VLC_CODEC_UYVY
, 0, 0, 0 },
460 { V4L2_PIX_FMT_Y41P
, VLC_FOURCC('I','4','1','N'), 0, 0, 0 },
461 { V4L2_PIX_FMT_YUV422P
, VLC_CODEC_I422
, 0, 0, 0 },
462 { V4L2_PIX_FMT_YVU420
, VLC_CODEC_YV12
, 0, 0, 0 },
463 { V4L2_PIX_FMT_YUV411P
, VLC_CODEC_I411
, 0, 0, 0 },
464 { V4L2_PIX_FMT_YUV410
, VLC_CODEC_I410
, 0, 0, 0 },
466 /* Raw data types, not in V4L2 spec but still in videodev2.h and supported
468 { V4L2_PIX_FMT_YUV420
, VLC_CODEC_I420
, 0, 0, 0 },
469 /* FIXME { V4L2_PIX_FMT_RGB444, VLC_CODEC_RGB32 }, */
471 /* Compressed data types */
472 { V4L2_PIX_FMT_MJPEG
, VLC_CODEC_MJPG
, 0, 0, 0 },
473 { V4L2_PIX_FMT_JPEG
, VLC_CODEC_JPEG
, 0, 0, 0 },
475 { V4L2_PIX_FMT_DV
, VLC_FOURCC('?','?','?','?') },
476 { V4L2_PIX_FMT_MPEG
, VLC_FOURCC('?','?','?','?') },
482 * List of V4L2 chromas were confident enough to use as fallbacks if the
483 * user hasn't provided a --v4l2-chroma value.
485 * Try YUV chromas first, then RGB little endian and MJPEG as last resort.
487 static const uint32_t p_chroma_fallbacks
[] =
488 { V4L2_PIX_FMT_YUV420
, V4L2_PIX_FMT_YVU420
, V4L2_PIX_FMT_YUV422P
,
489 V4L2_PIX_FMT_YUYV
, V4L2_PIX_FMT_UYVY
, V4L2_PIX_FMT_BGR24
,
490 V4L2_PIX_FMT_BGR32
, V4L2_PIX_FMT_MJPEG
, V4L2_PIX_FMT_JPEG
};
494 const char *psz_name
;
498 { "brightness", V4L2_CID_BRIGHTNESS
},
499 { "contrast", V4L2_CID_CONTRAST
},
500 { "saturation", V4L2_CID_SATURATION
},
501 { "hue", V4L2_CID_HUE
},
502 { "audio-volume", V4L2_CID_AUDIO_VOLUME
},
503 { "audio-balance", V4L2_CID_AUDIO_BALANCE
},
504 { "audio-bass", V4L2_CID_AUDIO_BASS
},
505 { "audio-treble", V4L2_CID_AUDIO_TREBLE
},
506 { "audio-mute", V4L2_CID_AUDIO_MUTE
},
507 { "audio-loudness", V4L2_CID_AUDIO_LOUDNESS
},
508 { "black-level", V4L2_CID_BLACK_LEVEL
},
509 { "auto-white-balance", V4L2_CID_AUTO_WHITE_BALANCE
},
510 { "do-white-balance", V4L2_CID_DO_WHITE_BALANCE
},
511 { "red-balance", V4L2_CID_RED_BALANCE
},
512 { "blue-balance", V4L2_CID_BLUE_BALANCE
},
513 { "gamma", V4L2_CID_GAMMA
},
514 { "exposure", V4L2_CID_EXPOSURE
},
515 { "autogain", V4L2_CID_AUTOGAIN
},
516 { "gain", V4L2_CID_GAIN
},
517 { "hflip", V4L2_CID_HFLIP
},
518 { "vflip", V4L2_CID_VFLIP
},
519 { "hcenter", V4L2_CID_HCENTER
},
520 { "vcenter", V4L2_CID_VCENTER
},
532 char *psz_device
; /* Main device from MRL */
535 char *psz_requested_chroma
;
542 struct v4l2_capability dev_cap
;
545 struct v4l2_input
*p_inputs
;
546 int i_selected_input
;
549 struct v4l2_standard
*p_standards
;
550 v4l2_std_id i_selected_standard_id
;
553 /* V4L2 devices cannot have more than 32 audio inputs */
554 struct v4l2_audio p_audios
[32];
555 int i_selected_audio_input
;
558 struct v4l2_tuner
*p_tuners
;
561 struct v4l2_fmtdesc
*p_codecs
;
563 struct buffer_t
*p_buffers
;
564 unsigned int i_nbuffers
;
568 unsigned int i_aspect
;
569 float f_fps
; /* <= 0.0 mean to grab at full rate */
570 mtime_t i_video_pts
; /* only used when f_fps > 0 */
572 uint32_t i_block_flags
;
587 int (*pf_open
)(const char *, int, ...);
588 int (*pf_close
)( int );
589 int (*pf_dup
)( int );
590 int (*pf_ioctl
)( int, unsigned long int, ... );
591 ssize_t (*pf_read
)( int, void *, size_t );
592 void *(*pf_mmap
)( void *, size_t, int, int, int, off_t
);
593 int (*pf_munmap
)( void *, size_t );
599 static void use_kernel_v4l2( demux_sys_t
*p_sys
)
601 p_sys
->pf_open
= vlc_open
;
602 p_sys
->pf_close
= close
;
604 p_sys
->pf_ioctl
= ioctl
;
605 p_sys
->pf_read
= read
;
606 p_sys
->pf_mmap
= mmap
;
607 p_sys
->pf_munmap
= munmap
;
608 p_sys
->b_libv4l2
= false;
611 static void use_libv4l2( demux_sys_t
*p_sys
)
613 p_sys
->pf_open
= v4l2_open
;
614 p_sys
->pf_close
= v4l2_close
;
615 p_sys
->pf_dup
= v4l2_dup
;
616 p_sys
->pf_ioctl
= v4l2_ioctl
;
617 p_sys
->pf_read
= v4l2_read
;
618 p_sys
->pf_mmap
= v4l2_mmap
;
619 p_sys
->pf_munmap
= v4l2_munmap
;
620 p_sys
->b_libv4l2
= true;
623 # define v4l2_open (p_sys->pf_open)
624 # define v4l2_close (p_sys->pf_close)
625 # define v4l2_dup (p_sys->pf_dup)
626 # define v4l2_ioctl (p_sys->pf_ioctl)
627 # define v4l2_read (p_sys->pf_read)
628 # define v4l2_mmap (p_sys->pf_mmap)
629 # define v4l2_munmap (p_sys->pf_munmap)
631 # define v4l2_open vlc_open
632 # define v4l2_close close
633 # define v4l2_dup dup
634 # define v4l2_ioctl ioctl
635 # define v4l2_read read
636 # define v4l2_mmap mmap
637 # define v4l2_munmap munmap
640 static int FindMainDevice( vlc_object_t
*p_this
, demux_sys_t
*p_sys
,
643 /* TODO: if using default device, loop through all /dev/video* until
645 msg_Dbg( p_this
, "opening device '%s'", p_sys
->psz_device
);
646 if( ProbeVideoDev( p_this
, p_sys
, p_sys
->psz_device
) )
648 msg_Dbg( p_this
, "'%s' is a video device", p_sys
->psz_device
);
649 p_sys
->i_fd
= OpenVideoDev( p_this
, p_sys
, b_demux
);
652 if( p_sys
->i_fd
< 0 ) return VLC_EGENERIC
;
656 /*****************************************************************************
657 * DemuxOpen: opens v4l2 device, access_demux callback
658 *****************************************************************************
660 * url: <video device>::::
662 *****************************************************************************/
663 static int DemuxOpen( vlc_object_t
*p_this
)
665 demux_t
*p_demux
= (demux_t
*)p_this
;
668 /* Only when selected */
669 if( strcmp( p_demux
->psz_access
, "v4l2" ) )
673 p_demux
->pf_control
= DemuxControl
;
674 p_demux
->pf_demux
= Demux
;
675 p_demux
->info
.i_update
= 0;
676 p_demux
->info
.i_title
= 0;
677 p_demux
->info
.i_seekpoint
= 0;
679 p_demux
->p_sys
= p_sys
= calloc( 1, sizeof( demux_sys_t
) );
680 if( p_sys
== NULL
) return VLC_ENOMEM
;
682 GetV4L2Params(p_sys
, (vlc_object_t
*) p_demux
);
684 ParseMRL( p_sys
, p_demux
->psz_location
, (vlc_object_t
*) p_demux
);
687 if( !var_InheritBool( p_this
, CFG_PREFIX
"use-libv4l2" ) )
689 msg_Dbg( p_this
, "Trying direct kernel v4l2" );
690 use_kernel_v4l2( p_sys
);
691 if( FindMainDevice( p_this
, p_sys
, true ) == VLC_SUCCESS
)
695 msg_Dbg( p_this
, "Trying libv4l2 wrapper" );
696 use_libv4l2( p_sys
);
698 if( FindMainDevice( p_this
, p_sys
, true ) == VLC_SUCCESS
)
701 DemuxClose( p_this
);
705 /*****************************************************************************
706 * GetV4L2Params: fill in p_sys parameters (shared by DemuxOpen and AccessOpen)
707 *****************************************************************************/
708 static void GetV4L2Params( demux_sys_t
*p_sys
, vlc_object_t
*p_obj
)
710 p_sys
->i_video_pts
= -1;
712 p_sys
->i_selected_standard_id
=
713 i_standards_list
[var_CreateGetInteger( p_obj
, "v4l2-standard" )];
715 p_sys
->i_selected_input
= var_CreateGetInteger( p_obj
, "v4l2-input" );
716 p_sys
->i_selected_audio_input
=
717 var_CreateGetInteger( p_obj
, "v4l2-audio-input" );
719 p_sys
->io
= var_CreateGetInteger( p_obj
, "v4l2-io" );
721 p_sys
->i_width
= var_CreateGetInteger( p_obj
, "v4l2-width" );
722 p_sys
->i_height
= var_CreateGetInteger( p_obj
, "v4l2-height" );
724 var_Create( p_obj
, "v4l2-controls-reset", VLC_VAR_BOOL
| VLC_VAR_DOINHERIT
);
726 p_sys
->f_fps
= var_CreateGetFloat( p_obj
, "v4l2-fps" );
727 p_sys
->psz_requested_chroma
= var_CreateGetString( p_obj
, "v4l2-chroma" );
729 p_sys
->i_cache
= var_CreateGetInteger( p_obj
, "v4l2-caching" );
731 p_sys
->i_cur_tuner
= var_CreateGetInteger( p_obj
, "v4l2-tuner" );
732 p_sys
->i_frequency
= var_CreateGetInteger( p_obj
, "v4l2-tuner-frequency" );
733 p_sys
->i_audio_mode
= var_CreateGetInteger( p_obj
, "v4l2-tuner-audio-mode" );
735 p_sys
->psz_set_ctrls
= var_CreateGetString( p_obj
, "v4l2-set-ctrls" );
737 char *psz_aspect
= var_CreateGetString( p_obj
, "v4l2-aspect-ratio" );
738 char *psz_delim
= !EMPTY_STR(psz_aspect
) ? strchr( psz_aspect
, ':' ) : NULL
;
741 p_sys
->i_aspect
= atoi( psz_aspect
) * VOUT_ASPECT_FACTOR
/ atoi( psz_delim
+ 1 );
745 p_sys
->i_aspect
= 4 * VOUT_ASPECT_FACTOR
/ 3 ;
750 p_sys
->psz_device
= NULL
;
756 /*****************************************************************************
757 * ParseMRL: parse the options contained in the MRL
758 *****************************************************************************/
759 static void ParseMRL( demux_sys_t
*p_sys
, char *psz_path
, vlc_object_t
*p_obj
)
761 char *psz_dup
= strdup( psz_path
);
762 char *psz_parser
= psz_dup
;
764 while( *psz_parser
&& *psz_parser
!= ':' )
769 if( *psz_parser
== ':' )
774 *psz_parser
++ = '\0';
776 if( !strncmp( psz_parser
, "standard=", strlen( "standard=" ) ) )
778 psz_parser
+= strlen( "standard=" );
780 for( i
= 0; i
< ARRAY_SIZE(psz_standards_list_text
); i
++ )
782 const char *psz_value
= psz_standards_list_text
[i
];
783 size_t i_len
= strlen( psz_value
);
784 if( !strncasecmp( psz_parser
, psz_value
, i_len
) &&
785 ( psz_parser
[i_len
] == ':' || psz_parser
[i_len
] == 0 ) )
787 p_sys
->i_selected_standard_id
= i_standards_list
[i
];
793 if( i
== ARRAY_SIZE(psz_standards_list_text
) )
794 p_sys
->i_selected_standard_id
= i_standards_list
[strtol( psz_parser
, &psz_parser
, 0 )];
796 else if( !strncmp( psz_parser
, "chroma=", strlen( "chroma=" ) ) )
800 psz_parser
+= strlen( "chroma=" );
801 if( strchr( psz_parser
, ':' ) )
803 i_len
= strchr( psz_parser
, ':' ) - psz_parser
;
807 i_len
= strlen( psz_parser
);
810 free( p_sys
->psz_requested_chroma
);
811 p_sys
->psz_requested_chroma
= strndup( psz_parser
, i_len
);
815 else if( !strncmp( psz_parser
, "input=", strlen( "input=" ) ) )
817 p_sys
->i_selected_input
= strtol( psz_parser
+ strlen( "input=" ),
820 else if( !strncmp( psz_parser
, "audio-input=", strlen( "audio-input=" ) ) )
822 p_sys
->i_selected_audio_input
= strtol( psz_parser
+ strlen( "audio-input=" ),
825 else if( !strncmp( psz_parser
, "fps=", strlen( "fps=" ) ) )
827 p_sys
->f_fps
= us_strtof( psz_parser
+ strlen( "fps=" ),
830 else if( !strncmp( psz_parser
, "io=", strlen( "io=" ) ) )
832 psz_parser
+= strlen( "io=" );
833 if( !strncmp( psz_parser
, "read", strlen( "read" ) ) )
835 p_sys
->io
= IO_METHOD_READ
;
836 psz_parser
+= strlen( "read" );
838 else if( !strncmp( psz_parser
, "mmap", strlen( "mmap" ) ) )
840 p_sys
->io
= IO_METHOD_MMAP
;
841 psz_parser
+= strlen( "mmap" );
843 else if( !strncmp( psz_parser
, "userptr", strlen( "userptr" ) ) )
845 p_sys
->io
= IO_METHOD_USERPTR
;
846 psz_parser
+= strlen( "userptr" );
848 else if( !strncmp( psz_parser
, "auto", strlen( "auto" ) ) )
850 p_sys
->io
= IO_METHOD_AUTO
;
851 psz_parser
+= strlen( "auto" );
855 p_sys
->io
= strtol( psz_parser
, &psz_parser
, 0 );
858 else if( !strncmp( psz_parser
, "width=",
859 strlen( "width=" ) ) )
862 strtol( psz_parser
+ strlen( "width=" ),
865 else if( !strncmp( psz_parser
, "height=",
866 strlen( "height=" ) ) )
869 strtol( psz_parser
+ strlen( "height=" ),
872 else if( !strncmp( psz_parser
, "aspect-ratio=",
873 strlen( "aspect-ratio=" ) ) )
875 unsigned int num
,den
;
876 num
= strtol( psz_parser
+ strlen( "aspect-ratio=" ),
878 den
= strtol( psz_parser
+ strlen( ":" ),
881 p_sys
->i_aspect
= num
* VOUT_ASPECT_FACTOR
/ den
;
883 else if( !strncmp( psz_parser
, "controls-reset",
884 strlen( "controls-reset" ) ) )
886 var_SetBool( p_obj
, "v4l2-controls-reset", true );
887 psz_parser
+= strlen( "controls-reset" );
890 else if( !strncmp( psz_parser
, "brightness=",
891 strlen( "brightness=" ) ) )
893 var_SetInteger( p_obj
, "brightness",
894 strtol( psz_parser
+ strlen( "brightness=" ),
897 else if( !strncmp( psz_parser
, "contrast=",
898 strlen( "contrast=" ) ) )
900 var_SetInteger( p_obj
, "contrast",
901 strtol( psz_parser
+ strlen( "contrast=" ),
904 else if( !strncmp( psz_parser
, "saturation=",
905 strlen( "saturation=" ) ) )
907 var_SetInteger( p_obj
, "saturation",
908 strtol( psz_parser
+ strlen( "saturation=" ),
911 else if( !strncmp( psz_parser
, "hue=",
914 var_SetInteger( p_obj
, "hue",
915 strtol( psz_parser
+ strlen( "hue=" ),
918 else if( !strncmp( psz_parser
, "gamma=",
919 strlen( "gamma=" ) ) )
921 var_SetInteger( p_obj
, "gamma",
922 strtol( psz_parser
+ strlen( "gamma=" ),
926 else if( !strncmp( psz_parser
, "caching=", strlen( "caching=" ) ) )
928 p_sys
->i_cache
= strtol( psz_parser
+ strlen( "caching=" ),
931 else if( !strncmp( psz_parser
, "tuner=", strlen( "tuner=" ) ) )
933 p_sys
->i_cur_tuner
= strtol( psz_parser
+ strlen( "tuner=" ),
936 else if( !strncmp( psz_parser
, "tuner-frequency=", strlen( "tuner-frequency=" ) ) )
938 p_sys
->i_frequency
= strtol( psz_parser
939 + strlen( "tuner-frequency=" ),
942 else if( !strncmp( psz_parser
, "tuner-audio-mode=", strlen( "tuner-audio-mode=" ) ) )
944 p_sys
->i_audio_mode
= strtol( psz_parser
945 + strlen( "tuner-audio-mode=" ),
948 else if( !strncmp( psz_parser
, "set-ctrls=", strlen( "set-ctrls=" )) )
952 psz_parser
+= strlen( "set-ctrls=" );
953 if( strchr( psz_parser
, ':' ) )
955 i_len
= strchr( psz_parser
, ':' ) - psz_parser
;
959 i_len
= strlen( psz_parser
);
962 p_sys
->psz_set_ctrls
= strndup( psz_parser
, i_len
);
966 else if( !strncmp( psz_parser
, "adev=", strlen( "adev=" ) )
967 || !strncmp( psz_parser
, "samplerate=", strlen( "samplerate=" ) )
968 || !strncmp( psz_parser
, "audio-method", strlen( "audio-method" ) )
969 || !strncmp( psz_parser
, "stereo", strlen( "stereo" ) )
970 || !strncmp( psz_parser
, "mono", strlen( "mono" ) ) )
972 if( strchr( psz_parser
, ':' ) )
974 psz_parser
= strchr( psz_parser
, ':' );
978 psz_parser
+= strlen( psz_parser
);
981 msg_Err( p_obj
, AUDIO_DEPRECATED_ERROR
);
985 char *psz_unk
= strchr( psz_parser
, ':' );
987 psz_unk
= strndup( psz_parser
, psz_unk
- psz_parser
);
989 psz_unk
= strdup( psz_parser
);
990 msg_Warn( p_obj
, "unknown option %s", psz_unk
);
994 while( *psz_parser
&& *psz_parser
!= ':' )
999 if( *psz_parser
== '\0' )
1008 p_sys
->psz_device
= strdup( psz_dup
);
1010 p_sys
->psz_device
= strdup( V4L2_DEFAULT
);
1014 /*****************************************************************************
1015 * Close: close device, free resources
1016 *****************************************************************************/
1017 static void AccessClose( vlc_object_t
*p_this
)
1019 access_t
*p_access
= (access_t
*)p_this
;
1020 demux_sys_t
*p_sys
= (demux_sys_t
*) p_access
->p_sys
;
1022 CommonClose( p_this
, p_sys
);
1025 static void DemuxClose( vlc_object_t
*p_this
)
1027 struct v4l2_buffer buf
;
1028 enum v4l2_buf_type buf_type
;
1031 demux_t
*p_demux
= (demux_t
*)p_this
;
1032 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1034 /* Stop video capture */
1035 if( p_sys
->i_fd
>= 0 )
1039 case IO_METHOD_READ
:
1043 case IO_METHOD_MMAP
:
1044 case IO_METHOD_USERPTR
:
1045 /* Some drivers 'hang' internally if this is not done before streamoff */
1046 for( unsigned int i
= 0; i
< p_sys
->i_nbuffers
; i
++ )
1048 memset( &buf
, 0, sizeof(buf
) );
1049 buf
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1050 buf
.memory
= ( p_sys
->io
== IO_METHOD_USERPTR
) ?
1051 V4L2_MEMORY_USERPTR
: V4L2_MEMORY_MMAP
;
1052 v4l2_ioctl( p_sys
->i_fd
, VIDIOC_DQBUF
, &buf
); /* ignore result */
1055 buf_type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1056 if( v4l2_ioctl( p_sys
->i_fd
, VIDIOC_STREAMOFF
, &buf_type
) < 0 ) {
1057 msg_Err( p_this
, "VIDIOC_STREAMOFF failed" );
1067 /* Free Video Buffers */
1068 if( p_sys
->p_buffers
) {
1071 case IO_METHOD_READ
:
1072 free( p_sys
->p_buffers
[0].start
);
1075 case IO_METHOD_MMAP
:
1076 for( i
= 0; i
< p_sys
->i_nbuffers
; ++i
)
1078 if( v4l2_munmap( p_sys
->p_buffers
[i
].start
, p_sys
->p_buffers
[i
].length
) )
1080 msg_Err( p_this
, "munmap failed" );
1085 case IO_METHOD_USERPTR
:
1086 for( i
= 0; i
< p_sys
->i_nbuffers
; ++i
)
1088 free( p_sys
->p_buffers
[i
].start
);
1095 free( p_sys
->p_buffers
);
1098 CommonClose( p_this
, p_sys
);
1101 static void CommonClose( vlc_object_t
*p_this
, demux_sys_t
*p_sys
)
1105 if( p_sys
->i_fd
>= 0 ) v4l2_close( p_sys
->i_fd
);
1106 free( p_sys
->psz_device
);
1107 free( p_sys
->p_standards
);
1108 free( p_sys
->p_inputs
);
1109 free( p_sys
->p_tuners
);
1110 free( p_sys
->p_codecs
);
1111 free( p_sys
->psz_requested_chroma
);
1112 free( p_sys
->psz_set_ctrls
);
1117 /*****************************************************************************
1118 * AccessOpen: opens v4l2 device, access callback
1119 *****************************************************************************
1121 * url: <video device>::::
1123 *****************************************************************************/
1124 static int AccessOpen( vlc_object_t
* p_this
)
1126 access_t
*p_access
= (access_t
*) p_this
;
1127 demux_sys_t
* p_sys
;
1129 /* Only when selected */
1130 if( *p_access
->psz_access
== '\0' ) return VLC_EGENERIC
;
1132 access_InitFields( p_access
);
1133 p_sys
= calloc( 1, sizeof( demux_sys_t
));
1134 if( !p_sys
) return VLC_ENOMEM
;
1135 p_access
->p_sys
= (access_sys_t
*)p_sys
;
1137 GetV4L2Params( p_sys
, (vlc_object_t
*) p_access
);
1139 ParseMRL( p_sys
, p_access
->psz_location
, (vlc_object_t
*) p_access
);
1142 if( !var_InheritBool( p_this
, CFG_PREFIX
"use-libv4l2" ) )
1144 msg_Dbg( p_this
, "Trying direct kernel v4l2" );
1145 use_kernel_v4l2( p_sys
);
1146 if( FindMainDevice( p_this
, p_sys
, false ) == VLC_SUCCESS
)
1148 if( p_sys
->io
== IO_METHOD_READ
)
1150 ACCESS_SET_CALLBACKS( AccessReadStream
, NULL
, AccessControl
, NULL
);
1154 ACCESS_SET_CALLBACKS( NULL
, AccessRead
, AccessControl
, NULL
);
1160 msg_Dbg( p_this
, "Trying libv4l2 wrapper" );
1161 use_libv4l2( p_sys
);
1163 if( FindMainDevice( p_this
, p_sys
, false ) == VLC_SUCCESS
)
1165 if( p_sys
->io
== IO_METHOD_READ
)
1167 ACCESS_SET_CALLBACKS( AccessReadStream
, NULL
, AccessControl
, NULL
);
1171 ACCESS_SET_CALLBACKS( NULL
, AccessRead
, AccessControl
, NULL
);
1176 AccessClose( p_this
);
1177 return VLC_EGENERIC
;
1180 /*****************************************************************************
1182 *****************************************************************************/
1183 static int DemuxControl( demux_t
*p_demux
, int i_query
, va_list args
)
1187 /* Special for access_demux */
1188 case DEMUX_CAN_PAUSE
:
1189 case DEMUX_CAN_SEEK
:
1190 case DEMUX_CAN_CONTROL_PACE
:
1191 *va_arg( args
, bool * ) = false;
1194 case DEMUX_GET_PTS_DELAY
:
1195 *va_arg(args
,int64_t *) = (int64_t)p_demux
->p_sys
->i_cache
*1000;
1198 case DEMUX_GET_TIME
:
1199 *va_arg( args
, int64_t * ) = mdate();
1202 /* TODO implement others */
1204 return VLC_EGENERIC
;
1207 return VLC_EGENERIC
;
1210 /*****************************************************************************
1211 * AccessControl: access callback
1212 *****************************************************************************/
1213 static int AccessControl( access_t
*p_access
, int i_query
, va_list args
)
1215 demux_sys_t
*p_sys
= (demux_sys_t
*) p_access
->p_sys
;
1220 case ACCESS_CAN_SEEK
:
1221 case ACCESS_CAN_FASTSEEK
:
1222 case ACCESS_CAN_PAUSE
:
1223 case ACCESS_CAN_CONTROL_PACE
:
1224 *va_arg( args
, bool* ) = false;
1228 case ACCESS_GET_PTS_DELAY
:
1229 *va_arg(args
,int64_t *) = (int64_t)p_sys
->i_cache
*1000;
1233 case ACCESS_SET_PAUSE_STATE
:
1237 case ACCESS_GET_TITLE_INFO
:
1238 case ACCESS_SET_TITLE
:
1239 case ACCESS_SET_SEEKPOINT
:
1240 case ACCESS_SET_PRIVATE_ID_STATE
:
1241 case ACCESS_GET_CONTENT_TYPE
:
1242 case ACCESS_GET_META
:
1243 return VLC_EGENERIC
;
1246 msg_Warn( p_access
, "Unimplemented query in control(%d).", i_query
);
1247 return VLC_EGENERIC
;
1253 /*****************************************************************************
1254 * AccessRead: access callback
1255 ******************************************************************************/
1256 static block_t
*AccessRead( access_t
* p_access
)
1258 demux_sys_t
*p_sys
= (demux_sys_t
*)p_access
->p_sys
;
1261 fd
.fd
= p_sys
->i_fd
;
1262 fd
.events
= POLLIN
|POLLPRI
;
1266 if( poll( &fd
, 1, 500 ) ) /* Timeout after 0.5 seconds since I don't know if pf_demux can be blocking. */
1268 if( fd
.revents
& (POLLIN
|POLLPRI
) )
1270 return GrabVideo( VLC_OBJECT(p_access
), p_sys
);
1277 static ssize_t
AccessReadStream( access_t
* p_access
, uint8_t * p_buffer
, size_t i_len
)
1279 demux_sys_t
*p_sys
= (demux_sys_t
*) p_access
->p_sys
;
1283 ufd
.fd
= p_sys
->i_fd
;
1284 ufd
.events
= POLLIN
;
1286 if( p_access
->info
.b_eof
)
1291 if( !vlc_object_alive (p_access
) )
1296 while( ( i_ret
= poll( &ufd
, 1, 500 ) ) == 0 );
1300 msg_Err( p_access
, "Polling error (%m)." );
1304 i_ret
= v4l2_read( p_sys
->i_fd
, p_buffer
, i_len
);
1307 p_access
->info
.b_eof
= true;
1309 else if( i_ret
> 0 )
1311 p_access
->info
.i_pos
+= i_ret
;
1317 /*****************************************************************************
1318 * Demux: Processes the audio or video frame
1319 *****************************************************************************/
1320 static int Demux( demux_t
*p_demux
)
1322 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1325 fd
.fd
= p_sys
->i_fd
;
1326 fd
.events
= POLLIN
|POLLPRI
;
1330 if( poll( &fd
, 1, 500 ) ) /* Timeout after 0.5 seconds since I don't know if pf_demux can be blocking. */
1332 if( fd
.revents
& (POLLIN
|POLLPRI
) )
1334 block_t
*p_block
= GrabVideo( VLC_OBJECT(p_demux
), p_sys
);
1337 es_out_Control( p_demux
->out
, ES_OUT_SET_PCR
, p_block
->i_pts
);
1338 es_out_Send( p_demux
->out
, p_sys
->p_es
, p_block
);
1346 /*****************************************************************************
1347 * GrabVideo: Grab a video frame
1348 *****************************************************************************/
1349 static block_t
* GrabVideo( vlc_object_t
*p_demux
, demux_sys_t
*p_sys
)
1351 block_t
*p_block
= NULL
;
1352 struct v4l2_buffer buf
;
1355 if( p_sys
->f_fps
>= 0.1 && p_sys
->i_video_pts
> 0 )
1357 mtime_t i_dur
= (mtime_t
)((double)1000000 / (double)p_sys
->f_fps
);
1359 /* Did we wait long enough ? (frame rate reduction) */
1360 if( p_sys
->i_video_pts
+ i_dur
> mdate() )
1364 /* Grab Video Frame */
1367 case IO_METHOD_READ
:
1368 i_ret
= v4l2_read( p_sys
->i_fd
, p_sys
->p_buffers
[0].start
, p_sys
->p_buffers
[0].length
);
1376 /* Could ignore EIO, see spec. */
1379 msg_Err( p_demux
, "Failed to read frame" );
1384 p_block
= ProcessVideoFrame( p_demux
, (uint8_t*)p_sys
->p_buffers
[0].start
, i_ret
);
1390 case IO_METHOD_MMAP
:
1391 memset( &buf
, 0, sizeof(buf
) );
1392 buf
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1393 buf
.memory
= V4L2_MEMORY_MMAP
;
1395 /* Wait for next frame */
1396 if (v4l2_ioctl( p_sys
->i_fd
, VIDIOC_DQBUF
, &buf
) < 0 )
1403 /* Could ignore EIO, see spec. */
1406 msg_Err( p_demux
, "Failed to wait (VIDIOC_DQBUF)" );
1411 if( buf
.index
>= p_sys
->i_nbuffers
) {
1412 msg_Err( p_demux
, "Failed capturing new frame as i>=nbuffers" );
1416 p_block
= ProcessVideoFrame( p_demux
, p_sys
->p_buffers
[buf
.index
].start
, buf
.bytesused
);
1421 if( v4l2_ioctl( p_sys
->i_fd
, VIDIOC_QBUF
, &buf
) < 0 )
1423 msg_Err( p_demux
, "Failed to unlock (VIDIOC_QBUF)" );
1424 block_Release( p_block
);
1430 case IO_METHOD_USERPTR
:
1431 memset( &buf
, 0, sizeof(buf
) );
1432 buf
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1433 buf
.memory
= V4L2_MEMORY_USERPTR
;
1435 /* Wait for next frame */
1436 if (v4l2_ioctl( p_sys
->i_fd
, VIDIOC_DQBUF
, &buf
) < 0 )
1443 /* Could ignore EIO, see spec. */
1446 msg_Err( p_demux
, "Failed to wait (VIDIOC_DQBUF)" );
1453 for( i
= 0; i
< p_sys
->i_nbuffers
; i
++ )
1455 if( buf
.m
.userptr
== (unsigned long)p_sys
->p_buffers
[i
].start
&&
1456 buf
.length
== p_sys
->p_buffers
[i
].length
) break;
1459 if( i
>= p_sys
->i_nbuffers
)
1461 msg_Err( p_demux
, "Failed capturing new frame as i>=nbuffers" );
1465 p_block
= ProcessVideoFrame( p_demux
, (uint8_t*)buf
.m
.userptr
, buf
.bytesused
);
1470 if( v4l2_ioctl( p_sys
->i_fd
, VIDIOC_QBUF
, &buf
) < 0 )
1472 msg_Err( p_demux
, "Failed to unlock (VIDIOC_QBUF)" );
1473 block_Release( p_block
);
1484 p_sys
->i_video_pts
= p_block
->i_pts
= p_block
->i_dts
= mdate();
1485 p_block
->i_flags
|= p_sys
->i_block_flags
;
1490 /*****************************************************************************
1491 * ProcessVideoFrame: Helper function to take a buffer and copy it into
1493 *****************************************************************************/
1494 static block_t
* ProcessVideoFrame( vlc_object_t
*p_demux
, uint8_t *p_frame
, size_t i_size
)
1498 if( !p_frame
) return NULL
;
1501 if( !( p_block
= block_New( p_demux
, i_size
) ) )
1503 msg_Warn( p_demux
, "Cannot get new block" );
1508 memcpy( p_block
->p_buffer
, p_frame
, i_size
);
1513 /*****************************************************************************
1514 * Helper function to initalise video IO using the Read method
1515 *****************************************************************************/
1516 static int InitRead( vlc_object_t
*p_demux
, demux_sys_t
*p_sys
, unsigned int i_buffer_size
)
1520 p_sys
->p_buffers
= calloc( 1, sizeof( *p_sys
->p_buffers
) );
1521 if( !p_sys
->p_buffers
)
1522 return VLC_EGENERIC
;
1524 p_sys
->p_buffers
[0].length
= i_buffer_size
;
1525 p_sys
->p_buffers
[0].start
= malloc( i_buffer_size
);
1526 if( !p_sys
->p_buffers
[0].start
)
1532 /*****************************************************************************
1533 * Helper function to initalise video IO using the mmap method
1534 *****************************************************************************/
1535 static int InitMmap( vlc_object_t
*p_demux
, demux_sys_t
*p_sys
, int i_fd
)
1537 struct v4l2_requestbuffers req
;
1539 memset( &req
, 0, sizeof(req
) );
1541 req
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1542 req
.memory
= V4L2_MEMORY_MMAP
;
1544 if( v4l2_ioctl( i_fd
, VIDIOC_REQBUFS
, &req
) < 0 )
1546 msg_Err( p_demux
, "device does not support mmap i/o" );
1552 msg_Err( p_demux
, "Insufficient buffer memory" );
1556 p_sys
->p_buffers
= calloc( req
.count
, sizeof( *p_sys
->p_buffers
) );
1557 if( !p_sys
->p_buffers
)
1560 for( p_sys
->i_nbuffers
= 0; p_sys
->i_nbuffers
< req
.count
; ++p_sys
->i_nbuffers
)
1562 struct v4l2_buffer buf
;
1564 memset( &buf
, 0, sizeof(buf
) );
1565 buf
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1566 buf
.memory
= V4L2_MEMORY_MMAP
;
1567 buf
.index
= p_sys
->i_nbuffers
;
1569 if( v4l2_ioctl( i_fd
, VIDIOC_QUERYBUF
, &buf
) < 0 )
1571 msg_Err( p_demux
, "VIDIOC_QUERYBUF" );
1575 p_sys
->p_buffers
[p_sys
->i_nbuffers
].length
= buf
.length
;
1576 p_sys
->p_buffers
[p_sys
->i_nbuffers
].start
=
1577 v4l2_mmap( NULL
, buf
.length
, PROT_READ
| PROT_WRITE
, MAP_SHARED
, i_fd
, buf
.m
.offset
);
1579 if( p_sys
->p_buffers
[p_sys
->i_nbuffers
].start
== MAP_FAILED
)
1581 msg_Err( p_demux
, "mmap failed (%m)" );
1589 return VLC_EGENERIC
;
1593 /*****************************************************************************
1594 * Helper function to initalise video IO using the userbuf method
1595 *****************************************************************************/
1596 static int InitUserP( vlc_object_t
*p_demux
, demux_sys_t
*p_sys
, int i_fd
, unsigned int i_buffer_size
)
1598 struct v4l2_requestbuffers req
;
1599 unsigned int i_page_size
;
1601 i_page_size
= sysconf(_SC_PAGESIZE
);
1602 i_buffer_size
= ( i_buffer_size
+ i_page_size
- 1 ) & ~( i_page_size
- 1);
1604 memset( &req
, 0, sizeof(req
) );
1606 req
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1607 req
.memory
= V4L2_MEMORY_USERPTR
;
1609 if( v4l2_ioctl( i_fd
, VIDIOC_REQBUFS
, &req
) < 0 )
1611 msg_Err( p_demux
, "device does not support user pointer i/o" );
1612 return VLC_EGENERIC
;
1615 p_sys
->p_buffers
= calloc( 4, sizeof( *p_sys
->p_buffers
) );
1616 if( !p_sys
->p_buffers
)
1619 for( p_sys
->i_nbuffers
= 0; p_sys
->i_nbuffers
< 4; ++p_sys
->i_nbuffers
)
1621 p_sys
->p_buffers
[p_sys
->i_nbuffers
].length
= i_buffer_size
;
1622 if( posix_memalign( &p_sys
->p_buffers
[p_sys
->i_nbuffers
].start
,
1623 /* boundary */ i_page_size
, i_buffer_size
) )
1630 free( p_sys
->p_buffers
);
1631 return VLC_EGENERIC
;
1635 /*****************************************************************************
1636 * IsPixelFormatSupported: returns true if the specified V4L2 pixel format is
1637 * in the array of supported formats returned by the driver
1638 *****************************************************************************/
1639 static bool IsPixelFormatSupported( demux_t
*p_demux
, unsigned int i_pixelformat
)
1641 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1643 for( int i_index
= 0; i_index
< p_sys
->i_codec
; i_index
++ )
1645 if( p_sys
->p_codecs
[i_index
].pixelformat
== i_pixelformat
)
1652 static float GetMaxFrameRate( demux_t
*p_demux
, int i_fd
,
1653 uint32_t i_pixel_format
,
1654 uint32_t i_width
, uint32_t i_height
)
1657 #ifdef VIDIOC_ENUM_FRAMEINTERVALS
1659 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1661 /* This is new in Linux 2.6.19 */
1662 struct v4l2_frmivalenum frmival
;
1663 memset( &frmival
, 0, sizeof(frmival
) );
1664 frmival
.pixel_format
= i_pixel_format
;
1665 frmival
.width
= i_width
;
1666 frmival
.height
= i_height
;
1667 if( v4l2_ioctl( i_fd
, VIDIOC_ENUM_FRAMEINTERVALS
, &frmival
) >= 0 )
1669 switch( frmival
.type
)
1671 case V4L2_FRMIVAL_TYPE_DISCRETE
:
1673 float f_fps_max
= -1;
1676 float f_fps
= (float)frmival
.discrete
.denominator
1677 / (float)frmival
.discrete
.numerator
;
1678 if( f_fps
> f_fps_max
) f_fps_max
= f_fps
;
1680 } while( v4l2_ioctl( i_fd
, VIDIOC_ENUM_FRAMEINTERVALS
,
1684 case V4L2_FRMSIZE_TYPE_STEPWISE
:
1685 case V4L2_FRMIVAL_TYPE_CONTINUOUS
:
1686 return __MAX( (float)frmival
.stepwise
.max
.denominator
1687 / (float)frmival
.stepwise
.max
.numerator
,
1688 (float)frmival
.stepwise
.min
.denominator
1689 / (float)frmival
.stepwise
.min
.numerator
);
1696 static float GetAbsoluteMaxFrameRate( demux_t
*p_demux
, int i_fd
,
1697 uint32_t i_pixel_format
)
1699 float f_fps_max
= -1.;
1700 #ifdef VIDIOC_ENUM_FRAMESIZES
1702 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1704 /* This is new in Linux 2.6.19 */
1705 struct v4l2_frmsizeenum frmsize
;
1706 memset( &frmsize
, 0, sizeof(frmsize
) );
1707 frmsize
.pixel_format
= i_pixel_format
;
1708 if( v4l2_ioctl( i_fd
, VIDIOC_ENUM_FRAMESIZES
, &frmsize
) >= 0 )
1710 switch( frmsize
.type
)
1712 case V4L2_FRMSIZE_TYPE_DISCRETE
:
1716 float f_fps
= GetMaxFrameRate( p_demux
, i_fd
,
1718 frmsize
.discrete
.width
,
1719 frmsize
.discrete
.height
);
1720 if( f_fps
> f_fps_max
) f_fps_max
= f_fps
;
1721 } while( v4l2_ioctl( i_fd
, VIDIOC_ENUM_FRAMESIZES
,
1724 case V4L2_FRMSIZE_TYPE_STEPWISE
:
1726 uint32_t i_width
= frmsize
.stepwise
.min_width
;
1727 uint32_t i_height
= frmsize
.stepwise
.min_height
;
1729 i_width
<= frmsize
.stepwise
.max_width
&&
1730 i_height
<= frmsize
.stepwise
.max_width
;
1731 i_width
+= frmsize
.stepwise
.step_width
,
1732 i_height
+= frmsize
.stepwise
.step_height
)
1734 float f_fps
= GetMaxFrameRate( p_demux
, i_fd
,
1736 i_width
, i_height
);
1737 if( f_fps
> f_fps_max
) f_fps_max
= f_fps
;
1741 case V4L2_FRMSIZE_TYPE_CONTINUOUS
:
1743 msg_Err( p_demux
, "GetAbsoluteMaxFrameRate implementation for V4L2_FRMSIZE_TYPE_CONTINUOUS isn't correct" );
1744 f_fps_max
= GetMaxFrameRate( p_demux
, i_fd
,
1746 frmsize
.stepwise
.max_width
,
1747 frmsize
.stepwise
.max_height
);
1755 static void GetMaxDimensions( demux_t
*p_demux
, int i_fd
,
1756 uint32_t i_pixel_format
, float f_fps_min
,
1757 uint32_t *pi_width
, uint32_t *pi_height
)
1761 #ifdef VIDIOC_ENUM_FRAMESIZES
1763 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1765 /* This is new in Linux 2.6.19 */
1766 struct v4l2_frmsizeenum frmsize
;
1767 memset( &frmsize
, 0, sizeof(frmsize
) );
1768 frmsize
.pixel_format
= i_pixel_format
;
1769 if( v4l2_ioctl( i_fd
, VIDIOC_ENUM_FRAMESIZES
, &frmsize
) >= 0 )
1771 switch( frmsize
.type
)
1773 case V4L2_FRMSIZE_TYPE_DISCRETE
:
1777 float f_fps
= GetMaxFrameRate( p_demux
, i_fd
,
1779 frmsize
.discrete
.width
,
1780 frmsize
.discrete
.height
);
1781 if( f_fps
>= f_fps_min
&&
1782 frmsize
.discrete
.width
> *pi_width
)
1784 *pi_width
= frmsize
.discrete
.width
;
1785 *pi_height
= frmsize
.discrete
.height
;
1787 } while( v4l2_ioctl( i_fd
, VIDIOC_ENUM_FRAMESIZES
,
1790 case V4L2_FRMSIZE_TYPE_STEPWISE
:
1792 uint32_t i_width
= frmsize
.stepwise
.min_width
;
1793 uint32_t i_height
= frmsize
.stepwise
.min_height
;
1795 i_width
<= frmsize
.stepwise
.max_width
&&
1796 i_height
<= frmsize
.stepwise
.max_width
;
1797 i_width
+= frmsize
.stepwise
.step_width
,
1798 i_height
+= frmsize
.stepwise
.step_height
)
1800 float f_fps
= GetMaxFrameRate( p_demux
, i_fd
,
1802 i_width
, i_height
);
1803 if( f_fps
>= f_fps_min
&& i_width
> *pi_width
)
1805 *pi_width
= i_width
;
1806 *pi_height
= i_height
;
1811 case V4L2_FRMSIZE_TYPE_CONTINUOUS
:
1813 msg_Err( p_demux
, "GetMaxDimension implementation for V4L2_FRMSIZE_TYPE_CONTINUOUS isn't correct" );
1814 float f_fps
= GetMaxFrameRate( p_demux
, i_fd
,
1816 frmsize
.stepwise
.max_width
,
1817 frmsize
.stepwise
.max_height
);
1818 if( f_fps
>= f_fps_min
&&
1819 frmsize
.stepwise
.max_width
> *pi_width
)
1821 *pi_width
= frmsize
.stepwise
.max_width
;
1822 *pi_height
= frmsize
.stepwise
.max_height
;
1830 /*****************************************************************************
1831 * OpenVideoDev: open and set up the video device and probe for capabilities
1832 *****************************************************************************/
1833 static int OpenVideoDev( vlc_object_t
*p_obj
, demux_sys_t
*p_sys
, bool b_demux
)
1836 struct v4l2_cropcap cropcap
;
1837 struct v4l2_crop crop
;
1838 struct v4l2_format fmt
;
1840 enum v4l2_buf_type buf_type
;
1841 const char *psz_device
= p_sys
->psz_device
;
1844 if( ( i_fd
= v4l2_open( psz_device
, O_RDWR
) ) < 0 )
1846 msg_Err( p_obj
, "cannot open device (%m)" );
1851 /* Note the v4l2_xxx functions are designed so that if they get passed an
1852 unknown fd, the will behave exactly as their regular xxx counterparts,
1853 so if v4l2_fd_open fails, we continue as normal (missing the libv4l2
1854 custom cam format to normal formats conversion). Chances are big we will
1855 still fail then though, as normally v4l2_fd_open only fails if the
1856 device is not a v4l2 device. */
1857 if( p_sys
->b_libv4l2
)
1860 libv4l2_fd
= v4l2_fd_open( i_fd
, V4L2_ENABLE_ENUM_FMT_EMULATION
);
1861 if( libv4l2_fd
!= -1 )
1866 /* Tune the tuner */
1867 if( p_sys
->i_frequency
>= 0 )
1869 if( p_sys
->i_cur_tuner
< 0 || p_sys
->i_cur_tuner
>= p_sys
->i_tuner
)
1871 msg_Err( p_obj
, "invalid tuner %d.", p_sys
->i_cur_tuner
);
1874 struct v4l2_frequency frequency
;
1875 memset( &frequency
, 0, sizeof( frequency
) );
1876 frequency
.tuner
= p_sys
->i_cur_tuner
;
1877 frequency
.type
= p_sys
->p_tuners
[p_sys
->i_cur_tuner
].type
;
1878 frequency
.frequency
= p_sys
->i_frequency
/ 62.5;
1879 if( v4l2_ioctl( i_fd
, VIDIOC_S_FREQUENCY
, &frequency
) < 0 )
1881 msg_Err( p_obj
, "cannot set tuner frequency (%m)" );
1884 msg_Dbg( p_obj
, "Tuner frequency set" );
1887 /* Set the tuner's audio mode */
1888 if( p_sys
->i_audio_mode
>= 0 )
1890 if( p_sys
->i_cur_tuner
< 0 || p_sys
->i_cur_tuner
>= p_sys
->i_tuner
)
1892 msg_Err( p_obj
, "invalid tuner %d.", p_sys
->i_cur_tuner
);
1895 struct v4l2_tuner tuner
;
1896 memset( &tuner
, 0, sizeof( tuner
) );
1897 tuner
.index
= p_sys
->i_cur_tuner
;
1898 tuner
.audmode
= p_sys
->i_audio_mode
;
1899 if( v4l2_ioctl( i_fd
, VIDIOC_S_TUNER
, &tuner
) < 0 )
1901 msg_Err( p_obj
, "cannot set tuner audio mode (%m)" );
1904 msg_Dbg( p_obj
, "Tuner audio mode set" );
1907 /* Select standard */
1909 if( p_sys
->i_selected_standard_id
!= V4L2_STD_UNKNOWN
)
1911 if( v4l2_ioctl( i_fd
, VIDIOC_S_STD
, &p_sys
->i_selected_standard_id
) < 0 )
1913 msg_Err( p_obj
, "cannot set standard (%m)" );
1916 if( v4l2_ioctl( i_fd
, VIDIOC_G_STD
, &p_sys
->i_selected_standard_id
) < 0 )
1918 msg_Err( p_obj
, "cannot get standard (%m). This should never happen!" );
1921 msg_Dbg( p_obj
, "Set standard to (0x%"PRIx64
"):", p_sys
->i_selected_standard_id
);
1923 for( i_standard
= 0; i_standard
<p_sys
->i_standard
; i_standard
++)
1925 if( p_sys
->p_standards
[i_standard
].id
& p_sys
->i_selected_standard_id
)
1927 msg_Dbg( p_obj
, " %s",
1928 p_sys
->p_standards
[i_standard
].name
);
1935 if( p_sys
->i_selected_input
>= p_sys
->i_input
)
1937 msg_Warn( p_obj
, "invalid input. Using the default one" );
1938 p_sys
->i_selected_input
= 0;
1941 if( v4l2_ioctl( i_fd
, VIDIOC_S_INPUT
, &p_sys
->i_selected_input
) < 0 )
1943 msg_Err( p_obj
, "cannot set input (%m)" );
1947 /* Set audio input */
1949 if( p_sys
->i_audio
> 0 )
1951 if( p_sys
->i_selected_audio_input
< 0
1952 || p_sys
->i_selected_audio_input
>= p_sys
->i_audio
)
1954 msg_Warn( p_obj
, "invalid audio input. Using the default one" );
1955 p_sys
->i_selected_audio_input
= 0;
1958 if( v4l2_ioctl( i_fd
, VIDIOC_S_AUDIO
, &p_sys
->p_audios
[p_sys
->i_selected_audio_input
] ) < 0 )
1960 msg_Err( p_obj
, "cannot set audio input (%m)" );
1963 msg_Dbg( p_obj
, "Audio input set to %d", p_sys
->i_selected_audio_input
);
1967 /* TODO: Move the resolution stuff up here */
1968 /* if MPEG encoder card, no need to do anything else after this */
1969 ControlList( p_obj
, p_sys
, i_fd
,
1970 var_GetBool( p_obj
, "v4l2-controls-reset" ), b_demux
);
1971 SetAvailControlsByString( p_obj
, p_sys
, i_fd
);
1973 /* Verify device support for the various IO methods */
1976 case IO_METHOD_READ
:
1977 if( !(p_sys
->dev_cap
.capabilities
& V4L2_CAP_READWRITE
) )
1979 msg_Err( p_obj
, "device does not support read i/o" );
1982 msg_Dbg( p_obj
, "using read i/o" );
1985 case IO_METHOD_MMAP
:
1986 case IO_METHOD_USERPTR
:
1987 if( !(p_sys
->dev_cap
.capabilities
& V4L2_CAP_STREAMING
) )
1989 msg_Err( p_obj
, "device does not support streaming i/o" );
1992 if( p_sys
->io
== IO_METHOD_MMAP
)
1993 msg_Dbg( p_obj
, "using streaming i/o (mmap)" );
1995 msg_Dbg( p_obj
, "using streaming i/o (userptr)" );
1999 msg_Err( p_obj
, "io method not supported" );
2003 /* Reset Cropping */
2004 memset( &cropcap
, 0, sizeof(cropcap
) );
2005 cropcap
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
2006 if( v4l2_ioctl( i_fd
, VIDIOC_CROPCAP
, &cropcap
) >= 0 )
2008 crop
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
2009 crop
.c
= cropcap
.defrect
; /* reset to default */
2010 if( crop
.c
.width
> 0 && crop
.c
.height
> 0 ) /* Fix for fm tuners */
2012 if( v4l2_ioctl( i_fd
, VIDIOC_S_CROP
, &crop
) < 0 )
2017 /* Cropping not supported. */
2020 /* Errors ignored. */
2027 /* Try and find default resolution if not specified */
2028 memset( &fmt
, 0, sizeof(fmt
) );
2029 fmt
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
2031 if( p_sys
->i_width
<= 0 || p_sys
->i_height
<= 0 )
2033 /* Use current width and height settings */
2034 if( v4l2_ioctl( i_fd
, VIDIOC_G_FMT
, &fmt
) < 0 )
2036 msg_Err( p_obj
, "Cannot get default width and height." );
2040 msg_Dbg( p_obj
, "found default width and height of %ux%u",
2041 fmt
.fmt
.pix
.width
, fmt
.fmt
.pix
.height
);
2043 if( p_sys
->i_width
< 0 || p_sys
->i_height
< 0 )
2045 msg_Dbg( p_obj
, "will try to find optimal width and height." );
2050 /* Use user specified width and height */
2051 msg_Dbg( p_obj
, "trying specified size %dx%d", p_sys
->i_width
, p_sys
->i_height
);
2052 fmt
.fmt
.pix
.width
= p_sys
->i_width
;
2053 fmt
.fmt
.pix
.height
= p_sys
->i_height
;
2056 fmt
.fmt
.pix
.field
= V4L2_FIELD_NONE
;
2060 demux_t
*p_demux
= (demux_t
*) p_obj
;
2062 /* Test and set Chroma */
2063 fmt
.fmt
.pix
.pixelformat
= 0;
2064 if( p_sys
->psz_requested_chroma
&& *p_sys
->psz_requested_chroma
)
2066 /* User specified chroma */
2067 const vlc_fourcc_t i_requested_fourcc
=
2068 vlc_fourcc_GetCodecFromString( VIDEO_ES
, p_sys
->psz_requested_chroma
);
2070 for( int i
= 0; v4l2chroma_to_fourcc
[i
].i_v4l2
!= 0; i
++ )
2072 if( v4l2chroma_to_fourcc
[i
].i_fourcc
== i_requested_fourcc
)
2074 fmt
.fmt
.pix
.pixelformat
= v4l2chroma_to_fourcc
[i
].i_v4l2
;
2078 /* Try and set user chroma */
2079 bool b_error
= !IsPixelFormatSupported( p_demux
, fmt
.fmt
.pix
.pixelformat
);
2080 if( !b_error
&& fmt
.fmt
.pix
.pixelformat
)
2082 if( v4l2_ioctl( i_fd
, VIDIOC_S_FMT
, &fmt
) < 0 )
2084 fmt
.fmt
.pix
.field
= V4L2_FIELD_ANY
;
2085 if( v4l2_ioctl( i_fd
, VIDIOC_S_FMT
, &fmt
) < 0 )
2087 fmt
.fmt
.pix
.field
= V4L2_FIELD_NONE
;
2094 msg_Warn( p_demux
, "Driver is unable to use specified chroma %s. Trying defaults.", p_sys
->psz_requested_chroma
);
2095 fmt
.fmt
.pix
.pixelformat
= 0;
2099 /* If no user specified chroma, find best */
2100 /* This also decides if MPEG encoder card or not */
2101 if( !fmt
.fmt
.pix
.pixelformat
)
2104 for( i
= 0; i
< ARRAY_SIZE( p_chroma_fallbacks
); i
++ )
2106 fmt
.fmt
.pix
.pixelformat
= p_chroma_fallbacks
[i
];
2107 if( IsPixelFormatSupported( p_demux
, fmt
.fmt
.pix
.pixelformat
) )
2109 if( v4l2_ioctl( i_fd
, VIDIOC_S_FMT
, &fmt
) >= 0 )
2111 fmt
.fmt
.pix
.field
= V4L2_FIELD_ANY
;
2112 if( v4l2_ioctl( i_fd
, VIDIOC_S_FMT
, &fmt
) >= 0 )
2114 fmt
.fmt
.pix
.field
= V4L2_FIELD_NONE
;
2117 if( i
== ARRAY_SIZE( p_chroma_fallbacks
) )
2119 msg_Warn( p_demux
, "Could not select any of the default chromas; attempting to open as MPEG encoder card (access)" );
2124 if( p_sys
->i_width
< 0 || p_sys
->i_height
< 0 )
2126 if( p_sys
->f_fps
<= 0 )
2128 p_sys
->f_fps
= GetAbsoluteMaxFrameRate( p_demux
, i_fd
,
2129 fmt
.fmt
.pix
.pixelformat
);
2130 msg_Dbg( p_demux
, "Found maximum framerate of %f", p_sys
->f_fps
);
2132 uint32_t i_width
, i_height
;
2133 GetMaxDimensions( p_demux
, i_fd
,
2134 fmt
.fmt
.pix
.pixelformat
, p_sys
->f_fps
,
2135 &i_width
, &i_height
);
2136 if( i_width
|| i_height
)
2138 msg_Dbg( p_demux
, "Found optimal dimensions for framerate %f "
2139 "of %ux%u", p_sys
->f_fps
, i_width
, i_height
);
2140 fmt
.fmt
.pix
.width
= i_width
;
2141 fmt
.fmt
.pix
.height
= i_height
;
2142 if( v4l2_ioctl( i_fd
, VIDIOC_S_FMT
, &fmt
) < 0 )
2144 msg_Err( p_obj
, "Cannot set size to optimal dimensions "
2145 "%ux%u", i_width
, i_height
);
2151 msg_Warn( p_obj
, "Could not find optimal width and height, "
2152 "falling back to driver default." );
2157 p_sys
->i_width
= fmt
.fmt
.pix
.width
;
2158 p_sys
->i_height
= fmt
.fmt
.pix
.height
;
2160 if( v4l2_ioctl( i_fd
, VIDIOC_G_FMT
, &fmt
) < 0 ) {;}
2161 /* Print extra info */
2162 msg_Dbg( p_obj
, "Driver requires at most %d bytes to store a complete image", fmt
.fmt
.pix
.sizeimage
);
2163 /* Check interlacing */
2164 switch( fmt
.fmt
.pix
.field
)
2166 case V4L2_FIELD_NONE
:
2167 msg_Dbg( p_obj
, "Interlacing setting: progressive" );
2169 case V4L2_FIELD_TOP
:
2170 msg_Dbg( p_obj
, "Interlacing setting: top field only" );
2172 case V4L2_FIELD_BOTTOM
:
2173 msg_Dbg( p_obj
, "Interlacing setting: bottom field only" );
2175 case V4L2_FIELD_INTERLACED
:
2176 msg_Dbg( p_obj
, "Interlacing setting: interleaved (bottom top if M/NTSC, top bottom otherwise)" );
2177 if( p_sys
->i_selected_standard_id
== V4L2_STD_NTSC
)
2178 p_sys
->i_block_flags
= BLOCK_FLAG_BOTTOM_FIELD_FIRST
;
2180 p_sys
->i_block_flags
= BLOCK_FLAG_TOP_FIELD_FIRST
;
2182 case V4L2_FIELD_SEQ_TB
:
2183 msg_Dbg( p_obj
, "Interlacing setting: sequential top bottom (TODO)" );
2185 case V4L2_FIELD_SEQ_BT
:
2186 msg_Dbg( p_obj
, "Interlacing setting: sequential bottom top (TODO)" );
2188 case V4L2_FIELD_ALTERNATE
:
2189 msg_Dbg( p_obj
, "Interlacing setting: alternate fields (TODO)" );
2190 p_sys
->i_height
= p_sys
->i_height
* 2;
2192 case V4L2_FIELD_INTERLACED_TB
:
2193 msg_Dbg( p_obj
, "Interlacing setting: interleaved top bottom" );
2194 p_sys
->i_block_flags
= BLOCK_FLAG_TOP_FIELD_FIRST
;
2196 case V4L2_FIELD_INTERLACED_BT
:
2197 msg_Dbg( p_obj
, "Interlacing setting: interleaved bottom top" );
2198 p_sys
->i_block_flags
= BLOCK_FLAG_BOTTOM_FIELD_FIRST
;
2201 msg_Warn( p_obj
, "Interlacing setting: unknown type (%d)",
2202 fmt
.fmt
.pix
.field
);
2206 /* Look up final fourcc */
2207 p_sys
->i_fourcc
= 0;
2208 for( int i
= 0; v4l2chroma_to_fourcc
[i
].i_fourcc
!= 0; i
++ )
2210 if( v4l2chroma_to_fourcc
[i
].i_v4l2
== fmt
.fmt
.pix
.pixelformat
)
2212 p_sys
->i_fourcc
= v4l2chroma_to_fourcc
[i
].i_fourcc
;
2213 es_format_Init( &es_fmt
, VIDEO_ES
, p_sys
->i_fourcc
);
2214 es_fmt
.video
.i_rmask
= v4l2chroma_to_fourcc
[i
].i_rmask
;
2215 es_fmt
.video
.i_gmask
= v4l2chroma_to_fourcc
[i
].i_gmask
;
2216 es_fmt
.video
.i_bmask
= v4l2chroma_to_fourcc
[i
].i_bmask
;
2221 /* Buggy driver paranoia */
2222 i_min
= fmt
.fmt
.pix
.width
* 2;
2223 if( fmt
.fmt
.pix
.bytesperline
< i_min
)
2224 fmt
.fmt
.pix
.bytesperline
= i_min
;
2225 i_min
= fmt
.fmt
.pix
.bytesperline
* fmt
.fmt
.pix
.height
;
2226 if( fmt
.fmt
.pix
.sizeimage
< i_min
)
2227 fmt
.fmt
.pix
.sizeimage
= i_min
;
2229 #ifdef VIDIOC_ENUM_FRAMEINTERVALS
2230 /* This is new in Linux 2.6.19 */
2231 /* List supported frame rates */
2232 struct v4l2_frmivalenum frmival
;
2233 memset( &frmival
, 0, sizeof(frmival
) );
2234 frmival
.pixel_format
= fmt
.fmt
.pix
.pixelformat
;
2235 frmival
.width
= p_sys
->i_width
;
2236 frmival
.height
= p_sys
->i_height
;
2237 if( v4l2_ioctl( i_fd
, VIDIOC_ENUM_FRAMEINTERVALS
, &frmival
) >= 0 )
2240 memset( &psz_fourcc
, 0, sizeof( psz_fourcc
) );
2241 vlc_fourcc_to_char( p_sys
->i_fourcc
, &psz_fourcc
);
2242 msg_Dbg( p_obj
, "supported frame intervals for %4.4s, %dx%d:",
2243 psz_fourcc
, frmival
.width
, frmival
.height
);
2244 switch( frmival
.type
)
2246 case V4L2_FRMIVAL_TYPE_DISCRETE
:
2249 msg_Dbg( p_obj
, " supported frame interval: %d/%d",
2250 frmival
.discrete
.numerator
,
2251 frmival
.discrete
.denominator
);
2253 } while( v4l2_ioctl( i_fd
, VIDIOC_ENUM_FRAMEINTERVALS
, &frmival
) >= 0 );
2255 case V4L2_FRMIVAL_TYPE_STEPWISE
:
2256 msg_Dbg( p_obj
, " supported frame intervals: %d/%d to "
2257 "%d/%d using %d/%d increments",
2258 frmival
.stepwise
.min
.numerator
,
2259 frmival
.stepwise
.min
.denominator
,
2260 frmival
.stepwise
.max
.numerator
,
2261 frmival
.stepwise
.max
.denominator
,
2262 frmival
.stepwise
.step
.numerator
,
2263 frmival
.stepwise
.step
.denominator
);
2265 case V4L2_FRMIVAL_TYPE_CONTINUOUS
:
2266 msg_Dbg( p_obj
, " supported frame intervals: %d/%d to %d/%d",
2267 frmival
.stepwise
.min
.numerator
,
2268 frmival
.stepwise
.min
.denominator
,
2269 frmival
.stepwise
.max
.numerator
,
2270 frmival
.stepwise
.max
.denominator
);
2277 /* Init IO method */
2280 case IO_METHOD_READ
:
2282 if( InitRead( p_obj
, p_sys
, fmt
.fmt
.pix
.sizeimage
) != VLC_SUCCESS
) goto open_failed
;
2285 case IO_METHOD_MMAP
:
2286 if( InitMmap( p_obj
, p_sys
, i_fd
) != VLC_SUCCESS
) goto open_failed
;
2289 case IO_METHOD_USERPTR
:
2290 if( InitUserP( p_obj
, p_sys
, i_fd
, fmt
.fmt
.pix
.sizeimage
) != VLC_SUCCESS
) goto open_failed
;
2301 es_fmt
.video
.i_width
= p_sys
->i_width
;
2302 es_fmt
.video
.i_height
= p_sys
->i_height
;
2304 /* Get aspect-ratio */
2305 es_fmt
.video
.i_sar_num
= p_sys
->i_aspect
* es_fmt
.video
.i_height
;
2306 es_fmt
.video
.i_sar_den
= VOUT_ASPECT_FACTOR
* es_fmt
.video
.i_width
;
2308 demux_t
*p_demux
= (demux_t
*) p_obj
;
2309 msg_Dbg( p_demux
, "added new video es %4.4s %dx%d",
2310 (char*)&es_fmt
.i_codec
, es_fmt
.video
.i_width
, es_fmt
.video
.i_height
);
2311 p_sys
->p_es
= es_out_Add( p_demux
->out
, &es_fmt
);
2318 case IO_METHOD_READ
:
2322 case IO_METHOD_MMAP
:
2323 for (unsigned int i
= 0; i
< p_sys
->i_nbuffers
; ++i
)
2325 struct v4l2_buffer buf
;
2327 memset( &buf
, 0, sizeof(buf
) );
2328 buf
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
2329 buf
.memory
= V4L2_MEMORY_MMAP
;
2332 if( v4l2_ioctl( i_fd
, VIDIOC_QBUF
, &buf
) < 0 )
2334 msg_Err( p_obj
, "VIDIOC_QBUF failed" );
2339 buf_type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
2340 if( v4l2_ioctl( i_fd
, VIDIOC_STREAMON
, &buf_type
) < 0 )
2342 msg_Err( p_obj
, "VIDIOC_STREAMON failed" );
2348 case IO_METHOD_USERPTR
:
2349 for( unsigned int i
= 0; i
< p_sys
->i_nbuffers
; ++i
)
2351 struct v4l2_buffer buf
;
2353 memset( &buf
, 0, sizeof(buf
) );
2354 buf
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
2355 buf
.memory
= V4L2_MEMORY_USERPTR
;
2357 buf
.m
.userptr
= (unsigned long)p_sys
->p_buffers
[i
].start
;
2358 buf
.length
= p_sys
->p_buffers
[i
].length
;
2360 if( v4l2_ioctl( i_fd
, VIDIOC_QBUF
, &buf
) < 0 )
2362 msg_Err( p_obj
, "VIDIOC_QBUF failed" );
2367 buf_type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
2368 if( v4l2_ioctl( i_fd
, VIDIOC_STREAMON
, &buf_type
) < 0 )
2370 msg_Err( p_obj
, "VIDIOC_STREAMON failed" );
2382 if( p_sys
->f_fps
>= 0.1 )
2384 msg_Dbg( p_obj
, "User set fps=%f", p_sys
->f_fps
);
2390 if( i_fd
>= 0 ) v4l2_close( i_fd
);
2395 /*****************************************************************************
2396 * ProbeVideoDev: probe video for capabilities
2397 *****************************************************************************/
2398 static bool ProbeVideoDev( vlc_object_t
*p_obj
, demux_sys_t
*p_sys
,
2399 const char *psz_device
)
2406 if( ( i_fd
= v4l2_open( psz_device
, O_RDWR
) ) < 0 )
2408 msg_Err( p_obj
, "cannot open video device '%s' (%m)", psz_device
);
2413 /* Note the v4l2_xxx functions are designed so that if they get passed an
2414 unknown fd, the will behave exactly as their regular xxx counterparts,
2415 so if v4l2_fd_open fails, we continue as normal (missing the libv4l2
2416 custom cam format to normal formats conversion). Chances are big we will
2417 still fail then though, as normally v4l2_fd_open only fails if the
2418 device is not a v4l2 device. */
2419 if( p_sys
->b_libv4l2
)
2422 libv4l2_fd
= v4l2_fd_open( i_fd
, V4L2_ENABLE_ENUM_FMT_EMULATION
);
2423 if( libv4l2_fd
!= -1 )
2428 /* Get device capabilites */
2430 if( v4l2_ioctl( i_fd
, VIDIOC_QUERYCAP
, &p_sys
->dev_cap
) < 0 )
2432 msg_Err( p_obj
, "cannot get video capabilities (%m)" );
2436 msg_Dbg( p_obj
, "V4L2 device: %s using driver: %s (version: %u.%u.%u) on %s",
2437 p_sys
->dev_cap
.card
,
2438 p_sys
->dev_cap
.driver
,
2439 (p_sys
->dev_cap
.version
>> 16) & 0xFF,
2440 (p_sys
->dev_cap
.version
>> 8) & 0xFF,
2441 p_sys
->dev_cap
.version
& 0xFF,
2442 p_sys
->dev_cap
.bus_info
);
2444 msg_Dbg( p_obj
, "the device has the capabilities: (%c) Video Capture, "
2448 ( p_sys
->dev_cap
.capabilities
& V4L2_CAP_VIDEO_CAPTURE
? 'X':' '),
2449 ( p_sys
->dev_cap
.capabilities
& V4L2_CAP_AUDIO
? 'X':' '),
2450 ( p_sys
->dev_cap
.capabilities
& V4L2_CAP_TUNER
? 'X':' '),
2451 ( p_sys
->dev_cap
.capabilities
& V4L2_CAP_RADIO
? 'X':' ') );
2453 msg_Dbg( p_obj
, "supported I/O methods are: (%c) Read/Write, "
2455 "(%c) Asynchronous",
2456 ( p_sys
->dev_cap
.capabilities
& V4L2_CAP_READWRITE
? 'X':' ' ),
2457 ( p_sys
->dev_cap
.capabilities
& V4L2_CAP_STREAMING
? 'X':' ' ),
2458 ( p_sys
->dev_cap
.capabilities
& V4L2_CAP_ASYNCIO
? 'X':' ' ) );
2460 if( p_sys
->io
== IO_METHOD_AUTO
)
2462 if( p_sys
->dev_cap
.capabilities
& V4L2_CAP_STREAMING
)
2463 p_sys
->io
= IO_METHOD_MMAP
;
2464 else if( p_sys
->dev_cap
.capabilities
& V4L2_CAP_READWRITE
)
2465 p_sys
->io
= IO_METHOD_READ
;
2467 msg_Err( p_obj
, "No known I/O method supported" );
2470 if( p_sys
->dev_cap
.capabilities
& V4L2_CAP_RDS_CAPTURE
)
2471 msg_Dbg( p_obj
, "device supports RDS" );
2473 #ifdef V4L2_CAP_HW_FREQ_SEEK
2474 if( p_sys
->dev_cap
.capabilities
& V4L2_CAP_HW_FREQ_SEEK
)
2475 msg_Dbg( p_obj
, "device supports hardware frequency seeking" );
2477 if( p_sys
->dev_cap
.capabilities
& V4L2_CAP_VBI_CAPTURE
)
2478 msg_Dbg( p_obj
, "device supports raw VBI capture" );
2480 if( p_sys
->dev_cap
.capabilities
& V4L2_CAP_SLICED_VBI_CAPTURE
)
2481 msg_Dbg( p_obj
, "device supports sliced VBI capture" );
2483 /* Now, enumerate all the video inputs. This is useless at the moment
2484 since we have no way to present that info to the user except with
2487 if( p_sys
->dev_cap
.capabilities
& V4L2_CAP_VIDEO_CAPTURE
)
2489 struct v4l2_input t_input
;
2490 memset( &t_input
, 0, sizeof(t_input
) );
2492 while( v4l2_ioctl( i_fd
, VIDIOC_ENUMINPUT
, &t_input
) >= 0 )
2495 t_input
.index
= p_sys
->i_input
;
2498 free( p_sys
->p_inputs
);
2499 p_sys
->p_inputs
= calloc( 1, p_sys
->i_input
* sizeof( struct v4l2_input
) );
2500 if( !p_sys
->p_inputs
) goto open_failed
;
2502 for( i_index
= 0; i_index
< p_sys
->i_input
; i_index
++ )
2504 p_sys
->p_inputs
[i_index
].index
= i_index
;
2506 if( v4l2_ioctl( i_fd
, VIDIOC_ENUMINPUT
, &p_sys
->p_inputs
[i_index
] ) )
2508 msg_Err( p_obj
, "cannot get video input characteristics (%m)" );
2511 msg_Dbg( p_obj
, "video input %i (%s) has type: %s %c",
2513 p_sys
->p_inputs
[i_index
].name
,
2514 p_sys
->p_inputs
[i_index
].type
2515 == V4L2_INPUT_TYPE_TUNER
?
2517 "External analog input",
2518 i_index
== p_sys
->i_selected_input
? '*' : ' ' );
2522 /* Probe video standards */
2523 if( p_sys
->dev_cap
.capabilities
& V4L2_CAP_VIDEO_CAPTURE
)
2525 struct v4l2_standard t_standards
;
2526 t_standards
.index
= 0;
2527 p_sys
->i_standard
= 0;
2528 while( v4l2_ioctl( i_fd
, VIDIOC_ENUMSTD
, &t_standards
) >=0 )
2530 p_sys
->i_standard
++;
2531 t_standards
.index
= p_sys
->i_standard
;
2534 free( p_sys
->p_standards
);
2535 p_sys
->p_standards
= calloc( 1, p_sys
->i_standard
* sizeof( struct v4l2_standard
) );
2536 if( !p_sys
->p_standards
) goto open_failed
;
2538 for( i_standard
= 0; i_standard
< p_sys
->i_standard
; i_standard
++ )
2540 p_sys
->p_standards
[i_standard
].index
= i_standard
;
2542 if( v4l2_ioctl( i_fd
, VIDIOC_ENUMSTD
, &p_sys
->p_standards
[i_standard
] ) )
2544 msg_Err( p_obj
, "cannot get video input standards (%m)" );
2547 msg_Dbg( p_obj
, "video standard %i is: %s %c",
2549 p_sys
->p_standards
[i_standard
].name
,
2550 (p_sys
->p_standards
[i_standard
].id
& p_sys
->i_selected_standard_id
) ? '*' : ' ' );
2554 /* initialize the structures for the ioctls */
2555 for( i_index
= 0; i_index
< 32; i_index
++ )
2557 p_sys
->p_audios
[i_index
].index
= i_index
;
2560 /* Probe audio inputs */
2561 if( p_sys
->dev_cap
.capabilities
& V4L2_CAP_AUDIO
)
2563 while( p_sys
->i_audio
< 32 &&
2564 v4l2_ioctl( i_fd
, VIDIOC_S_AUDIO
, &p_sys
->p_audios
[p_sys
->i_audio
] ) >= 0 )
2566 if( v4l2_ioctl( i_fd
, VIDIOC_G_AUDIO
, &p_sys
->p_audios
[ p_sys
->i_audio
] ) < 0 )
2568 msg_Err( p_obj
, "cannot get audio input characteristics (%m)" );
2572 msg_Dbg( p_obj
, "audio input %i (%s) is %s %s %c",
2574 p_sys
->p_audios
[p_sys
->i_audio
].name
,
2575 p_sys
->p_audios
[p_sys
->i_audio
].capability
&
2576 V4L2_AUDCAP_STEREO
?
2578 p_sys
->p_audios
[p_sys
->i_audio
].capability
&
2580 "(Automatic Volume Level supported)" : "",
2581 p_sys
->i_audio
== p_sys
->i_selected_audio_input
? '*' : ' ' );
2587 /* List tuner caps */
2588 if( p_sys
->dev_cap
.capabilities
& V4L2_CAP_TUNER
)
2590 struct v4l2_tuner tuner
;
2591 memset( &tuner
, 0, sizeof(tuner
) );
2593 while( v4l2_ioctl( i_fd
, VIDIOC_G_TUNER
, &tuner
) >= 0 )
2596 memset( &tuner
, 0, sizeof(tuner
) );
2597 tuner
.index
= p_sys
->i_tuner
;
2600 free( p_sys
->p_tuners
);
2601 p_sys
->p_tuners
= calloc( 1, p_sys
->i_tuner
* sizeof( struct v4l2_tuner
) );
2602 if( !p_sys
->p_tuners
) goto open_failed
;
2604 for( i_index
= 0; i_index
< p_sys
->i_tuner
; i_index
++ )
2606 p_sys
->p_tuners
[i_index
].index
= i_index
;
2608 if( v4l2_ioctl( i_fd
, VIDIOC_G_TUNER
, &p_sys
->p_tuners
[i_index
] ) )
2610 msg_Err( p_obj
, "cannot get tuner characteristics (%m)" );
2613 msg_Dbg( p_obj
, "tuner %i (%s) has type: %s, "
2614 "frequency range: %.1f %s -> %.1f %s",
2616 p_sys
->p_tuners
[i_index
].name
,
2617 p_sys
->p_tuners
[i_index
].type
2618 == V4L2_TUNER_RADIO
?
2619 "Radio" : "Analog TV",
2620 p_sys
->p_tuners
[i_index
].rangelow
* 62.5,
2621 p_sys
->p_tuners
[i_index
].capability
&
2622 V4L2_TUNER_CAP_LOW
?
2624 p_sys
->p_tuners
[i_index
].rangehigh
* 62.5,
2625 p_sys
->p_tuners
[i_index
].capability
&
2626 V4L2_TUNER_CAP_LOW
?
2629 struct v4l2_frequency frequency
;
2630 memset( &frequency
, 0, sizeof( frequency
) );
2631 if( v4l2_ioctl( i_fd
, VIDIOC_G_FREQUENCY
, &frequency
) < 0 )
2633 msg_Err( p_obj
, "cannot get tuner frequency (%m)" );
2636 msg_Dbg( p_obj
, "tuner %i (%s) frequency: %.1f %s",
2638 p_sys
->p_tuners
[i_index
].name
,
2639 frequency
.frequency
* 62.5,
2640 p_sys
->p_tuners
[i_index
].capability
&
2641 V4L2_TUNER_CAP_LOW
?
2646 /* Probe for available chromas */
2647 if( p_sys
->dev_cap
.capabilities
& V4L2_CAP_VIDEO_CAPTURE
)
2649 struct v4l2_fmtdesc codec
;
2652 memset( &codec
, 0, sizeof(codec
) );
2653 codec
.index
= i_index
;
2654 codec
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
2656 while( v4l2_ioctl( i_fd
, VIDIOC_ENUM_FMT
, &codec
) >= 0 )
2659 codec
.index
= i_index
;
2662 p_sys
->i_codec
= i_index
;
2664 free( p_sys
->p_codecs
);
2665 p_sys
->p_codecs
= calloc( 1, p_sys
->i_codec
* sizeof( struct v4l2_fmtdesc
) );
2667 for( i_index
= 0; i_index
< p_sys
->i_codec
; i_index
++ )
2669 p_sys
->p_codecs
[i_index
].index
= i_index
;
2670 p_sys
->p_codecs
[i_index
].type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
2672 if( v4l2_ioctl( i_fd
, VIDIOC_ENUM_FMT
, &p_sys
->p_codecs
[i_index
] ) < 0 )
2674 msg_Err( p_obj
, "cannot get codec description (%m)" );
2678 /* only print if vlc supports the format */
2679 char psz_fourcc_v4l2
[5];
2680 memset( &psz_fourcc_v4l2
, 0, sizeof( psz_fourcc_v4l2
) );
2681 vlc_fourcc_to_char( p_sys
->p_codecs
[i_index
].pixelformat
,
2683 bool b_codec_supported
= false;
2684 for( int i
= 0; v4l2chroma_to_fourcc
[i
].i_v4l2
!= 0; i
++ )
2686 if( v4l2chroma_to_fourcc
[i
].i_v4l2
== p_sys
->p_codecs
[i_index
].pixelformat
)
2688 b_codec_supported
= true;
2691 memset( &psz_fourcc
, 0, sizeof( psz_fourcc
) );
2692 vlc_fourcc_to_char( v4l2chroma_to_fourcc
[i
].i_fourcc
,
2694 msg_Dbg( p_obj
, "device supports chroma %4.4s [%s, %s]",
2696 p_sys
->p_codecs
[i_index
].description
,
2699 #ifdef VIDIOC_ENUM_FRAMESIZES
2700 /* This is new in Linux 2.6.19 */
2701 /* List valid frame sizes for this format */
2702 struct v4l2_frmsizeenum frmsize
;
2703 memset( &frmsize
, 0, sizeof(frmsize
) );
2704 frmsize
.pixel_format
= p_sys
->p_codecs
[i_index
].pixelformat
;
2705 if( v4l2_ioctl( i_fd
, VIDIOC_ENUM_FRAMESIZES
, &frmsize
) < 0 )
2707 /* Not all devices support this ioctl */
2708 msg_Warn( p_obj
, "Unable to query for frame sizes" );
2712 switch( frmsize
.type
)
2714 case V4L2_FRMSIZE_TYPE_DISCRETE
:
2718 " device supports size %dx%d",
2719 frmsize
.discrete
.width
, frmsize
.discrete
.height
);
2721 } while( v4l2_ioctl( i_fd
, VIDIOC_ENUM_FRAMESIZES
, &frmsize
) >= 0 );
2723 case V4L2_FRMSIZE_TYPE_STEPWISE
:
2725 " device supports sizes %dx%d to %dx%d using %dx%d increments",
2726 frmsize
.stepwise
.min_width
, frmsize
.stepwise
.min_height
,
2727 frmsize
.stepwise
.max_width
, frmsize
.stepwise
.max_height
,
2728 frmsize
.stepwise
.step_width
, frmsize
.stepwise
.step_height
);
2730 case V4L2_FRMSIZE_TYPE_CONTINUOUS
:
2732 " device supports all sizes %dx%d to %dx%d",
2733 frmsize
.stepwise
.min_width
, frmsize
.stepwise
.min_height
,
2734 frmsize
.stepwise
.max_width
, frmsize
.stepwise
.max_height
);
2741 if( !b_codec_supported
)
2744 "device codec %4.4s (%s) not supported",
2746 p_sys
->p_codecs
[i_index
].description
);
2752 if( i_fd
>= 0 ) v4l2_close( i_fd
);
2757 if( i_fd
>= 0 ) v4l2_close( i_fd
);
2762 static void name2var( unsigned char *name
)
2764 for( ; *name
; name
++ )
2765 *name
= (*name
== ' ') ? '_' : tolower( *name
);
2768 /*****************************************************************************
2769 * Print a user-class v4l2 control's details, create the relevant variable,
2770 * change the value if needed.
2771 *****************************************************************************/
2772 static void ControlListPrint( vlc_object_t
*p_obj
, demux_sys_t
*p_sys
, int i_fd
,
2773 struct v4l2_queryctrl queryctrl
,
2774 bool b_reset
, bool b_demux
)
2776 struct v4l2_querymenu querymenu
;
2783 vlc_value_t val
, val2
;
2785 if( queryctrl
.flags
& V4L2_CTRL_FLAG_GRABBED
)
2786 msg_Dbg( p_obj
, " control is busy" );
2787 if( queryctrl
.flags
& V4L2_CTRL_FLAG_READ_ONLY
)
2788 msg_Dbg( p_obj
, " control is read-only" );
2790 for( i
= 0; controls
[i
].psz_name
!= NULL
; i
++ )
2791 if( controls
[i
].i_cid
== queryctrl
.id
) break;
2793 if( controls
[i
].psz_name
)
2795 psz_name
= strdup( controls
[i
].psz_name
);
2796 char psz_cfg_name
[40];
2797 sprintf( psz_cfg_name
, CFG_PREFIX
"%s", psz_name
);
2798 i_val
= var_CreateGetInteger( p_obj
, psz_cfg_name
);
2799 var_Destroy( p_obj
, psz_cfg_name
);
2803 psz_name
= strdup( (const char *)queryctrl
.name
);
2804 name2var( (unsigned char *)psz_name
);
2808 switch( queryctrl
.type
)
2810 case V4L2_CTRL_TYPE_INTEGER
:
2811 msg_Dbg( p_obj
, " integer control" );
2813 " valid values: %d to %d by steps of %d",
2814 queryctrl
.minimum
, queryctrl
.maximum
,
2817 var_Create( p_obj
, psz_name
,
2818 VLC_VAR_INTEGER
| VLC_VAR_HASMIN
| VLC_VAR_HASMAX
2819 | VLC_VAR_HASSTEP
| VLC_VAR_ISCOMMAND
);
2820 val
.i_int
= queryctrl
.minimum
;
2821 var_Change( p_obj
, psz_name
, VLC_VAR_SETMIN
, &val
, NULL
);
2822 val
.i_int
= queryctrl
.maximum
;
2823 var_Change( p_obj
, psz_name
, VLC_VAR_SETMAX
, &val
, NULL
);
2824 val
.i_int
= queryctrl
.step
;
2825 var_Change( p_obj
, psz_name
, VLC_VAR_SETSTEP
, &val
, NULL
);
2827 case V4L2_CTRL_TYPE_BOOLEAN
:
2828 msg_Dbg( p_obj
, " boolean control" );
2829 var_Create( p_obj
, psz_name
,
2830 VLC_VAR_BOOL
| VLC_VAR_ISCOMMAND
);
2832 case V4L2_CTRL_TYPE_MENU
:
2833 msg_Dbg( p_obj
, " menu control" );
2834 var_Create( p_obj
, psz_name
,
2835 VLC_VAR_INTEGER
| VLC_VAR_HASCHOICE
2836 | VLC_VAR_ISCOMMAND
);
2837 memset( &querymenu
, 0, sizeof( querymenu
) );
2838 for( i_mid
= queryctrl
.minimum
;
2839 i_mid
<= (unsigned)queryctrl
.maximum
;
2842 querymenu
.index
= i_mid
;
2843 querymenu
.id
= queryctrl
.id
;
2844 if( v4l2_ioctl( i_fd
, VIDIOC_QUERYMENU
, &querymenu
) >= 0 )
2846 msg_Dbg( p_obj
, " %d: %s",
2847 querymenu
.index
, querymenu
.name
);
2848 val
.i_int
= querymenu
.index
;
2849 val2
.psz_string
= (char *)querymenu
.name
;
2850 var_Change( p_obj
, psz_name
,
2851 VLC_VAR_ADDCHOICE
, &val
, &val2
);
2855 case V4L2_CTRL_TYPE_BUTTON
:
2856 msg_Dbg( p_obj
, " button control" );
2857 var_Create( p_obj
, psz_name
,
2858 VLC_VAR_VOID
| VLC_VAR_ISCOMMAND
);
2860 case V4L2_CTRL_TYPE_CTRL_CLASS
:
2861 msg_Dbg( p_obj
, " control class" );
2862 var_Create( p_obj
, psz_name
, VLC_VAR_VOID
);
2865 msg_Dbg( p_obj
, " unknown control type (FIXME)" );
2870 switch( queryctrl
.type
)
2872 case V4L2_CTRL_TYPE_INTEGER
:
2873 case V4L2_CTRL_TYPE_BOOLEAN
:
2874 case V4L2_CTRL_TYPE_MENU
:
2876 struct v4l2_control control
;
2877 msg_Dbg( p_obj
, " default value: %d",
2878 queryctrl
.default_value
);
2879 memset( &control
, 0, sizeof( control
) );
2880 control
.id
= queryctrl
.id
;
2881 if( v4l2_ioctl( i_fd
, VIDIOC_G_CTRL
, &control
) >= 0 )
2883 msg_Dbg( p_obj
, " current value: %d", control
.value
);
2887 i_val
= control
.value
;
2888 if( b_reset
&& queryctrl
.default_value
!= control
.value
)
2890 msg_Dbg( p_obj
, " reset value to default" );
2891 Control( p_obj
, p_sys
, i_fd
, psz_name
,
2892 queryctrl
.id
, queryctrl
.default_value
);
2897 Control( p_obj
, p_sys
, i_fd
, psz_name
,
2898 queryctrl
.id
, i_val
);
2906 val
.psz_string
= (char *)queryctrl
.name
;
2907 var_Change( p_obj
, psz_name
, VLC_VAR_SETTEXT
, &val
, NULL
);
2908 val
.i_int
= queryctrl
.id
;
2909 val2
.psz_string
= (char *)psz_name
;
2910 var_Change( p_obj
, "allcontrols", VLC_VAR_ADDCHOICE
, &val
, &val2
);
2911 /* bad things happen changing MPEG mid-stream
2912 * so don't add to Ext Settings GUI */
2913 if( V4L2_CTRL_ID2CLASS( queryctrl
.id
) != V4L2_CTRL_CLASS_MPEG
)
2914 var_Change( p_obj
, "controls", VLC_VAR_ADDCHOICE
, &val
, &val2
);
2916 switch( var_Type( p_obj
, psz_name
) & VLC_VAR_TYPE
)
2919 var_SetBool( p_obj
, psz_name
, i_val
);
2921 case VLC_VAR_INTEGER
:
2922 var_SetInteger( p_obj
, psz_name
, i_val
);
2927 msg_Warn( p_obj
, "FIXME: %s %s %d", __FILE__
, __func__
,
2933 var_AddCallback( p_obj
, psz_name
,
2934 DemuxControlCallback
, (void*)(intptr_t)queryctrl
.id
);
2936 var_AddCallback( p_obj
, psz_name
,
2937 AccessControlCallback
, (void*)(intptr_t)queryctrl
.id
);
2942 /*****************************************************************************
2943 * List all user-class v4l2 controls, set them to the user specified
2944 * value and create the relevant variables to enable runtime changes
2945 *****************************************************************************/
2946 static int ControlList( vlc_object_t
*p_obj
, demux_sys_t
*p_sys
, int i_fd
,
2947 bool b_reset
, bool b_demux
)
2949 struct v4l2_queryctrl queryctrl
;
2952 memset( &queryctrl
, 0, sizeof( queryctrl
) );
2954 /* A list of available controls (aka the variable name) will be
2955 * stored as choices in the "allcontrols" variable. We'll thus be able
2956 * to use those to create an appropriate interface
2957 * A list of available controls that can be changed mid-stream will
2958 * be stored in the "controls" variable */
2959 var_Create( p_obj
, "controls", VLC_VAR_INTEGER
| VLC_VAR_HASCHOICE
);
2960 var_Create( p_obj
, "allcontrols", VLC_VAR_INTEGER
| VLC_VAR_HASCHOICE
);
2962 var_Create( p_obj
, "controls-update", VLC_VAR_VOID
| VLC_VAR_ISCOMMAND
);
2964 /* Add a control to reset all controls to their default values */
2965 vlc_value_t val
, val2
;
2966 var_Create( p_obj
, "controls-reset", VLC_VAR_VOID
| VLC_VAR_ISCOMMAND
);
2967 val
.psz_string
= _( "Reset controls to default" );
2968 var_Change( p_obj
, "controls-reset", VLC_VAR_SETTEXT
, &val
, NULL
);
2970 val2
.psz_string
= (char *)"controls-reset";
2971 var_Change( p_obj
, "controls", VLC_VAR_ADDCHOICE
, &val
, &val2
);
2973 var_AddCallback( p_obj
, "controls-reset", DemuxControlResetCallback
, NULL
);
2975 var_AddCallback( p_obj
, "controls-reset", AccessControlResetCallback
, NULL
);
2977 queryctrl
.id
= V4L2_CTRL_FLAG_NEXT_CTRL
;
2978 if( v4l2_ioctl( i_fd
, VIDIOC_QUERYCTRL
, &queryctrl
) >= 0 )
2980 msg_Dbg( p_obj
, "Extended control API supported by v4l2 driver" );
2982 /* List extended controls */
2983 queryctrl
.id
= V4L2_CTRL_FLAG_NEXT_CTRL
;
2984 while( v4l2_ioctl( i_fd
, VIDIOC_QUERYCTRL
, &queryctrl
) >= 0 )
2986 if( queryctrl
.type
== V4L2_CTRL_TYPE_CTRL_CLASS
)
2988 msg_Dbg( p_obj
, "%s", queryctrl
.name
);
2989 queryctrl
.id
|= V4L2_CTRL_FLAG_NEXT_CTRL
;
2992 switch( V4L2_CTRL_ID2CLASS( queryctrl
.id
) )
2994 case V4L2_CTRL_CLASS_USER
:
2995 msg_Dbg( p_obj
, "Available control: %s (%x)",
2996 queryctrl
.name
, queryctrl
.id
);
2998 case V4L2_CTRL_CLASS_MPEG
:
2999 name2var( queryctrl
.name
);
3000 msg_Dbg( p_obj
, "Available MPEG control: %s (%x)",
3001 queryctrl
.name
, queryctrl
.id
);
3004 msg_Dbg( p_obj
, "Available private control: %s (%x)",
3005 queryctrl
.name
, queryctrl
.id
);
3008 ControlListPrint( p_obj
, p_sys
, i_fd
, queryctrl
, b_reset
, b_demux
);
3009 queryctrl
.id
|= V4L2_CTRL_FLAG_NEXT_CTRL
;
3014 msg_Dbg( p_obj
, "Extended control API not supported by v4l2 driver" );
3016 /* List public controls */
3017 for( i_cid
= V4L2_CID_BASE
;
3018 i_cid
< V4L2_CID_LASTP1
;
3021 queryctrl
.id
= i_cid
;
3022 if( v4l2_ioctl( i_fd
, VIDIOC_QUERYCTRL
, &queryctrl
) >= 0 )
3024 if( queryctrl
.flags
& V4L2_CTRL_FLAG_DISABLED
)
3026 msg_Dbg( p_obj
, "Available control: %s (%x)",
3027 queryctrl
.name
, queryctrl
.id
);
3028 ControlListPrint( p_obj
, p_sys
, i_fd
, queryctrl
,
3033 /* List private controls */
3034 for( i_cid
= V4L2_CID_PRIVATE_BASE
;
3038 queryctrl
.id
= i_cid
;
3039 if( v4l2_ioctl( i_fd
, VIDIOC_QUERYCTRL
, &queryctrl
) >= 0 )
3041 if( queryctrl
.flags
& V4L2_CTRL_FLAG_DISABLED
)
3043 msg_Dbg( p_obj
, "Available private control: %s (%x)",
3044 queryctrl
.name
, queryctrl
.id
);
3045 ControlListPrint( p_obj
, p_sys
, i_fd
, queryctrl
,
3056 static void SetAvailControlsByString( vlc_object_t
*p_obj
, demux_sys_t
*p_sys
,
3059 char *psz_parser
= p_sys
->psz_set_ctrls
;
3060 vlc_value_t val
, text
, name
;
3062 if( psz_parser
== NULL
)
3065 if( *psz_parser
== '{' )
3068 int i_ret
= var_Change( p_obj
, "allcontrols", VLC_VAR_GETCHOICES
,
3072 msg_Err( p_obj
, "Oops, can't find 'allcontrols' variable." );
3076 while( *psz_parser
&& *psz_parser
!= '}' )
3078 char *psz_delim
, *psz_assign
;
3080 while( *psz_parser
== ',' || *psz_parser
== ' ' )
3083 psz_delim
= strchr( psz_parser
, ',' );
3084 if( psz_delim
== NULL
)
3085 psz_delim
= strchr( psz_parser
, '}' );
3086 if( psz_delim
== NULL
)
3087 psz_delim
= psz_parser
+ strlen( psz_parser
);
3089 psz_assign
= memchr( psz_parser
, '=', psz_delim
- psz_parser
);
3090 if( psz_assign
== NULL
)
3092 char *psz_name
= strndup( psz_parser
, psz_delim
- psz_parser
);
3093 msg_Err( p_obj
, "%s missing '='", psz_name
);
3095 psz_parser
= psz_delim
+ 1;
3100 i
< val
.p_list
->i_count
;//&& psz_parser < psz_assign;
3103 const char *psz_var
= text
.p_list
->p_values
[i
].psz_string
;
3104 int i_cid
= val
.p_list
->p_values
[i
].i_int
;
3105 var_Change( p_obj
, psz_var
, VLC_VAR_GETTEXT
, &name
, NULL
);
3106 const char *psz_name
= name
.psz_string
;
3108 int i_availstrlen
= strlen( psz_name
);
3109 int i_parsestrlen
= psz_assign
- psz_parser
;
3110 int i_maxstrlen
= __MAX( i_availstrlen
, i_parsestrlen
);
3112 if( !strncasecmp( psz_name
, psz_parser
, i_maxstrlen
) )
3114 Control( p_obj
, p_sys
, i_fd
, psz_name
, i_cid
,
3115 strtol( ++psz_assign
, &psz_parser
, 0) );
3117 free( name
.psz_string
);
3120 if( psz_parser
< psz_assign
)
3122 char *psz_name
= strndup( psz_parser
, psz_assign
- psz_parser
);
3123 msg_Err( p_obj
, "Control %s not available", psz_name
);
3125 psz_parser
= ( *psz_delim
) ? ( psz_delim
+ 1 ) : psz_delim
;
3128 var_FreeList( &val
, &text
);
3131 /*****************************************************************************
3132 * Reset all user-class v4l2 controls to their default value
3133 *****************************************************************************/
3134 static int ControlReset( vlc_object_t
*p_obj
, demux_sys_t
*p_sys
, int i_fd
)
3136 struct v4l2_queryctrl queryctrl
;
3138 memset( &queryctrl
, 0, sizeof( queryctrl
) );
3140 queryctrl
.id
= V4L2_CTRL_FLAG_NEXT_CTRL
;
3141 if( v4l2_ioctl( i_fd
, VIDIOC_QUERYCTRL
, &queryctrl
) >= 0 )
3143 /* Extended control API supported */
3144 queryctrl
.id
= V4L2_CTRL_FLAG_NEXT_CTRL
;
3145 while( v4l2_ioctl( i_fd
, VIDIOC_QUERYCTRL
, &queryctrl
) >= 0 )
3147 if( queryctrl
.type
== V4L2_CTRL_TYPE_CTRL_CLASS
3148 || V4L2_CTRL_ID2CLASS( queryctrl
.id
) == V4L2_CTRL_CLASS_MPEG
)
3150 queryctrl
.id
|= V4L2_CTRL_FLAG_NEXT_CTRL
;
3153 struct v4l2_control control
;
3154 memset( &control
, 0, sizeof( control
) );
3155 control
.id
= queryctrl
.id
;
3156 if( v4l2_ioctl( i_fd
, VIDIOC_G_CTRL
, &control
) >= 0
3157 && queryctrl
.default_value
!= control
.value
)
3160 for( i
= 0; controls
[i
].psz_name
!= NULL
; i
++ )
3161 if( controls
[i
].i_cid
== queryctrl
.id
) break;
3162 name2var( queryctrl
.name
);
3163 Control( p_obj
, p_sys
, i_fd
,
3164 controls
[i
].psz_name
? controls
[i
].psz_name
3165 : (const char *)queryctrl
.name
,
3166 queryctrl
.id
, queryctrl
.default_value
);
3168 queryctrl
.id
|= V4L2_CTRL_FLAG_NEXT_CTRL
;
3174 /* public controls */
3175 for( i_cid
= V4L2_CID_BASE
;
3176 i_cid
< V4L2_CID_LASTP1
;
3179 queryctrl
.id
= i_cid
;
3180 if( v4l2_ioctl( i_fd
, VIDIOC_QUERYCTRL
, &queryctrl
) >= 0 )
3182 struct v4l2_control control
;
3183 if( queryctrl
.flags
& V4L2_CTRL_FLAG_DISABLED
)
3185 memset( &control
, 0, sizeof( control
) );
3186 control
.id
= queryctrl
.id
;
3187 if( v4l2_ioctl( i_fd
, VIDIOC_G_CTRL
, &control
) >= 0
3188 && queryctrl
.default_value
!= control
.value
)
3191 for( i
= 0; controls
[i
].psz_name
!= NULL
; i
++ )
3192 if( controls
[i
].i_cid
== queryctrl
.id
) break;
3193 name2var( queryctrl
.name
);
3194 Control( p_obj
, p_sys
, i_fd
,
3195 controls
[i
].psz_name
? controls
[i
].psz_name
3196 : (const char *)queryctrl
.name
,
3197 queryctrl
.id
, queryctrl
.default_value
);
3202 /* private controls */
3203 for( i_cid
= V4L2_CID_PRIVATE_BASE
;
3207 queryctrl
.id
= i_cid
;
3208 if( v4l2_ioctl( i_fd
, VIDIOC_QUERYCTRL
, &queryctrl
) >= 0 )
3210 struct v4l2_control control
;
3211 if( queryctrl
.flags
& V4L2_CTRL_FLAG_DISABLED
)
3213 memset( &control
, 0, sizeof( control
) );
3214 control
.id
= queryctrl
.id
;
3215 if( v4l2_ioctl( i_fd
, VIDIOC_G_CTRL
, &control
) >= 0
3216 && queryctrl
.default_value
!= control
.value
)
3218 name2var( queryctrl
.name
);
3219 Control( p_obj
, p_sys
, i_fd
, (const char *)queryctrl
.name
,
3220 queryctrl
.id
, queryctrl
.default_value
);
3230 /*****************************************************************************
3231 * Issue user-class v4l2 controls
3232 *****************************************************************************/
3233 static int Control( vlc_object_t
*p_obj
, demux_sys_t
*p_sys
, int i_fd
,
3234 const char *psz_name
, int i_cid
, int i_value
)
3237 struct v4l2_queryctrl queryctrl
;
3238 struct v4l2_control control
;
3239 struct v4l2_ext_control ext_control
;
3240 struct v4l2_ext_controls ext_controls
;
3245 memset( &queryctrl
, 0, sizeof( queryctrl
) );
3247 queryctrl
.id
= i_cid
;
3249 if( v4l2_ioctl( i_fd
, VIDIOC_QUERYCTRL
, &queryctrl
) < 0
3250 || queryctrl
.flags
& V4L2_CTRL_FLAG_DISABLED
)
3252 msg_Dbg( p_obj
, "%s (%x) control is not supported.", psz_name
, i_cid
);
3253 return VLC_EGENERIC
;
3256 memset( &control
, 0, sizeof( control
) );
3257 memset( &ext_control
, 0, sizeof( ext_control
) );
3258 memset( &ext_controls
, 0, sizeof( ext_controls
) );
3260 ext_control
.id
= i_cid
;
3261 ext_controls
.ctrl_class
= V4L2_CTRL_ID2CLASS( i_cid
);
3262 ext_controls
.count
= 1;
3263 ext_controls
.controls
= &ext_control
;
3267 if( i_value
>= queryctrl
.minimum
&& i_value
<= queryctrl
.maximum
)
3269 ext_control
.value
= i_value
;
3270 if( v4l2_ioctl( i_fd
, VIDIOC_S_EXT_CTRLS
, &ext_controls
) < 0 )
3272 control
.value
= i_value
;
3273 if( v4l2_ioctl( i_fd
, VIDIOC_S_CTRL
, &control
) < 0 )
3275 msg_Err( p_obj
, "unable to set %s (%x) to %d (%m)",
3276 psz_name
, i_cid
, i_value
);
3277 return VLC_EGENERIC
;
3279 i_ret
= v4l2_ioctl( i_fd
, VIDIOC_G_CTRL
, &control
);
3283 i_ret
= v4l2_ioctl( i_fd
, VIDIOC_G_EXT_CTRLS
, &ext_controls
);
3284 control
.value
= ext_control
.value
;
3291 msg_Dbg( p_obj
, "video %s: %d", psz_name
, control
.value
);
3292 switch( var_Type( p_obj
, psz_name
) & VLC_VAR_TYPE
)
3295 val
.b_bool
= control
.value
;
3296 var_Change( p_obj
, psz_name
, VLC_VAR_SETVALUE
, &val
, NULL
);
3297 var_TriggerCallback( p_obj
, "controls-update" );
3299 case VLC_VAR_INTEGER
:
3300 val
.i_int
= control
.value
;
3301 var_Change( p_obj
, psz_name
, VLC_VAR_SETVALUE
, &val
, NULL
);
3302 var_TriggerCallback( p_obj
, "controls-update" );
3309 /*****************************************************************************
3310 * On the fly change settings callback
3311 *****************************************************************************/
3312 static int DemuxControlCallback( vlc_object_t
*p_this
,
3313 const char *psz_var
, vlc_value_t oldval
, vlc_value_t newval
,
3317 demux_t
*p_demux
= (demux_t
*)p_this
;
3318 demux_sys_t
*p_sys
= p_demux
->p_sys
;
3319 int i_cid
= (long int)p_data
;
3321 int i_fd
= p_sys
->i_fd
;
3324 return VLC_EGENERIC
;
3326 Control( p_this
, p_sys
, i_fd
, psz_var
, i_cid
, newval
.i_int
);
3328 return VLC_EGENERIC
;
3331 static int DemuxControlResetCallback( vlc_object_t
*p_this
,
3332 const char *psz_var
, vlc_value_t oldval
, vlc_value_t newval
, void *p_data
)
3334 (void)psz_var
; (void)oldval
; (void)newval
; (void)p_data
;
3335 demux_t
*p_demux
= (demux_t
*)p_this
;
3336 demux_sys_t
*p_sys
= p_demux
->p_sys
;
3338 int i_fd
= p_sys
->i_fd
;
3341 return VLC_EGENERIC
;
3343 ControlReset( p_this
, p_sys
, i_fd
);
3345 return VLC_EGENERIC
;
3348 static int AccessControlCallback( vlc_object_t
*p_this
,
3349 const char *psz_var
, vlc_value_t oldval
, vlc_value_t newval
,
3353 access_t
*p_access
= (access_t
*)p_this
;
3354 demux_sys_t
*p_sys
= (demux_sys_t
*) p_access
->p_sys
;
3355 int i_cid
= (long int)p_data
;
3357 int i_fd
= p_sys
->i_fd
;
3360 return VLC_EGENERIC
;
3362 Control( p_this
, p_sys
, i_fd
, psz_var
, i_cid
, newval
.i_int
);
3364 return VLC_EGENERIC
;
3367 static int AccessControlResetCallback( vlc_object_t
*p_this
,
3368 const char *psz_var
, vlc_value_t oldval
, vlc_value_t newval
, void *p_data
)
3370 (void)psz_var
; (void)oldval
; (void)newval
; (void)p_data
;
3371 access_t
*p_access
= (access_t
*)p_this
;
3372 demux_sys_t
*p_sys
= (demux_sys_t
*) p_access
->p_sys
;
3374 int i_fd
= p_sys
->i_fd
;
3377 return VLC_EGENERIC
;
3379 ControlReset( p_this
, p_sys
, i_fd
);
3381 return VLC_EGENERIC
;