mirror of
https://github.com/hyperion-project/hyperion.ng.git
synced 2025-03-01 10:33:28 +00:00
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:
parent
2f573a117f
commit
98654e48f6
20
README.md
20
README.md
@ -1,13 +1,13 @@
|
||||

|
||||

|
||||
|
||||
[](https://github.com/hyperion-project/hyperion.ng/releases)
|
||||
[](https://github.com/hyperion-project/hyperion.ng/releases)
|
||||
[](https://github.com/hyperion-project/hyperion.ng/actions)
|
||||
[](https://lgtm.com/projects/g/hyperion-project/hyperion.ng/alerts/)
|
||||
[](https://www.hyperion-project.org)
|
||||
[](https://docs.hyperion-project.org)
|
||||
[](https://discord.gg/khkR8Vx3ff)
|
||||

|
||||
[](https://lgtm.com/projects/g/hyperion-project/hyperion.ng/alerts/)
|
||||
[](https://www.hyperion-project.org)
|
||||
[](https://docs.hyperion-project.org)
|
||||
[](https://discord.gg/khkR8Vx3ff)
|
||||

|
||||
|
||||
## About Hyperion
|
||||
|
||||
@ -26,15 +26,15 @@
|
||||
* A multi language web interface to configure and remote control hyperion
|
||||
|
||||
If you need further support please open a topic at the forum!<br>
|
||||
[](https://www.hyperion-project.org)
|
||||
[](https://www.hyperion-project.org)
|
||||
|
||||
## Contributing
|
||||
|
||||
Contributions are welcome! Feel free to join us! We are looking always for people who wants to participate.<br>
|
||||
[](https://github.com/hyperion-project/hyperion.ng/graphs/contributors)
|
||||
[](https://github.com/hyperion-project/hyperion.ng/graphs/contributors)
|
||||
|
||||
For an example, you can participate in the translation.<br>
|
||||
[](https://poeditor.com/join/project/Y4F6vHRFjA)
|
||||
[](https://poeditor.com/join/project/Y4F6vHRFjA)
|
||||
|
||||
## Supported Platforms
|
||||
|
||||
@ -47,7 +47,7 @@ Covers these topics:
|
||||
- [Effect development](https://docs.hyperion-project.org/en/effects/#effect-files)
|
||||
- [JSON API](https://docs.hyperion-project.org/en/json/)
|
||||
|
||||
[](https://docs.hyperion-project.org)
|
||||
[](https://docs.hyperion-project.org)
|
||||
|
||||
## Changelog
|
||||
Released and unreleased changes at [CHANGELOG.md](CHANGELOG.md)
|
||||
|
@ -30,7 +30,6 @@ body{
|
||||
padding-right: 10px;
|
||||
}
|
||||
.navbar-brand{
|
||||
position:fixed;
|
||||
height: 80px;
|
||||
}
|
||||
#main-nav{
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user