teleport/client/tp-player/update_data.cpp

234 lines
7.2 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include "update_data.h"
#include "rle.h"
#include <QImage>
#include <QDebug>
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;
}
UpdateData::UpdateData() : QObject(nullptr)
{
_init();
}
UpdateData::UpdateData(int data_type) : QObject(nullptr)
{
_init();
m_data_type = data_type;
}
UpdateData::UpdateData(const TS_RECORD_HEADER& hdr) : QObject(nullptr)
{
_init();
m_data_type = TYPE_HEADER_INFO;
m_hdr = new TS_RECORD_HEADER;
memcpy(m_hdr, &hdr, sizeof(TS_RECORD_HEADER));
}
UpdateData::UpdateData(uint16_t screen_w, uint16_t screen_h) {
_init();
m_screen_w = screen_w;
m_screen_h = screen_h;
}
void UpdateData::_init() {
m_data_type = TYPE_UNKNOWN;
m_hdr = nullptr;
m_pointer = nullptr;
// m_img = nullptr;
// m_img_info = nullptr;
m_data_buf = nullptr;
m_data_len = 0;
m_time_ms = 0;
m_screen_w = 0;
m_screen_h = 0;
}
UpdateData::~UpdateData() {
if(m_hdr)
delete m_hdr;
if(m_pointer)
delete m_pointer;
// if(m_img)
// delete m_img;
// if(m_img_info)
// delete m_img_info;
for(int i = 0; i < m_images.size(); ++i) {
delete m_images[i].img;
}
m_images.clear();
if(m_data_buf)
delete m_data_buf;
}
bool UpdateData::parse(const TS_RECORD_PKG& pkg, const QByteArray& data) {
m_time_ms = pkg.time_ms;
if(pkg.type == TS_RECORD_TYPE_RDP_POINTER) {
m_data_type = TYPE_POINTER;
if(data.size() != sizeof(TS_RECORD_RDP_POINTER))
return false;
m_pointer = new TS_RECORD_RDP_POINTER;
memcpy(m_pointer, data.data(), sizeof(TS_RECORD_RDP_POINTER));
return true;
}
else if(pkg.type == TS_RECORD_TYPE_RDP_IMAGE) {
m_data_type = TYPE_IMAGE;
if(data.size() <= static_cast<int>(sizeof(uint16_t) + sizeof(TS_RECORD_RDP_IMAGE_INFO)))
return false;
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);
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);
//const uint8_t* img_dat = reinterpret_cast<const uint8_t*>(data.data() + sizeof(TS_RECORD_RDP_IMAGE_INFO));
//uint32_t img_len = data.size() - sizeof(TS_RECORD_RDP_IMAGE_INFO);
const uint8_t* img_dat = dat_ptr + offset;
offset += info->dat_len;
QImage* img = _rdpimg2QImage(info->width, info->height, info->bitsPerPixel, (info->format == TS_RDP_IMG_BMP) ? true : false, img_dat, info->dat_len);
if(img == nullptr)
return false;
// m_img = img;
// m_img_x = info->destLeft;
// m_img_y = info->destTop;
// m_img_w = info->destRight - info->destLeft + 1;
// m_img_h = info->destBottom - info->destTop + 1;
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;
uimg.img = img;
m_images.push_back(uimg);
}
return true;
}
else if(pkg.type == TS_RECORD_TYPE_RDP_KEYFRAME) {
m_data_type = TYPE_IMAGE;
// const TS_RECORD_RDP_KEYFRAME_INFO* info = reinterpret_cast<const TS_RECORD_RDP_KEYFRAME_INFO*>(data.data());
const uint8_t* img_dat = reinterpret_cast<const uint8_t*>(data.data() + sizeof(TS_RECORD_RDP_KEYFRAME_INFO));
uint32_t img_len = data.size() - sizeof(TS_RECORD_RDP_KEYFRAME_INFO);
QImage* img = _raw2QImage((int)m_screen_w, (int)m_screen_h, img_dat, img_len);
if(img == nullptr)
return false;
UPDATE_IMAGE uimg;
uimg.x = 0;
uimg.y = 0;
uimg.w = m_screen_w;
uimg.h = m_screen_h;
uimg.img = img;
m_images.push_back(uimg);
// m_img = img;
// m_img_x = 0;
// m_img_y = 0;
// m_img_w = m_screen_w;
// m_img_h = m_screen_h;
return true;
}
return false;
}
void UpdateData::alloc_data(uint32_t len) {
if(m_data_buf)
delete m_data_buf;
m_data_buf = new uint8_t[len];
memset(m_data_buf, 0, len);
m_data_len = len;
}
void UpdateData::attach_data(const uint8_t* dat, uint32_t len) {
if(m_data_buf)
delete m_data_buf;
m_data_buf = new uint8_t[len];
memcpy(m_data_buf, dat, len);
m_data_len = len;
}