* v4l: updated, now it should grab (and compress if you want) the video.
[vlc.git] / 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.5 2003/03/31 03:46:11 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
833     if( p_sys->p_encoder )
834     {
835         p_sys->p_encoder->pf_end( p_sys->p_encoder );
836
837         module_Unneed( p_sys->p_encoder,
838                        p_sys->p_encoder->p_module );
839         vlc_object_destroy( p_sys->p_encoder );
840
841         free( p_sys->p_video_frame );
842     }
843     free( p_sys );
844 }
845
846 #ifdef _V4L_AUDIO_
847 static int GrabAudio( input_thread_t * p_input,
848                       uint8_t **pp_data,
849                       int      *pi_data )
850 {
851     access_sys_t    *p_sys   = p_input->p_access_data;
852     fd_set  fds;
853     struct timeval  timeout;
854     int i_ret;
855     int i_read;
856
857     /* we first try to get an audio frame */
858     FD_ZERO( &fds );
859     FD_SET( p_sys->fd_audio, &fds );
860
861     timeout.tv_sec  = 0;
862     timeout.tv_usec = 0;
863
864     i_ret = select( p_sys->fd_audio + 1, &fds, NULL, NULL, &timeout );
865
866     if( i_ret < 0 && errno != EINTR )
867     {
868         msg_Warn( p_input, "audio select failed" );
869         return VLC_EGENERIC;
870     }
871
872     if( !FD_ISSET( p_sys->fd_audio , &fds) )
873     {
874         return VLC_EGENERIC;
875     }
876
877     i_read = read( p_sys->fd_audio, p_sys->p_audio_frame, p_sys->i_audio_frame_size_allocated );
878
879     if( i_read <= 0 )
880     {
881         return VLC_EGENERIC;
882     }
883
884     p_sys->i_audio_frame_size = i_read;
885
886
887     *pp_data = p_sys->p_audio_frame;
888     *pi_data = p_sys->i_audio_frame_size;
889     return VLC_SUCCESS;
890 }
891 #endif
892
893 static int GrabVideo( input_thread_t * p_input,
894                       uint8_t **pp_data,
895                       int      *pi_data )
896 {
897     access_sys_t    *p_sys   = p_input->p_access_data;
898
899     p_sys->vid_mmap.frame = ( p_sys->i_frame_pos + 1 ) % p_sys->vid_mbuf.frames;
900     for( ;; )
901     {
902         if( ioctl( p_sys->fd, VIDIOCMCAPTURE, &p_sys->vid_mmap ) >= 0 )
903         {
904             break;
905         }
906
907         if( errno != EAGAIN )
908         {
909             msg_Err( p_input, "failed while grabbing new frame" );
910             return( -1 );
911         }
912         msg_Dbg( p_input, "another try ?" );
913     }
914
915     //msg_Warn( p_input, "grab a new frame" );
916
917     while( ioctl(p_sys->fd, VIDIOCSYNC, &p_sys->i_frame_pos) < 0 &&
918            ( errno == EAGAIN || errno == EINTR ) );
919
920
921     p_sys->i_frame_pos = p_sys->vid_mmap.frame;
922
923     if( p_sys->p_encoder )
924     {
925         p_sys->pic.p[0].p_pixels = p_sys->p_video_mmap + p_sys->vid_mbuf.offsets[p_sys->i_frame_pos];
926         p_sys->pic.p[1].p_pixels = p_sys->pic.p[0].p_pixels +
927                                         p_sys->pic.p[0].i_pitch * p_sys->pic.p[0].i_lines;
928         p_sys->pic.p[2].p_pixels = p_sys->pic.p[1].p_pixels +
929                                         p_sys->pic.p[1].i_pitch * p_sys->pic.p[1].i_lines;
930
931         p_sys->i_video_frame_size = p_sys->i_video_frame_size_allocated;
932         p_sys->p_encoder->pf_encode( p_sys->p_encoder,
933                                      &p_sys->pic,
934                                      p_sys->p_video_frame,
935                                      &p_sys->i_video_frame_size );
936     }
937     else
938     {
939         p_sys->p_video_frame = p_sys->p_video_mmap + p_sys->vid_mbuf.offsets[p_sys->i_frame_pos];
940     }
941
942     *pp_data = p_sys->p_video_frame;
943     *pi_data = p_sys->i_video_frame_size;
944     return VLC_SUCCESS;
945 }
946
947 /*****************************************************************************
948  * Read: reads from the device into PES packets.
949  *****************************************************************************
950  * Returns -1 in case of error, 0 in case of EOF, otherwise the number of
951  * bytes.
952  *****************************************************************************/
953 static int Read( input_thread_t * p_input, byte_t * p_buffer,
954                  size_t i_len )
955 {
956     access_sys_t    *p_sys   = p_input->p_access_data;
957     int i_data = 0;
958     int i_stream;
959
960     msg_Info( p_input, "access read" );
961     while( i_len > 0 )
962     {
963
964         /* First copy header if any */
965         if( i_len > 0 && p_sys->i_header_pos < p_sys->i_header_size )
966         {
967             int i_copy;
968
969             i_copy = __MIN( p_sys->i_header_size - p_sys->i_header_pos,
970                             (int)i_len );
971             memcpy( p_buffer,
972                     &p_sys->p_header[p_sys->i_header_pos],
973                     i_copy );
974             p_sys->i_header_pos += i_copy;
975
976             p_buffer += i_copy;
977             i_len -= i_copy;
978             i_data += i_copy;
979         }
980
981         /* then data */
982         if( i_len > 0 && p_sys->i_data_pos < p_sys->i_data_size )
983         {
984             int i_copy;
985
986             i_copy = __MIN( p_sys->i_data_size - p_sys->i_data_pos,
987                             (int)i_len );
988
989             memcpy( p_buffer,
990                     &p_sys->p_data[p_sys->i_data_pos],
991                     i_copy );
992             p_sys->i_data_pos += i_copy;
993
994             p_buffer += i_copy;
995             i_len -= i_copy;
996             i_data += i_copy;
997         }
998
999         if( i_len <= 0 )
1000         {
1001             return( i_data );
1002         }
1003
1004         /* re fill data by grabbing audio/video */
1005         p_sys->i_data_pos = 0;
1006
1007         /* try grabbing audio frames */
1008 #ifdef _V4L_AUDIO_
1009         i_stream = 1;
1010         if( p_sys->fd_audio < 0 || GrabAudio( p_input, &p_sys->p_data, &p_sys->i_data_size ) )
1011         {
1012             /* and then get video frame if no audio */
1013             i_stream = 0;
1014             if( GrabVideo( p_input, &p_sys->p_data, &p_sys->i_data_size ) )
1015             {
1016                 return -1;
1017             }
1018         }
1019 #else
1020         /* and then get video frame if no audio */
1021         i_stream = 0;
1022         if( GrabVideo( p_input, &p_sys->p_data, &p_sys->i_data_size ) )
1023         {
1024             return -1;
1025         }
1026 #endif
1027
1028         /* create pseudo header */
1029         p_sys->i_header_size = 8;
1030         p_sys->i_header_pos  = 0;
1031         SetDWBE( &p_sys->p_header[0], i_stream );
1032         SetDWBE( &p_sys->p_header[4], p_sys->i_data_size );
1033     }
1034
1035     return i_data;
1036 }
1037
1038 /****************************************************************************
1039  * I. Demux Part
1040  ****************************************************************************/
1041 #define MAX_PACKETS_IN_FIFO 3
1042
1043 static int  DemuxOpen  ( vlc_object_t *p_this )
1044 {
1045     input_thread_t *p_input = (input_thread_t *)p_this;
1046     //demux_sys_t    *p_sys;
1047
1048     uint8_t        *p_peek;
1049     int            i_streams;
1050     int            i;
1051
1052     data_packet_t  *p_pk;
1053
1054     /* Initialize access plug-in structures. */
1055     if( p_input->i_mtu == 0 )
1056     {
1057         /* Improve speed. */
1058         p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE ;
1059     }
1060
1061     /* a little test to see if it's a v4l stream */
1062     if( input_Peek( p_input, &p_peek, 8 ) < 8 )
1063     {
1064         msg_Warn( p_input, "v4l plugin discarded (cannot peek)" );
1065         return( VLC_EGENERIC );
1066     }
1067
1068     if( strncmp( p_peek, ".v4l", 4 ) || GetDWBE( &p_peek[4] ) <= 0 )
1069     {
1070         msg_Warn( p_input, "v4l plugin discarded (not a valid stream)" );
1071         return VLC_EGENERIC;
1072     }
1073
1074     /*  create one program */
1075     vlc_mutex_lock( &p_input->stream.stream_lock );
1076     if( input_InitStream( p_input, 0 ) == -1)
1077     {
1078         vlc_mutex_unlock( &p_input->stream.stream_lock );
1079         msg_Err( p_input, "cannot init stream" );
1080         return( VLC_EGENERIC );
1081     }
1082     if( input_AddProgram( p_input, 0, 0) == NULL )
1083     {
1084         vlc_mutex_unlock( &p_input->stream.stream_lock );
1085         msg_Err( p_input, "cannot add program" );
1086         return( VLC_EGENERIC );
1087     }
1088
1089     p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
1090     p_input->stream.i_mux_rate =  0;
1091
1092     i_streams = GetDWBE( &p_peek[4] );
1093     if( input_Peek( p_input, &p_peek, 8 + 20 * i_streams ) < 8 + 20 * i_streams )
1094     {
1095         msg_Err( p_input, "v4l plugin discarded (cannot peek)" );
1096         return( VLC_EGENERIC );
1097     }
1098     p_peek += 8;
1099
1100     for( i = 0; i < i_streams; i++ )
1101     {
1102         es_descriptor_t *p_es;
1103
1104
1105         p_es = input_AddES( p_input, p_input->stream.pp_programs[0], i + 1, 0 );
1106         p_es->i_stream_id   = i + 1;
1107         if( !strncmp( p_peek, "auds", 4 ) )
1108         {
1109 #define wf ((WAVEFORMATEX*)p_es->p_waveformatex)
1110             p_es->i_cat         = AUDIO_ES;
1111             p_es->i_fourcc      = VLC_FOURCC( p_peek[4], p_peek[5], p_peek[6], p_peek[7] );
1112             p_es->p_waveformatex= malloc( sizeof( WAVEFORMATEX ) );
1113
1114             wf->wFormatTag      = WAVE_FORMAT_UNKNOWN;
1115             wf->nChannels       = GetDWBE( &p_peek[8] );
1116             wf->nSamplesPerSec  = GetDWBE( &p_peek[12] );
1117             wf->wBitsPerSample  = GetDWBE( &p_peek[16] );
1118             wf->nBlockAlign     = wf->wBitsPerSample * wf->nChannels / 8;
1119             wf->nAvgBytesPerSec = wf->nBlockAlign * wf->nSamplesPerSec;
1120             wf->cbSize          = 0;
1121
1122             msg_Dbg( p_input, "added new audio es %d channels %dHz",
1123                      wf->nChannels,
1124                      wf->nSamplesPerSec );
1125
1126             input_SelectES( p_input, p_es );
1127 #undef wf
1128         }
1129         else if( !strncmp( p_peek, "vids", 4 ) )
1130         {
1131 #define bih ((BITMAPINFOHEADER*)p_es->p_bitmapinfoheader)
1132             p_es->i_cat = VIDEO_ES;
1133             p_es->i_fourcc      = VLC_FOURCC( p_peek[4], p_peek[5], p_peek[6], p_peek[7] );
1134
1135             p_es->p_bitmapinfoheader = malloc( sizeof( BITMAPINFOHEADER ) );
1136
1137             bih->biSize     = sizeof( BITMAPINFOHEADER );
1138             bih->biWidth    = GetDWBE( &p_peek[8] );
1139             bih->biHeight   = GetDWBE( &p_peek[12] );
1140             bih->biPlanes   = 0;
1141             bih->biBitCount = 0;
1142             bih->biCompression      = 0;
1143             bih->biSizeImage= 0;
1144             bih->biXPelsPerMeter    = 0;
1145             bih->biYPelsPerMeter    = 0;
1146             bih->biClrUsed  = 0;
1147             bih->biClrImportant     = 0;
1148
1149             msg_Dbg( p_input, "added new video es %4.4s %dx%d",
1150                      (char*)&p_es->i_fourcc,
1151                      bih->biWidth,
1152                      bih->biHeight );
1153
1154             input_SelectES( p_input, p_es );
1155 #undef bih
1156         }
1157
1158         p_peek += 20;
1159     }
1160
1161     p_input->stream.p_selected_program->b_is_ok = 1;
1162     vlc_mutex_unlock( &p_input->stream.stream_lock );
1163
1164     if( input_SplitBuffer( p_input, &p_pk, 8 + i_streams * 20 ) > 0 )
1165     {
1166         input_DeletePacket( p_input->p_method_data, p_pk );
1167     }
1168
1169     p_input->pf_demux = Demux;
1170     return VLC_SUCCESS;
1171 }
1172
1173 static void DemuxClose ( vlc_object_t *p_this )
1174 {
1175     return;
1176 }
1177
1178
1179 static int  Demux      ( input_thread_t *p_input )
1180 {
1181     es_descriptor_t *p_es;
1182     pes_packet_t    *p_pes;
1183
1184     int i_stream;
1185     int i_size;
1186     uint8_t *p_peek;
1187
1188     if( input_Peek( p_input, &p_peek, 8 ) < 8 )
1189     {
1190         msg_Warn( p_input, "cannot peek (EOF ?)" );
1191         return( 0 );
1192     }
1193
1194     i_stream = GetDWBE( &p_peek[0] );
1195     i_size   = GetDWBE( &p_peek[4] );
1196
1197     msg_Dbg( p_input, "stream=%d size=%d", i_stream, i_size );
1198 //    p_es = input_FindES( p_input, i_stream );
1199     p_es = p_input->stream.p_selected_program->pp_es[i_stream];
1200
1201     if( p_es == NULL || p_es->p_decoder_fifo == NULL )
1202     {
1203         msg_Err( p_input, "cannot find decoder" );
1204         return 0;
1205     }
1206
1207     p_pes = input_NewPES( p_input->p_method_data );
1208     if( p_pes == NULL )
1209     {
1210         msg_Warn( p_input, "cannot allocate PES" );
1211         msleep( 1000 );
1212         return( 1 );
1213     }
1214     i_size += 8;
1215     while( i_size > 0 )
1216     {
1217         data_packet_t   *p_data;
1218         int i_read;
1219
1220         if( (i_read = input_SplitBuffer( p_input,
1221                                          &p_data,
1222                                          __MIN( i_size, 10000 ) ) ) <= 0 )
1223         {
1224             input_DeletePES( p_input->p_method_data, p_pes );
1225             return( 0 );
1226         }
1227         if( !p_pes->p_first )
1228         {
1229             p_pes->p_first = p_data;
1230             p_pes->i_nb_data = 1;
1231             p_pes->i_pes_size = i_read;
1232         }
1233         else
1234         {
1235             p_pes->p_last->p_next  = p_data;
1236             p_pes->i_nb_data++;
1237             p_pes->i_pes_size += i_read;
1238         }
1239         p_pes->p_last  = p_data;
1240         i_size -= i_read;
1241     }
1242 //    input_SplitBuffer( p_input, &p_pk, i_size + 8 );
1243     p_pes->p_first->p_payload_start += 8;
1244
1245     vlc_mutex_lock( &p_es->p_decoder_fifo->data_lock );
1246     if( p_es->p_decoder_fifo->i_depth >= MAX_PACKETS_IN_FIFO )
1247     {
1248         /* Wait for the decoder. */
1249         vlc_cond_wait( &p_es->p_decoder_fifo->data_wait, &p_es->p_decoder_fifo->data_lock );
1250     }
1251     vlc_mutex_unlock( &p_es->p_decoder_fifo->data_lock );
1252
1253     p_pes->i_pts = mdate() + p_input->i_pts_delay;
1254
1255     input_DecodePES( p_es->p_decoder_fifo, p_pes );
1256
1257     return 1;
1258 }