Commit 6d0e2fbc by Ludmány Balázs

Use libjpeg directly

parent bd050424
......@@ -19,7 +19,7 @@ QML_IMPORT_PATH =
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
DEPENDPATH += $$PWD/../libvnc
......
<?xml version="1.0" encoding="UTF-8"?>
<!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>
<data>
<variable>EnvironmentId</variable>
......
......@@ -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)
{
Dispatcher *dispatcher = static_cast<Dispatcher *>(rfbClientGetClientData(client, 0));
Jpeg *jpeg = new Jpeg(QByteArray::fromRawData((const char *) buffer, length),
dispatcher->uploader()->gotJpeg(x, y, w, h));
Jpeg *jpeg = new Jpeg((unsigned char*)buffer, length, dispatcher->uploader()->gotJpeg(x, y, w, h));
dispatcher->queue()->enqueue(jpeg);
return TRUE;
}
......
......@@ -4,5 +4,5 @@ varying highp vec3 varcolor;
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"
JpegDecoder::JpegDecoder(ConcurrentQueue<Jpeg *, 64u> *queue, QObject *parent) :
QObject(parent), m_queue(queue)
{
......@@ -10,9 +12,36 @@ void JpegDecoder::operate()
Jpeg *jpeg;
forever {
jpeg = m_queue->dequeue();
QImage image;
image.loadFromData(jpeg->data, "JPEG");
emit finished(image, image.width(), image.height(), jpeg->index);
struct jpeg_decompress_struct cinfo;
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 rows;
jpeg_destroy_decompress(&cinfo);
}
}
......@@ -2,28 +2,29 @@
#define JPEGDECODER_H
#include <QObject>
#include <QByteArray>
#include <QPoint>
#include <QSize>
#include <QImage>
#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"
struct Jpeg {
Jpeg(const QByteArray &d, const int i) :
data(d), index(i)
struct Jpeg
{
Jpeg(uint8_t *d, const int l, const int i) :
data(d), length(l), index(i)
{
}
~Jpeg()
{
// QByteArray::fromRawData: " QByteArray does not take ownership of data,
// so the QByteArray destructor will never delete the raw data,
// even when the last QByteArray referring to data is destroyed."
delete[] data.constData();
delete[] data;
}
QByteArray data;
uint8_t *data;
int length;
int index;
};
......@@ -39,9 +40,25 @@ public:
JpegDecoder(ConcurrentQueue<Jpeg*, 64u> *queue, QObject *parent = 0);
ConcurrentQueue<Jpeg*, 64u> *m_queue;
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:
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
#ifndef VNC_H
#define VNC_H
#define DECODER_COUNT 2
#define DECODER_COUNT 64
#include <QQuickWindow>
#include <QObject>
......
......@@ -223,7 +223,7 @@ int Uploader::gotJpeg(const quint32 x, const quint32 y, const quint32 width, con
GLuint id;
m_functions->glGenTextures(1, &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);
float bottom = (float) height / (float) real_height;
......@@ -273,12 +273,13 @@ int Uploader::gotJpeg(const quint32 x, const quint32 y, const quint32 width, con
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_functions->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
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) {
m_functions->glBindTexture(GL_TEXTURE_2D, 0);
m_functions->glFinish();
......
......@@ -69,7 +69,7 @@ public slots:
void createContext(QOpenGLContext *context);
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
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