135 lines
4.8 KiB
C++
135 lines
4.8 KiB
C++
/****************************************************************************
|
|
* Copyright (C) 2018 Maschell
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
****************************************************************************/
|
|
|
|
#include <vector>
|
|
#include "EncodingHelper.h"
|
|
#include "MJPEGStreamServer.hpp"
|
|
#include "stream_utils.h"
|
|
#include "JpegInformation.h"
|
|
#include <gx2/event.h>
|
|
#include <gx2/surface.h>
|
|
#include <gx2/mem.h>
|
|
|
|
EncodingHelper *EncodingHelper::instance = NULL;
|
|
|
|
OSMessageQueue encodeQueue __attribute__((section(".data")));
|
|
OSMessage encodeQueueMessages[ENCODE_QUEUE_MESSAGE_COUNT] __attribute__((section(".data")));
|
|
|
|
void EncodingHelper::StartAsyncThread() {
|
|
int32_t priority = 17;
|
|
this->pThread = CThread::create(DoAsyncThread, this, CThread::eAttributeAffCore0, priority,0x40000);
|
|
this->pThread->resumeThread();
|
|
}
|
|
|
|
void EncodingHelper::DoAsyncThread(CThread *thread, void *arg) {
|
|
EncodingHelper * arg_instance = (EncodingHelper *) arg;
|
|
return arg_instance->DoAsyncThreadInternal(thread);
|
|
}
|
|
|
|
|
|
JpegInformation * convertToJpeg(uint8_t * sourceBuffer, uint32_t width, uint32_t height, uint32_t pitch, uint32_t format, int quality) {
|
|
if(sourceBuffer == NULL) {
|
|
DEBUG_FUNCTION_LINE("path or buffer NULL\n");
|
|
return NULL;
|
|
}
|
|
if(( format != GX2_SURFACE_FORMAT_SRGB_R8_G8_B8_A8 &&
|
|
format != GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8)) {
|
|
DEBUG_FUNCTION_LINE("Format not supported\n");
|
|
return NULL;
|
|
}
|
|
|
|
tjhandle handle = tjInitCompress();
|
|
|
|
if(handle == NULL) {
|
|
const char *err = (const char *) tjGetErrorStr();
|
|
DEBUG_FUNCTION_LINE("TJ Error: %s UNABLE TO INIT TJ Compressor Object\n",err);
|
|
return NULL;
|
|
}
|
|
|
|
int jpegQual = quality;
|
|
int nbands = 4;
|
|
int flags = 0;
|
|
unsigned char* jpegBuf = NULL;
|
|
|
|
int pixelFormat = TJPF_GRAY;
|
|
int jpegSubsamp = TJSAMP_GRAY;
|
|
if(nbands == 4) {
|
|
pixelFormat = TJPF_RGBA;
|
|
jpegSubsamp = TJSAMP_411;
|
|
}
|
|
unsigned long jpegSize = 0;
|
|
|
|
int tj_stat = tjCompress2( handle, sourceBuffer, width, pitch * nbands, height, pixelFormat, &(jpegBuf), &jpegSize, jpegSubsamp, jpegQual, flags);
|
|
if(tj_stat != 0) {
|
|
const char *err = (const char *) tjGetErrorStr();
|
|
DEBUG_FUNCTION_LINE("TurboJPEG Error: %s UNABLE TO COMPRESS JPEG IMAGE\n", err);
|
|
tjDestroy(handle);
|
|
} else {
|
|
return new JpegInformation(handle, jpegBuf, jpegSize);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void EncodingHelper::DoAsyncThreadInternal(CThread *thread) {
|
|
serverRunning = true;
|
|
|
|
OSMessage message;
|
|
GX2ColorBuffer * colorBuffer = NULL;
|
|
shouldExit = false;
|
|
while(true) {
|
|
//DEBUG_FUNCTION_LINE("Waiting for message in EncoderHelper\n");
|
|
if(!OSReceiveMessage(&encodeQueue,&message,OS_MESSAGE_FLAGS_NONE)) {
|
|
//DEBUG_FUNCTION_LINE("... %08X\n",this->shouldExit);
|
|
if(this->shouldExit) {
|
|
DEBUG_FUNCTION_LINE("We should stop\n");
|
|
break;
|
|
}
|
|
OSSleepTicks(OSMicrosecondsToTicks(5000));
|
|
continue;
|
|
}
|
|
DCFlushRange(&message,sizeof(OSMessage));
|
|
|
|
//DEBUG_FUNCTION_LINE("Received message %08X: data1 %08X\n",message.message,message.args[1]);
|
|
if((uint32_t) message.message == 0xDEADBEEF) {
|
|
//DEBUG_FUNCTION_LINE("We should stop the server\n");
|
|
break;
|
|
}
|
|
|
|
colorBuffer = (GX2ColorBuffer *) message.args[1];
|
|
|
|
JpegInformation * info = convertToJpeg((uint8_t*) colorBuffer->surface.image,colorBuffer->surface.width,colorBuffer->surface.height,colorBuffer->surface.pitch,colorBuffer->surface.format,85);
|
|
|
|
if(info != NULL ) {
|
|
MJPEGStreamServer::getInstance()->streamJPEG(info);
|
|
}
|
|
|
|
//DEBUG_FUNCTION_LINE("We can now kill the colorBuffer\n",colorBuffer);
|
|
if(colorBuffer->surface.image != NULL) {
|
|
free(colorBuffer->surface.image);
|
|
colorBuffer->surface.image = NULL;
|
|
//DEBUG_FUNCTION_LINE("Free image data for %08X\n",colorBuffer);
|
|
}
|
|
free(colorBuffer);
|
|
colorBuffer = NULL;
|
|
//DEBUG_FUNCTION_LINE("Encoding Done.\n");
|
|
}
|
|
DEBUG_FUNCTION_LINE("Server not running anymore\n");
|
|
serverRunning = false;
|
|
DCFlushRange((void*)&serverRunning,sizeof(serverRunning));
|
|
}
|