X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Faccess%2Fv4l%2Fv4l.c;h=27641684f8836e8d86a57924eb5248fd6bf0a57e;hb=3d6ee48d4aacb1fbd5c2741b7b319a62a47009d9;hp=0cfe12cd3d1a1f139a10ad933e3e6bdbe9ec90d9;hpb=7689bc9224e3d9516c56126980cb68eadca6fcaf;p=vlc diff --git a/modules/access/v4l/v4l.c b/modules/access/v4l/v4l.c index 0cfe12cd3d..27641684f8 100644 --- a/modules/access/v4l/v4l.c +++ b/modules/access/v4l/v4l.c @@ -2,15 +2,17 @@ * v4l.c : Video4Linux input module for vlc ***************************************************************************** * Copyright (C) 2002 VideoLAN - * $Id: v4l.c,v 1.1 2002/08/08 00:35:10 sam Exp $ + * $Id: v4l.c,v 1.36 2003/12/04 16:49:43 sam Exp $ * - * Author: Samuel Hocevar + * Author: Laurent Aimar + * Paul Forgey + * Gildas Bazin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -24,41 +26,376 @@ /***************************************************************************** * Preamble *****************************************************************************/ +#include +#include +#include + #include #include +#include +#include #include #include +#include +#include +#include +#include #include -/***************************************************************************** - * Local prototypes - *****************************************************************************/ -static int V4lOpen ( vlc_object_t * ); -static void V4lClose ( vlc_object_t * ); -static int V4lRead ( input_thread_t *, byte_t *, size_t ); +/* From GStreamer's v4l plugin: + * Because of some really cool feature in video4linux1, also known as + * 'not including sys/types.h and sys/time.h', we had to include it + * ourselves. In all their intelligence, these people decided to fix + * this in the next version (video4linux2) in such a cool way that it + * breaks all compilations of old stuff... + * The real problem is actually that linux/time.h doesn't use proper + * macro checks before defining types like struct timeval. The proper + * fix here is to either fuck the kernel header (which is what we do + * by defining _LINUX_TIME_H, an innocent little hack) or by fixing it + * upstream, which I'll consider doing later on. If you get compiler + * errors here, check your linux/time.h && sys/time.h header setup. +*/ +#define _LINUX_TIME_H + +#include +#include "videodev_mjpeg.h" + +#include /***************************************************************************** * Module descriptior *****************************************************************************/ +static int AccessOpen ( vlc_object_t * ); +static void AccessClose( vlc_object_t * ); + +static int DemuxOpen ( vlc_object_t * ); +static void DemuxClose ( vlc_object_t * ); + +#define CACHING_TEXT N_("Caching value in ms") +#define CACHING_LONGTEXT N_( \ + "Allows you to modify the default caching value for v4l streams. This " \ + "value should be set in miliseconds units." ) +#define VDEV_TEXT N_("Video device name") +#define VDEV_LONGTEXT N_( \ + "Specify the name of the video device that will be used. " \ + "If you don't specify anything, no video device will be used.") +#define ADEV_TEXT N_("Audio device name") +#define ADEV_LONGTEXT N_( \ + "Specify the name of the audio device that will be used. " \ + "If you don't specify anything, no audio device will be used.") +#define CHROMA_TEXT N_("Video input chroma format") +#define CHROMA_LONGTEXT N_( \ + "Force the Video4Linux video device to use a specific chroma format " \ + "(eg. I420 (default), RV24, etc.)") + vlc_module_begin(); - set_description( _("Video4Linux input module") ); - set_capability( "access", 80 ); - set_callbacks( V4lOpen, V4lClose ); + set_description( _("Video4Linux input") ); + add_category_hint( N_("v4l"), NULL, VLC_TRUE ); + add_integer( "v4l-caching", DEFAULT_PTS_DELAY / 1000, NULL, + CACHING_TEXT, CACHING_LONGTEXT, VLC_TRUE ); + add_shortcut( "v4l" ); + set_capability( "access", 10 ); + set_callbacks( AccessOpen, AccessClose ); + + add_string( "v4l-vdev", "/dev/video", 0, VDEV_TEXT, VDEV_LONGTEXT, + VLC_FALSE ); + add_string( "v4l-adev", "/dev/dsp", 0, ADEV_TEXT, ADEV_LONGTEXT, + VLC_FALSE ); + add_string( "v4l-chroma", NULL, NULL, CHROMA_TEXT, CHROMA_LONGTEXT, + VLC_TRUE ); + + add_submodule(); + set_description( _("Video4Linux demuxer") ); + add_shortcut( "v4l" ); + set_capability( "demux", 200 ); + set_callbacks( DemuxOpen, DemuxClose ); vlc_module_end(); -static int i_fd; /***************************************************************************** - * V4lOpen: open device + * Access: local prototypes *****************************************************************************/ -static int V4lOpen( vlc_object_t *p_this ) -{ - input_thread_t * p_input = (input_thread_t *)p_this; +static int Read ( input_thread_t *, byte_t *, size_t ); + +static void ParseMRL ( input_thread_t * ); +static int OpenVideoDev( input_thread_t *, char * ); +static int OpenAudioDev( input_thread_t *, char * ); + +#define MJPEG_BUFFER_SIZE (256*1024) + +struct quicktime_mjpeg_app1 +{ + uint32_t i_reserved; /* set to 0 */ + uint32_t i_tag; /* 'mjpg' */ + uint32_t i_field_size; /* offset following EOI */ + uint32_t i_padded_field_size; /* offset following EOI+pad */ + uint32_t i_next_field; /* offset to next field */ + uint32_t i_DQT_offset; + uint32_t i_DHT_offset; + uint32_t i_SOF_offset; + uint32_t i_SOS_offset; + uint32_t i_data_offset; /* following SOS marker data */ +}; + +static struct +{ + int i_v4l; + int i_fourcc; + +} v4lchroma_to_fourcc[] = +{ + { VIDEO_PALETTE_GREY, VLC_FOURCC( 'G', 'R', 'E', 'Y' ) }, + { VIDEO_PALETTE_HI240, VLC_FOURCC( 'I', '2', '4', '0' ) }, + { VIDEO_PALETTE_RGB565, VLC_FOURCC( 'R', 'V', '1', '6' ) }, + { VIDEO_PALETTE_RGB555, VLC_FOURCC( 'R', 'V', '1', '5' ) }, + { VIDEO_PALETTE_RGB24, VLC_FOURCC( 'R', 'V', '2', '4' ) }, + { VIDEO_PALETTE_RGB32, VLC_FOURCC( 'R', 'V', '3', '2' ) }, + { VIDEO_PALETTE_YUV422, VLC_FOURCC( 'I', '4', '2', '2' ) }, + { VIDEO_PALETTE_YUYV, VLC_FOURCC( 'Y', 'U', 'Y', 'V' ) }, + { VIDEO_PALETTE_UYVY, VLC_FOURCC( 'U', 'Y', 'V', 'Y' ) }, + { VIDEO_PALETTE_YUV420, VLC_FOURCC( 'I', '4', '2', 'N' ) }, + { VIDEO_PALETTE_YUV411, VLC_FOURCC( 'I', '4', '1', 'N' ) }, + { VIDEO_PALETTE_RAW, VLC_FOURCC( 'G', 'R', 'A', 'W' ) }, + { VIDEO_PALETTE_YUV422P, VLC_FOURCC( 'I', '4', '2', '2' ) }, + { VIDEO_PALETTE_YUV420P, VLC_FOURCC( 'I', '4', '2', '0' ) }, + { VIDEO_PALETTE_YUV411P, VLC_FOURCC( 'I', '4', '1', '1' ) }, + { 0, 0 } +}; + +struct access_sys_t +{ + /* Devices */ + char *psz_device; /* Main device from MRL, can be video or audio */ + + char *psz_vdev; + int fd_video; + + char *psz_adev; + int fd_audio; + + /* Video properties */ + picture_t pic; + + int i_fourcc; + int i_channel; + int i_audio; + int i_norm; + int i_tuner; + int i_frequency; + int i_width; + int i_height; + + float f_fps; /* <= 0.0 mean to grab at full rate */ + mtime_t i_video_pts; /* only used when f_fps > 0 */ + + vlc_bool_t b_mjpeg; + int i_decimation; + int i_quality; + + struct video_capability vid_cap; + struct video_mbuf vid_mbuf; + struct mjpeg_requestbuffers mjpeg_buffers; + + uint8_t *p_video_mmap; + int i_frame_pos; + + struct video_mmap vid_mmap; + struct video_picture vid_picture; + + uint8_t *p_video_frame; + int i_video_frame_size; + int i_video_frame_size_allocated; + + /* Audio properties */ + vlc_fourcc_t i_acodec_raw; + int i_sample_rate; + vlc_bool_t b_stereo; + + uint8_t *p_audio_frame; + int i_audio_frame_size; + int i_audio_frame_size_allocated; + + /* header */ + int i_streams; + int i_header_size; + int i_header_pos; + uint8_t *p_header; // at lest 8 bytes allocated + + /* data */ + int i_data_size; + int i_data_pos; + uint8_t *p_data; // never allocated + +}; + +/* + * header: + * fcc ".v4l" + * u32 stream count + * fcc "auds"|"vids" 0 + * fcc codec 4 + * if vids + * u32 width 8 + * u32 height 12 + * u32 padding 16 + * if auds + * u32 channels 12 + * u32 samplerate 8 + * u32 samplesize 16 + * + * data: + * u32 stream number + * u32 data size + * u8 data + */ + +static void SetDWBE( uint8_t *p, uint32_t dw ) +{ + p[0] = (dw >> 24)&0xff; + p[1] = (dw >> 16)&0xff; + p[2] = (dw >> 8)&0xff; + p[3] = (dw )&0xff; +} + +static void SetQWBE( uint8_t *p, uint64_t qw ) +{ + SetDWBE( p, (qw >> 32)&0xffffffff ); + SetDWBE( &p[4], qw&0xffffffff); +} + +/***************************************************************************** + * AccessOpen: opens v4l device + ***************************************************************************** + * + * url: