Spacing, remove tests for v4l2, move control setting/getting code to a single function.
This commit is contained in:
parent
1f04723f3a
commit
75a014321e
|
@ -259,12 +259,12 @@ LocalCamera::LocalCamera(
|
|||
v4l_multi_buffer = p_v4l_multi_buffer;
|
||||
v4l_captures_per_frame = p_v4l_captures_per_frame;
|
||||
|
||||
if ( capture ) {
|
||||
if ( device_prime ) {
|
||||
if (capture) {
|
||||
if (device_prime) {
|
||||
Debug(2, "V4L support enabled, using V4L%d api", v4l_version);
|
||||
}
|
||||
|
||||
if ( (!last_camera) || (channel != last_camera->channel) ) {
|
||||
if ((!last_camera) || (channel != last_camera->channel)) {
|
||||
// We are the first, or only, input that uses this channel
|
||||
channel_prime = true;
|
||||
channel_index = channel_count++;
|
||||
|
@ -278,10 +278,10 @@ LocalCamera::LocalCamera(
|
|||
|
||||
/* The V4L1 API doesn't care about endianness, we need to check the endianness of the machine */
|
||||
uint32_t checkval = 0xAABBCCDD;
|
||||
if ( *(unsigned char*)&checkval == 0xDD ) {
|
||||
if (*(unsigned char*)&checkval == 0xDD) {
|
||||
BigEndian = 0;
|
||||
Debug(2, "little-endian processor detected");
|
||||
} else if ( *(unsigned char*)&checkval == 0xAA ) {
|
||||
} else if (*(unsigned char*)&checkval == 0xAA) {
|
||||
BigEndian = 1;
|
||||
Debug(2, "Big-endian processor detected");
|
||||
} else {
|
||||
|
@ -289,15 +289,15 @@ LocalCamera::LocalCamera(
|
|||
BigEndian = 0;
|
||||
}
|
||||
|
||||
if ( v4l_version == 2 && palette == 0 ) {
|
||||
if (v4l_version == 2 && palette == 0) {
|
||||
/* Use automatic format selection */
|
||||
Debug(2,"Using automatic format selection");
|
||||
palette = AutoSelectFormat(colours);
|
||||
if ( palette == 0 ) {
|
||||
if (palette == 0) {
|
||||
Error("Automatic format selection failed. Falling back to YUYV");
|
||||
palette = V4L2_PIX_FMT_YUYV;
|
||||
} else {
|
||||
if ( capture ) {
|
||||
if (capture) {
|
||||
Info("Selected capture palette: %s (0x%02hhx%02hhx%02hhx%02hhx)",
|
||||
palette_desc,
|
||||
static_cast<uint8>((palette >> 24) & 0xff),
|
||||
|
@ -328,130 +328,127 @@ LocalCamera::LocalCamera(
|
|||
imagePixFormat = AV_PIX_FMT_NONE;
|
||||
}
|
||||
|
||||
/* V4L2 format matching */
|
||||
if ( v4l_version == 2 ) {
|
||||
/* Try to find a match for the selected palette and target colourspace */
|
||||
/* Try to find a match for the selected palette and target colourspace */
|
||||
|
||||
/* RGB32 palette and 32bit target colourspace */
|
||||
if ( palette == V4L2_PIX_FMT_RGB32 && colours == ZM_COLOUR_RGB32 ) {
|
||||
conversion_type = 0;
|
||||
subpixelorder = ZM_SUBPIX_ORDER_ARGB;
|
||||
/* RGB32 palette and 32bit target colourspace */
|
||||
if (palette == V4L2_PIX_FMT_RGB32 && colours == ZM_COLOUR_RGB32) {
|
||||
conversion_type = 0;
|
||||
subpixelorder = ZM_SUBPIX_ORDER_ARGB;
|
||||
|
||||
/* BGR32 palette and 32bit target colourspace */
|
||||
} else if ( palette == V4L2_PIX_FMT_BGR32 && colours == ZM_COLOUR_RGB32 ) {
|
||||
conversion_type = 0;
|
||||
subpixelorder = ZM_SUBPIX_ORDER_BGRA;
|
||||
/* BGR32 palette and 32bit target colourspace */
|
||||
} else if (palette == V4L2_PIX_FMT_BGR32 && colours == ZM_COLOUR_RGB32) {
|
||||
conversion_type = 0;
|
||||
subpixelorder = ZM_SUBPIX_ORDER_BGRA;
|
||||
|
||||
/* RGB24 palette and 24bit target colourspace */
|
||||
} else if ( palette == V4L2_PIX_FMT_RGB24 && colours == ZM_COLOUR_RGB24 ) {
|
||||
conversion_type = 0;
|
||||
conversion_type = 0;
|
||||
subpixelorder = ZM_SUBPIX_ORDER_BGR;
|
||||
/* RGB24 palette and 24bit target colourspace */
|
||||
} else if (palette == V4L2_PIX_FMT_RGB24 && colours == ZM_COLOUR_RGB24) {
|
||||
conversion_type = 0;
|
||||
conversion_type = 0;
|
||||
subpixelorder = ZM_SUBPIX_ORDER_BGR;
|
||||
|
||||
/* Grayscale palette and grayscale target colourspace */
|
||||
} else if ( palette == V4L2_PIX_FMT_GREY && colours == ZM_COLOUR_GRAY8 ) {
|
||||
conversion_type = 0;
|
||||
/* Grayscale palette and grayscale target colourspace */
|
||||
} else if (palette == V4L2_PIX_FMT_GREY && colours == ZM_COLOUR_GRAY8) {
|
||||
conversion_type = 0;
|
||||
subpixelorder = ZM_SUBPIX_ORDER_NONE;
|
||||
/* Unable to find a solution for the selected palette and target colourspace. Conversion required. Notify the user of performance penalty */
|
||||
} else {
|
||||
if (capture) {
|
||||
Info(
|
||||
"No direct match for the selected palette (%d) and target colorspace (%02u). Format conversion is required, performance penalty expected",
|
||||
capturePixFormat,
|
||||
colours);
|
||||
}
|
||||
/* Try using swscale for the conversion */
|
||||
conversion_type = 1;
|
||||
Debug(2, "Using swscale for image conversion");
|
||||
if (colours == ZM_COLOUR_RGB32) {
|
||||
subpixelorder = ZM_SUBPIX_ORDER_RGBA;
|
||||
imagePixFormat = AV_PIX_FMT_RGBA;
|
||||
} else if (colours == ZM_COLOUR_RGB24) {
|
||||
subpixelorder = ZM_SUBPIX_ORDER_RGB;
|
||||
imagePixFormat = AV_PIX_FMT_RGB24;
|
||||
} else if (colours == ZM_COLOUR_GRAY8) {
|
||||
subpixelorder = ZM_SUBPIX_ORDER_NONE;
|
||||
/* Unable to find a solution for the selected palette and target colourspace. Conversion required. Notify the user of performance penalty */
|
||||
imagePixFormat = AV_PIX_FMT_GRAY8;
|
||||
} else {
|
||||
if ( capture ) {
|
||||
Info(
|
||||
"No direct match for the selected palette (%d) and target colorspace (%02u). Format conversion is required, performance penalty expected",
|
||||
capturePixFormat,
|
||||
colours);
|
||||
Panic("Unexpected colours: %u",colours);
|
||||
}
|
||||
if (capture) {
|
||||
if (!sws_isSupportedInput(capturePixFormat)) {
|
||||
Error("swscale does not support the used capture format: %d", capturePixFormat);
|
||||
conversion_type = 2; /* Try ZM format conversions */
|
||||
}
|
||||
/* Try using swscale for the conversion */
|
||||
conversion_type = 1;
|
||||
Debug(2, "Using swscale for image conversion");
|
||||
if ( colours == ZM_COLOUR_RGB32 ) {
|
||||
subpixelorder = ZM_SUBPIX_ORDER_RGBA;
|
||||
imagePixFormat = AV_PIX_FMT_RGBA;
|
||||
} else if ( colours == ZM_COLOUR_RGB24 ) {
|
||||
subpixelorder = ZM_SUBPIX_ORDER_RGB;
|
||||
imagePixFormat = AV_PIX_FMT_RGB24;
|
||||
} else if ( colours == ZM_COLOUR_GRAY8 ) {
|
||||
if (!sws_isSupportedOutput(imagePixFormat)) {
|
||||
Error("swscale does not support the target format: 0x%d", imagePixFormat);
|
||||
conversion_type = 2; /* Try ZM format conversions */
|
||||
}
|
||||
}
|
||||
/* Our YUYV->Grayscale conversion is a lot faster than swscale's */
|
||||
if (colours == ZM_COLOUR_GRAY8 && palette == V4L2_PIX_FMT_YUYV) {
|
||||
conversion_type = 2;
|
||||
}
|
||||
|
||||
/* JPEG */
|
||||
if (palette == V4L2_PIX_FMT_JPEG || palette == V4L2_PIX_FMT_MJPEG) {
|
||||
Debug(2,"Using JPEG image decoding");
|
||||
conversion_type = 3;
|
||||
}
|
||||
|
||||
if (conversion_type == 2) {
|
||||
Debug(2,"Using ZM for image conversion");
|
||||
if ( palette == V4L2_PIX_FMT_RGB32 && colours == ZM_COLOUR_GRAY8 ) {
|
||||
conversion_fptr = &std_convert_argb_gray8;
|
||||
subpixelorder = ZM_SUBPIX_ORDER_NONE;
|
||||
imagePixFormat = AV_PIX_FMT_GRAY8;
|
||||
} else {
|
||||
Panic("Unexpected colours: %u",colours);
|
||||
}
|
||||
if ( capture ) {
|
||||
if ( !sws_isSupportedInput(capturePixFormat) ) {
|
||||
Error("swscale does not support the used capture format: %d", capturePixFormat);
|
||||
conversion_type = 2; /* Try ZM format conversions */
|
||||
}
|
||||
if ( !sws_isSupportedOutput(imagePixFormat) ) {
|
||||
Error("swscale does not support the target format: 0x%d", imagePixFormat);
|
||||
conversion_type = 2; /* Try ZM format conversions */
|
||||
}
|
||||
}
|
||||
/* Our YUYV->Grayscale conversion is a lot faster than swscale's */
|
||||
if ( colours == ZM_COLOUR_GRAY8 && palette == V4L2_PIX_FMT_YUYV ) {
|
||||
conversion_type = 2;
|
||||
}
|
||||
|
||||
/* JPEG */
|
||||
if ( palette == V4L2_PIX_FMT_JPEG || palette == V4L2_PIX_FMT_MJPEG ) {
|
||||
Debug(2,"Using JPEG image decoding");
|
||||
conversion_type = 3;
|
||||
}
|
||||
|
||||
if ( conversion_type == 2 ) {
|
||||
Debug(2,"Using ZM for image conversion");
|
||||
if ( palette == V4L2_PIX_FMT_RGB32 && colours == ZM_COLOUR_GRAY8 ) {
|
||||
conversion_fptr = &std_convert_argb_gray8;
|
||||
subpixelorder = ZM_SUBPIX_ORDER_NONE;
|
||||
} else if ( palette == V4L2_PIX_FMT_BGR32 && colours == ZM_COLOUR_GRAY8 ) {
|
||||
conversion_fptr = &std_convert_bgra_gray8;
|
||||
subpixelorder = ZM_SUBPIX_ORDER_NONE;
|
||||
} else if ( palette == V4L2_PIX_FMT_YUYV && colours == ZM_COLOUR_GRAY8 ) {
|
||||
/* Fast YUYV->Grayscale conversion by extracting the Y channel */
|
||||
if ( config.cpu_extensions && sse_version >= 35 ) {
|
||||
conversion_fptr = &ssse3_convert_yuyv_gray8;
|
||||
Debug(2,"Using SSSE3 YUYV->grayscale fast conversion");
|
||||
} else {
|
||||
conversion_fptr = &std_convert_yuyv_gray8;
|
||||
Debug(2,"Using standard YUYV->grayscale fast conversion");
|
||||
}
|
||||
subpixelorder = ZM_SUBPIX_ORDER_NONE;
|
||||
} else if ( palette == V4L2_PIX_FMT_YUYV && colours == ZM_COLOUR_RGB24 ) {
|
||||
conversion_fptr = &zm_convert_yuyv_rgb;
|
||||
subpixelorder = ZM_SUBPIX_ORDER_RGB;
|
||||
} else if ( palette == V4L2_PIX_FMT_YUYV && colours == ZM_COLOUR_RGB32 ) {
|
||||
conversion_fptr = &zm_convert_yuyv_rgba;
|
||||
subpixelorder = ZM_SUBPIX_ORDER_RGBA;
|
||||
} else if ( palette == V4L2_PIX_FMT_RGB555 && colours == ZM_COLOUR_RGB24 ) {
|
||||
conversion_fptr = &zm_convert_rgb555_rgb;
|
||||
subpixelorder = ZM_SUBPIX_ORDER_RGB;
|
||||
} else if ( palette == V4L2_PIX_FMT_RGB555 && colours == ZM_COLOUR_RGB32 ) {
|
||||
conversion_fptr = &zm_convert_rgb555_rgba;
|
||||
subpixelorder = ZM_SUBPIX_ORDER_RGBA;
|
||||
} else if ( palette == V4L2_PIX_FMT_RGB565 && colours == ZM_COLOUR_RGB24 ) {
|
||||
conversion_fptr = &zm_convert_rgb565_rgb;
|
||||
subpixelorder = ZM_SUBPIX_ORDER_RGB;
|
||||
} else if ( palette == V4L2_PIX_FMT_RGB565 && colours == ZM_COLOUR_RGB32 ) {
|
||||
conversion_fptr = &zm_convert_rgb565_rgba;
|
||||
subpixelorder = ZM_SUBPIX_ORDER_RGBA;
|
||||
} else if (palette == V4L2_PIX_FMT_BGR32 && colours == ZM_COLOUR_GRAY8) {
|
||||
conversion_fptr = &std_convert_bgra_gray8;
|
||||
subpixelorder = ZM_SUBPIX_ORDER_NONE;
|
||||
} else if (palette == V4L2_PIX_FMT_YUYV && colours == ZM_COLOUR_GRAY8) {
|
||||
/* Fast YUYV->Grayscale conversion by extracting the Y channel */
|
||||
if (config.cpu_extensions && sse_version >= 35) {
|
||||
conversion_fptr = &ssse3_convert_yuyv_gray8;
|
||||
Debug(2,"Using SSSE3 YUYV->grayscale fast conversion");
|
||||
} else {
|
||||
Fatal("Unable to find a suitable format conversion for the selected palette and target colorspace.");
|
||||
conversion_fptr = &std_convert_yuyv_gray8;
|
||||
Debug(2,"Using standard YUYV->grayscale fast conversion");
|
||||
}
|
||||
} // end if conversion_type == 2
|
||||
} // end if needs conversion
|
||||
} // end if v4l2
|
||||
subpixelorder = ZM_SUBPIX_ORDER_NONE;
|
||||
} else if (palette == V4L2_PIX_FMT_YUYV && colours == ZM_COLOUR_RGB24) {
|
||||
conversion_fptr = &zm_convert_yuyv_rgb;
|
||||
subpixelorder = ZM_SUBPIX_ORDER_RGB;
|
||||
} else if (palette == V4L2_PIX_FMT_YUYV && colours == ZM_COLOUR_RGB32) {
|
||||
conversion_fptr = &zm_convert_yuyv_rgba;
|
||||
subpixelorder = ZM_SUBPIX_ORDER_RGBA;
|
||||
} else if (palette == V4L2_PIX_FMT_RGB555 && colours == ZM_COLOUR_RGB24) {
|
||||
conversion_fptr = &zm_convert_rgb555_rgb;
|
||||
subpixelorder = ZM_SUBPIX_ORDER_RGB;
|
||||
} else if (palette == V4L2_PIX_FMT_RGB555 && colours == ZM_COLOUR_RGB32) {
|
||||
conversion_fptr = &zm_convert_rgb555_rgba;
|
||||
subpixelorder = ZM_SUBPIX_ORDER_RGBA;
|
||||
} else if (palette == V4L2_PIX_FMT_RGB565 && colours == ZM_COLOUR_RGB24) {
|
||||
conversion_fptr = &zm_convert_rgb565_rgb;
|
||||
subpixelorder = ZM_SUBPIX_ORDER_RGB;
|
||||
} else if (palette == V4L2_PIX_FMT_RGB565 && colours == ZM_COLOUR_RGB32) {
|
||||
conversion_fptr = &zm_convert_rgb565_rgba;
|
||||
subpixelorder = ZM_SUBPIX_ORDER_RGBA;
|
||||
} else {
|
||||
Fatal("Unable to find a suitable format conversion for the selected palette and target colorspace.");
|
||||
}
|
||||
} // end if conversion_type == 2
|
||||
} // end if needs conversion
|
||||
|
||||
last_camera = this;
|
||||
Debug(3, "Selected subpixelorder: %u", subpixelorder);
|
||||
|
||||
/* Initialize swscale stuff */
|
||||
if ( capture and (conversion_type == 1) ) {
|
||||
if (capture and (conversion_type == 1)) {
|
||||
tmpPicture = av_frame_alloc();
|
||||
|
||||
if ( !tmpPicture )
|
||||
if (!tmpPicture)
|
||||
Fatal("Could not allocate temporary picture");
|
||||
|
||||
unsigned int pSize = av_image_get_buffer_size(imagePixFormat, width, height, 1);
|
||||
|
||||
if ( pSize != imagesize ) {
|
||||
if (pSize != imagesize) {
|
||||
Fatal("Image size mismatch. Required: %d Available: %llu", pSize, imagesize);
|
||||
}
|
||||
|
||||
|
@ -460,23 +457,23 @@ LocalCamera::LocalCamera(
|
|||
width, height, imagePixFormat, SWS_BICUBIC,
|
||||
nullptr, nullptr, nullptr);
|
||||
|
||||
if ( !imgConversionContext ) {
|
||||
if (!imgConversionContext) {
|
||||
Fatal("Unable to initialise image scaling context");
|
||||
}
|
||||
} else {
|
||||
tmpPicture = nullptr;
|
||||
imgConversionContext = nullptr;
|
||||
} // end if capture and conversion_tye == swscale
|
||||
if ( capture and device_prime )
|
||||
if (capture and device_prime)
|
||||
Initialise();
|
||||
} // end LocalCamera::LocalCamera
|
||||
|
||||
LocalCamera::~LocalCamera() {
|
||||
if ( device_prime && capture )
|
||||
if (device_prime && capture)
|
||||
Terminate();
|
||||
|
||||
/* Clean up swscale stuff */
|
||||
if ( capture && (conversion_type == 1) ) {
|
||||
if (capture && (conversion_type == 1)) {
|
||||
sws_freeContext(imgConversionContext);
|
||||
imgConversionContext = nullptr;
|
||||
|
||||
|
@ -492,251 +489,248 @@ int LocalCamera::Close() {
|
|||
|
||||
void LocalCamera::Initialise() {
|
||||
Debug(3, "Opening video device %s", device.c_str());
|
||||
//if ( (vid_fd = open( device.c_str(), O_RDWR|O_NONBLOCK, 0 )) < 0 )
|
||||
if ( (vid_fd = open(device.c_str(), O_RDWR, 0)) < 0 )
|
||||
if ((vid_fd = open(device.c_str(), O_RDWR, 0)) < 0)
|
||||
Fatal("Failed to open video device %s: %s", device.c_str(), strerror(errno));
|
||||
|
||||
struct stat st;
|
||||
if ( stat(device.c_str(), &st) < 0 )
|
||||
if (stat(device.c_str(), &st) < 0)
|
||||
Fatal("Failed to stat video device %s: %s", device.c_str(), strerror(errno));
|
||||
|
||||
if ( !S_ISCHR(st.st_mode) )
|
||||
if (!S_ISCHR(st.st_mode))
|
||||
Fatal("File %s is not device file: %s", device.c_str(), strerror(errno));
|
||||
|
||||
Debug(2, "V4L2 support enabled, using V4L%d api", v4l_version);
|
||||
if ( v4l_version == 2 ) {
|
||||
struct v4l2_capability vid_cap;
|
||||
struct v4l2_capability vid_cap;
|
||||
|
||||
Debug(3, "Checking video device capabilities");
|
||||
if ( vidioctl(vid_fd, VIDIOC_QUERYCAP, &vid_cap) < 0 )
|
||||
Fatal("Failed to query video device: %s", strerror(errno));
|
||||
Debug(3, "Checking video device capabilities");
|
||||
if ( vidioctl(vid_fd, VIDIOC_QUERYCAP, &vid_cap) < 0 )
|
||||
Fatal("Failed to query video device: %s", strerror(errno));
|
||||
|
||||
if ( !(vid_cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) )
|
||||
Fatal("Video device is not video capture device");
|
||||
if ( !(vid_cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) )
|
||||
Fatal("Video device is not video capture device");
|
||||
|
||||
if ( !(vid_cap.capabilities & V4L2_CAP_STREAMING) )
|
||||
Fatal("Video device does not support streaming i/o");
|
||||
if ( !(vid_cap.capabilities & V4L2_CAP_STREAMING) )
|
||||
Fatal("Video device does not support streaming i/o");
|
||||
|
||||
Debug(3, "Setting up video format");
|
||||
Debug(3, "Setting up video format");
|
||||
|
||||
memset(&v4l2_data.fmt, 0, sizeof(v4l2_data.fmt));
|
||||
v4l2_data.fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
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));
|
||||
if ( vidioctl( vid_fd, VIDIOC_G_FMT, &v4l2_data.fmt ) < 0 )
|
||||
Fatal("Failed to get video format: %s", strerror(errno));
|
||||
|
||||
Debug(4,
|
||||
" v4l2_data.fmt.type = %08x\n"
|
||||
" v4l2_data.fmt.fmt.pix.width = %d\n"
|
||||
" v4l2_data.fmt.fmt.pix.height = %d\n"
|
||||
" v4l2_data.fmt.fmt.pix.pixelformat = %08x\n"
|
||||
" v4l2_data.fmt.fmt.pix.field = %08x\n"
|
||||
" v4l2_data.fmt.fmt.pix.bytesperline = %d\n"
|
||||
" v4l2_data.fmt.fmt.pix.sizeimage = %d\n"
|
||||
" v4l2_data.fmt.fmt.pix.colorspace = %08x\n"
|
||||
" v4l2_data.fmt.fmt.pix.priv = %08x\n"
|
||||
, v4l2_data.fmt.type
|
||||
, v4l2_data.fmt.fmt.pix.width
|
||||
, v4l2_data.fmt.fmt.pix.height
|
||||
, v4l2_data.fmt.fmt.pix.pixelformat
|
||||
, v4l2_data.fmt.fmt.pix.field
|
||||
, v4l2_data.fmt.fmt.pix.bytesperline
|
||||
, v4l2_data.fmt.fmt.pix.sizeimage
|
||||
, v4l2_data.fmt.fmt.pix.colorspace
|
||||
, v4l2_data.fmt.fmt.pix.priv
|
||||
);
|
||||
Debug(4,
|
||||
" v4l2_data.fmt.type = %08x\n"
|
||||
" v4l2_data.fmt.fmt.pix.width = %d\n"
|
||||
" v4l2_data.fmt.fmt.pix.height = %d\n"
|
||||
" v4l2_data.fmt.fmt.pix.pixelformat = %08x\n"
|
||||
" v4l2_data.fmt.fmt.pix.field = %08x\n"
|
||||
" v4l2_data.fmt.fmt.pix.bytesperline = %d\n"
|
||||
" v4l2_data.fmt.fmt.pix.sizeimage = %d\n"
|
||||
" v4l2_data.fmt.fmt.pix.colorspace = %08x\n"
|
||||
" v4l2_data.fmt.fmt.pix.priv = %08x\n"
|
||||
, v4l2_data.fmt.type
|
||||
, v4l2_data.fmt.fmt.pix.width
|
||||
, v4l2_data.fmt.fmt.pix.height
|
||||
, v4l2_data.fmt.fmt.pix.pixelformat
|
||||
, v4l2_data.fmt.fmt.pix.field
|
||||
, v4l2_data.fmt.fmt.pix.bytesperline
|
||||
, v4l2_data.fmt.fmt.pix.sizeimage
|
||||
, v4l2_data.fmt.fmt.pix.colorspace
|
||||
, v4l2_data.fmt.fmt.pix.priv
|
||||
);
|
||||
|
||||
v4l2_data.fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
v4l2_data.fmt.fmt.pix.width = width;
|
||||
v4l2_data.fmt.fmt.pix.height = height;
|
||||
v4l2_data.fmt.fmt.pix.pixelformat = palette;
|
||||
v4l2_data.fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
v4l2_data.fmt.fmt.pix.width = width;
|
||||
v4l2_data.fmt.fmt.pix.height = height;
|
||||
v4l2_data.fmt.fmt.pix.pixelformat = palette;
|
||||
|
||||
if ( (extras & 0xff) != 0 ) {
|
||||
v4l2_data.fmt.fmt.pix.field = (v4l2_field)(extras & 0xff);
|
||||
if ((extras & 0xff) != 0) {
|
||||
v4l2_data.fmt.fmt.pix.field = (v4l2_field)(extras & 0xff);
|
||||
|
||||
if ( vidioctl(vid_fd, VIDIOC_S_FMT, &v4l2_data.fmt) < 0 ) {
|
||||
Warning("Failed to set V4L2 field to %d, falling back to auto", (extras & 0xff));
|
||||
v4l2_data.fmt.fmt.pix.field = V4L2_FIELD_ANY;
|
||||
if ( vidioctl(vid_fd, VIDIOC_S_FMT, &v4l2_data.fmt) < 0 ) {
|
||||
Fatal("Failed to set video format: %s", strerror(errno));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ( vidioctl(vid_fd, VIDIOC_S_FMT, &v4l2_data.fmt) < 0 ) {
|
||||
Error("Failed to set video format: %s", strerror(errno));
|
||||
if (vidioctl(vid_fd, VIDIOC_S_FMT, &v4l2_data.fmt) < 0) {
|
||||
Warning("Failed to set V4L2 field to %d, falling back to auto", (extras & 0xff));
|
||||
v4l2_data.fmt.fmt.pix.field = V4L2_FIELD_ANY;
|
||||
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. */
|
||||
Debug(4,
|
||||
" v4l2_data.fmt.type = %08x\n"
|
||||
" v4l2_data.fmt.fmt.pix.width = %d\n"
|
||||
" v4l2_data.fmt.fmt.pix.height = %d\n"
|
||||
" v4l2_data.fmt.fmt.pix.pixelformat = %08x\n"
|
||||
" v4l2_data.fmt.fmt.pix.field = %08x\n"
|
||||
" v4l2_data.fmt.fmt.pix.bytesperline = %d\n"
|
||||
" v4l2_data.fmt.fmt.pix.sizeimage = %d\n"
|
||||
" v4l2_data.fmt.fmt.pix.colorspace = %08x\n"
|
||||
" v4l2_data.fmt.fmt.pix.priv = %08x\n"
|
||||
, v4l2_data.fmt.type
|
||||
, v4l2_data.fmt.fmt.pix.width
|
||||
, v4l2_data.fmt.fmt.pix.height
|
||||
, v4l2_data.fmt.fmt.pix.pixelformat
|
||||
, v4l2_data.fmt.fmt.pix.field
|
||||
, v4l2_data.fmt.fmt.pix.bytesperline
|
||||
, v4l2_data.fmt.fmt.pix.sizeimage
|
||||
, v4l2_data.fmt.fmt.pix.colorspace
|
||||
, v4l2_data.fmt.fmt.pix.priv
|
||||
);
|
||||
|
||||
if ( v4l2_data.fmt.fmt.pix.width != width ) {
|
||||
Warning("Failed to set requested width");
|
||||
}
|
||||
if ( v4l2_data.fmt.fmt.pix.height != height ) {
|
||||
Warning("Failed to set requested height");
|
||||
} else {
|
||||
if (vidioctl(vid_fd, VIDIOC_S_FMT, &v4l2_data.fmt) < 0) {
|
||||
Error("Failed to set video format: %s", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
/* Buggy driver paranoia. */
|
||||
unsigned int min;
|
||||
min = v4l2_data.fmt.fmt.pix.width * 2;
|
||||
if ( v4l2_data.fmt.fmt.pix.bytesperline < min )
|
||||
v4l2_data.fmt.fmt.pix.bytesperline = min;
|
||||
min = v4l2_data.fmt.fmt.pix.bytesperline * v4l2_data.fmt.fmt.pix.height;
|
||||
if ( v4l2_data.fmt.fmt.pix.sizeimage < min )
|
||||
v4l2_data.fmt.fmt.pix.sizeimage = min;
|
||||
/* Note VIDIOC_S_FMT may change width and height. */
|
||||
Debug(4,
|
||||
" v4l2_data.fmt.type = %08x\n"
|
||||
" v4l2_data.fmt.fmt.pix.width = %d\n"
|
||||
" v4l2_data.fmt.fmt.pix.height = %d\n"
|
||||
" v4l2_data.fmt.fmt.pix.pixelformat = %08x\n"
|
||||
" v4l2_data.fmt.fmt.pix.field = %08x\n"
|
||||
" v4l2_data.fmt.fmt.pix.bytesperline = %d\n"
|
||||
" v4l2_data.fmt.fmt.pix.sizeimage = %d\n"
|
||||
" v4l2_data.fmt.fmt.pix.colorspace = %08x\n"
|
||||
" v4l2_data.fmt.fmt.pix.priv = %08x\n"
|
||||
, v4l2_data.fmt.type
|
||||
, v4l2_data.fmt.fmt.pix.width
|
||||
, v4l2_data.fmt.fmt.pix.height
|
||||
, v4l2_data.fmt.fmt.pix.pixelformat
|
||||
, v4l2_data.fmt.fmt.pix.field
|
||||
, v4l2_data.fmt.fmt.pix.bytesperline
|
||||
, v4l2_data.fmt.fmt.pix.sizeimage
|
||||
, v4l2_data.fmt.fmt.pix.colorspace
|
||||
, v4l2_data.fmt.fmt.pix.priv
|
||||
);
|
||||
|
||||
if ( palette == V4L2_PIX_FMT_JPEG || palette == V4L2_PIX_FMT_MJPEG ) {
|
||||
v4l2_jpegcompression jpeg_comp;
|
||||
if ( vidioctl(vid_fd, VIDIOC_G_JPEGCOMP, &jpeg_comp) < 0 ) {
|
||||
if ( errno == EINVAL ) {
|
||||
Debug(2, "JPEG compression options are not available");
|
||||
} else {
|
||||
Warning("Failed to get JPEG compression options: %s", strerror(errno));
|
||||
}
|
||||
if (v4l2_data.fmt.fmt.pix.width != width) {
|
||||
Warning("Failed to set requested width");
|
||||
}
|
||||
if (v4l2_data.fmt.fmt.pix.height != height) {
|
||||
Warning("Failed to set requested height");
|
||||
}
|
||||
|
||||
/* Buggy driver paranoia. */
|
||||
unsigned int min;
|
||||
min = v4l2_data.fmt.fmt.pix.width * 2;
|
||||
if (v4l2_data.fmt.fmt.pix.bytesperline < min)
|
||||
v4l2_data.fmt.fmt.pix.bytesperline = min;
|
||||
min = v4l2_data.fmt.fmt.pix.bytesperline * v4l2_data.fmt.fmt.pix.height;
|
||||
if (v4l2_data.fmt.fmt.pix.sizeimage < min)
|
||||
v4l2_data.fmt.fmt.pix.sizeimage = min;
|
||||
|
||||
if (palette == V4L2_PIX_FMT_JPEG || palette == V4L2_PIX_FMT_MJPEG) {
|
||||
v4l2_jpegcompression jpeg_comp;
|
||||
if (vidioctl(vid_fd, VIDIOC_G_JPEGCOMP, &jpeg_comp) < 0) {
|
||||
if (errno == EINVAL) {
|
||||
Debug(2, "JPEG compression options are not available");
|
||||
} else {
|
||||
/* Set flags and quality. MJPEG should not have the huffman tables defined */
|
||||
if ( palette == V4L2_PIX_FMT_MJPEG ) {
|
||||
jpeg_comp.jpeg_markers |= V4L2_JPEG_MARKER_DQT | V4L2_JPEG_MARKER_DRI;
|
||||
} else {
|
||||
jpeg_comp.jpeg_markers |= V4L2_JPEG_MARKER_DQT | V4L2_JPEG_MARKER_DRI | V4L2_JPEG_MARKER_DHT;
|
||||
}
|
||||
jpeg_comp.quality = 85;
|
||||
|
||||
/* Update the JPEG options */
|
||||
if ( vidioctl(vid_fd, VIDIOC_S_JPEGCOMP, &jpeg_comp) < 0 ) {
|
||||
Warning("Failed to set JPEG compression options: %s", strerror(errno));
|
||||
} else {
|
||||
if ( vidioctl(vid_fd, VIDIOC_G_JPEGCOMP, &jpeg_comp) < 0 ) {
|
||||
Debug(3,"Failed to get updated JPEG compression options: %s", strerror(errno));
|
||||
} else {
|
||||
Debug(4, "JPEG quality: %d, markers: %#x",
|
||||
jpeg_comp.quality, jpeg_comp.jpeg_markers);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // end if JPEG/MJPEG
|
||||
|
||||
Debug(3, "Setting up request buffers");
|
||||
|
||||
memset(&v4l2_data.reqbufs, 0, sizeof(v4l2_data.reqbufs));
|
||||
if ( channel_count > 1 ) {
|
||||
Debug(3, "Channel count is %d", channel_count);
|
||||
if ( v4l_multi_buffer ){
|
||||
v4l2_data.reqbufs.count = 2*channel_count;
|
||||
} else {
|
||||
v4l2_data.reqbufs.count = 1;
|
||||
Warning("Failed to get JPEG compression options: %s", strerror(errno));
|
||||
}
|
||||
} else {
|
||||
v4l2_data.reqbufs.count = 8;
|
||||
}
|
||||
Debug(3, "Request buffers count is %d", v4l2_data.reqbufs.count);
|
||||
|
||||
v4l2_data.reqbufs.type = v4l2_data.fmt.type;
|
||||
v4l2_data.reqbufs.memory = V4L2_MEMORY_MMAP;
|
||||
|
||||
if ( vidioctl(vid_fd, VIDIOC_REQBUFS, &v4l2_data.reqbufs) < 0 ) {
|
||||
if ( errno == EINVAL ) {
|
||||
Fatal("Unable to initialise memory mapping, unsupported in device");
|
||||
/* Set flags and quality. MJPEG should not have the huffman tables defined */
|
||||
if (palette == V4L2_PIX_FMT_MJPEG) {
|
||||
jpeg_comp.jpeg_markers |= V4L2_JPEG_MARKER_DQT | V4L2_JPEG_MARKER_DRI;
|
||||
} else {
|
||||
Fatal("Unable to initialise memory mapping: %s", strerror(errno));
|
||||
jpeg_comp.jpeg_markers |= V4L2_JPEG_MARKER_DQT | V4L2_JPEG_MARKER_DRI | V4L2_JPEG_MARKER_DHT;
|
||||
}
|
||||
jpeg_comp.quality = 85;
|
||||
|
||||
/* Update the JPEG options */
|
||||
if (vidioctl(vid_fd, VIDIOC_S_JPEGCOMP, &jpeg_comp) < 0) {
|
||||
Warning("Failed to set JPEG compression options: %s", strerror(errno));
|
||||
} else {
|
||||
if (vidioctl(vid_fd, VIDIOC_G_JPEGCOMP, &jpeg_comp) < 0) {
|
||||
Debug(3,"Failed to get updated JPEG compression options: %s", strerror(errno));
|
||||
} else {
|
||||
Debug(4, "JPEG quality: %d, markers: %#x",
|
||||
jpeg_comp.quality, jpeg_comp.jpeg_markers);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // end if JPEG/MJPEG
|
||||
|
||||
if ( v4l2_data.reqbufs.count < (v4l_multi_buffer?2:1) )
|
||||
Fatal("Insufficient buffer memory %d on video device", v4l2_data.reqbufs.count);
|
||||
Debug(3, "Setting up request buffers");
|
||||
|
||||
Debug(3, "Setting up data buffers: Channels %d MultiBuffer %d Buffers: %d",
|
||||
channel_count, v4l_multi_buffer, v4l2_data.reqbufs.count);
|
||||
|
||||
v4l2_data.buffers = new V4L2MappedBuffer[v4l2_data.reqbufs.count];
|
||||
capturePictures = new AVFrame *[v4l2_data.reqbufs.count];
|
||||
|
||||
for ( unsigned int i = 0; i < v4l2_data.reqbufs.count; i++ ) {
|
||||
struct v4l2_buffer vid_buf;
|
||||
|
||||
memset(&vid_buf, 0, sizeof(vid_buf));
|
||||
|
||||
//vid_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
vid_buf.type = v4l2_data.fmt.type;
|
||||
//vid_buf.memory = V4L2_MEMORY_MMAP;
|
||||
vid_buf.memory = v4l2_data.reqbufs.memory;
|
||||
vid_buf.index = i;
|
||||
|
||||
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;
|
||||
v4l2_data.buffers[i].start = mmap(nullptr, vid_buf.length, PROT_READ|PROT_WRITE, MAP_SHARED, vid_fd, vid_buf.m.offset);
|
||||
|
||||
if ( v4l2_data.buffers[i].start == MAP_FAILED )
|
||||
Fatal("Can't map video buffer %u (%u bytes) to memory: %s(%d)",
|
||||
i, vid_buf.length, strerror(errno), errno);
|
||||
|
||||
capturePictures[i] = av_frame_alloc();
|
||||
|
||||
if ( !capturePictures[i] )
|
||||
Fatal("Could not allocate picture");
|
||||
|
||||
av_image_fill_arrays(
|
||||
capturePictures[i]->data,
|
||||
capturePictures[i]->linesize,
|
||||
(uint8_t*)v4l2_data.buffers[i].start,
|
||||
capturePixFormat,
|
||||
v4l2_data.fmt.fmt.pix.width,
|
||||
v4l2_data.fmt.fmt.pix.height,
|
||||
1);
|
||||
} // end foreach request buf
|
||||
|
||||
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));
|
||||
memset(&v4l2_data.reqbufs, 0, sizeof(v4l2_data.reqbufs));
|
||||
if (channel_count > 1) {
|
||||
Debug(3, "Channel count is %d", channel_count);
|
||||
if (v4l_multi_buffer){
|
||||
v4l2_data.reqbufs.count = 2*channel_count;
|
||||
} else {
|
||||
v4l2_data.reqbufs.count = 1;
|
||||
}
|
||||
|
||||
struct v4l2_input input;
|
||||
v4l2_std_id stdId;
|
||||
|
||||
memset(&input, 0, sizeof(input));
|
||||
input.index = channel;
|
||||
|
||||
if ( vidioctl(vid_fd, VIDIOC_ENUMINPUT, &input) < 0 ) {
|
||||
Fatal("Failed to enumerate input %d: %s", channel, strerror(errno));
|
||||
}
|
||||
|
||||
if ( (input.std != V4L2_STD_UNKNOWN) && ((input.std & standard) == V4L2_STD_UNKNOWN) ) {
|
||||
Error("Device does not support video standard %d", standard);
|
||||
}
|
||||
|
||||
stdId = standard;
|
||||
if ((vidioctl(vid_fd, VIDIOC_S_STD, &stdId) < 0)) {
|
||||
Error("Failed to set video standard %d: %d %s", standard, errno, strerror(errno));
|
||||
}
|
||||
|
||||
Contrast(contrast);
|
||||
Brightness(brightness);
|
||||
Hue(hue);
|
||||
Colour(colour);
|
||||
} else {
|
||||
v4l2_data.reqbufs.count = 8;
|
||||
}
|
||||
Debug(3, "Request buffers count is %d", v4l2_data.reqbufs.count);
|
||||
|
||||
v4l2_data.reqbufs.type = v4l2_data.fmt.type;
|
||||
v4l2_data.reqbufs.memory = V4L2_MEMORY_MMAP;
|
||||
|
||||
if (vidioctl(vid_fd, VIDIOC_REQBUFS, &v4l2_data.reqbufs) < 0) {
|
||||
if (errno == EINVAL) {
|
||||
Fatal("Unable to initialise memory mapping, unsupported in device");
|
||||
} else {
|
||||
Fatal("Unable to initialise memory mapping: %s", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
if (v4l2_data.reqbufs.count < (v4l_multi_buffer?2:1))
|
||||
Fatal("Insufficient buffer memory %d on video device", v4l2_data.reqbufs.count);
|
||||
|
||||
Debug(3, "Setting up data buffers: Channels %d MultiBuffer %d Buffers: %d",
|
||||
channel_count, v4l_multi_buffer, v4l2_data.reqbufs.count);
|
||||
|
||||
v4l2_data.buffers = new V4L2MappedBuffer[v4l2_data.reqbufs.count];
|
||||
capturePictures = new AVFrame *[v4l2_data.reqbufs.count];
|
||||
|
||||
for (unsigned int i = 0; i < v4l2_data.reqbufs.count; i++) {
|
||||
struct v4l2_buffer vid_buf;
|
||||
|
||||
memset(&vid_buf, 0, sizeof(vid_buf));
|
||||
|
||||
//vid_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
vid_buf.type = v4l2_data.fmt.type;
|
||||
//vid_buf.memory = V4L2_MEMORY_MMAP;
|
||||
vid_buf.memory = v4l2_data.reqbufs.memory;
|
||||
vid_buf.index = i;
|
||||
|
||||
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;
|
||||
v4l2_data.buffers[i].start = mmap(nullptr, vid_buf.length, PROT_READ|PROT_WRITE, MAP_SHARED, vid_fd, vid_buf.m.offset);
|
||||
|
||||
if (v4l2_data.buffers[i].start == MAP_FAILED)
|
||||
Fatal("Can't map video buffer %u (%u bytes) to memory: %s(%d)",
|
||||
i, vid_buf.length, strerror(errno), errno);
|
||||
|
||||
capturePictures[i] = av_frame_alloc();
|
||||
|
||||
if (!capturePictures[i])
|
||||
Fatal("Could not allocate picture");
|
||||
|
||||
av_image_fill_arrays(
|
||||
capturePictures[i]->data,
|
||||
capturePictures[i]->linesize,
|
||||
(uint8_t*)v4l2_data.buffers[i].start,
|
||||
capturePixFormat,
|
||||
v4l2_data.fmt.fmt.pix.width,
|
||||
v4l2_data.fmt.fmt.pix.height,
|
||||
1);
|
||||
} // end foreach request buf
|
||||
|
||||
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));
|
||||
input.index = channel;
|
||||
|
||||
if (vidioctl(vid_fd, VIDIOC_ENUMINPUT, &input) < 0) {
|
||||
Fatal("Failed to enumerate input %d: %s", channel, strerror(errno));
|
||||
}
|
||||
|
||||
if ((input.std != V4L2_STD_UNKNOWN) && ((input.std & standard) == V4L2_STD_UNKNOWN)) {
|
||||
Error("Device does not support video standard %d", standard);
|
||||
}
|
||||
|
||||
stdId = standard;
|
||||
if ((vidioctl(vid_fd, VIDIOC_S_STD, &stdId) < 0)) {
|
||||
Error("Failed to set video standard %d: %d %s", standard, errno, strerror(errno));
|
||||
}
|
||||
|
||||
Contrast(contrast);
|
||||
Brightness(brightness);
|
||||
Hue(hue);
|
||||
Colour(colour);
|
||||
} // end LocalCamera::Initialize
|
||||
|
||||
void LocalCamera::Terminate() {
|
||||
|
@ -1170,126 +1164,47 @@ bool LocalCamera::GetCurrentSettings(
|
|||
return true;
|
||||
}
|
||||
|
||||
int LocalCamera::Brightness(int p_brightness) {
|
||||
if ( v4l_version == 2 ) {
|
||||
struct v4l2_control vid_control;
|
||||
int LocalCamera::Control(int vid_id, int newvalue) {
|
||||
struct v4l2_control vid_control;
|
||||
|
||||
memset(&vid_control, 0, sizeof(vid_control));
|
||||
vid_control.id = V4L2_CID_BRIGHTNESS;
|
||||
memset(&vid_control, 0, sizeof(vid_control));
|
||||
vid_control.id = vid_id;
|
||||
|
||||
if ( vidioctl(vid_fd, VIDIOC_G_CTRL, &vid_control) < 0 ) {
|
||||
if ( errno != EINVAL ) {
|
||||
Error("Unable to query brightness: %s", strerror(errno));
|
||||
} else {
|
||||
Warning("Brightness control is not supported");
|
||||
}
|
||||
//Info( "Brightness 1 %d", vid_control.value );
|
||||
} 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) ) {
|
||||
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 );
|
||||
if (vidioctl(vid_fd, VIDIOC_G_CTRL, &vid_control) < 0) {
|
||||
if (errno != EINVAL) {
|
||||
Error("Unable to query control: %s", strerror(errno));
|
||||
} else {
|
||||
Warning("Control is not supported");
|
||||
}
|
||||
} else if (newvalue >= 0) {
|
||||
vid_control.value = newvalue;
|
||||
|
||||
/* The driver may clamp the value or return ERANGE, ignored here */
|
||||
if ( vidioctl(vid_fd, VIDIOC_S_CTRL, &vid_control) ) {
|
||||
if (errno != ERANGE) {
|
||||
Error("Unable to set control: %s", strerror(errno));
|
||||
} else {
|
||||
Warning("Given control value (%d) may be out-of-range", newvalue);
|
||||
}
|
||||
}
|
||||
return vid_control.value;
|
||||
}
|
||||
return -1;
|
||||
return vid_control.value;
|
||||
}
|
||||
|
||||
int LocalCamera::Brightness(int p_brightness) {
|
||||
return Control(V4L2_CID_BRIGHTNESS, p_brightness);
|
||||
}
|
||||
|
||||
int LocalCamera::Hue(int p_hue) {
|
||||
if ( v4l_version == 2 ) {
|
||||
struct v4l2_control vid_control;
|
||||
|
||||
memset( &vid_control, 0, sizeof(vid_control) );
|
||||
vid_control.id = V4L2_CID_HUE;
|
||||
|
||||
if ( vidioctl(vid_fd, VIDIOC_G_CTRL, &vid_control) < 0 ) {
|
||||
if ( errno != EINVAL )
|
||||
Error("Unable to query hue: %s", strerror(errno));
|
||||
else
|
||||
Warning("Hue control is not supported");
|
||||
} else if ( p_hue >= 0 ) {
|
||||
vid_control.value = p_hue;
|
||||
|
||||
/* The driver may clamp the value or return ERANGE, ignored here */
|
||||
if ( vidioctl(vid_fd, VIDIOC_S_CTRL, &vid_control) < 0 ) {
|
||||
if ( errno != ERANGE ) {
|
||||
Error("Unable to set hue: %s", strerror(errno));
|
||||
} else {
|
||||
Warning("Given hue value (%d) may be out-of-range", p_hue);
|
||||
}
|
||||
}
|
||||
}
|
||||
return vid_control.value;
|
||||
}
|
||||
return -1;
|
||||
return Control(V4L2_CID_HUE, p_hue);
|
||||
}
|
||||
|
||||
int LocalCamera::Colour( int p_colour ) {
|
||||
if ( v4l_version == 2 ) {
|
||||
struct v4l2_control vid_control;
|
||||
|
||||
memset(&vid_control, 0, sizeof(vid_control));
|
||||
vid_control.id = V4L2_CID_SATURATION;
|
||||
|
||||
if ( vidioctl(vid_fd, VIDIOC_G_CTRL, &vid_control) < 0 ) {
|
||||
if ( errno != EINVAL ) {
|
||||
Error("Unable to query saturation: %s", strerror(errno));
|
||||
} else {
|
||||
Warning("Saturation control is not supported");
|
||||
}
|
||||
} else if ( p_colour >= 0 ) {
|
||||
vid_control.value = p_colour;
|
||||
|
||||
/* The driver may clamp the value or return ERANGE, ignored here */
|
||||
if ( vidioctl(vid_fd, VIDIOC_S_CTRL, &vid_control) < 0 ) {
|
||||
if ( errno != ERANGE ) {
|
||||
Error("Unable to set saturation: %s", strerror(errno));
|
||||
} else {
|
||||
Warning("Given saturation value (%d) may be out-of-range", p_colour);
|
||||
}
|
||||
}
|
||||
}
|
||||
return vid_control.value;
|
||||
}
|
||||
return -1;
|
||||
return Control(V4L2_CID_SATURATION, p_colour);
|
||||
}
|
||||
|
||||
int LocalCamera::Contrast( int p_contrast ) {
|
||||
if ( v4l_version == 2 ) {
|
||||
struct v4l2_control vid_control;
|
||||
|
||||
memset(&vid_control, 0, sizeof(vid_control));
|
||||
vid_control.id = V4L2_CID_CONTRAST;
|
||||
|
||||
if ( vidioctl(vid_fd, VIDIOC_G_CTRL, &vid_control) < 0 ) {
|
||||
if ( errno != EINVAL ) {
|
||||
Error("Unable to query contrast: %s", strerror(errno));
|
||||
} else {
|
||||
Warning("Contrast control is not supported");
|
||||
}
|
||||
} 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) ) {
|
||||
if ( errno != ERANGE ) {
|
||||
Error("Unable to set contrast: %s", strerror(errno));
|
||||
} else {
|
||||
Warning("Given contrast value (%d) may be out-of-range", p_contrast);
|
||||
}
|
||||
}
|
||||
}
|
||||
return vid_control.value;
|
||||
}
|
||||
return -1;
|
||||
int LocalCamera::Contrast(int p_contrast) {
|
||||
return Control(V4L2_CID_CONTRAST, p_contrast);
|
||||
}
|
||||
|
||||
int LocalCamera::PrimeCapture() {
|
||||
|
|
|
@ -113,6 +113,7 @@ public:
|
|||
int Palette() const { return palette; }
|
||||
int Extras() const { return extras; }
|
||||
|
||||
int Control(int vid_id, int newvalue=-1 );
|
||||
int Brightness( int p_brightness=-1 ) override;
|
||||
int Hue( int p_hue=-1 ) override;
|
||||
int Colour( int p_colour=-1 ) override;
|
||||
|
|
Loading…
Reference in New Issue