X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Faccess%2Fv4l2.c;h=01a7a01eb373a2bfad5c155fa9539ce38fa70afa;hb=745bd15ffe52fff777d201248b7cbe6b7e92ceca;hp=87c6f90334fdd141f016c7b19211719fbb0c848e;hpb=3fb0af1b2a0bd264a8989f8c7e0a58d74690f7b4;p=vlc diff --git a/modules/access/v4l2.c b/modules/access/v4l2.c index 87c6f90334..01a7a01eb3 100644 --- a/modules/access/v4l2.c +++ b/modules/access/v4l2.c @@ -1,11 +1,13 @@ /***************************************************************************** * v4l2.c : Video4Linux2 input module for vlc ***************************************************************************** - * Copyright (C) 2002-2007 the VideoLAN team + * Copyright (C) 2002-2009 the VideoLAN team * $Id$ * - * Author: Benjamin Pracht - * Richard Hosking + * Authors: Benjamin Pracht + * Richard Hosking + * Antoine Cellerier + * Dennis Lou * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,116 +27,185 @@ /* * Sections based on the reference V4L2 capture example at * http://v4l2spec.bytesex.org/spec/capture-example.html - * - * ALSA support based on parts of - * http://www.equalarea.com/paul/alsa-audio.html - * and hints taken from alsa-utils (aplay/arecord) - * http://www.alsa-project.org - */ - -/* - * TODO: No mjpeg support yet. - * TODO: Tuner partial implementation. - * TODO: Alsa input support - experimental */ /***************************************************************************** * Preamble *****************************************************************************/ -#include +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include #include #include #include -#include +#include +#include #include -#include #include #include #include -#include +#include -#ifdef HAVE_ALSA -# define ALSA_PCM_NEW_HW_PARAMS_API -# define ALSA_PCM_NEW_SW_PARAMS_API -# include +#ifdef HAVE_LIBV4L2 +# include #endif /***************************************************************************** * Module descriptior *****************************************************************************/ -static int Open ( vlc_object_t * ); -static void Close( vlc_object_t * ); +static int DemuxOpen ( vlc_object_t * ); +static void DemuxClose( vlc_object_t * ); +static int AccessOpen ( vlc_object_t * ); +static void AccessClose( vlc_object_t * ); -#define DEV_TEXT N_("Device name") -#define DEV_LONGTEXT N_( \ - "Name of the device to use. " \ - "If you don't specify anything, /dev/video0 will be used.") #define STANDARD_TEXT N_( "Standard" ) #define STANDARD_LONGTEXT N_( \ "Video standard (Default, SECAM, PAL, or NTSC)." ) #define CHROMA_TEXT N_("Video input chroma format") #define CHROMA_LONGTEXT N_( \ "Force the Video4Linux2 video device to use a specific chroma format " \ - "(eg. I420, RV24, etc.)") + "(eg. I420 or I422 for raw images, MJPG for M-JPEG compressed input) " \ + "(Complete list: GREY, I240, RV16, RV15, RV24, RV32, YUY2, YUYV, UYVY, " \ + "I41N, I422, I420, I411, I410, MJPG)") #define INPUT_TEXT N_( "Input" ) #define INPUT_LONGTEXT N_( \ - "Input of the card to use (Usually, 0 = tuner, " \ - "1 = composite, 2 = svideo)." ) + "Input of the card to use (see debug)." ) +#define AUDIO_INPUT_TEXT N_( "Audio input" ) +#define AUDIO_INPUT_LONGTEXT N_( \ + "Audio input of the card to use (see debug)." ) #define IOMETHOD_TEXT N_( "IO Method" ) #define IOMETHOD_LONGTEXT N_( \ "IO Method (READ, MMAP, USERPTR)." ) #define WIDTH_TEXT N_( "Width" ) #define WIDTH_LONGTEXT N_( \ - "Force width (-1 for autodetect)." ) + "Force width (-1 for autodetect, 0 for driver default)." ) #define HEIGHT_TEXT N_( "Height" ) #define HEIGHT_LONGTEXT N_( \ - "Force height (-1 for autodetect)." ) + "Force height (-1 for autodetect, 0 for driver default)." ) #define FPS_TEXT N_( "Framerate" ) #define FPS_LONGTEXT N_( "Framerate to capture, if applicable " \ - "(-1 for autodetect)." ) + "(0 for autodetect)." ) + +#ifdef HAVE_LIBV4L2 +#define LIBV4L2_TEXT N_( "Use libv4l2" ) +#define LIBV4L2_LONGTEXT N_( \ + "Force usage of the libv4l2 wrapper." ) +#endif -#define VIDEOCTRL_RESET_TEXT N_( "Reset video controls" ) -#define VIDEOCTRL_RESET_LONGTEXT N_( \ - "Reset video controls to defaults provided by the v4l2 driver." ) +#define CTRL_RESET_TEXT N_( "Reset v4l2 controls" ) +#define CTRL_RESET_LONGTEXT N_( \ + "Reset controls to defaults provided by the v4l2 driver." ) #define BRIGHTNESS_TEXT N_( "Brightness" ) #define BRIGHTNESS_LONGTEXT N_( \ - "Brightness of the video input." ) + "Brightness of the video input (if supported by the v4l2 driver)." ) #define CONTRAST_TEXT N_( "Contrast" ) #define CONTRAST_LONGTEXT N_( \ - "Contrast of the video input." ) + "Contrast of the video input (if supported by the v4l2 driver)." ) #define SATURATION_TEXT N_( "Saturation" ) #define SATURATION_LONGTEXT N_( \ - "Saturation of the video input." ) + "Saturation of the video input (if supported by the v4l2 driver)." ) #define HUE_TEXT N_( "Hue" ) #define HUE_LONGTEXT N_( \ - "Hue of the video input." ) + "Hue of the video input (if supported by the v4l2 driver)." ) +#define BLACKLEVEL_TEXT N_( "Black level" ) +#define BLACKLEVEL_LONGTEXT N_( \ + "Black level of the video input (if supported by the v4l2 driver)." ) +#define AUTOWHITEBALANCE_TEXT N_( "Auto white balance" ) +#define AUTOWHITEBALANCE_LONGTEXT N_( \ + "Automatically set the white balance of the video input " \ + "(if supported by the v4l2 driver)." ) +#define DOWHITEBALANCE_TEXT N_( "Do white balance" ) +#define DOWHITEBALANCE_LONGTEXT N_( \ + "Trigger a white balancing action, useless if auto white balance is " \ + "activated (if supported by the v4l2 driver)." ) +#define REDBALANCE_TEXT N_( "Red balance" ) +#define REDBALANCE_LONGTEXT N_( \ + "Red balance of the video input (if supported by the v4l2 driver)." ) +#define BLUEBALANCE_TEXT N_( "Blue balance" ) +#define BLUEBALANCE_LONGTEXT N_( \ + "Blue balance of the video input (if supported by the v4l2 driver)." ) #define GAMMA_TEXT N_( "Gamma" ) #define GAMMA_LONGTEXT N_( \ - "Gamma of the video input." ) - -#define ADEV_TEXT N_("Audio device name") -#define ADEV_LONGTEXT N_( \ - "Name of the audio device to use. " \ - "If you don't specify anything, /dev/dsp will be used.") -#define ALSA_TEXT N_( "Use Alsa" ) -#define ALSA_LONGTEXT N_( \ - "Use ALSA instead of OSS for audio" ) -#define STEREO_TEXT N_( "Stereo" ) -#define STEREO_LONGTEXT N_( \ - "Capture the audio stream in stereo." ) -#define SAMPLERATE_TEXT N_( "Samplerate" ) -#define SAMPLERATE_LONGTEXT N_( \ - "Samplerate of the captured audio stream, in Hz (eg: 11025, 22050, 44100, 48000)" ) + "Gamma of the video input (if supported by the v4l2 driver)." ) +#define EXPOSURE_TEXT N_( "Exposure" ) +#define EXPOSURE_LONGTEXT N_( \ + "Exposure of the video input (if supported by the v4L2 driver)." ) +#define AUTOGAIN_TEXT N_( "Auto gain" ) +#define AUTOGAIN_LONGTEXT N_( \ + "Automatically set the video input's gain (if supported by the " \ + "v4l2 driver)." ) +#define GAIN_TEXT N_( "Gain" ) +#define GAIN_LONGTEXT N_( \ + "Video input's gain (if supported by the v4l2 driver)." ) +#define HFLIP_TEXT N_( "Horizontal flip" ) +#define HFLIP_LONGTEXT N_( \ + "Flip the video horizontally (if supported by the v4l2 driver)." ) +#define VFLIP_TEXT N_( "Vertical flip" ) +#define VFLIP_LONGTEXT N_( \ + "Flip the video vertically (if supported by the v4l2 driver)." ) +#define HCENTER_TEXT N_( "Horizontal centering" ) +#define HCENTER_LONGTEXT N_( \ + "Set the camera's horizontal centering (if supported by the v4l2 driver)." ) +#define VCENTER_TEXT N_( "Vertical centering" ) +#define VCENTER_LONGTEXT N_( \ + "Set the camera's vertical centering (if supported by the v4l2 driver)." ) + +#define AUDIO_VOLUME_TEXT N_( "Volume" ) +#define AUDIO_VOLUME_LONGTEXT N_( \ + "Volume of the audio input (if supported by the v4l2 driver)." ) +#define AUDIO_BALANCE_TEXT N_( "Balance" ) +#define AUDIO_BALANCE_LONGTEXT N_( \ + "Balance of the audio input (if supported by the v4l2 driver)." ) +#define AUDIO_MUTE_TEXT N_( "Mute" ) +#define AUDIO_MUTE_LONGTEXT N_( \ + "Mute audio input (if supported by the v4l2 driver)." ) +#define AUDIO_BASS_TEXT N_( "Bass" ) +#define AUDIO_BASS_LONGTEXT N_( \ + "Bass level of the audio input (if supported by the v4l2 driver)." ) +#define AUDIO_TREBLE_TEXT N_( "Treble" ) +#define AUDIO_TREBLE_LONGTEXT N_( \ + "Treble level of the audio input (if supported by the v4l2 driver)." ) +#define AUDIO_LOUDNESS_TEXT N_( "Loudness" ) +#define AUDIO_LOUDNESS_LONGTEXT N_( \ + "Loudness of the audio input (if supported by the v4l2 driver)." ) #define CACHING_TEXT N_("Caching value in ms") #define CACHING_LONGTEXT N_( \ "Caching value for V4L2 captures. This " \ "value should be set in milliseconds." ) +#define S_CTRLS_TEXT N_("v4l2 driver controls") +#define S_CTRLS_LONGTEXT N_( \ + "Set the v4l2 driver controls to the values specified using a comma " \ + "separated list optionally encapsulated by curly braces " \ + "(e.g.: {video_bitrate=6000000,audio_crc=0,stream_type=3} ). " \ + "To list available controls, increase verbosity (-vvv) " \ + "or use the v4l2-ctl application." ) + +#define TUNER_TEXT N_("Tuner id") +#define TUNER_LONGTEXT N_( \ + "Tuner id (see debug output)." ) +#define FREQUENCY_TEXT N_("Frequency") +#define FREQUENCY_LONGTEXT N_( \ + "Tuner frequency in Hz or kHz (see debug output)" ) +#define TUNER_AUDIO_MODE_TEXT N_("Audio mode") +#define TUNER_AUDIO_MODE_LONGTEXT N_( \ + "Tuner audio mono/stereo and track selection." ) + +#define AUDIO_DEPRECATED_ERROR N_( \ + "Alsa or OSS audio capture in the v4l2 access is deprecated. " \ + "please use 'v4l2:/""/ :input-slave=alsa:/""/' or " \ + "'v4l2:/""/ :input-slave=oss:/""/' instead." ) + +#define ASPECT_TEXT N_("Picture aspect-ratio n:m") +#define ASPECT_LONGTEXT N_("Define input picture aspect-ratio to use. Default is 4:3" ) typedef enum { IO_METHOD_READ, @@ -142,148 +213,295 @@ typedef enum { IO_METHOD_USERPTR, } io_method; -static int i_standards_list[] = +static const int i_standards_list[] = { V4L2_STD_UNKNOWN, V4L2_STD_SECAM, V4L2_STD_PAL, V4L2_STD_NTSC }; -static const char *psz_standards_list_text[] = +static const char *const psz_standards_list_text[] = { N_("Default"), N_("SECAM"), N_("PAL"), N_("NTSC") }; -static int i_iomethod_list[] = +static const int i_iomethod_list[] = { IO_METHOD_READ, IO_METHOD_MMAP, IO_METHOD_USERPTR }; -static const char *psz_iomethod_list_text[] = +static const char *const psz_iomethod_list_text[] = { N_("READ"), N_("MMAP"), N_("USERPTR") }; -vlc_module_begin(); - set_shortname( _("Video4Linux2") ); - set_description( _("Video4Linux2 input") ); - set_category( CAT_INPUT ); - set_subcategory( SUBCAT_INPUT_ACCESS ); - - set_section( N_( "Video input" ), NULL ); - add_string( "v4l2-dev", "/dev/video0", 0, DEV_TEXT, DEV_LONGTEXT, - VLC_FALSE ); - add_integer( "v4l2-standard", 0, NULL, STANDARD_TEXT, STANDARD_LONGTEXT, - VLC_FALSE ); - change_integer_list( i_standards_list, psz_standards_list_text, 0 ); - add_string( "v4l2-chroma", NULL, NULL, CHROMA_TEXT, CHROMA_LONGTEXT, - VLC_TRUE ); - add_integer( "v4l2-input", 0, NULL, INPUT_TEXT, INPUT_LONGTEXT, - VLC_TRUE ); - add_integer( "v4l2-io", IO_METHOD_MMAP, NULL, IOMETHOD_TEXT, - IOMETHOD_LONGTEXT, VLC_TRUE ); - change_integer_list( i_iomethod_list, psz_iomethod_list_text, 0 ); - add_integer( "v4l2-width", 0, NULL, WIDTH_TEXT, - WIDTH_LONGTEXT, VLC_TRUE ); - add_integer( "v4l2-height", 0, NULL, HEIGHT_TEXT, - HEIGHT_LONGTEXT, VLC_TRUE ); - add_float( "v4l2-fps", 0, NULL, FPS_TEXT, FPS_LONGTEXT, VLC_TRUE ); - - set_section( N_( "Video controls" ), NULL ); - add_bool( "v4l2-videocontrol-reset", VLC_FALSE, NULL, VIDEOCTRL_RESET_TEXT, - VIDEOCTRL_RESET_LONGTEXT, VLC_TRUE ); - add_integer( "v4l2-brightness", -1, NULL, BRIGHTNESS_TEXT, - BRIGHTNESS_LONGTEXT, VLC_TRUE ); - add_integer( "v4l2-contrast", -1, NULL, CONTRAST_TEXT, - CONTRAST_LONGTEXT, VLC_TRUE ); - add_integer( "v4l2-saturation", -1, NULL, SATURATION_TEXT, - SATURATION_LONGTEXT, VLC_TRUE ); - add_integer( "v4l2-hue", -1, NULL, HUE_TEXT, - HUE_LONGTEXT, VLC_TRUE ); - add_integer( "v4l2-gamma", -1, NULL, GAMMA_TEXT, - GAMMA_LONGTEXT, VLC_TRUE ); - - set_section( N_( "Audio input" ), NULL ); - add_string( "v4l2-adev", "/dev/dsp", 0, ADEV_TEXT, ADEV_LONGTEXT, - VLC_FALSE ); -#ifdef HAVE_ALSA - add_bool( "v4l2-alsa", VLC_FALSE, NULL, ALSA_TEXT, ALSA_LONGTEXT, - VLC_TRUE ); +static const int i_tuner_audio_modes_list[] = + { V4L2_TUNER_MODE_MONO, V4L2_TUNER_MODE_STEREO, + V4L2_TUNER_MODE_LANG1, V4L2_TUNER_MODE_LANG2, + V4L2_TUNER_MODE_SAP, V4L2_TUNER_MODE_LANG1_LANG2 }; +static const char *const psz_tuner_audio_modes_list_text[] = + { N_( "Mono" ), + N_( "Stereo" ), + N_( "Primary language (Analog TV tuners only)" ), + N_( "Secondary language (Analog TV tuners only)" ), + N_( "Second audio program (Analog TV tuners only)" ), + N_( "Primary language left, Secondary language right" ) }; + +#define V4L2_DEFAULT "/dev/video0" +#define CFG_PREFIX "v4l2-" + +vlc_module_begin () + set_shortname( N_("Video4Linux2") ) + set_description( N_("Video4Linux2 input") ) + set_category( CAT_INPUT ) + set_subcategory( SUBCAT_INPUT_ACCESS ) + + set_section( N_( "Video input" ), NULL ) + add_integer( CFG_PREFIX "standard", 0, NULL, STANDARD_TEXT, + STANDARD_LONGTEXT, false ) + change_integer_list( i_standards_list, psz_standards_list_text, NULL ) + add_string( CFG_PREFIX "chroma", NULL, NULL, CHROMA_TEXT, CHROMA_LONGTEXT, + true ) + add_integer( CFG_PREFIX "input", 0, NULL, INPUT_TEXT, INPUT_LONGTEXT, + true ) + add_integer( CFG_PREFIX "audio-input", 0, NULL, AUDIO_INPUT_TEXT, + AUDIO_INPUT_LONGTEXT, true ) + add_integer( CFG_PREFIX "io", IO_METHOD_MMAP, NULL, IOMETHOD_TEXT, + IOMETHOD_LONGTEXT, true ) + change_integer_list( i_iomethod_list, psz_iomethod_list_text, NULL ) + add_integer( CFG_PREFIX "width", -1, NULL, WIDTH_TEXT, + WIDTH_LONGTEXT, true ) + add_integer( CFG_PREFIX "height", -1, NULL, HEIGHT_TEXT, + HEIGHT_LONGTEXT, true ) + add_string( CFG_PREFIX "aspect-ratio", "4:3", NULL, ASPECT_TEXT, + ASPECT_LONGTEXT, true ) + add_float( CFG_PREFIX "fps", 0, NULL, FPS_TEXT, FPS_LONGTEXT, true ) + add_integer( CFG_PREFIX "caching", DEFAULT_PTS_DELAY / 1000, NULL, + CACHING_TEXT, CACHING_LONGTEXT, true ) +#ifdef HAVE_LIBV4L2 + add_bool( CFG_PREFIX "use-libv4l2", false, NULL, LIBV4L2_TEXT, LIBV4L2_LONGTEXT, true ); #endif - add_bool( "v4l2-stereo", VLC_TRUE, NULL, STEREO_TEXT, STEREO_LONGTEXT, - VLC_TRUE ); - add_integer( "v4l2-samplerate", 48000, NULL, SAMPLERATE_TEXT, - SAMPLERATE_LONGTEXT, VLC_TRUE ); - add_integer( "v4l2-caching", DEFAULT_PTS_DELAY / 1000, NULL, - CACHING_TEXT, CACHING_LONGTEXT, VLC_TRUE ); - - add_shortcut( "v4l2" ); - set_capability( "access_demux", 10 ); - set_callbacks( Open, Close ); -vlc_module_end(); + + set_section( N_( "Tuner" ), NULL ) + add_integer( CFG_PREFIX "tuner", 0, NULL, TUNER_TEXT, TUNER_LONGTEXT, + true ) + add_integer( CFG_PREFIX "tuner-frequency", -1, NULL, FREQUENCY_TEXT, + FREQUENCY_LONGTEXT, true ) + add_integer( CFG_PREFIX "tuner-audio-mode", -1, NULL, TUNER_AUDIO_MODE_TEXT, + TUNER_AUDIO_MODE_LONGTEXT, true ) + change_integer_list( i_tuner_audio_modes_list, + psz_tuner_audio_modes_list_text, 0 ) + + set_section( N_( "Controls" ), + N_( "v4l2 driver controls, if supported by your v4l2 driver." ) ) + add_bool( CFG_PREFIX "controls-reset", false, NULL, CTRL_RESET_TEXT, + CTRL_RESET_LONGTEXT, true ) + add_integer( CFG_PREFIX "brightness", -1, NULL, BRIGHTNESS_TEXT, + BRIGHTNESS_LONGTEXT, true ) + add_integer( CFG_PREFIX "contrast", -1, NULL, CONTRAST_TEXT, + CONTRAST_LONGTEXT, true ) + add_integer( CFG_PREFIX "saturation", -1, NULL, SATURATION_TEXT, + SATURATION_LONGTEXT, true ) + add_integer( CFG_PREFIX "hue", -1, NULL, HUE_TEXT, + HUE_LONGTEXT, true ) + add_integer( CFG_PREFIX "black-level", -1, NULL, BLACKLEVEL_TEXT, + BLACKLEVEL_LONGTEXT, true ) + add_integer( CFG_PREFIX "auto-white-balance", -1, NULL, + AUTOWHITEBALANCE_TEXT, AUTOWHITEBALANCE_LONGTEXT, true ) + add_integer( CFG_PREFIX "do-white-balance", -1, NULL, DOWHITEBALANCE_TEXT, + DOWHITEBALANCE_LONGTEXT, true ) + add_integer( CFG_PREFIX "red-balance", -1, NULL, REDBALANCE_TEXT, + REDBALANCE_LONGTEXT, true ) + add_integer( CFG_PREFIX "blue-balance", -1, NULL, BLUEBALANCE_TEXT, + BLUEBALANCE_LONGTEXT, true ) + add_integer( CFG_PREFIX "gamma", -1, NULL, GAMMA_TEXT, + GAMMA_LONGTEXT, true ) + add_integer( CFG_PREFIX "exposure", -1, NULL, EXPOSURE_TEXT, + EXPOSURE_LONGTEXT, true ) + add_integer( CFG_PREFIX "autogain", -1, NULL, AUTOGAIN_TEXT, + AUTOGAIN_LONGTEXT, true ) + add_integer( CFG_PREFIX "gain", -1, NULL, GAIN_TEXT, + GAIN_LONGTEXT, true ) + add_integer( CFG_PREFIX "hflip", -1, NULL, HFLIP_TEXT, + HFLIP_LONGTEXT, true ) + add_integer( CFG_PREFIX "vflip", -1, NULL, VFLIP_TEXT, + VFLIP_LONGTEXT, true ) + add_integer( CFG_PREFIX "hcenter", -1, NULL, HCENTER_TEXT, + HCENTER_LONGTEXT, true ) + add_integer( CFG_PREFIX "vcenter", -1, NULL, VCENTER_TEXT, + VCENTER_LONGTEXT, true ) + add_integer( CFG_PREFIX "audio-volume", -1, NULL, AUDIO_VOLUME_TEXT, + AUDIO_VOLUME_LONGTEXT, true ) + add_integer( CFG_PREFIX "audio-balance", -1, NULL, AUDIO_BALANCE_TEXT, + AUDIO_BALANCE_LONGTEXT, true ) + add_bool( CFG_PREFIX "audio-mute", false, NULL, AUDIO_MUTE_TEXT, + AUDIO_MUTE_LONGTEXT, true ) + add_integer( CFG_PREFIX "audio-bass", -1, NULL, AUDIO_BASS_TEXT, + AUDIO_BASS_LONGTEXT, true ) + add_integer( CFG_PREFIX "audio-treble", -1, NULL, AUDIO_TREBLE_TEXT, + AUDIO_TREBLE_LONGTEXT, true ) + add_integer( CFG_PREFIX "audio-loudness", -1, NULL, AUDIO_LOUDNESS_TEXT, + AUDIO_LOUDNESS_LONGTEXT, true ) + add_string( CFG_PREFIX "set-ctrls", NULL, NULL, S_CTRLS_TEXT, + S_CTRLS_LONGTEXT, true ) + + add_obsolete_string( CFG_PREFIX "dev" ) + + add_obsolete_string( CFG_PREFIX "adev" ) + add_obsolete_integer( CFG_PREFIX "audio-method" ) + add_obsolete_bool( CFG_PREFIX "stereo" ) + add_obsolete_integer( CFG_PREFIX "samplerate" ) + + add_shortcut( "v4l2" ) + set_capability( "access_demux", 10 ) + set_callbacks( DemuxOpen, DemuxClose ) + + add_submodule () + add_shortcut( "v4l2" ) + add_shortcut( "v4l2c" ) + set_description( N_("Video4Linux2 Compressed A/V") ) + set_capability( "access", 0 ) + /* use these when open as access_demux fails; VLC will use another demux */ + set_callbacks( AccessOpen, AccessClose ) + +vlc_module_end () /***************************************************************************** * Access: local prototypes *****************************************************************************/ -static void ParseMRL( demux_t * ); +static void CommonClose( vlc_object_t *, demux_sys_t * ); +static void ParseMRL( demux_sys_t *, char *, vlc_object_t * ); +static void GetV4L2Params( demux_sys_t *, vlc_object_t * ); +static void SetAvailControlsByString( vlc_object_t *, demux_sys_t *, int ); -static int Control( demux_t *, int, va_list ); +static int DemuxControl( demux_t *, int, va_list ); +static int AccessControl( access_t *, int, va_list ); static int Demux( demux_t * ); -static block_t* GrabVideo( demux_t *p_demux ); -static block_t* ProcessVideoFrame( demux_t *p_demux, uint8_t *p_frame ); -static block_t* GrabAudio( demux_t *p_demux ); - -vlc_bool_t IsPixelFormatSupported( demux_t *p_demux, unsigned int i_pixelformat ); - -char* ResolveALSADeviceName( char *psz_device ); -static int OpenVideoDev( demux_t *, char *psz_device ); -static int OpenAudioDev( demux_t *, char *psz_device ); -static vlc_bool_t ProbeVideoDev( demux_t *, char *psz_device ); -static vlc_bool_t ProbeAudioDev( demux_t *, char *psz_device ); - -static int VideoControlList( demux_t *p_demux, int i_fd, vlc_bool_t b_reset ); -static int VideoControl( demux_t *, int i_fd, - const char *psz_label, int i_cid, int i_value ); -static int VideoControlCallback( vlc_object_t *p_this, - const char *psz_var, vlc_value_t oldval, vlc_value_t newval, - void *p_data ); - -static struct +static block_t *AccessRead( access_t * ); + +static block_t* GrabVideo( vlc_object_t *p_demux, demux_sys_t *p_sys ); +static block_t* ProcessVideoFrame( vlc_object_t *p_demux, uint8_t *p_frame, size_t ); + +static bool IsPixelFormatSupported( demux_t *p_demux, + unsigned int i_pixelformat ); + +static int OpenVideoDev( vlc_object_t *, demux_sys_t *, bool ); +static bool ProbeVideoDev( vlc_object_t *, demux_sys_t *, + const char *psz_device ); + +static int ControlList( vlc_object_t *, demux_sys_t *, int , bool, bool ); +static int Control( vlc_object_t *, demux_sys_t *, int i_fd, + const char *psz_name, int i_cid, int i_value ); + +static int DemuxControlCallback( vlc_object_t *p_this, const char *psz_var, + vlc_value_t oldval, vlc_value_t newval, + void *p_data ); +static int DemuxControlResetCallback( vlc_object_t *p_this, const char *psz_var, + vlc_value_t oldval, vlc_value_t newval, + void *p_data ); +static int AccessControlCallback( vlc_object_t *p_this, const char *psz_var, + vlc_value_t oldval, vlc_value_t newval, + void *p_data ); +static int AccessControlResetCallback( vlc_object_t *p_this, + const char *psz_var, vlc_value_t oldval, + vlc_value_t newval, void *p_data ); + +static const struct { unsigned int i_v4l2; - int i_fourcc; + vlc_fourcc_t i_fourcc; + int i_rmask; + int i_gmask; + int i_bmask; } v4l2chroma_to_fourcc[] = { - { V4L2_PIX_FMT_GREY, VLC_FOURCC( 'G', 'R', 'E', 'Y' ) }, - { V4L2_PIX_FMT_HI240, VLC_FOURCC( 'I', '2', '4', '0' ) }, - { V4L2_PIX_FMT_RGB565, VLC_FOURCC( 'R', 'V', '1', '6' ) }, - { V4L2_PIX_FMT_RGB555, VLC_FOURCC( 'R', 'V', '1', '5' ) }, - { V4L2_PIX_FMT_BGR24, VLC_FOURCC( 'R', 'V', '2', '4' ) }, - { V4L2_PIX_FMT_BGR32, VLC_FOURCC( 'R', 'V', '3', '2' ) }, - { V4L2_PIX_FMT_YUYV, VLC_FOURCC( 'Y', 'U', 'Y', '2' ) }, - { V4L2_PIX_FMT_YUYV, VLC_FOURCC( 'Y', 'U', 'Y', 'V' ) }, - { V4L2_PIX_FMT_UYVY, VLC_FOURCC( 'U', 'Y', 'V', 'Y' ) }, - { V4L2_PIX_FMT_Y41P, VLC_FOURCC( 'I', '4', '1', 'N' ) }, - { V4L2_PIX_FMT_YUV422P, VLC_FOURCC( 'I', '4', '2', '2' ) }, - { V4L2_PIX_FMT_YVU420, VLC_FOURCC( 'I', '4', '2', '0' ) }, - { V4L2_PIX_FMT_YUV411P, VLC_FOURCC( 'I', '4', '1', '1' ) }, - { V4L2_PIX_FMT_YUV410, VLC_FOURCC( 'I', '4', '1', '0' ) }, - { 0, 0 } + /* Raw data types */ + { V4L2_PIX_FMT_GREY, VLC_CODEC_GREY, 0, 0, 0 }, + { V4L2_PIX_FMT_HI240, VLC_FOURCC('I','2','4','0'), 0, 0, 0 }, + { V4L2_PIX_FMT_RGB555, VLC_CODEC_RGB15, 0x001f,0x03e0,0x7c00 }, + { V4L2_PIX_FMT_RGB565, VLC_CODEC_RGB16, 0x001f,0x07e0,0xf800 }, + /* Won't work since we don't know how to handle such gmask values + * correctly + { V4L2_PIX_FMT_RGB555X, VLC_CODEC_RGB15, 0x007c,0xe003,0x1f00 }, + { V4L2_PIX_FMT_RGB565X, VLC_CODEC_RGB16, 0x00f8,0xe007,0x1f00 }, + */ + { V4L2_PIX_FMT_BGR24, VLC_CODEC_RGB24, 0xff0000,0xff00,0xff }, + { V4L2_PIX_FMT_RGB24, VLC_CODEC_RGB24, 0xff,0xff00,0xff0000 }, + { V4L2_PIX_FMT_BGR32, VLC_CODEC_RGB32, 0xff0000,0xff00,0xff }, + { V4L2_PIX_FMT_RGB32, VLC_CODEC_RGB32, 0xff,0xff00,0xff0000 }, + { V4L2_PIX_FMT_YUYV, VLC_CODEC_YUYV, 0, 0, 0 }, + { V4L2_PIX_FMT_UYVY, VLC_CODEC_UYVY, 0, 0, 0 }, + { V4L2_PIX_FMT_Y41P, VLC_FOURCC('I','4','1','N'), 0, 0, 0 }, + { V4L2_PIX_FMT_YUV422P, VLC_CODEC_I422, 0, 0, 0 }, + { V4L2_PIX_FMT_YVU420, VLC_CODEC_YV12, 0, 0, 0 }, + { V4L2_PIX_FMT_YUV411P, VLC_CODEC_I411, 0, 0, 0 }, + { V4L2_PIX_FMT_YUV410, VLC_CODEC_I410, 0, 0, 0 }, + + /* Raw data types, not in V4L2 spec but still in videodev2.h and supported + * by VLC */ + { V4L2_PIX_FMT_YUV420, VLC_CODEC_I420, 0, 0, 0 }, + /* FIXME { V4L2_PIX_FMT_RGB444, VLC_CODEC_RGB32 }, */ + + /* Compressed data types */ + { V4L2_PIX_FMT_MJPEG, VLC_CODEC_MJPG, 0, 0, 0 }, + { V4L2_PIX_FMT_JPEG, VLC_CODEC_JPEG, 0, 0, 0 }, +#if 0 + { V4L2_PIX_FMT_DV, VLC_FOURCC('?','?','?','?') }, + { V4L2_PIX_FMT_MPEG, VLC_FOURCC('?','?','?','?') }, +#endif + { 0, 0, 0, 0, 0 } +}; + +/** + * List of V4L2 chromas were confident enough to use as fallbacks if the + * user hasn't provided a --v4l2-chroma value. + * + * Try YUV chromas first, then RGB little endian and MJPEG as last resort. + */ +static const __u32 p_chroma_fallbacks[] = +{ V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_YVU420, V4L2_PIX_FMT_YUV422P, + V4L2_PIX_FMT_YUYV, V4L2_PIX_FMT_UYVY, V4L2_PIX_FMT_BGR24, + V4L2_PIX_FMT_BGR32, V4L2_PIX_FMT_MJPEG, V4L2_PIX_FMT_JPEG }; + +static const struct +{ + const char *psz_name; + unsigned int i_cid; +} controls[] = +{ + { "brightness", V4L2_CID_BRIGHTNESS }, + { "contrast", V4L2_CID_CONTRAST }, + { "saturation", V4L2_CID_SATURATION }, + { "hue", V4L2_CID_HUE }, + { "audio-volume", V4L2_CID_AUDIO_VOLUME }, + { "audio-balance", V4L2_CID_AUDIO_BALANCE }, + { "audio-bass", V4L2_CID_AUDIO_BASS }, + { "audio-treble", V4L2_CID_AUDIO_TREBLE }, + { "audio-mute", V4L2_CID_AUDIO_MUTE }, + { "audio-loudness", V4L2_CID_AUDIO_LOUDNESS }, + { "black-level", V4L2_CID_BLACK_LEVEL }, + { "auto-white-balance", V4L2_CID_AUTO_WHITE_BALANCE }, + { "do-white-balance", V4L2_CID_DO_WHITE_BALANCE }, + { "red-balance", V4L2_CID_RED_BALANCE }, + { "blue-balance", V4L2_CID_BLUE_BALANCE }, + { "gamma", V4L2_CID_GAMMA }, + { "exposure", V4L2_CID_EXPOSURE }, + { "autogain", V4L2_CID_AUTOGAIN }, + { "gain", V4L2_CID_GAIN }, + { "hflip", V4L2_CID_HFLIP }, + { "vflip", V4L2_CID_VFLIP }, + { "hcenter", V4L2_CID_HCENTER }, + { "vcenter", V4L2_CID_VCENTER }, + { NULL, 0 } }; struct buffer_t { void * start; size_t length; - void * orig_userp; }; struct demux_sys_t { - char *psz_device; /* Main device from MRL, can be video or audio */ - - char *psz_vdev; - int i_fd_video; - - char *psz_adev; - int i_fd_audio; + char *psz_device; /* Main device from MRL */ + int i_fd; char *psz_requested_chroma; /* Video */ io_method io; - int i_pts; + int i_cache; struct v4l2_capability dev_cap; @@ -298,6 +516,7 @@ struct demux_sys_t int i_audio; /* V4L2 devices cannot have more than 32 audio inputs */ struct v4l2_audio p_audios[32]; + int i_selected_audio_input; int i_tuner; struct v4l2_tuner *p_tuners; @@ -310,56 +529,106 @@ struct demux_sys_t int i_width; int i_height; + unsigned int i_aspect; float f_fps; /* <= 0.0 mean to grab at full rate */ mtime_t i_video_pts; /* only used when f_fps > 0 */ int i_fourcc; - vlc_bool_t b_videoctrl_reset; - int i_brightness; - int i_contrast; - int i_saturation; - int i_hue; - int i_gamma; - - picture_t pic; - int i_video_frame_size; - - es_out_id_t *p_es_video; - - /* Audio */ - unsigned int i_sample_rate; - vlc_bool_t b_stereo; - int i_audio_max_frame_size; - block_t *p_block_audio; - es_out_id_t *p_es_audio; - -#ifdef HAVE_ALSA - /* ALSA Audio */ - vlc_bool_t b_use_alsa; - snd_pcm_t *p_alsa_pcm; - int i_alsa_frame_size; - int i_alsa_chunk_size; + es_out_id_t *p_es; + + /* Tuner */ + int i_cur_tuner; + int i_frequency; + int i_audio_mode; + + /* Controls */ + char *psz_set_ctrls; + + +#ifdef HAVE_LIBV4L2 + /* */ + int (*pf_close)( int ); + int (*pf_dup)( int ); + int (*pf_ioctl)( int, unsigned long int, ... ); + ssize_t (*pf_read)( int, void *, size_t ); + void *(*pf_mmap)( void *, size_t, int, int, int, off_t ); + int (*pf_munmap)( void *, size_t ); + bool b_libv4l2; #endif }; +#ifdef HAVE_LIBV4L2 +static void use_kernel_v4l2( demux_sys_t *p_sys ) +{ + p_sys->pf_close = close; + p_sys->pf_dup = dup; + p_sys->pf_ioctl = ioctl; + p_sys->pf_read = read; + p_sys->pf_mmap = mmap; + p_sys->pf_munmap = munmap; + p_sys->b_libv4l2 = false; +} + +static void use_libv4l2( demux_sys_t *p_sys ) +{ + p_sys->pf_close = v4l2_close; + p_sys->pf_dup = v4l2_dup; + p_sys->pf_ioctl = v4l2_ioctl; + p_sys->pf_read = v4l2_read; + p_sys->pf_mmap = v4l2_mmap; + p_sys->pf_munmap = v4l2_munmap; + p_sys->b_libv4l2 = true; +} + +# define v4l2_close (p_sys->pf_close) +# define v4l2_dup (p_sys->pf_dup) +# define v4l2_ioctl (p_sys->pf_ioctl) +# define v4l2_read (p_sys->pf_read) +# define v4l2_mmap (p_sys->pf_mmap) +# define v4l2_munmap (p_sys->pf_munmap) +#else +# define v4l2_close close +# define v4l2_dup dup +# define v4l2_ioctl ioctl +# define v4l2_read read +# define v4l2_mmap mmap +# define v4l2_munmap munmap +#endif + +static int FindMainDevice( vlc_object_t *p_this, demux_sys_t *p_sys, + bool b_demux ) +{ + /* TODO: if using default device, loop through all /dev/video* until + * one works */ + msg_Dbg( p_this, "opening device '%s'", p_sys->psz_device ); + if( ProbeVideoDev( p_this, p_sys, p_sys->psz_device ) ) + { + msg_Dbg( p_this, "'%s' is a video device", p_sys->psz_device ); + p_sys->i_fd = OpenVideoDev( p_this, p_sys, b_demux ); + } + + if( p_sys->i_fd < 0 ) return VLC_EGENERIC; + return VLC_SUCCESS; +} + /***************************************************************************** - * Open: opens v4l2 device + * DemuxOpen: opens v4l2 device, access_demux callback ***************************************************************************** * * url: