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

📄 v4l2.c

📁 vlc源码
💻 C
📖 第 1 页 / 共 5 页
字号:
            default:                msg_Err( p_demux, "Failed to wait (VIDIOC_DQBUF)" );                return 0;            }        }        /* Find frame? */        unsigned int i;        for( i = 0; i < p_sys->i_nbuffers; i++ )        {            if( buf.m.userptr == (unsigned long)p_sys->p_buffers[i].start &&                buf.length == p_sys->p_buffers[i].length ) break;        }        if( i >= p_sys->i_nbuffers )        {            msg_Err( p_demux, "Failed capturing new frame as i>=nbuffers" );            return 0;        }        p_block = ProcessVideoFrame( p_demux, (uint8_t*)buf.m.userptr, buf.bytesused );        if( !p_block ) return 0;        /* Unlock */        if( v4l2_ioctl( p_sys->i_fd_video, VIDIOC_QBUF, &buf ) < 0 )        {            msg_Err( p_demux, "Failed to unlock (VIDIOC_QBUF)" );            block_Release( p_block );            return 0;        }        break;    }    /* Timestamp */    p_sys->i_video_pts = p_block->i_pts = p_block->i_dts = mdate();    return p_block;}/***************************************************************************** * ProcessVideoFrame: Helper function to take a buffer and copy it into * a new block *****************************************************************************/static block_t* ProcessVideoFrame( demux_t *p_demux, uint8_t *p_frame, size_t i_size ){    block_t *p_block;    if( !p_frame ) return 0;    /* New block */    if( !( p_block = block_New( p_demux, i_size ) ) )    {        msg_Warn( p_demux, "Cannot get new block" );        return 0;    }    /* Copy frame */    memcpy( p_block->p_buffer, p_frame, i_size );    return p_block;}/***************************************************************************** * GrabAudio: Grab an audio frame *****************************************************************************/static block_t* GrabAudio( demux_t *p_demux ){    demux_sys_t *p_sys = p_demux->p_sys;    struct audio_buf_info buf_info;    int i_read = 0, i_correct;    block_t *p_block;    if( p_sys->p_block_audio ) p_block = p_sys->p_block_audio;    else p_block = block_New( p_demux, p_sys->i_audio_max_frame_size );    if( !p_block )    {        msg_Warn( p_demux, "cannot get block" );        return 0;    }    p_sys->p_block_audio = p_block;#ifdef HAVE_ALSA    if( p_sys->i_audio_method & AUDIO_METHOD_ALSA )    {        /* ALSA */        i_read = snd_pcm_readi( p_sys->p_alsa_pcm, p_block->p_buffer, p_sys->i_alsa_chunk_size );        if( i_read <= 0 )        {            int i_resume;            switch( i_read )            {                case -EAGAIN:                    break;                case -EPIPE:                    /* xrun */                    snd_pcm_prepare( p_sys->p_alsa_pcm );                    break;                case -ESTRPIPE:                    /* suspend */                    i_resume = snd_pcm_resume( p_sys->p_alsa_pcm );                    if( i_resume < 0 && i_resume != -EAGAIN ) snd_pcm_prepare( p_sys->p_alsa_pcm );                    break;                default:                    msg_Err( p_demux, "Failed to read alsa frame (%s)", snd_strerror( i_read ) );                    return 0;            }        }        else        {            /* convert from frames to bytes */            i_read *= p_sys->i_alsa_frame_size;        }    }    else#endif    if( p_sys->i_audio_method & AUDIO_METHOD_OSS )    {        /* OSS */        i_read = read( p_sys->i_fd_audio, p_block->p_buffer,                    p_sys->i_audio_max_frame_size );    }    if( i_read <= 0 ) return 0;    p_block->i_buffer = i_read;    p_sys->p_block_audio = 0;    /* Correct the date because of kernel buffering */    i_correct = i_read;    if( p_sys->i_audio_method & AUDIO_METHOD_OSS )    {        /* OSS */        if( ioctl( p_sys->i_fd_audio, SNDCTL_DSP_GETISPACE, &buf_info ) == 0 )        {            i_correct += buf_info.bytes;        }    }#ifdef HAVE_ALSA    else if( p_sys->i_audio_method & AUDIO_METHOD_ALSA )    {        /* ALSA */        int i_err;        snd_pcm_sframes_t delay = 0;        if( ( i_err = snd_pcm_delay( p_sys->p_alsa_pcm, &delay ) ) >= 0 )        {            size_t i_correction_delta = delay * p_sys->i_alsa_frame_size;            /* Test for overrun */            if( i_correction_delta > p_sys->i_audio_max_frame_size )            {                msg_Warn( p_demux, "ALSA read overrun (%zu > %zu)",                          i_correction_delta, p_sys->i_audio_max_frame_size );                i_correction_delta = p_sys->i_audio_max_frame_size;                snd_pcm_prepare( p_sys->p_alsa_pcm );            }            i_correct += i_correction_delta;        }        else        {            /* delay failed so reset */            msg_Warn( p_demux, "ALSA snd_pcm_delay failed (%s)", snd_strerror( i_err ) );            snd_pcm_prepare( p_sys->p_alsa_pcm );        }    }#endif    /* Timestamp */    p_block->i_pts = p_block->i_dts =        mdate() - INT64_C(1000000) * (mtime_t)i_correct /        2 / ( p_sys->b_stereo ? 2 : 1) / p_sys->i_sample_rate;    return p_block;}/***************************************************************************** * Helper function to initalise video IO using the Read method *****************************************************************************/static int InitRead( demux_t *p_demux, int i_fd, unsigned int i_buffer_size ){    demux_sys_t *p_sys = p_demux->p_sys;    p_sys->p_buffers = calloc( 1, sizeof( *p_sys->p_buffers ) );    if( !p_sys->p_buffers )        goto open_failed;    p_sys->p_buffers[0].length = i_buffer_size;    p_sys->p_buffers[0].start = malloc( i_buffer_size );    if( !p_sys->p_buffers[0].start )        goto open_failed;    return VLC_SUCCESS;open_failed:    return VLC_EGENERIC;}/***************************************************************************** * Helper function to initalise video IO using the mmap method *****************************************************************************/static int InitMmap( demux_t *p_demux, int i_fd ){    demux_sys_t *p_sys = p_demux->p_sys;    struct v4l2_requestbuffers req;    memset( &req, 0, sizeof(req) );    req.count = 4;    req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;    req.memory = V4L2_MEMORY_MMAP;    if( v4l2_ioctl( i_fd, VIDIOC_REQBUFS, &req ) < 0 )    {        msg_Err( p_demux, "device does not support mmap i/o" );        goto open_failed;    }    if( req.count < 2 )    {        msg_Err( p_demux, "Insufficient buffer memory" );        goto open_failed;    }    p_sys->p_buffers = calloc( req.count, sizeof( *p_sys->p_buffers ) );    if( !p_sys->p_buffers )    {        msg_Err( p_demux, "Out of memory" );        goto open_failed;    }    for( p_sys->i_nbuffers = 0; p_sys->i_nbuffers < req.count; ++p_sys->i_nbuffers )    {        struct v4l2_buffer buf;        memset( &buf, 0, sizeof(buf) );        buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;        buf.memory = V4L2_MEMORY_MMAP;        buf.index = p_sys->i_nbuffers;        if( v4l2_ioctl( i_fd, VIDIOC_QUERYBUF, &buf ) < 0 )        {            msg_Err( p_demux, "VIDIOC_QUERYBUF" );            goto open_failed;        }        p_sys->p_buffers[p_sys->i_nbuffers].length = buf.length;        p_sys->p_buffers[p_sys->i_nbuffers].start =            v4l2_mmap( NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, i_fd, buf.m.offset );        if( p_sys->p_buffers[p_sys->i_nbuffers].start == MAP_FAILED )        {            msg_Err( p_demux, "mmap failed (%m)" );            goto open_failed;        }    }    return VLC_SUCCESS;open_failed:    return VLC_EGENERIC;}/***************************************************************************** * Helper function to initalise video IO using the userbuf method *****************************************************************************/static int InitUserP( demux_t *p_demux, int i_fd, unsigned int i_buffer_size ){    demux_sys_t *p_sys = p_demux->p_sys;    struct v4l2_requestbuffers req;    unsigned int i_page_size;    i_page_size = sysconf(_SC_PAGESIZE);    i_buffer_size = ( i_buffer_size + i_page_size - 1 ) & ~( i_page_size - 1);    memset( &req, 0, sizeof(req) );    req.count = 4;    req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;    req.memory = V4L2_MEMORY_USERPTR;    if( v4l2_ioctl( i_fd, VIDIOC_REQBUFS, &req ) < 0 )    {        msg_Err( p_demux, "device does not support user pointer i/o" );        return VLC_EGENERIC;    }    p_sys->p_buffers = calloc( 4, sizeof( *p_sys->p_buffers ) );    if( !p_sys->p_buffers )        goto open_failed;    for( p_sys->i_nbuffers = 0; p_sys->i_nbuffers < 4; ++p_sys->i_nbuffers )    {        p_sys->p_buffers[p_sys->i_nbuffers].length = i_buffer_size;        if( posix_memalign( &p_sys->p_buffers[p_sys->i_nbuffers].start,                /* boundary */ i_page_size, i_buffer_size ) )            goto open_failed;    }    return VLC_SUCCESS;open_failed:    free( p_sys->p_buffers );    return VLC_EGENERIC;}/***************************************************************************** * IsPixelFormatSupported: returns true if the specified V4L2 pixel format is * in the array of supported formats returned by the driver *****************************************************************************/static bool IsPixelFormatSupported( demux_t *p_demux, unsigned int i_pixelformat ){    demux_sys_t *p_sys = p_demux->p_sys;    for( int i_index = 0; i_index < p_sys->i_codec; i_index++ )    {        if( p_sys->p_codecs[i_index].pixelformat == i_pixelformat )            return true;    }    return false;}/***************************************************************************** * OpenVideoDev: open and set up the video device and probe for capabilities *****************************************************************************/static int OpenVideoDev( vlc_object_t *p_obj, demux_sys_t *p_sys, bool b_demux ){    int i_fd;    struct v4l2_cropcap cropcap;    struct v4l2_crop crop;    struct v4l2_format fmt;    unsigned int i_min;    enum v4l2_buf_type buf_type;    char *psz_device = p_sys->psz_vdev;    es_format_t es_fmt;    int libv4l2_fd;    if( ( i_fd = open( psz_device, O_RDWR ) ) < 0 )    {        msg_Err( p_obj, "cannot open device (%m)" );        goto open_failed;    }    /* Note the v4l2_xxx functions are designed so that if they get passed an       unknown fd, the will behave exactly as their regular xxx counterparts,       so if v4l2_fd_open fails, we continue as normal (missing the libv4l2       custom cam format to normal formats conversion). Chances are big we will       still fail then though, as normally v4l2_fd_open only fails if the       device is not a v4l2 device. */    libv4l2_fd = v4l2_fd_open(i_fd, V4L2_ENABLE_ENUM_FMT_EMULATION);    if (libv4l2_fd != -1)        i_fd = libv4l2_fd;    /* Tune the tuner */    if( p_sys->i_frequency >= 0 )    {        if( p_sys->i_cur_tuner < 0 || p_sys->i_cur_tuner >= p_sys->i_tuner )        {            msg_Err( p_obj, "invalid tuner %d.", p_sys->i_cur_tuner );            goto open_failed;        }        struct v4l2_frequency frequency;        memset( &frequency, 0, sizeof( frequency ) );        frequency.tuner = p_sys->i_cur_tuner;        frequency.type = p_sys->p_tuners[p_sys->i_cur_tuner].type;        frequency.frequency = p_sys->i_frequency / 62.5;        if( v4l2_ioctl( i_fd, VIDIOC_S_FREQUENCY, &frequency ) < 0 )        {            msg_Err( p_obj, "cannot set tuner frequency (%m)" ); 

⌨️ 快捷键说明

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