diff --git a/include/utils/PixelFormat.h b/include/utils/PixelFormat.h index 5e808b6c4..92dea7e2c 100644 --- a/include/utils/PixelFormat.h +++ b/include/utils/PixelFormat.h @@ -6,6 +6,7 @@ enum class PixelFormat { YUYV, + UYVY, RGB24, XRGB, I420, @@ -22,6 +23,10 @@ inline PixelFormat parsePixelFormat(const QString& pixelFormat) { return PixelFormat::YUYV; } + else if (format.compare("uyvy") == 0) + { + return PixelFormat::UYVY; + } else if (format.compare("rgb24") == 0) { return PixelFormat::RGB24; @@ -53,6 +58,10 @@ inline QString pixelFormatToString(const PixelFormat& pixelFormat) { return "yuyv"; } + else if (pixelFormat == PixelFormat::UYVY) + { + return "uyvy"; + } else if (pixelFormat == PixelFormat::RGB24) { return "rgb24"; diff --git a/sources/grabber/v4l2/V4L2Grabber.cpp b/sources/grabber/v4l2/V4L2Grabber.cpp index 72c072d41..b16e96ec7 100644 --- a/sources/grabber/v4l2/V4L2Grabber.cpp +++ b/sources/grabber/v4l2/V4L2Grabber.cpp @@ -64,6 +64,7 @@ static const V4L2Grabber::HyperHdrFormat supportedFormats[] = { { V4L2_PIX_FMT_YUYV, PixelFormat::YUYV }, + { V4L2_PIX_FMT_UYVY, PixelFormat::UYVY }, { V4L2_PIX_FMT_XRGB32, PixelFormat::XRGB }, { V4L2_PIX_FMT_RGB24, PixelFormat::RGB24 }, { V4L2_PIX_FMT_YUV420, PixelFormat::I420 }, @@ -129,7 +130,7 @@ void V4L2Grabber::setHdrToneMappingEnabled(int mode) { Debug(_log, "setHdrToneMappingMode replacing LUT and restarting"); _V4L2WorkerManager.Stop(); - if ((_actualVideoFormat == PixelFormat::YUYV) || (_actualVideoFormat == PixelFormat::I420) || (_actualVideoFormat == PixelFormat::NV12) || (_actualVideoFormat == PixelFormat::MJPEG)) + if ((_actualVideoFormat == PixelFormat::YUYV) || (_actualVideoFormat == PixelFormat::UYVY) || (_actualVideoFormat == PixelFormat::I420) || (_actualVideoFormat == PixelFormat::NV12) || (_actualVideoFormat == PixelFormat::MJPEG)) loadLutFile(PixelFormat::YUYV); else loadLutFile(PixelFormat::RGB24); @@ -558,6 +559,28 @@ void V4L2Grabber::enumerateV4L2devices(bool silent) } } + if (properties.valid.size() == 0) + { + DevicePropertiesItem di; + di.x = fmt.fmt.pix.width; + di.y = fmt.fmt.pix.height; + di.fps = 0; + di.pf = identifyFormat(fmt.fmt.pix.pixelformat); + di.v4l2PixelFormat = fmt.fmt.pix.pixelformat; + di.input = inputIndex; + + QString pixelFormat = pixelFormatToString(di.pf); + if (di.pf == PixelFormat::NO_CHANGE) + { + Debug(_log, "%s %d x %d @ %d fps %s (unsupported)", QSTRING_CSTR(properties.name), di.x, di.y, di.fps, QSTRING_CSTR(pixelFormat)); + } + else + { + Debug(_log, "%s %d x %d @ %d fps %s, input = %i (seems supported, device not fully compatible with v4l2 grabber model, frame rate is unknown)", QSTRING_CSTR(properties.name), di.x, di.y, di.fps, QSTRING_CSTR(pixelFormat), di.input); + properties.valid.append(di); + } + } + _deviceProperties.insert(realName, properties); if (!silent) @@ -885,7 +908,7 @@ bool V4L2Grabber::init_device(QString selectedDeviceName, DevicePropertiesItem p streamparms.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; // Check that the driver knows about framerate get/set - if (xioctl(VIDIOC_G_PARM, &streamparms) >= 0) + if (props.fps > 0 && xioctl(VIDIOC_G_PARM, &streamparms) >= 0) { // Check if the device is able to accept a capture framerate set. if (streamparms.parm.capture.capability == V4L2_CAP_TIMEPERFRAME) @@ -899,6 +922,13 @@ bool V4L2Grabber::init_device(QString selectedDeviceName, DevicePropertiesItem p Info(_log, "Set framerate to %d FPS", streamparms.parm.capture.timeperframe.denominator); } } + else + { + if (props.fps == 0) + Warning(_log, "The device doesnt report frame rate settings"); + else + Error(_log, "The device doesnt support VIDIOC_G_PARM for frame rate settings"); + } // set the line length _lineLength = fmt.fmt.pix.bytesperline; @@ -955,6 +985,15 @@ bool V4L2Grabber::init_device(QString selectedDeviceName, DevicePropertiesItem p } break; + case V4L2_PIX_FMT_UYVY: + { + loadLutFile(PixelFormat::YUYV); + _actualVideoFormat = PixelFormat::UYVY; + _frameByteSize = props.x * props.y * 2; + Info(_log, "Video pixel format is set to: UYVY"); + } + break; + case V4L2_PIX_FMT_XRGB32: { loadLutFile(PixelFormat::RGB24); @@ -1180,7 +1219,7 @@ bool V4L2Grabber::process_image(v4l2_buffer* buf, const void* frameImageBuffer, { V4L2Worker* _workerThread = _V4L2WorkerManager.workers[i]; - if ((_actualVideoFormat == PixelFormat::YUYV || _actualVideoFormat == PixelFormat::I420 || + if ((_actualVideoFormat == PixelFormat::YUYV || _actualVideoFormat == PixelFormat::UYVY || _actualVideoFormat == PixelFormat::I420 || _actualVideoFormat == PixelFormat::NV12) && !_lutBufferInit) { loadLutFile(); diff --git a/sources/utils/FrameDecoder.cpp b/sources/utils/FrameDecoder.cpp index a7c38a931..5e1d47da4 100644 --- a/sources/utils/FrameDecoder.cpp +++ b/sources/utils/FrameDecoder.cpp @@ -47,7 +47,7 @@ void FrameDecoder::processImage( uint8_t buffer[8]; // validate format - if (pixelFormat != PixelFormat::YUYV && + if (pixelFormat != PixelFormat::YUYV && pixelFormat != PixelFormat::UYVY && pixelFormat != PixelFormat::XRGB && pixelFormat != PixelFormat::RGB24 && pixelFormat != PixelFormat::I420 && pixelFormat != PixelFormat::NV12 && pixelFormat != PixelFormat::MJPEG) { @@ -56,7 +56,7 @@ void FrameDecoder::processImage( } // validate format LUT - if ((pixelFormat == PixelFormat::YUYV || pixelFormat == PixelFormat::I420 || pixelFormat == PixelFormat::MJPEG || + if ((pixelFormat == PixelFormat::YUYV || pixelFormat == PixelFormat::UYVY || pixelFormat == PixelFormat::I420 || pixelFormat == PixelFormat::MJPEG || pixelFormat == PixelFormat::NV12) && lutBuffer == NULL) { Error(Logger::getInstance("FrameDecoder"), "Missing LUT table for YUV colorspace"); @@ -111,6 +111,31 @@ void FrameDecoder::processImage( return; } + if (pixelFormat == PixelFormat::UYVY) + { + for (int yDest = 0, ySource = _cropTop; yDest < outputHeight; ++ySource, ++yDest) + { + uint8_t* currentDest = destMemory + ((uint64_t)destLineSize) * yDest; + uint8_t* endDest = currentDest + destLineSize; + uint8_t* currentSource = (uint8_t*)data + (((uint64_t)lineLength * ySource) + (((uint64_t)_cropLeft) << 1)); + + while (currentDest < endDest) + { + *((uint32_t*)&buffer) = *((uint32_t*)currentSource); + + ind_lutd = LUT_INDEX(buffer[1], buffer[0], buffer[2]); + ind_lutd2 = LUT_INDEX(buffer[3], buffer[0], buffer[2]); + + *((uint32_t*)currentDest) = *((uint32_t*)(&lutBuffer[ind_lutd])); + currentDest += 3; + *((uint32_t*)currentDest) = *((uint32_t*)(&lutBuffer[ind_lutd2])); + currentDest += 3; + currentSource += 4; + } + } + return; + } + if (pixelFormat == PixelFormat::RGB24) { @@ -285,7 +310,7 @@ void FrameDecoder::processQImage( uint8_t buffer[8]; // validate format - if (pixelFormat != PixelFormat::YUYV && + if (pixelFormat != PixelFormat::YUYV && pixelFormat != PixelFormat::UYVY && pixelFormat != PixelFormat::XRGB && pixelFormat != PixelFormat::RGB24 && pixelFormat != PixelFormat::I420 && pixelFormat != PixelFormat::NV12) { @@ -294,7 +319,7 @@ void FrameDecoder::processQImage( } // validate format LUT - if ((pixelFormat == PixelFormat::YUYV || pixelFormat == PixelFormat::I420 || + if ((pixelFormat == PixelFormat::YUYV || pixelFormat == PixelFormat::UYVY || pixelFormat == PixelFormat::I420 || pixelFormat == PixelFormat::NV12) && lutBuffer == NULL) { Error(Logger::getInstance("FrameDecoder"), "Missing LUT table for YUV colorspace"); @@ -333,6 +358,27 @@ void FrameDecoder::processQImage( return; } + if (pixelFormat == PixelFormat::UYVY) + { + for (int yDest = 0, ySource = 0; yDest < outputHeight; ySource += 2, ++yDest) + { + uint8_t* currentDest = destMemory + ((uint64_t)destLineSize) * yDest; + uint8_t* endDest = currentDest + destLineSize; + uint8_t* currentSource = (uint8_t*)data + (((uint64_t)lineLength * ySource)); + + while (currentDest < endDest) + { + *((uint32_t*)&buffer) = *((uint32_t*)currentSource); + + ind_lutd = LUT_INDEX(buffer[1], buffer[0], buffer[2]); + + *((uint32_t*)currentDest) = *((uint32_t*)(&lutBuffer[ind_lutd])); + currentDest += 3; + currentSource += 4; + } + } + return; + } if (pixelFormat == PixelFormat::RGB24) {