Commit 6d0e2fbc by Ludmány Balázs

Use libjpeg directly

parent bd050424
...@@ -19,7 +19,7 @@ QML_IMPORT_PATH = ...@@ -19,7 +19,7 @@ QML_IMPORT_PATH =
include(deployment.pri) include(deployment.pri)
unix|win32: LIBS += -L$$PWD/../libvnc/libvncclient/.libs/ -lvncclient -lEGL unix|win32: LIBS += -L$$PWD/../libvnc/libvncclient/.libs/ -lvncclient -lEGL -ljpeg
INCLUDEPATH += $$PWD/../libvnc INCLUDEPATH += $$PWD/../libvnc
DEPENDPATH += $$PWD/../libvnc DEPENDPATH += $$PWD/../libvnc
......
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject> <!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 3.5.1, 2016-07-19T13:32:08. --> <!-- Written by QtCreator 3.5.1, 2016-07-20T14:21:50. -->
<qtcreator> <qtcreator>
<data> <data>
<variable>EnvironmentId</variable> <variable>EnvironmentId</variable>
......
...@@ -37,8 +37,7 @@ void Dispatcher::GotBitmap(rfbClient *client, const uint8_t *buffer, int x, int ...@@ -37,8 +37,7 @@ void Dispatcher::GotBitmap(rfbClient *client, const uint8_t *buffer, int x, int
rfbBool Dispatcher::GotJpeg(rfbClient *client, const uint8_t *buffer, int length, int x, int y, int w, int h) rfbBool Dispatcher::GotJpeg(rfbClient *client, const uint8_t *buffer, int length, int x, int y, int w, int h)
{ {
Dispatcher *dispatcher = static_cast<Dispatcher *>(rfbClientGetClientData(client, 0)); Dispatcher *dispatcher = static_cast<Dispatcher *>(rfbClientGetClientData(client, 0));
Jpeg *jpeg = new Jpeg(QByteArray::fromRawData((const char *) buffer, length), Jpeg *jpeg = new Jpeg((unsigned char*)buffer, length, dispatcher->uploader()->gotJpeg(x, y, w, h));
dispatcher->uploader()->gotJpeg(x, y, w, h));
dispatcher->queue()->enqueue(jpeg); dispatcher->queue()->enqueue(jpeg);
return TRUE; return TRUE;
} }
......
...@@ -4,5 +4,5 @@ varying highp vec3 varcolor; ...@@ -4,5 +4,5 @@ varying highp vec3 varcolor;
void main(void) void main(void)
{ {
gl_FragColor = vec4(texture2D(texture, vartexcoord).bgr + varcolor, 1.0); gl_FragColor = vec4(texture2D(texture, vartexcoord).rgb + varcolor, 1.0);
} }
#include "jpegdecoder.h" #include "jpegdecoder.h"
JpegDecoder::JpegDecoder(ConcurrentQueue<Jpeg *, 64u> *queue, QObject *parent) : JpegDecoder::JpegDecoder(ConcurrentQueue<Jpeg *, 64u> *queue, QObject *parent) :
QObject(parent), m_queue(queue) QObject(parent), m_queue(queue)
{ {
...@@ -10,9 +12,36 @@ void JpegDecoder::operate() ...@@ -10,9 +12,36 @@ void JpegDecoder::operate()
Jpeg *jpeg; Jpeg *jpeg;
forever { forever {
jpeg = m_queue->dequeue(); jpeg = m_queue->dequeue();
QImage image;
image.loadFromData(jpeg->data, "JPEG"); struct jpeg_decompress_struct cinfo;
emit finished(image, image.width(), image.height(), jpeg->index); struct error_mgr jerr;
cinfo.err = jpeg_std_error(&jerr.mgr);
jerr.mgr.error_exit = error_exit;
if (setjmp(jerr.setjmp_buffer)) {
jpeg_destroy_decompress(&cinfo);
return;
}
jpeg_create_decompress(&cinfo);
cinfo.do_fancy_upsampling = TRUE;
cinfo.dct_method = JDCT_IFAST;
jpeg_mem_src(&cinfo, jpeg->data, jpeg->length);
(void) jpeg_read_header(&cinfo, TRUE);
(void) jpeg_start_decompress(&cinfo);
JSAMPLE *samples = new JSAMPLE[cinfo.output_width * cinfo.output_height * cinfo.output_components];
JSAMPROW *rows = new JSAMPROW[cinfo.output_height * cinfo.output_components];
for(size_t i = 0; i < cinfo.output_height; i++) {
rows[i] = samples + (i * cinfo.output_width * cinfo.output_components);
}
while (cinfo.output_scanline < cinfo.output_height) {
jpeg_read_scanlines(&cinfo, rows + cinfo.output_scanline, 1);
}
(void) jpeg_finish_decompress(&cinfo);
emit finished(samples, cinfo.output_width, cinfo.output_height, jpeg->index);
delete jpeg; delete jpeg;
delete rows;
jpeg_destroy_decompress(&cinfo);
} }
} }
...@@ -2,28 +2,29 @@ ...@@ -2,28 +2,29 @@
#define JPEGDECODER_H #define JPEGDECODER_H
#include <QObject> #include <QObject>
#include <QByteArray>
#include <QPoint>
#include <QSize>
#include <QImage>
#include <QDebug> #include <QDebug>
// jpeglib requires stdlib.h
#include <stdio.h>
#include <jpeglib.h>
// setjmp.h is required for error handling
#include <setjmp.h>
#include "concurrentqueue.h" #include "concurrentqueue.h"
struct Jpeg { struct Jpeg
Jpeg(const QByteArray &d, const int i) : {
data(d), index(i) Jpeg(uint8_t *d, const int l, const int i) :
data(d), length(l), index(i)
{ {
} }
~Jpeg() ~Jpeg()
{ {
// QByteArray::fromRawData: " QByteArray does not take ownership of data, delete[] data;
// so the QByteArray destructor will never delete the raw data,
// even when the last QByteArray referring to data is destroyed."
delete[] data.constData();
} }
QByteArray data; uint8_t *data;
int length;
int index; int index;
}; };
...@@ -39,9 +40,25 @@ public: ...@@ -39,9 +40,25 @@ public:
JpegDecoder(ConcurrentQueue<Jpeg*, 64u> *queue, QObject *parent = 0); JpegDecoder(ConcurrentQueue<Jpeg*, 64u> *queue, QObject *parent = 0);
ConcurrentQueue<Jpeg*, 64u> *m_queue; ConcurrentQueue<Jpeg*, 64u> *m_queue;
signals: signals:
void finished(const QImage &image, const int width, const int height, const int index); void finished(const unsigned char *image, const int width, const int height, const int index);
public slots: public slots:
void operate(); void operate();
}; };
struct error_mgr
{
struct jpeg_error_mgr mgr;
jmp_buf setjmp_buffer;
};
typedef struct error_mgr* error_ptr;
METHODDEF(void)
error_exit (j_common_ptr cinfo)
{
error_ptr myerr = (error_ptr) cinfo->err;
(*cinfo->err->output_message) (cinfo);
longjmp(myerr->setjmp_buffer, 1);
}
#endif // JPEGDECODER_H #endif // JPEGDECODER_H
#ifndef VNC_H #ifndef VNC_H
#define VNC_H #define VNC_H
#define DECODER_COUNT 2 #define DECODER_COUNT 64
#include <QQuickWindow> #include <QQuickWindow>
#include <QObject> #include <QObject>
......
...@@ -223,7 +223,7 @@ int Uploader::gotJpeg(const quint32 x, const quint32 y, const quint32 width, con ...@@ -223,7 +223,7 @@ int Uploader::gotJpeg(const quint32 x, const quint32 y, const quint32 width, con
GLuint id; GLuint id;
m_functions->glGenTextures(1, &id); m_functions->glGenTextures(1, &id);
m_functions->glBindTexture(GL_TEXTURE_2D, id); m_functions->glBindTexture(GL_TEXTURE_2D, id);
m_functions->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, real_width, real_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); m_functions->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, real_width, real_height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
m_textures->append(id); m_textures->append(id);
float bottom = (float) height / (float) real_height; float bottom = (float) height / (float) real_height;
...@@ -273,12 +273,13 @@ int Uploader::gotJpeg(const quint32 x, const quint32 y, const quint32 width, con ...@@ -273,12 +273,13 @@ int Uploader::gotJpeg(const quint32 x, const quint32 y, const quint32 width, con
return m_textures->size() - 1; return m_textures->size() - 1;
} }
void Uploader::finishedJpeg(const QImage &image, const quint32 width, const quint32 height, const int index) void Uploader::finishedJpeg(const unsigned char *image, const quint32 width, const quint32 height, const int index)
{ {
m_jpegs--; m_jpegs--;
m_functions->glPixelStorei(GL_UNPACK_ALIGNMENT, 1); m_functions->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
m_functions->glBindTexture(GL_TEXTURE_2D, m_textures->at(index)); m_functions->glBindTexture(GL_TEXTURE_2D, m_textures->at(index));
m_functions->glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, image.constBits()); m_functions->glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, image);
delete[] image;
if(m_jpegs == 0 && m_finished) { if(m_jpegs == 0 && m_finished) {
m_functions->glBindTexture(GL_TEXTURE_2D, 0); m_functions->glBindTexture(GL_TEXTURE_2D, 0);
m_functions->glFinish(); m_functions->glFinish();
......
...@@ -69,7 +69,7 @@ public slots: ...@@ -69,7 +69,7 @@ public slots:
void createContext(QOpenGLContext *context); void createContext(QOpenGLContext *context);
void cleanup(); void cleanup();
void finishedJpeg(const QImage &image, const quint32 width, const quint32 height, int index); void finishedJpeg(const unsigned char *image, const quint32 width, const quint32 height, int index);
}; };
#endif // UPLOADER_H #endif // UPLOADER_H
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment