pull/175/head^2
Apex Liu 2019-09-18 00:51:22 +08:00
parent e5610b17a2
commit 6aa5c046df
4 changed files with 172 additions and 103 deletions

View File

@ -64,6 +64,13 @@ bool rdpimg2QImage(QImage& out, int w, int h, int bitsPerPixel, bool isCompresse
return true; return true;
} }
static inline int min(int a, int b){
return a < b ? a : b;
}
static inline int max(int a, int b){
return a > b ? a : b;
}
MainWindow::MainWindow(QWidget *parent) : MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent), QMainWindow(parent),
@ -181,6 +188,20 @@ void MainWindow::paintEvent(QPaintEvent *e)
painter.drawPixmap(m_pt.x-m_pt_normal.width()/2, m_pt.y-m_pt_normal.height()/2, m_pt_normal); painter.drawPixmap(m_pt.x-m_pt_normal.width()/2, m_pt.y-m_pt_normal.height()/2, m_pt_normal);
} }
{
QRect rc_draw = e->rect();
QRect rc(100, 100, m_img_message.width(), m_img_message.height());
//rc.moveTo(m_rc.left()+rc.left(), m_rc.top() + rc.top());
int from_x = max(rc_draw.left(), rc.left()) - rc.left();
int from_y = max(rc_draw.top(), rc.top()) - rc.top();
int w = min(rc.right(), rc_draw.right()) - rc.left() - from_x + 1;
int h = min(rc.bottom(), rc_draw.bottom()) - rc.top() - from_y + 1;
int to_x = rc.left() + from_x;
int to_y = rc.top() + from_y;
painter.drawPixmap(to_x, to_y, m_img_message, from_x, from_y, w, h);
}
// 绘制浮动控制窗 // 绘制浮动控制窗
if(m_bar_fading) { if(m_bar_fading) {
painter.setOpacity(m_bar_opacity); painter.setOpacity(m_bar_opacity);
@ -281,18 +302,37 @@ void MainWindow::_do_update_data(update_data* dat) {
} }
else if(dat->data_type() == TYPE_MESSAGE) { else if(dat->data_type() == TYPE_MESSAGE) {
//QMessageBox::warning(nullptr, QGuiApplication::applicationDisplayName(), dat->message()); QPainter pp(&m_canvas);
if(!m_msg_box) { QFontMetrics fm = pp.fontMetrics();
m_msg_box = new DlgMessage(this); QRect rcWin(0, 0, m_canvas.width(), m_canvas.height());
// 无窗口标题栏,无边框 QRect rc = fm.boundingRect(rcWin, Qt::AlignLeft|Qt::TextWordWrap, dat->message());
m_msg_box->setWindowFlags(Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint | Qt::ToolTip | Qt::FramelessWindowHint); qDebug("message, w=%d, h=%d", rc.width(), rc.height());
// 设置成非模态 // int w = fm.width(dat->message());
m_msg_box->setModal(false); // int h = fm.height();
} // qDebug("message, w=%d, h=%d", w, h);
m_msg_box->set_text(dat->message()); m_img_message = QPixmap(rc.width() + 30, rc.height() + 30);
// 显示对话框 m_img_message.fill(Qt::transparent);
m_msg_box->show(); QPainter pm(&m_img_message);
pm.setPen(QColor(255,255,255,153));
pm.fillRect(rc, QColor(0,0,0,190));
pm.drawText(rc, Qt::AlignLeft|Qt::TextWordWrap, dat->message());
// //QMessageBox::warning(nullptr, QGuiApplication::applicationDisplayName(), dat->message());
// if(!m_msg_box) {
// m_msg_box = new DlgMessage(this);
// // 无窗口标题栏,无边框
// m_msg_box->setWindowFlags(Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint | Qt::ToolTip | Qt::FramelessWindowHint);
// // 设置成非模态
// m_msg_box->setModal(false);
// }
// m_msg_box->set_text(dat->message());
// // 显示对话框
// m_msg_box->show();
return; return;
} }

View File

@ -78,6 +78,8 @@ private:
//QMessageBox* m_msg_box; //QMessageBox* m_msg_box;
DlgMessage* m_msg_box; DlgMessage* m_msg_box;
QPixmap m_img_message;
}; };
#endif // MAINWINDOW_H #endif // MAINWINDOW_H

View File

@ -75,9 +75,6 @@ void ThreadPlay::run() {
qDebug() << "DOWNLOAD"; qDebug() << "DOWNLOAD";
m_need_download = true; m_need_download = true;
// path_base = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation);
// path_base += "/tprdp/";
_notify_message("正在缓存录像数据,请稍候..."); _notify_message("正在缓存录像数据,请稍候...");
m_thr_download = new ThreadDownload(m_res); m_thr_download = new ThreadDownload(m_res);
@ -87,14 +84,8 @@ void ThreadPlay::run() {
for(;;) { for(;;) {
msleep(500); msleep(500);
if(m_need_stop) { if(m_need_stop)
// m_thr_download->stop();
// m_thr_download->wait();
// delete m_thr_download;
// m_thr_download = nullptr;
return; return;
}
if(!m_thr_download->prepare(path_base, msg)) { if(!m_thr_download->prepare(path_base, msg)) {
msg.sprintf("指定的文件或目录不存在!\n\n%s", _tmp_res.toStdString().c_str()); msg.sprintf("指定的文件或目录不存在!\n\n%s", _tmp_res.toStdString().c_str());
@ -137,8 +128,11 @@ void ThreadPlay::run() {
qint64 read_len = 0; qint64 read_len = 0;
uint32_t total_pkg = 0; uint32_t total_pkg = 0;
uint32_t total_ms = 0; uint32_t total_ms = 0;
uint32_t file_count = 0;
//======================================
// 加载录像基本信息数据 // 加载录像基本信息数据
//======================================
QString tpr_filename(path_base); QString tpr_filename(path_base);
tpr_filename += "tp-rdp.tpr"; tpr_filename += "tp-rdp.tpr";
@ -176,125 +170,153 @@ void ThreadPlay::run() {
return; return;
} }
// if(hdr->basic.width == 0 || hdr->basic.height == 0) { if(hdr->basic.width == 0 || hdr->basic.height == 0) {
// _notify_error("错误的录像信息,未记录窗口尺寸!"); _notify_error("错误的录像信息,未记录窗口尺寸!");
// return; return;
// } }
if(hdr->info.dat_file_count == 0) {
_notify_error("错误的录像信息,未记录数据文件数量!");
return;
}
total_pkg = hdr->info.packages; total_pkg = hdr->info.packages;
total_ms = hdr->info.time_ms; total_ms = hdr->info.time_ms;
file_count = hdr->info.dat_file_count;
emit signal_update_data(dat); emit signal_update_data(dat);
} }
// 加载录像文件数据 //======================================
// 加载录像文件数据并播放
QString tpd_filename(path_base); //======================================
tpd_filename += "tp-rdp.tpd";
QFile f_dat(tpd_filename);
if(!f_dat.open(QFile::ReadOnly)) {
qDebug() << "Can not open " << tpd_filename << " for read.";
QString msg;
msg.sprintf("无法打开录像数据文件!\n\n%s", tpd_filename.toStdString().c_str());
_notify_error(msg);
return;
}
uint32_t pkg_count = 0;
uint32_t time_pass = 0; uint32_t time_pass = 0;
uint32_t time_last_pass = 0; uint32_t time_last_pass = 0;
qint64 time_begin = QDateTime::currentMSecsSinceEpoch(); qint64 time_begin = QDateTime::currentMSecsSinceEpoch();
QString msg;
for(uint32_t i = 0; i < total_pkg; ++i) { for(uint32_t fidx = 0; fidx < file_count; ++fidx) {
if(m_need_stop) { if(m_need_stop) {
qDebug() << "stop, user cancel."; qDebug() << "stop, user cancel 1.";
break; break;
} }
if(m_need_pause) { QString tpd_filename;
msleep(50); tpd_filename.sprintf("%stp-rdp-%d.tpd", path_base.toStdString().c_str(), fidx+1);
time_begin += 50;
continue;
}
TS_RECORD_PKG pkg; // for test.
read_len = f_dat.read((char*)(&pkg), sizeof(pkg)); msg.sprintf("无法打开录像数据文件!\n\n%s", tpd_filename.toStdString().c_str());
if(read_len != sizeof(TS_RECORD_PKG)) { _notify_message(msg);
qDebug() << "invaid .tpd file (1).";
QString msg; QFile f_dat(tpd_filename);
msg.sprintf("错误的录像数据文件!\n\n%s", tpd_filename.toStdString().c_str()); if(!f_dat.open(QFile::ReadOnly)) {
qDebug() << "Can not open " << tpd_filename << " for read.";
msg.sprintf("无法打开录像数据文件!\n\n%s", tpd_filename.toStdString().c_str());
_notify_error(msg); _notify_error(msg);
return; return;
} }
update_data* dat = new update_data(TYPE_DATA);
dat->alloc_data(sizeof(TS_RECORD_PKG) + pkg.size);
memcpy(dat->data_buf(), &pkg, sizeof(TS_RECORD_PKG));
read_len = f_dat.read((char*)(dat->data_buf()+sizeof(TS_RECORD_PKG)), pkg.size);
if(read_len != pkg.size) {
delete dat;
qDebug() << "invaid .tpd file.";
QString msg;
msg.sprintf("错误的录像数据文件!\n\n%s", tpd_filename.toStdString().c_str());
_notify_error(msg);
return;
}
time_pass = (uint32_t)(QDateTime::currentMSecsSinceEpoch() - time_begin) * m_speed;
if(time_pass > total_ms)
time_pass = total_ms;
if(time_pass - time_last_pass > 200) {
update_data* _passed_ms = new update_data(TYPE_PLAYED_MS);
_passed_ms->played_ms(time_pass);
emit signal_update_data(_passed_ms);
time_last_pass = time_pass;
}
if(time_pass >= pkg.time_ms) {
emit signal_update_data(dat);
continue;
}
// 需要等待
uint32_t time_wait = pkg.time_ms - time_pass;
uint32_t wait_this_time = 0;
for(;;) { for(;;) {
if(m_need_stop) {
qDebug() << "stop, user cancel 2.";
break;
}
if(m_need_pause) { if(m_need_pause) {
msleep(50); msleep(50);
time_begin += 50; time_begin += 50;
continue; continue;
} }
wait_this_time = time_wait; TS_RECORD_PKG pkg;
if(wait_this_time > 10) read_len = f_dat.read((char*)(&pkg), sizeof(pkg));
wait_this_time = 10; if(read_len == 0)
if(m_need_stop) {
qDebug() << "stop, user cancel (2).";
break; break;
if(read_len != sizeof(TS_RECORD_PKG)) {
qDebug() << "invaid .tpd file (1).";
msg.sprintf("错误的录像数据文件!\n\n%s", tpd_filename.toStdString().c_str());
_notify_error(msg);
return;
} }
msleep(wait_this_time); update_data* dat = new update_data(TYPE_DATA);
dat->alloc_data(sizeof(TS_RECORD_PKG) + pkg.size);
memcpy(dat->data_buf(), &pkg, sizeof(TS_RECORD_PKG));
read_len = f_dat.read((char*)(dat->data_buf()+sizeof(TS_RECORD_PKG)), pkg.size);
if(read_len != pkg.size) {
delete dat;
qDebug() << "invaid .tpd file.";
msg.sprintf("错误的录像数据文件!\n\n%s", tpd_filename.toStdString().c_str());
_notify_error(msg);
return;
}
uint32_t _time_pass = (uint32_t)(QDateTime::currentMSecsSinceEpoch() - time_begin) * m_speed; pkg_count++;
if(_time_pass > total_ms)
_time_pass = total_ms; time_pass = (uint32_t)(QDateTime::currentMSecsSinceEpoch() - time_begin) * m_speed;
if(_time_pass - time_last_pass > 200) { if(time_pass > total_ms)
time_pass = total_ms;
if(time_pass - time_last_pass > 200) {
update_data* _passed_ms = new update_data(TYPE_PLAYED_MS); update_data* _passed_ms = new update_data(TYPE_PLAYED_MS);
_passed_ms->played_ms(_time_pass); _passed_ms->played_ms(time_pass);
emit signal_update_data(_passed_ms); emit signal_update_data(_passed_ms);
time_last_pass = _time_pass; time_last_pass = time_pass;
} }
time_wait -= wait_this_time; if(time_pass >= pkg.time_ms) {
if(time_wait == 0) {
emit signal_update_data(dat); emit signal_update_data(dat);
break; continue;
} }
// 需要等待
uint32_t time_wait = pkg.time_ms - time_pass;
uint32_t wait_this_time = 0;
for(;;) {
if(m_need_pause) {
msleep(50);
time_begin += 50;
continue;
}
wait_this_time = time_wait;
if(wait_this_time > 10)
wait_this_time = 10;
if(m_need_stop) {
qDebug() << "stop, user cancel (2).";
break;
}
msleep(wait_this_time);
uint32_t _time_pass = (uint32_t)(QDateTime::currentMSecsSinceEpoch() - time_begin) * m_speed;
if(_time_pass > total_ms)
_time_pass = total_ms;
if(_time_pass - time_last_pass > 200) {
update_data* _passed_ms = new update_data(TYPE_PLAYED_MS);
_passed_ms->played_ms(_time_pass);
emit signal_update_data(_passed_ms);
time_last_pass = _time_pass;
}
time_wait -= wait_this_time;
if(time_wait == 0) {
emit signal_update_data(dat);
break;
}
}
} }
} }
if(pkg_count < total_pkg) {
qDebug() << "total-pkg:" << total_pkg << ", played:" << pkg_count;
msg.sprintf("录像数据文件有误!\n\n部分录像数据缺失!");
_notify_message(msg);
}
update_data* _end = new update_data(TYPE_END); update_data* _end = new update_data(TYPE_END);
emit signal_update_data(_end); emit signal_update_data(_end);
} }

View File

@ -7,14 +7,19 @@
#include <ex.h> #include <ex.h>
#define MAX_SIZE_PER_FILE 4194304 // 4M = 1024*1024*4 #define MAX_CACHE_SIZE 1048576 // 1M = 1024*1024*1
#define MAX_SIZE_PER_FILE 4194304 // 4M = 1024*1024*4
#pragma pack(push,1) #pragma pack(push,1)
/* /*
* *
* *
* *
* *.tpr512
* *.tpdn tp-rdp-1.tpdtp-rdp-2.tpd4MB
* *.tpkRDP
* *-cmd.txtsshSSH
* 4M5 * 4M5
* *
*/ */
@ -26,8 +31,8 @@ typedef struct TS_RECORD_HEADER_INFO {
ex_u16 ver; // 录像文件版本v3.5.0开始为4 ex_u16 ver; // 录像文件版本v3.5.0开始为4
ex_u32 packages; // 总包数 ex_u32 packages; // 总包数
ex_u32 time_ms; // 总耗时(毫秒) ex_u32 time_ms; // 总耗时(毫秒)
uint32_t dat_file_count; // 数据文件数量 ex_u32 dat_file_count; // 数据文件数量
uint8_t _reserve[64-4-2-4-4-4]; ex_u8 _reserve[64-4-2-4-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)