mirror of
https://github.com/opencv/opencv.git
synced 2025-01-18 22:44:02 +08:00
videoio(v4l2): use logging, update handling of EBUSY, device closing
- DEBUG logging compilation is enabled for all videoio backends - eliminate output through perror(), stderr
This commit is contained in:
parent
373160ce00
commit
501ff7f056
@ -278,6 +278,32 @@ make & enjoy!
|
||||
|
||||
namespace cv {
|
||||
|
||||
static const char* decode_ioctl_code(unsigned long ioctlCode)
|
||||
{
|
||||
switch (ioctlCode)
|
||||
{
|
||||
#define CV_ADD_IOCTL_CODE(id) case id: return #id
|
||||
CV_ADD_IOCTL_CODE(VIDIOC_G_FMT);
|
||||
CV_ADD_IOCTL_CODE(VIDIOC_S_FMT);
|
||||
CV_ADD_IOCTL_CODE(VIDIOC_REQBUFS);
|
||||
CV_ADD_IOCTL_CODE(VIDIOC_DQBUF);
|
||||
CV_ADD_IOCTL_CODE(VIDIOC_QUERYCAP);
|
||||
CV_ADD_IOCTL_CODE(VIDIOC_S_PARM);
|
||||
CV_ADD_IOCTL_CODE(VIDIOC_G_PARM);
|
||||
CV_ADD_IOCTL_CODE(VIDIOC_QUERYBUF);
|
||||
CV_ADD_IOCTL_CODE(VIDIOC_QBUF);
|
||||
CV_ADD_IOCTL_CODE(VIDIOC_STREAMON);
|
||||
CV_ADD_IOCTL_CODE(VIDIOC_STREAMOFF);
|
||||
CV_ADD_IOCTL_CODE(VIDIOC_ENUMINPUT);
|
||||
CV_ADD_IOCTL_CODE(VIDIOC_G_INPUT);
|
||||
CV_ADD_IOCTL_CODE(VIDIOC_S_INPUT);
|
||||
CV_ADD_IOCTL_CODE(VIDIOC_G_CTRL);
|
||||
CV_ADD_IOCTL_CODE(VIDIOC_S_CTRL);
|
||||
#undef CV_ADD_IOCTL_CODE
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
/* Device Capture Objects */
|
||||
/* V4L2 structure */
|
||||
struct Buffer
|
||||
@ -299,6 +325,9 @@ struct CvCaptureCAM_V4L CV_FINAL : public CvCapture
|
||||
int getCaptureDomain() /*const*/ CV_OVERRIDE { return cv::CAP_V4L; }
|
||||
|
||||
int deviceHandle;
|
||||
bool v4l_buffersRequested;
|
||||
bool v4l_streamStarted;
|
||||
|
||||
int bufferIndex;
|
||||
bool FirstCapture;
|
||||
String deviceName;
|
||||
@ -339,6 +368,8 @@ struct CvCaptureCAM_V4L CV_FINAL : public CvCapture
|
||||
bool open(const char* deviceName);
|
||||
bool isOpened() const;
|
||||
|
||||
void closeDevice();
|
||||
|
||||
virtual double getProperty(int) const CV_OVERRIDE;
|
||||
virtual bool setProperty(int, double) CV_OVERRIDE;
|
||||
virtual bool grabFrame() CV_OVERRIDE;
|
||||
@ -373,7 +404,10 @@ struct CvCaptureCAM_V4L CV_FINAL : public CvCapture
|
||||
/*********************** Implementations ***************************************/
|
||||
|
||||
CvCaptureCAM_V4L::CvCaptureCAM_V4L() :
|
||||
deviceHandle(-1), bufferIndex(-1),
|
||||
deviceHandle(-1),
|
||||
v4l_buffersRequested(false),
|
||||
v4l_streamStarted(false),
|
||||
bufferIndex(-1),
|
||||
FirstCapture(true),
|
||||
palette(0),
|
||||
width(0), height(0), width_set(0), height_set(0),
|
||||
@ -386,11 +420,32 @@ CvCaptureCAM_V4L::CvCaptureCAM_V4L() :
|
||||
memset(×tamp, 0, sizeof(timestamp));
|
||||
}
|
||||
|
||||
CvCaptureCAM_V4L::~CvCaptureCAM_V4L() {
|
||||
streaming(false);
|
||||
releaseBuffers();
|
||||
CvCaptureCAM_V4L::~CvCaptureCAM_V4L()
|
||||
{
|
||||
try
|
||||
{
|
||||
closeDevice();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
CV_LOG_WARNING(NULL, "VIDEOIO(V4L2): unable properly close device: " << deviceName);
|
||||
if (deviceHandle != -1)
|
||||
close(deviceHandle);
|
||||
}
|
||||
}
|
||||
|
||||
void CvCaptureCAM_V4L::closeDevice()
|
||||
{
|
||||
if (v4l_streamStarted)
|
||||
streaming(false);
|
||||
if (v4l_buffersRequested)
|
||||
releaseBuffers();
|
||||
if(deviceHandle != -1)
|
||||
{
|
||||
CV_LOG_DEBUG(NULL, "VIDEOIO(V4L2:" << deviceName << "): close(" << deviceHandle << ")");
|
||||
close(deviceHandle);
|
||||
}
|
||||
deviceHandle = -1;
|
||||
}
|
||||
|
||||
bool CvCaptureCAM_V4L::isOpened() const
|
||||
@ -406,7 +461,7 @@ bool CvCaptureCAM_V4L::try_palette_v4l2()
|
||||
form.fmt.pix.field = V4L2_FIELD_ANY;
|
||||
form.fmt.pix.width = width;
|
||||
form.fmt.pix.height = height;
|
||||
if (!tryIoctl(VIDIOC_S_FMT, &form))
|
||||
if (!tryIoctl(VIDIOC_S_FMT, &form, true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -451,9 +506,7 @@ bool CvCaptureCAM_V4L::try_init_v4l2()
|
||||
// The cv::CAP_PROP_MODE used for set the video input channel number
|
||||
if (!setVideoInputChannel())
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
fprintf(stderr, "(DEBUG) V4L2: Unable to set Video Input Channel.");
|
||||
#endif
|
||||
CV_LOG_DEBUG(NULL, "VIDEOIO(V4L2:" << deviceName << "): Unable to set Video Input Channel");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -461,16 +514,14 @@ bool CvCaptureCAM_V4L::try_init_v4l2()
|
||||
capability = v4l2_capability();
|
||||
if (!tryIoctl(VIDIOC_QUERYCAP, &capability))
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
fprintf(stderr, "(DEBUG) V4L2: Unable to query capability.");
|
||||
#endif
|
||||
CV_LOG_DEBUG(NULL, "VIDEOIO(V4L2:" << deviceName << "): Unable to query capability");
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((capability.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0)
|
||||
{
|
||||
/* Nope. */
|
||||
fprintf(stderr, "VIDEOIO ERROR: V4L2: Unable to capture video memory.");
|
||||
CV_LOG_INFO(NULL, "VIDEOIO(V4L2:" << deviceName << "): not supported - device is unable to capture video (missing V4L2_CAP_VIDEO_CAPTURE)");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -479,10 +530,18 @@ bool CvCaptureCAM_V4L::try_init_v4l2()
|
||||
bool CvCaptureCAM_V4L::autosetup_capture_mode_v4l2()
|
||||
{
|
||||
//in case palette is already set and works, no need to setup.
|
||||
if (palette != 0 && try_palette_v4l2()) {
|
||||
return true;
|
||||
} else if (errno == EBUSY) {
|
||||
return false;
|
||||
if (palette != 0)
|
||||
{
|
||||
if (try_palette_v4l2())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (errno == EBUSY)
|
||||
{
|
||||
CV_LOG_INFO(NULL, "VIDEOIO(V4L2:" << deviceName << "): device is busy");
|
||||
closeDevice();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
__u32 try_order[] = {
|
||||
V4L2_PIX_FMT_BGR24,
|
||||
@ -510,6 +569,10 @@ bool CvCaptureCAM_V4L::autosetup_capture_mode_v4l2()
|
||||
palette = try_order[i];
|
||||
if (try_palette_v4l2()) {
|
||||
return true;
|
||||
} else if (errno == EBUSY) {
|
||||
CV_LOG_INFO(NULL, "VIDEOIO(V4L2:" << deviceName << "): device is busy");
|
||||
closeDevice();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@ -525,9 +588,15 @@ bool CvCaptureCAM_V4L::setFps(int value)
|
||||
streamparm.parm.capture.timeperframe.numerator = 1;
|
||||
streamparm.parm.capture.timeperframe.denominator = __u32(value);
|
||||
if (!tryIoctl(VIDIOC_S_PARM, &streamparm) || !tryIoctl(VIDIOC_G_PARM, &streamparm))
|
||||
{
|
||||
CV_LOG_INFO(NULL, "VIDEOIO(V4L2:" << deviceName << "): can't set FPS: " << value);
|
||||
return false;
|
||||
}
|
||||
|
||||
fps = streamparm.parm.capture.timeperframe.denominator;
|
||||
CV_LOG_DEBUG(NULL, "VIDEOIO(V4L2:" << deviceName << "): FPS="
|
||||
<< streamparm.parm.capture.timeperframe.denominator << "/"
|
||||
<< streamparm.parm.capture.timeperframe.numerator);
|
||||
fps = streamparm.parm.capture.timeperframe.denominator; // TODO use numerator
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -622,10 +691,9 @@ bool CvCaptureCAM_V4L::initCapture()
|
||||
if (!isOpened())
|
||||
return false;
|
||||
|
||||
if (!try_init_v4l2()) {
|
||||
#ifndef NDEBUG
|
||||
fprintf(stderr, " try_init_v4l2 open \"%s\": %s\n", deviceName.c_str(), strerror(errno));
|
||||
#endif
|
||||
if (!try_init_v4l2())
|
||||
{
|
||||
CV_LOG_DEBUG(NULL, "VIDEOIO(V4L2:" << deviceName << "): init failed: errno=" << errno << " (" << strerror(errno) << ")");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -633,14 +701,17 @@ bool CvCaptureCAM_V4L::initCapture()
|
||||
form = v4l2_format();
|
||||
form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
|
||||
if (!tryIoctl(VIDIOC_G_FMT, &form)) {
|
||||
fprintf( stderr, "VIDEOIO ERROR: V4L2: Could not obtain specifics of capture window.\n");
|
||||
if (!tryIoctl(VIDIOC_G_FMT, &form))
|
||||
{
|
||||
CV_LOG_DEBUG(NULL, "VIDEOIO(V4L2:" << deviceName << "): Could not obtain specifics of capture window (VIDIOC_G_FMT): errno=" << errno << " (" << strerror(errno) << ")");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!autosetup_capture_mode_v4l2()) {
|
||||
if (errno != EBUSY) {
|
||||
fprintf(stderr, "VIDEOIO ERROR: V4L2: Pixel format of incoming image is unsupported by OpenCV\n");
|
||||
if (!autosetup_capture_mode_v4l2())
|
||||
{
|
||||
if (errno != EBUSY)
|
||||
{
|
||||
CV_LOG_INFO(NULL, "VIDEOIO(V4L2:" << deviceName << "): Pixel format of incoming image is unsupported by OpenCV");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -682,16 +753,16 @@ bool CvCaptureCAM_V4L::requestBuffers()
|
||||
{
|
||||
unsigned int buffer_number = bufferSize;
|
||||
while (buffer_number > 0) {
|
||||
if (!requestBuffers(buffer_number))
|
||||
return false;
|
||||
if (req.count >= buffer_number)
|
||||
if (requestBuffers(buffer_number) && req.count >= buffer_number)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
buffer_number--;
|
||||
fprintf(stderr, "Insufficient buffer memory on %s -- decreasing buffers\n", deviceName.c_str());
|
||||
CV_LOG_DEBUG(NULL, "VIDEOIO(V4L2:" << deviceName << "): Insufficient buffer memory -- decreasing buffers: " << buffer_number);
|
||||
}
|
||||
if (buffer_number < 1) {
|
||||
fprintf(stderr, "Insufficient buffer memory on %s\n", deviceName.c_str());
|
||||
CV_LOG_WARNING(NULL, "VIDEOIO(V4L2:" << deviceName << "): Insufficient buffer memory");
|
||||
return false;
|
||||
}
|
||||
bufferSize = req.count;
|
||||
@ -709,13 +780,18 @@ bool CvCaptureCAM_V4L::requestBuffers(unsigned int buffer_number)
|
||||
req.memory = V4L2_MEMORY_MMAP;
|
||||
|
||||
if (!tryIoctl(VIDIOC_REQBUFS, &req)) {
|
||||
if (EINVAL == errno) {
|
||||
fprintf(stderr, "%s does not support memory mapping\n", deviceName.c_str());
|
||||
} else {
|
||||
perror("VIDIOC_REQBUFS");
|
||||
int err = errno;
|
||||
if (EINVAL == err)
|
||||
{
|
||||
CV_LOG_WARNING(NULL, "VIDEOIO(V4L2:" << deviceName << "): no support for memory mapping");
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_LOG_WARNING(NULL, "VIDEOIO(V4L2:" << deviceName << "): failed VIDIOC_REQBUFS: errno=" << err << " (" << strerror(err) << ")");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
v4l_buffersRequested = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -729,7 +805,7 @@ bool CvCaptureCAM_V4L::createBuffers()
|
||||
buf.index = n_buffers;
|
||||
|
||||
if (!tryIoctl(VIDIOC_QUERYBUF, &buf)) {
|
||||
perror("VIDIOC_QUERYBUF");
|
||||
CV_LOG_WARNING(NULL, "VIDEOIO(V4L2:" << deviceName << "): failed VIDIOC_QUERYBUF: errno=" << errno << " (" << strerror(errno) << ")");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -742,7 +818,7 @@ bool CvCaptureCAM_V4L::createBuffers()
|
||||
deviceHandle, buf.m.offset);
|
||||
|
||||
if (MAP_FAILED == buffers[n_buffers].start) {
|
||||
perror("mmap");
|
||||
CV_LOG_WARNING(NULL, "VIDEOIO(V4L2:" << deviceName << "): failed mmap(" << buf.length << "): errno=" << errno << " (" << strerror(errno) << ")");
|
||||
return false;
|
||||
}
|
||||
maxLength = maxLength > buf.length ? maxLength : buf.length;
|
||||
@ -786,7 +862,7 @@ bool CvCaptureCAM_V4L::open(int _index)
|
||||
}
|
||||
if (_index < 0)
|
||||
{
|
||||
fprintf(stderr, "VIDEOIO ERROR: V4L: can't find camera device\n");
|
||||
CV_LOG_WARNING(NULL, "VIDEOIO(V4L2): can't find camera device");
|
||||
name.clear();
|
||||
return false;
|
||||
}
|
||||
@ -799,16 +875,15 @@ bool CvCaptureCAM_V4L::open(int _index)
|
||||
bool res = open(name.c_str());
|
||||
if (!res)
|
||||
{
|
||||
CV_LOG_WARNING(NULL, cv::format("VIDEOIO ERROR: V4L: can't open camera by index %d", _index));
|
||||
CV_LOG_WARNING(NULL, "VIDEOIO(V4L2:" << deviceName << "): can't open camera by index");
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
bool CvCaptureCAM_V4L::open(const char* _deviceName)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
fprintf(stderr, "(DEBUG) V4L: opening %s\n", _deviceName);
|
||||
#endif
|
||||
CV_Assert(_deviceName);
|
||||
CV_LOG_DEBUG(NULL, "VIDEOIO(V4L2:" << _deviceName << "): opening...");
|
||||
FirstCapture = true;
|
||||
width = DEFAULT_V4L_WIDTH;
|
||||
height = DEFAULT_V4L_HEIGHT;
|
||||
@ -824,6 +899,7 @@ bool CvCaptureCAM_V4L::open(const char* _deviceName)
|
||||
bufferIndex = -1;
|
||||
|
||||
deviceHandle = ::open(deviceName.c_str(), O_RDWR /* required */ | O_NONBLOCK, 0);
|
||||
CV_LOG_DEBUG(NULL, "VIDEOIO(V4L2:" << _deviceName << "): deviceHandle=" << deviceHandle);
|
||||
if (deviceHandle == -1)
|
||||
return false;
|
||||
|
||||
@ -837,7 +913,8 @@ bool CvCaptureCAM_V4L::read_frame_v4l2()
|
||||
buf.memory = V4L2_MEMORY_MMAP;
|
||||
|
||||
while (!tryIoctl(VIDIOC_DQBUF, &buf)) {
|
||||
if (errno == EIO && !(buf.flags & (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE))) {
|
||||
int err = errno;
|
||||
if (err == EIO && !(buf.flags & (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE))) {
|
||||
// Maybe buffer not in the queue? Try to put there
|
||||
if (!tryIoctl(VIDIOC_QBUF, &buf))
|
||||
return false;
|
||||
@ -845,7 +922,7 @@ bool CvCaptureCAM_V4L::read_frame_v4l2()
|
||||
}
|
||||
/* display the error and stop processing */
|
||||
returnFrame = false;
|
||||
perror("VIDIOC_DQBUF");
|
||||
CV_LOG_DEBUG(NULL, "VIDEOIO(V4L2:" << deviceName << "): can't read frame (VIDIOC_DQBUF): errno=" << err << " (" << strerror(err) << ")");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -863,37 +940,64 @@ bool CvCaptureCAM_V4L::read_frame_v4l2()
|
||||
|
||||
bool CvCaptureCAM_V4L::tryIoctl(unsigned long ioctlCode, void *parameter, bool failIfBusy, int attempts) const
|
||||
{
|
||||
if (attempts == 0) {
|
||||
return false;
|
||||
}
|
||||
while (-1 == ioctl(deviceHandle, ioctlCode, parameter)) {
|
||||
const bool isBusy = (errno == EBUSY);
|
||||
if (isBusy & failIfBusy) {
|
||||
return false;
|
||||
}
|
||||
if ((attempts > 0) && (--attempts == 0)) {
|
||||
return false;
|
||||
}
|
||||
CV_Assert(attempts > 0);
|
||||
CV_LOG_DEBUG(NULL, "VIDEOIO(V4L2:" << deviceName << "): tryIoctl(" << deviceHandle << ", "
|
||||
<< decode_ioctl_code(ioctlCode) << "(" << ioctlCode << "), failIfBusy=" << failIfBusy << ")"
|
||||
);
|
||||
while (true)
|
||||
{
|
||||
errno = 0;
|
||||
int result = ioctl(deviceHandle, ioctlCode, parameter);
|
||||
int err = errno;
|
||||
CV_LOG_DEBUG(NULL, "VIDEOIO(V4L2:" << deviceName << "): call ioctl(" << deviceHandle << ", "
|
||||
<< decode_ioctl_code(ioctlCode) << "(" << ioctlCode << "), ...) => "
|
||||
<< result << " errno=" << err << " (" << strerror(err) << ")"
|
||||
);
|
||||
|
||||
if (result != -1)
|
||||
return true; // success
|
||||
|
||||
const bool isBusy = (err == EBUSY);
|
||||
if (isBusy && failIfBusy)
|
||||
{
|
||||
CV_LOG_INFO(NULL, "VIDEOIO(V4L2:" << deviceName << "): ioctl returns with errno=EBUSY");
|
||||
return false;
|
||||
}
|
||||
if (!(isBusy || errno == EAGAIN))
|
||||
return false;
|
||||
|
||||
if (--attempts == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
fd_set fds;
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(deviceHandle, &fds);
|
||||
|
||||
/* Timeout. */
|
||||
static int param_v4l_select_timeout = (int)utils::getConfigurationParameterSizeT("OPENCV_VIDEOIO_V4L_SELECT_TIMEOUT", 10);
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 10;
|
||||
tv.tv_sec = param_v4l_select_timeout;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
int result = select(deviceHandle + 1, &fds, NULL, NULL, &tv);
|
||||
if (0 == result) {
|
||||
fprintf(stderr, "select timeout\n");
|
||||
errno = 0;
|
||||
result = select(deviceHandle + 1, &fds, NULL, NULL, &tv);
|
||||
err = errno;
|
||||
|
||||
if (0 == result)
|
||||
{
|
||||
CV_LOG_WARNING(NULL, "VIDEOIO(V4L2:" << deviceName << "): select() timeout.");
|
||||
return false;
|
||||
}
|
||||
|
||||
CV_LOG_DEBUG(NULL, "VIDEOIO(V4L2:" << deviceName << "): select(" << deviceHandle << ") => "
|
||||
<< result << " errno = " << err << " (" << strerror(err) << ")"
|
||||
);
|
||||
|
||||
if (EINTR == err) // don't loop if signal occurred, like Ctrl+C
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (-1 == result && EINTR != errno)
|
||||
perror("select");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -914,14 +1018,12 @@ bool CvCaptureCAM_V4L::grabFrame()
|
||||
buf.index = index;
|
||||
|
||||
if (!tryIoctl(VIDIOC_QBUF, &buf)) {
|
||||
perror("VIDIOC_QBUF");
|
||||
CV_LOG_DEBUG(NULL, "VIDEOIO(V4L2:" << deviceName << "): failed VIDIOC_QBUF (buffer=" << index << "): errno=" << errno << " (" << strerror(errno) << ")");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(!streaming(true)) {
|
||||
/* error enabling the stream */
|
||||
perror("VIDIOC_STREAMON");
|
||||
if (!streaming(true)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -936,9 +1038,12 @@ bool CvCaptureCAM_V4L::grabFrame()
|
||||
FirstCapture = false;
|
||||
}
|
||||
// In the case that the grab frame was without retrieveFrame
|
||||
if (bufferIndex >= 0) {
|
||||
if (bufferIndex >= 0)
|
||||
{
|
||||
if (!tryIoctl(VIDIOC_QBUF, &buffers[bufferIndex].buffer))
|
||||
perror("VIDIOC_QBUF");
|
||||
{
|
||||
CV_LOG_DEBUG(NULL, "VIDEOIO(V4L2:" << deviceName << "): failed VIDIOC_QBUF (buffer=" << bufferIndex << "): errno=" << errno << " (" << strerror(errno) << ")");
|
||||
}
|
||||
}
|
||||
return read_frame_v4l2();
|
||||
}
|
||||
@ -1453,6 +1558,7 @@ void CvCaptureCAM_V4L::convertToRgb(const Buffer ¤tBuffer)
|
||||
#ifdef HAVE_JPEG
|
||||
case V4L2_PIX_FMT_MJPEG:
|
||||
case V4L2_PIX_FMT_JPEG:
|
||||
CV_LOG_DEBUG(NULL, "VIDEOIO(V4L2:" << deviceName << "): decoding JPEG frame: size=" << currentBuffer.buffer.bytesused);
|
||||
cv::imdecode(Mat(1, currentBuffer.buffer.bytesused, CV_8U, currentBuffer.start), IMREAD_COLOR, &destination);
|
||||
return;
|
||||
#endif
|
||||
@ -1695,7 +1801,7 @@ bool CvCaptureCAM_V4L::controlInfo(int property_id, __u32 &_v4l2id, cv::Range &r
|
||||
v4l2_queryctrl queryctrl = v4l2_queryctrl();
|
||||
queryctrl.id = __u32(v4l2id);
|
||||
if (v4l2id == -1 || !tryIoctl(VIDIOC_QUERYCTRL, &queryctrl)) {
|
||||
fprintf(stderr, "VIDEOIO ERROR: V4L2: property %s is not supported\n", capPropertyName(property_id).c_str());
|
||||
CV_LOG_INFO(NULL, "VIDEOIO(V4L2:" << deviceName << "): property " << capPropertyName(property_id) << " is not supported");
|
||||
return false;
|
||||
}
|
||||
_v4l2id = __u32(v4l2id);
|
||||
@ -1726,7 +1832,9 @@ bool CvCaptureCAM_V4L::icvControl(__u32 v4l2id, int &value, bool isSet) const
|
||||
|
||||
/* The driver may clamp the value or return ERANGE, ignored here */
|
||||
if (!tryIoctl(isSet ? VIDIOC_S_CTRL : VIDIOC_G_CTRL, &control)) {
|
||||
switch (errno) {
|
||||
int err = errno;
|
||||
CV_LOG_DEBUG(NULL, "VIDEOIO(V4L2:" << deviceName << "): failed " << (isSet ? "VIDIOC_S_CTRL" : "VIDIOC_G_CTRL") << ": errno=" << err << " (" << strerror(err) << ")");
|
||||
switch (err) {
|
||||
#ifndef NDEBUG
|
||||
case EINVAL:
|
||||
fprintf(stderr,
|
||||
@ -1741,7 +1849,6 @@ bool CvCaptureCAM_V4L::icvControl(__u32 v4l2id, int &value, bool isSet) const
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
perror(isSet ? "VIDIOC_S_CTRL" : "VIDIOC_G_CTRL");
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
@ -1775,7 +1882,7 @@ double CvCaptureCAM_V4L::getProperty(int property_id) const
|
||||
v4l2_streamparm sp = v4l2_streamparm();
|
||||
sp.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
if (!tryIoctl(VIDIOC_G_PARM, &sp)) {
|
||||
fprintf(stderr, "VIDEOIO ERROR: V4L: Unable to get camera FPS\n");
|
||||
CV_LOG_WARNING(NULL, "VIDEOIO(V4L2:" << deviceName << "): Unable to get camera FPS");
|
||||
return -1;
|
||||
}
|
||||
return sp.parm.capture.timeperframe.denominator / (double)sp.parm.capture.timeperframe.numerator;
|
||||
@ -1865,7 +1972,7 @@ bool CvCaptureCAM_V4L::setProperty( int property_id, double _value )
|
||||
return true;
|
||||
|
||||
if (value > MAX_V4L_BUFFERS || value < 1) {
|
||||
fprintf(stderr, "V4L: Bad buffer size %d, buffer size must be from 1 to %d\n", value, MAX_V4L_BUFFERS);
|
||||
CV_LOG_WARNING(NULL, "VIDEOIO(V4L2:" << deviceName << "): Bad buffer size " << value << ", buffer size must be from 1 to " << MAX_V4L_BUFFERS);
|
||||
return false;
|
||||
}
|
||||
bufferSize = value;
|
||||
@ -1921,13 +2028,15 @@ void CvCaptureCAM_V4L::releaseBuffers()
|
||||
|
||||
bufferIndex = -1;
|
||||
FirstCapture = true;
|
||||
if (!isOpened())
|
||||
|
||||
if (!v4l_buffersRequested)
|
||||
return;
|
||||
v4l_buffersRequested = false;
|
||||
|
||||
for (unsigned int n_buffers = 0; n_buffers < MAX_V4L_BUFFERS; ++n_buffers) {
|
||||
if (buffers[n_buffers].start) {
|
||||
if (-1 == munmap(buffers[n_buffers].start, buffers[n_buffers].length)) {
|
||||
perror("munmap");
|
||||
CV_LOG_DEBUG(NULL, "VIDEOIO(V4L2:" << deviceName << "): failed munmap(): errno=" << errno << " (" << strerror(errno) << ")");
|
||||
} else {
|
||||
buffers[n_buffers].start = 0;
|
||||
}
|
||||
@ -1941,11 +2050,28 @@ void CvCaptureCAM_V4L::releaseBuffers()
|
||||
|
||||
bool CvCaptureCAM_V4L::streaming(bool startStream)
|
||||
{
|
||||
if (!isOpened())
|
||||
return !startStream;
|
||||
if (startStream != v4l_streamStarted)
|
||||
{
|
||||
if (!isOpened())
|
||||
{
|
||||
CV_Assert(v4l_streamStarted == false);
|
||||
return !startStream;
|
||||
}
|
||||
|
||||
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
return tryIoctl(startStream ? VIDIOC_STREAMON : VIDIOC_STREAMOFF, &type);
|
||||
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
bool result = tryIoctl(startStream ? VIDIOC_STREAMON : VIDIOC_STREAMOFF, &type);
|
||||
if (result)
|
||||
{
|
||||
v4l_streamStarted = startStream;
|
||||
return true;
|
||||
}
|
||||
if (startStream)
|
||||
{
|
||||
CV_LOG_DEBUG(NULL, "VIDEOIO(V4L2:" << deviceName << "): failed VIDIOC_STREAMON: errno=" << errno << " (" << strerror(errno) << ")");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return startStream;
|
||||
}
|
||||
|
||||
IplImage *CvCaptureCAM_V4L::retrieveFrame(int)
|
||||
@ -1963,6 +2089,7 @@ IplImage *CvCaptureCAM_V4L::retrieveFrame(int)
|
||||
} else {
|
||||
// for mjpeg streams the size might change in between, so we have to change the header
|
||||
// We didn't allocate memory when not convert_rgb, but we have to recreate the header
|
||||
CV_LOG_DEBUG(NULL, "VIDEOIO(V4L2:" << deviceName << "): buffer input size=" << currentBuffer.buffer.bytesused);
|
||||
if (frame.imageSize != (int)currentBuffer.buffer.bytesused)
|
||||
v4l2_create_frame();
|
||||
|
||||
@ -1972,7 +2099,9 @@ IplImage *CvCaptureCAM_V4L::retrieveFrame(int)
|
||||
}
|
||||
//Revert buffer to the queue
|
||||
if (!tryIoctl(VIDIOC_QBUF, &buffers[bufferIndex].buffer))
|
||||
perror("VIDIOC_QBUF");
|
||||
{
|
||||
CV_LOG_DEBUG(NULL, "VIDEOIO(V4L2:" << deviceName << "): failed VIDIOC_QBUF: errno=" << errno << " (" << strerror(errno) << ")");
|
||||
}
|
||||
|
||||
bufferIndex = -1;
|
||||
return &frame;
|
||||
|
@ -48,6 +48,12 @@
|
||||
#include "opencv2/core/private.hpp"
|
||||
|
||||
#include <opencv2/core/utils/configuration.private.hpp>
|
||||
#include <opencv2/core/utils/logger.defines.hpp>
|
||||
#ifdef NDEBUG
|
||||
#define CV_LOG_STRIP_LEVEL CV_LOG_LEVEL_DEBUG + 1
|
||||
#else
|
||||
#define CV_LOG_STRIP_LEVEL CV_LOG_LEVEL_VERBOSE + 1
|
||||
#endif
|
||||
#include <opencv2/core/utils/logger.hpp>
|
||||
|
||||
#include "opencv2/imgcodecs.hpp"
|
||||
|
Loading…
Reference in New Issue
Block a user