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

📄 v4l.c

📁 VLC Player Source Code
💻 C
📖 第 1 页 / 共 4 页
字号:
            {                p_sys->vid_picture = vid_picture;            }            else            {                /* Try to set the format to something easy to encode */                vid_picture.palette = VIDEO_PALETTE_YUV420P;                if( ioctl( i_fd, VIDIOCSPICT, &vid_picture ) == 0 )                {                    p_sys->vid_picture = vid_picture;                }                else                {                    vid_picture.palette = VIDEO_PALETTE_YUV422P;                    if( ioctl( i_fd, VIDIOCSPICT, &vid_picture ) == 0 )                    {                        p_sys->vid_picture = vid_picture;                    }                }            }            /* Find out final format */            for( i = 0; v4lchroma_to_fourcc[i].i_v4l != 0; i++ )            {                if( v4lchroma_to_fourcc[i].i_v4l == p_sys->vid_picture.palette)                {                    p_sys->i_fourcc = v4lchroma_to_fourcc[i].i_fourcc;                    break;                }            }        }        else        {            msg_Err( p_demux, "ioctl VIDIOCGPICT failed" );            goto vdev_failed;        }    }    if( p_sys->b_mjpeg )    {        int i;        p_sys->mjpeg_buffers.count = 8;        p_sys->mjpeg_buffers.size = MJPEG_BUFFER_SIZE;        if( ioctl( i_fd, MJPIOC_REQBUFS, &p_sys->mjpeg_buffers ) < 0 )        {            msg_Err( p_demux, "mmap unsupported" );            goto vdev_failed;        }        p_sys->p_video_mmap = mmap( 0,                p_sys->mjpeg_buffers.size * p_sys->mjpeg_buffers.count,                PROT_READ | PROT_WRITE, MAP_SHARED, i_fd, 0 );        if( p_sys->p_video_mmap == MAP_FAILED )        {            msg_Err( p_demux, "mmap failed" );            goto vdev_failed;        }        p_sys->i_fourcc  = VLC_FOURCC( 'm','j','p','g' );        p_sys->i_frame_pos = -1;        /* queue up all the frames */        for( i = 0; i < (int)p_sys->mjpeg_buffers.count; i++ )        {            if( ioctl( i_fd, MJPIOC_QBUF_CAPT, &i ) < 0 )            {                msg_Err( p_demux, "unable to queue frame" );                goto vdev_failed;            }        }    }    else    {        /* Fill in picture_t fields */        vout_InitPicture( VLC_OBJECT(p_demux), &p_sys->pic, p_sys->i_fourcc,                          p_sys->i_width, p_sys->i_height, p_sys->i_width *                          VOUT_ASPECT_FACTOR / p_sys->i_height );        if( !p_sys->pic.i_planes )        {            msg_Err( p_demux, "unsupported chroma" );            goto vdev_failed;        }        p_sys->i_video_frame_size = 0;        for( i = 0; i < p_sys->pic.i_planes; i++ )        {            p_sys->i_video_frame_size += p_sys->pic.p[i].i_visible_lines *              p_sys->pic.p[i].i_visible_pitch;        }        msg_Dbg( p_demux, "v4l device uses frame size: %i",                 p_sys->i_video_frame_size );        msg_Dbg( p_demux, "v4l device uses chroma: %4.4s",                (char*)&p_sys->i_fourcc );        /* Allocate mmap buffer */        if( ioctl( i_fd, VIDIOCGMBUF, &p_sys->vid_mbuf ) < 0 )        {            msg_Err( p_demux, "mmap unsupported" );            goto vdev_failed;        }        p_sys->p_video_mmap = mmap( 0, p_sys->vid_mbuf.size,                                    PROT_READ|PROT_WRITE, MAP_SHARED,                                    i_fd, 0 );        if( p_sys->p_video_mmap == MAP_FAILED )        {            /* FIXME -> normal read */            msg_Err( p_demux, "mmap failed" );            goto vdev_failed;        }        /* init grabbing */        p_sys->vid_mmap.frame  = 0;        p_sys->vid_mmap.width  = p_sys->i_width;        p_sys->vid_mmap.height = p_sys->i_height;        p_sys->vid_mmap.format = p_sys->vid_picture.palette;        if( ioctl( i_fd, VIDIOCMCAPTURE, &p_sys->vid_mmap ) < 0 )        {            msg_Warn( p_demux, "%4.4s refused", (char*)&p_sys->i_fourcc );            msg_Err( p_demux, "chroma selection failed" );            goto vdev_failed;        }    }    return i_fd;vdev_failed:    if( i_fd >= 0 ) close( i_fd );    return -1;}/***************************************************************************** * OpenAudioDev: *****************************************************************************/static int OpenAudioDev( demux_t *p_demux, char *psz_device ){    demux_sys_t *p_sys = p_demux->p_sys;    int i_fd, i_format;    if( (i_fd = open( psz_device, O_RDONLY | O_NONBLOCK )) < 0 )    {        msg_Err( p_demux, "cannot open audio device (%m)" );        goto adev_fail;    }    i_format = AFMT_S16_LE;    if( ioctl( i_fd, SNDCTL_DSP_SETFMT, &i_format ) < 0        || i_format != AFMT_S16_LE )    {        msg_Err( p_demux, "cannot set audio format (16b little endian) "                 "(%m)" );        goto adev_fail;    }    if( ioctl( i_fd, SNDCTL_DSP_STEREO,               &p_sys->b_stereo ) < 0 )    {        msg_Err( p_demux, "cannot set audio channels count (%m)" );        goto adev_fail;    }    if( ioctl( i_fd, SNDCTL_DSP_SPEED,               &p_sys->i_sample_rate ) < 0 )    {        msg_Err( p_demux, "cannot set audio sample rate (%m)" );        goto adev_fail;    }    msg_Dbg( p_demux, "opened adev=`%s' %s %dHz",             psz_device, p_sys->b_stereo ? "stereo" : "mono",             p_sys->i_sample_rate );    p_sys->i_audio_max_frame_size = 6 * 1024;    return i_fd; adev_fail:    if( i_fd >= 0 ) close( i_fd );    return -1;}/***************************************************************************** * GrabAudio: grab audio *****************************************************************************/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, 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;    i_read = read( p_sys->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( ioctl( p_sys->fd_audio, SNDCTL_DSP_GETISPACE, &buf_info ) == 0 )    {        i_correct += buf_info.bytes;    }    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;}/***************************************************************************** * GrabVideo: *****************************************************************************/static uint8_t *GrabCapture( demux_t *p_demux ){    demux_sys_t *p_sys = p_demux->p_sys;    int i_captured_frame = p_sys->i_frame_pos;    p_sys->vid_mmap.frame = (p_sys->i_frame_pos + 1) % p_sys->vid_mbuf.frames;    while( ioctl( p_sys->fd_video, VIDIOCMCAPTURE, &p_sys->vid_mmap ) < 0 )    {        if( errno != EAGAIN )        {            msg_Err( p_demux, "failed capturing new frame" );            return NULL;        }        if( !vlc_object_alive (p_demux) )        {            return NULL;        }        msg_Dbg( p_demux, "grab failed, trying again" );    }    while( ioctl(p_sys->fd_video, VIDIOCSYNC, &p_sys->i_frame_pos) < 0 )    {        if( errno != EAGAIN && errno != EINTR )        {            msg_Err( p_demux, "failed syncing new frame" );            return NULL;        }    }    p_sys->i_frame_pos = p_sys->vid_mmap.frame;    /* leave i_video_frame_size alone */    return p_sys->p_video_mmap + p_sys->vid_mbuf.offsets[i_captured_frame];}static uint8_t *GrabMJPEG( demux_t *p_demux ){    demux_sys_t *p_sys = p_demux->p_sys;    struct mjpeg_sync sync;    uint8_t *p_frame, *p_field, *p;    uint16_t tag;    uint32_t i_size;    struct quicktime_mjpeg_app1 *p_app1 = NULL;    /* re-queue the last frame we sync'd */    if( p_sys->i_frame_pos != -1 )    {        while( ioctl( p_sys->fd_video, MJPIOC_QBUF_CAPT,                                       &p_sys->i_frame_pos ) < 0 )        {            if( errno != EAGAIN && errno != EINTR )            {                msg_Err( p_demux, "failed capturing new frame" );                return NULL;            }        }    }    /* sync on the next frame */    while( ioctl( p_sys->fd_video, MJPIOC_SYNC, &sync ) < 0 )    {        if( errno != EAGAIN && errno != EINTR )        {            msg_Err( p_demux, "failed syncing new frame" );            return NULL;        }    }    p_sys->i_frame_pos = sync.frame;    p_frame = p_sys->p_video_mmap + p_sys->mjpeg_buffers.size * sync.frame;    /* p_frame now points to the data.  fix up the Quicktime APP1 marker */    tag = 0xffd9;    tag = hton16( tag );    p_field = p_frame;    /* look for EOI */    p = memmem( p_field, sync.length, &tag, 2 );    if( p )    {        p += 2; /* data immediately following EOI */        /* UNALIGNED! */        p_app1 = (struct quicktime_mjpeg_app1 *)(p_field + 6);        i_size = ((uint32_t)(p - p_field));        i_size = hton32( i_size );        memcpy( &p_app1->i_field_size, &i_size, 4 );        while( *p == 0xff && *(p+1) == 0xff )            p++;        i_size = ((uint32_t)(p - p_field));        i_size = hton32( i_size );        memcpy( &p_app1->i_padded_field_size, &i_size, 4 );    }    tag = 0xffd8;    tag = hton16( tag );    p_field = memmem( p, sync.length - (size_t)(p - p_frame), &tag, 2 );    if( p_field )    {        i_size = (uint32_t)(p_field - p_frame);        i_size = hton32( i_size );        memcpy( &p_app1->i_next_field, &i_size, 4 );        /* UNALIGNED! */        p_app1 = (struct quicktime_mjpeg_app1 *)(p_field + 6);        tag = 0xffd9;        tag = hton16( tag );        p = memmem( p_field, sync.length - (size_t)(p_field - p_frame),                &tag, 2 );        if( !p )        {            /* sometimes the second field doesn't have the EOI.  just put it             * there             */            p = p_frame + sync.length;            memcpy( p, &tag, 2 );            sync.length += 2;        }        p += 2;        i_size = (uint32_t)(p - p_field);        i_size = hton32( i_size );        memcpy( &p_app1->i_field_size, &i_size, 4 );        i_size = (uint32_t)(sync.length - (uint32_t)(p_field - p_frame));        i_size = hton32( i_size );        memcpy( &p_app1->i_padded_field_size, &i_size, 4 );    }    p_sys->i_video_frame_size = sync.length;    return p_frame;}static block_t *GrabVideo( demux_t *p_demux ){    demux_sys_t *p_sys = p_demux->p_sys;    uint8_t     *p_frame;    block_t     *p_block;    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;    }    if( p_sys->b_mjpeg ) p_frame = GrabMJPEG( p_demux );    else p_frame = GrabCapture( p_demux );    if( !p_frame ) return 0;    if( !( p_block = block_New( p_demux, p_sys->i_video_frame_size ) ) )    {        msg_Warn( p_demux, "cannot get block" );        return 0;    }    memcpy( p_block->p_buffer, p_frame, p_sys->i_video_frame_size );    p_sys->i_video_pts = p_block->i_pts = p_block->i_dts = mdate();    return p_block;}

⌨️ 快捷键说明

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