Flatbuffer/Protobuf now able to receive rgba data (#1399)

* Flatbuffer/Protobuf now able to receive rgba data

* Proto/Flat schema comment added

* Prevent diveded by zero

* Address LGTM findings

* Fix EncoderThread & cleanup

Co-authored-by: LordGrey <lordgrey.emmel@gmail.com>
This commit is contained in:
Markus
2022-01-09 17:23:50 +01:00
committed by GitHub
parent 2f573a117f
commit 98654e48f6
11 changed files with 97 additions and 34 deletions

View File

@@ -152,15 +152,36 @@ void FlatBufferClient::handleImageCommand(const hyperionnet::Image *image)
const int width = img->width();
const int height = img->height();
if ((int) imageData->size() != width*height*3)
if (width <= 0 || height <= 0)
{
sendErrorReply("Size of image data does not match with the width and height");
return;
}
Image<ColorRgb> imageDest(width, height);
memmove(imageDest.memptr(), imageData->data(), imageData->size());
emit setGlobalInputImage(_priority, imageDest, duration);
// check consistency of the size of the received data
int channelCount = (int)imageData->size()/(width*height);
if (channelCount != 3 && channelCount != 4)
{
sendErrorReply("Size of image data does not match with the width and height");
return;
}
// create ImageRgb
Image<ColorRgb> imageRGB(width, height);
if (channelCount == 3)
{
memmove(imageRGB.memptr(), imageData->data(), imageData->size());
}
if (channelCount == 4)
{
for (int source=0, destination=0; source < width * height * static_cast<int>(sizeof(ColorRgb)); source+=sizeof(ColorRgb), destination+=sizeof(ColorRgba))
{
memmove((uint8_t*)imageRGB.memptr() + source, imageData->data() + destination, sizeof(ColorRgb));
}
}
emit setGlobalInputImage(_priority, imageRGB, duration);
}
// send reply

View File

@@ -4,6 +4,7 @@
#include <utils/Logger.h>
#include <utils/Image.h>
#include <utils/ColorRgb.h>
#include <utils/ColorRgba.h>
#include <utils/Components.h>
// flatbuffer FBS

View File

@@ -14,6 +14,7 @@ table RawImage {
union ImageType {RawImage}
// Either RGB or RGBA data can be transferred
table Image {
data:ImageType (required);
duration:int = -1;

View File

@@ -22,12 +22,15 @@ EncoderThread::~EncoderThread()
tjDestroy(_decompress);
#endif
if (_localData)
if (_localData != nullptr)
{
#ifdef HAVE_TURBO_JPEG
tjFree(_localData);
#else
delete[] _localData;
#endif
_localData = nullptr;
}
}
void EncoderThread::setup(
@@ -55,14 +58,18 @@ void EncoderThread::setup(
_imageResampler.setVerticalPixelDecimation(_pixelDecimation);
#ifdef HAVE_TURBO_JPEG
if (_localData)
if (_localData != nullptr)
tjFree(_localData);
_localData = (uint8_t*)tjAlloc(size + 1);
#else
delete[] _localData;
_localData = nullptr;
_localData = new uint8_t(size + 1);
if (_localData != nullptr)
{
delete[] _localData;
_localData = nullptr;
}
_localData = new uint8_t[size];
#endif
memcpy(_localData, sharedData, size);
@@ -177,23 +184,20 @@ void EncoderThread::processImageMjpeg()
else
{
// calculate the output size
int outputWidth = (_width - _cropLeft - _cropRight);
int outputHeight = (_height - _cropTop - _cropBottom);
int outputWidth = (scaledWidth - _cropLeft - _cropRight);
int outputHeight = (scaledHeight - _cropTop - _cropBottom);
if (outputWidth <= 0 || outputHeight <= 0)
{
emit newFrame(srcImage);
return;
}
Image<ColorRgb> destImage(outputWidth, outputHeight);
for (unsigned int y = 0; y < destImage.height(); y++)
{
unsigned char* source = (unsigned char*)srcImage.memptr() + (y + _cropTop)*srcImage.width()*3 + _cropLeft*3;
unsigned char* dest = (unsigned char*)destImage.memptr() + y*destImage.width()*3;
memcpy(dest, source, destImage.width()*3);
free(source);
source = nullptr;
free(dest);
dest = nullptr;
memcpy((unsigned char*)destImage.memptr() + y * destImage.width() * 3, (unsigned char*)srcImage.memptr() + (y + _cropTop) * srcImage.width() * 3 + _cropLeft * 3, destImage.width() * 3);
}
// emit

View File

@@ -529,7 +529,11 @@ void MFGrabber::process_image(const void *frameImageBuffer, int size)
return;
// We do want a new frame...
#ifdef HAVE_TURBO_JPEG
if (size < _frameByteSize && _pixelFormat != PixelFormat::MJPEG)
#else
if (size < _frameByteSize)
#endif
Error(_log, "Frame too small: %d != %d", size, _frameByteSize);
else if (_threadManager != nullptr)
{

View File

@@ -30,7 +30,9 @@ static PixelFormat GetPixelFormatForGuid(const GUID guid)
if (IsEqualGUID(guid, MFVideoFormat_RGB24)) return PixelFormat::BGR24;
if (IsEqualGUID(guid, MFVideoFormat_YUY2)) return PixelFormat::YUYV;
if (IsEqualGUID(guid, MFVideoFormat_UYVY)) return PixelFormat::UYVY;
#ifdef HAVE_TURBO_JPEG
if (IsEqualGUID(guid, MFVideoFormat_MJPG)) return PixelFormat::MJPEG;
#endif
if (IsEqualGUID(guid, MFVideoFormat_NV12)) return PixelFormat::NV12;
if (IsEqualGUID(guid, MFVideoFormat_I420)) return PixelFormat::I420;
return PixelFormat::NO_CHANGE;
@@ -142,7 +144,11 @@ public:
goto done;
}
#ifdef HAVE_TURBO_JPEG
if (_pixelformat != PixelFormat::MJPEG && _pixelformat != PixelFormat::BGR24 && _pixelformat != PixelFormat::NO_CHANGE)
#else
if (_pixelformat != PixelFormat::BGR24 && _pixelformat != PixelFormat::NO_CHANGE)
#endif
pSample = TransformSample(_transform, pSample);
_hrStatus = pSample->ConvertToContiguousBuffer(&buffer);
@@ -174,7 +180,11 @@ public:
if (MF_SOURCE_READERF_ENDOFSTREAM & dwStreamFlags)
_bEOS = TRUE; // Reached the end of the stream.
#ifdef HAVE_TURBO_JPEG
if (_pixelformat != PixelFormat::MJPEG && _pixelformat != PixelFormat::BGR24 && _pixelformat != PixelFormat::NO_CHANGE)
#else
if (_pixelformat != PixelFormat::BGR24 && _pixelformat != PixelFormat::NO_CHANGE)
#endif
SAFE_RELEASE(pSample);
_isBusy = false;
@@ -185,7 +195,11 @@ public:
HRESULT InitializeVideoEncoder(IMFMediaType* type, PixelFormat format)
{
_pixelformat = format;
#ifdef HAVE_TURBO_JPEG
if (format == PixelFormat::MJPEG || format == PixelFormat::BGR24 || format == PixelFormat::NO_CHANGE)
#else
if (format == PixelFormat::BGR24 || format == PixelFormat::NO_CHANGE)
#endif
return S_OK;
// Variable declaration

View File

@@ -168,18 +168,36 @@ void ProtoClientConnection::handleImageCommand(const proto::ImageRequest &messag
_priority = priority;
}
if (width <= 0 || height <= 0)
{
sendErrorReply("Size of image data does not match with the width and height");
return;
}
// check consistency of the size of the received data
if ((int) imageData.size() != width*height*3)
int channelCount = (int)imageData.size()/(width*height);
if (channelCount != 3 && channelCount != 4)
{
sendErrorReply("Size of image data does not match with the width and height");
return;
}
// create ImageRgb
Image<ColorRgb> image(width, height);
memcpy(image.memptr(), imageData.c_str(), imageData.size());
Image<ColorRgb> imageRGB(width, height);
if (channelCount == 3)
{
memmove(imageRGB.memptr(), imageData.c_str(), imageData.size());
}
emit setGlobalInputImage(_priority, image, duration);
if (channelCount == 4)
{
for (int source=0, destination=0; source < width * height * static_cast<int>(sizeof(ColorRgb)); source+=sizeof(ColorRgb), destination+=sizeof(ColorRgba))
{
memmove((uint8_t*)imageRGB.memptr() + source, imageData.c_str() + destination, sizeof(ColorRgb));
}
}
emit setGlobalInputImage(_priority, imageRGB, duration);
// send reply
sendSuccessReply();

View File

@@ -9,6 +9,7 @@
#include <utils/Logger.h>
#include <utils/Image.h>
#include <utils/ColorRgb.h>
#include <utils/ColorRgba.h>
#include <utils/Components.h>
class QTcpSocket;

View File

@@ -45,7 +45,7 @@ message ImageRequest {
// height of the image
required int32 imageheight = 3;
// image data
// image data (either RGB or RGBA data can be transferred)
required bytes imagedata = 4;
// duration of the request (negative results in infinite)