Skip to content

Commit 50a6930

Browse files
committed
Add support for "unicam image" RPi HDMI capture card and UYVY format
1 parent cfefbc5 commit 50a6930

File tree

3 files changed

+103
-9
lines changed

3 files changed

+103
-9
lines changed

Diff for: include/utils/PixelFormat.h

+9
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
enum class PixelFormat {
88
YUYV,
9+
UYVY,
910
RGB24,
1011
XRGB,
1112
I420,
@@ -23,6 +24,10 @@ inline PixelFormat parsePixelFormat(const QString& pixelFormat)
2324
{
2425
return PixelFormat::YUYV;
2526
}
27+
else if (format.compare("uyvy") == 0)
28+
{
29+
return PixelFormat::UYVY;
30+
}
2631
else if (format.compare("rgb24") == 0)
2732
{
2833
return PixelFormat::RGB24;
@@ -58,6 +63,10 @@ inline QString pixelFormatToString(const PixelFormat& pixelFormat)
5863
{
5964
return "yuyv";
6065
}
66+
else if (pixelFormat == PixelFormat::UYVY)
67+
{
68+
return "uyvy";
69+
}
6170
else if (pixelFormat == PixelFormat::RGB24)
6271
{
6372
return "rgb24";

Diff for: sources/grabber/linux/v4l2/V4L2Grabber.cpp

+45-5
Original file line numberDiff line numberDiff line change
@@ -79,12 +79,13 @@ namespace
7979
static const V4L2Grabber::HyperHdrFormat supportedFormats[] =
8080
{
8181
{ V4L2_PIX_FMT_YUYV, PixelFormat::YUYV },
82+
{ V4L2_PIX_FMT_UYVY, PixelFormat::UYVY },
8283
{ V4L2_PIX_FMT_XRGB32, PixelFormat::XRGB },
8384
{ V4L2_PIX_FMT_RGB24, PixelFormat::RGB24 },
8485
{ V4L2_PIX_FMT_YUV420, PixelFormat::I420 },
8586
{ V4L2_PIX_FMT_NV12, PixelFormat::NV12 },
8687
{ V4L2_PIX_FMT_MJPEG, PixelFormat::MJPEG },
87-
{ V4L2_PIX_FMT_P010, PixelFormat::P010 }
88+
{ V4L2_PIX_FMT_P010, PixelFormat::P010 }
8889
};
8990

9091

@@ -147,7 +148,7 @@ void V4L2Grabber::setHdrToneMappingEnabled(int mode)
147148
{
148149
Debug(_log, "setHdrToneMappingMode replacing LUT and restarting");
149150
_V4L2WorkerManager.Stop();
150-
if ((_actualVideoFormat == PixelFormat::YUYV) || (_actualVideoFormat == PixelFormat::I420) || (_actualVideoFormat == PixelFormat::NV12)
151+
if ((_actualVideoFormat == PixelFormat::YUYV) || (_actualVideoFormat == PixelFormat::UYVY) || (_actualVideoFormat == PixelFormat::I420) || (_actualVideoFormat == PixelFormat::NV12)
151152
|| (_actualVideoFormat == PixelFormat::P010) || (_actualVideoFormat == PixelFormat::MJPEG))
152153
loadLutFile(PixelFormat::YUYV);
153154
else
@@ -577,6 +578,28 @@ void V4L2Grabber::enumerateV4L2devices(bool silent)
577578
}
578579
}
579580

581+
if (properties.valid.size() == 0 && devName == "/dev/video0")
582+
{
583+
DevicePropertiesItem di;
584+
di.x = fmt.fmt.pix.width;
585+
di.y = fmt.fmt.pix.height;
586+
di.fps = 0;
587+
di.pf = identifyFormat(fmt.fmt.pix.pixelformat);
588+
di.v4l2PixelFormat = fmt.fmt.pix.pixelformat;
589+
di.input = inputIndex;
590+
591+
QString pixelFormat = pixelFormatToString(di.pf);
592+
if (di.pf == PixelFormat::NO_CHANGE)
593+
{
594+
Debug(_log, "%s %d x %d @ %d fps %s (unsupported)", QSTRING_CSTR(properties.name), di.x, di.y, di.fps, QSTRING_CSTR(pixelFormat));
595+
}
596+
else
597+
{
598+
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);
599+
properties.valid.append(di);
600+
}
601+
}
602+
580603
_deviceProperties.insert(realName, properties);
581604

582605
if (!silent)
@@ -904,7 +927,7 @@ bool V4L2Grabber::init_device(QString selectedDeviceName, DevicePropertiesItem p
904927

905928
streamparms.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
906929
// Check that the driver knows about framerate get/set
907-
if (xioctl(VIDIOC_G_PARM, &streamparms) >= 0)
930+
if (props.fps > 0 && xioctl(VIDIOC_G_PARM, &streamparms) >= 0)
908931
{
909932
// Check if the device is able to accept a capture framerate set.
910933
if (streamparms.parm.capture.capability == V4L2_CAP_TIMEPERFRAME)
@@ -918,6 +941,13 @@ bool V4L2Grabber::init_device(QString selectedDeviceName, DevicePropertiesItem p
918941
Info(_log, "Set framerate to %d FPS", streamparms.parm.capture.timeperframe.denominator);
919942
}
920943
}
944+
else
945+
{
946+
if (props.fps == 0)
947+
Warning(_log, "The device doesnt report frame rate settings");
948+
else
949+
Error(_log, "The device doesnt support VIDIOC_G_PARM for frame rate settings");
950+
}
921951

922952
// set the line length
923953
_lineLength = fmt.fmt.pix.bytesperline;
@@ -974,6 +1004,15 @@ bool V4L2Grabber::init_device(QString selectedDeviceName, DevicePropertiesItem p
9741004
}
9751005
break;
9761006

1007+
case V4L2_PIX_FMT_UYVY:
1008+
{
1009+
loadLutFile(PixelFormat::YUYV);
1010+
_actualVideoFormat = PixelFormat::UYVY;
1011+
_frameByteSize = props.x * props.y * 2;
1012+
Info(_log, "Video pixel format is set to: UYVY");
1013+
}
1014+
break;
1015+
9771016
case V4L2_PIX_FMT_XRGB32:
9781017
{
9791018
loadLutFile(PixelFormat::RGB24);
@@ -1209,10 +1248,11 @@ bool V4L2Grabber::process_image(v4l2_buffer* buf, const void* frameImageBuffer,
12091248
{
12101249
V4L2Worker* _workerThread = _V4L2WorkerManager.workers[i];
12111250

1212-
if ((_actualVideoFormat == PixelFormat::YUYV || _actualVideoFormat == PixelFormat::I420 ||
1251+
if ((_actualVideoFormat == PixelFormat::YUYV || _actualVideoFormat == PixelFormat::UYVY || _actualVideoFormat == PixelFormat::I420 ||
12131252
_actualVideoFormat == PixelFormat::NV12 || _hdrToneMappingEnabled) && !_lutBufferInit)
12141253
{
1215-
if ((_actualVideoFormat == PixelFormat::YUYV) || (_actualVideoFormat == PixelFormat::I420) || (_actualVideoFormat == PixelFormat::NV12) || (_actualVideoFormat == PixelFormat::MJPEG))
1254+
if ((_actualVideoFormat == PixelFormat::YUYV) || (_actualVideoFormat == PixelFormat::UYVY) (_actualVideoFormat == PixelFormat::I420) ||
1255+
(_actualVideoFormat == PixelFormat::NV12) || (_actualVideoFormat == PixelFormat::MJPEG))
12161256
{
12171257
loadLutFile(PixelFormat::YUYV, true);
12181258
}

Diff for: sources/utils/FrameDecoder.cpp

+49-4
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ void FrameDecoder::processImage(
191191
uint8_t buffer[8];
192192

193193
// validate format
194-
if (pixelFormat != PixelFormat::YUYV &&
194+
if (pixelFormat != PixelFormat::YUYV && pixelFormat != PixelFormat::UYVY &&
195195
pixelFormat != PixelFormat::XRGB && pixelFormat != PixelFormat::RGB24 &&
196196
pixelFormat != PixelFormat::I420 && pixelFormat != PixelFormat::NV12 && pixelFormat != PixelFormat::P010 && pixelFormat != PixelFormat::MJPEG)
197197
{
@@ -200,7 +200,7 @@ void FrameDecoder::processImage(
200200
}
201201

202202
// validate format LUT
203-
if ((pixelFormat == PixelFormat::YUYV || pixelFormat == PixelFormat::I420 || pixelFormat == PixelFormat::MJPEG ||
203+
if ((pixelFormat == PixelFormat::YUYV || pixelFormat == PixelFormat::UYVY || pixelFormat == PixelFormat::I420 || pixelFormat == PixelFormat::MJPEG ||
204204
pixelFormat == PixelFormat::NV12 || pixelFormat == PixelFormat::P010) && lutBuffer == NULL)
205205
{
206206
Error(Logger::getInstance("FrameDecoder"), "Missing LUT table for YUV colorspace");
@@ -248,6 +248,30 @@ void FrameDecoder::processImage(
248248
return;
249249
}
250250

251+
if (pixelFormat == PixelFormat::UYVY)
252+
{
253+
for (int yDest = 0, ySource = _cropTop; yDest < outputHeight; ++ySource, ++yDest)
254+
{
255+
uint8_t* currentDest = destMemory + ((uint64_t)destLineSize) * yDest;
256+
uint8_t* endDest = currentDest + destLineSize;
257+
uint8_t* currentSource = (uint8_t*)data + (((uint64_t)lineLength * ySource) + (((uint64_t)_cropLeft) << 1));
258+
259+
while (currentDest < endDest)
260+
{
261+
*((uint32_t*)&buffer) = *((uint32_t*)currentSource);
262+
263+
ind_lutd = LUT_INDEX(buffer[1], buffer[0], buffer[2]);
264+
ind_lutd2 = LUT_INDEX(buffer[3], buffer[0], buffer[2]);
265+
266+
*((uint32_t*)currentDest) = *((uint32_t*)(&lutBuffer[ind_lutd]));
267+
currentDest += 3;
268+
*((uint32_t*)currentDest) = *((uint32_t*)(&lutBuffer[ind_lutd2]));
269+
currentDest += 3;
270+
currentSource += 4;
271+
}
272+
}
273+
return;
274+
}
251275

252276
if (pixelFormat == PixelFormat::RGB24)
253277
{
@@ -474,7 +498,7 @@ void FrameDecoder::processQImage(
474498
uint8_t buffer[8];
475499

476500
// validate format
477-
if (pixelFormat != PixelFormat::YUYV &&
501+
if (pixelFormat != PixelFormat::YUYV && pixelFormat != PixelFormat::UYVY &&
478502
pixelFormat != PixelFormat::XRGB && pixelFormat != PixelFormat::RGB24 &&
479503
pixelFormat != PixelFormat::I420 && pixelFormat != PixelFormat::NV12 && pixelFormat != PixelFormat::P010)
480504
{
@@ -483,7 +507,7 @@ void FrameDecoder::processQImage(
483507
}
484508

485509
// validate format LUT
486-
if ((pixelFormat == PixelFormat::YUYV || pixelFormat == PixelFormat::I420 ||
510+
if ((pixelFormat == PixelFormat::YUYV || pixelFormat == PixelFormat::UYVY || pixelFormat == PixelFormat::I420 ||
487511
pixelFormat == PixelFormat::NV12 || pixelFormat == PixelFormat::P010) && lutBuffer == NULL)
488512
{
489513
Error(Logger::getInstance("FrameDecoder"), "Missing LUT table for YUV colorspace");
@@ -522,6 +546,27 @@ void FrameDecoder::processQImage(
522546
return;
523547
}
524548

549+
if (pixelFormat == PixelFormat::UYVY)
550+
{
551+
for (int yDest = 0, ySource = 0; yDest < outputHeight; ySource += 2, ++yDest)
552+
{
553+
uint8_t* currentDest = destMemory + ((uint64_t)destLineSize) * yDest;
554+
uint8_t* endDest = currentDest + destLineSize;
555+
uint8_t* currentSource = (uint8_t*)data + (((uint64_t)lineLength * ySource));
556+
557+
while (currentDest < endDest)
558+
{
559+
*((uint32_t*)&buffer) = *((uint32_t*)currentSource);
560+
561+
ind_lutd = LUT_INDEX(buffer[1], buffer[0], buffer[2]);
562+
563+
*((uint32_t*)currentDest) = *((uint32_t*)(&lutBuffer[ind_lutd]));
564+
currentDest += 3;
565+
currentSource += 4;
566+
}
567+
}
568+
return;
569+
}
525570

526571
if (pixelFormat == PixelFormat::RGB24)
527572
{

0 commit comments

Comments
 (0)