1
mirror of https://code.videolan.org/videolan/vlc synced 2024-09-04 09:11:33 +02:00

Add MJPEG support to the v4l2 access (and simplify the buffer size handling code). I now need people with v4l2 compatible devices with JPEG, DV and MPEG support to try to enable those features.

This commit is contained in:
Antoine Cellerier 2007-12-07 21:27:03 +00:00
parent fcde47951a
commit 23a8765c1a

View File

@ -4,8 +4,9 @@
* Copyright (C) 2002-2007 the VideoLAN team
* $Id$
*
* Author: Benjamin Pracht <bigben at videolan dot org>
* Richard Hosking <richard at hovis dot net>
* Authors: Benjamin Pracht <bigben at videolan dot org>
* Richard Hosking <richard at hovis dot net>
* Antoine Cellerier <dionoea at videolan d.t net>
*
* 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
@ -220,7 +221,7 @@ static int Control( demux_t *, int, va_list );
static int Demux( demux_t * );
static block_t* GrabVideo( demux_t *p_demux );
static block_t* ProcessVideoFrame( demux_t *p_demux, uint8_t *p_frame );
static block_t* ProcessVideoFrame( demux_t *p_demux, uint8_t *p_frame, size_t );
static block_t* GrabAudio( demux_t *p_demux );
vlc_bool_t IsPixelFormatSupported( demux_t *p_demux, unsigned int i_pixelformat );
@ -244,20 +245,28 @@ static struct
int i_fourcc;
} v4l2chroma_to_fourcc[] =
{
{ V4L2_PIX_FMT_GREY, VLC_FOURCC( 'G', 'R', 'E', 'Y' ) },
{ V4L2_PIX_FMT_HI240, VLC_FOURCC( 'I', '2', '4', '0' ) },
{ V4L2_PIX_FMT_RGB565, VLC_FOURCC( 'R', 'V', '1', '6' ) },
{ V4L2_PIX_FMT_RGB555, VLC_FOURCC( 'R', 'V', '1', '5' ) },
{ V4L2_PIX_FMT_BGR24, VLC_FOURCC( 'R', 'V', '2', '4' ) },
{ V4L2_PIX_FMT_BGR32, VLC_FOURCC( 'R', 'V', '3', '2' ) },
{ V4L2_PIX_FMT_YUYV, VLC_FOURCC( 'Y', 'U', 'Y', '2' ) },
{ V4L2_PIX_FMT_YUYV, VLC_FOURCC( 'Y', 'U', 'Y', 'V' ) },
{ V4L2_PIX_FMT_UYVY, VLC_FOURCC( 'U', 'Y', 'V', 'Y' ) },
{ V4L2_PIX_FMT_Y41P, VLC_FOURCC( 'I', '4', '1', 'N' ) },
{ V4L2_PIX_FMT_YUV422P, VLC_FOURCC( 'I', '4', '2', '2' ) },
{ V4L2_PIX_FMT_YVU420, VLC_FOURCC( 'I', '4', '2', '0' ) },
{ V4L2_PIX_FMT_YUV411P, VLC_FOURCC( 'I', '4', '1', '1' ) },
{ V4L2_PIX_FMT_YUV410, VLC_FOURCC( 'I', '4', '1', '0' ) },
/* Raw data types */
{ V4L2_PIX_FMT_GREY, VLC_FOURCC('G','R','E','Y') },
{ V4L2_PIX_FMT_HI240, VLC_FOURCC('I','2','4','0') },
{ V4L2_PIX_FMT_RGB565, VLC_FOURCC('R','V','1','6') },
{ V4L2_PIX_FMT_RGB555, VLC_FOURCC('R','V','1','5') },
{ V4L2_PIX_FMT_BGR24, VLC_FOURCC('R','V','2','4') },
{ V4L2_PIX_FMT_BGR32, VLC_FOURCC('R','V','3','2') },
{ V4L2_PIX_FMT_YUYV, VLC_FOURCC('Y','U','Y','2') },
{ V4L2_PIX_FMT_YUYV, VLC_FOURCC('Y','U','Y','V') },
{ V4L2_PIX_FMT_UYVY, VLC_FOURCC('U','Y','V','Y') },
{ V4L2_PIX_FMT_Y41P, VLC_FOURCC('I','4','1','N') },
{ V4L2_PIX_FMT_YUV422P, VLC_FOURCC('I','4','2','2') },
{ V4L2_PIX_FMT_YVU420, VLC_FOURCC('I','4','2','0') },
{ V4L2_PIX_FMT_YUV411P, VLC_FOURCC('I','4','1','1') },
{ V4L2_PIX_FMT_YUV410, VLC_FOURCC('I','4','1','0') },
/* Compressed data types */
{ V4L2_PIX_FMT_MJPEG, VLC_FOURCC('M','J','P','G') },
#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 }
};
@ -321,9 +330,6 @@ struct demux_sys_t
int i_hue;
int i_gamma;
picture_t pic;
int i_video_frame_size;
es_out_id_t *p_es_video;
/* Audio */
@ -933,6 +939,7 @@ static block_t* GrabVideo( demux_t *p_demux )
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 )
{
@ -946,7 +953,8 @@ static block_t* GrabVideo( demux_t *p_demux )
switch( p_sys->io )
{
case IO_METHOD_READ:
if( read( p_sys->i_fd_video, p_sys->p_buffers[0].start, p_sys->p_buffers[0].length ) )
i_ret = read( p_sys->i_fd_video, p_sys->p_buffers[0].start, p_sys->p_buffers[0].length );
if( i_ret == -1 )
{
switch( errno )
{
@ -961,7 +969,7 @@ static block_t* GrabVideo( demux_t *p_demux )
}
}
p_block = ProcessVideoFrame( p_demux, (uint8_t*)p_sys->p_buffers[0].start );
p_block = ProcessVideoFrame( p_demux, (uint8_t*)p_sys->p_buffers[0].start, i_ret );
if( !p_block ) return 0;
break;
@ -992,7 +1000,7 @@ static block_t* GrabVideo( demux_t *p_demux )
return 0;
}
p_block = ProcessVideoFrame( p_demux, p_sys->p_buffers[buf.index].start );
p_block = ProcessVideoFrame( p_demux, p_sys->p_buffers[buf.index].start, buf.bytesused );
if( !p_block ) return 0;
/* Unlock */
@ -1039,7 +1047,7 @@ static block_t* GrabVideo( demux_t *p_demux )
return 0;
}
p_block = ProcessVideoFrame( p_demux, (uint8_t*)buf.m.userptr );
p_block = ProcessVideoFrame( p_demux, (uint8_t*)buf.m.userptr, buf.bytesused );
if( !p_block ) return 0;
/* Unlock */
@ -1063,22 +1071,21 @@ static block_t* GrabVideo( demux_t *p_demux )
* 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 )
static block_t* ProcessVideoFrame( demux_t *p_demux, uint8_t *p_frame, size_t i_size )
{
demux_sys_t *p_sys = p_demux->p_sys;
block_t *p_block;
if( !p_frame ) return 0;
/* New block */
if( !( p_block = block_New( p_demux, p_sys->i_video_frame_size ) ) )
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, p_sys->i_video_frame_size );
memcpy( p_block->p_buffer, p_frame, i_size );
return p_block;
}
@ -1383,26 +1390,26 @@ int OpenVideoDev( demux_t *p_demux, char *psz_device )
/* Verify device support for the various IO methods */
switch( p_sys->io )
{
case IO_METHOD_READ:
if( !(p_sys->dev_cap.capabilities & V4L2_CAP_READWRITE) )
{
msg_Err( p_demux, "device does not support read i/o" );
goto open_failed;
}
break;
case IO_METHOD_READ:
if( !(p_sys->dev_cap.capabilities & V4L2_CAP_READWRITE) )
{
msg_Err( p_demux, "device does not support read i/o" );
goto open_failed;
}
break;
case IO_METHOD_MMAP:
case IO_METHOD_USERPTR:
if( !(p_sys->dev_cap.capabilities & V4L2_CAP_STREAMING) )
{
msg_Err( p_demux, "device does not support streaming i/o" );
goto open_failed;
}
break;
case IO_METHOD_MMAP:
case IO_METHOD_USERPTR:
if( !(p_sys->dev_cap.capabilities & V4L2_CAP_STREAMING) )
{
msg_Err( p_demux, "device does not support streaming i/o" );
goto open_failed;
}
break;
default:
msg_Err( p_demux, "io method not supported" );
goto open_failed;
default:
msg_Err( p_demux, "io method not supported" );
goto open_failed;
}
/* Reset Cropping */
@ -1416,12 +1423,12 @@ int OpenVideoDev( demux_t *p_demux, char *psz_device )
{
switch( errno )
{
case EINVAL:
/* Cropping not supported. */
break;
default:
/* Errors ignored. */
break;
case EINVAL:
/* Cropping not supported. */
break;
default:
/* Errors ignored. */
break;
}
}
}
@ -1582,21 +1589,6 @@ int OpenVideoDev( demux_t *p_demux, char *psz_device )
VideoControl( p_demux, i_fd, "hue", V4L2_CID_HUE, p_sys->i_hue );
VideoControl( p_demux, i_fd, "gamma", V4L2_CID_GAMMA, p_sys->i_gamma );
/* Init vout Picture */
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 open_failed;
}
p_sys->i_video_frame_size = 0;
for( int 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;
}
/* Init IO method */
switch( p_sys->io )
{