⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 v4l2.c

📁 VLC Player Source Code
💻 C
📖 第 1 页 / 共 5 页
字号:
    add_submodule();    add_shortcut( "v4l2c" );    set_description( N_("Video4Linux2 Compressed A/V") );    set_capability( "access", 0 );    /* use these when open as access_demux fails; VLC will use another demux */    set_callbacks( AccessOpen, AccessClose );vlc_module_end();/***************************************************************************** * Access: local prototypes *****************************************************************************/static void CommonClose( vlc_object_t *, demux_sys_t * );static void ParseMRL( demux_sys_t *, char *, vlc_object_t * );static void GetV4L2Params( demux_sys_t *, vlc_object_t * );static void SetAvailControlsByString( vlc_object_t *, demux_sys_t *, int );static int DemuxControl( demux_t *, int, va_list );static int AccessControl( access_t *, int, va_list );static int Demux( demux_t * );static ssize_t AccessRead( access_t *, uint8_t *, size_t );static block_t* GrabVideo( demux_t *p_demux );static block_t* ProcessVideoFrame( demux_t *p_demux, uint8_t *p_frame, size_t );static block_t* GrabAudio( demux_t *p_demux );static bool IsPixelFormatSupported( demux_t *p_demux,                                          unsigned int i_pixelformat );#ifdef HAVE_ALSAstatic char* ResolveALSADeviceName( const char *psz_device );#endifstatic int OpenVideoDev( vlc_object_t *, demux_sys_t *, bool );static int OpenAudioDev( vlc_object_t *, demux_sys_t *, bool );static bool ProbeVideoDev( vlc_object_t *, demux_sys_t *,                                 char *psz_device );static bool ProbeAudioDev( vlc_object_t *, demux_sys_t *,                                 char *psz_device );static int ControlList( vlc_object_t *, int , bool, bool );static int Control( vlc_object_t *, int i_fd,                    const char *psz_name, int i_cid, int i_value );static int DemuxControlCallback( vlc_object_t *p_this, const char *psz_var,                                 vlc_value_t oldval, vlc_value_t newval,                                 void *p_data );static int DemuxControlResetCallback( vlc_object_t *p_this, const char *psz_var,                                      vlc_value_t oldval, vlc_value_t newval,                                      void *p_data );static int AccessControlCallback( vlc_object_t *p_this, const char *psz_var,                                  vlc_value_t oldval, vlc_value_t newval,                                  void *p_data );static int AccessControlResetCallback( vlc_object_t *p_this,                                       const char *psz_var, vlc_value_t oldval,                                       vlc_value_t newval, void *p_data );static const struct{    unsigned int i_v4l2;    int i_fourcc;    int i_rmask;    int i_gmask;    int i_bmask;} v4l2chroma_to_fourcc[] ={    /* Raw data types */    { V4L2_PIX_FMT_GREY,    VLC_FOURCC('G','R','E','Y'), 0, 0, 0 },    { V4L2_PIX_FMT_HI240,   VLC_FOURCC('I','2','4','0'), 0, 0, 0 },    { V4L2_PIX_FMT_RGB555,  VLC_FOURCC('R','V','1','5'), 0x001f,0x03e0,0x7c00 },    { V4L2_PIX_FMT_RGB565,  VLC_FOURCC('R','V','1','6'), 0x001f,0x07e0,0xf800 },    /* Won't work since we don't know how to handle such gmask values     * correctly    { V4L2_PIX_FMT_RGB555X, VLC_FOURCC('R','V','1','5'), 0x007c,0xe003,0x1f00 },    { V4L2_PIX_FMT_RGB565X, VLC_FOURCC('R','V','1','6'), 0x00f8,0xe007,0x1f00 },    */    { V4L2_PIX_FMT_BGR24,   VLC_FOURCC('R','V','2','4'), 0xff0000,0xff00,0xff },    { V4L2_PIX_FMT_RGB24,   VLC_FOURCC('R','V','2','4'), 0xff,0xff00,0xff0000 },    { V4L2_PIX_FMT_BGR32,   VLC_FOURCC('R','V','3','2'), 0xff0000,0xff00,0xff },    { V4L2_PIX_FMT_RGB32,   VLC_FOURCC('R','V','3','2'), 0xff,0xff00,0xff0000 },    { V4L2_PIX_FMT_YUYV,    VLC_FOURCC('Y','U','Y','2'), 0, 0, 0 },    { V4L2_PIX_FMT_YUYV,    VLC_FOURCC('Y','U','Y','V'), 0, 0, 0 },    { V4L2_PIX_FMT_UYVY,    VLC_FOURCC('U','Y','V','Y'), 0, 0, 0 },    { V4L2_PIX_FMT_Y41P,    VLC_FOURCC('I','4','1','N'), 0, 0, 0 },    { V4L2_PIX_FMT_YUV422P, VLC_FOURCC('I','4','2','2'), 0, 0, 0 },    { V4L2_PIX_FMT_YVU420,  VLC_FOURCC('Y','V','1','2'), 0, 0, 0 },    { V4L2_PIX_FMT_YUV411P, VLC_FOURCC('I','4','1','1'), 0, 0, 0 },    { V4L2_PIX_FMT_YUV410,  VLC_FOURCC('I','4','1','0'), 0, 0, 0 },    /* Raw data types, not in V4L2 spec but still in videodev2.h and supported     * by VLC */    { V4L2_PIX_FMT_YUV420,  VLC_FOURCC('I','4','2','0'), 0, 0, 0 },    /* FIXME { V4L2_PIX_FMT_RGB444,  VLC_FOURCC('R','V','3','2') }, */    /* Compressed data types */    { V4L2_PIX_FMT_MJPEG,   VLC_FOURCC('M','J','P','G'), 0, 0, 0 },#if 0    { V4L2_PIX_FMT_JPEG,    VLC_FOURCC('J','P','E','G') },    { V4L2_PIX_FMT_DV,      VLC_FOURCC('?','?','?','?') },    { V4L2_PIX_FMT_MPEG,    VLC_FOURCC('?','?','?','?') },#endif    { 0, 0, 0, 0, 0 }};/** * List of V4L2 chromas were confident enough to use as fallbacks if the * user hasn't provided a --v4l2-chroma value. * * Try YUV chromas first, then RGB little endian and MJPEG as last resort. */static const __u32 p_chroma_fallbacks[] ={ V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_YVU420, V4L2_PIX_FMT_YUV422P,  V4L2_PIX_FMT_YUYV, V4L2_PIX_FMT_UYVY, V4L2_PIX_FMT_BGR24,  V4L2_PIX_FMT_BGR32, V4L2_PIX_FMT_MJPEG };static const struct{    const char *psz_name;    unsigned int i_cid;} controls[] ={    { "brightness", V4L2_CID_BRIGHTNESS },    { "contrast", V4L2_CID_CONTRAST },    { "saturation", V4L2_CID_SATURATION },    { "hue", V4L2_CID_HUE },    { "audio-volume", V4L2_CID_AUDIO_VOLUME },    { "audio-balance", V4L2_CID_AUDIO_BALANCE },    { "audio-bass", V4L2_CID_AUDIO_BASS },    { "audio-treble", V4L2_CID_AUDIO_TREBLE },    { "audio-mute", V4L2_CID_AUDIO_MUTE },    { "audio-loudness", V4L2_CID_AUDIO_LOUDNESS },    { "black-level", V4L2_CID_BLACK_LEVEL },    { "auto-white-balance", V4L2_CID_AUTO_WHITE_BALANCE },    { "do-white-balance", V4L2_CID_DO_WHITE_BALANCE },    { "red-balance", V4L2_CID_RED_BALANCE },    { "blue-balance", V4L2_CID_BLUE_BALANCE },    { "gamma", V4L2_CID_GAMMA },    { "exposure", V4L2_CID_EXPOSURE },    { "autogain", V4L2_CID_AUTOGAIN },    { "gain", V4L2_CID_GAIN },    { "hflip", V4L2_CID_HFLIP },    { "vflip", V4L2_CID_VFLIP },    { "hcenter", V4L2_CID_HCENTER },    { "vcenter", V4L2_CID_VCENTER },    { NULL, 0 }};struct buffer_t{    void *  start;    size_t  length;};struct demux_sys_t{    char *psz_device;  /* Main device from MRL, can be video or audio */    char *psz_vdev;    int  i_fd_video;    char *psz_adev;    int  i_fd_audio;    char *psz_requested_chroma;    /* Video */    io_method io;    int i_pts;    struct v4l2_capability dev_cap;    int i_input;    struct v4l2_input *p_inputs;    int i_selected_input;    int i_standard;    struct v4l2_standard *p_standards;    v4l2_std_id i_selected_standard_id;    int i_audio;    /* V4L2 devices cannot have more than 32 audio inputs */    struct v4l2_audio p_audios[32];    int i_selected_audio_input;    int i_tuner;    struct v4l2_tuner *p_tuners;    int i_codec;    struct v4l2_fmtdesc *p_codecs;    struct buffer_t *p_buffers;    unsigned int i_nbuffers;    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 */    int i_fourcc;    es_out_id_t *p_es_video;    /* Audio */    unsigned int i_sample_rate;    bool b_stereo;    size_t i_audio_max_frame_size;    block_t *p_block_audio;    es_out_id_t *p_es_audio;    int i_audio_method;#ifdef HAVE_ALSA    /* ALSA Audio */    snd_pcm_t *p_alsa_pcm;    size_t i_alsa_frame_size;    int i_alsa_chunk_size;#endif    /* Tuner */    int i_cur_tuner;    int i_frequency;    int i_audio_mode;    /* Controls */    char *psz_set_ctrls;};static int FindMainDevice( vlc_object_t *p_this, demux_sys_t *p_sys,                           int i_flags, bool b_demux,                           bool b_forced ){    /* Find main device (video or audio) */    if( p_sys->psz_device && *p_sys->psz_device )    {        msg_Dbg( p_this, "main device='%s'", p_sys->psz_device );        bool b_maindevice_is_video = false;        /* Try to open as video device */        if( i_flags & FIND_VIDEO )        {            msg_Dbg( p_this, "trying device '%s' as video", p_sys->psz_device );            if( ProbeVideoDev( p_this, p_sys, p_sys->psz_device ) )            {                msg_Dbg( p_this, "'%s' is a video device", p_sys->psz_device );                /* Device was a video device */                free( p_sys->psz_vdev );                p_sys->psz_vdev = p_sys->psz_device;                p_sys->psz_device = NULL;                p_sys->i_fd_video = OpenVideoDev( p_this, p_sys, b_demux );                if( p_sys->i_fd_video < 0 )                    return VLC_EGENERIC;                b_maindevice_is_video = true;                /* If successful we carry on to try the audio if access is forced */            }        }        /* Try to open as audio device only if main device was not detected as video above */        if( i_flags & FIND_AUDIO && !b_maindevice_is_video )        {            msg_Dbg( p_this, "trying device '%s' as audio", p_sys->psz_device );            if( ProbeAudioDev( p_this, p_sys, p_sys->psz_device ) )            {                msg_Dbg( p_this, "'%s' is an audio device", p_sys->psz_device );                /* Device was an audio device */                free( p_sys->psz_adev );                p_sys->psz_adev = p_sys->psz_device;                p_sys->psz_device = NULL;                p_sys->i_fd_audio = OpenAudioDev( p_this, p_sys, b_demux );                if( p_sys->i_fd_audio < 0 )                    return VLC_EGENERIC;                /* If successful we carry on to try the video if access is forced */            }        }    }    /* If no device opened, only continue if the access was forced */    if( b_forced == false        && !( ( i_flags & FIND_VIDEO && p_sys->i_fd_video >= 0 )           || ( i_flags & FIND_AUDIO && p_sys->i_fd_audio >= 0 ) ) )    {        return VLC_EGENERIC;    }    /* Find video device */    if( i_flags & FIND_VIDEO && p_sys->i_fd_video < 0 )    {        if( !p_sys->psz_vdev || !*p_sys->psz_vdev )        {            free( p_sys->psz_vdev );            p_sys->psz_vdev = var_CreateGetString( p_this, "v4l2-dev" );        }        msg_Dbg( p_this, "opening '%s' as video", p_sys->psz_vdev );        if( p_sys->psz_vdev && *p_sys->psz_vdev         && ProbeVideoDev( p_this, p_sys, p_sys->psz_vdev ) )        {            p_sys->i_fd_video = OpenVideoDev( p_this, p_sys, b_demux );        }    }    /* Find audio device */    if( i_flags & FIND_AUDIO && p_sys->i_fd_audio < 0 )    {        if( !p_sys->psz_adev )        {            p_sys->psz_adev = var_CreateGetNonEmptyString( p_this, "v4l2-adev" );        }        msg_Dbg( p_this, "opening '%s' as audio", p_sys->psz_adev );        if( ProbeAudioDev( p_this, p_sys, p_sys->psz_adev ) )        {            p_sys->i_fd_audio = OpenAudioDev( p_this, p_sys, b_demux );        }    }    if( !( ( i_flags & FIND_VIDEO && p_sys->i_fd_video >= 0 )        || ( i_flags & FIND_AUDIO && p_sys->i_fd_audio >= 0 ) ) )    {        return VLC_EGENERIC;    }    return VLC_SUCCESS;}/***************************************************************************** * DemuxOpen: opens v4l2 device, access_demux callback ***************************************************************************** * * url: <video device>:::: * *****************************************************************************/static int DemuxOpen( vlc_object_t *p_this ){    demux_t     *p_demux = (demux_t*)p_this;    demux_sys_t *p_sys;    /* Only when selected */    if( *p_demux->psz_access == '\0' ) return VLC_EGENERIC;    /* Set up p_demux */    p_demux->pf_control = DemuxControl;    p_demux->pf_demux = Demux;    p_demux->info.i_update = 0;    p_demux->info.i_title = 0;    p_demux->info.i_seekpoint = 0;    p_demux->p_sys = p_sys = calloc( 1, sizeof( demux_sys_t ) );    if( p_sys == NULL ) return VLC_ENOMEM;    GetV4L2Params(p_sys, (vlc_object_t *) p_demux);    ParseMRL( p_sys, p_demux->psz_path, (vlc_object_t *) p_demux );#ifdef HAVE_ALSA    /* Alsa support available? */    msg_Dbg( p_demux, "ALSA input support available" );#endif    if( FindMainDevice( p_this, p_sys, FIND_VIDEO|FIND_AUDIO,        true, !strncmp( p_demux->psz_access, "v4l2", 4 ) ) != VLC_SUCCESS )    {        DemuxClose( p_this );        return VLC_EGENERIC;    }    return VLC_SUCCESS;}/***************************************************************************** * GetV4L2Params: fill in p_sys parameters (shared by DemuxOpen and AccessOpen) *****************************************************************************/static void GetV4L2Params( demux_sys_t *p_sys, vlc_object_t *p_obj ){    p_sys->i_video_pts = -1;    p_sys->i_selected_standard_id =

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -