|
|
|
@ -49,7 +49,6 @@ static int vidioctl(int fd, int request, void *arg) {
|
|
|
|
|
static _AVPIXELFORMAT getFfPixFormatFromV4lPalette(int v4l_version, int palette) {
|
|
|
|
|
_AVPIXELFORMAT pixFormat = AV_PIX_FMT_NONE;
|
|
|
|
|
|
|
|
|
|
#if ZM_HAS_V4L2
|
|
|
|
|
if ( v4l_version == 2 ) {
|
|
|
|
|
switch ( palette ) {
|
|
|
|
|
#if defined(V4L2_PIX_FMT_RGB444) && defined(AV_PIX_FMT_RGB444)
|
|
|
|
@ -174,82 +173,11 @@ static _AVPIXELFORMAT getFfPixFormatFromV4lPalette(int v4l_version, int palette)
|
|
|
|
|
}
|
|
|
|
|
} // end switch palette
|
|
|
|
|
} // end if v4l2
|
|
|
|
|
#endif // ZM_HAS_V4L2
|
|
|
|
|
#if ZM_HAS_V4L1
|
|
|
|
|
if ( v4l_version == 1 ) {
|
|
|
|
|
switch( palette ) {
|
|
|
|
|
case VIDEO_PALETTE_RGB32 :
|
|
|
|
|
if ( BigEndian )
|
|
|
|
|
pixFormat = AV_PIX_FMT_ARGB;
|
|
|
|
|
else
|
|
|
|
|
pixFormat = AV_PIX_FMT_BGRA;
|
|
|
|
|
break;
|
|
|
|
|
case VIDEO_PALETTE_RGB24 :
|
|
|
|
|
if ( BigEndian )
|
|
|
|
|
pixFormat = AV_PIX_FMT_RGB24;
|
|
|
|
|
else
|
|
|
|
|
pixFormat = AV_PIX_FMT_BGR24;
|
|
|
|
|
break;
|
|
|
|
|
case VIDEO_PALETTE_GREY :
|
|
|
|
|
pixFormat = AV_PIX_FMT_GRAY8;
|
|
|
|
|
break;
|
|
|
|
|
case VIDEO_PALETTE_RGB555 :
|
|
|
|
|
pixFormat = AV_PIX_FMT_RGB555;
|
|
|
|
|
break;
|
|
|
|
|
case VIDEO_PALETTE_RGB565 :
|
|
|
|
|
pixFormat = AV_PIX_FMT_RGB565;
|
|
|
|
|
break;
|
|
|
|
|
case VIDEO_PALETTE_YUYV :
|
|
|
|
|
case VIDEO_PALETTE_YUV422 :
|
|
|
|
|
pixFormat = AV_PIX_FMT_YUYV422;
|
|
|
|
|
break;
|
|
|
|
|
case VIDEO_PALETTE_YUV422P :
|
|
|
|
|
pixFormat = AV_PIX_FMT_YUV422P;
|
|
|
|
|
break;
|
|
|
|
|
case VIDEO_PALETTE_YUV420P :
|
|
|
|
|
pixFormat = AV_PIX_FMT_YUV420P;
|
|
|
|
|
break;
|
|
|
|
|
default :
|
|
|
|
|
{
|
|
|
|
|
Fatal("Can't find swscale format for palette %d", palette);
|
|
|
|
|
break;
|
|
|
|
|
#if 0
|
|
|
|
|
// These are all spare and may match some of the above
|
|
|
|
|
pixFormat = AV_PIX_FMT_YUVJ420P;
|
|
|
|
|
pixFormat = AV_PIX_FMT_YUVJ422P;
|
|
|
|
|
pixFormat = AV_PIX_FMT_YUVJ444P;
|
|
|
|
|
pixFormat = AV_PIX_FMT_UYVY422;
|
|
|
|
|
pixFormat = AV_PIX_FMT_UYYVYY411;
|
|
|
|
|
pixFormat = AV_PIX_FMT_BGR565;
|
|
|
|
|
pixFormat = AV_PIX_FMT_BGR555;
|
|
|
|
|
pixFormat = AV_PIX_FMT_BGR8;
|
|
|
|
|
pixFormat = AV_PIX_FMT_BGR4;
|
|
|
|
|
pixFormat = AV_PIX_FMT_BGR4_BYTE;
|
|
|
|
|
pixFormat = AV_PIX_FMT_RGB8;
|
|
|
|
|
pixFormat = AV_PIX_FMT_RGB4;
|
|
|
|
|
pixFormat = AV_PIX_FMT_RGB4_BYTE;
|
|
|
|
|
pixFormat = AV_PIX_FMT_NV12;
|
|
|
|
|
pixFormat = AV_PIX_FMT_NV21;
|
|
|
|
|
pixFormat = AV_PIX_FMT_RGB32_1;
|
|
|
|
|
pixFormat = AV_PIX_FMT_BGR32_1;
|
|
|
|
|
pixFormat = AV_PIX_FMT_GRAY16BE;
|
|
|
|
|
pixFormat = AV_PIX_FMT_GRAY16LE;
|
|
|
|
|
pixFormat = AV_PIX_FMT_YUV440P;
|
|
|
|
|
pixFormat = AV_PIX_FMT_YUVJ440P;
|
|
|
|
|
pixFormat = AV_PIX_FMT_YUVA420P;
|
|
|
|
|
//pixFormat = AV_PIX_FMT_VDPAU_H264;
|
|
|
|
|
//pixFormat = AV_PIX_FMT_VDPAU_MPEG1;
|
|
|
|
|
//pixFormat = AV_PIX_FMT_VDPAU_MPEG2;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
} // end switch palette
|
|
|
|
|
} // end if v4l1
|
|
|
|
|
#endif // ZM_HAS_V4L1
|
|
|
|
|
|
|
|
|
|
return pixFormat;
|
|
|
|
|
} // end getFfPixFormatFromV4lPalette
|
|
|
|
|
#endif // HAVE_LIBSWSCALE
|
|
|
|
|
|
|
|
|
|
#if ZM_HAS_V4L2
|
|
|
|
|
static char palette_desc[32];
|
|
|
|
|
/* Automatic format selection preferred formats */
|
|
|
|
|
static const uint32_t prefered_rgb32_formats[] = {
|
|
|
|
@ -283,7 +211,6 @@ static const uint32_t prefered_gray8_formats[] = {
|
|
|
|
|
V4L2_PIX_FMT_YUV422P,
|
|
|
|
|
V4L2_PIX_FMT_YUV420
|
|
|
|
|
};
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
int LocalCamera::camera_count = 0;
|
|
|
|
|
int LocalCamera::channel_count = 0;
|
|
|
|
@ -293,12 +220,7 @@ int LocalCamera::standards[VIDEO_MAX_FRAME];
|
|
|
|
|
int LocalCamera::vid_fd = -1;
|
|
|
|
|
|
|
|
|
|
int LocalCamera::v4l_version = 0;
|
|
|
|
|
#if ZM_HAS_V4L2
|
|
|
|
|
LocalCamera::V4L2Data LocalCamera::v4l2_data;
|
|
|
|
|
#endif // ZM_HAS_V4L2
|
|
|
|
|
#if ZM_HAS_V4L1
|
|
|
|
|
LocalCamera::V4L1Data LocalCamera::v4l1_data;
|
|
|
|
|
#endif // ZM_HAS_V4L1
|
|
|
|
|
|
|
|
|
|
#if HAVE_LIBSWSCALE
|
|
|
|
|
AVFrame **LocalCamera::capturePictures = nullptr;
|
|
|
|
@ -370,7 +292,6 @@ LocalCamera::LocalCamera(
|
|
|
|
|
BigEndian = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if ZM_HAS_V4L2
|
|
|
|
|
if ( v4l_version == 2 && palette == 0 ) {
|
|
|
|
|
/* Use automatic format selection */
|
|
|
|
|
Debug(2,"Using automatic format selection");
|
|
|
|
@ -389,7 +310,6 @@ LocalCamera::LocalCamera(
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (capture) {
|
|
|
|
|
if (last_camera) {
|
|
|
|
@ -414,7 +334,6 @@ LocalCamera::LocalCamera(
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* V4L2 format matching */
|
|
|
|
|
#if ZM_HAS_V4L2
|
|
|
|
|
if ( v4l_version == 2 ) {
|
|
|
|
|
/* Try to find a match for the selected palette and target colourspace */
|
|
|
|
|
|
|
|
|
@ -535,119 +454,6 @@ LocalCamera::LocalCamera(
|
|
|
|
|
} // end if conversion_type == 2
|
|
|
|
|
} // end if needs conversion
|
|
|
|
|
} // end if v4l2
|
|
|
|
|
#endif // ZM_HAS_V4L2
|
|
|
|
|
|
|
|
|
|
/* V4L1 format matching */
|
|
|
|
|
#if ZM_HAS_V4L1
|
|
|
|
|
if ( v4l_version == 1 ) {
|
|
|
|
|
/* Try to find a match for the selected palette and target colourspace */
|
|
|
|
|
|
|
|
|
|
/* RGB32 palette and 32bit target colourspace */
|
|
|
|
|
if ( palette == VIDEO_PALETTE_RGB32 && colours == ZM_COLOUR_RGB32 ) {
|
|
|
|
|
conversion_type = 0;
|
|
|
|
|
if ( BigEndian ) {
|
|
|
|
|
subpixelorder = ZM_SUBPIX_ORDER_ARGB;
|
|
|
|
|
} else {
|
|
|
|
|
subpixelorder = ZM_SUBPIX_ORDER_BGRA;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* RGB24 palette and 24bit target colourspace */
|
|
|
|
|
} else if ( palette == VIDEO_PALETTE_RGB24 && colours == ZM_COLOUR_RGB24 ) {
|
|
|
|
|
conversion_type = 0;
|
|
|
|
|
if ( BigEndian ) {
|
|
|
|
|
subpixelorder = ZM_SUBPIX_ORDER_RGB;
|
|
|
|
|
} else {
|
|
|
|
|
subpixelorder = ZM_SUBPIX_ORDER_BGR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Grayscale palette and grayscale target colourspace */
|
|
|
|
|
} else if ( palette == VIDEO_PALETTE_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 and target colorspace. Format conversion is required, performance penalty expected");
|
|
|
|
|
#if HAVE_LIBSWSCALE
|
|
|
|
|
/* 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;
|
|
|
|
|
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");
|
|
|
|
|
conversion_type = 2; /* Try ZM format conversions */
|
|
|
|
|
}
|
|
|
|
|
if ( !sws_isSupportedOutput(imagePixFormat) ) {
|
|
|
|
|
Error("swscale does not support the target format");
|
|
|
|
|
conversion_type = 2; /* Try ZM format conversions */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Our YUYV->Grayscale conversion is a lot faster than swscale's */
|
|
|
|
|
if ( colours == ZM_COLOUR_GRAY8 && (palette == VIDEO_PALETTE_YUYV || palette == VIDEO_PALETTE_YUV422) ) {
|
|
|
|
|
conversion_type = 2;
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
/* Don't have swscale, see what we can do */
|
|
|
|
|
conversion_type = 2;
|
|
|
|
|
#endif
|
|
|
|
|
if ( conversion_type == 2 ) {
|
|
|
|
|
Debug(2,"Using ZM for image conversion");
|
|
|
|
|
if ( palette == VIDEO_PALETTE_RGB32 && colours == ZM_COLOUR_GRAY8 ) {
|
|
|
|
|
if ( BigEndian ) {
|
|
|
|
|
conversion_fptr = &std_convert_argb_gray8;
|
|
|
|
|
subpixelorder = ZM_SUBPIX_ORDER_NONE;
|
|
|
|
|
} else {
|
|
|
|
|
conversion_fptr = &std_convert_bgra_gray8;
|
|
|
|
|
subpixelorder = ZM_SUBPIX_ORDER_NONE;
|
|
|
|
|
}
|
|
|
|
|
} else if ( (palette == VIDEO_PALETTE_YUYV || palette == VIDEO_PALETTE_YUV422) && 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 == VIDEO_PALETTE_YUYV || palette == VIDEO_PALETTE_YUV422) && colours == ZM_COLOUR_RGB24 ) {
|
|
|
|
|
conversion_fptr = &zm_convert_yuyv_rgb;
|
|
|
|
|
subpixelorder = ZM_SUBPIX_ORDER_RGB;
|
|
|
|
|
} else if ( (palette == VIDEO_PALETTE_YUYV || palette == VIDEO_PALETTE_YUV422) && colours == ZM_COLOUR_RGB32 ) {
|
|
|
|
|
conversion_fptr = &zm_convert_yuyv_rgba;
|
|
|
|
|
subpixelorder = ZM_SUBPIX_ORDER_RGBA;
|
|
|
|
|
} else if ( palette == VIDEO_PALETTE_RGB555 && colours == ZM_COLOUR_RGB24 ) {
|
|
|
|
|
conversion_fptr = &zm_convert_rgb555_rgb;
|
|
|
|
|
subpixelorder = ZM_SUBPIX_ORDER_RGB;
|
|
|
|
|
} else if ( palette == VIDEO_PALETTE_RGB555 && colours == ZM_COLOUR_RGB32 ) {
|
|
|
|
|
conversion_fptr = &zm_convert_rgb555_rgba;
|
|
|
|
|
subpixelorder = ZM_SUBPIX_ORDER_RGBA;
|
|
|
|
|
} else if ( palette == VIDEO_PALETTE_RGB565 && colours == ZM_COLOUR_RGB24 ) {
|
|
|
|
|
conversion_fptr = &zm_convert_rgb565_rgb;
|
|
|
|
|
subpixelorder = ZM_SUBPIX_ORDER_RGB;
|
|
|
|
|
} else if ( palette == VIDEO_PALETTE_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
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif // ZM_HAS_V4L1
|
|
|
|
|
|
|
|
|
|
last_camera = this;
|
|
|
|
|
Debug(3, "Selected subpixelorder: %u", subpixelorder);
|
|
|
|
@ -724,7 +530,6 @@ void LocalCamera::Initialise() {
|
|
|
|
|
if ( !S_ISCHR(st.st_mode) )
|
|
|
|
|
Fatal("File %s is not device file: %s", device.c_str(), strerror(errno));
|
|
|
|
|
|
|
|
|
|
#if ZM_HAS_V4L2
|
|
|
|
|
Debug(2, "V4L2 support enabled, using V4L%d api", v4l_version);
|
|
|
|
|
if ( v4l_version == 2 ) {
|
|
|
|
|
struct v4l2_capability vid_cap;
|
|
|
|
@ -974,174 +779,9 @@ void LocalCamera::Initialise() {
|
|
|
|
|
Hue(hue);
|
|
|
|
|
Colour(colour);
|
|
|
|
|
}
|
|
|
|
|
#endif // ZM_HAS_V4L2
|
|
|
|
|
#if ZM_HAS_V4L1
|
|
|
|
|
if ( v4l_version == 1 ) {
|
|
|
|
|
Debug(3, "Configuring picture attributes");
|
|
|
|
|
|
|
|
|
|
struct video_picture vid_pic;
|
|
|
|
|
memset(&vid_pic, 0, sizeof(vid_pic));
|
|
|
|
|
if ( ioctl(vid_fd, VIDIOCGPICT, &vid_pic) < 0 )
|
|
|
|
|
Fatal("Failed to get picture attributes: %s", strerror(errno));
|
|
|
|
|
|
|
|
|
|
Debug(4,
|
|
|
|
|
"Old Palette:%d, depth:%d, brightness:%d, hue:%d, colour:%d, contrast:%d",
|
|
|
|
|
vid_pic.palette,
|
|
|
|
|
vid_pic.depth,
|
|
|
|
|
vid_pic.brightness,
|
|
|
|
|
vid_pic.hue,
|
|
|
|
|
vid_pic.colour,
|
|
|
|
|
vid_pic.contrast
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
switch (vid_pic.palette = palette) {
|
|
|
|
|
case VIDEO_PALETTE_RGB32 :
|
|
|
|
|
vid_pic.depth = 32;
|
|
|
|
|
break;
|
|
|
|
|
case VIDEO_PALETTE_RGB24 :
|
|
|
|
|
vid_pic.depth = 24;
|
|
|
|
|
break;
|
|
|
|
|
case VIDEO_PALETTE_GREY :
|
|
|
|
|
vid_pic.depth = 8;
|
|
|
|
|
break;
|
|
|
|
|
case VIDEO_PALETTE_RGB565 :
|
|
|
|
|
case VIDEO_PALETTE_YUYV :
|
|
|
|
|
case VIDEO_PALETTE_YUV422 :
|
|
|
|
|
case VIDEO_PALETTE_YUV420P :
|
|
|
|
|
case VIDEO_PALETTE_YUV422P :
|
|
|
|
|
default:
|
|
|
|
|
vid_pic.depth = 16;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( brightness >= 0 ) vid_pic.brightness = brightness;
|
|
|
|
|
if ( hue >= 0 ) vid_pic.hue = hue;
|
|
|
|
|
if ( colour >= 0 ) vid_pic.colour = colour;
|
|
|
|
|
if ( contrast >= 0 ) vid_pic.contrast = contrast;
|
|
|
|
|
|
|
|
|
|
if ( ioctl(vid_fd, VIDIOCSPICT, &vid_pic) < 0 ) {
|
|
|
|
|
Error("Failed to set picture attributes: %s", strerror(errno));
|
|
|
|
|
if ( config.strict_video_config )
|
|
|
|
|
exit(-1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Debug(3, "Configuring window attributes");
|
|
|
|
|
|
|
|
|
|
struct video_window vid_win;
|
|
|
|
|
memset(&vid_win, 0, sizeof(vid_win));
|
|
|
|
|
if ( ioctl(vid_fd, VIDIOCGWIN, &vid_win) < 0 ) {
|
|
|
|
|
Fatal("Failed to get window attributes: %s", strerror(errno));
|
|
|
|
|
}
|
|
|
|
|
Debug(4, "Old X:%d Y:%d W:%d H:%d",
|
|
|
|
|
vid_win.x, vid_win.y, vid_win.width, vid_win.height);
|
|
|
|
|
|
|
|
|
|
vid_win.x = 0;
|
|
|
|
|
vid_win.y = 0;
|
|
|
|
|
vid_win.width = width;
|
|
|
|
|
vid_win.height = height;
|
|
|
|
|
vid_win.flags &= ~VIDEO_WINDOW_INTERLACE;
|
|
|
|
|
|
|
|
|
|
if ( ioctl(vid_fd, VIDIOCSWIN, &vid_win) < 0 ) {
|
|
|
|
|
Error("Failed to set window attributes: %s", strerror(errno));
|
|
|
|
|
if ( config.strict_video_config )
|
|
|
|
|
exit(-1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Info("vid_win.width = %08x, vid_win.height = %08x, vid_win.flags = %08x",
|
|
|
|
|
vid_win.width, vid_win.height, vid_win.flags);
|
|
|
|
|
|
|
|
|
|
Debug(3, "Setting up request buffers");
|
|
|
|
|
if ( ioctl(vid_fd, VIDIOCGMBUF, &v4l1_data.frames) < 0 )
|
|
|
|
|
Fatal("Failed to setup memory: %s", strerror(errno));
|
|
|
|
|
if ( channel_count > 1 && !v4l_multi_buffer )
|
|
|
|
|
v4l1_data.frames.frames = 1;
|
|
|
|
|
v4l1_data.buffers = new video_mmap[v4l1_data.frames.frames];
|
|
|
|
|
Debug(4, "vmb.frames = %d, vmb.size = %d",
|
|
|
|
|
v4l1_data.frames.frames, v4l1_data.frames.size);
|
|
|
|
|
|
|
|
|
|
Debug(3, "Setting up %d frame buffers", v4l1_data.frames.frames);
|
|
|
|
|
|
|
|
|
|
v4l1_data.bufptr = (unsigned char *)mmap(0, v4l1_data.frames.size, PROT_READ|PROT_WRITE, MAP_SHARED, vid_fd, 0);
|
|
|
|
|
if ( v4l1_data.bufptr == MAP_FAILED )
|
|
|
|
|
Fatal("Could not mmap video: %s", strerror(errno));
|
|
|
|
|
|
|
|
|
|
#if HAVE_LIBSWSCALE
|
|
|
|
|
capturePictures = new AVFrame *[v4l1_data.frames.frames];
|
|
|
|
|
for ( int i = 0; i < v4l1_data.frames.frames; i++ ) {
|
|
|
|
|
v4l1_data.buffers[i].frame = i;
|
|
|
|
|
v4l1_data.buffers[i].width = width;
|
|
|
|
|
v4l1_data.buffers[i].height = height;
|
|
|
|
|
v4l1_data.buffers[i].format = palette;
|
|
|
|
|
|
|
|
|
|
#if LIBAVCODEC_VERSION_CHECK(55, 28, 1, 45, 101)
|
|
|
|
|
capturePictures[i] = av_frame_alloc();
|
|
|
|
|
#else
|
|
|
|
|
capturePictures[i] = avcodec_alloc_frame();
|
|
|
|
|
#endif
|
|
|
|
|
if ( !capturePictures[i] )
|
|
|
|
|
Fatal("Could not allocate picture");
|
|
|
|
|
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
|
|
|
|
|
av_image_fill_arrays(
|
|
|
|
|
capturePictures[i]->data,
|
|
|
|
|
capturePictures[i]->linesize,
|
|
|
|
|
(unsigned char *)v4l1_data.bufptr+v4l1_data.frames.offsets[i],
|
|
|
|
|
capturePixFormat, width, height, 1);
|
|
|
|
|
#else
|
|
|
|
|
avpicture_fill(
|
|
|
|
|
(AVPicture *)capturePictures[i],
|
|
|
|
|
(unsigned char *)v4l1_data.bufptr+v4l1_data.frames.offsets[i],
|
|
|
|
|
capturePixFormat, width, height );
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
#endif // HAVE_LIBSWSCALE
|
|
|
|
|
|
|
|
|
|
Debug(3, "Configuring video source");
|
|
|
|
|
|
|
|
|
|
struct video_channel vid_src;
|
|
|
|
|
memset(&vid_src, 0, sizeof(vid_src));
|
|
|
|
|
vid_src.channel = channel;
|
|
|
|
|
if ( ioctl(vid_fd, VIDIOCGCHAN, &vid_src) < 0 )
|
|
|
|
|
Fatal("Failed to get camera source: %s", strerror(errno));
|
|
|
|
|
|
|
|
|
|
Debug(4, "Old C:%d, F:%d, Fl:%x, T:%d",
|
|
|
|
|
vid_src.channel, vid_src.norm, vid_src.flags, vid_src.type);
|
|
|
|
|
|
|
|
|
|
vid_src.norm = standard;
|
|
|
|
|
vid_src.flags = 0;
|
|
|
|
|
vid_src.type = VIDEO_TYPE_CAMERA;
|
|
|
|
|
if ( ioctl(vid_fd, VIDIOCSCHAN, &vid_src) < 0 ) {
|
|
|
|
|
Error("Failed to set camera source %d: %s", channel, strerror(errno));
|
|
|
|
|
if ( config.strict_video_config )
|
|
|
|
|
exit(-1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( ioctl(vid_fd, VIDIOCGWIN, &vid_win) < 0 )
|
|
|
|
|
Fatal("Failed to get window data: %s", strerror(errno));
|
|
|
|
|
|
|
|
|
|
Info("vid_win.width = %08x, vid_win.height = %08x, vid_win.flags = %08x",
|
|
|
|
|
vid_win.width, vid_win.height, vid_win.flags);
|
|
|
|
|
|
|
|
|
|
Debug(4, "New X:%d Y:%d W:%d H:%d",
|
|
|
|
|
vid_win.x, vid_win.y, vid_win.width, vid_win.height);
|
|
|
|
|
|
|
|
|
|
if ( ioctl(vid_fd, VIDIOCGPICT, &vid_pic) < 0 )
|
|
|
|
|
Fatal("Failed to get window data: %s", strerror(errno));
|
|
|
|
|
|
|
|
|
|
Debug(4,
|
|
|
|
|
"New Palette:%d, depth:%d, brightness:%d, hue:%d, colour:%d, contrast:%d",
|
|
|
|
|
vid_pic.palette,
|
|
|
|
|
vid_pic.depth,
|
|
|
|
|
vid_pic.brightness,
|
|
|
|
|
vid_pic.hue,
|
|
|
|
|
vid_pic.colour,
|
|
|
|
|
vid_pic.contrast
|
|
|
|
|
);
|
|
|
|
|
} // end if v4l
|
|
|
|
|
#endif // ZM_HAS_V4L1
|
|
|
|
|
} // end LocalCamera::Initialize
|
|
|
|
|
|
|
|
|
|
void LocalCamera::Terminate() {
|
|
|
|
|
#if ZM_HAS_V4L2
|
|
|
|
|
if ( v4l_version == 2 ) {
|
|
|
|
|
Debug(3, "Terminating video stream");
|
|
|
|
|
//enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
|
|
|
@ -1164,28 +804,6 @@ void LocalCamera::Terminate() {
|
|
|
|
|
Error("Failed to munmap buffer %d: %s", i, strerror(errno));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif // ZM_HAS_V4L2
|
|
|
|
|
|
|
|
|
|
#if ZM_HAS_V4L1
|
|
|
|
|
if ( v4l_version == 1 ) {
|
|
|
|
|
#if HAVE_LIBSWSCALE
|
|
|
|
|
for ( int i=0; i < v4l1_data.frames.frames; i++ ) {
|
|
|
|
|
/* Free capture pictures */
|
|
|
|
|
#if LIBAVCODEC_VERSION_CHECK(55, 28, 1, 45, 101)
|
|
|
|
|
av_frame_free(&capturePictures[i]);
|
|
|
|
|
#else
|
|
|
|
|
av_freep(&capturePictures[i]);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
Debug(3, "Unmapping video buffers");
|
|
|
|
|
if ( munmap((char*)v4l1_data.bufptr, v4l1_data.frames.size) < 0 )
|
|
|
|
|
Error("Failed to munmap buffers: %s", strerror(errno));
|
|
|
|
|
|
|
|
|
|
delete[] v4l1_data.buffers;
|
|
|
|
|
} // end if using v4l1
|
|
|
|
|
#endif // ZM_HAS_V4L1
|
|
|
|
|
|
|
|
|
|
close(vid_fd);
|
|
|
|
|
primed = false;
|
|
|
|
@ -1194,7 +812,6 @@ void LocalCamera::Terminate() {
|
|
|
|
|
uint32_t LocalCamera::AutoSelectFormat(int p_colours) {
|
|
|
|
|
/* Automatic format selection */
|
|
|
|
|
uint32_t selected_palette = 0;
|
|
|
|
|
#if ZM_HAS_V4L2
|
|
|
|
|
char fmt_desc[64][32];
|
|
|
|
|
uint32_t fmt_fcc[64];
|
|
|
|
|
v4l2_fmtdesc fmtinfo;
|
|
|
|
@ -1289,7 +906,6 @@ uint32_t LocalCamera::AutoSelectFormat(int p_colours) {
|
|
|
|
|
/* Close the device */
|
|
|
|
|
close(enum_fd);
|
|
|
|
|
|
|
|
|
|
#endif /* ZM_HAS_V4L2 */
|
|
|
|
|
return selected_palette;
|
|
|
|
|
} //uint32_t LocalCamera::AutoSelectFormat(int p_colours)
|
|
|
|
|
|
|
|
|
@ -1332,7 +948,6 @@ bool LocalCamera::GetCurrentSettings(
|
|
|
|
|
output_ptr += sprintf(output_ptr, "d:%s|", queryDevice);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if ZM_HAS_V4L2
|
|
|
|
|
if ( version == 2 ) {
|
|
|
|
|
struct v4l2_capability vid_cap;
|
|
|
|
|
if ( vidioctl(vid_fd, VIDIOC_QUERYCAP, &vid_cap) < 0 ) {
|
|
|
|
@ -1591,200 +1206,7 @@ bool LocalCamera::GetCurrentSettings(
|
|
|
|
|
if ( !verbose )
|
|
|
|
|
*(output_ptr-1) = '\n';
|
|
|
|
|
}
|
|
|
|
|
#endif // ZM_HAS_V4L2
|
|
|
|
|
#if ZM_HAS_V4L1
|
|
|
|
|
if ( version == 1 ) {
|
|
|
|
|
struct video_capability vid_cap;
|
|
|
|
|
memset(&vid_cap, 0, sizeof(video_capability));
|
|
|
|
|
if ( ioctl(vid_fd, VIDIOCGCAP, &vid_cap) < 0 ) {
|
|
|
|
|
Error("Failed to get video capabilities: %s", strerror(errno));
|
|
|
|
|
if ( verbose )
|
|
|
|
|
output_ptr += sprintf(output_ptr,
|
|
|
|
|
"Error, failed to get video capabilities %s: %s\n",
|
|
|
|
|
queryDevice, strerror(errno));
|
|
|
|
|
else
|
|
|
|
|
output_ptr += sprintf(output_ptr, "error%d\n", errno);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if ( verbose ) {
|
|
|
|
|
output_ptr += sprintf( output_ptr, "Video Capabilities\n"
|
|
|
|
|
" Name: %s\n"
|
|
|
|
|
" Type: %d\n%s%s%s%s%s%s%s%s%s%s%s%s%s%s"
|
|
|
|
|
" Video Channels: %d\n"
|
|
|
|
|
" Audio Channels: %d\n"
|
|
|
|
|
" Maximum Width: %d\n"
|
|
|
|
|
" Maximum Height: %d\n"
|
|
|
|
|
" Minimum Width: %d\n"
|
|
|
|
|
" Minimum Height: %d\n",
|
|
|
|
|
vid_cap.name,
|
|
|
|
|
vid_cap.type,
|
|
|
|
|
(vid_cap.type&VID_TYPE_CAPTURE)?" Can capture\n":"",
|
|
|
|
|
(vid_cap.type&VID_TYPE_TUNER)?" Can tune\n":"",
|
|
|
|
|
(vid_cap.type&VID_TYPE_TELETEXT)?" Does teletext\n":"",
|
|
|
|
|
(vid_cap.type&VID_TYPE_OVERLAY)?" Overlay onto frame buffer\n":"",
|
|
|
|
|
(vid_cap.type&VID_TYPE_CHROMAKEY)?" Overlay by chromakey\n":"",
|
|
|
|
|
(vid_cap.type&VID_TYPE_CLIPPING)?" Can clip\n":"",
|
|
|
|
|
(vid_cap.type&VID_TYPE_FRAMERAM)?" Uses the frame buffer memory\n":"",
|
|
|
|
|
(vid_cap.type&VID_TYPE_SCALES)?" Scalable\n":"",
|
|
|
|
|
(vid_cap.type&VID_TYPE_MONOCHROME)?" Monochrome only\n":"",
|
|
|
|
|
(vid_cap.type&VID_TYPE_SUBCAPTURE)?" Can capture subareas of the image\n":"",
|
|
|
|
|
(vid_cap.type&VID_TYPE_MPEG_DECODER)?" Can decode MPEG streams\n":"",
|
|
|
|
|
(vid_cap.type&VID_TYPE_MPEG_ENCODER)?" Can encode MPEG streams\n":"",
|
|
|
|
|
(vid_cap.type&VID_TYPE_MJPEG_DECODER)?" Can decode MJPEG streams\n":"",
|
|
|
|
|
(vid_cap.type&VID_TYPE_MJPEG_ENCODER)?" Can encode MJPEG streams\n":"",
|
|
|
|
|
vid_cap.channels,
|
|
|
|
|
vid_cap.audios,
|
|
|
|
|
vid_cap.maxwidth,
|
|
|
|
|
vid_cap.maxheight,
|
|
|
|
|
vid_cap.minwidth,
|
|
|
|
|
vid_cap.minheight );
|
|
|
|
|
} else {
|
|
|
|
|
output_ptr += sprintf(output_ptr, "N:%s|T:%d|nC:%d|nA:%d|mxW:%d|mxH:%d|mnW:%d|mnH:%d|"
|
|
|
|
|
, vid_cap.name
|
|
|
|
|
, vid_cap.type
|
|
|
|
|
, vid_cap.channels
|
|
|
|
|
, vid_cap.audios
|
|
|
|
|
, vid_cap.maxwidth
|
|
|
|
|
, vid_cap.maxheight
|
|
|
|
|
, vid_cap.minwidth
|
|
|
|
|
, vid_cap.minheight);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct video_window vid_win;
|
|
|
|
|
memset(&vid_win, 0, sizeof(video_window));
|
|
|
|
|
if ( ioctl(vid_fd, VIDIOCGWIN, &vid_win) < 0 ) {
|
|
|
|
|
Error("Failed to get window attributes: %s", strerror(errno));
|
|
|
|
|
if ( verbose )
|
|
|
|
|
output_ptr += sprintf(output_ptr, "Error, failed to get window attributes: %s\n", strerror(errno));
|
|
|
|
|
else
|
|
|
|
|
output_ptr += sprintf(output_ptr, "error%d\n", errno);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if ( verbose ) {
|
|
|
|
|
output_ptr += sprintf(output_ptr,
|
|
|
|
|
"Window Attributes\n"
|
|
|
|
|
" X Offset: %d\n"
|
|
|
|
|
" Y Offset: %d\n"
|
|
|
|
|
" Width: %d\n"
|
|
|
|
|
" Height: %d\n"
|
|
|
|
|
, vid_win.x
|
|
|
|
|
, vid_win.y
|
|
|
|
|
, vid_win.width
|
|
|
|
|
, vid_win.height );
|
|
|
|
|
} else {
|
|
|
|
|
output_ptr += sprintf(output_ptr, "X:%d|Y:%d|W:%d|H:%d|",
|
|
|
|
|
vid_win.height, vid_win.x, vid_win.y, vid_win.width);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct video_picture vid_pic;
|
|
|
|
|
memset(&vid_pic, 0, sizeof(video_picture));
|
|
|
|
|
if ( ioctl(vid_fd, VIDIOCGPICT, &vid_pic) < 0 ) {
|
|
|
|
|
Error("Failed to get picture attributes: %s", strerror(errno));
|
|
|
|
|
if ( verbose )
|
|
|
|
|
output_ptr += sprintf(output_ptr, "Error, failed to get picture attributes: %s\n", strerror(errno));
|
|
|
|
|
else
|
|
|
|
|
output_ptr += sprintf(output_ptr, "error%d\n", errno);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if ( verbose ) {
|
|
|
|
|
output_ptr += sprintf(output_ptr,
|
|
|
|
|
"Picture Attributes\n"
|
|
|
|
|
" Palette: %d - %s\n"
|
|
|
|
|
" Colour Depth: %d\n"
|
|
|
|
|
" Brightness: %d\n"
|
|
|
|
|
" Hue: %d\n"
|
|
|
|
|
" Colour :%d\n"
|
|
|
|
|
" Contrast: %d\n"
|
|
|
|
|
" Whiteness: %d\n"
|
|
|
|
|
, vid_pic.palette,
|
|
|
|
|
vid_pic.palette==VIDEO_PALETTE_GREY?"Linear greyscale":(
|
|
|
|
|
vid_pic.palette==VIDEO_PALETTE_HI240?"High 240 cube (BT848)":(
|
|
|
|
|
vid_pic.palette==VIDEO_PALETTE_RGB565?"565 16 bit RGB":(
|
|
|
|
|
vid_pic.palette==VIDEO_PALETTE_RGB24?"24bit RGB":(
|
|
|
|
|
vid_pic.palette==VIDEO_PALETTE_RGB32?"32bit RGB":(
|
|
|
|
|
vid_pic.palette==VIDEO_PALETTE_RGB555?"555 15bit RGB":(
|
|
|
|
|
vid_pic.palette==VIDEO_PALETTE_YUV422?"YUV422 capture":(
|
|
|
|
|
vid_pic.palette==VIDEO_PALETTE_YUYV?"YUYV":(
|
|
|
|
|
vid_pic.palette==VIDEO_PALETTE_UYVY?"UVYV":(
|
|
|
|
|
vid_pic.palette==VIDEO_PALETTE_YUV420?"YUV420":(
|
|
|
|
|
vid_pic.palette==VIDEO_PALETTE_YUV411?"YUV411 capture":(
|
|
|
|
|
vid_pic.palette==VIDEO_PALETTE_RAW?"RAW capture (BT848)":(
|
|
|
|
|
vid_pic.palette==VIDEO_PALETTE_YUYV?"YUYV":(
|
|
|
|
|
vid_pic.palette==VIDEO_PALETTE_YUV422?"YUV422":(
|
|
|
|
|
vid_pic.palette==VIDEO_PALETTE_YUV422P?"YUV 4:2:2 Planar":(
|
|
|
|
|
vid_pic.palette==VIDEO_PALETTE_YUV411P?"YUV 4:1:1 Planar":(
|
|
|
|
|
vid_pic.palette==VIDEO_PALETTE_YUV420P?"YUV 4:2:0 Planar":(
|
|
|
|
|
vid_pic.palette==VIDEO_PALETTE_YUV410P?"YUV 4:1:0 Planar":"Unknown"
|
|
|
|
|
))))))))))))))))),
|
|
|
|
|
vid_pic.depth,
|
|
|
|
|
vid_pic.brightness,
|
|
|
|
|
vid_pic.hue,
|
|
|
|
|
vid_pic.colour,
|
|
|
|
|
vid_pic.contrast,
|
|
|
|
|
vid_pic.whiteness
|
|
|
|
|
);
|
|
|
|
|
} else {
|
|
|
|
|
output_ptr += sprintf(output_ptr, "P:%d|D:%d|B:%d|h:%d|Cl:%d|Cn:%d|w:%d|",
|
|
|
|
|
vid_pic.palette,
|
|
|
|
|
vid_pic.depth,
|
|
|
|
|
vid_pic.brightness,
|
|
|
|
|
vid_pic.hue,
|
|
|
|
|
vid_pic.colour,
|
|
|
|
|
vid_pic.contrast,
|
|
|
|
|
vid_pic.whiteness
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for ( int chan = 0; chan < vid_cap.channels; chan++ ) {
|
|
|
|
|
struct video_channel vid_src;
|
|
|
|
|
memset(&vid_src, 0, sizeof(video_channel));
|
|
|
|
|
vid_src.channel = chan;
|
|
|
|
|
if ( ioctl(vid_fd, VIDIOCGCHAN, &vid_src) < 0 ) {
|
|
|
|
|
Error("Failed to get channel %d attributes: %s", chan, strerror(errno));
|
|
|
|
|
if ( verbose )
|
|
|
|
|
output_ptr += sprintf(output_ptr, "Error, failed to get channel %d attributes: %s\n", chan, strerror(errno));
|
|
|
|
|
else
|
|
|
|
|
output_ptr += sprintf(output_ptr, "error%d\n", errno);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if ( verbose ) {
|
|
|
|
|
output_ptr += sprintf(output_ptr,
|
|
|
|
|
"Channel %d Attributes\n"
|
|
|
|
|
" Name: %s\n"
|
|
|
|
|
" Channel: %d\n"
|
|
|
|
|
" Flags: %d\n%s%s"
|
|
|
|
|
" Type: %d - %s\n"
|
|
|
|
|
" Format: %d - %s\n"
|
|
|
|
|
, chan
|
|
|
|
|
, vid_src.name
|
|
|
|
|
, vid_src.channel
|
|
|
|
|
, vid_src.flags
|
|
|
|
|
, (vid_src.flags&VIDEO_VC_TUNER)?" Channel has a tuner\n":""
|
|
|
|
|
, (vid_src.flags&VIDEO_VC_AUDIO)?" Channel has audio\n":""
|
|
|
|
|
, vid_src.type,
|
|
|
|
|
vid_src.type==VIDEO_TYPE_TV?"TV":(
|
|
|
|
|
vid_src.type==VIDEO_TYPE_CAMERA?"Camera":"Unknown"
|
|
|
|
|
)
|
|
|
|
|
, vid_src.norm,
|
|
|
|
|
vid_src.norm==VIDEO_MODE_PAL?"PAL":(
|
|
|
|
|
vid_src.norm==VIDEO_MODE_NTSC?"NTSC":(
|
|
|
|
|
vid_src.norm==VIDEO_MODE_SECAM?"SECAM":(
|
|
|
|
|
vid_src.norm==VIDEO_MODE_AUTO?"AUTO":"Unknown"
|
|
|
|
|
))));
|
|
|
|
|
} else {
|
|
|
|
|
output_ptr += sprintf(output_ptr, "n%d:%s|C%d:%d|Fl%d:%x|T%d:%d|F%d:%d%s|"
|
|
|
|
|
, chan, vid_src.name
|
|
|
|
|
, chan, vid_src.channel
|
|
|
|
|
, chan, vid_src.flags
|
|
|
|
|
, chan, vid_src.type
|
|
|
|
|
, chan, vid_src.norm, chan==(vid_cap.channels-1)?"":","
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if ( !verbose )
|
|
|
|
|
*output_ptr = '\n';
|
|
|
|
|
}
|
|
|
|
|
#endif // ZM_HAS_V4L1
|
|
|
|
|
close(vid_fd);
|
|
|
|
|
if ( device )
|
|
|
|
|
break;
|
|
|
|
@ -1793,7 +1215,6 @@ bool LocalCamera::GetCurrentSettings(
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int LocalCamera::Brightness(int p_brightness) {
|
|
|
|
|
#if ZM_HAS_V4L2
|
|
|
|
|
if ( v4l_version == 2 ) {
|
|
|
|
|
struct v4l2_control vid_control;
|
|
|
|
|
|
|
|
|
@ -1823,31 +1244,10 @@ int LocalCamera::Brightness(int p_brightness) {
|
|
|
|
|
}
|
|
|
|
|
return vid_control.value;
|
|
|
|
|
}
|
|
|
|
|
#endif // ZM_HAS_V4L2
|
|
|
|
|
#if ZM_HAS_V4L1
|
|
|
|
|
if ( v4l_version == 1 ) {
|
|
|
|
|
struct video_picture vid_pic;
|
|
|
|
|
memset(&vid_pic, 0, sizeof(video_picture));
|
|
|
|
|
if ( ioctl(vid_fd, VIDIOCGPICT, &vid_pic) < 0 ) {
|
|
|
|
|
Error("Failed to get picture attributes: %s", strerror(errno));
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( p_brightness >= 0 ) {
|
|
|
|
|
vid_pic.brightness = p_brightness;
|
|
|
|
|
if ( ioctl(vid_fd, VIDIOCSPICT, &vid_pic) < 0 ) {
|
|
|
|
|
Error("Failed to set picture attributes: %s", strerror(errno));
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return vid_pic.brightness;
|
|
|
|
|
}
|
|
|
|
|
#endif // ZM_HAS_V4L1
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int LocalCamera::Hue(int p_hue) {
|
|
|
|
|
#if ZM_HAS_V4L2
|
|
|
|
|
if ( v4l_version == 2 ) {
|
|
|
|
|
struct v4l2_control vid_control;
|
|
|
|
|
|
|
|
|
@ -1873,31 +1273,10 @@ int LocalCamera::Hue(int p_hue) {
|
|
|
|
|
}
|
|
|
|
|
return vid_control.value;
|
|
|
|
|
}
|
|
|
|
|
#endif // ZM_HAS_V4L2
|
|
|
|
|
#if ZM_HAS_V4L1
|
|
|
|
|
if ( v4l_version == 1 ) {
|
|
|
|
|
struct video_picture vid_pic;
|
|
|
|
|
memset(&vid_pic, 0, sizeof(video_picture));
|
|
|
|
|
if ( ioctl(vid_fd, VIDIOCGPICT, &vid_pic) < 0 ) {
|
|
|
|
|
Error("Failed to get picture attributes: %s", strerror(errno));
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( p_hue >= 0 ) {
|
|
|
|
|
vid_pic.hue = p_hue;
|
|
|
|
|
if ( ioctl(vid_fd, VIDIOCSPICT, &vid_pic) < 0 ) {
|
|
|
|
|
Error("Failed to set picture attributes: %s", strerror(errno));
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return vid_pic.hue;
|
|
|
|
|
}
|
|
|
|
|
#endif // ZM_HAS_V4L1
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int LocalCamera::Colour( int p_colour ) {
|
|
|
|
|
#if ZM_HAS_V4L2
|
|
|
|
|
if ( v4l_version == 2 ) {
|
|
|
|
|
struct v4l2_control vid_control;
|
|
|
|
|
|
|
|
|
@ -1924,31 +1303,10 @@ int LocalCamera::Colour( int p_colour ) {
|
|
|
|
|
}
|
|
|
|
|
return vid_control.value;
|
|
|
|
|
}
|
|
|
|
|
#endif // ZM_HAS_V4L2
|
|
|
|
|
#if ZM_HAS_V4L1
|
|
|
|
|
if ( v4l_version == 1 ) {
|
|
|
|
|
struct video_picture vid_pic;
|
|
|
|
|
memset(&vid_pic, 0, sizeof(video_picture));
|
|
|
|
|
if ( ioctl(vid_fd, VIDIOCGPICT, &vid_pic) < 0) {
|
|
|
|
|
Error("Failed to get picture attributes: %s", strerror(errno));
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( p_colour >= 0 ) {
|
|
|
|
|
vid_pic.colour = p_colour;
|
|
|
|
|
if ( ioctl(vid_fd, VIDIOCSPICT, &vid_pic) < 0 ) {
|
|
|
|
|
Error("Failed to set picture attributes: %s", strerror(errno));
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return vid_pic.colour;
|
|
|
|
|
}
|
|
|
|
|
#endif // ZM_HAS_V4L1
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int LocalCamera::Contrast( int p_contrast ) {
|
|
|
|
|
#if ZM_HAS_V4L2
|
|
|
|
|
if ( v4l_version == 2 ) {
|
|
|
|
|
struct v4l2_control vid_control;
|
|
|
|
|
|
|
|
|
@ -1975,26 +1333,6 @@ int LocalCamera::Contrast( int p_contrast ) {
|
|
|
|
|
}
|
|
|
|
|
return vid_control.value;
|
|
|
|
|
}
|
|
|
|
|
#endif // ZM_HAS_V4L2
|
|
|
|
|
#if ZM_HAS_V4L1
|
|
|
|
|
if ( v4l_version == 1 ) {
|
|
|
|
|
struct video_picture vid_pic;
|
|
|
|
|
memset(&vid_pic, 0, sizeof(video_picture));
|
|
|
|
|
if ( ioctl(vid_fd, VIDIOCGPICT, &vid_pic) < 0 ) {
|
|
|
|
|
Error("Failed to get picture attributes: %s", strerror(errno));
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( p_contrast >= 0 ) {
|
|
|
|
|
vid_pic.contrast = p_contrast;
|
|
|
|
|
if ( ioctl(vid_fd, VIDIOCSPICT, &vid_pic) < 0 ) {
|
|
|
|
|
Error("Failed to set picture attributes: %s", strerror(errno));
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return vid_pic.contrast;
|
|
|
|
|
}
|
|
|
|
|
#endif // ZM_HAS_V4L1
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -2004,7 +1342,6 @@ int LocalCamera::PrimeCapture() {
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
|
|
Debug(2, "Priming capture");
|
|
|
|
|
#if ZM_HAS_V4L2
|
|
|
|
|
if ( v4l_version == 2 ) {
|
|
|
|
|
Debug(3, "Queueing (%d) buffers", v4l2_data.reqbufs.count);
|
|
|
|
|
for ( unsigned int frame = 0; frame < v4l2_data.reqbufs.count; frame++ ) {
|
|
|
|
@ -2035,18 +1372,6 @@ int LocalCamera::PrimeCapture() {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
} // end if v4l_version == 2
|
|
|
|
|
#endif // ZM_HAS_V4L2
|
|
|
|
|
#if ZM_HAS_V4L1
|
|
|
|
|
if ( v4l_version == 1 ) {
|
|
|
|
|
for ( int frame = 0; frame < v4l1_data.frames.frames; frame++ ) {
|
|
|
|
|
Debug(3, "Queueing frame %d", frame);
|
|
|
|
|
if ( ioctl(vid_fd, VIDIOCMCAPTURE, &v4l1_data.buffers[frame]) < 0 ) {
|
|
|
|
|
Error("Capture failure for frame %d: %s", frame, strerror(errno));
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif // ZM_HAS_V4L1
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
} // end LocalCamera::PrimeCapture
|
|
|
|
@ -2072,7 +1397,6 @@ int LocalCamera::Capture(std::shared_ptr<ZMPacket> &zm_packet) {
|
|
|
|
|
|
|
|
|
|
// Do the capture, unless we are the second or subsequent camera on a channel, in which case just reuse the buffer
|
|
|
|
|
if ( channel_prime ) {
|
|
|
|
|
#if ZM_HAS_V4L2
|
|
|
|
|
if ( v4l_version == 2 ) {
|
|
|
|
|
static struct v4l2_buffer vid_buf;
|
|
|
|
|
|
|
|
|
@ -2119,37 +1443,7 @@ int LocalCamera::Capture(std::shared_ptr<ZMPacket> &zm_packet) {
|
|
|
|
|
v4l2_data.fmt.fmt.pix.width, v4l2_data.fmt.fmt.pix.height, width, height);
|
|
|
|
|
}
|
|
|
|
|
} // end if v4l2
|
|
|
|
|
#if ZM_HAS_V4L1
|
|
|
|
|
else
|
|
|
|
|
#endif // ZM_HAS_V4L1
|
|
|
|
|
#endif // ZM_HAS_V4L2
|
|
|
|
|
#if ZM_HAS_V4L1
|
|
|
|
|
if ( v4l_version == 1 ) {
|
|
|
|
|
Debug(3, "Capturing %d frames", captures_per_frame);
|
|
|
|
|
while ( captures_per_frame ) {
|
|
|
|
|
Debug(3, "Syncing frame %d", v4l1_data.active_frame);
|
|
|
|
|
if ( ioctl(vid_fd, VIDIOCSYNC, &v4l1_data.active_frame) < 0 ) {
|
|
|
|
|
Error("Sync failure for frame %d buffer %d: %s",
|
|
|
|
|
v4l1_data.active_frame, captures_per_frame, strerror(errno) );
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
captures_per_frame--;
|
|
|
|
|
if ( captures_per_frame ) {
|
|
|
|
|
Debug(3, "Capturing frame %d", v4l1_data.active_frame);
|
|
|
|
|
if ( ioctl(vid_fd, VIDIOCMCAPTURE, &v4l1_data.buffers[v4l1_data.active_frame]) < 0 ) {
|
|
|
|
|
Error("Capture failure for buffer %d (%d): %s",
|
|
|
|
|
v4l1_data.active_frame, captures_per_frame, strerror(errno));
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
capture_frame = v4l1_data.active_frame;
|
|
|
|
|
Debug(3, "Captured %d for channel %d", capture_frame, channel);
|
|
|
|
|
|
|
|
|
|
buffer = v4l1_data.bufptr+v4l1_data.frames.offsets[capture_frame];
|
|
|
|
|
}
|
|
|
|
|
#endif // ZM_HAS_V4L1
|
|
|
|
|
#if ZM_HAS_V4L2
|
|
|
|
|
if ( v4l_version == 2 ) {
|
|
|
|
|
if ( channel_count > 1 ) {
|
|
|
|
|
int next_channel = (channel_index+1)%channel_count;
|
|
|
|
@ -2174,41 +1468,6 @@ int LocalCamera::Capture(std::shared_ptr<ZMPacket> &zm_packet) {
|
|
|
|
|
Error("Unable to requeue buffer due to not v4l2_data");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#if ZM_HAS_V4L1
|
|
|
|
|
else
|
|
|
|
|
#endif // ZM_HAS_V4L1
|
|
|
|
|
#endif // ZM_HAS_V4L2
|
|
|
|
|
#if ZM_HAS_V4L1
|
|
|
|
|
if ( v4l_version == 1 ) {
|
|
|
|
|
if ( channel_count > 1 ) {
|
|
|
|
|
Debug(3, "Switching video source");
|
|
|
|
|
int next_channel = (channel_index+1)%channel_count;
|
|
|
|
|
struct video_channel vid_src;
|
|
|
|
|
memset(&vid_src, 0, sizeof(vid_src));
|
|
|
|
|
vid_src.channel = channel;
|
|
|
|
|
if ( ioctl(vid_fd, VIDIOCGCHAN, &vid_src) < 0 ) {
|
|
|
|
|
Error("Failed to get camera source %d: %s", channel, strerror(errno));
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vid_src.channel = channels[next_channel];
|
|
|
|
|
vid_src.norm = standards[next_channel];
|
|
|
|
|
vid_src.flags = 0;
|
|
|
|
|
vid_src.type = VIDEO_TYPE_CAMERA;
|
|
|
|
|
if ( ioctl(vid_fd, VIDIOCSCHAN, &vid_src) < 0 ) {
|
|
|
|
|
Error("Failed to set camera source %d: %s", channel, strerror(errno));
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Debug(3, "Requeueing frame %d", v4l1_data.active_frame);
|
|
|
|
|
if ( ioctl(vid_fd, VIDIOCMCAPTURE, &v4l1_data.buffers[v4l1_data.active_frame]) < 0 ) {
|
|
|
|
|
Error("Capture failure for frame %d: %s", v4l1_data.active_frame, strerror(errno));
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
v4l1_data.active_frame = (v4l1_data.active_frame+1)%v4l1_data.frames.frames;
|
|
|
|
|
}
|
|
|
|
|
#endif // ZM_HAS_V4L1
|
|
|
|
|
|
|
|
|
|
} /* prime capture */
|
|
|
|
|
|
|
|
|
|
if (!zm_packet->image) {
|
|
|
|
|