Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

v4l.c

00001 /*****************************************************************************
00002  * v4l.c : Video4Linux input module for vlc
00003  *****************************************************************************
00004  * Copyright (C) 2002-2004 the VideoLAN team
00005  * $Id: v4l.c 11664 2005-07-09 06:17:09Z courmisch $
00006  *
00007  * Author: Laurent Aimar <[email protected]>
00008  *         Paul Forgey <paulf at aphrodite dot com>
00009  *         Gildas Bazin <[email protected]>
00010  *         Benjamin Pracht <bigben at videolan dot org>
00011  *
00012  * This program is free software; you can redistribute it and/or modify
00013  * it under the terms of the GNU General Public License as published by
00014  * the Free Software Foundation; either version 2 of the License, or
00015  * (at your option) any later version.
00016  *
00017  * This program is distributed in the hope that it will be useful,
00018  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00019  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020  * GNU General Public License for more details.
00021  *
00022  * You should have received a copy of the GNU General Public License
00023  * along with this program; if not, write to the Free Software
00024  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00025  *****************************************************************************/
00026 
00027 /*****************************************************************************
00028  * Preamble
00029  *****************************************************************************/
00030 #include <stdlib.h>
00031 #include <stdio.h>
00032 #include <string.h>
00033 
00034 #include <vlc/vlc.h>
00035 #include <vlc/input.h>
00036 #include <vlc/vout.h>
00037 #include <codecs.h>
00038 
00039 #include <sys/types.h>
00040 #include <sys/stat.h>
00041 #include <sys/ioctl.h>
00042 #include <unistd.h>
00043 #include <sys/mman.h>
00044 #include <errno.h>
00045 #include <fcntl.h>
00046 
00047 /* From GStreamer's v4l plugin:
00048  * Because of some really cool feature in video4linux1, also known as
00049  * 'not including sys/types.h and sys/time.h', we had to include it
00050  * ourselves. In all their intelligence, these people decided to fix
00051  * this in the next version (video4linux2) in such a cool way that it
00052  * breaks all compilations of old stuff...
00053  * The real problem is actually that linux/time.h doesn't use proper
00054  * macro checks before defining types like struct timeval. The proper
00055  * fix here is to either fuck the kernel header (which is what we do
00056  * by defining _LINUX_TIME_H, an innocent little hack) or by fixing it
00057  * upstream, which I'll consider doing later on. If you get compiler
00058  * errors here, check your linux/time.h && sys/time.h header setup.
00059 */
00060 #define _LINUX_TIME_H
00061 
00062 #include <linux/videodev.h>
00063 #include "videodev_mjpeg.h"
00064 
00065 #include <sys/soundcard.h>
00066 
00067 /*****************************************************************************
00068  * Module descriptior
00069  *****************************************************************************/
00070 static int  Open ( vlc_object_t * );
00071 static void Close( vlc_object_t * );
00072 
00073 #define CACHING_TEXT N_("Caching value in ms")
00074 #define CACHING_LONGTEXT N_( \
00075     "Allows you to modify the default caching value for v4l streams. This " \
00076     "value should be set in millisecond units." )
00077 #define VDEV_TEXT N_("Video device name")
00078 #define VDEV_LONGTEXT N_( \
00079     "Specify the name of the video device that will be used. " \
00080     "If you don't specify anything, no video device will be used.")
00081 #define ADEV_TEXT N_("Audio device name")
00082 #define ADEV_LONGTEXT N_( \
00083     "Specify the name of the audio device that will be used. " \
00084     "If you don't specify anything, no audio device will be used.")
00085 #define CHROMA_TEXT N_("Video input chroma format")
00086 #define CHROMA_LONGTEXT N_( \
00087     "Force the Video4Linux video device to use a specific chroma format " \
00088     "(eg. I420 (default), RV24, etc.)")
00089 #define FREQUENCY_TEXT N_( "Frequency" )
00090 #define FREQUENCY_LONGTEXT N_( \
00091     "Frequency to capture (in kHz), if applicable" )
00092 #define CHANNEL_TEXT N_( "Channel" )
00093 #define CHANNEL_LONGTEXT N_( \
00094     "Channel of the card to use (Usually, 0 = tuner, " \
00095     "1 = composite, 2 = svideo)" )
00096 #define NORM_TEXT N_( "Norm" )
00097 #define NORM_LONGTEXT N_( \
00098     "Defines the norm of the stream (Automatic, SECAM, PAL, or NTSC)" )
00099 #define AUDIO_TEXT N_( "Audio Channel" )
00100 #define AUDIO_LONGTEXT N_( \
00101     "Audio Channel to use, if there are several audio input" )
00102 #define WIDTH_TEXT N_( "Width" )
00103 #define WIDTH_LONGTEXT N_( "Width of the stream to capture " \
00104     "(-1 for autodetect)" )
00105 #define HEIGHT_TEXT N_( "Height" )
00106 #define HEIGHT_LONGTEXT N_( "Height of the stream to capture " \
00107     "(-1 for autodetect)" )
00108 #define BRIGHTNESS_TEXT N_( "Brightness" )
00109 #define BRIGHTNESS_LONGTEXT N_( \
00110     "Set the Brightness of the video input" )
00111 #define HUE_TEXT N_( "Hue" )
00112 #define HUE_LONGTEXT N_( \
00113     "Set the Hue of the video input" )
00114 #define COLOUR_TEXT N_( "Color" )
00115 #define COLOUR_LONGTEXT N_( \
00116     "Set the Color of the video input" )
00117 #define CONTRAST_TEXT N_( "Contrast" )
00118 #define CONTRAST_LONGTEXT N_( \
00119     "Set the Contrast of the video input" )
00120 #define TUNER_TEXT N_( "Tuner" )
00121 #define TUNER_LONGTEXT N_( "Tuner to use, if there are several ones" )
00122 #define SAMPLERATE_TEXT N_( "Samplerate" )
00123 #define SAMPLERATE_LONGTEXT N_( \
00124     "Samplerate of the captures audio stream, in Hz" )
00125 #define STEREO_TEXT N_( "Stereo" )
00126 #define STEREO_LONGTEXT N_( \
00127     "If this option is set, the audio stream will be captured in stereo" )
00128 #define MJPEG_TEXT N_( "MJPEG" )
00129 #define MJPEG_LONGTEXT N_(  \
00130     "Set this option if the capture device outputs MJPEG" )
00131 #define DECIMATION_TEXT N_( "Decimation" )
00132 #define DECIMATION_LONGTEXT N_( \
00133     "Set the Decimation level for MJPEG streams" )
00134 #define QUALITY_TEXT N_( "Quality" )
00135 #define QUALITY_LONGTEXT N_( "Set the quality of the stream" )
00136 #define FPS_TEXT N_( "Framerate" )
00137 #define FPS_LONGTEXT N_( "Framerate to capture, if applicable " \
00138     "(-1 for autodetect)" )
00139 
00140 static int i_norm_list[] =
00141     { VIDEO_MODE_AUTO, VIDEO_MODE_SECAM, VIDEO_MODE_PAL, VIDEO_MODE_NTSC };
00142 static char *psz_norm_list_text[] =
00143     { N_("Automatic"), N_("SECAM"), N_("PAL"),  N_("NTSC") };
00144 
00145 vlc_module_begin();
00146     set_shortname( _("Video4Linux") );
00147     set_description( _("Video4Linux input") );
00148     set_category( CAT_INPUT );
00149     set_subcategory( SUBCAT_INPUT_ACCESS );
00150 
00151     add_integer( "v4l-caching", DEFAULT_PTS_DELAY / 1000, NULL,
00152                  CACHING_TEXT, CACHING_LONGTEXT, VLC_TRUE );
00153     add_string( "v4l-vdev", "/dev/video", 0, VDEV_TEXT, VDEV_LONGTEXT,
00154                 VLC_FALSE );
00155     add_string( "v4l-adev", "/dev/dsp", 0, ADEV_TEXT, ADEV_LONGTEXT,
00156                 VLC_FALSE );
00157     add_string( "v4l-chroma", NULL, NULL, CHROMA_TEXT, CHROMA_LONGTEXT,
00158                 VLC_TRUE );
00159     add_float( "v4l-fps", -1.0, NULL, FPS_TEXT, FPS_LONGTEXT, VLC_TRUE );
00160     add_integer( "v4l-samplerate", 44100, NULL, SAMPLERATE_TEXT,
00161                 SAMPLERATE_LONGTEXT, VLC_TRUE );
00162     add_integer( "v4l-channel", 0, NULL, CHANNEL_TEXT, CHANNEL_LONGTEXT,
00163                 VLC_TRUE );
00164     add_integer( "v4l-tuner", -1, NULL, TUNER_TEXT, TUNER_LONGTEXT, VLC_TRUE );
00165     add_integer( "v4l-norm", VIDEO_MODE_AUTO, NULL, NORM_TEXT, NORM_LONGTEXT,
00166                 VLC_FALSE );
00167         change_integer_list( i_norm_list, psz_norm_list_text, 0 );
00168     add_integer( "v4l-frequency", -1, NULL, FREQUENCY_TEXT, FREQUENCY_LONGTEXT,
00169                 VLC_FALSE );
00170     add_integer( "v4l-audio", -1, NULL, AUDIO_TEXT, AUDIO_LONGTEXT, VLC_TRUE );
00171     add_bool( "v4l-stereo", VLC_TRUE, NULL, STEREO_TEXT, STEREO_LONGTEXT,
00172             VLC_TRUE );
00173     add_integer( "v4l-width", 0, NULL, WIDTH_TEXT, WIDTH_LONGTEXT, VLC_TRUE );
00174     add_integer( "v4l-height", 0, NULL, HEIGHT_TEXT, HEIGHT_LONGTEXT,
00175                 VLC_TRUE );
00176     add_integer( "v4l-brightness", -1, NULL, BRIGHTNESS_TEXT,
00177                 BRIGHTNESS_LONGTEXT, VLC_TRUE );
00178     add_integer( "v4l-colour", -1, NULL, COLOUR_TEXT, COLOUR_LONGTEXT,
00179                 VLC_TRUE );
00180     add_integer( "v4l-hue", -1, NULL, HUE_TEXT, HUE_LONGTEXT, VLC_TRUE );
00181     add_integer( "v4l-contrast", -1, NULL, CONTRAST_TEXT, CONTRAST_LONGTEXT,
00182                 VLC_TRUE );
00183     add_bool( "v4l-mjpeg", VLC_FALSE, NULL, MJPEG_TEXT, MJPEG_LONGTEXT,
00184             VLC_TRUE );
00185     add_integer( "v4l-decimation", 1, NULL, DECIMATION_TEXT,
00186             DECIMATION_LONGTEXT, VLC_TRUE );
00187     add_integer( "v4l-quality", 100, NULL, QUALITY_TEXT, QUALITY_LONGTEXT,
00188             VLC_TRUE );
00189 
00190     add_shortcut( "v4l" );
00191     set_capability( "access_demux", 10 );
00192     set_callbacks( Open, Close );
00193 vlc_module_end();
00194 
00195 /*****************************************************************************
00196  * Access: local prototypes
00197  *****************************************************************************/
00198 static int Demux  ( demux_t * );
00199 static int Control( demux_t *, int, va_list );
00200 
00201 static void ParseMRL    ( demux_t * );
00202 static int  OpenVideoDev( demux_t *, char * );
00203 static int  OpenAudioDev( demux_t *, char * );
00204 
00205 static block_t *GrabAudio( demux_t * );
00206 static block_t *GrabVideo( demux_t * );
00207 
00208 #define MJPEG_BUFFER_SIZE (256*1024)
00209 
00210 struct quicktime_mjpeg_app1
00211 {
00212     uint32_t    i_reserved;             /* set to 0 */
00213     uint32_t    i_tag;                  /* 'mjpg' */
00214     uint32_t    i_field_size;           /* offset following EOI */
00215     uint32_t    i_padded_field_size;    /* offset following EOI+pad */
00216     uint32_t    i_next_field;           /* offset to next field */
00217     uint32_t    i_DQT_offset;
00218     uint32_t    i_DHT_offset;
00219     uint32_t    i_SOF_offset;
00220     uint32_t    i_SOS_offset;
00221     uint32_t    i_data_offset;          /* following SOS marker data */
00222 };
00223 
00224 static struct
00225 {
00226     int i_v4l;
00227     int i_fourcc;
00228 
00229 } v4lchroma_to_fourcc[] =
00230 {
00231     { VIDEO_PALETTE_GREY, VLC_FOURCC( 'G', 'R', 'E', 'Y' ) },
00232     { VIDEO_PALETTE_HI240, VLC_FOURCC( 'I', '2', '4', '0' ) },
00233     { VIDEO_PALETTE_RGB565, VLC_FOURCC( 'R', 'V', '1', '6' ) },
00234     { VIDEO_PALETTE_RGB555, VLC_FOURCC( 'R', 'V', '1', '5' ) },
00235     { VIDEO_PALETTE_RGB24, VLC_FOURCC( 'R', 'V', '2', '4' ) },
00236     { VIDEO_PALETTE_RGB32, VLC_FOURCC( 'R', 'V', '3', '2' ) },
00237     { VIDEO_PALETTE_YUV422, VLC_FOURCC( 'I', '4', '2', '2' ) },
00238     { VIDEO_PALETTE_YUYV, VLC_FOURCC( 'Y', 'U', 'Y', 'V' ) },
00239     { VIDEO_PALETTE_UYVY, VLC_FOURCC( 'U', 'Y', 'V', 'Y' ) },
00240     { VIDEO_PALETTE_YUV420, VLC_FOURCC( 'I', '4', '2', 'N' ) },
00241     { VIDEO_PALETTE_YUV411, VLC_FOURCC( 'I', '4', '1', 'N' ) },
00242     { VIDEO_PALETTE_RAW, VLC_FOURCC( 'G', 'R', 'A', 'W' ) },
00243     { VIDEO_PALETTE_YUV422P, VLC_FOURCC( 'I', '4', '2', '2' ) },
00244     { VIDEO_PALETTE_YUV420P, VLC_FOURCC( 'I', '4', '2', '0' ) },
00245     { VIDEO_PALETTE_YUV411P, VLC_FOURCC( 'I', '4', '1', '1' ) },
00246     { 0, 0 }
00247 };
00248 
00249 struct demux_sys_t
00250 {
00251     /* Devices */
00252     char *psz_device;         /* Main device from MRL, can be video or audio */
00253 
00254     char *psz_vdev;
00255     int  fd_video;
00256 
00257     char *psz_adev;
00258     int  fd_audio;
00259 
00260     /* Video properties */
00261     picture_t pic;
00262 
00263     int i_fourcc;
00264     int i_channel;
00265     int i_audio;
00266     int i_norm;
00267     int i_tuner;
00268     int i_frequency;
00269     int i_width;
00270     int i_height;
00271 
00272     int i_brightness;
00273     int i_hue;
00274     int i_colour;
00275     int i_contrast;
00276 
00277     float f_fps;            /* <= 0.0 mean to grab at full rate */
00278     mtime_t i_video_pts;    /* only used when f_fps > 0 */
00279 
00280     vlc_bool_t b_mjpeg;
00281     int i_decimation;
00282     int i_quality;
00283 
00284     struct video_capability vid_cap;
00285     struct video_mbuf       vid_mbuf;
00286     struct mjpeg_requestbuffers mjpeg_buffers;
00287 
00288     uint8_t *p_video_mmap;
00289     int     i_frame_pos;
00290 
00291     struct video_mmap   vid_mmap;
00292     struct video_picture vid_picture;
00293 
00294     int          i_video_frame_size;
00295     es_out_id_t  *p_es_video;
00296 
00297     /* Audio properties */
00298     vlc_fourcc_t i_acodec_raw;
00299     int          i_sample_rate;
00300     vlc_bool_t   b_stereo;
00301     int          i_audio_max_frame_size;
00302     block_t      *p_block_audio;
00303     es_out_id_t  *p_es_audio;
00304 };
00305 
00306 /*****************************************************************************
00307  * Open: opens v4l device
00308  *****************************************************************************
00309  *
00310  * url: <video device>::::
00311  *
00312  *****************************************************************************/
00313 static int Open( vlc_object_t *p_this )
00314 {
00315     demux_t     *p_demux = (demux_t*)p_this;
00316     demux_sys_t *p_sys;
00317     vlc_value_t val;
00318 
00319     /* Only when selected */
00320     if( *p_demux->psz_access == '\0' )
00321         return VLC_EGENERIC;
00322 
00323     /* Set up p_demux */
00324     p_demux->pf_demux = Demux;
00325     p_demux->pf_control = Control;
00326     p_demux->info.i_update = 0;
00327     p_demux->info.i_title = 0;
00328     p_demux->info.i_seekpoint = 0;
00329     p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );
00330     memset( p_sys, 0, sizeof( demux_sys_t ) );
00331 
00332     var_Create( p_demux, "v4l-audio", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
00333     var_Get( p_demux, "v4l-audio", &val );
00334     p_sys->i_audio          = val.i_int;
00335 
00336     var_Create( p_demux, "v4l-channel", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
00337     var_Get( p_demux, "v4l-channel", &val );
00338     p_sys->i_channel        = val.i_int;
00339 
00340     var_Create( p_demux, "v4l-norm", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
00341     var_Get( p_demux, "v4l-norm", &val );
00342     p_sys->i_norm           = val.i_int;
00343 
00344     var_Create( p_demux, "v4l-tuner", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
00345     var_Get( p_demux, "v4l-tuner", &val );
00346     p_sys->i_tuner          = val.i_int;
00347 
00348     var_Create( p_demux, "v4l-frequency",
00349                                     VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
00350     var_Get( p_demux, "v4l-frequency", &val );
00351     p_sys->i_frequency      = val.i_int;
00352 
00353     var_Create( p_demux, "v4l-fps", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT );
00354     var_Get( p_demux, "v4l-fps", &val );
00355     p_sys->f_fps            = val.f_float;
00356 
00357     var_Create( p_demux, "v4l-width", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
00358     var_Get( p_demux, "v4l-width", &val );
00359     p_sys->i_width          = val.i_int;
00360 
00361     var_Create( p_demux, "v4l-height", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
00362     var_Get( p_demux, "v4l-height", &val );
00363     p_sys->i_height         = val.i_int;
00364 
00365     p_sys->i_video_pts      = -1;
00366 
00367     var_Create( p_demux, "v4l-brightness", VLC_VAR_INTEGER |
00368                                                         VLC_VAR_DOINHERIT );
00369     var_Get( p_demux, "v4l-brightness", &val );
00370     p_sys->i_brightness     = val.i_int;
00371 
00372     var_Create( p_demux, "v4l-hue", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
00373     var_Get( p_demux, "v4l-hue", &val );
00374     p_sys->i_hue            = -1;
00375 
00376     var_Create( p_demux, "v4l-colour", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
00377     var_Get( p_demux, "v4l-colour", &val );
00378     p_sys->i_colour         = val.i_int;
00379 
00380     var_Create( p_demux, "v4l-contrast", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
00381     var_Get( p_demux, "v4l-contrast", &val );
00382     p_sys->i_contrast       = val.i_int;
00383 
00384     var_Create( p_demux, "v4l-mjpeg", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
00385     var_Get( p_demux, "v4l-mjpeg", &val );
00386     p_sys->b_mjpeg     = val.b_bool;
00387 
00388     var_Create( p_demux, "v4l-decimation", VLC_VAR_INTEGER |
00389                                                             VLC_VAR_DOINHERIT );
00390     var_Get( p_demux, "v4l-decimation", &val );
00391     p_sys->i_decimation = val.i_int;
00392 
00393     var_Create( p_demux, "v4l-quality", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
00394     var_Get( p_demux, "v4l-quality", &val );
00395     p_sys->i_quality = val.i_int;
00396 
00397     var_Create( p_demux, "v4l-samplerate",
00398                                     VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
00399     var_Get( p_demux, "v4l-samplerate", &val );
00400     p_sys->i_sample_rate  = val.i_int;
00401 
00402     var_Create( p_demux, "v4l-stereo", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
00403     var_Get( p_demux, "v4l-stereo", &val );
00404     p_sys->b_stereo       = val.b_bool;
00405 
00406     p_sys->psz_device = p_sys->psz_vdev = p_sys->psz_adev = NULL;
00407     p_sys->fd_video = -1;
00408     p_sys->fd_audio = -1;
00409 
00410     p_sys->p_es_video = p_sys->p_es_audio = 0;
00411     p_sys->p_block_audio = 0;
00412 
00413     ParseMRL( p_demux );
00414 
00415     /* Find main device (video or audio) */
00416     if( p_sys->psz_device && *p_sys->psz_device )
00417     {
00418         msg_Dbg( p_demux, "main device=`%s'", p_sys->psz_device );
00419 
00420         /* Try to open as video device */
00421         p_sys->fd_video = OpenVideoDev( p_demux, p_sys->psz_device );
00422 
00423         if( p_sys->fd_video < 0 )
00424         {
00425             /* Try to open as audio device */
00426             p_sys->fd_audio = OpenAudioDev( p_demux, p_sys->psz_device );
00427             if( p_sys->fd_audio >= 0 )
00428             {
00429                 if( p_sys->psz_adev ) free( p_sys->psz_adev );
00430                 p_sys->psz_adev = p_sys->psz_device;
00431                 p_sys->psz_device = NULL;
00432             }
00433         }
00434         else
00435         {
00436             if( p_sys->psz_vdev ) free( p_sys->psz_vdev );
00437             p_sys->psz_vdev = p_sys->psz_device;
00438             p_sys->psz_device = NULL;
00439         }
00440     }
00441 
00442     /* If no device opened, only continue if the access was forced */
00443     if( p_sys->fd_video < 0 && p_sys->fd_audio < 0 )
00444     {
00445         if( strcmp( p_demux->psz_access, "v4l" ) )
00446         {
00447             Close( p_this );
00448             return VLC_EGENERIC;
00449         }
00450     }
00451 
00452     /* Find video device */
00453     if( p_sys->fd_video < 0 )
00454     {
00455         if( !p_sys->psz_vdev || !*p_sys->psz_vdev )
00456         {
00457             if( p_sys->psz_vdev ) free( p_sys->psz_vdev );
00458             p_sys->psz_vdev = var_CreateGetString( p_demux, "v4l-vdev" );;
00459         }
00460 
00461         if( p_sys->psz_vdev && *p_sys->psz_vdev )
00462         {
00463             p_sys->fd_video = OpenVideoDev( p_demux, p_sys->psz_vdev );
00464         }
00465     }
00466 
00467     /* Find audio device */
00468     if( p_sys->fd_audio < 0 )
00469     {
00470         if( !p_sys->psz_adev || !*p_sys->psz_adev )
00471         {
00472             if( p_sys->psz_adev ) free( p_sys->psz_adev );
00473             p_sys->psz_adev = var_CreateGetString( p_demux, "v4l-adev" );;
00474         }
00475 
00476         if( p_sys->psz_adev && *p_sys->psz_adev )
00477         {
00478             p_sys->fd_audio = OpenAudioDev( p_demux, p_sys->psz_adev );
00479         }
00480     }
00481 
00482     if( p_sys->fd_video < 0 && p_sys->fd_audio < 0 )
00483     {
00484         Close( p_this );
00485         return VLC_EGENERIC;
00486     }
00487 
00488     msg_Dbg( p_demux, "v4l grabbing started" );
00489 
00490     /* Declare elementary streams */
00491     if( p_sys->fd_video >= 0 )
00492     {
00493         es_format_t fmt;
00494         es_format_Init( &fmt, VIDEO_ES, p_sys->i_fourcc );
00495         fmt.video.i_width  = p_sys->i_width;
00496         fmt.video.i_height = p_sys->i_height;
00497         fmt.video.i_aspect = 4 * VOUT_ASPECT_FACTOR / 3;
00498 
00499         /* Setup rgb mask for RGB formats */
00500         if( p_sys->i_fourcc == VLC_FOURCC('R','V','2','4') )
00501         {
00502             /* This is in BGR format */
00503             fmt.video.i_bmask = 0x00ff0000;
00504             fmt.video.i_gmask = 0x0000ff00;
00505             fmt.video.i_rmask = 0x000000ff;
00506         }
00507 
00508         msg_Dbg( p_demux, "added new video es %4.4s %dx%d",
00509                  (char*)&fmt.i_codec, fmt.video.i_width, fmt.video.i_height );
00510         p_sys->p_es_video = es_out_Add( p_demux->out, &fmt );
00511     }
00512 
00513     if( p_sys->fd_audio >= 0 )
00514     {
00515         es_format_t fmt;
00516         es_format_Init( &fmt, AUDIO_ES, VLC_FOURCC('a','r','a','w') );
00517 
00518         fmt.audio.i_channels = p_sys->b_stereo ? 2 : 1;
00519         fmt.audio.i_rate = p_sys->i_sample_rate;
00520         fmt.audio.i_bitspersample = 16; // FIXME ?
00521         fmt.audio.i_blockalign = fmt.audio.i_channels *
00522             fmt.audio.i_bitspersample / 8;
00523         fmt.i_bitrate = fmt.audio.i_channels * fmt.audio.i_rate *
00524             fmt.audio.i_bitspersample;
00525 
00526         msg_Dbg( p_demux, "new audio es %d channels %dHz",
00527                  fmt.audio.i_channels, fmt.audio.i_rate );
00528 
00529         p_sys->p_es_audio = es_out_Add( p_demux->out, &fmt );
00530     }
00531 
00532     /* Update default_pts to a suitable value for access */
00533     var_Create( p_demux, "v4l-caching", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
00534 
00535     return VLC_SUCCESS;
00536 }
00537 
00538 /*****************************************************************************
00539  * Close: close device, free resources
00540  *****************************************************************************/
00541 static void Close( vlc_object_t *p_this )
00542 {
00543     demux_t     *p_demux = (demux_t *)p_this;
00544     demux_sys_t *p_sys   = p_demux->p_sys;
00545 
00546     if( p_sys->psz_device ) free( p_sys->psz_device );
00547     if( p_sys->psz_vdev )   free( p_sys->psz_vdev );
00548     if( p_sys->psz_adev )   free( p_sys->psz_adev );
00549     if( p_sys->fd_video >= 0 ) close( p_sys->fd_video );
00550     if( p_sys->fd_audio >= 0 ) close( p_sys->fd_audio );
00551     if( p_sys->p_block_audio ) block_Release( p_sys->p_block_audio );
00552 
00553     if( p_sys->b_mjpeg )
00554     {
00555         int i_noframe = -1;
00556         ioctl( p_sys->fd_video, MJPIOC_QBUF_CAPT, &i_noframe );
00557     }
00558 
00559     if( p_sys->p_video_mmap && p_sys->p_video_mmap != MAP_FAILED )
00560     {
00561         if( p_sys->b_mjpeg )
00562             munmap( p_sys->p_video_mmap, p_sys->mjpeg_buffers.size *
00563                     p_sys->mjpeg_buffers.count );
00564         else
00565             munmap( p_sys->p_video_mmap, p_sys->vid_mbuf.size );
00566     }
00567 
00568     free( p_sys );
00569 }
00570 
00571 /*****************************************************************************
00572  * Control:
00573  *****************************************************************************/
00574 static int Control( demux_t *p_demux, int i_query, va_list args )
00575 {
00576     vlc_bool_t *pb;
00577     int64_t    *pi64;
00578 
00579     switch( i_query )
00580     {
00581         /* Special for access_demux */
00582         case DEMUX_CAN_PAUSE:
00583         case DEMUX_SET_PAUSE_STATE:
00584         case DEMUX_CAN_CONTROL_PACE:
00585             pb = (vlc_bool_t*)va_arg( args, vlc_bool_t * );
00586             *pb = VLC_FALSE;
00587             return VLC_SUCCESS;
00588 
00589         case DEMUX_GET_PTS_DELAY:
00590             pi64 = (int64_t*)va_arg( args, int64_t * );
00591             *pi64 = (int64_t)var_GetInteger( p_demux, "v4l-caching" ) * 1000;
00592             return VLC_SUCCESS;
00593 
00594         case DEMUX_GET_TIME:
00595             pi64 = (int64_t*)va_arg( args, int64_t * );
00596             *pi64 = mdate();
00597             return VLC_SUCCESS;
00598 
00599         /* TODO implement others */
00600         default:
00601             return VLC_EGENERIC;
00602     }
00603 
00604     return VLC_EGENERIC;
00605 }
00606 
00607 /*****************************************************************************
00608  * Demux:
00609  *****************************************************************************/
00610 static int Demux( demux_t *p_demux )
00611 {
00612     demux_sys_t *p_sys = p_demux->p_sys;
00613     es_out_id_t  *p_es = p_sys->p_es_audio;
00614     block_t *p_block = NULL;
00615 
00616     /* Try grabbing audio frames first */
00617     if( p_sys->fd_audio < 0 || !( p_block = GrabAudio( p_demux ) ) )
00618     {
00619         /* Try grabbing video frame */
00620         p_es = p_sys->p_es_video;
00621         if( p_sys->fd_video > 0 ) p_block = GrabVideo( p_demux );
00622     }
00623 
00624     if( !p_block )
00625     {
00626         /* Sleep so we do not consume all the cpu, 10ms seems
00627          * like a good value (100fps) */
00628         msleep( 10000 );
00629         return 1;
00630     }
00631 
00632     es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_block->i_pts );
00633     es_out_Send( p_demux->out, p_es, p_block );
00634 
00635     return 1;
00636 }
00637 
00638 /*****************************************************************************
00639  * ParseMRL: parse the options contained in the MRL
00640  *****************************************************************************/
00641 static void ParseMRL( demux_t *p_demux )
00642 {
00643     demux_sys_t *p_sys = p_demux->p_sys;
00644 
00645     char *psz_dup = strdup( p_demux->psz_path );
00646     char *psz_parser = psz_dup;
00647 
00648     while( *psz_parser && *psz_parser != ':' )
00649     {
00650         psz_parser++;
00651     }
00652 
00653     if( *psz_parser == ':' )
00654     {
00655         /* read options */
00656         for( ;; )
00657         {
00658             *psz_parser++ = '\0';
00659             if( !strncmp( psz_parser, "channel=", strlen( "channel=" ) ) )
00660             {
00661                 p_sys->i_channel = strtol( psz_parser + strlen( "channel=" ),
00662                                            &psz_parser, 0 );
00663             }
00664             else if( !strncmp( psz_parser, "norm=", strlen( "norm=" ) ) )
00665             {
00666                 psz_parser += strlen( "norm=" );
00667                 if( !strncmp( psz_parser, "pal", strlen( "pal" ) ) )
00668                 {
00669                     p_sys->i_norm = VIDEO_MODE_PAL;
00670                     psz_parser += strlen( "pal" );
00671                 }
00672                 else if( !strncmp( psz_parser, "ntsc", strlen( "ntsc" ) ) )
00673                 {
00674                     p_sys->i_norm = VIDEO_MODE_NTSC;
00675                     psz_parser += strlen( "ntsc" );
00676                 }
00677                 else if( !strncmp( psz_parser, "secam", strlen( "secam" ) ) )
00678                 {
00679                     p_sys->i_norm = VIDEO_MODE_SECAM;
00680                     psz_parser += strlen( "secam" );
00681                 }
00682                 else if( !strncmp( psz_parser, "auto", strlen( "auto" ) ) )
00683                 {
00684                     p_sys->i_norm = VIDEO_MODE_AUTO;
00685                     psz_parser += strlen( "auto" );
00686                 }
00687                 else
00688                 {
00689                     p_sys->i_norm = strtol( psz_parser, &psz_parser, 0 );
00690                 }
00691             }
00692             else if( !strncmp( psz_parser, "frequency=",
00693                                strlen( "frequency=" ) ) )
00694             {
00695                 p_sys->i_frequency =
00696                     strtol( psz_parser + strlen( "frequency=" ),
00697                             &psz_parser, 0 );
00698                 if( p_sys->i_frequency < 30000 )
00699                 {
00700                     msg_Warn( p_demux, "v4l syntax has changed : "
00701                               "'frequency' is now channel frequency in kHz");
00702                 }
00703             }
00704             else if( !strncmp( psz_parser, "audio=", strlen( "audio=" ) ) )
00705             {
00706                 p_sys->i_audio = strtol( psz_parser + strlen( "audio=" ),
00707                                          &psz_parser, 0 );
00708             }
00709             else if( !strncmp( psz_parser, "size=", strlen( "size=" ) ) )
00710             {
00711                 psz_parser += strlen( "size=" );
00712                 if( !strncmp( psz_parser, "subqcif", strlen( "subqcif" ) ) )
00713                 {
00714                     p_sys->i_width  = 128;
00715                     p_sys->i_height = 96;
00716                 }
00717                 else if( !strncmp( psz_parser, "qsif", strlen( "qsif" ) ) )
00718                 {
00719                     p_sys->i_width  = 160;
00720                     p_sys->i_height = 120;
00721                 }
00722                 else if( !strncmp( psz_parser, "qcif", strlen( "qcif" ) ) )
00723                 {
00724                     p_sys->i_width  = 176;
00725                     p_sys->i_height = 144;
00726                 }
00727                 else if( !strncmp( psz_parser, "sif", strlen( "sif" ) ) )
00728                 {
00729                     p_sys->i_width  = 320;
00730                     p_sys->i_height = 244;
00731                 }
00732                 else if( !strncmp( psz_parser, "cif", strlen( "cif" ) ) )
00733                 {
00734                     p_sys->i_width  = 352;
00735                     p_sys->i_height = 288;
00736                 }
00737                 else if( !strncmp( psz_parser, "vga", strlen( "vga" ) ) )
00738                 {
00739                     p_sys->i_width  = 640;
00740                     p_sys->i_height = 480;
00741                 }
00742                 else
00743                 {
00744                     /* widthxheight */
00745                     p_sys->i_width = strtol( psz_parser, &psz_parser, 0 );
00746                     if( *psz_parser == 'x' || *psz_parser == 'X')
00747                     {
00748                         p_sys->i_height = strtol( psz_parser + 1,
00749                                                   &psz_parser, 0 );
00750                     }
00751                     msg_Dbg( p_demux, "WxH %dx%d", p_sys->i_width,
00752                              p_sys->i_height );
00753                 }
00754             }
00755             else if( !strncmp( psz_parser, "brightness=", strlen( "brightness=" ) ) )
00756             {
00757                 p_sys->i_brightness = strtol( psz_parser + strlen( "brightness=" ),
00758                                               &psz_parser, 0 );
00759             }
00760             else if( !strncmp( psz_parser, "colour=", strlen( "colour=" ) ) )
00761             {
00762                 p_sys->i_colour = strtol( psz_parser + strlen( "colour=" ),
00763                                           &psz_parser, 0 );
00764             }
00765             else if( !strncmp( psz_parser, "hue=", strlen( "hue=" ) ) )
00766             {
00767                 p_sys->i_hue = strtol( psz_parser + strlen( "hue=" ), 
00768                                        &psz_parser, 0 );
00769             }
00770             else if( !strncmp( psz_parser, "contrast=", strlen( "contrast=" ) ) )
00771             {
00772                 p_sys->i_contrast = strtol( psz_parser + strlen( "contrast=" ),
00773                                             &psz_parser, 0 );
00774             }
00775             else if( !strncmp( psz_parser, "tuner=", strlen( "tuner=" ) ) )
00776             {
00777                 p_sys->i_tuner = strtol( psz_parser + strlen( "tuner=" ),
00778                                          &psz_parser, 0 );
00779             }
00780             else if( !strncmp( psz_parser, "adev=", strlen( "adev=" ) ) )
00781             {
00782                 int  i_len;
00783 
00784                 psz_parser += strlen( "adev=" );
00785                 if( strchr( psz_parser, ':' ) )
00786                 {
00787                     i_len = strchr( psz_parser, ':' ) - psz_parser;
00788                 }
00789                 else
00790                 {
00791                     i_len = strlen( psz_parser );
00792                 }
00793 
00794                 p_sys->psz_adev = strndup( psz_parser, i_len );
00795 
00796                 psz_parser += i_len;
00797             }
00798             else if( !strncmp( psz_parser, "samplerate=",
00799                                strlen( "samplerate=" ) ) )
00800             {
00801                 p_sys->i_sample_rate =
00802                     strtol( psz_parser + strlen( "samplerate=" ),
00803                             &psz_parser, 0 );
00804             }
00805             else if( !strncmp( psz_parser, "stereo", strlen( "stereo" ) ) )
00806             {
00807                 psz_parser += strlen( "stereo" );
00808 
00809                 p_sys->b_stereo = VLC_TRUE;
00810             }
00811             else if( !strncmp( psz_parser, "mono", strlen( "mono" ) ) )
00812             {
00813                 psz_parser += strlen( "mono" );
00814 
00815                 p_sys->b_stereo = VLC_FALSE;
00816             }
00817             else if( !strncmp( psz_parser, "mjpeg", strlen( "mjpeg" ) ) )
00818             {
00819                 psz_parser += strlen( "mjpeg" );
00820 
00821                 p_sys->b_mjpeg = VLC_TRUE;
00822             }
00823             else if( !strncmp( psz_parser, "decimation=",
00824                         strlen( "decimation=" ) ) )
00825             {
00826                 p_sys->i_decimation =
00827                     strtol( psz_parser + strlen( "decimation=" ),
00828                             &psz_parser, 0 );
00829             }
00830             else if( !strncmp( psz_parser, "quality=",
00831                         strlen( "quality=" ) ) )
00832             {
00833                 p_sys->i_quality =
00834                     strtol( psz_parser + strlen( "quality=" ),
00835                             &psz_parser, 0 );
00836             }
00837             else if( !strncmp( psz_parser, "fps=", strlen( "fps=" ) ) )
00838             {
00839                 p_sys->f_fps = strtof( psz_parser + strlen( "fps=" ),
00840                                        &psz_parser );
00841             }
00842             else
00843             {
00844                 msg_Warn( p_demux, "unknown option" );
00845             }
00846 
00847             while( *psz_parser && *psz_parser != ':' )
00848             {
00849                 psz_parser++;
00850             }
00851 
00852             if( *psz_parser == '\0' )
00853             {
00854                 break;
00855             }
00856         }
00857     }
00858 
00859     if( *psz_dup )
00860     {
00861         p_sys->psz_device = strdup( psz_dup );
00862     }
00863     if( psz_dup ) free( psz_dup );
00864 }
00865 
00866 /*****************************************************************************
00867  * OpenVideoDev:
00868  *****************************************************************************/
00869 static int OpenVideoDev( demux_t *p_demux, char *psz_device )
00870 {
00871     demux_sys_t *p_sys = p_demux->p_sys;
00872     int i_fd;
00873 
00874     struct video_channel vid_channel;
00875     struct mjpeg_params mjpeg;
00876     int i;
00877 
00878     if( ( i_fd = open( psz_device, O_RDWR ) ) < 0 )
00879     {
00880         msg_Err( p_demux, "cannot open device (%s)", strerror( errno ) );
00881         goto vdev_failed;
00882     }
00883 
00884     if( ioctl( i_fd, VIDIOCGCAP, &p_sys->vid_cap ) < 0 )
00885     {
00886         msg_Err( p_demux, "cannot get capabilities (%s)", strerror( errno ) );
00887         goto vdev_failed;
00888     }
00889 
00890     msg_Dbg( p_demux,
00891              "V4L device %s %d channels %d audios %d < w < %d %d < h < %d",
00892              p_sys->vid_cap.name,
00893              p_sys->vid_cap.channels,
00894              p_sys->vid_cap.audios,
00895              p_sys->vid_cap.minwidth,  p_sys->vid_cap.maxwidth,
00896              p_sys->vid_cap.minheight, p_sys->vid_cap.maxheight );
00897 
00898     if( p_sys->i_channel < 0 || p_sys->i_channel >= p_sys->vid_cap.channels )
00899     {
00900         msg_Dbg( p_demux, "invalid channel, falling back on channel 0" );
00901         p_sys->i_channel = 0;
00902     }
00903     if( p_sys->i_audio >= p_sys->vid_cap.audios )
00904     {
00905         msg_Dbg( p_demux, "invalid audio, falling back with no audio" );
00906         p_sys->i_audio = -1;
00907     }
00908 
00909     if( p_sys->i_width < p_sys->vid_cap.minwidth ||
00910         p_sys->i_width > p_sys->vid_cap.maxwidth )
00911     {
00912         msg_Dbg( p_demux, "invalid width %i", p_sys->i_width );
00913         p_sys->i_width = 0;
00914     }
00915     if( p_sys->i_height < p_sys->vid_cap.minheight ||
00916         p_sys->i_height > p_sys->vid_cap.maxheight )
00917     {
00918         msg_Dbg( p_demux, "invalid height %i", p_sys->i_height );
00919         p_sys->i_height = 0;
00920     }
00921 
00922     if( !( p_sys->vid_cap.type & VID_TYPE_CAPTURE ) )
00923     {
00924         msg_Err( p_demux, "cannot grab" );
00925         goto vdev_failed;
00926     }
00927 
00928     vid_channel.channel = p_sys->i_channel;
00929     if( ioctl( i_fd, VIDIOCGCHAN, &vid_channel ) < 0 )
00930     {
00931         msg_Err( p_demux, "cannot get channel infos (%s)",
00932                           strerror( errno ) );
00933         goto vdev_failed;
00934     }
00935     msg_Dbg( p_demux,
00936              "setting channel %s(%d) %d tuners flags=0x%x type=0x%x norm=0x%x",
00937              vid_channel.name, vid_channel.channel, vid_channel.tuners,
00938              vid_channel.flags, vid_channel.type, vid_channel.norm );
00939 
00940     if( p_sys->i_tuner >= vid_channel.tuners )
00941     {
00942         msg_Dbg( p_demux, "invalid tuner, falling back on tuner 0" );
00943         p_sys->i_tuner = 0;
00944     }
00945 
00946     vid_channel.norm = p_sys->i_norm;
00947     if( ioctl( i_fd, VIDIOCSCHAN, &vid_channel ) < 0 )
00948     {
00949         msg_Err( p_demux, "cannot set channel (%s)", strerror( errno ) );
00950         goto vdev_failed;
00951     }
00952 
00953     if( vid_channel.flags & VIDEO_VC_TUNER )
00954     {
00955 
00956         /* set tuner */
00957 #if 0
00958         struct video_tuner vid_tuner;
00959         if( p_sys->i_tuner >= 0 )
00960         {
00961             vid_tuner.tuner = p_sys->i_tuner;
00962             if( ioctl( i_fd, VIDIOCGTUNER, &vid_tuner ) < 0 )
00963             {
00964                 msg_Err( p_demux, "cannot get tuner (%s)", strerror( errno ) );
00965                 goto vdev_failed;
00966             }
00967             msg_Dbg( p_demux, "tuner %s low=%d high=%d, flags=0x%x "
00968                      "mode=0x%x signal=0x%x",
00969                      vid_tuner.name, vid_tuner.rangelow, vid_tuner.rangehigh,
00970                      vid_tuner.flags, vid_tuner.mode, vid_tuner.signal );
00971 
00972             msg_Dbg( p_demux, "setting tuner %s (%d)",
00973                      vid_tuner.name, vid_tuner.tuner );
00974 
00975             /* FIXME FIXME to be checked FIXME FIXME */
00976             //vid_tuner.mode = p_sys->i_norm;
00977             if( ioctl( i_fd, VIDIOCSTUNER, &vid_tuner ) < 0 )
00978             {
00979                 msg_Err( p_demux, "cannot set tuner (%s)", strerror( errno ) );
00980                 goto vdev_failed;
00981             }
00982         }
00983 #endif
00984 
00985         /* Show a warning if frequency is < than 30000.
00986          * User is certainly usint old syntax. */
00987 
00988 
00989         /* set frequency */
00990         if( p_sys->i_frequency >= 0 )
00991         {
00992             int driver_frequency = p_sys->i_frequency * 16 /1000;
00993             if( ioctl( i_fd, VIDIOCSFREQ, &driver_frequency ) < 0 )
00994             {
00995                 msg_Err( p_demux, "cannot set frequency (%s)",
00996                                   strerror( errno ) );
00997                 goto vdev_failed;
00998             }
00999             msg_Dbg( p_demux, "frequency %d (%d)", p_sys->i_frequency,
01000                                                    driver_frequency );
01001         }
01002     }
01003 
01004     /* set audio */
01005     if( vid_channel.flags & VIDEO_VC_AUDIO )
01006     {
01007         struct video_audio      vid_audio;
01008 
01009         /* XXX TODO volume, balance, ... */
01010         if( p_sys->i_audio >= 0 )
01011         {
01012             vid_audio.audio = p_sys->i_audio;
01013             if( ioctl( i_fd, VIDIOCGAUDIO, &vid_audio ) < 0 )
01014             {
01015                 msg_Err( p_demux, "cannot get audio (%s)", strerror( errno ) );
01016                 goto vdev_failed;
01017             }
01018 
01019             /* unmute audio */
01020             vid_audio.flags &= ~VIDEO_AUDIO_MUTE;
01021 
01022             if( ioctl( i_fd, VIDIOCSAUDIO, &vid_audio ) < 0 )
01023             {
01024                 msg_Err( p_demux, "cannot set audio (%s)", strerror( errno ) );
01025                 goto vdev_failed;
01026             }
01027         }
01028 
01029     }
01030 
01031     /* establish basic params with input and norm before feeling width
01032      * or height */
01033     if( p_sys->b_mjpeg )
01034     {
01035         struct quicktime_mjpeg_app1 *p_app1;
01036         int32_t i_offset;
01037 
01038         if( ioctl( i_fd, MJPIOC_G_PARAMS, &mjpeg ) < 0 )
01039         {
01040             msg_Err( p_demux, "cannot get mjpeg params (%s)",
01041                               strerror( errno ) );
01042             goto vdev_failed;
01043         }
01044         mjpeg.input = p_sys->i_channel;
01045         mjpeg.norm  = p_sys->i_norm;
01046         mjpeg.decimation = p_sys->i_decimation;
01047 
01048         if( p_sys->i_width )
01049             mjpeg.img_width = p_sys->i_width / p_sys->i_decimation;
01050         if( p_sys->i_height )
01051             mjpeg.img_height = p_sys->i_height / p_sys->i_decimation;
01052 
01053         /* establish Quicktime APP1 marker while we are here */
01054         mjpeg.APPn = 1;
01055         mjpeg.APP_len = 40;
01056 
01057         /* aligned */
01058         p_app1 = (struct quicktime_mjpeg_app1 *)mjpeg.APP_data;
01059         p_app1->i_reserved = 0;
01060         p_app1->i_tag = VLC_FOURCC( 'm','j','p','g' );
01061         p_app1->i_field_size = 0;
01062         p_app1->i_padded_field_size = 0;
01063         p_app1->i_next_field = 0;
01064         /* XXX WARNING XXX */
01065         /* these's nothing magic about these values.  We are dangerously
01066          * assuming the encoder card is encoding mjpeg-a and is not throwing
01067          * in marker tags we aren't expecting.  It's bad enough we have to
01068          * search through the jpeg output for every frame we grab just to
01069          * find the first field's end marker, so we take this risk to boost
01070          * performance.
01071          * This is really something the driver could do for us because this
01072          * does conform to standards outside of Apple Quicktime.
01073          */
01074         i_offset = 0x2e;
01075         p_app1->i_DQT_offset = hton32( i_offset );
01076         i_offset = 0xb4;
01077         p_app1->i_DHT_offset = hton32( i_offset );
01078         i_offset = 0x258;
01079         p_app1->i_SOF_offset = hton32( i_offset );
01080         i_offset = 0x26b;
01081         p_app1->i_SOS_offset = hton32( i_offset );
01082         i_offset = 0x279;
01083         p_app1->i_data_offset = hton32( i_offset );
01084 
01085         /* SOF and SOS aren't specified by the mjpeg API because they aren't
01086          * optional.  They will be present in the output. */
01087         mjpeg.jpeg_markers = JPEG_MARKER_DHT | JPEG_MARKER_DQT;
01088 
01089         if( ioctl( i_fd, MJPIOC_S_PARAMS, &mjpeg ) < 0 )
01090         {
01091             msg_Err( p_demux, "cannot set mjpeg params (%s)",
01092                               strerror( errno ) );
01093             goto vdev_failed;
01094         }
01095 
01096         p_sys->i_width = mjpeg.img_width * mjpeg.HorDcm;
01097         p_sys->i_height = mjpeg.img_height * mjpeg.VerDcm *
01098             mjpeg.field_per_buff;
01099     }
01100 
01101     /* fix width/height */
01102     if( !p_sys->b_mjpeg && ( p_sys->i_width == 0 || p_sys->i_height == 0 ) )
01103     {
01104         struct video_window vid_win;
01105 
01106         if( ioctl( i_fd, VIDIOCGWIN, &vid_win ) < 0 )
01107         {
01108             msg_Err( p_demux, "cannot get win (%s)", strerror( errno ) );
01109             goto vdev_failed;
01110         }
01111         p_sys->i_width  = vid_win.width;
01112         p_sys->i_height = vid_win.height;
01113 
01114         if( !p_sys->i_width || !p_sys->i_height )
01115         {
01116             p_sys->i_width = p_sys->vid_cap.maxwidth;
01117             p_sys->i_height = p_sys->vid_cap.maxheight;
01118         }
01119 
01120         if( !p_sys->i_width || !p_sys->i_height )
01121         {
01122             msg_Err( p_demux, "invalid video size (%ix%i)",
01123                      p_sys->i_width, p_sys->i_height );
01124             goto vdev_failed;
01125         }
01126 
01127         msg_Dbg( p_demux, "will use %dx%d", p_sys->i_width, p_sys->i_height );
01128     }
01129 
01130     if( !p_sys->b_mjpeg )
01131     {
01132         /* set hue/color/.. */
01133         if( ioctl( i_fd, VIDIOCGPICT, &p_sys->vid_picture ) == 0 )
01134         {
01135             struct video_picture vid_picture = p_sys->vid_picture;
01136 
01137             if( p_sys->i_brightness >= 0 && p_sys->i_brightness < 65536 )
01138             {
01139                 vid_picture.brightness = p_sys->i_brightness;
01140             }
01141             if( p_sys->i_colour >= 0 && p_sys->i_colour < 65536 )
01142             {
01143                 vid_picture.colour = p_sys->i_colour;
01144             }
01145             if( p_sys->i_hue >= 0 && p_sys->i_hue < 65536 )
01146             {
01147                 vid_picture.hue = p_sys->i_hue;
01148             }
01149             if( p_sys->i_contrast  >= 0 && p_sys->i_contrast < 65536 )
01150             {
01151                 vid_picture.contrast = p_sys->i_contrast;
01152             }
01153             if( ioctl( i_fd, VIDIOCSPICT, &vid_picture ) == 0 )
01154             {
01155                 msg_Dbg( p_demux, "v4l device uses brightness: %d",
01156                          vid_picture.brightness );
01157                 msg_Dbg( p_demux, "v4l device uses colour: %d",
01158                          vid_picture.colour );
01159                 msg_Dbg( p_demux, "v4l device uses hue: %d", vid_picture.hue );
01160                 msg_Dbg( p_demux, "v4l device uses contrast: %d",
01161                          vid_picture.contrast );
01162                 p_sys->vid_picture = vid_picture;
01163             }
01164         }
01165 
01166         /* Find out video format used by device */
01167         if( ioctl( i_fd, VIDIOCGPICT, &p_sys->vid_picture ) == 0 )
01168         {
01169             struct video_picture vid_picture = p_sys->vid_picture;
01170             char *psz;
01171             int i;
01172 
01173             vid_picture.palette = 0;
01174             p_sys->i_fourcc = 0;
01175 
01176             psz = var_CreateGetString( p_demux, "v4l-chroma" );
01177             if( strlen( psz ) >= 4 )
01178             {
01179                 int i_chroma = VLC_FOURCC( psz[0], psz[1], psz[2], psz[3] );
01180 
01181                 /* Find out v4l chroma code */
01182                 for( i = 0; v4lchroma_to_fourcc[i].i_v4l != 0; i++ )
01183                 {
01184                     if( v4lchroma_to_fourcc[i].i_fourcc == i_chroma )
01185                     {
01186                         vid_picture.palette = v4lchroma_to_fourcc[i].i_v4l;
01187                         break;
01188                     }
01189                 }
01190             }
01191             free( psz );
01192 
01193             if( vid_picture.palette &&
01194                 !ioctl( i_fd, VIDIOCSPICT, &vid_picture ) )
01195             {
01196                 p_sys->vid_picture = vid_picture;
01197             }
01198             else
01199             {
01200                 /* Try to set the format to something easy to encode */
01201                 vid_picture.palette = VIDEO_PALETTE_YUV420P;
01202                 if( ioctl( i_fd, VIDIOCSPICT, &vid_picture ) == 0 )
01203                 {
01204                     p_sys->vid_picture = vid_picture;
01205                 }
01206                 else
01207                 {
01208                     vid_picture.palette = VIDEO_PALETTE_YUV422P;
01209                     if( ioctl( i_fd, VIDIOCSPICT, &vid_picture ) == 0 )
01210                     {
01211                         p_sys->vid_picture = vid_picture;
01212                     }
01213                 }
01214             }
01215 
01216             /* Find out final format */
01217             for( i = 0; v4lchroma_to_fourcc[i].i_v4l != 0; i++ )
01218             {
01219                 if( v4lchroma_to_fourcc[i].i_v4l == p_sys->vid_picture.palette)
01220                 {
01221                     p_sys->i_fourcc = v4lchroma_to_fourcc[i].i_fourcc;
01222                     break;
01223                 }
01224             }
01225         }
01226         else
01227         {
01228             msg_Err( p_demux, "ioctl VIDIOCGPICT failed" );
01229             goto vdev_failed;
01230         }
01231     }
01232 
01233     if( p_sys->b_mjpeg )
01234     {
01235         int i;
01236 
01237         p_sys->mjpeg_buffers.count = 8;
01238         p_sys->mjpeg_buffers.size = MJPEG_BUFFER_SIZE;
01239 
01240         if( ioctl( i_fd, MJPIOC_REQBUFS, &p_sys->mjpeg_buffers ) < 0 )
01241         {
01242             msg_Err( p_demux, "mmap unsupported" );
01243             goto vdev_failed;
01244         }
01245 
01246         p_sys->p_video_mmap = mmap( 0,
01247                 p_sys->mjpeg_buffers.size * p_sys->mjpeg_buffers.count,
01248                 PROT_READ | PROT_WRITE, MAP_SHARED, i_fd, 0 );
01249         if( p_sys->p_video_mmap == MAP_FAILED )
01250         {
01251             msg_Err( p_demux, "mmap failed" );
01252             goto vdev_failed;
01253         }
01254 
01255         p_sys->i_fourcc  = VLC_FOURCC( 'm','j','p','g' );
01256         p_sys->i_frame_pos = -1;
01257 
01258         /* queue up all the frames */
01259         for( i = 0; i < (int)p_sys->mjpeg_buffers.count; i++ )
01260         {
01261             if( ioctl( i_fd, MJPIOC_QBUF_CAPT, &i ) < 0 )
01262             {
01263                 msg_Err( p_demux, "unable to queue frame" );
01264                 goto vdev_failed;
01265             }
01266         }
01267     }
01268     else
01269     {
01270         /* Fill in picture_t fields */
01271         vout_InitPicture( VLC_OBJECT(p_demux), &p_sys->pic, p_sys->i_fourcc,
01272                           p_sys->i_width, p_sys->i_height, p_sys->i_width *
01273                           VOUT_ASPECT_FACTOR / p_sys->i_height );
01274         if( !p_sys->pic.i_planes )
01275         {
01276             msg_Err( p_demux, "unsupported chroma" );
01277             goto vdev_failed;
01278         }
01279         p_sys->i_video_frame_size = 0;
01280         for( i = 0; i < p_sys->pic.i_planes; i++ )
01281         {
01282             p_sys->i_video_frame_size += p_sys->pic.p[i].i_visible_lines *
01283               p_sys->pic.p[i].i_visible_pitch;
01284         }
01285 
01286         msg_Dbg( p_demux, "v4l device uses frame size: %i",
01287                  p_sys->i_video_frame_size );
01288         msg_Dbg( p_demux, "v4l device uses chroma: %4.4s",
01289                 (char*)&p_sys->i_fourcc );
01290 
01291         /* Allocate mmap buffer */
01292         if( ioctl( i_fd, VIDIOCGMBUF, &p_sys->vid_mbuf ) < 0 )
01293         {
01294             msg_Err( p_demux, "mmap unsupported" );
01295             goto vdev_failed;
01296         }
01297 
01298         p_sys->p_video_mmap = mmap( 0, p_sys->vid_mbuf.size,
01299                                     PROT_READ|PROT_WRITE, MAP_SHARED,
01300                                     i_fd, 0 );
01301         if( p_sys->p_video_mmap == MAP_FAILED )
01302         {
01303             /* FIXME -> normal read */
01304             msg_Err( p_demux, "mmap failed" );
01305             goto vdev_failed;
01306         }
01307 
01308         /* init grabbing */
01309         p_sys->vid_mmap.frame  = 0;
01310         p_sys->vid_mmap.width  = p_sys->i_width;
01311         p_sys->vid_mmap.height = p_sys->i_height;
01312         p_sys->vid_mmap.format = p_sys->vid_picture.palette;
01313         if( ioctl( i_fd, VIDIOCMCAPTURE, &p_sys->vid_mmap ) < 0 )
01314         {
01315             msg_Warn( p_demux, "%4.4s refused", (char*)&p_sys->i_fourcc );
01316             msg_Err( p_demux, "chroma selection failed" );
01317             goto vdev_failed;
01318         }
01319     }
01320     return i_fd;
01321 
01322 vdev_failed:
01323 
01324     if( i_fd >= 0 ) close( i_fd );
01325     return -1;
01326 }
01327 
01328 /*****************************************************************************
01329  * OpenAudioDev:
01330  *****************************************************************************/
01331 static int OpenAudioDev( demux_t *p_demux, char *psz_device )
01332 {
01333     demux_sys_t *p_sys = p_demux->p_sys;
01334     int i_fd, i_format;
01335 
01336     if( (i_fd = open( psz_device, O_RDONLY | O_NONBLOCK )) < 0 )
01337     {
01338         msg_Err( p_demux, "cannot open audio device (%s)", strerror( errno ) );
01339         goto adev_fail;
01340     }
01341 
01342     i_format = AFMT_S16_LE;
01343     if( ioctl( i_fd, SNDCTL_DSP_SETFMT, &i_format ) < 0
01344         || i_format != AFMT_S16_LE )
01345     {
01346         msg_Err( p_demux, "cannot set audio format (16b little endian) "
01347                  "(%s)", strerror( errno ) );
01348         goto adev_fail;
01349     }
01350 
01351     if( ioctl( i_fd, SNDCTL_DSP_STEREO,
01352                &p_sys->b_stereo ) < 0 )
01353     {
01354         msg_Err( p_demux, "cannot set audio channels count (%s)",
01355                  strerror( errno ) );
01356         goto adev_fail;
01357     }
01358 
01359     if( ioctl( i_fd, SNDCTL_DSP_SPEED,
01360                &p_sys->i_sample_rate ) < 0 )
01361     {
01362         msg_Err( p_demux, "cannot set audio sample rate (%s)",
01363                  strerror( errno ) );
01364         goto adev_fail;
01365     }
01366 
01367     msg_Dbg( p_demux, "openened adev=`%s' %s %dHz",
01368              psz_device, p_sys->b_stereo ? "stereo" : "mono",
01369              p_sys->i_sample_rate );
01370 
01371     p_sys->i_audio_max_frame_size = 6 * 1024;
01372 
01373     return i_fd;
01374 
01375  adev_fail:
01376 
01377     if( i_fd >= 0 ) close( i_fd );
01378     return -1;
01379 }
01380 
01381 /*****************************************************************************
01382  * GrabAudio: grab audio
01383  *****************************************************************************/
01384 static block_t *GrabAudio( demux_t *p_demux )
01385 {
01386     demux_sys_t *p_sys = p_demux->p_sys;
01387     struct audio_buf_info buf_info;
01388     int i_read, i_correct;
01389     block_t *p_block;
01390 
01391     if( p_sys->p_block_audio ) p_block = p_sys->p_block_audio;
01392     else p_block = block_New( p_demux, p_sys->i_audio_max_frame_size );
01393 
01394     if( !p_block )
01395     {
01396         msg_Warn( p_demux, "cannot get block" );
01397         return 0;
01398     }
01399 
01400     p_sys->p_block_audio = p_block;
01401 
01402     i_read = read( p_sys->fd_audio, p_block->p_buffer,
01403                    p_sys->i_audio_max_frame_size );
01404 
01405     if( i_read <= 0 ) return 0;
01406 
01407     p_block->i_buffer = i_read;
01408     p_sys->p_block_audio = 0;
01409 
01410     /* Correct the date because of kernel buffering */
01411     i_correct = i_read;
01412     if( ioctl( p_sys->fd_audio, SNDCTL_DSP_GETISPACE, &buf_info ) == 0 )
01413     {
01414         i_correct += buf_info.bytes;
01415     }
01416 
01417     p_block->i_pts = p_block->i_dts =
01418         mdate() - I64C(1000000) * (mtime_t)i_correct /
01419         2 / ( p_sys->b_stereo ? 2 : 1) / p_sys->i_sample_rate;
01420 
01421     return p_block;
01422 }
01423 
01424 /*****************************************************************************
01425  * GrabVideo:
01426  *****************************************************************************/
01427 static uint8_t *GrabCapture( demux_t *p_demux )
01428 {
01429     demux_sys_t *p_sys = p_demux->p_sys;
01430     int i_captured_frame = p_sys->i_frame_pos;
01431 
01432     p_sys->vid_mmap.frame = (p_sys->i_frame_pos + 1) % p_sys->vid_mbuf.frames;
01433 
01434     while( ioctl( p_sys->fd_video, VIDIOCMCAPTURE, &p_sys->vid_mmap ) < 0 )
01435     {
01436         if( errno != EAGAIN )
01437         {
01438             msg_Err( p_demux, "failed capturing new frame" );
01439             return NULL;
01440         }
01441 
01442         if( p_demux->b_die )
01443         {
01444             return NULL;
01445         }
01446 
01447         msg_Dbg( p_demux, "grab failed, trying again" );
01448     }
01449 
01450     while( ioctl(p_sys->fd_video, VIDIOCSYNC, &p_sys->i_frame_pos) < 0 )
01451     {
01452         if( errno != EAGAIN && errno != EINTR )    
01453         {
01454             msg_Err( p_demux, "failed syncing new frame" );
01455             return NULL;
01456         }
01457     }
01458 
01459     p_sys->i_frame_pos = p_sys->vid_mmap.frame;
01460     /* leave i_video_frame_size alone */
01461     return p_sys->p_video_mmap + p_sys->vid_mbuf.offsets[i_captured_frame];
01462 }
01463 
01464 static uint8_t *GrabMJPEG( demux_t *p_demux )
01465 {
01466     demux_sys_t *p_sys = p_demux->p_sys;
01467     struct mjpeg_sync sync;
01468     uint8_t *p_frame, *p_field, *p;
01469     uint16_t tag;
01470     uint32_t i_size;
01471     struct quicktime_mjpeg_app1 *p_app1 = NULL;
01472 
01473     /* re-queue the last frame we sync'd */
01474     if( p_sys->i_frame_pos != -1 )
01475     {
01476         while( ioctl( p_sys->fd_video, MJPIOC_QBUF_CAPT,
01477                                        &p_sys->i_frame_pos ) < 0 )
01478         {
01479             if( errno != EAGAIN && errno != EINTR )
01480             {
01481                 msg_Err( p_demux, "failed capturing new frame" );
01482                 return NULL;
01483             }
01484         }
01485     }
01486 
01487     /* sync on the next frame */
01488     while( ioctl( p_sys->fd_video, MJPIOC_SYNC, &sync ) < 0 )
01489     {
01490         if( errno != EAGAIN && errno != EINTR )    
01491         {
01492             msg_Err( p_demux, "failed syncing new frame" );
01493             return NULL;
01494         }
01495     }
01496 
01497     p_sys->i_frame_pos = sync.frame;
01498     p_frame = p_sys->p_video_mmap + p_sys->mjpeg_buffers.size * sync.frame;
01499 
01500     /* p_frame now points to the data.  fix up the Quicktime APP1 marker */
01501     tag = 0xffd9;
01502     tag = hton16( tag );
01503     p_field = p_frame;
01504 
01505     /* look for EOI */
01506     p = memmem( p_field, sync.length, &tag, 2 );
01507 
01508     if( p )
01509     {
01510         p += 2; /* data immediately following EOI */
01511         /* UNALIGNED! */
01512         p_app1 = (struct quicktime_mjpeg_app1 *)(p_field + 6);
01513 
01514         i_size = ((uint32_t)(p - p_field));
01515         i_size = hton32( i_size );
01516         memcpy( &p_app1->i_field_size, &i_size, 4 );
01517 
01518         while( *p == 0xff && *(p+1) == 0xff )
01519             p++;
01520 
01521         i_size = ((uint32_t)(p - p_field));
01522         i_size = hton32( i_size );
01523         memcpy( &p_app1->i_padded_field_size, &i_size, 4 );
01524     }
01525 
01526     tag = 0xffd8;
01527     tag = hton16( tag );
01528     p_field = memmem( p, sync.length - (size_t)(p - p_frame), &tag, 2 );
01529 
01530     if( p_field )
01531     {
01532         i_size = (uint32_t)(p_field - p_frame);
01533         i_size = hton32( i_size );
01534         memcpy( &p_app1->i_next_field, &i_size, 4 );
01535 
01536         /* UNALIGNED! */
01537         p_app1 = (struct quicktime_mjpeg_app1 *)(p_field + 6);
01538         tag = 0xffd9;
01539         tag = hton16( tag );
01540         p = memmem( p_field, sync.length - (size_t)(p_field - p_frame),
01541                 &tag, 2 );
01542 
01543         if( !p )
01544         {
01545             /* sometimes the second field doesn't have the EOI.  just put it
01546              * there
01547              */
01548             p = p_frame + sync.length;
01549             memcpy( p, &tag, 2 );
01550             sync.length += 2;
01551         }
01552 
01553         p += 2;
01554         i_size = (uint32_t)(p - p_field);
01555         i_size = hton32( i_size );
01556         memcpy( &p_app1->i_field_size, &i_size, 4 );
01557         i_size = (uint32_t)(sync.length - (uint32_t)(p_field - p_frame));
01558         i_size = hton32( i_size );
01559         memcpy( &p_app1->i_padded_field_size, &i_size, 4 );
01560     }
01561 
01562     p_sys->i_video_frame_size = sync.length;
01563     return p_frame;
01564 }
01565 
01566 static block_t *GrabVideo( demux_t *p_demux )
01567 {
01568     demux_sys_t *p_sys = p_demux->p_sys;
01569     uint8_t     *p_frame;
01570     block_t     *p_block;
01571 
01572     if( p_sys->f_fps >= 0.1 && p_sys->i_video_pts > 0 )
01573     {
01574         mtime_t i_dur = (mtime_t)((double)1000000 / (double)p_sys->f_fps);
01575 
01576         /* Did we wait long enough ? (frame rate reduction) */
01577         if( p_sys->i_video_pts + i_dur > mdate() ) return 0;
01578     }
01579 
01580     if( p_sys->b_mjpeg ) p_frame = GrabMJPEG( p_demux );
01581     else p_frame = GrabCapture( p_demux );
01582 
01583     if( !p_frame ) return 0;
01584 
01585     if( !( p_block = block_New( p_demux, p_sys->i_video_frame_size ) ) )
01586     {
01587         msg_Warn( p_demux, "cannot get block" );
01588         return 0;
01589     }
01590 
01591     memcpy( p_block->p_buffer, p_frame, p_sys->i_video_frame_size );
01592     p_sys->i_video_pts = p_block->i_pts = p_block->i_dts = mdate();
01593 
01594     return p_block;
01595 }

Generated on Tue Dec 20 10:14:26 2005 for vlc-0.8.4a by  doxygen 1.4.2