v4l2.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:117k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * v4l2.c : Video4Linux2 input module for vlc
  3.  *****************************************************************************
  4.  * Copyright (C) 2002-2009 the VideoLAN team
  5.  * $Id: 2659b81508dd38b01076426bc93dd9ee49e660a5 $
  6.  *
  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>
  11.  *
  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.
  16.  *
  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.
  21.  *
  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.  *****************************************************************************/
  26. /*
  27.  * Sections based on the reference V4L2 capture example at
  28.  * http://v4l2spec.bytesex.org/spec/capture-example.html
  29.  */
  30. /*****************************************************************************
  31.  * Preamble
  32.  *****************************************************************************/
  33. #ifdef HAVE_CONFIG_H
  34. # include "config.h"
  35. #endif
  36. #include <vlc_common.h>
  37. #include <vlc_plugin.h>
  38. #include <vlc_access.h>
  39. #include <vlc_charset.h>
  40. #include <vlc_demux.h>
  41. #include <vlc_input.h>
  42. #include <ctype.h>
  43. #include <fcntl.h>
  44. #include <sys/ioctl.h>
  45. #include <sys/mman.h>
  46. #include <linux/videodev2.h>
  47. #include <poll.h>
  48. #ifdef HAVE_LIBV4L2
  49. #   include <libv4l2.h>
  50. #endif
  51. /*****************************************************************************
  52.  * Module descriptior
  53.  *****************************************************************************/
  54. static int  DemuxOpen ( vlc_object_t * );
  55. static void DemuxClose( vlc_object_t * );
  56. static int  AccessOpen ( vlc_object_t * );
  57. static void AccessClose( vlc_object_t * );
  58. #define STANDARD_TEXT N_( "Standard" )
  59. #define STANDARD_LONGTEXT N_( 
  60.     "Video standard (Default, SECAM, PAL, or NTSC)." )
  61. #define CHROMA_TEXT N_("Video input chroma format")
  62. #define CHROMA_LONGTEXT N_( 
  63.     "Force the Video4Linux2 video device to use a specific chroma format " 
  64.     "(eg. I420 or I422 for raw images, MJPG for M-JPEG compressed input) " 
  65.     "(Complete list: GREY, I240, RV16, RV15, RV24, RV32, YUY2, YUYV, UYVY, " 
  66.     "I41N, I422, I420, I411, I410, MJPG)")
  67. #define INPUT_TEXT N_( "Input" )
  68. #define INPUT_LONGTEXT N_( 
  69.     "Input of the card to use (see debug)." )
  70. #define AUDIO_INPUT_TEXT N_( "Audio input" )
  71. #define AUDIO_INPUT_LONGTEXT N_( 
  72.     "Audio input of the card to use (see debug)." )
  73. #define IOMETHOD_TEXT N_( "IO Method" )
  74. #define IOMETHOD_LONGTEXT N_( 
  75.     "IO Method (READ, MMAP, USERPTR)." )
  76. #define WIDTH_TEXT N_( "Width" )
  77. #define WIDTH_LONGTEXT N_( 
  78.     "Force width (-1 for autodetect, 0 for driver default)." )
  79. #define HEIGHT_TEXT N_( "Height" )
  80. #define HEIGHT_LONGTEXT N_( 
  81.     "Force height (-1 for autodetect, 0 for driver default)." )
  82. #define FPS_TEXT N_( "Framerate" )
  83. #define FPS_LONGTEXT N_( "Framerate to capture, if applicable " 
  84.     "(0 for autodetect)." )
  85. #ifdef HAVE_LIBV4L2
  86. #define LIBV4L2_TEXT N_( "Use libv4l2" )
  87. #define LIBV4L2_LONGTEXT N_( 
  88.     "Force usage of the libv4l2 wrapper." )
  89. #endif
  90. #define CTRL_RESET_TEXT N_( "Reset v4l2 controls" )
  91. #define CTRL_RESET_LONGTEXT N_( 
  92.     "Reset controls to defaults provided by the v4l2 driver." )
  93. #define BRIGHTNESS_TEXT N_( "Brightness" )
  94. #define BRIGHTNESS_LONGTEXT N_( 
  95.     "Brightness of the video input (if supported by the v4l2 driver)." )
  96. #define CONTRAST_TEXT N_( "Contrast" )
  97. #define CONTRAST_LONGTEXT N_( 
  98.     "Contrast of the video input (if supported by the v4l2 driver)." )
  99. #define SATURATION_TEXT N_( "Saturation" )
  100. #define SATURATION_LONGTEXT N_( 
  101.     "Saturation of the video input (if supported by the v4l2 driver)." )
  102. #define HUE_TEXT N_( "Hue" )
  103. #define HUE_LONGTEXT N_( 
  104.     "Hue of the video input (if supported by the v4l2 driver)." )
  105. #define BLACKLEVEL_TEXT N_( "Black level" )
  106. #define BLACKLEVEL_LONGTEXT N_( 
  107.     "Black level of the video input (if supported by the v4l2 driver)." )
  108. #define AUTOWHITEBALANCE_TEXT N_( "Auto white balance" )
  109. #define AUTOWHITEBALANCE_LONGTEXT N_( 
  110.     "Automatically set the white balance of the video input " 
  111.     "(if supported by the v4l2 driver)." )
  112. #define DOWHITEBALANCE_TEXT N_( "Do white balance" )
  113. #define DOWHITEBALANCE_LONGTEXT N_( 
  114.     "Trigger a white balancing action, useless if auto white balance is " 
  115.     "activated (if supported by the v4l2 driver)." )
  116. #define REDBALANCE_TEXT N_( "Red balance" )
  117. #define REDBALANCE_LONGTEXT N_( 
  118.     "Red balance of the video input (if supported by the v4l2 driver)." )
  119. #define BLUEBALANCE_TEXT N_( "Blue balance" )
  120. #define BLUEBALANCE_LONGTEXT N_( 
  121.     "Blue balance of the video input (if supported by the v4l2 driver)." )
  122. #define GAMMA_TEXT N_( "Gamma" )
  123. #define GAMMA_LONGTEXT N_( 
  124.     "Gamma of the video input (if supported by the v4l2 driver)." )
  125. #define EXPOSURE_TEXT N_( "Exposure" )
  126. #define EXPOSURE_LONGTEXT N_( 
  127.     "Exposure of the video input (if supported by the v4L2 driver)." )
  128. #define AUTOGAIN_TEXT N_( "Auto gain" )
  129. #define AUTOGAIN_LONGTEXT N_( 
  130.     "Automatically set the video input's gain (if supported by the " 
  131.     "v4l2 driver)." )
  132. #define GAIN_TEXT N_( "Gain" )
  133. #define GAIN_LONGTEXT N_( 
  134.     "Video input's gain (if supported by the v4l2 driver)." )
  135. #define HFLIP_TEXT N_( "Horizontal flip" )
  136. #define HFLIP_LONGTEXT N_( 
  137.     "Flip the video horizontally (if supported by the v4l2 driver)." )
  138. #define VFLIP_TEXT N_( "Vertical flip" )
  139. #define VFLIP_LONGTEXT N_( 
  140.     "Flip the video vertically (if supported by the v4l2 driver)." )
  141. #define HCENTER_TEXT N_( "Horizontal centering" )
  142. #define HCENTER_LONGTEXT N_( 
  143.     "Set the camera's horizontal centering (if supported by the v4l2 driver)." )
  144. #define VCENTER_TEXT N_( "Vertical centering" )
  145. #define VCENTER_LONGTEXT N_( 
  146.     "Set the camera's vertical centering (if supported by the v4l2 driver)." )
  147. #define AUDIO_VOLUME_TEXT N_( "Volume" )
  148. #define AUDIO_VOLUME_LONGTEXT N_( 
  149.     "Volume of the audio input (if supported by the v4l2 driver)." )
  150. #define AUDIO_BALANCE_TEXT N_( "Balance" )
  151. #define AUDIO_BALANCE_LONGTEXT N_( 
  152.     "Balance of the audio input (if supported by the v4l2 driver)." )
  153. #define AUDIO_MUTE_TEXT N_( "Mute" )
  154. #define AUDIO_MUTE_LONGTEXT N_( 
  155.     "Mute audio input (if supported by the v4l2 driver)." )
  156. #define AUDIO_BASS_TEXT N_( "Bass" )
  157. #define AUDIO_BASS_LONGTEXT N_( 
  158.     "Bass level of the audio input (if supported by the v4l2 driver)." )
  159. #define AUDIO_TREBLE_TEXT N_( "Treble" )
  160. #define AUDIO_TREBLE_LONGTEXT N_( 
  161.     "Treble level of the audio input (if supported by the v4l2 driver)." )
  162. #define AUDIO_LOUDNESS_TEXT N_( "Loudness" )
  163. #define AUDIO_LOUDNESS_LONGTEXT N_( 
  164.     "Loudness of the audio input (if supported by the v4l2 driver)." )
  165. #define CACHING_TEXT N_("Caching value in ms")
  166. #define CACHING_LONGTEXT N_( 
  167.     "Caching value for V4L2 captures. This " 
  168.     "value should be set in milliseconds." )
  169. #define S_CTRLS_TEXT N_("v4l2 driver controls")
  170. #define S_CTRLS_LONGTEXT N_( 
  171.     "Set the v4l2 driver controls to the values specified using a comma " 
  172.     "separated list optionally encapsulated by curly braces " 
  173.     "(e.g.: {video_bitrate=6000000,audio_crc=0,stream_type=3} ). " 
  174.     "To list available controls, increase verbosity (-vvv) " 
  175.     "or use the v4l2-ctl application." )
  176. #define TUNER_TEXT N_("Tuner id")
  177. #define TUNER_LONGTEXT N_( 
  178.     "Tuner id (see debug output)." )
  179. #define FREQUENCY_TEXT N_("Frequency")
  180. #define FREQUENCY_LONGTEXT N_( 
  181.     "Tuner frequency in Hz or kHz (see debug output)" )
  182. #define TUNER_AUDIO_MODE_TEXT N_("Audio mode")
  183. #define TUNER_AUDIO_MODE_LONGTEXT N_( 
  184.     "Tuner audio mono/stereo and track selection." )
  185. #define AUDIO_DEPRECATED_ERROR N_( 
  186.     "Alsa or OSS audio capture in the v4l2 access is deprecated. " 
  187.     "please use 'v4l2:/""/ :input-slave=alsa:/""/' or " 
  188.     "'v4l2:/""/ :input-slave=oss:/""/' instead." )
  189. #define ASPECT_TEXT N_("Picture aspect-ratio n:m")
  190. #define ASPECT_LONGTEXT N_("Define input picture aspect-ratio to use. Default is 4:3" )
  191. typedef enum {
  192.     IO_METHOD_AUTO,
  193.     IO_METHOD_READ,
  194.     IO_METHOD_MMAP,
  195.     IO_METHOD_USERPTR,
  196. } io_method;
  197. static const int i_standards_list[] =
  198.     { V4L2_STD_UNKNOWN, V4L2_STD_SECAM, V4L2_STD_PAL, V4L2_STD_NTSC };
  199. static const char *const psz_standards_list_text[] =
  200.     { N_("Default"), N_("SECAM"), N_("PAL"),  N_("NTSC") };
  201. static const int i_iomethod_list[] =
  202.     { IO_METHOD_AUTO, IO_METHOD_READ, IO_METHOD_MMAP, IO_METHOD_USERPTR };
  203. static const char *const psz_iomethod_list_text[] =
  204.     { N_("AUTO"), N_("READ"), N_("MMAP"),  N_("USERPTR") };
  205. static const int i_tuner_audio_modes_list[] =
  206.     { V4L2_TUNER_MODE_MONO, V4L2_TUNER_MODE_STEREO,
  207.       V4L2_TUNER_MODE_LANG1, V4L2_TUNER_MODE_LANG2,
  208.       V4L2_TUNER_MODE_SAP, V4L2_TUNER_MODE_LANG1_LANG2 };
  209. static const char *const psz_tuner_audio_modes_list_text[] =
  210.     { N_( "Mono" ),
  211.       N_( "Stereo" ),
  212.       N_( "Primary language (Analog TV tuners only)" ),
  213.       N_( "Secondary language (Analog TV tuners only)" ),
  214.       N_( "Second audio program (Analog TV tuners only)" ),
  215.       N_( "Primary language left, Secondary language right" ) };
  216. #define V4L2_DEFAULT "/dev/video0"
  217. #define CFG_PREFIX "v4l2-"
  218. vlc_module_begin ()
  219.     set_shortname( N_("Video4Linux2") )
  220.     set_description( N_("Video4Linux2 input") )
  221.     set_category( CAT_INPUT )
  222.     set_subcategory( SUBCAT_INPUT_ACCESS )
  223.     set_section( N_( "Video input" ), NULL )
  224.     add_integer( CFG_PREFIX "standard", 0, NULL, STANDARD_TEXT,
  225.                  STANDARD_LONGTEXT, false )
  226.         change_integer_list( i_standards_list, psz_standards_list_text, NULL )
  227.     add_string( CFG_PREFIX "chroma", NULL, NULL, CHROMA_TEXT, CHROMA_LONGTEXT,
  228.                 true )
  229.     add_integer( CFG_PREFIX "input", 0, NULL, INPUT_TEXT, INPUT_LONGTEXT,
  230.                 true )
  231.     add_integer( CFG_PREFIX "audio-input", 0, NULL, AUDIO_INPUT_TEXT,
  232.                  AUDIO_INPUT_LONGTEXT, true )
  233.     add_integer( CFG_PREFIX "io", IO_METHOD_AUTO, NULL, IOMETHOD_TEXT,
  234.                  IOMETHOD_LONGTEXT, true )
  235.         change_integer_list( i_iomethod_list, psz_iomethod_list_text, NULL )
  236.     add_integer( CFG_PREFIX "width", -1, NULL, WIDTH_TEXT,
  237.                 WIDTH_LONGTEXT, true )
  238.     add_integer( CFG_PREFIX "height", -1, NULL, HEIGHT_TEXT,
  239.                 HEIGHT_LONGTEXT, true )
  240.     add_string( CFG_PREFIX "aspect-ratio", "4:3", NULL, ASPECT_TEXT,
  241.               ASPECT_LONGTEXT, true )
  242.     add_float( CFG_PREFIX "fps", 0, NULL, FPS_TEXT, FPS_LONGTEXT, true )
  243.     add_integer( CFG_PREFIX "caching", DEFAULT_PTS_DELAY / 1000, NULL,
  244.                 CACHING_TEXT, CACHING_LONGTEXT, true )
  245. #ifdef HAVE_LIBV4L2
  246.     add_bool( CFG_PREFIX "use-libv4l2", false, NULL, LIBV4L2_TEXT, LIBV4L2_LONGTEXT, true );
  247. #endif
  248.     set_section( N_( "Tuner" ), NULL )
  249.     add_integer( CFG_PREFIX "tuner", 0, NULL, TUNER_TEXT, TUNER_LONGTEXT,
  250.                  true )
  251.     add_integer( CFG_PREFIX "tuner-frequency", -1, NULL, FREQUENCY_TEXT,
  252.                  FREQUENCY_LONGTEXT, true )
  253.     add_integer( CFG_PREFIX "tuner-audio-mode", -1, NULL, TUNER_AUDIO_MODE_TEXT,
  254.                  TUNER_AUDIO_MODE_LONGTEXT, true )
  255.         change_integer_list( i_tuner_audio_modes_list,
  256.                              psz_tuner_audio_modes_list_text, 0 )
  257.     set_section( N_( "Controls" ),
  258.                  N_( "v4l2 driver controls, if supported by your v4l2 driver." ) )
  259.     add_bool( CFG_PREFIX "controls-reset", false, NULL, CTRL_RESET_TEXT,
  260.               CTRL_RESET_LONGTEXT, true )
  261.     add_integer( CFG_PREFIX "brightness", -1, NULL, BRIGHTNESS_TEXT,
  262.                  BRIGHTNESS_LONGTEXT, true )
  263.     add_integer( CFG_PREFIX "contrast", -1, NULL, CONTRAST_TEXT,
  264.                  CONTRAST_LONGTEXT, true )
  265.     add_integer( CFG_PREFIX "saturation", -1, NULL, SATURATION_TEXT,
  266.                  SATURATION_LONGTEXT, true )
  267.     add_integer( CFG_PREFIX "hue", -1, NULL, HUE_TEXT,
  268.                  HUE_LONGTEXT, true )
  269.     add_integer( CFG_PREFIX "black-level", -1, NULL, BLACKLEVEL_TEXT,
  270.                  BLACKLEVEL_LONGTEXT, true )
  271.     add_integer( CFG_PREFIX "auto-white-balance", -1, NULL,
  272.                  AUTOWHITEBALANCE_TEXT, AUTOWHITEBALANCE_LONGTEXT, true )
  273.     add_integer( CFG_PREFIX "do-white-balance", -1, NULL, DOWHITEBALANCE_TEXT,
  274.                  DOWHITEBALANCE_LONGTEXT, true )
  275.     add_integer( CFG_PREFIX "red-balance", -1, NULL, REDBALANCE_TEXT,
  276.                  REDBALANCE_LONGTEXT, true )
  277.     add_integer( CFG_PREFIX "blue-balance", -1, NULL, BLUEBALANCE_TEXT,
  278.                  BLUEBALANCE_LONGTEXT, true )
  279.     add_integer( CFG_PREFIX "gamma", -1, NULL, GAMMA_TEXT,
  280.                  GAMMA_LONGTEXT, true )
  281.     add_integer( CFG_PREFIX "exposure", -1, NULL, EXPOSURE_TEXT,
  282.                  EXPOSURE_LONGTEXT, true )
  283.     add_integer( CFG_PREFIX "autogain", -1, NULL, AUTOGAIN_TEXT,
  284.                  AUTOGAIN_LONGTEXT, true )
  285.     add_integer( CFG_PREFIX "gain", -1, NULL, GAIN_TEXT,
  286.                  GAIN_LONGTEXT, true )
  287.     add_integer( CFG_PREFIX "hflip", -1, NULL, HFLIP_TEXT,
  288.                  HFLIP_LONGTEXT, true )
  289.     add_integer( CFG_PREFIX "vflip", -1, NULL, VFLIP_TEXT,
  290.                  VFLIP_LONGTEXT, true )
  291.     add_integer( CFG_PREFIX "hcenter", -1, NULL, HCENTER_TEXT,
  292.                  HCENTER_LONGTEXT, true )
  293.     add_integer( CFG_PREFIX "vcenter", -1, NULL, VCENTER_TEXT,
  294.                  VCENTER_LONGTEXT, true )
  295.     add_integer( CFG_PREFIX "audio-volume", -1, NULL, AUDIO_VOLUME_TEXT,
  296.                 AUDIO_VOLUME_LONGTEXT, true )
  297.     add_integer( CFG_PREFIX "audio-balance", -1, NULL, AUDIO_BALANCE_TEXT,
  298.                 AUDIO_BALANCE_LONGTEXT, true )
  299.     add_bool( CFG_PREFIX "audio-mute", false, NULL, AUDIO_MUTE_TEXT,
  300.               AUDIO_MUTE_LONGTEXT, true )
  301.     add_integer( CFG_PREFIX "audio-bass", -1, NULL, AUDIO_BASS_TEXT,
  302.                 AUDIO_BASS_LONGTEXT, true )
  303.     add_integer( CFG_PREFIX "audio-treble", -1, NULL, AUDIO_TREBLE_TEXT,
  304.                 AUDIO_TREBLE_LONGTEXT, true )
  305.     add_integer( CFG_PREFIX "audio-loudness", -1, NULL, AUDIO_LOUDNESS_TEXT,
  306.                 AUDIO_LOUDNESS_LONGTEXT, true )
  307.     add_string( CFG_PREFIX "set-ctrls", NULL, NULL, S_CTRLS_TEXT,
  308.               S_CTRLS_LONGTEXT, true )
  309.     add_obsolete_string( CFG_PREFIX "dev" )
  310.     add_obsolete_string( CFG_PREFIX "adev" )
  311.     add_obsolete_integer( CFG_PREFIX "audio-method" )
  312.     add_obsolete_bool( CFG_PREFIX "stereo" )
  313.     add_obsolete_integer( CFG_PREFIX "samplerate" )
  314.     add_shortcut( "v4l2" )
  315.     set_capability( "access_demux", 10 )
  316.     set_callbacks( DemuxOpen, DemuxClose )
  317.     add_submodule ()
  318.     add_shortcut( "v4l2" )
  319.     add_shortcut( "v4l2c" )
  320.     set_description( N_("Video4Linux2 Compressed A/V") )
  321.     set_capability( "access", 0 )
  322.     /* use these when open as access_demux fails; VLC will use another demux */
  323.     set_callbacks( AccessOpen, AccessClose )
  324. vlc_module_end ()
  325. /*****************************************************************************
  326.  * Access: local prototypes
  327.  *****************************************************************************/
  328. static void CommonClose( vlc_object_t *, demux_sys_t * );
  329. static void ParseMRL( demux_sys_t *, char *, vlc_object_t * );
  330. static void GetV4L2Params( demux_sys_t *, vlc_object_t * );
  331. static void SetAvailControlsByString( vlc_object_t *, demux_sys_t *, int );
  332. static int DemuxControl( demux_t *, int, va_list );
  333. static int AccessControl( access_t *, int, va_list );
  334. static int Demux( demux_t * );
  335. static block_t *AccessRead( access_t * );
  336. static ssize_t AccessReadStream( access_t * p_access, uint8_t * p_buffer, size_t i_len );
  337. static block_t* GrabVideo( vlc_object_t *p_demux, demux_sys_t *p_sys );
  338. static block_t* ProcessVideoFrame( vlc_object_t *p_demux, uint8_t *p_frame, size_t );
  339. static bool IsPixelFormatSupported( demux_t *p_demux,
  340.                                           unsigned int i_pixelformat );
  341. static int OpenVideoDev( vlc_object_t *, demux_sys_t *, bool );
  342. static bool ProbeVideoDev( vlc_object_t *, demux_sys_t *,
  343.                                  const char *psz_device );
  344. static int ControlList( vlc_object_t *, demux_sys_t *, int , bool, bool );
  345. static int Control( vlc_object_t *, demux_sys_t *, int i_fd,
  346.                     const char *psz_name, int i_cid, int i_value );
  347. static int DemuxControlCallback( vlc_object_t *p_this, const char *psz_var,
  348.                                  vlc_value_t oldval, vlc_value_t newval,
  349.                                  void *p_data );
  350. static int DemuxControlResetCallback( vlc_object_t *p_this, const char *psz_var,
  351.                                       vlc_value_t oldval, vlc_value_t newval,
  352.                                       void *p_data );
  353. static int AccessControlCallback( vlc_object_t *p_this, const char *psz_var,
  354.                                   vlc_value_t oldval, vlc_value_t newval,
  355.                                   void *p_data );
  356. static int AccessControlResetCallback( vlc_object_t *p_this,
  357.                                        const char *psz_var, vlc_value_t oldval,
  358.                                        vlc_value_t newval, void *p_data );
  359. static const struct
  360. {
  361.     unsigned int i_v4l2;
  362.     int i_fourcc;
  363.     int i_rmask;
  364.     int i_gmask;
  365.     int i_bmask;
  366. } v4l2chroma_to_fourcc[] =
  367. {
  368.     /* Raw data types */
  369.     { V4L2_PIX_FMT_GREY,    VLC_FOURCC('G','R','E','Y'), 0, 0, 0 },
  370.     { V4L2_PIX_FMT_HI240,   VLC_FOURCC('I','2','4','0'), 0, 0, 0 },
  371.     { V4L2_PIX_FMT_RGB555,  VLC_FOURCC('R','V','1','5'), 0x001f,0x03e0,0x7c00 },
  372.     { V4L2_PIX_FMT_RGB565,  VLC_FOURCC('R','V','1','6'), 0x001f,0x07e0,0xf800 },
  373.     /* Won't work since we don't know how to handle such gmask values
  374.      * correctly
  375.     { V4L2_PIX_FMT_RGB555X, VLC_FOURCC('R','V','1','5'), 0x007c,0xe003,0x1f00 },
  376.     { V4L2_PIX_FMT_RGB565X, VLC_FOURCC('R','V','1','6'), 0x00f8,0xe007,0x1f00 },
  377.     */
  378.     { V4L2_PIX_FMT_BGR24,   VLC_FOURCC('R','V','2','4'), 0xff0000,0xff00,0xff },
  379.     { V4L2_PIX_FMT_RGB24,   VLC_FOURCC('R','V','2','4'), 0xff,0xff00,0xff0000 },
  380.     { V4L2_PIX_FMT_BGR32,   VLC_FOURCC('R','V','3','2'), 0xff0000,0xff00,0xff },
  381.     { V4L2_PIX_FMT_RGB32,   VLC_FOURCC('R','V','3','2'), 0xff,0xff00,0xff0000 },
  382.     { V4L2_PIX_FMT_YUYV,    VLC_FOURCC('Y','U','Y','2'), 0, 0, 0 },
  383.     { V4L2_PIX_FMT_YUYV,    VLC_FOURCC('Y','U','Y','V'), 0, 0, 0 },
  384.     { V4L2_PIX_FMT_UYVY,    VLC_FOURCC('U','Y','V','Y'), 0, 0, 0 },
  385.     { V4L2_PIX_FMT_Y41P,    VLC_FOURCC('I','4','1','N'), 0, 0, 0 },
  386.     { V4L2_PIX_FMT_YUV422P, VLC_FOURCC('I','4','2','2'), 0, 0, 0 },
  387.     { V4L2_PIX_FMT_YVU420,  VLC_FOURCC('Y','V','1','2'), 0, 0, 0 },
  388.     { V4L2_PIX_FMT_YUV411P, VLC_FOURCC('I','4','1','1'), 0, 0, 0 },
  389.     { V4L2_PIX_FMT_YUV410,  VLC_FOURCC('I','4','1','0'), 0, 0, 0 },
  390.     /* Raw data types, not in V4L2 spec but still in videodev2.h and supported
  391.      * by VLC */
  392.     { V4L2_PIX_FMT_YUV420,  VLC_FOURCC('I','4','2','0'), 0, 0, 0 },
  393.     /* FIXME { V4L2_PIX_FMT_RGB444,  VLC_FOURCC('R','V','3','2') }, */
  394.     /* Compressed data types */
  395.     { V4L2_PIX_FMT_MJPEG,   VLC_FOURCC('M','J','P','G'), 0, 0, 0 },
  396.     { V4L2_PIX_FMT_JPEG,    VLC_FOURCC('J','P','E','G'), 0, 0, 0 },
  397. #if 0
  398.     { V4L2_PIX_FMT_DV,      VLC_FOURCC('?','?','?','?') },
  399.     { V4L2_PIX_FMT_MPEG,    VLC_FOURCC('?','?','?','?') },
  400. #endif
  401.     { 0, 0, 0, 0, 0 }
  402. };
  403. /**
  404.  * List of V4L2 chromas were confident enough to use as fallbacks if the
  405.  * user hasn't provided a --v4l2-chroma value.
  406.  *
  407.  * Try YUV chromas first, then RGB little endian and MJPEG as last resort.
  408.  */
  409. static const __u32 p_chroma_fallbacks[] =
  410. { V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_YVU420, V4L2_PIX_FMT_YUV422P,
  411.   V4L2_PIX_FMT_YUYV, V4L2_PIX_FMT_UYVY, V4L2_PIX_FMT_BGR24,
  412.   V4L2_PIX_FMT_BGR32, V4L2_PIX_FMT_MJPEG, V4L2_PIX_FMT_JPEG };
  413. static const struct
  414. {
  415.     const char *psz_name;
  416.     unsigned int i_cid;
  417. } controls[] =
  418. {
  419.     { "brightness", V4L2_CID_BRIGHTNESS },
  420.     { "contrast", V4L2_CID_CONTRAST },
  421.     { "saturation", V4L2_CID_SATURATION },
  422.     { "hue", V4L2_CID_HUE },
  423.     { "audio-volume", V4L2_CID_AUDIO_VOLUME },
  424.     { "audio-balance", V4L2_CID_AUDIO_BALANCE },
  425.     { "audio-bass", V4L2_CID_AUDIO_BASS },
  426.     { "audio-treble", V4L2_CID_AUDIO_TREBLE },
  427.     { "audio-mute", V4L2_CID_AUDIO_MUTE },
  428.     { "audio-loudness", V4L2_CID_AUDIO_LOUDNESS },
  429.     { "black-level", V4L2_CID_BLACK_LEVEL },
  430.     { "auto-white-balance", V4L2_CID_AUTO_WHITE_BALANCE },
  431.     { "do-white-balance", V4L2_CID_DO_WHITE_BALANCE },
  432.     { "red-balance", V4L2_CID_RED_BALANCE },
  433.     { "blue-balance", V4L2_CID_BLUE_BALANCE },
  434.     { "gamma", V4L2_CID_GAMMA },
  435.     { "exposure", V4L2_CID_EXPOSURE },
  436.     { "autogain", V4L2_CID_AUTOGAIN },
  437.     { "gain", V4L2_CID_GAIN },
  438.     { "hflip", V4L2_CID_HFLIP },
  439.     { "vflip", V4L2_CID_VFLIP },
  440.     { "hcenter", V4L2_CID_HCENTER },
  441.     { "vcenter", V4L2_CID_VCENTER },
  442.     { NULL, 0 }
  443. };
  444. struct buffer_t
  445. {
  446.     void *  start;
  447.     size_t  length;
  448. };
  449. struct demux_sys_t
  450. {
  451.     char *psz_device;  /* Main device from MRL */
  452.     int  i_fd;
  453.     char *psz_requested_chroma;
  454.     /* Video */
  455.     io_method io;
  456.     int i_cache;
  457.     struct v4l2_capability dev_cap;
  458.     int i_input;
  459.     struct v4l2_input *p_inputs;
  460.     int i_selected_input;
  461.     int i_standard;
  462.     struct v4l2_standard *p_standards;
  463.     v4l2_std_id i_selected_standard_id;
  464.     int i_audio;
  465.     /* V4L2 devices cannot have more than 32 audio inputs */
  466.     struct v4l2_audio p_audios[32];
  467.     int i_selected_audio_input;
  468.     int i_tuner;
  469.     struct v4l2_tuner *p_tuners;
  470.     int i_codec;
  471.     struct v4l2_fmtdesc *p_codecs;
  472.     struct buffer_t *p_buffers;
  473.     unsigned int i_nbuffers;
  474.     int i_width;
  475.     int i_height;
  476.     unsigned int i_aspect;
  477.     float f_fps;            /* <= 0.0 mean to grab at full rate */
  478.     mtime_t i_video_pts;    /* only used when f_fps > 0 */
  479.     int i_fourcc;
  480.     es_out_id_t *p_es;
  481.     /* Tuner */
  482.     int i_cur_tuner;
  483.     int i_frequency;
  484.     int i_audio_mode;
  485.     /* Controls */
  486.     char *psz_set_ctrls;
  487. #ifdef HAVE_LIBV4L2
  488.     /* */
  489.     int (*pf_close)( int );
  490.     int (*pf_dup)( int );
  491.     int (*pf_ioctl)( int, unsigned long int, ... );
  492.     ssize_t (*pf_read)( int, void *, size_t );
  493.     void *(*pf_mmap)( void *, size_t, int, int, int, off_t );
  494.     int (*pf_munmap)( void *, size_t );
  495.     bool b_libv4l2;
  496. #endif
  497. };
  498. #ifdef HAVE_LIBV4L2
  499. static void use_kernel_v4l2( demux_sys_t *p_sys )
  500. {
  501.     p_sys->pf_close = close;
  502.     p_sys->pf_dup = dup;
  503.     p_sys->pf_ioctl = ioctl;
  504.     p_sys->pf_read = read;
  505.     p_sys->pf_mmap = mmap;
  506.     p_sys->pf_munmap = munmap;
  507.     p_sys->b_libv4l2 = false;
  508. }
  509. static void use_libv4l2( demux_sys_t *p_sys )
  510. {
  511.     p_sys->pf_close = v4l2_close;
  512.     p_sys->pf_dup = v4l2_dup;
  513.     p_sys->pf_ioctl = v4l2_ioctl;
  514.     p_sys->pf_read = v4l2_read;
  515.     p_sys->pf_mmap = v4l2_mmap;
  516.     p_sys->pf_munmap = v4l2_munmap;
  517.     p_sys->b_libv4l2 = true;
  518. }
  519. #   define v4l2_close (p_sys->pf_close)
  520. #   define v4l2_dup (p_sys->pf_dup)
  521. #   define v4l2_ioctl (p_sys->pf_ioctl)
  522. #   define v4l2_read (p_sys->pf_read)
  523. #   define v4l2_mmap (p_sys->pf_mmap)
  524. #   define v4l2_munmap (p_sys->pf_munmap)
  525. #else
  526. #   define v4l2_close close
  527. #   define v4l2_dup dup
  528. #   define v4l2_ioctl ioctl
  529. #   define v4l2_read read
  530. #   define v4l2_mmap mmap
  531. #   define v4l2_munmap munmap
  532. #endif
  533. static int FindMainDevice( vlc_object_t *p_this, demux_sys_t *p_sys,
  534.                            bool b_demux )
  535. {
  536.     /* TODO: if using default device, loop through all /dev/video* until
  537.      * one works */
  538.     msg_Dbg( p_this, "opening device '%s'", p_sys->psz_device );
  539.     if( ProbeVideoDev( p_this, p_sys, p_sys->psz_device ) )
  540.     {
  541.         msg_Dbg( p_this, "'%s' is a video device", p_sys->psz_device );
  542.         p_sys->i_fd = OpenVideoDev( p_this, p_sys, b_demux );
  543.     }
  544.     if( p_sys->i_fd < 0 ) return VLC_EGENERIC;
  545.     return VLC_SUCCESS;
  546. }
  547. /*****************************************************************************
  548.  * DemuxOpen: opens v4l2 device, access_demux callback
  549.  *****************************************************************************
  550.  *
  551.  * url: <video device>::::
  552.  *
  553.  *****************************************************************************/
  554. static int DemuxOpen( vlc_object_t *p_this )
  555. {
  556.     demux_t     *p_demux = (demux_t*)p_this;
  557.     demux_sys_t *p_sys;
  558.     /* Only when selected */
  559.     if( strcmp( p_demux->psz_access, "v4l2" ) )
  560.         return VLC_EGENERIC;
  561.     /* Set up p_demux */
  562.     p_demux->pf_control = DemuxControl;
  563.     p_demux->pf_demux = Demux;
  564.     p_demux->info.i_update = 0;
  565.     p_demux->info.i_title = 0;
  566.     p_demux->info.i_seekpoint = 0;
  567.     p_demux->p_sys = p_sys = calloc( 1, sizeof( demux_sys_t ) );
  568.     if( p_sys == NULL ) return VLC_ENOMEM;
  569.     GetV4L2Params(p_sys, (vlc_object_t *) p_demux);
  570.     ParseMRL( p_sys, p_demux->psz_path, (vlc_object_t *) p_demux );
  571. #ifdef HAVE_LIBV4L2
  572.     if( !config_GetInt( p_this, CFG_PREFIX "use-libv4l2" ) )
  573.     {
  574.         msg_Dbg( p_this, "Trying direct kernel v4l2" );
  575.         use_kernel_v4l2( p_sys );
  576.         if( FindMainDevice( p_this, p_sys, true ) == VLC_SUCCESS)
  577.             return VLC_SUCCESS;
  578.     }
  579.     msg_Dbg( p_this, "Trying libv4l2 wrapper" );
  580.     use_libv4l2( p_sys );
  581. #endif
  582.     if( FindMainDevice( p_this, p_sys, true ) == VLC_SUCCESS)
  583.         return VLC_SUCCESS;
  584.     DemuxClose( p_this );
  585.     return VLC_EGENERIC;
  586. }
  587. /*****************************************************************************
  588.  * GetV4L2Params: fill in p_sys parameters (shared by DemuxOpen and AccessOpen)
  589.  *****************************************************************************/
  590. static void GetV4L2Params( demux_sys_t *p_sys, vlc_object_t *p_obj )
  591. {
  592.     p_sys->i_video_pts = -1;
  593.     p_sys->i_selected_standard_id =
  594.         i_standards_list[var_CreateGetInteger( p_obj, "v4l2-standard" )];
  595.     p_sys->i_selected_input = var_CreateGetInteger( p_obj, "v4l2-input" );
  596.     p_sys->i_selected_audio_input =
  597.         var_CreateGetInteger( p_obj, "v4l2-audio-input" );
  598.     p_sys->io = var_CreateGetInteger( p_obj, "v4l2-io" );
  599.     p_sys->i_width = var_CreateGetInteger( p_obj, "v4l2-width" );
  600.     p_sys->i_height = var_CreateGetInteger( p_obj, "v4l2-height" );
  601.     var_Create( p_obj, "v4l2-controls-reset", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
  602.     p_sys->f_fps = var_CreateGetFloat( p_obj, "v4l2-fps" );
  603.     p_sys->psz_requested_chroma = var_CreateGetString( p_obj, "v4l2-chroma" );
  604.     p_sys->i_cache = var_CreateGetInteger( p_obj, "v4l2-caching" );
  605.     p_sys->i_cur_tuner = var_CreateGetInteger( p_obj, "v4l2-tuner" );
  606.     p_sys->i_frequency = var_CreateGetInteger( p_obj, "v4l2-tuner-frequency" );
  607.     p_sys->i_audio_mode = var_CreateGetInteger( p_obj, "v4l2-tuner-audio-mode" );
  608.     p_sys->psz_set_ctrls = var_CreateGetString( p_obj, "v4l2-set-ctrls" );
  609.     char *psz_aspect = var_CreateGetString( p_obj, "v4l2-aspect-ratio" );
  610.     if( psz_aspect && *psz_aspect && strchr( psz_aspect, ':' ) )
  611.     {
  612.         char *psz_delim = strchr( psz_aspect, ':' );
  613.         p_sys->i_aspect = atoi( psz_aspect ) * VOUT_ASPECT_FACTOR / atoi( psz_delim + 1 );
  614.     }
  615.     else
  616.     {
  617.         p_sys->i_aspect = 4 * VOUT_ASPECT_FACTOR / 3 ;
  618.     }
  619.     free( psz_aspect );
  620.     p_sys->psz_device = NULL;
  621.     p_sys->i_fd = -1;
  622.     p_sys->p_es = NULL;
  623. }
  624. /*****************************************************************************
  625.  * ParseMRL: parse the options contained in the MRL
  626.  *****************************************************************************/
  627. static void ParseMRL( demux_sys_t *p_sys, char *psz_path, vlc_object_t *p_obj )
  628. {
  629.     char *psz_dup = strdup( psz_path );
  630.     char *psz_parser = psz_dup;
  631.     while( *psz_parser && *psz_parser != ':' )
  632.     {
  633.         psz_parser++;
  634.     }
  635.     if( *psz_parser == ':' )
  636.     {
  637.         /* read options */
  638.         for( ;; )
  639.         {
  640.             *psz_parser++ = '';
  641.             if( !strncmp( psz_parser, "standard=", strlen( "standard=" ) ) )
  642.             {
  643.                 psz_parser += strlen( "standard=" );
  644.                 if( !strncmp( psz_parser, "pal", strlen( "pal" ) ) )
  645.                 {
  646.                     p_sys->i_selected_standard_id = V4L2_STD_PAL;
  647.                     psz_parser += strlen( "pal" );
  648.                 }
  649.                 else if( !strncmp( psz_parser, "ntsc", strlen( "ntsc" ) ) )
  650.                 {
  651.                     p_sys->i_selected_standard_id = V4L2_STD_NTSC;
  652.                     psz_parser += strlen( "ntsc" );
  653.                 }
  654.                 else if( !strncmp( psz_parser, "secam", strlen( "secam" ) ) )
  655.                 {
  656.                     p_sys->i_selected_standard_id = V4L2_STD_SECAM;
  657.                     psz_parser += strlen( "secam" );
  658.                 }
  659.                 else if( !strncmp( psz_parser, "default", strlen( "default" ) ) )
  660.                 {
  661.                     p_sys->i_selected_standard_id = V4L2_STD_UNKNOWN;
  662.                     psz_parser += strlen( "default" );
  663.                 }
  664.                 else
  665.                 {
  666.                     p_sys->i_selected_standard_id = i_standards_list[strtol( psz_parser, &psz_parser, 0 )];
  667.                 }
  668.             }
  669.             else if( !strncmp( psz_parser, "chroma=", strlen( "chroma=" ) ) )
  670.             {
  671.                 int  i_len;
  672.                 psz_parser += strlen( "chroma=" );
  673.                 if( strchr( psz_parser, ':' ) )
  674.                 {
  675.                     i_len = strchr( psz_parser, ':' ) - psz_parser;
  676.                 }
  677.                 else
  678.                 {
  679.                     i_len = strlen( psz_parser );
  680.                 }
  681.                 free( p_sys->psz_requested_chroma );
  682.                 p_sys->psz_requested_chroma = strndup( psz_parser, i_len );
  683.                 psz_parser += i_len;
  684.             }
  685.             else if( !strncmp( psz_parser, "input=", strlen( "input=" ) ) )
  686.             {
  687.                 p_sys->i_selected_input = strtol( psz_parser + strlen( "input=" ),
  688.                                        &psz_parser, 0 );
  689.             }
  690.             else if( !strncmp( psz_parser, "audio-input=", strlen( "audio-input=" ) ) )
  691.             {
  692.                 p_sys->i_selected_audio_input = strtol( psz_parser + strlen( "audio-input=" ),
  693.                                        &psz_parser, 0 );
  694.             }
  695.             else if( !strncmp( psz_parser, "fps=", strlen( "fps=" ) ) )
  696.             {
  697.                 p_sys->f_fps = us_strtof( psz_parser + strlen( "fps=" ),
  698.                                           &psz_parser );
  699.             }
  700.             else if( !strncmp( psz_parser, "io=", strlen( "io=" ) ) )
  701.             {
  702.                 psz_parser += strlen( "io=" );
  703.                 if( !strncmp( psz_parser, "read", strlen( "read" ) ) )
  704.                 {
  705.                     p_sys->io = IO_METHOD_READ;
  706.                     psz_parser += strlen( "read" );
  707.                 }
  708.                 else if( !strncmp( psz_parser, "mmap", strlen( "mmap" ) ) )
  709.                 {
  710.                     p_sys->io = IO_METHOD_MMAP;
  711.                     psz_parser += strlen( "mmap" );
  712.                 }
  713.                 else if( !strncmp( psz_parser, "userptr", strlen( "userptr" ) ) )
  714.                 {
  715.                     p_sys->io = IO_METHOD_USERPTR;
  716.                     psz_parser += strlen( "userptr" );
  717.                 }
  718.                 else if( !strncmp( psz_parser, "auto", strlen( "auto" ) ) )
  719.                 {
  720.                     p_sys->io = IO_METHOD_AUTO;
  721.                     psz_parser += strlen( "auto" );
  722.                 }
  723.                 else
  724.                 {
  725.                     p_sys->io = strtol( psz_parser, &psz_parser, 0 );
  726.                 }
  727.             }
  728.             else if( !strncmp( psz_parser, "width=",
  729.                                strlen( "width=" ) ) )
  730.             {
  731.                 p_sys->i_width =
  732.                     strtol( psz_parser + strlen( "width=" ),
  733.                             &psz_parser, 0 );
  734.             }
  735.             else if( !strncmp( psz_parser, "height=",
  736.                                strlen( "height=" ) ) )
  737.             {
  738.                 p_sys->i_height =
  739.                     strtol( psz_parser + strlen( "height=" ),
  740.                             &psz_parser, 0 );
  741.             }
  742.             else if( !strncmp( psz_parser, "aspect-ratio=",
  743.                                strlen( "aspect-ratio=" ) ) )
  744.             {
  745.                 unsigned int num,den;
  746.                 num = strtol( psz_parser + strlen( "aspect-ratio=" ),
  747.                               &psz_parser, 0 );
  748.                 den = strtol( psz_parser + strlen( ":" ),
  749.                               &psz_parser, 0 );
  750.                 if( num && den )
  751.                     p_sys->i_aspect = num * VOUT_ASPECT_FACTOR / den;
  752.             }
  753.             else if( !strncmp( psz_parser, "controls-reset",
  754.                                strlen( "controls-reset" ) ) )
  755.             {
  756.                 var_SetBool( p_obj, "v4l2-controls-reset", true );
  757.                 psz_parser += strlen( "controls-reset" );
  758.             }
  759. #if 0
  760.             else if( !strncmp( psz_parser, "brightness=",
  761.                                strlen( "brightness=" ) ) )
  762.             {
  763.                 var_SetInteger( p_obj, "brightness",
  764.                     strtol( psz_parser + strlen( "brightness=" ),
  765.                             &psz_parser, 0 ) );
  766.             }
  767.             else if( !strncmp( psz_parser, "contrast=",
  768.                                strlen( "contrast=" ) ) )
  769.             {
  770.                 var_SetInteger( p_obj, "contrast",
  771.                     strtol( psz_parser + strlen( "contrast=" ),
  772.                             &psz_parser, 0 ) );
  773.             }
  774.             else if( !strncmp( psz_parser, "saturation=",
  775.                                strlen( "saturation=" ) ) )
  776.             {
  777.                 var_SetInteger( p_obj, "saturation",
  778.                     strtol( psz_parser + strlen( "saturation=" ),
  779.                             &psz_parser, 0 ) );
  780.             }
  781.             else if( !strncmp( psz_parser, "hue=",
  782.                                strlen( "hue=" ) ) )
  783.             {
  784.                 var_SetInteger( p_obj, "hue",
  785.                     strtol( psz_parser + strlen( "hue=" ),
  786.                             &psz_parser, 0 ) );
  787.             }
  788.             else if( !strncmp( psz_parser, "gamma=",
  789.                                strlen( "gamma=" ) ) )
  790.             {
  791.                 var_SetInteger( p_obj, "gamma",
  792.                     strtol( psz_parser + strlen( "gamma=" ),
  793.                             &psz_parser, 0 ) );
  794.             }
  795. #endif
  796.             else if( !strncmp( psz_parser, "caching=", strlen( "caching=" ) ) )
  797.             {
  798.                 p_sys->i_cache = strtol( psz_parser + strlen( "caching=" ),
  799.                                          &psz_parser, 0 );
  800.             }
  801.             else if( !strncmp( psz_parser, "tuner=", strlen( "tuner=" ) ) )
  802.             {
  803.                 p_sys->i_cur_tuner = strtol( psz_parser + strlen( "tuner=" ),
  804.                                          &psz_parser, 0 );
  805.             }
  806.             else if( !strncmp( psz_parser, "tuner-frequency=", strlen( "tuner-frequency=" ) ) )
  807.             {
  808.                 p_sys->i_frequency = strtol( psz_parser
  809.                                           + strlen( "tuner-frequency=" ),
  810.                                           &psz_parser, 0 );
  811.             }
  812.             else if( !strncmp( psz_parser, "tuner-audio-mode=", strlen( "tuner-audio-mode=" ) ) )
  813.             {
  814.                 p_sys->i_audio_mode = strtol( psz_parser
  815.                                           + strlen( "tuner-audio-mode=" ),
  816.                                           &psz_parser, 0 );
  817.             }
  818.             else if( !strncmp( psz_parser, "set-ctrls=", strlen( "set-ctrls=" )) )
  819.             {
  820.                 int  i_len;
  821.                 psz_parser += strlen( "set-ctrls=" );
  822.                 if( strchr( psz_parser, ':' ) )
  823.                 {
  824.                     i_len = strchr( psz_parser, ':' ) - psz_parser;
  825.                 }
  826.                 else
  827.                 {
  828.                     i_len = strlen( psz_parser );
  829.                 }
  830.                 p_sys->psz_set_ctrls = strndup( psz_parser, i_len );
  831.                 psz_parser += i_len;
  832.             }
  833.             else if( !strncmp( psz_parser, "adev=", strlen( "adev=" ) )
  834.              || !strncmp( psz_parser, "samplerate=", strlen( "samplerate=" ) )
  835.              || !strncmp( psz_parser, "audio-method", strlen( "audio-method" ) )
  836.              || !strncmp( psz_parser, "stereo", strlen( "stereo" ) )
  837.              || !strncmp( psz_parser, "mono", strlen( "mono" ) ) )
  838.             {
  839.                 if( strchr( psz_parser, ':' ) )
  840.                 {
  841.                     psz_parser = strchr( psz_parser, ':' );
  842.                 }
  843.                 else
  844.                 {
  845.                     psz_parser += strlen( psz_parser );
  846.                 }
  847.                 msg_Err( p_obj, AUDIO_DEPRECATED_ERROR );
  848.             }
  849.             else
  850.             {
  851.                 char *psz_unk = strchr( psz_parser, ':' );
  852.                 if (psz_unk)
  853.                     psz_unk = strndup( psz_parser, psz_unk - psz_parser );
  854.                 else
  855.                     psz_unk = strdup( psz_parser);
  856.                 msg_Warn( p_obj, "unknown option %s", psz_unk );
  857.                 free (psz_unk);
  858.             }
  859.             while( *psz_parser && *psz_parser != ':' )
  860.             {
  861.                 psz_parser++;
  862.             }
  863.             if( *psz_parser == '' )
  864.             {
  865.                 break;
  866.             }
  867.         }
  868.     }
  869.     /* Main device */
  870.     if( *psz_dup )
  871.         p_sys->psz_device = strdup( psz_dup );
  872.     else
  873.         p_sys->psz_device = strdup( V4L2_DEFAULT );
  874.     free( psz_dup );
  875. }
  876. /*****************************************************************************
  877.  * Close: close device, free resources
  878.  *****************************************************************************/
  879. static void AccessClose( vlc_object_t *p_this )
  880. {
  881.     access_t    *p_access = (access_t *)p_this;
  882.     demux_sys_t *p_sys   = (demux_sys_t *) p_access->p_sys;
  883.     CommonClose( p_this, p_sys );
  884. }
  885. static void DemuxClose( vlc_object_t *p_this )
  886. {
  887.     struct v4l2_buffer buf;
  888.     enum v4l2_buf_type buf_type;
  889.     unsigned int i;
  890.     demux_t     *p_demux = (demux_t *)p_this;
  891.     demux_sys_t *p_sys   = p_demux->p_sys;
  892.     /* Stop video capture */
  893.     if( p_sys->i_fd >= 0 )
  894.     {
  895.         switch( p_sys->io )
  896.         {
  897.         case IO_METHOD_READ:
  898.             /* Nothing to do */
  899.             break;
  900.         case IO_METHOD_MMAP:
  901.         case IO_METHOD_USERPTR:
  902.             /* Some drivers 'hang' internally if this is not done before streamoff */
  903.             for( unsigned int i = 0; i < p_sys->i_nbuffers; i++ )
  904.             {
  905.                 memset( &buf, 0, sizeof(buf) );
  906.                 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  907.                 buf.memory = ( p_sys->io == IO_METHOD_USERPTR ) ?
  908.                     V4L2_MEMORY_USERPTR : V4L2_MEMORY_MMAP;
  909.                 v4l2_ioctl( p_sys->i_fd, VIDIOC_DQBUF, &buf ); /* ignore result */
  910.             }
  911.             buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  912.             if( v4l2_ioctl( p_sys->i_fd, VIDIOC_STREAMOFF, &buf_type ) < 0 ) {
  913.                 msg_Err( p_this, "VIDIOC_STREAMOFF failed" );
  914.             }
  915.             break;
  916.         default:
  917.             break;
  918.         }
  919.     }
  920.     /* Free Video Buffers */
  921.     if( p_sys->p_buffers ) {
  922.         switch( p_sys->io )
  923.         {
  924.         case IO_METHOD_READ:
  925.             free( p_sys->p_buffers[0].start );
  926.             break;
  927.         case IO_METHOD_MMAP:
  928.             for( i = 0; i < p_sys->i_nbuffers; ++i )
  929.             {
  930.                 if( v4l2_munmap( p_sys->p_buffers[i].start, p_sys->p_buffers[i].length ) )
  931.                 {
  932.                     msg_Err( p_this, "munmap failed" );
  933.                 }
  934.             }
  935.             break;
  936.         case IO_METHOD_USERPTR:
  937.             for( i = 0; i < p_sys->i_nbuffers; ++i )
  938.             {
  939.                free( p_sys->p_buffers[i].start );
  940.             }
  941.             break;
  942.         default:
  943.             break;
  944.         }
  945.         free( p_sys->p_buffers );
  946.     }
  947.     CommonClose( p_this, p_sys );
  948. }
  949. static void CommonClose( vlc_object_t *p_this, demux_sys_t *p_sys )
  950. {
  951.     (void)p_this;
  952.     /* Close */
  953.     if( p_sys->i_fd >= 0 ) v4l2_close( p_sys->i_fd );
  954.     free( p_sys->psz_device );
  955.     free( p_sys->p_standards );
  956.     free( p_sys->p_inputs );
  957.     free( p_sys->p_tuners );
  958.     free( p_sys->p_codecs );
  959.     free( p_sys->psz_requested_chroma );
  960.     free( p_sys->psz_set_ctrls );
  961.     free( p_sys );
  962. }
  963. /*****************************************************************************
  964.  * AccessOpen: opens v4l2 device, access callback
  965.  *****************************************************************************
  966.  *
  967.  * url: <video device>::::
  968.  *
  969.  *****************************************************************************/
  970. static int AccessOpen( vlc_object_t * p_this )
  971. {
  972.     access_t *p_access = (access_t*) p_this;
  973.     demux_sys_t * p_sys;
  974.     /* Only when selected */
  975.     if( *p_access->psz_access == '' ) return VLC_EGENERIC;
  976.     access_InitFields( p_access );
  977.     p_sys = calloc( 1, sizeof( demux_sys_t ));
  978.     if( !p_sys ) return VLC_ENOMEM;
  979.     p_access->p_sys = (access_sys_t*)p_sys;
  980.     GetV4L2Params( p_sys, (vlc_object_t *) p_access );
  981.     ParseMRL( p_sys, p_access->psz_path, (vlc_object_t *) p_access );
  982. #ifdef HAVE_LIBV4L2
  983.     if( !config_GetInt( p_this, CFG_PREFIX "use-libv4l2" ) )
  984.     {
  985.         msg_Dbg( p_this, "Trying direct kernel v4l2" );
  986.         use_kernel_v4l2( p_sys );
  987.         if( FindMainDevice( p_this, p_sys, false ) == VLC_SUCCESS)
  988.         {
  989.             if( p_sys->io == IO_METHOD_READ )
  990.             {
  991.                 ACCESS_SET_CALLBACKS( AccessReadStream, NULL, AccessControl, NULL );
  992.             }
  993.             else
  994.             {
  995.                 ACCESS_SET_CALLBACKS( NULL, AccessRead, AccessControl, NULL );
  996.             }
  997.             return VLC_SUCCESS;
  998.         }
  999.     }
  1000.     msg_Dbg( p_this, "Trying libv4l2 wrapper" );
  1001.     use_libv4l2( p_sys );
  1002. #endif
  1003.     if( FindMainDevice( p_this, p_sys, false ) == VLC_SUCCESS )
  1004.     {
  1005.         if( p_sys->io == IO_METHOD_READ )
  1006.         {
  1007.             ACCESS_SET_CALLBACKS( AccessReadStream, NULL, AccessControl, NULL );
  1008.         }
  1009.         else
  1010.         {
  1011.             ACCESS_SET_CALLBACKS( NULL, AccessRead, AccessControl, NULL );
  1012.         }
  1013.         return VLC_SUCCESS;
  1014.     }
  1015.     AccessClose( p_this );
  1016.     return VLC_EGENERIC;
  1017. }
  1018. /*****************************************************************************
  1019.  * DemuxControl:
  1020.  *****************************************************************************/
  1021. static int DemuxControl( demux_t *p_demux, int i_query, va_list args )
  1022. {
  1023.     demux_sys_t *p_sys = p_demux->p_sys;
  1024.     bool *pb;
  1025.     int64_t    *pi64;
  1026.     switch( i_query )
  1027.     {
  1028.         /* Special for access_demux */
  1029.         case DEMUX_CAN_PAUSE:
  1030.         case DEMUX_CAN_SEEK:
  1031.         case DEMUX_SET_PAUSE_STATE:
  1032.         case DEMUX_CAN_CONTROL_PACE:
  1033.             pb = (bool*)va_arg( args, bool * );
  1034.             *pb = false;
  1035.             return VLC_SUCCESS;
  1036.         case DEMUX_GET_PTS_DELAY:
  1037.             pi64 = (int64_t*)va_arg( args, int64_t * );
  1038.             *pi64 = (int64_t)p_sys->i_cache * 1000;
  1039.             return VLC_SUCCESS;
  1040.         case DEMUX_GET_TIME:
  1041.             pi64 = (int64_t*)va_arg( args, int64_t * );
  1042.             *pi64 = mdate();
  1043.             return VLC_SUCCESS;
  1044.         /* TODO implement others */
  1045.         default:
  1046.             return VLC_EGENERIC;
  1047.     }
  1048.     return VLC_EGENERIC;
  1049. }
  1050. /*****************************************************************************
  1051.  * AccessControl: access callback
  1052.  *****************************************************************************/
  1053. static int AccessControl( access_t *p_access, int i_query, va_list args )
  1054. {
  1055.     bool    *pb_bool;
  1056.     int64_t *pi_64;
  1057.     demux_sys_t  *p_sys = (demux_sys_t *) p_access->p_sys;
  1058.     switch( i_query )
  1059.     {
  1060.         /* */
  1061.         case ACCESS_CAN_SEEK:
  1062.         case ACCESS_CAN_FASTSEEK:
  1063.             pb_bool = (bool*)va_arg( args, bool* );
  1064.             *pb_bool = false;
  1065.             break;
  1066.         case ACCESS_CAN_PAUSE:
  1067.             pb_bool = (bool*)va_arg( args, bool* );
  1068.             *pb_bool = false;
  1069.             break;
  1070.         case ACCESS_CAN_CONTROL_PACE:
  1071.             pb_bool = (bool*)va_arg( args, bool* );
  1072.             *pb_bool = false;
  1073.             break;
  1074.         /* */
  1075.         case ACCESS_GET_PTS_DELAY:
  1076.             pi_64 = (int64_t*)va_arg( args, int64_t * );
  1077.             *pi_64 = (int64_t) p_sys->i_cache * 1000;
  1078.             break;
  1079.         /* */
  1080.         case ACCESS_SET_PAUSE_STATE:
  1081.             /* Nothing to do */
  1082.             break;
  1083.         case ACCESS_GET_TITLE_INFO:
  1084.         case ACCESS_SET_TITLE:
  1085.         case ACCESS_SET_SEEKPOINT:
  1086.         case ACCESS_SET_PRIVATE_ID_STATE:
  1087.         case ACCESS_GET_CONTENT_TYPE:
  1088.         case ACCESS_GET_META:
  1089.             return VLC_EGENERIC;
  1090.         default:
  1091.             msg_Warn( p_access, "Unimplemented query in control(%d).", i_query);
  1092.             return VLC_EGENERIC;
  1093.     }
  1094.     return VLC_SUCCESS;
  1095. }
  1096. /*****************************************************************************
  1097.  * AccessRead: access callback
  1098.  ******************************************************************************/
  1099. static block_t *AccessRead( access_t * p_access )
  1100. {
  1101.     demux_sys_t *p_sys = (demux_sys_t *)p_access->p_sys;
  1102.     struct pollfd fd;
  1103.     fd.fd = p_sys->i_fd;
  1104.     fd.events = POLLIN|POLLPRI;
  1105.     fd.revents = 0;
  1106.     /* Wait for data */
  1107.     if( poll( &fd, 1, 500 ) ) /* Timeout after 0.5 seconds since I don't know if pf_demux can be blocking. */
  1108.     {
  1109.         if( fd.revents & (POLLIN|POLLPRI) )
  1110.         {
  1111.             return GrabVideo( VLC_OBJECT(p_access), p_sys );
  1112.         }
  1113.     }
  1114.     return NULL;
  1115. }
  1116. static ssize_t AccessReadStream( access_t * p_access, uint8_t * p_buffer, size_t i_len )
  1117. {
  1118.     demux_sys_t *p_sys = (demux_sys_t *) p_access->p_sys;
  1119.     struct pollfd ufd;
  1120.     int i_ret;
  1121.     ufd.fd = p_sys->i_fd;
  1122.     ufd.events = POLLIN;
  1123.     if( p_access->info.b_eof )
  1124.         return 0;
  1125.     do
  1126.     {
  1127.         if( !vlc_object_alive (p_access) )
  1128.             return 0;
  1129.         ufd.revents = 0;
  1130.     }
  1131.     while( ( i_ret = poll( &ufd, 1, 500 ) ) == 0 );
  1132.     if( i_ret < 0 )
  1133.     {
  1134.         msg_Err( p_access, "Polling error (%m)." );
  1135.         return -1;
  1136.     }
  1137.     i_ret = v4l2_read( p_sys->i_fd, p_buffer, i_len );
  1138.     if( i_ret == 0 )
  1139.     {
  1140.         p_access->info.b_eof = true;
  1141.     }
  1142.     else if( i_ret > 0 )
  1143.     {
  1144.         p_access->info.i_pos += i_ret;
  1145.     }
  1146.     return i_ret;
  1147. }
  1148. /*****************************************************************************
  1149.  * Demux: Processes the audio or video frame
  1150.  *****************************************************************************/
  1151. static int Demux( demux_t *p_demux )
  1152. {
  1153.     demux_sys_t *p_sys = p_demux->p_sys;
  1154.     struct pollfd fd;
  1155.     fd.fd = p_sys->i_fd;
  1156.     fd.events = POLLIN|POLLPRI;
  1157.     fd.revents = 0;
  1158.     /* Wait for data */
  1159.     if( poll( &fd, 1, 500 ) ) /* Timeout after 0.5 seconds since I don't know if pf_demux can be blocking. */
  1160.     {
  1161.         if( fd.revents & (POLLIN|POLLPRI) )
  1162.         {
  1163.             block_t *p_block = GrabVideo( VLC_OBJECT(p_demux), p_sys );
  1164.             if( p_block )
  1165.             {
  1166.                 es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_block->i_pts );
  1167.                 es_out_Send( p_demux->out, p_sys->p_es, p_block );
  1168.             }
  1169.         }
  1170.     }
  1171.     return 1;
  1172. }
  1173. /*****************************************************************************
  1174.  * GrabVideo: Grab a video frame
  1175.  *****************************************************************************/
  1176. static block_t* GrabVideo( vlc_object_t *p_demux, demux_sys_t *p_sys )
  1177. {
  1178.     block_t *p_block = NULL;
  1179.     struct v4l2_buffer buf;
  1180.     ssize_t i_ret;
  1181.     if( p_sys->f_fps >= 0.1 && p_sys->i_video_pts > 0 )
  1182.     {
  1183.         mtime_t i_dur = (mtime_t)((double)1000000 / (double)p_sys->f_fps);
  1184.         /* Did we wait long enough ? (frame rate reduction) */
  1185.         if( p_sys->i_video_pts + i_dur > mdate() ) return 0;
  1186.     }
  1187.     /* Grab Video Frame */
  1188.     switch( p_sys->io )
  1189.     {
  1190.     case IO_METHOD_READ:
  1191.         i_ret = v4l2_read( p_sys->i_fd, p_sys->p_buffers[0].start, p_sys->p_buffers[0].length );
  1192.         if( i_ret == -1 )
  1193.         {
  1194.             switch( errno )
  1195.             {
  1196.             case EAGAIN:
  1197.                 return 0;
  1198.             case EIO:
  1199.                 /* Could ignore EIO, see spec. */
  1200.                 /* fall through */
  1201.             default:
  1202.                 msg_Err( p_demux, "Failed to read frame" );
  1203.                 return 0;
  1204.                }
  1205.         }
  1206.         p_block = ProcessVideoFrame( p_demux, (uint8_t*)p_sys->p_buffers[0].start, i_ret );
  1207.         if( !p_block ) return 0;
  1208.         break;
  1209.     case IO_METHOD_MMAP:
  1210.         memset( &buf, 0, sizeof(buf) );
  1211.         buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  1212.         buf.memory = V4L2_MEMORY_MMAP;
  1213.         /* Wait for next frame */
  1214.         if (v4l2_ioctl( p_sys->i_fd, VIDIOC_DQBUF, &buf ) < 0 )
  1215.         {
  1216.             switch( errno )
  1217.             {
  1218.             case EAGAIN:
  1219.                 return 0;
  1220.             case EIO:
  1221.                 /* Could ignore EIO, see spec. */
  1222.                 /* fall through */
  1223.             default:
  1224.                 msg_Err( p_demux, "Failed to wait (VIDIOC_DQBUF)" );
  1225.                 return 0;
  1226.                }
  1227.         }
  1228.         if( buf.index >= p_sys->i_nbuffers ) {
  1229.             msg_Err( p_demux, "Failed capturing new frame as i>=nbuffers" );
  1230.             return 0;
  1231.         }
  1232.         p_block = ProcessVideoFrame( p_demux, p_sys->p_buffers[buf.index].start, buf.bytesused );
  1233.         if( !p_block ) return 0;
  1234.         /* Unlock */
  1235.         if( v4l2_ioctl( p_sys->i_fd, VIDIOC_QBUF, &buf ) < 0 )
  1236.         {
  1237.             msg_Err( p_demux, "Failed to unlock (VIDIOC_QBUF)" );
  1238.             block_Release( p_block );
  1239.             return 0;
  1240.         }
  1241.         break;
  1242.     case IO_METHOD_USERPTR:
  1243.         memset( &buf, 0, sizeof(buf) );
  1244.         buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  1245.         buf.memory = V4L2_MEMORY_USERPTR;
  1246.         /* Wait for next frame */
  1247.         if (v4l2_ioctl( p_sys->i_fd, VIDIOC_DQBUF, &buf ) < 0 )
  1248.         {
  1249.             switch( errno )
  1250.             {
  1251.             case EAGAIN:
  1252.                 return 0;
  1253.             case EIO:
  1254.                 /* Could ignore EIO, see spec. */
  1255.                 /* fall through */
  1256.             default:
  1257.                 msg_Err( p_demux, "Failed to wait (VIDIOC_DQBUF)" );
  1258.                 return 0;
  1259.             }
  1260.         }
  1261.         /* Find frame? */
  1262.         unsigned int i;
  1263.         for( i = 0; i < p_sys->i_nbuffers; i++ )
  1264.         {
  1265.             if( buf.m.userptr == (unsigned long)p_sys->p_buffers[i].start &&
  1266.                 buf.length == p_sys->p_buffers[i].length ) break;
  1267.         }
  1268.         if( i >= p_sys->i_nbuffers )
  1269.         {
  1270.             msg_Err( p_demux, "Failed capturing new frame as i>=nbuffers" );
  1271.             return 0;
  1272.         }
  1273.         p_block = ProcessVideoFrame( p_demux, (uint8_t*)buf.m.userptr, buf.bytesused );
  1274.         if( !p_block ) return 0;
  1275.         /* Unlock */
  1276.         if( v4l2_ioctl( p_sys->i_fd, VIDIOC_QBUF, &buf ) < 0 )
  1277.         {
  1278.             msg_Err( p_demux, "Failed to unlock (VIDIOC_QBUF)" );
  1279.             block_Release( p_block );
  1280.             return 0;
  1281.         }
  1282.         break;
  1283.     default:
  1284.         break;
  1285.     }
  1286.     /* Timestamp */
  1287.     p_sys->i_video_pts = p_block->i_pts = p_block->i_dts = mdate();
  1288.     return p_block;
  1289. }
  1290. /*****************************************************************************
  1291.  * ProcessVideoFrame: Helper function to take a buffer and copy it into
  1292.  * a new block
  1293.  *****************************************************************************/
  1294. static block_t* ProcessVideoFrame( vlc_object_t *p_demux, uint8_t *p_frame, size_t i_size )
  1295. {
  1296.     block_t *p_block;
  1297.     if( !p_frame ) return 0;
  1298.     /* New block */
  1299.     if( !( p_block = block_New( p_demux, i_size ) ) )
  1300.     {
  1301.         msg_Warn( p_demux, "Cannot get new block" );
  1302.         return 0;
  1303.     }
  1304.     /* Copy frame */
  1305.     memcpy( p_block->p_buffer, p_frame, i_size );
  1306.     return p_block;
  1307. }
  1308. /*****************************************************************************
  1309.  * Helper function to initalise video IO using the Read method
  1310.  *****************************************************************************/
  1311. static int InitRead( vlc_object_t *p_demux, demux_sys_t *p_sys, unsigned int i_buffer_size )
  1312. {
  1313.     (void)p_demux;
  1314.     p_sys->p_buffers = calloc( 1, sizeof( *p_sys->p_buffers ) );
  1315.     if( !p_sys->p_buffers )
  1316.         return VLC_EGENERIC;
  1317.     p_sys->p_buffers[0].length = i_buffer_size;
  1318.     p_sys->p_buffers[0].start = malloc( i_buffer_size );
  1319.     if( !p_sys->p_buffers[0].start )
  1320.         return VLC_ENOMEM;
  1321.     return VLC_SUCCESS;
  1322. }
  1323. /*****************************************************************************
  1324.  * Helper function to initalise video IO using the mmap method
  1325.  *****************************************************************************/
  1326. static int InitMmap( vlc_object_t *p_demux, demux_sys_t *p_sys, int i_fd )
  1327. {
  1328.     struct v4l2_requestbuffers req;
  1329.     memset( &req, 0, sizeof(req) );
  1330.     req.count = 4;
  1331.     req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  1332.     req.memory = V4L2_MEMORY_MMAP;
  1333.     if( v4l2_ioctl( i_fd, VIDIOC_REQBUFS, &req ) < 0 )
  1334.     {
  1335.         msg_Err( p_demux, "device does not support mmap i/o" );
  1336.         goto open_failed;
  1337.     }
  1338.     if( req.count < 2 )
  1339.     {
  1340.         msg_Err( p_demux, "Insufficient buffer memory" );
  1341.         goto open_failed;
  1342.     }
  1343.     p_sys->p_buffers = calloc( req.count, sizeof( *p_sys->p_buffers ) );
  1344.     if( !p_sys->p_buffers )
  1345.         goto open_failed;
  1346.     for( p_sys->i_nbuffers = 0; p_sys->i_nbuffers < req.count; ++p_sys->i_nbuffers )
  1347.     {
  1348.         struct v4l2_buffer buf;
  1349.         memset( &buf, 0, sizeof(buf) );
  1350.         buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  1351.         buf.memory = V4L2_MEMORY_MMAP;
  1352.         buf.index = p_sys->i_nbuffers;
  1353.         if( v4l2_ioctl( i_fd, VIDIOC_QUERYBUF, &buf ) < 0 )
  1354.         {
  1355.             msg_Err( p_demux, "VIDIOC_QUERYBUF" );
  1356.             goto open_failed;
  1357.         }
  1358.         p_sys->p_buffers[p_sys->i_nbuffers].length = buf.length;
  1359.         p_sys->p_buffers[p_sys->i_nbuffers].start =
  1360.             v4l2_mmap( NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, i_fd, buf.m.offset );
  1361.         if( p_sys->p_buffers[p_sys->i_nbuffers].start == MAP_FAILED )
  1362.         {
  1363.             msg_Err( p_demux, "mmap failed (%m)" );
  1364.             goto open_failed;
  1365.         }
  1366.     }
  1367.     return VLC_SUCCESS;
  1368. open_failed:
  1369.     return VLC_EGENERIC;
  1370. }
  1371. /*****************************************************************************
  1372.  * Helper function to initalise video IO using the userbuf method
  1373.  *****************************************************************************/
  1374. static int InitUserP( vlc_object_t *p_demux, demux_sys_t *p_sys, int i_fd, unsigned int i_buffer_size )
  1375. {
  1376.     struct v4l2_requestbuffers req;
  1377.     unsigned int i_page_size;
  1378.     i_page_size = sysconf(_SC_PAGESIZE);
  1379.     i_buffer_size = ( i_buffer_size + i_page_size - 1 ) & ~( i_page_size - 1);
  1380.     memset( &req, 0, sizeof(req) );
  1381.     req.count = 4;
  1382.     req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  1383.     req.memory = V4L2_MEMORY_USERPTR;
  1384.     if( v4l2_ioctl( i_fd, VIDIOC_REQBUFS, &req ) < 0 )
  1385.     {
  1386.         msg_Err( p_demux, "device does not support user pointer i/o" );
  1387.         return VLC_EGENERIC;
  1388.     }
  1389.     p_sys->p_buffers = calloc( 4, sizeof( *p_sys->p_buffers ) );
  1390.     if( !p_sys->p_buffers )
  1391.         goto open_failed;
  1392.     for( p_sys->i_nbuffers = 0; p_sys->i_nbuffers < 4; ++p_sys->i_nbuffers )
  1393.     {
  1394.         p_sys->p_buffers[p_sys->i_nbuffers].length = i_buffer_size;
  1395.         if( posix_memalign( &p_sys->p_buffers[p_sys->i_nbuffers].start,
  1396.                 /* boundary */ i_page_size, i_buffer_size ) )
  1397.             goto open_failed;
  1398.     }
  1399.     return VLC_SUCCESS;
  1400. open_failed:
  1401.     free( p_sys->p_buffers );
  1402.     return VLC_EGENERIC;
  1403. }
  1404. /*****************************************************************************
  1405.  * IsPixelFormatSupported: returns true if the specified V4L2 pixel format is
  1406.  * in the array of supported formats returned by the driver
  1407.  *****************************************************************************/
  1408. static bool IsPixelFormatSupported( demux_t *p_demux, unsigned int i_pixelformat )
  1409. {
  1410.     demux_sys_t *p_sys = p_demux->p_sys;
  1411.     for( int i_index = 0; i_index < p_sys->i_codec; i_index++ )
  1412.     {
  1413.         if( p_sys->p_codecs[i_index].pixelformat == i_pixelformat )
  1414.             return true;
  1415.     }
  1416.     return false;
  1417. }
  1418. static float GetMaxFrameRate( demux_t *p_demux, int i_fd,
  1419.                               uint32_t i_pixel_format,
  1420.                               uint32_t i_width, uint32_t i_height )
  1421. {
  1422.     (void)p_demux;
  1423. #ifdef VIDIOC_ENUM_FRAMEINTERVALS
  1424. #ifdef HAVE_LIBV4L2
  1425.     demux_sys_t *p_sys = p_demux->p_sys;
  1426. #endif
  1427.     /* This is new in Linux 2.6.19 */
  1428.     struct v4l2_frmivalenum frmival;
  1429.     memset( &frmival, 0, sizeof(frmival) );
  1430.     frmival.pixel_format = i_pixel_format;
  1431.     frmival.width = i_width;
  1432.     frmival.height = i_height;
  1433.     if( v4l2_ioctl( i_fd, VIDIOC_ENUM_FRAMEINTERVALS, &frmival ) >= 0 )
  1434.     {
  1435.         switch( frmival.type )
  1436.         {
  1437.             case V4L2_FRMIVAL_TYPE_DISCRETE:
  1438.             {
  1439.                 float f_fps_max = -1;
  1440.                 do
  1441.                 {
  1442.                     float f_fps = (float)frmival.discrete.denominator
  1443.                                 / (float)frmival.discrete.numerator;
  1444.                     if( f_fps > f_fps_max ) f_fps_max = f_fps;
  1445.                     frmival.index++;
  1446.                 } while( v4l2_ioctl( i_fd, VIDIOC_ENUM_FRAMEINTERVALS,
  1447.                                      &frmival ) >= 0 );
  1448.                 return f_fps_max;
  1449.             }
  1450.             case V4L2_FRMSIZE_TYPE_STEPWISE:
  1451.             case V4L2_FRMIVAL_TYPE_CONTINUOUS:
  1452.                 return __MAX( (float)frmival.stepwise.max.denominator
  1453.                             / (float)frmival.stepwise.max.numerator,
  1454.                               (float)frmival.stepwise.min.denominator
  1455.                             / (float)frmival.stepwise.min.numerator );
  1456.         }
  1457.     }
  1458. #endif
  1459.     return -1.;
  1460. }
  1461. static float GetAbsoluteMaxFrameRate( demux_t *p_demux, int i_fd,
  1462.                                       uint32_t i_pixel_format )
  1463. {
  1464.     float f_fps_max = -1.;
  1465. #ifdef VIDIOC_ENUM_FRAMESIZES
  1466. #ifdef HAVE_LIBV4L2
  1467.     demux_sys_t *p_sys = p_demux->p_sys;
  1468. #endif
  1469.     /* This is new in Linux 2.6.19 */
  1470.     struct v4l2_frmsizeenum frmsize;
  1471.     memset( &frmsize, 0, sizeof(frmsize) );
  1472.     frmsize.pixel_format = i_pixel_format;
  1473.     if( v4l2_ioctl( i_fd, VIDIOC_ENUM_FRAMESIZES, &frmsize ) >= 0 )
  1474.     {
  1475.         switch( frmsize.type )
  1476.         {
  1477.             case V4L2_FRMSIZE_TYPE_DISCRETE:
  1478.                 do
  1479.                 {
  1480.                     frmsize.index++;
  1481.                     float f_fps = GetMaxFrameRate( p_demux, i_fd,
  1482.                                                    i_pixel_format,
  1483.                                                    frmsize.discrete.width,
  1484.                                                    frmsize.discrete.height );
  1485.                     if( f_fps > f_fps_max ) f_fps_max = f_fps;
  1486.                 } while( v4l2_ioctl( i_fd, VIDIOC_ENUM_FRAMESIZES,
  1487.                          &frmsize ) >= 0 );
  1488.                 break;
  1489.             case V4L2_FRMSIZE_TYPE_STEPWISE:
  1490.             {
  1491.                 uint32_t i_width = frmsize.stepwise.min_width;
  1492.                 uint32_t i_height = frmsize.stepwise.min_height;
  1493.                 for( ;
  1494.                      i_width <= frmsize.stepwise.max_width &&
  1495.                      i_height <= frmsize.stepwise.max_width;
  1496.                      i_width += frmsize.stepwise.step_width,
  1497.                      i_height += frmsize.stepwise.step_height )
  1498.                 {
  1499.                     float f_fps = GetMaxFrameRate( p_demux, i_fd,
  1500.                                                    i_pixel_format,
  1501.                                                    i_width, i_height );
  1502.                     if( f_fps > f_fps_max ) f_fps_max = f_fps;
  1503.                 }
  1504.                 break;
  1505.             }
  1506.             case V4L2_FRMSIZE_TYPE_CONTINUOUS:
  1507.                 /* FIXME */
  1508.                 msg_Err( p_demux, "GetAbsoluteMaxFrameRate implementation for V4L2_FRMSIZE_TYPE_CONTINUOUS isn't correct" );
  1509.                  f_fps_max = GetMaxFrameRate( p_demux, i_fd,
  1510.                                               i_pixel_format,
  1511.                                               frmsize.stepwise.max_width,
  1512.                                               frmsize.stepwise.max_height );
  1513.                 break;
  1514.         }
  1515.     }
  1516. #endif
  1517.     return f_fps_max;
  1518. }
  1519. static void GetMaxDimensions( demux_t *p_demux, int i_fd,
  1520.                               uint32_t i_pixel_format, float f_fps_min,
  1521.                               uint32_t *pi_width, uint32_t *pi_height )
  1522. {
  1523.     *pi_width = 0;
  1524.     *pi_height = 0;
  1525. #ifdef VIDIOC_ENUM_FRAMESIZES
  1526. #ifdef HAVE_LIBV4L2
  1527.     demux_sys_t *p_sys = p_demux->p_sys;
  1528. #endif
  1529.     /* This is new in Linux 2.6.19 */
  1530.     struct v4l2_frmsizeenum frmsize;
  1531.     memset( &frmsize, 0, sizeof(frmsize) );
  1532.     frmsize.pixel_format = i_pixel_format;
  1533.     if( v4l2_ioctl( i_fd, VIDIOC_ENUM_FRAMESIZES, &frmsize ) >= 0 )
  1534.     {
  1535.         switch( frmsize.type )
  1536.         {
  1537.             case V4L2_FRMSIZE_TYPE_DISCRETE:
  1538.                 do
  1539.                 {
  1540.                     frmsize.index++;
  1541.                     float f_fps = GetMaxFrameRate( p_demux, i_fd,
  1542.                                                    i_pixel_format,
  1543.                                                    frmsize.discrete.width,
  1544.                                                    frmsize.discrete.height );
  1545.                     if( f_fps >= f_fps_min &&
  1546.                         frmsize.discrete.width > *pi_width )
  1547.                     {
  1548.                         *pi_width = frmsize.discrete.width;
  1549.                         *pi_height = frmsize.discrete.height;
  1550.                     }
  1551.                 } while( v4l2_ioctl( i_fd, VIDIOC_ENUM_FRAMESIZES,
  1552.                          &frmsize ) >= 0 );
  1553.                 break;
  1554.             case V4L2_FRMSIZE_TYPE_STEPWISE:
  1555.             {
  1556.                 uint32_t i_width = frmsize.stepwise.min_width;
  1557.                 uint32_t i_height = frmsize.stepwise.min_height;
  1558.                 for( ;
  1559.                      i_width <= frmsize.stepwise.max_width &&
  1560.                      i_height <= frmsize.stepwise.max_width;
  1561.                      i_width += frmsize.stepwise.step_width,
  1562.                      i_height += frmsize.stepwise.step_height )
  1563.                 {
  1564.                     float f_fps = GetMaxFrameRate( p_demux, i_fd,
  1565.                                                    i_pixel_format,
  1566.                                                    i_width, i_height );
  1567.                     if( f_fps >= f_fps_min && i_width > *pi_width )
  1568.                     {
  1569.                         *pi_width = i_width;
  1570.                         *pi_height = i_height;
  1571.                     }
  1572.                 }
  1573.                 break;
  1574.             }
  1575.             case V4L2_FRMSIZE_TYPE_CONTINUOUS:
  1576.                 /* FIXME */
  1577.                 msg_Err( p_demux, "GetMaxDimension implementation for V4L2_FRMSIZE_TYPE_CONTINUOUS isn't correct" );
  1578.                 float f_fps = GetMaxFrameRate( p_demux, i_fd,
  1579.                                                i_pixel_format,
  1580.                                                frmsize.stepwise.max_width,
  1581.                                                frmsize.stepwise.max_height );
  1582.                 if( f_fps >= f_fps_min &&
  1583.                     frmsize.stepwise.max_width > *pi_width )
  1584.                 {
  1585.                     *pi_width = frmsize.stepwise.max_width;
  1586.                     *pi_height = frmsize.stepwise.max_height;
  1587.                 }
  1588.                 break;
  1589.         }
  1590.     }
  1591. #endif
  1592. }
  1593. /*****************************************************************************
  1594.  * OpenVideoDev: open and set up the video device and probe for capabilities
  1595.  *****************************************************************************/
  1596. static int OpenVideoDev( vlc_object_t *p_obj, demux_sys_t *p_sys, bool b_demux )
  1597. {
  1598.     int i_fd;
  1599.     struct v4l2_cropcap cropcap;
  1600.     struct v4l2_crop crop;
  1601.     struct v4l2_format fmt;
  1602.     unsigned int i_min;
  1603.     enum v4l2_buf_type buf_type;
  1604.     const char *psz_device = p_sys->psz_device;
  1605.     es_format_t es_fmt;
  1606.     if( ( i_fd = open( psz_device, O_RDWR ) ) < 0 )
  1607.     {
  1608.         msg_Err( p_obj, "cannot open device (%m)" );
  1609.         goto open_failed;
  1610.     }
  1611. #ifdef HAVE_LIBV4L2
  1612.     /* Note the v4l2_xxx functions are designed so that if they get passed an
  1613.        unknown fd, the will behave exactly as their regular xxx counterparts,
  1614.        so if v4l2_fd_open fails, we continue as normal (missing the libv4l2
  1615.        custom cam format to normal formats conversion). Chances are big we will
  1616.        still fail then though, as normally v4l2_fd_open only fails if the
  1617.        device is not a v4l2 device. */
  1618.     if( p_sys->b_libv4l2 )
  1619.     {
  1620.         int libv4l2_fd;
  1621.         libv4l2_fd = v4l2_fd_open( i_fd, V4L2_ENABLE_ENUM_FMT_EMULATION );
  1622.         if( libv4l2_fd != -1 )
  1623.             i_fd = libv4l2_fd;
  1624.     }
  1625. #endif
  1626.     /* Tune the tuner */
  1627.     if( p_sys->i_frequency >= 0 )
  1628.     {
  1629.         if( p_sys->i_cur_tuner < 0 || p_sys->i_cur_tuner >= p_sys->i_tuner )
  1630.         {
  1631.             msg_Err( p_obj, "invalid tuner %d.", p_sys->i_cur_tuner );
  1632.             goto open_failed;
  1633.         }
  1634.         struct v4l2_frequency frequency;
  1635.         memset( &frequency, 0, sizeof( frequency ) );
  1636.         frequency.tuner = p_sys->i_cur_tuner;
  1637.         frequency.type = p_sys->p_tuners[p_sys->i_cur_tuner].type;
  1638.         frequency.frequency = p_sys->i_frequency / 62.5;
  1639.         if( v4l2_ioctl( i_fd, VIDIOC_S_FREQUENCY, &frequency ) < 0 )
  1640.         {
  1641.             msg_Err( p_obj, "cannot set tuner frequency (%m)" );
  1642.             goto open_failed;
  1643.         }
  1644.         msg_Dbg( p_obj, "Tuner frequency set" );
  1645.     }
  1646.     /* Set the tuner's audio mode */
  1647.     if( p_sys->i_audio_mode >= 0 )
  1648.     {
  1649.         if( p_sys->i_cur_tuner < 0 || p_sys->i_cur_tuner >= p_sys->i_tuner )
  1650.         {
  1651.             msg_Err( p_obj, "invalid tuner %d.", p_sys->i_cur_tuner );
  1652.             goto open_failed;
  1653.         }
  1654.         struct v4l2_tuner tuner;
  1655.         memset( &tuner, 0, sizeof( tuner ) );
  1656.         tuner.index = p_sys->i_cur_tuner;
  1657.         tuner.audmode = p_sys->i_audio_mode;
  1658.         if( v4l2_ioctl( i_fd, VIDIOC_S_TUNER, &tuner ) < 0 )
  1659.         {
  1660.             msg_Err( p_obj, "cannot set tuner audio mode (%m)" );
  1661.             goto open_failed;
  1662.         }
  1663.         msg_Dbg( p_obj, "Tuner audio mode set" );
  1664.     }
  1665.     /* Select standard */
  1666.     if( p_sys->i_selected_standard_id != V4L2_STD_UNKNOWN )
  1667.     {
  1668.         if( v4l2_ioctl( i_fd, VIDIOC_S_STD, &p_sys->i_selected_standard_id ) < 0 )
  1669.         {
  1670.             msg_Err( p_obj, "cannot set standard (%m)" );
  1671.             goto open_failed;
  1672.         }
  1673.         msg_Dbg( p_obj, "Set standard" );
  1674.     }
  1675.     /* Select input */
  1676.     if( p_sys->i_selected_input >= p_sys->i_input )
  1677.     {
  1678.         msg_Warn( p_obj, "invalid input. Using the default one" );
  1679.         p_sys->i_selected_input = 0;
  1680.     }
  1681.     if( v4l2_ioctl( i_fd, VIDIOC_S_INPUT, &p_sys->i_selected_input ) < 0 )
  1682.     {
  1683.         msg_Err( p_obj, "cannot set input (%m)" );
  1684.         goto open_failed;
  1685.     }
  1686.     /* Set audio input */
  1687.     if( p_sys->i_audio > 0 )
  1688.     {
  1689.         if( p_sys->i_selected_audio_input < 0
  1690.          || p_sys->i_selected_audio_input >= p_sys->i_audio )
  1691.         {
  1692.             msg_Warn( p_obj, "invalid audio input. Using the default one" );
  1693.             p_sys->i_selected_audio_input = 0;
  1694.         }
  1695.         if( v4l2_ioctl( i_fd, VIDIOC_S_AUDIO, &p_sys->p_audios[p_sys->i_selected_audio_input] ) < 0 )
  1696.         {
  1697.             msg_Err( p_obj, "cannot set audio input (%m)" );
  1698.             goto open_failed;
  1699.         }
  1700.         msg_Dbg( p_obj, "Audio input set to %d", p_sys->i_selected_audio_input );
  1701.     }
  1702.     /* TODO: Move the resolution stuff up here */
  1703.     /* if MPEG encoder card, no need to do anything else after this */
  1704.     ControlList( p_obj, p_sys, i_fd,
  1705.                   var_GetBool( p_obj, "v4l2-controls-reset" ), b_demux );
  1706.     SetAvailControlsByString( p_obj, p_sys, i_fd );
  1707.     /* Verify device support for the various IO methods */
  1708.     switch( p_sys->io )
  1709.     {
  1710.         case IO_METHOD_READ:
  1711.             if( !(p_sys->dev_cap.capabilities & V4L2_CAP_READWRITE) )
  1712.             {
  1713.                 msg_Err( p_obj, "device does not support read i/o" );
  1714.                 goto open_failed;
  1715.             }
  1716.             msg_Dbg( p_obj, "using read i/o" );
  1717.             break;
  1718.         case IO_METHOD_MMAP:
  1719.         case IO_METHOD_USERPTR:
  1720.             if( !(p_sys->dev_cap.capabilities & V4L2_CAP_STREAMING) )
  1721.             {
  1722.                 msg_Err( p_obj, "device does not support streaming i/o" );
  1723.                 goto open_failed;
  1724.             }
  1725.             if( p_sys->io == IO_METHOD_MMAP )
  1726.                 msg_Dbg( p_obj, "using streaming i/o (mmap)" );
  1727.             else
  1728.                 msg_Dbg( p_obj, "using streaming i/o (userptr)" );
  1729.             break;
  1730.         default:
  1731.             msg_Err( p_obj, "io method not supported" );
  1732.             goto open_failed;
  1733.     }
  1734.     /* Reset Cropping */
  1735.     memset( &cropcap, 0, sizeof(cropcap) );
  1736.     cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  1737.     if( v4l2_ioctl( i_fd, VIDIOC_CROPCAP, &cropcap ) >= 0 )
  1738.     {
  1739.         crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  1740.         crop.c = cropcap.defrect; /* reset to default */
  1741.         if( crop.c.width > 0 && crop.c.height > 0 ) /* Fix for fm tuners */
  1742.         {
  1743.             if( v4l2_ioctl( i_fd, VIDIOC_S_CROP, &crop ) < 0 )
  1744.             {
  1745.                 switch( errno )
  1746.                 {
  1747.                     case EINVAL:
  1748.                         /* Cropping not supported. */
  1749.                         break;
  1750.                     default:
  1751.                         /* Errors ignored. */
  1752.                         break;
  1753.                 }
  1754.             }
  1755.         }
  1756.     }
  1757.     /* Try and find default resolution if not specified */
  1758.     memset( &fmt, 0, sizeof(fmt) );
  1759.     fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  1760.     if( p_sys->i_width <= 0 || p_sys->i_height <= 0 )
  1761.     {
  1762.         /* Use current width and height settings */
  1763.         if( v4l2_ioctl( i_fd, VIDIOC_G_FMT, &fmt ) < 0 )
  1764.         {
  1765.             msg_Err( p_obj, "Cannot get default width and height." );
  1766.             goto open_failed;
  1767.         }
  1768.         msg_Dbg( p_obj, "found default width and height of %ux%u",
  1769.                  fmt.fmt.pix.width, fmt.fmt.pix.height );
  1770.         if( p_sys->i_width < 0 || p_sys->i_height < 0 )
  1771.         {
  1772.             msg_Dbg( p_obj, "will try to find optimal width and height." );
  1773.         }
  1774.     }
  1775.     else
  1776.     {
  1777.         /* Use user specified width and height */
  1778.         msg_Dbg( p_obj, "trying specified size %dx%d", p_sys->i_width, p_sys->i_height );
  1779.         fmt.fmt.pix.width = p_sys->i_width;
  1780.         fmt.fmt.pix.height = p_sys->i_height;
  1781.     }
  1782.     fmt.fmt.pix.field = V4L2_FIELD_NONE;
  1783.     if (b_demux)
  1784.     {
  1785.         demux_t *p_demux = (demux_t *) p_obj;
  1786.         /* Test and set Chroma */
  1787.         fmt.fmt.pix.pixelformat = 0;
  1788.         if( p_sys->psz_requested_chroma && *p_sys->psz_requested_chroma )
  1789.         {
  1790.             /* User specified chroma */
  1791.             int i_requested_fourcc = VLC_FOURCC(
  1792.                 p_sys->psz_requested_chroma[0], p_sys->psz_requested_chroma[1],
  1793.                 p_sys->psz_requested_chroma[2], p_sys->psz_requested_chroma[3] );
  1794.             for( int i = 0; v4l2chroma_to_fourcc[i].i_v4l2 != 0; i++ )
  1795.             {
  1796.                 if( v4l2chroma_to_fourcc[i].i_fourcc == i_requested_fourcc )
  1797.                 {
  1798.                     fmt.fmt.pix.pixelformat = v4l2chroma_to_fourcc[i].i_v4l2;
  1799.                     break;
  1800.                 }
  1801.             }
  1802.             /* Try and set user chroma */
  1803.             bool b_error = !IsPixelFormatSupported( p_demux, fmt.fmt.pix.pixelformat );
  1804.             if( !b_error && fmt.fmt.pix.pixelformat )
  1805.             {
  1806.                 if( v4l2_ioctl( i_fd, VIDIOC_S_FMT, &fmt ) < 0 )
  1807.                 {
  1808.                     fmt.fmt.pix.field = V4L2_FIELD_ANY;
  1809.                     if( v4l2_ioctl( i_fd, VIDIOC_S_FMT, &fmt ) < 0 )
  1810.                     {
  1811.                         fmt.fmt.pix.field = V4L2_FIELD_NONE;
  1812.                         b_error = true;
  1813.                     }
  1814.                 }
  1815.             }
  1816.             if( b_error )
  1817.             {
  1818.                 msg_Warn( p_demux, "Driver is unable to use specified chroma %s. Trying defaults.", p_sys->psz_requested_chroma );
  1819.                 fmt.fmt.pix.pixelformat = 0;
  1820.             }
  1821.         }
  1822.         /* If no user specified chroma, find best */
  1823.         /* This also decides if MPEG encoder card or not */
  1824.         if( !fmt.fmt.pix.pixelformat )
  1825.         {
  1826.             unsigned int i;
  1827.             for( i = 0; i < ARRAY_SIZE( p_chroma_fallbacks ); i++ )
  1828.             {
  1829.                 fmt.fmt.pix.pixelformat = p_chroma_fallbacks[i];
  1830.                 if( IsPixelFormatSupported( p_demux, fmt.fmt.pix.pixelformat ) )
  1831.                 {
  1832.                     if( v4l2_ioctl( i_fd, VIDIOC_S_FMT, &fmt ) >= 0 )
  1833.                         break;
  1834.                     fmt.fmt.pix.field = V4L2_FIELD_ANY;
  1835.                     if( v4l2_ioctl( i_fd, VIDIOC_S_FMT, &fmt ) >= 0 )
  1836.                         break;
  1837.                     fmt.fmt.pix.field = V4L2_FIELD_NONE;
  1838.                 }
  1839.             }
  1840.             if( i == ARRAY_SIZE( p_chroma_fallbacks ) )
  1841.             {
  1842.                 msg_Warn( p_demux, "Could not select any of the default chromas; attempting to open as MPEG encoder card (access)" );
  1843.                 goto open_failed;
  1844.             }
  1845.         }
  1846.         if( p_sys->i_width < 0 || p_sys->i_height < 0 )
  1847.         {
  1848.             if( p_sys->f_fps <= 0 )
  1849.             {
  1850.                 p_sys->f_fps = GetAbsoluteMaxFrameRate( p_demux, i_fd,
  1851.                                                         fmt.fmt.pix.pixelformat );
  1852.                 msg_Dbg( p_demux, "Found maximum framerate of %f", p_sys->f_fps );
  1853.             }
  1854.             uint32_t i_width, i_height;
  1855.             GetMaxDimensions( p_demux, i_fd,
  1856.                               fmt.fmt.pix.pixelformat, p_sys->f_fps,
  1857.                               &i_width, &i_height );
  1858.             if( i_width || i_height )
  1859.             {
  1860.                 msg_Dbg( p_demux, "Found optimal dimensions for framerate %f "
  1861.                                   "of %ux%u", p_sys->f_fps, i_width, i_height );
  1862.                 fmt.fmt.pix.width = i_width;
  1863.                 fmt.fmt.pix.height = i_height;
  1864.                 if( v4l2_ioctl( i_fd, VIDIOC_S_FMT, &fmt ) < 0 )
  1865.                 {
  1866.                     msg_Err( p_obj, "Cannot set size to optimal dimensions "
  1867.                                     "%ux%u", i_width, i_height );
  1868.                     goto open_failed;
  1869.                 }
  1870.             }
  1871.             else
  1872.             {
  1873.                 msg_Warn( p_obj, "Could not find optimal width and height, "
  1874.                                  "falling back to driver default." );
  1875.             }
  1876.         }
  1877.     }
  1878.     p_sys->i_width = fmt.fmt.pix.width;
  1879.     p_sys->i_height = fmt.fmt.pix.height;
  1880.     if( v4l2_ioctl( i_fd, VIDIOC_G_FMT, &fmt ) < 0 ) {;}
  1881.     /* Print extra info */
  1882.     msg_Dbg( p_obj, "Driver requires at most %d bytes to store a complete image", fmt.fmt.pix.sizeimage );
  1883.     /* Check interlacing */
  1884.     switch( fmt.fmt.pix.field )
  1885.     {
  1886.         case V4L2_FIELD_NONE:
  1887.             msg_Dbg( p_obj, "Interlacing setting: progressive" );
  1888.             break;
  1889.         case V4L2_FIELD_TOP:
  1890.             msg_Dbg( p_obj, "Interlacing setting: top field only" );
  1891.             break;
  1892.         case V4L2_FIELD_BOTTOM:
  1893.             msg_Dbg( p_obj, "Interlacing setting: bottom field only" );
  1894.             break;
  1895.         case V4L2_FIELD_INTERLACED:
  1896.             msg_Dbg( p_obj, "Interlacing setting: interleaved (bottom top if M/NTSC, top bottom otherwise)" );
  1897.             break;
  1898.         case V4L2_FIELD_SEQ_TB:
  1899.             msg_Dbg( p_obj, "Interlacing setting: sequential top bottom" );
  1900.             break;
  1901.         case V4L2_FIELD_SEQ_BT:
  1902.             msg_Dbg( p_obj, "Interlacing setting: sequential bottom top" );
  1903.             break;
  1904.         case V4L2_FIELD_ALTERNATE:
  1905.             msg_Dbg( p_obj, "Interlacing setting: alternate fields" );
  1906.             p_sys->i_height = p_sys->i_height * 2;
  1907.             break;
  1908.         case V4L2_FIELD_INTERLACED_TB:
  1909.             msg_Dbg( p_obj, "Interlacing setting: interleaved top bottom" );
  1910.             break;
  1911.         case V4L2_FIELD_INTERLACED_BT:
  1912.             msg_Dbg( p_obj, "Interlacing setting: interleaved bottom top" );
  1913.             break;
  1914.         default:
  1915.             msg_Warn( p_obj, "Interlacing setting: unknown type (%d)",
  1916.                       fmt.fmt.pix.field );
  1917.             break;
  1918.     }
  1919.     if( fmt.fmt.pix.field != V4L2_FIELD_NONE )
  1920.         msg_Warn( p_obj, "Interlaced inputs haven't been tested. Please report any issue." );
  1921.     /* Look up final fourcc */
  1922.     p_sys->i_fourcc = 0;
  1923.     for( int i = 0; v4l2chroma_to_fourcc[i].i_fourcc != 0; i++ )
  1924.     {
  1925.         if( v4l2chroma_to_fourcc[i].i_v4l2 == fmt.fmt.pix.pixelformat )
  1926.         {
  1927.             p_sys->i_fourcc = v4l2chroma_to_fourcc[i].i_fourcc;
  1928.             es_format_Init( &es_fmt, VIDEO_ES, p_sys->i_fourcc );
  1929.             es_fmt.video.i_rmask = v4l2chroma_to_fourcc[i].i_rmask;
  1930.             es_fmt.video.i_gmask = v4l2chroma_to_fourcc[i].i_gmask;
  1931.             es_fmt.video.i_bmask = v4l2chroma_to_fourcc[i].i_bmask;
  1932.             break;
  1933.         }
  1934.     }
  1935.     /* Buggy driver paranoia */
  1936.     i_min = fmt.fmt.pix.width * 2;
  1937.     if( fmt.fmt.pix.bytesperline < i_min )
  1938.         fmt.fmt.pix.bytesperline = i_min;
  1939.     i_min = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height;
  1940.     if( fmt.fmt.pix.sizeimage < i_min )
  1941.         fmt.fmt.pix.sizeimage = i_min;
  1942. #ifdef VIDIOC_ENUM_FRAMEINTERVALS
  1943.     /* This is new in Linux 2.6.19 */
  1944.     /* List supported frame rates */
  1945.     struct v4l2_frmivalenum frmival;
  1946.     memset( &frmival, 0, sizeof(frmival) );
  1947.     frmival.pixel_format = fmt.fmt.pix.pixelformat;
  1948.     frmival.width = p_sys->i_width;
  1949.     frmival.height = p_sys->i_height;
  1950.     if( v4l2_ioctl( i_fd, VIDIOC_ENUM_FRAMEINTERVALS, &frmival ) >= 0 )
  1951.     {
  1952.         char psz_fourcc[5];
  1953.         memset( &psz_fourcc, 0, sizeof( psz_fourcc ) );
  1954.         vlc_fourcc_to_char( p_sys->i_fourcc, &psz_fourcc );
  1955.         msg_Dbg( p_obj, "supported frame intervals for %4s, %dx%d:",
  1956.                  psz_fourcc, frmival.width, frmival.height );
  1957.         switch( frmival.type )
  1958.         {
  1959.             case V4L2_FRMIVAL_TYPE_DISCRETE:
  1960.                 do
  1961.                 {
  1962.                     msg_Dbg( p_obj, "    supported frame interval: %d/%d",
  1963.                              frmival.discrete.numerator,
  1964.                              frmival.discrete.denominator );
  1965.                     frmival.index++;
  1966.                 } while( v4l2_ioctl( i_fd, VIDIOC_ENUM_FRAMEINTERVALS, &frmival ) >= 0 );
  1967.                 break;
  1968.             case V4L2_FRMIVAL_TYPE_STEPWISE:
  1969.                 msg_Dbg( p_obj, "    supported frame intervals: %d/%d to "
  1970.                          "%d/%d using %d/%d increments",
  1971.                          frmival.stepwise.min.numerator,
  1972.                          frmival.stepwise.min.denominator,
  1973.                          frmival.stepwise.max.numerator,
  1974.                          frmival.stepwise.max.denominator,
  1975.                          frmival.stepwise.step.numerator,
  1976.                          frmival.stepwise.step.denominator );
  1977.                 break;
  1978.             case V4L2_FRMIVAL_TYPE_CONTINUOUS:
  1979.                 msg_Dbg( p_obj, "    supported frame intervals: %d/%d to %d/%d",
  1980.                          frmival.stepwise.min.numerator,
  1981.                          frmival.stepwise.min.denominator,
  1982.                          frmival.stepwise.max.numerator,
  1983.                          frmival.stepwise.max.denominator );
  1984.                 break;
  1985.         }
  1986.     }
  1987. #endif
  1988.     /* Init IO method */
  1989.     switch( p_sys->io )
  1990.     {
  1991.     case IO_METHOD_READ:
  1992.         if( b_demux )
  1993.             if( InitRead( p_obj, p_sys, fmt.fmt.pix.sizeimage ) != VLC_SUCCESS ) goto open_failed;
  1994.         break;
  1995.     case IO_METHOD_MMAP:
  1996.         if( InitMmap( p_obj, p_sys, i_fd ) != VLC_SUCCESS ) goto open_failed;
  1997.         break;
  1998.     case IO_METHOD_USERPTR:
  1999.         if( InitUserP( p_obj, p_sys, i_fd, fmt.fmt.pix.sizeimage ) != VLC_SUCCESS ) goto open_failed;
  2000.         break;
  2001.     default:
  2002.         goto open_failed;
  2003.         break;
  2004.     }
  2005.     if( b_demux )
  2006.     {
  2007.         /* Add */
  2008.         es_fmt.video.i_width  = p_sys->i_width;
  2009.         es_fmt.video.i_height = p_sys->i_height;
  2010.         /* Get aspect-ratio */
  2011.         es_fmt.video.i_aspect = p_sys->i_aspect;
  2012.         demux_t *p_demux = (demux_t *) p_obj;
  2013.         msg_Dbg( p_demux, "added new video es %4.4s %dx%d",
  2014.             (char*)&es_fmt.i_codec, es_fmt.video.i_width, es_fmt.video.i_height );
  2015.         p_sys->p_es = es_out_Add( p_demux->out, &es_fmt );
  2016.     }
  2017.     /* Start Capture */
  2018.     switch( p_sys->io )
  2019.     {
  2020.     case IO_METHOD_READ:
  2021.         /* Nothing to do */
  2022.         break;
  2023.     case IO_METHOD_MMAP:
  2024.         for (unsigned int i = 0; i < p_sys->i_nbuffers; ++i)
  2025.         {
  2026.             struct v4l2_buffer buf;
  2027.             memset( &buf, 0, sizeof(buf) );
  2028.             buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  2029.             buf.memory = V4L2_MEMORY_MMAP;
  2030.             buf.index = i;
  2031.             if( v4l2_ioctl( i_fd, VIDIOC_QBUF, &buf ) < 0 )
  2032.             {
  2033.                 msg_Err( p_obj, "VIDIOC_QBUF failed" );
  2034.                 goto open_failed;
  2035.             }
  2036.         }
  2037.         buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  2038.         if( v4l2_ioctl( i_fd, VIDIOC_STREAMON, &buf_type ) < 0 )
  2039.         {
  2040.             msg_Err( p_obj, "VIDIOC_STREAMON failed" );
  2041.             goto open_failed;
  2042.         }
  2043.         break;
  2044.     case IO_METHOD_USERPTR:
  2045.         for( unsigned int i = 0; i < p_sys->i_nbuffers; ++i )
  2046.         {
  2047.             struct v4l2_buffer buf;
  2048.             memset( &buf, 0, sizeof(buf) );
  2049.             buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  2050.             buf.memory = V4L2_MEMORY_USERPTR;
  2051.             buf.index = i;
  2052.             buf.m.userptr = (unsigned long)p_sys->p_buffers[i].start;
  2053.             buf.length = p_sys->p_buffers[i].length;
  2054.             if( v4l2_ioctl( i_fd, VIDIOC_QBUF, &buf ) < 0 )
  2055.             {
  2056.                 msg_Err( p_obj, "VIDIOC_QBUF failed" );
  2057.                 goto open_failed;
  2058.             }
  2059.         }
  2060.         buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  2061.         if( v4l2_ioctl( i_fd, VIDIOC_STREAMON, &buf_type ) < 0 )
  2062.         {
  2063.             msg_Err( p_obj, "VIDIOC_STREAMON failed" );
  2064.             goto open_failed;
  2065.         }
  2066.         break;
  2067.     default:
  2068.         goto open_failed;
  2069.         break;
  2070.     }
  2071.     /* report fps */
  2072.     if( p_sys->f_fps >= 0.1 )
  2073.     {
  2074.         msg_Dbg( p_obj, "User set fps=%f", p_sys->f_fps );
  2075.     }
  2076.     return i_fd;
  2077. open_failed:
  2078.     if( i_fd >= 0 ) v4l2_close( i_fd );
  2079.     return -1;
  2080. }
  2081. /*****************************************************************************
  2082.  * ProbeVideoDev: probe video for capabilities
  2083.  *****************************************************************************/
  2084. static bool ProbeVideoDev( vlc_object_t *p_obj, demux_sys_t *p_sys,
  2085.                                  const char *psz_device )
  2086. {
  2087.     int i_index;
  2088.     int i_standard;
  2089.     int i_fd;
  2090.     if( ( i_fd = open( psz_device, O_RDWR ) ) < 0 )
  2091.     {
  2092.         msg_Err( p_obj, "cannot open video device '%s' (%m)", psz_device );
  2093.         goto open_failed;
  2094.     }
  2095. #ifdef HAVE_LIBV4L2
  2096.     /* Note the v4l2_xxx functions are designed so that if they get passed an
  2097.        unknown fd, the will behave exactly as their regular xxx counterparts,
  2098.        so if v4l2_fd_open fails, we continue as normal (missing the libv4l2
  2099.        custom cam format to normal formats conversion). Chances are big we will
  2100.        still fail then though, as normally v4l2_fd_open only fails if the
  2101.        device is not a v4l2 device. */
  2102.     if( p_sys->b_libv4l2 )
  2103.     {
  2104.         int libv4l2_fd;
  2105.         libv4l2_fd = v4l2_fd_open( i_fd, V4L2_ENABLE_ENUM_FMT_EMULATION );
  2106.         if( libv4l2_fd != -1 )
  2107.             i_fd = libv4l2_fd;
  2108.     }
  2109. #endif
  2110.     /* Get device capabilites */
  2111.     if( v4l2_ioctl( i_fd, VIDIOC_QUERYCAP, &p_sys->dev_cap ) < 0 )
  2112.     {
  2113.         msg_Err( p_obj, "cannot get video capabilities (%m)" );
  2114.         goto open_failed;
  2115.     }
  2116.     msg_Dbg( p_obj, "V4L2 device: %s using driver: %s (version: %u.%u.%u) on %s",
  2117.                             p_sys->dev_cap.card,
  2118.                             p_sys->dev_cap.driver,
  2119.                             (p_sys->dev_cap.version >> 16) & 0xFF,
  2120.                             (p_sys->dev_cap.version >> 8) & 0xFF,
  2121.                             p_sys->dev_cap.version & 0xFF,
  2122.                             p_sys->dev_cap.bus_info );
  2123.     msg_Dbg( p_obj, "the device has the capabilities: (%c) Video Capure, "
  2124.                                                        "(%c) Audio, "
  2125.                                                        "(%c) Tuner, "
  2126.                                                        "(%c) Radio",
  2127.              ( p_sys->dev_cap.capabilities & V4L2_CAP_VIDEO_CAPTURE  ? 'X':' '),
  2128.              ( p_sys->dev_cap.capabilities & V4L2_CAP_AUDIO  ? 'X':' '),
  2129.              ( p_sys->dev_cap.capabilities & V4L2_CAP_TUNER  ? 'X':' '),
  2130.              ( p_sys->dev_cap.capabilities & V4L2_CAP_RADIO  ? 'X':' ') );
  2131.     msg_Dbg( p_obj, "supported I/O methods are: (%c) Read/Write, "
  2132.                                                  "(%c) Streaming, "
  2133.                                                  "(%c) Asynchronous",
  2134.             ( p_sys->dev_cap.capabilities & V4L2_CAP_READWRITE ? 'X':' ' ),
  2135.             ( p_sys->dev_cap.capabilities & V4L2_CAP_STREAMING ? 'X':' ' ),
  2136.             ( p_sys->dev_cap.capabilities & V4L2_CAP_ASYNCIO ? 'X':' ' ) );
  2137.     if( p_sys->io == IO_METHOD_AUTO )
  2138.     {
  2139.         if( p_sys->dev_cap.capabilities & V4L2_CAP_STREAMING )
  2140.             p_sys->io = IO_METHOD_MMAP;
  2141.         else if( p_sys->dev_cap.capabilities & V4L2_CAP_READWRITE )
  2142.             p_sys->io = IO_METHOD_READ;
  2143.         else
  2144.             msg_Err( p_obj, "No known I/O method supported" );
  2145.     }
  2146.     if( p_sys->dev_cap.capabilities & V4L2_CAP_RDS_CAPTURE )
  2147.         msg_Dbg( p_obj, "device supports RDS" );
  2148. #ifdef V4L2_CAP_HW_FREQ_SEEK
  2149.     if( p_sys->dev_cap.capabilities & V4L2_CAP_HW_FREQ_SEEK )
  2150.         msg_Dbg( p_obj, "device supports hardware frequency seeking" );
  2151. #endif
  2152.     if( p_sys->dev_cap.capabilities & V4L2_CAP_VBI_CAPTURE )
  2153.         msg_Dbg( p_obj, "device support raw VBI capture" );
  2154.     if( p_sys->dev_cap.capabilities & V4L2_CAP_SLICED_VBI_CAPTURE )
  2155.         msg_Dbg( p_obj, "device support sliced VBI capture" );
  2156.     /* Now, enumerate all the video inputs. This is useless at the moment
  2157.        since we have no way to present that info to the user except with
  2158.        debug messages */
  2159.     if( p_sys->dev_cap.capabilities & V4L2_CAP_VIDEO_CAPTURE )
  2160.     {
  2161.         struct v4l2_input t_input;
  2162.         memset( &t_input, 0, sizeof(t_input) );
  2163.         p_sys->i_input = 0;
  2164.         while( v4l2_ioctl( i_fd, VIDIOC_ENUMINPUT, &t_input ) >= 0 )
  2165.         {
  2166.             p_sys->i_input++;
  2167.             t_input.index = p_sys->i_input;
  2168.         }
  2169.         free( p_sys->p_inputs );
  2170.         p_sys->p_inputs = calloc( 1, p_sys->i_input * sizeof( struct v4l2_input ) );
  2171.         if( !p_sys->p_inputs ) goto open_failed;
  2172.         for( i_index = 0; i_index < p_sys->i_input; i_index++ )
  2173.         {
  2174.             p_sys->p_inputs[i_index].index = i_index;
  2175.             if( v4l2_ioctl( i_fd, VIDIOC_ENUMINPUT, &p_sys->p_inputs[i_index] ) )
  2176.             {
  2177.                 msg_Err( p_obj, "cannot get video input characteristics (%m)" );
  2178.                 goto open_failed;
  2179.             }
  2180.             msg_Dbg( p_obj, "video input %i (%s) has type: %s %c",
  2181.                                 i_index,
  2182.                                 p_sys->p_inputs[i_index].name,
  2183.                                 p_sys->p_inputs[i_index].type
  2184.                                         == V4L2_INPUT_TYPE_TUNER ?
  2185.                                         "Tuner adapter" :
  2186.                                         "External analog input",
  2187.                                 i_index == p_sys->i_selected_input ? '*' : ' ' );
  2188.         }
  2189.     }
  2190.     /* Probe video standards */
  2191.     if( p_sys->dev_cap.capabilities & V4L2_CAP_VIDEO_CAPTURE )
  2192.     {
  2193.         struct v4l2_standard t_standards;
  2194.         t_standards.index = 0;
  2195.         p_sys->i_standard = 0;
  2196.         while( v4l2_ioctl( i_fd, VIDIOC_ENUMSTD, &t_standards ) >=0 )
  2197.         {
  2198.             p_sys->i_standard++;
  2199.             t_standards.index = p_sys->i_standard;
  2200.         }
  2201.         free( p_sys->p_standards );
  2202.         p_sys->p_standards = calloc( 1, p_sys->i_standard * sizeof( struct v4l2_standard ) );
  2203.         if( !p_sys->p_standards ) goto open_failed;
  2204.         for( i_standard = 0; i_standard < p_sys->i_standard; i_standard++ )
  2205.         {
  2206.             p_sys->p_standards[i_standard].index = i_standard;
  2207.             if( v4l2_ioctl( i_fd, VIDIOC_ENUMSTD, &p_sys->p_standards[i_standard] ) )
  2208.             {
  2209.                 msg_Err( p_obj, "cannot get video input standards (%m)" );
  2210.                 goto open_failed;
  2211.             }
  2212.             msg_Dbg( p_obj, "video standard %i is: %s %c",
  2213.                                 i_standard,
  2214.                                 p_sys->p_standards[i_standard].name,
  2215.                                 (unsigned)i_standard == p_sys->i_selected_standard_id ? '*' : ' ' );
  2216.         }
  2217.     }
  2218.     /* initialize the structures for the ioctls */
  2219.     for( i_index = 0; i_index < 32; i_index++ )
  2220.     {
  2221.         p_sys->p_audios[i_index].index = i_index;
  2222.     }
  2223.     /* Probe audio inputs */
  2224.     if( p_sys->dev_cap.capabilities & V4L2_CAP_AUDIO )
  2225.     {
  2226.         while( p_sys->i_audio < 32 &&
  2227.                v4l2_ioctl( i_fd, VIDIOC_S_AUDIO, &p_sys->p_audios[p_sys->i_audio] ) >= 0 )
  2228.         {
  2229.             if( v4l2_ioctl( i_fd, VIDIOC_G_AUDIO, &p_sys->p_audios[ p_sys->i_audio] ) < 0 )
  2230.             {
  2231.                 msg_Err( p_obj, "cannot get audio input characteristics (%m)" );
  2232.                 goto open_failed;
  2233.             }
  2234.             msg_Dbg( p_obj, "audio input %i (%s) is %s %s %c",
  2235.                                 p_sys->i_audio,
  2236.                                 p_sys->p_audios[p_sys->i_audio].name,
  2237.                                 p_sys->p_audios[p_sys->i_audio].capability &
  2238.                                                     V4L2_AUDCAP_STEREO ?
  2239.                                         "Stereo" : "Mono",
  2240.                                 p_sys->p_audios[p_sys->i_audio].capability &
  2241.                                                     V4L2_AUDCAP_AVL ?
  2242.                                     "(Automatic Volume Level supported)" : "",
  2243.                                 p_sys->i_audio == p_sys->i_selected_audio_input ? '*' : ' ' );
  2244.             p_sys->i_audio++;
  2245.         }
  2246.     }
  2247.     /* List tuner caps */
  2248.     if( p_sys->dev_cap.capabilities & V4L2_CAP_TUNER )
  2249.     {
  2250.         struct v4l2_tuner tuner;
  2251.         memset( &tuner, 0, sizeof(tuner) );
  2252.         p_sys->i_tuner = 0;
  2253.         while( v4l2_ioctl( i_fd, VIDIOC_G_TUNER, &tuner ) >= 0 )
  2254.         {
  2255.             p_sys->i_tuner++;
  2256.             memset( &tuner, 0, sizeof(tuner) );
  2257.             tuner.index = p_sys->i_tuner;
  2258.         }
  2259.         free( p_sys->p_tuners );
  2260.         p_sys->p_tuners = calloc( 1, p_sys->i_tuner * sizeof( struct v4l2_tuner ) );
  2261.         if( !p_sys->p_tuners ) goto open_failed;
  2262.         for( i_index = 0; i_index < p_sys->i_tuner; i_index++ )
  2263.         {
  2264.             p_sys->p_tuners[i_index].index = i_index;
  2265.             if( v4l2_ioctl( i_fd, VIDIOC_G_TUNER, &p_sys->p_tuners[i_index] ) )
  2266.             {
  2267.                 msg_Err( p_obj, "cannot get tuner characteristics (%m)" );
  2268.                 goto open_failed;
  2269.             }
  2270.             msg_Dbg( p_obj, "tuner %i (%s) has type: %s, "
  2271.                               "frequency range: %.1f %s -> %.1f %s",
  2272.                                 i_index,
  2273.                                 p_sys->p_tuners[i_index].name,
  2274.                                 p_sys->p_tuners[i_index].type
  2275.                                         == V4L2_TUNER_RADIO ?
  2276.                                         "Radio" : "Analog TV",
  2277.                                 p_sys->p_tuners[i_index].rangelow * 62.5,
  2278.                                 p_sys->p_tuners[i_index].capability &
  2279.                                         V4L2_TUNER_CAP_LOW ?
  2280.                                         "Hz" : "kHz",
  2281.                                 p_sys->p_tuners[i_index].rangehigh * 62.5,
  2282.                                 p_sys->p_tuners[i_index].capability &
  2283.                                         V4L2_TUNER_CAP_LOW ?
  2284.                                         "Hz" : "kHz" );
  2285.             struct v4l2_frequency frequency;
  2286.             memset( &frequency, 0, sizeof( frequency ) );
  2287.             if( v4l2_ioctl( i_fd, VIDIOC_G_FREQUENCY, &frequency ) < 0 )
  2288.             {
  2289.                 msg_Err( p_obj, "cannot get tuner frequency (%m)" );
  2290.                 goto open_failed;
  2291.             }
  2292.             msg_Dbg( p_obj, "tuner %i (%s) frequency: %.1f %s",
  2293.                      i_index,
  2294.                      p_sys->p_tuners[i_index].name,
  2295.                      frequency.frequency * 62.5,
  2296.                      p_sys->p_tuners[i_index].capability &
  2297.                              V4L2_TUNER_CAP_LOW ?
  2298.                              "Hz" : "kHz" );
  2299.         }
  2300.     }
  2301.     /* Probe for available chromas */
  2302.     if( p_sys->dev_cap.capabilities & V4L2_CAP_VIDEO_CAPTURE )
  2303.     {
  2304.         struct v4l2_fmtdesc codec;
  2305.         i_index = 0;
  2306.         memset( &codec, 0, sizeof(codec) );
  2307.         codec.index = i_index;
  2308.         codec.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  2309.         while( v4l2_ioctl( i_fd, VIDIOC_ENUM_FMT, &codec ) >= 0 )
  2310.         {
  2311.             i_index++;
  2312.             codec.index = i_index;
  2313.         }
  2314.         p_sys->i_codec = i_index;
  2315.         free( p_sys->p_codecs );
  2316.         p_sys->p_codecs = calloc( 1, p_sys->i_codec * sizeof( struct v4l2_fmtdesc ) );
  2317.         for( i_index = 0; i_index < p_sys->i_codec; i_index++ )
  2318.         {
  2319.             p_sys->p_codecs[i_index].index = i_index;
  2320.             p_sys->p_codecs[i_index].type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  2321.             if( v4l2_ioctl( i_fd, VIDIOC_ENUM_FMT, &p_sys->p_codecs[i_index] ) < 0 )
  2322.             {
  2323.                 msg_Err( p_obj, "cannot get codec description (%m)" );
  2324.                 goto open_failed;
  2325.             }
  2326.             /* only print if vlc supports the format */
  2327.             char psz_fourcc_v4l2[5];
  2328.             memset( &psz_fourcc_v4l2, 0, sizeof( psz_fourcc_v4l2 ) );
  2329.             vlc_fourcc_to_char( p_sys->p_codecs[i_index].pixelformat,
  2330.                                 &psz_fourcc_v4l2 );
  2331.             bool b_codec_supported = false;
  2332.             for( int i = 0; v4l2chroma_to_fourcc[i].i_v4l2 != 0; i++ )
  2333.             {
  2334.                 if( v4l2chroma_to_fourcc[i].i_v4l2 == p_sys->p_codecs[i_index].pixelformat )
  2335.                 {
  2336.                     b_codec_supported = true;
  2337.                     char psz_fourcc[5];
  2338.                     memset( &psz_fourcc, 0, sizeof( psz_fourcc ) );
  2339.                     vlc_fourcc_to_char( v4l2chroma_to_fourcc[i].i_fourcc,
  2340.                                         &psz_fourcc );
  2341.                     msg_Dbg( p_obj, "device supports chroma %4s [%s, %s]",
  2342.                                 psz_fourcc,
  2343.                                 p_sys->p_codecs[i_index].description,
  2344.                                 psz_fourcc_v4l2 );
  2345. #ifdef VIDIOC_ENUM_FRAMESIZES
  2346.                     /* This is new in Linux 2.6.19 */
  2347.                     /* List valid frame sizes for this format */
  2348.                     struct v4l2_frmsizeenum frmsize;
  2349.                     memset( &frmsize, 0, sizeof(frmsize) );
  2350.                     frmsize.pixel_format = p_sys->p_codecs[i_index].pixelformat;
  2351.                     if( v4l2_ioctl( i_fd, VIDIOC_ENUM_FRAMESIZES, &frmsize ) < 0 )
  2352.                     {
  2353.                         /* Not all devices support this ioctl */
  2354.                         msg_Warn( p_obj, "Unable to query for frame sizes" );
  2355.                     }
  2356.                     else
  2357.                     {
  2358.                         switch( frmsize.type )
  2359.                         {
  2360.                             case V4L2_FRMSIZE_TYPE_DISCRETE:
  2361.                                 do
  2362.                                 {
  2363.                                     msg_Dbg( p_obj,
  2364.                 "    device supports size %dx%d",
  2365.                 frmsize.discrete.width, frmsize.discrete.height );
  2366.                                     frmsize.index++;
  2367.                                 } while( v4l2_ioctl( i_fd, VIDIOC_ENUM_FRAMESIZES, &frmsize ) >= 0 );
  2368.                                 break;
  2369.                             case V4L2_FRMSIZE_TYPE_STEPWISE:
  2370.                                 msg_Dbg( p_obj,
  2371.                 "    device supports sizes %dx%d to %dx%d using %dx%d increments",
  2372.                 frmsize.stepwise.min_width, frmsize.stepwise.min_height,
  2373.                 frmsize.stepwise.max_width, frmsize.stepwise.max_height,
  2374.                 frmsize.stepwise.step_width, frmsize.stepwise.step_height );
  2375.                                 break;
  2376.                             case V4L2_FRMSIZE_TYPE_CONTINUOUS:
  2377.                                 msg_Dbg( p_obj,
  2378.                 "    device supports all sizes %dx%d to %dx%d",
  2379.                 frmsize.stepwise.min_width, frmsize.stepwise.min_height,
  2380.                 frmsize.stepwise.max_width, frmsize.stepwise.max_height );
  2381.                                 break;
  2382.                         }
  2383.                     }
  2384. #endif
  2385.                 }
  2386.             }
  2387.             if( !b_codec_supported )
  2388.             {
  2389.                     msg_Dbg( p_obj,
  2390.                          "device codec %4s (%s) not supported",
  2391.                          psz_fourcc_v4l2,
  2392.                          p_sys->p_codecs[i_index].description );
  2393.             }
  2394.         }
  2395.     }
  2396.     if( i_fd >= 0 ) v4l2_close( i_fd );
  2397.     return true;
  2398. open_failed:
  2399.     if( i_fd >= 0 ) v4l2_close( i_fd );
  2400.     return false;
  2401. }
  2402. static void name2var( unsigned char *name )
  2403. {
  2404.     for( ; *name; name++ )
  2405.         *name = (*name == ' ') ? '_' : tolower( *name );
  2406. }
  2407. /*****************************************************************************
  2408.  * Print a user-class v4l2 control's details, create the relevant variable,
  2409.  * change the value if needed.
  2410.  *****************************************************************************/
  2411. static void ControlListPrint( vlc_object_t *p_obj, demux_sys_t *p_sys, int i_fd,
  2412.                               struct v4l2_queryctrl queryctrl,
  2413.                               bool b_reset, bool b_demux )
  2414. {
  2415.     struct v4l2_querymenu querymenu;
  2416.     unsigned int i_mid;
  2417.     int i;
  2418.     int i_val;
  2419.     char *psz_name;
  2420.     vlc_value_t val, val2;
  2421.     if( queryctrl.flags & V4L2_CTRL_FLAG_GRABBED )
  2422.         msg_Dbg( p_obj, "    control is busy" );
  2423.     if( queryctrl.flags & V4L2_CTRL_FLAG_READ_ONLY )
  2424.         msg_Dbg( p_obj, "    control is read-only" );
  2425.     for( i = 0; controls[i].psz_name != NULL; i++ )
  2426.         if( controls[i].i_cid == queryctrl.id ) break;
  2427.     if( controls[i].psz_name )
  2428.     {
  2429.         psz_name = strdup( controls[i].psz_name );
  2430.         char psz_cfg_name[40];
  2431.         sprintf( psz_cfg_name, CFG_PREFIX "%s", psz_name );
  2432.         i_val = var_CreateGetInteger( p_obj, psz_cfg_name );
  2433.         var_Destroy( p_obj, psz_cfg_name );
  2434.     }
  2435.     else
  2436.     {
  2437.         psz_name = strdup( (const char *)queryctrl.name );
  2438.         name2var( (unsigned char *)psz_name );
  2439.         i_val = -1;
  2440.     }
  2441.     switch( queryctrl.type )
  2442.     {
  2443.         case V4L2_CTRL_TYPE_INTEGER:
  2444.             msg_Dbg( p_obj, "    integer control" );
  2445.             msg_Dbg( p_obj,
  2446.                      "    valid values: %d to %d by steps of %d",
  2447.                      queryctrl.minimum, queryctrl.maximum,
  2448.                      queryctrl.step );
  2449.             var_Create( p_obj, psz_name,
  2450.                         VLC_VAR_INTEGER | VLC_VAR_HASMIN | VLC_VAR_HASMAX
  2451.                       | VLC_VAR_HASSTEP | VLC_VAR_ISCOMMAND );
  2452.             val.i_int = queryctrl.minimum;
  2453.             var_Change( p_obj, psz_name, VLC_VAR_SETMIN, &val, NULL );
  2454.             val.i_int = queryctrl.maximum;
  2455.             var_Change( p_obj, psz_name, VLC_VAR_SETMAX, &val, NULL );
  2456.             val.i_int = queryctrl.step;
  2457.             var_Change( p_obj, psz_name, VLC_VAR_SETSTEP, &val, NULL );
  2458.             break;
  2459.         case V4L2_CTRL_TYPE_BOOLEAN:
  2460.             msg_Dbg( p_obj, "    boolean control" );
  2461.             var_Create( p_obj, psz_name,
  2462.                         VLC_VAR_BOOL | VLC_VAR_ISCOMMAND );
  2463.             break;
  2464.         case V4L2_CTRL_TYPE_MENU:
  2465.             msg_Dbg( p_obj, "    menu control" );
  2466.             var_Create( p_obj, psz_name,
  2467.                         VLC_VAR_INTEGER | VLC_VAR_HASCHOICE
  2468.                       | VLC_VAR_ISCOMMAND );
  2469.             memset( &querymenu, 0, sizeof( querymenu ) );
  2470.             for( i_mid = queryctrl.minimum;
  2471.                  i_mid <= (unsigned)queryctrl.maximum;
  2472.                  i_mid++ )
  2473.             {
  2474.                 querymenu.index = i_mid;
  2475.                 querymenu.id = queryctrl.id;
  2476.                 if( v4l2_ioctl( i_fd, VIDIOC_QUERYMENU, &querymenu ) >= 0 )
  2477.                 {
  2478.                     msg_Dbg( p_obj, "        %d: %s",
  2479.                              querymenu.index, querymenu.name );
  2480.                     val.i_int = querymenu.index;
  2481.                     val2.psz_string = (char *)querymenu.name;
  2482.                     var_Change( p_obj, psz_name,
  2483.                                 VLC_VAR_ADDCHOICE, &val, &val2 );
  2484.                 }
  2485.             }
  2486.             break;
  2487.         case V4L2_CTRL_TYPE_BUTTON:
  2488.             msg_Dbg( p_obj, "    button control" );
  2489.             var_Create( p_obj, psz_name,
  2490.                         VLC_VAR_VOID | VLC_VAR_ISCOMMAND );
  2491.             break;
  2492.         case V4L2_CTRL_TYPE_CTRL_CLASS:
  2493.             msg_Dbg( p_obj, "    control class" );
  2494.             var_Create( p_obj, psz_name, VLC_VAR_VOID );
  2495.             break;
  2496.         default:
  2497.             msg_Dbg( p_obj, "    unknown control type (FIXME)" );
  2498.             /* FIXME */
  2499.             break;
  2500.     }
  2501.     switch( queryctrl.type )
  2502.     {
  2503.         case V4L2_CTRL_TYPE_INTEGER:
  2504.         case V4L2_CTRL_TYPE_BOOLEAN:
  2505.         case V4L2_CTRL_TYPE_MENU:
  2506.             {
  2507.                 struct v4l2_control control;
  2508.                 msg_Dbg( p_obj, "    default value: %d",
  2509.                          queryctrl.default_value );
  2510.                 memset( &control, 0, sizeof( control ) );
  2511.                 control.id = queryctrl.id;
  2512.                 if( v4l2_ioctl( i_fd, VIDIOC_G_CTRL, &control ) >= 0 )
  2513.                 {
  2514.                     msg_Dbg( p_obj, "    current value: %d", control.value );
  2515.                 }
  2516.                 if( i_val == -1 )
  2517.                 {
  2518.                     i_val = control.value;
  2519.                     if( b_reset && queryctrl.default_value != control.value )
  2520.                     {
  2521.                         msg_Dbg( p_obj, "    reset value to default" );
  2522.                         Control( p_obj, p_sys, i_fd, psz_name,
  2523.                                  queryctrl.id, queryctrl.default_value );
  2524.                     }
  2525.                 }
  2526.                 else
  2527.                 {
  2528.                     Control( p_obj, p_sys, i_fd, psz_name,
  2529.                              queryctrl.id, i_val );
  2530.                 }
  2531.             }
  2532.             break;
  2533.         default:
  2534.             break;
  2535.     }
  2536.     val.psz_string = (char *)queryctrl.name;
  2537.     var_Change( p_obj, psz_name, VLC_VAR_SETTEXT, &val, NULL );
  2538.     val.i_int = queryctrl.id;
  2539.     val2.psz_string = (char *)psz_name;
  2540.     var_Change( p_obj, "allcontrols", VLC_VAR_ADDCHOICE, &val, &val2 );
  2541.     /* bad things happen changing MPEG mid-stream
  2542.      * so don't add to Ext Settings GUI */
  2543.     if( V4L2_CTRL_ID2CLASS( queryctrl.id ) != V4L2_CTRL_CLASS_MPEG )
  2544.         var_Change( p_obj, "controls", VLC_VAR_ADDCHOICE, &val, &val2 );
  2545.     switch( var_Type( p_obj, psz_name ) & VLC_VAR_TYPE )
  2546.     {
  2547.         case VLC_VAR_BOOL:
  2548.             var_SetBool( p_obj, psz_name, i_val );
  2549.             break;
  2550.         case VLC_VAR_INTEGER:
  2551.             var_SetInteger( p_obj, psz_name, i_val );
  2552.             break;
  2553.         case VLC_VAR_VOID:
  2554.             break;
  2555.         default:
  2556.             msg_Warn( p_obj, "FIXME: %s %s %d", __FILE__, __func__,
  2557.                       __LINE__ );
  2558.             break;
  2559.     }
  2560.     if( b_demux )
  2561.         var_AddCallback( p_obj, psz_name,
  2562.                         DemuxControlCallback, (void*)(intptr_t)queryctrl.id );
  2563.     else
  2564.         var_AddCallback( p_obj, psz_name,
  2565.                         AccessControlCallback, (void*)(intptr_t)queryctrl.id );
  2566.     free( psz_name );
  2567. }
  2568. /*****************************************************************************
  2569.  * List all user-class v4l2 controls, set them to the user specified
  2570.  * value and create the relevant variables to enable runtime changes
  2571.  *****************************************************************************/
  2572. static int ControlList( vlc_object_t *p_obj, demux_sys_t *p_sys, int i_fd,
  2573.                         bool b_reset, bool b_demux )
  2574. {
  2575.     struct v4l2_queryctrl queryctrl;
  2576.     int i_cid;
  2577.     memset( &queryctrl, 0, sizeof( queryctrl ) );
  2578.     /* A list of available controls (aka the variable name) will be
  2579.      * stored as choices in the "allcontrols" variable. We'll thus be able
  2580.      * to use those to create an appropriate interface
  2581.      * A list of available controls that can be changed mid-stream will
  2582.      * be stored in the "controls" variable */
  2583.     var_Create( p_obj, "controls", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE );
  2584.     var_Create( p_obj, "allcontrols", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE );
  2585.     var_Create( p_obj, "controls-update", VLC_VAR_VOID | VLC_VAR_ISCOMMAND );
  2586.     /* Add a control to reset all controls to their default values */
  2587.     vlc_value_t val, val2;
  2588.     var_Create( p_obj, "controls-reset", VLC_VAR_VOID | VLC_VAR_ISCOMMAND );
  2589.     val.psz_string = _( "Reset controls to default" );
  2590.     var_Change( p_obj, "controls-reset", VLC_VAR_SETTEXT, &val, NULL );
  2591.     val.i_int = -1;
  2592.     val2.psz_string = (char *)"controls-reset";
  2593.     var_Change( p_obj, "controls", VLC_VAR_ADDCHOICE, &val, &val2 );
  2594.     if (b_demux)
  2595.         var_AddCallback( p_obj, "controls-reset", DemuxControlResetCallback, NULL );
  2596.     else
  2597.         var_AddCallback( p_obj, "controls-reset", AccessControlResetCallback, NULL );
  2598.     queryctrl.id = V4L2_CTRL_FLAG_NEXT_CTRL;
  2599.     if( v4l2_ioctl( i_fd, VIDIOC_QUERYCTRL, &queryctrl ) >= 0 )
  2600.     {
  2601.         msg_Dbg( p_obj, "Extended control API supported by v4l2 driver" );
  2602.         /* List extended controls */
  2603.         queryctrl.id = V4L2_CTRL_FLAG_NEXT_CTRL;
  2604.         while( v4l2_ioctl( i_fd, VIDIOC_QUERYCTRL, &queryctrl ) >= 0 )
  2605.         {
  2606.             if( queryctrl.type == V4L2_CTRL_TYPE_CTRL_CLASS )
  2607.             {
  2608.                 msg_Dbg( p_obj, "%s", queryctrl.name );
  2609.                 queryctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
  2610.                 continue;
  2611.             }
  2612.             switch( V4L2_CTRL_ID2CLASS( queryctrl.id ) )
  2613.             {
  2614.                 case V4L2_CTRL_CLASS_USER:
  2615.                     msg_Dbg( p_obj, "Available control: %s (%x)",
  2616.                              queryctrl.name, queryctrl.id );
  2617.                     break;
  2618.                 case V4L2_CTRL_CLASS_MPEG:
  2619.                     name2var( queryctrl.name );
  2620.                     msg_Dbg( p_obj, "Available MPEG control: %s (%x)",
  2621.                              queryctrl.name, queryctrl.id );
  2622.                     break;
  2623.                 default:
  2624.                     msg_Dbg( p_obj, "Available private control: %s (%x)",
  2625.                              queryctrl.name, queryctrl.id );
  2626.                     break;
  2627.             }
  2628.             ControlListPrint( p_obj, p_sys, i_fd, queryctrl, b_reset, b_demux );
  2629.             queryctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
  2630.         }
  2631.     }
  2632.     else
  2633.     {
  2634.         msg_Dbg( p_obj, "Extended control API not supported by v4l2 driver" );
  2635.         /* List public controls */
  2636.         for( i_cid = V4L2_CID_BASE;
  2637.              i_cid < V4L2_CID_LASTP1;
  2638.              i_cid ++ )
  2639.         {
  2640.             queryctrl.id = i_cid;
  2641.             if( v4l2_ioctl( i_fd, VIDIOC_QUERYCTRL, &queryctrl ) >= 0 )
  2642.             {
  2643.                 if( queryctrl.flags & V4L2_CTRL_FLAG_DISABLED )
  2644.                     continue;
  2645.                 msg_Dbg( p_obj, "Available control: %s (%x)",
  2646.                          queryctrl.name, queryctrl.id );
  2647.                 ControlListPrint( p_obj, p_sys, i_fd, queryctrl,
  2648.                                   b_reset, b_demux );
  2649.             }
  2650.         }
  2651.         /* List private controls */
  2652.         for( i_cid = V4L2_CID_PRIVATE_BASE;
  2653.              ;
  2654.              i_cid ++ )
  2655.         {
  2656.             queryctrl.id = i_cid;
  2657.             if( v4l2_ioctl( i_fd, VIDIOC_QUERYCTRL, &queryctrl ) >= 0 )
  2658.             {
  2659.                 if( queryctrl.flags & V4L2_CTRL_FLAG_DISABLED )
  2660.                     continue;
  2661.                 msg_Dbg( p_obj, "Available private control: %s (%x)",
  2662.                          queryctrl.name, queryctrl.id );
  2663.                 ControlListPrint( p_obj, p_sys, i_fd, queryctrl,
  2664.                                   b_reset, b_demux );
  2665.             }
  2666.             else
  2667.                 break;
  2668.         }
  2669.     }
  2670.     return VLC_SUCCESS;
  2671. }
  2672. static void SetAvailControlsByString( vlc_object_t *p_obj, demux_sys_t *p_sys,
  2673.                                       int i_fd )
  2674. {
  2675.     char *psz_parser = p_sys->psz_set_ctrls;
  2676.     vlc_value_t val, text, name;
  2677.     if( psz_parser == NULL )
  2678.         return;
  2679.     if( *psz_parser == '{' )
  2680.         psz_parser++;
  2681.     int i_ret = var_Change( p_obj, "allcontrols", VLC_VAR_GETCHOICES,
  2682.                             &val, &text );
  2683.     if( i_ret < 0 )
  2684.     {
  2685.         msg_Err( p_obj, "Oops, can't find 'allcontrols' variable." );
  2686.         return;
  2687.     }
  2688.     while( *psz_parser && *psz_parser != '}' )
  2689.     {
  2690.         char *psz_delim, *psz_assign;
  2691.         while( *psz_parser == ',' || *psz_parser == ' ' )
  2692.             psz_parser++;
  2693.         psz_delim = strchr( psz_parser, ',' );
  2694.         if( psz_delim == NULL )
  2695.             psz_delim = strchr( psz_parser, '}' );
  2696.         if( psz_delim == NULL )
  2697.             psz_delim = psz_parser + strlen( psz_parser );
  2698.         psz_assign = memchr( psz_parser, '=', psz_delim - psz_parser );
  2699.         if( psz_assign == NULL )
  2700.         {
  2701.             char *psz_name = strndup( psz_parser, psz_delim - psz_parser );
  2702.             msg_Err( p_obj, "%s missing '='", psz_name );
  2703.             free( psz_name );
  2704.             psz_parser = psz_delim + 1;
  2705.             continue;
  2706.         }
  2707.         for( int i = 0;
  2708.              i < val.p_list->i_count ;//&& psz_parser < psz_assign;
  2709.              i++ )
  2710.         {
  2711.             const char *psz_var = text.p_list->p_values[i].psz_string;
  2712.             int i_cid = val.p_list->p_values[i].i_int;
  2713.             var_Change( p_obj, psz_var, VLC_VAR_GETTEXT, &name, NULL );
  2714.             const char *psz_name = name.psz_string;
  2715.             int i_availstrlen = strlen( psz_name );
  2716.             int i_parsestrlen = psz_assign - psz_parser;
  2717.             int i_maxstrlen = __MAX( i_availstrlen, i_parsestrlen);
  2718.             if( !strncasecmp( psz_name, psz_parser, i_maxstrlen ) )
  2719.             {
  2720.                 Control( p_obj, p_sys, i_fd, psz_name, i_cid,
  2721.                          strtol( ++psz_assign, &psz_parser, 0) );
  2722.             }
  2723.             free( name.psz_string );
  2724.         }
  2725.         if( psz_parser < psz_assign )
  2726.         {
  2727.             char *psz_name = strndup( psz_parser, psz_assign - psz_parser );
  2728.             msg_Err( p_obj, "Control %s not available", psz_name );
  2729.             free( psz_name );
  2730.             psz_parser = ( *psz_delim ) ? ( psz_delim + 1 ) : psz_delim;
  2731.         }
  2732.     }
  2733.     var_Change( p_obj, "allcontrols", VLC_VAR_FREELIST, &val, &text );
  2734. }
  2735. /*****************************************************************************
  2736.  * Reset all user-class v4l2 controls to their default value
  2737.  *****************************************************************************/
  2738. static int ControlReset( vlc_object_t *p_obj, demux_sys_t *p_sys, int i_fd )
  2739. {
  2740.     struct v4l2_queryctrl queryctrl;
  2741.     int i_cid;
  2742.     memset( &queryctrl, 0, sizeof( queryctrl ) );
  2743.     queryctrl.id = V4L2_CTRL_FLAG_NEXT_CTRL;
  2744.     if( v4l2_ioctl( i_fd, VIDIOC_QUERYCTRL, &queryctrl ) >= 0 )
  2745.     {
  2746.         /* Extended control API supported */
  2747.         queryctrl.id = V4L2_CTRL_FLAG_NEXT_CTRL;
  2748.         while( v4l2_ioctl( i_fd, VIDIOC_QUERYCTRL, &queryctrl ) >= 0 )
  2749.         {
  2750.             if( queryctrl.type == V4L2_CTRL_TYPE_CTRL_CLASS
  2751.              || V4L2_CTRL_ID2CLASS( queryctrl.id ) == V4L2_CTRL_CLASS_MPEG )
  2752.             {
  2753.                 queryctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
  2754.                 continue;
  2755.             }
  2756.             struct v4l2_control control;
  2757.             memset( &control, 0, sizeof( control ) );
  2758.             control.id = queryctrl.id;
  2759.             if( v4l2_ioctl( i_fd, VIDIOC_G_CTRL, &control ) >= 0
  2760.              && queryctrl.default_value != control.value )
  2761.             {
  2762.                 int i;
  2763.                 for( i = 0; controls[i].psz_name != NULL; i++ )
  2764.                     if( controls[i].i_cid == queryctrl.id ) break;
  2765.                 name2var( queryctrl.name );
  2766.                 Control( p_obj, p_sys, i_fd,
  2767.                          controls[i].psz_name ? controls[i].psz_name
  2768.                           : (const char *)queryctrl.name,
  2769.                          queryctrl.id, queryctrl.default_value );
  2770.             }
  2771.             queryctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
  2772.         }
  2773.     }
  2774.     else
  2775.     {
  2776.         /* public controls */
  2777.         for( i_cid = V4L2_CID_BASE;
  2778.              i_cid < V4L2_CID_LASTP1;
  2779.              i_cid ++ )
  2780.         {
  2781.             queryctrl.id = i_cid;
  2782.             if( v4l2_ioctl( i_fd, VIDIOC_QUERYCTRL, &queryctrl ) >= 0 )
  2783.             {
  2784.                 struct v4l2_control control;
  2785.                 if( queryctrl.flags & V4L2_CTRL_FLAG_DISABLED )
  2786.                     continue;
  2787.                 memset( &control, 0, sizeof( control ) );
  2788.                 control.id = queryctrl.id;
  2789.                 if( v4l2_ioctl( i_fd, VIDIOC_G_CTRL, &control ) >= 0
  2790.                  && queryctrl.default_value != control.value )
  2791.                 {
  2792.                     int i;
  2793.                     for( i = 0; controls[i].psz_name != NULL; i++ )
  2794.                         if( controls[i].i_cid == queryctrl.id ) break;
  2795.                     name2var( queryctrl.name );
  2796.                     Control( p_obj, p_sys, i_fd,
  2797.                              controls[i].psz_name ? controls[i].psz_name
  2798.                               : (const char *)queryctrl.name,
  2799.                              queryctrl.id, queryctrl.default_value );
  2800.                 }
  2801.             }
  2802.         }
  2803.         /* private controls */
  2804.         for( i_cid = V4L2_CID_PRIVATE_BASE;
  2805.              ;
  2806.              i_cid ++ )
  2807.         {
  2808.             queryctrl.id = i_cid;
  2809.             if( v4l2_ioctl( i_fd, VIDIOC_QUERYCTRL, &queryctrl ) >= 0 )
  2810.             {
  2811.                 struct v4l2_control control;
  2812.                 if( queryctrl.flags & V4L2_CTRL_FLAG_DISABLED )
  2813.                     continue;
  2814.                 memset( &control, 0, sizeof( control ) );
  2815.                 control.id = queryctrl.id;
  2816.                 if( v4l2_ioctl( i_fd, VIDIOC_G_CTRL, &control ) >= 0
  2817.                  && queryctrl.default_value != control.value )
  2818.                 {
  2819.                     name2var( queryctrl.name );
  2820.                     Control( p_obj, p_sys, i_fd, (const char *)queryctrl.name,
  2821.                              queryctrl.id, queryctrl.default_value );
  2822.                 }
  2823.             }
  2824.             else
  2825.                 break;
  2826.         }
  2827.     }
  2828.     return VLC_SUCCESS;
  2829. }
  2830. /*****************************************************************************
  2831.  * Issue user-class v4l2 controls
  2832.  *****************************************************************************/
  2833. static int Control( vlc_object_t *p_obj, demux_sys_t *p_sys, int i_fd,
  2834.                     const char *psz_name, int i_cid, int i_value )
  2835. {
  2836.     (void)p_sys;
  2837.     struct v4l2_queryctrl queryctrl;
  2838.     struct v4l2_control control;
  2839.     struct v4l2_ext_control ext_control;
  2840.     struct v4l2_ext_controls ext_controls;
  2841.     if( i_value == -1 )
  2842.         return VLC_SUCCESS;
  2843.     memset( &queryctrl, 0, sizeof( queryctrl ) );
  2844.     queryctrl.id = i_cid;
  2845.     if( v4l2_ioctl( i_fd, VIDIOC_QUERYCTRL, &queryctrl ) < 0
  2846.         || queryctrl.flags & V4L2_CTRL_FLAG_DISABLED )
  2847.     {
  2848.         msg_Dbg( p_obj, "%s (%x) control is not supported.", psz_name, i_cid );
  2849.         return VLC_EGENERIC;
  2850.     }
  2851.     memset( &control, 0, sizeof( control ) );
  2852.     memset( &ext_control, 0, sizeof( ext_control ) );
  2853.     memset( &ext_controls, 0, sizeof( ext_controls ) );
  2854.     control.id = i_cid;
  2855.     ext_control.id = i_cid;
  2856.     ext_controls.ctrl_class = V4L2_CTRL_ID2CLASS( i_cid );
  2857.     ext_controls.count = 1;
  2858.     ext_controls.controls = &ext_control;
  2859.     int i_ret = -1;
  2860.     if( i_value >= queryctrl.minimum && i_value <= queryctrl.maximum )
  2861.     {
  2862.         ext_control.value = i_value;
  2863.         if( v4l2_ioctl( i_fd, VIDIOC_S_EXT_CTRLS, &ext_controls ) < 0 )
  2864.         {
  2865.             control.value = i_value;
  2866.             if( v4l2_ioctl( i_fd, VIDIOC_S_CTRL, &control ) < 0 )
  2867.             {
  2868.                 msg_Err( p_obj, "unable to set %s (%x) to %d (%m)",
  2869.                          psz_name, i_cid, i_value );
  2870.                 return VLC_EGENERIC;
  2871.             }
  2872.             i_ret = v4l2_ioctl( i_fd, VIDIOC_G_CTRL, &control );
  2873.         }
  2874.         else
  2875.         {
  2876.             i_ret = v4l2_ioctl( i_fd, VIDIOC_G_EXT_CTRLS, &ext_controls );
  2877.             control.value = ext_control.value;
  2878.         }
  2879.     }
  2880.     if( i_ret >= 0 )
  2881.     {
  2882.         vlc_value_t val;
  2883.         msg_Dbg( p_obj, "video %s: %d", psz_name, control.value );
  2884.         switch( var_Type( p_obj, psz_name ) & VLC_VAR_TYPE )
  2885.         {
  2886.             case VLC_VAR_BOOL:
  2887.                 val.b_bool = control.value;
  2888.                 var_Change( p_obj, psz_name, VLC_VAR_SETVALUE, &val, NULL );
  2889.                 var_SetVoid( p_obj, "controls-update" );
  2890.                 break;
  2891.             case VLC_VAR_INTEGER:
  2892.                 val.i_int = control.value;
  2893.                 var_Change( p_obj, psz_name, VLC_VAR_SETVALUE, &val, NULL );
  2894.                 var_SetVoid( p_obj, "controls-update" );
  2895.                 break;
  2896.         }
  2897.     }
  2898.     return VLC_SUCCESS;
  2899. }
  2900. /*****************************************************************************
  2901.  * On the fly change settings callback
  2902.  *****************************************************************************/
  2903. static int DemuxControlCallback( vlc_object_t *p_this,
  2904.     const char *psz_var, vlc_value_t oldval, vlc_value_t newval,
  2905.     void *p_data )
  2906. {
  2907.     (void)oldval;
  2908.     demux_t *p_demux = (demux_t*)p_this;
  2909.     demux_sys_t *p_sys = p_demux->p_sys;
  2910.     int i_cid = (long int)p_data;
  2911.     int i_fd = p_sys->i_fd;
  2912.     if( i_fd < 0 )
  2913.         return VLC_EGENERIC;
  2914.     Control( p_this, p_sys, i_fd, psz_var, i_cid, newval.i_int );
  2915.     return VLC_EGENERIC;
  2916. }
  2917. static int DemuxControlResetCallback( vlc_object_t *p_this,
  2918.     const char *psz_var, vlc_value_t oldval, vlc_value_t newval, void *p_data )
  2919. {
  2920.     (void)psz_var;    (void)oldval;    (void)newval;    (void)p_data;
  2921.     demux_t *p_demux = (demux_t*)p_this;
  2922.     demux_sys_t *p_sys = p_demux->p_sys;
  2923.     int i_fd = p_sys->i_fd;
  2924.     if( i_fd < 0 )
  2925.         return VLC_EGENERIC;
  2926.     ControlReset( p_this, p_sys, i_fd );
  2927.     return VLC_EGENERIC;
  2928. }
  2929. static int AccessControlCallback( vlc_object_t *p_this,
  2930.     const char *psz_var, vlc_value_t oldval, vlc_value_t newval,
  2931.     void *p_data )
  2932. {
  2933.     (void)oldval;
  2934.     access_t *p_access = (access_t *)p_this;
  2935.     demux_sys_t *p_sys = (demux_sys_t *) p_access->p_sys;
  2936.     int i_cid = (long int)p_data;
  2937.     int i_fd = p_sys->i_fd;
  2938.     if( i_fd < 0 )
  2939.         return VLC_EGENERIC;
  2940.     Control( p_this, p_sys, i_fd, psz_var, i_cid, newval.i_int );
  2941.     return VLC_EGENERIC;
  2942. }
  2943. static int AccessControlResetCallback( vlc_object_t *p_this,
  2944.     const char *psz_var, vlc_value_t oldval, vlc_value_t newval, void *p_data )
  2945. {
  2946.     (void)psz_var;     (void)oldval;     (void)newval;     (void)p_data;
  2947.     access_t *p_access = (access_t *)p_this;
  2948.     demux_sys_t *p_sys = (demux_sys_t *) p_access->p_sys;
  2949.     int i_fd = p_sys->i_fd;
  2950.     if( i_fd < 0 )
  2951.         return VLC_EGENERIC;
  2952.     ControlReset( p_this, p_sys, i_fd );
  2953.     return VLC_EGENERIC;
  2954. }