diff --git a/db/zm_create.sql.in b/db/zm_create.sql.in index 1f275f3bd..7cf9bfadc 100644 --- a/db/zm_create.sql.in +++ b/db/zm_create.sql.in @@ -269,8 +269,8 @@ CREATE TABLE `MonitorPresets` ( `Name` varchar(64) NOT NULL default '', `Type` enum('Local','Remote','File','Ffmpeg') NOT NULL default 'Local', `Device` tinytext, - `Channel` varchar(32) default NULL, - `Format` varchar(32) default NULL, + `Channel` tinyint(3) unsigned default NULL, + `Format` int(10) unsigned default NULL, `Protocol` varchar(16) default NULL, `Method` varchar(16) default NULL, `Host` varchar(64) default NULL, @@ -279,7 +279,7 @@ CREATE TABLE `MonitorPresets` ( `SubPath` varchar(64) default NULL, `Width` 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, `Controllable` tinyint(3) unsigned NOT NULL default '0', `ControlId` varchar(16) default NULL, @@ -305,7 +305,7 @@ CREATE TABLE `Monitors` ( `Triggers` set('X10') NOT NULL default '', `Device` varchar(64) NOT NULL default '', `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 '', `Method` varchar(16) NOT NULL default '', `Host` varchar(64) NOT NULL default '', @@ -314,7 +314,7 @@ CREATE TABLE `Monitors` ( `Path` varchar(64) NOT NULL default '', `Width` 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', `Brightness` mediumint(7) NOT NULL default '-1', `Contrast` mediumint(7) NOT NULL default '-1', diff --git a/db/zm_update-1.23.3.sql b/db/zm_update-1.23.3.sql index 7c483aa1c..5c1757fca 100644 --- a/db/zm_update-1.23.3.sql +++ b/db/zm_update-1.23.3.sql @@ -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 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 -- diff --git a/src/zm_local_camera.cpp b/src/zm_local_camera.cpp index 9796cec54..ade23ea8a 100644 --- a/src/zm_local_camera.cpp +++ b/src/zm_local_camera.cpp @@ -17,22 +17,24 @@ // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // +#include "zm_local_camera.h" + +#include "zm_ffmpeg.h" + #include #include #include #include #include -#include "zm_local_camera.h" - static int vidioctl( int fd, int request, void *arg ) { - int result; - do - { - result = ioctl( fd, request, arg ); - } while ( result == -1 && errno == EINTR ); - return( result ); + int result = -1; + do + { + result = ioctl( fd, request, arg ); + } while ( result == -1 && errno == EINTR ); + return( result ); } int LocalCamera::camera_count = 0; @@ -146,58 +148,17 @@ void LocalCamera::Initialise() memset( &v4l2_data.fmt, 0, sizeof(v4l2_data.fmt) ); 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.height = height; - switch( 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.pixelformat = palette; 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) ); /* 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.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) ); v4l2_data.buffers[i].length = vid_buf.length; @@ -257,6 +218,34 @@ void LocalCamera::Initialise() 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 ); } + + 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 #endif // ZM_V4L2 @@ -688,19 +677,22 @@ int LocalCamera::Brightness( int p_brightness ) Error( "Unable to query brightness: %s", strerror(errno) ) else Warning( "Brightness control is not suppported" ) + Info( "Brightness 1 %d", vid_control.value ); } - else + else if ( p_brightness >= 0 ) { vid_control.value = p_brightness; + Info( "Brightness 2 %d", vid_control.value ); /* 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 ) Error( "Unable to set brightness: %s", strerror(errno) ) else Warning( "Given brightness value (%d) may be out-of-range", p_brightness ) } + Info( "Brightness 3 %d", vid_control.value ); } return( vid_control.value ); } @@ -744,7 +736,7 @@ int LocalCamera::Hue( int p_hue ) else Warning( "Hue control is not suppported" ) } - else + else if ( p_hue >= 0 ) { vid_control.value = p_hue; @@ -799,7 +791,7 @@ int LocalCamera::Colour( int p_colour ) else Warning( "Saturation control is not suppported" ) } - else + else if ( p_colour >= 0 ) { vid_control.value = p_colour; @@ -854,12 +846,12 @@ int LocalCamera::Contrast( int p_contrast ) else Warning( "Contrast control is not suppported" ) } - else + else if ( p_contrast >= 0 ) { vid_control.value = p_contrast; /* 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 ) Error( "Unable to set contrast: %s", strerror(errno) ) @@ -921,7 +913,7 @@ int LocalCamera::PrimeCapture() vid_buf.memory = v4l2_data.reqbufs.memory; 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) ); } } @@ -950,17 +942,27 @@ int LocalCamera::PreCapture() if ( channel_count > 1 ) { 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) ); 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" ); if ( v4l2_data.buffer ) { 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 @@ -1087,10 +1089,173 @@ int LocalCamera::PostCapture( Image &image ) 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]; switch( palette ) { case VIDEO_PALETTE_YUV420P : + case V4L2_PIX_FMT_YUV420 : { static unsigned char y_plane[ZM_MAX_IMAGE_DIM]; static char u_plane[ZM_MAX_IMAGE_DIM]; @@ -1163,6 +1328,7 @@ int LocalCamera::PostCapture( Image &image ) break; } case VIDEO_PALETTE_YUV422P : + case V4L2_PIX_FMT_YUV422P : { static unsigned char y_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_YUV422 : + case V4L2_PIX_FMT_YUYV : { int size = width*height*2; unsigned char *s_ptr = buffer; @@ -1255,6 +1422,7 @@ int LocalCamera::PostCapture( Image &image ) break; } case VIDEO_PALETTE_RGB555 : + case V4L2_PIX_FMT_RGB555 : { int size = width*height*2; unsigned char r,g,b; @@ -1275,6 +1443,7 @@ int LocalCamera::PostCapture( Image &image ) break; } case VIDEO_PALETTE_RGB565 : + case V4L2_PIX_FMT_RGB565 : { int size = width*height*2; unsigned char r,g,b; @@ -1312,7 +1481,23 @@ int LocalCamera::PostCapture( Image &image ) } 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 V4L2_PIX_FMT_GREY : { //int size = width*height; //for ( int i = 0; i < size; i++ ) @@ -1328,6 +1513,7 @@ int LocalCamera::PostCapture( Image &image ) break; } } +#endif // HAVE_LIBSWSCALE } Debug( 3, "Assigning image" ); diff --git a/web/lang/en_gb.php b/web/lang/en_gb.php index eba11d900..327045dcc 100644 --- a/web/lang/en_gb.php +++ b/web/lang/en_gb.php @@ -611,6 +611,7 @@ $SLANG = array( 'TurboTiltSpeed' => 'Turbo Tilt Speed', 'Type' => 'Type', 'Unarchive' => 'Unarchive', + 'Undefined' => 'Undefined', 'Units' => 'Units', 'Unknown' => 'Unknown', 'UpdateAvailable' => 'An update to ZoneMinder is available.', diff --git a/web/skins/classic/views/monitor.php b/web/skins/classic/views/monitor.php index da930bc91..0e5c684f0 100644 --- a/web/skins/classic/views/monitor.php +++ b/web/skins/classic/views/monitor.php @@ -179,7 +179,8 @@ if ( !ZM_PCRE ) // Currently unsupported unset($httpMethods['jpegTags']); -$deviceFormats = array( +$v4l1DeviceFormats = array( + $SLANG['Undefined'] => -1, "PAL" => 0, "NTSC" => 1, "SECAM" => 2, @@ -190,21 +191,132 @@ $deviceFormats = array( "FMT7" => 7 ); -$deviceChannels = array(); -for ( $i = 0; $i <= 15; $i++ ) - $deviceChannels["$i"] = $i; +$v4l1MaxChannels = 15; +$v4l1DeviceChannels = array(); +for ( $i = 0; $i <= $v4l1MaxChannels; $i++ ) + $v4l1DeviceChannels["$i"] = $i; -$localPalettes = array( - $SLANG['Grey'] => 1, - "RGB24" => 4, - "RGB565" => 3, - "RGB555" => 6, - "YUV422" => 7, - "YUYV" => 8, - "YUV422P" => 13, - "YUV420P" => 15 +$v4l1LocalPalettes = array( + $SLANG['Undefined'] => 0, + $SLANG['Grey'] => 1, + "RGB24" => 4, + "RGB565" => 3, + "RGB555" => 6, + "YUV422" => 7, + "YUYV" => 8, + "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( $SLANG['8BitGrey'] => 1, $SLANG['24BitColour'] => 3 @@ -474,11 +586,24 @@ switch ( $tab ) { ?> - - - - + + + + + + + + +