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

📄 v4l2.c

📁 vlc源码
💻 C
📖 第 1 页 / 共 5 页
字号:
        }    }    /* Free Video Buffers */    if( p_sys->p_buffers ) {        switch( p_sys->io )        {        case IO_METHOD_READ:            free( p_sys->p_buffers[0].start );            break;        case IO_METHOD_MMAP:            for( i = 0; i < p_sys->i_nbuffers; ++i )            {                if( v4l2_munmap( p_sys->p_buffers[i].start, p_sys->p_buffers[i].length ) )                {                    msg_Err( p_this, "munmap failed" );                }            }            break;        case IO_METHOD_USERPTR:            for( i = 0; i < p_sys->i_nbuffers; ++i )            {               free( p_sys->p_buffers[i].start );            }            break;        }        free( p_sys->p_buffers );    }    CommonClose( p_this, p_sys );}static void CommonClose( vlc_object_t *p_this, demux_sys_t *p_sys ){    (void)p_this;    /* Close */    if( p_sys->i_fd_video >= 0 ) v4l2_close( p_sys->i_fd_video );#ifdef HAVE_ALSA    if( p_sys->p_alsa_pcm )    {        snd_pcm_close( p_sys->p_alsa_pcm );        p_sys->i_fd_audio = -1;    }#endif    if( p_sys->i_fd_audio >= 0 ) close( p_sys->i_fd_audio );    if( p_sys->p_block_audio ) block_Release( p_sys->p_block_audio );    free( p_sys->psz_device );    free( p_sys->psz_vdev );    free( p_sys->psz_adev );    free( p_sys->p_standards );    free( p_sys->p_inputs );    free( p_sys->p_tuners );    free( p_sys->p_codecs );    free( p_sys->psz_requested_chroma );    free( p_sys->psz_set_ctrls );    free( p_sys );}/***************************************************************************** * AccessOpen: opens v4l2 device, access callback ***************************************************************************** * * url: <video device>:::: * *****************************************************************************/static int AccessOpen( vlc_object_t * p_this ){    access_t *p_access = (access_t*) p_this;    demux_sys_t * p_sys;    /* Only when selected */    if( *p_access->psz_access == '\0' ) return VLC_EGENERIC;    p_access->pf_read = AccessRead;    p_access->pf_block = NULL;    p_access->pf_seek = NULL;    p_access->pf_control = AccessControl;    p_access->info.i_update = 0;    p_access->info.i_size = 0;    p_access->info.i_pos = 0;    p_access->info.b_eof = false;    p_access->info.i_title = 0;    p_access->info.i_seekpoint = 0;    p_sys = calloc( 1, sizeof( demux_sys_t ) );    p_access->p_sys = (access_sys_t *) p_sys;    if( p_sys == NULL ) return VLC_ENOMEM;    GetV4L2Params( p_sys, (vlc_object_t *) p_access );    ParseMRL( p_sys, p_access->psz_path, (vlc_object_t *) p_access );    if( FindMainDevice( p_this, p_sys, FIND_VIDEO,        false, !strncmp( p_access->psz_access, "v4l2", 4 ) ) != VLC_SUCCESS )    {        AccessClose( p_this );        return VLC_EGENERIC;    }    return VLC_SUCCESS;}/***************************************************************************** * DemuxControl: *****************************************************************************/static int DemuxControl( demux_t *p_demux, int i_query, va_list args ){    demux_sys_t *p_sys = p_demux->p_sys;    bool *pb;    int64_t    *pi64;    switch( i_query )    {        /* Special for access_demux */        case DEMUX_CAN_PAUSE:        case DEMUX_CAN_SEEK:        case DEMUX_SET_PAUSE_STATE:        case DEMUX_CAN_CONTROL_PACE:            pb = (bool*)va_arg( args, bool * );            *pb = false;            return VLC_SUCCESS;        case DEMUX_GET_PTS_DELAY:            pi64 = (int64_t*)va_arg( args, int64_t * );            *pi64 = (int64_t)p_sys->i_pts * 1000;            return VLC_SUCCESS;        case DEMUX_GET_TIME:            pi64 = (int64_t*)va_arg( args, int64_t * );            *pi64 = mdate();            return VLC_SUCCESS;        /* TODO implement others */        default:            return VLC_EGENERIC;    }    return VLC_EGENERIC;}/***************************************************************************** * AccessControl: access callback *****************************************************************************/static int AccessControl( access_t *p_access, int i_query, va_list args ){    bool   *pb_bool;    int          *pi_int;    int64_t      *pi_64;    demux_sys_t  *p_sys = (demux_sys_t *) p_access->p_sys;    switch( i_query )    {        /* */        case ACCESS_CAN_SEEK:        case ACCESS_CAN_FASTSEEK:            pb_bool = (bool*)va_arg( args, bool* );            *pb_bool = false;            break;        case ACCESS_CAN_PAUSE:            pb_bool = (bool*)va_arg( args, bool* );            *pb_bool = false;            break;        case ACCESS_CAN_CONTROL_PACE:            pb_bool = (bool*)va_arg( args, bool* );            *pb_bool = false;            break;        /* */        case ACCESS_GET_MTU:            pi_int = (int*)va_arg( args, int * );            *pi_int = 0;            break;        case ACCESS_GET_PTS_DELAY:            pi_64 = (int64_t*)va_arg( args, int64_t * );            *pi_64 = (int64_t) p_sys->i_pts * 1000;            break;        /* */        case ACCESS_SET_PAUSE_STATE:            /* Nothing to do */            break;        case ACCESS_GET_TITLE_INFO:        case ACCESS_SET_TITLE:        case ACCESS_SET_SEEKPOINT:        case ACCESS_SET_PRIVATE_ID_STATE:        case ACCESS_GET_CONTENT_TYPE:        case ACCESS_GET_META:            return VLC_EGENERIC;        default:            msg_Warn( p_access, "Unimplemented query in control(%d).", i_query);            return VLC_EGENERIC;    }    return VLC_SUCCESS;}/***************************************************************************** * AccessRead: access callback ******************************************************************************/static ssize_t AccessRead( access_t * p_access, uint8_t * p_buffer, size_t i_len ){    demux_sys_t *p_sys = (demux_sys_t *) p_access->p_sys;    struct pollfd ufd;    int i_ret;    ufd.fd = p_sys->i_fd_video;    ufd.events = POLLIN;    if( p_access->info.b_eof )        return 0;    do    {        if( !vlc_object_alive (p_access) )            return 0;        ufd.revents = 0;    }    while( ( i_ret = poll( &ufd, 1, 500 ) ) == 0 );    if( i_ret < 0 )    {        msg_Err( p_access, "Polling error (%m)." );        return -1;    }    i_ret = v4l2_read( p_sys->i_fd_video, p_buffer, i_len );    if( i_ret == 0 )    {        p_access->info.b_eof = true;    }    else if( i_ret > 0 )    {        p_access->info.i_pos += i_ret;    }    return i_ret;}/***************************************************************************** * Demux: Processes the audio or video frame *****************************************************************************/static int Demux( demux_t *p_demux ){    demux_sys_t *p_sys = p_demux->p_sys;    es_out_id_t *p_es = p_sys->p_es_audio;    block_t *p_block = NULL;    /* Try grabbing audio frames first */    if( p_sys->i_fd_audio < 0 || !( p_block = GrabAudio( p_demux ) ) )    {        /* Try grabbing video frame */        p_es = p_sys->p_es_video;        if( p_sys->i_fd_video > 0 ) p_block = GrabVideo( p_demux );    }    if( !p_block )    {        /* Sleep so we do not consume all the cpu, 10ms seems         * like a good value (100fps) */        /* Yeah, nevermind this was sleeping 10 microseconds! This is         * completely brain damaged anyway. Use poll() or mwait() FIXME. */        msleep(10000);        return 1;    }    es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_block->i_pts );    es_out_Send( p_demux->out, p_es, p_block );    return 1;}/***************************************************************************** * GrabVideo: Grab a video frame *****************************************************************************/static block_t* GrabVideo( demux_t *p_demux ){    demux_sys_t *p_sys = p_demux->p_sys;    block_t *p_block = NULL;    struct v4l2_buffer buf;    ssize_t i_ret;    if( p_sys->f_fps >= 0.1 && p_sys->i_video_pts > 0 )    {        mtime_t i_dur = (mtime_t)((double)1000000 / (double)p_sys->f_fps);        /* Did we wait long enough ? (frame rate reduction) */        if( p_sys->i_video_pts + i_dur > mdate() ) return 0;    }    /* Grab Video Frame */    switch( p_sys->io )    {    case IO_METHOD_READ:        i_ret = v4l2_read( p_sys->i_fd_video, p_sys->p_buffers[0].start, p_sys->p_buffers[0].length );        if( i_ret == -1 )        {            switch( errno )            {            case EAGAIN:                return 0;            case EIO:                /* Could ignore EIO, see spec. */                /* fall through */            default:                msg_Err( p_demux, "Failed to read frame" );                return 0;               }        }        p_block = ProcessVideoFrame( p_demux, (uint8_t*)p_sys->p_buffers[0].start, i_ret );        if( !p_block ) return 0;        break;    case IO_METHOD_MMAP:        memset( &buf, 0, sizeof(buf) );        buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;        buf.memory = V4L2_MEMORY_MMAP;        /* Wait for next frame */        if (v4l2_ioctl( p_sys->i_fd_video, VIDIOC_DQBUF, &buf ) < 0 )        {            switch( errno )            {            case EAGAIN:                return 0;            case EIO:                /* Could ignore EIO, see spec. */                /* fall through */            default:                msg_Err( p_demux, "Failed to wait (VIDIOC_DQBUF)" );                return 0;               }        }        if( buf.index >= p_sys->i_nbuffers ) {            msg_Err( p_demux, "Failed capturing new frame as i>=nbuffers" );            return 0;        }        p_block = ProcessVideoFrame( p_demux, p_sys->p_buffers[buf.index].start, 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;    case IO_METHOD_USERPTR:        memset( &buf, 0, sizeof(buf) );        buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;        buf.memory = V4L2_MEMORY_USERPTR;        /* Wait for next frame */        if (v4l2_ioctl( p_sys->i_fd_video, VIDIOC_DQBUF, &buf ) < 0 )        {            switch( errno )            {            case EAGAIN:                return 0;            case EIO:                /* Could ignore EIO, see spec. */                /* fall through */

⌨️ 快捷键说明

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