1 /*****************************************************************************
2 * v4l.c : Video4Linux input module for vlc
3 *****************************************************************************
4 * Copyright (C) 2002-2004 the VideoLAN team
7 * Author: Laurent Aimar <fenrir@via.ecp.fr>
8 * Paul Forgey <paulf at aphrodite dot com>
9 * Gildas Bazin <gbazin@videolan.org>
10 * Benjamin Pracht <bigben at videolan dot org>
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
25 *****************************************************************************/
27 /*****************************************************************************
29 *****************************************************************************/
35 #include <vlc_common.h>
36 #include <vlc_plugin.h>
37 #include <vlc_input.h>
38 #include <vlc_demux.h>
39 #include <vlc_access.h>
40 #include <vlc_picture.h>
41 #include <vlc_charset.h>
44 #include <sys/ioctl.h>
47 #include <arpa/inet.h>
50 /* From GStreamer's v4l plugin:
51 * Because of some really cool feature in video4linux1, also known as
52 * 'not including sys/types.h and sys/time.h', we had to include it
53 * ourselves. In all their intelligence, these people decided to fix
54 * this in the next version (video4linux2) in such a cool way that it
55 * breaks all compilations of old stuff...
56 * The real problem is actually that linux/time.h doesn't use proper
57 * macro checks before defining types like struct timeval. The proper
58 * fix here is to either fuck the kernel header (which is what we do
59 * by defining _LINUX_TIME_H, an innocent little hack) or by fixing it
60 * upstream, which I'll consider doing later on. If you get compiler
61 * errors here, check your linux/time.h && sys/time.h header setup.
65 #include <linux/videodev.h>
66 #include "videodev_mjpeg.h"
71 /*****************************************************************************
73 *****************************************************************************/
74 static int Open ( vlc_object_t
* );
75 static void Close( vlc_object_t
* );
77 #define CACHING_TEXT N_("Caching value in ms")
78 #define CACHING_LONGTEXT N_( \
79 "Caching value for V4L captures. This " \
80 "value should be set in milliseconds." )
81 #define VDEV_TEXT N_("Video device name")
82 #define VDEV_LONGTEXT N_( \
83 "Name of the video device to use. " \
84 "If you don't specify anything, no video device will be used.")
85 #define CHROMA_TEXT N_("Video input chroma format")
86 #define CHROMA_LONGTEXT N_( \
87 "Force the Video4Linux video device to use a specific chroma format " \
88 "(eg. I420 (default), RV24, etc.)")
89 #define FREQUENCY_TEXT N_( "Frequency" )
90 #define FREQUENCY_LONGTEXT N_( \
91 "Frequency to capture (in kHz), if applicable." )
92 #define CHANNEL_TEXT N_( "Channel" )
93 #define CHANNEL_LONGTEXT N_( \
94 "Channel of the card to use (Usually, 0 = tuner, " \
95 "1 = composite, 2 = svideo)." )
96 #define NORM_TEXT N_( "Norm" )
97 #define NORM_LONGTEXT N_( \
98 "Norm of the stream (Automatic, SECAM, PAL, or NTSC)." )
99 #define AUDIO_TEXT N_( "Audio Channel" )
100 #define AUDIO_LONGTEXT N_( \
101 "Audio Channel to use, if there are several audio inputs." )
102 #define WIDTH_TEXT N_( "Width" )
103 #define WIDTH_LONGTEXT N_( "Width of the stream to capture " \
104 "(-1 for autodetect)." )
105 #define HEIGHT_TEXT N_( "Height" )
106 #define HEIGHT_LONGTEXT N_( "Height of the stream to capture " \
107 "(-1 for autodetect)." )
108 #define BRIGHTNESS_TEXT N_( "Brightness" )
109 #define BRIGHTNESS_LONGTEXT N_( \
110 "Brightness of the video input." )
111 #define HUE_TEXT N_( "Hue" )
112 #define HUE_LONGTEXT N_( \
113 "Hue of the video input." )
114 #define COLOUR_TEXT N_( "Color" )
115 #define COLOUR_LONGTEXT N_( \
116 "Color of the video input." )
117 #define CONTRAST_TEXT N_( "Contrast" )
118 #define CONTRAST_LONGTEXT N_( \
119 "Contrast of the video input." )
120 #define TUNER_TEXT N_( "Tuner" )
121 #define TUNER_LONGTEXT N_( "Tuner to use, if there are several ones." )
122 #define MJPEG_TEXT N_( "MJPEG" )
123 #define MJPEG_LONGTEXT N_( \
124 "Set this option if the capture device outputs MJPEG" )
125 #define DECIMATION_TEXT N_( "Decimation" )
126 #define DECIMATION_LONGTEXT N_( \
127 "Decimation level for MJPEG streams" )
128 #define QUALITY_TEXT N_( "Quality" )
129 #define QUALITY_LONGTEXT N_( "Quality of the stream." )
130 #define FPS_TEXT N_( "Framerate" )
131 #define FPS_LONGTEXT N_( "Framerate to capture, if applicable " \
132 "(-1 for autodetect)." )
134 #define AUDIO_DEPRECATED_ERROR N_( \
135 "Alsa or OSS audio capture in the v4l access is deprecated. " \
136 "please use 'v4l:/""/ :input-slave=alsa:/""/' or " \
137 "'v4l:/""/ :input-slave=oss:/""/' instead." )
139 static const int i_norm_list
[] =
140 { VIDEO_MODE_AUTO
, VIDEO_MODE_SECAM
, VIDEO_MODE_PAL
, VIDEO_MODE_NTSC
};
141 static const char *const psz_norm_list_text
[] =
142 { N_("Automatic"), N_("SECAM"), N_("PAL"), N_("NTSC") };
144 #define V4L_DEFAULT "/dev/video"
147 set_shortname( N_("Video4Linux") )
148 set_description( N_("Video4Linux input") )
149 set_category( CAT_INPUT
)
150 set_subcategory( SUBCAT_INPUT_ACCESS
)
152 add_integer( "v4l-caching", DEFAULT_PTS_DELAY
/ 1000, NULL
,
153 CACHING_TEXT
, CACHING_LONGTEXT
, true )
154 add_obsolete_string( "v4l-vdev" );
155 add_obsolete_string( "v4l-adev" );
156 add_string( "v4l-chroma", NULL
, NULL
, CHROMA_TEXT
, CHROMA_LONGTEXT
,
158 add_float( "v4l-fps", -1.0, NULL
, FPS_TEXT
, FPS_LONGTEXT
, true )
159 add_obsolete_integer( "v4l-samplerate" );
160 add_integer( "v4l-channel", 0, NULL
, CHANNEL_TEXT
, CHANNEL_LONGTEXT
,
162 add_integer( "v4l-tuner", -1, NULL
, TUNER_TEXT
, TUNER_LONGTEXT
, true )
163 add_integer( "v4l-norm", VIDEO_MODE_AUTO
, NULL
, NORM_TEXT
, NORM_LONGTEXT
,
165 change_integer_list( i_norm_list
, psz_norm_list_text
, NULL
);
166 add_integer( "v4l-frequency", -1, NULL
, FREQUENCY_TEXT
, FREQUENCY_LONGTEXT
,
168 add_integer( "v4l-audio", -1, NULL
, AUDIO_TEXT
, AUDIO_LONGTEXT
, true )
169 add_obsolete_bool( "v4l-stereo" );
170 add_integer( "v4l-width", 0, NULL
, WIDTH_TEXT
, WIDTH_LONGTEXT
, true )
171 add_integer( "v4l-height", 0, NULL
, HEIGHT_TEXT
, HEIGHT_LONGTEXT
,
173 add_integer( "v4l-brightness", -1, NULL
, BRIGHTNESS_TEXT
,
174 BRIGHTNESS_LONGTEXT
, true )
175 add_integer( "v4l-colour", -1, NULL
, COLOUR_TEXT
, COLOUR_LONGTEXT
,
177 add_integer( "v4l-hue", -1, NULL
, HUE_TEXT
, HUE_LONGTEXT
, true )
178 add_integer( "v4l-contrast", -1, NULL
, CONTRAST_TEXT
, CONTRAST_LONGTEXT
,
180 add_bool( "v4l-mjpeg", false, NULL
, MJPEG_TEXT
, MJPEG_LONGTEXT
,
182 add_integer( "v4l-decimation", 1, NULL
, DECIMATION_TEXT
,
183 DECIMATION_LONGTEXT
, true )
184 add_integer( "v4l-quality", 100, NULL
, QUALITY_TEXT
, QUALITY_LONGTEXT
,
187 add_shortcut( "v4l" )
188 set_capability( "access_demux", 10 )
189 set_callbacks( Open
, Close
)
192 /*****************************************************************************
193 * Access: local prototypes
194 *****************************************************************************/
195 static int Demux ( demux_t
* );
196 static int Control( demux_t
*, int, va_list );
198 static void ParseMRL ( demux_t
* );
199 static int OpenVideoDev( demux_t
*, char * );
200 static block_t
*GrabVideo( demux_t
* );
202 #define MJPEG_BUFFER_SIZE (256*1024)
204 struct quicktime_mjpeg_app1
206 uint32_t i_reserved
; /* set to 0 */
207 uint32_t i_tag
; /* 'mjpg' */
208 uint32_t i_field_size
; /* offset following EOI */
209 uint32_t i_padded_field_size
; /* offset following EOI+pad */
210 uint32_t i_next_field
; /* offset to next field */
211 uint32_t i_DQT_offset
;
212 uint32_t i_DHT_offset
;
213 uint32_t i_SOF_offset
;
214 uint32_t i_SOS_offset
;
215 uint32_t i_data_offset
; /* following SOS marker data */
221 vlc_fourcc_t i_fourcc
;
223 } v4lchroma_to_fourcc
[] =
225 { VIDEO_PALETTE_GREY
, VLC_CODEC_GREY
},
226 { VIDEO_PALETTE_HI240
, VLC_FOURCC( 'I', '2', '4', '0' ) },
227 { VIDEO_PALETTE_RGB565
, VLC_CODEC_RGB16
},
228 { VIDEO_PALETTE_RGB555
, VLC_CODEC_RGB15
},
229 { VIDEO_PALETTE_RGB24
, VLC_CODEC_RGB24
},
230 { VIDEO_PALETTE_RGB32
, VLC_CODEC_RGB32
},
231 { VIDEO_PALETTE_YUV422
, VLC_CODEC_YUYV
},
232 { VIDEO_PALETTE_YUYV
, VLC_CODEC_YUYV
},
233 { VIDEO_PALETTE_UYVY
, VLC_CODEC_UYVY
},
234 { VIDEO_PALETTE_YUV420
, VLC_FOURCC( 'I', '4', '2', 'N' ) },
235 { VIDEO_PALETTE_YUV411
, VLC_FOURCC( 'I', '4', '1', 'N' ) },
236 { VIDEO_PALETTE_RAW
, VLC_FOURCC( 'G', 'R', 'A', 'W' ) },
237 { VIDEO_PALETTE_YUV422P
, VLC_CODEC_I422
},
238 { VIDEO_PALETTE_YUV420P
, VLC_CODEC_I420
},
239 { VIDEO_PALETTE_YUV411P
, VLC_CODEC_I411
},
246 char *psz_device
; /* Main device from MRL */
249 /* Video properties */
266 float f_fps
; /* <= 0.0 mean to grab at full rate */
267 mtime_t i_video_pts
; /* only used when f_fps > 0 */
273 struct video_capability vid_cap
;
274 struct video_mbuf vid_mbuf
;
275 struct mjpeg_requestbuffers mjpeg_buffers
;
277 uint8_t *p_video_mmap
;
280 struct video_mmap vid_mmap
;
281 struct video_picture vid_picture
;
283 int i_video_frame_size
;
288 # define v4l1_close close
289 # define v4l1_ioctl ioctl
290 # define v4l1_mmap mmap
291 # define v4l1_munmap munmap
292 # define v4l1_open vlc_open
295 /*****************************************************************************
296 * Open: opens v4l device
297 *****************************************************************************
299 * url: <video device>::::
301 *****************************************************************************/
302 static int Open( vlc_object_t
*p_this
)
304 demux_t
*p_demux
= (demux_t
*)p_this
;
307 /* Only when selected */
308 if( *p_demux
->psz_access
== '\0' )
312 p_demux
->pf_demux
= Demux
;
313 p_demux
->pf_control
= Control
;
314 p_demux
->info
.i_update
= 0;
315 p_demux
->info
.i_title
= 0;
316 p_demux
->info
.i_seekpoint
= 0;
317 p_demux
->p_sys
= p_sys
= calloc( 1, sizeof( demux_sys_t
) );
321 p_sys
->i_audio
= var_CreateGetInteger( p_demux
, "v4l-audio" );
322 p_sys
->i_channel
= var_CreateGetInteger( p_demux
, "v4l-channel" );
323 p_sys
->i_norm
= var_CreateGetInteger( p_demux
, "v4l-norm" );
324 p_sys
->i_tuner
= var_CreateGetInteger( p_demux
, "v4l-tuner" );
325 p_sys
->i_frequency
= var_CreateGetInteger( p_demux
, "v4l-frequency" );
327 p_sys
->f_fps
= var_CreateGetFloat( p_demux
, "v4l-fps" );
328 p_sys
->i_width
= var_CreateGetInteger( p_demux
, "v4l-width" );
329 p_sys
->i_height
= var_CreateGetInteger( p_demux
, "v4l-height" );
330 p_sys
->i_video_pts
= -1;
331 p_sys
->i_brightness
= var_CreateGetInteger( p_demux
, "v4l-brightness" );
333 p_sys
->i_hue
= var_CreateGetInteger( p_demux
, "v4l-hue" );
334 p_sys
->i_colour
= var_CreateGetInteger( p_demux
, "v4l-colour" );
335 p_sys
->i_contrast
= var_CreateGetInteger( p_demux
, "v4l-contrast" );
337 p_sys
->b_mjpeg
= var_CreateGetBool( p_demux
, "v4l-mjpeg" );
338 p_sys
->i_decimation
= var_CreateGetInteger( p_demux
, "v4l-decimation" );
339 p_sys
->i_quality
= var_CreateGetInteger( p_demux
, "v4l-quality" );
341 p_sys
->psz_device
= NULL
;
348 msg_Dbg( p_this
, "opening device '%s'", p_sys
->psz_device
);
349 p_sys
->i_fd
= OpenVideoDev( p_demux
, p_sys
->psz_device
);
350 if( p_sys
->i_fd
< 0 )
357 msg_Dbg( p_demux
, "v4l grabbing started" );
359 /* Declare elementary streams */
361 es_format_Init( &fmt
, VIDEO_ES
, p_sys
->i_fourcc
);
362 fmt
.video
.i_width
= p_sys
->i_width
;
363 fmt
.video
.i_height
= p_sys
->i_height
;
364 fmt
.video
.i_sar_num
= 4 * fmt
.video
.i_height
;
365 fmt
.video
.i_sar_den
= 3 * fmt
.video
.i_width
;
367 /* Setup rgb mask for RGB formats */
368 switch( p_sys
->i_fourcc
)
370 case VLC_CODEC_RGB15
:
371 fmt
.video
.i_rmask
= 0x001f;
372 fmt
.video
.i_gmask
= 0x03e0;
373 fmt
.video
.i_bmask
= 0x7c00;
375 case VLC_CODEC_RGB16
:
376 fmt
.video
.i_rmask
= 0x001f;
377 fmt
.video
.i_gmask
= 0x07e0;
378 fmt
.video
.i_bmask
= 0xf800;
380 case VLC_CODEC_RGB24
:
381 case VLC_CODEC_RGB32
:
382 fmt
.video
.i_rmask
= 0x00ff0000;
383 fmt
.video
.i_gmask
= 0x0000ff00;
384 fmt
.video
.i_bmask
= 0x000000ff;
388 msg_Dbg( p_demux
, "added new video es %4.4s %dx%d",
389 (char*)&fmt
.i_codec
, fmt
.video
.i_width
, fmt
.video
.i_height
);
390 p_sys
->p_es
= es_out_Add( p_demux
->out
, &fmt
);
392 /* Update default_pts to a suitable value for access */
393 var_Create( p_demux
, "v4l-caching", VLC_VAR_INTEGER
| VLC_VAR_DOINHERIT
);
398 /*****************************************************************************
399 * Close: close device, free resources
400 *****************************************************************************/
401 static void Close( vlc_object_t
*p_this
)
403 demux_t
*p_demux
= (demux_t
*)p_this
;
404 demux_sys_t
*p_sys
= p_demux
->p_sys
;
406 free( p_sys
->psz_device
);
407 if( p_sys
->i_fd
>= 0 ) v4l1_close( p_sys
->i_fd
);
412 v4l1_ioctl( p_sys
->i_fd
, MJPIOC_QBUF_CAPT
, &i_noframe
);
415 if( p_sys
->p_video_mmap
&& p_sys
->p_video_mmap
!= MAP_FAILED
)
418 v4l1_munmap( p_sys
->p_video_mmap
, p_sys
->mjpeg_buffers
.size
*
419 p_sys
->mjpeg_buffers
.count
);
421 v4l1_munmap( p_sys
->p_video_mmap
, p_sys
->vid_mbuf
.size
);
427 /*****************************************************************************
429 *****************************************************************************/
430 static int Control( demux_t
*p_demux
, int i_query
, va_list args
)
437 /* Special for access_demux */
438 case DEMUX_CAN_PAUSE
:
440 case DEMUX_CAN_CONTROL_PACE
:
441 pb
= (bool*)va_arg( args
, bool * );
445 case DEMUX_GET_PTS_DELAY
:
446 pi64
= (int64_t*)va_arg( args
, int64_t * );
447 *pi64
= (int64_t)var_GetInteger( p_demux
, "v4l-caching" ) * 1000;
451 pi64
= (int64_t*)va_arg( args
, int64_t * );
455 /* TODO implement others */
463 /*****************************************************************************
465 *****************************************************************************/
466 static int Demux( demux_t
*p_demux
)
468 demux_sys_t
*p_sys
= p_demux
->p_sys
;
470 block_t
*p_block
= GrabVideo( p_demux
);
474 msleep( 10000 ); /* Unfortunately v4l doesn't allow polling */
478 es_out_Control( p_demux
->out
, ES_OUT_SET_PCR
, p_block
->i_pts
);
479 es_out_Send( p_demux
->out
, p_sys
->p_es
, p_block
);
484 /*****************************************************************************
485 * ParseMRL: parse the options contained in the MRL
486 *****************************************************************************/
487 static void ParseMRL( demux_t
*p_demux
)
489 demux_sys_t
*p_sys
= p_demux
->p_sys
;
491 char *psz_dup
= strdup( p_demux
->psz_path
);
492 char *psz_parser
= psz_dup
;
494 while( *psz_parser
&& *psz_parser
!= ':' )
499 if( *psz_parser
== ':' )
504 *psz_parser
++ = '\0';
505 if( !strncmp( psz_parser
, "channel=", strlen( "channel=" ) ) )
507 p_sys
->i_channel
= strtol( psz_parser
+ strlen( "channel=" ),
510 else if( !strncmp( psz_parser
, "norm=", strlen( "norm=" ) ) )
512 psz_parser
+= strlen( "norm=" );
513 if( !strncmp( psz_parser
, "pal", strlen( "pal" ) ) )
515 p_sys
->i_norm
= VIDEO_MODE_PAL
;
516 psz_parser
+= strlen( "pal" );
518 else if( !strncmp( psz_parser
, "ntsc", strlen( "ntsc" ) ) )
520 p_sys
->i_norm
= VIDEO_MODE_NTSC
;
521 psz_parser
+= strlen( "ntsc" );
523 else if( !strncmp( psz_parser
, "secam", strlen( "secam" ) ) )
525 p_sys
->i_norm
= VIDEO_MODE_SECAM
;
526 psz_parser
+= strlen( "secam" );
528 else if( !strncmp( psz_parser
, "auto", strlen( "auto" ) ) )
530 p_sys
->i_norm
= VIDEO_MODE_AUTO
;
531 psz_parser
+= strlen( "auto" );
535 p_sys
->i_norm
= strtol( psz_parser
, &psz_parser
, 0 );
538 else if( !strncmp( psz_parser
, "frequency=",
539 strlen( "frequency=" ) ) )
542 strtol( psz_parser
+ strlen( "frequency=" ),
544 if( p_sys
->i_frequency
< 30000 )
546 msg_Warn( p_demux
, "v4l syntax has changed : "
547 "'frequency' is now channel frequency in kHz");
550 else if( !strncmp( psz_parser
, "audio=", strlen( "audio=" ) ) )
552 p_sys
->i_audio
= strtol( psz_parser
+ strlen( "audio=" ),
555 else if( !strncmp( psz_parser
, "size=", strlen( "size=" ) ) )
557 psz_parser
+= strlen( "size=" );
558 if( !strncmp( psz_parser
, "subqcif", strlen( "subqcif" ) ) )
560 p_sys
->i_width
= 128;
561 p_sys
->i_height
= 96;
563 else if( !strncmp( psz_parser
, "qsif", strlen( "qsif" ) ) )
565 p_sys
->i_width
= 160;
566 p_sys
->i_height
= 120;
568 else if( !strncmp( psz_parser
, "qcif", strlen( "qcif" ) ) )
570 p_sys
->i_width
= 176;
571 p_sys
->i_height
= 144;
573 else if( !strncmp( psz_parser
, "sif", strlen( "sif" ) ) )
575 p_sys
->i_width
= 320;
576 p_sys
->i_height
= 244;
578 else if( !strncmp( psz_parser
, "cif", strlen( "cif" ) ) )
580 p_sys
->i_width
= 352;
581 p_sys
->i_height
= 288;
583 else if( !strncmp( psz_parser
, "vga", strlen( "vga" ) ) )
585 p_sys
->i_width
= 640;
586 p_sys
->i_height
= 480;
591 p_sys
->i_width
= strtol( psz_parser
, &psz_parser
, 0 );
592 if( *psz_parser
== 'x' || *psz_parser
== 'X')
594 p_sys
->i_height
= strtol( psz_parser
+ 1,
597 msg_Dbg( p_demux
, "WxH %dx%d", p_sys
->i_width
,
601 else if( !strncmp( psz_parser
, "brightness=", strlen( "brightness=" ) ) )
603 p_sys
->i_brightness
= strtol( psz_parser
+ strlen( "brightness=" ),
606 else if( !strncmp( psz_parser
, "colour=", strlen( "colour=" ) ) )
608 p_sys
->i_colour
= strtol( psz_parser
+ strlen( "colour=" ),
611 else if( !strncmp( psz_parser
, "hue=", strlen( "hue=" ) ) )
613 p_sys
->i_hue
= strtol( psz_parser
+ strlen( "hue=" ),
616 else if( !strncmp( psz_parser
, "contrast=", strlen( "contrast=" ) ) )
618 p_sys
->i_contrast
= strtol( psz_parser
+ strlen( "contrast=" ),
621 else if( !strncmp( psz_parser
, "tuner=", strlen( "tuner=" ) ) )
623 p_sys
->i_tuner
= strtol( psz_parser
+ strlen( "tuner=" ),
626 else if( !strncmp( psz_parser
, "mjpeg", strlen( "mjpeg" ) ) )
628 psz_parser
+= strlen( "mjpeg" );
630 p_sys
->b_mjpeg
= true;
632 else if( !strncmp( psz_parser
, "decimation=",
633 strlen( "decimation=" ) ) )
635 p_sys
->i_decimation
=
636 strtol( psz_parser
+ strlen( "decimation=" ),
639 else if( !strncmp( psz_parser
, "quality=",
640 strlen( "quality=" ) ) )
643 strtol( psz_parser
+ strlen( "quality=" ),
646 else if( !strncmp( psz_parser
, "fps=", strlen( "fps=" ) ) )
648 p_sys
->f_fps
= us_strtof( psz_parser
+ strlen( "fps=" ),
651 else if( !strncmp( psz_parser
, "adev=", strlen( "adev=" ) )
652 || !strncmp( psz_parser
, "samplerate=", strlen( "samplerate=" ) )
653 || !strncmp( psz_parser
, "stereo", strlen( "stereo" ) )
654 || !strncmp( psz_parser
, "mono", strlen( "mono" ) ) )
656 if( strchr( psz_parser
, ':' ) )
657 psz_parser
= strchr( psz_parser
, ':' );
659 psz_parser
+= strlen( psz_parser
);
660 msg_Err( p_demux
, AUDIO_DEPRECATED_ERROR
);
664 msg_Warn( p_demux
, "unknown option" );
667 while( *psz_parser
&& *psz_parser
!= ':' )
672 if( *psz_parser
== '\0' )
680 p_sys
->psz_device
= strdup( psz_dup
);
682 p_sys
->psz_device
= strdup( V4L_DEFAULT
);
686 /*****************************************************************************
688 *****************************************************************************/
689 static int OpenVideoDev( demux_t
*p_demux
, char *psz_device
)
691 demux_sys_t
*p_sys
= p_demux
->p_sys
;
694 struct video_channel vid_channel
;
695 struct mjpeg_params mjpeg
;
698 if( ( i_fd
= v4l1_open( psz_device
, O_RDWR
) ) < 0 )
700 msg_Err( p_demux
, "cannot open device (%m)" );
704 if( v4l1_ioctl( i_fd
, VIDIOCGCAP
, &p_sys
->vid_cap
) < 0 )
706 msg_Err( p_demux
, "cannot get capabilities (%m)" );
711 "V4L device %s %d channels %d audios %d < w < %d %d < h < %d",
713 p_sys
->vid_cap
.channels
,
714 p_sys
->vid_cap
.audios
,
715 p_sys
->vid_cap
.minwidth
, p_sys
->vid_cap
.maxwidth
,
716 p_sys
->vid_cap
.minheight
, p_sys
->vid_cap
.maxheight
);
718 if( p_sys
->i_channel
< 0 || p_sys
->i_channel
>= p_sys
->vid_cap
.channels
)
720 msg_Dbg( p_demux
, "invalid channel, falling back on channel 0" );
721 p_sys
->i_channel
= 0;
723 if( p_sys
->vid_cap
.audios
&& p_sys
->i_audio
>= p_sys
->vid_cap
.audios
)
725 msg_Dbg( p_demux
, "invalid audio, falling back with no audio" );
729 if( p_sys
->i_width
< p_sys
->vid_cap
.minwidth
||
730 p_sys
->i_width
> p_sys
->vid_cap
.maxwidth
)
732 msg_Dbg( p_demux
, "invalid width %i", p_sys
->i_width
);
735 if( p_sys
->i_height
< p_sys
->vid_cap
.minheight
||
736 p_sys
->i_height
> p_sys
->vid_cap
.maxheight
)
738 msg_Dbg( p_demux
, "invalid height %i", p_sys
->i_height
);
742 if( !( p_sys
->vid_cap
.type
& VID_TYPE_CAPTURE
) )
744 msg_Err( p_demux
, "cannot grab" );
748 vid_channel
.channel
= p_sys
->i_channel
;
749 if( v4l1_ioctl( i_fd
, VIDIOCGCHAN
, &vid_channel
) < 0 )
751 msg_Err( p_demux
, "cannot get channel infos (%m)" );
755 "setting channel %s(%d) %d tuners flags=0x%x type=0x%x norm=0x%x",
756 vid_channel
.name
, vid_channel
.channel
, vid_channel
.tuners
,
757 vid_channel
.flags
, vid_channel
.type
, vid_channel
.norm
);
759 if( p_sys
->i_tuner
>= vid_channel
.tuners
)
761 msg_Dbg( p_demux
, "invalid tuner, falling back on tuner 0" );
765 vid_channel
.norm
= p_sys
->i_norm
;
766 if( v4l1_ioctl( i_fd
, VIDIOCSCHAN
, &vid_channel
) < 0 )
768 msg_Err( p_demux
, "cannot set channel (%m)" );
772 if( vid_channel
.flags
& VIDEO_VC_TUNER
)
777 struct video_tuner vid_tuner
;
778 if( p_sys
->i_tuner
>= 0 )
780 vid_tuner
.tuner
= p_sys
->i_tuner
;
781 if( v4l1_ioctl( i_fd
, VIDIOCGTUNER
, &vid_tuner
) < 0 )
783 msg_Err( p_demux
, "cannot get tuner (%m)" );
786 msg_Dbg( p_demux
, "tuner %s low=%d high=%d, flags=0x%x "
787 "mode=0x%x signal=0x%x",
788 vid_tuner
.name
, vid_tuner
.rangelow
, vid_tuner
.rangehigh
,
789 vid_tuner
.flags
, vid_tuner
.mode
, vid_tuner
.signal
);
791 msg_Dbg( p_demux
, "setting tuner %s (%d)",
792 vid_tuner
.name
, vid_tuner
.tuner
);
794 /* FIXME FIXME to be checked FIXME FIXME */
795 //vid_tuner.mode = p_sys->i_norm;
796 if( v4l1_ioctl( i_fd
, VIDIOCSTUNER
, &vid_tuner
) < 0 )
798 msg_Err( p_demux
, "cannot set tuner (%m)" );
804 /* Show a warning if frequency is < than 30000.
805 * User is certainly usint old syntax. */
809 if( p_sys
->i_frequency
>= 0 )
811 int driver_frequency
= p_sys
->i_frequency
* 16 /1000;
812 if( v4l1_ioctl( i_fd
, VIDIOCSFREQ
, &driver_frequency
) < 0 )
814 msg_Err( p_demux
, "cannot set frequency (%m)" );
817 msg_Dbg( p_demux
, "frequency %d (%d)", p_sys
->i_frequency
,
823 if( vid_channel
.flags
& VIDEO_VC_AUDIO
)
825 struct video_audio vid_audio
;
827 /* XXX TODO volume, balance, ... */
828 if( p_sys
->i_audio
>= 0 )
830 vid_audio
.audio
= p_sys
->i_audio
;
831 if( v4l1_ioctl( i_fd
, VIDIOCGAUDIO
, &vid_audio
) < 0 )
833 msg_Err( p_demux
, "cannot get audio (%m)" );
838 vid_audio
.flags
&= ~VIDEO_AUDIO_MUTE
;
840 if( v4l1_ioctl( i_fd
, VIDIOCSAUDIO
, &vid_audio
) < 0 )
842 msg_Err( p_demux
, "cannot set audio (%m)" );
849 /* establish basic params with input and norm before feeling width
853 struct quicktime_mjpeg_app1 p_app1
;
856 if( v4l1_ioctl( i_fd
, MJPIOC_G_PARAMS
, &mjpeg
) < 0 )
858 msg_Err( p_demux
, "cannot get mjpeg params (%m)" );
861 mjpeg
.input
= p_sys
->i_channel
;
862 mjpeg
.norm
= p_sys
->i_norm
;
863 mjpeg
.decimation
= p_sys
->i_decimation
;
866 mjpeg
.img_width
= p_sys
->i_width
/ p_sys
->i_decimation
;
867 if( p_sys
->i_height
)
868 mjpeg
.img_height
= p_sys
->i_height
/ p_sys
->i_decimation
;
870 /* establish Quicktime APP1 marker while we are here */
875 p_app1
.i_reserved
= 0;
876 p_app1
.i_tag
= VLC_FOURCC( 'm','j','p','g' );
877 p_app1
.i_field_size
= 0;
878 p_app1
.i_padded_field_size
= 0;
879 p_app1
.i_next_field
= 0;
880 /* XXX WARNING XXX */
881 /* these's nothing magic about these values. We are dangerously
882 * assuming the encoder card is encoding mjpeg-a and is not throwing
883 * in marker tags we aren't expecting. It's bad enough we have to
884 * search through the jpeg output for every frame we grab just to
885 * find the first field's end marker, so we take this risk to boost
887 * This is really something the driver could do for us because this
888 * does conform to standards outside of Apple Quicktime.
891 p_app1
.i_DQT_offset
= hton32( i_offset
);
893 p_app1
.i_DHT_offset
= hton32( i_offset
);
895 p_app1
.i_SOF_offset
= hton32( i_offset
);
897 p_app1
.i_SOS_offset
= hton32( i_offset
);
899 p_app1
.i_data_offset
= hton32( i_offset
);
900 memcpy(mjpeg
.APP_data
, &p_app1
, sizeof(struct quicktime_mjpeg_app1
));
902 /* SOF and SOS aren't specified by the mjpeg API because they aren't
903 * optional. They will be present in the output. */
904 mjpeg
.jpeg_markers
= JPEG_MARKER_DHT
| JPEG_MARKER_DQT
;
906 if( v4l1_ioctl( i_fd
, MJPIOC_S_PARAMS
, &mjpeg
) < 0 )
908 msg_Err( p_demux
, "cannot set mjpeg params (%m)" );
912 p_sys
->i_width
= mjpeg
.img_width
* mjpeg
.HorDcm
;
913 p_sys
->i_height
= mjpeg
.img_height
* mjpeg
.VerDcm
*
914 mjpeg
.field_per_buff
;
917 /* fix width/height */
918 if( !p_sys
->b_mjpeg
&& ( p_sys
->i_width
== 0 || p_sys
->i_height
== 0 ) )
920 struct video_window vid_win
;
922 if( v4l1_ioctl( i_fd
, VIDIOCGWIN
, &vid_win
) < 0 )
924 msg_Err( p_demux
, "cannot get win (%m)" );
927 p_sys
->i_width
= vid_win
.width
;
928 p_sys
->i_height
= vid_win
.height
;
930 if( !p_sys
->i_width
|| !p_sys
->i_height
)
932 p_sys
->i_width
= p_sys
->vid_cap
.maxwidth
;
933 p_sys
->i_height
= p_sys
->vid_cap
.maxheight
;
936 if( !p_sys
->i_width
|| !p_sys
->i_height
)
938 msg_Err( p_demux
, "invalid video size (%ix%i)",
939 p_sys
->i_width
, p_sys
->i_height
);
943 msg_Dbg( p_demux
, "will use %dx%d", p_sys
->i_width
, p_sys
->i_height
);
946 if( !p_sys
->b_mjpeg
)
948 /* set hue/color/.. */
949 if( v4l1_ioctl( i_fd
, VIDIOCGPICT
, &p_sys
->vid_picture
) == 0 )
951 struct video_picture vid_picture
= p_sys
->vid_picture
;
953 if( p_sys
->i_brightness
>= 0 && p_sys
->i_brightness
< 65536 )
955 vid_picture
.brightness
= p_sys
->i_brightness
;
957 if( p_sys
->i_colour
>= 0 && p_sys
->i_colour
< 65536 )
959 vid_picture
.colour
= p_sys
->i_colour
;
961 if( p_sys
->i_hue
>= 0 && p_sys
->i_hue
< 65536 )
963 vid_picture
.hue
= p_sys
->i_hue
;
965 if( p_sys
->i_contrast
>= 0 && p_sys
->i_contrast
< 65536 )
967 vid_picture
.contrast
= p_sys
->i_contrast
;
969 if( v4l1_ioctl( i_fd
, VIDIOCSPICT
, &vid_picture
) == 0 )
971 msg_Dbg( p_demux
, "v4l device uses brightness: %d",
972 vid_picture
.brightness
);
973 msg_Dbg( p_demux
, "v4l device uses colour: %d",
974 vid_picture
.colour
);
975 msg_Dbg( p_demux
, "v4l device uses hue: %d", vid_picture
.hue
);
976 msg_Dbg( p_demux
, "v4l device uses contrast: %d",
977 vid_picture
.contrast
);
978 p_sys
->vid_picture
= vid_picture
;
982 /* Find out video format used by device */
983 if( v4l1_ioctl( i_fd
, VIDIOCGPICT
, &p_sys
->vid_picture
) == 0 )
985 struct video_picture vid_picture
= p_sys
->vid_picture
;
991 psz
= var_CreateGetString( p_demux
, "v4l-chroma" );
993 const vlc_fourcc_t i_chroma
=
994 vlc_fourcc_GetCodecFromString( VIDEO_ES
, psz
);
997 vid_picture
.palette
= 0;
999 /* Find out v4l chroma code */
1000 for( i
= 0; v4lchroma_to_fourcc
[i
].i_v4l
!= 0; i
++ )
1002 if( v4lchroma_to_fourcc
[i
].i_fourcc
== i_chroma
)
1004 vid_picture
.palette
= v4lchroma_to_fourcc
[i
].i_v4l
;
1011 if( vid_picture
.palette
&&
1012 !v4l1_ioctl( i_fd
, VIDIOCSPICT
, &vid_picture
) )
1014 p_sys
->vid_picture
= vid_picture
;
1018 /* Try to set the format to something easy to encode */
1019 vid_picture
.palette
= VIDEO_PALETTE_YUV420P
;
1020 if( v4l1_ioctl( i_fd
, VIDIOCSPICT
, &vid_picture
) == 0 )
1022 p_sys
->vid_picture
= vid_picture
;
1026 vid_picture
.palette
= VIDEO_PALETTE_YUV422P
;
1027 if( v4l1_ioctl( i_fd
, VIDIOCSPICT
, &vid_picture
) == 0 )
1029 p_sys
->vid_picture
= vid_picture
;
1034 /* Find out final format */
1035 for( i
= 0; v4lchroma_to_fourcc
[i
].i_v4l
!= 0; i
++ )
1037 if( v4lchroma_to_fourcc
[i
].i_v4l
== p_sys
->vid_picture
.palette
)
1039 p_sys
->i_fourcc
= v4lchroma_to_fourcc
[i
].i_fourcc
;
1046 msg_Err( p_demux
, "ioctl VIDIOCGPICT failed" );
1051 if( p_sys
->b_mjpeg
)
1055 p_sys
->mjpeg_buffers
.count
= 8;
1056 p_sys
->mjpeg_buffers
.size
= MJPEG_BUFFER_SIZE
;
1058 if( v4l1_ioctl( i_fd
, MJPIOC_REQBUFS
, &p_sys
->mjpeg_buffers
) < 0 )
1060 msg_Err( p_demux
, "mmap unsupported" );
1064 p_sys
->p_video_mmap
= v4l1_mmap( 0,
1065 p_sys
->mjpeg_buffers
.size
* p_sys
->mjpeg_buffers
.count
,
1066 PROT_READ
| PROT_WRITE
, MAP_SHARED
, i_fd
, 0 );
1067 if( p_sys
->p_video_mmap
== MAP_FAILED
)
1069 msg_Err( p_demux
, "mmap failed" );
1073 p_sys
->i_fourcc
= VLC_CODEC_MJPG
;
1074 p_sys
->i_frame_pos
= -1;
1076 /* queue up all the frames */
1077 for( i
= 0; i
< (int)p_sys
->mjpeg_buffers
.count
; i
++ )
1079 if( v4l1_ioctl( i_fd
, MJPIOC_QBUF_CAPT
, &i
) < 0 )
1081 msg_Err( p_demux
, "unable to queue frame" );
1088 /* Fill in picture_t fields */
1089 if( picture_Setup( &p_sys
->pic
, p_sys
->i_fourcc
,
1090 p_sys
->i_width
, p_sys
->i_height
,
1093 msg_Err( p_demux
, "unsupported chroma" );
1096 p_sys
->i_video_frame_size
= 0;
1097 for( i
= 0; i
< p_sys
->pic
.i_planes
; i
++ )
1099 p_sys
->i_video_frame_size
+= p_sys
->pic
.p
[i
].i_visible_lines
*
1100 p_sys
->pic
.p
[i
].i_visible_pitch
;
1103 msg_Dbg( p_demux
, "v4l device uses frame size: %i",
1104 p_sys
->i_video_frame_size
);
1105 msg_Dbg( p_demux
, "v4l device uses chroma: %4.4s",
1106 (char*)&p_sys
->i_fourcc
);
1108 /* Allocate mmap buffer */
1109 if( v4l1_ioctl( i_fd
, VIDIOCGMBUF
, &p_sys
->vid_mbuf
) < 0 )
1111 msg_Err( p_demux
, "mmap unsupported" );
1115 p_sys
->p_video_mmap
= v4l1_mmap( 0, p_sys
->vid_mbuf
.size
,
1116 PROT_READ
|PROT_WRITE
, MAP_SHARED
,
1118 if( p_sys
->p_video_mmap
== MAP_FAILED
)
1120 /* FIXME -> normal read */
1121 msg_Err( p_demux
, "mmap failed" );
1126 p_sys
->vid_mmap
.frame
= 0;
1127 p_sys
->vid_mmap
.width
= p_sys
->i_width
;
1128 p_sys
->vid_mmap
.height
= p_sys
->i_height
;
1129 p_sys
->vid_mmap
.format
= p_sys
->vid_picture
.palette
;
1130 if( v4l1_ioctl( i_fd
, VIDIOCMCAPTURE
, &p_sys
->vid_mmap
) < 0 )
1132 msg_Warn( p_demux
, "%4.4s refused", (char*)&p_sys
->i_fourcc
);
1133 msg_Err( p_demux
, "chroma selection failed" );
1141 if( i_fd
>= 0 ) v4l1_close( i_fd
);
1145 /*****************************************************************************
1147 *****************************************************************************/
1148 static uint8_t *GrabCapture( demux_t
*p_demux
)
1150 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1151 int i_captured_frame
= p_sys
->i_frame_pos
;
1153 p_sys
->vid_mmap
.frame
= (p_sys
->i_frame_pos
+ 1) % p_sys
->vid_mbuf
.frames
;
1155 while( v4l1_ioctl( p_sys
->i_fd
, VIDIOCMCAPTURE
, &p_sys
->vid_mmap
) < 0 )
1157 if( errno
!= EAGAIN
)
1159 msg_Err( p_demux
, "failed capturing new frame" );
1163 if( !vlc_object_alive (p_demux
) )
1168 msg_Dbg( p_demux
, "grab failed, trying again" );
1171 while( v4l1_ioctl(p_sys
->i_fd
, VIDIOCSYNC
, &p_sys
->i_frame_pos
) < 0 )
1173 if( errno
!= EAGAIN
&& errno
!= EINTR
)
1175 msg_Err( p_demux
, "failed syncing new frame" );
1180 p_sys
->i_frame_pos
= p_sys
->vid_mmap
.frame
;
1181 /* leave i_video_frame_size alone */
1182 return p_sys
->p_video_mmap
+ p_sys
->vid_mbuf
.offsets
[i_captured_frame
];
1185 static uint8_t *GrabMJPEG( demux_t
*p_demux
)
1187 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1188 struct mjpeg_sync sync
;
1189 uint8_t *p_frame
, *p_field
, *p
;
1192 struct quicktime_mjpeg_app1
*p_app1
= NULL
;
1194 /* re-queue the last frame we sync'd */
1195 if( p_sys
->i_frame_pos
!= -1 )
1197 while( v4l1_ioctl( p_sys
->i_fd
, MJPIOC_QBUF_CAPT
,
1198 &p_sys
->i_frame_pos
) < 0 )
1200 if( errno
!= EAGAIN
&& errno
!= EINTR
)
1202 msg_Err( p_demux
, "failed capturing new frame" );
1208 /* sync on the next frame */
1209 while( v4l1_ioctl( p_sys
->i_fd
, MJPIOC_SYNC
, &sync
) < 0 )
1211 if( errno
!= EAGAIN
&& errno
!= EINTR
)
1213 msg_Err( p_demux
, "failed syncing new frame" );
1218 p_sys
->i_frame_pos
= sync
.frame
;
1219 p_frame
= p_sys
->p_video_mmap
+ p_sys
->mjpeg_buffers
.size
* sync
.frame
;
1221 /* p_frame now points to the data. fix up the Quicktime APP1 marker */
1223 tag
= hton16( tag
);
1227 p
= memmem( p_field
, sync
.length
, &tag
, 2 );
1231 p
+= 2; /* data immediately following EOI */
1233 p_app1
= (struct quicktime_mjpeg_app1
*)(p_field
+ 6);
1235 i_size
= ((uint32_t)(p
- p_field
));
1236 i_size
= hton32( i_size
);
1237 memcpy( &p_app1
->i_field_size
, &i_size
, 4 );
1239 while( *p
== 0xff && *(p
+1) == 0xff )
1242 i_size
= ((uint32_t)(p
- p_field
));
1243 i_size
= hton32( i_size
);
1244 memcpy( &p_app1
->i_padded_field_size
, &i_size
, 4 );
1248 tag
= hton16( tag
);
1249 p_field
= memmem( p
, sync
.length
- (size_t)(p
- p_frame
), &tag
, 2 );
1253 i_size
= (uint32_t)(p_field
- p_frame
);
1254 i_size
= hton32( i_size
);
1255 memcpy( &p_app1
->i_next_field
, &i_size
, 4 );
1258 p_app1
= (struct quicktime_mjpeg_app1
*)(p_field
+ 6);
1260 tag
= hton16( tag
);
1261 p
= memmem( p_field
, sync
.length
- (size_t)(p_field
- p_frame
),
1266 /* sometimes the second field doesn't have the EOI. just put it
1269 p
= p_frame
+ sync
.length
;
1270 memcpy( p
, &tag
, 2 );
1275 i_size
= (uint32_t)(p
- p_field
);
1276 i_size
= hton32( i_size
);
1277 memcpy( &p_app1
->i_field_size
, &i_size
, 4 );
1278 i_size
= (uint32_t)(sync
.length
- (uint32_t)(p_field
- p_frame
));
1279 i_size
= hton32( i_size
);
1280 memcpy( &p_app1
->i_padded_field_size
, &i_size
, 4 );
1283 p_sys
->i_video_frame_size
= sync
.length
;
1287 static block_t
*GrabVideo( demux_t
*p_demux
)
1289 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1293 if( p_sys
->f_fps
>= 0.1 && p_sys
->i_video_pts
> 0 )
1295 mtime_t i_dur
= (mtime_t
)((double)1000000 / (double)p_sys
->f_fps
);
1297 /* Did we wait long enough ? (frame rate reduction) */
1298 if( p_sys
->i_video_pts
+ i_dur
> mdate() ) return 0;
1301 if( p_sys
->b_mjpeg
) p_frame
= GrabMJPEG( p_demux
);
1302 else p_frame
= GrabCapture( p_demux
);
1304 if( !p_frame
) return 0;
1306 if( !( p_block
= block_New( p_demux
, p_sys
->i_video_frame_size
) ) )
1308 msg_Warn( p_demux
, "cannot get block" );
1312 memcpy( p_block
->p_buffer
, p_frame
, p_sys
->i_video_frame_size
);
1313 p_sys
->i_video_pts
= p_block
->i_pts
= p_block
->i_dts
= mdate();