]> git.sesse.net Git - vlc/blob - modules/access/v4l/v4l.c
Improvements to preferences
[vlc] / modules / access / v4l / v4l.c
1 /*****************************************************************************
2  * v4l.c : Video4Linux input module for vlc
3  *****************************************************************************
4  * Copyright (C) 2002-2004 VideoLAN
5  * $Id$
6  *
7  * Author: Laurent Aimar <fenrir@via.ecp.fr>
8  *         Paul Forgey <paulf at aphrodite dot com>
9  *         Gildas Bazin <gbazin@videolan.org>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
24  *****************************************************************************/
25
26 /*****************************************************************************
27  * Preamble
28  *****************************************************************************/
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <string.h>
32
33 #include <vlc/vlc.h>
34 #include <vlc/input.h>
35 #include <vlc/vout.h>
36 #include <codecs.h>
37
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <sys/ioctl.h>
41 #include <unistd.h>
42 #include <sys/mman.h>
43 #include <errno.h>
44 #include <fcntl.h>
45
46 /* From GStreamer's v4l plugin:
47  * Because of some really cool feature in video4linux1, also known as
48  * 'not including sys/types.h and sys/time.h', we had to include it
49  * ourselves. In all their intelligence, these people decided to fix
50  * this in the next version (video4linux2) in such a cool way that it
51  * breaks all compilations of old stuff...
52  * The real problem is actually that linux/time.h doesn't use proper
53  * macro checks before defining types like struct timeval. The proper
54  * fix here is to either fuck the kernel header (which is what we do
55  * by defining _LINUX_TIME_H, an innocent little hack) or by fixing it
56  * upstream, which I'll consider doing later on. If you get compiler
57  * errors here, check your linux/time.h && sys/time.h header setup.
58 */
59 #define _LINUX_TIME_H
60
61 #include <linux/videodev.h>
62 #include "videodev_mjpeg.h"
63
64 #include <sys/soundcard.h>
65
66 /*****************************************************************************
67  * Module descriptior
68  *****************************************************************************/
69 static int  Open ( vlc_object_t * );
70 static void Close( vlc_object_t * );
71
72 #define CACHING_TEXT N_("Caching value in ms")
73 #define CACHING_LONGTEXT N_( \
74     "Allows you to modify the default caching value for v4l streams. This " \
75     "value should be set in millisecond units." )
76 #define VDEV_TEXT N_("Video device name")
77 #define VDEV_LONGTEXT N_( \
78     "Specify the name of the video device that will be used. " \
79     "If you don't specify anything, no video device will be used.")
80 #define ADEV_TEXT N_("Audio device name")
81 #define ADEV_LONGTEXT N_( \
82     "Specify the name of the audio device that will be used. " \
83     "If you don't specify anything, no audio device will be used.")
84 #define CHROMA_TEXT N_("Video input chroma format")
85 #define CHROMA_LONGTEXT N_( \
86     "Force the Video4Linux video device to use a specific chroma format " \
87     "(eg. I420 (default), RV24, etc.)")
88
89 vlc_module_begin();
90     set_shortname( _("Video4Linux") );
91     set_description( _("Video4Linux input") );
92     set_category( CAT_INPUT );
93     set_subcategory( SUBCAT_INPUT_ACCESS );
94
95     add_integer( "v4l-caching", DEFAULT_PTS_DELAY / 1000, NULL,
96                  CACHING_TEXT, CACHING_LONGTEXT, VLC_TRUE );
97     add_string( "v4l-vdev", "/dev/video", 0, VDEV_TEXT, VDEV_LONGTEXT,
98                 VLC_FALSE );
99     add_string( "v4l-adev", "/dev/dsp", 0, ADEV_TEXT, ADEV_LONGTEXT,
100                 VLC_FALSE );
101     add_string( "v4l-chroma", NULL, NULL, CHROMA_TEXT, CHROMA_LONGTEXT,
102                 VLC_TRUE );
103
104     add_shortcut( "v4l" );
105     set_capability( "access_demux", 10 );
106     set_callbacks( Open, Close );
107 vlc_module_end();
108
109 /*****************************************************************************
110  * Access: local prototypes
111  *****************************************************************************/
112 static int Demux  ( demux_t * );
113 static int Control( demux_t *, int, va_list );
114
115 static void ParseMRL    ( demux_t * );
116 static int  OpenVideoDev( demux_t *, char * );
117 static int  OpenAudioDev( demux_t *, char * );
118
119 static block_t *GrabAudio( demux_t * );
120 static block_t *GrabVideo( demux_t * );
121
122 #define MJPEG_BUFFER_SIZE (256*1024)
123
124 struct quicktime_mjpeg_app1
125 {
126     uint32_t    i_reserved;             /* set to 0 */
127     uint32_t    i_tag;                  /* 'mjpg' */
128     uint32_t    i_field_size;           /* offset following EOI */
129     uint32_t    i_padded_field_size;    /* offset following EOI+pad */
130     uint32_t    i_next_field;           /* offset to next field */
131     uint32_t    i_DQT_offset;
132     uint32_t    i_DHT_offset;
133     uint32_t    i_SOF_offset;
134     uint32_t    i_SOS_offset;
135     uint32_t    i_data_offset;          /* following SOS marker data */
136 };
137
138 static struct
139 {
140     int i_v4l;
141     int i_fourcc;
142
143 } v4lchroma_to_fourcc[] =
144 {
145     { VIDEO_PALETTE_GREY, VLC_FOURCC( 'G', 'R', 'E', 'Y' ) },
146     { VIDEO_PALETTE_HI240, VLC_FOURCC( 'I', '2', '4', '0' ) },
147     { VIDEO_PALETTE_RGB565, VLC_FOURCC( 'R', 'V', '1', '6' ) },
148     { VIDEO_PALETTE_RGB555, VLC_FOURCC( 'R', 'V', '1', '5' ) },
149     { VIDEO_PALETTE_RGB24, VLC_FOURCC( 'R', 'V', '2', '4' ) },
150     { VIDEO_PALETTE_RGB32, VLC_FOURCC( 'R', 'V', '3', '2' ) },
151     { VIDEO_PALETTE_YUV422, VLC_FOURCC( 'I', '4', '2', '2' ) },
152     { VIDEO_PALETTE_YUYV, VLC_FOURCC( 'Y', 'U', 'Y', 'V' ) },
153     { VIDEO_PALETTE_UYVY, VLC_FOURCC( 'U', 'Y', 'V', 'Y' ) },
154     { VIDEO_PALETTE_YUV420, VLC_FOURCC( 'I', '4', '2', 'N' ) },
155     { VIDEO_PALETTE_YUV411, VLC_FOURCC( 'I', '4', '1', 'N' ) },
156     { VIDEO_PALETTE_RAW, VLC_FOURCC( 'G', 'R', 'A', 'W' ) },
157     { VIDEO_PALETTE_YUV422P, VLC_FOURCC( 'I', '4', '2', '2' ) },
158     { VIDEO_PALETTE_YUV420P, VLC_FOURCC( 'I', '4', '2', '0' ) },
159     { VIDEO_PALETTE_YUV411P, VLC_FOURCC( 'I', '4', '1', '1' ) },
160     { 0, 0 }
161 };
162
163 struct demux_sys_t
164 {
165     /* Devices */
166     char *psz_device;         /* Main device from MRL, can be video or audio */
167
168     char *psz_vdev;
169     int  fd_video;
170
171     char *psz_adev;
172     int  fd_audio;
173
174     /* Video properties */
175     picture_t pic;
176
177     int i_fourcc;
178     int i_channel;
179     int i_audio;
180     int i_norm;
181     int i_tuner;
182     int i_frequency;
183     int i_width;
184     int i_height;
185
186     int i_brightness;
187     int i_hue;
188     int i_colour;
189     int i_contrast;
190
191     float f_fps;            /* <= 0.0 mean to grab at full rate */
192     mtime_t i_video_pts;    /* only used when f_fps > 0 */
193
194     vlc_bool_t b_mjpeg;
195     int i_decimation;
196     int i_quality;
197
198     struct video_capability vid_cap;
199     struct video_mbuf       vid_mbuf;
200     struct mjpeg_requestbuffers mjpeg_buffers;
201
202     uint8_t *p_video_mmap;
203     int     i_frame_pos;
204
205     struct video_mmap   vid_mmap;
206     struct video_picture vid_picture;
207
208     int          i_video_frame_size;
209     es_out_id_t  *p_es_video;
210
211     /* Audio properties */
212     vlc_fourcc_t i_acodec_raw;
213     int          i_sample_rate;
214     vlc_bool_t   b_stereo;
215     int          i_audio_max_frame_size;
216     block_t      *p_block_audio;
217     es_out_id_t  *p_es_audio;
218 };
219
220 /*****************************************************************************
221  * Open: opens v4l device
222  *****************************************************************************
223  *
224  * url: <video device>::::
225  *
226  *****************************************************************************/
227 static int Open( vlc_object_t *p_this )
228 {
229     demux_t     *p_demux = (demux_t*)p_this;
230     demux_sys_t *p_sys;
231
232     /* Only when selected */
233     if( *p_demux->psz_access == '\0' )
234         return VLC_EGENERIC;
235
236     /* Set up p_demux */
237     p_demux->pf_demux = Demux;
238     p_demux->pf_control = Control;
239     p_demux->info.i_update = 0;
240     p_demux->info.i_title = 0;
241     p_demux->info.i_seekpoint = 0;
242     p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );
243     memset( p_sys, 0, sizeof( demux_sys_t ) );
244
245     p_sys->i_audio          = -1;
246     p_sys->i_norm           = VIDEO_MODE_AUTO;    // auto
247     p_sys->i_tuner          = -1;
248     p_sys->i_frequency      = -1;
249
250     p_sys->f_fps            = -1.0;
251     p_sys->i_video_pts      = -1;
252
253     p_sys->i_brightness     = -1;
254     p_sys->i_hue            = -1;
255     p_sys->i_colour         = -1;
256     p_sys->i_contrast       = -1;
257
258     p_sys->b_mjpeg     = VLC_FALSE;
259     p_sys->i_decimation = 1;
260     p_sys->i_quality = 100;
261
262     p_sys->i_sample_rate  = 44100;
263     p_sys->b_stereo       = VLC_TRUE;
264
265     p_sys->psz_device = p_sys->psz_vdev = p_sys->psz_adev = NULL;
266     p_sys->fd_video = -1;
267     p_sys->fd_audio = -1;
268
269     p_sys->p_es_video = p_sys->p_es_audio = 0;
270     p_sys->p_block_audio = 0;
271
272     ParseMRL( p_demux );
273
274     /* Find main device (video or audio) */
275     if( p_sys->psz_device && *p_sys->psz_device )
276     {
277         msg_Dbg( p_demux, "main device=`%s'", p_sys->psz_device );
278
279         /* Try to open as video device */
280         p_sys->fd_video = OpenVideoDev( p_demux, p_sys->psz_device );
281
282         if( p_sys->fd_video < 0 )
283         {
284             /* Try to open as audio device */
285             p_sys->fd_audio = OpenAudioDev( p_demux, p_sys->psz_device );
286             if( p_sys->fd_audio >= 0 )
287             {
288                 if( p_sys->psz_adev ) free( p_sys->psz_adev );
289                 p_sys->psz_adev = p_sys->psz_device;
290                 p_sys->psz_device = NULL;
291             }
292         }
293         else
294         {
295             if( p_sys->psz_vdev ) free( p_sys->psz_vdev );
296             p_sys->psz_vdev = p_sys->psz_device;
297             p_sys->psz_device = NULL;
298         }
299     }
300
301     /* If no device opened, only continue if the access was forced */
302     if( p_sys->fd_video < 0 && p_sys->fd_audio < 0 )
303     {
304         if( strcmp( p_demux->psz_access, "v4l" ) )
305         {
306             Close( p_this );
307             return VLC_EGENERIC;
308         }
309     }
310
311     /* Find video device */
312     if( p_sys->fd_video < 0 )
313     {
314         if( !p_sys->psz_vdev || !*p_sys->psz_vdev )
315         {
316             if( p_sys->psz_vdev ) free( p_sys->psz_vdev );
317             p_sys->psz_vdev = var_CreateGetString( p_demux, "v4l-vdev" );;
318         }
319
320         if( p_sys->psz_vdev && *p_sys->psz_vdev )
321         {
322             p_sys->fd_video = OpenVideoDev( p_demux, p_sys->psz_vdev );
323         }
324     }
325
326     /* Find audio device */
327     if( p_sys->fd_audio < 0 )
328     {
329         if( !p_sys->psz_adev || !*p_sys->psz_adev )
330         {
331             if( p_sys->psz_adev ) free( p_sys->psz_adev );
332             p_sys->psz_adev = var_CreateGetString( p_demux, "v4l-adev" );;
333         }
334
335         if( p_sys->psz_adev && *p_sys->psz_adev )
336         {
337             p_sys->fd_audio = OpenAudioDev( p_demux, p_sys->psz_adev );
338         }
339     }
340
341     if( p_sys->fd_video < 0 && p_sys->fd_audio < 0 )
342     {
343         Close( p_this );
344         return VLC_EGENERIC;
345     }
346
347     msg_Dbg( p_demux, "v4l grabbing started" );
348
349     /* Declare elementary streams */
350     if( p_sys->fd_video >= 0 )
351     {
352         es_format_t fmt;
353         es_format_Init( &fmt, VIDEO_ES, p_sys->i_fourcc );
354         fmt.video.i_width  = p_sys->i_width;
355         fmt.video.i_height = p_sys->i_height;
356         fmt.video.i_aspect = 4 * VOUT_ASPECT_FACTOR / 3;
357
358         /* Setup rgb mask for RGB formats */
359         if( p_sys->i_fourcc == VLC_FOURCC('R','V','2','4') )
360         {
361             /* This is in BGR format */
362             fmt.video.i_bmask = 0x00ff0000;
363             fmt.video.i_gmask = 0x0000ff00;
364             fmt.video.i_rmask = 0x000000ff;
365         }
366
367         msg_Dbg( p_demux, "added new video es %4.4s %dx%d",
368                  (char*)&fmt.i_codec, fmt.video.i_width, fmt.video.i_height );
369         p_sys->p_es_video = es_out_Add( p_demux->out, &fmt );
370     }
371
372     if( p_sys->fd_audio >= 0 )
373     {
374         es_format_t fmt;
375         es_format_Init( &fmt, AUDIO_ES, VLC_FOURCC('a','r','a','w') );
376
377         fmt.audio.i_channels = p_sys->b_stereo ? 2 : 1;
378         fmt.audio.i_rate = p_sys->i_sample_rate;
379         fmt.audio.i_bitspersample = 16; // FIXME ?
380         fmt.audio.i_blockalign = fmt.audio.i_channels *
381             fmt.audio.i_bitspersample / 8;
382         fmt.i_bitrate = fmt.audio.i_channels * fmt.audio.i_rate *
383             fmt.audio.i_bitspersample;
384
385         msg_Dbg( p_demux, "new audio es %d channels %dHz",
386                  fmt.audio.i_channels, fmt.audio.i_rate );
387
388         p_sys->p_es_audio = es_out_Add( p_demux->out, &fmt );
389     }
390
391     /* Update default_pts to a suitable value for access */
392     var_Create( p_demux, "v4l-caching", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
393
394     return VLC_SUCCESS;
395 }
396
397 /*****************************************************************************
398  * Close: close device, free resources
399  *****************************************************************************/
400 static void Close( vlc_object_t *p_this )
401 {
402     demux_t     *p_demux = (demux_t *)p_this;
403     demux_sys_t *p_sys   = p_demux->p_sys;
404
405     if( p_sys->psz_device ) free( p_sys->psz_device );
406     if( p_sys->psz_vdev )   free( p_sys->psz_vdev );
407     if( p_sys->psz_adev )   free( p_sys->psz_adev );
408     if( p_sys->fd_video >= 0 ) close( p_sys->fd_video );
409     if( p_sys->fd_audio >= 0 ) close( p_sys->fd_audio );
410     if( p_sys->p_block_audio ) block_Release( p_sys->p_block_audio );
411
412     if( p_sys->b_mjpeg )
413     {
414         int i_noframe = -1;
415         ioctl( p_sys->fd_video, MJPIOC_QBUF_CAPT, &i_noframe );
416     }
417
418     if( p_sys->p_video_mmap && p_sys->p_video_mmap != MAP_FAILED )
419     {
420         if( p_sys->b_mjpeg )
421             munmap( p_sys->p_video_mmap, p_sys->mjpeg_buffers.size *
422                     p_sys->mjpeg_buffers.count );
423         else
424             munmap( p_sys->p_video_mmap, p_sys->vid_mbuf.size );
425     }
426
427     free( p_sys );
428 }
429
430 /*****************************************************************************
431  * Control:
432  *****************************************************************************/
433 static int Control( demux_t *p_demux, int i_query, va_list args )
434 {
435     vlc_bool_t *pb;
436     int64_t    *pi64;
437
438     switch( i_query )
439     {
440         /* Special for access_demux */
441         case DEMUX_CAN_PAUSE:
442         case DEMUX_SET_PAUSE_STATE:
443         case DEMUX_CAN_CONTROL_PACE:
444             pb = (vlc_bool_t*)va_arg( args, vlc_bool_t * );
445             *pb = VLC_FALSE;
446             return VLC_SUCCESS;
447
448         case DEMUX_GET_PTS_DELAY:
449             pi64 = (int64_t*)va_arg( args, int64_t * );
450             *pi64 = (int64_t)var_GetInteger( p_demux, "v4l-caching" ) * 1000;
451             return VLC_SUCCESS;
452
453         case DEMUX_GET_TIME:
454             pi64 = (int64_t*)va_arg( args, int64_t * );
455             *pi64 = mdate();
456             return VLC_SUCCESS;
457
458         /* TODO implement others */
459         default:
460             return VLC_EGENERIC;
461     }
462
463     return VLC_EGENERIC;
464 }
465
466 /*****************************************************************************
467  * Demux:
468  *****************************************************************************/
469 static int Demux( demux_t *p_demux )
470 {
471     demux_sys_t *p_sys = p_demux->p_sys;
472     es_out_id_t  *p_es = p_sys->p_es_audio;
473     block_t *p_block = NULL;
474
475     /* Try grabbing audio frames first */
476     if( p_sys->fd_audio < 0 || !( p_block = GrabAudio( p_demux ) ) )
477     {
478         /* Try grabbing video frame */
479         p_es = p_sys->p_es_video;
480         if( p_sys->fd_video > 0 ) p_block = GrabVideo( p_demux );
481     }
482
483     if( !p_block )
484     {
485         /* Sleep so we do not consume all the cpu, 10ms seems
486          * like a good value (100fps) */
487         msleep( 10000 );
488         return 1;
489     }
490
491     es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_block->i_pts );
492     es_out_Send( p_demux->out, p_es, p_block );
493
494     return 1;
495 }
496
497 /*****************************************************************************
498  * ParseMRL: parse the options contained in the MRL
499  *****************************************************************************/
500 static void ParseMRL( demux_t *p_demux )
501 {
502     demux_sys_t *p_sys = p_demux->p_sys;
503
504     char *psz_dup = strdup( p_demux->psz_path );
505     char *psz_parser = psz_dup;
506
507     while( *psz_parser && *psz_parser != ':' )
508     {
509         psz_parser++;
510     }
511
512     if( *psz_parser == ':' )
513     {
514         /* read options */
515         for( ;; )
516         {
517             *psz_parser++ = '\0';
518             if( !strncmp( psz_parser, "channel=", strlen( "channel=" ) ) )
519             {
520                 p_sys->i_channel = strtol( psz_parser + strlen( "channel=" ),
521                                            &psz_parser, 0 );
522             }
523             else if( !strncmp( psz_parser, "norm=", strlen( "norm=" ) ) )
524             {
525                 psz_parser += strlen( "norm=" );
526                 if( !strncmp( psz_parser, "pal", strlen( "pal" ) ) )
527                 {
528                     p_sys->i_norm = VIDEO_MODE_PAL;
529                     psz_parser += strlen( "pal" );
530                 }
531                 else if( !strncmp( psz_parser, "ntsc", strlen( "ntsc" ) ) )
532                 {
533                     p_sys->i_norm = VIDEO_MODE_NTSC;
534                     psz_parser += strlen( "ntsc" );
535                 }
536                 else if( !strncmp( psz_parser, "secam", strlen( "secam" ) ) )
537                 {
538                     p_sys->i_norm = VIDEO_MODE_SECAM;
539                     psz_parser += strlen( "secam" );
540                 }
541                 else if( !strncmp( psz_parser, "auto", strlen( "auto" ) ) )
542                 {
543                     p_sys->i_norm = VIDEO_MODE_AUTO;
544                     psz_parser += strlen( "auto" );
545                 }
546                 else
547                 {
548                     p_sys->i_norm = strtol( psz_parser, &psz_parser, 0 );
549                 }
550             }
551             else if( !strncmp( psz_parser, "frequency=",
552                                strlen( "frequency=" ) ) )
553             {
554                 p_sys->i_frequency =
555                     strtol( psz_parser + strlen( "frequency=" ),
556                             &psz_parser, 0 );
557                 if( p_sys->i_frequency < 30000 )
558                 {
559                     msg_Warn( p_demux, "v4l syntax has changed : "
560                               "'frequency' is now channel frequency in kHz");
561                 }
562             }
563             else if( !strncmp( psz_parser, "audio=", strlen( "audio=" ) ) )
564             {
565                 p_sys->i_audio = strtol( psz_parser + strlen( "audio=" ),
566                                          &psz_parser, 0 );
567             }
568             else if( !strncmp( psz_parser, "size=", strlen( "size=" ) ) )
569             {
570                 psz_parser += strlen( "size=" );
571                 if( !strncmp( psz_parser, "subqcif", strlen( "subqcif" ) ) )
572                 {
573                     p_sys->i_width  = 128;
574                     p_sys->i_height = 96;
575                 }
576                 else if( !strncmp( psz_parser, "qsif", strlen( "qsif" ) ) )
577                 {
578                     p_sys->i_width  = 160;
579                     p_sys->i_height = 120;
580                 }
581                 else if( !strncmp( psz_parser, "qcif", strlen( "qcif" ) ) )
582                 {
583                     p_sys->i_width  = 176;
584                     p_sys->i_height = 144;
585                 }
586                 else if( !strncmp( psz_parser, "sif", strlen( "sif" ) ) )
587                 {
588                     p_sys->i_width  = 320;
589                     p_sys->i_height = 244;
590                 }
591                 else if( !strncmp( psz_parser, "cif", strlen( "cif" ) ) )
592                 {
593                     p_sys->i_width  = 352;
594                     p_sys->i_height = 288;
595                 }
596                 else if( !strncmp( psz_parser, "vga", strlen( "vga" ) ) )
597                 {
598                     p_sys->i_width  = 640;
599                     p_sys->i_height = 480;
600                 }
601                 else
602                 {
603                     /* widthxheight */
604                     p_sys->i_width = strtol( psz_parser, &psz_parser, 0 );
605                     if( *psz_parser == 'x' || *psz_parser == 'X')
606                     {
607                         p_sys->i_height = strtol( psz_parser + 1,
608                                                   &psz_parser, 0 );
609                     }
610                     msg_Dbg( p_demux, "WxH %dx%d", p_sys->i_width,
611                              p_sys->i_height );
612                 }
613             }
614             else if( !strncmp( psz_parser, "brightness=", strlen( "brightness=" ) ) )
615             {
616                 p_sys->i_brightness = strtol( psz_parser + strlen( "brightness=" ),
617                                               &psz_parser, 0 );
618             }
619             else if( !strncmp( psz_parser, "colour=", strlen( "colour=" ) ) )
620             {
621                 p_sys->i_colour = strtol( psz_parser + strlen( "colour=" ),
622                                           &psz_parser, 0 );
623             }
624             else if( !strncmp( psz_parser, "hue=", strlen( "hue=" ) ) )
625             {
626                 p_sys->i_hue = strtol( psz_parser + strlen( "hue=" ), 
627                                        &psz_parser, 0 );
628             }
629             else if( !strncmp( psz_parser, "contrast=", strlen( "contrast=" ) ) )
630             {
631                 p_sys->i_contrast = strtol( psz_parser + strlen( "contrast=" ),
632                                             &psz_parser, 0 );
633             }
634             else if( !strncmp( psz_parser, "tuner=", strlen( "tuner=" ) ) )
635             {
636                 p_sys->i_tuner = strtol( psz_parser + strlen( "tuner=" ),
637                                          &psz_parser, 0 );
638             }
639             else if( !strncmp( psz_parser, "adev=", strlen( "adev=" ) ) )
640             {
641                 int  i_len;
642
643                 psz_parser += strlen( "adev=" );
644                 if( strchr( psz_parser, ':' ) )
645                 {
646                     i_len = strchr( psz_parser, ':' ) - psz_parser;
647                 }
648                 else
649                 {
650                     i_len = strlen( psz_parser );
651                 }
652
653                 p_sys->psz_adev = strndup( psz_parser, i_len );
654
655                 psz_parser += i_len;
656             }
657             else if( !strncmp( psz_parser, "samplerate=",
658                                strlen( "samplerate=" ) ) )
659             {
660                 p_sys->i_sample_rate =
661                     strtol( psz_parser + strlen( "samplerate=" ),
662                             &psz_parser, 0 );
663             }
664             else if( !strncmp( psz_parser, "stereo", strlen( "stereo" ) ) )
665             {
666                 psz_parser += strlen( "stereo" );
667
668                 p_sys->b_stereo = VLC_TRUE;
669             }
670             else if( !strncmp( psz_parser, "mono", strlen( "mono" ) ) )
671             {
672                 psz_parser += strlen( "mono" );
673
674                 p_sys->b_stereo = VLC_FALSE;
675             }
676             else if( !strncmp( psz_parser, "mjpeg", strlen( "mjpeg" ) ) )
677             {
678                 psz_parser += strlen( "mjpeg" );
679
680                 p_sys->b_mjpeg = VLC_TRUE;
681             }
682             else if( !strncmp( psz_parser, "decimation=",
683                         strlen( "decimation=" ) ) )
684             {
685                 p_sys->i_decimation =
686                     strtol( psz_parser + strlen( "decimation=" ),
687                             &psz_parser, 0 );
688             }
689             else if( !strncmp( psz_parser, "quality=",
690                         strlen( "quality=" ) ) )
691             {
692                 p_sys->i_quality =
693                     strtol( psz_parser + strlen( "quality=" ),
694                             &psz_parser, 0 );
695             }
696             else if( !strncmp( psz_parser, "fps=", strlen( "fps=" ) ) )
697             {
698                 p_sys->f_fps = strtof( psz_parser + strlen( "fps=" ),
699                                        &psz_parser );
700             }
701             else
702             {
703                 msg_Warn( p_demux, "unknown option" );
704             }
705
706             while( *psz_parser && *psz_parser != ':' )
707             {
708                 psz_parser++;
709             }
710
711             if( *psz_parser == '\0' )
712             {
713                 break;
714             }
715         }
716     }
717
718     if( *psz_dup )
719     {
720         p_sys->psz_device = strdup( psz_dup );
721     }
722     if( psz_dup ) free( psz_dup );
723 }
724
725 /*****************************************************************************
726  * OpenVideoDev:
727  *****************************************************************************/
728 static int OpenVideoDev( demux_t *p_demux, char *psz_device )
729 {
730     demux_sys_t *p_sys = p_demux->p_sys;
731     int i_fd;
732
733     struct video_channel vid_channel;
734     struct mjpeg_params mjpeg;
735     int i;
736
737     if( ( i_fd = open( psz_device, O_RDWR ) ) < 0 )
738     {
739         msg_Err( p_demux, "cannot open device (%s)", strerror( errno ) );
740         goto vdev_failed;
741     }
742
743     if( ioctl( i_fd, VIDIOCGCAP, &p_sys->vid_cap ) < 0 )
744     {
745         msg_Err( p_demux, "cannot get capabilities (%s)", strerror( errno ) );
746         goto vdev_failed;
747     }
748
749     msg_Dbg( p_demux,
750              "V4L device %s %d channels %d audios %d < w < %d %d < h < %d",
751              p_sys->vid_cap.name,
752              p_sys->vid_cap.channels,
753              p_sys->vid_cap.audios,
754              p_sys->vid_cap.minwidth,  p_sys->vid_cap.maxwidth,
755              p_sys->vid_cap.minheight, p_sys->vid_cap.maxheight );
756
757     if( p_sys->i_channel < 0 || p_sys->i_channel >= p_sys->vid_cap.channels )
758     {
759         msg_Dbg( p_demux, "invalid channel, falling back on channel 0" );
760         p_sys->i_channel = 0;
761     }
762     if( p_sys->i_audio >= p_sys->vid_cap.audios )
763     {
764         msg_Dbg( p_demux, "invalid audio, falling back with no audio" );
765         p_sys->i_audio = -1;
766     }
767
768     if( p_sys->i_width < p_sys->vid_cap.minwidth ||
769         p_sys->i_width > p_sys->vid_cap.maxwidth )
770     {
771         msg_Dbg( p_demux, "invalid width %i", p_sys->i_width );
772         p_sys->i_width = 0;
773     }
774     if( p_sys->i_height < p_sys->vid_cap.minheight ||
775         p_sys->i_height > p_sys->vid_cap.maxheight )
776     {
777         msg_Dbg( p_demux, "invalid height %i", p_sys->i_height );
778         p_sys->i_height = 0;
779     }
780
781     if( !( p_sys->vid_cap.type & VID_TYPE_CAPTURE ) )
782     {
783         msg_Err( p_demux, "cannot grab" );
784         goto vdev_failed;
785     }
786
787     vid_channel.channel = p_sys->i_channel;
788     if( ioctl( i_fd, VIDIOCGCHAN, &vid_channel ) < 0 )
789     {
790         msg_Err( p_demux, "cannot get channel infos (%s)",
791                           strerror( errno ) );
792         goto vdev_failed;
793     }
794     msg_Dbg( p_demux,
795              "setting channel %s(%d) %d tuners flags=0x%x type=0x%x norm=0x%x",
796              vid_channel.name, vid_channel.channel, vid_channel.tuners,
797              vid_channel.flags, vid_channel.type, vid_channel.norm );
798
799     if( p_sys->i_tuner >= vid_channel.tuners )
800     {
801         msg_Dbg( p_demux, "invalid tuner, falling back on tuner 0" );
802         p_sys->i_tuner = 0;
803     }
804
805     vid_channel.norm = p_sys->i_norm;
806     if( ioctl( i_fd, VIDIOCSCHAN, &vid_channel ) < 0 )
807     {
808         msg_Err( p_demux, "cannot set channel (%s)", strerror( errno ) );
809         goto vdev_failed;
810     }
811
812     if( vid_channel.flags & VIDEO_VC_TUNER )
813     {
814
815         /* set tuner */
816 #if 0
817         struct video_tuner vid_tuner;
818         if( p_sys->i_tuner >= 0 )
819         {
820             vid_tuner.tuner = p_sys->i_tuner;
821             if( ioctl( i_fd, VIDIOCGTUNER, &vid_tuner ) < 0 )
822             {
823                 msg_Err( p_demux, "cannot get tuner (%s)", strerror( errno ) );
824                 goto vdev_failed;
825             }
826             msg_Dbg( p_demux, "tuner %s low=%d high=%d, flags=0x%x "
827                      "mode=0x%x signal=0x%x",
828                      vid_tuner.name, vid_tuner.rangelow, vid_tuner.rangehigh,
829                      vid_tuner.flags, vid_tuner.mode, vid_tuner.signal );
830
831             msg_Dbg( p_demux, "setting tuner %s (%d)",
832                      vid_tuner.name, vid_tuner.tuner );
833
834             /* FIXME FIXME to be checked FIXME FIXME */
835             //vid_tuner.mode = p_sys->i_norm;
836             if( ioctl( i_fd, VIDIOCSTUNER, &vid_tuner ) < 0 )
837             {
838                 msg_Err( p_demux, "cannot set tuner (%s)", strerror( errno ) );
839                 goto vdev_failed;
840             }
841         }
842 #endif
843
844         /* Show a warning if frequency is < than 30000.
845          * User is certainly usint old syntax. */
846
847
848         /* set frequency */
849         if( p_sys->i_frequency >= 0 )
850         {
851             int driver_frequency = p_sys->i_frequency * 16 /1000;
852             if( ioctl( i_fd, VIDIOCSFREQ, &driver_frequency ) < 0 )
853             {
854                 msg_Err( p_demux, "cannot set frequency (%s)",
855                                   strerror( errno ) );
856                 goto vdev_failed;
857             }
858             msg_Dbg( p_demux, "frequency %d (%d)", p_sys->i_frequency,
859                                                    driver_frequency );
860         }
861     }
862
863     /* set audio */
864     if( vid_channel.flags & VIDEO_VC_AUDIO )
865     {
866         struct video_audio      vid_audio;
867
868         /* XXX TODO volume, balance, ... */
869         if( p_sys->i_audio >= 0 )
870         {
871             vid_audio.audio = p_sys->i_audio;
872             if( ioctl( i_fd, VIDIOCGAUDIO, &vid_audio ) < 0 )
873             {
874                 msg_Err( p_demux, "cannot get audio (%s)", strerror( errno ) );
875                 goto vdev_failed;
876             }
877
878             /* unmute audio */
879             vid_audio.flags &= ~VIDEO_AUDIO_MUTE;
880
881             if( ioctl( i_fd, VIDIOCSAUDIO, &vid_audio ) < 0 )
882             {
883                 msg_Err( p_demux, "cannot set audio (%s)", strerror( errno ) );
884                 goto vdev_failed;
885             }
886         }
887
888     }
889
890     /* establish basic params with input and norm before feeling width
891      * or height */
892     if( p_sys->b_mjpeg )
893     {
894         struct quicktime_mjpeg_app1 *p_app1;
895         int32_t i_offset;
896
897         if( ioctl( i_fd, MJPIOC_G_PARAMS, &mjpeg ) < 0 )
898         {
899             msg_Err( p_demux, "cannot get mjpeg params (%s)",
900                               strerror( errno ) );
901             goto vdev_failed;
902         }
903         mjpeg.input = p_sys->i_channel;
904         mjpeg.norm  = p_sys->i_norm;
905         mjpeg.decimation = p_sys->i_decimation;
906
907         if( p_sys->i_width )
908             mjpeg.img_width = p_sys->i_width / p_sys->i_decimation;
909         if( p_sys->i_height )
910             mjpeg.img_height = p_sys->i_height / p_sys->i_decimation;
911
912         /* establish Quicktime APP1 marker while we are here */
913         mjpeg.APPn = 1;
914         mjpeg.APP_len = 40;
915
916         /* aligned */
917         p_app1 = (struct quicktime_mjpeg_app1 *)mjpeg.APP_data;
918         p_app1->i_reserved = 0;
919         p_app1->i_tag = VLC_FOURCC( 'm','j','p','g' );
920         p_app1->i_field_size = 0;
921         p_app1->i_padded_field_size = 0;
922         p_app1->i_next_field = 0;
923         /* XXX WARNING XXX */
924         /* these's nothing magic about these values.  We are dangerously
925          * assuming the encoder card is encoding mjpeg-a and is not throwing
926          * in marker tags we aren't expecting.  It's bad enough we have to
927          * search through the jpeg output for every frame we grab just to
928          * find the first field's end marker, so we take this risk to boost
929          * performance.
930          * This is really something the driver could do for us because this
931          * does conform to standards outside of Apple Quicktime.
932          */
933         i_offset = 0x2e;
934         p_app1->i_DQT_offset = hton32( i_offset );
935         i_offset = 0xb4;
936         p_app1->i_DHT_offset = hton32( i_offset );
937         i_offset = 0x258;
938         p_app1->i_SOF_offset = hton32( i_offset );
939         i_offset = 0x26b;
940         p_app1->i_SOS_offset = hton32( i_offset );
941         i_offset = 0x279;
942         p_app1->i_data_offset = hton32( i_offset );
943
944         /* SOF and SOS aren't specified by the mjpeg API because they aren't
945          * optional.  They will be present in the output. */
946         mjpeg.jpeg_markers = JPEG_MARKER_DHT | JPEG_MARKER_DQT;
947
948         if( ioctl( i_fd, MJPIOC_S_PARAMS, &mjpeg ) < 0 )
949         {
950             msg_Err( p_demux, "cannot set mjpeg params (%s)",
951                               strerror( errno ) );
952             goto vdev_failed;
953         }
954
955         p_sys->i_width = mjpeg.img_width * mjpeg.HorDcm;
956         p_sys->i_height = mjpeg.img_height * mjpeg.VerDcm *
957             mjpeg.field_per_buff;
958     }
959
960     /* fix width/height */
961     if( !p_sys->b_mjpeg && ( p_sys->i_width == 0 || p_sys->i_height == 0 ) )
962     {
963         struct video_window vid_win;
964
965         if( ioctl( i_fd, VIDIOCGWIN, &vid_win ) < 0 )
966         {
967             msg_Err( p_demux, "cannot get win (%s)", strerror( errno ) );
968             goto vdev_failed;
969         }
970         p_sys->i_width  = vid_win.width;
971         p_sys->i_height = vid_win.height;
972
973         msg_Dbg( p_demux, "will use %dx%d", p_sys->i_width, p_sys->i_height );
974     }
975
976     if( !p_sys->b_mjpeg )
977     {
978         /* set hue/color/.. */
979         if( ioctl( i_fd, VIDIOCGPICT, &p_sys->vid_picture ) == 0 )
980         {
981             struct video_picture vid_picture = p_sys->vid_picture;
982
983             if( p_sys->i_brightness >= 0 && p_sys->i_brightness < 65536 )
984             {
985                 vid_picture.brightness = p_sys->i_brightness;
986             }
987             if( p_sys->i_colour >= 0 && p_sys->i_colour < 65536 )
988             {
989                 vid_picture.colour = p_sys->i_colour;
990             }
991             if( p_sys->i_hue >= 0 && p_sys->i_hue < 65536 )
992             {
993                 vid_picture.hue = p_sys->i_hue;
994             }
995             if( p_sys->i_contrast  >= 0 && p_sys->i_contrast < 65536 )
996             {
997                 vid_picture.contrast = p_sys->i_contrast;
998             }
999             if( ioctl( i_fd, VIDIOCSPICT, &vid_picture ) == 0 )
1000             {
1001                 msg_Dbg( p_demux, "v4l device uses brightness: %d",
1002                          vid_picture.brightness );
1003                 msg_Dbg( p_demux, "v4l device uses colour: %d",
1004                          vid_picture.colour );
1005                 msg_Dbg( p_demux, "v4l device uses hue: %d", vid_picture.hue );
1006                 msg_Dbg( p_demux, "v4l device uses contrast: %d",
1007                          vid_picture.contrast );
1008                 p_sys->vid_picture = vid_picture;
1009             }
1010         }
1011
1012         /* Find out video format used by device */
1013         if( ioctl( i_fd, VIDIOCGPICT, &p_sys->vid_picture ) == 0 )
1014         {
1015             struct video_picture vid_picture = p_sys->vid_picture;
1016             char *psz;
1017             int i;
1018
1019             vid_picture.palette = 0;
1020             p_sys->i_fourcc = 0;
1021
1022             psz = var_CreateGetString( p_demux, "v4l-chroma" );
1023             if( strlen( psz ) >= 4 )
1024             {
1025                 int i_chroma = VLC_FOURCC( psz[0], psz[1], psz[2], psz[3] );
1026
1027                 /* Find out v4l chroma code */
1028                 for( i = 0; v4lchroma_to_fourcc[i].i_v4l != 0; i++ )
1029                 {
1030                     if( v4lchroma_to_fourcc[i].i_fourcc == i_chroma )
1031                     {
1032                         vid_picture.palette = v4lchroma_to_fourcc[i].i_v4l;
1033                         break;
1034                     }
1035                 }
1036             }
1037             free( psz );
1038
1039             if( vid_picture.palette &&
1040                 !ioctl( i_fd, VIDIOCSPICT, &vid_picture ) )
1041             {
1042                 p_sys->vid_picture = vid_picture;
1043             }
1044             else
1045             {
1046                 /* Try to set the format to something easy to encode */
1047                 vid_picture.palette = VIDEO_PALETTE_YUV420P;
1048                 if( ioctl( i_fd, VIDIOCSPICT, &vid_picture ) == 0 )
1049                 {
1050                     p_sys->vid_picture = vid_picture;
1051                 }
1052                 else
1053                 {
1054                     vid_picture.palette = VIDEO_PALETTE_YUV422P;
1055                     if( ioctl( i_fd, VIDIOCSPICT, &vid_picture ) == 0 )
1056                     {
1057                         p_sys->vid_picture = vid_picture;
1058                     }
1059                 }
1060             }
1061
1062             /* Find out final format */
1063             for( i = 0; v4lchroma_to_fourcc[i].i_v4l != 0; i++ )
1064             {
1065                 if( v4lchroma_to_fourcc[i].i_v4l == p_sys->vid_picture.palette)
1066                 {
1067                     p_sys->i_fourcc = v4lchroma_to_fourcc[i].i_fourcc;
1068                     break;
1069                 }
1070             }
1071         }
1072         else
1073         {
1074             msg_Err( p_demux, "ioctl VIDIOCGPICT failed" );
1075             goto vdev_failed;
1076         }
1077     }
1078
1079     if( p_sys->b_mjpeg )
1080     {
1081         int i;
1082
1083         p_sys->mjpeg_buffers.count = 8;
1084         p_sys->mjpeg_buffers.size = MJPEG_BUFFER_SIZE;
1085
1086         if( ioctl( i_fd, MJPIOC_REQBUFS, &p_sys->mjpeg_buffers ) < 0 )
1087         {
1088             msg_Err( p_demux, "mmap unsupported" );
1089             goto vdev_failed;
1090         }
1091
1092         p_sys->p_video_mmap = mmap( 0,
1093                 p_sys->mjpeg_buffers.size * p_sys->mjpeg_buffers.count,
1094                 PROT_READ | PROT_WRITE, MAP_SHARED, i_fd, 0 );
1095         if( p_sys->p_video_mmap == MAP_FAILED )
1096         {
1097             msg_Err( p_demux, "mmap failed" );
1098             goto vdev_failed;
1099         }
1100
1101         p_sys->i_fourcc  = VLC_FOURCC( 'm','j','p','g' );
1102         p_sys->i_frame_pos = -1;
1103
1104         /* queue up all the frames */
1105         for( i = 0; i < (int)p_sys->mjpeg_buffers.count; i++ )
1106         {
1107             if( ioctl( i_fd, MJPIOC_QBUF_CAPT, &i ) < 0 )
1108             {
1109                 msg_Err( p_demux, "unable to queue frame" );
1110                 goto vdev_failed;
1111             }
1112         }
1113     }
1114     else
1115     {
1116         /* Fill in picture_t fields */
1117         vout_InitPicture( VLC_OBJECT(p_demux), &p_sys->pic, p_sys->i_fourcc,
1118                           p_sys->i_width, p_sys->i_height, p_sys->i_width *
1119                           VOUT_ASPECT_FACTOR / p_sys->i_height );
1120         if( !p_sys->pic.i_planes )
1121         {
1122             msg_Err( p_demux, "unsupported chroma" );
1123             goto vdev_failed;
1124         }
1125         p_sys->i_video_frame_size = 0;
1126         for( i = 0; i < p_sys->pic.i_planes; i++ )
1127         {
1128             p_sys->i_video_frame_size += p_sys->pic.p[i].i_visible_lines *
1129               p_sys->pic.p[i].i_visible_pitch;
1130         }
1131
1132         msg_Dbg( p_demux, "v4l device uses frame size: %i",
1133                  p_sys->i_video_frame_size );
1134         msg_Dbg( p_demux, "v4l device uses chroma: %4.4s",
1135                 (char*)&p_sys->i_fourcc );
1136
1137         /* Allocate mmap buffer */
1138         if( ioctl( i_fd, VIDIOCGMBUF, &p_sys->vid_mbuf ) < 0 )
1139         {
1140             msg_Err( p_demux, "mmap unsupported" );
1141             goto vdev_failed;
1142         }
1143
1144         p_sys->p_video_mmap = mmap( 0, p_sys->vid_mbuf.size,
1145                                     PROT_READ|PROT_WRITE, MAP_SHARED,
1146                                     i_fd, 0 );
1147         if( p_sys->p_video_mmap == MAP_FAILED )
1148         {
1149             /* FIXME -> normal read */
1150             msg_Err( p_demux, "mmap failed" );
1151             goto vdev_failed;
1152         }
1153
1154         /* init grabbing */
1155         p_sys->vid_mmap.frame  = 0;
1156         p_sys->vid_mmap.width  = p_sys->i_width;
1157         p_sys->vid_mmap.height = p_sys->i_height;
1158         p_sys->vid_mmap.format = p_sys->vid_picture.palette;
1159         if( ioctl( i_fd, VIDIOCMCAPTURE, &p_sys->vid_mmap ) < 0 )
1160         {
1161             msg_Warn( p_demux, "%4.4s refused", (char*)&p_sys->i_fourcc );
1162             msg_Err( p_demux, "chroma selection failed" );
1163             goto vdev_failed;
1164         }
1165     }
1166     return i_fd;
1167
1168 vdev_failed:
1169
1170     if( i_fd >= 0 ) close( i_fd );
1171     return -1;
1172 }
1173
1174 /*****************************************************************************
1175  * OpenAudioDev:
1176  *****************************************************************************/
1177 static int OpenAudioDev( demux_t *p_demux, char *psz_device )
1178 {
1179     demux_sys_t *p_sys = p_demux->p_sys;
1180     int i_fd, i_format;
1181
1182     if( (i_fd = open( psz_device, O_RDONLY | O_NONBLOCK )) < 0 )
1183     {
1184         msg_Err( p_demux, "cannot open audio device (%s)", strerror( errno ) );
1185         goto adev_fail;
1186     }
1187
1188     i_format = AFMT_S16_LE;
1189     if( ioctl( i_fd, SNDCTL_DSP_SETFMT, &i_format ) < 0
1190         || i_format != AFMT_S16_LE )
1191     {
1192         msg_Err( p_demux, "cannot set audio format (16b little endian) "
1193                  "(%s)", strerror( errno ) );
1194         goto adev_fail;
1195     }
1196
1197     if( ioctl( i_fd, SNDCTL_DSP_STEREO,
1198                &p_sys->b_stereo ) < 0 )
1199     {
1200         msg_Err( p_demux, "cannot set audio channels count (%s)",
1201                  strerror( errno ) );
1202         goto adev_fail;
1203     }
1204
1205     if( ioctl( i_fd, SNDCTL_DSP_SPEED,
1206                &p_sys->i_sample_rate ) < 0 )
1207     {
1208         msg_Err( p_demux, "cannot set audio sample rate (%s)",
1209                  strerror( errno ) );
1210         goto adev_fail;
1211     }
1212
1213     msg_Dbg( p_demux, "openened adev=`%s' %s %dHz",
1214              psz_device, p_sys->b_stereo ? "stereo" : "mono",
1215              p_sys->i_sample_rate );
1216
1217     p_sys->i_audio_max_frame_size = 6 * 1024;
1218
1219     return i_fd;
1220
1221  adev_fail:
1222
1223     if( i_fd >= 0 ) close( i_fd );
1224     return -1;
1225 }
1226
1227 /*****************************************************************************
1228  * GrabAudio: grab audio
1229  *****************************************************************************/
1230 static block_t *GrabAudio( demux_t *p_demux )
1231 {
1232     demux_sys_t *p_sys = p_demux->p_sys;
1233     struct audio_buf_info buf_info;
1234     int i_read, i_correct;
1235     block_t *p_block;
1236
1237     if( p_sys->p_block_audio ) p_block = p_sys->p_block_audio;
1238     else p_block = block_New( p_demux, p_sys->i_audio_max_frame_size );
1239
1240     if( !p_block )
1241     {
1242         msg_Warn( p_demux, "cannot get block" );
1243         return 0;
1244     }
1245
1246     p_sys->p_block_audio = p_block;
1247
1248     i_read = read( p_sys->fd_audio, p_block->p_buffer,
1249                    p_sys->i_audio_max_frame_size );
1250
1251     if( i_read <= 0 ) return 0;
1252
1253     p_block->i_buffer = i_read;
1254     p_sys->p_block_audio = 0;
1255
1256     /* Correct the date because of kernel buffering */
1257     i_correct = i_read;
1258     if( ioctl( p_sys->fd_audio, SNDCTL_DSP_GETISPACE, &buf_info ) == 0 )
1259     {
1260         i_correct += buf_info.bytes;
1261     }
1262
1263     p_block->i_pts = p_block->i_dts =
1264         mdate() - I64C(1000000) * (mtime_t)i_correct /
1265         2 / ( p_sys->b_stereo ? 2 : 1) / p_sys->i_sample_rate;
1266
1267     return p_block;
1268 }
1269
1270 /*****************************************************************************
1271  * GrabVideo:
1272  *****************************************************************************/
1273 static uint8_t *GrabCapture( demux_t *p_demux )
1274 {
1275     demux_sys_t *p_sys = p_demux->p_sys;
1276     int i_captured_frame = p_sys->i_frame_pos;
1277
1278     p_sys->vid_mmap.frame = (p_sys->i_frame_pos + 1) % p_sys->vid_mbuf.frames;
1279
1280     while( ioctl( p_sys->fd_video, VIDIOCMCAPTURE, &p_sys->vid_mmap ) < 0 )
1281     {
1282         if( errno != EAGAIN )
1283         {
1284             msg_Err( p_demux, "failed capturing new frame" );
1285             return NULL;
1286         }
1287
1288         if( p_demux->b_die )
1289         {
1290             return NULL;
1291         }
1292
1293         msg_Dbg( p_demux, "grab failed, trying again" );
1294     }
1295
1296     while( ioctl(p_sys->fd_video, VIDIOCSYNC, &p_sys->i_frame_pos) < 0 )
1297     {
1298         if( errno != EAGAIN && errno != EINTR )    
1299         {
1300             msg_Err( p_demux, "failed syncing new frame" );
1301             return NULL;
1302         }
1303     }
1304
1305     p_sys->i_frame_pos = p_sys->vid_mmap.frame;
1306     /* leave i_video_frame_size alone */
1307     return p_sys->p_video_mmap + p_sys->vid_mbuf.offsets[i_captured_frame];
1308 }
1309
1310 static uint8_t *GrabMJPEG( demux_t *p_demux )
1311 {
1312     demux_sys_t *p_sys = p_demux->p_sys;
1313     struct mjpeg_sync sync;
1314     uint8_t *p_frame, *p_field, *p;
1315     uint16_t tag;
1316     uint32_t i_size;
1317     struct quicktime_mjpeg_app1 *p_app1 = NULL;
1318
1319     /* re-queue the last frame we sync'd */
1320     if( p_sys->i_frame_pos != -1 )
1321     {
1322         while( ioctl( p_sys->fd_video, MJPIOC_QBUF_CAPT,
1323                                        &p_sys->i_frame_pos ) < 0 )
1324         {
1325             if( errno != EAGAIN && errno != EINTR )
1326             {
1327                 msg_Err( p_demux, "failed capturing new frame" );
1328                 return NULL;
1329             }
1330         }
1331     }
1332
1333     /* sync on the next frame */
1334     while( ioctl( p_sys->fd_video, MJPIOC_SYNC, &sync ) < 0 )
1335     {
1336         if( errno != EAGAIN && errno != EINTR )    
1337         {
1338             msg_Err( p_demux, "failed syncing new frame" );
1339             return NULL;
1340         }
1341     }
1342
1343     p_sys->i_frame_pos = sync.frame;
1344     p_frame = p_sys->p_video_mmap + p_sys->mjpeg_buffers.size * sync.frame;
1345
1346     /* p_frame now points to the data.  fix up the Quicktime APP1 marker */
1347     tag = 0xffd9;
1348     tag = hton16( tag );
1349     p_field = p_frame;
1350
1351     /* look for EOI */
1352     p = memmem( p_field, sync.length, &tag, 2 );
1353
1354     if( p )
1355     {
1356         p += 2; /* data immediately following EOI */
1357         /* UNALIGNED! */
1358         p_app1 = (struct quicktime_mjpeg_app1 *)(p_field + 6);
1359
1360         i_size = ((uint32_t)(p - p_field));
1361         i_size = hton32( i_size );
1362         memcpy( &p_app1->i_field_size, &i_size, 4 );
1363
1364         while( *p == 0xff && *(p+1) == 0xff )
1365             p++;
1366
1367         i_size = ((uint32_t)(p - p_field));
1368         i_size = hton32( i_size );
1369         memcpy( &p_app1->i_padded_field_size, &i_size, 4 );
1370     }
1371
1372     tag = 0xffd8;
1373     tag = hton16( tag );
1374     p_field = memmem( p, sync.length - (size_t)(p - p_frame), &tag, 2 );
1375
1376     if( p_field )
1377     {
1378         i_size = (uint32_t)(p_field - p_frame);
1379         i_size = hton32( i_size );
1380         memcpy( &p_app1->i_next_field, &i_size, 4 );
1381
1382         /* UNALIGNED! */
1383         p_app1 = (struct quicktime_mjpeg_app1 *)(p_field + 6);
1384         tag = 0xffd9;
1385         tag = hton16( tag );
1386         p = memmem( p_field, sync.length - (size_t)(p_field - p_frame),
1387                 &tag, 2 );
1388
1389         if( !p )
1390         {
1391             /* sometimes the second field doesn't have the EOI.  just put it
1392              * there
1393              */
1394             p = p_frame + sync.length;
1395             memcpy( p, &tag, 2 );
1396             sync.length += 2;
1397         }
1398
1399         p += 2;
1400         i_size = (uint32_t)(p - p_field);
1401         i_size = hton32( i_size );
1402         memcpy( &p_app1->i_field_size, &i_size, 4 );
1403         i_size = (uint32_t)(sync.length - (uint32_t)(p_field - p_frame));
1404         i_size = hton32( i_size );
1405         memcpy( &p_app1->i_padded_field_size, &i_size, 4 );
1406     }
1407
1408     p_sys->i_video_frame_size = sync.length;
1409     return p_frame;
1410 }
1411
1412 static block_t *GrabVideo( demux_t *p_demux )
1413 {
1414     demux_sys_t *p_sys = p_demux->p_sys;
1415     uint8_t     *p_frame;
1416     block_t     *p_block;
1417
1418     if( p_sys->f_fps >= 0.1 && p_sys->i_video_pts > 0 )
1419     {
1420         mtime_t i_dur = (mtime_t)((double)1000000 / (double)p_sys->f_fps);
1421
1422         /* Did we wait long enough ? (frame rate reduction) */
1423         if( p_sys->i_video_pts + i_dur > mdate() ) return 0;
1424     }
1425
1426     if( p_sys->b_mjpeg ) p_frame = GrabMJPEG( p_demux );
1427     else p_frame = GrabCapture( p_demux );
1428
1429     if( !p_frame ) return 0;
1430
1431     if( !( p_block = block_New( p_demux, p_sys->i_video_frame_size ) ) )
1432     {
1433         msg_Warn( p_demux, "cannot get block" );
1434         return 0;
1435     }
1436
1437     memcpy( p_block->p_buffer, p_frame, p_sys->i_video_frame_size );
1438     p_sys->i_video_pts = p_block->i_pts = p_block->i_dts = mdate();
1439
1440     return p_block;
1441 }