]> git.sesse.net Git - vlc/blob - modules/access/v4l/v4l.c
* v4l: forgot a munmap.
[vlc] / modules / access / v4l / v4l.c
1 /*****************************************************************************
2  * v4l.c : Video4Linux input module for vlc
3  *****************************************************************************
4  * Copyright (C) 2002 VideoLAN
5  * $Id: v4l.c,v 1.6 2003/03/31 04:26:17 fenrir Exp $
6  *
7  * Author: Samuel Hocevar <sam@zoy.org>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <string.h>
30
31 #include <vlc/vlc.h>
32 #include <vlc/input.h>
33 #include <vlc/vout.h>
34 #include <codecs.h>
35 #include "encoder.h"
36
37 #include <sys/types.h>
38 #include <sys/stat.h>
39 #include <sys/ioctl.h>
40 #include <unistd.h>
41 #include <sys/mman.h>
42 #include <errno.h>
43
44 #include <fcntl.h>
45 #include <linux/videodev.h>
46
47 /* enable audio grabbing */
48 #undef _V4L_AUDIO_
49
50 #ifdef _V4L_AUDIO_
51     #include <sys/soundcard.h>
52 #endif
53
54 /*****************************************************************************
55  * Local prototypes
56  *****************************************************************************/
57 static int  AccessOpen  ( vlc_object_t * );
58 static void AccessClose ( vlc_object_t * );
59 static int  Read        ( input_thread_t *, byte_t *, size_t );
60
61 static int  DemuxOpen  ( vlc_object_t * );
62 static void DemuxClose ( vlc_object_t * );
63 static int  Demux      ( input_thread_t * );
64
65
66 /*****************************************************************************
67  * Module descriptior
68  *****************************************************************************/
69 #define CACHING_TEXT N_("caching value in ms")
70 #define CACHING_LONGTEXT N_( \
71     "Allows you to modify the default caching value for v4l streams. This " \
72     "value should be set in miliseconds units." )
73
74 vlc_module_begin();
75     set_description( _("Video4Linux input") );
76     add_category_hint( N_("v4l"), NULL, VLC_TRUE );
77         add_integer( "v4l-caching", DEFAULT_PTS_DELAY / 1000, NULL,
78                      CACHING_TEXT, CACHING_LONGTEXT, VLC_TRUE );
79     add_submodule();
80         add_shortcut( "v4l" );
81         set_capability( "access", 0 );
82         set_callbacks( AccessOpen, AccessClose );
83     add_submodule();
84         add_shortcut( "v4l" );
85         set_capability( "demux", 200 );
86         set_callbacks( DemuxOpen, DemuxClose );
87 vlc_module_end();
88
89
90 /****************************************************************************
91  * I. Access Part
92  ****************************************************************************/
93 struct access_sys_t
94 {
95     char    *psz_video_device;
96     int     fd;
97
98     vlc_fourcc_t    i_codec;   // if i_codec != i_chroma then we need a compressor
99     video_encoder_t *p_encoder;
100     picture_t       pic;
101
102     int i_channel;
103     int i_audio;
104     int i_norm;
105     int i_tuner;
106     int i_frequency;
107     int i_chroma;
108     int i_width;
109     int i_height;
110
111     struct video_capability vid_cap;
112     struct video_mbuf       vid_mbuf;
113
114     uint8_t *p_video_mmap;
115     int     i_frame_pos;
116     struct video_mmap   vid_mmap;
117
118     uint8_t *p_video_frame;
119     int     i_video_frame_size;
120     int     i_video_frame_size_allocated;
121
122 #ifdef _V4L_AUDIO_
123     char         *psz_adev;
124     int          fd_audio;
125     vlc_fourcc_t i_acodec_raw;
126     int          i_sample_rate;
127     vlc_bool_t   b_stereo;
128
129     uint8_t *p_audio_frame;
130     int     i_audio_frame_size;
131     int     i_audio_frame_size_allocated;
132
133 #endif
134
135     /* header */
136     int     i_header_size;
137     int     i_header_pos;
138     uint8_t *p_header;      // at lest 8 bytes allocated
139
140     /* data */
141     int     i_data_size;
142     int     i_data_pos;
143     uint8_t *p_data;        // never allocated
144
145 };
146
147 /*
148  * header:
149  *  fcc  ".v4l"
150  *  u32    stream count
151  *      fcc "auds"|"vids"       0
152  *      fcc codec               4
153  *      if vids
154  *          u32 width           8
155  *          u32 height          12
156  *          u32 padding         16
157  *      if auds
158  *          u32 channels        12
159  *          u32 samplerate      8
160  *          u32 samplesize      16
161  *
162  * data:
163  *  u32     stream number
164  *  u32     data size
165  *  u8      data
166  */
167
168 static void    SetDWBE( uint8_t *p, uint32_t dw )
169 {
170     p[0] = (dw >> 24)&0xff;
171     p[1] = (dw >> 16)&0xff;
172     p[2] = (dw >>  8)&0xff;
173     p[3] = (dw      )&0xff;
174 }
175
176 static uint32_t GetDWBE( uint8_t *p_buff )
177 {
178     return( ( p_buff[0] << 24 ) + ( p_buff[1] << 16 ) +
179             ( p_buff[2] <<  8 ) + p_buff[3] );
180 }
181
182 /*****************************************************************************
183  * Open: open device:
184  *****************************************************************************
185  *
186  * url: <video device>::::
187  *
188  *****************************************************************************/
189 static int AccessOpen( vlc_object_t *p_this )
190 {
191     input_thread_t *p_input = (input_thread_t *)p_this;
192     access_sys_t   *p_sys;
193     char           *psz_dup, *psz_parser;
194
195     struct video_channel    vid_channel;
196
197     /* create access private data */
198     p_sys = malloc( sizeof( access_sys_t ) );
199     memset( p_sys, 0, sizeof( access_sys_t ) );
200
201     p_sys->psz_video_device = NULL;
202     p_sys->fd               = -1;
203     p_sys->i_channel        = -1;
204     p_sys->i_audio          = -1;
205     p_sys->i_norm           = VIDEO_MODE_AUTO;    // auto
206     p_sys->i_tuner          = -1;
207     p_sys->i_frequency      = -1;
208     p_sys->i_width          = 0;
209     p_sys->i_height         = 0;
210
211     p_sys->i_frame_pos = 0;
212
213     p_sys->i_codec          = VLC_FOURCC( 0, 0, 0, 0 );
214     p_sys->i_video_frame_size_allocated = 0;
215 #ifdef _V4L_AUDIO_
216     p_sys->psz_adev         = NULL;
217     p_sys->fd_audio         = -1;
218     p_sys->i_sample_rate    = 44100;
219     p_sys->b_stereo         = VLC_TRUE;
220 #endif
221
222     p_sys->i_data_size = 0;
223     p_sys->i_data_pos  = 0;
224     p_sys->p_data      = NULL;
225
226     /* parse url and open device(s) */
227     psz_dup = strdup( p_input->psz_name );
228     psz_parser = psz_dup;
229
230     while( *psz_parser && *psz_parser != ':' )
231     {
232         psz_parser++;
233     }
234
235     if( *psz_parser == ':' )
236     {
237         /* read options */
238         for( ;; )
239         {
240             *psz_parser++ = '\0';
241             if( !strncmp( psz_parser, "channel=", strlen( "channel=" ) ) )
242             {
243                 p_sys->i_channel =
244                     strtol( psz_parser + strlen( "channel=" ), &psz_parser, 0 );
245             }
246             else if( !strncmp( psz_parser, "norm=", strlen( "norm=" ) ) )
247             {
248                 psz_parser += strlen( "norm=" );
249                 if( !strncmp( psz_parser, "pal", strlen( "pal" ) ) )
250                 {
251                     p_sys->i_norm = VIDEO_MODE_PAL;
252                     psz_parser += strlen( "pal" );
253                 }
254                 else if( !strncmp( psz_parser, "ntsc", strlen( "ntsc" ) ) )
255                 {
256                     p_sys->i_norm = VIDEO_MODE_NTSC;
257                     psz_parser += strlen( "ntsc" );
258                 }
259                 else if( !strncmp( psz_parser, "secam", strlen( "secam" ) ) )
260                 {
261                     p_sys->i_norm = VIDEO_MODE_SECAM;
262                     psz_parser += strlen( "secam" );
263                 }
264                 else if( !strncmp( psz_parser, "auto", strlen( "auto" ) ) )
265                 {
266                     p_sys->i_norm = VIDEO_MODE_AUTO;
267                     psz_parser += strlen( "auto" );
268                 }
269                 else
270                 {
271                     p_sys->i_norm = strtol( psz_parser, &psz_parser, 0 );
272                 }
273             }
274             else if( !strncmp( psz_parser, "frequency=", strlen( "frequency=" ) ) )
275             {
276                 p_sys->i_frequency =
277                     strtol( psz_parser + strlen( "frequency=" ), &psz_parser, 0 );
278             }
279             else if( !strncmp( psz_parser, "audio=", strlen( "audio=" ) ) )
280             {
281                 p_sys->i_audio = strtol( psz_parser + strlen( "audio=" ), &psz_parser, 0 );
282             }
283             else if( !strncmp( psz_parser, "size=", strlen( "size=" ) ) )
284             {
285                 psz_parser += strlen( "size=" );
286                 if( !strncmp( psz_parser, "subqcif", strlen( "subqcif" ) ) )
287                 {
288                     p_sys->i_width  = 128;
289                     p_sys->i_height = 96;
290                 }
291                 else if( !strncmp( psz_parser, "qsif", strlen( "qsif" ) ) )
292                 {
293                     p_sys->i_width  = 160;
294                     p_sys->i_height = 120;
295                 }
296                 else if( !strncmp( psz_parser, "qcif", strlen( "qcif" ) ) )
297                 {
298                     p_sys->i_width  = 176;
299                     p_sys->i_height = 144;
300                 }
301                 else if( !strncmp( psz_parser, "sif", strlen( "sif" ) ) )
302                 {
303                     p_sys->i_width  = 320;
304                     p_sys->i_height = 244;
305                 }
306                 else if( !strncmp( psz_parser, "cif", strlen( "cif" ) ) )
307                 {
308                     p_sys->i_width  = 352;
309                     p_sys->i_height = 288;
310                 }
311                 else if( !strncmp( psz_parser, "vga", strlen( "vga" ) ) )
312                 {
313                     p_sys->i_width  = 640;
314                     p_sys->i_height = 480;
315                 }
316                 else
317                 {
318                     /* widthxheight */
319                     p_sys->i_width = strtol( psz_parser, &psz_parser, 0 );
320                     if( *psz_parser == 'x' || *psz_parser == 'X')
321                     {
322                         p_sys->i_height = strtol( psz_parser + 1, &psz_parser, 0 );
323                     }
324                     msg_Dbg( p_input, "WxH %dx%d", p_sys->i_width, p_sys->i_height );
325                 }
326             }
327             else if( !strncmp( psz_parser, "tuner=", strlen( "tuner=" ) ) )
328             {
329                 p_sys->i_tuner = strtol( psz_parser + strlen( "tuner=" ), &psz_parser, 0 );
330             }
331             else if( !strncmp( psz_parser, "codec=", strlen( "codec=" ) ) )
332             {
333                 psz_parser += strlen( "codec=" );
334                 if( !strncmp( psz_parser, "mpeg4", strlen( "mpeg4" ) ) )
335                 {
336                     p_sys->i_codec = VLC_FOURCC( 'm', 'p', '4', 'v' );
337                 }
338                 else if( !strncmp( psz_parser, "mpeg1", strlen( "mpeg1" ) ) )
339                 {
340                     p_sys->i_codec = VLC_FOURCC( 'm', 'p', '1', 'v' );
341                 }
342                 else
343                 {
344                     msg_Warn( p_input, "unknow codec" );
345                 }
346             }
347 #ifdef _V4L_AUDIO_
348             else if( !strncmp( psz_parser, "adev=", strlen( "adev=" ) ) )
349             {
350                 int  i_len;
351
352                 psz_parser += strlen( "adev=" );
353                 if( strchr( psz_parser, ':' ) )
354                 {
355                     i_len = strchr( psz_parser, ':' ) - psz_parser;
356                 }
357                 else
358                 {
359                     i_len = strlen( psz_parser );
360                 }
361
362                 p_sys->psz_adev = strndup( psz_parser, i_len );
363
364                 psz_parser += i_len;
365             }
366             else if( !strncmp( psz_parser, "samplerate=", strlen( "samplerate=" ) ) )
367             {
368                 p_sys->i_sample_rate = strtol( psz_parser + strlen( "samplerate=" ), &psz_parser, 0 );
369             }
370             else if( !strncmp( psz_parser, "stereo", strlen( "stereo" ) ) )
371             {
372                 psz_parser += strlen( "stereo" );
373
374                 p_sys->b_stereo = VLC_TRUE;
375             }
376             else if( !strncmp( psz_parser, "mono", strlen( "mono" ) ) )
377             {
378                 psz_parser += strlen( "mono" );
379
380                 p_sys->b_stereo = VLC_FALSE;
381             }
382 #endif
383             else
384             {
385                 msg_Warn( p_input, "unknow option" );
386             }
387
388             while( *psz_parser && *psz_parser != ':' )
389             {
390                 psz_parser++;
391             }
392
393             if( *psz_parser == '\0' )
394             {
395                 break;
396             }
397         }
398     }
399
400     if( *psz_dup )
401     {
402         p_sys->psz_video_device = strdup( psz_dup );
403     }
404     else
405     {
406         p_sys->psz_video_device = strdup( "/dev/video" );
407     }
408     msg_Dbg( p_input, "video device=`%s'", p_sys->psz_video_device );
409
410 #ifdef _V4L_AUDIO_
411     if( p_sys->psz_adev && *p_sys->psz_adev == '\0' )
412     {
413         p_sys->psz_adev = strdup( "/dev/dsp" );
414     }
415     msg_Dbg( p_input, "audio device=`%s'", p_sys->psz_adev );
416 #endif
417
418
419
420     if( ( p_sys->fd = open( p_sys->psz_video_device, O_RDWR ) ) < 0 )
421     {
422         msg_Err( p_input, "cannot open device" );
423         goto failed;
424     }
425
426     if( ioctl( p_sys->fd, VIDIOCGCAP, &p_sys->vid_cap ) < 0 )
427     {
428         msg_Err( p_input, "cannot get capabilities" );
429         goto failed;
430     }
431
432     msg_Dbg( p_input,
433              "V4L device %s %d channels %d audios %d < w < %d %d < h < %d",
434              p_sys->vid_cap.name,
435              p_sys->vid_cap.channels,
436              p_sys->vid_cap.audios,
437              p_sys->vid_cap.minwidth,  p_sys->vid_cap.maxwidth,
438              p_sys->vid_cap.minheight, p_sys->vid_cap.maxheight );
439
440     if( p_sys->i_channel < 0 || p_sys->i_channel >= p_sys->vid_cap.channels )
441     {
442         msg_Dbg( p_input, "invalid channel, falling back on channel 0" );
443         p_sys->i_channel = 0;
444     }
445     if( p_sys->i_audio >= p_sys->vid_cap.audios )
446     {
447         msg_Dbg( p_input, "invalid audio, falling back with no audio" );
448         p_sys->i_audio = -1;
449     }
450
451     if( p_sys->i_width < p_sys->vid_cap.minwidth ||
452         p_sys->i_width > p_sys->vid_cap.maxwidth )
453     {
454         msg_Dbg( p_input, "invalid width" );
455         p_sys->i_width = 0;
456     }
457     if( p_sys->i_height < p_sys->vid_cap.minheight ||
458         p_sys->i_height > p_sys->vid_cap.maxheight )
459     {
460         msg_Dbg( p_input, "invalid height" );
461         p_sys->i_height = 0;
462     }
463
464     if( !( p_sys->vid_cap.type&VID_TYPE_CAPTURE ) )
465     {
466         msg_Err( p_input, "cannot grab" );
467         goto failed;
468     }
469
470     vid_channel.channel = p_sys->i_channel;
471     if( ioctl( p_sys->fd, VIDIOCGCHAN, &vid_channel ) < 0 )
472     {
473         msg_Err( p_input, "cannot get channel infos" );
474         goto failed;
475     }
476     msg_Dbg( p_input,
477              "setting channel %s(%d) %d tuners flags=0x%x type=0x%x norm=0x%x",
478              vid_channel.name,
479              vid_channel.channel,
480              vid_channel.tuners,
481              vid_channel.flags,
482              vid_channel.type,
483              vid_channel.norm );
484
485     if( p_sys->i_tuner >= vid_channel.tuners )
486     {
487         msg_Dbg( p_input, "invalid tuner, falling back on tuner 0" );
488         p_sys->i_tuner = 0;
489     }
490
491     vid_channel.norm = p_sys->i_norm;
492     if( ioctl( p_sys->fd, VIDIOCSCHAN, &vid_channel ) < 0 )
493     {
494         msg_Err( p_input, "cannot set channel" );
495         goto failed;
496     }
497
498     if( vid_channel.flags & VIDEO_VC_TUNER )
499     {
500
501         /* set tuner */
502 #if 0
503         struct video_tuner vid_tuner;
504         if( p_sys->i_tuner >= 0 )
505         {
506             vid_tuner.tuner = p_sys->i_tuner;
507             if( ioctl( p_sys->fd, VIDIOCGTUNER, &vid_tuner ) < 0 )
508             {
509                 msg_Err( p_input, "cannot get tuner" );
510                 goto failed;
511             }
512             msg_Dbg( p_input,
513                      "tuner %s low=%d high=%d, flags=0x%x mode=0x%x signal=0x%x",
514                      vid_tuner.name,
515                      vid_tuner.rangelow, vid_tuner.rangehigh,
516                      vid_tuner.flags,
517                      vid_tuner.mode,
518                      vid_tuner.signal );
519
520             msg_Dbg( p_input,
521                      "setting tuner %s (%d)",
522                      vid_tuner.name, vid_tuner.tuner );
523
524             //vid_tuner.mode = p_sys->i_norm; /* FIXME FIXME to be checked FIXME FIXME */
525             if( ioctl( p_sys->fd, VIDIOCSTUNER, &vid_tuner ) < 0 )
526             {
527                 msg_Err( p_input, "cannot set tuner" );
528                 goto failed;
529             }
530         }
531 #endif
532         /* set frequency */
533         if( p_sys->i_frequency >= 0 )
534         {
535             if( ioctl( p_sys->fd, VIDIOCSFREQ, &p_sys->i_frequency ) < 0 )
536             {
537                 msg_Err( p_input, "cannot set frequency" );
538                 goto failed;
539             }
540             msg_Dbg( p_input, "frequency %d", p_sys->i_frequency );
541         }
542     }
543
544     /* set audio */
545     if( vid_channel.flags & VIDEO_VC_AUDIO )
546     {
547         struct video_audio      vid_audio;
548
549         /* XXX TODO volume, balance, ... */
550         if( p_sys->i_audio >= 0 )
551         {
552             vid_audio.audio = p_sys->i_audio;
553             if( ioctl( p_sys->fd, VIDIOCGAUDIO, &vid_audio ) < 0 )
554             {
555                 msg_Err( p_input, "cannot get audio" );
556                 goto failed;
557             }
558
559             /* unmute audio */
560             vid_audio.flags &= ~VIDEO_AUDIO_MUTE;
561
562             if( ioctl( p_sys->fd, VIDIOCSAUDIO, &vid_audio ) < 0 )
563             {
564                 msg_Err( p_input, "cannot set audio" );
565                 goto failed;
566             }
567
568 #ifdef _V4L_AUDIO_
569             if( p_sys->psz_adev )
570             {
571                 int    i_format;
572                 if( ( p_sys->fd_audio = open( p_sys->psz_adev, O_RDONLY ) ) < 0 )
573                 {
574                     msg_Err( p_input, "cannot open audio device" );
575                     goto failed;
576                 }
577
578                 i_format = AFMT_S16_LE;
579                 if( ioctl( p_sys->fd_audio, SNDCTL_DSP_SETFMT, &i_format ) < 0 ||
580                     i_format != AFMT_S16_LE )
581                 {
582                     msg_Err( p_input, "cannot set audio format (16b little endian)" );
583                     goto failed;
584                 }
585
586                 if( ioctl( p_sys->fd_audio, SNDCTL_DSP_STEREO, &p_sys->b_stereo ) < 0 )
587                 {
588                     msg_Err( p_input, "cannot set audio channels count" );
589                     goto failed;
590                 }
591
592                 if( ioctl( p_sys->fd_audio, SNDCTL_DSP_SPEED, &p_sys->i_sample_rate ) < 0 )
593                 {
594                     msg_Err( p_input, "cannot set audio sample rate" );
595                     goto failed;
596                 }
597
598                 msg_Dbg( p_input,
599                          "adev=`%s' %s %dHz",
600                          p_sys->psz_adev,
601                          p_sys->b_stereo ? "stereo" : "mono",
602                          p_sys->i_sample_rate );
603
604                 p_sys->i_audio_frame_size = 0;
605                 p_sys->i_audio_frame_size_allocated = 10*1024;
606                 p_sys->p_audio_frame = malloc( p_sys->i_audio_frame_size_allocated );
607             }
608 #endif
609         }
610     }
611
612     /* fix width/heigh */
613     if( p_sys->i_width == 0 || p_sys->i_height == 0 )
614     {
615         struct video_window vid_win;
616
617         if( ioctl( p_sys->fd, VIDIOCGWIN, &vid_win ) < 0 )
618         {
619             msg_Err( p_input, "cannot get win" );
620             goto failed;
621         }
622         p_sys->i_width  = vid_win.width;
623         p_sys->i_height = vid_win.height;
624
625         msg_Dbg( p_input, "will use %dx%d", p_sys->i_width, p_sys->i_height );
626     }
627
628     if( ioctl( p_sys->fd, VIDIOCGMBUF, &p_sys->vid_mbuf ) < 0 )
629     {
630         msg_Err( p_input, "mmap unsupported" );
631         goto failed;
632     }
633
634     p_sys->p_video_mmap = mmap( 0, p_sys->vid_mbuf.size,
635                                 PROT_READ|PROT_WRITE,
636                                 MAP_SHARED,
637                                 p_sys->fd,
638                                 0 );
639     if( p_sys->p_video_mmap == MAP_FAILED )
640     {
641         /* FIXME -> normal read */
642         msg_Err( p_input, "mmap failed" );
643         goto failed;
644     }
645
646     p_sys->p_video_frame = NULL;
647
648     /* init grabbing */
649     p_sys->vid_mmap.frame  = 0;
650     p_sys->vid_mmap.width  = p_sys->i_width;
651     p_sys->vid_mmap.height = p_sys->i_height;
652     p_sys->vid_mmap.format = VIDEO_PALETTE_YUV420P;
653     p_sys->i_chroma = VLC_FOURCC( 'I', '4', '2', '0' );
654     if( ioctl( p_sys->fd, VIDIOCMCAPTURE, &p_sys->vid_mmap ) < 0 )
655     {
656         msg_Warn( p_input, "%4.4s refused", (char*)&p_sys->i_chroma );
657
658         p_sys->vid_mmap.format = VIDEO_PALETTE_YUV422P;
659         p_sys->i_chroma = VLC_FOURCC( 'I', '4', '2', '2' );
660
661         if( ioctl( p_sys->fd, VIDIOCMCAPTURE, &p_sys->vid_mmap ) < 0 )
662         {
663             msg_Warn( p_input, "%4.4s refused", (char*)&p_sys->i_chroma );
664
665             msg_Err( p_input, "chroma selection failed" );
666             goto failed;
667         }
668         else
669         {
670             p_sys->i_video_frame_size = p_sys->i_width * p_sys->i_height * 2;
671         }
672     }
673     else
674     {
675         p_sys->i_video_frame_size = p_sys->i_width * p_sys->i_height * 3 / 2;
676     }
677     /* encoder part */
678     if( p_sys->i_codec != VLC_FOURCC( 0, 0, 0, 0 ) )
679     {
680         msg_Dbg( p_input,
681                  "need a rencoder from %4.4s to %4.4s",
682                  (char*)&p_sys->i_chroma,
683                  (char*)&p_sys->i_codec );
684 #define p_enc p_sys->p_encoder
685         p_enc = vlc_object_create( p_input, sizeof( video_encoder_t ) );
686         p_enc->i_codec = p_sys->i_codec;
687         p_enc->i_chroma= p_sys->i_chroma;
688         p_enc->i_width = p_sys->i_width;
689         p_enc->i_height= p_sys->i_height;
690         p_enc->i_aspect= 0;
691
692
693         p_enc->p_module = module_Need( p_enc,
694                                        "video encoder",
695                                        "$video-encoder" );
696         if( !p_enc->p_module )
697         {
698             msg_Warn( p_input,
699                       "no suitable encoder to %4.4s",
700                       (char*)&p_enc->i_codec );
701             vlc_object_destroy( p_enc );
702             goto failed;
703         }
704
705         /* *** init the codec *** */
706         if( p_enc->pf_init( p_enc ) )
707         {
708             msg_Err( p_input, "failed to initialize video encoder plugin" );
709             vlc_object_destroy( p_enc );
710             goto failed;
711         }
712
713         /* *** alloacted buffer *** */
714         if( p_enc->i_buffer_size <= 0 )
715         {
716             p_enc->i_buffer_size = 10 * p_enc->i_width * p_enc->i_height;
717         }
718         p_sys->i_video_frame_size = p_enc->i_buffer_size;
719         p_sys->i_video_frame_size_allocated = p_enc->i_buffer_size;
720         if( !( p_sys->p_video_frame = malloc( p_enc->i_buffer_size ) ) )
721         {
722             msg_Err( p_input, "out of memory" );
723             goto failed;
724         }
725
726         switch( p_sys->i_chroma )
727         {
728             case VLC_FOURCC( 'I', '4', '2', '0' ):
729                 p_sys->pic.i_planes = 3;
730                 p_sys->pic.p[0].i_pitch = p_sys->i_width;
731                 p_sys->pic.p[0].i_lines = p_sys->i_height;
732                 p_sys->pic.p[0].i_pixel_pitch = 1;
733                 p_sys->pic.p[0].i_visible_pitch = p_sys->i_width;
734
735                 p_sys->pic.p[1].i_pitch = p_sys->i_width / 2;
736                 p_sys->pic.p[1].i_lines = p_sys->i_height / 2;
737                 p_sys->pic.p[1].i_pixel_pitch = 1;
738                 p_sys->pic.p[1].i_visible_pitch = p_sys->i_width / 2;
739
740                 p_sys->pic.p[2].i_pitch = p_sys->i_width / 2;
741                 p_sys->pic.p[2].i_lines = p_sys->i_height / 2;
742                 p_sys->pic.p[2].i_pixel_pitch = 1;
743                 p_sys->pic.p[2].i_visible_pitch = p_sys->i_width / 2;
744                 break;
745             default:
746                 msg_Err( p_input, "unsuported chroma" );
747                 vlc_object_destroy( p_enc );
748                 goto failed;
749         }
750 #undef p_enc
751     }
752     else
753     {
754         p_sys->i_codec  = p_sys->i_chroma;
755         p_sys->p_encoder = NULL;
756     }
757
758
759     p_input->pf_read        = Read;
760     p_input->pf_seek        = NULL;
761     p_input->pf_set_area    = NULL;
762     p_input->pf_set_program = NULL;
763
764     p_input->p_access_data  = p_sys;
765
766     vlc_mutex_lock( &p_input->stream.stream_lock );
767     p_input->stream.b_pace_control = 0;
768     p_input->stream.b_seekable = 0;
769     p_input->stream.p_selected_area->i_size = 0;
770     p_input->stream.p_selected_area->i_tell = 0;
771     p_input->stream.i_method = INPUT_METHOD_FILE;
772     vlc_mutex_unlock( &p_input->stream.stream_lock );
773
774     /* Update default_pts to a suitable value for access */
775     p_input->i_pts_delay = config_GetInt( p_input, "v4l-caching" ) * 1000;
776
777     msg_Info( p_input, "v4l grabbing started" );
778
779     /* create header */
780     p_sys->i_header_size = 8 + 20;
781     p_sys->i_header_pos  = 0;
782     p_sys->p_header      = malloc( p_sys->i_header_size );
783
784     memcpy(  &p_sys->p_header[0], ".v4l", 4 );
785     SetDWBE( &p_sys->p_header[4], 1 );
786
787     memcpy(  &p_sys->p_header[ 8], "vids", 4 );
788     memcpy(  &p_sys->p_header[12], &p_sys->i_codec, 4 );
789     SetDWBE( &p_sys->p_header[16], p_sys->i_width );
790     SetDWBE( &p_sys->p_header[20], p_sys->i_height );
791     SetDWBE( &p_sys->p_header[24], 0 );
792
793 #ifdef _V4L_AUDIO_
794     if( p_sys->fd_audio > 0 )
795     {
796         p_sys->i_header_size += 20;
797         p_sys->p_header = realloc( p_sys->p_header, p_sys->i_header_size );
798
799         SetDWBE( &p_sys->p_header[4], 2 );
800
801         memcpy(  &p_sys->p_header[28], "auds", 4 );
802         memcpy(  &p_sys->p_header[32], "araw", 4 );
803         SetDWBE( &p_sys->p_header[36], p_sys->b_stereo ? 2 : 1 );
804         SetDWBE( &p_sys->p_header[40], p_sys->i_sample_rate );
805         SetDWBE( &p_sys->p_header[44], 16 );
806     }
807 #endif
808     return VLC_SUCCESS;
809
810 failed:
811     free( p_sys->psz_video_device );
812     if( p_sys->fd >= 0 )
813     {
814         close( p_sys->fd );
815     }
816     free( p_sys );
817     return VLC_EGENERIC;
818 }
819
820 /*****************************************************************************
821  * V4lClose: close device
822  *****************************************************************************/
823 static void AccessClose( vlc_object_t *p_this )
824 {
825     input_thread_t  *p_input = (input_thread_t *)p_this;
826     access_sys_t    *p_sys   = p_input->p_access_data;
827
828     msg_Info( p_input, "v4l grabbing stoped" );
829
830     free( p_sys->psz_video_device );
831     close( p_sys->fd );
832     if( p_sys->p_video_mmap )
833     {
834         munmap( p_sys->p_video_mmap, p_sys->vid_mbuf.size )
835     }
836 #ifdef _V4L_AUDIO_
837     if( p_sys->fd_audio >= 0 )
838     {
839         close( p_sys->fd_audio );
840     }
841 #endif
842
843     if( p_sys->p_encoder )
844     {
845         p_sys->p_encoder->pf_end( p_sys->p_encoder );
846
847         module_Unneed( p_sys->p_encoder,
848                        p_sys->p_encoder->p_module );
849         vlc_object_destroy( p_sys->p_encoder );
850
851         free( p_sys->p_video_frame );
852     }
853     free( p_sys );
854 }
855
856 #ifdef _V4L_AUDIO_
857 static int GrabAudio( input_thread_t * p_input,
858                       uint8_t **pp_data,
859                       int      *pi_data )
860 {
861     access_sys_t    *p_sys   = p_input->p_access_data;
862     fd_set  fds;
863     struct timeval  timeout;
864     int i_ret;
865     int i_read;
866
867     /* we first try to get an audio frame */
868     FD_ZERO( &fds );
869     FD_SET( p_sys->fd_audio, &fds );
870
871     timeout.tv_sec  = 0;
872     timeout.tv_usec = 0;
873
874     i_ret = select( p_sys->fd_audio + 1, &fds, NULL, NULL, &timeout );
875
876     if( i_ret < 0 && errno != EINTR )
877     {
878         msg_Warn( p_input, "audio select failed" );
879         return VLC_EGENERIC;
880     }
881
882     if( !FD_ISSET( p_sys->fd_audio , &fds) )
883     {
884         return VLC_EGENERIC;
885     }
886
887     i_read = read( p_sys->fd_audio, p_sys->p_audio_frame, p_sys->i_audio_frame_size_allocated );
888
889     if( i_read <= 0 )
890     {
891         return VLC_EGENERIC;
892     }
893
894     p_sys->i_audio_frame_size = i_read;
895
896
897     *pp_data = p_sys->p_audio_frame;
898     *pi_data = p_sys->i_audio_frame_size;
899     return VLC_SUCCESS;
900 }
901 #endif
902
903 static int GrabVideo( input_thread_t * p_input,
904                       uint8_t **pp_data,
905                       int      *pi_data )
906 {
907     access_sys_t    *p_sys   = p_input->p_access_data;
908
909     p_sys->vid_mmap.frame = ( p_sys->i_frame_pos + 1 ) % p_sys->vid_mbuf.frames;
910     for( ;; )
911     {
912         if( ioctl( p_sys->fd, VIDIOCMCAPTURE, &p_sys->vid_mmap ) >= 0 )
913         {
914             break;
915         }
916
917         if( errno != EAGAIN )
918         {
919             msg_Err( p_input, "failed while grabbing new frame" );
920             return( -1 );
921         }
922         msg_Dbg( p_input, "another try ?" );
923     }
924
925     //msg_Warn( p_input, "grab a new frame" );
926
927     while( ioctl(p_sys->fd, VIDIOCSYNC, &p_sys->i_frame_pos) < 0 &&
928            ( errno == EAGAIN || errno == EINTR ) );
929
930
931     p_sys->i_frame_pos = p_sys->vid_mmap.frame;
932
933     if( p_sys->p_encoder )
934     {
935         p_sys->pic.p[0].p_pixels = p_sys->p_video_mmap + p_sys->vid_mbuf.offsets[p_sys->i_frame_pos];
936         p_sys->pic.p[1].p_pixels = p_sys->pic.p[0].p_pixels +
937                                         p_sys->pic.p[0].i_pitch * p_sys->pic.p[0].i_lines;
938         p_sys->pic.p[2].p_pixels = p_sys->pic.p[1].p_pixels +
939                                         p_sys->pic.p[1].i_pitch * p_sys->pic.p[1].i_lines;
940
941         p_sys->i_video_frame_size = p_sys->i_video_frame_size_allocated;
942         p_sys->p_encoder->pf_encode( p_sys->p_encoder,
943                                      &p_sys->pic,
944                                      p_sys->p_video_frame,
945                                      &p_sys->i_video_frame_size );
946     }
947     else
948     {
949         p_sys->p_video_frame = p_sys->p_video_mmap + p_sys->vid_mbuf.offsets[p_sys->i_frame_pos];
950     }
951
952     *pp_data = p_sys->p_video_frame;
953     *pi_data = p_sys->i_video_frame_size;
954     return VLC_SUCCESS;
955 }
956
957 /*****************************************************************************
958  * Read: reads from the device into PES packets.
959  *****************************************************************************
960  * Returns -1 in case of error, 0 in case of EOF, otherwise the number of
961  * bytes.
962  *****************************************************************************/
963 static int Read( input_thread_t * p_input, byte_t * p_buffer,
964                  size_t i_len )
965 {
966     access_sys_t    *p_sys   = p_input->p_access_data;
967     int i_data = 0;
968     int i_stream;
969
970     msg_Info( p_input, "access read" );
971     while( i_len > 0 )
972     {
973
974         /* First copy header if any */
975         if( i_len > 0 && p_sys->i_header_pos < p_sys->i_header_size )
976         {
977             int i_copy;
978
979             i_copy = __MIN( p_sys->i_header_size - p_sys->i_header_pos,
980                             (int)i_len );
981             memcpy( p_buffer,
982                     &p_sys->p_header[p_sys->i_header_pos],
983                     i_copy );
984             p_sys->i_header_pos += i_copy;
985
986             p_buffer += i_copy;
987             i_len -= i_copy;
988             i_data += i_copy;
989         }
990
991         /* then data */
992         if( i_len > 0 && p_sys->i_data_pos < p_sys->i_data_size )
993         {
994             int i_copy;
995
996             i_copy = __MIN( p_sys->i_data_size - p_sys->i_data_pos,
997                             (int)i_len );
998
999             memcpy( p_buffer,
1000                     &p_sys->p_data[p_sys->i_data_pos],
1001                     i_copy );
1002             p_sys->i_data_pos += i_copy;
1003
1004             p_buffer += i_copy;
1005             i_len -= i_copy;
1006             i_data += i_copy;
1007         }
1008
1009         if( i_len <= 0 )
1010         {
1011             return( i_data );
1012         }
1013
1014         /* re fill data by grabbing audio/video */
1015         p_sys->i_data_pos = 0;
1016
1017         /* try grabbing audio frames */
1018 #ifdef _V4L_AUDIO_
1019         i_stream = 1;
1020         if( p_sys->fd_audio < 0 || GrabAudio( p_input, &p_sys->p_data, &p_sys->i_data_size ) )
1021         {
1022             /* and then get video frame if no audio */
1023             i_stream = 0;
1024             if( GrabVideo( p_input, &p_sys->p_data, &p_sys->i_data_size ) )
1025             {
1026                 return -1;
1027             }
1028         }
1029 #else
1030         /* and then get video frame if no audio */
1031         i_stream = 0;
1032         if( GrabVideo( p_input, &p_sys->p_data, &p_sys->i_data_size ) )
1033         {
1034             return -1;
1035         }
1036 #endif
1037
1038         /* create pseudo header */
1039         p_sys->i_header_size = 8;
1040         p_sys->i_header_pos  = 0;
1041         SetDWBE( &p_sys->p_header[0], i_stream );
1042         SetDWBE( &p_sys->p_header[4], p_sys->i_data_size );
1043     }
1044
1045     return i_data;
1046 }
1047
1048 /****************************************************************************
1049  * I. Demux Part
1050  ****************************************************************************/
1051 #define MAX_PACKETS_IN_FIFO 3
1052
1053 static int  DemuxOpen  ( vlc_object_t *p_this )
1054 {
1055     input_thread_t *p_input = (input_thread_t *)p_this;
1056     //demux_sys_t    *p_sys;
1057
1058     uint8_t        *p_peek;
1059     int            i_streams;
1060     int            i;
1061
1062     data_packet_t  *p_pk;
1063
1064     /* Initialize access plug-in structures. */
1065     if( p_input->i_mtu == 0 )
1066     {
1067         /* Improve speed. */
1068         p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE ;
1069     }
1070
1071     /* a little test to see if it's a v4l stream */
1072     if( input_Peek( p_input, &p_peek, 8 ) < 8 )
1073     {
1074         msg_Warn( p_input, "v4l plugin discarded (cannot peek)" );
1075         return( VLC_EGENERIC );
1076     }
1077
1078     if( strncmp( p_peek, ".v4l", 4 ) || GetDWBE( &p_peek[4] ) <= 0 )
1079     {
1080         msg_Warn( p_input, "v4l plugin discarded (not a valid stream)" );
1081         return VLC_EGENERIC;
1082     }
1083
1084     /*  create one program */
1085     vlc_mutex_lock( &p_input->stream.stream_lock );
1086     if( input_InitStream( p_input, 0 ) == -1)
1087     {
1088         vlc_mutex_unlock( &p_input->stream.stream_lock );
1089         msg_Err( p_input, "cannot init stream" );
1090         return( VLC_EGENERIC );
1091     }
1092     if( input_AddProgram( p_input, 0, 0) == NULL )
1093     {
1094         vlc_mutex_unlock( &p_input->stream.stream_lock );
1095         msg_Err( p_input, "cannot add program" );
1096         return( VLC_EGENERIC );
1097     }
1098
1099     p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
1100     p_input->stream.i_mux_rate =  0;
1101
1102     i_streams = GetDWBE( &p_peek[4] );
1103     if( input_Peek( p_input, &p_peek, 8 + 20 * i_streams ) < 8 + 20 * i_streams )
1104     {
1105         msg_Err( p_input, "v4l plugin discarded (cannot peek)" );
1106         return( VLC_EGENERIC );
1107     }
1108     p_peek += 8;
1109
1110     for( i = 0; i < i_streams; i++ )
1111     {
1112         es_descriptor_t *p_es;
1113
1114
1115         p_es = input_AddES( p_input, p_input->stream.pp_programs[0], i + 1, 0 );
1116         p_es->i_stream_id   = i + 1;
1117         if( !strncmp( p_peek, "auds", 4 ) )
1118         {
1119 #define wf ((WAVEFORMATEX*)p_es->p_waveformatex)
1120             p_es->i_cat         = AUDIO_ES;
1121             p_es->i_fourcc      = VLC_FOURCC( p_peek[4], p_peek[5], p_peek[6], p_peek[7] );
1122             p_es->p_waveformatex= malloc( sizeof( WAVEFORMATEX ) );
1123
1124             wf->wFormatTag      = WAVE_FORMAT_UNKNOWN;
1125             wf->nChannels       = GetDWBE( &p_peek[8] );
1126             wf->nSamplesPerSec  = GetDWBE( &p_peek[12] );
1127             wf->wBitsPerSample  = GetDWBE( &p_peek[16] );
1128             wf->nBlockAlign     = wf->wBitsPerSample * wf->nChannels / 8;
1129             wf->nAvgBytesPerSec = wf->nBlockAlign * wf->nSamplesPerSec;
1130             wf->cbSize          = 0;
1131
1132             msg_Dbg( p_input, "added new audio es %d channels %dHz",
1133                      wf->nChannels,
1134                      wf->nSamplesPerSec );
1135
1136             input_SelectES( p_input, p_es );
1137 #undef wf
1138         }
1139         else if( !strncmp( p_peek, "vids", 4 ) )
1140         {
1141 #define bih ((BITMAPINFOHEADER*)p_es->p_bitmapinfoheader)
1142             p_es->i_cat = VIDEO_ES;
1143             p_es->i_fourcc      = VLC_FOURCC( p_peek[4], p_peek[5], p_peek[6], p_peek[7] );
1144
1145             p_es->p_bitmapinfoheader = malloc( sizeof( BITMAPINFOHEADER ) );
1146
1147             bih->biSize     = sizeof( BITMAPINFOHEADER );
1148             bih->biWidth    = GetDWBE( &p_peek[8] );
1149             bih->biHeight   = GetDWBE( &p_peek[12] );
1150             bih->biPlanes   = 0;
1151             bih->biBitCount = 0;
1152             bih->biCompression      = 0;
1153             bih->biSizeImage= 0;
1154             bih->biXPelsPerMeter    = 0;
1155             bih->biYPelsPerMeter    = 0;
1156             bih->biClrUsed  = 0;
1157             bih->biClrImportant     = 0;
1158
1159             msg_Dbg( p_input, "added new video es %4.4s %dx%d",
1160                      (char*)&p_es->i_fourcc,
1161                      bih->biWidth,
1162                      bih->biHeight );
1163
1164             input_SelectES( p_input, p_es );
1165 #undef bih
1166         }
1167
1168         p_peek += 20;
1169     }
1170
1171     p_input->stream.p_selected_program->b_is_ok = 1;
1172     vlc_mutex_unlock( &p_input->stream.stream_lock );
1173
1174     if( input_SplitBuffer( p_input, &p_pk, 8 + i_streams * 20 ) > 0 )
1175     {
1176         input_DeletePacket( p_input->p_method_data, p_pk );
1177     }
1178
1179     p_input->pf_demux = Demux;
1180     return VLC_SUCCESS;
1181 }
1182
1183 static void DemuxClose ( vlc_object_t *p_this )
1184 {
1185     return;
1186 }
1187
1188
1189 static int  Demux      ( input_thread_t *p_input )
1190 {
1191     es_descriptor_t *p_es;
1192     pes_packet_t    *p_pes;
1193
1194     int i_stream;
1195     int i_size;
1196     uint8_t *p_peek;
1197
1198     if( input_Peek( p_input, &p_peek, 8 ) < 8 )
1199     {
1200         msg_Warn( p_input, "cannot peek (EOF ?)" );
1201         return( 0 );
1202     }
1203
1204     i_stream = GetDWBE( &p_peek[0] );
1205     i_size   = GetDWBE( &p_peek[4] );
1206
1207     msg_Dbg( p_input, "stream=%d size=%d", i_stream, i_size );
1208 //    p_es = input_FindES( p_input, i_stream );
1209     p_es = p_input->stream.p_selected_program->pp_es[i_stream];
1210
1211     if( p_es == NULL || p_es->p_decoder_fifo == NULL )
1212     {
1213         msg_Err( p_input, "cannot find decoder" );
1214         return 0;
1215     }
1216
1217     p_pes = input_NewPES( p_input->p_method_data );
1218     if( p_pes == NULL )
1219     {
1220         msg_Warn( p_input, "cannot allocate PES" );
1221         msleep( 1000 );
1222         return( 1 );
1223     }
1224     i_size += 8;
1225     while( i_size > 0 )
1226     {
1227         data_packet_t   *p_data;
1228         int i_read;
1229
1230         if( (i_read = input_SplitBuffer( p_input,
1231                                          &p_data,
1232                                          __MIN( i_size, 10000 ) ) ) <= 0 )
1233         {
1234             input_DeletePES( p_input->p_method_data, p_pes );
1235             return( 0 );
1236         }
1237         if( !p_pes->p_first )
1238         {
1239             p_pes->p_first = p_data;
1240             p_pes->i_nb_data = 1;
1241             p_pes->i_pes_size = i_read;
1242         }
1243         else
1244         {
1245             p_pes->p_last->p_next  = p_data;
1246             p_pes->i_nb_data++;
1247             p_pes->i_pes_size += i_read;
1248         }
1249         p_pes->p_last  = p_data;
1250         i_size -= i_read;
1251     }
1252 //    input_SplitBuffer( p_input, &p_pk, i_size + 8 );
1253     p_pes->p_first->p_payload_start += 8;
1254
1255     vlc_mutex_lock( &p_es->p_decoder_fifo->data_lock );
1256     if( p_es->p_decoder_fifo->i_depth >= MAX_PACKETS_IN_FIFO )
1257     {
1258         /* Wait for the decoder. */
1259         vlc_cond_wait( &p_es->p_decoder_fifo->data_wait, &p_es->p_decoder_fifo->data_lock );
1260     }
1261     vlc_mutex_unlock( &p_es->p_decoder_fifo->data_lock );
1262
1263     p_pes->i_pts = mdate() + p_input->i_pts_delay;
1264
1265     input_DecodePES( p_es->p_decoder_fifo, p_pes );
1266
1267     return 1;
1268 }