mirror of https://github.com/tp4a/teleport
按优化后的RDP录像格式进行播放,功能完成。
parent
8ef5cfe118
commit
41fa960afc
|
@ -214,8 +214,8 @@ void MainWindow::_do_update_data(UpdateData* dat) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if(dat->data_type() == TYPE_IMAGE) {
|
else if(dat->data_type() == TYPE_IMAGE) {
|
||||||
UpdateImages uimgs;
|
const UpdateImages uimgs = dat->get_images();
|
||||||
if(!dat->get_images(uimgs))
|
if(uimgs.size() == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(uimgs.size() > 1) {
|
if(uimgs.size() > 1) {
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#define TS_RDP_BTN_PRESSED 1
|
#define TS_RDP_BTN_PRESSED 1
|
||||||
#define TS_RDP_IMG_RAW 0 // 未压缩,原始数据(根据bitsPerPixel,多个字节对应一个点的颜色)
|
#define TS_RDP_IMG_RAW 0 // 未压缩,原始数据(根据bitsPerPixel,多个字节对应一个点的颜色)
|
||||||
#define TS_RDP_IMG_BMP 1 // 压缩的BMP数据
|
#define TS_RDP_IMG_BMP 1 // 压缩的BMP数据
|
||||||
|
#define TS_RDP_IMG_ALT 2
|
||||||
|
|
||||||
#pragma pack(push,1)
|
#pragma pack(push,1)
|
||||||
|
|
||||||
|
@ -92,6 +93,7 @@ typedef struct TS_RECORD_RDP_IMAGE_INFO {
|
||||||
uint8_t format;
|
uint8_t format;
|
||||||
uint8_t _reserved;
|
uint8_t _reserved;
|
||||||
uint32_t dat_len;
|
uint32_t dat_len;
|
||||||
|
uint32_t zip_len;
|
||||||
}TS_RECORD_RDP_IMAGE_INFO;
|
}TS_RECORD_RDP_IMAGE_INFO;
|
||||||
|
|
||||||
// 关键帧索引
|
// 关键帧索引
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
#include <qcoreapplication.h>
|
#include <qcoreapplication.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
#include <zlib.h>
|
||||||
|
|
||||||
#include "thr_play.h"
|
#include "thr_play.h"
|
||||||
#include "thr_data.h"
|
#include "thr_data.h"
|
||||||
|
@ -15,6 +16,80 @@
|
||||||
|
|
||||||
#include "rle.h"
|
#include "rle.h"
|
||||||
|
|
||||||
|
|
||||||
|
static QImage* _rdpimg2QImage(int w, int h, int bitsPerPixel, bool isCompressed, const uint8_t* dat, uint32_t len) {
|
||||||
|
QImage* out;
|
||||||
|
switch(bitsPerPixel) {
|
||||||
|
case 15:
|
||||||
|
if(isCompressed) {
|
||||||
|
uint8_t* _dat = reinterpret_cast<uint8_t*>(calloc(1, w*h*2));
|
||||||
|
if(!bitmap_decompress1(_dat, w, h, dat, len)) {
|
||||||
|
free(_dat);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
out = new QImage(_dat, w, h, QImage::Format_RGB555);
|
||||||
|
free(_dat);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
out = new QImage(QImage(dat, w, h, QImage::Format_RGB555).transformed(QMatrix(1.0, 0.0, 0.0, -1.0, 0.0, 0.0)));
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
|
||||||
|
case 16:
|
||||||
|
if(isCompressed) {
|
||||||
|
uint8_t* _dat = reinterpret_cast<uint8_t*>(calloc(1, w*h*2));
|
||||||
|
if(!bitmap_decompress2(_dat, w, h, dat, len)) {
|
||||||
|
free(_dat);
|
||||||
|
qDebug() << "22------------------DECOMPRESS2 failed.";
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: 这里需要进一步优化,直接操作QImage的buffer。
|
||||||
|
out = new QImage(w, h, QImage::Format_RGB16);
|
||||||
|
for(int y = 0; y < h; y++) {
|
||||||
|
for(int x = 0; x < w; x++) {
|
||||||
|
uint16 a = ((uint16*)_dat)[y * w + x];
|
||||||
|
uint8 r = ((a & 0xf800) >> 11) * 255 / 31;
|
||||||
|
uint8 g = ((a & 0x07e0) >> 5) * 255 / 63;
|
||||||
|
uint8 b = (a & 0x001f) * 255 / 31;
|
||||||
|
out->setPixelColor(x, y, QColor(r,g,b));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(_dat);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
out = new QImage(QImage(dat, w, h, QImage::Format_RGB16).transformed(QMatrix(1.0, 0.0, 0.0, -1.0, 0.0, 0.0)));
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
|
||||||
|
case 24:
|
||||||
|
case 32:
|
||||||
|
default:
|
||||||
|
qDebug() << "--------NOT support UNKNOWN bitsPerPix" << bitsPerPixel;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static QImage* _raw2QImage(int w, int h, const uint8_t* dat, uint32_t len) {
|
||||||
|
QImage* out;
|
||||||
|
|
||||||
|
// TODO: 这里需要进一步优化,直接操作QImage的buffer。
|
||||||
|
out = new QImage(w, h, QImage::Format_RGB16);
|
||||||
|
for(int y = 0; y < h; y++) {
|
||||||
|
for(int x = 0; x < w; x++) {
|
||||||
|
uint16 a = ((uint16*)dat)[y * w + x];
|
||||||
|
uint8 r = ((a & 0xf800) >> 11) * 255 / 31;
|
||||||
|
uint8 g = ((a & 0x07e0) >> 5) * 255 / 63;
|
||||||
|
uint8 b = (a & 0x001f) * 255 / 31;
|
||||||
|
out->setPixelColor(x, y, QColor(r,g,b));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//=================================================================
|
//=================================================================
|
||||||
// ThrData
|
// ThrData
|
||||||
//=================================================================
|
//=================================================================
|
||||||
|
@ -186,9 +261,9 @@ void ThrData::_run() {
|
||||||
pkg_count_in_queue = m_data.size();
|
pkg_count_in_queue = m_data.size();
|
||||||
m_locker.unlock();
|
m_locker.unlock();
|
||||||
|
|
||||||
// 少于500个的话,补足到1000个
|
// 少于1000个的话,补足到2000个
|
||||||
if(m_data.size() < 500)
|
if(m_data.size() < 1000)
|
||||||
pkg_need_add = 1000 - pkg_count_in_queue;
|
pkg_need_add = 2000 - pkg_count_in_queue;
|
||||||
|
|
||||||
if(pkg_need_add == 0) {
|
if(pkg_need_add == 0) {
|
||||||
msleep(100);
|
msleep(100);
|
||||||
|
@ -283,13 +358,24 @@ void ThrData::_run() {
|
||||||
}
|
}
|
||||||
file_processed += pkg.size;
|
file_processed += pkg.size;
|
||||||
|
|
||||||
UpdateData* dat = new UpdateData(m_hdr.basic.width, m_hdr.basic.height);
|
//UpdateData* dat = new UpdateData(m_hdr.basic.width, m_hdr.basic.height);
|
||||||
if(!dat->parse(pkg, pkg_data)) {
|
UpdateData* dat = _parse(pkg, pkg_data);
|
||||||
|
//if(!dat->parse(pkg, pkg_data)) {
|
||||||
|
if(dat == nullptr) {
|
||||||
qDebug("invaid tp-rdp-%d.tpd file (4).", m_file_idx+1);
|
qDebug("invaid tp-rdp-%d.tpd file (4).", m_file_idx+1);
|
||||||
_notify_error(QString("%1\ntp-rdp-%2.tpd").arg(LOCAL8BIT("错误的录像数据文件!"), str_fidx));
|
_notify_error(QString("%1\ntp-rdp-%2.tpd").arg(LOCAL8BIT("错误的录像数据文件!"), str_fidx));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 遇到关键帧,需要清除自上一个关键帧以来保存的缓存图像数据
|
||||||
|
if(pkg.type == TS_RECORD_TYPE_RDP_KEYFRAME) {
|
||||||
|
for(size_t ci = 0; ci < m_cache_imgs.size(); ++ci) {
|
||||||
|
if(m_cache_imgs[ci] != nullptr)
|
||||||
|
delete m_cache_imgs[ci];
|
||||||
|
}
|
||||||
|
m_cache_imgs.clear();
|
||||||
|
}
|
||||||
|
|
||||||
// 拖动滚动条后,需要显示一次关键帧数据,然后跳过后续关键帧。
|
// 拖动滚动条后,需要显示一次关键帧数据,然后跳过后续关键帧。
|
||||||
if(pkg.type == TS_RECORD_TYPE_RDP_KEYFRAME) {
|
if(pkg.type == TS_RECORD_TYPE_RDP_KEYFRAME) {
|
||||||
qDebug("----key frame: %ld, processed=%" PRId64 ", pkg.size=%d", pkg.time_ms, file_processed, pkg.size);
|
qDebug("----key frame: %ld, processed=%" PRId64 ", pkg.size=%d", pkg.time_ms, file_processed, pkg.size);
|
||||||
|
@ -333,6 +419,147 @@ void ThrData::_run() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UpdateData* ThrData::_parse(const TS_RECORD_PKG& pkg, const QByteArray& data) {
|
||||||
|
if(pkg.type == TS_RECORD_TYPE_RDP_POINTER) {
|
||||||
|
if(data.size() != sizeof(TS_RECORD_RDP_POINTER))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
UpdateData* ud = new UpdateData();
|
||||||
|
ud->set_pointer(pkg.time_ms, reinterpret_cast<const TS_RECORD_RDP_POINTER*>(data.data()));
|
||||||
|
return ud;
|
||||||
|
}
|
||||||
|
else if(pkg.type == TS_RECORD_TYPE_RDP_IMAGE) {
|
||||||
|
UpdateData* ud = new UpdateData(TYPE_IMAGE, pkg.time_ms);
|
||||||
|
|
||||||
|
if(data.size() < static_cast<int>(sizeof(uint16_t) + sizeof(TS_RECORD_RDP_IMAGE_INFO))) {
|
||||||
|
delete ud;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint8_t* dat_ptr = reinterpret_cast<const uint8_t*>(data.data());
|
||||||
|
|
||||||
|
uint16_t count = (reinterpret_cast<const uint16_t*>(dat_ptr))[0];
|
||||||
|
uint32_t offset = sizeof(uint16_t);
|
||||||
|
|
||||||
|
UpdateImages& imgs = ud->get_images();
|
||||||
|
|
||||||
|
for(uint16_t i = 0; i < count; ++i) {
|
||||||
|
|
||||||
|
const TS_RECORD_RDP_IMAGE_INFO* info = reinterpret_cast<const TS_RECORD_RDP_IMAGE_INFO*>(dat_ptr+offset);
|
||||||
|
offset += sizeof(TS_RECORD_RDP_IMAGE_INFO);
|
||||||
|
|
||||||
|
if(info->format != TS_RDP_IMG_ALT) {
|
||||||
|
const uint8_t* img_dat = dat_ptr + offset;
|
||||||
|
|
||||||
|
const uint8_t* real_img_dat = nullptr;
|
||||||
|
QByteArray unzip_data;
|
||||||
|
if(info->zip_len > 0) {
|
||||||
|
// 数据被压缩了,需要解压缩
|
||||||
|
unzip_data.resize(static_cast<int>(info->dat_len));
|
||||||
|
|
||||||
|
uLong u_len = info->dat_len;
|
||||||
|
int err = uncompress(reinterpret_cast<uint8_t*>(unzip_data.data()), &u_len, img_dat, info->zip_len);
|
||||||
|
if(err != Z_OK || u_len != info->dat_len) {
|
||||||
|
qDebug("image uncompress failed. err=%d.", err);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
real_img_dat = reinterpret_cast<const uint8_t*>(unzip_data.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
offset += info->zip_len;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
real_img_dat = img_dat;
|
||||||
|
offset += info->dat_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
UPDATE_IMAGE uimg;
|
||||||
|
uimg.x = info->destLeft;
|
||||||
|
uimg.y = info->destTop;
|
||||||
|
uimg.w = info->destRight - info->destLeft + 1;
|
||||||
|
uimg.h = info->destBottom - info->destTop + 1;
|
||||||
|
if(real_img_dat)
|
||||||
|
uimg.img = _rdpimg2QImage(info->width, info->height, info->bitsPerPixel, (info->format == TS_RDP_IMG_BMP) ? true : false, real_img_dat, info->dat_len);
|
||||||
|
else
|
||||||
|
uimg.img = nullptr;
|
||||||
|
imgs.push_back(uimg);
|
||||||
|
|
||||||
|
QImage* cache_img = nullptr;
|
||||||
|
if(uimg.img != nullptr)
|
||||||
|
cache_img = new QImage(*uimg.img);
|
||||||
|
|
||||||
|
m_cache_imgs.push_back(cache_img);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
UPDATE_IMAGE uimg;
|
||||||
|
uimg.x = info->destLeft;
|
||||||
|
uimg.y = info->destTop;
|
||||||
|
uimg.w = info->destRight - info->destLeft + 1;
|
||||||
|
uimg.h = info->destBottom - info->destTop + 1;
|
||||||
|
|
||||||
|
size_t cache_idx = info->dat_len;
|
||||||
|
|
||||||
|
if(cache_idx >= m_cache_imgs.size() || m_cache_imgs[cache_idx] == nullptr) {
|
||||||
|
uimg.img = nullptr;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
uimg.img = new QImage(*m_cache_imgs[cache_idx]);
|
||||||
|
}
|
||||||
|
imgs.push_back(uimg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ud;
|
||||||
|
}
|
||||||
|
else if(pkg.type == TS_RECORD_TYPE_RDP_KEYFRAME) {
|
||||||
|
UpdateData* ud = new UpdateData(TYPE_IMAGE, pkg.time_ms);
|
||||||
|
const TS_RECORD_RDP_KEYFRAME_INFO* info = reinterpret_cast<const TS_RECORD_RDP_KEYFRAME_INFO*>(data.data());
|
||||||
|
const uint8_t* data_buf = reinterpret_cast<const uint8_t*>(data.data() + sizeof(TS_RECORD_RDP_KEYFRAME_INFO));
|
||||||
|
uint32_t data_len = data.size() - sizeof(TS_RECORD_RDP_KEYFRAME_INFO);
|
||||||
|
|
||||||
|
UpdateImages& imgs = ud->get_images();
|
||||||
|
|
||||||
|
UPDATE_IMAGE uimg;
|
||||||
|
uimg.x = 0;
|
||||||
|
uimg.y = 0;
|
||||||
|
uimg.w = m_hdr.basic.width;
|
||||||
|
uimg.h = m_hdr.basic.height;
|
||||||
|
|
||||||
|
const uint8_t* real_img_dat = nullptr;
|
||||||
|
uint32_t real_img_len = m_hdr.basic.width * m_hdr.basic.height * 2;
|
||||||
|
|
||||||
|
QByteArray unzip_data;
|
||||||
|
if(data_len != real_img_len) {
|
||||||
|
// 数据被压缩了,需要解压缩
|
||||||
|
unzip_data.resize(static_cast<int>(real_img_len));
|
||||||
|
|
||||||
|
uLong u_len = real_img_len;
|
||||||
|
int err = uncompress(reinterpret_cast<uint8_t*>(unzip_data.data()), &u_len, data_buf, data_len);
|
||||||
|
if(err != Z_OK || u_len != real_img_len) {
|
||||||
|
qDebug("keyframe uncompress failed. err=%d.", err);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
real_img_dat = reinterpret_cast<const uint8_t*>(unzip_data.data());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
real_img_dat = data_buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(real_img_dat != nullptr)
|
||||||
|
uimg.img = _raw2QImage(m_hdr.basic.width, m_hdr.basic.height, real_img_dat, real_img_len);
|
||||||
|
else
|
||||||
|
uimg.img = nullptr;
|
||||||
|
imgs.push_back(uimg);
|
||||||
|
|
||||||
|
return ud;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void ThrData::restart(uint32_t start_ms) {
|
void ThrData::restart(uint32_t start_ms) {
|
||||||
qDebug("restart at %ld ms", start_ms);
|
qDebug("restart at %ld ms", start_ms);
|
||||||
// 让处理线程处理完当前循环,然后等待
|
// 让处理线程处理完当前循环,然后等待
|
||||||
|
@ -441,19 +668,19 @@ bool ThrData::_load_keyframe() {
|
||||||
}
|
}
|
||||||
|
|
||||||
qint64 fsize = f_kf.size();
|
qint64 fsize = f_kf.size();
|
||||||
if(!fsize || fsize % sizeof(KEYFRAME_INFO) != 0) {
|
if(!fsize || fsize % sizeof(TS_RECORD_RDP_KEYFRAME_INFO) != 0) {
|
||||||
qDebug() << "Can not open " << tpk_fname << " for read.";
|
qDebug() << "Can not open " << tpk_fname << " for read.";
|
||||||
_notify_error(LOCAL8BIT("关键帧信息文件格式错误!"));
|
_notify_error(LOCAL8BIT("关键帧信息文件格式错误!"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
qint64 read_len = 0;
|
qint64 read_len = 0;
|
||||||
int kf_count = static_cast<int>(fsize / sizeof(KEYFRAME_INFO));
|
int kf_count = static_cast<int>(fsize / sizeof(TS_RECORD_RDP_KEYFRAME_INFO));
|
||||||
for(int i = 0; i < kf_count; ++i) {
|
for(int i = 0; i < kf_count; ++i) {
|
||||||
KEYFRAME_INFO kf;
|
TS_RECORD_RDP_KEYFRAME_INFO kf;
|
||||||
memset(&kf, 0, sizeof(KEYFRAME_INFO));
|
memset(&kf, 0, sizeof(TS_RECORD_RDP_KEYFRAME_INFO));
|
||||||
read_len = f_kf.read(reinterpret_cast<char*>(&kf), sizeof(KEYFRAME_INFO));
|
read_len = f_kf.read(reinterpret_cast<char*>(&kf), sizeof(TS_RECORD_RDP_KEYFRAME_INFO));
|
||||||
if(read_len != sizeof(KEYFRAME_INFO)) {
|
if(read_len != sizeof(TS_RECORD_RDP_KEYFRAME_INFO)) {
|
||||||
qDebug() << "invaid .tpk file.";
|
qDebug() << "invaid .tpk file.";
|
||||||
_notify_error(LOCAL8BIT("关键帧信息文件格式错误!"));
|
_notify_error(LOCAL8BIT("关键帧信息文件格式错误!"));
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include <QNetworkReply>
|
#include <QNetworkReply>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QEventLoop>
|
#include <QEventLoop>
|
||||||
|
#include <QImage>
|
||||||
#include "update_data.h"
|
#include "update_data.h"
|
||||||
#include "record_format.h"
|
#include "record_format.h"
|
||||||
#include "thr_download.h"
|
#include "thr_download.h"
|
||||||
|
@ -33,13 +34,15 @@
|
||||||
这样,下次需要下载指定文件时,如果发现对应的临时文件存在,可以根据已下载字节数,继续下载。
|
这样,下次需要下载指定文件时,如果发现对应的临时文件存在,可以根据已下载字节数,继续下载。
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef struct KEYFRAME_INFO {
|
//typedef struct KEYFRAME_INFO {
|
||||||
uint32_t time_ms; // 此关键帧的时间点
|
// uint32_t time_ms; // 此关键帧的时间点
|
||||||
uint32_t file_index; // 此关键帧图像数据位于哪一个数据文件中
|
// uint32_t file_index; // 此关键帧图像数据位于哪一个数据文件中
|
||||||
uint32_t offset; // 此关键帧图像数据在数据文件中的偏移
|
// uint32_t offset; // 此关键帧图像数据在数据文件中的偏移
|
||||||
}KEYFRAME_INFO;
|
//}KEYFRAME_INFO;
|
||||||
|
|
||||||
typedef std::vector<KEYFRAME_INFO> KeyFrames;
|
typedef std::vector<TS_RECORD_RDP_KEYFRAME_INFO> KeyFrames;
|
||||||
|
|
||||||
|
typedef std::vector<QImage*> CachedImages;
|
||||||
|
|
||||||
class MainWindow;
|
class MainWindow;
|
||||||
|
|
||||||
|
@ -69,6 +72,8 @@ private:
|
||||||
void _clear_data();
|
void _clear_data();
|
||||||
void _prepare();
|
void _prepare();
|
||||||
|
|
||||||
|
UpdateData* _parse(const TS_RECORD_PKG& pkg, const QByteArray& data);
|
||||||
|
|
||||||
void _notify_message(const QString& msg);
|
void _notify_message(const QString& msg);
|
||||||
void _notify_error(const QString& err_msg);
|
void _notify_error(const QString& err_msg);
|
||||||
|
|
||||||
|
@ -104,6 +109,7 @@ private:
|
||||||
|
|
||||||
// bool m_xxx;
|
// bool m_xxx;
|
||||||
// int m_restart_kf_idx;
|
// int m_restart_kf_idx;
|
||||||
|
CachedImages m_cache_imgs;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // THR_DATA_H
|
#endif // THR_DATA_H
|
||||||
|
|
|
@ -37,3 +37,16 @@ RC_FILE += \
|
||||||
|
|
||||||
FORMS += \
|
FORMS += \
|
||||||
mainwindow.ui
|
mainwindow.ui
|
||||||
|
|
||||||
|
win32:CONFIG(release, debug|release): LIBS += -L$$PWD/../../external/zlib/build/release/ -lzlibstatic
|
||||||
|
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/../../external/zlib/build/debug/ -lzlibstaticd
|
||||||
|
|
||||||
|
INCLUDEPATH += $$PWD/../../external/zlib
|
||||||
|
INCLUDEPATH += $$PWD/../../external/zlib/build
|
||||||
|
DEPENDPATH += $$PWD/../../external/zlib
|
||||||
|
DEPENDPATH += $$PWD/../../external/zlib/build
|
||||||
|
|
||||||
|
win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$PWD/../../external/zlib/build/release/libzlibstaticd.a
|
||||||
|
else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$PWD/../../external/zlib/build/debug/libzlibstaticd.a
|
||||||
|
else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$PWD/../../external/zlib/build/release/zlibstaticd.lib
|
||||||
|
else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$PWD/../../external/zlib/build/debug/zlibstaticd.lib
|
||||||
|
|
|
@ -1,80 +1,80 @@
|
||||||
#include "update_data.h"
|
#include "update_data.h"
|
||||||
#include "rle.h"
|
//#include "rle.h"
|
||||||
|
|
||||||
#include <QImage>
|
#include <QImage>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
|
|
||||||
static QImage* _rdpimg2QImage(int w, int h, int bitsPerPixel, bool isCompressed, const uint8_t* dat, uint32_t len) {
|
//static QImage* _rdpimg2QImage(int w, int h, int bitsPerPixel, bool isCompressed, const uint8_t* dat, uint32_t len) {
|
||||||
QImage* out;
|
// QImage* out;
|
||||||
switch(bitsPerPixel) {
|
// switch(bitsPerPixel) {
|
||||||
case 15:
|
// case 15:
|
||||||
if(isCompressed) {
|
// if(isCompressed) {
|
||||||
uint8_t* _dat = reinterpret_cast<uint8_t*>(calloc(1, w*h*2));
|
// uint8_t* _dat = reinterpret_cast<uint8_t*>(calloc(1, w*h*2));
|
||||||
if(!bitmap_decompress1(_dat, w, h, dat, len)) {
|
// if(!bitmap_decompress1(_dat, w, h, dat, len)) {
|
||||||
free(_dat);
|
// free(_dat);
|
||||||
return nullptr;
|
// return nullptr;
|
||||||
}
|
// }
|
||||||
out = new QImage(_dat, w, h, QImage::Format_RGB555);
|
// out = new QImage(_dat, w, h, QImage::Format_RGB555);
|
||||||
free(_dat);
|
// free(_dat);
|
||||||
}
|
// }
|
||||||
else {
|
// else {
|
||||||
out = new QImage(QImage(dat, w, h, QImage::Format_RGB555).transformed(QMatrix(1.0, 0.0, 0.0, -1.0, 0.0, 0.0)));
|
// out = new QImage(QImage(dat, w, h, QImage::Format_RGB555).transformed(QMatrix(1.0, 0.0, 0.0, -1.0, 0.0, 0.0)));
|
||||||
}
|
// }
|
||||||
return out;
|
// return out;
|
||||||
|
|
||||||
case 16:
|
// case 16:
|
||||||
if(isCompressed) {
|
// if(isCompressed) {
|
||||||
uint8_t* _dat = reinterpret_cast<uint8_t*>(calloc(1, w*h*2));
|
// uint8_t* _dat = reinterpret_cast<uint8_t*>(calloc(1, w*h*2));
|
||||||
if(!bitmap_decompress2(_dat, w, h, dat, len)) {
|
// if(!bitmap_decompress2(_dat, w, h, dat, len)) {
|
||||||
free(_dat);
|
// free(_dat);
|
||||||
qDebug() << "22------------------DECOMPRESS2 failed.";
|
// qDebug() << "22------------------DECOMPRESS2 failed.";
|
||||||
return nullptr;
|
// return nullptr;
|
||||||
}
|
// }
|
||||||
|
|
||||||
// TODO: 这里需要进一步优化,直接操作QImage的buffer。
|
// // TODO: 这里需要进一步优化,直接操作QImage的buffer。
|
||||||
out = new QImage(w, h, QImage::Format_RGB16);
|
// out = new QImage(w, h, QImage::Format_RGB16);
|
||||||
for(int y = 0; y < h; y++) {
|
// for(int y = 0; y < h; y++) {
|
||||||
for(int x = 0; x < w; x++) {
|
// for(int x = 0; x < w; x++) {
|
||||||
uint16 a = ((uint16*)_dat)[y * w + x];
|
// uint16 a = ((uint16*)_dat)[y * w + x];
|
||||||
uint8 r = ((a & 0xf800) >> 11) * 255 / 31;
|
// uint8 r = ((a & 0xf800) >> 11) * 255 / 31;
|
||||||
uint8 g = ((a & 0x07e0) >> 5) * 255 / 63;
|
// uint8 g = ((a & 0x07e0) >> 5) * 255 / 63;
|
||||||
uint8 b = (a & 0x001f) * 255 / 31;
|
// uint8 b = (a & 0x001f) * 255 / 31;
|
||||||
out->setPixelColor(x, y, QColor(r,g,b));
|
// out->setPixelColor(x, y, QColor(r,g,b));
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
free(_dat);
|
// free(_dat);
|
||||||
return out;
|
// return out;
|
||||||
}
|
// }
|
||||||
else {
|
// else {
|
||||||
out = new QImage(QImage(dat, w, h, QImage::Format_RGB16).transformed(QMatrix(1.0, 0.0, 0.0, -1.0, 0.0, 0.0)));
|
// out = new QImage(QImage(dat, w, h, QImage::Format_RGB16).transformed(QMatrix(1.0, 0.0, 0.0, -1.0, 0.0, 0.0)));
|
||||||
}
|
// }
|
||||||
return out;
|
// return out;
|
||||||
|
|
||||||
case 24:
|
// case 24:
|
||||||
case 32:
|
// case 32:
|
||||||
default:
|
// default:
|
||||||
qDebug() << "--------NOT support UNKNOWN bitsPerPix" << bitsPerPixel;
|
// qDebug() << "--------NOT support UNKNOWN bitsPerPix" << bitsPerPixel;
|
||||||
return nullptr;
|
// return nullptr;
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|
||||||
static QImage* _raw2QImage(int w, int h, const uint8_t* dat, uint32_t len) {
|
//static QImage* _raw2QImage(int w, int h, const uint8_t* dat, uint32_t len) {
|
||||||
QImage* out;
|
// QImage* out;
|
||||||
|
|
||||||
// TODO: 这里需要进一步优化,直接操作QImage的buffer。
|
// // TODO: 这里需要进一步优化,直接操作QImage的buffer。
|
||||||
out = new QImage(w, h, QImage::Format_RGB16);
|
// out = new QImage(w, h, QImage::Format_RGB16);
|
||||||
for(int y = 0; y < h; y++) {
|
// for(int y = 0; y < h; y++) {
|
||||||
for(int x = 0; x < w; x++) {
|
// for(int x = 0; x < w; x++) {
|
||||||
uint16 a = ((uint16*)dat)[y * w + x];
|
// uint16 a = ((uint16*)dat)[y * w + x];
|
||||||
uint8 r = ((a & 0xf800) >> 11) * 255 / 31;
|
// uint8 r = ((a & 0xf800) >> 11) * 255 / 31;
|
||||||
uint8 g = ((a & 0x07e0) >> 5) * 255 / 63;
|
// uint8 g = ((a & 0x07e0) >> 5) * 255 / 63;
|
||||||
uint8 b = (a & 0x001f) * 255 / 31;
|
// uint8 b = (a & 0x001f) * 255 / 31;
|
||||||
out->setPixelColor(x, y, QColor(r,g,b));
|
// out->setPixelColor(x, y, QColor(r,g,b));
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
return out;
|
// return out;
|
||||||
}
|
//}
|
||||||
|
|
||||||
UpdateData::UpdateData() : QObject(nullptr)
|
UpdateData::UpdateData() : QObject(nullptr)
|
||||||
{
|
{
|
||||||
|
@ -87,6 +87,13 @@ UpdateData::UpdateData(int data_type) : QObject(nullptr)
|
||||||
m_data_type = data_type;
|
m_data_type = data_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UpdateData::UpdateData(int data_type, uint32_t time_ms) : QObject(nullptr)
|
||||||
|
{
|
||||||
|
_init();
|
||||||
|
m_data_type = data_type;
|
||||||
|
m_time_ms = time_ms;
|
||||||
|
}
|
||||||
|
|
||||||
UpdateData::UpdateData(const TS_RECORD_HEADER& hdr) : QObject(nullptr)
|
UpdateData::UpdateData(const TS_RECORD_HEADER& hdr) : QObject(nullptr)
|
||||||
{
|
{
|
||||||
_init();
|
_init();
|
||||||
|
@ -95,11 +102,11 @@ UpdateData::UpdateData(const TS_RECORD_HEADER& hdr) : QObject(nullptr)
|
||||||
memcpy(m_hdr, &hdr, sizeof(TS_RECORD_HEADER));
|
memcpy(m_hdr, &hdr, sizeof(TS_RECORD_HEADER));
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateData::UpdateData(uint16_t screen_w, uint16_t screen_h) {
|
//UpdateData::UpdateData(uint16_t screen_w, uint16_t screen_h) {
|
||||||
_init();
|
// _init();
|
||||||
m_screen_w = screen_w;
|
// m_screen_w = screen_w;
|
||||||
m_screen_h = screen_h;
|
// m_screen_h = screen_h;
|
||||||
}
|
//}
|
||||||
|
|
||||||
void UpdateData::_init() {
|
void UpdateData::_init() {
|
||||||
m_data_type = TYPE_UNKNOWN;
|
m_data_type = TYPE_UNKNOWN;
|
||||||
|
@ -134,6 +141,14 @@ UpdateData::~UpdateData() {
|
||||||
delete m_data_buf;
|
delete m_data_buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UpdateData::set_pointer(uint32_t ts, const TS_RECORD_RDP_POINTER* p) {
|
||||||
|
m_data_type = TYPE_POINTER;
|
||||||
|
m_time_ms = ts;
|
||||||
|
m_pointer = new TS_RECORD_RDP_POINTER;
|
||||||
|
memcpy(m_pointer, p, sizeof(TS_RECORD_RDP_POINTER));
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
bool UpdateData::parse(const TS_RECORD_PKG& pkg, const QByteArray& data) {
|
bool UpdateData::parse(const TS_RECORD_PKG& pkg, const QByteArray& data) {
|
||||||
m_time_ms = pkg.time_ms;
|
m_time_ms = pkg.time_ms;
|
||||||
|
|
||||||
|
@ -213,7 +228,7 @@ bool UpdateData::parse(const TS_RECORD_PKG& pkg, const QByteArray& data) {
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void UpdateData::alloc_data(uint32_t len) {
|
void UpdateData::alloc_data(uint32_t len) {
|
||||||
if(m_data_buf)
|
if(m_data_buf)
|
||||||
|
|
|
@ -37,29 +37,18 @@ class UpdateData : public QObject
|
||||||
public:
|
public:
|
||||||
explicit UpdateData();
|
explicit UpdateData();
|
||||||
explicit UpdateData(int data_type);
|
explicit UpdateData(int data_type);
|
||||||
|
explicit UpdateData(int data_type, uint32_t time_ms);
|
||||||
explicit UpdateData(const TS_RECORD_HEADER& hdr);
|
explicit UpdateData(const TS_RECORD_HEADER& hdr);
|
||||||
explicit UpdateData(uint16_t screen_w, uint16_t screen_h);
|
//explicit UpdateData(uint16_t screen_w, uint16_t screen_h);
|
||||||
virtual ~UpdateData();
|
virtual ~UpdateData();
|
||||||
|
|
||||||
bool parse(const TS_RECORD_PKG& pkg, const QByteArray& data);
|
void set_pointer(uint32_t ts, const TS_RECORD_RDP_POINTER* p);
|
||||||
|
|
||||||
|
// bool parse(const TS_RECORD_PKG& pkg, const QByteArray& data);
|
||||||
TS_RECORD_HEADER* get_header() {return m_hdr;}
|
TS_RECORD_HEADER* get_header() {return m_hdr;}
|
||||||
TS_RECORD_RDP_POINTER* get_pointer() {return m_pointer;}
|
TS_RECORD_RDP_POINTER* get_pointer() {return m_pointer;}
|
||||||
// bool get_image(QImage** img, int& x, int& y, int& w, int& h) {
|
UpdateImages& get_images() {return m_images;}
|
||||||
// if(m_img == nullptr)
|
const UpdateImages& get_images() const {return m_images;}
|
||||||
// return false;
|
|
||||||
// *img = m_img;
|
|
||||||
// x = m_img_x;
|
|
||||||
// y = m_img_y;
|
|
||||||
// w = m_img_w;
|
|
||||||
// h = m_img_h;
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
bool get_images(UpdateImages& uimgs) const {
|
|
||||||
if(m_images.size() == 0)
|
|
||||||
return false;
|
|
||||||
uimgs = m_images;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t get_time() {return m_time_ms;}
|
uint32_t get_time() {return m_time_ms;}
|
||||||
|
|
||||||
|
|
|
@ -5,4 +5,5 @@ mbedtls = 2.12.0
|
||||||
libssh = 0.9.0
|
libssh = 0.9.0
|
||||||
jsoncpp = 0.10.6
|
jsoncpp = 0.10.6
|
||||||
mongoose = 6.12
|
mongoose = 6.12
|
||||||
|
; https://www.zlib.net/zlib1211.zip
|
||||||
|
zlilb = 1211,1.2.11
|
Loading…
Reference in New Issue