Added query capabilities for V4L2 cameras
git-svn-id: http://svn.zoneminder.com/svn/zm/trunk@2824 e3e1d417-86f3-4887-817a-d78f3d33393f
This commit is contained in:
parent
3310ea3ae9
commit
41c2889df2
|
@ -240,7 +240,6 @@ int LocalCamera::channel_count = 0;
|
||||||
int LocalCamera::channels[VIDEO_MAX_FRAME];
|
int LocalCamera::channels[VIDEO_MAX_FRAME];
|
||||||
int LocalCamera::standards[VIDEO_MAX_FRAME];
|
int LocalCamera::standards[VIDEO_MAX_FRAME];
|
||||||
|
|
||||||
|
|
||||||
int LocalCamera::vid_fd = -1;
|
int LocalCamera::vid_fd = -1;
|
||||||
|
|
||||||
int LocalCamera::v4l_version = 0;
|
int LocalCamera::v4l_version = 0;
|
||||||
|
@ -721,7 +720,7 @@ bool LocalCamera::GetCurrentSettings( const char *device, char *output, bool ver
|
||||||
output[0] = 0;
|
output[0] = 0;
|
||||||
if ( verbose )
|
if ( verbose )
|
||||||
sprintf( output, output+strlen(output), "Checking Video Device: %s\n", device );
|
sprintf( output, output+strlen(output), "Checking Video Device: %s\n", device );
|
||||||
if ( (vid_fd=open(device, O_RDWR)) <=0 )
|
if ( (vid_fd = open(device, O_RDWR)) <= 0 )
|
||||||
{
|
{
|
||||||
Error( "Failed to open video device %s: %s", device, strerror(errno) );
|
Error( "Failed to open video device %s: %s", device, strerror(errno) );
|
||||||
if ( verbose )
|
if ( verbose )
|
||||||
|
@ -731,6 +730,244 @@ bool LocalCamera::GetCurrentSettings( const char *device, char *output, bool ver
|
||||||
return( false );
|
return( false );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef ZM_V4L2
|
||||||
|
//if ( v4l_version == 2 )
|
||||||
|
if ( true )
|
||||||
|
{
|
||||||
|
struct v4l2_capability vid_cap;
|
||||||
|
if ( vidioctl( vid_fd, VIDIOC_QUERYCAP, &vid_cap ) < 0 )
|
||||||
|
{
|
||||||
|
Error( "Failed to query video device: %s", strerror(errno) );
|
||||||
|
if ( verbose )
|
||||||
|
sprintf( output, "Error, failed to query video capabilities %s: %s\n", device, strerror(errno) );
|
||||||
|
else
|
||||||
|
sprintf( output, "error%d\n", errno );
|
||||||
|
return( false );
|
||||||
|
}
|
||||||
|
#define capString(test,prefix,yesString,noString,capability) \
|
||||||
|
(test) ? (prefix yesString " " capability "\n") : (prefix noString " " capability "\n")
|
||||||
|
|
||||||
|
if ( verbose )
|
||||||
|
{
|
||||||
|
sprintf( output+strlen(output), "General Capabilities\n" );
|
||||||
|
sprintf( output+strlen(output), " Driver: %s\n", vid_cap.driver );
|
||||||
|
sprintf( output+strlen(output), " Card: %s\n", vid_cap.card );
|
||||||
|
sprintf( output+strlen(output), " Bus: %s\n", vid_cap.bus_info );
|
||||||
|
sprintf( output+strlen(output), " Version: %u.%u.%u\n", (vid_cap.version>>16)&0xff, (vid_cap.version>>8)&0xff, vid_cap.version&0xff );
|
||||||
|
sprintf( output+strlen(output), " Type: 0x%x\n%s%s%s%s%s%s%s%s%s%s%s%s%s%s", vid_cap.capabilities,
|
||||||
|
capString( vid_cap.capabilities&V4L2_CAP_VIDEO_CAPTURE, " ", "Supports", "Does not support", "video capture (X)" ),
|
||||||
|
capString( vid_cap.capabilities&V4L2_CAP_VIDEO_OUTPUT, " ", "Supports", "Does not support", "video output" ),
|
||||||
|
capString( vid_cap.capabilities&V4L2_CAP_VIDEO_OVERLAY, " ", "Supports", "Does not support", "frame buffer overlay" ),
|
||||||
|
capString( vid_cap.capabilities&V4L2_CAP_VBI_CAPTURE, " ", "Supports", "Does not support", "VBI capture" ),
|
||||||
|
capString( vid_cap.capabilities&V4L2_CAP_VBI_OUTPUT, " ", "Supports", "Does not support", "VBI output" ),
|
||||||
|
capString( vid_cap.capabilities&V4L2_CAP_SLICED_VBI_CAPTURE, " ", "Supports", "Does not support", "sliced VBI capture" ),
|
||||||
|
capString( vid_cap.capabilities&V4L2_CAP_SLICED_VBI_OUTPUT, " ", "Supports", "Does not support", "sliced VBI output" ),
|
||||||
|
capString( vid_cap.capabilities&V4L2_CAP_VIDEO_OUTPUT_OVERLAY, " ", "Supports", "Does not support", "video output overlay" ),
|
||||||
|
capString( vid_cap.capabilities&V4L2_CAP_TUNER, " ", "Has", "Does not have", "tuner" ),
|
||||||
|
capString( vid_cap.capabilities&V4L2_CAP_AUDIO, " ", "Has", "Does not have", "audio in and/or out" ),
|
||||||
|
capString( vid_cap.capabilities&V4L2_CAP_RADIO, " ", "Has", "Does not have", "radio" ),
|
||||||
|
capString( vid_cap.capabilities&V4L2_CAP_READWRITE, " ", "Supports", "Does not support", "read/write i/o (X)" ),
|
||||||
|
capString( vid_cap.capabilities&V4L2_CAP_ASYNCIO, " ", "Supports", "Does not support", "async i/o" ),
|
||||||
|
capString( vid_cap.capabilities&V4L2_CAP_STREAMING, " ", "Supports", "Does not support", "streaming i/o (X)" )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sprintf( output+strlen(output), "D:%s ", vid_cap.driver );
|
||||||
|
sprintf( output+strlen(output), "C:%s ", vid_cap.card );
|
||||||
|
sprintf( output+strlen(output), "B:%s ", vid_cap.bus_info );
|
||||||
|
sprintf( output+strlen(output), "V:%u.%u.%u ", (vid_cap.version>>16)&0xff, (vid_cap.version>>8)&0xff, vid_cap.version&0xff );
|
||||||
|
sprintf( output+strlen(output), "T:0x%x ", vid_cap.capabilities );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( verbose )
|
||||||
|
sprintf( output+strlen(output), " Standards:\n" );
|
||||||
|
struct v4l2_standard standard;
|
||||||
|
int standardIndex = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
memset( &standard, 0, sizeof(standard) );
|
||||||
|
standard.index = standardIndex;
|
||||||
|
|
||||||
|
if ( vidioctl( vid_fd, VIDIOC_ENUMSTD, &standard ) < 0 )
|
||||||
|
{
|
||||||
|
if ( errno == EINVAL )
|
||||||
|
{
|
||||||
|
standardIndex = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Error( "Failed to enumerate standard %d: %s", standard.index, strerror(errno) );
|
||||||
|
if ( verbose )
|
||||||
|
sprintf( output, "Error, failed to enumerate standard %d: %s\n", standard.index, strerror(errno) );
|
||||||
|
else
|
||||||
|
sprintf( output, "error%d\n", errno );
|
||||||
|
return( false );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( verbose )
|
||||||
|
sprintf( output+strlen(output), " %s\n", standard.name );
|
||||||
|
else
|
||||||
|
sprintf( output+strlen(output), "S:%s ", standard.name );
|
||||||
|
}
|
||||||
|
while ( standardIndex++ >= 0 );
|
||||||
|
|
||||||
|
if ( verbose )
|
||||||
|
sprintf( output+strlen(output), " Formats:\n" );
|
||||||
|
struct v4l2_fmtdesc format;
|
||||||
|
int formatIndex = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
memset( &format, 0, sizeof(format) );
|
||||||
|
format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||||
|
format.index = formatIndex;
|
||||||
|
|
||||||
|
if ( vidioctl( vid_fd, VIDIOC_ENUM_FMT, &format ) < 0 )
|
||||||
|
{
|
||||||
|
if ( errno == EINVAL )
|
||||||
|
{
|
||||||
|
formatIndex = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Error( "Failed to enumerate format %d: %s", format.index, strerror(errno) );
|
||||||
|
if ( verbose )
|
||||||
|
sprintf( output, "Error, failed to enumerate format %d: %s\n", format.index, strerror(errno) );
|
||||||
|
else
|
||||||
|
sprintf( output, "error%d\n", errno );
|
||||||
|
return( false );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( verbose )
|
||||||
|
sprintf( output+strlen(output), " %s (%c%c%c%c)\n", format.description, format.pixelformat&0xff, (format.pixelformat>>8)&0xff, (format.pixelformat>>16)&0xff, (format.pixelformat>>24)&0xff );
|
||||||
|
else
|
||||||
|
sprintf( output+strlen(output), "F:%c%c%c%c ", format.pixelformat&0xff, (format.pixelformat>>8)&0xff, (format.pixelformat>>16)&0xff, (format.pixelformat>>24)&0xff );
|
||||||
|
}
|
||||||
|
while ( formatIndex++ >= 0 );
|
||||||
|
|
||||||
|
struct v4l2_cropcap cropcap;
|
||||||
|
memset( &cropcap, 0, sizeof(cropcap) );
|
||||||
|
cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||||
|
if ( vidioctl( vid_fd, VIDIOC_CROPCAP, &cropcap ) < 0 )
|
||||||
|
{
|
||||||
|
Error( "Failed to query crop capabilities: %s", strerror(errno) );
|
||||||
|
if ( verbose )
|
||||||
|
sprintf( output, "Error, failed to query crop capabilities %s: %s\n", device, strerror(errno) );
|
||||||
|
else
|
||||||
|
sprintf( output, "error%d\n", errno );
|
||||||
|
return( false );
|
||||||
|
}
|
||||||
|
if ( verbose )
|
||||||
|
{
|
||||||
|
sprintf( output+strlen(output), "Crop Capabilities\n" );
|
||||||
|
sprintf( output+strlen(output), " Bounds: %d x %d\n", cropcap.bounds.width, cropcap.bounds.height );
|
||||||
|
sprintf( output+strlen(output), " Default: %d x %d\n", cropcap.defrect.width, cropcap.defrect.height );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sprintf( output+strlen(output), "B:%dx%d ", cropcap.bounds.width, cropcap.bounds.height );
|
||||||
|
}
|
||||||
|
|
||||||
|
struct v4l2_crop crop;
|
||||||
|
memset( &crop, 0, sizeof(crop) );
|
||||||
|
crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||||
|
if ( vidioctl( vid_fd, VIDIOC_G_CROP, &crop ) < 0 )
|
||||||
|
{
|
||||||
|
Error( "Failed to query crop: %s", strerror(errno) );
|
||||||
|
if ( verbose )
|
||||||
|
sprintf( output, "Error, failed to query crop %s: %s\n", device, strerror(errno) );
|
||||||
|
else
|
||||||
|
sprintf( output, "error%d\n", errno );
|
||||||
|
return( false );
|
||||||
|
}
|
||||||
|
if ( verbose )
|
||||||
|
{
|
||||||
|
sprintf( output+strlen(output), " Current: %d x %d\n", crop.c.width, crop.c.height );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//sprintf( output+strlen(output), "D:%s ", vid_cap.driver );
|
||||||
|
//sprintf( output+strlen(output), "C:%s ", vid_cap.card );
|
||||||
|
//sprintf( output+strlen(output), "B:%s ", vid_cap.bus_info );
|
||||||
|
//sprintf( output+strlen(output), "V:%u.%u.%u ", (vid_cap.version>>16)&0xff, (vid_cap.version>>8)&0xff, vid_cap.version&0xff );
|
||||||
|
//sprintf( output+strlen(output), "T:0x%x ", vid_cap.capabilities );
|
||||||
|
}
|
||||||
|
|
||||||
|
struct v4l2_input input;
|
||||||
|
int inputIndex = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
memset( &input, 0, sizeof(input) );
|
||||||
|
input.index = inputIndex;
|
||||||
|
|
||||||
|
if ( vidioctl( vid_fd, VIDIOC_ENUMINPUT, &input ) < 0 )
|
||||||
|
{
|
||||||
|
if ( errno == EINVAL )
|
||||||
|
{
|
||||||
|
inputIndex = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Error( "Failed to enumerate input %d: %s", input.index, strerror(errno) );
|
||||||
|
if ( verbose )
|
||||||
|
sprintf( output, "Error, failed to enumerate input %d: %s\n", input.index, strerror(errno) );
|
||||||
|
else
|
||||||
|
sprintf( output, "error%d\n", errno );
|
||||||
|
return( false );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( false )
|
||||||
|
if ( vidioctl( vid_fd, VIDIOC_S_INPUT, &input.index ) < 0 )
|
||||||
|
{
|
||||||
|
Error( "Failed to set video input %d: %s", input.index, strerror(errno) );
|
||||||
|
if ( verbose )
|
||||||
|
sprintf( output, "Error, failed to switch to input %d: %s\n", input.index, strerror(errno) );
|
||||||
|
else
|
||||||
|
sprintf( output, "error%d\n", errno );
|
||||||
|
return( false );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( verbose )
|
||||||
|
{
|
||||||
|
sprintf( output+strlen(output), "Input %d\n", input.index );
|
||||||
|
sprintf( output+strlen(output), " Name: %s\n", input.name );
|
||||||
|
sprintf( output+strlen(output), " Type: %s\n", input.type==V4L2_INPUT_TYPE_TUNER?"Tuner":(input.type==V4L2_INPUT_TYPE_CAMERA?"Camera":"Unknown") );
|
||||||
|
sprintf( output+strlen(output), " Audioset: %08x\n", input.audioset );
|
||||||
|
sprintf( output+strlen(output), " Standards: 0x%llx\n", input.std );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sprintf( output+strlen(output), "i%d:%s ", input.index, input.name );
|
||||||
|
sprintf( output+strlen(output), "i%dT:%s ", input.index, input.type==V4L2_INPUT_TYPE_TUNER?"Tuner":(input.type==V4L2_INPUT_TYPE_CAMERA?"Camera":"Unknown") );
|
||||||
|
sprintf( output+strlen(output), "i%dS:%llx ", input.index, input.std );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( verbose )
|
||||||
|
{
|
||||||
|
sprintf( output+strlen(output), " %s", capString( input.status&V4L2_IN_ST_NO_POWER, "Power ", "off", "on", " (X)" ) );
|
||||||
|
sprintf( output+strlen(output), " %s", capString( input.status&V4L2_IN_ST_NO_SIGNAL, "Signal ", "not detected", "detected", " (X)" ) );
|
||||||
|
sprintf( output+strlen(output), " %s", capString( input.status&V4L2_IN_ST_NO_COLOR, "Colour Signal ", "not detected", "detected", "" ) );
|
||||||
|
sprintf( output+strlen(output), " %s", capString( input.status&V4L2_IN_ST_NO_H_LOCK, "Horizontal Lock ", "not detected", "detected", "" ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sprintf( output+strlen(output), "i%dSP:%d ", input.index, input.status&V4L2_IN_ST_NO_POWER?0:1 );
|
||||||
|
sprintf( output+strlen(output), "i%dSS:%d ", input.index, input.status&V4L2_IN_ST_NO_SIGNAL?0:1 );
|
||||||
|
sprintf( output+strlen(output), "i%dSC:%d ", input.index, input.status&V4L2_IN_ST_NO_COLOR?0:1 );
|
||||||
|
sprintf( output+strlen(output), "i%dHP:%d ", input.index, input.status&V4L2_IN_ST_NO_H_LOCK?0:1 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while ( inputIndex++ >= 0 );
|
||||||
|
if ( !verbose )
|
||||||
|
output[strlen(output)-1] = '\n';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif // ZM_V4L2
|
||||||
|
{
|
||||||
struct video_capability vid_cap;
|
struct video_capability vid_cap;
|
||||||
if ( ioctl( vid_fd, VIDIOCGCAP, &vid_cap ) < 0 )
|
if ( ioctl( vid_fd, VIDIOCGCAP, &vid_cap ) < 0 )
|
||||||
{
|
{
|
||||||
|
@ -899,6 +1136,7 @@ bool LocalCamera::GetCurrentSettings( const char *device, char *output, bool ver
|
||||||
sprintf( output+strlen(output), "F%d:%d%s,", chan, vid_src.norm, chan==(vid_cap.channels-1)?"":"," );
|
sprintf( output+strlen(output), "F%d:%d%s,", chan, vid_src.norm, chan==(vid_cap.channels-1)?"":"," );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return( true );
|
return( true );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1597,7 +1835,7 @@ int LocalCamera::PostCapture()
|
||||||
Debug( 3, "Switching video source to %d", channels[next_channel] );
|
Debug( 3, "Switching video source to %d", channels[next_channel] );
|
||||||
if ( vidioctl( vid_fd, VIDIOC_S_INPUT, &channels[next_channel] ) < 0 )
|
if ( vidioctl( vid_fd, VIDIOC_S_INPUT, &channels[next_channel] ) < 0 )
|
||||||
{
|
{
|
||||||
Error( "Failed to set camera source %d: %s", channel, strerror(errno) );
|
Error( "Failed to set camera source %d: %s", channels[next_channel], strerror(errno) );
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue