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:
stan 2009-03-30 15:27:15 +00:00
parent 3310ea3ae9
commit 41c2889df2
1 changed files with 406 additions and 168 deletions

View File

@ -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;
@ -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 );
} }