Skip to content

Commit 3168734

Browse files
authored
Add NV12 image format support for flatbuffers (#920)
1 parent 313ca62 commit 3168734

22 files changed

+364
-225
lines changed

Diff for: include/base/Grabber.h

+2-9
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <utils/Components.h>
1818
#include <image/MemoryBuffer.h>
1919
#include <utils/FrameDecoder.h>
20+
#include <utils/LutLoader.h>
2021
#include <base/DetectionManual.h>
2122
#include <base/DetectionAutomatic.h>
2223
#include <performance-counters/PerformanceCounters.h>
@@ -32,11 +33,9 @@
3233
#include <CoreGraphics/CoreGraphics.h>
3334
#endif
3435

35-
#define LUT_FILE_SIZE 50331648
36-
3736
#define UNSUPPORTED_DECODER "UNSUPPORTED YUV DECODER"
3837

39-
class Grabber : public DetectionAutomatic, public DetectionManual
38+
class Grabber : public DetectionAutomatic, public DetectionManual, protected LutLoader
4039
{
4140
Q_OBJECT
4241

@@ -174,7 +173,6 @@ public slots:
174173
void SignalBenchmarkUpdate(int status, QString message);
175174

176175
protected:
177-
void loadLutFile(PixelFormat color, const QList<QString>& files);
178176

179177
int getTargetSystemFrameDimension(int& targetSizeX, int& targetSizeY);
180178

@@ -234,9 +232,6 @@ public slots:
234232

235233
bool _enabled;
236234

237-
// enable/disable HDR tone mapping
238-
uint8_t _hdrToneMappingEnabled;
239-
240235
/// logger instance
241236
Logger* _log;
242237

@@ -266,8 +261,6 @@ public slots:
266261
int _actualWidth, _actualHeight, _actualFPS;
267262
QString _actualDeviceName;
268263
uint _targetMonitorNits;
269-
MemoryBuffer<uint8_t> _lut;
270-
bool _lutBufferInit;
271264

272265
int _lineLength;
273266
int _frameByteSize;

Diff for: include/flatbuffers/parser/FlatBuffersParser.h

+26-2
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,30 @@
3232
namespace FlatBuffersParser
3333
{
3434
enum FLATBUFFERS_PACKAGE_TYPE { COLOR = 1, IMAGE, CLEAR, PRIORITY, ERROR };
35+
enum FLATBUFFERS_IMAGE_FORMAT { RGB = 1, NV12 };
36+
37+
struct FlatbuffersColor
38+
{
39+
uint8_t red;
40+
uint8_t green;
41+
uint8_t blue;
42+
};
43+
44+
struct FlatbuffersTransientImage
45+
{
46+
FLATBUFFERS_IMAGE_FORMAT format;
47+
48+
struct
49+
{
50+
uint8_t* data;
51+
int size;
52+
int stride;
53+
} firstPlane, secondPlane;
54+
55+
int width;
56+
int height;
57+
int size;
58+
};
3559

3660

3761
void* createFlatbuffersBuilder();
@@ -43,8 +67,8 @@ namespace FlatBuffersParser
4367
void encodeColorIntoFlatbuffers(void* builder, int red, int green, int blue, int priority, int duration, uint8_t** buffer, size_t* bufferSize);
4468
bool verifyFlatbuffersReplyBuffer(const uint8_t* messageData, size_t messageSize, bool* _sent, bool* _registered, int* _priority);
4569
int decodeIncomingFlatbuffersFrame(void* builder, const uint8_t* messageData, size_t messageSize,
46-
uint8_t* red, uint8_t* green, uint8_t* blue,
4770
int* priority, std::string* clientDescription, int* duration,
48-
uint8_t** imageData, int* imageWidth, int* imageHeight, size_t* imageSize,
71+
FlatbuffersTransientImage& image,
72+
FlatbuffersColor& color,
4973
uint8_t** buffer, size_t* bufferSize);
5074
}

Diff for: include/flatbuffers/parser/hyperhdr_request.fbs

+10-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,16 @@ table RawImage {
1212
height:int = -1;
1313
}
1414

15-
union ImageType {RawImage}
15+
table NV12Image {
16+
data_y:[ubyte];
17+
data_uv:[ubyte];
18+
width:int;
19+
height:int;
20+
stride_y:int = 0;
21+
stride_uv:int = 0;
22+
}
23+
24+
union ImageType {RawImage, NV12Image}
1625

1726
table Image {
1827
data:ImageType (required);

Diff for: include/flatbuffers/server/FlatBuffersServer.h

+10-7
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,23 @@
99
#include <utils/settings.h>
1010
#include <image/Image.h>
1111
#include <utils/Components.h>
12+
#include <utils/LutLoader.h>
1213

1314
class BonjourServiceRegister;
1415
class QTcpServer;
1516
class QLocalServer;
1617
class FlatBuffersServerConnection;
1718
class NetOrigin;
1819

20+
namespace FlatBuffersParser
21+
{
22+
struct FlatbuffersTransientImage;
23+
};
24+
1925
#define HYPERHDR_DOMAIN_SERVER QStringLiteral("hyperhdr-domain")
2026
#define BASEAPI_FLATBUFFER_USER_LUT_FILE QStringLiteral("BASEAPI_user_lut_file")
2127

22-
class FlatBuffersServer : public QObject
28+
class FlatBuffersServer : public QObject, protected LutLoader
2329
{
2430
Q_OBJECT
2531
public:
@@ -35,7 +41,7 @@ public slots:
3541
void initServer();
3642
int getHdrToneMappingEnabled();
3743
void handlerImportFromProto(int priority, int duration, const Image<ColorRgb>& image, QString clientDescription);
38-
void handlerImageReceived(int priority, const Image<ColorRgb>& image, int timeout_ms, hyperhdr::Components origin, QString clientDescription);
44+
void handlerImageReceived(int priority, FlatBuffersParser::FlatbuffersTransientImage* flatImage, int timeout_ms, hyperhdr::Components origin, QString clientDescription);
3945
void signalRequestSourceHandler(hyperhdr::Components component, int instanceIndex, bool listen);
4046

4147
private slots:
@@ -60,11 +66,8 @@ private slots:
6066
BonjourServiceRegister* _serviceRegister = nullptr;
6167
QVector<FlatBuffersServerConnection*> _openConnections;
6268

63-
int _hdrToneMappingMode;
64-
int _realHdrToneMappingMode;
65-
bool _lutBufferInit;
6669
QString _configurationPath;
6770
QString _userLutFile;
68-
69-
MemoryBuffer<uint8_t> _lut;
71+
PixelFormat _currentLutPixelFormat;
72+
int _flatbufferToneMappingMode;
7073
};

Diff for: include/flatbuffers/server/FlatBuffersServerConnection.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@
3737
class QTcpSocket;
3838
class QLocalSocket;
3939
class QTimer;
40+
namespace FlatBuffersParser
41+
{
42+
struct FlatbuffersTransientImage;
43+
};
4044

4145
class FlatBuffersServerConnection : public QObject
4246
{
@@ -49,7 +53,7 @@ class FlatBuffersServerConnection : public QObject
4953

5054
signals:
5155
void SignalClearGlobalInput(int priority, bool forceClearAll);
52-
void SignalImageReceived(int priority, const Image<ColorRgb>& image, int timeout_ms, hyperhdr::Components origin, QString clientDescription);
56+
void SignalDirectImageReceivedInTempBuffer(int priority, FlatBuffersParser::FlatbuffersTransientImage* image, int timeout_ms, hyperhdr::Components origin, QString clientDescription);
5357
void SignalSetGlobalColor(int priority, const std::vector<ColorRgb>& ledColor, int timeout_ms, hyperhdr::Components origin, QString clientDescription);
5458
void SignalClientDisconnected(FlatBuffersServerConnection* client);
5559

Diff for: include/image/ColorRgb.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ struct ColorRgb
9191
operator std::string()
9292
{
9393
std::stringstream ss;
94-
ss << "(" << red << ", " << green << ", " << blue << ")";
94+
ss << "(" << std::to_string(red) << ", " << std::to_string(green) << ", " << std::to_string(blue) << ")";
9595
return ss.str();
9696
}
9797

Diff for: include/utils/FrameDecoder.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ class FrameDecoder
1313
public:
1414
static void processImage(
1515
int _cropLeft, int _cropRight, int _cropTop, int _cropBottom,
16-
const uint8_t* data, int width, int height, int lineLength,
16+
const uint8_t* data, const uint8_t* dataUV, int width, int height, int lineLength,
1717
const PixelFormat pixelFormat, const uint8_t* lutBuffer, Image<ColorRgb>& outputImage);
1818

1919
static void processQImage(

Diff for: include/utils/LutLoader.h

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#pragma once
2+
3+
#ifndef PCH_ENABLED
4+
#include <QString>
5+
#include <QList>
6+
#endif
7+
8+
#include <utils/PixelFormat.h>
9+
#include <image/MemoryBuffer.h>
10+
#include <utils/Logger.h>
11+
12+
class LutLoader {
13+
public:
14+
int _hdrToneMappingEnabled = 0;
15+
bool _lutBufferInit = false;
16+
17+
MemoryBuffer<uint8_t> _lut;
18+
19+
void loadLutFile(Logger* _log, PixelFormat color, const QList<QString>& files);
20+
};

Diff for: sources/base/Grabber.cpp

-96
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ Grabber::Grabber(const QString& configurationPath, const QString& grabberName)
4949
, _cropTop(0)
5050
, _cropBottom(0)
5151
, _enabled(true)
52-
, _hdrToneMappingEnabled(0)
5352
, _log(Logger::getInstance(grabberName.toUpper()))
5453
, _currentFrame(0)
5554
, _deviceName()
@@ -70,7 +69,6 @@ Grabber::Grabber(const QString& configurationPath, const QString& grabberName)
7069
, _actualFPS(0)
7170
, _actualDeviceName("")
7271
, _targetMonitorNits(200)
73-
, _lutBufferInit(false)
7472
, _lineLength(-1)
7573
, _frameByteSize(-1)
7674
, _signalDetectionEnabled(false)
@@ -410,100 +408,6 @@ int Grabber::getHdrToneMappingEnabled()
410408
return _hdrToneMappingEnabled;
411409
}
412410

413-
void Grabber::loadLutFile(PixelFormat color, const QList<QString>& files)
414-
{
415-
bool is_yuv = (color == PixelFormat::YUYV);
416-
417-
_lutBufferInit = false;
418-
419-
if (color != PixelFormat::NO_CHANGE && color != PixelFormat::RGB24 && color != PixelFormat::YUYV)
420-
{
421-
Error(_log, "Unsupported mode for loading LUT table: %s", QSTRING_CSTR(pixelFormatToString(color)));
422-
return;
423-
}
424-
425-
if (color == PixelFormat::NO_CHANGE)
426-
{
427-
_lut.resize(LUT_FILE_SIZE + 4);
428-
429-
if (_lut.data() != nullptr)
430-
{
431-
for (int y = 0; y < 256; y++)
432-
for (int u = 0; u < 256; u++)
433-
for (int v = 0; v < 256; v++)
434-
{
435-
uint32_t ind_lutd = LUT_INDEX(y, u, v);
436-
ColorRgb::yuv2rgb(y, u, v,
437-
_lut.data()[ind_lutd],
438-
_lut.data()[ind_lutd + 1],
439-
_lut.data()[ind_lutd + 2]);
440-
}
441-
_lutBufferInit = true;
442-
}
443-
444-
Error(_log, "You have forgotten to put lut_lin_tables.3d file in the HyperHDR configuration folder. Internal LUT table for YUV conversion has been created instead.");
445-
return;
446-
}
447-
448-
if (_hdrToneMappingEnabled || is_yuv)
449-
{
450-
for (QString fileName3d : files)
451-
{
452-
QFile file(fileName3d);
453-
454-
if (file.open(QIODevice::ReadOnly))
455-
{
456-
size_t length;
457-
Debug(_log, "LUT file found: %s", QSTRING_CSTR(fileName3d));
458-
459-
length = file.size();
460-
461-
if (length == LUT_FILE_SIZE * 3)
462-
{
463-
qint64 index = 0;
464-
465-
if (is_yuv && _hdrToneMappingEnabled)
466-
{
467-
Debug(_log, "Index 1 for HDR YUV");
468-
index = LUT_FILE_SIZE;
469-
}
470-
else if (is_yuv)
471-
{
472-
Debug(_log, "Index 2 for YUV");
473-
index = LUT_FILE_SIZE * 2;
474-
}
475-
else
476-
Debug(_log, "Index 0 for HDR RGB");
477-
478-
file.seek(index);
479-
480-
_lut.resize(LUT_FILE_SIZE + 64);
481-
482-
if (file.read((char*)_lut.data(), LUT_FILE_SIZE) != LUT_FILE_SIZE)
483-
{
484-
Error(_log, "Error reading LUT file %s", QSTRING_CSTR(fileName3d));
485-
}
486-
else
487-
{
488-
_lutBufferInit = true;
489-
Info(_log, "Found and loaded LUT: '%s'", QSTRING_CSTR(fileName3d));
490-
}
491-
}
492-
else
493-
Error(_log, "LUT file has invalid length: %i %s. Please generate new one LUT table using the generator page.", length, QSTRING_CSTR(fileName3d));
494-
495-
file.close();
496-
497-
return;
498-
}
499-
else
500-
Warning(_log, "LUT file is not found here: %s", QSTRING_CSTR(fileName3d));
501-
}
502-
503-
Error(_log, "Could not find any required LUT file");
504-
}
505-
}
506-
507411
QMap<Grabber::VideoControls, int> Grabber::getVideoDeviceControls(const QString& devicePath)
508412
{
509413
QMap<Grabber::VideoControls, int> retVal;

Diff for: sources/flatbuffers/parser/FlatBuffersParser.cpp

+33-10
Original file line numberDiff line numberDiff line change
@@ -138,10 +138,10 @@ static void sendErrorReply(flatbuffers::FlatBufferBuilder* _builder, const char*
138138
_builder->Finish(reply);
139139
}
140140

141-
int FlatBuffersParser::decodeIncomingFlatbuffersFrame(void* builder, const uint8_t* messageData, size_t messageSize,
142-
uint8_t* red, uint8_t* green, uint8_t* blue,
141+
int FlatBuffersParser::decodeIncomingFlatbuffersFrame(void* builder, const uint8_t* messageData, size_t messageSize,
143142
int* priority, std::string* clientDescription, int* duration,
144-
uint8_t** imageData, int* imageWidth, int* imageHeight, size_t* imageSize,
143+
FlatbuffersTransientImage& image,
144+
FlatbuffersColor& color,
145145
uint8_t** buffer, size_t* bufferSize)
146146
{
147147
int retType = FLATBUFFERS_PACKAGE_TYPE::ERROR;
@@ -158,9 +158,9 @@ int FlatBuffersParser::decodeIncomingFlatbuffersFrame(void* builder, const uint8
158158
auto colorReq = static_cast<const hyperhdrnet::Color*>(reqPtr);
159159
const int32_t rgbData = colorReq->data();
160160

161-
*red = uint8_t((rgbData >> 16) & 0xff);
162-
*green = uint8_t((rgbData >> 8) & 0xff);
163-
*blue = uint8_t(rgbData & 0xff);
161+
color.red = uint8_t((rgbData >> 16) & 0xff);
162+
color.green = uint8_t((rgbData >> 8) & 0xff);
163+
color.blue = uint8_t(rgbData & 0xff);
164164
*duration = colorReq->duration();
165165

166166
retType = FLATBUFFERS_PACKAGE_TYPE::COLOR;
@@ -177,10 +177,33 @@ int FlatBuffersParser::decodeIncomingFlatbuffersFrame(void* builder, const uint8
177177
const auto* img = static_cast<const hyperhdrnet::RawImage*>(rawFlatImage);
178178
const auto& imgD = img->data();
179179

180-
*imageData = const_cast<uint8_t*>(imgD->data());
181-
*imageSize = imgD->size();
182-
*imageWidth = img->width();
183-
*imageHeight = img->height();
180+
image.format = FLATBUFFERS_IMAGE_FORMAT::RGB;
181+
image.firstPlane.data = const_cast<uint8_t*>(imgD->data());
182+
image.firstPlane.size = static_cast<int>(imgD->size());
183+
image.size = imgD->size();
184+
image.width = img->width();
185+
image.height = img->height();
186+
187+
retType = FLATBUFFERS_PACKAGE_TYPE::IMAGE;
188+
auto reply = hyperhdrnet::CreateReplyDirect(*_builder, nullptr, -1, *priority);
189+
_builder->Finish(reply);
190+
}
191+
else if ((rawFlatImage = flatImage->data_as_NV12Image()) != nullptr)
192+
{
193+
const auto* img = static_cast<const hyperhdrnet::NV12Image*>(rawFlatImage);
194+
const auto& imgD = img->data_y();
195+
const auto& imgUvD = img->data_uv();
196+
197+
image.format = FLATBUFFERS_IMAGE_FORMAT::NV12;
198+
image.firstPlane.data = const_cast<uint8_t*>(imgD->data());
199+
image.firstPlane.size = static_cast<int>(imgD->size());
200+
image.firstPlane.stride = img->stride_y();
201+
image.secondPlane.data = const_cast<uint8_t*>(imgUvD->data());
202+
image.secondPlane.size = static_cast<int>(imgUvD->size());
203+
image.secondPlane.stride = img->stride_uv();
204+
image.size = imgD->size() + imgUvD->size();
205+
image.width = img->width();
206+
image.height = img->height();
184207

185208
retType = FLATBUFFERS_PACKAGE_TYPE::IMAGE;
186209
auto reply = hyperhdrnet::CreateReplyDirect(*_builder, nullptr, -1, *priority);

0 commit comments

Comments
 (0)