mirror of https://github.com/tp4a/teleport
RDP播放器完工,允许拖动进度条了。
parent
23c24ceb69
commit
dd115c8af6
|
@ -372,7 +372,7 @@ void Bar::onMouseMove(int x, int y) {
|
||||||
|
|
||||||
if(pt.x() < m_rc_progress.left()) {
|
if(pt.x() < m_rc_progress.left()) {
|
||||||
percent = 0;
|
percent = 0;
|
||||||
m_resume_ms = 0;
|
m_resume_ms = 1;
|
||||||
}
|
}
|
||||||
else if(pt.x() > m_rc_progress.right()) {
|
else if(pt.x() > m_rc_progress.right()) {
|
||||||
percent = 100;
|
percent = 100;
|
||||||
|
|
|
@ -65,7 +65,7 @@ int main(int argc, char *argv[])
|
||||||
// qDebug("data-path-base: %s", data_path_base.toStdString().c_str());
|
// qDebug("data-path-base: %s", data_path_base.toStdString().c_str());
|
||||||
// return 0;
|
// return 0;
|
||||||
|
|
||||||
QGuiApplication::setApplicationDisplayName("TP-Player");
|
QGuiApplication::setApplicationDisplayName(LOCAL8BIT("[Teleport播放器]"));
|
||||||
|
|
||||||
QCommandLineParser parser;
|
QCommandLineParser parser;
|
||||||
const QCommandLineOption opt_help = parser.addHelpOption();
|
const QCommandLineOption opt_help = parser.addHelpOption();
|
||||||
|
|
|
@ -75,8 +75,6 @@ MainWindow::~MainWindow()
|
||||||
{
|
{
|
||||||
if(m_thr_play) {
|
if(m_thr_play) {
|
||||||
m_thr_play->stop();
|
m_thr_play->stop();
|
||||||
//m_thr_play->wait();
|
|
||||||
//qDebug() << "play thread stoped.";
|
|
||||||
|
|
||||||
disconnect(m_thr_play, SIGNAL(signal_update_data(UpdateData*)), this, SLOT(_do_update_data(UpdateData*)));
|
disconnect(m_thr_play, SIGNAL(signal_update_data(UpdateData*)), this, SLOT(_do_update_data(UpdateData*)));
|
||||||
|
|
||||||
|
@ -87,16 +85,10 @@ MainWindow::~MainWindow()
|
||||||
if(m_thr_data) {
|
if(m_thr_data) {
|
||||||
m_thr_data->stop();
|
m_thr_data->stop();
|
||||||
disconnect(m_thr_data, SIGNAL(signal_update_data(UpdateData*)), this, SLOT(_do_update_data(UpdateData*)));
|
disconnect(m_thr_data, SIGNAL(signal_update_data(UpdateData*)), this, SLOT(_do_update_data(UpdateData*)));
|
||||||
// disconnect(m_thr_data, SIGNAL(signal_download(DownloadParam*)), this, SLOT(_do_download(DownloadParam*)));
|
|
||||||
delete m_thr_data;
|
delete m_thr_data;
|
||||||
m_thr_data = nullptr;
|
m_thr_data = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if(m_dl) {
|
|
||||||
// delete m_dl;
|
|
||||||
// m_dl = nullptr;
|
|
||||||
// }
|
|
||||||
|
|
||||||
delete ui;
|
delete ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,10 +99,8 @@ void MainWindow::set_resource(const QString &res) {
|
||||||
void MainWindow::_do_first_run() {
|
void MainWindow::_do_first_run() {
|
||||||
m_thr_data = new ThrData(this, m_res);
|
m_thr_data = new ThrData(this, m_res);
|
||||||
connect(m_thr_data, SIGNAL(signal_update_data(UpdateData*)), this, SLOT(_do_update_data(UpdateData*)));
|
connect(m_thr_data, SIGNAL(signal_update_data(UpdateData*)), this, SLOT(_do_update_data(UpdateData*)));
|
||||||
// connect(m_thr_data, SIGNAL(signal_download(DownloadParam*)), this, SLOT(_do_download(DownloadParam*)));
|
|
||||||
m_thr_data->start();
|
m_thr_data->start();
|
||||||
|
|
||||||
//_start_play_thread();
|
|
||||||
m_thr_play = new ThrPlay(this);
|
m_thr_play = new ThrPlay(this);
|
||||||
connect(m_thr_play, SIGNAL(signal_update_data(UpdateData*)), this, SLOT(_do_update_data(UpdateData*)));
|
connect(m_thr_play, SIGNAL(signal_update_data(UpdateData*)), this, SLOT(_do_update_data(UpdateData*)));
|
||||||
|
|
||||||
|
@ -118,24 +108,6 @@ void MainWindow::_do_first_run() {
|
||||||
m_thr_play->start();
|
m_thr_play->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
//void MainWindow::_start_play_thread() {
|
|
||||||
// if(m_thr_play) {
|
|
||||||
// m_thr_play->stop();
|
|
||||||
// //m_thr_play->wait();
|
|
||||||
|
|
||||||
// disconnect(m_thr_play, SIGNAL(signal_update_data(UpdateData*)), this, SLOT(_do_update_data(UpdateData*)));
|
|
||||||
|
|
||||||
// delete m_thr_play;
|
|
||||||
// m_thr_play = nullptr;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// m_thr_play = new ThrPlay(this);
|
|
||||||
// connect(m_thr_play, SIGNAL(signal_update_data(UpdateData*)), this, SLOT(_do_update_data(UpdateData*)));
|
|
||||||
|
|
||||||
// m_thr_play->speed(m_bar.get_speed());
|
|
||||||
// m_thr_play->start();
|
|
||||||
//}
|
|
||||||
|
|
||||||
void MainWindow::set_speed(int s) {
|
void MainWindow::set_speed(int s) {
|
||||||
if(m_thr_play)
|
if(m_thr_play)
|
||||||
m_thr_play->speed(s);
|
m_thr_play->speed(s);
|
||||||
|
@ -242,20 +214,27 @@ void MainWindow::_do_update_data(UpdateData* dat) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if(dat->data_type() == TYPE_IMAGE) {
|
else if(dat->data_type() == TYPE_IMAGE) {
|
||||||
QImage* img_update = nullptr;
|
UpdateImages uimgs;
|
||||||
int x, y, w, h;
|
if(!dat->get_images(uimgs))
|
||||||
if(!dat->get_image(&img_update, x, y, w, h))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
static int img_idx = 0;
|
if(uimgs.size() > 1) {
|
||||||
img_idx++;
|
// 禁止界面更新
|
||||||
qDebug("draw img: %d (%d,%d)-(%d,%d)", img_idx, x, y, w, h);
|
setUpdatesEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
QPainter pp(&m_canvas);
|
QPainter pp(&m_canvas);
|
||||||
pp.drawImage(x, y, *img_update, 0, 0, w, h, Qt::AutoColor);
|
for(int i = 0; i < uimgs.size(); ++i) {
|
||||||
|
pp.drawImage(uimgs[i].x, uimgs[i].y, *(uimgs[i].img), 0, 0, uimgs[i].w, uimgs[i].h, Qt::AutoColor);
|
||||||
|
update(uimgs[i].x, uimgs[i].y, uimgs[i].w, uimgs[i].h);
|
||||||
|
}
|
||||||
|
|
||||||
update(x, y, w, h);
|
|
||||||
|
if(uimgs.size() > 1) {
|
||||||
|
// 允许界面更新
|
||||||
|
setUpdatesEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -265,6 +244,18 @@ void MainWindow::_do_update_data(UpdateData* dat) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if(dat->data_type() == TYPE_DISABLE_DRAW) {
|
||||||
|
// 禁止界面更新
|
||||||
|
setUpdatesEnabled(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if(dat->data_type() == TYPE_ENABLE_DRAW) {
|
||||||
|
// 允许界面更新
|
||||||
|
setUpdatesEnabled(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
else if(dat->data_type() == TYPE_MESSAGE) {
|
else if(dat->data_type() == TYPE_MESSAGE) {
|
||||||
if(dat->message().isEmpty()) {
|
if(dat->message().isEmpty()) {
|
||||||
m_show_message = false;
|
m_show_message = false;
|
||||||
|
@ -361,12 +352,14 @@ void MainWindow::_do_update_data(UpdateData* dat) {
|
||||||
|
|
||||||
QString title;
|
QString title;
|
||||||
if (m_rec_hdr.basic.conn_port == 3389) {
|
if (m_rec_hdr.basic.conn_port == 3389) {
|
||||||
title = QString(LOCAL8BIT("[%1] %2@%3 [Teleport-RDP录像回放]").arg(m_rec_hdr.basic.acc_username, m_rec_hdr.basic.user_username, m_rec_hdr.basic.conn_ip));
|
// title = QString(LOCAL8BIT("[%1] %2@%3 [Teleport-RDP录像回放]").arg(m_rec_hdr.basic.acc_username, m_rec_hdr.basic.user_username, m_rec_hdr.basic.conn_ip));
|
||||||
|
title = QString(LOCAL8BIT("用户 %1 访问 %2 的 %3 账号").arg(m_rec_hdr.basic.user_username, m_rec_hdr.basic.conn_ip, m_rec_hdr.basic.acc_username));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
QString _port;
|
QString _port;
|
||||||
_port.sprintf("%d", m_rec_hdr.basic.conn_port);
|
_port.sprintf("%d", m_rec_hdr.basic.conn_port);
|
||||||
title = QString(LOCAL8BIT("[%1] %2@%3:%4 [Teleport-RDP录像回放]").arg(m_rec_hdr.basic.acc_username, m_rec_hdr.basic.user_username, m_rec_hdr.basic.conn_ip, _port));
|
//title = QString(LOCAL8BIT("[%1] %2@%3:%4 [Teleport-RDP录像回放]").arg(m_rec_hdr.basic.acc_username, m_rec_hdr.basic.user_username, m_rec_hdr.basic.conn_ip, _port));
|
||||||
|
title = QString(LOCAL8BIT("用户 %1 访问 %2:%3 的 %4 账号").arg(m_rec_hdr.basic.user_username, m_rec_hdr.basic.conn_ip, _port, m_rec_hdr.basic.acc_username));
|
||||||
}
|
}
|
||||||
|
|
||||||
setWindowTitle(title);
|
setWindowTitle(title);
|
||||||
|
@ -457,13 +450,6 @@ void MainWindow::mousePressEvent(QMouseEvent *e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::mouseReleaseEvent(QMouseEvent *e) {
|
void MainWindow::mouseReleaseEvent(QMouseEvent *e) {
|
||||||
qDebug("mouse release.");
|
|
||||||
// if(!m_show_default) {
|
|
||||||
// QRect rc = m_bar.rc();
|
|
||||||
// if(rc.contains(e->pos())) {
|
|
||||||
// m_bar.onMouseRelease(e->x(), e->y(), e->button());
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
m_bar.onMouseRelease(e->x(), e->y(), e->button());
|
m_bar.onMouseRelease(e->x(), e->y(), e->button());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,10 +24,10 @@ typedef struct TS_RECORD_HEADER_INFO {
|
||||||
uint32_t magic; // "TPPR" 标志 TelePort Protocol Record
|
uint32_t magic; // "TPPR" 标志 TelePort Protocol Record
|
||||||
uint16_t ver; // 录像文件版本,从3.5.0开始,为4
|
uint16_t ver; // 录像文件版本,从3.5.0开始,为4
|
||||||
uint16_t type; //
|
uint16_t type; //
|
||||||
uint32_t packages; // 总包数
|
// uint32_t packages; // 总包数
|
||||||
uint32_t time_ms; // 总耗时(毫秒)
|
uint32_t time_ms; // 总耗时(毫秒)
|
||||||
uint32_t dat_file_count; // 数据文件数量
|
uint32_t dat_file_count; // 数据文件数量
|
||||||
uint8_t _reserve[64-4-2-2-4-4-4];
|
uint8_t _reserve[64-4-2-2-4-4];
|
||||||
}TS_RECORD_HEADER_INFO;
|
}TS_RECORD_HEADER_INFO;
|
||||||
#define ts_record_header_info_size sizeof(TS_RECORD_HEADER_INFO)
|
#define ts_record_header_info_size sizeof(TS_RECORD_HEADER_INFO)
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ typedef struct TS_RECORD_PKG {
|
||||||
uint8_t _reserve[3]; // 保留
|
uint8_t _reserve[3]; // 保留
|
||||||
uint32_t size; // 这个包的总大小(不含包头)
|
uint32_t size; // 这个包的总大小(不含包头)
|
||||||
uint32_t time_ms; // 这个包距起始时间的时间差(毫秒,意味着一个连接不能持续超过49天)
|
uint32_t time_ms; // 这个包距起始时间的时间差(毫秒,意味着一个连接不能持续超过49天)
|
||||||
uint32_t index; // 这个包的序号(最后一个包的序号与TS_RECORD_HEADER_INFO::packages数量匹配)
|
// uint32_t index; // 这个包的序号(最后一个包的序号与TS_RECORD_HEADER_INFO::packages数量匹配)
|
||||||
}TS_RECORD_PKG;
|
}TS_RECORD_PKG;
|
||||||
|
|
||||||
|
|
||||||
|
@ -91,6 +91,7 @@ typedef struct TS_RECORD_RDP_IMAGE_INFO {
|
||||||
uint16_t bitsPerPixel;
|
uint16_t bitsPerPixel;
|
||||||
uint8_t format;
|
uint8_t format;
|
||||||
uint8_t _reserved;
|
uint8_t _reserved;
|
||||||
|
uint32_t dat_len;
|
||||||
}TS_RECORD_RDP_IMAGE_INFO;
|
}TS_RECORD_RDP_IMAGE_INFO;
|
||||||
|
|
||||||
// 关键帧索引
|
// 关键帧索引
|
||||||
|
|
|
@ -15,77 +15,6 @@
|
||||||
|
|
||||||
#include "rle.h"
|
#include "rle.h"
|
||||||
|
|
||||||
// for test only
|
|
||||||
int g_kf_idx = 0;
|
|
||||||
QByteArray g_kfdata[10];
|
|
||||||
QByteArray* g_kf = nullptr;
|
|
||||||
|
|
||||||
int g_img_idx = 0;
|
|
||||||
|
|
||||||
void _update_key_frame(QByteArray* kf, uint16_t screen_w, uint16_t screen_h, uint16_t destLeft, uint16_t destTop, uint16_t w, uint16_t h, uint16_t wr, uint16_t hr, uint16_t bitsPerPixel, bool isCompressed, const uint8_t* dat, size_t len) {
|
|
||||||
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);
|
|
||||||
// qDebug("bitmap_decompress1() failed.");
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// 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:
|
|
||||||
{
|
|
||||||
g_img_idx++;
|
|
||||||
uint8_t* kfd = reinterpret_cast<uint8_t*>(kf->data());
|
|
||||||
if(isCompressed) {
|
|
||||||
uint8_t* _dat = reinterpret_cast<uint8_t*>(calloc(1, w*h*2));
|
|
||||||
if(!bitmap_decompress2(_dat, w, h, dat, static_cast<int>(len))) {
|
|
||||||
free(_dat);
|
|
||||||
qDebug() << "------------------DECOMPRESS2 failed.";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// out = new QImage(w, h, QImage::Format_RGB16);
|
|
||||||
|
|
||||||
qDebug("c: %ld, img: %d (%d,%d)-(%d,%d) (%d,%d)", ((destTop+hr-1)*screen_w)+destLeft+wr-1, g_img_idx, destLeft, destTop, w, h, wr, hr);
|
|
||||||
for(int y = 0; y < hr; y++) {
|
|
||||||
// if((destTop+y)*screen_w+destLeft > 6)
|
|
||||||
// memcpy(kfd+((destTop+y)*screen_w+destLeft - 6)*2, _dat+((y*w)*2), wr*2);
|
|
||||||
// else
|
|
||||||
memcpy(kfd+((destTop+y)*screen_w+destLeft)*2, _dat+((y*w)*2), wr*2);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(_dat);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
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)));
|
|
||||||
|
|
||||||
qDebug("nc: %ld, img: %d (%d,%d)-(%d,%d) (%d,%d)", ((destTop+hr-1)*screen_w)+destLeft+wr-1, g_img_idx, destLeft, destTop, w, h, wr, hr);
|
|
||||||
for(int y = 0; y < hr; y++) {
|
|
||||||
memcpy(kfd+((destTop+h-y)*screen_w+destLeft)*2, dat+(y*w*2), wr*2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 24:
|
|
||||||
case 32:
|
|
||||||
default:
|
|
||||||
qDebug() << "------------------NOT support UNKNOWN bitsPerPix" << bitsPerPixel;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//=================================================================
|
//=================================================================
|
||||||
// ThrData
|
// ThrData
|
||||||
//=================================================================
|
//=================================================================
|
||||||
|
@ -102,8 +31,6 @@ ThrData::ThrData(MainWindow* mainwin, const QString& res) {
|
||||||
m_file_idx = 0;
|
m_file_idx = 0;
|
||||||
m_offset = 0;
|
m_offset = 0;
|
||||||
|
|
||||||
m_xxx = false;
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
m_data_path_base = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
|
m_data_path_base = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
|
||||||
m_data_path_base += "/tp-testdata/";
|
m_data_path_base += "/tp-testdata/";
|
||||||
|
@ -223,18 +150,11 @@ void ThrData::_run() {
|
||||||
|
|
||||||
|
|
||||||
QFile* fdata = nullptr;
|
QFile* fdata = nullptr;
|
||||||
//uint32_t file_idx = 0;
|
|
||||||
//uint32_t start_offset = 0;
|
|
||||||
qint64 file_size = 0;
|
qint64 file_size = 0;
|
||||||
qint64 file_processed = 0;
|
qint64 file_processed = 0;
|
||||||
qint64 read_len = 0;
|
qint64 read_len = 0;
|
||||||
QString str_fidx;
|
QString str_fidx;
|
||||||
|
|
||||||
g_kf_idx = 0;
|
|
||||||
g_kf = &(g_kfdata[g_kf_idx]);
|
|
||||||
g_kf->resize(m_hdr.basic.width*m_hdr.basic.height*2);
|
|
||||||
memset(g_kf->data(), 0, m_hdr.basic.width*m_hdr.basic.height*2);
|
|
||||||
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
// 任何时候确保第一时间响应退出操作
|
// 任何时候确保第一时间响应退出操作
|
||||||
if(m_need_stop)
|
if(m_need_stop)
|
||||||
|
@ -356,49 +276,13 @@ void ThrData::_run() {
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray pkg_data = fdata->read(pkg.size);
|
QByteArray pkg_data = fdata->read(pkg.size);
|
||||||
if(pkg_data.size() != pkg.size) {
|
if(pkg_data.size() != static_cast<int>(pkg.size)) {
|
||||||
qDebug("invaid tp-rdp-%d.tpd file, read_len=%" PRId64 " (3).", m_file_idx+1, read_len);
|
qDebug("invaid tp-rdp-%d.tpd file, read_len=%" PRId64 " (3).", m_file_idx+1, read_len);
|
||||||
_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;
|
||||||
}
|
}
|
||||||
file_processed += pkg.size;
|
file_processed += pkg.size;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// for test only
|
|
||||||
if(!m_xxx && pkg.type == TS_RECORD_TYPE_RDP_IMAGE) {
|
|
||||||
const TS_RECORD_RDP_IMAGE_INFO* info = reinterpret_cast<const TS_RECORD_RDP_IMAGE_INFO*>(pkg_data.data());
|
|
||||||
uint8_t* img_dat = reinterpret_cast<uint8_t*>(pkg_data.data() + sizeof(TS_RECORD_RDP_IMAGE_INFO));
|
|
||||||
size_t img_len = pkg_data.size() - sizeof(TS_RECORD_RDP_IMAGE_INFO);
|
|
||||||
|
|
||||||
bool isCompress = (info->format == TS_RDP_IMG_BMP) ? true : false;
|
|
||||||
// _update_key_frame(&g_kf, m_hdr.basic.width, m_hdr.basic.height, info->destLeft, info->destTop, (info->destRight-info->destLeft+1), (info->destBottom-info->destTop+1), info->bitsPerPixel, isCompress, img_dat, img_len);
|
|
||||||
_update_key_frame(g_kf, m_hdr.basic.width, m_hdr.basic.height,
|
|
||||||
info->destLeft, info->destTop,
|
|
||||||
info->width, info->height,
|
|
||||||
info->destRight - info->destLeft + 1, info->destBottom - info->destTop + 1,
|
|
||||||
info->bitsPerPixel, isCompress, img_dat, img_len);
|
|
||||||
}
|
|
||||||
if(pkg.type == TS_RECORD_TYPE_RDP_KEYFRAME) {
|
|
||||||
// const TS_RECORD_RDP_KEYFRAME_INFO* info = reinterpret_cast<const TS_RECORD_RDP_KEYFRAME_INFO*>(pkg_data.data());
|
|
||||||
uint8_t* img_dat = reinterpret_cast<uint8_t*>(pkg_data.data() + sizeof(TS_RECORD_RDP_KEYFRAME_INFO));
|
|
||||||
uint32_t img_len = pkg_data.size() - sizeof(TS_RECORD_RDP_KEYFRAME_INFO);
|
|
||||||
|
|
||||||
if(m_xxx) {
|
|
||||||
qDebug("use kf: %d", m_restart_kf_idx);
|
|
||||||
memcpy(img_dat, g_kfdata[m_restart_kf_idx].data(), img_len);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
memcpy(img_dat, g_kf->data(), img_len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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)) {
|
if(!dat->parse(pkg, pkg_data)) {
|
||||||
qDebug("invaid tp-rdp-%d.tpd file (4).", m_file_idx+1);
|
qDebug("invaid tp-rdp-%d.tpd file (4).", m_file_idx+1);
|
||||||
|
@ -406,47 +290,20 @@ void ThrData::_run() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 拖动滚动条后,需要显示一次关键帧数据,然后跳过后续关键帧。
|
// 拖动滚动条后,需要显示一次关键帧数据,然后跳过后续关键帧。
|
||||||
if(pkg.type == TS_RECORD_TYPE_RDP_KEYFRAME) {
|
if(pkg.type == TS_RECORD_TYPE_RDP_KEYFRAME) {
|
||||||
g_kf_idx++;
|
|
||||||
g_kf = &(g_kfdata[g_kf_idx]);
|
|
||||||
if(!m_xxx) {
|
|
||||||
g_kf->resize(m_hdr.basic.width*m_hdr.basic.height*2);
|
|
||||||
memcpy(g_kf->data(), g_kfdata[g_kf_idx-1].data(), m_hdr.basic.width*m_hdr.basic.height*2);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
||||||
if(m_need_show_kf) {
|
if(m_need_show_kf) {
|
||||||
m_need_show_kf = false;
|
m_need_show_kf = false;
|
||||||
qDebug("++ show keyframe.");
|
qDebug("++ show keyframe.");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
//m_restart_kf_idx
|
|
||||||
|
|
||||||
|
|
||||||
QString tmp;
|
|
||||||
tmp.sprintf("%d", g_kf_idx);
|
|
||||||
QString img_fname = QString("%1/img-%2.png").arg(m_data_path, tmp);
|
|
||||||
QImage* img = nullptr;
|
|
||||||
int x = 0, y = 0, w = 0, h = 0;
|
|
||||||
dat->get_image(&img, x, y, w, h);
|
|
||||||
if(img != nullptr)
|
|
||||||
img->save(img_fname, "png");
|
|
||||||
|
|
||||||
qDebug("-- skip keyframe.");
|
qDebug("-- skip keyframe.");
|
||||||
delete dat;
|
delete dat;
|
||||||
dat = nullptr;
|
dat = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 数据放到待播放列表中
|
// 数据放到待播放列表中
|
||||||
if(dat) {
|
if(dat) {
|
||||||
m_locker.lock();
|
m_locker.lock();
|
||||||
|
@ -497,10 +354,6 @@ void ThrData::restart(uint32_t start_ms) {
|
||||||
m_offset = 0;
|
m_offset = 0;
|
||||||
m_file_idx = 0;
|
m_file_idx = 0;
|
||||||
m_need_show_kf = false;
|
m_need_show_kf = false;
|
||||||
|
|
||||||
g_kf_idx = 0;
|
|
||||||
m_restart_kf_idx = 0;
|
|
||||||
m_xxx = true;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// 找到最接近 start_ms 但小于它的关键帧
|
// 找到最接近 start_ms 但小于它的关键帧
|
||||||
|
@ -512,15 +365,14 @@ void ThrData::restart(uint32_t start_ms) {
|
||||||
}
|
}
|
||||||
if(i > 0)
|
if(i > 0)
|
||||||
i--;
|
i--;
|
||||||
g_kf_idx = i;
|
|
||||||
m_restart_kf_idx = i;
|
|
||||||
m_xxx = true;
|
|
||||||
|
|
||||||
qDebug("restart acturelly at %ld ms, kf: %d", m_kf[i].time_ms, i);
|
qDebug("restart acturelly at %ld ms, kf: %d", m_kf[i].time_ms, i);
|
||||||
|
|
||||||
// 指定要播放的数据的开始位置
|
// 指定要播放的数据的开始位置
|
||||||
m_offset = m_kf[i].offset;
|
m_offset = m_kf[i].offset;
|
||||||
m_file_idx = m_kf[i].file_index;
|
m_file_idx = m_kf[i].file_index;
|
||||||
|
if(m_file_idx == (uint32_t)-1)
|
||||||
|
m_file_idx = 0;
|
||||||
m_need_show_kf = true;
|
m_need_show_kf = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -596,7 +448,7 @@ bool ThrData::_load_keyframe() {
|
||||||
}
|
}
|
||||||
|
|
||||||
qint64 read_len = 0;
|
qint64 read_len = 0;
|
||||||
int kf_count = fsize / sizeof(KEYFRAME_INFO);
|
int kf_count = static_cast<int>(fsize / sizeof(KEYFRAME_INFO));
|
||||||
for(int i = 0; i < kf_count; ++i) {
|
for(int i = 0; i < kf_count; ++i) {
|
||||||
KEYFRAME_INFO kf;
|
KEYFRAME_INFO kf;
|
||||||
memset(&kf, 0, sizeof(KEYFRAME_INFO));
|
memset(&kf, 0, sizeof(KEYFRAME_INFO));
|
||||||
|
|
|
@ -102,8 +102,8 @@ private:
|
||||||
uint32_t m_file_idx;
|
uint32_t m_file_idx;
|
||||||
uint32_t m_offset;
|
uint32_t m_offset;
|
||||||
|
|
||||||
bool m_xxx;
|
// bool m_xxx;
|
||||||
int m_restart_kf_idx;
|
// int m_restart_kf_idx;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // THR_DATA_H
|
#endif // THR_DATA_H
|
||||||
|
|
|
@ -102,6 +102,8 @@ void ThrPlay::run() {
|
||||||
}
|
}
|
||||||
last_time_ms = m_start_ms;
|
last_time_ms = m_start_ms;
|
||||||
m_start_ms = 0;
|
m_start_ms = 0;
|
||||||
|
UpdateData* _enable = new UpdateData(TYPE_ENABLE_DRAW);
|
||||||
|
emit signal_update_data(_enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 根据数据包的信息,等待到播放时间点
|
// 2. 根据数据包的信息,等待到播放时间点
|
||||||
|
@ -139,10 +141,10 @@ void ThrPlay::run() {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if(m_start_ms > 0) {
|
if(m_start_ms > 0) {
|
||||||
// if(dat) {
|
delete dat;
|
||||||
// delete dat;
|
dat = nullptr;
|
||||||
// dat = nullptr;
|
UpdateData* _disable = new UpdateData(TYPE_DISABLE_DRAW);
|
||||||
// }
|
emit signal_update_data(_disable);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,25 +172,18 @@ void ThrPlay::run() {
|
||||||
|
|
||||||
if(m_need_stop)
|
if(m_need_stop)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// if(m_start_ms > 0) {
|
|
||||||
// if(dat) {
|
|
||||||
// delete dat;
|
|
||||||
// dat = nullptr;
|
|
||||||
// }
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
last_time_ms = this_time_ms;
|
last_time_ms = this_time_ms;
|
||||||
|
|
||||||
// 3. 将数据包发送给主UI界面进行显示
|
// 3. 将数据包发送给主UI界面进行显示
|
||||||
if(dat->data_type() == TYPE_END) {
|
if(dat != nullptr) {
|
||||||
_notify_message(LOCAL8BIT("播放结束"));
|
if(dat->data_type() == TYPE_END) {
|
||||||
|
_notify_message(LOCAL8BIT("播放结束"));
|
||||||
|
}
|
||||||
|
emit signal_update_data(dat);
|
||||||
}
|
}
|
||||||
|
|
||||||
emit signal_update_data(dat);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(dat != nullptr)
|
if(dat != nullptr)
|
||||||
|
|
|
@ -105,7 +105,7 @@ void UpdateData::_init() {
|
||||||
m_data_type = TYPE_UNKNOWN;
|
m_data_type = TYPE_UNKNOWN;
|
||||||
m_hdr = nullptr;
|
m_hdr = nullptr;
|
||||||
m_pointer = nullptr;
|
m_pointer = nullptr;
|
||||||
m_img = nullptr;
|
// m_img = nullptr;
|
||||||
// m_img_info = nullptr;
|
// m_img_info = nullptr;
|
||||||
|
|
||||||
m_data_buf = nullptr;
|
m_data_buf = nullptr;
|
||||||
|
@ -121,10 +121,14 @@ UpdateData::~UpdateData() {
|
||||||
delete m_hdr;
|
delete m_hdr;
|
||||||
if(m_pointer)
|
if(m_pointer)
|
||||||
delete m_pointer;
|
delete m_pointer;
|
||||||
if(m_img)
|
// if(m_img)
|
||||||
delete m_img;
|
// delete m_img;
|
||||||
// if(m_img_info)
|
// if(m_img_info)
|
||||||
// delete 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)
|
if(m_data_buf)
|
||||||
delete m_data_buf;
|
delete m_data_buf;
|
||||||
|
@ -143,21 +147,41 @@ bool UpdateData::parse(const TS_RECORD_PKG& pkg, const QByteArray& data) {
|
||||||
}
|
}
|
||||||
else if(pkg.type == TS_RECORD_TYPE_RDP_IMAGE) {
|
else if(pkg.type == TS_RECORD_TYPE_RDP_IMAGE) {
|
||||||
m_data_type = TYPE_IMAGE;
|
m_data_type = TYPE_IMAGE;
|
||||||
if(data.size() <= sizeof(TS_RECORD_RDP_IMAGE_INFO))
|
if(data.size() <= static_cast<int>(sizeof(uint16_t) + sizeof(TS_RECORD_RDP_IMAGE_INFO)))
|
||||||
return false;
|
|
||||||
const TS_RECORD_RDP_IMAGE_INFO* info = reinterpret_cast<const TS_RECORD_RDP_IMAGE_INFO*>(data.data());
|
|
||||||
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);
|
|
||||||
|
|
||||||
QImage* img = _rdpimg2QImage(info->width, info->height, info->bitsPerPixel, (info->format == TS_RDP_IMG_BMP) ? true : false, img_dat, img_len);
|
|
||||||
if(img == nullptr)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
m_img = img;
|
const uint8_t* dat_ptr = reinterpret_cast<const uint8_t*>(data.data());
|
||||||
m_img_x = info->destLeft;
|
|
||||||
m_img_y = info->destTop;
|
uint16_t count = (reinterpret_cast<const uint16_t*>(dat_ptr))[0];
|
||||||
m_img_w = info->destRight - info->destLeft + 1;
|
uint32_t offset = sizeof(uint16_t);
|
||||||
m_img_h = info->destBottom - info->destTop + 1;
|
|
||||||
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -170,11 +194,20 @@ bool UpdateData::parse(const TS_RECORD_PKG& pkg, const QByteArray& data) {
|
||||||
QImage* img = _raw2QImage((int)m_screen_w, (int)m_screen_h, img_dat, img_len);
|
QImage* img = _raw2QImage((int)m_screen_w, (int)m_screen_h, img_dat, img_len);
|
||||||
if(img == nullptr)
|
if(img == nullptr)
|
||||||
return false;
|
return false;
|
||||||
m_img = img;
|
|
||||||
m_img_x = 0;
|
UPDATE_IMAGE uimg;
|
||||||
m_img_y = 0;
|
uimg.x = 0;
|
||||||
m_img_w = m_screen_w;
|
uimg.y = 0;
|
||||||
m_img_h = m_screen_h;
|
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 true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,10 +2,15 @@
|
||||||
#define UPDATE_DATA_H
|
#define UPDATE_DATA_H
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QVector>
|
||||||
#include "record_format.h"
|
#include "record_format.h"
|
||||||
|
|
||||||
#define TYPE_UNKNOWN 0
|
#define TYPE_UNKNOWN 0
|
||||||
#define TYPE_HEADER_INFO 1
|
#define TYPE_HEADER_INFO 1
|
||||||
|
|
||||||
|
#define TYPE_DISABLE_DRAW 5
|
||||||
|
#define TYPE_ENABLE_DRAW 6
|
||||||
|
|
||||||
#define TYPE_POINTER 10
|
#define TYPE_POINTER 10
|
||||||
#define TYPE_IMAGE 11
|
#define TYPE_IMAGE 11
|
||||||
#define TYPE_KEYFRAME 12
|
#define TYPE_KEYFRAME 12
|
||||||
|
@ -15,6 +20,17 @@
|
||||||
#define TYPE_MESSAGE 90
|
#define TYPE_MESSAGE 90
|
||||||
#define TYPE_ERROR 91
|
#define TYPE_ERROR 91
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct UPDATE_IMAGE {
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
int w;
|
||||||
|
int h;
|
||||||
|
QImage* img;
|
||||||
|
}UPDATE_IMAGE;
|
||||||
|
|
||||||
|
typedef QVector<UPDATE_IMAGE> UpdateImages;
|
||||||
|
|
||||||
class UpdateData : public QObject
|
class UpdateData : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -28,14 +44,20 @@ public:
|
||||||
bool parse(const TS_RECORD_PKG& pkg, const QByteArray& data);
|
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) {
|
// bool get_image(QImage** img, int& x, int& y, int& w, int& h) {
|
||||||
if(m_img == nullptr)
|
// if(m_img == nullptr)
|
||||||
|
// 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;
|
return false;
|
||||||
*img = m_img;
|
uimgs = m_images;
|
||||||
x = m_img_x;
|
|
||||||
y = m_img_y;
|
|
||||||
w = m_img_w;
|
|
||||||
h = m_img_h;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,11 +98,12 @@ private:
|
||||||
// for POINTER
|
// for POINTER
|
||||||
TS_RECORD_RDP_POINTER* m_pointer;
|
TS_RECORD_RDP_POINTER* m_pointer;
|
||||||
// for IMAGE
|
// for IMAGE
|
||||||
QImage* m_img;
|
// QImage* m_img;
|
||||||
int m_img_x;
|
// int m_img_x;
|
||||||
int m_img_y;
|
// int m_img_y;
|
||||||
int m_img_w;
|
// int m_img_w;
|
||||||
int m_img_h;
|
// int m_img_h;
|
||||||
|
UpdateImages m_images;
|
||||||
|
|
||||||
// TS_RECORD_RDP_IMAGE_INFO* m_img_info;
|
// TS_RECORD_RDP_IMAGE_INFO* m_img_info;
|
||||||
|
|
||||||
|
|
|
@ -36,10 +36,10 @@ typedef struct TS_RECORD_HEADER_INFO {
|
||||||
ex_u32 magic; // "TPPR" 标志 TelePort Protocol Record
|
ex_u32 magic; // "TPPR" 标志 TelePort Protocol Record
|
||||||
ex_u16 ver; // 录像文件版本,v3.5.0开始为4
|
ex_u16 ver; // 录像文件版本,v3.5.0开始为4
|
||||||
ex_u16 type; // 录像内容,SSH or RDP
|
ex_u16 type; // 录像内容,SSH or RDP
|
||||||
ex_u32 packages; // 总包数
|
// ex_u32 packages; // 总包数
|
||||||
ex_u32 time_ms; // 总耗时(毫秒)
|
ex_u32 time_ms; // 总耗时(毫秒)
|
||||||
ex_u32 dat_file_count; // 数据文件数量
|
ex_u32 dat_file_count; // 数据文件数量
|
||||||
ex_u8 _reserve[64-4-2-2-4-4-4];
|
ex_u8 _reserve[64-4-2-2-4-4];
|
||||||
}TS_RECORD_HEADER_INFO;
|
}TS_RECORD_HEADER_INFO;
|
||||||
#define ts_record_header_info_size sizeof(TS_RECORD_HEADER_INFO)
|
#define ts_record_header_info_size sizeof(TS_RECORD_HEADER_INFO)
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ typedef struct TS_RECORD_PKG {
|
||||||
ex_u8 _reserve[3]; // 保留
|
ex_u8 _reserve[3]; // 保留
|
||||||
ex_u32 size; // 这个包的总大小(不含包头)
|
ex_u32 size; // 这个包的总大小(不含包头)
|
||||||
ex_u32 time_ms; // 这个包距起始时间的时间差(毫秒,意味着一个连接不能持续超过49天)
|
ex_u32 time_ms; // 这个包距起始时间的时间差(毫秒,意味着一个连接不能持续超过49天)
|
||||||
ex_u32 index; // 这个包的序号(最后一个包的序号与TS_RECORD_HEADER_INFO::packages数量匹配)
|
//ex_u32 index; // 这个包的序号(最后一个包的序号与TS_RECORD_HEADER_INFO::packages数量匹配)
|
||||||
}TS_RECORD_PKG;
|
}TS_RECORD_PKG;
|
||||||
|
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
Loading…
Reference in New Issue