V4L2 updates

git-svn-id: http://svn.zoneminder.com/svn/zm/trunk@2723 e3e1d417-86f3-4887-817a-d78f3d33393f
This commit is contained in:
stan 2009-01-27 11:07:24 +00:00
parent 69662d644a
commit 21d8d74a28
5 changed files with 409 additions and 88 deletions

View File

@ -269,8 +269,8 @@ CREATE TABLE `MonitorPresets` (
`Name` varchar(64) NOT NULL default '', `Name` varchar(64) NOT NULL default '',
`Type` enum('Local','Remote','File','Ffmpeg') NOT NULL default 'Local', `Type` enum('Local','Remote','File','Ffmpeg') NOT NULL default 'Local',
`Device` tinytext, `Device` tinytext,
`Channel` varchar(32) default NULL, `Channel` tinyint(3) unsigned default NULL,
`Format` varchar(32) default NULL, `Format` int(10) unsigned default NULL,
`Protocol` varchar(16) default NULL, `Protocol` varchar(16) default NULL,
`Method` varchar(16) default NULL, `Method` varchar(16) default NULL,
`Host` varchar(64) default NULL, `Host` varchar(64) default NULL,
@ -279,7 +279,7 @@ CREATE TABLE `MonitorPresets` (
`SubPath` varchar(64) default NULL, `SubPath` varchar(64) default NULL,
`Width` smallint(5) unsigned default NULL, `Width` smallint(5) unsigned default NULL,
`Height` smallint(5) unsigned default NULL, `Height` smallint(5) unsigned default NULL,
`Palette` tinyint(3) unsigned default NULL, `Palette` int(10) unsigned default NULL,
`MaxFPS` decimal(5,2) default NULL, `MaxFPS` decimal(5,2) default NULL,
`Controllable` tinyint(3) unsigned NOT NULL default '0', `Controllable` tinyint(3) unsigned NOT NULL default '0',
`ControlId` varchar(16) default NULL, `ControlId` varchar(16) default NULL,
@ -305,7 +305,7 @@ CREATE TABLE `Monitors` (
`Triggers` set('X10') NOT NULL default '', `Triggers` set('X10') NOT NULL default '',
`Device` varchar(64) NOT NULL default '', `Device` varchar(64) NOT NULL default '',
`Channel` tinyint(3) unsigned NOT NULL default '0', `Channel` tinyint(3) unsigned NOT NULL default '0',
`Format` tinyint(3) unsigned NOT NULL default '0', `Format` int(10) unsigned NOT NULL default '0',
`Protocol` varchar(16) NOT NULL default '', `Protocol` varchar(16) NOT NULL default '',
`Method` varchar(16) NOT NULL default '', `Method` varchar(16) NOT NULL default '',
`Host` varchar(64) NOT NULL default '', `Host` varchar(64) NOT NULL default '',
@ -314,7 +314,7 @@ CREATE TABLE `Monitors` (
`Path` varchar(64) NOT NULL default '', `Path` varchar(64) NOT NULL default '',
`Width` smallint(5) unsigned NOT NULL default '0', `Width` smallint(5) unsigned NOT NULL default '0',
`Height` smallint(5) unsigned NOT NULL default '0', `Height` smallint(5) unsigned NOT NULL default '0',
`Palette` tinyint(3) unsigned NOT NULL default '1', `Palette` int(10) unsigned NOT NULL default '0',
`Orientation` enum('0','90','180','270','hori','vert') NOT NULL default '0', `Orientation` enum('0','90','180','270','hori','vert') NOT NULL default '0',
`Brightness` mediumint(7) NOT NULL default '-1', `Brightness` mediumint(7) NOT NULL default '-1',
`Contrast` mediumint(7) NOT NULL default '-1', `Contrast` mediumint(7) NOT NULL default '-1',

View File

@ -43,6 +43,15 @@ update Monitors set Method = "v4l1" where Type = 'Local';
alter table Monitors modify column `Type` enum('Local','Remote','File','Ffmpeg') NOT NULL default 'Local'; alter table Monitors modify column `Type` enum('Local','Remote','File','Ffmpeg') NOT NULL default 'Local';
alter table MonitorPresets modify column `Type` enum('Local','Remote','File','Ffmpeg') NOT NULL default 'Local'; alter table MonitorPresets modify column `Type` enum('Local','Remote','File','Ffmpeg') NOT NULL default 'Local';
--
-- Fix columns to fit V4L2 formats and palettes
--
alter table Monitors modify column `Format` int(10) unsigned NOT NULL default '0';
alter table Monitors modify column `Palette` int(10) unsigned NOT NULL default '0';
alter table MonitorPresets modify column `Channel` tinyint(3) unsigned default NULL;
alter table MonitorPresets modify column `Format` int(10) unsigned default NULL;
alter table MonitorPresets modify column `Palette` int(10) unsigned default NULL;
-- --
-- Add in new MPEG presets -- Add in new MPEG presets
-- --

View File

@ -17,22 +17,24 @@
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
// //
#include "zm_local_camera.h"
#include "zm_ffmpeg.h"
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
#include <unistd.h> #include <unistd.h>
#include <sys/mman.h> #include <sys/mman.h>
#include "zm_local_camera.h"
static int vidioctl( int fd, int request, void *arg ) static int vidioctl( int fd, int request, void *arg )
{ {
int result; int result = -1;
do do
{ {
result = ioctl( fd, request, arg ); result = ioctl( fd, request, arg );
} while ( result == -1 && errno == EINTR ); } while ( result == -1 && errno == EINTR );
return( result ); return( result );
} }
int LocalCamera::camera_count = 0; int LocalCamera::camera_count = 0;
@ -146,58 +148,17 @@ void LocalCamera::Initialise()
memset( &v4l2_data.fmt, 0, sizeof(v4l2_data.fmt) ); memset( &v4l2_data.fmt, 0, sizeof(v4l2_data.fmt) );
v4l2_data.fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; v4l2_data.fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if ( vidioctl( vid_fd, VIDIOC_G_FMT, &v4l2_data.fmt ) < 0 )
Fatal( "Failed to get video format: %s", strerror(errno) );
v4l2_data.fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
v4l2_data.fmt.fmt.pix.width = width; v4l2_data.fmt.fmt.pix.width = width;
v4l2_data.fmt.fmt.pix.height = height; v4l2_data.fmt.fmt.pix.height = height;
switch( palette ) v4l2_data.fmt.fmt.pix.pixelformat = palette;
{
case VIDEO_PALETTE_GREY :
v4l2_data.fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_GREY;
break;
case VIDEO_PALETTE_HI240 :
v4l2_data.fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_HI240;
break;
case VIDEO_PALETTE_RGB565 :
v4l2_data.fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB565;
break;
case VIDEO_PALETTE_RGB24 :
v4l2_data.fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_BGR24;
break;
case VIDEO_PALETTE_RGB32 :
v4l2_data.fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_BGR32;
break;
case VIDEO_PALETTE_RGB555 :
v4l2_data.fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB555;
break;
case VIDEO_PALETTE_YUV422 :
case VIDEO_PALETTE_YUYV :
v4l2_data.fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
break;
case VIDEO_PALETTE_UYVY :
v4l2_data.fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
break;
case VIDEO_PALETTE_YUV420P :
v4l2_data.fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420;
break;
case VIDEO_PALETTE_YUV422P :
v4l2_data.fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV422P;
break;
case VIDEO_PALETTE_YUV411P :
v4l2_data.fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV411P;
break;
case VIDEO_PALETTE_YUV411 :
v4l2_data.fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_Y41P;
break;
case VIDEO_PALETTE_YUV410P :
v4l2_data.fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV410;
break;
// case VIDEO_PALETTE_YUV420 : // Defunct
// case VIDEO_PALETTE_RAW : // Defunct
default :
Fatal( "Unrecognised palette/format entry %d", palette );
}
v4l2_data.fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; v4l2_data.fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
if ( vidioctl( vid_fd, VIDIOC_S_FMT, &v4l2_data.fmt) ) if ( vidioctl( vid_fd, VIDIOC_S_FMT, &v4l2_data.fmt ) < 0 )
Fatal( "Failed to set video format: %s", strerror(errno) ); Fatal( "Failed to set video format: %s", strerror(errno) );
/* Note VIDIOC_S_FMT may change width and height. */ /* Note VIDIOC_S_FMT may change width and height. */
@ -248,7 +209,7 @@ void LocalCamera::Initialise()
vid_buf.memory = v4l2_data.reqbufs.memory; vid_buf.memory = v4l2_data.reqbufs.memory;
vid_buf.index = i; vid_buf.index = i;
if ( vidioctl( vid_fd, VIDIOC_QUERYBUF, &vid_buf ) ) if ( vidioctl( vid_fd, VIDIOC_QUERYBUF, &vid_buf ) < 0 )
Fatal( "Unable to query video buffer: %s", strerror(errno) ); Fatal( "Unable to query video buffer: %s", strerror(errno) );
v4l2_data.buffers[i].length = vid_buf.length; v4l2_data.buffers[i].length = vid_buf.length;
@ -257,6 +218,34 @@ void LocalCamera::Initialise()
if ( v4l2_data.buffers[i].start == MAP_FAILED ) if ( v4l2_data.buffers[i].start == MAP_FAILED )
Fatal( "Can't map video buffer %d (%d bytes) to memory: %s(%d)", i, vid_buf.length, strerror(errno), errno ); Fatal( "Can't map video buffer %d (%d bytes) to memory: %s(%d)", i, vid_buf.length, strerror(errno), errno );
} }
Debug( 3, "Configuring video source" );
if ( vidioctl( vid_fd, VIDIOC_S_INPUT, &channel ) < 0 )
{
Fatal( "Failed to set camera source %d: %s", channel, strerror(errno) );
}
struct v4l2_input input;
v4l2_std_id stdId;
memset( &input, 0, sizeof(input) );
if ( vidioctl( vid_fd, VIDIOC_ENUMINPUT, &input ) < 0 )
{
Fatal( "Failed to enumerate input %d: %s", channel, strerror(errno) );
}
if ( !(input.std & format) )
{
Fatal( "Device does not support video standard %d", format );
}
stdId = format;
if ( vidioctl( vid_fd, VIDIOC_S_STD, &stdId ) < 0 )
{
Fatal( "Failed to set video standard %d: %s", format, strerror(errno) );
}
} }
else else
#endif // ZM_V4L2 #endif // ZM_V4L2
@ -688,19 +677,22 @@ int LocalCamera::Brightness( int p_brightness )
Error( "Unable to query brightness: %s", strerror(errno) ) Error( "Unable to query brightness: %s", strerror(errno) )
else else
Warning( "Brightness control is not suppported" ) Warning( "Brightness control is not suppported" )
Info( "Brightness 1 %d", vid_control.value );
} }
else else if ( p_brightness >= 0 )
{ {
vid_control.value = p_brightness; vid_control.value = p_brightness;
Info( "Brightness 2 %d", vid_control.value );
/* The driver may clamp the value or return ERANGE, ignored here */ /* The driver may clamp the value or return ERANGE, ignored here */
if ( vidioctl ( vid_fd, VIDIOC_S_CTRL, &vid_control ) < 0 ) if ( vidioctl ( vid_fd, VIDIOC_S_CTRL, &vid_control ) )
{ {
if ( errno != ERANGE ) if ( errno != ERANGE )
Error( "Unable to set brightness: %s", strerror(errno) ) Error( "Unable to set brightness: %s", strerror(errno) )
else else
Warning( "Given brightness value (%d) may be out-of-range", p_brightness ) Warning( "Given brightness value (%d) may be out-of-range", p_brightness )
} }
Info( "Brightness 3 %d", vid_control.value );
} }
return( vid_control.value ); return( vid_control.value );
} }
@ -744,7 +736,7 @@ int LocalCamera::Hue( int p_hue )
else else
Warning( "Hue control is not suppported" ) Warning( "Hue control is not suppported" )
} }
else else if ( p_hue >= 0 )
{ {
vid_control.value = p_hue; vid_control.value = p_hue;
@ -799,7 +791,7 @@ int LocalCamera::Colour( int p_colour )
else else
Warning( "Saturation control is not suppported" ) Warning( "Saturation control is not suppported" )
} }
else else if ( p_colour >= 0 )
{ {
vid_control.value = p_colour; vid_control.value = p_colour;
@ -854,12 +846,12 @@ int LocalCamera::Contrast( int p_contrast )
else else
Warning( "Contrast control is not suppported" ) Warning( "Contrast control is not suppported" )
} }
else else if ( p_contrast >= 0 )
{ {
vid_control.value = p_contrast; vid_control.value = p_contrast;
/* The driver may clamp the value or return ERANGE, ignored here */ /* The driver may clamp the value or return ERANGE, ignored here */
if ( vidioctl ( vid_fd, VIDIOC_S_CTRL, &vid_control ) < 0 ) if ( vidioctl ( vid_fd, VIDIOC_S_CTRL, &vid_control ) )
{ {
if ( errno != ERANGE ) if ( errno != ERANGE )
Error( "Unable to set contrast: %s", strerror(errno) ) Error( "Unable to set contrast: %s", strerror(errno) )
@ -921,7 +913,7 @@ int LocalCamera::PrimeCapture()
vid_buf.memory = v4l2_data.reqbufs.memory; vid_buf.memory = v4l2_data.reqbufs.memory;
vid_buf.index = i; vid_buf.index = i;
if ( vidioctl( vid_fd, VIDIOC_QBUF, &vid_buf ) ) if ( vidioctl( vid_fd, VIDIOC_QBUF, &vid_buf ) < 0 )
Fatal( "Failed to queue buffer %d: %s", i, strerror(errno) ); Fatal( "Failed to queue buffer %d: %s", i, strerror(errno) );
} }
} }
@ -950,17 +942,27 @@ int LocalCamera::PreCapture()
if ( channel_count > 1 ) if ( channel_count > 1 )
{ {
Debug( 3, "Switching video source" ); Debug( 3, "Switching video source" );
if ( vidioctl( vid_fd, VIDIOC_S_INPUT, &channel ) ) if ( vidioctl( vid_fd, VIDIOC_S_INPUT, &channel ) < 0 )
{ {
Error( "Failed to set camera source %d: %s", channel, strerror(errno) ); Error( "Failed to set camera source %d: %s", channel, strerror(errno) );
return( -1 ); return( -1 );
} }
v4l2_std_id stdId = format;
if ( vidioctl( vid_fd, VIDIOC_S_STD, &stdId ) < 0 )
{
Error( "Failed to set video format %d: %s", format, strerror(errno) );
return( -1 );
}
} }
Debug( 3, "Requeing buffer" ); Debug( 3, "Requeing buffer" );
if ( v4l2_data.buffer ) if ( v4l2_data.buffer )
{ {
if ( vidioctl( vid_fd, VIDIOC_QBUF, v4l2_data.buffer ) < 0 ) if ( vidioctl( vid_fd, VIDIOC_QBUF, v4l2_data.buffer ) < 0 )
Fatal( "Unable to requeue buffer %d: %s", v4l2_data.buffer->index, strerror(errno) ) {
Error( "Unable to requeue buffer %d: %s", v4l2_data.buffer->index, strerror(errno) )
return( -1 );
}
} }
} }
else else
@ -1087,10 +1089,173 @@ int LocalCamera::PostCapture( Image &image )
Debug( 3, "Doing format conversion" ); Debug( 3, "Doing format conversion" );
#if HAVE_LIBSWSCALE
static struct SwsContext *imgConversionContext = 0;
static AVFrame *picture = NULL;
static AVFrame *tmpPicture = NULL;
if ( !imgConversionContext )
{
int ffPixFormat = PIX_FMT_NONE;
switch( palette )
{
case V4L2_PIX_FMT_RGB444 :
ffPixFormat = PIX_FMT_RGB32;
break;
case VIDEO_PALETTE_RGB555 :
case V4L2_PIX_FMT_RGB555 :
ffPixFormat = PIX_FMT_RGB555;
break;
case VIDEO_PALETTE_RGB565 :
case V4L2_PIX_FMT_RGB565 :
ffPixFormat = PIX_FMT_RGB565;
break;
case V4L2_PIX_FMT_BGR24 :
ffPixFormat = PIX_FMT_BGR24;
break;
case VIDEO_PALETTE_RGB24 :
if ( config.local_bgr_invert )
ffPixFormat = PIX_FMT_BGR24;
else
ffPixFormat = PIX_FMT_RGB24;
break;
case V4L2_PIX_FMT_RGB24 :
ffPixFormat = PIX_FMT_RGB24;
break;
case V4L2_PIX_FMT_BGR32 :
ffPixFormat = PIX_FMT_BGR32;
break;
case V4L2_PIX_FMT_RGB32 :
ffPixFormat = PIX_FMT_RGB32;
break;
case VIDEO_PALETTE_GREY :
case V4L2_PIX_FMT_GREY :
ffPixFormat = PIX_FMT_GRAY8;
break;
case VIDEO_PALETTE_YUYV :
case VIDEO_PALETTE_YUV422 :
case V4L2_PIX_FMT_YUYV :
ffPixFormat = PIX_FMT_YUYV422;
break;
case VIDEO_PALETTE_YUV422P :
case V4L2_PIX_FMT_YUV422P :
ffPixFormat = PIX_FMT_YUV422P;
break;
case V4L2_PIX_FMT_YUV411P :
ffPixFormat = PIX_FMT_YUV411P;
break;
case V4L2_PIX_FMT_YUV444 :
ffPixFormat = PIX_FMT_YUV444P;
break;
case V4L2_PIX_FMT_YUV410 :
ffPixFormat = PIX_FMT_YUV410P;
break;
case VIDEO_PALETTE_YUV420P :
case V4L2_PIX_FMT_YUV420 :
ffPixFormat = PIX_FMT_YUV420P;
break;
// These don't seem to have ffmpeg equivalents
// See if you can match any of the ones in the default clause below!?
case V4L2_PIX_FMT_UYVY :
case V4L2_PIX_FMT_RGB332 :
case V4L2_PIX_FMT_RGB555X :
case V4L2_PIX_FMT_RGB565X :
case V4L2_PIX_FMT_Y16 :
case V4L2_PIX_FMT_PAL8 :
case V4L2_PIX_FMT_YVU410 :
case V4L2_PIX_FMT_YVU420 :
case V4L2_PIX_FMT_Y41P :
case V4L2_PIX_FMT_YUV555 :
case V4L2_PIX_FMT_YUV565 :
case V4L2_PIX_FMT_YUV32 :
case V4L2_PIX_FMT_NV12 :
case V4L2_PIX_FMT_NV21 :
case V4L2_PIX_FMT_YYUV :
case V4L2_PIX_FMT_HI240 :
case V4L2_PIX_FMT_HM12 :
case V4L2_PIX_FMT_SBGGR8 :
case V4L2_PIX_FMT_SGBRG8 :
case V4L2_PIX_FMT_SBGGR16 :
case V4L2_PIX_FMT_MJPEG :
case V4L2_PIX_FMT_JPEG :
case V4L2_PIX_FMT_DV :
case V4L2_PIX_FMT_MPEG :
case V4L2_PIX_FMT_WNVA :
case V4L2_PIX_FMT_SN9C10X :
case V4L2_PIX_FMT_PWC1 :
case V4L2_PIX_FMT_PWC2 :
case V4L2_PIX_FMT_ET61X251 :
case V4L2_PIX_FMT_SPCA501 :
case V4L2_PIX_FMT_SPCA505 :
case V4L2_PIX_FMT_SPCA508 :
case V4L2_PIX_FMT_SPCA561 :
case V4L2_PIX_FMT_PAC207 :
case V4L2_PIX_FMT_PJPG :
case V4L2_PIX_FMT_YVYU :
default :
{
Fatal( "Can't find swscale format for palette %d", palette );
break;
// These are all spare and may match some of the above
ffPixFormat = PIX_FMT_YUVJ420P;
ffPixFormat = PIX_FMT_YUVJ422P;
ffPixFormat = PIX_FMT_YUVJ444P;
ffPixFormat = PIX_FMT_XVMC_MPEG2_MC;
ffPixFormat = PIX_FMT_XVMC_MPEG2_IDCT;
ffPixFormat = PIX_FMT_UYVY422;
ffPixFormat = PIX_FMT_UYYVYY411;
ffPixFormat = PIX_FMT_BGR565;
ffPixFormat = PIX_FMT_BGR555;
ffPixFormat = PIX_FMT_BGR8;
ffPixFormat = PIX_FMT_BGR4;
ffPixFormat = PIX_FMT_BGR4_BYTE;
ffPixFormat = PIX_FMT_RGB8;
ffPixFormat = PIX_FMT_RGB4;
ffPixFormat = PIX_FMT_RGB4_BYTE;
ffPixFormat = PIX_FMT_NV12;
ffPixFormat = PIX_FMT_NV21;
ffPixFormat = PIX_FMT_RGB32_1;
ffPixFormat = PIX_FMT_BGR32_1;
ffPixFormat = PIX_FMT_GRAY16BE;
ffPixFormat = PIX_FMT_GRAY16LE;
ffPixFormat = PIX_FMT_YUV440P;
ffPixFormat = PIX_FMT_YUVJ440P;
ffPixFormat = PIX_FMT_YUVA420P;
ffPixFormat = PIX_FMT_VDPAU_H264;
ffPixFormat = PIX_FMT_VDPAU_MPEG1;
ffPixFormat = PIX_FMT_VDPAU_MPEG2;
ffPixFormat = PIX_FMT_NB;
}
}
imgConversionContext = sws_getContext( width, height, ffPixFormat, width, height, PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL );
if ( !imgConversionContext )
Fatal( "Unable to initialise image scaling context" );
Info( "Using swscaler" );
picture = avcodec_alloc_frame();
if ( !picture )
Fatal( "Could not allocate picture" );
int size = avpicture_get_size( ffPixFormat, width, height);
avpicture_fill( (AVPicture *)picture, buffer, ffPixFormat, width, height );
tmpPicture = avcodec_alloc_frame();
if ( !tmpPicture )
Fatal( "Could not allocate temporary picture" );
size = avpicture_get_size( PIX_FMT_RGB24, width, height);
uint8_t *tmpPictureBuf = (uint8_t *)av_malloc(size);
if (!tmpPictureBuf)
Fatal( "Could not allocate temporary picture buffer" );
avpicture_fill( (AVPicture *)tmpPicture, tmpPictureBuf, PIX_FMT_RGB24, width, height );
}
sws_scale( imgConversionContext, picture->data, picture->linesize, 0, height, tmpPicture->data, tmpPicture->linesize );
buffer = tmpPicture->data[0];
#else // HAVE_LIBSWSCALE
static unsigned char temp_buffer[ZM_MAX_IMAGE_SIZE]; static unsigned char temp_buffer[ZM_MAX_IMAGE_SIZE];
switch( palette ) switch( palette )
{ {
case VIDEO_PALETTE_YUV420P : case VIDEO_PALETTE_YUV420P :
case V4L2_PIX_FMT_YUV420 :
{ {
static unsigned char y_plane[ZM_MAX_IMAGE_DIM]; static unsigned char y_plane[ZM_MAX_IMAGE_DIM];
static char u_plane[ZM_MAX_IMAGE_DIM]; static char u_plane[ZM_MAX_IMAGE_DIM];
@ -1163,6 +1328,7 @@ int LocalCamera::PostCapture( Image &image )
break; break;
} }
case VIDEO_PALETTE_YUV422P : case VIDEO_PALETTE_YUV422P :
case V4L2_PIX_FMT_YUV422P :
{ {
static unsigned char y_plane[ZM_MAX_IMAGE_DIM]; static unsigned char y_plane[ZM_MAX_IMAGE_DIM];
static char u_plane[ZM_MAX_IMAGE_DIM]; static char u_plane[ZM_MAX_IMAGE_DIM];
@ -1221,6 +1387,7 @@ int LocalCamera::PostCapture( Image &image )
} }
case VIDEO_PALETTE_YUYV : case VIDEO_PALETTE_YUYV :
case VIDEO_PALETTE_YUV422 : case VIDEO_PALETTE_YUV422 :
case V4L2_PIX_FMT_YUYV :
{ {
int size = width*height*2; int size = width*height*2;
unsigned char *s_ptr = buffer; unsigned char *s_ptr = buffer;
@ -1255,6 +1422,7 @@ int LocalCamera::PostCapture( Image &image )
break; break;
} }
case VIDEO_PALETTE_RGB555 : case VIDEO_PALETTE_RGB555 :
case V4L2_PIX_FMT_RGB555 :
{ {
int size = width*height*2; int size = width*height*2;
unsigned char r,g,b; unsigned char r,g,b;
@ -1275,6 +1443,7 @@ int LocalCamera::PostCapture( Image &image )
break; break;
} }
case VIDEO_PALETTE_RGB565 : case VIDEO_PALETTE_RGB565 :
case V4L2_PIX_FMT_RGB565 :
{ {
int size = width*height*2; int size = width*height*2;
unsigned char r,g,b; unsigned char r,g,b;
@ -1312,7 +1481,23 @@ int LocalCamera::PostCapture( Image &image )
} }
break; break;
} }
case V4L2_PIX_FMT_BGR24 :
{
int size = width*height*3;
unsigned char *s_ptr = buffer;
unsigned char *d_ptr = temp_buffer;
for ( int i = 0; i < size; i += 3 )
{
*d_ptr++ = *(s_ptr+2);
*d_ptr++ = *(s_ptr+1);
*d_ptr++ = *s_ptr;
s_ptr += 3;
}
buffer = temp_buffer;
break;
}
case VIDEO_PALETTE_GREY : case VIDEO_PALETTE_GREY :
case V4L2_PIX_FMT_GREY :
{ {
//int size = width*height; //int size = width*height;
//for ( int i = 0; i < size; i++ ) //for ( int i = 0; i < size; i++ )
@ -1328,6 +1513,7 @@ int LocalCamera::PostCapture( Image &image )
break; break;
} }
} }
#endif // HAVE_LIBSWSCALE
} }
Debug( 3, "Assigning image" ); Debug( 3, "Assigning image" );

View File

@ -611,6 +611,7 @@ $SLANG = array(
'TurboTiltSpeed' => 'Turbo Tilt Speed', 'TurboTiltSpeed' => 'Turbo Tilt Speed',
'Type' => 'Type', 'Type' => 'Type',
'Unarchive' => 'Unarchive', 'Unarchive' => 'Unarchive',
'Undefined' => 'Undefined',
'Units' => 'Units', 'Units' => 'Units',
'Unknown' => 'Unknown', 'Unknown' => 'Unknown',
'UpdateAvailable' => 'An update to ZoneMinder is available.', 'UpdateAvailable' => 'An update to ZoneMinder is available.',

View File

@ -179,7 +179,8 @@ if ( !ZM_PCRE )
// Currently unsupported // Currently unsupported
unset($httpMethods['jpegTags']); unset($httpMethods['jpegTags']);
$deviceFormats = array( $v4l1DeviceFormats = array(
$SLANG['Undefined'] => -1,
"PAL" => 0, "PAL" => 0,
"NTSC" => 1, "NTSC" => 1,
"SECAM" => 2, "SECAM" => 2,
@ -190,21 +191,132 @@ $deviceFormats = array(
"FMT7" => 7 "FMT7" => 7
); );
$deviceChannels = array(); $v4l1MaxChannels = 15;
for ( $i = 0; $i <= 15; $i++ ) $v4l1DeviceChannels = array();
$deviceChannels["$i"] = $i; for ( $i = 0; $i <= $v4l1MaxChannels; $i++ )
$v4l1DeviceChannels["$i"] = $i;
$localPalettes = array( $v4l1LocalPalettes = array(
$SLANG['Grey'] => 1, $SLANG['Undefined'] => 0,
"RGB24" => 4, $SLANG['Grey'] => 1,
"RGB565" => 3, "RGB24" => 4,
"RGB555" => 6, "RGB565" => 3,
"YUV422" => 7, "RGB555" => 6,
"YUYV" => 8, "YUV422" => 7,
"YUV422P" => 13, "YUYV" => 8,
"YUV420P" => 15 "YUV422P" => 13,
"YUV420P" => 15
); );
if ( ZM_V4L2 )
{
$v4l2DeviceFormats = array(
$SLANG['Undefined'] => 0,
"PAL B" => 0x00000001,
"PAL B1" => 0x00000002,
"PAL G" => 0x00000004,
"PAL H" => 0x00000008,
"PAL I" => 0x00000010,
"PAL D" => 0x00000020,
"PAL D1" => 0x00000040,
"PAL K" => 0x00000080,
"PAL M" => 0x00000100,
"PAL N" => 0x00000200,
"PAL Nc" => 0x00000400,
"PAL 60" => 0x00000800,
"NTSC M" => 0x00001000,
"NTSC M JP" => 0x00002000,
"NTSC 443" => 0x00004000,
"NTSC M KR" => 0x00008000,
"SECAM B" => 0x00010000,
"SECAM D" => 0x00020000,
"SECAM G" => 0x00040000,
"SECAM H" => 0x00080000,
"SECAM K" => 0x00100000,
"SECAM K1" => 0x00200000,
"SECAM L" => 0x00400000,
"SECAM LC" => 0x00800000,
"ATSC 8 VSB" => 0x01000000,
"ATSC 16 VSB" => 0x02000000,
);
$v4l2MaxChannels = 31;
$v4l2DeviceChannels = array();
for ( $i = 0; $i <= $v4l2MaxChannels; $i++ )
$v4l2DeviceChannels["$i"] = $i;
function fourcc( $a, $b, $c, $d )
{
return( ord($a) | (ord($b) << 8) | (ord($c) << 16) | (ord($d) << 24) );
}
$v4l2LocalPalettes = array(
$SLANG['Undefined'] => 0,
/* Pixel format FOURCC depth Description */
"RGB332" => fourcc('R','G','B','1'), /* 8 RGB-3-3-2 */
"RGB444" => fourcc('R','4','4','4'), /* 16 xxxxrrrr ggggbbbb */
"RGB555" => fourcc('R','G','B','O'), /* 16 RGB-5-5-5 */
"RGB565" => fourcc('R','G','B','P'), /* 16 RGB-5-6-5 */
"RGB555X" => fourcc('R','G','B','Q'), /* 16 RGB-5-5-5 BE */
"RGB565X" => fourcc('R','G','B','R'), /* 16 RGB-5-6-5 BE */
"BGR24" => fourcc('B','G','R','3'), /* 24 BGR-8-8-8 */
"RGB24" => fourcc('R','G','B','3'), /* 24 RGB-8-8-8 */
"BGR32" => fourcc('B','G','R','4'), /* 32 BGR-8-8-8-8 */
"RGB32" => fourcc('R','G','B','4'), /* 32 RGB-8-8-8-8 */
"GREY" => fourcc('G','R','E','Y'), /* 8 Greyscale */
"Y16" => fourcc('Y','1','6',''), /* 16 Greyscale */
"PAL8" => fourcc('P','A','L','8'), /* 8 8-bit palette */
"YVU410" => fourcc('Y','V','U','9'), /* 9 YVU 4:1:0 */
"YVU420" => fourcc('Y','V','1','2'), /* 12 YVU 4:2:0 */
"YUYV" => fourcc('Y','U','Y','V'), /* 16 YUV 4:2:2 */
"UYVY" => fourcc('U','Y','V','Y'), /* 16 YUV 4:2:2 */
"YUV422P" => fourcc('4','2','2','P'), /* 16 YVU422 planar */
"YUV411P" => fourcc('4','1','1','P'), /* 16 YVU411 planar */
"Y41P" => fourcc('Y','4','1','P'), /* 12 YUV 4:1:1 */
"YUV444" => fourcc('Y','4','4','4'), /* 16 xxxxyyyy uuuuvvvv */
"YUV555" => fourcc('Y','U','V','O'), /* 16 YUV-5-5-5 */
"YUV565" => fourcc('Y','U','V','P'), /* 16 YUV-5-6-5 */
"YUV32" => fourcc('Y','U','V','4'), /* 32 YUV-8-8-8-8 */
/* two planes -- one Y, one Cr + Cb interleaved */
"NV12" => fourcc('N','V','1','2'), /* 12 Y/CbCr 4:2:0 */
"NV21" => fourcc('N','V','2','1'), /* 12 Y/CrCb 4:2:0 */
/* The following formats are not defined in the V4L2 specification */
"YUV410" => fourcc('Y','U','V','9'), /* 9 YUV 4:1:0 */
"YUV420" => fourcc('Y','U','1','2'), /* 12 YUV 4:2:0 */
"YYUV" => fourcc('Y','Y','U','V'), /* 16 YUV 4:2:2 */
"HI240" => fourcc('H','I','2','4'), /* 8 8-bit color */
"HM12" => fourcc('H','M','1','2'), /* 8 YUV 4:2:0 16x16 macroblocks */
/* see http://www.siliconimaging.com/RGB%20Bayer.htm */
"SBGGR8" => fourcc('B','A','8','1'), /* 8 BGBG.. GRGR.. */
"SGBRG8" => fourcc('G','B','R','G'), /* 8 GBGB.. RGRG.. */
"SBGGR16" => fourcc('B','Y','R','2'), /* 16 BGBG.. GRGR.. */
/* compressed formats */
"MJPEG" => fourcc('M','J','P','G'), /* Motion-JPEG */
"JPEG" => fourcc('J','P','E','G'), /* JFIF JPEG */
"DV" => fourcc('d','v','s','d'), /* 1394 */
"MPEG" => fourcc('M','P','E','G'), /* MPEG-1/2/4 */
/* Vendor-specific formats */
"WNVA" => fourcc('W','N','V','A'), /* Winnov hw compress */
"SN9C10X" => fourcc('S','9','1','0'), /* SN9C10x compression */
"PWC1" => fourcc('P','W','C','1'), /* pwc older webcam */
"PWC2" => fourcc('P','W','C','2'), /* pwc newer webcam */
"ET61X251" => fourcc('E','6','2','5'), /* ET61X251 compression */
"SPCA501" => fourcc('S','5','0','1'), /* YUYV per line */
"SPCA505" => fourcc('S','5','0','5'), /* YYUV per line */
"SPCA508" => fourcc('S','5','0','8'), /* YUVY per line */
"SPCA561" => fourcc('S','5','6','1'), /* compressed GBRG bayer */
"PAC207" => fourcc('P','2','0','7'), /* compressed BGGR bayer */
"PJPG" => fourcc('P','J','P','G'), /* Pixart 73xx JPEG */
"YVYU" => fourcc('Y','V','Y','U'), /* 16 YVU 4:2:2 */
);
}
$remoteColours = $fileColours = array( $remoteColours = $fileColours = array(
$SLANG['8BitGrey'] => 1, $SLANG['8BitGrey'] => 1,
$SLANG['24BitColour'] => 3 $SLANG['24BitColour'] => 3
@ -474,11 +586,24 @@ switch ( $tab )
{ {
?> ?>
<tr><td><?= $SLANG['DevicePath'] ?></td><td><input type="text" name="newMonitor[Device]" value="<?= validHtmlStr($newMonitor['Device']) ?>" size="24"/></td></tr> <tr><td><?= $SLANG['DevicePath'] ?></td><td><input type="text" name="newMonitor[Device]" value="<?= validHtmlStr($newMonitor['Device']) ?>" size="24"/></td></tr>
<tr><td><?= $SLANG['DeviceChannel'] ?></td><td><select name="newMonitor[Channel]"><?php foreach ( $deviceChannels as $name => $value ) { ?><option value="<?= $value ?>"<?php if ( $value == $newMonitor['Channel'] ) { ?> selected="selected"<?php } ?>><?= $name ?></option><?php } ?></select></td></tr> <tr><td><?= $SLANG['CaptureMethod'] ?></td><td><?= buildSelect( "newMonitor[Method]", $localMethods, "submitTab( '$tab' )" ); ?></td></tr>
<tr><td><?= $SLANG['DeviceFormat'] ?></td><td><select name="newMonitor[Format]"><?php foreach ( $deviceFormats as $name => $value ) { ?><option value="<?= $value ?>"<?php if ( $value == $newMonitor['Format'] ) { ?> selected="selected"<?php } ?>><?= $name ?></option><?php } ?></select></td></tr>
<tr><td><?= $SLANG['CaptureMethod'] ?></td><td><?= buildSelect( "newMonitor[Method]", $localMethods ); ?></td></tr>
<tr><td><?= $SLANG['CapturePalette'] ?></td><td><select name="newMonitor[Palette]"><?php foreach ( $localPalettes as $name => $value ) { ?><option value="<?= $value ?>"<?php if ( $value == $newMonitor['Palette'] ) { ?> selected="selected"<?php } ?>><?= $name ?></option><?php } ?></select></td></tr>
<?php <?php
if ( ZM_V4L2 && $newMonitor['Method'] == 'v4l2' )
{
?>
<tr><td><?= $SLANG['DeviceChannel'] ?></td><td><select name="newMonitor[Channel]"><?php foreach ( $v4l2DeviceChannels as $name => $value ) { ?><option value="<?= $value ?>"<?php if ( $value == $newMonitor['Channel'] ) { ?> selected="selected"<?php } ?>><?= $name ?></option><?php } ?></select></td></tr>
<tr><td><?= $SLANG['DeviceFormat'] ?></td><td><select name="newMonitor[Format]"><?php foreach ( $v4l2DeviceFormats as $name => $value ) { ?><option value="<?= $value ?>"<?php if ( $value == $newMonitor['Format'] ) { ?> selected="selected"<?php } ?>><?= $name ?></option><?php } ?></select></td></tr>
<tr><td><?= $SLANG['CapturePalette'] ?></td><td><select name="newMonitor[Palette]"><?php foreach ( $v4l2LocalPalettes as $name => $value ) { ?><option value="<?= $value ?>"<?php if ( $value == $newMonitor['Palette'] ) { ?> selected="selected"<?php } ?>><?= $name ?></option><?php } ?></select></td></tr>
<?php
}
else
{
?>
<tr><td><?= $SLANG['DeviceChannel'] ?></td><td><select name="newMonitor[Channel]"><?php foreach ( $v4l1DeviceChannels as $name => $value ) { ?><option value="<?= $value ?>"<?php if ( $value == $newMonitor['Channel'] ) { ?> selected="selected"<?php } ?>><?= $name ?></option><?php } ?></select></td></tr>
<tr><td><?= $SLANG['DeviceFormat'] ?></td><td><select name="newMonitor[Format]"><?php foreach ( $v4l1DeviceFormats as $name => $value ) { ?><option value="<?= $value ?>"<?php if ( $value == $newMonitor['Format'] ) { ?> selected="selected"<?php } ?>><?= $name ?></option><?php } ?></select></td></tr>
<tr><td><?= $SLANG['CapturePalette'] ?></td><td><select name="newMonitor[Palette]"><?php foreach ( $v4l1LocalPalettes as $name => $value ) { ?><option value="<?= $value ?>"<?php if ( $value == $newMonitor['Palette'] ) { ?> selected="selected"<?php } ?>><?= $name ?></option><?php } ?></select></td></tr>
<?php
}
} }
elseif ( $newMonitor['Type'] == "Remote" ) elseif ( $newMonitor['Type'] == "Remote" )
{ {