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:
		
							
								
								
									
										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) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user